summaryrefslogtreecommitdiffstats
path: root/src/lib
ModeNameSize
d---------formats15431logstatsplain
d---------netlist1235logstatsplain
d---------util4066logstatsplain
0143u4'>logtreecommitdiffstatshomepage
path: root/trunk/src
diff options
context:
space:
mode:
author Angelo Salese <angelosa@users.noreply.github.com>2011-08-25 18:12:05 +0000
committer Angelo Salese <angelosa@users.noreply.github.com>2011-08-25 18:12:05 +0000
commite65f7e8441410ab238cd968f3b6c0b3b16ec061c (patch)
tree3f2b814923c026858e2cd7524e414eceb433add3 /trunk/src
parent2811f1f8f7cbea4bdbb0959e020f44d46ca27abc (diff)
MAME 0.143u4 tagmame0143u4
Diffstat (limited to 'trunk/src')
-rw-r--r--trunk/src/build/build.mak131
-rw-r--r--trunk/src/build/file2str.c101
-rw-r--r--trunk/src/build/makedep.c551
-rw-r--r--trunk/src/build/makedev.c233
-rw-r--r--trunk/src/build/makelist.c236
-rw-r--r--trunk/src/build/png2bdc.c453
-rw-r--r--trunk/src/build/verinfo.c302
-rw-r--r--trunk/src/emu/addrmap.c975
-rw-r--r--trunk/src/emu/addrmap.h1151
-rw-r--r--trunk/src/emu/attotime.c187
-rw-r--r--trunk/src/emu/attotime.h434
-rw-r--r--trunk/src/emu/audio/generic.c168
-rw-r--r--trunk/src/emu/audio/generic.h59
-rw-r--r--trunk/src/emu/audit.c551
-rw-r--r--trunk/src/emu/audit.h196
-rw-r--r--trunk/src/emu/cheat.c1479
-rw-r--r--trunk/src/emu/cheat.h365
-rw-r--r--trunk/src/emu/clifront.c1673
-rw-r--r--trunk/src/emu/clifront.h167
-rw-r--r--trunk/src/emu/config.c328
-rw-r--r--trunk/src/emu/config.h61
-rw-r--r--trunk/src/emu/cothread.c95
-rw-r--r--trunk/src/emu/cothread.h88
-rw-r--r--trunk/src/emu/cpu/adsp2100/2100dasm.c551
-rw-r--r--trunk/src/emu/cpu/adsp2100/2100ops.c2230
-rw-r--r--trunk/src/emu/cpu/adsp2100/adsp2100.c1947
-rw-r--r--trunk/src/emu/cpu/adsp2100/adsp2100.h625
-rw-r--r--trunk/src/emu/cpu/alph8201/8201dasm.c402
-rw-r--r--trunk/src/emu/cpu/alph8201/alph8201.c1000
-rw-r--r--trunk/src/emu/cpu/alph8201/alph8201.h43
-rw-r--r--trunk/src/emu/cpu/am29000/am29000.c1216
-rw-r--r--trunk/src/emu/cpu/am29000/am29000.h438
-rw-r--r--trunk/src/emu/cpu/am29000/am29dasm.c257
-rw-r--r--trunk/src/emu/cpu/am29000/am29ops.h1725
-rw-r--r--trunk/src/emu/cpu/apexc/apexc.c954
-rw-r--r--trunk/src/emu/cpu/apexc/apexc.h26
-rw-r--r--trunk/src/emu/cpu/apexc/apexcdsm.c183
-rw-r--r--trunk/src/emu/cpu/arm/arm.c1651
-rw-r--r--trunk/src/emu/cpu/arm/arm.h29
-rw-r--r--trunk/src/emu/cpu/arm/armdasm.c407
-rw-r--r--trunk/src/emu/cpu/arm7/arm7.c1061
-rw-r--r--trunk/src/emu/cpu/arm7/arm7.h49
-rw-r--r--trunk/src/emu/cpu/arm7/arm7core.c2015
-rw-r--r--trunk/src/emu/cpu/arm7/arm7core.h530
-rw-r--r--trunk/src/emu/cpu/arm7/arm7dasm.c1339
-rw-r--r--trunk/src/emu/cpu/arm7/arm7exec.c1648
-rw-r--r--trunk/src/emu/cpu/asap/asap.c1714
-rw-r--r--trunk/src/emu/cpu/asap/asap.h305
-rw-r--r--trunk/src/emu/cpu/asap/asapdasm.c142
-rw-r--r--trunk/src/emu/cpu/avr8/avr8.c1205
-rw-r--r--trunk/src/emu/cpu/avr8/avr8.h91
-rw-r--r--trunk/src/emu/cpu/avr8/avr8dasm.c568
-rw-r--r--trunk/src/emu/cpu/ccpu/ccpu.c830
-rw-r--r--trunk/src/emu/cpu/ccpu/ccpu.h63
-rw-r--r--trunk/src/emu/cpu/ccpu/ccpudasm.c328
-rw-r--r--trunk/src/emu/cpu/cop400/cop400.c1709
-rw-r--r--trunk/src/emu/cpu/cop400/cop400.h159
-rw-r--r--trunk/src/emu/cpu/cop400/cop400op.c1318
-rw-r--r--trunk/src/emu/cpu/cop400/cop410ds.c350
-rw-r--r--trunk/src/emu/cpu/cop400/cop420ds.c399
-rw-r--r--trunk/src/emu/cpu/cop400/cop440ds.c416
-rw-r--r--trunk/src/emu/cpu/cosmac/cosdasm.c173
-rw-r--r--trunk/src/emu/cpu/cosmac/cosmac.c1146
-rw-r--r--trunk/src/emu/cpu/cosmac/cosmac.h385
-rw-r--r--trunk/src/emu/cpu/cp1610/1610dasm.c1488
-rw-r--r--trunk/src/emu/cpu/cp1610/cp1610.c3536
-rw-r--r--trunk/src/emu/cpu/cp1610/cp1610.h41
-rw-r--r--trunk/src/emu/cpu/cpu.mak1865
-rw-r--r--trunk/src/emu/cpu/cubeqcpu/cubedasm.c304
-rw-r--r--trunk/src/emu/cpu/cubeqcpu/cubeqcpu.c1885
-rw-r--r--trunk/src/emu/cpu/cubeqcpu/cubeqcpu.h161
-rw-r--r--trunk/src/emu/cpu/drcbec.c2281
-rw-r--r--trunk/src/emu/cpu/drcbec.h88
-rw-r--r--trunk/src/emu/cpu/drcbeut.c606
-rw-r--r--trunk/src/emu/cpu/drcbeut.h195
-rw-r--r--trunk/src/emu/cpu/drcbex64.c6735
-rw-r--r--trunk/src/emu/cpu/drcbex64.h373
-rw-r--r--trunk/src/emu/cpu/drcbex86.c6615
-rw-r--r--trunk/src/emu/cpu/drcbex86.h374
-rw-r--r--trunk/src/emu/cpu/drccache.c281
-rw-r--r--trunk/src/emu/cpu/drccache.h143
-rw-r--r--trunk/src/emu/cpu/drcfe.c401
-rw-r--r--trunk/src/emu/cpu/drcfe.h193
-rw-r--r--trunk/src/emu/cpu/drcuml.c1169
-rw-r--r--trunk/src/emu/cpu/drcuml.h268
-rw-r--r--trunk/src/emu/cpu/drcumlsh.h186
-rw-r--r--trunk/src/emu/cpu/dsp16/dsp16.c215
-rw-r--r--trunk/src/emu/cpu/dsp16/dsp16.h100
-rw-r--r--trunk/src/emu/cpu/dsp16/dsp16dis.c567
-rw-r--r--trunk/src/emu/cpu/dsp32/dsp32.c889
-rw-r--r--trunk/src/emu/cpu/dsp32/dsp32.h484
-rw-r--r--trunk/src/emu/cpu/dsp32/dsp32dis.c702
-rw-r--r--trunk/src/emu/cpu/dsp32/dsp32ops.c2859
-rw-r--r--trunk/src/emu/cpu/dsp56k/dsp56def.h55
-rw-r--r--trunk/src/emu/cpu/dsp56k/dsp56dsm.c28
-rw-r--r--trunk/src/emu/cpu/dsp56k/dsp56k.c677
-rw-r--r--trunk/src/emu/cpu/dsp56k/dsp56k.h219
-rw-r--r--trunk/src/emu/cpu/dsp56k/dsp56mem.c962
-rw-r--r--trunk/src/emu/cpu/dsp56k/dsp56mem.h245
-rw-r--r--trunk/src/emu/cpu/dsp56k/dsp56ops.c4922
-rw-r--r--trunk/src/emu/cpu/dsp56k/dsp56pcu.c486
-rw-r--r--trunk/src/emu/cpu/dsp56k/dsp56pcu.h149
-rw-r--r--trunk/src/emu/cpu/dsp56k/inst.c786
-rw-r--r--trunk/src/emu/cpu/dsp56k/inst.h3776
-rw-r--r--trunk/src/emu/cpu/dsp56k/opcode.c81
-rw-r--r--trunk/src/emu/cpu/dsp56k/opcode.h46
-rw-r--r--trunk/src/emu/cpu/dsp56k/pmove.c78
-rw-r--r--trunk/src/emu/cpu/dsp56k/pmove.h337
-rw-r--r--trunk/src/emu/cpu/dsp56k/tables.c899
-rw-r--r--trunk/src/emu/cpu/dsp56k/tables.h93
-rw-r--r--trunk/src/emu/cpu/e132xs/32xsdasm.c2140
-rw-r--r--trunk/src/emu/cpu/e132xs/e132xs.c5449
-rw-r--r--trunk/src/emu/cpu/e132xs/e132xs.h156
-rw-r--r--trunk/src/emu/cpu/e132xs/e132xsop.c1925
-rw-r--r--trunk/src/emu/cpu/esrip/esrip.c2000
-rw-r--r--trunk/src/emu/cpu/esrip/esrip.h101
-rw-r--r--trunk/src/emu/cpu/esrip/esripdsm.c93
-rw-r--r--trunk/src/emu/cpu/f8/f8.c2235
-rw-r--r--trunk/src/emu/cpu/f8/f8.h54
-rw-r--r--trunk/src/emu/cpu/f8/f8dasm.c533
-rw-r--r--trunk/src/emu/cpu/g65816/g65816.c557
-rw-r--r--trunk/src/emu/cpu/g65816/g65816.h74
-rw-r--r--trunk/src/emu/cpu/g65816/g65816cm.h318
-rw-r--r--trunk/src/emu/cpu/g65816/g65816ds.c352
-rw-r--r--trunk/src/emu/cpu/g65816/g65816ds.h25
-rw-r--r--trunk/src/emu/cpu/g65816/g65816o0.c6
-rw-r--r--trunk/src/emu/cpu/g65816/g65816o1.c6
-rw-r--r--trunk/src/emu/cpu/g65816/g65816o2.c6
-rw-r--r--trunk/src/emu/cpu/g65816/g65816o3.c6
-rw-r--r--trunk/src/emu/cpu/g65816/g65816o4.c6
-rw-r--r--trunk/src/emu/cpu/g65816/g65816op.h2385
-rw-r--r--trunk/src/emu/cpu/h6280/6280dasm.c248
-rw-r--r--trunk/src/emu/cpu/h6280/h6280.c535
-rw-r--r--trunk/src/emu/cpu/h6280/h6280.h90
-rw-r--r--trunk/src/emu/cpu/h6280/h6280ops.h1370
-rw-r--r--trunk/src/emu/cpu/h6280/tblh6280.c344
-rw-r--r--trunk/src/emu/cpu/h83002/h8.h401
-rw-r--r--trunk/src/emu/cpu/h83002/h8_16.c866
-rw-r--r--trunk/src/emu/cpu/h83002/h8_8.c816
-rw-r--r--trunk/src/emu/cpu/h83002/h8disasm.c1583
-rw-r--r--trunk/src/emu/cpu/h83002/h8ops.h4220
-rw-r--r--trunk/src/emu/cpu/h83002/h8periph.c794
-rw-r--r--trunk/src/emu/cpu/h83002/h8priv.h131
-rw-r--r--trunk/src/emu/cpu/h83002/h8speriph.c1540
-rw-r--r--trunk/src/emu/cpu/hcd62121/hcd62121.c512
-rw-r--r--trunk/src/emu/cpu/hcd62121/hcd62121.h40
-rw-r--r--trunk/src/emu/cpu/hcd62121/hcd62121_ops.h1023
-rw-r--r--trunk/src/emu/cpu/hcd62121/hcd62121d.c352
-rw-r--r--trunk/src/emu/cpu/hd61700/hd61700.c3020
-rw-r--r--trunk/src/emu/cpu/hd61700/hd61700.h162
-rw-r--r--trunk/src/emu/cpu/hd61700/hd61700d.c437
-rw-r--r--trunk/src/emu/cpu/hd6309/6309dasm.c941
-rw-r--r--trunk/src/emu/cpu/hd6309/6309ops.c5535
-rw-r--r--trunk/src/emu/cpu/hd6309/6309tbl.c814
-rw-r--r--trunk/src/emu/cpu/hd6309/hd6309.c1355
-rw-r--r--trunk/src/emu/cpu/hd6309/hd6309.h25
-rw-r--r--trunk/src/emu/cpu/i386/cycles.h674
-rw-r--r--trunk/src/emu/cpu/i386/i386.c3392
-rw-r--r--trunk/src/emu/cpu/i386/i386.h19
-rw-r--r--trunk/src/emu/cpu/i386/i386dasm.c2191
-rw-r--r--trunk/src/emu/cpu/i386/i386op16.c3484
-rw-r--r--trunk/src/emu/cpu/i386/i386op32.c3300
-rw-r--r--trunk/src/emu/cpu/i386/i386ops.c2400
-rw-r--r--trunk/src/emu/cpu/i386/i386ops.h378
-rw-r--r--trunk/src/emu/cpu/i386/i386priv.h993
-rw-r--r--trunk/src/emu/cpu/i386/i486ops.c424
-rw-r--r--trunk/src/emu/cpu/i386/pentops.c53
-rw-r--r--trunk/src/emu/cpu/i386/x87ops.c391
-rw-r--r--trunk/src/emu/cpu/i4004/4004dasm.c133
-rw-r--r--trunk/src/emu/cpu/i4004/i4004.c622
-rw-r--r--trunk/src/emu/cpu/i4004/i4004.h34
-rw-r--r--trunk/src/emu/cpu/i8008/8008dasm.c115
-rw-r--r--trunk/src/emu/cpu/i8008/i8008.c725
-rw-r--r--trunk/src/emu/cpu/i8008/i8008.h31
-rw-r--r--trunk/src/emu/cpu/i8085/8085dasm.c581
-rw-r--r--trunk/src/emu/cpu/i8085/i8085.c1298
-rw-r--r--trunk/src/emu/cpu/i8085/i8085.h61
-rw-r--r--trunk/src/emu/cpu/i8085/i8085cpu.h188
-rw-r--r--trunk/src/emu/cpu/i86/ea.h55
-rw-r--r--trunk/src/emu/cpu/i86/host.h12
-rw-r--r--trunk/src/emu/cpu/i86/i286.c540
-rw-r--r--trunk/src/emu/cpu/i86/i286.h50
-rw-r--r--trunk/src/emu/cpu/i86/i86.c698
-rw-r--r--trunk/src/emu/cpu/i86/i86.h65
-rw-r--r--trunk/src/emu/cpu/i86/i86.txt111
-rw-r--r--trunk/src/emu/cpu/i86/i86priv.h168
-rw-r--r--trunk/src/emu/cpu/i86/i86time.c310
-rw-r--r--trunk/src/emu/cpu/i86/instr186.c205
-rw-r--r--trunk/src/emu/cpu/i86/instr186.h36
-rw-r--r--trunk/src/emu/cpu/i86/instr286.c869
-rw-r--r--trunk/src/emu/cpu/i86/instr286.h48
-rw-r--r--trunk/src/emu/cpu/i86/instr86.c3295
-rw-r--r--trunk/src/emu/cpu/i86/instr86.h250
-rw-r--r--trunk/src/emu/cpu/i86/modrm.h119
-rw-r--r--trunk/src/emu/cpu/i86/modrm286.h145
-rw-r--r--trunk/src/emu/cpu/i86/table186.h525
-rw-r--r--trunk/src/emu/cpu/i86/table286.h530
-rw-r--r--trunk/src/emu/cpu/i86/table86.h525
-rw-r--r--trunk/src/emu/cpu/i860/i860.c384
-rw-r--r--trunk/src/emu/cpu/i860/i860.h223
-rw-r--r--trunk/src/emu/cpu/i860/i860dasm.c377
-rw-r--r--trunk/src/emu/cpu/i860/i860dec.c4718
-rw-r--r--trunk/src/emu/cpu/i860/i860dis.c696
-rw-r--r--trunk/src/emu/cpu/i960/i960.c2232
-rw-r--r--trunk/src/emu/cpu/i960/i960.h68
-rw-r--r--trunk/src/emu/cpu/i960/i960dis.c305
-rw-r--r--trunk/src/emu/cpu/i960/i960dis.h14
-rw-r--r--trunk/src/emu/cpu/jaguar/jagdasm.c197
-rw-r--r--trunk/src/emu/cpu/jaguar/jaguar.c1666
-rw-r--r--trunk/src/emu/cpu/jaguar/jaguar.h111
-rw-r--r--trunk/src/emu/cpu/konami/knmidasm.c1875
-rw-r--r--trunk/src/emu/cpu/konami/konami.c632
-rw-r--r--trunk/src/emu/cpu/konami/konami.h30
-rw-r--r--trunk/src/emu/cpu/konami/konamops.c4339
-rw-r--r--trunk/src/emu/cpu/konami/konamtbl.c491
-rw-r--r--trunk/src/emu/cpu/lh5801/5801dasm.c736
-rw-r--r--trunk/src/emu/cpu/lh5801/5801tbl.c692
-rw-r--r--trunk/src/emu/cpu/lh5801/lh5801.c348
-rw-r--r--trunk/src/emu/cpu/lh5801/lh5801.h85
-rw-r--r--trunk/src/emu/cpu/lr35902/lr35902.c495
-rw-r--r--trunk/src/emu/cpu/lr35902/lr35902.h36
-rw-r--r--trunk/src/emu/cpu/lr35902/lr35902d.c289
-rw-r--r--trunk/src/emu/cpu/lr35902/opc_cb.h1440
-rw-r--r--trunk/src/emu/cpu/lr35902/opc_main.h1551
-rw-r--r--trunk/src/emu/cpu/m37710/m37710.c1130
-rw-r--r--trunk/src/emu/cpu/m37710/m37710.h95
-rw-r--r--trunk/src/emu/cpu/m37710/m37710cm.h336
-rw-r--r--trunk/src/emu/cpu/m37710/m37710o0.c5
-rw-r--r--trunk/src/emu/cpu/m37710/m37710o1.c5
-rw-r--r--trunk/src/emu/cpu/m37710/m37710o2.c5
-rw-r--r--trunk/src/emu/cpu/m37710/m37710o3.c5
-rw-r--r--trunk/src/emu/cpu/m37710/m37710op.h2959
-rw-r--r--trunk/src/emu/cpu/m37710/m7700ds.c616
-rw-r--r--trunk/src/emu/cpu/m37710/m7700ds.h21
-rw-r--r--trunk/src/emu/cpu/m6502/6502dasm.c767
-rw-r--r--trunk/src/emu/cpu/m6502/ill02.h337
-rw-r--r--trunk/src/emu/cpu/m6502/m4510.c557
-rw-r--r--trunk/src/emu/cpu/m6502/m4510.h49
-rw-r--r--trunk/src/emu/cpu/m6502/m6502.c996
-rw-r--r--trunk/src/emu/cpu/m6502/m6502.h226
-rw-r--r--trunk/src/emu/cpu/m6502/m6502.txt163
-rw-r--r--trunk/src/emu/cpu/m6502/m6509.c418
-rw-r--r--trunk/src/emu/cpu/m6502/m6509.h44
-rw-r--r--trunk/src/emu/cpu/m6502/m65ce02.c365
-rw-r--r--trunk/src/emu/cpu/m6502/m65ce02.h42
-rw-r--r--trunk/src/emu/cpu/m6502/minc4510.h70
-rw-r--r--trunk/src/emu/cpu/m6502/mincce02.h69
-rw-r--r--trunk/src/emu/cpu/m6502/ops02.h808
-rw-r--r--trunk/src/emu/cpu/m6502/ops09.h206
-rw-r--r--trunk/src/emu/cpu/m6502/ops4510.h61
-rw-r--r--trunk/src/emu/cpu/m6502/opsc02.h359
-rw-r--r--trunk/src/emu/cpu/m6502/opsce02.h989
-rw-r--r--trunk/src/emu/cpu/m6502/opsn2a03.h38
-rw-r--r--trunk/src/emu/cpu/m6502/t6502.c360
-rw-r--r--trunk/src/emu/cpu/m6502/t6509.c352
-rw-r--r--trunk/src/emu/cpu/m6502/t6510.c27
-rw-r--r--trunk/src/emu/cpu/m6502/t65c02.c410
-rw-r--r--trunk/src/emu/cpu/m6502/t65ce02.c399
-rw-r--r--trunk/src/emu/cpu/m6502/t65sc02.c80
-rw-r--r--trunk/src/emu/cpu/m6502/tdeco16.c428
-rw-r--r--trunk/src/emu/cpu/m6502/tn2a03.c114
-rw-r--r--trunk/src/emu/cpu/m6800/6800dasm.c280
-rw-r--r--trunk/src/emu/cpu/m6800/6800ops.c2284
-rw-r--r--trunk/src/emu/cpu/m6800/6800tbl.c386
-rw-r--r--trunk/src/emu/cpu/m6800/m6800.c2130
-rw-r--r--trunk/src/emu/cpu/m6800/m6800.h76
-rw-r--r--trunk/src/emu/cpu/m68000/m68000.h120
-rw-r--r--trunk/src/emu/cpu/m68000/m68k_in.c10231
-rw-r--r--trunk/src/emu/cpu/m68000/m68kcpu.c2248
-rw-r--r--trunk/src/emu/cpu/m68000/m68kcpu.h1923
-rw-r--r--trunk/src/emu/cpu/m68000/m68kdasm.c4031
-rw-r--r--trunk/src/emu/cpu/m68000/m68kfpu.c1993
-rw-r--r--trunk/src/emu/cpu/m68000/m68kmake.c1433
-rw-r--r--trunk/src/emu/cpu/m68000/m68kmmu.h806
-rw-r--r--trunk/src/emu/cpu/m6805/6805dasm.c212
-rw-r--r--trunk/src/emu/cpu/m6805/6805ops.c1799
-rw-r--r--trunk/src/emu/cpu/m6805/m6805.c1182
-rw-r--r--trunk/src/emu/cpu/m6805/m6805.h70
-rw-r--r--trunk/src/emu/cpu/m6809/6809dasm.c619
-rw-r--r--trunk/src/emu/cpu/m6809/6809ops.c2977
-rw-r--r--trunk/src/emu/cpu/m6809/6809tbl.c414
-rw-r--r--trunk/src/emu/cpu/m6809/m6809.c942
-rw-r--r--trunk/src/emu/cpu/m6809/m6809.h32
-rw-r--r--trunk/src/emu/cpu/mb86233/mb86233.c1716
-rw-r--r--trunk/src/emu/cpu/mb86233/mb86233.h58
-rw-r--r--trunk/src/emu/cpu/mb86233/mb86233d.c782
-rw-r--r--trunk/src/emu/cpu/mb88xx/mb88dasm.c222
-rw-r--r--trunk/src/emu/cpu/mb88xx/mb88xx.c1121
-rw-r--r--trunk/src/emu/cpu/mb88xx/mb88xx.h77
-rw-r--r--trunk/src/emu/cpu/mc68hc11/hc11dasm.c1297
-rw-r--r--trunk/src/emu/cpu/mc68hc11/hc11ops.c3509
-rw-r--r--trunk/src/emu/cpu/mc68hc11/hc11ops.h324
-rw-r--r--trunk/src/emu/cpu/mc68hc11/mc68hc11.c613
-rw-r--r--trunk/src/emu/cpu/mc68hc11/mc68hc11.h41
-rw-r--r--trunk/src/emu/cpu/mcs48/mcs48.c1546
-rw-r--r--trunk/src/emu/cpu/mcs48/mcs48.h134
-rw-r--r--trunk/src/emu/cpu/mcs48/mcs48dsm.c310
-rw-r--r--trunk/src/emu/cpu/mcs51/mcs51.c2767
-rw-r--r--trunk/src/emu/cpu/mcs51/mcs51.h153
-rw-r--r--trunk/src/emu/cpu/mcs51/mcs51dasm.c1223
-rw-r--r--trunk/src/emu/cpu/mcs51/mcs51ops.c980
-rw-r--r--trunk/src/emu/cpu/minx/minx.c397
-rw-r--r--trunk/src/emu/cpu/minx/minx.h18
-rw-r--r--trunk/src/emu/cpu/minx/minxd.c467
-rw-r--r--trunk/src/emu/cpu/minx/minxfunc.h362
-rw-r--r--trunk/src/emu/cpu/minx/minxopce.h331
-rw-r--r--trunk/src/emu/cpu/minx/minxopcf.h331
-rw-r--r--trunk/src/emu/cpu/minx/minxops.h331
-rw-r--r--trunk/src/emu/cpu/mips/mips3.c2767
-rw-r--r--trunk/src/emu/cpu/mips/mips3.h272
-rw-r--r--trunk/src/emu/cpu/mips/mips3com.c986
-rw-r--r--trunk/src/emu/cpu/mips/mips3com.h271
-rw-r--r--trunk/src/emu/cpu/mips/mips3drc.c4104
-rw-r--r--trunk/src/emu/cpu/mips/mips3dsm.c541
-rw-r--r--trunk/src/emu/cpu/mips/mips3fe.c770
-rw-r--r--trunk/src/emu/cpu/mips/mips3fe.h95
-rw-r--r--trunk/src/emu/cpu/mips/r3000.c1377
-rw-r--r--trunk/src/emu/cpu/mips/r3000.h68
-rw-r--r--trunk/src/emu/cpu/mips/r3kdasm.c387
-rw-r--r--trunk/src/emu/cpu/mn10200/mn10200.c2440
-rw-r--r--trunk/src/emu/cpu/mn10200/mn10200.h52
-rw-r--r--trunk/src/emu/cpu/mn10200/mn102dis.c1033
-rw-r--r--trunk/src/emu/cpu/nec/nec.c685
-rw-r--r--trunk/src/emu/cpu/nec/nec.h37
-rw-r--r--trunk/src/emu/cpu/nec/necdasm.c1613
-rw-r--r--trunk/src/emu/cpu/nec/necea.h60
-rw-r--r--trunk/src/emu/cpu/nec/necinstr.c671
-rw-r--r--trunk/src/emu/cpu/nec/necinstr.h507
-rw-r--r--trunk/src/emu/cpu/nec/necmacro.h267
-rw-r--r--trunk/src/emu/cpu/nec/necmodrm.h104
-rw-r--r--trunk/src/emu/cpu/nec/necpriv.h174
-rw-r--r--trunk/src/emu/cpu/nec/v25.c805
-rw-r--r--trunk/src/emu/cpu/nec/v25instr.c82
-rw-r--r--trunk/src/emu/cpu/nec/v25instr.h510
-rw-r--r--trunk/src/emu/cpu/nec/v25priv.h258
-rw-r--r--trunk/src/emu/cpu/nec/v25sfr.c400
-rw-r--r--trunk/src/emu/cpu/pdp1/pdp1.c1890
-rw-r--r--trunk/src/emu/cpu/pdp1/pdp1.h83
-rw-r--r--trunk/src/emu/cpu/pdp1/pdp1dasm.c292
-rw-r--r--trunk/src/emu/cpu/pdp1/tx0.c1303
-rw-r--r--trunk/src/emu/cpu/pdp1/tx0.h52
-rw-r--r--trunk/src/emu/cpu/pdp1/tx0dasm.c121
-rw-r--r--trunk/src/emu/cpu/pic16c5x/16c5xdsm.c254
-rw-r--r--trunk/src/emu/cpu/pic16c5x/dis16c5x.c134
-rw-r--r--trunk/src/emu/cpu/pic16c5x/pic16c5x.c1393
-rw-r--r--trunk/src/emu/cpu/pic16c5x/pic16c5x.h60
-rw-r--r--trunk/src/emu/cpu/pic16c62x/16c62xdsm.c265
-rw-r--r--trunk/src/emu/cpu/pic16c62x/dis16c62x.c136
-rw-r--r--trunk/src/emu/cpu/pic16c62x/pic16c62x.c1613
-rw-r--r--trunk/src/emu/cpu/pic16c62x/pic16c62x.h65
-rw-r--r--trunk/src/emu/cpu/powerpc/drc_ops.c3800
-rw-r--r--trunk/src/emu/cpu/powerpc/drc_ops.h143
-rw-r--r--trunk/src/emu/cpu/powerpc/ppc.c2108
-rw-r--r--trunk/src/emu/cpu/powerpc/ppc.h182
-rw-r--r--trunk/src/emu/cpu/powerpc/ppc403.c953
-rw-r--r--trunk/src/emu/cpu/powerpc/ppc602.c279
-rw-r--r--trunk/src/emu/cpu/powerpc/ppc603.c283
-rw-r--r--trunk/src/emu/cpu/powerpc/ppc_dasm.c1175
-rw-r--r--trunk/src/emu/cpu/powerpc/ppc_mem.c419
-rw-r--r--trunk/src/emu/cpu/powerpc/ppc_ops.c2818
-rw-r--r--trunk/src/emu/cpu/powerpc/ppc_ops.h150
-rw-r--r--trunk/src/emu/cpu/powerpc/ppccom.c2231
-rw-r--r--trunk/src/emu/cpu/powerpc/ppccom.h604
-rw-r--r--trunk/src/emu/cpu/powerpc/ppcdrc.c4586
-rw-r--r--trunk/src/emu/cpu/powerpc/ppcfe.c1422
-rw-r--r--trunk/src/emu/cpu/powerpc/ppcfe.h106
-rw-r--r--trunk/src/emu/cpu/pps4/pps4.c454
-rw-r--r--trunk/src/emu/cpu/pps4/pps4.h28
-rw-r--r--trunk/src/emu/cpu/pps4/pps4dasm.c135
-rw-r--r--trunk/src/emu/cpu/psx/dismips.c360
-rw-r--r--trunk/src/emu/cpu/psx/dismips.mak2
-rw-r--r--trunk/src/emu/cpu/psx/dma.c421
-rw-r--r--trunk/src/emu/cpu/psx/dma.h64
-rw-r--r--trunk/src/emu/cpu/psx/gte.c2980
-rw-r--r--trunk/src/emu/cpu/psx/gte.h45
-rw-r--r--trunk/src/emu/cpu/psx/irq.c112
-rw-r--r--trunk/src/emu/cpu/psx/irq.h51
-rw-r--r--trunk/src/emu/cpu/psx/mdec.c572
-rw-r--r--trunk/src/emu/cpu/psx/mdec.h74
-rw-r--r--trunk/src/emu/cpu/psx/psx.c3207
-rw-r--r--trunk/src/emu/cpu/psx/psx.h455
-rw-r--r--trunk/src/emu/cpu/psx/psxdasm.c749
-rw-r--r--trunk/src/emu/cpu/psx/rcnt.c237
-rw-r--r--trunk/src/emu/cpu/psx/rcnt.h60
-rw-r--r--trunk/src/emu/cpu/psx/sio.c383
-rw-r--r--trunk/src/emu/cpu/psx/sio.h94
-rw-r--r--trunk/src/emu/cpu/rsp/rsp.c3144
-rw-r--r--trunk/src/emu/cpu/rsp/rsp.h194
-rw-r--r--trunk/src/emu/cpu/rsp/rsp_dasm.c353
-rw-r--r--trunk/src/emu/cpu/rsp/rspdiv.h1027
-rw-r--r--trunk/src/emu/cpu/rsp/rspdrc.c4848
-rw-r--r--trunk/src/emu/cpu/rsp/rspfe.c304
-rw-r--r--trunk/src/emu/cpu/rsp/rspfe.h58
-rw-r--r--trunk/src/emu/cpu/s2650/2650dasm.c868
-rw-r--r--trunk/src/emu/cpu/s2650/s2650.c1647
-rw-r--r--trunk/src/emu/cpu/s2650/s2650.h28
-rw-r--r--trunk/src/emu/cpu/s2650/s2650cpu.h33
-rw-r--r--trunk/src/emu/cpu/saturn/satops.c1137
-rw-r--r--trunk/src/emu/cpu/saturn/sattable.c1037
-rw-r--r--trunk/src/emu/cpu/saturn/saturn.c412
-rw-r--r--trunk/src/emu/cpu/saturn/saturn.h92
-rw-r--r--trunk/src/emu/cpu/saturn/saturnds.c1486
-rw-r--r--trunk/src/emu/cpu/sc61860/readpc.c195
-rw-r--r--trunk/src/emu/cpu/sc61860/sc.h32
-rw-r--r--trunk/src/emu/cpu/sc61860/sc61860.c252
-rw-r--r--trunk/src/emu/cpu/sc61860/sc61860.h60
-rw-r--r--trunk/src/emu/cpu/sc61860/scdasm.c221
-rw-r--r--trunk/src/emu/cpu/sc61860/scops.c773
-rw-r--r--trunk/src/emu/cpu/sc61860/sctable.c144
-rw-r--r--trunk/src/emu/cpu/scmp/scmp.c670
-rw-r--r--trunk/src/emu/cpu/scmp/scmp.h42
-rw-r--r--trunk/src/emu/cpu/scmp/scmpdasm.c153
-rw-r--r--trunk/src/emu/cpu/se3208/se3208.c1941
-rw-r--r--trunk/src/emu/cpu/se3208/se3208.h12
-rw-r--r--trunk/src/emu/cpu/se3208/se3208dis.c1413
-rw-r--r--trunk/src/emu/cpu/sh2/sh2.c2508
-rw-r--r--trunk/src/emu/cpu/sh2/sh2.h91
-rw-r--r--trunk/src/emu/cpu/sh2/sh2comn.c1011
-rw-r--r--trunk/src/emu/cpu/sh2/sh2comn.h217
-rw-r--r--trunk/src/emu/cpu/sh2/sh2dasm.c609
-rw-r--r--trunk/src/emu/cpu/sh2/sh2drc.c3421
-rw-r--r--trunk/src/emu/cpu/sh2/sh2fe.c764
-rw-r--r--trunk/src/emu/cpu/sh4/sh4.c3852
-rw-r--r--trunk/src/emu/cpu/sh4/sh4.h131
-rw-r--r--trunk/src/emu/cpu/sh4/sh4comn.c1566
-rw-r--r--trunk/src/emu/cpu/sh4/sh4comn.h299
-rw-r--r--trunk/src/emu/cpu/sh4/sh4dasm.c818
-rw-r--r--trunk/src/emu/cpu/sh4/sh4regs.h204
-rw-r--r--trunk/src/emu/cpu/sharc/compute.c1338
-rw-r--r--trunk/src/emu/cpu/sharc/sharc.c1322
-rw-r--r--trunk/src/emu/cpu/sharc/sharc.h33
-rw-r--r--trunk/src/emu/cpu/sharc/sharcdma.c204
-rw-r--r--trunk/src/emu/cpu/sharc/sharcdsm.c1197
-rw-r--r--trunk/src/emu/cpu/sharc/sharcdsm.h77
-rw-r--r--trunk/src/emu/cpu/sharc/sharcmem.c202
-rw-r--r--trunk/src/emu/cpu/sharc/sharcops.c2754
-rw-r--r--trunk/src/emu/cpu/sharc/sharcops.h138
-rw-r--r--trunk/src/emu/cpu/sm8500/sm8500.c601
-rw-r--r--trunk/src/emu/cpu/sm8500/sm8500.h39
-rw-r--r--trunk/src/emu/cpu/sm8500/sm8500d.c582
-rw-r--r--trunk/src/emu/cpu/sm8500/sm85ops.h1686
-rw-r--r--trunk/src/emu/cpu/spc700/spc700.c1756
-rw-r--r--trunk/src/emu/cpu/spc700/spc700.h38
-rw-r--r--trunk/src/emu/cpu/spc700/spc700ds.c433
-rw-r--r--trunk/src/emu/cpu/spc700/spc700ds.h26
-rw-r--r--trunk/src/emu/cpu/ssem/ssem.c309
-rw-r--r--trunk/src/emu/cpu/ssem/ssem.h23
-rw-r--r--trunk/src/emu/cpu/ssem/ssemdasm.c85
-rw-r--r--trunk/src/emu/cpu/ssp1601/ssp1601.c916
-rw-r--r--trunk/src/emu/cpu/ssp1601/ssp1601.h22
-rw-r--r--trunk/src/emu/cpu/ssp1601/ssp1601d.c298
-rw-r--r--trunk/src/emu/cpu/superfx/sfx_dasm.c423
-rw-r--r--trunk/src/emu/cpu/superfx/superfx.c1680
-rw-r--r--trunk/src/emu/cpu/superfx/superfx.h104
-rw-r--r--trunk/src/emu/cpu/t11/t11.c499
-rw-r--r--trunk/src/emu/cpu/t11/t11.h39
-rw-r--r--trunk/src/emu/cpu/t11/t11dasm.c516
-rw-r--r--trunk/src/emu/cpu/t11/t11ops.c1414
-rw-r--r--trunk/src/emu/cpu/t11/t11table.c2410
-rw-r--r--trunk/src/emu/cpu/tlcs90/tlcs90.c2945
-rw-r--r--trunk/src/emu/cpu/tlcs90/tlcs90.h26
-rw-r--r--trunk/src/emu/cpu/tlcs900/900tbl.c6023
-rw-r--r--trunk/src/emu/cpu/tlcs900/dasm900.c2256
-rw-r--r--trunk/src/emu/cpu/tlcs900/tlcs900.c1244
-rw-r--r--trunk/src/emu/cpu/tlcs900/tlcs900.h46
-rw-r--r--trunk/src/emu/cpu/tms0980/tms0980.c1285
-rw-r--r--trunk/src/emu/cpu/tms0980/tms0980.h42
-rw-r--r--trunk/src/emu/cpu/tms0980/tms0980d.c345
-rw-r--r--trunk/src/emu/cpu/tms32010/32010dsm.c336
-rw-r--r--trunk/src/emu/cpu/tms32010/dis32010.c136
-rw-r--r--trunk/src/emu/cpu/tms32010/tms32010.c1139
-rw-r--r--trunk/src/emu/cpu/tms32010/tms32010.h54
-rw-r--r--trunk/src/emu/cpu/tms32025/32025dsm.c505
-rw-r--r--trunk/src/emu/cpu/tms32025/dis32025.c135
-rw-r--r--trunk/src/emu/cpu/tms32025/tms32025.c2479
-rw-r--r--trunk/src/emu/cpu/tms32025/tms32025.h74
-rw-r--r--trunk/src/emu/cpu/tms32031/32031ops.c6906
-rw-r--r--trunk/src/emu/cpu/tms32031/dis32031.c741
-rw-r--r--trunk/src/emu/cpu/tms32031/tms32031.c898
-rw-r--r--trunk/src/emu/cpu/tms32031/tms32031.h848
-rw-r--r--trunk/src/emu/cpu/tms32051/32051ops.c1961
-rw-r--r--trunk/src/emu/cpu/tms32051/32051ops.h251
-rw-r--r--trunk/src/emu/cpu/tms32051/dis32051.c642
-rw-r--r--trunk/src/emu/cpu/tms32051/tms32051.c739
-rw-r--r--trunk/src/emu/cpu/tms32051/tms32051.h10
-rw-r--r--trunk/src/emu/cpu/tms34010/34010dsm.c1760
-rw-r--r--trunk/src/emu/cpu/tms34010/34010fld.c680
-rw-r--r--trunk/src/emu/cpu/tms34010/34010gfx.c2043
-rw-r--r--trunk/src/emu/cpu/tms34010/34010ops.c2458
-rw-r--r--trunk/src/emu/cpu/tms34010/34010ops.h157
-rw-r--r--trunk/src/emu/cpu/tms34010/34010tbl.c1167
-rw-r--r--trunk/src/emu/cpu/tms34010/dis34010.c113
-rw-r--r--trunk/src/emu/cpu/tms34010/makefile6
-rw-r--r--trunk/src/emu/cpu/tms34010/tms34010.c1791
-rw-r--r--trunk/src/emu/cpu/tms34010/tms34010.h241
-rw-r--r--trunk/src/emu/cpu/tms57002/57002dsm.c91
-rw-r--r--trunk/src/emu/cpu/tms57002/tms57002.c1152
-rw-r--r--trunk/src/emu/cpu/tms57002/tms57002.h24
-rw-r--r--trunk/src/emu/cpu/tms57002/tms57kdec.c91
-rw-r--r--trunk/src/emu/cpu/tms57002/tms57kpr.h171
-rw-r--r--trunk/src/emu/cpu/tms57002/tmsinstr.lst535
-rw-r--r--trunk/src/emu/cpu/tms57002/tmsmake.c959
-rw-r--r--trunk/src/emu/cpu/tms7000/7000dasm.c446
-rw-r--r--trunk/src/emu/cpu/tms7000/tms7000.c732
-rw-r--r--trunk/src/emu/cpu/tms7000/tms7000.h56
-rw-r--r--trunk/src/emu/cpu/tms7000/tms70op.c3903
-rw-r--r--trunk/src/emu/cpu/tms7000/tms70tb.c124
-rw-r--r--trunk/src/emu/cpu/tms9900/9900dasm.c799
-rw-r--r--trunk/src/emu/cpu/tms9900/99xxcore.h4816
-rw-r--r--trunk/src/emu/cpu/tms9900/99xxstat.h483
-rw-r--r--trunk/src/emu/cpu/tms9900/ti990_10.c13
-rw-r--r--trunk/src/emu/cpu/tms9900/tms9900.c13
-rw-r--r--trunk/src/emu/cpu/tms9900/tms9900.h210
-rw-r--r--trunk/src/emu/cpu/tms9900/tms9980a.c13
-rw-r--r--trunk/src/emu/cpu/tms9900/tms9995.c13
-rw-r--r--trunk/src/emu/cpu/uml.c1059
-rw-r--r--trunk/src/emu/cpu/uml.h690
-rw-r--r--trunk/src/emu/cpu/unsp/unsp.c924
-rw-r--r--trunk/src/emu/cpu/unsp/unsp.h71
-rw-r--r--trunk/src/emu/cpu/unsp/unspdasm.c270
-rwxr-xr-xtrunk/src/emu/cpu/upd7725/dasm7725.c233
-rwxr-xr-xtrunk/src/emu/cpu/upd7725/upd7725.c639
-rwxr-xr-xtrunk/src/emu/cpu/upd7725/upd7725.h235
-rw-r--r--trunk/src/emu/cpu/upd7810/7810dasm.c5466
-rw-r--r--trunk/src/emu/cpu/upd7810/7810ops.c9488
-rw-r--r--trunk/src/emu/cpu/upd7810/7810tbl.c7288
-rw-r--r--trunk/src/emu/cpu/upd7810/upd7810.c2390
-rw-r--r--trunk/src/emu/cpu/upd7810/upd7810.h85
-rw-r--r--trunk/src/emu/cpu/v30mz/nec.h23
-rw-r--r--trunk/src/emu/cpu/v30mz/necea.h56
-rw-r--r--trunk/src/emu/cpu/v30mz/nechost.h11
-rw-r--r--trunk/src/emu/cpu/v30mz/necinstr.h507
-rw-r--r--trunk/src/emu/cpu/v30mz/necmodrm.h104
-rw-r--r--trunk/src/emu/cpu/v30mz/v30mz.c1171
-rw-r--r--trunk/src/emu/cpu/v30mz/v30mz.h358
-rw-r--r--trunk/src/emu/cpu/v60/am.c84
-rw-r--r--trunk/src/emu/cpu/v60/am1.c1388
-rw-r--r--trunk/src/emu/cpu/v60/am2.c1256
-rw-r--r--trunk/src/emu/cpu/v60/am3.c887
-rw-r--r--trunk/src/emu/cpu/v60/op12.c2391
-rw-r--r--trunk/src/emu/cpu/v60/op2.c353
-rw-r--r--trunk/src/emu/cpu/v60/op3.c639
-rw-r--r--trunk/src/emu/cpu/v60/op4.c354
-rw-r--r--trunk/src/emu/cpu/v60/op5.c93
-rw-r--r--trunk/src/emu/cpu/v60/op6.c254
-rw-r--r--trunk/src/emu/cpu/v60/op7a.c1211
-rw-r--r--trunk/src/emu/cpu/v60/optable.c259
-rw-r--r--trunk/src/emu/cpu/v60/v60.c766
-rw-r--r--trunk/src/emu/cpu/v60/v60.h85
-rw-r--r--trunk/src/emu/cpu/v60/v60d.c1497
-rw-r--r--trunk/src/emu/cpu/v810/v810.c1354
-rw-r--r--trunk/src/emu/cpu/v810/v810.h83
-rw-r--r--trunk/src/emu/cpu/v810/v810dasm.c176
-rw-r--r--trunk/src/emu/cpu/vtlb.c287
-rw-r--r--trunk/src/emu/cpu/vtlb.h88
-rw-r--r--trunk/src/emu/cpu/x86emit.h3218
-rw-r--r--trunk/src/emu/cpu/x86log.c304
-rw-r--r--trunk/src/emu/cpu/x86log.h52
-rw-r--r--trunk/src/emu/cpu/z180/z180.c2738
-rw-r--r--trunk/src/emu/cpu/z180/z180.h141
-rw-r--r--trunk/src/emu/cpu/z180/z180cb.c293
-rw-r--r--trunk/src/emu/cpu/z180/z180dasm.c554
-rw-r--r--trunk/src/emu/cpu/z180/z180dd.c296
-rw-r--r--trunk/src/emu/cpu/z180/z180ed.c297
-rw-r--r--trunk/src/emu/cpu/z180/z180fd.c291
-rw-r--r--trunk/src/emu/cpu/z180/z180op.c382
-rw-r--r--trunk/src/emu/cpu/z180/z180ops.h954
-rw-r--r--trunk/src/emu/cpu/z180/z180tbl.h304
-rw-r--r--trunk/src/emu/cpu/z180/z180xy.c292
-rw-r--r--trunk/src/emu/cpu/z8/z8.c923
-rw-r--r--trunk/src/emu/cpu/z8/z8.h37
-rw-r--r--trunk/src/emu/cpu/z8/z8dasm.c378
-rw-r--r--trunk/src/emu/cpu/z8/z8ops.c746
-rw-r--r--trunk/src/emu/cpu/z80/z80.c3959
-rw-r--r--trunk/src/emu/cpu/z80/z80.h36
-rw-r--r--trunk/src/emu/cpu/z80/z80daisy.c170
-rw-r--r--trunk/src/emu/cpu/z80/z80daisy.h87
-rw-r--r--trunk/src/emu/cpu/z80/z80dasm.c544
-rw-r--r--trunk/src/emu/cpu/z8000/8000dasm.c322
-rw-r--r--trunk/src/emu/cpu/z8000/makedab.c87
-rw-r--r--trunk/src/emu/cpu/z8000/z8000.c719
-rw-r--r--trunk/src/emu/cpu/z8000/z8000.h32
-rw-r--r--trunk/src/emu/cpu/z8000/z8000cpu.h215
-rw-r--r--trunk/src/emu/cpu/z8000/z8000dab.h275
-rw-r--r--trunk/src/emu/cpu/z8000/z8000ops.c6607
-rw-r--r--trunk/src/emu/cpu/z8000/z8000tbl.c1152
-rw-r--r--trunk/src/emu/crsshair.c532
-rw-r--r--trunk/src/emu/crsshair.h80
-rw-r--r--trunk/src/emu/debug/debugcmd.c2738
-rw-r--r--trunk/src/emu/debug/debugcmd.h38
-rw-r--r--trunk/src/emu/debug/debugcon.c568
-rw-r--r--trunk/src/emu/debug/debugcon.h96
-rw-r--r--trunk/src/emu/debug/debugcpu.c3376
-rw-r--r--trunk/src/emu/debug/debugcpu.h460
-rw-r--r--trunk/src/emu/debug/debughlp.c1323
-rw-r--r--trunk/src/emu/debug/debughlp.h23
-rw-r--r--trunk/src/emu/debug/debugvw.c633
-rw-r--r--trunk/src/emu/debug/debugvw.h335
-rw-r--r--trunk/src/emu/debug/dvdisasm.c705
-rw-r--r--trunk/src/emu/debug/dvdisasm.h146
-rw-r--r--trunk/src/emu/debug/dvmemory.c815
-rw-r--r--trunk/src/emu/debug/dvmemory.h160
-rw-r--r--trunk/src/emu/debug/dvstate.c370
-rw-r--r--trunk/src/emu/debug/dvstate.h117
-rw-r--r--trunk/src/emu/debug/dvtext.c184
-rw-r--r--trunk/src/emu/debug/dvtext.h90
-rw-r--r--trunk/src/emu/debug/express.c1781
-rw-r--r--trunk/src/emu/debug/express.h413
-rw-r--r--trunk/src/emu/debug/textbuf.c326
-rw-r--r--trunk/src/emu/debug/textbuf.h56
-rw-r--r--trunk/src/emu/debugger.c148
-rw-r--r--trunk/src/emu/debugger.h140
-rw-r--r--trunk/src/emu/debugint/debugint.c1484
-rw-r--r--trunk/src/emu/debugint/debugint.h47
-rw-r--r--trunk/src/emu/delegate.c70
-rw-r--r--trunk/src/emu/delegate.h700
-rw-r--r--trunk/src/emu/deprecat.h53
-rw-r--r--trunk/src/emu/devcb.c754
-rw-r--r--trunk/src/emu/devcb.h541
-rw-r--r--trunk/src/emu/devconv.h1020
-rw-r--r--trunk/src/emu/devcpu.c484
-rw-r--r--trunk/src/emu/devcpu.h437
-rw-r--r--trunk/src/emu/device.c1143
-rw-r--r--trunk/src/emu/device.h544
-rw-r--r--trunk/src/emu/devimage.c181
-rw-r--r--trunk/src/emu/devlegcy.c359
-rw-r--r--trunk/src/emu/devlegcy.h546
-rw-r--r--trunk/src/emu/devtempl.h327
-rw-r--r--trunk/src/emu/didisasm.c63
-rw-r--r--trunk/src/emu/didisasm.h102
-rw-r--r--trunk/src/emu/diexec.c1001
-rw-r--r--trunk/src/emu/diexec.h475
-rw-r--r--trunk/src/emu/diimage.c1035
-rw-r--r--trunk/src/emu/diimage.h325
-rw-r--r--trunk/src/emu/dimemory.c379
-rw-r--r--trunk/src/emu/dimemory.h164
-rw-r--r--trunk/src/emu/dinvram.c64
-rw-r--r--trunk/src/emu/dinvram.h78
-rw-r--r--trunk/src/emu/dirtc.c33
-rw-r--r--trunk/src/emu/dirtc.h41
-rw-r--r--trunk/src/emu/dislot.c52
-rw-r--r--trunk/src/emu/dislot.h68
-rw-r--r--trunk/src/emu/disound.c366
-rw-r--r--trunk/src/emu/disound.h150
-rw-r--r--trunk/src/emu/distate.c608
-rw-r--r--trunk/src/emu/distate.h218
-rw-r--r--trunk/src/emu/drawgfx.c2014
-rw-r--r--trunk/src/emu/drawgfx.h426
-rw-r--r--trunk/src/emu/drawgfxm.h1394
-rw-r--r--trunk/src/emu/driver.c430
-rw-r--r--trunk/src/emu/driver.h338
-rw-r--r--trunk/src/emu/drivers/empty.c69
-rw-r--r--trunk/src/emu/drivers/emudummy.c67
-rw-r--r--trunk/src/emu/drivers/xtal.h573
-rw-r--r--trunk/src/emu/eigccppc.h493
-rw-r--r--trunk/src/emu/eigccx86.h688
-rw-r--r--trunk/src/emu/eminline.h453
-rw-r--r--trunk/src/emu/emu.h137
-rw-r--r--trunk/src/emu/emu.mak363
-rw-r--r--trunk/src/emu/emualloc.c607
-rw-r--r--trunk/src/emu/emualloc.h336
-rw-r--r--trunk/src/emu/emucore.c11
-rw-r--r--trunk/src/emu/emucore.h455
-rw-r--r--trunk/src/emu/emuopts.c514
-rw-r--r--trunk/src/emu/emuopts.h364
-rw-r--r--trunk/src/emu/emupal.c770
-rw-r--r--trunk/src/emu/emupal.h250
-rw-r--r--trunk/src/emu/emutempl.h431
-rw-r--r--trunk/src/emu/fileio.c769
-rw-r--r--trunk/src/emu/fileio.h183
-rw-r--r--trunk/src/emu/hash.c739
-rw-r--r--trunk/src/emu/hash.h187
-rw-r--r--trunk/src/emu/hashfile.c626
-rw-r--r--trunk/src/emu/hashfile.h17
-rw-r--r--trunk/src/emu/image.c495
-rw-r--r--trunk/src/emu/image.h35
-rw-r--r--trunk/src/emu/imagedev/bitbngr.c523
-rw-r--r--trunk/src/emu/imagedev/bitbngr.h99
-rw-r--r--trunk/src/emu/imagedev/cartslot.c315
-rw-r--r--trunk/src/emu/imagedev/cartslot.h84
-rw-r--r--trunk/src/emu/imagedev/cassette.c380
-rw-r--r--trunk/src/emu/imagedev/cassette.h132
-rw-r--r--trunk/src/emu/imagedev/chd_cd.c165
-rw-r--r--trunk/src/emu/imagedev/chd_cd.h76
-rw-r--r--trunk/src/emu/imagedev/flopdrv.c1071
-rw-r--r--trunk/src/emu/imagedev/flopdrv.h249
-rw-r--r--trunk/src/emu/imagedev/floppy.c216
-rw-r--r--trunk/src/emu/imagedev/floppy.h125
-rw-r--r--trunk/src/emu/imagedev/harddriv.c268
-rw-r--r--trunk/src/emu/imagedev/harddriv.h84
-rw-r--r--trunk/src/emu/imagedev/multcart.c888
-rw-r--r--trunk/src/emu/imagedev/multcart.h194
-rw-r--r--trunk/src/emu/imagedev/printer.c120
-rw-r--r--trunk/src/emu/imagedev/printer.h74
-rw-r--r--trunk/src/emu/imagedev/snapquik.c373
-rw-r--r--trunk/src/emu/imagedev/snapquik.h115
-rw-r--r--trunk/src/emu/info.c1231
-rw-r--r--trunk/src/emu/info.h94
-rw-r--r--trunk/src/emu/inpttype.h672
-rw-r--r--trunk/src/emu/input.c2432
-rw-r--r--trunk/src/emu/input.h1087
-rw-r--r--trunk/src/emu/ioport.c4892
-rw-r--r--trunk/src/emu/ioport.h1287
-rw-r--r--trunk/src/emu/layout/dualhovu.lay72
-rw-r--r--trunk/src/emu/layout/dualhsxs.lay72
-rw-r--r--trunk/src/emu/layout/dualhuov.lay72
-rw-r--r--trunk/src/emu/layout/ho20ffff.lay18
-rw-r--r--trunk/src/emu/layout/ho2eff2e.lay18
-rw-r--r--trunk/src/emu/layout/ho4f893d.lay21
-rw-r--r--trunk/src/emu/layout/ho88ffff.lay18
-rw-r--r--trunk/src/emu/layout/hoa0a0ff.lay18
-rw-r--r--trunk/src/emu/layout/hoffe457.lay18
-rw-r--r--trunk/src/emu/layout/hoffff20.lay18
-rw-r--r--trunk/src/emu/layout/horizont.lay24
-rw-r--r--trunk/src/emu/layout/lcd.lay8
-rw-r--r--trunk/src/emu/layout/lcd_rot.lay8
-rw-r--r--trunk/src/emu/layout/noscreens.lay22
-rw-r--r--trunk/src/emu/layout/quadhsxs.lay110
-rw-r--r--trunk/src/emu/layout/snap.lay50
-rw-r--r--trunk/src/emu/layout/triphsxs.lay62
-rw-r--r--trunk/src/emu/layout/vertical.lay37
-rw-r--r--trunk/src/emu/layout/voffff20.lay18
-rw-r--r--trunk/src/emu/machine.c1241
-rw-r--r--trunk/src/emu/machine.h624
-rw-r--r--trunk/src/emu/machine/53c810.c919
-rw-r--r--trunk/src/emu/machine/53c810.h27
-rw-r--r--trunk/src/emu/machine/6522via.c1072
-rw-r--r--trunk/src/emu/machine/6522via.h190
-rw-r--r--trunk/src/emu/machine/6525tpi.c623
-rw-r--r--trunk/src/emu/machine/6525tpi.h94
-rw-r--r--trunk/src/emu/machine/6526cia.c921
-rw-r--r--trunk/src/emu/machine/6526cia.h264
-rw-r--r--trunk/src/emu/machine/6532riot.c544
-rw-r--r--trunk/src/emu/machine/6532riot.h132
-rw-r--r--trunk/src/emu/machine/6821pia.c1210
-rw-r--r--trunk/src/emu/machine/6821pia.h230
-rw-r--r--trunk/src/emu/machine/6840ptm.c728
-rw-r--r--trunk/src/emu/machine/6840ptm.h139
-rw-r--r--trunk/src/emu/machine/6850acia.c746
-rw-r--r--trunk/src/emu/machine/6850acia.h187
-rw-r--r--trunk/src/emu/machine/68681.c816
-rw-r--r--trunk/src/emu/machine/68681.h30
-rw-r--r--trunk/src/emu/machine/74123.c304
-rw-r--r--trunk/src/emu/machine/74123.h142
-rw-r--r--trunk/src/emu/machine/74148.c226
-rw-r--r--trunk/src/emu/machine/74148.h70
-rw-r--r--trunk/src/emu/machine/74153.c188
-rw-r--r--trunk/src/emu/machine/74153.h66
-rw-r--r--trunk/src/emu/machine/74181.c165
-rw-r--r--trunk/src/emu/machine/74181.h40
-rw-r--r--trunk/src/emu/machine/7474.c266
-rw-r--r--trunk/src/emu/machine/7474.h141
-rw-r--r--trunk/src/emu/machine/8042kbdc.c622
-rw-r--r--trunk/src/emu/machine/8042kbdc.h41
-rw-r--r--trunk/src/emu/machine/8237dma.c711
-rw-r--r--trunk/src/emu/machine/8237dma.h210
-rw-r--r--trunk/src/emu/machine/8255ppi.c666
-rw-r--r--trunk/src/emu/machine/8255ppi.h153
-rw-r--r--trunk/src/emu/machine/8257dma.c454
-rw-r--r--trunk/src/emu/machine/8257dma.h165
-rw-r--r--trunk/src/emu/machine/adc0808.c171
-rw-r--r--trunk/src/emu/machine/adc0808.h116
-rw-r--r--trunk/src/emu/machine/adc083x.c539
-rw-r--r--trunk/src/emu/machine/adc083x.h81
-rw-r--r--trunk/src/emu/machine/adc1038.c177
-rw-r--r--trunk/src/emu/machine/adc1038.h50
-rw-r--r--trunk/src/emu/machine/adc1213x.c377
-rw-r--r--trunk/src/emu/machine/adc1213x.h60
-rw-r--r--trunk/src/emu/machine/am53cf96.c289
-rw-r--r--trunk/src/emu/machine/am53cf96.h25
-rw-r--r--trunk/src/emu/machine/am8530h.c57
-rw-r--r--trunk/src/emu/machine/am8530h.h42
-rw-r--r--trunk/src/emu/machine/at28c16.c295
-rw-r--r--trunk/src/emu/machine/at28c16.h92
-rw-r--r--trunk/src/emu/machine/cdp1852.c221
-rw-r--r--trunk/src/emu/machine/cdp1852.h124
-rw-r--r--trunk/src/emu/machine/cdp1871.c305
-rw-r--r--trunk/src/emu/machine/cdp1871.h148
-rw-r--r--trunk/src/emu/machine/com8116.c135
-rw-r--r--trunk/src/emu/machine/com8116.h108
-rw-r--r--trunk/src/emu/machine/cr589.c156
-rw-r--r--trunk/src/emu/machine/cr589.h3
-rw-r--r--trunk/src/emu/machine/ctronics.c395
-rw-r--r--trunk/src/emu/machine/ctronics.h75
-rw-r--r--trunk/src/emu/machine/devhelpr.h41
-rw-r--r--trunk/src/emu/machine/ds1302.c215
-rw-r--r--trunk/src/emu/machine/ds1302.h75
-rw-r--r--trunk/src/emu/machine/ds2401.c239
-rw-r--r--trunk/src/emu/machine/ds2401.h69
-rw-r--r--trunk/src/emu/machine/ds2404.c388
-rw-r--r--trunk/src/emu/machine/ds2404.h140
-rw-r--r--trunk/src/emu/machine/e0516.c274
-rw-r--r--trunk/src/emu/machine/e0516.h92
-rw-r--r--trunk/src/emu/machine/eeprom.c563
-rw-r--r--trunk/src/emu/machine/eeprom.h142
-rw-r--r--trunk/src/emu/machine/er2055.c205
-rw-r--r--trunk/src/emu/machine/er2055.h113
-rw-r--r--trunk/src/emu/machine/f3853.c253
-rw-r--r--trunk/src/emu/machine/f3853.h129
-rw-r--r--trunk/src/emu/machine/generic.c769
-rw-r--r--trunk/src/emu/machine/generic.h177
-rw-r--r--trunk/src/emu/machine/i2cmem.c566
-rw-r--r--trunk/src/emu/machine/i2cmem.h128
-rw-r--r--trunk/src/emu/machine/i8155.c614
-rw-r--r--trunk/src/emu/machine/i8155.h154
-rw-r--r--trunk/src/emu/machine/i8212.c165
-rw-r--r--trunk/src/emu/machine/i8212.h111
-rw-r--r--trunk/src/emu/machine/i8214.c225
-rw-r--r--trunk/src/emu/machine/i8214.h104
-rw-r--r--trunk/src/emu/machine/i8243.c168
-rw-r--r--trunk/src/emu/machine/i8243.h97
-rw-r--r--trunk/src/emu/machine/i8255.c1031
-rw-r--r--trunk/src/emu/machine/i8255.h156
-rw-r--r--trunk/src/emu/machine/i8355.c231
-rw-r--r--trunk/src/emu/machine/i8355.h124
-rw-r--r--trunk/src/emu/machine/idectrl.c2033
-rw-r--r--trunk/src/emu/machine/idectrl.h89
-rw-r--r--trunk/src/emu/machine/ins8154.c271
-rw-r--r--trunk/src/emu/machine/ins8154.h126
-rw-r--r--trunk/src/emu/machine/ins8250.c715
-rw-r--r--trunk/src/emu/machine/ins8250.h83
-rw-r--r--trunk/src/emu/machine/intelfsh.c753
-rw-r--r--trunk/src/emu/machine/intelfsh.h255
-rw-r--r--trunk/src/emu/machine/jvsdev.c254
-rw-r--r--trunk/src/emu/machine/jvsdev.h53
-rw-r--r--trunk/src/emu/machine/jvshost.c157
-rw-r--r--trunk/src/emu/machine/jvshost.h45
-rw-r--r--trunk/src/emu/machine/k033906.c161
-rw-r--r--trunk/src/emu/machine/k033906.h89
-rw-r--r--trunk/src/emu/machine/k053252.c256
-rw-r--r--trunk/src/emu/machine/k053252.h39
-rw-r--r--trunk/src/emu/machine/k056230.c148
-rw-r--r--trunk/src/emu/machine/k056230.h89
-rw-r--r--trunk/src/emu/machine/laserdsc.h240
-rw-r--r--trunk/src/emu/machine/latch8.c259
-rw-r--r--trunk/src/emu/machine/latch8.h143
-rw-r--r--trunk/src/emu/machine/ldcore.c1716
-rw-r--r--trunk/src/emu/machine/ldcore.h268
-rw-r--r--trunk/src/emu/machine/ldpr8210.c1271
-rw-r--r--trunk/src/emu/machine/ldv1000.c761
-rw-r--r--trunk/src/emu/machine/ldvp931.c781
-rw-r--r--trunk/src/emu/machine/matsucd.c766
-rw-r--r--trunk/src/emu/machine/matsucd.h29
-rw-r--r--trunk/src/emu/machine/mb14241.c80
-rw-r--r--trunk/src/emu/machine/mb14241.h32
-rw-r--r--trunk/src/emu/machine/mb3773.c114
-rw-r--r--trunk/src/emu/machine/mb3773.h62
-rw-r--r--trunk/src/emu/machine/mb87078.c278
-rw-r--r--trunk/src/emu/machine/mb87078.h59
-rw-r--r--trunk/src/emu/machine/mc146818.c514
-rw-r--r--trunk/src/emu/machine/mc146818.h118
-rw-r--r--trunk/src/emu/machine/mc6852.c370
-rw-r--r--trunk/src/emu/machine/mc6852.h139
-rw-r--r--trunk/src/emu/machine/mc68901.c1476
-rw-r--r--trunk/src/emu/machine/mc68901.h232
-rw-r--r--trunk/src/emu/machine/mccs1850.c598
-rw-r--r--trunk/src/emu/machine/mccs1850.h135
-rw-r--r--trunk/src/emu/machine/microtch.c254
-rw-r--r--trunk/src/emu/machine/microtch.h12
-rw-r--r--trunk/src/emu/machine/mm74c922.c217
-rw-r--r--trunk/src/emu/machine/mm74c922.h139
-rw-r--r--trunk/src/emu/machine/mos6529.c91
-rw-r--r--trunk/src/emu/machine/mos6529.h86
-rw-r--r--trunk/src/emu/machine/msm5832.c377
-rw-r--r--trunk/src/emu/machine/msm5832.h102
-rw-r--r--trunk/src/emu/machine/msm58321.c452
-rw-r--r--trunk/src/emu/machine/msm58321.h121
-rw-r--r--trunk/src/emu/machine/msm6242.c204
-rw-r--r--trunk/src/emu/machine/msm6242.h28
-rw-r--r--trunk/src/emu/machine/nmc9306.c322
-rw-r--r--trunk/src/emu/machine/nmc9306.h94
-rw-r--r--trunk/src/emu/machine/nvram.c199
-rw-r--r--trunk/src/emu/machine/nvram.h153
-rw-r--r--trunk/src/emu/machine/pc16552d.c439
-rw-r--r--trunk/src/emu/machine/pc16552d.h12
-rw-r--r--trunk/src/emu/machine/pci.c335
-rw-r--r--trunk/src/emu/machine/pci.h73
-rw-r--r--trunk/src/emu/machine/pckeybrd.h35
-rw-r--r--trunk/src/emu/machine/pcshare.h14
-rw-r--r--trunk/src/emu/machine/pd4990a.c537
-rw-r--r--trunk/src/emu/machine/pd4990a.h37
-rw-r--r--trunk/src/emu/machine/pic8259.c475
-rw-r--r--trunk/src/emu/machine/pic8259.h73
-rw-r--r--trunk/src/emu/machine/pit8253.c1193
-rw-r--r--trunk/src/emu/machine/pit8253.h83
-rw-r--r--trunk/src/emu/machine/ram.c268
-rw-r--r--trunk/src/emu/machine/ram.h68
-rw-r--r--trunk/src/emu/machine/rescap.h23
-rw-r--r--trunk/src/emu/machine/roc10937.c398
-rw-r--r--trunk/src/emu/machine/roc10937.h34
-rw-r--r--trunk/src/emu/machine/rp5c01.c527
-rw-r--r--trunk/src/emu/machine/rp5c01.h123
-rw-r--r--trunk/src/emu/machine/rp5c15.c552
-rw-r--r--trunk/src/emu/machine/rp5c15.h122
-rw-r--r--trunk/src/emu/machine/rp5h01.c216
-rw-r--r--trunk/src/emu/machine/rp5h01.h39
-rw-r--r--trunk/src/emu/machine/rtc65271.c722
-rw-r--r--trunk/src/emu/machine/rtc65271.h33
-rw-r--r--trunk/src/emu/machine/s3c2400.c92
-rw-r--r--trunk/src/emu/machine/s3c2400.h727
-rw-r--r--trunk/src/emu/machine/s3c2410.c116
-rw-r--r--trunk/src/emu/machine/s3c2410.h863
-rw-r--r--trunk/src/emu/machine/s3c2440.c117
-rw-r--r--trunk/src/emu/machine/s3c2440.h933
-rw-r--r--trunk/src/emu/machine/s3c24xx.c3200
-rw-r--r--trunk/src/emu/machine/scsi.c159
-rw-r--r--trunk/src/emu/machine/scsi.h113
-rw-r--r--trunk/src/emu/machine/scsicd.c775
-rw-r--r--trunk/src/emu/machine/scsicd.h17
-rw-r--r--trunk/src/emu/machine/scsidev.c160
-rw-r--r--trunk/src/emu/machine/scsidev.h15
-rw-r--r--trunk/src/emu/machine/scsihd.c338
-rw-r--r--trunk/src/emu/machine/scsihd.h16
-rw-r--r--trunk/src/emu/machine/secflash.c74
-rw-r--r--trunk/src/emu/machine/secflash.h35
-rw-r--r--trunk/src/emu/machine/smc91c9x.c637
-rw-r--r--trunk/src/emu/machine/smc91c9x.h57
-rw-r--r--trunk/src/emu/machine/timekpr.c446
-rw-r--r--trunk/src/emu/machine/timekpr.h160
-rw-r--r--trunk/src/emu/machine/tmp68301.c189
-rw-r--r--trunk/src/emu/machine/tmp68301.h17
-rw-r--r--trunk/src/emu/machine/tms6100.c282
-rw-r--r--trunk/src/emu/machine/tms6100.h20
-rw-r--r--trunk/src/emu/machine/upd1990a.c526
-rw-r--r--trunk/src/emu/machine/upd1990a.h131
-rw-r--r--trunk/src/emu/machine/upd4701.c317
-rw-r--r--trunk/src/emu/machine/upd4701.h42
-rw-r--r--trunk/src/emu/machine/upd7201.c332
-rw-r--r--trunk/src/emu/machine/upd7201.h151
-rw-r--r--trunk/src/emu/machine/wd17xx.c2264
-rw-r--r--trunk/src/emu/machine/wd17xx.h198
-rw-r--r--trunk/src/emu/machine/wd33c93.c877
-rw-r--r--trunk/src/emu/machine/wd33c93.h27
-rw-r--r--trunk/src/emu/machine/x2212.c227
-rw-r--r--trunk/src/emu/machine/x2212.h94
-rw-r--r--trunk/src/emu/machine/x76f041.c416
-rw-r--r--trunk/src/emu/machine/x76f041.h116
-rw-r--r--trunk/src/emu/machine/x76f100.c328
-rw-r--r--trunk/src/emu/machine/x76f100.h87
-rw-r--r--trunk/src/emu/machine/z80ctc.c526
-rw-r--r--trunk/src/emu/machine/z80ctc.h168
-rw-r--r--trunk/src/emu/machine/z80dart.c1471
-rw-r--r--trunk/src/emu/machine/z80dart.h378
-rw-r--r--trunk/src/emu/machine/z80dma.c887
-rw-r--r--trunk/src/emu/machine/z80dma.h181
-rw-r--r--trunk/src/emu/machine/z80pio.c844
-rw-r--r--trunk/src/emu/machine/z80pio.h221
-rw-r--r--trunk/src/emu/machine/z80sio.c865
-rw-r--r--trunk/src/emu/machine/z80sio.h174
-rw-r--r--trunk/src/emu/machine/z80sti.c756
-rw-r--r--trunk/src/emu/machine/z80sti.h206
-rw-r--r--trunk/src/emu/machine/z8536.c596
-rw-r--r--trunk/src/emu/machine/z8536.h159
-rw-r--r--trunk/src/emu/mame.c439
-rw-r--r--trunk/src/emu/mame.h166
-rw-r--r--trunk/src/emu/mconfig.c224
-rw-r--r--trunk/src/emu/mconfig.h310
-rw-r--r--trunk/src/emu/memconv.h1020
-rw-r--r--trunk/src/emu/memory.c5868
-rw-r--r--trunk/src/emu/memory.h812
-rw-r--r--trunk/src/emu/output.c412
-rw-r--r--trunk/src/emu/output.h99
-rw-r--r--trunk/src/emu/profiler.c288
-rw-r--r--trunk/src/emu/profiler.h208
-rw-r--r--trunk/src/emu/render.c2885
-rw-r--r--trunk/src/emu/render.h799
-rw-r--r--trunk/src/emu/rendersw.c2397
-rw-r--r--trunk/src/emu/rendfont.c816
-rw-r--r--trunk/src/emu/rendfont.h125
-rw-r--r--trunk/src/emu/rendlay.c1984
-rw-r--r--trunk/src/emu/rendlay.h336
-rw-r--r--trunk/src/emu/rendutil.c770
-rw-r--r--trunk/src/emu/rendutil.h203
-rw-r--r--trunk/src/emu/romload.c1604
-rw-r--r--trunk/src/emu/romload.h328
-rw-r--r--trunk/src/emu/save.c484
-rw-r--r--trunk/src/emu/save.h293
-rw-r--r--trunk/src/emu/schedule.c991
-rw-r--r--trunk/src/emu/schedule.h243
-rw-r--r--trunk/src/emu/screen.c1096
-rw-r--r--trunk/src/emu/screen.h305
-rw-r--r--trunk/src/emu/softlist.c1858
-rw-r--r--trunk/src/emu/softlist.h172
-rw-r--r--trunk/src/emu/sound.c1067
-rw-r--r--trunk/src/emu/sound.h276
-rw-r--r--trunk/src/emu/sound/2151intf.c135
-rw-r--r--trunk/src/emu/sound/2151intf.h24
-rw-r--r--trunk/src/emu/sound/2203intf.c209
-rw-r--r--trunk/src/emu/sound/2203intf.h29
-rw-r--r--trunk/src/emu/sound/2413intf.c145
-rw-r--r--trunk/src/emu/sound/2413intf.h15
-rw-r--r--trunk/src/emu/sound/2608intf.c235
-rw-r--r--trunk/src/emu/sound/2608intf.h34
-rw-r--r--trunk/src/emu/sound/2610intf.c260
-rw-r--r--trunk/src/emu/sound/2610intf.h34
-rw-r--r--trunk/src/emu/sound/2612intf.c202
-rw-r--r--trunk/src/emu/sound/2612intf.h56
-rw-r--r--trunk/src/emu/sound/262intf.c161
-rw-r--r--trunk/src/emu/sound/262intf.h28
-rw-r--r--trunk/src/emu/sound/3526intf.c169
-rw-r--r--trunk/src/emu/sound/3526intf.h24
-rw-r--r--trunk/src/emu/sound/3812intf.c170
-rw-r--r--trunk/src/emu/sound/3812intf.h24
-rw-r--r--trunk/src/emu/sound/8950intf.c203
-rw-r--r--trunk/src/emu/sound/8950intf.h29
-rw-r--r--trunk/src/emu/sound/aica.c1367
-rw-r--r--trunk/src/emu/sound/aica.h31
-rw-r--r--trunk/src/emu/sound/aicadsp.c350
-rw-r--r--trunk/src/emu/sound/aicadsp.h40
-rw-r--r--trunk/src/emu/sound/aicalfo.c159
-rw-r--r--trunk/src/emu/sound/asc.c616
-rw-r--r--trunk/src/emu/sound/asc.h131
-rw-r--r--trunk/src/emu/sound/astrocde.c334
-rw-r--r--trunk/src/emu/sound/astrocde.h12
-rw-r--r--trunk/src/emu/sound/awacs.c175
-rw-r--r--trunk/src/emu/sound/awacs.h76
-rw-r--r--trunk/src/emu/sound/ay8910.c1097
-rw-r--r--trunk/src/emu/sound/ay8910.h110
-rw-r--r--trunk/src/emu/sound/beep.c192
-rw-r--r--trunk/src/emu/sound/beep.h16
-rw-r--r--trunk/src/emu/sound/bsmt2000.c391
-rw-r--r--trunk/src/emu/sound/bsmt2000.h146
-rw-r--r--trunk/src/emu/sound/c140.c528
-rw-r--r--trunk/src/emu/sound/c140.h30
-rw-r--r--trunk/src/emu/sound/c352.c527
-rw-r--r--trunk/src/emu/sound/c352.h112
-rw-r--r--trunk/src/emu/sound/c6280.c375
-rw-r--r--trunk/src/emu/sound/c6280.h20
-rw-r--r--trunk/src/emu/sound/cdda.c346
-rw-r--r--trunk/src/emu/sound/cdda.h24
-rw-r--r--trunk/src/emu/sound/cdp1863.c199
-rw-r--r--trunk/src/emu/sound/cdp1863.h90
-rw-r--r--trunk/src/emu/sound/cdp1864.c484
-rw-r--r--trunk/src/emu/sound/cdp1864.h218
-rw-r--r--trunk/src/emu/sound/cdp1869.c976
-rw-r--r--trunk/src/emu/sound/cdp1869.h313
-rw-r--r--trunk/src/emu/sound/cem3394.c589
-rw-r--r--trunk/src/emu/sound/cem3394.h50
-rw-r--r--trunk/src/emu/sound/dac.c159
-rw-r--r--trunk/src/emu/sound/dac.h18
-rw-r--r--trunk/src/emu/sound/digitalk.c708
-rw-r--r--trunk/src/emu/sound/digitalk.h14
-rw-r--r--trunk/src/emu/sound/disc_cls.h257
-rw-r--r--trunk/src/emu/sound/disc_dev.c1774
-rw-r--r--trunk/src/emu/sound/disc_dev.h127
-rw-r--r--trunk/src/emu/sound/disc_flt.c1436
-rw-r--r--trunk/src/emu/sound/disc_flt.h178
-rw-r--r--trunk/src/emu/sound/disc_inp.c341
-rw-r--r--trunk/src/emu/sound/disc_mth.c2771
-rw-r--r--trunk/src/emu/sound/disc_mth.h238
-rw-r--r--trunk/src/emu/sound/disc_sys.c123
-rw-r--r--trunk/src/emu/sound/disc_wav.c1786
-rw-r--r--trunk/src/emu/sound/disc_wav.h191
-rw-r--r--trunk/src/emu/sound/discrete.c1136
-rw-r--r--trunk/src/emu/sound/discrete.h4746
-rw-r--r--trunk/src/emu/sound/dmadac.c265
-rw-r--r--trunk/src/emu/sound/dmadac.h22
-rw-r--r--trunk/src/emu/sound/es5503.c530
-rw-r--r--trunk/src/emu/sound/es5503.h22
-rw-r--r--trunk/src/emu/sound/es5506.c2209
-rw-r--r--trunk/src/emu/sound/es5506.h48
-rw-r--r--trunk/src/emu/sound/es8712.c410
-rw-r--r--trunk/src/emu/sound/es8712.h18
-rw-r--r--trunk/src/emu/sound/filter.c232
-rw-r--r--trunk/src/emu/sound/filter.h120
-rw-r--r--trunk/src/emu/sound/flt_rc.c140
-rw-r--r--trunk/src/emu/sound/flt_rc.h64
-rw-r--r--trunk/src/emu/sound/flt_vol.c75
-rw-r--r--trunk/src/emu/sound/flt_vol.h13
-rw-r--r--trunk/src/emu/sound/fm.c4459
-rw-r--r--trunk/src/emu/sound/fm.h214
-rw-r--r--trunk/src/emu/sound/fm2612.c2557
-rw-r--r--trunk/src/emu/sound/fmopl.c2581
-rw-r--r--trunk/src/emu/sound/fmopl.h113
-rw-r--r--trunk/src/emu/sound/gaelco.c343
-rw-r--r--trunk/src/emu/sound/gaelco.h21
-rw-r--r--trunk/src/emu/sound/hc55516.c349
-rw-r--r--trunk/src/emu/sound/hc55516.h22
-rw-r--r--trunk/src/emu/sound/ics2115.c894
-rw-r--r--trunk/src/emu/sound/ics2115.h162
-rw-r--r--trunk/src/emu/sound/iremga20.c296
-rw-r--r--trunk/src/emu/sound/iremga20.h18
-rw-r--r--trunk/src/emu/sound/k005289.c277
-rw-r--r--trunk/src/emu/sound/k005289.h17
-rw-r--r--trunk/src/emu/sound/k007232.c476
-rw-r--r--trunk/src/emu/sound/k007232.h35
-rw-r--r--trunk/src/emu/sound/k051649.c247
-rw-r--r--trunk/src/emu/sound/k051649.h18
-rw-r--r--trunk/src/emu/sound/k053260.c466
-rw-r--r--trunk/src/emu/sound/k053260.h26
-rw-r--r--trunk/src/emu/sound/k054539.c708
-rw-r--r--trunk/src/emu/sound/k054539.h50
-rw-r--r--trunk/src/emu/sound/k056800.c177
-rw-r--r--trunk/src/emu/sound/k056800.h50
-rw-r--r--trunk/src/emu/sound/lmc1992.c233
-rw-r--r--trunk/src/emu/sound/lmc1992.h117
-rw-r--r--trunk/src/emu/sound/mas3507d.c261
-rw-r--r--trunk/src/emu/sound/mas3507d.h66
-rw-r--r--trunk/src/emu/sound/mos6560.c956
-rw-r--r--trunk/src/emu/sound/mos6560.h113
-rw-r--r--trunk/src/emu/sound/msm5205.c338
-rw-r--r--trunk/src/emu/sound/msm5205.h45
-rw-r--r--trunk/src/emu/sound/msm5232.c881
-rw-r--r--trunk/src/emu/sound/msm5232.h21
-rw-r--r--trunk/src/emu/sound/multipcm.c703
-rw-r--r--trunk/src/emu/sound/multipcm.h15
-rw-r--r--trunk/src/emu/sound/n63701x.c188
-rw-r--r--trunk/src/emu/sound/n63701x.h12
-rw-r--r--trunk/src/emu/sound/namco.c896
-rw-r--r--trunk/src/emu/sound/namco.h36
-rw-r--r--trunk/src/emu/sound/nes_apu.c795
-rw-r--r--trunk/src/emu/sound/nes_apu.h51
-rw-r--r--trunk/src/emu/sound/nes_defs.h208
-rw-r--r--trunk/src/emu/sound/nile.c261
-rw-r--r--trunk/src/emu/sound/nile.h15
-rw-r--r--trunk/src/emu/sound/okiadpcm.c190
-rw-r--r--trunk/src/emu/sound/okiadpcm.h62
-rw-r--r--trunk/src/emu/sound/okim6258.c384
-rw-r--r--trunk/src/emu/sound/okim6258.h39
-rw-r--r--trunk/src/emu/sound/okim6295.c502
-rw-r--r--trunk/src/emu/sound/okim6295.h148
-rw-r--r--trunk/src/emu/sound/okim6376.c649
-rw-r--r--trunk/src/emu/sound/okim6376.h23
-rw-r--r--trunk/src/emu/sound/okim9810.c556
-rw-r--r--trunk/src/emu/sound/okim9810.h162
-rw-r--r--trunk/src/emu/sound/pokey.c1417
-rw-r--r--trunk/src/emu/sound/pokey.h95
-rw-r--r--trunk/src/emu/sound/pokey.txt319
-rw-r--r--trunk/src/emu/sound/qsound.c402
-rw-r--r--trunk/src/emu/sound/qsound.h21
-rw-r--r--trunk/src/emu/sound/rf5c400.c586
-rw-r--r--trunk/src/emu/sound/rf5c400.h15
-rw-r--r--trunk/src/emu/sound/rf5c68.c289
-rw-r--r--trunk/src/emu/sound/rf5c68.h27
-rw-r--r--trunk/src/emu/sound/s14001a.c651
-rw-r--r--trunk/src/emu/sound/s14001a.h17
-rw-r--r--trunk/src/emu/sound/s2636.c102
-rw-r--r--trunk/src/emu/sound/s2636.h16
-rw-r--r--trunk/src/emu/sound/saa1099.c466
-rw-r--r--trunk/src/emu/sound/saa1099.h17
-rw-r--r--trunk/src/emu/sound/samples.c530
-rw-r--r--trunk/src/emu/sound/samples.h49
-rw-r--r--trunk/src/emu/sound/scsp.c1390
-rw-r--r--trunk/src/emu/sound/scsp.h34
-rw-r--r--trunk/src/emu/sound/scspdsp.c354
-rw-r--r--trunk/src/emu/sound/scspdsp.h40
-rw-r--r--trunk/src/emu/sound/scsplfo.c160
-rw-r--r--trunk/src/emu/sound/segapcm.c179
-rw-r--r--trunk/src/emu/sound/segapcm.h30
-rw-r--r--trunk/src/emu/sound/sid.c363
-rw-r--r--trunk/src/emu/sound/sid.h66
-rw-r--r--trunk/src/emu/sound/sid6581.c126
-rw-r--r--trunk/src/emu/sound/sid6581.h37
-rw-r--r--trunk/src/emu/sound/side6581.h126
-rw-r--r--trunk/src/emu/sound/sidenvel.c586
-rw-r--r--trunk/src/emu/sound/sidenvel.h37
-rw-r--r--trunk/src/emu/sound/sidvoice.c809
-rw-r--r--trunk/src/emu/sound/sidvoice.h118
-rw-r--r--trunk/src/emu/sound/sidw6581.h1051
-rw-r--r--trunk/src/emu/sound/sidw8580.h1397
-rw-r--r--trunk/src/emu/sound/sn76477.c2487
-rw-r--r--trunk/src/emu/sound/sn76477.h130
-rw-r--r--trunk/src/emu/sound/sn76496.c581
-rw-r--r--trunk/src/emu/sound/sn76496.h21
-rw-r--r--trunk/src/emu/sound/snkwave.c189
-rw-r--r--trunk/src/emu/sound/snkwave.h12
-rw-r--r--trunk/src/emu/sound/sound.mak720
-rw-r--r--trunk/src/emu/sound/sp0250.c269
-rw-r--r--trunk/src/emu/sound/sp0250.h17
-rw-r--r--trunk/src/emu/sound/sp0256.c1375
-rw-r--r--trunk/src/emu/sound/sp0256.h72
-rw-r--r--trunk/src/emu/sound/speaker.c447
-rw-r--r--trunk/src/emu/sound/speaker.h29
-rw-r--r--trunk/src/emu/sound/spu.c3129
-rw-r--r--trunk/src/emu/sound/spu.h254
-rw-r--r--trunk/src/emu/sound/spu_tables.c701
-rw-r--r--trunk/src/emu/sound/spureverb.c336
-rw-r--r--trunk/src/emu/sound/spureverb.h70
-rw-r--r--trunk/src/emu/sound/st0016.c176
-rw-r--r--trunk/src/emu/sound/st0016.h19
-rw-r--r--trunk/src/emu/sound/t6w28.c395
-rw-r--r--trunk/src/emu/sound/t6w28.h12
-rw-r--r--trunk/src/emu/sound/tiaintf.c79
-rw-r--r--trunk/src/emu/sound/tiaintf.h12
-rw-r--r--trunk/src/emu/sound/tiasound.c592
-rw-r--r--trunk/src/emu/sound/tiasound.h46
-rw-r--r--trunk/src/emu/sound/tms3615.c123
-rw-r--r--trunk/src/emu/sound/tms3615.h15
-rw-r--r--trunk/src/emu/sound/tms36xx.c555
-rw-r--r--trunk/src/emu/sound/tms36xx.h33
-rw-r--r--trunk/src/emu/sound/tms5110.c1561
-rw-r--r--trunk/src/emu/sound/tms5110.h97
-rw-r--r--trunk/src/emu/sound/tms5110r.c535
-rw-r--r--trunk/src/emu/sound/tms5220.c2041
-rw-r--r--trunk/src/emu/sound/tms5220.h50
-rw-r--r--trunk/src/emu/sound/tms5220.txt86
-rw-r--r--trunk/src/emu/sound/tms5220r.c107
-rw-r--r--trunk/src/emu/sound/upd7759.c770
-rw-r--r--trunk/src/emu/sound/upd7759.h30
-rw-r--r--trunk/src/emu/sound/vlm5030.c758
-rw-r--r--trunk/src/emu/sound/vlm5030.h30
-rw-r--r--trunk/src/emu/sound/votrax.c187
-rw-r--r--trunk/src/emu/sound/votrax.h13
-rw-r--r--trunk/src/emu/sound/vrender0.c270
-rw-r--r--trunk/src/emu/sound/vrender0.h22
-rw-r--r--trunk/src/emu/sound/wave.c110
-rw-r--r--trunk/src/emu/sound/wave.h22
-rw-r--r--trunk/src/emu/sound/wavwrite.c202
-rw-r--r--trunk/src/emu/sound/wavwrite.h16
-rw-r--r--trunk/src/emu/sound/x1_010.c314
-rw-r--r--trunk/src/emu/sound/x1_010.h26
-rw-r--r--trunk/src/emu/sound/ym2151.c2500
-rw-r--r--trunk/src/emu/sound/ym2151.h86
-rw-r--r--trunk/src/emu/sound/ym2151.txt162
-rw-r--r--trunk/src/emu/sound/ym2413.c2179
-rw-r--r--trunk/src/emu/sound/ym2413.h43
-rw-r--r--trunk/src/emu/sound/ymdeltat.c652
-rw-r--r--trunk/src/emu/sound/ymdeltat.h84
-rw-r--r--trunk/src/emu/sound/ymf262.c2715
-rw-r--r--trunk/src/emu/sound/ymf262.h48
-rw-r--r--trunk/src/emu/sound/ymf271.c1839
-rw-r--r--trunk/src/emu/sound/ymf271.h22
-rw-r--r--trunk/src/emu/sound/ymf278b.c1097
-rw-r--r--trunk/src/emu/sound/ymf278b.h22
-rw-r--r--trunk/src/emu/sound/ymz280b.c1076
-rw-r--r--trunk/src/emu/sound/ymz280b.h29
-rw-r--r--trunk/src/emu/sound/zsg2.c260
-rw-r--r--trunk/src/emu/sound/zsg2.h21
-rw-r--r--trunk/src/emu/speaker.c226
-rw-r--r--trunk/src/emu/speaker.h120
-rw-r--r--trunk/src/emu/tilemap.c2342
-rw-r--r--trunk/src/emu/tilemap.h618
-rw-r--r--trunk/src/emu/timer.c330
-rw-r--r--trunk/src/emu/timer.h188
-rw-r--r--trunk/src/emu/ui.c2252
-rw-r--r--trunk/src/emu/ui.h190
-rw-r--r--trunk/src/emu/uigfx.c1076
-rw-r--r--trunk/src/emu/uigfx.h30
-rw-r--r--trunk/src/emu/uiimage.c1553
-rw-r--r--trunk/src/emu/uiimage.h31
-rw-r--r--trunk/src/emu/uiinput.c289
-rw-r--r--trunk/src/emu/uiinput.h189
-rw-r--r--trunk/src/emu/uimenu.c3989
-rw-r--r--trunk/src/emu/uimenu.h154
-rw-r--r--trunk/src/emu/uismall.pngbin0 -> 1488 bytes
-rw-r--r--trunk/src/emu/uiswlist.c491
-rw-r--r--trunk/src/emu/uiswlist.h22
-rw-r--r--trunk/src/emu/validity.c1318
-rw-r--r--trunk/src/emu/validity.h20
-rw-r--r--trunk/src/emu/video.c1330
-rw-r--r--trunk/src/emu/video.h210
-rw-r--r--trunk/src/emu/video/cdp1861.c264
-rw-r--r--trunk/src/emu/video/cdp1861.h156
-rw-r--r--trunk/src/emu/video/cdp1862.c220
-rw-r--r--trunk/src/emu/video/cdp1862.h125
-rw-r--r--trunk/src/emu/video/crt9007.c978
-rw-r--r--trunk/src/emu/video/crt9007.h208
-rw-r--r--trunk/src/emu/video/crt9021.c227
-rw-r--r--trunk/src/emu/video/crt9021.h120
-rw-r--r--trunk/src/emu/video/crt9212.c226
-rw-r--r--trunk/src/emu/video/crt9212.h124
-rw-r--r--trunk/src/emu/video/dm9368.c165
-rw-r--r--trunk/src/emu/video/dm9368.h96
-rw-r--r--trunk/src/emu/video/generic.c1092
-rw-r--r--trunk/src/emu/video/generic.h162
-rw-r--r--trunk/src/emu/video/hd44102.c298
-rw-r--r--trunk/src/emu/video/hd44102.h88
-rw-r--r--trunk/src/emu/video/hd61830.c562
-rw-r--r--trunk/src/emu/video/hd61830.h129
-rw-r--r--trunk/src/emu/video/hd63484.c1588
-rw-r--r--trunk/src/emu/video/hd63484.h52
-rw-r--r--trunk/src/emu/video/i8275.c616
-rw-r--r--trunk/src/emu/video/i8275.h66
-rw-r--r--trunk/src/emu/video/k053250.c469
-rw-r--r--trunk/src/emu/video/k053250.h57
-rw-r--r--trunk/src/emu/video/mc6845.c1088
-rw-r--r--trunk/src/emu/video/mc6845.h374
-rw-r--r--trunk/src/emu/video/msm6255.c437
-rw-r--r--trunk/src/emu/video/msm6255.h109
-rw-r--r--trunk/src/emu/video/pc_vga.c1276
-rw-r--r--trunk/src/emu/video/pc_vga.h99
-rw-r--r--trunk/src/emu/video/poly.c1394
-rw-r--r--trunk/src/emu/video/poly.h156
-rw-r--r--trunk/src/emu/video/psx.c3730
-rw-r--r--trunk/src/emu/video/psx.h342
-rw-r--r--trunk/src/emu/video/resnet.c725
-rw-r--r--trunk/src/emu/video/resnet.h202
-rw-r--r--trunk/src/emu/video/rgbgen.h450
-rw-r--r--trunk/src/emu/video/rgbsse.h394
-rw-r--r--trunk/src/emu/video/rgbutil.c302
-rw-r--r--trunk/src/emu/video/rgbutil.h25
-rw-r--r--trunk/src/emu/video/rgbvmx.h414
-rw-r--r--trunk/src/emu/video/s2636.c382
-rw-r--r--trunk/src/emu/video/s2636.h61
-rw-r--r--trunk/src/emu/video/saa5050.c388
-rw-r--r--trunk/src/emu/video/saa5050.h54
-rw-r--r--trunk/src/emu/video/sed1330.c702
-rw-r--r--trunk/src/emu/video/sed1330.h131
-rw-r--r--trunk/src/emu/video/tlc34076.c288
-rw-r--r--trunk/src/emu/video/tlc34076.h43
-rw-r--r--trunk/src/emu/video/tms34061.c553
-rw-r--r--trunk/src/emu/video/tms34061.h75
-rw-r--r--trunk/src/emu/video/tms9927.c367
-rw-r--r--trunk/src/emu/video/tms9927.h56
-rw-r--r--trunk/src/emu/video/tms9928a.c658
-rw-r--r--trunk/src/emu/video/tms9928a.h215
-rw-r--r--trunk/src/emu/video/upd3301.c653
-rw-r--r--trunk/src/emu/video/upd3301.h198
-rw-r--r--trunk/src/emu/video/v9938.c2625
-rw-r--r--trunk/src/emu/video/v9938.h39
-rw-r--r--trunk/src/emu/video/v9938mod.c736
-rw-r--r--trunk/src/emu/video/vector.c314
-rw-r--r--trunk/src/emu/video/vector.h27
-rw-r--r--trunk/src/emu/video/vooddefs.h3684
-rw-r--r--trunk/src/emu/video/voodoo.c5870
-rw-r--r--trunk/src/emu/video/voodoo.h156
-rw-r--r--trunk/src/emu/watchdog.c150
-rw-r--r--trunk/src/emu/watchdog.h32
-rw-r--r--trunk/src/ldplayer/layout/pr8210.lay121
-rw-r--r--trunk/src/ldplayer/ldplayer.c673
-rw-r--r--trunk/src/ldplayer/ldplayer.lst42
-rw-r--r--trunk/src/ldplayer/ldplayer.mak55
-rw-r--r--trunk/src/lib/cothread/amd64.c104
-rw-r--r--trunk/src/lib/cothread/doc/amd64.asm85
-rw-r--r--trunk/src/lib/cothread/doc/style.css8
-rw-r--r--trunk/src/lib/cothread/doc/targets.html89
-rw-r--r--trunk/src/lib/cothread/doc/usage.html107
-rw-r--r--trunk/src/lib/cothread/doc/x86.asm21
-rw-r--r--trunk/src/lib/cothread/fiber.c51
-rw-r--r--trunk/src/lib/cothread/libco.c23
-rw-r--r--trunk/src/lib/cothread/libco.h34
-rw-r--r--trunk/src/lib/cothread/ppc.c411
-rw-r--r--trunk/src/lib/cothread/sjlj.c102
-rw-r--r--trunk/src/lib/cothread/test/cc.bat4
-rw-r--r--trunk/src/lib/cothread/test/cc.sh5
-rw-r--r--trunk/src/lib/cothread/test/test.h6
-rw-r--r--trunk/src/lib/cothread/test/test_args.cpp76
-rw-r--r--trunk/src/lib/cothread/test/test_timing.cpp52
-rw-r--r--trunk/src/lib/cothread/ucontext.c67
-rw-r--r--trunk/src/lib/cothread/x86.c93
-rw-r--r--trunk/src/lib/expat/ascii.h92
-rw-r--r--trunk/src/lib/expat/asciitab.h36
-rw-r--r--trunk/src/lib/expat/expat.h1014
-rw-r--r--trunk/src/lib/expat/expat_external.h115
-rw-r--r--trunk/src/lib/expat/iasciitab.h37
-rw-r--r--trunk/src/lib/expat/intconfig.h19
-rw-r--r--trunk/src/lib/expat/internal.h73
-rw-r--r--trunk/src/lib/expat/latin1tab.h36
-rw-r--r--trunk/src/lib/expat/nametab.h150
-rw-r--r--trunk/src/lib/expat/utf8tab.h37
-rw-r--r--trunk/src/lib/expat/xmlparse.c6277
-rw-r--r--trunk/src/lib/expat/xmlrole.c1324
-rw-r--r--trunk/src/lib/expat/xmlrole.h114
-rw-r--r--trunk/src/lib/expat/xmltok.c1639
-rw-r--r--trunk/src/lib/expat/xmltok.h316
-rw-r--r--trunk/src/lib/expat/xmltok_impl.c1783
-rw-r--r--trunk/src/lib/expat/xmltok_impl.h46
-rw-r--r--trunk/src/lib/expat/xmltok_ns.c115
-rw-r--r--trunk/src/lib/formats/a26_cas.c166
-rw-r--r--trunk/src/lib/formats/a26_cas.h14
-rw-r--r--trunk/src/lib/formats/ace_tap.c188
-rw-r--r--trunk/src/lib/formats/ace_tap.h29
-rw-r--r--trunk/src/lib/formats/ami_dsk.c75
-rw-r--r--trunk/src/lib/formats/ami_dsk.h27
-rw-r--r--trunk/src/lib/formats/ap2_dsk.c511
-rw-r--r--trunk/src/lib/formats/ap2_dsk.h33
-rw-r--r--trunk/src/lib/formats/ap_dsk35.c1187
-rw-r--r--trunk/src/lib/formats/ap_dsk35.h25
-rw-r--r--trunk/src/lib/formats/apf_apt.c157
-rw-r--r--trunk/src/lib/formats/apf_apt.h9
-rw-r--r--trunk/src/lib/formats/apridisk.c226
-rw-r--r--trunk/src/lib/formats/apridisk.h15
-rw-r--r--trunk/src/lib/formats/atari_dsk.c33
-rw-r--r--trunk/src/lib/formats/atari_dsk.h16
-rw-r--r--trunk/src/lib/formats/atarist_dsk.c82
-rw-r--r--trunk/src/lib/formats/atarist_dsk.h18
-rw-r--r--trunk/src/lib/formats/atom_tap.c143
-rw-r--r--trunk/src/lib/formats/atom_tap.h18
-rw-r--r--trunk/src/lib/formats/basicdsk.c352
-rw-r--r--trunk/src/lib/formats/basicdsk.h35
-rw-r--r--trunk/src/lib/formats/cassimg.c1057
-rw-r--r--trunk/src/lib/formats/cassimg.h230
-rw-r--r--trunk/src/lib/formats/cbm_tap.c369
-rw-r--r--trunk/src/lib/formats/cbm_tap.h16
-rw-r--r--trunk/src/lib/formats/cgen_cas.c149
-rw-r--r--trunk/src/lib/formats/cgen_cas.h17
-rw-r--r--trunk/src/lib/formats/coco_cas.c313
-rw-r--r--trunk/src/lib/formats/coco_cas.h20
-rw-r--r--trunk/src/lib/formats/coco_dsk.c1198
-rw-r--r--trunk/src/lib/formats/coco_dsk.h22
-rw-r--r--trunk/src/lib/formats/comx35_dsk.c78
-rw-r--r--trunk/src/lib/formats/comx35_dsk.h18
-rw-r--r--trunk/src/lib/formats/coupedsk.c488
-rw-r--r--trunk/src/lib/formats/coupedsk.h23
-rw-r--r--trunk/src/lib/formats/cpis_dsk.c93
-rw-r--r--trunk/src/lib/formats/cpis_dsk.h19
-rw-r--r--trunk/src/lib/formats/cqm_dsk.c228
-rw-r--r--trunk/src/lib/formats/csw_cas.c329
-rw-r--r--trunk/src/lib/formats/csw_cas.h15
-rw-r--r--trunk/src/lib/formats/d64_dsk.c856
-rw-r--r--trunk/src/lib/formats/d64_dsk.h26
-rw-r--r--trunk/src/lib/formats/d81_dsk.c131
-rw-r--r--trunk/src/lib/formats/d81_dsk.h21
-rw-r--r--trunk/src/lib/formats/d88_dsk.c378
-rw-r--r--trunk/src/lib/formats/dim_dsk.c101
-rw-r--r--trunk/src/lib/formats/dim_dsk.h19
-rw-r--r--trunk/src/lib/formats/dsk_dsk.c257
-rw-r--r--trunk/src/lib/formats/fdi_dsk.c288
-rw-r--r--trunk/src/lib/formats/flopimg.c1305
-rw-r--r--trunk/src/lib/formats/flopimg.h391
-rw-r--r--trunk/src/lib/formats/fm7_cas.c108
-rw-r--r--trunk/src/lib/formats/fm7_cas.h12
-rw-r--r--trunk/src/lib/formats/fmsx_cas.c142
-rw-r--r--trunk/src/lib/formats/fmsx_cas.h16
-rw-r--r--trunk/src/lib/formats/g64_dsk.c296
-rw-r--r--trunk/src/lib/formats/g64_dsk.h45
-rw-r--r--trunk/src/lib/formats/gtp_cas.c200
-rw-r--r--trunk/src/lib/formats/gtp_cas.h15
-rw-r--r--trunk/src/lib/formats/hect_dsk.c96
-rw-r--r--trunk/src/lib/formats/hect_dsk.h19
-rw-r--r--trunk/src/lib/formats/hect_tap.c305
-rw-r--r--trunk/src/lib/formats/hect_tap.h17
-rw-r--r--trunk/src/lib/formats/hxcmfm_dsk.c70
-rw-r--r--trunk/src/lib/formats/hxcmfm_dsk.h25
-rw-r--r--trunk/src/lib/formats/imageutl.c223
-rw-r--r--trunk/src/lib/formats/imageutl.h207
-rw-r--r--trunk/src/lib/formats/imd_dsk.c275
-rw-r--r--trunk/src/lib/formats/ioprocs.c166
-rw-r--r--trunk/src/lib/formats/ioprocs.h68
-rw-r--r--trunk/src/lib/formats/kim1_cas.c194
-rw-r--r--trunk/src/lib/formats/kim1_cas.h17
-rw-r--r--trunk/src/lib/formats/lviv_lvt.c149
-rw-r--r--trunk/src/lib/formats/lviv_lvt.h16
-rw-r--r--trunk/src/lib/formats/msx_dsk.c25
-rw-r--r--trunk/src/lib/formats/msx_dsk.h18
-rw-r--r--trunk/src/lib/formats/mz_cas.c340
-rw-r--r--trunk/src/lib/formats/mz_cas.h16
-rw-r--r--trunk/src/lib/formats/nes_dsk.c72
-rw-r--r--trunk/src/lib/formats/nes_dsk.h16
-rw-r--r--trunk/src/lib/formats/orao_cas.c120
-rw-r--r--trunk/src/lib/formats/orao_cas.h15
-rw-r--r--trunk/src/lib/formats/oric_dsk.c316
-rw-r--r--trunk/src/lib/formats/oric_dsk.h18
-rw-r--r--trunk/src/lib/formats/oric_tap.c519
-rw-r--r--trunk/src/lib/formats/oric_tap.h16
-rw-r--r--trunk/src/lib/formats/p6001_cas.c93
-rw-r--r--trunk/src/lib/formats/p6001_cas.h12
-rw-r--r--trunk/src/lib/formats/pc_dsk.c137
-rw-r--r--trunk/src/lib/formats/pc_dsk.h19
-rw-r--r--trunk/src/lib/formats/pmd_pmd.c119
-rw-r--r--trunk/src/lib/formats/pmd_pmd.h16
-rw-r--r--trunk/src/lib/formats/primoptp.c247
-rw-r--r--trunk/src/lib/formats/primoptp.h16
-rw-r--r--trunk/src/lib/formats/rk_cas.c310
-rw-r--r--trunk/src/lib/formats/rk_cas.h24
-rw-r--r--trunk/src/lib/formats/smx_dsk.c159
-rw-r--r--trunk/src/lib/formats/smx_dsk.h18
-rw-r--r--trunk/src/lib/formats/sorc_dsk.c157
-rw-r--r--trunk/src/lib/formats/sorc_dsk.h18
-rw-r--r--trunk/src/lib/formats/sord_cas.c138
-rw-r--r--trunk/src/lib/formats/sord_cas.h16
-rw-r--r--trunk/src/lib/formats/st_dsk.c605
-rw-r--r--trunk/src/lib/formats/st_dsk.h47
-rw-r--r--trunk/src/lib/formats/svi_cas.c209
-rw-r--r--trunk/src/lib/formats/svi_cas.h17
-rw-r--r--trunk/src/lib/formats/svi_dsk.c171
-rw-r--r--trunk/src/lib/formats/svi_dsk.h18
-rw-r--r--trunk/src/lib/formats/td0_dsk.c766
-rw-r--r--trunk/src/lib/formats/thom_cas.c787
-rw-r--r--trunk/src/lib/formats/thom_cas.h22
-rw-r--r--trunk/src/lib/formats/thom_dsk.c391
-rw-r--r--trunk/src/lib/formats/thom_dsk.h14
-rw-r--r--trunk/src/lib/formats/ti99_dsk.c2036
-rw-r--r--trunk/src/lib/formats/ti99_dsk.h19
-rw-r--r--trunk/src/lib/formats/trd_dsk.c50
-rw-r--r--trunk/src/lib/formats/trd_dsk.h18
-rw-r--r--trunk/src/lib/formats/trs_cas.c134
-rw-r--r--trunk/src/lib/formats/trs_cas.h17
-rw-r--r--trunk/src/lib/formats/trs_dsk.c77
-rw-r--r--trunk/src/lib/formats/trs_dsk.h18
-rw-r--r--trunk/src/lib/formats/tzx_cas.c679
-rw-r--r--trunk/src/lib/formats/tzx_cas.h16
-rw-r--r--trunk/src/lib/formats/uef_cas.c333
-rw-r--r--trunk/src/lib/formats/uef_cas.h16
-rw-r--r--trunk/src/lib/formats/vg5k_cas.c234
-rw-r--r--trunk/src/lib/formats/vg5k_cas.h15
-rw-r--r--trunk/src/lib/formats/vt_cas.c222
-rw-r--r--trunk/src/lib/formats/vt_cas.h17
-rw-r--r--trunk/src/lib/formats/vt_dsk.c54
-rw-r--r--trunk/src/lib/formats/vt_dsk.h16
-rw-r--r--trunk/src/lib/formats/vtech1_dsk.c33
-rw-r--r--trunk/src/lib/formats/vtech1_dsk.h16
-rw-r--r--trunk/src/lib/formats/wavfile.c291
-rw-r--r--trunk/src/lib/formats/wavfile.h16
-rw-r--r--trunk/src/lib/formats/x1_tap.c127
-rw-r--r--trunk/src/lib/formats/x1_tap.h14
-rw-r--r--trunk/src/lib/formats/z80ne_dsk.c848
-rw-r--r--trunk/src/lib/formats/z80ne_dsk.h22
-rw-r--r--trunk/src/lib/formats/zx81_p.c293
-rw-r--r--trunk/src/lib/formats/zx81_p.h17
-rw-r--r--trunk/src/lib/lib.mak218
-rw-r--r--trunk/src/lib/softfloat/README.txt78
-rwxr-xr-xtrunk/src/lib/softfloat/fpu_constant.h80
-rwxr-xr-xtrunk/src/lib/softfloat/fsincos.c569
-rw-r--r--trunk/src/lib/softfloat/mamesf.h66
-rw-r--r--trunk/src/lib/softfloat/milieu.h42
-rw-r--r--trunk/src/lib/softfloat/softfloat-macros732
-rw-r--r--trunk/src/lib/softfloat/softfloat-specialize470
-rw-r--r--trunk/src/lib/softfloat/softfloat.c4960
-rw-r--r--trunk/src/lib/softfloat/softfloat.h456
-rw-r--r--trunk/src/lib/util/astring.c804
-rw-r--r--trunk/src/lib/util/astring.h415
-rw-r--r--trunk/src/lib/util/avcomp.c879
-rw-r--r--trunk/src/lib/util/avcomp.h123
-rw-r--r--trunk/src/lib/util/aviio.c2901
-rw-r--r--trunk/src/lib/util/aviio.h153
-rw-r--r--trunk/src/lib/util/bitmap.c506
-rw-r--r--trunk/src/lib/util/bitmap.h227
-rw-r--r--trunk/src/lib/util/cdrom.c899
-rw-r--r--trunk/src/lib/util/cdrom.h201
-rw-r--r--trunk/src/lib/util/chd.c3089
-rw-r--r--trunk/src/lib/util/chd.h390
-rw-r--r--trunk/src/lib/util/chdcd.c1020
-rw-r--r--trunk/src/lib/util/chdcd.h30
-rw-r--r--trunk/src/lib/util/corefile.c1051
-rw-r--r--trunk/src/lib/util/corefile.h158
-rw-r--r--trunk/src/lib/util/corestr.c178
-rw-r--r--trunk/src/lib/util/corestr.h93
-rw-r--r--trunk/src/lib/util/coreutil.c125
-rw-r--r--trunk/src/lib/util/coreutil.h72
-rw-r--r--trunk/src/lib/util/harddisk.c201
-rw-r--r--trunk/src/lib/util/harddisk.h79
-rw-r--r--trunk/src/lib/util/huffman.c1695
-rw-r--r--trunk/src/lib/util/huffman.h101
-rw-r--r--trunk/src/lib/util/jedparse.c463
-rw-r--r--trunk/src/lib/util/jedparse.h117
-rw-r--r--trunk/src/lib/util/md5.c239
-rw-r--r--trunk/src/lib/util/md5.h42
-rw-r--r--trunk/src/lib/util/opresolv.c565
-rw-r--r--trunk/src/lib/util/opresolv.h160
-rw-r--r--trunk/src/lib/util/options.c799
-rw-r--r--trunk/src/lib/util/options.h206
-rw-r--r--trunk/src/lib/util/palette.c789
-rw-r--r--trunk/src/lib/util/palette.h299
-rw-r--r--trunk/src/lib/util/png.c1174
-rw-r--r--trunk/src/lib/util/png.h165
-rw-r--r--trunk/src/lib/util/pool.c645
-rw-r--r--trunk/src/lib/util/pool.h145
-rw-r--r--trunk/src/lib/util/sha1.c387
-rw-r--r--trunk/src/lib/util/sha1.h61
-rw-r--r--trunk/src/lib/util/tagmap.c218
-rw-r--r--trunk/src/lib/util/tagmap.h224
-rw-r--r--trunk/src/lib/util/unicode.c374
-rw-r--r--trunk/src/lib/util/unicode.h138
-rw-r--r--trunk/src/lib/util/unzip.c645
-rw-r--r--trunk/src/lib/util/unzip.h171
-rw-r--r--trunk/src/lib/util/vbiparse.c406
-rw-r--r--trunk/src/lib/util/vbiparse.h122
-rw-r--r--trunk/src/lib/util/xmlfile.c940
-rw-r--r--trunk/src/lib/util/xmlfile.h201
-rw-r--r--trunk/src/lib/util/zippath.c859
-rw-r--r--trunk/src/lib/util/zippath.h66
-rw-r--r--trunk/src/lib/zlib/Makefile154
-rw-r--r--trunk/src/lib/zlib/Makefile.in154
-rw-r--r--trunk/src/lib/zlib/adler32.c149
-rw-r--r--trunk/src/lib/zlib/compress.c79
-rw-r--r--trunk/src/lib/zlib/crc32.c423
-rw-r--r--trunk/src/lib/zlib/crc32.h441
-rw-r--r--trunk/src/lib/zlib/deflate.c1736
-rw-r--r--trunk/src/lib/zlib/deflate.h331
-rw-r--r--trunk/src/lib/zlib/example.c565
-rw-r--r--trunk/src/lib/zlib/gzio.c1026
-rw-r--r--trunk/src/lib/zlib/infback.c623
-rw-r--r--trunk/src/lib/zlib/inffast.c318
-rw-r--r--trunk/src/lib/zlib/inffast.h11
-rw-r--r--trunk/src/lib/zlib/inffixed.h94
-rw-r--r--trunk/src/lib/zlib/inflate.c1368
-rw-r--r--trunk/src/lib/zlib/inflate.h115
-rw-r--r--trunk/src/lib/zlib/inftrees.c329
-rw-r--r--trunk/src/lib/zlib/inftrees.h55
-rw-r--r--trunk/src/lib/zlib/minigzip.c322
-rw-r--r--trunk/src/lib/zlib/readme125
-rw-r--r--trunk/src/lib/zlib/trees.c1219
-rw-r--r--trunk/src/lib/zlib/trees.h128
-rw-r--r--trunk/src/lib/zlib/uncompr.c61
-rw-r--r--trunk/src/lib/zlib/zconf.h332
-rw-r--r--trunk/src/lib/zlib/zconf.in.h332
-rw-r--r--trunk/src/lib/zlib/zlib.h1357
-rw-r--r--trunk/src/lib/zlib/zutil.c318
-rw-r--r--trunk/src/lib/zlib/zutil.h269
-rw-r--r--trunk/src/mame/audio/8080bw.c1169
-rw-r--r--trunk/src/mame/audio/amiga.c298
-rw-r--r--trunk/src/mame/audio/asteroid.c323
-rw-r--r--trunk/src/mame/audio/astrof.c242
-rw-r--r--trunk/src/mame/audio/atarifb.c208
-rw-r--r--trunk/src/mame/audio/atarijsa.c978
-rw-r--r--trunk/src/mame/audio/atarijsa.h25
-rw-r--r--trunk/src/mame/audio/avalnche.c135
-rw-r--r--trunk/src/mame/audio/aztarac.c58
-rw-r--r--trunk/src/mame/audio/beezer.c576
-rw-r--r--trunk/src/mame/audio/blockade.c70
-rw-r--r--trunk/src/mame/audio/bsktball.c135
-rw-r--r--trunk/src/mame/audio/bzone.c411
-rw-r--r--trunk/src/mame/audio/cage.c727
-rw-r--r--trunk/src/mame/audio/cage.h21
-rw-r--r--trunk/src/mame/audio/canyon.c212
-rw-r--r--trunk/src/mame/audio/carnival.c312
-rw-r--r--trunk/src/mame/audio/cchasm.c145
-rw-r--r--trunk/src/mame/audio/cclimber.c96
-rw-r--r--trunk/src/mame/audio/cclimber.h8
-rw-r--r--trunk/src/mame/audio/cinemat.c1635
-rw-r--r--trunk/src/mame/audio/circus.c279
-rw-r--r--trunk/src/mame/audio/cliffhgr.c52
-rw-r--r--trunk/src/mame/audio/copsnrob.c744
-rw-r--r--trunk/src/mame/audio/cps3.c190
-rw-r--r--trunk/src/mame/audio/crbaloon.c181
-rw-r--r--trunk/src/mame/audio/cyberbal.c165
-rw-r--r--trunk/src/mame/audio/dcs.c2427
-rw-r--r--trunk/src/mame/audio/dcs.h34
-rw-r--r--trunk/src/mame/audio/depthch.c94
-rw-r--r--trunk/src/mame/audio/dkong.c1490
-rw-r--r--trunk/src/mame/audio/dragrace.c193
-rw-r--r--trunk/src/mame/audio/exidy.c1136
-rw-r--r--trunk/src/mame/audio/exidy.h16
-rw-r--r--trunk/src/mame/audio/exidy440.c1020
-rw-r--r--trunk/src/mame/audio/exidy440.h4
-rw-r--r--trunk/src/mame/audio/firetrk.c691
-rw-r--r--trunk/src/mame/audio/flower.c377
-rw-r--r--trunk/src/mame/audio/galaga.c366
-rw-r--r--trunk/src/mame/audio/galaxian.c500
-rw-r--r--trunk/src/mame/audio/galaxian.h13
-rw-r--r--trunk/src/mame/audio/geebee.c163
-rw-r--r--trunk/src/mame/audio/gomoku.c297
-rw-r--r--trunk/src/mame/audio/gorf.c182
-rw-r--r--trunk/src/mame/audio/gottlieb.c622
-rw-r--r--trunk/src/mame/audio/gotya.c74
-rw-r--r--trunk/src/mame/audio/grchamp.c62
-rw-r--r--trunk/src/mame/audio/gridlee.c200
-rw-r--r--trunk/src/mame/audio/harddriv.c384
-rw-r--r--trunk/src/mame/audio/hitme.c80
-rw-r--r--trunk/src/mame/audio/hyprolyb.c151
-rw-r--r--trunk/src/mame/audio/hyprolyb.h6
-rw-r--r--trunk/src/mame/audio/invinco.c114
-rw-r--r--trunk/src/mame/audio/irem.c502
-rw-r--r--trunk/src/mame/audio/irem.h7
-rw-r--r--trunk/src/mame/audio/jaguar.c448
-rw-r--r--trunk/src/mame/audio/jedi.c230
-rw-r--r--trunk/src/mame/audio/laserbat.c106
-rw-r--r--trunk/src/mame/audio/leland.c2258
-rw-r--r--trunk/src/mame/audio/llander.c96
-rw-r--r--trunk/src/mame/audio/m72.c274
-rw-r--r--trunk/src/mame/audio/m72.h21
-rw-r--r--trunk/src/mame/audio/m79amb.c343
-rw-r--r--trunk/src/mame/audio/madalien.c259
-rw-r--r--trunk/src/mame/audio/mario.c669
-rw-r--r--trunk/src/mame/audio/mcr.c998
-rw-r--r--trunk/src/mame/audio/mcr.h71
-rw-r--r--trunk/src/mame/audio/meadows.c120
-rw-r--r--trunk/src/mame/audio/micro3d.c427
-rw-r--r--trunk/src/mame/audio/mw8080bw.c4769
-rw-r--r--trunk/src/mame/audio/n8080.c642
-rw-r--r--trunk/src/mame/audio/namco52.c241
-rw-r--r--trunk/src/mame/audio/namco52.h35
-rw-r--r--trunk/src/mame/audio/namco54.c197
-rw-r--r--trunk/src/mame/audio/namco54.h35
-rw-r--r--trunk/src/mame/audio/nitedrvr.c146
-rw-r--r--trunk/src/mame/audio/norautp.c98
-rw-r--r--trunk/src/mame/audio/orbit.c130
-rw-r--r--trunk/src/mame/audio/phoenix.c591
-rw-r--r--trunk/src/mame/audio/pleiads.c736
-rw-r--r--trunk/src/mame/audio/pleiads.h7
-rw-r--r--trunk/src/mame/audio/polepos.c372
-rw-r--r--trunk/src/mame/audio/polyplay.c77
-rw-r--r--trunk/src/mame/audio/poolshrk.c176
-rw-r--r--trunk/src/mame/audio/pulsar.c191
-rw-r--r--trunk/src/mame/audio/qix.c271
-rw-r--r--trunk/src/mame/audio/redalert.c423
-rw-r--r--trunk/src/mame/audio/redbaron.c247
-rw-r--r--trunk/src/mame/audio/scramble.c364
-rw-r--r--trunk/src/mame/audio/segag80r.c1016
-rw-r--r--trunk/src/mame/audio/segag80v.c333
-rw-r--r--trunk/src/mame/audio/segasnd.c1034
-rw-r--r--trunk/src/mame/audio/segasnd.h20
-rw-r--r--trunk/src/mame/audio/seibu.c626
-rw-r--r--trunk/src/mame/audio/seibu.h195
-rw-r--r--trunk/src/mame/audio/senjyo.c94
-rw-r--r--trunk/src/mame/audio/skydiver.c146
-rw-r--r--trunk/src/mame/audio/skyraid.c301
-rw-r--r--trunk/src/mame/audio/snes_snd.c1367
-rw-r--r--trunk/src/mame/audio/snes_snd.h36
-rw-r--r--trunk/src/mame/audio/snk6502.c1269
-rw-r--r--trunk/src/mame/audio/spacefb.c97
-rw-r--r--trunk/src/mame/audio/spiders.c210
-rw-r--r--trunk/src/mame/audio/sprint2.c403
-rw-r--r--trunk/src/mame/audio/sprint4.c302
-rw-r--r--trunk/src/mame/audio/sprint4.h31
-rw-r--r--trunk/src/mame/audio/sprint8.c314
-rw-r--r--trunk/src/mame/audio/starshp1.c296
-rw-r--r--trunk/src/mame/audio/starwars.c152
-rw-r--r--trunk/src/mame/audio/subs.c147
-rw-r--r--trunk/src/mame/audio/suna8.c60
-rw-r--r--trunk/src/mame/audio/t5182.c325
-rw-r--r--trunk/src/mame/audio/t5182.h19
-rw-r--r--trunk/src/mame/audio/taito_en.c296
-rw-r--r--trunk/src/mame/audio/taito_en.h6
-rw-r--r--trunk/src/mame/audio/taito_zm.c64
-rw-r--r--trunk/src/mame/audio/taito_zm.h1
-rw-r--r--trunk/src/mame/audio/taitosnd.c332
-rw-r--r--trunk/src/mame/audio/taitosnd.h44
-rw-r--r--trunk/src/mame/audio/tank8.c267
-rw-r--r--trunk/src/mame/audio/targ.c223
-rw-r--r--trunk/src/mame/audio/tiamc1.c351
-rw-r--r--trunk/src/mame/audio/timeplt.c274
-rw-r--r--trunk/src/mame/audio/timeplt.h6
-rw-r--r--trunk/src/mame/audio/trackfld.c189
-rw-r--r--trunk/src/mame/audio/trackfld.h10
-rw-r--r--trunk/src/mame/audio/triplhnt.c185
-rw-r--r--trunk/src/mame/audio/turbo.c746
-rw-r--r--trunk/src/mame/audio/tx1.c612
-rw-r--r--trunk/src/mame/audio/vicdual.c589
-rw-r--r--trunk/src/mame/audio/videopin.c99
-rw-r--r--trunk/src/mame/audio/warpwarp.c261
-rw-r--r--trunk/src/mame/audio/williams.c754
-rw-r--r--trunk/src/mame/audio/williams.h23
-rw-r--r--trunk/src/mame/audio/wiping.c281
-rw-r--r--trunk/src/mame/audio/wiping.h3
-rw-r--r--trunk/src/mame/audio/wow.c176
-rw-r--r--trunk/src/mame/audio/zaxxon.c262
-rw-r--r--trunk/src/mame/drivers/1942.c518
-rw-r--r--trunk/src/mame/drivers/1943.c615
-rw-r--r--trunk/src/mame/drivers/1945kiii.c304
-rw-r--r--trunk/src/mame/drivers/20pacgal.c474
-rw-r--r--trunk/src/mame/drivers/2mindril.c556
-rw-r--r--trunk/src/mame/drivers/39in1.c1658
-rw-r--r--trunk/src/mame/drivers/3do.c252
-rw-r--r--trunk/src/mame/drivers/40love.c1306
-rw-r--r--trunk/src/mame/drivers/4enraya.c300
-rw-r--r--trunk/src/mame/drivers/4roses.c475
-rw-r--r--trunk/src/mame/drivers/5clown.c1265
-rw-r--r--trunk/src/mame/drivers/8080bw.c3473
-rw-r--r--trunk/src/mame/drivers/88games.c603
-rw-r--r--trunk/src/mame/drivers/ace.c393
-rw-r--r--trunk/src/mame/drivers/acefruit.c738
-rw-r--r--trunk/src/mame/drivers/aces1.c258
-rw-r--r--trunk/src/mame/drivers/acesp.c1302
-rw-r--r--trunk/src/mame/drivers/acommand.c665
-rw-r--r--trunk/src/mame/drivers/actfancr.c613
-rw-r--r--trunk/src/mame/drivers/adp.c849
-rw-r--r--trunk/src/mame/drivers/aeroboto.c359
-rw-r--r--trunk/src/mame/drivers/aerofgt.c2497
-rw-r--r--trunk/src/mame/drivers/airbustr.c813
-rw-r--r--trunk/src/mame/drivers/ajax.c418
-rw-r--r--trunk/src/mame/drivers/albazc.c306
-rw-r--r--trunk/src/mame/drivers/albazg.c432
-rw-r--r--trunk/src/mame/drivers/aleck64.c847
-rw-r--r--trunk/src/mame/drivers/alg.c836
-rw-r--r--trunk/src/mame/drivers/alien.c111
-rw-r--r--trunk/src/mame/drivers/aliens.c566
-rw-r--r--trunk/src/mame/drivers/allied.c67
-rw-r--r--trunk/src/mame/drivers/alpha68k.c3301
-rw-r--r--trunk/src/mame/drivers/alvg.c239
-rw-r--r--trunk/src/mame/drivers/amaticmg.c783
-rw-r--r--trunk/src/mame/drivers/ambush.c336
-rw-r--r--trunk/src/mame/drivers/ampoker2.c1488
-rw-r--r--trunk/src/mame/drivers/amspdwy.c405
-rw-r--r--trunk/src/mame/drivers/angelkds.c767
-rw-r--r--trunk/src/mame/drivers/appoooh.c614
-rw-r--r--trunk/src/mame/drivers/aquarium.c437
-rw-r--r--trunk/src/mame/drivers/arabian.c455
-rw-r--r--trunk/src/mame/drivers/arcadecl.c414
-rw-r--r--trunk/src/mame/drivers/arcadia.c876
-rw-r--r--trunk/src/mame/drivers/argus.c783
-rw-r--r--trunk/src/mame/drivers/aristmk4.c2337
-rw-r--r--trunk/src/mame/drivers/aristmk5.c753
-rw-r--r--trunk/src/mame/drivers/aristmk6.c451
-rw-r--r--trunk/src/mame/drivers/arkanoid.c1701
-rw-r--r--trunk/src/mame/drivers/armedf.c2171
-rw-r--r--trunk/src/mame/drivers/artmagic.c1220
-rw-r--r--trunk/src/mame/drivers/ashnojoe.c477
-rw-r--r--trunk/src/mame/drivers/asterix.c480
-rw-r--r--trunk/src/mame/drivers/asteroid.c953
-rw-r--r--trunk/src/mame/drivers/astinvad.c774
-rw-r--r--trunk/src/mame/drivers/astrafr.c1955
-rw-r--r--trunk/src/mame/drivers/astrocde.c1875
-rw-r--r--trunk/src/mame/drivers/astrocorp.c1040
-rw-r--r--trunk/src/mame/drivers/astrof.c1363
-rw-r--r--trunk/src/mame/drivers/asuka.c1556
-rw-r--r--trunk/src/mame/drivers/atari_s1.c102
-rw-r--r--trunk/src/mame/drivers/atari_s2.c71
-rw-r--r--trunk/src/mame/drivers/atari_s3.c56
-rw-r--r--trunk/src/mame/drivers/atarifb.c790
-rw-r--r--trunk/src/mame/drivers/atarig1.c1267
-rw-r--r--trunk/src/mame/drivers/atarig42.c879
-rw-r--r--trunk/src/mame/drivers/atarigt.c1321
-rw-r--r--trunk/src/mame/drivers/atarigx2.c2272
-rw-r--r--trunk/src/mame/drivers/atarisy1.c2448
-rw-r--r--trunk/src/mame/drivers/atarisy2.c3320
-rw-r--r--trunk/src/mame/drivers/atarisy4.c1020
-rw-r--r--trunk/src/mame/drivers/ataxx.c798
-rw-r--r--trunk/src/mame/drivers/atetris.c514
-rw-r--r--trunk/src/mame/drivers/attckufo.c232
-rw-r--r--trunk/src/mame/drivers/atvtrack.c423
-rw-r--r--trunk/src/mame/drivers/avalnche.c336
-rw-r--r--trunk/src/mame/drivers/avt.c921
-rw-r--r--trunk/src/mame/drivers/aztarac.c223
-rw-r--r--trunk/src/mame/drivers/backfire.c694
-rw-r--r--trunk/src/mame/drivers/badlands.c787
-rw-r--r--trunk/src/mame/drivers/bagman.c952
-rw-r--r--trunk/src/mame/drivers/balsente.c2230
-rw-r--r--trunk/src/mame/drivers/bankp.c383
-rw-r--r--trunk/src/mame/drivers/baraduke.c559
-rw-r--r--trunk/src/mame/drivers/bartop52.c154
-rw-r--r--trunk/src/mame/drivers/batman.c349
-rw-r--r--trunk/src/mame/drivers/battlane.c433
-rw-r--r--trunk/src/mame/drivers/battlera.c338
-rw-r--r--trunk/src/mame/drivers/battlex.c355
-rw-r--r--trunk/src/mame/drivers/battlnts.c420
-rw-r--r--trunk/src/mame/drivers/bbusters.c939
-rw-r--r--trunk/src/mame/drivers/beaminv.c388
-rw-r--r--trunk/src/mame/drivers/beathead.c518
-rw-r--r--trunk/src/mame/drivers/beezer.c163
-rw-r--r--trunk/src/mame/drivers/berzerk.c1227
-rw-r--r--trunk/src/mame/drivers/bestleag.c460
-rw-r--r--trunk/src/mame/drivers/bfcobra.c1975
-rw-r--r--trunk/src/mame/drivers/bfm_sc1.c2839
-rw-r--r--trunk/src/mame/drivers/bfm_sc2.c5324
-rw-r--r--trunk/src/mame/drivers/bfm_sc4.c16777
-rw-r--r--trunk/src/mame/drivers/bfm_sc5.c43
-rw-r--r--trunk/src/mame/drivers/bfm_swp.c250
-rw-r--r--trunk/src/mame/drivers/bfmsys83.c63
-rw-r--r--trunk/src/mame/drivers/bfmsys85.c695
-rw-r--r--trunk/src/mame/drivers/bgt.c90
-rw-r--r--trunk/src/mame/drivers/big10.c303
-rw-r--r--trunk/src/mame/drivers/bigevglf.c641
-rw-r--r--trunk/src/mame/drivers/bigstrkb.c263
-rw-r--r--trunk/src/mame/drivers/bingo.c87
-rw-r--r--trunk/src/mame/drivers/bingoc.c193
-rw-r--r--trunk/src/mame/drivers/bingor.c744
-rw-r--r--trunk/src/mame/drivers/bionicc.c596
-rw-r--r--trunk/src/mame/drivers/bishi.c522
-rw-r--r--trunk/src/mame/drivers/bking.c836
-rw-r--r--trunk/src/mame/drivers/blackt96.c551
-rw-r--r--trunk/src/mame/drivers/bladestl.c454
-rw-r--r--trunk/src/mame/drivers/blitz.c917
-rw-r--r--trunk/src/mame/drivers/blitz68k.c2824
-rw-r--r--trunk/src/mame/drivers/blktiger.c594
-rw-r--r--trunk/src/mame/drivers/blmbycar.c552
-rw-r--r--trunk/src/mame/drivers/blockade.c598
-rw-r--r--trunk/src/mame/drivers/blockhl.c349
-rw-r--r--trunk/src/mame/drivers/blockout.c427
-rw-r--r--trunk/src/mame/drivers/bloodbro.c634
-rw-r--r--trunk/src/mame/drivers/blstroid.c450
-rw-r--r--trunk/src/mame/drivers/blueprnt.c424
-rw-r--r--trunk/src/mame/drivers/bmcbowl.c549
-rw-r--r--trunk/src/mame/drivers/bnstars.c1478
-rw-r--r--trunk/src/mame/drivers/bogeyman.c315
-rw-r--r--trunk/src/mame/drivers/bombjack.c465
-rw-r--r--trunk/src/mame/drivers/boogwing.c581
-rw-r--r--trunk/src/mame/drivers/bottom9.c592
-rw-r--r--trunk/src/mame/drivers/boxer.c504
-rw-r--r--trunk/src/mame/drivers/brkthru.c670
-rw-r--r--trunk/src/mame/drivers/bsktball.c310
-rw-r--r--trunk/src/mame/drivers/btime.c2227
-rw-r--r--trunk/src/mame/drivers/btoads.c386
-rw-r--r--trunk/src/mame/drivers/bublbobl.c1596
-rw-r--r--trunk/src/mame/drivers/buggychl.c523
-rw-r--r--trunk/src/mame/drivers/buster.c372
-rw-r--r--trunk/src/mame/drivers/bwidow.c957
-rw-r--r--trunk/src/mame/drivers/bwing.c612
-rw-r--r--trunk/src/mame/drivers/by17.c157
-rw-r--r--trunk/src/mame/drivers/by35.c1347
-rw-r--r--trunk/src/mame/drivers/by6803.c327
-rw-r--r--trunk/src/mame/drivers/by68701.c124
-rw-r--r--trunk/src/mame/drivers/byvid.c90
-rw-r--r--trunk/src/mame/drivers/bzone.c820
-rw-r--r--trunk/src/mame/drivers/cabal.c887
-rw-r--r--trunk/src/mame/drivers/cabaret.c399
-rw-r--r--trunk/src/mame/drivers/calchase.c746
-rw-r--r--trunk/src/mame/drivers/calomega.c4036
-rw-r--r--trunk/src/mame/drivers/calorie.c567
-rw-r--r--trunk/src/mame/drivers/canyon.c322
-rw-r--r--trunk/src/mame/drivers/capbowl.c525
-rw-r--r--trunk/src/mame/drivers/capcom.c293
-rw-r--r--trunk/src/mame/drivers/cardline.c264
-rw-r--r--trunk/src/mame/drivers/carjmbre.c267
-rw-r--r--trunk/src/mame/drivers/carpolo.c341
-rw-r--r--trunk/src/mame/drivers/carrera.c372
-rw-r--r--trunk/src/mame/drivers/castle.c108
-rw-r--r--trunk/src/mame/drivers/caswin.c357
-rw-r--r--trunk/src/mame/drivers/cave.c4806
-rw-r--r--trunk/src/mame/drivers/cavesh3.c269
-rw-r--r--trunk/src/mame/drivers/cb2001.c889
-rw-r--r--trunk/src/mame/drivers/cball.c275
-rw-r--r--trunk/src/mame/drivers/cbasebal.c372
-rw-r--r--trunk/src/mame/drivers/cbuster.c580
-rw-r--r--trunk/src/mame/drivers/ccastles.c698
-rw-r--r--trunk/src/mame/drivers/cchance.c265
-rw-r--r--trunk/src/mame/drivers/cchasm.c267
-rw-r--r--trunk/src/mame/drivers/cclimber.c2124
-rw-r--r--trunk/src/mame/drivers/cd32.c1382
-rw-r--r--trunk/src/mame/drivers/cdi.c540
-rw-r--r--trunk/src/mame/drivers/centiped.c2033
-rw-r--r--trunk/src/mame/drivers/cesclass.c89
-rw-r--r--trunk/src/mame/drivers/chaknpop.c445
-rw-r--r--trunk/src/mame/drivers/cham24.c377
-rw-r--r--trunk/src/mame/drivers/champbas.c1239
-rw-r--r--trunk/src/mame/drivers/champbwl.c690
-rw-r--r--trunk/src/mame/drivers/chanbara.c474
-rw-r--r--trunk/src/mame/drivers/changela.c593
-rw-r--r--trunk/src/mame/drivers/cheekyms.c184
-rw-r--r--trunk/src/mame/drivers/chihiro.c903
-rw-r--r--trunk/src/mame/drivers/chinagat.c934
-rw-r--r--trunk/src/mame/drivers/chinsan.c687
-rw-r--r--trunk/src/mame/drivers/chqflag.c501
-rw-r--r--trunk/src/mame/drivers/chsuper.c363
-rw-r--r--trunk/src/mame/drivers/cidelsa.c579
-rw-r--r--trunk/src/mame/drivers/cinemat.c1527
-rw-r--r--trunk/src/mame/drivers/circus.c606
-rw-r--r--trunk/src/mame/drivers/circusc.c551
-rw-r--r--trunk/src/mame/drivers/cischeat.c3012
-rw-r--r--trunk/src/mame/drivers/citycon.c370
-rw-r--r--trunk/src/mame/drivers/clayshoo.c373
-rw-r--r--trunk/src/mame/drivers/cliffhgr.c788
-rw-r--r--trunk/src/mame/drivers/cloak.c627
-rw-r--r--trunk/src/mame/drivers/cloud9.c527
-rw-r--r--trunk/src/mame/drivers/clshroad.c486
-rw-r--r--trunk/src/mame/drivers/cmmb.c342
-rw-r--r--trunk/src/mame/drivers/cninja.c2076
-rw-r--r--trunk/src/mame/drivers/cntsteer.c1184
-rw-r--r--trunk/src/mame/drivers/coinmstr.c1247
-rw-r--r--trunk/src/mame/drivers/coinmvga.c910
-rw-r--r--trunk/src/mame/drivers/combatsc.c1033
-rw-r--r--trunk/src/mame/drivers/comebaby.c118
-rw-r--r--trunk/src/mame/drivers/commando.c564
-rw-r--r--trunk/src/mame/drivers/compgolf.c377
-rw-r--r--trunk/src/mame/drivers/contra.c453
-rw-r--r--trunk/src/mame/drivers/coolpool.c1267
-rw-r--r--trunk/src/mame/drivers/coolridr.c1194
-rw-r--r--trunk/src/mame/drivers/cop01.c683
-rw-r--r--trunk/src/mame/drivers/copsnrob.c347
-rw-r--r--trunk/src/mame/drivers/corona.c1698
-rw-r--r--trunk/src/mame/drivers/cosmic.c1587
-rw-r--r--trunk/src/mame/drivers/cps1.c10563
-rw-r--r--trunk/src/mame/drivers/cps2.c9659
-rw-r--r--trunk/src/mame/drivers/cps3.c3335
-rw-r--r--trunk/src/mame/drivers/crbaloon.c441
-rw-r--r--trunk/src/mame/drivers/crgolf.c619
-rw-r--r--trunk/src/mame/drivers/crimfght.c428
-rw-r--r--trunk/src/mame/drivers/crospang.c617
-rw-r--r--trunk/src/mame/drivers/crshrace.c611
-rw-r--r--trunk/src/mame/drivers/crystal.c1025
-rw-r--r--trunk/src/mame/drivers/cshooter.c711
-rw-r--r--trunk/src/mame/drivers/csplayh5.c880
-rw-r--r--trunk/src/mame/drivers/cubeqst.c769
-rw-r--r--trunk/src/mame/drivers/cultures.c484
-rw-r--r--trunk/src/mame/drivers/cvs.c1740
-rw-r--r--trunk/src/mame/drivers/cyberbal.c1046
-rw-r--r--trunk/src/mame/drivers/cybertnk.c1042
-rw-r--r--trunk/src/mame/drivers/cyclemb.c610
-rw-r--r--trunk/src/mame/drivers/d9final.c321
-rw-r--r--trunk/src/mame/drivers/dacholer.c611
-rw-r--r--trunk/src/mame/drivers/dai3wksi.c663
-rw-r--r--trunk/src/mame/drivers/dambustr.c361
-rw-r--r--trunk/src/mame/drivers/darius.c1308
-rw-r--r--trunk/src/mame/drivers/darkhors.c969
-rw-r--r--trunk/src/mame/drivers/darkmist.c481
-rw-r--r--trunk/src/mame/drivers/darkseal.c492
-rw-r--r--trunk/src/mame/drivers/dassault.c895
-rw-r--r--trunk/src/mame/drivers/dblewing.c757
-rw-r--r--trunk/src/mame/drivers/dbz.c529
-rw-r--r--trunk/src/mame/drivers/dcheese.c818
-rw-r--r--trunk/src/mame/drivers/dcon.c391
-rw-r--r--trunk/src/mame/drivers/dday.c354
-rw-r--r--trunk/src/mame/drivers/ddayjlc.c694
-rw-r--r--trunk/src/mame/drivers/ddealer.c696
-rw-r--r--trunk/src/mame/drivers/ddenlovr.c10379
-rw-r--r--trunk/src/mame/drivers/ddragon.c2124
-rw-r--r--trunk/src/mame/drivers/ddragon3.c1018
-rw-r--r--trunk/src/mame/drivers/ddribble.c411
-rw-r--r--trunk/src/mame/drivers/ddz.c103
-rw-r--r--trunk/src/mame/drivers/de_1.c66
-rw-r--r--trunk/src/mame/drivers/de_2.c170
-rw-r--r--trunk/src/mame/drivers/de_3.c1024
-rw-r--r--trunk/src/mame/drivers/de_3b.c455
-rw-r--r--trunk/src/mame/drivers/deadang.c435
-rw-r--r--trunk/src/mame/drivers/dec0.c3007
-rw-r--r--trunk/src/mame/drivers/dec8.c3639
-rw-r--r--trunk/src/mame/drivers/deco156.c655
-rw-r--r--trunk/src/mame/drivers/deco32.c3365
-rw-r--r--trunk/src/mame/drivers/deco_ld.c689
-rw-r--r--trunk/src/mame/drivers/deco_mlc.c775
-rw-r--r--trunk/src/mame/drivers/decocass.c1418
-rw-r--r--trunk/src/mame/drivers/deniam.c443
-rw-r--r--trunk/src/mame/drivers/deshoros.c225
-rw-r--r--trunk/src/mame/drivers/destroyr.c521
-rw-r--r--trunk/src/mame/drivers/dfruit.c157
-rw-r--r--trunk/src/mame/drivers/dgpix.c620
-rw-r--r--trunk/src/mame/drivers/dietgo.c379
-rw-r--r--trunk/src/mame/drivers/discoboy.c555
-rw-r--r--trunk/src/mame/drivers/diverboy.c317
-rw-r--r--trunk/src/mame/drivers/djboy.c764
-rw-r--r--trunk/src/mame/drivers/djmain.c2281
-rw-r--r--trunk/src/mame/drivers/dkong.c3236
-rw-r--r--trunk/src/mame/drivers/dlair.c984
-rw-r--r--trunk/src/mame/drivers/dmndrby.c639
-rw-r--r--trunk/src/mame/drivers/docastle.c1111
-rw-r--r--trunk/src/mame/drivers/dogfgt.c396
-rw-r--r--trunk/src/mame/drivers/dominob.c364
-rw-r--r--trunk/src/mame/drivers/dooyong.c1929
-rw-r--r--trunk/src/mame/drivers/dorachan.c297
-rw-r--r--trunk/src/mame/drivers/dotrikun.c190
-rw-r--r--trunk/src/mame/drivers/dragrace.c390
-rw-r--r--trunk/src/mame/drivers/dreamwld.c693
-rw-r--r--trunk/src/mame/drivers/drgnmst.c575
-rw-r--r--trunk/src/mame/drivers/dribling.c401
-rw-r--r--trunk/src/mame/drivers/drmicro.c341
-rw-r--r--trunk/src/mame/drivers/drtomy.c352
-rw-r--r--trunk/src/mame/drivers/drw80pkr.c532
-rw-r--r--trunk/src/mame/drivers/dunhuang.c878
-rw-r--r--trunk/src/mame/drivers/dwarfd.c1344
-rw-r--r--trunk/src/mame/drivers/dynadice.c310
-rw-r--r--trunk/src/mame/drivers/dynax.c7253
-rw-r--r--trunk/src/mame/drivers/dynduke.c526
-rw-r--r--trunk/src/mame/drivers/ecoinfr.c1007
-rw-r--r--trunk/src/mame/drivers/egghunt.c466
-rw-r--r--trunk/src/mame/drivers/embargo.c303
-rw-r--r--trunk/src/mame/drivers/enigma2.c722
-rw-r--r--trunk/src/mame/drivers/eolith.c1167
-rw-r--r--trunk/src/mame/drivers/eolith16.c267
-rw-r--r--trunk/src/mame/drivers/eolithsp.c105
-rw-r--r--trunk/src/mame/drivers/epos.c666
-rw-r--r--trunk/src/mame/drivers/eprom.c762
-rw-r--r--trunk/src/mame/drivers/equites.c1947
-rw-r--r--trunk/src/mame/drivers/ertictac.c315
-rw-r--r--trunk/src/mame/drivers/esd16.c1227
-rw-r--r--trunk/src/mame/drivers/esh.c398
-rw-r--r--trunk/src/mame/drivers/espial.c458
-rw-r--r--trunk/src/mame/drivers/esripsys.c1115
-rw-r--r--trunk/src/mame/drivers/ettrivia.c481
-rw-r--r--trunk/src/mame/drivers/exedexes.c353
-rw-r--r--trunk/src/mame/drivers/exerion.c627
-rw-r--r--trunk/src/mame/drivers/exidy.c1508
-rw-r--r--trunk/src/mame/drivers/exidy440.c2032
-rw-r--r--trunk/src/mame/drivers/expro02.c792
-rw-r--r--trunk/src/mame/drivers/exprraid.c796
-rw-r--r--trunk/src/mame/drivers/exterm.c531
-rw-r--r--trunk/src/mame/drivers/exzisus.c413
-rw-r--r--trunk/src/mame/drivers/f-32.c241
-rw-r--r--trunk/src/mame/drivers/f1gp.c711
-rw-r--r--trunk/src/mame/drivers/famibox.c110
-rw-r--r--trunk/src/mame/drivers/fantland.c1456
-rw-r--r--trunk/src/mame/drivers/fastfred.c1043
-rw-r--r--trunk/src/mame/drivers/fastlane.c274
-rw-r--r--trunk/src/mame/drivers/fcombat.c466
-rw-r--r--trunk/src/mame/drivers/fcrash.c919
-rw-r--r--trunk/src/mame/drivers/feversoc.c302
-rw-r--r--trunk/src/mame/drivers/fgoal.c448
-rw-r--r--trunk/src/mame/drivers/finalizr.c371
-rw-r--r--trunk/src/mame/drivers/firebeat.c2424
-rw-r--r--trunk/src/mame/drivers/firefox.c843
-rw-r--r--trunk/src/mame/drivers/firetrap.c956
-rw-r--r--trunk/src/mame/drivers/firetrk.c1046
-rw-r--r--trunk/src/mame/drivers/fitfight.c1004
-rw-r--r--trunk/src/mame/drivers/flicker.c52
-rw-r--r--trunk/src/mame/drivers/flkatck.c306
-rw-r--r--trunk/src/mame/drivers/flower.c380
-rw-r--r--trunk/src/mame/drivers/flstory.c1628
-rw-r--r--trunk/src/mame/drivers/flyball.c465
-rw-r--r--trunk/src/mame/drivers/foodf.c485
-rw-r--r--trunk/src/mame/drivers/forte2.c181
-rw-r--r--trunk/src/mame/drivers/fortecar.c348
-rw-r--r--trunk/src/mame/drivers/freekick.c1137
-rw-r--r--trunk/src/mame/drivers/fromanc2.c854
-rw-r--r--trunk/src/mame/drivers/fromance.c1347
-rw-r--r--trunk/src/mame/drivers/funkball.c128
-rw-r--r--trunk/src/mame/drivers/funkybee.c438
-rw-r--r--trunk/src/mame/drivers/funkyjet.c418
-rw-r--r--trunk/src/mame/drivers/funworld.c4504
-rw-r--r--trunk/src/mame/drivers/funybubl.c320
-rw-r--r--trunk/src/mame/drivers/fuukifg2.c687
-rw-r--r--trunk/src/mame/drivers/fuukifg3.c756
-rw-r--r--trunk/src/mame/drivers/g627.c52
-rw-r--r--trunk/src/mame/drivers/gaelco.c875
-rw-r--r--trunk/src/mame/drivers/gaelco2.c1462
-rw-r--r--trunk/src/mame/drivers/gaelco3d.c1261
-rw-r--r--trunk/src/mame/drivers/gaiden.c1633
-rw-r--r--trunk/src/mame/drivers/gal3.c928
-rw-r--r--trunk/src/mame/drivers/galaga.c3298
-rw-r--r--trunk/src/mame/drivers/galastrm.c384
-rw-r--r--trunk/src/mame/drivers/galaxi.c481
-rw-r--r--trunk/src/mame/drivers/galaxia.c365
-rw-r--r--trunk/src/mame/drivers/galaxian.c3387
-rw-r--r--trunk/src/mame/drivers/galaxold.c3093
-rw-r--r--trunk/src/mame/drivers/galdrvr.c6462
-rw-r--r--trunk/src/mame/drivers/galivan.c1118
-rw-r--r--trunk/src/mame/drivers/galpani2.c1014
-rw-r--r--trunk/src/mame/drivers/galpani3.c1012
-rw-r--r--trunk/src/mame/drivers/galpanic.c1017
-rw-r--r--trunk/src/mame/drivers/galspnbl.c312
-rw-r--r--trunk/src/mame/drivers/gamecstl.c805
-rw-r--r--trunk/src/mame/drivers/gameplan.c1202
-rw-r--r--trunk/src/mame/drivers/gaplus.c876
-rw-r--r--trunk/src/mame/drivers/gatron.c500
-rw-r--r--trunk/src/mame/drivers/gauntlet.c1721
-rw-r--r--trunk/src/mame/drivers/gberet.c582
-rw-r--r--trunk/src/mame/drivers/gbusters.c451
-rw-r--r--trunk/src/mame/drivers/gcpinbal.c503
-rw-r--r--trunk/src/mame/drivers/gei.c1889
-rw-r--r--trunk/src/mame/drivers/ggconnie.c200
-rw-r--r--trunk/src/mame/drivers/ghosteo.c557
-rw-r--r--trunk/src/mame/drivers/gijoe.c461
-rw-r--r--trunk/src/mame/drivers/ginganin.c397
-rw-r--r--trunk/src/mame/drivers/gladiatr.c1041
-rw-r--r--trunk/src/mame/drivers/glass.c338
-rw-r--r--trunk/src/mame/drivers/globalfr.c119
-rw-r--r--trunk/src/mame/drivers/gng.c737
-rw-r--r--trunk/src/mame/drivers/go2000.c368
-rw-r--r--trunk/src/mame/drivers/goal92.c423
-rw-r--r--trunk/src/mame/drivers/goindol.c425
-rw-r--r--trunk/src/mame/drivers/goldngam.c626
-rw-r--r--trunk/src/mame/drivers/goldnpkr.c4918
-rw-r--r--trunk/src/mame/drivers/goldstar.c10399
-rw-r--r--trunk/src/mame/drivers/gomoku.c182
-rw-r--r--trunk/src/mame/drivers/good.c319
-rw-r--r--trunk/src/mame/drivers/goodejan.c470
-rw-r--r--trunk/src/mame/drivers/gotcha.c397
-rw-r--r--trunk/src/mame/drivers/gottlieb.c2669
-rw-r--r--trunk/src/mame/drivers/gotya.c291
-rw-r--r--trunk/src/mame/drivers/gp_1.c97
-rw-r--r--trunk/src/mame/drivers/gp_2.c245
-rw-r--r--trunk/src/mame/drivers/gpworld.c539
-rw-r--r--trunk/src/mame/drivers/gradius3.c518
-rw-r--r--trunk/src/mame/drivers/grchamp.c792
-rw-r--r--trunk/src/mame/drivers/gridlee.c497
-rw-r--r--trunk/src/mame/drivers/groundfx.c491
-rw-r--r--trunk/src/mame/drivers/gstream.c648
-rw-r--r--trunk/src/mame/drivers/gstriker.c1066
-rw-r--r--trunk/src/mame/drivers/gsword.c939
-rw-r--r--trunk/src/mame/drivers/gticlub.c1184
-rw-r--r--trunk/src/mame/drivers/gts1.c311
-rw-r--r--trunk/src/mame/drivers/gts3.c955
-rw-r--r--trunk/src/mame/drivers/gts80.c705
-rw-r--r--trunk/src/mame/drivers/gts80a.c655
-rw-r--r--trunk/src/mame/drivers/gts80b.c601
-rw-r--r--trunk/src/mame/drivers/guab.c962
-rw-r--r--trunk/src/mame/drivers/gumbo.c401
-rw-r--r--trunk/src/mame/drivers/gunbustr.c423
-rw-r--r--trunk/src/mame/drivers/gundealr.c595
-rw-r--r--trunk/src/mame/drivers/gunpey.c395
-rw-r--r--trunk/src/mame/drivers/gunsmoke.c541
-rw-r--r--trunk/src/mame/drivers/gyruss.c735
-rw-r--r--trunk/src/mame/drivers/halleys.c2268
-rw-r--r--trunk/src/mame/drivers/hanaawas.c262
-rw-r--r--trunk/src/mame/drivers/hankin.c111
-rw-r--r--trunk/src/mame/drivers/harddriv.c4360
-rw-r--r--trunk/src/mame/drivers/hazelgr.c43
-rw-r--r--trunk/src/mame/drivers/hcastle.c372
-rw-r--r--trunk/src/mame/drivers/hexion.c299
-rw-r--r--trunk/src/mame/drivers/higemaru.c219
-rw-r--r--trunk/src/mame/drivers/highvdeo.c1265
-rw-r--r--trunk/src/mame/drivers/hikaru.c641
-rw-r--r--trunk/src/mame/drivers/himesiki.c360
-rw-r--r--trunk/src/mame/drivers/hitme.c707
-rw-r--r--trunk/src/mame/drivers/hitpoker.c542
-rw-r--r--trunk/src/mame/drivers/hnayayoi.c707
-rw-r--r--trunk/src/mame/drivers/hng64.c2225
-rw-r--r--trunk/src/mame/drivers/holeland.c506
-rw-r--r--trunk/src/mame/drivers/homedata.c2083
-rw-r--r--trunk/src/mame/drivers/homerun.c320
-rw-r--r--trunk/src/mame/drivers/hornet.c1494
-rw-r--r--trunk/src/mame/drivers/hotblock.c245
-rw-r--r--trunk/src/mame/drivers/hotstuff.c105
-rw-r--r--trunk/src/mame/drivers/hshavoc.c232
-rw-r--r--trunk/src/mame/drivers/hvyunit.c818
-rw-r--r--trunk/src/mame/drivers/hyhoo.c327
-rw-r--r--trunk/src/mame/drivers/hyperspt.c532
-rw-r--r--trunk/src/mame/drivers/hyprduel.c832
-rw-r--r--trunk/src/mame/drivers/icecold.c44
-rw-r--r--trunk/src/mame/drivers/igs009.c835
-rw-r--r--trunk/src/mame/drivers/igs011.c4389
-rw-r--r--trunk/src/mame/drivers/igs017.c3149
-rw-r--r--trunk/src/mame/drivers/igs_m027.c629
-rw-r--r--trunk/src/mame/drivers/igspoker.c2453
-rw-r--r--trunk/src/mame/drivers/ikki.c348
-rw-r--r--trunk/src/mame/drivers/imolagp.c606
-rw-r--r--trunk/src/mame/drivers/inder.c131
-rw-r--r--trunk/src/mame/drivers/intrscti.c141
-rw-r--r--trunk/src/mame/drivers/inufuku.c431
-rw-r--r--trunk/src/mame/drivers/iqblock.c477
-rw-r--r--trunk/src/mame/drivers/irobot.c392
-rw-r--r--trunk/src/mame/drivers/ironhors.c570
-rw-r--r--trunk/src/mame/drivers/istellar.c419
-rw-r--r--trunk/src/mame/drivers/itech32.c4355
-rw-r--r--trunk/src/mame/drivers/itech8.c2756
-rw-r--r--trunk/src/mame/drivers/itgambl2.c944
-rw-r--r--trunk/src/mame/drivers/itgambl3.c493
-rw-r--r--trunk/src/mame/drivers/itgamble.c701
-rw-r--r--trunk/src/mame/drivers/jack.c1450
-rw-r--r--trunk/src/mame/drivers/jackal.c520
-rw-r--r--trunk/src/mame/drivers/jackie.c616
-rw-r--r--trunk/src/mame/drivers/jackpool.c303
-rw-r--r--trunk/src/mame/drivers/jaguar.c2479
-rw-r--r--trunk/src/mame/drivers/jailbrek.c434
-rw-r--r--trunk/src/mame/drivers/jalmah.c2463
-rw-r--r--trunk/src/mame/drivers/jangou.c1434
-rw-r--r--trunk/src/mame/drivers/jantotsu.c579
-rw-r--r--trunk/src/mame/drivers/jchan.c803
-rw-r--r--trunk/src/mame/drivers/jedi.c410
-rw-r--r--trunk/src/mame/drivers/jokrwild.c569
-rw-r--r--trunk/src/mame/drivers/jollyjgr.c762
-rw-r--r--trunk/src/mame/drivers/jongkyo.c570
-rw-r--r--trunk/src/mame/drivers/jp.c150
-rw-r--r--trunk/src/mame/drivers/jpmimpct.c5492
-rw-r--r--trunk/src/mame/drivers/jpmmps.c2170
-rw-r--r--trunk/src/mame/drivers/jpms80.c371
-rw-r--r--trunk/src/mame/drivers/jpmsys5.c2478
-rw-r--r--trunk/src/mame/drivers/jpmsys7.c210
-rw-r--r--trunk/src/mame/drivers/jrpacman.c397
-rw-r--r--trunk/src/mame/drivers/jubilee.c462
-rw-r--r--trunk/src/mame/drivers/junofrst.c513
-rw-r--r--trunk/src/mame/drivers/jvh.c60
-rw-r--r--trunk/src/mame/drivers/kaneko16.c3954
-rw-r--r--trunk/src/mame/drivers/kangaroo.c578
-rw-r--r--trunk/src/mame/drivers/karnov.c1208
-rw-r--r--trunk/src/mame/drivers/kchamp.c795
-rw-r--r--trunk/src/mame/drivers/kickgoal.c826
-rw-r--r--trunk/src/mame/drivers/kingdrby.c1179
-rw-r--r--trunk/src/mame/drivers/kingobox.c830
-rw-r--r--trunk/src/mame/drivers/kingpin.c227
-rw-r--r--trunk/src/mame/drivers/kinst.c936
-rw-r--r--trunk/src/mame/drivers/kissproto.c49
-rw-r--r--trunk/src/mame/drivers/klax.c369
-rw-r--r--trunk/src/mame/drivers/kncljoe.c423
-rw-r--r--trunk/src/mame/drivers/koftball.c311
-rw-r--r--trunk/src/mame/drivers/koikoi.c428
-rw-r--r--trunk/src/mame/drivers/konamigq.c496
-rw-r--r--trunk/src/mame/drivers/konamigv.c873
-rw-r--r--trunk/src/mame/drivers/konamigx.c3925
-rw-r--r--trunk/src/mame/drivers/konamim2.c1299
-rw-r--r--trunk/src/mame/drivers/kongambl.c215
-rw-r--r--trunk/src/mame/drivers/kopunch.c250
-rw-r--r--trunk/src/mame/drivers/ksayakyu.c356
-rw-r--r--trunk/src/mame/drivers/ksys573.c5356
-rw-r--r--trunk/src/mame/drivers/kungfur.c410
-rw-r--r--trunk/src/mame/drivers/kyugo.c1376
-rw-r--r--trunk/src/mame/drivers/labyrunr.c299
-rw-r--r--trunk/src/mame/drivers/ladybug.c1084
-rw-r--r--trunk/src/mame/drivers/ladyfrog.c403
-rw-r--r--trunk/src/mame/drivers/laserbas.c283
-rw-r--r--trunk/src/mame/drivers/laserbat.c1061
-rw-r--r--trunk/src/mame/drivers/lasso.c895
-rw-r--r--trunk/src/mame/drivers/lastbank.c161
-rw-r--r--trunk/src/mame/drivers/lastduel.c883
-rw-r--r--trunk/src/mame/drivers/lastfght.c635
-rw-r--r--trunk/src/mame/drivers/lazercmd.c880
-rw-r--r--trunk/src/mame/drivers/legionna.c2254
-rw-r--r--trunk/src/mame/drivers/leland.c2348
-rw-r--r--trunk/src/mame/drivers/lemmings.c341
-rw-r--r--trunk/src/mame/drivers/lethal.c954
-rw-r--r--trunk/src/mame/drivers/lethalj.c931
-rw-r--r--trunk/src/mame/drivers/lgp.c479
-rw-r--r--trunk/src/mame/drivers/liberate.c1428
-rw-r--r--trunk/src/mame/drivers/liberatr.c503
-rw-r--r--trunk/src/mame/drivers/limenko.c1092
-rw-r--r--trunk/src/mame/drivers/littlerb.c515
-rw-r--r--trunk/src/mame/drivers/lkage.c999
-rw-r--r--trunk/src/mame/drivers/lockon.c821
-rw-r--r--trunk/src/mame/drivers/looping.c916
-rw-r--r--trunk/src/mame/drivers/lordgun.c1056
-rw-r--r--trunk/src/mame/drivers/lsasquad.c833
-rw-r--r--trunk/src/mame/drivers/ltcasino.c723
-rw-r--r--trunk/src/mame/drivers/ltd.c127
-rw-r--r--trunk/src/mame/drivers/luckgrln.c934
-rw-r--r--trunk/src/mame/drivers/lucky74.c1375
-rw-r--r--trunk/src/mame/drivers/lvcards.c584
-rw-r--r--trunk/src/mame/drivers/lwings.c1362
-rw-r--r--trunk/src/mame/drivers/m10.c1062
-rw-r--r--trunk/src/mame/drivers/m107.c1003
-rw-r--r--trunk/src/mame/drivers/m14.c388
-rw-r--r--trunk/src/mame/drivers/m52.c555
-rw-r--r--trunk/src/mame/drivers/m57.c331
-rw-r--r--trunk/src/mame/drivers/m58.c454
-rw-r--r--trunk/src/mame/drivers/m62.c2231
-rw-r--r--trunk/src/mame/drivers/m63.c1012
-rw-r--r--trunk/src/mame/drivers/m72.c3719
-rw-r--r--trunk/src/mame/drivers/m79amb.c323
-rw-r--r--trunk/src/mame/drivers/m90.c1207
-rw-r--r--trunk/src/mame/drivers/m92.c2147
-rw-r--r--trunk/src/mame/drivers/macrossp.c806
-rw-r--r--trunk/src/mame/drivers/macs.c764
-rw-r--r--trunk/src/mame/drivers/madalien.c421
-rw-r--r--trunk/src/mame/drivers/madmotor.c368
-rw-r--r--trunk/src/mame/drivers/magic10.c1257
-rw-r--r--trunk/src/mame/drivers/magicard.c843
-rw-r--r--trunk/src/mame/drivers/magicfly.c857
-rw-r--r--trunk/src/mame/drivers/magictg.c235
-rw-r--r--trunk/src/mame/drivers/magmax.c446
-rw-r--r--trunk/src/mame/drivers/magtouch.c246
-rw-r--r--trunk/src/mame/drivers/mainevt.c789
-rw-r--r--trunk/src/mame/drivers/mainsnk.c496
-rw-r--r--trunk/src/mame/drivers/majorpkr.c1097
-rw-r--r--trunk/src/mame/drivers/malzak.c499
-rw-r--r--trunk/src/mame/drivers/mappy.c2274
-rw-r--r--trunk/src/mame/drivers/marineb.c881
-rw-r--r--trunk/src/mame/drivers/marinedt.c725
-rw-r--r--trunk/src/mame/drivers/mario.c544
-rw-r--r--trunk/src/mame/drivers/markham.c244
-rw-r--r--trunk/src/mame/drivers/mastboy.c1000
-rw-r--r--trunk/src/mame/drivers/matmania.c690
-rw-r--r--trunk/src/mame/drivers/maxaflex.c485
-rw-r--r--trunk/src/mame/drivers/maygay1b.c3309
-rw-r--r--trunk/src/mame/drivers/maygayep.c4602
-rw-r--r--trunk/src/mame/drivers/maygaysw.c348
-rw-r--r--trunk/src/mame/drivers/maygayv1.c1415
-rw-r--r--trunk/src/mame/drivers/mayumi.c439
-rw-r--r--trunk/src/mame/drivers/mazerbla.c1725
-rw-r--r--trunk/src/mame/drivers/mcatadv.c677
-rw-r--r--trunk/src/mame/drivers/mcr.c2705
-rw-r--r--trunk/src/mame/drivers/mcr3.c1662
-rw-r--r--trunk/src/mame/drivers/mcr68.c1689
-rw-r--r--trunk/src/mame/drivers/meadows.c925
-rw-r--r--trunk/src/mame/drivers/mediagx.c1312
-rw-r--r--trunk/src/mame/drivers/megadrvb.c801
-rw-r--r--trunk/src/mame/drivers/megaplay.c948
-rw-r--r--trunk/src/mame/drivers/megasys1.c3949
-rw-r--r--trunk/src/mame/drivers/megatech.c1297
-rw-r--r--trunk/src/mame/drivers/megazone.c536
-rw-r--r--trunk/src/mame/drivers/meijinsn.c409
-rw-r--r--trunk/src/mame/drivers/mephisto.c78
-rw-r--r--trunk/src/mame/drivers/merit.c2120
-rw-r--r--trunk/src/mame/drivers/meritm.c1959
-rw-r--r--trunk/src/mame/drivers/mermaid.c598
-rw-r--r--trunk/src/mame/drivers/metalmx.c917
-rw-r--r--trunk/src/mame/drivers/metlclsh.c444
-rw-r--r--trunk/src/mame/drivers/metro.c6199
-rw-r--r--trunk/src/mame/drivers/mexico86.c716
-rw-r--r--trunk/src/mame/drivers/mgolf.c373
-rw-r--r--trunk/src/mame/drivers/mhavoc.c749
-rw-r--r--trunk/src/mame/drivers/micro3d.c676
-rw-r--r--trunk/src/mame/drivers/micropin.c60
-rw-r--r--trunk/src/mame/drivers/midas.c959
-rw-r--r--trunk/src/mame/drivers/midqslvr.c111
-rw-r--r--trunk/src/mame/drivers/midtunit.c1450
-rw-r--r--trunk/src/mame/drivers/midvunit.c1753
-rw-r--r--trunk/src/mame/drivers/midwunit.c1247
-rw-r--r--trunk/src/mame/drivers/midxunit.c365
-rw-r--r--trunk/src/mame/drivers/midyunit.c2681
-rw-r--r--trunk/src/mame/drivers/midzeus.c1452
-rw-r--r--trunk/src/mame/drivers/mikie.c377
-rw-r--r--trunk/src/mame/drivers/mil4000.c479
-rw-r--r--trunk/src/mame/drivers/miniboy7.c566
-rw-r--r--trunk/src/mame/drivers/minivadr.c113
-rw-r--r--trunk/src/mame/drivers/mirage.c389
-rw-r--r--trunk/src/mame/drivers/mirax.c507
-rw-r--r--trunk/src/mame/drivers/missb2.c594
-rw-r--r--trunk/src/mame/drivers/missile.c1288
-rw-r--r--trunk/src/mame/drivers/mitchell.c2351
-rw-r--r--trunk/src/mame/drivers/mjkjidai.c447
-rw-r--r--trunk/src/mame/drivers/mjsister.c562
-rw-r--r--trunk/src/mame/drivers/mlanding.c840
-rw-r--r--trunk/src/mame/drivers/mmm.c43
-rw-r--r--trunk/src/mame/drivers/model1.c1598
-rw-r--r--trunk/src/mame/drivers/model2.c5188
-rw-r--r--trunk/src/mame/drivers/model3.c5736
-rw-r--r--trunk/src/mame/drivers/mogura.c246
-rw-r--r--trunk/src/mame/drivers/mole.c378
-rw-r--r--trunk/src/mame/drivers/momoko.c348
-rw-r--r--trunk/src/mame/drivers/monzagp.c307
-rw-r--r--trunk/src/mame/drivers/moo.c940
-rw-r--r--trunk/src/mame/drivers/mosaic.c373
-rw-r--r--trunk/src/mame/drivers/mouser.c317
-rw-r--r--trunk/src/mame/drivers/mpoker.c631
-rw-r--r--trunk/src/mame/drivers/mpu2.c93
-rw-r--r--trunk/src/mame/drivers/mpu3.c1685
-rw-r--r--trunk/src/mame/drivers/mpu4.c15097
-rw-r--r--trunk/src/mame/drivers/mpu4vid.c4871
-rw-r--r--trunk/src/mame/drivers/mpu5.c5783
-rw-r--r--trunk/src/mame/drivers/mquake.c475
-rw-r--r--trunk/src/mame/drivers/mrdo.c395
-rw-r--r--trunk/src/mame/drivers/mrflea.c453
-rw-r--r--trunk/src/mame/drivers/mrgame.c163
-rw-r--r--trunk/src/mame/drivers/mrjong.c277
-rw-r--r--trunk/src/mame/drivers/ms32.c2609
-rw-r--r--trunk/src/mame/drivers/msisaac.c578
-rw-r--r--trunk/src/mame/drivers/mugsmash.c474
-rw-r--r--trunk/src/mame/drivers/multfish.c4351
-rw-r--r--trunk/src/mame/drivers/multigam.c1421
-rw-r--r--trunk/src/mame/drivers/munchmo.c442
-rw-r--r--trunk/src/mame/drivers/murogem.c284
-rw-r--r--trunk/src/mame/drivers/murogmbl.c221
-rw-r--r--trunk/src/mame/drivers/mustache.c301
-rw-r--r--trunk/src/mame/drivers/mw18w.c203
-rw-r--r--trunk/src/mame/drivers/mw8080bw.c3234
-rw-r--r--trunk/src/mame/drivers/mwarr.c651
-rw-r--r--trunk/src/mame/drivers/mystston.c287
-rw-r--r--trunk/src/mame/drivers/mystwarr.c2121
-rw-r--r--trunk/src/mame/drivers/n8080.c924
-rw-r--r--trunk/src/mame/drivers/namcofl.c834
-rw-r--r--trunk/src/mame/drivers/namcoic.c1692
-rw-r--r--trunk/src/mame/drivers/namcona1.c1431
-rw-r--r--trunk/src/mame/drivers/namconb1.c2054
-rw-r--r--trunk/src/mame/drivers/namcond1.c418
-rw-r--r--trunk/src/mame/drivers/namcops2.c376
-rw-r--r--trunk/src/mame/drivers/namcos1.c2746
-rw-r--r--trunk/src/mame/drivers/namcos10.c648
-rw-r--r--trunk/src/mame/drivers/namcos11.c1841
-rw-r--r--trunk/src/mame/drivers/namcos12.c2798
-rw-r--r--trunk/src/mame/drivers/namcos2.c5316
-rw-r--r--trunk/src/mame/drivers/namcos21.c2467
-rw-r--r--trunk/src/mame/drivers/namcos22.c6029
-rw-r--r--trunk/src/mame/drivers/namcos23.c3906
-rw-r--r--trunk/src/mame/drivers/namcos86.c1537
-rw-r--r--trunk/src/mame/drivers/naomi.c7784
-rw-r--r--trunk/src/mame/drivers/naughtyb.c892
-rw-r--r--trunk/src/mame/drivers/nbmj8688.c4101
-rw-r--r--trunk/src/mame/drivers/nbmj8891.c3872
-rw-r--r--trunk/src/mame/drivers/nbmj8900.c410
-rw-r--r--trunk/src/mame/drivers/nbmj8991.c2214
-rw-r--r--trunk/src/mame/drivers/nbmj9195.c3983
-rw-r--r--trunk/src/mame/drivers/nemesis.c2882
-rw-r--r--trunk/src/mame/drivers/neodrvr.c9339
-rw-r--r--trunk/src/mame/drivers/neogeo.c1386
-rw-r--r--trunk/src/mame/drivers/neoprint.c618
-rw-r--r--trunk/src/mame/drivers/neptunp2.c126
-rw-r--r--trunk/src/mame/drivers/news.c188
-rw-r--r--trunk/src/mame/drivers/nightgal.c1252
-rw-r--r--trunk/src/mame/drivers/ninjakd2.c1476
-rw-r--r--trunk/src/mame/drivers/ninjaw.c1136
-rw-r--r--trunk/src/mame/drivers/nitedrvr.c204
-rw-r--r--trunk/src/mame/drivers/niyanpai.c1005
-rw-r--r--trunk/src/mame/drivers/nmg5.c1560
-rw-r--r--trunk/src/mame/drivers/nmk16.c7228
-rw-r--r--trunk/src/mame/drivers/norautp.c3575
-rw-r--r--trunk/src/mame/drivers/nova2001.c1045
-rw-r--r--trunk/src/mame/drivers/nsm.c57
-rw-r--r--trunk/src/mame/drivers/nsmpoker.c445
-rw-r--r--trunk/src/mame/drivers/nss.c873
-rw-r--r--trunk/src/mame/drivers/nwk-tr.c898
-rw-r--r--trunk/src/mame/drivers/nycaptor.c1396
-rw-r--r--trunk/src/mame/drivers/nyny.c844
-rw-r--r--trunk/src/mame/drivers/offtwall.c528
-rw-r--r--trunk/src/mame/drivers/ohmygod.c408
-rw-r--r--trunk/src/mame/drivers/ojankohs.c1109
-rw-r--r--trunk/src/mame/drivers/olibochu.c524
-rw-r--r--trunk/src/mame/drivers/omegrace.c609
-rw-r--r--trunk/src/mame/drivers/oneshot.c501
-rw-r--r--trunk/src/mame/drivers/onetwo.c438
-rw-r--r--trunk/src/mame/drivers/opwolf.c1021
-rw-r--r--trunk/src/mame/drivers/orbit.c377
-rw-r--r--trunk/src/mame/drivers/othello.c478
-rw-r--r--trunk/src/mame/drivers/othldrby.c292
-rw-r--r--trunk/src/mame/drivers/othunder.c946
-rw-r--r--trunk/src/mame/drivers/overdriv.c439
-rw-r--r--trunk/src/mame/drivers/pachifev.c409
-rw-r--r--trunk/src/mame/drivers/pacland.c621
-rw-r--r--trunk/src/mame/drivers/pacman.c5766
-rw-r--r--trunk/src/mame/drivers/pandoras.c440
-rw-r--r--trunk/src/mame/drivers/pangofun.c255
-rw-r--r--trunk/src/mame/drivers/panicr.c572
-rw-r--r--trunk/src/mame/drivers/paradise.c1253
-rw-r--r--trunk/src/mame/drivers/paranoia.c205
-rw-r--r--trunk/src/mame/drivers/parodius.c427
-rw-r--r--trunk/src/mame/drivers/pasha2.c479
-rw-r--r--trunk/src/mame/drivers/pass.c294
-rw-r--r--trunk/src/mame/drivers/pastelg.c579
-rw-r--r--trunk/src/mame/drivers/pbaction.c502
-rw-r--r--trunk/src/mame/drivers/pcat_dyn.c198
-rw-r--r--trunk/src/mame/drivers/pcat_nit.c402
-rw-r--r--trunk/src/mame/drivers/pcktgal.c463
-rw-r--r--trunk/src/mame/drivers/pcxt.c1135
-rw-r--r--trunk/src/mame/drivers/pengadvb.c353
-rw-r--r--trunk/src/mame/drivers/pengo.c724
-rw-r--r--trunk/src/mame/drivers/peplus.c1531
-rw-r--r--trunk/src/mame/drivers/peyper.c626
-rw-r--r--trunk/src/mame/drivers/pgm.c6023
-rw-r--r--trunk/src/mame/drivers/phoenix.c1118
-rw-r--r--trunk/src/mame/drivers/photon.c278
-rw-r--r--trunk/src/mame/drivers/photon2.c374
-rw-r--r--trunk/src/mame/drivers/photoply.c577
-rw-r--r--trunk/src/mame/drivers/pingpong.c621
-rw-r--r--trunk/src/mame/drivers/pinkiri8.c1230
-rw-r--r--trunk/src/mame/drivers/pipedrm.c907
-rw-r--r--trunk/src/mame/drivers/pipeline.c460
-rw-r--r--trunk/src/mame/drivers/pirates.c471
-rw-r--r--trunk/src/mame/drivers/pitnrun.c348
-rw-r--r--trunk/src/mame/drivers/pkscram.c346
-rw-r--r--trunk/src/mame/drivers/pktgaldx.c466
-rw-r--r--trunk/src/mame/drivers/play_1.c104
-rw-r--r--trunk/src/mame/drivers/play_2.c242
-rw-r--r--trunk/src/mame/drivers/play_3.c75
-rw-r--r--trunk/src/mame/drivers/play_5.c182
-rw-r--r--trunk/src/mame/drivers/playch10.c1703
-rw-r--r--trunk/src/mame/drivers/playmark.c1716
-rw-r--r--trunk/src/mame/drivers/pluto5.c354
-rw-r--r--trunk/src/mame/drivers/plygonet.c836
-rw-r--r--trunk/src/mame/drivers/pntnpuzl.c500
-rw-r--r--trunk/src/mame/drivers/pokechmp.c297
-rw-r--r--trunk/src/mame/drivers/poker72.c399
-rw-r--r--trunk/src/mame/drivers/polepos.c2018
-rw-r--r--trunk/src/mame/drivers/policetr.c725
-rw-r--r--trunk/src/mame/drivers/polyplay.c360
-rw-r--r--trunk/src/mame/drivers/poo.c381
-rw-r--r--trunk/src/mame/drivers/poolshrk.c262
-rw-r--r--trunk/src/mame/drivers/pooyan.c346
-rw-r--r--trunk/src/mame/drivers/popeye.c671
-rw-r--r--trunk/src/mame/drivers/popper.c403
-rw-r--r--trunk/src/mame/drivers/portrait.c388
-rw-r--r--trunk/src/mame/drivers/powerbal.c707
-rw-r--r--trunk/src/mame/drivers/powerins.c725
-rw-r--r--trunk/src/mame/drivers/ppmast93.c415
-rw-r--r--trunk/src/mame/drivers/prehisle.c362
-rw-r--r--trunk/src/mame/drivers/proconn.c720
-rw-r--r--trunk/src/mame/drivers/progolf.c571
-rw-r--r--trunk/src/mame/drivers/psattack.c224
-rw-r--r--trunk/src/mame/drivers/psikyo.c2059
-rw-r--r--trunk/src/mame/drivers/psikyo4.c997
-rw-r--r--trunk/src/mame/drivers/psikyosh.c1281
-rw-r--r--trunk/src/mame/drivers/psychic5.c913
-rw-r--r--trunk/src/mame/drivers/pturn.c558
-rw-r--r--trunk/src/mame/drivers/puckpkmn.c342
-rw-r--r--trunk/src/mame/drivers/punchout.c1369
-rw-r--r--trunk/src/mame/drivers/pushman.c702
-rw-r--r--trunk/src/mame/drivers/pzletime.c385
-rw-r--r--trunk/src/mame/drivers/qdrmfgp.c803
-rw-r--r--trunk/src/mame/drivers/qix.c1345
-rw-r--r--trunk/src/mame/drivers/quakeat.c201
-rw-r--r--trunk/src/mame/drivers/quantum.c340
-rw-r--r--trunk/src/mame/drivers/quasar.c437
-rw-r--r--trunk/src/mame/drivers/queen.c114
-rw-r--r--trunk/src/mame/drivers/quizdna.c579
-rw-r--r--trunk/src/mame/drivers/quizo.c267
-rw-r--r--trunk/src/mame/drivers/quizpani.c251
-rw-r--r--trunk/src/mame/drivers/quizpun2.c593
-rw-r--r--trunk/src/mame/drivers/r2dtank.c599
-rw-r--r--trunk/src/mame/drivers/r2dx_v33.c871
-rw-r--r--trunk/src/mame/drivers/rabbit.c1036
-rw-r--r--trunk/src/mame/drivers/raiden.c605
-rw-r--r--trunk/src/mame/drivers/raiden2.c2673
-rw-r--r--trunk/src/mame/drivers/rainbow.c909
-rw-r--r--trunk/src/mame/drivers/rallyx.c1419
-rw-r--r--trunk/src/mame/drivers/rampart.c499
-rw-r--r--trunk/src/mame/drivers/rastan.c615
-rw-r--r--trunk/src/mame/drivers/rbmk.c593
-rw-r--r--trunk/src/mame/drivers/rcorsair.c162
-rw-r--r--trunk/src/mame/drivers/re900.c474
-rw-r--r--trunk/src/mame/drivers/realbrk.c1174
-rw-r--r--trunk/src/mame/drivers/redalert.c542
-rw-r--r--trunk/src/mame/drivers/redclash.c565
-rw-r--r--trunk/src/mame/drivers/relief.c483
-rw-r--r--trunk/src/mame/drivers/renegade.c1102
-rw-r--r--trunk/src/mame/drivers/retofinv.c502
-rw-r--r--trunk/src/mame/drivers/rgum.c317
-rw-r--r--trunk/src/mame/drivers/rltennis.c234
-rw-r--r--trunk/src/mame/drivers/rmhaihai.c688
-rw-r--r--trunk/src/mame/drivers/rockrage.c433
-rw-r--r--trunk/src/mame/drivers/rocnrope.c357
-rw-r--r--trunk/src/mame/drivers/rohga.c1566
-rw-r--r--trunk/src/mame/drivers/rollerg.c385
-rw-r--r--trunk/src/mame/drivers/rollrace.c396
-rw-r--r--trunk/src/mame/drivers/rotaryf.c194
-rw-r--r--trunk/src/mame/drivers/roul.c319
-rw-r--r--trunk/src/mame/drivers/route16.c1021
-rw-r--r--trunk/src/mame/drivers/rowamet.c55
-rw-r--r--trunk/src/mame/drivers/royalmah.c4741
-rw-r--r--trunk/src/mame/drivers/rpunch.c726
-rw-r--r--trunk/src/mame/drivers/runaway.c434
-rw-r--r--trunk/src/mame/drivers/rungun.c668
-rw-r--r--trunk/src/mame/drivers/s11.c198
-rw-r--r--trunk/src/mame/drivers/s11a.c188
-rw-r--r--trunk/src/mame/drivers/s11b.c914
-rw-r--r--trunk/src/mame/drivers/s11c.c359
-rw-r--r--trunk/src/mame/drivers/s3.c118
-rw-r--r--trunk/src/mame/drivers/s4.c248
-rw-r--r--trunk/src/mame/drivers/s6.c351
-rw-r--r--trunk/src/mame/drivers/s6a.c120
-rw-r--r--trunk/src/mame/drivers/s7.c434
-rw-r--r--trunk/src/mame/drivers/s8.c64
-rw-r--r--trunk/src/mame/drivers/s9.c157
-rw-r--r--trunk/src/mame/drivers/safarir.c487
-rw-r--r--trunk/src/mame/drivers/sandscrp.c583
-rw-r--r--trunk/src/mame/drivers/sangho.c480
-rw-r--r--trunk/src/mame/drivers/saturn.c2455
-rw-r--r--trunk/src/mame/drivers/sauro.c567
-rw-r--r--trunk/src/mame/drivers/savquest.c94
-rw-r--r--trunk/src/mame/drivers/sbasketb.c397
-rw-r--r--trunk/src/mame/drivers/sbowling.c417
-rw-r--r--trunk/src/mame/drivers/sbrkout.c590
-rw-r--r--trunk/src/mame/drivers/sbugger.c280
-rw-r--r--trunk/src/mame/drivers/scobra.c1206
-rw-r--r--trunk/src/mame/drivers/scotrsht.c248
-rw-r--r--trunk/src/mame/drivers/scramble.c1986
-rw-r--r--trunk/src/mame/drivers/scregg.c407
-rw-r--r--trunk/src/mame/drivers/sderby.c655
-rw-r--r--trunk/src/mame/drivers/seattle.c3014
-rw-r--r--trunk/src/mame/drivers/segac2.c2267
-rw-r--r--trunk/src/mame/drivers/segae.c1012
-rw-r--r--trunk/src/mame/drivers/segag80r.c1596
-rw-r--r--trunk/src/mame/drivers/segag80v.c1435
-rw-r--r--trunk/src/mame/drivers/segahang.c1909
-rw-r--r--trunk/src/mame/drivers/segald.c610
-rw-r--r--trunk/src/mame/drivers/segaorun.c2231
-rw-r--r--trunk/src/mame/drivers/segas16a.c3543
-rw-r--r--trunk/src/mame/drivers/segas16b.c7267
-rw-r--r--trunk/src/mame/drivers/segas18.c2334
-rw-r--r--trunk/src/mame/drivers/segas24.c2512
-rw-r--r--trunk/src/mame/drivers/segas32.c4271
-rw-r--r--trunk/src/mame/drivers/segaxbd.c2893
-rw-r--r--trunk/src/mame/drivers/segaybd.c2270
-rw-r--r--trunk/src/mame/drivers/seibuspi.c3625
-rw-r--r--trunk/src/mame/drivers/seicross.c593
-rw-r--r--trunk/src/mame/drivers/sengokmj.c362
-rw-r--r--trunk/src/mame/drivers/senjyo.c936
-rw-r--r--trunk/src/mame/drivers/seta.c10782
-rw-r--r--trunk/src/mame/drivers/seta2.c3190
-rw-r--r--trunk/src/mame/drivers/sf.c1249
-rw-r--r--trunk/src/mame/drivers/sfbonus.c6181
-rw-r--r--trunk/src/mame/drivers/sfcbox.c341
-rw-r--r--trunk/src/mame/drivers/sfkick.c602
-rw-r--r--trunk/src/mame/drivers/sg1000a.c349
-rw-r--r--trunk/src/mame/drivers/shadfrce.c684
-rw-r--r--trunk/src/mame/drivers/shangha3.c674
-rw-r--r--trunk/src/mame/drivers/shanghai.c645
-rw-r--r--trunk/src/mame/drivers/shangkid.c985
-rw-r--r--trunk/src/mame/drivers/shaolins.c344
-rw-r--r--trunk/src/mame/drivers/shisen.c437
-rw-r--r--trunk/src/mame/drivers/shootout.c435
-rw-r--r--trunk/src/mame/drivers/shougi.c480
-rw-r--r--trunk/src/mame/drivers/shuuz.c377
-rw-r--r--trunk/src/mame/drivers/sidearms.c1187
-rw-r--r--trunk/src/mame/drivers/sidepckt.c395
-rw-r--r--trunk/src/mame/drivers/sigmab52.c689
-rw-r--r--trunk/src/mame/drivers/sigmab98.c2140
-rw-r--r--trunk/src/mame/drivers/silkroad.c389
-rw-r--r--trunk/src/mame/drivers/simpl156.c1151
-rw-r--r--trunk/src/mame/drivers/simpsons.c555
-rw-r--r--trunk/src/mame/drivers/skeetsht.c300
-rw-r--r--trunk/src/mame/drivers/skimaxx.c617
-rw-r--r--trunk/src/mame/drivers/skullxbo.c639
-rw-r--r--trunk/src/mame/drivers/skyarmy.c323
-rw-r--r--trunk/src/mame/drivers/skydiver.c439
-rw-r--r--trunk/src/mame/drivers/skyfox.c456
-rw-r--r--trunk/src/mame/drivers/skykid.c645
-rw-r--r--trunk/src/mame/drivers/skylncr.c872
-rw-r--r--trunk/src/mame/drivers/skyraid.c285
-rw-r--r--trunk/src/mame/drivers/slapfght.c1884
-rw-r--r--trunk/src/mame/drivers/slapshot.c768
-rw-r--r--trunk/src/mame/drivers/sleic.c65
-rw-r--r--trunk/src/mame/drivers/sliver.c634
-rw-r--r--trunk/src/mame/drivers/slotcarn.c765
-rw-r--r--trunk/src/mame/drivers/sms.c932
-rw-r--r--trunk/src/mame/drivers/snesb.c855
-rw-r--r--trunk/src/mame/drivers/snk.c6310
-rw-r--r--trunk/src/mame/drivers/snk6502.c1469
-rw-r--r--trunk/src/mame/drivers/snk68.c1019
-rw-r--r--trunk/src/mame/drivers/snookr10.c801
-rw-r--r--trunk/src/mame/drivers/snowbros.c2731
-rw-r--r--trunk/src/mame/drivers/solomon.c292
-rw-r--r--trunk/src/mame/drivers/sonson.c354
-rw-r--r--trunk/src/mame/drivers/sothello.c434
-rw-r--r--trunk/src/mame/drivers/spacefb.c568
-rw-r--r--trunk/src/mame/drivers/spaceg.c473
-rw-r--r--trunk/src/mame/drivers/spbactn.c424
-rw-r--r--trunk/src/mame/drivers/spcforce.c358
-rw-r--r--trunk/src/mame/drivers/spdodgeb.c590
-rw-r--r--trunk/src/mame/drivers/speedatk.c384
-rw-r--r--trunk/src/mame/drivers/speedbal.c287
-rw-r--r--trunk/src/mame/drivers/speedspn.c343
-rw-r--r--trunk/src/mame/drivers/speglsht.c447
-rw-r--r--trunk/src/mame/drivers/spiders.c839
-rw-r--r--trunk/src/mame/drivers/spinb.c125
-rw-r--r--trunk/src/mame/drivers/splash.c1125
-rw-r--r--trunk/src/mame/drivers/splus.c543
-rw-r--r--trunk/src/mame/drivers/spoker.c722
-rw-r--r--trunk/src/mame/drivers/spool99.c427
-rw-r--r--trunk/src/mame/drivers/sprcros2.c383
-rw-r--r--trunk/src/mame/drivers/sprint2.c666
-rw-r--r--trunk/src/mame/drivers/sprint4.c472
-rw-r--r--trunk/src/mame/drivers/sprint8.c536
-rw-r--r--trunk/src/mame/drivers/spy.c657
-rw-r--r--trunk/src/mame/drivers/srmp2.c1589
-rw-r--r--trunk/src/mame/drivers/srmp5.c631
-rw-r--r--trunk/src/mame/drivers/srmp6.c725
-rw-r--r--trunk/src/mame/drivers/srumbler.c421
-rw-r--r--trunk/src/mame/drivers/ssfindo.c884
-rw-r--r--trunk/src/mame/drivers/sshangha.c518
-rw-r--r--trunk/src/mame/drivers/ssingles.c558
-rw-r--r--trunk/src/mame/drivers/sslam.c955
-rw-r--r--trunk/src/mame/drivers/ssozumo.c274
-rw-r--r--trunk/src/mame/drivers/sspeedr.c233
-rw-r--r--trunk/src/mame/drivers/ssrj.c198
-rw-r--r--trunk/src/mame/drivers/sstrangr.c299
-rw-r--r--trunk/src/mame/drivers/ssv.c4727
-rw-r--r--trunk/src/mame/drivers/st0016.c704
-rw-r--r--trunk/src/mame/drivers/st_mp100.c170
-rw-r--r--trunk/src/mame/drivers/st_mp200.c359
-rw-r--r--trunk/src/mame/drivers/stactics.c356
-rw-r--r--trunk/src/mame/drivers/stadhero.c297
-rw-r--r--trunk/src/mame/drivers/starcrus.c198
-rw-r--r--trunk/src/mame/drivers/starfire.c405
-rw-r--r--trunk/src/mame/drivers/starshp1.c403
-rw-r--r--trunk/src/mame/drivers/starwars.c559
-rw-r--r--trunk/src/mame/drivers/statriv2.c1153
-rw-r--r--trunk/src/mame/drivers/stellafr.c61
-rw-r--r--trunk/src/mame/drivers/stepstag.c366
-rw-r--r--trunk/src/mame/drivers/stfight.c812
-rw-r--r--trunk/src/mame/drivers/stlforce.c381
-rw-r--r--trunk/src/mame/drivers/strnskil.c528
-rw-r--r--trunk/src/mame/drivers/stv.c2248
-rw-r--r--trunk/src/mame/drivers/sub.c492
-rw-r--r--trunk/src/mame/drivers/subs.c252
-rw-r--r--trunk/src/mame/drivers/subsino.c3593
-rw-r--r--trunk/src/mame/drivers/subsino2.c2763
-rw-r--r--trunk/src/mame/drivers/summit.c338
-rw-r--r--trunk/src/mame/drivers/suna16.c1254
-rw-r--r--trunk/src/mame/drivers/suna8.c2404
-rw-r--r--trunk/src/mame/drivers/supbtime.c512
-rw-r--r--trunk/src/mame/drivers/supdrapo.c600
-rw-r--r--trunk/src/mame/drivers/superchs.c470
-rw-r--r--trunk/src/mame/drivers/superdq.c419
-rw-r--r--trunk/src/mame/drivers/superqix.c1439
-rw-r--r--trunk/src/mame/drivers/supertnk.c502
-rw-r--r--trunk/src/mame/drivers/superwng.c521
-rw-r--r--trunk/src/mame/drivers/suprgolf.c648
-rw-r--r--trunk/src/mame/drivers/suprloco.c296
-rw-r--r--trunk/src/mame/drivers/suprnova.c1734
-rw-r--r--trunk/src/mame/drivers/suprridr.c447
-rw-r--r--trunk/src/mame/drivers/suprslam.c394
-rw-r--r--trunk/src/mame/drivers/surpratk.c344
-rw-r--r--trunk/src/mame/drivers/system1.c4778
-rw-r--r--trunk/src/mame/drivers/system16.c3611
-rw-r--r--trunk/src/mame/drivers/tagteam.c299
-rw-r--r--trunk/src/mame/drivers/tail2nos.c354
-rw-r--r--trunk/src/mame/drivers/taito.c634
-rw-r--r--trunk/src/mame/drivers/taito_b.c3564
-rw-r--r--trunk/src/mame/drivers/taito_f2.c5442
-rw-r--r--trunk/src/mame/drivers/taito_f3.c4166
-rw-r--r--trunk/src/mame/drivers/taito_h.c834
-rw-r--r--trunk/src/mame/drivers/taito_l.c2791
-rw-r--r--trunk/src/mame/drivers/taito_o.c299
-rw-r--r--trunk/src/mame/drivers/taito_x.c1240
-rw-r--r--trunk/src/mame/drivers/taito_z.c4921
-rw-r--r--trunk/src/mame/drivers/taitoair.c834
-rw-r--r--trunk/src/mame/drivers/taitogn.c1363
-rw-r--r--trunk/src/mame/drivers/taitojc.c1988
-rw-r--r--trunk/src/mame/drivers/taitopjc.c161
-rw-r--r--trunk/src/mame/drivers/taitosj.c2796
-rw-r--r--trunk/src/mame/drivers/taitotz.c201
-rw-r--r--trunk/src/mame/drivers/taitowlf.c769
-rw-r--r--trunk/src/mame/drivers/tank8.c492
-rw-r--r--trunk/src/mame/drivers/tankbatt.c347
-rw-r--r--trunk/src/mame/drivers/tankbust.c421
-rw-r--r--trunk/src/mame/drivers/taotaido.c421
-rw-r--r--trunk/src/mame/drivers/tapatune.c430
-rw-r--r--trunk/src/mame/drivers/targeth.c235
-rw-r--r--trunk/src/mame/drivers/tatsumi.c1392
-rw-r--r--trunk/src/mame/drivers/tattack.c275
-rw-r--r--trunk/src/mame/drivers/taxidrvr.c460
-rw-r--r--trunk/src/mame/drivers/tbowl.c681
-rw-r--r--trunk/src/mame/drivers/tceptor.c567
-rw-r--r--trunk/src/mame/drivers/tcl.c221
-rw-r--r--trunk/src/mame/drivers/techno.c44
-rw-r--r--trunk/src/mame/drivers/tecmo.c1151
-rw-r--r--trunk/src/mame/drivers/tecmo16.c635
-rw-r--r--trunk/src/mame/drivers/tecmosys.c676
-rw-r--r--trunk/src/mame/drivers/tehkanwc.c916
-rw-r--r--trunk/src/mame/drivers/tempest.c815
-rw-r--r--trunk/src/mame/drivers/terracre.c1045
-rw-r--r--trunk/src/mame/drivers/tetrisp2.c1861
-rw-r--r--trunk/src/mame/drivers/tgtpanic.c167
-rw-r--r--trunk/src/mame/drivers/thayers.c851
-rw-r--r--trunk/src/mame/drivers/thedeep.c484
-rw-r--r--trunk/src/mame/drivers/thepit.c1086
-rw-r--r--trunk/src/mame/drivers/thief.c658
-rw-r--r--trunk/src/mame/drivers/thoop2.c233
-rw-r--r--trunk/src/mame/drivers/thunderj.c427
-rw-r--r--trunk/src/mame/drivers/thunderx.c1029
-rw-r--r--trunk/src/mame/drivers/tiamc1.c335
-rw-r--r--trunk/src/mame/drivers/tickee.c1142
-rw-r--r--trunk/src/mame/drivers/tigeroad.c785
-rw-r--r--trunk/src/mame/drivers/timelimt.c353
-rw-r--r--trunk/src/mame/drivers/timeplt.c594
-rw-r--r--trunk/src/mame/drivers/timetrv.c178
-rw-r--r--trunk/src/mame/drivers/tmaster.c1908
-rw-r--r--trunk/src/mame/drivers/tmmjprd.c856
-rw-r--r--trunk/src/mame/drivers/tmnt.c4361
-rw-r--r--trunk/src/mame/drivers/tnzs.c2748
-rw-r--r--trunk/src/mame/drivers/toaplan1.c2597
-rw-r--r--trunk/src/mame/drivers/toaplan2.c5248
-rw-r--r--trunk/src/mame/drivers/toki.c866
-rw-r--r--trunk/src/mame/drivers/tokyocop.c78
-rw-r--r--trunk/src/mame/drivers/tomcat.c436
-rw-r--r--trunk/src/mame/drivers/toobin.c624
-rw-r--r--trunk/src/mame/drivers/topspeed.c880
-rw-r--r--trunk/src/mame/drivers/toratora.c459
-rw-r--r--trunk/src/mame/drivers/tourtabl.c229
-rw-r--r--trunk/src/mame/drivers/toypop.c673
-rw-r--r--trunk/src/mame/drivers/tp84.c435
-rw-r--r--trunk/src/mame/drivers/trackfld.c1493
-rw-r--r--trunk/src/mame/drivers/travrusa.c487
-rw-r--r--trunk/src/mame/drivers/triforce.c679
-rw-r--r--trunk/src/mame/drivers/triplhnt.c369
-rw-r--r--trunk/src/mame/drivers/truco.c176
-rw-r--r--trunk/src/mame/drivers/trucocl.c194
-rw-r--r--trunk/src/mame/drivers/trvmadns.c397
-rw-r--r--trunk/src/mame/drivers/trvquest.c265
-rw-r--r--trunk/src/mame/drivers/tryout.c246
-rw-r--r--trunk/src/mame/drivers/tsamurai.c1223
-rw-r--r--trunk/src/mame/drivers/ttchamp.c342
-rw-r--r--trunk/src/mame/drivers/tubep.c1214
-rw-r--r--trunk/src/mame/drivers/tugboat.c460
-rw-r--r--trunk/src/mame/drivers/tumbleb.c3793
-rw-r--r--trunk/src/mame/drivers/tumblep.c414
-rw-r--r--trunk/src/mame/drivers/tunhunt.c425
-rw-r--r--trunk/src/mame/drivers/turbo.c1811
-rw-r--r--trunk/src/mame/drivers/turrett.c148
-rw-r--r--trunk/src/mame/drivers/tutankhm.c321
-rw-r--r--trunk/src/mame/drivers/twin16.c1364
-rw-r--r--trunk/src/mame/drivers/twincobr.c1025
-rw-r--r--trunk/src/mame/drivers/twinkle.c1110
-rw-r--r--trunk/src/mame/drivers/twins.c334
-rw-r--r--trunk/src/mame/drivers/tx1.c1249
-rw-r--r--trunk/src/mame/drivers/uapce.c250
-rw-r--r--trunk/src/mame/drivers/ultraman.c307
-rw-r--r--trunk/src/mame/drivers/ultratnk.c352
-rw-r--r--trunk/src/mame/drivers/ultrsprt.c273
-rw-r--r--trunk/src/mame/drivers/undrfire.c1026
-rw-r--r--trunk/src/mame/drivers/unico.c1048
-rw-r--r--trunk/src/mame/drivers/unkpcp.c171
-rw-r--r--trunk/src/mame/drivers/upscope.c416
-rw-r--r--trunk/src/mame/drivers/usgames.c395
-rw-r--r--trunk/src/mame/drivers/vamphalf.c1997
-rw-r--r--trunk/src/mame/drivers/vaportra.c873
-rw-r--r--trunk/src/mame/drivers/vastar.c415
-rw-r--r--trunk/src/mame/drivers/vball.c543
-rw-r--r--trunk/src/mame/drivers/vcombat.c707
-rw-r--r--trunk/src/mame/drivers/vd.c51
-rw-r--r--trunk/src/mame/drivers/vectrex.c234
-rw-r--r--trunk/src/mame/drivers/vega.c149
-rw-r--r--trunk/src/mame/drivers/vegaeo.c287
-rw-r--r--trunk/src/mame/drivers/vegas.c2600
-rw-r--r--trunk/src/mame/drivers/vendetta.c822
-rw-r--r--trunk/src/mame/drivers/vertigo.c215
-rw-r--r--trunk/src/mame/drivers/vicdual.c3470
-rw-r--r--trunk/src/mame/drivers/victory.c321
-rw-r--r--trunk/src/mame/drivers/videopin.c401
-rw-r--r--trunk/src/mame/drivers/videopkr.c1459
-rw-r--r--trunk/src/mame/drivers/vigilant.c923
-rw-r--r--trunk/src/mame/drivers/vindictr.c564
-rw-r--r--trunk/src/mame/drivers/viper.c1636
-rw-r--r--trunk/src/mame/drivers/vmetal.c516
-rw-r--r--trunk/src/mame/drivers/volfied.c429
-rw-r--r--trunk/src/mame/drivers/vp101.c107
-rw-r--r--trunk/src/mame/drivers/vpoker.c727
-rw-r--r--trunk/src/mame/drivers/vroulet.c328
-rw-r--r--trunk/src/mame/drivers/vsnes.c2686
-rw-r--r--trunk/src/mame/drivers/vulgus.c374
-rw-r--r--trunk/src/mame/drivers/wallc.c358
-rw-r--r--trunk/src/mame/drivers/wardner.c623
-rw-r--r--trunk/src/mame/drivers/warpsped.c365
-rw-r--r--trunk/src/mame/drivers/warpwarp.c1004
-rw-r--r--trunk/src/mame/drivers/warriorb.c898
-rw-r--r--trunk/src/mame/drivers/wc90.c488
-rw-r--r--trunk/src/mame/drivers/wc90b.c548
-rw-r--r--trunk/src/mame/drivers/wecleman.c1430
-rw-r--r--trunk/src/mame/drivers/welltris.c840
-rw-r--r--trunk/src/mame/drivers/wgp.c1292
-rw-r--r--trunk/src/mame/drivers/wheelfir.c872
-rw-r--r--trunk/src/mame/drivers/white_mod.c2625
-rw-r--r--trunk/src/mame/drivers/whitestar.c3384
-rw-r--r--trunk/src/mame/drivers/wico.c50
-rw-r--r--trunk/src/mame/drivers/williams.c2956
-rw-r--r--trunk/src/mame/drivers/wink.c433
-rw-r--r--trunk/src/mame/drivers/wiping.c385
-rw-r--r--trunk/src/mame/drivers/witch.c876
-rw-r--r--trunk/src/mame/drivers/wiz.c1106
-rw-r--r--trunk/src/mame/drivers/wldarrow.c496
-rw-r--r--trunk/src/mame/drivers/wolfpack.c349
-rw-r--r--trunk/src/mame/drivers/wpc_95.c927
-rw-r--r--trunk/src/mame/drivers/wpc_an.c380
-rw-r--r--trunk/src/mame/drivers/wpc_dcs.c667
-rw-r--r--trunk/src/mame/drivers/wpc_dot.c412
-rw-r--r--trunk/src/mame/drivers/wpc_flip1.c132
-rw-r--r--trunk/src/mame/drivers/wpc_flip2.c755
-rw-r--r--trunk/src/mame/drivers/wpc_s.c1218
-rw-r--r--trunk/src/mame/drivers/wrally.c367
-rw-r--r--trunk/src/mame/drivers/wwfsstar.c688
-rw-r--r--trunk/src/mame/drivers/wwfwfest.c604
-rw-r--r--trunk/src/mame/drivers/xain.c814
-rw-r--r--trunk/src/mame/drivers/xexex.c707
-rw-r--r--trunk/src/mame/drivers/xmen.c825
-rw-r--r--trunk/src/mame/drivers/xorworld.c242
-rw-r--r--trunk/src/mame/drivers/xtheball.c387
-rw-r--r--trunk/src/mame/drivers/xtom3d.c111
-rw-r--r--trunk/src/mame/drivers/xxmissio.c359
-rw-r--r--trunk/src/mame/drivers/xybots.c414
-rw-r--r--trunk/src/mame/drivers/xyonix.c267
-rw-r--r--trunk/src/mame/drivers/yiear.c351
-rw-r--r--trunk/src/mame/drivers/yunsun16.c963
-rw-r--r--trunk/src/mame/drivers/yunsung8.c705
-rw-r--r--trunk/src/mame/drivers/zac2650.c317
-rw-r--r--trunk/src/mame/drivers/zac_1.c192
-rw-r--r--trunk/src/mame/drivers/zac_2.c914
-rw-r--r--trunk/src/mame/drivers/zac_proto.c74
-rw-r--r--trunk/src/mame/drivers/zaccaria.c795
-rw-r--r--trunk/src/mame/drivers/zaxxon.c1564
-rw-r--r--trunk/src/mame/drivers/zerozone.c266
-rw-r--r--trunk/src/mame/drivers/zn.c4653
-rw-r--r--trunk/src/mame/drivers/zodiack.c729
-rw-r--r--trunk/src/mame/drivers/zr107.c1014
-rw-r--r--trunk/src/mame/etc/fd1094dp.c587
-rw-r--r--trunk/src/mame/etc/jrcrypt.c528
-rw-r--r--trunk/src/mame/includes/1942.h41
-rw-r--r--trunk/src/mame/includes/1943.h43
-rw-r--r--trunk/src/mame/includes/20pacgal.h44
-rw-r--r--trunk/src/mame/includes/3do.h202
-rw-r--r--trunk/src/mame/includes/40love.h71
-rw-r--r--trunk/src/mame/includes/4enraya.h31
-rw-r--r--trunk/src/mame/includes/8080bw.h105
-rw-r--r--trunk/src/mame/includes/88games.h45
-rw-r--r--trunk/src/mame/includes/actfancr.h42
-rw-r--r--trunk/src/mame/includes/aeroboto.h52
-rw-r--r--trunk/src/mame/includes/aerofgt.h78
-rw-r--r--trunk/src/mame/includes/airbustr.h55
-rw-r--r--trunk/src/mame/includes/ajax.h48
-rw-r--r--trunk/src/mame/includes/aliens.h38
-rw-r--r--trunk/src/mame/includes/alpha68k.h74
-rw-r--r--trunk/src/mame/includes/ambush.h28
-rw-r--r--trunk/src/mame/includes/amiga.h500
-rw-r--r--trunk/src/mame/includes/ampoker2.h18
-rw-r--r--trunk/src/mame/includes/amspdwy.h41
-rw-r--r--trunk/src/mame/includes/angelkds.h52
-rw-r--r--trunk/src/mame/includes/appoooh.h47
-rw-r--r--trunk/src/mame/includes/aquarium.h39
-rw-r--r--trunk/src/mame/includes/arabian.h40
-rw-r--r--trunk/src/mame/includes/arcadecl.h23
-rw-r--r--trunk/src/mame/includes/archimds.h130
-rw-r--r--trunk/src/mame/includes/argus.h76
-rw-r--r--trunk/src/mame/includes/arkanoid.h84
-rw-r--r--trunk/src/mame/includes/armedf.h66
-rw-r--r--trunk/src/mame/includes/artmagic.h46
-rw-r--r--trunk/src/mame/includes/ashnojoe.h57
-rw-r--r--trunk/src/mame/includes/asterix.h45
-rw-r--r--trunk/src/mame/includes/asteroid.h55
-rw-r--r--trunk/src/mame/includes/astrocde.h109
-rw-r--r--trunk/src/mame/includes/astrof.h50
-rw-r--r--trunk/src/mame/includes/asuka.h55
-rw-r--r--trunk/src/mame/includes/atari.h603
-rw-r--r--trunk/src/mame/includes/atarifb.h93
-rw-r--r--trunk/src/mame/includes/atarig1.h43
-rw-r--r--trunk/src/mame/includes/atarig42.h46
-rw-r--r--trunk/src/mame/includes/atarigt.h61
-rw-r--r--trunk/src/mame/includes/atarigx2.h41
-rw-r--r--trunk/src/mame/includes/atarisy1.h63
-rw-r--r--trunk/src/mame/includes/atarisy2.h63
-rw-r--r--trunk/src/mame/includes/atetris.h29
-rw-r--r--trunk/src/mame/includes/avalnche.h30
-rw-r--r--trunk/src/mame/includes/aztarac.h38
-rw-r--r--trunk/src/mame/includes/badlands.h29
-rw-r--r--trunk/src/mame/includes/bagman.h67
-rw-r--r--trunk/src/mame/includes/balsente.h190
-rw-r--r--trunk/src/mame/includes/bankp.h45
-rw-r--r--trunk/src/mame/includes/baraduke.h33
-rw-r--r--trunk/src/mame/includes/batman.h26
-rw-r--r--trunk/src/mame/includes/battlane.h40
-rw-r--r--trunk/src/mame/includes/battlera.h42
-rw-r--r--trunk/src/mame/includes/battlex.h37
-rw-r--r--trunk/src/mame/includes/battlnts.h34
-rw-r--r--trunk/src/mame/includes/bbusters.h36
-rw-r--r--trunk/src/mame/includes/beathead.h79
-rw-r--r--trunk/src/mame/includes/beezer.h39
-rw-r--r--trunk/src/mame/includes/bigevglf.h80
-rw-r--r--trunk/src/mame/includes/bigstrkb.h27
-rw-r--r--trunk/src/mame/includes/bionicc.h42
-rw-r--r--trunk/src/mame/includes/bishi.h41
-rw-r--r--trunk/src/mame/includes/bking.h75
-rw-r--r--trunk/src/mame/includes/bladestl.h38
-rw-r--r--trunk/src/mame/includes/blktiger.h57
-rw-r--r--trunk/src/mame/includes/blmbycar.h41
-rw-r--r--trunk/src/mame/includes/blockade.h35
-rw-r--r--trunk/src/mame/includes/blockhl.h38
-rw-r--r--trunk/src/mame/includes/blockout.h35
-rw-r--r--trunk/src/mame/includes/bloodbro.h28
-rw-r--r--trunk/src/mame/includes/blstroid.h24
-rw-r--r--trunk/src/mame/includes/blueprnt.h40
-rw-r--r--trunk/src/mame/includes/bogeyman.h43
-rw-r--r--trunk/src/mame/includes/bombjack.h38
-rw-r--r--trunk/src/mame/includes/boogwing.h44
-rw-r--r--trunk/src/mame/includes/bottom9.h44
-rw-r--r--trunk/src/mame/includes/brkthru.h42
-rw-r--r--trunk/src/mame/includes/bsktball.h72
-rw-r--r--trunk/src/mame/includes/btime.h85
-rw-r--r--trunk/src/mame/includes/btoads.h115
-rw-r--r--trunk/src/mame/includes/bublbobl.h110
-rw-r--r--trunk/src/mame/includes/buggychl.h50
-rw-r--r--trunk/src/mame/includes/bwing.h64
-rw-r--r--trunk/src/mame/includes/bzone.h33
-rw-r--r--trunk/src/mame/includes/cabal.h25
-rw-r--r--trunk/src/mame/includes/calomega.h23
-rw-r--r--trunk/src/mame/includes/canyon.h49
-rw-r--r--trunk/src/mame/includes/capbowl.h40
-rw-r--r--trunk/src/mame/includes/carjmbre.h37
-rw-r--r--trunk/src/mame/includes/carpolo.h97
-rw-r--r--trunk/src/mame/includes/cave.h144
-rw-r--r--trunk/src/mame/includes/cbasebal.h47
-rw-r--r--trunk/src/mame/includes/cbuster.h41
-rw-r--r--trunk/src/mame/includes/ccastles.h65
-rw-r--r--trunk/src/mame/includes/cchasm.h50
-rw-r--r--trunk/src/mame/includes/cchip.h9
-rw-r--r--trunk/src/mame/includes/cclimber.h54
-rw-r--r--trunk/src/mame/includes/cd32.h31
-rw-r--r--trunk/src/mame/includes/cdi.h42
-rw-r--r--trunk/src/mame/includes/centiped.h50
-rw-r--r--trunk/src/mame/includes/chaknpop.h57
-rw-r--r--trunk/src/mame/includes/champbas.h52
-rw-r--r--trunk/src/mame/includes/changela.h70
-rw-r--r--trunk/src/mame/includes/cheekyms.h35
-rw-r--r--trunk/src/mame/includes/chqflag.h45
-rw-r--r--trunk/src/mame/includes/cidelsa.h108
-rw-r--r--trunk/src/mame/includes/cinemat.h81
-rw-r--r--trunk/src/mame/includes/circus.h52
-rw-r--r--trunk/src/mame/includes/circusc.h45
-rw-r--r--trunk/src/mame/includes/cischeat.h66
-rw-r--r--trunk/src/mame/includes/citycon.h38
-rw-r--r--trunk/src/mame/includes/cloak.h39
-rw-r--r--trunk/src/mame/includes/cloud9.h58
-rw-r--r--trunk/src/mame/includes/clshroad.h28
-rw-r--r--trunk/src/mame/includes/cninja.h54
-rw-r--r--trunk/src/mame/includes/combatsc.h61
-rw-r--r--trunk/src/mame/includes/commando.h44
-rw-r--r--trunk/src/mame/includes/compgolf.h37
-rw-r--r--trunk/src/mame/includes/contra.h56
-rw-r--r--trunk/src/mame/includes/coolpool.h34
-rw-r--r--trunk/src/mame/includes/cop01.h44
-rw-r--r--trunk/src/mame/includes/copsnrob.h44
-rw-r--r--trunk/src/mame/includes/cosmic.h60
-rw-r--r--trunk/src/mame/includes/cps1.h214
-rw-r--r--trunk/src/mame/includes/cps3.h69
-rw-r--r--trunk/src/mame/includes/crbaloon.h49
-rw-r--r--trunk/src/mame/includes/crgolf.h42
-rw-r--r--trunk/src/mame/includes/crimfght.h34
-rw-r--r--trunk/src/mame/includes/crospang.h49
-rw-r--r--trunk/src/mame/includes/crshrace.h39
-rw-r--r--trunk/src/mame/includes/cvs.h119
-rw-r--r--trunk/src/mame/includes/cyberbal.h62
-rw-r--r--trunk/src/mame/includes/darius.h72
-rw-r--r--trunk/src/mame/includes/darkmist.h25
-rw-r--r--trunk/src/mame/includes/darkseal.h30
-rw-r--r--trunk/src/mame/includes/dassault.h45
-rw-r--r--trunk/src/mame/includes/dbz.h48
-rw-r--r--trunk/src/mame/includes/dc.h329
-rw-r--r--trunk/src/mame/includes/dcheese.h53
-rw-r--r--trunk/src/mame/includes/dcon.h36
-rw-r--r--trunk/src/mame/includes/dday.h49
-rw-r--r--trunk/src/mame/includes/ddragon.h72
-rw-r--r--trunk/src/mame/includes/ddragon3.h48
-rw-r--r--trunk/src/mame/includes/ddribble.h47
-rw-r--r--trunk/src/mame/includes/deadang.h27
-rw-r--r--trunk/src/mame/includes/dec0.h72
-rw-r--r--trunk/src/mame/includes/dec8.h84
-rw-r--r--trunk/src/mame/includes/deco32.h95
-rw-r--r--trunk/src/mame/includes/deco_mlc.h27
-rw-r--r--trunk/src/mame/includes/decocrpt.h15
-rw-r--r--trunk/src/mame/includes/decoprot.h29
-rw-r--r--trunk/src/mame/includes/deniam.h57
-rw-r--r--trunk/src/mame/includes/dietgo.h30
-rw-r--r--trunk/src/mame/includes/djboy.h57
-rw-r--r--trunk/src/mame/includes/djmain.h26
-rw-r--r--trunk/src/mame/includes/dkong.h233
-rw-r--r--trunk/src/mame/includes/docastle.h53
-rw-r--r--trunk/src/mame/includes/dogfgt.h49
-rw-r--r--trunk/src/mame/includes/dooyong.h81
-rw-r--r--trunk/src/mame/includes/dragrace.h54
-rw-r--r--trunk/src/mame/includes/drgnmst.h50
-rw-r--r--trunk/src/mame/includes/dribling.h38
-rw-r--r--trunk/src/mame/includes/drmicro.h37
-rw-r--r--trunk/src/mame/includes/dynax.h240
-rw-r--r--trunk/src/mame/includes/dynduke.h35
-rw-r--r--trunk/src/mame/includes/eolith.h18
-rw-r--r--trunk/src/mame/includes/eolithsp.h6
-rw-r--r--trunk/src/mame/includes/epos.h28
-rw-r--r--trunk/src/mame/includes/eprom.h30
-rw-r--r--trunk/src/mame/includes/equites.h80
-rw-r--r--trunk/src/mame/includes/esd16.h49
-rw-r--r--trunk/src/mame/includes/espial.h45
-rw-r--r--trunk/src/mame/includes/esripsys.h78
-rw-r--r--trunk/src/mame/includes/exedexes.h44
-rw-r--r--trunk/src/mame/includes/exerion.h61
-rw-r--r--trunk/src/mame/includes/exidy.h57
-rw-r--r--trunk/src/mame/includes/exidy440.h57
-rw-r--r--trunk/src/mame/includes/exprraid.h45
-rw-r--r--trunk/src/mame/includes/exterm.h33
-rw-r--r--trunk/src/mame/includes/exzisus.h33
-rw-r--r--trunk/src/mame/includes/f1gp.h59
-rw-r--r--trunk/src/mame/includes/fantland.h37
-rw-r--r--trunk/src/mame/includes/fastfred.h51
-rw-r--r--trunk/src/mame/includes/fastlane.h41
-rw-r--r--trunk/src/mame/includes/fcombat.h62
-rw-r--r--trunk/src/mame/includes/fgoal.h39
-rw-r--r--trunk/src/mame/includes/finalizr.h46
-rw-r--r--trunk/src/mame/includes/firetrap.h59
-rw-r--r--trunk/src/mame/includes/firetrk.h91
-rw-r--r--trunk/src/mame/includes/fitfight.h39
-rw-r--r--trunk/src/mame/includes/flkatck.h40
-rw-r--r--trunk/src/mame/includes/flower.h40
-rw-r--r--trunk/src/mame/includes/flstory.h107
-rw-r--r--trunk/src/mame/includes/foodf.h35
-rw-r--r--trunk/src/mame/includes/freekick.h34
-rw-r--r--trunk/src/mame/includes/fromanc2.h78
-rw-r--r--trunk/src/mame/includes/fromance.h77
-rw-r--r--trunk/src/mame/includes/funkybee.h29
-rw-r--r--trunk/src/mame/includes/funkyjet.h30
-rw-r--r--trunk/src/mame/includes/funworld.h20
-rw-r--r--trunk/src/mame/includes/funybubl.h26
-rw-r--r--trunk/src/mame/includes/fuukifg2.h38
-rw-r--r--trunk/src/mame/includes/fuukifg3.h52
-rw-r--r--trunk/src/mame/includes/gaelco.h37
-rw-r--r--trunk/src/mame/includes/gaelco2.h46
-rw-r--r--trunk/src/mame/includes/gaelco3d.h61
-rw-r--r--trunk/src/mame/includes/gaelcrpt.h3
-rw-r--r--trunk/src/mame/includes/gaiden.h76
-rw-r--r--trunk/src/mame/includes/galaga.h159
-rw-r--r--trunk/src/mame/includes/galastrm.h44
-rw-r--r--trunk/src/mame/includes/galaxian.h164
-rw-r--r--trunk/src/mame/includes/galaxold.h184
-rw-r--r--trunk/src/mame/includes/galivan.h52
-rw-r--r--trunk/src/mame/includes/galpani2.h37
-rw-r--r--trunk/src/mame/includes/galpanic.h27
-rw-r--r--trunk/src/mame/includes/galpnipt.h157
-rw-r--r--trunk/src/mame/includes/galspnbl.h32
-rw-r--r--trunk/src/mame/includes/gameplan.h64
-rw-r--r--trunk/src/mame/includes/gaplus.h39
-rw-r--r--trunk/src/mame/includes/gatron.h18
-rw-r--r--trunk/src/mame/includes/gauntlet.h28
-rw-r--r--trunk/src/mame/includes/gberet.h42
-rw-r--r--trunk/src/mame/includes/gbusters.h39
-rw-r--r--trunk/src/mame/includes/gcpinbal.h54
-rw-r--r--trunk/src/mame/includes/genesis.h13
-rw-r--r--trunk/src/mame/includes/gijoe.h45
-rw-r--r--trunk/src/mame/includes/ginganin.h45
-rw-r--r--trunk/src/mame/includes/gladiatr.h43
-rw-r--r--trunk/src/mame/includes/glass.h37
-rw-r--r--trunk/src/mame/includes/gng.h38
-rw-r--r--trunk/src/mame/includes/goal92.h50
-rw-r--r--trunk/src/mame/includes/goindol.h42
-rw-r--r--trunk/src/mame/includes/goldstar.h68
-rw-r--r--trunk/src/mame/includes/gomoku.h37
-rw-r--r--trunk/src/mame/includes/gotcha.h42
-rw-r--r--trunk/src/mame/includes/gottlieb.h85
-rw-r--r--trunk/src/mame/includes/gotya.h40
-rw-r--r--trunk/src/mame/includes/gradius3.h44
-rw-r--r--trunk/src/mame/includes/grchamp.h66
-rw-r--r--trunk/src/mame/includes/gridlee.h63
-rw-r--r--trunk/src/mame/includes/groundfx.h32
-rw-r--r--trunk/src/mame/includes/gstriker.h80
-rw-r--r--trunk/src/mame/includes/gsword.h35
-rw-r--r--trunk/src/mame/includes/gumbo.h30
-rw-r--r--trunk/src/mame/includes/gunbustr.h29
-rw-r--r--trunk/src/mame/includes/gundealr.h41
-rw-r--r--trunk/src/mame/includes/gunsmoke.h41
-rw-r--r--trunk/src/mame/includes/gyruss.h35
-rw-r--r--trunk/src/mame/includes/hanaawas.h33
-rw-r--r--trunk/src/mame/includes/harddriv.h361
-rw-r--r--trunk/src/mame/includes/hcastle.h47
-rw-r--r--trunk/src/mame/includes/hexion.h26
-rw-r--r--trunk/src/mame/includes/higemaru.h32
-rw-r--r--trunk/src/mame/includes/himesiki.h35
-rw-r--r--trunk/src/mame/includes/hitme.h34
-rw-r--r--trunk/src/mame/includes/hnayayoi.h35
-rw-r--r--trunk/src/mame/includes/hng64.h106
-rw-r--r--trunk/src/mame/includes/holeland.h38
-rw-r--r--trunk/src/mame/includes/homedata.h73
-rw-r--r--trunk/src/mame/includes/homerun.h38
-rw-r--r--trunk/src/mame/includes/hyhoo.h29
-rw-r--r--trunk/src/mame/includes/hyperspt.h31
-rw-r--r--trunk/src/mame/includes/hyprduel.h67
-rw-r--r--trunk/src/mame/includes/ikki.h33
-rw-r--r--trunk/src/mame/includes/inufuku.h46
-rw-r--r--trunk/src/mame/includes/iqblock.h25
-rw-r--r--trunk/src/mame/includes/iremipt.h300
-rw-r--r--trunk/src/mame/includes/irobot.h92
-rw-r--r--trunk/src/mame/includes/ironhors.h45
-rw-r--r--trunk/src/mame/includes/itech32.h112
-rw-r--r--trunk/src/mame/includes/itech8.h97
-rw-r--r--trunk/src/mame/includes/jack.h49
-rw-r--r--trunk/src/mame/includes/jackal.h38
-rw-r--r--trunk/src/mame/includes/jaguar.h72
-rw-r--r--trunk/src/mame/includes/jailbrek.h40
-rw-r--r--trunk/src/mame/includes/jedi.h66
-rw-r--r--trunk/src/mame/includes/jpmimpct.h87
-rw-r--r--trunk/src/mame/includes/kaneko16.h190
-rw-r--r--trunk/src/mame/includes/kangaroo.h34
-rw-r--r--trunk/src/mame/includes/karnov.h60
-rw-r--r--trunk/src/mame/includes/kchamp.h43
-rw-r--r--trunk/src/mame/includes/kickgoal.h56
-rw-r--r--trunk/src/mame/includes/kingobox.h51
-rw-r--r--trunk/src/mame/includes/klax.h22
-rw-r--r--trunk/src/mame/includes/kncljoe.h43
-rw-r--r--trunk/src/mame/includes/konamigx.h113
-rw-r--r--trunk/src/mame/includes/konamipt.h440
-rw-r--r--trunk/src/mame/includes/kopunch.h39
-rw-r--r--trunk/src/mame/includes/ksayakyu.h35
-rw-r--r--trunk/src/mame/includes/kyugo.h51
-rw-r--r--trunk/src/mame/includes/labyrunr.h39
-rw-r--r--trunk/src/mame/includes/ladybug.h83
-rw-r--r--trunk/src/mame/includes/ladyfrog.h54
-rw-r--r--trunk/src/mame/includes/laserbat.h65
-rw-r--r--trunk/src/mame/includes/lasso.h56
-rw-r--r--trunk/src/mame/includes/lastduel.h48
-rw-r--r--trunk/src/mame/includes/lazercmd.h46
-rw-r--r--trunk/src/mame/includes/legionna.h43
-rw-r--r--trunk/src/mame/includes/leland.h192
-rw-r--r--trunk/src/mame/includes/lemmings.h37
-rw-r--r--trunk/src/mame/includes/lethal.h40
-rw-r--r--trunk/src/mame/includes/lethalj.h32
-rw-r--r--trunk/src/mame/includes/liberate.h50
-rw-r--r--trunk/src/mame/includes/liberatr.h93
-rw-r--r--trunk/src/mame/includes/lkage.h74
-rw-r--r--trunk/src/mame/includes/lockon.h96
-rw-r--r--trunk/src/mame/includes/lordgun.h49
-rw-r--r--trunk/src/mame/includes/lsasquad.h68
-rw-r--r--trunk/src/mame/includes/lucky74.h32
-rw-r--r--trunk/src/mame/includes/lvcards.h24
-rw-r--r--trunk/src/mame/includes/lwings.h47
-rw-r--r--trunk/src/mame/includes/m10.h77
-rw-r--r--trunk/src/mame/includes/m107.h41
-rw-r--r--trunk/src/mame/includes/m52.h39
-rw-r--r--trunk/src/mame/includes/m57.h26
-rw-r--r--trunk/src/mame/includes/m58.h30
-rw-r--r--trunk/src/mame/includes/m62.h80
-rw-r--r--trunk/src/mame/includes/m72.h69
-rw-r--r--trunk/src/mame/includes/m79amb.h9
-rw-r--r--trunk/src/mame/includes/m90.h30
-rw-r--r--trunk/src/mame/includes/m92.h54
-rw-r--r--trunk/src/mame/includes/macrossp.h55
-rw-r--r--trunk/src/mame/includes/madalien.h52
-rw-r--r--trunk/src/mame/includes/madmotor.h30
-rw-r--r--trunk/src/mame/includes/magmax.h27
-rw-r--r--trunk/src/mame/includes/mainevt.h43
-rw-r--r--trunk/src/mame/includes/mainsnk.h25
-rw-r--r--trunk/src/mame/includes/malzak.h33
-rw-r--r--trunk/src/mame/includes/mappy.h33
-rw-r--r--trunk/src/mame/includes/marineb.h42
-rw-r--r--trunk/src/mame/includes/mario.h88
-rw-r--r--trunk/src/mame/includes/markham.h31
-rw-r--r--trunk/src/mame/includes/matmania.h72
-rw-r--r--trunk/src/mame/includes/mcatadv.h38
-rw-r--r--trunk/src/mame/includes/mcr.h76
-rw-r--r--trunk/src/mame/includes/mcr3.h42
-rw-r--r--trunk/src/mame/includes/mcr68.h84
-rw-r--r--trunk/src/mame/includes/meadows.h48
-rw-r--r--trunk/src/mame/includes/megadriv.h280
-rw-r--r--trunk/src/mame/includes/megasys1.h70
-rw-r--r--trunk/src/mame/includes/megazone.h46
-rw-r--r--trunk/src/mame/includes/mermaid.h70
-rw-r--r--trunk/src/mame/includes/metalmx.h27
-rw-r--r--trunk/src/mame/includes/metlclsh.h43
-rw-r--r--trunk/src/mame/includes/metro.h101
-rw-r--r--trunk/src/mame/includes/mexico86.h63
-rw-r--r--trunk/src/mame/includes/mhavoc.h72
-rw-r--r--trunk/src/mame/includes/micro3d.h155
-rw-r--r--trunk/src/mame/includes/midtunit.h75
-rw-r--r--trunk/src/mame/includes/midvunit.h68
-rw-r--r--trunk/src/mame/includes/midwunit.h51
-rw-r--r--trunk/src/mame/includes/midxunit.h50
-rw-r--r--trunk/src/mame/includes/midyunit.h111
-rw-r--r--trunk/src/mame/includes/midzeus.h37
-rw-r--r--trunk/src/mame/includes/mikie.h41
-rw-r--r--trunk/src/mame/includes/mitchell.h71
-rw-r--r--trunk/src/mame/includes/mjkjidai.h28
-rw-r--r--trunk/src/mame/includes/model1.h119
-rw-r--r--trunk/src/mame/includes/model2.h76
-rw-r--r--trunk/src/mame/includes/model3.h143
-rw-r--r--trunk/src/mame/includes/momoko.h49
-rw-r--r--trunk/src/mame/includes/moo.h49
-rw-r--r--trunk/src/mame/includes/mosaic.h33
-rw-r--r--trunk/src/mame/includes/mouser.h34
-rw-r--r--trunk/src/mame/includes/mpu4.h253
-rw-r--r--trunk/src/mame/includes/mrdo.h36
-rw-r--r--trunk/src/mame/includes/mrflea.h39
-rw-r--r--trunk/src/mame/includes/mrjong.h30
-rw-r--r--trunk/src/mame/includes/ms32.h51
-rw-r--r--trunk/src/mame/includes/msisaac.h63
-rw-r--r--trunk/src/mame/includes/mugsmash.h29
-rw-r--r--trunk/src/mame/includes/multfish.h31
-rw-r--r--trunk/src/mame/includes/munchmo.h44
-rw-r--r--trunk/src/mame/includes/mustache.h23
-rw-r--r--trunk/src/mame/includes/mw8080bw.h234
-rw-r--r--trunk/src/mame/includes/mystston.h44
-rw-r--r--trunk/src/mame/includes/mystwarr.h44
-rw-r--r--trunk/src/mame/includes/n64.h106
-rw-r--r--trunk/src/mame/includes/n8080.h76
-rw-r--r--trunk/src/mame/includes/namcofl.h35
-rw-r--r--trunk/src/mame/includes/namcoic.h173
-rw-r--r--trunk/src/mame/includes/namcona1.h67
-rw-r--r--trunk/src/mame/includes/namconb1.h41
-rw-r--r--trunk/src/mame/includes/namcond1.h30
-rw-r--r--trunk/src/mame/includes/namcos1.h106
-rw-r--r--trunk/src/mame/includes/namcos2.h242
-rw-r--r--trunk/src/mame/includes/namcos21.h82
-rw-r--r--trunk/src/mame/includes/namcos22.h145
-rw-r--r--trunk/src/mame/includes/namcos86.h40
-rw-r--r--trunk/src/mame/includes/naomi.h48
-rw-r--r--trunk/src/mame/includes/naughtyb.h27
-rw-r--r--trunk/src/mame/includes/nb1413m3.h159
-rw-r--r--trunk/src/mame/includes/nb1414m4.h1
-rw-r--r--trunk/src/mame/includes/nbmj8688.h61
-rw-r--r--trunk/src/mame/includes/nbmj8891.h56
-rw-r--r--trunk/src/mame/includes/nbmj8900.h47
-rw-r--r--trunk/src/mame/includes/nbmj8991.h39
-rw-r--r--trunk/src/mame/includes/nbmj9195.h72
-rw-r--r--trunk/src/mame/includes/nemesis.h64
-rw-r--r--trunk/src/mame/includes/neogeo.h225
-rw-r--r--trunk/src/mame/includes/news.h27
-rw-r--r--trunk/src/mame/includes/ninjakd2.h63
-rw-r--r--trunk/src/mame/includes/ninjaw.h43
-rw-r--r--trunk/src/mame/includes/nitedrvr.h74
-rw-r--r--trunk/src/mame/includes/niyanpai.h58
-rw-r--r--trunk/src/mame/includes/nmk16.h95
-rw-r--r--trunk/src/mame/includes/norautp.h24
-rw-r--r--trunk/src/mame/includes/nova2001.h36
-rw-r--r--trunk/src/mame/includes/nycaptor.h86
-rw-r--r--trunk/src/mame/includes/offtwall.h27
-rw-r--r--trunk/src/mame/includes/ohmygod.h39
-rw-r--r--trunk/src/mame/includes/ojankohs.h61
-rw-r--r--trunk/src/mame/includes/oneshot.h42
-rw-r--r--trunk/src/mame/includes/opwolf.h70
-rw-r--r--trunk/src/mame/includes/orbit.h55
-rw-r--r--trunk/src/mame/includes/othldrby.h41
-rw-r--r--trunk/src/mame/includes/othunder.h59
-rw-r--r--trunk/src/mame/includes/overdriv.h42
-rw-r--r--trunk/src/mame/includes/pacland.h31
-rw-r--r--trunk/src/mame/includes/pacman.h92
-rw-r--r--trunk/src/mame/includes/pandoras.h47
-rw-r--r--trunk/src/mame/includes/paradise.h48
-rw-r--r--trunk/src/mame/includes/parodius.h40
-rw-r--r--trunk/src/mame/includes/pass.h21
-rw-r--r--trunk/src/mame/includes/pastelg.h38
-rw-r--r--trunk/src/mame/includes/pbaction.h44
-rw-r--r--trunk/src/mame/includes/pcktgal.h19
-rw-r--r--trunk/src/mame/includes/pgm.h160
-rw-r--r--trunk/src/mame/includes/phoenix.h68
-rw-r--r--trunk/src/mame/includes/pingpong.h24
-rw-r--r--trunk/src/mame/includes/pirates.h25
-rw-r--r--trunk/src/mame/includes/pitnrun.h60
-rw-r--r--trunk/src/mame/includes/pk8000.h21
-rw-r--r--trunk/src/mame/includes/pktgaldx.h33
-rw-r--r--trunk/src/mame/includes/playch10.h101
-rw-r--r--trunk/src/mame/includes/playmark.h78
-rw-r--r--trunk/src/mame/includes/plygonet.h45
-rw-r--r--trunk/src/mame/includes/pokechmp.h20
-rw-r--r--trunk/src/mame/includes/polepos.h73
-rw-r--r--trunk/src/mame/includes/policetr.h45
-rw-r--r--trunk/src/mame/includes/polyplay.h43
-rw-r--r--trunk/src/mame/includes/poolshrk.h39
-rw-r--r--trunk/src/mame/includes/pooyan.h33
-rw-r--r--trunk/src/mame/includes/popeye.h37
-rw-r--r--trunk/src/mame/includes/popper.h49
-rw-r--r--trunk/src/mame/includes/portrait.h23
-rw-r--r--trunk/src/mame/includes/powerins.h30
-rw-r--r--trunk/src/mame/includes/prehisle.h27
-rw-r--r--trunk/src/mame/includes/psikyo.h73
-rw-r--r--trunk/src/mame/includes/psikyo4.h38
-rw-r--r--trunk/src/mame/includes/psikyosh.h49
-rw-r--r--trunk/src/mame/includes/psx.h42
-rw-r--r--trunk/src/mame/includes/psychic5.h50
-rw-r--r--trunk/src/mame/includes/punchout.h44
-rw-r--r--trunk/src/mame/includes/pushman.h42
-rw-r--r--trunk/src/mame/includes/qdrmfgp.h23
-rw-r--r--trunk/src/mame/includes/qix.h97
-rw-r--r--trunk/src/mame/includes/quizdna.h30
-rw-r--r--trunk/src/mame/includes/quizpani.h24
-rw-r--r--trunk/src/mame/includes/raiden.h29
-rw-r--r--trunk/src/mame/includes/raiden2.h121
-rw-r--r--trunk/src/mame/includes/rainbow.h55
-rw-r--r--trunk/src/mame/includes/rallyx.h55
-rw-r--r--trunk/src/mame/includes/rampart.h23
-rw-r--r--trunk/src/mame/includes/rastan.h36
-rw-r--r--trunk/src/mame/includes/realbrk.h43
-rw-r--r--trunk/src/mame/includes/redalert.h46
-rw-r--r--trunk/src/mame/includes/relief.h24
-rw-r--r--trunk/src/mame/includes/renegade.h49
-rw-r--r--trunk/src/mame/includes/retofinv.h54
-rw-r--r--trunk/src/mame/includes/rltennis.h54
-rw-r--r--trunk/src/mame/includes/rockrage.h35
-rw-r--r--trunk/src/mame/includes/rocnrope.h26
-rw-r--r--trunk/src/mame/includes/rohga.h52
-rw-r--r--trunk/src/mame/includes/rollerg.h37
-rw-r--r--trunk/src/mame/includes/rollrace.h35
-rw-r--r--trunk/src/mame/includes/route16.h25
-rw-r--r--trunk/src/mame/includes/rpunch.h35
-rw-r--r--trunk/src/mame/includes/runaway.h24
-rw-r--r--trunk/src/mame/includes/rungun.h51
-rw-r--r--trunk/src/mame/includes/sauro.h34
-rw-r--r--trunk/src/mame/includes/sbasketb.h27
-rw-r--r--trunk/src/mame/includes/sbugger.h20
-rw-r--r--trunk/src/mame/includes/scotrsht.h29
-rw-r--r--trunk/src/mame/includes/scramble.h78
-rw-r--r--trunk/src/mame/includes/sderby.h30
-rw-r--r--trunk/src/mame/includes/segag80r.h99
-rw-r--r--trunk/src/mame/includes/segag80v.h43
-rw-r--r--trunk/src/mame/includes/segamsys.h73
-rw-r--r--trunk/src/mame/includes/segas16.h152
-rw-r--r--trunk/src/mame/includes/segas24.h100
-rw-r--r--trunk/src/mame/includes/segas32.h124
-rw-r--r--trunk/src/mame/includes/sei_crtc.h14
-rw-r--r--trunk/src/mame/includes/seibuspi.h72
-rw-r--r--trunk/src/mame/includes/seicross.h30
-rw-r--r--trunk/src/mame/includes/senjyo.h65
-rw-r--r--trunk/src/mame/includes/seta.h118
-rw-r--r--trunk/src/mame/includes/seta2.h39
-rw-r--r--trunk/src/mame/includes/sf.h41
-rw-r--r--trunk/src/mame/includes/shadfrce.h38
-rw-r--r--trunk/src/mame/includes/shangha3.h26
-rw-r--r--trunk/src/mame/includes/shangkid.h25
-rw-r--r--trunk/src/mame/includes/shaolins.h28
-rw-r--r--trunk/src/mame/includes/shisen.h21
-rw-r--r--trunk/src/mame/includes/shootout.h24
-rw-r--r--trunk/src/mame/includes/shuuz.h22
-rw-r--r--trunk/src/mame/includes/sidearms.h40
-rw-r--r--trunk/src/mame/includes/sidepckt.h29
-rw-r--r--trunk/src/mame/includes/silkroad.h24
-rw-r--r--trunk/src/mame/includes/simpl156.h41
-rw-r--r--trunk/src/mame/includes/simpsons.h48
-rw-r--r--trunk/src/mame/includes/skullxbo.h27
-rw-r--r--trunk/src/mame/includes/skydiver.h56
-rw-r--r--trunk/src/mame/includes/skyfox.h36
-rw-r--r--trunk/src/mame/includes/skykid.h31
-rw-r--r--trunk/src/mame/includes/skyraid.h32
-rw-r--r--trunk/src/mame/includes/slapfght.h135
-rw-r--r--trunk/src/mame/includes/slapshot.h62
-rw-r--r--trunk/src/mame/includes/slapstic.h18
-rw-r--r--trunk/src/mame/includes/snes.h696
-rw-r--r--trunk/src/mame/includes/snk.h109
-rw-r--r--trunk/src/mame/includes/snk6502.h84
-rw-r--r--trunk/src/mame/includes/snk68.h33
-rw-r--r--trunk/src/mame/includes/snookr10.h30
-rw-r--r--trunk/src/mame/includes/snowbros.h17
-rw-r--r--trunk/src/mame/includes/solomon.h28
-rw-r--r--trunk/src/mame/includes/sonson.h40
-rw-r--r--trunk/src/mame/includes/spacefb.h62
-rw-r--r--trunk/src/mame/includes/spbactn.h19
-rw-r--r--trunk/src/mame/includes/spcforce.h19
-rw-r--r--trunk/src/mame/includes/spdodgeb.h43
-rw-r--r--trunk/src/mame/includes/speedatk.h27
-rw-r--r--trunk/src/mame/includes/speedbal.h21
-rw-r--r--trunk/src/mame/includes/speedspn.h25
-rw-r--r--trunk/src/mame/includes/spiders.h33
-rw-r--r--trunk/src/mame/includes/splash.h39
-rw-r--r--trunk/src/mame/includes/sprcros2.h27
-rw-r--r--trunk/src/mame/includes/sprint2.h62
-rw-r--r--trunk/src/mame/includes/sprint4.h27
-rw-r--r--trunk/src/mame/includes/sprint8.h48
-rw-r--r--trunk/src/mame/includes/spy.h44
-rw-r--r--trunk/src/mame/includes/srmp2.h35
-rw-r--r--trunk/src/mame/includes/srumbler.h24
-rw-r--r--trunk/src/mame/includes/sshangha.h32
-rw-r--r--trunk/src/mame/includes/sslam.h43
-rw-r--r--trunk/src/mame/includes/ssozumo.h32
-rw-r--r--trunk/src/mame/includes/sspeedr.h41
-rw-r--r--trunk/src/mame/includes/ssrj.h27
-rw-r--r--trunk/src/mame/includes/ssv.h68
-rw-r--r--trunk/src/mame/includes/st0016.h50
-rw-r--r--trunk/src/mame/includes/stactics.h53
-rw-r--r--trunk/src/mame/includes/stadhero.h19
-rw-r--r--trunk/src/mame/includes/starcrus.h58
-rw-r--r--trunk/src/mame/includes/starfire.h44
-rw-r--r--trunk/src/mame/includes/starshp1.h94
-rw-r--r--trunk/src/mame/includes/starwars.h77
-rw-r--r--trunk/src/mame/includes/stfight.h50
-rw-r--r--trunk/src/mame/includes/stlforce.h34
-rw-r--r--trunk/src/mame/includes/strnskil.h23
-rw-r--r--trunk/src/mame/includes/stv.h228
-rw-r--r--trunk/src/mame/includes/subs.h64
-rw-r--r--trunk/src/mame/includes/suna16.h25
-rw-r--r--trunk/src/mame/includes/suna8.h60
-rw-r--r--trunk/src/mame/includes/supbtime.h32
-rw-r--r--trunk/src/mame/includes/superchs.h31
-rw-r--r--trunk/src/mame/includes/superqix.h47
-rw-r--r--trunk/src/mame/includes/suprloco.h24
-rw-r--r--trunk/src/mame/includes/suprnova.h84
-rw-r--r--trunk/src/mame/includes/suprridr.h41
-rw-r--r--trunk/src/mame/includes/suprslam.h44
-rw-r--r--trunk/src/mame/includes/surpratk.h37
-rw-r--r--trunk/src/mame/includes/system1.h53
-rw-r--r--trunk/src/mame/includes/system16.h127
-rw-r--r--trunk/src/mame/includes/tagteam.h27
-rw-r--r--trunk/src/mame/includes/tail2nos.h43
-rw-r--r--trunk/src/mame/includes/taito_b.h55
-rw-r--r--trunk/src/mame/includes/taito_f2.h128
-rw-r--r--trunk/src/mame/includes/taito_f3.h220
-rw-r--r--trunk/src/mame/includes/taito_h.h31
-rw-r--r--trunk/src/mame/includes/taito_l.h87
-rw-r--r--trunk/src/mame/includes/taito_o.h23
-rw-r--r--trunk/src/mame/includes/taito_z.h65
-rw-r--r--trunk/src/mame/includes/taitoair.h57
-rw-r--r--trunk/src/mame/includes/taitoipt.h379
-rw-r--r--trunk/src/mame/includes/taitojc.h116
-rw-r--r--trunk/src/mame/includes/taitosj.h76
-rw-r--r--trunk/src/mame/includes/tank8.h64
-rw-r--r--trunk/src/mame/includes/tankbatt.h22
-rw-r--r--trunk/src/mame/includes/tankbust.h38
-rw-r--r--trunk/src/mame/includes/taotaido.h29
-rw-r--r--trunk/src/mame/includes/targ.h16
-rw-r--r--trunk/src/mame/includes/targeth.h18
-rw-r--r--trunk/src/mame/includes/tatsumi.h108
-rw-r--r--trunk/src/mame/includes/taxidrvr.h31
-rw-r--r--trunk/src/mame/includes/tbowl.h41
-rw-r--r--trunk/src/mame/includes/tceptor.h42
-rw-r--r--trunk/src/mame/includes/tecmo.h34
-rw-r--r--trunk/src/mame/includes/tecmo16.h50
-rw-r--r--trunk/src/mame/includes/tecmosys.h64
-rw-r--r--trunk/src/mame/includes/tehkanwc.h37
-rw-r--r--trunk/src/mame/includes/terracre.h29
-rw-r--r--trunk/src/mame/includes/tetrisp2.h73
-rw-r--r--trunk/src/mame/includes/thedeep.h32
-rw-r--r--trunk/src/mame/includes/thepit.h35
-rw-r--r--trunk/src/mame/includes/thief.h38
-rw-r--r--trunk/src/mame/includes/thoop2.h20
-rw-r--r--trunk/src/mame/includes/thunderj.h22
-rw-r--r--trunk/src/mame/includes/thunderx.h44
-rw-r--r--trunk/src/mame/includes/tiamc1.h47
-rw-r--r--trunk/src/mame/includes/tigeroad.h22
-rw-r--r--trunk/src/mame/includes/timelimt.h30
-rw-r--r--trunk/src/mame/includes/timeplt.h40
-rw-r--r--trunk/src/mame/includes/tmnt.h109
-rw-r--r--trunk/src/mame/includes/tnzs.h91
-rw-r--r--trunk/src/mame/includes/toaplan1.h156
-rw-r--r--trunk/src/mame/includes/toaplan2.h82
-rw-r--r--trunk/src/mame/includes/toaplipt.h350
-rw-r--r--trunk/src/mame/includes/toki.h29
-rw-r--r--trunk/src/mame/includes/toobin.h31
-rw-r--r--trunk/src/mame/includes/topspeed.h43
-rw-r--r--trunk/src/mame/includes/toypop.h28
-rw-r--r--trunk/src/mame/includes/tp84.h30
-rw-r--r--trunk/src/mame/includes/trackfld.h44
-rw-r--r--trunk/src/mame/includes/travrusa.h27
-rw-r--r--trunk/src/mame/includes/triplhnt.h58
-rw-r--r--trunk/src/mame/includes/truco.h16
-rw-r--r--trunk/src/mame/includes/trucocl.h21
-rw-r--r--trunk/src/mame/includes/tryout.h29
-rw-r--r--trunk/src/mame/includes/tsamurai.h45
-rw-r--r--trunk/src/mame/includes/tubep.h63
-rw-r--r--trunk/src/mame/includes/tumbleb.h73
-rw-r--r--trunk/src/mame/includes/tumblep.h30
-rw-r--r--trunk/src/mame/includes/tunhunt.h21
-rw-r--r--trunk/src/mame/includes/turbo.h117
-rw-r--r--trunk/src/mame/includes/tutankhm.h31
-rw-r--r--trunk/src/mame/includes/twin16.h47
-rw-r--r--trunk/src/mame/includes/twincobr.h125
-rw-r--r--trunk/src/mame/includes/tx1.h181
-rw-r--r--trunk/src/mame/includes/ultraman.h44
-rw-r--r--trunk/src/mame/includes/ultratnk.h29
-rw-r--r--trunk/src/mame/includes/undrfire.h34
-rw-r--r--trunk/src/mame/includes/unico.h32
-rw-r--r--trunk/src/mame/includes/usgames.h19
-rw-r--r--trunk/src/mame/includes/vaportra.h37
-rw-r--r--trunk/src/mame/includes/vastar.h35
-rw-r--r--trunk/src/mame/includes/vball.h31
-rw-r--r--trunk/src/mame/includes/vectrex.h103
-rw-r--r--trunk/src/mame/includes/vendetta.h42
-rw-r--r--trunk/src/mame/includes/vertigo.h127
-rw-r--r--trunk/src/mame/includes/vicdual.h86
-rw-r--r--trunk/src/mame/includes/victory.h68
-rw-r--r--trunk/src/mame/includes/videopin.h47
-rw-r--r--trunk/src/mame/includes/vigilant.h30
-rw-r--r--trunk/src/mame/includes/vindictr.h28
-rw-r--r--trunk/src/mame/includes/volfied.h58
-rw-r--r--trunk/src/mame/includes/vsnes.h81
-rw-r--r--trunk/src/mame/includes/vulgus.h28
-rw-r--r--trunk/src/mame/includes/warpwarp.h49
-rw-r--r--trunk/src/mame/includes/warriorb.h39
-rw-r--r--trunk/src/mame/includes/wc90.h37
-rw-r--r--trunk/src/mame/includes/wc90b.h32
-rw-r--r--trunk/src/mame/includes/wecleman.h56
-rw-r--r--trunk/src/mame/includes/welltris.h33
-rw-r--r--trunk/src/mame/includes/wgp.h59
-rw-r--r--trunk/src/mame/includes/williams.h152
-rw-r--r--trunk/src/mame/includes/wiping.h23
-rw-r--r--trunk/src/mame/includes/wiz.h40
-rw-r--r--trunk/src/mame/includes/wolfpack.h45
-rw-r--r--trunk/src/mame/includes/wrally.h27
-rw-r--r--trunk/src/mame/includes/wwfsstar.h23
-rw-r--r--trunk/src/mame/includes/wwfwfest.h31
-rw-r--r--trunk/src/mame/includes/xain.h48
-rw-r--r--trunk/src/mame/includes/xexex.h58
-rw-r--r--trunk/src/mame/includes/xmen.h48
-rw-r--r--trunk/src/mame/includes/xorworld.h19
-rw-r--r--trunk/src/mame/includes/xxmissio.h31
-rw-r--r--trunk/src/mame/includes/xybots.h22
-rw-r--r--trunk/src/mame/includes/xyonix.h22
-rw-r--r--trunk/src/mame/includes/yiear.h27
-rw-r--r--trunk/src/mame/includes/yunsun16.h40
-rw-r--r--trunk/src/mame/includes/yunsung8.h41
-rw-r--r--trunk/src/mame/includes/zac2650.h25
-rw-r--r--trunk/src/mame/includes/zaccaria.h29
-rw-r--r--trunk/src/mame/includes/zaxxon.h77
-rw-r--r--trunk/src/mame/includes/zerozone.h32
-rw-r--r--trunk/src/mame/includes/zodiack.h41
-rw-r--r--trunk/src/mame/layout/18w.lay58
-rw-r--r--trunk/src/mame/layout/280zzzap.lay69
-rw-r--r--trunk/src/mame/layout/3bagflnz.lay316
-rw-r--r--trunk/src/mame/layout/3bagflvt.lay351
-rw-r--r--trunk/src/mame/layout/abaseb.lay72
-rw-r--r--trunk/src/mame/layout/ampoker2.lay136
-rw-r--r--trunk/src/mame/layout/arcwins.lay351
-rw-r--r--trunk/src/mame/layout/arimk4nz.lay351
-rw-r--r--trunk/src/mame/layout/aristmk4.lay351
-rw-r--r--trunk/src/mame/layout/armora.lay186
-rw-r--r--trunk/src/mame/layout/atarifb.lay72
-rw-r--r--trunk/src/mame/layout/atarifb4.lay88
-rw-r--r--trunk/src/mame/layout/avalnche.lay34
-rw-r--r--trunk/src/mame/layout/awpdmd.lay2212
-rw-r--r--trunk/src/mame/layout/awpvid14.lay1298
-rw-r--r--trunk/src/mame/layout/awpvid16.lay1298
-rw-r--r--trunk/src/mame/layout/babydad.lay256
-rw-r--r--trunk/src/mame/layout/babypkr.lay258
-rw-r--r--trunk/src/mame/layout/bfm_sc1.lay2091
-rw-r--r--trunk/src/mame/layout/bfm_sc2.lay911
-rw-r--r--trunk/src/mame/layout/bigdeal.lay140
-rw-r--r--trunk/src/mame/layout/blckjack.lay137
-rw-r--r--trunk/src/mame/layout/blockade.lay32
-rw-r--r--trunk/src/mame/layout/buckrog.lay142
-rw-r--r--trunk/src/mame/layout/buggybjr.lay72
-rw-r--r--trunk/src/mame/layout/buggyboy.lay107
-rw-r--r--trunk/src/mame/layout/buggychl.lay69
-rw-r--r--trunk/src/mame/layout/bzone.lay22
-rw-r--r--trunk/src/mame/layout/cardline.lay112
-rw-r--r--trunk/src/mame/layout/cbombers.lay69
-rw-r--r--trunk/src/mame/layout/cdi.lay36
-rw-r--r--trunk/src/mame/layout/cgold2.lay316
-rw-r--r--trunk/src/mame/layout/changela.lay69
-rw-r--r--trunk/src/mame/layout/chqflag.lay69
-rw-r--r--trunk/src/mame/layout/circus.lay34
-rw-r--r--trunk/src/mame/layout/cischeat.lay69
-rw-r--r--trunk/src/mame/layout/clowns.lay35
-rw-r--r--trunk/src/mame/layout/connect4.lay713
-rw-r--r--trunk/src/mame/layout/contcirc.lay69
-rw-r--r--trunk/src/mame/layout/copsnrob.lay26
-rw-r--r--trunk/src/mame/layout/cosmicm.lay26
-rw-r--r--trunk/src/mame/layout/crash.lay34
-rw-r--r--trunk/src/mame/layout/crmaze2p.lay71
-rw-r--r--trunk/src/mame/layout/crmaze4p.lay102
-rw-r--r--trunk/src/mame/layout/crsbingo.lay156
-rw-r--r--trunk/src/mame/layout/crusnexo.lay183
-rw-r--r--trunk/src/mame/layout/darius.lay70
-rw-r--r--trunk/src/mame/layout/dblaxle.lay69
-rw-r--r--trunk/src/mame/layout/deadeye.lay42
-rw-r--r--trunk/src/mame/layout/depthch.lay20
-rw-r--r--trunk/src/mame/layout/destroyr.lay69
-rw-r--r--trunk/src/mame/layout/dlair.lay83
-rw-r--r--trunk/src/mame/layout/drwho.lay2432
-rw-r--r--trunk/src/mame/layout/eforest.lay351
-rw-r--r--trunk/src/mame/layout/elecyoyo.lay24
-rw-r--r--trunk/src/mame/layout/f1gpstar.lay69
-rw-r--r--trunk/src/mame/layout/fashion.lay105
-rw-r--r--trunk/src/mame/layout/fhunter.lay316
-rw-r--r--trunk/src/mame/layout/finallap.lay69
-rw-r--r--trunk/src/mame/layout/firebeat.lay11
-rw-r--r--trunk/src/mame/layout/galaxi.lay105
-rw-r--r--trunk/src/mame/layout/gamball.lay2047
-rw-r--r--trunk/src/mame/layout/geebee.lay76
-rw-r--r--trunk/src/mame/layout/gldncrwn.lay187
-rw-r--r--trunk/src/mame/layout/gldnpkr.lay299
-rw-r--r--trunk/src/mame/layout/goldenc.lay351
-rw-r--r--trunk/src/mame/layout/goldnpkr.lay148
-rw-r--r--trunk/src/mame/layout/gorf.lay170
-rw-r--r--trunk/src/mame/layout/grchamp.lay69
-rw-r--r--trunk/src/mame/layout/gridiron.lay25
-rw-r--r--trunk/src/mame/layout/gypsyjug.lay46
-rw-r--r--trunk/src/mame/layout/igspoker.lay105
-rw-r--r--trunk/src/mame/layout/invad2ct.lay54
-rw-r--r--trunk/src/mame/layout/invaders.lay30
-rw-r--r--trunk/src/mame/layout/invrvnge.lay26
-rw-r--r--trunk/src/mame/layout/jollycrd.lay132
-rw-r--r--trunk/src/mame/layout/kgbird.lay351
-rw-r--r--trunk/src/mame/layout/lagunar.lay69
-rw-r--r--trunk/src/mame/layout/lazercmd.lay38
-rw-r--r--trunk/src/mame/layout/luckgrln.lay212
-rw-r--r--trunk/src/mame/layout/lucky74.lay212
-rw-r--r--trunk/src/mame/layout/lucky8.lay111
-rw-r--r--trunk/src/mame/layout/luckyrlt.lay141
-rw-r--r--trunk/src/mame/layout/majorpkr.lay237
-rw-r--r--trunk/src/mame/layout/maxaflex.lay75
-rw-r--r--trunk/src/mame/layout/mil4000.lay120
-rw-r--r--trunk/src/mame/layout/mpoker.lay153
-rw-r--r--trunk/src/mame/layout/mpu4.lay940
-rw-r--r--trunk/src/mame/layout/mpu4ext.lay1327
-rw-r--r--trunk/src/mame/layout/musicsrt.lay152
-rw-r--r--trunk/src/mame/layout/namcofl.lay69
-rw-r--r--trunk/src/mame/layout/navarone.lay36
-rw-r--r--trunk/src/mame/layout/nbmj8688.lay70
-rw-r--r--trunk/src/mame/layout/neogeo.lay33
-rw-r--r--trunk/src/mame/layout/noraut11.lay229
-rw-r--r--trunk/src/mame/layout/noraut12.lay207
-rw-r--r--trunk/src/mame/layout/outrun.lay69
-rw-r--r--trunk/src/mame/layout/overdriv.lay69
-rw-r--r--trunk/src/mame/layout/paradice.lay172
-rw-r--r--trunk/src/mame/layout/pdrift.lay69
-rw-r--r--trunk/src/mame/layout/pe_bjack.lay267
-rw-r--r--trunk/src/mame/layout/pe_keno.lay195
-rw-r--r--trunk/src/mame/layout/pe_poker.lay219
-rw-r--r--trunk/src/mame/layout/pe_schip.lay31
-rw-r--r--trunk/src/mame/layout/pe_slots.lay180
-rw-r--r--trunk/src/mame/layout/peplus.lay177
-rw-r--r--trunk/src/mame/layout/peyper.lay169
-rw-r--r--trunk/src/mame/layout/pirpok2.lay128
-rw-r--r--trunk/src/mame/layout/pmpoker.lay104
-rw-r--r--trunk/src/mame/layout/pmroulet.lay42
-rw-r--r--trunk/src/mame/layout/poker41.lay162
-rw-r--r--trunk/src/mame/layout/pokio.lay190
-rw-r--r--trunk/src/mame/layout/polepos.lay69
-rw-r--r--trunk/src/mame/layout/pulltabs.lay76
-rw-r--r--trunk/src/mame/layout/pyramid.lay157
-rw-r--r--trunk/src/mame/layout/quintoon.lay172
-rw-r--r--trunk/src/mame/layout/radr.lay69
-rw-r--r--trunk/src/mame/layout/re800.lay141
-rw-r--r--trunk/src/mame/layout/re900.lay256
-rw-r--r--trunk/src/mame/layout/rocknms.lay39
-rw-r--r--trunk/src/mame/layout/roul.lay141
-rw-r--r--trunk/src/mame/layout/roundup5.lay73
-rw-r--r--trunk/src/mame/layout/royalcrd.lay136
-rw-r--r--trunk/src/mame/layout/sbrkout.lay42
-rw-r--r--trunk/src/mame/layout/sderby.lay58
-rw-r--r--trunk/src/mame/layout/sgsafari.lay136
-rw-r--r--trunk/src/mame/layout/sharkpy.lay152
-rw-r--r--trunk/src/mame/layout/sharkpye.lay146
-rw-r--r--trunk/src/mame/layout/shuttlei.lay24
-rw-r--r--trunk/src/mame/layout/sidewndr.lay61
-rw-r--r--trunk/src/mame/layout/sigmapkr.lay136
-rw-r--r--trunk/src/mame/layout/slots.lay187
-rw-r--r--trunk/src/mame/layout/sltblgpo.lay157
-rw-r--r--trunk/src/mame/layout/sltblgtk.lay187
-rw-r--r--trunk/src/mame/layout/smoto.lay164
-rw-r--r--trunk/src/mame/layout/sms1.lay62
-rw-r--r--trunk/src/mame/layout/snookr10.lay124
-rw-r--r--trunk/src/mame/layout/solarq.lay26
-rw-r--r--trunk/src/mame/layout/sos.lay26
-rw-r--r--trunk/src/mame/layout/spacewin.lay121
-rw-r--r--trunk/src/mame/layout/spacwalk.lay57
-rw-r--r--trunk/src/mame/layout/splus.lay148
-rw-r--r--trunk/src/mame/layout/sspeedr.lay199
-rw-r--r--trunk/src/mame/layout/sstrangr.lay69
-rw-r--r--trunk/src/mame/layout/stactics.lay1158
-rw-r--r--trunk/src/mame/layout/starcas.lay30
-rw-r--r--trunk/src/mame/layout/stepstag.lay57
-rw-r--r--trunk/src/mame/layout/stisub.lay143
-rw-r--r--trunk/src/mame/layout/stocker.lay69
-rw-r--r--trunk/src/mame/layout/subroc3d.lay93
-rw-r--r--trunk/src/mame/layout/superchs.lay69
-rw-r--r--trunk/src/mame/layout/tceptor2.lay21
-rw-r--r--trunk/src/mame/layout/tenpindx.lay188
-rw-r--r--trunk/src/mame/layout/tinv2650.lay30
-rw-r--r--trunk/src/mame/layout/tisub.lay152
-rw-r--r--trunk/src/mame/layout/topgear.lay248
-rw-r--r--trunk/src/mame/layout/topracer.lay69
-rw-r--r--trunk/src/mame/layout/topspeed.lay69
-rw-r--r--trunk/src/mame/layout/turbo.lay202
-rw-r--r--trunk/src/mame/layout/turbotag.lay69
-rw-r--r--trunk/src/mame/layout/tx1.lay107
-rw-r--r--trunk/src/mame/layout/victor21.lay144
-rw-r--r--trunk/src/mame/layout/victor5.lay152
-rw-r--r--trunk/src/mame/layout/videocba.lay96
-rw-r--r--trunk/src/mame/layout/videodad.lay181
-rw-r--r--trunk/src/mame/layout/videopin.lay99
-rw-r--r--trunk/src/mame/layout/videopkr.lay236
-rw-r--r--trunk/src/mame/layout/wecleman.lay69
-rw-r--r--trunk/src/mame/layout/wildone.lay316
-rw-r--r--trunk/src/mame/machine/3do.c1031
-rw-r--r--trunk/src/mame/machine/acitya.c209
-rw-r--r--trunk/src/mame/machine/ajax.c239
-rw-r--r--trunk/src/mame/machine/amiga.c1777
-rw-r--r--trunk/src/mame/machine/archimds.c1099
-rw-r--r--trunk/src/mame/machine/arkanoid.c653
-rw-r--r--trunk/src/mame/machine/asic65.c747
-rw-r--r--trunk/src/mame/machine/asic65.h18
-rw-r--r--trunk/src/mame/machine/asteroid.c140
-rw-r--r--trunk/src/mame/machine/atari.c372
-rw-r--r--trunk/src/mame/machine/atari_vg.c157
-rw-r--r--trunk/src/mame/machine/atari_vg.h28
-rw-r--r--trunk/src/mame/machine/atarifb.c347
-rw-r--r--trunk/src/mame/machine/atarigen.c1619
-rw-r--r--trunk/src/mame/machine/atarigen.h383
-rw-r--r--trunk/src/mame/machine/awboard.c330
-rw-r--r--trunk/src/mame/machine/awboard.h61
-rw-r--r--trunk/src/mame/machine/bagman.c238
-rw-r--r--trunk/src/mame/machine/balsente.c1249
-rw-r--r--trunk/src/mame/machine/beezer.c183
-rw-r--r--trunk/src/mame/machine/bfm_bd1.c567
-rw-r--r--trunk/src/mame/machine/bfm_bd1.h22
-rw-r--r--trunk/src/mame/machine/bfm_comn.c69
-rw-r--r--trunk/src/mame/machine/bfm_comn.h3
-rw-r--r--trunk/src/mame/machine/bigevglf.c118
-rw-r--r--trunk/src/mame/machine/bonzeadv.c468
-rw-r--r--trunk/src/mame/machine/bsktball.c170
-rw-r--r--trunk/src/mame/machine/btime.c94
-rw-r--r--trunk/src/mame/machine/bublbobl.c530
-rw-r--r--trunk/src/mame/machine/buggychl.c251
-rw-r--r--trunk/src/mame/machine/buggychl.h7
-rw-r--r--trunk/src/mame/machine/carpolo.c577
-rw-r--r--trunk/src/mame/machine/cchasm.c15
-rw-r--r--trunk/src/mame/machine/cchip.c149
-rw-r--r--trunk/src/mame/machine/cclimber.c122
-rw-r--r--trunk/src/mame/machine/cd32.c929
-rw-r--r--trunk/src/mame/machine/cdi070.c1161
-rw-r--r--trunk/src/mame/machine/cdi070.h253
-rw-r--r--trunk/src/mame/machine/cdicdic.c1276
-rw-r--r--trunk/src/mame/machine/cdicdic.h137
-rw-r--r--trunk/src/mame/machine/cdislave.c533
-rw-r--r--trunk/src/mame/machine/cdislave.h126
-rw-r--r--trunk/src/mame/machine/chaknpop.c147
-rw-r--r--trunk/src/mame/machine/cps2crpt.c1006
-rw-r--r--trunk/src/mame/machine/cx4data.c198
-rw-r--r--trunk/src/mame/machine/cx4fn.c329
-rw-r--r--trunk/src/mame/machine/cx4oam.c306
-rw-r--r--trunk/src/mame/machine/cx4ops.c276
-rw-r--r--trunk/src/mame/machine/dc-ctrl.c110
-rw-r--r--trunk/src/mame/machine/dc-ctrl.h50
-rw-r--r--trunk/src/mame/machine/dc.c845
-rw-r--r--trunk/src/mame/machine/dec0.c421
-rw-r--r--trunk/src/mame/machine/deco102.c93
-rw-r--r--trunk/src/mame/machine/deco156.c134
-rw-r--r--trunk/src/mame/machine/decocass.c2254
-rw-r--r--trunk/src/mame/machine/decocass.h206
-rw-r--r--trunk/src/mame/machine/decocrpt.c664
-rw-r--r--trunk/src/mame/machine/decoprot.c1785
-rw-r--r--trunk/src/mame/machine/docastle.c85
-rw-r--r--trunk/src/mame/machine/fd1089.c442
-rw-r--r--trunk/src/mame/machine/fd1089.h4
-rw-r--r--trunk/src/mame/machine/fd1094.c843
-rw-r--r--trunk/src/mame/machine/fd1094.h15
-rw-r--r--trunk/src/mame/machine/fddebug.c2416
-rw-r--r--trunk/src/mame/machine/fddebug.h4
-rw-r--r--trunk/src/mame/machine/flstory.c287
-rw-r--r--trunk/src/mame/machine/gaelco2.c320
-rw-r--r--trunk/src/mame/machine/gaelco3d.c525
-rw-r--r--trunk/src/mame/machine/gaelco3d.h73
-rw-r--r--trunk/src/mame/machine/gaelcrpt.c152
-rw-r--r--trunk/src/mame/machine/galaxold.c428
-rw-r--r--trunk/src/mame/machine/gaplus.c50
-rw-r--r--trunk/src/mame/machine/gdrom.c875
-rw-r--r--trunk/src/mame/machine/gdrom.h17
-rw-r--r--trunk/src/mame/machine/harddriv.c1910
-rw-r--r--trunk/src/mame/machine/irem_cpu.c657
-rw-r--r--trunk/src/mame/machine/irem_cpu.h18
-rw-r--r--trunk/src/mame/machine/irobot.c994
-rw-r--r--trunk/src/mame/machine/jalcrpt.c252
-rw-r--r--trunk/src/mame/machine/jalcrpt.h7
-rw-r--r--trunk/src/mame/machine/jumpshot.c56
-rw-r--r--trunk/src/mame/machine/jvs13551.c163
-rw-r--r--trunk/src/mame/machine/jvs13551.h60
-rw-r--r--trunk/src/mame/machine/kabuki.c216
-rw-r--r--trunk/src/mame/machine/kaneko16.c2561
-rw-r--r--trunk/src/mame/machine/kanekotb.h286
-rw-r--r--trunk/src/mame/machine/konami1.c58
-rw-r--r--trunk/src/mame/machine/konami1.h1
-rw-r--r--trunk/src/mame/machine/konamigx.c482
-rw-r--r--trunk/src/mame/machine/konppc.c575
-rw-r--r--trunk/src/mame/machine/konppc.h43
-rw-r--r--trunk/src/mame/machine/leland.c1453
-rw-r--r--trunk/src/mame/machine/lkage.c158
-rw-r--r--trunk/src/mame/machine/lsasquad.c231
-rw-r--r--trunk/src/mame/machine/m68kfmly.c217
-rw-r--r--trunk/src/mame/machine/m68kfmly.h18
-rw-r--r--trunk/src/mame/machine/maniach.c154
-rw-r--r--trunk/src/mame/machine/maple-dc.c284
-rw-r--r--trunk/src/mame/machine/maple-dc.h68
-rw-r--r--trunk/src/mame/machine/mapledev.c76
-rw-r--r--trunk/src/mame/machine/mapledev.h47
-rw-r--r--trunk/src/mame/machine/mathbox.c364
-rw-r--r--trunk/src/mame/machine/mathbox.h29
-rw-r--r--trunk/src/mame/machine/mc8123.c419
-rw-r--r--trunk/src/mame/machine/mc8123.h5
-rw-r--r--trunk/src/mame/machine/mcr.c303
-rw-r--r--trunk/src/mame/machine/mcr68.c637
-rw-r--r--trunk/src/mame/machine/md_cart.c2021
-rw-r--r--trunk/src/mame/machine/megadriv.c10145
-rw-r--r--trunk/src/mame/machine/meters.c117
-rw-r--r--trunk/src/mame/machine/meters.h35
-rw-r--r--trunk/src/mame/machine/mexico86.c342
-rw-r--r--trunk/src/mame/machine/mhavoc.c345
-rw-r--r--trunk/src/mame/machine/micro3d.c668
-rw-r--r--trunk/src/mame/machine/midtunit.c654
-rw-r--r--trunk/src/mame/machine/midwayic.c1092
-rw-r--r--trunk/src/mame/machine/midwayic.h55
-rw-r--r--trunk/src/mame/machine/midwunit.c446
-rw-r--r--trunk/src/mame/machine/midxunit.c420
-rw-r--r--trunk/src/mame/machine/midyunit.c634
-rw-r--r--trunk/src/mame/machine/mie.c365
-rw-r--r--trunk/src/mame/machine/mie.h128
-rw-r--r--trunk/src/mame/machine/model1.c2253
-rw-r--r--trunk/src/mame/machine/model3.c353
-rw-r--r--trunk/src/mame/machine/mw8080bw.c124
-rw-r--r--trunk/src/mame/machine/n64.c2146
-rw-r--r--trunk/src/mame/machine/namco06.c305
-rw-r--r--trunk/src/mame/machine/namco06.h37
-rw-r--r--trunk/src/mame/machine/namco50.c309
-rw-r--r--trunk/src/mame/machine/namco50.h20
-rw-r--r--trunk/src/mame/machine/namco51.c457
-rw-r--r--trunk/src/mame/machine/namco51.h27
-rw-r--r--trunk/src/mame/machine/namco53.c209
-rw-r--r--trunk/src/mame/machine/namco53.h28
-rw-r--r--trunk/src/mame/machine/namco62.c102
-rw-r--r--trunk/src/mame/machine/namco62.h27
-rw-r--r--trunk/src/mame/machine/namcoio.c556
-rw-r--r--trunk/src/mame/machine/namcoio.h57
-rw-r--r--trunk/src/mame/machine/namcond1.c115
-rw-r--r--trunk/src/mame/machine/namcos1.c1474
-rw-r--r--trunk/src/mame/machine/namcos2.c840
-rw-r--r--trunk/src/mame/machine/naomi.c350
-rw-r--r--trunk/src/mame/machine/naomibd.c213
-rw-r--r--trunk/src/mame/machine/naomibd.h57
-rw-r--r--trunk/src/mame/machine/naomig1.c257
-rw-r--r--trunk/src/mame/machine/naomig1.h67
-rw-r--r--trunk/src/mame/machine/naomigd.c515
-rw-r--r--trunk/src/mame/machine/naomigd.h61
-rw-r--r--trunk/src/mame/machine/naomim1.c223
-rw-r--r--trunk/src/mame/machine/naomim1.h56
-rw-r--r--trunk/src/mame/machine/naomim2.c839
-rw-r--r--trunk/src/mame/machine/naomim2.h73
-rw-r--r--trunk/src/mame/machine/naomim4.c165
-rw-r--r--trunk/src/mame/machine/naomim4.h47
-rw-r--r--trunk/src/mame/machine/naomirom.c40
-rw-r--r--trunk/src/mame/machine/naomirom.h28
-rw-r--r--trunk/src/mame/machine/nb1413m3.c893
-rw-r--r--trunk/src/mame/machine/nb1414m4.c304
-rw-r--r--trunk/src/mame/machine/neoboot.c1125
-rw-r--r--trunk/src/mame/machine/neocrypt.c1580
-rw-r--r--trunk/src/mame/machine/neoprot.c544
-rw-r--r--trunk/src/mame/machine/nitedrvr.c314
-rw-r--r--trunk/src/mame/machine/nmk004.c1080
-rw-r--r--trunk/src/mame/machine/nmk004.h4
-rw-r--r--trunk/src/mame/machine/nmk112.c169
-rw-r--r--trunk/src/mame/machine/nmk112.h41
-rw-r--r--trunk/src/mame/machine/nycaptor.c132
-rw-r--r--trunk/src/mame/machine/opwolf.c756
-rw-r--r--trunk/src/mame/machine/pacplus.c56
-rw-r--r--trunk/src/mame/machine/pcecommn.c73
-rw-r--r--trunk/src/mame/machine/pcecommn.h34
-rw-r--r--trunk/src/mame/machine/pckeybrd.c1253
-rw-r--r--trunk/src/mame/machine/pcshare.c346
-rw-r--r--trunk/src/mame/machine/pgmcrypt.c1087
-rw-r--r--trunk/src/mame/machine/pgmprot.c1132
-rw-r--r--trunk/src/mame/machine/pitnrun.c159
-rw-r--r--trunk/src/mame/machine/playch10.c1192
-rw-r--r--trunk/src/mame/machine/psx.c90
-rw-r--r--trunk/src/mame/machine/pxa255.h509
-rw-r--r--trunk/src/mame/machine/qix.c552
-rw-r--r--trunk/src/mame/machine/r2crypt.c284
-rw-r--r--trunk/src/mame/machine/rainbow.c837
-rw-r--r--trunk/src/mame/machine/retofinv.c143
-rw-r--r--trunk/src/mame/machine/s16fd.c234
-rw-r--r--trunk/src/mame/machine/s24fd.c183
-rw-r--r--trunk/src/mame/machine/scramble.c676
-rw-r--r--trunk/src/mame/machine/scudsp.c1317
-rw-r--r--trunk/src/mame/machine/scudsp.h10
-rw-r--r--trunk/src/mame/machine/segacrp2.c316
-rw-r--r--trunk/src/mame/machine/segacrp2.h9
-rw-r--r--trunk/src/mame/machine/segacrpt.c1069
-rw-r--r--trunk/src/mame/machine/segacrpt.h25
-rw-r--r--trunk/src/mame/machine/segag80.c338
-rw-r--r--trunk/src/mame/machine/segag80.h3
-rw-r--r--trunk/src/mame/machine/segaic16.c877
-rw-r--r--trunk/src/mame/machine/segaic16.h93
-rw-r--r--trunk/src/mame/machine/segamsys.c1745
-rw-r--r--trunk/src/mame/machine/segas32.c387
-rw-r--r--trunk/src/mame/machine/seibuspi.c400
-rw-r--r--trunk/src/mame/machine/seibuspi.h11
-rw-r--r--trunk/src/mame/machine/seicop.c3058
-rw-r--r--trunk/src/mame/machine/seicop.h22
-rw-r--r--trunk/src/mame/machine/simpsons.c133
-rw-r--r--trunk/src/mame/machine/slapfght.c943
-rw-r--r--trunk/src/mame/machine/slapstic.c1191
-rw-r--r--trunk/src/mame/machine/slikshot.c685
-rw-r--r--trunk/src/mame/machine/smpc.c964
-rw-r--r--trunk/src/mame/machine/smpc.h4
-rw-r--r--trunk/src/mame/machine/snes.c2521
-rw-r--r--trunk/src/mame/machine/snes7110.c1661
-rw-r--r--trunk/src/mame/machine/snesbsx.c252
-rw-r--r--trunk/src/mame/machine/snescx4.c258
-rw-r--r--trunk/src/mame/machine/snescx4.h24
-rw-r--r--trunk/src/mame/machine/snesobc1.c116
-rw-r--r--trunk/src/mame/machine/snesrtc.c222
-rw-r--r--trunk/src/mame/machine/snessdd1.c716
-rw-r--r--trunk/src/mame/machine/spisprit.c283
-rw-r--r--trunk/src/mame/machine/starwars.c482
-rw-r--r--trunk/src/mame/machine/steppers.c284
-rw-r--r--trunk/src/mame/machine/steppers.h49
-rw-r--r--trunk/src/mame/machine/stfight.c254
-rw-r--r--trunk/src/mame/machine/stvcd.c2553
-rw-r--r--trunk/src/mame/machine/stvcd.h24
-rw-r--r--trunk/src/mame/machine/stvprot.c712
-rw-r--r--trunk/src/mame/machine/stvprot.h12
-rw-r--r--trunk/src/mame/machine/subs.c184
-rw-r--r--trunk/src/mame/machine/subsino.c104
-rw-r--r--trunk/src/mame/machine/subsino.h18
-rw-r--r--trunk/src/mame/machine/tait8741.c638
-rw-r--r--trunk/src/mame/machine/tait8741.h64
-rw-r--r--trunk/src/mame/machine/taitoio.c579
-rw-r--r--trunk/src/mame/machine/taitoio.h102
-rw-r--r--trunk/src/mame/machine/taitosj.c322
-rw-r--r--trunk/src/mame/machine/tatsumi.c385
-rw-r--r--trunk/src/mame/machine/tecmosys.c237
-rw-r--r--trunk/src/mame/machine/theglobp.c263
-rw-r--r--trunk/src/mame/machine/ticket.c168
-rw-r--r--trunk/src/mame/machine/ticket.h37
-rw-r--r--trunk/src/mame/machine/tnzs.c814
-rw-r--r--trunk/src/mame/machine/toaplan1.c463
-rw-r--r--trunk/src/mame/machine/twincobr.c385
-rw-r--r--trunk/src/mame/machine/tx1.c1425
-rw-r--r--trunk/src/mame/machine/vectrex.c368
-rw-r--r--trunk/src/mame/machine/vertigo.c246
-rw-r--r--trunk/src/mame/machine/volfied.c509
-rw-r--r--trunk/src/mame/machine/vsnes.c1056
-rw-r--r--trunk/src/mame/machine/williams.c1038
-rw-r--r--trunk/src/mame/machine/wrally.c53
-rw-r--r--trunk/src/mame/machine/xevious.c189
-rw-r--r--trunk/src/mame/machine/znsec.c181
-rw-r--r--trunk/src/mame/machine/znsec.h5
-rw-r--r--trunk/src/mame/machine/zs01.c533
-rw-r--r--trunk/src/mame/machine/zs01.h92
-rw-r--r--trunk/src/mame/mame.lst15884
-rw-r--r--trunk/src/mame/mame.mak2134
-rw-r--r--trunk/src/mame/mame_dev.lst52
-rw-r--r--trunk/src/mame/tiny.lst68
-rw-r--r--trunk/src/mame/tiny.mak103
-rw-r--r--trunk/src/mame/tiny_dev.lst39
-rw-r--r--trunk/src/mame/video/1942.c251
-rw-r--r--trunk/src/mame/video/1943.c287
-rw-r--r--trunk/src/mame/video/20pacgal.c438
-rw-r--r--trunk/src/mame/video/40love.c371
-rw-r--r--trunk/src/mame/video/4enraya.c46
-rw-r--r--trunk/src/mame/video/8080bw.c481
-rw-r--r--trunk/src/mame/video/88games.c83
-rw-r--r--trunk/src/mame/video/actfancr.c41
-rw-r--r--trunk/src/mame/video/aeroboto.c229
-rw-r--r--trunk/src/mame/video/aerofgt.c1090
-rw-r--r--trunk/src/mame/video/airbustr.c156
-rw-r--r--trunk/src/mame/video/ajax.c116
-rw-r--r--trunk/src/mame/video/aliens.c93
-rw-r--r--trunk/src/mame/video/alpha68k.c574
-rw-r--r--trunk/src/mame/video/ambush.c158
-rw-r--r--trunk/src/mame/video/amiga.c1012
-rw-r--r--trunk/src/mame/video/amigaaga.c872
-rw-r--r--trunk/src/mame/video/ampoker2.c169
-rw-r--r--trunk/src/mame/video/amspdwy.c155
-rw-r--r--trunk/src/mame/video/angelkds.c312
-rw-r--r--trunk/src/mame/video/antic.c588
-rw-r--r--trunk/src/mame/video/appoooh.c331
-rw-r--r--trunk/src/mame/video/aquarium.c180
-rw-r--r--trunk/src/mame/video/arabian.c395
-rw-r--r--trunk/src/mame/video/arcadecl.c143
-rw-r--r--trunk/src/mame/video/archimds.c129
-rw-r--r--trunk/src/mame/video/argus.c1235
-rw-r--r--trunk/src/mame/video/arkanoid.c220
-rw-r--r--trunk/src/mame/video/armedf.c442
-rw-r--r--trunk/src/mame/video/artmagic.c355
-rw-r--r--trunk/src/mame/video/ashnojoe.c247
-rw-r--r--trunk/src/mame/video/asterix.c112
-rw-r--r--trunk/src/mame/video/astrocde.c1090
-rw-r--r--trunk/src/mame/video/asuka.c71
-rw-r--r--trunk/src/mame/video/atari.c1663
-rw-r--r--trunk/src/mame/video/atarifb.c210
-rw-r--r--trunk/src/mame/video/atarig1.c174
-rw-r--r--trunk/src/mame/video/atarig42.c235
-rw-r--r--trunk/src/mame/video/atarigt.c640
-rw-r--r--trunk/src/mame/video/atarigx2.c228
-rw-r--r--trunk/src/mame/video/atarimo.c1161
-rw-r--r--trunk/src/mame/video/atarimo.h133
-rw-r--r--trunk/src/mame/video/atarirle.c1817
-rw-r--r--trunk/src/mame/video/atarirle.h93
-rw-r--r--trunk/src/mame/video/atarisy1.c688
-rw-r--r--trunk/src/mame/video/atarisy2.c369
-rw-r--r--trunk/src/mame/video/atetris.c73
-rw-r--r--trunk/src/mame/video/avgdvg.c1583
-rw-r--r--trunk/src/mame/video/avgdvg.h29
-rw-r--r--trunk/src/mame/video/awpvid.c119
-rw-r--r--trunk/src/mame/video/awpvid.h15
-rw-r--r--trunk/src/mame/video/aztarac.c98
-rw-r--r--trunk/src/mame/video/badlands.c144
-rw-r--r--trunk/src/mame/video/bagman.c159
-rw-r--r--trunk/src/mame/video/balsente.c228
-rw-r--r--trunk/src/mame/video/bankp.c213
-rw-r--r--trunk/src/mame/video/baraduke.c359
-rw-r--r--trunk/src/mame/video/batman.c314
-rw-r--r--trunk/src/mame/video/battlane.c247
-rw-r--r--trunk/src/mame/video/battlera.c396
-rw-r--r--trunk/src/mame/video/battlex.c107
-rw-r--r--trunk/src/mame/video/battlnts.c56
-rw-r--r--trunk/src/mame/video/bbusters.c314
-rw-r--r--trunk/src/mame/video/beathead.c188
-rw-r--r--trunk/src/mame/video/beezer.c74
-rw-r--r--trunk/src/mame/video/bfm_adr2.c538
-rw-r--r--trunk/src/mame/video/bfm_adr2.h21
-rw-r--r--trunk/src/mame/video/bfm_dm01.c258
-rw-r--r--trunk/src/mame/video/bfm_dm01.h19
-rw-r--r--trunk/src/mame/video/bigevglf.c101
-rw-r--r--trunk/src/mame/video/bigstrkb.c151
-rw-r--r--trunk/src/mame/video/bionicc.c268
-rw-r--r--trunk/src/mame/video/bishi.c76
-rw-r--r--trunk/src/mame/video/bking.c359
-rw-r--r--trunk/src/mame/video/bladestl.c92
-rw-r--r--trunk/src/mame/video/blktiger.c259
-rw-r--r--trunk/src/mame/video/blmbycar.c262
-rw-r--r--trunk/src/mame/video/blockade.c37
-rw-r--r--trunk/src/mame/video/blockhl.c72
-rw-r--r--trunk/src/mame/video/blockout.c142
-rw-r--r--trunk/src/mame/video/bloodbro.c287
-rw-r--r--trunk/src/mame/video/blstroid.c180
-rw-r--r--trunk/src/mame/video/blueprnt.c144
-rw-r--r--trunk/src/mame/video/bogeyman.c162
-rw-r--r--trunk/src/mame/video/bombjack.c143
-rw-r--r--trunk/src/mame/video/boogwing.c190
-rw-r--r--trunk/src/mame/video/bosco.c321
-rw-r--r--trunk/src/mame/video/bottom9.c96
-rw-r--r--trunk/src/mame/video/brkthru.c275
-rw-r--r--trunk/src/mame/video/bsktball.c63
-rw-r--r--trunk/src/mame/video/btime.c584
-rw-r--r--trunk/src/mame/video/btoads.c537
-rw-r--r--trunk/src/mame/video/bublbobl.c95
-rw-r--r--trunk/src/mame/video/buggychl.c256
-rw-r--r--trunk/src/mame/video/bwing.c346
-rw-r--r--trunk/src/mame/video/cabal.c158
-rw-r--r--trunk/src/mame/video/calomega.c106
-rw-r--r--trunk/src/mame/video/canyon.c99
-rw-r--r--trunk/src/mame/video/capbowl.c197
-rw-r--r--trunk/src/mame/video/carjmbre.c164
-rw-r--r--trunk/src/mame/video/carpolo.c732
-rw-r--r--trunk/src/mame/video/cave.c1677
-rw-r--r--trunk/src/mame/video/cbasebal.c196
-rw-r--r--trunk/src/mame/video/cbuster.c83
-rw-r--r--trunk/src/mame/video/ccastles.c360
-rw-r--r--trunk/src/mame/video/cchasm.c131
-rw-r--r--trunk/src/mame/video/cclimber.c812
-rw-r--r--trunk/src/mame/video/centiped.c578
-rw-r--r--trunk/src/mame/video/chaknpop.c269
-rw-r--r--trunk/src/mame/video/champbas.c299
-rw-r--r--trunk/src/mame/video/changela.c823
-rw-r--r--trunk/src/mame/video/cheekyms.c201
-rw-r--r--trunk/src/mame/video/chqflag.c86
-rw-r--r--trunk/src/mame/video/cidelsa.c234
-rw-r--r--trunk/src/mame/video/cinemat.c253
-rw-r--r--trunk/src/mame/video/circus.c222
-rw-r--r--trunk/src/mame/video/circusc.c216
-rw-r--r--trunk/src/mame/video/cischeat.c1467
-rw-r--r--trunk/src/mame/video/citycon.c168
-rw-r--r--trunk/src/mame/video/cloak.c240
-rw-r--r--trunk/src/mame/video/cloud9.c328
-rw-r--r--trunk/src/mame/video/clshroad.c345
-rw-r--r--trunk/src/mame/video/cninja.c293
-rw-r--r--trunk/src/mame/video/combatsc.c596
-rw-r--r--trunk/src/mame/video/commando.c153
-rw-r--r--trunk/src/mame/video/compgolf.c134
-rw-r--r--trunk/src/mame/video/contra.c347
-rw-r--r--trunk/src/mame/video/cop01.c220
-rw-r--r--trunk/src/mame/video/copsnrob.c134
-rw-r--r--trunk/src/mame/video/cosmic.c615
-rw-r--r--trunk/src/mame/video/cps1.c2976
-rw-r--r--trunk/src/mame/video/crbaloon.c159
-rw-r--r--trunk/src/mame/video/crgolf.c205
-rw-r--r--trunk/src/mame/video/crimfght.c93
-rw-r--r--trunk/src/mame/video/crospang.c225
-rw-r--r--trunk/src/mame/video/crshrace.c226
-rw-r--r--trunk/src/mame/video/cvs.c340
-rw-r--r--trunk/src/mame/video/cyberbal.c391
-rw-r--r--trunk/src/mame/video/darius.c125
-rw-r--r--trunk/src/mame/video/darkmist.c201
-rw-r--r--trunk/src/mame/video/darkseal.c82
-rw-r--r--trunk/src/mame/video/dassault.c218
-rw-r--r--trunk/src/mame/video/dbz.c166
-rw-r--r--trunk/src/mame/video/dc.c2728
-rw-r--r--trunk/src/mame/video/dcheese.c325
-rw-r--r--trunk/src/mame/video/dcon.c340
-rw-r--r--trunk/src/mame/video/dday.c349
-rw-r--r--trunk/src/mame/video/ddragon.c257
-rw-r--r--trunk/src/mame/video/ddragon3.c217
-rw-r--r--trunk/src/mame/video/ddribble.c272
-rw-r--r--trunk/src/mame/video/deadang.c167
-rw-r--r--trunk/src/mame/video/dec0.c271
-rw-r--r--trunk/src/mame/video/dec8.c632
-rw-r--r--trunk/src/mame/video/decbac06.c540
-rw-r--r--trunk/src/mame/video/decbac06.h96
-rw-r--r--trunk/src/mame/video/deckarn.c102
-rw-r--r--trunk/src/mame/video/deckarn.h22
-rw-r--r--trunk/src/mame/video/decmxc06.c170
-rw-r--r--trunk/src/mame/video/decmxc06.h26
-rw-r--r--trunk/src/mame/video/deco16ic.c1010
-rw-r--r--trunk/src/mame/video/deco16ic.h93
-rw-r--r--trunk/src/mame/video/deco32.c920
-rw-r--r--trunk/src/mame/video/deco_mlc.c529
-rw-r--r--trunk/src/mame/video/decocass.c616
-rw-r--r--trunk/src/mame/video/decocomn.c257
-rw-r--r--trunk/src/mame/video/decocomn.h57
-rw-r--r--trunk/src/mame/video/decospr.c568
-rw-r--r--trunk/src/mame/video/decospr.h39
-rw-r--r--trunk/src/mame/video/deniam.c418
-rw-r--r--trunk/src/mame/video/dietgo.c21
-rw-r--r--trunk/src/mame/video/digdug.c316
-rw-r--r--trunk/src/mame/video/djboy.c88
-rw-r--r--trunk/src/mame/video/djmain.c190
-rw-r--r--trunk/src/mame/video/dkong.c1033
-rw-r--r--trunk/src/mame/video/docastle.c235
-rw-r--r--trunk/src/mame/video/dogfgt.c243
-rw-r--r--trunk/src/mame/video/dooyong.c946
-rw-r--r--trunk/src/mame/video/dragrace.c75
-rw-r--r--trunk/src/mame/video/drgnmst.c203
-rw-r--r--trunk/src/mame/video/dribling.c88
-rw-r--r--trunk/src/mame/video/drmicro.c170
-rw-r--r--trunk/src/mame/video/dynax.c1446
-rw-r--r--trunk/src/mame/video/dynduke.c259
-rw-r--r--trunk/src/mame/video/eolith.c58
-rw-r--r--trunk/src/mame/video/epos.c95
-rw-r--r--trunk/src/mame/video/eprom.c464
-rw-r--r--trunk/src/mame/video/equites.c496
-rw-r--r--trunk/src/mame/video/esd16.c483
-rw-r--r--trunk/src/mame/video/espial.c242
-rw-r--r--trunk/src/mame/video/esripsys.c373
-rw-r--r--trunk/src/mame/video/exedexes.c253
-rw-r--r--trunk/src/mame/video/exerion.c419
-rw-r--r--trunk/src/mame/video/exidy.c379
-rw-r--r--trunk/src/mame/video/exidy440.c504
-rw-r--r--trunk/src/mame/video/exprraid.c147
-rw-r--r--trunk/src/mame/video/exterm.c115
-rw-r--r--trunk/src/mame/video/exzisus.c228
-rw-r--r--trunk/src/mame/video/f1gp.c479
-rw-r--r--trunk/src/mame/video/fantland.c148
-rw-r--r--trunk/src/mame/video/fastfred.c390
-rw-r--r--trunk/src/mame/video/fastlane.c180
-rw-r--r--trunk/src/mame/video/fcombat.c213
-rw-r--r--trunk/src/mame/video/fgoal.c127
-rw-r--r--trunk/src/mame/video/finalizr.c226
-rw-r--r--trunk/src/mame/video/firetrap.c282
-rw-r--r--trunk/src/mame/video/firetrk.c455
-rw-r--r--trunk/src/mame/video/fitfight.c172
-rw-r--r--trunk/src/mame/video/flkatck.c176
-rw-r--r--trunk/src/mame/video/flower.c220
-rw-r--r--trunk/src/mame/video/flstory.c301
-rw-r--r--trunk/src/mame/video/foodf.c155
-rw-r--r--trunk/src/mame/video/freekick.c159
-rw-r--r--trunk/src/mame/video/fromanc2.c582
-rw-r--r--trunk/src/mame/video/fromance.c454
-rw-r--r--trunk/src/mame/video/funkybee.c170
-rw-r--r--trunk/src/mame/video/funkyjet.c27
-rw-r--r--trunk/src/mame/video/funworld.c202
-rw-r--r--trunk/src/mame/video/funybubl.c113
-rw-r--r--trunk/src/mame/video/fuukifg2.c350
-rw-r--r--trunk/src/mame/video/fuukifg3.c379
-rw-r--r--trunk/src/mame/video/gaelco.c258
-rw-r--r--trunk/src/mame/video/gaelco2.c519
-rw-r--r--trunk/src/mame/video/gaelco3d.c500
-rw-r--r--trunk/src/mame/video/gaiden.c734
-rw-r--r--trunk/src/mame/video/galaga.c597
-rw-r--r--trunk/src/mame/video/galastrm.c570
-rw-r--r--trunk/src/mame/video/galaxian.c1369
-rw-r--r--trunk/src/mame/video/galaxold.c1888
-rw-r--r--trunk/src/mame/video/galivan.c391
-rw-r--r--trunk/src/mame/video/galpani2.c199
-rw-r--r--trunk/src/mame/video/galpanic.c138
-rw-r--r--trunk/src/mame/video/galspnbl.c137
-rw-r--r--trunk/src/mame/video/gameplan.c364
-rw-r--r--trunk/src/mame/video/gaplus.c406
-rw-r--r--trunk/src/mame/video/gatron.c64
-rw-r--r--trunk/src/mame/video/gauntlet.c220
-rw-r--r--trunk/src/mame/video/gberet.c234
-rw-r--r--trunk/src/mame/video/gbusters.c76
-rw-r--r--trunk/src/mame/video/gcpinbal.c330
-rw-r--r--trunk/src/mame/video/genesis.c1308
-rw-r--r--trunk/src/mame/video/gijoe.c171
-rw-r--r--trunk/src/mame/video/ginganin.c295
-rw-r--r--trunk/src/mame/video/gladiatr.c313
-rw-r--r--trunk/src/mame/video/glass.c214
-rw-r--r--trunk/src/mame/video/gng.c158
-rw-r--r--trunk/src/mame/video/goal92.c195
-rw-r--r--trunk/src/mame/video/goindol.c137
-rw-r--r--trunk/src/mame/video/goldstar.c614
-rw-r--r--trunk/src/mame/video/gomoku.c234
-rw-r--r--trunk/src/mame/video/gotcha.c145
-rw-r--r--trunk/src/mame/video/gottlieb.c271
-rw-r--r--trunk/src/mame/video/gotya.c188
-rw-r--r--trunk/src/mame/video/gp9001.c1030
-rw-r--r--trunk/src/mame/video/gp9001.h109
-rw-r--r--trunk/src/mame/video/gradius3.c152
-rw-r--r--trunk/src/mame/video/grchamp.c549
-rw-r--r--trunk/src/mame/video/gridlee.c218
-rw-r--r--trunk/src/mame/video/groundfx.c275
-rw-r--r--trunk/src/mame/video/gstriker.c640
-rw-r--r--trunk/src/mame/video/gsword.c214
-rw-r--r--trunk/src/mame/video/gtia.c1143
-rw-r--r--trunk/src/mame/video/gtia.h156
-rw-r--r--trunk/src/mame/video/gticlub.c1084
-rw-r--r--trunk/src/mame/video/gticlub.h19
-rw-r--r--trunk/src/mame/video/gumbo.c51
-rw-r--r--trunk/src/mame/video/gunbustr.c242
-rw-r--r--trunk/src/mame/video/gundealr.c141
-rw-r--r--trunk/src/mame/video/gunsmoke.c195
-rw-r--r--trunk/src/mame/video/gyruss.c168
-rw-r--r--trunk/src/mame/video/hanaawas.c116
-rw-r--r--trunk/src/mame/video/harddriv.c455
-rw-r--r--trunk/src/mame/video/hcastle.c279
-rw-r--r--trunk/src/mame/video/hexion.c174
-rw-r--r--trunk/src/mame/video/higemaru.c154
-rw-r--r--trunk/src/mame/video/himesiki.c130
-rw-r--r--trunk/src/mame/video/hnayayoi.c287
-rw-r--r--trunk/src/mame/video/hng64.c3483
-rw-r--r--trunk/src/mame/video/holeland.c207
-rw-r--r--trunk/src/mame/video/homedata.c1056
-rw-r--r--trunk/src/mame/video/homerun.c108
-rw-r--r--trunk/src/mame/video/hyhoo.c243
-rw-r--r--trunk/src/mame/video/hyperspt.c211
-rw-r--r--trunk/src/mame/video/hyprduel.c754
-rw-r--r--trunk/src/mame/video/ikki.c225
-rw-r--r--trunk/src/mame/video/inufuku.c265
-rw-r--r--trunk/src/mame/video/iqblock.c102
-rw-r--r--trunk/src/mame/video/irobot.c374
-rw-r--r--trunk/src/mame/video/ironhors.c367
-rw-r--r--trunk/src/mame/video/itech32.c1468
-rw-r--r--trunk/src/mame/video/itech8.c767
-rw-r--r--trunk/src/mame/video/jack.c191
-rw-r--r--trunk/src/mame/video/jackal.c231
-rw-r--r--trunk/src/mame/video/jagblit.c480
-rw-r--r--trunk/src/mame/video/jagblit.h139
-rw-r--r--trunk/src/mame/video/jagobj.c1109
-rw-r--r--trunk/src/mame/video/jaguar.c1050
-rw-r--r--trunk/src/mame/video/jailbrek.c127
-rw-r--r--trunk/src/mame/video/jalblend.c212
-rw-r--r--trunk/src/mame/video/jalblend.h7
-rw-r--r--trunk/src/mame/video/jedi.c366
-rw-r--r--trunk/src/mame/video/jpmimpct.c142
-rw-r--r--trunk/src/mame/video/kan_panb.c278
-rw-r--r--trunk/src/mame/video/kan_panb.h4
-rw-r--r--trunk/src/mame/video/kan_pand.c337
-rw-r--r--trunk/src/mame/video/kan_pand.h54
-rw-r--r--trunk/src/mame/video/kaneko16.c1139
-rw-r--r--trunk/src/mame/video/kangaroo.c204
-rw-r--r--trunk/src/mame/video/karnov.c190
-rw-r--r--trunk/src/mame/video/kchamp.c146
-rw-r--r--trunk/src/mame/video/kickgoal.c275
-rw-r--r--trunk/src/mame/video/kingobox.c320
-rw-r--r--trunk/src/mame/video/klax.c136
-rw-r--r--trunk/src/mame/video/kncljoe.c248
-rw-r--r--trunk/src/mame/video/konamigx.c2710
-rw-r--r--trunk/src/mame/video/konamiic.c3333
-rw-r--r--trunk/src/mame/video/konamiic.h198
-rw-r--r--trunk/src/mame/video/konicdev.c10709
-rw-r--r--trunk/src/mame/video/konicdev.h770
-rw-r--r--trunk/src/mame/video/kopunch.c108
-rw-r--r--trunk/src/mame/video/ksayakyu.c139
-rw-r--r--trunk/src/mame/video/kyugo.c238
-rw-r--r--trunk/src/mame/video/labyrunr.c290
-rw-r--r--trunk/src/mame/video/ladybug.c371
-rw-r--r--trunk/src/mame/video/ladyfrog.c183
-rw-r--r--trunk/src/mame/video/lasso.c422
-rw-r--r--trunk/src/mame/video/lastduel.c317
-rw-r--r--trunk/src/mame/video/lazercmd.c82
-rw-r--r--trunk/src/mame/video/legionna.c509
-rw-r--r--trunk/src/mame/video/leland.c546
-rw-r--r--trunk/src/mame/video/lemmings.c199
-rw-r--r--trunk/src/mame/video/lethal.c122
-rw-r--r--trunk/src/mame/video/lethalj.c195
-rw-r--r--trunk/src/mame/video/liberate.c610
-rw-r--r--trunk/src/mame/video/liberatr.c309
-rw-r--r--trunk/src/mame/video/lkage.c232
-rw-r--r--trunk/src/mame/video/lockon.c968
-rw-r--r--trunk/src/mame/video/lordgun.c428
-rw-r--r--trunk/src/mame/video/lsasquad.c221
-rw-r--r--trunk/src/mame/video/lucky74.c252
-rw-r--r--trunk/src/mame/video/lvcards.c120
-rw-r--r--trunk/src/mame/video/lwings.c299
-rw-r--r--trunk/src/mame/video/m10.c193
-rw-r--r--trunk/src/mame/video/m107.c397
-rw-r--r--trunk/src/mame/video/m3raster.c286
-rw-r--r--trunk/src/mame/video/m52.c431
-rw-r--r--trunk/src/mame/video/m57.c275
-rw-r--r--trunk/src/mame/video/m58.c326
-rw-r--r--trunk/src/mame/video/m62.c988
-rw-r--r--trunk/src/mame/video/m72.c585
-rw-r--r--trunk/src/mame/video/m90.c560
-rw-r--r--trunk/src/mame/video/m92.c464
-rw-r--r--trunk/src/mame/video/macrossp.c439
-rw-r--r--trunk/src/mame/video/madalien.c410
-rw-r--r--trunk/src/mame/video/madmotor.c37
-rw-r--r--trunk/src/mame/video/magmax.c242
-rw-r--r--trunk/src/mame/video/mainevt.c123
-rw-r--r--trunk/src/mame/video/mainsnk.c180
-rw-r--r--trunk/src/mame/video/malzak.c95
-rw-r--r--trunk/src/mame/video/mappy.c607
-rw-r--r--trunk/src/mame/video/marineb.c481
-rw-r--r--trunk/src/mame/video/mario.c230
-rw-r--r--trunk/src/mame/video/markham.c136
-rw-r--r--trunk/src/mame/video/matmania.c274
-rw-r--r--trunk/src/mame/video/mcatadv.c277
-rw-r--r--trunk/src/mame/video/mcd212.c1675
-rw-r--r--trunk/src/mame/video/mcd212.h195
-rw-r--r--trunk/src/mame/video/mcr.c435
-rw-r--r--trunk/src/mame/video/mcr3.c313
-rw-r--r--trunk/src/mame/video/mcr68.c367
-rw-r--r--trunk/src/mame/video/meadows.c118
-rw-r--r--trunk/src/mame/video/megasys1.c1035
-rw-r--r--trunk/src/mame/video/megazone.c227
-rw-r--r--trunk/src/mame/video/mermaid.c574
-rw-r--r--trunk/src/mame/video/metlclsh.c266
-rw-r--r--trunk/src/mame/video/metro.c800
-rw-r--r--trunk/src/mame/video/mexico86.c167
-rw-r--r--trunk/src/mame/video/micro3d.c771
-rw-r--r--trunk/src/mame/video/midtunit.c827
-rw-r--r--trunk/src/mame/video/midvunit.c586
-rw-r--r--trunk/src/mame/video/midyunit.c574
-rw-r--r--trunk/src/mame/video/midzeus.c1465
-rw-r--r--trunk/src/mame/video/midzeus2.c1390
-rw-r--r--trunk/src/mame/video/mikie.c185
-rw-r--r--trunk/src/mame/video/mitchell.c339
-rw-r--r--trunk/src/mame/video/mjkjidai.c143
-rw-r--r--trunk/src/mame/video/model1.c1545
-rw-r--r--trunk/src/mame/video/model2.c2782
-rw-r--r--trunk/src/mame/video/model2rd.c195
-rw-r--r--trunk/src/mame/video/model3.c1570
-rw-r--r--trunk/src/mame/video/momoko.c327
-rw-r--r--trunk/src/mame/video/moo.c135
-rw-r--r--trunk/src/mame/video/mosaic.c90
-rw-r--r--trunk/src/mame/video/mouser.c161
-rw-r--r--trunk/src/mame/video/mrdo.c273
-rw-r--r--trunk/src/mame/video/mrflea.c112
-rw-r--r--trunk/src/mame/video/mrjong.c154
-rw-r--r--trunk/src/mame/video/ms32.c729
-rw-r--r--trunk/src/mame/video/msisaac.c255
-rw-r--r--trunk/src/mame/video/mugsmash.c162
-rw-r--r--trunk/src/mame/video/munchmo.c159
-rw-r--r--trunk/src/mame/video/mustache.c152
-rw-r--r--trunk/src/mame/video/mw8080bw.c391
-rw-r--r--trunk/src/mame/video/mystston.c335
-rw-r--r--trunk/src/mame/video/mystwarr.c558
-rw-r--r--trunk/src/mame/video/n64.c3329
-rw-r--r--trunk/src/mame/video/n64.h769
-rw-r--r--trunk/src/mame/video/n8080.c391
-rw-r--r--trunk/src/mame/video/namcofl.c125
-rw-r--r--trunk/src/mame/video/namcona1.c733
-rw-r--r--trunk/src/mame/video/namconb1.c235
-rw-r--r--trunk/src/mame/video/namcos1.c459
-rw-r--r--trunk/src/mame/video/namcos2.c615
-rw-r--r--trunk/src/mame/video/namcos21.c499
-rw-r--r--trunk/src/mame/video/namcos22.c2492
-rw-r--r--trunk/src/mame/video/namcos86.c415
-rw-r--r--trunk/src/mame/video/naughtyb.c266
-rw-r--r--trunk/src/mame/video/nbmj8688.c743
-rw-r--r--trunk/src/mame/video/nbmj8891.c573
-rw-r--r--trunk/src/mame/video/nbmj8900.c450
-rw-r--r--trunk/src/mame/video/nbmj8991.c383
-rw-r--r--trunk/src/mame/video/nbmj9195.c510
-rw-r--r--trunk/src/mame/video/nemesis.c482
-rw-r--r--trunk/src/mame/video/neogeo.c935
-rw-r--r--trunk/src/mame/video/news.c106
-rw-r--r--trunk/src/mame/video/ninjakd2.c564
-rw-r--r--trunk/src/mame/video/ninjaw.c148
-rw-r--r--trunk/src/mame/video/nitedrvr.c83
-rw-r--r--trunk/src/mame/video/niyanpai.c437
-rw-r--r--trunk/src/mame/video/nmk16.c973
-rw-r--r--trunk/src/mame/video/nova2001.c409
-rw-r--r--trunk/src/mame/video/nycaptor.c337
-rw-r--r--trunk/src/mame/video/offtwall.c121
-rw-r--r--trunk/src/mame/video/ohmygod.c115
-rw-r--r--trunk/src/mame/video/ojankohs.c345
-rw-r--r--trunk/src/mame/video/oneshot.c191
-rw-r--r--trunk/src/mame/video/opwolf.c61
-rw-r--r--trunk/src/mame/video/orbit.c92
-rw-r--r--trunk/src/mame/video/othldrby.c234
-rw-r--r--trunk/src/mame/video/othunder.c231
-rw-r--r--trunk/src/mame/video/overdriv.c70
-rw-r--r--trunk/src/mame/video/pacland.c406
-rw-r--r--trunk/src/mame/video/pacman.c605
-rw-r--r--trunk/src/mame/video/pandoras.c187
-rw-r--r--trunk/src/mame/video/paradise.c337
-rw-r--r--trunk/src/mame/video/parodius.c78
-rw-r--r--trunk/src/mame/video/pass.c68
-rw-r--r--trunk/src/mame/video/pastelg.c322
-rw-r--r--trunk/src/mame/video/pbaction.c143
-rw-r--r--trunk/src/mame/video/pcktgal.c80
-rw-r--r--trunk/src/mame/video/pgm.c427
-rw-r--r--trunk/src/mame/video/phoenix.c459
-rw-r--r--trunk/src/mame/video/pingpong.c161
-rw-r--r--trunk/src/mame/video/pirates.c120
-rw-r--r--trunk/src/mame/video/pitnrun.c287
-rw-r--r--trunk/src/mame/video/pk8000.c177
-rw-r--r--trunk/src/mame/video/pktgaldx.c81
-rw-r--r--trunk/src/mame/video/playch10.c183
-rw-r--r--trunk/src/mame/video/playmark.c611
-rw-r--r--trunk/src/mame/video/plygonet.c138
-rw-r--r--trunk/src/mame/video/pokechmp.c81
-rw-r--r--trunk/src/mame/video/polepos.c533
-rw-r--r--trunk/src/mame/video/policetr.c362
-rw-r--r--trunk/src/mame/video/polyplay.c68
-rw-r--r--trunk/src/mame/video/poolshrk.c54
-rw-r--r--trunk/src/mame/video/pooyan.c202
-rw-r--r--trunk/src/mame/video/popeye.c381
-rw-r--r--trunk/src/mame/video/popper.c273
-rw-r--r--trunk/src/mame/video/portrait.c213
-rw-r--r--trunk/src/mame/video/powerins.c375
-rw-r--r--trunk/src/mame/video/ppu2c0x.c1501
-rw-r--r--trunk/src/mame/video/ppu2c0x.h164
-rw-r--r--trunk/src/mame/video/prehisle.c177
-rw-r--r--trunk/src/mame/video/psikyo.c873
-rw-r--r--trunk/src/mame/video/psikyo4.c151
-rw-r--r--trunk/src/mame/video/psikyosh.c1352
-rw-r--r--trunk/src/mame/video/psychic5.c457
-rw-r--r--trunk/src/mame/video/punchout.c435
-rw-r--r--trunk/src/mame/video/pushman.c135
-rw-r--r--trunk/src/mame/video/qdrmfgp.c70
-rw-r--r--trunk/src/mame/video/qix.c471
-rw-r--r--trunk/src/mame/video/quasar.c205
-rw-r--r--trunk/src/mame/video/quizdna.c207
-rw-r--r--trunk/src/mame/video/quizpani.c93
-rw-r--r--trunk/src/mame/video/raiden.c185
-rw-r--r--trunk/src/mame/video/rainbow.c143
-rw-r--r--trunk/src/mame/video/rallyx.c745
-rw-r--r--trunk/src/mame/video/rampart.c131
-rw-r--r--trunk/src/mame/video/rastan.c51
-rw-r--r--trunk/src/mame/video/rdpblend.c296
-rw-r--r--trunk/src/mame/video/rdpblend.h64
-rw-r--r--trunk/src/mame/video/rdpfb.c275
-rw-r--r--trunk/src/mame/video/rdpfb.h53
-rw-r--r--trunk/src/mame/video/rdpfiltr.c613
-rw-r--r--trunk/src/mame/video/rdpspn16.c507
-rw-r--r--trunk/src/mame/video/rdpspn16.h77
-rw-r--r--trunk/src/mame/video/rdptpipe.c1260
-rw-r--r--trunk/src/mame/video/rdptpipe.h70
-rw-r--r--trunk/src/mame/video/rdptri.h42
-rw-r--r--trunk/src/mame/video/realbrk.c632
-rw-r--r--trunk/src/mame/video/redalert.c465
-rw-r--r--trunk/src/mame/video/redclash.c436
-rw-r--r--trunk/src/mame/video/relief.c179
-rw-r--r--trunk/src/mame/video/renegade.c142
-rw-r--r--trunk/src/mame/video/retofinv.c239
-rw-r--r--trunk/src/mame/video/rltennis.c277
-rw-r--r--trunk/src/mame/video/rockrage.c113
-rw-r--r--trunk/src/mame/video/rocnrope.c151
-rw-r--r--trunk/src/mame/video/rohga.c540
-rw-r--r--trunk/src/mame/video/rollerg.c72
-rw-r--r--trunk/src/mame/video/rollrace.c213
-rw-r--r--trunk/src/mame/video/route16.c189
-rw-r--r--trunk/src/mame/video/rpunch.c290
-rw-r--r--trunk/src/mame/video/runaway.c159
-rw-r--r--trunk/src/mame/video/rungun.c120
-rw-r--r--trunk/src/mame/video/sauro.c239
-rw-r--r--trunk/src/mame/video/sbasketb.c185
-rw-r--r--trunk/src/mame/video/sbugger.c64
-rw-r--r--trunk/src/mame/video/scotrsht.c152
-rw-r--r--trunk/src/mame/video/sderby.c149
-rw-r--r--trunk/src/mame/video/sega16sp.c1698
-rw-r--r--trunk/src/mame/video/segag80r.c860
-rw-r--r--trunk/src/mame/video/segag80v.c343
-rw-r--r--trunk/src/mame/video/segahang.c88
-rw-r--r--trunk/src/mame/video/segaic16.c2118
-rw-r--r--trunk/src/mame/video/segaic16.h334
-rw-r--r--trunk/src/mame/video/segaic24.c851
-rw-r--r--trunk/src/mame/video/segaic24.h106
-rw-r--r--trunk/src/mame/video/segaorun.c116
-rw-r--r--trunk/src/mame/video/segas16a.c67
-rw-r--r--trunk/src/mame/video/segas16b.c79
-rw-r--r--trunk/src/mame/video/segas18.c253
-rw-r--r--trunk/src/mame/video/segas24.c57
-rw-r--r--trunk/src/mame/video/segas32.c2830
-rw-r--r--trunk/src/mame/video/segaxbd.c75
-rw-r--r--trunk/src/mame/video/segaybd.c65
-rw-r--r--trunk/src/mame/video/sei_crtc.c295
-rw-r--r--trunk/src/mame/video/seibuspi.c681
-rw-r--r--trunk/src/mame/video/seicross.c151
-rw-r--r--trunk/src/mame/video/senjyo.c395
-rw-r--r--trunk/src/mame/video/seta.c1093
-rw-r--r--trunk/src/mame/video/seta001.c464
-rw-r--r--trunk/src/mame/video/seta001.h86
-rw-r--r--trunk/src/mame/video/seta2.c499
-rw-r--r--trunk/src/mame/video/sf.c237
-rw-r--r--trunk/src/mame/video/shadfrce.c191
-rw-r--r--trunk/src/mame/video/shangha3.c270
-rw-r--r--trunk/src/mame/video/shangkid.c330
-rw-r--r--trunk/src/mame/video/shaolins.c202
-rw-r--r--trunk/src/mame/video/shisen.c77
-rw-r--r--trunk/src/mame/video/shootout.c196
-rw-r--r--trunk/src/mame/video/shuuz.c143
-rw-r--r--trunk/src/mame/video/sidearms.c374
-rw-r--r--trunk/src/mame/video/sidepckt.c151
-rw-r--r--trunk/src/mame/video/silkroad.c175
-rw-r--r--trunk/src/mame/video/simpl156.c46
-rw-r--r--trunk/src/mame/video/simpsons.c155
-rw-r--r--trunk/src/mame/video/sknsspr.c561
-rw-r--r--trunk/src/mame/video/sknsspr.h24
-rw-r--r--trunk/src/mame/video/skullxbo.c320
-rw-r--r--trunk/src/mame/video/skydiver.c216
-rw-r--r--trunk/src/mame/video/skyfox.c290
-rw-r--r--trunk/src/mame/video/skykid.c278
-rw-r--r--trunk/src/mame/video/skyraid.c153
-rw-r--r--trunk/src/mame/video/slapfght.c255
-rw-r--r--trunk/src/mame/video/slapshot.c572
-rw-r--r--trunk/src/mame/video/snes.c2785
-rw-r--r--trunk/src/mame/video/snk.c1078
-rw-r--r--trunk/src/mame/video/snk6502.c333
-rw-r--r--trunk/src/mame/video/snk68.c304
-rw-r--r--trunk/src/mame/video/snookr10.c195
-rw-r--r--trunk/src/mame/video/solomon.c117
-rw-r--r--trunk/src/mame/video/sonson.c184
-rw-r--r--trunk/src/mame/video/spacefb.c406
-rw-r--r--trunk/src/mame/video/spbactn.c220
-rw-r--r--trunk/src/mame/video/spcforce.c50
-rw-r--r--trunk/src/mame/video/spdodgeb.c219
-rw-r--r--trunk/src/mame/video/speedatk.c120
-rw-r--r--trunk/src/mame/video/speedbal.c139
-rw-r--r--trunk/src/mame/video/speedspn.c115
-rw-r--r--trunk/src/mame/video/splash.c292
-rw-r--r--trunk/src/mame/video/sprcros2.c205
-rw-r--r--trunk/src/mame/video/sprint2.c216
-rw-r--r--trunk/src/mame/video/sprint4.c154
-rw-r--r--trunk/src/mame/video/sprint8.c195
-rw-r--r--trunk/src/mame/video/spy.c84
-rw-r--r--trunk/src/mame/video/srmp2.c102
-rw-r--r--trunk/src/mame/video/srumbler.c178
-rw-r--r--trunk/src/mame/video/sshangha.c65
-rw-r--r--trunk/src/mame/video/sslam.c250
-rw-r--r--trunk/src/mame/video/ssozumo.c195
-rw-r--r--trunk/src/mame/video/sspeedr.c274
-rw-r--r--trunk/src/mame/video/ssrj.c290
-rw-r--r--trunk/src/mame/video/ssv.c1241
-rw-r--r--trunk/src/mame/video/st0016.c623
-rw-r--r--trunk/src/mame/video/stactics.c428
-rw-r--r--trunk/src/mame/video/stadhero.c67
-rw-r--r--trunk/src/mame/video/starcrus.c510
-rw-r--r--trunk/src/mame/video/starfire.c277
-rw-r--r--trunk/src/mame/video/starshp1.c425
-rw-r--r--trunk/src/mame/video/stfight.c312
-rw-r--r--trunk/src/mame/video/stlforce.c203
-rw-r--r--trunk/src/mame/video/strnskil.c151
-rw-r--r--trunk/src/mame/video/stvvdp1.c2200
-rw-r--r--trunk/src/mame/video/stvvdp2.c7381
-rw-r--r--trunk/src/mame/video/subs.c152
-rw-r--r--trunk/src/mame/video/suna16.c253
-rw-r--r--trunk/src/mame/video/suna8.c456
-rw-r--r--trunk/src/mame/video/supbtime.c38
-rw-r--r--trunk/src/mame/video/superchs.c239
-rw-r--r--trunk/src/mame/video/superqix.c244
-rw-r--r--trunk/src/mame/video/suprloco.c279
-rw-r--r--trunk/src/mame/video/suprnova.c643
-rw-r--r--trunk/src/mame/video/suprridr.c222
-rw-r--r--trunk/src/mame/video/suprslam.c184
-rw-r--r--trunk/src/mame/video/surpratk.c79
-rw-r--r--trunk/src/mame/video/system1.c670
-rw-r--r--trunk/src/mame/video/system16.c811
-rw-r--r--trunk/src/mame/video/tagteam.c201
-rw-r--r--trunk/src/mame/video/tail2nos.c194
-rw-r--r--trunk/src/mame/video/taito_b.c414
-rw-r--r--trunk/src/mame/video/taito_f2.c1399
-rw-r--r--trunk/src/mame/video/taito_f3.c3273
-rw-r--r--trunk/src/mame/video/taito_h.c473
-rw-r--r--trunk/src/mame/video/taito_l.c336
-rw-r--r--trunk/src/mame/video/taito_o.c160
-rw-r--r--trunk/src/mame/video/taito_z.c1035
-rw-r--r--trunk/src/mame/video/taitoair.c464
-rw-r--r--trunk/src/mame/video/taitoic.c5352
-rw-r--r--trunk/src/mame/video/taitoic.h320
-rw-r--r--trunk/src/mame/video/taitojc.c799
-rw-r--r--trunk/src/mame/video/taitosj.c766
-rw-r--r--trunk/src/mame/video/tank8.c292
-rw-r--r--trunk/src/mame/video/tankbatt.c110
-rw-r--r--trunk/src/mame/video/tankbust.c258
-rw-r--r--trunk/src/mame/video/taotaido.c240
-rw-r--r--trunk/src/mame/video/targeth.c150
-rw-r--r--trunk/src/mame/video/tatsumi.c1176
-rw-r--r--trunk/src/mame/video/taxidrvr.c148
-rw-r--r--trunk/src/mame/video/tbowl.c254
-rw-r--r--trunk/src/mame/video/tceptor.c574
-rw-r--r--trunk/src/mame/video/tecmo.c262
-rw-r--r--trunk/src/mame/video/tecmo16.c516
-rw-r--r--trunk/src/mame/video/tecmosys.c367
-rw-r--r--trunk/src/mame/video/tehkanwc.c178
-rw-r--r--trunk/src/mame/video/terracre.c216
-rw-r--r--trunk/src/mame/video/tetrisp2.c753
-rw-r--r--trunk/src/mame/video/thedeep.c233
-rw-r--r--trunk/src/mame/video/thepit.c328
-rw-r--r--trunk/src/mame/video/thief.c292
-rw-r--r--trunk/src/mame/video/thoop2.c241
-rw-r--r--trunk/src/mame/video/thunderj.c268
-rw-r--r--trunk/src/mame/video/thunderx.c93
-rw-r--r--trunk/src/mame/video/tia.c2000
-rw-r--r--trunk/src/mame/video/tia.h26
-rw-r--r--trunk/src/mame/video/tiamc1.c221
-rw-r--r--trunk/src/mame/video/tigeroad.c179
-rw-r--r--trunk/src/mame/video/timelimt.c157
-rw-r--r--trunk/src/mame/video/timeplt.c220
-rw-r--r--trunk/src/mame/video/tmnt.c838
-rw-r--r--trunk/src/mame/video/tnzs.c59
-rw-r--r--trunk/src/mame/video/toaplan1.c1245
-rw-r--r--trunk/src/mame/video/toaplan2.c498
-rw-r--r--trunk/src/mame/video/toki.c326
-rw-r--r--trunk/src/mame/video/toobin.c280
-rw-r--r--trunk/src/mame/video/topspeed.c187
-rw-r--r--trunk/src/mame/video/toypop.c290
-rw-r--r--trunk/src/mame/video/tp84.c209
-rw-r--r--trunk/src/mame/video/trackfld.c267
-rw-r--r--trunk/src/mame/video/travrusa.c350
-rw-r--r--trunk/src/mame/video/triplhnt.c135
-rw-r--r--trunk/src/mame/video/truco.c58
-rw-r--r--trunk/src/mame/video/trucocl.c87
-rw-r--r--trunk/src/mame/video/tryout.c268
-rw-r--r--trunk/src/mame/video/tsamurai.c281
-rw-r--r--trunk/src/mame/video/tubep.c862
-rw-r--r--trunk/src/mame/video/tumbleb.c971
-rw-r--r--trunk/src/mame/video/tumblep.c37
-rw-r--r--trunk/src/mame/video/tunhunt.c406
-rw-r--r--trunk/src/mame/video/turbo.c1104
-rw-r--r--trunk/src/mame/video/tutankhm.c91
-rw-r--r--trunk/src/mame/video/twin16.c560
-rw-r--r--trunk/src/mame/video/twincobr.c527
-rw-r--r--trunk/src/mame/video/tx1.c3087
-rw-r--r--trunk/src/mame/video/ultraman.c135
-rw-r--r--trunk/src/mame/video/ultratnk.c154
-rw-r--r--trunk/src/mame/video/undrfire.c625
-rw-r--r--trunk/src/mame/video/unico.c423
-rw-r--r--trunk/src/mame/video/usgames.c73
-rw-r--r--trunk/src/mame/video/vaportra.c98
-rw-r--r--trunk/src/mame/video/vastar.c240
-rw-r--r--trunk/src/mame/video/vball.c179
-rw-r--r--trunk/src/mame/video/vdc.c1212
-rw-r--r--trunk/src/mame/video/vdc.h54
-rw-r--r--trunk/src/mame/video/vectrex.c496
-rw-r--r--trunk/src/mame/video/vendetta.c83
-rw-r--r--trunk/src/mame/video/vertigo.c572
-rw-r--r--trunk/src/mame/video/vicdual.c150
-rw-r--r--trunk/src/mame/video/victory.c1127
-rw-r--r--trunk/src/mame/video/videopin.c116
-rw-r--r--trunk/src/mame/video/vigilant.c340
-rw-r--r--trunk/src/mame/video/vindictr.c301
-rw-r--r--trunk/src/mame/video/volfied.c139
-rw-r--r--trunk/src/mame/video/vrender0.c613
-rw-r--r--trunk/src/mame/video/vrender0.h33
-rw-r--r--trunk/src/mame/video/vsnes.c70
-rw-r--r--trunk/src/mame/video/vulgus.c230
-rw-r--r--trunk/src/mame/video/warpwarp.c253
-rw-r--r--trunk/src/mame/video/warriorb.c131
-rw-r--r--trunk/src/mame/video/wc90.c366
-rw-r--r--trunk/src/mame/video/wc90b.c149
-rw-r--r--trunk/src/mame/video/wecleman.c1150
-rw-r--r--trunk/src/mame/video/welltris.c253
-rw-r--r--trunk/src/mame/video/wgp.c754
-rw-r--r--trunk/src/mame/video/williams.c705
-rw-r--r--trunk/src/mame/video/wiping.c227
-rw-r--r--trunk/src/mame/video/wiz.c262
-rw-r--r--trunk/src/mame/video/wolfpack.c329
-rw-r--r--trunk/src/mame/video/wrally.c210
-rw-r--r--trunk/src/mame/video/wwfsstar.c235
-rw-r--r--trunk/src/mame/video/wwfwfest.c296
-rw-r--r--trunk/src/mame/video/xain.c281
-rw-r--r--trunk/src/mame/video/xevious.c508
-rw-r--r--trunk/src/mame/video/xexex.c112
-rw-r--r--trunk/src/mame/video/xmen.c225
-rw-r--r--trunk/src/mame/video/xorworld.c122
-rw-r--r--trunk/src/mame/video/xxmissio.c153
-rw-r--r--trunk/src/mame/video/xybots.c171
-rw-r--r--trunk/src/mame/video/xyonix.c65
-rw-r--r--trunk/src/mame/video/ygv608.c1800
-rw-r--r--trunk/src/mame/video/ygv608.h344
-rw-r--r--trunk/src/mame/video/yiear.c151
-rw-r--r--trunk/src/mame/video/yunsun16.c234
-rw-r--r--trunk/src/mame/video/yunsung8.c221
-rw-r--r--trunk/src/mame/video/zac2650.c237
-rw-r--r--trunk/src/mame/video/zaccaria.c258
-rw-r--r--trunk/src/mame/video/zaxxon.c519
-rw-r--r--trunk/src/mame/video/zerozone.c55
-rw-r--r--trunk/src/mame/video/zodiack.c211
-rw-r--r--trunk/src/osd/osdcomm.h227
-rw-r--r--trunk/src/osd/osdcore.h912
-rw-r--r--trunk/src/osd/osdepend.c242
-rw-r--r--trunk/src/osd/osdepend.h103
-rw-r--r--trunk/src/osd/osdmini/minidir.c88
-rw-r--r--trunk/src/osd/osdmini/minifile.c220
-rw-r--r--trunk/src/osd/osdmini/minimain.c235
-rw-r--r--trunk/src/osd/osdmini/minimisc.c127
-rw-r--r--trunk/src/osd/osdmini/minisync.c99
-rw-r--r--trunk/src/osd/osdmini/minitime.c76
-rw-r--r--trunk/src/osd/osdmini/miniwork.c163
-rw-r--r--trunk/src/osd/osdmini/osdmini.h98
-rw-r--r--trunk/src/osd/osdmini/osdmini.mak81
-rw-r--r--trunk/src/osd/sdl/README_SDL13.txt151
-rw-r--r--trunk/src/osd/sdl/SDL1211_opengl.h6551
-rw-r--r--trunk/src/osd/sdl/SDLMain_tmpl.h11
-rw-r--r--trunk/src/osd/sdl/SDLMain_tmpl.m384
-rw-r--r--trunk/src/osd/sdl/blit13.h202
-rw-r--r--trunk/src/osd/sdl/build.mak13
-rw-r--r--trunk/src/osd/sdl/debug-cb.h111
-rw-r--r--trunk/src/osd/sdl/debug-cb.ign1422
-rw-r--r--trunk/src/osd/sdl/debug-intf.c1504
-rw-r--r--trunk/src/osd/sdl/debug-intf.h8
-rw-r--r--trunk/src/osd/sdl/debug-sup.c144
-rw-r--r--trunk/src/osd/sdl/debug-sup.h44
-rw-r--r--trunk/src/osd/sdl/debug.glade1077
-rw-r--r--trunk/src/osd/sdl/debug.gladep20
-rw-r--r--trunk/src/osd/sdl/debugosx.h376
-rw-r--r--trunk/src/osd/sdl/debugosx.m2340
-rw-r--r--trunk/src/osd/sdl/debugwin.c1300
-rw-r--r--trunk/src/osd/sdl/debugwin.h23
-rw-r--r--trunk/src/osd/sdl/draw13.c1203
-rw-r--r--trunk/src/osd/sdl/drawogl.c3248
-rw-r--r--trunk/src/osd/sdl/drawsdl.c1154
-rw-r--r--trunk/src/osd/sdl/dview.c428
-rw-r--r--trunk/src/osd/sdl/dview.h53
-rw-r--r--trunk/src/osd/sdl/gl_shader_mgr.c283
-rw-r--r--trunk/src/osd/sdl/gl_shader_mgr.h54
-rw-r--r--trunk/src/osd/sdl/gl_shader_tool.c615
-rw-r--r--trunk/src/osd/sdl/gl_shader_tool.h198
-rw-r--r--trunk/src/osd/sdl/input.c1887
-rw-r--r--trunk/src/osd/sdl/input.h30
-rw-r--r--trunk/src/osd/sdl/keymaps/km-be.txt23
-rw-r--r--trunk/src/osd/sdl/keymaps/km-ch.txt14
-rw-r--r--trunk/src/osd/sdl/keymaps/km-de.txt14
-rw-r--r--trunk/src/osd/sdl/keymaps/km-fr-OSX.txt13
-rw-r--r--trunk/src/osd/sdl/keymaps/km-fr.txt23
-rw-r--r--trunk/src/osd/sdl/keymaps/km_it.txt12
-rw-r--r--trunk/src/osd/sdl/ledutil.sh97
-rw-r--r--trunk/src/osd/sdl/main.c76
-rw-r--r--trunk/src/osd/sdl/man/chdman.178
-rw-r--r--trunk/src/osd/sdl/man/jedutil.136
-rw-r--r--trunk/src/osd/sdl/man/ldplayer.152
-rw-r--r--trunk/src/osd/sdl/man/ldverify.124
-rw-r--r--trunk/src/osd/sdl/man/mame.11024
-rw-r--r--trunk/src/osd/sdl/man/romcmp.152
-rw-r--r--trunk/src/osd/sdl/man/testkeys.123
-rw-r--r--trunk/src/osd/sdl/osd_opengl.h1875
-rw-r--r--trunk/src/osd/sdl/osdsdl.h283
-rw-r--r--trunk/src/osd/sdl/osinline.h89
-rw-r--r--trunk/src/osd/sdl/osxutils.h22
-rw-r--r--trunk/src/osd/sdl/osxutils.m35
-rw-r--r--trunk/src/osd/sdl/output.c141
-rw-r--r--trunk/src/osd/sdl/output.h20
-rw-r--r--trunk/src/osd/sdl/sdl.mak573
-rw-r--r--trunk/src/osd/sdl/sdldir.c216
-rw-r--r--trunk/src/osd/sdl/sdlfile.c479
-rw-r--r--trunk/src/osd/sdl/sdlfile.h51
-rw-r--r--trunk/src/osd/sdl/sdlmain.c1132
-rw-r--r--trunk/src/osd/sdl/sdlmisc_macosx.c62
-rw-r--r--trunk/src/osd/sdl/sdlmisc_os2.c60
-rw-r--r--trunk/src/osd/sdl/sdlmisc_unix.c66
-rw-r--r--trunk/src/osd/sdl/sdlmisc_win32.c57
-rw-r--r--trunk/src/osd/sdl/sdlos.h58
-rw-r--r--trunk/src/osd/sdl/sdlos_macosx.c407
-rw-r--r--trunk/src/osd/sdl/sdlos_os2.c331
-rw-r--r--trunk/src/osd/sdl/sdlos_unix.c333
-rw-r--r--trunk/src/osd/sdl/sdlos_win32.c570
-rw-r--r--trunk/src/osd/sdl/sdlprefix.h83
-rw-r--r--trunk/src/osd/sdl/sdlptty_macosx.c87
-rw-r--r--trunk/src/osd/sdl/sdlptty_os2.c35
-rw-r--r--trunk/src/osd/sdl/sdlptty_unix.c97
-rw-r--r--trunk/src/osd/sdl/sdlptty_win32.c35
-rw-r--r--trunk/src/osd/sdl/sdlsocket.c153
-rw-r--r--trunk/src/osd/sdl/sdlsync.h204
-rw-r--r--trunk/src/osd/sdl/sdlsync_ntc.c529
-rw-r--r--trunk/src/osd/sdl/sdlsync_os2.c477
-rw-r--r--trunk/src/osd/sdl/sdlsync_sdl.c354
-rw-r--r--trunk/src/osd/sdl/sdlsync_tc.c389
-rw-r--r--trunk/src/osd/sdl/sdlsync_win32.c231
-rw-r--r--trunk/src/osd/sdl/sdlwork.c767
-rw-r--r--trunk/src/osd/sdl/shader/genc.sh46
-rw-r--r--trunk/src/osd/sdl/shader/glsl_bilinear.vsh7
-rw-r--r--trunk/src/osd/sdl/shader/glsl_bilinear_idx16_lut.fsh55
-rw-r--r--trunk/src/osd/sdl/shader/glsl_bilinear_idx16_lut.fsh.c57
-rw-r--r--trunk/src/osd/sdl/shader/glsl_bilinear_rgb32_dir.fsh54
-rw-r--r--trunk/src/osd/sdl/shader/glsl_bilinear_rgb32_dir.fsh.c56
-rw-r--r--trunk/src/osd/sdl/shader/glsl_bilinear_rgb32_lut.fsh58
-rw-r--r--trunk/src/osd/sdl/shader/glsl_bilinear_rgb32_lut.fsh.c60
-rw-r--r--trunk/src/osd/sdl/shader/glsl_general.vsh7
-rw-r--r--trunk/src/osd/sdl/shader/glsl_general.vsh.c9
-rw-r--r--trunk/src/osd/sdl/shader/glsl_plain.vsh7
-rw-r--r--trunk/src/osd/sdl/shader/glsl_plain_idx16_lut.fsh30
-rw-r--r--trunk/src/osd/sdl/shader/glsl_plain_idx16_lut.fsh.c32
-rw-r--r--trunk/src/osd/sdl/shader/glsl_plain_rgb32_dir.fsh24
-rw-r--r--trunk/src/osd/sdl/shader/glsl_plain_rgb32_dir.fsh.c26
-rw-r--r--trunk/src/osd/sdl/shader/glsl_plain_rgb32_lut.fsh28
-rw-r--r--trunk/src/osd/sdl/shader/glsl_plain_rgb32_lut.fsh.c30
-rw-r--r--trunk/src/osd/sdl/sound.c545
-rw-r--r--trunk/src/osd/sdl/strconv.c83
-rw-r--r--trunk/src/osd/sdl/strconv.h42
-rw-r--r--trunk/src/osd/sdl/testkeys.c189
-rw-r--r--trunk/src/osd/sdl/texcopy.c295
-rw-r--r--trunk/src/osd/sdl/texsrc.h114
-rw-r--r--trunk/src/osd/sdl/video.c836
-rw-r--r--trunk/src/osd/sdl/video.h157
-rw-r--r--trunk/src/osd/sdl/watchdog.c64
-rw-r--r--trunk/src/osd/sdl/watchdog.h35
-rw-r--r--trunk/src/osd/sdl/window.c1351
-rw-r--r--trunk/src/osd/sdl/window.h159
-rw-r--r--trunk/src/osd/windows/d3d8intf.c707
-rw-r--r--trunk/src/osd/windows/d3d9intf.c800
-rw-r--r--trunk/src/osd/windows/d3dcomm.h113
-rw-r--r--trunk/src/osd/windows/d3dhlsl.c2799
-rw-r--r--trunk/src/osd/windows/d3dhlsl.h213
-rw-r--r--trunk/src/osd/windows/d3dintf.h302
-rw-r--r--trunk/src/osd/windows/debugwin.c3129
-rw-r--r--trunk/src/osd/windows/debugwin.h63
-rw-r--r--trunk/src/osd/windows/drawd3d.c2607
-rw-r--r--trunk/src/osd/windows/drawd3d.h127
-rw-r--r--trunk/src/osd/windows/drawdd.c1465
-rw-r--r--trunk/src/osd/windows/drawgdi.c249
-rw-r--r--trunk/src/osd/windows/drawnone.c138
-rw-r--r--trunk/src/osd/windows/eivc.h201
-rw-r--r--trunk/src/osd/windows/eivcx86.h537
-rw-r--r--trunk/src/osd/windows/input.c2210
-rw-r--r--trunk/src/osd/windows/input.h61
-rw-r--r--trunk/src/osd/windows/ledutil.c774
-rw-r--r--trunk/src/osd/windows/main.c90
-rw-r--r--trunk/src/osd/windows/mame.man10
-rw-r--r--trunk/src/osd/windows/mame.rc47
-rw-r--r--trunk/src/osd/windows/multidef.h38
-rw-r--r--trunk/src/osd/windows/osinline.h84
-rw-r--r--trunk/src/osd/windows/output.c350
-rw-r--r--trunk/src/osd/windows/output.h129
-rw-r--r--trunk/src/osd/windows/sound.c446
-rw-r--r--trunk/src/osd/windows/sound.h52
-rw-r--r--trunk/src/osd/windows/strconv.c136
-rw-r--r--trunk/src/osd/windows/strconv.h71
-rw-r--r--trunk/src/osd/windows/vconv.c496
-rw-r--r--trunk/src/osd/windows/video.c476
-rw-r--r--trunk/src/osd/windows/video.h134
-rw-r--r--trunk/src/osd/windows/winclip.c122
-rw-r--r--trunk/src/osd/windows/windir.c187
-rw-r--r--trunk/src/osd/windows/window.c1905
-rw-r--r--trunk/src/osd/windows/window.h202
-rw-r--r--trunk/src/osd/windows/windows.mak365
-rw-r--r--trunk/src/osd/windows/winfile.c546
-rw-r--r--trunk/src/osd/windows/winfile.h48
-rw-r--r--trunk/src/osd/windows/winmain.c1850
-rw-r--r--trunk/src/osd/windows/winmain.h348
-rw-r--r--trunk/src/osd/windows/winmenu.c67
-rw-r--r--trunk/src/osd/windows/winmisc.c191
-rw-r--r--trunk/src/osd/windows/winprefix.h62
-rw-r--r--trunk/src/osd/windows/winsocket.c165
-rw-r--r--trunk/src/osd/windows/winsync.c204
-rw-r--r--trunk/src/osd/windows/wintime.c141
-rw-r--r--trunk/src/osd/windows/winutf8.c292
-rw-r--r--trunk/src/osd/windows/winutf8.h62
-rw-r--r--trunk/src/osd/windows/winutil.c156
-rw-r--r--trunk/src/osd/windows/winutil.h52
-rw-r--r--trunk/src/osd/windows/winwork.c850
-rw-r--r--trunk/src/tools/chdman.c3470
-rw-r--r--trunk/src/tools/jedutil.c317
-rw-r--r--trunk/src/tools/ldresample.c692
-rw-r--r--trunk/src/tools/ldverify.c851
-rw-r--r--trunk/src/tools/regrep.c1197
-rw-r--r--trunk/src/tools/romcmp.c755
-rw-r--r--trunk/src/tools/runtest.cmd190
-rw-r--r--trunk/src/tools/split.c470
-rw-r--r--trunk/src/tools/src2html.c1002
-rw-r--r--trunk/src/tools/srcclean.c263
-rw-r--r--trunk/src/tools/tools.mak193
-rw-r--r--trunk/src/tools/unidasm.c664
-rw-r--r--trunk/src/version.c41
4949 files changed, 2820594 insertions, 0 deletions
diff --git a/trunk/src/build/build.mak b/trunk/src/build/build.mak
new file mode 100644
index 00000000000..19a920ed8ed
--- /dev/null
+++ b/trunk/src/build/build.mak
@@ -0,0 +1,131 @@
+###########################################################################
+#
+# build.mak
+#
+# MAME build tools makefile
+#
+# Copyright Nicola Salmoria and the MAME Team.
+# Visit http://mamedev.org for licensing and usage restrictions.
+#
+###########################################################################
+
+OBJDIRS += \
+ $(BUILDOBJ) \
+
+
+
+#-------------------------------------------------
+# set of build targets
+#-------------------------------------------------
+
+FILE2STR_TARGET = $(BUILDOUT)/file2str$(BUILD_EXE)
+MAKEDEP_TARGET = $(BUILDOUT)/makedep$(BUILD_EXE)
+MAKELIST_TARGET = $(BUILDOUT)/makelist$(BUILD_EXE)
+MAKEDEV_TARGET = $(BUILDOUT)/makedev$(BUILD_EXE)
+PNG2BDC_TARGET = $(BUILDOUT)/png2bdc$(BUILD_EXE)
+VERINFO_TARGET = $(BUILDOUT)/verinfo$(BUILD_EXE)
+
+ifeq ($(TARGETOS),win32)
+FILE2STR = $(subst /,\,$(FILE2STR_TARGET))
+MAKEDEP = $(subst /,\,$(MAKEDEP_TARGET))
+MAKELIST = $(subst /,\,$(MAKELIST_TARGET))
+MAKEDEV = $(subst /,\,$(MAKEDEV_TARGET))
+PNG2BDC = $(subst /,\,$(PNG2BDC_TARGET))
+VERINFO = $(subst /,\,$(VERINFO_TARGET))
+else
+FILE2STR = $(FILE2STR_TARGET)
+MAKEDEP = $(MAKEDEP_TARGET)
+MAKELIST = $(MAKELIST_TARGET)
+MAKEDEV = $(MAKEDEV_TARGET)
+PNG2BDC = $(PNG2BDC_TARGET)
+VERINFO = $(VERINFO_TARGET)
+endif
+
+ifneq ($(CROSS_BUILD),1)
+BUILD += \
+ $(FILE2STR_TARGET) \
+ $(MAKEDEP_TARGET) \
+ $(MAKELIST_TARGET) \
+ $(MAKEDEV_TARGET) \
+ $(PNG2BDC_TARGET) \
+ $(VERINFO_TARGET) \
+
+
+
+#-------------------------------------------------
+# file2str
+#-------------------------------------------------
+
+FILE2STROBJS = \
+ $(BUILDOBJ)/file2str.o \
+
+$(FILE2STR_TARGET): $(FILE2STROBJS) $(LIBOCORE)
+ @echo Linking $@...
+ $(LD) $(LDFLAGS) $^ $(LIBS) -o $@
+
+
+
+#-------------------------------------------------
+# makedep
+#-------------------------------------------------
+
+MAKEDEPOBJS = \
+ $(BUILDOBJ)/makedep.o \
+
+$(MAKEDEP_TARGET): $(MAKEDEPOBJS) $(LIBUTIL) $(LIBOCORE) $(ZLIB)
+ @echo Linking $@...
+ $(LD) $(LDFLAGS) $^ $(LIBS) -o $@
+
+
+
+#-------------------------------------------------
+# makelist
+#-------------------------------------------------
+
+MAKELISTOBJS = \
+ $(BUILDOBJ)/makelist.o \
+
+$(MAKELIST_TARGET): $(MAKELISTOBJS) $(LIBUTIL) $(LIBOCORE) $(ZLIB)
+ @echo Linking $@...
+ $(LD) $(LDFLAGS) $^ $(LIBS) -o $@
+
+
+
+#-------------------------------------------------
+# makedev
+#-------------------------------------------------
+
+MAKEDEVOBJS = \
+ $(BUILDOBJ)/makedev.o \
+
+$(MAKEDEV_TARGET): $(MAKEDEVOBJS) $(LIBUTIL) $(LIBOCORE) $(ZLIB)
+ @echo Linking $@...
+ $(LD) $(LDFLAGS) $^ $(LIBS) -o $@
+
+
+
+#-------------------------------------------------
+# png2bdc
+#-------------------------------------------------
+
+PNG2BDCOBJS = \
+ $(BUILDOBJ)/png2bdc.o \
+
+$(PNG2BDC_TARGET): $(PNG2BDCOBJS) $(LIBUTIL) $(LIBOCORE) $(ZLIB)
+ @echo Linking $@...
+ $(LD) $(LDFLAGS) $^ $(LIBS) -o $@
+
+
+
+#-------------------------------------------------
+# verinfo
+#-------------------------------------------------
+
+VERINFOOBJS = \
+ $(BUILDOBJ)/verinfo.o
+
+$(VERINFO_TARGET): $(VERINFOOBJS) $(LIBOCORE)
+ @echo Linking $@...
+ $(LD) $(LDFLAGS) $^ $(LIBS) -o $@
+
+endif
diff --git a/trunk/src/build/file2str.c b/trunk/src/build/file2str.c
new file mode 100644
index 00000000000..7964ea977ee
--- /dev/null
+++ b/trunk/src/build/file2str.c
@@ -0,0 +1,101 @@
+/***************************************************************************
+
+ file2str.c
+
+ Simple file to string converter.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+
+/*-------------------------------------------------
+ main - primary entry point
+-------------------------------------------------*/
+
+int main(int argc, char *argv[])
+{
+ const char *srcfile, *dstfile, *varname, *type;
+ FILE *src, *dst;
+ unsigned char *buffer;
+ int bytes, offs;
+ int terminate = 1;
+
+ /* needs at least three arguments */
+ if (argc < 4)
+ {
+ fprintf(stderr,
+ "Usage:\n"
+ " laytostr <source.lay> <output.h> <varname> [<type>]\n"
+ "\n"
+ "The default <type> is char, with an assumed NULL terminator\n"
+ );
+ return 0;
+ }
+
+ /* extract arguments */
+ srcfile = argv[1];
+ dstfile = argv[2];
+ varname = argv[3];
+ type = (argc >= 5) ? argv[4] : "char";
+ if (argc >= 5)
+ terminate = 0;
+
+ /* open source file */
+ src = fopen(srcfile, "rb");
+ if (src == NULL)
+ {
+ fprintf(stderr, "Unable to open source file '%s'\n", srcfile);
+ return 1;
+ }
+
+ /* determine file size */
+ fseek(src, 0, SEEK_END);
+ bytes = ftell(src);
+ fseek(src, 0, SEEK_SET);
+
+ /* allocate memory */
+ buffer = (unsigned char *)malloc(bytes + 1);
+ if (buffer == NULL)
+ {
+ fclose(src);
+ fprintf(stderr, "Out of memory allocating %d byte buffer\n", bytes);
+ return 1;
+ }
+
+ /* read the source file */
+ fread(buffer, 1, bytes, src);
+ buffer[bytes] = 0;
+ fclose(src);
+
+ /* open dest file */
+ dst = fopen(dstfile, "w");
+ if (dst == NULL)
+ {
+ free(buffer);
+ fprintf(stderr, "Unable to open output file '%s'\n", dstfile);
+ return 1;
+ }
+
+ /* write the initial header */
+ fprintf(dst, "extern const %s %s[];\n", type, varname);
+ fprintf(dst, "const %s %s[] =\n{\n\t", type, varname);
+
+ /* write out the data */
+ for (offs = 0; offs < bytes + terminate; offs++)
+ {
+ fprintf(dst, "0x%02x%s", buffer[offs], (offs != bytes + terminate - 1) ? "," : "");
+ if (offs % 16 == 15)
+ fprintf(dst, "\n\t");
+ }
+ fprintf(dst, "\n};\n");
+
+ /* close the files */
+ free(buffer);
+ fclose(dst);
+ return 0;
+}
diff --git a/trunk/src/build/makedep.c b/trunk/src/build/makedep.c
new file mode 100644
index 00000000000..51862ec3feb
--- /dev/null
+++ b/trunk/src/build/makedep.c
@@ -0,0 +1,551 @@
+/***************************************************************************
+
+ MAME source code dependency generator
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+***************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <zlib.h>
+#include "osdcore.h"
+#include "astring.h"
+#include "corefile.h"
+#include "tagmap.h"
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define HASH_SIZE 193
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _include_path include_path;
+struct _include_path
+{
+ include_path * next;
+ const astring * path;
+};
+
+
+typedef struct _exclude_path exclude_path;
+struct _exclude_path
+{
+ exclude_path * next;
+ const astring * path;
+ int pathlen;
+ UINT8 recursive;
+};
+
+
+typedef struct _list_entry list_entry;
+struct _list_entry
+{
+ list_entry * next;
+ const astring * name;
+};
+
+
+typedef struct _file_entry file_entry;
+
+typedef struct _dependency dependency;
+struct _dependency
+{
+ dependency * next;
+ file_entry * file;
+};
+
+
+struct _file_entry
+{
+ astring * name;
+ dependency * deplist;
+};
+
+
+
+/***************************************************************************
+ GLOBAL VARIABLES
+***************************************************************************/
+
+static include_path *incpaths;
+static exclude_path *excpaths;
+static tagmap *file_map;
+
+
+
+/***************************************************************************
+ PROTOTYPES
+***************************************************************************/
+
+/* core output functions */
+static int recurse_dir(int srcrootlen, const astring *srcdir);
+static file_entry *compute_dependencies(int srcrootlen, const astring *srcfile);
+
+/* path helpers */
+static astring *find_include_file(int srcrootlen, const astring *srcfile, const astring *filename);
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+/* core output functions */
+static int recurse_dir(int srcrootlen, const astring *srcdir);
+static file_entry *compute_dependencies(int srcrootlen, const astring *srcfile);
+
+/* path helpers */
+static astring *find_include_file(int srcrootlen, const astring *srcfile, const astring *filename);
+
+
+
+/***************************************************************************
+ MAIN
+***************************************************************************/
+
+/*-------------------------------------------------
+ main - main entry point
+-------------------------------------------------*/
+
+int main(int argc, char *argv[])
+{
+ include_path **incpathhead = &incpaths;
+ exclude_path **excpathhead = &excpaths;
+ astring *srcdir = NULL;
+ int unadorned = 0;
+ int result;
+ int argnum;
+
+ /* loop over arguments */
+ for (argnum = 1; argnum < argc; argnum++)
+ {
+ char *arg = argv[argnum];
+
+ /* include path? */
+ if (arg[0] == '-' && arg[1] == 'I')
+ {
+ *incpathhead = (include_path *)malloc(sizeof(**incpathhead));
+ if (*incpathhead != NULL)
+ {
+ (*incpathhead)->next = NULL;
+ (*incpathhead)->path = astring_replacechr(astring_dupc(&arg[2]), '/', PATH_SEPARATOR[0]);
+ incpathhead = &(*incpathhead)->next;
+ }
+ }
+
+ /* exclude path? */
+ else if (arg[0] == '-' && arg[1] == 'X')
+ {
+ *excpathhead = (exclude_path *)malloc(sizeof(**excpathhead));
+ if (*excpathhead != NULL)
+ {
+ astring *path;
+ (*excpathhead)->next = NULL;
+ path = astring_replacechr(astring_dupc(&arg[2]), PATH_SEPARATOR[0], '/');
+ (*excpathhead)->recursive = (astring_replacec(path, astring_len(path) - 4, "/...", "") != 0);
+ (*excpathhead)->path = path;
+ (*excpathhead)->pathlen = astring_len(path);
+ excpathhead = &(*excpathhead)->next;
+ }
+ }
+
+ /* ignore -include which is used by sdlmame to include sdlprefix.h before all other includes */
+ else if (strcmp(arg,"-include") == 0)
+ {
+ argnum++;
+ }
+
+ /* other parameter */
+ else if (arg[0] != '-' && unadorned == 0)
+ {
+ srcdir = astring_replacechr(astring_dupc(arg), '/', PATH_SEPARATOR[0]);
+ unadorned++;
+ }
+ else
+ goto usage;
+ }
+
+ /* make sure we got 1 parameter */
+ if (srcdir == NULL)
+ goto usage;
+
+ /* create a tagmap for tracking files we've visited */
+ file_map = tagmap_alloc();
+
+ /* recurse over subdirectories */
+ result = recurse_dir(astring_len(srcdir), srcdir);
+
+ /* free source and destination directories */
+ tagmap_free(file_map);
+ astring_free(srcdir);
+ return result;
+
+usage:
+ fprintf(stderr, "Usage:\n%s <srcroot> [-Iincpath [-Iincpath [...]]]\n", argv[0]);
+ return 1;
+}
+
+
+
+/***************************************************************************
+ CORE OUTPUT FUNCTIONS
+***************************************************************************/
+
+static int compare_list_entries(const void *p1, const void *p2)
+{
+ const list_entry *entry1 = *(const list_entry **)p1;
+ const list_entry *entry2 = *(const list_entry **)p2;
+ return strcmp(astring_c(entry1->name), astring_c(entry2->name));
+}
+
+
+/*-------------------------------------------------
+ recurse_dependencies - recurse through the
+ dependencies found, adding the mto the tagmap
+ unless we already exist in the map
+-------------------------------------------------*/
+
+static void recurse_dependencies(file_entry *file, tagmap *map)
+{
+ int filelen = astring_len(file->name);
+ exclude_path *exclude;
+ dependency *dep;
+
+ /* skip if we're in an exclude path */
+ for (exclude = excpaths; exclude != NULL; exclude = exclude->next)
+ if (exclude->pathlen < filelen && strncmp(astring_c(file->name), astring_c(exclude->path), exclude->pathlen) == 0)
+ if (exclude->recursive || astring_chr(file->name, exclude->pathlen + 1, '/') == -1)
+ return;
+
+ /* attempt to add; if we get an error, we're already present */
+ if (tagmap_add(map, astring_c(file->name), file->name, FALSE) != TMERR_NONE)
+ return;
+
+ /* recurse the list from there */
+ for (dep = file->deplist; dep != NULL; dep = dep->next)
+ recurse_dependencies(dep->file, map);
+}
+
+
+/*-------------------------------------------------
+ recurse_dir - recurse through a directory
+-------------------------------------------------*/
+
+static int recurse_dir(int srcrootlen, const astring *srcdir)
+{
+ static const osd_dir_entry_type typelist[] = { ENTTYPE_DIR, ENTTYPE_FILE };
+ int result = 0;
+ int entindex;
+
+ /* iterate first over directories, then over files */
+ for (entindex = 0; entindex < ARRAY_LENGTH(typelist) && result == 0; entindex++)
+ {
+ osd_dir_entry_type entry_type = typelist[entindex];
+ const osd_directory_entry *entry;
+ list_entry **listarray = NULL;
+ list_entry *list = NULL;
+ list_entry *curlist;
+ osd_directory *dir;
+ int found = 0;
+
+ /* open the directory and iterate through it */
+ dir = osd_opendir(astring_c(srcdir));
+ if (dir == NULL)
+ {
+ result = 1;
+ goto error;
+ }
+
+ /* build up the list of files */
+ while ((entry = osd_readdir(dir)) != NULL)
+ if (entry->type == entry_type && entry->name[0] != '.')
+ {
+ list_entry *lentry = (list_entry *)malloc(sizeof(*lentry));
+ lentry->name = astring_dupc(entry->name);
+ lentry->next = list;
+ list = lentry;
+ found++;
+ }
+
+ /* close the directory */
+ osd_closedir(dir);
+
+ /* skip if nothing found */
+ if (found == 0)
+ continue;
+
+ /* allocate memory for sorting */
+ listarray = (list_entry **)malloc(sizeof(list_entry *) * found);
+ found = 0;
+ for (curlist = list; curlist != NULL; curlist = curlist->next)
+ listarray[found++] = curlist;
+
+ /* sort the list */
+ qsort(listarray, found, sizeof(listarray[0]), compare_list_entries);
+
+ /* rebuild the list */
+ list = NULL;
+ while (--found >= 0)
+ {
+ listarray[found]->next = list;
+ list = listarray[found];
+ }
+ free(listarray);
+
+ /* iterate through each file */
+ for (curlist = list; curlist != NULL && result == 0; curlist = curlist->next)
+ {
+ astring *srcfile;
+
+ /* build the source filename */
+ srcfile = astring_alloc();
+ astring_printf(srcfile, "%s%c%s", astring_c(srcdir), PATH_SEPARATOR[0], astring_c(curlist->name));
+
+ /* if we have a file, output it */
+ if (entry_type == ENTTYPE_FILE)
+ {
+ /* make sure we care, first */
+ if (core_filename_ends_with(astring_c(curlist->name), ".c"))
+ {
+ tagmap *depend_map = tagmap_alloc();
+ tagmap_entry *map_entry;
+ file_entry *file;
+ astring *target;
+ int taghash;
+
+ /* find dependencies */
+ file = compute_dependencies(srcrootlen, srcfile);
+ recurse_dependencies(file, depend_map);
+
+ /* convert the target from source to object (makes assumptions about rules) */
+ target = astring_dup(file->name);
+ astring_replacec(target, 0, "src/", "$(OBJ)/");
+ astring_replacec(target, 0, ".c", ".o");
+ printf("\n%s : \\\n", astring_c(target));
+
+ /* iterate over the hashed dependencies and output them as well */
+ for (taghash = 0; taghash < TAGMAP_HASH_SIZE; taghash++)
+ for (map_entry = depend_map->table[taghash]; map_entry != NULL; map_entry = map_entry->next)
+ printf("\t%s \\\n", astring_c((astring *)map_entry->object));
+
+ astring_free(target);
+ tagmap_free(depend_map);
+ }
+ }
+
+ /* if we have a directory, recurse */
+ else
+ result = recurse_dir(srcrootlen, srcfile);
+
+ /* free memory for the names */
+ astring_free(srcfile);
+ }
+
+ /* free all the allocated entries */
+ while (list != NULL)
+ {
+ list_entry *next = list->next;
+ astring_free((astring *)list->name);
+ free(list);
+ list = next;
+ }
+ }
+
+error:
+ return result;
+}
+
+
+/*-------------------------------------------------
+ output_file - output a file, converting to
+ HTML
+-------------------------------------------------*/
+
+static file_entry *compute_dependencies(int srcrootlen, const astring *srcfile)
+{
+ astring *normalfile;
+ UINT32 filelength;
+ file_entry *file;
+ char *filedata;
+ int index;
+
+ /* see if we already have an entry */
+ normalfile = astring_dup(srcfile);
+ astring_replacechr(normalfile, PATH_SEPARATOR[0], '/');
+ file = (file_entry *)tagmap_find(file_map, astring_c(normalfile));
+ if (file != NULL)
+ return file;
+
+ /* create a new header entry */
+ file = (file_entry *)malloc(sizeof(*file));
+ file->deplist = NULL;
+ file->name = normalfile;
+ tagmap_add(file_map, astring_c(file->name), file, FALSE);
+
+ /* read the source file */
+ if (core_fload(astring_c(srcfile), (void **)&filedata, &filelength) != FILERR_NONE)
+ {
+ fprintf(stderr, "Unable to read file '%s'\n", astring_c(srcfile));
+ return file;
+ }
+
+ /* find the #include directives in this file */
+ for (index = 0; index < filelength; index++)
+ if (filedata[index] == '#' && strncmp(&filedata[index + 1], "include", 7) == 0)
+ {
+ astring *filename, *target;
+ int scan = index;
+ dependency *dep;
+ int start;
+ int just_continue = 0;
+
+ /* first make sure we're not commented or quoted */
+ for (scan = index; scan > 2 && filedata[scan] != 13 && filedata[scan] != 10; scan--)
+ if ((filedata[scan] == '/' && filedata[scan - 1] == '/') || filedata[scan] == '"')
+ {
+ just_continue = 1;
+ break;
+ }
+ if (just_continue)
+ continue;
+
+ /* scan forward to find the quotes or bracket */
+ index += 7;
+ for (scan = index; scan < filelength && filedata[scan] != '<' && filedata[scan] != '"' && filedata[scan] != 13 && filedata[scan] != 10; scan++) ;
+
+ /* ignore if not found or if it's bracketed */
+ if (scan >= filelength || filedata[scan] != '"')
+ continue;
+ start = ++scan;
+
+ /* find the closing quote */
+ while (scan < filelength && filedata[scan] != '"')
+ scan++;
+ if (scan >= filelength)
+ continue;
+
+ /* find the include file */
+ filename = astring_dupch(&filedata[start], scan - start);
+ target = find_include_file(srcrootlen, srcfile, filename);
+
+ /* create a new dependency */
+ if (target != NULL)
+ {
+ dep = (dependency *)malloc(sizeof(*dep));
+ dep->next = file->deplist;
+ file->deplist = dep;
+ dep->file = compute_dependencies(srcrootlen, target);
+ astring_free(target);
+ }
+
+ astring_free(filename);
+ }
+
+ osd_free(filedata);
+ return file;
+}
+
+
+
+/***************************************************************************
+ HELPERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ find_include_file - find an include file
+-------------------------------------------------*/
+
+static astring *find_include_file(int srcrootlen, const astring *srcfile, const astring *filename)
+{
+ include_path *curpath;
+
+ /* iterate over include paths and find the file */
+ for (curpath = incpaths; curpath != NULL; curpath = curpath->next)
+ {
+ astring *srcincpath = astring_dup(curpath->path);
+ core_file *testfile;
+ int lastsepindex = 0;
+ int sepindex;
+
+ /* a '.' include path is specially treated */
+ if (astring_cmpc(curpath->path, ".") == 0)
+ astring_cpysubstr(srcincpath, srcfile, 0, astring_rchr(srcfile, 0, PATH_SEPARATOR[0]));
+
+ /* append the filename piecemeal to account for directories */
+ while ((sepindex = astring_chr(filename, lastsepindex, '/')) != -1)
+ {
+ astring *pathpart = astring_dupsubstr(filename, lastsepindex, sepindex - lastsepindex);
+
+ /* handle .. by removing a chunk from the incpath */
+ if (astring_cmpc(pathpart, "..") == 0)
+ {
+ int sepindex_part = astring_rchr(srcincpath, 0, PATH_SEPARATOR[0]);
+ if (sepindex_part != -1)
+ astring_substr(srcincpath, 0, sepindex_part);
+ }
+
+ /* otherwise, append a path separator and the pathpart */
+ else
+ astring_cat(astring_catc(srcincpath, PATH_SEPARATOR), pathpart);
+
+ /* advance past the previous index */
+ lastsepindex = sepindex + 1;
+
+ /* free the path part we extracted */
+ astring_free(pathpart);
+ }
+
+ /* now append the filename */
+ astring_catsubstr(astring_catc(srcincpath, PATH_SEPARATOR), filename, lastsepindex, -1);
+
+ /* see if we can open it */
+ if (core_fopen(astring_c(srcincpath), OPEN_FLAG_READ, &testfile) == FILERR_NONE)
+ {
+ /* close the file */
+ core_fclose(testfile);
+ return srcincpath;
+ }
+
+ /* free our include path */
+ astring_free(srcincpath);
+ }
+ return NULL;
+}
diff --git a/trunk/src/build/makedev.c b/trunk/src/build/makedev.c
new file mode 100644
index 00000000000..3bac0170235
--- /dev/null
+++ b/trunk/src/build/makedev.c
@@ -0,0 +1,233 @@
+/***************************************************************************
+
+ makedev.c
+
+ Create and sort the driver list.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+***************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "corefile.h"
+
+
+#define MAX_DEVICES 65536
+
+static const char *devlist[MAX_DEVICES];
+static int devcount;
+
+
+//-------------------------------------------------
+// driver_sort_callback - compare two items in
+// a string array
+//-------------------------------------------------
+
+int sort_callback(const void *elem1, const void *elem2)
+{
+ const char **item1 = (const char **)elem1;
+ const char **item2 = (const char **)elem2;
+ return strcmp(*item1, *item2);
+}
+
+
+//-------------------------------------------------
+// parse_file - parse a single file, may be
+// called recursively
+//-------------------------------------------------
+
+int parse_file(const char *srcfile)
+{
+ // read source file
+ void *buffer;
+ UINT32 length;
+ file_error filerr = core_fload(srcfile, &buffer, &length);
+ if (filerr != FILERR_NONE)
+ {
+ fprintf(stderr, "Unable to read source file '%s'\n", srcfile);
+ return 1;
+ }
+
+ // rip through it to find all drivers
+ char *srcptr = (char *)buffer;
+ char *endptr = srcptr + length;
+ int linenum = 1;
+ bool in_comment = false;
+ while (srcptr < endptr)
+ {
+ char c = *srcptr++;
+
+ // count newlines
+ if (c == 13 || c == 10)
+ {
+ if (c == 13 && *srcptr == 10)
+ srcptr++;
+ linenum++;
+ continue;
+ }
+
+ // skip any spaces
+ if (isspace(c))
+ continue;
+
+ // look for end of C comment
+ if (in_comment && c == '*' && *srcptr == '/')
+ {
+ srcptr++;
+ in_comment = false;
+ continue;
+ }
+
+ // skip anything else inside a C comment
+ if (in_comment)
+ continue;
+
+ // look for start of C comment
+ if (c == '/' && *srcptr == '*')
+ {
+ srcptr++;
+ in_comment = true;
+ continue;
+ }
+
+ // if we hit a C++ comment, scan to the end of line
+ if (c == '/' && *srcptr == '/')
+ {
+ while (srcptr < endptr && *srcptr != 13 && *srcptr != 10)
+ srcptr++;
+ continue;
+ }
+
+ // look for an import directive
+ if (c == '#')
+ {
+ char filename[256];
+ filename[0] = 0;
+ for (int pos = 0; srcptr < endptr && pos < ARRAY_LENGTH(filename) - 1 && !isspace(*srcptr); pos++)
+ {
+ filename[pos] = *srcptr++;
+ filename[pos+1] = 0;
+ }
+ fprintf(stderr, "Importing devices from '%s'\n", filename);
+ parse_file(filename);
+ continue;
+ }
+
+ // otherwise treat as a device name
+ char drivname[32];
+ drivname[0] = 0;
+ srcptr--;
+ for (int pos = 0; srcptr < endptr && pos < ARRAY_LENGTH(drivname) - 1 && !isspace(*srcptr); pos++)
+ {
+ drivname[pos] = *srcptr++;
+ drivname[pos+1] = 0;
+ }
+
+ // verify the name as valid
+ for (char *drivch = drivname; *drivch != 0; drivch++)
+ {
+ if ((*drivch >= 'A' && *drivch <= 'Z') || (*drivch >= '0' && *drivch <= '9') || *drivch == '_')
+ continue;
+ fprintf(stderr, "%s:%d - Invalid character '%c' in device type \"%s\"\n", srcfile, linenum, *drivch, drivname);
+ return 1;
+ }
+
+ // add it to the list
+ char *name = (char *)malloc(strlen(drivname) + 1);
+ strcpy(name, drivname);
+ devlist[devcount++] = name;
+ }
+
+ osd_free(buffer);
+
+ return 0;
+}
+
+
+//-------------------------------------------------
+// main - primary entry point
+//-------------------------------------------------
+
+int main(int argc, char *argv[])
+{
+ // needs at least 1 argument
+ if (argc < 2)
+ {
+ fprintf(stderr,
+ "Usage:\n"
+ " makedev <source.lst>\n"
+ );
+ return 0;
+ }
+
+ // extract arguments
+ const char *srcfile = argv[1];
+
+ // parse the root file, exit early upon failure
+ devcount = 0;
+ if (parse_file(srcfile))
+ return 1;
+
+ // output a count
+ if (devcount == 0)
+ {
+ fprintf(stderr, "No devices found\n");
+ } else {
+ fprintf(stderr, "%d devices found\n", devcount);
+ }
+
+ // sort the list
+ qsort(devlist, devcount, sizeof(*devlist), sort_callback);
+
+ // start with a header
+ printf("#include \"emu.h\"\n\n");
+
+ // output the list of externs first
+ for (int index = 0; index < devcount; index++)
+ printf("extern const device_type %s;\n", devlist[index]);
+ printf("\n");
+
+ // then output the array
+ printf("const device_type * s_devices_sorted[] =\n");
+ printf("{\n");
+ for (int index = 0; index < devcount; index++)
+ printf("\t&%s%s\n", devlist[index], (index == devcount - 1) ? "" : ",");
+ printf("};\n");
+ printf("\n");
+
+ // also output a global count
+ printf("int m_device_count = %d;\n", devcount);
+
+ return 0;
+}
diff --git a/trunk/src/build/makelist.c b/trunk/src/build/makelist.c
new file mode 100644
index 00000000000..1edc747c810
--- /dev/null
+++ b/trunk/src/build/makelist.c
@@ -0,0 +1,236 @@
+/***************************************************************************
+
+ makelist.c
+
+ Create and sort the driver list.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+***************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "corefile.h"
+
+
+#define MAX_DRIVERS 65536
+
+static const char *drivlist[MAX_DRIVERS];
+static int drivcount;
+
+
+//-------------------------------------------------
+// driver_sort_callback - compare two items in
+// a string array
+//-------------------------------------------------
+
+int sort_callback(const void *elem1, const void *elem2)
+{
+ const char **item1 = (const char **)elem1;
+ const char **item2 = (const char **)elem2;
+ return strcmp(*item1, *item2);
+}
+
+
+//-------------------------------------------------
+// parse_file - parse a single file, may be
+// called recursively
+//-------------------------------------------------
+
+int parse_file(const char *srcfile)
+{
+ // read source file
+ void *buffer;
+ UINT32 length;
+ file_error filerr = core_fload(srcfile, &buffer, &length);
+ if (filerr != FILERR_NONE)
+ {
+ fprintf(stderr, "Unable to read source file '%s'\n", srcfile);
+ return 1;
+ }
+
+ // rip through it to find all drivers
+ char *srcptr = (char *)buffer;
+ char *endptr = srcptr + length;
+ int linenum = 1;
+ bool in_comment = false;
+ while (srcptr < endptr)
+ {
+ char c = *srcptr++;
+
+ // count newlines
+ if (c == 13 || c == 10)
+ {
+ if (c == 13 && *srcptr == 10)
+ srcptr++;
+ linenum++;
+ continue;
+ }
+
+ // skip any spaces
+ if (isspace(c))
+ continue;
+
+ // look for end of C comment
+ if (in_comment && c == '*' && *srcptr == '/')
+ {
+ srcptr++;
+ in_comment = false;
+ continue;
+ }
+
+ // skip anything else inside a C comment
+ if (in_comment)
+ continue;
+
+ // look for start of C comment
+ if (c == '/' && *srcptr == '*')
+ {
+ srcptr++;
+ in_comment = true;
+ continue;
+ }
+
+ // if we hit a C++ comment, scan to the end of line
+ if (c == '/' && *srcptr == '/')
+ {
+ while (srcptr < endptr && *srcptr != 13 && *srcptr != 10)
+ srcptr++;
+ continue;
+ }
+
+ // look for an import directive
+ if (c == '#')
+ {
+ char filename[256];
+ filename[0] = 0;
+ for (int pos = 0; srcptr < endptr && pos < ARRAY_LENGTH(filename) - 1 && !isspace(*srcptr); pos++)
+ {
+ filename[pos] = *srcptr++;
+ filename[pos+1] = 0;
+ }
+ fprintf(stderr, "Importing drivers from '%s'\n", filename);
+ parse_file(filename);
+ continue;
+ }
+
+ // otherwise treat as a driver name
+ char drivname[32];
+ drivname[0] = 0;
+ srcptr--;
+ for (int pos = 0; srcptr < endptr && pos < ARRAY_LENGTH(drivname) - 1 && !isspace(*srcptr); pos++)
+ {
+ drivname[pos] = *srcptr++;
+ drivname[pos+1] = 0;
+ }
+
+ // verify the name as valid
+ for (char *drivch = drivname; *drivch != 0; drivch++)
+ {
+ if ((*drivch >= 'a' && *drivch <= 'z') || (*drivch >= '0' && *drivch <= '9') || *drivch == '_')
+ continue;
+ fprintf(stderr, "%s:%d - Invalid character '%c' in driver \"%s\"\n", srcfile, linenum, *drivch, drivname);
+ return 1;
+ }
+
+ // add it to the list
+ char *name = (char *)malloc(strlen(drivname) + 1);
+ strcpy(name, drivname);
+ drivlist[drivcount++] = name;
+ }
+
+ osd_free(buffer);
+
+ return 0;
+}
+
+
+//-------------------------------------------------
+// main - primary entry point
+//-------------------------------------------------
+
+int main(int argc, char *argv[])
+{
+ // needs at least 1 argument
+ if (argc < 2)
+ {
+ fprintf(stderr,
+ "Usage:\n"
+ " makelist <source.lst>\n"
+ );
+ return 0;
+ }
+
+ // extract arguments
+ const char *srcfile = argv[1];
+
+ // parse the root file, exit early upon failure
+ drivcount = 0;
+ if (parse_file(srcfile))
+ return 1;
+
+ // add a reference to the ___empty driver
+ drivlist[drivcount++] = "___empty";
+
+ // output a count
+ if (drivcount == 0)
+ {
+ fprintf(stderr, "No drivers found\n");
+ return 1;
+ }
+ fprintf(stderr, "%d drivers found\n", drivcount);
+
+ // sort the list
+ qsort(drivlist, drivcount, sizeof(*drivlist), sort_callback);
+
+ // start with a header
+ printf("#include \"emu.h\"\n\n");
+
+ // output the list of externs first
+ for (int index = 0; index < drivcount; index++)
+ printf("GAME_EXTERN(%s);\n", drivlist[index]);
+ printf("\n");
+
+ // then output the array
+ printf("const game_driver * const driver_list::s_drivers_sorted[%d] =\n", drivcount);
+ printf("{\n");
+ for (int index = 0; index < drivcount; index++)
+ printf("\t&GAME_NAME(%s)%s\n", drivlist[index], (index == drivcount - 1) ? "" : ",");
+ printf("};\n");
+ printf("\n");
+
+ // also output a global count
+ printf("int driver_list::s_driver_count = %d;\n", drivcount);
+
+ return 0;
+}
diff --git a/trunk/src/build/png2bdc.c b/trunk/src/build/png2bdc.c
new file mode 100644
index 00000000000..dce72a642ee
--- /dev/null
+++ b/trunk/src/build/png2bdc.c
@@ -0,0 +1,453 @@
+/***************************************************************************
+
+ png2bdc.c
+
+ Super-simple PNG to BDC file generator
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+****************************************************************************
+
+ Format of PNG data:
+
+ Multiple rows of characters. A black pixel means "on". All other colors
+ mean "off". Each row looks like this:
+
+ * 8888 *** *
+ * 4444 * * **
+ * 2222 * * *
+ * 1111 * * *
+ * * * *
+ ** *** ***
+ *
+ *
+
+ ****** ****
+
+ The column of pixels on the left-hand side (column 0) indicates the
+ character cell height. This column must be present on each row and
+ the height must be consistent for each row.
+
+ Protruding one pixel into column 1 is the baseline indicator. There
+ should only be one row with a pixel in column 1 for each line, and
+ that pixel row index should be consistent for each row.
+
+ In columns 2-5 are a 4-hex-digit starting character index number. This
+ is encoded as binary value. Each column is 4 pixels tall and represents
+ one binary digit. The character index number is the unicode character
+ number of the first character encoded in this row; subsequent
+ characters in the row are at increasing character indices.
+
+ Starting in column 6 and beyond are the actual character bitmaps.
+ Below them, in the second row after the last row of the character,
+ is a solid line that indicates the width of the character, and also
+ where the character bitmap begins and ends.
+
+***************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "png.h"
+
+
+/***************************************************************************
+ CONSTANTS & DEFINES
+***************************************************************************/
+
+#define CACHED_CHAR_SIZE 12
+#define CACHED_HEADER_SIZE 16
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+/* a render_font contains information about a single character in a font */
+typedef struct _render_font_char render_font_char;
+struct _render_font_char
+{
+ INT32 width; /* width from this character to the next */
+ INT32 xoffs, yoffs; /* X and Y offset from baseline to top,left of bitmap */
+ INT32 bmwidth, bmheight; /* width and height of bitmap */
+ bitmap_t * bitmap; /* pointer to the bitmap containing the raw data */
+};
+
+
+/* a render_font contains information about a font */
+typedef struct _render_font render_font;
+struct _render_font
+{
+ int height; /* height of the font, from ascent to descent */
+ int yoffs; /* y offset from baseline to descent */
+ render_font_char chars[65536]; /* array of characters */
+};
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+INLINE int pixel_is_set(bitmap_t *bitmap, int y, int x)
+{
+ return (*BITMAP_ADDR32(bitmap, y, x) & 0xffffff) == 0;
+}
+
+
+
+/***************************************************************************
+ MAIN
+***************************************************************************/
+
+static int render_font_save_cached(render_font *font, const char *filename, UINT32 hash)
+{
+ file_error filerr;
+ render_font_char *ch;
+ UINT32 bytes_written;
+ UINT8 *tempbuffer;
+ UINT8 *chartable;
+ core_file *file;
+ int numchars;
+ UINT8 *dest;
+ int tableindex;
+ int chnum;
+
+ /* attempt to open the file */
+ filerr = core_fopen(filename, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, &file);
+ if (filerr != FILERR_NONE)
+ return 1;
+
+ /* determine the number of characters */
+ numchars = 0;
+ for (chnum = 0; chnum < 65536; chnum++)
+ if (font->chars[chnum].width > 0)
+ numchars++;
+
+ /* allocate an array to hold the character data */
+ chartable = (UINT8 *)malloc(numchars * CACHED_CHAR_SIZE);
+
+ /* allocate a temp buffer to compress into */
+ tempbuffer = (UINT8 *)malloc(65536);
+ if (chartable == NULL || tempbuffer == NULL)
+ goto error;
+
+ memset(chartable, 0, numchars * CACHED_CHAR_SIZE);
+
+ /* write the header */
+ dest = tempbuffer;
+ *dest++ = 'f';
+ *dest++ = 'o';
+ *dest++ = 'n';
+ *dest++ = 't';
+ *dest++ = hash >> 24;
+ *dest++ = hash >> 16;
+ *dest++ = hash >> 8;
+ *dest++ = hash & 0xff;
+ *dest++ = font->height >> 8;
+ *dest++ = font->height & 0xff;
+ *dest++ = font->yoffs >> 8;
+ *dest++ = font->yoffs & 0xff;
+ *dest++ = numchars >> 24;
+ *dest++ = numchars >> 16;
+ *dest++ = numchars >> 8;
+ *dest++ = numchars & 0xff;
+ bytes_written = core_fwrite(file, tempbuffer, dest - tempbuffer);
+ if (bytes_written != dest - tempbuffer)
+ goto error;
+
+ /* write the empty table to the beginning of the file */
+ bytes_written = core_fwrite(file, chartable, numchars * CACHED_CHAR_SIZE);
+ if (bytes_written != numchars * CACHED_CHAR_SIZE)
+ goto error;
+
+ /* loop over all characters */
+ tableindex = 0;
+ for (chnum = 0; chnum < 65536; chnum++)
+ {
+ ch = &font->chars[chnum];
+ if (ch->width > 0)
+ {
+ UINT8 accum, accbit;
+ int x, y;
+
+ /* write out a bit-compressed bitmap if we have one */
+ if (ch->bitmap != NULL)
+ {
+ /* write the data to the tempbuffer */
+ dest = tempbuffer;
+ accum = 0;
+ accbit = 7;
+
+ /* bit-encode the character data */
+ for (y = 0; y < ch->bmheight; y++)
+ {
+ int desty = y + font->height + font->yoffs - ch->yoffs - ch->bmheight;
+ const UINT32 *src = (desty >= 0 && desty < font->height) ? BITMAP_ADDR32(ch->bitmap, desty, 0) : NULL;
+ for (x = 0; x < ch->bmwidth; x++)
+ {
+ if (src != NULL && src[x] != 0)
+ accum |= 1 << accbit;
+ if (accbit-- == 0)
+ {
+ *dest++ = accum;
+ accum = 0;
+ accbit = 7;
+ }
+ }
+ }
+
+ /* flush any extra */
+ if (accbit != 7)
+ *dest++ = accum;
+
+ /* write the data */
+ bytes_written = core_fwrite(file, tempbuffer, dest - tempbuffer);
+ if (bytes_written != dest - tempbuffer)
+ goto error;
+
+ /* free the bitmap and texture */
+ bitmap_free(ch->bitmap);
+ ch->bitmap = NULL;
+ }
+
+ /* compute the table entry */
+ dest = &chartable[tableindex++ * CACHED_CHAR_SIZE];
+ *dest++ = chnum >> 8;
+ *dest++ = chnum & 0xff;
+ *dest++ = ch->width >> 8;
+ *dest++ = ch->width & 0xff;
+ *dest++ = ch->xoffs >> 8;
+ *dest++ = ch->xoffs & 0xff;
+ *dest++ = ch->yoffs >> 8;
+ *dest++ = ch->yoffs & 0xff;
+ *dest++ = ch->bmwidth >> 8;
+ *dest++ = ch->bmwidth & 0xff;
+ *dest++ = ch->bmheight >> 8;
+ *dest++ = ch->bmheight & 0xff;
+ }
+ }
+
+ /* seek back to the beginning and rewrite the table */
+ core_fseek(file, CACHED_HEADER_SIZE, SEEK_SET);
+ bytes_written = core_fwrite(file, chartable, numchars * CACHED_CHAR_SIZE);
+ if (bytes_written != numchars * CACHED_CHAR_SIZE)
+ goto error;
+
+ /* all done */
+ core_fclose(file);
+ free(tempbuffer);
+ free(chartable);
+ return 0;
+
+error:
+ core_fclose(file);
+ osd_rmfile(filename);
+ free(tempbuffer);
+ free(chartable);
+ return 1;
+}
+
+
+/*-------------------------------------------------
+ bitmap_to_chars - convert a bitmap to
+ characters in the given font
+-------------------------------------------------*/
+
+static int bitmap_to_chars(bitmap_t *bitmap, render_font *font)
+{
+ int rowstart = 0;
+ int x, y;
+
+ /* loop over rows */
+ while (rowstart < bitmap->height)
+ {
+ int rowend, baseline, colstart;
+ int chstart;
+
+ /* find the top of the row */
+ for ( ; rowstart < bitmap->height; rowstart++)
+ if (pixel_is_set(bitmap, rowstart, 0))
+ break;
+ if (rowstart >= bitmap->height)
+ break;
+
+ /* find the bottom of the row */
+ for (rowend = rowstart + 1; rowend < bitmap->height; rowend++)
+ if (!pixel_is_set(bitmap, rowend, 0))
+ {
+ rowend--;
+ break;
+ }
+
+ /* find the baseline */
+ for (baseline = rowstart; baseline <= rowend; baseline++)
+ if (pixel_is_set(bitmap, baseline, 1))
+ break;
+ if (baseline > rowend)
+ {
+ fprintf(stderr, "No baseline found between rows %d-%d\n", rowstart, rowend);
+ break;
+ }
+
+ /* set or confirm the height */
+ if (font->height == 0)
+ {
+ font->height = rowend - rowstart + 1;
+ font->yoffs = baseline - rowend;
+ }
+ else
+ {
+ if (font->height != rowend - rowstart + 1)
+ {
+ fprintf(stderr, "Inconsistent font height at rows %d-%d\n", rowstart, rowend);
+ break;
+ }
+ if (font->yoffs != baseline - rowend)
+ {
+ fprintf(stderr, "Inconsistent baseline at rows %d-%d\n", rowstart, rowend);
+ break;
+ }
+ }
+
+ /* decode the starting character */
+ chstart = 0;
+ for (x = 0; x < 4; x++)
+ for (y = 0; y < 4; y++)
+ chstart = (chstart << 1) | pixel_is_set(bitmap, rowstart + y, 2 + x);
+
+ /* print info */
+// printf("Row %d-%d, baseline %d, character start %X\n", rowstart, rowend, baseline, chstart);
+
+ /* scan the column to find characters */
+ colstart = 0;
+ while (colstart < bitmap->width)
+ {
+ render_font_char *ch = &font->chars[chstart];
+ int colend;
+
+ /* find the start of the character */
+ for ( ; colstart < bitmap->width; colstart++)
+ if (pixel_is_set(bitmap, rowend + 2, colstart))
+ break;
+ if (colstart >= bitmap->width)
+ break;
+
+ /* find the end of the character */
+ for (colend = colstart + 1; colend < bitmap->width; colend++)
+ if (!pixel_is_set(bitmap, rowend + 2, colend))
+ {
+ colend--;
+ break;
+ }
+
+ // skip char which code is already registered
+ if (ch->width <= 0)
+ {
+ /* print info */
+// printf(" Character %X - width = %d\n", chstart, colend - colstart + 1);
+
+ /* allocate a bitmap */
+ ch->bitmap = bitmap_alloc(colend - colstart + 1, font->height, BITMAP_FORMAT_ARGB32);
+ if (ch->bitmap == NULL)
+ {
+ fprintf(stderr, "Error allocating character bitmap (%dx%d)\n", colend - colstart + 1, font->height);
+ continue;
+ }
+
+ /* plot the character */
+ for (y = rowstart; y <= rowend; y++)
+ for (x = colstart; x <= colend; x++)
+ *BITMAP_ADDR32(ch->bitmap, y - rowstart, x - colstart) = pixel_is_set(bitmap, y, x) ? 0xffffffff : 0x00000000;
+
+ /* set the character parameters */
+ ch->width = colend - colstart + 1;
+ ch->xoffs = 0;
+ ch->yoffs = font->yoffs;
+ ch->bmwidth = ch->bitmap->width;
+ ch->bmheight = ch->bitmap->height;
+ }
+
+ /* next character */
+ chstart++;
+ colstart = colend + 1;
+ }
+
+ /* next row */
+ rowstart = rowend + 1;
+ }
+
+ /* return non-zero (TRUE) if we errored */
+ return (rowstart < bitmap->height);
+}
+
+
+/*-------------------------------------------------
+ main - main entry point
+-------------------------------------------------*/
+
+int main(int argc, char *argv[])
+{
+ const char *bdcname;
+ render_font *font;
+ int error = FALSE;
+ int curarg;
+
+ /* validate arguments */
+ if (argc < 3)
+ {
+ fprintf(stderr, "Usage:\n%s <input.png> [<input2.png> [...]] <output.bdc>\n", argv[0]);
+ return 1;
+ }
+ bdcname = argv[argc - 1];
+
+ /* allocate a font */
+ font = (render_font *)malloc(sizeof(*font));
+ if (font == NULL)
+ return 1;
+ memset(font, 0, sizeof(*font));
+
+ /* iterate over input files */
+ for (curarg = 1; curarg < argc - 1; curarg++)
+ {
+ const char *pngname = argv[curarg];
+ file_error filerr;
+ png_error pngerr;
+ bitmap_t *bitmap;
+ core_file *file;
+
+ /* load the png file */
+ filerr = core_fopen(pngname, OPEN_FLAG_READ, &file);
+ if (filerr != FILERR_NONE)
+ {
+ fprintf(stderr, "Error %d attempting to open PNG file\n", filerr);
+ error = TRUE;
+ break;
+ }
+ pngerr = png_read_bitmap(file, &bitmap);
+ core_fclose(file);
+ if (pngerr != PNGERR_NONE)
+ {
+ fprintf(stderr, "Error %d reading PNG file\n", pngerr);
+ error = TRUE;
+ break;
+ }
+
+ /* parse the PNG into characters */
+ error = bitmap_to_chars(bitmap, font);
+ bitmap_free(bitmap);
+ if (error)
+ break;
+ }
+
+ /* write out the resulting font */
+ if (!error)
+ render_font_save_cached(font, bdcname, 0);
+
+ /* cleanup after ourselves */
+ free(font);
+ return error;
+}
diff --git a/trunk/src/build/verinfo.c b/trunk/src/build/verinfo.c
new file mode 100644
index 00000000000..473ac7dc6d2
--- /dev/null
+++ b/trunk/src/build/verinfo.c
@@ -0,0 +1,302 @@
+//============================================================
+//
+// verinfo.c - Version resource emitter code
+//
+// Copyright Nicola Salmoria and the MAME Team.
+// Visit http://mamedev.org for licensing and usage restrictions.
+//
+//============================================================
+
+#include <stdio.h>
+#include <ctype.h>
+
+#include <string.h>
+#include <stdlib.h>
+
+typedef unsigned char UINT8;
+
+#define ARRAY_LENGTH(x) (sizeof(x) / sizeof(x[0]))
+#define BUILD_WINDOWS (0)
+#define BUILD_WINUI (1)
+#define BUILD_MESS (2)
+
+//============================================================
+// TYPE DEFINITIONS
+//============================================================
+
+typedef struct _version_info version_info;
+struct _version_info
+{
+ int version_major;
+ int version_minor;
+ int version_build;
+ int version_subbuild;
+ const char *version_string;
+ const char *author;
+ const char *comments;
+ const char *company_name;
+ const char *file_description;
+ const char *internal_name;
+ const char *legal_copyright;
+ const char *original_filename;
+ const char *product_name;
+};
+
+
+
+//============================================================
+// STATIC
+//============================================================
+
+static int build;
+
+
+//============================================================
+// emit_version_info
+//============================================================
+
+static void emit_version_info(const version_info *v)
+{
+ printf("VS_VERSION_INFO VERSIONINFO\n");
+ printf("\tFILEVERSION %d,%d,%d,%d\n", v->version_major, v->version_minor, v->version_build, v->version_subbuild);
+ printf("\tPRODUCTVERSION %d,%d,%d,%d\n", v->version_major, v->version_minor, v->version_build, v->version_subbuild);
+ printf("\tFILEFLAGSMASK 0x3fL\n");
+#ifdef MAME_DEBUG
+ if (v->version_build == 0)
+ printf("\tFILEFLAGS VS_FF_DEBUG\n");
+ else
+ printf("\tFILEFLAGS VS_FF_PRERELEASE | VS_FF_DEBUG\n");
+#else
+ if (v->version_build == 0)
+ printf("\tFILEFLAGS 0x0L\n");
+ else
+ printf("\tFILEFLAGS VS_FF_PRERELEASE\n");
+#endif
+ printf("\tFILEOS VOS_NT_WINDOWS32\n");
+ printf("\tFILETYPE VFT_APP\n");
+ printf("\tFILESUBTYPE VFT2_UNKNOWN\n");
+ printf("BEGIN\n");
+ printf("\tBLOCK \"StringFileInfo\"\n");
+ printf("\tBEGIN\n");
+ printf("#ifdef UNICODE\n");
+ printf("\t\tBLOCK \"040904b0\"\n");
+ printf("#else\n");
+ printf("\t\tBLOCK \"040904E4\"\n");
+ printf("#endif\n");
+ printf("\t\tBEGIN\n");
+ if (v->author != NULL)
+ printf("\t\t\tVALUE \"Author\", \"%s\\0\"\n", v->author);
+ if (v->comments != NULL)
+ printf("\t\t\tVALUE \"Comments\", \"%s\\0\"\n", v->comments);
+ if (v->company_name != NULL)
+ printf("\t\t\tVALUE \"CompanyName\", \"%s\\0\"\n", v->company_name);
+ if (v->file_description != NULL)
+ printf("\t\t\tVALUE \"FileDescription\", \"%s\\0\"\n", v->file_description);
+ printf("\t\t\tVALUE \"FileVersion\", \"%d, %d, %d, %d\\0\"\n", v->version_major, v->version_minor, v->version_build, v->version_subbuild);
+ if (v->internal_name != NULL)
+ printf("\t\t\tVALUE \"InternalName\", \"%s\\0\"\n", v->internal_name);
+ if (v->legal_copyright != NULL)
+ printf("\t\t\tVALUE \"LegalCopyright\", \"%s\\0\"\n", v->legal_copyright);
+ if (v->original_filename != NULL)
+ printf("\t\t\tVALUE \"OriginalFilename\", \"%s\\0\"\n", v->original_filename);
+ if (v->product_name != NULL)
+ printf("\t\t\tVALUE \"ProductName\", \"%s\\0\"\n", v->product_name);
+ printf("\t\t\tVALUE \"ProductVersion\", \"%s\\0\"\n", v->version_string);
+ printf("\t\tEND\n");
+ printf("\tEND\n");
+ printf("\tBLOCK \"VarFileInfo\"\n");
+ printf("\tBEGIN\n");
+ printf("#ifdef UNICODE\n");
+ printf("\t\tVALUE \"Translation\", 0x409, 1200\n");
+ printf("#else\n");
+ printf("\t\tVALUE \"Translation\", 0x409, 1252\n");
+ printf("#endif\n");
+ printf("\tEND\n");
+ printf("END\n");
+}
+
+
+
+//============================================================
+// parse_version_digit
+//============================================================
+
+static int parse_version_digit(const char *str, int *position)
+{
+ int value = 0;
+
+ while (str[*position] != 0 && !isspace((UINT8)str[*position]) && !isdigit((UINT8)str[*position]))
+ (*position)++;
+
+ if (str[*position] != 0 && isdigit((UINT8)str[*position]))
+ {
+ sscanf(&str[*position], "%d", &value);
+ while (isdigit((UINT8)str[*position]))
+ (*position)++;
+ }
+ return value;
+}
+
+
+
+//============================================================
+// parse_version
+//============================================================
+
+static int parse_version(char *str, int *version_major, int *version_minor, int *version_micro, const char **version_string)
+{
+ char *version;
+ int position = 0;
+
+ // find the version string
+ version = strstr(str, "build_version");
+ if (version != NULL)
+ version = strchr(version, '"');
+ if (version == NULL)
+ {
+ fprintf(stderr, "Unable to find build_version string\n");
+ return 1;
+ }
+ version++;
+ *strchr(version, ' ') = 0;
+
+ *version_string = version;
+ *version_major = parse_version_digit(version, &position);
+ *version_minor = parse_version_digit(version, &position);
+ *version_micro = parse_version_digit(version, &position);
+ return 0;
+}
+
+
+
+//============================================================
+// main
+//============================================================
+static int usage(char *me)
+{
+ fprintf(stderr, "Usage: %s [-b windows|winui|mess] <filename>\n", me);
+ return 1;
+}
+
+
+//============================================================
+// main
+//============================================================
+
+int main(int argc, char *argv[])
+{
+ version_info v;
+ char legal_copyright[512];
+ char *buffer;
+ size_t size;
+ int opt;
+ FILE *f;
+
+ memset(&v, 0, sizeof(v));
+ build = BUILD_WINDOWS;
+
+ // validate parameters
+ opt = 1;
+ while (opt < argc && *argv[opt] == '-')
+ {
+ if (!strcmp(argv[opt], "-b"))
+ {
+ char *p = argv[++opt];
+ if (!strcmp(p,"windows"))
+ build = BUILD_WINDOWS;
+ else if (!strcmp(p,"winui"))
+ build = BUILD_WINUI;
+ else if (!strcmp(p,"mess"))
+ build = BUILD_MESS;
+ else
+ return usage(argv[0]);
+ }
+ else
+ return usage(argv[0]);
+ opt++;
+ }
+
+ if (opt != argc-1 )
+ {
+ return usage(argv[0]);
+ }
+
+ // open the file
+ f = fopen(argv[argc-1], "rb");
+ if (f == NULL)
+ {
+ fprintf(stderr, "Error opening file %s\n", argv[argc-1]);
+ return 1;
+ }
+
+ // get the file size
+ fseek(f, 0, SEEK_END);
+ size = ftell(f);
+ fseek(f, 0, SEEK_SET);
+
+ // allocate a buffer
+ buffer = (char *)malloc(size + 1);
+ if (buffer == NULL)
+ {
+ fclose(f);
+ fprintf(stderr, "Error allocating %ld bytes\n", (long) size + 1);
+ return 1;
+ }
+
+ // read the file contents and NULL-terminate
+ fread(buffer, 1, size, f);
+ fclose(f);
+ buffer[size] = 0;
+
+ // parse out version string
+ if (parse_version(buffer, &v.version_major, &v.version_minor, &v.version_build, &v.version_string))
+ {
+ fprintf(stderr, "Error parsing version from '%s'\n", buffer);
+ free(buffer);
+ return 1;
+ }
+
+ if (build == BUILD_MESS)
+ {
+ // MESS
+ v.author = "MESS Team";
+ v.comments = "Multi Emulation Super System";
+ v.company_name = "MESS Team";
+ v.file_description = "Multi Emulation Super System";
+ v.internal_name = "MESS";
+ v.original_filename = "MESS";
+ v.product_name = "MESS";
+ }
+ else if (build == BUILD_WINUI)
+ {
+ // MAMEUI
+ v.author = "Christopher Kirmse and the MAMEUI team";
+ v.comments = "Multiple Arcade Machine Emulator with GUI";
+ v.company_name = "MAME Team";
+ v.file_description = "Multiple Arcade Machine Emulator with GUI";
+ v.internal_name = "MAMEUI";
+ v.original_filename = "MAMEUI";
+ v.product_name = "MAMEUI";
+ }
+ else
+ {
+ // MAME
+ v.author = "Nicola Salmoria and the MAME Team";
+ v.comments = "Multiple Arcade Machine Emulator";
+ v.company_name = "MAME Team";
+ v.file_description = "Multiple Arcade Machine Emulator";
+ v.internal_name = "MAME";
+ v.original_filename = "MAME";
+ v.product_name = "MAME";
+ }
+
+ // build legal_copyright string
+ v.legal_copyright = legal_copyright;
+ snprintf(legal_copyright, ARRAY_LENGTH(legal_copyright), "Copyright Nicola Salmoria and the MAME team");
+
+ // emit the info
+ emit_version_info(&v);
+
+ free(buffer);
+ return 0;
+}
diff --git a/trunk/src/emu/addrmap.c b/trunk/src/emu/addrmap.c
new file mode 100644
index 00000000000..78f6317ceba
--- /dev/null
+++ b/trunk/src/emu/addrmap.c
@@ -0,0 +1,975 @@
+/***************************************************************************
+
+ addrmap.c
+
+ Macros and helper functions for handling address map definitions.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+***************************************************************************/
+
+#include "emu.h"
+
+
+//**************************************************************************
+// ADDRESS MAP ENTRY
+//**************************************************************************
+
+//-------------------------------------------------
+// set_tag - set the appropriate tag for a device
+//-------------------------------------------------
+
+inline void map_handler_data::set_tag(const device_t &device, const char *tag)
+{
+ if (strcmp(tag, DEVICE_SELF) == 0)
+ m_tag = device.tag();
+ else if (strcmp(tag, DEVICE_SELF_OWNER) == 0)
+ {
+ assert(device.owner() != NULL);
+ m_tag = device.owner()->tag();
+ }
+ else
+ m_tag = device.subtag(m_derived_tag, tag);
+}
+
+
+
+//**************************************************************************
+// ADDRESS MAP ENTRY
+//**************************************************************************
+
+//-------------------------------------------------
+// address_map_entry - constructor
+//-------------------------------------------------
+
+address_map_entry::address_map_entry(address_map &map, offs_t start, offs_t end)
+ : m_next(NULL),
+ m_map(map),
+ m_addrstart((map.m_globalmask == 0) ? start : start & map.m_globalmask),
+ m_addrend((map.m_globalmask == 0) ? end : end & map.m_globalmask),
+ m_addrmirror(0),
+ m_addrmask(0),
+ m_share(NULL),
+ m_baseptr(NULL),
+ m_sizeptr(NULL),
+ m_baseptroffs_plus1(0),
+ m_sizeptroffs_plus1(0),
+ m_genbaseptroffs_plus1(0),
+ m_gensizeptroffs_plus1(0),
+ m_region(NULL),
+ m_rgnoffs(0),
+ m_rspace8(NULL),
+ m_rspace16(NULL),
+ m_rspace32(NULL),
+ m_rspace64(NULL),
+ m_rdevice8(NULL),
+ m_rdevice16(NULL),
+ m_rdevice32(NULL),
+ m_rdevice64(NULL),
+ m_wspace8(NULL),
+ m_wspace16(NULL),
+ m_wspace32(NULL),
+ m_wspace64(NULL),
+ m_wdevice8(NULL),
+ m_wdevice16(NULL),
+ m_wdevice32(NULL),
+ m_wdevice64(NULL),
+ m_memory(NULL),
+ m_bytestart(0),
+ m_byteend(0),
+ m_bytemirror(0),
+ m_bytemask(0)
+{
+}
+
+
+//-------------------------------------------------
+// set_mask - set the mask value
+//-------------------------------------------------
+
+void address_map_entry::set_mask(offs_t _mask)
+{
+ m_addrmask = _mask;
+ if (m_map.m_globalmask != 0)
+ m_addrmask &= m_map.m_globalmask;
+}
+
+
+//-------------------------------------------------
+// set_read_port - set up a handler for reading
+// an I/O port
+//-------------------------------------------------
+
+void address_map_entry::set_read_port(const device_t &device, const char *tag)
+{
+ m_read.m_type = AMH_PORT;
+ m_read.set_tag(device, tag);
+}
+
+
+//-------------------------------------------------
+// set_write_port - set up a handler for writing
+// an I/O port
+//-------------------------------------------------
+
+void address_map_entry::set_write_port(const device_t &device, const char *tag)
+{
+ m_write.m_type = AMH_PORT;
+ m_write.set_tag(device, tag);
+}
+
+
+//-------------------------------------------------
+// set_readwrite_port - set up a handler for
+// reading and writing an I/O port
+//-------------------------------------------------
+
+void address_map_entry::set_readwrite_port(const device_t &device, const char *tag)
+{
+ m_read.m_type = AMH_PORT;
+ m_read.set_tag(device, tag);
+ m_write.m_type = AMH_PORT;
+ m_write.set_tag(device, tag);
+}
+
+
+//-------------------------------------------------
+// set_read_bank - set up a handler for reading
+// from a memory bank
+//-------------------------------------------------
+
+void address_map_entry::set_read_bank(const device_t &device, const char *tag)
+{
+ m_read.m_type = AMH_BANK;
+ m_read.set_tag(device, tag);
+}
+
+
+//-------------------------------------------------
+// set_write_bank - set up a handler for writing
+// to a memory bank
+//-------------------------------------------------
+
+void address_map_entry::set_write_bank(const device_t &device, const char *tag)
+{
+ m_write.m_type = AMH_BANK;
+ m_write.set_tag(device, tag);
+}
+
+
+//-------------------------------------------------
+// set_readwrite_bank - set up a handler for
+// reading and writing to a memory bank
+//-------------------------------------------------
+
+void address_map_entry::set_readwrite_bank(const device_t &device, const char *tag)
+{
+ m_read.m_type = AMH_BANK;
+ m_read.set_tag(device, tag);
+ m_write.m_type = AMH_BANK;
+ m_write.set_tag(device, tag);
+}
+
+
+//-------------------------------------------------
+// set_submap - set up a handler for
+// retrieve a submap from a device
+//-------------------------------------------------
+
+void address_map_entry::set_submap(const device_t &device, const char *tag, address_map_delegate func, int bits, UINT64 mask)
+{
+ if(!bits)
+ bits = m_map.m_databits;
+
+ assert(unitmask_is_appropriate(bits, mask, func.name()));
+
+ m_read.m_type = AMH_DEVICE_SUBMAP;
+ m_read.set_tag(device, tag);
+ m_read.m_mask = mask;
+ m_write.m_type = AMH_DEVICE_SUBMAP;
+ m_write.set_tag(device, tag);
+ m_write.m_mask = mask;
+ m_submap_delegate = func;
+ m_submap_bits = bits;
+}
+
+
+//-------------------------------------------------
+// internal_set_handler - handler setters for
+// 8-bit read/write handlers
+//-------------------------------------------------
+
+void address_map_entry::internal_set_handler(read8_space_func func, const char *string, UINT64 unitmask)
+{
+ assert(func != NULL);
+ assert(unitmask_is_appropriate(8, unitmask, string));
+ m_read.m_type = AMH_LEGACY_SPACE_HANDLER;
+ m_read.m_bits = 8;
+ m_read.m_mask = unitmask;
+ m_read.m_name = string;
+ m_rspace8 = func;
+}
+
+
+void address_map_entry::internal_set_handler(write8_space_func func, const char *string, UINT64 unitmask)
+{
+ assert(func != NULL);
+ assert(unitmask_is_appropriate(8, unitmask, string));
+ m_write.m_type = AMH_LEGACY_SPACE_HANDLER;
+ m_write.m_bits = 8;
+ m_write.m_mask = unitmask;
+ m_write.m_name = string;
+ m_wspace8 = func;
+}
+
+
+void address_map_entry::internal_set_handler(read8_space_func rfunc, const char *rstring, write8_space_func wfunc, const char *wstring, UINT64 unitmask)
+{
+ internal_set_handler(rfunc, rstring, unitmask);
+ internal_set_handler(wfunc, wstring, unitmask);
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, read8_device_func func, const char *string, UINT64 unitmask)
+{
+ assert(func != NULL);
+ assert(unitmask_is_appropriate(8, unitmask, string));
+ m_read.m_type = AMH_LEGACY_DEVICE_HANDLER;
+ m_read.m_bits = 8;
+ m_read.m_mask = unitmask;
+ m_read.m_name = string;
+ m_read.set_tag(device, tag);
+ m_rdevice8 = func;
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, write8_device_func func, const char *string, UINT64 unitmask)
+{
+ assert(func != NULL);
+ assert(unitmask_is_appropriate(8, unitmask, string));
+ m_write.m_type = AMH_LEGACY_DEVICE_HANDLER;
+ m_write.m_bits = 8;
+ m_write.m_mask = unitmask;
+ m_write.m_name = string;
+ m_write.set_tag(device, tag);
+ m_wdevice8 = func;
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, read8_device_func rfunc, const char *rstring, write8_device_func wfunc, const char *wstring, UINT64 unitmask)
+{
+ internal_set_handler(device, tag, rfunc, rstring, unitmask);
+ internal_set_handler(device, tag, wfunc, wstring, unitmask);
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, read8_delegate func, UINT64 unitmask)
+{
+ assert(!func.isnull());
+ assert(unitmask_is_appropriate(8, unitmask, func.name()));
+ m_read.m_type = AMH_DEVICE_DELEGATE;
+ m_read.m_bits = 8;
+ m_read.m_mask = unitmask;
+ m_read.m_name = func.name();
+ m_read.set_tag(device, tag);
+ m_rproto8 = func;
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, write8_delegate func, UINT64 unitmask)
+{
+ assert(!func.isnull());
+ assert(unitmask_is_appropriate(8, unitmask, func.name()));
+ m_write.m_type = AMH_DEVICE_DELEGATE;
+ m_write.m_bits = 8;
+ m_write.m_mask = unitmask;
+ m_write.m_name = func.name();
+ m_write.set_tag(device, tag);
+ m_wproto8 = func;
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, read8_delegate rfunc, write8_delegate wfunc, UINT64 unitmask)
+{
+ internal_set_handler(device, tag, rfunc, unitmask);
+ internal_set_handler(device, tag, wfunc, unitmask);
+}
+
+
+//-------------------------------------------------
+// internal_set_handler - handler setters for
+// 16-bit read/write handlers
+//-------------------------------------------------
+
+void address_map_entry::internal_set_handler(read16_space_func func, const char *string, UINT64 unitmask)
+{
+ assert(func != NULL);
+ assert(unitmask_is_appropriate(16, unitmask, string));
+ m_read.m_type = AMH_LEGACY_SPACE_HANDLER;
+ m_read.m_bits = 16;
+ m_read.m_mask = unitmask;
+ m_read.m_name = string;
+ m_rspace16 = func;
+}
+
+
+void address_map_entry::internal_set_handler(write16_space_func func, const char *string, UINT64 unitmask)
+{
+ assert(func != NULL);
+ assert(unitmask_is_appropriate(16, unitmask, string));
+ m_write.m_type = AMH_LEGACY_SPACE_HANDLER;
+ m_write.m_bits = 16;
+ m_write.m_mask = unitmask;
+ m_write.m_name = string;
+ m_wspace16 = func;
+}
+
+
+void address_map_entry::internal_set_handler(read16_space_func rfunc, const char *rstring, write16_space_func wfunc, const char *wstring, UINT64 unitmask)
+{
+ internal_set_handler(rfunc, rstring, unitmask);
+ internal_set_handler(wfunc, wstring, unitmask);
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, read16_device_func func, const char *string, UINT64 unitmask)
+{
+ assert(func != NULL);
+ assert(unitmask_is_appropriate(16, unitmask, string));
+ m_read.m_type = AMH_LEGACY_DEVICE_HANDLER;
+ m_read.m_bits = 16;
+ m_read.m_mask = unitmask;
+ m_read.m_name = string;
+ m_read.set_tag(device, tag);
+ m_rdevice16 = func;
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, write16_device_func func, const char *string, UINT64 unitmask)
+{
+ assert(func != NULL);
+ assert(unitmask_is_appropriate(16, unitmask, string));
+ m_write.m_type = AMH_LEGACY_DEVICE_HANDLER;
+ m_write.m_bits = 16;
+ m_write.m_mask = unitmask;
+ m_write.m_name = string;
+ m_write.set_tag(device, tag);
+ m_wdevice16 = func;
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, read16_device_func rfunc, const char *rstring, write16_device_func wfunc, const char *wstring, UINT64 unitmask)
+{
+ internal_set_handler(device, tag, rfunc, rstring, unitmask);
+ internal_set_handler(device, tag, wfunc, wstring, unitmask);
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, read16_delegate func, UINT64 unitmask)
+{
+ assert(!func.isnull());
+ assert(unitmask_is_appropriate(16, unitmask, func.name()));
+ m_read.m_type = AMH_DEVICE_DELEGATE;
+ m_read.m_bits = 16;
+ m_read.m_mask = unitmask;
+ m_read.m_name = func.name();
+ m_read.set_tag(device, tag);
+ m_rproto16 = func;
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, write16_delegate func, UINT64 unitmask)
+{
+ assert(!func.isnull());
+ assert(unitmask_is_appropriate(16, unitmask, func.name()));
+ m_write.m_type = AMH_DEVICE_DELEGATE;
+ m_write.m_bits = 16;
+ m_write.m_mask = unitmask;
+ m_write.m_name = func.name();
+ m_write.set_tag(device, tag);
+ m_wproto16 = func;
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, read16_delegate rfunc, write16_delegate wfunc, UINT64 unitmask)
+{
+ internal_set_handler(device, tag, rfunc, unitmask);
+ internal_set_handler(device, tag, wfunc, unitmask);
+}
+
+
+//-------------------------------------------------
+// internal_set_handler - handler setters for
+// 32-bit read/write handlers
+//-------------------------------------------------
+
+void address_map_entry::internal_set_handler(read32_space_func func, const char *string, UINT64 unitmask)
+{
+ assert(func != NULL);
+ assert(unitmask_is_appropriate(32, unitmask, string));
+ m_read.m_type = AMH_LEGACY_SPACE_HANDLER;
+ m_read.m_bits = 32;
+ m_read.m_mask = unitmask;
+ m_read.m_name = string;
+ m_rspace32 = func;
+}
+
+
+void address_map_entry::internal_set_handler(write32_space_func func, const char *string, UINT64 unitmask)
+{
+ assert(func != NULL);
+ assert(unitmask_is_appropriate(32, unitmask, string));
+ m_write.m_type = AMH_LEGACY_SPACE_HANDLER;
+ m_write.m_bits = 32;
+ m_write.m_mask = unitmask;
+ m_write.m_name = string;
+ m_wspace32 = func;
+}
+
+
+void address_map_entry::internal_set_handler(read32_space_func rfunc, const char *rstring, write32_space_func wfunc, const char *wstring, UINT64 unitmask)
+{
+ internal_set_handler(rfunc, rstring, unitmask);
+ internal_set_handler(wfunc, wstring, unitmask);
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, read32_device_func func, const char *string, UINT64 unitmask)
+{
+ assert(func != NULL);
+ assert(unitmask_is_appropriate(32, unitmask, string));
+ m_read.m_type = AMH_LEGACY_DEVICE_HANDLER;
+ m_read.m_bits = 32;
+ m_read.m_mask = unitmask;
+ m_read.m_name = string;
+ m_read.set_tag(device, tag);
+ m_rdevice32 = func;
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, write32_device_func func, const char *string, UINT64 unitmask)
+{
+ assert(func != NULL);
+ assert(unitmask_is_appropriate(32, unitmask, string));
+ m_write.m_type = AMH_LEGACY_DEVICE_HANDLER;
+ m_write.m_bits = 32;
+ m_write.m_mask = unitmask;
+ m_write.m_name = string;
+ m_write.set_tag(device, tag);
+ m_wdevice32 = func;
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, read32_device_func rfunc, const char *rstring, write32_device_func wfunc, const char *wstring, UINT64 unitmask)
+{
+ internal_set_handler(device, tag, rfunc, rstring, unitmask);
+ internal_set_handler(device, tag, wfunc, wstring, unitmask);
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, read32_delegate func, UINT64 unitmask)
+{
+ assert(!func.isnull());
+ assert(unitmask_is_appropriate(32, unitmask, func.name()));
+ m_read.m_type = AMH_DEVICE_DELEGATE;
+ m_read.m_bits = 32;
+ m_read.m_mask = unitmask;
+ m_read.m_name = func.name();
+ m_read.set_tag(device, tag);
+ m_rproto32 = func;
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, write32_delegate func, UINT64 unitmask)
+{
+ assert(!func.isnull());
+ assert(unitmask_is_appropriate(32, unitmask, func.name()));
+ m_write.m_type = AMH_DEVICE_DELEGATE;
+ m_write.m_bits = 32;
+ m_write.m_mask = unitmask;
+ m_write.m_name = func.name();
+ m_write.set_tag(device, tag);
+ m_wproto32 = func;
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, read32_delegate rfunc, write32_delegate wfunc, UINT64 unitmask)
+{
+ internal_set_handler(device, tag, rfunc, unitmask);
+ internal_set_handler(device, tag, wfunc, unitmask);
+}
+
+
+//-------------------------------------------------
+// internal_set_handler - handler setters for
+// 64-bit read/write handlers
+//-------------------------------------------------
+
+void address_map_entry::internal_set_handler(read64_space_func func, const char *string, UINT64 unitmask)
+{
+ assert(func != NULL);
+ assert(unitmask_is_appropriate(64, unitmask, string));
+ m_read.m_type = AMH_LEGACY_SPACE_HANDLER;
+ m_read.m_bits = 64;
+ m_read.m_mask = 0;
+ m_read.m_name = string;
+ m_rspace64 = func;
+}
+
+
+void address_map_entry::internal_set_handler(write64_space_func func, const char *string, UINT64 unitmask)
+{
+ assert(func != NULL);
+ assert(unitmask_is_appropriate(64, unitmask, string));
+ m_write.m_type = AMH_LEGACY_SPACE_HANDLER;
+ m_write.m_bits = 64;
+ m_write.m_mask = 0;
+ m_write.m_name = string;
+ m_wspace64 = func;
+}
+
+
+void address_map_entry::internal_set_handler(read64_space_func rfunc, const char *rstring, write64_space_func wfunc, const char *wstring, UINT64 unitmask)
+{
+ internal_set_handler(rfunc, rstring, unitmask);
+ internal_set_handler(wfunc, wstring, unitmask);
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, read64_device_func func, const char *string, UINT64 unitmask)
+{
+ assert(func != NULL);
+ assert(unitmask_is_appropriate(64, unitmask, string));
+ m_read.m_type = AMH_LEGACY_DEVICE_HANDLER;
+ m_read.m_bits = 64;
+ m_read.m_mask = 0;
+ m_read.m_name = string;
+ m_read.set_tag(device, tag);
+ m_rdevice64 = func;
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, write64_device_func func, const char *string, UINT64 unitmask)
+{
+ assert(func != NULL);
+ assert(unitmask_is_appropriate(64, unitmask, string));
+ m_write.m_type = AMH_LEGACY_DEVICE_HANDLER;
+ m_write.m_bits = 64;
+ m_write.m_mask = 0;
+ m_write.m_name = string;
+ m_write.set_tag(device, tag);
+ m_wdevice64 = func;
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, read64_device_func rfunc, const char *rstring, write64_device_func wfunc, const char *wstring, UINT64 unitmask)
+{
+ internal_set_handler(device, tag, rfunc, rstring, unitmask);
+ internal_set_handler(device, tag, wfunc, wstring, unitmask);
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, read64_delegate func, UINT64 unitmask)
+{
+ assert(!func.isnull());
+ assert(unitmask_is_appropriate(64, unitmask, func.name()));
+ m_read.m_type = AMH_DEVICE_DELEGATE;
+ m_read.m_bits = 64;
+ m_read.m_mask = 0;
+ m_read.m_name = func.name();
+ m_read.set_tag(device, tag);
+ m_rproto64 = func;
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, write64_delegate func, UINT64 unitmask)
+{
+ assert(!func.isnull());
+ assert(unitmask_is_appropriate(64, unitmask, func.name()));
+ m_write.m_type = AMH_DEVICE_DELEGATE;
+ m_write.m_bits = 64;
+ m_write.m_mask = 0;
+ m_write.m_name = func.name();
+ m_write.set_tag(device, tag);
+ m_wproto64 = func;
+}
+
+
+void address_map_entry::internal_set_handler(const device_t &device, const char *tag, read64_delegate rfunc, write64_delegate wfunc, UINT64 unitmask)
+{
+ internal_set_handler(device, tag, rfunc, unitmask);
+ internal_set_handler(device, tag, wfunc, unitmask);
+}
+
+
+//-------------------------------------------------
+// unitmask_is_appropriate - verify that the
+// provided unitmask is valid and expected
+//-------------------------------------------------
+
+bool address_map_entry::unitmask_is_appropriate(UINT8 width, UINT64 unitmask, const char *string)
+{
+ // if no mask, this must match the default width of the map
+ if (unitmask == 0)
+ {
+ if (m_map.m_databits != width)
+ throw emu_fatalerror("Handler %s is a %d-bit handler but was specified in a %d-bit address map", string, width, m_map.m_databits);
+ return true;
+ }
+
+ // if we have a mask, we must be smaller than the default width of the map
+ if (m_map.m_databits <= width)
+ throw emu_fatalerror("Handler %s is a %d-bit handler and is too wide to be used in a %d-bit address map", string, width, m_map.m_databits);
+
+ // the mask must represent whole units of width
+ UINT32 basemask = (width == 8) ? 0xff : (width == 16) ? 0xffff : 0xffffffff;
+ UINT64 singlemask = basemask;
+ while (singlemask != 0)
+ {
+ if ((unitmask & singlemask) != 0 && (unitmask & singlemask) != singlemask)
+ throw emu_fatalerror("Handler %s specified a mask of %08X%08X; needs to be in even chunks of %X", string, (UINT32)(unitmask >> 32), (UINT32)unitmask, basemask);
+ singlemask <<= width;
+ }
+ return true;
+}
+
+
+
+//**************************************************************************
+// WIDTH-SPECIFIC ADDRESS MAP ENTRY CONSTRUCTORS
+//**************************************************************************
+
+//-------------------------------------------------
+// address_map_entry8 - constructor
+//-------------------------------------------------
+
+address_map_entry8::address_map_entry8(address_map &map, offs_t start, offs_t end)
+ : address_map_entry(map, start, end)
+{
+}
+
+
+//-------------------------------------------------
+// address_map_entry16 - constructor
+//-------------------------------------------------
+
+address_map_entry16::address_map_entry16(address_map &map, offs_t start, offs_t end)
+ : address_map_entry(map, start, end)
+{
+}
+
+
+//-------------------------------------------------
+// address_map_entry32 - constructor
+//-------------------------------------------------
+
+address_map_entry32::address_map_entry32(address_map &map, offs_t start, offs_t end)
+ : address_map_entry(map, start, end)
+{
+}
+
+
+//-------------------------------------------------
+// address_map_entry64 - constructor
+//-------------------------------------------------
+
+address_map_entry64::address_map_entry64(address_map &map, offs_t start, offs_t end)
+ : address_map_entry(map, start, end)
+{
+}
+
+
+
+//**************************************************************************
+// ADDRESS MAP
+//**************************************************************************
+
+//-------------------------------------------------
+// address_map - constructor
+//-------------------------------------------------
+
+address_map::address_map(const device_t &device, address_spacenum spacenum)
+ : m_spacenum(spacenum),
+ m_databits(0xff),
+ m_unmapval(0),
+ m_globalmask(0)
+{
+ // get our memory interface
+ const device_memory_interface *memintf;
+ if (!device.interface(memintf))
+ throw emu_fatalerror("No memory interface defined for device '%s'\n", device.tag());
+
+ // and then the configuration for the current address space
+ const address_space_config *spaceconfig = memintf->space_config(spacenum);
+ if (!device.interface(memintf))
+ throw emu_fatalerror("No memory address space configuration found for device '%s', space %d\n", device.tag(), spacenum);
+
+ // append the internal device map (first so it takes priority) */
+ if (spaceconfig->m_internal_map != NULL)
+ (*spaceconfig->m_internal_map)(*this, device);
+
+ // construct the standard map */
+ if (memintf->address_map(spacenum) != NULL)
+ (*memintf->address_map(spacenum))(*this, *device.owner());
+
+ // append the default device map (last so it can be overridden) */
+ if (spaceconfig->m_default_map != NULL)
+ (*spaceconfig->m_default_map)(*this, device);
+}
+
+
+
+//-------------------------------------------------
+// address_map - constructor in the submap case
+//-------------------------------------------------
+
+address_map::address_map(const device_t &device, address_map_entry *entry)
+ : m_spacenum(AS_PROGRAM),
+ m_databits(0xff),
+ m_unmapval(0),
+ m_globalmask(0)
+{
+ // Retrieve the submap
+ entry->m_submap_delegate.late_bind(const_cast<device_t &>(device));
+ entry->m_submap_delegate(*this, device);
+}
+
+
+//-------------------------------------------------
+// ~address_map - destructor
+//-------------------------------------------------
+
+address_map::~address_map()
+{
+}
+
+
+//-------------------------------------------------
+// configure - either configure the space and
+// databits, or verify they match previously-set
+// values
+//-------------------------------------------------
+
+void address_map::configure(address_spacenum spacenum, UINT8 databits)
+{
+ assert(m_spacenum == spacenum);
+ if (m_databits == 0xff)
+ m_databits = databits;
+ else
+ assert(m_databits == databits);
+}
+
+
+//-------------------------------------------------
+// append - append an entry to the end of the
+// list
+//-------------------------------------------------
+
+void address_map::set_global_mask(offs_t mask)
+{
+// if (m_entrylist != NULL)
+// throw emu_fatalerror("AM_GLOBALMASK must be specified before any entries");
+ m_globalmask = mask;
+}
+
+
+
+//-------------------------------------------------
+// add - add a new entry of the appropriate type
+//-------------------------------------------------
+
+address_map_entry8 *address_map::add(offs_t start, offs_t end, address_map_entry8 *ptr)
+{
+ ptr = global_alloc(address_map_entry8(*this, start, end));
+ m_entrylist.append(*ptr);
+ return ptr;
+}
+
+
+address_map_entry16 *address_map::add(offs_t start, offs_t end, address_map_entry16 *ptr)
+{
+ ptr = global_alloc(address_map_entry16(*this, start, end));
+ m_entrylist.append(*ptr);
+ return ptr;
+}
+
+
+address_map_entry32 *address_map::add(offs_t start, offs_t end, address_map_entry32 *ptr)
+{
+ ptr = global_alloc(address_map_entry32(*this, start, end));
+ m_entrylist.append(*ptr);
+ return ptr;
+}
+
+
+address_map_entry64 *address_map::add(offs_t start, offs_t end, address_map_entry64 *ptr)
+{
+ ptr = global_alloc(address_map_entry64(*this, start, end));
+ m_entrylist.append(*ptr);
+ return ptr;
+}
+
+
+//-------------------------------------------------
+// uplift_submaps - propagate in the device submaps
+//-------------------------------------------------
+
+void address_map::uplift_submaps(running_machine &machine, device_t &device, endianness_t endian)
+{
+ address_map_entry *prev = 0;
+ address_map_entry *entry = m_entrylist.first();
+ while (entry)
+ {
+ if (entry->m_read.m_type == AMH_DEVICE_SUBMAP)
+ {
+ const char *tag = entry->m_read.m_tag;
+ device_t *mapdevice = machine.device(tag);
+ if (mapdevice == NULL)
+ throw emu_fatalerror("Attempted to submap a non-existent device '%s' in space %d of device '%s'\n", tag, m_spacenum, device.tag());
+ // Grab the submap
+ address_map submap(*mapdevice, entry);
+
+ // Recursively uplift it if needed
+ submap.uplift_submaps(machine, *mapdevice, endian);
+
+ // Compute the unit repartition characteristics
+ int entry_bits = entry->m_submap_bits;
+ if (!entry_bits)
+ entry_bits = m_databits;
+
+ if (submap.m_databits != entry_bits)
+ throw emu_fatalerror("AM_DEVICE wants a %d bits large address map and got a %d bits large one instead.\n", entry_bits, submap.m_databits);
+
+ int entry_bytes = entry_bits / 8;
+ int databytes = m_databits / 8;
+
+ offs_t mirror_address_mask = (databytes - 1) & ~(entry_bytes - 1);
+
+ UINT64 entry_mask = (2ULL << (entry_bits-1)) - 1;
+
+ int slot_offset[8];
+ int slot_count = 0;
+ int max_slot_count = m_databits / entry_bits;
+ int slot_xor_mask = endian == ENDIANNESS_LITTLE ? 0 : max_slot_count - 1;
+
+ UINT64 global_mask = entry->m_read.m_mask;
+ // zero means all
+ if (!global_mask)
+ global_mask = ~global_mask;
+
+ // mask consistency has already been checked in
+ // unitmask_is_appropriate, so one bit is enough
+ for (int slot=0; slot < max_slot_count; slot++)
+ if (global_mask & (1ULL << (slot * entry_bits)))
+ slot_offset[slot_count++] = (slot ^ slot_xor_mask) * entry_bits;
+
+ // Merge in all the map contents in order
+ while (submap.m_entrylist.count())
+ {
+ address_map_entry *subentry = submap.m_entrylist.detach_head();
+
+ // Remap start and end
+
+ int start_offset = subentry->m_addrstart / entry_bytes;
+ int start_slot = start_offset % slot_count;
+ subentry->m_addrstart = entry->m_addrstart + (start_offset / slot_count) * databytes;
+
+ // Drop the entry if it ends up outside the range
+ if (subentry->m_addrstart > entry->m_addrend)
+ {
+ global_free(subentry);
+ continue;
+ }
+
+ int end_offset = subentry->m_addrend / entry_bytes;
+ int end_slot = end_offset % slot_count;
+ subentry->m_addrend = entry->m_addrstart + (end_offset / slot_count) * databytes + databytes - 1;
+
+ // Clip the entry to the end of the range
+ if (subentry->m_addrend > entry->m_addrend)
+ subentry->m_addrend = entry->m_addrend;
+
+ // Detect special unhandled case (range straddling
+ // slots, requiring splitting in multiple entries and
+ // unimplemented offset-add subunit handler)
+ if (subentry->m_addrstart + databytes - 1 != subentry->m_addrend &&
+ (start_slot != 0 || end_slot != slot_count - 1))
+ throw emu_fatalerror("uplift_submaps unhandled case: range straddling slots.\n");
+
+ if (entry->m_addrmask || subentry->m_addrmask)
+ throw emu_fatalerror("uplift_submaps unhandled case: address masks.\n");
+
+ if (subentry->m_addrmirror & mirror_address_mask)
+ throw emu_fatalerror("uplift_submaps unhandled case: address mirror bit within subentry.\n");
+
+ subentry->m_addrmirror |= entry->m_addrmirror;
+
+ // Twiddle the unitmask on the data accessors that need it
+ for (int data_entry = 0; data_entry < 2; data_entry++)
+ {
+ map_handler_data &mdata = data_entry ? subentry->m_write : subentry->m_read;
+
+ if (mdata.m_type == AMH_NONE)
+ continue;
+
+ if (mdata.m_type != AMH_DEVICE_DELEGATE)
+ throw emu_fatalerror("Only normal read/write methods are accepted in device submaps.\n");
+
+ if (mdata.m_bits == 0 && entry_bits != m_databits)
+ mdata.m_bits = entry_bits;
+
+ UINT64 mask = 0;
+ if (entry_bits != m_databits)
+ {
+ UINT64 unitmask = mdata.m_mask ? mdata.m_mask : entry_mask;
+ for (int slot = start_slot; slot <= end_slot; slot++)
+ mask |= unitmask << slot_offset[slot];
+ }
+ mdata.m_mask = mask;
+ }
+
+ // Insert the entry in the map
+ m_entrylist.insert_after(*subentry, prev);
+ prev = subentry;
+ }
+
+ address_map_entry *to_delete = entry;
+ entry = entry->next();
+ m_entrylist.remove(*to_delete);
+ }
+ else
+ {
+ prev = entry;
+ entry = entry->next();
+ }
+ }
+}
diff --git a/trunk/src/emu/addrmap.h b/trunk/src/emu/addrmap.h
new file mode 100644
index 00000000000..846bbba0066
--- /dev/null
+++ b/trunk/src/emu/addrmap.h
@@ -0,0 +1,1151 @@
+/***************************************************************************
+
+ addrmap.h
+
+ Macros and helper functions for handling address map definitions.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __EMU_H__
+#error Dont include this file directly; include emu.h instead.
+#endif
+
+#ifndef __ADDRMAP_H__
+#define __ADDRMAP_H__
+
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// address map handler types
+enum map_handler_type
+{
+ AMH_NONE = 0,
+ AMH_RAM,
+ AMH_ROM,
+ AMH_NOP,
+ AMH_UNMAP,
+ AMH_DEVICE_DELEGATE,
+ AMH_LEGACY_SPACE_HANDLER,
+ AMH_LEGACY_DEVICE_HANDLER,
+ AMH_PORT,
+ AMH_BANK,
+ AMH_DEVICE_SUBMAP
+};
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// submap retriever delegate
+typedef delegate<void (address_map &, const device_t &)> address_map_delegate;
+
+// address map handler data
+class map_handler_data
+{
+public:
+ map_handler_data()
+ : m_type(AMH_NONE),
+ m_bits(0),
+ m_mask(0),
+ m_name(NULL),
+ m_tag(NULL) { }
+
+ map_handler_type m_type; // type of the handler
+ UINT8 m_bits; // width of the handler in bits, or 0 for default
+ UINT64 m_mask; // mask for which lanes apply
+ const char * m_name; // name of the handler
+ const char * m_tag; // tag pointing to a reference
+ astring m_derived_tag; // string used to hold derived names
+
+ void set_tag(const device_t &device, const char *tag);
+};
+
+
+
+// ======================> address_map_entry
+
+// address_map_entry is a linked list element describing one address range in a map
+class address_map_entry
+{
+public:
+ // construction/destruction
+ address_map_entry(address_map &map, offs_t start, offs_t end);
+
+ // getters
+ address_map_entry *next() const { return m_next; }
+
+ // simple inline setters
+ void set_mirror(offs_t _mirror) { m_addrmirror = _mirror; }
+ void set_read_type(map_handler_type _type) { m_read.m_type = _type; }
+ void set_write_type(map_handler_type _type) { m_write.m_type = _type; }
+ void set_region(const char *tag, offs_t offset) { m_region = tag; m_rgnoffs = offset; }
+ void set_share(const char *tag) { m_share = tag; }
+ void set_sizeptr(size_t *_sizeptr) { m_sizeptr = _sizeptr; }
+ void set_member_baseptr(FPTR offs) { m_baseptroffs_plus1 = offs + 1; }
+ void set_member_sizeptr(FPTR offs) { m_sizeptroffs_plus1 = offs + 1; }
+ void set_generic_baseptr(FPTR offs) { m_genbaseptroffs_plus1 = offs + 1; }
+ void set_generic_sizeptr(FPTR offs) { m_gensizeptroffs_plus1 = offs + 1; }
+
+ // mask setting
+ void set_mask(offs_t _mask);
+
+ // I/O port configuration
+ void set_read_port(const device_t &device, const char *tag);
+ void set_write_port(const device_t &device, const char *tag);
+ void set_readwrite_port(const device_t &device, const char *tag);
+
+ // memory bank configuration
+ void set_read_bank(const device_t &device, const char *tag);
+ void set_write_bank(const device_t &device, const char *tag);
+ void set_readwrite_bank(const device_t &device, const char *tag);
+
+ // submap referencing
+ void set_submap(const device_t &device, const char *tag, address_map_delegate func, int bits, UINT64 mask);
+
+ // public state
+ address_map_entry * m_next; // pointer to the next entry
+ address_map & m_map; // reference to our owning map
+ astring m_region_string; // string used to hold derived names
+
+ // basic information
+ offs_t m_addrstart; // start address
+ offs_t m_addrend; // end address
+ offs_t m_addrmirror; // mirror bits
+ offs_t m_addrmask; // mask bits
+ map_handler_data m_read; // data for read handler
+ map_handler_data m_write; // data for write handler
+ const char * m_share; // tag of a shared memory block
+ void ** m_baseptr; // receives pointer to memory (optional)
+ size_t * m_sizeptr; // receives size of area in bytes (optional)
+ UINT32 m_baseptroffs_plus1; // offset of base pointer within driver_data, plus 1
+ UINT32 m_sizeptroffs_plus1; // offset of size pointer within driver_data, plus 1
+ UINT32 m_genbaseptroffs_plus1; // offset of base pointer within generic_pointers, plus 1
+ UINT32 m_gensizeptroffs_plus1; // offset of size pointer within generic_pointers, plus 1
+ const char * m_region; // tag of region containing the memory backing this entry
+ offs_t m_rgnoffs; // offset within the region
+
+ // handlers
+ read8_delegate m_rproto8; // 8-bit read proto-delegate
+ read16_delegate m_rproto16; // 16-bit read proto-delegate
+ read32_delegate m_rproto32; // 32-bit read proto-delegate
+ read64_delegate m_rproto64; // 64-bit read proto-delegate
+ read8_space_func m_rspace8; // 8-bit legacy address space handler
+ read16_space_func m_rspace16; // 16-bit legacy address space handler
+ read32_space_func m_rspace32; // 32-bit legacy address space handler
+ read64_space_func m_rspace64; // 64-bit legacy address space handler
+ read8_device_func m_rdevice8; // 8-bit legacy device handler
+ read16_device_func m_rdevice16; // 16-bit legacy device handler
+ read32_device_func m_rdevice32; // 32-bit legacy device handler
+ read64_device_func m_rdevice64; // 64-bit legacy device handler
+ write8_delegate m_wproto8; // 8-bit write proto-delegate
+ write16_delegate m_wproto16; // 16-bit write proto-delegate
+ write32_delegate m_wproto32; // 32-bit write proto-delegate
+ write64_delegate m_wproto64; // 64-bit write proto-delegate
+ write8_space_func m_wspace8; // 8-bit legacy address space handler
+ write16_space_func m_wspace16; // 16-bit legacy address space handler
+ write32_space_func m_wspace32; // 32-bit legacy address space handler
+ write64_space_func m_wspace64; // 64-bit legacy address space handler
+ write8_device_func m_wdevice8; // 8-bit legacy device handler
+ write16_device_func m_wdevice16; // 16-bit legacy device handler
+ write32_device_func m_wdevice32; // 32-bit legacy device handler
+ write64_device_func m_wdevice64; // 64-bit legacy device handler
+
+ address_map_delegate m_submap_delegate;
+ int m_submap_bits;
+
+ // information used during processing
+ void * m_memory; // pointer to memory backing this entry
+ offs_t m_bytestart; // byte-adjusted start address
+ offs_t m_byteend; // byte-adjusted end address
+ offs_t m_bytemirror; // byte-adjusted mirror bits
+ offs_t m_bytemask; // byte-adjusted mask bits
+
+protected:
+ // internal base pointer setting (derived classes provide typed versions)
+ void internal_set_baseptr(void **_baseptr) { m_baseptr = _baseptr; }
+
+ // internal handler setters for 8-bit functions
+ void internal_set_handler(read8_space_func func, const char *string, UINT64 mask);
+ void internal_set_handler(write8_space_func func, const char *string, UINT64 mask);
+ void internal_set_handler(read8_space_func rfunc, const char *rstring, write8_space_func wfunc, const char *wstring, UINT64 mask);
+ void internal_set_handler(const device_t &device, const char *tag, read8_device_func func, const char *string, UINT64 mask);
+ void internal_set_handler(const device_t &device, const char *tag, write8_device_func func, const char *string, UINT64 mask);
+ void internal_set_handler(const device_t &device, const char *tag, read8_device_func rfunc, const char *rstring, write8_device_func wfunc, const char *wstring, UINT64 mask);
+ void internal_set_handler(const device_t &device, const char *tag, read8_delegate func, UINT64 mask);
+ void internal_set_handler(const device_t &device, const char *tag, write8_delegate func, UINT64 mask);
+ void internal_set_handler(const device_t &device, const char *tag, read8_delegate rfunc, write8_delegate wfunc, UINT64 mask);
+
+ // internal handler setters for 16-bit functions
+ void internal_set_handler(read16_space_func func, const char *string, UINT64 mask);
+ void internal_set_handler(write16_space_func func, const char *string, UINT64 mask);
+ void internal_set_handler(read16_space_func rfunc, const char *rstring, write16_space_func wfunc, const char *wstring, UINT64 mask);
+ void internal_set_handler(const device_t &device, const char *tag, read16_device_func func, const char *string, UINT64 mask);
+ void internal_set_handler(const device_t &device, const char *tag, write16_device_func func, const char *string, UINT64 mask);
+ void internal_set_handler(const device_t &device, const char *tag, read16_device_func rfunc, const char *rstring, write16_device_func wfunc, const char *wstring, UINT64 mask);
+ void internal_set_handler(const device_t &device, const char *tag, read16_delegate func, UINT64 mask);
+ void internal_set_handler(const device_t &device, const char *tag, write16_delegate func, UINT64 mask);
+ void internal_set_handler(const device_t &device, const char *tag, read16_delegate rfunc, write16_delegate wfunc, UINT64 mask);
+
+ // internal handler setters for 32-bit functions
+ void internal_set_handler(read32_space_func func, const char *string, UINT64 mask);
+ void internal_set_handler(write32_space_func func, const char *string, UINT64 mask);
+ void internal_set_handler(read32_space_func rfunc, const char *rstring, write32_space_func wfunc, const char *wstring, UINT64 mask);
+ void internal_set_handler(const device_t &device, const char *tag, read32_device_func func, const char *string, UINT64 mask);
+ void internal_set_handler(const device_t &device, const char *tag, write32_device_func func, const char *string, UINT64 mask);
+ void internal_set_handler(const device_t &device, const char *tag, read32_device_func rfunc, const char *rstring, write32_device_func wfunc, const char *wstring, UINT64 mask);
+ void internal_set_handler(const device_t &device, const char *tag, read32_delegate func, UINT64 mask);
+ void internal_set_handler(const device_t &device, const char *tag, write32_delegate func, UINT64 mask);
+ void internal_set_handler(const device_t &device, const char *tag, read32_delegate rfunc, write32_delegate wfunc, UINT64 mask);
+
+ // internal handler setters for 64-bit functions
+ void internal_set_handler(read64_space_func func, const char *string, UINT64 mask);
+ void internal_set_handler(write64_space_func func, const char *string, UINT64 mask);
+ void internal_set_handler(read64_space_func rfunc, const char *rstring, write64_space_func wfunc, const char *wstring, UINT64 mask);
+ void internal_set_handler(const device_t &device, const char *tag, read64_device_func func, const char *string, UINT64 mask);
+ void internal_set_handler(const device_t &device, const char *tag, write64_device_func func, const char *string, UINT64 mask);
+ void internal_set_handler(const device_t &device, const char *tag, read64_device_func rfunc, const char *rstring, write64_device_func wfunc, const char *wstring, UINT64 mask);
+ void internal_set_handler(const device_t &device, const char *tag, read64_delegate func, UINT64 mask);
+ void internal_set_handler(const device_t &device, const char *tag, write64_delegate func, UINT64 mask);
+ void internal_set_handler(const device_t &device, const char *tag, read64_delegate rfunc, write64_delegate wfunc, UINT64 mask);
+
+private:
+ // helper functions
+ bool unitmask_is_appropriate(UINT8 width, UINT64 unitmask, const char *string);
+};
+
+
+// ======================> address_map_entry8
+
+// 8-bit address map version of address_map_entry which only permits valid 8-bit handlers
+class address_map_entry8 : public address_map_entry
+{
+public:
+ address_map_entry8(address_map &map, offs_t start, offs_t end);
+
+ void set_baseptr(UINT8 **baseptr) { internal_set_baseptr(reinterpret_cast<void **>(baseptr)); }
+
+ // native-size handlers
+ void set_handler(read8_space_func func, const char *string) { internal_set_handler(func, string, 0); }
+ void set_handler(write8_space_func func, const char *string) { internal_set_handler(func, string, 0); }
+ void set_handler(read8_space_func rfunc, const char *rstring, write8_space_func wfunc, const char *wstring) { internal_set_handler(rfunc, rstring, wfunc, wstring, 0); }
+ void set_handler(const device_t &device, const char *tag, read8_device_func func, const char *string) { internal_set_handler(device, tag, func, string, 0); }
+ void set_handler(const device_t &device, const char *tag, write8_device_func func, const char *string) { internal_set_handler(device, tag, func, string, 0); }
+ void set_handler(const device_t &device, const char *tag, read8_device_func rfunc, const char *rstring, write8_device_func wfunc, const char *wstring) { internal_set_handler(device, tag, rfunc, rstring, wfunc, wstring, 0); }
+ void set_handler(const device_t &device, const char *tag, read8_delegate func) { internal_set_handler(device, tag, func, 0); }
+ void set_handler(const device_t &device, const char *tag, write8_delegate func) { internal_set_handler(device, tag, func, 0); }
+ void set_handler(const device_t &device, const char *tag, read8_delegate rfunc, write8_delegate wfunc) { internal_set_handler(device, tag, rfunc, wfunc, 0); }
+};
+
+
+// ======================> address_map_entry16
+
+// 16-bit address map version of address_map_entry which only permits valid 16-bit handlers
+class address_map_entry16 : public address_map_entry
+{
+public:
+ address_map_entry16(address_map &map, offs_t start, offs_t end);
+
+ void set_baseptr(UINT16 **baseptr) { internal_set_baseptr(reinterpret_cast<void **>(baseptr)); }
+
+ // native-size handlers
+ void set_handler(read16_space_func func, const char *string) { internal_set_handler(func, string, 0); }
+ void set_handler(write16_space_func func, const char *string) { internal_set_handler(func, string, 0); }
+ void set_handler(read16_space_func rfunc, const char *rstring, write16_space_func wfunc, const char *wstring) { internal_set_handler(rfunc, rstring, wfunc, wstring, 0); }
+ void set_handler(const device_t &device, const char *tag, read16_device_func func, const char *string) { internal_set_handler(device, tag, func, string, 0); }
+ void set_handler(const device_t &device, const char *tag, write16_device_func func, const char *string) { internal_set_handler(device, tag, func, string, 0); }
+ void set_handler(const device_t &device, const char *tag, read16_device_func rfunc, const char *rstring, write16_device_func wfunc, const char *wstring) { internal_set_handler(device, tag, rfunc, rstring, wfunc, wstring, 0); }
+ void set_handler(const device_t &device, const char *tag, read16_delegate func) { internal_set_handler(device, tag, func, 0); }
+ void set_handler(const device_t &device, const char *tag, write16_delegate func) { internal_set_handler(device, tag, func, 0); }
+ void set_handler(const device_t &device, const char *tag, read16_delegate rfunc, write16_delegate wfunc) { internal_set_handler(device, tag, rfunc, wfunc, 0); }
+
+ // 8-bit handlers
+ void set_handler(read8_space_func func, const char *string, UINT16 mask) { internal_set_handler(func, string, mask); }
+ void set_handler(write8_space_func func, const char *string, UINT16 mask) { internal_set_handler(func, string, mask); }
+ void set_handler(read8_space_func rfunc, const char *rstring, write8_space_func wfunc, const char *wstring, UINT16 mask) { internal_set_handler(rfunc, rstring, wfunc, wstring, mask); }
+ void set_handler(const device_t &device, const char *tag, read8_device_func func, const char *string, UINT16 mask) { internal_set_handler(device, tag, func, string, mask); }
+ void set_handler(const device_t &device, const char *tag, write8_device_func func, const char *string, UINT16 mask) { internal_set_handler(device, tag, func, string, mask); }
+ void set_handler(const device_t &device, const char *tag, read8_device_func rfunc, const char *rstring, write8_device_func wfunc, const char *wstring, UINT16 mask) { internal_set_handler(device, tag, rfunc, rstring, wfunc, wstring, mask); }
+ void set_handler(const device_t &device, const char *tag, read8_delegate func, UINT16 mask) { internal_set_handler(device, tag, func, mask); }
+ void set_handler(const device_t &device, const char *tag, write8_delegate func, UINT16 mask) { internal_set_handler(device, tag, func, mask); }
+ void set_handler(const device_t &device, const char *tag, read8_delegate rfunc, write8_delegate wfunc, UINT16 mask) { internal_set_handler(device, tag, rfunc, wfunc, mask); }
+};
+
+
+// ======================> address_map_entry32
+
+// 32-bit address map version of address_map_entry which only permits valid 32-bit handlers
+class address_map_entry32 : public address_map_entry
+{
+public:
+ address_map_entry32(address_map &map, offs_t start, offs_t end);
+
+ void set_baseptr(UINT32 **baseptr) { internal_set_baseptr(reinterpret_cast<void **>(baseptr)); }
+
+ // native-size handlers
+ void set_handler(read32_space_func func, const char *string) { internal_set_handler(func, string, 0); }
+ void set_handler(write32_space_func func, const char *string) { internal_set_handler(func, string, 0); }
+ void set_handler(read32_space_func rfunc, const char *rstring, write32_space_func wfunc, const char *wstring) { internal_set_handler(rfunc, rstring, wfunc, wstring, 0); }
+ void set_handler(const device_t &device, const char *tag, read32_device_func func, const char *string) { internal_set_handler(device, tag, func, string, 0); }
+ void set_handler(const device_t &device, const char *tag, write32_device_func func, const char *string) { internal_set_handler(device, tag, func, string, 0); }
+ void set_handler(const device_t &device, const char *tag, read32_device_func rfunc, const char *rstring, write32_device_func wfunc, const char *wstring) { internal_set_handler(device, tag, rfunc, rstring, wfunc, wstring, 0); }
+ void set_handler(const device_t &device, const char *tag, read32_delegate func) { internal_set_handler(device, tag, func, 0); }
+ void set_handler(const device_t &device, const char *tag, write32_delegate func) { internal_set_handler(device, tag, func, 0); }
+ void set_handler(const device_t &device, const char *tag, read32_delegate rfunc, write32_delegate wfunc) { internal_set_handler(device, tag, rfunc, wfunc, 0); }
+
+ // 16-bit handlers
+ void set_handler(read16_space_func func, const char *string, UINT32 mask) { internal_set_handler(func, string, mask); }
+ void set_handler(write16_space_func func, const char *string, UINT32 mask) { internal_set_handler(func, string, mask); }
+ void set_handler(read16_space_func rfunc, const char *rstring, write16_space_func wfunc, const char *wstring, UINT32 mask) { internal_set_handler(rfunc, rstring, wfunc, wstring, mask); }
+ void set_handler(const device_t &device, const char *tag, read16_device_func func, const char *string, UINT32 mask) { internal_set_handler(device, tag, func, string, mask); }
+ void set_handler(const device_t &device, const char *tag, write16_device_func func, const char *string, UINT32 mask) { internal_set_handler(device, tag, func, string, mask); }
+ void set_handler(const device_t &device, const char *tag, read16_device_func rfunc, const char *rstring, write16_device_func wfunc, const char *wstring, UINT32 mask) { internal_set_handler(device, tag, rfunc, rstring, wfunc, wstring, mask); }
+ void set_handler(const device_t &device, const char *tag, read16_delegate func, UINT32 mask) { internal_set_handler(device, tag, func, mask); }
+ void set_handler(const device_t &device, const char *tag, write16_delegate func, UINT32 mask) { internal_set_handler(device, tag, func, mask); }
+ void set_handler(const device_t &device, const char *tag, read16_delegate rfunc, write16_delegate wfunc, UINT32 mask) { internal_set_handler(device, tag, rfunc, wfunc, mask); }
+
+ // 8-bit handlers
+ void set_handler(read8_space_func func, const char *string, UINT32 mask) { internal_set_handler(func, string, mask); }
+ void set_handler(write8_space_func func, const char *string, UINT32 mask) { internal_set_handler(func, string, mask); }
+ void set_handler(read8_space_func rfunc, const char *rstring, write8_space_func wfunc, const char *wstring, UINT32 mask) { internal_set_handler(rfunc, rstring, wfunc, wstring, mask); }
+ void set_handler(const device_t &device, const char *tag, read8_device_func func, const char *string, UINT32 mask) { internal_set_handler(device, tag, func, string, mask); }
+ void set_handler(const device_t &device, const char *tag, write8_device_func func, const char *string, UINT32 mask) { internal_set_handler(device, tag, func, string, mask); }
+ void set_handler(const device_t &device, const char *tag, read8_device_func rfunc, const char *rstring, write8_device_func wfunc, const char *wstring, UINT32 mask) { internal_set_handler(device, tag, rfunc, rstring, wfunc, wstring, mask); }
+ void set_handler(const device_t &device, const char *tag, read8_delegate func, UINT32 mask) { internal_set_handler(device, tag, func, mask); }
+ void set_handler(const device_t &device, const char *tag, write8_delegate func, UINT32 mask) { internal_set_handler(device, tag, func, mask); }
+ void set_handler(const device_t &device, const char *tag, read8_delegate rfunc, write8_delegate wfunc, UINT32 mask) { internal_set_handler(device, tag, rfunc, wfunc, mask); }
+};
+
+
+// ======================> address_map_entry64
+
+// 64-bit address map version of address_map_entry which only permits valid 64-bit handlers
+class address_map_entry64 : public address_map_entry
+{
+public:
+ address_map_entry64(address_map &map, offs_t start, offs_t end);
+
+ void set_baseptr(UINT64 **baseptr) { internal_set_baseptr(reinterpret_cast<void **>(baseptr)); }
+
+ // native-size handlers
+ void set_handler(read64_space_func func, const char *string) { internal_set_handler(func, string, 0); }
+ void set_handler(write64_space_func func, const char *string) { internal_set_handler(func, string, 0); }
+ void set_handler(read64_space_func rfunc, const char *rstring, write64_space_func wfunc, const char *wstring) { internal_set_handler(rfunc, rstring, wfunc, wstring, 0); }
+ void set_handler(const device_t &device, const char *tag, read64_device_func func, const char *string) { internal_set_handler(device, tag, func, string, 0); }
+ void set_handler(const device_t &device, const char *tag, write64_device_func func, const char *string) { internal_set_handler(device, tag, func, string, 0); }
+ void set_handler(const device_t &device, const char *tag, read64_device_func rfunc, const char *rstring, write64_device_func wfunc, const char *wstring) { internal_set_handler(device, tag, rfunc, rstring, wfunc, wstring, 0); }
+ void set_handler(const device_t &device, const char *tag, read64_delegate func) { internal_set_handler(device, tag, func, 0); }
+ void set_handler(const device_t &device, const char *tag, write64_delegate func) { internal_set_handler(device, tag, func, 0); }
+ void set_handler(const device_t &device, const char *tag, read64_delegate rfunc, write64_delegate wfunc) { internal_set_handler(device, tag, rfunc, wfunc, 0); }
+
+ // 32-bit handlers
+ void set_handler(read32_space_func func, const char *string, UINT64 mask) { internal_set_handler(func, string, mask); }
+ void set_handler(write32_space_func func, const char *string, UINT64 mask) { internal_set_handler(func, string, mask); }
+ void set_handler(read32_space_func rfunc, const char *rstring, write32_space_func wfunc, const char *wstring, UINT64 mask) { internal_set_handler(rfunc, rstring, wfunc, wstring, mask); }
+ void set_handler(const device_t &device, const char *tag, read32_device_func func, const char *string, UINT64 mask) { internal_set_handler(device, tag, func, string, mask); }
+ void set_handler(const device_t &device, const char *tag, write32_device_func func, const char *string, UINT64 mask) { internal_set_handler(device, tag, func, string, mask); }
+ void set_handler(const device_t &device, const char *tag, read32_device_func rfunc, const char *rstring, write32_device_func wfunc, const char *wstring, UINT64 mask) { internal_set_handler(device, tag, rfunc, rstring, wfunc, wstring, mask); }
+ void set_handler(const device_t &device, const char *tag, read32_delegate func, UINT64 mask) { internal_set_handler(device, tag, func, mask); }
+ void set_handler(const device_t &device, const char *tag, write32_delegate func, UINT64 mask) { internal_set_handler(device, tag, func, mask); }
+ void set_handler(const device_t &device, const char *tag, read32_delegate rfunc, write32_delegate wfunc, UINT64 mask) { internal_set_handler(device, tag, rfunc, wfunc, mask); }
+
+ // 16-bit handlers
+ void set_handler(read16_space_func func, const char *string, UINT64 mask) { internal_set_handler(func, string, mask); }
+ void set_handler(write16_space_func func, const char *string, UINT64 mask) { internal_set_handler(func, string, mask); }
+ void set_handler(read16_space_func rfunc, const char *rstring, write16_space_func wfunc, const char *wstring, UINT64 mask) { internal_set_handler(rfunc, rstring, wfunc, wstring, mask); }
+ void set_handler(const device_t &device, const char *tag, read16_device_func func, const char *string, UINT64 mask) { internal_set_handler(device, tag, func, string, mask); }
+ void set_handler(const device_t &device, const char *tag, write16_device_func func, const char *string, UINT64 mask) { internal_set_handler(device, tag, func, string, mask); }
+ void set_handler(const device_t &device, const char *tag, read16_device_func rfunc, const char *rstring, write16_device_func wfunc, const char *wstring, UINT64 mask) { internal_set_handler(device, tag, rfunc, rstring, wfunc, wstring, mask); }
+ void set_handler(const device_t &device, const char *tag, read16_delegate func, UINT64 mask) { internal_set_handler(device, tag, func, mask); }
+ void set_handler(const device_t &device, const char *tag, write16_delegate func, UINT64 mask) { internal_set_handler(device, tag, func, mask); }
+ void set_handler(const device_t &device, const char *tag, read16_delegate rfunc, write16_delegate wfunc, UINT64 mask) { internal_set_handler(device, tag, rfunc, wfunc, mask); }
+
+ // 8-bit handlers
+ void set_handler(read8_space_func func, const char *string, UINT64 mask) { internal_set_handler(func, string, mask); }
+ void set_handler(write8_space_func func, const char *string, UINT64 mask) { internal_set_handler(func, string, mask); }
+ void set_handler(read8_space_func rfunc, const char *rstring, write8_space_func wfunc, const char *wstring, UINT64 mask) { internal_set_handler(rfunc, rstring, wfunc, wstring, mask); }
+ void set_handler(const device_t &device, const char *tag, read8_device_func func, const char *string, UINT64 mask) { internal_set_handler(device, tag, func, string, mask); }
+ void set_handler(const device_t &device, const char *tag, write8_device_func func, const char *string, UINT64 mask) { internal_set_handler(device, tag, func, string, mask); }
+ void set_handler(const device_t &device, const char *tag, read8_device_func rfunc, const char *rstring, write8_device_func wfunc, const char *wstring, UINT64 mask) { internal_set_handler(device, tag, rfunc, rstring, wfunc, wstring, mask); }
+ void set_handler(const device_t &device, const char *tag, read8_delegate func, UINT64 mask) { internal_set_handler(device, tag, func, mask); }
+ void set_handler(const device_t &device, const char *tag, write8_delegate func, UINT64 mask) { internal_set_handler(device, tag, func, mask); }
+ void set_handler(const device_t &device, const char *tag, read8_delegate rfunc, write8_delegate wfunc, UINT64 mask) { internal_set_handler(device, tag, rfunc, wfunc, mask); }
+};
+
+
+// ======================> address_map
+
+// address_map holds global map parameters plus the head of the list of entries
+class address_map
+{
+public:
+ // construction/destruction
+ address_map(const device_t &device, address_spacenum spacenum);
+ address_map(const device_t &device, address_map_entry *entry);
+ ~address_map();
+
+ // configuration
+ void configure(address_spacenum _spacenum, UINT8 _databits);
+
+ // setters
+ void set_global_mask(offs_t mask);
+ void set_unmap_value(UINT8 value) { m_unmapval = value; }
+
+ // add a new entry of the given type
+ address_map_entry8 *add(offs_t start, offs_t end, address_map_entry8 *ptr);
+ address_map_entry16 *add(offs_t start, offs_t end, address_map_entry16 *ptr);
+ address_map_entry32 *add(offs_t start, offs_t end, address_map_entry32 *ptr);
+ address_map_entry64 *add(offs_t start, offs_t end, address_map_entry64 *ptr);
+
+ // public data
+ address_spacenum m_spacenum; // space number of the map
+ UINT8 m_databits; // data bits represented by the map
+ UINT8 m_unmapval; // unmapped memory value
+ offs_t m_globalmask; // global mask
+ simple_list<address_map_entry> m_entrylist; // list of entries
+
+ void uplift_submaps(running_machine &machine, device_t &device, endianness_t endian);
+};
+
+
+//**************************************************************************
+// ADDRESS MAP MACROS
+//**************************************************************************
+
+//
+// There are two versions of the macros below
+//
+// By default, the legacy forms are enabled; however, if ADDRESS_MAP_MODERN is #defined
+// prior to including this file, the new format are enabled instead.
+//
+
+// so that "0" can be used for unneeded address maps
+#define construct_address_map_0 NULL
+
+
+#ifndef ADDRESS_MAP_MODERN
+
+//
+// Legacy ADDRESS_MAPs
+//
+
+// start/end tags for the address map
+#define ADDRESS_MAP_NAME(_name) construct_address_map_##_name
+
+#define ADDRESS_MAP_START(_name, _space, _bits) \
+void ADDRESS_MAP_NAME(_name)(address_map &map, const device_t &device) \
+{ \
+ typedef read##_bits##_delegate read_delegate; \
+ typedef write##_bits##_delegate write_delegate; \
+ address_map_entry##_bits *curentry = NULL; \
+ (void)curentry; \
+ map.configure(_space, _bits); \
+
+#define ADDRESS_MAP_END \
+}
+
+// use this to declare external references to an address map
+#define ADDRESS_MAP_EXTERN(_name, _bits) \
+ extern void ADDRESS_MAP_NAME(_name)(address_map &map, const device_t &device)
+
+// use this to declare an address map as a member of a modern device class
+#define DECLARE_ADDRESS_MAP(_name, _bits) \
+ void _name(address_map &map, const device_t &device)
+
+
+// global controls
+#define ADDRESS_MAP_GLOBAL_MASK(_mask) \
+ map.set_global_mask(_mask); \
+
+#define ADDRESS_MAP_UNMAP_LOW \
+ map.set_unmap_value(0); \
+
+#define ADDRESS_MAP_UNMAP_HIGH \
+ map.set_unmap_value(~0); \
+
+
+// importing data from other address maps
+#define AM_IMPORT_FROM(_name) \
+ ADDRESS_MAP_NAME(_name)(map, device); \
+
+
+// address ranges
+#define AM_RANGE(_start, _end) \
+ curentry = map.add(_start, _end, curentry); \
+
+#define AM_MASK(_mask) \
+ curentry->set_mask(_mask); \
+
+#define AM_MIRROR(_mirror) \
+ curentry->set_mirror(_mirror); \
+
+
+// legacy space reads
+#define AM_READ(_handler) \
+ curentry->set_handler(_handler, #_handler); \
+
+#define AM_READ8(_handler, _unitmask) \
+ curentry->set_handler(_handler, #_handler, _unitmask); \
+
+#define AM_READ16(_handler, _unitmask) \
+ curentry->set_handler(_handler, #_handler, _unitmask); \
+
+#define AM_READ32(_handler, _unitmask) \
+ curentry->set_handler(_handler, #_handler, _unitmask); \
+
+
+// legacy space writes
+#define AM_WRITE(_handler) \
+ curentry->set_handler(_handler, #_handler); \
+
+#define AM_WRITE8(_handler, _unitmask) \
+ curentry->set_handler(_handler, #_handler, _unitmask); \
+
+#define AM_WRITE16(_handler, _unitmask) \
+ curentry->set_handler(_handler, #_handler, _unitmask); \
+
+#define AM_WRITE32(_handler, _unitmask) \
+ curentry->set_handler(_handler, #_handler, _unitmask); \
+
+
+// legacy space reads/writes
+#define AM_READWRITE(_rhandler, _whandler) \
+ curentry->set_handler(_rhandler, #_rhandler, _whandler, #_whandler); \
+
+#define AM_READWRITE8(_rhandler, _whandler, _unitmask) \
+ curentry->set_handler(_rhandler, #_rhandler, _whandler, #_whandler, _unitmask); \
+
+#define AM_READWRITE16(_rhandler, _whandler, _unitmask) \
+ curentry->set_handler(_rhandler, #_rhandler, _whandler, #_whandler, _unitmask); \
+
+#define AM_READWRITE32(_rhandler, _whandler, _unitmask) \
+ curentry->set_handler(_rhandler, #_rhandler, _whandler, #_whandler, _unitmask); \
+
+
+// legacy device reads
+#define AM_DEVREAD(_tag, _handler) \
+ curentry->set_handler(device, _tag, _handler, #_handler); \
+
+#define AM_DEVREAD8(_tag, _handler, _unitmask) \
+ curentry->set_handler(device, _tag, _handler, #_handler, _unitmask); \
+
+#define AM_DEVREAD16(_tag, _handler, _unitmask) \
+ curentry->set_handler(device, _tag, _handler, #_handler, _unitmask); \
+
+#define AM_DEVREAD32(_tag, _handler, _unitmask) \
+ curentry->set_handler(device, _tag, _handler, #_handler, _unitmask); \
+
+
+// legacy device writes
+#define AM_DEVWRITE(_tag, _handler) \
+ curentry->set_handler(device, _tag, _handler, #_handler); \
+
+#define AM_DEVWRITE8(_tag, _handler, _unitmask) \
+ curentry->set_handler(device, _tag, _handler, #_handler, _unitmask); \
+
+#define AM_DEVWRITE16(_tag, _handler, _unitmask) \
+ curentry->set_handler(device, _tag, _handler, #_handler, _unitmask); \
+
+#define AM_DEVWRITE32(_tag, _handler, _unitmask) \
+ curentry->set_handler(device, _tag, _handler, #_handler, _unitmask); \
+
+
+// legacy device reads/writes
+#define AM_DEVREADWRITE(_tag, _rhandler, _whandler) \
+ curentry->set_handler(device, _tag, _rhandler, #_rhandler, _whandler, #_whandler); \
+
+#define AM_DEVREADWRITE8(_tag, _rhandler, _whandler, _unitmask) \
+ curentry->set_handler(device, _tag, _rhandler, #_rhandler, _whandler, #_whandler, _unitmask); \
+
+#define AM_DEVREADWRITE16(_tag, _rhandler, _whandler, _unitmask) \
+ curentry->set_handler(device, _tag, _rhandler, #_rhandler, _whandler, #_whandler, _unitmask); \
+
+#define AM_DEVREADWRITE32(_tag, _rhandler, _whandler, _unitmask) \
+ curentry->set_handler(device, _tag, _rhandler, #_rhandler, _whandler, #_whandler, _unitmask); \
+
+
+// device reads
+#define AM_DEVREAD_MODERN(_tag, _class, _handler) \
+ curentry->set_handler(device, _tag, read_delegate(&_class::_handler, #_class "::" #_handler, (_class *)0)); \
+
+#define AM_DEVREAD8_MODERN(_tag, _class, _handler, _unitmask) \
+ curentry->set_handler(device, _tag, read8_delegate(&_class::_handler, #_class "::" #_handler, (_class *)0), _unitmask); \
+
+#define AM_DEVREAD16_MODERN(_tag, _class, _handler, _unitmask) \
+ curentry->set_handler(device, _tag, read16_delegate(&_class::_handler, #_class "::" #_handler, (_class *)0), _unitmask); \
+
+#define AM_DEVREAD32_MODERN(_tag, _class, _handler, _unitmask) \
+ curentry->set_handler(device, _tag, read32_delegate(&_class::_handler, #_class "::" #_handler, (_class *)0), _unitmask); \
+
+
+// device writes
+#define AM_DEVWRITE_MODERN(_tag, _class, _handler) \
+ curentry->set_handler(device, _tag, write_delegate(&_class::_handler, #_class "::" #_handler, (_class *)0)); \
+
+#define AM_DEVWRITE8_MODERN(_tag, _class, _handler, _unitmask) \
+ curentry->set_handler(device, _tag, write8_delegate(&_class::_handler, #_class "::" #_handler, (_class *)0), _unitmask); \
+
+#define AM_DEVWRITE16_MODERN(_tag, _class, _handler, _unitmask) \
+ curentry->set_handler(device, _tag, write16_delegate(&_class::_handler, #_class "::" #_handler, (_class *)0), _unitmask); \
+
+#define AM_DEVWRITE32_MODERN(_tag, _class, _handler, _unitmask) \
+ curentry->set_handler(device, _tag, write32_delegate(&_class::_handler, #_class "::" #_handler, (_class *)0), _unitmask); \
+
+
+// device reads/writes
+#define AM_DEVREADWRITE_MODERN(_tag, _class, _rhandler, _whandler) \
+ curentry->set_handler(device, _tag, read_delegate(&_class::_rhandler, #_class "::" #_rhandler, (_class *)0), write_delegate(&_class::_whandler, #_class "::" #_whandler, (_class *)0)); \
+
+#define AM_DEVREADWRITE8_MODERN(_tag, _class, _rhandler, _whandler, _unitmask) \
+ curentry->set_handler(device, _tag, read8_delegate(&_class::_rhandler, #_class "::" #_rhandler, (_class *)0), write8_delegate(&_class::_whandler, #_class "::" #_whandler, (_class *)0), _unitmask); \
+
+#define AM_DEVREADWRITE16_MODERN(_tag, _class, _rhandler, _whandler, _unitmask) \
+ curentry->set_handler(device, _tag, read16_delegate(&_class::_rhandler, #_class "::" #_rhandler, (_class *)0), write16_delegate(&_class::_whandler, #_class "::" #_whandler, (_class *)0), _unitmask); \
+
+#define AM_DEVREADWRITE32_MODERN(_tag, _class, _rhandler, _whandler, _unitmask) \
+ curentry->set_handler(device, _tag, read32_delegate(&_class::_rhandler, #_class "::" #_rhandler, (_class *)0), write32_delegate(&_class::_whandler, #_class "::" #_whandler, (_class *)0), _unitmask); \
+
+
+// device mapping
+#define AM_DEVICE(_tag, _class, _handler) \
+ curentry->set_submap(device, _tag, address_map_delegate(&_class::_handler, #_class "::" #_handler, (_class *)0), 0, 0); \
+
+#define AM_DEVICE8(_tag, _class, _handler, _unitmask) \
+ curentry->set_submap(device, _tag, address_map_delegate(&_class::_handler, #_class "::" #_handler, (_class *)0), 8, _unitmask); \
+
+#define AM_DEVICE16(_tag, _class, _handler, _unitmask) \
+ curentry->set_submap(device, _tag, address_map_delegate(&_class::_handler, #_class "::" #_handler, (_class *)0), 16, _unitmask); \
+
+#define AM_DEVICE32(_tag, _class, _handler, _unitmask) \
+ curentry->set_submap(device, _tag, address_map_delegate(&_class::_handler, #_class "::" #_handler, (_class *)0), 32, _unitmask); \
+
+
+
+// special-case accesses
+#define AM_ROM \
+ curentry->set_read_type(AMH_ROM); \
+
+#define AM_RAM \
+ curentry->set_read_type(AMH_RAM); \
+ curentry->set_write_type(AMH_RAM); \
+
+#define AM_READONLY \
+ curentry->set_read_type(AMH_RAM); \
+
+#define AM_WRITEONLY \
+ curentry->set_write_type(AMH_RAM); \
+
+#define AM_UNMAP \
+ curentry->set_read_type(AMH_UNMAP); \
+ curentry->set_write_type(AMH_UNMAP); \
+
+#define AM_NOP \
+ curentry->set_read_type(AMH_NOP); \
+ curentry->set_write_type(AMH_NOP); \
+
+#define AM_READNOP \
+ curentry->set_read_type(AMH_NOP); \
+
+#define AM_WRITENOP \
+ curentry->set_write_type(AMH_NOP); \
+
+
+// port accesses
+#define AM_READ_PORT(_tag) \
+ curentry->set_read_port(device, _tag); \
+
+#define AM_WRITE_PORT(_tag) \
+ curentry->set_write_port(device, _tag); \
+
+#define AM_READWRITE_PORT(_tag) \
+ curentry->set_readwrite_port(device, _tag); \
+
+
+// bank accesses
+#define AM_READ_BANK(_tag) \
+ curentry->set_read_bank(device, _tag); \
+
+#define AM_WRITE_BANK(_tag) \
+ curentry->set_write_bank(device, _tag); \
+
+#define AM_READWRITE_BANK(_tag) \
+ curentry->set_readwrite_bank(device, _tag); \
+
+
+// attributes for accesses
+#define AM_REGION(_tag, _offs) \
+ curentry->set_region(_tag, _offs); \
+
+#define AM_SHARE(_tag) \
+ curentry->set_share(_tag); \
+
+#define AM_BASE(_base) \
+ curentry->set_baseptr(_base); \
+
+#define myoffsetof(_struct, _member) ((FPTR)&((_struct *)0x1000)->_member - 0x1000)
+#define AM_BASE_MEMBER(_struct, _member) \
+ curentry->set_member_baseptr(myoffsetof(_struct, _member)); \
+
+#define AM_BASE_GENERIC(_member) \
+ curentry->set_generic_baseptr(myoffsetof(generic_pointers, _member)); \
+
+#define AM_SIZE(_size) \
+ curentry->set_sizeptr(_size); \
+
+#define AM_SIZE_MEMBER(_struct, _member) \
+ curentry->set_member_sizeptr(myoffsetof(_struct, _member)); \
+
+#define AM_SIZE_GENERIC(_member) \
+ curentry->set_generic_sizeptr(myoffsetof(generic_pointers, _member##_size)); \
+
+
+// common shortcuts
+#define AM_ROMBANK(_bank) AM_READ_BANK(_bank)
+#define AM_RAMBANK(_bank) AM_READWRITE_BANK(_bank)
+#define AM_RAM_READ(_read) AM_READ(_read) AM_WRITEONLY
+#define AM_RAM_WRITE(_write) AM_READONLY AM_WRITE(_write)
+#define AM_RAM_DEVREAD(_tag, _read) AM_DEVREAD(_tag, _read) AM_WRITEONLY
+#define AM_RAM_DEVWRITE(_tag, _write) AM_READONLY AM_DEVWRITE(_tag, _write)
+
+#define AM_BASE_SIZE_MEMBER(_struct, _base, _size) AM_BASE_MEMBER(_struct, _base) AM_SIZE_MEMBER(_struct, _size)
+#define AM_BASE_SIZE_GENERIC(_member) AM_BASE_GENERIC(_member) AM_SIZE_GENERIC(_member)
+
+
+#else
+
+//
+// Modern ADDRESS_MAPs
+//
+
+// start/end tags for the address map
+#define ADDRESS_MAP_NAME(_name) construct_address_map_##_name
+
+#define ADDRESS_MAP_START(_name, _space, _bits, _class) \
+void ADDRESS_MAP_NAME(_name)(address_map &map, const device_t &device) \
+{ \
+ typedef read##_bits##_delegate read_delegate; \
+ typedef write##_bits##_delegate write_delegate; \
+ address_map_entry##_bits *curentry = NULL; \
+ (void)curentry; \
+ map.configure(_space, _bits); \
+ typedef _class drivdata_class; \
+
+#define DEVICE_ADDRESS_MAP_START(_name, _bits, _class) \
+void _class :: _name(address_map &map, const device_t &device) \
+{ \
+ typedef read##_bits##_delegate read_delegate; \
+ typedef write##_bits##_delegate write_delegate; \
+ address_map_entry##_bits *curentry = NULL; \
+ (void)curentry; \
+ map.configure(AS_PROGRAM, _bits); \
+ typedef _class drivdata_class; \
+
+#define ADDRESS_MAP_END \
+}
+
+// use this to declare external references to an address map
+#define ADDRESS_MAP_EXTERN(_name, _bits) \
+ extern void ADDRESS_MAP_NAME(_name)(address_map &map, const device_t &device)
+
+// use this to declare an address map as a member of a modern device class
+#define DECLARE_ADDRESS_MAP(_name, _bits) \
+ void _name(address_map &map, const device_t &device)
+
+
+// global controls
+#define ADDRESS_MAP_GLOBAL_MASK(_mask) \
+ map.set_global_mask(_mask); \
+
+#define ADDRESS_MAP_UNMAP_LOW \
+ map.set_unmap_value(0); \
+
+#define ADDRESS_MAP_UNMAP_HIGH \
+ map.set_unmap_value(~0); \
+
+
+// importing data from other address maps
+#define AM_IMPORT_FROM(_name) \
+ ADDRESS_MAP_NAME(_name)(map, device); \
+
+// importing data from inherited address maps
+#define AM_INHERIT_FROM(_name) \
+ _name(map, device); \
+
+
+// address ranges
+#define AM_RANGE(_start, _end) \
+ curentry = map.add(_start, _end, curentry); \
+
+#define AM_MASK(_mask) \
+ curentry->set_mask(_mask); \
+
+#define AM_MIRROR(_mirror) \
+ curentry->set_mirror(_mirror); \
+
+
+// legacy space reads
+#define AM_READ_LEGACY(_handler) \
+ curentry->set_handler(_handler, #_handler); \
+
+#define AM_READ8_LEGACY(_handler, _unitmask) \
+ curentry->set_handler(_handler, #_handler, _unitmask); \
+
+#define AM_READ16_LEGACY(_handler, _unitmask) \
+ curentry->set_handler(_handler, #_handler, _unitmask); \
+
+#define AM_READ32_LEGACY(_handler, _unitmask) \
+ curentry->set_handler(_handler, #_handler, _unitmask); \
+
+
+// legacy space writes
+#define AM_WRITE_LEGACY(_handler) \
+ curentry->set_handler(_handler, #_handler); \
+
+#define AM_WRITE8_LEGACY(_handler, _unitmask) \
+ curentry->set_handler(_handler, #_handler, _unitmask); \
+
+#define AM_WRITE16_LEGACY(_handler, _unitmask) \
+ curentry->set_handler(_handler, #_handler, _unitmask); \
+
+#define AM_WRITE32_LEGACY(_handler, _unitmask) \
+ curentry->set_handler(_handler, #_handler, _unitmask); \
+
+
+// legacy space reads/writes
+#define AM_READWRITE_LEGACY(_rhandler, _whandler) \
+ curentry->set_handler(_rhandler, #_rhandler, _whandler, #_whandler); \
+
+#define AM_READWRITE8_LEGACY(_rhandler, _whandler, _unitmask) \
+ curentry->set_handler(_rhandler, #_rhandler, _whandler, #_whandler, _unitmask); \
+
+#define AM_READWRITE16_LEGACY(_rhandler, _whandler, _unitmask) \
+ curentry->set_handler(_rhandler, #_rhandler, _whandler, #_whandler, _unitmask); \
+
+#define AM_READWRITE32_LEGACY(_rhandler, _whandler, _unitmask) \
+ curentry->set_handler(_rhandler, #_rhandler, _whandler, #_whandler, _unitmask); \
+
+
+// legacy device reads
+#define AM_DEVREAD_LEGACY(_tag, _handler) \
+ curentry->set_handler(device, _tag, _handler, #_handler); \
+
+#define AM_DEVREAD8_LEGACY(_tag, _handler, _unitmask) \
+ curentry->set_handler(device, _tag, _handler, #_handler, _unitmask); \
+
+#define AM_DEVREAD16_LEGACY(_tag, _handler, _unitmask) \
+ curentry->set_handler(device, _tag, _handler, #_handler, _unitmask); \
+
+#define AM_DEVREAD32_LEGACY(_tag, _handler, _unitmask) \
+ curentry->set_handler(device, _tag, _handler, #_handler, _unitmask); \
+
+
+// legacy device writes
+#define AM_DEVWRITE_LEGACY(_tag, _handler) \
+ curentry->set_handler(device, _tag, _handler, #_handler); \
+
+#define AM_DEVWRITE8_LEGACY(_tag, _handler, _unitmask) \
+ curentry->set_handler(device, _tag, _handler, #_handler, _unitmask); \
+
+#define AM_DEVWRITE16_LEGACY(_tag, _handler, _unitmask) \
+ curentry->set_handler(device, _tag, _handler, #_handler, _unitmask); \
+
+#define AM_DEVWRITE32_LEGACY(_tag, _handler, _unitmask) \
+ curentry->set_handler(device, _tag, _handler, #_handler, _unitmask); \
+
+
+// legacy device reads/writes
+#define AM_DEVREADWRITE_LEGACY(_tag, _rhandler, _whandler) \
+ curentry->set_handler(device, _tag, _rhandler, #_rhandler, _whandler, #_whandler); \
+
+#define AM_DEVREADWRITE8_LEGACY(_tag, _rhandler, _whandler, _unitmask) \
+ curentry->set_handler(device, _tag, _rhandler, #_rhandler, _whandler, #_whandler, _unitmask); \
+
+#define AM_DEVREADWRITE16_LEGACY(_tag, _rhandler, _whandler, _unitmask) \
+ curentry->set_handler(device, _tag, _rhandler, #_rhandler, _whandler, #_whandler, _unitmask); \
+
+#define AM_DEVREADWRITE32_LEGACY(_tag, _rhandler, _whandler, _unitmask) \
+ curentry->set_handler(device, _tag, _rhandler, #_rhandler, _whandler, #_whandler, _unitmask); \
+
+
+// driver data base reads
+#define AM_READ_BASE(_class, _handler) \
+ curentry->set_handler(device, DEVICE_SELF, read_delegate(&_class::_handler, "driver_data::" #_handler, (_class *)0)); \
+
+#define AM_READ8_BASE(_class, _handler, _unitmask) \
+ curentry->set_handler(device, DEVICE_SELF, read8_delegate(&_class::_handler, "driver_data::" #_handler, (_class *)0), _unitmask); \
+
+#define AM_READ16_BASE(_class, _handler, _unitmask) \
+ curentry->set_handler(device, DEVICE_SELF, read16_delegate(&_class::_handler, "driver_data::" #_handler, (_class *)0), _unitmask); \
+
+#define AM_READ32_BASE(_class, _handler, _unitmask) \
+ curentry->set_handler(device, DEVICE_SELF, read32_delegate(&_class::_handler, "driver_data::" #_handler, (_class *)0), _unitmask); \
+
+
+// driver data base writes
+#define AM_WRITE_BASE(_class, _handler) \
+ curentry->set_handler(device, DEVICE_SELF, write_delegate(&_class::_handler, "driver_data::" #_handler, (_class *)0)); \
+
+#define AM_WRITE8_BASE(_class, _handler, _unitmask) \
+ curentry->set_handler(device, DEVICE_SELF, write8_delegate(&_class::_handler, "driver_data::" #_handler, (_class *)0), _unitmask); \
+
+#define AM_WRITE16_BASE(_class, _handler, _unitmask) \
+ curentry->set_handler(device, DEVICE_SELF, write16_delegate(&_class::_handler, "driver_data::" #_handler, (_class *)0), _unitmask); \
+
+#define AM_WRITE32_BASE(_class, _handler, _unitmask) \
+ curentry->set_handler(device, DEVICE_SELF, write32_delegate(&_class::_handler, "driver_data::" #_handler, (_class *)0), _unitmask); \
+
+
+// driver data base reads/writes
+#define AM_READWRITE_BASE(_class, _rhandler, _whandler) \
+ curentry->set_handler(device, DEVICE_SELF, read_delegate(&_class::_rhandler, "driver_data::" #_rhandler, (_class *)0), write_delegate(&_class::_whandler, "driver_data::" #_whandler, (_class *)0)); \
+
+#define AM_READWRITE8_BASE(_class, _rhandler, _whandler, _unitmask) \
+ curentry->set_handler(device, DEVICE_SELF, read8_delegate(&_class::_rhandler, "driver_data::" #_rhandler, (_class *)0), write8_delegate(&_class::_whandler, "driver_data::" #_whandler, (_class *)0), _unitmask); \
+
+#define AM_READWRITE16_BASE(_class, _rhandler, _whandler, _unitmask) \
+ curentry->set_handler(device, DEVICE_SELF, read16_delegate(&_class::_rhandler, "driver_data::" #_rhandler, (_class *)0), write16_delegate(&_class::_whandler, "driver_data::" #_whandler, (_class *)0), _unitmask); \
+
+#define AM_READWRITE32_BASE(_class, _rhandler, _whandler, _unitmask) \
+ curentry->set_handler(device, DEVICE_SELF, read32_delegate(&_class::_rhandler, "driver_data::" #_rhandler, (_class *)0), write32_delegate(&_class::_whandler, "driver_data::" #_whandler, (_class *)0), _unitmask); \
+
+
+// driver data reads
+#define AM_READ(_handler) \
+ curentry->set_handler(device, DEVICE_SELF, read_delegate(&drivdata_class::_handler, "driver_data::" #_handler, (drivdata_class *)0)); \
+
+#define AM_READ8(_handler, _unitmask) \
+ curentry->set_handler(device, DEVICE_SELF, read8_delegate(&drivdata_class::_handler, "driver_data::" #_handler, (drivdata_class *)0), _unitmask); \
+
+#define AM_READ16(_handler, _unitmask) \
+ curentry->set_handler(device, DEVICE_SELF, read16_delegate(&drivdata_class::_handler, "driver_data::" #_handler, (drivdata_class *)0), _unitmask); \
+
+#define AM_READ32(_handler, _unitmask) \
+ curentry->set_handler(device, DEVICE_SELF, read32_delegate(&drivdata_class::_handler, "driver_data::" #_handler, (drivdata_class *)0), _unitmask); \
+
+
+// driver data writes
+#define AM_WRITE(_handler) \
+ curentry->set_handler(device, DEVICE_SELF, write_delegate(&drivdata_class::_handler, "driver_data::" #_handler, (drivdata_class *)0)); \
+
+#define AM_WRITE8(_handler, _unitmask) \
+ curentry->set_handler(device, DEVICE_SELF, write8_delegate(&drivdata_class::_handler, "driver_data::" #_handler, (drivdata_class *)0), _unitmask); \
+
+#define AM_WRITE16(_handler, _unitmask) \
+ curentry->set_handler(device, DEVICE_SELF, write16_delegate(&drivdata_class::_handler, "driver_data::" #_handler, (drivdata_class *)0), _unitmask); \
+
+#define AM_WRITE32(_handler, _unitmask) \
+ curentry->set_handler(device, DEVICE_SELF, write32_delegate(&drivdata_class::_handler, "driver_data::" #_handler, (drivdata_class *)0), _unitmask); \
+
+
+// driver data reads/writes
+#define AM_READWRITE(_rhandler, _whandler) \
+ curentry->set_handler(device, DEVICE_SELF, read_delegate(&drivdata_class::_rhandler, "driver_data::" #_rhandler, (drivdata_class *)0), write_delegate(&drivdata_class::_whandler, "driver_data::" #_whandler, (drivdata_class *)0)); \
+
+#define AM_READWRITE8(_rhandler, _whandler, _unitmask) \
+ curentry->set_handler(device, DEVICE_SELF, read8_delegate(&drivdata_class::_rhandler, "driver_data::" #_rhandler, (drivdata_class *)0), write8_delegate(&drivdata_class::_whandler, "driver_data::" #_whandler, (drivdata_class *)0), _unitmask); \
+
+#define AM_READWRITE16(_rhandler, _whandler, _unitmask) \
+ curentry->set_handler(device, DEVICE_SELF, read16_delegate(&drivdata_class::_rhandler, "driver_data::" #_rhandler, (drivdata_class *)0), write16_delegate(&drivdata_class::_whandler, "driver_data::" #_whandler, (drivdata_class *)0), _unitmask); \
+
+#define AM_READWRITE32(_rhandler, _whandler, _unitmask) \
+ curentry->set_handler(device, DEVICE_SELF, read32_delegate(&drivdata_class::_rhandler, "driver_data::" #_rhandler, (drivdata_class *)0), write32_delegate(&drivdata_class::_whandler, "driver_data::" #_whandler, (drivdata_class *)0), _unitmask); \
+
+
+// device reads
+#define AM_DEVREAD(_tag, _class, _handler) \
+ curentry->set_handler(device, _tag, read_delegate(&_class::_handler, #_class "::" #_handler, (_class *)0)); \
+
+#define AM_DEVREAD8(_tag, _class, _handler, _unitmask) \
+ curentry->set_handler(device, _tag, read8_delegate(&_class::_handler, #_class "::" #_handler, (_class *)0), _unitmask); \
+
+#define AM_DEVREAD16(_tag, _class, _handler, _unitmask) \
+ curentry->set_handler(device, _tag, read16_delegate(&_class::_handler, #_class "::" #_handler, (_class *)0), _unitmask); \
+
+#define AM_DEVREAD32(_tag, _class, _handler, _unitmask) \
+ curentry->set_handler(device, _tag, read32_delegate(&_class::_handler, #_class "::" #_handler, (_class *)0), _unitmask); \
+
+
+// device writes
+#define AM_DEVWRITE(_tag, _class, _handler) \
+ curentry->set_handler(device, _tag, write_delegate(&_class::_handler, #_class "::" #_handler, (_class *)0)); \
+
+#define AM_DEVWRITE8(_tag, _class, _handler, _unitmask) \
+ curentry->set_handler(device, _tag, write8_delegate(&_class::_handler, #_class "::" #_handler, (_class *)0), _unitmask); \
+
+#define AM_DEVWRITE16(_tag, _class, _handler, _unitmask) \
+ curentry->set_handler(device, _tag, write16_delegate(&_class::_handler, #_class "::" #_handler, (_class *)0), _unitmask); \
+
+#define AM_DEVWRITE32(_tag, _class, _handler, _unitmask) \
+ curentry->set_handler(device, _tag, write32_delegate(&_class::_handler, #_class "::" #_handler, (_class *)0), _unitmask); \
+
+
+// device reads/writes
+#define AM_DEVREADWRITE(_tag, _class, _rhandler, _whandler) \
+ curentry->set_handler(device, _tag, read_delegate(&_class::_rhandler, #_class "::" #_rhandler, (_class *)0), write_delegate(&_class::_whandler, #_class "::" #_whandler, (_class *)0)); \
+
+#define AM_DEVREADWRITE8(_tag, _class, _rhandler, _whandler, _unitmask) \
+ curentry->set_handler(device, _tag, read8_delegate(&_class::_rhandler, #_class "::" #_rhandler, (_class *)0), write8_delegate(&_class::_whandler, #_class "::" #_whandler, (_class *)0), _unitmask); \
+
+#define AM_DEVREADWRITE16(_tag, _class, _rhandler, _whandler, _unitmask) \
+ curentry->set_handler(device, _tag, read16_delegate(&_class::_rhandler, #_class "::" #_rhandler, (_class *)0), write16_delegate(&_class::_whandler, #_class "::" #_whandler, (_class *)0), _unitmask); \
+
+#define AM_DEVREADWRITE32(_tag, _class, _rhandler, _whandler, _unitmask) \
+ curentry->set_handler(device, _tag, read32_delegate(&_class::_rhandler, #_class "::" #_rhandler, (_class *)0), write32_delegate(&_class::_whandler, #_class "::" #_whandler, (_class *)0), _unitmask); \
+
+
+// device mapping
+#define AM_DEVICE(_tag, _class, _handler) \
+ curentry->set_submap(device, _tag, address_map_delegate(&_class::_handler, #_class "::" #_handler, (_class *)0), 0, 0); \
+
+#define AM_DEVICE8(_tag, _class, _handler, _unitmask) \
+ curentry->set_submap(device, _tag, address_map_delegate(&_class::_handler, #_class "::" #_handler, (_class *)0), 8, _unitmask); \
+
+#define AM_DEVICE16(_tag, _class, _handler, _unitmask) \
+ curentry->set_submap(device, _tag, address_map_delegate(&_class::_handler, #_class "::" #_handler, (_class *)0), 16, _unitmask); \
+
+#define AM_DEVICE32(_tag, _class, _handler, _unitmask) \
+ curentry->set_submap(device, _tag, address_map_delegate(&_class::_handler, #_class "::" #_handler, (_class *)0), 32, _unitmask); \
+
+
+// special-case accesses
+#define AM_ROM \
+ curentry->set_read_type(AMH_ROM); \
+
+#define AM_RAM \
+ curentry->set_read_type(AMH_RAM); \
+ curentry->set_write_type(AMH_RAM); \
+
+#define AM_READONLY \
+ curentry->set_read_type(AMH_RAM); \
+
+#define AM_WRITEONLY \
+ curentry->set_write_type(AMH_RAM); \
+
+#define AM_UNMAP \
+ curentry->set_read_type(AMH_UNMAP); \
+ curentry->set_write_type(AMH_UNMAP); \
+
+#define AM_NOP \
+ curentry->set_read_type(AMH_NOP); \
+ curentry->set_write_type(AMH_NOP); \
+
+#define AM_READNOP \
+ curentry->set_read_type(AMH_NOP); \
+
+#define AM_WRITENOP \
+ curentry->set_write_type(AMH_NOP); \
+
+
+// port accesses
+#define AM_READ_PORT(_tag) \
+ curentry->set_read_port(device, _tag); \
+
+#define AM_WRITE_PORT(_tag) \
+ curentry->set_write_port(device, _tag); \
+
+#define AM_READWRITE_PORT(_tag) \
+ curentry->set_readwrite_port(device, _tag); \
+
+
+// bank accesses
+#define AM_READ_BANK(_tag) \
+ curentry->set_read_bank(device, _tag); \
+
+#define AM_WRITE_BANK(_tag) \
+ curentry->set_write_bank(device, _tag); \
+
+#define AM_READWRITE_BANK(_tag) \
+ curentry->set_readwrite_bank(device, _tag); \
+
+
+// attributes for accesses
+#define AM_REGION(_tag, _offs) \
+ curentry->set_region(_tag, _offs); \
+
+#define AM_SHARE(_tag) \
+ curentry->set_share(_tag); \
+
+#define AM_BASE_LEGACY(_base) \
+ curentry->set_baseptr(_base); \
+
+#define myoffsetof(_struct, _member) ((FPTR)&((_struct *)0x1000)->_member - 0x1000)
+#define AM_BASE(_member) \
+ curentry->set_member_baseptr(myoffsetof(drivdata_class, _member)); \
+
+#define AM_BASE_GENERIC(_member) \
+ curentry->set_generic_baseptr(myoffsetof(generic_pointers, _member)); \
+
+#define AM_SIZE_LEGACY(_size) \
+ curentry->set_sizeptr(_size); \
+
+#define AM_SIZE(_struct, _member) \
+ curentry->set_member_sizeptr(myoffsetof(drivdata_class, _member)); \
+
+#define AM_SIZE_GENERIC(_member) \
+ curentry->set_generic_sizeptr(myoffsetof(generic_pointers, _member##_size)); \
+
+
+// common shortcuts
+#define AM_ROMBANK(_bank) AM_READ_BANK(_bank)
+#define AM_RAMBANK(_bank) AM_READWRITE_BANK(_bank)
+#define AM_RAM_READ(_read) AM_READ(_read) AM_WRITEONLY
+#define AM_RAM_WRITE(_write) AM_READONLY AM_WRITE(_write)
+#define AM_RAM_DEVREAD(_tag, _class, _read) AM_DEVREAD(_tag, _class, _read) AM_WRITEONLY
+#define AM_RAM_DEVWRITE(_tag, _class, _write) AM_READONLY AM_DEVWRITE(_tag, _class, _write)
+
+#define AM_BASE_SIZE(_base, _size) AM_BASE_MEMBER(_base) AM_SIZE_MEMBER(_size)
+#define AM_BASE_SIZE_GENERIC(_member) AM_BASE_GENERIC(_member) AM_SIZE_GENERIC(_member)
+
+#endif
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// use this to refer to the owning device when providing a device tag
+static const char DEVICE_SELF[] = "";
+
+// use this to refer to the owning device's owner when providing a device tag
+static const char DEVICE_SELF_OWNER[] = "^";
+
+
+#endif /* __ADDRMAP_H__ */
diff --git a/trunk/src/emu/attotime.c b/trunk/src/emu/attotime.c
new file mode 100644
index 00000000000..d28f832ceca
--- /dev/null
+++ b/trunk/src/emu/attotime.c
@@ -0,0 +1,187 @@
+/***************************************************************************
+
+ attotime.c
+
+ Support functions for working with attotime data.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+***************************************************************************/
+
+#include "emucore.h"
+#include "eminline.h"
+#include "attotime.h"
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+const attotime attotime::zero(0, 0);
+const attotime attotime::never(ATTOTIME_MAX_SECONDS, 0);
+
+
+
+//**************************************************************************
+// CORE MATH FUNCTIONS
+//**************************************************************************
+
+//-------------------------------------------------
+// operator*= - multiply an attotime by a
+// constant
+//-------------------------------------------------
+
+attotime &attotime::operator*=(UINT32 factor)
+{
+ // if one of the items is attotime::never, return attotime::never
+ if (seconds >= ATTOTIME_MAX_SECONDS)
+ return *this = never;
+
+ // 0 times anything is zero
+ if (factor == 0)
+ return *this = zero;
+
+ // split attoseconds into upper and lower halves which fit into 32 bits
+ UINT32 attolo;
+ UINT32 attohi = divu_64x32_rem(attoseconds, ATTOSECONDS_PER_SECOND_SQRT, &attolo);
+
+ // scale the lower half, then split into high/low parts
+ UINT64 temp = mulu_32x32(attolo, factor);
+ UINT32 reslo;
+ temp = divu_64x32_rem(temp, ATTOSECONDS_PER_SECOND_SQRT, &reslo);
+
+ // scale the upper half, then split into high/low parts
+ temp += mulu_32x32(attohi, factor);
+ UINT32 reshi;
+ temp = divu_64x32_rem(temp, ATTOSECONDS_PER_SECOND_SQRT, &reshi);
+
+ // scale the seconds
+ temp += mulu_32x32(seconds, factor);
+ if (temp >= ATTOTIME_MAX_SECONDS)
+ return *this = never;
+
+ // build the result
+ seconds = temp;
+ attoseconds = (attoseconds_t)reslo + mul_32x32(reshi, ATTOSECONDS_PER_SECOND_SQRT);
+ return *this;
+}
+
+
+//-------------------------------------------------
+// operator/= - divide an attotime by a constant
+//-------------------------------------------------
+
+attotime &attotime::operator/=(UINT32 factor)
+{
+ // if one of the items is attotime::never, return attotime::never
+ if (seconds >= ATTOTIME_MAX_SECONDS)
+ return *this = never;
+
+ // ignore divide by zero
+ if (factor == 0)
+ return *this;
+
+ // split attoseconds into upper and lower halves which fit into 32 bits
+ UINT32 attolo;
+ UINT32 attohi = divu_64x32_rem(attoseconds, ATTOSECONDS_PER_SECOND_SQRT, &attolo);
+
+ // divide the seconds and get the remainder
+ UINT32 remainder;
+ seconds = divu_64x32_rem(seconds, factor, &remainder);
+
+ // combine the upper half of attoseconds with the remainder and divide that
+ UINT64 temp = (INT64)attohi + mulu_32x32(remainder, ATTOSECONDS_PER_SECOND_SQRT);
+ UINT32 reshi = divu_64x32_rem(temp, factor, &remainder);
+
+ // combine the lower half of attoseconds with the remainder and divide that
+ temp = attolo + mulu_32x32(remainder, ATTOSECONDS_PER_SECOND_SQRT);
+ UINT32 reslo = divu_64x32_rem(temp, factor, &remainder);
+
+ // round based on the remainder
+ attoseconds = (attoseconds_t)reslo + mulu_32x32(reshi, ATTOSECONDS_PER_SECOND_SQRT);
+ if (remainder >= factor / 2)
+ if (++attoseconds >= ATTOSECONDS_PER_SECOND)
+ {
+ attoseconds = 0;
+ seconds++;
+ }
+ return *this;
+}
+
+
+//-------------------------------------------------
+// as_string - return a temporary printable
+// string describing an attotime
+//-------------------------------------------------
+
+const char *attotime::as_string(int precision) const
+{
+ static char buffers[8][30];
+ static int nextbuf;
+ char *buffer = &buffers[nextbuf++ % 8][0];
+
+ // special case: never
+ if (*this == never)
+ sprintf(buffer, "%-*s", precision, "(never)");
+
+ // case 1: we want no precision; seconds only
+ else if (precision == 0)
+ sprintf(buffer, "%d", seconds);
+
+ // case 2: we want 9 or fewer digits of precision
+ else if (precision <= 9)
+ {
+ UINT32 upper = attoseconds / ATTOSECONDS_PER_SECOND_SQRT;
+ int temp = precision;
+ while (temp < 9)
+ {
+ upper /= 10;
+ temp++;
+ }
+ sprintf(buffer, "%d.%0*d", seconds, precision, upper);
+ }
+
+ // case 3: more than 9 digits of precision
+ else
+ {
+ UINT32 lower;
+ UINT32 upper = divu_64x32_rem(attoseconds, ATTOSECONDS_PER_SECOND_SQRT, &lower);
+ int temp = precision;
+ while (temp < 18)
+ {
+ lower /= 10;
+ temp++;
+ }
+ sprintf(buffer, "%d.%09d%0*d", seconds, upper, precision - 9, lower);
+ }
+ return buffer;
+}
diff --git a/trunk/src/emu/attotime.h b/trunk/src/emu/attotime.h
new file mode 100644
index 00000000000..eb9e1ee2915
--- /dev/null
+++ b/trunk/src/emu/attotime.h
@@ -0,0 +1,434 @@
+/***************************************************************************
+
+ attotime.h
+
+ Support functions for working with attotime data.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+****************************************************************************
+
+ Attotime is an attosecond-accurate timing system implemented as
+ 96-bit integers.
+
+ 1 second = 1e0 seconds
+ 1 millisecond = 1e-3 seconds
+ 1 microsecond = 1e-6 seconds
+ 1 nanosecond = 1e-9 seconds
+ 1 picosecond = 1e-12 seconds
+ 1 femtosecond = 1e-15 seconds
+ 1 attosecond = 1e-18 seconds
+
+ This may seem insanely accurate, but it has its uses when multiple
+ clocks in the system are run by independent crystals. It is also
+ useful to compute the attotime for something small, say 1 clock tick,
+ and still have it be accurate and useful for scaling.
+
+ Attotime consists of a 32-bit seconds count and a 64-bit attoseconds
+ count. Because the lower bits are kept as attoseconds and not as a
+ full 64-bit value, there is headroom to make some operations simpler.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __ATTOTIME_H__
+#define __ATTOTIME_H__
+
+#include <math.h>
+#undef min
+#undef max
+
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// core components of the attotime structure
+typedef INT64 attoseconds_t;
+typedef INT32 seconds_t;
+
+// core definitions
+const attoseconds_t ATTOSECONDS_PER_SECOND_SQRT = 1000000000;
+const attoseconds_t ATTOSECONDS_PER_SECOND = ATTOSECONDS_PER_SECOND_SQRT * ATTOSECONDS_PER_SECOND_SQRT;
+const attoseconds_t ATTOSECONDS_PER_MILLISECOND = ATTOSECONDS_PER_SECOND / 1000;
+const attoseconds_t ATTOSECONDS_PER_MICROSECOND = ATTOSECONDS_PER_SECOND / 1000000;
+const attoseconds_t ATTOSECONDS_PER_NANOSECOND = ATTOSECONDS_PER_SECOND / 1000000000;
+
+const seconds_t ATTOTIME_MAX_SECONDS = 1000000000;
+
+
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+// convert between a double and attoseconds
+#define ATTOSECONDS_TO_DOUBLE(x) ((double)(x) * 1e-18)
+#define DOUBLE_TO_ATTOSECONDS(x) ((attoseconds_t)((x) * 1e18))
+
+// convert between hertz (as a double) and attoseconds
+#define ATTOSECONDS_TO_HZ(x) ((double)ATTOSECONDS_PER_SECOND / (double)(x))
+#define HZ_TO_ATTOSECONDS(x) ((attoseconds_t)(ATTOSECONDS_PER_SECOND / (x)))
+
+// macros for converting other seconds types to attoseconds
+#define ATTOSECONDS_IN_SEC(x) ((attoseconds_t)(x) * ATTOSECONDS_PER_SECOND)
+#define ATTOSECONDS_IN_MSEC(x) ((attoseconds_t)(x) * ATTOSECONDS_PER_MILLISECOND)
+#define ATTOSECONDS_IN_USEC(x) ((attoseconds_t)(x) * ATTOSECONDS_PER_MICROSECOND)
+#define ATTOSECONDS_IN_NSEC(x) ((attoseconds_t)(x) * ATTOSECONDS_PER_NANOSECOND)
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//***************************************************************************/
+
+// the attotime structure itself
+class attotime
+{
+public:
+ // construction/destruction
+ attotime()
+ : seconds(0),
+ attoseconds(0) { }
+
+ attotime(seconds_t secs, attoseconds_t attos)
+ : seconds(secs),
+ attoseconds(attos) { }
+
+ // queries
+ bool is_zero() const { return (seconds == 0 && attoseconds == 0); }
+ bool is_never() const { return (seconds >= ATTOTIME_MAX_SECONDS); }
+
+ // conversion to other forms
+ double as_double() const { return double(seconds) + ATTOSECONDS_TO_DOUBLE(attoseconds); }
+ attoseconds_t as_attoseconds() const;
+ UINT64 as_ticks(UINT32 frequency) const;
+ const char *as_string(int precision = 9) const;
+
+ // conversion from other forms
+ static attotime from_double(double _time);
+ static attotime from_ticks(UINT64 ticks, UINT32 frequency);
+ static attotime from_seconds(INT32 seconds) { return attotime(seconds, 0); }
+ static attotime from_msec(INT64 msec) { return attotime(msec / 1000, (msec % 1000) * (ATTOSECONDS_PER_SECOND / 1000)); }
+ static attotime from_usec(INT64 usec) { return attotime(usec / 1000000, (usec % 1000000) * (ATTOSECONDS_PER_SECOND / 1000000)); }
+ static attotime from_nsec(INT64 nsec) { return attotime(nsec / 1000000000, (nsec % 1000000000) * (ATTOSECONDS_PER_SECOND / 1000000000)); }
+ static attotime from_hz(double frequency) { return attotime(0, double(ATTOSECONDS_PER_SECOND) / frequency); }
+
+ // math
+ attotime &operator+=(const attotime &right);
+ attotime &operator-=(const attotime &right);
+ attotime &operator*=(UINT32 factor);
+ attotime &operator/=(UINT32 factor);
+
+ // members
+ seconds_t seconds;
+ attoseconds_t attoseconds;
+
+ // constants
+ static const attotime never;
+ static const attotime zero;
+};
+
+
+
+//**************************************************************************
+// INLINE FUNCTIONS
+//**************************************************************************
+
+//-------------------------------------------------
+// operator+ - handle addition between two
+// attotimes
+//-------------------------------------------------
+
+inline attotime operator+(const attotime &left, const attotime &right)
+{
+ attotime result;
+
+ // if one of the items is never, return never
+ if (left.seconds >= ATTOTIME_MAX_SECONDS || right.seconds >= ATTOTIME_MAX_SECONDS)
+ return attotime::never;
+
+ // add the seconds and attoseconds
+ result.attoseconds = left.attoseconds + right.attoseconds;
+ result.seconds = left.seconds + right.seconds;
+
+ // normalize and return
+ if (result.attoseconds >= ATTOSECONDS_PER_SECOND)
+ {
+ result.attoseconds -= ATTOSECONDS_PER_SECOND;
+ result.seconds++;
+ }
+
+ // overflow
+ if (result.seconds >= ATTOTIME_MAX_SECONDS)
+ return attotime::never;
+ return result;
+}
+
+inline attotime &attotime::operator+=(const attotime &right)
+{
+ // if one of the items is never, return never
+ if (this->seconds >= ATTOTIME_MAX_SECONDS || right.seconds >= ATTOTIME_MAX_SECONDS)
+ return *this = never;
+
+ // add the seconds and attoseconds
+ attoseconds += right.attoseconds;
+ seconds += right.seconds;
+
+ // normalize and return
+ if (this->attoseconds >= ATTOSECONDS_PER_SECOND)
+ {
+ this->attoseconds -= ATTOSECONDS_PER_SECOND;
+ this->seconds++;
+ }
+
+ // overflow
+ if (this->seconds >= ATTOTIME_MAX_SECONDS)
+ return *this = never;
+ return *this;
+}
+
+
+//-------------------------------------------------
+// operator- - handle subtraction between two
+// attotimes
+//-------------------------------------------------
+
+inline attotime operator-(const attotime &left, const attotime &right)
+{
+ attotime result;
+
+ // if time1 is never, return never
+ if (left.seconds >= ATTOTIME_MAX_SECONDS)
+ return attotime::never;
+
+ // add the seconds and attoseconds
+ result.attoseconds = left.attoseconds - right.attoseconds;
+ result.seconds = left.seconds - right.seconds;
+
+ // normalize and return
+ if (result.attoseconds < 0)
+ {
+ result.attoseconds += ATTOSECONDS_PER_SECOND;
+ result.seconds--;
+ }
+ return result;
+}
+
+inline attotime &attotime::operator-=(const attotime &right)
+{
+ // if time1 is never, return never
+ if (this->seconds >= ATTOTIME_MAX_SECONDS)
+ return *this = never;
+
+ // add the seconds and attoseconds
+ attoseconds -= right.attoseconds;
+ seconds -= right.seconds;
+
+ // normalize and return
+ if (this->attoseconds < 0)
+ {
+ this->attoseconds += ATTOSECONDS_PER_SECOND;
+ this->seconds--;
+ }
+ return *this;
+}
+
+
+//-------------------------------------------------
+// operator* - handle multiplication/division by
+// an integral factor; defined in terms of the
+// assignment operators
+//-------------------------------------------------
+
+inline attotime operator*(const attotime &left, UINT32 factor)
+{
+ attotime result = left;
+ result *= factor;
+ return result;
+}
+
+inline attotime operator*(UINT32 factor, const attotime &right)
+{
+ attotime result = right;
+ result *= factor;
+ return result;
+}
+
+inline attotime operator/(const attotime &left, UINT32 factor)
+{
+ attotime result = left;
+ result /= factor;
+ return result;
+}
+
+
+//-------------------------------------------------
+// operator== - handle comparisons between
+// attotimes
+//-------------------------------------------------
+
+inline bool operator==(const attotime &left, const attotime &right)
+{
+ return (left.seconds == right.seconds && left.attoseconds == right.attoseconds);
+}
+
+inline bool operator!=(const attotime &left, const attotime &right)
+{
+ return (left.seconds != right.seconds || left.attoseconds != right.attoseconds);
+}
+
+inline bool operator<(const attotime &left, const attotime &right)
+{
+ return (left.seconds < right.seconds || (left.seconds == right.seconds && left.attoseconds < right.attoseconds));
+}
+
+inline bool operator<=(const attotime &left, const attotime &right)
+{
+ return (left.seconds < right.seconds || (left.seconds == right.seconds && left.attoseconds <= right.attoseconds));
+}
+
+inline bool operator>(const attotime &left, const attotime &right)
+{
+ return (left.seconds > right.seconds || (left.seconds == right.seconds && left.attoseconds > right.attoseconds));
+}
+
+inline bool operator>=(const attotime &left, const attotime &right)
+{
+ return (left.seconds > right.seconds || (left.seconds == right.seconds && left.attoseconds >= right.attoseconds));
+}
+
+
+//-------------------------------------------------
+// min - return the minimum of two attotimes
+//-------------------------------------------------
+
+inline attotime min(const attotime &left, const attotime &right)
+{
+ if (left.seconds > right.seconds)
+ return right;
+ if (left.seconds < right.seconds)
+ return left;
+ if (left.attoseconds > right.attoseconds)
+ return right;
+ return left;
+}
+
+
+//-------------------------------------------------
+// max - return the maximum of two attotimes
+//-------------------------------------------------
+
+inline attotime max(const attotime &left, const attotime &right)
+{
+ if (left.seconds > right.seconds)
+ return left;
+ if (left.seconds < right.seconds)
+ return right;
+ if (left.attoseconds > right.attoseconds)
+ return left;
+ return right;
+}
+
+
+//-------------------------------------------------
+// as_attoseconds - convert to an attoseconds
+// value, clamping to +/- 1 second
+//-------------------------------------------------
+
+inline attoseconds_t attotime::as_attoseconds() const
+{
+ // positive values between 0 and 1 second
+ if (seconds == 0)
+ return attoseconds;
+
+ // negative values between -1 and 0 seconds
+ else if (seconds == -1)
+ return attoseconds - ATTOSECONDS_PER_SECOND;
+
+ // out-of-range positive values
+ else if (seconds > 0)
+ return ATTOSECONDS_PER_SECOND;
+
+ // out-of-range negative values
+ else
+ return -ATTOSECONDS_PER_SECOND;
+}
+
+
+//-------------------------------------------------
+// as_ticks - convert to ticks at the given
+// frequency
+//-------------------------------------------------
+
+inline UINT64 attotime::as_ticks(UINT32 frequency) const
+{
+ UINT32 fracticks = (attotime(0, attoseconds) * frequency).seconds;
+ return mulu_32x32(seconds, frequency) + fracticks;
+}
+
+
+//-------------------------------------------------
+// from_ticks - create an attotime from a tick
+// count at the given frequency
+//-------------------------------------------------
+
+inline attotime attotime::from_ticks(UINT64 ticks, UINT32 frequency)
+{
+ attoseconds_t attos_per_tick = HZ_TO_ATTOSECONDS(frequency);
+
+ if (ticks < frequency)
+ return attotime(0, ticks * attos_per_tick);
+
+ UINT32 remainder;
+ INT32 secs = divu_64x32_rem(ticks, frequency, &remainder);
+ return attotime(secs, (UINT64)remainder * attos_per_tick);
+}
+
+
+//-------------------------------------------------
+// from_double - create an attotime from floating
+// point count of seconds
+//-------------------------------------------------
+
+inline attotime attotime::from_double(double _time)
+{
+ seconds_t secs = floor(_time);
+ _time -= double(secs);
+ attoseconds_t attos = DOUBLE_TO_ATTOSECONDS(_time);
+ return attotime(secs, attos);
+}
+
+
+#endif // __ATTOTIME_H__
diff --git a/trunk/src/emu/audio/generic.c b/trunk/src/emu/audio/generic.c
new file mode 100644
index 00000000000..a40474d9da2
--- /dev/null
+++ b/trunk/src/emu/audio/generic.c
@@ -0,0 +1,168 @@
+/***************************************************************************
+
+ generic.c
+
+ Generic simple sound functions.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#include "emu.h"
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+struct _generic_audio_private
+{
+ UINT16 latch_clear_value;
+ UINT16 latched_value[4];
+ UINT8 latch_read[4];
+};
+
+
+
+/***************************************************************************
+ INITIALIZATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ generic_sound_init - initialize globals and
+ register for save states
+-------------------------------------------------*/
+
+int generic_sound_init(running_machine &machine)
+{
+ generic_audio_private *state;
+
+ state = machine.generic_audio_data = auto_alloc_clear(machine, generic_audio_private);
+
+ /* register globals with the save state system */
+ state_save_register_global_array(machine, state->latched_value);
+ state_save_register_global_array(machine, state->latch_read);
+
+ return 0;
+}
+
+
+
+/***************************************************************************
+
+ Many games use a master-slave CPU setup. Typically, the main CPU writes
+ a command to some register, and then writes to another register to trigger
+ an interrupt on the slave CPU (the interrupt might also be triggered by
+ the first write). The slave CPU, notified by the interrupt, goes and reads
+ the command.
+
+***************************************************************************/
+
+/*-------------------------------------------------
+ latch_callback - time-delayed callback to
+ set a latch value
+-------------------------------------------------*/
+
+static TIMER_CALLBACK( latch_callback )
+{
+ generic_audio_private *state = machine.generic_audio_data;
+ UINT16 value = param >> 8;
+ int which = param & 0xff;
+
+ /* if the latch hasn't been read and the value is changed, log a warning */
+ if (!state->latch_read[which] && state->latched_value[which] != value)
+ logerror("Warning: sound latch %d written before being read. Previous: %02x, new: %02x\n", which, state->latched_value[which], value);
+
+ /* store the new value and mark it not read */
+ state->latched_value[which] = value;
+ state->latch_read[which] = 0;
+}
+
+
+/*-------------------------------------------------
+ latch_w - handle a write to a given latch
+-------------------------------------------------*/
+
+INLINE void latch_w(address_space *space, int which, UINT16 value)
+{
+ space->machine().scheduler().synchronize(FUNC(latch_callback), which | (value << 8));
+}
+
+
+/*-------------------------------------------------
+ latch_r - handle a read from a given latch
+-------------------------------------------------*/
+
+INLINE UINT16 latch_r(address_space *space, int which)
+{
+ generic_audio_private *state = space->machine().generic_audio_data;
+ state->latch_read[which] = 1;
+ return state->latched_value[which];
+}
+
+
+/*-------------------------------------------------
+ latch_clear - clear a given latch
+-------------------------------------------------*/
+
+INLINE void latch_clear(address_space *space, int which)
+{
+ generic_audio_private *state = space->machine().generic_audio_data;
+ state->latched_value[which] = state->latch_clear_value;
+}
+
+
+/*-------------------------------------------------
+ soundlatch_w - global write handlers for
+ writing to sound latches
+-------------------------------------------------*/
+
+WRITE8_HANDLER( soundlatch_w ) { latch_w(space, 0, data); }
+WRITE16_HANDLER( soundlatch_word_w ) { latch_w(space, 0, data); }
+WRITE8_HANDLER( soundlatch2_w ) { latch_w(space, 1, data); }
+WRITE16_HANDLER( soundlatch2_word_w ) { latch_w(space, 1, data); }
+WRITE8_HANDLER( soundlatch3_w ) { latch_w(space, 2, data); }
+WRITE16_HANDLER( soundlatch3_word_w ) { latch_w(space, 2, data); }
+WRITE8_HANDLER( soundlatch4_w ) { latch_w(space, 3, data); }
+WRITE16_HANDLER( soundlatch4_word_w ) { latch_w(space, 3, data); }
+
+
+/*-------------------------------------------------
+ soundlatch_r - global read handlers for
+ reading from sound latches
+-------------------------------------------------*/
+
+READ8_HANDLER( soundlatch_r ) { return latch_r(space, 0); }
+READ16_HANDLER( soundlatch_word_r ) { return latch_r(space, 0); }
+READ8_HANDLER( soundlatch2_r ) { return latch_r(space, 1); }
+READ16_HANDLER( soundlatch2_word_r ) { return latch_r(space, 1); }
+READ8_HANDLER( soundlatch3_r ) { return latch_r(space, 2); }
+READ16_HANDLER( soundlatch3_word_r ) { return latch_r(space, 2); }
+READ8_HANDLER( soundlatch4_r ) { return latch_r(space, 3); }
+READ16_HANDLER( soundlatch4_word_r ) { return latch_r(space, 3); }
+
+
+/*-------------------------------------------------
+ soundlatch_clear_w - global write handlers
+ for clearing sound latches
+-------------------------------------------------*/
+
+WRITE8_HANDLER( soundlatch_clear_w ) { latch_clear(space, 0); }
+WRITE8_HANDLER( soundlatch2_clear_w ) { latch_clear(space, 1); }
+WRITE8_HANDLER( soundlatch3_clear_w ) { latch_clear(space, 2); }
+WRITE8_HANDLER( soundlatch4_clear_w ) { latch_clear(space, 3); }
+
+
+/*-------------------------------------------------
+ soundlatch_setclearedvalue - set the "clear"
+ value for all sound latches
+-------------------------------------------------*/
+
+void soundlatch_setclearedvalue(running_machine &machine, int value)
+{
+ generic_audio_private *state = machine.generic_audio_data;
+ assert_always(machine.phase() == MACHINE_PHASE_INIT, "Can only call soundlatch_setclearedvalue at init time!");
+ state->latch_clear_value = value;
+}
diff --git a/trunk/src/emu/audio/generic.h b/trunk/src/emu/audio/generic.h
new file mode 100644
index 00000000000..d693e723d40
--- /dev/null
+++ b/trunk/src/emu/audio/generic.h
@@ -0,0 +1,59 @@
+/***************************************************************************
+
+ generic.h
+
+ Generic simple sound functions.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __SOUND_GENERIC_H__
+#define __SOUND_GENERIC_H__
+
+
+
+/***************************************************************************
+
+ Function prototypes
+
+***************************************************************************/
+
+int generic_sound_init(running_machine &machine);
+
+/* latch readers */
+READ8_HANDLER( soundlatch_r );
+READ8_HANDLER( soundlatch2_r );
+READ8_HANDLER( soundlatch3_r );
+READ8_HANDLER( soundlatch4_r );
+READ16_HANDLER( soundlatch_word_r );
+READ16_HANDLER( soundlatch2_word_r );
+READ16_HANDLER( soundlatch3_word_r );
+READ16_HANDLER( soundlatch4_word_r );
+
+/* latch writers */
+WRITE8_HANDLER( soundlatch_w );
+WRITE8_HANDLER( soundlatch2_w );
+WRITE8_HANDLER( soundlatch3_w );
+WRITE8_HANDLER( soundlatch4_w );
+WRITE16_HANDLER( soundlatch_word_w );
+WRITE16_HANDLER( soundlatch2_word_w );
+WRITE16_HANDLER( soundlatch3_word_w );
+WRITE16_HANDLER( soundlatch4_word_w );
+
+/* latch clearers */
+WRITE8_HANDLER( soundlatch_clear_w );
+WRITE8_HANDLER( soundlatch2_clear_w );
+WRITE8_HANDLER( soundlatch3_clear_w );
+WRITE8_HANDLER( soundlatch4_clear_w );
+
+/* If you're going to use soundlatchX_clear_w, and the cleared value is
+ something other than 0x00, use this function from machine_init. Note
+ that this one call effects all 4 latches */
+void soundlatch_setclearedvalue(running_machine &machine, int value);
+
+
+#endif /* __SOUND_GENERIC_H__ */
diff --git a/trunk/src/emu/audit.c b/trunk/src/emu/audit.c
new file mode 100644
index 00000000000..03318ac0ce0
--- /dev/null
+++ b/trunk/src/emu/audit.c
@@ -0,0 +1,551 @@
+/***************************************************************************
+
+ audit.c
+
+ ROM set auditing functions.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "emuopts.h"
+#include "hash.h"
+#include "audit.h"
+#include "harddisk.h"
+#include "sound/samples.h"
+
+
+//**************************************************************************
+// CORE FUNCTIONS
+//**************************************************************************
+
+//-------------------------------------------------
+// media_auditor - constructor
+//-------------------------------------------------
+
+media_auditor::media_auditor(const driver_enumerator &enumerator)
+ : m_enumerator(enumerator),
+ m_validation(AUDIT_VALIDATE_FULL),
+ m_searchpath(NULL)
+{
+}
+
+
+//-------------------------------------------------
+// audit_media - audit the media described by the
+// currently-enumerated driver
+//-------------------------------------------------
+
+media_auditor::summary media_auditor::audit_media(const char *validation)
+{
+ // start fresh
+ m_record_list.reset();
+
+ // store validation for later
+ m_validation = validation;
+
+// temporary hack until romload is update: get the driver path and support it for
+// all searches
+const char *driverpath = m_enumerator.config().devicelist().find("root")->searchpath();
+
+ // iterate over ROM sources and regions
+ int found = 0;
+ int required = 0;
+ int sharedFound = 0;
+ int sharedRequired = 0;
+
+ for (const rom_source *source = rom_first_source(m_enumerator.config()); source != NULL; source = rom_next_source(*source))
+ {
+ // determine the search path for this source and iterate through the regions
+ m_searchpath = source->searchpath();
+
+ // now iterate over regions and ROMs within
+ for (const rom_entry *region = rom_first_region(*source); region != NULL; region = rom_next_region(region))
+ {
+// temporary hack: add the driver path & region name
+astring combinedpath(source->searchpath(), ";", driverpath);
+if(source->shortname())
+{
+ combinedpath=combinedpath.cat(";");
+ combinedpath=combinedpath.cat(source->shortname());
+}
+m_searchpath = combinedpath;
+
+ for (const rom_entry *rom = rom_first_file(region); rom; rom = rom_next_file(rom))
+ {
+ hash_collection hashes(ROM_GETHASHDATA(rom));
+ const rom_source *shared_source = find_shared_source(source, hashes, ROM_GETLENGTH(rom));
+
+ // count the number of files with hashes
+ if (!hashes.flag(hash_collection::FLAG_NO_DUMP) && !ROM_ISOPTIONAL(rom))
+ {
+ required++;
+ if (shared_source != NULL)
+ {
+ sharedRequired++;
+ }
+ }
+
+ // audit a file
+ audit_record *record = NULL;
+ if (ROMREGION_ISROMDATA(region))
+ record = audit_one_rom(rom);
+
+ // audit a disk
+ else if (ROMREGION_ISDISKDATA(region))
+ record = audit_one_disk(rom);
+
+ if (record != NULL)
+ {
+ // count the number of files that are found.
+ if (record->status() == audit_record::STATUS_GOOD || (record->status() == audit_record::STATUS_FOUND_INVALID && find_shared_source(source,record->actual_hashes(), record->actual_length()) != NULL))
+ {
+ found++;
+ if (shared_source != NULL)
+ {
+ sharedFound++;
+ }
+ }
+
+ record->set_shared_source(shared_source);
+ }
+ }
+ }
+ }
+
+ // if we only find files that are in the parent & either the set has no unique files or the parent is not found, then assume we don't have the set at all
+ if (found == sharedFound && required > 0 && (required != sharedRequired || sharedFound == 0))
+ {
+ m_record_list.reset();
+ return NOTFOUND;
+ }
+
+ // return a summary
+ return summarize(m_enumerator.driver().name);
+}
+
+
+//-------------------------------------------------
+// audit_device - audit the device
+//-------------------------------------------------
+
+media_auditor::summary media_auditor::audit_device(device_t *device, const char *validation)
+{
+ // start fresh
+ m_record_list.reset();
+
+ // store validation for later
+ m_validation = validation;
+ m_searchpath = device->shortname();
+
+ int found = 0;
+ int required = 0;
+
+ // now iterate over regions and ROMs within
+ for (const rom_entry *region = rom_first_region(*device); region != NULL; region = rom_next_region(region))
+ {
+ for (const rom_entry *rom = rom_first_file(region); rom; rom = rom_next_file(rom))
+ {
+ hash_collection hashes(ROM_GETHASHDATA(rom));
+
+ // count the number of files with hashes
+ if (!hashes.flag(hash_collection::FLAG_NO_DUMP) && !ROM_ISOPTIONAL(rom))
+ {
+ required++;
+ }
+
+ // audit a file
+ audit_record *record = NULL;
+ if (ROMREGION_ISROMDATA(region))
+ record = audit_one_rom(rom);
+
+ // audit a disk
+ else if (ROMREGION_ISDISKDATA(region))
+ record = audit_one_disk(rom);
+
+ // count the number of files that are found.
+ if (record != NULL && (record->status() == audit_record::STATUS_GOOD || record->status() == audit_record::STATUS_FOUND_INVALID))
+ {
+ found++;
+ }
+ }
+ }
+
+ if (found == 0 && required > 0)
+ {
+ m_record_list.reset();
+ return NOTFOUND;
+ }
+
+ // return a summary
+ return summarize(device->shortname());
+}
+
+
+//-------------------------------------------------
+// audit_samples - validate the samples for the
+// currently-enumerated driver
+//-------------------------------------------------
+
+media_auditor::summary media_auditor::audit_samples()
+{
+ // start fresh
+ m_record_list.reset();
+
+ // iterate over sample entries
+ for (const device_t *device = m_enumerator.config().first_device(); device != NULL; device = device->next())
+ if (device->type() == SAMPLES)
+ {
+ const samples_interface *intf = reinterpret_cast<const samples_interface *>(device->static_config());
+ if (intf->samplenames != NULL)
+ {
+ // by default we just search using the driver name
+ astring searchpath(m_enumerator.driver().name);
+
+ // iterate over samples in this entry
+ for (int sampnum = 0; intf->samplenames[sampnum] != NULL; sampnum++)
+ {
+ // starred entries indicate an additional searchpath
+ if (intf->samplenames[sampnum][0] == '*')
+ {
+ searchpath.cat(";").cat(&intf->samplenames[sampnum][1]);
+ continue;
+ }
+
+ // create a new record
+ audit_record &record = m_record_list.append(*global_alloc(audit_record(intf->samplenames[sampnum], audit_record::MEDIA_SAMPLE)));
+
+ // look for the files
+ emu_file file(m_enumerator.options().sample_path(), OPEN_FLAG_READ | OPEN_FLAG_NO_PRELOAD);
+ path_iterator path(searchpath);
+ astring curpath;
+ while (path.next(curpath, intf->samplenames[sampnum]))
+ {
+ // attempt to access the file
+ file_error filerr = file.open(curpath);
+ if (filerr == FILERR_NONE)
+ record.set_status(audit_record::STATUS_GOOD, audit_record::SUBSTATUS_GOOD);
+ else
+ record.set_status(audit_record::STATUS_NOT_FOUND, audit_record::SUBSTATUS_NOT_FOUND);
+ }
+ }
+ }
+ }
+
+ // no count AND no records means not found
+ if (m_record_list.count() == 0)
+ return NOTFOUND;
+
+ // return a summary
+ return summarize(m_enumerator.driver().name);
+}
+
+
+//-------------------------------------------------
+// summary - generate a summary, with an optional
+// string format
+//-------------------------------------------------
+
+media_auditor::summary media_auditor::summarize(const char *name, astring *string)
+{
+ // loop over records
+ summary overall_status = CORRECT;
+ for (audit_record *record = m_record_list.first(); record != NULL; record = record->next())
+ {
+ summary best_new_status = INCORRECT;
+
+ // skip anything that's fine
+ if (record->substatus() == audit_record::SUBSTATUS_GOOD)
+ continue;
+
+ // output the game name, file name, and length (if applicable)
+ if (string != NULL)
+ {
+ string->catprintf("%-12s: %s", name, record->name());
+ if (record->expected_length() > 0)
+ string->catprintf(" (%d bytes)", record->expected_length());
+ string->catprintf(" - ");
+ }
+
+ // use the substatus for finer details
+ switch (record->substatus())
+ {
+ case audit_record::SUBSTATUS_GOOD_NEEDS_REDUMP:
+ if (string != NULL) string->catprintf("NEEDS REDUMP\n");
+ best_new_status = BEST_AVAILABLE;
+ break;
+
+ case audit_record::SUBSTATUS_FOUND_NODUMP:
+ if (string != NULL) string->catprintf("NO GOOD DUMP KNOWN\n");
+ best_new_status = BEST_AVAILABLE;
+ break;
+
+ case audit_record::SUBSTATUS_FOUND_BAD_CHECKSUM:
+ if (string != NULL)
+ {
+ astring tempstr;
+ string->catprintf("INCORRECT CHECKSUM:\n");
+ string->catprintf("EXPECTED: %s\n", record->expected_hashes().macro_string(tempstr));
+ string->catprintf(" FOUND: %s\n", record->actual_hashes().macro_string(tempstr));
+ }
+ break;
+
+ case audit_record::SUBSTATUS_FOUND_WRONG_LENGTH:
+ if (string != NULL) string->catprintf("INCORRECT LENGTH: %d bytes\n", record->actual_length());
+ break;
+
+ case audit_record::SUBSTATUS_NOT_FOUND:
+ if (string != NULL)
+ {
+ const rom_source *shared_source = record->shared_source();
+ if (shared_source == NULL) string->catprintf("NOT FOUND\n");
+ else string->catprintf("NOT FOUND (%s)\n", shared_source->shortname());
+ }
+ break;
+
+ case audit_record::SUBSTATUS_NOT_FOUND_NODUMP:
+ if (string != NULL) string->catprintf("NOT FOUND - NO GOOD DUMP KNOWN\n");
+ best_new_status = BEST_AVAILABLE;
+ break;
+
+ case audit_record::SUBSTATUS_NOT_FOUND_OPTIONAL:
+ if (string != NULL) string->catprintf("NOT FOUND BUT OPTIONAL\n");
+ best_new_status = BEST_AVAILABLE;
+ break;
+
+ default:
+ assert(false);
+ }
+
+ // downgrade the overall status if necessary
+ overall_status = MAX(overall_status, best_new_status);
+ }
+ return overall_status;
+}
+
+
+//-------------------------------------------------
+// audit_one_rom - validate a single ROM entry
+//-------------------------------------------------
+
+audit_record *media_auditor::audit_one_rom(const rom_entry *rom)
+{
+ // allocate and append a new record
+ audit_record &record = m_record_list.append(*global_alloc(audit_record(*rom, audit_record::MEDIA_ROM)));
+
+ // see if we have a CRC and extract it if so
+ UINT32 crc = 0;
+ bool has_crc = record.expected_hashes().crc(crc);
+
+ // find the file and checksum it, getting the file length along the way
+ emu_file file(m_enumerator.options().media_path(), OPEN_FLAG_READ | OPEN_FLAG_NO_PRELOAD);
+ path_iterator path(m_searchpath);
+ astring curpath;
+ while (path.next(curpath, record.name()))
+ {
+ // open the file if we can
+ file_error filerr;
+ if (has_crc)
+ filerr = file.open(curpath, crc);
+ else
+ filerr = file.open(curpath);
+
+ // if it worked, get the actual length and hashes, then stop
+ if (filerr == FILERR_NONE)
+ {
+ record.set_actual(file.hashes(m_validation), file.size());
+ break;
+ }
+ }
+
+ // compute the final status
+ compute_status(record, rom, record.actual_length() != 0);
+ return &record;
+}
+
+
+//-------------------------------------------------
+// audit_one_disk - validate a single disk entry
+//-------------------------------------------------
+
+audit_record *media_auditor::audit_one_disk(const rom_entry *rom)
+{
+ // allocate and append a new record
+ audit_record &record = m_record_list.append(*global_alloc(audit_record(*rom, audit_record::MEDIA_DISK)));
+
+ // open the disk
+ emu_file *source_file;
+ chd_file *source;
+ chd_error err = open_disk_image(m_enumerator.options(), &m_enumerator.driver(), rom, &source_file, &source, NULL);
+
+ // if we succeeded, get the hashes
+ if (err == CHDERR_NONE)
+ {
+ static const UINT8 nullhash[20] = { 0 };
+ chd_header header = *chd_get_header(source);
+ hash_collection hashes;
+
+ // if there's a SHA1 hash, add them to the output hash
+ if (memcmp(nullhash, header.sha1, sizeof(header.sha1)) != 0)
+ hashes.add_from_buffer(hash_collection::HASH_SHA1, header.sha1, sizeof(header.sha1));
+
+ // update the actual values
+ record.set_actual(hashes);
+
+ // close the file and release the source
+ chd_close(source);
+ global_free(source_file);
+ }
+
+ // compute the final status
+ compute_status(record, rom, err == CHDERR_NONE);
+ return &record;
+}
+
+
+//-------------------------------------------------
+// compute_status - compute a detailed status
+// based on the information we have
+//-------------------------------------------------
+
+void media_auditor::compute_status(audit_record &record, const rom_entry *rom, bool found)
+{
+ // if not found, provide more details
+ if (!found)
+ {
+ // no good dump
+ if (record.expected_hashes().flag(hash_collection::FLAG_NO_DUMP))
+ record.set_status(audit_record::STATUS_NOT_FOUND, audit_record::SUBSTATUS_NOT_FOUND_NODUMP);
+
+ // optional ROM
+ else if (ROM_ISOPTIONAL(rom))
+ record.set_status(audit_record::STATUS_NOT_FOUND, audit_record::SUBSTATUS_NOT_FOUND_OPTIONAL);
+
+ // just plain old not found
+ else
+ record.set_status(audit_record::STATUS_NOT_FOUND, audit_record::SUBSTATUS_NOT_FOUND);
+ }
+
+ // if found, provide more details
+ else
+ {
+ // length mismatch
+ if (record.expected_length() != record.actual_length())
+ record.set_status(audit_record::STATUS_FOUND_INVALID, audit_record::SUBSTATUS_FOUND_WRONG_LENGTH);
+
+ // found but needs a dump
+ else if (record.expected_hashes().flag(hash_collection::FLAG_NO_DUMP))
+ record.set_status(audit_record::STATUS_GOOD, audit_record::SUBSTATUS_FOUND_NODUMP);
+
+ // incorrect hash
+ else if (record.expected_hashes() != record.actual_hashes())
+ record.set_status(audit_record::STATUS_FOUND_INVALID, audit_record::SUBSTATUS_FOUND_BAD_CHECKSUM);
+
+ // correct hash but needs a redump
+ else if (record.expected_hashes().flag(hash_collection::FLAG_BAD_DUMP))
+ record.set_status(audit_record::STATUS_GOOD, audit_record::SUBSTATUS_GOOD_NEEDS_REDUMP);
+
+ // just plain old good
+ else
+ record.set_status(audit_record::STATUS_GOOD, audit_record::SUBSTATUS_GOOD);
+ }
+}
+
+
+//-------------------------------------------------
+// find_shared_source - return the source that
+// shares a media entry with the same hashes
+//-------------------------------------------------
+const rom_source *media_auditor::find_shared_source(const rom_source *source, const hash_collection &romhashes, UINT64 romlength)
+{
+ const rom_source *highest_source = NULL;
+
+ if (!romhashes.flag(hash_collection::FLAG_NO_DUMP))
+ {
+ if (dynamic_cast<const driver_device *>(source) == NULL)
+ {
+ for (const rom_entry *region = rom_first_region(*source); region; region = rom_next_region(region))
+ for (const rom_entry *rom = rom_first_file(region); rom; rom = rom_next_file(rom))
+ if (ROM_GETLENGTH(rom) == romlength)
+ {
+ hash_collection hashes(ROM_GETHASHDATA(rom));
+ if (hashes == romhashes)
+ highest_source = source;
+ }
+ }
+ else
+ {
+ // iterate up the parent chain
+ for (int drvindex = m_enumerator.find(m_enumerator.driver().parent); drvindex != -1; drvindex = m_enumerator.find(m_enumerator.driver(drvindex).parent))
+ for (const rom_source *source = rom_first_source(m_enumerator.config(drvindex)); source != NULL; source = rom_next_source(*source))
+ for (const rom_entry *region = rom_first_region(*source); region; region = rom_next_region(region))
+ for (const rom_entry *rom = rom_first_file(region); rom; rom = rom_next_file(rom))
+ if (ROM_GETLENGTH(rom) == romlength)
+ {
+ hash_collection hashes(ROM_GETHASHDATA(rom));
+ if (hashes == romhashes)
+ highest_source = source;
+ }
+ }
+ }
+
+ return highest_source;
+}
+
+
+//-------------------------------------------------
+// audit_record - constructor
+//-------------------------------------------------
+
+audit_record::audit_record(const rom_entry &media, media_type type)
+ : m_next(NULL),
+ m_type(type),
+ m_status(STATUS_ERROR),
+ m_substatus(SUBSTATUS_ERROR),
+ m_name(ROM_GETNAME(&media)),
+ m_explength(rom_file_size(&media)),
+ m_length(0)
+{
+ m_exphashes.from_internal_string(ROM_GETHASHDATA(&media));
+}
+
+audit_record::audit_record(const char *name, media_type type)
+ : m_next(NULL),
+ m_type(type),
+ m_status(STATUS_ERROR),
+ m_substatus(SUBSTATUS_ERROR),
+ m_name(name),
+ m_explength(0),
+ m_length(0)
+{
+}
diff --git a/trunk/src/emu/audit.h b/trunk/src/emu/audit.h
new file mode 100644
index 00000000000..44190f19557
--- /dev/null
+++ b/trunk/src/emu/audit.h
@@ -0,0 +1,196 @@
+/***************************************************************************
+
+ audit.h
+
+ ROM, disk, and sample auditing functions.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __AUDIT_H__
+#define __AUDIT_H__
+
+#include "hash.h"
+
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// hashes to use for validation
+#define AUDIT_VALIDATE_FAST "R" /* CRC only */
+#define AUDIT_VALIDATE_FULL "RS" /* CRC + SHA1 */
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+
+// ======================> audit_record
+
+// holds the result of auditing a single item
+class audit_record
+{
+ friend class simple_list<audit_record>;
+
+public:
+ // media types
+ enum media_type
+ {
+ MEDIA_ROM = 0,
+ MEDIA_DISK,
+ MEDIA_SAMPLE
+ };
+
+ // status values
+ enum audit_status
+ {
+ STATUS_GOOD = 0,
+ STATUS_FOUND_INVALID,
+ STATUS_NOT_FOUND,
+ STATUS_ERROR
+ };
+
+ // substatus values
+ enum audit_substatus
+ {
+ SUBSTATUS_GOOD = 0,
+ SUBSTATUS_GOOD_NEEDS_REDUMP,
+ SUBSTATUS_FOUND_NODUMP,
+ SUBSTATUS_FOUND_BAD_CHECKSUM,
+ SUBSTATUS_FOUND_WRONG_LENGTH,
+ SUBSTATUS_NOT_FOUND,
+ SUBSTATUS_NOT_FOUND_NODUMP,
+ SUBSTATUS_NOT_FOUND_OPTIONAL,
+ SUBSTATUS_ERROR = 100
+ };
+
+ // construction/destruction
+ audit_record(const rom_entry &media, media_type type);
+ audit_record(const char *name, media_type type);
+
+ // getters
+ audit_record *next() const { return m_next; }
+ media_type type() const { return m_type; }
+ audit_status status() const { return m_status; }
+ audit_substatus substatus() const { return m_substatus; }
+ const char *name() const { return m_name; }
+ UINT64 expected_length() const { return m_explength; }
+ UINT64 actual_length() const { return m_length; }
+ const hash_collection &expected_hashes() const { return m_exphashes; }
+ const hash_collection &actual_hashes() const { return m_hashes; }
+ const rom_source *shared_source() const { return m_shared_source; }
+
+ // setters
+ void set_status(audit_status status, audit_substatus substatus)
+ {
+ m_status = status;
+ m_substatus = substatus;
+ }
+
+ void set_actual(const hash_collection &hashes, UINT64 length = 0)
+ {
+ m_hashes = hashes;
+ m_length = length;
+ }
+
+ void set_shared_source(const rom_source *shared_source)
+ {
+ m_shared_source = shared_source;
+ }
+
+private:
+ // internal state
+ audit_record * m_next;
+ media_type m_type; /* type of item that was audited */
+ audit_status m_status; /* status of audit on this item */
+ audit_substatus m_substatus; /* finer-detail status */
+ const char * m_name; /* name of item */
+ UINT64 m_explength; /* expected length of item */
+ UINT64 m_length; /* actual length of item */
+ hash_collection m_exphashes; /* expected hash data */
+ hash_collection m_hashes; /* actual hash information */
+ const rom_source * m_shared_source; /* rom_source that shares the rom */
+};
+
+
+// ======================> media_auditor
+
+// class which manages auditing of items
+class media_auditor
+{
+public:
+ // summary values
+ enum summary
+ {
+ CORRECT = 0,
+ NONE_NEEDED,
+ BEST_AVAILABLE,
+ INCORRECT,
+ NOTFOUND
+ };
+
+ // construction/destruction
+ media_auditor(const driver_enumerator &enumerator);
+
+ // getters
+ audit_record *first() const { return m_record_list.first(); }
+ int count() const { return m_record_list.count(); }
+
+ // audit operations
+ summary audit_media(const char *validation = AUDIT_VALIDATE_FULL);
+ summary audit_device(device_t *device, const char *validation = AUDIT_VALIDATE_FULL);
+ summary audit_samples();
+ summary summarize(const char *name,astring *output = NULL);
+
+private:
+ // internal helpers
+ audit_record *audit_one_rom(const rom_entry *rom);
+ audit_record *audit_one_disk(const rom_entry *rom);
+ void compute_status(audit_record &record, const rom_entry *rom, bool found);
+ const rom_source *find_shared_source(const rom_source *source, const hash_collection &romhashes, UINT64 romlength);
+
+ // internal state
+ simple_list<audit_record> m_record_list;
+ const driver_enumerator & m_enumerator;
+ const char * m_validation;
+ const char * m_searchpath;
+};
+
+
+#endif /* __AUDIT_H__ */
diff --git a/trunk/src/emu/cheat.c b/trunk/src/emu/cheat.c
new file mode 100644
index 00000000000..e058398717f
--- /dev/null
+++ b/trunk/src/emu/cheat.c
@@ -0,0 +1,1479 @@
+/***************************************************************************
+
+ cheat.c
+
+ MAME cheat system.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+****************************************************************************
+
+ Cheat XML format:
+
+ <mamecheat version="1">
+ <cheat desc="blah">
+ <parameter min="minval(0)" max="maxval(numitems)" step="stepval(1)">
+ <item value="itemval(previtemval|minval+stepval)">text</item>
+ ...
+ </parameter>
+ <script state="on|off|run|change(run)">
+ <action condition="condexpr(1)">expression</action>
+ ...
+ <output condition="condexpr(1)" format="format(required)" line="line(0)" align="left|center|right(left)">
+ <argument count="count(1)">expression</argument>
+ </output>
+ ...
+ </script>
+ ...
+ <comment>
+ ... text ...
+ </comment>
+ </cheat>
+ ...
+ </mamecheat>
+
+****************************************************************************
+
+ Expressions are standard debugger expressions. Note that & and
+ < must be escaped per XML rules. Within attributes you must use
+ &amp; and &lt;. For tags, you can also use <![CDATA[ ... ]]>.
+
+ Each cheat has its own context-specific variables:
+
+ temp0-temp9 -- 10 temporary variables for any use
+ param -- the current value of the cheat parameter
+ frame -- the current frame index
+ argindex -- for arguments with multiple iterations, this is the index
+
+ By default, each cheat has 10 temporary variables that are
+ persistent while executing its scripts. Additional temporary
+ variables may be requested via the 'tempvariables' attribute
+ on the cheat.
+
+****************************************************************************
+
+ Cheats are generally broken down into categories based on
+ which actions are defined and whether or not there is a
+ parameter present:
+
+ ---- Actions -----
+ On Off Run Chg Param? Type
+ === === === === ====== =================================
+ N N N ? None Text-only (displays text in menu)
+ Y N N ? None Oneshot (select to activate)
+ Y Y N ? None On/Off (select to toggle)
+ ? ? Y ? None On/Off (select to toggle)
+
+ ? N N Y Any Oneshot parameter (select to alter)
+ ? Y ? ? Value Value parameter (off or a live value)
+ ? ? Y ? Value Value parameter (off or a live value)
+ ? Y ? ? List Item list parameter (off or a live value)
+ ? ? Y ? List Item list parameter (off or a live value)
+
+***************************************************************************/
+
+#include "emu.h"
+#include "emuopts.h"
+#include "xmlfile.h"
+#include "ui.h"
+#include "uimenu.h"
+#include "cheat.h"
+#include "debug/debugcpu.h"
+
+#include <ctype.h>
+
+
+
+//**************************************************************************
+// PARAMETERS
+//**************************************************************************
+
+// turn this on to enable removing duplicate cheats; not sure if we should
+#define REMOVE_DUPLICATE_CHEATS 0
+
+
+
+//**************************************************************************
+// NUMBER AND FORMAT
+//**************************************************************************
+
+//-------------------------------------------------
+// format - format an integer according to
+// the format
+//-------------------------------------------------
+
+inline const char *number_and_format::format(astring &string) const
+{
+ switch (m_format)
+ {
+ default:
+ case XML_INT_FORMAT_DECIMAL:
+ string.printf("%d", (UINT32)m_value);
+ break;
+
+ case XML_INT_FORMAT_DECIMAL_POUND:
+ string.printf("#%d", (UINT32)m_value);
+ break;
+
+ case XML_INT_FORMAT_HEX_DOLLAR:
+ string.printf("$%X", (UINT32)m_value);
+ break;
+
+ case XML_INT_FORMAT_HEX_C:
+ string.printf("0x%X", (UINT32)m_value);
+ break;
+ }
+ return string;
+}
+
+
+
+//**************************************************************************
+// CHEAT PARAMETER
+//**************************************************************************
+
+//-------------------------------------------------
+// cheat_parameter - constructor
+//-------------------------------------------------
+
+cheat_parameter::cheat_parameter(cheat_manager &manager, symbol_table &symbols, const char *filename, xml_data_node &paramnode)
+ : m_value(0),
+ m_itemlist(manager.machine().respool())
+{
+ // read the core attributes
+ m_minval = number_and_format(xml_get_attribute_int(&paramnode, "min", 0), xml_get_attribute_int_format(&paramnode, "min"));
+ m_maxval = number_and_format(xml_get_attribute_int(&paramnode, "max", 0), xml_get_attribute_int_format(&paramnode, "max"));
+ m_stepval = number_and_format(xml_get_attribute_int(&paramnode, "step", 1), xml_get_attribute_int_format(&paramnode, "step"));
+
+ // iterate over items
+ for (xml_data_node *itemnode = xml_get_sibling(paramnode.child, "item"); itemnode != NULL; itemnode = xml_get_sibling(itemnode->next, "item"))
+ {
+ // check for NULL text
+ if (itemnode->value == NULL || itemnode->value[0] == 0)
+ throw emu_fatalerror("%s.xml(%d): item is missing text\n", filename, itemnode->line);
+
+ // check for non-existant value
+ if (xml_get_attribute(itemnode, "value") == NULL)
+ throw emu_fatalerror("%s.xml(%d): item is value\n", filename, itemnode->line);
+
+ // extract the parameters
+ UINT64 value = xml_get_attribute_int(itemnode, "value", 0);
+ int format = xml_get_attribute_int_format(itemnode, "value");
+
+ // allocate and append a new item
+ item &curitem = m_itemlist.append(*auto_alloc(manager.machine(), item(itemnode->value, value, format)));
+
+ // ensure the maximum expands to suit
+ m_maxval = MAX(m_maxval, curitem.value());
+ }
+
+ // add a variable to the symbol table for our value
+ symbols.add("param", symbol_table::READ_ONLY, &m_value);
+}
+
+
+//-------------------------------------------------
+// text - return the current text for a parameter
+//-------------------------------------------------
+
+const char *cheat_parameter::text()
+{
+ // are we a value cheat?
+ if (!has_itemlist())
+ m_curtext.format("%d (0x%X)", UINT32(m_value), UINT32(m_value));
+
+ // if not, we're an item cheat
+ else
+ {
+ m_curtext.format("??? (%d)", UINT32(m_value));
+ for (item *curitem = m_itemlist.first(); curitem != NULL; curitem = curitem->next())
+ if (curitem->value() == m_value)
+ {
+ m_curtext.cpy(curitem->text());
+ break;
+ }
+ }
+ return m_curtext;
+}
+
+
+//-------------------------------------------------
+// save - save a single cheat parameter
+//-------------------------------------------------
+
+void cheat_parameter::save(emu_file &cheatfile) const
+{
+ // output the parameter tag
+ cheatfile.printf("\t\t<parameter");
+
+ // if no items, just output min/max/step
+ astring string;
+ if (!has_itemlist())
+ {
+ if (m_minval != 0)
+ cheatfile.printf(" min=\"%s\"", m_minval.format(string));
+ if (m_maxval != 0)
+ cheatfile.printf(" max=\"%s\"", m_maxval.format(string));
+ if (m_stepval != 1)
+ cheatfile.printf(" step=\"%s\"", m_stepval.format(string));
+ cheatfile.printf("/>\n");
+ }
+
+ // iterate over items
+ else
+ {
+ for (const item *curitem = m_itemlist.first(); curitem != NULL; curitem = curitem->next())
+ cheatfile.printf("\t\t\t<item value=\"%s\">%s</item>\n", curitem->value().format(string), curitem->text());
+ cheatfile.printf("\t\t</parameter>\n");
+ }
+}
+
+
+//-------------------------------------------------
+// set_minimum_state - set the minimum state
+//-------------------------------------------------
+
+bool cheat_parameter::set_minimum_state()
+{
+ UINT64 origvalue = m_value;
+
+ // set based on whether we have an item list
+ m_value = (!has_itemlist()) ? m_minval : m_itemlist.first()->value();
+
+ return (m_value != origvalue);
+}
+
+
+//-------------------------------------------------
+// set_minimum_state - set the previous state
+//-------------------------------------------------
+
+bool cheat_parameter::set_prev_state()
+{
+ UINT64 origvalue = m_value;
+
+ // are we a value cheat?
+ if (!has_itemlist())
+ {
+ if (m_value < m_minval + m_stepval)
+ m_value = m_minval;
+ else
+ m_value -= m_stepval;
+ }
+
+ // if not, we're an item cheat
+ else
+ {
+ item *curitem, *previtem = NULL;
+ for (curitem = m_itemlist.first(); curitem != NULL; previtem = curitem, curitem = curitem->next())
+ if (curitem->value() == m_value)
+ break;
+ if (previtem != NULL)
+ m_value = previtem->value();
+ }
+
+ return (m_value != origvalue);
+}
+
+
+//-------------------------------------------------
+// set_next_state - advance to the next state
+//-------------------------------------------------
+
+bool cheat_parameter::set_next_state()
+{
+ UINT64 origvalue = m_value;
+
+ // are we a value cheat?
+ if (!has_itemlist())
+ {
+ if (m_value > m_maxval - m_stepval)
+ m_value = m_maxval;
+ else
+ m_value += m_stepval;
+ }
+
+ // if not, we're an item cheat
+ else
+ {
+ item *curitem;
+ for (curitem = m_itemlist.first(); curitem != NULL; curitem = curitem->next())
+ if (curitem->value() == m_value)
+ break;
+ if (curitem != NULL && curitem->next() != NULL)
+ m_value = curitem->next()->value();
+ }
+
+ return (m_value != origvalue);
+}
+
+
+
+//**************************************************************************
+// CHEAT SCRIPT
+//**************************************************************************
+
+//-------------------------------------------------
+// cheat_script - constructor
+//-------------------------------------------------
+
+cheat_script::cheat_script(cheat_manager &manager, symbol_table &symbols, const char *filename, xml_data_node &scriptnode)
+ : m_entrylist(manager.machine().respool()),
+ m_state(SCRIPT_STATE_RUN)
+{
+ // read the core attributes
+ const char *state = xml_get_attribute_string(&scriptnode, "state", "run");
+ if (strcmp(state, "on") == 0)
+ m_state = SCRIPT_STATE_ON;
+ else if (strcmp(state, "off") == 0)
+ m_state = SCRIPT_STATE_OFF;
+ else if (strcmp(state, "change") == 0)
+ m_state = SCRIPT_STATE_CHANGE;
+ else if (strcmp(state, "run") != 0)
+ throw emu_fatalerror("%s.xml(%d): invalid script state '%s'\n", filename, scriptnode.line, state);
+
+ // iterate over nodes within the script
+ for (xml_data_node *entrynode = scriptnode.child; entrynode != NULL; entrynode = entrynode->next)
+ {
+ // handle action nodes
+ if (strcmp(entrynode->name, "action") == 0)
+ m_entrylist.append(*auto_alloc(manager.machine(), script_entry(manager, symbols, filename, *entrynode, true)));
+
+ // handle output nodes
+ else if (strcmp(entrynode->name, "output") == 0)
+ m_entrylist.append(*auto_alloc(manager.machine(), script_entry(manager, symbols, filename, *entrynode, false)));
+
+ // anything else is ignored
+ else
+ {
+ mame_printf_warning("%s.xml(%d): unknown script item '%s' will be lost if saved\n", filename, entrynode->line, entrynode->name);
+ continue;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// execute - execute ourself
+//-------------------------------------------------
+
+void cheat_script::execute(cheat_manager &manager, UINT64 &argindex)
+{
+ // do nothing if disabled
+ if (!manager.enabled())
+ return;
+
+ // iterate over entries
+ for (script_entry *entry = m_entrylist.first(); entry != NULL; entry = entry->next())
+ entry->execute(manager, argindex);
+}
+
+
+//-------------------------------------------------
+// save - save a single cheat script
+//-------------------------------------------------
+
+void cheat_script::save(emu_file &cheatfile) const
+{
+ // output the script tag
+ cheatfile.printf("\t\t<script");
+ switch (m_state)
+ {
+ case SCRIPT_STATE_OFF: cheatfile.printf(" state=\"off\""); break;
+ case SCRIPT_STATE_ON: cheatfile.printf(" state=\"on\""); break;
+ default:
+ case SCRIPT_STATE_RUN: cheatfile.printf(" state=\"run\""); break;
+ case SCRIPT_STATE_CHANGE: cheatfile.printf(" state=\"change\""); break;
+ }
+ cheatfile.printf(">\n");
+
+ // output entries
+ for (const script_entry *entry = m_entrylist.first(); entry != NULL; entry = entry->next())
+ entry->save(cheatfile);
+
+ // close the tag
+ cheatfile.printf("\t\t</script>\n");
+}
+
+
+//-------------------------------------------------
+// script_entry - constructor
+//-------------------------------------------------
+
+cheat_script::script_entry::script_entry(cheat_manager &manager, symbol_table &symbols, const char *filename, xml_data_node &entrynode, bool isaction)
+ : m_next(NULL),
+ m_condition(&symbols),
+ m_expression(&symbols),
+ m_arglist(manager.machine().respool())
+{
+ const char *expression = NULL;
+ try
+ {
+ // read the condition if present
+ expression = xml_get_attribute_string(&entrynode, "condition", NULL);
+ if (expression != NULL)
+ m_condition.parse(expression);
+
+ // if this is an action, parse the expression
+ if (isaction)
+ {
+ expression = entrynode.value;
+ if (expression == NULL || expression[0] == 0)
+ throw emu_fatalerror("%s.xml(%d): missing expression in action tag\n", filename, entrynode.line);
+ m_expression.parse(expression);
+ }
+
+ // otherwise, parse the attributes and arguments
+ else
+ {
+ // extract format
+ const char *format = xml_get_attribute_string(&entrynode, "format", NULL);
+ if (format == NULL || format[0] == 0)
+ throw emu_fatalerror("%s.xml(%d): missing format in output tag\n", filename, entrynode.line);
+ m_format.cpy(format);
+
+ // extract other attributes
+ m_line = xml_get_attribute_int(&entrynode, "line", 0);
+ m_justify = JUSTIFY_LEFT;
+ const char *align = xml_get_attribute_string(&entrynode, "align", "left");
+ if (strcmp(align, "center") == 0)
+ m_justify = JUSTIFY_CENTER;
+ else if (strcmp(align, "right") == 0)
+ m_justify = JUSTIFY_RIGHT;
+ else if (strcmp(align, "left") != 0)
+ throw emu_fatalerror("%s.xml(%d): invalid alignment '%s' specified\n", filename, entrynode.line, align);
+
+ // then parse arguments
+ int totalargs = 0;
+ for (xml_data_node *argnode = xml_get_sibling(entrynode.child, "argument"); argnode != NULL; argnode = xml_get_sibling(argnode->next, "argument"))
+ {
+ output_argument &curarg = m_arglist.append(*auto_alloc(manager.machine(), output_argument(manager, symbols, filename, *argnode)));
+
+ // verify we didn't overrun the argument count
+ totalargs += curarg.count();
+ if (totalargs > MAX_ARGUMENTS)
+ throw emu_fatalerror("%s.xml(%d): too many arguments (found %d, max is %d)\n", filename, argnode->line, totalargs, MAX_ARGUMENTS);
+ }
+
+ // validate the format against the arguments
+ validate_format(filename, entrynode.line);
+ }
+ }
+ catch (expression_error &err)
+ {
+ throw emu_fatalerror("%s.xml(%d): error parsing cheat expression \"%s\" (%s)\n", filename, entrynode.line, expression, err.code_string());
+ }
+}
+
+
+//-------------------------------------------------
+// execute - execute a single script entry
+//-------------------------------------------------
+
+void cheat_script::script_entry::execute(cheat_manager &manager, UINT64 &argindex)
+{
+ // evaluate the condition
+ if (!m_condition.is_empty())
+ {
+ try
+ {
+ UINT64 result = m_condition.execute();
+ if (result == 0)
+ return;
+ }
+ catch (expression_error &err)
+ {
+ mame_printf_warning("Error executing conditional expression \"%s\": %s\n", m_condition.original_string(), err.code_string());
+ return;
+ }
+ }
+
+ // if there is an action, execute it
+ if (!m_expression.is_empty())
+ {
+ try
+ {
+ m_expression.execute();
+ }
+ catch (expression_error &err)
+ {
+ mame_printf_warning("Error executing expression \"%s\": %s\n", m_expression.original_string(), err.code_string());
+ }
+ }
+
+ // if there is a string to display, compute it
+ if (m_format)
+ {
+ // iterate over arguments and evaluate them
+ UINT64 params[MAX_ARGUMENTS];
+ int curarg = 0;
+ for (output_argument *arg = m_arglist.first(); arg != NULL; arg = arg->next())
+ curarg += arg->values(argindex, &params[curarg]);
+
+ // generate the astring
+ manager.get_output_astring(m_line, m_justify).printf(m_format,
+ (UINT32)params[0], (UINT32)params[1], (UINT32)params[2], (UINT32)params[3],
+ (UINT32)params[4], (UINT32)params[5], (UINT32)params[6], (UINT32)params[7],
+ (UINT32)params[8], (UINT32)params[9], (UINT32)params[10], (UINT32)params[11],
+ (UINT32)params[12], (UINT32)params[13], (UINT32)params[14], (UINT32)params[15],
+ (UINT32)params[16], (UINT32)params[17], (UINT32)params[18], (UINT32)params[19],
+ (UINT32)params[20], (UINT32)params[21], (UINT32)params[22], (UINT32)params[23],
+ (UINT32)params[24], (UINT32)params[25], (UINT32)params[26], (UINT32)params[27],
+ (UINT32)params[28], (UINT32)params[29], (UINT32)params[30], (UINT32)params[31]);
+ }
+}
+
+
+//-------------------------------------------------
+// save - save a single action or output
+//-------------------------------------------------
+
+void cheat_script::script_entry::save(emu_file &cheatfile) const
+{
+ astring tempstring;
+
+ // output an action
+ if (!m_format)
+ {
+ cheatfile.printf("\t\t\t<action");
+ if (!m_condition.is_empty())
+ cheatfile.printf(" condition=\"%s\"", cheat_manager::quote_expression(tempstring, m_condition));
+ cheatfile.printf(">%s</action>\n", cheat_manager::quote_expression(tempstring, m_expression));
+ }
+
+ // output an output
+ else
+ {
+ cheatfile.printf("\t\t\t<output format=\"%s\"", m_format.cstr());
+ if (!m_condition.is_empty())
+ cheatfile.printf(" condition=\"%s\"", cheat_manager::quote_expression(tempstring, m_condition));
+ if (m_line != 0)
+ cheatfile.printf(" line=\"%d\"", m_line);
+ if (m_justify == JUSTIFY_CENTER)
+ cheatfile.printf(" align=\"center\"");
+ else if (m_justify == JUSTIFY_RIGHT)
+ cheatfile.printf(" align=\"right\"");
+ if (m_arglist.count() == 0)
+ cheatfile.printf(" />\n");
+
+ // output arguments
+ else
+ {
+ cheatfile.printf(">\n");
+ for (const output_argument *curarg = m_arglist.first(); curarg != NULL; curarg = curarg->next())
+ curarg->save(cheatfile);
+ cheatfile.printf("\t\t\t</output>\n");
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// validate_format - check that a format string
+// has the correct number and type of arguments
+//-------------------------------------------------
+
+void cheat_script::script_entry::validate_format(const char *filename, int line)
+{
+ // first count arguments
+ int argsprovided = 0;
+ for (const output_argument *curarg = m_arglist.first(); curarg != NULL; curarg = curarg->next())
+ argsprovided += curarg->count();
+
+ // now scan the string for valid argument usage
+ const char *p = strchr(m_format, '%');
+ int argscounted = 0;
+ while (p != NULL)
+ {
+ // skip past any valid attributes
+ p++;
+ while (strchr("lh0123456789.-+ #", *p) != NULL)
+ p++;
+
+ // look for a valid type
+ if (strchr("cdiouxX", *p) == NULL)
+ throw emu_fatalerror("%s.xml(%d): invalid format specification \"%s\"\n", filename, line, m_format.cstr());
+ argscounted++;
+
+ // look for the next one
+ p = strchr(p, '%');
+ }
+
+ // did we match?
+ if (argscounted < argsprovided)
+ throw emu_fatalerror("%s.xml(%d): too many arguments provided (%d) for format \"%s\"\n", filename, line, argsprovided, m_format.cstr());
+ if (argscounted > argsprovided)
+ throw emu_fatalerror("%s.xml(%d): not enough arguments provided (%d) for format \"%s\"\n", filename, line, argsprovided, m_format.cstr());
+}
+
+
+//-------------------------------------------------
+// output_argument - constructor
+//-------------------------------------------------
+
+cheat_script::script_entry::output_argument::output_argument(cheat_manager &manager, symbol_table &symbols, const char *filename, xml_data_node &argnode)
+ : m_next(NULL),
+ m_expression(&symbols),
+ m_count(0)
+{
+ // first extract attributes
+ m_count = xml_get_attribute_int(&argnode, "count", 1);
+
+ // read the expression
+ const char *expression = argnode.value;
+ if (expression == NULL || expression[0] == 0)
+ throw emu_fatalerror("%s.xml(%d): missing expression in argument tag\n", filename, argnode.line);
+
+ // parse it
+ try
+ {
+ m_expression.parse(expression);
+ }
+ catch (expression_error &err)
+ {
+ throw emu_fatalerror("%s.xml(%d): error parsing cheat expression \"%s\" (%s)\n", filename, argnode.line, expression, err.code_string());
+ }
+}
+
+
+//-------------------------------------------------
+// value - return the evaluated value of the
+// given output argument
+//-------------------------------------------------
+
+int cheat_script::script_entry::output_argument::values(UINT64 &argindex, UINT64 *result)
+{
+ for (argindex = 0; argindex < m_count; argindex++)
+ {
+ try
+ {
+ result[argindex] = m_expression.execute();
+ }
+ catch (expression_error &err)
+ {
+ mame_printf_warning("Error executing argument expression \"%s\": %s\n", m_expression.original_string(), err.code_string());
+ }
+ }
+ return m_count;
+}
+
+
+//-------------------------------------------------
+// save - save a single output argument
+//-------------------------------------------------
+
+void cheat_script::script_entry::output_argument::save(emu_file &cheatfile) const
+{
+ astring tempstring;
+
+ cheatfile.printf("\t\t\t\t<argument");
+ if (m_count != 1)
+ cheatfile.printf(" count=\"%d\"", (int)m_count);
+ cheatfile.printf(">%s</argument>\n", cheat_manager::quote_expression(tempstring, m_expression));
+}
+
+
+
+//**************************************************************************
+// CHEAT ENTRY
+//**************************************************************************
+
+//-------------------------------------------------
+// cheat_entry - constructor
+//-------------------------------------------------
+
+cheat_entry::cheat_entry(cheat_manager &manager, symbol_table &globaltable, const char *filename, xml_data_node &cheatnode)
+ : m_manager(manager),
+ m_next(NULL),
+ m_parameter(NULL),
+ m_on_script(NULL),
+ m_off_script(NULL),
+ m_change_script(NULL),
+ m_run_script(NULL),
+ m_symbols(&manager.machine(), &globaltable),
+ m_state(SCRIPT_STATE_OFF),
+ m_numtemp(DEFAULT_TEMP_VARIABLES),
+ m_argindex(0)
+{
+ // reset scripts
+ try
+ {
+ // pull the variable count out ahead of things
+ int tempcount = xml_get_attribute_int(&cheatnode, "tempvariables", DEFAULT_TEMP_VARIABLES);
+ if (tempcount < 1)
+ throw emu_fatalerror("%s.xml(%d): invalid tempvariables attribute (%d)\n", filename, cheatnode.line, tempcount);
+
+ // allocate memory for the cheat
+ m_numtemp = tempcount;
+
+ // get the description
+ const char *description = xml_get_attribute_string(&cheatnode, "desc", NULL);
+ if (description == NULL || description[0] == 0)
+ throw emu_fatalerror("%s.xml(%d): empty or missing desc attribute on cheat\n", filename, cheatnode.line);
+ m_description = description;
+
+ // create the symbol table
+ m_symbols.add("argindex", symbol_table::READ_ONLY, &m_argindex);
+ astring tempname;
+ for (int curtemp = 0; curtemp < tempcount; curtemp++)
+ m_symbols.add(tempname.format("temp%d", curtemp), symbol_table::READ_WRITE);
+
+ // read the first comment node
+ xml_data_node *commentnode = xml_get_sibling(cheatnode.child, "comment");
+ if (commentnode != NULL)
+ {
+ // set the value if not NULL
+ if (commentnode->value != NULL && commentnode->value[0] != 0)
+ m_comment.cpy(commentnode->value);
+
+ // only one comment is kept
+ commentnode = xml_get_sibling(commentnode->next, "comment");
+ if (commentnode != NULL)
+ mame_printf_warning("%s.xml(%d): only one comment node is retained; ignoring additional nodes\n", filename, commentnode->line);
+ }
+
+ // read the first parameter node
+ xml_data_node *paramnode = xml_get_sibling(cheatnode.child, "parameter");
+ if (paramnode != NULL)
+ {
+ // load this parameter
+ m_parameter = auto_alloc(manager.machine(), cheat_parameter(manager, m_symbols, filename, *paramnode));
+
+ // only one parameter allowed
+ paramnode = xml_get_sibling(paramnode->next, "parameter");
+ if (paramnode != NULL)
+ mame_printf_warning("%s.xml(%d): only one parameter node allowed; ignoring additional nodes\n", filename, paramnode->line);
+ }
+
+ // read the script nodes
+ for (xml_data_node *scriptnode = xml_get_sibling(cheatnode.child, "script"); scriptnode != NULL; scriptnode = xml_get_sibling(scriptnode->next, "script"))
+ {
+ // load this entry
+ cheat_script *curscript = auto_alloc(manager.machine(), cheat_script(manager, m_symbols, filename, *scriptnode));
+
+ // if we have a script already for this slot, it is an error
+ cheat_script *&slot = script_for_state(curscript->state());
+ if (slot != NULL)
+ mame_printf_warning("%s.xml(%d): only one on script allowed; ignoring additional scripts\n", filename, scriptnode->line);
+ else
+ slot = curscript;
+ }
+ }
+ catch (emu_fatalerror &)
+ {
+ // call our destructor to clean up and re-throw
+ this->~cheat_entry();
+ throw;
+ }
+}
+
+
+//-------------------------------------------------
+// ~cheat_entry - destructor
+//-------------------------------------------------
+
+cheat_entry::~cheat_entry()
+{
+ auto_free(m_manager.machine(), m_on_script);
+ auto_free(m_manager.machine(), m_off_script);
+ auto_free(m_manager.machine(), m_change_script);
+ auto_free(m_manager.machine(), m_run_script);
+ auto_free(m_manager.machine(), m_parameter);
+}
+
+
+//-------------------------------------------------
+// save - save a single cheat entry
+//-------------------------------------------------
+
+void cheat_entry::save(emu_file &cheatfile) const
+{
+ // determine if we have scripts
+ bool has_scripts = (m_off_script != NULL || m_on_script != NULL || m_run_script != NULL || m_change_script != NULL);
+
+ // output the cheat tag
+ cheatfile.printf("\t<cheat desc=\"%s\"", m_description.cstr());
+ if (m_numtemp != DEFAULT_TEMP_VARIABLES)
+ cheatfile.printf(" tempvariables=\"%d\"", m_numtemp);
+ if (!m_comment && m_parameter == NULL && !has_scripts)
+ cheatfile.printf(" />\n");
+ else
+ {
+ cheatfile.printf(">\n");
+
+ // save the comment
+ if (m_comment)
+ cheatfile.printf("\t\t<comment><![CDATA[\n%s\n\t\t]]></comment>\n", m_comment.cstr());
+
+ // output the parameter, if present
+ if (m_parameter != NULL)
+ m_parameter->save(cheatfile);
+
+ // output the script nodes
+ if (m_on_script != NULL)
+ m_on_script->save(cheatfile);
+ if (m_off_script != NULL)
+ m_off_script->save(cheatfile);
+ if (m_change_script != NULL)
+ m_change_script->save(cheatfile);
+ if (m_run_script != NULL)
+ m_run_script->save(cheatfile);
+
+ // close the cheat tag
+ cheatfile.printf("\t</cheat>\n");
+ }
+}
+
+
+//-------------------------------------------------
+// activate - activate a oneshot cheat
+//-------------------------------------------------
+
+bool cheat_entry::activate()
+{
+ bool changed = false;
+
+ // if cheats have been toggled off no point in even trying to do anything
+ if (!m_manager.enabled())
+ return changed;
+
+ // if we're a oneshot cheat, execute the "on" script and indicate change
+ if (is_oneshot())
+ {
+ execute_on_script();
+ changed = true;
+ popmessage("Activated %s", m_description.cstr());
+ }
+
+ // if we're a oneshot parameter cheat and we're active, execute the "state change" script and indicate change
+ else if (is_oneshot_parameter() && m_state != SCRIPT_STATE_OFF)
+ {
+ execute_change_script();
+ changed = true;
+ popmessage("Activated\n %s = %s", m_description.cstr(), m_parameter->text());
+ }
+
+ return changed;
+}
+
+
+//-------------------------------------------------
+// select_default_state - select the default
+// state for a cheat, or activate a oneshot cheat
+//-------------------------------------------------
+
+bool cheat_entry::select_default_state()
+{
+ bool changed = false;
+
+ // if we're a oneshot cheat, there is no default state
+ if (is_oneshot())
+ ;
+
+ // all other types switch to the "off" state
+ else
+ changed = set_state(SCRIPT_STATE_OFF);
+
+ return changed;
+}
+
+
+//-------------------------------------------------
+// select_previous_state - select the previous
+// state for a cheat
+//-------------------------------------------------
+
+bool cheat_entry::select_previous_state()
+{
+ bool changed = false;
+
+ // if we're a oneshot, there is no previous state
+ if (is_oneshot())
+ ;
+
+ // if we're on/off, toggle to off
+ else if (is_onoff())
+ changed = set_state(SCRIPT_STATE_OFF);
+
+ // if we have a parameter, set the previous state
+ else if (m_parameter != NULL)
+ {
+ // if we're at our minimum, turn off
+ if (m_parameter->is_minimum())
+ changed = set_state(SCRIPT_STATE_OFF);
+ else
+ {
+ // if we changed, ensure we are in the running state and signal state change
+ changed = m_parameter->set_prev_state();
+ if (changed)
+ {
+ set_state(SCRIPT_STATE_RUN);
+ if (!is_oneshot_parameter())
+ execute_change_script();
+ }
+ }
+ }
+ return changed;
+}
+
+
+//-------------------------------------------------
+// select_next_state - select the next state for
+// a cheat
+//-------------------------------------------------
+
+bool cheat_entry::select_next_state()
+{
+ bool changed = false;
+
+ // if we're a oneshot, there is no next state
+ if (is_oneshot())
+ ;
+
+ // if we're on/off, toggle to running state
+ else if (is_onoff())
+ changed = set_state(SCRIPT_STATE_RUN);
+
+ // if we have a parameter, set the next state
+ else if (m_parameter != NULL)
+ {
+ // if we're off, switch on to the minimum state
+ if (m_state == SCRIPT_STATE_OFF)
+ {
+ changed = set_state(SCRIPT_STATE_RUN);
+ m_parameter->set_minimum_state();
+ }
+
+ // otherwise, switch to the next state
+ else
+ changed = m_parameter->set_next_state();
+
+ // if we changed, signal a state change
+ if (changed && !is_oneshot_parameter())
+ execute_change_script();
+ }
+ return changed;
+}
+
+
+//-------------------------------------------------
+// menu_text - return the text needed to display
+// this cheat in a menu item
+//-------------------------------------------------
+
+void cheat_entry::menu_text(astring &description, astring &state, UINT32 &flags)
+{
+ // description is standard
+ description.cpy(m_description);
+ state.reset();
+ flags = 0;
+
+ // some cheat entries are just text for display
+ if (is_text_only())
+ {
+ if (description)
+ {
+ description.trimspace();
+ if (!description)
+ description.cpy(MENU_SEPARATOR_ITEM);
+ }
+ flags = MENU_FLAG_DISABLE;
+ }
+
+ // if we have no parameter and no run or off script, it's a oneshot cheat
+ else if (is_oneshot())
+ state.cpy("Set");
+
+ // if we have no parameter, it's just on/off
+ else if (is_onoff())
+ {
+ state.cpy((m_state == SCRIPT_STATE_RUN) ? "On" : "Off");
+ flags = (m_state != 0) ? MENU_FLAG_LEFT_ARROW : MENU_FLAG_RIGHT_ARROW;
+ }
+
+ // if we have a value parameter, compute it
+ else if (m_parameter != NULL)
+ {
+ if (m_state == SCRIPT_STATE_OFF)
+ {
+ state.cpy(is_oneshot_parameter() ? "Set" : "Off");
+ flags = MENU_FLAG_RIGHT_ARROW;
+ }
+ else
+ {
+ state.cpy(m_parameter->text());
+ flags = MENU_FLAG_LEFT_ARROW;
+ if (!m_parameter->is_maximum())
+ flags |= MENU_FLAG_RIGHT_ARROW;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// set_state - switch to the given state
+//-------------------------------------------------
+
+bool cheat_entry::set_state(script_state newstate)
+{
+ // if we're already in the state, indicate no change
+ if (m_state == newstate)
+ return false;
+
+ // change to the state and run the appropriate script
+ m_state = newstate;
+ if (newstate == SCRIPT_STATE_OFF)
+ execute_off_script();
+ else if (newstate == SCRIPT_STATE_ON || newstate == SCRIPT_STATE_RUN)
+ execute_on_script();
+ return true;
+}
+
+
+//-------------------------------------------------
+// script_for_state - get a reference to the
+// given script pointer
+//-------------------------------------------------
+
+cheat_script *&cheat_entry::script_for_state(script_state state)
+{
+ switch (state)
+ {
+ case SCRIPT_STATE_ON: return m_on_script;
+ case SCRIPT_STATE_OFF: return m_off_script;
+ case SCRIPT_STATE_CHANGE: return m_change_script;
+ default:
+ case SCRIPT_STATE_RUN: return m_run_script;
+ }
+}
+
+
+
+//**************************************************************************
+// CHEAT MANAGER
+//**************************************************************************
+
+//-------------------------------------------------
+// cheat_manager - constructor
+//-------------------------------------------------
+
+cheat_manager::cheat_manager(running_machine &machine)
+ : m_machine(machine),
+ m_cheatlist(machine.respool()),
+ m_disabled(true),
+ m_symtable(&machine)
+{
+ // if the cheat engine is disabled, we're done
+ if (!machine.options().cheat())
+ return;
+
+ // request a callback
+ machine.add_notifier(MACHINE_NOTIFY_FRAME, machine_notify_delegate(FUNC(cheat_manager::frame_update), this));
+
+ // create a global symbol table
+ m_symtable.add("frame", symbol_table::READ_ONLY, &m_framecount);
+ m_symtable.add("frombcd", NULL, 1, 1, execute_frombcd);
+ m_symtable.add("tobcd", NULL, 1, 1, execute_tobcd);
+
+ // we rely on the debugger expression callbacks; if the debugger isn't
+ // enabled, we must jumpstart them manually
+ if ((machine.debug_flags & DEBUG_FLAG_ENABLED) == 0)
+ debug_cpu_init(machine);
+
+ // configure for memory access (shared with debugger)
+ debug_cpu_configure_memory(machine, m_symtable);
+
+ // load the cheats
+ reload();
+}
+
+
+//-------------------------------------------------
+// set_enable - globally enable or disable the
+// cheat engine
+//-------------------------------------------------
+
+void cheat_manager::set_enable(bool enable)
+{
+ // if the cheat engine is disabled, we're done
+ if (!machine().options().cheat())
+ return;
+
+ // if we're enabled currently and we don't want to be, turn things off
+ if (!m_disabled && !enable)
+ {
+ // iterate over running cheats and execute any OFF Scripts
+ for (cheat_entry *cheat = m_cheatlist.first(); cheat != NULL; cheat = cheat->next())
+ if (cheat->state() == SCRIPT_STATE_RUN)
+ cheat->execute_off_script();
+ popmessage("Cheats Disabled");
+ m_disabled = true;
+ }
+
+ // if we're disabled currently and we want to be enabled, turn things on
+ else if (m_disabled && enable)
+ {
+ // iterate over running cheats and execute any ON Scripts
+ m_disabled = false;
+ for (cheat_entry *cheat = m_cheatlist.first(); cheat != NULL; cheat = cheat->next())
+ if (cheat->state() == SCRIPT_STATE_RUN)
+ cheat->execute_on_script();
+ popmessage("Cheats Enabled");
+ }
+}
+
+
+//-------------------------------------------------
+// reload - re-initialize the cheat engine, and
+// and reload the cheat file(s)
+//-------------------------------------------------
+
+void cheat_manager::reload()
+{
+ // if the cheat engine is disabled, we're done
+ if (!machine().options().cheat())
+ return;
+
+ // free everything
+ m_cheatlist.reset();
+
+ // reset state
+ m_framecount = 0;
+ m_numlines = 0;
+ m_lastline = 0;
+ m_disabled = false;
+
+ // load the cheat file, MESS will load a crc32.xml ( eg. 01234567.xml )
+ // and MAME will load gamename.xml
+ device_image_interface *image = NULL;
+ for (bool gotone = machine().devicelist().first(image); gotone; gotone = image->next(image))
+ if (image->exists())
+ {
+ // if we are loading through software lists, try to load shortname.xml
+ if (image->software_entry() != NULL)
+ {
+ load_cheats(image->basename());
+ break;
+ }
+ else
+ {
+ UINT32 crc = image->crc();
+ if (crc != 0)
+ {
+ astring filename;
+ filename.printf("%08X", crc);
+ load_cheats(filename);
+ break;
+ }
+ }
+ }
+
+ // if we haven't found the cheats yet, load by basename
+ if (m_cheatlist.count() == 0)
+ load_cheats(machine().basename());
+
+ // temporary: save the file back out as output.xml for comparison
+ if (m_cheatlist.count() != 0)
+ save_all("output");
+}
+
+
+//-------------------------------------------------
+// cheat_list_save - save a cheat file from
+// memory to the given filename
+//-------------------------------------------------
+
+bool cheat_manager::save_all(const char *filename)
+{
+ // open the file with the proper name
+ emu_file cheatfile(machine().options().cheat_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ file_error filerr = cheatfile.open(filename, ".xml");
+
+ // if that failed, return nothing
+ if (filerr != FILERR_NONE)
+ return false;
+
+ // wrap the rest of catch errors
+ try
+ {
+ // output the outer layers
+ cheatfile.printf("<?xml version=\"1.0\"?>\n");
+ cheatfile.printf("<!-- This file is autogenerated; comments and unknown tags will be stripped -->\n");
+ cheatfile.printf("<mamecheat version=\"%d\">\n", CHEAT_VERSION);
+
+ // iterate over cheats in the list and save them
+ for (cheat_entry *cheat = m_cheatlist.first(); cheat != NULL; cheat = cheat->next())
+ cheat->save(cheatfile);
+
+ // close out the file
+ cheatfile.printf("</mamecheat>\n");
+ return true;
+ }
+
+ // catch errors and cleanup
+ catch (emu_fatalerror &err)
+ {
+ mame_printf_error("%s\n", err.string());
+ cheatfile.remove_on_close();
+ }
+ return false;
+}
+
+
+//-------------------------------------------------
+// render_text - called by the UI system to
+// render text
+//-------------------------------------------------
+
+void cheat_manager::render_text(render_container &container)
+{
+ // render any text and free it along the way
+ for (int linenum = 0; linenum < ARRAY_LENGTH(m_output); linenum++)
+ if (m_output[linenum])
+ {
+ // output the text
+ ui_draw_text_full(&container, m_output[linenum],
+ 0.0f, (float)linenum * ui_get_line_height(machine()), 1.0f,
+ m_justify[linenum], WRAP_NEVER, DRAW_OPAQUE,
+ ARGB_WHITE, ARGB_BLACK, NULL, NULL);
+ }
+}
+
+
+//-------------------------------------------------
+// get_output_astring - return a reference to
+// the given row's string, and set the
+// justification
+//-------------------------------------------------
+
+astring &cheat_manager::get_output_astring(int row, int justify)
+{
+ // if the row is not specified, grab the next one
+ if (row == 0)
+ row = (m_lastline >= 0) ? m_lastline + 1 : m_lastline - 1;
+
+ // remember the last request
+ m_lastline = row;
+
+ // invert if negative
+ row = (row < 0) ? m_numlines + row : row - 1;
+
+ // clamp within range
+ row = MAX(row, 0);
+ row = MIN(row, m_numlines - 1);
+
+ // return the appropriate string
+ m_justify[row] = justify;
+ return m_output[row];
+}
+
+
+//-------------------------------------------------
+// quote_expression - quote an expression
+// string so that it is valid to embed in an XML
+// document
+//-------------------------------------------------
+
+const char *cheat_manager::quote_expression(astring &string, const parsed_expression &expression)
+{
+ string.cpy(expression.original_string());
+
+ string.replace(0, " && ", " and ");
+ string.replace(0, " &&", " and ");
+ string.replace(0, "&& ", " and ");
+ string.replace(0, "&&", " and ");
+
+ string.replace(0, " & ", " band ");
+ string.replace(0, " &", " band ");
+ string.replace(0, "& ", " band ");
+ string.replace(0, "&", " band ");
+
+ string.replace(0, " <= ", " le ");
+ string.replace(0, " <=", " le ");
+ string.replace(0, "<= ", " le ");
+ string.replace(0, "<=", " le ");
+
+ string.replace(0, " < ", " lt ");
+ string.replace(0, " <", " lt ");
+ string.replace(0, "< ", " lt ");
+ string.replace(0, "<", " lt ");
+
+ string.replace(0, " << ", " lshift ");
+ string.replace(0, " <<", " lshift ");
+ string.replace(0, "<< ", " lshift ");
+ string.replace(0, "<<", " lshift ");
+
+ return string;
+}
+
+
+//-------------------------------------------------
+// execute_frombcd - convert a value from BCD
+//-------------------------------------------------
+
+UINT64 cheat_manager::execute_frombcd(symbol_table &table, void *ref, int params, const UINT64 *param)
+{
+ UINT64 value = param[0];
+ UINT64 multiplier = 1;
+ UINT64 result = 0;
+
+ while (value != 0)
+ {
+ result += (value & 0x0f) * multiplier;
+ value >>= 4;
+ multiplier *= 10;
+ }
+ return result;
+}
+
+
+//-------------------------------------------------
+// execute_tobcd - convert a value to BCD
+//-------------------------------------------------
+
+UINT64 cheat_manager::execute_tobcd(symbol_table &table, void *ref, int params, const UINT64 *param)
+{
+ UINT64 value = param[0];
+ UINT64 result = 0;
+ UINT8 shift = 0;
+
+ while (value != 0)
+ {
+ result += (value % 10) << shift;
+ value /= 10;
+ shift += 4;
+ }
+ return result;
+}
+
+
+//-------------------------------------------------
+// frame_update - per-frame callback
+//-------------------------------------------------
+
+void cheat_manager::frame_update()
+{
+ // set up for accumulating output
+ m_lastline = 0;
+ m_numlines = floor(1.0f / ui_get_line_height(machine()));
+ m_numlines = MIN(m_numlines, ARRAY_LENGTH(m_output));
+ for (int linenum = 0; linenum < ARRAY_LENGTH(m_output); linenum++)
+ m_output[linenum].reset();
+
+ // iterate over running cheats and execute them
+ for (cheat_entry *cheat = m_cheatlist.first(); cheat != NULL; cheat = cheat->next())
+ cheat->frame_update();
+
+ // increment the frame counter
+ m_framecount++;
+}
+
+
+//-------------------------------------------------
+// load_cheats - load a cheat file into memory
+// and create the cheat entry list
+//-------------------------------------------------
+
+void cheat_manager::load_cheats(const char *filename)
+{
+ xml_data_node *rootnode = NULL;
+ emu_file cheatfile(machine().options().cheat_path(), OPEN_FLAG_READ);
+ try
+ {
+ // open the file with the proper name
+ file_error filerr = cheatfile.open(filename, ".xml");
+
+ // loop over all instrances of the files found in our search paths
+ while (filerr == FILERR_NONE)
+ {
+ mame_printf_verbose("Loading cheats file from %s\n", cheatfile.fullpath());
+
+ // read the XML file into internal data structures
+ xml_parse_options options = { 0 };
+ xml_parse_error error;
+ options.error = &error;
+ rootnode = xml_file_read(cheatfile, &options);
+
+ // if unable to parse the file, just bail
+ if (rootnode == NULL)
+ throw emu_fatalerror("%s.xml(%d): error parsing XML (%s)\n", filename, error.error_line, error.error_message);
+
+ // find the layout node
+ xml_data_node *mamecheatnode = xml_get_sibling(rootnode->child, "mamecheat");
+ if (mamecheatnode == NULL)
+ throw emu_fatalerror("%s.xml: missing mamecheatnode node", filename);
+
+ // validate the config data version
+ int version = xml_get_attribute_int(mamecheatnode, "version", 0);
+ if (version != CHEAT_VERSION)
+ throw emu_fatalerror("%s.xml(%d): Invalid cheat XML file: unsupported version", filename, mamecheatnode->line);
+
+ // parse all the elements
+ for (xml_data_node *cheatnode = xml_get_sibling(mamecheatnode->child, "cheat"); cheatnode != NULL; cheatnode = xml_get_sibling(cheatnode->next, "cheat"))
+ {
+ // load this entry
+ cheat_entry *curcheat = auto_alloc(machine(), cheat_entry(*this, m_symtable, filename, *cheatnode));
+
+ // make sure we're not a duplicate
+ cheat_entry *scannode = NULL;
+ if (REMOVE_DUPLICATE_CHEATS)
+ for (scannode = m_cheatlist.first(); scannode != NULL; scannode = scannode->next())
+ if (strcmp(scannode->description(), curcheat->description()) == 0)
+ {
+ mame_printf_verbose("Ignoring duplicate cheat '%s' from file %s\n", curcheat->description(), cheatfile.fullpath());
+ break;
+ }
+
+ // add to the end of the list
+ if (scannode == NULL)
+ m_cheatlist.append(*curcheat);
+ else
+ auto_free(machine(), curcheat);
+ }
+
+ // free the file and loop for the next one
+ xml_file_free(rootnode);
+
+ // open the next file in sequence
+ filerr = cheatfile.open_next();
+ }
+ }
+
+ // handle errors cleanly
+ catch (emu_fatalerror &err)
+ {
+ mame_printf_error("%s\n", err.string());
+ m_cheatlist.reset();
+ if (rootnode != NULL)
+ xml_file_free(rootnode);
+ }
+}
diff --git a/trunk/src/emu/cheat.h b/trunk/src/emu/cheat.h
new file mode 100644
index 00000000000..b405e96e5fd
--- /dev/null
+++ b/trunk/src/emu/cheat.h
@@ -0,0 +1,365 @@
+/***************************************************************************
+
+ cheat.h
+
+ Cheat system.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __CHEAT_H__
+#define __CHEAT_H__
+
+#include "debug/express.h"
+#include "ui.h"
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+enum script_state
+{
+ SCRIPT_STATE_OFF = 0,
+ SCRIPT_STATE_ON,
+ SCRIPT_STATE_RUN,
+ SCRIPT_STATE_CHANGE,
+ SCRIPT_STATE_COUNT
+};
+DECLARE_ENUM_OPERATORS(script_state)
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class cheat_manager;
+
+
+// ======================> number_and_format
+
+// helper class to remember a format along with a number
+class number_and_format
+{
+public:
+ // construction/destruction
+ number_and_format(UINT64 value = 0, int format = 0)
+ : m_value(value),
+ m_format(format) { }
+
+ // pass-through to look like a regular number
+ operator UINT64 &() { return m_value; }
+ operator const UINT64 &() const { return m_value; }
+
+ // format the number according to its format
+ const char *format(astring &string) const;
+
+private:
+ // internal state
+ UINT64 m_value;
+ int m_format;
+};
+
+
+// ======================> cheat_parameter
+
+// a parameter for a cheat, which can be set in the UI
+class cheat_parameter
+{
+public:
+ // construction/destruction
+ cheat_parameter(cheat_manager &manager, symbol_table &symbols, const char *filename, xml_data_node &paramnode);
+
+ // queries
+ const char *text();
+ bool has_itemlist() const { return (m_itemlist.count() != 0); }
+ bool is_minimum() const { return (m_value == ((m_itemlist.count() == 0) ? m_minval : m_itemlist.first()->value())); }
+ bool is_maximum() const { return (m_value == ((m_itemlist.count() == 0) ? m_maxval : m_itemlist.last()->value())); }
+
+ // state setters
+ bool set_minimum_state();
+ bool set_prev_state();
+ bool set_next_state();
+
+ // actions
+ void save(emu_file &cheatfile) const;
+
+private:
+ // a single item in a parameter item list
+ class item
+ {
+ friend class simple_list<item>;
+
+ public:
+ // construction/destruction
+ item(const char *text, UINT64 value, int valformat)
+ : m_next(NULL),
+ m_text(text),
+ m_value(value, valformat) { }
+
+ // getters
+ item *next() const { return m_next; }
+ const number_and_format &value() const { return m_value; }
+ const char *text() const { return m_text; }
+
+ private:
+ // internal state
+ item * m_next; // next item in list
+ astring m_text; // name of the item
+ number_and_format m_value; // value of the item
+ };
+
+ // internal state
+ number_and_format m_minval; // minimum value
+ number_and_format m_maxval; // maximum value
+ number_and_format m_stepval; // step value
+ UINT64 m_value; // live value of the parameter
+ astring m_curtext; // holding for a value string
+ simple_list<item> m_itemlist; // list of items
+};
+
+
+// ======================> cheat_script
+
+// a script entry, specifying which state to execute under
+class cheat_script
+{
+ friend class simple_list<cheat_script>;
+
+public:
+ // construction/destruction
+ cheat_script(cheat_manager &manager, symbol_table &symbols, const char *filename, xml_data_node &scriptnode);
+
+ // getters
+ script_state state() const { return m_state; }
+
+ // actions
+ void execute(cheat_manager &manager, UINT64 &argindex);
+ void save(emu_file &cheatfile) const;
+
+private:
+ // an entry within the script
+ class script_entry
+ {
+ friend class simple_list<script_entry>;
+
+ public:
+ // construction/destruction
+ script_entry(cheat_manager &manager, symbol_table &symbols, const char *filename, xml_data_node &entrynode, bool isaction);
+
+ // getters
+ script_entry *next() const { return m_next; }
+
+ // actions
+ void execute(cheat_manager &manager, UINT64 &argindex);
+ void save(emu_file &cheatfile) const;
+
+ private:
+ // an argument for output
+ class output_argument
+ {
+ friend class simple_list<output_argument>;
+
+ public:
+ // construction/destruction
+ output_argument(cheat_manager &manager, symbol_table &symbols, const char *filename, xml_data_node &argnode);
+
+ // getters
+ output_argument *next() const { return m_next; }
+ int count() const { return m_count; }
+ int values(UINT64 &argindex, UINT64 *result);
+
+ // actions
+ void save(emu_file &cheatfile) const;
+
+ private:
+ // internal state
+ output_argument * m_next; // link to next argument
+ parsed_expression m_expression; // expression for argument
+ UINT64 m_count; // number of repetitions
+ };
+
+ // internal helpers
+ void validate_format(const char *filename, int line);
+
+ // internal state
+ script_entry * m_next; // link to next entry
+ parsed_expression m_condition; // condition under which this is executed
+ parsed_expression m_expression; // expression to execute
+ astring m_format; // string format to print
+ simple_list<output_argument> m_arglist; // list of arguments
+ INT8 m_line; // which line to print on
+ UINT8 m_justify; // justification when printing
+
+ // constants
+ static const int MAX_ARGUMENTS = 32;
+ };
+
+ // internal state
+ simple_list<script_entry> m_entrylist; // list of actions to perform
+ script_state m_state; // which state this script is for
+};
+
+
+// ======================> cheat_entry
+
+// a single cheat
+class cheat_entry
+{
+ friend class simple_list<cheat_entry>;
+
+public:
+ // construction/destruction
+ cheat_entry(cheat_manager &manager, symbol_table &globaltable, const char *filename, xml_data_node &cheatnode);
+ ~cheat_entry();
+
+ // getters
+ cheat_manager &manager() const { return m_manager; }
+ cheat_entry *next() const { return m_next; }
+ script_state state() const { return m_state; }
+ const char *description() const { return m_description; }
+ const char *comment() const { return m_comment; }
+
+ // script detection
+ bool has_run_script() const { return (m_run_script != NULL); }
+ bool has_on_script() const { return (m_on_script != NULL); }
+ bool has_off_script() const { return (m_off_script != NULL); }
+ bool has_change_script() const { return (m_change_script != NULL); }
+
+ // script execution
+ void execute_off_script() { if (has_off_script()) m_off_script->execute(m_manager, m_argindex); }
+ void execute_on_script() { if (has_on_script()) m_on_script->execute(m_manager, m_argindex); }
+ void execute_run_script() { if (has_run_script()) m_run_script->execute(m_manager, m_argindex); }
+ void execute_change_script() { if (has_change_script()) m_change_script->execute(m_manager, m_argindex); }
+
+ // cheat classification
+ bool is_text_only() const { return (m_parameter == NULL && !has_run_script() && !has_off_script() && !has_on_script()); }
+ bool is_oneshot() const { return (m_parameter == NULL && !has_run_script() && !has_off_script() && has_on_script()); }
+ bool is_onoff() const { return (m_parameter == NULL && (has_run_script() || (has_off_script() && has_on_script()))); }
+ bool is_value_parameter() const { return (m_parameter != NULL && !m_parameter->has_itemlist()); }
+ bool is_itemlist_parameter() const { return (m_parameter != NULL && m_parameter->has_itemlist()); }
+ bool is_oneshot_parameter() const { return (m_parameter != NULL && !has_run_script() && !has_off_script() && has_change_script()); }
+
+ // actions
+ bool activate();
+ bool select_default_state();
+ bool select_previous_state();
+ bool select_next_state();
+ void save(emu_file &cheatfile) const;
+
+ // UI helpers
+ void menu_text(astring &description, astring &state, UINT32 &flags);
+
+ // per-frame update
+ void frame_update() { if (m_state == SCRIPT_STATE_RUN) execute_run_script(); }
+
+private:
+ // internal helpers
+ bool set_state(script_state newstate);
+ cheat_script *&script_for_state(script_state state);
+
+ // internal state
+ cheat_manager & m_manager; // reference to our manager
+ cheat_entry * m_next; // next cheat entry
+ astring m_description; // string description/menu title
+ astring m_comment; // comment data
+ cheat_parameter * m_parameter; // parameter
+ cheat_script * m_on_script; // script to run when turning on
+ cheat_script * m_off_script; // script to run when turning off
+ cheat_script * m_change_script; // script to run when value changes
+ cheat_script * m_run_script; // script to run each frame when on
+ symbol_table m_symbols; // symbol table for this cheat
+ script_state m_state; // current cheat state
+ UINT32 m_numtemp; // number of temporary variables
+ UINT64 m_argindex; // argument index variable
+
+ // constants
+ static const int DEFAULT_TEMP_VARIABLES = 10;
+};
+
+
+// ======================> cheat_manager
+
+// private machine-global data
+class cheat_manager
+{
+public:
+ // construction/destruction
+ cheat_manager(running_machine &machine);
+
+ // getters
+ running_machine &machine() const { return m_machine; }
+ bool enabled() const { return !m_disabled; }
+ cheat_entry *first() const { return m_cheatlist.first(); }
+
+ // setters
+ void set_enable(bool enable = true);
+
+ // actions
+ void reload();
+ bool save_all(const char *filename);
+ void render_text(render_container &container);
+
+ // output helpers
+ astring &get_output_astring(int row, int justify);
+
+ // global helpers
+ static const char *quote_expression(astring &string, const parsed_expression &expression);
+ static UINT64 execute_frombcd(symbol_table &table, void *ref, int params, const UINT64 *param);
+ static UINT64 execute_tobcd(symbol_table &table, void *ref, int params, const UINT64 *param);
+
+private:
+ // internal helpers
+ void frame_update();
+ void load_cheats(const char *filename);
+
+ // internal state
+ running_machine & m_machine; // reference to our machine
+ simple_list<cheat_entry> m_cheatlist; // cheat list
+ UINT64 m_framecount; // frame count
+ astring m_output[UI_TARGET_FONT_ROWS*2]; // array of output strings
+ UINT8 m_justify[UI_TARGET_FONT_ROWS*2]; // justification for each string
+ UINT8 m_numlines; // number of lines available for output
+ INT8 m_lastline; // last line used for output
+ bool m_disabled; // true if the cheat engine is disabled
+ symbol_table m_symtable; // global symbol table
+
+ // constants
+ static const int CHEAT_VERSION = 1;
+};
+
+
+#endif /* __CHEAT_H__ */
diff --git a/trunk/src/emu/clifront.c b/trunk/src/emu/clifront.c
new file mode 100644
index 00000000000..356524a0a14
--- /dev/null
+++ b/trunk/src/emu/clifront.c
@@ -0,0 +1,1673 @@
+/***************************************************************************
+
+ clifront.c
+
+ Command-line interface frontend for MAME.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "emuopts.h"
+#include "hash.h"
+#include "jedparse.h"
+#include "audit.h"
+#include "info.h"
+#include "unzip.h"
+#include "validity.h"
+#include "sound/samples.h"
+#include "clifront.h"
+#include "xmlfile.h"
+
+#include <new>
+#include <ctype.h>
+
+
+//**************************************************************************
+// COMMAND-LINE OPTIONS
+//**************************************************************************
+
+const options_entry cli_options::s_option_entries[] =
+{
+ /* core commands */
+ { NULL, NULL, OPTION_HEADER, "CORE COMMANDS" },
+ { CLICOMMAND_HELP ";h;?", "0", OPTION_COMMAND, "show help message" },
+ { CLICOMMAND_VALIDATE ";valid", "0", OPTION_COMMAND, "perform driver validation on all game drivers" },
+
+ /* configuration commands */
+ { NULL, NULL, OPTION_HEADER, "CONFIGURATION COMMANDS" },
+ { CLICOMMAND_CREATECONFIG ";cc", "0", OPTION_COMMAND, "create the default configuration file" },
+ { CLICOMMAND_SHOWCONFIG ";sc", "0", OPTION_COMMAND, "display running parameters" },
+ { CLICOMMAND_SHOWUSAGE ";su", "0", OPTION_COMMAND, "show this help" },
+
+ /* frontend commands */
+ { NULL, NULL, OPTION_HEADER, "FRONTEND COMMANDS" },
+ { CLICOMMAND_LISTXML ";lx", "0", OPTION_COMMAND, "all available info on driver in XML format" },
+ { CLICOMMAND_LISTFULL ";ll", "0", OPTION_COMMAND, "short name, full name" },
+ { CLICOMMAND_LISTSOURCE ";ls", "0", OPTION_COMMAND, "driver sourcefile" },
+ { CLICOMMAND_LISTCLONES ";lc", "0", OPTION_COMMAND, "show clones" },
+ { CLICOMMAND_LISTBROTHERS ";lb", "0", OPTION_COMMAND, "show \"brothers\", or other drivers from same sourcefile" },
+ { CLICOMMAND_LISTCRC, "0", OPTION_COMMAND, "CRC-32s" },
+ { CLICOMMAND_LISTROMS, "0", OPTION_COMMAND, "list required roms for a driver" },
+ { CLICOMMAND_LISTSAMPLES, "0", OPTION_COMMAND, "list optional samples for a driver" },
+ { CLICOMMAND_VERIFYROMS, "0", OPTION_COMMAND, "report romsets that have problems" },
+ { CLICOMMAND_VERIFYSAMPLES, "0", OPTION_COMMAND, "report samplesets that have problems" },
+ { CLICOMMAND_ROMIDENT, "0", OPTION_COMMAND, "compare files with known MAME roms" },
+ { CLICOMMAND_LISTDEVICES ";ld", "0", OPTION_COMMAND, "list available devices" },
+ { CLICOMMAND_LISTSLOTS ";lslot", "0", OPTION_COMMAND, "list available slots and slot devices" },
+ { CLICOMMAND_LISTMEDIA ";lm", "0", OPTION_COMMAND, "list available media for the system" },
+ { CLICOMMAND_LISTSOFTWARE ";lsoft", "0", OPTION_COMMAND, "list known software for the system" },
+
+ { NULL }
+};
+
+
+
+//**************************************************************************
+// CLI OPTIONS
+//**************************************************************************
+
+//-------------------------------------------------
+// cli_options - constructor
+//-------------------------------------------------
+
+cli_options::cli_options()
+{
+ add_entries(s_option_entries);
+}
+
+
+
+//**************************************************************************
+// CLI FRONTEND
+//**************************************************************************
+
+//-------------------------------------------------
+// cli_frontend - constructor
+//-------------------------------------------------
+
+cli_frontend::cli_frontend(cli_options &options, osd_interface &osd)
+ : m_options(options),
+ m_osd(osd),
+ m_result(MAMERR_NONE)
+{
+ // begin tracking memory
+ track_memory(true);
+}
+
+
+//-------------------------------------------------
+// ~cli_frontend - destructor
+//-------------------------------------------------
+
+cli_frontend::~cli_frontend()
+{
+ // report any unfreed memory on clean exits
+ track_memory(false);
+ if (m_result == MAMERR_NONE)
+ dump_unfreed_mem();
+}
+
+
+//-------------------------------------------------
+// execute - execute a game via the standard
+// command line interface
+//-------------------------------------------------
+
+int cli_frontend::execute(int argc, char **argv)
+{
+ // wrap the core execution in a try/catch to field all fatal errors
+ m_result = MAMERR_NONE;
+ try
+ {
+ // parse the command line, adding any system-specific options
+ astring option_errors;
+ if (!m_options.parse_command_line(argc, argv, option_errors))
+ {
+ // if we failed, check for no command and a system name first; in that case error on the name
+ if (strlen(m_options.command()) == 0 && m_options.system() == NULL && strlen(m_options.system_name()) > 0)
+ throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "Unknown system '%s'", m_options.system_name());
+
+ // otherwise, error on the options
+ throw emu_fatalerror(MAMERR_INVALID_CONFIG, "%s", option_errors.trimspace().cstr());
+ }
+ if (option_errors)
+ printf("Error in command line:\n%s\n", option_errors.trimspace().cstr());
+
+ // determine the base name of the EXE
+ astring exename;
+ core_filename_extract_base(&exename, argv[0], TRUE);
+
+ // if we have a command, execute that
+ if (strlen(m_options.command()) != 0)
+ execute_commands(exename);
+
+ // otherwise, check for a valid system
+ else
+ {
+ // if we can't find it, give an appropriate error
+ const game_driver *system = m_options.system();
+ if (system == NULL && strlen(m_options.system_name()) > 0)
+ throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "Unknown system '%s'", m_options.system_name());
+
+ if (strlen(m_options.software_name()) > 0) {
+ machine_config config(*system, m_options);
+ if (!config.devicelist().first(SOFTWARE_LIST))
+ throw emu_fatalerror(MAMERR_FATALERROR, "Error: unknown option: %s\n", m_options.software_name());
+
+ bool found = FALSE;
+ for (device_t *swlists = config.devicelist().first(SOFTWARE_LIST); swlists != NULL; swlists = swlists->typenext())
+ {
+ software_list_config *swlist = (software_list_config *)downcast<const legacy_device_base *>(swlists)->inline_config();
+
+ for (int i = 0; i < DEVINFO_STR_SWLIST_MAX - DEVINFO_STR_SWLIST_0; i++)
+ {
+ if (swlist->list_name[i] && *swlist->list_name[i])
+ {
+ software_list *list = software_list_open(m_options, swlist->list_name[i], FALSE, NULL);
+
+ if (list)
+ {
+ software_info *swinfo = software_list_find(list, m_options.software_name(), NULL);
+ if (swinfo!=NULL) {
+ for (software_part *swpart = software_find_part(swinfo, NULL, NULL); swpart != NULL; swpart = software_part_next(swpart))
+ {
+ const char *mount = software_part_get_feature(swpart, "automount");
+ if (mount==NULL || strcmp(mount,"no")!=0) {
+ // loop trough all parts
+ // search for a device with the right interface
+ const device_image_interface *image = NULL;
+ for (bool gotone = config.devicelist().first(image); gotone; gotone = image->next(image))
+ {
+ const char *interface = image->image_interface();
+ if (interface != NULL)
+ {
+ if (!strcmp(interface, swpart->interface_))
+ {
+ const char *option = m_options.value(image->brief_instance_name());
+ // mount only if not already mounted
+ if (strlen(option)==0) {
+ astring val;
+ val.printf("%s:%s",m_options.software_name(),swpart->name);
+ // call this in order to set slot devices according to mounting
+ m_options.parse_slot_devices(argc, argv, option_errors, image->instance_name(), val.cstr());
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ software_list_close(list);
+ found = TRUE;
+ break;
+ }
+
+ }
+ software_list_close(list);
+ }
+ if (found) break;
+ }
+ if (found) break;
+ }
+ if (!found) {
+ software_display_matches(config.devicelist(),m_options, NULL,m_options.software_name());
+ throw emu_fatalerror(MAMERR_FATALERROR, "");
+ }
+ }
+ // otherwise just run the game
+ m_result = mame_execute(m_options, m_osd);
+ }
+ }
+
+ // handle exceptions of various types
+ catch (emu_fatalerror &fatal)
+ {
+ astring string(fatal.string());
+ fprintf(stderr, "%s\n", string.trimspace().cstr());
+ m_result = (fatal.exitcode() != 0) ? fatal.exitcode() : MAMERR_FATALERROR;
+
+ // if a game was specified, wasn't a wildcard, and our error indicates this was the
+ // reason for failure, offer some suggestions
+ if (m_result == MAMERR_NO_SUCH_GAME && strlen(m_options.system_name()) > 0 && strchr(m_options.system_name(), '*') == NULL && m_options.system() == NULL)
+ {
+ // get the top 10 approximate matches
+ driver_enumerator drivlist(m_options);
+ int matches[10];
+ drivlist.find_approximate_matches(m_options.system_name(), ARRAY_LENGTH(matches), matches);
+
+ // print them out
+ fprintf(stderr, "\n\"%s\" approximately matches the following\n"
+ "supported " GAMESNOUN " (best match first):\n\n", m_options.system_name());
+ for (int matchnum = 0; matchnum < ARRAY_LENGTH(matches); matchnum++)
+ if (matches[matchnum] != -1)
+ fprintf(stderr, "%-18s%s\n", drivlist.driver(matches[matchnum]).name, drivlist.driver(matches[matchnum]).description);
+ }
+ }
+ catch (emu_exception &)
+ {
+ fprintf(stderr, "Caught unhandled emulator exception\n");
+ m_result = MAMERR_FATALERROR;
+ }
+ catch (std::bad_alloc &)
+ {
+ fprintf(stderr, "Out of memory!\n");
+ m_result = MAMERR_FATALERROR;
+ }
+
+ // handle any other exceptions
+ catch (...)
+ {
+ fprintf(stderr, "Caught unhandled exception\n");
+ m_result = MAMERR_FATALERROR;
+ }
+
+ return m_result;
+}
+
+
+//-------------------------------------------------
+// listxml - output the XML data for one or more
+// games
+//-------------------------------------------------
+
+void cli_frontend::listxml(const char *gamename)
+{
+ // determine which drivers to output; return an error if none found
+ driver_enumerator drivlist(m_options, gamename);
+ if (drivlist.count() == 0)
+ throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
+
+ // create the XML and print it to stdout
+ info_xml_creator creator(drivlist);
+ creator.output(stdout);
+}
+
+
+//-------------------------------------------------
+// listfull - output the name and description of
+// one or more games
+//-------------------------------------------------
+
+void cli_frontend::listfull(const char *gamename)
+{
+ // determine which drivers to output; return an error if none found
+ driver_enumerator drivlist(m_options, gamename);
+ if (drivlist.count() == 0)
+ throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
+
+ // print the header
+ mame_printf_info("Name: Description:\n");
+
+ // iterate through drivers and output the info
+ while (drivlist.next())
+ if ((drivlist.driver().flags & GAME_NO_STANDALONE) == 0)
+ mame_printf_info("%-18s\"%s\"\n", drivlist.driver().name, drivlist.driver().description);
+}
+
+
+//-------------------------------------------------
+// listsource - output the name and source
+// filename of one or more games
+//-------------------------------------------------
+
+void cli_frontend::listsource(const char *gamename)
+{
+ // determine which drivers to output; return an error if none found
+ driver_enumerator drivlist(m_options, gamename);
+ if (drivlist.count() == 0)
+ throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
+
+ // iterate through drivers and output the info
+ astring filename;
+ while (drivlist.next())
+ mame_printf_info("%-16s %s\n", drivlist.driver().name, core_filename_extract_base(&filename, drivlist.driver().source_file, FALSE)->cstr());
+}
+
+
+//-------------------------------------------------
+// listclones - output the name and parent of all
+// clones matching the given pattern
+//-------------------------------------------------
+
+void cli_frontend::listclones(const char *gamename)
+{
+ // start with a filtered list of drivers
+ driver_enumerator drivlist(m_options, gamename);
+ int original_count = drivlist.count();
+
+ // iterate through the remaining ones to see if their parent matches
+ while (drivlist.next_excluded())
+ {
+ // if we have a non-bios clone and it matches, keep it
+ int clone_of = drivlist.clone();
+ if (clone_of != -1 && (drivlist.driver(clone_of).flags & GAME_IS_BIOS_ROOT) == 0)
+ if (drivlist.matches(gamename, drivlist.driver(clone_of).name))
+ drivlist.include();
+ }
+
+ // return an error if none found
+ if (drivlist.count() == 0)
+ {
+ // see if we match but just weren't a clone
+ if (original_count == 0)
+ throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
+ else
+ mame_printf_info("Found %d matches for '%s' but none were clones\n", drivlist.count(), gamename);
+ return;
+ }
+
+ // print the header
+ mame_printf_info("Name: Clone of:\n");
+
+ // iterate through drivers and output the info
+ drivlist.reset();
+ while (drivlist.next())
+ {
+ int clone_of = drivlist.clone();
+ if (clone_of != -1 && (drivlist.driver(clone_of).flags & GAME_IS_BIOS_ROOT) == 0)
+ mame_printf_info("%-16s %-8s\n", drivlist.driver().name, drivlist.driver(clone_of).name);
+ }
+}
+
+
+//-------------------------------------------------
+// listbrothers - for each matching game, output
+// the list of other games that share the same
+// source file
+//-------------------------------------------------
+
+void cli_frontend::listbrothers(const char *gamename)
+{
+ // start with a filtered list of drivers; return an error if none found
+ driver_enumerator initial_drivlist(m_options, gamename);
+ if (initial_drivlist.count() == 0)
+ throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
+
+ // for the final list, start with an empty driver list
+ driver_enumerator drivlist(m_options);
+ drivlist.exclude_all();
+
+ // scan through the initially-selected drivers
+ while (initial_drivlist.next())
+ {
+ // if we are already marked in the final list, we don't need to do anything
+ if (drivlist.included(initial_drivlist.current()))
+ continue;
+
+ // otherwise, walk excluded items in the final list and mark any that match
+ drivlist.reset();
+ while (drivlist.next_excluded())
+ if (strcmp(drivlist.driver().source_file, initial_drivlist.driver().source_file) == 0)
+ drivlist.include();
+ }
+
+ // print the header
+ mame_printf_info("Source file: Name: Parent:\n");
+
+ // output the entries found
+ drivlist.reset();
+ astring filename;
+ while (drivlist.next())
+ {
+ int clone_of = drivlist.clone();
+ mame_printf_info("%-16s %-16s %-16s\n", core_filename_extract_base(&filename, drivlist.driver().source_file, FALSE)->cstr(), drivlist.driver().name, (clone_of == -1 ? "" : drivlist.driver(clone_of).name));
+ }
+}
+
+
+//-------------------------------------------------
+// listcrc - output the CRC and name of all ROMs
+// referenced by the emulator
+//-------------------------------------------------
+
+void cli_frontend::listcrc(const char *gamename)
+{
+ // determine which drivers to output; return an error if none found
+ driver_enumerator drivlist(m_options, gamename);
+ if (drivlist.count() == 0)
+ throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
+
+ // iterate through matches, and then through ROMs
+ while (drivlist.next())
+ for (const rom_source *source = rom_first_source(drivlist.config()); source != NULL; source = rom_next_source(*source))
+ {
+ bool isdriver = (source == rom_first_source(drivlist.config()));
+ for (const rom_entry *region = rom_first_region(*source); region; region = rom_next_region(region))
+ for (const rom_entry *rom = rom_first_file(region); rom; rom = rom_next_file(rom))
+ {
+ // if we have a CRC, display it
+ UINT32 crc;
+ if (hash_collection(ROM_GETHASHDATA(rom)).crc(crc))
+ mame_printf_info("%08x %-16s %s\n", crc, ROM_GETNAME(rom), isdriver ? drivlist.driver().description : source->name());
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// listroms - output the list of ROMs referenced
+// by a given game or set of games
+//-------------------------------------------------
+
+void cli_frontend::listroms(const char *gamename)
+{
+ // determine which drivers to output; return an error if none found
+ driver_enumerator drivlist(m_options, gamename);
+ if (drivlist.count() == 0)
+ throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
+
+ // iterate through matches
+ astring tempstr;
+ bool first = true;
+ while (drivlist.next())
+ {
+ // print a header
+ if (!first)
+ mame_printf_info("\n");
+ first = false;
+ mame_printf_info("ROMs required for driver \"%s\".\n"
+ "Name Size Checksum\n", drivlist.driver().name);
+
+ // iterate through roms
+ for (const rom_source *source = rom_first_source(drivlist.config()); source != NULL; source = rom_next_source(*source))
+ for (const rom_entry *region = rom_first_region(*source); region; region = rom_next_region(region))
+ for (const rom_entry *rom = rom_first_file(region); rom; rom = rom_next_file(rom))
+ {
+ // accumulate the total length of all chunks
+ int length = -1;
+ if (ROMREGION_ISROMDATA(region))
+ length = rom_file_size(rom);
+
+ // start with the name
+ const char *name = ROM_GETNAME(rom);
+ mame_printf_info("%-20s ", name);
+
+ // output the length next
+ if (length >= 0)
+ mame_printf_info("%7d", length);
+ else
+ mame_printf_info(" ");
+
+ // output the hash data
+ hash_collection hashes(ROM_GETHASHDATA(rom));
+ if (!hashes.flag(hash_collection::FLAG_NO_DUMP))
+ {
+ if (hashes.flag(hash_collection::FLAG_BAD_DUMP))
+ mame_printf_info(" BAD");
+ mame_printf_info(" %s", hashes.macro_string(tempstr));
+ }
+ else
+ mame_printf_info(" NO GOOD DUMP KNOWN");
+
+ // end with a CR
+ mame_printf_info("\n");
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// listsamples - output the list of samples
+// referenced by a given game or set of games
+//-------------------------------------------------
+
+void cli_frontend::listsamples(const char *gamename)
+{
+ // determine which drivers to output; return an error if none found
+ driver_enumerator drivlist(m_options, gamename);
+ if (drivlist.count() == 0)
+ throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
+
+ // iterate over drivers, looking for SAMPLES devices
+ bool first = true;
+ while (drivlist.next())
+ {
+ // see if we have samples
+ const device_t *device;
+ for (device = drivlist.config().first_device(); device != NULL; device = device->next())
+ if (device->type() == SAMPLES)
+ break;
+ if (device == NULL)
+ continue;
+
+ // print a header
+ if (!first)
+ mame_printf_info("\n");
+ first = false;
+ mame_printf_info("Samples required for driver \"%s\".\n", drivlist.driver().name);
+
+ // iterate over samples devices
+ for ( ; device != NULL; device = device->next())
+ if (device->type() == SAMPLES)
+ {
+ // if the list is legit, walk it and print the sample info
+ const char *const *samplenames = reinterpret_cast<const samples_interface *>(device->static_config())->samplenames;
+ if (samplenames != NULL)
+ for (int sampnum = 0; samplenames[sampnum] != NULL; sampnum++)
+ if (samplenames[sampnum][0] != '*')
+ mame_printf_info("%s\n", samplenames[sampnum]);
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// listdevices - output the list of devices
+// referenced by a given game or set of games
+//-------------------------------------------------
+
+void cli_frontend::listdevices(const char *gamename)
+{
+ // determine which drivers to output; return an error if none found
+ driver_enumerator drivlist(m_options, gamename);
+ if (drivlist.count() == 0)
+ throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
+
+ // iterate over drivers, looking for SAMPLES devices
+ bool first = true;
+ while (drivlist.next())
+ {
+ // print a header
+ if (!first)
+ printf("\n");
+ first = false;
+ printf("Driver %s (%s):\n", drivlist.driver().name, drivlist.driver().description);
+
+ // iterate through devices
+ for (const device_t *device = drivlist.config().first_device(); device != NULL; device = device->next())
+ {
+ printf(" %s ('%s')", device->name(), device->tag());
+
+ UINT32 clock = device->clock();
+ if (clock >= 1000000000)
+ printf(" @ %d.%02d GHz\n", clock / 1000000000, (clock / 10000000) % 100);
+ else if (clock >= 1000000)
+ printf(" @ %d.%02d MHz\n", clock / 1000000, (clock / 10000) % 100);
+ else if (clock >= 1000)
+ printf(" @ %d.%02d kHz\n", clock / 1000, (clock / 10) % 100);
+ else if (clock > 0)
+ printf(" @ %d Hz\n", clock);
+ else
+ printf("\n");
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// listslots - output the list of slot devices
+// referenced by a given game or set of games
+//-------------------------------------------------
+
+void cli_frontend::listslots(const char *gamename)
+{
+ // determine which drivers to output; return an error if none found
+ driver_enumerator drivlist(m_options, gamename);
+ if (drivlist.count() == 0)
+ throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
+
+ // print header
+ printf(" SYSTEM SLOT NAME SLOT OPTIONS SLOT DEVICE NAME \n");
+ printf("---------- ----------- -------------- ----------------------\n");
+
+ // iterate over drivers
+ while (drivlist.next())
+ {
+ // iterate
+ const device_slot_interface *slot = NULL;
+ bool first = true;
+ for (bool gotone = drivlist.config().devicelist().first(slot); gotone; gotone = slot->next(slot))
+ {
+ // output the line, up to the list of extensions
+ printf("%-13s%-10s ", first ? drivlist.driver().name : "", slot->device().tag());
+
+ // get the options and print them
+ const slot_interface* intf = slot->get_slot_interfaces();
+ for (int i = 0; intf[i].name != NULL; i++)
+ {
+ device_t *dev = (*intf[i].devtype)(drivlist.config(), "dummy", drivlist.config().devicelist().first(), 0);
+ dev->config_complete();
+ if (i==0) {
+ printf("%-15s %s\n", intf[i].name,dev->name());
+ } else {
+ printf("%-23s %-15s %s\n", "",intf[i].name,dev->name());
+ }
+ global_free(dev);
+ }
+ // end the line
+ printf("\n");
+ first = false;
+ }
+
+ // if we didn't get any at all, just print a none line
+ if (first)
+ printf("%-13s(none)\n", drivlist.driver().name);
+ }
+}
+
+
+//-------------------------------------------------
+// listmedia - output the list of image devices
+// referenced by a given game or set of games
+//-------------------------------------------------
+
+void cli_frontend::listmedia(const char *gamename)
+{
+ // determine which drivers to output; return an error if none found
+ driver_enumerator drivlist(m_options, gamename);
+ if (drivlist.count() == 0)
+ throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
+
+ // print header
+ printf(" SYSTEM MEDIA NAME (brief) IMAGE FILE EXTENSIONS SUPPORTED \n");
+ printf("---------- -------------------- ------------------------------------\n");
+
+ // iterate over drivers
+ while (drivlist.next())
+ {
+ // iterate
+ const device_image_interface *imagedev = NULL;
+ bool first = true;
+ for (bool gotone = drivlist.config().devicelist().first(imagedev); gotone; gotone = imagedev->next(imagedev))
+ {
+ // extract the shortname with parentheses
+ astring paren_shortname;
+ paren_shortname.format("(%s)", imagedev->brief_instance_name());
+
+ // output the line, up to the list of extensions
+ printf("%-13s%-12s%-8s ", first ? drivlist.driver().name : "", imagedev->instance_name(), paren_shortname.cstr());
+
+ // get the extensions and print them
+ astring extensions(imagedev->file_extensions());
+ for (int start = 0, end = extensions.chr(0, ','); ; start = end + 1, end = extensions.chr(start, ','))
+ {
+ astring curext(extensions, start, (end == -1) ? extensions.len() - start : end - start);
+ printf(".%-5s", curext.cstr());
+ if (end == -1)
+ break;
+ }
+
+ // end the line
+ printf("\n");
+ first = false;
+ }
+
+ // if we didn't get any at all, just print a none line
+ if (first)
+ printf("%-13s(none)\n", drivlist.driver().name);
+ }
+}
+
+
+//-------------------------------------------------
+// verifyroms - verify the ROM sets of one or
+// more games
+//-------------------------------------------------
+extern int m_device_count;
+extern const device_type *s_devices_sorted[];
+
+void cli_frontend::verifyroms(const char *gamename)
+{
+ // determine which drivers to output;
+ driver_enumerator drivlist(m_options, gamename);
+
+ int correct = 0;
+ int incorrect = 0;
+ int notfound = 0;
+ int matched = 0;
+
+ // iterate over drivers
+ media_auditor auditor(drivlist);
+ while (drivlist.next())
+ {
+ matched++;
+
+ // audit the ROMs in this set
+ media_auditor::summary summary = auditor.audit_media(AUDIT_VALIDATE_FAST);
+
+ // if not found, count that and leave it at that
+ if (summary == media_auditor::NOTFOUND)
+ notfound++;
+
+ // else display information about what we discovered
+ else
+ {
+ // output the summary of the audit
+ astring summary_string;
+ auditor.summarize(drivlist.driver().name,&summary_string);
+ mame_printf_info("%s", summary_string.cstr());
+
+ // output the name of the driver and its clone
+ mame_printf_info("romset %s ", drivlist.driver().name);
+ int clone_of = drivlist.clone();
+ if (clone_of != -1)
+ mame_printf_info("[%s] ", drivlist.driver(clone_of).name);
+
+ // switch off of the result
+ switch (summary)
+ {
+ case media_auditor::INCORRECT:
+ mame_printf_info("is bad\n");
+ incorrect++;
+ break;
+
+ case media_auditor::CORRECT:
+ mame_printf_info("is good\n");
+ correct++;
+ break;
+
+ case media_auditor::BEST_AVAILABLE:
+ mame_printf_info("is best available\n");
+ correct++;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ driver_enumerator dummy_drivlist(m_options);
+ dummy_drivlist.next();
+ machine_config &config = dummy_drivlist.config();
+ device_t *owner = config.devicelist().first();
+ // check if all are listed, note that empty one is included
+ for (int i=0;i<m_device_count;i++)
+ {
+ device_type type = *s_devices_sorted[i];
+ device_t *dev = (*type)(config, "dummy", owner, 0);
+ dev->config_complete();
+
+ if (mame_strwildcmp(gamename, dev->shortname()) == 0)
+ {
+ matched++;
+
+ // audit the ROMs in this set
+ media_auditor::summary summary = auditor.audit_device(dev, AUDIT_VALIDATE_FAST);
+
+ // if not found, count that and leave it at that
+ if (summary == media_auditor::NOTFOUND)
+ notfound++;
+
+ // else display information about what we discovered
+ else
+ {
+ // output the summary of the audit
+ astring summary_string;
+ auditor.summarize(dev->shortname(),&summary_string);
+ mame_printf_info("%s", summary_string.cstr());
+
+ // display information about what we discovered
+ mame_printf_info("romset %s ", dev->shortname());
+
+ // switch off of the result
+ switch (summary)
+ {
+ case media_auditor::INCORRECT:
+ mame_printf_info("is bad\n");
+ incorrect++;
+ break;
+
+ case media_auditor::CORRECT:
+ mame_printf_info("is good\n");
+ correct++;
+ break;
+
+ case media_auditor::BEST_AVAILABLE:
+ mame_printf_info("is best available\n");
+ correct++;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ global_free(dev);
+ }
+
+ // clear out any cached files
+ zip_file_cache_clear();
+
+ // return an error if none found
+ if (matched==0)
+ throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
+
+ // if we didn't get anything at all, display a generic end message
+ if (correct + incorrect == 0)
+ {
+ if (notfound > 0)
+ throw emu_fatalerror(MAMERR_MISSING_FILES, "romset \"%s\" not found!\n", gamename);
+ else
+ throw emu_fatalerror(MAMERR_MISSING_FILES, "romset \"%s\" not supported!\n", gamename);
+ }
+
+ // otherwise, print a summary
+ else
+ {
+ if (incorrect > 0)
+ throw emu_fatalerror(MAMERR_MISSING_FILES, "%d romsets found, %d were OK.\n", correct + incorrect, correct);
+ mame_printf_info("%d romsets found, %d were OK.\n", correct, correct);
+ }
+}
+
+
+//-------------------------------------------------
+// info_verifysamples - verify the sample sets of
+// one or more games
+//-------------------------------------------------
+
+void cli_frontend::verifysamples(const char *gamename)
+{
+ // determine which drivers to output; return an error if none found
+ driver_enumerator drivlist(m_options, gamename);
+ if (drivlist.count() == 0)
+ throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
+
+ int correct = 0;
+ int incorrect = 0;
+ int notfound = 0;
+
+ // iterate over drivers
+ media_auditor auditor(drivlist);
+ while (drivlist.next())
+ {
+ // audit the samples in this set
+ media_auditor::summary summary = auditor.audit_samples();
+
+ // output the summary of the audit
+ astring summary_string;
+ auditor.summarize(drivlist.driver().name,&summary_string);
+ mame_printf_info("%s", summary_string.cstr());
+
+ // if not found, print a message and set the flag
+ if (summary == media_auditor::NOTFOUND)
+ {
+ mame_printf_error("sampleset \"%s\" not found!\n", drivlist.driver().name);
+ notfound++;
+ }
+
+ // else display information about what we discovered
+ else
+ {
+ // output the name of the driver and its clone
+ mame_printf_info("sampleset %s ", drivlist.driver().name);
+ int clone_of = drivlist.clone();
+ if (clone_of != -1)
+ mame_printf_info("[%s] ", drivlist.driver(clone_of).name);
+
+ // switch off of the result
+ switch (summary)
+ {
+ case media_auditor::INCORRECT:
+ mame_printf_info("is bad\n");
+ incorrect++;
+ break;
+
+ case media_auditor::CORRECT:
+ mame_printf_info("is good\n");
+ correct++;
+ break;
+
+ case media_auditor::BEST_AVAILABLE:
+ mame_printf_info("is best available\n");
+ correct++;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ // clear out any cached files
+ zip_file_cache_clear();
+
+ // if we didn't get anything at all, display a generic end message
+ if (correct + incorrect == 0)
+ {
+ if (notfound > 0)
+ throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "sampleset \"%s\" not found!\n", gamename);
+ else
+ throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "sampleset \"%s\" not supported!\n", gamename);
+ }
+
+ // otherwise, print a summary
+ else
+ {
+ if (incorrect > 0)
+ throw emu_fatalerror(MAMERR_MISSING_FILES, "%d samplesets found, %d were OK.\n", correct + incorrect, correct);
+ mame_printf_info("%d samplesets found, %d were OK.\n", correct, correct);
+ }
+}
+
+
+/*-------------------------------------------------
+ info_listsoftware - output the list of
+ software supported by a given game or set of
+ games
+ TODO: Add all information read from the source files
+ Possible improvement: use a sorted list for
+ identifying duplicate lists.
+-------------------------------------------------*/
+
+void cli_frontend::listsoftware(const char *gamename)
+{
+ FILE *out = stdout;
+
+ // determine which drivers to output; return an error if none found
+ driver_enumerator drivlist(m_options, gamename);
+ if (drivlist.count() == 0)
+ throw emu_fatalerror(MAMERR_NO_SUCH_GAME, "No matching games found for '%s'", gamename);
+
+ // first determine the maximum number of lists we might encounter
+ int list_count = 0;
+ while (drivlist.next())
+ for (const device_t *dev = drivlist.config().devicelist().first(SOFTWARE_LIST); dev != NULL; dev = dev->typenext())
+ {
+ software_list_config *swlist = (software_list_config *)downcast<const legacy_device_base *>(dev)->inline_config();
+
+ for (int listnum = 0; listnum < DEVINFO_STR_SWLIST_MAX - DEVINFO_STR_SWLIST_0; listnum++)
+ if (swlist->list_name[listnum] && *swlist->list_name[listnum] && swlist->list_type == SOFTWARE_LIST_ORIGINAL_SYSTEM)
+ list_count++;
+ }
+
+ // allocate a list
+ astring *lists = global_alloc_array(astring, list_count);
+
+ if (list_count)
+ {
+ fprintf( out,
+ "<?xml version=\"1.0\"?>\n"
+ "<!DOCTYPE softwarelist [\n"
+ "<!ELEMENT softwarelists (softwarelist*)>\n"
+ "\t<!ELEMENT softwarelist (software+)>\n"
+ "\t\t<!ATTLIST softwarelist name CDATA #REQUIRED>\n"
+ "\t\t<!ATTLIST softwarelist description CDATA #IMPLIED>\n"
+ "\t\t<!ELEMENT software (description, year?, publisher, info*, sharedfeat*, part*)>\n"
+ "\t\t\t<!ATTLIST software name CDATA #REQUIRED>\n"
+ "\t\t\t<!ATTLIST software cloneof CDATA #IMPLIED>\n"
+ "\t\t\t<!ATTLIST software supported (yes|partial|no) \"yes\">\n"
+ "\t\t\t<!ELEMENT description (#PCDATA)>\n"
+ "\t\t\t<!ELEMENT year (#PCDATA)>\n"
+ "\t\t\t<!ELEMENT publisher (#PCDATA)>\n"
+ // we still do not store the info strings internally, so there is no output here
+ // TODO: add parsing info in softlist.c and then add output here!
+ "\t\t\t<!ELEMENT info EMPTY>\n"
+ "\t\t\t\t<!ATTLIST info name CDATA #REQUIRED>\n"
+ "\t\t\t\t<!ATTLIST info value CDATA #IMPLIED>\n"
+ // shared features get stored in the part->feature below and are output there
+ // this means that we don't output any <sharedfeat> and that -lsoft output will
+ // be different from the list in hash/ when the list uses sharedfeat. But this
+ // is by design: sharedfeat is only available to simplify the life to list creators,
+ // to e.g. avoid manually adding the same feature to each disk of a 9 floppies game!
+ "\t\t\t<!ELEMENT sharedfeat EMPTY>\n"
+ "\t\t\t\t<!ATTLIST sharedfeat name CDATA #REQUIRED>\n"
+ "\t\t\t\t<!ATTLIST sharedfeat value CDATA #IMPLIED>\n"
+ "\t\t\t<!ELEMENT part (feature*, dataarea*, diskarea*, dipswitch*)>\n"
+ "\t\t\t\t<!ATTLIST part name CDATA #REQUIRED>\n"
+ "\t\t\t\t<!ATTLIST part interface CDATA #REQUIRED>\n"
+ "\t\t\t\t<!ELEMENT feature EMPTY>\n"
+ "\t\t\t\t\t<!ATTLIST feature name CDATA #REQUIRED>\n"
+ "\t\t\t\t\t<!ATTLIST feature value CDATA #IMPLIED>\n"
+ "\t\t\t\t<!ELEMENT dataarea (rom*)>\n"
+ "\t\t\t\t\t<!ATTLIST dataarea name CDATA #REQUIRED>\n"
+ "\t\t\t\t\t<!ATTLIST dataarea size CDATA #REQUIRED>\n"
+ "\t\t\t\t\t<!ATTLIST dataarea databits (8|16|32|64) \"8\">\n"
+ "\t\t\t\t\t<!ATTLIST dataarea endian (big|little) \"little\">\n"
+ "\t\t\t\t\t<!ELEMENT rom EMPTY>\n"
+ "\t\t\t\t\t\t<!ATTLIST rom name CDATA #IMPLIED>\n"
+ "\t\t\t\t\t\t<!ATTLIST rom size CDATA #IMPLIED>\n"
+ "\t\t\t\t\t\t<!ATTLIST rom length CDATA #IMPLIED>\n"
+ "\t\t\t\t\t\t<!ATTLIST rom crc CDATA #IMPLIED>\n"
+ "\t\t\t\t\t\t<!ATTLIST rom sha1 CDATA #IMPLIED>\n"
+ "\t\t\t\t\t\t<!ATTLIST rom offset CDATA #IMPLIED>\n"
+ "\t\t\t\t\t\t<!ATTLIST rom value CDATA #IMPLIED>\n"
+ "\t\t\t\t\t\t<!ATTLIST rom status (baddump|nodump|good) \"good\">\n"
+ "\t\t\t\t\t\t<!ATTLIST rom loadflag (load16_byte|load16_word|load16_word_swap|load32_byte|load32_word|load32_word_swap|load32_dword|load64_word|load64_word_swap|reload|fill|continue) #IMPLIED>\n"
+ "\t\t\t\t<!ELEMENT diskarea (disk*)>\n"
+ "\t\t\t\t\t<!ATTLIST diskarea name CDATA #REQUIRED>\n"
+ "\t\t\t\t\t<!ELEMENT disk EMPTY>\n"
+ "\t\t\t\t\t\t<!ATTLIST disk name CDATA #REQUIRED>\n"
+ "\t\t\t\t\t\t<!ATTLIST disk sha1 CDATA #IMPLIED>\n"
+ "\t\t\t\t\t\t<!ATTLIST disk status (baddump|nodump|good) \"good\">\n"
+ "\t\t\t\t\t\t<!ATTLIST disk writeable (yes|no) \"no\">\n"
+ // we still do not store the dipswitch values internally, so there is no output here
+ // TODO: add parsing dipsw in softlist.c and then add output here!
+ "\t\t\t\t<!ELEMENT dipswitch (dipvalue*)>\n"
+ "\t\t\t\t\t<!ATTLIST dipswitch name CDATA #REQUIRED>\n"
+ "\t\t\t\t\t<!ATTLIST dipswitch tag CDATA #REQUIRED>\n"
+ "\t\t\t\t\t<!ATTLIST dipswitch mask CDATA #REQUIRED>\n"
+ "\t\t\t\t\t<!ELEMENT dipvalue EMPTY>\n"
+ "\t\t\t\t\t\t<!ATTLIST dipvalue name CDATA #REQUIRED>\n"
+ "\t\t\t\t\t\t<!ATTLIST dipvalue value CDATA #REQUIRED>\n"
+ "\t\t\t\t\t\t<!ATTLIST dipvalue default (yes|no) \"no\">\n"
+ "]>\n\n"
+ "<softwarelists>\n"
+ );
+ }
+
+ drivlist.reset();
+ list_count = 0;
+ while (drivlist.next())
+ for (const device_t *dev = drivlist.config().devicelist().first(SOFTWARE_LIST); dev != NULL; dev = dev->typenext())
+ {
+ software_list_config *swlist = (software_list_config *)downcast<const legacy_device_base *>(dev)->inline_config();
+
+ for (int listnum = 0; listnum < DEVINFO_STR_SWLIST_MAX - DEVINFO_STR_SWLIST_0; listnum++)
+ {
+ if (swlist->list_name[listnum] && *swlist->list_name[listnum] && swlist->list_type == SOFTWARE_LIST_ORIGINAL_SYSTEM)
+ {
+ software_list *list = software_list_open(m_options, swlist->list_name[listnum], FALSE, NULL);
+
+ if ( list )
+ {
+ /* Verify if we have encountered this list before */
+ bool seen_before = false;
+ for (int seen_index = 0; seen_index < list_count && !seen_before; seen_index++)
+ if (lists[seen_index] == swlist->list_name[listnum])
+ seen_before = true;
+
+ if (!seen_before)
+ {
+ lists[list_count++] = swlist->list_name[listnum];
+ software_list_parse( list, NULL, NULL );
+
+ fprintf(out, "\t<softwarelist name=\"%s\" description=\"%s\">\n", swlist->list_name[listnum], xml_normalize_string(software_list_get_description(list)) );
+
+ for ( software_info *swinfo = software_list_find( list, "*", NULL ); swinfo != NULL; swinfo = software_list_find( list, "*", swinfo ) )
+ {
+ fprintf( out, "\t\t<software name=\"%s\"", swinfo->shortname );
+ if ( swinfo->parentname != NULL )
+ fprintf( out, " cloneof=\"%s\"", swinfo->parentname );
+ if ( swinfo->supported == SOFTWARE_SUPPORTED_PARTIAL )
+ fprintf( out, " supported=\"partial\"" );
+ if ( swinfo->supported == SOFTWARE_SUPPORTED_NO )
+ fprintf( out, " supported=\"no\"" );
+ fprintf( out, ">\n" );
+ fprintf( out, "\t\t\t<description>%s</description>\n", xml_normalize_string(swinfo->longname) );
+ fprintf( out, "\t\t\t<year>%s</year>\n", xml_normalize_string( swinfo->year ) );
+ fprintf( out, "\t\t\t<publisher>%s</publisher>\n", xml_normalize_string( swinfo->publisher ) );
+
+ for ( software_part *part = software_find_part( swinfo, NULL, NULL ); part != NULL; part = software_part_next( part ) )
+ {
+ fprintf( out, "\t\t\t<part name=\"%s\"", part->name );
+ if ( part->interface_ )
+ fprintf( out, " interface=\"%s\"", part->interface_ );
+
+ fprintf( out, ">\n");
+
+ if ( part->featurelist )
+ {
+ feature_list *flist = part->featurelist;
+
+ while( flist )
+ {
+ fprintf( out, "\t\t\t\t<feature name=\"%s\" value=\"%s\" />\n", flist->name, flist->value );
+ flist = flist->next;
+ }
+ }
+
+ /* TODO: display rom region information */
+ for ( const rom_entry *region = part->romdata; region; region = rom_next_region( region ) )
+ {
+ int is_disk = ROMREGION_ISDISKDATA(region);
+
+ if (!is_disk)
+ fprintf( out, "\t\t\t\t<dataarea name=\"%s\" size=\"%d\">\n", ROMREGION_GETTAG(region), ROMREGION_GETLENGTH(region) );
+ else
+ fprintf( out, "\t\t\t\t<diskarea name=\"%s\">\n", ROMREGION_GETTAG(region) );
+
+ for ( const rom_entry *rom = rom_first_file( region ); rom && !ROMENTRY_ISREGIONEND(rom); rom++ )
+ {
+ if ( ROMENTRY_ISFILE(rom) )
+ {
+ if (!is_disk)
+ fprintf( out, "\t\t\t\t\t<rom name=\"%s\" size=\"%d\"", xml_normalize_string(ROM_GETNAME(rom)), rom_file_size(rom) );
+ else
+ fprintf( out, "\t\t\t\t\t<disk name=\"%s\"", xml_normalize_string(ROM_GETNAME(rom)) );
+
+ /* dump checksum information only if there is a known dump */
+ hash_collection hashes(ROM_GETHASHDATA(rom));
+ if (!hashes.flag(hash_collection::FLAG_NO_DUMP))
+ {
+ astring tempstr;
+ for (hash_base *hash = hashes.first(); hash != NULL; hash = hash->next())
+ fprintf(out, " %s=\"%s\"", hash->name(), hash->string(tempstr));
+ }
+
+ if (!is_disk)
+ fprintf( out, " offset=\"0x%x\"", ROM_GETOFFSET(rom) );
+
+ if ( hashes.flag(hash_collection::FLAG_BAD_DUMP) )
+ fprintf( out, " status=\"baddump\"" );
+ if ( hashes.flag(hash_collection::FLAG_NO_DUMP) )
+ fprintf( out, " status=\"nodump\"" );
+
+ if (is_disk)
+ fprintf( out, " writeable=\"%s\"", (ROM_GETFLAGS(rom) & DISK_READONLYMASK) ? "no" : "yes");
+
+ if ((ROM_GETFLAGS(rom) & ROM_SKIPMASK) == ROM_SKIP(1))
+ fprintf( out, " loadflag=\"load16_byte\"" );
+
+ if ((ROM_GETFLAGS(rom) & ROM_SKIPMASK) == ROM_SKIP(3))
+ fprintf( out, " loadflag=\"load32_byte\"" );
+
+ if (((ROM_GETFLAGS(rom) & ROM_SKIPMASK) == ROM_SKIP(2)) && ((ROM_GETFLAGS(rom) & ROM_GROUPMASK) == ROM_GROUPWORD))
+ {
+ if (!(ROM_GETFLAGS(rom) & ROM_REVERSEMASK))
+ fprintf( out, " loadflag=\"load32_word\"" );
+ else
+ fprintf( out, " loadflag=\"load32_word_swap\"" );
+ }
+
+ if (((ROM_GETFLAGS(rom) & ROM_SKIPMASK) == ROM_SKIP(6)) && ((ROM_GETFLAGS(rom) & ROM_GROUPMASK) == ROM_GROUPWORD))
+ {
+ if (!(ROM_GETFLAGS(rom) & ROM_REVERSEMASK))
+ fprintf( out, " loadflag=\"load64_word\"" );
+ else
+ fprintf( out, " loadflag=\"load64_word_swap\"" );
+ }
+
+ if (((ROM_GETFLAGS(rom) & ROM_SKIPMASK) == ROM_NOSKIP) && ((ROM_GETFLAGS(rom) & ROM_GROUPMASK) == ROM_GROUPWORD))
+ {
+ if (!(ROM_GETFLAGS(rom) & ROM_REVERSEMASK))
+ fprintf( out, " loadflag=\"load32_dword\"" );
+ else
+ fprintf( out, " loadflag=\"load16_word_swap\"" );
+ }
+
+ fprintf( out, "/>\n" );
+ }
+ else if ( ROMENTRY_ISRELOAD(rom) )
+ {
+ fprintf( out, "\t\t\t\t\t<rom size=\"%d\" offset=\"0x%x\" loadflag=\"reload\" />\n", ROM_GETLENGTH(rom), ROM_GETOFFSET(rom) );
+ }
+ else if ( ROMENTRY_ISCONTINUE(rom) )
+ {
+ fprintf( out, "\t\t\t\t\t<rom size=\"%d\" offset=\"0x%x\" loadflag=\"continue\" />\n", ROM_GETLENGTH(rom), ROM_GETOFFSET(rom) );
+ }
+ else if ( ROMENTRY_ISFILL(rom) )
+ {
+ fprintf( out, "\t\t\t\t\t<rom size=\"%d\" offset=\"0x%x\" loadflag=\"fill\" />\n", ROM_GETLENGTH(rom), ROM_GETOFFSET(rom) );
+ }
+ }
+
+ if (!is_disk)
+ fprintf( out, "\t\t\t\t</dataarea>\n" );
+ else
+ fprintf( out, "\t\t\t\t</diskarea>\n" );
+ }
+
+ fprintf( out, "\t\t\t</part>\n" );
+ }
+
+ fprintf( out, "\t\t</software>\n" );
+ }
+
+ fprintf(out, "\t</softwarelist>\n" );
+ }
+
+ software_list_close( list );
+ }
+ }
+ }
+ }
+
+ if (list_count > 0)
+ fprintf( out, "</softwarelists>\n" );
+ else
+ fprintf( out, "No software lists found for this system\n" );
+
+ global_free( lists );
+}
+
+
+//-------------------------------------------------
+// romident - identify ROMs by looking for
+// matches in our internal database
+//-------------------------------------------------
+
+void cli_frontend::romident(const char *filename)
+{
+ media_identifier ident(m_options);
+
+ // identify the file, then output results
+ mame_printf_info("Identifying %s....\n", filename);
+ ident.identify(filename);
+
+ // return the appropriate error code
+ if (ident.matches() == ident.total())
+ return;
+ else if (ident.matches() == ident.total() - ident.nonroms())
+ throw emu_fatalerror(MAMERR_IDENT_NONROMS, "");
+ else if (ident.matches() > 0)
+ throw emu_fatalerror(MAMERR_IDENT_PARTIAL, "");
+ else
+ throw emu_fatalerror(MAMERR_IDENT_NONE, "");
+}
+
+
+//-------------------------------------------------
+// execute_commands - execute various frontend
+// commands
+//-------------------------------------------------
+
+void cli_frontend::execute_commands(const char *exename)
+{
+ // help?
+ if (strcmp(m_options.command(), CLICOMMAND_HELP) == 0)
+ {
+ display_help();
+ return;
+ }
+
+ // showusage?
+ if (strcmp(m_options.command(), CLICOMMAND_SHOWUSAGE) == 0)
+ {
+ astring helpstring;
+ mame_printf_info(USAGE "\n\nOptions:\n%s", exename, GAMENOUN, m_options.output_help(helpstring));
+ return;
+ }
+
+ // validate?
+ if (strcmp(m_options.command(), CLICOMMAND_VALIDATE) == 0)
+ {
+ validate_drivers(m_options);
+ return;
+ }
+
+ // other commands need the INIs parsed
+ astring option_errors;
+ m_options.parse_standard_inis(option_errors);
+ if (option_errors)
+ printf("%s\n", option_errors.cstr());
+
+ // createconfig?
+ if (strcmp(m_options.command(), CLICOMMAND_CREATECONFIG) == 0)
+ {
+ // attempt to open the output file
+ emu_file file(OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ if (file.open(CONFIGNAME ".ini") != FILERR_NONE)
+ throw emu_fatalerror("Unable to create file " CONFIGNAME ".ini\n");
+
+ // generate the updated INI
+ astring initext;
+ file.puts(m_options.output_ini(initext));
+ return;
+ }
+
+ // showconfig?
+ if (strcmp(m_options.command(), CLICOMMAND_SHOWCONFIG) == 0)
+ {
+ // print the INI text
+ astring initext;
+ printf("%s\n", m_options.output_ini(initext));
+ return;
+ }
+
+ // all other commands call out to one of these helpers
+ static const struct
+ {
+ const char *option;
+ void (cli_frontend::*function)(const char *gamename);
+ } info_commands[] =
+ {
+ { CLICOMMAND_LISTXML, &cli_frontend::listxml },
+ { CLICOMMAND_LISTFULL, &cli_frontend::listfull },
+ { CLICOMMAND_LISTSOURCE, &cli_frontend::listsource },
+ { CLICOMMAND_LISTCLONES, &cli_frontend::listclones },
+ { CLICOMMAND_LISTBROTHERS, &cli_frontend::listbrothers },
+ { CLICOMMAND_LISTCRC, &cli_frontend::listcrc },
+ { CLICOMMAND_LISTDEVICES, &cli_frontend::listdevices },
+ { CLICOMMAND_LISTSLOTS, &cli_frontend::listslots },
+ { CLICOMMAND_LISTROMS, &cli_frontend::listroms },
+ { CLICOMMAND_LISTSAMPLES, &cli_frontend::listsamples },
+ { CLICOMMAND_VERIFYROMS, &cli_frontend::verifyroms },
+ { CLICOMMAND_VERIFYSAMPLES, &cli_frontend::verifysamples },
+ { CLICOMMAND_LISTMEDIA, &cli_frontend::listmedia },
+ { CLICOMMAND_LISTSOFTWARE, &cli_frontend::listsoftware },
+ { CLICOMMAND_ROMIDENT, &cli_frontend::romident }
+ };
+
+ // find the command
+ for (int cmdindex = 0; cmdindex < ARRAY_LENGTH(info_commands); cmdindex++)
+ if (strcmp(m_options.command(), info_commands[cmdindex].option) == 0)
+ {
+ // parse any relevant INI files before proceeding
+ const char *sysname = m_options.system_name();
+ (this->*info_commands[cmdindex].function)((sysname[0] == 0) ? "*" : sysname);
+ return;
+ }
+
+ // if we get here, we don't know what has been requested
+ throw emu_fatalerror(MAMERR_INVALID_CONFIG, "Unknown command '%s' specified", m_options.command());
+}
+
+
+//-------------------------------------------------
+// display_help - display help to standard
+// output
+//-------------------------------------------------
+
+void cli_frontend::display_help()
+{
+ mame_printf_info(APPLONGNAME " v%s - " FULLLONGNAME "\n"
+ COPYRIGHT_INFO "\n\n", build_version);
+ mame_printf_info("%s\n", DISCLAIMER);
+ mame_printf_info(USAGE "\n\n"
+ " " APPNAME " -showusage for a brief list of options\n"
+ " " APPNAME " -showconfig for a list of configuration options\n"
+ " " APPNAME " -listmedia for a full list of supported media\n"
+ " " APPNAME " -createconfig to create a " CONFIGNAME ".ini\n\n"
+ "For usage instructions, please consult the files config.txt and windows.txt.\n",APPNAME,GAMENOUN);
+}
+
+
+//-------------------------------------------------
+// display_suggestions - display 10 possible
+// matches for a given invalid gamename
+//-------------------------------------------------
+
+void cli_frontend::display_suggestions(const char *gamename)
+{
+}
+
+
+//**************************************************************************
+// MEDIA IDENTIFIER
+//**************************************************************************
+
+//-------------------------------------------------
+// media_identifier - constructor
+//-------------------------------------------------
+
+media_identifier::media_identifier(cli_options &options)
+ : m_drivlist(options),
+ m_total(0),
+ m_matches(0),
+ m_nonroms(0)
+{
+}
+
+
+//-------------------------------------------------
+// identify - identify a directory, ZIP file,
+// or raw file
+//-------------------------------------------------
+
+void media_identifier::identify(const char *filename)
+{
+ // first try to open as a directory
+ osd_directory *directory = osd_opendir(filename);
+ if (directory != NULL)
+ {
+ // iterate over all files in the directory
+ for (const osd_directory_entry *entry = osd_readdir(directory); entry != NULL; entry = osd_readdir(directory))
+ if (entry->type == ENTTYPE_FILE)
+ {
+ astring curfile(filename, PATH_SEPARATOR, entry->name);
+ identify_file(curfile);
+ }
+
+ // close the directory and be done
+ osd_closedir(directory);
+ }
+
+ // if that failed, and the filename ends with .zip, identify as a ZIP file
+ else if (core_filename_ends_with(filename, ".zip"))
+ {
+ // first attempt to examine it as a valid ZIP file
+ zip_file *zip = NULL;
+ zip_error ziperr = zip_file_open(filename, &zip);
+ if (ziperr == ZIPERR_NONE && zip != NULL)
+ {
+ // loop over entries in the ZIP, skipping empty files and directories
+ for (const zip_file_header *entry = zip_file_first_file(zip); entry != NULL; entry = zip_file_next_file(zip))
+ if (entry->uncompressed_length != 0)
+ {
+ UINT8 *data = global_alloc_array(UINT8, entry->uncompressed_length);
+ if (data != NULL)
+ {
+ // decompress data into RAM and identify it
+ ziperr = zip_file_decompress(zip, data, entry->uncompressed_length);
+ if (ziperr == ZIPERR_NONE)
+ identify_data(entry->filename, data, entry->uncompressed_length);
+ global_free(data);
+ }
+ }
+
+ // close up
+ zip_file_close(zip);
+ }
+
+ // clear out any cached files
+ zip_file_cache_clear();
+ }
+
+ // otherwise, identify as a raw file
+ else
+ identify_file(filename);
+}
+
+
+//-------------------------------------------------
+// identify_file - identify a file
+//-------------------------------------------------
+
+void media_identifier::identify_file(const char *name)
+{
+ // CHD files need to be parsed and their hashes extracted from the header
+ if (core_filename_ends_with(name, ".chd"))
+ {
+ // output the name
+ astring basename;
+ mame_printf_info("%-20s", core_filename_extract_base(&basename, name, FALSE)->cstr());
+ m_total++;
+
+ // attempt to open as a CHD; fail if not
+ chd_file *chd;
+ chd_error err = chd_open(name, CHD_OPEN_READ, NULL, &chd);
+ if (err != CHDERR_NONE)
+ {
+ mame_printf_info("NOT A CHD\n");
+ m_nonroms++;
+ return;
+ }
+
+ // fetch the header and close the file
+ chd_header header = *chd_get_header(chd);
+ chd_close(chd);
+
+ // error on writable CHDs
+ if (header.flags & CHDFLAGS_IS_WRITEABLE)
+ {
+ mame_printf_info("is a writeable CHD\n");
+ return;
+ }
+
+ // otherwise, get the hash collection for this CHD
+ static const UINT8 nullhash[20] = { 0 };
+ hash_collection hashes;
+
+ if (memcmp(nullhash, header.sha1, sizeof(header.sha1)) != 0)
+ hashes.add_from_buffer(hash_collection::HASH_SHA1, header.sha1, sizeof(header.sha1));
+
+ // determine whether this file exists
+ int found = find_by_hash(hashes, header.logicalbytes);
+ if (found == 0)
+ mame_printf_info("NO MATCH\n");
+ else
+ m_matches++;
+ }
+
+ // all other files have their hashes computed directly
+ else
+ {
+ // load the file and process if it opens and has a valid length
+ UINT32 length;
+ void *data;
+ file_error filerr = core_fload(name, &data, &length);
+ if (filerr == FILERR_NONE && length > 0)
+ {
+ identify_data(name, reinterpret_cast<UINT8 *>(data), length);
+ osd_free(data);
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// identify_data - identify a buffer full of
+// data; if it comes from a .JED file, parse the
+// fusemap into raw data first
+//-------------------------------------------------
+
+void media_identifier::identify_data(const char *name, const UINT8 *data, int length)
+{
+ // if this is a '.jed' file, process it into raw bits first
+ UINT8 *tempjed = NULL;
+ jed_data jed;
+ if (core_filename_ends_with(name, ".jed") && jed_parse(data, length, &jed) == JEDERR_NONE)
+ {
+ // now determine the new data length and allocate temporary memory for it
+ length = jedbin_output(&jed, NULL, 0);
+ tempjed = global_alloc_array(UINT8, length);
+ jedbin_output(&jed, tempjed, length);
+ data = tempjed;
+ }
+
+ // compute the hash of the data
+ hash_collection hashes;
+ hashes.compute(data, length, hash_collection::HASH_TYPES_CRC_SHA1);
+
+ // output the name
+ m_total++;
+ astring basename;
+ mame_printf_info("%-20s", core_filename_extract_base(&basename, name, FALSE)->cstr());
+
+ // see if we can find a match in the ROMs
+ int found = find_by_hash(hashes, length);
+
+ // if we didn't find it, try to guess what it might be
+ if (found == 0)
+ {
+ // if not a power of 2, assume it is a non-ROM file
+ if ((length & (length - 1)) != 0)
+ {
+ mame_printf_info("NOT A ROM\n");
+ m_nonroms++;
+ }
+
+ // otherwise, it's just not a match
+ else
+ mame_printf_info("NO MATCH\n");
+ }
+
+ // if we did find it, count it as a match
+ else
+ m_matches++;
+
+ // free any temporary JED data
+ global_free(tempjed);
+}
+
+
+//-------------------------------------------------
+// find_by_hash - scan for a file in the list
+// of drivers by hash
+//-------------------------------------------------
+
+int media_identifier::find_by_hash(const hash_collection &hashes, int length)
+{
+ int found = 0;
+
+ // iterate over drivers
+ m_drivlist.reset();
+ while (m_drivlist.next())
+ {
+ // iterate over sources, regions and files within the region */
+ for (const rom_source *source = rom_first_source(m_drivlist.config()); source != NULL; source = rom_next_source(*source))
+ for (const rom_entry *region = rom_first_region(*source); region != NULL; region = rom_next_region(region))
+ for (const rom_entry *rom = rom_first_file(region); rom != NULL; rom = rom_next_file(rom))
+ {
+ hash_collection romhashes(ROM_GETHASHDATA(rom));
+ if (!romhashes.flag(hash_collection::FLAG_NO_DUMP) && hashes == romhashes)
+ {
+ bool baddump = romhashes.flag(hash_collection::FLAG_BAD_DUMP);
+
+ // output information about the match
+ if (found)
+ mame_printf_info(" ");
+ mame_printf_info("= %s%-20s %-10s %s\n", baddump ? "(BAD) " : "", ROM_GETNAME(rom), m_drivlist.driver().name, m_drivlist.driver().description);
+ found++;
+ }
+ }
+
+ // next iterate over softlists
+ for (const device_t *dev = m_drivlist.config().devicelist().first(SOFTWARE_LIST); dev != NULL; dev = dev->typenext())
+ {
+ software_list_config *swlist = (software_list_config *)downcast<const legacy_device_base *>(dev)->inline_config();
+
+ for (int listnum = 0; listnum < DEVINFO_STR_SWLIST_MAX - DEVINFO_STR_SWLIST_0; listnum++)
+ if (swlist->list_name[listnum] != NULL)
+ {
+ software_list *list = software_list_open(m_drivlist.options(), swlist->list_name[listnum], FALSE, NULL);
+
+ for (software_info *swinfo = software_list_find(list, "*", NULL); swinfo != NULL; swinfo = software_list_find(list, "*", swinfo))
+ for (software_part *part = software_find_part(swinfo, NULL, NULL); part != NULL; part = software_part_next(part))
+ for (const rom_entry *region = part->romdata; region != NULL; region = rom_next_region(region))
+ for (const rom_entry *rom = rom_first_file(region); rom != NULL; rom = rom_next_file(rom))
+ {
+ hash_collection romhashes(ROM_GETHASHDATA(rom));
+ if (hashes == romhashes)
+ {
+ bool baddump = romhashes.flag(hash_collection::FLAG_BAD_DUMP);
+
+ // output information about the match
+ if (found)
+ mame_printf_info(" ");
+ mame_printf_info("= %s%-20s %s:%s %s\n", baddump ? "(BAD) " : "", ROM_GETNAME(rom), swlist->list_name[listnum], swinfo->shortname, swinfo->longname);
+ found++;
+ }
+ }
+
+ software_list_close(list);
+ }
+ }
+ }
+
+ return found;
+}
diff --git a/trunk/src/emu/clifront.h b/trunk/src/emu/clifront.h
new file mode 100644
index 00000000000..7edc4380130
--- /dev/null
+++ b/trunk/src/emu/clifront.h
@@ -0,0 +1,167 @@
+/***************************************************************************
+
+ clifront.h
+
+ Command-line interface frontend for MAME.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __CLIFRONT_H__
+#define __CLIFRONT_H__
+
+#include "emuopts.h"
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// core commands
+#define CLICOMMAND_HELP "help"
+#define CLICOMMAND_VALIDATE "validate"
+
+// configuration commands
+#define CLICOMMAND_CREATECONFIG "createconfig"
+#define CLICOMMAND_SHOWCONFIG "showconfig"
+#define CLICOMMAND_SHOWUSAGE "showusage"
+
+// frontend commands
+#define CLICOMMAND_LISTXML "listxml"
+#define CLICOMMAND_LISTFULL "listfull"
+#define CLICOMMAND_LISTSOURCE "listsource"
+#define CLICOMMAND_LISTCLONES "listclones"
+#define CLICOMMAND_LISTBROTHERS "listbrothers"
+#define CLICOMMAND_LISTCRC "listcrc"
+#define CLICOMMAND_LISTROMS "listroms"
+#define CLICOMMAND_LISTSAMPLES "listsamples"
+#define CLICOMMAND_VERIFYROMS "verifyroms"
+#define CLICOMMAND_VERIFYSAMPLES "verifysamples"
+#define CLICOMMAND_ROMIDENT "romident"
+#define CLICOMMAND_LISTDEVICES "listdevices"
+#define CLICOMMAND_LISTSLOTS "listslots"
+#define CLICOMMAND_LISTMEDIA "listmedia" // needed by MESS
+#define CLICOMMAND_LISTSOFTWARE "listsoftware"
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// cli_options wraps the general emu options with CLI-specific additions
+class cli_options : public emu_options
+{
+public:
+ // construction/destruction
+ cli_options();
+
+private:
+ static const options_entry s_option_entries[];
+};
+
+
+// cli_frontend handles command-line processing and emulator execution
+class cli_frontend
+{
+public:
+ // construction/destruction
+ cli_frontend(cli_options &options, osd_interface &osd);
+ ~cli_frontend();
+
+ // execute based on the incoming argc/argv
+ int execute(int argc, char **argv);
+
+ // direct access to the command operations
+ void listxml(const char *gamename = "*");
+ void listfull(const char *gamename = "*");
+ void listsource(const char *gamename = "*");
+ void listclones(const char *gamename = "*");
+ void listbrothers(const char *gamename = "*");
+ void listcrc(const char *gamename = "*");
+ void listroms(const char *gamename = "*");
+ void listsamples(const char *gamename = "*");
+ void listdevices(const char *gamename = "*");
+ void listslots(const char *gamename = "*");
+ void listmedia(const char *gamename = "*");
+ void listsoftware(const char *gamename = "*");
+ void verifyroms(const char *gamename = "*");
+ void verifysamples(const char *gamename = "*");
+ void romident(const char *filename);
+
+private:
+ // internal helpers
+ void execute_commands(const char *exename);
+ void display_help();
+ void display_suggestions(const char *gamename);
+
+ // internal state
+ cli_options & m_options;
+ osd_interface & m_osd;
+ int m_result;
+};
+
+
+// media_identifier class identifies media by hash via a search in
+// the driver database
+class media_identifier
+{
+public:
+ // construction/destruction
+ media_identifier(cli_options &options);
+
+ // getters
+ int total() const { return m_total; }
+ int matches() const { return m_matches; }
+ int nonroms() const { return m_nonroms; }
+
+ // operations
+ void reset() { m_total = m_matches = m_nonroms = 0; }
+ void identify(const char *name);
+ void identify_file(const char *name);
+ void identify_data(const char *name, const UINT8 *data, int length);
+ int find_by_hash(const hash_collection &hashes, int length);
+
+private:
+ // internal state
+ driver_enumerator m_drivlist;
+ int m_total;
+ int m_matches;
+ int m_nonroms;
+};
+
+
+
+#endif /* __CLIFRONT_H__ */
diff --git a/trunk/src/emu/config.c b/trunk/src/emu/config.c
new file mode 100644
index 00000000000..d2937d38f21
--- /dev/null
+++ b/trunk/src/emu/config.c
@@ -0,0 +1,328 @@
+/***************************************************************************
+
+ config.c
+
+ Configuration file I/O.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "emuopts.h"
+#include "config.h"
+#include "xmlfile.h"
+
+
+#define DEBUG_CONFIG 0
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _config_type config_type;
+struct _config_type
+{
+ struct _config_type * next; /* next in line */
+ const char * name; /* node name */
+ config_saveload_delegate load; /* load callback */
+ config_saveload_delegate save; /* save callback */
+};
+
+
+
+/***************************************************************************
+ GLOBAL VARIABLES
+***************************************************************************/
+
+static config_type *typelist;
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static int config_load_xml(running_machine &machine, emu_file &file, int type);
+static int config_save_xml(running_machine &machine, emu_file &file, int type);
+
+
+
+/***************************************************************************
+ CORE IMPLEMENTATION
+***************************************************************************/
+
+/*************************************
+ *
+ * Reset the configuration callbacks
+ *
+ *************************************/
+
+void config_init(running_machine &machine)
+{
+ typelist = NULL;
+}
+
+
+
+/*************************************
+ *
+ * Register to be involved in config
+ * save/load
+ *
+ *************************************/
+
+void config_register(running_machine &machine, const char *nodename, config_saveload_delegate load, config_saveload_delegate save)
+{
+ config_type *newtype;
+ config_type **ptype;
+
+ /* allocate a new type */
+ newtype = auto_alloc(machine, config_type);
+ newtype->next = NULL;
+ newtype->name = nodename;
+ newtype->load = load;
+ newtype->save = save;
+
+ /* add us to the end */
+ for (ptype = &typelist; *ptype; ptype = &(*ptype)->next) ;
+ *ptype = newtype;
+}
+
+
+
+/*************************************
+ *
+ * Settings save/load frontend
+ *
+ *************************************/
+
+int config_load_settings(running_machine &machine)
+{
+ const char *controller = machine.options().ctrlr();
+ config_type *type;
+ int loaded = 0;
+
+ /* loop over all registrants and call their init function */
+ for (type = typelist; type; type = type->next)
+ type->load(CONFIG_TYPE_INIT, NULL);
+
+ /* now load the controller file */
+ if (controller[0] != 0)
+ {
+ /* open the config file */
+ emu_file file(machine.options().ctrlr_path(), OPEN_FLAG_READ);
+ file_error filerr = file.open(controller, ".cfg");
+
+ if (filerr != FILERR_NONE)
+ throw emu_fatalerror("Could not load controller file %s.cfg", controller);
+
+ /* load the XML */
+ if (!config_load_xml(machine, file, CONFIG_TYPE_CONTROLLER))
+ throw emu_fatalerror("Could not load controller file %s.cfg", controller);
+ }
+
+ /* next load the defaults file */
+ emu_file file(machine.options().cfg_directory(), OPEN_FLAG_READ);
+ file_error filerr = file.open("default.cfg");
+ if (filerr == FILERR_NONE)
+ config_load_xml(machine, file, CONFIG_TYPE_DEFAULT);
+
+ /* finally, load the game-specific file */
+ filerr = file.open(machine.basename(), ".cfg");
+ if (filerr == FILERR_NONE)
+ loaded = config_load_xml(machine, file, CONFIG_TYPE_GAME);
+
+ /* loop over all registrants and call their final function */
+ for (type = typelist; type; type = type->next)
+ type->load(CONFIG_TYPE_FINAL, NULL);
+
+ /* if we didn't find a saved config, return 0 so the main core knows that it */
+ /* is the first time the game is run and it should diplay the disclaimer. */
+ return loaded;
+}
+
+
+void config_save_settings(running_machine &machine)
+{
+ config_type *type;
+
+ /* loop over all registrants and call their init function */
+ for (type = typelist; type; type = type->next)
+ type->save(CONFIG_TYPE_INIT, NULL);
+
+ /* save the defaults file */
+ emu_file file(machine.options().cfg_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ file_error filerr = file.open("default.cfg");
+ if (filerr == FILERR_NONE)
+ config_save_xml(machine, file, CONFIG_TYPE_DEFAULT);
+
+ /* finally, save the game-specific file */
+ filerr = file.open(machine.basename(), ".cfg");
+ if (filerr == FILERR_NONE)
+ config_save_xml(machine, file, CONFIG_TYPE_GAME);
+
+ /* loop over all registrants and call their final function */
+ for (type = typelist; type; type = type->next)
+ type->save(CONFIG_TYPE_FINAL, NULL);
+}
+
+
+
+/*************************************
+ *
+ * XML file load
+ *
+ *************************************/
+
+static int config_load_xml(running_machine &machine, emu_file &file, int which_type)
+{
+ xml_data_node *root, *confignode, *systemnode;
+ config_type *type;
+ const char *srcfile;
+ int version, count;
+
+ /* read the file */
+ root = xml_file_read(file, NULL);
+ if (!root)
+ goto error;
+
+ /* find the config node */
+ confignode = xml_get_sibling(root->child, "mameconfig");
+ if (!confignode)
+ goto error;
+
+ /* validate the config data version */
+ version = xml_get_attribute_int(confignode, "version", 0);
+ if (version != CONFIG_VERSION)
+ goto error;
+
+ /* strip off all the path crap from the source filename */
+ srcfile = strrchr(machine.system().source_file, '/');
+ if (!srcfile)
+ srcfile = strrchr(machine.system().source_file, '\\');
+ if (!srcfile)
+ srcfile = strrchr(machine.system().source_file, ':');
+ if (!srcfile)
+ srcfile = machine.system().source_file;
+ else
+ srcfile++;
+
+ /* loop over all system nodes in the file */
+ count = 0;
+ for (systemnode = xml_get_sibling(confignode->child, "system"); systemnode; systemnode = xml_get_sibling(systemnode->next, "system"))
+ {
+ /* look up the name of the system here; skip if none */
+ const char *name = xml_get_attribute_string(systemnode, "name", "");
+
+ /* based on the file type, determine whether we have a match */
+ switch (which_type)
+ {
+ case CONFIG_TYPE_GAME:
+ /* only match on the specific game name */
+ if (strcmp(name, machine.system().name) != 0)
+ continue;
+ break;
+
+ case CONFIG_TYPE_DEFAULT:
+ /* only match on default */
+ if (strcmp(name, "default") != 0)
+ continue;
+ break;
+
+ case CONFIG_TYPE_CONTROLLER:
+ {
+ int clone_of;
+ /* match on: default, game name, source file name, parent name, grandparent name */
+ if (strcmp(name, "default") != 0 &&
+ strcmp(name, machine.system().name) != 0 &&
+ strcmp(name, srcfile) != 0 &&
+ ((clone_of = driver_list::clone(machine.system())) == -1 || strcmp(name, driver_list::driver(clone_of).name) != 0) &&
+ (clone_of == -1 || ((clone_of = driver_list::clone(clone_of)) == -1) || strcmp(name, driver_list::driver(clone_of).name) != 0))
+ continue;
+ break;
+ }
+ }
+
+ /* log that we are processing this entry */
+ if (DEBUG_CONFIG)
+ mame_printf_debug("Entry: %s -- processing\n", name);
+
+ /* loop over all registrants and call their load function */
+ for (type = typelist; type; type = type->next)
+ type->load(which_type, xml_get_sibling(systemnode->child, type->name));
+ count++;
+ }
+
+ /* error if this isn't a valid game match */
+ if (count == 0)
+ goto error;
+
+ /* free the parser */
+ xml_file_free(root);
+ return 1;
+
+error:
+ if (root)
+ xml_file_free(root);
+ return 0;
+}
+
+
+
+/*************************************
+ *
+ * XML file save
+ *
+ *************************************/
+
+static int config_save_xml(running_machine &machine, emu_file &file, int which_type)
+{
+ xml_data_node *root = xml_file_create();
+ xml_data_node *confignode, *systemnode;
+ config_type *type;
+
+ /* if we don't have a root, bail */
+ if (!root)
+ return 0;
+
+ /* create a config node */
+ confignode = xml_add_child(root, "mameconfig", NULL);
+ if (!confignode)
+ goto error;
+ xml_set_attribute_int(confignode, "version", CONFIG_VERSION);
+
+ /* create a system node */
+ systemnode = xml_add_child(confignode, "system", NULL);
+ if (!systemnode)
+ goto error;
+ xml_set_attribute(systemnode, "name", (which_type == CONFIG_TYPE_DEFAULT) ? "default" : machine.system().name);
+
+ /* create the input node and write it out */
+ /* loop over all registrants and call their save function */
+ for (type = typelist; type; type = type->next)
+ {
+ xml_data_node *curnode = xml_add_child(systemnode, type->name, NULL);
+ if (!curnode)
+ goto error;
+ type->save(which_type, curnode);
+
+ /* if nothing was added, just nuke the node */
+ if (!curnode->value && !curnode->child)
+ xml_delete_node(curnode);
+ }
+
+ /* flush the file */
+ xml_file_write(root, file);
+
+ /* free and get out of here */
+ xml_file_free(root);
+ return 1;
+
+error:
+ xml_file_free(root);
+ return 0;
+}
diff --git a/trunk/src/emu/config.h b/trunk/src/emu/config.h
new file mode 100644
index 00000000000..e94b0bfbb2f
--- /dev/null
+++ b/trunk/src/emu/config.h
@@ -0,0 +1,61 @@
+/***************************************************************************
+
+ config.h
+
+ Wrappers for handling MAME configuration files
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __CONFIG_H__
+#define __CONFIG_H__
+
+#include "xmlfile.h"
+
+
+
+/*************************************
+ *
+ * Constants
+ *
+ *************************************/
+
+#define CONFIG_VERSION 10
+
+enum
+{
+ CONFIG_TYPE_INIT = 0, /* opportunity to initialize things first */
+ CONFIG_TYPE_CONTROLLER, /* loading from controller file */
+ CONFIG_TYPE_DEFAULT, /* loading from default.cfg */
+ CONFIG_TYPE_GAME, /* loading from game.cfg */
+ CONFIG_TYPE_FINAL /* opportunity to finish initialization */
+};
+
+
+
+/*************************************
+ *
+ * Type definitions
+ *
+ *************************************/
+
+typedef delegate<void (int, xml_data_node *)> config_saveload_delegate;
+
+
+
+/*************************************
+ *
+ * Function prototypes
+ *
+ *************************************/
+
+void config_init(running_machine &machine);
+void config_register(running_machine &machine, const char *nodename, config_saveload_delegate load, config_saveload_delegate save);
+int config_load_settings(running_machine &machine);
+void config_save_settings(running_machine &machine);
+
+#endif /* __CONFIG_H__ */
diff --git a/trunk/src/emu/cothread.c b/trunk/src/emu/cothread.c
new file mode 100644
index 00000000000..4dbce1fa465
--- /dev/null
+++ b/trunk/src/emu/cothread.c
@@ -0,0 +1,95 @@
+/***************************************************************************
+
+ cothread.c
+
+ Class wrapper around byuu's cothread library.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "cothread/libco.h"
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// static members of the cothread class
+osd_lock *cothread::s_create_lock = osd_lock_alloc();
+cothread *cothread::s_create_cothread;
+
+
+
+//**************************************************************************
+// COTHREAD
+//**************************************************************************
+
+//-------------------------------------------------
+// cothread - constructor
+//-------------------------------------------------
+
+cothread::cothread(cothread_t existing_thread)
+ : m_cothread(existing_thread),
+ m_creator_cothread(NULL)
+{
+}
+
+cothread::cothread(cothread_entry_delegate entry, size_t stack)
+ : m_cothread(NULL),
+ m_creator_cothread(co_active()),
+ m_entry(entry)
+{
+ // due to the lack of input parameter to the entry function,
+ // all cothread creation is explicitly serialized
+ osd_lock_acquire(s_create_lock);
+ s_create_cothread = this;
+ m_cothread = co_create(stack, &cothread_entry);
+ co_switch(m_cothread);
+ osd_lock_release(s_create_lock);
+}
+
+
+//-------------------------------------------------
+// cothread_entry - static entry point
+//-------------------------------------------------
+
+void cothread::cothread_entry()
+{
+ // on first call, retrieve the static pointer and return
+ cothread *thread = s_create_cothread;
+ co_switch(thread->m_creator_cothread);
+
+ // when actually swapped in later, call the entry point
+ thread->m_entry();
+}
diff --git a/trunk/src/emu/cothread.h b/trunk/src/emu/cothread.h
new file mode 100644
index 00000000000..e75dee02f59
--- /dev/null
+++ b/trunk/src/emu/cothread.h
@@ -0,0 +1,88 @@
+/***************************************************************************
+
+ cothread.h
+
+ Class wrapper around byuu's cothread library.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __EMU_H__
+#error Dont include this file directly; include emu.h instead.
+#endif
+
+#ifndef __COTHREAD_H__
+#define __COTHREAD_H__
+
+#include "cothread/libco.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// delegate that points to a thread's entry
+typedef delegate<void ()> cothread_entry_delegate;
+
+
+// ======================> cothread
+
+class cothread
+{
+public:
+ // construction/destruction
+ cothread(cothread_t existing_thread);
+ cothread(cothread_entry_delegate entry, size_t stack = 1048576);
+ ~cothread() { if (m_creator_cothread != NULL) co_delete(m_cothread); }
+
+ // switching
+ void make_active() { co_switch(m_cothread); }
+
+private:
+ // internal helpers
+ static void cothread_entry();
+
+ // internal state
+ cothread_t m_cothread;
+ cothread_t m_creator_cothread;
+ cothread_entry_delegate m_entry;
+
+ // static state
+ static osd_lock * s_create_lock;
+ static cothread * s_create_cothread;
+};
+
+
+#endif // __COTHREAD_H__
diff --git a/trunk/src/emu/cpu/adsp2100/2100dasm.c b/trunk/src/emu/cpu/adsp2100/2100dasm.c
new file mode 100644
index 00000000000..ec71a7d0432
--- /dev/null
+++ b/trunk/src/emu/cpu/adsp2100/2100dasm.c
@@ -0,0 +1,551 @@
+#include "emu.h"
+#include "adsp2100.h"
+
+static const char *const flag_change[] = { "", "TOGGLE %s ", "RESET %s ", "SET %s " };
+static const char *const mode_change[] = { "", "", "DIS %s ", "ENA %s " };
+
+static const char *const alu_xop[] = { "AX0", "AX1", "AR", "MR0", "MR1", "MR2", "SR0", "SR1" };
+static const char *const alu_yop[] = { "AY0", "AY1", "AF", "0" };
+static const char *const alu_dst[] = { "AR", "AF", "NONE" };
+
+static const char *const mac_xop[] = { "MX0", "MX1", "AR", "MR0", "MR1", "MR2", "SR0", "SR1" };
+static const char *const mac_yop[] = { "MY0", "MY1", "MF", "0" };
+static const char *const mac_dst[] = { "MR", "MF", "NONE" };
+
+static const char *const shift_xop[] = { "SI", "??", "AR", "MR0", "MR1", "MR2", "SR0", "SR1" };
+
+static const char *const reg_grp[][16] =
+{
+ { "AX0", "AX1", "MX0", "MX1", "AY0", "AY1", "MY0", "MY1", "SI", "SE", "AR", "MR0", "MR1", "MR2", "SR0", "SR1" },
+ { "I0", "I1", "I2", "I3", "M0", "M1", "M2", "M3", "L0", "L1", "L2", "L3", "??", "??", "??", "??" },
+ { "I4", "I5", "I6", "I7", "M4", "M5", "M6", "M7", "L4", "L5", "L6", "L7", "??", "??", "??", "??" },
+ { "ASTAT", "MSTAT", "SSTAT", "IMASK", "ICNTL", "CNTR", "SB", "PX", "RX0", "TX0", "RX1", "TX1", "IFC", "OWRCNTR", "??", "??" }
+};
+static const char *const dual_xreg[] = { "AX0", "AX1", "MX0", "MX1" };
+static const char *const dual_yreg[] = { "AY0", "AY1", "MY0", "MY1" };
+
+static const char *const condition[] =
+{
+ "IF EQ ",
+ "IF NE ",
+ "IF GT ",
+ "IF LE ",
+ "IF LT ",
+ "IF GE ",
+ "IF AV ",
+ "IF NOT AV ",
+ "IF AC ",
+ "IF NOT AC ",
+ "IF NEG ",
+ "IF POS ",
+ "IF MV ",
+ "IF NOT MV ",
+ "IF NOT CE ",
+ ""
+};
+
+static const char *const do_condition[] =
+{
+ "NE",
+ "EQ",
+ "LE",
+ "GT",
+ "GE",
+ "LT",
+ "NOT AV",
+ "AV",
+ "NOT AC",
+ "AC",
+ "POS",
+ "NEG",
+ "NOT MV",
+ "MV",
+ "CE",
+ "FOREVER"
+};
+
+static const char *const alumac_op[][2] =
+{
+ { "", "" },
+ { "%s = %s * %s (RND)", "%s = %s * %s (RND)" },
+ { "%s = MR + %s * %s (RND)", "%s = MR + %s * %s (RND)" },
+ { "%s = MR - %s * %s (RND)", "%s = MR - %s * %s (RND)" },
+ { "%s = %s * %s (SS)", "%s = 0" },
+ { "%s = %s * %s (SU)", "%s = %s * %s (SU)" },
+ { "%s = %s * %s (US)", "%s = %s * %s (US)" },
+ { "%s = %s * %s (UU)", "%s = %s * %s (UU)" },
+ { "%s = MR + %s * %s (SS)", "%s = MR + %s * %s (SS)" },
+ { "%s = MR + %s * %s (SU)", "%s = MR + %s * %s (SU)" },
+ { "%s = MR + %s * %s (US)", "%s = MR + %s * %s (US)" },
+ { "%s = MR + %s * %s (UU)", "%s = MR + %s * %s (UU)" },
+ { "%s = MR - %s * %s (SS)", "%s = MR - %s * %s (SS)" },
+ { "%s = MR - %s * %s (SS)", "%s = MR - %s * %s (SS)" },
+ { "%s = MR - %s * %s (US)", "%s = MR - %s * %s (US)" },
+ { "%s = MR - %s * %s (UU)", "%s = MR - %s * %s (UU)" },
+
+ { "!%s = %s", "%s = 0" },
+ { "!%s = %s + 1", "%s = 1" },
+ { "%s = %s + %s + C", "%s = %s + %s + C" },
+ { "%s = %s + %s", "%s = %s" },
+ { "!%s = NOT %s", "!%s = NOT %s" },
+ { "!%s = -%s", "!%s = -%s" },
+ { "%s = %s - %s + C - 1", "%s = %s + C - 1" },
+ { "%s = %s - %s", "%s = %s - %s" },
+ { "!%s = %s - 1", "%s = -1" },
+ { "!%s = %s - %s", "%s = -%s" },
+ { "!%s = %s - %s + C - 1", "%s = -%s + C - 1" },
+ { "%s = NOT %s", "%s = NOT %s" },
+ { "%s = %s AND %s", "%s = %s AND %s" },
+ { "%s = %s OR %s", "%s = %s OR %s" },
+ { "%s = %s XOR %s", "%s = %s XOR %s" },
+ { "%s = ABS %s", "%s = ABS %s" }
+};
+
+static const char *const shift_op[] =
+{
+ "SR = LSHIFT %s (HI)",
+ "SR = SR OR LSHIFT %s (HI)",
+ "SR = LSHIFT %s (LO)",
+ "SR = SR OR LSHIFT %s (LO)",
+ "SR = ASHIFT %s (HI)",
+ "SR = SR OR ASHIFT %s (HI)",
+ "SR = ASHIFT %s (LO)",
+ "SR = SR OR ASHIFT %s (LO)",
+ "SR = NORM %s (HI)",
+ "SR = SR OR NORM %s (HI)",
+ "SR = NORM %s (LO)",
+ "SR = SR OR NORM %s (LO)",
+ "SE = EXP %s (HI)",
+ "SE = EXP %s (HIX)",
+ "SE = EXP %s (LO)",
+ "SB = EXPADJ %s",
+};
+
+static const char *const shift_by_op[] =
+{
+ "SR = LSHIFT %s BY %d (HI)",
+ "SR = SR OR LSHIFT %s BY %d (HI)",
+ "SR = LSHIFT %s BY %d (LO)",
+ "SR = SR OR LSHIFT %s BY %d (LO)",
+ "SR = ASHIFT %s BY %d (HI)",
+ "SR = SR OR ASHIFT %s BY %d (HI)",
+ "SR = ASHIFT %s BY %d (LO)",
+ "SR = SR OR ASHIFT %s BY %d (LO)",
+ "???",
+ "???",
+ "???",
+ "???",
+ "???",
+ "???",
+ "???",
+ "???"
+};
+
+static const char *const constants[] =
+{
+ "$0001",
+ "$FFFE",
+ "$0002",
+ "$FFFD",
+ "$0004",
+ "$FFFB",
+ "$0008",
+ "$FFF7",
+ "$0010",
+ "$FFEF",
+ "$0020",
+ "$FFDF",
+ "$0040",
+ "$FFBF",
+ "$0080",
+ "$FF7F",
+ "$0100",
+ "$FEFF",
+ "$0200",
+ "$FDFF",
+ "$0400",
+ "$FBFF",
+ "$0800",
+ "$F7FF",
+ "$1000",
+ "$EFFF",
+ "$2000",
+ "$DFFF",
+ "$4000",
+ "$BFFF",
+ "$8000",
+ "$7FFF"
+};
+
+
+
+
+static int alumac(char *buffer, int dest, int op)
+{
+ int opindex = (op >> 13) & 31;
+ const char *xop, *yop, *dst, *opstring;
+
+ if (opindex & 16)
+ {
+ xop = alu_xop[(op >> 8) & 7];
+ yop = alu_yop[(op >> 11) & 3];
+ dst = alu_dst[dest];
+ }
+ else
+ {
+ xop = mac_xop[(op >> 8) & 7];
+ yop = mac_yop[(op >> 11) & 3];
+ dst = mac_dst[dest];
+ }
+ opstring = alumac_op[opindex][((op >> 11) & 3) == 3];
+ if (opstring[0] == '!')
+ return sprintf(buffer, opstring + 1, dst, yop, xop);
+ else
+ return sprintf(buffer, opstring, dst, xop, yop);
+}
+
+
+static int aluconst(char *buffer, int dest, int op)
+{
+ int opindex = (op >> 13) & 31;
+ const char *xop, *dst, *cval, *opstring;
+
+ if (opindex & 16)
+ {
+ xop = alu_xop[(op >> 8) & 7];
+ cval = constants[((op >> 5) & 0x07) | ((op >> 8) & 0x18)];
+ dst = alu_dst[dest];
+ }
+ else
+ {
+ xop = mac_xop[(op >> 8) & 7];
+ cval = xop;
+ dst = mac_dst[dest];
+ }
+ opstring = alumac_op[opindex][((op >> 11) & 3) == 3];
+ if (opstring[0] == '!')
+ return sprintf(buffer, opstring + 1, dst, cval, xop);
+ else
+ return sprintf(buffer, opstring, dst, xop, cval);
+}
+
+
+/* execute instructions on this CPU until icount expires */
+CPU_DISASSEMBLE( adsp21xx )
+{
+ unsigned int op = oprom[0] | (oprom[1] << 8) | (oprom[2] << 16);
+ unsigned dasmflags = 0;
+ int temp;
+
+ switch ((op >> 16) & 0xff)
+ {
+ case 0x00:
+ /* 00000000 00000000 00000000 NOP */
+ sprintf(buffer, "%s", "NOP");
+ break;
+ case 0x01:
+ /* 00000000 0xxxxxxx xxxxxxxx dst = IO(x) */
+ /* 00000000 1xxxxxxx xxxxxxxx IO(x) = dst */
+ /* ADSP-218x only */
+ if ((op & 0x008000) == 0x000000)
+ buffer += sprintf(buffer, "%s = IO($%X)", reg_grp[0][op & 15], (op >> 4) & 0x7ff);
+ else
+ buffer += sprintf(buffer, "IO($%X) = %s", (op >> 4) & 0x7ff, reg_grp[0][op & 15]);
+ break;
+ case 0x02:
+ /* 00000010 0000xxxx xxxxxxxx modify flag out */
+ if ((op & 0x00f000) == 0x000000)
+ {
+ buffer += sprintf(buffer, "%s", condition[op & 15]);
+ buffer += sprintf(buffer, flag_change[(op >> 4) & 3], "FLAG_OUT");
+ buffer += sprintf(buffer, flag_change[(op >> 6) & 3], "FL0");
+ buffer += sprintf(buffer, flag_change[(op >> 8) & 3], "FL1");
+ buffer += sprintf(buffer, flag_change[(op >> 10) & 3], "FL2");
+ }
+ /* 00000010 10000000 00000000 idle */
+ /* 00000010 10000000 0000xxxx idle (n) */
+ else if ((op & 0x00fff0) == 0x008000)
+ {
+ }
+ else
+ buffer += sprintf(buffer, "??? (%06X)", op);
+ break;
+ case 0x03:
+ /* 00000011 xxxxxxxx xxxxxxxx call or jump on flag in */
+ if (op & 2)
+ buffer += sprintf(buffer, "%s", "IF FLAG_IN ");
+ else
+ buffer += sprintf(buffer, "%s", "IF NOT FLAG_IN ");
+ if (op & 1)
+ {
+ buffer += sprintf(buffer, "%s", "CALL ");
+ dasmflags = DASMFLAG_STEP_OVER;
+ }
+ else
+ buffer += sprintf(buffer, "%s", "JUMP ");
+ temp = ((op >> 4) & 0x0fff) | ((op << 10) & 0x3000);
+ buffer += sprintf(buffer, "$%04X", temp);
+ break;
+ case 0x04:
+ /* 00000100 00000000 000xxxxx stack control */
+ if ((op & 0x00ffe0) == 0x000000)
+ {
+ if (op & 0x000010)
+ {
+ buffer += sprintf(buffer, "%s", "POP PC ");
+ dasmflags = DASMFLAG_STEP_OUT;
+ }
+ if (op & 0x000008) buffer += sprintf(buffer, "%s", "POP LOOP ");
+ if (op & 0x000004) buffer += sprintf(buffer, "%s", "POP CNTR ");
+ if ((op & 0x000003) == 0x000002) buffer += sprintf(buffer, "%s", "PUSH STAT ");
+ else if ((op & 0x000003) == 0x000003) buffer += sprintf(buffer, "%s", "POP STAT ");
+ }
+ else
+ buffer += sprintf(buffer, "??? (%06X)", op);
+ break;
+ case 0x05:
+ /* 00000101 00000000 00000000 saturate MR */
+ if ((op & 0x00ffff) == 0x000000)
+ buffer += sprintf(buffer, "%s", "IF MV SAT MR");
+ else
+ buffer += sprintf(buffer, "??? (%06X)", op);
+ break;
+ case 0x06:
+ /* 00000110 000xxxxx 00000000 DIVS */
+ if ((op & 0x00e0ff) == 0x000000)
+ buffer += sprintf(buffer, "DIVS %s,%s", alu_yop[(op >> 11) & 3], alu_xop[(op >> 8) & 7]);
+ else
+ buffer += sprintf(buffer, "??? (%06X)", op);
+ break;
+ case 0x07:
+ /* 00000111 00010xxx 00000000 DIVQ */
+ if ((op & 0x00f8ff) == 0x001000)
+ buffer += sprintf(buffer, "DIVQ %s", alu_xop[(op >> 8) & 7]);
+ else
+ buffer += sprintf(buffer, "??? (%06X)", op);
+ break;
+ case 0x08:
+ /* 00001000 00000000 0000xxxx reserved */
+ buffer += sprintf(buffer, "??? (%06X)", op);
+ break;
+ case 0x09:
+ /* 00001001 00000000 000xxxxx modify address register */
+ if ((op & 0x00ffe0) == 0x000000)
+ {
+ temp = (op >> 2) & 4;
+ buffer += sprintf(buffer, "MODIFY (I%d,M%d)", temp + ((op >> 2) & 3), temp + (op & 3));
+ }
+ else
+ buffer += sprintf(buffer, "??? (%06X)", op);
+ break;
+ case 0x0a:
+ /* 00001010 00000000 0000xxxx conditional return */
+ if ((op & 0x00ffe0) == 0x000000)
+ {
+ buffer += sprintf(buffer, "%s", condition[op & 15]);
+ if (op & 0x000010)
+ buffer += sprintf(buffer, "%s", "RTI");
+ else
+ buffer += sprintf(buffer, "%s", "RTS");
+ dasmflags = DASMFLAG_STEP_OUT;
+ }
+ else
+ buffer += sprintf(buffer, "??? (%06X)", op);
+ break;
+ case 0x0b:
+ /* 00001011 00000000 xx00xxxx conditional jump (indirect address) */
+ if ((op & 0x00ff00) == 0x000000)
+ {
+ buffer += sprintf(buffer, "%s", condition[op & 15]);
+ if (op & 0x000010)
+ {
+ buffer += sprintf(buffer, "CALL (I%d)", 4 + ((op >> 6) & 3));
+ dasmflags = DASMFLAG_STEP_OVER;
+ }
+ else
+ buffer += sprintf(buffer, "JUMP (I%d)", 4 + ((op >> 6) & 3));
+ }
+ else
+ buffer += sprintf(buffer, "??? (%06X)", op);
+ break;
+ case 0x0c:
+ /* 00001100 xxxxxxxx xxxxxxxx mode control */
+ buffer += sprintf(buffer, mode_change[(op >> 4) & 3], "SEC_REG");
+ buffer += sprintf(buffer, mode_change[(op >> 6) & 3], "BIT_REV");
+ buffer += sprintf(buffer, mode_change[(op >> 8) & 3], "AV_LATCH");
+ buffer += sprintf(buffer, mode_change[(op >> 10) & 3], "AR_SAT");
+ buffer += sprintf(buffer, mode_change[(op >> 12) & 3], "M_MODE");
+ buffer += sprintf(buffer, mode_change[(op >> 14) & 3], "TIMER");
+ buffer += sprintf(buffer, mode_change[(op >> 2) & 3], "G_MODE");
+ break;
+ case 0x0d:
+ /* 00001101 0000xxxx xxxxxxxx internal data move */
+ if ((op & 0x00f000) == 0x000000)
+ buffer += sprintf(buffer, "%s = %s", reg_grp[(op >> 10) & 3][(op >> 4) & 15], reg_grp[(op >> 8) & 3][op & 15]);
+ else
+ buffer += sprintf(buffer, "??? (%06X)", op);
+ break;
+ case 0x0e:
+ /* 00001110 0xxxxxxx xxxxxxxx conditional shift */
+ if ((op & 0x0080f0) == 0x000000)
+ {
+ buffer += sprintf(buffer, "%s", condition[op & 15]);
+ buffer += sprintf(buffer, shift_op[(op >> 11) & 15], shift_xop[(op >> 8) & 7]);
+ }
+ else
+ buffer += sprintf(buffer, "??? (%06X)", op);
+ break;
+ case 0x0f:
+ /* 00001111 0xxxxxxx xxxxxxxx shift immediate */
+ if ((op & 0x008000) == 0x000000)
+ buffer += sprintf(buffer, shift_by_op[(op >> 11) & 15], shift_xop[(op >> 8) & 7], (signed char)op);
+ else
+ buffer += sprintf(buffer, "??? (%06X)", op);
+ break;
+ case 0x10:
+ /* 00010000 0xxxxxxx xxxxxxxx shift with internal data register move */
+ if ((op & 0x008000) == 0x000000)
+ {
+ buffer += sprintf(buffer, shift_op[(op >> 11) & 15], shift_xop[(op >> 8) & 7]);
+ buffer += sprintf(buffer, ", %s = %s", reg_grp[0][(op >> 4) & 15], reg_grp[0][op & 15]);
+ }
+ else
+ buffer += sprintf(buffer, "??? (%06X)", op);
+ break;
+ case 0x11:
+ /* 00010001 0xxxxxxx xxxxxxxx shift with pgm memory read/write */
+ buffer += sprintf(buffer, shift_op[(op >> 11) & 15], shift_xop[(op >> 8) & 7]);
+ if (op & 0x008000)
+ buffer += sprintf(buffer, ", PM(I%d,M%d) = %s", 4 + ((op >> 2) & 3), 4 + (op & 3), reg_grp[0][(op >> 4) & 15]);
+ else
+ buffer += sprintf(buffer, ", %s = PM(I%d,M%d)", reg_grp[0][(op >> 4) & 15], 4 + ((op >> 2) & 3), 4 + (op & 3));
+ break;
+ case 0x12: case 0x13:
+ /* 0001001x 0xxxxxxx xxxxxxxx shift with data memory read/write */
+ buffer += sprintf(buffer, shift_op[(op >> 11) & 15], shift_xop[(op >> 8) & 7]);
+ temp = (op >> 14) & 4;
+ if (op & 0x008000)
+ buffer += sprintf(buffer, ", DM(I%d,M%d) = %s", temp + ((op >> 2) & 3), temp + (op & 3), reg_grp[0][(op >> 4) & 15]);
+ else
+ buffer += sprintf(buffer, ", %s = DM(I%d,M%d)", reg_grp[0][(op >> 4) & 15], temp + ((op >> 2) & 3), temp + (op & 3));
+ break;
+ case 0x14: case 0x15: case 0x16: case 0x17:
+ /* 000101xx xxxxxxxx xxxxxxxx do until */
+ buffer += sprintf(buffer, "DO $%04X UNTIL %s", (op >> 4) & 0x3fff, do_condition[op & 15]);
+ break;
+ case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ /* 00011xxx xxxxxxxx xxxxxxxx conditional jump (immediate addr) */
+ if (op & 0x040000)
+ {
+ buffer += sprintf(buffer, "%sCALL $%04X", condition[op & 15], (op >> 4) & 0x3fff);
+ dasmflags = DASMFLAG_STEP_OVER;
+ }
+ else
+ buffer += sprintf(buffer, "%sJUMP $%04X", condition[op & 15], (op >> 4) & 0x3fff);
+ break;
+ case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
+ /* 00100xxx xxxxxxxx xxxxxxxx conditional ALU/MAC */
+ buffer += sprintf(buffer, "%s", condition[op & 15]);
+ if (!(op & 0x10))
+ buffer += alumac(buffer, (op >> 18) & 1, op);
+ else
+ {
+ /* ADSP-218x only */
+ buffer += aluconst(buffer, (op >> 18) & 1, op);
+ }
+ break;
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ /* 00101xxx xxxxxxxx xxxxxxxx ALU/MAC with internal data register move */
+ if ((op & 0x0600ff) == 0x0200aa)
+ {
+ /* ADSP-218x only */
+ buffer += alumac(buffer, 2, op);
+ }
+ else
+ {
+ if ((op & 0x03e000) != 0)
+ {
+ buffer += alumac(buffer, (op >> 18) & 1, op);
+ buffer += sprintf(buffer, ", ");
+ }
+ buffer += sprintf(buffer, "%s = %s", reg_grp[0][(op >> 4) & 15], reg_grp[0][op & 15]);
+ }
+ break;
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
+ case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
+ /* 0011xxxx xxxxxxxx xxxxxxxx load non-data register immediate */
+ buffer += sprintf(buffer, "%s = $%04X", reg_grp[(op >> 18) & 3][op & 15], (op >> 4) & 0x3fff);
+ break;
+ case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47:
+ case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f:
+ /* 0100xxxx xxxxxxxx xxxxxxxx load data register immediate */
+ buffer += sprintf(buffer, "%s = $%04X", reg_grp[0][op & 15], (op >> 4) & 0xffff);
+ break;
+ case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57:
+ case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f:
+ /* 0101xxxx xxxxxxxx xxxxxxxx ALU/MAC with pgm memory read/write */
+ if ((op & 0x03e000) != 0)
+ {
+ buffer += alumac(buffer, (op >> 18) & 1, op);
+ buffer += sprintf(buffer, ", ");
+ }
+ if (op & 0x080000)
+ buffer += sprintf(buffer, "PM(I%d,M%d) = %s", 4 + ((op >> 2) & 3), 4 + (op & 3), reg_grp[0][(op >> 4) & 15]);
+ else
+ buffer += sprintf(buffer, "%s = PM(I%d,M%d)", reg_grp[0][(op >> 4) & 15], 4 + ((op >> 2) & 3), 4 + (op & 3));
+ break;
+ case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67:
+ case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6e: case 0x6f:
+ case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77:
+ case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f:
+ /* 011xxxxx xxxxxxxx xxxxxxxx ALU/MAC with data memory read/write */
+ if ((op & 0x03e000) != 0)
+ {
+ buffer += alumac(buffer, (op >> 18) & 1, op);
+ buffer += sprintf(buffer, ", ");
+ }
+ temp = (op >> 18) & 4;
+ if (op & 0x080000)
+ buffer += sprintf(buffer, "DM(I%d,M%d) = %s", temp + ((op >> 2) & 3), temp + (op & 3), reg_grp[0][(op >> 4) & 15]);
+ else
+ buffer += sprintf(buffer, "%s = DM(I%d,M%d)", reg_grp[0][(op >> 4) & 15], temp + ((op >> 2) & 3), temp + (op & 3));
+ break;
+ case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87:
+ case 0x88: case 0x89: case 0x8a: case 0x8b: case 0x8c: case 0x8d: case 0x8e: case 0x8f:
+ case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97:
+ case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f:
+ /* 100xxxxx xxxxxxxx xxxxxxxx read/write data memory (immediate addr) */
+ if (op & 0x100000)
+ buffer += sprintf(buffer, "DM($%04X) = %s", (op >> 4) & 0x3fff, reg_grp[(op >> 18) & 3][op & 15]);
+ else
+ buffer += sprintf(buffer, "%s = DM($%04X)", reg_grp[(op >> 18) & 3][op & 15], (op >> 4) & 0x3fff);
+ break;
+ case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7:
+ case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf:
+ case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7:
+ case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf:
+ /* 101xxxxx xxxxxxxx xxxxxxxx data memory write (immediate) */
+ temp = (op >> 18) & 4;
+ buffer += sprintf(buffer, "DM(I%d,M%d) = $%04X", temp + ((op >> 2) & 3), temp + (op & 3), (op >> 4) & 0xffff);
+ break;
+ case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7:
+ case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf:
+ case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7:
+ case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf:
+ case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7:
+ case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef:
+ case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7:
+ case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff:
+ /* 11xxxxxx xxxxxxxx xxxxxxxx ALU/MAC with data & pgm memory read */
+ if ((op & 0x03e000) != 0)
+ {
+ buffer += alumac(buffer, 0, op);
+ buffer += sprintf(buffer, ", ");
+ }
+ buffer += sprintf(buffer, "%s = DM(I%d,M%d), %s = PM(I%d,M%d)", dual_xreg[(op >> 18) & 3], (op >> 2) & 3, op & 3,
+ dual_yreg[(op >> 20) & 3], 4 + ((op >> 6) & 3), 4 + ((op >> 4) & 3));
+ break;
+ }
+
+ return 1 | dasmflags | DASMFLAG_SUPPORTED;
+}
diff --git a/trunk/src/emu/cpu/adsp2100/2100ops.c b/trunk/src/emu/cpu/adsp2100/2100ops.c
new file mode 100644
index 00000000000..0c14e8f7b15
--- /dev/null
+++ b/trunk/src/emu/cpu/adsp2100/2100ops.c
@@ -0,0 +1,2230 @@
+/*===========================================================================
+ ASTAT -- ALU/MAC status register
+===========================================================================*/
+
+/* extracts flags */
+#define GET_SS (m_astat & SSFLAG)
+#define GET_MV (m_astat & MVFLAG)
+#define GET_Q (m_astat & QFLAG)
+#define GET_S (m_astat & SFLAG)
+#define GET_C (m_astat & CFLAG)
+#define GET_V (m_astat & VFLAG)
+#define GET_N (m_astat & NFLAG)
+#define GET_Z (m_astat & ZFLAG)
+
+/* clears flags */
+#define CLR_SS (m_astat &= ~SSFLAG)
+#define CLR_MV (m_astat &= ~MVFLAG)
+#define CLR_Q (m_astat &= ~QFLAG)
+#define CLR_S (m_astat &= ~SFLAG)
+#define CLR_C (m_astat &= ~CFLAG)
+#define CLR_V (m_astat &= ~VFLAG)
+#define CLR_N (m_astat &= ~NFLAG)
+#define CLR_Z (m_astat &= ~ZFLAG)
+
+/* sets flags */
+#define SET_SS (m_astat |= SSFLAG)
+#define SET_MV (m_astat |= MVFLAG)
+#define SET_Q (m_astat |= QFLAG)
+#define SET_S (m_astat |= SFLAG)
+#define SET_C (m_astat |= CFLAG)
+#define SET_V (m_astat |= VFLAG)
+#define SET_Z (m_astat |= ZFLAG)
+#define SET_N (m_astat |= NFLAG)
+
+/* flag clearing; must be done before setting */
+#define CLR_FLAGS (m_astat &= m_astat_clear)
+
+/* compute flags */
+#define CALC_Z(r) (m_astat |= ((r & 0xffff) == 0))
+#define CALC_N(r) (m_astat |= (r >> 14) & 0x02)
+#define CALC_V(s,d,r) (m_astat |= ((s ^ d ^ r ^ (r >> 1)) >> 13) & 0x04)
+#define CALC_C(r) (m_astat |= (r >> 13) & 0x08)
+#define CALC_C_SUB(r) (m_astat |= (~r >> 13) & 0x08)
+#define CALC_NZ(r) CLR_FLAGS; CALC_N(r); CALC_Z(r)
+#define CALC_NZV(s,d,r) CLR_FLAGS; CALC_N(r); CALC_Z(r); CALC_V(s,d,r)
+#define CALC_NZVC(s,d,r) CLR_FLAGS; CALC_N(r); CALC_Z(r); CALC_V(s,d,r); CALC_C(r)
+#define CALC_NZVC_SUB(s,d,r) CLR_FLAGS; CALC_N(r); CALC_Z(r); CALC_V(s,d,r); CALC_C_SUB(r)
+
+/* ADSP-218x constants */
+static const INT32 constants[] =
+{
+ 0x0001, 0xfffe, 0x0002, 0xfffd, 0x0004, 0xfffb, 0x0008, 0xfff7,
+ 0x0010, 0xffef, 0x0020, 0xffdf, 0x0040, 0xffbf, 0x0080, 0xff7f,
+ 0x0100, 0xfeff, 0x0200, 0xfdff, 0x0400, 0xfbff, 0x0800, 0xf7ff,
+ 0x1000, 0xefff, 0x2000, 0xdfff, 0x4000, 0xbfff, 0x8000, 0x7fff
+};
+
+
+
+/*===========================================================================
+ MSTAT -- ALU/MAC control register
+===========================================================================*/
+
+/* flag definitions */
+#define MSTAT_BANK 0x01 /* register bank select */
+#define MSTAT_REVERSE 0x02 /* bit-reverse addressing enable (DAG1) */
+#define MSTAT_STICKYV 0x04 /* sticky ALU overflow enable */
+#define MSTAT_SATURATE 0x08 /* AR saturation mode enable */
+#define MSTAT_INTEGER 0x10 /* MAC result placement; 0=fractional, 1=integer */
+#define MSTAT_TIMER 0x20 /* timer enable */
+#define MSTAT_GOMODE 0x40 /* go mode enable */
+
+/* you must call this in order to change MSTAT */
+inline void adsp21xx_device::update_mstat()
+{
+ if ((m_mstat ^ m_mstat_prev) & MSTAT_BANK)
+ {
+ adsp_core temp = m_core;
+ m_core = m_alt;
+ m_alt = temp;
+ }
+ if ((m_mstat ^ m_mstat_prev) & MSTAT_TIMER)
+ if (m_timer_fired != NULL)
+ (*m_timer_fired)(*this, (m_mstat & MSTAT_TIMER) != 0);
+ if (m_mstat & MSTAT_STICKYV)
+ m_astat_clear = ~(CFLAG | NFLAG | ZFLAG);
+ else
+ m_astat_clear = ~(CFLAG | VFLAG | NFLAG | ZFLAG);
+ m_mstat_prev = m_mstat;
+}
+
+
+/*===========================================================================
+ SSTAT -- stack status register
+===========================================================================*/
+
+/* flag definitions */
+#define PC_EMPTY 0x01 /* PC stack empty */
+#define PC_OVER 0x02 /* PC stack overflow */
+#define COUNT_EMPTY 0x04 /* count stack empty */
+#define COUNT_OVER 0x08 /* count stack overflow */
+#define STATUS_EMPTY 0x10 /* status stack empty */
+#define STATUS_OVER 0x20 /* status stack overflow */
+#define LOOP_EMPTY 0x40 /* loop stack empty */
+#define LOOP_OVER 0x80 /* loop stack overflow */
+
+
+
+/*===========================================================================
+ PC stack handlers
+===========================================================================*/
+
+inline UINT32 adsp21xx_device::pc_stack_top()
+{
+ if (m_pc_sp > 0)
+ return m_pc_stack[m_pc_sp - 1];
+ else
+ return m_pc_stack[0];
+}
+
+inline void adsp21xx_device::set_pc_stack_top(UINT32 top)
+{
+ if (m_pc_sp > 0)
+ m_pc_stack[m_pc_sp - 1] = top;
+ else
+ m_pc_stack[0] = top;
+}
+
+inline void adsp21xx_device::pc_stack_push()
+{
+ if (m_pc_sp < PC_STACK_DEPTH)
+ {
+ m_pc_stack[m_pc_sp] = m_pc;
+ m_pc_sp++;
+ m_sstat &= ~PC_EMPTY;
+ }
+ else
+ m_sstat |= PC_OVER;
+}
+
+inline void adsp21xx_device::pc_stack_push_val(UINT32 val)
+{
+ if (m_pc_sp < PC_STACK_DEPTH)
+ {
+ m_pc_stack[m_pc_sp] = val;
+ m_pc_sp++;
+ m_sstat &= ~PC_EMPTY;
+ }
+ else
+ m_sstat |= PC_OVER;
+}
+
+inline void adsp21xx_device::pc_stack_pop()
+{
+ if (m_pc_sp > 0)
+ {
+ m_pc_sp--;
+ if (m_pc_sp == 0)
+ m_sstat |= PC_EMPTY;
+ }
+ m_pc = m_pc_stack[m_pc_sp];
+}
+
+inline UINT32 adsp21xx_device::pc_stack_pop_val()
+{
+ if (m_pc_sp > 0)
+ {
+ m_pc_sp--;
+ if (m_pc_sp == 0)
+ m_sstat |= PC_EMPTY;
+ }
+ return m_pc_stack[m_pc_sp];
+}
+
+
+/*===========================================================================
+ CNTR stack handlers
+===========================================================================*/
+
+inline UINT32 adsp21xx_device::cntr_stack_top()
+{
+ if (m_cntr_sp > 0)
+ return m_cntr_stack[m_cntr_sp - 1];
+ else
+ return m_cntr_stack[0];
+}
+
+inline void adsp21xx_device::cntr_stack_push()
+{
+ if (m_cntr_sp < CNTR_STACK_DEPTH)
+ {
+ m_cntr_stack[m_cntr_sp] = m_cntr;
+ m_cntr_sp++;
+ m_sstat &= ~COUNT_EMPTY;
+ }
+ else
+ m_sstat |= COUNT_OVER;
+}
+
+inline void adsp21xx_device::cntr_stack_pop()
+{
+ if (m_cntr_sp > 0)
+ {
+ m_cntr_sp--;
+ if (m_cntr_sp == 0)
+ m_sstat |= COUNT_EMPTY;
+ }
+ m_cntr = m_cntr_stack[m_cntr_sp];
+}
+
+
+/*===========================================================================
+ LOOP stack handlers
+===========================================================================*/
+
+inline UINT32 adsp21xx_device::loop_stack_top()
+{
+ if (m_loop_sp > 0)
+ return m_loop_stack[m_loop_sp - 1];
+ else
+ return m_loop_stack[0];
+}
+
+inline void adsp21xx_device::loop_stack_push(UINT32 value)
+{
+ if (m_loop_sp < LOOP_STACK_DEPTH)
+ {
+ m_loop_stack[m_loop_sp] = value;
+ m_loop_sp++;
+ m_loop = value >> 4;
+ m_loop_condition = value & 15;
+ m_sstat &= ~LOOP_EMPTY;
+ }
+ else
+ m_sstat |= LOOP_OVER;
+}
+
+inline void adsp21xx_device::loop_stack_pop()
+{
+ if (m_loop_sp > 0)
+ {
+ m_loop_sp--;
+ if (m_loop_sp == 0)
+ {
+ m_loop = 0xffff;
+ m_loop_condition = 0;
+ m_sstat |= LOOP_EMPTY;
+ }
+ else
+ {
+ m_loop = m_loop_stack[m_loop_sp -1] >> 4;
+ m_loop_condition = m_loop_stack[m_loop_sp - 1] & 15;
+ }
+ }
+}
+
+
+/*===========================================================================
+ STAT stack handlers
+===========================================================================*/
+
+inline void adsp21xx_device::stat_stack_push()
+{
+ if (m_stat_sp < STAT_STACK_DEPTH)
+ {
+ m_stat_stack[m_stat_sp][0] = m_mstat;
+ m_stat_stack[m_stat_sp][1] = m_imask;
+ m_stat_stack[m_stat_sp][2] = m_astat;
+ m_stat_sp++;
+ m_sstat &= ~STATUS_EMPTY;
+ }
+ else
+ m_sstat |= STATUS_OVER;
+}
+
+inline void adsp21xx_device::stat_stack_pop()
+{
+ if (m_stat_sp > 0)
+ {
+ m_stat_sp--;
+ if (m_stat_sp == 0)
+ m_sstat |= STATUS_EMPTY;
+ }
+ m_mstat = m_stat_stack[m_stat_sp][0];
+ update_mstat();
+ m_imask = m_stat_stack[m_stat_sp][1];
+ m_astat = m_stat_stack[m_stat_sp][2];
+ check_irqs();
+}
+
+
+
+/*===========================================================================
+ condition code checking
+===========================================================================*/
+
+// gcc doesn't want to inline this, so we use a macro
+#define condition(c) (((c) != 14) ? (m_condition_table[((c) << 8) | m_astat]) : slow_condition())
+
+/*
+inline int adsp21xx_device::condition(int c)
+{
+ if (c != 14)
+ return m_condition_table[((c) << 8) | m_astat];
+ else
+ return slow_condition(c);
+}
+*/
+
+int adsp21xx_device::slow_condition()
+{
+ if ((INT32)--m_cntr > 0)
+ return 1;
+ else
+ {
+ cntr_stack_pop();
+ return 0;
+ }
+}
+
+
+
+/*===========================================================================
+ register writing
+===========================================================================*/
+
+inline void adsp21xx_device::update_i(int which)
+{
+ m_base[which] = m_i[which] & m_lmask[which];
+}
+
+inline void adsp21xx_device::update_l(int which)
+{
+ m_lmask[which] = m_mask_table[m_l[which] & 0x3fff];
+ m_base[which] = m_i[which] & m_lmask[which];
+}
+
+void adsp21xx_device::write_reg0(int regnum, INT32 val)
+{
+ switch (regnum)
+ {
+ case 0x00: m_core.ax0.s = val; break;
+ case 0x01: m_core.ax1.s = val; break;
+ case 0x02: m_core.mx0.s = val; break;
+ case 0x03: m_core.mx1.s = val; break;
+ case 0x04: m_core.ay0.s = val; break;
+ case 0x05: m_core.ay1.s = val; break;
+ case 0x06: m_core.my0.s = val; break;
+ case 0x07: m_core.my1.s = val; break;
+ case 0x08: m_core.si.s = val; break;
+ case 0x09: m_core.se.s = (INT8)val; break;
+ case 0x0a: m_core.ar.s = val; break;
+ case 0x0b: m_core.mr.mrx.mr0.s = val; break;
+ case 0x0c: m_core.mr.mrx.mr1.s = val; m_core.mr.mrx.mr2.s = (INT16)val >> 15; break;
+ case 0x0d: m_core.mr.mrx.mr2.s = (INT8)val; break;
+ case 0x0e: m_core.sr.srx.sr0.s = val; break;
+ case 0x0f: m_core.sr.srx.sr1.s = val; break;
+ }
+}
+
+void adsp21xx_device::write_reg1(int regnum, INT32 val)
+{
+ int index = regnum & 3;
+ switch (regnum >> 2)
+ {
+ case 0:
+ m_i[index] = val & 0x3fff;
+ update_i(index);
+ break;
+
+ case 1:
+ m_m[index] = (INT32)(val << 18) >> 18;
+ break;
+
+ case 2:
+ m_l[index] = val & 0x3fff;
+ update_l(index);
+ break;
+
+ case 3:
+ logerror("ADSP %04x: Writing to an invalid register!\n", m_ppc);
+ break;
+ }
+}
+
+void adsp21xx_device::write_reg2(int regnum, INT32 val)
+{
+ int index = 4 + (regnum & 3);
+ switch (regnum >> 2)
+ {
+ case 0:
+ m_i[index] = val & 0x3fff;
+ update_i(index);
+ break;
+
+ case 1:
+ m_m[index] = (INT32)(val << 18) >> 18;
+ break;
+
+ case 2:
+ m_l[index] = val & 0x3fff;
+ update_l(index);
+ break;
+
+ case 3:
+ logerror("ADSP %04x: Writing to an invalid register!\n", m_ppc);
+ break;
+ }
+}
+
+void adsp21xx_device::write_reg3(int regnum, INT32 val)
+{
+ switch (regnum)
+ {
+ case 0x00: m_astat = val & 0x00ff; break;
+ case 0x01: m_mstat = val & m_mstat_mask; update_mstat(); break;
+ case 0x03: m_imask = val & m_imask_mask; check_irqs(); break;
+ case 0x04: m_icntl = val & 0x001f; check_irqs(); break;
+ case 0x05: cntr_stack_push(); m_cntr = val & 0x3fff; break;
+ case 0x06: m_core.sb.s = (INT32)(val << 27) >> 27; break;
+ case 0x07: m_px = val; break;
+ case 0x09: if (m_sport_tx_callback != NULL) (*m_sport_tx_callback)(*this, 0, val); break;
+ case 0x0b: if (m_sport_tx_callback != NULL) (*m_sport_tx_callback)(*this, 1, val); break;
+ case 0x0c:
+ m_ifc = val;
+ if (m_chip_type >= CHIP_TYPE_ADSP2181)
+ {
+ /* clear timer */
+ if (val & 0x0002) m_irq_latch[ADSP2181_IRQ0] = 0;
+ if (val & 0x0004) m_irq_latch[ADSP2181_IRQ1] = 0;
+ /* clear BDMA */
+ if (val & 0x0010) m_irq_latch[ADSP2181_IRQE] = 0;
+ if (val & 0x0020) m_irq_latch[ADSP2181_SPORT0_RX] = 0;
+ if (val & 0x0040) m_irq_latch[ADSP2181_SPORT0_TX] = 0;
+ if (val & 0x0080) m_irq_latch[ADSP2181_IRQ2] = 0;
+ /* force timer */
+ if (val & 0x0200) m_irq_latch[ADSP2181_IRQ0] = 1;
+ if (val & 0x0400) m_irq_latch[ADSP2181_IRQ1] = 1;
+ /* force BDMA */
+ if (val & 0x1000) m_irq_latch[ADSP2181_IRQE] = 1;
+ if (val & 0x2000) m_irq_latch[ADSP2181_SPORT0_RX] = 1;
+ if (val & 0x4000) m_irq_latch[ADSP2181_SPORT0_TX] = 1;
+ if (val & 0x8000) m_irq_latch[ADSP2181_IRQ2] = 1;
+ }
+ else
+ {
+ /* clear timer */
+ if (val & 0x002) m_irq_latch[ADSP2101_IRQ0] = 0;
+ if (val & 0x004) m_irq_latch[ADSP2101_IRQ1] = 0;
+ if (val & 0x008) m_irq_latch[ADSP2101_SPORT0_RX] = 0;
+ if (val & 0x010) m_irq_latch[ADSP2101_SPORT0_TX] = 0;
+ if (val & 0x020) m_irq_latch[ADSP2101_IRQ2] = 0;
+ /* set timer */
+ if (val & 0x080) m_irq_latch[ADSP2101_IRQ0] = 1;
+ if (val & 0x100) m_irq_latch[ADSP2101_IRQ1] = 1;
+ if (val & 0x200) m_irq_latch[ADSP2101_SPORT0_RX] = 1;
+ if (val & 0x400) m_irq_latch[ADSP2101_SPORT0_TX] = 1;
+ if (val & 0x800) m_irq_latch[ADSP2101_IRQ2] = 1;
+ }
+ check_irqs();
+ break;
+ case 0x0d: m_cntr = val & 0x3fff; break;
+ case 0x0f: pc_stack_push_val(val & 0x3fff); break;
+ default: logerror("ADSP %04x: Writing to an invalid register!\n", m_ppc); break;
+ }
+}
+
+#define WRITE_REG(adsp,grp,reg,val) ((this->*wr_reg[grp][reg])(val))
+
+
+
+/*===========================================================================
+ register reading
+===========================================================================*/
+
+INT32 adsp21xx_device::read_reg0(int regnum)
+{
+ return *m_read0_ptr[regnum];
+}
+
+INT32 adsp21xx_device::read_reg1(int regnum)
+{
+ return *m_read1_ptr[regnum];
+}
+
+INT32 adsp21xx_device::read_reg2(int regnum)
+{
+ return *m_read2_ptr[regnum];
+}
+
+INT32 adsp21xx_device::read_reg3(int regnum)
+{
+ switch (regnum)
+ {
+ case 0x00: return m_astat;
+ case 0x01: return m_mstat;
+ case 0x02: return m_sstat;
+ case 0x03: return m_imask;
+ case 0x04: return m_icntl;
+ case 0x05: return m_cntr;
+ case 0x06: return m_core.sb.s;
+ case 0x07: return m_px;
+ case 0x08: if (m_sport_rx_callback) return (*m_sport_rx_callback)(*this, 0); else return 0;
+ case 0x0a: if (m_sport_rx_callback) return (*m_sport_rx_callback)(*this, 1); else return 0;
+ case 0x0f: return pc_stack_pop_val();
+ default: logerror("ADSP %04x: Reading from an invalid register!\n", m_ppc); return 0;
+ }
+}
+
+
+
+/*===========================================================================
+ Modulus addressing logic
+===========================================================================*/
+
+inline void adsp21xx_device::modify_address(UINT32 ireg, UINT32 mreg)
+{
+ UINT32 base = m_base[ireg];
+ UINT32 i = m_i[ireg];
+ UINT32 l = m_l[ireg];
+
+ i += m_m[mreg];
+ if (i < base) i += l;
+ else if (i >= base + l) i -= l;
+ m_i[ireg] = i;
+}
+
+
+
+/*===========================================================================
+ Data memory accessors
+===========================================================================*/
+
+inline void adsp21xx_device::data_write_dag1(UINT32 op, INT32 val)
+{
+ UINT32 ireg = (op >> 2) & 3;
+ UINT32 mreg = op & 3;
+ UINT32 base = m_base[ireg];
+ UINT32 i = m_i[ireg];
+ UINT32 l = m_l[ireg];
+
+ if ( m_mstat & MSTAT_REVERSE )
+ {
+ UINT32 ir = m_reverse_table[ i & 0x3fff ];
+ data_write(ir, val);
+ }
+ else
+ data_write(i, val);
+
+ i += m_m[mreg];
+ if (i < base) i += l;
+ else if (i >= base + l) i -= l;
+ m_i[ireg] = i;
+}
+
+
+inline UINT32 adsp21xx_device::data_read_dag1(UINT32 op)
+{
+ UINT32 ireg = (op >> 2) & 3;
+ UINT32 mreg = op & 3;
+ UINT32 base = m_base[ireg];
+ UINT32 i = m_i[ireg];
+ UINT32 l = m_l[ireg];
+ UINT32 res;
+
+ if (m_mstat & MSTAT_REVERSE)
+ {
+ UINT32 ir = m_reverse_table[i & 0x3fff];
+ res = data_read(ir);
+ }
+ else
+ res = data_read(i);
+
+ i += m_m[mreg];
+ if (i < base) i += l;
+ else if (i >= base + l) i -= l;
+ m_i[ireg] = i;
+
+ return res;
+}
+
+inline void adsp21xx_device::data_write_dag2(UINT32 op, INT32 val)
+{
+ UINT32 ireg = 4 + ((op >> 2) & 3);
+ UINT32 mreg = 4 + (op & 3);
+ UINT32 base = m_base[ireg];
+ UINT32 i = m_i[ireg];
+ UINT32 l = m_l[ireg];
+
+ data_write(i, val);
+
+ i += m_m[mreg];
+ if (i < base) i += l;
+ else if (i >= base + l) i -= l;
+ m_i[ireg] = i;
+}
+
+
+inline UINT32 adsp21xx_device::data_read_dag2(UINT32 op)
+{
+ UINT32 ireg = 4 + ((op >> 2) & 3);
+ UINT32 mreg = 4 + (op & 3);
+ UINT32 base = m_base[ireg];
+ UINT32 i = m_i[ireg];
+ UINT32 l = m_l[ireg];
+
+ UINT32 res = data_read(i);
+
+ i += m_m[mreg];
+ if (i < base) i += l;
+ else if (i >= base + l) i -= l;
+ m_i[ireg] = i;
+
+ return res;
+}
+
+/*===========================================================================
+ Program memory accessors
+===========================================================================*/
+
+inline void adsp21xx_device::pgm_write_dag2(UINT32 op, INT32 val)
+{
+ UINT32 ireg = 4 + ((op >> 2) & 3);
+ UINT32 mreg = 4 + (op & 3);
+ UINT32 base = m_base[ireg];
+ UINT32 i = m_i[ireg];
+ UINT32 l = m_l[ireg];
+
+ program_write(i, (val << 8) | m_px);
+
+ i += m_m[mreg];
+ if (i < base) i += l;
+ else if (i >= base + l) i -= l;
+ m_i[ireg] = i;
+}
+
+
+inline UINT32 adsp21xx_device::pgm_read_dag2(UINT32 op)
+{
+ UINT32 ireg = 4 + ((op >> 2) & 3);
+ UINT32 mreg = 4 + (op & 3);
+ UINT32 base = m_base[ireg];
+ UINT32 i = m_i[ireg];
+ UINT32 l = m_l[ireg];
+ UINT32 res;
+
+ res = program_read(i);
+ m_px = res;
+ res >>= 8;
+
+ i += m_m[mreg];
+ if (i < base) i += l;
+ else if (i >= base + l) i -= l;
+ m_i[ireg] = i;
+
+ return res;
+}
+
+
+
+/*===========================================================================
+ register reading
+===========================================================================*/
+
+#define ALU_GETXREG_UNSIGNED(x) (*(UINT16 *)m_alu_xregs[x])
+#define ALU_GETYREG_UNSIGNED(y) (*(UINT16 *)m_alu_yregs[y])
+
+#define MAC_GETXREG_UNSIGNED(x) (*(UINT16 *)m_mac_xregs[x])
+#define MAC_GETXREG_SIGNED(x) (*( INT16 *)m_mac_xregs[x])
+#define MAC_GETYREG_UNSIGNED(y) (*(UINT16 *)m_mac_yregs[y])
+#define MAC_GETYREG_SIGNED(y) (*( INT16 *)m_mac_yregs[y])
+
+#define SHIFT_GETXREG_UNSIGNED(x) (*(UINT16 *)m_shift_xregs[x])
+#define SHIFT_GETXREG_SIGNED(x) (*( INT16 *)m_shift_xregs[x])
+
+
+
+/*===========================================================================
+ ALU operations (result in AR)
+===========================================================================*/
+
+void adsp21xx_device::alu_op_ar(int op)
+{
+ INT32 xop = (op >> 8) & 7;
+ INT32 yop = (op >> 11) & 3;
+ INT32 res;
+
+ switch (op & (15<<13)) /*JB*/
+ {
+ case 0x00<<13:
+ /* Y Clear when y = 0 */
+ res = ALU_GETYREG_UNSIGNED(yop);
+ CALC_NZ(res);
+ break;
+ case 0x01<<13:
+ /* Y + 1 PASS 1 when y = 0 */
+ yop = ALU_GETYREG_UNSIGNED(yop);
+ res = yop + 1;
+ CALC_NZ(res);
+ if (yop == 0x7fff) SET_V;
+ else if (yop == 0xffff) SET_C;
+ break;
+ case 0x02<<13:
+ /* X + Y + C */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ yop = ALU_GETYREG_UNSIGNED(yop);
+ yop += GET_C >> 3;
+ res = xop + yop;
+ CALC_NZVC(xop, yop, res);
+ break;
+ case 0x03<<13:
+ /* X + Y X when y = 0 */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ yop = ALU_GETYREG_UNSIGNED(yop);
+ res = xop + yop;
+ CALC_NZVC(xop, yop, res);
+ break;
+ case 0x04<<13:
+ /* NOT Y */
+ res = ALU_GETYREG_UNSIGNED(yop) ^ 0xffff;
+ CALC_NZ(res);
+ break;
+ case 0x05<<13:
+ /* -Y */
+ yop = ALU_GETYREG_UNSIGNED(yop);
+ res = -yop;
+ CALC_NZ(res);
+ if (yop == 0x8000) SET_V;
+ if (yop == 0x0000) SET_C;
+ break;
+ case 0x06<<13:
+ /* X - Y + C - 1 X + C - 1 when y = 0 */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ yop = ALU_GETYREG_UNSIGNED(yop);
+ res = xop - yop + (GET_C >> 3) - 1;
+ CALC_NZVC_SUB(xop, yop, res);
+ break;
+ case 0x07<<13:
+ /* X - Y */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ yop = ALU_GETYREG_UNSIGNED(yop);
+ res = xop - yop;
+ CALC_NZVC_SUB(xop, yop, res);
+ break;
+ case 0x08<<13:
+ /* Y - 1 PASS -1 when y = 0 */
+ yop = ALU_GETYREG_UNSIGNED(yop);
+ res = yop - 1;
+ CALC_NZ(res);
+ if (yop == 0x8000) SET_V;
+ else if (yop == 0x0000) SET_C;
+ break;
+ case 0x09<<13:
+ /* Y - X -X when y = 0 */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ yop = ALU_GETYREG_UNSIGNED(yop);
+ res = yop - xop;
+ CALC_NZVC_SUB(yop, xop, res);
+ break;
+ case 0x0a<<13:
+ /* Y - X + C - 1 -X + C - 1 when y = 0 */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ yop = ALU_GETYREG_UNSIGNED(yop);
+ res = yop - xop + (GET_C >> 3) - 1;
+ CALC_NZVC_SUB(yop, xop, res);
+ break;
+ case 0x0b<<13:
+ /* NOT X */
+ res = ALU_GETXREG_UNSIGNED(xop) ^ 0xffff;
+ CALC_NZ(res);
+ break;
+ case 0x0c<<13:
+ /* X AND Y */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ yop = ALU_GETYREG_UNSIGNED(yop);
+ res = xop & yop;
+ CALC_NZ(res);
+ break;
+ case 0x0d<<13:
+ /* X OR Y */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ yop = ALU_GETYREG_UNSIGNED(yop);
+ res = xop | yop;
+ CALC_NZ(res);
+ break;
+ case 0x0e<<13:
+ /* X XOR Y */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ yop = ALU_GETYREG_UNSIGNED(yop);
+ res = xop ^ yop;
+ CALC_NZ(res);
+ break;
+ case 0x0f<<13:
+ /* ABS X */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ res = (xop & 0x8000) ? -xop : xop;
+ CLR_FLAGS;
+ if (xop == 0) SET_Z;
+ if (xop == 0x8000) SET_N, SET_V;
+ if (xop & 0x8000) SET_S;
+ break;
+ default:
+ res = 0; /* just to keep the compiler happy */
+ break;
+ }
+
+ /* saturate */
+ if ((m_mstat & MSTAT_SATURATE) && GET_V) res = GET_C ? -32768 : 32767;
+
+ /* set the final value */
+ m_core.ar.u = res;
+}
+
+
+
+/*===========================================================================
+ ALU operations (result in AR, constant yop)
+===========================================================================*/
+
+void adsp21xx_device::alu_op_ar_const(int op)
+{
+ INT32 xop = (op >> 8) & 7;
+ INT32 yop = constants[((op >> 5) & 0x07) | ((op >> 8) & 0x18)];
+ INT32 res;
+
+ switch (op & (15<<13)) /*JB*/
+ {
+ case 0x00<<13:
+ /* Y Clear when y = 0 */
+ res = yop;
+ CALC_NZ(res);
+ break;
+ case 0x01<<13:
+ /* Y + 1 PASS 1 when y = 0 */
+ res = yop + 1;
+ CALC_NZ(res);
+ if (yop == 0x7fff) SET_V;
+ else if (yop == 0xffff) SET_C;
+ break;
+ case 0x02<<13:
+ /* X + Y + C */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ yop += GET_C >> 3;
+ res = xop + yop;
+ CALC_NZVC(xop, yop, res);
+ break;
+ case 0x03<<13:
+ /* X + Y X when y = 0 */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ res = xop + yop;
+ CALC_NZVC(xop, yop, res);
+ break;
+ case 0x04<<13:
+ /* NOT Y */
+ res = yop ^ 0xffff;
+ CALC_NZ(res);
+ break;
+ case 0x05<<13:
+ /* -Y */
+ res = -yop;
+ CALC_NZ(res);
+ if (yop == 0x8000) SET_V;
+ if (yop == 0x0000) SET_C;
+ break;
+ case 0x06<<13:
+ /* X - Y + C - 1 X + C - 1 when y = 0 */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ res = xop - yop + (GET_C >> 3) - 1;
+ CALC_NZVC_SUB(xop, yop, res);
+ break;
+ case 0x07<<13:
+ /* X - Y */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ res = xop - yop;
+ CALC_NZVC_SUB(xop, yop, res);
+ break;
+ case 0x08<<13:
+ /* Y - 1 PASS -1 when y = 0 */
+ res = yop - 1;
+ CALC_NZ(res);
+ if (yop == 0x8000) SET_V;
+ else if (yop == 0x0000) SET_C;
+ break;
+ case 0x09<<13:
+ /* Y - X -X when y = 0 */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ res = yop - xop;
+ CALC_NZVC_SUB(yop, xop, res);
+ break;
+ case 0x0a<<13:
+ /* Y - X + C - 1 -X + C - 1 when y = 0 */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ res = yop - xop + (GET_C >> 3) - 1;
+ CALC_NZVC_SUB(yop, xop, res);
+ break;
+ case 0x0b<<13:
+ /* NOT X */
+ res = ALU_GETXREG_UNSIGNED(xop) ^ 0xffff;
+ CALC_NZ(res);
+ break;
+ case 0x0c<<13:
+ /* X AND Y */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ res = xop & yop;
+ CALC_NZ(res);
+ break;
+ case 0x0d<<13:
+ /* X OR Y */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ res = xop | yop;
+ CALC_NZ(res);
+ break;
+ case 0x0e<<13:
+ /* X XOR Y */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ res = xop ^ yop;
+ CALC_NZ(res);
+ break;
+ case 0x0f<<13:
+ /* ABS X */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ res = (xop & 0x8000) ? -xop : xop;
+ CLR_FLAGS;
+ if (xop == 0) SET_Z;
+ if (xop == 0x8000) SET_N, SET_V;
+ if (xop & 0x8000) SET_S;
+ break;
+ default:
+ res = 0; /* just to keep the compiler happy */
+ break;
+ }
+
+ /* saturate */
+ if ((m_mstat & MSTAT_SATURATE) && GET_V) res = GET_C ? -32768 : 32767;
+
+ /* set the final value */
+ m_core.ar.u = res;
+}
+
+
+
+/*===========================================================================
+ ALU operations (result in AF)
+===========================================================================*/
+
+void adsp21xx_device::alu_op_af(int op)
+{
+ INT32 xop = (op >> 8) & 7;
+ INT32 yop = (op >> 11) & 3;
+ INT32 res;
+
+ switch (op & (15<<13)) /*JB*/
+ {
+ case 0x00<<13:
+ /* Y Clear when y = 0 */
+ res = ALU_GETYREG_UNSIGNED(yop);
+ CALC_NZ(res);
+ break;
+ case 0x01<<13:
+ /* Y + 1 PASS 1 when y = 0 */
+ yop = ALU_GETYREG_UNSIGNED(yop);
+ res = yop + 1;
+ CALC_NZ(res);
+ if (yop == 0x7fff) SET_V;
+ else if (yop == 0xffff) SET_C;
+ break;
+ case 0x02<<13:
+ /* X + Y + C */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ yop = ALU_GETYREG_UNSIGNED(yop);
+ yop += GET_C >> 3;
+ res = xop + yop;
+ CALC_NZVC(xop, yop, res);
+ break;
+ case 0x03<<13:
+ /* X + Y X when y = 0 */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ yop = ALU_GETYREG_UNSIGNED(yop);
+ res = xop + yop;
+ CALC_NZVC(xop, yop, res);
+ break;
+ case 0x04<<13:
+ /* NOT Y */
+ res = ALU_GETYREG_UNSIGNED(yop) ^ 0xffff;
+ CALC_NZ(res);
+ break;
+ case 0x05<<13:
+ /* -Y */
+ yop = ALU_GETYREG_UNSIGNED(yop);
+ res = -yop;
+ CALC_NZ(res);
+ if (yop == 0x8000) SET_V;
+ if (yop == 0x0000) SET_C;
+ break;
+ case 0x06<<13:
+ /* X - Y + C - 1 X + C - 1 when y = 0 */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ yop = ALU_GETYREG_UNSIGNED(yop);
+ res = xop - yop + (GET_C >> 3) - 1;
+ CALC_NZVC_SUB(xop, yop, res);
+ break;
+ case 0x07<<13:
+ /* X - Y */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ yop = ALU_GETYREG_UNSIGNED(yop);
+ res = xop - yop;
+ CALC_NZVC_SUB(xop, yop, res);
+ break;
+ case 0x08<<13:
+ /* Y - 1 PASS -1 when y = 0 */
+ yop = ALU_GETYREG_UNSIGNED(yop);
+ res = yop - 1;
+ CALC_NZ(res);
+ if (yop == 0x8000) SET_V;
+ else if (yop == 0x0000) SET_C;
+ break;
+ case 0x09<<13:
+ /* Y - X -X when y = 0 */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ yop = ALU_GETYREG_UNSIGNED(yop);
+ res = yop - xop;
+ CALC_NZVC_SUB(yop, xop, res);
+ break;
+ case 0x0a<<13:
+ /* Y - X + C - 1 -X + C - 1 when y = 0 */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ yop = ALU_GETYREG_UNSIGNED(yop);
+ res = yop - xop + (GET_C >> 3) - 1;
+ CALC_NZVC_SUB(yop, xop, res);
+ break;
+ case 0x0b<<13:
+ /* NOT X */
+ res = ALU_GETXREG_UNSIGNED(xop) ^ 0xffff;
+ CALC_NZ(res);
+ break;
+ case 0x0c<<13:
+ /* X AND Y */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ yop = ALU_GETYREG_UNSIGNED(yop);
+ res = xop & yop;
+ CALC_NZ(res);
+ break;
+ case 0x0d<<13:
+ /* X OR Y */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ yop = ALU_GETYREG_UNSIGNED(yop);
+ res = xop | yop;
+ CALC_NZ(res);
+ break;
+ case 0x0e<<13:
+ /* X XOR Y */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ yop = ALU_GETYREG_UNSIGNED(yop);
+ res = xop ^ yop;
+ CALC_NZ(res);
+ break;
+ case 0x0f<<13:
+ /* ABS X */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ res = (xop & 0x8000) ? -xop : xop;
+ CLR_FLAGS;
+ if (xop == 0) SET_Z;
+ if (xop == 0x8000) SET_N, SET_V;
+ if (xop & 0x8000) SET_S;
+ break;
+ default:
+ res = 0; /* just to keep the compiler happy */
+ break;
+ }
+
+ /* set the final value */
+ m_core.af.u = res;
+}
+
+
+
+/*===========================================================================
+ ALU operations (result in AF, constant yop)
+===========================================================================*/
+
+void adsp21xx_device::alu_op_af_const(int op)
+{
+ INT32 xop = (op >> 8) & 7;
+ INT32 yop = constants[((op >> 5) & 0x07) | ((op >> 8) & 0x18)];
+ INT32 res;
+
+ switch (op & (15<<13)) /*JB*/
+ {
+ case 0x00<<13:
+ /* Y Clear when y = 0 */
+ res = yop;
+ CALC_NZ(res);
+ break;
+ case 0x01<<13:
+ /* Y + 1 PASS 1 when y = 0 */
+ res = yop + 1;
+ CALC_NZ(res);
+ if (yop == 0x7fff) SET_V;
+ else if (yop == 0xffff) SET_C;
+ break;
+ case 0x02<<13:
+ /* X + Y + C */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ yop += GET_C >> 3;
+ res = xop + yop;
+ CALC_NZVC(xop, yop, res);
+ break;
+ case 0x03<<13:
+ /* X + Y X when y = 0 */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ res = xop + yop;
+ CALC_NZVC(xop, yop, res);
+ break;
+ case 0x04<<13:
+ /* NOT Y */
+ res = yop ^ 0xffff;
+ CALC_NZ(res);
+ break;
+ case 0x05<<13:
+ /* -Y */
+ res = -yop;
+ CALC_NZ(res);
+ if (yop == 0x8000) SET_V;
+ if (yop == 0x0000) SET_C;
+ break;
+ case 0x06<<13:
+ /* X - Y + C - 1 X + C - 1 when y = 0 */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ res = xop - yop + (GET_C >> 3) - 1;
+ CALC_NZVC_SUB(xop, yop, res);
+ break;
+ case 0x07<<13:
+ /* X - Y */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ res = xop - yop;
+ CALC_NZVC_SUB(xop, yop, res);
+ break;
+ case 0x08<<13:
+ /* Y - 1 PASS -1 when y = 0 */
+ res = yop - 1;
+ CALC_NZ(res);
+ if (yop == 0x8000) SET_V;
+ else if (yop == 0x0000) SET_C;
+ break;
+ case 0x09<<13:
+ /* Y - X -X when y = 0 */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ res = yop - xop;
+ CALC_NZVC_SUB(yop, xop, res);
+ break;
+ case 0x0a<<13:
+ /* Y - X + C - 1 -X + C - 1 when y = 0 */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ res = yop - xop + (GET_C >> 3) - 1;
+ CALC_NZVC_SUB(yop, xop, res);
+ break;
+ case 0x0b<<13:
+ /* NOT X */
+ res = ALU_GETXREG_UNSIGNED(xop) ^ 0xffff;
+ CALC_NZ(res);
+ break;
+ case 0x0c<<13:
+ /* X AND Y */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ res = xop & yop;
+ CALC_NZ(res);
+ break;
+ case 0x0d<<13:
+ /* X OR Y */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ res = xop | yop;
+ CALC_NZ(res);
+ break;
+ case 0x0e<<13:
+ /* X XOR Y */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ res = xop ^ yop;
+ CALC_NZ(res);
+ break;
+ case 0x0f<<13:
+ /* ABS X */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ res = (xop & 0x8000) ? -xop : xop;
+ CLR_FLAGS;
+ if (xop == 0) SET_Z;
+ if (xop == 0x8000) SET_N, SET_V;
+ if (xop & 0x8000) SET_S;
+ break;
+ default:
+ res = 0; /* just to keep the compiler happy */
+ break;
+ }
+
+ /* set the final value */
+ m_core.af.u = res;
+}
+
+
+
+/*===========================================================================
+ ALU operations (no result)
+===========================================================================*/
+
+void adsp21xx_device::alu_op_none(int op)
+{
+ INT32 xop = (op >> 8) & 7;
+ INT32 yop = (op >> 11) & 3;
+ INT32 res;
+
+ switch (op & (15<<13)) /*JB*/
+ {
+ case 0x00<<13:
+ /* Y Clear when y = 0 */
+ res = ALU_GETYREG_UNSIGNED(yop);
+ CALC_NZ(res);
+ break;
+ case 0x01<<13:
+ /* Y + 1 PASS 1 when y = 0 */
+ yop = ALU_GETYREG_UNSIGNED(yop);
+ res = yop + 1;
+ CALC_NZ(res);
+ if (yop == 0x7fff) SET_V;
+ else if (yop == 0xffff) SET_C;
+ break;
+ case 0x02<<13:
+ /* X + Y + C */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ yop = ALU_GETYREG_UNSIGNED(yop);
+ yop += GET_C >> 3;
+ res = xop + yop;
+ CALC_NZVC(xop, yop, res);
+ break;
+ case 0x03<<13:
+ /* X + Y X when y = 0 */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ yop = ALU_GETYREG_UNSIGNED(yop);
+ res = xop + yop;
+ CALC_NZVC(xop, yop, res);
+ break;
+ case 0x04<<13:
+ /* NOT Y */
+ res = ALU_GETYREG_UNSIGNED(yop) ^ 0xffff;
+ CALC_NZ(res);
+ break;
+ case 0x05<<13:
+ /* -Y */
+ yop = ALU_GETYREG_UNSIGNED(yop);
+ res = -yop;
+ CALC_NZ(res);
+ if (yop == 0x8000) SET_V;
+ if (yop == 0x0000) SET_C;
+ break;
+ case 0x06<<13:
+ /* X - Y + C - 1 X + C - 1 when y = 0 */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ yop = ALU_GETYREG_UNSIGNED(yop);
+ res = xop - yop + (GET_C >> 3) - 1;
+ CALC_NZVC_SUB(xop, yop, res);
+ break;
+ case 0x07<<13:
+ /* X - Y */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ yop = ALU_GETYREG_UNSIGNED(yop);
+ res = xop - yop;
+ CALC_NZVC_SUB(xop, yop, res);
+ break;
+ case 0x08<<13:
+ /* Y - 1 PASS -1 when y = 0 */
+ yop = ALU_GETYREG_UNSIGNED(yop);
+ res = yop - 1;
+ CALC_NZ(res);
+ if (yop == 0x8000) SET_V;
+ else if (yop == 0x0000) SET_C;
+ break;
+ case 0x09<<13:
+ /* Y - X -X when y = 0 */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ yop = ALU_GETYREG_UNSIGNED(yop);
+ res = yop - xop;
+ CALC_NZVC_SUB(yop, xop, res);
+ break;
+ case 0x0a<<13:
+ /* Y - X + C - 1 -X + C - 1 when y = 0 */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ yop = ALU_GETYREG_UNSIGNED(yop);
+ res = yop - xop + (GET_C >> 3) - 1;
+ CALC_NZVC_SUB(yop, xop, res);
+ break;
+ case 0x0b<<13:
+ /* NOT X */
+ res = ALU_GETXREG_UNSIGNED(xop) ^ 0xffff;
+ CALC_NZ(res);
+ break;
+ case 0x0c<<13:
+ /* X AND Y */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ yop = ALU_GETYREG_UNSIGNED(yop);
+ res = xop & yop;
+ CALC_NZ(res);
+ break;
+ case 0x0d<<13:
+ /* X OR Y */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ yop = ALU_GETYREG_UNSIGNED(yop);
+ res = xop | yop;
+ CALC_NZ(res);
+ break;
+ case 0x0e<<13:
+ /* X XOR Y */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ yop = ALU_GETYREG_UNSIGNED(yop);
+ res = xop ^ yop;
+ CALC_NZ(res);
+ break;
+ case 0x0f<<13:
+ /* ABS X */
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ res = (xop & 0x8000) ? -xop : xop;
+ CLR_FLAGS;
+ if (xop == 0) SET_Z;
+ if (xop == 0x8000) SET_N, SET_V;
+ if (xop & 0x8000) SET_S;
+ break;
+ }
+}
+
+
+
+/*===========================================================================
+ MAC operations (result in MR)
+===========================================================================*/
+
+void adsp21xx_device::mac_op_mr(int op)
+{
+ INT8 shift = ((m_mstat & MSTAT_INTEGER) >> 4) ^ 1;
+ INT32 xop = (op >> 8) & 7;
+ INT32 yop = (op >> 11) & 3;
+ INT32 temp;
+ INT64 res;
+
+ switch (op & (15<<13)) /*JB*/
+ {
+ case 0x00<<13:
+ /* no-op */
+ return;
+ case 0x01<<13:
+ /* X * Y (RND) */
+ xop = MAC_GETXREG_SIGNED(xop);
+ yop = MAC_GETYREG_SIGNED(yop);
+ temp = (xop * yop) << shift;
+ res = (INT64)temp;
+#if 0
+ if ((res & 0xffff) == 0x8000) res &= ~((UINT64)0x10000);
+ else res += (res & 0x8000) << 1;
+#else
+ temp &= 0xffff;
+ res += 0x8000;
+ if ( temp == 0x8000 )
+ res &= ~((UINT64)0x10000);
+#endif
+ break;
+ case 0x02<<13:
+ /* MR + X * Y (RND) */
+ xop = MAC_GETXREG_SIGNED(xop);
+ yop = MAC_GETYREG_SIGNED(yop);
+ temp = (xop * yop) << shift;
+ res = m_core.mr.mr + (INT64)temp;
+#if 0
+ if ((res & 0xffff) == 0x8000) res &= ~((UINT64)0x10000);
+ else res += (res & 0x8000) << 1;
+#else
+ temp &= 0xffff;
+ res += 0x8000;
+ if ( temp == 0x8000 )
+ res &= ~((UINT64)0x10000);
+#endif
+ break;
+ case 0x03<<13:
+ /* MR - X * Y (RND) */
+ xop = MAC_GETXREG_SIGNED(xop);
+ yop = MAC_GETYREG_SIGNED(yop);
+ temp = (xop * yop) << shift;
+ res = m_core.mr.mr - (INT64)temp;
+#if 0
+ if ((res & 0xffff) == 0x8000) res &= ~((UINT64)0x10000);
+ else res += (res & 0x8000) << 1;
+#else
+ temp &= 0xffff;
+ res += 0x8000;
+ if ( temp == 0x8000 )
+ res &= ~((UINT64)0x10000);
+#endif
+ break;
+ case 0x04<<13:
+ /* X * Y (SS) Clear when y = 0 */
+ xop = MAC_GETXREG_SIGNED(xop);
+ yop = MAC_GETYREG_SIGNED(yop);
+ temp = (xop * yop) << shift;
+ res = (INT64)temp;
+ break;
+ case 0x05<<13:
+ /* X * Y (SU) */
+ xop = MAC_GETXREG_SIGNED(xop);
+ yop = MAC_GETYREG_UNSIGNED(yop);
+ temp = (xop * yop) << shift;
+ res = (INT64)temp;
+ break;
+ case 0x06<<13:
+ /* X * Y (US) */
+ xop = MAC_GETXREG_UNSIGNED(xop);
+ yop = MAC_GETYREG_SIGNED(yop);
+ temp = (xop * yop) << shift;
+ res = (INT64)temp;
+ break;
+ case 0x07<<13:
+ /* X * Y (UU) */
+ xop = MAC_GETXREG_UNSIGNED(xop);
+ yop = MAC_GETYREG_UNSIGNED(yop);
+ temp = (xop * yop) << shift;
+ res = (INT64)temp;
+ break;
+ case 0x08<<13:
+ /* MR + X * Y (SS) */
+ xop = MAC_GETXREG_SIGNED(xop);
+ yop = MAC_GETYREG_SIGNED(yop);
+ temp = (xop * yop) << shift;
+ res = m_core.mr.mr + (INT64)temp;
+ break;
+ case 0x09<<13:
+ /* MR + X * Y (SU) */
+ xop = MAC_GETXREG_SIGNED(xop);
+ yop = MAC_GETYREG_UNSIGNED(yop);
+ temp = (xop * yop) << shift;
+ res = m_core.mr.mr + (INT64)temp;
+ break;
+ case 0x0a<<13:
+ /* MR + X * Y (US) */
+ xop = MAC_GETXREG_UNSIGNED(xop);
+ yop = MAC_GETYREG_SIGNED(yop);
+ temp = (xop * yop) << shift;
+ res = m_core.mr.mr + (INT64)temp;
+ break;
+ case 0x0b<<13:
+ /* MR + X * Y (UU) */
+ xop = MAC_GETXREG_UNSIGNED(xop);
+ yop = MAC_GETYREG_UNSIGNED(yop);
+ temp = (xop * yop) << shift;
+ res = m_core.mr.mr + (INT64)temp;
+ break;
+ case 0x0c<<13:
+ /* MR - X * Y (SS) */
+ xop = MAC_GETXREG_SIGNED(xop);
+ yop = MAC_GETYREG_SIGNED(yop);
+ temp = (xop * yop) << shift;
+ res = m_core.mr.mr - (INT64)temp;
+ break;
+ case 0x0d<<13:
+ /* MR - X * Y (SU) */
+ xop = MAC_GETXREG_SIGNED(xop);
+ yop = MAC_GETYREG_UNSIGNED(yop);
+ temp = (xop * yop) << shift;
+ res = m_core.mr.mr - (INT64)temp;
+ break;
+ case 0x0e<<13:
+ /* MR - X * Y (US) */
+ xop = MAC_GETXREG_UNSIGNED(xop);
+ yop = MAC_GETYREG_SIGNED(yop);
+ temp = (xop * yop) << shift;
+ res = m_core.mr.mr - (INT64)temp;
+ break;
+ case 0x0f<<13:
+ /* MR - X * Y (UU) */
+ xop = MAC_GETXREG_UNSIGNED(xop);
+ yop = MAC_GETYREG_UNSIGNED(yop);
+ temp = (xop * yop) << shift;
+ res = m_core.mr.mr - (INT64)temp;
+ break;
+ default:
+ res = 0; /* just to keep the compiler happy */
+ break;
+ }
+
+ /* set the final value */
+ temp = (res >> 31) & 0x1ff;
+ CLR_MV;
+ if (temp != 0x000 && temp != 0x1ff) SET_MV;
+ m_core.mr.mr = res;
+}
+
+
+
+/*===========================================================================
+ MAC operations (result in MR, yop == xop)
+===========================================================================*/
+
+void adsp21xx_device::mac_op_mr_xop(int op)
+{
+ INT8 shift = ((m_mstat & MSTAT_INTEGER) >> 4) ^ 1;
+ INT32 xop = (op >> 8) & 7;
+ INT32 temp;
+ INT64 res;
+
+ switch (op & (15<<13)) /*JB*/
+ {
+ case 0x00<<13:
+ /* no-op */
+ return;
+ case 0x01<<13:
+ /* X * Y (RND) */
+ xop = MAC_GETXREG_SIGNED(xop);
+ temp = (xop * xop) << shift;
+ res = (INT64)temp;
+#if 0
+ if ((res & 0xffff) == 0x8000) res &= ~((UINT64)0x10000);
+ else res += (res & 0x8000) << 1;
+#else
+ temp &= 0xffff;
+ res += 0x8000;
+ if ( temp == 0x8000 )
+ res &= ~((UINT64)0x10000);
+#endif
+ break;
+ case 0x02<<13:
+ /* MR + X * Y (RND) */
+ xop = MAC_GETXREG_SIGNED(xop);
+ temp = (xop * xop) << shift;
+ res = m_core.mr.mr + (INT64)temp;
+#if 0
+ if ((res & 0xffff) == 0x8000) res &= ~((UINT64)0x10000);
+ else res += (res & 0x8000) << 1;
+#else
+ temp &= 0xffff;
+ res += 0x8000;
+ if ( temp == 0x8000 )
+ res &= ~((UINT64)0x10000);
+#endif
+ break;
+ case 0x03<<13:
+ /* MR - X * Y (RND) */
+ xop = MAC_GETXREG_SIGNED(xop);
+ temp = (xop * xop) << shift;
+ res = m_core.mr.mr - (INT64)temp;
+#if 0
+ if ((res & 0xffff) == 0x8000) res &= ~((UINT64)0x10000);
+ else res += (res & 0x8000) << 1;
+#else
+ temp &= 0xffff;
+ res += 0x8000;
+ if ( temp == 0x8000 )
+ res &= ~((UINT64)0x10000);
+#endif
+ break;
+ case 0x04<<13:
+ /* X * Y (SS) Clear when y = 0 */
+ xop = MAC_GETXREG_SIGNED(xop);
+ temp = (xop * xop) << shift;
+ res = (INT64)temp;
+ break;
+ case 0x05<<13:
+ /* X * Y (SU) */
+ xop = MAC_GETXREG_SIGNED(xop);
+ temp = (xop * xop) << shift;
+ res = (INT64)temp;
+ break;
+ case 0x06<<13:
+ /* X * Y (US) */
+ xop = MAC_GETXREG_UNSIGNED(xop);
+ temp = (xop * xop) << shift;
+ res = (INT64)temp;
+ break;
+ case 0x07<<13:
+ /* X * Y (UU) */
+ xop = MAC_GETXREG_UNSIGNED(xop);
+ temp = (xop * xop) << shift;
+ res = (INT64)temp;
+ break;
+ case 0x08<<13:
+ /* MR + X * Y (SS) */
+ xop = MAC_GETXREG_SIGNED(xop);
+ temp = (xop * xop) << shift;
+ res = m_core.mr.mr + (INT64)temp;
+ break;
+ case 0x09<<13:
+ /* MR + X * Y (SU) */
+ xop = MAC_GETXREG_SIGNED(xop);
+ temp = (xop * xop) << shift;
+ res = m_core.mr.mr + (INT64)temp;
+ break;
+ case 0x0a<<13:
+ /* MR + X * Y (US) */
+ xop = MAC_GETXREG_UNSIGNED(xop);
+ temp = (xop * xop) << shift;
+ res = m_core.mr.mr + (INT64)temp;
+ break;
+ case 0x0b<<13:
+ /* MR + X * Y (UU) */
+ xop = MAC_GETXREG_UNSIGNED(xop);
+ temp = (xop * xop) << shift;
+ res = m_core.mr.mr + (INT64)temp;
+ break;
+ case 0x0c<<13:
+ /* MR - X * Y (SS) */
+ xop = MAC_GETXREG_SIGNED(xop);
+ temp = (xop * xop) << shift;
+ res = m_core.mr.mr - (INT64)temp;
+ break;
+ case 0x0d<<13:
+ /* MR - X * Y (SU) */
+ xop = MAC_GETXREG_SIGNED(xop);
+ temp = (xop * xop) << shift;
+ res = m_core.mr.mr - (INT64)temp;
+ break;
+ case 0x0e<<13:
+ /* MR - X * Y (US) */
+ xop = MAC_GETXREG_UNSIGNED(xop);
+ temp = (xop * xop) << shift;
+ res = m_core.mr.mr - (INT64)temp;
+ break;
+ case 0x0f<<13:
+ /* MR - X * Y (UU) */
+ xop = MAC_GETXREG_UNSIGNED(xop);
+ temp = (xop * xop) << shift;
+ res = m_core.mr.mr - (INT64)temp;
+ break;
+ default:
+ res = 0; /* just to keep the compiler happy */
+ break;
+ }
+
+ /* set the final value */
+ temp = (res >> 31) & 0x1ff;
+ CLR_MV;
+ if (temp != 0x000 && temp != 0x1ff) SET_MV;
+ m_core.mr.mr = res;
+}
+
+
+
+/*===========================================================================
+ MAC operations (result in MF)
+===========================================================================*/
+
+void adsp21xx_device::mac_op_mf(int op)
+{
+ INT8 shift = ((m_mstat & MSTAT_INTEGER) >> 4) ^ 1;
+ INT32 xop = (op >> 8) & 7;
+ INT32 yop = (op >> 11) & 3;
+ INT32 temp;
+ INT64 res;
+
+ switch (op & (15<<13)) /*JB*/
+ {
+ case 0x00<<13:
+ /* no-op */
+ return;
+ case 0x01<<13:
+ /* X * Y (RND) */
+ xop = MAC_GETXREG_SIGNED(xop);
+ yop = MAC_GETYREG_SIGNED(yop);
+ temp = (xop * yop) << shift;
+ res = (INT64)temp;
+#if 0
+ if ((res & 0xffff) == 0x8000) res &= ~((UINT64)0x10000);
+ else res += (res & 0x8000) << 1;
+#else
+ temp &= 0xffff;
+ res += 0x8000;
+ if ( temp == 0x8000 )
+ res &= ~((UINT64)0x10000);
+#endif
+ break;
+ case 0x02<<13:
+ /* MR + X * Y (RND) */
+ xop = MAC_GETXREG_SIGNED(xop);
+ yop = MAC_GETYREG_SIGNED(yop);
+ temp = (xop * yop) << shift;
+ res = m_core.mr.mr + (INT64)temp;
+#if 0
+ if ((res & 0xffff) == 0x8000) res &= ~((UINT64)0x10000);
+ else res += (res & 0x8000) << 1;
+#else
+ temp &= 0xffff;
+ res += 0x8000;
+ if ( temp == 0x8000 )
+ res &= ~((UINT64)0x10000);
+#endif
+ break;
+ case 0x03<<13:
+ /* MR - X * Y (RND) */
+ xop = MAC_GETXREG_SIGNED(xop);
+ yop = MAC_GETYREG_SIGNED(yop);
+ temp = (xop * yop) << shift;
+ res = m_core.mr.mr - (INT64)temp;
+#if 0
+ if ((res & 0xffff) == 0x8000) res &= ~((UINT64)0x10000);
+ else res += (res & 0x8000) << 1;
+#else
+ temp &= 0xffff;
+ res += 0x8000;
+ if ( temp == 0x8000 )
+ res &= ~((UINT64)0x10000);
+#endif
+ break;
+ case 0x04<<13:
+ /* X * Y (SS) Clear when y = 0 */
+ xop = MAC_GETXREG_SIGNED(xop);
+ yop = MAC_GETYREG_SIGNED(yop);
+ temp = (xop * yop) << shift;
+ res = (INT64)temp;
+ break;
+ case 0x05<<13:
+ /* X * Y (SU) */
+ xop = MAC_GETXREG_SIGNED(xop);
+ yop = MAC_GETYREG_UNSIGNED(yop);
+ temp = (xop * yop) << shift;
+ res = (INT64)temp;
+ break;
+ case 0x06<<13:
+ /* X * Y (US) */
+ xop = MAC_GETXREG_UNSIGNED(xop);
+ yop = MAC_GETYREG_SIGNED(yop);
+ temp = (xop * yop) << shift;
+ res = (INT64)temp;
+ break;
+ case 0x07<<13:
+ /* X * Y (UU) */
+ xop = MAC_GETXREG_UNSIGNED(xop);
+ yop = MAC_GETYREG_UNSIGNED(yop);
+ temp = (xop * yop) << shift;
+ res = (INT64)temp;
+ break;
+ case 0x08<<13:
+ /* MR + X * Y (SS) */
+ xop = MAC_GETXREG_SIGNED(xop);
+ yop = MAC_GETYREG_SIGNED(yop);
+ temp = (xop * yop) << shift;
+ res = m_core.mr.mr + (INT64)temp;
+ break;
+ case 0x09<<13:
+ /* MR + X * Y (SU) */
+ xop = MAC_GETXREG_SIGNED(xop);
+ yop = MAC_GETYREG_UNSIGNED(yop);
+ temp = (xop * yop) << shift;
+ res = m_core.mr.mr + (INT64)temp;
+ break;
+ case 0x0a<<13:
+ /* MR + X * Y (US) */
+ xop = MAC_GETXREG_UNSIGNED(xop);
+ yop = MAC_GETYREG_SIGNED(yop);
+ temp = (xop * yop) << shift;
+ res = m_core.mr.mr + (INT64)temp;
+ break;
+ case 0x0b<<13:
+ /* MR + X * Y (UU) */
+ xop = MAC_GETXREG_UNSIGNED(xop);
+ yop = MAC_GETYREG_UNSIGNED(yop);
+ temp = (xop * yop) << shift;
+ res = m_core.mr.mr + (INT64)temp;
+ break;
+ case 0x0c<<13:
+ /* MR - X * Y (SS) */
+ xop = MAC_GETXREG_SIGNED(xop);
+ yop = MAC_GETYREG_SIGNED(yop);
+ temp = (xop * yop) << shift;
+ res = m_core.mr.mr - (INT64)temp;
+ break;
+ case 0x0d<<13:
+ /* MR - X * Y (SU) */
+ xop = MAC_GETXREG_SIGNED(xop);
+ yop = MAC_GETYREG_UNSIGNED(yop);
+ temp = (xop * yop) << shift;
+ res = m_core.mr.mr - (INT64)temp;
+ break;
+ case 0x0e<<13:
+ /* MR - X * Y (US) */
+ xop = MAC_GETXREG_UNSIGNED(xop);
+ yop = MAC_GETYREG_SIGNED(yop);
+ temp = (xop * yop) << shift;
+ res = m_core.mr.mr - (INT64)temp;
+ break;
+ case 0x0f<<13:
+ /* MR - X * Y (UU) */
+ xop = MAC_GETXREG_UNSIGNED(xop);
+ yop = MAC_GETYREG_UNSIGNED(yop);
+ temp = (xop * yop) << shift;
+ res = m_core.mr.mr - (INT64)temp;
+ break;
+ default:
+ res = 0; /* just to keep the compiler happy */
+ break;
+ }
+
+ /* set the final value */
+ m_core.mf.u = (UINT32)res >> 16;
+}
+
+
+
+/*===========================================================================
+ MAC operations (result in MF, yop == xop)
+===========================================================================*/
+
+void adsp21xx_device::mac_op_mf_xop(int op)
+{
+ INT8 shift = ((m_mstat & MSTAT_INTEGER) >> 4) ^ 1;
+ INT32 xop = (op >> 8) & 7;
+ INT32 temp;
+ INT64 res;
+
+ switch (op & (15<<13)) /*JB*/
+ {
+ case 0x00<<13:
+ /* no-op */
+ return;
+ case 0x01<<13:
+ /* X * Y (RND) */
+ xop = MAC_GETXREG_SIGNED(xop);
+ temp = (xop * xop) << shift;
+ res = (INT64)temp;
+#if 0
+ if ((res & 0xffff) == 0x8000) res &= ~((UINT64)0x10000);
+ else res += (res & 0x8000) << 1;
+#else
+ temp &= 0xffff;
+ res += 0x8000;
+ if ( temp == 0x8000 )
+ res &= ~((UINT64)0x10000);
+#endif
+ break;
+ case 0x02<<13:
+ /* MR + X * Y (RND) */
+ xop = MAC_GETXREG_SIGNED(xop);
+ temp = (xop * xop) << shift;
+ res = m_core.mr.mr + (INT64)temp;
+#if 0
+ if ((res & 0xffff) == 0x8000) res &= ~((UINT64)0x10000);
+ else res += (res & 0x8000) << 1;
+#else
+ temp &= 0xffff;
+ res += 0x8000;
+ if ( temp == 0x8000 )
+ res &= ~((UINT64)0x10000);
+#endif
+ break;
+ case 0x03<<13:
+ /* MR - X * Y (RND) */
+ xop = MAC_GETXREG_SIGNED(xop);
+ temp = (xop * xop) << shift;
+ res = m_core.mr.mr - (INT64)temp;
+#if 0
+ if ((res & 0xffff) == 0x8000) res &= ~((UINT64)0x10000);
+ else res += (res & 0x8000) << 1;
+#else
+ temp &= 0xffff;
+ res += 0x8000;
+ if ( temp == 0x8000 )
+ res &= ~((UINT64)0x10000);
+#endif
+ break;
+ case 0x04<<13:
+ /* X * Y (SS) Clear when y = 0 */
+ xop = MAC_GETXREG_SIGNED(xop);
+ temp = (xop * xop) << shift;
+ res = (INT64)temp;
+ break;
+ case 0x05<<13:
+ /* X * Y (SU) */
+ xop = MAC_GETXREG_SIGNED(xop);
+ temp = (xop * xop) << shift;
+ res = (INT64)temp;
+ break;
+ case 0x06<<13:
+ /* X * Y (US) */
+ xop = MAC_GETXREG_UNSIGNED(xop);
+ temp = (xop * xop) << shift;
+ res = (INT64)temp;
+ break;
+ case 0x07<<13:
+ /* X * Y (UU) */
+ xop = MAC_GETXREG_UNSIGNED(xop);
+ temp = (xop * xop) << shift;
+ res = (INT64)temp;
+ break;
+ case 0x08<<13:
+ /* MR + X * Y (SS) */
+ xop = MAC_GETXREG_SIGNED(xop);
+ temp = (xop * xop) << shift;
+ res = m_core.mr.mr + (INT64)temp;
+ break;
+ case 0x09<<13:
+ /* MR + X * Y (SU) */
+ xop = MAC_GETXREG_SIGNED(xop);
+ temp = (xop * xop) << shift;
+ res = m_core.mr.mr + (INT64)temp;
+ break;
+ case 0x0a<<13:
+ /* MR + X * Y (US) */
+ xop = MAC_GETXREG_UNSIGNED(xop);
+ temp = (xop * xop) << shift;
+ res = m_core.mr.mr + (INT64)temp;
+ break;
+ case 0x0b<<13:
+ /* MR + X * Y (UU) */
+ xop = MAC_GETXREG_UNSIGNED(xop);
+ temp = (xop * xop) << shift;
+ res = m_core.mr.mr + (INT64)temp;
+ break;
+ case 0x0c<<13:
+ /* MR - X * Y (SS) */
+ xop = MAC_GETXREG_SIGNED(xop);
+ temp = (xop * xop) << shift;
+ res = m_core.mr.mr - (INT64)temp;
+ break;
+ case 0x0d<<13:
+ /* MR - X * Y (SU) */
+ xop = MAC_GETXREG_SIGNED(xop);
+ temp = (xop * xop) << shift;
+ res = m_core.mr.mr - (INT64)temp;
+ break;
+ case 0x0e<<13:
+ /* MR - X * Y (US) */
+ xop = MAC_GETXREG_UNSIGNED(xop);
+ temp = (xop * xop) << shift;
+ res = m_core.mr.mr - (INT64)temp;
+ break;
+ case 0x0f<<13:
+ /* MR - X * Y (UU) */
+ xop = MAC_GETXREG_UNSIGNED(xop);
+ temp = (xop * xop) << shift;
+ res = m_core.mr.mr - (INT64)temp;
+ break;
+ default:
+ res = 0; /* just to keep the compiler happy */
+ break;
+ }
+
+ /* set the final value */
+ m_core.mf.u = (UINT32)res >> 16;
+}
+
+
+
+/*===========================================================================
+ SHIFT operations (result in SR/SE/SB)
+===========================================================================*/
+
+void adsp21xx_device::shift_op(int op)
+{
+ INT8 sc = m_core.se.s;
+ INT32 xop = (op >> 8) & 7;
+ UINT32 res;
+
+ switch (op & (15<<11)) /*JB*/
+ {
+ case 0x00<<11:
+ /* LSHIFT (HI) */
+ xop = SHIFT_GETXREG_UNSIGNED(xop) << 16;
+ if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
+ else res = (sc > -32) ? ((UINT32)xop >> -sc) : 0;
+ m_core.sr.sr = res;
+ break;
+ case 0x01<<11:
+ /* LSHIFT (HI, OR) */
+ xop = SHIFT_GETXREG_UNSIGNED(xop) << 16;
+ if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
+ else res = (sc > -32) ? ((UINT32)xop >> -sc) : 0;
+ m_core.sr.sr |= res;
+ break;
+ case 0x02<<11:
+ /* LSHIFT (LO) */
+ xop = SHIFT_GETXREG_UNSIGNED(xop);
+ if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
+ else res = (sc > -32) ? (xop >> -sc) : 0;
+ m_core.sr.sr = res;
+ break;
+ case 0x03<<11:
+ /* LSHIFT (LO, OR) */
+ xop = SHIFT_GETXREG_UNSIGNED(xop);
+ if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
+ else res = (sc > -32) ? (xop >> -sc) : 0;
+ m_core.sr.sr |= res;
+ break;
+ case 0x04<<11:
+ /* ASHIFT (HI) */
+ xop = SHIFT_GETXREG_SIGNED(xop) << 16;
+ if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
+ else res = (sc > -32) ? (xop >> -sc) : (xop >> 31);
+ m_core.sr.sr = res;
+ break;
+ case 0x05<<11:
+ /* ASHIFT (HI, OR) */
+ xop = SHIFT_GETXREG_SIGNED(xop) << 16;
+ if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
+ else res = (sc > -32) ? (xop >> -sc) : (xop >> 31);
+ m_core.sr.sr |= res;
+ break;
+ case 0x06<<11:
+ /* ASHIFT (LO) */
+ xop = SHIFT_GETXREG_SIGNED(xop);
+ if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
+ else res = (sc > -32) ? (xop >> -sc) : (xop >> 31);
+ m_core.sr.sr = res;
+ break;
+ case 0x07<<11:
+ /* ASHIFT (LO, OR) */
+ xop = SHIFT_GETXREG_SIGNED(xop);
+ if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
+ else res = (sc > -32) ? (xop >> -sc) : (xop >> 31);
+ m_core.sr.sr |= res;
+ break;
+ case 0x08<<11:
+ /* NORM (HI) */
+ xop = SHIFT_GETXREG_SIGNED(xop) << 16;
+ if (sc > 0)
+ {
+ xop = ((UINT32)xop >> 1) | ((m_astat & CFLAG) << 28);
+ res = xop >> (sc - 1);
+ }
+ else res = (sc > -32) ? (xop << -sc) : 0;
+ m_core.sr.sr = res;
+ break;
+ case 0x09<<11:
+ /* NORM (HI, OR) */
+ xop = SHIFT_GETXREG_SIGNED(xop) << 16;
+ if (sc > 0)
+ {
+ xop = ((UINT32)xop >> 1) | ((m_astat & CFLAG) << 28);
+ res = xop >> (sc - 1);
+ }
+ else res = (sc > -32) ? (xop << -sc) : 0;
+ m_core.sr.sr |= res;
+ break;
+ case 0x0a<<11:
+ /* NORM (LO) */
+ xop = SHIFT_GETXREG_UNSIGNED(xop);
+ if (sc > 0) res = (sc < 32) ? (xop >> sc) : 0;
+ else res = (sc > -32) ? (xop << -sc) : 0;
+ m_core.sr.sr = res;
+ break;
+ case 0x0b<<11:
+ /* NORM (LO, OR) */
+ xop = SHIFT_GETXREG_UNSIGNED(xop);
+ if (sc > 0) res = (sc < 32) ? (xop >> sc) : 0;
+ else res = (sc > -32) ? (xop << -sc) : 0;
+ m_core.sr.sr |= res;
+ break;
+ case 0x0c<<11:
+ /* EXP (HI) */
+ xop = SHIFT_GETXREG_SIGNED(xop) << 16;
+ res = 0;
+ if (xop < 0)
+ {
+ SET_SS;
+ while ((xop & 0x40000000) != 0) res++, xop <<= 1;
+ }
+ else
+ {
+ CLR_SS;
+ xop |= 0x8000;
+ while ((xop & 0x40000000) == 0) res++, xop <<= 1;
+ }
+ m_core.se.s = -res;
+ break;
+ case 0x0d<<11:
+ /* EXP (HIX) */
+ xop = SHIFT_GETXREG_SIGNED(xop) << 16;
+ if (GET_V)
+ {
+ m_core.se.s = 1;
+ if (xop < 0) CLR_SS;
+ else SET_SS;
+ }
+ else
+ {
+ res = 0;
+ if (xop < 0)
+ {
+ SET_SS;
+ while ((xop & 0x40000000) != 0) res++, xop <<= 1;
+ }
+ else
+ {
+ CLR_SS;
+ xop |= 0x8000;
+ while ((xop & 0x40000000) == 0) res++, xop <<= 1;
+ }
+ m_core.se.s = -res;
+ }
+ break;
+ case 0x0e<<11:
+ /* EXP (LO) */
+ if (m_core.se.s == -15)
+ {
+ xop = SHIFT_GETXREG_SIGNED(xop);
+ res = 15;
+ if (GET_SS)
+ while ((xop & 0x8000) != 0) res++, xop <<= 1;
+ else
+ {
+ xop = (xop << 1) | 1;
+ while ((xop & 0x10000) == 0) res++, xop <<= 1;
+ }
+ m_core.se.s = -res;
+ }
+ break;
+ case 0x0f<<11:
+ /* EXPADJ */
+ xop = SHIFT_GETXREG_SIGNED(xop) << 16;
+ res = 0;
+ if (xop < 0)
+ while ((xop & 0x40000000) != 0) res++, xop <<= 1;
+ else
+ {
+ xop |= 0x8000;
+ while ((xop & 0x40000000) == 0) res++, xop <<= 1;
+ }
+ if (res < -m_core.sb.s)
+ m_core.sb.s = -res;
+ break;
+ }
+}
+
+
+
+/*===========================================================================
+ Immediate SHIFT operations (result in SR/SE/SB)
+===========================================================================*/
+
+void adsp21xx_device::shift_op_imm(int op)
+{
+ INT8 sc = (INT8)op;
+ INT32 xop = (op >> 8) & 7;
+ UINT32 res;
+
+ switch (op & (15<<11)) /*JB*/
+ {
+ case 0x00<<11:
+ /* LSHIFT (HI) */
+ xop = SHIFT_GETXREG_UNSIGNED(xop) << 16;
+ if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
+ else res = (sc > -32) ? ((UINT32)xop >> -sc) : 0;
+ m_core.sr.sr = res;
+ break;
+ case 0x01<<11:
+ /* LSHIFT (HI, OR) */
+ xop = SHIFT_GETXREG_UNSIGNED(xop) << 16;
+ if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
+ else res = (sc > -32) ? ((UINT32)xop >> -sc) : 0;
+ m_core.sr.sr |= res;
+ break;
+ case 0x02<<11:
+ /* LSHIFT (LO) */
+ xop = SHIFT_GETXREG_UNSIGNED(xop);
+ if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
+ else res = (sc > -32) ? (xop >> -sc) : 0;
+ m_core.sr.sr = res;
+ break;
+ case 0x03<<11:
+ /* LSHIFT (LO, OR) */
+ xop = SHIFT_GETXREG_UNSIGNED(xop);
+ if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
+ else res = (sc > -32) ? (xop >> -sc) : 0;
+ m_core.sr.sr |= res;
+ break;
+ case 0x04<<11:
+ /* ASHIFT (HI) */
+ xop = SHIFT_GETXREG_SIGNED(xop) << 16;
+ if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
+ else res = (sc > -32) ? (xop >> -sc) : (xop >> 31);
+ m_core.sr.sr = res;
+ break;
+ case 0x05<<11:
+ /* ASHIFT (HI, OR) */
+ xop = SHIFT_GETXREG_SIGNED(xop) << 16;
+ if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
+ else res = (sc > -32) ? (xop >> -sc) : (xop >> 31);
+ m_core.sr.sr |= res;
+ break;
+ case 0x06<<11:
+ /* ASHIFT (LO) */
+ xop = SHIFT_GETXREG_SIGNED(xop);
+ if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
+ else res = (sc > -32) ? (xop >> -sc) : (xop >> 31);
+ m_core.sr.sr = res;
+ break;
+ case 0x07<<11:
+ /* ASHIFT (LO, OR) */
+ xop = SHIFT_GETXREG_SIGNED(xop);
+ if (sc > 0) res = (sc < 32) ? (xop << sc) : 0;
+ else res = (sc > -32) ? (xop >> -sc) : (xop >> 31);
+ m_core.sr.sr |= res;
+ break;
+ case 0x08<<11:
+ /* NORM (HI) */
+ xop = SHIFT_GETXREG_SIGNED(xop) << 16;
+ if (sc > 0)
+ {
+ xop = ((UINT32)xop >> 1) | ((m_astat & CFLAG) << 28);
+ res = xop >> (sc - 1);
+ }
+ else res = (sc > -32) ? (xop << -sc) : 0;
+ m_core.sr.sr = res;
+ break;
+ case 0x09<<11:
+ /* NORM (HI, OR) */
+ xop = SHIFT_GETXREG_SIGNED(xop) << 16;
+ if (sc > 0)
+ {
+ xop = ((UINT32)xop >> 1) | ((m_astat & CFLAG) << 28);
+ res = xop >> (sc - 1);
+ }
+ else res = (sc > -32) ? (xop << -sc) : 0;
+ m_core.sr.sr |= res;
+ break;
+ case 0x0a<<11:
+ /* NORM (LO) */
+ xop = SHIFT_GETXREG_UNSIGNED(xop);
+ if (sc > 0) res = (sc < 32) ? (xop >> sc) : 0;
+ else res = (sc > -32) ? (xop << -sc) : 0;
+ m_core.sr.sr = res;
+ break;
+ case 0x0b<<11:
+ /* NORM (LO, OR) */
+ xop = SHIFT_GETXREG_UNSIGNED(xop);
+ if (sc > 0) res = (sc < 32) ? (xop >> sc) : 0;
+ else res = (sc > -32) ? (xop << -sc) : 0;
+ m_core.sr.sr |= res;
+ break;
+ }
+}
diff --git a/trunk/src/emu/cpu/adsp2100/adsp2100.c b/trunk/src/emu/cpu/adsp2100/adsp2100.c
new file mode 100644
index 00000000000..bdc335e1057
--- /dev/null
+++ b/trunk/src/emu/cpu/adsp2100/adsp2100.c
@@ -0,0 +1,1947 @@
+/***************************************************************************
+
+ ADSP2100.c
+
+ ADSP-21xx series emulator.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+****************************************************************************
+
+ For ADSP-2101, ADSP-2111
+ ------------------------
+
+ MMAP = 0 MMAP = 1
+
+ Automatic boot loading No auto boot loading
+
+ Program Space: Program Space:
+ 0000-07ff = 2k Internal RAM (booted) 0000-37ff = 14k External access
+ 0800-3fff = 14k External access 3800-3fff = 2k Internal RAM
+
+ Data Space: Data Space:
+ 0000-03ff = 1k External DWAIT0 0000-03ff = 1k External DWAIT0
+ 0400-07ff = 1k External DWAIT1 0400-07ff = 1k External DWAIT1
+ 0800-2fff = 10k External DWAIT2 0800-2fff = 10k External DWAIT2
+ 3000-33ff = 1k External DWAIT3 3000-33ff = 1k External DWAIT3
+ 3400-37ff = 1k External DWAIT4 3400-37ff = 1k External DWAIT4
+ 3800-3bff = 1k Internal RAM 3800-3bff = 1k Internal RAM
+ 3c00-3fff = 1k Internal Control regs 3c00-3fff = 1k Internal Control regs
+
+
+ For ADSP-2105, ADSP-2115
+ ------------------------
+
+ MMAP = 0 MMAP = 1
+
+ Automatic boot loading No auto boot loading
+
+ Program Space: Program Space:
+ 0000-03ff = 1k Internal RAM (booted) 0000-37ff = 14k External access
+ 0400-07ff = 1k Reserved 3800-3bff = 1k Internal RAM
+ 0800-3fff = 14k External access 3c00-3fff = 1k Reserved
+
+ Data Space: Data Space:
+ 0000-03ff = 1k External DWAIT0 0000-03ff = 1k External DWAIT0
+ 0400-07ff = 1k External DWAIT1 0400-07ff = 1k External DWAIT1
+ 0800-2fff = 10k External DWAIT2 0800-2fff = 10k External DWAIT2
+ 3000-33ff = 1k External DWAIT3 3000-33ff = 1k External DWAIT3
+ 3400-37ff = 1k External DWAIT4 3400-37ff = 1k External DWAIT4
+ 3800-39ff = 512 Internal RAM 3800-39ff = 512 Internal RAM
+ 3a00-3bff = 512 Reserved 3a00-3bff = 512 Reserved
+ 3c00-3fff = 1k Internal Control regs 3c00-3fff = 1k Internal Control regs
+
+
+ For ADSP-2104
+ -------------
+
+ MMAP = 0 MMAP = 1
+
+ Automatic boot loading No auto boot loading
+
+ Program Space: Program Space:
+ 0000-01ff = 512 Internal RAM (booted) 0000-37ff = 14k External access
+ 0400-07ff = 1k Reserved 3800-3bff = 1k Internal RAM
+ 0800-3fff = 14k External access 3c00-3fff = 1k Reserved
+
+ Data Space: Data Space:
+ 0000-03ff = 1k External DWAIT0 0000-03ff = 1k External DWAIT0
+ 0400-07ff = 1k External DWAIT1 0400-07ff = 1k External DWAIT1
+ 0800-2fff = 10k External DWAIT2 0800-2fff = 10k External DWAIT2
+ 3000-33ff = 1k External DWAIT3 3000-33ff = 1k External DWAIT3
+ 3400-37ff = 1k External DWAIT4 3400-37ff = 1k External DWAIT4
+ 3800-38ff = 256 Internal RAM 3800-38ff = 256 Internal RAM
+ 3a00-3bff = 512 Reserved 3a00-3bff = 512 Reserved
+ 3c00-3fff = 1k Internal Control regs 3c00-3fff = 1k Internal Control regs
+
+
+ For ADSP-2181
+ -------------
+
+ MMAP = 0 MMAP = 1
+
+ Program Space: Program Space:
+ 0000-1fff = 8k Internal RAM 0000-1fff = 8k External access
+ 2000-3fff = 8k Internal RAM or Overlay 2000-3fff = 8k Internal
+
+ Data Space: Data Space:
+ 0000-1fff = 8k Internal RAM or Overlay 0000-1fff = 8k Internal RAM or Overlay
+ 2000-3fdf = 8k-32 Internal RAM 2000-3fdf = 8k-32 Internal RAM
+ 3fe0-3fff = 32 Internal Control regs 3fe0-3fff = 32 Internal Control regs
+
+ I/O Space: I/O Space:
+ 0000-01ff = 512 External IOWAIT0 0000-01ff = 512 External IOWAIT0
+ 0200-03ff = 512 External IOWAIT1 0200-03ff = 512 External IOWAIT1
+ 0400-05ff = 512 External IOWAIT2 0400-05ff = 512 External IOWAIT2
+ 0600-07ff = 512 External IOWAIT3 0600-07ff = 512 External IOWAIT3
+
+***************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "adsp2100.h"
+
+
+// device type definitions
+const device_type ADSP2100 = &device_creator<adsp2100_device>;
+const device_type ADSP2101 = &device_creator<adsp2101_device>;
+const device_type ADSP2104 = &device_creator<adsp2104_device>;
+const device_type ADSP2105 = &device_creator<adsp2105_device>;
+const device_type ADSP2115 = &device_creator<adsp2115_device>;
+const device_type ADSP2181 = &device_creator<adsp2181_device>;
+
+
+//**************************************************************************
+// DEVICE INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// adsp21xx_device - constructor
+//-------------------------------------------------
+
+adsp21xx_device::adsp21xx_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, UINT32 chiptype)
+ : cpu_device(mconfig, type, name, tag, owner, clock),
+ m_program_config("program", ENDIANNESS_LITTLE, 32, 14, -2),
+ m_data_config("data", ENDIANNESS_LITTLE, 16, 14, -1),
+ m_chip_type(chiptype),
+ m_pc(0),
+ m_ppc(0),
+ m_loop(0),
+ m_loop_condition(0),
+ m_cntr(0),
+ m_astat(0),
+ m_sstat(0),
+ m_mstat(0),
+ m_mstat_prev(0),
+ m_astat_clear(0),
+ m_idle(0),
+ m_px(0),
+ m_pc_sp(0),
+ m_cntr_sp(0),
+ m_stat_sp(0),
+ m_loop_sp(0),
+ m_flagout(0),
+ m_flagin(0),
+ m_fl0(0),
+ m_fl1(0),
+ m_fl2(0),
+ m_idma_addr(0),
+ m_idma_cache(0),
+ m_idma_offs(0),
+ m_imask(0),
+ m_icntl(0),
+ m_ifc(0),
+ m_icount(0),
+ m_mstat_mask((m_chip_type >= CHIP_TYPE_ADSP2101) ? 0x7f : 0x0f),
+ m_imask_mask((m_chip_type >= CHIP_TYPE_ADSP2181) ? 0x3ff :
+ (m_chip_type >= CHIP_TYPE_ADSP2101) ? 0x3f : 0x0f)
+{
+ // initialize remaining state
+ memset(&m_core, 0, sizeof(m_core));
+ memset(&m_alt, 0, sizeof(m_alt));
+ memset(&m_i, 0, sizeof(m_i));
+ memset(&m_m, 0, sizeof(m_m));
+ memset(&m_l, 0, sizeof(m_l));
+ memset(&m_lmask, 0, sizeof(m_lmask));
+ memset(&m_base, 0, sizeof(m_base));
+ memset(&m_loop_stack, 0, sizeof(m_loop_stack));
+ memset(&m_cntr_stack, 0, sizeof(m_cntr_stack));
+ memset(&m_pc_stack, 0, sizeof(m_pc_stack));
+ memset(&m_stat_stack, 0, sizeof(m_stat_stack));
+ memset(&m_irq_state, 0, sizeof(m_irq_state));
+ memset(&m_irq_latch, 0, sizeof(m_irq_latch));
+
+ m_sport_rx_callback = NULL;
+ m_sport_tx_callback = NULL;
+ m_timer_fired = NULL;
+
+ // create the tables
+ create_tables();
+
+ // set up read register group 0 pointers
+ m_read0_ptr[0x00] = &m_core.ax0.s;
+ m_read0_ptr[0x01] = &m_core.ax1.s;
+ m_read0_ptr[0x02] = &m_core.mx0.s;
+ m_read0_ptr[0x03] = &m_core.mx1.s;
+ m_read0_ptr[0x04] = &m_core.ay0.s;
+ m_read0_ptr[0x05] = &m_core.ay1.s;
+ m_read0_ptr[0x06] = &m_core.my0.s;
+ m_read0_ptr[0x07] = &m_core.my1.s;
+ m_read0_ptr[0x08] = &m_core.si.s;
+ m_read0_ptr[0x09] = &m_core.se.s;
+ m_read0_ptr[0x0a] = &m_core.ar.s;
+ m_read0_ptr[0x0b] = &m_core.mr.mrx.mr0.s;
+ m_read0_ptr[0x0c] = &m_core.mr.mrx.mr1.s;
+ m_read0_ptr[0x0d] = &m_core.mr.mrx.mr2.s;
+ m_read0_ptr[0x0e] = &m_core.sr.srx.sr0.s;
+ m_read0_ptr[0x0f] = &m_core.sr.srx.sr1.s;
+
+ // set up read register group 1 + 2 pointers
+ for (int index = 0; index < 4; index++)
+ {
+ m_read1_ptr[0x00 + index] = &m_i[0 + index];
+ m_read1_ptr[0x04 + index] = (UINT32 *)&m_m[0 + index];
+ m_read1_ptr[0x08 + index] = &m_l[0 + index];
+ m_read1_ptr[0x0c + index] = &m_l[0 + index];
+ m_read2_ptr[0x00 + index] = &m_i[4 + index];
+ m_read2_ptr[0x04 + index] = (UINT32 *)&m_m[4 + index];
+ m_read2_ptr[0x08 + index] = &m_l[4 + index];
+ m_read2_ptr[0x0c + index] = &m_l[4 + index];
+ }
+
+ // set up ALU register pointers
+ m_alu_xregs[0] = &m_core.ax0;
+ m_alu_xregs[1] = &m_core.ax1;
+ m_alu_xregs[2] = &m_core.ar;
+ m_alu_xregs[3] = &m_core.mr.mrx.mr0;
+ m_alu_xregs[4] = &m_core.mr.mrx.mr1;
+ m_alu_xregs[5] = &m_core.mr.mrx.mr2;
+ m_alu_xregs[6] = &m_core.sr.srx.sr0;
+ m_alu_xregs[7] = &m_core.sr.srx.sr1;
+ m_alu_yregs[0] = &m_core.ay0;
+ m_alu_yregs[1] = &m_core.ay1;
+ m_alu_yregs[2] = &m_core.af;
+ m_alu_yregs[3] = &m_core.zero;
+
+ // set up MAC register pointers
+ m_mac_xregs[0] = &m_core.mx0;
+ m_mac_xregs[1] = &m_core.mx1;
+ m_mac_xregs[2] = &m_core.ar;
+ m_mac_xregs[3] = &m_core.mr.mrx.mr0;
+ m_mac_xregs[4] = &m_core.mr.mrx.mr1;
+ m_mac_xregs[5] = &m_core.mr.mrx.mr2;
+ m_mac_xregs[6] = &m_core.sr.srx.sr0;
+ m_mac_xregs[7] = &m_core.sr.srx.sr1;
+ m_mac_yregs[0] = &m_core.my0;
+ m_mac_yregs[1] = &m_core.my1;
+ m_mac_yregs[2] = &m_core.mf;
+ m_mac_yregs[3] = &m_core.zero;
+
+ // set up shift register pointers
+ m_shift_xregs[0] = &m_core.si;
+ m_shift_xregs[1] = &m_core.si;
+ m_shift_xregs[2] = &m_core.ar;
+ m_shift_xregs[3] = &m_core.mr.mrx.mr0;
+ m_shift_xregs[4] = &m_core.mr.mrx.mr1;
+ m_shift_xregs[5] = &m_core.mr.mrx.mr2;
+ m_shift_xregs[6] = &m_core.sr.srx.sr0;
+ m_shift_xregs[7] = &m_core.sr.srx.sr1;
+}
+
+adsp2100_device::adsp2100_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : adsp21xx_device(mconfig, ADSP2100, "ADSP-2100", tag, owner, clock, CHIP_TYPE_ADSP2100) { }
+
+adsp2101_device::adsp2101_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : adsp21xx_device(mconfig, ADSP2101, "ADSP-2101", tag, owner, clock, CHIP_TYPE_ADSP2101) { }
+
+adsp2101_device::adsp2101_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, UINT32 chiptype)
+ : adsp21xx_device(mconfig, type, name, tag, owner, clock, chiptype) { }
+
+adsp2104_device::adsp2104_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : adsp2101_device(mconfig, ADSP2104, "ADSP-2104", tag, owner, clock, CHIP_TYPE_ADSP2104) { }
+
+adsp2105_device::adsp2105_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : adsp2101_device(mconfig, ADSP2105, "ADSP-2105", tag, owner, clock, CHIP_TYPE_ADSP2105) { }
+
+adsp2115_device::adsp2115_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : adsp2101_device(mconfig, ADSP2115, "ADSP-2115", tag, owner, clock, CHIP_TYPE_ADSP2115) { }
+
+adsp2181_device::adsp2181_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : adsp21xx_device(mconfig, ADSP2181, "ADSP-2181", tag, owner, clock, CHIP_TYPE_ADSP2181),
+ m_io_config("I/O", ENDIANNESS_LITTLE, 16, 11, -1) { }
+
+
+//-------------------------------------------------
+// ~adsp21xx_device - destructor
+//-------------------------------------------------
+
+adsp21xx_device::~adsp21xx_device()
+{
+#if ADSP_TRACK_HOTSPOTS
+ FILE *log = fopen("adsp.hot", "w");
+ while (1)
+ {
+ int maxindex = 0, i;
+ for (i = 1; i < 0x4000; i++)
+ if (m_pcbucket[i] > m_pcbucket[maxindex])
+ maxindex = i;
+ if (m_pcbucket[maxindex] == 0)
+ break;
+ fprintf(log, "PC=%04X (%10d hits)\n", maxindex, pcbucket[maxindex]);
+ m_pcbucket[maxindex] = 0;
+ }
+ fclose(log);
+#endif
+}
+
+
+//-------------------------------------------------
+// static_set_config - set the configuration
+// structure
+//-------------------------------------------------
+
+void adsp21xx_device::static_set_config(device_t &device, const adsp21xx_config &config)
+{
+ adsp21xx_device &adsp = downcast<adsp21xx_device &>(device);
+ static_cast<adsp21xx_config &>(adsp) = config;
+}
+
+
+//-------------------------------------------------
+// load_boot_data - load the boot data from an
+// 8-bit ROM
+//-------------------------------------------------
+
+void adsp21xx_device::load_boot_data(UINT8 *srcdata, UINT32 *dstdata)
+{
+ // see how many words we need to copy
+ int pagelen = (srcdata[3] + 1) * 8;
+ for (int i = 0; i < pagelen; i++)
+ {
+ UINT32 opcode = (srcdata[i*4+0] << 16) | (srcdata[i*4+1] << 8) | srcdata[i*4+2];
+ dstdata[i] = opcode;
+ }
+}
+
+
+//-------------------------------------------------
+// idma_addr_w - write the IDMA address register
+//-------------------------------------------------
+
+void adsp2181_device::idma_addr_w(UINT16 data)
+{
+ m_idma_addr = data;
+ m_idma_offs = 0;
+}
+
+
+//-------------------------------------------------
+// idma_addr_r - read the IDMA address register
+//-------------------------------------------------
+
+UINT16 adsp2181_device::idma_addr_r()
+{
+ return m_idma_addr;
+}
+
+
+//-------------------------------------------------
+// idma_data_w - write the IDMA data register
+//-------------------------------------------------
+
+void adsp2181_device::idma_data_w(UINT16 data)
+{
+ // program memory?
+ if (!(m_idma_addr & 0x4000))
+ {
+ // upper 16 bits
+ if (m_idma_offs == 0)
+ {
+ m_idma_cache = data;
+ m_idma_offs = 1;
+ }
+
+ // lower 8 bits
+ else
+ {
+ program_write(m_idma_addr++ & 0x3fff, (m_idma_cache << 8) | (data & 0xff));
+ m_idma_offs = 0;
+ }
+ }
+
+ // data memory
+ else
+ data_write(m_idma_addr++ & 0x3fff, data);
+}
+
+
+//-------------------------------------------------
+// idma_data_r - read the IDMA data register
+//-------------------------------------------------
+
+UINT16 adsp2181_device::idma_data_r()
+{
+ UINT16 result = 0xffff;
+
+ // program memory?
+ if (!(m_idma_addr & 0x4000))
+ {
+ // upper 16 bits
+ if (m_idma_offs == 0)
+ {
+ result = program_read(m_idma_addr & 0x3fff) >> 8;
+ m_idma_offs = 1;
+ }
+
+ // lower 8 bits
+ else
+ {
+ result = program_read(m_idma_addr++ & 0x3fff) & 0xff;
+ m_idma_offs = 0;
+ }
+ }
+
+ // data memory
+ else
+ result = data_read(m_idma_addr++ & 0x3fff);
+
+ return result;
+}
+
+
+//-------------------------------------------------
+// device_start - start up the device
+//-------------------------------------------------
+
+void adsp21xx_device::device_start()
+{
+ // get our address spaces
+ m_program = space(AS_PROGRAM);
+ m_direct = &m_program->direct();
+ m_data = space(AS_DATA);
+ m_io = space(AS_IO);
+
+ // "core"
+ save_item(NAME(m_core.ax0.u));
+ save_item(NAME(m_core.ax1.u));
+ save_item(NAME(m_core.ay0.u));
+ save_item(NAME(m_core.ay1.u));
+ save_item(NAME(m_core.ar.u));
+ save_item(NAME(m_core.af.u));
+ save_item(NAME(m_core.mx0.u));
+ save_item(NAME(m_core.mx1.u));
+ save_item(NAME(m_core.my0.u));
+ save_item(NAME(m_core.my1.u));
+ save_item(NAME(m_core.mr.mr));
+ save_item(NAME(m_core.mf.u));
+ save_item(NAME(m_core.si.u));
+ save_item(NAME(m_core.se.u));
+ save_item(NAME(m_core.sb.u));
+ save_item(NAME(m_core.sr.sr));
+ save_item(NAME(m_core.zero.u));
+
+ // "alt"
+ save_item(NAME(m_alt.ax0.u));
+ save_item(NAME(m_alt.ax1.u));
+ save_item(NAME(m_alt.ay0.u));
+ save_item(NAME(m_alt.ay1.u));
+ save_item(NAME(m_alt.ar.u));
+ save_item(NAME(m_alt.af.u));
+ save_item(NAME(m_alt.mx0.u));
+ save_item(NAME(m_alt.mx1.u));
+ save_item(NAME(m_alt.my0.u));
+ save_item(NAME(m_alt.my1.u));
+ save_item(NAME(m_alt.mr.mr));
+ save_item(NAME(m_alt.mf.u));
+ save_item(NAME(m_alt.si.u));
+ save_item(NAME(m_alt.se.u));
+ save_item(NAME(m_alt.sb.u));
+ save_item(NAME(m_alt.sr.sr));
+ save_item(NAME(m_alt.zero.u));
+
+ save_item(NAME(m_i));
+ save_item(NAME(m_m));
+ save_item(NAME(m_l));
+ save_item(NAME(m_lmask));
+ save_item(NAME(m_base));
+ save_item(NAME(m_px));
+
+ save_item(NAME(m_pc));
+ save_item(NAME(m_ppc));
+ save_item(NAME(m_loop));
+ save_item(NAME(m_loop_condition));
+ save_item(NAME(m_cntr));
+ save_item(NAME(m_astat));
+ save_item(NAME(m_sstat));
+ save_item(NAME(m_mstat));
+ save_item(NAME(m_mstat_prev));
+ save_item(NAME(m_astat_clear));
+ save_item(NAME(m_idle));
+
+ save_item(NAME(m_loop_stack));
+ save_item(NAME(m_cntr_stack));
+ save_item(NAME(m_pc_stack));
+ save_item(NAME(m_stat_stack));
+
+ save_item(NAME(m_pc_sp));
+ save_item(NAME(m_cntr_sp));
+ save_item(NAME(m_stat_sp));
+ save_item(NAME(m_loop_sp));
+
+ save_item(NAME(m_flagout));
+ save_item(NAME(m_flagin));
+ save_item(NAME(m_fl0));
+ save_item(NAME(m_fl1));
+ save_item(NAME(m_fl2));
+ save_item(NAME(m_idma_addr));
+ save_item(NAME(m_idma_cache));
+ save_item(NAME(m_idma_offs));
+
+ save_item(NAME(m_imask));
+ save_item(NAME(m_icntl));
+ save_item(NAME(m_ifc));
+ save_item(NAME(m_irq_state));
+ save_item(NAME(m_irq_latch));
+
+ // register state with the debugger
+ state_add(ADSP2100_PC, "PC", m_pc);
+ state_add(STATE_GENPC, "GENPC", m_pc).noshow();
+ state_add(STATE_GENPCBASE, "GENPCBASE", m_ppc).noshow();
+ state_add(STATE_GENFLAGS, "GENFLAGS", m_astat).mask(0xff).noshow().formatstr("%8s");
+
+ state_add(ADSP2100_AX0, "AX0", m_core.ax0.u);
+ state_add(ADSP2100_AX1, "AX1", m_core.ax1.u);
+ state_add(ADSP2100_AY0, "AY0", m_core.ay0.u);
+ state_add(ADSP2100_AY1, "AY1", m_core.ay1.u);
+ state_add(ADSP2100_AR, "AR", m_core.ar.u);
+ state_add(ADSP2100_AF, "AF", m_core.af.u);
+
+ state_add(ADSP2100_MX0, "MX0", m_core.mx0.u);
+ state_add(ADSP2100_MX1, "MX1", m_core.mx1.u);
+ state_add(ADSP2100_MY0, "MY0", m_core.my0.u);
+ state_add(ADSP2100_MY1, "MY1", m_core.my1.u);
+ state_add(ADSP2100_MR0, "MR0", m_core.mr.mrx.mr0.u);
+ state_add(ADSP2100_MR1, "MR1", m_core.mr.mrx.mr1.u);
+ state_add(ADSP2100_MR2, "MR2", m_core.mr.mrx.mr2.u).signed_mask(0xff);
+ state_add(ADSP2100_MF, "MF", m_core.mf.u);
+
+ state_add(ADSP2100_SI, "SI", m_core.si.u);
+ state_add(ADSP2100_SE, "SE", m_core.se.u).signed_mask(0xff);
+ state_add(ADSP2100_SB, "SB", m_core.sb.u).signed_mask(0x1f);
+ state_add(ADSP2100_SR0, "SR0", m_core.sr.srx.sr0.u);
+ state_add(ADSP2100_SR1, "SR1", m_core.sr.srx.sr1.u);
+
+ state_add(ADSP2100_AX0_SEC, "AX0_SEC", m_alt.ax0.u);
+ state_add(ADSP2100_AX1_SEC, "AX1_SEC", m_alt.ax1.u);
+ state_add(ADSP2100_AY0_SEC, "AY0_SEC", m_alt.ay0.u);
+ state_add(ADSP2100_AY1_SEC, "AY1_SEC", m_alt.ay1.u);
+ state_add(ADSP2100_AR_SEC, "AR_SEC", m_alt.ar.u);
+ state_add(ADSP2100_AF_SEC, "AF_SEC", m_alt.af.u);
+
+ state_add(ADSP2100_MX0_SEC, "MX0_SEC", m_alt.mx0.u);
+ state_add(ADSP2100_MX1_SEC, "MX1_SEC", m_alt.mx1.u);
+ state_add(ADSP2100_MY0_SEC, "MY0_SEC", m_alt.my0.u);
+ state_add(ADSP2100_MY1_SEC, "MY1_SEC", m_alt.my1.u);
+ state_add(ADSP2100_MR0_SEC, "MR0_SEC", m_alt.mr.mrx.mr0.u);
+ state_add(ADSP2100_MR1_SEC, "MR1_SEC", m_alt.mr.mrx.mr1.u);
+ state_add(ADSP2100_MR2_SEC, "MR2_SEC", m_alt.mr.mrx.mr2.u).signed_mask(0xff);
+ state_add(ADSP2100_MF_SEC, "MF_SEC", m_alt.mf.u);
+
+ state_add(ADSP2100_SI_SEC, "SI_SEC", m_alt.si.u);
+ state_add(ADSP2100_SE_SEC, "SE_SEC", m_alt.se.u).signed_mask(0xff);
+ state_add(ADSP2100_SB_SEC, "SB_SEC", m_alt.sb.u).signed_mask(0x1f);
+ state_add(ADSP2100_SR0_SEC, "SR0_SEC", m_alt.sr.srx.sr0.u);
+ state_add(ADSP2100_SR1_SEC, "SR1_SEC", m_alt.sr.srx.sr1.u);
+
+ astring tempstring;
+ for (int ireg = 0; ireg < 8; ireg++)
+ state_add(ADSP2100_I0 + ireg, tempstring.format("I%d", ireg), m_i[ireg]).mask(0x3fff).callimport();
+
+ for (int lreg = 0; lreg < 8; lreg++)
+ state_add(ADSP2100_L0 + lreg, tempstring.format("L%d", lreg), m_l[lreg]).mask(0x3fff).callimport();
+
+ for (int mreg = 0; mreg < 8; mreg++)
+ state_add(ADSP2100_M0 + mreg, tempstring.format("M%d", mreg), m_m[mreg]).signed_mask(0x3fff);
+
+ state_add(ADSP2100_PX, "PX", m_px);
+ state_add(ADSP2100_CNTR, "CNTR", m_cntr).mask(0x3fff);
+ state_add(ADSP2100_ASTAT, "ASTAT", m_astat).mask(0xff);
+ state_add(ADSP2100_SSTAT, "SSTAT", m_sstat).mask(0xff);
+ state_add(ADSP2100_MSTAT, "MSTAT", m_mstat).mask((m_chip_type == CHIP_TYPE_ADSP2100) ? 0x0f : 0x7f).callimport();
+
+ state_add(ADSP2100_PCSP, "PCSP", m_pc_sp).mask(0xff);
+ state_add(STATE_GENSP, "GENSP", m_pc_sp).mask(0xff).noshow();
+ state_add(ADSP2100_CNTRSP, "CNTRSP", m_cntr_sp).mask(0xf);
+ state_add(ADSP2100_STATSP, "STATSP", m_stat_sp).mask(0xf);
+ state_add(ADSP2100_LOOPSP, "LOOPSP", m_loop_sp).mask(0xf);
+
+ state_add(ADSP2100_IMASK, "IMASK", m_imask).mask((m_chip_type == CHIP_TYPE_ADSP2100) ? 0x00f : (m_chip_type == CHIP_TYPE_ADSP2181) ? 0x3ff : 0x07f).callimport();
+ state_add(ADSP2100_ICNTL, "ICNTL", m_icntl).mask(0x1f).callimport();
+
+ for (int irqnum = 0; irqnum < 4; irqnum++)
+ if (irqnum < 4 || m_chip_type == CHIP_TYPE_ADSP2100)
+ state_add(ADSP2100_IRQSTATE0 + irqnum, tempstring.format("IRQ%d", irqnum), m_irq_state[irqnum]).mask(1).callimport();
+
+ state_add(ADSP2100_FLAGIN, "FLAGIN", m_flagin).mask(1);
+ state_add(ADSP2100_FLAGOUT, "FLAGOUT", m_flagout).mask(1);
+ state_add(ADSP2100_FL0, "FL0", m_fl0).mask(1);
+ state_add(ADSP2100_FL1, "FL1", m_fl1).mask(1);
+ state_add(ADSP2100_FL2, "FL2", m_fl2).mask(1);
+
+ // set our instruction counter
+ m_icountptr = &m_icount;
+}
+
+
+//-------------------------------------------------
+// device_reset - reset the device
+//-------------------------------------------------
+
+void adsp21xx_device::device_reset()
+{
+ // ensure that zero is zero
+ m_core.zero.u = m_alt.zero.u = 0;
+
+ // recompute the memory registers with their current values
+ write_reg1(0x08, m_l[0]); write_reg1(0x00, m_i[0]);
+ write_reg1(0x09, m_l[1]); write_reg1(0x01, m_i[1]);
+ write_reg1(0x0a, m_l[2]); write_reg1(0x02, m_i[2]);
+ write_reg1(0x0b, m_l[3]); write_reg1(0x03, m_i[3]);
+ write_reg2(0x08, m_l[4]); write_reg2(0x00, m_i[4]);
+ write_reg2(0x09, m_l[5]); write_reg2(0x01, m_i[5]);
+ write_reg2(0x0a, m_l[6]); write_reg2(0x02, m_i[6]);
+ write_reg2(0x0b, m_l[7]); write_reg2(0x03, m_i[7]);
+
+ // reset PC and loops
+ m_pc = (m_chip_type >= CHIP_TYPE_ADSP2101) ? 0 : 4;
+ m_ppc = -1;
+ m_loop = 0xffff;
+ m_loop_condition = 0;
+
+ // reset status registers
+ m_astat_clear = ~(CFLAG | VFLAG | NFLAG | ZFLAG);
+ m_mstat = 0;
+ m_sstat = 0x55;
+ m_idle = 0;
+ update_mstat();
+
+ // reset stacks
+ m_pc_sp = 0;
+ m_cntr_sp = 0;
+ m_stat_sp = 0;
+ m_loop_sp = 0;
+
+ // reset external I/O
+ m_flagout = 0;
+ m_flagin = 0;
+ m_fl0 = 0;
+ m_fl1 = 0;
+ m_fl2 = 0;
+
+ // reset interrupts
+ m_imask = 0;
+ for (int irq = 0; irq < 8; irq++)
+ m_irq_state[irq] = m_irq_latch[irq] = CLEAR_LINE;
+}
+
+
+//-------------------------------------------------
+// memory_space_config - return the configuration
+// of the specified address space, or NULL if
+// the space doesn't exist
+//-------------------------------------------------
+
+const address_space_config *adsp2100_device::memory_space_config(address_spacenum spacenum) const
+{
+ return (spacenum == AS_PROGRAM) ? &m_program_config :
+ (spacenum == AS_DATA) ? &m_data_config :
+ NULL;
+}
+
+const address_space_config *adsp2101_device::memory_space_config(address_spacenum spacenum) const
+{
+ return (spacenum == AS_PROGRAM) ? &m_program_config :
+ (spacenum == AS_DATA) ? &m_data_config :
+ NULL;
+}
+
+const address_space_config *adsp2181_device::memory_space_config(address_spacenum spacenum) const
+{
+ return (spacenum == AS_PROGRAM) ? &m_program_config :
+ (spacenum == AS_DATA) ? &m_data_config :
+ (spacenum == AS_IO) ? &m_io_config :
+ NULL;
+}
+
+
+//-------------------------------------------------
+// state_import - import state into the device,
+// after it has been set
+//-------------------------------------------------
+
+void adsp21xx_device::state_import(const device_state_entry &entry)
+{
+ switch (entry.index())
+ {
+ case ADSP2100_MSTAT:
+ update_mstat();
+ break;
+
+ case ADSP2100_IMASK:
+ case ADSP2100_ICNTL:
+ case ADSP2100_IRQSTATE0:
+ case ADSP2100_IRQSTATE1:
+ case ADSP2100_IRQSTATE2:
+ case ADSP2100_IRQSTATE3:
+ check_irqs();
+ break;
+
+ case ADSP2100_I0:
+ case ADSP2100_I1:
+ case ADSP2100_I2:
+ case ADSP2100_I3:
+ case ADSP2100_I4:
+ case ADSP2100_I5:
+ case ADSP2100_I6:
+ case ADSP2100_I7:
+ update_i(entry.index() - ADSP2100_I0);
+ break;
+
+ case ADSP2100_L0:
+ case ADSP2100_L1:
+ case ADSP2100_L2:
+ case ADSP2100_L3:
+ case ADSP2100_L4:
+ case ADSP2100_L5:
+ case ADSP2100_L6:
+ case ADSP2100_L7:
+ update_l(entry.index() - ADSP2100_L0);
+ break;
+
+ default:
+ fatalerror("CPU_IMPORT_STATE(adsp21xx) called for unexpected value\n");
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// state_string_export - export state as a string
+// for the debugger
+//-------------------------------------------------
+
+void adsp21xx_device::state_string_export(const device_state_entry &entry, astring &string)
+{
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ string.printf("%c%c%c%c%c%c%c%c",
+ m_astat & 0x80 ? 'X':'.',
+ m_astat & 0x40 ? 'M':'.',
+ m_astat & 0x20 ? 'Q':'.',
+ m_astat & 0x10 ? 'S':'.',
+ m_astat & 0x08 ? 'C':'.',
+ m_astat & 0x04 ? 'V':'.',
+ m_astat & 0x02 ? 'N':'.',
+ m_astat & 0x01 ? 'Z':'.');
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// disasm_min_opcode_bytes - return the length
+// of the shortest instruction, in bytes
+//-------------------------------------------------
+
+UINT32 adsp21xx_device::disasm_min_opcode_bytes() const
+{
+ return 4;
+}
+
+
+//-------------------------------------------------
+// disasm_max_opcode_bytes - return the length
+// of the longest instruction, in bytes
+//-------------------------------------------------
+
+UINT32 adsp21xx_device::disasm_max_opcode_bytes() const
+{
+ return 4;
+}
+
+
+//-------------------------------------------------
+// disasm_disassemble - call the disassembly
+// helper function
+//-------------------------------------------------
+
+offs_t adsp21xx_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
+{
+ extern CPU_DISASSEMBLE( adsp21xx );
+ return CPU_DISASSEMBLE_NAME(adsp21xx)(NULL, buffer, pc, oprom, opram, 0);
+}
+
+
+
+
+/***************************************************************************
+ MEMORY ACCESSORS
+***************************************************************************/
+
+inline UINT16 adsp21xx_device::data_read(UINT32 addr)
+{
+ return m_data->read_word(addr << 1);
+}
+
+inline void adsp21xx_device::data_write(UINT32 addr, UINT16 data)
+{
+ m_data->write_word(addr << 1, data);
+}
+
+inline UINT16 adsp21xx_device::io_read(UINT32 addr)
+{
+ return m_io->read_word(addr << 1);
+}
+
+inline void adsp21xx_device::io_write(UINT32 addr, UINT16 data)
+{
+ m_io->write_word(addr << 1, data);
+}
+
+inline UINT32 adsp21xx_device::program_read(UINT32 addr)
+{
+ return m_program->read_dword(addr << 2);
+}
+
+inline void adsp21xx_device::program_write(UINT32 addr, UINT32 data)
+{
+ m_program->write_dword(addr << 2, data & 0xffffff);
+}
+
+inline UINT32 adsp21xx_device::opcode_read()
+{
+ return m_direct->read_decrypted_dword(m_pc << 2);
+}
+
+
+/***************************************************************************
+ IMPORT CORE UTILITIES
+***************************************************************************/
+
+#include "2100ops.c"
+
+
+
+/***************************************************************************
+ IRQ HANDLING
+***************************************************************************/
+
+bool adsp2100_device::generate_irq(int which, int indx)
+{
+ // skip if masked
+ if (!(m_imask & (1 << which)))
+ return false;
+
+ // clear the latch
+ m_irq_latch[which] = 0;
+
+ // push the PC and the status
+ pc_stack_push();
+ stat_stack_push();
+
+ // vector to location & stop idling
+ m_pc = indx;
+ m_idle = 0;
+
+ // mask other interrupts based on the nesting bit
+ if (m_icntl & 0x10) m_imask &= ~((2 << which) - 1);
+ else m_imask &= ~0xf;
+
+ return true;
+}
+
+
+bool adsp2101_device::generate_irq(int which, int indx)
+{
+ // skip if masked
+ if (!(m_imask & (0x20 >> indx)))
+ return false;
+
+ // clear the latch
+ m_irq_latch[which] = 0;
+
+ // push the PC and the status
+ pc_stack_push();
+ stat_stack_push();
+
+ // vector to location & stop idling
+ m_pc = 0x04 + indx * 4;
+ m_idle = 0;
+
+ // mask other interrupts based on the nesting bit
+ if (m_icntl & 0x10) m_imask &= ~(0x3f >> indx);
+ else m_imask &= ~0x3f;
+
+ return true;
+}
+
+
+bool adsp2181_device::generate_irq(int which, int indx)
+{
+ // skip if masked
+ if (!(m_imask & (0x200 >> indx)))
+ return false;
+
+ // clear the latch
+ m_irq_latch[which] = 0;
+
+ // push the PC and the status
+ pc_stack_push();
+ stat_stack_push();
+
+ // vector to location & stop idling
+ m_pc = 0x04 + indx * 4;
+ m_idle = 0;
+
+ // mask other interrupts based on the nesting bit
+ if (m_icntl & 0x10) m_imask &= ~(0x3ff >> indx);
+ else m_imask &= ~0x3ff;
+
+ return true;
+}
+
+
+void adsp2100_device::check_irqs()
+{
+ UINT8 check;
+
+ // check IRQ3
+ check = (m_icntl & 8) ? m_irq_latch[ADSP2100_IRQ3] : m_irq_state[ADSP2100_IRQ3];
+ if (check && generate_irq(ADSP2100_IRQ3, 3))
+ return;
+
+ // check IRQ2
+ check = (m_icntl & 4) ? m_irq_latch[ADSP2100_IRQ2] : m_irq_state[ADSP2100_IRQ2];
+ if (check && generate_irq(ADSP2100_IRQ2, 2))
+ return;
+
+ // check IRQ1
+ check = (m_icntl & 2) ? m_irq_latch[ADSP2100_IRQ1] : m_irq_state[ADSP2100_IRQ1];
+ if (check && generate_irq(ADSP2100_IRQ1, 1))
+ return;
+
+ // check IRQ0
+ check = (m_icntl & 1) ? m_irq_latch[ADSP2100_IRQ0] : m_irq_state[ADSP2100_IRQ0];
+ if (check && generate_irq(ADSP2100_IRQ0, 0))
+ return;
+}
+
+
+void adsp2101_device::check_irqs()
+{
+ UINT8 check;
+
+ // check IRQ2
+ check = (m_icntl & 4) ? m_irq_latch[ADSP2101_IRQ2] : m_irq_state[ADSP2101_IRQ2];
+ if (check && generate_irq(ADSP2101_IRQ2, 0))
+ return;
+
+ // check SPORT0 transmit
+ check = m_irq_latch[ADSP2101_SPORT0_TX];
+ if (check && generate_irq(ADSP2101_SPORT0_TX, 1))
+ return;
+
+ // check SPORT0 receive
+ check = m_irq_latch[ADSP2101_SPORT0_RX];
+ if (check && generate_irq(ADSP2101_SPORT0_RX, 2))
+ return;
+
+ // check IRQ1/SPORT1 transmit
+ check = (m_icntl & 2) ? m_irq_latch[ADSP2101_IRQ1] : m_irq_state[ADSP2101_IRQ1];
+ if (check && generate_irq(ADSP2101_IRQ1, 3))
+ return;
+
+ // check IRQ0/SPORT1 receive
+ check = (m_icntl & 1) ? m_irq_latch[ADSP2101_IRQ0] : m_irq_state[ADSP2101_IRQ0];
+ if (check && generate_irq(ADSP2101_IRQ0, 4))
+ return;
+
+ // check timer
+ check = m_irq_latch[ADSP2101_TIMER];
+ if (check && generate_irq(ADSP2101_TIMER, 5))
+ return;
+}
+
+
+void adsp2181_device::check_irqs()
+{
+ UINT8 check;
+
+ // check IRQ2
+ check = (m_icntl & 4) ? m_irq_latch[ADSP2181_IRQ2] : m_irq_state[ADSP2181_IRQ2];
+ if (check && generate_irq(ADSP2181_IRQ2, 0))
+ return;
+
+ // check IRQL1
+ check = m_irq_state[ADSP2181_IRQL1];
+ if (check && generate_irq(ADSP2181_IRQL1, 1))
+ return;
+
+ // check IRQL2
+ check = m_irq_state[ADSP2181_IRQL2];
+ if (check && generate_irq(ADSP2181_IRQL2, 2))
+ return;
+
+ // check SPORT0 transmit
+ check = m_irq_latch[ADSP2181_SPORT0_TX];
+ if (check && generate_irq(ADSP2181_SPORT0_TX, 3))
+ return;
+
+ // check SPORT0 receive
+ check = m_irq_latch[ADSP2181_SPORT0_RX];
+ if (check && generate_irq(ADSP2181_SPORT0_RX, 4))
+ return;
+
+ // check IRQE
+ check = m_irq_latch[ADSP2181_IRQE];
+ if (check && generate_irq(ADSP2181_IRQE, 5))
+ return;
+
+ // check BDMA interrupt
+
+ // check IRQ1/SPORT1 transmit
+ check = (m_icntl & 2) ? m_irq_latch[ADSP2181_IRQ1] : m_irq_state[ADSP2181_IRQ1];
+ if (check && generate_irq(ADSP2181_IRQ1, 7))
+ return;
+
+ // check IRQ0/SPORT1 receive
+ check = (m_icntl & 1) ? m_irq_latch[ADSP2181_IRQ0] : m_irq_state[ADSP2181_IRQ0];
+ if (check && generate_irq(ADSP2181_IRQ0, 8))
+ return;
+
+ // check timer
+ check = m_irq_latch[ADSP2181_TIMER];
+ if (check && generate_irq(ADSP2181_TIMER, 9))
+ return;
+}
+
+
+
+/***************************************************************************
+ INITIALIZATION AND SHUTDOWN
+***************************************************************************/
+
+void adsp21xx_device::create_tables()
+{
+ // initialize the bit reversing table
+ for (int i = 0; i < 0x4000; i++)
+ {
+ UINT16 data = 0;
+
+ data |= (i >> 13) & 0x0001;
+ data |= (i >> 11) & 0x0002;
+ data |= (i >> 9) & 0x0004;
+ data |= (i >> 7) & 0x0008;
+ data |= (i >> 5) & 0x0010;
+ data |= (i >> 3) & 0x0020;
+ data |= (i >> 1) & 0x0040;
+ data |= (i << 1) & 0x0080;
+ data |= (i << 3) & 0x0100;
+ data |= (i << 5) & 0x0200;
+ data |= (i << 7) & 0x0400;
+ data |= (i << 9) & 0x0800;
+ data |= (i << 11) & 0x1000;
+ data |= (i << 13) & 0x2000;
+
+ m_reverse_table[i] = data;
+ }
+
+ // initialize the mask table
+ for (int i = 0; i < 0x4000; i++)
+ {
+ if (i > 0x2000) m_mask_table[i] = 0x0000;
+ else if (i > 0x1000) m_mask_table[i] = 0x2000;
+ else if (i > 0x0800) m_mask_table[i] = 0x3000;
+ else if (i > 0x0400) m_mask_table[i] = 0x3800;
+ else if (i > 0x0200) m_mask_table[i] = 0x3c00;
+ else if (i > 0x0100) m_mask_table[i] = 0x3e00;
+ else if (i > 0x0080) m_mask_table[i] = 0x3f00;
+ else if (i > 0x0040) m_mask_table[i] = 0x3f80;
+ else if (i > 0x0020) m_mask_table[i] = 0x3fc0;
+ else if (i > 0x0010) m_mask_table[i] = 0x3fe0;
+ else if (i > 0x0008) m_mask_table[i] = 0x3ff0;
+ else if (i > 0x0004) m_mask_table[i] = 0x3ff8;
+ else if (i > 0x0002) m_mask_table[i] = 0x3ffc;
+ else if (i > 0x0001) m_mask_table[i] = 0x3ffe;
+ else m_mask_table[i] = 0x3fff;
+ }
+
+ // initialize the condition table
+ for (int i = 0; i < 0x100; i++)
+ {
+ int az = ((i & ZFLAG) != 0);
+ int an = ((i & NFLAG) != 0);
+ int av = ((i & VFLAG) != 0);
+ int ac = ((i & CFLAG) != 0);
+ int mv = ((i & MVFLAG) != 0);
+ int as = ((i & SFLAG) != 0);
+
+ m_condition_table[i | 0x000] = az;
+ m_condition_table[i | 0x100] = !az;
+ m_condition_table[i | 0x200] = !((an ^ av) | az);
+ m_condition_table[i | 0x300] = (an ^ av) | az;
+ m_condition_table[i | 0x400] = an ^ av;
+ m_condition_table[i | 0x500] = !(an ^ av);
+ m_condition_table[i | 0x600] = av;
+ m_condition_table[i | 0x700] = !av;
+ m_condition_table[i | 0x800] = ac;
+ m_condition_table[i | 0x900] = !ac;
+ m_condition_table[i | 0xa00] = as;
+ m_condition_table[i | 0xb00] = !as;
+ m_condition_table[i | 0xc00] = mv;
+ m_condition_table[i | 0xd00] = !mv;
+ m_condition_table[i | 0xf00] = 1;
+ }
+}
+
+
+
+/***************************************************************************
+ CORE EXECUTION LOOP
+***************************************************************************/
+
+//-------------------------------------------------
+// execute_min_cycles - return minimum number of
+// cycles it takes for one instruction to execute
+//-------------------------------------------------
+
+UINT32 adsp21xx_device::execute_min_cycles() const
+{
+ return 1;
+}
+
+
+//-------------------------------------------------
+// execute_max_cycles - return maximum number of
+// cycles it takes for one instruction to execute
+//-------------------------------------------------
+
+UINT32 adsp21xx_device::execute_max_cycles() const
+{
+ return 1;
+}
+
+
+//-------------------------------------------------
+// execute_input_lines - return the number of
+// input/interrupt lines
+//-------------------------------------------------
+
+UINT32 adsp2100_device::execute_input_lines() const
+{
+ return 4;
+}
+
+UINT32 adsp2101_device::execute_input_lines() const
+{
+ return 5;
+}
+
+UINT32 adsp2181_device::execute_input_lines() const
+{
+ return 9;
+}
+
+
+void adsp21xx_device::execute_set_input(int inputnum, int state)
+{
+ // update the latched state
+ if (state != CLEAR_LINE && m_irq_state[inputnum] == CLEAR_LINE)
+ m_irq_latch[inputnum] = 1;
+
+ // update the absolute state
+ m_irq_state[inputnum] = state;
+}
+
+
+void adsp21xx_device::execute_run()
+{
+ bool check_debugger = ((device_t::machine().debug_flags & DEBUG_FLAG_ENABLED) != 0);
+
+ check_irqs();
+
+ do
+ {
+ // debugging
+ m_ppc = m_pc; // copy PC to previous PC
+ if (check_debugger)
+ debugger_instruction_hook(this, m_pc);
+
+#if ADSP_TRACK_HOTSPOTS
+ m_pcbucket[m_pc & 0x3fff]++;
+#endif
+
+ // instruction fetch
+ UINT32 op = opcode_read();
+
+ // advance to the next instruction
+ if (m_pc != m_loop)
+ m_pc++;
+
+ // handle looping
+ else
+ {
+ // condition not met, keep looping
+ if (condition(m_loop_condition))
+ m_pc = pc_stack_top();
+
+ // condition met; pop the PC and loop stacks and fall through
+ else
+ {
+ loop_stack_pop();
+ pc_stack_pop_val();
+ m_pc++;
+ }
+ }
+
+ // parse the instruction
+ UINT32 temp;
+ switch ((op >> 16) & 0xff)
+ {
+ case 0x00:
+ // 00000000 00000000 00000000 NOP
+ break;
+ case 0x01:
+ // 00000001 0xxxxxxx xxxxxxxx dst = IO(x)
+ // 00000001 1xxxxxxx xxxxxxxx IO(x) = dst
+ // ADSP-218x only
+ if (m_chip_type >= CHIP_TYPE_ADSP2181)
+ {
+ if ((op & 0x008000) == 0x000000)
+ write_reg0(op & 15, io_read((op >> 4) & 0x7ff));
+ else
+ io_write((op >> 4) & 0x7ff, read_reg0(op & 15));
+ }
+ break;
+ case 0x02:
+ // 00000010 0000xxxx xxxxxxxx modify flag out
+ // 00000010 10000000 00000000 idle
+ // 00000010 10000000 0000xxxx idle (n)
+ if (op & 0x008000)
+ {
+ m_idle = 1;
+ m_icount = 0;
+ }
+ else
+ {
+ if (condition(op & 15))
+ {
+ if (op & 0x020) m_flagout = 0;
+ if (op & 0x010) m_flagout ^= 1;
+ if (m_chip_type >= CHIP_TYPE_ADSP2101)
+ {
+ if (op & 0x080) m_fl0 = 0;
+ if (op & 0x040) m_fl0 ^= 1;
+ if (op & 0x200) m_fl1 = 0;
+ if (op & 0x100) m_fl1 ^= 1;
+ if (op & 0x800) m_fl2 = 0;
+ if (op & 0x400) m_fl2 ^= 1;
+ }
+ }
+ }
+ break;
+ case 0x03:
+ // 00000011 xxxxxxxx xxxxxxxx call or jump on flag in
+ if (op & 0x000002)
+ {
+ if (m_flagin)
+ {
+ if (op & 0x000001)
+ pc_stack_push();
+ m_pc = ((op >> 4) & 0x0fff) | ((op << 10) & 0x3000);
+ }
+ }
+ else
+ {
+ if (!m_flagin)
+ {
+ if (op & 0x000001)
+ pc_stack_push();
+ m_pc = ((op >> 4) & 0x0fff) | ((op << 10) & 0x3000);
+ }
+ }
+ break;
+ case 0x04:
+ // 00000100 00000000 000xxxxx stack control
+ if (op & 0x000010) pc_stack_pop_val();
+ if (op & 0x000008) loop_stack_pop();
+ if (op & 0x000004) cntr_stack_pop();
+ if (op & 0x000002)
+ {
+ if (op & 0x000001) stat_stack_pop();
+ else stat_stack_push();
+ }
+ break;
+ case 0x05:
+ // 00000101 00000000 00000000 saturate MR
+ if (GET_MV)
+ {
+ if (m_core.mr.mrx.mr2.u & 0x80)
+ m_core.mr.mrx.mr2.u = 0xffff, m_core.mr.mrx.mr1.u = 0x8000, m_core.mr.mrx.mr0.u = 0x0000;
+ else
+ m_core.mr.mrx.mr2.u = 0x0000, m_core.mr.mrx.mr1.u = 0x7fff, m_core.mr.mrx.mr0.u = 0xffff;
+ }
+ break;
+ case 0x06:
+ // 00000110 000xxxxx 00000000 DIVS
+ {
+ int xop = (op >> 8) & 7;
+ int yop = (op >> 11) & 3;
+
+ xop = ALU_GETXREG_UNSIGNED(xop);
+ yop = ALU_GETYREG_UNSIGNED(yop);
+
+ temp = xop ^ yop;
+ m_astat = (m_astat & ~QFLAG) | ((temp >> 10) & QFLAG);
+ m_core.af.u = (yop << 1) | (m_core.ay0.u >> 15);
+ m_core.ay0.u = (m_core.ay0.u << 1) | (temp >> 15);
+ }
+ break;
+ case 0x07:
+ // 00000111 00010xxx 00000000 DIVQ
+ {
+ int xop = (op >> 8) & 7;
+ int res;
+
+ xop = ALU_GETXREG_UNSIGNED(xop);
+
+ if (GET_Q)
+ res = m_core.af.u + xop;
+ else
+ res = m_core.af.u - xop;
+
+ temp = res ^ xop;
+ m_astat = (m_astat & ~QFLAG) | ((temp >> 10) & QFLAG);
+ m_core.af.u = (res << 1) | (m_core.ay0.u >> 15);
+ m_core.ay0.u = (m_core.ay0.u << 1) | ((~temp >> 15) & 0x0001);
+ }
+ break;
+ case 0x08:
+ // 00001000 00000000 0000xxxx reserved
+ break;
+ case 0x09:
+ // 00001001 00000000 000xxxxx modify address register
+ temp = (op >> 2) & 4;
+ modify_address(temp + ((op >> 2) & 3), temp + (op & 3));
+ break;
+ case 0x0a:
+ // 00001010 00000000 000xxxxx conditional return
+ if (condition(op & 15))
+ {
+ pc_stack_pop();
+
+ // RTI case
+ if (op & 0x000010)
+ stat_stack_pop();
+ }
+ break;
+ case 0x0b:
+ // 00001011 00000000 xxxxxxxx conditional jump (indirect address)
+ if (condition(op & 15))
+ {
+ if (op & 0x000010)
+ pc_stack_push();
+ m_pc = m_i[4 + ((op >> 6) & 3)] & 0x3fff;
+ }
+ break;
+ case 0x0c:
+ // 00001100 xxxxxxxx xxxxxxxx mode control
+ if (m_chip_type >= CHIP_TYPE_ADSP2101)
+ {
+ if (op & 0x000008) m_mstat = (m_mstat & ~MSTAT_GOMODE) | ((op << 5) & MSTAT_GOMODE);
+ if (op & 0x002000) m_mstat = (m_mstat & ~MSTAT_INTEGER) | ((op >> 8) & MSTAT_INTEGER);
+ if (op & 0x008000) m_mstat = (m_mstat & ~MSTAT_TIMER) | ((op >> 9) & MSTAT_TIMER);
+ }
+ if (op & 0x000020) m_mstat = (m_mstat & ~MSTAT_BANK) | ((op >> 4) & MSTAT_BANK);
+ if (op & 0x000080) m_mstat = (m_mstat & ~MSTAT_REVERSE) | ((op >> 5) & MSTAT_REVERSE);
+ if (op & 0x000200) m_mstat = (m_mstat & ~MSTAT_STICKYV) | ((op >> 6) & MSTAT_STICKYV);
+ if (op & 0x000800) m_mstat = (m_mstat & ~MSTAT_SATURATE) | ((op >> 7) & MSTAT_SATURATE);
+ update_mstat();
+ break;
+ case 0x0d:
+ // 00001101 0000xxxx xxxxxxxx internal data move
+ switch ((op >> 8) & 15)
+ {
+ case 0x00: write_reg0((op >> 4) & 15, read_reg0(op & 15)); break;
+ case 0x01: write_reg0((op >> 4) & 15, read_reg1(op & 15)); break;
+ case 0x02: write_reg0((op >> 4) & 15, read_reg2(op & 15)); break;
+ case 0x03: write_reg0((op >> 4) & 15, read_reg3(op & 15)); break;
+ case 0x04: write_reg1((op >> 4) & 15, read_reg0(op & 15)); break;
+ case 0x05: write_reg1((op >> 4) & 15, read_reg1(op & 15)); break;
+ case 0x06: write_reg1((op >> 4) & 15, read_reg2(op & 15)); break;
+ case 0x07: write_reg1((op >> 4) & 15, read_reg3(op & 15)); break;
+ case 0x08: write_reg2((op >> 4) & 15, read_reg0(op & 15)); break;
+ case 0x09: write_reg2((op >> 4) & 15, read_reg1(op & 15)); break;
+ case 0x0a: write_reg2((op >> 4) & 15, read_reg2(op & 15)); break;
+ case 0x0b: write_reg2((op >> 4) & 15, read_reg3(op & 15)); break;
+ case 0x0c: write_reg3((op >> 4) & 15, read_reg0(op & 15)); break;
+ case 0x0d: write_reg3((op >> 4) & 15, read_reg1(op & 15)); break;
+ case 0x0e: write_reg3((op >> 4) & 15, read_reg2(op & 15)); break;
+ case 0x0f: write_reg3((op >> 4) & 15, read_reg3(op & 15)); break;
+ }
+ break;
+ case 0x0e:
+ // 00001110 0xxxxxxx xxxxxxxx conditional shift
+ if (condition(op & 15)) shift_op(op);
+ break;
+ case 0x0f:
+ // 00001111 0xxxxxxx xxxxxxxx shift immediate
+ shift_op_imm(op);
+ break;
+ case 0x10:
+ // 00010000 0xxxxxxx xxxxxxxx shift with internal data register move
+ shift_op(op);
+ temp = read_reg0(op & 15);
+ write_reg0((op >> 4) & 15, temp);
+ break;
+ case 0x11:
+ // 00010001 xxxxxxxx xxxxxxxx shift with pgm memory read/write
+ if (op & 0x8000)
+ {
+ pgm_write_dag2(op, read_reg0((op >> 4) & 15));
+ shift_op(op);
+ }
+ else
+ {
+ shift_op(op);
+ write_reg0((op >> 4) & 15, pgm_read_dag2(op));
+ }
+ break;
+ case 0x12:
+ // 00010010 xxxxxxxx xxxxxxxx shift with data memory read/write DAG1
+ if (op & 0x8000)
+ {
+ data_write_dag1(op, read_reg0((op >> 4) & 15));
+ shift_op(op);
+ }
+ else
+ {
+ shift_op(op);
+ write_reg0((op >> 4) & 15, data_read_dag1(op));
+ }
+ break;
+ case 0x13:
+ // 00010011 xxxxxxxx xxxxxxxx shift with data memory read/write DAG2
+ if (op & 0x8000)
+ {
+ data_write_dag2(op, read_reg0((op >> 4) & 15));
+ shift_op(op);
+ }
+ else
+ {
+ shift_op(op);
+ write_reg0((op >> 4) & 15, data_read_dag2(op));
+ }
+ break;
+ case 0x14: case 0x15: case 0x16: case 0x17:
+ // 000101xx xxxxxxxx xxxxxxxx do until
+ loop_stack_push(op & 0x3ffff);
+ pc_stack_push();
+ break;
+ case 0x18: case 0x19: case 0x1a: case 0x1b:
+ // 000110xx xxxxxxxx xxxxxxxx conditional jump (immediate addr)
+ if (condition(op & 15))
+ {
+ m_pc = (op >> 4) & 0x3fff;
+ // check for a busy loop
+ if (m_pc == m_ppc)
+ m_icount = 0;
+ }
+ break;
+ case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ // 000111xx xxxxxxxx xxxxxxxx conditional call (immediate addr)
+ if (condition(op & 15))
+ {
+ pc_stack_push();
+ m_pc = (op >> 4) & 0x3fff;
+ }
+ break;
+ case 0x20: case 0x21:
+ // 0010000x xxxxxxxx xxxxxxxx conditional MAC to MR
+ if (condition(op & 15))
+ {
+ if (m_chip_type >= CHIP_TYPE_ADSP2181 && (op & 0x0018f0) == 0x000010)
+ mac_op_mr_xop(op);
+ else
+ mac_op_mr(op);
+ }
+ break;
+ case 0x22: case 0x23:
+ // 0010001x xxxxxxxx xxxxxxxx conditional ALU to AR
+ if (condition(op & 15))
+ {
+ if (m_chip_type >= CHIP_TYPE_ADSP2181 && (op & 0x000010) == 0x000010)
+ alu_op_ar_const(op);
+ else
+ alu_op_ar(op);
+ }
+ break;
+ case 0x24: case 0x25:
+ // 0010010x xxxxxxxx xxxxxxxx conditional MAC to MF
+ if (condition(op & 15))
+ {
+ if (m_chip_type >= CHIP_TYPE_ADSP2181 && (op & 0x0018f0) == 0x000010)
+ mac_op_mf_xop(op);
+ else
+ mac_op_mf(op);
+ }
+ break;
+ case 0x26: case 0x27:
+ // 0010011x xxxxxxxx xxxxxxxx conditional ALU to AF
+ if (condition(op & 15))
+ {
+ if (m_chip_type >= CHIP_TYPE_ADSP2181 && (op & 0x000010) == 0x000010)
+ alu_op_af_const(op);
+ else
+ alu_op_af(op);
+ }
+ break;
+ case 0x28: case 0x29:
+ // 0010100x xxxxxxxx xxxxxxxx MAC to MR with internal data register move
+ temp = read_reg0(op & 15);
+ mac_op_mr(op);
+ write_reg0((op >> 4) & 15, temp);
+ break;
+ case 0x2a: case 0x2b:
+ // 0010101x xxxxxxxx xxxxxxxx ALU to AR with internal data register move
+ if (m_chip_type >= CHIP_TYPE_ADSP2181 && (op & 0x0000ff) == 0x0000aa)
+ alu_op_none(op);
+ else
+ {
+ temp = read_reg0(op & 15);
+ alu_op_ar(op);
+ write_reg0((op >> 4) & 15, temp);
+ }
+ break;
+ case 0x2c: case 0x2d:
+ // 0010110x xxxxxxxx xxxxxxxx MAC to MF with internal data register move
+ temp = read_reg0(op & 15);
+ mac_op_mf(op);
+ write_reg0((op >> 4) & 15, temp);
+ break;
+ case 0x2e: case 0x2f:
+ // 0010111x xxxxxxxx xxxxxxxx ALU to AF with internal data register move
+ temp = read_reg0(op & 15);
+ alu_op_af(op);
+ write_reg0((op >> 4) & 15, temp);
+ break;
+ case 0x30: case 0x31: case 0x32: case 0x33:
+ // 001100xx xxxxxxxx xxxxxxxx load non-data register immediate (group 0)
+ write_reg0(op & 15, (INT32)(op << 14) >> 18);
+ break;
+ case 0x34: case 0x35: case 0x36: case 0x37:
+ // 001101xx xxxxxxxx xxxxxxxx load non-data register immediate (group 1)
+ write_reg1(op & 15, (INT32)(op << 14) >> 18);
+ break;
+ case 0x38: case 0x39: case 0x3a: case 0x3b:
+ // 001110xx xxxxxxxx xxxxxxxx load non-data register immediate (group 2)
+ write_reg2(op & 15, (INT32)(op << 14) >> 18);
+ break;
+ case 0x3c: case 0x3d: case 0x3e: case 0x3f:
+ // 001111xx xxxxxxxx xxxxxxxx load non-data register immediate (group 3)
+ write_reg3(op & 15, (INT32)(op << 14) >> 18);
+ break;
+ case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47:
+ case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f:
+ // 0100xxxx xxxxxxxx xxxxxxxx load data register immediate
+ write_reg0(op & 15, (op >> 4) & 0xffff);
+ break;
+ case 0x50: case 0x51:
+ // 0101000x xxxxxxxx xxxxxxxx MAC to MR with pgm memory read
+ mac_op_mr(op);
+ write_reg0((op >> 4) & 15, pgm_read_dag2(op));
+ break;
+ case 0x52: case 0x53:
+ // 0101001x xxxxxxxx xxxxxxxx ALU to AR with pgm memory read
+ alu_op_ar(op);
+ write_reg0((op >> 4) & 15, pgm_read_dag2(op));
+ break;
+ case 0x54: case 0x55:
+ // 0101010x xxxxxxxx xxxxxxxx MAC to MF with pgm memory read
+ mac_op_mf(op);
+ write_reg0((op >> 4) & 15, pgm_read_dag2(op));
+ break;
+ case 0x56: case 0x57:
+ // 0101011x xxxxxxxx xxxxxxxx ALU to AF with pgm memory read
+ alu_op_af(op);
+ write_reg0((op >> 4) & 15, pgm_read_dag2(op));
+ break;
+ case 0x58: case 0x59:
+ // 0101100x xxxxxxxx xxxxxxxx MAC to MR with pgm memory write
+ pgm_write_dag2(op, read_reg0((op >> 4) & 15));
+ mac_op_mr(op);
+ break;
+ case 0x5a: case 0x5b:
+ // 0101101x xxxxxxxx xxxxxxxx ALU to AR with pgm memory write
+ pgm_write_dag2(op, read_reg0((op >> 4) & 15));
+ alu_op_ar(op);
+ break;
+ case 0x5c: case 0x5d:
+ // 0101110x xxxxxxxx xxxxxxxx ALU to MR with pgm memory write
+ pgm_write_dag2(op, read_reg0((op >> 4) & 15));
+ mac_op_mf(op);
+ break;
+ case 0x5e: case 0x5f:
+ // 0101111x xxxxxxxx xxxxxxxx ALU to MF with pgm memory write
+ pgm_write_dag2(op, read_reg0((op >> 4) & 15));
+ alu_op_af(op);
+ break;
+ case 0x60: case 0x61:
+ // 0110000x xxxxxxxx xxxxxxxx MAC to MR with data memory read DAG1
+ mac_op_mr(op);
+ write_reg0((op >> 4) & 15, data_read_dag1(op));
+ break;
+ case 0x62: case 0x63:
+ // 0110001x xxxxxxxx xxxxxxxx ALU to AR with data memory read DAG1
+ alu_op_ar(op);
+ write_reg0((op >> 4) & 15, data_read_dag1(op));
+ break;
+ case 0x64: case 0x65:
+ // 0110010x xxxxxxxx xxxxxxxx MAC to MF with data memory read DAG1
+ mac_op_mf(op);
+ write_reg0((op >> 4) & 15, data_read_dag1(op));
+ break;
+ case 0x66: case 0x67:
+ // 0110011x xxxxxxxx xxxxxxxx ALU to AF with data memory read DAG1
+ alu_op_af(op);
+ write_reg0((op >> 4) & 15, data_read_dag1(op));
+ break;
+ case 0x68: case 0x69:
+ // 0110100x xxxxxxxx xxxxxxxx MAC to MR with data memory write DAG1
+ data_write_dag1(op, read_reg0((op >> 4) & 15));
+ mac_op_mr(op);
+ break;
+ case 0x6a: case 0x6b:
+ // 0110101x xxxxxxxx xxxxxxxx ALU to AR with data memory write DAG1
+ data_write_dag1(op, read_reg0((op >> 4) & 15));
+ alu_op_ar(op);
+ break;
+ case 0x6c: case 0x6d:
+ // 0111110x xxxxxxxx xxxxxxxx MAC to MF with data memory write DAG1
+ data_write_dag1(op, read_reg0((op >> 4) & 15));
+ mac_op_mf(op);
+ break;
+ case 0x6e: case 0x6f:
+ // 0111111x xxxxxxxx xxxxxxxx ALU to AF with data memory write DAG1
+ data_write_dag1(op, read_reg0((op >> 4) & 15));
+ alu_op_af(op);
+ break;
+ case 0x70: case 0x71:
+ // 0111000x xxxxxxxx xxxxxxxx MAC to MR with data memory read DAG2
+ mac_op_mr(op);
+ write_reg0((op >> 4) & 15, data_read_dag2(op));
+ break;
+ case 0x72: case 0x73:
+ // 0111001x xxxxxxxx xxxxxxxx ALU to AR with data memory read DAG2
+ alu_op_ar(op);
+ write_reg0((op >> 4) & 15, data_read_dag2(op));
+ break;
+ case 0x74: case 0x75:
+ // 0111010x xxxxxxxx xxxxxxxx MAC to MF with data memory read DAG2
+ mac_op_mf(op);
+ write_reg0((op >> 4) & 15, data_read_dag2(op));
+ break;
+ case 0x76: case 0x77:
+ // 0111011x xxxxxxxx xxxxxxxx ALU to AF with data memory read DAG2
+ alu_op_af(op);
+ write_reg0((op >> 4) & 15, data_read_dag2(op));
+ break;
+ case 0x78: case 0x79:
+ // 0111100x xxxxxxxx xxxxxxxx MAC to MR with data memory write DAG2
+ data_write_dag2(op, read_reg0((op >> 4) & 15));
+ mac_op_mr(op);
+ break;
+ case 0x7a: case 0x7b:
+ // 0111101x xxxxxxxx xxxxxxxx ALU to AR with data memory write DAG2
+ data_write_dag2(op, read_reg0((op >> 4) & 15));
+ alu_op_ar(op);
+ break;
+ case 0x7c: case 0x7d:
+ // 0111110x xxxxxxxx xxxxxxxx MAC to MF with data memory write DAG2
+ data_write_dag2(op, read_reg0((op >> 4) & 15));
+ mac_op_mf(op);
+ break;
+ case 0x7e: case 0x7f:
+ // 0111111x xxxxxxxx xxxxxxxx ALU to AF with data memory write DAG2
+ data_write_dag2(op, read_reg0((op >> 4) & 15));
+ alu_op_af(op);
+ break;
+ case 0x80: case 0x81: case 0x82: case 0x83:
+ // 100000xx xxxxxxxx xxxxxxxx read data memory (immediate addr) to reg group 0
+ write_reg0(op & 15, data_read((op >> 4) & 0x3fff));
+ break;
+ case 0x84: case 0x85: case 0x86: case 0x87:
+ // 100001xx xxxxxxxx xxxxxxxx read data memory (immediate addr) to reg group 1
+ write_reg1(op & 15, data_read((op >> 4) & 0x3fff));
+ break;
+ case 0x88: case 0x89: case 0x8a: case 0x8b:
+ // 100010xx xxxxxxxx xxxxxxxx read data memory (immediate addr) to reg group 2
+ write_reg2(op & 15, data_read((op >> 4) & 0x3fff));
+ break;
+ case 0x8c: case 0x8d: case 0x8e: case 0x8f:
+ // 100011xx xxxxxxxx xxxxxxxx read data memory (immediate addr) to reg group 3
+ write_reg3(op & 15, data_read((op >> 4) & 0x3fff));
+ break;
+ case 0x90: case 0x91: case 0x92: case 0x93:
+ // 1001xxxx xxxxxxxx xxxxxxxx write data memory (immediate addr) from reg group 0
+ data_write((op >> 4) & 0x3fff, read_reg0(op & 15));
+ break;
+ case 0x94: case 0x95: case 0x96: case 0x97:
+ // 1001xxxx xxxxxxxx xxxxxxxx write data memory (immediate addr) from reg group 1
+ data_write((op >> 4) & 0x3fff, read_reg1(op & 15));
+ break;
+ case 0x98: case 0x99: case 0x9a: case 0x9b:
+ // 1001xxxx xxxxxxxx xxxxxxxx write data memory (immediate addr) from reg group 2
+ data_write((op >> 4) & 0x3fff, read_reg2(op & 15));
+ break;
+ case 0x9c: case 0x9d: case 0x9e: case 0x9f:
+ // 1001xxxx xxxxxxxx xxxxxxxx write data memory (immediate addr) from reg group 3
+ data_write((op >> 4) & 0x3fff, read_reg3(op & 15));
+ break;
+ case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7:
+ case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf:
+ // 1010xxxx xxxxxxxx xxxxxxxx data memory write (immediate) DAG1
+ data_write_dag1(op, (op >> 4) & 0xffff);
+ break;
+ case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7:
+ case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf:
+ // 1011xxxx xxxxxxxx xxxxxxxx data memory write (immediate) DAG2
+ data_write_dag2(op, (op >> 4) & 0xffff);
+ break;
+ case 0xc0: case 0xc1:
+ // 1100000x xxxxxxxx xxxxxxxx MAC to MR with data read to AX0 & pgm read to AY0
+ mac_op_mr(op);
+ m_core.ax0.u = data_read_dag1(op);
+ m_core.ay0.u = pgm_read_dag2(op >> 4);
+ break;
+ case 0xc2: case 0xc3:
+ // 1100001x xxxxxxxx xxxxxxxx ALU to AR with data read to AX0 & pgm read to AY0
+ alu_op_ar(op);
+ m_core.ax0.u = data_read_dag1(op);
+ m_core.ay0.u = pgm_read_dag2(op >> 4);
+ break;
+ case 0xc4: case 0xc5:
+ // 1100010x xxxxxxxx xxxxxxxx MAC to MR with data read to AX1 & pgm read to AY0
+ mac_op_mr(op);
+ m_core.ax1.u = data_read_dag1(op);
+ m_core.ay0.u = pgm_read_dag2(op >> 4);
+ break;
+ case 0xc6: case 0xc7:
+ // 1100011x xxxxxxxx xxxxxxxx ALU to AR with data read to AX1 & pgm read to AY0
+ alu_op_ar(op);
+ m_core.ax1.u = data_read_dag1(op);
+ m_core.ay0.u = pgm_read_dag2(op >> 4);
+ break;
+ case 0xc8: case 0xc9:
+ // 1100100x xxxxxxxx xxxxxxxx MAC to MR with data read to MX0 & pgm read to AY0
+ mac_op_mr(op);
+ m_core.mx0.u = data_read_dag1(op);
+ m_core.ay0.u = pgm_read_dag2(op >> 4);
+ break;
+ case 0xca: case 0xcb:
+ // 1100101x xxxxxxxx xxxxxxxx ALU to AR with data read to MX0 & pgm read to AY0
+ alu_op_ar(op);
+ m_core.mx0.u = data_read_dag1(op);
+ m_core.ay0.u = pgm_read_dag2(op >> 4);
+ break;
+ case 0xcc: case 0xcd:
+ // 1100110x xxxxxxxx xxxxxxxx MAC to MR with data read to MX1 & pgm read to AY0
+ mac_op_mr(op);
+ m_core.mx1.u = data_read_dag1(op);
+ m_core.ay0.u = pgm_read_dag2(op >> 4);
+ break;
+ case 0xce: case 0xcf:
+ // 1100111x xxxxxxxx xxxxxxxx ALU to AR with data read to MX1 & pgm read to AY0
+ alu_op_ar(op);
+ m_core.mx1.u = data_read_dag1(op);
+ m_core.ay0.u = pgm_read_dag2(op >> 4);
+ break;
+ case 0xd0: case 0xd1:
+ // 1101000x xxxxxxxx xxxxxxxx MAC to MR with data read to AX0 & pgm read to AY1
+ mac_op_mr(op);
+ m_core.ax0.u = data_read_dag1(op);
+ m_core.ay1.u = pgm_read_dag2(op >> 4);
+ break;
+ case 0xd2: case 0xd3:
+ // 1101001x xxxxxxxx xxxxxxxx ALU to AR with data read to AX0 & pgm read to AY1
+ alu_op_ar(op);
+ m_core.ax0.u = data_read_dag1(op);
+ m_core.ay1.u = pgm_read_dag2(op >> 4);
+ break;
+ case 0xd4: case 0xd5:
+ // 1101010x xxxxxxxx xxxxxxxx MAC to MR with data read to AX1 & pgm read to AY1
+ mac_op_mr(op);
+ m_core.ax1.u = data_read_dag1(op);
+ m_core.ay1.u = pgm_read_dag2(op >> 4);
+ break;
+ case 0xd6: case 0xd7:
+ // 1101011x xxxxxxxx xxxxxxxx ALU to AR with data read to AX1 & pgm read to AY1
+ alu_op_ar(op);
+ m_core.ax1.u = data_read_dag1(op);
+ m_core.ay1.u = pgm_read_dag2(op >> 4);
+ break;
+ case 0xd8: case 0xd9:
+ // 1101100x xxxxxxxx xxxxxxxx MAC to MR with data read to MX0 & pgm read to AY1
+ mac_op_mr(op);
+ m_core.mx0.u = data_read_dag1(op);
+ m_core.ay1.u = pgm_read_dag2(op >> 4);
+ break;
+ case 0xda: case 0xdb:
+ // 1101101x xxxxxxxx xxxxxxxx ALU to AR with data read to MX0 & pgm read to AY1
+ alu_op_ar(op);
+ m_core.mx0.u = data_read_dag1(op);
+ m_core.ay1.u = pgm_read_dag2(op >> 4);
+ break;
+ case 0xdc: case 0xdd:
+ // 1101110x xxxxxxxx xxxxxxxx MAC to MR with data read to MX1 & pgm read to AY1
+ mac_op_mr(op);
+ m_core.mx1.u = data_read_dag1(op);
+ m_core.ay1.u = pgm_read_dag2(op >> 4);
+ break;
+ case 0xde: case 0xdf:
+ // 1101111x xxxxxxxx xxxxxxxx ALU to AR with data read to MX1 & pgm read to AY1
+ alu_op_ar(op);
+ m_core.mx1.u = data_read_dag1(op);
+ m_core.ay1.u = pgm_read_dag2(op >> 4);
+ break;
+ case 0xe0: case 0xe1:
+ // 1110000x xxxxxxxx xxxxxxxx MAC to MR with data read to AX0 & pgm read to MY0
+ mac_op_mr(op);
+ m_core.ax0.u = data_read_dag1(op);
+ m_core.my0.u = pgm_read_dag2(op >> 4);
+ break;
+ case 0xe2: case 0xe3:
+ // 1110001x xxxxxxxx xxxxxxxx ALU to AR with data read to AX0 & pgm read to MY0
+ alu_op_ar(op);
+ m_core.ax0.u = data_read_dag1(op);
+ m_core.my0.u = pgm_read_dag2(op >> 4);
+ break;
+ case 0xe4: case 0xe5:
+ // 1110010x xxxxxxxx xxxxxxxx MAC to MR with data read to AX1 & pgm read to MY0
+ mac_op_mr(op);
+ m_core.ax1.u = data_read_dag1(op);
+ m_core.my0.u = pgm_read_dag2(op >> 4);
+ break;
+ case 0xe6: case 0xe7:
+ // 1110011x xxxxxxxx xxxxxxxx ALU to AR with data read to AX1 & pgm read to MY0
+ alu_op_ar(op);
+ m_core.ax1.u = data_read_dag1(op);
+ m_core.my0.u = pgm_read_dag2(op >> 4);
+ break;
+ case 0xe8: case 0xe9:
+ // 1110100x xxxxxxxx xxxxxxxx MAC to MR with data read to MX0 & pgm read to MY0
+ mac_op_mr(op);
+ m_core.mx0.u = data_read_dag1(op);
+ m_core.my0.u = pgm_read_dag2(op >> 4);
+ break;
+ case 0xea: case 0xeb:
+ // 1110101x xxxxxxxx xxxxxxxx ALU to AR with data read to MX0 & pgm read to MY0
+ alu_op_ar(op);
+ m_core.mx0.u = data_read_dag1(op);
+ m_core.my0.u = pgm_read_dag2(op >> 4);
+ break;
+ case 0xec: case 0xed:
+ // 1110110x xxxxxxxx xxxxxxxx MAC to MR with data read to MX1 & pgm read to MY0
+ mac_op_mr(op);
+ m_core.mx1.u = data_read_dag1(op);
+ m_core.my0.u = pgm_read_dag2(op >> 4);
+ break;
+ case 0xee: case 0xef:
+ // 1110111x xxxxxxxx xxxxxxxx ALU to AR with data read to MX1 & pgm read to MY0
+ alu_op_ar(op);
+ m_core.mx1.u = data_read_dag1(op);
+ m_core.my0.u = pgm_read_dag2(op >> 4);
+ break;
+ case 0xf0: case 0xf1:
+ // 1111000x xxxxxxxx xxxxxxxx MAC to MR with data read to AX0 & pgm read to MY1
+ mac_op_mr(op);
+ m_core.ax0.u = data_read_dag1(op);
+ m_core.my1.u = pgm_read_dag2(op >> 4);
+ break;
+ case 0xf2: case 0xf3:
+ // 1111001x xxxxxxxx xxxxxxxx ALU to AR with data read to AX0 & pgm read to MY1
+ alu_op_ar(op);
+ m_core.ax0.u = data_read_dag1(op);
+ m_core.my1.u = pgm_read_dag2(op >> 4);
+ break;
+ case 0xf4: case 0xf5:
+ // 1111010x xxxxxxxx xxxxxxxx MAC to MR with data read to AX1 & pgm read to MY1
+ mac_op_mr(op);
+ m_core.ax1.u = data_read_dag1(op);
+ m_core.my1.u = pgm_read_dag2(op >> 4);
+ break;
+ case 0xf6: case 0xf7:
+ // 1111011x xxxxxxxx xxxxxxxx ALU to AR with data read to AX1 & pgm read to MY1
+ alu_op_ar(op);
+ m_core.ax1.u = data_read_dag1(op);
+ m_core.my1.u = pgm_read_dag2(op >> 4);
+ break;
+ case 0xf8: case 0xf9:
+ // 1111100x xxxxxxxx xxxxxxxx MAC to MR with data read to MX0 & pgm read to MY1
+ mac_op_mr(op);
+ m_core.mx0.u = data_read_dag1(op);
+ m_core.my1.u = pgm_read_dag2(op >> 4);
+ break;
+ case 0xfa: case 0xfb:
+ // 1111101x xxxxxxxx xxxxxxxx ALU to AR with data read to MX0 & pgm read to MY1
+ alu_op_ar(op);
+ m_core.mx0.u = data_read_dag1(op);
+ m_core.my1.u = pgm_read_dag2(op >> 4);
+ break;
+ case 0xfc: case 0xfd:
+ // 1111110x xxxxxxxx xxxxxxxx MAC to MR with data read to MX1 & pgm read to MY1
+ mac_op_mr(op);
+ m_core.mx1.u = data_read_dag1(op);
+ m_core.my1.u = pgm_read_dag2(op >> 4);
+ break;
+ case 0xfe: case 0xff:
+ // 1111111x xxxxxxxx xxxxxxxx ALU to AR with data read to MX1 & pgm read to MY1
+ alu_op_ar(op);
+ m_core.mx1.u = data_read_dag1(op);
+ m_core.my1.u = pgm_read_dag2(op >> 4);
+ break;
+ }
+
+ m_icount--;
+ } while (m_icount > 0);
+}
diff --git a/trunk/src/emu/cpu/adsp2100/adsp2100.h b/trunk/src/emu/cpu/adsp2100/adsp2100.h
new file mode 100644
index 00000000000..4e39cf2cddf
--- /dev/null
+++ b/trunk/src/emu/cpu/adsp2100/adsp2100.h
@@ -0,0 +1,625 @@
+/***************************************************************************
+
+ adsp2100.h
+
+ ADSP-21xx series emulator.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __ADSP2100_H__
+#define __ADSP2100_H__
+
+
+//**************************************************************************
+// DEBUGGING
+//**************************************************************************
+
+#define ADSP_TRACK_HOTSPOTS 0
+
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// ADSP-2100 IRQs
+const int ADSP2100_IRQ0 = 0; // IRQ0
+const int ADSP2100_SPORT1_RX = 0; // SPORT1 receive IRQ
+const int ADSP2100_IRQ1 = 1; // IRQ1
+const int ADSP2100_SPORT1_TX = 1; // SPORT1 transmit IRQ
+const int ADSP2100_IRQ2 = 2; // IRQ2
+const int ADSP2100_IRQ3 = 3; // IRQ3
+
+// ADSP-2101 IRQs
+const int ADSP2101_IRQ0 = 0; // IRQ0
+const int ADSP2101_SPORT1_RX = 0; // SPORT1 receive IRQ
+const int ADSP2101_IRQ1 = 1; // IRQ1
+const int ADSP2101_SPORT1_TX = 1; // SPORT1 transmit IRQ
+const int ADSP2101_IRQ2 = 2; // IRQ2
+const int ADSP2101_SPORT0_RX = 3; // SPORT0 receive IRQ
+const int ADSP2101_SPORT0_TX = 4; // SPORT0 transmit IRQ
+const int ADSP2101_TIMER = 5; // internal timer IRQ
+
+// ADSP-2104 IRQs
+const int ADSP2104_IRQ0 = 0; // IRQ0
+const int ADSP2104_SPORT1_RX = 0; // SPORT1 receive IRQ
+const int ADSP2104_IRQ1 = 1; // IRQ1
+const int ADSP2104_SPORT1_TX = 1; // SPORT1 transmit IRQ
+const int ADSP2104_IRQ2 = 2; // IRQ2
+const int ADSP2104_SPORT0_RX = 3; // SPORT0 receive IRQ
+const int ADSP2104_SPORT0_TX = 4; // SPORT0 transmit IRQ
+const int ADSP2104_TIMER = 5; // internal timer IRQ
+
+// ADSP-2105 IRQs
+const int ADSP2105_IRQ0 = 0; // IRQ0
+const int ADSP2105_SPORT1_RX = 0; // SPORT1 receive IRQ
+const int ADSP2105_IRQ1 = 1; // IRQ1
+const int ADSP2105_SPORT1_TX = 1; // SPORT1 transmit IRQ
+const int ADSP2105_IRQ2 = 2; // IRQ2
+const int ADSP2105_TIMER = 5; // internal timer IRQ
+
+// ADSP-2115 IRQs
+const int ADSP2115_IRQ0 = 0; // IRQ0
+const int ADSP2115_SPORT1_RX = 0; // SPORT1 receive IRQ
+const int ADSP2115_IRQ1 = 1; // IRQ1
+const int ADSP2115_SPORT1_TX = 1; // SPORT1 transmit IRQ
+const int ADSP2115_IRQ2 = 2; // IRQ2
+const int ADSP2115_SPORT0_RX = 3; // SPORT0 receive IRQ
+const int ADSP2115_SPORT0_TX = 4; // SPORT0 transmit IRQ
+const int ADSP2115_TIMER = 5; // internal timer IRQ
+
+// ADSP-2181 IRQs
+const int ADSP2181_IRQ0 = 0; // IRQ0
+const int ADSP2181_SPORT1_RX = 0; // SPORT1 receive IRQ
+const int ADSP2181_IRQ1 = 1; // IRQ1
+const int ADSP2181_SPORT1_TX = 1; // SPORT1 transmit IRQ
+const int ADSP2181_IRQ2 = 2; // IRQ2
+const int ADSP2181_SPORT0_RX = 3; // SPORT0 receive IRQ
+const int ADSP2181_SPORT0_TX = 4; // SPORT0 transmit IRQ
+const int ADSP2181_TIMER = 5; // internal timer IRQ
+const int ADSP2181_IRQE = 6; // IRQE
+const int ADSP2181_IRQL1 = 7; // IRQL1
+const int ADSP2181_IRQL2 = 8; // IRQL2
+
+// register enumeration
+enum
+{
+ ADSP2100_PC,
+ ADSP2100_AX0,
+ ADSP2100_AX1,
+ ADSP2100_AY0,
+ ADSP2100_AY1,
+ ADSP2100_AR,
+ ADSP2100_AF,
+ ADSP2100_MX0,
+ ADSP2100_MX1,
+ ADSP2100_MY0,
+ ADSP2100_MY1,
+ ADSP2100_MR0,
+ ADSP2100_MR1,
+ ADSP2100_MR2,
+ ADSP2100_MF,
+ ADSP2100_SI,
+ ADSP2100_SE,
+ ADSP2100_SB,
+ ADSP2100_SR0,
+ ADSP2100_SR1,
+ ADSP2100_I0,
+ ADSP2100_I1,
+ ADSP2100_I2,
+ ADSP2100_I3,
+ ADSP2100_I4,
+ ADSP2100_I5,
+ ADSP2100_I6,
+ ADSP2100_I7,
+ ADSP2100_L0,
+ ADSP2100_L1,
+ ADSP2100_L2,
+ ADSP2100_L3,
+ ADSP2100_L4,
+ ADSP2100_L5,
+ ADSP2100_L6,
+ ADSP2100_L7,
+ ADSP2100_M0,
+ ADSP2100_M1,
+ ADSP2100_M2,
+ ADSP2100_M3,
+ ADSP2100_M4,
+ ADSP2100_M5,
+ ADSP2100_M6,
+ ADSP2100_M7,
+ ADSP2100_PX,
+ ADSP2100_CNTR,
+ ADSP2100_ASTAT,
+ ADSP2100_SSTAT,
+ ADSP2100_MSTAT,
+ ADSP2100_PCSP,
+ ADSP2100_CNTRSP,
+ ADSP2100_STATSP,
+ ADSP2100_LOOPSP,
+ ADSP2100_IMASK,
+ ADSP2100_ICNTL,
+ ADSP2100_IRQSTATE0,
+ ADSP2100_IRQSTATE1,
+ ADSP2100_IRQSTATE2,
+ ADSP2100_IRQSTATE3,
+ ADSP2100_FLAGIN,
+ ADSP2100_FLAGOUT,
+ ADSP2100_FL0,
+ ADSP2100_FL1,
+ ADSP2100_FL2,
+ ADSP2100_AX0_SEC,
+ ADSP2100_AX1_SEC,
+ ADSP2100_AY0_SEC,
+ ADSP2100_AY1_SEC,
+ ADSP2100_AR_SEC,
+ ADSP2100_AF_SEC,
+ ADSP2100_MX0_SEC,
+ ADSP2100_MX1_SEC,
+ ADSP2100_MY0_SEC,
+ ADSP2100_MY1_SEC,
+ ADSP2100_MR0_SEC,
+ ADSP2100_MR1_SEC,
+ ADSP2100_MR2_SEC,
+ ADSP2100_MF_SEC,
+ ADSP2100_SI_SEC,
+ ADSP2100_SE_SEC,
+ ADSP2100_SB_SEC,
+ ADSP2100_SR0_SEC,
+ ADSP2100_SR1_SEC,
+
+ ADSP2100_GENPC = STATE_GENPC,
+ ADSP2100_GENSP = STATE_GENSP,
+ ADSP2100_GENPCBASE = STATE_GENPCBASE
+};
+
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_ADSP21XX_CONFIG(_config) \
+ adsp21xx_device::static_set_config(*device, _config); \
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class adsp21xx_device;
+
+// transmit and receive data callbacks types
+typedef INT32 (*adsp21xx_rx_func)(adsp21xx_device &device, int port);
+typedef void (*adsp21xx_tx_func)(adsp21xx_device &device, int port, INT32 data);
+typedef void (*adsp21xx_timer_func)(adsp21xx_device &device, int enable);
+
+
+// ======================> adsp21xx_config
+
+struct adsp21xx_config
+{
+ adsp21xx_rx_func m_sport_rx_callback; // callback for serial receive
+ adsp21xx_tx_func m_sport_tx_callback; // callback for serial transmit
+ adsp21xx_timer_func m_timer_fired; // callback for timer fired
+};
+
+
+
+// ======================> adsp21xx_device
+
+class adsp21xx_device : public cpu_device,
+ public adsp21xx_config
+{
+protected:
+ enum
+ {
+ CHIP_TYPE_ADSP2100,
+ CHIP_TYPE_ADSP2101,
+ CHIP_TYPE_ADSP2104,
+ CHIP_TYPE_ADSP2105,
+ CHIP_TYPE_ADSP2115,
+ CHIP_TYPE_ADSP2181,
+ };
+
+ // construction/destruction
+ adsp21xx_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, UINT32 chiptype);
+ virtual ~adsp21xx_device();
+
+public:
+ // inline configuration helpers
+ static void static_set_config(device_t &device, const adsp21xx_config &config);
+
+ // public interfaces
+ void load_boot_data(UINT8 *srcdata, UINT32 *dstdata);
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ // device_execute_interface overrides
+ virtual UINT32 execute_min_cycles() const;
+ virtual UINT32 execute_max_cycles() const;
+ virtual void execute_run();
+ virtual void execute_set_input(int inputnum, int state);
+
+ // device_state_interface overrides
+ virtual void state_import(const device_state_entry &entry);
+ virtual void state_string_export(const device_state_entry &entry, astring &string);
+
+ // device_disasm_interface overrides
+ virtual UINT32 disasm_min_opcode_bytes() const;
+ virtual UINT32 disasm_max_opcode_bytes() const;
+ virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);
+
+ // helpers
+ void create_tables();
+ inline void update_mstat();
+ inline UINT32 pc_stack_top();
+ inline void set_pc_stack_top(UINT32 top);
+ inline void pc_stack_push();
+ inline void pc_stack_push_val(UINT32 val);
+ inline void pc_stack_pop();
+ inline UINT32 pc_stack_pop_val();
+ inline UINT32 cntr_stack_top();
+ inline void cntr_stack_push();
+ inline void cntr_stack_pop();
+ inline UINT32 loop_stack_top();
+ inline void loop_stack_push(UINT32 value);
+ inline void loop_stack_pop();
+ inline void stat_stack_push();
+ inline void stat_stack_pop();
+// inline int condition(int c);
+ int slow_condition();
+ inline void modify_address(UINT32 ireg, UINT32 mreg);
+ inline void data_write_dag1(UINT32 op, INT32 val);
+ inline UINT32 data_read_dag1(UINT32 op);
+ inline void data_write_dag2(UINT32 op, INT32 val);
+ inline UINT32 data_read_dag2(UINT32 op);
+ inline void pgm_write_dag2(UINT32 op, INT32 val);
+ inline UINT32 pgm_read_dag2(UINT32 op);
+ void alu_op_ar(int op);
+ void alu_op_ar_const(int op);
+ void alu_op_af(int op);
+ void alu_op_af_const(int op);
+ void alu_op_none(int op);
+ void mac_op_mr(int op);
+ void mac_op_mr_xop(int op);
+ void mac_op_mf(int op);
+ void mac_op_mf_xop(int op);
+ void shift_op(int op);
+ void shift_op_imm(int op);
+
+ // memory access
+ inline UINT16 data_read(UINT32 addr);
+ inline void data_write(UINT32 addr, UINT16 data);
+ inline UINT16 io_read(UINT32 addr);
+ inline void io_write(UINT32 addr, UINT16 data);
+ inline UINT32 program_read(UINT32 addr);
+ inline void program_write(UINT32 addr, UINT32 data);
+ inline UINT32 opcode_read();
+
+ // register read/write
+ inline void update_i(int which);
+ inline void update_l(int which);
+ inline void write_reg0(int regnum, INT32 val);
+ inline void write_reg1(int regnum, INT32 val);
+ inline void write_reg2(int regnum, INT32 val);
+ inline void write_reg3(int regnum, INT32 val);
+ inline INT32 read_reg0(int regnum);
+ inline INT32 read_reg1(int regnum);
+ inline INT32 read_reg2(int regnum);
+ inline INT32 read_reg3(int regnum);
+
+ // interrupts
+ virtual bool generate_irq(int which, int indx = 0) = 0;
+ virtual void check_irqs() = 0;
+
+ // internal state
+ static const int PC_STACK_DEPTH = 16;
+ static const int CNTR_STACK_DEPTH = 4;
+ static const int STAT_STACK_DEPTH = 4;
+ static const int LOOP_STACK_DEPTH = 4;
+
+ // 16-bit registers that can be loaded signed or unsigned
+ union adsp_reg16
+ {
+ UINT16 u;
+ INT16 s;
+ };
+
+ // the SHIFT result register is 32 bits
+ union adsp_shift
+ {
+#ifdef LSB_FIRST
+ struct { adsp_reg16 sr0, sr1; } srx;
+#else
+ struct { adsp_reg16 sr1, sr0; } srx;
+#endif
+ UINT32 sr;
+ };
+
+ // the MAC result register is 40 bits
+ union adsp_mac
+ {
+#ifdef LSB_FIRST
+ struct { adsp_reg16 mr0, mr1, mr2, mrzero; } mrx;
+ struct { UINT32 mr0, mr1; } mry;
+#else
+ struct { adsp_reg16 mrzero, mr2, mr1, mr0; } mrx;
+ struct { UINT32 mr1, mr0; } mry;
+#endif
+ UINT64 mr;
+ };
+
+ // core registers which are replicated
+ struct adsp_core
+ {
+ // ALU registers
+ adsp_reg16 ax0, ax1;
+ adsp_reg16 ay0, ay1;
+ adsp_reg16 ar;
+ adsp_reg16 af;
+
+ // MAC registers
+ adsp_reg16 mx0, mx1;
+ adsp_reg16 my0, my1;
+ adsp_mac mr;
+ adsp_reg16 mf;
+
+ // SHIFT registers
+ adsp_reg16 si;
+ adsp_reg16 se;
+ adsp_reg16 sb;
+ adsp_shift sr;
+
+ // dummy registers
+ adsp_reg16 zero;
+ };
+
+ // configuration
+ const address_space_config m_program_config;
+ const address_space_config m_data_config;
+ UINT32 m_chip_type;
+
+ // other CPU registers
+ UINT32 m_pc;
+ UINT32 m_ppc;
+ UINT32 m_loop;
+ UINT32 m_loop_condition;
+ UINT32 m_cntr;
+
+ // status registers
+ UINT32 m_astat;
+ UINT32 m_sstat;
+ UINT32 m_mstat;
+ UINT32 m_mstat_prev;
+ UINT32 m_astat_clear;
+ UINT32 m_idle;
+
+ // live set of core registers
+ adsp_core m_core;
+
+ // memory addressing registers
+ UINT32 m_i[8];
+ INT32 m_m[8];
+ UINT32 m_l[8];
+ UINT32 m_lmask[8];
+ UINT32 m_base[8];
+ UINT8 m_px;
+
+ // stacks
+ UINT32 m_loop_stack[LOOP_STACK_DEPTH];
+ UINT32 m_cntr_stack[CNTR_STACK_DEPTH];
+ UINT32 m_pc_stack[PC_STACK_DEPTH];
+ UINT16 m_stat_stack[STAT_STACK_DEPTH][3];
+ INT32 m_pc_sp;
+ INT32 m_cntr_sp;
+ INT32 m_stat_sp;
+ INT32 m_loop_sp;
+
+ // external I/O
+ UINT8 m_flagout;
+ UINT8 m_flagin;
+ UINT8 m_fl0;
+ UINT8 m_fl1;
+ UINT8 m_fl2;
+ UINT16 m_idma_addr;
+ UINT16 m_idma_cache;
+ UINT8 m_idma_offs;
+
+ // interrupt handling
+ UINT16 m_imask;
+ UINT8 m_icntl;
+ UINT16 m_ifc;
+ UINT8 m_irq_state[9];
+ UINT8 m_irq_latch[9];
+
+ // other internal states
+ int m_icount;
+ int m_mstat_mask;
+ int m_imask_mask;
+
+ // register maps
+ INT16 * m_read0_ptr[16];
+ UINT32 * m_read1_ptr[16];
+ UINT32 * m_read2_ptr[16];
+ void * m_alu_xregs[8];
+ void * m_alu_yregs[4];
+ void * m_mac_xregs[8];
+ void * m_mac_yregs[4];
+ void * m_shift_xregs[8];
+
+ // alternate core registers (at end for performance)
+ adsp_core m_alt;
+
+ // address spaces
+ address_space * m_program;
+ address_space * m_data;
+ address_space * m_io;
+ direct_read_data * m_direct;
+
+ // tables
+ UINT8 m_condition_table[0x1000];
+ UINT16 m_mask_table[0x4000];
+ UINT16 m_reverse_table[0x4000];
+
+ // debugging
+#if ADSP_TRACK_HOTSPOTS
+ UINT32 m_pcbucket[0x4000];
+#endif
+
+ // flag definitions
+ static const int SSFLAG = 0x80;
+ static const int MVFLAG = 0x40;
+ static const int QFLAG = 0x20;
+ static const int SFLAG = 0x10;
+ static const int CFLAG = 0x08;
+ static const int VFLAG = 0x04;
+ static const int NFLAG = 0x02;
+ static const int ZFLAG = 0x01;
+};
+
+
+// ======================> adsp2100_device
+
+class adsp2100_device : public adsp21xx_device
+{
+public:
+ // construction/destruction
+ adsp2100_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+protected:
+ // device_execute_interface overrides
+ virtual UINT32 execute_input_lines() const;
+
+ // device_memory_interface overrides
+ virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const;
+
+ // interrupts
+ virtual bool generate_irq(int which, int indx);
+ virtual void check_irqs();
+};
+
+
+// ======================> adsp2101_device
+
+class adsp2101_device : public adsp21xx_device
+{
+public:
+ // construction/destruction
+ adsp2101_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+protected:
+ adsp2101_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, UINT32 chiptype);
+
+ // device_execute_interface overrides
+ virtual UINT32 execute_input_lines() const;
+
+ // device_memory_interface overrides
+ virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const;
+
+ // interrupts
+ virtual bool generate_irq(int which, int indx);
+ virtual void check_irqs();
+};
+
+
+// ======================> adsp2181_device
+
+class adsp2181_device : public adsp21xx_device
+{
+public:
+ // construction/destruction
+ adsp2181_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+protected:
+ // device_execute_interface overrides
+ virtual UINT32 execute_input_lines() const;
+
+ // device_memory_interface overrides
+ virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const;
+
+ // interrupts
+ virtual bool generate_irq(int which, int indx);
+ virtual void check_irqs();
+
+ // address spaces
+ const address_space_config m_io_config;
+
+public:
+ // public interfaces
+ void idma_addr_w(UINT16 data);
+ UINT16 idma_addr_r();
+ void idma_data_w(UINT16 data);
+ UINT16 idma_data_r();
+};
+
+
+// ======================> trivial variants
+
+class adsp2104_device : public adsp2101_device
+{
+public:
+ adsp2104_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+class adsp2105_device : public adsp2101_device
+{
+public:
+ adsp2105_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+class adsp2115_device : public adsp2101_device
+{
+public:
+ adsp2115_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+
+
+// device type definition
+extern const device_type ADSP2100;
+extern const device_type ADSP2101;
+extern const device_type ADSP2104;
+extern const device_type ADSP2105;
+extern const device_type ADSP2115;
+extern const device_type ADSP2181;
+
+
+#endif /* __ADSP2100_H__ */
diff --git a/trunk/src/emu/cpu/alph8201/8201dasm.c b/trunk/src/emu/cpu/alph8201/8201dasm.c
new file mode 100644
index 00000000000..4cdd76075a0
--- /dev/null
+++ b/trunk/src/emu/cpu/alph8201/8201dasm.c
@@ -0,0 +1,402 @@
+/****************************************************************************
+ Alpha 8201/8301 Disassembler
+
+ Copyright Tatsuyuki Satoh
+ Originally written for the MAME project.
+
+****************************************************************************/
+
+#include "emu.h"
+
+#include <ctype.h>
+
+typedef unsigned char byte;
+
+#define FMT(a,b) a, b
+#define PTRS_PER_FORMAT 2
+
+/****************************************************
+
+8201 CONFIRMED OPCODES:
+
+opcode mnemonic function flags
+-------- ------------ ------------- -----
+00000000 NOP - --
+00000001 RORA ror A -C
+00000010 ROLA rol A -C
+00000011 INC RXB RXB+=2 ZC
+00000100 DEC RXB RXB-=2 ZC (C=1 means No Borrow: RXB>=2)
+00000101 INC A A++ ZC
+00000110 DEC A A-- ZC (C=1 means No Borrow: A>=1)
+00000110 CPL A A^=$FF --
+00001aaa LD A,(IX0+i) A=[IX0+i] --
+00010aaa LD A,(IX1+i) A=[IX1+i] --
+00011aaa LD (IX2+i),A [IX2+i]=A --
+00111aaa BIT R0.n ZF=R0 bit n Z-
+0100aaa0 LD A,Rn A=Rn Z- [1]
+0100aaa1 LD Rn,A Rn=A --
+0101aaa0 ADD A,Rn A+=Rn ZC
+0101aaa1 SUB A,Rn A-=Rn ZC (C=1 means No Borrow: A>=Rn)
+0110aaa0 AND A,Rn A&=Rn Z-
+0110aaa1 OR A,Rn A|=Rn Z-
+0111aaaa ADD IX0,i IX0+=i --
+1000aaaa ADD IX1,i IX1+=i --
+1001aaaa ADD IX2,i IX2+=i --
+1010aaaa LD RB,i RB=i -- Note: no bounds checking. Can set bank up to F.
+1011-0aa LD MB,i set after-jump page
+1011-1-- STOP
+11000000 imm LD IX0,imm IX0=imm --
+11000001 imm LD IX1,imm IX1=imm --
+11000010 imm LD IX2,imm IX2=imm --
+11000011 imm LD A,imm A=imm --
+11000100 imm LD LP0,imm LP0=imm --
+11000101 imm LD LP1,imm LP1=imm --
+11000110 imm LD LP2,imm LP2=imm --
+11000111 imm LD RXB,imm RXB=imm --
+11001000 imm ADD A,imm A+=imm ZC
+11001001 imm SUB A,imm A-=imm ZC (C=1 means No Borrow: A>=imm)
+11001010 imm AND A,imm A&=imm Z-
+11001011 imm OR A,imm A|=imm Z-
+11001100 imm DJNZ LP0,imm LP0--,branch --
+11001101 imm DJNZ LP1,imm LP1--,branch --
+11001110 imm DJNZ LP2,imm LP2--,branch --
+11001111 imm JNZ imm branch if !Z --
+1101--00 imm JNC imm branch if !C --
+1101--01 imm JZ imm branch if Z --
+1101--1- imm J imm branch --
+1110--xx mirror for the above
+1111--xx mirror for the above
+
+Notes:
+[1] bug: the Z flag is not updated correctly after a LD A,Rn instruction. Fixed in 8302 (possibly 8301).
+
+
+8302 CONFIRMED OPCODES:
+----------------------
+all of the 8201 ones, with stricter decoding for the following:
+
+11010-00 imm JNC imm branch if !C --
+11010-01 imm JZ imm branch if Z --
+11010-1- imm J imm branch --
+
+and these new opcodes:
+
+opcode mnemonic function flags
+-------- ------------ --------------- -----
+11011000 imm LD A,(imm) A=MB:[imm] --
+11011001 imm LD (imm),A MB:[imm]=A --
+11011010 imm CMP A,imm temp=A-imm ZC
+11011011 imm XOR A,imm A^=imm Z0
+11011100 imm LD A,R(imm) A=reg(imm) --
+11011101 imm LD R(imm),A reg(imm)=A --
+11011110 imm JC imm branch if C --
+11011111 imm CALL $xx save PC, branch --
+
+11100000 EXG A,IX0 A<->IX0 --
+11100001 EXG A,IX1 A<->IX1 --
+11100010 EXG A,IX2 A<->IX2 --
+11100011 EXG A,LP1 A<->LP1 --
+11100100 EXG A,LP2 A<->LP2 --
+11100101 EXG A,RXB A<->RXB --
+11100110 EXG A,LP0 A<->LP0 --
+11100111 EXG A,RB A<->RB --
+11101000 LD IX0,A IX0=A --
+11101001 LD IX1,A IX1=A --
+11101010 LD IX2,A IX2=A --
+11101011 LD LP1,A LP1=A --
+11101100 LD LP2,A LP2=A --
+11101101 LD RXB,A RXB=A --
+11101110 LD LP0,A LP0=A --
+11101111 LD RB,A RB=A --
+11110000 EXG IX0,IX1 IX0<->IX1 --
+11110001 EXG IX0,IX2 IX0<->IX2 --
+11110010 REP LD (IX2),(RXB) equivalent to LD (IX2),(RXB); INC RXB; DJNZ LP0
+11110011 REP LD (RXB),(IX0) equivalent to LD (RXB),(IX0); INC RXB; DJNZ LP0
+11110100 SAVE ZC save ZC --
+11110101 REST ZC restore ZC ZC
+11110110 LD (RXB),A reg(RXB)=A --
+11110111 LD A,(RXB) A=reg(RXB) --
+11111000 CMP A,(RXB) temp=A-reg(RXB) ZC
+11111001 XOR A,(RXB) A^=reg(RXB) Z0
+11111010 ADD A,CF if (C) A++ ZC
+11111011 SUB A,!CF if (!C) A-- ZC
+11111100 TST A A==0? Z-
+11111101 CLR A A=0 --
+11111110 LD A,(IX0+A) A=[IX0+A] --
+11111111 RET restore PC --
+
+
+8303 CONFIRMED OPCODES:
+----------------------
+all of the 8302 ones, with stricter decoding for the following:
+
+11010000 imm JNC imm branch if !C --
+11010001 imm JZ imm branch if Z --
+1101001- imm J imm branch --
+
+additionally, this opcode is modified to support 11-bit instead of 10-bit
+external addressing, this wasn't used in games however.
+
+1011-0aa LD MB,i modified so that bit 3 is shifted to bit 2 before loading MB.
+
+and these new opcodes are added:
+
+110101--
+11010100 imm LD A,(R77:$%02X)
+11010101 imm LD (R77:$%02X),A
+11010110 imm LD PC,(R77:$%02X) [1]
+11010111 imm LD (R77:$%02X),PC [2]
+
+Notes:
+[1] appears to be LD PC,x in the disassembly, however it's LD LP0,x for kouyakyu
+ which uses a 8304, so the opcode was probably changed again.
+[2] appears to be LD x,PC in the disassembly, however it's LD x,LP0 for hvoltage
+ which uses a 8304 (or 8404?), so the opcode was probably changed again.
+
+****************************************************/
+
+
+/****************************************************/
+
+static const char *const Formats[] = {
+ FMT("0000_0000", "NOP"), // 00
+ FMT("0000_0001", "RRCA"), // 01
+ FMT("0000_0010", "RLCA"), // 02
+ FMT("0000_0011", "INC RXB"), // 03 : shougi $360 to $377; splndrbt
+ FMT("0000_0100", "DEC RXB"), // 04 : not found
+ FMT("0000_0101", "INC A"), // 05
+ FMT("0000_0110", "DEC A"), // 06
+ FMT("0000_0111", "CPL A"), // 07
+ FMT("0000_1aaa", "LD A,(IX0+%X)"), // 08-0F
+ FMT("0001_0aaa", "LD A,(IX1+%X)"), // 10-17
+ FMT("0001_1aaa", "LD (IX2+%X),A"), // 18-1F
+ FMT("0010_0aaa", "LD (RXB),(IX0+%X)"),// 20-27 : shougi $360 to $377
+ FMT("0010_1aaa", "LD (RXB),(IX1+%X)"),// 28-2f : not found
+ FMT("0011_0aaa", "LD (IX2+%X),(RXB)"),// 30-37 : not found
+ FMT("0011_1aaa", "BIT R0.%d"), // 38-3F ZF = R0.a (bit test)
+ FMT("0100_aaa0", "LD A,R%X"), // 40-4E
+ FMT("0100_aaa1", "LD R%X,A"), // 41-4F
+ FMT("0101_aaa0", "ADD A,R%X"), // 50-5E
+ FMT("0101_aaa1", "SUB A,R%X"), // 51-5F
+ FMT("0110_aaa0", "AND A,R%X"), // 60-6E
+ FMT("0110_aaa1", "OR A,R%X"), // 61-6F
+ FMT("0111_aaaa", "ADD IX0,$%X"), // 70-7f
+ FMT("1000_aaaa", "ADD IX1,$%X"), // 80-8f
+ FMT("1001_aaaa", "ADD IX2,$%X"), // 90-9f
+ FMT("1010_aaaa", "LD RB,%X"), // A0-AF
+ FMT("1011_x0aa", "LD MB,%X"), // B0-B3 (+ mirrors)
+ FMT("1011_x1xx", "STOP"), // B4 (+ mirrors)
+
+ FMT("1100_0000 I", "LD IX0,$%02X"), // C0
+ FMT("1100_0001 I", "LD IX1,$%02X"), // C1
+ FMT("1100_0010 I", "LD IX2,$%02X"), // C2
+ FMT("1100_0011 I", "LD A,$%02X"), // C3
+ FMT("1100_0100 I", "LD LP0,$%02X"), // C4
+ FMT("1100_0101 I", "LD LP1,$%02X"), // C5
+ FMT("1100_0110 I", "LD LP2,$%02X"), // C6
+ FMT("1100_0111 I", "LD RXB,$%02X"), // C7 : shougi, splndrbt, equites
+ FMT("1100_1000 I", "ADD A,$%02X"), // C8
+ FMT("1100_1001 I", "SUB A,$%02X"), // C9
+ FMT("1100_1010 I", "AND A,$%02X"), // CA
+ FMT("1100_1011 I", "OR A,$%02X"), // CB
+ FMT("1100_1100 I", "DJNZ LP0,$%02X"), // CC
+ FMT("1100_1101 I", "DJNZ LP1,$%02X"), // CD
+ FMT("1100_1110 I", "DJNZ LP2,$%02X"), // CE
+ FMT("1100_1111 I", "JNZ $%02X"), // CF
+ FMT("1101_0000 I", "JNC $%02X"), // D0
+ FMT("1101_0001 I", "JZ $%02X"), // D1
+ FMT("1101_001x I", "J $%02X"), // D2 (+ mirror)
+
+ /* -------------- 830x only ------------- */
+
+ FMT("1101_0100 I", "LD A,(R77:$%02X)"), // D4 : 8303+ only. exctscc2, bullfgtr
+ FMT("1101_0101 I", "LD (R77:$%02X),A"), // D5 : 8303+ only. exctscc2, bullfgtr, kouyakyu
+ FMT("1101_0110 I", "LD LP0,(R77:$%02X)"), // D6 : 8303+ only. kouyakyu
+ FMT("1101_0111 I", "LD (R77:$%02X),LP0"), // D7 : 8303+ only. hvoltage
+ FMT("1101_1000 I", "LD A,($%02X)"), // D8 : equites
+ FMT("1101_1001 I", "LD ($%02X),A"), // D9 : equites
+ FMT("1101_1010 I", "CMP A,$%02X"), // DA :
+ FMT("1101_1011 I", "XOR A,$%02X"), // DB : equites splndrbt
+ FMT("1101_1100 I", "LD A,R($%02X)"), // DC : not found
+ FMT("1101_1101 I", "LD R($%02X),A"), // DD : equites, splndrbt
+ FMT("1101_1110 I", "JC $%02X"), // DE : not found
+ FMT("1101_1111 I", "CALL $%02X"), // DF :
+
+ FMT("1110_0000", "EXG A,IX0"), // E0 : exctsccr
+ FMT("1110_0001", "EXG A,IX1"), // E1 : not found
+ FMT("1110_0010", "EXG A,IX2"), // E2 : not found
+ FMT("1110_0011", "EXG A,LP1"), // E3 : exctsccr in pair with EB
+ FMT("1110_0100", "EXG A,LP2"), // E4 : not found
+ FMT("1110_0101", "EXG A,RXB"), // E5 : splndrbt
+ FMT("1110_0110", "EXG A,LP0"), // E6 : splndrbt, bullfgtr, kouyakyu. EXG, not LD: see splndrbt $3ba to $3d3
+ FMT("1110_0111", "EXG A,RB"), // E7 : not found
+ FMT("1110_1000", "LD IX0,A"), // E8 :
+ FMT("1110_1001", "LD IX1,A"), // E9 : not found
+ FMT("1110_1010", "LD IX2,A"), // EA :
+ FMT("1110_1011", "LD LP1,A"), // EB : exctsccr in pair with E3
+ FMT("1110_1100", "LP LP2,A"), // EC : not found
+ FMT("1110_1101", "LD RXB,A"), // ED : splndrbt
+ FMT("1110_1110", "LD LP0,A"), // EE : splndrbt, bullfgtr
+ FMT("1110_1111", "LD RB,A"), // EF : not found
+ FMT("1111_0000", "EXG IX0,IX1"), // F0 : not found
+ FMT("1111_0001", "EXG IX0,IX2"), // F1 : splndrbt $2e to $38, equites $40 to $4a
+ FMT("1111_0010", "REP LD (IX2),(RXB)"),// F2 : splndrbt LD (IX2),(RXB); INC RXB; DJNZ LP0
+ FMT("1111_0011", "REP LD (RXB),(IX0)"),// F3 : not found LD (RXB),(IX0); INC RXB; DJNZ LP0
+ FMT("1111_0100", "SAVE ZC"), // F4 : not found
+ FMT("1111_0101", "REST ZC"), // F5 : not found
+ FMT("1111_0110", "LD (RXB),A"), // F6 : exctsccr
+ FMT("1111_0111", "LD A,(RXB)"), // F7 : not found
+ FMT("1111_1000", "CMP A,(RXB)"), // F8 : exctsccr
+ FMT("1111_1001", "XOR A,(RXB)"), // F9 : exctsccr
+ FMT("1111_1010", "ADD A,CF"), // FA :
+ FMT("1111_1011", "SUB A,!CF"), // FB : not found
+ FMT("1111_1100", "TST A"), // FC :
+ FMT("1111_1101", "CLR A"), // FD :
+ FMT("1111_1110", "LD A,(IX0+A)"), // FE :
+ FMT("1111_1111", "RET"), // FF :
+ NULL
+};
+
+#define MAX_OPS (((sizeof(Formats) / sizeof(Formats[0])) - 1) / PTRS_PER_FORMAT)
+
+typedef struct opcode {
+ byte mask;
+ byte bits;
+ byte type;
+ byte pmask;
+ byte pdown;
+ const char *fmt;
+} AD8201Opcode;
+
+static AD8201Opcode Op[MAX_OPS+1];
+static int OpInizialized = 0;
+
+static void InitDasm8201(void)
+{
+ const char *p;
+ byte mask, bits;
+ int bit;
+ int i;
+ char chr , type;
+ int pmask , pdown;
+
+ for(i=0;(p=Formats[i*2])!=NULL;i++)
+ {
+ mask = 0;
+ bits = 0;
+ pmask = 0;
+ pdown = 0;
+ type = 0;
+ bit = 7;
+ while (*p && bit >= 0) {
+ chr = *p++;
+ switch (chr) {
+ case '1': bits |= 1<<bit;
+ case '0': mask |= 1<<bit; bit--; break;
+#if 0
+ case 'b':
+ type |= 0x80;
+#endif
+ case 'a':
+ pmask |= 1<<bit;
+ pdown = bit;
+ case 'x':
+ bit --;
+ break;
+ case '_':
+ continue;
+ default:
+ fatalerror("Invalid instruction encoding '%s %s'\n", Formats[i*2],Formats[i*2+1]);
+ }
+ }
+ if (bit != -1 ) {
+ fatalerror("not enough bits in encoding '%s %s' %d\n", Formats[i*2],Formats[i*2+1],bit);
+ }
+
+ Op[i].mask = mask;
+ Op[i].bits = bits;
+ Op[i].pmask = pmask;
+ Op[i].pdown = pdown;
+ Op[i].fmt = Formats[i*2+1];
+ Op[i].type = type;
+
+ /* 2 byte code ? */
+ while (isspace((UINT8)*p)) p++;
+ if( (*p) )
+ Op[i].type |= 0x10;
+ /* number of param */
+ if( (p=strchr(Op[i].fmt,'%'))!=NULL )
+ {
+ Op[i].type |= 0x01; /* single param */
+ if(strchr(p+1,'%') )
+ Op[i].type |= 0x02; /* double param */
+ }
+ }
+
+ OpInizialized = 1;
+}
+
+CPU_DISASSEMBLE( alpha8201 )
+{
+ offs_t dasmflags = 0;
+ int i;
+ int op;
+ int cnt = 1;
+ int code , disp;
+
+ if (!OpInizialized) InitDasm8201();
+
+ code = oprom[0];
+ op = -1; /* no matching opcode */
+ for ( i = 0; i < MAX_OPS; i++)
+ {
+ if( (code & Op[i].mask) == Op[i].bits )
+ {
+ if (op != -1)
+ {
+ fprintf(stderr, "Error: opcode %02X matches %d (%s) and %d (%s)\n",
+ code,i,Op[i].fmt,op,Op[op].fmt);
+ }
+ op = i;
+ }
+ }
+
+ if (op == -1)
+ {
+ sprintf(buffer,"db %2.2x",code);
+ return cnt;
+ }
+
+ if (Op[op].type & 0x10)
+ {
+ disp = opram[1];
+ cnt++;
+ }
+ else
+ {
+ disp = (code & Op[op].pmask) >> Op[op].pdown;
+ }
+
+ if (Op[op].type & 0x02)
+ sprintf(buffer, Op[op].fmt,disp,disp);
+ else if (Op[op].type & 0x01)
+ sprintf(buffer, Op[op].fmt,disp);
+ else
+ sprintf(buffer, "%s",Op[op].fmt);
+
+ switch (code)
+ {
+ case 0xcc:
+ case 0xcd:
+ case 0xce:
+ case 0xdf:
+ dasmflags = DASMFLAG_STEP_OVER;
+ break;
+
+ case 0xff:
+ dasmflags = DASMFLAG_STEP_OUT;
+ break;
+ }
+
+ return cnt | dasmflags | DASMFLAG_SUPPORTED;
+}
diff --git a/trunk/src/emu/cpu/alph8201/alph8201.c b/trunk/src/emu/cpu/alph8201/alph8201.c
new file mode 100644
index 00000000000..fb95ddf6c10
--- /dev/null
+++ b/trunk/src/emu/cpu/alph8201/alph8201.c
@@ -0,0 +1,1000 @@
+/****************************************************************************
+ Alpha8201 Emulator
+
+ Copyright Tatsuyuki Satoh
+ Originally written for the MAME project.
+
+
+The Alpha8201/830x isn't a real CPU. It is a Hitachi HD44801 4-bit MCU,
+programmed to interpret an external program using a custom instruction set.
+Alpha8301 has an expanded instruction set, backwards compatible with Alpha8201
+
+The internal ROM hasn't been read (yet), so here we provide a simulation of
+the behaviour.
+
+
+Game Year MCU
+------------------------ ---- ----
+Shougi 1982? 8201 (pcb)
+Shougi 2 1982? 8201 (pcb)
+Talbot 1982 8201?
+Champion Base Ball 1983 8201 (schematics)
+Exciting Soccer 1983 8302 (pcb)
+Champion Base Ball II 1983 8302 (pcb, unofficial schematics)
+Exciting Soccer II 1984 8303 (uses 8303+ opcodes)
+Equites 1984 8303 (post)
+Bull Fighter 1984 8303 (post)
+Splendor Blast 1985 8303 (post)
+Gekisou 1985 8304 (post)
+The Koukouyakyuh 1985 8304 (post)
+High Voltage 1985 8404?(post says 8404, but readme says 8304)
+
+alpha8201: "44801A75" -> HD44801 , ROM code = A75
+ALPHA8302: "44801B35" -> HD44801 , ROM code = B35
+ALPHA8303: "44801B42" -> HD44801 , ROM code = B42
+ALPHA8304: ?
+
+
+ Notes :
+ some unknown instruction are not emulated.
+
+ Because there was no information, opcode-syntax was created.
+
+ TODO:
+ verify with real chip or analyze more.
+ -A lot of 8301 opcode.
+ -memory address 000 specification
+ -memory address 001 bit 7-5 specification
+ -write value after HALT operation to ODD of vector memory.
+ -operation cycle(execution speed).
+
+****************************************************************************/
+
+/****************************************************************************
+
+-----------------------
+package / pin assign
+-----------------------
+ALPHA 8201 DIP 42
+
+pin HD44801 Alpha
+--- ------- -----
+1 : D3 WR
+2-4 : D4-D6 n.c.
+5-7 : D7-D9 GND in shougi , n.c. in champbas
+8-13 : D10-D15 n.c.
+14 : n.c. n.c.
+15 : RESET RESET
+16 : GND GND
+17 : OSC1 (champbas=384KHz)
+18 : OSC2 n.c.
+19 : !HLT Vcc
+20 : !TEST Vcc
+21 : Vcc Vcc
+22-25: R00-R03 DB4-DB7
+26-29: R10-R13 DB0-DB3
+30 : INT0 GO (input)
+31 : INT1 n.c.
+32-35: R20-R23 A4-A7
+36-39: R30-R33 A0-A3
+40-41: D0-D1 A8-A9
+42 : D2 /RD
+
+
+-----------------------
+Register Set
+-----------------------
+
+PC : 10bit Program Pointer
+ A lower 8bits are loaded from the immidate.
+ A higher 2bits are loaded from the MB register.
+
+MB : 2bit memory bank register, load PC[9:8] after branch
+ load high to higher 2bit of PC after branch.
+
+RB : 3bit register bank select register
+
+R0-R7 : internal? RAM register 8bitx8 (x8 bank)
+
+A : 8bit
+
+cpustate->IX0/1 : memory indirect 'read' access pointer
+
+cpustate->IX2 : memory indirect 'write' access pointer
+
+RXB : unknown , looks index register
+
+cpustate->LP0/1/2 : loop count register used by DJNZ operation
+
+cpustate->cf : carry flag
+cpustate->zf : zero flag
+
+-----------------------
+Memoy Space
+-----------------------
+
+000 : unknown ...
+001 : bit4..0 = pointer of current entry , bit7..6 = unknown
+002-003 : entrypoint1 vector
+004-005 : entrypoint2 vector
+006-007 : entrypoint3 vector
+008-009 : entrypoint4 vector
+00A-00B : entrypoint5 vector
+00C-00D : entrypoint6 vector
+00E-00F : entrypoint7 vector
+010-011 : entrypoint8 vector
+012-013 : entrypoint9 vector
+014-015 : entrypoint10 vector
+016-017 : entrypoint11 vector
+018-019 : entrypoint12 vector
+01A-01B : entrypoint13 vector
+01C-01D : entrypoint14 vector
+01E-01F : entrypoint15 vector
+020-0FF : bank 0, program / data memory
+100-1FF : bank 1, program / data memory
+200-2FF : bank 2, program / data memory
+300-3FF : bank 3, program / data memory
+
+The even address is the lower byte of the entry address.
+The odd-address of entry point is a MB and status.
+ Bit 0 and 1 are a memory bank.
+ Bit 2 is HALT.At the time of set, it doesn't execute entry address.
+ After EXIT operation, Bit2 is set.
+
+-----------------------
+Timming
+-----------------------
+
+****************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "alph8201.h"
+
+/* instruction cycle count */
+#define C1 16
+#define C2 32
+
+/* debug option */
+#define TRACE_PC 0
+#define SHOW_ENTRY_POINT 0
+#define SHOW_MESSAGE_CONSOLE 0
+#define BREAK_ON_UNKNOWN_OPCODE 0
+#define BREAK_ON_UNCERTAIN_OPCODE 0
+
+/* MAME is unnecessary */
+#define HANDLE_HALT_LINE 0
+
+#define M_RDMEM(A) cpustate->program->read_byte(A)
+#define M_WRMEM(A,V) cpustate->program->write_byte(A, V)
+#define M_RDOP(A) cpustate->direct->read_decrypted_byte(A)
+#define M_RDOP_ARG(A) cpustate->direct->read_raw_byte(A)
+
+typedef struct _alpha8201_state alpha8201_state;
+struct _alpha8201_state
+{
+ UINT8 RAM[8*8]; /* internal GP register 8 * 8bank */
+ unsigned PREVPC;
+ PAIR retptr; /* for 8301, return address of CALL */
+ PAIR pc; /* 2bit+8bit program counter */
+ UINT8 regPtr; /* RB register base */
+ UINT8 mb; /* MB memory bank reg. latch after Branch */
+ UINT8 cf; /* C flag */
+ UINT8 zf; /* Z flag */
+ UINT8 savec; /* for 8301, save flags */
+ UINT8 savez; /* for 8301, save flags */
+//
+ PAIR ix0; /* 8bit memory read index reg. */
+ PAIR ix1; /* 8bitmemory read index reg. */
+ PAIR ix2; /* 8bitmemory write index reg. */
+ UINT8 lp0; /* 8bit loop reg. */
+ UINT8 lp1; /* 8bit loop reg. */
+ UINT8 lp2; /* 8bit loop reg. */
+ UINT8 A; /* 8bit accumerator */
+ UINT8 B; /* 8bit regiser */
+//
+#if HANDLE_HALT_LINE
+ UINT8 halt; /* halt input line */
+#endif
+
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ int icount;
+ int inst_cycles;
+};
+
+/* The opcode table now is a combination of cycle counts and function pointers */
+typedef struct {
+ unsigned cycles;
+ void (*function) (alpha8201_state *cpustate);
+} s_opcode;
+
+
+#define PC pc.w.l
+#define PCL pc.b.l
+#define RD_REG(x) cpustate->RAM[(cpustate->regPtr<<3)+(x)]
+#define WR_REG(x,d) cpustate->RAM[(cpustate->regPtr<<3)+(x)]=(d)
+#define IX0 ix0.b.l
+#define IX1 ix1.b.l
+#define IX2 ix2.b.l
+#define BIX0 ix0.w.l
+#define BIX1 ix1.w.l
+#define BIX2 ix2.w.l
+#define LP0 lp0
+#define LP1 lp1
+#define LP2 lp2
+
+INLINE alpha8201_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == ALPHA8201 ||
+ device->type() == ALPHA8301);
+ return (alpha8201_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+/* Get next opcode argument and increment program counter */
+INLINE unsigned M_RDMEM_OPCODE (alpha8201_state *cpustate)
+{
+ unsigned retval;
+ retval=M_RDOP_ARG(cpustate->PC);
+ cpustate->PCL++;
+ return retval;
+}
+
+INLINE void M_ADD(alpha8201_state *cpustate, UINT8 dat)
+{
+ UINT16 temp = cpustate->A + dat;
+ cpustate->A = temp & 0xff;
+ cpustate->zf = (cpustate->A==0);
+ cpustate->cf = temp>>8;
+}
+
+INLINE void M_ADDB(alpha8201_state *cpustate, UINT8 dat)
+{
+ UINT16 temp = cpustate->B + dat;
+ cpustate->B = temp & 0xff;
+ cpustate->zf = (cpustate->B==0);
+ cpustate->cf = temp>>8;
+}
+
+INLINE void M_SUB(alpha8201_state *cpustate, UINT8 dat)
+{
+ cpustate->cf = (cpustate->A>=dat); // cpustate->cf is No Borrow
+ cpustate->A -= dat;
+ cpustate->zf = (cpustate->A==0);
+}
+
+INLINE void M_AND(alpha8201_state *cpustate, UINT8 dat)
+{
+ cpustate->A &= dat;
+ cpustate->zf = (cpustate->A==0);
+}
+
+INLINE void M_OR(alpha8201_state *cpustate, UINT8 dat)
+{
+ cpustate->A |= dat;
+ cpustate->zf = (cpustate->A==0);
+}
+
+INLINE void M_XOR(alpha8201_state *cpustate, UINT8 dat)
+{
+ cpustate->A ^= dat;
+ cpustate->zf = (cpustate->A==0);
+ cpustate->cf = 0;
+}
+
+INLINE void M_JMP(alpha8201_state *cpustate, UINT8 dat)
+{
+ cpustate->PCL = dat;
+ /* update pc page */
+ cpustate->pc.b.h = cpustate->ix0.b.h = cpustate->ix1.b.h = cpustate->ix2.b.h = cpustate->mb & 3;
+}
+
+INLINE void M_UNDEFINED(alpha8201_state *cpustate)
+{
+ logerror("alpha8201: cpustate->PC = %03x, Unimplemented opcode = %02x\n", cpustate->PC-1, M_RDMEM(cpustate->PC-1));
+#if SHOW_MESSAGE_CONSOLE
+ mame_printf_debug("alpha8201: cpustate->PC = %03x, Unimplemented opcode = %02x\n", cpustate->PC-1, M_RDMEM(cpustate->PC-1));
+#endif
+#if BREAK_ON_UNKNOWN_OPCODE
+ debugger_break(cpustate->device->machine());
+#endif
+}
+
+INLINE void M_UNDEFINED2(alpha8201_state *cpustate)
+{
+ UINT8 op = M_RDOP(cpustate->PC-1);
+ UINT8 imm = M_RDMEM_OPCODE(cpustate);
+ logerror("alpha8201: cpustate->PC = %03x, Unimplemented opcode = %02x,%02x\n", cpustate->PC-2, op,imm);
+#if SHOW_MESSAGE_CONSOLE
+ mame_printf_debug("alpha8201: cpustate->PC = %03x, Unimplemented opcode = %02x,%02x\n", cpustate->PC-2, op,imm);
+#endif
+#if BREAK_ON_UNKNOWN_OPCODE
+ debugger_break(cpustate->device->machine());
+#endif
+}
+
+static void undefined(alpha8201_state *cpustate) { M_UNDEFINED(cpustate); }
+static void undefined2(alpha8201_state *cpustate) { M_UNDEFINED2(cpustate); }
+
+static void nop(alpha8201_state *cpustate) { }
+static void rora(alpha8201_state *cpustate) { cpustate->cf = cpustate->A &1; cpustate->A = (cpustate->A>>1) | (cpustate->A<<7); }
+static void rola(alpha8201_state *cpustate) { cpustate->cf = (cpustate->A>>7)&1; cpustate->A = (cpustate->A<<1) | (cpustate->A>>7); }
+static void inc_b(alpha8201_state *cpustate) { M_ADDB(cpustate, 0x02); }
+static void dec_b(alpha8201_state *cpustate) { M_ADDB(cpustate, 0xfe); }
+static void inc_a(alpha8201_state *cpustate) { M_ADD(cpustate, 0x01); }
+static void dec_a(alpha8201_state *cpustate) { M_ADD(cpustate, 0xff); }
+static void cpl(alpha8201_state *cpustate) { cpustate->A ^= 0xff; };
+
+static void ld_a_ix0_0(alpha8201_state *cpustate) { cpustate->A = M_RDMEM(cpustate->BIX0+0); }
+static void ld_a_ix0_1(alpha8201_state *cpustate) { cpustate->A = M_RDMEM(cpustate->BIX0+1); }
+static void ld_a_ix0_2(alpha8201_state *cpustate) { cpustate->A = M_RDMEM(cpustate->BIX0+2); }
+static void ld_a_ix0_3(alpha8201_state *cpustate) { cpustate->A = M_RDMEM(cpustate->BIX0+3); }
+static void ld_a_ix0_4(alpha8201_state *cpustate) { cpustate->A = M_RDMEM(cpustate->BIX0+4); }
+static void ld_a_ix0_5(alpha8201_state *cpustate) { cpustate->A = M_RDMEM(cpustate->BIX0+5); }
+static void ld_a_ix0_6(alpha8201_state *cpustate) { cpustate->A = M_RDMEM(cpustate->BIX0+6); }
+static void ld_a_ix0_7(alpha8201_state *cpustate) { cpustate->A = M_RDMEM(cpustate->BIX0+7); }
+
+static void ld_a_ix1_0(alpha8201_state *cpustate) { cpustate->A = M_RDMEM(cpustate->BIX1+0); }
+static void ld_a_ix1_1(alpha8201_state *cpustate) { cpustate->A = M_RDMEM(cpustate->BIX1+1); }
+static void ld_a_ix1_2(alpha8201_state *cpustate) { cpustate->A = M_RDMEM(cpustate->BIX1+2); }
+static void ld_a_ix1_3(alpha8201_state *cpustate) { cpustate->A = M_RDMEM(cpustate->BIX1+3); }
+static void ld_a_ix1_4(alpha8201_state *cpustate) { cpustate->A = M_RDMEM(cpustate->BIX1+4); }
+static void ld_a_ix1_5(alpha8201_state *cpustate) { cpustate->A = M_RDMEM(cpustate->BIX1+5); }
+static void ld_a_ix1_6(alpha8201_state *cpustate) { cpustate->A = M_RDMEM(cpustate->BIX1+6); }
+static void ld_a_ix1_7(alpha8201_state *cpustate) { cpustate->A = M_RDMEM(cpustate->BIX1+7); }
+
+static void ld_ix2_0_a(alpha8201_state *cpustate) { M_WRMEM(cpustate->BIX2+0,cpustate->A); }
+static void ld_ix2_1_a(alpha8201_state *cpustate) { M_WRMEM(cpustate->BIX2+1,cpustate->A); }
+static void ld_ix2_2_a(alpha8201_state *cpustate) { M_WRMEM(cpustate->BIX2+2,cpustate->A); }
+static void ld_ix2_3_a(alpha8201_state *cpustate) { M_WRMEM(cpustate->BIX2+3,cpustate->A); }
+static void ld_ix2_4_a(alpha8201_state *cpustate) { M_WRMEM(cpustate->BIX2+4,cpustate->A); }
+static void ld_ix2_5_a(alpha8201_state *cpustate) { M_WRMEM(cpustate->BIX2+5,cpustate->A); }
+static void ld_ix2_6_a(alpha8201_state *cpustate) { M_WRMEM(cpustate->BIX2+6,cpustate->A); }
+static void ld_ix2_7_a(alpha8201_state *cpustate) { M_WRMEM(cpustate->BIX2+7,cpustate->A); }
+
+static void ld_ix0_0_b(alpha8201_state *cpustate) { cpustate->RAM[(cpustate->B>>1)&0x3f] = M_RDMEM(cpustate->BIX0+0); }
+static void ld_ix0_1_b(alpha8201_state *cpustate) { cpustate->RAM[(cpustate->B>>1)&0x3f] = M_RDMEM(cpustate->BIX0+1); }
+static void ld_ix0_2_b(alpha8201_state *cpustate) { cpustate->RAM[(cpustate->B>>1)&0x3f] = M_RDMEM(cpustate->BIX0+2); }
+static void ld_ix0_3_b(alpha8201_state *cpustate) { cpustate->RAM[(cpustate->B>>1)&0x3f] = M_RDMEM(cpustate->BIX0+3); }
+static void ld_ix0_4_b(alpha8201_state *cpustate) { cpustate->RAM[(cpustate->B>>1)&0x3f] = M_RDMEM(cpustate->BIX0+4); }
+static void ld_ix0_5_b(alpha8201_state *cpustate) { cpustate->RAM[(cpustate->B>>1)&0x3f] = M_RDMEM(cpustate->BIX0+5); }
+static void ld_ix0_6_b(alpha8201_state *cpustate) { cpustate->RAM[(cpustate->B>>1)&0x3f] = M_RDMEM(cpustate->BIX0+6); }
+static void ld_ix0_7_b(alpha8201_state *cpustate) { cpustate->RAM[(cpustate->B>>1)&0x3f] = M_RDMEM(cpustate->BIX0+7); }
+
+static void bit_r0_0(alpha8201_state *cpustate) { cpustate->zf = RD_REG(0)&(1<<0)?0:1; }
+static void bit_r0_1(alpha8201_state *cpustate) { cpustate->zf = RD_REG(0)&(1<<1)?0:1; }
+static void bit_r0_2(alpha8201_state *cpustate) { cpustate->zf = RD_REG(0)&(1<<2)?0:1; }
+static void bit_r0_3(alpha8201_state *cpustate) { cpustate->zf = RD_REG(0)&(1<<3)?0:1; }
+static void bit_r0_4(alpha8201_state *cpustate) { cpustate->zf = RD_REG(0)&(1<<4)?0:1; }
+static void bit_r0_5(alpha8201_state *cpustate) { cpustate->zf = RD_REG(0)&(1<<5)?0:1; }
+static void bit_r0_6(alpha8201_state *cpustate) { cpustate->zf = RD_REG(0)&(1<<6)?0:1; }
+static void bit_r0_7(alpha8201_state *cpustate) { cpustate->zf = RD_REG(0)&(1<<7)?0:1; }
+
+static void ld_a_n(alpha8201_state *cpustate) { cpustate->A = M_RDMEM_OPCODE(cpustate); }
+
+static void ld_a_r0(alpha8201_state *cpustate) { cpustate->A = RD_REG(0); cpustate->zf = (cpustate->A==0); }
+static void ld_a_r1(alpha8201_state *cpustate) { cpustate->A = RD_REG(1); cpustate->zf = (cpustate->A==0); }
+static void ld_a_r2(alpha8201_state *cpustate) { cpustate->A = RD_REG(2); cpustate->zf = (cpustate->A==0); }
+static void ld_a_r3(alpha8201_state *cpustate) { cpustate->A = RD_REG(3); cpustate->zf = (cpustate->A==0); }
+static void ld_a_r4(alpha8201_state *cpustate) { cpustate->A = RD_REG(4); cpustate->zf = (cpustate->A==0); }
+static void ld_a_r5(alpha8201_state *cpustate) { cpustate->A = RD_REG(5); cpustate->zf = (cpustate->A==0); }
+static void ld_a_r6(alpha8201_state *cpustate) { cpustate->A = RD_REG(6); cpustate->zf = (cpustate->A==0); }
+static void ld_a_r7(alpha8201_state *cpustate) { cpustate->A = RD_REG(7); cpustate->zf = (cpustate->A==0); }
+
+static void ld_r0_a(alpha8201_state *cpustate) { WR_REG(0,cpustate->A); }
+static void ld_r1_a(alpha8201_state *cpustate) { WR_REG(1,cpustate->A); }
+static void ld_r2_a(alpha8201_state *cpustate) { WR_REG(2,cpustate->A); }
+static void ld_r3_a(alpha8201_state *cpustate) { WR_REG(3,cpustate->A); }
+static void ld_r4_a(alpha8201_state *cpustate) { WR_REG(4,cpustate->A); }
+static void ld_r5_a(alpha8201_state *cpustate) { WR_REG(5,cpustate->A); }
+static void ld_r6_a(alpha8201_state *cpustate) { WR_REG(6,cpustate->A); }
+static void ld_r7_a(alpha8201_state *cpustate) { WR_REG(7,cpustate->A); }
+
+static void add_a_n(alpha8201_state *cpustate) { M_ADD(cpustate, M_RDMEM_OPCODE(cpustate)); }
+
+static void add_a_r0(alpha8201_state *cpustate) { M_ADD(cpustate, RD_REG(0)); }
+static void add_a_r1(alpha8201_state *cpustate) { M_ADD(cpustate, RD_REG(1)); }
+static void add_a_r2(alpha8201_state *cpustate) { M_ADD(cpustate, RD_REG(2)); }
+static void add_a_r3(alpha8201_state *cpustate) { M_ADD(cpustate, RD_REG(3)); }
+static void add_a_r4(alpha8201_state *cpustate) { M_ADD(cpustate, RD_REG(4)); }
+static void add_a_r5(alpha8201_state *cpustate) { M_ADD(cpustate, RD_REG(5)); }
+static void add_a_r6(alpha8201_state *cpustate) { M_ADD(cpustate, RD_REG(6)); }
+static void add_a_r7(alpha8201_state *cpustate) { M_ADD(cpustate, RD_REG(7)); }
+
+static void sub_a_n(alpha8201_state *cpustate) { M_SUB(cpustate, M_RDMEM_OPCODE(cpustate)); }
+
+static void sub_a_r0(alpha8201_state *cpustate) { M_SUB(cpustate, RD_REG(0)); }
+static void sub_a_r1(alpha8201_state *cpustate) { M_SUB(cpustate, RD_REG(1)); }
+static void sub_a_r2(alpha8201_state *cpustate) { M_SUB(cpustate, RD_REG(2)); }
+static void sub_a_r3(alpha8201_state *cpustate) { M_SUB(cpustate, RD_REG(3)); }
+static void sub_a_r4(alpha8201_state *cpustate) { M_SUB(cpustate, RD_REG(4)); }
+static void sub_a_r5(alpha8201_state *cpustate) { M_SUB(cpustate, RD_REG(5)); }
+static void sub_a_r6(alpha8201_state *cpustate) { M_SUB(cpustate, RD_REG(6)); }
+static void sub_a_r7(alpha8201_state *cpustate) { M_SUB(cpustate, RD_REG(7)); }
+
+static void and_a_n(alpha8201_state *cpustate) { M_AND(cpustate, M_RDMEM_OPCODE(cpustate)); }
+
+static void and_a_r0(alpha8201_state *cpustate) { M_AND(cpustate, RD_REG(0)); }
+static void and_a_r1(alpha8201_state *cpustate) { M_AND(cpustate, RD_REG(1)); }
+static void and_a_r2(alpha8201_state *cpustate) { M_AND(cpustate, RD_REG(2)); }
+static void and_a_r3(alpha8201_state *cpustate) { M_AND(cpustate, RD_REG(3)); }
+static void and_a_r4(alpha8201_state *cpustate) { M_AND(cpustate, RD_REG(4)); }
+static void and_a_r5(alpha8201_state *cpustate) { M_AND(cpustate, RD_REG(5)); }
+static void and_a_r6(alpha8201_state *cpustate) { M_AND(cpustate, RD_REG(6)); }
+static void and_a_r7(alpha8201_state *cpustate) { M_AND(cpustate, RD_REG(7)); }
+
+static void or_a_n(alpha8201_state *cpustate) { M_OR(cpustate, M_RDMEM_OPCODE(cpustate)); }
+
+static void or_a_r0(alpha8201_state *cpustate) { M_OR(cpustate, RD_REG(0)); }
+static void or_a_r1(alpha8201_state *cpustate) { M_OR(cpustate, RD_REG(1)); }
+static void or_a_r2(alpha8201_state *cpustate) { M_OR(cpustate, RD_REG(2)); }
+static void or_a_r3(alpha8201_state *cpustate) { M_OR(cpustate, RD_REG(3)); }
+static void or_a_r4(alpha8201_state *cpustate) { M_OR(cpustate, RD_REG(4)); }
+static void or_a_r5(alpha8201_state *cpustate) { M_OR(cpustate, RD_REG(5)); }
+static void or_a_r6(alpha8201_state *cpustate) { M_OR(cpustate, RD_REG(6)); }
+static void or_a_r7(alpha8201_state *cpustate) { M_OR(cpustate, RD_REG(7)); }
+
+static void add_ix0_0(alpha8201_state *cpustate) { }
+static void add_ix0_1(alpha8201_state *cpustate) { cpustate->IX0 += 1; }
+static void add_ix0_2(alpha8201_state *cpustate) { cpustate->IX0 += 2; }
+static void add_ix0_3(alpha8201_state *cpustate) { cpustate->IX0 += 3; }
+static void add_ix0_4(alpha8201_state *cpustate) { cpustate->IX0 += 4; }
+static void add_ix0_5(alpha8201_state *cpustate) { cpustate->IX0 += 5; }
+static void add_ix0_6(alpha8201_state *cpustate) { cpustate->IX0 += 6; }
+static void add_ix0_7(alpha8201_state *cpustate) { cpustate->IX0 += 7; }
+static void add_ix0_8(alpha8201_state *cpustate) { cpustate->IX0 += 8; }
+static void add_ix0_9(alpha8201_state *cpustate) { cpustate->IX0 += 9; }
+static void add_ix0_a(alpha8201_state *cpustate) { cpustate->IX0 += 10; }
+static void add_ix0_b(alpha8201_state *cpustate) { cpustate->IX0 += 11; }
+static void add_ix0_c(alpha8201_state *cpustate) { cpustate->IX0 += 12; }
+static void add_ix0_d(alpha8201_state *cpustate) { cpustate->IX0 += 13; }
+static void add_ix0_e(alpha8201_state *cpustate) { cpustate->IX0 += 14; }
+static void add_ix0_f(alpha8201_state *cpustate) { cpustate->IX0 += 15; }
+
+static void add_ix1_0(alpha8201_state *cpustate) { }
+static void add_ix1_1(alpha8201_state *cpustate) { cpustate->IX1 += 1; }
+static void add_ix1_2(alpha8201_state *cpustate) { cpustate->IX1 += 2; }
+static void add_ix1_3(alpha8201_state *cpustate) { cpustate->IX1 += 3; }
+static void add_ix1_4(alpha8201_state *cpustate) { cpustate->IX1 += 4; }
+static void add_ix1_5(alpha8201_state *cpustate) { cpustate->IX1 += 5; }
+static void add_ix1_6(alpha8201_state *cpustate) { cpustate->IX1 += 6; }
+static void add_ix1_7(alpha8201_state *cpustate) { cpustate->IX1 += 7; }
+static void add_ix1_8(alpha8201_state *cpustate) { cpustate->IX1 += 8; }
+static void add_ix1_9(alpha8201_state *cpustate) { cpustate->IX1 += 9; }
+static void add_ix1_a(alpha8201_state *cpustate) { cpustate->IX1 += 10; }
+static void add_ix1_b(alpha8201_state *cpustate) { cpustate->IX1 += 11; }
+static void add_ix1_c(alpha8201_state *cpustate) { cpustate->IX1 += 12; }
+static void add_ix1_d(alpha8201_state *cpustate) { cpustate->IX1 += 13; }
+static void add_ix1_e(alpha8201_state *cpustate) { cpustate->IX1 += 14; }
+static void add_ix1_f(alpha8201_state *cpustate) { cpustate->IX1 += 15; }
+
+static void add_ix2_0(alpha8201_state *cpustate) { }
+static void add_ix2_1(alpha8201_state *cpustate) { cpustate->IX2 += 1; }
+static void add_ix2_2(alpha8201_state *cpustate) { cpustate->IX2 += 2; }
+static void add_ix2_3(alpha8201_state *cpustate) { cpustate->IX2 += 3; }
+static void add_ix2_4(alpha8201_state *cpustate) { cpustate->IX2 += 4; }
+static void add_ix2_5(alpha8201_state *cpustate) { cpustate->IX2 += 5; }
+static void add_ix2_6(alpha8201_state *cpustate) { cpustate->IX2 += 6; }
+static void add_ix2_7(alpha8201_state *cpustate) { cpustate->IX2 += 7; }
+static void add_ix2_8(alpha8201_state *cpustate) { cpustate->IX2 += 8; }
+static void add_ix2_9(alpha8201_state *cpustate) { cpustate->IX2 += 9; }
+static void add_ix2_a(alpha8201_state *cpustate) { cpustate->IX2 += 10; }
+static void add_ix2_b(alpha8201_state *cpustate) { cpustate->IX2 += 11; }
+static void add_ix2_c(alpha8201_state *cpustate) { cpustate->IX2 += 12; }
+static void add_ix2_d(alpha8201_state *cpustate) { cpustate->IX2 += 13; }
+static void add_ix2_e(alpha8201_state *cpustate) { cpustate->IX2 += 14; }
+static void add_ix2_f(alpha8201_state *cpustate) { cpustate->IX2 += 15; }
+
+static void ld_base_0(alpha8201_state *cpustate) { cpustate->regPtr = 0; }
+static void ld_base_1(alpha8201_state *cpustate) { cpustate->regPtr = 1; }
+static void ld_base_2(alpha8201_state *cpustate) { cpustate->regPtr = 2; }
+static void ld_base_3(alpha8201_state *cpustate) { cpustate->regPtr = 3; }
+static void ld_base_4(alpha8201_state *cpustate) { cpustate->regPtr = 4; }
+static void ld_base_5(alpha8201_state *cpustate) { cpustate->regPtr = 5; }
+static void ld_base_6(alpha8201_state *cpustate) { cpustate->regPtr = 6; }
+static void ld_base_7(alpha8201_state *cpustate) { cpustate->regPtr = 7; }
+
+static void ld_bank_0(alpha8201_state *cpustate) { cpustate->mb = 0; }
+static void ld_bank_1(alpha8201_state *cpustate) { cpustate->mb = 1; }
+static void ld_bank_2(alpha8201_state *cpustate) { cpustate->mb = 2; }
+static void ld_bank_3(alpha8201_state *cpustate) { cpustate->mb = 3; }
+
+static void stop(alpha8201_state *cpustate)
+{
+ UINT8 pcptr = M_RDMEM(0x001) & 0x1f;
+ M_WRMEM(pcptr,(M_RDMEM(pcptr)&0xf)+0x08); /* mark entry point ODD to HALT */
+ cpustate->mb |= 0x08; /* mark internal HALT state */
+}
+
+static void ld_ix0_n(alpha8201_state *cpustate) { cpustate->IX0 = M_RDMEM_OPCODE(cpustate); }
+static void ld_ix1_n(alpha8201_state *cpustate) { cpustate->IX1 = M_RDMEM_OPCODE(cpustate); }
+static void ld_ix2_n(alpha8201_state *cpustate) { cpustate->IX2 = M_RDMEM_OPCODE(cpustate); }
+static void ld_lp0_n(alpha8201_state *cpustate) { cpustate->LP0 = M_RDMEM_OPCODE(cpustate); }
+static void ld_lp1_n(alpha8201_state *cpustate) { cpustate->LP1 = M_RDMEM_OPCODE(cpustate); }
+static void ld_lp2_n(alpha8201_state *cpustate) { cpustate->LP2 = M_RDMEM_OPCODE(cpustate); }
+static void ld_b_n(alpha8201_state *cpustate) { cpustate->B = M_RDMEM_OPCODE(cpustate); }
+
+static void djnz_lp0(alpha8201_state *cpustate) { UINT8 i=M_RDMEM_OPCODE(cpustate); cpustate->LP0--; if (cpustate->LP0 != 0) M_JMP(cpustate, i); }
+static void djnz_lp1(alpha8201_state *cpustate) { UINT8 i=M_RDMEM_OPCODE(cpustate); cpustate->LP1--; if (cpustate->LP1 != 0) M_JMP(cpustate, i); }
+static void djnz_lp2(alpha8201_state *cpustate) { UINT8 i=M_RDMEM_OPCODE(cpustate); cpustate->LP2--; if (cpustate->LP2 != 0) M_JMP(cpustate, i); }
+static void jnz(alpha8201_state *cpustate) { UINT8 i=M_RDMEM_OPCODE(cpustate); if (!cpustate->zf) M_JMP(cpustate, i); }
+static void jnc(alpha8201_state *cpustate) { UINT8 i=M_RDMEM_OPCODE(cpustate); if (!cpustate->cf) M_JMP(cpustate, i);}
+static void jz(alpha8201_state *cpustate) { UINT8 i=M_RDMEM_OPCODE(cpustate); if ( cpustate->zf) M_JMP(cpustate, i); }
+static void jc(alpha8201_state *cpustate) { UINT8 i=M_RDMEM_OPCODE(cpustate); if ( cpustate->cf) M_JMP(cpustate, i);}
+static void jmp(alpha8201_state *cpustate) { M_JMP(cpustate, M_RDMEM_OPCODE(cpustate) ); }
+
+static const s_opcode opcode_8201[256]=
+{
+ {C1, nop },{C1,rora },{C1, rola },{C1,inc_b },{C1,dec_b },{C1, inc_a },{C1, dec_a },{C1, cpl },
+ {C2,ld_a_ix0_0 },{C2,ld_a_ix0_1},{C2, ld_a_ix0_2},{C2,ld_a_ix0_3},{C2,ld_a_ix0_4},{C2,ld_a_ix0_5},{C2,ld_a_ix0_6},{C2,ld_a_ix0_7},
+ {C2,ld_a_ix1_0 },{C2,ld_a_ix1_1},{C2, ld_a_ix1_2},{C2,ld_a_ix1_3},{C2,ld_a_ix1_4},{C2,ld_a_ix1_5},{C2,ld_a_ix1_6},{C2,ld_a_ix1_7},
+ {C2,ld_ix2_0_a },{C2,ld_ix2_1_a},{C2, ld_ix2_2_a},{C2,ld_ix2_3_a},{C2,ld_ix2_4_a},{C2,ld_ix2_5_a},{C2,ld_ix2_6_a},{C2,ld_ix2_7_a},
+/* 20 */
+ {C2,ld_ix0_0_b },{C2,ld_ix0_1_b},{C2, ld_ix0_2_b},{C2,ld_ix0_3_b},{C2,ld_ix0_4_b},{C2,ld_ix0_5_b},{C2,ld_ix0_6_b},{C2,ld_ix0_7_b},
+ {C2,undefined },{C2,undefined },{C2, undefined },{C2,undefined },{C2,undefined },{C2,undefined },{C2,undefined },{C2,undefined },
+ {C2,undefined },{C2,undefined },{C2, undefined },{C2,undefined },{C2,undefined },{C2,undefined },{C2,undefined },{C2,undefined },
+ {C2,bit_r0_0 },{C2,bit_r0_1 },{C2, bit_r0_2 },{C2, bit_r0_3 },{C2, bit_r0_4 },{C2, bit_r0_5 },{C2, bit_r0_6 },{C2, bit_r0_7 },
+/* 40 : 8201 */
+ {C2, ld_a_r0 },{C2, ld_r0_a },{C2, ld_a_r1 },{C2, ld_r1_a },{C2, ld_a_r2 },{C2, ld_r2_a },{C2, ld_a_r3 },{C2, ld_r3_a },
+ {C2, ld_a_r4 },{C2, ld_r4_a },{C2, ld_a_r5 },{C2, ld_r5_a },{C2, ld_a_r6 },{C2, ld_r6_a },{C2, ld_a_r7 },{C2, ld_r7_a },
+ {C1, add_a_r0 },{C1, sub_a_r0 },{C1, add_a_r1 },{C1, sub_a_r1 },{C1, add_a_r2 },{C1, sub_a_r2 },{C1, add_a_r3 },{C1, sub_a_r3 },
+ {C1, add_a_r4 },{C1, sub_a_r4 },{C1, add_a_r5 },{C1, sub_a_r5 },{C1, add_a_r6 },{C1, sub_a_r6 },{C1, add_a_r7 },{C1, sub_a_r7 },
+ {C1, and_a_r0 },{C1, or_a_r0 },{C1, and_a_r1 },{C1, or_a_r1 },{C1, and_a_r2 },{C1, or_a_r2 },{C1, and_a_r3 },{C1, or_a_r3 },
+ {C1, and_a_r4 },{C1, or_a_r4 },{C1, and_a_r5 },{C1, or_a_r5 },{C1, and_a_r6 },{C1, or_a_r6 },{C1, and_a_r7 },{C1, or_a_r7 },
+ {C1, add_ix0_0 },{C1, add_ix0_1},{C1, add_ix0_2},{C1, add_ix0_3},{C1, add_ix0_4},{C1, add_ix0_5},{C1, add_ix0_6},{C1, add_ix0_7},
+ {C1, add_ix0_8 },{C1, add_ix0_9},{C1, add_ix0_a},{C1, add_ix0_b},{C1, add_ix0_c},{C1, add_ix0_d},{C1, add_ix0_e},{C1, add_ix0_f},
+/* 80 : 8201 */
+ {C1, add_ix1_0 },{C1, add_ix1_1},{C1, add_ix1_2},{C1, add_ix1_3},{C1, add_ix1_4},{C1, add_ix1_5},{C1, add_ix1_6},{C1, add_ix1_7},
+ {C1, add_ix1_8 },{C1, add_ix1_9},{C1, add_ix1_a},{C1, add_ix1_b},{C1, add_ix1_c},{C1, add_ix1_d},{C1, add_ix1_e},{C1, add_ix1_f},
+ {C1, add_ix2_0 },{C1, add_ix2_1},{C1, add_ix2_2},{C1, add_ix2_3},{C1, add_ix2_4},{C1, add_ix2_5},{C1, add_ix2_6},{C1, add_ix2_7},
+ {C1, add_ix2_8 },{C1, add_ix2_9},{C1, add_ix2_a},{C1, add_ix2_b},{C1, add_ix2_c},{C1, add_ix2_d},{C1, add_ix2_e},{C1, add_ix2_f},
+ {C1, ld_base_0 },{C1, ld_base_1},{C1, ld_base_2},{C1, ld_base_3},{C1, ld_base_4},{C1, ld_base_5},{C1, ld_base_6},{C1, ld_base_7},
+ {C1, undefined },{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},
+ {C1, ld_bank_0 },{C1, ld_bank_1},{C1, ld_bank_2},{C1, ld_bank_3},{C2, stop },{C1, undefined},{C1, undefined},{C1, undefined},
+ {C1, undefined },{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},
+/* c0 : 8201 */
+ {C2, ld_ix0_n },{C2, ld_ix1_n },{C2, ld_ix2_n },{C2, ld_a_n },{C2, ld_lp0_n },{C2, ld_lp1_n },{C2, ld_lp2_n },{C2, ld_b_n },
+ {C2, add_a_n },{C2, sub_a_n },{C2, and_a_n },{C2, or_a_n },{C2, djnz_lp0 },{C2, djnz_lp1 },{C2, djnz_lp2 },{C2, jnz },
+ {C2, jnc },{C2, jz },{C2, jmp },{C2,undefined2},{C2,undefined2},{C2,undefined2},{C2,undefined2},{C2, undefined2},
+ {C2, undefined2 },{C2,undefined2},{C2,undefined2},{C2,undefined2},{C2,undefined2},{C2,undefined2},{C2,undefined2},{C2, undefined2},
+/* E0 : 8201*/
+ {C1, undefined },{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},
+ {C1, undefined },{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},
+ {C1, undefined },{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},
+ {C1, undefined },{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined }
+};
+
+
+/* ALPHA 8301 : added instruction */
+static void exg_a_ix0(alpha8201_state *cpustate) { UINT8 t=cpustate->A; cpustate->A = cpustate->IX0; cpustate->IX0 = t; }
+static void exg_a_ix1(alpha8201_state *cpustate) { UINT8 t=cpustate->A; cpustate->A = cpustate->IX1; cpustate->IX1 = t; }
+static void exg_a_ix2(alpha8201_state *cpustate) { UINT8 t=cpustate->A; cpustate->A = cpustate->IX2; cpustate->IX2 = t; }
+static void exg_a_lp0(alpha8201_state *cpustate) { UINT8 t=cpustate->A; cpustate->A = cpustate->LP0; cpustate->LP0 = t; }
+static void exg_a_lp1(alpha8201_state *cpustate) { UINT8 t=cpustate->A; cpustate->A = cpustate->LP1; cpustate->LP1 = t; }
+static void exg_a_lp2(alpha8201_state *cpustate) { UINT8 t=cpustate->A; cpustate->A = cpustate->LP2; cpustate->LP2 = t; }
+static void exg_a_b(alpha8201_state *cpustate) { UINT8 t=cpustate->A; cpustate->A = cpustate->B; cpustate->B = t; }
+static void exg_a_rb(alpha8201_state *cpustate) { UINT8 t=cpustate->A; cpustate->A = cpustate->regPtr; cpustate->regPtr = t; }
+
+static void ld_ix0_a(alpha8201_state *cpustate) { cpustate->IX0 = cpustate->A; }
+static void ld_ix1_a(alpha8201_state *cpustate) { cpustate->IX1 = cpustate->A; }
+static void ld_ix2_a(alpha8201_state *cpustate) { cpustate->IX2 = cpustate->A; }
+static void ld_lp0_a(alpha8201_state *cpustate) { cpustate->LP0 = cpustate->A; }
+static void ld_lp1_a(alpha8201_state *cpustate) { cpustate->LP1 = cpustate->A; }
+static void ld_lp2_a(alpha8201_state *cpustate) { cpustate->LP2 = cpustate->A; }
+static void ld_b_a(alpha8201_state *cpustate) { cpustate->B = cpustate->A; }
+static void ld_rb_a(alpha8201_state *cpustate) { cpustate->regPtr = cpustate->A; }
+
+static void exg_ix0_ix1(alpha8201_state *cpustate) { UINT8 t=cpustate->IX1; cpustate->IX1 = cpustate->IX0; cpustate->IX0 = t; }
+static void exg_ix0_ix2(alpha8201_state *cpustate) { UINT8 t=cpustate->IX2; cpustate->IX2 = cpustate->IX0; cpustate->IX0 = t; }
+
+static void op_d4(alpha8201_state *cpustate) { cpustate->A = M_RDMEM( ((cpustate->RAM[(7<<3)+7] & 3) << 8) | M_RDMEM_OPCODE(cpustate) ); }
+static void op_d5(alpha8201_state *cpustate) { M_WRMEM( ((cpustate->RAM[(7<<3)+7] & 3) << 8) | M_RDMEM_OPCODE(cpustate), cpustate->A ); }
+static void op_d6(alpha8201_state *cpustate) { cpustate->LP0 = M_RDMEM( ((cpustate->RAM[(7<<3)+7] & 3) << 8) | M_RDMEM_OPCODE(cpustate) ); }
+static void op_d7(alpha8201_state *cpustate) { M_WRMEM( ((cpustate->RAM[(7<<3)+7] & 3) << 8) | M_RDMEM_OPCODE(cpustate), cpustate->LP0 ); }
+
+static void ld_a_abs(alpha8201_state *cpustate) { cpustate->A = M_RDMEM( ((cpustate->mb & 3) << 8) | M_RDMEM_OPCODE(cpustate) ); }
+static void ld_abs_a(alpha8201_state *cpustate) { M_WRMEM( ((cpustate->mb & 3) << 8) | M_RDMEM_OPCODE(cpustate), cpustate->A ); }
+
+static void ld_a_r(alpha8201_state *cpustate) { cpustate->A = cpustate->RAM[(M_RDMEM_OPCODE(cpustate)>>1)&0x3f]; }
+static void ld_r_a(alpha8201_state *cpustate) { cpustate->RAM[(M_RDMEM_OPCODE(cpustate)>>1)&0x3f] = cpustate->A; }
+static void op_rep_ld_ix2_b(alpha8201_state *cpustate) { do { M_WRMEM(cpustate->BIX2, cpustate->RAM[(cpustate->B>>1)&0x3f]); cpustate->IX2++; cpustate->B+=2; cpustate->LP0--; } while (cpustate->LP0 != 0); }
+static void op_rep_ld_b_ix0(alpha8201_state *cpustate) { do { cpustate->RAM[(cpustate->B>>1)&0x3f] = M_RDMEM(cpustate->BIX0); cpustate->IX0++; cpustate->B+=2; cpustate->LP0--; } while (cpustate->LP0 != 0); }
+static void ld_rxb_a(alpha8201_state *cpustate) { cpustate->RAM[(cpustate->B>>1)&0x3f] = cpustate->A; }
+static void ld_a_rxb(alpha8201_state *cpustate) { cpustate->A = cpustate->RAM[(cpustate->B>>1)&0x3f]; }
+static void cmp_a_rxb(alpha8201_state *cpustate) { UINT8 i=cpustate->RAM[(cpustate->B>>1)&0x3f]; cpustate->zf = (cpustate->A==i); cpustate->cf = (cpustate->A>=i); }
+static void xor_a_rxb(alpha8201_state *cpustate) { M_XOR(cpustate, cpustate->RAM[(cpustate->B>>1)&0x3f] ); }
+
+static void add_a_cf(alpha8201_state *cpustate) { if (cpustate->cf) inc_a(cpustate); }
+static void sub_a_cf(alpha8201_state *cpustate) { if (cpustate->cf) dec_a(cpustate); }
+static void tst_a(alpha8201_state *cpustate) { cpustate->zf = (cpustate->A==0); }
+static void clr_a(alpha8201_state *cpustate) { cpustate->A = 0; cpustate->zf = (cpustate->A==0); }
+static void cmp_a_n(alpha8201_state *cpustate) { UINT8 i=M_RDMEM_OPCODE(cpustate); cpustate->zf = (cpustate->A==i); cpustate->cf = (cpustate->A>=i); }
+static void xor_a_n(alpha8201_state *cpustate) { M_XOR(cpustate, M_RDMEM_OPCODE(cpustate) ); }
+static void call(alpha8201_state *cpustate) { UINT8 i=M_RDMEM_OPCODE(cpustate); cpustate->retptr.w.l = cpustate->PC; M_JMP(cpustate, i); };
+static void ld_a_ix0_a(alpha8201_state *cpustate) { cpustate->A = M_RDMEM(cpustate->BIX0+cpustate->A); }
+static void ret(alpha8201_state *cpustate) { cpustate->mb = cpustate->retptr.b.h; M_JMP(cpustate, cpustate->retptr.b.l ); };
+static void save_zc(alpha8201_state *cpustate) { cpustate->savez = cpustate->zf; cpustate->savec = cpustate->cf; };
+static void rest_zc(alpha8201_state *cpustate) { cpustate->zf = cpustate->savez; cpustate->cf = cpustate->savec; };
+
+static const s_opcode opcode_8301[256]=
+{
+ {C1, nop },{C1,rora },{C1, rola },{C1,inc_b },{C1,dec_b },{C1, inc_a },{C1, dec_a },{C1, cpl },
+ {C2,ld_a_ix0_0 },{C2,ld_a_ix0_1},{C2, ld_a_ix0_2},{C2,ld_a_ix0_3},{C2,ld_a_ix0_4},{C2,ld_a_ix0_5},{C2,ld_a_ix0_6},{C2,ld_a_ix0_7},
+ {C2,ld_a_ix1_0 },{C2,ld_a_ix1_1},{C2, ld_a_ix1_2},{C2,ld_a_ix1_3},{C2,ld_a_ix1_4},{C2,ld_a_ix1_5},{C2,ld_a_ix1_6},{C2,ld_a_ix1_7},
+ {C2,ld_ix2_0_a },{C2,ld_ix2_1_a},{C2, ld_ix2_2_a},{C2,ld_ix2_3_a},{C2,ld_ix2_4_a},{C2,ld_ix2_5_a},{C2,ld_ix2_6_a},{C2,ld_ix2_7_a},
+/* 20 : 8301 */
+ {C2,ld_ix0_0_b },{C2,ld_ix0_1_b},{C2, ld_ix0_2_b},{C2,ld_ix0_3_b},{C2,ld_ix0_4_b},{C2,ld_ix0_5_b},{C2,ld_ix0_6_b},{C2,ld_ix0_7_b},
+ {C2,undefined },{C2,undefined },{C2, undefined },{C2,undefined },{C2,undefined },{C2,undefined },{C2,undefined },{C2,undefined },
+ {C2,undefined },{C2,undefined },{C2, undefined },{C2,undefined },{C2,undefined },{C2,undefined },{C2,undefined },{C2,undefined },
+ {C2,bit_r0_0 },{C2,bit_r0_1 },{C2, bit_r0_2 },{C2, bit_r0_3 },{C2, bit_r0_4 },{C2, bit_r0_5 },{C2, bit_r0_6 },{C2, bit_r0_7 },
+/* 40 : 8301 */
+ {C2, ld_a_r0 },{C2, ld_r0_a },{C2, ld_a_r1 },{C2, ld_r1_a },{C2, ld_a_r2 },{C2, ld_r2_a },{C2, ld_a_r3 },{C2, ld_r3_a },
+ {C2, ld_a_r4 },{C2, ld_r4_a },{C2, ld_a_r5 },{C2, ld_r5_a },{C2, ld_a_r6 },{C2, ld_r6_a },{C2, ld_a_r7 },{C2, ld_r7_a },
+ {C1, add_a_r0 },{C1, sub_a_r0 },{C1, add_a_r1 },{C1, sub_a_r1 },{C1, add_a_r2 },{C1, sub_a_r2 },{C1, add_a_r3 },{C1, sub_a_r3 },
+ {C1, add_a_r4 },{C1, sub_a_r4 },{C1, add_a_r5 },{C1, sub_a_r5 },{C1, add_a_r6 },{C1, sub_a_r6 },{C1, add_a_r7 },{C1, sub_a_r7 },
+/* 60 : 8301 */
+ {C1, and_a_r0 },{C1, or_a_r0 },{C1, and_a_r1 },{C1, or_a_r1 },{C1, and_a_r2 },{C1, or_a_r2 },{C1, and_a_r3 },{C1, or_a_r3 },
+ {C1, and_a_r4 },{C1, or_a_r4 },{C1, and_a_r5 },{C1, or_a_r5 },{C1, and_a_r6 },{C1, or_a_r6 },{C1, and_a_r7 },{C1, or_a_r7 },
+ {C1, add_ix0_0 },{C1, add_ix0_1},{C1, add_ix0_2},{C1, add_ix0_3},{C1, add_ix0_4},{C1, add_ix0_5},{C1, add_ix0_6},{C1, add_ix0_7},
+ {C1, add_ix0_8 },{C1, add_ix0_9},{C1, add_ix0_a},{C1, add_ix0_b},{C1, add_ix0_c},{C1, add_ix0_d},{C1, add_ix0_e},{C1, add_ix0_f},
+/* 80 : 8301 */
+ {C1, add_ix1_0 },{C1, add_ix1_1},{C1, add_ix1_2},{C1, add_ix1_3},{C1, add_ix1_4},{C1, add_ix1_5},{C1, add_ix1_6},{C1, add_ix1_7},
+ {C1, add_ix1_8 },{C1, add_ix1_9},{C1, add_ix1_a},{C1, add_ix1_b},{C1, add_ix1_c},{C1, add_ix1_d},{C1, add_ix1_e},{C1, add_ix1_f},
+ {C1, add_ix2_0 },{C1, add_ix2_1},{C1, add_ix2_2},{C1, add_ix2_3},{C1, add_ix2_4},{C1, add_ix2_5},{C1, add_ix2_6},{C1, add_ix2_7},
+ {C1, add_ix2_8 },{C1, add_ix2_9},{C1, add_ix2_a},{C1, add_ix2_b},{C1, add_ix2_c},{C1, add_ix2_d},{C1, add_ix2_e},{C1, add_ix2_f},
+/* A0 : 8301 */
+ {C1, ld_base_0 },{C1, ld_base_1},{C1, ld_base_2},{C1, ld_base_3},{C1, ld_base_4},{C1, ld_base_5},{C1, ld_base_6},{C1, ld_base_7},
+ {C1, undefined },{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},
+ {C1, ld_bank_0 },{C1, ld_bank_1},{C1, ld_bank_2},{C1, ld_bank_3},{C2, stop },{C1, undefined},{C1, undefined},{C1, undefined},
+ {C1, undefined },{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},
+/* c0 : 8301 */
+ {C2, ld_ix0_n },{C2, ld_ix1_n},{C2, ld_ix2_n },{C2, ld_a_n },{C2, ld_lp0_n },{C2, ld_lp1_n },{C2, ld_lp2_n },{C2, ld_b_n },
+ {C2, add_a_n },{C2, sub_a_n },{C2, and_a_n },{C2, or_a_n },{C2, djnz_lp0 },{C2, djnz_lp1 },{C2, djnz_lp2 },{C2, jnz },
+ {C2, jnc },{C2, jz },{C2, jmp },{C2,undefined2},{C2, op_d4 },{C2, op_d5 },{C2, op_d6 },{C2, op_d7 },
+ {C2, ld_a_abs },{C2, ld_abs_a},{C2,cmp_a_n },{C2,xor_a_n },{C2, ld_a_r },{C2, ld_r_a },{C2, jc },{C2, call},
+/* E0 : 8301 */
+ {C1, exg_a_ix0 },{C1, exg_a_ix1},{C1, exg_a_ix2},{C1, exg_a_lp1},{C1, exg_a_lp2},{C1, exg_a_b },{C1, exg_a_lp0},{C1, exg_a_rb },
+ {C1, ld_ix0_a },{C1, ld_ix1_a },{C1, ld_ix2_a },{C1, ld_lp1_a },{C1, ld_lp2_a },{C1, ld_b_a },{C1, ld_lp0_a },{C1, ld_rb_a },
+ {C1,exg_ix0_ix1},{C1,exg_ix0_ix2},{C1,op_rep_ld_ix2_b},{C1, op_rep_ld_b_ix0},{C1, save_zc},{C1, rest_zc},{C1, ld_rxb_a },{C1, ld_a_rxb },
+ {C1, cmp_a_rxb },{C1, xor_a_rxb},{C1, add_a_cf },{C1, sub_a_cf },{C1, tst_a },{C1, clr_a },{C1, ld_a_ix0_a},{C1, ret }
+};
+
+/****************************************************************************
+ * Initialize emulation
+ ****************************************************************************/
+static CPU_INIT( alpha8201 )
+{
+ alpha8201_state *cpustate = get_safe_token(device);
+
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+
+ device->save_item(NAME(cpustate->RAM));
+ device->save_item(NAME(cpustate->PREVPC));
+ device->save_item(NAME(cpustate->PC));
+ device->save_item(NAME(cpustate->regPtr));
+ device->save_item(NAME(cpustate->zf));
+ device->save_item(NAME(cpustate->cf));
+ device->save_item(NAME(cpustate->mb));
+#if HANDLE_HALT_LINE
+ device->save_item(NAME(cpustate->halt));
+#endif
+ device->save_item(NAME(cpustate->IX0));
+ device->save_item(NAME(cpustate->IX1));
+ device->save_item(NAME(cpustate->IX2));
+ device->save_item(NAME(cpustate->LP0));
+ device->save_item(NAME(cpustate->LP1));
+ device->save_item(NAME(cpustate->LP2));
+ device->save_item(NAME(cpustate->A));
+ device->save_item(NAME(cpustate->B));
+ device->save_item(NAME(cpustate->retptr));
+ device->save_item(NAME(cpustate->savec));
+ device->save_item(NAME(cpustate->savez));
+}
+/****************************************************************************
+ * Reset registers to their initial values
+ ****************************************************************************/
+static CPU_RESET( alpha8201 )
+{
+ alpha8201_state *cpustate = get_safe_token(device);
+ cpustate->PC = 0;
+ cpustate->regPtr = 0;
+ cpustate->zf = 0;
+ cpustate->cf = 0;
+ cpustate->mb = 0;
+ cpustate->BIX0 = 0;
+ cpustate->BIX1 = 0;
+ cpustate->BIX2 = 0;
+ cpustate->LP0 = 0;
+ cpustate->LP1 = 0;
+ cpustate->LP2 = 0;
+ cpustate->A = 0;
+ cpustate->B = 0;
+#if HANDLE_HALT_LINE
+ cpustate->halt = 0;
+#endif
+}
+
+/****************************************************************************
+ * Shut down CPU emulation
+ ****************************************************************************/
+static CPU_EXIT( alpha8201 )
+{
+ /* nothing to do ? */
+}
+
+/****************************************************************************
+ * Execute cycles CPU cycles. Return number of cycles really executed
+ ****************************************************************************/
+
+static void alpha8xxx_execute(device_t *device,const s_opcode *op_map)
+{
+ alpha8201_state *cpustate = get_safe_token(device);
+ unsigned opcode;
+ UINT8 pcptr;
+
+#if HANDLE_HALT_LINE
+ if(cpustate->halt)
+ {
+ cpustate->icount = 0;
+ return;
+ }
+#endif
+
+ /* setup address bank & fall safe */
+ cpustate->ix0.b.h =
+ cpustate->ix1.b.h =
+ cpustate->ix2.b.h = (cpustate->pc.b.h &= 3);
+
+ /* reset start hack */
+ if(cpustate->PC<0x20)
+ cpustate->mb |= 0x08;
+
+ do
+ {
+ if(cpustate->mb & 0x08)
+ {
+ pcptr = M_RDMEM(0x001) & 0x1f; /* pointer of entry point */
+ cpustate->icount -= C1;
+
+ /* entry point scan phase */
+ if( (pcptr&1) == 0)
+ {
+ /* EVEN , get cpustate->PC low */
+ cpustate->pc.b.l = M_RDMEM(pcptr);
+//mame_printf_debug("alpha8201 load PCL ENTRY=%02X PCL=%02X\n",pcptr, cpustate->pc.b.l);
+ cpustate->icount -= C1;
+ M_WRMEM(0x001,pcptr+1);
+ continue;
+ }
+
+ /* ODD , check HALT flag */
+ cpustate->mb = M_RDMEM(pcptr) & (0x08|0x03);
+ cpustate->icount -= C1;
+
+ /* not entryaddress 000,001 */
+ if(pcptr<2) cpustate->mb |= 0x08;
+
+ if(cpustate->mb & 0x08)
+ {
+ /* HALTED current entry point . next one */
+ pcptr = (pcptr+1)&0x1f;
+ M_WRMEM(0x001,pcptr);
+ cpustate->icount -= C1;
+ continue;
+ }
+
+ /* goto run phase */
+ M_JMP(cpustate, cpustate->pc.b.l);
+
+#if SHOW_ENTRY_POINT
+logerror("alpha8201 START ENTRY=%02X cpustate->PC=%03X\n",pcptr,cpustate->PC);
+mame_printf_debug("alpha8201 START ENTRY=%02X cpustate->PC=%03X\n",pcptr,cpustate->PC);
+#endif
+ }
+
+ /* run */
+ cpustate->PREVPC = cpustate->PC;
+ debugger_instruction_hook(device, cpustate->PC);
+ opcode =M_RDOP(cpustate->PC);
+#if TRACE_PC
+mame_printf_debug("alpha8201: cpustate->PC = %03x, opcode = %02x\n", cpustate->PC, opcode);
+#endif
+ cpustate->PCL++;
+ cpustate->inst_cycles = op_map[opcode].cycles;
+ (*(op_map[opcode].function))(cpustate);
+ cpustate->icount -= cpustate->inst_cycles;
+ } while (cpustate->icount>0);
+}
+
+static CPU_EXECUTE( alpha8201 ) { alpha8xxx_execute(device,opcode_8201); }
+
+static CPU_EXECUTE( ALPHA8301 ) { alpha8xxx_execute(device,opcode_8301); }
+
+/****************************************************************************
+ * Set IRQ line state
+ ****************************************************************************/
+#if HANDLE_HALT_LINE
+static void set_irq_line(alpha8201_state *cpustate, int irqline, int state)
+{
+ if(irqline == INPUT_LINE_HALT)
+ {
+ cpustate->halt = (state==ASSERT_LINE) ? 1 : 0;
+/* mame_printf_debug("alpha8201 HALT %d\n",cpustate->halt); */
+ }
+}
+#endif
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( alpha8201 )
+{
+ alpha8201_state *cpustate = get_safe_token(device);
+ switch (state)
+ {
+#if HANDLE_HALT_LINE
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_HALT: set_irq_line(cpustate, INPUT_LINE_HALT, info->i); break;
+#endif
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + ALPHA8201_PC: cpustate->PC = info->i; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + ALPHA8201_SP: M_WRMEM(0x001,info->i); break;
+ case CPUINFO_INT_REGISTER + ALPHA8201_RB: cpustate->regPtr = info->i & 7; break;
+ case CPUINFO_INT_REGISTER + ALPHA8201_MB: cpustate->mb = info->i & 0x03; break;
+#if 0
+ case CPUINFO_INT_REGISTER + ALPHA8201_ZF: cpustate->zf= info->i & 0x01; break;
+ case CPUINFO_INT_REGISTER + ALPHA8201_CF: cpustate->cf= info->i & 0x01; break;
+#endif
+ case CPUINFO_INT_REGISTER + ALPHA8201_IX0: cpustate->IX0 = info->i; break;
+ case CPUINFO_INT_REGISTER + ALPHA8201_IX1: cpustate->IX1 = info->i; break;
+ case CPUINFO_INT_REGISTER + ALPHA8201_IX2: cpustate->IX2 = info->i; break;
+ case CPUINFO_INT_REGISTER + ALPHA8201_LP0: cpustate->LP0 = info->i; break;
+ case CPUINFO_INT_REGISTER + ALPHA8201_LP1: cpustate->LP1 = info->i; break;
+ case CPUINFO_INT_REGISTER + ALPHA8201_LP2: cpustate->LP2 = info->i; break;
+ case CPUINFO_INT_REGISTER + ALPHA8201_A: cpustate->A = info->i; break;
+ case CPUINFO_INT_REGISTER + ALPHA8201_B: cpustate->B = info->i; break;
+ case CPUINFO_INT_REGISTER + ALPHA8201_R0: WR_REG(0,info->i); break;
+ case CPUINFO_INT_REGISTER + ALPHA8201_R1: WR_REG(1,info->i); break;
+ case CPUINFO_INT_REGISTER + ALPHA8201_R2: WR_REG(2,info->i); break;
+ case CPUINFO_INT_REGISTER + ALPHA8201_R3: WR_REG(3,info->i); break;
+ case CPUINFO_INT_REGISTER + ALPHA8201_R4: WR_REG(4,info->i); break;
+ case CPUINFO_INT_REGISTER + ALPHA8201_R5: WR_REG(5,info->i); break;
+ case CPUINFO_INT_REGISTER + ALPHA8201_R6: WR_REG(6,info->i); break;
+ case CPUINFO_INT_REGISTER + ALPHA8201_R7: WR_REG(7,info->i); break;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+/* 8201 and 8301 */
+static CPU_GET_INFO( alpha8xxx )
+{
+ alpha8201_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(alpha8201_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 0; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 2; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 16; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 10; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 6; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+#if HANDLE_HALT_LINE
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_HALT: info->i = cpustate->halt ? ASSERT_LINE : CLEAR_LINE; break;
+#endif
+ case CPUINFO_INT_PREVIOUSPC: info->i = cpustate->PREVPC; break;
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + ALPHA8201_PC: info->i = cpustate->PC & 0x3ff; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + ALPHA8201_SP: info->i = M_RDMEM(0x001); break;
+ case CPUINFO_INT_REGISTER + ALPHA8201_RB: info->i = cpustate->regPtr; break;
+ case CPUINFO_INT_REGISTER + ALPHA8201_MB: info->i = cpustate->mb; break;
+ case CPUINFO_INT_REGISTER + ALPHA8201_ZF: info->i = cpustate->zf; break;
+ case CPUINFO_INT_REGISTER + ALPHA8201_CF: info->i = cpustate->cf; break;
+ case CPUINFO_INT_REGISTER + ALPHA8201_IX0: info->i = cpustate->IX0; break;
+ case CPUINFO_INT_REGISTER + ALPHA8201_IX1: info->i = cpustate->IX1; break;
+ case CPUINFO_INT_REGISTER + ALPHA8201_IX2: info->i = cpustate->IX2; break;
+ case CPUINFO_INT_REGISTER + ALPHA8201_LP0: info->i = cpustate->LP0; break;
+ case CPUINFO_INT_REGISTER + ALPHA8201_LP1: info->i = cpustate->LP1; break;
+ case CPUINFO_INT_REGISTER + ALPHA8201_LP2: info->i = cpustate->LP2; break;
+ case CPUINFO_INT_REGISTER + ALPHA8201_A: info->i = cpustate->A; break;
+ case CPUINFO_INT_REGISTER + ALPHA8201_B: info->i = cpustate->B; break;
+ case CPUINFO_INT_REGISTER + ALPHA8201_R0: info->i = RD_REG(0); break;
+ case CPUINFO_INT_REGISTER + ALPHA8201_R1: info->i = RD_REG(1); break;
+ case CPUINFO_INT_REGISTER + ALPHA8201_R2: info->i = RD_REG(2); break;
+ case CPUINFO_INT_REGISTER + ALPHA8201_R3: info->i = RD_REG(3); break;
+ case CPUINFO_INT_REGISTER + ALPHA8201_R4: info->i = RD_REG(4); break;
+ case CPUINFO_INT_REGISTER + ALPHA8201_R5: info->i = RD_REG(5); break;
+ case CPUINFO_INT_REGISTER + ALPHA8201_R6: info->i = RD_REG(6); break;
+ case CPUINFO_INT_REGISTER + ALPHA8201_R7: info->i = RD_REG(7); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(alpha8201); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(alpha8201); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(alpha8201); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(alpha8201); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(alpha8201); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "AlphaDenshi MCU"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "0.1"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Tatsuyuki Satoh"); break;
+ case CPUINFO_STR_FLAGS: sprintf(info->s, "%c%c", cpustate->cf?'C':'.',cpustate->zf?'Z':'.'); break;
+ case CPUINFO_STR_REGISTER + ALPHA8201_PC: sprintf(info->s, "cpustate->PC:%03X", cpustate->PC); break;
+ case CPUINFO_STR_REGISTER + ALPHA8201_SP: sprintf(info->s, "SP:%02X", M_RDMEM(0x001) ); break;
+ case CPUINFO_STR_REGISTER + ALPHA8201_RB: sprintf(info->s, "RB:%X", cpustate->regPtr); break;
+ case CPUINFO_STR_REGISTER + ALPHA8201_MB: sprintf(info->s, "MB:%X", cpustate->mb); break;
+#if 0
+ case CPUINFO_STR_REGISTER + ALPHA8201_ZF: sprintf(info->s, "cpustate->zf:%X", cpustate->zf); break;
+ case CPUINFO_STR_REGISTER + ALPHA8201_CF: sprintf(info->s, "cpustate->cf:%X", cpustate->cf); break;
+#endif
+ case CPUINFO_STR_REGISTER + ALPHA8201_IX0: sprintf(info->s, "cpustate->IX0:%02X", cpustate->IX0); break;
+ case CPUINFO_STR_REGISTER + ALPHA8201_IX1: sprintf(info->s, "cpustate->IX1:%02X", cpustate->IX1); break;
+ case CPUINFO_STR_REGISTER + ALPHA8201_IX2: sprintf(info->s, "cpustate->IX2:%02X", cpustate->IX2); break;
+ case CPUINFO_STR_REGISTER + ALPHA8201_LP0: sprintf(info->s, "cpustate->LP0:%02X", cpustate->LP0); break;
+ case CPUINFO_STR_REGISTER + ALPHA8201_LP1: sprintf(info->s, "cpustate->LP1:%02X", cpustate->LP1); break;
+ case CPUINFO_STR_REGISTER + ALPHA8201_LP2: sprintf(info->s, "cpustate->LP2:%02X", cpustate->LP2); break;
+ case CPUINFO_STR_REGISTER + ALPHA8201_A: sprintf(info->s, "A:%02X", cpustate->A); break;
+ case CPUINFO_STR_REGISTER + ALPHA8201_B: sprintf(info->s, "B:%02X", cpustate->B); break;
+ case CPUINFO_STR_REGISTER + ALPHA8201_R0: sprintf(info->s, "R0:%02X", RD_REG(0)); break;
+ case CPUINFO_STR_REGISTER + ALPHA8201_R1: sprintf(info->s, "R1:%02X", RD_REG(1)); break;
+ case CPUINFO_STR_REGISTER + ALPHA8201_R2: sprintf(info->s, "R2:%02X", RD_REG(2)); break;
+ case CPUINFO_STR_REGISTER + ALPHA8201_R3: sprintf(info->s, "R3:%02X", RD_REG(3)); break;
+ case CPUINFO_STR_REGISTER + ALPHA8201_R4: sprintf(info->s, "R4:%02X", RD_REG(4)); break;
+ case CPUINFO_STR_REGISTER + ALPHA8201_R5: sprintf(info->s, "R5:%02X", RD_REG(5)); break;
+ case CPUINFO_STR_REGISTER + ALPHA8201_R6: sprintf(info->s, "R6:%02X", RD_REG(6)); break;
+ case CPUINFO_STR_REGISTER + ALPHA8201_R7: sprintf(info->s, "R7:%02X", RD_REG(7)); break;
+ }
+}
+CPU_GET_INFO( alpha8201 )
+{
+ switch (state)
+ {
+ case DEVINFO_STR_NAME: strcpy(info->s, "ALPHA-8201"); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(alpha8201); break;
+ default:
+ /* 8201 / 8301 */
+ CPU_GET_INFO_CALL(alpha8xxx);
+ }
+}
+
+CPU_GET_INFO( alpha8301 )
+{
+ switch (state)
+ {
+ case DEVINFO_STR_NAME: strcpy(info->s, "ALPHA-8301"); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(ALPHA8301); break;
+ default:
+ /* 8201 / 8301 */
+ CPU_GET_INFO_CALL(alpha8xxx);
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(ALPHA8201, alpha8201);
+DEFINE_LEGACY_CPU_DEVICE(ALPHA8301, alpha8301);
diff --git a/trunk/src/emu/cpu/alph8201/alph8201.h b/trunk/src/emu/cpu/alph8201/alph8201.h
new file mode 100644
index 00000000000..449e584fe67
--- /dev/null
+++ b/trunk/src/emu/cpu/alph8201/alph8201.h
@@ -0,0 +1,43 @@
+ /**************************************************************************\
+ * Alpha8201 Emulator *
+ * *
+ * Copyright Tatsuyuki Satoh *
+ * Originally written for the MAME project. *
+ * *
+ * *
+ \**************************************************************************/
+
+#pragma once
+
+#ifndef __ALPH8201_H__
+#define __ALPH8201_H__
+
+enum
+{
+ ALPHA8201_PC=1,
+ ALPHA8201_SP,
+ ALPHA8201_RB,
+ ALPHA8201_MB,
+//
+ ALPHA8201_CF,
+ ALPHA8201_ZF,
+//
+ ALPHA8201_IX0,
+ ALPHA8201_IX1,
+ ALPHA8201_IX2,
+ ALPHA8201_LP0,
+ ALPHA8201_LP1,
+ ALPHA8201_LP2,
+ ALPHA8201_A,
+ ALPHA8201_B,
+//
+ ALPHA8201_R0,ALPHA8201_R1,ALPHA8201_R2,ALPHA8201_R3,
+ ALPHA8201_R4,ALPHA8201_R5,ALPHA8201_R6,ALPHA8201_R7
+};
+
+DECLARE_LEGACY_CPU_DEVICE(ALPHA8201, alpha8201);
+DECLARE_LEGACY_CPU_DEVICE(ALPHA8301, alpha8301);
+
+CPU_DISASSEMBLE( alpha8201 );
+
+#endif /* __ALPH8201_H__ */
diff --git a/trunk/src/emu/cpu/am29000/am29000.c b/trunk/src/emu/cpu/am29000/am29000.c
new file mode 100644
index 00000000000..f23a5ca4d5c
--- /dev/null
+++ b/trunk/src/emu/cpu/am29000/am29000.c
@@ -0,0 +1,1216 @@
+/***************************************************************************
+
+ am29000.c
+ Core implementation of the Am29000 emulator
+
+ Written by Philip Bennett
+
+ Features missing:
+ * MMU
+ * Some instructions
+ * Various exceptions
+
+***************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "am29000.h"
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define MAX_EXCEPTIONS (4)
+
+#define PFLAG_FETCH_EN (1 << 0)
+#define PFLAG_DECODE_EN (1 << 1)
+#define PFLAG_EXECUTE_EN (1 << 2)
+#define PFLAG_WRITEBACK_EN (1 << 3)
+#define PFLAG_IRQ (1 << 4)
+#define PFLAG_LOADSTORE (1 << 5)
+#define PFLAG_MULTI_LOADSTORE (1 << 6)
+#define PFLAG_JUMP (1 << 7)
+#define PFLAG_JUMP2 (1 << 8)
+#define PFLAG_IRET (1 << 9)
+#define PFLAG_TIMER_LOADED (1 << 10)
+
+#define PFLAG_RA_DEPENDENCY (1 << 26)
+#define PFLAG_RB_DEPENDENCY (1 << 27)
+
+#define PFLAG_MEM_MULTIPLE (1 << 29)
+#define PFLAG_REG_WRITEBACK (1 << 30)
+#define PFLAG_MEM_WRITEBACK (1 << 31)
+
+#define MMU_PROGRAM_ACCESS (0)
+#define MMU_DATA_ACCESS (1)
+
+#define FREEZE_MODE (am29000->cps & CPS_FZ)
+#define SUPERVISOR_MODE (am29000->cps & CPS_SM)
+#define USER_MODE (~am29000->cps & CPS_SM)
+#define REGISTER_IS_PROTECTED(x) (am29000->rbp & (1 << ((x) >> 4)))
+
+#define INST_RB_FIELD(x) ((x) & 0xff)
+#define INST_RA_FIELD(x) (((x) >> 8) & 0xff)
+#define INST_RC_FIELD(x) (((x) >> 16) & 0xff)
+#define INST_SA_FIELD(x) (((x) >> 8) & 0xff)
+
+#define FIELD_RA 0
+#define FIELD_RB 1
+#define FIELD_RC 2
+
+#define SIGNAL_EXCEPTION(x) (signal_exception(am29000, x))
+
+
+#define GET_ALU_FC ((am29000->alu >> ALU_FC_SHIFT) & ALU_FC_MASK)
+#define GET_ALU_BP ((am29000->alu >> ALU_BP_SHIFT) & ALU_BP_MASK)
+#define GET_CHC_CR ((am29000->chc >> CHC_CR_SHIFT) & CHC_CR_MASK)
+
+#define SET_ALU_FC(x) do { am29000->alu &= ~(ALU_FC_MASK << ALU_FC_SHIFT); am29000->alu |= ((x) & ALU_FC_MASK) << ALU_FC_SHIFT; } while(0)
+#define SET_ALU_BP(x) do { am29000->alu &= ~(ALU_BP_MASK << ALU_BP_SHIFT); am29000->alu |= ((x) & ALU_BP_MASK) << ALU_BP_SHIFT; } while(0)
+#define SET_CHC_CR(x) do { am29000->chc &= ~(CHC_CR_MASK << CHC_CR_SHIFT); am29000->chc |= ((x) & CHC_CR_MASK) << CHC_CR_SHIFT; } while(0)
+
+
+/***************************************************************************
+ STRUCTURES & TYPEDEFS
+***************************************************************************/
+
+typedef struct _am29000_state
+{
+ INT32 icount;
+ UINT32 pc;
+
+ /* General purpose */
+ UINT32 r[256]; // TODO: There's only 192 implemented!
+
+ /* TLB */
+ UINT32 tlb[128];
+
+ /* Protected SPRs */
+ UINT32 vab;
+ UINT32 ops;
+ UINT32 cps;
+ UINT32 cfg;
+ UINT32 cha;
+ UINT32 chd;
+ UINT32 chc;
+ UINT32 rbp;
+ UINT32 tmc;
+ UINT32 tmr;
+ UINT32 pc0;
+ UINT32 pc1;
+ UINT32 pc2;
+ UINT32 mmu;
+ UINT32 lru;
+
+ /* Unprotected SPRs */
+ UINT32 ipc;
+ UINT32 ipa;
+ UINT32 ipb;
+ UINT32 q;
+ UINT32 alu;
+ UINT32 fpe;
+ UINT32 inte;
+ UINT32 fps;
+
+ /* Pipeline state */
+ UINT32 exceptions;
+ UINT32 exception_queue[MAX_EXCEPTIONS];
+
+ UINT8 irq_active;
+ UINT8 irq_lines;
+
+ UINT32 exec_ir;
+ UINT32 next_ir;
+
+ UINT32 pl_flags;
+ UINT32 next_pl_flags;
+
+ UINT32 iret_pc;
+
+ UINT32 exec_pc;
+ UINT32 next_pc;
+
+ address_space *program;
+ direct_read_data *direct;
+ address_space *data;
+ direct_read_data *datadirect;
+ address_space *io;
+} am29000_state;
+
+
+/***************************************************************************
+ STATE ACCESSORS
+***************************************************************************/
+
+INLINE am29000_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == AM29000);
+ return (am29000_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+static CPU_INIT( am29000 )
+{
+ am29000_state *am29000 = get_safe_token(device);
+
+ am29000->program = device->space(AS_PROGRAM);
+ am29000->direct = &am29000->program->direct();
+ am29000->data = device->space(AS_DATA);
+ am29000->datadirect = &am29000->data->direct();
+ am29000->io = device->space(AS_IO);
+ am29000->cfg = (PRL_AM29000 | PRL_REV_D) << CFG_PRL_SHIFT;
+
+ /* Register state for saving */
+ device->save_item(NAME(am29000->icount));
+ device->save_item(NAME(am29000->pc));
+ device->save_item(NAME(am29000->r));
+ device->save_item(NAME(am29000->tlb));
+
+ device->save_item(NAME(am29000->vab));
+ device->save_item(NAME(am29000->ops));
+ device->save_item(NAME(am29000->cps));
+ device->save_item(NAME(am29000->cfg));
+ device->save_item(NAME(am29000->cha));
+ device->save_item(NAME(am29000->chd));
+ device->save_item(NAME(am29000->chc));
+ device->save_item(NAME(am29000->rbp));
+ device->save_item(NAME(am29000->tmc));
+ device->save_item(NAME(am29000->tmr));
+ device->save_item(NAME(am29000->pc0));
+ device->save_item(NAME(am29000->pc1));
+ device->save_item(NAME(am29000->pc2));
+ device->save_item(NAME(am29000->mmu));
+ device->save_item(NAME(am29000->lru));
+
+ device->save_item(NAME(am29000->ipc));
+ device->save_item(NAME(am29000->ipa));
+ device->save_item(NAME(am29000->ipb));
+ device->save_item(NAME(am29000->q));
+
+ device->save_item(NAME(am29000->alu));
+ device->save_item(NAME(am29000->fpe));
+ device->save_item(NAME(am29000->inte));
+ device->save_item(NAME(am29000->fps));
+
+ device->save_item(NAME(am29000->exceptions));
+ device->save_item(NAME(am29000->exception_queue));
+
+ device->save_item(NAME(am29000->irq_active));
+ device->save_item(NAME(am29000->irq_lines));
+
+ device->save_item(NAME(am29000->exec_ir));
+ device->save_item(NAME(am29000->next_ir));
+
+ device->save_item(NAME(am29000->pl_flags));
+ device->save_item(NAME(am29000->next_pl_flags));
+
+ device->save_item(NAME(am29000->iret_pc));
+ device->save_item(NAME(am29000->exec_pc));
+ device->save_item(NAME(am29000->next_pc));
+}
+
+static CPU_RESET( am29000 )
+{
+ am29000_state *am29000 = get_safe_token(device);
+
+ am29000->cps = CPS_FZ | CPS_RE | CPS_PD | CPS_PI | CPS_SM | CPS_DI | CPS_DA;
+ am29000->cfg &= ~(CFG_DW | CFG_CD);
+ am29000->chc &= ~CHC_CV;
+
+ am29000->pc = 0;
+ am29000->next_pl_flags = 0;
+ am29000->exceptions = 0;
+ am29000->irq_lines = 0;
+}
+
+
+static CPU_EXIT( am29000 )
+{
+
+}
+
+
+static void signal_exception(am29000_state *am29000, UINT32 type)
+{
+ am29000->exception_queue[am29000->exceptions++] = type;
+}
+
+static void external_irq_check(am29000_state *am29000)
+{
+ int mask = (am29000->cps >> CPS_IM_SHIFT) & CPS_IM_MASK;
+ int irq_en = !(am29000->cps & CPS_DI) && !(am29000->cps & CPS_DA);
+ int i;
+
+ /* Clear interrupt pending bit to begin with */
+ am29000->cps &= ~CPS_IP;
+
+ for (i = 0; i < 4; ++i)
+ {
+ if (!(am29000->irq_active & (1 << i)) && (am29000->irq_lines & (1 << i)))
+ {
+ if (irq_en)
+ {
+ if (i <= mask)
+ {
+ am29000->irq_active |= (1 << i);
+ SIGNAL_EXCEPTION(EXCEPTION_INTR0 + i);
+ am29000->pl_flags |= PFLAG_IRQ;
+ return;
+ }
+ }
+ /* Set interrupt pending bit if interrupt was disabled */
+ am29000->cps |= CPS_IP;
+ }
+ else
+ am29000->irq_active &= ~(1 << i);
+ }
+}
+
+static UINT32 read_program_word(am29000_state *state, UINT32 address)
+{
+ /* TODO: ROM enable? */
+ if (state->cps & CPS_PI || state->cps & CPS_RE)
+ return state->direct->read_decrypted_dword(address);
+ else
+ {
+ fatalerror("Am29000 instruction MMU translation enabled!");
+ }
+ return 0;
+}
+
+/***************************************************************************
+ HELPER FUNCTIONS
+***************************************************************************/
+
+INLINE UINT32 get_abs_reg(am29000_state *am29000, UINT8 r, UINT32 iptr)
+{
+ if (r & 0x80)
+ {
+ /* Stack pointer access */
+ r = ((am29000->r[1] >> 2) & 0x7f) + (r & 0x7f);
+ r |= 0x80;
+ }
+ else if (r == 0)
+ {
+ /* Indirect pointer access */
+ r = (iptr >> IPX_SHIFT) & 0xff;
+ }
+ else if (r > 1 && r < 64)
+ {
+ fatalerror("Am29000: Undefined register access (%d)\n", r);
+ }
+ return r;
+}
+
+
+/***************************************************************************
+ CORE INCLUDE
+***************************************************************************/
+
+#include "am29ops.h"
+
+
+/***************************************************************************
+ PIPELINE STAGES
+***************************************************************************/
+
+INLINE void fetch_decode(am29000_state *am29000)
+{
+ UINT32 inst;
+ op_info op;
+
+ inst = read_program_word(am29000, am29000->pc);
+ am29000->next_ir = inst;
+
+ op = op_table[inst >> 24];
+
+ /* Illegal instruction */
+ /* TODO: This should be checked at this point */
+#if 0
+ if (op.flags & IFLAG_ILLEGAL)
+ {
+ fatalerror("Illegal instruction: %x PC:%x PC0:%x PC1:%x\n", inst, am29000->pc, am29000->pc0, am29000->pc1);
+ SIGNAL_EXCEPTION(EXCEPTION_ILLEGAL_OPCODE);
+ return;
+ }
+#endif
+
+ /* Privledge violations */
+ if (USER_MODE)
+ {
+ if ((op.flags & IFLAG_SUPERVISOR_ONLY))
+ {
+ SIGNAL_EXCEPTION(EXCEPTION_PROTECTION_VIOLATION);
+ return;
+ }
+
+ if ((op.flags & IFLAG_SPR_ACCESS))
+ {
+ /* TODO: Is this the right place to check this? */
+ if (INST_SA_FIELD(inst) < 128)
+ {
+ SIGNAL_EXCEPTION(EXCEPTION_PROTECTION_VIOLATION);
+ return;
+ }
+ }
+
+ /* Register bank protection */
+ if ((op.flags & IFLAG_RA_PRESENT) && REGISTER_IS_PROTECTED(INST_RA_FIELD(inst)))
+ {
+ SIGNAL_EXCEPTION(EXCEPTION_PROTECTION_VIOLATION);
+ return;
+ }
+
+ if ((op.flags & IFLAG_RB_PRESENT) && REGISTER_IS_PROTECTED(INST_RB_FIELD(inst)))
+ {
+ SIGNAL_EXCEPTION(EXCEPTION_PROTECTION_VIOLATION);
+ return;
+ }
+
+ if ((op.flags & IFLAG_RC_PRESENT) && REGISTER_IS_PROTECTED(INST_RC_FIELD(inst)))
+ {
+ SIGNAL_EXCEPTION(EXCEPTION_PROTECTION_VIOLATION);
+ return;
+ }
+ }
+
+ if (am29000->pl_flags & PFLAG_IRET)
+ am29000->next_pc = am29000->iret_pc;
+ else
+ am29000->next_pc += 4;
+}
+
+/***************************************************************************
+ CORE EXECUTION LOOP
+***************************************************************************/
+
+static CPU_EXECUTE( am29000 )
+{
+ am29000_state *am29000 = get_safe_token(device);
+ UINT32 call_debugger = (device->machine().debug_flags & DEBUG_FLAG_ENABLED) != 0;
+
+ external_irq_check(am29000);
+
+ do
+ {
+ am29000->next_pl_flags = PFLAG_EXECUTE_EN;
+
+ if (!FREEZE_MODE)
+ {
+ am29000->pc1 = am29000->pc0;
+ am29000->pc0 = am29000->pc;
+ }
+
+ if (am29000->exceptions)
+ {
+ am29000->ops = am29000->cps;
+ am29000->cps &= ~(CPS_TE | CPS_TP | CPS_TU | CPS_FZ | CPS_LK | CPS_WM | CPS_PD | CPS_PI | CPS_SM | CPS_DI | CPS_DA);
+ am29000->cps |= (CPS_FZ | CPS_PD | CPS_PI | CPS_SM | CPS_DI | CPS_DA);
+
+ if (am29000->pl_flags & PFLAG_IRET)
+ {
+ am29000->pc0 = am29000->iret_pc;
+ am29000->pc1 = am29000->next_pc;
+ }
+
+
+ if (am29000->cfg & CFG_VF)
+ {
+ UINT32 vaddr = am29000->vab | am29000->exception_queue[0] * 4;
+ UINT32 vect = am29000->datadirect->read_decrypted_dword(vaddr);
+
+ am29000->pc = vect & ~3;
+ am29000->next_pc = am29000->pc;
+ }
+ else
+ {
+ fatalerror("Am29000: Non vectored interrupt fetch!");
+ }
+
+ am29000->exceptions = 0;
+ am29000->pl_flags = 0;
+ }
+
+ if (call_debugger)
+ debugger_instruction_hook(device, am29000->pc);
+
+ fetch_decode(am29000);
+
+ if (am29000->pl_flags & PFLAG_EXECUTE_EN)
+ {
+ if (!FREEZE_MODE)
+ am29000->pc2 = am29000->pc1;
+
+ op_table[am29000->exec_ir >> 24].opcode(am29000);
+ }
+
+ am29000->exec_ir = am29000->next_ir;
+ am29000->pl_flags = am29000->next_pl_flags;
+ am29000->exec_pc = am29000->pc;
+ am29000->pc = am29000->next_pc;
+ } while (--am29000->icount > 0);
+}
+
+static void set_irq_line(am29000_state *am29000, int line, int state)
+{
+ if (state)
+ am29000->irq_lines |= (1 << line);
+ else
+ am29000->irq_lines &= ~(1 << line);
+
+ // TODO : CHECK IRQs
+}
+
+/***************************************************************************
+ DISASSEMBLY HOOK
+***************************************************************************/
+
+extern CPU_DISASSEMBLE( am29000 );
+
+
+static CPU_SET_INFO( am29000 )
+{
+ am29000_state *am29000 = get_safe_token(device);
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + AM29000_INTR0: set_irq_line(am29000, AM29000_INTR0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AM29000_INTR1: set_irq_line(am29000, AM29000_INTR1, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AM29000_INTR2: set_irq_line(am29000, AM29000_INTR2, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AM29000_INTR3: set_irq_line(am29000, AM29000_INTR3, info->i); break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + AM29000_PC: am29000->pc = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_VAB: am29000->vab = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_OPS: am29000->ops = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_CPS: am29000->cps = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_CFG: am29000->cfg = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_CHA: am29000->cha = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_CHD: am29000->chd = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_CHC: am29000->chc = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_RBP: am29000->rbp = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_TMC: am29000->tmc = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_TMR: am29000->tmr = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_PC0: am29000->pc0 = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_PC1: am29000->pc1 = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_PC2: am29000->pc2 = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_MMU: am29000->mmu = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_LRU: am29000->lru = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_IPC: am29000->ipc = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_IPA: am29000->ipa = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_IPB: am29000->ipb = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_Q: am29000->q = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_ALU: am29000->alu = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_BP: SET_ALU_BP(info->i); break;
+ case CPUINFO_INT_REGISTER + AM29000_FC: SET_ALU_FC(info->i); break;
+ case CPUINFO_INT_REGISTER + AM29000_CR: SET_CHC_CR(info->i); break;
+ case CPUINFO_INT_REGISTER + AM29000_FPE: am29000->fpe = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_INTE: am29000->inte = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_FPS: am29000->fps = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R1: am29000->r[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R64: am29000->r[64] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R65: am29000->r[65] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R66: am29000->r[66] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R67: am29000->r[67] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R68: am29000->r[68] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R69: am29000->r[69] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R70: am29000->r[70] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R71: am29000->r[71] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R72: am29000->r[72] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R73: am29000->r[73] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R74: am29000->r[74] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R75: am29000->r[75] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R76: am29000->r[76] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R77: am29000->r[77] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R78: am29000->r[78] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R79: am29000->r[79] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R80: am29000->r[80] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R81: am29000->r[81] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R82: am29000->r[82] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R83: am29000->r[83] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R84: am29000->r[84] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R85: am29000->r[85] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R86: am29000->r[86] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R87: am29000->r[87] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R88: am29000->r[88] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R89: am29000->r[89] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R90: am29000->r[90] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R91: am29000->r[91] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R92: am29000->r[92] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R93: am29000->r[93] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R94: am29000->r[94] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R95: am29000->r[95] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R96: am29000->r[96] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R97: am29000->r[97] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R98: am29000->r[98] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R99: am29000->r[99] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R100: am29000->r[100] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R101: am29000->r[101] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R102: am29000->r[102] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R103: am29000->r[103] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R104: am29000->r[104] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R105: am29000->r[105] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R106: am29000->r[106] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R107: am29000->r[107] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R108: am29000->r[108] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R109: am29000->r[109] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R110: am29000->r[110] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R111: am29000->r[111] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R112: am29000->r[112] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R113: am29000->r[113] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R114: am29000->r[114] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R115: am29000->r[115] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R116: am29000->r[116] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R117: am29000->r[117] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R118: am29000->r[118] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R119: am29000->r[119] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R120: am29000->r[120] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R121: am29000->r[121] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R122: am29000->r[122] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R123: am29000->r[123] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R124: am29000->r[124] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R125: am29000->r[125] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R126: am29000->r[126] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R127: am29000->r[127] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R128: am29000->r[128] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R129: am29000->r[129] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R130: am29000->r[130] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R131: am29000->r[131] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R132: am29000->r[132] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R133: am29000->r[133] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R134: am29000->r[134] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R135: am29000->r[135] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R136: am29000->r[136] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R137: am29000->r[137] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R138: am29000->r[138] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R139: am29000->r[139] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R140: am29000->r[140] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R141: am29000->r[141] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R142: am29000->r[142] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R143: am29000->r[143] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R144: am29000->r[144] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R145: am29000->r[145] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R146: am29000->r[146] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R147: am29000->r[147] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R148: am29000->r[148] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R149: am29000->r[149] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R150: am29000->r[150] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R151: am29000->r[151] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R152: am29000->r[152] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R153: am29000->r[153] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R154: am29000->r[154] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R155: am29000->r[155] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R156: am29000->r[156] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R157: am29000->r[157] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R158: am29000->r[158] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R159: am29000->r[159] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R160: am29000->r[160] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R161: am29000->r[161] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R162: am29000->r[162] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R163: am29000->r[163] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R164: am29000->r[164] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R165: am29000->r[165] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R166: am29000->r[166] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R167: am29000->r[167] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R168: am29000->r[168] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R169: am29000->r[169] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R170: am29000->r[170] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R171: am29000->r[171] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R172: am29000->r[172] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R173: am29000->r[173] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R174: am29000->r[174] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R175: am29000->r[175] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R176: am29000->r[176] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R177: am29000->r[177] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R178: am29000->r[178] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R179: am29000->r[179] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R180: am29000->r[180] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R181: am29000->r[181] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R182: am29000->r[182] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R183: am29000->r[183] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R184: am29000->r[184] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R185: am29000->r[185] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R186: am29000->r[186] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R187: am29000->r[187] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R188: am29000->r[188] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R189: am29000->r[189] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R190: am29000->r[190] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R191: am29000->r[191] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R192: am29000->r[192] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R193: am29000->r[193] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R194: am29000->r[194] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R195: am29000->r[195] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R196: am29000->r[196] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R197: am29000->r[197] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R198: am29000->r[198] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R199: am29000->r[199] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R200: am29000->r[200] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R201: am29000->r[201] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R202: am29000->r[202] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R203: am29000->r[203] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R204: am29000->r[204] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R205: am29000->r[205] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R206: am29000->r[206] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R207: am29000->r[207] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R208: am29000->r[208] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R209: am29000->r[209] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R210: am29000->r[210] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R211: am29000->r[211] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R212: am29000->r[212] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R213: am29000->r[213] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R214: am29000->r[214] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R215: am29000->r[215] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R216: am29000->r[216] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R217: am29000->r[217] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R218: am29000->r[218] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R219: am29000->r[219] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R220: am29000->r[220] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R221: am29000->r[221] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R222: am29000->r[222] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R223: am29000->r[223] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R224: am29000->r[224] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R225: am29000->r[225] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R226: am29000->r[226] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R227: am29000->r[227] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R228: am29000->r[228] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R229: am29000->r[229] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R230: am29000->r[230] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R231: am29000->r[231] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R232: am29000->r[232] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R233: am29000->r[233] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R234: am29000->r[234] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R235: am29000->r[235] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R236: am29000->r[236] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R237: am29000->r[237] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R238: am29000->r[238] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R239: am29000->r[239] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R240: am29000->r[240] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R241: am29000->r[241] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R242: am29000->r[242] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R243: am29000->r[243] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R244: am29000->r[244] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R245: am29000->r[245] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R246: am29000->r[246] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R247: am29000->r[247] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R248: am29000->r[248] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R249: am29000->r[249] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R250: am29000->r[250] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R251: am29000->r[251] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R252: am29000->r[252] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R253: am29000->r[253] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R254: am29000->r[254] = info->i; break;
+ case CPUINFO_INT_REGISTER + AM29000_R255: am29000->r[255] = info->i; break;
+ }
+}
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+CPU_GET_INFO( am29000 )
+{
+ am29000_state *am29000 = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(am29000_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 1; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 2; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 32; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 32; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 32; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 32; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + AM29000_PC: info->i = am29000->pc; break;
+ case CPUINFO_INT_REGISTER + AM29000_VAB: info->i = am29000->vab; break;
+ case CPUINFO_INT_REGISTER + AM29000_OPS: info->i = am29000->ops; break;
+ case CPUINFO_INT_REGISTER + AM29000_CPS: info->i = am29000->cps; break;
+ case CPUINFO_INT_REGISTER + AM29000_CFG: info->i = am29000->cfg; break;
+ case CPUINFO_INT_REGISTER + AM29000_CHA: info->i = am29000->cha; break;
+ case CPUINFO_INT_REGISTER + AM29000_CHD: info->i = am29000->chd; break;
+ case CPUINFO_INT_REGISTER + AM29000_CHC: info->i = am29000->chc; break;
+ case CPUINFO_INT_REGISTER + AM29000_RBP: info->i = am29000->rbp; break;
+ case CPUINFO_INT_REGISTER + AM29000_TMC: info->i = am29000->tmc; break;
+ case CPUINFO_INT_REGISTER + AM29000_TMR: info->i = am29000->tmr; break;
+ case CPUINFO_INT_REGISTER + AM29000_PC0: info->i = am29000->pc0; break;
+ case CPUINFO_INT_REGISTER + AM29000_PC1: info->i = am29000->pc1; break;
+ case CPUINFO_INT_REGISTER + AM29000_PC2: info->i = am29000->pc2; break;
+ case CPUINFO_INT_REGISTER + AM29000_MMU: info->i = am29000->mmu; break;
+ case CPUINFO_INT_REGISTER + AM29000_LRU: info->i = am29000->lru; break;
+ case CPUINFO_INT_REGISTER + AM29000_IPC: info->i = am29000->ipc; break;
+ case CPUINFO_INT_REGISTER + AM29000_IPA: info->i = am29000->ipa; break;
+ case CPUINFO_INT_REGISTER + AM29000_IPB: info->i = am29000->ipb; break;
+ case CPUINFO_INT_REGISTER + AM29000_Q: info->i = am29000->q; break;
+ case CPUINFO_INT_REGISTER + AM29000_ALU: info->i = am29000->alu; break;
+ case CPUINFO_INT_REGISTER + AM29000_BP: info->i = GET_ALU_BP; break;
+ case CPUINFO_INT_REGISTER + AM29000_FC: info->i = GET_ALU_FC; break;
+ case CPUINFO_INT_REGISTER + AM29000_CR: info->i = GET_CHC_CR; break;
+ case CPUINFO_INT_REGISTER + AM29000_FPE: info->i = am29000->fpe; break;
+ case CPUINFO_INT_REGISTER + AM29000_INTE: info->i = am29000->inte; break;
+ case CPUINFO_INT_REGISTER + AM29000_FPS: info->i = am29000->fps; break;
+ case CPUINFO_INT_REGISTER + AM29000_R1: info->i = am29000->r[1]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R64: info->i = am29000->r[64]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R65: info->i = am29000->r[65]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R66: info->i = am29000->r[66]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R67: info->i = am29000->r[67]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R68: info->i = am29000->r[68]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R69: info->i = am29000->r[69]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R70: info->i = am29000->r[70]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R71: info->i = am29000->r[71]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R72: info->i = am29000->r[72]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R73: info->i = am29000->r[73]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R74: info->i = am29000->r[74]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R75: info->i = am29000->r[75]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R76: info->i = am29000->r[76]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R77: info->i = am29000->r[77]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R78: info->i = am29000->r[78]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R79: info->i = am29000->r[79]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R80: info->i = am29000->r[80]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R81: info->i = am29000->r[81]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R82: info->i = am29000->r[82]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R83: info->i = am29000->r[83]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R84: info->i = am29000->r[84]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R85: info->i = am29000->r[85]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R86: info->i = am29000->r[86]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R87: info->i = am29000->r[87]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R88: info->i = am29000->r[88]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R89: info->i = am29000->r[89]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R90: info->i = am29000->r[90]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R91: info->i = am29000->r[91]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R92: info->i = am29000->r[92]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R93: info->i = am29000->r[93]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R94: info->i = am29000->r[94]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R95: info->i = am29000->r[95]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R96: info->i = am29000->r[96]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R97: info->i = am29000->r[97]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R98: info->i = am29000->r[98]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R99: info->i = am29000->r[99]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R100: info->i = am29000->r[100]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R101: info->i = am29000->r[101]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R102: info->i = am29000->r[102]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R103: info->i = am29000->r[103]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R104: info->i = am29000->r[104]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R105: info->i = am29000->r[105]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R106: info->i = am29000->r[106]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R107: info->i = am29000->r[107]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R108: info->i = am29000->r[108]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R109: info->i = am29000->r[109]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R110: info->i = am29000->r[110]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R111: info->i = am29000->r[111]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R112: info->i = am29000->r[112]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R113: info->i = am29000->r[113]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R114: info->i = am29000->r[114]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R115: info->i = am29000->r[115]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R116: info->i = am29000->r[116]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R117: info->i = am29000->r[117]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R118: info->i = am29000->r[118]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R119: info->i = am29000->r[119]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R120: info->i = am29000->r[120]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R121: info->i = am29000->r[121]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R122: info->i = am29000->r[122]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R123: info->i = am29000->r[123]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R124: info->i = am29000->r[124]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R125: info->i = am29000->r[125]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R126: info->i = am29000->r[126]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R127: info->i = am29000->r[127]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R128: info->i = am29000->r[128]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R129: info->i = am29000->r[129]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R130: info->i = am29000->r[130]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R131: info->i = am29000->r[131]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R132: info->i = am29000->r[132]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R133: info->i = am29000->r[133]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R134: info->i = am29000->r[134]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R135: info->i = am29000->r[135]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R136: info->i = am29000->r[136]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R137: info->i = am29000->r[137]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R138: info->i = am29000->r[138]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R139: info->i = am29000->r[139]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R140: info->i = am29000->r[140]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R141: info->i = am29000->r[141]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R142: info->i = am29000->r[142]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R143: info->i = am29000->r[143]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R144: info->i = am29000->r[144]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R145: info->i = am29000->r[145]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R146: info->i = am29000->r[146]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R147: info->i = am29000->r[147]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R148: info->i = am29000->r[148]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R149: info->i = am29000->r[149]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R150: info->i = am29000->r[150]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R151: info->i = am29000->r[151]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R152: info->i = am29000->r[152]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R153: info->i = am29000->r[153]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R154: info->i = am29000->r[154]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R155: info->i = am29000->r[155]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R156: info->i = am29000->r[156]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R157: info->i = am29000->r[157]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R158: info->i = am29000->r[158]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R159: info->i = am29000->r[159]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R160: info->i = am29000->r[160]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R161: info->i = am29000->r[161]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R162: info->i = am29000->r[162]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R163: info->i = am29000->r[163]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R164: info->i = am29000->r[164]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R165: info->i = am29000->r[165]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R166: info->i = am29000->r[166]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R167: info->i = am29000->r[167]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R168: info->i = am29000->r[168]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R169: info->i = am29000->r[169]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R170: info->i = am29000->r[170]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R171: info->i = am29000->r[171]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R172: info->i = am29000->r[172]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R173: info->i = am29000->r[173]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R174: info->i = am29000->r[174]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R175: info->i = am29000->r[175]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R176: info->i = am29000->r[176]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R177: info->i = am29000->r[177]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R178: info->i = am29000->r[178]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R179: info->i = am29000->r[179]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R180: info->i = am29000->r[180]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R181: info->i = am29000->r[181]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R182: info->i = am29000->r[182]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R183: info->i = am29000->r[183]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R184: info->i = am29000->r[184]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R185: info->i = am29000->r[185]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R186: info->i = am29000->r[186]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R187: info->i = am29000->r[187]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R188: info->i = am29000->r[188]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R189: info->i = am29000->r[189]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R190: info->i = am29000->r[190]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R191: info->i = am29000->r[191]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R192: info->i = am29000->r[192]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R193: info->i = am29000->r[193]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R194: info->i = am29000->r[194]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R195: info->i = am29000->r[195]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R196: info->i = am29000->r[196]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R197: info->i = am29000->r[197]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R198: info->i = am29000->r[198]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R199: info->i = am29000->r[199]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R200: info->i = am29000->r[200]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R201: info->i = am29000->r[201]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R202: info->i = am29000->r[202]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R203: info->i = am29000->r[203]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R204: info->i = am29000->r[204]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R205: info->i = am29000->r[205]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R206: info->i = am29000->r[206]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R207: info->i = am29000->r[207]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R208: info->i = am29000->r[208]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R209: info->i = am29000->r[209]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R210: info->i = am29000->r[210]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R211: info->i = am29000->r[211]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R212: info->i = am29000->r[212]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R213: info->i = am29000->r[213]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R214: info->i = am29000->r[214]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R215: info->i = am29000->r[215]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R216: info->i = am29000->r[216]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R217: info->i = am29000->r[217]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R218: info->i = am29000->r[218]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R219: info->i = am29000->r[219]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R220: info->i = am29000->r[220]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R221: info->i = am29000->r[221]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R222: info->i = am29000->r[222]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R223: info->i = am29000->r[223]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R224: info->i = am29000->r[224]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R225: info->i = am29000->r[225]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R226: info->i = am29000->r[226]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R227: info->i = am29000->r[227]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R228: info->i = am29000->r[228]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R229: info->i = am29000->r[229]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R230: info->i = am29000->r[230]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R231: info->i = am29000->r[231]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R232: info->i = am29000->r[232]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R233: info->i = am29000->r[233]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R234: info->i = am29000->r[234]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R235: info->i = am29000->r[235]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R236: info->i = am29000->r[236]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R237: info->i = am29000->r[237]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R238: info->i = am29000->r[238]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R239: info->i = am29000->r[239]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R240: info->i = am29000->r[240]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R241: info->i = am29000->r[241]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R242: info->i = am29000->r[242]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R243: info->i = am29000->r[243]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R244: info->i = am29000->r[244]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R245: info->i = am29000->r[245]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R246: info->i = am29000->r[246]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R247: info->i = am29000->r[247]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R248: info->i = am29000->r[248]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R249: info->i = am29000->r[249]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R250: info->i = am29000->r[250]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R251: info->i = am29000->r[251]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R252: info->i = am29000->r[252]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R253: info->i = am29000->r[253]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R254: info->i = am29000->r[254]; break;
+ case CPUINFO_INT_REGISTER + AM29000_R255: info->i = am29000->r[255]; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(am29000); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(am29000); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(am29000); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(am29000); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(am29000); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(am29000); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &am29000->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "Am29000"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "AMD Am29000"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Philip Bennett"); break;
+
+ case CPUINFO_STR_FLAGS: sprintf(info->s, "%c%c%c%c%c%c%c%c%c|%3d", am29000->alu & ALU_V ? 'V' : '.',
+ am29000->alu & ALU_Z ? 'Z' : '.',
+ am29000->alu & ALU_N ? 'N' : '.',
+ am29000->alu & ALU_C ? 'C' : '.',
+
+ am29000->cps & CPS_IP ? 'I' : '.',
+ am29000->cps & CPS_FZ ? 'F' : '.',
+ am29000->cps & CPS_SM ? 'S' : 'U',
+ am29000->cps & CPS_DI ? 'I' : '.',
+ am29000->cps & CPS_DA ? 'D' : '.',
+ (am29000->r[1] >> 2) & 0x7f); break;
+
+ case CPUINFO_STR_REGISTER + AM29000_PC: sprintf(info->s, "PC: %08X", am29000->pc); break;
+ case CPUINFO_STR_REGISTER + AM29000_VAB: sprintf(info->s, "VAB: %08X", am29000->vab); break;
+ case CPUINFO_STR_REGISTER + AM29000_OPS: sprintf(info->s, "OPS: %08X", am29000->ops); break;
+ case CPUINFO_STR_REGISTER + AM29000_CPS: sprintf(info->s, "CPS: %08X", am29000->cps); break;
+ case CPUINFO_STR_REGISTER + AM29000_CFG: sprintf(info->s, "CFG: %08X", am29000->cfg); break;
+ case CPUINFO_STR_REGISTER + AM29000_CHA: sprintf(info->s, "CHA: %08X", am29000->cha); break;
+ case CPUINFO_STR_REGISTER + AM29000_CHD: sprintf(info->s, "CHD: %08X", am29000->chd); break;
+ case CPUINFO_STR_REGISTER + AM29000_CHC: sprintf(info->s, "CHC: %08X", am29000->chc); break;
+ case CPUINFO_STR_REGISTER + AM29000_RBP: sprintf(info->s, "RBP: %08X", am29000->rbp); break;
+ case CPUINFO_STR_REGISTER + AM29000_TMC: sprintf(info->s, "TMC: %08X", am29000->tmc); break;
+ case CPUINFO_STR_REGISTER + AM29000_TMR: sprintf(info->s, "TMR: %08X", am29000->tmr); break;
+ case CPUINFO_STR_REGISTER + AM29000_PC0: sprintf(info->s, "PC0: %08X", am29000->pc0); break;
+ case CPUINFO_STR_REGISTER + AM29000_PC1: sprintf(info->s, "PC1: %08X", am29000->pc1); break;
+ case CPUINFO_STR_REGISTER + AM29000_PC2: sprintf(info->s, "PC2: %08X", am29000->pc2); break;
+ case CPUINFO_STR_REGISTER + AM29000_MMU: sprintf(info->s, "MMU: %08X", am29000->mmu); break;
+ case CPUINFO_STR_REGISTER + AM29000_LRU: sprintf(info->s, "LRU: %08X", am29000->lru); break;
+ case CPUINFO_STR_REGISTER + AM29000_IPC: sprintf(info->s, "IPC: %08X", am29000->ipc); break;
+ case CPUINFO_STR_REGISTER + AM29000_IPA: sprintf(info->s, "IPA: %08X", am29000->ipa); break;
+ case CPUINFO_STR_REGISTER + AM29000_IPB: sprintf(info->s, "IPB: %08X", am29000->ipb); break;
+ case CPUINFO_STR_REGISTER + AM29000_Q: sprintf(info->s, "Q: %08X", am29000->q); break;
+ case CPUINFO_STR_REGISTER + AM29000_ALU: sprintf(info->s, "ALU: %08X", am29000->alu); break;
+ case CPUINFO_STR_REGISTER + AM29000_BP: sprintf(info->s, "BP: %08X", GET_ALU_BP); break;
+ case CPUINFO_STR_REGISTER + AM29000_FC: sprintf(info->s, "FC: %08X", GET_ALU_FC); break;
+ case CPUINFO_STR_REGISTER + AM29000_CR: sprintf(info->s, "CR: %08X", GET_CHC_CR); break;
+ case CPUINFO_STR_REGISTER + AM29000_FPE: sprintf(info->s, "FPE: %08X", am29000->fpe); break;
+ case CPUINFO_STR_REGISTER + AM29000_INTE: sprintf(info->s, "INTE: %08X", am29000->inte); break;
+ case CPUINFO_STR_REGISTER + AM29000_FPS: sprintf(info->s, "FPS: %08X", am29000->fps); break;
+ case CPUINFO_STR_REGISTER + AM29000_R1: sprintf(info->s, "R1: %08X", am29000->r[1]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R64: sprintf(info->s, "R64: %08X", am29000->r[64]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R65: sprintf(info->s, "R65: %08X", am29000->r[65]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R66: sprintf(info->s, "R66: %08X", am29000->r[66]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R67: sprintf(info->s, "R67: %08X", am29000->r[67]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R68: sprintf(info->s, "R68: %08X", am29000->r[68]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R69: sprintf(info->s, "R69: %08X", am29000->r[69]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R70: sprintf(info->s, "R70: %08X", am29000->r[70]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R71: sprintf(info->s, "R71: %08X", am29000->r[71]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R72: sprintf(info->s, "R72: %08X", am29000->r[72]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R73: sprintf(info->s, "R73: %08X", am29000->r[73]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R74: sprintf(info->s, "R74: %08X", am29000->r[74]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R75: sprintf(info->s, "R75: %08X", am29000->r[75]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R76: sprintf(info->s, "R76: %08X", am29000->r[76]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R77: sprintf(info->s, "R77: %08X", am29000->r[77]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R78: sprintf(info->s, "R78: %08X", am29000->r[78]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R79: sprintf(info->s, "R79: %08X", am29000->r[79]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R80: sprintf(info->s, "R80: %08X", am29000->r[80]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R81: sprintf(info->s, "R81: %08X", am29000->r[81]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R82: sprintf(info->s, "R82: %08X", am29000->r[82]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R83: sprintf(info->s, "R83: %08X", am29000->r[83]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R84: sprintf(info->s, "R84: %08X", am29000->r[84]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R85: sprintf(info->s, "R85: %08X", am29000->r[85]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R86: sprintf(info->s, "R86: %08X", am29000->r[86]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R87: sprintf(info->s, "R87: %08X", am29000->r[87]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R88: sprintf(info->s, "R88: %08X", am29000->r[88]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R89: sprintf(info->s, "R89: %08X", am29000->r[89]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R90: sprintf(info->s, "R90: %08X", am29000->r[90]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R91: sprintf(info->s, "R91: %08X", am29000->r[91]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R92: sprintf(info->s, "R92: %08X", am29000->r[92]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R93: sprintf(info->s, "R93: %08X", am29000->r[93]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R94: sprintf(info->s, "R94: %08X", am29000->r[94]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R95: sprintf(info->s, "R95: %08X", am29000->r[95]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R96: sprintf(info->s, "R96: %08X", am29000->r[96]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R97: sprintf(info->s, "R97: %08X", am29000->r[97]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R98: sprintf(info->s, "R98: %08X", am29000->r[98]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R99: sprintf(info->s, "R99: %08X", am29000->r[99]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R100: sprintf(info->s, "R100: %08X", am29000->r[100]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R101: sprintf(info->s, "R101: %08X", am29000->r[101]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R102: sprintf(info->s, "R102: %08X", am29000->r[102]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R103: sprintf(info->s, "R103: %08X", am29000->r[103]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R104: sprintf(info->s, "R104: %08X", am29000->r[104]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R105: sprintf(info->s, "R105: %08X", am29000->r[105]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R106: sprintf(info->s, "R106: %08X", am29000->r[106]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R107: sprintf(info->s, "R107: %08X", am29000->r[107]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R108: sprintf(info->s, "R108: %08X", am29000->r[108]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R109: sprintf(info->s, "R109: %08X", am29000->r[109]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R110: sprintf(info->s, "R110: %08X", am29000->r[110]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R111: sprintf(info->s, "R111: %08X", am29000->r[111]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R112: sprintf(info->s, "R112: %08X", am29000->r[112]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R113: sprintf(info->s, "R113: %08X", am29000->r[113]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R114: sprintf(info->s, "R114: %08X", am29000->r[114]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R115: sprintf(info->s, "R115: %08X", am29000->r[115]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R116: sprintf(info->s, "R116: %08X", am29000->r[116]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R117: sprintf(info->s, "R117: %08X", am29000->r[117]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R118: sprintf(info->s, "R118: %08X", am29000->r[118]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R119: sprintf(info->s, "R119: %08X", am29000->r[119]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R120: sprintf(info->s, "R120: %08X", am29000->r[120]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R121: sprintf(info->s, "R121: %08X", am29000->r[121]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R122: sprintf(info->s, "R122: %08X", am29000->r[122]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R123: sprintf(info->s, "R123: %08X", am29000->r[123]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R124: sprintf(info->s, "R124: %08X", am29000->r[124]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R125: sprintf(info->s, "R125: %08X", am29000->r[125]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R126: sprintf(info->s, "R126: %08X", am29000->r[126]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R127: sprintf(info->s, "R127: %08X", am29000->r[127]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R128: sprintf(info->s, "R128: %08X", am29000->r[128]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R129: sprintf(info->s, "R129: %08X", am29000->r[129]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R130: sprintf(info->s, "R130: %08X", am29000->r[130]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R131: sprintf(info->s, "R131: %08X", am29000->r[131]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R132: sprintf(info->s, "R132: %08X", am29000->r[132]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R133: sprintf(info->s, "R133: %08X", am29000->r[133]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R134: sprintf(info->s, "R134: %08X", am29000->r[134]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R135: sprintf(info->s, "R135: %08X", am29000->r[135]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R136: sprintf(info->s, "R136: %08X", am29000->r[136]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R137: sprintf(info->s, "R137: %08X", am29000->r[137]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R138: sprintf(info->s, "R138: %08X", am29000->r[138]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R139: sprintf(info->s, "R139: %08X", am29000->r[139]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R140: sprintf(info->s, "R140: %08X", am29000->r[140]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R141: sprintf(info->s, "R141: %08X", am29000->r[141]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R142: sprintf(info->s, "R142: %08X", am29000->r[142]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R143: sprintf(info->s, "R143: %08X", am29000->r[143]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R144: sprintf(info->s, "R144: %08X", am29000->r[144]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R145: sprintf(info->s, "R145: %08X", am29000->r[145]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R146: sprintf(info->s, "R146: %08X", am29000->r[146]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R147: sprintf(info->s, "R147: %08X", am29000->r[147]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R148: sprintf(info->s, "R148: %08X", am29000->r[148]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R149: sprintf(info->s, "R149: %08X", am29000->r[149]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R150: sprintf(info->s, "R150: %08X", am29000->r[150]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R151: sprintf(info->s, "R151: %08X", am29000->r[151]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R152: sprintf(info->s, "R152: %08X", am29000->r[152]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R153: sprintf(info->s, "R153: %08X", am29000->r[153]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R154: sprintf(info->s, "R154: %08X", am29000->r[154]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R155: sprintf(info->s, "R155: %08X", am29000->r[155]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R156: sprintf(info->s, "R156: %08X", am29000->r[156]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R157: sprintf(info->s, "R157: %08X", am29000->r[157]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R158: sprintf(info->s, "R158: %08X", am29000->r[158]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R159: sprintf(info->s, "R159: %08X", am29000->r[159]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R160: sprintf(info->s, "R160: %08X", am29000->r[160]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R161: sprintf(info->s, "R161: %08X", am29000->r[161]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R162: sprintf(info->s, "R162: %08X", am29000->r[162]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R163: sprintf(info->s, "R163: %08X", am29000->r[163]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R164: sprintf(info->s, "R164: %08X", am29000->r[164]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R165: sprintf(info->s, "R165: %08X", am29000->r[165]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R166: sprintf(info->s, "R166: %08X", am29000->r[166]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R167: sprintf(info->s, "R167: %08X", am29000->r[167]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R168: sprintf(info->s, "R168: %08X", am29000->r[168]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R169: sprintf(info->s, "R169: %08X", am29000->r[169]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R170: sprintf(info->s, "R170: %08X", am29000->r[170]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R171: sprintf(info->s, "R171: %08X", am29000->r[171]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R172: sprintf(info->s, "R172: %08X", am29000->r[172]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R173: sprintf(info->s, "R173: %08X", am29000->r[173]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R174: sprintf(info->s, "R174: %08X", am29000->r[174]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R175: sprintf(info->s, "R175: %08X", am29000->r[175]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R176: sprintf(info->s, "R176: %08X", am29000->r[176]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R177: sprintf(info->s, "R177: %08X", am29000->r[177]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R178: sprintf(info->s, "R178: %08X", am29000->r[178]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R179: sprintf(info->s, "R179: %08X", am29000->r[179]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R180: sprintf(info->s, "R180: %08X", am29000->r[180]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R181: sprintf(info->s, "R181: %08X", am29000->r[181]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R182: sprintf(info->s, "R182: %08X", am29000->r[182]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R183: sprintf(info->s, "R183: %08X", am29000->r[183]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R184: sprintf(info->s, "R184: %08X", am29000->r[184]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R185: sprintf(info->s, "R185: %08X", am29000->r[185]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R186: sprintf(info->s, "R186: %08X", am29000->r[186]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R187: sprintf(info->s, "R187: %08X", am29000->r[187]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R188: sprintf(info->s, "R188: %08X", am29000->r[188]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R189: sprintf(info->s, "R189: %08X", am29000->r[189]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R190: sprintf(info->s, "R190: %08X", am29000->r[190]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R191: sprintf(info->s, "R191: %08X", am29000->r[191]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R192: sprintf(info->s, "R192: %08X", am29000->r[192]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R193: sprintf(info->s, "R193: %08X", am29000->r[193]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R194: sprintf(info->s, "R194: %08X", am29000->r[194]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R195: sprintf(info->s, "R195: %08X", am29000->r[195]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R196: sprintf(info->s, "R196: %08X", am29000->r[196]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R197: sprintf(info->s, "R197: %08X", am29000->r[197]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R198: sprintf(info->s, "R198: %08X", am29000->r[198]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R199: sprintf(info->s, "R199: %08X", am29000->r[199]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R200: sprintf(info->s, "R200: %08X", am29000->r[200]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R201: sprintf(info->s, "R201: %08X", am29000->r[201]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R202: sprintf(info->s, "R202: %08X", am29000->r[202]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R203: sprintf(info->s, "R203: %08X", am29000->r[203]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R204: sprintf(info->s, "R204: %08X", am29000->r[204]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R205: sprintf(info->s, "R205: %08X", am29000->r[205]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R206: sprintf(info->s, "R206: %08X", am29000->r[206]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R207: sprintf(info->s, "R207: %08X", am29000->r[207]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R208: sprintf(info->s, "R208: %08X", am29000->r[208]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R209: sprintf(info->s, "R209: %08X", am29000->r[209]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R210: sprintf(info->s, "R210: %08X", am29000->r[210]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R211: sprintf(info->s, "R211: %08X", am29000->r[211]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R212: sprintf(info->s, "R212: %08X", am29000->r[212]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R213: sprintf(info->s, "R213: %08X", am29000->r[213]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R214: sprintf(info->s, "R214: %08X", am29000->r[214]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R215: sprintf(info->s, "R215: %08X", am29000->r[215]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R216: sprintf(info->s, "R216: %08X", am29000->r[216]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R217: sprintf(info->s, "R217: %08X", am29000->r[217]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R218: sprintf(info->s, "R218: %08X", am29000->r[218]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R219: sprintf(info->s, "R219: %08X", am29000->r[219]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R220: sprintf(info->s, "R220: %08X", am29000->r[220]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R221: sprintf(info->s, "R221: %08X", am29000->r[221]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R222: sprintf(info->s, "R222: %08X", am29000->r[222]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R223: sprintf(info->s, "R223: %08X", am29000->r[223]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R224: sprintf(info->s, "R224: %08X", am29000->r[224]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R225: sprintf(info->s, "R225: %08X", am29000->r[225]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R226: sprintf(info->s, "R226: %08X", am29000->r[226]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R227: sprintf(info->s, "R227: %08X", am29000->r[227]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R228: sprintf(info->s, "R228: %08X", am29000->r[228]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R229: sprintf(info->s, "R229: %08X", am29000->r[229]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R230: sprintf(info->s, "R230: %08X", am29000->r[230]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R231: sprintf(info->s, "R231: %08X", am29000->r[231]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R232: sprintf(info->s, "R232: %08X", am29000->r[232]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R233: sprintf(info->s, "R233: %08X", am29000->r[233]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R234: sprintf(info->s, "R234: %08X", am29000->r[234]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R235: sprintf(info->s, "R235: %08X", am29000->r[235]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R236: sprintf(info->s, "R236: %08X", am29000->r[236]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R237: sprintf(info->s, "R237: %08X", am29000->r[237]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R238: sprintf(info->s, "R238: %08X", am29000->r[238]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R239: sprintf(info->s, "R239: %08X", am29000->r[239]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R240: sprintf(info->s, "R240: %08X", am29000->r[240]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R241: sprintf(info->s, "R241: %08X", am29000->r[241]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R242: sprintf(info->s, "R242: %08X", am29000->r[242]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R243: sprintf(info->s, "R243: %08X", am29000->r[243]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R244: sprintf(info->s, "R244: %08X", am29000->r[244]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R245: sprintf(info->s, "R245: %08X", am29000->r[245]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R246: sprintf(info->s, "R246: %08X", am29000->r[246]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R247: sprintf(info->s, "R247: %08X", am29000->r[247]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R248: sprintf(info->s, "R248: %08X", am29000->r[248]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R249: sprintf(info->s, "R249: %08X", am29000->r[249]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R250: sprintf(info->s, "R250: %08X", am29000->r[250]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R251: sprintf(info->s, "R251: %08X", am29000->r[251]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R252: sprintf(info->s, "R252: %08X", am29000->r[252]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R253: sprintf(info->s, "R253: %08X", am29000->r[253]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R254: sprintf(info->s, "R254: %08X", am29000->r[254]); break;
+ case CPUINFO_STR_REGISTER + AM29000_R255: sprintf(info->s, "R255: %08X", am29000->r[255]); break;
+ }
+}
+
+
+DEFINE_LEGACY_CPU_DEVICE(AM29000, am29000);
diff --git a/trunk/src/emu/cpu/am29000/am29000.h b/trunk/src/emu/cpu/am29000/am29000.h
new file mode 100644
index 00000000000..69e82382fed
--- /dev/null
+++ b/trunk/src/emu/cpu/am29000/am29000.h
@@ -0,0 +1,438 @@
+/***************************************************************************
+
+ am29000.h
+ Interface file for the portable AMD Am29000 emulator.
+ Written by Phil Bennett
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __AM29000_H__
+#define __AM29000_H__
+
+
+/***************************************************************************
+ REGISTER ENUMERATION
+***************************************************************************/
+
+enum
+{
+ AM29000_PC = 1,
+ AM29000_VAB,
+ AM29000_OPS,
+ AM29000_CPS,
+ AM29000_CFG,
+ AM29000_CHA,
+ AM29000_CHD,
+ AM29000_CHC,
+ AM29000_RBP,
+ AM29000_TMC,
+ AM29000_TMR,
+ AM29000_PC0,
+ AM29000_PC1,
+ AM29000_PC2,
+ AM29000_MMU,
+ AM29000_LRU,
+ AM29000_IPC,
+ AM29000_IPA,
+ AM29000_IPB,
+ AM29000_Q,
+ AM29000_ALU,
+ AM29000_BP,
+ AM29000_FC,
+ AM29000_CR,
+ AM29000_FPE,
+ AM29000_INTE,
+ AM29000_FPS,
+ AM29000_R1,
+ AM29000_R64,
+ AM29000_R65,
+ AM29000_R66,
+ AM29000_R67,
+ AM29000_R68,
+ AM29000_R69,
+ AM29000_R70,
+ AM29000_R71,
+ AM29000_R72,
+ AM29000_R73,
+ AM29000_R74,
+ AM29000_R75,
+ AM29000_R76,
+ AM29000_R77,
+ AM29000_R78,
+ AM29000_R79,
+ AM29000_R80,
+ AM29000_R81,
+ AM29000_R82,
+ AM29000_R83,
+ AM29000_R84,
+ AM29000_R85,
+ AM29000_R86,
+ AM29000_R87,
+ AM29000_R88,
+ AM29000_R89,
+ AM29000_R90,
+ AM29000_R91,
+ AM29000_R92,
+ AM29000_R93,
+ AM29000_R94,
+ AM29000_R95,
+ AM29000_R96,
+ AM29000_R97,
+ AM29000_R98,
+ AM29000_R99,
+ AM29000_R100,
+ AM29000_R101,
+ AM29000_R102,
+ AM29000_R103,
+ AM29000_R104,
+ AM29000_R105,
+ AM29000_R106,
+ AM29000_R107,
+ AM29000_R108,
+ AM29000_R109,
+ AM29000_R110,
+ AM29000_R111,
+ AM29000_R112,
+ AM29000_R113,
+ AM29000_R114,
+ AM29000_R115,
+ AM29000_R116,
+ AM29000_R117,
+ AM29000_R118,
+ AM29000_R119,
+ AM29000_R120,
+ AM29000_R121,
+ AM29000_R122,
+ AM29000_R123,
+ AM29000_R124,
+ AM29000_R125,
+ AM29000_R126,
+ AM29000_R127,
+ AM29000_R128,
+ AM29000_R129,
+ AM29000_R130,
+ AM29000_R131,
+ AM29000_R132,
+ AM29000_R133,
+ AM29000_R134,
+ AM29000_R135,
+ AM29000_R136,
+ AM29000_R137,
+ AM29000_R138,
+ AM29000_R139,
+ AM29000_R140,
+ AM29000_R141,
+ AM29000_R142,
+ AM29000_R143,
+ AM29000_R144,
+ AM29000_R145,
+ AM29000_R146,
+ AM29000_R147,
+ AM29000_R148,
+ AM29000_R149,
+ AM29000_R150,
+ AM29000_R151,
+ AM29000_R152,
+ AM29000_R153,
+ AM29000_R154,
+ AM29000_R155,
+ AM29000_R156,
+ AM29000_R157,
+ AM29000_R158,
+ AM29000_R159,
+ AM29000_R160,
+ AM29000_R161,
+ AM29000_R162,
+ AM29000_R163,
+ AM29000_R164,
+ AM29000_R165,
+ AM29000_R166,
+ AM29000_R167,
+ AM29000_R168,
+ AM29000_R169,
+ AM29000_R170,
+ AM29000_R171,
+ AM29000_R172,
+ AM29000_R173,
+ AM29000_R174,
+ AM29000_R175,
+ AM29000_R176,
+ AM29000_R177,
+ AM29000_R178,
+ AM29000_R179,
+ AM29000_R180,
+ AM29000_R181,
+ AM29000_R182,
+ AM29000_R183,
+ AM29000_R184,
+ AM29000_R185,
+ AM29000_R186,
+ AM29000_R187,
+ AM29000_R188,
+ AM29000_R189,
+ AM29000_R190,
+ AM29000_R191,
+ AM29000_R192,
+ AM29000_R193,
+ AM29000_R194,
+ AM29000_R195,
+ AM29000_R196,
+ AM29000_R197,
+ AM29000_R198,
+ AM29000_R199,
+ AM29000_R200,
+ AM29000_R201,
+ AM29000_R202,
+ AM29000_R203,
+ AM29000_R204,
+ AM29000_R205,
+ AM29000_R206,
+ AM29000_R207,
+ AM29000_R208,
+ AM29000_R209,
+ AM29000_R210,
+ AM29000_R211,
+ AM29000_R212,
+ AM29000_R213,
+ AM29000_R214,
+ AM29000_R215,
+ AM29000_R216,
+ AM29000_R217,
+ AM29000_R218,
+ AM29000_R219,
+ AM29000_R220,
+ AM29000_R221,
+ AM29000_R222,
+ AM29000_R223,
+ AM29000_R224,
+ AM29000_R225,
+ AM29000_R226,
+ AM29000_R227,
+ AM29000_R228,
+ AM29000_R229,
+ AM29000_R230,
+ AM29000_R231,
+ AM29000_R232,
+ AM29000_R233,
+ AM29000_R234,
+ AM29000_R235,
+ AM29000_R236,
+ AM29000_R237,
+ AM29000_R238,
+ AM29000_R239,
+ AM29000_R240,
+ AM29000_R241,
+ AM29000_R242,
+ AM29000_R243,
+ AM29000_R244,
+ AM29000_R245,
+ AM29000_R246,
+ AM29000_R247,
+ AM29000_R248,
+ AM29000_R249,
+ AM29000_R250,
+ AM29000_R251,
+ AM29000_R252,
+ AM29000_R253,
+ AM29000_R254,
+ AM29000_R255
+};
+
+
+/***************************************************************************
+ SPECIAL PURPOSE REGISTER INDICES
+***************************************************************************/
+
+enum
+{ SPR_VAB = 0,
+ SPR_OPS = 1,
+ SPR_CPS = 2,
+ SPR_CFG = 3,
+ SPR_CHA = 4,
+ SPR_CHD = 5,
+ SPR_CHC = 6,
+ SPR_RBP = 7,
+ SPR_TMC = 8,
+ SPR_TMR = 9,
+ SPR_PC0 = 10,
+ SPR_PC1 = 11,
+ SPR_PC2 = 12,
+ SPR_MMU = 13,
+ SPR_LRU = 14,
+ SPR_IPC = 128,
+ SPR_IPA = 129,
+ SPR_IPB = 130,
+ SPR_Q = 131,
+ SPR_ALU = 132,
+ SPR_BP = 133,
+ SPR_FC = 134,
+ SPR_CR = 135,
+ SPR_FPE = 160,
+ SPR_INTE = 161,
+ SPR_FPS = 162,
+};
+
+
+enum
+{
+ SPACE_INSTRUCTION = 0,
+ SPACE_DATA,
+ SPACE_IO,
+ SPACE_COPROCESSOR,
+};
+
+
+/***************************************************************************
+ EXCEPTION VECTORS
+***************************************************************************/
+
+enum
+{
+ EXCEPTION_ILLEGAL_OPCODE = 0,
+ EXCEPTION_UNALIGNED_ACCESS = 1,
+ EXCEPTION_OUT_OF_RANGE = 2,
+ EXCEPTION_COPRO_NOT_PRESENT = 3,
+ EXCEPTION_COPRO_EXCEPTION = 4,
+ EXCEPTION_PROTECTION_VIOLATION = 5,
+ EXCEPTION_INST_ACCESS_VIOLATION = 6,
+ EXCEPTION_DATA_ACCESS_VIOLATION = 7,
+ EXCEPTION_USER_INST_TLB_MISS = 8,
+ EXCEPTION_USER_DATA_TLB_MISS = 9,
+ EXCEPTION_SUPER_INST_TLB_MISS = 10,
+ EXCEPTION_SUPER_DATA_TLB_MISS = 11,
+ EXCEPTION_INST_TLB_PROT_VIOLATION = 12,
+ EXCEPTION_DATA_TLB_PROT_VIOLATION = 13,
+ EXCEPTION_TIMER = 14,
+ EXCEPTION_TRACE = 15,
+ EXCEPTION_INTR0 = 16,
+ EXCEPTION_INTR1 = 17,
+ EXCEPTION_INTR2 = 18,
+ EXCEPTION_INTR3 = 19,
+ EXCEPTION_TRAP0 = 20,
+ EXCEPTION_TRAP1 = 21,
+ EXCEPTION_FLOATING_POINT_EXCEPTION = 22,
+ EXCEPTION_MULTM = 30,
+ EXCEPTION_MULTMU = 31,
+ EXCEPTION_MULTIPLY = 32,
+ EXCEPTION_DIVIDE = 33,
+ EXCEPTION_MULTIPLU = 44, // TODO: FINISH ME
+};
+
+
+/***************************************************************************
+ SPECIAL PURPOSE REGISTER FIELDS
+***************************************************************************/
+
+#define PRL_AM29000 (0 << 3)
+#define PRL_AM29050 (1 << 3)
+#define PRL_REV_A (0)
+#define PRL_REV_B (1)
+#define PRL_REV_C (2)
+#define PRL_REV_D (3)
+
+#define PROCESSOR_REL_FIELD (PRL_AM29000 | PRL_REV_D)
+
+#define VAB_SHIFT (16)
+#define VAB_MASK (0xffff)
+
+#define CPS_CA (1 << 15)
+#define CPS_IP (1 << 14)
+#define CPS_TE (1 << 13)
+#define CPS_TP (1 << 12)
+#define CPS_TU (1 << 11)
+#define CPS_FZ (1 << 10)
+#define CPS_LK (1 << 9)
+#define CPS_RE (1 << 8)
+#define CPS_WM (1 << 7)
+#define CPS_PD (1 << 6)
+#define CPS_PI (1 << 5)
+#define CPS_SM (1 << 4)
+#define CPS_IM_SHIFT (2)
+#define CPS_IM_MASK (3)
+#define CPS_DI (1 << 1)
+#define CPS_DA (1 << 0)
+
+#define CFG_PRL_MASK (0xff)
+#define CFG_PRL_SHIFT (24)
+#define CFG_DW (1 << 5)
+#define CFG_VF (1 << 4)
+#define CFG_RV (1 << 3)
+#define CFG_BO (1 << 2)
+#define CFG_CP (1 << 1)
+#define CFG_CD (1 << 0)
+
+#define CHC_CE_CNTL_MASK (0xff)
+#define CHC_CE_CNTL_SHIFT (24)
+#define CHC_CR_MASK (0xff)
+#define CHC_CR_SHIFT (16)
+#define CHC_LS (1 << 15)
+#define CHC_ML (1 << 14)
+#define CHC_ST (1 << 13)
+#define CHC_LA (1 << 12)
+#define CHC_TF (1 << 11)
+#define CHC_TR_MASK (0xff)
+#define CHC_TR_SHIFT (2)
+#define CHC_NN (1 << 1)
+#define CHC_CV (1 << 0)
+
+#define RBP_MASK (0xffff)
+
+#define TCV_MASK (0x00ffffff)
+#define TCV_SHIFT (0)
+
+#define TMR_OV (1 << 26)
+#define TMR_IN (1 << 25)
+#define TMR_IE (1 << 24)
+#define TMR_TRV_MASK (0x00ffffff)
+#define TMR_TRV_SHIFT (0)
+
+#define PC_MASK (0xfffffffc)
+
+#define MMU_PS_MASK (3)
+#define MMU_PS_SHIFT (8)
+#define MMU_PID_MASK (0xff)
+#define MMU_PID_SHIFT (0)
+
+#define LRU_MASK (0x3f)
+#define LRU_SHIFT (1)
+
+#define ALU_DF_SHIFT (11)
+#define ALU_DF (1 << 11)
+#define ALU_V_SHIFT (10)
+#define ALU_V (1 << 10)
+#define ALU_N_SHIFT (9)
+#define ALU_N (1 << 9)
+#define ALU_Z_SHIFT (8)
+#define ALU_Z (1 << 8)
+#define ALU_C_SHIFT (7)
+#define ALU_C (1 << 7)
+#define ALU_BP_MASK (3)
+#define ALU_BP_SHIFT (5)
+#define ALU_FC_MASK (0x1f)
+#define ALU_FC_SHIFT (0)
+
+#define IPX_MASK (0xff)
+#define IPX_SHIFT (2)
+
+
+
+
+/***************************************************************************
+ INTERRUPT CONSTANTS
+***************************************************************************/
+
+#define AM29000_INTR0 0
+#define AM29000_INTR1 1
+#define AM29000_INTR2 2
+#define AM29000_INTR3 3
+
+
+/***************************************************************************
+ PUBLIC FUNCTIONS
+***************************************************************************/
+
+DECLARE_LEGACY_CPU_DEVICE(AM29000, am29000);
+
+#endif /* __AM29000_H__ */
diff --git a/trunk/src/emu/cpu/am29000/am29dasm.c b/trunk/src/emu/cpu/am29000/am29dasm.c
new file mode 100644
index 00000000000..270cc340a3d
--- /dev/null
+++ b/trunk/src/emu/cpu/am29000/am29dasm.c
@@ -0,0 +1,257 @@
+/***************************************************************************
+
+ am29dasm.c
+ Disassembler for the portable Am29000 emulator.
+ Written by Phil Bennett
+
+***************************************************************************/
+
+#include "emu.h"
+#include "am29000.h"
+
+
+/***************************************************************************
+ DEFINES AND MACROS
+***************************************************************************/
+
+#define OP_M_BIT (1 << 24)
+#define OP_RC ((op >> 16) & 0xff)
+#define OP_RA ((op >> 8) & 0xff)
+#define OP_RB (op & 0xff)
+#define OP_I8 (op & 0xff)
+#define OP_SA ((op >> 8) & 0xff)
+#define OP_I16 (((op >> 8) & 0xff00) | (op & 0xff))
+#define OP_IJMP (OP_I16 << 2)
+#define OP_VN ((op >> 16) & 0xff)
+
+#define OP_CE ((op >> 23) & 1)
+#define OP_CNTL ((op >> 16) & 0x7f)
+
+#define OP_SJMP ((INT32)(INT16)OP_I16 << 2)
+
+
+/***************************************************************************
+ CODE
+***************************************************************************/
+
+static const char *dasm_type1(UINT32 op)
+{
+ static char buf[32];
+
+ if (op & OP_M_BIT)
+ sprintf(buf, "r%d, r%d, $%.2x", OP_RC, OP_RA, OP_I8);
+ else
+ sprintf(buf, "r%d, r%d, r%d", OP_RC, OP_RA, OP_RB);
+
+ return buf;
+}
+
+static const char *dasm_type2(UINT32 op)
+{
+ static char buf[32];
+
+ sprintf(buf, "r%d, r%d, r%d", OP_RC, OP_RA, OP_RB);
+
+ return buf;
+}
+
+static const char *dasm_type3(UINT32 op)
+{
+ static char buf[32];
+
+ sprintf(buf, "r%d, $%.4x", OP_RA, OP_I16);
+
+ return buf;
+}
+
+static const char *dasm_type4(UINT32 op, UINT32 pc)
+{
+ static char buf[32];
+
+ if (op & OP_M_BIT)
+ sprintf(buf, "r%d, $%.4x", OP_RA, OP_IJMP);
+ else
+ sprintf(buf, "r%d, $%.4x", OP_RA, pc + OP_SJMP);
+
+ return buf;
+}
+
+static const char *dasm_type5(UINT32 op)
+{
+ static char buf[32];
+
+ if (op & OP_M_BIT)
+ sprintf(buf, "trap%d, r%d, $%.2x", OP_VN, OP_RA, OP_I8);
+ else
+ sprintf(buf, "trap%d, r%d, r%d", OP_VN, OP_RA, OP_RB);
+
+ return buf;
+}
+
+static const char *dasm_type6(UINT32 op)
+{
+ static char buf[32];
+
+ if (op & OP_M_BIT)
+ sprintf(buf, "%d, %x, r%d, $%.2x", OP_CE, OP_CNTL, OP_RA, OP_I8);
+ else
+ sprintf(buf, "%d, %x, r%d, r%d", OP_CE, OP_CNTL, OP_RA, OP_RB);
+
+ return buf;
+}
+
+#define TYPE_1 dasm_type1(op)
+#define TYPE_2 dasm_type2(op)
+#define TYPE_3 dasm_type3(op)
+#define TYPE_4 dasm_type4(op, pc)
+#define TYPE_5 dasm_type5(op)
+#define TYPE_6 dasm_type6(op)
+
+
+static const char* get_spr(int spid)
+{
+ switch (spid)
+ {
+ case 0: return "VAB";
+ case 1: return "OPS";
+ case 2: return "CPS";
+ case 3: return "CFG";
+ case 4: return "CHA";
+ case 5: return "CHD";
+ case 6: return "CHC";
+ case 7: return "RBP";
+ case 8: return "TMC";
+ case 9: return "TMR";
+ case 10: return "PC0";
+ case 11: return "PC1";
+ case 12: return "PC2";
+ case 13: return "MMU";
+ case 14: return "LRU";
+ case 128: return "IPC";
+ case 129: return "IPA";
+ case 130: return "IPB";
+ case 131: return "Q";
+ case 132: return "ALU";
+ case 133: return "BP";
+ case 134: return "FC";
+ case 135: return "CR";
+ case 160: return "FPE";
+ case 161: return "INTE";
+ case 162: return "FPS";
+ case 164: return "EXOP";
+ default: return "????";
+ }
+}
+
+CPU_DISASSEMBLE( am29000 )
+{
+ UINT32 op = (oprom[0] << 24) | (oprom[1] << 16) | (oprom[2] << 8) | oprom[3];
+ UINT32 flags = 0;
+
+ switch (op >> 24)
+ {
+ case 0x01: sprintf(buffer, "constn %s", TYPE_3); break;
+ case 0x02: sprintf(buffer, "consth %s", TYPE_3); break;
+ case 0x03: sprintf(buffer, "const %s", TYPE_3); break;
+ case 0x04: sprintf(buffer, "mtsrim %s, $%.4x", get_spr(OP_SA), OP_I16); break;
+ case 0x06: case 0x07: sprintf(buffer, "loadl %s", TYPE_6); break;
+ case 0x08: sprintf(buffer, "clz r%d, %d", OP_RC, OP_RB); break;
+ case 0x09: sprintf(buffer, "clz %d, %.2x", OP_RC, OP_I8); break;
+ case 0x0a: case 0x0b: sprintf(buffer, "exbyte %s", TYPE_1); break;
+ case 0x0c: case 0x0d: sprintf(buffer, "inbyte %s", TYPE_1); break;
+ case 0x0e: case 0x0f: sprintf(buffer, "storel %s", TYPE_6); break;
+ case 0x10: case 0x11: sprintf(buffer, "adds %s", TYPE_1); break;
+ case 0x12: case 0x13: sprintf(buffer, "addu %s", TYPE_1); break;
+ case 0x14: case 0x15: sprintf(buffer, "add %s", TYPE_1); break;
+ case 0x16: case 0x17: sprintf(buffer, "load %s", TYPE_6); break;
+ case 0x18: case 0x19: sprintf(buffer, "addcs %s", TYPE_1); break;
+ case 0x1a: case 0x1b: sprintf(buffer, "addcu %s", TYPE_1); break;
+ case 0x1c: case 0x1d: sprintf(buffer, "addc %s", TYPE_1); break;
+ case 0x1e: case 0x1f: sprintf(buffer, "store %s", TYPE_6); break;
+ case 0x20: case 0x21: sprintf(buffer, "subs %s", TYPE_1); break;
+ case 0x22: case 0x23: sprintf(buffer, "subu %s", TYPE_1); break;
+ case 0x24: case 0x25: sprintf(buffer, "sub %s", TYPE_1); break;
+ case 0x26: case 0x27: sprintf(buffer, "loadset %s", TYPE_6); break;
+ case 0x28: case 0x29: sprintf(buffer, "subcs %s", TYPE_1); break;
+ case 0x2a: case 0x2b: sprintf(buffer, "subcu %s", TYPE_1); break;
+ case 0x2c: case 0x2d: sprintf(buffer, "subc %s", TYPE_1); break;
+ case 0x2e: case 0x2f: sprintf(buffer, "cpbyte %s", TYPE_1); break;
+ case 0x30: case 0x31: sprintf(buffer, "subrs %s", TYPE_1); break;
+ case 0x32: case 0x33: sprintf(buffer, "subru %s", TYPE_1); break;
+ case 0x34: case 0x35: sprintf(buffer, "subr %s", TYPE_1); break;
+ case 0x36: case 0x37: sprintf(buffer, "loadm %s", TYPE_6); break;
+ case 0x38: case 0x39: sprintf(buffer, "subrcs %s", TYPE_1); break;
+ case 0x3a: case 0x3b: sprintf(buffer, "subrcu %s", TYPE_1); break;
+ case 0x3c: case 0x3d: sprintf(buffer, "subrc %s", TYPE_1); break;
+ case 0x3e: case 0x3f: sprintf(buffer, "storem %s", TYPE_6); break;
+ case 0x40: case 0x41: sprintf(buffer, "cplt %s", TYPE_1); break;
+ case 0x42: case 0x43: sprintf(buffer, "cpltu %s", TYPE_1); break;
+ case 0x44: case 0x45: sprintf(buffer, "cple %s", TYPE_1); break;
+ case 0x46: case 0x47: sprintf(buffer, "cpleu %s", TYPE_1); break;
+ case 0x48: case 0x49: sprintf(buffer, "cpgt %s", TYPE_1); break;
+ case 0x4a: case 0x4b: sprintf(buffer, "cpgtu %s", TYPE_1); break;
+ case 0x4c: case 0x4d: sprintf(buffer, "cpge %s", TYPE_1); break;
+ case 0x4e: case 0x4f: sprintf(buffer, "cpgeu %s", TYPE_1); break;
+ case 0x50: case 0x51: sprintf(buffer, "aslt %s", TYPE_5); break;
+ case 0x52: case 0x53: sprintf(buffer, "asltu %s", TYPE_5); break;
+ case 0x54: case 0x55: sprintf(buffer, "asle %s", TYPE_5); break;
+ case 0x56: case 0x57: sprintf(buffer, "asleu %s", TYPE_5); break;
+ case 0x58: case 0x59: sprintf(buffer, "asgt %s", TYPE_5); break;
+ case 0x5a: case 0x5b: sprintf(buffer, "asgtu %s", TYPE_5); break;
+ case 0x5c: case 0x5d: sprintf(buffer, "asge %s", TYPE_5); break;
+ case 0x5e: case 0x5f: sprintf(buffer, "asgeu %s", TYPE_5); break;
+ case 0x60: case 0x61: sprintf(buffer, "cpeq %s", TYPE_1); break;
+ case 0x62: case 0x63: sprintf(buffer, "cpneq %s", TYPE_1); break;
+ case 0x64: case 0x65: sprintf(buffer, "mul %s", TYPE_1); break;
+ case 0x66: case 0x67: sprintf(buffer, "mull %s", TYPE_1); break;
+ case 0x68: sprintf(buffer, "div0 r%d, r%d", OP_RC, OP_RB); break;
+ case 0x69: sprintf(buffer, "div0 r%d, %.2x", OP_RC, OP_I8); break;
+ case 0x6a: case 0x6b: sprintf(buffer, "div %s", TYPE_1); break;
+ case 0x6c: case 0x6d: sprintf(buffer, "divl %s", TYPE_1); break;
+ case 0x6e: case 0x6f: sprintf(buffer, "divrem %s", TYPE_1); break;
+ case 0x70: case 0x71: sprintf(buffer, "aseq %s", TYPE_5); break;
+ case 0x72: case 0x73: sprintf(buffer, "asneq %s", TYPE_5); break;
+ case 0x74: case 0x75: sprintf(buffer, "mulu %s", TYPE_1); break;
+ case 0x78: case 0x79: sprintf(buffer, "inhw %s", TYPE_1); break;
+ case 0x7a: case 0x7b: sprintf(buffer, "extract %s", TYPE_1); break;
+ case 0x7c: case 0x7d: sprintf(buffer, "exhw %s", TYPE_1); break;
+ case 0x7e: sprintf(buffer, "exhws %s", TYPE_1); break;
+ case 0x80: case 0x81: sprintf(buffer, "sll %s", TYPE_1); break;
+ case 0x82: case 0x83: sprintf(buffer, "srl %s", TYPE_1); break;
+ case 0x86: case 0x87: sprintf(buffer, "sra %s", TYPE_1); break;
+ case 0x88: sprintf(buffer, "iret"); break;
+ case 0x89: sprintf(buffer, "halt"); break;
+ case 0x8c: sprintf(buffer, "iretinv"); break;
+ case 0x90: case 0x91: sprintf(buffer, "and %s", TYPE_1); break;
+ case 0x92: case 0x93: sprintf(buffer, "or %s", TYPE_1); break;
+ case 0x94: case 0x95: sprintf(buffer, "xor %s", TYPE_1); break;
+ case 0x96: case 0x97: sprintf(buffer, "xnor %s", TYPE_1); break;
+ case 0x98: case 0x99: sprintf(buffer, "nor %s", TYPE_1); break;
+ case 0x9a: case 0x9b: sprintf(buffer, "nand %s", TYPE_1); break;
+ case 0x9c: case 0x9d: sprintf(buffer, "andn %s", TYPE_1); break;
+ case 0x9e: sprintf(buffer, "setip %s", TYPE_2); break;
+ case 0x9f: sprintf(buffer, "inv"); break;
+ case 0xa0: sprintf(buffer, "jmp $%.4x", pc + OP_SJMP); break;
+ case 0xa1: sprintf(buffer, "jmp $%.4x", OP_IJMP); break;
+ case 0xa4: case 0xa5: sprintf(buffer, "jmpf %s", TYPE_4); break;
+ case 0xa8: case 0xa9: sprintf(buffer, "call %s", TYPE_4); break;
+ case 0xac: case 0xad: sprintf(buffer, "jmpt %s", TYPE_4); break;
+ case 0xb4: case 0xb5: sprintf(buffer, "jmpfdec %s", TYPE_4); break;
+ case 0xb6: sprintf(buffer, "mftlb r%d, r%d", OP_RC, OP_RA); break;
+ case 0xbe: sprintf(buffer, "mttlb r%d, r%d", OP_RA, OP_RB); break;
+ case 0xc0: sprintf(buffer, "jmpi r%d", OP_RB); break;
+ case 0xc4: sprintf(buffer, "jmpfi r%d, r%d", OP_RA, OP_RB); break;
+ case 0xc6: sprintf(buffer, "mfsr r%d, %s", OP_RC, get_spr(OP_SA)); break;
+ case 0xc8: sprintf(buffer, "calli r%d, r%d", OP_RA, OP_RB); break;
+ case 0xcc: sprintf(buffer, "jmpti r%d, r%d", OP_RA, OP_RB); break;
+ case 0xce: sprintf(buffer, "mtsr %s, r%d", get_spr(OP_SA), OP_RB); break;
+ case 0xd7: sprintf(buffer, "emulate %s", TYPE_5); break;
+ case 0xde: sprintf(buffer, "multm %s", TYPE_2); break;
+ case 0xdf: sprintf(buffer, "multmu %s", TYPE_2); break;
+
+ case 0xe0: sprintf(buffer, "multiply %s", TYPE_2); break;
+ case 0xe1: sprintf(buffer, "divide %s", TYPE_2); break;
+ default: sprintf(buffer, "??????"); break;
+ }
+ return 4 | flags | DASMFLAG_SUPPORTED;
+}
diff --git a/trunk/src/emu/cpu/am29000/am29ops.h b/trunk/src/emu/cpu/am29000/am29ops.h
new file mode 100644
index 00000000000..f23189a043a
--- /dev/null
+++ b/trunk/src/emu/cpu/am29000/am29ops.h
@@ -0,0 +1,1725 @@
+/***************************************************************************
+
+ am29ops.h
+ Am29000 instructions
+
+***************************************************************************/
+
+/***************************************************************************
+ DEFINES
+***************************************************************************/
+
+#define IFLAG_ILLEGAL (1 << 0)
+#define IFLAG_SUPERVISOR_ONLY (1 << 1)
+#define IFLAG_RA_PRESENT (1 << 2)
+#define IFLAG_RB_PRESENT (1 << 3)
+#define IFLAG_RC_PRESENT (1 << 4)
+
+#define IFLAG_SPR_ACCESS (1 << 6)
+#define IFLAG_MEMORY_ACCESS (1 << 8)
+#define IFLAG_CONTROL (1 << 9)
+
+
+#define GET_RA_VAL (am29000->r[RA])
+#define GET_RB_VAL (am29000->r[RB])
+
+#define RA (get_abs_reg(am29000, am29000->exec_ir >> 8, am29000->ipa))
+#define RB (get_abs_reg(am29000, am29000->exec_ir >> 0, am29000->ipb))
+#define RC (get_abs_reg(am29000, am29000->exec_ir >> 16, am29000->ipc))
+
+#define INST_SA ((am29000->exec_ir >> 8) & 0xff)
+#define INST_VN ((am29000->exec_ir >> 16) & 0xff)
+#define INST_M_BIT (am29000->exec_ir & (1 << 24))
+#define INST_CE_BIT (am29000->exec_ir & (1 << 23))
+#define INST_AS_BIT (am29000->exec_ir & (1 << 22))
+#define INST_PA_BIT (am29000->exec_ir & (1 << 21))
+#define INST_SB_BIT (am29000->exec_ir & (1 << 20))
+#define INST_UA_BIT (am29000->exec_ir & (1 << 19))
+#define INST_OPT_MASK (7)
+#define INST_OPT_SHIFT (16)
+#define INST_OPT_FIELD (((am29000->exec_ir) >> INST_OPT_SHIFT) & INST_OPT_MASK)
+#define INST_CNTL_MASK (0x7f)
+#define INST_CNTL_SHIFT (16)
+
+#define I8 (am29000->exec_ir & 0xff)
+#define I16 (((am29000->exec_ir >> 8) & 0xff00) | (am29000->exec_ir & 0xff))
+#define I16_ZEX ((UINT32)(I16))
+#define I16_SEX ((INT32)(INT16)I16)
+#define I16_OEX (0xffff0000 | I16)
+
+#define JMP_ZEX (I16 << 2)
+#define JMP_SEX ((INT32)(INT16)(((am29000->exec_ir >> 8) & 0xff00) | (am29000->exec_ir & 0xff)) << 2)
+
+#define BOOLEAN_MASK (1 << 31)
+#define BOOLEAN_TRUE (1 << 31)
+#define BOOLEAN_FALSE (0)
+
+#define UNHANDLED_OP fatalerror("Am29000: Unhandled inst %s at %x\n", __FUNCTION__, am29000->exec_pc);
+
+
+/***************************************************************************
+ STRUCTS
+***************************************************************************/
+
+typedef struct _op_info
+{
+ void (*opcode)(am29000_state *);
+ UINT32 flags;
+} op_info;
+
+
+/***************************************************************************
+ ALU FLAG CALCULATION
+***************************************************************************/
+
+#define SET_ALU_Z(r) am29000->alu &= ~ALU_Z; \
+ am29000->alu |= (r == 0) << ALU_Z_SHIFT;
+
+#define SET_ALU_N(r) am29000->alu &= ~ALU_N; \
+ am29000->alu |= ((UINT32)r & 0x80000000) >> (31 - ALU_N_SHIFT);
+
+#define CALC_C_ADD(r, a) ((UINT32)(r) < (UINT32)(a))
+
+#define SET_ALU_C_ADD(r, a) am29000->alu &= ~ALU_C; \
+ am29000->alu |= CALC_C_ADD(r, a) << ALU_C_SHIFT;
+
+#define CALC_C_SUB(a, b) (!((UINT32)(a) < (UINT32)(b)))
+
+#define SET_ALU_C_SUB(a, b) am29000->alu &= ~ALU_C; \
+ am29000->alu |= CALC_C_SUB(a, b) << ALU_C_SHIFT;
+
+#define SET_ALU_V_ADD(r, a, b) am29000->alu &= ~ALU_V; \
+ am29000->alu |= (((INT32)(~((a) ^ (b)) & ((a) ^ (r))) < 0)) << ALU_V_SHIFT;
+
+#define SET_ALU_V_SUB(r, a, b) am29000->alu &= ~ALU_V; \
+ am29000->alu |= ((INT32)(((a) ^ (b)) & ((a) ^ (r))) < 0) << ALU_V_SHIFT;
+
+#define GET_CARRY ((am29000->alu >> ALU_C_SHIFT) & 1)
+
+
+
+static UINT32 read_spr(am29000_state *am29000, UINT32 idx)
+{
+ UINT32 val = 0;
+
+ switch (idx)
+ {
+ case SPR_VAB: val = am29000->vab; break;
+ case SPR_OPS: val = am29000->ops; break;
+ case SPR_CPS: val = am29000->cps; break;
+ case SPR_CFG: val = am29000->cfg; break;
+ case SPR_CHA: val = am29000->cha; break;
+ case SPR_CHD: val = am29000->chd; break;
+ case SPR_CHC: val = am29000->chc; break;
+ case SPR_RBP: val = am29000->rbp; break;
+ case SPR_TMC: val = am29000->tmc; break;
+ case SPR_TMR: val = am29000->tmr; break;
+ case SPR_PC0: val = am29000->pc0; break;
+ case SPR_PC1: val = am29000->pc1; break;
+ case SPR_PC2: val = am29000->pc2; break;
+ case SPR_MMU: val = am29000->mmu; break;
+ case SPR_LRU: val = am29000->lru; break;
+ case SPR_IPC: val = am29000->ipc; break;
+ case SPR_IPA: val = am29000->ipa; break;
+ case SPR_IPB: val = am29000->ipb; break;
+ case SPR_Q: val = am29000->q; break;
+ case SPR_ALU: val = am29000->alu; break;
+ case SPR_BP: val = GET_ALU_BP; break;
+ case SPR_FC: val = GET_ALU_FC; break;
+ case SPR_CR: val = GET_CHC_CR; break;
+ case SPR_FPE: val = am29000->fpe; break;
+ case SPR_INTE: val = am29000->inte; break;
+ case SPR_FPS: val = am29000->fps; break;
+ default:
+ logerror("Unknown SPR read (%d)\n", idx);
+ }
+
+ return val;
+}
+
+
+static void write_spr(am29000_state *am29000, UINT32 idx, UINT32 val)
+{
+ switch (idx)
+ {
+ case SPR_VAB: am29000->vab = val & (VAB_MASK << VAB_SHIFT);
+ break;
+ case SPR_OPS: am29000->ops = val & (CPS_CA | CPS_IP | CPS_TE | CPS_TP | CPS_TU | CPS_FZ | CPS_LK | CPS_RE |
+ CPS_WM | CPS_PD | CPS_PI | CPS_SM | (CPS_IM_MASK << CPS_IM_SHIFT) | CPS_DI | CPS_DA);
+ break;
+ case SPR_CPS: am29000->cps = val & (CPS_CA | CPS_IP | CPS_TE | CPS_TP | CPS_TU | CPS_FZ | CPS_LK | CPS_RE |
+ CPS_WM | CPS_PD | CPS_PI | CPS_SM | (CPS_IM_MASK << CPS_IM_SHIFT) | CPS_DI | CPS_DA);
+ break;
+ case SPR_CFG: am29000->cfg = val & (CFG_DW | CFG_VF | CFG_RV | CFG_BO | CFG_CP | CFG_CD);
+ am29000->cfg |= PROCESSOR_REL_FIELD << CFG_PRL_SHIFT;
+ break;
+ case SPR_CHA: am29000->cha = val;
+ break;
+ case SPR_CHD: am29000->chd = val;
+ break;
+ case SPR_CHC: am29000->chc = val;
+ break;
+ case SPR_RBP: am29000->rbp = val & RBP_MASK;
+ break;
+ case SPR_TMC: am29000->tmc = val & TCV_MASK;
+ break;
+ case SPR_TMR: am29000->tmr = val & (TMR_OV | TMR_IN | TMR_IE | TMR_TRV_MASK);
+ break;
+ case SPR_PC0: am29000->pc0 = val & PC_MASK;
+ break;
+ case SPR_PC1: am29000->pc1 = val & PC_MASK;
+ break;
+ case SPR_PC2: am29000->pc2 = val & PC_MASK;
+ break;
+ case SPR_MMU: am29000->mmu = val & ((MMU_PS_MASK << MMU_PS_SHIFT) | MMU_PID_MASK);
+ break;
+ case SPR_LRU: am29000->lru = val & (LRU_MASK << LRU_SHIFT);
+ break;
+ case SPR_IPC: am29000->ipc = val;// & IPX_MASK;
+ break;
+ case SPR_IPA: am29000->ipa = val;// & IPX_MASK;
+ break;
+ case SPR_IPB: am29000->ipb = val;// & IPX_MASK;
+ break;
+ case SPR_Q: am29000->q = val;
+ break;
+ case SPR_ALU: am29000->alu = val & (ALU_DF | ALU_V | ALU_N | ALU_Z | ALU_C | (ALU_BP_MASK << ALU_BP_SHIFT) | (ALU_FC_MASK << ALU_FC_SHIFT));
+ break;
+ case SPR_BP: am29000->alu &= ~(ALU_BP_MASK << ALU_BP_SHIFT);
+ am29000->alu |= (val & ALU_BP_MASK) << ALU_BP_SHIFT;
+ break;
+ case SPR_FC: am29000->alu &= ~(ALU_FC_MASK << ALU_FC_SHIFT);
+ am29000->alu |= (val & ALU_FC_MASK) << ALU_FC_SHIFT;
+ break;
+ case SPR_CR: am29000->chc &= ~(CHC_CR_MASK << CHC_CR_SHIFT);
+ am29000->chc |= (val & CHC_CR_MASK) << CHC_CR_SHIFT;
+ break;
+// case SPR_FPE:
+// case SPR_INTE:
+// case SPR_FPS:
+ default: logerror("Unhandled SPR write (%d)\n", idx);
+ }
+}
+
+
+/***************************************************************************
+ INSTRUCTIONS
+***************************************************************************/
+
+/***************************************************************************
+ INTEGER ARITHMETIC
+***************************************************************************/
+
+static void ADD(am29000_state *am29000)
+{
+ UINT32 a = GET_RA_VAL;
+ UINT32 b = INST_M_BIT ? I8: GET_RB_VAL;
+ UINT32 r = a + b;
+
+ if (!FREEZE_MODE)
+ {
+ SET_ALU_V_ADD(r, a, b);
+ SET_ALU_Z(r);
+ SET_ALU_N(r);
+ SET_ALU_C_ADD(r, a);
+ }
+
+ am29000->r[RC] = r;
+}
+
+static void ADDS(am29000_state *am29000)
+{
+ UNHANDLED_OP;
+}
+
+static void ADDU(am29000_state *am29000)
+{
+ UNHANDLED_OP;
+}
+
+static void ADDC(am29000_state *am29000)
+{
+ UNHANDLED_OP;
+}
+
+static void ADDCS(am29000_state *am29000)
+{
+ UINT32 a = GET_RA_VAL;
+ UINT32 b = INST_M_BIT ? I8: GET_RB_VAL;
+ UINT32 r = a + b + GET_CARRY;
+
+ if (!FREEZE_MODE)
+ {
+ UINT32 carry = GET_CARRY;
+ UINT32 tmp = a + b;
+
+ SET_ALU_V_ADD(r, a, b);
+ SET_ALU_Z(r);
+ SET_ALU_N(r);
+
+ carry = CALC_C_ADD(tmp, a) || CALC_C_ADD(tmp + carry, carry);
+ am29000->alu &= ~ALU_C;
+ am29000->alu |= carry << ALU_C_SHIFT;
+ }
+
+ // TODO: Trap on signed overflow
+ am29000->r[RC] = r;
+}
+
+static void ADDCU(am29000_state *am29000)
+{
+ UNHANDLED_OP;
+}
+
+static void SUB(am29000_state *am29000)
+{
+ UINT32 a = GET_RA_VAL;
+ UINT32 b = INST_M_BIT ? I8 : GET_RB_VAL;
+ UINT32 r = a - b;
+
+ if (!FREEZE_MODE)
+ {
+ SET_ALU_V_SUB(r, a, b);
+ SET_ALU_Z(r);
+ SET_ALU_N(r);
+ SET_ALU_C_SUB(a, b);
+ }
+
+ // TODO: Trap on unsigned overflow
+ am29000->r[RC] = r;
+}
+
+static void SUBS(am29000_state *am29000)
+{
+ UINT32 a = GET_RA_VAL;
+ UINT32 b = INST_M_BIT ? I8 : GET_RB_VAL;
+ UINT32 r = a - b;
+
+ if (!FREEZE_MODE)
+ {
+ SET_ALU_V_SUB(r, a, b);
+ SET_ALU_Z(r);
+ SET_ALU_N(r);
+ SET_ALU_C_SUB(a, b);
+ }
+
+ if ((INT32)(((a) ^ (b)) & ((a) ^ (r))) < 0)
+ SIGNAL_EXCEPTION(EXCEPTION_OUT_OF_RANGE);
+
+ am29000->r[RC] = r;
+}
+
+static void SUBU(am29000_state *am29000)
+{
+ UNHANDLED_OP;
+}
+
+static void SUBC(am29000_state *am29000)
+{
+ UNHANDLED_OP;
+}
+
+static void SUBCS(am29000_state *am29000)
+{
+ UNHANDLED_OP;
+}
+
+static void SUBCU(am29000_state *am29000)
+{
+ UNHANDLED_OP;
+}
+
+static void SUBR(am29000_state *am29000)
+{
+ UINT32 a = GET_RA_VAL;
+ UINT32 b = INST_M_BIT ? I8 : GET_RB_VAL;
+ UINT32 r = b - a;
+
+ if (!FREEZE_MODE)
+ {
+ SET_ALU_V_SUB(r, a, b);
+ SET_ALU_Z(r);
+ SET_ALU_N(r);
+ SET_ALU_C_SUB(a, b);
+ }
+
+ am29000->r[RC] = r;
+}
+
+static void SUBRS(am29000_state *am29000)
+{
+ UNHANDLED_OP;
+}
+
+static void SUBRU(am29000_state *am29000)
+{
+ UNHANDLED_OP;
+}
+
+static void SUBRC(am29000_state *am29000)
+{
+ UINT32 a = GET_RA_VAL;
+ UINT32 b = INST_M_BIT ? I8 : GET_RB_VAL;
+ UINT32 r = b - a - 1 + GET_CARRY;
+
+ if (!FREEZE_MODE)
+ {
+ SET_ALU_V_SUB(r, a, b);
+ SET_ALU_Z(r);
+ SET_ALU_N(r);
+ SET_ALU_C_SUB(a, b);
+ }
+
+ am29000->r[RC] = r;
+}
+
+static void SUBRCS(am29000_state *am29000)
+{
+ UNHANDLED_OP;
+}
+
+static void SUBRCU(am29000_state *am29000)
+{
+ UNHANDLED_OP;
+}
+
+static void MULTIPLU(am29000_state *am29000)
+{
+ UNHANDLED_OP;
+}
+
+static void MULTIPLY(am29000_state *am29000)
+{
+ UNHANDLED_OP;
+}
+
+static void MUL(am29000_state *am29000)
+{
+ /* TODO: Zero/Neg flags ? */
+ UINT32 a = GET_RA_VAL;
+ UINT32 b = INST_M_BIT ? I8 : GET_RB_VAL;
+ UINT32 r;
+ UINT64 v;
+ UINT32 sign;
+
+ if (am29000->q & 1)
+ {
+ r = a + b;
+ sign = (r >> 31) ^ (((INT32)(~((a) ^ (b)) & ((a) ^ (r))) < 0));
+ }
+ else
+ {
+ r = b;
+ sign = b >> 31;
+ }
+
+ v = ((((UINT64)r << 32) | am29000->q) >> 1) | ((UINT64)sign << 63);
+ am29000->q = v & 0xffffffff;
+
+ am29000->r[RC] = v >> 32;
+}
+
+static void MULL(am29000_state *am29000)
+{
+ /* TODO: Zero/Neg flags ? */
+ UINT32 a = GET_RA_VAL;
+ UINT32 b = INST_M_BIT ? I8 : GET_RB_VAL;
+ UINT32 r;
+ UINT64 v;
+ UINT32 sign;
+
+ if (am29000->q & 1)
+ {
+ r = b - a;
+ sign = (r >> 31) ^ ((INT32)(((a) ^ (b)) & ((a) ^ (r))) < 0);
+ }
+ else
+ {
+ r = b;
+ sign = b >> 31;
+ }
+
+ v = ((((UINT64)r << 32) | am29000->q) >> 1) | ((UINT64)sign << 63);
+ am29000->q = v & 0xffffffff;
+
+ am29000->r[RC] = v >> 32;
+}
+
+static void MULU(am29000_state *am29000)
+{
+ /* TODO: Zero/Neg flags ? */
+ UINT32 a = GET_RA_VAL;
+ UINT32 b = INST_M_BIT ? I8 : GET_RB_VAL;
+ UINT32 r;
+ UINT64 v;
+ UINT32 c;
+
+ if (am29000->q & 1)
+ {
+ r = a + b;
+ c = (UINT32)(r) < (UINT32)(a);
+ }
+ else
+ {
+ r = b;
+ c = 0;
+ }
+
+ v = ((((UINT64)r << 32) | am29000->q) >> 1) | ((UINT64)c << 63);
+ am29000->q = v & 0xffffffff;
+
+ am29000->r[RC] = v >> 32;
+}
+
+static void DIVIDE(am29000_state *am29000)
+{
+ am29000->ipa = RA << IPX_SHIFT;
+ am29000->ipb = RB << IPX_SHIFT;
+ am29000->ipc = RC << IPX_SHIFT;
+
+ SIGNAL_EXCEPTION(EXCEPTION_DIVIDE);
+}
+
+static void DIVIDU(am29000_state *am29000)
+{
+ UNHANDLED_OP;
+}
+
+static void DIV0(am29000_state *am29000)
+{
+ UINT32 b = INST_M_BIT ? I8: GET_RB_VAL;
+ UINT64 v;
+
+ if (!FREEZE_MODE)
+ {
+ am29000->alu |= ALU_DF;
+ SET_ALU_N(b);
+ }
+
+ v = (((UINT64)b << 32) | am29000->q) << 1;
+
+ am29000->q = v & 0xffffffff;
+
+ am29000->r[RC] = v >> 32;
+}
+
+static void DIV(am29000_state *am29000)
+{
+ UINT32 a = GET_RA_VAL;
+ UINT32 b = INST_M_BIT ? I8: GET_RB_VAL;
+ UINT32 c;
+ UINT32 r;
+ UINT64 r64;
+ UINT32 df;
+
+ if (am29000->alu & ALU_DF)
+ {
+ r = a - b;
+ c = !((UINT32)(a) < (UINT32)(b));
+ }
+ else
+ {
+ r = a + b;
+ c = (UINT32)(r) < (UINT32)(a);
+ }
+
+
+ df = (~(c ^ (am29000->alu >> ALU_DF_SHIFT) ^ (am29000->alu >> ALU_N_SHIFT)) & 1);
+
+ if (!FREEZE_MODE)
+ {
+ am29000->alu &= ~ALU_DF;
+ am29000->alu |= df << ALU_DF_SHIFT;
+ SET_ALU_N(r);
+ }
+
+ r64 = ((((UINT64)r << 32) | am29000->q) << 1) | df;
+ am29000->q = r64 & 0xffffffff;
+
+ am29000->r[RC] = r64 >> 32;
+}
+
+static void DIVL(am29000_state *am29000)
+{
+ UINT32 a = GET_RA_VAL;
+ UINT32 b = INST_M_BIT ? I8: GET_RB_VAL;
+ UINT32 c;
+ UINT32 r;
+ UINT32 df;
+
+ if (am29000->alu & ALU_DF)
+ {
+ r = a - b;
+ c = !((UINT32)(a) < (UINT32)(b));
+ }
+ else
+ {
+ r = a + b;
+ c = (UINT32)(r) < (UINT32)(a);
+ }
+
+ df = (~(c ^ (am29000->alu >> ALU_DF_SHIFT) ^ (am29000->alu >> ALU_N_SHIFT)) & 1);
+
+ if (!FREEZE_MODE)
+ {
+ am29000->alu &= ~ALU_DF;
+ am29000->alu |= df << ALU_DF_SHIFT;
+ SET_ALU_N(r);
+ }
+
+ am29000->q = (am29000->q << 1) | df;
+ am29000->r[RC] = r;
+}
+
+static void DIVREM(am29000_state *am29000)
+{
+ UINT32 a = GET_RA_VAL;
+ UINT32 b = INST_M_BIT ? I8: GET_RB_VAL;
+
+ if (am29000->alu & ALU_DF)
+ am29000->r[RC] = a;
+ else
+ am29000->r[RC] = a + b;
+}
+
+
+/***************************************************************************
+ COMPARE
+***************************************************************************/
+
+static void CPEQ(am29000_state *am29000)
+{
+ UINT32 a = GET_RA_VAL;
+ UINT32 b = INST_M_BIT ? I8: GET_RB_VAL;
+ UINT32 r = a == b ? BOOLEAN_TRUE : BOOLEAN_FALSE;
+
+ am29000->r[RC] = r;
+}
+
+static void CPNEQ(am29000_state *am29000)
+{
+ UINT32 a = GET_RA_VAL;
+ UINT32 b = INST_M_BIT ? I8: GET_RB_VAL;
+ UINT32 r = a != b ? BOOLEAN_TRUE : BOOLEAN_FALSE;
+
+ am29000->r[RC] = r;
+}
+
+static void CPLT(am29000_state *am29000)
+{
+ UINT32 a = GET_RA_VAL;
+ UINT32 b = INST_M_BIT ? I8: GET_RB_VAL;
+ UINT32 r = (INT32)a < (INT32)b ? BOOLEAN_TRUE : BOOLEAN_FALSE;
+
+ am29000->r[RC] = r;
+}
+
+static void CPLTU(am29000_state *am29000)
+{
+ UINT32 a = GET_RA_VAL;
+ UINT32 b = INST_M_BIT ? I8: GET_RB_VAL;
+ UINT32 r = (UINT32)a < (UINT32)b ? BOOLEAN_TRUE : BOOLEAN_FALSE;
+
+ am29000->r[RC] = r;
+}
+
+static void CPLE(am29000_state *am29000)
+{
+ UINT32 a = GET_RA_VAL;
+ UINT32 b = INST_M_BIT ? I8: GET_RB_VAL;
+ UINT32 r = (INT32)a <= (INT32)b ? BOOLEAN_TRUE : BOOLEAN_FALSE;
+
+ am29000->r[RC] = r;
+}
+
+static void CPLEU(am29000_state *am29000)
+{
+ UINT32 a = GET_RA_VAL;
+ UINT32 b = INST_M_BIT ? I8: GET_RB_VAL;
+ UINT32 r = (UINT32)a <= (UINT32)b ? BOOLEAN_TRUE : BOOLEAN_FALSE;
+
+ am29000->r[RC] = r;
+}
+
+static void CPGT(am29000_state *am29000)
+{
+ UINT32 a = GET_RA_VAL;
+ UINT32 b = INST_M_BIT ? I8: GET_RB_VAL;
+ UINT32 r = (INT32)a > (INT32)b ? BOOLEAN_TRUE : BOOLEAN_FALSE;
+
+ am29000->r[RC] = r;
+}
+
+static void CPGTU(am29000_state *am29000)
+{
+ UINT32 a = GET_RA_VAL;
+ UINT32 b = INST_M_BIT ? I8: GET_RB_VAL;
+ UINT32 r = (UINT32)a > (UINT32)b ? BOOLEAN_TRUE : BOOLEAN_FALSE;
+
+ am29000->r[RC] = r;
+}
+
+static void CPGE(am29000_state *am29000)
+{
+ UINT32 a = GET_RA_VAL;
+ UINT32 b = INST_M_BIT ? I8: GET_RB_VAL;
+ UINT32 r = (INT32)a >= (INT32)b ? BOOLEAN_TRUE : BOOLEAN_FALSE;
+
+ am29000->r[RC] = r;
+}
+
+static void CPGEU(am29000_state *am29000)
+{
+ UINT32 a = GET_RA_VAL;
+ UINT32 b = INST_M_BIT ? I8: GET_RB_VAL;
+ UINT32 r = (UINT32)a >= (UINT32)b ? BOOLEAN_TRUE : BOOLEAN_FALSE;
+
+ am29000->r[RC] = r;
+}
+
+static void CPBYTE(am29000_state *am29000)
+{
+ UINT32 a = GET_RA_VAL;
+ UINT32 b = INST_M_BIT ? I8 : GET_RB_VAL;
+ UINT32 r =
+ ((a & 0xff000000) == (b & 0xff000000)) ||
+ ((a & 0x00ff0000) == (b & 0x00ff0000)) ||
+ ((a & 0x0000ff00) == (b & 0x0000ff00)) ||
+ ((a & 0x000000ff) == (b & 0x000000ff))
+ ? BOOLEAN_TRUE : BOOLEAN_FALSE;
+
+ am29000->r[RC] = r;
+}
+
+static void ASEQ(am29000_state *am29000)
+{
+ if (USER_MODE && INST_VN < 64)
+ SIGNAL_EXCEPTION(EXCEPTION_PROTECTION_VIOLATION);
+ else if (!(GET_RA_VAL == GET_RB_VAL))
+ SIGNAL_EXCEPTION(INST_VN);
+}
+
+static void ASNEQ(am29000_state *am29000)
+{
+ if (USER_MODE && INST_VN < 64)
+ SIGNAL_EXCEPTION(EXCEPTION_PROTECTION_VIOLATION);
+ else if (!(GET_RA_VAL != GET_RB_VAL))
+ SIGNAL_EXCEPTION(INST_VN);
+}
+
+static void ASLT(am29000_state *am29000)
+{
+ if (USER_MODE && INST_VN < 64)
+ SIGNAL_EXCEPTION(EXCEPTION_PROTECTION_VIOLATION);
+ else if (!((INT32)GET_RA_VAL < (INT32)GET_RB_VAL))
+ SIGNAL_EXCEPTION(INST_VN);
+}
+
+static void ASLTU(am29000_state *am29000)
+{
+ if (USER_MODE && INST_VN < 64)
+ SIGNAL_EXCEPTION(EXCEPTION_PROTECTION_VIOLATION);
+ else if (!((UINT32)GET_RA_VAL < (UINT32)GET_RB_VAL))
+ SIGNAL_EXCEPTION(INST_VN);
+}
+
+static void ASLE(am29000_state *am29000)
+{
+ if (USER_MODE && INST_VN < 64)
+ SIGNAL_EXCEPTION(EXCEPTION_PROTECTION_VIOLATION);
+ else if (!((INT32)GET_RA_VAL <= (INT32)GET_RB_VAL))
+ SIGNAL_EXCEPTION(INST_VN);
+}
+
+static void ASLEU(am29000_state *am29000)
+{
+ if (USER_MODE && INST_VN < 64)
+ SIGNAL_EXCEPTION(EXCEPTION_PROTECTION_VIOLATION);
+ else if (!((UINT32)GET_RA_VAL <= (UINT32)GET_RB_VAL))
+ SIGNAL_EXCEPTION(INST_VN);
+}
+
+static void ASGT(am29000_state *am29000)
+{
+ if (USER_MODE && INST_VN < 64)
+ SIGNAL_EXCEPTION(EXCEPTION_PROTECTION_VIOLATION);
+ else if (!((INT32)GET_RA_VAL > (INT32)GET_RB_VAL))
+ SIGNAL_EXCEPTION(INST_VN);
+}
+
+static void ASGTU(am29000_state *am29000)
+{
+ if (USER_MODE && INST_VN < 64)
+ SIGNAL_EXCEPTION(EXCEPTION_PROTECTION_VIOLATION);
+ else if (!((UINT32)GET_RA_VAL > (UINT32)GET_RB_VAL))
+ SIGNAL_EXCEPTION(INST_VN);
+}
+
+static void ASGE(am29000_state *am29000)
+{
+ if (USER_MODE && INST_VN < 64)
+ SIGNAL_EXCEPTION(EXCEPTION_PROTECTION_VIOLATION);
+ else if (!((INT32)GET_RA_VAL >= (INT32)GET_RB_VAL))
+ SIGNAL_EXCEPTION(INST_VN);
+}
+
+static void ASGEU(am29000_state *am29000)
+{
+ if (USER_MODE && INST_VN < 64)
+ SIGNAL_EXCEPTION(EXCEPTION_PROTECTION_VIOLATION);
+ else if (!((UINT32)GET_RA_VAL >= (UINT32)GET_RB_VAL))
+ SIGNAL_EXCEPTION(INST_VN);
+}
+
+
+/***************************************************************************
+ LOGICAL
+***************************************************************************/
+
+static void AND(am29000_state *am29000)
+{
+ UINT32 a = GET_RA_VAL;
+ UINT32 b = INST_M_BIT ? I8: GET_RB_VAL;
+ UINT32 r = a & b;
+
+ if (!FREEZE_MODE)
+ {
+ SET_ALU_Z(r);
+ SET_ALU_N(r);
+ }
+
+ am29000->r[RC] = r;
+}
+
+static void ANDN(am29000_state *am29000)
+{
+ UINT32 a = GET_RA_VAL;
+ UINT32 b = INST_M_BIT ? I8: GET_RB_VAL;
+ UINT32 r = a & ~b;
+
+ if (!FREEZE_MODE)
+ {
+ SET_ALU_Z(r);
+ SET_ALU_N(r);
+ }
+
+ am29000->r[RC] = r;
+}
+
+static void NAND(am29000_state *am29000)
+{
+ UINT32 a = GET_RA_VAL;
+ UINT32 b = INST_M_BIT ? I8: GET_RB_VAL;
+ UINT32 r = ~(a & b);
+
+ if (!FREEZE_MODE)
+ {
+ SET_ALU_Z(r);
+ SET_ALU_N(r);
+ }
+
+ am29000->r[RC] = r;
+}
+
+static void OR(am29000_state *am29000)
+{
+ UINT32 a = GET_RA_VAL;
+ UINT32 b = INST_M_BIT ? I8: GET_RB_VAL;
+ UINT32 r = a | b;
+
+ if (!FREEZE_MODE)
+ {
+ SET_ALU_Z(r);
+ SET_ALU_N(r);
+ }
+
+ am29000->r[RC] = r;
+}
+
+static void NOR(am29000_state *am29000)
+{
+ UINT32 a = GET_RA_VAL;
+ UINT32 b = INST_M_BIT ? I8: GET_RB_VAL;
+ UINT32 r = ~(a | b);
+
+ if (!FREEZE_MODE)
+ {
+ SET_ALU_Z(r);
+ SET_ALU_N(r);
+ }
+
+ am29000->r[RC] = r;
+}
+
+static void XOR(am29000_state *am29000)
+{
+ UINT32 a = GET_RA_VAL;
+ UINT32 b = INST_M_BIT ? I8: GET_RB_VAL;
+ UINT32 r = a ^ b;
+
+ if (!FREEZE_MODE)
+ {
+ SET_ALU_Z(r);
+ SET_ALU_N(r);
+ }
+
+ am29000->r[RC] = r;
+}
+
+static void XNOR(am29000_state *am29000)
+{
+ UINT32 a = GET_RA_VAL;
+ UINT32 b = INST_M_BIT ? I8: GET_RB_VAL;
+ UINT32 r = ~(a ^ b);
+
+ if (!FREEZE_MODE)
+ {
+ SET_ALU_Z(r);
+ SET_ALU_N(r);
+ }
+
+ am29000->r[RC] = r;
+}
+
+
+/***************************************************************************
+ SHIFT
+***************************************************************************/
+
+static void SLL(am29000_state *am29000)
+{
+ UINT32 a = GET_RA_VAL;
+ UINT32 b = (INST_M_BIT ? I8: GET_RB_VAL) & 0x1f;
+ UINT32 r = a << b;
+
+ am29000->r[RC] = r;
+}
+
+static void SRL(am29000_state *am29000)
+{
+ UINT32 a = GET_RA_VAL;
+ UINT32 b = (INST_M_BIT ? I8: GET_RB_VAL) & 0x1f;
+ UINT32 r = a >> b;
+
+ am29000->r[RC] = r;
+}
+
+static void SRA(am29000_state *am29000)
+{
+ INT32 a = GET_RA_VAL;
+ UINT32 b = (INST_M_BIT ? I8: GET_RB_VAL) & 0x1f;
+ UINT32 r = a >> b;
+
+ am29000->r[RC] = r;
+}
+
+static void EXTRACT(am29000_state *am29000)
+{
+ INT32 a = GET_RA_VAL;
+ UINT32 b = (INST_M_BIT ? I8: GET_RB_VAL);
+ UINT64 r;
+
+ r = (((UINT64)a << 32) | b) << GET_ALU_FC;
+
+ am29000->r[RC] = r >> 32;
+}
+
+
+/***************************************************************************
+ DATA MOVEMENT
+***************************************************************************/
+
+static void LOAD(am29000_state *am29000)
+{
+ UINT32 addr = INST_M_BIT ? I8: GET_RB_VAL;
+ UINT32 r;
+
+ if (INST_UA_BIT)
+ fatalerror("Am29000: UA bit set on LOAD\n");
+
+ if (INST_CE_BIT)
+ {
+ logerror("Am29000: Attempting a co-processor LOAD!\n");
+ r = 0;
+ }
+ else
+ {
+ if (!INST_PA_BIT && !(am29000->cps & CPS_PD))
+ {
+ fatalerror("Am29000: Address translation on LOAD\n");
+ }
+ else
+ {
+ if (USER_MODE)
+ {
+ SIGNAL_EXCEPTION(EXCEPTION_PROTECTION_VIOLATION);
+ return;
+ }
+
+ r = am29000->data->read_dword(addr);
+ }
+ }
+
+// if (opt & 2)
+// logerror("Am29000: Half word LOAD\n");
+
+ if (!FREEZE_MODE)
+ {
+ am29000->chc = ((am29000->exec_ir << 8) & 0xff) |
+ CHC_LS |
+ RA << CHC_TR_SHIFT |
+ CHC_CV;
+
+ am29000->cha = addr;
+ am29000->chd = r;
+
+ if (!(am29000->cfg & CFG_DW) && (am29000->exec_ir & INST_SB_BIT))
+ SET_ALU_BP(addr & 3);
+ }
+
+ am29000->r[RA] = r;
+
+ if (am29000->cfg & CFG_DW)
+ logerror("DW ON A STORE");
+}
+
+static void LOADL(am29000_state *am29000)
+{
+ UNHANDLED_OP;
+}
+
+static void LOADSET(am29000_state *am29000)
+{
+ UNHANDLED_OP;
+}
+
+static void LOADM(am29000_state *am29000)
+{
+ UINT32 addr = INST_M_BIT ? I8: GET_RB_VAL;
+ UINT32 r;
+
+ if (INST_UA_BIT)
+ fatalerror("Am29000: UA bit set on LOAD\n");
+
+ if (INST_CE_BIT)
+ {
+ logerror("Am29000: Attempting a co-processor LOAD!\n");
+ r = 0;
+ }
+ else
+ {
+ if (!INST_PA_BIT && !(am29000->cps & CPS_PD))
+ {
+ fatalerror("Am29000: Address translation on LOAD\n");
+ }
+ else
+ {
+ if (USER_MODE)
+ {
+ SIGNAL_EXCEPTION(EXCEPTION_PROTECTION_VIOLATION);
+ return;
+ }
+
+ r = am29000->data->read_dword(addr);
+ }
+ }
+
+ if (!FREEZE_MODE)
+ {
+ // TODO
+ am29000->chc &= (CHC_CR_MASK << CHC_CR_SHIFT);
+ am29000->chc |= ((am29000->exec_ir << 8) & 0xff) |
+ RA << CHC_TR_SHIFT |
+ CHC_CV;
+
+ am29000->cha = addr;
+ am29000->chd = r; // ?????
+
+ if (!(am29000->cfg & CFG_DW) && (am29000->exec_ir & INST_SB_BIT))
+ SET_ALU_BP(addr & 3);
+ }
+
+ r = RA;
+
+ {
+ int cnt;
+ for (cnt = 0; cnt <= GET_CHC_CR; ++cnt)
+ {
+ am29000->r[r] = am29000->data->read_dword(addr);
+
+// SET_CHC_CR(cnt - 1);
+ addr += 4;
+
+ if (++r == 256)
+ r = 128;
+ }
+ }
+}
+
+static void STORE(am29000_state *am29000)
+{
+ UINT32 addr = INST_M_BIT ? I8: GET_RB_VAL;
+// UINT32 r;
+
+ if (INST_UA_BIT)
+ fatalerror("Am29000: UA bit set on LOAD\n");
+
+ if (INST_CE_BIT)
+ {
+ logerror("Am29000: Attempting a co-processor LOAD!\n");
+// r = 0;
+ }
+ else
+ {
+ if (!INST_PA_BIT && !(am29000->cps & CPS_PD))
+ {
+ fatalerror("Am29000: Address translation on LOAD\n");
+ }
+ else
+ {
+ if (USER_MODE)
+ {
+ SIGNAL_EXCEPTION(EXCEPTION_PROTECTION_VIOLATION);
+ return;
+ }
+
+ }
+ }
+
+ am29000->data->write_dword(addr, am29000->r[RA]);
+
+ if (!FREEZE_MODE)
+ {
+ am29000->chc = ((am29000->exec_ir << 8) & 0xff) |
+ RA << CHC_TR_SHIFT |
+ CHC_CV;
+
+ am29000->cha = addr;
+
+ if (!(am29000->cfg & CFG_DW) && (am29000->exec_ir & INST_SB_BIT))
+ SET_ALU_BP(addr & 3);
+ }
+
+ if (am29000->cfg & CFG_DW)
+ logerror("DW ON A STORE");
+}
+
+static void STOREL(am29000_state *am29000)
+{
+ UNHANDLED_OP;
+}
+
+static void STOREM(am29000_state *am29000)
+{
+ UINT32 addr = INST_M_BIT ? I8: GET_RB_VAL;
+ UINT32 r;
+
+ if (INST_UA_BIT)
+ fatalerror("Am29000: UA bit set on LOAD\n");
+
+ if (INST_CE_BIT)
+ {
+ logerror("Am29000: Attempting a co-processor LOAD!\n");
+ r = 0;
+ }
+ else
+ {
+ if (!INST_PA_BIT && !(am29000->cps & CPS_PD))
+ {
+ fatalerror("Am29000: Address translation on LOAD\n");
+ }
+ else
+ {
+ if (USER_MODE)
+ {
+ SIGNAL_EXCEPTION(EXCEPTION_PROTECTION_VIOLATION);
+ return;
+ }
+
+ }
+ }
+
+ if (!FREEZE_MODE)
+ {
+ // TODO
+ am29000->chc &= (CHC_CR_MASK << CHC_CR_SHIFT);
+ am29000->chc |= ((am29000->exec_ir << 8) & 0xff) |
+ RA << CHC_TR_SHIFT |
+ CHC_CV;
+
+ am29000->cha = addr;
+
+ if (!(am29000->cfg & CFG_DW) && (am29000->exec_ir & INST_SB_BIT))
+ SET_ALU_BP(addr & 3);
+ }
+
+ r = RA;
+
+ {
+ int cnt;
+ for (cnt = 0; cnt <= GET_CHC_CR; ++cnt)
+ {
+ am29000->data->write_dword(addr, am29000->r[r]);
+
+// SET_CHC_CR(cnt - 1);
+ addr += 4;
+
+ if (++r == 256)
+ r = 128;
+ }
+ }
+}
+
+static void EXBYTE(am29000_state *am29000)
+{
+ UINT32 a = GET_RA_VAL;
+ UINT32 b = INST_M_BIT ? I8: GET_RB_VAL;
+ UINT32 bp = GET_ALU_BP;
+ UINT8 srcbyte;
+ UINT32 r;
+
+ if (am29000->cfg & CFG_BO)
+ srcbyte = a >> 8 * bp;
+ else
+ srcbyte = a >> (8 * (3 - bp));
+
+ r = (b & 0xffffff00) | srcbyte;
+
+ am29000->r[RC] = r;
+}
+
+static void EXHW(am29000_state *am29000)
+{
+ UINT32 a = GET_RA_VAL;
+ UINT32 b = INST_M_BIT ? I8: GET_RB_VAL;
+ UINT32 wp = ((am29000->alu >> ALU_BP_SHIFT) & ALU_BP_MASK) >> 1;
+ UINT16 srcword;
+ UINT32 r;
+
+ if (am29000->cfg & CFG_BO)
+ srcword = a >> 16 * wp;
+ else
+ srcword = a >> (16 * (1 - wp));
+
+ r = (b & 0xffff0000) | srcword;
+
+ am29000->r[RC] = r;
+}
+
+static void EXHWS(am29000_state *am29000)
+{
+ UINT32 a = GET_RA_VAL;
+ UINT32 wp = ((am29000->alu >> ALU_BP_SHIFT) & ALU_BP_MASK) >> 1;
+ UINT16 srcword;
+ UINT32 r;
+
+ if (am29000->cfg & CFG_BO)
+ srcword = a >> 16 * wp;
+ else
+ srcword = a >> (16 * (1 - wp));
+
+ r = (INT32)(INT16)srcword;
+
+ am29000->r[RC] = r;
+}
+
+static void INBYTE(am29000_state *am29000)
+{
+ UINT32 a = GET_RA_VAL;
+ UINT32 b = INST_M_BIT ? I8: GET_RB_VAL;
+ UINT32 bp = GET_ALU_BP;
+ UINT8 shift = (am29000->cfg & CFG_BO) ? 8 * bp : (8 * (3 - bp));
+ UINT32 r;
+
+ r = (a & ~(0xff << shift)) | ((b & 0xff) << shift);
+
+ am29000->r[RC] = r;
+}
+
+static void INHW(am29000_state *am29000)
+{
+ UINT32 a = GET_RA_VAL;
+ UINT32 b = INST_M_BIT ? I8: GET_RB_VAL;
+ UINT32 wp = ((am29000->alu >> ALU_BP_SHIFT) & ALU_BP_MASK) >> 1;
+ UINT32 shift = (am29000->cfg & CFG_BO) ? 16 * wp : (16 * (1 - wp));
+ UINT32 r;
+
+ r = (a & ~(0xffff << shift)) | ((b & 0xffff) << shift);
+
+ am29000->r[RC] = r;
+}
+
+static void MFSR(am29000_state *am29000)
+{
+ am29000->r[RC] = read_spr(am29000, INST_SA);
+}
+
+static void MFTLB(am29000_state *am29000)
+{
+ am29000->r[RC] = am29000->tlb[GET_RA_VAL & 0x7f];
+}
+
+static void MTSR(am29000_state *am29000)
+{
+ write_spr(am29000, INST_SA, GET_RB_VAL);
+}
+
+static void MTSRIM(am29000_state *am29000)
+{
+ write_spr(am29000, INST_SA, I16_ZEX);
+}
+
+static void MTTLB(am29000_state *am29000)
+{
+ am29000->tlb[GET_RA_VAL & 0x7f] = GET_RB_VAL;
+}
+
+
+/***************************************************************************
+ CONSTANT
+***************************************************************************/
+
+static void CONST(am29000_state *am29000)
+{
+ am29000->r[RA] = I16_ZEX;
+}
+
+static void CONSTH(am29000_state *am29000)
+{
+ am29000->r[RA] = (I16 << 16) | GET_RA_VAL;
+}
+
+static void CONSTN(am29000_state *am29000)
+{
+ am29000->r[RA] = I16_OEX;
+}
+
+
+/***************************************************************************
+ BRANCH INSTRUCTIONS
+***************************************************************************/
+
+static void CALL(am29000_state *am29000)
+{
+ UINT32 ret = am29000->next_pc;
+
+ if (INST_M_BIT)
+ am29000->next_pc = JMP_ZEX;
+ else
+ am29000->next_pc = am29000->exec_pc + JMP_SEX;
+
+ am29000->r[RA] = ret;
+am29000->next_pl_flags |= PFLAG_JUMP;
+}
+
+static void CALLI(am29000_state *am29000)
+{
+ UINT32 ret = am29000->next_pc;
+ am29000->next_pc = GET_RB_VAL;
+ am29000->r[RA] = ret;
+ am29000->next_pl_flags |= PFLAG_JUMP;
+}
+
+static void JMP(am29000_state *am29000)
+{
+ if (INST_M_BIT)
+ am29000->next_pc = JMP_ZEX;
+ else
+ am29000->next_pc = am29000->exec_pc + JMP_SEX;
+
+ am29000->next_pl_flags |= PFLAG_JUMP;
+}
+
+static void JMPI(am29000_state *am29000)
+{
+ am29000->next_pc = GET_RB_VAL;
+
+ am29000->next_pl_flags |= PFLAG_JUMP;
+}
+
+static void JMPT(am29000_state *am29000)
+{
+ if ((GET_RA_VAL & BOOLEAN_MASK) == BOOLEAN_TRUE)
+ {
+ if (INST_M_BIT)
+ am29000->next_pc = JMP_ZEX;
+ else
+ am29000->next_pc = am29000->exec_pc + JMP_SEX;
+
+ am29000->next_pl_flags |= PFLAG_JUMP;
+ }
+}
+
+static void JMPTI(am29000_state *am29000)
+{
+ if ((GET_RA_VAL & BOOLEAN_MASK) == BOOLEAN_TRUE)
+ {
+ am29000->next_pc = GET_RB_VAL;
+ am29000->next_pl_flags |= PFLAG_JUMP;
+ }
+}
+
+static void JMPF(am29000_state *am29000)
+{
+ if ((GET_RA_VAL & BOOLEAN_MASK) == BOOLEAN_FALSE)
+ {
+ if (INST_M_BIT)
+ am29000->next_pc = JMP_ZEX;
+ else
+ am29000->next_pc = am29000->exec_pc + JMP_SEX;
+
+ am29000->next_pl_flags |= PFLAG_JUMP;
+ }
+}
+
+static void JMPFI(am29000_state *am29000)
+{
+ if ((GET_RA_VAL & BOOLEAN_MASK) == BOOLEAN_FALSE)
+ {
+ am29000->next_pc = GET_RB_VAL;
+ am29000->next_pl_flags |= PFLAG_JUMP;
+ }
+}
+
+static void JMPFDEC(am29000_state *am29000)
+{
+ UINT32 a = GET_RA_VAL;
+
+ if ((a & BOOLEAN_MASK) == BOOLEAN_FALSE)
+ {
+ if (INST_M_BIT)
+ am29000->next_pc = JMP_ZEX;
+ else
+ am29000->next_pc = am29000->exec_pc + JMP_SEX;
+
+ am29000->next_pl_flags |= PFLAG_JUMP;
+ }
+
+ am29000->r[RA] = a - 1;
+}
+
+
+/***************************************************************************
+ MISCELLANEOUS INSTRUCTIONS
+***************************************************************************/
+
+static void CLZ(am29000_state *am29000)
+{
+ UINT32 b = INST_M_BIT ? I8: GET_RB_VAL;
+
+ am29000->r[RC] = count_leading_zeros(b);
+}
+
+static void SETIP(am29000_state *am29000)
+{
+ am29000->ipa = RA << IPX_SHIFT;
+ am29000->ipb = RB << IPX_SHIFT;
+ am29000->ipc = RC << IPX_SHIFT;
+}
+
+static void EMULATE(am29000_state *am29000)
+{
+ UNHANDLED_OP;
+}
+
+static void INV(am29000_state *am29000)
+{
+ /* Nothing to do yet */
+}
+
+static void IRET(am29000_state *am29000)
+{
+ am29000->iret_pc = am29000->pc0;
+ am29000->next_pc = am29000->pc1;
+ am29000->cps = am29000->ops;
+ am29000->next_pl_flags = PFLAG_IRET;
+}
+
+static void IRETINV(am29000_state *am29000)
+{
+ UNHANDLED_OP;
+}
+
+static void HALT(am29000_state *am29000)
+{
+ UNHANDLED_OP;
+}
+
+
+static void ILLEGAL(am29000_state *am29000)
+{
+ fatalerror("Am29000: Executed illegal instruction - this should never happen! %x (%x)\n", am29000->pc2, am29000->exec_pc);
+}
+
+
+
+/***************************************************************************
+ UNHANDLED
+***************************************************************************/
+
+static void CONVERT(am29000_state *am29000)
+{
+ UNHANDLED_OP;
+}
+
+static void SQRT(am29000_state *am29000)
+{
+ UNHANDLED_OP;
+}
+
+static void CLASS(am29000_state *am29000)
+{
+ UNHANDLED_OP;
+}
+
+static void MULTM(am29000_state *am29000)
+{
+ UNHANDLED_OP;
+}
+
+static void MULTMU(am29000_state *am29000)
+{
+ UNHANDLED_OP;
+}
+
+
+const op_info op_table[256] =
+{
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { CONSTN, IFLAG_RA_PRESENT },
+ { CONSTH, IFLAG_RA_PRESENT },
+ { CONST, IFLAG_RA_PRESENT },
+ { MTSRIM, 0 },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { LOADL, 0 },
+ { LOADL, 0 },
+ { CLZ, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT },
+ { CLZ, IFLAG_RC_PRESENT },
+ { EXBYTE, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT },
+ { EXBYTE, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT },
+ { INBYTE, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT },
+ { INBYTE, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT },
+ { STOREL, 0 },
+ { STOREL, 0 },
+ { ADDS, 0 },
+ { ADDS, 0 },
+ { ADDU, 0 },
+ { ADDU, 0 },
+ { ADD, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT },
+ { ADD, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT },
+ { LOAD, IFLAG_RA_PRESENT | IFLAG_RB_PRESENT },
+ { LOAD, IFLAG_RA_PRESENT },
+ { ADDCS, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT },
+ { ADDCS, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT },
+ { ADDCU, 0 },
+ { ADDCU, 0 },
+ { ADDC, 0 },
+ { ADDC, 0 },
+ { STORE, IFLAG_RA_PRESENT | IFLAG_RB_PRESENT },
+ { STORE, IFLAG_RA_PRESENT },
+ { SUBS, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT },
+ { SUBS, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT },
+ { SUBU, 0 },
+ { SUBU, 0 },
+ { SUB, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT },
+ { SUB, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT },
+ { LOADSET, 0 },
+ { LOADSET, 0 },
+ { SUBCS, 0 },
+ { SUBCS, 0 },
+ { SUBCU, 0 },
+ { SUBCU, 0 },
+ { SUBC, 0 },
+ { SUBC, 0 },
+ { CPBYTE, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT },
+ { CPBYTE, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT },
+ { SUBRS, 0 },
+ { SUBRS, 0 },
+ { SUBRU, 0 },
+ { SUBRU, 0 },
+ { SUBR, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT },
+ { SUBR, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT },
+ { LOADM, IFLAG_RA_PRESENT | IFLAG_RB_PRESENT },
+ { LOADM, IFLAG_RA_PRESENT },
+ { SUBRCS, 0 },
+ { SUBRCS, 0 },
+ { SUBRCU, 0 },
+ { SUBRCU, 0 },
+ { SUBRC, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT },
+ { SUBRC, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT },
+ { STOREM, IFLAG_RA_PRESENT | IFLAG_RB_PRESENT },
+ { STOREM, IFLAG_RA_PRESENT },
+ { CPLT, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT },
+ { CPLT, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT },
+ { CPLTU, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT },
+ { CPLTU, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT },
+ { CPLE, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT },
+ { CPLE, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT },
+ { CPLEU, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT },
+ { CPLEU, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT },
+ { CPGT, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT },
+ { CPGT, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT },
+ { CPGTU, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT },
+ { CPGTU, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT },
+ { CPGE, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT },
+ { CPGE, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT },
+ { CPGEU, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT },
+ { CPGEU, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT },
+ { ASLT, IFLAG_RA_PRESENT | IFLAG_RB_PRESENT },
+ { ASLT, IFLAG_RA_PRESENT },
+ { ASLTU, IFLAG_RA_PRESENT | IFLAG_RB_PRESENT },
+ { ASLTU, IFLAG_RA_PRESENT },
+ { ASLE, IFLAG_RA_PRESENT | IFLAG_RB_PRESENT },
+ { ASLE, IFLAG_RA_PRESENT },
+ { ASLEU, IFLAG_RA_PRESENT | IFLAG_RB_PRESENT },
+ { ASLEU, IFLAG_RA_PRESENT },
+ { ASGT, IFLAG_RA_PRESENT | IFLAG_RB_PRESENT },
+ { ASGT, IFLAG_RA_PRESENT },
+ { ASGTU, IFLAG_RA_PRESENT | IFLAG_RB_PRESENT },
+ { ASGTU, IFLAG_RA_PRESENT },
+ { ASGE, IFLAG_RA_PRESENT | IFLAG_RB_PRESENT },
+ { ASGE, IFLAG_RA_PRESENT },
+ { ASGEU, IFLAG_RA_PRESENT | IFLAG_RB_PRESENT },
+ { ASGEU, IFLAG_RA_PRESENT },
+ { CPEQ, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT },
+ { CPEQ, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT },
+ { CPNEQ, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT },
+ { CPNEQ, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT },
+ { MUL, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT | IFLAG_RB_PRESENT },
+ { MUL, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT },
+ { MULL, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT | IFLAG_RB_PRESENT },
+ { MULL, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT },
+ { DIV0, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT },
+ { DIV0, IFLAG_RC_PRESENT },
+ { DIV, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT | IFLAG_RB_PRESENT },
+ { DIV, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT },
+ { DIVL, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT | IFLAG_RB_PRESENT },
+ { DIVL, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT },
+ { DIVREM, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT | IFLAG_RB_PRESENT },
+ { DIVREM, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT },
+ { ASEQ, IFLAG_RA_PRESENT | IFLAG_RB_PRESENT },
+ { ASEQ, IFLAG_RA_PRESENT },
+ { ASNEQ, IFLAG_RA_PRESENT | IFLAG_RB_PRESENT },
+ { ASNEQ, IFLAG_RA_PRESENT },
+ { MULU, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT | IFLAG_RB_PRESENT },
+ { MULU, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { INHW, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT },
+ { INHW, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT },
+ { EXTRACT, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT },
+ { EXTRACT, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT },
+ { EXHW, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT },
+ { EXHW, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT },
+ { EXHWS, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { SLL, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT },
+ { SLL, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT },
+ { SRL, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT },
+ { SRL, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { SRA, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT },
+ { SRA, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT },
+ { IRET, IFLAG_SUPERVISOR_ONLY },
+ { HALT, IFLAG_SUPERVISOR_ONLY },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { IRETINV, IFLAG_SUPERVISOR_ONLY },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { AND, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT },
+ { AND, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT },
+ { OR, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT },
+ { OR, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT },
+ { XOR, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT },
+ { XOR, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT },
+ { XNOR, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT },
+ { XNOR, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT },
+ { NOR, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT },
+ { NOR, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT },
+ { NAND, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT },
+ { NAND, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT },
+ { ANDN, IFLAG_RC_PRESENT | IFLAG_RB_PRESENT | IFLAG_RA_PRESENT },
+ { ANDN, IFLAG_RC_PRESENT | IFLAG_RA_PRESENT },
+ { SETIP, IFLAG_RA_PRESENT | IFLAG_RB_PRESENT | IFLAG_RC_PRESENT },
+ { INV, IFLAG_SUPERVISOR_ONLY },
+ { JMP, 0 },
+ { JMP, 0 },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { JMPF, IFLAG_RA_PRESENT },
+ { JMPF, IFLAG_RA_PRESENT },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { CALL, IFLAG_RA_PRESENT },
+ { CALL, IFLAG_RA_PRESENT },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { JMPT, IFLAG_RA_PRESENT },
+ { JMPT, IFLAG_RA_PRESENT },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { JMPFDEC, IFLAG_RA_PRESENT },
+ { JMPFDEC, IFLAG_RA_PRESENT },
+ { MFTLB, IFLAG_SUPERVISOR_ONLY | IFLAG_RC_PRESENT | IFLAG_RA_PRESENT },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { MTTLB, IFLAG_SUPERVISOR_ONLY | IFLAG_RA_PRESENT | IFLAG_RB_PRESENT },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { JMPI, IFLAG_RB_PRESENT },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { JMPFI, IFLAG_RA_PRESENT | IFLAG_RB_PRESENT },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { MFSR, IFLAG_RC_PRESENT },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { CALLI, IFLAG_RA_PRESENT | IFLAG_RB_PRESENT },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { JMPTI, IFLAG_RA_PRESENT | IFLAG_RB_PRESENT },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { MTSR, IFLAG_RB_PRESENT },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { EMULATE, 0 },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { MULTM, 0 },
+ { MULTMU, 0 },
+ { MULTIPLY, 0 },
+ { DIVIDE, 0 },
+ { MULTIPLU, 0 },
+ { DIVIDU, 0 },
+ { CONVERT, 0 },
+ { SQRT, 0 },
+ { CLASS, 0 },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ { ILLEGAL, IFLAG_ILLEGAL },
+ // FEQ
+ // DEQ
+ // TODO! etc
+};
diff --git a/trunk/src/emu/cpu/apexc/apexc.c b/trunk/src/emu/cpu/apexc/apexc.c
new file mode 100644
index 00000000000..e50ab8e3ce1
--- /dev/null
+++ b/trunk/src/emu/cpu/apexc/apexc.c
@@ -0,0 +1,954 @@
+/*
+ cpu/apexc/apexc.c: APE(X)C CPU emulation
+
+ By Raphael Nabet
+
+ APE(X)C (All Purpose Electronic X-ray Computer) was a computer built by Andrew D. Booth
+ and others for the Birkbeck College, in London, which was used to compute cristal
+ structure using X-ray diffraction.
+
+ It was one of the APEC series of computer, which were simple electronic computers
+ built in the early 1950s for various British Universities. Known members of this series
+ are:
+ * APE(X)C: Birkbeck College, London (before 1953 (1951?))
+ * APE(N)C: Board of Mathematical Machines, Oslo
+ * APE(H)C: British Tabulating Machine Company
+ * APE(R)C: British Rayon Research Association
+ * UCC: University College, London (circa january 1956)
+ * MAC (Magnetic Automatic Calculator): "built by Wharf Engineering Laboratories"
+ (february 1955), which used some germanium diodes
+ * The HEC (built by the British Tabulating Machine Company), a commercial machine sold
+ in two models at least (HEC 2M and HEC 4) (before 1955)
+
+ References:
+ * Andrew D. Booth & Kathleen H. V. Booth: Automatic Digital Calculators, 2nd edition
+ (Buttersworth Scientific Publications, 1956) (referred to as 'Booth&Booth')
+ * Kathleen H. V. Booth: Programming for an Automatic Digital Calculator
+ (Buttersworth Scientific Publications, 1958) (referred to as 'Booth')
+ * Digital Engineering Newsletter vol 7 nb 1 p 60 and vol 8 nb 1 p 60-61 provided some
+ dates
+*/
+
+/*
+ Generals specs:
+ * 32-bit data word size (10-bit addresses): uses fixed-point, 2's complement arithmetic
+ * CPU has one accumulator (A) and one register (R), plus a Control Register (this is
+ what we would call an "instruction register" nowadays). No Program Counter, each
+ instruction contains the address of the next instruction (!).
+ * memory is composed of 256 (maximal value only found on the UCC - APE(X)C only has
+ 32 tracks) circular magnetic tracks of 32 words: only 32 tracks can
+ be accessed at a time (the 16 first ones, plus 16 others chosen by the programmer),
+ and the rotation rate is 3750rpm (62.5 rotations per second).
+ * two I/O units: tape reader and tape puncher. A teletyper was designed to read
+ specially-encoded punched tapes and print decoded text. (See /systems/apexc.c)
+ * machine code has 15 instructions (!), including add, substract, shift, multiply (!),
+ test and branch, input and punch. A so-called vector mode allow to repeat the same
+ operation 32 times with 32 successive memory locations. Note the lack of bitwise
+ and/or/xor (!) .
+ * 1 kIPS, although memory access times make this figure fairly theorical (drum rotation
+ time: 16ms, which would allow about 60IPS when no optimization is made)
+ * there is no indirect addressing whatever, although dynamic modification of opcodes (!)
+ allows to simulate it...
+ * a control panel allows operation and debugging of the machine. (See /systems/apexc.c)
+
+ Conventions:
+ Bits are numbered in big-endian order, starting with 1: bit #1 is the
+ MSBit, and bit #32 is the LSBit.
+
+ References:
+ * Andrew D. Booth & Kathleen H. V. Booth: Automatic Digital Calculators, 2nd edition
+ (Buttersworth Scientific Publications, 1956)
+ * Kathleen H. V. Booth: Programming for an Automatic Digital Calculator
+ (Buttersworth Scientific Publications, 1958)
+*/
+
+/*
+ Machine code (reference: Booth):
+
+ Format of a machine instruction:
+bits: 1-5 6-10 11-15 16-20 21-25 26-31 32
+field: X address X address Y address Y address Function C6 Vector
+ (track) (location) (track) (location)
+
+ Meaning of fields:
+ X: address of an operand, or immediate, or meaningless, depending on Function
+ (When X is meaningless, it should be a duplicate of Y. Maybe this is because
+ X is unintentionnally loaded into the memory address register, and if track # is
+ different, we add unneeded track switch delays (this theory is either wrong or
+ incomplete, since it cannot be true for B or X))
+ Y: address of the next instruction
+ Function: code for the actual instruction executed
+ C6: immediate value used by shift, multiply and store operations
+ Vector: repeat operation 32 times (on all 32 consecutive locations of a track,
+ starting with the location given by the X field)
+
+ Function code:
+ # Mnemonic C6 Description
+
+ 0 Stop
+
+ 2 I(y) Input. A 5-bit word is read from tape and loaded
+ into the 5 MSBits of R. (These bits of R must be
+ cleared initially.)
+
+ 4 P(y) Punch. The 5 MSBits of R are punched onto the
+ output tape.
+
+ 6 B<(x)>=(y) Branch. If A<0, next instruction is fetched from @x, whereas
+ if A>=0, next instruction is fetched from @y
+
+ 8 l (y) n Shift left: the 64 bits of A and R are rotated left n times.
+ n
+
+ 10 r (y) 64-n Shift right: the 64 bits of A and R are shifted right n times.
+ n The sign bit of A is duplicated.
+
+ 14 X (x)(y) 33-n Multiply the contents of *track* x by the last n digits of the
+ n number in R, sending the 32 MSBs to A and 31 LSBs to R
+
+ 16 +c(x)(y) A <- (x)
+
+ 18 -c(x)(y) A <- -(x)
+
+ 20 +(x)(y) A <- A+(x)
+
+ 22 -(x)(y) A <- A-(x)
+
+ 24 T(x)(y) R <- (x)
+
+ 26 R (x)(y) 32+n Store first or last bits of R into (x). The remaining bits of (x)
+ 1-n are unaffected. "The contents of R are filled with 0s or 1s
+ according as the original contents were positive or negative".
+ R (x)(y) n-1
+ n-32
+
+ 28 A (x)(y) 32+n Same as 26, except that source is A, and the contents of A are
+ 1-n not modified.
+
+ A (x)(y) n-1
+ n-32
+
+ 30 S(x)(y) Block Head switch. This enables the block of heads specified
+ in x to be loaded into the working store.
+
+ Note: Mnemonics use subscripts (!), which I tried to render the best I could. Also,
+ ">=" is actually one single character. Last, "1-n" and "n-32" in store mnemonics
+ are the actual sequences "1 *DASH* <number n>" and "<number n> *DASH* 32"
+ (these are NOT formulas with substract signs).
+
+ Note2: Short-hand notations: X stands for X , A for A , and R for R .
+ 32 1-32 1-32
+
+ Note3: Vectors instruction are notated with a subscript 'v' following the basic
+ mnemonic. For instance:
+
+ A (x)(y), + (x)(y)
+ v v
+
+ are the vector counterparts of A(x)(y) and +(x)(y).
+
+
+
+
+ Note that the code has been presented so far as it was in 1957. It appears that
+ it was somewhat different in 1953 (Booth&Booth):
+
+ Format of a machine instruction:
+ Format for r, l, A:
+bits: 1-9 10-15 16-17 18-21 22-30 31-32
+field: X address C6 spare Function Y address spare
+ Format for other instructions:
+bits: 1-9 10-17 18-21 22-30 31-32
+field: X address D Function Y address D (part 2)
+
+ Meaning of fields:
+ D (i.e. drum #): MSBs for the address of the X operand. I don't know whether this feature
+ was actually implemented, since it is said in Booth&Booth that the APE(X)C does
+ not use this feature (it had only one drum of 16 tracks at the time, hence the 9
+ address bits).
+
+ Function code:
+ # Mnemonic C6 Description
+
+ 1 A (x)(y) 32+n(?) record first bits of A in (x). The remaining bits of x
+ 1-n are unaffected.
+
+ 2 +c(x)(y) A <- (x)
+
+ 3 -c(x)(y) A <- -(x)
+
+ 4 +(x)(y) A <- A+(x)
+
+ 5 -(x)(y) A <- A-(x)
+
+ 6 T(x)(y) R <- (x)
+
+ 7 X (x)(y) Multiply the contents of (x) by the number in R,
+ sending the 32 MSBs to A and 31 LSBs to R
+
+ 8 r (y) 64-n(?) Shift right: the 64 bits of A and R are shifted right n times.
+ n The sign bit of A is duplicated.
+
+ 9 l (y) n(?) Shift left: the 64 bits of A and R are rotated left n times.
+ n
+
+ 10 R (x)(y) 32+n record R into (x).
+ 1-n "the contents of R are filled with 0s or 1s
+ according as the original contents were positive or negative".
+
+ 11 B<(x)>=(y) Branch. If A<0, next instruction is read from @x, whereas
+ if A>=0, next instruction is read from @y
+
+ 12 Print(y) Punch. Contents of A are printed.
+
+ 13 C(d+x) branch ("switch Control") to instruction located in position
+ (D:X)
+
+ 14 Stop
+
+ You will notice the absence of input instruction. It seems that program and data were
+ meant to be entered with a teletyper or a card reader located on the control panel.
+
+ I don't know whether this computer really was in operation with this code. Handle
+ these info with caution.
+*/
+
+/*
+ memory interface:
+
+ Data is exchanged on a 1-bit (!) data bus, 10-bit address bus.
+
+ While the bus is 1-bit wide, read/write operation can only be take place on word
+ (i.e. 32 bit) boundaries. However, it is possible to store only the n first bits or
+ n last bits of a word, leaving other bits in memory unaffected.
+
+ The LSBits are transferred first, since this enables to perform bit-per-bit add and
+ substract. Otherwise, the CPU would need an additionnal register to store the second
+ operand, and it would be probably slower, since the operation could only
+ take place after all the data has been transfered.
+
+ Memory operations are synchronous with 2 clocks found on the memory controller:
+ * word clock: a pulse on each word boundary (3750rpm*32 -> 2kHz)
+ * bit clock: a pulse when a bit is present on the bus (word clock * 32 -> 64kHz)
+
+ CPU operation is synchronous with these clocks, too. For instance, the AU does bit-per-bit
+ addition and substraction with a memory operand, synchronously with bit clock,
+ starting and stopping on word clock boundaries. Similar thing with a Fetch operation.
+
+ There is a 10-bit memory location (i.e. address) register on the memory controller.
+ It is loaded with the contents of X after when instruction fetch is complete, and
+ with the contents of Y when instruction execution is complete, so that the next fetch
+ can be executed correctly.
+*/
+
+/*
+ Instruction timings:
+
+
+ References: Booth p. 14 for the table below
+
+
+ Mnemonic delay in word clock cycles
+
+ I 32
+
+ P 32
+
+ B 0
+
+ l 1 if n>=32 (i.e. C6>=32) (see 4.)
+ n 2 if n<32 (i.e. C6<32)
+
+ r 1 if n<=32 (i.e. C6>=32) (see 4.)
+ n 2 if n>32 (i.e. C6<32)
+
+ X 32
+
+ +c, -c, +, -, T 0
+
+ R , R , A , A 1 (see 1. & 4.)
+ 1-n n-32 1-n n-32
+
+ track switch 6 (see 2.)
+
+ vector 12 (see 3.)
+
+
+ (S and stop are missing in the table)
+
+
+ Note that you must add the fetch delay (at least 1 cycle), and, when applicable, the
+ operand read/write delay (at least 1 cycle).
+
+
+ Notes:
+
+ 1. The delay is applied after the store is done (from the analysis of the example
+ in Booth p.52)
+
+ 2. I guess that the memory controller needs 6 cycles to stabilize whenever track
+ switching occurs, i.e. when X does not refer to the current track, and then when Y
+ does not refer to the same track as X. This matches various examples in Booth,
+ although it appears that this delay is not applied when X is not read (cf cross-track
+ B in Booth p. 49).
+ However, and here comes the wacky part, analysis of Booth p. 55 shows that
+ no additionnal delay is caused by an X instruction having its X operand
+ on another track. Maybe, just maybe, this is related to the fact that X does not
+ need to take the word count into account, any word in track is as good as any (yet,
+ this leaves the question of why this optimization could not be applied to vector
+ operations unanswered).
+
+ 3. This is an ambiguous statement. Analysis of Booth p. 55 shows that
+ an instance of an Av instruction with its destination on another track takes no more
+ than 45 cycles, as follow:
+ * 1 cycle for fetch
+ * 6-cycle delay (at most) before write starts (-> track switch)
+ * 32 memory cycles
+ * 6-cycle delay (at most) after write completion (-> track switch)
+ It appears that the delay associated with the vector mode is not distinguishable from
+ the delay caused by track switch and even the delay associated to the Av instruction.
+ Is there really a specific delay associated with the vector mode? To know this, we
+ would need to see a vector instruction on the same track as its operands, which is
+ unlikely to be seen (the only reasonnable application I can see is running a '+_v'
+ to compute the checksum of the current track).
+
+ 4. Example in Booth p. 76 ("20/4 A (27/27) (21/2)") seems to imply that
+ when doing a store with a destination on a track other than the track where next
+ instruction is located, the 1-cycle post-store delay is merged with the 6-cycle track
+ switch delay. (I assume this because there is lots of room on track 21, and if
+ the delays were not merged, it should be easy to move the instruction forward
+ to speed up loop execution time.
+ Similarly, example in Booth p. 49-50 ("4/24 l 32 (5/31)") seems to show that
+ a similar delay merge occurs when doing a shift with the next instruction located on
+ another track.
+*/
+
+#include "emu.h"
+#include "debugger.h"
+#include "apexc.h"
+
+#ifndef SUPPORT_ODD_WORD_SIZES
+#define apexc_readmem(address) cpustate->program->read_dword((address)<<2)
+#define apexc_writemem(address, data) cpustate->program->write_dword((address)<<2, (data))
+/* eewww ! - Fortunately, there is no memory mapped I/O, so we can simulate masked write
+without danger */
+#define apexc_writemem_masked(address, data, mask) \
+ apexc_writemem((address), (apexc_readmem(address) & ~(mask)) | ((data) & (mask)))
+#else
+#define apexc_readmem(address) cpu_readmem13_32(address)
+#define apexc_writemem(address, data) cpu_writemem13_32((address), (data))
+#define apexc_writemem_masked(address, data, mask) cpu_writemem13_32masked((address), (data), (mask))
+#endif
+
+
+#define apexc_readop(address) apexc_readmem(address)
+
+typedef struct _apexc_state apexc_state;
+struct _apexc_state
+{
+ UINT32 a; /* accumulator */
+ UINT32 r; /* register */
+ UINT32 cr; /* control register (i.e. instruction register) */
+ int ml; /* memory location (current track in working store, and requested
+ word position within track) (10 bits) */
+ int working_store; /* current working store (group of 16 tracks) (1-15) */
+ int current_word; /* current word position within track (0-31) */
+
+ int running; /* 1 flag: */
+ /* running: flag implied by the existence of the stop instruction */
+ UINT32 pc; /* address of next instruction for the disassembler */
+
+ legacy_cpu_device *device;
+ address_space *program;
+ address_space *io;
+ int icount;
+};
+
+/* decrement ICount by n */
+#define DELAY(n) {cpustate->icount -= (n); cpustate->current_word = (cpustate->current_word + (n)) & 0x1f;}
+
+
+INLINE apexc_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == APEXC);
+ return (apexc_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+
+/*
+ word accessor functions
+
+ take a 10-bit word address
+ 5 bits (MSBs): track address within working store
+ 5 bits (LSBs): word position within track
+
+ 'special' flag: if true, read first word found in track (used by X instruction only)
+
+ 'mask': one bit is set for each bit to write (used by store instructions)
+
+ memory latency delays are taken into account, but not track switching delays
+*/
+
+/* compute complete word address (i.e. translate a logical track address (expressed
+in current working store) to an absolute track address) */
+static int effective_address(apexc_state *cpustate, int address)
+{
+ if (address & 0x200)
+ {
+ address = (address & 0x1FF) | (cpustate->working_store) << 9;
+ }
+
+ return address;
+}
+
+/* read word */
+static UINT32 word_read(apexc_state *cpustate, int address, int special)
+{
+ UINT32 result;
+
+ /* compute absolute track address */
+ address = effective_address(cpustate, address);
+
+ if (special)
+ {
+ /* ignore word position in x - use current position instead */
+ address = (address & ~ 0x1f) | cpustate->current_word;
+ }
+ else
+ {
+ /* wait for requested word to appear under the heads */
+ DELAY(((address /*& 0x1f*/) - cpustate->current_word) & 0x1f);
+ }
+
+ /* read 32 bits */
+#if 0
+ /* note that the APEXC reads LSBits first */
+ result = 0;
+ for (i=0; i<31; i++)
+ {
+ /*if (mask & (1 << i))*/
+ result |= bit_read((address << 5) | i) << i;
+ }
+#else
+ result = apexc_readmem(address);
+#endif
+
+ /* read takes one memory cycle */
+ DELAY(1);
+
+ return result;
+}
+
+/* write word (or part of a word, according to mask) */
+static void word_write(apexc_state *cpustate, int address, UINT32 data, UINT32 mask)
+{
+ /* compute absolute track address */
+ address = effective_address(cpustate, address);
+
+ /* wait for requested word to appear under the heads */
+ DELAY(((address /*& 0x1f*/) - cpustate->current_word) & 0x1f);
+
+ /* write 32 bits according to mask */
+#if 0
+ /* note that the APEXC reads LSBits first */
+ for (i=0; i<31; i++)
+ {
+ if (mask & (1 << i))
+ bit_write((address << 5) | i, (data >> i) & 1);
+ }
+#else
+ apexc_writemem_masked(address, data, mask);
+#endif
+
+ /* write takes one memory cycle (2, actually, but the 2nd cycle is taken into
+ account in execute) */
+ DELAY(1);
+}
+
+/*
+ I/O accessors
+
+ no address is used, these functions just punch or read 5 bits
+*/
+
+static int papertape_read(apexc_state *cpustate)
+{
+ return cpustate->io->read_byte(0) & 0x1f;
+}
+
+static void papertape_punch(apexc_state *cpustate, int data)
+{
+ cpustate->io->write_byte(0, data);
+}
+
+/*
+ now for emulation code
+*/
+
+/*
+ set the memory location (i.e. address) register, and compute the associated delay
+*/
+INLINE int load_ml(apexc_state *cpustate, int address, int vector)
+{
+ int delay;
+
+ /* additionnal delay appears if we switch tracks */
+ if (((cpustate->ml & 0x3E0) != (address & 0x3E0)) /*|| vector*/)
+ delay = 6; /* if tracks are different, delay to allow for track switching */
+ else
+ delay = 0; /* else, no problem */
+
+ cpustate->ml = address; /* save ml */
+
+ return delay;
+}
+
+/*
+ execute one instruction
+
+ TODO:
+ * test!!!
+
+ NOTE:
+ * I do not know whether we should fetch instructions at the beginning or the end of the
+ instruction cycle. Either solution is roughly equivalent to the other, but changes
+ the control panel operation (and I know virtually nothing on the control panel).
+ Currently, I fetch each instruction right after executing the previous instruction, so that
+ the user may enter an instruction into the control register with the control panel, then
+ execute it.
+ This solution makes timing simulation much simpler, too.
+*/
+static void execute(apexc_state *cpustate)
+{
+ int x, y, function, c6, vector; /* instruction fields */
+ int i = 0; /* misc counter */
+ int has_operand; /* true if instruction is an AU operation with an X operand */
+ static const char has_operand_table[32] = /* table for has_operand - one entry for each function code */
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0
+ };
+ int delay1; /* pre-operand-access delay */
+ int delay2; /* post-operation delay */
+ int delay3; /* pre-operand-fetch delay */
+
+ /* first isolate the instruction fields */
+ x = (cpustate->cr >> 22) & 0x3FF;
+ y = (cpustate->cr >> 12) & 0x3FF;
+ function = (cpustate->cr >> 7) & 0x1F;
+ c6 = (cpustate->cr >> 1) & 0x3F;
+ vector = cpustate->cr & 1;
+ cpustate->pc = y<<2;
+
+ function &= 0x1E; /* this is a mere guess - the LSBit is reserved for future additions */
+
+ /* determinates if we need to read an operand*/
+ has_operand = has_operand_table[function];
+
+ if (has_operand)
+ {
+ /* load ml with X */
+ delay1 = load_ml(cpustate, x, vector);
+ /* burn pre-operand-access delay if needed */
+ if (delay1)
+ {
+ DELAY(delay1);
+ }
+ }
+
+ delay2 = 0; /* default */
+
+ do
+ {
+ switch (function)
+ {
+ case 0:
+ /* stop */
+
+ cpustate->running = FALSE;
+
+ /* BTW, I don't know whether stop loads y into ml or not, and whether
+ subsequent fetch is done */
+ break;
+
+ case 2:
+ /* I */
+ /* I do not know whether the CPU does an OR or whatever, but since docs say that
+ the 5 bits must be cleared initially, an OR kind of makes sense */
+ cpustate->r |= papertape_read(cpustate) << 27;
+ delay2 = 32; /* no idea whether this should be counted as an absolute delay
+ or as a value in delay2 */
+ break;
+
+ case 4:
+ /* P */
+ papertape_punch(cpustate, (cpustate->r >> 27) & 0x1f);
+ delay2 = 32; /* no idea whether this should be counted as an absolute delay
+ or as a value in delay2 */
+ break;
+
+ case 6:
+ /* B<(x)>=(y) */
+ /* I have no idea what we should do if the vector bit is set */
+ if (cpustate->a & 0x80000000UL)
+ {
+ /* load ml with X */
+ delay1 = load_ml(cpustate, x, vector);
+ cpustate->pc = x<<2;
+ /* burn pre-fetch delay if needed */
+ if (delay1)
+ {
+ DELAY(delay1);
+ }
+ /* and do fetch at X */
+ goto special_fetch;
+ }
+ /* else, the instruction ends with a normal fetch */
+ break;
+
+ case 8:
+ /* l_n */
+ delay2 = (c6 & 0x20) ? 1 : 2; /* if more than 32 shifts, it takes more time */
+
+ /* Yes, this code is inefficient, but this must be the way the APEXC does it ;-) */
+ while (c6 != 0)
+ {
+ int shifted_bit = 0;
+
+ /* shift and increment c6 */
+ shifted_bit = cpustate->r & 1;
+ cpustate->r >>= 1;
+ if (cpustate->a & 1)
+ cpustate->r |= 0x80000000UL;
+ cpustate->a >>= 1;
+ if (shifted_bit)
+ cpustate->a |= 0x80000000UL;
+
+ c6 = (c6+1) & 0x3f;
+ }
+
+ break;
+
+ case 10:
+ /* r_n */
+ delay2 = (c6 & 0x20) ? 1 : 2; /* if more than 32 shifts, it takes more time */
+
+ /* Yes, this code is inefficient, but this must be the way the APEXC does it ;-) */
+ while (c6 != 0)
+ {
+ /* shift and increment c6 */
+ cpustate->r >>= 1;
+ if (cpustate->a & 1)
+ cpustate->r |= 0x80000000UL;
+ cpustate->a = ((INT32) cpustate->a) >> 1;
+
+ c6 = (c6+1) & 0x3f;
+ }
+
+ break;
+
+ case 12:
+ /* unused function code. I assume this results into a NOP, for lack of any
+ specific info... */
+
+ break;
+
+ case 14:
+ /* X_n(x) */
+
+ /* Yes, this code is inefficient, but this must be the way the APEXC does it ;-) */
+ /* algorithm found in Booth&Booth, p. 45-48 */
+ {
+ int shifted_bit;
+
+ cpustate->a = 0;
+ shifted_bit = 0;
+ while (1)
+ {
+ /* note we read word at current word position */
+ if (shifted_bit && ! (cpustate->r & 1))
+ cpustate->a += word_read(cpustate, x, 1);
+ else if ((! shifted_bit) && (cpustate->r & 1))
+ cpustate->a -= word_read(cpustate, x, 1);
+ else
+ /* Even if we do not read anything, the loop still takes 1 cycle of
+ the memory word clock. */
+ /* Anyway, maybe we still read the data even if we do not use it. */
+ DELAY(1);
+
+ /* exit if c6 reached 32 ("c6 & 0x20" is simpler to implement and
+ essentially equivalent, so this is most likely the actual implementation) */
+ if (c6 & 0x20)
+ break;
+
+ /* else increment c6 and shift */
+ c6 = (c6+1) & 0x3f;
+
+ /* shift */
+ shifted_bit = cpustate->r & 1;
+ cpustate->r >>= 1;
+ if (cpustate->a & 1)
+ cpustate->r |= 0x80000000UL;
+ cpustate->a = ((INT32) cpustate->a) >> 1;
+ }
+ }
+
+ //DELAY(32); /* mmmh... we have already counted 32 wait states */
+ /* actually, if (n < 32) (which is an untypical case), we do not have 32 wait
+ states. Question is: do we really have 32 wait states if (n < 32), or is
+ the timing table incomplete? */
+ break;
+
+ case 16:
+ /* +c(x) */
+ cpustate->a = + word_read(cpustate, cpustate->ml, 0);
+ break;
+
+ case 18:
+ /* -c(x) */
+ cpustate->a = - word_read(cpustate, cpustate->ml, 0);
+ break;
+
+ case 20:
+ /* +(x) */
+ cpustate->a += word_read(cpustate, cpustate->ml, 0);
+ break;
+
+ case 22:
+ /* -(x) */
+ cpustate->a -= word_read(cpustate, cpustate->ml, 0);
+ break;
+
+ case 24:
+ /* T(x) */
+ cpustate->r = word_read(cpustate, cpustate->ml, 0);
+ break;
+
+ case 26:
+ /* R_(1-n)(x) & R_(n-32)(x) */
+
+ {
+ UINT32 mask;
+
+ if (c6 & 0x20)
+ mask = 0xFFFFFFFFUL << (64 - c6);
+ else
+ mask = 0xFFFFFFFFUL >> c6;
+
+ word_write(cpustate, cpustate->ml, cpustate->r, mask);
+ }
+
+ cpustate->r = (cpustate->r & 0x80000000UL) ? 0xFFFFFFFFUL : 0;
+
+ delay2 = 1;
+ break;
+
+ case 28:
+ /* A_(1-n)(x) & A_(n-32)(x) */
+
+ {
+ UINT32 mask;
+
+ if (c6 & 0x20)
+ mask = 0xFFFFFFFFUL << (64 - c6);
+ else
+ mask = 0xFFFFFFFFUL >> c6;
+
+ word_write(cpustate, cpustate->ml, cpustate->a, mask);
+ }
+
+ delay2 = 1;
+ break;
+
+ case 30:
+ /* S(x) */
+ cpustate->working_store = (x >> 5) & 0xf; /* or is it (x >> 6)? */
+ DELAY(32); /* no idea what the value is... All I know is that it takes much
+ more time than track switching (which takes 6 cycles) */
+ break;
+ }
+ if (vector)
+ /* increment word position in vector operations */
+ cpustate->ml = (cpustate->ml & 0x3E0) | ((cpustate->ml + 1) & 0x1F);
+ } while (vector && has_operand && (++i < 32)); /* iterate 32 times if vector bit is set */
+ /* the has_operand is a mere guess */
+
+ /* load ml with Y */
+ delay3 = load_ml(cpustate, y, 0);
+
+ /* compute max(delay2, delay3) */
+ if (delay2 > delay3)
+ delay3 = delay2;
+
+ /* burn pre-fetch delay if needed */
+ if (delay3)
+ {
+ DELAY(delay3);
+ }
+
+ /* entry point after a successful Branch (which alters the normal instruction sequence,
+ in order not to load ml with Y) */
+special_fetch:
+
+ /* fetch current instruction into control register */
+ cpustate->cr = word_read(cpustate, cpustate->ml, 0);
+}
+
+
+static CPU_INIT( apexc )
+{
+ apexc_state *cpustate = get_safe_token(device);
+
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->io = device->space(AS_IO);
+
+ device->save_item(NAME(cpustate->a));
+ device->save_item(NAME(cpustate->r));
+ device->save_item(NAME(cpustate->cr));
+ device->save_item(NAME(cpustate->ml));
+ device->save_item(NAME(cpustate->working_store));
+ device->save_item(NAME(cpustate->current_word));
+ device->save_item(NAME(cpustate->running));
+ device->save_item(NAME(cpustate->pc));
+}
+
+static CPU_RESET( apexc )
+{
+ apexc_state *cpustate = get_safe_token(device);
+
+ /* mmmh... I don't know what happens on reset with an actual APEXC. */
+
+ cpustate->working_store = 1; /* mere guess */
+ cpustate->current_word = 0; /* well, we do have to start somewhere... */
+
+ /* next two lines are just the product of my bold fantasy */
+ cpustate->cr = 0; /* first instruction executed will be a stop */
+ cpustate->running = TRUE; /* this causes the CPU to load the instruction at 0/0,
+ which enables easy booting (just press run on the panel) */
+}
+
+static CPU_EXECUTE( apexc )
+{
+ apexc_state *cpustate = get_safe_token(device);
+
+ do
+ {
+ debugger_instruction_hook(device, cpustate->pc);
+
+ if (cpustate->running)
+ execute(cpustate);
+ else
+ {
+ DELAY(cpustate->icount); /* burn cycles once for all */
+ }
+ } while (cpustate->icount > 0);
+}
+
+static CPU_SET_INFO( apexc )
+{
+ apexc_state *cpustate = get_safe_token(device);
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ /*case CPUINFO_INT_INPUT_STATE + ...:*/ /* no interrupts */
+
+ case CPUINFO_INT_PC:
+ /* keep address 9 LSBits - 10th bit depends on whether we are accessing the permanent
+ track group or a switchable one */
+ cpustate->ml = info->i & 0x1ff;
+ if (info->i & 0x1e00)
+ { /* we are accessing a switchable track group */
+ cpustate->ml |= 0x200; /* set 10th bit */
+
+ if (((info->i >> 9) & 0xf) != cpustate->working_store)
+ { /* we need to do a store switch */
+ cpustate->working_store = ((info->i >> 9) & 0xf);
+ }
+ }
+ break;
+
+ case CPUINFO_INT_SP: (void) info->i; /* no SP */ break;
+
+ case CPUINFO_INT_REGISTER + APEXC_CR: cpustate->cr = info->i; break;
+ case CPUINFO_INT_REGISTER + APEXC_A: cpustate->a = info->i; break;
+ case CPUINFO_INT_REGISTER + APEXC_R: cpustate->r = info->i; break;
+ case CPUINFO_INT_REGISTER + APEXC_ML: cpustate->ml = info->i & 0x3ff; break;
+ case CPUINFO_INT_REGISTER + APEXC_PC: cpustate->pc = info->i; break;
+ case CPUINFO_INT_REGISTER + APEXC_WS: cpustate->working_store = info->i & 0xf; break;
+ case CPUINFO_INT_REGISTER + APEXC_STATE: cpustate->running = info->i ? TRUE : FALSE; break;
+ }
+}
+
+CPU_GET_INFO( apexc )
+{
+ apexc_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(apexc_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 0; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; /*don't care*/ break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 2; /* IIRC */ break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 75; /* IIRC */ break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 15; /*13+2 ignored bits to make double word address*/ break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = /*5*/8; /* no I/O bus, but we use address 0 for punchtape I/O */ break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = /*0*/1; /*0 is quite enough but the MAME core does not understand*/ break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_SP: info->i = 0; /* no SP */ break;
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_PREVIOUSPC: info->i = cpustate->pc; /* psuedo-PC */ break;
+
+ /*case CPUINFO_INT_INPUT_STATE + ...:*/ /* no interrupts */
+
+ case CPUINFO_INT_REGISTER + APEXC_CR: info->i = cpustate->cr; break;
+ case CPUINFO_INT_REGISTER + APEXC_A: info->i = cpustate->a; break;
+ case CPUINFO_INT_REGISTER + APEXC_R: info->i = cpustate->r; break;
+ case CPUINFO_INT_REGISTER + APEXC_ML: info->i = cpustate->ml; break;
+ case CPUINFO_INT_REGISTER + APEXC_PC: info->i = cpustate->pc; break;
+ case CPUINFO_INT_REGISTER + APEXC_WS: info->i = cpustate->working_store; break;
+ case CPUINFO_INT_REGISTER + APEXC_STATE: info->i = cpustate->running; break;
+ case CPUINFO_INT_REGISTER + APEXC_ML_FULL: info->i = effective_address(cpustate, cpustate->ml); break;
+
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(apexc); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(apexc); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(apexc); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(apexc); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(apexc); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+
+ case DEVINFO_STR_NAME: strcpy(info->s, "APEXC"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "APEC"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Raphael Nabet"); break;
+
+ case CPUINFO_STR_FLAGS: sprintf(info->s, "%c", (cpustate->running) ? 'R' : 'S'); break;
+
+ case CPUINFO_STR_REGISTER + APEXC_CR: sprintf(info->s, "CR:%08X", cpustate->cr); break;
+ case CPUINFO_STR_REGISTER + APEXC_A: sprintf(info->s, "A :%08X", cpustate->a); break;
+ case CPUINFO_STR_REGISTER + APEXC_R: sprintf(info->s, "R :%08X", cpustate->r); break;
+ case CPUINFO_STR_REGISTER + APEXC_ML: sprintf(info->s, "ML:%03X", cpustate->ml); break;
+ case CPUINFO_STR_REGISTER + APEXC_PC: sprintf(info->s, "PC:%03X", cpustate->pc); break;
+ case CPUINFO_STR_REGISTER + APEXC_WS: sprintf(info->s, "WS:%01X", cpustate->working_store); break;
+
+ case CPUINFO_STR_REGISTER + APEXC_STATE: sprintf(info->s, "CPU state:%01X", cpustate->running ? TRUE : FALSE); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(APEXC, apexc);
diff --git a/trunk/src/emu/cpu/apexc/apexc.h b/trunk/src/emu/cpu/apexc/apexc.h
new file mode 100644
index 00000000000..553b1d87cf0
--- /dev/null
+++ b/trunk/src/emu/cpu/apexc/apexc.h
@@ -0,0 +1,26 @@
+/* register names for apexc_get_reg & apexc_set_reg */
+#pragma once
+
+#ifndef __APEXC_H__
+#define __APEXC_H__
+
+enum
+{
+ APEXC_CR =1, /* control register */
+ APEXC_A, /* acumulator */
+ APEXC_R, /* register */
+ APEXC_ML, /* memory location */
+ APEXC_WS, /* working store */
+ APEXC_STATE, /* whether CPU is running */
+
+ APEXC_ML_FULL, /* read-only pseudo-register for exclusive use by the control panel code
+ in the apexc driver : enables it to get the complete address computed
+ from the contents of ML and WS */
+ APEXC_PC /* doesn't actually exist; is there for the disassembler */
+};
+
+DECLARE_LEGACY_CPU_DEVICE(APEXC, apexc);
+
+CPU_DISASSEMBLE( apexc );
+
+#endif /* __APEXC_H__ */
diff --git a/trunk/src/emu/cpu/apexc/apexcdsm.c b/trunk/src/emu/cpu/apexc/apexcdsm.c
new file mode 100644
index 00000000000..61752703f74
--- /dev/null
+++ b/trunk/src/emu/cpu/apexc/apexcdsm.c
@@ -0,0 +1,183 @@
+/*
+ cpu/apexc/apexcsm.c : APE(X)C CPU disassembler
+
+ By Raphael Nabet
+
+ see cpu/apexc.c for background and tech info
+*/
+
+
+#include "emu.h"
+#include "debugger.h"
+
+#include "apexc.h"
+
+/*
+ Here is the format used for debugger output.
+
+ Since the only assembler for the APEXC that I know of uses numerical data
+ (yes, mnemonics are numbers), I do not know if there is an official way of writing
+ APEXC assembly on a text terminal. The format I chose is closely inspired by
+ the assembly format found in Booth, but was slightly adapted to accommodate
+ the lack of subscripts and of a 'greater or equal' character.
+
+ Printed format Name
+ 0 1 2
+ 012345678901234567890123456
+ Stop (##/##) one_address
+ I (##/##) one_address
+ P (##/##) one_address
+ B <(##/##) >=(##/##) branch
+ l (##) (##/##) shiftl
+ r (##) (##/##) shiftr
+ Illegal (##/##) one_address
+ X (##) (##) (##/##) multiply
+ X (##) (##/##) multiply
+ +c (##/##) (##/##) two_address
+ -c (##/##) (##/##) two_address
+ + (##/##) (##/##) two_address
+ - (##/##) (##/##) two_address
+ T (##/##) (##/##) two_address
+ R (1-##) (##/##) (##/##) store
+ R (##-32) (##/##) (##/##) store
+ R (##/##) (##/##) store
+ A (1-##) (##/##) (##/##) store
+ A (##-32) (##/##) (##/##) store
+ A (##/##) (##/##) store
+ S (##) (##/##) swap
+ +--------++--------++-----+
+ mnemonic X field Y field
+ field
+
+ For vector instructions, replace the first space on the right of the mnemonic
+ with a 'v'.
+
+ 01-Feb-2010 (Robbbert):
+ I've added the actual address, (as shown in the extreme left of the debugger
+ output), so that you can see much easier how the program will flow. Example:
+
+ +C XXX(##/##) XXX(##/##)
+
+ The X value shows where the data word is located, and the Y value is the
+ address of the next instruction.
+*/
+enum _format_type {branch, shiftl, shiftr, multiply, store, swap, one_address, two_address};
+typedef enum _format_type format_type;
+
+typedef struct instr_desc
+{
+ const char *mnemonic;
+ format_type format; /* -> X and Y are format */
+} instr_desc;
+
+static const instr_desc instructions[16] =
+{
+ { "Stop", one_address }, { "I", one_address },
+ { "P", one_address }, { "B", branch },
+ { "l", shiftl }, { "r", shiftr },
+ { "Illegal",one_address }, { "X", multiply },
+ { "+c", two_address }, { "-c", two_address },
+ { "+", two_address }, { "-", two_address },
+ { "T", two_address }, { "R", store },
+ { "A", store }, { "S", swap }
+};
+
+CPU_DISASSEMBLE( apexc )
+{
+ UINT32 instruction; /* 32-bit machine instruction */
+ int x, y, function, c6, vector; /* instruction fields */
+ int n; /* 'friendly', instruction-dependant interpretation of C6 */
+ const instr_desc *the_desc; /* pointer to the revelant entry in the instructions array */
+ char mnemonic[9]; /* storage for generated mnemonic */
+
+ /* read the instruction to disassemble */
+ instruction = oprom[0] << 24 | oprom[1] << 16 | oprom[2] << 8 | oprom[3];
+
+ /* isolate the instruction fields */
+ x = (instruction >> 22) & 0x3FF;
+ y = (instruction >> 12) & 0x3FF;
+ function = (instruction >> 7) & 0x1F;
+ c6 = (instruction >> 1) & 0x3F;
+ vector = instruction & 1;
+
+ /* get the revelant entry in instructions */
+ the_desc = & instructions[function >> 1];
+
+ /* generate mnemonic : append a 'v' to the basic mnemonic if it is a vector instruction */
+ sprintf(mnemonic, "%.*s%c", (int)sizeof(mnemonic)-2, the_desc->mnemonic, vector ? 'v' : ' ');
+
+ /* print mnemonic and n immediate */
+ switch (the_desc->format)
+ {
+ case one_address:
+ case two_address:
+ case branch:
+ case swap:
+ buffer += sprintf(buffer, " %-10s", mnemonic); /* 10 chars*/
+ break;
+
+ case shiftl:
+ case shiftr:
+ if (the_desc->format == shiftl)
+ n = c6;
+ else
+ n = 64-c6;
+ buffer += sprintf(buffer, " %-2s(%2d) ", mnemonic, n); /* 10 chars */
+ break;
+
+ case multiply:
+ n = 33-c6;
+ if (n == 32)
+ /* case "32" : do not show bit specifier */
+ buffer += sprintf(buffer, " %-10s", mnemonic); /* 10 chars */
+ else
+ buffer += sprintf(buffer, " %-2s(%2d) ", mnemonic, n); /* 10 chars */
+ break;
+
+ case store:
+ if (c6 == 0)
+ { /* case "1-32" : do not show bit specifier */
+ buffer += sprintf(buffer, " %-10s", mnemonic); /* 10 chars*/
+ }
+ else if (c6 & 0x20)
+ { /* case "1-n" */
+ n = c6-32;
+ buffer += sprintf(buffer, " %-2s (1-%02d) ", mnemonic, n); /* 10 chars */
+ }
+ else
+ { /* case "n-32" */
+ n = c6+1;
+ buffer += sprintf(buffer, " %-2s(%02d-32) ", mnemonic, n); /* 8 chars */
+ }
+ }
+
+ /* print X address */
+ switch (the_desc->format)
+ {
+ case branch:
+ buffer--; /* eat last char */
+ buffer += sprintf(buffer, "<%03X(%02d/%02d) >=", x<<2, (x >> 5) & 0x1f, x & 0x1f); /* 10+1 chars */
+ break;
+
+ case multiply:
+ case swap:
+ buffer += sprintf(buffer, " (%02d) ", (x >> 5) & 0x1f); /* 10 chars */
+ break;
+
+ case one_address:
+ case shiftl:
+ case shiftr:
+ buffer += sprintf(buffer, " "); /* 10 chars */
+ break;
+
+ case two_address:
+ case store:
+ buffer += sprintf(buffer, "%03X(%02d/%02d) ", x<<2, (x >> 5) & 0x1f, x & 0x1f); /* 10 chars */
+ break;
+ }
+
+ /* print Y address */
+ buffer += sprintf(buffer, "%03X(%02d/%02d)", y<<2, (y >> 5) & 0x1f, y & 0x1f); /* 7 chars */
+
+ return 4;
+}
diff --git a/trunk/src/emu/cpu/arm/arm.c b/trunk/src/emu/cpu/arm/arm.c
new file mode 100644
index 00000000000..efe4102a7ce
--- /dev/null
+++ b/trunk/src/emu/cpu/arm/arm.c
@@ -0,0 +1,1651 @@
+/* arm.c
+
+ ARM 2/3/6 Emulation (26 bit address bus)
+
+ Todo:
+ Timing - Currently very approximated, nothing relies on proper timing so far.
+ IRQ timing not yet correct (again, nothing is affected by this so far).
+
+ Recent changes (2005):
+ Fixed software interrupts
+ Fixed various mode change bugs
+ Added preliminary co-processor support.
+
+ By Bryan McPhail (bmcphail@tendril.co.uk) and Phil Stroffolino
+
+*/
+
+#include "emu.h"
+#include "debugger.h"
+#include "arm.h"
+
+CPU_DISASSEMBLE( arm );
+CPU_DISASSEMBLE( arm_be );
+
+#define READ8(addr) cpu_read8(cpustate,addr)
+#define WRITE8(addr,data) cpu_write8(cpustate,addr,data)
+#define READ32(addr) cpu_read32(cpustate,addr)
+#define WRITE32(addr,data) cpu_write32(cpustate,addr,data)
+
+#define ARM_DEBUG_CORE 0
+#define ARM_DEBUG_COPRO 0
+
+enum
+{
+ eARM_MODE_USER = 0x0,
+ eARM_MODE_FIQ = 0x1,
+ eARM_MODE_IRQ = 0x2,
+ eARM_MODE_SVC = 0x3,
+
+ kNumModes
+};
+
+/* There are 27 32 bit processor registers */
+enum
+{
+ eR0=0,eR1,eR2,eR3,eR4,eR5,eR6,eR7,
+ eR8,eR9,eR10,eR11,eR12,
+ eR13, /* Stack Pointer */
+ eR14, /* Link Register (holds return address) */
+ eR15, /* Program Counter */
+
+ /* Fast Interrupt */
+ eR8_FIQ,eR9_FIQ,eR10_FIQ,eR11_FIQ,eR12_FIQ,eR13_FIQ,eR14_FIQ,
+
+ /* IRQ */
+ eR13_IRQ,eR14_IRQ,
+
+ /* Software Interrupt */
+ eR13_SVC,eR14_SVC,
+
+ kNumRegisters
+};
+
+/* 16 processor registers are visible at any given time,
+ * banked depending on processor mode.
+ */
+static const int sRegisterTable[kNumModes][16] =
+{
+ { /* USR */
+ eR0,eR1,eR2,eR3,eR4,eR5,eR6,eR7,
+ eR8,eR9,eR10,eR11,eR12,
+ eR13,eR14,
+ eR15
+ },
+ { /* FIQ */
+ eR0,eR1,eR2,eR3,eR4,eR5,eR6,eR7,
+ eR8_FIQ,eR9_FIQ,eR10_FIQ,eR11_FIQ,eR12_FIQ,
+ eR13_FIQ,eR14_FIQ,
+ eR15
+ },
+ { /* IRQ */
+ eR0,eR1,eR2,eR3,eR4,eR5,eR6,eR7,
+ eR8,eR9,eR10,eR11,eR12,
+ eR13_IRQ,eR14_IRQ,
+ eR15
+ },
+ { /* SVC */
+ eR0,eR1,eR2,eR3,eR4,eR5,eR6,eR7,
+ eR8,eR9,eR10,eR11,eR12,
+ eR13_SVC,eR14_SVC,
+ eR15
+ }
+};
+
+#define N_BIT 31
+#define Z_BIT 30
+#define C_BIT 29
+#define V_BIT 28
+#define I_BIT 27
+#define F_BIT 26
+
+#define N_MASK ((UINT32)(1<<N_BIT)) /* Negative flag */
+#define Z_MASK ((UINT32)(1<<Z_BIT)) /* Zero flag */
+#define C_MASK ((UINT32)(1<<C_BIT)) /* Carry flag */
+#define V_MASK ((UINT32)(1<<V_BIT)) /* oVerflow flag */
+#define I_MASK ((UINT32)(1<<I_BIT)) /* Interrupt request disable */
+#define F_MASK ((UINT32)(1<<F_BIT)) /* Fast interrupt request disable */
+
+#define N_IS_SET(pc) ((pc) & N_MASK)
+#define Z_IS_SET(pc) ((pc) & Z_MASK)
+#define C_IS_SET(pc) ((pc) & C_MASK)
+#define V_IS_SET(pc) ((pc) & V_MASK)
+#define I_IS_SET(pc) ((pc) & I_MASK)
+#define F_IS_SET(pc) ((pc) & F_MASK)
+
+#define N_IS_CLEAR(pc) (!N_IS_SET(pc))
+#define Z_IS_CLEAR(pc) (!Z_IS_SET(pc))
+#define C_IS_CLEAR(pc) (!C_IS_SET(pc))
+#define V_IS_CLEAR(pc) (!V_IS_SET(pc))
+#define I_IS_CLEAR(pc) (!I_IS_SET(pc))
+#define F_IS_CLEAR(pc) (!F_IS_SET(pc))
+
+#define PSR_MASK ((UINT32) 0xf0000000u)
+#define IRQ_MASK ((UINT32) 0x0c000000u)
+#define ADDRESS_MASK ((UINT32) 0x03fffffcu)
+#define MODE_MASK ((UINT32) 0x00000003u)
+
+#define R15 cpustate->sArmRegister[eR15]
+#define MODE (R15&0x03)
+#define SIGN_BIT ((UINT32)(1<<31))
+#define SIGN_BITS_DIFFER(a,b) (((a)^(b)) >> 31)
+
+/* Deconstructing an instruction */
+
+#define INSN_COND ((UINT32) 0xf0000000u)
+#define INSN_SDT_L ((UINT32) 0x00100000u)
+#define INSN_SDT_W ((UINT32) 0x00200000u)
+#define INSN_SDT_B ((UINT32) 0x00400000u)
+#define INSN_SDT_U ((UINT32) 0x00800000u)
+#define INSN_SDT_P ((UINT32) 0x01000000u)
+#define INSN_BDT_L ((UINT32) 0x00100000u)
+#define INSN_BDT_W ((UINT32) 0x00200000u)
+#define INSN_BDT_S ((UINT32) 0x00400000u)
+#define INSN_BDT_U ((UINT32) 0x00800000u)
+#define INSN_BDT_P ((UINT32) 0x01000000u)
+#define INSN_BDT_REGS ((UINT32) 0x0000ffffu)
+#define INSN_SDT_IMM ((UINT32) 0x00000fffu)
+#define INSN_MUL_A ((UINT32) 0x00200000u)
+#define INSN_MUL_RM ((UINT32) 0x0000000fu)
+#define INSN_MUL_RS ((UINT32) 0x00000f00u)
+#define INSN_MUL_RN ((UINT32) 0x0000f000u)
+#define INSN_MUL_RD ((UINT32) 0x000f0000u)
+#define INSN_I ((UINT32) 0x02000000u)
+#define INSN_OPCODE ((UINT32) 0x01e00000u)
+#define INSN_S ((UINT32) 0x00100000u)
+#define INSN_BL ((UINT32) 0x01000000u)
+#define INSN_BRANCH ((UINT32) 0x00ffffffu)
+#define INSN_SWI ((UINT32) 0x00ffffffu)
+#define INSN_RN ((UINT32) 0x000f0000u)
+#define INSN_RD ((UINT32) 0x0000f000u)
+#define INSN_OP2 ((UINT32) 0x00000fffu)
+#define INSN_OP2_SHIFT ((UINT32) 0x00000f80u)
+#define INSN_OP2_SHIFT_TYPE ((UINT32) 0x00000070u)
+#define INSN_OP2_RM ((UINT32) 0x0000000fu)
+#define INSN_OP2_ROTATE ((UINT32) 0x00000f00u)
+#define INSN_OP2_IMM ((UINT32) 0x000000ffu)
+#define INSN_OP2_SHIFT_TYPE_SHIFT 4
+#define INSN_OP2_SHIFT_SHIFT 7
+#define INSN_OP2_ROTATE_SHIFT 8
+#define INSN_MUL_RS_SHIFT 8
+#define INSN_MUL_RN_SHIFT 12
+#define INSN_MUL_RD_SHIFT 16
+#define INSN_OPCODE_SHIFT 21
+#define INSN_RN_SHIFT 16
+#define INSN_RD_SHIFT 12
+#define INSN_COND_SHIFT 28
+
+#define S_CYCLE 1
+#define N_CYCLE 1
+#define I_CYCLE 1
+
+enum
+{
+ OPCODE_AND, /* 0000 */
+ OPCODE_EOR, /* 0001 */
+ OPCODE_SUB, /* 0010 */
+ OPCODE_RSB, /* 0011 */
+ OPCODE_ADD, /* 0100 */
+ OPCODE_ADC, /* 0101 */
+ OPCODE_SBC, /* 0110 */
+ OPCODE_RSC, /* 0111 */
+ OPCODE_TST, /* 1000 */
+ OPCODE_TEQ, /* 1001 */
+ OPCODE_CMP, /* 1010 */
+ OPCODE_CMN, /* 1011 */
+ OPCODE_ORR, /* 1100 */
+ OPCODE_MOV, /* 1101 */
+ OPCODE_BIC, /* 1110 */
+ OPCODE_MVN /* 1111 */
+};
+
+enum
+{
+ COND_EQ = 0, /* Z: equal */
+ COND_NE, /* ~Z: not equal */
+ COND_CS, COND_HS = 2, /* C: unsigned higher or same */
+ COND_CC, COND_LO = 3, /* ~C: unsigned lower */
+ COND_MI, /* N: negative */
+ COND_PL, /* ~N: positive or zero */
+ COND_VS, /* V: overflow */
+ COND_VC, /* ~V: no overflow */
+ COND_HI, /* C && ~Z: unsigned higher */
+ COND_LS, /* ~C || Z: unsigned lower or same */
+ COND_GE, /* N == V: greater or equal */
+ COND_LT, /* N != V: less than */
+ COND_GT, /* ~Z && (N == V): greater than */
+ COND_LE, /* Z || (N != V): less than or equal */
+ COND_AL, /* always */
+ COND_NV /* never */
+};
+
+#define LSL(v,s) ((v) << (s))
+#define LSR(v,s) ((v) >> (s))
+#define ROL(v,s) (LSL((v),(s)) | (LSR((v),32u - (s))))
+#define ROR(v,s) (LSR((v),(s)) | (LSL((v),32u - (s))))
+
+/* Private Data */
+
+/* sArmRegister defines the CPU state */
+typedef struct
+{
+ int icount;
+ UINT32 sArmRegister[kNumRegisters];
+ UINT32 coproRegister[16];
+ UINT8 pendingIrq;
+ UINT8 pendingFiq;
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ endianness_t endian;
+} ARM_REGS;
+
+/* Prototypes */
+static void HandleALU( ARM_REGS* cpustate, UINT32 insn);
+static void HandleMul( ARM_REGS* cpustate, UINT32 insn);
+static void HandleBranch( ARM_REGS* cpustate, UINT32 insn);
+static void HandleMemSingle( ARM_REGS* cpustate, UINT32 insn);
+static void HandleMemBlock( ARM_REGS* cpustate, UINT32 insn);
+static void HandleCoPro( ARM_REGS* cpustate, UINT32 insn);
+static UINT32 decodeShift( ARM_REGS* cpustate, UINT32 insn, UINT32 *pCarry);
+static void arm_check_irq_state(ARM_REGS* cpustate);
+
+/***************************************************************************/
+
+INLINE ARM_REGS *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == ARM || device->type() == ARM_BE);
+ return (ARM_REGS *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+INLINE void cpu_write32( ARM_REGS* cpustate, int addr, UINT32 data )
+{
+ /* Unaligned writes are treated as normal writes */
+ if ( cpustate->endian == ENDIANNESS_BIG )
+ cpustate->program->write_dword(addr&ADDRESS_MASK,data);
+ else
+ cpustate->program->write_dword(addr&ADDRESS_MASK,data);
+ if (ARM_DEBUG_CORE && addr&3) logerror("%08x: Unaligned write %08x\n",R15,addr);
+}
+
+INLINE void cpu_write8( ARM_REGS* cpustate, int addr, UINT8 data )
+{
+ if ( cpustate->endian == ENDIANNESS_BIG )
+ cpustate->program->write_byte(addr,data);
+ else
+ cpustate->program->write_byte(addr,data);
+}
+
+INLINE UINT32 cpu_read32( ARM_REGS* cpustate, int addr )
+{
+ UINT32 result;
+
+ if ( cpustate->endian == ENDIANNESS_BIG )
+ result = cpustate->program->read_dword(addr&ADDRESS_MASK);
+ else
+ result = cpustate->program->read_dword(addr&ADDRESS_MASK);
+
+ /* Unaligned reads rotate the word, they never combine words */
+ if (addr&3) {
+ if (ARM_DEBUG_CORE && addr&1)
+ logerror("%08x: Unaligned byte read %08x\n",R15,addr);
+
+ if ((addr&3)==1)
+ return ((result&0x000000ff)<<24)|((result&0xffffff00)>> 8);
+ if ((addr&3)==2)
+ return ((result&0x0000ffff)<<16)|((result&0xffff0000)>>16);
+ if ((addr&3)==3)
+ return ((result&0x00ffffff)<< 8)|((result&0xff000000)>>24);
+ }
+
+ return result;
+}
+
+INLINE UINT8 cpu_read8( ARM_REGS* cpustate, int addr )
+{
+ if ( cpustate->endian == ENDIANNESS_BIG )
+ return cpustate->program->read_byte(addr);
+ else
+ return cpustate->program->read_byte(addr);
+}
+
+INLINE UINT32 GetRegister( ARM_REGS* cpustate, int rIndex )
+{
+ return cpustate->sArmRegister[sRegisterTable[MODE][rIndex]];
+}
+
+INLINE void SetRegister( ARM_REGS* cpustate, int rIndex, UINT32 value )
+{
+ cpustate->sArmRegister[sRegisterTable[MODE][rIndex]] = value;
+}
+
+INLINE UINT32 GetModeRegister( ARM_REGS* cpustate, int mode, int rIndex )
+{
+ return cpustate->sArmRegister[sRegisterTable[mode][rIndex]];
+}
+
+INLINE void SetModeRegister( ARM_REGS* cpustate, int mode, int rIndex, UINT32 value )
+{
+ cpustate->sArmRegister[sRegisterTable[mode][rIndex]] = value;
+}
+
+
+/***************************************************************************/
+
+static CPU_RESET( arm )
+{
+ ARM_REGS *cpustate = get_safe_token(device);
+
+ device_irq_callback save_irqcallback = cpustate->irq_callback;
+ endianness_t save_endian = cpustate->endian;
+
+ memset(cpustate, 0, sizeof(ARM_REGS));
+ cpustate->irq_callback = save_irqcallback;
+ cpustate->endian = save_endian;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+
+ /* start up in SVC mode with interrupts disabled. */
+ R15 = eARM_MODE_SVC|I_MASK|F_MASK;
+}
+
+static CPU_EXIT( arm )
+{
+ /* nothing to do here */
+}
+
+static CPU_EXECUTE( arm )
+{
+ UINT32 pc;
+ UINT32 insn;
+ ARM_REGS *cpustate = get_safe_token(device);
+
+ do
+ {
+ debugger_instruction_hook(device, R15 & ADDRESS_MASK);
+
+ /* load instruction */
+ pc = R15;
+ insn = cpustate->direct->read_decrypted_dword( pc & ADDRESS_MASK );
+
+ switch (insn >> INSN_COND_SHIFT)
+ {
+ case COND_EQ:
+ if (Z_IS_CLEAR(pc)) goto L_Next;
+ break;
+ case COND_NE:
+ if (Z_IS_SET(pc)) goto L_Next;
+ break;
+ case COND_CS:
+ if (C_IS_CLEAR(pc)) goto L_Next;
+ break;
+ case COND_CC:
+ if (C_IS_SET(pc)) goto L_Next;
+ break;
+ case COND_MI:
+ if (N_IS_CLEAR(pc)) goto L_Next;
+ break;
+ case COND_PL:
+ if (N_IS_SET(pc)) goto L_Next;
+ break;
+ case COND_VS:
+ if (V_IS_CLEAR(pc)) goto L_Next;
+ break;
+ case COND_VC:
+ if (V_IS_SET(pc)) goto L_Next;
+ break;
+ case COND_HI:
+ if (C_IS_CLEAR(pc) || Z_IS_SET(pc)) goto L_Next;
+ break;
+ case COND_LS:
+ if (C_IS_SET(pc) && Z_IS_CLEAR(pc)) goto L_Next;
+ break;
+ case COND_GE:
+ if (!(pc & N_MASK) != !(pc & V_MASK)) goto L_Next; /* Use x ^ (x >> ...) method */
+ break;
+ case COND_LT:
+ if (!(pc & N_MASK) == !(pc & V_MASK)) goto L_Next;
+ break;
+ case COND_GT:
+ if (Z_IS_SET(pc) || (!(pc & N_MASK) != !(pc & V_MASK))) goto L_Next;
+ break;
+ case COND_LE:
+ if (Z_IS_CLEAR(pc) && (!(pc & N_MASK) == !(pc & V_MASK))) goto L_Next;
+ break;
+ case COND_NV:
+ goto L_Next;
+ }
+ /* Condition satisfied, so decode the instruction */
+ if ((insn & 0x0fc000f0u) == 0x00000090u) /* Multiplication */
+ {
+ HandleMul(cpustate, insn);
+ R15 += 4;
+ }
+ else if (!(insn & 0x0c000000u)) /* Data processing */
+ {
+ HandleALU(cpustate, insn);
+ }
+ else if ((insn & 0x0c000000u) == 0x04000000u) /* Single data access */
+ {
+ HandleMemSingle(cpustate, insn);
+ R15 += 4;
+ }
+ else if ((insn & 0x0e000000u) == 0x08000000u ) /* Block data access */
+ {
+ HandleMemBlock(cpustate, insn);
+ R15 += 4;
+ }
+ else if ((insn & 0x0e000000u) == 0x0a000000u) /* Branch */
+ {
+ HandleBranch(cpustate, insn);
+ }
+ else if ((insn & 0x0f000000u) == 0x0e000000u) /* Coprocessor */
+ {
+ HandleCoPro(cpustate, insn);
+ R15 += 4;
+ }
+ else if ((insn & 0x0f000000u) == 0x0f000000u) /* Software interrupt */
+ {
+ pc=R15+4;
+ R15 = eARM_MODE_SVC; /* Set SVC mode so PC is saved to correct R14 bank */
+ SetRegister( cpustate, 14, pc ); /* save PC */
+ R15 = (pc&PSR_MASK)|(pc&IRQ_MASK)|0x8|eARM_MODE_SVC|I_MASK|(pc&MODE_MASK);
+ cpustate->icount -= 2 * S_CYCLE + N_CYCLE;
+ }
+ else /* Undefined */
+ {
+ logerror("%08x: Undefined instruction\n",R15);
+ L_Next:
+ cpustate->icount -= S_CYCLE;
+ R15 += 4;
+ }
+
+ arm_check_irq_state(cpustate);
+
+ } while( cpustate->icount > 0 );
+} /* arm_execute */
+
+
+static void arm_check_irq_state(ARM_REGS* cpustate)
+{
+ UINT32 pc = R15+4; /* save old pc (already incremented in pipeline) */;
+
+ /* Exception priorities (from ARM6, not specifically ARM2/3):
+
+ Reset
+ Data abort
+ FIRQ
+ IRQ
+ Prefetch abort
+ Undefined instruction
+ */
+
+ if (cpustate->pendingFiq && (pc&F_MASK)==0) {
+ R15 = eARM_MODE_FIQ; /* Set FIQ mode so PC is saved to correct R14 bank */
+ SetRegister( cpustate, 14, pc ); /* save PC */
+ R15 = (pc&PSR_MASK)|(pc&IRQ_MASK)|0x1c|eARM_MODE_FIQ|I_MASK|F_MASK; /* Mask both IRQ & FIRQ, set PC=0x1c */
+ cpustate->pendingFiq=0;
+ return;
+ }
+
+ if (cpustate->pendingIrq && (pc&I_MASK)==0) {
+ R15 = eARM_MODE_IRQ; /* Set IRQ mode so PC is saved to correct R14 bank */
+ SetRegister( cpustate, 14, pc ); /* save PC */
+ R15 = (pc&PSR_MASK)|(pc&IRQ_MASK)|0x18|eARM_MODE_IRQ|I_MASK|(pc&F_MASK); /* Mask only IRQ, set PC=0x18 */
+ cpustate->pendingIrq=0;
+ return;
+ }
+}
+
+static void set_irq_line(ARM_REGS* cpustate, int irqline, int state)
+{
+ switch (irqline) {
+
+ case ARM_IRQ_LINE: /* IRQ */
+ if (state && (R15&0x3)!=eARM_MODE_IRQ) /* Don't allow nested IRQs */
+ cpustate->pendingIrq=1;
+ else
+ cpustate->pendingIrq=0;
+ break;
+
+ case ARM_FIRQ_LINE: /* FIRQ */
+ if (state && (R15&0x3)!=eARM_MODE_FIQ) /* Don't allow nested FIRQs */
+ cpustate->pendingFiq=1;
+ else
+ cpustate->pendingFiq=0;
+ break;
+ }
+
+ arm_check_irq_state(cpustate);
+}
+
+static CPU_INIT( arm )
+{
+ ARM_REGS *cpustate = get_safe_token(device);
+
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->endian = ENDIANNESS_LITTLE;
+
+ device->save_item(NAME(cpustate->sArmRegister));
+ device->save_item(NAME(cpustate->coproRegister));
+ device->save_item(NAME(cpustate->pendingIrq));
+ device->save_item(NAME(cpustate->pendingFiq));
+}
+
+
+static CPU_INIT( arm_be )
+{
+ ARM_REGS *cpustate = get_safe_token(device);
+
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->endian = ENDIANNESS_BIG;
+
+ device->save_item(NAME(cpustate->sArmRegister));
+ device->save_item(NAME(cpustate->coproRegister));
+ device->save_item(NAME(cpustate->pendingIrq));
+ device->save_item(NAME(cpustate->pendingFiq));
+}
+
+
+/***************************************************************************/
+
+static void HandleBranch( ARM_REGS* cpustate, UINT32 insn )
+{
+ UINT32 off = (insn & INSN_BRANCH) << 2;
+
+ /* Save PC into LR if this is a branch with link */
+ if (insn & INSN_BL)
+ {
+ SetRegister(cpustate, 14,R15 + 4);
+ }
+
+ /* Sign-extend the 24-bit offset in our calculations */
+ if (off & 0x2000000u)
+ {
+ R15 -= ((~(off | 0xfc000000u)) + 1) - 8;
+ }
+ else
+ {
+ R15 += off + 8;
+ }
+ cpustate->icount -= 2 * S_CYCLE + N_CYCLE;
+}
+
+static void HandleMemSingle( ARM_REGS* cpustate, UINT32 insn )
+{
+ UINT32 rn, rnv, off, rd;
+
+ /* Fetch the offset */
+ if (insn & INSN_I)
+ {
+ off = decodeShift(cpustate, insn, NULL);
+ }
+ else
+ {
+ off = insn & INSN_SDT_IMM;
+ }
+
+ /* Calculate Rn, accounting for PC */
+ rn = (insn & INSN_RN) >> INSN_RN_SHIFT;
+
+// if (rn==0xf) logerror("%08x: Source R15\n",R15);
+
+ if (insn & INSN_SDT_P)
+ {
+ /* Pre-indexed addressing */
+ if (insn & INSN_SDT_U)
+ {
+ if (rn != eR15)
+ rnv = (GetRegister(cpustate, rn) + off);
+ else
+ rnv = (R15 & ADDRESS_MASK) + off;
+ }
+ else
+ {
+ if (rn != eR15)
+ rnv = (GetRegister(cpustate, rn) - off);
+ else
+ rnv = (R15 & ADDRESS_MASK) - off;
+ }
+
+ if (insn & INSN_SDT_W)
+ {
+ SetRegister(cpustate, rn,rnv);
+ if (ARM_DEBUG_CORE && rn == eR15)
+ logerror("writeback R15 %08x\n", R15);
+ }
+ else if (rn == eR15)
+ {
+ rnv = rnv + 8;
+ }
+ }
+ else
+ {
+ /* Post-indexed addressing */
+ if (rn == eR15)
+ {
+ rnv = (R15 & ADDRESS_MASK) + 8;
+ }
+ else
+ {
+ rnv = GetRegister(cpustate, rn);
+ }
+ }
+
+ /* Do the transfer */
+ rd = (insn & INSN_RD) >> INSN_RD_SHIFT;
+ if (insn & INSN_SDT_L)
+ {
+ /* Load */
+ cpustate->icount -= S_CYCLE + I_CYCLE + N_CYCLE;
+ if (insn & INSN_SDT_B)
+ {
+ if (ARM_DEBUG_CORE && rd == eR15)
+ logerror("read byte R15 %08x\n", R15);
+ SetRegister(cpustate, rd,(UINT32) READ8(rnv) );
+ }
+ else
+ {
+ if (rd == eR15)
+ {
+ R15 = (READ32(rnv) & ADDRESS_MASK) | (R15 & PSR_MASK) | (R15 & MODE_MASK);
+
+ /*
+ The docs are explicit in that the bottom bits should be masked off
+ when writing to R15 in this way, however World Cup Volleyball 95 has
+ an example of an unaligned jump (bottom bits = 2) where execution
+ should definitely continue from the rounded up address.
+
+ In other cases, 4 is subracted from R15 here to account for pipelining.
+ */
+ if ((READ32(rnv)&3)==0)
+ R15 -= 4;
+
+ cpustate->icount -= S_CYCLE + N_CYCLE;
+ }
+ else
+ {
+ SetRegister(cpustate, rd, READ32(rnv));
+ }
+ }
+ }
+ else
+ {
+ /* Store */
+ cpustate->icount -= 2 * N_CYCLE;
+ if (insn & INSN_SDT_B)
+ {
+ if (ARM_DEBUG_CORE && rd==eR15)
+ logerror("Wrote R15 in byte mode\n");
+
+ WRITE8(rnv, (UINT8) GetRegister(cpustate, rd) & 0xffu);
+ }
+ else
+ {
+ if (ARM_DEBUG_CORE && rd==eR15)
+ logerror("Wrote R15 in 32bit mode\n");
+
+ WRITE32(rnv, rd == eR15 ? R15 + 8 : GetRegister(cpustate, rd));
+ }
+ }
+
+ /* Do post-indexing writeback */
+ if (!(insn & INSN_SDT_P)/* && (insn&INSN_SDT_W)*/)
+ {
+ if (insn & INSN_SDT_U)
+ {
+ /* Writeback is applied in pipeline, before value is read from mem,
+ so writeback is effectively ignored */
+ if (rd==rn) {
+ SetRegister(cpustate, rn,GetRegister(cpustate, rd));
+ }
+ else {
+
+ if ((insn&INSN_SDT_W)!=0)
+ logerror("%08x: RegisterWritebackIncrement %d %d %d\n",R15,(insn & INSN_SDT_P)!=0,(insn&INSN_SDT_W)!=0,(insn & INSN_SDT_U)!=0);
+
+ SetRegister(cpustate, rn,(rnv + off));
+ }
+ }
+ else
+ {
+ /* Writeback is applied in pipeline, before value is read from mem,
+ so writeback is effectively ignored */
+ if (rd==rn) {
+ SetRegister(cpustate, rn,GetRegister(cpustate, rd));
+ }
+ else {
+ SetRegister(cpustate, rn,(rnv - off));
+
+ if ((insn&INSN_SDT_W)!=0)
+ logerror("%08x: RegisterWritebackDecrement %d %d %d\n",R15,(insn & INSN_SDT_P)!=0,(insn&INSN_SDT_W)!=0,(insn & INSN_SDT_U)!=0);
+ }
+ }
+ }
+} /* HandleMemSingle */
+
+#define IsNeg(i) ((i) >> 31)
+#define IsPos(i) ((~(i)) >> 31)
+
+/* Set NZCV flags for ADDS / SUBS */
+
+#define HandleALUAddFlags(rd, rn, op2) \
+ if (insn & INSN_S) \
+ R15 = \
+ ((R15 &~ (N_MASK | Z_MASK | V_MASK | C_MASK)) \
+ | (((!SIGN_BITS_DIFFER(rn, op2)) && SIGN_BITS_DIFFER(rn, rd)) \
+ << V_BIT) \
+ | (((~(rn)) < (op2)) << C_BIT) \
+ | HandleALUNZFlags(rd)) \
+ + 4; \
+ else R15 += 4;
+
+#define HandleALUSubFlags(rd, rn, op2) \
+ if (insn & INSN_S) \
+ R15 = \
+ ((R15 &~ (N_MASK | Z_MASK | V_MASK | C_MASK)) \
+ | ((SIGN_BITS_DIFFER(rn, op2) && SIGN_BITS_DIFFER(rn, rd)) \
+ << V_BIT) \
+ | (((IsNeg(rn) & IsPos(op2)) | (IsNeg(rn) & IsPos(rd)) | (IsPos(op2) & IsPos(rd))) ? C_MASK : 0) \
+ | HandleALUNZFlags(rd)) \
+ + 4; \
+ else R15 += 4;
+
+/* Set NZC flags for logical operations. */
+
+#define HandleALUNZFlags(rd) \
+ (((rd) & SIGN_BIT) | ((!(rd)) << Z_BIT))
+
+#define HandleALULogicalFlags(rd, sc) \
+ if (insn & INSN_S) \
+ R15 = ((R15 &~ (N_MASK | Z_MASK | C_MASK)) \
+ | HandleALUNZFlags(rd) \
+ | (((sc) != 0) << C_BIT)) + 4; \
+ else R15 += 4;
+
+static void HandleALU( ARM_REGS* cpustate, UINT32 insn )
+{
+ UINT32 op2, sc=0, rd, rn, opcode;
+ UINT32 by, rdn;
+
+ opcode = (insn & INSN_OPCODE) >> INSN_OPCODE_SHIFT;
+ cpustate->icount -= S_CYCLE;
+
+ rd = 0;
+ rn = 0;
+
+ /* Construct Op2 */
+ if (insn & INSN_I)
+ {
+ /* Immediate constant */
+ by = (insn & INSN_OP2_ROTATE) >> INSN_OP2_ROTATE_SHIFT;
+ if (by)
+ {
+ op2 = ROR(insn & INSN_OP2_IMM, by << 1);
+ sc = op2 & SIGN_BIT;
+ }
+ else
+ {
+ op2 = insn & INSN_OP2;
+ sc = R15 & C_MASK;
+ }
+ }
+ else
+ {
+ op2 = decodeShift(cpustate, insn, (insn & INSN_S) ? &sc : NULL);
+
+ if (!(insn & INSN_S))
+ sc=0;
+ }
+
+ /* Calculate Rn to account for pipelining */
+ if ((opcode & 0xd) != 0xd) /* No Rn in MOV */
+ {
+ if ((rn = (insn & INSN_RN) >> INSN_RN_SHIFT) == eR15)
+ {
+ if (ARM_DEBUG_CORE)
+ logerror("%08x: Pipelined R15 (Shift %d)\n",R15,(insn&INSN_I?8:insn&0x10u?12:12));
+
+ /* Docs strongly suggest the mode bits should be included here, but it breaks Captain
+ America, as it starts doing unaligned reads */
+ rn=(R15+8)&ADDRESS_MASK;
+ }
+ else
+ {
+ rn = GetRegister(cpustate, rn);
+ }
+ }
+
+ /* Perform the operation */
+ switch ((insn & INSN_OPCODE) >> INSN_OPCODE_SHIFT)
+ {
+ /* Arithmetic operations */
+ case OPCODE_SBC:
+ rd = (rn - op2 - (R15 & C_MASK ? 0 : 1));
+ HandleALUSubFlags(rd, rn, op2);
+ break;
+ case OPCODE_CMP:
+ case OPCODE_SUB:
+ rd = (rn - op2);
+ HandleALUSubFlags(rd, rn, op2);
+ break;
+ case OPCODE_RSC:
+ rd = (op2 - rn - (R15 & C_MASK ? 0 : 1));
+ HandleALUSubFlags(rd, op2, rn);
+ break;
+ case OPCODE_RSB:
+ rd = (op2 - rn);
+ HandleALUSubFlags(rd, op2, rn);
+ break;
+ case OPCODE_ADC:
+ rd = (rn + op2 + ((R15 & C_MASK) >> C_BIT));
+ HandleALUAddFlags(rd, rn, op2);
+ break;
+ case OPCODE_CMN:
+ case OPCODE_ADD:
+ rd = (rn + op2);
+ HandleALUAddFlags(rd, rn, op2);
+ break;
+ /* Logical operations */
+ case OPCODE_AND:
+ case OPCODE_TST:
+ rd = rn & op2;
+ HandleALULogicalFlags(rd, sc);
+ break;
+ case OPCODE_BIC:
+ rd = rn &~ op2;
+ HandleALULogicalFlags(rd, sc);
+ break;
+ case OPCODE_TEQ:
+ case OPCODE_EOR:
+ rd = rn ^ op2;
+ HandleALULogicalFlags(rd, sc);
+ break;
+ case OPCODE_ORR:
+ rd = rn | op2;
+ HandleALULogicalFlags(rd, sc);
+ break;
+ case OPCODE_MOV:
+ rd = op2;
+ HandleALULogicalFlags(rd, sc);
+ break;
+ case OPCODE_MVN:
+ rd = (~op2);
+ HandleALULogicalFlags(rd, sc);
+ break;
+ }
+
+ /* Put the result in its register if not a test */
+ rdn = (insn & INSN_RD) >> INSN_RD_SHIFT;
+ if ((opcode & 0xc) != 0x8)
+ {
+ if (rdn == eR15 && !(insn & INSN_S))
+ {
+ /* Merge the old NZCV flags into the new PC value */
+ R15 = (rd & ADDRESS_MASK) | (R15 & PSR_MASK) | (R15 & IRQ_MASK) | (R15&MODE_MASK);
+ cpustate->icount -= S_CYCLE + N_CYCLE;
+ }
+ else
+ {
+ if (rdn==eR15)
+ {
+ /* S Flag is set - update PSR & mode if in non-user mode only */
+ if ((R15&MODE_MASK)!=0)
+ {
+ SetRegister(cpustate,rdn,rd);
+ }
+ else
+ {
+ SetRegister(cpustate, rdn,(rd&ADDRESS_MASK) | (rd&PSR_MASK) | (R15&IRQ_MASK) | (R15&MODE_MASK));
+ }
+ cpustate->icount -= S_CYCLE + N_CYCLE;
+ }
+ else
+ {
+ SetRegister(cpustate,rdn,rd);
+ }
+ }
+ /* TST & TEQ can affect R15 (the condition code register) with the S bit set */
+ }
+ else if ((rdn==eR15) && (insn & INSN_S))
+ {
+ // update only the flags
+ if ((R15&MODE_MASK)!=0)
+ {
+ // combine the flags from rd with the address from R15
+ rd &= ~ADDRESS_MASK;
+ rd |= (R15 & ADDRESS_MASK);
+ SetRegister(cpustate,rdn,rd);
+ }
+ else
+ {
+ // combine the flags from rd with the address from R15
+ rd &= ~ADDRESS_MASK; // clear address part of RD
+ rd |= (R15 & ADDRESS_MASK); // RD = address part of R15
+ SetRegister(cpustate, rdn,(rd&ADDRESS_MASK) | (rd&PSR_MASK) | (R15&IRQ_MASK) | (R15&MODE_MASK));
+ }
+ cpustate->icount -= S_CYCLE + N_CYCLE;
+ }
+}
+
+static void HandleMul( ARM_REGS* cpustate, UINT32 insn)
+{
+ UINT32 r;
+
+ cpustate->icount -= S_CYCLE + I_CYCLE;
+ /* should be:
+ Range of Rs Number of cycles
+
+ &0 -- &1 1S + 1I
+ &2 -- &7 1S + 2I
+ &8 -- &1F 1S + 3I
+ &20 -- &7F 1S + 4I
+ &80 -- &1FF 1S + 5I
+ &200 -- &7FF 1S + 6I
+ &800 -- &1FFF 1S + 7I
+ &2000 -- &7FFF 1S + 8I
+ &8000 -- &1FFFF 1S + 9I
+ &20000 -- &7FFFF 1S + 10I
+ &80000 -- &1FFFFF 1S + 11I
+ &200000 -- &7FFFFF 1S + 12I
+ &800000 -- &1FFFFFF 1S + 13I
+ &2000000 -- &7FFFFFF 1S + 14I
+ &8000000 -- &1FFFFFFF 1S + 15I
+ &20000000 -- &FFFFFFFF 1S + 16I
+ */
+
+ /* Do the basic multiply of Rm and Rs */
+ r = GetRegister( cpustate, insn&INSN_MUL_RM ) *
+ GetRegister( cpustate, (insn&INSN_MUL_RS)>>INSN_MUL_RS_SHIFT );
+
+ if (ARM_DEBUG_CORE && ((insn&INSN_MUL_RM)==0xf
+ || ((insn&INSN_MUL_RS)>>INSN_MUL_RS_SHIFT )==0xf
+ || ((insn&INSN_MUL_RN)>>INSN_MUL_RN_SHIFT)==0xf)
+ )
+ logerror("%08x: R15 used in mult\n",R15);
+
+ /* Add on Rn if this is a MLA */
+ if (insn & INSN_MUL_A)
+ {
+ r += GetRegister(cpustate, (insn&INSN_MUL_RN)>>INSN_MUL_RN_SHIFT);
+ }
+
+ /* Write the result */
+ SetRegister(cpustate,(insn&INSN_MUL_RD)>>INSN_MUL_RD_SHIFT,r);
+
+ /* Set N and Z if asked */
+ if( insn & INSN_S )
+ {
+ R15 = (R15 &~ (N_MASK | Z_MASK)) | HandleALUNZFlags(r);
+ }
+}
+
+static int loadInc ( ARM_REGS* cpustate, UINT32 pat, UINT32 rbv, UINT32 s)
+{
+ int i,result;
+
+ result = 0;
+ for( i=0; i<16; i++ )
+ {
+ if( (pat>>i)&1 )
+ {
+ if (i==15) {
+ if (s) /* Pull full contents from stack */
+ SetRegister( cpustate, 15, READ32(rbv+=4) );
+ else /* Pull only address, preserve mode & status flags */
+ SetRegister( cpustate, 15, (R15&PSR_MASK) | (R15&IRQ_MASK) | (R15&MODE_MASK) | ((READ32(rbv+=4))&ADDRESS_MASK) );
+ } else
+ SetRegister( cpustate, i, READ32(rbv+=4) );
+
+ result++;
+ }
+ }
+ return result;
+}
+
+static int loadDec( ARM_REGS* cpustate, UINT32 pat, UINT32 rbv, UINT32 s, UINT32* deferredR15, int* defer)
+{
+ int i,result;
+
+ result = 0;
+ for( i=15; i>=0; i-- )
+ {
+ if( (pat>>i)&1 )
+ {
+ if (i==15) {
+ *defer=1;
+ if (s) /* Pull full contents from stack */
+ *deferredR15=READ32(rbv-=4);
+ else /* Pull only address, preserve mode & status flags */
+ *deferredR15=(R15&PSR_MASK) | (R15&IRQ_MASK) | (R15&MODE_MASK) | ((READ32(rbv-=4))&ADDRESS_MASK);
+ }
+ else
+ SetRegister( cpustate, i, READ32(rbv -=4) );
+ result++;
+ }
+ }
+ return result;
+}
+
+static int storeInc( ARM_REGS* cpustate, UINT32 pat, UINT32 rbv)
+{
+ int i,result;
+
+ result = 0;
+ for( i=0; i<16; i++ )
+ {
+ if( (pat>>i)&1 )
+ {
+ if (ARM_DEBUG_CORE && i==15) /* R15 is plus 12 from address of STM */
+ logerror("%08x: StoreInc on R15\n",R15);
+
+ WRITE32( rbv += 4, GetRegister(cpustate, i) );
+ result++;
+ }
+ }
+ return result;
+} /* storeInc */
+
+static int storeDec( ARM_REGS* cpustate, UINT32 pat, UINT32 rbv)
+{
+ int i,result;
+
+ result = 0;
+ for( i=15; i>=0; i-- )
+ {
+ if( (pat>>i)&1 )
+ {
+ if (ARM_DEBUG_CORE && i==15) /* R15 is plus 12 from address of STM */
+ logerror("%08x: StoreDec on R15\n",R15);
+
+ WRITE32( rbv -= 4, GetRegister(cpustate, i) );
+ result++;
+ }
+ }
+ return result;
+} /* storeDec */
+
+static void HandleMemBlock( ARM_REGS* cpustate, UINT32 insn )
+{
+ UINT32 rb = (insn & INSN_RN) >> INSN_RN_SHIFT;
+ UINT32 rbp = GetRegister(cpustate, rb);
+ int result;
+
+ if (ARM_DEBUG_CORE && insn & INSN_BDT_S)
+ logerror("%08x: S Bit set in MEMBLOCK\n",R15);
+
+ if (insn & INSN_BDT_L)
+ {
+ /* Loading */
+ if (insn & INSN_BDT_U)
+ {
+ int mode = MODE;
+
+ /* Incrementing */
+ if (!(insn & INSN_BDT_P)) rbp = rbp + (- 4);
+
+ result = loadInc( cpustate, insn & 0xffff, rbp, insn&INSN_BDT_S );
+
+ if (insn & 0x8000) {
+ R15-=4;
+ cpustate->icount -= S_CYCLE + N_CYCLE;
+ }
+
+ if (insn & INSN_BDT_W)
+ {
+ /* Arm docs notes: The base register can always be loaded without any problems.
+ However, don't specify writeback if the base register is being loaded -
+ you can't end up with both a written-back value and a loaded value in the base register!
+
+ However - Fighter's History does exactly that at 0x121e4 (LDMUW [R13], { R13-R15 })!
+
+ This emulator implementation skips applying writeback in this case, which is confirmed
+ correct for this situation, but that is not necessarily true for all ARM hardware
+ implementations (the results are officially undefined).
+ */
+
+ if (ARM_DEBUG_CORE && rb==15)
+ logerror("%08x: Illegal LDRM writeback to r15\n",R15);
+
+ if ((insn&(1<<rb))==0)
+ SetModeRegister(cpustate, mode, rb, GetModeRegister(cpustate, mode, rb) + result * 4);
+ else if (ARM_DEBUG_CORE)
+ logerror("%08x: Illegal LDRM writeback to base register (%d)\n",R15, rb);
+ }
+ }
+ else
+ {
+ UINT32 deferredR15=0;
+ int defer=0;
+
+ /* Decrementing */
+ if (!(insn & INSN_BDT_P))
+ {
+ rbp = rbp - (- 4);
+ }
+
+ result = loadDec( cpustate, insn&0xffff, rbp, insn&INSN_BDT_S, &deferredR15, &defer );
+
+ if (insn & INSN_BDT_W)
+ {
+ if (rb==0xf)
+ logerror("%08x: Illegal LDRM writeback to r15\n",R15);
+ SetRegister(cpustate,rb,GetRegister(cpustate, rb)-result*4);
+ }
+
+ // If R15 is pulled from memory we defer setting it until after writeback
+ // is performed, else we may writeback to the wrong context (ie, the new
+ // context if the mode has changed as a result of the R15 read)
+ if (defer)
+ SetRegister(cpustate, 15, deferredR15);
+
+ if (insn & 0x8000) {
+ cpustate->icount -= S_CYCLE + N_CYCLE;
+ R15-=4;
+ }
+ }
+ cpustate->icount -= result * S_CYCLE + N_CYCLE + I_CYCLE;
+ } /* Loading */
+ else
+ {
+ /* Storing
+
+ ARM docs notes: Storing a list of registers including the base register using writeback
+ will write the value of the base register before writeback to memory only if the base
+ register is the first in the list. Otherwise, the value which is used is not defined.
+
+ */
+ if (insn & (1<<eR15))
+ {
+ if (ARM_DEBUG_CORE)
+ logerror("%08x: Writing R15 in strm\n",R15);
+
+ /* special case handling if writing to PC */
+ R15 += 12;
+ }
+ if (insn & INSN_BDT_U)
+ {
+ /* Incrementing */
+ if (!(insn & INSN_BDT_P))
+ {
+ rbp = rbp + (- 4);
+ }
+ result = storeInc( cpustate, insn&0xffff, rbp );
+ if( insn & INSN_BDT_W )
+ {
+ SetRegister(cpustate,rb,GetRegister(cpustate, rb)+result*4);
+ }
+ }
+ else
+ {
+ /* Decrementing */
+ if (!(insn & INSN_BDT_P))
+ {
+ rbp = rbp - (- 4);
+ }
+ result = storeDec( cpustate, insn&0xffff, rbp );
+ if( insn & INSN_BDT_W )
+ {
+ SetRegister(cpustate,rb,GetRegister(cpustate, rb)-result*4);
+ }
+ }
+ if( insn & (1<<eR15) )
+ R15 -= 12;
+
+ cpustate->icount -= (result - 1) * S_CYCLE + 2 * N_CYCLE;
+ }
+} /* HandleMemBlock */
+
+
+
+/* Decodes an Op2-style shifted-register form. If @carry@ is non-zero the
+ * shifter carry output will manifest itself as @*carry == 0@ for carry clear
+ * and @*carry != 0@ for carry set.
+ */
+static UINT32 decodeShift( ARM_REGS* cpustate, UINT32 insn, UINT32 *pCarry)
+{
+ UINT32 k = (insn & INSN_OP2_SHIFT) >> INSN_OP2_SHIFT_SHIFT;
+ UINT32 rm = GetRegister( cpustate, insn & INSN_OP2_RM );
+ UINT32 t = (insn & INSN_OP2_SHIFT_TYPE) >> INSN_OP2_SHIFT_TYPE_SHIFT;
+
+ if ((insn & INSN_OP2_RM)==0xf) {
+ /* If hardwired shift, then PC is 8 bytes ahead, else if register shift
+ is used, then 12 bytes - TODO?? */
+ rm+=8;
+ }
+
+ /* All shift types ending in 1 are Rk, not #k */
+ if( t & 1 )
+ {
+// logerror("%08x: RegShift %02x %02x\n",R15, k>>1,GetRegister(cpustate, k >> 1));
+ if (ARM_DEBUG_CORE && (insn&0x80)==0x80)
+ logerror("%08x: RegShift ERROR (p36)\n",R15);
+
+ //see p35 for check on this
+ k = GetRegister(cpustate, k >> 1)&0x1f;
+ cpustate->icount -= S_CYCLE;
+ if( k == 0 ) /* Register shift by 0 is a no-op */
+ {
+// logerror("%08x: NO-OP Regshift\n",R15);
+ if (pCarry) *pCarry = R15 & C_MASK;
+ return rm;
+ }
+ }
+ /* Decode the shift type and perform the shift */
+ switch (t >> 1)
+ {
+ case 0: /* LSL */
+ if (pCarry)
+ {
+ *pCarry = k ? (rm & (1 << (32 - k))) : (R15 & C_MASK);
+ }
+ return k ? LSL(rm, k) : rm;
+
+ case 1: /* LSR */
+ if (k == 0 || k == 32)
+ {
+ if (pCarry) *pCarry = rm & SIGN_BIT;
+ return 0;
+ }
+ else if (k > 32)
+ {
+ if (pCarry) *pCarry = 0;
+ return 0;
+ }
+ else
+ {
+ if (pCarry) *pCarry = (rm & (1 << (k - 1)));
+ return LSR(rm, k);
+ }
+ break;
+
+ case 2: /* ASR */
+ if (k == 0 || k > 32)
+ k = 32;
+ if (pCarry) *pCarry = (rm & (1 << (k - 1)));
+ if (k >= 32)
+ return rm & SIGN_BIT ? 0xffffffffu : 0;
+ else
+ {
+ if (rm & SIGN_BIT)
+ return LSR(rm, k) | (0xffffffffu << (32 - k));
+ else
+ return LSR(rm, k);
+ }
+ break;
+
+ case 3: /* ROR and RRX */
+ if (k)
+ {
+ while (k > 32) k -= 32;
+ if (pCarry) *pCarry = rm & SIGN_BIT;
+ return ROR(rm, k);
+ }
+ else
+ {
+ if (pCarry) *pCarry = (rm & 1);
+ return LSR(rm, 1) | ((R15 & C_MASK) << 2);
+ }
+ break;
+ }
+
+ logerror("%08x: Decodeshift error\n",R15);
+ return 0;
+} /* decodeShift */
+
+
+static UINT32 BCDToDecimal(UINT32 value)
+{
+ UINT32 accumulator = 0;
+ UINT32 multiplier = 1;
+ int i;
+
+ for(i = 0; i < 8; i++)
+ {
+ accumulator += (value & 0xF) * multiplier;
+
+ multiplier *= 10;
+ value >>= 4;
+ }
+
+ return accumulator;
+}
+
+static UINT32 DecimalToBCD(UINT32 value)
+{
+ UINT32 accumulator = 0;
+ UINT32 divisor = 10;
+ int i;
+
+ for(i = 0; i < 8; i++)
+ {
+ UINT32 temp;
+
+ temp = value % divisor;
+ value -= temp;
+ temp /= divisor / 10;
+
+ accumulator += temp << (i * 4);
+
+ divisor *= 10;
+ }
+
+ return accumulator;
+}
+
+static void HandleCoPro( ARM_REGS* cpustate, UINT32 insn )
+{
+ UINT32 rn=(insn>>12)&0xf;
+ UINT32 crn=(insn>>16)&0xf;
+
+ cpustate->icount -= S_CYCLE;
+
+ /* MRC - transfer copro register to main register */
+ if( (insn&0x0f100010)==0x0e100010 )
+ {
+ SetRegister(cpustate, rn, cpustate->coproRegister[crn]);
+
+ if (ARM_DEBUG_COPRO)
+ logerror("%08x: Copro read CR%d (%08x) to R%d\n", R15, crn, cpustate->coproRegister[crn], rn);
+ }
+ /* MCR - transfer main register to copro register */
+ else if( (insn&0x0f100010)==0x0e000010 )
+ {
+ cpustate->coproRegister[crn]=GetRegister(cpustate, rn);
+
+ /* Data East 156 copro specific - trigger BCD operation */
+ if (crn==2)
+ {
+ if (cpustate->coproRegister[crn]==0)
+ {
+ /* Unpack BCD */
+ int v0=BCDToDecimal(cpustate->coproRegister[0]);
+ int v1=BCDToDecimal(cpustate->coproRegister[1]);
+
+ /* Repack vcd */
+ cpustate->coproRegister[5]=DecimalToBCD(v0+v1);
+
+ if (ARM_DEBUG_COPRO)
+ logerror("Cmd: Add 0 + 1, result in 5 (%08x + %08x == %08x)\n", v0, v1, cpustate->coproRegister[5]);
+ }
+ else if (cpustate->coproRegister[crn]==1)
+ {
+ /* Unpack BCD */
+ int v0=BCDToDecimal(cpustate->coproRegister[0]);
+ int v1=BCDToDecimal(cpustate->coproRegister[1]);
+
+ /* Repack vcd */
+ cpustate->coproRegister[5]=DecimalToBCD(v0*v1);
+
+ if (ARM_DEBUG_COPRO)
+ logerror("Cmd: Multiply 0 * 1, result in 5 (%08x * %08x == %08x)\n", v0, v1, cpustate->coproRegister[5]);
+ }
+ else if (cpustate->coproRegister[crn]==3)
+ {
+ /* Unpack BCD */
+ int v0=BCDToDecimal(cpustate->coproRegister[0]);
+ int v1=BCDToDecimal(cpustate->coproRegister[1]);
+
+ /* Repack vcd */
+ cpustate->coproRegister[5]=DecimalToBCD(v0-v1);
+
+ if (ARM_DEBUG_COPRO)
+ logerror("Cmd: Sub 0 - 1, result in 5 (%08x - %08x == %08x)\n", v0, v1, cpustate->coproRegister[5]);
+ }
+ else
+ {
+ logerror("Unknown bcd copro command %08x\n", cpustate->coproRegister[crn]);
+ }
+ }
+
+ if (ARM_DEBUG_COPRO)
+ logerror("%08x: Copro write R%d (%08x) to CR%d\n", R15, rn, GetRegister(cpustate, rn), crn);
+ }
+ /* CDP - perform copro operation */
+ else if( (insn&0x0f000010)==0x0e000000 )
+ {
+ /* Data East 156 copro specific divider - result in reg 3/4 */
+ if (cpustate->coproRegister[1])
+ {
+ cpustate->coproRegister[3]=cpustate->coproRegister[0] / cpustate->coproRegister[1];
+ cpustate->coproRegister[4]=cpustate->coproRegister[0] % cpustate->coproRegister[1];
+ }
+ else
+ {
+ /* Unverified */
+ cpustate->coproRegister[3]=0xffffffff;
+ cpustate->coproRegister[4]=0xffffffff;
+ }
+
+ if (ARM_DEBUG_COPRO)
+ logerror("%08x: Copro cdp (%08x) (3==> %08x, 4==> %08x)\n", R15, insn, cpustate->coproRegister[3], cpustate->coproRegister[4]);
+ }
+ else
+ {
+ logerror("%08x: Unimplemented copro instruction %08x\n", R15, insn);
+ }
+}
+
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( arm )
+{
+ ARM_REGS *cpustate = get_safe_token(device);
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + ARM_IRQ_LINE: set_irq_line(cpustate, ARM_IRQ_LINE, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + ARM_FIRQ_LINE: set_irq_line(cpustate, ARM_FIRQ_LINE, info->i); break;
+
+ case CPUINFO_INT_REGISTER + ARM32_R0: cpustate->sArmRegister[ 0]= info->i; break;
+ case CPUINFO_INT_REGISTER + ARM32_R1: cpustate->sArmRegister[ 1]= info->i; break;
+ case CPUINFO_INT_REGISTER + ARM32_R2: cpustate->sArmRegister[ 2]= info->i; break;
+ case CPUINFO_INT_REGISTER + ARM32_R3: cpustate->sArmRegister[ 3]= info->i; break;
+ case CPUINFO_INT_REGISTER + ARM32_R4: cpustate->sArmRegister[ 4]= info->i; break;
+ case CPUINFO_INT_REGISTER + ARM32_R5: cpustate->sArmRegister[ 5]= info->i; break;
+ case CPUINFO_INT_REGISTER + ARM32_R6: cpustate->sArmRegister[ 6]= info->i; break;
+ case CPUINFO_INT_REGISTER + ARM32_R7: cpustate->sArmRegister[ 7]= info->i; break;
+ case CPUINFO_INT_REGISTER + ARM32_R8: cpustate->sArmRegister[ 8]= info->i; break;
+ case CPUINFO_INT_REGISTER + ARM32_R9: cpustate->sArmRegister[ 9]= info->i; break;
+ case CPUINFO_INT_REGISTER + ARM32_R10: cpustate->sArmRegister[10]= info->i; break;
+ case CPUINFO_INT_REGISTER + ARM32_R11: cpustate->sArmRegister[11]= info->i; break;
+ case CPUINFO_INT_REGISTER + ARM32_R12: cpustate->sArmRegister[12]= info->i; break;
+ case CPUINFO_INT_REGISTER + ARM32_R13: cpustate->sArmRegister[13]= info->i; break;
+ case CPUINFO_INT_REGISTER + ARM32_R14: cpustate->sArmRegister[14]= info->i; break;
+ case CPUINFO_INT_REGISTER + ARM32_R15: cpustate->sArmRegister[15]= info->i; break;
+ case CPUINFO_INT_REGISTER + ARM32_FR8: cpustate->sArmRegister[eR8_FIQ] = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM32_FR9: cpustate->sArmRegister[eR9_FIQ] = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM32_FR10: cpustate->sArmRegister[eR10_FIQ] = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM32_FR11: cpustate->sArmRegister[eR11_FIQ] = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM32_FR12: cpustate->sArmRegister[eR12_FIQ] = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM32_FR13: cpustate->sArmRegister[eR13_FIQ] = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM32_FR14: cpustate->sArmRegister[eR14_FIQ] = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM32_IR13: cpustate->sArmRegister[eR13_IRQ] = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM32_IR14: cpustate->sArmRegister[eR14_IRQ] = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM32_SR13: cpustate->sArmRegister[eR13_SVC] = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM32_SR14: cpustate->sArmRegister[eR14_SVC] = info->i; break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + ARM32_PC: R15 = (R15&~ADDRESS_MASK)|info->i; break;
+ case CPUINFO_INT_SP: SetRegister(cpustate,13,info->i); break;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+CPU_GET_INFO( arm )
+{
+ ARM_REGS *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(ARM_REGS); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 2; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 3; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 4; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 26; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_INPUT_STATE + ARM_IRQ_LINE: info->i = cpustate->pendingIrq; break;
+ case CPUINFO_INT_INPUT_STATE + ARM_FIRQ_LINE: info->i = cpustate->pendingFiq; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = 0; /* not implemented */ break;
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + ARM32_PC: info->i = cpustate->sArmRegister[15]&ADDRESS_MASK; break;
+ case CPUINFO_INT_SP: info->i = GetRegister(cpustate, 13); break;
+
+ case CPUINFO_INT_REGISTER + ARM32_R0: info->i = cpustate->sArmRegister[ 0]; break;
+ case CPUINFO_INT_REGISTER + ARM32_R1: info->i = cpustate->sArmRegister[ 1]; break;
+ case CPUINFO_INT_REGISTER + ARM32_R2: info->i = cpustate->sArmRegister[ 2]; break;
+ case CPUINFO_INT_REGISTER + ARM32_R3: info->i = cpustate->sArmRegister[ 3]; break;
+ case CPUINFO_INT_REGISTER + ARM32_R4: info->i = cpustate->sArmRegister[ 4]; break;
+ case CPUINFO_INT_REGISTER + ARM32_R5: info->i = cpustate->sArmRegister[ 5]; break;
+ case CPUINFO_INT_REGISTER + ARM32_R6: info->i = cpustate->sArmRegister[ 6]; break;
+ case CPUINFO_INT_REGISTER + ARM32_R7: info->i = cpustate->sArmRegister[ 7]; break;
+ case CPUINFO_INT_REGISTER + ARM32_R8: info->i = cpustate->sArmRegister[ 8]; break;
+ case CPUINFO_INT_REGISTER + ARM32_R9: info->i = cpustate->sArmRegister[ 9]; break;
+ case CPUINFO_INT_REGISTER + ARM32_R10: info->i = cpustate->sArmRegister[10]; break;
+ case CPUINFO_INT_REGISTER + ARM32_R11: info->i = cpustate->sArmRegister[11]; break;
+ case CPUINFO_INT_REGISTER + ARM32_R12: info->i = cpustate->sArmRegister[12]; break;
+ case CPUINFO_INT_REGISTER + ARM32_R13: info->i = cpustate->sArmRegister[13]; break;
+ case CPUINFO_INT_REGISTER + ARM32_R14: info->i = cpustate->sArmRegister[14]; break;
+ case CPUINFO_INT_REGISTER + ARM32_R15: info->i = cpustate->sArmRegister[15]; break;
+
+ case CPUINFO_INT_REGISTER + ARM32_FR8: info->i = cpustate->sArmRegister[eR8_FIQ]; break;
+ case CPUINFO_INT_REGISTER + ARM32_FR9: info->i = cpustate->sArmRegister[eR9_FIQ]; break;
+ case CPUINFO_INT_REGISTER + ARM32_FR10: info->i = cpustate->sArmRegister[eR10_FIQ]; break;
+ case CPUINFO_INT_REGISTER + ARM32_FR11: info->i = cpustate->sArmRegister[eR11_FIQ]; break;
+ case CPUINFO_INT_REGISTER + ARM32_FR12: info->i = cpustate->sArmRegister[eR12_FIQ]; break;
+ case CPUINFO_INT_REGISTER + ARM32_FR13: info->i = cpustate->sArmRegister[eR13_FIQ]; break;
+ case CPUINFO_INT_REGISTER + ARM32_FR14: info->i = cpustate->sArmRegister[eR14_FIQ]; break;
+ case CPUINFO_INT_REGISTER + ARM32_IR13: info->i = cpustate->sArmRegister[eR13_IRQ]; break;
+ case CPUINFO_INT_REGISTER + ARM32_IR14: info->i = cpustate->sArmRegister[eR14_IRQ]; break;
+ case CPUINFO_INT_REGISTER + ARM32_SR13: info->i = cpustate->sArmRegister[eR13_SVC]; break;
+ case CPUINFO_INT_REGISTER + ARM32_SR14: info->i = cpustate->sArmRegister[eR14_SVC]; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(arm); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(arm); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(arm); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(arm); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(arm); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(arm); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "ARM"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Acorn Risc Machine"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.3"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Bryan McPhail, bmcphail@tendril.co.uk"); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c%c%c%c%c",
+ (cpustate->sArmRegister[15] & N_MASK) ? 'N' : '-',
+ (cpustate->sArmRegister[15] & Z_MASK) ? 'Z' : '-',
+ (cpustate->sArmRegister[15] & C_MASK) ? 'C' : '-',
+ (cpustate->sArmRegister[15] & V_MASK) ? 'V' : '-',
+ (cpustate->sArmRegister[15] & I_MASK) ? 'I' : '-',
+ (cpustate->sArmRegister[15] & F_MASK) ? 'F' : '-');
+ switch (cpustate->sArmRegister[15] & 3)
+ {
+ case 0:
+ strcat(info->s, " USER");
+ break;
+ case 1:
+ strcat(info->s, " FIRQ");
+ break;
+ case 2:
+ strcat(info->s, " IRQ ");
+ break;
+ default:
+ strcat(info->s, " SVC ");
+ break;
+ }
+ break;
+
+ case CPUINFO_STR_REGISTER + ARM32_PC: sprintf( info->s, "PC :%08x", cpustate->sArmRegister[15]&ADDRESS_MASK ); break;
+ case CPUINFO_STR_REGISTER + ARM32_R0: sprintf( info->s, "R0 :%08x", cpustate->sArmRegister[ 0] ); break;
+ case CPUINFO_STR_REGISTER + ARM32_R1: sprintf( info->s, "R1 :%08x", cpustate->sArmRegister[ 1] ); break;
+ case CPUINFO_STR_REGISTER + ARM32_R2: sprintf( info->s, "R2 :%08x", cpustate->sArmRegister[ 2] ); break;
+ case CPUINFO_STR_REGISTER + ARM32_R3: sprintf( info->s, "R3 :%08x", cpustate->sArmRegister[ 3] ); break;
+ case CPUINFO_STR_REGISTER + ARM32_R4: sprintf( info->s, "R4 :%08x", cpustate->sArmRegister[ 4] ); break;
+ case CPUINFO_STR_REGISTER + ARM32_R5: sprintf( info->s, "R5 :%08x", cpustate->sArmRegister[ 5] ); break;
+ case CPUINFO_STR_REGISTER + ARM32_R6: sprintf( info->s, "R6 :%08x", cpustate->sArmRegister[ 6] ); break;
+ case CPUINFO_STR_REGISTER + ARM32_R7: sprintf( info->s, "R7 :%08x", cpustate->sArmRegister[ 7] ); break;
+ case CPUINFO_STR_REGISTER + ARM32_R8: sprintf( info->s, "R8 :%08x", cpustate->sArmRegister[ 8] ); break;
+ case CPUINFO_STR_REGISTER + ARM32_R9: sprintf( info->s, "R9 :%08x", cpustate->sArmRegister[ 9] ); break;
+ case CPUINFO_STR_REGISTER + ARM32_R10: sprintf( info->s, "R10 :%08x", cpustate->sArmRegister[10] ); break;
+ case CPUINFO_STR_REGISTER + ARM32_R11: sprintf( info->s, "R11 :%08x", cpustate->sArmRegister[11] ); break;
+ case CPUINFO_STR_REGISTER + ARM32_R12: sprintf( info->s, "R12 :%08x", cpustate->sArmRegister[12] ); break;
+ case CPUINFO_STR_REGISTER + ARM32_R13: sprintf( info->s, "R13 :%08x", cpustate->sArmRegister[13] ); break;
+ case CPUINFO_STR_REGISTER + ARM32_R14: sprintf( info->s, "R14 :%08x", cpustate->sArmRegister[14] ); break;
+ case CPUINFO_STR_REGISTER + ARM32_R15: sprintf( info->s, "R15 :%08x", cpustate->sArmRegister[15] ); break;
+ case CPUINFO_STR_REGISTER + ARM32_FR8: sprintf( info->s, "FR8 :%08x", cpustate->sArmRegister[eR8_FIQ] ); break;
+ case CPUINFO_STR_REGISTER + ARM32_FR9: sprintf( info->s, "FR9 :%08x", cpustate->sArmRegister[eR9_FIQ] ); break;
+ case CPUINFO_STR_REGISTER + ARM32_FR10: sprintf( info->s, "FR10:%08x", cpustate->sArmRegister[eR10_FIQ] ); break;
+ case CPUINFO_STR_REGISTER + ARM32_FR11: sprintf( info->s, "FR11:%08x", cpustate->sArmRegister[eR11_FIQ]); break;
+ case CPUINFO_STR_REGISTER + ARM32_FR12: sprintf( info->s, "FR12:%08x", cpustate->sArmRegister[eR12_FIQ] ); break;
+ case CPUINFO_STR_REGISTER + ARM32_FR13: sprintf( info->s, "FR13:%08x", cpustate->sArmRegister[eR13_FIQ] ); break;
+ case CPUINFO_STR_REGISTER + ARM32_FR14: sprintf( info->s, "FR14:%08x", cpustate->sArmRegister[eR14_FIQ] ); break;
+ case CPUINFO_STR_REGISTER + ARM32_IR13: sprintf( info->s, "IR13:%08x", cpustate->sArmRegister[eR13_IRQ] ); break;
+ case CPUINFO_STR_REGISTER + ARM32_IR14: sprintf( info->s, "IR14:%08x", cpustate->sArmRegister[eR14_IRQ] ); break;
+ case CPUINFO_STR_REGISTER + ARM32_SR13: sprintf( info->s, "SR13:%08x", cpustate->sArmRegister[eR13_SVC] ); break;
+ case CPUINFO_STR_REGISTER + ARM32_SR14: sprintf( info->s, "SR14:%08x", cpustate->sArmRegister[eR14_SVC] ); break;
+ }
+}
+
+
+CPU_GET_INFO( arm_be )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(arm_be); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(arm_be); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "ARM (big endian)"); break;
+
+ default: CPU_GET_INFO_CALL(arm); break;
+ }
+}
+
+
+DEFINE_LEGACY_CPU_DEVICE(ARM, arm);
+DEFINE_LEGACY_CPU_DEVICE(ARM_BE, arm_be);
+
diff --git a/trunk/src/emu/cpu/arm/arm.h b/trunk/src/emu/cpu/arm/arm.h
new file mode 100644
index 00000000000..19297096a68
--- /dev/null
+++ b/trunk/src/emu/cpu/arm/arm.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#ifndef __ARM_H__
+#define __ARM_H__
+
+/****************************************************************************************************
+ * INTERRUPT CONSTANTS
+ ***************************************************************************************************/
+
+#define ARM_IRQ_LINE 0
+#define ARM_FIRQ_LINE 1
+
+/****************************************************************************************************
+ * PUBLIC FUNCTIONS
+ ***************************************************************************************************/
+
+DECLARE_LEGACY_CPU_DEVICE(ARM, arm);
+DECLARE_LEGACY_CPU_DEVICE(ARM_BE, arm_be);
+
+enum
+{
+ ARM32_PC=0,
+ ARM32_R0, ARM32_R1, ARM32_R2, ARM32_R3, ARM32_R4, ARM32_R5, ARM32_R6, ARM32_R7,
+ ARM32_R8, ARM32_R9, ARM32_R10, ARM32_R11, ARM32_R12, ARM32_R13, ARM32_R14, ARM32_R15,
+ ARM32_FR8, ARM32_FR9, ARM32_FR10, ARM32_FR11, ARM32_FR12, ARM32_FR13, ARM32_FR14,
+ ARM32_IR13, ARM32_IR14, ARM32_SR13, ARM32_SR14
+};
+
+#endif /* __ARM_H__ */
diff --git a/trunk/src/emu/cpu/arm/armdasm.c b/trunk/src/emu/cpu/arm/armdasm.c
new file mode 100644
index 00000000000..0d596fb5597
--- /dev/null
+++ b/trunk/src/emu/cpu/arm/armdasm.c
@@ -0,0 +1,407 @@
+/*
+ ARM 2/3 disassembler
+
+ (c) 2002-2006 Bryan McPhail (bmcphail@tendril.co.uk) and Phil Stroffolino
+*/
+
+#include "emu.h"
+#include "arm.h"
+
+static char *WriteImmediateOperand( char *pBuf, UINT32 opcode )
+{
+ /* rrrrbbbbbbbb */
+ UINT32 imm;
+ int r;
+
+ imm = opcode&0xff;
+ r = ((opcode>>8)&0xf)*2;
+ imm = (imm>>r)|(imm<<(32-r));
+ pBuf += sprintf( pBuf, ", #$%x", imm );
+ return pBuf;
+}
+
+static char *WriteDataProcessingOperand( char *pBuf, UINT32 opcode, int printOp0, int printOp1, int printOp2 )
+{
+ /* ccccctttmmmm */
+ static const char *const pRegOp[4] = { "LSL","LSR","ASR","ROR" };
+
+ if (printOp0)
+ pBuf += sprintf(pBuf,"R%d, ", (opcode>>12)&0xf);
+ if (printOp1)
+ pBuf += sprintf(pBuf,"R%d, ", (opcode>>16)&0xf);
+
+ /* Immediate Op2 */
+ if( opcode&0x02000000 )
+ return WriteImmediateOperand(pBuf-2,opcode);
+
+ /* Register Op2 */
+ if (printOp2)
+ pBuf += sprintf(pBuf,"R%d, ", (opcode>>0)&0xf);
+
+ pBuf += sprintf(pBuf, "%s ", pRegOp[(opcode>>5)&3] );
+
+ if( opcode&0x10 ) /* Shift amount specified in bottom bits of RS */
+ {
+ pBuf += sprintf( pBuf, "R%d", (opcode>>8)&0xf );
+ }
+ else /* Shift amount immediate 5 bit unsigned integer */
+ {
+ int c=(opcode>>7)&0x1f;
+ if( c==0 ) c = 32;
+ pBuf += sprintf( pBuf, "#%d", c );
+ }
+ return pBuf;
+}
+
+static char *WriteRegisterOperand1( char *pBuf, UINT32 opcode )
+{
+ /* ccccctttmmmm */
+ static const char *const pRegOp[4] = { "LSL","LSR","ASR","ROR" };
+
+ pBuf += sprintf(
+ pBuf,
+ ", R%d %s ", /* Operand 1 register, Operand 2 register, shift type */
+ (opcode>> 0)&0xf,
+ pRegOp[(opcode>>5)&3] );
+
+ if( opcode&0x10 ) /* Shift amount specified in bottom bits of RS */
+ {
+ pBuf += sprintf( pBuf, "R%d", (opcode>>7)&0xf );
+ }
+ else /* Shift amount immediate 5 bit unsigned integer */
+ {
+ int c=(opcode>>7)&0x1f;
+ if( c==0 ) c = 32;
+ pBuf += sprintf( pBuf, "#%d", c );
+ }
+ return pBuf;
+} /* WriteRegisterOperand */
+
+
+static char *WriteBranchAddress( char *pBuf, UINT32 pc, UINT32 opcode )
+{
+ opcode &= 0x00ffffff;
+ if( opcode&0x00800000 )
+ {
+ opcode |= 0xff000000; /* sign-extend */
+ }
+ pc += 8+4*opcode;
+ sprintf( pBuf, "$%x", pc );
+ return pBuf;
+} /* WriteBranchAddress */
+
+static char *WritePadding( char *pBuf, const char *pBuf0 )
+{
+ pBuf0 += 8;
+ while( pBuf<pBuf0 )
+ {
+ *pBuf++ = ' ';
+ }
+ return pBuf;
+}
+
+static UINT32 arm_disasm( char *pBuf, UINT32 pc, UINT32 opcode )
+{
+ const char *pBuf0;
+
+ static const char *const pConditionCodeTable[16] =
+ {
+ "EQ","NE","CS","CC",
+ "MI","PL","VS","VC",
+ "HI","LS","GE","LT",
+ "GT","LE","","NV"
+ };
+ static const char *const pOperation[16] =
+ {
+ "AND","EOR","SUB","RSB",
+ "ADD","ADC","SBC","RSC",
+ "TST","TEQ","CMP","CMN",
+ "ORR","MOV","BIC","MVN"
+ };
+ const char *pConditionCode;
+ UINT32 dasmflags = 0;
+
+ pConditionCode= pConditionCodeTable[opcode>>28];
+ pBuf0 = pBuf;
+
+ if( (opcode&0x0fc000f0)==0x00000090u )
+ {
+ /* multiply */
+ /* xxxx0000 00ASdddd nnnnssss 1001mmmm */
+ if( opcode&0x00200000 )
+ {
+ pBuf += sprintf( pBuf, "MLA" );
+ }
+ else
+ {
+ pBuf += sprintf( pBuf, "MUL" );
+ }
+ pBuf += sprintf( pBuf, "%s", pConditionCode );
+ if( opcode&0x00100000 )
+ {
+ *pBuf++ = 'S';
+ }
+ pBuf = WritePadding( pBuf, pBuf0 );
+
+ pBuf += sprintf( pBuf,
+ "R%d, R%d, R%d",
+ (opcode>>16)&0xf,
+ (opcode&0xf),
+ (opcode>>8)&0xf );
+
+ if( opcode&0x00200000 )
+ {
+ pBuf += sprintf( pBuf, ", R%d", (opcode>>12)&0xf );
+ }
+ }
+ else if( (opcode&0x0c000000)==0 )
+ {
+ int op=(opcode>>21)&0xf;
+
+ /* Data Processing */
+ /* xxxx001a aaaSnnnn ddddrrrr bbbbbbbb */
+ /* xxxx000a aaaSnnnn ddddcccc ctttmmmm */
+
+ pBuf += sprintf(
+ pBuf, "%s%s",
+ pOperation[op],
+ pConditionCode );
+
+ if( (opcode&0x01000000) )
+ {
+ *pBuf++ = 'S';
+ }
+
+ pBuf = WritePadding( pBuf, pBuf0 );
+
+ switch (op) {
+ case 0x00:
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ case 0x04:
+ case 0x05:
+ case 0x06:
+ case 0x07:
+ case 0x0c:
+ case 0x0e:
+ WriteDataProcessingOperand(pBuf, opcode, 1, 1, 1);
+ break;
+ case 0x08:
+ case 0x09:
+ case 0x0a:
+ case 0x0b:
+ WriteDataProcessingOperand(pBuf, opcode, 0, 1, 1);
+ break;
+ case 0x0d:
+ /* look for mov pc,lr */
+ if (((opcode >> 12) & 0x0f) == 15 && ((opcode >> 0) & 0x0f) == 14 && (opcode & 0x02000000) == 0)
+ dasmflags = DASMFLAG_STEP_OUT;
+ case 0x0f:
+ WriteDataProcessingOperand(pBuf, opcode, 1, 0, 1);
+ break;
+ }
+ }
+ else if( (opcode&0x0c000000)==0x04000000 )
+ {
+ /* Data Transfer */
+
+ /* xxxx010P UBWLnnnn ddddoooo oooooooo Immediate form */
+ /* xxxx011P UBWLnnnn ddddcccc ctt0mmmm Register form */
+ if( opcode&0x00100000 )
+ {
+ pBuf += sprintf( pBuf, "LDR" );
+ }
+ else
+ {
+ pBuf += sprintf( pBuf, "STR" );
+ }
+ pBuf += sprintf( pBuf, "%s", pConditionCode );
+
+ if( opcode&0x00400000 )
+ {
+ pBuf += sprintf( pBuf, "B" );
+ }
+
+ if( opcode&0x00200000 )
+ {
+ /* writeback addr */
+ if( opcode&0x01000000 )
+ {
+ /* pre-indexed addressing */
+ pBuf += sprintf( pBuf, "!" );
+ }
+ else
+ {
+ /* post-indexed addressing */
+ pBuf += sprintf( pBuf, "T" );
+ }
+ }
+
+ pBuf = WritePadding( pBuf, pBuf0 );
+ pBuf += sprintf( pBuf, "R%d, [R%d",
+ (opcode>>12)&0xf, (opcode>>16)&0xf );
+
+ if( opcode&0x02000000 )
+ {
+ /* register form */
+ pBuf = WriteRegisterOperand1( pBuf, opcode );
+ pBuf += sprintf( pBuf, "]" );
+ }
+ else
+ {
+ /* immediate form */
+ pBuf += sprintf( pBuf, "]" );
+ if( opcode&0x00800000 )
+ {
+ pBuf += sprintf( pBuf, ", #$%x", opcode&0xfff );
+ }
+ else
+ {
+ pBuf += sprintf( pBuf, ", -#$%x", opcode&0xfff );
+ }
+ }
+ }
+ else if( (opcode&0x0e000000) == 0x08000000 )
+ {
+ /* xxxx100P USWLnnnn llllllll llllllll */
+ /* Block Data Transfer */
+
+ if( opcode&0x00100000 )
+ {
+ pBuf += sprintf( pBuf, "LDM" );
+ }
+ else
+ {
+ pBuf += sprintf( pBuf, "STM" );
+ }
+ pBuf += sprintf( pBuf, "%s", pConditionCode );
+
+ if( opcode&0x01000000 )
+ {
+ pBuf += sprintf( pBuf, "P" );
+ }
+ if( opcode&0x00800000 )
+ {
+ pBuf += sprintf( pBuf, "U" );
+ }
+ if( opcode&0x00400000 )
+ {
+ pBuf += sprintf( pBuf, "^" );
+ }
+ if( opcode&0x00200000 )
+ {
+ pBuf += sprintf( pBuf, "W" );
+ }
+
+ pBuf = WritePadding( pBuf, pBuf0 );
+ pBuf += sprintf( pBuf, "[R%d], {",(opcode>>16)&0xf);
+
+ {
+ int j=0,last=0,found=0;
+ for (j=0; j<16; j++) {
+ if (opcode&(1<<j) && found==0) {
+ found=1;
+ last=j;
+ }
+ else if ((opcode&(1<<j))==0 && found) {
+ if (last==j-1)
+ pBuf += sprintf( pBuf, " R%d,",last);
+ else
+ pBuf += sprintf( pBuf, " R%d-R%d,",last,j-1);
+ found=0;
+ }
+ }
+ if (found && last==15)
+ pBuf += sprintf( pBuf, " R15,");
+ else if (found)
+ pBuf += sprintf( pBuf, " R%d-R%d,",last,15);
+ }
+
+ pBuf--;
+ pBuf += sprintf( pBuf, " }");
+ }
+ else if( (opcode&0x0e000000)==0x0a000000 )
+ {
+ /* branch instruction */
+ /* xxxx101L oooooooo oooooooo oooooooo */
+ if( opcode&0x01000000 )
+ {
+ pBuf += sprintf( pBuf, "BL" );
+ dasmflags = DASMFLAG_STEP_OVER;
+ }
+ else
+ {
+ pBuf += sprintf( pBuf, "B" );
+ }
+
+ pBuf += sprintf( pBuf, "%s", pConditionCode );
+
+ pBuf = WritePadding( pBuf, pBuf0 );
+
+ pBuf = WriteBranchAddress( pBuf, pc, opcode );
+ }
+ else if( (opcode&0x0f000000) == 0x0e000000 )
+ {
+ /* co-processor */
+ /* xxxx1110 oooLNNNN ddddpppp qqq1MMMM MRC/MCR */
+ if( (opcode&0x0f100000)==0x0e100000 )
+ {
+ if( (opcode&0x0f100010)==0x0e100010 )
+ {
+ pBuf += sprintf( pBuf, "MRC" );
+ }
+ else if( (opcode&0x0f100010)==0x0e000010 )
+ {
+ pBuf += sprintf( pBuf, "MCR" );
+ }
+ else
+ {
+ pBuf += sprintf( pBuf, "???" );
+ }
+
+ pBuf += sprintf( pBuf, "%s", pConditionCode );
+ pBuf = WritePadding( pBuf, pBuf0 );
+ pBuf += sprintf( pBuf, "R%d, CR%d {CRM%d, q%d}",(opcode>>12)&0xf, (opcode>>16)&0xf, (opcode>>0)&0xf, (opcode>>5)&0x7);
+ /* Nb: full form should be o, p, R, CR, CRM, q */
+ }
+ else if( (opcode&0x0f000010)==0x0e000000 )
+ {
+ pBuf += sprintf( pBuf, "CDP" );
+ pBuf += sprintf( pBuf, "%s", pConditionCode );
+ pBuf = WritePadding( pBuf, pBuf0 );
+ pBuf += sprintf( pBuf, "%08x", opcode );
+ }
+ else
+ {
+ pBuf += sprintf( pBuf, "???" );
+ }
+ }
+ else if( (opcode&0x0f000000) == 0x0f000000 )
+ {
+ /* Software Interrupt */
+ pBuf += sprintf( pBuf, "SWI%s $%x",
+ pConditionCode,
+ opcode&0x00ffffff );
+ dasmflags = DASMFLAG_STEP_OVER;
+ }
+ else
+ {
+ pBuf += sprintf( pBuf, "Undefined" );
+ }
+
+ return dasmflags | DASMFLAG_SUPPORTED;
+}
+
+CPU_DISASSEMBLE( arm )
+{
+ UINT32 opcode = oprom[0] | (oprom[1] << 8) | (oprom[2] << 16) | (oprom[3] << 24);
+ return 4 | arm_disasm(buffer, pc, opcode);
+}
+
+CPU_DISASSEMBLE( arm_be )
+{
+ UINT32 opcode = oprom[3] | (oprom[2] << 8) | (oprom[1] << 16) | (oprom[0] << 24);
+ return 4 | arm_disasm(buffer, pc, opcode);
+}
+
diff --git a/trunk/src/emu/cpu/arm7/arm7.c b/trunk/src/emu/cpu/arm7/arm7.c
new file mode 100644
index 00000000000..d647f04ddce
--- /dev/null
+++ b/trunk/src/emu/cpu/arm7/arm7.c
@@ -0,0 +1,1061 @@
+/*****************************************************************************
+ *
+ * arm7.c
+ * Portable CPU Emulator for 32-bit ARM v3/4/5/6
+ *
+ * Copyright Steve Ellenoff, all rights reserved.
+ * Thumb, DSP, and MMU support and many bugfixes by R. Belmont and Ryan Holtz.
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * sellenoff@hotmail.com
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ * This work is based on:
+ * #1) 'Atmel Corporation ARM7TDMI (Thumb) Datasheet - January 1999'
+ * #2) Arm 2/3/6 emulator By Bryan McPhail (bmcphail@tendril.co.uk) and Phil Stroffolino (MAME CORE 0.76)
+ *
+ *****************************************************************************/
+
+/******************************************************************************
+ * Notes:
+
+ ** This is a plain vanilla implementation of an ARM7 cpu which incorporates my ARM7 core.
+ It can be used as is, or used to demonstrate how to utilize the arm7 core to create a cpu
+ that uses the core, since there are numerous different mcu packages that incorporate an arm7 core.
+
+ See the notes in the arm7core.c file itself regarding issues/limitations of the arm7 core.
+ **
+*****************************************************************************/
+#include "emu.h"
+#include "debugger.h"
+#include "arm7.h"
+#include "arm7core.h" //include arm7 core
+
+#if 0
+#define LOG(x) mame_printf_debug x
+#else
+#define LOG(x) logerror x
+#endif
+
+/* prototypes of coprocessor functions */
+static WRITE32_DEVICE_HANDLER(arm7_do_callback);
+static READ32_DEVICE_HANDLER(arm7_rt_r_callback);
+static WRITE32_DEVICE_HANDLER(arm7_rt_w_callback);
+void arm7_dt_r_callback(arm_state *cpustate, UINT32 insn, UINT32 *prn, UINT32 (*read32)(arm_state *cpustate, UINT32 addr));
+void arm7_dt_w_callback(arm_state *cpustate, UINT32 insn, UINT32 *prn, void (*write32)(arm_state *cpustate, UINT32 addr, UINT32 data));
+
+/* Macros that can be re-defined for custom cpu implementations - The core expects these to be defined */
+/* In this case, we are using the default arm7 handlers (supplied by the core)
+ - but simply changes these and define your own if needed for cpu implementation specific needs */
+#define READ8(addr) arm7_cpu_read8(cpustate, addr)
+#define WRITE8(addr,data) arm7_cpu_write8(cpustate, addr,data)
+#define READ16(addr) arm7_cpu_read16(cpustate, addr)
+#define WRITE16(addr,data) arm7_cpu_write16(cpustate, addr,data)
+#define READ32(addr) arm7_cpu_read32(cpustate, addr)
+#define WRITE32(addr,data) arm7_cpu_write32(cpustate, addr,data)
+#define PTR_READ32 &arm7_cpu_read32
+#define PTR_WRITE32 &arm7_cpu_write32
+
+/* Macros that need to be defined according to the cpu implementation specific need */
+#define ARM7REG(reg) cpustate->sArmRegister[reg]
+#define ARM7_ICOUNT cpustate->iCount
+
+INLINE arm_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == ARM7 || device->type() == ARM7_BE || device->type() == ARM7500 || device->type() == ARM9 || device->type() == ARM920T || device->type() == PXA255);
+ return (arm_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+void set_cpsr( arm_state *cpustate, UINT32 val)
+{
+ if (cpustate->archFlags & eARM_ARCHFLAGS_MODE26)
+ {
+ if ((val & 0x10) != (ARM7REG(eCPSR) & 0x10))
+ {
+ if (val & 0x10)
+ {
+ // 26 -> 32
+ val = (val & 0x0FFFFF3F) | (R15 & 0xF0000000) /* N Z C V */ | ((R15 & 0x0C000000) >> (26 - 6)) /* I F */;
+ R15 = R15 & 0x03FFFFFC;
+ }
+ else
+ {
+ // 32 -> 26
+ R15 = (R15 & 0x03FFFFFC) /* PC */ | (val & 0xF0000000) /* N Z C V */ | ((val & 0x000000C0) << (26 - 6)) /* I F */ | (val & 0x00000003) /* M1 M0 */;
+ }
+ }
+ else
+ {
+ if (!(val & 0x10))
+ {
+ // mirror bits in pc
+ R15 = (R15 & 0x03FFFFFF) | (val & 0xF0000000) /* N Z C V */ | ((val & 0x000000C0) << (26 - 6)) /* I F */;
+ }
+ }
+ }
+ else
+ {
+ val |= 0x10; // force valid mode
+ }
+ ARM7REG(eCPSR) = val;
+}
+
+INLINE INT64 saturate_qbit_overflow(arm_state *cpustate, INT64 res)
+{
+ if (res > 2147483647) // INT32_MAX
+ { // overflow high? saturate and set Q
+ res = 2147483647;
+ SET_CPSR(GET_CPSR | Q_MASK);
+ }
+ else if (res < (-2147483647-1)) // INT32_MIN
+ { // overflow low? saturate and set Q
+ res = (-2147483647-1);
+ SET_CPSR(GET_CPSR | Q_MASK);
+ }
+
+ return res;
+}
+
+/**************************************************************************
+ * ARM TLB IMPLEMENTATION
+ **************************************************************************/
+
+enum
+{
+ TLB_COARSE = 0,
+ TLB_FINE,
+};
+
+INLINE UINT32 arm7_tlb_get_first_level_descriptor( arm_state *cpustate, UINT32 vaddr )
+{
+ UINT32 entry_paddr = ( COPRO_TLB_BASE & COPRO_TLB_BASE_MASK ) | ( ( vaddr & COPRO_TLB_VADDR_FLTI_MASK ) >> COPRO_TLB_VADDR_FLTI_MASK_SHIFT );
+ return cpustate->program->read_dword( entry_paddr );
+}
+
+INLINE UINT32 arm7_tlb_get_second_level_descriptor( arm_state *cpustate, UINT32 granularity, UINT32 first_desc, UINT32 vaddr )
+{
+ UINT32 desc_lvl2 = vaddr;
+
+ switch( granularity )
+ {
+ case TLB_COARSE:
+ desc_lvl2 = ( first_desc & COPRO_TLB_CFLD_ADDR_MASK ) | ( ( vaddr & COPRO_TLB_VADDR_CSLTI_MASK ) >> COPRO_TLB_VADDR_CSLTI_MASK_SHIFT );
+ break;
+ case TLB_FINE:
+ LOG( ( "ARM7: Attempting to get second-level TLB descriptor of fine granularity\n" ) );
+ break;
+ default:
+ // We shouldn't be here
+ LOG( ( "ARM7: Attempting to get second-level TLB descriptor of invalid granularity (%d)\n", granularity ) );
+ break;
+ }
+
+ return cpustate->program->read_dword( desc_lvl2 );
+}
+
+INLINE UINT32 arm7_tlb_translate(arm_state *cpustate, UINT32 vaddr, int mode)
+{
+ UINT32 desc_lvl1;
+ UINT32 desc_lvl2 = 0;
+ UINT32 paddr;
+ UINT8 domain, permission;
+
+ if (vaddr < 32 * 1024 * 1024)
+ {
+ UINT32 pid = ((COPRO_FCSE_PID >> 25) & 0x7F);
+ if (pid > 0)
+ {
+ //LOG( ( "ARM7: FCSE PID vaddr %08X -> %08X\n", vaddr, vaddr + (pid * (32 * 1024 * 1024))) );
+ vaddr = vaddr + (((COPRO_FCSE_PID >> 25) & 0x7F) * (32 * 1024 * 1024));
+ }
+ }
+
+ desc_lvl1 = arm7_tlb_get_first_level_descriptor( cpustate, vaddr );
+
+ paddr = vaddr;
+
+#if ARM7_MMU_ENABLE_HACK
+ if ((R15 == (cpustate->mmu_enable_addr + 4)) || (R15 == (cpustate->mmu_enable_addr + 8)))
+ {
+ LOG( ( "ARM7: fetch flat, PC = %08x, vaddr = %08x\n", R15, vaddr ) );
+ return vaddr;
+ }
+ else
+ {
+ cpustate->mmu_enable_addr = 1;
+ }
+#endif
+
+ domain = (desc_lvl1 >> 5) & 0xF;
+ permission = (COPRO_DOMAIN_ACCESS_CONTROL >> (domain << 1)) & 3;
+
+ switch( desc_lvl1 & 3 )
+ {
+ case COPRO_TLB_UNMAPPED:
+ // Unmapped, generate a translation fault
+ if (mode == ARM7_TLB_ABORT_D)
+ {
+ LOG( ( "ARM7: Not Yet Implemented: Translation fault on unmapped virtual address, PC = %08x, vaddr = %08x\n", R15, vaddr ) );
+ COPRO_FAULT_STATUS = (5 << 0);
+ COPRO_FAULT_ADDRESS = vaddr;
+ cpustate->pendingAbtD = 1;
+ }
+ else if (mode == ARM7_TLB_ABORT_P)
+ {
+ LOG( ( "ARM7: Not Yet Implemented: Translation fault on unmapped virtual address, PC = %08x, vaddr = %08x\n", R15, vaddr ) );
+ cpustate->pendingAbtP = 1;
+ }
+ break;
+ case COPRO_TLB_COARSE_TABLE:
+ // Entry is the physical address of a coarse second-level table
+ if (permission == 1)
+ {
+ desc_lvl2 = arm7_tlb_get_second_level_descriptor( cpustate, TLB_COARSE, desc_lvl1, vaddr );
+ }
+ else
+ {
+ LOG( ( "domain %d permission = %d\n", domain, permission ) );
+ LOG( ( "ARM7: Coarse Table, Section Domain fault on virtual address, vaddr = %08x, domain = %08x, PC = %08x\n", vaddr, domain, R15 ) );
+ }
+ break;
+ case COPRO_TLB_SECTION_TABLE:
+ // Entry is a section
+ if ((permission == 1) || (permission == 3))
+ {
+ paddr = ( desc_lvl1 & COPRO_TLB_SECTION_PAGE_MASK ) | ( vaddr & ~COPRO_TLB_SECTION_PAGE_MASK );
+ }
+ else
+ {
+ if (mode == ARM7_TLB_ABORT_D)
+ {
+ LOG( ( "domain %d permission = %d\n", domain, permission ) );
+ LOG( ( "ARM7: Section Table, Section Domain fault on virtual address, vaddr = %08x, domain = %08x, PC = %08x\n", vaddr, domain, R15 ) );
+ COPRO_FAULT_STATUS = (9 << 0);
+ COPRO_FAULT_ADDRESS = vaddr;
+ cpustate->pendingAbtD = 1;
+ }
+ else if (mode == ARM7_TLB_ABORT_P)
+ {
+ LOG( ( "domain %d permission = %d\n", domain, permission ) );
+ LOG( ( "ARM7: Section Table, Section Domain fault on virtual address, vaddr = %08x, domain = %08x, PC = %08x\n", vaddr, domain, R15 ) );
+ cpustate->pendingAbtP = 1;
+ }
+ }
+ break;
+ case COPRO_TLB_FINE_TABLE:
+ // Entry is the physical address of a fine second-level table
+ LOG( ( "ARM7: Not Yet Implemented: fine second-level TLB lookup, PC = %08x, vaddr = %08x\n", R15, vaddr ) );
+ break;
+ default:
+ // Entry is the physical address of a three-legged termite-eaten table
+ break;
+ }
+
+ if( ( desc_lvl1 & 3 ) == COPRO_TLB_COARSE_TABLE || ( desc_lvl1 & 3 ) == COPRO_TLB_FINE_TABLE )
+ {
+ switch( desc_lvl2 & 3 )
+ {
+ case COPRO_TLB_UNMAPPED:
+ // Unmapped, generate a translation fault
+ if (mode == ARM7_TLB_ABORT_D)
+ {
+ LOG( ( "ARM7: Not Yet Implemented: Translation fault on unmapped virtual address, vaddr = %08x, PC %08X\n", vaddr, R15 ) );
+ COPRO_FAULT_STATUS = (7 << 0);
+ COPRO_FAULT_ADDRESS = vaddr;
+ cpustate->pendingAbtD = 1;
+ }
+ else if (mode == ARM7_TLB_ABORT_P)
+ {
+ LOG( ( "ARM7: Not Yet Implemented: Translation fault on unmapped virtual address, vaddr = %08x, PC %08X\n", vaddr, R15 ) );
+ cpustate->pendingAbtP = 1;
+ }
+ break;
+ case COPRO_TLB_LARGE_PAGE:
+ // Large page descriptor
+ paddr = ( desc_lvl2 & COPRO_TLB_LARGE_PAGE_MASK ) | ( vaddr & ~COPRO_TLB_LARGE_PAGE_MASK );
+ break;
+ case COPRO_TLB_SMALL_PAGE:
+ // Small page descriptor
+ paddr = ( desc_lvl2 & COPRO_TLB_SMALL_PAGE_MASK ) | ( vaddr & ~COPRO_TLB_SMALL_PAGE_MASK );
+ break;
+ case COPRO_TLB_TINY_PAGE:
+ // Tiny page descriptor
+ if( ( desc_lvl1 & 3 ) == 1 )
+ {
+ LOG( ( "ARM7: It would appear that we're looking up a tiny page from a coarse TLB lookup. This is bad. vaddr = %08x\n", vaddr ) );
+ }
+ paddr = ( desc_lvl2 & COPRO_TLB_TINY_PAGE_MASK ) | ( vaddr & ~COPRO_TLB_TINY_PAGE_MASK );
+ break;
+ }
+ }
+
+ return paddr;
+}
+
+static CPU_TRANSLATE( arm7 )
+{
+ arm_state *cpustate = (device != NULL) ? (arm_state *)device->token() : NULL;
+
+ /* only applies to the program address space and only does something if the MMU's enabled */
+ if( space == AS_PROGRAM && ( COPRO_CTRL & COPRO_CTRL_MMU_EN ) )
+ {
+ *address = arm7_tlb_translate(cpustate, *address, ARM7_TLB_NO_ABORT);
+ }
+ return TRUE;
+}
+
+
+/* include the arm7 core */
+#include "arm7core.c"
+
+/***************************************************************************
+ * CPU SPECIFIC IMPLEMENTATIONS
+ **************************************************************************/
+static CPU_INIT( arm7 )
+{
+ arm_state *cpustate = get_safe_token(device);
+
+ // must call core
+ arm7_core_init(device, "arm7");
+
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+
+ // setup co-proc callbacks
+ arm7_coproc_do_callback = arm7_do_callback;
+ arm7_coproc_rt_r_callback = arm7_rt_r_callback;
+ arm7_coproc_rt_w_callback = arm7_rt_w_callback;
+ arm7_coproc_dt_r_callback = arm7_dt_r_callback;
+ arm7_coproc_dt_w_callback = arm7_dt_w_callback;
+}
+
+static CPU_RESET( arm7 )
+{
+ arm_state *cpustate = get_safe_token(device);
+
+ // must call core reset
+ arm7_core_reset(device);
+
+ cpustate->archRev = 4; // ARMv4
+ cpustate->archFlags = eARM_ARCHFLAGS_T; // has Thumb
+}
+
+static CPU_RESET( arm7_be )
+{
+ arm_state *cpustate = get_safe_token(device);
+
+ CPU_RESET_CALL( arm7 );
+ cpustate->endian = ENDIANNESS_BIG;
+}
+
+static CPU_RESET( arm7500 )
+{
+ arm_state *cpustate = get_safe_token(device);
+
+ // must call core reset
+ arm7_core_reset(device);
+
+ cpustate->archRev = 3; // ARMv3
+ cpustate->archFlags = eARM_ARCHFLAGS_MODE26;
+}
+
+static CPU_RESET( arm9 )
+{
+ arm_state *cpustate = get_safe_token(device);
+
+ // must call core reset
+ arm7_core_reset(device);
+
+ cpustate->archRev = 5; // ARMv5
+ cpustate->archFlags = eARM_ARCHFLAGS_T | eARM_ARCHFLAGS_E; // has TE extensions
+}
+
+static CPU_RESET( arm920t )
+{
+ arm_state *cpustate = get_safe_token(device);
+
+ // must call core reset
+ arm7_core_reset(device);
+
+ cpustate->archRev = 4; // ARMv4
+ cpustate->archFlags = eARM_ARCHFLAGS_T; // has T extension
+}
+
+static CPU_RESET( pxa255 )
+{
+ arm_state *cpustate = get_safe_token(device);
+
+ // must call core reset
+ arm7_core_reset(device);
+
+ cpustate->archRev = 5; // ARMv5
+ cpustate->archFlags = eARM_ARCHFLAGS_T | eARM_ARCHFLAGS_E | eARM_ARCHFLAGS_XSCALE; // has TE and XScale extensions
+}
+
+static CPU_RESET( sa1110 )
+{
+ arm_state *cpustate = get_safe_token(device);
+
+ // must call core reset
+ arm7_core_reset(device);
+
+ cpustate->archRev = 4; // ARMv4
+ cpustate->archFlags = eARM_ARCHFLAGS_SA; // has StrongARM, no Thumb, no Enhanced DSP
+}
+
+static CPU_EXIT( arm7 )
+{
+ /* nothing to do here */
+}
+
+static CPU_EXECUTE( arm7 )
+{
+/* include the arm7 core execute code */
+#include "arm7exec.c"
+}
+
+
+static void set_irq_line(arm_state *cpustate, int irqline, int state)
+{
+ // must call core
+ arm7_core_set_irq_line(cpustate, irqline, state);
+}
+
+static CPU_DISASSEMBLE( arm7 )
+{
+ CPU_DISASSEMBLE( arm7arm );
+ CPU_DISASSEMBLE( arm7thumb );
+
+ arm_state *cpustate = get_safe_token(device);
+
+ if (T_IS_SET(GET_CPSR))
+ return CPU_DISASSEMBLE_CALL(arm7thumb);
+ else
+ return CPU_DISASSEMBLE_CALL(arm7arm);
+}
+
+static CPU_DISASSEMBLE( arm7_be )
+{
+ CPU_DISASSEMBLE( arm7arm_be );
+ CPU_DISASSEMBLE( arm7thumb_be );
+
+ arm_state *cpustate = get_safe_token(device);
+
+ if (T_IS_SET(GET_CPSR))
+ return CPU_DISASSEMBLE_CALL(arm7thumb_be);
+ else
+ return CPU_DISASSEMBLE_CALL(arm7arm_be);
+}
+
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( arm7 )
+{
+ arm_state *cpustate = get_safe_token(device);
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+
+ /* interrupt lines/exceptions */
+ case CPUINFO_INT_INPUT_STATE + ARM7_IRQ_LINE: set_irq_line(cpustate, ARM7_IRQ_LINE, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + ARM7_FIRQ_LINE: set_irq_line(cpustate, ARM7_FIRQ_LINE, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + ARM7_ABORT_EXCEPTION: set_irq_line(cpustate, ARM7_ABORT_EXCEPTION, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + ARM7_ABORT_PREFETCH_EXCEPTION: set_irq_line(cpustate, ARM7_ABORT_PREFETCH_EXCEPTION, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + ARM7_UNDEFINE_EXCEPTION: set_irq_line(cpustate, ARM7_UNDEFINE_EXCEPTION, info->i); break;
+
+ /* registers shared by all operating modes */
+ case CPUINFO_INT_REGISTER + ARM7_R0: ARM7REG( 0) = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM7_R1: ARM7REG( 1) = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM7_R2: ARM7REG( 2) = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM7_R3: ARM7REG( 3) = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM7_R4: ARM7REG( 4) = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM7_R5: ARM7REG( 5) = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM7_R6: ARM7REG( 6) = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM7_R7: ARM7REG( 7) = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM7_R8: ARM7REG( 8) = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM7_R9: ARM7REG( 9) = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM7_R10: ARM7REG(10) = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM7_R11: ARM7REG(11) = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM7_R12: ARM7REG(12) = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM7_R13: ARM7REG(13) = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM7_R14: ARM7REG(14) = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM7_R15: ARM7REG(15) = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM7_CPSR: SET_CPSR(info->i); break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + ARM7_PC: R15 = info->i; break;
+ case CPUINFO_INT_SP: SetRegister(cpustate, 13,info->i); break;
+
+ /* FIRQ Mode Shadowed Registers */
+ case CPUINFO_INT_REGISTER + ARM7_FR8: ARM7REG(eR8_FIQ) = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM7_FR9: ARM7REG(eR9_FIQ) = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM7_FR10: ARM7REG(eR10_FIQ) = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM7_FR11: ARM7REG(eR11_FIQ) = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM7_FR12: ARM7REG(eR12_FIQ) = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM7_FR13: ARM7REG(eR13_FIQ) = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM7_FR14: ARM7REG(eR14_FIQ) = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM7_FSPSR: ARM7REG(eSPSR_FIQ) = info->i; break;
+
+ /* IRQ Mode Shadowed Registers */
+ case CPUINFO_INT_REGISTER + ARM7_IR13: ARM7REG(eR13_IRQ) = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM7_IR14: ARM7REG(eR14_IRQ) = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM7_ISPSR: ARM7REG(eSPSR_IRQ) = info->i; break;
+
+ /* Supervisor Mode Shadowed Registers */
+ case CPUINFO_INT_REGISTER + ARM7_SR13: ARM7REG(eR13_SVC) = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM7_SR14: ARM7REG(eR14_SVC) = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM7_SSPSR: ARM7REG(eSPSR_SVC) = info->i; break;
+
+ /* Abort Mode Shadowed Registers */
+ case CPUINFO_INT_REGISTER + ARM7_AR13: ARM7REG(eR13_ABT) = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM7_AR14: ARM7REG(eR14_ABT) = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM7_ASPSR: ARM7REG(eSPSR_ABT) = info->i; break;
+
+ /* Undefined Mode Shadowed Registers */
+ case CPUINFO_INT_REGISTER + ARM7_UR13: ARM7REG(eR13_UND) = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM7_UR14: ARM7REG(eR14_UND) = info->i; break;
+ case CPUINFO_INT_REGISTER + ARM7_USPSR: ARM7REG(eSPSR_UND) = info->i; break;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+CPU_GET_INFO( arm7 )
+{
+ arm_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+
+ /* cpu implementation data */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(arm_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = ARM7_NUM_LINES; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 2; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 3; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 4; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ /* interrupt lines/exceptions */
+ case CPUINFO_INT_INPUT_STATE + ARM7_IRQ_LINE: info->i = cpustate->pendingIrq; break;
+ case CPUINFO_INT_INPUT_STATE + ARM7_FIRQ_LINE: info->i = cpustate->pendingFiq; break;
+ case CPUINFO_INT_INPUT_STATE + ARM7_ABORT_EXCEPTION: info->i = cpustate->pendingAbtD; break;
+ case CPUINFO_INT_INPUT_STATE + ARM7_ABORT_PREFETCH_EXCEPTION: info->i = cpustate->pendingAbtP; break;
+ case CPUINFO_INT_INPUT_STATE + ARM7_UNDEFINE_EXCEPTION: info->i = cpustate->pendingUnd; break;
+
+ /* registers shared by all operating modes */
+ case CPUINFO_INT_REGISTER + ARM7_R0: info->i = ARM7REG( 0); break;
+ case CPUINFO_INT_REGISTER + ARM7_R1: info->i = ARM7REG( 1); break;
+ case CPUINFO_INT_REGISTER + ARM7_R2: info->i = ARM7REG( 2); break;
+ case CPUINFO_INT_REGISTER + ARM7_R3: info->i = ARM7REG( 3); break;
+ case CPUINFO_INT_REGISTER + ARM7_R4: info->i = ARM7REG( 4); break;
+ case CPUINFO_INT_REGISTER + ARM7_R5: info->i = ARM7REG( 5); break;
+ case CPUINFO_INT_REGISTER + ARM7_R6: info->i = ARM7REG( 6); break;
+ case CPUINFO_INT_REGISTER + ARM7_R7: info->i = ARM7REG( 7); break;
+ case CPUINFO_INT_REGISTER + ARM7_R8: info->i = ARM7REG( 8); break;
+ case CPUINFO_INT_REGISTER + ARM7_R9: info->i = ARM7REG( 9); break;
+ case CPUINFO_INT_REGISTER + ARM7_R10: info->i = ARM7REG(10); break;
+ case CPUINFO_INT_REGISTER + ARM7_R11: info->i = ARM7REG(11); break;
+ case CPUINFO_INT_REGISTER + ARM7_R12: info->i = ARM7REG(12); break;
+ case CPUINFO_INT_REGISTER + ARM7_R13: info->i = ARM7REG(13); break;
+ case CPUINFO_INT_REGISTER + ARM7_R14: info->i = ARM7REG(14); break;
+ case CPUINFO_INT_REGISTER + ARM7_R15: info->i = ARM7REG(15); break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = 0; /* not implemented */ break;
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + ARM7_PC: info->i = GET_PC; break;
+ case CPUINFO_INT_SP: info->i = GetRegister(cpustate, 13); break;
+
+ /* FIRQ Mode Shadowed Registers */
+ case CPUINFO_INT_REGISTER + ARM7_FR8: info->i = ARM7REG(eR8_FIQ); break;
+ case CPUINFO_INT_REGISTER + ARM7_FR9: info->i = ARM7REG(eR9_FIQ); break;
+ case CPUINFO_INT_REGISTER + ARM7_FR10: info->i = ARM7REG(eR10_FIQ); break;
+ case CPUINFO_INT_REGISTER + ARM7_FR11: info->i = ARM7REG(eR11_FIQ); break;
+ case CPUINFO_INT_REGISTER + ARM7_FR12: info->i = ARM7REG(eR12_FIQ); break;
+ case CPUINFO_INT_REGISTER + ARM7_FR13: info->i = ARM7REG(eR13_FIQ); break;
+ case CPUINFO_INT_REGISTER + ARM7_FR14: info->i = ARM7REG(eR14_FIQ); break;
+ case CPUINFO_INT_REGISTER + ARM7_FSPSR: info->i = ARM7REG(eSPSR_FIQ); break;
+
+ /* IRQ Mode Shadowed Registers */
+ case CPUINFO_INT_REGISTER + ARM7_IR13: info->i = ARM7REG(eR13_IRQ); break;
+ case CPUINFO_INT_REGISTER + ARM7_IR14: info->i = ARM7REG(eR14_IRQ); break;
+ case CPUINFO_INT_REGISTER + ARM7_ISPSR: info->i = ARM7REG(eSPSR_IRQ); break;
+
+ /* Supervisor Mode Shadowed Registers */
+ case CPUINFO_INT_REGISTER + ARM7_SR13: info->i = ARM7REG(eR13_SVC); break;
+ case CPUINFO_INT_REGISTER + ARM7_SR14: info->i = ARM7REG(eR14_SVC); break;
+ case CPUINFO_INT_REGISTER + ARM7_SSPSR: info->i = ARM7REG(eSPSR_SVC); break;
+
+ /* Abort Mode Shadowed Registers */
+ case CPUINFO_INT_REGISTER + ARM7_AR13: info->i = ARM7REG(eR13_ABT); break;
+ case CPUINFO_INT_REGISTER + ARM7_AR14: info->i = ARM7REG(eR14_ABT); break;
+ case CPUINFO_INT_REGISTER + ARM7_ASPSR: info->i = ARM7REG(eSPSR_ABT); break;
+
+ /* Undefined Mode Shadowed Registers */
+ case CPUINFO_INT_REGISTER + ARM7_UR13: info->i = ARM7REG(eR13_UND); break;
+ case CPUINFO_INT_REGISTER + ARM7_UR14: info->i = ARM7REG(eR14_UND); break;
+ case CPUINFO_INT_REGISTER + ARM7_USPSR: info->i = ARM7REG(eSPSR_UND); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(arm7); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(arm7); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(arm7); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(arm7); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(arm7); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(arm7); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &ARM7_ICOUNT; break;
+ case CPUINFO_FCT_TRANSLATE: info->translate = CPU_TRANSLATE_NAME(arm7); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "ARM7"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Acorn Risc Machine"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "2.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Steve Ellenoff, sellenoff@hotmail.com"); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c%c%c%c%c%c%c %s",
+ (ARM7REG(eCPSR) & N_MASK) ? 'N' : '-',
+ (ARM7REG(eCPSR) & Z_MASK) ? 'Z' : '-',
+ (ARM7REG(eCPSR) & C_MASK) ? 'C' : '-',
+ (ARM7REG(eCPSR) & V_MASK) ? 'V' : '-',
+ (ARM7REG(eCPSR) & Q_MASK) ? 'Q' : '-',
+ (ARM7REG(eCPSR) & I_MASK) ? 'I' : '-',
+ (ARM7REG(eCPSR) & F_MASK) ? 'F' : '-',
+ (ARM7REG(eCPSR) & T_MASK) ? 'T' : '-',
+ GetModeText(ARM7REG(eCPSR)));
+ break;
+
+ /* registers shared by all operating modes */
+ case CPUINFO_STR_REGISTER + ARM7_PC: sprintf(info->s, "PC :%08x", GET_PC); break;
+ case CPUINFO_STR_REGISTER + ARM7_R0: sprintf(info->s, "R0 :%08x", ARM7REG( 0)); break;
+ case CPUINFO_STR_REGISTER + ARM7_R1: sprintf(info->s, "R1 :%08x", ARM7REG( 1)); break;
+ case CPUINFO_STR_REGISTER + ARM7_R2: sprintf(info->s, "R2 :%08x", ARM7REG( 2)); break;
+ case CPUINFO_STR_REGISTER + ARM7_R3: sprintf(info->s, "R3 :%08x", ARM7REG( 3)); break;
+ case CPUINFO_STR_REGISTER + ARM7_R4: sprintf(info->s, "R4 :%08x", ARM7REG( 4)); break;
+ case CPUINFO_STR_REGISTER + ARM7_R5: sprintf(info->s, "R5 :%08x", ARM7REG( 5)); break;
+ case CPUINFO_STR_REGISTER + ARM7_R6: sprintf(info->s, "R6 :%08x", ARM7REG( 6)); break;
+ case CPUINFO_STR_REGISTER + ARM7_R7: sprintf(info->s, "R7 :%08x", ARM7REG( 7)); break;
+ case CPUINFO_STR_REGISTER + ARM7_R8: sprintf(info->s, "R8 :%08x", ARM7REG( 8)); break;
+ case CPUINFO_STR_REGISTER + ARM7_R9: sprintf(info->s, "R9 :%08x", ARM7REG( 9)); break;
+ case CPUINFO_STR_REGISTER + ARM7_R10: sprintf(info->s, "R10 :%08x", ARM7REG(10)); break;
+ case CPUINFO_STR_REGISTER + ARM7_R11: sprintf(info->s, "R11 :%08x", ARM7REG(11)); break;
+ case CPUINFO_STR_REGISTER + ARM7_R12: sprintf(info->s, "R12 :%08x", ARM7REG(12)); break;
+ case CPUINFO_STR_REGISTER + ARM7_R13: sprintf(info->s, "R13 :%08x", ARM7REG(13)); break;
+ case CPUINFO_STR_REGISTER + ARM7_R14: sprintf(info->s, "R14 :%08x", ARM7REG(14)); break;
+ case CPUINFO_STR_REGISTER + ARM7_R15: sprintf(info->s, "R15 :%08x", ARM7REG(15)); break;
+
+ /* FIRQ Mode Shadowed Registers */
+ case CPUINFO_STR_REGISTER + ARM7_FR8: sprintf(info->s, "FR8 :%08x", ARM7REG(eR8_FIQ) ); break;
+ case CPUINFO_STR_REGISTER + ARM7_FR9: sprintf(info->s, "FR9 :%08x", ARM7REG(eR9_FIQ) ); break;
+ case CPUINFO_STR_REGISTER + ARM7_FR10: sprintf(info->s, "FR10:%08x", ARM7REG(eR10_FIQ) ); break;
+ case CPUINFO_STR_REGISTER + ARM7_FR11: sprintf(info->s, "FR11:%08x", ARM7REG(eR11_FIQ) ); break;
+ case CPUINFO_STR_REGISTER + ARM7_FR12: sprintf(info->s, "FR12:%08x", ARM7REG(eR12_FIQ) ); break;
+ case CPUINFO_STR_REGISTER + ARM7_FR13: sprintf(info->s, "FR13:%08x", ARM7REG(eR13_FIQ) ); break;
+ case CPUINFO_STR_REGISTER + ARM7_FR14: sprintf(info->s, "FR14:%08x", ARM7REG(eR14_FIQ) ); break;
+ case CPUINFO_STR_REGISTER + ARM7_FSPSR: sprintf(info->s, "FR16:%08x", ARM7REG(eSPSR_FIQ)); break;
+
+ /* IRQ Mode Shadowed Registers */
+ case CPUINFO_STR_REGISTER + ARM7_IR13: sprintf(info->s, "IR13:%08x", ARM7REG(eR13_IRQ) ); break;
+ case CPUINFO_STR_REGISTER + ARM7_IR14: sprintf(info->s, "IR14:%08x", ARM7REG(eR14_IRQ) ); break;
+ case CPUINFO_STR_REGISTER + ARM7_ISPSR: sprintf(info->s, "IR16:%08x", ARM7REG(eSPSR_IRQ)); break;
+
+ /* Supervisor Mode Shadowed Registers */
+ case CPUINFO_STR_REGISTER + ARM7_SR13: sprintf(info->s, "SR13:%08x", ARM7REG(eR13_SVC) ); break;
+ case CPUINFO_STR_REGISTER + ARM7_SR14: sprintf(info->s, "SR14:%08x", ARM7REG(eR14_SVC) ); break;
+ case CPUINFO_STR_REGISTER + ARM7_SSPSR: sprintf(info->s, "SR16:%08x", ARM7REG(eSPSR_SVC)); break;
+
+ /* Abort Mode Shadowed Registers */
+ case CPUINFO_STR_REGISTER + ARM7_AR13: sprintf(info->s, "AR13:%08x", ARM7REG(eR13_ABT) ); break;
+ case CPUINFO_STR_REGISTER + ARM7_AR14: sprintf(info->s, "AR14:%08x", ARM7REG(eR14_ABT) ); break;
+ case CPUINFO_STR_REGISTER + ARM7_ASPSR: sprintf(info->s, "AR16:%08x", ARM7REG(eSPSR_ABT)); break;
+
+ /* Undefined Mode Shadowed Registers */
+ case CPUINFO_STR_REGISTER + ARM7_UR13: sprintf(info->s, "UR13:%08x", ARM7REG(eR13_UND) ); break;
+ case CPUINFO_STR_REGISTER + ARM7_UR14: sprintf(info->s, "UR14:%08x", ARM7REG(eR14_UND) ); break;
+ case CPUINFO_STR_REGISTER + ARM7_USPSR: sprintf(info->s, "UR16:%08x", ARM7REG(eSPSR_UND)); break;
+ }
+}
+
+
+CPU_GET_INFO( arm7_be )
+{
+ switch (state)
+ {
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(arm7_be); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(arm7_be); break;
+ case DEVINFO_STR_NAME: strcpy(info->s, "ARM7 (big endian)"); break;
+ default: CPU_GET_INFO_CALL(arm7);
+ }
+}
+
+CPU_GET_INFO( arm7500 )
+{
+ switch (state)
+ {
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(arm7500); break;
+ case DEVINFO_STR_NAME: strcpy(info->s, "ARM7500"); break;
+ default: CPU_GET_INFO_CALL(arm7);
+ break;
+ }
+}
+
+CPU_GET_INFO( arm9 )
+{
+ switch (state)
+ {
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(arm9); break;
+ case DEVINFO_STR_NAME: strcpy(info->s, "ARM9"); break;
+ default: CPU_GET_INFO_CALL(arm7);
+ break;
+ }
+}
+
+CPU_GET_INFO( arm920t )
+{
+ switch (state)
+ {
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(arm920t); break;
+ case DEVINFO_STR_NAME: strcpy(info->s, "ARM920T"); break;
+ default: CPU_GET_INFO_CALL(arm7);
+ break;
+ }
+}
+
+CPU_GET_INFO( pxa255 )
+{
+ switch (state)
+ {
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(pxa255); break;
+ case DEVINFO_STR_NAME: strcpy(info->s, "PXA255"); break;
+ default: CPU_GET_INFO_CALL(arm7);
+ break;
+ }
+}
+
+CPU_GET_INFO( sa1110 )
+{
+ switch (state)
+ {
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(sa1110); break;
+ case DEVINFO_STR_NAME: strcpy(info->s, "SA1110"); break;
+ default: CPU_GET_INFO_CALL(arm7);
+ break;
+ }
+}
+
+/* ARM system coprocessor support */
+
+static WRITE32_DEVICE_HANDLER( arm7_do_callback )
+{
+}
+
+static READ32_DEVICE_HANDLER( arm7_rt_r_callback )
+{
+ arm_state *cpustate = get_safe_token(device);
+ UINT32 opcode = offset;
+ UINT8 cReg = ( opcode & INSN_COPRO_CREG ) >> INSN_COPRO_CREG_SHIFT;
+ UINT8 op2 = ( opcode & INSN_COPRO_OP2 ) >> INSN_COPRO_OP2_SHIFT;
+// UINT8 op3 = opcode & INSN_COPRO_OP3;
+ UINT8 cpnum = (opcode & INSN_COPRO_CPNUM) >> INSN_COPRO_CPNUM_SHIFT;
+ UINT32 data = 0;
+
+// printf("cpnum %d cReg %d op2 %d op3 %d (%x)\n", cpnum, cReg, op2, op3, GET_REGISTER(cpustate, 15));
+
+ // we only handle system copro here
+ if (cpnum != 15)
+ {
+ if (cpustate->archFlags & eARM_ARCHFLAGS_XSCALE)
+ {
+ // handle XScale specific CP14
+ if (cpnum == 14)
+ {
+ switch( cReg )
+ {
+ case 1: // clock counter
+ data = (UINT32)cpustate->device->total_cycles();
+ break;
+
+ default:
+ break;
+ }
+ }
+ else
+ {
+ fatalerror("XScale: Unhandled coprocessor %d (archFlags %x)\n", cpnum, cpustate->archFlags);
+ }
+
+ return data;
+ }
+ else
+ {
+ LOG( ("ARM7: Unhandled coprocessor %d (archFlags %x)\n", cpnum, cpustate->archFlags) );
+ cpustate->pendingUnd = 1;
+ return 0;
+ }
+ }
+
+ switch( cReg )
+ {
+ case 4:
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ // RESERVED
+ LOG( ( "arm7_rt_r_callback CR%d, RESERVED\n", cReg ) );
+ break;
+ case 0: // ID
+ switch(op2)
+ {
+ case 0:
+ switch (cpustate->archRev)
+ {
+ case 3: // ARM6 32-bit
+ data = 0x41;
+ break;
+
+ case 4: // ARM7/SA11xx
+ if (cpustate->archFlags & eARM_ARCHFLAGS_SA)
+ {
+ // ARM Architecture Version 4
+ // Part Number 0xB11 (SA1110)
+ // Stepping B5
+ data = 0x69 | ( 0x01 << 16 ) | ( 0xB11 << 4 ) | 0x9;
+ }
+ else
+ {
+ data = 0x41 | (1 << 23) | (7 << 12);
+ //data = (0x41 << 24) | (1 << 20) | (2 << 16) | (0x920 << 4) | (0 << 0); // ARM920T (S3C24xx)
+ //data = (0x41 << 24) | (0 << 20) | (1 << 16) | (0x710 << 4) | (0 << 0); // ARM7500
+ }
+ break;
+
+ case 5: // ARM9/10/XScale
+ data = 0x41 | (9 << 12);
+ if (cpustate->archFlags & eARM_ARCHFLAGS_T)
+ {
+ if (cpustate->archFlags & eARM_ARCHFLAGS_E)
+ {
+ if (cpustate->archFlags & eARM_ARCHFLAGS_J)
+ {
+ data |= (6<<16); // v5TEJ
+ }
+ else
+ {
+ data |= (5<<16); // v5TE
+ }
+ }
+ else
+ {
+ data |= (4<<16); // v5T
+ }
+ }
+ break;
+
+ case 6: // ARM11
+ data = 0x41 | (10<< 12) | (7<<16); // v6
+ break;
+ }
+ break;
+ case 1: // cache type
+ data = 0x0f0d2112; // HACK: value expected by ARMWrestler (probably Nintendo DS ARM9's value)
+ //data = (6 << 25) | (1 << 24) | (0x172 << 12) | (0x172 << 0); // ARM920T (S3C24xx)
+ break;
+ case 2: // TCM type
+ data = 0;
+ break;
+ case 3: // TLB type
+ data = 0;
+ break;
+ case 4: // MPU type
+ data = 0;
+ break;
+ }
+ LOG( ( "arm7_rt_r_callback, ID\n" ) );
+ break;
+ case 1: // Control
+ data = COPRO_CTRL | 0x70; // bits 4-6 always read back as "1" (bit 3 too in XScale)
+ break;
+ case 2: // Translation Table Base
+ data = COPRO_TLB_BASE;
+ break;
+ case 3: // Domain Access Control
+ LOG( ( "arm7_rt_r_callback, Domain Access Control\n" ) );
+ data = COPRO_DOMAIN_ACCESS_CONTROL;
+ break;
+ case 5: // Fault Status
+ LOG( ( "arm7_rt_r_callback, Fault Status\n" ) );
+ data = COPRO_FAULT_STATUS;
+ break;
+ case 6: // Fault Address
+ LOG( ( "arm7_rt_r_callback, Fault Address\n" ) );
+ data = COPRO_FAULT_ADDRESS;
+ break;
+ case 13: // Read Process ID (PID)
+ LOG( ( "arm7_rt_r_callback, Read PID\n" ) );
+ data = COPRO_FCSE_PID;
+ break;
+ case 14: // Read Breakpoint
+ LOG( ( "arm7_rt_r_callback, Read Breakpoint\n" ) );
+ break;
+ case 15: // Test, Clock, Idle
+ LOG( ( "arm7_rt_r_callback, Test / Clock / Idle \n" ) );
+ break;
+ }
+
+ op2 = 0;
+// op3 = 0;
+
+ return data;
+}
+
+static WRITE32_DEVICE_HANDLER( arm7_rt_w_callback )
+{
+ arm_state *cpustate = get_safe_token(device);
+ UINT32 opcode = offset;
+ UINT8 cReg = ( opcode & INSN_COPRO_CREG ) >> INSN_COPRO_CREG_SHIFT;
+ UINT8 op2 = ( opcode & INSN_COPRO_OP2 ) >> INSN_COPRO_OP2_SHIFT;
+ UINT8 op3 = opcode & INSN_COPRO_OP3;
+ UINT8 cpnum = (opcode & INSN_COPRO_CPNUM) >> INSN_COPRO_CPNUM_SHIFT;
+
+ // handle XScale specific CP14 - just eat writes for now
+ if (cpnum != 15)
+ {
+ if (cpnum == 14)
+ {
+ LOG( ("arm7_rt_w_callback: write %x to XScale CP14 reg %d\n", data, cReg) );
+ return;
+ }
+ else
+ {
+ fatalerror("ARM7: Unhandled coprocessor %d\n", cpnum);
+ }
+ }
+
+ switch( cReg )
+ {
+ case 0:
+ case 4:
+ case 10:
+ case 11:
+ case 12:
+ // RESERVED
+ LOG( ( "arm7_rt_w_callback CR%d, RESERVED = %08x\n", cReg, data) );
+ break;
+ case 1: // Control
+ LOG( ( "arm7_rt_w_callback Control = %08x (%d) (%d)\n", data, op2, op3 ) );
+ LOG( ( " MMU:%d, Address Fault:%d, Data Cache:%d, Write Buffer:%d\n",
+ data & COPRO_CTRL_MMU_EN, ( data & COPRO_CTRL_ADDRFAULT_EN ) >> COPRO_CTRL_ADDRFAULT_EN_SHIFT,
+ ( data & COPRO_CTRL_DCACHE_EN ) >> COPRO_CTRL_DCACHE_EN_SHIFT,
+ ( data & COPRO_CTRL_WRITEBUF_EN ) >> COPRO_CTRL_WRITEBUF_EN_SHIFT ) );
+ LOG( ( " Endianness:%d, System:%d, ROM:%d, Instruction Cache:%d\n",
+ ( data & COPRO_CTRL_ENDIAN ) >> COPRO_CTRL_ENDIAN_SHIFT,
+ ( data & COPRO_CTRL_SYSTEM ) >> COPRO_CTRL_SYSTEM_SHIFT,
+ ( data & COPRO_CTRL_ROM ) >> COPRO_CTRL_ROM_SHIFT,
+ ( data & COPRO_CTRL_ICACHE_EN ) >> COPRO_CTRL_ICACHE_EN_SHIFT ) );
+ LOG( ( " Int Vector Adjust:%d\n", ( data & COPRO_CTRL_INTVEC_ADJUST ) >> COPRO_CTRL_INTVEC_ADJUST_SHIFT ) );
+#if ARM7_MMU_ENABLE_HACK
+ if (((data & COPRO_CTRL_MMU_EN) != 0) && ((COPRO_CTRL & COPRO_CTRL_MMU_EN) == 0))
+ {
+ cpustate->mmu_enable_addr = R15;
+ }
+ if (((data & COPRO_CTRL_MMU_EN) == 0) && ((COPRO_CTRL & COPRO_CTRL_MMU_EN) != 0))
+ {
+ R15 = arm7_tlb_translate( cpustate, R15, ARM7_TLB_NO_ABORT);
+ }
+#endif
+ COPRO_CTRL = data & COPRO_CTRL_MASK;
+ break;
+ case 2: // Translation Table Base
+ LOG( ( "arm7_rt_w_callback TLB Base = %08x (%d) (%d)\n", data, op2, op3 ) );
+ COPRO_TLB_BASE = data;
+ break;
+ case 3: // Domain Access Control
+ LOG( ( "arm7_rt_w_callback Domain Access Control = %08x (%d) (%d)\n", data, op2, op3 ) );
+ COPRO_DOMAIN_ACCESS_CONTROL = data;
+ break;
+ case 5: // Fault Status
+ LOG( ( "arm7_rt_w_callback Fault Status = %08x (%d) (%d)\n", data, op2, op3 ) );
+ COPRO_FAULT_STATUS = data;
+ break;
+ case 6: // Fault Address
+ LOG( ( "arm7_rt_w_callback Fault Address = %08x (%d) (%d)\n", data, op2, op3 ) );
+ COPRO_FAULT_ADDRESS = data;
+ break;
+ case 7: // Cache Operations
+// LOG( ( "arm7_rt_w_callback Cache Ops = %08x (%d) (%d)\n", data, op2, op3 ) );
+ break;
+ case 8: // TLB Operations
+ LOG( ( "arm7_rt_w_callback TLB Ops = %08x (%d) (%d)\n", data, op2, op3 ) );
+ break;
+ case 9: // Read Buffer Operations
+ LOG( ( "arm7_rt_w_callback Read Buffer Ops = %08x (%d) (%d)\n", data, op2, op3 ) );
+ break;
+ case 13: // Write Process ID (PID)
+ LOG( ( "arm7_rt_w_callback Write PID = %08x (%d) (%d)\n", data, op2, op3 ) );
+ COPRO_FCSE_PID = data;
+ break;
+ case 14: // Write Breakpoint
+ LOG( ( "arm7_rt_w_callback Write Breakpoint = %08x (%d) (%d)\n", data, op2, op3 ) );
+ break;
+ case 15: // Test, Clock, Idle
+ LOG( ( "arm7_rt_w_callback Test / Clock / Idle = %08x (%d) (%d)\n", data, op2, op3 ) );
+ break;
+ }
+ op2 = 0;
+ op3 = 0;
+}
+
+void arm7_dt_r_callback(arm_state *cpustate, UINT32 insn, UINT32 *prn, UINT32 (*read32)(arm_state *cpustate, UINT32 addr))
+{
+}
+
+void arm7_dt_w_callback(arm_state *cpustate, UINT32 insn, UINT32 *prn, void (*write32)(arm_state *cpustate, UINT32 addr, UINT32 data))
+{
+}
+
+DEFINE_LEGACY_CPU_DEVICE(ARM7, arm7);
+DEFINE_LEGACY_CPU_DEVICE(ARM7_BE, arm7_be);
+DEFINE_LEGACY_CPU_DEVICE(ARM7500, arm7500);
+DEFINE_LEGACY_CPU_DEVICE(ARM9, arm9);
+DEFINE_LEGACY_CPU_DEVICE(ARM920T, arm920t);
+DEFINE_LEGACY_CPU_DEVICE(PXA255, pxa255);
+DEFINE_LEGACY_CPU_DEVICE(SA1110, sa1110);
diff --git a/trunk/src/emu/cpu/arm7/arm7.h b/trunk/src/emu/cpu/arm7/arm7.h
new file mode 100644
index 00000000000..c1d7cc11a12
--- /dev/null
+++ b/trunk/src/emu/cpu/arm7/arm7.h
@@ -0,0 +1,49 @@
+/*****************************************************************************
+ *
+ * arm7.h
+ * Portable ARM7TDMI CPU Emulator
+ *
+ * Copyright Steve Ellenoff, all rights reserved.
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * sellenoff@hotmail.com
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ * This work is based on:
+ * #1) 'Atmel Corporation ARM7TDMI (Thumb) Datasheet - January 1999'
+ * #2) Arm 2/3/6 emulator By Bryan McPhail (bmcphail@tendril.co.uk) and Phil Stroffolino (MAME CORE 0.76)
+ *
+ *****************************************************************************
+
+ This file contains everything related to the arm7 cpu specific implementation.
+ Anything related to the arm7 core itself is defined in arm7core.h instead.
+
+ ******************************************************************************/
+
+#pragma once
+
+#ifndef __ARM7_H__
+#define __ARM7_H__
+
+
+/****************************************************************************************************
+ * PUBLIC FUNCTIONS
+ ***************************************************************************************************/
+
+DECLARE_LEGACY_CPU_DEVICE(ARM7, arm7);
+DECLARE_LEGACY_CPU_DEVICE(ARM7_BE, arm7_be);
+DECLARE_LEGACY_CPU_DEVICE(ARM7500, arm7500);
+DECLARE_LEGACY_CPU_DEVICE(ARM9, arm9);
+DECLARE_LEGACY_CPU_DEVICE(ARM920T, arm920t);
+DECLARE_LEGACY_CPU_DEVICE(PXA255, pxa255);
+DECLARE_LEGACY_CPU_DEVICE(SA1110, sa1110);
+
+#endif /* __ARM7_H__ */
diff --git a/trunk/src/emu/cpu/arm7/arm7core.c b/trunk/src/emu/cpu/arm7/arm7core.c
new file mode 100644
index 00000000000..b07de65ce33
--- /dev/null
+++ b/trunk/src/emu/cpu/arm7/arm7core.c
@@ -0,0 +1,2015 @@
+/*****************************************************************************
+ *
+ * arm7core.c
+ * Portable ARM7TDMI Core Emulator
+ *
+ * Copyright Steve Ellenoff, all rights reserved.
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * sellenoff@hotmail.com
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ * This work is based on:
+ * #1) 'Atmel Corporation ARM7TDMI (Thumb) Datasheet - January 1999'
+ * #2) Arm 2/3/6 emulator By Bryan McPhail (bmcphail@tendril.co.uk) and Phil Stroffolino (MAME CORE 0.76)
+ * #3) Thumb support by Ryan Holtz
+ * #4) Additional Thumb support and bugfixes by R. Belmont
+ *
+ *****************************************************************************/
+
+/******************************************************************************
+ * Notes:
+
+ **This core comes from my AT91 cpu core contributed to PinMAME,
+ but with all the AT91 specific junk removed,
+ which leaves just the ARM7TDMI core itself. I further removed the CPU specific MAME stuff
+ so you just have the actual ARM7 core itself, since many cpu's incorporate an ARM7 core, but add on
+ many cpu specific functionality.
+
+ Therefore, to use the core, you simpy include this file along with the .h file into your own cpu specific
+ implementation, and therefore, this file shouldn't be compiled as part of your project directly.
+ Additionally, you will need to include arm7exec.c in your cpu's execute routine.
+
+ For better or for worse, the code itself is very much intact from it's arm 2/3/6 origins from
+ Bryan & Phil's work. I contemplated merging it in, but thought the fact that the CPSR is
+ no longer part of the PC was enough of a change to make it annoying to merge.
+ **
+
+ Coprocessor functions are heavily implementation specific, so callback handlers are used to allow the
+ implementation to handle the functionality. Custom DASM handlers are included as well to allow the DASM
+ output to be tailored to the co-proc implementation details.
+
+ Todo:
+ 26 bit compatibility mode not implemented.
+ Data Processing opcodes need cycle count adjustments (see page 194 of ARM7TDMI manual for instruction timing summary)
+ Multi-emulated cpu support untested, but probably will not work too well, as no effort was made to code for more than 1.
+ Could not find info on what the TEQP opcode is from page 44..
+ I have no idea if user bank switching is right, as I don't fully understand it's use.
+ Search for Todo: tags for remaining items not done.
+
+
+ Differences from Arm 2/3 (6 also?)
+ -Thumb instruction support
+ -Full 32 bit address support
+ -PC no longer contains CPSR information, CPSR is own register now
+ -New register SPSR to store previous contents of CPSR (this register is banked in many modes)
+ -New opcodes for CPSR transfer, Long Multiplication, Co-Processor support, and some others
+ -User Bank Mode transfer using certain flags which were previously unallowed (LDM/STM with S Bit & R15)
+ -New operation modes? (unconfirmed)
+
+ Based heavily on arm core from MAME 0.76:
+ *****************************************
+ ARM 2/3/6 Emulation
+
+ Todo:
+ Software interrupts unverified (nothing uses them so far, but they should be ok)
+ Timing - Currently very approximated, nothing relies on proper timing so far.
+ IRQ timing not yet correct (again, nothing is affected by this so far).
+
+ By Bryan McPhail (bmcphail@tendril.co.uk) and Phil Stroffolino
+*****************************************************************************/
+
+#define ARM7_DEBUG_CORE 0
+
+/* Prototypes */
+
+// SJE: should these be inline? or are they too big to see any benefit?
+
+static void HandleCoProcDO(arm_state *cpustate, UINT32 insn);
+static void HandleCoProcRT(arm_state *cpustate, UINT32 insn);
+static void HandleCoProcDT(arm_state *cpustate, UINT32 insn);
+static void HandleHalfWordDT(arm_state *cpustate, UINT32 insn);
+static void HandleSwap(arm_state *cpustate, UINT32 insn);
+static void HandlePSRTransfer(arm_state *cpustate, UINT32 insn);
+static void HandleALU(arm_state *cpustate, UINT32 insn);
+static void HandleMul(arm_state *cpustate, UINT32 insn);
+static void HandleUMulLong(arm_state *cpustate, UINT32 insn);
+static void HandleSMulLong(arm_state *cpustate, UINT32 insn);
+INLINE void HandleBranch(arm_state *cpustate, UINT32 insn); // pretty short, so inline should be ok
+static void HandleMemSingle(arm_state *cpustate, UINT32 insn);
+static void HandleMemBlock(arm_state *cpustate, UINT32 insn);
+static UINT32 decodeShift(arm_state *cpustate, UINT32 insn, UINT32 *pCarry);
+INLINE void SwitchMode(arm_state *cpustate, int);
+static void arm7_check_irq_state(arm_state *cpustate);
+
+INLINE void arm7_cpu_write32(arm_state *cpustate, UINT32 addr, UINT32 data);
+INLINE void arm7_cpu_write16(arm_state *cpustate, UINT32 addr, UINT16 data);
+INLINE void arm7_cpu_write8(arm_state *cpustate, UINT32 addr, UINT8 data);
+INLINE UINT32 arm7_cpu_read32(arm_state *cpustate, UINT32 addr);
+INLINE UINT16 arm7_cpu_read16(arm_state *cpustate, UINT32 addr);
+INLINE UINT8 arm7_cpu_read8(arm_state *cpustate, offs_t addr);
+
+/* Static Vars */
+// Note: for multi-cpu implementation, this approach won't work w/o modification
+write32_device_func arm7_coproc_do_callback; // holder for the co processor Data Operations Callback func.
+read32_device_func arm7_coproc_rt_r_callback; // holder for the co processor Register Transfer Read Callback func.
+write32_device_func arm7_coproc_rt_w_callback; // holder for the co processor Register Transfer Write Callback Callback func.
+// holder for the co processor Data Transfer Read & Write Callback funcs
+void (*arm7_coproc_dt_r_callback)(arm_state *cpustate, UINT32 insn, UINT32 *prn, UINT32 (*read32)(arm_state *cpustate, UINT32 addr));
+void (*arm7_coproc_dt_w_callback)(arm_state *cpustate, UINT32 insn, UINT32 *prn, void (*write32)(arm_state *cpustate, UINT32 addr, UINT32 data));
+
+#ifdef UNUSED_DEFINITION
+// custom dasm callback handlers for co-processor instructions
+char *(*arm7_dasm_cop_dt_callback)(arm_state *cpustate, char *pBuf, UINT32 opcode, char *pConditionCode, char *pBuf0);
+char *(*arm7_dasm_cop_rt_callback)(arm_state *cpustate, char *pBuf, UINT32 opcode, char *pConditionCode, char *pBuf0);
+char *(*arm7_dasm_cop_do_callback)(arm_state *cpustate, char *pBuf, UINT32 opcode, char *pConditionCode, char *pBuf0);
+#endif
+
+
+/***************************************************************************
+ * Default Memory Handlers
+ ***************************************************************************/
+INLINE void arm7_cpu_write32(arm_state *cpustate, UINT32 addr, UINT32 data)
+{
+ if( COPRO_CTRL & COPRO_CTRL_MMU_EN )
+ {
+ addr = arm7_tlb_translate( cpustate, addr, ARM7_TLB_ABORT_D );
+ }
+
+ addr &= ~3;
+ if ( cpustate->endian == ENDIANNESS_BIG )
+ cpustate->program->write_dword(addr, data);
+ else
+ cpustate->program->write_dword(addr, data);
+}
+
+
+INLINE void arm7_cpu_write16(arm_state *cpustate, UINT32 addr, UINT16 data)
+{
+ if( COPRO_CTRL & COPRO_CTRL_MMU_EN )
+ {
+ addr = arm7_tlb_translate( cpustate, addr, ARM7_TLB_ABORT_D );
+ }
+
+ addr &= ~1;
+ if ( cpustate->endian == ENDIANNESS_BIG )
+ cpustate->program->write_word(addr, data);
+ else
+ cpustate->program->write_word(addr, data);
+}
+
+INLINE void arm7_cpu_write8(arm_state *cpustate, UINT32 addr, UINT8 data)
+{
+ if( COPRO_CTRL & COPRO_CTRL_MMU_EN )
+ {
+ addr = arm7_tlb_translate( cpustate, addr, ARM7_TLB_ABORT_D );
+ }
+
+ if ( cpustate->endian == ENDIANNESS_BIG )
+ cpustate->program->write_byte(addr, data);
+ else
+ cpustate->program->write_byte(addr, data);
+}
+
+INLINE UINT32 arm7_cpu_read32(arm_state *cpustate, offs_t addr)
+{
+ UINT32 result;
+
+ if( COPRO_CTRL & COPRO_CTRL_MMU_EN )
+ {
+ addr = arm7_tlb_translate( cpustate, addr, ARM7_TLB_ABORT_D );
+ }
+
+ if (addr & 3)
+ {
+ if ( cpustate->endian == ENDIANNESS_BIG )
+ result = cpustate->program->read_dword(addr & ~3);
+ else
+ result = cpustate->program->read_dword(addr & ~3);
+ result = (result >> (8 * (addr & 3))) | (result << (32 - (8 * (addr & 3))));
+ }
+ else
+ {
+ if ( cpustate->endian == ENDIANNESS_BIG )
+ result = cpustate->program->read_dword(addr);
+ else
+ result = cpustate->program->read_dword(addr);
+ }
+
+ return result;
+}
+
+INLINE UINT16 arm7_cpu_read16(arm_state *cpustate, offs_t addr)
+{
+ UINT16 result;
+
+ if( COPRO_CTRL & COPRO_CTRL_MMU_EN )
+ {
+ addr = arm7_tlb_translate( cpustate, addr, ARM7_TLB_ABORT_D );
+ }
+
+ if ( cpustate->endian == ENDIANNESS_BIG )
+ result = cpustate->program->read_word(addr & ~1);
+ else
+ result = cpustate->program->read_word(addr & ~1);
+
+ if (addr & 1)
+ {
+ result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
+ }
+
+ return result;
+}
+
+INLINE UINT8 arm7_cpu_read8(arm_state *cpustate, offs_t addr)
+{
+ if( COPRO_CTRL & COPRO_CTRL_MMU_EN )
+ {
+ addr = arm7_tlb_translate( cpustate, addr, ARM7_TLB_ABORT_D );
+ }
+
+ // Handle through normal 8 bit handler (for 32 bit cpu)
+ if ( cpustate->endian == ENDIANNESS_BIG )
+ return cpustate->program->read_byte(addr);
+ else
+ return cpustate->program->read_byte(addr);
+}
+
+/***************
+ * helper funcs
+ ***************/
+
+// TODO LD:
+// - SIGN_BITS_DIFFER = THUMB_SIGN_BITS_DIFFER
+// - do while (0)
+// - HandleALUAddFlags = HandleThumbALUAddFlags except for PC incr
+// - HandleALUSubFlags = HandleThumbALUSubFlags except for PC incr
+
+#define IsNeg(i) ((i) >> 31)
+#define IsPos(i) ((~(i)) >> 31)
+
+/* Set NZCV flags for ADDS / SUBS */
+#define HandleALUAddFlags(rd, rn, op2) \
+ if (insn & INSN_S) \
+ SET_CPSR(((GET_CPSR & ~(N_MASK | Z_MASK | V_MASK | C_MASK)) \
+ | (((!SIGN_BITS_DIFFER(rn, op2)) && SIGN_BITS_DIFFER(rn, rd)) << V_BIT) \
+ | (((IsNeg(rn) & IsNeg(op2)) | (IsNeg(rn) & IsPos(rd)) | (IsNeg(op2) & IsPos(rd))) ? C_MASK : 0) \
+ | HandleALUNZFlags(rd))); \
+ R15 += 4;
+
+#define HandleThumbALUAddFlags(rd, rn, op2) \
+ SET_CPSR(((GET_CPSR & ~(N_MASK | Z_MASK | V_MASK | C_MASK)) \
+ | (((!THUMB_SIGN_BITS_DIFFER(rn, op2)) && THUMB_SIGN_BITS_DIFFER(rn, rd)) << V_BIT) \
+ | (((~(rn)) < (op2)) << C_BIT) \
+ | HandleALUNZFlags(rd))); \
+ R15 += 2;
+
+#define HandleALUSubFlags(rd, rn, op2) \
+ if (insn & INSN_S) \
+ SET_CPSR(((GET_CPSR & ~(N_MASK | Z_MASK | V_MASK | C_MASK)) \
+ | ((SIGN_BITS_DIFFER(rn, op2) && SIGN_BITS_DIFFER(rn, rd)) << V_BIT) \
+ | (((IsNeg(rn) & IsPos(op2)) | (IsNeg(rn) & IsPos(rd)) | (IsPos(op2) & IsPos(rd))) ? C_MASK : 0) \
+ | HandleALUNZFlags(rd))); \
+ R15 += 4;
+
+#define HandleThumbALUSubFlags(rd, rn, op2) \
+ SET_CPSR(((GET_CPSR & ~(N_MASK | Z_MASK | V_MASK | C_MASK)) \
+ | ((THUMB_SIGN_BITS_DIFFER(rn, op2) && THUMB_SIGN_BITS_DIFFER(rn, rd)) << V_BIT) \
+ | (((IsNeg(rn) & IsPos(op2)) | (IsNeg(rn) & IsPos(rd)) | (IsPos(op2) & IsPos(rd))) ? C_MASK : 0) \
+ | HandleALUNZFlags(rd))); \
+ R15 += 2;
+
+/* Set NZC flags for logical operations. */
+
+// This macro (which I didn't write) - doesn't make it obvious that the SIGN BIT = 31, just as the N Bit does,
+// therefore, N is set by default
+#define HandleALUNZFlags(rd) \
+ (((rd) & SIGN_BIT) | ((!(rd)) << Z_BIT))
+
+
+// Long ALU Functions use bit 63
+#define HandleLongALUNZFlags(rd) \
+ ((((rd) & ((UINT64)1 << 63)) >> 32) | ((!(rd)) << Z_BIT))
+
+#define HandleALULogicalFlags(rd, sc) \
+ if (insn & INSN_S) \
+ SET_CPSR(((GET_CPSR & ~(N_MASK | Z_MASK | C_MASK)) \
+ | HandleALUNZFlags(rd) \
+ | (((sc) != 0) << C_BIT))); \
+ R15 += 4;
+
+// convert cpsr mode num into to text
+static const char modetext[ARM7_NUM_MODES][5] = {
+ "USER", "FIRQ", "IRQ", "SVC", "ILL1", "ILL2", "ILL3", "ABT",
+ "ILL4", "ILL5", "ILL6", "UND", "ILL7", "ILL8", "ILL9", "SYS"
+};
+static const char *GetModeText(int cpsr)
+{
+ return modetext[cpsr & MODE_FLAG];
+}
+
+// used to be functions, but no longer a need, so we'll use define for better speed.
+#define GetRegister(cpustate, rIndex) ARM7REG(sRegisterTable[GET_MODE][rIndex])
+#define SetRegister(cpustate, rIndex, value) ARM7REG(sRegisterTable[GET_MODE][rIndex]) = value
+
+// I could prob. convert to macro, but Switchmode shouldn't occur that often in emulated code..
+INLINE void SwitchMode(arm_state *cpustate, int cpsr_mode_val)
+{
+ UINT32 cspr = GET_CPSR & ~MODE_FLAG;
+ SET_CPSR(cspr | cpsr_mode_val);
+}
+
+
+/* Decodes an Op2-style shifted-register form. If @carry@ is non-zero the
+ * shifter carry output will manifest itself as @*carry == 0@ for carry clear
+ * and @*carry != 0@ for carry set.
+
+ SJE: Rules:
+ IF RC = 256, Result = no shift.
+ LSL 0 = Result = RM, Carry = Old Contents of CPSR C Bit
+ LSL(0,31) = Result shifted, least significant bit is in carry out
+ LSL 32 = Result of 0, Carry = Bit 0 of RM
+ LSL >32 = Result of 0, Carry out 0
+ LSR 0 = LSR 32 (see below)
+ LSR 32 = Result of 0, Carry = Bit 31 of RM
+ LSR >32 = Result of 0, Carry out 0
+ ASR >=32 = ENTIRE Result = bit 31 of RM
+ ROR 32 = Result = RM, Carry = Bit 31 of RM
+ ROR >32 = Same result as ROR n-32 until amount in range of 1-32 then follow rules
+*/
+
+static UINT32 decodeShift(arm_state *cpustate, UINT32 insn, UINT32 *pCarry)
+{
+ UINT32 k = (insn & INSN_OP2_SHIFT) >> INSN_OP2_SHIFT_SHIFT; // Bits 11-7
+ UINT32 rm = GET_REGISTER(cpustate, insn & INSN_OP2_RM);
+ UINT32 t = (insn & INSN_OP2_SHIFT_TYPE) >> INSN_OP2_SHIFT_TYPE_SHIFT;
+
+ if ((insn & INSN_OP2_RM) == 0xf) {
+ // "If a register is used to specify the shift amount the PC will be 12 bytes ahead." (instead of 8)
+ rm += t & 1 ? 12 : 8;
+ }
+
+ /* All shift types ending in 1 are Rk, not #k */
+ if (t & 1)
+ {
+// LOG(("%08x: RegShift %02x %02x\n", R15, k >> 1, GET_REGISTER(cpustate, k >> 1)));
+#if ARM7_DEBUG_CORE
+ if ((insn & 0x80) == 0x80)
+ LOG(("%08x: RegShift ERROR (p36)\n", R15));
+#endif
+
+ // see p35 for check on this
+ //k = GET_REGISTER(cpustate, k >> 1) & 0x1f;
+
+ // Keep only the bottom 8 bits for a Register Shift
+ k = GET_REGISTER(cpustate, k >> 1) & 0xff;
+
+ if (k == 0) /* Register shift by 0 is a no-op */
+ {
+// LOG(("%08x: NO-OP Regshift\n", R15));
+ /* TODO this is wrong for at least ROR by reg with lower
+ * 5 bits 0 but lower 8 bits non zero */
+ if (pCarry)
+ *pCarry = GET_CPSR & C_MASK;
+ return rm;
+ }
+ }
+ /* Decode the shift type and perform the shift */
+ switch (t >> 1)
+ {
+ case 0: /* LSL */
+ // LSL 32 = Result of 0, Carry = Bit 0 of RM
+ // LSL >32 = Result of 0, Carry out 0
+ if (k >= 32)
+ {
+ if (pCarry)
+ *pCarry = (k == 32) ? rm & 1 : 0;
+ return 0;
+ }
+ else
+ {
+ if (pCarry)
+ {
+ // LSL 0 = Result = RM, Carry = Old Contents of CPSR C Bit
+ // LSL (0,31) = Result shifted, least significant bit is in carry out
+ *pCarry = k ? (rm & (1 << (32 - k))) : (GET_CPSR & C_MASK);
+ }
+ return k ? LSL(rm, k) : rm;
+ }
+ break;
+
+ case 1: /* LSR */
+ if (k == 0 || k == 32)
+ {
+ if (pCarry)
+ *pCarry = rm & SIGN_BIT;
+ return 0;
+ }
+ else if (k > 32)
+ {
+ if (pCarry)
+ *pCarry = 0;
+ return 0;
+ }
+ else
+ {
+ if (pCarry)
+ *pCarry = (rm & (1 << (k - 1)));
+ return LSR(rm, k);
+ }
+ break;
+
+ case 2: /* ASR */
+ if (k == 0 || k > 32)
+ k = 32;
+
+ if (pCarry)
+ *pCarry = (rm & (1 << (k - 1)));
+ if (k >= 32)
+ return rm & SIGN_BIT ? 0xffffffffu : 0;
+ else
+ {
+ if (rm & SIGN_BIT)
+ return LSR(rm, k) | (0xffffffffu << (32 - k));
+ else
+ return LSR(rm, k);
+ }
+ break;
+
+ case 3: /* ROR and RRX */
+ if (k)
+ {
+ while (k > 32)
+ k -= 32;
+ if (pCarry)
+ *pCarry = rm & (1 << (k - 1));
+ return ROR(rm, k);
+ }
+ else
+ {
+ /* RRX */
+ if (pCarry)
+ *pCarry = (rm & 1);
+ return LSR(rm, 1) | ((GET_CPSR & C_MASK) << 2);
+ }
+ break;
+ }
+
+ LOG(("%08x: Decodeshift error\n", R15));
+ return 0;
+} /* decodeShift */
+
+
+static int loadInc(arm_state *cpustate, UINT32 pat, UINT32 rbv, UINT32 s)
+{
+ int i, result;
+ UINT32 data;
+
+ result = 0;
+ rbv &= ~3;
+ for (i = 0; i < 16; i++)
+ {
+ if ((pat >> i) & 1)
+ {
+ data = READ32(rbv += 4);
+ if (cpustate->pendingAbtD != 0) break;
+ if (i == 15) {
+ if (s) /* Pull full contents from stack */
+ SET_REGISTER(cpustate, 15, data);
+ else /* Pull only address, preserve mode & status flags */
+ if (MODE32)
+ SET_REGISTER(cpustate, 15, data);
+ else
+ {
+ SET_REGISTER(cpustate, 15, (GET_REGISTER(cpustate, 15) & ~0x03FFFFFC) | (data & 0x03FFFFFC));
+ }
+ } else
+ SET_REGISTER(cpustate, i, data);
+
+ result++;
+ }
+ }
+ return result;
+}
+
+static int loadDec(arm_state *cpustate, UINT32 pat, UINT32 rbv, UINT32 s)
+{
+ int i, result;
+ UINT32 data;
+
+ result = 0;
+ rbv &= ~3;
+ for (i = 15; i >= 0; i--)
+ {
+ if ((pat >> i) & 1)
+ {
+ data = READ32(rbv -= 4);
+ if (cpustate->pendingAbtD != 0) break;
+ if (i == 15) {
+ if (s) /* Pull full contents from stack */
+ SET_REGISTER(cpustate, 15, data);
+ else /* Pull only address, preserve mode & status flags */
+ if (MODE32)
+ SET_REGISTER(cpustate, 15, data);
+ else
+ {
+ SET_REGISTER(cpustate, 15, (GET_REGISTER(cpustate, 15) & ~0x03FFFFFC) | (data & 0x03FFFFFC));
+ }
+ }
+ else
+ SET_REGISTER(cpustate, i, data);
+ result++;
+ }
+ }
+ return result;
+}
+
+static int storeInc(arm_state *cpustate, UINT32 pat, UINT32 rbv)
+{
+ int i, result;
+
+ result = 0;
+ for (i = 0; i < 16; i++)
+ {
+ if ((pat >> i) & 1)
+ {
+#if ARM7_DEBUG_CORE
+ if (i == 15) /* R15 is plus 12 from address of STM */
+ LOG(("%08x: StoreInc on R15\n", R15));
+#endif
+ WRITE32(rbv += 4, GET_REGISTER(cpustate, i));
+ result++;
+ }
+ }
+ return result;
+} /* storeInc */
+
+static int storeDec(arm_state *cpustate, UINT32 pat, UINT32 rbv)
+{
+ int i, result;
+
+ result = 0;
+ for (i = 15; i >= 0; i--)
+ {
+ if ((pat >> i) & 1)
+ {
+#if ARM7_DEBUG_CORE
+ if (i == 15) /* R15 is plus 12 from address of STM */
+ LOG(("%08x: StoreDec on R15\n", R15));
+#endif
+ WRITE32(rbv -= 4, GET_REGISTER(cpustate, i));
+ result++;
+ }
+ }
+ return result;
+} /* storeDec */
+
+/***************************************************************************
+ * Main CPU Funcs
+ ***************************************************************************/
+
+// CPU INIT
+static void arm7_core_init(device_t *device, const char *cpuname)
+{
+ arm_state *cpustate = get_safe_token(device);
+
+ device->save_item(NAME(cpustate->sArmRegister));
+ device->save_item(NAME(cpustate->pendingIrq));
+ device->save_item(NAME(cpustate->pendingFiq));
+ device->save_item(NAME(cpustate->pendingAbtD));
+ device->save_item(NAME(cpustate->pendingAbtP));
+ device->save_item(NAME(cpustate->pendingUnd));
+ device->save_item(NAME(cpustate->pendingSwi));
+}
+
+// CPU RESET
+static void arm7_core_reset(legacy_cpu_device *device)
+{
+ arm_state *cpustate = get_safe_token(device);
+
+ device_irq_callback save_irqcallback = cpustate->irq_callback;
+
+ memset(cpustate, 0, sizeof(arm_state));
+ cpustate->irq_callback = save_irqcallback;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->endian = ENDIANNESS_LITTLE;
+ cpustate->direct = &cpustate->program->direct();
+
+ /* start up in SVC mode with interrupts disabled. */
+ ARM7REG(eCPSR) = I_MASK | F_MASK | 0x10;
+ SwitchMode(cpustate, eARM7_MODE_SVC);
+ R15 = 0;
+}
+
+// Execute used to be here.. moved to separate file (arm7exec.c) to be included by cpu cores separately
+
+// CPU CHECK IRQ STATE
+// Note: couldn't find any exact cycle counts for most of these exceptions
+static void arm7_check_irq_state(arm_state *cpustate)
+{
+ UINT32 cpsr = GET_CPSR; /* save current CPSR */
+ UINT32 pc = R15 + 4; /* save old pc (already incremented in pipeline) */;
+
+ /* Exception priorities:
+
+ Reset
+ Data abort
+ FIRQ
+ IRQ
+ Prefetch abort
+ Undefined instruction
+ Software Interrupt
+ */
+
+ // Data Abort
+ if (cpustate->pendingAbtD) {
+ if (MODE26) fatalerror( "pendingAbtD (todo)");
+ SwitchMode(cpustate, eARM7_MODE_ABT); /* Set ABT mode so PC is saved to correct R14 bank */
+ SET_REGISTER(cpustate, 14, pc - 8 + 8); /* save PC to R14 */
+ SET_REGISTER(cpustate, SPSR, cpsr); /* Save current CPSR */
+ SET_CPSR(GET_CPSR | I_MASK); /* Mask IRQ */
+ SET_CPSR(GET_CPSR & ~T_MASK);
+ R15 = 0x10; /* IRQ Vector address */
+ if ((COPRO_CTRL & COPRO_CTRL_MMU_EN) && (COPRO_CTRL & COPRO_CTRL_INTVEC_ADJUST)) R15 |= 0xFFFF0000;
+ cpustate->pendingAbtD = 0;
+ return;
+ }
+
+ // FIQ
+ if (cpustate->pendingFiq && (cpsr & F_MASK) == 0) {
+ if (MODE26) fatalerror( "pendingFiq (todo)");
+ SwitchMode(cpustate, eARM7_MODE_FIQ); /* Set FIQ mode so PC is saved to correct R14 bank */
+ SET_REGISTER(cpustate, 14, pc - 4 + 4); /* save PC to R14 */
+ SET_REGISTER(cpustate, SPSR, cpsr); /* Save current CPSR */
+ SET_CPSR(GET_CPSR | I_MASK | F_MASK); /* Mask both IRQ & FIQ */
+ SET_CPSR(GET_CPSR & ~T_MASK);
+ R15 = 0x1c; /* IRQ Vector address */
+ if ((COPRO_CTRL & COPRO_CTRL_MMU_EN) && (COPRO_CTRL & COPRO_CTRL_INTVEC_ADJUST)) R15 |= 0xFFFF0000;
+ return;
+ }
+
+ // IRQ
+ if (cpustate->pendingIrq && (cpsr & I_MASK) == 0) {
+ SwitchMode(cpustate, eARM7_MODE_IRQ); /* Set IRQ mode so PC is saved to correct R14 bank */
+ SET_REGISTER(cpustate, 14, pc - 4 + 4); /* save PC to R14 */
+ if (MODE32)
+ {
+ SET_REGISTER(cpustate, SPSR, cpsr); /* Save current CPSR */
+ SET_CPSR(GET_CPSR | I_MASK); /* Mask IRQ */
+ SET_CPSR(GET_CPSR & ~T_MASK);
+ R15 = 0x18; /* IRQ Vector address */
+ }
+ else
+ {
+ UINT32 temp;
+ R15 = (pc & 0xF4000000) /* N Z C V F */ | 0x18 | 0x00000002 /* IRQ */ | 0x08000000 /* I */;
+ temp = (GET_CPSR & 0x0FFFFF3F) /* N Z C V I F */ | (R15 & 0xF0000000) /* N Z C V */ | ((R15 & 0x0C000000) >> (26 - 6)) /* I F */;
+ SET_CPSR(temp); /* Mask IRQ */
+ }
+ if ((COPRO_CTRL & COPRO_CTRL_MMU_EN) && (COPRO_CTRL & COPRO_CTRL_INTVEC_ADJUST)) R15 |= 0xFFFF0000;
+ return;
+ }
+
+ // Prefetch Abort
+ if (cpustate->pendingAbtP) {
+ if (MODE26) fatalerror( "pendingAbtP (todo)");
+ SwitchMode(cpustate, eARM7_MODE_ABT); /* Set ABT mode so PC is saved to correct R14 bank */
+ SET_REGISTER(cpustate, 14, pc - 4 + 4); /* save PC to R14 */
+ SET_REGISTER(cpustate, SPSR, cpsr); /* Save current CPSR */
+ SET_CPSR(GET_CPSR | I_MASK); /* Mask IRQ */
+ SET_CPSR(GET_CPSR & ~T_MASK);
+ R15 = 0x0c; /* IRQ Vector address */
+ if ((COPRO_CTRL & COPRO_CTRL_MMU_EN) && (COPRO_CTRL & COPRO_CTRL_INTVEC_ADJUST)) R15 |= 0xFFFF0000;
+ cpustate->pendingAbtP = 0;
+ return;
+ }
+
+ // Undefined instruction
+ if (cpustate->pendingUnd) {
+ if (MODE26) fatalerror( "pendingUnd (todo)");
+ SwitchMode(cpustate, eARM7_MODE_UND); /* Set UND mode so PC is saved to correct R14 bank */
+ // compensate for prefetch (should this also be done for normal IRQ?)
+ if (T_IS_SET(GET_CPSR))
+ {
+ SET_REGISTER(cpustate, 14, pc - 4 + 2); /* save PC to R14 */
+ }
+ else
+ {
+ SET_REGISTER(cpustate, 14, pc - 4 + 4 - 4); /* save PC to R14 */
+ }
+ SET_REGISTER(cpustate, SPSR, cpsr); /* Save current CPSR */
+ SET_CPSR(GET_CPSR | I_MASK); /* Mask IRQ */
+ SET_CPSR(GET_CPSR & ~T_MASK);
+ R15 = 0x04; /* IRQ Vector address */
+ if ((COPRO_CTRL & COPRO_CTRL_MMU_EN) && (COPRO_CTRL & COPRO_CTRL_INTVEC_ADJUST)) R15 |= 0xFFFF0000;
+ cpustate->pendingUnd = 0;
+ return;
+ }
+
+ // Software Interrupt
+ if (cpustate->pendingSwi) {
+ SwitchMode(cpustate, eARM7_MODE_SVC); /* Set SVC mode so PC is saved to correct R14 bank */
+ // compensate for prefetch (should this also be done for normal IRQ?)
+ if (T_IS_SET(GET_CPSR))
+ {
+ SET_REGISTER(cpustate, 14, pc - 4 + 2); /* save PC to R14 */
+ }
+ else
+ {
+ SET_REGISTER(cpustate, 14, pc - 4 + 4); /* save PC to R14 */
+ }
+ if (MODE32)
+ {
+ SET_REGISTER(cpustate, SPSR, cpsr); /* Save current CPSR */
+ SET_CPSR(GET_CPSR | I_MASK); /* Mask IRQ */
+ SET_CPSR(GET_CPSR & ~T_MASK); /* Go to ARM mode */
+ R15 = 0x08; /* Jump to the SWI vector */
+ }
+ else
+ {
+ UINT32 temp;
+ R15 = (pc & 0xF4000000) /* N Z C V F */ | 0x08 | 0x00000003 /* SVC */ | 0x08000000 /* I */;
+ temp = (GET_CPSR & 0x0FFFFF3F) /* N Z C V I F */ | (R15 & 0xF0000000) /* N Z C V */ | ((R15 & 0x0C000000) >> (26 - 6)) /* I F */;
+ SET_CPSR(temp); /* Mask IRQ */
+ }
+ if ((COPRO_CTRL & COPRO_CTRL_MMU_EN) && (COPRO_CTRL & COPRO_CTRL_INTVEC_ADJUST)) R15 |= 0xFFFF0000;
+ cpustate->pendingSwi = 0;
+ return;
+ }
+}
+
+// CPU - SET IRQ LINE
+static void arm7_core_set_irq_line(arm_state *cpustate, int irqline, int state)
+{
+ switch (irqline) {
+
+ case ARM7_IRQ_LINE: /* IRQ */
+ cpustate->pendingIrq = state & 1;
+ break;
+
+ case ARM7_FIRQ_LINE: /* FIRQ */
+ cpustate->pendingFiq = state & 1;
+ break;
+
+ case ARM7_ABORT_EXCEPTION:
+ cpustate->pendingAbtD = state & 1;
+ break;
+ case ARM7_ABORT_PREFETCH_EXCEPTION:
+ cpustate->pendingAbtP = state & 1;
+ break;
+
+ case ARM7_UNDEFINE_EXCEPTION:
+ cpustate->pendingUnd = state & 1;
+ break;
+ }
+
+ ARM7_CHECKIRQ;
+}
+
+/***************************************************************************
+ * OPCODE HANDLING
+ ***************************************************************************/
+
+// Co-Processor Data Operation
+static void HandleCoProcDO(arm_state *cpustate, UINT32 insn)
+{
+ // This instruction simply instructs the co-processor to do something, no data is returned to ARM7 core
+ if (arm7_coproc_do_callback)
+ arm7_coproc_do_callback(cpustate->device, insn, 0, 0); // simply pass entire opcode to callback - since data format is actually dependent on co-proc implementation
+ else
+ LOG(("%08x: Co-Processor Data Operation executed, but no callback defined!\n", R15));
+}
+
+// Co-Processor Register Transfer - To/From Arm to Co-Proc
+static void HandleCoProcRT(arm_state *cpustate, UINT32 insn)
+{
+
+ /* xxxx 1110 oooL nnnn dddd cccc ppp1 mmmm */
+
+ // Load (MRC) data from Co-Proc to ARM7 register
+ if (insn & 0x00100000) // Bit 20 = Load or Store
+ {
+ if (arm7_coproc_rt_r_callback)
+ {
+ UINT32 res = arm7_coproc_rt_r_callback(cpustate->device, insn, 0); // RT Read handler must parse opcode & return appropriate result
+ SET_REGISTER(cpustate, (insn >> 12) & 0xf, res);
+ }
+ else
+ LOG(("%08x: Co-Processor Register Transfer executed, but no RT Read callback defined!\n", R15));
+ }
+ // Store (MCR) data from ARM7 to Co-Proc register
+ else
+ {
+ if (arm7_coproc_rt_w_callback)
+ arm7_coproc_rt_w_callback(cpustate->device, insn, GET_REGISTER(cpustate, (insn >> 12) & 0xf), 0);
+ else
+ LOG(("%08x: Co-Processor Register Transfer executed, but no RT Write callback defined!\n", R15));
+ }
+}
+
+/* Data Transfer - To/From Arm to Co-Proc
+ Loading or Storing, the co-proc function is responsible to read/write from the base register supplied + offset
+ 8 bit immediate value Base Offset address is << 2 to get the actual #
+
+ issues - #1 - the co-proc function, needs direct access to memory reads or writes (ie, so we must send a pointer to a func)
+ - #2 - the co-proc may adjust the base address (especially if it reads more than 1 word), so a pointer to the register must be used
+ but the old value of the register must be restored if write back is not set..
+ - #3 - when post incrementing is used, it's up to the co-proc func. to add the offset, since the transfer
+ address supplied in that case, is simply the base. I suppose this is irrelevant if write back not set
+ but if co-proc reads multiple address, it must handle the offset adjustment itself.
+*/
+// todo: test with valid instructions
+static void HandleCoProcDT(arm_state *cpustate, UINT32 insn)
+{
+ UINT32 rn = (insn >> 16) & 0xf;
+ UINT32 rnv = GET_REGISTER(cpustate, rn); // Get Address Value stored from Rn
+ UINT32 ornv = rnv; // Keep value of Rn
+ UINT32 off = (insn & 0xff) << 2; // Offset is << 2 according to manual
+ UINT32 *prn = &ARM7REG(rn); // Pointer to our register, so it can be changed in the callback
+
+ // Pointers to read32/write32 functions
+ void (*write32)(arm_state *cpustate, UINT32 addr, UINT32 data);
+ UINT32 (*read32)(arm_state *cpustate, UINT32 addr);
+ write32 = PTR_WRITE32;
+ read32 = PTR_READ32;
+
+#if ARM7_DEBUG_CORE
+ if (((insn >> 16) & 0xf) == 15 && (insn & 0x200000))
+ LOG(("%08x: Illegal use of R15 as base for write back value!\n", R15));
+#endif
+
+ // Pre-Increment base address (IF POST INCREMENT - CALL BACK FUNCTION MUST DO IT)
+ if ((insn & 0x1000000) && off)
+ {
+ // Up - Down bit
+ if (insn & 0x800000)
+ rnv += off;
+ else
+ rnv -= off;
+ }
+
+ // Load (LDC) data from ARM7 memory to Co-Proc memory
+ if (insn & 0x00100000)
+ {
+ if (arm7_coproc_dt_r_callback)
+ arm7_coproc_dt_r_callback(cpustate, insn, prn, read32);
+ else
+ LOG(("%08x: Co-Processer Data Transfer executed, but no READ callback defined!\n", R15));
+ }
+ // Store (STC) data from Co-Proc to ARM7 memory
+ else
+ {
+ if (arm7_coproc_dt_w_callback)
+ arm7_coproc_dt_w_callback(cpustate, insn, prn, write32);
+ else
+ LOG(("%08x: Co-Processer Data Transfer executed, but no WRITE callback defined!\n", R15));
+ }
+
+ // If writeback not used - ensure the original value of RN is restored in case co-proc callback changed value
+ if ((insn & 0x200000) == 0)
+ SET_REGISTER(cpustate, rn, ornv);
+}
+
+INLINE void HandleBranch(arm_state *cpustate, UINT32 insn)
+{
+ UINT32 off = (insn & INSN_BRANCH) << 2;
+
+ /* Save PC into LR if this is a branch with link */
+ if (insn & INSN_BL)
+ {
+ SET_REGISTER(cpustate, 14, R15 + 4);
+ }
+
+ /* Sign-extend the 24-bit offset in our calculations */
+ if (off & 0x2000000u)
+ {
+ if (MODE32)
+ R15 -= ((~(off | 0xfc000000u)) + 1) - 8;
+ else
+ R15 = ((R15 - (((~(off | 0xfc000000u)) + 1) - 8)) & 0x03FFFFFC) | (R15 & ~0x03FFFFFC);
+ }
+ else
+ {
+ if (MODE32)
+ R15 += off + 8;
+ else
+ R15 = ((R15 + (off + 8)) & 0x03FFFFFC) | (R15 & ~0x03FFFFFC);
+ }
+}
+
+static void HandleMemSingle(arm_state *cpustate, UINT32 insn)
+{
+ UINT32 rn, rnv, off, rd, rnv_old = 0;
+
+ /* Fetch the offset */
+ if (insn & INSN_I)
+ {
+ /* Register Shift */
+ off = decodeShift(cpustate, insn, NULL);
+ }
+ else
+ {
+ /* Immediate Value */
+ off = insn & INSN_SDT_IMM;
+ }
+
+ /* Calculate Rn, accounting for PC */
+ rn = (insn & INSN_RN) >> INSN_RN_SHIFT;
+
+ if (insn & INSN_SDT_P)
+ {
+ /* Pre-indexed addressing */
+ if (insn & INSN_SDT_U)
+ {
+ if ((MODE32) || (rn != eR15))
+ rnv = (GET_REGISTER(cpustate, rn) + off);
+ else
+ rnv = (GET_PC + off);
+ }
+ else
+ {
+ if ((MODE32) || (rn != eR15))
+ rnv = (GET_REGISTER(cpustate, rn) - off);
+ else
+ rnv = (GET_PC - off);
+ }
+
+ if (insn & INSN_SDT_W)
+ {
+ rnv_old = GET_REGISTER(cpustate, rn);
+ SET_REGISTER(cpustate, rn, rnv);
+
+ // check writeback???
+ }
+ else if (rn == eR15)
+ {
+ rnv = rnv + 8;
+ }
+ }
+ else
+ {
+ /* Post-indexed addressing */
+ if (rn == eR15)
+ {
+ if (MODE32)
+ rnv = R15 + 8;
+ else
+ rnv = GET_PC + 8;
+ }
+ else
+ {
+ rnv = GET_REGISTER(cpustate, rn);
+ }
+ }
+
+ /* Do the transfer */
+ rd = (insn & INSN_RD) >> INSN_RD_SHIFT;
+ if (insn & INSN_SDT_L)
+ {
+ /* Load */
+ if (insn & INSN_SDT_B)
+ {
+ UINT32 data = READ8(rnv);
+ if (cpustate->pendingAbtD == 0)
+ {
+ SET_REGISTER(cpustate, rd, data);
+ }
+ }
+ else
+ {
+ UINT32 data = READ32(rnv);
+ if (cpustate->pendingAbtD == 0)
+ {
+ if (rd == eR15)
+ {
+ if (MODE32)
+ R15 = data - 4;
+ else
+ R15 = (R15 & ~0x03FFFFFC) /* N Z C V I F M1 M0 */ | ((data - 4) & 0x03FFFFFC);
+ // LDR, PC takes 2S + 2N + 1I (5 total cycles)
+ ARM7_ICOUNT -= 2;
+ }
+ else
+ {
+ SET_REGISTER(cpustate, rd, data);
+ }
+ }
+ }
+ }
+ else
+ {
+ /* Store */
+ if (insn & INSN_SDT_B)
+ {
+#if ARM7_DEBUG_CORE
+ if (rd == eR15)
+ LOG(("Wrote R15 in byte mode\n"));
+#endif
+
+ WRITE8(rnv, (UINT8) GET_REGISTER(cpustate, rd) & 0xffu);
+ }
+ else
+ {
+#if ARM7_DEBUG_CORE
+ if (rd == eR15)
+ LOG(("Wrote R15 in 32bit mode\n"));
+#endif
+
+ //WRITE32(rnv, rd == eR15 ? R15 + 8 : GET_REGISTER(cpustate, rd));
+ WRITE32(rnv, rd == eR15 ? R15 + 8 + 4 : GET_REGISTER(cpustate, rd)); // manual says STR rd = PC, +12
+ }
+ // Store takes only 2 N Cycles, so add + 1
+ ARM7_ICOUNT += 1;
+ }
+
+ if (cpustate->pendingAbtD != 0)
+ {
+ if ((insn & INSN_SDT_P) && (insn & INSN_SDT_W))
+ {
+ SET_REGISTER(cpustate, rn, rnv_old);
+ }
+ }
+ else
+ {
+
+ /* Do post-indexing writeback */
+ if (!(insn & INSN_SDT_P)/* && (insn & INSN_SDT_W)*/)
+ {
+ if (insn & INSN_SDT_U)
+ {
+ /* Writeback is applied in pipeline, before value is read from mem,
+ so writeback is effectively ignored */
+ if (rd == rn) {
+ SET_REGISTER(cpustate, rn, GET_REGISTER(cpustate, rd));
+ // todo: check for offs... ?
+ }
+ else {
+
+ if ((insn & INSN_SDT_W) != 0)
+ LOG(("%08x: RegisterWritebackIncrement %d %d %d\n", R15, (insn & INSN_SDT_P) != 0, (insn & INSN_SDT_W) != 0, (insn & INSN_SDT_U) != 0));
+
+ SET_REGISTER(cpustate, rn, (rnv + off));
+ }
+ }
+ else
+ {
+ /* Writeback is applied in pipeline, before value is read from mem,
+ so writeback is effectively ignored */
+ if (rd == rn) {
+ SET_REGISTER(cpustate, rn, GET_REGISTER(cpustate, rd));
+ }
+ else {
+ SET_REGISTER(cpustate, rn, (rnv - off));
+
+ if ((insn & INSN_SDT_W) != 0)
+ LOG(("%08x: RegisterWritebackDecrement %d %d %d\n", R15, (insn & INSN_SDT_P) != 0, (insn & INSN_SDT_W) != 0, (insn & INSN_SDT_U) != 0));
+ }
+ }
+ }
+
+ }
+
+// ARM7_CHECKIRQ
+
+} /* HandleMemSingle */
+
+static void HandleHalfWordDT(arm_state *cpustate, UINT32 insn)
+{
+ UINT32 rn, rnv, off, rd, rnv_old = 0;
+
+ // Immediate or Register Offset?
+ if (insn & 0x400000) { // Bit 22 - 1 = immediate, 0 = register
+ // imm. value in high nibble (bits 8-11) and lo nibble (bit 0-3)
+ off = (((insn >> 8) & 0x0f) << 4) | (insn & 0x0f);
+ }
+ else {
+ // register
+ off = GET_REGISTER(cpustate, insn & 0x0f);
+ }
+
+ /* Calculate Rn, accounting for PC */
+ rn = (insn & INSN_RN) >> INSN_RN_SHIFT;
+
+ if (insn & INSN_SDT_P)
+ {
+ /* Pre-indexed addressing */
+ if (insn & INSN_SDT_U)
+ {
+ rnv = (GET_REGISTER(cpustate, rn) + off);
+ }
+ else
+ {
+ rnv = (GET_REGISTER(cpustate, rn) - off);
+ }
+
+ if (insn & INSN_SDT_W)
+ {
+ rnv_old = GET_REGISTER(cpustate, rn);
+ SET_REGISTER(cpustate, rn, rnv);
+
+ // check writeback???
+ }
+ else if (rn == eR15)
+ {
+ rnv = (rnv) + 8;
+ }
+ }
+ else
+ {
+ /* Post-indexed addressing */
+ if (rn == eR15)
+ {
+ rnv = R15 + 8;
+ }
+ else
+ {
+ rnv = GET_REGISTER(cpustate, rn);
+ }
+ }
+
+ /* Do the transfer */
+ rd = (insn & INSN_RD) >> INSN_RD_SHIFT;
+
+ /* Load */
+ if (insn & INSN_SDT_L)
+ {
+ // Signed?
+ if (insn & 0x40)
+ {
+ UINT32 newval = 0;
+
+ // Signed Half Word?
+ if (insn & 0x20) {
+ UINT16 signbyte, databyte;
+ databyte = READ16(rnv) & 0xFFFF;
+ signbyte = (databyte & 0x8000) ? 0xffff : 0;
+ newval = (UINT32)(signbyte << 16)|databyte;
+ }
+ // Signed Byte
+ else {
+ UINT8 databyte;
+ UINT32 signbyte;
+ databyte = READ8(rnv) & 0xff;
+ signbyte = (databyte & 0x80) ? 0xffffff : 0;
+ newval = (UINT32)(signbyte << 8)|databyte;
+ }
+
+ if (cpustate->pendingAbtD == 0)
+ {
+
+ // PC?
+ if (rd == eR15)
+ {
+ R15 = newval + 8;
+ // LDR(H,SH,SB) PC takes 2S + 2N + 1I (5 total cycles)
+ ARM7_ICOUNT -= 2;
+
+ }
+ else
+ {
+ SET_REGISTER(cpustate, rd, newval);
+ R15 += 4;
+ }
+
+ }
+ else
+ {
+ R15 += 4;
+ }
+
+ }
+ // Unsigned Half Word
+ else
+ {
+ UINT32 newval = READ16(rnv);
+
+ if (cpustate->pendingAbtD == 0)
+ {
+
+ if (rd == eR15)
+ {
+ R15 = newval + 8;
+ // extra cycles for LDR(H,SH,SB) PC (5 total cycles)
+ ARM7_ICOUNT -= 2;
+ }
+ else
+ {
+ SET_REGISTER(cpustate, rd, newval);
+ R15 += 4;
+ }
+
+ }
+ else
+ {
+ R15 += 4;
+ }
+
+ }
+
+
+ }
+ /* Store or ARMv5+ dword insns */
+ else
+ {
+ if ((insn & 0x60) == 0x40) // LDRD
+ {
+ SET_REGISTER(cpustate, rd, READ32(rnv));
+ SET_REGISTER(cpustate, rd+1, READ32(rnv+4));
+ R15 += 4;
+ }
+ else if ((insn & 0x60) == 0x60) // STRD
+ {
+ WRITE32(rnv, GET_REGISTER(cpustate, rd));
+ WRITE32(rnv+4, GET_REGISTER(cpustate, rd+1));
+ R15 += 4;
+ }
+ else
+ {
+ // WRITE16(rnv, rd == eR15 ? R15 + 8 : GET_REGISTER(cpustate, rd));
+ WRITE16(rnv, rd == eR15 ? R15 + 8 + 4 : GET_REGISTER(cpustate, rd)); // manual says STR RD=PC, +12 of address
+
+// if R15 is not increased then e.g. "STRH R10, [R15,#$10]" will be executed over and over again
+#if 0
+ if (rn != eR15)
+#endif
+ R15 += 4;
+
+ // STRH takes 2 cycles, so we add + 1
+ ARM7_ICOUNT += 1;
+ }
+ }
+
+ if (cpustate->pendingAbtD != 0)
+ {
+ if ((insn & INSN_SDT_P) && (insn & INSN_SDT_W))
+ {
+ SET_REGISTER(cpustate, rn, rnv_old);
+ }
+ }
+ else
+ {
+
+ // SJE: No idea if this writeback code works or makes sense here..
+
+ /* Do post-indexing writeback */
+ if (!(insn & INSN_SDT_P)/* && (insn & INSN_SDT_W)*/)
+ {
+ if (insn & INSN_SDT_U)
+ {
+ /* Writeback is applied in pipeline, before value is read from mem,
+ so writeback is effectively ignored */
+ if (rd == rn) {
+ SET_REGISTER(cpustate, rn, GET_REGISTER(cpustate, rd));
+ // todo: check for offs... ?
+ }
+ else {
+
+ if ((insn & INSN_SDT_W) != 0)
+ LOG(("%08x: RegisterWritebackIncrement %d %d %d\n", R15, (insn & INSN_SDT_P) != 0, (insn & INSN_SDT_W) != 0, (insn & INSN_SDT_U) != 0));
+
+ SET_REGISTER(cpustate, rn, (rnv + off));
+ }
+ }
+ else
+ {
+ /* Writeback is applied in pipeline, before value is read from mem,
+ so writeback is effectively ignored */
+ if (rd == rn) {
+ SET_REGISTER(cpustate, rn, GET_REGISTER(cpustate, rd));
+ }
+ else {
+ SET_REGISTER(cpustate, rn, (rnv - off));
+
+ if ((insn & INSN_SDT_W) != 0)
+ LOG(("%08x: RegisterWritebackDecrement %d %d %d\n", R15, (insn & INSN_SDT_P) != 0, (insn & INSN_SDT_W) != 0, (insn & INSN_SDT_U) != 0));
+ }
+ }
+ }
+
+ }
+
+}
+
+static void HandleSwap(arm_state *cpustate, UINT32 insn)
+{
+ UINT32 rn, rm, rd, tmp;
+
+ rn = GET_REGISTER(cpustate, (insn >> 16) & 0xf); // reg. w/read address
+ rm = GET_REGISTER(cpustate, insn & 0xf); // reg. w/write address
+ rd = (insn >> 12) & 0xf; // dest reg
+
+#if ARM7_DEBUG_CORE
+ if (rn == 15 || rm == 15 || rd == 15)
+ LOG(("%08x: Illegal use of R15 in Swap Instruction\n", R15));
+#endif
+
+ // can be byte or word
+ if (insn & 0x400000)
+ {
+ tmp = READ8(rn);
+ WRITE8(rn, rm);
+ SET_REGISTER(cpustate, rd, tmp);
+ }
+ else
+ {
+ tmp = READ32(rn);
+ WRITE32(rn, rm);
+ SET_REGISTER(cpustate, rd, tmp);
+ }
+
+ R15 += 4;
+ // Instruction takes 1S+2N+1I cycles - so we subtract one more..
+ ARM7_ICOUNT -= 1;
+}
+
+static void HandlePSRTransfer(arm_state *cpustate, UINT32 insn)
+{
+ int reg = (insn & 0x400000) ? SPSR : eCPSR; // Either CPSR or SPSR
+ UINT32 newval, val = 0;
+ int oldmode = GET_CPSR & MODE_FLAG;
+
+ // get old value of CPSR/SPSR
+ newval = GET_REGISTER(cpustate, reg);
+
+ // MSR (bit 21 set) - Copy value to CPSR/SPSR
+ if ((insn & 0x00200000))
+ {
+ // Immediate Value?
+ if (insn & INSN_I) {
+ // Value can be specified for a Right Rotate, 2x the value specified.
+ int by = (insn & INSN_OP2_ROTATE) >> INSN_OP2_ROTATE_SHIFT;
+ if (by)
+ val = ROR(insn & INSN_OP2_IMM, by << 1);
+ else
+ val = insn & INSN_OP2_IMM;
+ }
+ // Value from Register
+ else
+ {
+ val = GET_REGISTER(cpustate, insn & 0x0f);
+ }
+
+ // apply field code bits
+ if (reg == eCPSR)
+ {
+ if (oldmode != eARM7_MODE_USER)
+ {
+ if (insn & 0x00010000)
+ {
+ newval = (newval & 0xffffff00) | (val & 0x000000ff);
+ }
+ if (insn & 0x00020000)
+ {
+ newval = (newval & 0xffff00ff) | (val & 0x0000ff00);
+ }
+ if (insn & 0x00040000)
+ {
+ newval = (newval & 0xff00ffff) | (val & 0x00ff0000);
+ }
+ }
+
+ // status flags can be modified regardless of mode
+ if (insn & 0x00080000)
+ {
+ // TODO for non ARMv5E mask should be 0xf0000000 (ie mask Q bit)
+ newval = (newval & 0x00ffffff) | (val & 0xf8000000);
+ }
+ }
+ else // SPSR has stricter requirements
+ {
+ if (((GET_CPSR & 0x1f) > 0x10) && ((GET_CPSR & 0x1f) < 0x1f))
+ {
+ if (insn & 0x00010000)
+ {
+ newval = (newval & 0xffffff00) | (val & 0xff);
+ }
+ if (insn & 0x00020000)
+ {
+ newval = (newval & 0xffff00ff) | (val & 0xff00);
+ }
+ if (insn & 0x00040000)
+ {
+ newval = (newval & 0xff00ffff) | (val & 0xff0000);
+ }
+ if (insn & 0x00080000)
+ {
+ // TODO for non ARMv5E mask should be 0xf0000000 (ie mask Q bit)
+ newval = (newval & 0x00ffffff) | (val & 0xf8000000);
+ }
+ }
+ }
+
+#if 0
+ // force valid mode
+ newval |= 0x10;
+#endif
+
+ // Update the Register
+ if (reg == eCPSR)
+ SET_CPSR(newval);
+ else
+ SET_REGISTER(cpustate, reg, newval);
+
+ // Switch to new mode if changed
+ if ((newval & MODE_FLAG) != oldmode)
+ SwitchMode(cpustate, GET_MODE);
+
+ }
+ // MRS (bit 21 clear) - Copy CPSR or SPSR to specified Register
+ else
+ {
+ SET_REGISTER(cpustate, (insn >> 12)& 0x0f, GET_REGISTER(cpustate, reg));
+ }
+}
+
+static void HandleALU(arm_state *cpustate, UINT32 insn)
+{
+ UINT32 op2, sc = 0, rd, rn, opcode;
+ UINT32 by, rdn;
+
+ // Normal Data Processing : 1S
+ // Data Processing with register specified shift : 1S + 1I
+ // Data Processing with PC written : 2S + 1N
+ // Data Processing with register specified shift and PC written : 2S + 1N + 1I
+
+ opcode = (insn & INSN_OPCODE) >> INSN_OPCODE_SHIFT;
+
+ rd = 0;
+ rn = 0;
+
+ /* --------------*/
+ /* Construct Op2 */
+ /* --------------*/
+
+ /* Immediate constant */
+ if (insn & INSN_I)
+ {
+ by = (insn & INSN_OP2_ROTATE) >> INSN_OP2_ROTATE_SHIFT;
+ if (by)
+ {
+ op2 = ROR(insn & INSN_OP2_IMM, by << 1);
+ sc = op2 & SIGN_BIT;
+ }
+ else
+ {
+ op2 = insn & INSN_OP2; // SJE: Shouldn't this be INSN_OP2_IMM?
+ sc = GET_CPSR & C_MASK;
+ }
+ }
+ /* Op2 = Register Value */
+ else
+ {
+ op2 = decodeShift(cpustate, insn, (insn & INSN_S) ? &sc : NULL);
+
+ // LD TODO sc will always be 0 if this applies
+ if (!(insn & INSN_S))
+ sc = 0;
+
+ // extra cycle (register specified shift)
+ ARM7_ICOUNT -= 1;
+ }
+
+ // LD TODO this comment is wrong
+ /* Calculate Rn to account for pipelining */
+ if ((opcode & 0xd) != 0xd) /* No Rn in MOV */
+ {
+ if ((rn = (insn & INSN_RN) >> INSN_RN_SHIFT) == eR15)
+ {
+#if ARM7_DEBUG_CORE
+ LOG(("%08x: Pipelined R15 (Shift %d)\n", R15, (insn & INSN_I ? 8 : insn & 0x10u ? 12 : 12)));
+#endif
+ if (MODE32)
+ rn = R15 + 8;
+ else
+ rn = GET_PC + 8;
+ }
+ else
+ {
+ rn = GET_REGISTER(cpustate, rn);
+ }
+ }
+
+ /* Perform the operation */
+
+ switch (opcode)
+ {
+ /* Arithmetic operations */
+ case OPCODE_SBC:
+ rd = (rn - op2 - (GET_CPSR & C_MASK ? 0 : 1));
+ HandleALUSubFlags(rd, rn, op2);
+ break;
+ case OPCODE_CMP:
+ case OPCODE_SUB:
+ rd = (rn - op2);
+ HandleALUSubFlags(rd, rn, op2);
+ break;
+ case OPCODE_RSC:
+ rd = (op2 - rn - (GET_CPSR & C_MASK ? 0 : 1));
+ HandleALUSubFlags(rd, op2, rn);
+ break;
+ case OPCODE_RSB:
+ rd = (op2 - rn);
+ HandleALUSubFlags(rd, op2, rn);
+ break;
+ case OPCODE_ADC:
+ rd = (rn + op2 + ((GET_CPSR & C_MASK) >> C_BIT));
+ HandleALUAddFlags(rd, rn, op2);
+ break;
+ case OPCODE_CMN:
+ case OPCODE_ADD:
+ rd = (rn + op2);
+ HandleALUAddFlags(rd, rn, op2);
+ break;
+
+ /* Logical operations */
+ case OPCODE_AND:
+ case OPCODE_TST:
+ rd = rn & op2;
+ HandleALULogicalFlags(rd, sc);
+ break;
+ case OPCODE_BIC:
+ rd = rn & ~op2;
+ HandleALULogicalFlags(rd, sc);
+ break;
+ case OPCODE_TEQ:
+ case OPCODE_EOR:
+ rd = rn ^ op2;
+ HandleALULogicalFlags(rd, sc);
+ break;
+ case OPCODE_ORR:
+ rd = rn | op2;
+ HandleALULogicalFlags(rd, sc);
+ break;
+ case OPCODE_MOV:
+ rd = op2;
+ HandleALULogicalFlags(rd, sc);
+ break;
+ case OPCODE_MVN:
+ rd = (~op2);
+ HandleALULogicalFlags(rd, sc);
+ break;
+ }
+
+ /* Put the result in its register if not one of the test only opcodes (TST,TEQ,CMP,CMN) */
+ rdn = (insn & INSN_RD) >> INSN_RD_SHIFT;
+ if ((opcode & 0xc) != 0x8)
+ {
+ // If Rd = R15, but S Flag not set, Result is placed in R15, but CPSR is not affected (page 44)
+ if (rdn == eR15 && !(insn & INSN_S))
+ {
+ if (MODE32)
+ {
+ R15 = rd;
+ }
+ else
+ {
+ R15 = (R15 & ~0x03FFFFFC) | (rd & 0x03FFFFFC);
+ }
+ // extra cycles (PC written)
+ ARM7_ICOUNT -= 2;
+ }
+ else
+ {
+ // Rd = 15 and S Flag IS set, Result is placed in R15, and current mode SPSR moved to CPSR
+ if (rdn == eR15) {
+
+ if (MODE32)
+ {
+ // When Rd is R15 and the S flag is set the result of the operation is placed in R15 and the SPSR corresponding to
+ // the current mode is moved to the CPSR. This allows state changes which automatically restore both PC and
+ // CPSR. --> This form of instruction should not be used in User mode. <--
+
+ if (GET_MODE != eARM7_MODE_USER)
+ {
+ // Update CPSR from SPSR
+ SET_CPSR(GET_REGISTER(cpustate, SPSR));
+ SwitchMode(cpustate, GET_MODE);
+ }
+
+ R15 = rd;
+
+ }
+ else
+ {
+ UINT32 temp;
+ R15 = rd; //(R15 & 0x03FFFFFC) | (rd & 0xFC000003);
+ temp = (GET_CPSR & 0x0FFFFF20) | (rd & 0xF0000000) /* N Z C V */ | ((rd & 0x0C000000) >> (26 - 6)) /* I F */ | (rd & 0x00000003) /* M1 M0 */;
+ SET_CPSR( temp);
+ SwitchMode( cpustate, temp & 3);
+ }
+
+ // extra cycles (PC written)
+ ARM7_ICOUNT -= 2;
+
+ /* IRQ masks may have changed in this instruction */
+// ARM7_CHECKIRQ;
+ }
+ else
+ /* S Flag is set - Write results to register & update CPSR (which was already handled using HandleALU flag macros) */
+ SET_REGISTER(cpustate, rdn, rd);
+ }
+ }
+ // SJE: Don't think this applies any more.. (see page 44 at bottom)
+ /* TST & TEQ can affect R15 (the condition code register) with the S bit set */
+ else if (rdn == eR15)
+ {
+ if (insn & INSN_S) {
+#if ARM7_DEBUG_CORE
+ LOG(("%08x: TST class on R15 s bit set\n", R15));
+#endif
+ if (MODE32)
+ R15 = rd;
+ else
+ {
+ UINT32 temp;
+ R15 = (R15 & 0x03FFFFFC) | (rd & ~0x03FFFFFC);
+ temp = (GET_CPSR & 0x0FFFFF20) | (rd & 0xF0000000) /* N Z C V */ | ((rd & 0x0C000000) >> (26 - 6)) /* I F */ | (rd & 0x00000003) /* M1 M0 */;
+ SET_CPSR( temp);
+ SwitchMode( cpustate, temp & 3);
+ }
+
+ /* IRQ masks may have changed in this instruction */
+// ARM7_CHECKIRQ;
+ }
+ else
+ {
+#if ARM7_DEBUG_CORE
+ LOG(("%08x: TST class on R15 no s bit set\n", R15));
+#endif
+ }
+ // extra cycles (PC written)
+ ARM7_ICOUNT -= 2;
+ }
+
+ // compensate for the -3 at the end
+ ARM7_ICOUNT += 2;
+}
+
+static void HandleMul(arm_state *cpustate, UINT32 insn)
+{
+ UINT32 r, rm, rs;
+
+ // MUL takes 1S + mI and MLA 1S + (m+1)I cycles to execute, where S and I are as
+ // defined in 6.2 Cycle Types on page 6-2.
+ // m is the number of 8 bit multiplier array cycles required to complete the
+ // multiply, which is controlled by the value of the multiplier operand
+ // specified by Rs.
+
+ rm = GET_REGISTER(cpustate, insn & INSN_MUL_RM);
+ rs = GET_REGISTER(cpustate, (insn & INSN_MUL_RS) >> INSN_MUL_RS_SHIFT);
+
+ /* Do the basic multiply of Rm and Rs */
+ r = rm * rs;
+
+#if ARM7_DEBUG_CORE
+ if ((insn & INSN_MUL_RM) == 0xf ||
+ ((insn & INSN_MUL_RS) >> INSN_MUL_RS_SHIFT) == 0xf ||
+ ((insn & INSN_MUL_RN) >> INSN_MUL_RN_SHIFT) == 0xf)
+ LOG(("%08x: R15 used in mult\n", R15));
+#endif
+
+ /* Add on Rn if this is a MLA */
+ if (insn & INSN_MUL_A)
+ {
+ r += GET_REGISTER(cpustate, (insn & INSN_MUL_RN) >> INSN_MUL_RN_SHIFT);
+ // extra cycle for MLA
+ ARM7_ICOUNT -= 1;
+ }
+
+ /* Write the result */
+ SET_REGISTER(cpustate, (insn & INSN_MUL_RD) >> INSN_MUL_RD_SHIFT, r);
+
+ /* Set N and Z if asked */
+ if (insn & INSN_S)
+ {
+ SET_CPSR((GET_CPSR & ~(N_MASK | Z_MASK)) | HandleALUNZFlags(r));
+ }
+
+ if (rs & SIGN_BIT) rs = -rs;
+ if (rs < 0x00000100) ARM7_ICOUNT -= 1 + 1;
+ else if (rs < 0x00010000) ARM7_ICOUNT -= 1 + 2;
+ else if (rs < 0x01000000) ARM7_ICOUNT -= 1 + 3;
+ else ARM7_ICOUNT -= 1 + 4;
+
+ ARM7_ICOUNT += 3;
+}
+
+// todo: add proper cycle counts
+static void HandleSMulLong(arm_state *cpustate, UINT32 insn)
+{
+ INT32 rm, rs;
+ UINT32 rhi, rlo;
+ INT64 res = 0;
+
+ // MULL takes 1S + (m+1)I and MLAL 1S + (m+2)I cycles to execute, where m is the
+ // number of 8 bit multiplier array cycles required to complete the multiply, which is
+ // controlled by the value of the multiplier operand specified by Rs.
+
+ rm = (INT32)GET_REGISTER(cpustate, insn & 0xf);
+ rs = (INT32)GET_REGISTER(cpustate, ((insn >> 8) & 0xf));
+ rhi = (insn >> 16) & 0xf;
+ rlo = (insn >> 12) & 0xf;
+
+#if ARM7_DEBUG_CORE
+ if ((insn & 0xf) == 15 || ((insn >> 8) & 0xf) == 15 || ((insn >> 16) & 0xf) == 15 || ((insn >> 12) & 0xf) == 15)
+ LOG(("%08x: Illegal use of PC as a register in SMULL opcode\n", R15));
+#endif
+
+ /* Perform the multiplication */
+ res = (INT64)rm * rs;
+
+ /* Add on Rn if this is a MLA */
+ if (insn & INSN_MUL_A)
+ {
+ INT64 acum = (INT64)((((INT64)(GET_REGISTER(cpustate, rhi))) << 32) | GET_REGISTER(cpustate, rlo));
+ res += acum;
+ // extra cycle for MLA
+ ARM7_ICOUNT -= 1;
+ }
+
+ /* Write the result (upper dword goes to RHi, lower to RLo) */
+ SET_REGISTER(cpustate, rhi, res >> 32);
+ SET_REGISTER(cpustate, rlo, res & 0xFFFFFFFF);
+
+ /* Set N and Z if asked */
+ if (insn & INSN_S)
+ {
+ SET_CPSR((GET_CPSR & ~(N_MASK | Z_MASK)) | HandleLongALUNZFlags(res));
+ }
+
+ if (rs < 0) rs = -rs;
+ if (rs < 0x00000100) ARM7_ICOUNT -= 1 + 1 + 1;
+ else if (rs < 0x00010000) ARM7_ICOUNT -= 1 + 2 + 1;
+ else if (rs < 0x01000000) ARM7_ICOUNT -= 1 + 3 + 1;
+ else ARM7_ICOUNT -= 1 + 4 + 1;
+
+ ARM7_ICOUNT += 3;
+}
+
+// todo: add proper cycle counts
+static void HandleUMulLong(arm_state *cpustate, UINT32 insn)
+{
+ UINT32 rm, rs;
+ UINT32 rhi, rlo;
+ UINT64 res = 0;
+
+ // MULL takes 1S + (m+1)I and MLAL 1S + (m+2)I cycles to execute, where m is the
+ // number of 8 bit multiplier array cycles required to complete the multiply, which is
+ // controlled by the value of the multiplier operand specified by Rs.
+
+ rm = (INT32)GET_REGISTER(cpustate, insn & 0xf);
+ rs = (INT32)GET_REGISTER(cpustate, ((insn >> 8) & 0xf));
+ rhi = (insn >> 16) & 0xf;
+ rlo = (insn >> 12) & 0xf;
+
+#if ARM7_DEBUG_CORE
+ if (((insn & 0xf) == 15) || (((insn >> 8) & 0xf) == 15) || (((insn >> 16) & 0xf) == 15) || (((insn >> 12) & 0xf) == 15))
+ LOG(("%08x: Illegal use of PC as a register in SMULL opcode\n", R15));
+#endif
+
+ /* Perform the multiplication */
+ res = (UINT64)rm * rs;
+
+ /* Add on Rn if this is a MLA */
+ if (insn & INSN_MUL_A)
+ {
+ UINT64 acum = (UINT64)((((UINT64)(GET_REGISTER(cpustate, rhi))) << 32) | GET_REGISTER(cpustate, rlo));
+ res += acum;
+ // extra cycle for MLA
+ ARM7_ICOUNT -= 1;
+ }
+
+ /* Write the result (upper dword goes to RHi, lower to RLo) */
+ SET_REGISTER(cpustate, rhi, res >> 32);
+ SET_REGISTER(cpustate, rlo, res & 0xFFFFFFFF);
+
+ /* Set N and Z if asked */
+ if (insn & INSN_S)
+ {
+ SET_CPSR((GET_CPSR & ~(N_MASK | Z_MASK)) | HandleLongALUNZFlags(res));
+ }
+
+ if (rs < 0x00000100) ARM7_ICOUNT -= 1 + 1 + 1;
+ else if (rs < 0x00010000) ARM7_ICOUNT -= 1 + 2 + 1;
+ else if (rs < 0x01000000) ARM7_ICOUNT -= 1 + 3 + 1;
+ else ARM7_ICOUNT -= 1 + 4 + 1;
+
+ ARM7_ICOUNT += 3;
+}
+
+static void HandleMemBlock(arm_state *cpustate, UINT32 insn)
+{
+ UINT32 rb = (insn & INSN_RN) >> INSN_RN_SHIFT;
+ UINT32 rbp = GET_REGISTER(cpustate, rb);
+ int result;
+
+#if ARM7_DEBUG_CORE
+ if (rbp & 3)
+ LOG(("%08x: Unaligned Mem Transfer @ %08x\n", R15, rbp));
+#endif
+
+ // Normal LDM instructions take nS + 1N + 1I and LDM PC takes (n+1)S + 2N + 1I
+ // incremental cycles, where S,N and I are as defined in 6.2 Cycle Types on page 6-2.
+ // STM instructions take (n-1)S + 2N incremental cycles to execute, where n is the
+ // number of words transferred.
+
+ if (insn & INSN_BDT_L)
+ {
+ /* Loading */
+ if (insn & INSN_BDT_U)
+ {
+ /* Incrementing */
+ if (!(insn & INSN_BDT_P))
+ {
+ rbp = rbp + (- 4);
+ }
+
+ // S Flag Set, but R15 not in list = User Bank Transfer
+ if (insn & INSN_BDT_S && (insn & 0x8000) == 0)
+ {
+ // set to user mode - then do the transfer, and set back
+ int curmode = GET_MODE;
+ SwitchMode(cpustate, eARM7_MODE_USER);
+ LOG(("%08x: User Bank Transfer not fully tested - please check if working properly!\n", R15));
+ result = loadInc(cpustate, insn & 0xffff, rbp, insn & INSN_BDT_S);
+ // todo - not sure if Writeback occurs on User registers also..
+ SwitchMode(cpustate, curmode);
+ }
+ else
+ result = loadInc(cpustate, insn & 0xffff, rbp, insn & INSN_BDT_S);
+
+ if ((insn & INSN_BDT_W) && (cpustate->pendingAbtD == 0))
+ {
+#if ARM7_DEBUG_CORE
+ if (rb == 15)
+ LOG(("%08x: Illegal LDRM writeback to r15\n", R15));
+#endif
+ // "A LDM will always overwrite the updated base if the base is in the list." (also for a user bank transfer?)
+ // GBA "V-Rally 3" expects R0 not to be overwritten with the updated base value [BP 8077B0C]
+ if (((insn >> rb) & 1) == 0)
+ {
+ SET_REGISTER(cpustate, rb, GET_REGISTER(cpustate, rb) + result * 4);
+ }
+ }
+
+ // R15 included? (NOTE: CPSR restore must occur LAST otherwise wrong registers restored!)
+ if ((insn & 0x8000) && (cpustate->pendingAbtD == 0)) {
+ R15 -= 4; // SJE: I forget why i did this?
+ // S - Flag Set? Signals transfer of current mode SPSR->CPSR
+ if (insn & INSN_BDT_S)
+ {
+ if (MODE32)
+ {
+ SET_CPSR(GET_REGISTER(cpustate, SPSR));
+ SwitchMode(cpustate, GET_MODE);
+ }
+ else
+ {
+ UINT32 temp;
+// LOG(("LDM + S | R15 %08X CPSR %08X\n", R15, GET_CPSR));
+ temp = (GET_CPSR & 0x0FFFFF20) | (R15 & 0xF0000000) /* N Z C V */ | ((R15 & 0x0C000000) >> (26 - 6)) /* I F */ | (R15 & 0x00000003) /* M1 M0 */;
+ SET_CPSR( temp);
+ SwitchMode(cpustate, temp & 3);
+ }
+ }
+ // LDM PC - takes 2 extra cycles
+ ARM7_ICOUNT -= 2;
+ }
+ }
+ else
+ {
+ /* Decrementing */
+ if (!(insn & INSN_BDT_P))
+ {
+ rbp = rbp - (- 4);
+ }
+
+ // S Flag Set, but R15 not in list = User Bank Transfer
+ if (insn & INSN_BDT_S && ((insn & 0x8000) == 0))
+ {
+ // set to user mode - then do the transfer, and set back
+ int curmode = GET_MODE;
+ SwitchMode(cpustate, eARM7_MODE_USER);
+ LOG(("%08x: User Bank Transfer not fully tested - please check if working properly!\n", R15));
+ result = loadDec(cpustate, insn & 0xffff, rbp, insn & INSN_BDT_S);
+ // todo - not sure if Writeback occurs on User registers also..
+ SwitchMode(cpustate, curmode);
+ }
+ else
+ result = loadDec(cpustate, insn & 0xffff, rbp, insn & INSN_BDT_S);
+
+ if ((insn & INSN_BDT_W) && (cpustate->pendingAbtD == 0))
+ {
+ if (rb == 0xf)
+ LOG(("%08x: Illegal LDRM writeback to r15\n", R15));
+ // "A LDM will always overwrite the updated base if the base is in the list." (also for a user bank transfer?)
+ if (((insn >> rb) & 1) == 0)
+ {
+ SET_REGISTER(cpustate, rb, GET_REGISTER(cpustate, rb) - result * 4);
+ }
+ }
+
+ // R15 included? (NOTE: CPSR restore must occur LAST otherwise wrong registers restored!)
+ if ((insn & 0x8000) && (cpustate->pendingAbtD == 0)) {
+ R15 -= 4; // SJE: I forget why i did this?
+ // S - Flag Set? Signals transfer of current mode SPSR->CPSR
+ if (insn & INSN_BDT_S)
+ {
+ if (MODE32)
+ {
+ SET_CPSR(GET_REGISTER(cpustate, SPSR));
+ SwitchMode(cpustate, GET_MODE);
+ }
+ else
+ {
+ UINT32 temp;
+// LOG(("LDM + S | R15 %08X CPSR %08X\n", R15, GET_CPSR));
+ temp = (GET_CPSR & 0x0FFFFF20) /* N Z C V I F M4 M3 M2 M1 M0 */ | (R15 & 0xF0000000) /* N Z C V */ | ((R15 & 0x0C000000) >> (26 - 6)) /* I F */ | (R15 & 0x00000003) /* M1 M0 */;
+ SET_CPSR( temp);
+ SwitchMode(cpustate, temp & 3);
+ }
+ }
+ // LDM PC - takes 2 extra cycles
+ ARM7_ICOUNT -= 2;
+ }
+ }
+ // LDM (NO PC) takes (n)S + 1N + 1I cycles (n = # of register transfers)
+ ARM7_ICOUNT -= result + 1 + 1;
+ } /* Loading */
+ else
+ {
+ /* Storing */
+ if (insn & (1 << eR15))
+ {
+#if ARM7_DEBUG_CORE
+ LOG(("%08x: Writing R15 in strm\n", R15));
+#endif
+ /* special case handling if writing to PC */
+ R15 += 12;
+ }
+ if (insn & INSN_BDT_U)
+ {
+ /* Incrementing */
+ if (!(insn & INSN_BDT_P))
+ {
+ rbp = rbp + (- 4);
+ }
+
+ // S Flag Set = User Bank Transfer
+ if (insn & INSN_BDT_S)
+ {
+ // todo: needs to be tested..
+
+ // set to user mode - then do the transfer, and set back
+ int curmode = GET_MODE;
+ SwitchMode(cpustate, eARM7_MODE_USER);
+ LOG(("%08x: User Bank Transfer not fully tested - please check if working properly!\n", R15));
+ result = storeInc(cpustate, insn & 0xffff, rbp);
+ // todo - not sure if Writeback occurs on User registers also..
+ SwitchMode(cpustate, curmode);
+ }
+ else
+ result = storeInc(cpustate, insn & 0xffff, rbp);
+
+ if ((insn & INSN_BDT_W) && (cpustate->pendingAbtD == 0))
+ {
+ SET_REGISTER(cpustate, rb, GET_REGISTER(cpustate, rb) + result * 4);
+ }
+ }
+ else
+ {
+ /* Decrementing */
+ if (!(insn & INSN_BDT_P))
+ {
+ rbp = rbp - (-4);
+ }
+
+ // S Flag Set = User Bank Transfer
+ if (insn & INSN_BDT_S)
+ {
+ // set to user mode - then do the transfer, and set back
+ int curmode = GET_MODE;
+ SwitchMode(cpustate, eARM7_MODE_USER);
+ LOG(("%08x: User Bank Transfer not fully tested - please check if working properly!\n", R15));
+ result = storeDec(cpustate, insn & 0xffff, rbp);
+ // todo - not sure if Writeback occurs on User registers also..
+ SwitchMode(cpustate, curmode);
+ }
+ else
+ result = storeDec(cpustate, insn & 0xffff, rbp);
+
+ if ((insn & INSN_BDT_W) && (cpustate->pendingAbtD == 0))
+ {
+ SET_REGISTER(cpustate, rb, GET_REGISTER(cpustate, rb) - result * 4);
+ }
+ }
+ if (insn & (1 << eR15))
+ R15 -= 12;
+
+ // STM takes (n-1)S + 2N cycles (n = # of register transfers)
+ ARM7_ICOUNT -= (result - 1) + 2;
+ }
+
+ // We will specify the cycle count for each case, so remove the -3 that occurs at the end
+ ARM7_ICOUNT += 3;
+
+} /* HandleMemBlock */
diff --git a/trunk/src/emu/cpu/arm7/arm7core.h b/trunk/src/emu/cpu/arm7/arm7core.h
new file mode 100644
index 00000000000..8209c3c89bb
--- /dev/null
+++ b/trunk/src/emu/cpu/arm7/arm7core.h
@@ -0,0 +1,530 @@
+/*****************************************************************************
+ *
+ * arm7core.h
+ * Portable ARM7TDMI Core Emulator
+ *
+ * Copyright Steve Ellenoff, all rights reserved.
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * sellenoff@hotmail.com
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ * This work is based on:
+ * #1) 'Atmel Corporation ARM7TDMI (Thumb) Datasheet - January 1999'
+ * #2) Arm 2/3/6 emulator By Bryan McPhail (bmcphail@tendril.co.uk) and Phil Stroffolino (MAME CORE 0.76)
+ *
+ *****************************************************************************
+
+ This file contains everything related to the arm7 core itself, and is presumed
+ to be cpu implementation non-specific, ie, applies to only the core.
+
+ ******************************************************************************/
+
+#pragma once
+
+#ifndef __ARM7CORE_H__
+#define __ARM7CORE_H__
+
+#define ARM7_MMU_ENABLE_HACK 0
+
+/****************************************************************************************************
+ * INTERRUPT LINES/EXCEPTIONS
+ ***************************************************************************************************/
+enum
+{
+ ARM7_IRQ_LINE=0, ARM7_FIRQ_LINE,
+ ARM7_ABORT_EXCEPTION, ARM7_ABORT_PREFETCH_EXCEPTION, ARM7_UNDEFINE_EXCEPTION,
+ ARM7_NUM_LINES
+};
+// Really there's only 1 ABORT Line.. and cpu decides whether it's during data fetch or prefetch, but we let the user specify
+
+/****************************************************************************************************
+ * ARM7 CORE REGISTERS
+ ***************************************************************************************************/
+enum
+{
+ ARM7_PC = 0,
+ ARM7_R0, ARM7_R1, ARM7_R2, ARM7_R3, ARM7_R4, ARM7_R5, ARM7_R6, ARM7_R7,
+ ARM7_R8, ARM7_R9, ARM7_R10, ARM7_R11, ARM7_R12, ARM7_R13, ARM7_R14, ARM7_R15,
+ ARM7_FR8, ARM7_FR9, ARM7_FR10, ARM7_FR11, ARM7_FR12, ARM7_FR13, ARM7_FR14,
+ ARM7_IR13, ARM7_IR14, ARM7_SR13, ARM7_SR14, ARM7_FSPSR, ARM7_ISPSR, ARM7_SSPSR,
+ ARM7_CPSR, ARM7_AR13, ARM7_AR14, ARM7_ASPSR, ARM7_UR13, ARM7_UR14, ARM7_USPSR
+};
+
+/* There are 36 Unique - 32 bit processor registers */
+/* Each mode has 17 registers (except user & system, which have 16) */
+/* This is a list of each *unique* register */
+enum
+{
+ /* All modes have the following */
+ eR0 = 0, eR1, eR2, eR3, eR4, eR5, eR6, eR7,
+ eR8, eR9, eR10, eR11, eR12,
+ eR13, /* Stack Pointer */
+ eR14, /* Link Register (holds return address) */
+ eR15, /* Program Counter */
+ eCPSR, /* Current Status Program Register */
+
+ /* Fast Interrupt - Bank switched registers */
+ eR8_FIQ, eR9_FIQ, eR10_FIQ, eR11_FIQ, eR12_FIQ, eR13_FIQ, eR14_FIQ, eSPSR_FIQ,
+
+ /* IRQ - Bank switched registers */
+ eR13_IRQ, eR14_IRQ, eSPSR_IRQ,
+
+ /* Supervisor/Service Mode - Bank switched registers */
+ eR13_SVC, eR14_SVC, eSPSR_SVC,
+
+ /* Abort Mode - Bank switched registers */
+ eR13_ABT, eR14_ABT, eSPSR_ABT,
+
+ /* Undefined Mode - Bank switched registers */
+ eR13_UND, eR14_UND, eSPSR_UND,
+
+ kNumRegisters
+};
+
+/* Coprocessor-related macros */
+#define COPRO_TLB_BASE cpustate->tlbBase
+#define COPRO_TLB_BASE_MASK 0xffffc000
+#define COPRO_TLB_VADDR_FLTI_MASK 0xfff00000
+#define COPRO_TLB_VADDR_FLTI_MASK_SHIFT 18
+#define COPRO_TLB_VADDR_CSLTI_MASK 0x000ff000
+#define COPRO_TLB_VADDR_CSLTI_MASK_SHIFT 10
+#define COPRO_TLB_VADDR_FSLTI_MASK 0x000ffc00
+#define COPRO_TLB_VADDR_FSLTI_MASK_SHIFT 8
+#define COPRO_TLB_CFLD_ADDR_MASK 0xfffffc00
+#define COPRO_TLB_CFLD_ADDR_MASK_SHIFT 10
+#define COPRO_TLB_SECTION_PAGE_MASK 0xfff00000
+#define COPRO_TLB_LARGE_PAGE_MASK 0xffff0000
+#define COPRO_TLB_SMALL_PAGE_MASK 0xfffff000
+#define COPRO_TLB_TINY_PAGE_MASK 0xfffffc00
+#define COPRO_TLB_UNMAPPED 0
+#define COPRO_TLB_LARGE_PAGE 1
+#define COPRO_TLB_SMALL_PAGE 2
+#define COPRO_TLB_TINY_PAGE 3
+#define COPRO_TLB_COARSE_TABLE 1
+#define COPRO_TLB_SECTION_TABLE 2
+#define COPRO_TLB_FINE_TABLE 3
+
+#define COPRO_CTRL cpustate->control
+#define COPRO_CTRL_MMU_EN 0x00000001
+#define COPRO_CTRL_ADDRFAULT_EN 0x00000002
+#define COPRO_CTRL_DCACHE_EN 0x00000004
+#define COPRO_CTRL_WRITEBUF_EN 0x00000008
+#define COPRO_CTRL_ENDIAN 0x00000080
+#define COPRO_CTRL_SYSTEM 0x00000100
+#define COPRO_CTRL_ROM 0x00000200
+#define COPRO_CTRL_ICACHE_EN 0x00001000
+#define COPRO_CTRL_INTVEC_ADJUST 0x00002000
+#define COPRO_CTRL_ADDRFAULT_EN_SHIFT 1
+#define COPRO_CTRL_DCACHE_EN_SHIFT 2
+#define COPRO_CTRL_WRITEBUF_EN_SHIFT 3
+#define COPRO_CTRL_ENDIAN_SHIFT 7
+#define COPRO_CTRL_SYSTEM_SHIFT 8
+#define COPRO_CTRL_ROM_SHIFT 9
+#define COPRO_CTRL_ICACHE_EN_SHIFT 12
+#define COPRO_CTRL_INTVEC_ADJUST_SHIFT 13
+#define COPRO_CTRL_LITTLE_ENDIAN 0
+#define COPRO_CTRL_BIG_ENDIAN 1
+#define COPRO_CTRL_INTVEC_0 0
+#define COPRO_CTRL_INTVEC_F 1
+#define COPRO_CTRL_MASK 0x0000338f
+
+#define COPRO_DOMAIN_ACCESS_CONTROL cpustate->domainAccessControl
+
+#define COPRO_FAULT_STATUS cpustate->faultStatus
+
+#define COPRO_FAULT_ADDRESS cpustate->faultAddress
+
+#define COPRO_FCSE_PID cpustate->fcsePID
+
+/* Coprocessor Registers */
+#define ARM7COPRO_REGS \
+ UINT32 control; \
+ UINT32 tlbBase; \
+ UINT32 faultStatus; \
+ UINT32 faultAddress; \
+ UINT32 fcsePID; \
+ UINT32 domainAccessControl;
+
+enum
+{
+ eARM_ARCHFLAGS_T = 1, // Thumb present
+ eARM_ARCHFLAGS_E = 2, // extended DSP operations present (only for v5+)
+ eARM_ARCHFLAGS_J = 4, // "Jazelle" (direct execution of Java bytecode)
+ eARM_ARCHFLAGS_MMU = 8, // has on-board MMU (traditional ARM style like the SA1110)
+ eARM_ARCHFLAGS_SA = 16, // StrongARM extensions (enhanced TLB)
+ eARM_ARCHFLAGS_XSCALE = 32, // XScale extensions (CP14, enhanced TLB)
+ eARM_ARCHFLAGS_MODE26 = 64, // supports 26-bit backwards compatibility mode
+};
+
+#define ARM7CORE_REGS \
+ UINT32 sArmRegister[kNumRegisters]; \
+ UINT8 pendingIrq; \
+ UINT8 pendingFiq; \
+ UINT8 pendingAbtD; \
+ UINT8 pendingAbtP; \
+ UINT8 pendingUnd; \
+ UINT8 pendingSwi; \
+ INT32 iCount; \
+ endianness_t endian; \
+ device_irq_callback irq_callback; \
+ legacy_cpu_device *device; \
+ address_space *program; \
+ direct_read_data *direct;
+
+
+/* CPU state struct */
+typedef struct
+{
+ ARM7CORE_REGS // these must be included in your cpu specific register implementation
+ ARM7COPRO_REGS
+
+ UINT8 archRev; // ARM architecture revision (3, 4, and 5 are valid)
+ UINT8 archFlags; // architecture flags
+
+#if ARM7_MMU_ENABLE_HACK
+ UINT32 mmu_enable_addr; // workaround for "MMU is enabled when PA != VA" problem
+#endif
+} arm_state;
+
+/****************************************************************************************************
+ * VARIOUS INTERNAL STRUCS/DEFINES/ETC..
+ ***************************************************************************************************/
+// Mode values come from bit 4-0 of CPSR, but we are ignoring bit 4 here, since bit 4 always = 1 for valid modes
+enum
+{
+ eARM7_MODE_USER = 0x0, // Bit: 4-0 = 10000
+ eARM7_MODE_FIQ = 0x1, // Bit: 4-0 = 10001
+ eARM7_MODE_IRQ = 0x2, // Bit: 4-0 = 10010
+ eARM7_MODE_SVC = 0x3, // Bit: 4-0 = 10011
+ eARM7_MODE_ABT = 0x7, // Bit: 4-0 = 10111
+ eARM7_MODE_UND = 0xb, // Bit: 4-0 = 11011
+ eARM7_MODE_SYS = 0xf // Bit: 4-0 = 11111
+};
+
+#define ARM7_NUM_MODES 0x10
+
+static const int thumbCycles[256] =
+{
+// 0 1 2 3 4 5 6 7 8 9 a b c d e f
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3
+ 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 4
+ 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 5
+ 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, // 6
+ 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, // 7
+ 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, // 8
+ 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, // 9
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // a
+ 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2, 4, 1, 1, // b
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // c
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, // d
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // e
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 // f
+};
+
+/* 17 processor registers are visible at any given time,
+ * banked depending on processor mode.
+ */
+
+static const int sRegisterTable[ARM7_NUM_MODES][18] =
+{
+ { /* USR */
+ eR0, eR1, eR2, eR3, eR4, eR5, eR6, eR7,
+ eR8, eR9, eR10, eR11, eR12,
+ eR13, eR14,
+ eR15, eCPSR // No SPSR in this mode
+ },
+ { /* FIQ */
+ eR0, eR1, eR2, eR3, eR4, eR5, eR6, eR7,
+ eR8_FIQ, eR9_FIQ, eR10_FIQ, eR11_FIQ, eR12_FIQ,
+ eR13_FIQ, eR14_FIQ,
+ eR15, eCPSR, eSPSR_FIQ
+ },
+ { /* IRQ */
+ eR0, eR1, eR2, eR3, eR4, eR5, eR6, eR7,
+ eR8, eR9, eR10, eR11, eR12,
+ eR13_IRQ, eR14_IRQ,
+ eR15, eCPSR, eSPSR_IRQ
+ },
+ { /* SVC */
+ eR0, eR1, eR2, eR3, eR4, eR5, eR6, eR7,
+ eR8, eR9, eR10, eR11, eR12,
+ eR13_SVC, eR14_SVC,
+ eR15, eCPSR, eSPSR_SVC
+ },
+ {0}, {0}, {0}, // values for modes 4,5,6 are not valid
+ { /* ABT */
+ eR0, eR1, eR2, eR3, eR4, eR5, eR6, eR7,
+ eR8, eR9, eR10, eR11, eR12,
+ eR13_ABT, eR14_ABT,
+ eR15, eCPSR, eSPSR_ABT
+ },
+ {0}, {0}, {0}, // values for modes 8,9,a are not valid!
+ { /* UND */
+ eR0, eR1, eR2, eR3, eR4, eR5, eR6, eR7,
+ eR8, eR9, eR10, eR11, eR12,
+ eR13_UND, eR14_UND,
+ eR15, eCPSR, eSPSR_UND
+ },
+ {0}, {0}, {0}, // values for modes c,d, e are not valid!
+ { /* SYS */
+ eR0, eR1, eR2, eR3, eR4, eR5, eR6, eR7,
+ eR8, eR9, eR10, eR11, eR12,
+ eR13, eR14,
+ eR15, eCPSR // No SPSR in this mode
+ }
+};
+
+#define N_BIT 31
+#define Z_BIT 30
+#define C_BIT 29
+#define V_BIT 28
+#define Q_BIT 27
+#define I_BIT 7
+#define F_BIT 6
+#define T_BIT 5 // Thumb mode
+
+#define N_MASK ((UINT32)(1 << N_BIT)) /* Negative flag */
+#define Z_MASK ((UINT32)(1 << Z_BIT)) /* Zero flag */
+#define C_MASK ((UINT32)(1 << C_BIT)) /* Carry flag */
+#define V_MASK ((UINT32)(1 << V_BIT)) /* oVerflow flag */
+#define Q_MASK ((UINT32)(1 << Q_BIT)) /* signed overflow for QADD, MAC */
+#define I_MASK ((UINT32)(1 << I_BIT)) /* Interrupt request disable */
+#define F_MASK ((UINT32)(1 << F_BIT)) /* Fast interrupt request disable */
+#define T_MASK ((UINT32)(1 << T_BIT)) /* Thumb Mode flag */
+
+#define N_IS_SET(pc) ((pc) & N_MASK)
+#define Z_IS_SET(pc) ((pc) & Z_MASK)
+#define C_IS_SET(pc) ((pc) & C_MASK)
+#define V_IS_SET(pc) ((pc) & V_MASK)
+#define Q_IS_SET(pc) ((pc) & Q_MASK)
+#define I_IS_SET(pc) ((pc) & I_MASK)
+#define F_IS_SET(pc) ((pc) & F_MASK)
+#define T_IS_SET(pc) ((pc) & T_MASK)
+
+#define N_IS_CLEAR(pc) (!N_IS_SET(pc))
+#define Z_IS_CLEAR(pc) (!Z_IS_SET(pc))
+#define C_IS_CLEAR(pc) (!C_IS_SET(pc))
+#define V_IS_CLEAR(pc) (!V_IS_SET(pc))
+#define Q_IS_CLEAR(pc) (!Q_IS_SET(pc))
+#define I_IS_CLEAR(pc) (!I_IS_SET(pc))
+#define F_IS_CLEAR(pc) (!F_IS_SET(pc))
+#define T_IS_CLEAR(pc) (!T_IS_SET(pc))
+
+/* Deconstructing an instruction */
+// todo: use these in all places (including dasm file)
+#define INSN_COND ((UINT32)0xf0000000u)
+#define INSN_SDT_L ((UINT32)0x00100000u)
+#define INSN_SDT_W ((UINT32)0x00200000u)
+#define INSN_SDT_B ((UINT32)0x00400000u)
+#define INSN_SDT_U ((UINT32)0x00800000u)
+#define INSN_SDT_P ((UINT32)0x01000000u)
+#define INSN_BDT_L ((UINT32)0x00100000u)
+#define INSN_BDT_W ((UINT32)0x00200000u)
+#define INSN_BDT_S ((UINT32)0x00400000u)
+#define INSN_BDT_U ((UINT32)0x00800000u)
+#define INSN_BDT_P ((UINT32)0x01000000u)
+#define INSN_BDT_REGS ((UINT32)0x0000ffffu)
+#define INSN_SDT_IMM ((UINT32)0x00000fffu)
+#define INSN_MUL_A ((UINT32)0x00200000u)
+#define INSN_MUL_RM ((UINT32)0x0000000fu)
+#define INSN_MUL_RS ((UINT32)0x00000f00u)
+#define INSN_MUL_RN ((UINT32)0x0000f000u)
+#define INSN_MUL_RD ((UINT32)0x000f0000u)
+#define INSN_I ((UINT32)0x02000000u)
+#define INSN_OPCODE ((UINT32)0x01e00000u)
+#define INSN_S ((UINT32)0x00100000u)
+#define INSN_BL ((UINT32)0x01000000u)
+#define INSN_BRANCH ((UINT32)0x00ffffffu)
+#define INSN_SWI ((UINT32)0x00ffffffu)
+#define INSN_RN ((UINT32)0x000f0000u)
+#define INSN_RD ((UINT32)0x0000f000u)
+#define INSN_OP2 ((UINT32)0x00000fffu)
+#define INSN_OP2_SHIFT ((UINT32)0x00000f80u)
+#define INSN_OP2_SHIFT_TYPE ((UINT32)0x00000070u)
+#define INSN_OP2_RM ((UINT32)0x0000000fu)
+#define INSN_OP2_ROTATE ((UINT32)0x00000f00u)
+#define INSN_OP2_IMM ((UINT32)0x000000ffu)
+#define INSN_OP2_SHIFT_TYPE_SHIFT 4
+#define INSN_OP2_SHIFT_SHIFT 7
+#define INSN_OP2_ROTATE_SHIFT 8
+#define INSN_MUL_RS_SHIFT 8
+#define INSN_MUL_RN_SHIFT 12
+#define INSN_MUL_RD_SHIFT 16
+#define INSN_OPCODE_SHIFT 21
+#define INSN_RN_SHIFT 16
+#define INSN_RD_SHIFT 12
+#define INSN_COND_SHIFT 28
+
+#define INSN_COPRO_N ((UINT32) 0x00100000u)
+#define INSN_COPRO_CREG ((UINT32) 0x000f0000u)
+#define INSN_COPRO_AREG ((UINT32) 0x0000f000u)
+#define INSN_COPRO_CPNUM ((UINT32) 0x00000f00u)
+#define INSN_COPRO_OP2 ((UINT32) 0x000000e0u)
+#define INSN_COPRO_OP3 ((UINT32) 0x0000000fu)
+#define INSN_COPRO_N_SHIFT 20
+#define INSN_COPRO_CREG_SHIFT 16
+#define INSN_COPRO_AREG_SHIFT 12
+#define INSN_COPRO_CPNUM_SHIFT 8
+#define INSN_COPRO_OP2_SHIFT 5
+
+#define THUMB_INSN_TYPE ((UINT16)0xf000)
+#define THUMB_COND_TYPE ((UINT16)0x0f00)
+#define THUMB_GROUP4_TYPE ((UINT16)0x0c00)
+#define THUMB_GROUP5_TYPE ((UINT16)0x0e00)
+#define THUMB_GROUP5_RM ((UINT16)0x01c0)
+#define THUMB_GROUP5_RN ((UINT16)0x0038)
+#define THUMB_GROUP5_RD ((UINT16)0x0007)
+#define THUMB_ADDSUB_RNIMM ((UINT16)0x01c0)
+#define THUMB_ADDSUB_RS ((UINT16)0x0038)
+#define THUMB_ADDSUB_RD ((UINT16)0x0007)
+#define THUMB_INSN_ADDSUB ((UINT16)0x0800)
+#define THUMB_INSN_CMP ((UINT16)0x0800)
+#define THUMB_INSN_SUB ((UINT16)0x0800)
+#define THUMB_INSN_IMM_RD ((UINT16)0x0700)
+#define THUMB_INSN_IMM_S ((UINT16)0x0080)
+#define THUMB_INSN_IMM ((UINT16)0x00ff)
+#define THUMB_ADDSUB_TYPE ((UINT16)0x0600)
+#define THUMB_HIREG_OP ((UINT16)0x0300)
+#define THUMB_HIREG_H ((UINT16)0x00c0)
+#define THUMB_HIREG_RS ((UINT16)0x0038)
+#define THUMB_HIREG_RD ((UINT16)0x0007)
+#define THUMB_STACKOP_TYPE ((UINT16)0x0f00)
+#define THUMB_STACKOP_L ((UINT16)0x0800)
+#define THUMB_STACKOP_RD ((UINT16)0x0700)
+#define THUMB_ALUOP_TYPE ((UINT16)0x03c0)
+#define THUMB_BLOP_LO ((UINT16)0x0800)
+#define THUMB_BLOP_OFFS ((UINT16)0x07ff)
+#define THUMB_SHIFT_R ((UINT16)0x0800)
+#define THUMB_SHIFT_AMT ((UINT16)0x07c0)
+#define THUMB_HALFOP_L ((UINT16)0x0800)
+#define THUMB_HALFOP_OFFS ((UINT16)0x07c0)
+#define THUMB_BRANCH_OFFS ((UINT16)0x07ff)
+#define THUMB_LSOP_L ((UINT16)0x0800)
+#define THUMB_LSOP_OFFS ((UINT16)0x07c0)
+#define THUMB_MULTLS ((UINT16)0x0800)
+#define THUMB_MULTLS_BASE ((UINT16)0x0700)
+#define THUMB_RELADDR_SP ((UINT16)0x0800)
+#define THUMB_RELADDR_RD ((UINT16)0x0700)
+#define THUMB_INSN_TYPE_SHIFT 12
+#define THUMB_COND_TYPE_SHIFT 8
+#define THUMB_GROUP4_TYPE_SHIFT 10
+#define THUMB_GROUP5_TYPE_SHIFT 9
+#define THUMB_ADDSUB_TYPE_SHIFT 9
+#define THUMB_INSN_IMM_RD_SHIFT 8
+#define THUMB_STACKOP_TYPE_SHIFT 8
+#define THUMB_HIREG_OP_SHIFT 8
+#define THUMB_STACKOP_RD_SHIFT 8
+#define THUMB_MULTLS_BASE_SHIFT 8
+#define THUMB_RELADDR_RD_SHIFT 8
+#define THUMB_HIREG_H_SHIFT 6
+#define THUMB_HIREG_RS_SHIFT 3
+#define THUMB_ALUOP_TYPE_SHIFT 6
+#define THUMB_SHIFT_AMT_SHIFT 6
+#define THUMB_HALFOP_OFFS_SHIFT 6
+#define THUMB_LSOP_OFFS_SHIFT 6
+#define THUMB_GROUP5_RM_SHIFT 6
+#define THUMB_GROUP5_RN_SHIFT 3
+#define THUMB_GROUP5_RD_SHIFT 0
+#define THUMB_ADDSUB_RNIMM_SHIFT 6
+#define THUMB_ADDSUB_RS_SHIFT 3
+#define THUMB_ADDSUB_RD_SHIFT 0
+
+enum
+{
+ OPCODE_AND, /* 0000 */
+ OPCODE_EOR, /* 0001 */
+ OPCODE_SUB, /* 0010 */
+ OPCODE_RSB, /* 0011 */
+ OPCODE_ADD, /* 0100 */
+ OPCODE_ADC, /* 0101 */
+ OPCODE_SBC, /* 0110 */
+ OPCODE_RSC, /* 0111 */
+ OPCODE_TST, /* 1000 */
+ OPCODE_TEQ, /* 1001 */
+ OPCODE_CMP, /* 1010 */
+ OPCODE_CMN, /* 1011 */
+ OPCODE_ORR, /* 1100 */
+ OPCODE_MOV, /* 1101 */
+ OPCODE_BIC, /* 1110 */
+ OPCODE_MVN /* 1111 */
+};
+
+enum
+{
+ COND_EQ = 0, /* Z equal */
+ COND_NE, /* ~Z not equal */
+ COND_CS, COND_HS = 2, /* C unsigned higher or same */
+ COND_CC, COND_LO = 3, /* ~C unsigned lower */
+ COND_MI, /* N negative */
+ COND_PL, /* ~N positive or zero */
+ COND_VS, /* V overflow */
+ COND_VC, /* ~V no overflow */
+ COND_HI, /* C && ~Z unsigned higher */
+ COND_LS, /* ~C || Z unsigned lower or same */
+ COND_GE, /* N == V greater or equal */
+ COND_LT, /* N != V less than */
+ COND_GT, /* ~Z && N == V greater than */
+ COND_LE, /* Z || N != V less than or equal */
+ COND_AL, /* 1 always */
+ COND_NV /* 0 never */
+};
+
+#define LSL(v, s) ((v) << (s))
+#define LSR(v, s) ((v) >> (s))
+#define ROL(v, s) (LSL((v), (s)) | (LSR((v), 32u - (s))))
+#define ROR(v, s) (LSR((v), (s)) | (LSL((v), 32u - (s))))
+
+/* Convenience Macros */
+#define R15 ARM7REG(eR15)
+#define SPSR 17 // SPSR is always the 18th register in our 0 based array sRegisterTable[][18]
+#define GET_CPSR ARM7REG(eCPSR)
+#define SET_CPSR(v) set_cpsr(cpustate,v)
+#define MODE_FLAG 0xF // Mode bits are 4:0 of CPSR, but we ignore bit 4.
+#define GET_MODE (GET_CPSR & MODE_FLAG)
+#define SIGN_BIT ((UINT32)(1 << 31))
+#define SIGN_BITS_DIFFER(a, b) (((a) ^ (b)) >> 31)
+/* I really don't know why these were set to 16-bit, the thumb registers are still 32-bit ... */
+#define THUMB_SIGN_BIT ((UINT32)(1 << 31))
+#define THUMB_SIGN_BITS_DIFFER(a, b) (((a)^(b)) >> 31)
+
+#define MODE32 (GET_CPSR & 0x10)
+#define MODE26 (!(GET_CPSR & 0x10))
+#define GET_PC (MODE32 ? R15 : R15 & 0x03FFFFFC)
+
+enum
+{
+ ARM7_TLB_NO_ABORT,
+ ARM7_TLB_ABORT_D,
+ ARM7_TLB_ABORT_P
+};
+
+/* At one point I thought these needed to be cpu implementation specific, but they don't.. */
+#define GET_REGISTER(state, reg) GetRegister(state, reg)
+#define SET_REGISTER(state, reg, val) SetRegister(state, reg, val)
+#define ARM7_CHECKIRQ arm7_check_irq_state(cpustate)
+
+extern write32_device_func arm7_coproc_do_callback;
+extern read32_device_func arm7_coproc_rt_r_callback;
+extern write32_device_func arm7_coproc_rt_w_callback;
+extern void arm7_dt_r_callback(arm_state *cpustate, UINT32 insn, UINT32 *prn, UINT32 (*read32)(arm_state *cpustate, UINT32 addr));
+extern void arm7_dt_w_callback(arm_state *cpustate, UINT32 insn, UINT32 *prn, void (*write32)(arm_state *cpustate, UINT32 addr, UINT32 data));
+
+#ifdef UNUSED_DEFINITION
+extern char *(*arm7_dasm_cop_dt_callback)(arm_state *cpustate, char *pBuf, UINT32 opcode, char *pConditionCode, char *pBuf0);
+extern char *(*arm7_dasm_cop_rt_callback)(arm_state *cpustate, char *pBuf, UINT32 opcode, char *pConditionCode, char *pBuf0);
+extern char *(*arm7_dasm_cop_do_callback)(arm_state *cpustate, char *pBuf, UINT32 opcode, char *pConditionCode, char *pBuf0);
+#endif
+
+#endif /* __ARM7CORE_H__ */
diff --git a/trunk/src/emu/cpu/arm7/arm7dasm.c b/trunk/src/emu/cpu/arm7/arm7dasm.c
new file mode 100644
index 00000000000..7c52e8fa0e0
--- /dev/null
+++ b/trunk/src/emu/cpu/arm7/arm7dasm.c
@@ -0,0 +1,1339 @@
+/*****************************************************************************
+ *
+ * arm7dasm.c
+ * Portable ARM7TDMI Core Emulator - Disassembler
+ *
+ * Copyright Steve Ellenoff, all rights reserved.
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * sellenoff@hotmail.com
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ * This work is based on:
+ * #1) 'Atmel Corporation ARM7TDMI (Thumb) Datasheet - January 1999'
+ * #2) Arm 2/3/6 emulator By Bryan McPhail (bmcphail@tendril.co.uk) and Phil Stroffolino (MAME CORE 0.76)
+ *
+ *****************************************************************************/
+/******************************************************************************
+ * Notes:
+ *
+ * Because Co-Processor functions are highly specialized to the actual co-proc
+ * implementation being used, I've setup callback handlers to allow for custom
+ * dasm display of the co-proc functions so that the implementation specific
+ * commands/interpretation can be used. If not used, the default handlers which
+ * implement the ARM7TDMI guideline format is used
+ ******************************************************************************/
+
+#include "emu.h"
+#include "arm7core.h"
+
+static char *WritePadding( char *pBuf, const char *pBuf0 )
+{
+ pBuf0 += 8;
+ while( pBuf<pBuf0 )
+ {
+ *pBuf++ = ' ';
+ }
+ return pBuf;
+}
+
+static char *DasmCoProc_RT( char *pBuf, UINT32 opcode, const char *pConditionCode, const char *pBuf0)
+{
+ /* co processor register transfer */
+ /* xxxx 1110 oooL nnnn dddd cccc ppp1 mmmm */
+ if( opcode&0x00100000 ) //Bit 20 = Load or Store
+ {
+ pBuf += sprintf( pBuf, "MRC" );
+ }
+ else
+ {
+ pBuf += sprintf( pBuf, "MCR" );
+ }
+ pBuf += sprintf( pBuf, "%s", pConditionCode );
+ pBuf = WritePadding( pBuf, pBuf0 );
+ pBuf += sprintf( pBuf, "p%d, %d, R%d, c%d, c%d",
+ (opcode>>8)&0xf, (opcode>>21)&7, (opcode>>12)&0xf, (opcode>>16)&0xf, opcode&0xf );
+ if((opcode>>5)&7) pBuf += sprintf( pBuf, ", %d",(opcode>>5)&7);
+ return pBuf;
+}
+
+static char *DasmCoProc_DT( char *pBuf, UINT32 opcode, const char *pConditionCode, const char *pBuf0 )
+{
+ /* co processor data transfer */
+ /* xxxx 111P UNWL nnnn dddd pppp oooooooo */
+ //todo: test this on valid instructions
+
+ pBuf += sprintf(pBuf, "%s%s",(opcode&0x00100000)?"LDC":"STC",pConditionCode); //Bit 20 = 1 for Load, 0 for Store
+ //Long Operation
+ if(opcode & 0x400000) pBuf += sprintf(pBuf, "L");
+ pBuf = WritePadding( pBuf, pBuf0 );
+
+ //P# & CD #
+ pBuf += sprintf(pBuf, "p%d, c%d, ",(opcode>>8)&0x0f,(opcode>>12)&0x0f);
+
+ //Base Register (Rn)
+ pBuf += sprintf(pBuf, "[R%d%s",(opcode>>16)&0x0f,(opcode&0x1000000)?"":"]"); //If Bit 24 = 1, Pre-increment, otherwise, Post increment so close brace
+
+ //immediate value ( 8 bit value is << 2 according to manual )
+ if(opcode & 0xff) pBuf += sprintf(pBuf, ",%s#$%x",(opcode&0x800000)?"":"-",(opcode & 0xff)<<2);
+
+ //Pre-Inc brace & Write back
+ pBuf += sprintf(pBuf, "%s%s",(opcode&0x1000000)?"]":"",(opcode&0x200000)?"{!}":"");
+ return pBuf;
+}
+
+static char *DasmCoProc_DO( char *pBuf, UINT32 opcode, const char *pConditionCode, const char *pBuf0 )
+{
+ /* co processor data operation */
+ /* xxxx 1110 oooo nnnn dddd cccc ppp0 mmmm */
+ pBuf += sprintf( pBuf, "CDP" );
+ pBuf += sprintf( pBuf, "%s", pConditionCode );
+ pBuf = WritePadding( pBuf, pBuf0 );
+ //p#,CPOpc,cd,cn,cm
+ pBuf += sprintf( pBuf, "p%d, %d, c%d, c%d, c%d",
+ (opcode>>8)&0xf, (opcode>>20)&0xf, (opcode>>12)&0xf, (opcode>>16)&0xf, opcode&0xf );
+ if((opcode>>5)&7) pBuf += sprintf( pBuf, ", %d",(opcode>>5)&7);
+ return pBuf;
+}
+
+static char *WriteImmediateOperand( char *pBuf, UINT32 opcode )
+{
+ /* rrrrbbbbbbbb */
+ UINT32 imm;
+ int r;
+
+ imm = opcode&0xff;
+ r = ((opcode>>8)&0xf)*2;
+ imm = (imm>>r)|(imm<<(32-r));
+ pBuf += sprintf( pBuf, ", #$%x", imm );
+ return pBuf;
+}
+
+static char *WriteDataProcessingOperand( char *pBuf, UINT32 opcode, int printOp0, int printOp1, int printOp2 )
+{
+ /* ccccctttmmmm */
+ static const char *const pRegOp[4] = { "LSL","LSR","ASR","ROR" };
+
+ if (printOp0)
+ pBuf += sprintf(pBuf,"R%d, ", (opcode>>12)&0xf);
+ if (printOp1)
+ pBuf += sprintf(pBuf,"R%d, ", (opcode>>16)&0xf);
+
+ /* Immediate Op2 */
+ if( opcode&0x02000000 )
+ return WriteImmediateOperand(pBuf-2,opcode);
+
+ /* Register Op2 */
+ if (printOp2)
+//SJE: pBuf += sprintf(pBuf,"R%d, ", (opcode>>0)&0xf);
+ pBuf += sprintf(pBuf,"R%d ", (opcode>>0)&0xf);
+
+ //SJE: ignore if LSL#0 for register shift
+ if( ((opcode&0x2000000) == 0) && (((opcode>>4) & 0xff)==0) )
+ return pBuf;
+
+ pBuf += sprintf(pBuf, ",%s ", pRegOp[(opcode>>5)&3] );
+ //SJE: pBuf += sprintf(pBuf, "%s ", pRegOp[(opcode>>5)&3] );
+
+ if( opcode&0x10 ) /* Shift amount specified in bottom bits of RS */
+ {
+ pBuf += sprintf( pBuf, "R%d", (opcode>>8)&0xf );
+ }
+ else /* Shift amount immediate 5 bit unsigned integer */
+ {
+ int c=(opcode>>7)&0x1f;
+ if( c==0 ) c = 32;
+ pBuf += sprintf( pBuf, "#%d", c );
+ }
+ return pBuf;
+}
+
+static char *WriteRegisterOperand1( char *pBuf, UINT32 opcode )
+{
+ /* ccccctttmmmm */
+ static const char *const pRegOp[4] = { "LSL","LSR","ASR","ROR" };
+
+ pBuf += sprintf(
+ pBuf,
+ ", R%d", /* Operand 1 register, Operand 2 register, shift type */
+ (opcode>> 0)&0xf);
+
+ //check for LSL 0
+ if( (((opcode>>5)&3)==0) && (((opcode>>7)&0xf)==0) )
+ return pBuf;
+ else
+ //Add rotation type
+ pBuf += sprintf(pBuf," %s ",pRegOp[(opcode>>5)&3]);
+
+ if( opcode&0x10 ) /* Shift amount specified in bottom bits of RS */
+ {
+ pBuf += sprintf( pBuf, "R%d", (opcode>>7)&0xf );
+ }
+ else /* Shift amount immediate 5 bit unsigned integer */
+ {
+ int c=(opcode>>7)&0x1f;
+ if( c==0 ) c = 32;
+ pBuf += sprintf( pBuf, "#%d", c );
+ }
+ return pBuf;
+} /* WriteRegisterOperand */
+
+
+static char *WriteBranchAddress( char *pBuf, UINT32 pc, UINT32 opcode )
+{
+ opcode &= 0x00ffffff;
+ if( opcode&0x00800000 )
+ {
+ opcode |= 0xff000000; /* sign-extend */
+ }
+ pc += 8+4*opcode;
+ sprintf( pBuf, "$%x", pc );
+ return pBuf;
+} /* WriteBranchAddress */
+
+static UINT32 arm7_disasm( char *pBuf, UINT32 pc, UINT32 opcode )
+{
+ const char *pBuf0;
+
+ static const char *const pConditionCodeTable[16] =
+ {
+ "EQ","NE","CS","CC",
+ "MI","PL","VS","VC",
+ "HI","LS","GE","LT",
+ "GT","LE","","NV"
+ };
+ static const char *const pOperation[16] =
+ {
+ "AND","EOR","SUB","RSB",
+ "ADD","ADC","SBC","RSC",
+ "TST","TEQ","CMP","CMN",
+ "ORR","MOV","BIC","MVN"
+ };
+ const char *pConditionCode;
+ UINT32 dasmflags = 0;
+
+ pConditionCode= pConditionCodeTable[opcode>>28];
+ pBuf0 = pBuf;
+
+ if( (opcode&0x0ffffff0)==0x012fff10 ) { //bits 27-4 == 000100101111111111110001
+ /* Branch and Exchange (BX) */
+ pBuf += sprintf( pBuf, "B");
+ pBuf += sprintf( pBuf, "%sX", pConditionCode );
+ pBuf = WritePadding( pBuf, pBuf0 );
+ pBuf += sprintf( pBuf, "R%d",(opcode&0xf));
+ if ((opcode & 0x0f) == 14)
+ dasmflags = DASMFLAG_STEP_OUT;
+ }
+ else if ((opcode & 0x0ff000f0) == 0x01600010) // CLZ - v5
+ {
+ pBuf += sprintf(pBuf, "CLZ");
+ pBuf = WritePadding( pBuf, pBuf0 );
+ pBuf += sprintf(pBuf, "R%d, R%d", (opcode>>12)&0xf, opcode&0xf);
+ }
+ else if ((opcode & 0x0ff000f0) == 0x01000050) // QADD - v5
+ {
+ pBuf += sprintf(pBuf, "QADD");
+ pBuf = WritePadding( pBuf, pBuf0 );
+ pBuf += sprintf(pBuf, "R%d, R%d, R%d", (opcode>>12)&0xf, opcode&0xf, (opcode>>16)&0xf);
+ }
+ else if ((opcode & 0x0ff000f0) == 0x01400050) // QDADD - v5
+ {
+ pBuf += sprintf(pBuf, "QDADD");
+ pBuf = WritePadding( pBuf, pBuf0 );
+ pBuf += sprintf(pBuf, "R%d, R%d, R%d", (opcode>>12)&0xf, opcode&0xf, (opcode>>16)&0xf);
+ }
+ else if ((opcode & 0x0ff000f0) == 0x01200050) // QSUB - v5
+ {
+ pBuf += sprintf(pBuf, "QSUB");
+ pBuf = WritePadding( pBuf, pBuf0 );
+ pBuf += sprintf(pBuf, "R%d, R%d, R%d", (opcode>>12)&0xf, opcode&0xf, (opcode>>16)&0xf);
+ }
+ else if ((opcode & 0x0ff000f0) == 0x01600050) // QDSUB - v5
+ {
+ pBuf += sprintf(pBuf, "QDSUB");
+ pBuf = WritePadding( pBuf, pBuf0 );
+ pBuf += sprintf(pBuf, "R%d, R%d, R%d", (opcode>>12)&0xf, opcode&0xf, (opcode>>16)&0xf);
+ }
+ else if ((opcode & 0x0ff00090) == 0x01000080) // SMLAxy - v5
+ {
+ pBuf += sprintf(pBuf, "SMLA%c%c", (opcode&0x20) ? 'T' : 'B', (opcode&0x40) ? 'T' : 'B');
+ pBuf = WritePadding( pBuf, pBuf0 );
+ pBuf += sprintf(pBuf, "R%d, R%d, R%d, R%d", (opcode>>16)&0xf, (opcode>>12)&0xf, opcode&0xf, (opcode>>8)&0xf);
+ }
+ else if ((opcode & 0x0ff00090) == 0x01400080) // SMLALxy - v5
+ {
+ pBuf += sprintf(pBuf, "SMLAL%c%c", (opcode&0x20) ? 'T' : 'B', (opcode&0x40) ? 'T' : 'B');
+ pBuf = WritePadding( pBuf, pBuf0 );
+ pBuf += sprintf(pBuf, "R%d, R%d, R%d, R%d", (opcode>>16)&0xf, (opcode>>12)&0xf, opcode&0xf, (opcode>>8)&0xf);
+ }
+ else if ((opcode & 0x0ff00090) == 0x01600080) // SMULxy - v5
+ {
+ pBuf += sprintf(pBuf, "SMUL%c%c", (opcode&0x20) ? 'T' : 'B', (opcode&0x40) ? 'T' : 'B');
+ pBuf = WritePadding( pBuf, pBuf0 );
+ pBuf += sprintf(pBuf, "R%d, R%d, R%d", (opcode>>16)&0xf, opcode&0xf, (opcode>>12)&0xf);
+ }
+ else if ((opcode & 0x0ff000b0) == 0x012000a0) // SMULWy - v5
+ {
+ pBuf += sprintf(pBuf, "SMULW%c", (opcode&0x40) ? 'T' : 'B');
+ pBuf = WritePadding( pBuf, pBuf0 );
+ pBuf += sprintf(pBuf, "R%d, R%d, R%d", (opcode>>16)&0xf, opcode&0xf, (opcode>>8)&0xf);
+ }
+ else if ((opcode & 0x0ff000b0) == 0x01200080) // SMLAWy - v5
+ {
+ pBuf += sprintf(pBuf, "SMLAW%c", (opcode&0x40) ? 'T' : 'B');
+ pBuf = WritePadding( pBuf, pBuf0 );
+ pBuf += sprintf(pBuf, "R%d, R%d, R%d, R%d", (opcode>>16)&0xf, opcode&0xf, (opcode>>8)&0xf, (opcode>>12)&0xf);
+ }
+ else if( (opcode&0x0e000000)==0 && (opcode&0x80) && (opcode&0x10) ) //bits 27-25 == 000, bit 7=1, bit 4=1
+ {
+ /* multiply or swap or half word data transfer */
+ if(opcode&0x60)
+ { //bits = 6-5 != 00
+ /* half word data transfer */
+ if (((opcode & 0x60) == 0x40) && !(opcode & 0x100000)) // bit 20 = 0, bits 5&6 = 10 is ARMv5 LDRD
+ {
+ pBuf += sprintf(pBuf, "LDRD%s", pConditionCode);
+ }
+ else if (((opcode & 0x60) == 0x60) && !(opcode & 0x100000)) // bit 20 = 0, bits 5&6 = 11 is ARMv5 STRD
+ {
+ pBuf += sprintf(pBuf, "STRD%s", pConditionCode);
+ }
+ else
+ {
+ pBuf += sprintf(pBuf, "%s%s",(opcode&0x00100000)?"LDR":"STR",pConditionCode); //Bit 20 = 1 for Load, 0 for Store
+
+ //Signed? (if not, always unsigned half word)
+ if(opcode&0x40)
+ {
+ pBuf += sprintf(pBuf, "%s",(opcode&0x20)?"SH":"SB"); //Bit 5 = 1 for Half Word, 0 for Byte
+ }
+ else
+ {
+ pBuf += sprintf(pBuf, "H");
+ }
+ }
+
+ pBuf = WritePadding( pBuf, pBuf0 );
+
+ //Dest Register
+ pBuf += sprintf(pBuf, "R%d, ",(opcode>>12)&0x0f);
+ //Base Register
+ pBuf += sprintf(pBuf, "[R%d%s",(opcode>>16)&0x0f,(opcode&0x1000000)?"":"]"); //If Bit 24 = 1, Pre-increment, otherwise, Post increment so close brace
+
+ //Immediate or Register Offset?
+ if(opcode&0x400000) { //Bit 22 - 1 = immediate, 0 = register
+ //immediate ( imm. value in high nibble (bits 8-11) and lo nibble (bit 0-3) )
+ pBuf += sprintf(pBuf, ",%s#$%x",(opcode&0x800000)?"":"-",( (((opcode>>8)&0x0f)<<4) | (opcode&0x0f)));
+ }
+ else {
+ //register
+ pBuf += sprintf(pBuf, ",%sR%d",(opcode&0x800000)?"":"-",(opcode & 0x0f));
+ }
+
+ //Pre-Inc brace & Write back
+ pBuf += sprintf(pBuf, "%s%s",(opcode&0x1000000)?"]":"",(opcode&0x200000)?"{!}":"");
+ }
+ else {
+ if(opcode&0x01000000) { //bit 24 = 1
+ /* swap */
+ //todo: Test on valid instructions
+ /* xxxx 0001 0B00 nnnn dddd 0000 1001 mmmm */
+ pBuf += sprintf( pBuf, "SWP" );
+ pBuf += sprintf( pBuf, "%s%s", pConditionCode, (opcode & 0x400000)?"B":"" ); //Bit 22 = Byte/Word selection
+ //Rd, Rm, [Rn]
+ pBuf += sprintf( pBuf, "R%d, R%d, [R%d]",
+ (opcode>>12)&0xf, opcode&0xf, (opcode>>16)&0xf );
+ }
+ else {
+ /* multiply or multiply long */
+
+ if( opcode&0x800000 ) //Bit 23 = 1 for Multiply Long
+ {
+ /* Multiply Long */
+ /* xxxx0001 UAShhhhllllnnnn1001mmmm */
+
+ /* Signed? */
+ if( opcode&0x00400000 )
+ pBuf += sprintf( pBuf, "S" );
+ else
+ pBuf += sprintf( pBuf, "U" );
+
+ /* Multiply & Accumulate? */
+ if( opcode&0x00200000 )
+ {
+ pBuf += sprintf( pBuf, "MLAL" );
+ }
+ else
+ {
+ pBuf += sprintf( pBuf, "MULL" );
+ }
+ pBuf += sprintf( pBuf, "%s", pConditionCode );
+
+ /* Set Status Flags */
+ if( opcode&0x00100000 )
+ {
+ *pBuf++ = 'S';
+ }
+ pBuf = WritePadding( pBuf, pBuf0 );
+
+ //Format is RLo,RHi,Rm,Rs
+ pBuf += sprintf( pBuf,
+ "R%d, R%d, R%d, R%d",
+ (opcode>>12)&0xf,
+ (opcode>>16)&0xf,
+ (opcode&0xf),
+ (opcode>>8)&0xf);
+ }
+ else
+ {
+ /* Multiply */
+ /* xxxx0000 00ASdddd nnnnssss 1001mmmm */
+
+ /* Multiply & Accumulate? */
+ if( opcode&0x00200000 )
+ {
+ pBuf += sprintf( pBuf, "MLA" );
+ }
+ /* Multiply */
+ else
+ {
+ pBuf += sprintf( pBuf, "MUL" );
+ }
+ pBuf += sprintf( pBuf, "%s", pConditionCode );
+ if( opcode&0x00100000 )
+ {
+ *pBuf++ = 'S';
+ }
+ pBuf = WritePadding( pBuf, pBuf0 );
+
+ pBuf += sprintf( pBuf,
+ "R%d, R%d, R%d",
+ (opcode>>16)&0xf,
+ (opcode&0xf),
+ (opcode>>8)&0xf );
+
+ if( opcode&0x00200000 )
+ {
+ pBuf += sprintf( pBuf, ", R%d", (opcode>>12)&0xf );
+ }
+ }
+ }
+ }
+ }
+ else if( (opcode&0x0c000000)==0 ) //bits 27-26 == 00 - This check can only exist properly after Multiplication check above
+ {
+
+ /* Data Processing OR PSR Transfer */
+
+ //SJE: check for MRS & MSR ( S bit must be clear, and bit 24,23 = 10 )
+ if( ((opcode&0x00100000)==0) && ((opcode&0x01800000)==0x01000000) ) {
+ char strpsr[6];
+ sprintf(strpsr, "%s",(opcode&0x400000)?"SPSR":"CPSR");
+
+ //MSR ( bit 21 set )
+ if( (opcode&0x00200000) ) {
+ pBuf += sprintf(pBuf, "MSR%s",pConditionCode );
+ //Flag Bits Only? (Bit 16 Clear)
+ if( (opcode&0x10000)==0) pBuf += sprintf(pBuf, "F");
+ pBuf = WritePadding( pBuf, pBuf0 );
+ pBuf += sprintf(pBuf, "%s,",strpsr);
+ WriteDataProcessingOperand(pBuf, opcode, (opcode&0x02000000)?1:0, 0, 1);
+ }
+ //MRS ( bit 21 clear )
+ else {
+ pBuf += sprintf(pBuf, "MRS%s",pConditionCode );
+ pBuf = WritePadding( pBuf, pBuf0 );
+ pBuf += sprintf(pBuf, "R%d,",(opcode>>12)&0x0f);
+ pBuf += sprintf(pBuf, "%s",strpsr);
+ }
+ }
+ else {
+ /* Data Processing */
+ /* xxxx001a aaaSnnnn ddddrrrr bbbbbbbb */
+ /* xxxx000a aaaSnnnn ddddcccc ctttmmmm */
+ int op=(opcode>>21)&0xf;
+ pBuf += sprintf(
+ pBuf, "%s%s",
+ pOperation[op],
+ pConditionCode );
+
+ //SJE: corrected S-Bit bug here
+ //if( (opcode&0x01000000) )
+ if( (opcode&0x0100000) )
+ {
+ *pBuf++ = 'S';
+ }
+
+ pBuf = WritePadding( pBuf, pBuf0 );
+
+ switch (op) {
+ case 0x00:
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ case 0x04:
+ case 0x05:
+ case 0x06:
+ case 0x07:
+ case 0x0c:
+ case 0x0e:
+ WriteDataProcessingOperand(pBuf, opcode, 1, 1, 1);
+ break;
+ case 0x08:
+ case 0x09:
+ case 0x0a:
+ case 0x0b:
+ WriteDataProcessingOperand(pBuf, opcode, 0, 1, 1);
+ break;
+ case 0x0d:
+ /* look for mov pc,lr */
+ if (((opcode >> 12) & 0x0f) == 15 && ((opcode >> 0) & 0x0f) == 14 && (opcode & 0x02000000) == 0)
+ dasmflags = DASMFLAG_STEP_OUT;
+ case 0x0f:
+ WriteDataProcessingOperand(pBuf, opcode, 1, 0, 1);
+ break;
+ }
+ }
+ }
+ else if( (opcode&0x0c000000)==0x04000000 ) //bits 27-26 == 01
+ {
+ UINT32 rn = 0;
+ UINT32 rnv = 0;
+
+ /* Data Transfer */
+
+ /* xxxx010P UBWLnnnn ddddoooo oooooooo Immediate form */
+ /* xxxx011P UBWLnnnn ddddcccc ctt0mmmm Register form */
+ if( opcode&0x00100000 )
+ {
+ pBuf += sprintf( pBuf, "LDR" );
+ }
+ else
+ {
+ pBuf += sprintf( pBuf, "STR" );
+ }
+ pBuf += sprintf( pBuf, "%s", pConditionCode );
+
+ if( opcode&0x00400000 )
+ {
+ pBuf += sprintf( pBuf, "B" );
+ }
+
+ if( opcode&0x00200000 )
+ {
+ /* writeback addr */
+ if( opcode&0x01000000 )
+ {
+ /* pre-indexed addressing */
+ pBuf += sprintf( pBuf, "!" );
+ }
+ else
+ {
+ /* post-indexed addressing */
+ pBuf += sprintf( pBuf, "T" );
+ }
+ }
+
+ pBuf = WritePadding( pBuf, pBuf0 );
+ pBuf += sprintf( pBuf, "R%d, [R%d",
+ (opcode>>12)&0xf, (opcode>>16)&0xf );
+
+ //grab value of pc if used as base register
+ rn = (opcode>>16)&0xf;
+ if(rn==15) rnv = pc+8;
+
+ if( opcode&0x02000000 )
+ {
+ /* register form */
+ pBuf += sprintf( pBuf, "%s",(opcode&0x01000000)?"":"]" );
+ pBuf = WriteRegisterOperand1( pBuf, opcode );
+ pBuf += sprintf( pBuf, "%s",(opcode&0x01000000)?"]":"" );
+ }
+ else
+ {
+ /* immediate form */
+ pBuf += sprintf( pBuf, "%s",(opcode&0x01000000)?"":"]" );
+ //hide zero offsets
+ if(opcode&0xfff) {
+ if( opcode&0x00800000 )
+ {
+ pBuf += sprintf( pBuf, ", #$%x", opcode&0xfff );
+ rnv += (rnv)?opcode&0xfff:0;
+ }
+ else
+ {
+ pBuf += sprintf( pBuf, ", -#$%x", opcode&0xfff );
+ rnv -= (rnv)?opcode&0xfff:0;
+ }
+ }
+ pBuf += sprintf( pBuf, "%s",(opcode&0x01000000)?"]":"" );
+ //show where the read will occur if we found a value
+ if(rnv) pBuf += sprintf( pBuf, " (%x)",rnv);
+ }
+ }
+ else if( (opcode&0x0e000000) == 0x08000000 ) //bits 27-25 == 100
+ {
+ /* xxxx100P USWLnnnn llllllll llllllll */
+ /* Block Data Transfer */
+
+ if( opcode&0x00100000 )
+ {
+ pBuf += sprintf( pBuf, "LDM" );
+ }
+ else
+ {
+ pBuf += sprintf( pBuf, "STM" );
+ }
+ pBuf += sprintf( pBuf, "%s", pConditionCode );
+
+ if( opcode&0x01000000 )
+ {
+ pBuf += sprintf( pBuf, "P" );
+ }
+ if( opcode&0x00800000 )
+ {
+ pBuf += sprintf( pBuf, "U" );
+ }
+ if( opcode&0x00400000 )
+ {
+ pBuf += sprintf( pBuf, "^" );
+ }
+ if( opcode&0x00200000 )
+ {
+ pBuf += sprintf( pBuf, "W" );
+ }
+
+ pBuf = WritePadding( pBuf, pBuf0 );
+ pBuf += sprintf( pBuf, "[R%d], {",(opcode>>16)&0xf);
+
+ {
+ int j=0,last=0,found=0;
+ for (j=0; j<16; j++) {
+ if (opcode&(1<<j) && found==0) {
+ found=1;
+ last=j;
+ }
+ else if ((opcode&(1<<j))==0 && found) {
+ if (last==j-1)
+ pBuf += sprintf( pBuf, " R%d,",last);
+ else
+ pBuf += sprintf( pBuf, " R%d-R%d,",last,j-1);
+ found=0;
+ }
+ }
+ if (found && last==15)
+ pBuf += sprintf( pBuf, " R15,");
+ else if (found)
+ pBuf += sprintf( pBuf, " R%d-R%d,",last,15);
+ }
+
+ pBuf--;
+ pBuf += sprintf( pBuf, " }");
+ }
+ else if( (opcode&0x0e000000)==0x0a000000 ) //bits 27-25 == 101
+ {
+ /* branch instruction */
+ /* xxxx101L oooooooo oooooooo oooooooo */
+ if( opcode&0x01000000 )
+ {
+ pBuf += sprintf( pBuf, "BL" );
+ dasmflags = DASMFLAG_STEP_OVER;
+ }
+ else
+ {
+ pBuf += sprintf( pBuf, "B" );
+ }
+
+ pBuf += sprintf( pBuf, "%s", pConditionCode );
+
+ pBuf = WritePadding( pBuf, pBuf0 );
+
+ pBuf = WriteBranchAddress( pBuf, pc, opcode );
+ }
+ else if( (opcode&0x0e000000)==0x0c000000 ) //bits 27-25 == 110
+ {
+ /* co processor data transfer */
+ DasmCoProc_DT(pBuf,opcode,(char*)pConditionCode,(char*)pBuf0);
+ }
+ else if( (opcode&0x0f000000)==0x0e000000 ) //bits 27-24 == 1110
+ {
+ /* co processor data operation or register transfer */
+
+ //Register Transfer
+ if(opcode&0x10)
+ {
+ DasmCoProc_RT(pBuf,opcode,pConditionCode,pBuf0);
+ }
+ //Data Op
+ else
+ {
+ DasmCoProc_DO(pBuf,opcode,pConditionCode,pBuf0);
+ }
+ }
+ else if( (opcode&0x0f000000) == 0x0f000000 ) //bits 27-24 == 1111
+ {
+ /* Software Interrupt */
+ pBuf += sprintf( pBuf, "SWI%s $%x",
+ pConditionCode,
+ opcode&0x00ffffff );
+ dasmflags = DASMFLAG_STEP_OVER;
+ }
+ else
+ {
+ pBuf += sprintf( pBuf, "Undefined" );
+ }
+ return dasmflags | DASMFLAG_SUPPORTED;
+}
+
+static UINT32 thumb_disasm( char *pBuf, UINT32 pc, UINT16 opcode )
+{
+ const char *pBuf0;
+ UINT32 dasmflags = 0;
+
+// UINT32 readword;
+ UINT32 addr;
+ UINT32 rm, rn, rs, rd, op2, imm;//, rrs;
+ INT32 offs;
+
+ pBuf0 = pBuf;
+ pBuf = WritePadding( pBuf, pBuf0 );
+
+
+ switch( ( opcode & THUMB_INSN_TYPE ) >> THUMB_INSN_TYPE_SHIFT )
+ {
+ case 0x0: /* Logical shifting */
+ if( opcode & THUMB_SHIFT_R ) /* Shift right */
+ {
+ rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT;
+ offs = ( opcode & THUMB_SHIFT_AMT ) >> THUMB_SHIFT_AMT_SHIFT;
+ pBuf += sprintf( pBuf, "LSR R%d, R%d, %d", rd, rs, offs);
+ }
+ else /* Shift left */
+ {
+ rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT;
+ offs = ( opcode & THUMB_SHIFT_AMT ) >> THUMB_SHIFT_AMT_SHIFT;
+ pBuf += sprintf( pBuf, "LSL R%d, R%d, %d", rd, rs, offs);
+ }
+ break;
+ case 0x1: /* Arithmetic */
+ if( opcode & THUMB_INSN_ADDSUB )
+ {
+ switch( ( opcode & THUMB_ADDSUB_TYPE ) >> THUMB_ADDSUB_TYPE_SHIFT )
+ {
+ case 0x0: /* ADD Rd, Rs, Rn */
+ rn = ( opcode & THUMB_ADDSUB_RNIMM ) >> THUMB_ADDSUB_RNIMM_SHIFT;
+ rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT;
+ pBuf += sprintf( pBuf, "ADD R%d, R%d, R%d", rd, rs, rn );
+ break;
+ case 0x1: /* SUB Rd, Rs, Rn */
+ rn = ( opcode & THUMB_ADDSUB_RNIMM ) >> THUMB_ADDSUB_RNIMM_SHIFT;
+ rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT;
+ pBuf += sprintf( pBuf, "SUB R%d, R%d, R%d", rd, rs, rn );
+ break;
+ case 0x2: /* ADD Rd, Rs, #imm */
+ imm = ( opcode & THUMB_ADDSUB_RNIMM ) >> THUMB_ADDSUB_RNIMM_SHIFT;
+ rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT;
+ pBuf += sprintf( pBuf, "ADD R%d, R%d, #%d", rd, rs, imm );
+ break;
+ case 0x3: /* SUB Rd, Rs, #imm */
+ imm = ( opcode & THUMB_ADDSUB_RNIMM ) >> THUMB_ADDSUB_RNIMM_SHIFT;
+ rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT;
+ pBuf += sprintf( pBuf, "SUB R%d, R%d, #%d", rd, rs, imm );
+ break;
+ default:
+ sprintf( pBuf, "INVALID %04x", opcode);
+ break;
+ }
+ }
+ else
+ {
+ rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT;
+ offs = ( opcode & THUMB_SHIFT_AMT ) >> THUMB_SHIFT_AMT_SHIFT;
+ pBuf += sprintf( pBuf, "ASR R%d, R%d, %d", rd, rs, offs);
+ }
+ break;
+ case 0x2: /* CMP / MOV */
+ if( opcode & THUMB_INSN_CMP )
+ {
+ rn = ( opcode & THUMB_INSN_IMM_RD ) >> THUMB_INSN_IMM_RD_SHIFT;
+ op2 = ( opcode & THUMB_INSN_IMM );
+ pBuf += sprintf( pBuf, "CMP R%d, %02x", rn, op2 );
+ }
+ else
+ {
+ rd = ( opcode & THUMB_INSN_IMM_RD ) >> THUMB_INSN_IMM_RD_SHIFT;
+ op2 = ( opcode & THUMB_INSN_IMM );
+ pBuf += sprintf( pBuf, "MOV R%d, %02x", rd, op2 );
+ }
+ break;
+ case 0x3: /* ADD/SUB immediate */
+ if( opcode & THUMB_INSN_SUB ) /* SUB Rd, #Offset8 */
+ {
+ rn = ( opcode & THUMB_INSN_IMM_RD ) >> THUMB_INSN_IMM_RD_SHIFT;
+ op2 = ( opcode & THUMB_INSN_IMM );
+ pBuf += sprintf( pBuf, "SUB R%d, %02x", rn, op2 ); // fixed, rd -> rn
+ }
+ else /* ADD Rd, #Offset8 */
+ {
+ rn = ( opcode & THUMB_INSN_IMM_RD ) >> THUMB_INSN_IMM_RD_SHIFT;
+ op2 = opcode & THUMB_INSN_IMM;
+ pBuf += sprintf( pBuf, "ADD R%d, %02x", rn, op2 );
+ }
+ break;
+ case 0x4: /* Rd & Rm instructions */
+ switch( ( opcode & THUMB_GROUP4_TYPE ) >> THUMB_GROUP4_TYPE_SHIFT )
+ {
+ case 0x0:
+ switch( ( opcode & THUMB_ALUOP_TYPE ) >> THUMB_ALUOP_TYPE_SHIFT )
+ {
+ case 0x0: /* AND Rd, Rs */
+ rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT;
+ pBuf += sprintf( pBuf, "AND R%d, R%d", rd, rs );
+ break;
+ case 0x1: /* EOR Rd, Rs */
+ rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT;
+ pBuf += sprintf( pBuf, "EOR R%d, R%d", rd, rs );
+ break;
+ case 0x2: /* LSL Rd, Rs */
+ rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT;
+ pBuf += sprintf( pBuf, "LSL R%d, R%d", rd, rs );
+ break;
+ case 0x3: /* LSR Rd, Rs */
+ rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT;
+ pBuf += sprintf( pBuf, "LSR R%d, R%d", rd, rs );
+ break;
+ case 0x4: /* ASR Rd, Rs */
+ rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT;
+ pBuf += sprintf( pBuf, "ASR R%d, R%d", rd, rs );
+ break;
+ case 0x5: /* ADC Rd, Rs */
+ rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT;
+ pBuf += sprintf( pBuf, "ADC R%d, R%d", rd, rs );
+ break;
+ case 0x6: /* SBC Rd, Rs */
+ rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT;
+ pBuf += sprintf( pBuf, "SBC R%d, R%d", rd, rs );
+ break;
+ case 0x7: /* ROR Rd, Rs */
+ rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT;
+ pBuf += sprintf( pBuf, "ROR R%d, R%d", rd, rs );
+ break;
+ case 0x8: /* TST Rd, Rs */
+ rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT;
+ pBuf += sprintf( pBuf, "TST R%d, R%d", rd, rs );
+ break;
+ case 0x9: /* NEG Rd, Rs */
+ rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT;
+ pBuf += sprintf( pBuf, "NEG R%d, R%d", rd, rs );
+ break;
+ case 0xa: /* CMP Rd, Rs */
+ rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT;
+ pBuf += sprintf( pBuf, "CMP R%d, R%d", rd, rs );
+ break;
+ case 0xb: /* CMN Rd, Rs - check flags, add dasm */
+ rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT;
+ pBuf += sprintf( pBuf, "CMN R%d, R%d", rd, rs );
+ break;
+ case 0xc: /* ORR Rd, Rs */
+ rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT;
+ pBuf += sprintf( pBuf, "ORR R%d, R%d", rd, rs );
+ break;
+ case 0xd: /* MUL Rd, Rs */
+ rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT;
+ pBuf += sprintf( pBuf, "MUL R%d, R%d", rd, rs );
+ break;
+ case 0xe: /* MUL Rd, Rs */
+ rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT;
+ pBuf += sprintf( pBuf, "BIC R%d, R%d", rd, rs );
+ break;
+ case 0xf: /* MVN Rd, Rs */
+ rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT;
+ pBuf += sprintf( pBuf, "MVN R%d, R%d", rd, rs );
+ break;
+ default:
+ sprintf( pBuf, "INVALID %04x", opcode);
+ break;
+ }
+ break;
+ case 0x1:
+ switch( ( opcode & THUMB_HIREG_OP ) >> THUMB_HIREG_OP_SHIFT )
+ {
+ case 0x0: /* ADD Rd, Rs */
+ rs = ( opcode & THUMB_HIREG_RS ) >> THUMB_HIREG_RS_SHIFT;
+ rd = opcode & THUMB_HIREG_RD;
+ switch( ( opcode & THUMB_HIREG_H ) >> THUMB_HIREG_H_SHIFT )
+ {
+ case 0x1: /* ADD Rd, HRs */
+ pBuf += sprintf( pBuf, "ADD R%d, R%d", rd, rs + 8 );
+ break;
+ case 0x2: /* ADD HRd, Rs */
+ pBuf += sprintf( pBuf, "ADD R%d, R%d", rd + 8, rs );
+ break;
+ case 0x3: /* ADD HRd, HRs */
+ pBuf += sprintf( pBuf, "ADD R%d, R%d", rd + 8, rs + 8 );
+ break;
+ default:
+ sprintf( pBuf, "INVALID %04x", opcode);
+ break;
+ }
+ break;
+ case 0x1: /* CMP */
+ switch( ( opcode & THUMB_HIREG_H ) >> THUMB_HIREG_H_SHIFT )
+ {
+ case 0x0: /* CMP Rd, Rs */
+ rs = ( opcode & THUMB_HIREG_RS ) >> THUMB_HIREG_RS_SHIFT;
+ rd = opcode & THUMB_HIREG_RD;
+ pBuf += sprintf( pBuf, "CMP R%d, R%d", rd, rs );
+ break;
+ case 0x1: /* CMP Rd, HRs */
+ rs = ( opcode & THUMB_HIREG_RS ) >> THUMB_HIREG_RS_SHIFT;
+ rd = opcode & THUMB_HIREG_RD;
+ pBuf += sprintf( pBuf, "CMP R%d, R%d", rd, rs + 8 );
+ break;
+ case 0x2: /* CMP Hd, Rs */
+ rs = ( opcode & THUMB_HIREG_RS ) >> THUMB_HIREG_RS_SHIFT;
+ rd = opcode & THUMB_HIREG_RD;
+ pBuf += sprintf( pBuf, "CMP R%d, R%d", rd + 8, rs );
+ break;
+ case 0x3: /* CMP Hd, Hs */
+ rs = ( opcode & THUMB_HIREG_RS ) >> THUMB_HIREG_RS_SHIFT;
+ rd = opcode & THUMB_HIREG_RD;
+ pBuf += sprintf( pBuf, "CMP R%d, R%d", rd + 8, rs + 8 );
+ break;
+ default:
+ sprintf( pBuf, "INVALID %04x", opcode);
+ break;
+ }
+ break;
+ case 0x2: /* MOV */
+ switch( ( opcode & THUMB_HIREG_H ) >> THUMB_HIREG_H_SHIFT )
+ {
+ case 0x0:
+ rs = ( opcode & THUMB_HIREG_RS ) >> THUMB_HIREG_RS_SHIFT;
+ rd = opcode & THUMB_HIREG_RD;
+ pBuf += sprintf( pBuf, "MOV R%d, R%d", rd, rs );
+ break;
+ case 0x1:
+ rs = ( opcode & THUMB_HIREG_RS ) >> THUMB_HIREG_RS_SHIFT;
+ rd = opcode & THUMB_HIREG_RD;
+ pBuf += sprintf( pBuf, "MOV R%d, R%d", rd, rs + 8 );
+ break;
+ case 0x2:
+ rs = ( opcode & THUMB_HIREG_RS ) >> THUMB_HIREG_RS_SHIFT;
+ rd = opcode & THUMB_HIREG_RD;
+ pBuf += sprintf( pBuf, "MOV R%d, R%d", rd + 8, rs );
+ break;
+ case 0x3:
+ rs = ( opcode & THUMB_HIREG_RS ) >> THUMB_HIREG_RS_SHIFT;
+ rd = opcode & THUMB_HIREG_RD;
+ pBuf += sprintf( pBuf, "MOV R%d, R%d", rd + 8, rs + 8 );
+ break;
+ default:
+ sprintf( pBuf, "INVALID %04x", opcode);
+ break;
+ }
+ break;
+ case 0x3:
+ switch( ( opcode & THUMB_HIREG_H ) >> THUMB_HIREG_H_SHIFT )
+ {
+ case 0x0:
+ rd = ( opcode & THUMB_HIREG_RS ) >> THUMB_HIREG_RS_SHIFT;
+ pBuf += sprintf( pBuf, "BX R%d", rd );
+ break;
+ case 0x1:
+ rd = ( ( opcode & THUMB_HIREG_RS ) >> THUMB_HIREG_RS_SHIFT ) + 8;
+ pBuf += sprintf( pBuf, "BX R%d", rd );
+ if (rd == 14)
+ dasmflags = DASMFLAG_STEP_OUT;
+ break;
+ default:
+ sprintf( pBuf, "INVALID %04x", opcode);
+ break;
+ }
+ break;
+ default:
+ sprintf( pBuf, "INVALID %04x", opcode);
+ break;
+ }
+ break;
+ case 0x2:
+ case 0x3:
+ rd = ( opcode & THUMB_INSN_IMM_RD ) >> THUMB_INSN_IMM_RD_SHIFT;
+ addr = ( opcode & THUMB_INSN_IMM ) << 2;
+ pBuf += sprintf( pBuf, "LDR R%d, [PC, #%03x]", rd, addr );
+ break;
+ default:
+ sprintf( pBuf, "INVALID %04x", opcode);
+ break;
+ }
+ break;
+ case 0x5: /* LDR* STR* */
+ switch( ( opcode & THUMB_GROUP5_TYPE ) >> THUMB_GROUP5_TYPE_SHIFT )
+ {
+ case 0x0: /* STR Rd, [Rn, Rm] */
+ rm = ( opcode & THUMB_GROUP5_RM ) >> THUMB_GROUP5_RM_SHIFT;
+ rn = ( opcode & THUMB_GROUP5_RN ) >> THUMB_GROUP5_RN_SHIFT;
+ rd = ( opcode & THUMB_GROUP5_RD ) >> THUMB_GROUP5_RD_SHIFT;
+ pBuf += sprintf( pBuf, "STR R%d, [R%d, R%d]", rd, rn, rm );
+ break;
+ case 0x1: /* STRH Rd, [Rn, Rm] */
+ rm = ( opcode & THUMB_GROUP5_RM ) >> THUMB_GROUP5_RM_SHIFT;
+ rn = ( opcode & THUMB_GROUP5_RN ) >> THUMB_GROUP5_RN_SHIFT;
+ rd = ( opcode & THUMB_GROUP5_RD ) >> THUMB_GROUP5_RD_SHIFT;
+ pBuf += sprintf( pBuf, "STRH R%d, [R%d, R%d]", rd, rn, rm );
+ break;
+ case 0x2: /* STRB Rd, [Rn, Rm] */ /* check */
+ rm = ( opcode & THUMB_GROUP5_RM ) >> THUMB_GROUP5_RM_SHIFT;
+ rn = ( opcode & THUMB_GROUP5_RN ) >> THUMB_GROUP5_RN_SHIFT;
+ rd = ( opcode & THUMB_GROUP5_RD ) >> THUMB_GROUP5_RD_SHIFT;
+ pBuf += sprintf( pBuf, "STRB R%d, [R%d, R%d]", rd, rn, rm );
+ break;
+ case 0x3: /* LDRSB Rd, [Rn, Rm] */
+ rm = ( opcode & THUMB_GROUP5_RM ) >> THUMB_GROUP5_RM_SHIFT;
+ rn = ( opcode & THUMB_GROUP5_RN ) >> THUMB_GROUP5_RN_SHIFT;
+ rd = ( opcode & THUMB_GROUP5_RD ) >> THUMB_GROUP5_RD_SHIFT;
+ pBuf += sprintf( pBuf, "LDRSB R%d, [R%d, R%d]", rd, rn, rm );
+ break;
+ case 0x4: /* LDR Rd, [Rn, Rm] */ /* check */
+ rm = ( opcode & THUMB_GROUP5_RM ) >> THUMB_GROUP5_RM_SHIFT;
+ rn = ( opcode & THUMB_GROUP5_RN ) >> THUMB_GROUP5_RN_SHIFT;
+ rd = ( opcode & THUMB_GROUP5_RD ) >> THUMB_GROUP5_RD_SHIFT;
+ pBuf += sprintf( pBuf, "LDR R%d, [R%d, R%d]", rd, rn, rm );
+ break;
+ case 0x5: /* LDRH Rd, [Rn, Rm] */
+ rm = ( opcode & THUMB_GROUP5_RM ) >> THUMB_GROUP5_RM_SHIFT;
+ rn = ( opcode & THUMB_GROUP5_RN ) >> THUMB_GROUP5_RN_SHIFT;
+ rd = ( opcode & THUMB_GROUP5_RD ) >> THUMB_GROUP5_RD_SHIFT;
+ pBuf += sprintf( pBuf, "LDRH R%d, [R%d, R%d]", rd, rn, rm );
+ break;
+
+ case 0x6: /* LDRB Rd, [Rn, Rm] */
+ rm = ( opcode & THUMB_GROUP5_RM ) >> THUMB_GROUP5_RM_SHIFT;
+ rn = ( opcode & THUMB_GROUP5_RN ) >> THUMB_GROUP5_RN_SHIFT;
+ rd = ( opcode & THUMB_GROUP5_RD ) >> THUMB_GROUP5_RD_SHIFT;
+ pBuf += sprintf( pBuf, "LDRB R%d, [R%d, R%d]", rd, rn, rm );
+ break;
+ case 0x7: /* LDSH Rd, [Rn, Rm] */
+ rm = ( opcode & THUMB_GROUP5_RM ) >> THUMB_GROUP5_RM_SHIFT;
+ rn = ( opcode & THUMB_GROUP5_RN ) >> THUMB_GROUP5_RN_SHIFT;
+ rd = ( opcode & THUMB_GROUP5_RD ) >> THUMB_GROUP5_RD_SHIFT;
+ pBuf += sprintf( pBuf, "LDSH R%d, [R%d, R%d]", rd, rn, rm );
+ break;
+ default:
+ sprintf( pBuf, "INVALID %04x", opcode);
+ break;
+ }
+ break;
+ case 0x6: /* Word Store w/ Immediate Offset */
+ if( opcode & THUMB_LSOP_L ) /* Load */
+ {
+ rn = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = opcode & THUMB_ADDSUB_RD;
+ offs = ( ( opcode & THUMB_LSOP_OFFS ) >> THUMB_LSOP_OFFS_SHIFT ) << 2;
+ pBuf += sprintf( pBuf, "LDR R%d [R%d + #%02x]", rd, rn, offs );
+ }
+ else /* Store */
+ {
+ rn = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = opcode & THUMB_ADDSUB_RD;
+ offs = ( ( opcode & THUMB_LSOP_OFFS ) >> THUMB_LSOP_OFFS_SHIFT ) << 2;
+ pBuf += sprintf( pBuf, "STR R%d, [R%d + #%02x] ", rd, rn, offs );
+ }
+ break;
+ case 0x7: /* Byte Store w/ Immeidate Offset */
+ if( opcode & THUMB_LSOP_L ) /* Load */
+ {
+ rn = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = opcode & THUMB_ADDSUB_RD;
+ offs = ( opcode & THUMB_LSOP_OFFS ) >> THUMB_LSOP_OFFS_SHIFT;
+ pBuf += sprintf( pBuf, "LDRB R%d, [R%d + #%02x]", rd, rn, offs );
+ }
+ else /* Store */
+ {
+ rn = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = opcode & THUMB_ADDSUB_RD;
+ offs = ( opcode & THUMB_LSOP_OFFS ) >> THUMB_LSOP_OFFS_SHIFT;
+ pBuf += sprintf( pBuf, "STRB R%d, [R%d + #%02x] ", rd, rn, offs );
+ }
+ break;
+ case 0x8: /* Load/Store Halfword */
+ if( opcode & THUMB_HALFOP_L ) /* Load */
+ {
+ imm = ( opcode & THUMB_HALFOP_OFFS ) >> THUMB_HALFOP_OFFS_SHIFT;
+ rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT;
+ pBuf += sprintf( pBuf, "LDRH R%d, [R%d, #%03x]", rd, rs, imm << 1 );
+ }
+ else /* Store */
+ {
+ imm = ( opcode & THUMB_HALFOP_OFFS ) >> THUMB_HALFOP_OFFS_SHIFT;
+ rs = ( opcode & THUMB_ADDSUB_RS ) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = ( opcode & THUMB_ADDSUB_RD ) >> THUMB_ADDSUB_RD_SHIFT;
+ pBuf += sprintf( pBuf, "STRH R%d, [R%d, #%03x]", rd, rs, imm << 1 );
+ }
+ break;
+ case 0x9: /* Stack-Relative Load/Store */
+ if( opcode & THUMB_STACKOP_L )
+ {
+ rd = ( opcode & THUMB_STACKOP_RD ) >> THUMB_STACKOP_RD_SHIFT;
+ offs = (UINT8)( opcode & THUMB_INSN_IMM );
+ pBuf += sprintf( pBuf, "LDR R%d, [SP, #%03x]", rd, offs << 2 );
+ }
+ else
+ {
+ rd = ( opcode & THUMB_STACKOP_RD ) >> THUMB_STACKOP_RD_SHIFT;
+ offs = (UINT8)( opcode & THUMB_INSN_IMM );
+ pBuf += sprintf( pBuf, "STR R%d, [SP, #%03x]", rd, offs << 2 );
+ }
+ break;
+ case 0xa: /* Get relative address */
+ if( opcode & THUMB_RELADDR_SP ) /* ADD Rd, SP, #nn */
+ {
+ rd = ( opcode & THUMB_RELADDR_RD ) >> THUMB_RELADDR_RD_SHIFT;
+ offs = (UINT8)( opcode & THUMB_INSN_IMM ) << 2;
+ pBuf += sprintf( pBuf, "ADD R%d, SP, #%03x", rd, offs );
+ }
+ else /* ADD Rd, PC, #nn */
+ {
+ rd = ( opcode & THUMB_RELADDR_RD ) >> THUMB_RELADDR_RD_SHIFT;
+ offs = (UINT8)( opcode & THUMB_INSN_IMM ) << 2;
+ pBuf += sprintf( pBuf, "ADD R%d, PC, #%03x", rd, offs );
+ }
+ break;
+ case 0xb: /* Stack-Related Opcodes */
+ switch( ( opcode & THUMB_STACKOP_TYPE ) >> THUMB_STACKOP_TYPE_SHIFT )
+ {
+ case 0x0: /* ADD SP, #imm */
+ addr = ( opcode & THUMB_INSN_IMM );
+ addr &= ~THUMB_INSN_IMM_S;
+ pBuf += sprintf( pBuf, "ADD SP, #");
+ if( opcode & THUMB_INSN_IMM_S )
+ {
+ pBuf += sprintf( pBuf, "-");
+ }
+ pBuf += sprintf( pBuf, "%03x", addr << 2);
+ break;
+ case 0x5: /* PUSH {Rlist}{LR} */
+ pBuf += sprintf( pBuf, "PUSH {LR, ");
+ for( offs = 7; offs >= 0; offs-- )
+ {
+ if( opcode & ( 1 << offs ) )
+ {
+ pBuf += sprintf( pBuf, "R%d, ", offs);
+ }
+ }
+ pBuf += sprintf( pBuf, "}");
+ break;
+ case 0x4: /* PUSH {Rlist} */
+ pBuf += sprintf( pBuf, "PUSH {");
+ for( offs = 7; offs >= 0; offs-- )
+ {
+ if( opcode & ( 1 << offs ) )
+ {
+ pBuf += sprintf( pBuf, "R%d, ", offs);
+ }
+ }
+ pBuf += sprintf( pBuf, "}");
+ break;
+ case 0xc: /* POP {Rlist} */
+ pBuf += sprintf( pBuf, "POP {");
+ for( offs = 0; offs < 8; offs++ )
+ {
+ if( opcode & ( 1 << offs ) )
+ {
+ pBuf += sprintf( pBuf, "R%d, ", offs);
+ }
+ }
+ pBuf += sprintf( pBuf, "}");
+ break;
+ case 0xd: /* POP {Rlist}{PC} */
+ pBuf += sprintf( pBuf, "POP {");
+ for( offs = 0; offs < 8; offs++ )
+ {
+ if( opcode & ( 1 << offs ) )
+ {
+ pBuf += sprintf( pBuf, "R%d, ", offs);
+ }
+ }
+ pBuf += sprintf( pBuf, "PC}");
+ break;
+ default:
+ sprintf( pBuf, "INVALID %04x", opcode);
+ break;
+ }
+ break;
+ case 0xc: /* Multiple Load/Store */
+ if( opcode & THUMB_MULTLS ) /* Load */
+ {
+ rd = ( opcode & THUMB_MULTLS_BASE ) >> THUMB_MULTLS_BASE_SHIFT;
+ pBuf += sprintf( pBuf, "LDMIA R%d!,{", rd);
+ for( offs = 0; offs < 8; offs++ )
+ {
+ if( opcode & ( 1 << offs ) )
+ {
+ pBuf += sprintf( pBuf, "R%d, ", offs);
+ }
+ }
+ pBuf += sprintf( pBuf, "}");
+ }
+ else /* Store */
+ {
+ rd = ( opcode & THUMB_MULTLS_BASE ) >> THUMB_MULTLS_BASE_SHIFT;
+ pBuf += sprintf( pBuf, "STMIA R%d!,{", rd);
+ for( offs = 7; offs >= 0; offs-- )
+ {
+ if( opcode & ( 1 << offs ) )
+ {
+ pBuf += sprintf( pBuf, "R%d, ", offs);
+ }
+ }
+ pBuf += sprintf( pBuf, "}");
+ }
+ break;
+ case 0xd: /* Conditional Branch */
+ offs = (INT8)( opcode & THUMB_INSN_IMM );
+ switch( ( opcode & THUMB_COND_TYPE ) >> THUMB_COND_TYPE_SHIFT )
+ {
+ case COND_EQ:
+ pBuf += sprintf( pBuf, "BEQ %08x (%02x)", pc + 4 + (offs << 1), offs << 1);
+ break;
+ case COND_NE:
+ pBuf += sprintf( pBuf, "BNE %08x (%02x)", pc + 4 + (offs << 1), offs << 1);
+ break;
+ case COND_CS:
+ pBuf += sprintf( pBuf, "BCS %08x (%02x)", pc + 4 + (offs << 1), offs << 1);
+ break;
+ case COND_CC:
+ pBuf += sprintf( pBuf, "BCC %08x (%02x)", pc + 4 + (offs << 1), offs << 1);
+ break;
+ case COND_MI:
+ pBuf += sprintf( pBuf, "BMI %08x (%02x)", pc + 4 + (offs << 1), offs << 1);
+ break;
+ case COND_PL:
+ pBuf += sprintf( pBuf, "BPL %08x (%02x)", pc + 4 + (offs << 1), offs << 1);
+ break;
+ case COND_VS:
+ pBuf += sprintf( pBuf, "BVS %08x (%02x)", pc + 4 + (offs << 1), offs << 1);
+ break;
+ case COND_VC:
+ pBuf += sprintf( pBuf, "BVC %08x (%02x)", pc + 4 + (offs << 1), offs << 1);
+ break;
+ case COND_HI:
+ pBuf += sprintf( pBuf, "BHI %08x (%02x)", pc + 4 + (offs << 1), offs << 1);
+ break;
+ case COND_LS:
+ pBuf += sprintf( pBuf, "BLS %08x (%02x)", pc + 4 + (offs << 1), offs << 1);
+ break;
+ case COND_GE:
+ pBuf += sprintf( pBuf, "BGE %08x (%02x)", pc + 4 + (offs << 1), offs << 1);
+ break;
+ case COND_LT:
+ pBuf += sprintf( pBuf, "BLT %08x (%02x)", pc + 4 + (offs << 1), offs << 1);
+ break;
+ case COND_GT:
+ pBuf += sprintf( pBuf, "BGT %08x (%02x)", pc + 4 + (offs << 1), offs << 1);
+ break;
+ case COND_LE:
+ pBuf += sprintf( pBuf, "BLE %08x (%02x)", pc + 4 + (offs << 1), offs << 1);
+ break;
+ case COND_AL:
+ pBuf += sprintf( pBuf, "INVALID");
+ break;
+ case COND_NV:
+ pBuf += sprintf( pBuf, "SWI %02x\n", opcode & 0xff);
+ break;
+ }
+ break;
+ case 0xe: /* B #offs */
+ if( opcode & THUMB_BLOP_LO )
+ {
+ addr = ( ( opcode & THUMB_BLOP_OFFS ) << 1 ) & 0xfffc;
+ pBuf += sprintf( pBuf, "BLX (LO) %08x", addr );
+ dasmflags = DASMFLAG_STEP_OVER;
+ }
+ else
+ {
+ offs = ( opcode & THUMB_BRANCH_OFFS ) << 1;
+ if( offs & 0x00000800 )
+ {
+ offs |= 0xfffff800;
+ }
+ pBuf += sprintf( pBuf, "B #%08x (%08x)", offs, pc + 4 + offs);
+ }
+ break;
+ case 0xf: /* BL */
+ if( opcode & THUMB_BLOP_LO )
+ {
+ pBuf += sprintf( pBuf, "BL (LO) %08x", ( opcode & THUMB_BLOP_OFFS ) << 1 );
+ dasmflags = DASMFLAG_STEP_OVER;
+ }
+ else
+ {
+ addr = ( opcode & THUMB_BLOP_OFFS ) << 12;
+ if( addr & ( 1 << 22 ) )
+ {
+ addr |= 0xff800000;
+ }
+ pBuf += sprintf( pBuf, "BL (HI) %08x", addr );
+ dasmflags = DASMFLAG_STEP_OVER;
+ }
+ break;
+ default:
+ sprintf( pBuf, "INVALID %04x", opcode);
+ break;
+ }
+
+ return dasmflags | DASMFLAG_SUPPORTED;
+}
+
+CPU_DISASSEMBLE( arm7arm )
+{
+ return arm7_disasm(buffer, pc, oprom[0] | (oprom[1] << 8) | (oprom[2] << 16) | (oprom[3] << 24)) | 4;
+}
+
+CPU_DISASSEMBLE( arm7arm_be )
+{
+ return arm7_disasm(buffer, pc, oprom[3] | (oprom[2] << 8) | (oprom[1] << 16) | (oprom[0] << 24)) | 4;
+}
+
+CPU_DISASSEMBLE( arm7thumb )
+{
+ return thumb_disasm(buffer, pc, oprom[0] | (oprom[1] << 8)) | 2;
+}
+
+CPU_DISASSEMBLE( arm7thumb_be )
+{
+ return thumb_disasm(buffer, pc, oprom[1] | (oprom[0] << 8)) | 2;
+}
+
diff --git a/trunk/src/emu/cpu/arm7/arm7exec.c b/trunk/src/emu/cpu/arm7/arm7exec.c
new file mode 100644
index 00000000000..5cf952c46e4
--- /dev/null
+++ b/trunk/src/emu/cpu/arm7/arm7exec.c
@@ -0,0 +1,1648 @@
+/*****************************************************************************
+ *
+ * arm7exec.c
+ * Portable ARM7TDMI Core Emulator
+ *
+ * Copyright Steve Ellenoff, all rights reserved.
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * sellenoff@hotmail.com
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ * This work is based on:
+ * #1) 'Atmel Corporation ARM7TDMI (Thumb) Datasheet - January 1999'
+ * #2) Arm 2/3/6 emulator By Bryan McPhail (bmcphail@tendril.co.uk) and Phil Stroffolino (MAME CORE 0.76)
+ *
+ *****************************************************************************/
+
+/******************************************************************************
+ * Notes:
+ * This file contains the code to run during the CPU EXECUTE METHOD.
+ * It has been split into it's own file (from the arm7core.c) so it can be
+ * directly compiled into any cpu core that wishes to use it.
+ *
+ * It should be included as follows in your cpu core:
+ *
+ * CPU_EXECUTE( arm7 )
+ * {
+ * #include "arm7exec.c"
+ * }
+ *
+*****************************************************************************/
+
+/* This implementation uses an improved switch() for hopefully faster opcode fetches compared to my last version
+.. though there's still room for improvement. */
+{
+ UINT32 pc;
+ UINT32 insn;
+ arm_state *cpustate = get_safe_token(device);
+
+ do
+ {
+ debugger_instruction_hook(cpustate->device, GET_PC);
+
+ /* handle Thumb instructions if active */
+ if (T_IS_SET(GET_CPSR))
+ {
+ UINT32 readword, addr, raddr;
+ UINT32 rm, rn, rs, rd, op2, imm, rrs, rrd;
+ INT32 offs;
+
+ pc = R15;
+
+ // "In Thumb state, bit [0] is undefined and must be ignored. Bits [31:1] contain the PC."
+ raddr = pc & (~1);
+
+ if ( COPRO_CTRL & COPRO_CTRL_MMU_EN )
+ {
+ raddr = arm7_tlb_translate(cpustate, raddr, ARM7_TLB_ABORT_P);
+ if (cpustate->pendingAbtP != 0)
+ {
+ goto skip_exec;
+ }
+ }
+ insn = cpustate->direct->read_decrypted_word(raddr);
+ ARM7_ICOUNT -= (3 - thumbCycles[insn >> 8]);
+ switch ((insn & THUMB_INSN_TYPE) >> THUMB_INSN_TYPE_SHIFT)
+ {
+ case 0x0: /* Logical shifting */
+ SET_CPSR(GET_CPSR & ~(N_MASK | Z_MASK));
+ if (insn & THUMB_SHIFT_R) /* Shift right */
+ {
+ rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
+ rrs = GET_REGISTER(cpustate, rs);
+ offs = (insn & THUMB_SHIFT_AMT) >> THUMB_SHIFT_AMT_SHIFT;
+ if (offs != 0)
+ {
+ SET_REGISTER(cpustate, rd, rrs >> offs);
+ if (rrs & (1 << (offs - 1)))
+ {
+ SET_CPSR(GET_CPSR | C_MASK);
+ }
+ else
+ {
+ SET_CPSR(GET_CPSR & ~C_MASK);
+ }
+ }
+ else
+ {
+ SET_REGISTER(cpustate, rd, 0);
+ if (rrs & 0x80000000)
+ {
+ SET_CPSR(GET_CPSR | C_MASK);
+ }
+ else
+ {
+ SET_CPSR(GET_CPSR & ~C_MASK);
+ }
+ }
+ SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK));
+ SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(cpustate, rd)));
+ R15 += 2;
+ }
+ else /* Shift left */
+ {
+ rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
+ rrs = GET_REGISTER(cpustate, rs);
+ offs = (insn & THUMB_SHIFT_AMT) >> THUMB_SHIFT_AMT_SHIFT;
+ if (offs != 0)
+ {
+ SET_REGISTER(cpustate, rd, rrs << offs);
+ if (rrs & (1 << (31 - (offs - 1))))
+ {
+ SET_CPSR(GET_CPSR | C_MASK);
+ }
+ else
+ {
+ SET_CPSR(GET_CPSR & ~C_MASK);
+ }
+ }
+ else
+ {
+ SET_REGISTER(cpustate, rd, rrs);
+ }
+ SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK));
+ SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(cpustate, rd)));
+ R15 += 2;
+ }
+ break;
+ case 0x1: /* Arithmetic */
+ if (insn & THUMB_INSN_ADDSUB)
+ {
+ switch ((insn & THUMB_ADDSUB_TYPE) >> THUMB_ADDSUB_TYPE_SHIFT)
+ {
+ case 0x0: /* ADD Rd, Rs, Rn */
+ rn = GET_REGISTER(cpustate, (insn & THUMB_ADDSUB_RNIMM) >> THUMB_ADDSUB_RNIMM_SHIFT);
+ rs = GET_REGISTER(cpustate, (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT);
+ rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
+ SET_REGISTER(cpustate, rd, rs + rn);
+ HandleThumbALUAddFlags(GET_REGISTER(cpustate, rd), rs, rn);
+ break;
+ case 0x1: /* SUB Rd, Rs, Rn */
+ rn = GET_REGISTER(cpustate, (insn & THUMB_ADDSUB_RNIMM) >> THUMB_ADDSUB_RNIMM_SHIFT);
+ rs = GET_REGISTER(cpustate, (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT);
+ rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
+ SET_REGISTER(cpustate, rd, rs - rn);
+ HandleThumbALUSubFlags(GET_REGISTER(cpustate, rd), rs, rn);
+ break;
+ case 0x2: /* ADD Rd, Rs, #imm */
+ imm = (insn & THUMB_ADDSUB_RNIMM) >> THUMB_ADDSUB_RNIMM_SHIFT;
+ rs = GET_REGISTER(cpustate, (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT);
+ rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
+ SET_REGISTER(cpustate, rd, rs + imm);
+ HandleThumbALUAddFlags(GET_REGISTER(cpustate, rd), rs, imm);
+ break;
+ case 0x3: /* SUB Rd, Rs, #imm */
+ imm = (insn & THUMB_ADDSUB_RNIMM) >> THUMB_ADDSUB_RNIMM_SHIFT;
+ rs = GET_REGISTER(cpustate, (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT);
+ rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
+ SET_REGISTER(cpustate, rd, rs - imm);
+ HandleThumbALUSubFlags(GET_REGISTER(cpustate, rd), rs,imm);
+ break;
+ default:
+ fatalerror("%08x: G1 Undefined Thumb instruction: %04x\n", pc, insn);
+ R15 += 2;
+ break;
+ }
+ }
+ else
+ {
+ /* ASR.. */
+ //if (insn & THUMB_SHIFT_R) /* Shift right */
+ {
+ rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
+ rrs = GET_REGISTER(cpustate, rs);
+ offs = (insn & THUMB_SHIFT_AMT) >> THUMB_SHIFT_AMT_SHIFT;
+ if (offs == 0)
+ {
+ offs = 32;
+ }
+ if (offs >= 32)
+ {
+ if (rrs >> 31)
+ {
+ SET_CPSR(GET_CPSR | C_MASK);
+ }
+ else
+ {
+ SET_CPSR(GET_CPSR & ~C_MASK);
+ }
+ SET_REGISTER(cpustate, rd, (rrs & 0x80000000) ? 0xFFFFFFFF : 0x00000000);
+ }
+ else
+ {
+ if ((rrs >> (offs - 1)) & 1)
+ {
+ SET_CPSR(GET_CPSR | C_MASK);
+ }
+ else
+ {
+ SET_CPSR(GET_CPSR & ~C_MASK);
+ }
+ SET_REGISTER(cpustate, rd,
+ (rrs & 0x80000000)
+ ? ((0xFFFFFFFF << (32 - offs)) | (rrs >> offs))
+ : (rrs >> offs));
+ }
+ SET_CPSR(GET_CPSR & ~(N_MASK | Z_MASK));
+ SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(cpustate, rd)));
+ R15 += 2;
+ }
+ }
+ break;
+ case 0x2: /* CMP / MOV */
+ if (insn & THUMB_INSN_CMP)
+ {
+ rn = GET_REGISTER(cpustate, (insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT);
+ op2 = insn & THUMB_INSN_IMM;
+ rd = rn - op2;
+ HandleThumbALUSubFlags(rd, rn, op2);
+ //mame_printf_debug("%08x: xxx Thumb instruction: CMP R%d (%08x), %02x (N=%d, Z=%d, C=%d, V=%d)\n", pc, (insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT, GET_REGISTER(cpustate, (insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT), op2, N_IS_SET(GET_CPSR) ? 1 : 0, Z_IS_SET(GET_CPSR) ? 1 : 0, C_IS_SET(GET_CPSR) ? 1 : 0, V_IS_SET(GET_CPSR) ? 1 : 0);
+ }
+ else
+ {
+ rd = (insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT;
+ op2 = (insn & THUMB_INSN_IMM);
+ SET_REGISTER(cpustate, rd, op2);
+ SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK));
+ SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(cpustate, rd)));
+ R15 += 2;
+ }
+ break;
+ case 0x3: /* ADD/SUB immediate */
+ if (insn & THUMB_INSN_SUB) /* SUB Rd, #Offset8 */
+ {
+ rn = GET_REGISTER(cpustate, (insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT);
+ op2 = insn & THUMB_INSN_IMM;
+ //mame_printf_debug("%08x: Thumb instruction: SUB R%d, %02x\n", pc, (insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT, op2);
+ rd = rn - op2;
+ SET_REGISTER(cpustate, (insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT, rd);
+ HandleThumbALUSubFlags(rd, rn, op2);
+ }
+ else /* ADD Rd, #Offset8 */
+ {
+ rn = GET_REGISTER(cpustate, (insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT);
+ op2 = insn & THUMB_INSN_IMM;
+ rd = rn + op2;
+ //mame_printf_debug("%08x: Thumb instruction: ADD R%d, %02x\n", pc, (insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT, op2);
+ SET_REGISTER(cpustate, (insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT, rd);
+ HandleThumbALUAddFlags(rd, rn, op2);
+ }
+ break;
+ case 0x4: /* Rd & Rm instructions */
+ switch ((insn & THUMB_GROUP4_TYPE) >> THUMB_GROUP4_TYPE_SHIFT)
+ {
+ case 0x0:
+ switch ((insn & THUMB_ALUOP_TYPE) >> THUMB_ALUOP_TYPE_SHIFT)
+ {
+ case 0x0: /* AND Rd, Rs */
+ rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
+ SET_REGISTER(cpustate, rd, GET_REGISTER(cpustate, rd) & GET_REGISTER(cpustate, rs));
+ SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK));
+ SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(cpustate, rd)));
+ R15 += 2;
+ break;
+ case 0x1: /* EOR Rd, Rs */
+ rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
+ SET_REGISTER(cpustate, rd, GET_REGISTER(cpustate, rd) ^ GET_REGISTER(cpustate, rs));
+ SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK));
+ SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(cpustate, rd)));
+ R15 += 2;
+ break;
+ case 0x2: /* LSL Rd, Rs */
+ rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
+ rrd = GET_REGISTER(cpustate, rd);
+ offs = GET_REGISTER(cpustate, rs) & 0x000000ff;
+ if (offs > 0)
+ {
+ if (offs < 32)
+ {
+ SET_REGISTER(cpustate, rd, rrd << offs);
+ if (rrd & (1 << (31 - (offs - 1))))
+ {
+ SET_CPSR(GET_CPSR | C_MASK);
+ }
+ else
+ {
+ SET_CPSR(GET_CPSR & ~C_MASK);
+ }
+ }
+ else if (offs == 32)
+ {
+ SET_REGISTER(cpustate, rd, 0);
+ if (rrd & 1)
+ {
+ SET_CPSR(GET_CPSR | C_MASK);
+ }
+ else
+ {
+ SET_CPSR(GET_CPSR & ~C_MASK);
+ }
+ }
+ else
+ {
+ SET_REGISTER(cpustate, rd, 0);
+ SET_CPSR(GET_CPSR & ~C_MASK);
+ }
+ }
+ SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK));
+ SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(cpustate, rd)));
+ R15 += 2;
+ break;
+ case 0x3: /* LSR Rd, Rs */
+ rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
+ rrd = GET_REGISTER(cpustate, rd);
+ offs = GET_REGISTER(cpustate, rs) & 0x000000ff;
+ if (offs > 0)
+ {
+ if (offs < 32)
+ {
+ SET_REGISTER(cpustate, rd, rrd >> offs);
+ if (rrd & (1 << (offs - 1)))
+ {
+ SET_CPSR(GET_CPSR | C_MASK);
+ }
+ else
+ {
+ SET_CPSR(GET_CPSR & ~C_MASK);
+ }
+ }
+ else if (offs == 32)
+ {
+ SET_REGISTER(cpustate, rd, 0);
+ if (rrd & 0x80000000)
+ {
+ SET_CPSR(GET_CPSR | C_MASK);
+ }
+ else
+ {
+ SET_CPSR(GET_CPSR & ~C_MASK);
+ }
+ }
+ else
+ {
+ SET_REGISTER(cpustate, rd, 0);
+ SET_CPSR(GET_CPSR & ~C_MASK);
+ }
+ }
+ SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK));
+ SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(cpustate, rd)));
+ R15 += 2;
+ break;
+ case 0x4: /* ASR Rd, Rs */
+ rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
+ rrs = GET_REGISTER(cpustate, rs)&0xff;
+ rrd = GET_REGISTER(cpustate, rd);
+ if (rrs != 0)
+ {
+ if (rrs >= 32)
+ {
+ if (rrd >> 31)
+ {
+ SET_CPSR(GET_CPSR | C_MASK);
+ }
+ else
+ {
+ SET_CPSR(GET_CPSR & ~C_MASK);
+ }
+ SET_REGISTER(cpustate, rd, (GET_REGISTER(cpustate, rd) & 0x80000000) ? 0xFFFFFFFF : 0x00000000);
+ }
+ else
+ {
+ if ((rrd >> (rrs-1)) & 1)
+ {
+ SET_CPSR(GET_CPSR | C_MASK);
+ }
+ else
+ {
+ SET_CPSR(GET_CPSR & ~C_MASK);
+ }
+ SET_REGISTER(cpustate, rd, (rrd & 0x80000000)
+ ? ((0xFFFFFFFF << (32 - rrs)) | (rrd >> rrs))
+ : (rrd >> rrs));
+ }
+ }
+ SET_CPSR(GET_CPSR & ~(N_MASK | Z_MASK));
+ SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(cpustate, rd)));
+ R15 += 2;
+ break;
+ case 0x5: /* ADC Rd, Rs */
+ rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
+ op2=(GET_CPSR & C_MASK) ? 1 : 0;
+ rn=GET_REGISTER(cpustate, rd) + GET_REGISTER(cpustate, rs) + op2;
+ HandleThumbALUAddFlags(rn, GET_REGISTER(cpustate, rd), (GET_REGISTER(cpustate, rs))); // ?
+ SET_REGISTER(cpustate, rd, rn);
+ break;
+ case 0x6: /* SBC Rd, Rs */
+ rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
+ op2=(GET_CPSR & C_MASK) ? 0 : 1;
+ rn=GET_REGISTER(cpustate, rd) - GET_REGISTER(cpustate, rs) - op2;
+ HandleThumbALUSubFlags(rn, GET_REGISTER(cpustate, rd), (GET_REGISTER(cpustate, rs))); //?
+ SET_REGISTER(cpustate, rd, rn);
+ break;
+ case 0x7: /* ROR Rd, Rs */
+ rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
+ rrd = GET_REGISTER(cpustate, rd);
+ imm = GET_REGISTER(cpustate, rs) & 0x0000001f;
+ SET_REGISTER(cpustate, rd, (rrd >> imm) | (rrd << (32 - imm)));
+ if (rrd & (1 << (imm - 1)))
+ {
+ SET_CPSR(GET_CPSR | C_MASK);
+ }
+ else
+ {
+ SET_CPSR(GET_CPSR & ~C_MASK);
+ }
+ SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK));
+ SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(cpustate, rd)));
+ R15 += 2;
+ break;
+ case 0x8: /* TST Rd, Rs */
+ rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
+ SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK));
+ SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(cpustate, rd) & GET_REGISTER(cpustate, rs)));
+ R15 += 2;
+ break;
+ case 0x9: /* NEG Rd, Rs */
+ rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
+ rrs = GET_REGISTER(cpustate, rs);
+ rn = 0 - rrs;
+ SET_REGISTER(cpustate, rd, rn);
+ HandleThumbALUSubFlags(GET_REGISTER(cpustate, rd), 0, rrs);
+ break;
+ case 0xa: /* CMP Rd, Rs */
+ rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
+ rn = GET_REGISTER(cpustate, rd) - GET_REGISTER(cpustate, rs);
+ HandleThumbALUSubFlags(rn, GET_REGISTER(cpustate, rd), GET_REGISTER(cpustate, rs));
+ break;
+ case 0xb: /* CMN Rd, Rs - check flags, add dasm */
+ rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
+ rn = GET_REGISTER(cpustate, rd) + GET_REGISTER(cpustate, rs);
+ HandleThumbALUAddFlags(rn, GET_REGISTER(cpustate, rd), GET_REGISTER(cpustate, rs));
+ break;
+ case 0xc: /* ORR Rd, Rs */
+ rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
+ SET_REGISTER(cpustate, rd, GET_REGISTER(cpustate, rd) | GET_REGISTER(cpustate, rs));
+ SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK));
+ SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(cpustate, rd)));
+ R15 += 2;
+ break;
+ case 0xd: /* MUL Rd, Rs */
+ rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
+ rn = GET_REGISTER(cpustate, rd) * GET_REGISTER(cpustate, rs);
+ SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK));
+ SET_REGISTER(cpustate, rd, rn);
+ SET_CPSR(GET_CPSR | HandleALUNZFlags(rn));
+ R15 += 2;
+ break;
+ case 0xe: /* BIC Rd, Rs */
+ rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
+ SET_REGISTER(cpustate, rd, GET_REGISTER(cpustate, rd) & (~GET_REGISTER(cpustate, rs)));
+ SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK));
+ SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(cpustate, rd)));
+ R15 += 2;
+ break;
+ case 0xf: /* MVN Rd, Rs */
+ rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
+ op2 = GET_REGISTER(cpustate, rs);
+ SET_REGISTER(cpustate, rd, ~op2);
+ SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK));
+ SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(cpustate, rd)));
+ R15 += 2;
+ break;
+ default:
+ fatalerror("%08x: G4-0 Undefined Thumb instruction: %04x %x\n", pc, insn, (insn & THUMB_ALUOP_TYPE) >> THUMB_ALUOP_TYPE_SHIFT);
+ R15 += 2;
+ break;
+ }
+ break;
+ case 0x1:
+ switch ((insn & THUMB_HIREG_OP) >> THUMB_HIREG_OP_SHIFT)
+ {
+ case 0x0: /* ADD Rd, Rs */
+ rs = (insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT;
+ rd = insn & THUMB_HIREG_RD;
+ switch ((insn & THUMB_HIREG_H) >> THUMB_HIREG_H_SHIFT)
+ {
+ case 0x1: /* ADD Rd, HRs */
+ SET_REGISTER(cpustate, rd, GET_REGISTER(cpustate, rd) + GET_REGISTER(cpustate, rs+8));
+ // emulate the effects of pre-fetch
+ if (rs == 7)
+ {
+ SET_REGISTER(cpustate, rd, GET_REGISTER(cpustate, rd) + 4);
+ }
+ break;
+ case 0x2: /* ADD HRd, Rs */
+ SET_REGISTER(cpustate, rd+8, GET_REGISTER(cpustate, rd+8) + GET_REGISTER(cpustate, rs));
+ if (rd == 7)
+ {
+ R15 += 2;
+ }
+ break;
+ case 0x3: /* Add HRd, HRs */
+ SET_REGISTER(cpustate, rd+8, GET_REGISTER(cpustate, rd+8) + GET_REGISTER(cpustate, rs+8));
+ // emulate the effects of pre-fetch
+ if (rs == 7)
+ {
+ SET_REGISTER(cpustate, rd+8, GET_REGISTER(cpustate, rd+8) + 4);
+ }
+ if (rd == 7)
+ {
+ R15 += 2;
+ }
+ break;
+ default:
+ fatalerror("%08x: G4-1-0 Undefined Thumb instruction: %04x %x\n", pc, insn, (insn & THUMB_HIREG_H) >> THUMB_HIREG_H_SHIFT);
+ break;
+ }
+ R15 += 2;
+ break;
+ case 0x1: /* CMP */
+ switch ((insn & THUMB_HIREG_H) >> THUMB_HIREG_H_SHIFT)
+ {
+ case 0x0: /* CMP Rd, Rs */
+ rs = GET_REGISTER(cpustate, ((insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT));
+ rd = GET_REGISTER(cpustate, insn & THUMB_HIREG_RD);
+ rn = rd - rs;
+ HandleThumbALUSubFlags(rn, rd, rs);
+ break;
+ case 0x1: /* CMP Rd, Hs */
+ rs = GET_REGISTER(cpustate, ((insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT) + 8);
+ rd = GET_REGISTER(cpustate, insn & THUMB_HIREG_RD);
+ rn = rd - rs;
+ HandleThumbALUSubFlags(rn, rd, rs);
+ break;
+ case 0x2: /* CMP Hd, Rs */
+ rs = GET_REGISTER(cpustate, ((insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT));
+ rd = GET_REGISTER(cpustate, (insn & THUMB_HIREG_RD) + 8);
+ rn = rd - rs;
+ HandleThumbALUSubFlags(rn, rd, rs);
+ break;
+ case 0x3: /* CMP Hd, Hs */
+ rs = GET_REGISTER(cpustate, ((insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT) + 8);
+ rd = GET_REGISTER(cpustate, (insn & THUMB_HIREG_RD) + 8);
+ rn = rd - rs;
+ HandleThumbALUSubFlags(rn, rd, rs);
+ break;
+ default:
+ fatalerror("%08x: G4-1 Undefined Thumb instruction: %04x %x\n", pc, insn, (insn & THUMB_HIREG_H) >> THUMB_HIREG_H_SHIFT);
+ R15 += 2;
+ break;
+ }
+ break;
+ case 0x2: /* MOV */
+ switch ((insn & THUMB_HIREG_H) >> THUMB_HIREG_H_SHIFT)
+ {
+ case 0x0: // MOV Rd, Rs (undefined)
+ // "The action of H1 = 0, H2 = 0 for Op = 00 (ADD), Op = 01 (CMP) and Op = 10 (MOV) is undefined, and should not be used."
+ rs = (insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT;
+ rd = insn & THUMB_HIREG_RD;
+ SET_REGISTER(cpustate, rd, GET_REGISTER(cpustate, rs));
+ R15 += 2;
+ break;
+ case 0x1: // MOV Rd, Hs
+ rs = (insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT;
+ rd = insn & THUMB_HIREG_RD;
+ if (rs == 7)
+ {
+ SET_REGISTER(cpustate, rd, GET_REGISTER(cpustate, rs + 8) + 4);
+ }
+ else
+ {
+ SET_REGISTER(cpustate, rd, GET_REGISTER(cpustate, rs + 8));
+ }
+ R15 += 2;
+ break;
+ case 0x2: // MOV Hd, Rs
+ rs = (insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT;
+ rd = insn & THUMB_HIREG_RD;
+ SET_REGISTER(cpustate, rd + 8, GET_REGISTER(cpustate, rs));
+ if (rd != 7)
+ {
+ R15 += 2;
+ }
+ else
+ {
+ R15 &= ~1;
+ }
+ break;
+ case 0x3: // MOV Hd, Hs
+ rs = (insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT;
+ rd = insn & THUMB_HIREG_RD;
+ if (rs == 7)
+ {
+ SET_REGISTER(cpustate, rd + 8, GET_REGISTER(cpustate, rs+8)+4);
+ }
+ else
+ {
+ SET_REGISTER(cpustate, rd + 8, GET_REGISTER(cpustate, rs+8));
+ }
+ if (rd != 7)
+ {
+ R15 += 2;
+ }
+ if (rd == 7)
+ {
+ R15 &= ~1;
+ }
+ break;
+ default:
+ fatalerror("%08x: G4-2 Undefined Thumb instruction: %04x (%x)\n", pc, insn, (insn & THUMB_HIREG_H) >> THUMB_HIREG_H_SHIFT);
+ R15 += 2;
+ break;
+ }
+ break;
+ case 0x3:
+ switch ((insn & THUMB_HIREG_H) >> THUMB_HIREG_H_SHIFT)
+ {
+ case 0x0:
+ rd = (insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT;
+ addr = GET_REGISTER(cpustate, rd);
+ if (addr & 1)
+ {
+ addr &= ~1;
+ }
+ else
+ {
+ SET_CPSR(GET_CPSR & ~T_MASK);
+ if (addr & 2)
+ {
+ addr += 2;
+ }
+ }
+ R15 = addr;
+ break;
+ case 0x1:
+ addr = GET_REGISTER(cpustate, ((insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT) + 8);
+ if ((((insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT) + 8) == 15)
+ {
+ addr += 2;
+ }
+ if (addr & 1)
+ {
+ addr &= ~1;
+ }
+ else
+ {
+ SET_CPSR(GET_CPSR & ~T_MASK);
+ if (addr & 2)
+ {
+ addr += 2;
+ }
+ }
+ R15 = addr;
+ break;
+ default:
+ fatalerror("%08x: G4-3 Undefined Thumb instruction: %04x\n", pc, insn);
+ R15 += 2;
+ break;
+ }
+ break;
+ default:
+ fatalerror("%08x: G4-x Undefined Thumb instruction: %04x\n", pc, insn);
+ R15 += 2;
+ break;
+ }
+ break;
+ case 0x2:
+ case 0x3:
+ readword = READ32((R15 & ~2) + 4 + ((insn & THUMB_INSN_IMM) << 2));
+ SET_REGISTER(cpustate, (insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT, readword);
+ R15 += 2;
+ break;
+ default:
+ fatalerror("%08x: G4-y Undefined Thumb instruction: %04x\n", pc, insn);
+ R15 += 2;
+ break;
+ }
+ break;
+ case 0x5: /* LDR* STR* */
+ switch ((insn & THUMB_GROUP5_TYPE) >> THUMB_GROUP5_TYPE_SHIFT)
+ {
+ case 0x0: /* STR Rd, [Rn, Rm] */
+ rm = (insn & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT;
+ rn = (insn & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT;
+ rd = (insn & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT;
+ addr = GET_REGISTER(cpustate, rn) + GET_REGISTER(cpustate, rm);
+ WRITE32(addr, GET_REGISTER(cpustate, rd));
+ R15 += 2;
+ break;
+ case 0x1: /* STRH Rd, [Rn, Rm] */
+ rm = (insn & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT;
+ rn = (insn & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT;
+ rd = (insn & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT;
+ addr = GET_REGISTER(cpustate, rn) + GET_REGISTER(cpustate, rm);
+ WRITE16(addr, GET_REGISTER(cpustate, rd));
+ R15 += 2;
+ break;
+ case 0x2: /* STRB Rd, [Rn, Rm] */
+ rm = (insn & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT;
+ rn = (insn & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT;
+ rd = (insn & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT;
+ addr = GET_REGISTER(cpustate, rn) + GET_REGISTER(cpustate, rm);
+ WRITE8(addr, GET_REGISTER(cpustate, rd));
+ R15 += 2;
+ break;
+ case 0x3: /* LDSB Rd, [Rn, Rm] todo, add dasm */
+ rm = (insn & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT;
+ rn = (insn & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT;
+ rd = (insn & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT;
+ addr = GET_REGISTER(cpustate, rn) + GET_REGISTER(cpustate, rm);
+ op2 = READ8(addr);
+ if (op2 & 0x00000080)
+ {
+ op2 |= 0xffffff00;
+ }
+ SET_REGISTER(cpustate, rd, op2);
+ R15 += 2;
+ break;
+ case 0x4: /* LDR Rd, [Rn, Rm] */
+ rm = (insn & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT;
+ rn = (insn & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT;
+ rd = (insn & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT;
+ addr = GET_REGISTER(cpustate, rn) + GET_REGISTER(cpustate, rm);
+ op2 = READ32(addr);
+ SET_REGISTER(cpustate, rd, op2);
+ R15 += 2;
+ break;
+ case 0x5: /* LDRH Rd, [Rn, Rm] */
+ rm = (insn & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT;
+ rn = (insn & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT;
+ rd = (insn & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT;
+ addr = GET_REGISTER(cpustate, rn) + GET_REGISTER(cpustate, rm);
+ op2 = READ16(addr);
+ SET_REGISTER(cpustate, rd, op2);
+ R15 += 2;
+ break;
+ case 0x6: /* LDRB Rd, [Rn, Rm] */
+ rm = (insn & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT;
+ rn = (insn & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT;
+ rd = (insn & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT;
+ addr = GET_REGISTER(cpustate, rn) + GET_REGISTER(cpustate, rm);
+ op2 = READ8(addr);
+ SET_REGISTER(cpustate, rd, op2);
+ R15 += 2;
+ break;
+ case 0x7: /* LDSH Rd, [Rn, Rm] */
+ rm = (insn & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT;
+ rn = (insn & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT;
+ rd = (insn & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT;
+ addr = GET_REGISTER(cpustate, rn) + GET_REGISTER(cpustate, rm);
+ op2 = READ16(addr);
+ if (op2 & 0x00008000)
+ {
+ op2 |= 0xffff0000;
+ }
+ SET_REGISTER(cpustate, rd, op2);
+ R15 += 2;
+ break;
+ default:
+ fatalerror("%08x: G5 Undefined Thumb instruction: %04x\n", pc, insn);
+ R15 += 2;
+ break;
+ }
+ break;
+ case 0x6: /* Word Store w/ Immediate Offset */
+ if (insn & THUMB_LSOP_L) /* Load */
+ {
+ rn = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = insn & THUMB_ADDSUB_RD;
+ offs = ((insn & THUMB_LSOP_OFFS) >> THUMB_LSOP_OFFS_SHIFT) << 2;
+ SET_REGISTER(cpustate, rd, READ32(GET_REGISTER(cpustate, rn) + offs)); // fix
+ R15 += 2;
+ }
+ else /* Store */
+ {
+ rn = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = insn & THUMB_ADDSUB_RD;
+ offs = ((insn & THUMB_LSOP_OFFS) >> THUMB_LSOP_OFFS_SHIFT) << 2;
+ WRITE32(GET_REGISTER(cpustate, rn) + offs, GET_REGISTER(cpustate, rd));
+ R15 += 2;
+ }
+ break;
+ case 0x7: /* Byte Store w/ Immeidate Offset */
+ if (insn & THUMB_LSOP_L) /* Load */
+ {
+ rn = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = insn & THUMB_ADDSUB_RD;
+ offs = (insn & THUMB_LSOP_OFFS) >> THUMB_LSOP_OFFS_SHIFT;
+ SET_REGISTER(cpustate, rd, READ8(GET_REGISTER(cpustate, rn) + offs));
+ R15 += 2;
+ }
+ else /* Store */
+ {
+ rn = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = insn & THUMB_ADDSUB_RD;
+ offs = (insn & THUMB_LSOP_OFFS) >> THUMB_LSOP_OFFS_SHIFT;
+ WRITE8(GET_REGISTER(cpustate, rn) + offs, GET_REGISTER(cpustate, rd));
+ R15 += 2;
+ }
+ break;
+ case 0x8: /* Load/Store Halfword */
+ if (insn & THUMB_HALFOP_L) /* Load */
+ {
+ imm = (insn & THUMB_HALFOP_OFFS) >> THUMB_HALFOP_OFFS_SHIFT;
+ rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
+ SET_REGISTER(cpustate, rd, READ16(GET_REGISTER(cpustate, rs) + (imm << 1)));
+ R15 += 2;
+ }
+ else /* Store */
+ {
+ imm = (insn & THUMB_HALFOP_OFFS) >> THUMB_HALFOP_OFFS_SHIFT;
+ rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
+ rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
+ WRITE16(GET_REGISTER(cpustate, rs) + (imm << 1), GET_REGISTER(cpustate, rd));
+ R15 += 2;
+ }
+ break;
+ case 0x9: /* Stack-Relative Load/Store */
+ if (insn & THUMB_STACKOP_L)
+ {
+ rd = (insn & THUMB_STACKOP_RD) >> THUMB_STACKOP_RD_SHIFT;
+ offs = (UINT8)(insn & THUMB_INSN_IMM);
+ readword = READ32(GET_REGISTER(cpustate, 13) + ((UINT32)offs << 2));
+ SET_REGISTER(cpustate, rd, readword);
+ R15 += 2;
+ }
+ else
+ {
+ rd = (insn & THUMB_STACKOP_RD) >> THUMB_STACKOP_RD_SHIFT;
+ offs = (UINT8)(insn & THUMB_INSN_IMM);
+ WRITE32(GET_REGISTER(cpustate, 13) + ((UINT32)offs << 2), GET_REGISTER(cpustate, rd));
+ R15 += 2;
+ }
+ break;
+ case 0xa: /* Get relative address */
+ if (insn & THUMB_RELADDR_SP) /* ADD Rd, SP, #nn */
+ {
+ rd = (insn & THUMB_RELADDR_RD) >> THUMB_RELADDR_RD_SHIFT;
+ offs = (UINT8)(insn & THUMB_INSN_IMM) << 2;
+ SET_REGISTER(cpustate, rd, GET_REGISTER(cpustate, 13) + offs);
+ R15 += 2;
+ }
+ else /* ADD Rd, PC, #nn */
+ {
+ rd = (insn & THUMB_RELADDR_RD) >> THUMB_RELADDR_RD_SHIFT;
+ offs = (UINT8)(insn & THUMB_INSN_IMM) << 2;
+ SET_REGISTER(cpustate, rd, ((R15 + 4) & ~2) + offs);
+ R15 += 2;
+ }
+ break;
+ case 0xb: /* Stack-Related Opcodes */
+ switch ((insn & THUMB_STACKOP_TYPE) >> THUMB_STACKOP_TYPE_SHIFT)
+ {
+ case 0x0: /* ADD SP, #imm */
+ addr = (insn & THUMB_INSN_IMM);
+ addr &= ~THUMB_INSN_IMM_S;
+ SET_REGISTER(cpustate, 13, GET_REGISTER(cpustate, 13) + ((insn & THUMB_INSN_IMM_S) ? -(addr << 2) : (addr << 2)));
+ R15 += 2;
+ break;
+ case 0x4: /* PUSH {Rlist} */
+ for (offs = 7; offs >= 0; offs--)
+ {
+ if (insn & (1 << offs))
+ {
+ SET_REGISTER(cpustate, 13, GET_REGISTER(cpustate, 13) - 4);
+ WRITE32(GET_REGISTER(cpustate, 13), GET_REGISTER(cpustate, offs));
+ }
+ }
+ R15 += 2;
+ break;
+ case 0x5: /* PUSH {Rlist}{LR} */
+ SET_REGISTER(cpustate, 13, GET_REGISTER(cpustate, 13) - 4);
+ WRITE32(GET_REGISTER(cpustate, 13), GET_REGISTER(cpustate, 14));
+ for (offs = 7; offs >= 0; offs--)
+ {
+ if (insn & (1 << offs))
+ {
+ SET_REGISTER(cpustate, 13, GET_REGISTER(cpustate, 13) - 4);
+ WRITE32(GET_REGISTER(cpustate, 13), GET_REGISTER(cpustate, offs));
+ }
+ }
+ R15 += 2;
+ break;
+ case 0xc: /* POP {Rlist} */
+ for (offs = 0; offs < 8; offs++)
+ {
+ if (insn & (1 << offs))
+ {
+ SET_REGISTER(cpustate, offs, READ32(GET_REGISTER(cpustate, 13)));
+ SET_REGISTER(cpustate, 13, GET_REGISTER(cpustate, 13) + 4);
+ }
+ }
+ R15 += 2;
+ break;
+ case 0xd: /* POP {Rlist}{PC} */
+ for (offs = 0; offs < 8; offs++)
+ {
+ if (insn & (1 << offs))
+ {
+ SET_REGISTER(cpustate, offs, READ32(GET_REGISTER(cpustate, 13)));
+ SET_REGISTER(cpustate, 13, GET_REGISTER(cpustate, 13) + 4);
+ }
+ }
+ R15 = READ32(GET_REGISTER(cpustate, 13)) & ~1;
+ SET_REGISTER(cpustate, 13, GET_REGISTER(cpustate, 13) + 4);
+ break;
+ default:
+ fatalerror("%08x: Gb Undefined Thumb instruction: %04x\n", pc, insn);
+ R15 += 2;
+ break;
+ }
+ break;
+ case 0xc: /* Multiple Load/Store */
+ {
+ UINT32 ld_st_address;
+
+ rd = (insn & THUMB_MULTLS_BASE) >> THUMB_MULTLS_BASE_SHIFT;
+
+ // "The address should normally be a word aligned quantity and non-word aligned addresses do not affect the instruction."
+ // "However, the bottom 2 bits of the address will appear on A[1:0] and might be interpreted by the memory system."
+
+ // GBA "BB Ball" performs an unaligned read with A[1:0] = 2 and expects A[1] not to be ignored [BP 800B90A,(R4&3)!=0]
+ // GBA "Gadget Racers" performs an unaligned read with A[1:0] = 1 and expects A[0] to be ignored [BP B72,(R0&3)!=0]
+
+ ld_st_address = GET_REGISTER(cpustate, rd);
+
+ if (insn & THUMB_MULTLS) /* Load */
+ {
+ int rd_in_list;
+
+ rd_in_list = insn & (1 << rd);
+ for (offs = 0; offs < 8; offs++)
+ {
+ if (insn & (1 << offs))
+ {
+ SET_REGISTER(cpustate, offs, READ32(ld_st_address & ~1));
+ ld_st_address += 4;
+ }
+ }
+ if (!rd_in_list)
+ SET_REGISTER(cpustate, rd, ld_st_address);
+ R15 += 2;
+ }
+ else /* Store */
+ {
+ for (offs = 0; offs < 8; offs++)
+ {
+ if (insn & (1 << offs))
+ {
+ WRITE32(ld_st_address & ~3, GET_REGISTER(cpustate, offs));
+ ld_st_address += 4;
+ }
+ }
+ SET_REGISTER(cpustate, rd, ld_st_address);
+ R15 += 2;
+ }
+ }
+ break;
+ case 0xd: /* Conditional Branch */
+ offs = (INT8)(insn & THUMB_INSN_IMM);
+ switch ((insn & THUMB_COND_TYPE) >> THUMB_COND_TYPE_SHIFT)
+ {
+ case COND_EQ:
+ if (Z_IS_SET(GET_CPSR))
+ {
+ R15 += 4 + (offs << 1);
+ }
+ else
+ {
+ R15 += 2;
+ }
+ break;
+ case COND_NE:
+ if (Z_IS_CLEAR(GET_CPSR))
+ {
+ R15 += 4 + (offs << 1);
+ }
+ else
+ {
+ R15 += 2;
+ }
+ break;
+ case COND_CS:
+ if (C_IS_SET(GET_CPSR))
+ {
+ R15 += 4 + (offs << 1);
+ }
+ else
+ {
+ R15 += 2;
+ }
+ break;
+ case COND_CC:
+ if (C_IS_CLEAR(GET_CPSR))
+ {
+ R15 += 4 + (offs << 1);
+ }
+ else
+ {
+ R15 += 2;
+ }
+ break;
+ case COND_MI:
+ if (N_IS_SET(GET_CPSR))
+ {
+ R15 += 4 + (offs << 1);
+ }
+ else
+ {
+ R15 += 2;
+ }
+ break;
+ case COND_PL:
+ if (N_IS_CLEAR(GET_CPSR))
+ {
+ R15 += 4 + (offs << 1);
+ }
+ else
+ {
+ R15 += 2;
+ }
+ break;
+ case COND_VS:
+ if (V_IS_SET(GET_CPSR))
+ {
+ R15 += 4 + (offs << 1);
+ }
+ else
+ {
+ R15 += 2;
+ }
+ break;
+ case COND_VC:
+ if (V_IS_CLEAR(GET_CPSR))
+ {
+ R15 += 4 + (offs << 1);
+ }
+ else
+ {
+ R15 += 2;
+ }
+ break;
+ case COND_HI:
+ if (C_IS_SET(GET_CPSR) && Z_IS_CLEAR(GET_CPSR))
+ {
+ R15 += 4 + (offs << 1);
+ }
+ else
+ {
+ R15 += 2;
+ }
+ break;
+ case COND_LS:
+ if (C_IS_CLEAR(GET_CPSR) || Z_IS_SET(GET_CPSR))
+ {
+ R15 += 4 + (offs << 1);
+ }
+ else
+ {
+ R15 += 2;
+ }
+ break;
+ case COND_GE:
+ if (!(GET_CPSR & N_MASK) == !(GET_CPSR & V_MASK))
+ {
+ R15 += 4 + (offs << 1);
+ }
+ else
+ {
+ R15 += 2;
+ }
+ break;
+ case COND_LT:
+ if (!(GET_CPSR & N_MASK) != !(GET_CPSR & V_MASK))
+ {
+ R15 += 4 + (offs << 1);
+ }
+ else
+ {
+ R15 += 2;
+ }
+ break;
+ case COND_GT:
+ if (Z_IS_CLEAR(GET_CPSR) && !(GET_CPSR & N_MASK) == !(GET_CPSR & V_MASK))
+ {
+ R15 += 4 + (offs << 1);
+ }
+ else
+ {
+ R15 += 2;
+ }
+ break;
+ case COND_LE:
+ if (Z_IS_SET(GET_CPSR) || !(GET_CPSR & N_MASK) != !(GET_CPSR & V_MASK))
+ {
+ R15 += 4 + (offs << 1);
+ }
+ else
+ {
+ R15 += 2;
+ }
+ break;
+ case COND_AL:
+ fatalerror("%08x: Undefined Thumb instruction: %04x (ARM9 reserved)\n", pc, insn);
+ R15 += 2;
+ break;
+ case COND_NV: // SWI (this is sort of a "hole" in the opcode encoding)
+ cpustate->pendingSwi = 1;
+ ARM7_CHECKIRQ;
+ break;
+ }
+ break;
+ case 0xe: /* B #offs */
+ if (insn & THUMB_BLOP_LO)
+ {
+ addr = GET_REGISTER(cpustate, 14);
+ addr += (insn & THUMB_BLOP_OFFS) << 1;
+ addr &= 0xfffffffc;
+ SET_REGISTER(cpustate, 14, (R15 + 4) | 1);
+ R15 = addr;
+ }
+ else
+ {
+ offs = (insn & THUMB_BRANCH_OFFS) << 1;
+ if (offs & 0x00000800)
+ {
+ offs |= 0xfffff800;
+ }
+ R15 += 4 + offs;
+ }
+ break;
+ case 0xf: /* BL */
+ if (insn & THUMB_BLOP_LO)
+ {
+ addr = GET_REGISTER(cpustate, 14) & ~1;
+ addr += (insn & THUMB_BLOP_OFFS) << 1;
+ SET_REGISTER(cpustate, 14, (R15 + 2) | 1);
+ R15 = addr;
+ //R15 += 2;
+ }
+ else
+ {
+ addr = (insn & THUMB_BLOP_OFFS) << 12;
+ if (addr & (1 << 22))
+ {
+ addr |= 0xff800000;
+ }
+ addr += R15 + 4;
+ SET_REGISTER(cpustate, 14, addr);
+ R15 += 2;
+ }
+ break;
+ default:
+ fatalerror("%08x: Undefined Thumb instruction: %04x\n", pc, insn);
+ R15 += 2;
+ break;
+ }
+ }
+ else
+ {
+ UINT32 raddr;
+
+ /* load 32 bit instruction */
+ pc = GET_PC;
+
+ // "In ARM state, bits [1:0] of r15 are undefined and must be ignored. Bits [31:2] contain the PC."
+ raddr = pc & (~3);
+
+ if ( COPRO_CTRL & COPRO_CTRL_MMU_EN )
+ {
+ raddr = arm7_tlb_translate(cpustate, raddr, ARM7_TLB_ABORT_P);
+ if (cpustate->pendingAbtP != 0)
+ {
+ goto skip_exec;
+ }
+ }
+
+#if 0
+ if (MODE26)
+ {
+ UINT32 temp1, temp2;
+ temp1 = GET_CPSR & 0xF00000C3;
+ temp2 = (R15 & 0xF0000000) | ((R15 & 0x0C000000) >> (26 - 6)) | (R15 & 0x00000003);
+ if (temp1 != temp2) fatalerror( "%08X: 32-bit and 26-bit modes are out of sync (%08X %08X)", pc, temp1, temp2);
+ }
+#endif
+
+ insn = cpustate->direct->read_decrypted_dword(raddr);
+
+ /* process condition codes for this instruction */
+ switch (insn >> INSN_COND_SHIFT)
+ {
+ case COND_EQ:
+ if (Z_IS_CLEAR(GET_CPSR))
+ goto L_Next;
+ break;
+ case COND_NE:
+ if (Z_IS_SET(GET_CPSR))
+ goto L_Next;
+ break;
+ case COND_CS:
+ if (C_IS_CLEAR(GET_CPSR))
+ goto L_Next;
+ break;
+ case COND_CC:
+ if (C_IS_SET(GET_CPSR))
+ goto L_Next;
+ break;
+ case COND_MI:
+ if (N_IS_CLEAR(GET_CPSR))
+ goto L_Next;
+ break;
+ case COND_PL:
+ if (N_IS_SET(GET_CPSR))
+ goto L_Next;
+ break;
+ case COND_VS:
+ if (V_IS_CLEAR(GET_CPSR))
+ goto L_Next;
+ break;
+ case COND_VC:
+ if (V_IS_SET(GET_CPSR))
+ goto L_Next;
+ break;
+ case COND_HI:
+ if (C_IS_CLEAR(GET_CPSR) || Z_IS_SET(GET_CPSR))
+ goto L_Next;
+ break;
+ case COND_LS:
+ if (C_IS_SET(GET_CPSR) && Z_IS_CLEAR(GET_CPSR))
+ goto L_Next;
+ break;
+ case COND_GE:
+ if (!(GET_CPSR & N_MASK) != !(GET_CPSR & V_MASK)) /* Use x ^ (x >> ...) method */
+ goto L_Next;
+ break;
+ case COND_LT:
+ if (!(GET_CPSR & N_MASK) == !(GET_CPSR & V_MASK))
+ goto L_Next;
+ break;
+ case COND_GT:
+ if (Z_IS_SET(GET_CPSR) || (!(GET_CPSR & N_MASK) != !(GET_CPSR & V_MASK)))
+ goto L_Next;
+ break;
+ case COND_LE:
+ if (Z_IS_CLEAR(GET_CPSR) && (!(GET_CPSR & N_MASK) == !(GET_CPSR & V_MASK)))
+ goto L_Next;
+ break;
+ case COND_NV:
+ goto L_Next;
+ }
+ /*******************************************************************/
+ /* If we got here - condition satisfied, so decode the instruction */
+ /*******************************************************************/
+ switch ((insn & 0xF000000) >> 24)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ /* Branch and Exchange (BX) */
+ if ((insn & 0x0ffffff0) == 0x012fff10) // bits 27-4 == 000100101111111111110001
+ {
+ R15 = GET_REGISTER(cpustate, insn & 0x0f);
+ // If new PC address has A0 set, switch to Thumb mode
+ if (R15 & 1) {
+ SET_CPSR(GET_CPSR|T_MASK);
+ R15--;
+ }
+ }
+ else if ((insn & 0x0ff000f0) == 0x01600010) // CLZ - v5
+ {
+ UINT32 rm = insn&0xf;
+ UINT32 rd = (insn>>12)&0xf;
+
+ SET_REGISTER(cpustate, rd, count_leading_zeros(GET_REGISTER(cpustate, rm)));
+
+ R15 += 4;
+ }
+ else if ((insn & 0x0ff000f0) == 0x01000050) // QADD - v5
+ {
+ INT32 src1 = GET_REGISTER(cpustate, insn&0xf);
+ INT32 src2 = GET_REGISTER(cpustate, (insn>>16)&0xf);
+ INT64 res;
+
+ res = saturate_qbit_overflow(cpustate, (INT64)src1 + (INT64)src2);
+
+ SET_REGISTER(cpustate, (insn>>12)&0xf, (INT32)res);
+ R15 += 4;
+ }
+ else if ((insn & 0x0ff000f0) == 0x01400050) // QDADD - v5
+ {
+ INT32 src1 = GET_REGISTER(cpustate, insn&0xf);
+ INT32 src2 = GET_REGISTER(cpustate, (insn>>16)&0xf);
+ INT64 res;
+
+ // check if doubling operation will overflow
+ res = (INT64)src2 * 2;
+ saturate_qbit_overflow(cpustate, res);
+
+ src2 *= 2;
+ res = saturate_qbit_overflow(cpustate, (INT64)src1 + (INT64)src2);
+
+ SET_REGISTER(cpustate, (insn>>12)&0xf, (INT32)res);
+ R15 += 4;
+ }
+ else if ((insn & 0x0ff000f0) == 0x01200050) // QSUB - v5
+ {
+ INT32 src1 = GET_REGISTER(cpustate, insn&0xf);
+ INT32 src2 = GET_REGISTER(cpustate, (insn>>16)&0xf);
+ INT64 res;
+
+ res = saturate_qbit_overflow(cpustate, (INT64)src1 - (INT64)src2);
+
+ SET_REGISTER(cpustate, (insn>>12)&0xf, (INT32)res);
+ R15 += 4;
+ }
+ else if ((insn & 0x0ff000f0) == 0x01600050) // QDSUB - v5
+ {
+ INT32 src1 = GET_REGISTER(cpustate, insn&0xf);
+ INT32 src2 = GET_REGISTER(cpustate, (insn>>16)&0xf);
+ INT64 res;
+
+ // check if doubling operation will overflow
+ res = (INT64)src2 * 2;
+ saturate_qbit_overflow(cpustate, res);
+
+ src2 *= 2;
+ res = saturate_qbit_overflow(cpustate, (INT64)src1 - (INT64)src2);
+
+ SET_REGISTER(cpustate, (insn>>12)&0xf, (INT32)res);
+ R15 += 4;
+ }
+ else if ((insn & 0x0ff00090) == 0x01000080) // SMLAxy - v5
+ {
+ INT32 src1 = GET_REGISTER(cpustate, insn&0xf);
+ INT32 src2 = GET_REGISTER(cpustate, (insn>>8)&0xf);
+ INT32 res1;
+
+ // select top and bottom halves of src1/src2 and sign extend if necessary
+ if (insn & 0x20)
+ {
+ src1 >>= 16;
+ }
+ else
+ {
+ src1 &= 0xffff;
+ if (src1 & 0x8000)
+ {
+ src1 |= 0xffff;
+ }
+ }
+
+ if (insn & 0x40)
+ {
+ src2 >>= 16;
+ }
+ else
+ {
+ src2 &= 0xffff;
+ if (src2 & 0x8000)
+ {
+ src2 |= 0xffff;
+ }
+ }
+
+ // do the signed multiply
+ res1 = src1 * src2;
+ // and the accumulate. NOTE: only the accumulate can cause an overflow, which is why we do it this way.
+ saturate_qbit_overflow(cpustate, (INT64)res1 + (INT64)GET_REGISTER(cpustate, (insn>>12)&0xf));
+
+ SET_REGISTER(cpustate, (insn>>16)&0xf, res1 + GET_REGISTER(cpustate, (insn>>12)&0xf));
+ R15 += 4;
+ }
+ else if ((insn & 0x0ff00090) == 0x01400080) // SMLALxy - v5
+ {
+ INT32 src1 = GET_REGISTER(cpustate, insn&0xf);
+ INT32 src2 = GET_REGISTER(cpustate, (insn>>8)&0xf);
+ INT64 dst;
+
+ // select top and bottom halves of src1/src2 and sign extend if necessary
+ if (insn & 0x20)
+ {
+ src1 >>= 16;
+ }
+ else
+ {
+ src1 &= 0xffff;
+ if (src1 & 0x8000)
+ {
+ src1 |= 0xffff;
+ }
+ }
+
+ if (insn & 0x40)
+ {
+ src2 >>= 16;
+ }
+ else
+ {
+ src2 &= 0xffff;
+ if (src2 & 0x8000)
+ {
+ src2 |= 0xffff;
+ }
+ }
+
+ dst = (INT64)GET_REGISTER(cpustate, (insn>>12)&0xf);
+ dst |= (INT64)GET_REGISTER(cpustate, (insn>>16)&0xf)<<32;
+
+ // do the multiply and accumulate
+ dst += (INT64)src1 * (INT64)src2;
+
+ // write back the result
+ SET_REGISTER(cpustart, (insn>>12)&0xf, (UINT32)(dst&0xffffffff));
+ SET_REGISTER(cpustart, (insn>>16)&0xf, (UINT32)(dst>>32));
+ }
+ else if ((insn & 0x0ff00090) == 0x01600080) // SMULxy - v5
+ {
+ INT32 src1 = GET_REGISTER(cpustate, insn&0xf);
+ INT32 src2 = GET_REGISTER(cpustate, (insn>>8)&0xf);
+ INT32 res;
+
+ // select top and bottom halves of src1/src2 and sign extend if necessary
+ if (insn & 0x20)
+ {
+ src1 >>= 16;
+ }
+ else
+ {
+ src1 &= 0xffff;
+ if (src1 & 0x8000)
+ {
+ src1 |= 0xffff;
+ }
+ }
+
+ if (insn & 0x40)
+ {
+ src2 >>= 16;
+ }
+ else
+ {
+ src2 &= 0xffff;
+ if (src2 & 0x8000)
+ {
+ src2 |= 0xffff;
+ }
+ }
+
+ res = src1 * src2;
+ SET_REGISTER(cpustart, (insn>>16)&0xf, res);
+ }
+ else if ((insn & 0x0ff000b0) == 0x012000a0) // SMULWy - v5
+ {
+ INT32 src1 = GET_REGISTER(cpustate, insn&0xf);
+ INT32 src2 = GET_REGISTER(cpustate, (insn>>8)&0xf);
+ INT64 res;
+
+ if (insn & 0x40)
+ {
+ src2 >>= 16;
+ }
+ else
+ {
+ src2 &= 0xffff;
+ if (src2 & 0x8000)
+ {
+ src2 |= 0xffff;
+ }
+ }
+
+ res = (INT64)src1 * (INT64)src2;
+ res >>= 16;
+ SET_REGISTER(cpustart, (insn>>16)&0xf, (UINT32)res);
+ }
+ else if ((insn & 0x0ff000b0) == 0x01200080) // SMLAWy - v5
+ {
+ INT32 src1 = GET_REGISTER(cpustate, insn&0xf);
+ INT32 src2 = GET_REGISTER(cpustate, (insn>>8)&0xf);
+ INT32 src3 = GET_REGISTER(cpustate, (insn>>12)&0xf);
+ INT64 res;
+
+ if (insn & 0x40)
+ {
+ src2 >>= 16;
+ }
+ else
+ {
+ src2 &= 0xffff;
+ if (src2 & 0x8000)
+ {
+ src2 |= 0xffff;
+ }
+ }
+
+ res = (INT64)src1 * (INT64)src2;
+ res >>= 16;
+
+ // check for overflow and set the Q bit
+ saturate_qbit_overflow(cpustate, (INT64)src3 + res);
+
+ // do the real accumulate
+ src3 += (INT32)res;
+
+ // write the result back
+ SET_REGISTER(cpustart, (insn>>16)&0xf, (UINT32)res);
+ }
+ else
+ /* Multiply OR Swap OR Half Word Data Transfer */
+ if ((insn & 0x0e000000) == 0 && (insn & 0x80) && (insn & 0x10)) // bits 27-25=000 bit 7=1 bit 4=1
+ {
+ /* Half Word Data Transfer */
+ if (insn & 0x60) // bits = 6-5 != 00
+ {
+ HandleHalfWordDT(cpustate, insn);
+ }
+ else
+ /* Swap */
+ if (insn & 0x01000000) // bit 24 = 1
+ {
+ HandleSwap(cpustate, insn);
+ }
+ /* Multiply Or Multiply Long */
+ else
+ {
+ /* multiply long */
+ if (insn & 0x800000) // Bit 23 = 1 for Multiply Long
+ {
+ /* Signed? */
+ if (insn & 0x00400000)
+ HandleSMulLong(cpustate, insn);
+ else
+ HandleUMulLong(cpustate, insn);
+ }
+ /* multiply */
+ else
+ {
+ HandleMul(cpustate, insn);
+ }
+ R15 += 4;
+ }
+ }
+ else
+ /* Data Processing OR PSR Transfer */
+ if ((insn & 0x0c000000) == 0) // bits 27-26 == 00 - This check can only exist properly after Multiplication check above
+ {
+ /* PSR Transfer (MRS & MSR) */
+ if (((insn & 0x00100000) == 0) && ((insn & 0x01800000) == 0x01000000)) // S bit must be clear, and bit 24,23 = 10
+ {
+ HandlePSRTransfer(cpustate, insn);
+ ARM7_ICOUNT += 2; // PSR only takes 1 - S Cycle, so we add + 2, since at end, we -3..
+ R15 += 4;
+ }
+ /* Data Processing */
+ else
+ {
+ HandleALU(cpustate, insn);
+ }
+ }
+ break;
+ /* Data Transfer - Single Data Access */
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ HandleMemSingle(cpustate, insn);
+ R15 += 4;
+ break;
+ /* Block Data Transfer/Access */
+ case 8:
+ case 9:
+ HandleMemBlock(cpustate, insn);
+ R15 += 4;
+ break;
+ /* Branch or Branch & Link */
+ case 0xa:
+ case 0xb:
+ HandleBranch(cpustate, insn);
+ break;
+ /* Co-Processor Data Transfer */
+ case 0xc:
+ case 0xd:
+ HandleCoProcDT(cpustate, insn);
+ R15 += 4;
+ break;
+ /* Co-Processor Data Operation or Register Transfer */
+ case 0xe:
+ if (insn & 0x10)
+ HandleCoProcRT(cpustate, insn);
+ else
+ HandleCoProcDO(cpustate, insn);
+ R15 += 4;
+ break;
+ /* Software Interrupt */
+ case 0x0f:
+ cpustate->pendingSwi = 1;
+ ARM7_CHECKIRQ;
+ //couldn't find any cycle counts for SWI
+ break;
+ /* Undefined */
+ default:
+ cpustate->pendingSwi = 1;
+ ARM7_CHECKIRQ;
+ ARM7_ICOUNT -= 1; //undefined takes 4 cycles (page 77)
+ LOG(("%08x: Undefined instruction\n",pc-4));
+ L_Next:
+ R15 += 4;
+ ARM7_ICOUNT +=2; //Any unexecuted instruction only takes 1 cycle (page 193)
+ }
+ }
+
+skip_exec:
+
+ ARM7_CHECKIRQ;
+
+ /* All instructions remove 3 cycles.. Others taking less / more will have adjusted this # prior to here */
+ ARM7_ICOUNT -= 3;
+ } while (ARM7_ICOUNT > 0);
+}
diff --git a/trunk/src/emu/cpu/asap/asap.c b/trunk/src/emu/cpu/asap/asap.c
new file mode 100644
index 00000000000..115278ec9a9
--- /dev/null
+++ b/trunk/src/emu/cpu/asap/asap.c
@@ -0,0 +1,1714 @@
+/***************************************************************************
+
+ asap.c
+
+ Core implementation for the portable ASAP emulator.
+ ASAP = Atari Simplified Architecture Processor
+
+ Special thanks to Mike Albaugh for clarification on a couple of fine points.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "asap.h"
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+const UINT32 PS_CFLAG = 0x00000001;
+const UINT32 PS_VFLAG = 0x00000002;
+const UINT32 PS_ZFLAG = 0x00000004;
+const UINT32 PS_NFLAG = 0x00000008;
+const UINT32 PS_IFLAG = 0x00000010;
+const UINT32 PS_PFLAG = 0x00000020;
+
+const int EXCEPTION_RESET = 0;
+const int EXCEPTION_TRAP0 = 1;
+const int EXCEPTION_TRAPF = 2;
+const int EXCEPTION_INTERRUPT = 3;
+
+const int REGBASE = 0xffe0;
+
+
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+#define SET_C_ADD(a,b) (m_cflag = (UINT32)(b) > (UINT32)(~(a)))
+#define SET_C_SUB(a,b) (m_cflag = (UINT32)(b) <= (UINT32)(a))
+#define SET_V_ADD(r,a,b) (m_vflag = ~((a) ^ (b)) & ((a) ^ (r)))
+#define SET_V_SUB(r,a,b) (m_vflag = ((a) ^ (b)) & ((a) ^ (r)))
+#define SET_ZN(r) (m_znflag = (r))
+#define SET_ZNCV_ADD(r,a,b) SET_ZN(r); SET_C_ADD(a,b); SET_V_ADD(r,a,b)
+#define SET_ZNCV_SUB(r,a,b) SET_ZN(r); SET_C_SUB(a,b); SET_V_SUB(r,a,b)
+
+#define SET_VFLAG(val) (m_vflag = (val) << 31)
+#define SET_CFLAG(val) (m_cflag = (val))
+
+#define GET_FLAGS() (m_cflag | \
+ ((m_vflag >> 30) & PS_VFLAG) | \
+ ((m_znflag == 0) << 2) | \
+ ((m_znflag >> 28) & PS_NFLAG) | \
+ (m_iflag << 4) | \
+ (m_pflag << 5))
+
+#define SET_FLAGS(v) do { \
+ m_cflag = (v) & PS_CFLAG; \
+ m_vflag = ((v) & PS_VFLAG) << 30; \
+ m_znflag = ((v) & PS_ZFLAG) ? 0 : ((v) & PS_NFLAG) ? -1 : 1; \
+ m_iflag = ((v) & PS_IFLAG) >> 4; \
+ m_pflag = ((v) & PS_PFLAG) >> 5; \
+ } while (0);
+
+#define OPCODE (m_op >> 27)
+#define DSTREG ((m_op >> 22) & 31)
+#define DSTVAL m_src2val[REGBASE + DSTREG]
+#define SRC1REG ((m_op >> 16) & 31)
+#define SRC1VAL m_src2val[REGBASE + SRC1REG]
+#define SRC2VAL m_src2val[m_op & 0xffff]
+
+
+
+//**************************************************************************
+// STATIC OPCODE TABLES
+//**************************************************************************
+
+const asap_device::ophandler asap_device::s_opcodetable[32][4] =
+{
+ { &asap_device::trap0, &asap_device::trap0, &asap_device::trap0, &asap_device::trap0 },
+ { &asap_device::noop, &asap_device::noop, &asap_device::noop, &asap_device::noop },
+ { &asap_device::bsr, &asap_device::bsr_0, &asap_device::bsr, &asap_device::bsr_0 },
+ { &asap_device::lea, &asap_device::noop, &asap_device::lea_c, &asap_device::lea_c0 },
+ { &asap_device::leah, &asap_device::noop, &asap_device::leah_c, &asap_device::leah_c0 },
+ { &asap_device::subr, &asap_device::noop, &asap_device::subr_c, &asap_device::subr_c0 },
+ { &asap_device::xor_, &asap_device::noop, &asap_device::xor_c, &asap_device::xor_c0 },
+ { &asap_device::xorn, &asap_device::noop, &asap_device::xorn_c, &asap_device::xorn_c0 },
+ { &asap_device::add, &asap_device::noop, &asap_device::add_c, &asap_device::add_c0 },
+ { &asap_device::sub, &asap_device::noop, &asap_device::sub_c, &asap_device::sub_c0 },
+ { &asap_device::addc, &asap_device::noop, &asap_device::addc_c, &asap_device::addc_c0 },
+ { &asap_device::subc, &asap_device::noop, &asap_device::subc_c, &asap_device::subc_c0 },
+ { &asap_device::and_, &asap_device::noop, &asap_device::and_c, &asap_device::and_c0 },
+ { &asap_device::andn, &asap_device::noop, &asap_device::andn_c, &asap_device::andn_c0 },
+ { &asap_device::or_, &asap_device::noop, &asap_device::or_c, &asap_device::or_c0 },
+ { &asap_device::orn, &asap_device::noop, &asap_device::orn_c, &asap_device::orn_c0 },
+ { &asap_device::ld, &asap_device::ld_0, &asap_device::ld_c, &asap_device::ld_c0 },
+ { &asap_device::ldh, &asap_device::ldh_0, &asap_device::ldh_c, &asap_device::ldh_c0 },
+ { &asap_device::lduh, &asap_device::lduh_0, &asap_device::lduh_c, &asap_device::lduh_c0 },
+ { &asap_device::sth, &asap_device::sth_0, &asap_device::sth_c, &asap_device::sth_c0 },
+ { &asap_device::st, &asap_device::st_0, &asap_device::st_c, &asap_device::st_c0 },
+ { &asap_device::ldb, &asap_device::ldb_0, &asap_device::ldb_c, &asap_device::ldb_c0 },
+ { &asap_device::ldub, &asap_device::ldub_0, &asap_device::ldub_c, &asap_device::ldub_c0 },
+ { &asap_device::stb, &asap_device::stb_0, &asap_device::stb_c, &asap_device::stb_c0 },
+ { &asap_device::ashr, &asap_device::noop, &asap_device::ashr_c, &asap_device::ashr_c0 },
+ { &asap_device::lshr, &asap_device::noop, &asap_device::lshr_c, &asap_device::lshr_c0 },
+ { &asap_device::ashl, &asap_device::noop, &asap_device::ashl_c, &asap_device::ashl_c0 },
+ { &asap_device::rotl, &asap_device::noop, &asap_device::rotl_c, &asap_device::rotl_c0 },
+ { &asap_device::getps, &asap_device::noop, &asap_device::getps, &asap_device::noop },
+ { &asap_device::putps, &asap_device::putps, &asap_device::putps, &asap_device::putps },
+ { &asap_device::jsr, &asap_device::jsr_0, &asap_device::jsr_c, &asap_device::jsr_c0 },
+ { &asap_device::trapf, &asap_device::trapf, &asap_device::trapf, &asap_device::trapf }
+};
+
+const asap_device::ophandler asap_device::s_conditiontable[16] =
+{
+ &asap_device::bsp, &asap_device::bmz, &asap_device::bgt, &asap_device::ble,
+ &asap_device::bge, &asap_device::blt, &asap_device::bhi, &asap_device::bls,
+ &asap_device::bcc, &asap_device::bcs, &asap_device::bpl, &asap_device::bmi,
+ &asap_device::bne, &asap_device::beq, &asap_device::bvc, &asap_device::bvs
+};
+
+
+
+//**************************************************************************
+// DEVICE INTERFACE
+//**************************************************************************
+
+// device type definition
+const device_type ASAP = &device_creator<asap_device>;
+
+//-------------------------------------------------
+// asap_device - constructor
+//-------------------------------------------------
+
+asap_device::asap_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : cpu_device(mconfig, ASAP, "ASAP", tag, owner, clock),
+ m_program_config("program", ENDIANNESS_LITTLE, 32, 32),
+ m_pc(0),
+ m_pflag(0),
+ m_iflag(0),
+ m_cflag(0),
+ m_vflag(0),
+ m_znflag(0),
+ m_flagsio(0),
+ m_op(0),
+ m_ppc(0),
+ m_nextpc(0),
+ m_irq_state(0),
+ m_icount(0),
+ m_program(NULL),
+ m_direct(NULL)
+{
+ // initialize the src2val table to contain immediates for low values
+ for (int i = 0; i < REGBASE; i++)
+ m_src2val[i] = i;
+
+ // build the opcode table
+ for (int op = 0; op < 32; op++)
+ for (int dst = 0; dst < 32; dst++)
+ for (int cond = 0; cond < 2; cond++)
+ if (op == 1)
+ m_opcode[(op << 6) + (dst << 1) + cond] = s_conditiontable[dst & 15];
+ else if (cond && dst == 0)
+ m_opcode[(op << 6) + (dst << 1) + cond] = s_opcodetable[op][3];
+ else if (cond)
+ m_opcode[(op << 6) + (dst << 1) + cond] = s_opcodetable[op][2];
+ else if (dst == 0)
+ m_opcode[(op << 6) + (dst << 1) + cond] = s_opcodetable[op][1];
+ else
+ m_opcode[(op << 6) + (dst << 1) + cond] = s_opcodetable[op][0];
+}
+
+
+//-------------------------------------------------
+// device_start - start up the device
+//-------------------------------------------------
+
+void asap_device::device_start()
+{
+ // get our address spaces
+ m_program = space(AS_PROGRAM);
+ m_direct = &m_program->direct();
+
+ // register our state for the debugger
+ astring tempstr;
+ state_add(STATE_GENPC, "GENPC", m_pc).noshow();
+ state_add(STATE_GENPCBASE, "GENPCBASE", m_ppc).noshow();
+ state_add(STATE_GENSP, "GENSP", m_src2val[REGBASE + 31]).noshow();
+ state_add(STATE_GENFLAGS, "GENFLAGS", m_flagsio).callimport().callexport().formatstr("%6s").noshow();
+ state_add(ASAP_PC, "PC", m_pc);
+ state_add(ASAP_PS, "PS", m_flagsio).callimport().callexport();
+ for (int regnum = 0; regnum < 32; regnum++)
+ state_add(ASAP_R0 + regnum, tempstr.format("R%d", regnum), m_src2val[REGBASE + regnum]);
+
+ // register our state for saving
+ save_item(NAME(m_pc));
+ save_item(NAME(m_pflag));
+ save_item(NAME(m_iflag));
+ save_item(NAME(m_cflag));
+ save_item(NAME(m_vflag));
+ save_item(NAME(m_znflag));
+ save_item(NAME(m_op));
+ save_item(NAME(m_ppc));
+ save_item(NAME(m_nextpc));
+ save_item(NAME(m_irq_state));
+
+ // set our instruction counter
+ m_icountptr = &m_icount;
+}
+
+
+//-------------------------------------------------
+// device_reset - reset the device
+//-------------------------------------------------
+
+void asap_device::device_reset()
+{
+ // initialize the state
+ m_src2val[REGBASE + 0] = 0;
+ m_pc = 0;
+ m_iflag = 0;
+
+ m_ppc = 0;
+ m_nextpc = ~0;
+ m_irq_state = 0;
+}
+
+
+//-------------------------------------------------
+// memory_space_config - return the configuration
+// of the specified address space, or NULL if
+// the space doesn't exist
+//-------------------------------------------------
+
+const address_space_config *asap_device::memory_space_config(address_spacenum spacenum) const
+{
+ return (spacenum == AS_PROGRAM) ? &m_program_config : NULL;
+}
+
+
+//-------------------------------------------------
+// state_import - import state into the device,
+// after it has been set
+//-------------------------------------------------
+
+void asap_device::state_import(const device_state_entry &entry)
+{
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ case ASAP_PS:
+ SET_FLAGS(m_flagsio);
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// state_export - export state from the device,
+// to a known location where it can be read
+//-------------------------------------------------
+
+void asap_device::state_export(const device_state_entry &entry)
+{
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ case ASAP_PS:
+ m_flagsio = GET_FLAGS();
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// state_string_export - export state as a string
+// for the debugger
+//-------------------------------------------------
+
+void asap_device::state_string_export(const device_state_entry &entry, astring &string)
+{
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ string.printf("%c%c%c%c%c%c",
+ m_pflag ? 'P' : '.',
+ m_iflag ? 'I' : '.',
+ ((INT32)m_znflag < 0) ? 'N' : '.',
+ (m_znflag == 0) ? 'Z' : '.',
+ ((m_vflag >> 30) & PS_VFLAG) ? 'V' : '.',
+ m_cflag ? 'C' : '.');
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// disasm_min_opcode_bytes - return the length
+// of the shortest instruction, in bytes
+//-------------------------------------------------
+
+UINT32 asap_device::disasm_min_opcode_bytes() const
+{
+ return 4;
+}
+
+
+//-------------------------------------------------
+// disasm_max_opcode_bytes - return the length
+// of the longest instruction, in bytes
+//-------------------------------------------------
+
+UINT32 asap_device::disasm_max_opcode_bytes() const
+{
+ return 12;
+}
+
+
+//-------------------------------------------------
+// disasm_disassemble - call the disassembly
+// helper function
+//-------------------------------------------------
+
+offs_t asap_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
+{
+ extern CPU_DISASSEMBLE( asap );
+ return CPU_DISASSEMBLE_NAME(asap)(NULL, buffer, pc, oprom, opram, 0);
+}
+
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// readop - read an opcode at the given address
+//-------------------------------------------------
+
+inline UINT32 asap_device::readop(offs_t pc)
+{
+ return m_direct->read_decrypted_dword(pc);
+}
+
+
+//-------------------------------------------------
+// readbyte - read a byte at the given address
+//-------------------------------------------------
+
+inline UINT8 asap_device::readbyte(offs_t address)
+{
+ // no alignment issues with bytes
+ return m_program->read_byte(address);
+}
+
+
+//-------------------------------------------------
+// readword - read a word at the given address
+//-------------------------------------------------
+
+inline UINT16 asap_device::readword(offs_t address)
+{
+ // aligned reads are easy
+ if (!(address & 1))
+ return m_program->read_word(address);
+
+ // misaligned reads are tricky
+ return m_program->read_dword(address & ~3) >> (address & 3);
+}
+
+
+//-------------------------------------------------
+// readlong - read a long at the given address
+//-------------------------------------------------
+
+inline UINT32 asap_device::readlong(offs_t address)
+{
+ // aligned reads are easy
+ if (!(address & 3))
+ return m_program->read_dword(address);
+
+ // misaligned reads are tricky
+ return m_program->read_dword(address & ~3) >> (address & 3);
+}
+
+
+//-------------------------------------------------
+// writebyte - write a byte at the given address
+//-------------------------------------------------
+
+inline void asap_device::writebyte(offs_t address, UINT8 data)
+{
+ // no alignment issues with bytes
+ m_program->write_byte(address, data);
+}
+
+
+//-------------------------------------------------
+// writeword - write a word at the given address
+//-------------------------------------------------
+
+inline void asap_device::writeword(offs_t address, UINT16 data)
+{
+ // aligned writes are easy
+ if (!(address & 1))
+ {
+ m_program->write_word(address, data);
+ return;
+ }
+
+ // misaligned writes are tricky
+ if (!(address & 2))
+ {
+ m_program->write_byte(address + 1, data);
+ m_program->write_byte(address + 2, data >> 8);
+ }
+ else
+ m_program->write_byte(address + 1, data);
+}
+
+
+//-------------------------------------------------
+// writelong - write a long at the given address
+//-------------------------------------------------
+
+inline void asap_device::writelong(offs_t address, UINT32 data)
+{
+ // aligned writes are easy
+ if (!(address & 3))
+ {
+ m_program->write_dword(address, data);
+ return;
+ }
+
+ // misaligned writes are tricky
+ switch (address & 3)
+ {
+ case 1:
+ m_program->write_byte(address, data);
+ m_program->write_word(address + 1, data >> 8);
+ break;
+ case 2:
+ m_program->write_word(address, data);
+ break;
+ case 3:
+ m_program->write_byte(address, data);
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// generate_exception - generate an exception of
+// the requested type
+//-------------------------------------------------
+
+inline void asap_device::generate_exception(int exception)
+{
+ m_pflag = m_iflag;
+ m_iflag = 0;
+
+ m_src2val[REGBASE + 30] = m_pc;
+ m_src2val[REGBASE + 31] = (m_nextpc == ~0) ? m_pc + 4 : m_nextpc;
+
+ m_pc = 0x40 * exception;
+ m_nextpc = ~0;
+
+ m_icount--;
+}
+
+
+//-------------------------------------------------
+// check_irqs - check for pending IRQs
+//-------------------------------------------------
+
+inline void asap_device::check_irqs()
+{
+ if (m_irq_state && m_iflag)
+ {
+ generate_exception(EXCEPTION_INTERRUPT);
+ standard_irq_callback(ASAP_IRQ0);
+ }
+}
+
+
+
+//**************************************************************************
+// CORE EXECUTION
+//**************************************************************************
+
+inline void asap_device::fetch_instruction()
+{
+ // debugging
+ m_ppc = m_pc;
+
+ // instruction fetch
+ m_op = readop(m_pc);
+ m_pc += 4;
+}
+
+inline void asap_device::fetch_instruction_debug()
+{
+ // debugging
+ m_ppc = m_pc;
+ debugger_instruction_hook(this, m_pc);
+
+ // instruction fetch
+ m_op = readop(m_pc);
+ m_pc += 4;
+}
+
+inline void asap_device::execute_instruction()
+{
+ // parse the instruction
+ (this->*m_opcode[m_op >> 21])();
+}
+
+
+//-------------------------------------------------
+// execute_min_cycles - return minimum number of
+// cycles it takes for one instruction to execute
+//-------------------------------------------------
+
+UINT32 asap_device::execute_min_cycles() const
+{
+ return 1;
+}
+
+
+//-------------------------------------------------
+// execute_max_cycles - return maximum number of
+// cycles it takes for one instruction to execute
+//-------------------------------------------------
+
+UINT32 asap_device::execute_max_cycles() const
+{
+ return 2;
+}
+
+
+//-------------------------------------------------
+// execute_input_lines - return the number of
+// input/interrupt lines
+//-------------------------------------------------
+
+UINT32 asap_device::execute_input_lines() const
+{
+ return 1;
+}
+
+
+void asap_device::execute_set_input(int inputnum, int state)
+{
+ m_irq_state = (state != CLEAR_LINE);
+}
+
+
+void asap_device::execute_run()
+{
+ // check for IRQs
+ check_irqs();
+
+ // core execution loop
+ if ((device_t::machine().debug_flags & DEBUG_FLAG_ENABLED) == 0)
+ {
+ do
+ {
+ // fetch and execute the next instruction
+ fetch_instruction();
+ execute_instruction();
+
+ // fetch and execute the next instruction
+ fetch_instruction();
+ execute_instruction();
+
+ // fetch and execute the next instruction
+ fetch_instruction();
+ execute_instruction();
+
+ // fetch and execute the next instruction
+ fetch_instruction();
+ execute_instruction();
+
+ m_icount -= 4;
+
+ } while (m_icount > 0);
+ }
+ else
+ {
+ do
+ {
+ // fetch and execute the next instruction
+ fetch_instruction_debug();
+ execute_instruction();
+
+ // fetch and execute the next instruction
+ fetch_instruction_debug();
+ execute_instruction();
+
+ // fetch and execute the next instruction
+ fetch_instruction_debug();
+ execute_instruction();
+
+ // fetch and execute the next instruction
+ fetch_instruction_debug();
+ execute_instruction();
+
+ m_icount -= 4;
+
+ } while (m_icount > 0);
+ }
+}
+
+
+
+//**************************************************************************
+// OPCODE IMPLEMENTATIONS
+//**************************************************************************
+
+void asap_device::noop()
+{
+}
+
+/**************************** TRAP 0 ******************************/
+
+void asap_device::trap0()
+{
+ generate_exception(EXCEPTION_TRAP0);
+}
+
+/**************************** Bcc ******************************/
+
+void asap_device::bsp()
+{
+ if ((INT32)m_znflag > 0)
+ {
+ m_nextpc = m_ppc + ((INT32)(m_op << 10) >> 8);
+
+ fetch_instruction();
+ m_pc = m_nextpc;
+ m_nextpc = ~0;
+
+ execute_instruction();
+ m_icount--;
+ }
+}
+
+void asap_device::bmz()
+{
+ if ((INT32)m_znflag <= 0)
+ {
+ m_nextpc = m_ppc + ((INT32)(m_op << 10) >> 8);
+
+ fetch_instruction();
+ m_pc = m_nextpc;
+ m_nextpc = ~0;
+
+ execute_instruction();
+ m_icount--;
+ }
+}
+
+void asap_device::bgt()
+{
+ if (m_znflag != 0 && (INT32)(m_znflag ^ m_vflag) >= 0)
+ {
+ m_nextpc = m_ppc + ((INT32)(m_op << 10) >> 8);
+
+ fetch_instruction();
+ m_pc = m_nextpc;
+ m_nextpc = ~0;
+
+ execute_instruction();
+ m_icount--;
+ }
+}
+
+void asap_device::ble()
+{
+ if (m_znflag == 0 || (INT32)(m_znflag ^ m_vflag) < 0)
+ {
+ m_nextpc = m_ppc + ((INT32)(m_op << 10) >> 8);
+
+ fetch_instruction();
+ m_pc = m_nextpc;
+ m_nextpc = ~0;
+
+ execute_instruction();
+ m_icount--;
+ }
+}
+
+void asap_device::bge()
+{
+ if ((INT32)(m_znflag ^ m_vflag) >= 0)
+ {
+ m_nextpc = m_ppc + ((INT32)(m_op << 10) >> 8);
+
+ fetch_instruction();
+ m_pc = m_nextpc;
+ m_nextpc = ~0;
+
+ execute_instruction();
+ m_icount--;
+ }
+}
+
+void asap_device::blt()
+{
+ if ((INT32)(m_znflag ^ m_vflag) < 0)
+ {
+ m_nextpc = m_ppc + ((INT32)(m_op << 10) >> 8);
+
+ fetch_instruction();
+ m_pc = m_nextpc;
+ m_nextpc = ~0;
+
+ execute_instruction();
+ m_icount--;
+ }
+}
+
+void asap_device::bhi()
+{
+ if (m_znflag != 0 && m_cflag)
+ {
+ m_nextpc = m_ppc + ((INT32)(m_op << 10) >> 8);
+
+ fetch_instruction();
+ m_pc = m_nextpc;
+ m_nextpc = ~0;
+
+ execute_instruction();
+ m_icount--;
+ }
+}
+
+void asap_device::bls()
+{
+ if (m_znflag == 0 || !m_cflag)
+ {
+ m_nextpc = m_ppc + ((INT32)(m_op << 10) >> 8);
+
+ fetch_instruction();
+ m_pc = m_nextpc;
+ m_nextpc = ~0;
+
+ execute_instruction();
+ m_icount--;
+ }
+}
+
+void asap_device::bcc()
+{
+ if (!m_cflag)
+ {
+ m_nextpc = m_ppc + ((INT32)(m_op << 10) >> 8);
+
+ fetch_instruction();
+ m_pc = m_nextpc;
+ m_nextpc = ~0;
+
+ execute_instruction();
+ m_icount--;
+ }
+}
+
+void asap_device::bcs()
+{
+ if (m_cflag)
+ {
+ m_nextpc = m_ppc + ((INT32)(m_op << 10) >> 8);
+
+ fetch_instruction();
+ m_pc = m_nextpc;
+ m_nextpc = ~0;
+
+ execute_instruction();
+ m_icount--;
+ }
+}
+
+void asap_device::bpl()
+{
+ if ((INT32)m_znflag >= 0)
+ {
+ m_nextpc = m_ppc + ((INT32)(m_op << 10) >> 8);
+
+ fetch_instruction();
+ m_pc = m_nextpc;
+ m_nextpc = ~0;
+
+ execute_instruction();
+ m_icount--;
+ }
+}
+
+void asap_device::bmi()
+{
+ if ((INT32)m_znflag < 0)
+ {
+ m_nextpc = m_ppc + ((INT32)(m_op << 10) >> 8);
+
+ fetch_instruction();
+ m_pc = m_nextpc;
+ m_nextpc = ~0;
+
+ execute_instruction();
+ m_icount--;
+ }
+}
+
+void asap_device::bne()
+{
+ if (m_znflag != 0)
+ {
+ m_nextpc = m_ppc + ((INT32)(m_op << 10) >> 8);
+
+ fetch_instruction();
+ m_pc = m_nextpc;
+ m_nextpc = ~0;
+
+ execute_instruction();
+ m_icount--;
+ }
+}
+
+void asap_device::beq()
+{
+ if (m_znflag == 0)
+ {
+ m_nextpc = m_ppc + ((INT32)(m_op << 10) >> 8);
+
+ fetch_instruction();
+ m_pc = m_nextpc;
+ m_nextpc = ~0;
+
+ execute_instruction();
+ m_icount--;
+ }
+}
+
+void asap_device::bvc()
+{
+ if ((INT32)m_vflag >= 0)
+ {
+ m_nextpc = m_ppc + ((INT32)(m_op << 10) >> 8);
+
+ fetch_instruction();
+ m_pc = m_nextpc;
+ m_nextpc = ~0;
+
+ execute_instruction();
+ m_icount--;
+ }
+}
+
+void asap_device::bvs()
+{
+ if ((INT32)m_vflag < 0)
+ {
+ m_nextpc = m_ppc + ((INT32)(m_op << 10) >> 8);
+
+ fetch_instruction();
+ m_pc = m_nextpc;
+ m_nextpc = ~0;
+
+ execute_instruction();
+ m_icount--;
+ }
+}
+
+/**************************** BSR ******************************/
+
+void asap_device::bsr()
+{
+ DSTVAL = m_pc + 4;
+ m_nextpc = m_ppc + ((INT32)(m_op << 10) >> 8);
+
+ fetch_instruction();
+ m_pc = m_nextpc;
+ m_nextpc = ~0;
+
+ execute_instruction();
+ m_icount--;
+}
+
+void asap_device::bsr_0()
+{
+ m_nextpc = m_ppc + ((INT32)(m_op << 10) >> 8);
+
+ fetch_instruction();
+ m_pc = m_nextpc;
+ m_nextpc = ~0;
+
+ execute_instruction();
+ m_icount--;
+}
+
+/**************************** LEA ******************************/
+
+void asap_device::lea()
+{
+ DSTVAL = SRC1VAL + (SRC2VAL << 2);
+}
+
+void asap_device::lea_c()
+{
+ UINT32 src1 = SRC1VAL;
+ UINT32 src2 = SRC2VAL;
+ UINT32 dst = src1 + (src2 << 2);
+
+ SET_ZNCV_ADD(dst, src1, src2);
+ if (src1 & 0xc0000000)
+ SET_CFLAG(1);
+ if (((src1 ^ (src1 >> 1)) & 0x20000000) || (src1 ^ (src1 >> 2)) & 0x20000000)
+ SET_VFLAG(1);
+ DSTVAL = dst;
+}
+
+void asap_device::lea_c0()
+{
+ UINT32 src1 = SRC1VAL;
+ UINT32 src2 = SRC2VAL;
+ UINT32 dst = src1 + (src2 << 2);
+
+ SET_ZNCV_ADD(dst, src1, src2);
+ if (src1 & 0xc0000000)
+ SET_CFLAG(1);
+ if (((src1 ^ (src1 >> 1)) & 0x20000000) || (src1 ^ (src1 >> 2)) & 0x20000000)
+ SET_VFLAG(1);
+}
+
+/**************************** LEAH ******************************/
+
+void asap_device::leah()
+{
+ DSTVAL = SRC1VAL + (SRC2VAL << 1);
+}
+
+void asap_device::leah_c()
+{
+ UINT32 src1 = SRC1VAL;
+ UINT32 src2 = SRC2VAL;
+ UINT32 dst = src1 + (src2 << 1);
+
+ SET_ZNCV_ADD(dst, src1, src2);
+ if (src1 & 0x80000000)
+ SET_CFLAG(1);
+ if ((src1 ^ (src1 >> 1)) & 0x40000000)
+ SET_VFLAG(1);
+ DSTVAL = dst;
+}
+
+void asap_device::leah_c0()
+{
+ UINT32 src1 = SRC1VAL;
+ UINT32 src2 = SRC2VAL;
+ UINT32 dst = src1 + (src2 << 1);
+
+ SET_ZNCV_ADD(dst, src1, src2);
+ if (src1 & 0x80000000)
+ SET_CFLAG(1);
+ if ((src1 ^ (src1 >> 1)) & 0x40000000)
+ SET_VFLAG(1);
+}
+
+/**************************** SUBR ******************************/
+
+void asap_device::subr()
+{
+ DSTVAL = SRC2VAL - SRC1VAL;
+}
+
+void asap_device::subr_c()
+{
+ UINT32 src1 = SRC1VAL;
+ UINT32 src2 = SRC2VAL;
+ UINT32 dst = src2 - src1;
+
+ SET_ZNCV_SUB(dst, src2, src1);
+ DSTVAL = dst;
+}
+
+void asap_device::subr_c0()
+{
+ UINT32 src1 = SRC1VAL;
+ UINT32 src2 = SRC2VAL;
+ UINT32 dst = src2 - src1;
+
+ SET_ZNCV_SUB(dst, src2, src1);
+}
+
+/**************************** XOR ******************************/
+
+void asap_device::xor_()
+{
+ DSTVAL = SRC1VAL ^ SRC2VAL;
+}
+
+void asap_device::xor_c()
+{
+ UINT32 dst = SRC1VAL ^ SRC2VAL;
+ SET_ZN(dst);
+ DSTVAL = dst;
+}
+
+void asap_device::xor_c0()
+{
+ UINT32 dst = SRC1VAL ^ SRC2VAL;
+ SET_ZN(dst);
+}
+
+/**************************** XOR ******************************/
+
+void asap_device::xorn()
+{
+ DSTVAL = SRC1VAL ^ ~SRC2VAL;
+}
+
+void asap_device::xorn_c()
+{
+ UINT32 dst = SRC1VAL ^ ~SRC2VAL;
+ SET_ZN(dst);
+ DSTVAL = dst;
+}
+
+void asap_device::xorn_c0()
+{
+ UINT32 dst = SRC1VAL ^ ~SRC2VAL;
+ SET_ZN(dst);
+}
+
+/**************************** ADD ******************************/
+
+void asap_device::add()
+{
+ DSTVAL = SRC1VAL + SRC2VAL;
+}
+
+void asap_device::add_c()
+{
+ UINT32 src1 = SRC1VAL;
+ UINT32 src2 = SRC2VAL;
+ UINT32 dst = src1 + src2;
+
+ SET_ZNCV_ADD(dst, src1, src2);
+ DSTVAL = dst;
+}
+
+void asap_device::add_c0()
+{
+ UINT32 src1 = SRC1VAL;
+ UINT32 src2 = SRC2VAL;
+ UINT32 dst = src1 + src2;
+
+ SET_ZNCV_ADD(dst, src1, src2);
+}
+
+/**************************** ADD ******************************/
+
+void asap_device::sub()
+{
+ DSTVAL = SRC1VAL - SRC2VAL;
+}
+
+void asap_device::sub_c()
+{
+ UINT32 src1 = SRC1VAL;
+ UINT32 src2 = SRC2VAL;
+ UINT32 dst = src1 - src2;
+
+ SET_ZNCV_SUB(dst, src1, src2);
+ DSTVAL = dst;
+}
+
+void asap_device::sub_c0()
+{
+ UINT32 src1 = SRC1VAL;
+ UINT32 src2 = SRC2VAL;
+ UINT32 dst = src1 - src2;
+
+ SET_ZNCV_SUB(dst, src1, src2);
+}
+
+/**************************** ADDC ******************************/
+
+void asap_device::addc()
+{
+ DSTVAL = SRC1VAL + SRC2VAL + m_cflag;
+}
+
+void asap_device::addc_c()
+{
+ UINT32 src1 = SRC1VAL;
+ UINT32 src2 = SRC2VAL;
+ UINT32 dst = src1 + src2 + m_cflag;
+
+ SET_ZNCV_ADD(dst, src1, src2);
+ DSTVAL = dst;
+}
+
+void asap_device::addc_c0()
+{
+ UINT32 src1 = SRC1VAL;
+ UINT32 src2 = SRC2VAL;
+ UINT32 dst = src1 + src2 + m_cflag;
+
+ SET_ZNCV_ADD(dst, src1, src2);
+}
+
+/**************************** SUBC ******************************/
+
+void asap_device::subc()
+{
+ DSTVAL = SRC1VAL - SRC2VAL - 1 + m_cflag;
+}
+
+void asap_device::subc_c()
+{
+ UINT32 src1 = SRC1VAL;
+ UINT32 src2 = SRC2VAL;
+ UINT32 dst = src1 - src2 - 1 + m_cflag;
+
+ SET_ZNCV_SUB(dst, src1, src2);
+ DSTVAL = dst;
+}
+
+void asap_device::subc_c0()
+{
+ UINT32 src1 = SRC1VAL;
+ UINT32 src2 = SRC2VAL;
+ UINT32 dst = src1 - src2 - 1 + m_cflag;
+
+ SET_ZNCV_SUB(dst, src1, src2);
+}
+
+/**************************** AND ******************************/
+
+void asap_device::and_()
+{
+ DSTVAL = SRC1VAL & SRC2VAL;
+}
+
+void asap_device::and_c()
+{
+ UINT32 dst = SRC1VAL & SRC2VAL;
+ SET_ZN(dst);
+ DSTVAL = dst;
+}
+
+void asap_device::and_c0()
+{
+ UINT32 dst = SRC1VAL & SRC2VAL;
+ SET_ZN(dst);
+}
+
+/**************************** ANDN ******************************/
+
+void asap_device::andn()
+{
+ DSTVAL = SRC1VAL & ~SRC2VAL;
+}
+
+void asap_device::andn_c()
+{
+ UINT32 dst = SRC1VAL & ~SRC2VAL;
+ SET_ZN(dst);
+ DSTVAL = dst;
+}
+
+void asap_device::andn_c0()
+{
+ UINT32 dst = SRC1VAL & ~SRC2VAL;
+ SET_ZN(dst);
+}
+
+/**************************** OR ******************************/
+
+void asap_device::or_()
+{
+ DSTVAL = SRC1VAL | SRC2VAL;
+}
+
+void asap_device::or_c()
+{
+ UINT32 dst = SRC1VAL | SRC2VAL;
+ SET_ZN(dst);
+ DSTVAL = dst;
+}
+
+void asap_device::or_c0()
+{
+ UINT32 dst = SRC1VAL | SRC2VAL;
+ SET_ZN(dst);
+}
+
+/**************************** ORN ******************************/
+
+void asap_device::orn()
+{
+ DSTVAL = SRC1VAL | ~SRC2VAL;
+}
+
+void asap_device::orn_c()
+{
+ UINT32 dst = SRC1VAL | ~SRC2VAL;
+ SET_ZN(dst);
+ DSTVAL = dst;
+}
+
+void asap_device::orn_c0()
+{
+ UINT32 dst = SRC1VAL | ~SRC2VAL;
+ SET_ZN(dst);
+}
+
+/**************************** LD ******************************/
+
+void asap_device::ld()
+{
+ DSTVAL = readlong(SRC1VAL + (SRC2VAL << 2));
+}
+
+void asap_device::ld_0()
+{
+ readlong(SRC1VAL + (SRC2VAL << 2));
+}
+
+void asap_device::ld_c()
+{
+ UINT32 dst = readlong(SRC1VAL + (SRC2VAL << 2));
+ SET_ZN(dst);
+ DSTVAL = dst;
+}
+
+void asap_device::ld_c0()
+{
+ UINT32 dst = readlong(SRC1VAL + (SRC2VAL << 2));
+ SET_ZN(dst);
+}
+
+/**************************** LDH ******************************/
+
+void asap_device::ldh()
+{
+ DSTVAL = (INT16)readword(SRC1VAL + (SRC2VAL << 1));
+}
+
+void asap_device::ldh_0()
+{
+ readword(SRC1VAL + (SRC2VAL << 1));
+}
+
+void asap_device::ldh_c()
+{
+ UINT32 dst = (INT16)readword(SRC1VAL + (SRC2VAL << 1));
+ SET_ZN(dst);
+ DSTVAL = dst;
+}
+
+void asap_device::ldh_c0()
+{
+ UINT32 dst = (INT16)readword(SRC1VAL + (SRC2VAL << 1));
+ SET_ZN(dst);
+}
+
+/**************************** LDUH ******************************/
+
+void asap_device::lduh()
+{
+ DSTVAL = readword(SRC1VAL + (SRC2VAL << 1));
+}
+
+void asap_device::lduh_0()
+{
+ readword(SRC1VAL + (SRC2VAL << 1));
+}
+
+void asap_device::lduh_c()
+{
+ UINT32 dst = readword(SRC1VAL + (SRC2VAL << 1));
+ SET_ZN(dst);
+ DSTVAL = dst;
+}
+
+void asap_device::lduh_c0()
+{
+ UINT32 dst = readword(SRC1VAL + (SRC2VAL << 1));
+ SET_ZN(dst);
+}
+
+/**************************** STH ******************************/
+
+void asap_device::sth()
+{
+ writeword(SRC1VAL + (SRC2VAL << 1), DSTVAL);
+}
+
+void asap_device::sth_0()
+{
+ writeword(SRC1VAL + (SRC2VAL << 1), 0);
+}
+
+void asap_device::sth_c()
+{
+ UINT32 dst = (UINT16)DSTVAL;
+ SET_ZN(dst);
+ writeword(SRC1VAL + (SRC2VAL << 1), dst);
+}
+
+void asap_device::sth_c0()
+{
+ SET_ZN(0);
+ writeword(SRC1VAL + (SRC2VAL << 1), 0);
+}
+
+/**************************** ST ******************************/
+
+void asap_device::st()
+{
+ writelong(SRC1VAL + (SRC2VAL << 2), DSTVAL);
+}
+
+void asap_device::st_0()
+{
+ writelong(SRC1VAL + (SRC2VAL << 2), 0);
+}
+
+void asap_device::st_c()
+{
+ UINT32 dst = DSTVAL;
+ SET_ZN(dst);
+ writelong(SRC1VAL + (SRC2VAL << 2), dst);
+}
+
+void asap_device::st_c0()
+{
+ SET_ZN(0);
+ writelong(SRC1VAL + (SRC2VAL << 2), 0);
+}
+
+/**************************** LDB ******************************/
+
+void asap_device::ldb()
+{
+ DSTVAL = (INT8)readbyte(SRC1VAL + SRC2VAL);
+}
+
+void asap_device::ldb_0()
+{
+ readbyte(SRC1VAL + SRC2VAL);
+}
+
+void asap_device::ldb_c()
+{
+ UINT32 dst = (INT8)readbyte(SRC1VAL + SRC2VAL);
+ SET_ZN(dst);
+ DSTVAL = dst;
+}
+
+void asap_device::ldb_c0()
+{
+ UINT32 dst = (INT8)readbyte(SRC1VAL + SRC2VAL);
+ SET_ZN(dst);
+}
+
+/**************************** LDUB ******************************/
+
+void asap_device::ldub()
+{
+ DSTVAL = readbyte(SRC1VAL + SRC2VAL);
+}
+
+void asap_device::ldub_0()
+{
+ readbyte(SRC1VAL + SRC2VAL);
+}
+
+void asap_device::ldub_c()
+{
+ UINT32 dst = readbyte(SRC1VAL + SRC2VAL);
+ SET_ZN(dst);
+ DSTVAL = dst;
+}
+
+void asap_device::ldub_c0()
+{
+ UINT32 dst = readbyte(SRC1VAL + SRC2VAL);
+ SET_ZN(dst);
+}
+
+/**************************** STB ******************************/
+
+void asap_device::stb()
+{
+ writebyte(SRC1VAL + SRC2VAL, DSTVAL);
+}
+
+void asap_device::stb_0()
+{
+ writebyte(SRC1VAL + SRC2VAL, 0);
+}
+
+void asap_device::stb_c()
+{
+ UINT32 dst = (UINT8)DSTVAL;
+ SET_ZN(dst);
+ writebyte(SRC1VAL + SRC2VAL, dst);
+}
+
+void asap_device::stb_c0()
+{
+ SET_ZN(0);
+ writebyte(SRC1VAL + SRC2VAL, 0);
+}
+
+/**************************** ASHR ******************************/
+
+void asap_device::ashr()
+{
+ UINT32 src2 = SRC2VAL;
+ DSTVAL = (src2 < 32) ? ((INT32)SRC1VAL >> src2) : ((INT32)SRC1VAL >> 31);
+}
+
+void asap_device::ashr_c()
+{
+ UINT32 src2 = SRC2VAL;
+ m_cflag = 0;
+ if (src2 < 32)
+ {
+ UINT32 src1 = SRC1VAL;
+ UINT32 dst = (INT32)src1 >> src2;
+ SET_ZN(dst);
+ if (src2 != 0)
+ {
+ src1 = src1 << (32 - src2);
+ m_cflag = src1 >> 31;
+ }
+ DSTVAL = dst;
+ }
+ else
+ {
+ UINT32 dst = (INT32)SRC1VAL >> 31;
+ SET_ZN(dst);
+ DSTVAL = dst;
+ }
+}
+
+void asap_device::ashr_c0()
+{
+ UINT32 src2 = SRC2VAL;
+ m_cflag = 0;
+ if (src2 < 32)
+ {
+ UINT32 src1 = SRC1VAL;
+ UINT32 dst = (INT32)src1 >> src2;
+ SET_ZN(dst);
+ if (src2 != 0)
+ {
+ src1 = src1 << (32 - src2);
+ m_cflag = src1 >> 31;
+ }
+ }
+ else
+ {
+ UINT32 dst = (INT32)SRC1VAL >> 31;
+ SET_ZN(dst);
+ }
+}
+
+/**************************** LSHR ******************************/
+
+void asap_device::lshr()
+{
+ UINT32 src2 = SRC2VAL;
+ DSTVAL = (src2 < 32) ? (SRC1VAL >> src2) : (SRC1VAL >> 31);
+}
+
+void asap_device::lshr_c()
+{
+ UINT32 src2 = SRC2VAL;
+ m_cflag = 0;
+ if (src2 < 32)
+ {
+ UINT32 src1 = SRC1VAL;
+ UINT32 dst = src1 >> src2;
+ SET_ZN(dst);
+ if (src2 != 0)
+ {
+ src1 = src1 << (32 - src2);
+ m_cflag = src1 >> 31;
+ }
+ DSTVAL = dst;
+ }
+ else
+ {
+ UINT32 dst = SRC1VAL >> 31;
+ SET_ZN(dst);
+ DSTVAL = dst;
+ }
+}
+
+void asap_device::lshr_c0()
+{
+ UINT32 src2 = SRC2VAL;
+ m_cflag = 0;
+ if (src2 < 32)
+ {
+ UINT32 src1 = SRC1VAL;
+ UINT32 dst = src1 >> src2;
+ SET_ZN(dst);
+ if (src2 != 0)
+ {
+ src1 = src1 << (32 - src2);
+ m_cflag = src1 >> 31;
+ }
+ }
+ else
+ {
+ SET_ZN(0);
+ DSTVAL = 0;
+ }
+}
+
+/**************************** ASHL ******************************/
+
+void asap_device::ashl()
+{
+ UINT32 src2 = SRC2VAL;
+ DSTVAL = (src2 < 32) ? (SRC1VAL << src2) : 0;
+}
+
+void asap_device::ashl_c()
+{
+ UINT32 src2 = SRC2VAL;
+ m_cflag = m_vflag = 0;
+ if (src2 < 32)
+ {
+ UINT32 src1 = SRC1VAL;
+ UINT32 dst = src1 << src2;
+ SET_ZN(dst);
+ if (src2 != 0)
+ {
+ src1 = (INT32)src1 >> (32 - src2);
+ m_cflag = src1 & PS_CFLAG;
+ m_vflag = (src1 != ((INT32)dst >> 31)) << 31;
+ }
+ DSTVAL = dst;
+ }
+ else
+ {
+ SET_ZN(0);
+ DSTVAL = 0;
+ }
+}
+
+void asap_device::ashl_c0()
+{
+ UINT32 src2 = SRC2VAL;
+ m_cflag = m_vflag = 0;
+ if (src2 < 32)
+ {
+ UINT32 src1 = SRC1VAL;
+ UINT32 dst = src1 << src2;
+ SET_ZN(dst);
+ if (src2 != 0)
+ {
+ src1 = (INT32)src1 >> (32 - src2);
+ m_cflag = src1 & PS_CFLAG;
+ m_vflag = (src1 != ((INT32)dst >> 31)) << 31;
+ }
+ }
+ else
+ SET_ZN(0);
+}
+
+/**************************** ROTL ******************************/
+
+void asap_device::rotl()
+{
+ UINT32 src1 = SRC1VAL;
+ UINT32 src2 = SRC2VAL & 31;
+ DSTVAL = (src1 << src2) | (src1 >> (32 - src2));
+}
+
+void asap_device::rotl_c()
+{
+ UINT32 src1 = SRC1VAL;
+ UINT32 src2 = SRC2VAL & 31;
+ UINT32 dst = (src1 << src2) | (src1 >> (32 - src2));
+ SET_ZN(dst);
+ DSTVAL = dst;
+}
+
+void asap_device::rotl_c0()
+{
+ UINT32 src1 = SRC1VAL;
+ UINT32 src2 = SRC2VAL & 31;
+ UINT32 dst = (src1 << src2) | (src1 >> (32 - src2));
+ SET_ZN(dst);
+}
+
+/**************************** GETPS ******************************/
+
+void asap_device::getps()
+{
+ DSTVAL = GET_FLAGS();
+}
+
+/**************************** PUTPS ******************************/
+
+void asap_device::putps()
+{
+ UINT32 src2 = SRC2VAL & 0x3f;
+ SET_FLAGS(src2);
+ check_irqs();
+}
+
+/**************************** JSR ******************************/
+
+void asap_device::jsr()
+{
+ DSTVAL = m_pc + 4;
+ m_nextpc = SRC1VAL + (SRC2VAL << 2);
+
+ fetch_instruction();
+ m_pc = m_nextpc;
+ m_nextpc = ~0;
+
+ execute_instruction();
+ m_icount--;
+}
+
+void asap_device::jsr_0()
+{
+ m_nextpc = SRC1VAL + (SRC2VAL << 2);
+
+ fetch_instruction();
+ m_pc = m_nextpc;
+ m_nextpc = ~0;
+
+ execute_instruction();
+ m_icount--;
+}
+
+void asap_device::jsr_c()
+{
+ DSTVAL = m_pc + 4;
+ m_nextpc = SRC1VAL + (SRC2VAL << 2);
+ m_iflag = m_pflag;
+
+ fetch_instruction();
+ m_pc = m_nextpc;
+ m_nextpc = ~0;
+
+ execute_instruction();
+ m_icount--;
+ check_irqs();
+}
+
+void asap_device::jsr_c0()
+{
+ m_nextpc = SRC1VAL + (SRC2VAL << 2);
+ m_iflag = m_pflag;
+
+ fetch_instruction();
+ m_pc = m_nextpc;
+ m_nextpc = ~0;
+
+ execute_instruction();
+ m_icount--;
+ check_irqs();
+}
+
+/**************************** TRAP F ******************************/
+
+void asap_device::trapf()
+{
+ generate_exception(EXCEPTION_TRAPF);
+}
diff --git a/trunk/src/emu/cpu/asap/asap.h b/trunk/src/emu/cpu/asap/asap.h
new file mode 100644
index 00000000000..8728470579e
--- /dev/null
+++ b/trunk/src/emu/cpu/asap/asap.h
@@ -0,0 +1,305 @@
+/***************************************************************************
+
+ asap.h
+
+ Core implementation for the portable ASAP emulator.
+ ASAP = Atari Simplified Architecture Processor
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __ASAP_H__
+#define __ASAP_H__
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+
+// ======================> asap_device
+
+class asap_device : public cpu_device
+{
+public:
+ // construction/destruction
+ asap_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // public interfaces
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ // device_execute_interface overrides
+ virtual UINT32 execute_min_cycles() const;
+ virtual UINT32 execute_max_cycles() const;
+ virtual UINT32 execute_input_lines() const;
+ virtual void execute_run();
+ virtual void execute_set_input(int inputnum, int state);
+
+ // device_memory_interface overrides
+ virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const;
+
+ // device_state_interface overrides
+ virtual void state_import(const device_state_entry &entry);
+ virtual void state_export(const device_state_entry &entry);
+ virtual void state_string_export(const device_state_entry &entry, astring &string);
+
+ // device_disasm_interface overrides
+ virtual UINT32 disasm_min_opcode_bytes() const;
+ virtual UINT32 disasm_max_opcode_bytes() const;
+ virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);
+
+ // helpers
+ inline UINT32 readop(offs_t pc);
+ inline UINT8 readbyte(offs_t address);
+ inline UINT16 readword(offs_t address);
+ inline UINT32 readlong(offs_t address);
+ inline void writebyte(offs_t address, UINT8 data);
+ inline void writeword(offs_t address, UINT16 data);
+ inline void writelong(offs_t address, UINT32 data);
+ inline void generate_exception(int exception);
+ inline void check_irqs();
+ inline void fetch_instruction();
+ inline void fetch_instruction_debug();
+ inline void execute_instruction();
+
+ // condition handlers
+ void bsp();
+ void bmz();
+ void bgt();
+ void ble();
+ void bge();
+ void blt();
+ void bhi();
+ void bls();
+ void bcc();
+ void bcs();
+ void bpl();
+ void bmi();
+ void bne();
+ void beq();
+ void bvc();
+ void bvs();
+
+ // opcode handlers
+ void noop();
+ void trap0();
+ void bsr();
+ void bsr_0();
+ void lea();
+ void lea_c();
+ void lea_c0();
+ void leah();
+ void leah_c();
+ void leah_c0();
+ void subr();
+ void subr_c();
+ void subr_c0();
+ void xor_();
+ void xor_c();
+ void xor_c0();
+ void xorn();
+ void xorn_c();
+ void xorn_c0();
+ void add();
+ void add_c();
+ void add_c0();
+ void sub();
+ void sub_c();
+ void sub_c0();
+ void addc();
+ void addc_c();
+ void addc_c0();
+ void subc();
+ void subc_c();
+ void subc_c0();
+ void and_();
+ void and_c();
+ void and_c0();
+ void andn();
+ void andn_c();
+ void andn_c0();
+ void or_();
+ void or_c();
+ void or_c0();
+ void orn();
+ void orn_c();
+ void orn_c0();
+ void ld();
+ void ld_0();
+ void ld_c();
+ void ld_c0();
+ void ldh();
+ void ldh_0();
+ void ldh_c();
+ void ldh_c0();
+ void lduh();
+ void lduh_0();
+ void lduh_c();
+ void lduh_c0();
+ void sth();
+ void sth_0();
+ void sth_c();
+ void sth_c0();
+ void st();
+ void st_0();
+ void st_c();
+ void st_c0();
+ void ldb();
+ void ldb_0();
+ void ldb_c();
+ void ldb_c0();
+ void ldub();
+ void ldub_0();
+ void ldub_c();
+ void ldub_c0();
+ void stb();
+ void stb_0();
+ void stb_c();
+ void stb_c0();
+ void ashr();
+ void ashr_c();
+ void ashr_c0();
+ void lshr();
+ void lshr_c();
+ void lshr_c0();
+ void ashl();
+ void ashl_c();
+ void ashl_c0();
+ void rotl();
+ void rotl_c();
+ void rotl_c0();
+ void getps();
+ void putps();
+ void jsr();
+ void jsr_0();
+ void jsr_c();
+ void jsr_c0();
+ void trapf();
+
+ // internal state
+ const address_space_config m_program_config;
+ UINT32 m_pc;
+
+ // expanded flags
+ UINT32 m_pflag;
+ UINT32 m_iflag;
+ UINT32 m_cflag;
+ UINT32 m_vflag;
+ UINT32 m_znflag;
+ UINT32 m_flagsio;
+
+ // internal stuff
+ UINT32 m_op;
+ UINT32 m_ppc;
+ UINT32 m_nextpc;
+ UINT8 m_irq_state;
+ int m_icount;
+ address_space * m_program;
+ direct_read_data * m_direct;
+
+ // src2val table, registers are at the end
+ UINT32 m_src2val[65536];
+
+ // opcode/condition tables
+ typedef void (asap_device::*ophandler)();
+
+ ophandler m_opcode[32 * 32 * 2];
+
+ static const ophandler s_opcodetable[32][4];
+ static const ophandler s_conditiontable[16];
+};
+
+
+
+//**************************************************************************
+// ENUMERATIONS
+//**************************************************************************
+
+// registers
+enum
+{
+ ASAP_PC = 1,
+ ASAP_PS,
+ ASAP_R0,
+ ASAP_R1,
+ ASAP_R2,
+ ASAP_R3,
+ ASAP_R4,
+ ASAP_R5,
+ ASAP_R6,
+ ASAP_R7,
+ ASAP_R8,
+ ASAP_R9,
+ ASAP_R10,
+ ASAP_R11,
+ ASAP_R12,
+ ASAP_R13,
+ ASAP_R14,
+ ASAP_R15,
+ ASAP_R16,
+ ASAP_R17,
+ ASAP_R18,
+ ASAP_R19,
+ ASAP_R20,
+ ASAP_R21,
+ ASAP_R22,
+ ASAP_R23,
+ ASAP_R24,
+ ASAP_R25,
+ ASAP_R26,
+ ASAP_R27,
+ ASAP_R28,
+ ASAP_R29,
+ ASAP_R30,
+ ASAP_R31
+};
+
+// input lines
+enum
+{
+ ASAP_IRQ0
+};
+
+
+
+// device type definition
+extern const device_type ASAP;
+
+
+#endif /* __ASAP_H__ */
diff --git a/trunk/src/emu/cpu/asap/asapdasm.c b/trunk/src/emu/cpu/asap/asapdasm.c
new file mode 100644
index 00000000000..d88ad7b3a6f
--- /dev/null
+++ b/trunk/src/emu/cpu/asap/asapdasm.c
@@ -0,0 +1,142 @@
+/***************************************************************************
+
+ asapdasm.c
+ Disassembler for the portable ASAP emulator.
+ Written by Aaron Giles
+
+***************************************************************************/
+
+#include "emu.h"
+#include "asap.h"
+
+
+static const char *const reg[32] =
+{
+ "0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+ "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"
+};
+
+static const char *const setcond[2] =
+{
+ " ", ".c"
+};
+
+static const char *const condition[16] =
+{
+ "sp", "mz", "gt", "le", "ge", "lt", "hi", "ls", "cc", "cs", "pl", "mi", "ne", "eq", "vc", "vs"
+};
+
+
+/***************************************************************************
+ CODE CODE
+***************************************************************************/
+
+INLINE char *src2(UINT32 op, int scale)
+{
+ static char temp[20];
+ if ((op & 0xffe0) == 0xffe0)
+ sprintf(temp, "%s", reg[op & 31]);
+ else
+ sprintf(temp, "$%x", (op & 0xffff) << scale);
+ return temp;
+}
+
+CPU_DISASSEMBLE( asap )
+{
+ UINT32 op = oprom[0] | (oprom[1] << 8) | (oprom[2] << 16) | (oprom[3] << 24);
+ int opcode = op >> 27;
+ int cond = (op >> 21) & 1;
+ int rdst = (op >> 22) & 31;
+ int rsrc1 = (op >> 16) & 31;
+ int rsrc2 = op & 0xffff;
+ int rsrc2_iszero = (!rsrc2 || rsrc2 == 0xffe0);
+ UINT32 flags = 0;
+
+ switch (opcode)
+ {
+ case 0x00: sprintf(buffer, "trap $00"); flags = DASMFLAG_STEP_OVER; break;
+ case 0x01: sprintf(buffer, "b%s $%08x", condition[rdst & 15], pc + ((INT32)(op << 10) >> 8)); break;
+ case 0x02: if ((op & 0x003fffff) == 3)
+ {
+ UINT32 nextop = oprom[4] | (oprom[5] << 8) | (oprom[6] << 16) | (oprom[7] << 24);
+ if ((nextop >> 27) == 0x10 && ((nextop >> 22) & 31) == rdst && (nextop & 0xffff) == 0)
+ {
+ UINT32 nextnextop = oprom[8] | (oprom[9] << 8) | (oprom[10] << 16) | (oprom[11] << 24);
+ sprintf(buffer, "llit%s $%08x,%s", setcond[cond], nextnextop, reg[rdst]);
+ return 12 | DASMFLAG_STEP_OVER | DASMFLAG_SUPPORTED;
+ }
+ }
+ if (rdst)
+ {
+ flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1);
+ sprintf(buffer, "bsr %s,$%08x", reg[rdst], pc + ((INT32)(op << 10) >> 8));
+ }
+ else
+ sprintf(buffer, "bra $%08x", pc + ((INT32)(op << 10) >> 8));
+ break;
+ case 0x03: sprintf(buffer, "lea%s %s[%s],%s", setcond[cond], reg[rsrc1], src2(op,2), reg[rdst]); break;
+ case 0x04: sprintf(buffer, "leah%s %s[%s],%s", setcond[cond], reg[rsrc1], src2(op,1), reg[rdst]); break;
+ case 0x05: sprintf(buffer, "subr%s %s,%s,%s", setcond[cond], reg[rsrc1], src2(op,0), reg[rdst]); break;
+ case 0x06: sprintf(buffer, "xor%s %s,%s,%s", setcond[cond], reg[rsrc1], src2(op,0), reg[rdst]); break;
+ case 0x07: sprintf(buffer, "xorn%s %s,%s,%s", setcond[cond], reg[rsrc1], src2(op,0), reg[rdst]); break;
+ case 0x08: if (!rsrc1 && !rdst && rsrc2_iszero)
+ sprintf(buffer, "nop");
+ else if (!rsrc1)
+ sprintf(buffer, "mov%s %s,%s", setcond[cond], src2(op,0), reg[rdst]);
+ else if (rsrc2_iszero)
+ sprintf(buffer, "mov%s %s,%s", setcond[cond], reg[rsrc1], reg[rdst]);
+ else
+ sprintf(buffer, "add%s %s,%s,%s", setcond[cond], reg[rsrc1], src2(op,0), reg[rdst]); break;
+ case 0x09: sprintf(buffer, "sub%s %s,%s,%s", setcond[cond], reg[rsrc1], src2(op,0), reg[rdst]); break;
+ case 0x0a: sprintf(buffer, "addc%s %s,%s,%s", setcond[cond], reg[rsrc1], src2(op,0), reg[rdst]); break;
+ case 0x0b: sprintf(buffer, "subc%s %s,%s,%s", setcond[cond], reg[rsrc1], src2(op,0), reg[rdst]); break;
+ case 0x0c: sprintf(buffer, "and%s %s,%s,%s", setcond[cond], reg[rsrc1], src2(op,0), reg[rdst]); break;
+ case 0x0d: sprintf(buffer, "andn%s %s,%s,%s", setcond[cond], reg[rsrc1], src2(op,0), reg[rdst]); break;
+ case 0x0e: if (!rsrc1 && !rdst && rsrc2_iszero)
+ sprintf(buffer, "nop");
+ else if (!rsrc1)
+ sprintf(buffer, "mov%s %s,%s", setcond[cond], src2(op,0), reg[rdst]);
+ else if (rsrc2_iszero)
+ sprintf(buffer, "mov%s %s,%s", setcond[cond], reg[rsrc1], reg[rdst]);
+ else
+ sprintf(buffer, "or%s %s,%s,%s", setcond[cond], reg[rsrc1], src2(op,0), reg[rdst]); break;
+ case 0x0f: sprintf(buffer, "orn%s %s,%s,%s", setcond[cond], reg[rsrc1], src2(op,0), reg[rdst]); break;
+ case 0x10: sprintf(buffer, "ld%s %s[%s],%s", setcond[cond], reg[rsrc1], src2(op,2), reg[rdst]); break;
+ case 0x11: sprintf(buffer, "ldh%s %s[%s],%s", setcond[cond], reg[rsrc1], src2(op,1), reg[rdst]); break;
+ case 0x12: sprintf(buffer, "lduh%s %s[%s],%s", setcond[cond], reg[rsrc1], src2(op,1), reg[rdst]); break;
+ case 0x13: sprintf(buffer, "sth%s %s[%s],%s", setcond[cond], reg[rsrc1], src2(op,1), reg[rdst]); break;
+ case 0x14: sprintf(buffer, "st%s %s[%s],%s", setcond[cond], reg[rsrc1], src2(op,2), reg[rdst]); break;
+ case 0x15: sprintf(buffer, "ldb%s %s[%s],%s", setcond[cond], reg[rsrc1], src2(op,0), reg[rdst]); break;
+ case 0x16: sprintf(buffer, "ldub%s %s[%s],%s", setcond[cond], reg[rsrc1], src2(op,0), reg[rdst]); break;
+ case 0x17: sprintf(buffer, "stb%s %s[%s],%s", setcond[cond], reg[rsrc1], src2(op,0), reg[rdst]); break;
+ case 0x18: sprintf(buffer, "ashr%s %s,%s,%s", setcond[cond], reg[rsrc1], src2(op,0), reg[rdst]); break;
+ case 0x19: sprintf(buffer, "lshr%s %s,%s,%s", setcond[cond], reg[rsrc1], src2(op,0), reg[rdst]); break;
+ case 0x1a: sprintf(buffer, "ashl%s %s,%s,%s", setcond[cond], reg[rsrc1], src2(op,0), reg[rdst]); break;
+ case 0x1b: sprintf(buffer, "rotl%s %s,%s,%s", setcond[cond], reg[rsrc1], src2(op,0), reg[rdst]); break;
+ case 0x1c: sprintf(buffer, "getps %s", reg[rdst]); break;
+ case 0x1d: sprintf(buffer, "putps %s", src2(op,0)); break;
+ case 0x1e: if (rdst && rsrc2_iszero)
+ {
+ flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1);
+ sprintf(buffer, "jsr%s %s,%s", setcond[cond], reg[rdst], reg[rsrc1]);
+ }
+ else if (rdst)
+ {
+ flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1);
+ sprintf(buffer, "jsr%s %s,%s[%s]", setcond[cond], reg[rdst], reg[rsrc1], src2(op,2));
+ }
+ else if (rsrc2_iszero)
+ {
+ if (rsrc1 == 28)
+ flags = DASMFLAG_STEP_OUT;
+ sprintf(buffer, "jmp%s %s", setcond[cond], reg[rsrc1]);
+ }
+ else
+ sprintf(buffer, "jmp%s %s[%s]", setcond[cond], reg[rsrc1], src2(op,2));
+ break;
+ case 0x1f: sprintf(buffer, "trap $1f"); flags = DASMFLAG_STEP_OVER; break;
+ }
+ return 4 | flags | DASMFLAG_SUPPORTED;
+}
diff --git a/trunk/src/emu/cpu/avr8/avr8.c b/trunk/src/emu/cpu/avr8/avr8.c
new file mode 100644
index 00000000000..045a46c9d00
--- /dev/null
+++ b/trunk/src/emu/cpu/avr8/avr8.c
@@ -0,0 +1,1205 @@
+/*
+ Atmel 8-bit AVR emulator
+
+ (Skeleton)
+
+ DONE:
+ - Disassembler
+ - [lft]'s "Craft" depends on on-chip device support now instead of opcodes (it requires unusually few in order to boot)
+
+ TODO:
+ - Everything else
+ * Finish opcode implementation
+ * Add proper cycle timing
+ * Add Interrupts
+ * Add on-chip hardware (machine driver)
+
+ Written by MooglyGuy
+*/
+
+#include "emu.h"
+#include "debugger.h"
+#include "avr8.h"
+
+typedef struct _avr8_state avr8_state;
+struct _avr8_state
+{
+ UINT32 pc;
+
+ legacy_cpu_device *device;
+ address_space *program;
+ address_space *io;
+ int icount;
+ UINT32 addr_mask;
+};
+
+enum
+{
+ AVR8_SREG_C = 0,
+ AVR8_SREG_Z,
+ AVR8_SREG_N,
+ AVR8_SREG_V,
+ AVR8_SREG_S,
+ AVR8_SREG_H,
+ AVR8_SREG_T,
+ AVR8_SREG_I,
+};
+
+enum
+{
+ AVR8_IO_SPL = 0x5d,
+ AVR8_IO_SPH = 0x5e,
+ AVR8_IO_SREG = 0x5f,
+};
+
+#define SREG_R(b) ((READ_IO_8(cpustate, AVR8_IO_SREG) & (1 << (b))) >> (b))
+#define SREG_W(b,v) WRITE_IO_8(cpustate, AVR8_IO_SREG, (READ_IO_8(cpustate, AVR8_IO_SREG) &~ (1 << (b))) | (((v) ? 1 : 0) << (b)))
+#define NOT(x) (1 - (x))
+
+#define RD2(op) (((op) >> 4) & 0x0003)
+#define RD3(op) (((op) >> 4) & 0x0007)
+#define RD4(op) (((op) >> 4) & 0x000f)
+#define RD5(op) (((op) >> 4) & 0x001f)
+#define RR3(op) ((op) & 0x0007)
+#define RR4(op) ((op) & 0x000f)
+#define RR5(op) ((((op) >> 5) & 0x0010) | ((op) & 0x000f))
+#define KCONST6(op) ((((op) >> 2) & 0x0030) | ((op) & 0x000f))
+#define KCONST7(op) (((op) >> 3) & 0x007f)
+#define KCONST8(op) ((((op) >> 4) & 0x00f0) | ((op) & 0x000f))
+#define KCONST22(op) (((((UINT32)(op) >> 3) & 0x003e) | ((UINT32)(op) & 0x0001)) << 16)
+#define QCONST6(op) ((((op) >> 8) & 0x0020) | (((op) >> 7) & 0x0018) | ((op) & 0x0007))
+#define ACONST5(op) (((op) >> 3) & 0x001f)
+#define ACONST6(op) ((((op) >> 5) & 0x0030) | ((op) & 0x000f))
+
+#define XREG ((READ_IO_8(cpustate, 27) << 8) | READ_IO_8(cpustate, 26))
+#define YREG ((READ_IO_8(cpustate, 29) << 8) | READ_IO_8(cpustate, 28))
+#define ZREG ((READ_IO_8(cpustate, 31) << 8) | READ_IO_8(cpustate, 30))
+#define SPREG ((READ_IO_8(cpustate, AVR8_IO_SPH) << 8) | READ_IO_8(cpustate, AVR8_IO_SPL))
+
+INLINE avr8_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == ATMEGA88 || device->type() == ATMEGA644);
+ return (avr8_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+/*****************************************************************************/
+
+static void unimplemented_opcode(avr8_state *cpustate, UINT32 op)
+{
+ fatalerror("AVR8: unknown opcode (%08x) at %08x\n", op, cpustate->pc);
+}
+
+/*****************************************************************************/
+
+INLINE bool avr8_is_long_opcode(UINT16 op)
+{
+ if((op & 0xf000) == 0x9000)
+ {
+ if((op & 0x0f00) < 0x0400)
+ {
+ if((op & 0x000f) == 0x0000)
+ {
+ return true;
+ }
+ }
+ else if((op & 0x0f00) < 0x0600)
+ {
+ if((op & 0x000f) >= 0x000c)
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+INLINE UINT8 READ_PRG_8(avr8_state *cpustate, UINT32 address)
+{
+ return cpustate->program->read_byte(address);
+}
+
+INLINE UINT16 READ_PRG_16(avr8_state *cpustate, UINT32 address)
+{
+ return cpustate->program->read_word(address << 1);
+}
+
+INLINE void WRITE_PRG_8(avr8_state *cpustate, UINT32 address, UINT8 data)
+{
+ cpustate->program->write_byte(address, data);
+}
+
+INLINE void WRITE_PRG_16(avr8_state *cpustate, UINT32 address, UINT16 data)
+{
+ cpustate->program->write_word(address, data);
+}
+
+INLINE UINT8 READ_IO_8(avr8_state *cpustate, UINT16 address)
+{
+ return cpustate->io->read_byte(address);
+}
+
+INLINE void WRITE_IO_8(avr8_state *cpustate, UINT16 address, UINT8 data)
+{
+ cpustate->io->write_byte(address, data);
+}
+
+INLINE void PUSH(avr8_state *cpustate, UINT8 val)
+{
+ UINT16 sp = SPREG;
+ WRITE_IO_8(cpustate, sp, val);
+ sp--;
+ //printf( "PUSH %02x, new SP = %04x\n", val, sp );
+ WRITE_IO_8(cpustate, AVR8_IO_SPH, (sp >> 8) & 0x00ff);
+ WRITE_IO_8(cpustate, AVR8_IO_SPL, sp & 0x00ff);
+}
+
+INLINE UINT8 POP(avr8_state *cpustate)
+{
+ UINT16 sp = SPREG;
+ sp++;
+ WRITE_IO_8(cpustate, AVR8_IO_SPH, (sp >> 8) & 0x00ff);
+ WRITE_IO_8(cpustate, AVR8_IO_SPL, sp & 0x00ff);
+ //printf( "POP %02x, new SP = %04x\n", READ_IO_8(cpustate, sp), sp );
+ return READ_IO_8(cpustate, sp);
+}
+
+static void avr8_set_irq_line(avr8_state *cpustate, UINT16 vector, int state)
+{
+ //printf( "OMFG SETTING IRQ LINE\n" );
+ // Horrible hack, not accurate
+ if(state)
+ {
+ if(SREG_R(AVR8_SREG_I))
+ {
+ SREG_W(AVR8_SREG_I, 0);
+ PUSH(cpustate, (cpustate->pc >> 8) & 0x00ff);
+ PUSH(cpustate, cpustate->pc & 0x00ff);
+ cpustate->pc = vector;
+ }
+ }
+}
+
+/*****************************************************************************/
+
+static CPU_INIT( avr8 )
+{
+ avr8_state *cpustate = get_safe_token(device);
+
+ cpustate->pc = 0;
+
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->io = device->space(AS_IO);
+
+ WRITE_IO_8(cpustate, AVR8_IO_SREG, 0);
+
+ device->save_item(NAME(cpustate->pc));
+}
+
+static CPU_EXIT( avr8 )
+{
+}
+
+static CPU_RESET( avr8 )
+{
+ avr8_state *cpustate = get_safe_token(device);
+
+ WRITE_IO_8(cpustate, AVR8_IO_SREG, 0);
+ cpustate->pc = 0;
+}
+
+static CPU_EXECUTE( avr8 )
+{
+ UINT32 op = 0;
+ INT32 offs = 0;
+ UINT8 rd = 0;
+ UINT8 rr = 0;
+ UINT8 res = 0;
+ UINT16 pd = 0;
+ INT16 sd = 0;
+ INT32 opcycles = 1;
+ //UINT16 pr = 0;
+ avr8_state *cpustate = get_safe_token(device);
+
+ while (cpustate->icount > 0)
+ {
+ cpustate->pc &= cpustate->addr_mask;
+
+ debugger_instruction_hook(device, cpustate->pc << 1);
+
+ op = (UINT32)READ_PRG_16(cpustate, cpustate->pc);
+
+ switch(op & 0xf000)
+ {
+ case 0x0000:
+ switch(op & 0x0f00)
+ {
+ case 0x0000: // NOP
+ break;
+ case 0x0100: // MOVW Rd+1:Rd,Rr+1:Rd
+ WRITE_IO_8(cpustate, (RD4(op) << 1)+1, READ_IO_8(cpustate, (RR4(op) << 1)+1));
+ WRITE_IO_8(cpustate, RD4(op) << 1, READ_IO_8(cpustate, RR4(op) << 1));
+ break;
+ case 0x0200: // MULS Rd,Rr
+ //output += sprintf( output, "MULS R%d, R%d", 16+RD4(op), 16+RR4(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0300: // MULSU Rd,Rr
+ sd = (INT8)READ_IO_8(cpustate, 16+RD4(op)) * (UINT8)READ_IO_8(cpustate, 16+RR4(op));
+ WRITE_IO_8(cpustate, 1, (sd >> 8) & 0x00ff);
+ WRITE_IO_8(cpustate, 0, sd & 0x00ff);
+ SREG_W(AVR8_SREG_C, (sd & 0x8000) ? 1 : 0);
+ SREG_W(AVR8_SREG_Z, (sd == 0) ? 1 : 0);
+ opcycles = 2;
+ break;
+ case 0x0400:
+ case 0x0500:
+ case 0x0600:
+ case 0x0700: // CPC Rd,Rr
+ rd = READ_IO_8(cpustate, RD5(op));
+ rr = READ_IO_8(cpustate, RR5(op));
+ res = rd - (rr + SREG_R(AVR8_SREG_C));
+ SREG_W(AVR8_SREG_H, (NOT(BIT(rd,3)) & BIT(rr,3)) | (BIT(rr,3) & BIT(res,3)) | (BIT(res,3) & NOT(BIT(rd,3))));
+ SREG_W(AVR8_SREG_V, (BIT(rd,7) & NOT(BIT(rr,7)) & NOT(BIT(res,7))) | (NOT(BIT(rd,7)) & BIT(rr,7) & BIT(res,7)));
+ SREG_W(AVR8_SREG_N, BIT(res,7));
+ SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V));
+ SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0);
+ SREG_W(AVR8_SREG_C, (NOT(BIT(rd,7)) & BIT(rr,7)) | (BIT(rr,7) & BIT(res,7)) | (BIT(res,7) & NOT(BIT(rd,7))));
+ break;
+ case 0x0800:
+ case 0x0900:
+ case 0x0a00:
+ case 0x0b00: // SBC Rd,Rr
+ rd = READ_IO_8(cpustate, RD5(op));
+ rr = READ_IO_8(cpustate, RR5(op));
+ res = rd - (rr + SREG_R(AVR8_SREG_C));
+ WRITE_IO_8(cpustate, RD5(op), res);
+ SREG_W(AVR8_SREG_H, (NOT(BIT(rd,3)) & BIT(rr,3)) | (BIT(rr,3) & BIT(res,3)) | (BIT(res,3) & NOT(BIT(rd,3))));
+ SREG_W(AVR8_SREG_V, (BIT(rd,7) & NOT(BIT(rr,7)) & NOT(BIT(res,7))) | (NOT(BIT(rd,7)) & BIT(rr,7) & BIT(res,7)));
+ SREG_W(AVR8_SREG_N, BIT(res,7));
+ SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V));
+ SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0);
+ SREG_W(AVR8_SREG_C, (NOT(BIT(rd,7)) & BIT(rr,7)) | (BIT(rr,7) & BIT(res,7)) | (BIT(res,7) & NOT(BIT(rd,7))));
+ break;
+ case 0x0c00:
+ case 0x0d00:
+ case 0x0e00:
+ case 0x0f00: // ADD Rd,Rr
+ rd = READ_IO_8(cpustate, RD5(op));
+ rr = READ_IO_8(cpustate, RR5(op));
+ res = rd + rr;
+ WRITE_IO_8(cpustate, RD5(op), res);
+ SREG_W(AVR8_SREG_H, (BIT(rd,3) & BIT(rr,3)) | (BIT(rr,3) & NOT(BIT(res,3))) | (NOT(BIT(res,3)) & BIT(rd,3)));
+ SREG_W(AVR8_SREG_V, (BIT(rd,7) & BIT(rr,7) & NOT(BIT(res,7))) | (NOT(BIT(rd,7)) & NOT(BIT(rr,7)) & BIT(res,7)));
+ SREG_W(AVR8_SREG_N, BIT(res,7));
+ SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V));
+ SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0);
+ SREG_W(AVR8_SREG_C, (BIT(rd,7) & BIT(rr,7)) | (BIT(rr,7) & NOT(BIT(res,7))) | (NOT(BIT(res,7)) & BIT(rd,7)));
+ break;
+ }
+ break;
+ case 0x1000:
+ switch(op & 0x0c00)
+ {
+ case 0x0000: // CPSR Rd,Rr
+ //output += sprintf( output, "CPSE R%d, R%d", RD5(op), RR5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0400: // CP Rd,Rr
+ rd = READ_IO_8(cpustate, RD5(op));
+ rr = READ_IO_8(cpustate, RR5(op));
+ res = rd - rr;
+ SREG_W(AVR8_SREG_H, (NOT(BIT(rd,3)) & BIT(rr,3)) | (BIT(rr,3) & BIT(res,3)) | (BIT(res,3) & NOT(BIT(rd,3))));
+ SREG_W(AVR8_SREG_V, (BIT(rd,7) & NOT(BIT(rr,7)) & NOT(BIT(res,7))) | (NOT(BIT(rd,7)) & BIT(rr,7) & BIT(res,7)));
+ SREG_W(AVR8_SREG_N, BIT(res,7));
+ SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V));
+ SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0);
+ SREG_W(AVR8_SREG_C, (NOT(BIT(rd,7)) & BIT(rr,7)) | (BIT(rr,7) & BIT(res,7)) | (BIT(res,7) & NOT(BIT(rd,7))));
+ break;
+ case 0x0800: // SUB Rd,Rr
+ rd = READ_IO_8(cpustate, RD5(op));
+ rr = READ_IO_8(cpustate, RR5(op));
+ res = rd - rr;
+ WRITE_IO_8(cpustate, RD5(op), res);
+ SREG_W(AVR8_SREG_H, (NOT(BIT(rd,3)) & BIT(rr,3)) | (BIT(rr,3) & BIT(res,3)) | (BIT(res,3) & NOT(BIT(rd,3))));
+ SREG_W(AVR8_SREG_V, (BIT(rd,7) & NOT(BIT(rr,7)) & NOT(BIT(res,7))) | (NOT(BIT(rd,7)) & BIT(rr,7) & BIT(res,7)));
+ SREG_W(AVR8_SREG_N, BIT(res,7));
+ SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V));
+ SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0);
+ SREG_W(AVR8_SREG_C, (NOT(BIT(rd,7)) & BIT(rr,7)) | (BIT(rr,7) & BIT(res,7)) | (BIT(res,7) & NOT(BIT(rd,7))));
+ break;
+ case 0x0c00: // ADC Rd,Rr
+ rd = READ_IO_8(cpustate, RD5(op));
+ rr = READ_IO_8(cpustate, RR5(op));
+ res = rd + rr + SREG_R(AVR8_SREG_C);
+ WRITE_IO_8(cpustate, RD5(op), res);
+ SREG_W(AVR8_SREG_H, (BIT(rd,3) & BIT(rr,3)) | (BIT(rr,3) & NOT(BIT(res,3))) | (NOT(BIT(res,3)) & BIT(rd,3)));
+ SREG_W(AVR8_SREG_V, (BIT(rd,7) & BIT(rr,7) & NOT(BIT(res,7))) | (NOT(BIT(rd,7)) & NOT(BIT(rr,7)) & BIT(res,7)));
+ SREG_W(AVR8_SREG_N, BIT(res,7));
+ SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V));
+ SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0);
+ SREG_W(AVR8_SREG_C, (BIT(rd,7) & BIT(rr,7)) | (BIT(rr,7) & NOT(BIT(res,7))) | (NOT(BIT(res,7)) & BIT(rd,7)));
+ break;
+ }
+ break;
+ case 0x2000:
+ switch(op & 0x0c00)
+ {
+ case 0x0000: // AND Rd,Rr
+ //output += sprintf( output, "AND R%d, R%d", RD5(op), RR5(op) );
+ rd = READ_IO_8(cpustate, RD5(op));
+ rr = READ_IO_8(cpustate, RR5(op));
+ rd &= rr;
+ SREG_W(AVR8_SREG_V, 0);
+ SREG_W(AVR8_SREG_N, rd & 0x80);
+ SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V));
+ SREG_W(AVR8_SREG_Z, (rd == 0) ? 1 : 0);
+ WRITE_IO_8(cpustate, RD5(op), rd);
+ break;
+ case 0x0400: // EOR Rd,Rr
+ rd = READ_IO_8(cpustate, RD5(op));
+ rr = READ_IO_8(cpustate, RR5(op));
+ rd ^= rr;
+ SREG_W(AVR8_SREG_V, 0);
+ SREG_W(AVR8_SREG_N, rd & 0x80);
+ SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V));
+ SREG_W(AVR8_SREG_Z, (rd == 0) ? 1 : 0);
+ WRITE_IO_8(cpustate, RD5(op), rd);
+ break;
+ case 0x0800: // OR Rd,Rr
+ //output += sprintf( output, "OR R%d, R%d", RD5(op), RR5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0c00: // MOV Rd,Rr
+ WRITE_IO_8(cpustate, RD5(op), READ_IO_8(cpustate, RR5(op)));
+ break;
+ }
+ break;
+ case 0x3000: // CPI Rd,K
+ rd = READ_IO_8(cpustate, 16+RD4(op));
+ rr = KCONST8(op);
+ res = rd - rr;
+ SREG_W(AVR8_SREG_H, (NOT(BIT(rd,3)) & BIT(rr,3)) | (BIT(rr,3) & BIT(res,3)) | (BIT(res,3) & NOT(BIT(rd,3))));
+ SREG_W(AVR8_SREG_V, (BIT(rd,7) & NOT(BIT(rr,7)) & NOT(BIT(res,7))) | (NOT(BIT(rd,7)) & BIT(rr,7) & BIT(res,7)));
+ SREG_W(AVR8_SREG_N, BIT(res,7));
+ SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V));
+ SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0);
+ SREG_W(AVR8_SREG_C, (NOT(BIT(rd,7)) & BIT(rr,7)) | (BIT(rr,7) & BIT(res,7)) | (BIT(res,7) & NOT(BIT(rd,7))));
+ break;
+ case 0x4000: // SBCI Rd,K
+ //output += sprintf( output, "SBCI R%d, 0x%02x", 16+RD4(op), KCONST8(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x5000: // SUBI Rd,K
+ rd = READ_IO_8(cpustate, 16+RD4(op));
+ rr = KCONST8(op);
+ res = rd - rr;
+ WRITE_IO_8(cpustate, 16+RD4(op), res);
+ SREG_W(AVR8_SREG_H, (NOT(BIT(rd,3)) & BIT(rr,3)) | (BIT(rr,3) & BIT(res,3)) | (BIT(res,3) & NOT(BIT(rd,3))));
+ SREG_W(AVR8_SREG_V, (BIT(rd,7) & NOT(BIT(rr,7)) & NOT(BIT(res,7))) | (NOT(BIT(rd,7)) & BIT(rr,7) & BIT(res,7)));
+ SREG_W(AVR8_SREG_N, BIT(res,7));
+ SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V));
+ SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0);
+ SREG_W(AVR8_SREG_C, (NOT(BIT(rd,7)) & BIT(rr,7)) | (BIT(rr,7) & BIT(res,7)) | (BIT(res,7) & NOT(BIT(rd,7))));
+ break;
+ case 0x6000: // ORI Rd,K
+ //output += sprintf( output, "ORI R%d, 0x%02x", 16+RD4(op), KCONST8(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x7000: // ANDI Rd,K
+ //output += sprintf( output, "ANDI R%d, 0x%02x", 16+RD4(op), KCONST8(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x8000:
+ case 0xa000:
+ switch(op & 0x0208)
+ {
+ case 0x0000: // LDD Rd,Z+q
+ //output += sprintf( output, "LD(D) R%d, Z+%02x", RD5(op), QCONST6(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0008: // LDD Rd,Y+q
+ WRITE_IO_8(cpustate, RD5(op), YREG + QCONST6(op));
+ opcycles = 2;
+ break;
+ case 0x0200: // STD Z+q,Rr
+ //output += sprintf( output, "ST(D) Z+%02x, R%d", QCONST6(op), RD5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0208: // STD Y+q,Rr
+ WRITE_IO_8(cpustate, YREG + QCONST6(op), READ_IO_8(cpustate, RD5(op)));
+ opcycles = 2;
+ break;
+ }
+ break;
+ case 0x9000:
+ switch(op & 0x0f00)
+ {
+ case 0x0000:
+ case 0x0100:
+ switch(op & 0x000f)
+ {
+ case 0x0000: // LDS Rd,k
+ op <<= 16;
+ cpustate->pc++;
+ op |= READ_PRG_16(cpustate, cpustate->pc);
+ WRITE_IO_8(cpustate, RD5(op >> 16), READ_IO_8(cpustate, op & 0x0000ffff));
+ opcycles = 2;
+ break;
+ case 0x0001: // LD Rd,Z+
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0002: // LD Rd,-Z
+ //output += sprintf( output, "LD R%d,-Z", RD5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0004: // LPM Rd,Z
+ WRITE_IO_8(cpustate, RD5(op), READ_PRG_8(cpustate, ZREG));
+ opcycles = 3;
+ break;
+ case 0x0005: // LPM Rd,Z+
+ pd = ZREG;
+ WRITE_IO_8(cpustate, RD5(op), READ_PRG_8(cpustate, pd));
+ pd++;
+ WRITE_IO_8(cpustate, 31, (pd >> 8) & 0x00ff);
+ WRITE_IO_8(cpustate, 30, pd & 0x00ff);
+ opcycles = 3;
+ break;
+ case 0x0006: // ELPM Rd,Z
+ //output += sprintf( output, "ELPM R%d, Z", RD5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0007: // ELPM Rd,Z+
+ //output += sprintf( output, "ELPM R%d, Z+", RD5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0009: // LD Rd,Y+
+ //output += sprintf( output, "LD R%d, Y+", RD5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x000a: // LD Rd,-Y
+ //output += sprintf( output, "LD R%d,-Y", RD5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x000c: // LD Rd,X
+ //output += sprintf( output, "LD R%d, X", RD5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x000d: // LD Rd,X+
+ pd = XREG;
+ WRITE_IO_8(cpustate, RD5(op), READ_IO_8(cpustate, pd));
+ pd++;
+ WRITE_IO_8(cpustate, 27, (pd >> 8) & 0x00ff);
+ WRITE_IO_8(cpustate, 26, pd & 0x00ff);
+ opcycles = 2;
+ break;
+ case 0x000e: // LD Rd,-X
+ //output += sprintf( output, "LD R%d,-X", RD5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x000f: // POP Rd
+ WRITE_IO_8(cpustate, RD5(op), POP(cpustate));
+ opcycles = 2;
+ break;
+ default:
+ unimplemented_opcode(cpustate, op);
+ //output += sprintf( output, "Undefined (%04x)", op );
+ break;
+ }
+ break;
+ case 0x0200:
+ case 0x0300:
+ switch(op & 0x000f)
+ {
+ case 0x0000: // STS k,Rr
+ op <<= 16;
+ cpustate->pc++;
+ op |= READ_PRG_16(cpustate, cpustate->pc);
+ WRITE_IO_8(cpustate, op & 0x0000ffff, READ_IO_8(cpustate, RD5(op >> 16)));
+ opcycles = 2;
+ break;
+ case 0x0001: // ST Z+,Rd
+ //output += sprintf( output, "ST Z+, R%d", RD5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0002: // ST -Z,Rd
+ //output += sprintf( output, "ST -Z , R%d", RD5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0009: // ST Y+,Rd
+ //output += sprintf( output, "ST Y+, R%d", RD5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x000a: // ST -Z,Rd
+ //output += sprintf( output, "ST -Y , R%d", RD5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x000c: // ST X,Rd
+ rd = READ_IO_8(cpustate, RD5(op));
+ WRITE_IO_8(cpustate, XREG, rd);
+ opcycles = 2;
+ break;
+ case 0x000d: // ST X+,Rd
+ pd = XREG;
+ WRITE_IO_8(cpustate, pd, READ_IO_8(cpustate, RD5(op)));
+ pd++;
+ WRITE_IO_8(cpustate, 27, (pd >> 8) & 0x00ff);
+ WRITE_IO_8(cpustate, 26, pd & 0x00ff);
+ opcycles = 2;
+ break;
+ case 0x000e: // ST -X,Rd
+ //output += sprintf( output, "ST -X , R%d", RD5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x000f: // PUSH Rd
+ PUSH(cpustate, READ_IO_8(cpustate, RD5(op)));
+ opcycles = 2;
+ break;
+ default:
+ unimplemented_opcode(cpustate, op);
+ //output += sprintf( output, "Undefined (%04x)", op );
+ break;
+ }
+ break;
+ case 0x0400:
+ switch(op & 0x000f)
+ {
+ case 0x0000: // COM Rd
+ rd = READ_IO_8(cpustate, RD5(op));
+ rd = ~rd;
+ SREG_W(AVR8_SREG_C, 1);
+ SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0);
+ SREG_W(AVR8_SREG_N, BIT(res,7));
+ SREG_W(AVR8_SREG_V, 0);
+ SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) | SREG_R(AVR8_SREG_V));
+ break;
+ case 0x0001: // NEG Rd
+ rd = READ_IO_8(cpustate, RD5(op));
+ res = 0 - rd;
+ SREG_W(AVR8_SREG_C, (res == 0) ? 0 : 1);
+ SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0);
+ SREG_W(AVR8_SREG_N, BIT(res,7));
+ SREG_W(AVR8_SREG_V, (res == 0x80) ? 1 : 0);
+ SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) | SREG_R(AVR8_SREG_V));
+ SREG_W(AVR8_SREG_H, BIT(res,3) | BIT(rd,3));
+ break;
+ case 0x0002: // SWAP Rd
+ //output += sprintf( output, "SWAP R%d", RD5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0003: // INC Rd
+ rd = READ_IO_8(cpustate, RD5(op));
+ res = rd + 1;
+ SREG_W(AVR8_SREG_V, (rd == 0x7f) ? 1 : 0);
+ SREG_W(AVR8_SREG_N, BIT(res,7));
+ SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V));
+ SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0);
+ WRITE_IO_8(cpustate, RD5(op), res);
+ break;
+ case 0x0005: // ASR Rd
+ //output += sprintf( output, "ASR R%d", RD5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0006: // LSR Rd
+ rd = READ_IO_8(cpustate, RD5(op));
+ res = rd >> 1;
+ SREG_W(AVR8_SREG_C, rd & 0x01);
+ SREG_W(AVR8_SREG_Z, (res == 0) ? 1 :0);
+ SREG_W(AVR8_SREG_N, 0);
+ SREG_W(AVR8_SREG_V, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_C));
+ SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V));
+ break;
+ case 0x0007: // ROR Rd
+ //output += sprintf( output, "ROR R%d", RD5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0008:
+ switch(op & 0x00f0)
+ {
+ case 0x0000: // SEC
+ case 0x0010: // SEZ
+ case 0x0020: // SEN
+ case 0x0030: // SEV
+ case 0x0040: // SES
+ case 0x0050: // SEH
+ case 0x0060: // SET
+ case 0x0070: // SEI
+ SREG_W((op >> 4) & 0x07, 1);
+ break;
+ case 0x0080: // CLC
+ case 0x0090: // CLZ
+ case 0x00a0: // CLN
+ case 0x00b0: // CLV
+ case 0x00c0: // CLS
+ case 0x00d0: // CLH
+ case 0x00e0: // CLT
+ case 0x00f0: // CLI
+ SREG_W((op >> 4) & 0x07, 0);
+ break;
+ }
+ break;
+ case 0x0009:
+ switch(op & 0x00f0)
+ {
+ case 0x0000: // IJMP
+ cpustate->pc = ZREG - 1;
+ opcycles = 2;
+ break;
+ case 0x0010: // EIJMP
+ //output += sprintf( output, "EIJMP" );
+ unimplemented_opcode(cpustate, op);
+ break;
+ default:
+ //output += sprintf( output, "Undefined (%04x)", op );
+ unimplemented_opcode(cpustate, op);
+ break;
+ }
+ break;
+ case 0x000a: // DEC Rd
+ rd = READ_IO_8(cpustate, RD5(op));
+ res = rd - 1;
+ SREG_W(AVR8_SREG_V, (rd == 0x7f) ? 1 : 0);
+ SREG_W(AVR8_SREG_N, BIT(res,7));
+ SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V));
+ SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0);
+ WRITE_IO_8(cpustate, RD5(op), res);
+ break;
+ case 0x000c:
+ case 0x000d: // JMP k
+ offs = KCONST22(op) << 16;
+ cpustate->pc++;
+ offs |= READ_PRG_16(cpustate, cpustate->pc);
+ cpustate->pc = offs;
+ cpustate->pc--;
+ opcycles = 4;
+ break;
+ case 0x000e: // CALL k
+ case 0x000f:
+ PUSH(cpustate, ((cpustate->pc + 1) >> 8) & 0x00ff);
+ PUSH(cpustate, (cpustate->pc + 1) & 0x00ff);
+ offs = KCONST22(op) << 16;
+ cpustate->pc++;
+ offs |= READ_PRG_16(cpustate, cpustate->pc);
+ cpustate->pc = offs;
+ cpustate->pc--;
+ break;
+ default:
+ unimplemented_opcode(cpustate, op);
+ //output += sprintf( output, "Undefined (%04x)", op );
+ break;
+ }
+ break;
+ case 0x0500:
+ switch(op & 0x000f)
+ {
+ case 0x0000: // COM Rd
+ rd = READ_IO_8(cpustate, RD5(op));
+ rd = ~rd;
+ SREG_W(AVR8_SREG_C, 1);
+ SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0);
+ SREG_W(AVR8_SREG_N, BIT(res,7));
+ SREG_W(AVR8_SREG_V, 0);
+ SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) | SREG_R(AVR8_SREG_V));
+ break;
+ case 0x0001: // NEG Rd
+ rd = READ_IO_8(cpustate, RD5(op));
+ res = 0 - rd;
+ WRITE_IO_8(cpustate, RD5(op), res);
+ SREG_W(AVR8_SREG_C, (res == 0) ? 0 : 1);
+ SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0);
+ SREG_W(AVR8_SREG_N, BIT(res,7));
+ SREG_W(AVR8_SREG_V, (res == 0x80) ? 1 : 0);
+ SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) | SREG_R(AVR8_SREG_V));
+ SREG_W(AVR8_SREG_H, BIT(res,3) | BIT(rd,3));
+ break;
+ case 0x0002: // SWAP Rd
+ //output += sprintf( output, "SWAP R%d", RD5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0003: // INC Rd
+ rd = READ_IO_8(cpustate, RD5(op));
+ res = rd + 1;
+ SREG_W(AVR8_SREG_V, (rd == 0x7f) ? 1 : 0);
+ SREG_W(AVR8_SREG_N, BIT(res,7));
+ SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V));
+ SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0);
+ WRITE_IO_8(cpustate, RD5(op), res);
+ break;
+ case 0x0005: // ASR Rd
+ //output += sprintf( output, "ASR R%d", RD5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0006: // LSR Rd
+ rd = READ_IO_8(cpustate, RD5(op));
+ res = rd >> 1;
+ SREG_W(AVR8_SREG_C, rd & 0x01);
+ SREG_W(AVR8_SREG_Z, (res == 0) ? 1 :0);
+ SREG_W(AVR8_SREG_N, 0);
+ SREG_W(AVR8_SREG_V, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_C));
+ SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V));
+ break;
+ case 0x0007: // ROR Rd
+ //output += sprintf( output, "ROR R%d", RD5(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0008:
+ switch(op & 0x00f0)
+ {
+ case 0x0000: // RET
+ cpustate->pc = POP(cpustate);
+ cpustate->pc |= POP(cpustate) << 8;
+ cpustate->pc--;
+ opcycles = 4;
+ break;
+ case 0x0010: // RETI
+ cpustate->pc = POP(cpustate);
+ cpustate->pc |= POP(cpustate) << 8;
+ cpustate->pc--;
+ SREG_W(AVR8_SREG_I, 1);
+ opcycles = 4;
+ break;
+ case 0x0080: // SLEEP
+ //output += sprintf( output, "SLEEP" );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0090: // BREAK
+ //output += sprintf( output, "BREAK" );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x00a0: // WDR
+ //output += sprintf( output, "WDR" );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x00c0: // LPM
+ WRITE_IO_8(cpustate, 0, READ_PRG_8(cpustate, ZREG));
+ opcycles = 3;
+ break;
+ case 0x00d0: // ELPM
+ //output += sprintf( output, "ELPM" );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x00e0: // SPM
+ //output += sprintf( output, "SPM" );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x00f0: // SPM Z+
+ //output += sprintf( output, "SPM Z+" );
+ unimplemented_opcode(cpustate, op);
+ break;
+ default:
+ unimplemented_opcode(cpustate, op);
+ //output += sprintf( output, "Undefined (%04x)", op );
+ break;
+ }
+ break;
+ case 0x0009:
+ switch(op & 0x00f0)
+ {
+ case 0x0000: // ICALL
+ //output += sprintf( output, "ICALL" );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0010: // EICALL
+ //output += sprintf( output, "EICALL" );
+ unimplemented_opcode(cpustate, op);
+ break;
+ default:
+ unimplemented_opcode(cpustate, op);
+ //output += sprintf( output, "Undefined (%04x)", op );
+ break;
+ }
+ break;
+ case 0x000a: // DEC Rd
+ rd = READ_IO_8(cpustate, RD5(op));
+ res = rd - 1;
+ SREG_W(AVR8_SREG_V, (rd == 0x7f) ? 1 : 0);
+ SREG_W(AVR8_SREG_N, BIT(res,7));
+ SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V));
+ SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0);
+ WRITE_IO_8(cpustate, RD5(op), res);
+ break;
+ case 0x000c:
+ case 0x000d: // JMP k
+ //op <<= 8;
+ //op |= oprom[pos++];
+ //op <<= 8;
+ //op |= oprom[pos++];
+ //output += sprintf( output, "JMP 0x%06x", KCONST22(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x000e:
+ case 0x000f: // CALL k
+ //op <<= 8;
+ //op |= oprom[pos++];
+ //op <<= 8;
+ //op |= oprom[pos++];
+ //output += sprintf( output, "CALL 0x%06x", KCONST22(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ }
+ break;
+ case 0x0600: // ADIW Rd+1:Rd,K
+ //output += sprintf( output, "ADIW R%d:R%d, 0x%02x", 24+(RD2(op) << 1)+1, 24+(RD2(op) << 1), KCONST6(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0700: // SBIW Rd+1:Rd,K
+ //output += sprintf( output, "SBIW R%d:R%d, 0x%02x", 24+(RD2(op) << 1)+1, 24+(RD2(op) << 1), KCONST6(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0800: // CBI A,b
+ //output += sprintf( output, "CBI 0x%02x, %d", ACONST5(op), RR3(op) );
+ WRITE_IO_8(cpustate, ACONST5(op), READ_IO_8(cpustate, ACONST5(op)) &~ (1 << RR3(op)));
+ opcycles = 2;
+ break;
+ case 0x0900: // SBIC A,b
+ if(!(READ_IO_8(cpustate, ACONST5(op)) & (1 << RR3(op))))
+ {
+ opcycles += avr8_is_long_opcode(op) ? 2 : 1;
+ cpustate->pc += avr8_is_long_opcode(op) ? 2 : 1;
+ }
+ break;
+ case 0x0a00: // SBI A,b
+ //output += sprintf( output, "SBI 0x%02x, %d", ACONST5(op), RR3(op) );
+ WRITE_IO_8(cpustate, ACONST5(op), READ_IO_8(cpustate, ACONST5(op)) | (1 << RR3(op)));
+ opcycles = 2;
+ break;
+ case 0x0b00: // SBIS A,b
+ //output += sprintf( output, "SBIS 0x%02x, %d", ACONST5(op), RR3(op) );
+ unimplemented_opcode(cpustate, op);
+ break;
+ case 0x0c00:
+ case 0x0d00:
+ case 0x0e00:
+ case 0x0f00: // MUL Rd,Rr
+ sd = (UINT8)READ_IO_8(cpustate, RD5(op)) * (UINT8)READ_IO_8(cpustate, RR5(op));
+ WRITE_IO_8(cpustate, 1, (sd >> 8) & 0x00ff);
+ WRITE_IO_8(cpustate, 0, sd & 0x00ff);
+ SREG_W(AVR8_SREG_C, (sd & 0x8000) ? 1 : 0);
+ SREG_W(AVR8_SREG_Z, (sd == 0) ? 1 : 0);
+ opcycles = 2;
+ //output += sprintf( output, "MUL R%d, R%d", RD5(op), RR5(op) );
+ break;
+ }
+ break;
+ case 0xb000:
+ if(op & 0x0800) // OUT A,Rr
+ {
+ WRITE_IO_8(cpustate, 0x20 + ACONST6(op), READ_IO_8(cpustate, RD5(op)));
+ }
+ else // IN Rd,A
+ {
+ WRITE_IO_8(cpustate, RD5(op), READ_IO_8(cpustate, 0x20 + ACONST6(op)));
+ }
+ break;
+ case 0xc000: // RJMP k
+ offs = (INT32)((op & 0x0800) ? ((op & 0x0fff) | 0xfffff000) : (op & 0x0fff));
+ cpustate->pc += offs;
+ opcycles = 2;
+ break;
+ case 0xd000: // RCALL k
+ offs = (INT32)((op & 0x0800) ? ((op & 0x0fff) | 0xfffff000) : (op & 0x0fff));
+ PUSH(cpustate, ((cpustate->pc + 1) >> 8) & 0x00ff);
+ PUSH(cpustate, (cpustate->pc + 1) & 0x00ff);
+ cpustate->pc += offs;
+ opcycles = 3;
+ break;
+ case 0xe000: // LDI Rd,K
+ rd = KCONST8(op);
+ WRITE_IO_8(cpustate, 16 + RD4(op), rd);
+ break;
+ case 0xf000:
+ switch(op & 0x0c00)
+ {
+ case 0x0000: // BRLO through BRIE
+ if(SREG_R(op & 0x0007))
+ {
+ offs = (INT32)(KCONST7(op));
+ if(offs & 0x40)
+ {
+ offs |= 0xffffff80;
+ }
+ cpustate->pc += offs;
+ opcycles = 2;
+ }
+ break;
+ case 0x0400: // BRSH through BRID
+ if(SREG_R(op & 0x0007) == 0)
+ {
+ offs = (INT32)(KCONST7(op));
+ if(offs & 0x40)
+ {
+ offs |= 0xffffff80;
+ }
+ cpustate->pc += offs;
+ opcycles = 2;
+ }
+ break;
+ case 0x0800:
+ if(op & 0x0200) // BST Rd, b
+ {
+ SREG_W(AVR8_SREG_T, (BIT(READ_IO_8(cpustate, RD5(op)),RR3(op))) ? 1 : 0);
+ }
+ else // BLD Rd, b
+ {
+ if(SREG_R(AVR8_SREG_T))
+ {
+ WRITE_IO_8(cpustate, RD5(op), READ_IO_8(cpustate, RD5(op)) | (1 << RR3(op)));
+ }
+ else
+ {
+ WRITE_IO_8(cpustate, RD5(op), READ_IO_8(cpustate, RD5(op)) &~ (1 << RR3(op)));
+ }
+ }
+ break;
+ case 0x0c00:
+ if(op & 0x0200) // SBRS Rd, b
+ {
+ if(BIT(READ_IO_8(cpustate, RD5(op)),RR3(op)))
+ {
+ op = (UINT32)READ_PRG_16(cpustate, cpustate->pc++);
+ opcycles = 2;
+ if((op & 0xfe0c) == 0x940c ||
+ (op & 0xfe0f) == 0xfe0f)
+ {
+ cpustate->pc++;
+ opcycles = 3;
+ }
+ }
+ }
+ else // SBRC Rd, b
+ {
+ if(!BIT(READ_IO_8(cpustate, RD5(op)),RR3(op)))
+ {
+ op = (UINT32)READ_PRG_16(cpustate, cpustate->pc++);
+ opcycles = 2;
+ if((op & 0xfe0c) == 0x940c ||
+ (op & 0xfc0f) == 0x9000)
+ {
+ cpustate->pc++;
+ opcycles = 3;
+ }
+ }
+ }
+ break;
+ }
+ break;
+ }
+
+ cpustate->pc++;
+
+ cpustate->icount -= opcycles;
+ }
+}
+
+/*****************************************************************************/
+
+static CPU_SET_INFO( avr8 )
+{
+ avr8_state *cpustate = get_safe_token(device);
+
+ switch (state)
+ {
+
+ /* interrupt lines/exceptions */
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_RESET: avr8_set_irq_line(cpustate, AVR8_INT_RESET, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_INT0: avr8_set_irq_line(cpustate, AVR8_INT_INT0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_INT1: avr8_set_irq_line(cpustate, AVR8_INT_INT1, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_PCINT0: avr8_set_irq_line(cpustate, AVR8_INT_PCINT0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_PCINT1: avr8_set_irq_line(cpustate, AVR8_INT_PCINT1, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_PCINT2: avr8_set_irq_line(cpustate, AVR8_INT_PCINT2, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_WDT: avr8_set_irq_line(cpustate, AVR8_INT_WDT, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_T2COMPA: avr8_set_irq_line(cpustate, AVR8_INT_T2COMPA, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_T2COMPB: avr8_set_irq_line(cpustate, AVR8_INT_T2COMPB, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_T2OVF: avr8_set_irq_line(cpustate, AVR8_INT_T2OVF, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_T1CAPT: avr8_set_irq_line(cpustate, AVR8_INT_T1CAPT, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_T1COMPA: avr8_set_irq_line(cpustate, AVR8_INT_T1COMPA, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_T1COMPB: avr8_set_irq_line(cpustate, AVR8_INT_T1COMPB, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_T1OVF: avr8_set_irq_line(cpustate, AVR8_INT_T1OVF, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_T0COMPA: avr8_set_irq_line(cpustate, AVR8_INT_T0COMPA, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_T0COMPB: avr8_set_irq_line(cpustate, AVR8_INT_T0COMPB, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_T0OVF: avr8_set_irq_line(cpustate, AVR8_INT_T0OVF, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_SPI_STC: avr8_set_irq_line(cpustate, AVR8_INT_SPI_STC, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_USART_RX: avr8_set_irq_line(cpustate, AVR8_INT_USART_RX, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_USART_UDRE: avr8_set_irq_line(cpustate, AVR8_INT_USART_UDRE, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_USART_TX: avr8_set_irq_line(cpustate, AVR8_INT_USART_TX, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_ADC: avr8_set_irq_line(cpustate, AVR8_INT_ADC, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_EE_RDY: avr8_set_irq_line(cpustate, AVR8_INT_EE_RDY, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_ANALOG_COMP: avr8_set_irq_line(cpustate, AVR8_INT_ANALOG_COMP, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_TWI: avr8_set_irq_line(cpustate, AVR8_INT_TWI, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + AVR8_INT_SPM_RDY: avr8_set_irq_line(cpustate, AVR8_INT_SPM_RDY, info->i); break;
+
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_PC: /* intentional fallthrough */
+ case CPUINFO_INT_REGISTER + AVR8_PC: cpustate->pc = info->i; break;
+ case CPUINFO_INT_REGISTER + AVR8_SREG: WRITE_IO_8(cpustate, AVR8_IO_SREG, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R0: WRITE_IO_8(cpustate, 0, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R1: WRITE_IO_8(cpustate, 1, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R2: WRITE_IO_8(cpustate, 2, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R3: WRITE_IO_8(cpustate, 3, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R4: WRITE_IO_8(cpustate, 4, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R5: WRITE_IO_8(cpustate, 5, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R6: WRITE_IO_8(cpustate, 6, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R7: WRITE_IO_8(cpustate, 7, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R8: WRITE_IO_8(cpustate, 8, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R9: WRITE_IO_8(cpustate, 9, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R10: WRITE_IO_8(cpustate, 10, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R11: WRITE_IO_8(cpustate, 11, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R12: WRITE_IO_8(cpustate, 12, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R13: WRITE_IO_8(cpustate, 13, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R14: WRITE_IO_8(cpustate, 14, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R15: WRITE_IO_8(cpustate, 15, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R16: WRITE_IO_8(cpustate, 16, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R17: WRITE_IO_8(cpustate, 17, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R18: WRITE_IO_8(cpustate, 18, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R19: WRITE_IO_8(cpustate, 19, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R20: WRITE_IO_8(cpustate, 20, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R21: WRITE_IO_8(cpustate, 21, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R22: WRITE_IO_8(cpustate, 22, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R23: WRITE_IO_8(cpustate, 23, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R24: WRITE_IO_8(cpustate, 24, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R25: WRITE_IO_8(cpustate, 25, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R26: WRITE_IO_8(cpustate, 26, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R27: WRITE_IO_8(cpustate, 27, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R28: WRITE_IO_8(cpustate, 28, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R29: WRITE_IO_8(cpustate, 29, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R30: WRITE_IO_8(cpustate, 30, info->i); break;
+ case CPUINFO_INT_REGISTER + AVR8_R31: WRITE_IO_8(cpustate, 31, info->i); break;
+ }
+}
+
+CPU_GET_INFO( avr8 )
+{
+ avr8_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch(state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(avr8_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 0; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 2; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 4; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 22; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 11; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_PC: /* intentional fallthrough */
+ case CPUINFO_INT_REGISTER + AVR8_PC: info->i = cpustate->pc << 1; break;
+ case CPUINFO_INT_REGISTER + AVR8_SREG: info->i = READ_IO_8(cpustate, AVR8_IO_SREG); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(avr8); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(avr8); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(avr8); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(avr8); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(avr8); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(avr8); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "Atmel 8-bit AVR"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "AVR8"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Nicola Salmoria and the MAME Team"); break;
+
+ case CPUINFO_STR_FLAGS: strcpy(info->s, " "); break;
+
+ case CPUINFO_STR_REGISTER + AVR8_SREG: sprintf(info->s, "SREG: %c%c%c%c%c%c%c%c", (READ_IO_8(cpustate, AVR8_IO_SREG) & 0x80) ? 'I' : '-', (READ_IO_8(cpustate, AVR8_IO_SREG) & 0x40) ? 'T' : '-', (READ_IO_8(cpustate, AVR8_IO_SREG) & 0x20) ? 'H' : '-', (READ_IO_8(cpustate, AVR8_IO_SREG) & 0x10) ? 'S' : '-', (READ_IO_8(cpustate, AVR8_IO_SREG) & 0x08) ? 'V' : '-', (READ_IO_8(cpustate, AVR8_IO_SREG) & 0x04) ? 'N' : '-', (READ_IO_8(cpustate, AVR8_IO_SREG) & 0x02) ? 'Z' : '-', (READ_IO_8(cpustate, AVR8_IO_SREG) & 0x01) ? 'C' : '-'); break;
+ case CPUINFO_STR_REGISTER + AVR8_R0: sprintf(info->s, "R0: %02x", READ_IO_8(cpustate, 0) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R1: sprintf(info->s, "R1: %02x", READ_IO_8(cpustate, 1) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R2: sprintf(info->s, "R2: %02x", READ_IO_8(cpustate, 2) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R3: sprintf(info->s, "R3: %02x", READ_IO_8(cpustate, 3) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R4: sprintf(info->s, "R4: %02x", READ_IO_8(cpustate, 4) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R5: sprintf(info->s, "R5: %02x", READ_IO_8(cpustate, 5) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R6: sprintf(info->s, "R6: %02x", READ_IO_8(cpustate, 6) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R7: sprintf(info->s, "R7: %02x", READ_IO_8(cpustate, 7) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R8: sprintf(info->s, "R8: %02x", READ_IO_8(cpustate, 8) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R9: sprintf(info->s, "R9: %02x", READ_IO_8(cpustate, 9) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R10: sprintf(info->s, "R10: %02x", READ_IO_8(cpustate, 10) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R11: sprintf(info->s, "R11: %02x", READ_IO_8(cpustate, 11) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R12: sprintf(info->s, "R12: %02x", READ_IO_8(cpustate, 12) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R13: sprintf(info->s, "R13: %02x", READ_IO_8(cpustate, 13) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R14: sprintf(info->s, "R14: %02x", READ_IO_8(cpustate, 14) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R15: sprintf(info->s, "R15: %02x", READ_IO_8(cpustate, 15) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R16: sprintf(info->s, "R16: %02x", READ_IO_8(cpustate, 16) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R17: sprintf(info->s, "R17: %02x", READ_IO_8(cpustate, 17) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R18: sprintf(info->s, "R18: %02x", READ_IO_8(cpustate, 18) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R19: sprintf(info->s, "R19: %02x", READ_IO_8(cpustate, 19) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R20: sprintf(info->s, "R20: %02x", READ_IO_8(cpustate, 20) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R21: sprintf(info->s, "R21: %02x", READ_IO_8(cpustate, 21) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R22: sprintf(info->s, "R22: %02x", READ_IO_8(cpustate, 22) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R23: sprintf(info->s, "R23: %02x", READ_IO_8(cpustate, 23) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R24: sprintf(info->s, "R24: %02x", READ_IO_8(cpustate, 24) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R25: sprintf(info->s, "R25: %02x", READ_IO_8(cpustate, 25) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R26: sprintf(info->s, "R26: %02x", READ_IO_8(cpustate, 26) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R27: sprintf(info->s, "R27: %02x", READ_IO_8(cpustate, 27) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R28: sprintf(info->s, "R28: %02x", READ_IO_8(cpustate, 28) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R29: sprintf(info->s, "R29: %02x", READ_IO_8(cpustate, 29) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R30: sprintf(info->s, "R30: %02x", READ_IO_8(cpustate, 30) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_R31: sprintf(info->s, "R31: %02x", READ_IO_8(cpustate, 31) ); break;
+ case CPUINFO_STR_REGISTER + AVR8_X: sprintf(info->s, "X: %04x", XREG ); break;
+ case CPUINFO_STR_REGISTER + AVR8_Y: sprintf(info->s, "Y: %04x", YREG ); break;
+ case CPUINFO_STR_REGISTER + AVR8_Z: sprintf(info->s, "Z: %04x", ZREG ); break;
+ case CPUINFO_STR_REGISTER + AVR8_SP: sprintf(info->s, "SP: %04x", SPREG ); break;
+ }
+}
+
+static CPU_INIT( atmega88 )
+{
+ CPU_INIT_CALL(avr8);
+ avr8_state *cpustate = get_safe_token(device);
+ cpustate->addr_mask = 0x0fff;
+}
+
+static CPU_INIT( atmega644 )
+{
+ CPU_INIT_CALL(avr8);
+ avr8_state *cpustate = get_safe_token(device);
+ cpustate->addr_mask = 0xffff;
+}
+
+CPU_GET_INFO( atmega88 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(atmega88); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "ATmega88"); break;
+
+ default: CPU_GET_INFO_CALL(avr8); break;
+ }
+}
+
+CPU_GET_INFO( atmega644 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(atmega644); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "ATmega644"); break;
+
+ default: CPU_GET_INFO_CALL(avr8); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(ATMEGA88, atmega88);
+DEFINE_LEGACY_CPU_DEVICE(ATMEGA644, atmega644);
diff --git a/trunk/src/emu/cpu/avr8/avr8.h b/trunk/src/emu/cpu/avr8/avr8.h
new file mode 100644
index 00000000000..ff3816333c2
--- /dev/null
+++ b/trunk/src/emu/cpu/avr8/avr8.h
@@ -0,0 +1,91 @@
+/*
+ Atmel 8-bit AVR simulator
+
+ (Skeleton)
+
+ Written by MooglyGuy
+*/
+
+#pragma once
+
+#ifndef __AVR8_H__
+#define __AVR8_H__
+
+enum
+{
+ AVR8_SREG = 1,
+ AVR8_PC,
+ AVR8_R0,
+ AVR8_R1,
+ AVR8_R2,
+ AVR8_R3,
+ AVR8_R4,
+ AVR8_R5,
+ AVR8_R6,
+ AVR8_R7,
+ AVR8_R8,
+ AVR8_R9,
+ AVR8_R10,
+ AVR8_R11,
+ AVR8_R12,
+ AVR8_R13,
+ AVR8_R14,
+ AVR8_R15,
+ AVR8_R16,
+ AVR8_R17,
+ AVR8_R18,
+ AVR8_R19,
+ AVR8_R20,
+ AVR8_R21,
+ AVR8_R22,
+ AVR8_R23,
+ AVR8_R24,
+ AVR8_R25,
+ AVR8_R26,
+ AVR8_R27,
+ AVR8_R28,
+ AVR8_R29,
+ AVR8_R30,
+ AVR8_R31,
+ AVR8_X,
+ AVR8_Y,
+ AVR8_Z,
+ AVR8_SP,
+};
+
+enum
+{
+ AVR8_INT_RESET = 0,
+ AVR8_INT_INT0,
+ AVR8_INT_INT1,
+ AVR8_INT_PCINT0,
+ AVR8_INT_PCINT1,
+ AVR8_INT_PCINT2,
+ AVR8_INT_WDT,
+ AVR8_INT_T2COMPA,
+ AVR8_INT_T2COMPB,
+ AVR8_INT_T2OVF,
+ AVR8_INT_T1CAPT,
+ AVR8_INT_T1COMPA,
+ AVR8_INT_T1COMPB,
+ AVR8_INT_T1OVF,
+ AVR8_INT_T0COMPA,
+ AVR8_INT_T0COMPB,
+ AVR8_INT_T0OVF,
+ AVR8_INT_SPI_STC,
+ AVR8_INT_USART_RX,
+ AVR8_INT_USART_UDRE,
+ AVR8_INT_USART_TX,
+ AVR8_INT_ADC,
+ AVR8_INT_EE_RDY,
+ AVR8_INT_ANALOG_COMP,
+ AVR8_INT_TWI,
+ AVR8_INT_SPM_RDY,
+};
+
+DECLARE_LEGACY_CPU_DEVICE(ATMEGA88, atmega88);
+DECLARE_LEGACY_CPU_DEVICE(ATMEGA644, atmega644);
+
+CPU_DISASSEMBLE( avr8 );
+
+#endif /* __AVR8_H__ */
diff --git a/trunk/src/emu/cpu/avr8/avr8dasm.c b/trunk/src/emu/cpu/avr8/avr8dasm.c
new file mode 100644
index 00000000000..9764927e09f
--- /dev/null
+++ b/trunk/src/emu/cpu/avr8/avr8dasm.c
@@ -0,0 +1,568 @@
+/*
+ Atmel 8-bit AVR disassembler
+
+ Written by MooglyGuy
+*/
+
+#include "emu.h"
+#include "avr8.h"
+
+#define RD2(op) (((op) >> 4) & 0x0003)
+#define RD3(op) (((op) >> 4) & 0x0007)
+#define RD4(op) (((op) >> 4) & 0x000f)
+#define RD5(op) (((op) >> 4) & 0x001f)
+#define RR3(op) ((op) & 0x0007)
+#define RR4(op) ((op) & 0x000f)
+#define RR5(op) ((((op) >> 5) & 0x0010) | ((op) & 0x000f))
+#define KCONST6(op) ((((op) >> 2) & 0x0030) | ((op) & 0x000f))
+#define KCONST7(op) (((op) >> 3) & 0x007f)
+#define KCONST8(op) ((((op) >> 4) & 0x00f0) | ((op) & 0x000f))
+#define KCONST22(op) (((((UINT32)(op) >> 3) & 0x003e) | ((UINT32)(op) & 0x0001)) << 16)
+#define QCONST6(op) ((((op) >> 8) & 0x0020) | (((op) >> 7) & 0x0018) | ((op) & 0x0007))
+#define ACONST5(op) (((op) >> 3) & 0x001f)
+#define ACONST6(op) ((((op) >> 5) & 0x0030) | ((op) & 0x000f))
+
+CPU_DISASSEMBLE( avr8 )
+{
+ char *output = buffer;
+ int pos = 0;
+ UINT32 op = oprom[pos++];
+ op |= oprom[pos++] << 8;
+ UINT32 addr = 0;
+ switch(op & 0xf000)
+ {
+ case 0x0000:
+ switch(op & 0x0f00)
+ {
+ case 0x0000:
+ output += sprintf( output, "NOP" );
+ break;
+ case 0x0100:
+ output += sprintf( output, "MOVW R%d:R%d, R%d:R%d", (RD4(op) << 1)+1, RD4(op) << 1, (RR4(op) << 1)+1, RR4(op) << 1 );
+ break;
+ case 0x0200:
+ output += sprintf( output, "MULS R%d, R%d", 16+RD4(op), 16+RR4(op) );
+ break;
+ case 0x0300:
+ output += sprintf( output, "MULSU R%d, R%d", 16+RD4(op), 16+RR4(op) );
+ break;
+ case 0x0400:
+ case 0x0500:
+ case 0x0600:
+ case 0x0700:
+ output += sprintf( output, "CPC R%d, R%d", RD5(op), RR5(op) );
+ break;
+ case 0x0800:
+ case 0x0900:
+ case 0x0a00:
+ case 0x0b00:
+ output += sprintf( output, "SBC R%d, R%d", RD5(op), RR5(op) );
+ break;
+ case 0x0c00:
+ case 0x0d00:
+ case 0x0e00:
+ case 0x0f00:
+ output += sprintf( output, "ADD R%d, R%d", RD5(op), RR5(op) );
+ break;
+ }
+ break;
+ case 0x1000:
+ switch(op & 0x0c00)
+ {
+ case 0x0000:
+ output += sprintf( output, "CPSE R%d, R%d", RD5(op), RR5(op) );
+ break;
+ case 0x0400:
+ output += sprintf( output, "CP R%d, R%d", RD5(op), RR5(op) );
+ break;
+ case 0x0800:
+ output += sprintf( output, "SUB R%d, R%d", RD5(op), RR5(op) );
+ break;
+ case 0x0c00:
+ output += sprintf( output, "ADC R%d, R%d", RD5(op), RR5(op) );
+ break;
+ }
+ break;
+ case 0x2000:
+ switch(op & 0x0c00)
+ {
+ case 0x0000:
+ output += sprintf( output, "AND R%d, R%d", RD5(op), RR5(op) );
+ break;
+ case 0x0400:
+ output += sprintf( output, "EOR R%d, R%d", RD5(op), RR5(op) );
+ break;
+ case 0x0800:
+ output += sprintf( output, "OR R%d, R%d", RD5(op), RR5(op) );
+ break;
+ case 0x0c00:
+ output += sprintf( output, "MOV R%d, R%d", RD5(op), RR5(op) );
+ break;
+ }
+ break;
+ case 0x3000:
+ output += sprintf( output, "CPI R%d, 0x%02x", 16+RD4(op), KCONST8(op) );
+ break;
+ case 0x4000:
+ output += sprintf( output, "SBCI R%d, 0x%02x", 16+RD4(op), KCONST8(op) );
+ break;
+ case 0x5000:
+ output += sprintf( output, "SUBI R%d, 0x%02x", 16+RD4(op), KCONST8(op) );
+ break;
+ case 0x6000:
+ output += sprintf( output, "ORI R%d, 0x%02x", 16+RD4(op), KCONST8(op) );
+ break;
+ case 0x7000:
+ output += sprintf( output, "ANDI R%d, 0x%02x", 16+RD4(op), KCONST8(op) );
+ break;
+ case 0x8000:
+ case 0xa000:
+ switch(op & 0x0208)
+ {
+ case 0x0000:
+ output += sprintf( output, "LD(D) R%d, Z+%02x", RD5(op), QCONST6(op) );
+ break;
+ case 0x0008:
+ output += sprintf( output, "LD(D) R%d, Y+%02x", RD5(op), QCONST6(op) );
+ break;
+ case 0x0200:
+ output += sprintf( output, "ST(D) Z+%02x, R%d", QCONST6(op), RD5(op) );
+ break;
+ case 0x0208:
+ output += sprintf( output, "ST(D) Y+%02x, R%d", QCONST6(op), RD5(op) );
+ break;
+ }
+ break;
+ case 0x9000:
+ switch(op & 0x0f00)
+ {
+ case 0x0000:
+ case 0x0100:
+ switch(op & 0x000f)
+ {
+ case 0x0000:
+ op <<= 16;
+ op |= oprom[pos++];
+ op |= oprom[pos++] << 8;
+ output += sprintf( output, "LDS R%d, (0x%04x)", RD5(op >> 16), op & 0x0000ffff );
+ break;
+ case 0x0001:
+ output += sprintf( output, "LD R%d, Z+", RD5(op) );
+ break;
+ case 0x0002:
+ output += sprintf( output, "LD R%d,-Z", RD5(op) );
+ break;
+ case 0x0004:
+ output += sprintf( output, "LPM R%d, Z", RD5(op) );
+ break;
+ case 0x0005:
+ output += sprintf( output, "LPM R%d, Z+", RD5(op) );
+ break;
+ case 0x0006:
+ output += sprintf( output, "ELPM R%d, Z", RD5(op) );
+ break;
+ case 0x0007:
+ output += sprintf( output, "ELPM R%d, Z+", RD5(op) );
+ break;
+ case 0x0009:
+ output += sprintf( output, "LD R%d, Y+", RD5(op) );
+ break;
+ case 0x000a:
+ output += sprintf( output, "LD R%d,-Y", RD5(op) );
+ break;
+ case 0x000c:
+ output += sprintf( output, "LD R%d, X", RD5(op) );
+ break;
+ case 0x000d:
+ output += sprintf( output, "LD R%d, X+", RD5(op) );
+ break;
+ case 0x000e:
+ output += sprintf( output, "LD R%d,-X", RD5(op) );
+ break;
+ case 0x000f:
+ output += sprintf( output, "POP R%d", RD5(op) );
+ break;
+ default:
+ output += sprintf( output, "Undefined (%08x)", op );
+ break;
+ }
+ break;
+ case 0x0200:
+ case 0x0300:
+ switch(op & 0x000f)
+ {
+ case 0x0000:
+ op <<= 16;
+ op |= oprom[pos++];
+ op |= oprom[pos++] << 8;
+ output += sprintf( output, "STS (0x%04x), R%d", op & 0x0000ffff, RD5(op >> 16) );
+ break;
+ case 0x0001:
+ output += sprintf( output, "ST Z+, R%d", RD5(op) );
+ break;
+ case 0x0002:
+ output += sprintf( output, "ST -Z , R%d", RD5(op) );
+ break;
+ case 0x0009:
+ output += sprintf( output, "ST Y+, R%d", RD5(op) );
+ break;
+ case 0x000a:
+ output += sprintf( output, "ST -Y , R%d", RD5(op) );
+ break;
+ case 0x000c:
+ output += sprintf( output, "ST X , R%d", RD5(op) );
+ break;
+ case 0x000d:
+ output += sprintf( output, "ST X+, R%d", RD5(op) );
+ break;
+ case 0x000e:
+ output += sprintf( output, "ST -X , R%d", RD5(op) );
+ break;
+ case 0x000f:
+ output += sprintf( output, "PUSH R%d", RD5(op) );
+ break;
+ default:
+ output += sprintf( output, "Undefined (%08x)", op );
+ break;
+ }
+ break;
+ case 0x0400:
+ switch(op & 0x000f)
+ {
+ case 0x0000:
+ output += sprintf( output, "COM R%d", RD5(op) );
+ break;
+ case 0x0001:
+ output += sprintf( output, "NEG R%d", RD5(op) );
+ break;
+ case 0x0002:
+ output += sprintf( output, "SWAP R%d", RD5(op) );
+ break;
+ case 0x0003:
+ output += sprintf( output, "INC R%d", RD5(op) );
+ break;
+ case 0x0005:
+ output += sprintf( output, "ASR R%d", RD5(op) );
+ break;
+ case 0x0006:
+ output += sprintf( output, "LSR R%d", RD5(op) );
+ break;
+ case 0x0007:
+ output += sprintf( output, "ROR R%d", RD5(op) );
+ break;
+ case 0x0008:
+ switch(op & 0x00f0)
+ {
+ case 0x0000:
+ output += sprintf( output, "SEC" );
+ break;
+ case 0x0010:
+ output += sprintf( output, "SEZ" );
+ break;
+ case 0x0020:
+ output += sprintf( output, "SEN" );
+ break;
+ case 0x0030:
+ output += sprintf( output, "SEV" );
+ break;
+ case 0x0040:
+ output += sprintf( output, "SES" );
+ break;
+ case 0x0050:
+ output += sprintf( output, "SEH" );
+ break;
+ case 0x0060:
+ output += sprintf( output, "SET" );
+ break;
+ case 0x0070:
+ output += sprintf( output, "SEI" );
+ break;
+ case 0x0080:
+ output += sprintf( output, "CLC" );
+ break;
+ case 0x0090:
+ output += sprintf( output, "CLZ" );
+ break;
+ case 0x00a0:
+ output += sprintf( output, "CLN" );
+ break;
+ case 0x00b0:
+ output += sprintf( output, "CLV" );
+ break;
+ case 0x00c0:
+ output += sprintf( output, "CLS" );
+ break;
+ case 0x00d0:
+ output += sprintf( output, "CLH" );
+ break;
+ case 0x00e0:
+ output += sprintf( output, "CLT" );
+ break;
+ case 0x00f0:
+ output += sprintf( output, "CLI" );
+ break;
+ default:
+ output += sprintf( output, "Undefined (%08x)", op );
+ break;
+ }
+ break;
+ case 0x0009:
+ switch(op & 0x00f0)
+ {
+ case 0x0000:
+ output += sprintf( output, "IJMP" );
+ break;
+ case 0x0010:
+ output += sprintf( output, "EIJMP" );
+ break;
+ default:
+ output += sprintf( output, "Undefined (%08x)", op );
+ break;
+ }
+ break;
+ case 0x000a:
+ output += sprintf( output, "DEC R%d", RD5(op) );
+ break;
+ case 0x000c:
+ case 0x000d:
+ addr = KCONST22(op) << 16;
+ addr |= oprom[pos++];
+ addr |= oprom[pos++] << 8;
+ output += sprintf( output, "JMP 0x%06x", addr << 1 );
+ break;
+ case 0x000e:
+ case 0x000f:
+ addr = KCONST22(op) << 16;
+ addr |= oprom[pos++];
+ addr |= oprom[pos++] << 8;
+ output += sprintf( output, "CALL 0x%06x", addr << 1 );
+ break;
+ default:
+ output += sprintf( output, "Undefined (%08x)", op );
+ break;
+ }
+ break;
+ case 0x0500:
+ switch(op & 0x000f)
+ {
+ case 0x0000:
+ output += sprintf( output, "COM R%d", RD5(op) );
+ break;
+ case 0x0001:
+ output += sprintf( output, "NEG R%d", RD5(op) );
+ break;
+ case 0x0002:
+ output += sprintf( output, "SWAP R%d", RD5(op) );
+ break;
+ case 0x0003:
+ output += sprintf( output, "INC R%d", RD5(op) );
+ break;
+ case 0x0005:
+ output += sprintf( output, "ASR R%d", RD5(op) );
+ break;
+ case 0x0006:
+ output += sprintf( output, "LSR R%d", RD5(op) );
+ break;
+ case 0x0007:
+ output += sprintf( output, "ROR R%d", RD5(op) );
+ break;
+ case 0x0008:
+ switch(op & 0x00f0)
+ {
+ case 0x0000:
+ output += sprintf( output, "RET" );
+ break;
+ case 0x0010:
+ output += sprintf( output, "RETI" );
+ break;
+ case 0x0080:
+ output += sprintf( output, "SLEEP" );
+ break;
+ case 0x0090:
+ output += sprintf( output, "BREAK" );
+ break;
+ case 0x00a0:
+ output += sprintf( output, "WDR" );
+ break;
+ case 0x00c0:
+ output += sprintf( output, "LPM" );
+ break;
+ case 0x00d0:
+ output += sprintf( output, "ELPM" );
+ break;
+ case 0x00e0:
+ output += sprintf( output, "SPM" );
+ break;
+ case 0x00f0:
+ output += sprintf( output, "SPM Z+" );
+ break;
+ default:
+ output += sprintf( output, "Undefined (%08x)", op );
+ break;
+ }
+ break;
+ case 0x0009:
+ switch(op & 0x00f0)
+ {
+ case 0x0000:
+ output += sprintf( output, "ICALL" );
+ break;
+ case 0x0010:
+ output += sprintf( output, "EICALL" );
+ break;
+ default:
+ output += sprintf( output, "Undefined (%08x)", op );
+ break;
+ }
+ break;
+ case 0x000a:
+ output += sprintf( output, "DEC R%d", RD5(op) );
+ break;
+ case 0x000c:
+ case 0x000d:
+ op <<= 16;
+ op |= oprom[pos++];
+ op |= oprom[pos++] << 8;
+ output += sprintf( output, "JMP 0x%06x", KCONST22(op) << 1 );
+ break;
+ case 0x000e:
+ case 0x000f:
+ op <<= 16;
+ op |= oprom[pos++];
+ op |= oprom[pos++] << 8;
+ output += sprintf( output, "CALL 0x%06x", KCONST22(op) << 1 );
+ break;
+ }
+ break;
+ case 0x0600:
+ output += sprintf( output, "ADIW R%d:R%d, 0x%02x", 24+(RD2(op) << 1)+1, 24+(RD2(op) << 1), KCONST6(op) );
+ break;
+ case 0x0700:
+ output += sprintf( output, "SBIW R%d:R%d, 0x%02x", 24+(RD2(op) << 1)+1, 24+(RD2(op) << 1), KCONST6(op) );
+ break;
+ case 0x0800:
+ output += sprintf( output, "CBI 0x%02x, %d", ACONST5(op), RR3(op) );
+ break;
+ case 0x0900:
+ output += sprintf( output, "SBIC 0x%02x, %d", ACONST5(op), RR3(op) );
+ break;
+ case 0x0a00:
+ output += sprintf( output, "SBI 0x%02x, %d", ACONST5(op), RR3(op) );
+ break;
+ case 0x0b00:
+ output += sprintf( output, "SBIS 0x%02x, %d", ACONST5(op), RR3(op) );
+ break;
+ case 0x0c00:
+ case 0x0d00:
+ case 0x0e00:
+ case 0x0f00:
+ output += sprintf( output, "MUL R%d, R%d", RD5(op), RR5(op) );
+ break;
+ }
+ break;
+ case 0xb000:
+ if(op & 0x0800)
+ {
+ output += sprintf( output, "OUT 0x%02x, R%d", ACONST6(op), RD5(op) );
+ }
+ else
+ {
+ output += sprintf( output, "IN R%d, 0x%02x", RD5(op), ACONST6(op) );
+ }
+ break;
+ case 0xc000:
+ output += sprintf( output, "RJMP %08x", (((op & 0x0800) ? ((op & 0x0fff) | 0xfffff000) : (op & 0x0fff)) << 1) );
+ break;
+ case 0xd000:
+ output += sprintf( output, "RCALL %08x", (((op & 0x0800) ? ((op & 0x0fff) | 0xfffff000) : (op & 0x0fff)) << 1) );
+ break;
+ case 0xe000:
+ output += sprintf( output, "LDI R%d, 0x%02x", 16 + RD4(op), KCONST8(op) );
+ break;
+ case 0xf000:
+ switch(op & 0x0c00)
+ {
+ case 0x0000:
+ switch(op & 0x0007)
+ {
+ case 0x0000:
+ output += sprintf( output, "BRLO %08x", (((op & 0x0200) ? ((KCONST7(op) & 0x007f) | 0xff80) : KCONST7(op)) << 1) );
+ break;
+ case 0x0001:
+ output += sprintf( output, "BREQ %08x", (((op & 0x0200) ? ((KCONST7(op) & 0x007f) | 0xff80) : KCONST7(op)) << 1) );
+ break;
+ case 0x0002:
+ output += sprintf( output, "BRMI %08x", (((op & 0x0200) ? ((KCONST7(op) & 0x007f) | 0xff80) : KCONST7(op)) << 1) );
+ break;
+ case 0x0003:
+ output += sprintf( output, "BRVS %08x", (((op & 0x0200) ? ((KCONST7(op) & 0x007f) | 0xff80) : KCONST7(op)) << 1) );
+ break;
+ case 0x0004:
+ output += sprintf( output, "BRLT %08x", (((op & 0x0200) ? ((KCONST7(op) & 0x007f) | 0xff80) : KCONST7(op)) << 1) );
+ break;
+ case 0x0005:
+ output += sprintf( output, "BRHS %08x", (((op & 0x0200) ? ((KCONST7(op) & 0x007f) | 0xff80) : KCONST7(op)) << 1) );
+ break;
+ case 0x0006:
+ output += sprintf( output, "BRTS %08x", (((op & 0x0200) ? ((KCONST7(op) & 0x007f) | 0xff80) : KCONST7(op)) << 1) );
+ break;
+ case 0x0007:
+ output += sprintf( output, "BRIE %08x", (((op & 0x0200) ? ((KCONST7(op) & 0x007f) | 0xff80) : KCONST7(op)) << 1) );
+ break;
+ }
+ break;
+ case 0x0400:
+ switch(op & 0x0007)
+ {
+ case 0x0000:
+ output += sprintf( output, "BRSH %08x", (((op & 0x0200) ? ((KCONST7(op) & 0x007f) | 0xff80) : KCONST7(op)) << 1) );
+ break;
+ case 0x0001:
+ output += sprintf( output, "BRNE %08x", (((op & 0x0200) ? ((KCONST7(op) & 0x007f) | 0xff80) : KCONST7(op)) << 1) );
+ break;
+ case 0x0002:
+ output += sprintf( output, "BRPL %08x", (((op & 0x0200) ? ((KCONST7(op) & 0x007f) | 0xff80) : KCONST7(op)) << 1) );
+ break;
+ case 0x0003:
+ output += sprintf( output, "BRVC %08x", (((op & 0x0200) ? ((KCONST7(op) & 0x007f) | 0xff80) : KCONST7(op)) << 1) );
+ break;
+ case 0x0004:
+ output += sprintf( output, "BRGE %08x", (((op & 0x0200) ? ((KCONST7(op) & 0x007f) | 0xff80) : KCONST7(op)) << 1) );
+ break;
+ case 0x0005:
+ output += sprintf( output, "BRHC %08x", (((op & 0x0200) ? ((KCONST7(op) & 0x007f) | 0xff80) : KCONST7(op)) << 1) );
+ break;
+ case 0x0006:
+ output += sprintf( output, "BRTC %08x", (((op & 0x0200) ? ((KCONST7(op) & 0x007f) | 0xff80) : KCONST7(op)) << 1) );
+ break;
+ case 0x0007:
+ output += sprintf( output, "BRID %08x", (((op & 0x0200) ? ((KCONST7(op) & 0x007f) | 0xff80) : KCONST7(op)) << 1) );
+ break;
+ }
+ break;
+ case 0x0800:
+ if(op & 0x0200)
+ {
+ output += sprintf( output, "BST R%d, %d", RD5(op), RR3(op) );
+ }
+ else
+ {
+ output += sprintf( output, "BLD R%d, %d", RD5(op), RR3(op) );
+ }
+ break;
+ case 0x0c00:
+ if(op & 0x0200)
+ {
+ output += sprintf( output, "SBRS R%d, %d", RD5(op), RR3(op) );
+ }
+ else
+ {
+ output += sprintf( output, "SBRC R%d, %d", RD5(op), RR3(op) );
+ }
+ break;
+ }
+ break;
+ }
+
+ return pos | DASMFLAG_SUPPORTED;
+}
diff --git a/trunk/src/emu/cpu/ccpu/ccpu.c b/trunk/src/emu/cpu/ccpu/ccpu.c
new file mode 100644
index 00000000000..0df55522816
--- /dev/null
+++ b/trunk/src/emu/cpu/ccpu/ccpu.c
@@ -0,0 +1,830 @@
+/***************************************************************************
+
+ ccpu.c
+ Core implementation for the portable Cinematronics CPU emulator.
+
+ Written by Aaron Giles
+ Special thanks to Zonn Moore for his detailed documentation.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "ccpu.h"
+
+
+/***************************************************************************
+ STRUCTURES & TYPEDEFS
+***************************************************************************/
+
+typedef struct _ccpu_state ccpu_state;
+struct _ccpu_state
+{
+ UINT16 PC;
+ UINT16 A;
+ UINT16 B;
+ UINT8 I;
+ UINT16 J;
+ UINT8 P;
+ UINT16 X;
+ UINT16 Y;
+ UINT16 T;
+ UINT16 * acc;
+
+ UINT16 a0flag, ncflag, cmpacc, cmpval;
+ UINT16 miflag, nextmiflag, nextnextmiflag;
+ UINT16 drflag;
+
+ ccpu_input_func external_input;
+ ccpu_vector_func vector_callback;
+
+ UINT8 waiting;
+ UINT8 watchdog;
+
+ int icount;
+
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ address_space *data;
+ address_space *io;
+};
+
+
+INLINE ccpu_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == CCPU);
+ return (ccpu_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+#define READOP(C,a) ((C)->direct->read_decrypted_byte(a))
+
+#define RDMEM(C,a) ((C)->data->read_word((a) * 2) & 0xfff)
+#define WRMEM(C,a,v) ((C)->data->write_word((a) * 2, (v)))
+
+#define READPORT(C,a) ((C)->io->read_byte(a))
+#define WRITEPORT(C,a,v) ((C)->io->write_byte((a), (v)))
+
+#define SET_A0(C) do { (C)->a0flag = (C)->A; } while (0)
+#define SET_CMP_VAL(C,x) do { (C)->cmpacc = *(C)->acc; (C)->cmpval = (x) & 0xfff; } while (0)
+#define SET_NC(C,a) do { (C)->ncflag = ~(a); } while (0)
+#define SET_MI(C,a) do { (C)->nextnextmiflag = (a); } while (0)
+
+#define TEST_A0(C) ((C)->a0flag & 1)
+#define TEST_NC(C) (((C)->ncflag >> 12) & 1)
+#define TEST_MI(C) (((C)->miflag >> 11) & 1)
+#define TEST_LT(C) ((C)->cmpval < (C)->cmpacc)
+#define TEST_EQ(C) ((C)->cmpval == (C)->cmpacc)
+#define TEST_DR(C) ((C)->drflag != 0)
+
+#define NEXT_ACC_A(C) do { SET_MI(C, *(C)->acc); (C)->acc = &(C)->A; } while (0)
+#define NEXT_ACC_B(C) do { SET_MI(C, *(C)->acc); if ((C)->acc == &(C)->A) (C)->acc = &(C)->B; else (C)->acc = &(C)->A; } while (0)
+
+#define CYCLES(C,x) do { (C)->icount -= (x); } while (0)
+
+#define STANDARD_ACC_OP(C,resexp,cmpval) \
+do { \
+ UINT16 result = resexp; \
+ SET_A0(C); /* set the A0 bit based on the previous 'A' value */ \
+ SET_CMP_VAL(C,cmpval); /* set the compare values to the previous accumulator and the cmpval */ \
+ SET_NC(C,result); /* set the NC flag based on the unmasked result */ \
+ *(C)->acc = result & 0xfff; /* store the low 12 bits of the new value */ \
+} while (0)
+
+
+
+/***************************************************************************
+ INITIALIZATION AND SHUTDOWN
+***************************************************************************/
+
+static UINT8 read_jmi(device_t *device)
+{
+ /* this routine is called when there is no external input */
+ /* and the JMI jumper is present */
+ ccpu_state *cpustate = get_safe_token(device);
+ return TEST_MI(cpustate);
+}
+
+
+void ccpu_wdt_timer_trigger(device_t *device)
+{
+ ccpu_state *cpustate = get_safe_token(device);
+ cpustate->waiting = FALSE;
+ cpustate->watchdog++;
+ if (cpustate->watchdog >= 3)
+ cpustate->PC = 0;
+}
+
+
+static CPU_INIT( ccpu )
+{
+ const ccpu_config *configdata = (const ccpu_config *)device->static_config();
+ ccpu_state *cpustate = get_safe_token(device);
+
+ /* copy input params */
+ cpustate->external_input = configdata->external_input ? configdata->external_input : read_jmi;
+ cpustate->vector_callback = configdata->vector_callback;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+ cpustate->data = device->space(AS_DATA);
+ cpustate->io = device->space(AS_IO);
+
+ device->save_item(NAME(cpustate->PC));
+ device->save_item(NAME(cpustate->A));
+ device->save_item(NAME(cpustate->B));
+ device->save_item(NAME(cpustate->I));
+ device->save_item(NAME(cpustate->J));
+ device->save_item(NAME(cpustate->P));
+ device->save_item(NAME(cpustate->X));
+ device->save_item(NAME(cpustate->Y));
+ device->save_item(NAME(cpustate->T));
+ device->save_item(NAME(cpustate->a0flag));
+ device->save_item(NAME(cpustate->ncflag));
+ device->save_item(NAME(cpustate->cmpacc));
+ device->save_item(NAME(cpustate->cmpval));
+ device->save_item(NAME(cpustate->miflag));
+ device->save_item(NAME(cpustate->nextmiflag));
+ device->save_item(NAME(cpustate->nextnextmiflag));
+ device->save_item(NAME(cpustate->drflag));
+ device->save_item(NAME(cpustate->waiting));
+ device->save_item(NAME(cpustate->watchdog));
+}
+
+
+static CPU_RESET( ccpu )
+{
+ ccpu_state *cpustate = get_safe_token(device);
+
+ /* zero registers */
+ cpustate->PC = 0;
+ cpustate->A = 0;
+ cpustate->B = 0;
+ cpustate->I = 0;
+ cpustate->J = 0;
+ cpustate->P = 0;
+ cpustate->X = 0;
+ cpustate->Y = 0;
+ cpustate->T = 0;
+ cpustate->acc = &cpustate->A;
+
+ /* zero flags */
+ cpustate->a0flag = 0;
+ cpustate->ncflag = 0;
+ cpustate->cmpacc = 0;
+ cpustate->cmpval = 1;
+ cpustate->miflag = cpustate->nextmiflag = cpustate->nextnextmiflag = 0;
+ cpustate->drflag = 0;
+
+ cpustate->waiting = FALSE;
+ cpustate->watchdog = 0;
+}
+
+
+
+/***************************************************************************
+ CORE EXECUTION LOOP
+***************************************************************************/
+
+static CPU_EXECUTE( ccpu )
+{
+ ccpu_state *cpustate = get_safe_token(device);
+
+ if (cpustate->waiting)
+ {
+ cpustate->icount = 0;
+ return;
+ }
+
+ do
+ {
+ UINT16 tempval;
+ UINT8 opcode;
+
+ /* update the delayed MI flag */
+ cpustate->miflag = cpustate->nextmiflag;
+ cpustate->nextmiflag = cpustate->nextnextmiflag;
+
+ /* fetch the opcode */
+ debugger_instruction_hook(device, cpustate->PC);
+ opcode = READOP(cpustate, cpustate->PC++);
+
+ switch (opcode)
+ {
+ /* LDAI */
+ case 0x00: case 0x01: case 0x02: case 0x03:
+ case 0x04: case 0x05: case 0x06: case 0x07:
+ case 0x08: case 0x09: case 0x0a: case 0x0b:
+ case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ tempval = (opcode & 0x0f) << 8;
+ STANDARD_ACC_OP(cpustate, tempval, tempval);
+ NEXT_ACC_A(cpustate); CYCLES(cpustate, 1);
+ break;
+
+ /* INP */
+ case 0x10: case 0x11: case 0x12: case 0x13:
+ case 0x14: case 0x15: case 0x16: case 0x17:
+ case 0x18: case 0x19: case 0x1a: case 0x1b:
+ case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ if (cpustate->acc == &cpustate->A)
+ tempval = READPORT(cpustate, opcode & 0x0f) & 1;
+ else
+ tempval = READPORT(cpustate, 16 + (opcode & 0x07)) & 1;
+ STANDARD_ACC_OP(cpustate, tempval, tempval);
+ NEXT_ACC_A(cpustate); CYCLES(cpustate, 1);
+ break;
+
+ /* A8I */
+ case 0x20:
+ tempval = READOP(cpustate, cpustate->PC++);
+ STANDARD_ACC_OP(cpustate, *cpustate->acc + tempval, tempval);
+ NEXT_ACC_A(cpustate); CYCLES(cpustate, 3);
+ break;
+
+ /* A4I */
+ case 0x21: case 0x22: case 0x23:
+ case 0x24: case 0x25: case 0x26: case 0x27:
+ case 0x28: case 0x29: case 0x2a: case 0x2b:
+ case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ tempval = opcode & 0x0f;
+ STANDARD_ACC_OP(cpustate, *cpustate->acc + tempval, tempval);
+ NEXT_ACC_A(cpustate); CYCLES(cpustate, 1);
+ break;
+
+ /* S8I */
+ case 0x30:
+ tempval = READOP(cpustate, cpustate->PC++);
+ STANDARD_ACC_OP(cpustate, *cpustate->acc + (tempval ^ 0xfff) + 1, tempval);
+ NEXT_ACC_A(cpustate); CYCLES(cpustate, 3);
+ break;
+
+ /* S4I */
+ case 0x31: case 0x32: case 0x33:
+ case 0x34: case 0x35: case 0x36: case 0x37:
+ case 0x38: case 0x39: case 0x3a: case 0x3b:
+ case 0x3c: case 0x3d: case 0x3e: case 0x3f:
+ tempval = opcode & 0x0f;
+ STANDARD_ACC_OP(cpustate, *cpustate->acc + (tempval ^ 0xfff) + 1, tempval);
+ NEXT_ACC_A(cpustate); CYCLES(cpustate, 1);
+ break;
+
+ /* LPAI */
+ case 0x40: case 0x41: case 0x42: case 0x43:
+ case 0x44: case 0x45: case 0x46: case 0x47:
+ case 0x48: case 0x49: case 0x4a: case 0x4b:
+ case 0x4c: case 0x4d: case 0x4e: case 0x4f:
+ tempval = READOP(cpustate, cpustate->PC++);
+ cpustate->J = (opcode & 0x0f) + (tempval & 0xf0) + ((tempval & 0x0f) << 8);
+ NEXT_ACC_A(cpustate); CYCLES(cpustate, 3);
+ break;
+
+ /* T4K */
+ case 0x50:
+ cpustate->PC = (cpustate->P << 12) + cpustate->J;
+ NEXT_ACC_B(cpustate); CYCLES(cpustate, 4);
+ break;
+
+ /* JMIB/JEHB */
+ case 0x51:
+ if ((*cpustate->external_input)(device)) { cpustate->PC = ((cpustate->PC - 1) & 0xf000) + cpustate->J; CYCLES(cpustate, 2); }
+ NEXT_ACC_B(cpustate); CYCLES(cpustate, 2);
+ break;
+
+ /* JVNB */
+ case 0x52:
+ if (TEST_DR(cpustate)) { cpustate->PC = ((cpustate->PC - 1) & 0xf000) + cpustate->J; CYCLES(cpustate, 2); }
+ NEXT_ACC_B(cpustate); CYCLES(cpustate, 2);
+ break;
+
+ /* JLTB */
+ case 0x53:
+ if (TEST_LT(cpustate)) { cpustate->PC = ((cpustate->PC - 1) & 0xf000) + cpustate->J; CYCLES(cpustate, 2); }
+ NEXT_ACC_B(cpustate); CYCLES(cpustate, 2);
+ break;
+
+ /* JEQB */
+ case 0x54:
+ if (TEST_EQ(cpustate)) { cpustate->PC = ((cpustate->PC - 1) & 0xf000) + cpustate->J; CYCLES(cpustate, 2); }
+ NEXT_ACC_B(cpustate); CYCLES(cpustate, 2);
+ break;
+
+ /* JCZB */
+ case 0x55:
+ if (TEST_NC(cpustate)) { cpustate->PC = ((cpustate->PC - 1) & 0xf000) + cpustate->J; CYCLES(cpustate, 2); }
+ NEXT_ACC_B(cpustate); CYCLES(cpustate, 2);
+ break;
+
+ /* JOSB */
+ case 0x56:
+ if (TEST_A0(cpustate)) { cpustate->PC = ((cpustate->PC - 1) & 0xf000) + cpustate->J; CYCLES(cpustate, 2); }
+ NEXT_ACC_B(cpustate); CYCLES(cpustate, 2);
+ break;
+
+ /* SSA */
+ case 0x57:
+ NEXT_ACC_B(cpustate); CYCLES(cpustate, 2);
+ break;
+
+ /* JMP */
+ case 0x58:
+ cpustate->PC = ((cpustate->PC - 1) & 0xf000) + cpustate->J;
+ NEXT_ACC_A(cpustate); CYCLES(cpustate, 4);
+ break;
+
+ /* JMI/JEH */
+ case 0x59:
+ if ((*cpustate->external_input)(device)) { cpustate->PC = ((cpustate->PC - 1) & 0xf000) + cpustate->J; CYCLES(cpustate, 2); }
+ NEXT_ACC_A(cpustate); CYCLES(cpustate, 2);
+ break;
+
+ /* JVN */
+ case 0x5a:
+ if (TEST_DR(cpustate)) { cpustate->PC = ((cpustate->PC - 1) & 0xf000) + cpustate->J; CYCLES(cpustate, 2); }
+ NEXT_ACC_A(cpustate); CYCLES(cpustate, 2);
+ break;
+
+ /* JLT */
+ case 0x5b:
+ if (TEST_LT(cpustate)) { cpustate->PC = ((cpustate->PC - 1) & 0xf000) + cpustate->J; CYCLES(cpustate, 2); }
+ NEXT_ACC_A(cpustate); CYCLES(cpustate, 2);
+ break;
+
+ /* JEQ */
+ case 0x5c:
+ if (TEST_EQ(cpustate)) { cpustate->PC = ((cpustate->PC - 1) & 0xf000) + cpustate->J; CYCLES(cpustate, 2); }
+ NEXT_ACC_A(cpustate); CYCLES(cpustate, 2);
+ break;
+
+ /* JCZ */
+ case 0x5d:
+ if (TEST_NC(cpustate)) { cpustate->PC = ((cpustate->PC - 1) & 0xf000) + cpustate->J; CYCLES(cpustate, 2); }
+ NEXT_ACC_A(cpustate); CYCLES(cpustate, 2);
+ break;
+
+ /* JOS */
+ case 0x5e:
+ if (TEST_A0(cpustate)) { cpustate->PC = ((cpustate->PC - 1) & 0xf000) + cpustate->J; CYCLES(cpustate, 2); }
+ NEXT_ACC_A(cpustate); CYCLES(cpustate, 2);
+ break;
+
+ /* NOP */
+ case 0x5f:
+ NEXT_ACC_A(cpustate); CYCLES(cpustate, 2);
+ break;
+
+ /* ADD */
+ case 0x60: case 0x61: case 0x62: case 0x63:
+ case 0x64: case 0x65: case 0x66: case 0x67:
+ case 0x68: case 0x69: case 0x6a: case 0x6b:
+ case 0x6c: case 0x6d: case 0x6e: case 0x6f:
+ cpustate->I = (cpustate->P << 4) + (opcode & 0x0f);
+ tempval = RDMEM(cpustate, cpustate->I);
+ STANDARD_ACC_OP(cpustate, *cpustate->acc + tempval, tempval);
+ NEXT_ACC_A(cpustate); CYCLES(cpustate, 3);
+ break;
+
+ /* SUB */
+ case 0x70: case 0x71: case 0x72: case 0x73:
+ case 0x74: case 0x75: case 0x76: case 0x77:
+ case 0x78: case 0x79: case 0x7a: case 0x7b:
+ case 0x7c: case 0x7d: case 0x7e: case 0x7f:
+ cpustate->I = (cpustate->P << 4) + (opcode & 0x0f);
+ tempval = RDMEM(cpustate, cpustate->I);
+ STANDARD_ACC_OP(cpustate, *cpustate->acc + (tempval ^ 0xfff) + 1, tempval);
+ NEXT_ACC_A(cpustate); CYCLES(cpustate, 3);
+ break;
+
+ /* SETP */
+ case 0x80: case 0x81: case 0x82: case 0x83:
+ case 0x84: case 0x85: case 0x86: case 0x87:
+ case 0x88: case 0x89: case 0x8a: case 0x8b:
+ case 0x8c: case 0x8d: case 0x8e: case 0x8f:
+ cpustate->P = opcode & 0x0f;
+ NEXT_ACC_A(cpustate); CYCLES(cpustate, 1);
+ break;
+
+ /* OUT */
+ case 0x90: case 0x91: case 0x92: case 0x93:
+ case 0x94: case 0x95: case 0x96: case 0x97:
+ case 0x98: case 0x99: case 0x9a: case 0x9b:
+ case 0x9c: case 0x9d: case 0x9e: case 0x9f:
+ if (cpustate->acc == &cpustate->A)
+ WRITEPORT(cpustate, opcode & 0x07, ~*cpustate->acc & 1);
+ NEXT_ACC_A(cpustate); CYCLES(cpustate, 1);
+ break;
+
+ /* LDA */
+ case 0xa0: case 0xa1: case 0xa2: case 0xa3:
+ case 0xa4: case 0xa5: case 0xa6: case 0xa7:
+ case 0xa8: case 0xa9: case 0xaa: case 0xab:
+ case 0xac: case 0xad: case 0xae: case 0xaf:
+ cpustate->I = (cpustate->P << 4) + (opcode & 0x0f);
+ tempval = RDMEM(cpustate, cpustate->I);
+ STANDARD_ACC_OP(cpustate, tempval, tempval);
+ NEXT_ACC_A(cpustate); CYCLES(cpustate, 3);
+ break;
+
+ /* TST */
+ case 0xb0: case 0xb1: case 0xb2: case 0xb3:
+ case 0xb4: case 0xb5: case 0xb6: case 0xb7:
+ case 0xb8: case 0xb9: case 0xba: case 0xbb:
+ case 0xbc: case 0xbd: case 0xbe: case 0xbf:
+ cpustate->I = (cpustate->P << 4) + (opcode & 0x0f);
+ tempval = RDMEM(cpustate, cpustate->I);
+ {
+ UINT16 result = *cpustate->acc + (tempval ^ 0xfff) + 1;
+ SET_A0(cpustate);
+ SET_CMP_VAL(cpustate, tempval);
+ SET_NC(cpustate, result);
+ SET_MI(cpustate, result);
+ }
+ NEXT_ACC_A(cpustate); CYCLES(cpustate, 3);
+ break;
+
+ /* WS */
+ case 0xc0: case 0xc1: case 0xc2: case 0xc3:
+ case 0xc4: case 0xc5: case 0xc6: case 0xc7:
+ case 0xc8: case 0xc9: case 0xca: case 0xcb:
+ case 0xcc: case 0xcd: case 0xce: case 0xcf:
+ cpustate->I = (cpustate->P << 4) + (opcode & 0x0f);
+ cpustate->I = RDMEM(cpustate, cpustate->I) & 0xff;
+ NEXT_ACC_A(cpustate); CYCLES(cpustate, 3);
+ break;
+
+ /* STA */
+ case 0xd0: case 0xd1: case 0xd2: case 0xd3:
+ case 0xd4: case 0xd5: case 0xd6: case 0xd7:
+ case 0xd8: case 0xd9: case 0xda: case 0xdb:
+ case 0xdc: case 0xdd: case 0xde: case 0xdf:
+ cpustate->I = (cpustate->P << 4) + (opcode & 0x0f);
+ WRMEM(cpustate, cpustate->I, *cpustate->acc);
+ NEXT_ACC_A(cpustate); CYCLES(cpustate, 3);
+ break;
+
+ /* DV */
+ case 0xe0:
+ {
+ INT16 stopX = (INT16)(cpustate->A << 4) >> 4;
+ INT16 stopY = (INT16)(cpustate->B << 4) >> 4;
+
+ stopX = ((INT16)(stopX - cpustate->X) >> cpustate->T) + cpustate->X;
+ stopY = ((INT16)(stopY - cpustate->Y) >> cpustate->T) + cpustate->Y;
+
+ (*cpustate->vector_callback)(device, cpustate->X, cpustate->Y, stopX, stopY, cpustate->T);
+
+ /* hack to make QB3 display semi-correctly during explosions */
+ cpustate->A = cpustate->X & 0xfff;
+ cpustate->B = cpustate->Y & 0xfff;
+ }
+ NEXT_ACC_A(cpustate); CYCLES(cpustate, 1);
+ break;
+
+ /* LPAP */
+ case 0xe1:
+ cpustate->J = RDMEM(cpustate, cpustate->I);
+ NEXT_ACC_A(cpustate); CYCLES(cpustate, 3);
+ break;
+
+ /* WSP */
+ case 0xf1:
+ cpustate->I = RDMEM(cpustate, cpustate->I) & 0xff;
+ NEXT_ACC_A(cpustate); CYCLES(cpustate, 3);
+ break;
+
+ /* LKP */
+ case 0xe2:
+ case 0xf2:
+ tempval = READOP(cpustate, ((cpustate->PC - 1) & 0xf000) + *cpustate->acc);
+ STANDARD_ACC_OP(cpustate, tempval, tempval);
+ NEXT_ACC_A(cpustate); CYCLES(cpustate, 7);
+ cpustate->PC++;
+ break;
+
+ /* MUL */
+ case 0xe3:
+ case 0xf3:
+ tempval = RDMEM(cpustate, cpustate->I);
+ SET_A0(cpustate);
+ cpustate->cmpval = tempval & 0xfff;
+ if (cpustate->acc == &cpustate->A)
+ {
+ if (cpustate->A & 1)
+ {
+ UINT16 result;
+ cpustate->cmpacc = cpustate->B;
+ cpustate->A = (cpustate->A >> 1) | ((cpustate->B << 11) & 0x800);
+ cpustate->B = ((INT16)(cpustate->B << 4) >> 5) & 0xfff;
+ result = cpustate->B + tempval;
+ SET_NC(cpustate, result);
+ SET_MI(cpustate, result);
+ cpustate->B = result & 0xfff;
+ }
+ else
+ {
+ UINT16 result;
+ cpustate->cmpacc = cpustate->A;
+ result = cpustate->A + tempval;
+ cpustate->A = (cpustate->A >> 1) | ((cpustate->B << 11) & 0x800);
+ cpustate->B = ((INT16)(cpustate->B << 4) >> 5) & 0xfff;
+ SET_NC(cpustate, result);
+ SET_MI(cpustate, result);
+ }
+ }
+ else
+ {
+ UINT16 result;
+ cpustate->cmpacc = cpustate->B;
+ cpustate->B = ((INT16)(cpustate->B << 4) >> 5) & 0xfff;
+ result = cpustate->B + tempval;
+ SET_NC(cpustate, result);
+ SET_MI(cpustate, result);
+ if (cpustate->A & 1)
+ cpustate->B = result & 0xfff;
+ }
+ NEXT_ACC_A(cpustate); CYCLES(cpustate, 2);
+ break;
+
+ /* NV */
+ case 0xe4:
+ case 0xf4:
+ cpustate->T = 0;
+ while (((cpustate->A & 0xa00) == 0x000 || (cpustate->A & 0xa00) == 0xa00) &&
+ ((cpustate->B & 0xa00) == 0x000 || (cpustate->B & 0xa00) == 0xa00) &&
+ cpustate->T < 16)
+ {
+ cpustate->A = (cpustate->A << 1) & 0xfff;
+ cpustate->B = (cpustate->B << 1) & 0xfff;
+ cpustate->T++;
+ CYCLES(cpustate, 1);
+ }
+ NEXT_ACC_A(cpustate); CYCLES(cpustate, 1);
+ break;
+
+ /* FRM */
+ case 0xe5:
+ case 0xf5:
+ cpustate->waiting = TRUE;
+ NEXT_ACC_A(cpustate);
+ cpustate->icount = -1;
+
+ /* some games repeat the FRM opcode twice; it apparently does not cause
+ a second wait, so we make sure we skip any duplicate opcode at this
+ point */
+ if (READOP(cpustate, cpustate->PC) == opcode)
+ cpustate->PC++;
+ break;
+
+ /* STAP */
+ case 0xe6:
+ case 0xf6:
+ WRMEM(cpustate, cpustate->I, *cpustate->acc);
+ NEXT_ACC_A(cpustate); CYCLES(cpustate, 2);
+ break;
+
+ /* CST */
+ case 0xf7:
+ cpustate->watchdog = 0;
+ /* ADDP */
+ case 0xe7:
+ tempval = RDMEM(cpustate, cpustate->I);
+ STANDARD_ACC_OP(cpustate, *cpustate->acc + tempval, tempval);
+ NEXT_ACC_A(cpustate); CYCLES(cpustate, 2);
+ break;
+
+ /* SUBP */
+ case 0xe8:
+ case 0xf8:
+ tempval = RDMEM(cpustate, cpustate->I);
+ STANDARD_ACC_OP(cpustate, *cpustate->acc + (tempval ^ 0xfff) + 1, tempval);
+ NEXT_ACC_A(cpustate); CYCLES(cpustate, 3);
+ break;
+
+ /* ANDP */
+ case 0xe9:
+ case 0xf9:
+ tempval = RDMEM(cpustate, cpustate->I);
+ STANDARD_ACC_OP(cpustate, *cpustate->acc & tempval, tempval);
+ NEXT_ACC_A(cpustate); CYCLES(cpustate, 2);
+ break;
+
+ /* LDAP */
+ case 0xea:
+ case 0xfa:
+ tempval = RDMEM(cpustate, cpustate->I);
+ STANDARD_ACC_OP(cpustate, tempval, tempval);
+ NEXT_ACC_A(cpustate); CYCLES(cpustate, 2);
+ break;
+
+ /* SHR */
+ case 0xeb:
+ case 0xfb:
+ tempval = ((cpustate->acc == &cpustate->A) ? (cpustate->A >> 1) : ((INT16)(cpustate->B << 4) >> 5)) & 0xfff;
+ tempval |= (*cpustate->acc + (0xb0b | (opcode & 0xf0))) & 0x1000;
+ STANDARD_ACC_OP(cpustate, tempval, 0xb0b | (opcode & 0xf0));
+ NEXT_ACC_A(cpustate); CYCLES(cpustate, 1);
+ break;
+
+ /* SHL */
+ case 0xec:
+ case 0xfc:
+ tempval = (*cpustate->acc << 1) & 0xfff;
+ tempval |= (*cpustate->acc + (0xc0c | (opcode & 0xf0))) & 0x1000;
+ STANDARD_ACC_OP(cpustate, tempval, 0xc0c | (opcode & 0xf0));
+ NEXT_ACC_A(cpustate); CYCLES(cpustate, 1);
+ break;
+
+ /* ASR */
+ case 0xed:
+ case 0xfd:
+ tempval = ((INT16)(*cpustate->acc << 4) >> 5) & 0xfff;
+ STANDARD_ACC_OP(cpustate, tempval, 0xd0d | (opcode & 0xf0));
+ NEXT_ACC_A(cpustate); CYCLES(cpustate, 1);
+ break;
+
+ /* SHRB */
+ case 0xee:
+ case 0xfe:
+ if (cpustate->acc == &cpustate->A)
+ {
+ tempval = (cpustate->A >> 1) | ((cpustate->B << 11) & 0x800);
+ cpustate->B = ((INT16)(cpustate->B << 4) >> 5) & 0xfff;
+ }
+ else
+ tempval = ((INT16)(cpustate->B << 4) >> 5) & 0xfff;
+ tempval |= (*cpustate->acc + (0xe0e | (opcode & 0xf0))) & 0x1000;
+ STANDARD_ACC_OP(cpustate, tempval, 0xe0e | (opcode & 0xf0));
+ NEXT_ACC_A(cpustate); CYCLES(cpustate, 1);
+ break;
+
+ /* SHLB */
+ case 0xef:
+ case 0xff:
+ if (cpustate->acc == &cpustate->A)
+ {
+ tempval = (cpustate->A << 1) & 0xfff;
+ cpustate->B = (cpustate->B << 1) & 0xfff;
+ }
+ else
+ tempval = (cpustate->B << 1) & 0xfff;
+ tempval |= (*cpustate->acc + (0xf0f | (opcode & 0xf0))) & 0x1000;
+ STANDARD_ACC_OP(cpustate, tempval, 0xf0f | (opcode & 0xf0));
+ NEXT_ACC_A(cpustate); CYCLES(cpustate, 1);
+ break;
+
+ /* IV */
+ case 0xf0:
+ cpustate->X = (INT16)(cpustate->A << 4) >> 4;
+ cpustate->Y = (INT16)(cpustate->B << 4) >> 4;
+ NEXT_ACC_A(cpustate); CYCLES(cpustate, 1);
+ break;
+ }
+ } while (cpustate->icount > 0);
+}
+
+
+
+/***************************************************************************
+ INFORMATION SETTERS
+***************************************************************************/
+
+static CPU_SET_INFO( ccpu )
+{
+ ccpu_state *cpustate = get_safe_token(device);
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + CCPU_PC: cpustate->PC = info->i; break;
+ case CPUINFO_INT_REGISTER + CCPU_FLAGS:
+ cpustate->a0flag = (info->i & 0x01) ? 1 : 0;
+ cpustate->ncflag = (info->i & 0x02) ? 0x0000 : 0x1000;
+ cpustate->cmpacc = 1;
+ cpustate->cmpval = (info->i & 0x04) ? 0 : (info->i & 0x08) ? 1 : 2;
+ cpustate->miflag = (info->i & 0x10) ? 1 : 0;
+ cpustate->drflag = (info->i & 0x20) ? 1 : 0;
+ break;
+ case CPUINFO_INT_REGISTER + CCPU_A: cpustate->A = info->i & 0xfff; break;
+ case CPUINFO_INT_REGISTER + CCPU_B: cpustate->B = info->i & 0xfff; break;
+ case CPUINFO_INT_REGISTER + CCPU_I: cpustate->I = info->i & 0xff; break;
+ case CPUINFO_INT_REGISTER + CCPU_J: cpustate->J = info->i & 0xfff; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + CCPU_P: cpustate->P = info->i & 0x0f; break;
+ case CPUINFO_INT_REGISTER + CCPU_X: cpustate->X = info->i & 0xfff; break;
+ case CPUINFO_INT_REGISTER + CCPU_Y: cpustate->Y = info->i & 0xfff; break;
+ case CPUINFO_INT_REGISTER + CCPU_T: cpustate->T = info->i & 0xfff; break;
+ }
+}
+
+
+
+/***************************************************************************
+ INFORMATION GETTERS
+***************************************************************************/
+
+CPU_GET_INFO( ccpu )
+{
+ ccpu_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(ccpu_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 0; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 3; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 1; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 15; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = -1; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 5; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_PREVIOUSPC: /* not implemented */ break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + CCPU_PC: info->i = cpustate->PC; break;
+ case CPUINFO_INT_REGISTER + CCPU_FLAGS: info->i = 0;
+ if (TEST_A0(cpustate)) info->i |= 0x01;
+ if (TEST_NC(cpustate)) info->i |= 0x02;
+ if (TEST_LT(cpustate)) info->i |= 0x04;
+ if (TEST_EQ(cpustate)) info->i |= 0x08;
+ if ((*cpustate->external_input)(cpustate->device)) info->i |= 0x10;
+ if (TEST_DR(cpustate)) info->i |= 0x20;
+ break;
+ case CPUINFO_INT_REGISTER + CCPU_A: info->i = cpustate->A; break;
+ case CPUINFO_INT_REGISTER + CCPU_B: info->i = cpustate->B; break;
+ case CPUINFO_INT_REGISTER + CCPU_I: info->i = cpustate->I; break;
+ case CPUINFO_INT_REGISTER + CCPU_J: info->i = cpustate->J; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + CCPU_P: info->i = cpustate->P; break;
+ case CPUINFO_INT_REGISTER + CCPU_X: info->i = cpustate->X; break;
+ case CPUINFO_INT_REGISTER + CCPU_Y: info->i = cpustate->Y; break;
+ case CPUINFO_INT_REGISTER + CCPU_T: info->i = cpustate->T; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(ccpu); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(ccpu); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(ccpu); break;
+ case CPUINFO_FCT_EXIT: info->exit = NULL; break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(ccpu); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(ccpu); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "CCPU"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Cinematronics CPU"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Aaron Giles & Zonn Moore"); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c%c%c%c%c",
+ TEST_A0(cpustate) ? '0' : 'o',
+ TEST_NC(cpustate) ? 'N' : 'n',
+ TEST_LT(cpustate) ? 'L' : 'l',
+ TEST_EQ(cpustate) ? 'E' : 'e',
+ (*cpustate->external_input)(cpustate->device) ? 'M' : 'm',
+ TEST_DR(cpustate) ? 'D' : 'd');
+ break;
+
+ case CPUINFO_STR_REGISTER + CCPU_FLAGS:
+ sprintf(info->s, "FL:%c%c%c%c%c%c",
+ TEST_A0(cpustate) ? '0' : 'o',
+ TEST_NC(cpustate) ? 'N' : 'n',
+ TEST_LT(cpustate) ? 'L' : 'l',
+ TEST_EQ(cpustate) ? 'E' : 'e',
+ (*cpustate->external_input)(cpustate->device) ? 'M' : 'm',
+ TEST_DR(cpustate) ? 'D' : 'd');
+ break;
+
+ case CPUINFO_STR_REGISTER + CCPU_PC: sprintf(info->s, "PC:%04X", cpustate->PC); break;
+ case CPUINFO_STR_REGISTER + CCPU_A: sprintf(info->s, "A:%03X", cpustate->A); break;
+ case CPUINFO_STR_REGISTER + CCPU_B: sprintf(info->s, "B:%03X", cpustate->B); break;
+ case CPUINFO_STR_REGISTER + CCPU_I: sprintf(info->s, "I:%03X", cpustate->I); break;
+ case CPUINFO_STR_REGISTER + CCPU_J: sprintf(info->s, "J:%03X", cpustate->J); break;
+ case CPUINFO_STR_REGISTER + CCPU_P: sprintf(info->s, "P:%X", cpustate->P); break;
+ case CPUINFO_STR_REGISTER + CCPU_X: sprintf(info->s, "X:%03X", cpustate->X); break;
+ case CPUINFO_STR_REGISTER + CCPU_Y: sprintf(info->s, "Y:%03X", cpustate->Y); break;
+ case CPUINFO_STR_REGISTER + CCPU_T: sprintf(info->s, "T:%03X", cpustate->T); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(CCPU, ccpu);
diff --git a/trunk/src/emu/cpu/ccpu/ccpu.h b/trunk/src/emu/cpu/ccpu/ccpu.h
new file mode 100644
index 00000000000..3f679c08bc3
--- /dev/null
+++ b/trunk/src/emu/cpu/ccpu/ccpu.h
@@ -0,0 +1,63 @@
+/***************************************************************************
+
+ ccpu.h
+ Core implementation for the portable Cinematronics CPU emulator.
+
+ Written by Aaron Giles
+ Special thanks to Zonn Moore for his detailed documentation.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __CCPU_H__
+#define __CCPU_H__
+
+
+/***************************************************************************
+ REGISTER ENUMERATION
+***************************************************************************/
+
+enum
+{
+ CCPU_PC=1,
+ CCPU_FLAGS,
+ CCPU_A,
+ CCPU_B,
+ CCPU_I,
+ CCPU_J,
+ CCPU_P,
+ CCPU_X,
+ CCPU_Y,
+ CCPU_T
+};
+
+
+
+/***************************************************************************
+ CONFIG STRUCTURE
+***************************************************************************/
+
+typedef UINT8 (*ccpu_input_func)(device_t *device);
+typedef void (*ccpu_vector_func)(device_t *device, INT16 sx, INT16 sy, INT16 ex, INT16 ey, UINT8 shift);
+
+typedef struct _ccpu_config ccpu_config;
+struct _ccpu_config
+{
+ ccpu_input_func external_input; /* if NULL, assume JMI jumper is present */
+ ccpu_vector_func vector_callback;
+};
+
+
+
+/***************************************************************************
+ PUBLIC FUNCTIONS
+***************************************************************************/
+
+DECLARE_LEGACY_CPU_DEVICE(CCPU, ccpu);
+
+void ccpu_wdt_timer_trigger(device_t *device);
+
+CPU_DISASSEMBLE( ccpu );
+
+#endif /* __CCPU_H__ */
diff --git a/trunk/src/emu/cpu/ccpu/ccpudasm.c b/trunk/src/emu/cpu/ccpu/ccpudasm.c
new file mode 100644
index 00000000000..24c1107f55d
--- /dev/null
+++ b/trunk/src/emu/cpu/ccpu/ccpudasm.c
@@ -0,0 +1,328 @@
+/***************************************************************************
+
+ ccpudasm.c
+ Core implementation for the portable Cinematronics CPU disassembler.
+
+ Written by Aaron Giles
+ Special thanks to Zonn Moore for his detailed documentation.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "ccpu.h"
+
+
+CPU_DISASSEMBLE( ccpu )
+{
+ unsigned startpc = pc;
+ UINT8 opcode = oprom[pc++ - startpc];
+ UINT8 tempval;
+
+ switch (opcode)
+ {
+ /* LDAI */
+ case 0x00: case 0x01: case 0x02: case 0x03:
+ case 0x04: case 0x05: case 0x06: case 0x07:
+ case 0x08: case 0x09: case 0x0a: case 0x0b:
+ case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ sprintf(buffer, "LDAI $%X", opcode & 0x0f);
+ break;
+
+ /* INP */
+ case 0x10: case 0x11: case 0x12: case 0x13:
+ case 0x14: case 0x15: case 0x16: case 0x17:
+ case 0x18: case 0x19: case 0x1a: case 0x1b:
+ case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ sprintf(buffer, "INP $%X", opcode & 0x0f);
+ break;
+
+ /* A8I */
+ case 0x20:
+ sprintf(buffer, "A8I $%X", oprom[pc++ - startpc]);
+ break;
+
+ /* A4I */
+ case 0x21: case 0x22: case 0x23:
+ case 0x24: case 0x25: case 0x26: case 0x27:
+ case 0x28: case 0x29: case 0x2a: case 0x2b:
+ case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ sprintf(buffer, "A4I $%X", opcode & 0x0f);
+ break;
+
+ /* S8I */
+ case 0x30:
+ sprintf(buffer, "S8I $%X", oprom[pc++ - startpc]);
+ break;
+
+ /* S4I */
+ case 0x31: case 0x32: case 0x33:
+ case 0x34: case 0x35: case 0x36: case 0x37:
+ case 0x38: case 0x39: case 0x3a: case 0x3b:
+ case 0x3c: case 0x3d: case 0x3e: case 0x3f:
+ sprintf(buffer, "S4I $%X", opcode & 0x0f);
+ break;
+
+ /* LPAI */
+ case 0x40: case 0x41: case 0x42: case 0x43:
+ case 0x44: case 0x45: case 0x46: case 0x47:
+ case 0x48: case 0x49: case 0x4a: case 0x4b:
+ case 0x4c: case 0x4d: case 0x4e: case 0x4f:
+ tempval = oprom[pc++ - startpc];
+ sprintf(buffer, "LPAI $%03X", (opcode & 0x0f) + (tempval & 0xf0) + ((tempval & 0x0f) << 8));
+ break;
+
+ /* T4K */
+ case 0x50:
+ sprintf(buffer, "T4K");
+ break;
+
+ /* JMIB/JEHB */
+ case 0x51:
+ sprintf(buffer, "JMIB/JEHB");
+ break;
+
+ /* JVNB */
+ case 0x52:
+ sprintf(buffer, "JVNB");
+ break;
+
+ /* JLTB */
+ case 0x53:
+ sprintf(buffer, "JLTB");
+ break;
+
+ /* JEQB */
+ case 0x54:
+ sprintf(buffer, "JEQB");
+ break;
+
+ /* JCZB */
+ case 0x55:
+ sprintf(buffer, "JCZB");
+ break;
+
+ /* JOSB */
+ case 0x56:
+ sprintf(buffer, "JOSB");
+ break;
+
+ /* SSA */
+ case 0x57:
+ sprintf(buffer, "SSA");
+ break;
+
+ /* JMP */
+ case 0x58:
+ sprintf(buffer, "JMP");
+ break;
+
+ /* JMI/JEH */
+ case 0x59:
+ sprintf(buffer, "JMI/JEH");
+ break;
+
+ /* JVN */
+ case 0x5a:
+ sprintf(buffer, "JVN");
+ break;
+
+ /* JLT */
+ case 0x5b:
+ sprintf(buffer, "JLT");
+ break;
+
+ /* JEQ */
+ case 0x5c:
+ sprintf(buffer, "JEQ");
+ break;
+
+ /* JCZ */
+ case 0x5d:
+ sprintf(buffer, "JCZ");
+ break;
+
+ /* JOS */
+ case 0x5e:
+ sprintf(buffer, "JOS");
+ break;
+
+ /* NOP */
+ case 0x5f:
+ sprintf(buffer, "NOP");
+ break;
+
+ /* ADD */
+ case 0x60: case 0x61: case 0x62: case 0x63:
+ case 0x64: case 0x65: case 0x66: case 0x67:
+ case 0x68: case 0x69: case 0x6a: case 0x6b:
+ case 0x6c: case 0x6d: case 0x6e: case 0x6f:
+ sprintf(buffer, "ADD $%X", opcode & 0x0f);
+ break;
+
+ /* SUB n */
+ case 0x70: case 0x71: case 0x72: case 0x73:
+ case 0x74: case 0x75: case 0x76: case 0x77:
+ case 0x78: case 0x79: case 0x7a: case 0x7b:
+ case 0x7c: case 0x7d: case 0x7e: case 0x7f:
+ sprintf(buffer, "SUB $%X", opcode & 0x0f);
+ break;
+
+ /* SETP n */
+ case 0x80: case 0x81: case 0x82: case 0x83:
+ case 0x84: case 0x85: case 0x86: case 0x87:
+ case 0x88: case 0x89: case 0x8a: case 0x8b:
+ case 0x8c: case 0x8d: case 0x8e: case 0x8f:
+ sprintf(buffer, "SETP $%X", opcode & 0x0f);
+ break;
+
+ /* OUT */
+ case 0x90: case 0x91: case 0x92: case 0x93:
+ case 0x94: case 0x95: case 0x96: case 0x97:
+ case 0x98: case 0x99: case 0x9a: case 0x9b:
+ case 0x9c: case 0x9d: case 0x9e: case 0x9f:
+ sprintf(buffer, "OUT $%X", opcode & 0x0f);
+ break;
+
+ /* LDA */
+ case 0xa0: case 0xa1: case 0xa2: case 0xa3:
+ case 0xa4: case 0xa5: case 0xa6: case 0xa7:
+ case 0xa8: case 0xa9: case 0xaa: case 0xab:
+ case 0xac: case 0xad: case 0xae: case 0xaf:
+ sprintf(buffer, "LDA $%X", opcode & 0x0f);
+ break;
+
+ /* CMP */
+ case 0xb0: case 0xb1: case 0xb2: case 0xb3:
+ case 0xb4: case 0xb5: case 0xb6: case 0xb7:
+ case 0xb8: case 0xb9: case 0xba: case 0xbb:
+ case 0xbc: case 0xbd: case 0xbe: case 0xbf:
+ sprintf(buffer, "TST $%X", opcode & 0x0f);
+ break;
+
+ /* WS */
+ case 0xc0: case 0xc1: case 0xc2: case 0xc3:
+ case 0xc4: case 0xc5: case 0xc6: case 0xc7:
+ case 0xc8: case 0xc9: case 0xca: case 0xcb:
+ case 0xcc: case 0xcd: case 0xce: case 0xcf:
+ sprintf(buffer, "WS $%X", opcode & 0x0f);
+ break;
+
+ /* STA n */
+ case 0xd0: case 0xd1: case 0xd2: case 0xd3:
+ case 0xd4: case 0xd5: case 0xd6: case 0xd7:
+ case 0xd8: case 0xd9: case 0xda: case 0xdb:
+ case 0xdc: case 0xdd: case 0xde: case 0xdf:
+ sprintf(buffer, "STA $%X", opcode & 0x0f);
+ break;
+
+ /* DV */
+ case 0xe0:
+ sprintf(buffer, "DV");
+ break;
+
+ /* LPAP */
+ case 0xe1:
+ sprintf(buffer, "LPAP");
+ break;
+
+ /* WSP */
+ case 0xf1:
+ sprintf(buffer, "WSP");
+ break;
+
+ /* LKP */
+ case 0xe2:
+ case 0xf2:
+ sprintf(buffer, "LKP");
+ break;
+
+ /* MUL */
+ case 0xe3:
+ case 0xf3:
+ sprintf(buffer, "MUL");
+ break;
+
+ /* NV */
+ case 0xe4:
+ case 0xf4:
+ sprintf(buffer, "NV");
+ break;
+
+ /* FRM */
+ case 0xe5:
+ case 0xf5:
+ sprintf(buffer, "FRM");
+ break;
+
+ /* STAP */
+ case 0xe6:
+ case 0xf6:
+ sprintf(buffer, "STAP");
+ break;
+
+ /* CST */
+ case 0xf7:
+ sprintf(buffer, "CST");
+ break;
+
+ /* ADDP */
+ case 0xe7:
+ sprintf(buffer, "ADDP");
+ break;
+
+ /* SUBP */
+ case 0xe8:
+ case 0xf8:
+ sprintf(buffer, "SUBP");
+ break;
+
+ /* ANDP */
+ case 0xe9:
+ case 0xf9:
+ sprintf(buffer, "ANDP");
+ break;
+
+ /* LDAP */
+ case 0xea:
+ case 0xfa:
+ sprintf(buffer, "LDAP");
+ break;
+
+ /* SHR */
+ case 0xeb:
+ case 0xfb:
+ sprintf(buffer, "SHR");
+ break;
+
+ /* SHL */
+ case 0xec:
+ case 0xfc:
+ sprintf(buffer, "SHL");
+ break;
+
+ /* ASR */
+ case 0xed:
+ case 0xfd:
+ sprintf(buffer, "ASR");
+ break;
+
+ /* SHRB */
+ case 0xee:
+ case 0xfe:
+ sprintf(buffer, "SHRB");
+ break;
+
+ /* SHLB */
+ case 0xef:
+ case 0xff:
+ sprintf(buffer, "SHLB");
+ break;
+
+ /* IV */
+ case 0xf0:
+ sprintf(buffer, "IV");
+ break;
+ }
+
+ return (pc - startpc) | DASMFLAG_SUPPORTED;
+}
diff --git a/trunk/src/emu/cpu/cop400/cop400.c b/trunk/src/emu/cpu/cop400/cop400.c
new file mode 100644
index 00000000000..f629e7913bd
--- /dev/null
+++ b/trunk/src/emu/cpu/cop400/cop400.c
@@ -0,0 +1,1709 @@
+/***************************************************************************
+
+ cop400.c
+
+ National Semiconductor COP400 Emulator.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+****************************************************************************
+
+ Type ROM RAM G D IN
+
+ COP410 512x8 32x4 none
+ COP411 512x8 32x4 0-2 0-1 none
+ COP401 none 32x4 none
+ COP413?
+ COP414?
+ COP415?
+ COP405?
+
+ COP420 1024x8 64x4
+ COP421 1024x8 64x4 none
+ COP422 1024x8 64x4 2-3 2-3 none
+ COP402 none 64x4
+
+ COP444 2048x8 128x4
+ COP445 2048x8 128x4 none
+ COP424 1024x8 64x4
+ COP425 1024x8 64x4 none
+ COP426 1024x8 64x4 2-3 2-3
+ COP404 none none
+
+ COP440 2048x8 160x4
+ COP441 2048x8 160x4
+ COP442 2048x8 160x4
+
+****************************************************************************
+
+ Prefix Temperature Range
+
+ COP4xx 0C ... 70C
+ COP3xx -40C ... +85C
+ COP2xx -55C ... +125C
+
+***************************************************************************/
+
+/*
+
+ TODO:
+
+ - remove LBIOps
+ - remove InstLen
+ - run interrupt test suite
+ - run production test suite
+ - run microbus test suite
+ - when is the microbus int cleared?
+ - opcode support for 2048x8 and 128x4/160x4 memory sizes
+ - CKO sync input
+ - save internal RAM when CKO is RAM power supply pin
+ - COP413/COP414/COP415/COP405
+ - COP404 opcode map switching, dual timer, microbus enable
+ - COP440/COP441/COP442 (new registers: 2-bit N, 4-bit H, 8-bit R; some new opcodes, 2Kx8 ROM, 160x4 RAM)
+
+*/
+
+#include "emu.h"
+#include "debugger.h"
+#include "cop400.h"
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+/* feature masks */
+#define COP410_FEATURE 0x01
+#define COP420_FEATURE 0x02
+#define COP444_FEATURE 0x04
+#define COP440_FEATURE 0x08
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _cop400_opcode_map cop400_opcode_map;
+
+typedef struct _cop400_state cop400_state;
+struct _cop400_state
+{
+ const cop400_interface *intf;
+
+ address_space *program;
+ direct_read_data *direct;
+ address_space *data;
+ address_space *io;
+
+ UINT8 featuremask;
+
+ /* registers */
+ UINT16 pc; /* 9/10/11-bit ROM address program counter */
+ UINT16 prevpc; /* previous value of program counter */
+ UINT8 a; /* 4-bit accumulator */
+ UINT8 b; /* 5/6/7-bit RAM address register */
+ int c; /* 1-bit carry register */
+ UINT8 n; /* 2-bit stack pointer (COP440 only) */
+ UINT8 en; /* 4-bit enable register */
+ UINT8 g; /* 4-bit general purpose I/O port */
+ UINT8 q; /* 8-bit latch for L port */
+ UINT16 sa, sb, sc; /* subroutine save registers (not present in COP440) */
+ UINT8 sio; /* 4-bit shift register and counter */
+ int skl; /* 1-bit latch for SK output */
+ UINT8 h; /* 4-bit general purpose I/O port (COP440 only) */
+ UINT8 r; /* 8-bit general purpose I/O port (COP440 only) */
+ UINT8 flags; // used for I/O only
+
+ /* counter */
+ UINT8 t; /* 8-bit timer */
+ int skt_latch; /* timer overflow latch */
+
+ /* input/output ports */
+ UINT8 g_mask; /* G port mask */
+ UINT8 d_mask; /* D port mask */
+ UINT8 in_mask; /* IN port mask */
+ UINT8 il; /* IN latch */
+ UINT8 in[4]; /* IN port shift register */
+ UINT8 si; /* serial input */
+
+ /* skipping logic */
+ int skip; /* skip next instruction */
+ int skip_lbi; /* skip until next non-LBI instruction */
+ int last_skip; /* last value of skip */
+ int halt; /* halt mode */
+ int idle; /* idle mode */
+
+ /* microbus */
+ int microbus_int; /* microbus interrupt */
+
+ /* execution logic */
+ int InstLen[256]; /* instruction length in bytes */
+ int LBIops[256];
+ int LBIops33[256];
+ int icount; /* instruction counter */
+
+ const cop400_opcode_map *opcode_map;
+
+ /* timers */
+ emu_timer *serial_timer;
+ emu_timer *counter_timer;
+ emu_timer *inil_timer;
+ emu_timer *microbus_timer;
+};
+
+typedef void (*cop400_opcode_func) (cop400_state *cpustate, UINT8 opcode);
+
+struct _cop400_opcode_map {
+ unsigned cycles;
+ cop400_opcode_func function;
+};
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+#define ROM(a) cpustate->direct->read_decrypted_byte(a)
+#define RAM_R(a) cpustate->data->read_byte(a)
+#define RAM_W(a, v) cpustate->data->write_byte(a, v)
+#define IN(a) cpustate->io->read_byte(a)
+#define OUT(a, v) cpustate->io->write_byte(a, v)
+
+#define IN_G() (IN(COP400_PORT_G) & cpustate->g_mask)
+#define IN_L() IN(COP400_PORT_L)
+#define IN_SI() BIT(IN(COP400_PORT_SIO), 0)
+#define IN_CKO() BIT(IN(COP400_PORT_CKO), 0)
+#define IN_IN() (cpustate->in_mask ? IN(COP400_PORT_IN) : 0)
+
+#define OUT_G(v) OUT(COP400_PORT_G, (v) & cpustate->g_mask)
+#define OUT_L(v) OUT(COP400_PORT_L, (v))
+#define OUT_D(v) OUT(COP400_PORT_D, (v) & cpustate->d_mask)
+#define OUT_SK(v) OUT(COP400_PORT_SK, (v))
+#define OUT_SO(v) OUT(COP400_PORT_SIO, (v))
+
+#define PC cpustate->pc
+#define A cpustate->a
+#define B cpustate->b
+#define C cpustate->c
+#define G cpustate->g
+#define Q cpustate->q
+#define H cpustate->h
+#define R cpustate->r
+#define EN cpustate->en
+#define SA cpustate->sa
+#define SB cpustate->sb
+#define SC cpustate->sc
+#define SIO cpustate->sio
+#define SKL cpustate->skl
+#define T cpustate->t
+#define IL cpustate->il
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+INLINE cop400_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == COP401 ||
+ device->type() == COP410 ||
+ device->type() == COP411 ||
+ device->type() == COP402 ||
+ device->type() == COP420 ||
+ device->type() == COP421 ||
+ device->type() == COP422 ||
+ device->type() == COP404 ||
+ device->type() == COP424 ||
+ device->type() == COP425 ||
+ device->type() == COP426 ||
+ device->type() == COP444 ||
+ device->type() == COP445);
+ return (cop400_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+INLINE void PUSH(cop400_state *cpustate, UINT16 data)
+{
+ if (cpustate->featuremask != COP410_FEATURE)
+ {
+ SC = SB;
+ }
+
+ SB = SA;
+ SA = data;
+}
+
+INLINE void POP(cop400_state *cpustate)
+{
+ PC = SA;
+ SA = SB;
+
+ if (cpustate->featuremask != COP410_FEATURE)
+ {
+ SB = SC;
+ }
+}
+
+INLINE void WRITE_Q(cop400_state *cpustate, UINT8 data)
+{
+ Q = data;
+
+ if (BIT(EN, 2))
+ {
+ OUT_L(Q);
+ }
+}
+
+INLINE void WRITE_G(cop400_state *cpustate, UINT8 data)
+{
+ if (cpustate->intf->microbus == COP400_MICROBUS_ENABLED)
+ {
+ data = (data & 0x0e) | cpustate->microbus_int;
+ }
+
+ G = data;
+
+ OUT_G(G);
+}
+
+/***************************************************************************
+ OPCODE HANDLERS
+***************************************************************************/
+
+#define INSTRUCTION(mnemonic) INLINE void (mnemonic)(cop400_state *cpustate, UINT8 opcode)
+
+INSTRUCTION(illegal)
+{
+ logerror("COP400: PC = %04x, Illegal opcode = %02x\n", PC-1, ROM(PC-1));
+}
+
+#include "cop400op.c"
+
+/***************************************************************************
+ OPCODE TABLES
+***************************************************************************/
+
+static const cop400_opcode_map COP410_OPCODE_23_MAP[] =
+{
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, xad },
+
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }
+};
+
+static void cop410_op23(cop400_state *cpustate, UINT8 opcode)
+{
+ UINT8 opcode23 = ROM(PC++);
+
+ (*(COP410_OPCODE_23_MAP[opcode23].function))(cpustate, opcode23);
+}
+
+static const cop400_opcode_map COP410_OPCODE_33_MAP[] =
+{
+ {1, illegal },{1, skgbz0 },{1, illegal },{1, skgbz2 },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, skgbz1 },{1, illegal },{1, skgbz3 },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, skgz },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, ing },{1, illegal },{1, illegal },{1, illegal },{1, inl },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, halt },{1, illegal },{1, omg },{1, illegal },{1, camq },{1, illegal },{1, obd },{1, illegal },
+
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, lei },{1, lei },{1, lei },{1, lei },{1, lei },{1, lei },{1, lei },{1, lei },
+ {1, lei },{1, lei },{1, lei },{1, lei },{1, lei },{1, lei },{1, lei },{1, lei },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }
+};
+
+static void cop410_op33(cop400_state *cpustate, UINT8 opcode)
+{
+ UINT8 opcode33 = ROM(PC++);
+
+ (*(COP410_OPCODE_33_MAP[opcode33].function))(cpustate, opcode33);
+}
+
+static const cop400_opcode_map COP410_OPCODE_MAP[] =
+{
+ {1, clra },{1, skmbz0 },{1, xor_ },{1, skmbz2 },{1, xis },{1, ld },{1, x },{1, xds },
+ {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },
+ {0, illegal },{1, skmbz1 },{0, illegal },{1, skmbz3 },{1, xis },{1, ld },{1, x },{1, xds },
+ {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },
+ {1, skc },{1, ske },{1, sc },{1, cop410_op23 },{1, xis },{1, ld },{1, x },{1, xds },
+ {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },
+ {1, asc },{1, add },{1, rc },{1, cop410_op33 },{1, xis },{1, ld },{1, x },{1, xds },
+ {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },
+
+ {1, comp },{0, illegal },{1, rmb2 },{1, rmb3 },{1, nop },{1, rmb1 },{1, smb2 },{1, smb1 },
+ {1, ret },{1, retsk },{0, illegal },{1, smb3 },{1, rmb0 },{1, smb0 },{1, cba },{1, xas },
+ {1, cab },{1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc },
+ {1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc },
+ {2, jmp },{2, jmp },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },
+ {2, jsr },{2, jsr },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },
+ {1, stii },{1, stii },{1, stii },{1, stii },{1, stii },{1, stii },{1, stii },{1, stii },
+ {1, stii },{1, stii },{1, stii },{1, stii },{1, stii },{1, stii },{1, stii },{1, stii },
+
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{2, lqid },
+
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{2, jid }
+};
+
+static const cop400_opcode_map COP420_OPCODE_23_MAP[] =
+{
+ {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },
+ {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },
+ {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },
+ {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },
+ {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },
+ {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },
+ {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },
+ {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },
+
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+
+ {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },
+ {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },
+ {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },
+ {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },
+ {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },
+ {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },
+ {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },
+ {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },
+
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }
+};
+
+static void cop420_op23(cop400_state *cpustate, UINT8 opcode)
+{
+ UINT8 opcode23 = ROM(PC++);
+
+ (*(COP420_OPCODE_23_MAP[opcode23].function))(cpustate, opcode23);
+}
+
+static const cop400_opcode_map COP420_OPCODE_33_MAP[] =
+{
+ {1, illegal },{1, skgbz0 },{1, illegal },{1, skgbz2 },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, skgbz1 },{1, illegal },{1, skgbz3 },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, skgz },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, inin },{1, inil },{1, ing },{1, illegal },{1, cqma },{1, illegal },{1, inl },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, omg },{1, illegal },{1, camq },{1, illegal },{1, obd },{1, illegal },
+
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, ogi },{1, ogi },{1, ogi },{1, ogi },{1, ogi },{1, ogi },{1, ogi },{1, ogi },
+ {1, ogi },{1, ogi },{1, ogi },{1, ogi },{1, ogi },{1, ogi },{1, ogi },{1, ogi },
+ {1, lei },{1, lei },{1, lei },{1, lei },{1, lei },{1, lei },{1, lei },{1, lei },
+ {1, lei },{1, lei },{1, lei },{1, lei },{1, lei },{1, lei },{1, lei },{1, lei },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+
+ {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },
+ {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },
+ {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },
+ {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },
+ {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },
+ {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },
+ {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },
+ {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },
+
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal }
+};
+
+static void cop420_op33(cop400_state *cpustate, UINT8 opcode)
+{
+ UINT8 opcode33 = ROM(PC++);
+
+ (*(COP420_OPCODE_33_MAP[opcode33].function))(cpustate, opcode33);
+}
+
+static const cop400_opcode_map COP420_OPCODE_MAP[] =
+{
+ {1, clra },{1, skmbz0 },{1, xor_ },{1, skmbz2 },{1, xis },{1, ld },{1, x },{1, xds },
+ {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },
+ {1, casc },{1, skmbz1 },{1, xabr },{1, skmbz3 },{1, xis },{1, ld },{1, x },{1, xds },
+ {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },
+ {1, skc },{1, ske },{1, sc },{1, cop420_op23 },{1, xis },{1, ld },{1, x },{1, xds },
+ {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },
+ {1, asc },{1, add },{1, rc },{1, cop420_op33 },{1, xis },{1, ld },{1, x },{1, xds },
+ {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },
+
+ {1, comp },{1, skt },{1, rmb2 },{1, rmb3 },{1, nop },{1, rmb1 },{1, smb2 },{1, smb1 },
+ {1, cop420_ret },{1, retsk },{1, adt },{1, smb3 },{1, rmb0 },{1, smb0 },{1, cba },{1, xas },
+ {1, cab },{1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc },
+ {1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc },
+ {2, jmp },{2, jmp },{2, jmp },{2, jmp },{0, illegal },{0, illegal },{0, illegal },{0, illegal },
+ {2, jsr },{2, jsr },{2, jsr },{2, jsr },{0, illegal },{0, illegal },{0, illegal },{0, illegal },
+ {1, stii },{1, stii },{1, stii },{1, stii },{1, stii },{1, stii },{1, stii },{1, stii },
+ {1, stii },{1, stii },{1, stii },{1, stii },{1, stii },{1, stii },{1, stii },{1, stii },
+
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{2, lqid },
+
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{2, jid }
+};
+
+static const cop400_opcode_map COP444_OPCODE_23_MAP[256] =
+{
+ {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },
+ {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },
+ {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },
+ {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },
+ {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },
+ {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },
+ {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },
+ {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },
+
+ {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },
+ {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },
+ {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },
+ {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },
+ {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },
+ {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },
+ {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },
+ {1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },{1, ldd },
+
+ {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },
+ {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },
+ {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },
+ {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },
+ {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },
+ {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },
+ {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },
+ {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },
+
+ {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },
+ {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },
+ {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },
+ {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },
+ {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },
+ {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },
+ {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },
+ {1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },{1, xad },
+};
+
+static void cop444_op23(cop400_state *cpustate, UINT8 opcode)
+{
+ UINT8 opcode23 = ROM(PC++);
+
+ (*(COP444_OPCODE_23_MAP[opcode23].function))(cpustate, opcode23);
+}
+
+static const cop400_opcode_map COP444_OPCODE_33_MAP[256] =
+{
+ {1, illegal },{1, skgbz0 },{1, illegal },{1, skgbz2 },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, skgbz1 },{1, illegal },{1, skgbz3 },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, skgz },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, inin },{1, inil },{1, ing },{1, illegal },{1, cqma },{1, illegal },{1, inl },{1, ctma },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, it },{1, illegal },{1, omg },{1, illegal },{1, camq },{1, illegal },{1, obd },{1, camt },
+
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, ogi },{1, ogi },{1, ogi },{1, ogi },{1, ogi },{1, ogi },{1, ogi },{1, ogi },
+ {1, ogi },{1, ogi },{1, ogi },{1, ogi },{1, ogi },{1, ogi },{1, ogi },{1, ogi },
+ {1, lei },{1, lei },{1, lei },{1, lei },{1, lei },{1, lei },{1, lei },{1, lei },
+ {1, lei },{1, lei },{1, lei },{1, lei },{1, lei },{1, lei },{1, lei },{1, lei },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+ {1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
+
+ {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },
+ {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },
+ {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },
+ {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },
+ {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },
+ {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },
+ {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },
+ {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },
+
+ {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },
+ {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },
+ {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },
+ {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },
+ {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },
+ {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },
+ {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },
+ {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },
+};
+
+static void cop444_op33(cop400_state *cpustate, UINT8 opcode)
+{
+ UINT8 opcode33 = ROM(PC++);
+
+ (*(COP444_OPCODE_33_MAP[opcode33].function))(cpustate, opcode33);
+}
+
+static const cop400_opcode_map COP444_OPCODE_MAP[256] =
+{
+ {1, clra },{1, skmbz0 },{1, xor_ },{1, skmbz2 },{1, xis },{1, ld },{1, x },{1, xds },
+ {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },
+ {1, casc },{1, skmbz1 },{1, cop444_xabr},{1, skmbz3 },{1, xis },{1, ld },{1, x },{1, xds },
+ {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },
+ {1, skc },{1, ske },{1, sc },{1, cop444_op23 },{1, xis },{1, ld },{1, x },{1, xds },
+ {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },
+ {1, asc },{1, add },{1, rc },{1, cop444_op33 },{1, xis },{1, ld },{1, x },{1, xds },
+ {1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },{1, lbi },
+
+ {1, comp },{1, skt },{1, rmb2 },{1, rmb3 },{1, nop },{1, rmb1 },{1, smb2 },{1, smb1 },
+ {1, cop420_ret },{1, retsk },{1, adt },{1, smb3 },{1, rmb0 },{1, smb0 },{1, cba },{1, xas },
+ {1, cab },{1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc },
+ {1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc },{1, aisc },
+ {2, jmp },{2, jmp },{2, jmp },{2, jmp },{2, jmp },{2, jmp },{2, jmp },{2, jmp },
+ {2, jsr },{2, jsr },{2, jsr },{2, jsr },{2, jsr },{2, jsr },{2, jsr },{2, jsr },
+ {1, stii },{1, stii },{1, stii },{1, stii },{1, stii },{1, stii },{1, stii },{1, stii },
+ {1, stii },{1, stii },{1, stii },{1, stii },{1, stii },{1, stii },{1, stii },{1, stii },
+
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{2, lqid },
+
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },
+ {1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{1, jp },{2, jid }
+};
+
+/***************************************************************************
+ TIMER CALLBACKS
+***************************************************************************/
+
+static TIMER_CALLBACK( serial_tick )
+{
+ cop400_state *cpustate = (cop400_state *)ptr;
+
+ if (BIT(EN, 0))
+ {
+ /*
+
+ SIO is an asynchronous binary counter decrementing its value by one upon each low-going pulse ("1" to "0") occurring on the SI input.
+ Each pulse must remain at each logic level at least two instruction cycles. SK outputs the value of the C upon the execution of an XAS
+ and remains latched until the execution of another XAS instruction. The SO output is equal to the value of EN3.
+
+ */
+
+ // serial output
+
+ OUT_SO(BIT(EN, 3));
+
+ // serial clock
+
+ OUT_SK(SKL);
+
+ // serial input
+
+ cpustate->si <<= 1;
+ cpustate->si = (cpustate->si & 0x0e) | IN_SI();
+
+ if ((cpustate->si & 0x0f) == 0x0c) // 1100
+ {
+ SIO--;
+ SIO &= 0x0f;
+ }
+ }
+ else
+ {
+ /*
+
+ SIO is a serial shift register, shifting continuously left each instruction cycle time. The data present at SI goes into the least
+ significant bit of SIO: SO can be enabled to output the most significant bit of SIO each cycle time. SK output becomes a logic-
+ controlled clock, providing a SYNC signal each instruction time. It will start outputting a SYNC pulse upon the execution of an XAS
+ instruction with C = "1," stopping upon the execution of a subsequent XAS with C = "0".
+
+ If EN0 is changed from "1" to "0" ("0" to "1") the SK output will change from "1" to SYNC (SYNC to "1") without the execution of
+ an XAS instruction.
+
+ */
+
+ // serial output
+
+ if (BIT(EN, 3))
+ {
+ OUT_SO(BIT(SIO, 3));
+ }
+ else
+ {
+ OUT_SO(0);
+ }
+
+ // serial clock
+
+ if (SKL)
+ {
+ OUT_SK(1); // SYNC
+ }
+ else
+ {
+ OUT_SK(0);
+ }
+
+ // serial input
+
+ SIO = ((SIO << 1) | IN_SI()) & 0x0f;
+ }
+}
+
+static TIMER_CALLBACK( counter_tick )
+{
+ cop400_state *cpustate = (cop400_state *)ptr;
+
+ T++;
+
+ if (T == 0)
+ {
+ cpustate->skt_latch = 1;
+
+ if (cpustate->idle)
+ {
+ cpustate->idle = 0;
+ cpustate->halt = 0;
+ }
+ }
+}
+
+static TIMER_CALLBACK( inil_tick )
+{
+ cop400_state *cpustate = (cop400_state *)ptr;
+ UINT8 in;
+ int i;
+
+ in = IN_IN();
+
+ for (i = 0; i < 4; i++)
+ {
+ cpustate->in[i] = (cpustate->in[i] << 1) | BIT(in, i);
+
+ if ((cpustate->in[i] & 0x07) == 0x04) // 100
+ {
+ IL |= (1 << i);
+ }
+ }
+}
+
+static TIMER_CALLBACK( microbus_tick )
+{
+ cop400_state *cpustate = (cop400_state *)ptr;
+ UINT8 in;
+
+ in = IN_IN();
+
+ if (!BIT(in, 2))
+ {
+ // chip select
+
+ if (!BIT(in, 1))
+ {
+ // read strobe
+
+ OUT_L(Q);
+
+ cpustate->microbus_int = 1;
+ }
+ else if (!BIT(in, 3))
+ {
+ // write strobe
+
+ Q = IN_L();
+
+ cpustate->microbus_int = 0;
+ }
+ }
+}
+
+/***************************************************************************
+ INITIALIZATION
+***************************************************************************/
+
+static void define_state_table(device_t *device)
+{
+ cop400_state *cpustate = get_safe_token(device);
+
+ device_state_interface *state;
+ device->interface(state);
+ state->state_add(STATE_GENPC, "GENPC", cpustate->pc).mask(0xfff).noshow();
+ state->state_add(STATE_GENPCBASE, "GENPCBASE", cpustate->prevpc).mask(0xfff).noshow();
+ state->state_add(STATE_GENSP, "GENSP", cpustate->n).mask(0x3).noshow();
+ state->state_add(STATE_GENFLAGS, "GENFLAGS", cpustate->flags).mask(0x3).callimport().callexport().noshow().formatstr("%2s");
+
+ state->state_add(COP400_PC, "PC", cpustate->pc).mask(0xfff);
+
+ if (cpustate->featuremask & (COP410_FEATURE | COP420_FEATURE | COP444_FEATURE))
+ {
+ state->state_add(COP400_SA, "SA", cpustate->sa).mask(0xfff);
+ state->state_add(COP400_SB, "SB", cpustate->sb).mask(0xfff);
+ if (cpustate->featuremask & (COP420_FEATURE | COP444_FEATURE))
+ state->state_add(COP400_SC, "SC", cpustate->sc).mask(0xfff);
+ }
+ if (cpustate->featuremask & COP440_FEATURE)
+ state->state_add(COP400_N, "N", cpustate->n).mask(0x3);
+
+ state->state_add(COP400_A, "A", cpustate->a).mask(0xf);
+ state->state_add(COP400_B, "B", cpustate->b);
+ state->state_add(COP400_C, "C", cpustate->c).mask(0x1);
+
+ state->state_add(COP400_EN, "EN", cpustate->en).mask(0xf);
+ state->state_add(COP400_G, "G", cpustate->g).mask(0xf);
+ if (cpustate->featuremask & COP440_FEATURE)
+ state->state_add(COP400_H, "H", cpustate->h).mask(0xf);
+ state->state_add(COP400_Q, "Q", cpustate->q);
+ if (cpustate->featuremask & COP440_FEATURE)
+ state->state_add(COP400_R, "R", cpustate->r);
+
+ state->state_add(COP400_SIO, "SIO", cpustate->sio).mask(0xf);
+ state->state_add(COP400_SKL, "SKL", cpustate->skl).mask(0x1);
+
+ if (cpustate->featuremask & (COP420_FEATURE | COP444_FEATURE | COP440_FEATURE))
+ state->state_add(COP400_T, "T", cpustate->t);
+}
+
+static void cop400_init(legacy_cpu_device *device, UINT8 g_mask, UINT8 d_mask, UINT8 in_mask, int has_counter, int has_inil)
+{
+ cop400_state *cpustate = get_safe_token(device);
+
+ cpustate->intf = (cop400_interface *) device->static_config();
+
+ /* find address spaces */
+
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+ cpustate->data = device->space(AS_DATA);
+ cpustate->io = device->space(AS_IO);
+
+ /* set output pin masks */
+
+ cpustate->g_mask = g_mask;
+ cpustate->d_mask = d_mask;
+ cpustate->in_mask = in_mask;
+
+ /* allocate serial timer */
+
+ cpustate->serial_timer = device->machine().scheduler().timer_alloc(FUNC(serial_tick), cpustate);
+ cpustate->serial_timer->adjust(attotime::zero, 0, attotime::from_hz(device->clock() / 16));
+
+ /* allocate counter timer */
+
+ if (has_counter)
+ {
+ cpustate->counter_timer = device->machine().scheduler().timer_alloc(FUNC(counter_tick), cpustate);
+ cpustate->counter_timer->adjust(attotime::zero, 0, attotime::from_hz(device->clock() / 16 / 4));
+ }
+
+ /* allocate IN latch timer */
+
+ if (has_inil)
+ {
+ cpustate->inil_timer = device->machine().scheduler().timer_alloc(FUNC(inil_tick), cpustate);
+ cpustate->inil_timer->adjust(attotime::zero, 0, attotime::from_hz(device->clock() / 16));
+ }
+
+ /* allocate Microbus timer */
+
+ if (cpustate->intf->microbus == COP400_MICROBUS_ENABLED)
+ {
+ cpustate->microbus_timer = device->machine().scheduler().timer_alloc(FUNC(microbus_tick), cpustate);
+ cpustate->microbus_timer->adjust(attotime::zero, 0, attotime::from_hz(device->clock() / 16));
+ }
+
+ /* register for state saving */
+
+ device->save_item(NAME(cpustate->pc));
+ device->save_item(NAME(cpustate->prevpc));
+ device->save_item(NAME(cpustate->n));
+ device->save_item(NAME(cpustate->sa));
+ device->save_item(NAME(cpustate->sb));
+ device->save_item(NAME(cpustate->sc));
+ device->save_item(NAME(cpustate->a));
+ device->save_item(NAME(cpustate->b));
+ device->save_item(NAME(cpustate->c));
+ device->save_item(NAME(cpustate->g));
+ device->save_item(NAME(cpustate->h));
+ device->save_item(NAME(cpustate->q));
+ device->save_item(NAME(cpustate->r));
+ device->save_item(NAME(cpustate->en));
+ device->save_item(NAME(cpustate->sio));
+ device->save_item(NAME(cpustate->skl));
+ device->save_item(NAME(cpustate->t));
+ device->save_item(NAME(cpustate->skip));
+ device->save_item(NAME(cpustate->skip_lbi));
+ device->save_item(NAME(cpustate->skt_latch));
+ device->save_item(NAME(cpustate->si));
+ device->save_item(NAME(cpustate->last_skip));
+ device->save_item(NAME(cpustate->in));
+ device->save_item(NAME(cpustate->microbus_int));
+ device->save_item(NAME(cpustate->halt));
+ device->save_item(NAME(cpustate->idle));
+}
+
+static void cop410_init_opcodes(device_t *device)
+{
+ cop400_state *cpustate = get_safe_token(device);
+ int i;
+
+ /* set up the state table */
+
+ cpustate->featuremask = COP410_FEATURE;
+ define_state_table(device);
+
+ /* initialize instruction length array */
+
+ for (i=0; i<256; i++) cpustate->InstLen[i]=1;
+
+ cpustate->InstLen[0x60] = cpustate->InstLen[0x61] = cpustate->InstLen[0x68] =
+ cpustate->InstLen[0x69] = cpustate->InstLen[0x33] = cpustate->InstLen[0x23] = 2;
+
+ /* initialize LBI opcode array */
+
+ for (i=0x00; i<0x100; i++) cpustate->LBIops[i] = 0;
+ for (i=0x08; i<0x10; i++) cpustate->LBIops[i] = 1;
+ for (i=0x18; i<0x20; i++) cpustate->LBIops[i] = 1;
+ for (i=0x28; i<0x30; i++) cpustate->LBIops[i] = 1;
+ for (i=0x38; i<0x40; i++) cpustate->LBIops[i] = 1;
+
+ /* select opcode map */
+
+ cpustate->opcode_map = COP410_OPCODE_MAP;
+}
+
+static void cop420_init_opcodes(device_t *device)
+{
+ cop400_state *cpustate = get_safe_token(device);
+ int i;
+
+ /* set up the state table */
+
+ cpustate->featuremask = COP420_FEATURE;
+ define_state_table(device);
+
+ /* initialize instruction length array */
+
+ for (i=0; i<256; i++) cpustate->InstLen[i]=1;
+
+ cpustate->InstLen[0x60] = cpustate->InstLen[0x61] = cpustate->InstLen[0x62] = cpustate->InstLen[0x63] =
+ cpustate->InstLen[0x68] = cpustate->InstLen[0x69] = cpustate->InstLen[0x6a] = cpustate->InstLen[0x6b] =
+ cpustate->InstLen[0x33] = cpustate->InstLen[0x23] = 2;
+
+ /* initialize LBI opcode array */
+
+ for (i=0x00; i<0x100; i++) cpustate->LBIops[i] = 0;
+ for (i=0x08; i<0x10; i++) cpustate->LBIops[i] = 1;
+ for (i=0x18; i<0x20; i++) cpustate->LBIops[i] = 1;
+ for (i=0x28; i<0x30; i++) cpustate->LBIops[i] = 1;
+ for (i=0x38; i<0x40; i++) cpustate->LBIops[i] = 1;
+
+ for (i=0; i<256; i++) cpustate->LBIops33[i] = 0;
+ for (i=0x80; i<0xc0; i++) cpustate->LBIops33[i] = 1;
+
+ /* select opcode map */
+
+ cpustate->opcode_map = COP420_OPCODE_MAP;
+}
+
+static void cop444_init_opcodes(device_t *device)
+{
+ cop400_state *cpustate = get_safe_token(device);
+ int i;
+
+ /* set up the state table */
+
+ cpustate->featuremask = COP444_FEATURE;
+ define_state_table(device);
+
+ /* initialize instruction length array */
+
+ for (i=0; i<256; i++) cpustate->InstLen[i]=1;
+
+ cpustate->InstLen[0x60] = cpustate->InstLen[0x61] = cpustate->InstLen[0x62] = cpustate->InstLen[0x63] =
+ cpustate->InstLen[0x68] = cpustate->InstLen[0x69] = cpustate->InstLen[0x6a] = cpustate->InstLen[0x6b] =
+ cpustate->InstLen[0x33] = cpustate->InstLen[0x23] = 2;
+
+ /* initialize LBI opcode array */
+
+ for (i=0x00; i<0x100; i++) cpustate->LBIops[i] = 0;
+ for (i=0x08; i<0x10; i++) cpustate->LBIops[i] = 1;
+ for (i=0x18; i<0x20; i++) cpustate->LBIops[i] = 1;
+ for (i=0x28; i<0x30; i++) cpustate->LBIops[i] = 1;
+ for (i=0x38; i<0x40; i++) cpustate->LBIops[i] = 1;
+
+ for (i=0; i<256; i++) cpustate->LBIops33[i] = 0;
+ for (i=0x80; i<0xc0; i++) cpustate->LBIops33[i] = 1;
+
+ /* select opcode map */
+
+ cpustate->opcode_map = COP444_OPCODE_MAP;
+}
+
+static CPU_INIT( cop410 )
+{
+ cop410_init_opcodes(device);
+ cop400_init(device, 0xf, 0xf, 0, 0, 0);
+}
+
+static CPU_INIT( cop411 )
+{
+ cop410_init_opcodes(device);
+ cop400_init(device, 0x7, 0x3, 0, 0, 0);
+}
+
+static CPU_INIT( cop420 )
+{
+ cop420_init_opcodes(device);
+ cop400_init(device, 0xf, 0xf, 0xf, 1, 1);
+}
+
+static CPU_INIT( cop421 )
+{
+ cop420_init_opcodes(device);
+ cop400_init(device, 0xf, 0xf, 0, 1, 0);
+}
+
+static CPU_INIT( cop422 )
+{
+ cop420_init_opcodes(device);
+ cop400_init(device, 0xe, 0xe, 0, 1, 0);
+}
+
+static CPU_INIT( cop444 )
+{
+ cop444_init_opcodes(device);
+ cop400_init(device, 0xf, 0xf, 0xf, 1, 1);
+}
+
+static CPU_INIT( cop425 )
+{
+ cop444_init_opcodes(device);
+ cop400_init(device, 0xf, 0xf, 0, 1, 0);
+}
+
+static CPU_INIT( cop426 )
+{
+ cop444_init_opcodes(device);
+ cop400_init(device, 0xe, 0xe, 0xf, 1, 1);
+}
+
+static CPU_INIT( cop445 )
+{
+ cop444_init_opcodes(device);
+ cop400_init(device, 0x7, 0x3, 0, 1, 0);
+}
+
+/***************************************************************************
+ RESET
+***************************************************************************/
+
+static CPU_RESET( cop400 )
+{
+ cop400_state *cpustate = get_safe_token(device);
+
+ PC = 0;
+ A = 0;
+ B = 0;
+ C = 0;
+ OUT_D(0);
+ EN = 0;
+ WRITE_G(cpustate, 0);
+ SKL = 1;
+
+ T = 0;
+ cpustate->skt_latch = 1;
+
+ cpustate->halt = 0;
+ cpustate->idle = 0;
+}
+
+/***************************************************************************
+ EXECUTION
+***************************************************************************/
+
+static CPU_EXECUTE( cop400 )
+{
+ cop400_state *cpustate = get_safe_token(device);
+
+ UINT8 opcode;
+
+ do
+ {
+ cpustate->prevpc = PC;
+
+ debugger_instruction_hook(device, PC);
+
+ if (cpustate->intf->cko == COP400_CKO_HALT_IO_PORT)
+ {
+ cpustate->halt = IN_CKO();
+ }
+
+ if (cpustate->halt)
+ {
+ cpustate->icount -= 1;
+ continue;
+ }
+
+ opcode = ROM(PC);
+
+ if (cpustate->skip_lbi)
+ {
+ int is_lbi = 0;
+
+ if (opcode == 0x33)
+ {
+ is_lbi = cpustate->LBIops33[ROM(PC+1)];
+ }
+ else
+ {
+ is_lbi = cpustate->LBIops[opcode];
+ }
+
+ if (is_lbi)
+ {
+ cpustate->icount -= cpustate->opcode_map[opcode].cycles;
+
+ PC += cpustate->InstLen[opcode];
+ }
+ else
+ {
+ cpustate->skip_lbi = 0;
+ }
+ }
+
+ if (!cpustate->skip_lbi)
+ {
+ int inst_cycles = cpustate->opcode_map[opcode].cycles;
+
+ PC++;
+
+ (*(cpustate->opcode_map[opcode].function))(cpustate, opcode);
+ cpustate->icount -= inst_cycles;
+
+ // check for interrupt
+
+ if (BIT(EN, 1) && BIT(IL, 1))
+ {
+ cop400_opcode_func function = cpustate->opcode_map[ROM(PC)].function;
+
+ if ((function != jp) && (function != jmp) && (function != jsr))
+ {
+ // store skip logic
+ cpustate->last_skip = cpustate->skip;
+ cpustate->skip = 0;
+
+ // push next PC
+ PUSH(cpustate, PC);
+
+ // jump to interrupt service routine
+ PC = 0x0ff;
+
+ // disable interrupt
+ EN &= ~0x02;
+ }
+
+ IL &= ~2;
+ }
+
+ // skip next instruction?
+
+ if (cpustate->skip)
+ {
+ cop400_opcode_func function = cpustate->opcode_map[ROM(PC)].function;
+
+ opcode = ROM(PC);
+
+ if ((function == lqid) || (function == jid))
+ {
+ cpustate->icount -= 1;
+ }
+ else
+ {
+ cpustate->icount -= cpustate->opcode_map[opcode].cycles;
+ }
+
+ PC += cpustate->InstLen[opcode];
+
+ cpustate->skip = 0;
+ }
+ }
+ } while (cpustate->icount > 0);
+}
+
+/***************************************************************************
+ ADDRESS MAPS
+***************************************************************************/
+
+static ADDRESS_MAP_START( program_512b, AS_PROGRAM, 8 )
+ AM_RANGE(0x000, 0x1ff) AM_ROM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( program_1kb, AS_PROGRAM, 8 )
+ AM_RANGE(0x000, 0x3ff) AM_ROM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( program_2kb, AS_PROGRAM, 8 )
+ AM_RANGE(0x000, 0x7ff) AM_ROM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( data_32b, AS_DATA, 8 )
+ AM_RANGE(0x00, 0x1f) AM_RAM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( data_64b, AS_DATA, 8 )
+ AM_RANGE(0x00, 0x3f) AM_RAM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( data_128b, AS_DATA, 8 )
+ AM_RANGE(0x00, 0x7f) AM_RAM
+ADDRESS_MAP_END
+
+#ifdef UNUSED_CODE
+static ADDRESS_MAP_START( data_160b, AS_DATA, 8 )
+ AM_RANGE(0x00, 0x9f) AM_RAM
+ADDRESS_MAP_END
+#endif
+
+/***************************************************************************
+ VALIDITY CHECKS
+***************************************************************************/
+
+#if 0
+static CPU_VALIDITY_CHECK( cop410 )
+{
+ int error = FALSE;
+ const cop400_interface *intf = (const cop400_interface *) config;
+
+ if ((intf == NULL) || (intf->cki <= 0))
+ {
+ mame_printf_error("%s: %s has an invalid CPU configuration\n", driver->source_file, driver->name);
+ error = TRUE;
+ }
+
+ return error;
+}
+
+static CPU_VALIDITY_CHECK( cop420 )
+{
+ int error = FALSE;
+ const cop400_interface *intf = (const cop400_interface *) config;
+
+ if ((intf == NULL) || (intf->cki <= 0))
+ {
+ mame_printf_error("%s: %s has an invalid CPU configuration\n", driver->source_file, driver->name);
+ error = TRUE;
+ }
+
+ return error;
+}
+
+static CPU_VALIDITY_CHECK( cop421 )
+{
+ int error = FALSE;
+ const cop400_interface *intf = (const cop400_interface *) config;
+
+ if ((intf == NULL) || (intf->cki <= 0) || (intf->microbus == COP400_MICROBUS_ENABLED))
+ {
+ mame_printf_error("%s: %s has an invalid CPU configuration\n", driver->source_file, driver->name);
+ error = TRUE;
+ }
+
+ return error;
+}
+
+static CPU_VALIDITY_CHECK( cop444 )
+{
+ int error = FALSE;
+ const cop400_interface *intf = (const cop400_interface *) config;
+
+ if ((intf == NULL) || (intf->cki <= 0))
+ {
+ mame_printf_error("%s: %s has an invalid CPU configuration\n", driver->source_file, driver->name);
+ error = TRUE;
+ }
+
+ return error;
+}
+#endif
+
+/***************************************************************************
+ GENERAL CONTEXT ACCESS
+***************************************************************************/
+
+static CPU_IMPORT_STATE( cop400 )
+{
+ cop400_state *cpustate = get_safe_token(device);
+
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ cpustate->c = (cpustate->flags >> 1) & 1;
+ cpustate->skl = (cpustate->flags >> 0) & 1;
+ break;
+ }
+}
+
+static CPU_EXPORT_STATE( cop400 )
+{
+ cop400_state *cpustate = get_safe_token(device);
+
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ cpustate->flags = (cpustate->c ? 0x02 : 0x00) |
+ (cpustate->skl ? 0x01 : 0x00);
+ break;
+ }
+}
+
+static CPU_EXPORT_STRING( cop400 )
+{
+ cop400_state *cpustate = get_safe_token(device);
+
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ string.printf("%c%c",
+ cpustate->c ? 'C' : '.',
+ cpustate->skl ? 'S' : '.');
+ break;
+ }
+}
+
+static CPU_SET_INFO( cop400 )
+{
+ /* nothing to set */
+}
+
+static CPU_GET_INFO( cop400 )
+{
+ cop400_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+ cop400_interface *intf = (device->static_config() != NULL) ? (cop400_interface *)device->static_config() : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(cop400_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 0; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = (intf != NULL) ? intf->cki : 16; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 2; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 2; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: /* set per-core */ break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 8; /* really 4 */ break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: /* set per-core */ break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 9; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ /* --- the following bits of info are returned as pointers to functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(cop400); break;
+ case CPUINFO_FCT_INIT: /* set per-core */ break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(cop400); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(cop400); break;
+ case CPUINFO_FCT_DISASSEMBLE: /* set per-core */ break;
+// case CPUINFO_FCT_VALIDITY_CHECK: /* set per-core */ break;
+ case CPUINFO_FCT_IMPORT_STATE: info->import_state = CPU_IMPORT_STATE_NAME(cop400); break;
+ case CPUINFO_FCT_EXPORT_STATE: info->export_state = CPU_EXPORT_STATE_NAME(cop400); break;
+ case CPUINFO_FCT_EXPORT_STRING: info->export_string = CPU_EXPORT_STRING_NAME(cop400); break;
+
+ /* --- the following bits of info are returned as pointers --- */
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: /* set per-core */ break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: /* set per-core */ break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "COP400"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "National Semiconductor COPS"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright MAME Team"); break;
+ }
+}
+
+/***************************************************************************
+ CPU-SPECIFIC CONTEXT ACCESS
+***************************************************************************/
+
+CPU_GET_INFO( cop410 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 9; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 5; break;
+
+ /* --- the following bits of info are returned as pointers to functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(cop410); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(cop410); break;
+// case CPUINFO_FCT_VALIDITY_CHECK: info->validity_check = CPU_VALIDITY_CHECK_NAME(cop410); break;
+
+ /* --- the following bits of info are returned as pointers --- */
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME(program_512b); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = ADDRESS_MAP_NAME(data_32b); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "COP410"); break;
+
+ default: CPU_GET_INFO_CALL(cop400); break;
+ }
+}
+
+CPU_GET_INFO( cop411 )
+{
+ // COP411 is a 20-pin package version of the COP410, missing D2/D3/G3/CKO
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(cop411); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "COP411"); break;
+
+ default: CPU_GET_INFO_CALL(cop410); break;
+ }
+}
+
+CPU_GET_INFO( cop401 )
+{
+ // COP401 is a ROMless version of the COP410
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers --- */
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = NULL; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "COP401"); break;
+
+ default: CPU_GET_INFO_CALL(cop410); break;
+ }
+}
+
+CPU_GET_INFO( cop420 )
+{
+ cop400_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 10; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 6; break;
+
+ /* --- the following bits of info are returned as pointers to functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(cop420); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(cop420); break;
+// case CPUINFO_FCT_VALIDITY_CHECK: info->validity_check = CPU_VALIDITY_CHECK_NAME(cop420); break;
+
+ /* --- the following bits of info are returned as pointers --- */
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME(program_1kb); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = ADDRESS_MAP_NAME(data_64b); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "COP420"); break;
+
+ case CPUINFO_STR_FLAGS: sprintf(info->s,
+ "%c%c%c",
+ cpustate->c ? 'C' : '.',
+ cpustate->skl ? 'S' : '.',
+ cpustate->skt_latch ? 'T' : '.'); break;
+
+ default: CPU_GET_INFO_CALL(cop400); break;
+ }
+}
+
+CPU_GET_INFO( cop421 )
+{
+ // COP421 is a 24-pin package version of the COP420, lacking the IN ports
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(cop421); break;
+// case CPUINFO_FCT_VALIDITY_CHECK: info->validity_check = CPU_VALIDITY_CHECK_NAME(cop421); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "COP421"); break;
+
+ default: CPU_GET_INFO_CALL(cop420); break;
+ }
+}
+
+CPU_GET_INFO( cop422 )
+{
+ // COP422 is a 20-pin package version of the COP420, lacking G0/G1, D0/D1, and the IN ports
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(cop422); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "COP422"); break;
+
+ default: CPU_GET_INFO_CALL(cop421); break;
+ }
+}
+
+CPU_GET_INFO( cop402 )
+{
+ // COP402 is a ROMless version of the COP420
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = NULL; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "COP402"); break;
+
+ default: CPU_GET_INFO_CALL(cop420); break;
+ }
+}
+
+CPU_GET_INFO( cop444 )
+{
+ cop400_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 11; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 7; break;
+
+ /* --- the following bits of info are returned as pointers to functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(cop444); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(cop444); break;
+// case CPUINFO_FCT_VALIDITY_CHECK: info->validity_check = CPU_VALIDITY_CHECK_NAME(cop444); break;
+
+ /* --- the following bits of info are returned as pointers --- */
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME(program_2kb); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = ADDRESS_MAP_NAME(data_128b); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "COP444"); break;
+
+ case CPUINFO_STR_FLAGS: sprintf(info->s,
+ "%c%c%c",
+ cpustate->c ? 'C' : '.',
+ cpustate->skl ? 'S' : '.',
+ cpustate->skt_latch ? 'T' : '.'); break;
+
+ default: CPU_GET_INFO_CALL(cop400); break;
+ }
+}
+
+CPU_GET_INFO( cop445 )
+{
+ // COP445 is a 24-pin package version of the COP444, lacking the IN ports
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(cop445); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "COP445"); break;
+
+ default: CPU_GET_INFO_CALL(cop444); break;
+ }
+}
+
+CPU_GET_INFO( cop424 )
+{
+ // COP424 is functionally equivalent to COP444, with only 1K ROM and 64x4 bytes RAM
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 10; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 6; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME(program_1kb); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = ADDRESS_MAP_NAME(data_64b); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "COP424"); break;
+
+ default: CPU_GET_INFO_CALL(cop444); break;
+ }
+}
+
+CPU_GET_INFO( cop425 )
+{
+ // COP425 is a 24-pin package version of the COP424, lacking the IN ports
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(cop425); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "COP425"); break;
+
+ default: CPU_GET_INFO_CALL(cop424); break;
+ }
+}
+
+CPU_GET_INFO( cop426 )
+{
+ // COP426 is a 20-pin package version of the COP424, with only L0-L7, G2-G3, D2-D3 ports
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(cop426); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "COP426"); break;
+
+ default: CPU_GET_INFO_CALL(cop424); break;
+ }
+}
+
+CPU_GET_INFO( cop404 )
+{
+ // COP404 is a ROMless version of the COP444, which can emulate a COP410C/COP411C, COP424C/COP425C, or a COP444C/COP445C
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = NULL; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "COP404"); break;
+
+ default: CPU_GET_INFO_CALL(cop444); break;
+ }
+}
+
+/* COP410 family */
+DEFINE_LEGACY_CPU_DEVICE(COP401, cop401);
+DEFINE_LEGACY_CPU_DEVICE(COP410, cop410);
+DEFINE_LEGACY_CPU_DEVICE(COP411, cop411);
+
+/* COP420 family */
+DEFINE_LEGACY_CPU_DEVICE(COP402, cop402);
+DEFINE_LEGACY_CPU_DEVICE(COP420, cop420);
+DEFINE_LEGACY_CPU_DEVICE(COP421, cop421);
+DEFINE_LEGACY_CPU_DEVICE(COP422, cop422);
+
+/* COP444 family */
+DEFINE_LEGACY_CPU_DEVICE(COP404, cop404);
+DEFINE_LEGACY_CPU_DEVICE(COP424, cop424);
+DEFINE_LEGACY_CPU_DEVICE(COP425, cop425);
+DEFINE_LEGACY_CPU_DEVICE(COP426, cop426);
+DEFINE_LEGACY_CPU_DEVICE(COP444, cop444);
+DEFINE_LEGACY_CPU_DEVICE(COP445, cop445);
diff --git a/trunk/src/emu/cpu/cop400/cop400.h b/trunk/src/emu/cpu/cop400/cop400.h
new file mode 100644
index 00000000000..ad859e1296f
--- /dev/null
+++ b/trunk/src/emu/cpu/cop400/cop400.h
@@ -0,0 +1,159 @@
+/***************************************************************************
+
+ cop400.h
+
+ National Semiconductor COPS Emulator.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __COP400__
+#define __COP400__
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+/* register access indexes */
+enum
+{
+ COP400_PC,
+ COP400_SA,
+ COP400_SB,
+ COP400_SC,
+ COP400_N,
+ COP400_A,
+ COP400_B,
+ COP400_C,
+ COP400_G,
+ COP400_H,
+ COP400_Q,
+ COP400_R,
+ COP400_EN,
+ COP400_SIO,
+ COP400_SKL,
+ COP400_T,
+ COP400_GENPC = STATE_GENPC,
+ COP400_GENPCBASE = STATE_GENPCBASE,
+ COP400_GENSP = STATE_GENSP
+};
+
+/* special I/O space ports */
+enum
+{
+ COP400_PORT_L = 0x100,
+ COP400_PORT_G,
+ COP400_PORT_D,
+ COP400_PORT_H,
+ COP400_PORT_R,
+ COP400_PORT_IN,
+ COP400_PORT_SK,
+ COP400_PORT_SIO,
+ COP400_PORT_CKO
+};
+
+/* input lines */
+enum
+{
+ /* COP420 */
+ COP400_IN0 = 0,
+ COP400_IN1,
+ COP400_IN2,
+ COP400_IN3,
+
+ /* COP404 */
+ COP400_MB,
+ COP400_DUAL,
+ COP400_SEL10,
+ COP400_SEL20
+};
+
+/* CKI bonding options */
+enum _cop400_cki_bond {
+ COP400_CKI_DIVISOR_4 = 4,
+ COP400_CKI_DIVISOR_8 = 8,
+ COP400_CKI_DIVISOR_16 = 16,
+ COP400_CKI_DIVISOR_32 = 32
+};
+typedef enum _cop400_cki_bond cop400_cki_bond;
+
+/* CKO bonding options */
+enum _cop400_cko_bond {
+ COP400_CKO_OSCILLATOR_OUTPUT = 0,
+ COP400_CKO_RAM_POWER_SUPPLY,
+ COP400_CKO_HALT_IO_PORT,
+ COP400_CKO_SYNC_INPUT,
+ COP400_CKO_GENERAL_PURPOSE_INPUT
+};
+typedef enum _cop400_cko_bond cop400_cko_bond;
+
+/* microbus bonding options */
+enum _cop400_microbus {
+ COP400_MICROBUS_DISABLED = 0,
+ COP400_MICROBUS_ENABLED
+};
+typedef enum _cop400_microbus cop400_microbus;
+
+/* interface */
+typedef struct _cop400_interface cop400_interface;
+struct _cop400_interface
+{
+ cop400_cki_bond cki; /* CKI bonding option */
+ cop400_cko_bond cko; /* CKO bonding option */
+ cop400_microbus microbus; /* microbus option */
+};
+#define COP400_INTERFACE(name) const cop400_interface (name) =
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+#define CPU_COP401 CPU_GET_INFO_NAME( cop401 )
+#define CPU_COP410 CPU_GET_INFO_NAME( cop410 )
+#define CPU_COP411 CPU_GET_INFO_NAME( cop411 )
+
+#define CPU_COP402 CPU_GET_INFO_NAME( cop402 )
+#define CPU_COP420 CPU_GET_INFO_NAME( cop420 )
+#define CPU_COP421 CPU_GET_INFO_NAME( cop421 )
+#define CPU_COP422 CPU_GET_INFO_NAME( cop422 )
+
+#define CPU_COP404 CPU_GET_INFO_NAME( cop404 )
+#define CPU_COP424 CPU_GET_INFO_NAME( cop424 )
+#define CPU_COP425 CPU_GET_INFO_NAME( cop425 )
+#define CPU_COP426 CPU_GET_INFO_NAME( cop426 )
+#define CPU_COP444 CPU_GET_INFO_NAME( cop444 )
+#define CPU_COP445 CPU_GET_INFO_NAME( cop445 )
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+/* COP410 family */
+DECLARE_LEGACY_CPU_DEVICE(COP401, cop401);
+DECLARE_LEGACY_CPU_DEVICE(COP410, cop410);
+DECLARE_LEGACY_CPU_DEVICE(COP411, cop411);
+
+/* COP420 family */
+DECLARE_LEGACY_CPU_DEVICE(COP402, cop402);
+DECLARE_LEGACY_CPU_DEVICE(COP420, cop420);
+DECLARE_LEGACY_CPU_DEVICE(COP421, cop421);
+DECLARE_LEGACY_CPU_DEVICE(COP422, cop422);
+
+/* COP444 family */
+DECLARE_LEGACY_CPU_DEVICE(COP404, cop404);
+DECLARE_LEGACY_CPU_DEVICE(COP424, cop424);
+DECLARE_LEGACY_CPU_DEVICE(COP425, cop425);
+DECLARE_LEGACY_CPU_DEVICE(COP426, cop426);
+DECLARE_LEGACY_CPU_DEVICE(COP444, cop444);
+DECLARE_LEGACY_CPU_DEVICE(COP445, cop445);
+
+/* disassemblers */
+extern CPU_DISASSEMBLE( cop410 );
+extern CPU_DISASSEMBLE( cop420 );
+extern CPU_DISASSEMBLE( cop444 );
+
+#endif /* __COP400__ */
diff --git a/trunk/src/emu/cpu/cop400/cop400op.c b/trunk/src/emu/cpu/cop400/cop400op.c
new file mode 100644
index 00000000000..9c737f0807e
--- /dev/null
+++ b/trunk/src/emu/cpu/cop400/cop400op.c
@@ -0,0 +1,1318 @@
+/***************************************************************************
+
+ cop400op.c
+
+ National Semiconductor COP400 Emulator.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+/***************************************************************************
+ ARITHMETIC INSTRUCTIONS
+***************************************************************************/
+
+/*
+
+ Mnemonic: ASC
+
+ Hex Code: 30
+ Binary: 0 0 1 1 0 0 0 0
+
+ Data Flow: A + C + RAM(B) -> A
+ Carry -> C
+
+ Skip Conditions: Carry
+
+ Description: Add with Carry, Skip on Carry
+
+*/
+
+INSTRUCTION( asc )
+{
+ A = A + C + RAM_R(B);
+
+ if (A > 0xF)
+ {
+ C = 1;
+ cpustate->skip = 1;
+ A &= 0xF;
+ }
+ else
+ {
+ C = 0;
+ }
+}
+
+/*
+
+ Mnemonic: ADD
+
+ Hex Code: 31
+ Binary: 0 0 1 1 0 0 0 1
+
+ Data Flow: A + RAM(B) -> A
+
+ Description: Add RAM to A
+
+*/
+
+INSTRUCTION( add )
+{
+ A = (A + RAM_R(B)) & 0x0F;
+}
+
+/*
+
+ Mnemonic: AISC
+
+ Operand: y
+ Hex Code: 5-
+ Binary: 0 1 0 1 y3 y2 y1 y0
+
+ Data Flow: A + y -> A
+
+ Skip Conditions: Carry
+
+ Description: Add Immediate, Skip on Carry (y != 0)
+
+*/
+
+INSTRUCTION( aisc )
+{
+ UINT8 y = opcode & 0x0f;
+
+ A = A + y;
+
+ if (A > 0x0f)
+ {
+ cpustate->skip = 1;
+ A &= 0xF;
+ }
+}
+
+/*
+
+ Mnemonic: CLRA
+
+ Hex Code: 00
+ Binary: 0 0 0 0 0 0 0 0
+
+ Data Flow: 0 -> A
+
+ Description: Clear A
+
+*/
+
+INSTRUCTION( clra )
+{
+ A = 0;
+}
+
+/*
+
+ Mnemonic: COMP
+
+ Hex Code: 40
+ Binary: 0 1 0 0 0 0 0 0
+
+ Data Flow: ~A -> A
+
+ Description: Ones Complement of A to A
+
+*/
+
+INSTRUCTION( comp )
+{
+ A = A ^ 0xF;
+}
+
+/*
+
+ Mnemonic: NOP
+
+ Hex Code: 44
+ Binary: 0 1 0 0 0 1 0 0
+
+ Description: No Operation
+
+*/
+
+INSTRUCTION( nop )
+{
+ // do nothing
+}
+
+/*
+
+ Mnemonic: RC
+
+ Hex Code: 32
+ Binary: 0 0 1 1 0 0 1 0
+
+ Data Flow: "0" -> C
+
+ Description: Reset C
+
+*/
+
+INSTRUCTION( rc )
+{
+ C = 0;
+}
+
+/*
+
+ Mnemonic: SC
+
+ Hex Code: 22
+ Binary: 0 0 1 0 0 0 1 0
+
+ Data Flow: "1" -> C
+
+ Description: Set C
+
+*/
+
+INSTRUCTION( sc )
+{
+ C = 1;
+}
+
+/*
+
+ Mnemonic: XOR
+
+ Hex Code: 02
+ Binary: 0 0 0 0 0 0 1 0
+
+ Data Flow: A ^ RAM(B) -> A
+
+ Description: Exclusive-OR RAM with A
+
+*/
+
+INSTRUCTION( xor_ )
+{
+ A = A ^ RAM_R(B);
+}
+
+/*
+
+ Mnemonic: ADT
+
+ Hex Code: 4A
+ Binary: 0 1 0 0 1 0 1 0
+
+ Data Flow: A + 10 -> A
+
+ Description: Add Ten to A
+
+*/
+
+INSTRUCTION( adt )
+{
+ A = (A + 10) & 0x0F;
+}
+
+/*
+
+ Mnemonic: CASC
+
+ Hex Code: 10
+ Binary: 0 0 0 1 0 0 0 0
+
+ Data Flow: ~A + RAM(B) + C -> A
+ Carry -> C
+
+ Skip Conditions: Carry
+
+ Description: Complement and Add with Carry, Skip on Carry
+
+*/
+
+INSTRUCTION( casc )
+{
+ A = (A ^ 0xF) + RAM_R(B) + C;
+
+ if (A > 0xF)
+ {
+ C = 1;
+ cpustate->skip = 1;
+ A &= 0xF;
+ }
+ else
+ {
+ C = 0;
+ }
+}
+
+/***************************************************************************
+ TRANSFER-OF-CONTROL INSTRUCTIONS
+***************************************************************************/
+
+/*
+
+ Mnemonic: JID
+
+ Hex Code: FF
+ Binary: 1 1 1 1 1 1 1 1
+
+ Data Flow: ROM(PC10:8,A,M) -> PC7:0
+
+ Description: Jump Indirect
+
+*/
+
+INSTRUCTION( jid )
+{
+ UINT16 addr = (PC & 0x700) | (A << 4) | RAM_R(B);
+ PC = (PC & 0x700) | ROM(addr);
+}
+
+/*
+
+ Mnemonic: JMP
+
+ Operand: a
+ Hex Code: 6- --
+ Binary: 0 1 1 0 0 a10 a9 a8 a7 a6 a5 a4 a3 a2 a1 a0
+
+ Data Flow: a -> PC
+
+ Description: Jump
+
+*/
+
+INSTRUCTION( jmp )
+{
+ UINT16 a = ((opcode & 0x07) << 8) | ROM(PC);
+
+ PC = a;
+}
+
+/*
+
+ Mnemonic: JP
+
+ Operand: a
+ Hex Code: --
+ Binary: 1 a6 a5 a4 a3 a2 a1 a0
+ (pages 2,3 only)
+
+ 1 1 a5 a4 a3 a2 a1 a0
+ (all other pages)
+
+ Data Flow: a -> PC6:0
+
+ a -> PC5:0
+
+ Description: Jump within Page
+
+*/
+
+INSTRUCTION( jp )
+{
+ UINT8 page = PC >> 6;
+
+ if (page == 2 || page == 3)
+ {
+ UINT8 a = opcode & 0x7f;
+ PC = (PC & 0x780) | a;
+ }
+ else if ((opcode & 0xc0) == 0xc0)
+ {
+ UINT8 a = opcode & 0x3f;
+ PC = (PC & 0x7c0) | a;
+ }
+ else
+ {
+ // JSRP
+ UINT8 a = opcode & 0x3f;
+ PUSH(cpustate, PC);
+ PC = 0x80 | a;
+ }
+}
+
+/*
+
+ Mnemonic: JSR
+
+ Operand: a
+ Hex Code: 6- --
+ Binary: 0 1 1 0 1 a10 a9 a8 a7 a6 a5 a4 a3 a2 a1 a0
+
+ Data Flow: PC + 1 -> SA -> SB -> SC
+ a -> PC
+
+ Description: Jump to Subroutine
+
+*/
+
+INSTRUCTION( jsr )
+{
+ UINT16 a = ((opcode & 0x07) << 8) | ROM(PC);
+
+ PUSH(cpustate, PC + 1);
+ PC = a;
+}
+
+/*
+
+ Mnemonic: RET
+
+ Hex Code: 48
+ Binary: 0 1 0 0 1 0 0 0
+
+ Data Flow: SC -> SB -> SA -> PC
+
+ Description: Return from Subroutine
+
+*/
+
+INSTRUCTION( ret )
+{
+ POP(cpustate);
+}
+
+/*
+
+ Processor: COP420
+
+ Mnemonic: RET
+
+ Hex Code: 48
+ Binary: 0 1 0 0 1 0 0 0
+
+ Data Flow: SC -> SB -> SA -> PC
+
+ Description: Return from Subroutine, restore Skip logic
+
+*/
+
+INSTRUCTION( cop420_ret )
+{
+ POP(cpustate);
+ cpustate->skip = cpustate->last_skip;
+}
+
+/*
+
+ Mnemonic: RETSK
+
+ Hex Code: 49
+ Binary: 0 1 0 0 1 0 0 1
+
+ Data Flow: SC -> SB -> SA -> PC
+
+ Skip Conditions: Always Skip on Return
+
+ Description: Return from Subroutine then Skip
+
+*/
+
+INSTRUCTION( retsk )
+{
+ POP(cpustate);
+ cpustate->skip = 1;
+}
+
+/*
+
+ Processor: COP410C/COP411C
+
+ Mnemonic: HALT
+
+ Hex Code: 33 38
+ Binary: 0 0 1 1 0 0 1 1 0 0 1 1 1 0 0 0
+
+ Description: Halt processor
+
+*/
+
+INSTRUCTION( halt )
+{
+ cpustate->halt = 1;
+}
+
+/*
+
+ Mnemonic: IT
+
+ Hex Code: 33 39
+ Binary: 0 0 1 1 0 0 1 1 0 0 1 1 1 0 0 1
+
+ Description: IDLE till Timer Overflows then Continues
+
+*/
+
+INSTRUCTION( it )
+{
+ cpustate->halt = 1;
+ cpustate->idle = 1;
+}
+
+/***************************************************************************
+ MEMORY REFERENCE INSTRUCTIONS
+***************************************************************************/
+
+/*
+
+ Mnemonic: CAMQ
+
+ Hex Code: 33 3C
+ Binary: 0 0 1 1 0 0 1 1 0 0 1 1 1 1 0 0
+
+ Data Flow: A -> Q7:4
+ RAM(B) -> Q3:0
+
+ Description: Copy A, RAM to Q
+
+*/
+
+INSTRUCTION( camq )
+{
+ /*
+
+ Excerpt from the COP410L data sheet:
+
+ False states may be generated on L0-L7 during the execution of the CAMQ instruction.
+ The L-ports should not be used as clocks for edge sensitive devices such as flip-flops,
+ counters, shift registers, etc. the following short program that illustrates this situation.
+
+ START:
+ CLRA ;ENABLE THE Q
+ LEI 4 ;REGISTER TO L LINES
+ LBI TEST
+ STII 3
+ AISC 12
+ LOOP:
+ LBI TEST ;LOAD Q WITH X'C3
+ CAMQ
+ JP LOOP
+
+ In this program the internal Q register is enabled onto the L lines and a steady bit
+ pattern of logic highs is output on L0, L1, L6, L7, and logic lows on L2-L5 via the
+ two-byte CAMQ instruction. Timing constraints on the device are such that the Q
+ register may be temporarily loaded with the second byte of the CAMQ opcode (3C) prior
+ to receiving the valid data pattern. If this occurs, the opcode will ripple onto the L
+ lines and cause negative-going glitches on L0, L1, L6, L7, and positive glitches on
+ L2-L5. Glitch durations are under 2 ms, although the exact value may vary due to data
+ patterns, processing parameters, and L line loading. These false states are peculiar
+ only to the CAMQ instruction and the L lines.
+
+ */
+
+ UINT8 data = (A << 4) | RAM_R(B);
+
+ WRITE_Q(cpustate, data);
+
+#ifdef CAMQ_BUG
+ WRITE_Q(cpustate, 0x3c);
+ WRITE_Q(cpustate, data);
+#endif
+}
+
+/*
+
+ Mnemonic: LD
+
+ Operand: r
+ Hex Code: -5
+ Binary: 0 0 r1 r0 0 1 0 1
+
+ Data Flow: RAM(B) -> A
+ Br ^ r -> Br
+
+ Description: Load RAM into A, Exclusive-OR Br with r
+
+*/
+
+INSTRUCTION( ld )
+{
+ UINT8 r = opcode & 0x30;
+
+ A = RAM_R(B);
+ B = B ^ r;
+}
+
+/*
+
+ Mnemonic: LQID
+
+ Hex Code: BF
+ Binary: 1 0 1 1 1 1 1 1
+
+ Data Flow: ROM(PC10:8,A,M) -> Q
+ SB -> SC
+
+ Description: Load Q Indirect
+
+*/
+
+INSTRUCTION( lqid )
+{
+ PUSH(cpustate, PC);
+ PC = (PC & 0x700) | (A << 4) | RAM_R(B);
+ WRITE_Q(cpustate, ROM(PC));
+ POP(cpustate);
+}
+
+/*
+
+ Mnemonic: RMB
+
+ Operand: 0
+ 1
+ 2
+ 3
+
+ Hex Code: 4C
+ 45
+ 42
+ 43
+
+ Binary: 0 1 0 0 1 1 0 0
+ 0 1 0 0 0 1 0 1
+ 0 1 0 0 0 0 1 0
+ 0 1 0 0 0 0 1 1
+
+ Data Flow: 0 -> RAM(B)0
+ 0 -> RAM(B)1
+ 0 -> RAM(B)2
+ 0 -> RAM(B)3
+
+ Description: Reset RAM Bit
+
+*/
+
+INSTRUCTION( rmb0 ) { RAM_W(B, RAM_R(B) & 0xE); }
+INSTRUCTION( rmb1 ) { RAM_W(B, RAM_R(B) & 0xD); }
+INSTRUCTION( rmb2 ) { RAM_W(B, RAM_R(B) & 0xB); }
+INSTRUCTION( rmb3 ) { RAM_W(B, RAM_R(B) & 0x7); }
+
+/*
+
+ Mnemonic: SMB
+
+ Operand: 0
+ 1
+ 2
+ 3
+
+ Hex Code: 4D
+ 47
+ 46
+ 4B
+
+ Binary: 0 1 0 0 1 1 0 1
+ 0 1 0 0 0 1 1 1
+ 0 1 0 0 0 1 1 0
+ 0 1 0 0 1 0 1 1
+
+ Data Flow: 1 -> RAM(B)0
+ 1 -> RAM(B)1
+ 1 -> RAM(B)2
+ 1 -> RAM(B)3
+
+ Description: Set RAM Bit
+
+*/
+
+INSTRUCTION( smb0 ) { RAM_W(B, RAM_R(B) | 0x1); }
+INSTRUCTION( smb1 ) { RAM_W(B, RAM_R(B) | 0x2); }
+INSTRUCTION( smb2 ) { RAM_W(B, RAM_R(B) | 0x4); }
+INSTRUCTION( smb3 ) { RAM_W(B, RAM_R(B) | 0x8); }
+
+/*
+
+ Mnemonic: STII
+
+ Operand: y
+ Hex Code: 7-
+ Binary: 0 1 1 1 y3 y2 y1 y0
+
+ Data Flow: y -> RAM(B)
+ Bd + 1 -> Bd
+
+ Description: Store Memory Immediate and Increment Bd
+
+*/
+
+INSTRUCTION( stii )
+{
+ UINT8 y = opcode & 0x0f;
+ UINT16 Bd;
+
+ RAM_W(B, y);
+
+ Bd = ((B & 0x0f) + 1) & 0x0f;
+ B = (B & 0x70) + Bd;
+}
+
+/*
+
+ Mnemonic: X
+
+ Operand: r
+ Hex Code: -6
+ Binary: 0 0 r1 r0 0 1 1 0
+
+ Data Flow: RAM(B) <-> A
+ Br ^ r -> Br
+
+ Description: Exchange RAM with A, Exclusive-OR Br with r
+
+*/
+
+INSTRUCTION( x )
+{
+ UINT8 r = opcode & 0x30;
+ UINT8 t = RAM_R(B);
+
+ RAM_W(B, A);
+
+ A = t;
+ B = B ^ r;
+}
+
+/*
+
+ Mnemonic: XAD
+
+ Operand: r,d
+ Hex Code: 23 --
+ Binary: 0 0 1 0 0 0 1 1 1 r2 r1 r0 d3 d2 d1 d0
+
+ Data Flow: RAM(r,d) <-> A
+
+ Description: Exchange A with RAM pointed to directly by r,d
+
+*/
+
+INSTRUCTION( xad )
+{
+ UINT8 rd = opcode & 0x7f;
+ UINT8 t = A;
+
+ A = RAM_R(rd);
+
+ RAM_W(rd, t);
+}
+
+/*
+
+ Mnemonic: XDS
+
+ Operand: r
+ Hex Code: -7
+ Binary: 0 0 r1 r0 0 1 1 1
+
+ Data Flow: RAM(B) <-> A
+ Bd - 1 -> Bd
+ Br ^ r -> Br
+
+ Skip Conditions: Bd decrements past 0
+
+ Description: Exchange RAM with A and Decrement Bd, Exclusive-OR Br with r
+
+*/
+
+INSTRUCTION( xds )
+{
+ UINT8 t, Bd;
+ UINT8 r = opcode & 0x30;
+
+ t = RAM_R(B);
+ RAM_W(B, A);
+ A = t;
+
+ Bd = ((B & 0x0f) - 1) & 0x0f;
+ B = (B & 0x30) | Bd;
+
+ B = B ^ r;
+
+ if (Bd == 0x0f) cpustate->skip = 1;
+}
+
+/*
+
+ Mnemonic: XIS
+
+ Operand: r
+ Hex Code: -4
+ Binary: 0 0 r1 r0 0 1 0 0
+
+ Data Flow: RAM(B) <-> A
+ Bd + 1 -> Bd
+ Br ^ r -> Br
+
+ Skip Conditions: Bd increments past 15
+
+ Description: Exchange RAM with A and Increment Bd, Exclusive-OR Br with r
+
+*/
+
+INSTRUCTION( xis )
+{
+ UINT8 t, Bd;
+ UINT8 r = opcode & 0x30;
+
+ t = RAM_R(B);
+ RAM_W(B, A);
+ A = t;
+
+ Bd = ((B & 0x0f) + 1) & 0x0f;
+ B = (B & 0x30) | Bd;
+
+ B = B ^ r;
+
+ if (Bd == 0x00) cpustate->skip = 1;
+}
+
+/*
+
+ Mnemonic: CQMA
+
+ Hex Code: 33 2C
+ Binary: 0 0 1 1 0 0 1 1 0 0 1 0 1 1 0 0
+
+ Data Flow: Q7:4 -> RAM(B)
+ Q3:0 -> A
+
+ Description: Copy Q to RAM, A
+
+*/
+
+INSTRUCTION( cqma )
+{
+ RAM_W(B, Q >> 4);
+ A = Q & 0xF;
+}
+
+/*
+
+ Mnemonic: LDD
+
+ Operand: r, d
+ Hex Code: 23 --
+ Binary: 0 0 1 0 0 0 1 1 0 r2 r1 r0 d3 d2 d1 d0
+
+ Data Flow: RAM(r,d) -> A
+
+ Description: Load A with RAM pointed to directly by r,d
+
+*/
+
+INSTRUCTION( ldd )
+{
+ UINT8 rd = opcode & 0x7f;
+
+ A = RAM_R(rd);
+}
+
+/*
+
+ Mnemonic: CAMT
+
+ Hex Code: 33 3F
+ Binary:
+
+ Data Flow: A -> T7:4
+ RAM(B) -> T3:0
+
+ Description: Copy A, RAM to T
+
+*/
+
+INSTRUCTION( camt )
+{
+ T = (A << 4) | RAM_R(B);
+}
+/*
+
+ Mnemonic: CTMA
+
+ Hex Code: 33 2F
+ Binary:
+
+ Data Flow: T7:4 -> RAM(B)
+ T3:0 -> A
+
+ Description: Copy T to RAM, A
+
+*/
+
+INSTRUCTION( ctma )
+{
+ RAM_W(B, T >> 4);
+ A = T & 0x0f;
+}
+
+/***************************************************************************
+ REGISTER REFERENCE INSTRUCTIONS
+***************************************************************************/
+
+/*
+
+ Mnemonic: CAB
+
+ Hex Code: 50
+ Binary: 0 1 0 1 0 0 0 0 0
+
+ Data Flow: A -> Bd
+
+ Description: Copy A to Bd
+
+*/
+
+INSTRUCTION( cab )
+{
+ B = (B & 0x70) | A;
+}
+
+/*
+
+ Mnemonic: CBA
+
+ Hex Code: 4E
+ Binary: 0 1 0 0 1 1 1 0
+
+ Data Flow: Bd -> A
+
+ Description: Copy Bd to A
+
+*/
+
+INSTRUCTION( cba )
+{
+ A = B & 0xF;
+}
+
+/*
+
+ Mnemonic: LBI
+
+ Operand: r,d
+ Hex Code: --
+ 33 --
+
+ Binary: 0 0 r1 r0 d3 d2 d1 d0 (d-1)
+ 0 0 1 1 0 0 1 1 1 r2 r1 r0 d3 d2 d1 d0
+
+ Data Flow: r,d -> B
+
+ Skip Conditions: Skip until not a LBI
+
+ Description: Load B Immediate with r,d
+
+*/
+
+INSTRUCTION( lbi )
+{
+ if (opcode & 0x80)
+ {
+ B = opcode & 0x3f;
+ }
+ else
+ {
+ B = (opcode & 0x70) | (((opcode & 0x0f) + 1) & 0x0f);
+ }
+
+ cpustate->skip_lbi = 1;
+}
+
+/*
+
+ Mnemonic: LEI
+
+ Operand: y
+ Hex Code: 33 6-
+ Binary: 0 0 1 1 0 0 1 1 0 1 1 0 y3 y2 y1 y0
+
+ Data Flow: y -> EN
+
+ Description: Load EN Immediate
+
+*/
+
+INSTRUCTION( lei )
+{
+ UINT8 y = opcode & 0x0f;
+
+ EN = y;
+
+ if (BIT(EN, 2))
+ {
+ OUT_L(Q);
+ }
+}
+
+/*
+
+ Mnemonic: XABR
+
+ Hex Code: 12
+ Binary: 0 0 0 1 0 0 1 0
+
+ Data Flow: A <-> Br(0,0 -> A3,A2)
+
+ Description: Exchange A with Br
+
+*/
+
+INSTRUCTION( xabr )
+{
+ UINT8 Br = A & 0x03;
+ UINT8 Bd = B & 0x0f;
+
+ A = B >> 4;
+ B = (Br << 4) + Bd;
+}
+
+/*
+
+ Processor: COP444
+
+ Mnemonic: XABR
+
+ Hex Code: 12
+ Binary: 0 0 0 1 0 0 1 0
+
+ Data Flow: A <-> Br(0 -> A3)
+
+ Description: Exchange A with Br
+
+*/
+
+INSTRUCTION( cop444_xabr )
+{
+ UINT8 Br = A & 0x07;
+ UINT8 Bd = B & 0x0f;
+
+ A = B >> 4;
+ B = (Br << 4) + Bd;
+}
+
+/***************************************************************************
+ TEST INSTRUCTIONS
+***************************************************************************/
+
+/*
+
+ Mnemonic: SKC
+
+ Hex Code: 20
+ Binary: 0 0 1 0 0 0 0 0
+
+ Skip Conditions: C = "1"
+
+ Description: Skip if C is True
+
+*/
+
+INSTRUCTION( skc )
+{
+ if (C == 1) cpustate->skip = 1;
+}
+
+/*
+
+ Mnemonic: SKE
+
+ Hex Code: 21
+ Binary: 0 0 1 0 0 0 0 1
+
+ Skip Conditions: A = RAM(B)
+
+ Description: Skip if A Equals RAM
+
+*/
+
+INSTRUCTION( ske )
+{
+ if (A == RAM_R(B)) cpustate->skip = 1;
+}
+
+/*
+
+ Mnemonic: SKGZ
+
+ Hex Code: 33 21
+ Binary: 00 0 1 1 0 0 1 1 0 0 1 0 0 0 0 1
+
+ Skip Conditions: G3:0 = 0
+
+ Description: Skip if G is Zero (all 4 bits)
+
+*/
+
+INSTRUCTION( skgz )
+{
+ if (IN_G() == 0) cpustate->skip = 1;
+}
+
+/*
+
+ Mnemonic: SKGBZ
+
+ Hex Code: 33 01
+ 33 11
+ 33 03
+ 33 13
+
+ Binary:
+
+ Skip Conditions: G0 = 0
+ G1 = 0
+ G2 = 0
+ G3 = 0
+
+ Description: Skip if G Bit is Zero
+
+*/
+
+INLINE void skgbz(cop400_state *cpustate, int bit)
+{
+ if (!BIT(IN_G(), bit)) cpustate->skip = 1;
+}
+
+INSTRUCTION( skgbz0 ) { skgbz(cpustate, 0); }
+INSTRUCTION( skgbz1 ) { skgbz(cpustate, 1); }
+INSTRUCTION( skgbz2 ) { skgbz(cpustate, 2); }
+INSTRUCTION( skgbz3 ) { skgbz(cpustate, 3); }
+
+/*
+
+ Mnemonic: SKMBZ
+
+ Hex Code: 01
+ 11
+ 03
+ 13
+
+ Binary:
+
+ Skip Conditions: RAM(B)0 = 0
+ RAM(B)0 = 1
+ RAM(B)0 = 2
+ RAM(B)0 = 3
+
+ Description: Skip if RAM Bit is Zero
+
+*/
+
+INLINE void skmbz(cop400_state *cpustate, int bit)
+{
+ if (!BIT(RAM_R(B), bit)) cpustate->skip = 1;
+}
+
+INSTRUCTION( skmbz0 ) { skmbz(cpustate, 0); }
+INSTRUCTION( skmbz1 ) { skmbz(cpustate, 1); }
+INSTRUCTION( skmbz2 ) { skmbz(cpustate, 2); }
+INSTRUCTION( skmbz3 ) { skmbz(cpustate, 3); }
+
+/*
+
+ Mnemonic: SKT
+
+ Hex Code: 41
+ Binary: 0 1 0 0 0 0 0 1
+
+ Skip Conditions: A time-base counter carry has occurred since last test
+
+ Description: Skip on Timer
+
+*/
+
+INSTRUCTION( skt )
+{
+ if (cpustate->skt_latch)
+ {
+ cpustate->skt_latch = 0;
+ cpustate->skip = 1;
+ }
+}
+
+/***************************************************************************
+ INPUT/OUTPUT INSTRUCTIONS
+***************************************************************************/
+
+/*
+
+ Mnemonic: ING
+
+ Hex Code: 33 2A
+ Binary:
+
+ Data Flow: G -> A
+
+ Description: Input G Ports to A
+
+*/
+
+INSTRUCTION( ing )
+{
+ A = IN_G();
+}
+
+/*
+
+ Mnemonic: INL
+
+ Hex Code: 33 2E
+ Binary:
+
+ Data Flow: L7:4 -> RAM(B)
+ L3:0 -> A
+
+ Description: Input L Ports to RAM,A
+
+*/
+
+INSTRUCTION( inl )
+{
+ UINT8 L = IN_L();
+
+ RAM_W(B, L >> 4);
+ A = L & 0xF;
+}
+
+/*
+
+ Mnemonic: OBD
+
+ Hex Code: 33 3E
+ Binary:
+
+ Data Flow: Bd -> D
+
+ Description: Output Bd to D Outputs
+
+*/
+
+INSTRUCTION( obd )
+{
+ OUT_D(B & 0x0f);
+}
+
+/*
+
+ Mnemonic: OMG
+
+ Hex Code: 33 3A
+ Binary:
+
+ Data Flow: RAM(B) -> G
+
+ Description: Output RAM to G Ports
+
+*/
+
+INSTRUCTION( omg )
+{
+ WRITE_G(cpustate, RAM_R(B));
+}
+
+/*
+
+ Mnemonic: XAS
+
+ Hex Code: 4F
+ Binary: 0 1 0 0 1 1 1 1
+
+ Data Flow: A <-> SIO
+ C -> SK
+
+ Description: Exchange A with SIO
+
+*/
+
+INSTRUCTION( xas )
+{
+ UINT8 t = SIO;
+ SIO = A;
+ A = t;
+
+ SKL = C;
+}
+
+/*
+
+ Mnemonic: ININ
+
+ Hex Code: 33 28
+ Binary:
+
+ Data Flow: IN -> A
+
+ Description: Input IN Inputs to A
+
+*/
+
+INSTRUCTION( inin )
+{
+ A = IN_IN();
+}
+
+/*
+
+ Processor: COP402M
+
+ Mnemonic: ININ
+
+ Hex Code: 33 28
+ Binary:
+
+ Data Flow: IN -> A, A1 = "1"
+
+ Description: Input IN Inputs to A
+
+*/
+
+INSTRUCTION( cop402m_inin )
+{
+ A = IN_IN() | 0x02;
+}
+
+/*
+
+ Mnemonic: INIL
+
+ Hex Code: 33 29
+ Binary:
+
+ Data Flow: IL3,CKO,"0",IL0 -> A
+
+ Description: Input IL Latches to A
+
+*/
+
+INSTRUCTION( inil )
+{
+ A = (IL & 0x09) | IN_CKO() << 2;
+
+ IL = 0;
+}
+
+/*
+
+ Mnemonic: OGI
+
+ Operand: y
+ Hex Code: 33 5-
+ Binary: 0 0 1 1 0 0 1 1 0 1 0 1 y3 y2 y1 y0
+
+ Data Flow: y -> G
+
+ Description: Output to G Ports Immediate
+
+*/
+
+INSTRUCTION( ogi )
+{
+ UINT8 y = opcode & 0x0f;
+
+ WRITE_G(cpustate, y);
+}
diff --git a/trunk/src/emu/cpu/cop400/cop410ds.c b/trunk/src/emu/cpu/cop400/cop410ds.c
new file mode 100644
index 00000000000..9680c10cf0b
--- /dev/null
+++ b/trunk/src/emu/cpu/cop400/cop410ds.c
@@ -0,0 +1,350 @@
+/***************************************************************************
+
+ cop410ds.c
+
+ National Semiconductor COP410 Emulator.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#include "emu.h"
+
+CPU_DISASSEMBLE( cop410 )
+{
+ UINT8 opcode = oprom[0];
+ UINT8 next_opcode = oprom[1];
+ UINT16 address;
+ UINT32 flags = 0;
+ int bytes = 1;
+
+ if ((opcode >= 0x80 && opcode <= 0xBE) || (opcode >= 0xC0 && opcode <= 0xFE))
+ {
+ if ((pc & 0x3E0) >= 0x80 && (pc & 0x3E0) < 0x100) //JP pages 2,3
+ {
+ address = (UINT16)((pc & 0x380) | (opcode & 0x7F));
+ sprintf(buffer, "JP %x", address);
+ }
+ else
+ {
+ if ((opcode & 0xC0) == 0xC0) //JP other pages
+ {
+ address = (UINT16)((pc & 0x3C0) | (opcode & 0x3F));
+ sprintf(buffer, "JP %x", address);
+ }
+ else //JSRP
+ {
+ address = (UINT16)(0x80 | (opcode & 0x3F));
+ sprintf(buffer, "JSRP %x", address);
+ flags = DASMFLAG_STEP_OVER;
+ }
+ }
+ }
+ else if (opcode >= 0x08 && opcode <= 0x0F)
+ {
+ sprintf(buffer, "LBI 0,%u", ((opcode & 0xF) + 1) & 0xF);
+ }
+ else if (opcode >= 0x18 && opcode <= 0x1F)
+ {
+ sprintf(buffer, "LBI 1,%u", ((opcode & 0xF) + 1) & 0xF);
+ }
+ else if (opcode >= 0x28 && opcode <= 0x2F)
+ {
+ sprintf(buffer, "LBI 2,%u", ((opcode & 0xF) + 1) & 0xF);
+ }
+ else if (opcode >= 0x38 && opcode <= 0x3F)
+ {
+ sprintf(buffer, "LBI 3,%u", ((opcode & 0xF) + 1) & 0xF);
+ }
+ else if (opcode >= 0x51 && opcode <= 0x5F)
+ {
+ sprintf(buffer, "AISC %u", opcode & 0xF);
+ }
+ else if (opcode >= 0x60 && opcode <= 0x61)
+ {
+ address = ((opcode & 0x01) << 8) | next_opcode;
+ sprintf(buffer, "JMP %x", address);
+ bytes = 2;
+ }
+ else if (opcode >= 0x68 && opcode <= 0x69)
+ {
+ address = ((opcode & 0x01) << 8) | next_opcode;
+ sprintf(buffer, "JSR %x", address);
+ flags = DASMFLAG_STEP_OVER;
+ bytes = 2;
+ }
+ else if (opcode >= 0x70 && opcode <= 0x7F)
+ {
+ sprintf(buffer, "STII %u", opcode & 0xF);
+ }
+ else
+ {
+ switch (opcode)
+ {
+ case 0:
+ sprintf(buffer, "CLRA");
+ break;
+
+ case 1:
+ sprintf(buffer, "SKMBZ 0");
+ break;
+
+ case 2:
+ sprintf(buffer, "XOR");
+ break;
+
+ case 3:
+ sprintf(buffer, "SKMBZ 2");
+ break;
+
+ case 4:
+ sprintf(buffer, "XIS 0");
+ break;
+
+ case 5:
+ sprintf(buffer, "LD 0");
+ break;
+
+ case 6:
+ sprintf(buffer, "X 0");
+ break;
+
+ case 7:
+ sprintf(buffer, "XDS 0");
+ break;
+
+ case 0x11:
+ sprintf(buffer, "SKMBZ 1");
+ break;
+
+ case 0x13:
+ sprintf(buffer, "SKMBZ 3");
+ break;
+
+ case 0x14:
+ sprintf(buffer, "XIS 1");
+ break;
+
+ case 0x15:
+ sprintf(buffer, "LD 1");
+ break;
+
+ case 0x16:
+ sprintf(buffer, "X 1");
+ break;
+
+ case 0x17:
+ sprintf(buffer, "XDS 1");
+ break;
+
+ case 0x20:
+ sprintf(buffer, "SKC");
+ break;
+
+ case 0x21:
+ sprintf(buffer, "SKE");
+ break;
+
+ case 0x22:
+ sprintf(buffer, "SC");
+ break;
+
+ case 0x23:
+ bytes = 2;
+
+ if (next_opcode >= 0x80 && next_opcode <= 0xbf)
+ {
+ address = (UINT16)(next_opcode & 0x3F);
+ sprintf(buffer, "XAD %x,%x", ((address & 0x30) >> 4),address & 0x0F);
+ }
+ else
+ {
+ sprintf(buffer, "Invalid");
+ }
+ break;
+
+ case 0x24:
+ sprintf(buffer, "XIS 2");
+ break;
+
+ case 0x25:
+ sprintf(buffer, "LD 2");
+ break;
+
+ case 0x26:
+ sprintf(buffer, "X 2");
+ break;
+
+ case 0x27:
+ sprintf(buffer, "XDS 2");
+ break;
+
+ case 0x30:
+ sprintf(buffer, "ASC");
+ break;
+
+ case 0x31:
+ sprintf(buffer, "ADD");
+ break;
+
+ case 0x32:
+ sprintf(buffer, "RC");
+ break;
+
+ case 0x33:
+ bytes = 2;
+
+ if (next_opcode >= 0x60 || next_opcode <= 0x6F)
+ {
+ sprintf(buffer, "LEI %x", next_opcode & 0xF);
+ }
+ else
+ {
+ switch (next_opcode)
+ {
+ case 0x01:
+ sprintf(buffer, "SKGBZ 0");
+ break;
+
+ case 0x03:
+ sprintf(buffer, "SKGBZ 2");
+ break;
+
+ case 0x11:
+ sprintf(buffer, "SKGBZ 1");
+ break;
+
+ case 0x13:
+ sprintf(buffer, "SKGBZ 3");
+ break;
+
+ case 0x21:
+ sprintf(buffer, "SKGZ");
+ break;
+
+ case 0x2A:
+ sprintf(buffer, "ING");
+ break;
+
+ case 0x2E:
+ sprintf(buffer, "INL");
+ break;
+
+ case 0x38:
+ sprintf(buffer, "HALT");
+ break;
+
+ case 0x3A:
+ sprintf(buffer, "OMG");
+ break;
+
+ case 0x3C:
+ sprintf(buffer, "CAMQ");
+ break;
+
+ case 0x3E:
+ sprintf(buffer, "OBD");
+ break;
+
+ default:
+ sprintf(buffer, "Invalid");
+ break;
+ }
+ break;
+ }
+
+ case 0x34:
+ sprintf(buffer, "XIS 3");
+ break;
+
+ case 0x35:
+ sprintf(buffer, "LD 3");
+ break;
+
+ case 0x36:
+ sprintf(buffer, "X 3");
+ break;
+
+ case 0x37:
+ sprintf(buffer, "XDS 3");
+ break;
+
+ case 0x40:
+ sprintf(buffer, "COMP");
+ break;
+
+ case 0x42:
+ sprintf(buffer, "RMB 2");
+ break;
+
+ case 0x43:
+ sprintf(buffer, "RMB 3");
+ break;
+
+ case 0x44:
+ sprintf(buffer, "NOP");
+ break;
+
+ case 0x45:
+ sprintf(buffer, "RMB 1");
+ break;
+
+ case 0x46:
+ sprintf(buffer, "SMB 2");
+ break;
+
+ case 0x47:
+ sprintf(buffer, "SMB 1");
+ break;
+
+ case 0x48:
+ sprintf(buffer, "RET");
+ flags = DASMFLAG_STEP_OUT;
+ break;
+
+ case 0x49:
+ sprintf(buffer, "RETSK");
+ flags = DASMFLAG_STEP_OUT;
+ break;
+
+ case 0x4B:
+ sprintf(buffer, "SMB 3");
+ break;
+
+ case 0x4C:
+ sprintf(buffer, "RMB 0");
+ break;
+
+ case 0x4D:
+ sprintf(buffer, "SMB 0");
+ break;
+
+ case 0x4E:
+ sprintf(buffer, "CBA");
+ break;
+
+ case 0x4F:
+ sprintf(buffer, "XAS");
+ break;
+
+ case 0x50:
+ sprintf(buffer, "CAB");
+ break;
+
+ case 0xBF:
+ sprintf(buffer, "LQID");
+ break;
+
+ case 0xFF:
+ sprintf(buffer, "JID");
+ break;
+
+ default:
+ sprintf(buffer, "Invalid");
+ break;
+ }
+ }
+
+ return bytes | flags | DASMFLAG_SUPPORTED;
+}
diff --git a/trunk/src/emu/cpu/cop400/cop420ds.c b/trunk/src/emu/cpu/cop400/cop420ds.c
new file mode 100644
index 00000000000..9ed207ea66a
--- /dev/null
+++ b/trunk/src/emu/cpu/cop400/cop420ds.c
@@ -0,0 +1,399 @@
+/***************************************************************************
+
+ cop420ds.c
+
+ National Semiconductor COP420 Emulator.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#include "emu.h"
+
+CPU_DISASSEMBLE( cop420 )
+{
+ UINT8 opcode = oprom[0];
+ UINT8 next_opcode = oprom[1];
+ UINT16 address;
+ UINT32 flags = 0;
+ int bytes = 1;
+
+ if ((opcode >= 0x80 && opcode <= 0xBE) || (opcode >= 0xC0 && opcode <= 0xFE))
+ {
+ if ((pc & 0x3E0) >= 0x80 && (pc & 0x3E0) < 0x100) //JP pages 2,3
+ {
+ address = (UINT16)((pc & 0x380) | (opcode & 0x7F));
+ sprintf(buffer, "JP %x", address);
+ }
+ else
+ {
+ if ((opcode & 0xC0) == 0xC0) //JP other pages
+ {
+ address = (UINT16)((pc & 0x3C0) | (opcode & 0x3F));
+ sprintf(buffer, "JP %x", address);
+ }
+ else //JSRP
+ {
+ address = (UINT16)(0x80 | (opcode & 0x3F));
+ sprintf(buffer, "JSRP %x", address);
+ flags = DASMFLAG_STEP_OVER;
+ }
+ }
+ }
+ else if (opcode >= 0x08 && opcode <= 0x0F)
+ {
+ sprintf(buffer, "LBI 0,%u", ((opcode & 0xF) + 1) & 0xF);
+ }
+ else if (opcode >= 0x18 && opcode <= 0x1F)
+ {
+ sprintf(buffer, "LBI 1,%u", ((opcode & 0xF) + 1) & 0xF);
+ }
+ else if (opcode >= 0x28 && opcode <= 0x2F)
+ {
+ sprintf(buffer, "LBI 2,%u", ((opcode & 0xF) + 1) & 0xF);
+ }
+ else if (opcode >= 0x38 && opcode <= 0x3F)
+ {
+ sprintf(buffer, "LBI 3,%u", ((opcode & 0xF) + 1) & 0xF);
+ }
+ else if (opcode >= 0x51 && opcode <= 0x5F)
+ {
+ sprintf(buffer, "AISC %u", opcode & 0xF);
+ }
+ else if (opcode >= 0x60 && opcode <= 0x63)
+ {
+ address = ((opcode & 0x03) << 8) | next_opcode;
+ sprintf(buffer, "JMP %x", address);
+ bytes = 2;
+ }
+ else if (opcode >= 0x68 && opcode <= 0x6B)
+ {
+ address = ((opcode & 0x03) << 8) | next_opcode;
+ sprintf(buffer, "JSR %x", address);
+ flags = DASMFLAG_STEP_OVER;
+ bytes = 2;
+ }
+ else if (opcode >= 0x70 && opcode <= 0x7F)
+ {
+ sprintf(buffer, "STII %u", opcode & 0xF);
+ }
+ else
+ {
+ switch (opcode)
+ {
+ case 0:
+ sprintf(buffer, "CLRA");
+ break;
+
+ case 1:
+ sprintf(buffer, "SKMBZ 0");
+ break;
+
+ case 2:
+ sprintf(buffer, "XOR");
+ break;
+
+ case 3:
+ sprintf(buffer, "SKMBZ 2");
+ break;
+
+ case 4:
+ sprintf(buffer, "XIS 0");
+ break;
+
+ case 5:
+ sprintf(buffer, "LD 0");
+ break;
+
+ case 6:
+ sprintf(buffer, "X 0");
+ break;
+
+ case 7:
+ sprintf(buffer, "XDS 0");
+ break;
+
+ case 0x10:
+ sprintf(buffer, "CASC");
+ break;
+
+ case 0x11:
+ sprintf(buffer, "SKMBZ 1");
+ break;
+
+ case 0x12:
+ sprintf(buffer, "XABR");
+ break;
+
+ case 0x13:
+ sprintf(buffer, "SKMBZ 3");
+ break;
+
+ case 0x14:
+ sprintf(buffer, "XIS 1");
+ break;
+
+ case 0x15:
+ sprintf(buffer, "LD 1");
+ break;
+
+ case 0x16:
+ sprintf(buffer, "X 1");
+ break;
+
+ case 0x17:
+ sprintf(buffer, "XDS 1");
+ break;
+
+ case 0x20:
+ sprintf(buffer, "SKC");
+ break;
+
+ case 0x21:
+ sprintf(buffer, "SKE");
+ break;
+
+ case 0x22:
+ sprintf(buffer, "SC");
+ break;
+
+ case 0x23:
+ bytes = 2;
+
+ if (next_opcode <= 0x3f)
+ {
+ address = (UINT16)(next_opcode & 0x3F);
+ sprintf(buffer, "LDD %x,%x", ((address & 0x30) >> 4),address & 0x0F);
+ }
+ else if (next_opcode >= 0x80 && next_opcode <= 0xbf)
+ {
+ address = (UINT16)(next_opcode & 0x3F);
+ sprintf(buffer, "XAD %x,%x", ((address & 0x30) >> 4),address & 0x0F);
+ }
+ else
+ {
+ sprintf(buffer, "Invalid");
+ }
+ break;
+
+ case 0x24:
+ sprintf(buffer, "XIS 2");
+ break;
+
+ case 0x25:
+ sprintf(buffer, "LD 2");
+ break;
+
+ case 0x26:
+ sprintf(buffer, "X 2");
+ break;
+
+ case 0x27:
+ sprintf(buffer, "XDS 2");
+ break;
+
+ case 0x30:
+ sprintf(buffer, "ASC");
+ break;
+
+ case 0x31:
+ sprintf(buffer, "ADD");
+ break;
+
+ case 0x32:
+ sprintf(buffer, "RC");
+ break;
+
+ case 0x33:
+ bytes = 2;
+
+ if (next_opcode >= 0x50 && next_opcode <= 0x5F)
+ {
+ sprintf(buffer, "OGI %u", next_opcode & 0xF);
+ }
+ else if (next_opcode >= 0x60 && next_opcode <= 0x6F)
+ {
+ sprintf(buffer, "LEI %u", next_opcode & 0xF);
+ }
+ else if (next_opcode >= 0x80 && next_opcode <= 0x8F)
+ {
+ sprintf(buffer, "LBI 0,%u", next_opcode & 0xF);
+ }
+ else if (next_opcode >= 0x90 && next_opcode <= 0x9F)
+ {
+ sprintf(buffer, "LBI 1,%u", next_opcode & 0xF);
+ }
+ else if (next_opcode >= 0xA0 && next_opcode <= 0xAF)
+ {
+ sprintf(buffer, "LBI 2,%u", next_opcode & 0xF);
+ }
+ else if (next_opcode >= 0xB0 && next_opcode <= 0xBF)
+ {
+ sprintf(buffer, "LBI 3,%u", next_opcode & 0xF);
+ }
+ else
+ {
+ switch (next_opcode)
+ {
+ case 0x01:
+ sprintf(buffer, "SKGBZ 0");
+ break;
+
+ case 0x03:
+ sprintf(buffer, "SKGBZ 2");
+ break;
+
+ case 0x11:
+ sprintf(buffer, "SKGBZ 1");
+ break;
+
+ case 0x13:
+ sprintf(buffer, "SKGBZ 3");
+ break;
+
+ case 0x21:
+ sprintf(buffer, "SKGZ");
+ break;
+
+ case 0x28:
+ sprintf(buffer, "ININ");
+ break;
+
+ case 0x29:
+ sprintf(buffer, "INIL");
+ break;
+
+ case 0x2A:
+ sprintf(buffer, "ING");
+ break;
+
+ case 0x2C:
+ sprintf(buffer, "CQMA");
+ break;
+
+ case 0x2E:
+ sprintf(buffer, "INL");
+ break;
+
+ case 0x3A:
+ sprintf(buffer, "OMG");
+ break;
+
+ case 0x3C:
+ sprintf(buffer, "CAMQ");
+ break;
+
+ case 0x3E:
+ sprintf(buffer, "OBD");
+ break;
+
+ default:
+ sprintf(buffer, "Invalid");
+ break;
+ }
+ }
+ break;
+
+ case 0x34:
+ sprintf(buffer, "XIS 3");
+ break;
+
+ case 0x35:
+ sprintf(buffer, "LD 3");
+ break;
+
+ case 0x36:
+ sprintf(buffer, "X 3");
+ break;
+
+ case 0x37:
+ sprintf(buffer, "XDS 3");
+ break;
+
+ case 0x40:
+ sprintf(buffer, "COMP");
+ break;
+
+ case 0x41:
+ sprintf(buffer, "SKT");
+ break;
+
+ case 0x42:
+ sprintf(buffer, "RMB 2");
+ break;
+
+ case 0x43:
+ sprintf(buffer, "RMB 3");
+ break;
+
+ case 0x44:
+ sprintf(buffer, "NOP");
+ break;
+
+ case 0x45:
+ sprintf(buffer, "RMB 1");
+ break;
+
+ case 0x46:
+ sprintf(buffer, "SMB 2");
+ break;
+
+ case 0x47:
+ sprintf(buffer, "SMB 1");
+ break;
+
+ case 0x48:
+ sprintf(buffer, "RET");
+ flags = DASMFLAG_STEP_OUT;
+ break;
+
+ case 0x49:
+ sprintf(buffer, "RETSK");
+ flags = DASMFLAG_STEP_OUT;
+ break;
+
+ case 0x4A:
+ sprintf(buffer, "ADT");
+ break;
+
+ case 0x4B:
+ sprintf(buffer, "SMB 3");
+ break;
+
+ case 0x4C:
+ sprintf(buffer, "RMB 0");
+ break;
+
+ case 0x4D:
+ sprintf(buffer, "SMB 0");
+ break;
+
+ case 0x4E:
+ sprintf(buffer, "CBA");
+ break;
+
+ case 0x4F:
+ sprintf(buffer, "XAS");
+ break;
+
+ case 0x50:
+ sprintf(buffer, "CAB");
+ break;
+
+ case 0xBF:
+ sprintf(buffer, "LQID");
+ break;
+
+ case 0xFF:
+ sprintf(buffer, "JID");
+ break;
+
+ default:
+ sprintf(buffer, "Invalid");
+ break;
+ }
+ }
+
+ return bytes | flags | DASMFLAG_SUPPORTED;
+}
diff --git a/trunk/src/emu/cpu/cop400/cop440ds.c b/trunk/src/emu/cpu/cop400/cop440ds.c
new file mode 100644
index 00000000000..05e47e3bd4b
--- /dev/null
+++ b/trunk/src/emu/cpu/cop400/cop440ds.c
@@ -0,0 +1,416 @@
+/***************************************************************************
+
+ cop440ds.c
+
+ National Semiconductor COP420 Emulator.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#include "emu.h"
+
+CPU_DISASSEMBLE( cop444 )
+{
+ UINT8 opcode = oprom[0];
+ UINT8 next_opcode = oprom[1];
+ UINT16 address;
+ UINT32 flags = 0;
+ int bytes = 1;
+
+ if ((opcode >= 0x80 && opcode <= 0xBE) || (opcode >= 0xC0 && opcode <= 0xFE))
+ {
+ if ((pc & 0x3E0) >= 0x80 && (pc & 0x3E0) < 0x100) //JP pages 2,3
+ {
+ address = (UINT16)((pc & 0x380) | (opcode & 0x7F));
+ sprintf(buffer, "JP %x", address);
+ }
+ else
+ {
+ if ((opcode & 0xC0) == 0xC0) //JP other pages
+ {
+ address = (UINT16)((pc & 0x3C0) | (opcode & 0x3F));
+ sprintf(buffer, "JP %x", address);
+ }
+ else //JSRP
+ {
+ address = (UINT16)(0x80 | (opcode & 0x3F));
+ sprintf(buffer, "JSRP %x", address);
+ flags = DASMFLAG_STEP_OVER;
+ }
+ }
+ }
+ else if (opcode >= 0x08 && opcode <= 0x0F)
+ {
+ sprintf(buffer, "LBI 0,%u", ((opcode & 0xF) + 1) & 0xF);
+ }
+ else if (opcode >= 0x18 && opcode <= 0x1F)
+ {
+ sprintf(buffer, "LBI 1,%u", ((opcode & 0xF) + 1) & 0xF);
+ }
+ else if (opcode >= 0x28 && opcode <= 0x2F)
+ {
+ sprintf(buffer, "LBI 2,%u", ((opcode & 0xF) + 1) & 0xF);
+ }
+ else if (opcode >= 0x38 && opcode <= 0x3F)
+ {
+ sprintf(buffer, "LBI 3,%u", ((opcode & 0xF) + 1) & 0xF);
+ }
+ else if (opcode >= 0x51 && opcode <= 0x5F)
+ {
+ sprintf(buffer, "AISC %u", opcode & 0xF);
+ }
+ else if (opcode >= 0x60 && opcode <= 0x63)
+ {
+ address = ((opcode & 0x03) << 8) | next_opcode;
+ sprintf(buffer, "JMP %x", address);
+ bytes = 2;
+ }
+ else if (opcode >= 0x68 && opcode <= 0x6B)
+ {
+ address = ((opcode & 0x03) << 8) | next_opcode;
+ sprintf(buffer, "JSR %x", address);
+ flags = DASMFLAG_STEP_OVER;
+ bytes = 2;
+ }
+ else if (opcode >= 0x70 && opcode <= 0x7F)
+ {
+ sprintf(buffer, "STII %u", opcode & 0xF);
+ }
+ else
+ {
+ switch (opcode)
+ {
+ case 0:
+ sprintf(buffer, "CLRA");
+ break;
+
+ case 1:
+ sprintf(buffer, "SKMBZ 0");
+ break;
+
+ case 2:
+ sprintf(buffer, "XOR");
+ break;
+
+ case 3:
+ sprintf(buffer, "SKMBZ 2");
+ break;
+
+ case 4:
+ sprintf(buffer, "XIS 0");
+ break;
+
+ case 5:
+ sprintf(buffer, "LD 0");
+ break;
+
+ case 6:
+ sprintf(buffer, "X 0");
+ break;
+
+ case 7:
+ sprintf(buffer, "XDS 0");
+ break;
+
+ case 0x10:
+ sprintf(buffer, "CASC");
+ break;
+
+ case 0x11:
+ sprintf(buffer, "SKMBZ 1");
+ break;
+
+ case 0x12:
+ sprintf(buffer, "XABR");
+ break;
+
+ case 0x13:
+ sprintf(buffer, "SKMBZ 3");
+ break;
+
+ case 0x14:
+ sprintf(buffer, "XIS 1");
+ break;
+
+ case 0x15:
+ sprintf(buffer, "LD 1");
+ break;
+
+ case 0x16:
+ sprintf(buffer, "X 1");
+ break;
+
+ case 0x17:
+ sprintf(buffer, "XDS 1");
+ break;
+
+ case 0x20:
+ sprintf(buffer, "SKC");
+ break;
+
+ case 0x21:
+ sprintf(buffer, "SKE");
+ break;
+
+ case 0x22:
+ sprintf(buffer, "SC");
+ break;
+
+ case 0x23:
+ bytes = 2;
+
+ if (next_opcode <= 0x3f)
+ {
+ address = (UINT16)(next_opcode & 0x3F);
+ sprintf(buffer, "LDD %x,%x", ((address & 0x30) >> 4),address & 0x0F);
+ }
+ else if (next_opcode >= 0x80 && next_opcode <= 0xbf)
+ {
+ address = (UINT16)(next_opcode & 0x3F);
+ sprintf(buffer, "XAD %x,%x", ((address & 0x30) >> 4),address & 0x0F);
+ }
+ else
+ {
+ sprintf(buffer, "Invalid");
+ }
+ break;
+
+ case 0x24:
+ sprintf(buffer, "XIS 2");
+ break;
+
+ case 0x25:
+ sprintf(buffer, "LD 2");
+ break;
+
+ case 0x26:
+ sprintf(buffer, "X 2");
+ break;
+
+ case 0x27:
+ sprintf(buffer, "XDS 2");
+ break;
+
+ case 0x30:
+ sprintf(buffer, "ASC");
+ break;
+
+ case 0x31:
+ sprintf(buffer, "ADD");
+ break;
+
+ case 0x32:
+ sprintf(buffer, "RC");
+ break;
+
+ case 0x33:
+ bytes = 2;
+
+ if (next_opcode >= 0x50 && next_opcode <= 0x5F)
+ {
+ sprintf(buffer, "OGI %u", next_opcode & 0xF);
+ }
+ else if (next_opcode >= 0x60 && next_opcode <= 0x6F)
+ {
+ sprintf(buffer, "LEI %u", next_opcode & 0xF);
+ }
+ else if (next_opcode >= 0x80 && next_opcode <= 0x8F)
+ {
+ sprintf(buffer, "LBI 0,%u", next_opcode & 0xF);
+ }
+ else if (next_opcode >= 0x90 && next_opcode <= 0x9F)
+ {
+ sprintf(buffer, "LBI 1,%u", next_opcode & 0xF);
+ }
+ else if (next_opcode >= 0xA0 && next_opcode <= 0xAF)
+ {
+ sprintf(buffer, "LBI 2,%u", next_opcode & 0xF);
+ }
+ else if (next_opcode >= 0xB0 && next_opcode <= 0xBF)
+ {
+ sprintf(buffer, "LBI 3,%u", next_opcode & 0xF);
+ }
+ else
+ {
+ switch (next_opcode)
+ {
+ case 0x01:
+ sprintf(buffer, "SKGBZ 0");
+ break;
+
+ case 0x03:
+ sprintf(buffer, "SKGBZ 2");
+ break;
+
+ case 0x11:
+ sprintf(buffer, "SKGBZ 1");
+ break;
+
+ case 0x13:
+ sprintf(buffer, "SKGBZ 3");
+ break;
+
+ case 0x21:
+ sprintf(buffer, "SKGZ");
+ break;
+
+ case 0x28:
+ sprintf(buffer, "ININ");
+ break;
+
+ case 0x29:
+ sprintf(buffer, "INIL");
+ break;
+
+ case 0x2A:
+ sprintf(buffer, "ING");
+ break;
+
+ case 0x2C:
+ sprintf(buffer, "CQMA");
+ break;
+
+ case 0x2E:
+ sprintf(buffer, "INL");
+ break;
+
+ case 0x2F:
+ sprintf(buffer, "CTMA");
+ break;
+
+ case 0x38:
+ sprintf(buffer, "HALT");
+ break;
+
+ case 0x39:
+ sprintf(buffer, "IT");
+ break;
+
+ case 0x3A:
+ sprintf(buffer, "OMG");
+ break;
+
+ case 0x3C:
+ sprintf(buffer, "CAMQ");
+ break;
+
+ case 0x3E:
+ sprintf(buffer, "OBD");
+ break;
+
+ case 0x3F:
+ sprintf(buffer, "CAMT");
+ break;
+
+
+ default:
+ sprintf(buffer, "Invalid");
+ break;
+ }
+ }
+ break;
+
+ case 0x34:
+ sprintf(buffer, "XIS 3");
+ break;
+
+ case 0x35:
+ sprintf(buffer, "LD 3");
+ break;
+
+ case 0x36:
+ sprintf(buffer, "X 3");
+ break;
+
+ case 0x37:
+ sprintf(buffer, "XDS 3");
+ break;
+
+ case 0x40:
+ sprintf(buffer, "COMP");
+ break;
+
+ case 0x41:
+ sprintf(buffer, "SKT");
+ break;
+
+ case 0x42:
+ sprintf(buffer, "RMB 2");
+ break;
+
+ case 0x43:
+ sprintf(buffer, "RMB 3");
+ break;
+
+ case 0x44:
+ sprintf(buffer, "NOP");
+ break;
+
+ case 0x45:
+ sprintf(buffer, "RMB 1");
+ break;
+
+ case 0x46:
+ sprintf(buffer, "SMB 2");
+ break;
+
+ case 0x47:
+ sprintf(buffer, "SMB 1");
+ break;
+
+ case 0x48:
+ sprintf(buffer, "RET");
+ flags = DASMFLAG_STEP_OUT;
+ break;
+
+ case 0x49:
+ sprintf(buffer, "RETSK");
+ flags = DASMFLAG_STEP_OUT;
+ break;
+
+ case 0x4A:
+ sprintf(buffer, "ADT");
+ break;
+
+ case 0x4B:
+ sprintf(buffer, "SMB 3");
+ break;
+
+ case 0x4C:
+ sprintf(buffer, "RMB 0");
+ break;
+
+ case 0x4D:
+ sprintf(buffer, "SMB 0");
+ break;
+
+ case 0x4E:
+ sprintf(buffer, "CBA");
+ break;
+
+ case 0x4F:
+ sprintf(buffer, "XAS");
+ break;
+
+ case 0x50:
+ sprintf(buffer, "CAB");
+ break;
+
+ case 0xBF:
+ sprintf(buffer, "LQID");
+ break;
+
+ case 0xFF:
+ sprintf(buffer, "JID");
+ break;
+
+ default:
+ sprintf(buffer, "Invalid");
+ break;
+ }
+ }
+
+ return bytes | flags | DASMFLAG_SUPPORTED;
+}
diff --git a/trunk/src/emu/cpu/cosmac/cosdasm.c b/trunk/src/emu/cpu/cosmac/cosdasm.c
new file mode 100644
index 00000000000..aa5dbe4a8fd
--- /dev/null
+++ b/trunk/src/emu/cpu/cosmac/cosdasm.c
@@ -0,0 +1,173 @@
+/*****************************************************************************
+ *
+ * disasm.c
+ * portable cosmac cdp1802 emulator interface
+ *
+ * Copyright Peter Trauner, all rights reserved.
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * peter.trauner@jk.uni-linz.ac.at
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ *****************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+
+#include "cosmac.h"
+
+typedef enum
+{
+ Ill,
+ Imm,
+ Imp,
+ Imp2, // lownibble contains register number
+ Imp3, // bit 0,1,2 1..7 contains n0,n1,n2 level
+ Low, // only low byte of address specified
+ Abs
+} Adr;
+
+static const struct { const char *mnemonic; Adr adr; } table[]={
+ { "IDL", Imp }, { "LDN", Imp2},{ 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+
+ { "INC", Imp2},{ 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+
+ { "DEC", Imp2},{ 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+
+
+ { "BR", Low }, { "BQ", Low }, { "BZ", Low }, { "BDF", Low },
+ { "B1", Low }, { "B2", Low }, { "B3", Low }, { "B4", Low },
+ { "SKP", Low }, { "BNQ", Low }, { "BNZ", Low }, { "BNF", Low },
+ { "BN1", Low }, { "BN2", Low }, { "BN3", Low }, { "BN4", Low },
+
+ { "LDA", Imp2},{ 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+
+ { "STR", Imp2},{ 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+
+ { "IRX", Imp } ,{ "OUT", Imp3},{ 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+ { 0 } ,{ "INP", Imp3},{ 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+
+ { "RET", Imp }, { "DIS", Imp }, { "LDXA", Imp }, { "STXD", Imp },
+ { "ADC", Imp }, { "SDB", Imp }, { "SHRC", Imp }, { "SMB", Imp },
+ { "SAV", Imp }, { "MARK", Imp }, { "REQ", Imp }, { "SEQ", Imp },
+ { "ADCI", Imm }, { "SDBI", Imm }, { "SHLC", Imp }, { "SMBI", Imm },
+
+
+ { "GLO", Imp2},{ 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+
+ { "GHI", Imp2},{ 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+
+ { "PLO", Imp2},{ 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+
+ { "PHI", Imp2},{ 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+
+ { "LBR", Abs }, { "LBQ", Abs }, { "LBZ", Abs }, { "LBDF", Abs },
+ { "NOP", Imp }, { "LSNQ", Imp }, { "LSNZ", Imp }, { "LSNF", Imp },
+ { "LSKP", Imp }, { "LBNQ", Abs }, { "LBNZ", Abs }, { "LBNF", Abs },
+ { "LSIE", Imp }, { "LSQ", Imp }, { "LSZ", Imp }, { "LSDF", Imp },
+
+ { "SEP", Imp2},{ 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+
+ { "SEX", Imp2},{ 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
+
+ { "LDX", Imp }, { "OR", Imp }, { "AND", Imp }, { "XOR", Imp },
+ { "ADD", Imp }, { "SD", Imp }, { "SHR", Imp }, { "SM", Imp },
+ { "LDI", Imm }, { "ORI", Imm }, { "ANI", Imm }, { "XRI", Imm },
+ { "ADI", Imm }, { "SDI", Imm }, { "SHL", Imp }, { "SMI", Imm },
+
+};
+
+CPU_DISASSEMBLE( cosmac )
+{
+ UINT32 flags = 0;
+ int oldpc = pc;
+ int oper;
+ UINT16 absolut;
+ oldpc&=0xffff;
+ pc=oldpc;
+ oper=oprom[pc++ - oldpc];
+
+ switch(oper&0xf0) {
+ case 0:
+ if (oper==0) {
+ sprintf(buffer,"%-5s",table[oper].mnemonic);
+ } else {
+ sprintf(buffer,"%-5sR%.1x",table[(oper&0xf0)|1].mnemonic, oper&0x0f);
+ }
+ break;
+ case 0xd0:
+ flags = DASMFLAG_STEP_OVER;
+ /* fall through */
+ case 0x10:
+ case 0x20:
+ case 0x40:
+ case 0x50:
+ case 0x80:
+ case 0x90:
+ case 0xa0:
+ case 0xb0:
+ case 0xe0:
+ sprintf(buffer,"%-5sR%.1x",table[oper&0xf0].mnemonic, oper&0x0f);
+ break;
+ default:
+ switch(oper&0xf8) {
+ case 0x60:
+ if (oper==0x60) {
+ sprintf(buffer,"%-5s",table[oper].mnemonic);
+ } else {
+ sprintf(buffer,"%-5s%d",table[(oper&0xf8)|1].mnemonic, oper&0x7);
+ }
+ break;
+ case 0x68:
+ sprintf(buffer,"%-5s%d",table[(oper&0xf8)|1].mnemonic, oper&0x7);
+ break;
+ default:
+ switch (table[oper].adr) {
+ case Imp:
+ sprintf(buffer,"%-5s",table[oper].mnemonic);
+ if (oper == 0x70 || oper == 0x71)
+ flags = DASMFLAG_STEP_OUT;
+ break;
+ case Imm:
+ sprintf(buffer,"%-5s#%.2x",table[oper].mnemonic,oprom[pc++ - oldpc]);
+ break;
+ case Low:
+ absolut=oprom[pc++ - oldpc];
+ absolut|=pc&0xff00;
+ sprintf(buffer,"%-5s%.4x",table[oper].mnemonic,absolut);
+ break;
+ case Abs:
+ absolut=oprom[pc++ - oldpc]<<8;
+ absolut|=oprom[pc++ - oldpc];
+ sprintf(buffer,"%-5s%.4x",table[oper].mnemonic,absolut);
+ break;
+ default:
+ sprintf(buffer,"%-5s%.2x","ill",oper);
+ break;
+ }
+ break;
+ }
+ break;
+ }
+
+ return (pc-oldpc) | flags | DASMFLAG_SUPPORTED;
+}
diff --git a/trunk/src/emu/cpu/cosmac/cosmac.c b/trunk/src/emu/cpu/cosmac/cosmac.c
new file mode 100644
index 00000000000..89bc3423ce3
--- /dev/null
+++ b/trunk/src/emu/cpu/cosmac/cosmac.c
@@ -0,0 +1,1146 @@
+/**********************************************************************
+
+ RCA "COSMAC" CPU emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "cosmac.h"
+
+
+/*
+
+ TODO:
+
+ - divide clock by 8
+ - min cycles -> 2 and 3
+
+*/
+
+// permit our enums to be saved
+ALLOW_SAVE_TYPE(cosmac_device::cosmac_mode);
+ALLOW_SAVE_TYPE(cosmac_device::cosmac_state);
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+#define CLOCKS_RESET 8
+#define CLOCKS_INIT 8 // really 9, but needs to be 8 to synchronize cdp1861 video timings
+#define CLOCKS_FETCH 8
+#define CLOCKS_EXECUTE 8
+#define CLOCKS_DMA 8
+#define CLOCKS_INTERRUPT 8
+
+const cosmac_state_code COSMAC_STATE_CODE[] =
+{
+ COSMAC_STATE_CODE_S0_FETCH, // COSMAC_STATE_0_FETCH
+ COSMAC_STATE_CODE_S1_EXECUTE, // COSMAC_STATE_1_RESET
+ COSMAC_STATE_CODE_S1_EXECUTE, // COSMAC_STATE_1_INIT
+ COSMAC_STATE_CODE_S1_EXECUTE, // COSMAC_STATE_1_EXECUTE
+ COSMAC_STATE_CODE_S2_DMA, // COSMAC_STATE_2_DMA_IN
+ COSMAC_STATE_CODE_S2_DMA, // COSMAC_STATE_2_DMA_OUT
+ COSMAC_STATE_CODE_S3_INTERRUPT // COSMAC_STATE_3_INT
+};
+
+
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+#define OPCODE_R(addr) read_opcode(addr)
+#define RAM_R(addr) read_byte(addr)
+#define RAM_W(addr, data) write_byte(addr, data)
+#define IO_R(addr) read_io_byte(addr)
+#define IO_W(addr, data) write_io_byte(addr, data)
+
+#define P m_p
+#define X m_x
+#define D m_d
+#define B m_b
+#define T m_t
+#define R m_r
+#define DF m_df
+#define IE m_ie
+#define Q m_q
+#define N m_n
+#define I m_i
+#define EF m_ef
+
+#define GET_FLAGS() ((m_df << 2) | (m_ie << 1) | m_q)
+
+#define SET_FLAGS(v) do { \
+ m_df = BIT(v, 2); \
+ m_ie = BIT(v, 1); \
+ m_q = BIT(v, 0); \
+ } while (0);
+
+
+
+//**************************************************************************
+// STATIC OPCODE TABLES
+//**************************************************************************
+
+const cosmac_device::ophandler cosmac_device::s_opcodetable[256] =
+{
+ &cosmac_device::idl, &cosmac_device::ldn, &cosmac_device::ldn, &cosmac_device::ldn,
+ &cosmac_device::ldn, &cosmac_device::ldn, &cosmac_device::ldn, &cosmac_device::ldn,
+ &cosmac_device::ldn, &cosmac_device::ldn, &cosmac_device::ldn, &cosmac_device::ldn,
+ &cosmac_device::ldn, &cosmac_device::ldn, &cosmac_device::ldn, &cosmac_device::ldn,
+
+ &cosmac_device::inc, &cosmac_device::inc, &cosmac_device::inc, &cosmac_device::inc,
+ &cosmac_device::inc, &cosmac_device::inc, &cosmac_device::inc, &cosmac_device::inc,
+ &cosmac_device::inc, &cosmac_device::inc, &cosmac_device::inc, &cosmac_device::inc,
+ &cosmac_device::inc, &cosmac_device::inc, &cosmac_device::inc, &cosmac_device::inc,
+
+ &cosmac_device::dec, &cosmac_device::dec, &cosmac_device::dec, &cosmac_device::dec,
+ &cosmac_device::dec, &cosmac_device::dec, &cosmac_device::dec, &cosmac_device::dec,
+ &cosmac_device::dec, &cosmac_device::dec, &cosmac_device::dec, &cosmac_device::dec,
+ &cosmac_device::dec, &cosmac_device::dec, &cosmac_device::dec, &cosmac_device::dec,
+
+ &cosmac_device::br, &cosmac_device::bq, &cosmac_device::bz, &cosmac_device::bdf,
+ &cosmac_device::b, &cosmac_device::b, &cosmac_device::b, &cosmac_device::b,
+ &cosmac_device::nbr, &cosmac_device::bnq, &cosmac_device::bnz, &cosmac_device::bnf,
+ &cosmac_device::bn, &cosmac_device::bn, &cosmac_device::bn, &cosmac_device::bn,
+
+ &cosmac_device::lda, &cosmac_device::lda, &cosmac_device::lda, &cosmac_device::lda,
+ &cosmac_device::lda, &cosmac_device::lda, &cosmac_device::lda, &cosmac_device::lda,
+ &cosmac_device::lda, &cosmac_device::lda, &cosmac_device::lda, &cosmac_device::lda,
+ &cosmac_device::lda, &cosmac_device::lda, &cosmac_device::lda, &cosmac_device::lda,
+
+ &cosmac_device::str, &cosmac_device::str, &cosmac_device::str, &cosmac_device::str,
+ &cosmac_device::str, &cosmac_device::str, &cosmac_device::str, &cosmac_device::str,
+ &cosmac_device::str, &cosmac_device::str, &cosmac_device::str, &cosmac_device::str,
+ &cosmac_device::str, &cosmac_device::str, &cosmac_device::str, &cosmac_device::str,
+
+ &cosmac_device::irx, &cosmac_device::out, &cosmac_device::out, &cosmac_device::out,
+ &cosmac_device::out, &cosmac_device::out, &cosmac_device::out, &cosmac_device::out,
+ &cosmac_device::inp, &cosmac_device::inp, &cosmac_device::inp, &cosmac_device::inp,
+ &cosmac_device::inp, &cosmac_device::inp, &cosmac_device::inp, &cosmac_device::inp,
+
+ &cosmac_device::ret, &cosmac_device::dis, &cosmac_device::ldxa, &cosmac_device::stxd,
+ &cosmac_device::adc, &cosmac_device::sdb, &cosmac_device::shrc, &cosmac_device::smb,
+ &cosmac_device::sav, &cosmac_device::mark, &cosmac_device::req, &cosmac_device::seq,
+ &cosmac_device::adci, &cosmac_device::sdbi, &cosmac_device::shlc, &cosmac_device::smbi,
+
+ &cosmac_device::glo, &cosmac_device::glo, &cosmac_device::glo, &cosmac_device::glo,
+ &cosmac_device::glo, &cosmac_device::glo, &cosmac_device::glo, &cosmac_device::glo,
+ &cosmac_device::glo, &cosmac_device::glo, &cosmac_device::glo, &cosmac_device::glo,
+ &cosmac_device::glo, &cosmac_device::glo, &cosmac_device::glo, &cosmac_device::glo,
+
+ &cosmac_device::ghi, &cosmac_device::ghi, &cosmac_device::ghi, &cosmac_device::ghi,
+ &cosmac_device::ghi, &cosmac_device::ghi, &cosmac_device::ghi, &cosmac_device::ghi,
+ &cosmac_device::ghi, &cosmac_device::ghi, &cosmac_device::ghi, &cosmac_device::ghi,
+ &cosmac_device::ghi, &cosmac_device::ghi, &cosmac_device::ghi, &cosmac_device::ghi,
+
+ &cosmac_device::plo, &cosmac_device::plo, &cosmac_device::plo, &cosmac_device::plo,
+ &cosmac_device::plo, &cosmac_device::plo, &cosmac_device::plo, &cosmac_device::plo,
+ &cosmac_device::plo, &cosmac_device::plo, &cosmac_device::plo, &cosmac_device::plo,
+ &cosmac_device::plo, &cosmac_device::plo, &cosmac_device::plo, &cosmac_device::plo,
+
+ &cosmac_device::phi, &cosmac_device::phi, &cosmac_device::phi, &cosmac_device::phi,
+ &cosmac_device::phi, &cosmac_device::phi, &cosmac_device::phi, &cosmac_device::phi,
+ &cosmac_device::phi, &cosmac_device::phi, &cosmac_device::phi, &cosmac_device::phi,
+ &cosmac_device::phi, &cosmac_device::phi, &cosmac_device::phi, &cosmac_device::phi,
+
+ &cosmac_device::lbr, &cosmac_device::lbq, &cosmac_device::lbz, &cosmac_device::lbdf,
+ &cosmac_device::nop, &cosmac_device::lsnq, &cosmac_device::lsnz, &cosmac_device::lsnf,
+ &cosmac_device::nlbr, &cosmac_device::lbnq, &cosmac_device::lbnz, &cosmac_device::lbnf,
+ &cosmac_device::lsie, &cosmac_device::lsq, &cosmac_device::lsz, &cosmac_device::lsdf,
+
+ &cosmac_device::sep, &cosmac_device::sep, &cosmac_device::sep, &cosmac_device::sep,
+ &cosmac_device::sep, &cosmac_device::sep, &cosmac_device::sep, &cosmac_device::sep,
+ &cosmac_device::sep, &cosmac_device::sep, &cosmac_device::sep, &cosmac_device::sep,
+ &cosmac_device::sep, &cosmac_device::sep, &cosmac_device::sep, &cosmac_device::sep,
+
+ &cosmac_device::sex, &cosmac_device::sex, &cosmac_device::sex, &cosmac_device::sex,
+ &cosmac_device::sex, &cosmac_device::sex, &cosmac_device::sex, &cosmac_device::sex,
+ &cosmac_device::sex, &cosmac_device::sex, &cosmac_device::sex, &cosmac_device::sex,
+ &cosmac_device::sex, &cosmac_device::sex, &cosmac_device::sex, &cosmac_device::sex,
+
+ &cosmac_device::ldx, &cosmac_device::_or, &cosmac_device::_and, &cosmac_device::_xor,
+ &cosmac_device::add, &cosmac_device::sd, &cosmac_device::shr, &cosmac_device::sm,
+ &cosmac_device::ldi, &cosmac_device::ori, &cosmac_device::ani, &cosmac_device::xri,
+ &cosmac_device::adi, &cosmac_device::sdi, &cosmac_device::shl, &cosmac_device::smi
+};
+
+
+
+//**************************************************************************
+// DEVICE INTERFACE
+//**************************************************************************
+
+// device type definition
+const device_type COSMAC = &device_creator<cosmac_device>;
+
+
+//-------------------------------------------------
+// cosmac_device - constructor
+//-------------------------------------------------
+
+cosmac_device::cosmac_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : cpu_device(mconfig, COSMAC, "COSMAC", tag, owner, clock),
+ m_program_config("program", ENDIANNESS_LITTLE, 8, 16),
+ m_io_config("io", ENDIANNESS_LITTLE, 8, 3),
+ m_op(0),
+ m_state(COSMAC_STATE_1_RESET),
+ m_mode(COSMAC_MODE_RESET),
+ m_irq(0),
+ m_dmain(0),
+ m_dmaout(0),
+ m_program(NULL),
+ m_io(NULL),
+ m_direct(NULL)
+{
+ for (int i = 0; i < 4; i++)
+ EF[i] = 0;
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void cosmac_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const cosmac_interface *intf = reinterpret_cast<const cosmac_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<cosmac_interface *>(this) = *intf;
+
+ // or error out if none provided
+ else
+ {
+ fatalerror("COSMAC_INTERFACE for cpu '%s' not defined!", tag());
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - start up the device
+//-------------------------------------------------
+
+void cosmac_device::device_start()
+{
+ // get our address spaces
+ m_program = space(AS_PROGRAM);
+ m_direct = &m_program->direct();
+ m_io = space(AS_IO);
+
+ // register our state for the debugger
+ state_add(STATE_GENPC, "GENPC", m_pc).callimport().callexport().noshow();
+ state_add(STATE_GENFLAGS, "GENFLAGS", m_flagsio).mask(0x7).callimport().callexport().noshow().formatstr("%3s");
+
+ state_add(COSMAC_P, "P", m_p).mask(0xf);
+ state_add(COSMAC_X, "X", m_x).mask(0xf);
+ state_add(COSMAC_D, "D", m_d);
+ state_add(COSMAC_B, "B", m_b);
+ state_add(COSMAC_T, "T", m_t);
+
+ state_add(COSMAC_I, "I", m_i).mask(0xf);
+ state_add(COSMAC_N, "N", m_n).mask(0xf);
+
+ astring tempstr;
+ for (int regnum = 0; regnum < 16; regnum++)
+ state_add(COSMAC_R0 + regnum, tempstr.format("R%x", regnum), m_r[regnum]);
+
+ state_add(COSMAC_DF, "DF", m_df).mask(0x1).noshow();
+ state_add(COSMAC_IE, "IE", m_ie).mask(0x1).noshow();
+ state_add(COSMAC_Q, "Q", m_q).mask(0x1).noshow();
+
+ // resolve callbacks
+ m_in_wait_func.resolve(m_in_wait_cb, *this);
+ m_in_clear_func.resolve(m_in_clear_cb, *this);
+ m_in_ef_func[0].resolve(m_in_ef1_cb, *this);
+ m_in_ef_func[1].resolve(m_in_ef2_cb, *this);
+ m_in_ef_func[2].resolve(m_in_ef3_cb, *this);
+ m_in_ef_func[3].resolve(m_in_ef4_cb, *this);
+ m_out_q_func.resolve(m_out_q_cb, *this);
+ m_in_dma_func.resolve(m_in_dma_cb, *this);
+ m_out_dma_func.resolve(m_out_dma_cb, *this);
+ m_out_sc_func = m_out_sc_cb;
+ m_out_tpa_func.resolve(m_out_tpa_cb, *this);
+ m_out_tpb_func.resolve(m_out_tpb_cb, *this);
+
+ // register our state for saving
+ save_item(NAME(m_op));
+ save_item(NAME(m_flagsio));
+ save_item(NAME(m_state));
+ save_item(NAME(m_mode));
+ save_item(NAME(m_pmode));
+ save_item(NAME(m_irq));
+ save_item(NAME(m_dmain));
+ save_item(NAME(m_dmaout));
+ save_item(NAME(m_ef));
+ save_item(NAME(m_d));
+ save_item(NAME(m_b));
+ save_item(NAME(m_r));
+ save_item(NAME(m_p));
+ save_item(NAME(m_x));
+ save_item(NAME(m_n));
+ save_item(NAME(m_i));
+ save_item(NAME(m_t));
+ save_item(NAME(m_df));
+ save_item(NAME(m_ie));
+ save_item(NAME(m_q));
+ save_item(NAME(m_icount));
+
+ // set our instruction counter
+ m_icountptr = &m_icount;
+}
+
+
+//-------------------------------------------------
+// device_reset - reset the device
+//-------------------------------------------------
+
+void cosmac_device::device_reset()
+{
+}
+
+
+//-------------------------------------------------
+// memory_space_config - return the configuration
+// of the specified address space, or NULL if
+// the space doesn't exist
+//-------------------------------------------------
+
+const address_space_config *cosmac_device::memory_space_config(address_spacenum spacenum) const
+{
+ switch (spacenum)
+ {
+ case AS_PROGRAM:
+ return &m_program_config;
+
+ case AS_IO:
+ return &m_io_config;
+
+ default:
+ return NULL;
+ }
+}
+
+
+//-------------------------------------------------
+// state_import - import state into the device,
+// after it has been set
+//-------------------------------------------------
+
+void cosmac_device::state_import(const device_state_entry &entry)
+{
+ switch (entry.index())
+ {
+ case STATE_GENPC:
+ R[P] = m_pc;
+ break;
+
+ case STATE_GENFLAGS:
+ SET_FLAGS(m_flagsio);
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// state_export - export state from the device,
+// to a known location where it can be read
+//-------------------------------------------------
+
+void cosmac_device::state_export(const device_state_entry &entry)
+{
+ switch (entry.index())
+ {
+ case STATE_GENPC:
+ m_pc = R[P];
+ break;
+
+ case STATE_GENFLAGS:
+ m_flagsio = GET_FLAGS();
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// state_string_export - export state as a string
+// for the debugger
+//-------------------------------------------------
+
+void cosmac_device::state_string_export(const device_state_entry &entry, astring &string)
+{
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ string.printf("%c%c%c",
+ m_df ? 'D' : '.',
+ m_ie ? 'I' : '.',
+ m_q ? 'Q' : '.');
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// disasm_min_opcode_bytes - return the length
+// of the shortest instruction, in bytes
+//-------------------------------------------------
+
+UINT32 cosmac_device::disasm_min_opcode_bytes() const
+{
+ return 1;
+}
+
+
+//-------------------------------------------------
+// disasm_max_opcode_bytes - return the length
+// of the longest instruction, in bytes
+//-------------------------------------------------
+
+UINT32 cosmac_device::disasm_max_opcode_bytes() const
+{
+ return 3;
+}
+
+
+//-------------------------------------------------
+// disasm_disassemble - call the disassembly
+// helper function
+//-------------------------------------------------
+
+offs_t cosmac_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
+{
+ extern CPU_DISASSEMBLE( cosmac );
+ return CPU_DISASSEMBLE_NAME(cosmac)(NULL, buffer, pc, oprom, opram, 0);
+}
+
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// read_opcode - read an opcode at the given address
+//-------------------------------------------------
+
+inline UINT8 cosmac_device::read_opcode(offs_t pc)
+{
+ return m_direct->read_decrypted_byte(pc);
+}
+
+
+//-------------------------------------------------
+// read_byte - read a byte at the given address
+//-------------------------------------------------
+
+inline UINT8 cosmac_device::read_byte(offs_t address)
+{
+ return m_program->read_byte(address);
+}
+
+
+//-------------------------------------------------
+// read_io_byte - read an I/O byte at the given
+// address
+//-------------------------------------------------
+
+inline UINT8 cosmac_device::read_io_byte(offs_t address)
+{
+ return m_io->read_byte(address);
+}
+
+
+//-------------------------------------------------
+// write_byte - write a byte at the given address
+//-------------------------------------------------
+
+inline void cosmac_device::write_byte(offs_t address, UINT8 data)
+{
+ m_program->write_byte(address, data);
+}
+
+
+//-------------------------------------------------
+// write_io_byte - write an I/O byte at the given
+// address
+//-------------------------------------------------
+
+inline void cosmac_device::write_io_byte(offs_t address, UINT8 data)
+{
+ m_io->write_byte(address, data);
+}
+
+
+
+//**************************************************************************
+// CORE EXECUTION
+//**************************************************************************
+
+//-------------------------------------------------
+// get_memory_address - get current memory address
+//-------------------------------------------------
+
+offs_t cosmac_device::get_memory_address()
+{
+ // this is valid for INP/OUT opcodes
+ return R[X];
+}
+
+//-------------------------------------------------
+// execute_min_cycles - return minimum number of
+// cycles it takes for one instruction to execute
+//-------------------------------------------------
+
+UINT32 cosmac_device::execute_min_cycles() const
+{
+ return 8 * 2;
+}
+
+
+//-------------------------------------------------
+// execute_max_cycles - return maximum number of
+// cycles it takes for one instruction to execute
+//-------------------------------------------------
+
+UINT32 cosmac_device::execute_max_cycles() const
+{
+ return 8 * 3;
+}
+
+
+//-------------------------------------------------
+// execute_input_lines - return the number of
+// input/interrupt lines
+//-------------------------------------------------
+
+UINT32 cosmac_device::execute_input_lines() const
+{
+ return 7;
+}
+
+
+//-------------------------------------------------
+// execute_set_input -
+//-------------------------------------------------
+
+void cosmac_device::execute_set_input(int inputnum, int state)
+{
+ switch (inputnum)
+ {
+ case COSMAC_INPUT_LINE_INT:
+ m_irq = state;
+ break;
+
+ case COSMAC_INPUT_LINE_DMAIN:
+ m_dmain = state;
+ break;
+
+ case COSMAC_INPUT_LINE_DMAOUT:
+ m_dmaout = state;
+ break;
+
+ case COSMAC_INPUT_LINE_EF1:
+ case COSMAC_INPUT_LINE_EF2:
+ case COSMAC_INPUT_LINE_EF3:
+ case COSMAC_INPUT_LINE_EF4:
+ EF[inputnum - COSMAC_INPUT_LINE_EF1] = state;
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// execute_run -
+//-------------------------------------------------
+
+void cosmac_device::execute_run()
+{
+ do
+ {
+ sample_wait_clear();
+
+ switch (m_mode)
+ {
+ case COSMAC_MODE_LOAD:
+ if (m_pmode == COSMAC_MODE_RESET)
+ {
+ m_pmode = COSMAC_MODE_LOAD;
+
+ // execute initialization cycle
+ m_state = COSMAC_STATE_1_INIT;
+ run();
+
+ // next state is IDLE
+ m_state = COSMAC_STATE_1_EXECUTE;
+ }
+ else
+ {
+ // idle
+ m_op = 0;
+ I = 0;
+ N = 0;
+ run();
+ }
+ break;
+
+ case COSMAC_MODE_RESET:
+ m_state = COSMAC_STATE_1_RESET;
+ run();
+ break;
+
+ case COSMAC_MODE_PAUSE:
+ m_icount--;
+ break;
+
+ case COSMAC_MODE_RUN:
+ switch (m_pmode)
+ {
+ case COSMAC_MODE_LOAD:
+ // RUN mode cannot be initiated from LOAD mode
+ logerror("COSMAC '%s' Tried to initiate RUN mode from LOAD mode\n", tag());
+ m_mode = COSMAC_MODE_LOAD;
+ break;
+
+ case COSMAC_MODE_RESET:
+ m_pmode = COSMAC_MODE_RUN;
+ m_state = COSMAC_STATE_1_INIT;
+ run();
+ break;
+
+ case COSMAC_MODE_PAUSE:
+ m_pmode = COSMAC_MODE_RUN;
+ m_state = COSMAC_STATE_0_FETCH;
+ run();
+ break;
+
+ case COSMAC_MODE_RUN:
+ run();
+ break;
+ }
+ break;
+ }
+ }
+ while (m_icount > 0);
+}
+
+
+//-------------------------------------------------
+// run - run the CPU state machine
+//-------------------------------------------------
+
+inline void cosmac_device::run()
+{
+ output_state_code();
+
+ switch (m_state)
+ {
+ case COSMAC_STATE_0_FETCH:
+ fetch_instruction();
+ break;
+
+ case COSMAC_STATE_1_RESET:
+ reset();
+ debug();
+ break;
+
+ case COSMAC_STATE_1_INIT:
+ initialize();
+ debug();
+ break;
+
+ case COSMAC_STATE_1_EXECUTE:
+ sample_ef_lines();
+ execute_instruction();
+ debug();
+ break;
+
+ case COSMAC_STATE_2_DMA_IN:
+ dma_input();
+ break;
+
+ case COSMAC_STATE_2_DMA_OUT:
+ dma_output();
+ break;
+
+ case COSMAC_STATE_3_INT:
+ interrupt();
+ debug();
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// debug - hook into debugger
+//-------------------------------------------------
+
+inline void cosmac_device::debug()
+{
+ if (device_t::machine().debug_flags & DEBUG_FLAG_ENABLED)
+ {
+ debugger_instruction_hook(this, R[P]);
+ }
+}
+
+
+//-------------------------------------------------
+// sample_wait_clear - sample wait/clear lines
+//-------------------------------------------------
+
+inline void cosmac_device::sample_wait_clear()
+{
+ int wait = m_in_wait_func();
+ int clear = m_in_clear_func();
+
+ m_pmode = m_mode;
+ m_mode = (cosmac_mode) ((clear << 1) | wait);
+}
+
+
+//-------------------------------------------------
+// sample_ef_lines - sample EF input lines
+//-------------------------------------------------
+
+inline void cosmac_device::sample_ef_lines()
+{
+ for (int i = 0; i < 4; i++)
+ {
+ if (!m_in_ef_func[i].isnull())
+ {
+ EF[i] = m_in_ef_func[i]();
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// output_state_code - output state code
+//-------------------------------------------------
+
+inline void cosmac_device::output_state_code()
+{
+ if (m_out_sc_func != NULL)
+ {
+ m_out_sc_func(this, COSMAC_STATE_CODE[m_state]);
+ }
+}
+
+
+//-------------------------------------------------
+// set_q_flag - set Q flag state and output it
+//-------------------------------------------------
+
+inline void cosmac_device::set_q_flag(int state)
+{
+ Q = state;
+
+ m_out_q_func(Q);
+}
+
+
+//-------------------------------------------------
+// fetch_instruction - fetch instruction from
+// the program memory
+//-------------------------------------------------
+
+inline void cosmac_device::fetch_instruction()
+{
+ // instruction fetch
+ m_op = read_opcode(R[P]);
+ R[P]++;
+
+ I = m_op >> 4;
+ N = m_op & 0x0f;
+
+ m_icount -= CLOCKS_FETCH;
+
+ m_state = COSMAC_STATE_1_EXECUTE;
+}
+
+
+//-------------------------------------------------
+// reset - handle reset state
+//-------------------------------------------------
+
+inline void cosmac_device::reset()
+{
+ m_op = 0;
+ I = 0;
+ N = 0;
+ Q = 0;
+ IE = 1;
+
+ m_icount -= CLOCKS_RESET;
+}
+
+
+//-------------------------------------------------
+// initialize - handle initialization state
+//-------------------------------------------------
+
+inline void cosmac_device::initialize()
+{
+ X = 0;
+ P = 0;
+ R[0] = 0;
+
+ m_icount -= CLOCKS_INIT;
+
+ if (m_dmain)
+ {
+ m_state = COSMAC_STATE_2_DMA_IN;
+ }
+ else if (m_dmaout)
+ {
+ m_state = COSMAC_STATE_2_DMA_OUT;
+ }
+ else
+ {
+ m_state = COSMAC_STATE_0_FETCH;
+ }
+}
+
+
+//-------------------------------------------------
+// execute_instruction - execute instruction
+//-------------------------------------------------
+
+inline void cosmac_device::execute_instruction()
+{
+ // parse the instruction
+ (this->*s_opcodetable[m_op])();
+
+ m_icount -= CLOCKS_EXECUTE;
+
+ if (m_dmain)
+ {
+ m_state = COSMAC_STATE_2_DMA_IN;
+ }
+ else if (m_dmaout)
+ {
+ m_state = COSMAC_STATE_2_DMA_OUT;
+ }
+ else if (IE && m_irq)
+ {
+ m_state = COSMAC_STATE_3_INT;
+ }
+ else if ((I > 0) || (N > 0)) // not idling
+ {
+ m_state = COSMAC_STATE_0_FETCH;
+ }
+}
+
+
+//-------------------------------------------------
+// dma_input - handle DMA input state
+//-------------------------------------------------
+
+inline void cosmac_device::dma_input()
+{
+ RAM_W(R[0], m_in_dma_func(R[0]));
+
+ R[0]++;
+
+ m_icount -= CLOCKS_DMA;
+
+ if (m_dmain)
+ {
+ m_state = COSMAC_STATE_2_DMA_IN;
+ }
+ else if (m_dmaout)
+ {
+ m_state = COSMAC_STATE_2_DMA_OUT;
+ }
+ else if (IE && m_irq)
+ {
+ m_state = COSMAC_STATE_3_INT;
+ }
+ else if (m_mode == COSMAC_MODE_LOAD)
+ {
+ m_state = COSMAC_STATE_1_EXECUTE;
+ }
+ else
+ {
+ m_state = COSMAC_STATE_0_FETCH;
+ }
+}
+
+
+//-------------------------------------------------
+// dma_output - handle DMA output state
+//-------------------------------------------------
+
+inline void cosmac_device::dma_output()
+{
+ m_out_dma_func(R[0], RAM_R(R[0]));
+
+ R[0]++;
+
+ m_icount -= CLOCKS_DMA;
+
+ if (m_dmain)
+ {
+ m_state = COSMAC_STATE_2_DMA_IN;
+ }
+ else if (m_dmaout)
+ {
+ m_state = COSMAC_STATE_2_DMA_OUT;
+ }
+ else if (IE && m_irq)
+ {
+ m_state = COSMAC_STATE_3_INT;
+ }
+ else
+ {
+ m_state = COSMAC_STATE_0_FETCH;
+ }
+}
+
+
+//-------------------------------------------------
+// interrupt - handle interrupt state
+//-------------------------------------------------
+
+inline void cosmac_device::interrupt()
+{
+ T = (X << 4) | P;
+ X = 2;
+ P = 1;
+ IE = 0;
+
+ m_icount -= CLOCKS_INTERRUPT;
+
+ if (m_dmain)
+ {
+ m_state = COSMAC_STATE_2_DMA_IN;
+ }
+ else if (m_dmaout)
+ {
+ m_state = COSMAC_STATE_2_DMA_OUT;
+ }
+ else
+ {
+ m_state = COSMAC_STATE_0_FETCH;
+ }
+}
+
+
+
+//**************************************************************************
+// OPCODE IMPLEMENTATIONS
+//**************************************************************************
+
+// memory reference opcode handlers
+void cosmac_device::ldn() { D = RAM_R(R[N]); }
+void cosmac_device::lda() { D = RAM_R(R[N]); R[N]++; }
+void cosmac_device::ldx() { D = RAM_R(R[X]); }
+void cosmac_device::ldxa() { D = RAM_R(R[X]); R[X]++; }
+void cosmac_device::ldi() { D = RAM_R(R[P]); R[P]++; }
+void cosmac_device::str() { RAM_W(R[N], D); }
+void cosmac_device::stxd() { RAM_W(R[X], D); R[X]--; }
+
+// register operations opcode handlers
+void cosmac_device::inc() { R[N]++; }
+void cosmac_device::dec() { R[N]--; }
+void cosmac_device::irx() { R[X]++; }
+void cosmac_device::glo() { D = R[N] & 0xff; }
+void cosmac_device::plo() { R[N] = (R[N] & 0xff00) | D; }
+void cosmac_device::ghi() { D = R[N] >> 8; }
+void cosmac_device::phi() { R[N] = (D << 8) | (R[N] & 0xff); }
+
+// logic operations opcode handlers
+void cosmac_device::_or() { D = RAM_R(R[X]) | D; }
+void cosmac_device::ori() { D = RAM_R(R[P]) | D; R[P]++; }
+void cosmac_device::_xor() { D = RAM_R(R[X]) ^ D; }
+void cosmac_device::xri() { D = RAM_R(R[P]) ^ D; R[P]++; }
+void cosmac_device::_and() { D = RAM_R(R[X]) & D; }
+void cosmac_device::ani() { D = RAM_R(R[P]) & D; R[P]++; }
+void cosmac_device::shr() { DF = BIT(D, 0); D >>= 1; }
+void cosmac_device::shrc() { int b = DF; DF = BIT(D, 0); D >>= 1; D |= b << 7; }
+void cosmac_device::shl() { DF = BIT(D, 7); D <<= 1; }
+void cosmac_device::shlc() { int b = DF; DF = BIT(D, 7); D <<= 1; D |= b; }
+
+// arithmetic operations opcode handlers
+void cosmac_device::add(int left, int right)
+{
+ int result = left + right;
+
+ D = result & 0xff;
+ DF = result > 0xff;
+}
+
+void cosmac_device::add_with_carry(int left, int right)
+{
+ int result = left + right + DF;
+
+ D = result & 0xff;
+ DF = result > 0xff;
+}
+
+void cosmac_device::subtract(int left, int right)
+{
+ int result = left + (right ^ 0xff) + 1;
+
+ D = result & 0xff;
+ DF = result > 0xff;
+}
+
+void cosmac_device::subtract_with_borrow(int left, int right)
+{
+ int result = left + (right ^ 0xff) + DF;
+
+ D = result & 0xff;
+ DF = result > 0xff;
+}
+
+void cosmac_device::add() { add(RAM_R(R[X]), D); }
+void cosmac_device::adi() { add(RAM_R(R[P]), D); R[P]++; }
+void cosmac_device::adc() { add_with_carry(RAM_R(R[X]), D); }
+void cosmac_device::adci() { add_with_carry(RAM_R(R[P]), D); R[P]++; }
+void cosmac_device::sd() { subtract(RAM_R(R[X]), D); }
+void cosmac_device::sdi() { subtract(RAM_R(R[P]), D); R[P]++; }
+void cosmac_device::sdb() { subtract_with_borrow(RAM_R(R[X]), D); }
+void cosmac_device::sdbi() { subtract_with_borrow(RAM_R(R[P]), D); R[P]++; }
+void cosmac_device::sm() { subtract(D, RAM_R(R[X])); }
+void cosmac_device::smi() { subtract(D, RAM_R(R[P])); R[P]++; }
+void cosmac_device::smb() { subtract_with_borrow(D, RAM_R(R[X])); }
+void cosmac_device::smbi() { subtract_with_borrow(D, RAM_R(R[P])); R[P]++; }
+
+// short branch instructions opcode handlers
+void cosmac_device::short_branch(int taken)
+{
+ if (taken)
+ {
+ R[P] = (R[P] & 0xff00) | OPCODE_R(R[P]);
+ }
+ else
+ {
+ R[P]++;
+ }
+}
+
+void cosmac_device::br() { short_branch(1); }
+void cosmac_device::nbr() { short_branch(0); }
+void cosmac_device::bz() { short_branch(D == 0); }
+void cosmac_device::bnz() { short_branch(D != 0); }
+void cosmac_device::bdf() { short_branch(DF); }
+void cosmac_device::bnf() { short_branch(!DF); }
+void cosmac_device::bq() { short_branch(Q); }
+void cosmac_device::bnq() { short_branch(!Q); }
+void cosmac_device::b() { short_branch(EF[N & 0x03]); }
+void cosmac_device::bn() { short_branch(!EF[N & 0x03]); }
+
+// long branch instructions opcode handlers
+void cosmac_device::long_branch(int taken)
+{
+ if (taken)
+ {
+ // S1#1
+ B = OPCODE_R(R[P]++);
+
+ // S1#2
+ R[P] = (B << 8) | OPCODE_R(R[P]);
+ }
+ else
+ {
+ // S1#1
+ R[P]++;
+
+ // S1#2
+ R[P]++;
+ }
+
+ m_icount -= CLOCKS_EXECUTE;
+}
+
+void cosmac_device::lbr() { long_branch(1); }
+void cosmac_device::nlbr() { long_skip(1); }
+void cosmac_device::lbz() { long_branch(D == 0); }
+void cosmac_device::lbnz() { long_branch(D != 0); }
+void cosmac_device::lbdf() { long_branch(DF); }
+void cosmac_device::lbnf() { long_branch(!DF); }
+void cosmac_device::lbq() { long_branch(Q); }
+void cosmac_device::lbnq() { long_branch(!Q); }
+
+// skip instructions opcode handlers
+void cosmac_device::long_skip(int taken)
+{
+ if (taken)
+ {
+ // S1#1
+ R[P]++;
+
+ // S1#2
+ R[P]++;
+ }
+
+ m_icount -= CLOCKS_EXECUTE;
+}
+
+void cosmac_device::lsz() { long_skip(D == 0); }
+void cosmac_device::lsnz() { long_skip(D != 0); }
+void cosmac_device::lsdf() { long_skip(DF); }
+void cosmac_device::lsnf() { long_skip(!DF); }
+void cosmac_device::lsq() { long_skip(Q); }
+void cosmac_device::lsnq() { long_skip(!Q); }
+void cosmac_device::lsie() { long_skip(IE); }
+
+// control instructions opcode handlers
+void cosmac_device::idl() { /* idle */ }
+void cosmac_device::nop() { m_icount -= CLOCKS_EXECUTE; }
+void cosmac_device::sep() { P = N; }
+void cosmac_device::sex() { X = N; }
+void cosmac_device::seq() { set_q_flag(1); }
+void cosmac_device::req() { set_q_flag(0); }
+void cosmac_device::sav() { RAM_W(R[X], T); }
+
+void cosmac_device::mark()
+{
+ T = (X << 4) | P;
+ RAM_W(R[2], T);
+ X = P;
+ R[2]--;
+}
+
+void cosmac_device::return_from_interrupt(int ie)
+{
+ UINT8 data = RAM_R(R[X]);
+ R[X]++;
+ P = data & 0xf;
+ X = data >> 4;
+ IE = ie;
+}
+
+void cosmac_device::ret() { return_from_interrupt(1); }
+void cosmac_device::dis() { return_from_interrupt(0); }
+
+// input/output byte transfer opcode handlers
+void cosmac_device::out() { IO_W(N, RAM_R(R[X])); R[X]++; }
+
+/*
+
+ A note about INP 0 (0x68) from Tom Pittman's "A Short Course in Programming":
+
+ If you look carefully, you will notice that we never studied the opcode "68".
+ That's because it is not a defined 1802 instruction. It has the form of an INP
+ instruction, but 0 is not a defined input port, so if you execute it (try it!)
+ nothing is input. "Nothing" is the answer to a question; it is data, and something
+ will be put in the accumulator and memory (so now you know what the computer uses
+ to mean "nothing").
+
+ However, since the result of the "68" opcode is unpredictable, it should not be
+ used in your programs. In fact, "68" is the first byte of a series of additional
+ instructions for the 1804 and 1805 microprocessors.
+
+ http://www.ittybittycomputers.com/IttyBitty/ShortCor.htm
+
+*/
+void cosmac_device::inp() { D = IO_R(N & 0x07); RAM_W(R[X], D); }
diff --git a/trunk/src/emu/cpu/cosmac/cosmac.h b/trunk/src/emu/cpu/cosmac/cosmac.h
new file mode 100644
index 00000000000..16e9201a041
--- /dev/null
+++ b/trunk/src/emu/cpu/cosmac/cosmac.h
@@ -0,0 +1,385 @@
+/**********************************************************************
+
+ RCA "COSMAC" CPU emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************
+ _____ _____
+ CLOCK 1 |* \_/ | 40 Vdd
+ _WAIT 2 | | 39 _XTAL
+ _CLEAR 3 | | 38 _DMA IN
+ Q 4 | | 37 _DMA OUT
+ SC1 5 | | 36 _INTERRUPT
+ SC0 6 | | 35 _MWR
+ _MRD 7 | | 34 TPA
+ BUS 7 8 | | 33 TPB
+ BUS 6 9 | CDP1802 | 32 MA7
+ BUS 5 10 | CDP1803 | 31 MA6
+ BUS 4 11 | CDP1804 | 30 MA5
+ BUS 3 12 | CDP1805 | 29 MA4
+ BUS 2 13 | CDP1806 | 28 MA3
+ BUS 1 14 | | 27 MA2
+ BUS 0 15 | | 26 MA1
+ * 16 | | 25 MA0
+ N2 17 | | 24 _EF1
+ N1 18 | | 23 _EF2
+ N0 19 | | 22 _EF3
+ Vss 20 |_____________| 21 _EF4
+
+
+ Type Internal ROM Internal RAM Timer Pin 16 (*)
+ ------------------------------------------------------------------
+ CDP1802 none none no Vcc
+ CDP1803 ? ? ? ?
+ CDP1804 2 KB 64 bytes yes ?
+ CDP1805 none 64 bytes yes _ME
+ CDP1806 none none yes Vdd
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __COSMAC_H__
+#define __COSMAC_H__
+
+
+//**************************************************************************
+// ENUMERATIONS
+//**************************************************************************
+
+// registers
+enum
+{
+ COSMAC_P,
+ COSMAC_X,
+ COSMAC_D,
+ COSMAC_B,
+ COSMAC_T,
+ COSMAC_R0,
+ COSMAC_R1,
+ COSMAC_R2,
+ COSMAC_R3,
+ COSMAC_R4,
+ COSMAC_R5,
+ COSMAC_R6,
+ COSMAC_R7,
+ COSMAC_R8,
+ COSMAC_R9,
+ COSMAC_Ra,
+ COSMAC_Rb,
+ COSMAC_Rc,
+ COSMAC_Rd,
+ COSMAC_Re,
+ COSMAC_Rf,
+ COSMAC_DF,
+ COSMAC_IE,
+ COSMAC_Q,
+ COSMAC_N,
+ COSMAC_I,
+ COSMAC_SC
+};
+
+
+// input lines
+enum
+{
+ COSMAC_INPUT_LINE_INT = 0,
+ COSMAC_INPUT_LINE_DMAIN,
+ COSMAC_INPUT_LINE_DMAOUT,
+ COSMAC_INPUT_LINE_EF1,
+ COSMAC_INPUT_LINE_EF2,
+ COSMAC_INPUT_LINE_EF3,
+ COSMAC_INPUT_LINE_EF4,
+};
+
+
+// state codes
+enum cosmac_state_code
+{
+ COSMAC_STATE_CODE_S0_FETCH = 0,
+ COSMAC_STATE_CODE_S1_EXECUTE,
+ COSMAC_STATE_CODE_S2_DMA,
+ COSMAC_STATE_CODE_S3_INTERRUPT
+};
+
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+typedef void (*cosmac_out_sc_func)(device_t *device, cosmac_state_code sc);
+#define COSMAC_SC_WRITE(name) void name(device_t *device, cosmac_state_code sc)
+
+
+// ======================> cosmac_interface
+
+struct cosmac_interface
+{
+ devcb_read_line m_in_wait_cb;
+ devcb_read_line m_in_clear_cb;
+ devcb_read_line m_in_ef1_cb;
+ devcb_read_line m_in_ef2_cb;
+ devcb_read_line m_in_ef3_cb;
+ devcb_read_line m_in_ef4_cb;
+ devcb_write_line m_out_q_cb;
+ devcb_read8 m_in_dma_cb;
+ devcb_write8 m_out_dma_cb;
+ cosmac_out_sc_func m_out_sc_cb;
+ devcb_write_line m_out_tpa_cb;
+ devcb_write_line m_out_tpb_cb;
+};
+
+#define COSMAC_INTERFACE(name) \
+ const cosmac_interface (name) =
+
+
+// ======================> cosmac_device
+
+class cosmac_device : public cpu_device,
+ public cosmac_interface
+{
+public:
+ // construction/destruction
+ cosmac_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // public interfaces
+ offs_t get_memory_address();
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete();
+ virtual void device_start();
+ virtual void device_reset();
+
+ // device_execute_interface overrides
+ virtual UINT32 execute_min_cycles() const;
+ virtual UINT32 execute_max_cycles() const;
+ virtual UINT32 execute_input_lines() const;
+ virtual void execute_run();
+ virtual void execute_set_input(int inputnum, int state);
+
+ // device_memory_interface overrides
+ virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const;
+
+ // device_state_interface overrides
+ virtual void state_import(const device_state_entry &entry);
+ virtual void state_export(const device_state_entry &entry);
+ virtual void state_string_export(const device_state_entry &entry, astring &string);
+
+ // device_disasm_interface overrides
+ virtual UINT32 disasm_min_opcode_bytes() const;
+ virtual UINT32 disasm_max_opcode_bytes() const;
+ virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);
+
+ // helpers
+ inline UINT8 read_opcode(offs_t pc);
+ inline UINT8 read_byte(offs_t address);
+ inline UINT8 read_io_byte(offs_t address);
+ inline void write_byte(offs_t address, UINT8 data);
+ inline void write_io_byte(offs_t address, UINT8 data);
+
+ // execution logic
+ inline void run();
+ inline void debug();
+ inline void reset();
+ inline void initialize();
+ inline void fetch_instruction();
+ inline void fetch_instruction_debug();
+ inline void execute_instruction();
+ inline void dma_input();
+ inline void dma_output();
+ inline void interrupt();
+ inline void sample_wait_clear();
+ inline void sample_ef_lines();
+ inline void output_state_code();
+ inline void set_q_flag(int state);
+
+ // arithmetic handlers
+ void add(int left, int right);
+ void add_with_carry(int left, int right);
+ void subtract(int left, int right);
+ void subtract_with_borrow(int left, int right);
+
+ // condition handlers
+ void short_branch(int taken);
+ void long_branch(int taken);
+ void long_skip(int taken);
+
+ // control handlers
+ void return_from_interrupt(int ie);
+
+ // memory reference opcode handlers
+ void ldn();
+ void lda();
+ void ldx();
+ void ldxa();
+ void ldi();
+ void str();
+ void stxd();
+
+ // register operations opcode handlers
+ void inc();
+ void dec();
+ void irx();
+ void glo();
+ void plo();
+ void ghi();
+ void phi();
+
+ // logic operations opcode handlers
+ void _or();
+ void ori();
+ void _xor();
+ void xri();
+ void _and();
+ void ani();
+ void shr();
+ void shrc();
+ void shl();
+ void shlc();
+
+ // arithmetic operations opcode handlers
+ void add();
+ void adi();
+ void adc();
+ void adci();
+ void sd();
+ void sdi();
+ void sdb();
+ void sdbi();
+ void sm();
+ void smi();
+ void smb();
+ void smbi();
+
+ // short branch instructions opcode handlers
+ void br();
+ void nbr();
+ void bz();
+ void bnz();
+ void bdf();
+ void bnf();
+ void bq();
+ void bnq();
+ void b();
+ void bn();
+
+ // long branch instructions opcode handlers
+ void lbr();
+ void nlbr();
+ void lbz();
+ void lbnz();
+ void lbdf();
+ void lbnf();
+ void lbq();
+ void lbnq();
+
+ // skip instructions opcode handlers
+ void lsz();
+ void lsnz();
+ void lsdf();
+ void lsnf();
+ void lsq();
+ void lsnq();
+ void lsie();
+
+ // control instructions opcode handlers
+ void idl();
+ void nop();
+ void sep();
+ void sex();
+ void seq();
+ void req();
+ void sav();
+ void mark();
+ void ret();
+ void dis();
+
+ // input/output byte transfer opcode handlers
+ void out();
+ void inp();
+
+ const address_space_config m_program_config;
+ const address_space_config m_io_config;
+
+ // device callbacks
+ devcb_resolved_read_line m_in_wait_func;
+ devcb_resolved_read_line m_in_clear_func;
+ devcb_resolved_read_line m_in_ef_func[4];
+ devcb_resolved_write_line m_out_q_func;
+ devcb_resolved_read8 m_in_dma_func;
+ devcb_resolved_write8 m_out_dma_func;
+ cosmac_out_sc_func m_out_sc_func;
+ devcb_resolved_write_line m_out_tpa_func;
+ devcb_resolved_write_line m_out_tpb_func;
+
+ // control modes
+ enum cosmac_mode
+ {
+ COSMAC_MODE_LOAD = 0,
+ COSMAC_MODE_RESET,
+ COSMAC_MODE_PAUSE,
+ COSMAC_MODE_RUN
+ };
+
+ // execution states
+ enum cosmac_state
+ {
+ COSMAC_STATE_0_FETCH = 0,
+ COSMAC_STATE_1_RESET,
+ COSMAC_STATE_1_INIT,
+ COSMAC_STATE_1_EXECUTE,
+ COSMAC_STATE_2_DMA_IN,
+ COSMAC_STATE_2_DMA_OUT,
+ COSMAC_STATE_3_INT
+ };
+
+ // internal state
+ UINT16 m_pc; // fake program counter
+ UINT8 m_op; // current opcode
+ UINT8 m_flagsio; // flags storage for state saving
+ cosmac_state m_state; // state
+ cosmac_mode m_mode; // control mode
+ cosmac_mode m_pmode; // previous control mode
+ int m_irq; // interrupt request
+ int m_dmain; // DMA input request
+ int m_dmaout; // DMA output request
+ int m_ef[4]; // external flags
+
+ // registers
+ UINT8 m_d; // data register (accumulator)
+ UINT8 m_b; // auxiliary holding register
+ UINT16 m_r[16]; // scratchpad registers
+ UINT8 m_p; // designates which register is Program Counter
+ UINT8 m_x; // designates which register is Data Pointer
+ UINT8 m_n; // low-order instruction digit
+ UINT8 m_i; // high-order instruction digit
+ UINT8 m_t; // temporary register
+
+ // flags
+ int m_df; // data flag (ALU carry)
+ int m_ie; // interrupt enable
+ int m_q; // output flip-flop
+
+ // internal stuff
+ int m_icount;
+ address_space * m_program;
+ address_space * m_io;
+ direct_read_data * m_direct;
+
+ // opcode/condition tables
+ typedef void (cosmac_device::*ophandler)();
+
+ static const ophandler s_opcodetable[256];
+};
+
+
+// device type definition
+extern const device_type COSMAC;
+
+
+#endif /* __COSMAC_H__ */
diff --git a/trunk/src/emu/cpu/cp1610/1610dasm.c b/trunk/src/emu/cpu/cp1610/1610dasm.c
new file mode 100644
index 00000000000..573c63f4dba
--- /dev/null
+++ b/trunk/src/emu/cpu/cp1610/1610dasm.c
@@ -0,0 +1,1488 @@
+#include "emu.h"
+#include "debugger.h"
+#include "cp1610.h"
+
+CPU_DISASSEMBLE( cp1610 )
+{
+ UINT16 oprom16[4]={ (oprom[0] << 8) | oprom[1], (oprom[2] << 8) | oprom[3], (oprom[4] << 8) | oprom[5], (oprom[6] << 8) | oprom[7] };
+ UINT16 op = oprom16[0]; UINT16 subop;
+ UINT16 ea, ea1, ea2;
+ unsigned size = 1;
+// const char *sym, *sym2;
+
+ switch( op )
+ {
+ /* opcode bitmask */
+ case 0x00: /* 0 000 000 000 */
+// sym = set_ea_info( 0, 12, EA_UINT8, EA_ZPG_RD );
+ sprintf(buffer, "HLT");
+ break;
+ case 0x001: /* 0 000 000 001 */
+ subop = oprom16[1];
+ switch (subop & 0x3f8)
+ {
+ case 0x280: /* 1 010 000 xxx */
+ case 0x288: /* 1 010 001 xxx */
+ case 0x290: /* 1 010 010 xxx */
+ case 0x298: /* 1 010 011 xxx */
+ case 0x2a0: /* 1 010 100 xxx */
+ case 0x2a8: /* 1 010 101 xxx */
+ case 0x2b0: /* 1 010 110 xxx */
+ sprintf(buffer,"MVI@ (R%01d), R%01d",(subop&0x38)>>3,subop&7);
+ size += 1;
+ break;
+ case 0x2b8: /* 1 010 111 xxx */
+ ea1 = oprom16[2];
+ ea2 = oprom16[3];
+ ea = ((ea2&0xff)<<8) | (ea1&0xff);
+ sprintf(buffer,"MVII #%04X, R%01d",ea,subop&7);
+ size += 3;
+ break;
+ case 0x2c0: /* 1 011 000 xxx */
+ case 0x2c8: /* 1 011 001 xxx */
+ case 0x2d0: /* 1 011 010 xxx */
+ case 0x2d8: /* 1 011 011 xxx */
+ case 0x2e0: /* 1 011 100 xxx */
+ case 0x2e8: /* 1 011 101 xxx */
+ case 0x2f0: /* 1 011 110 xxx */
+ sprintf(buffer,"ADD@ (R%01d), R%01d",(subop&0x38)>>3,subop&7);
+ size += 1;
+ break;
+ case 0x2f8: /* 1 011 111 xxx */
+ ea1 = oprom16[2];
+ ea2 = oprom16[3];
+ ea = ((ea2&0xff)<<8) | (ea1&0xff);
+ sprintf(buffer,"ADDI #%04X, R%01d",ea,subop&7);
+ size += 3;
+ break;
+ case 0x300: /* 1 100 000 xxx */
+ case 0x308: /* 1 100 001 xxx */
+ case 0x310: /* 1 100 010 xxx */
+ case 0x318: /* 1 100 011 xxx */
+ case 0x320: /* 1 100 100 xxx */
+ case 0x328: /* 1 100 101 xxx */
+ case 0x330: /* 1 100 110 xxx */
+ sprintf(buffer,"SUB@ (R%01d), R%01d",(subop&0x38)>>3,subop&7);
+ size += 1;
+ break;
+ case 0x338: /* 1 100 111 xxx */
+ ea1 = oprom16[2];
+ ea2 = oprom16[3];
+ ea = ((ea2&0xff)<<8) | (ea1&0xff);
+ sprintf(buffer,"SUBI #%04X, R%01d",ea,subop&7);
+ size += 3;
+ break;
+ case 0x340: /* 1 101 000 xxx */
+ case 0x348: /* 1 101 001 xxx */
+ case 0x350: /* 1 101 010 xxx */
+ case 0x358: /* 1 101 011 xxx */
+ case 0x360: /* 1 101 100 xxx */
+ case 0x368: /* 1 101 101 xxx */
+ case 0x370: /* 1 101 110 xxx */
+ sprintf(buffer,"CMP@ (R%01d), R%01d",(subop&0x38)>>3,subop&7);
+ size += 1;
+ break;
+ case 0x378: /* 1 101 111 xxx */
+ ea1 = oprom16[2];
+ ea2 = oprom16[3];
+ ea = ((ea2&0xff)<<8) | (ea1&0xff);
+ sprintf(buffer,"CMPI #%04X, R%01d",ea,subop&7);
+ size += 3;
+ break;
+ case 0x380: /* 1 110 000 xxx */
+ case 0x388: /* 1 110 001 xxx */
+ case 0x390: /* 1 110 010 xxx */
+ case 0x398: /* 1 110 011 xxx */
+ case 0x3a0: /* 1 110 100 xxx */
+ case 0x3a8: /* 1 110 101 xxx */
+ case 0x3b0: /* 1 110 110 xxx */
+ sprintf(buffer,"AND@ (R%01d), R%01d",(subop&0x38)>>3,subop&7);
+ size += 1;
+ break;
+ case 0x3b8: /* 1 110 111 xxx */
+ ea1 = oprom16[2];
+ ea2 = oprom16[3];
+ ea = ((ea2&0xff)<<8) | (ea1&0xff);
+ sprintf(buffer,"ANDI #%04X, R%01d",ea,subop&7);
+ size += 3;
+ break;
+ case 0x3c0: /* 1 111 000 xxx */
+ case 0x3c8: /* 1 111 001 xxx */
+ case 0x3d0: /* 1 111 010 xxx */
+ case 0x3d8: /* 1 111 011 xxx */
+ case 0x3e0: /* 1 111 100 xxx */
+ case 0x3e8: /* 1 111 101 xxx */
+ case 0x3f0: /* 1 111 110 xxx */
+ sprintf(buffer,"XOR@ (R%01d), R%01d",(subop&0x38)>>3,subop&7);
+ size += 1;
+ break;
+ case 0x3f8: /* 1 111 111 xxx */
+ ea1 = oprom16[2];
+ ea2 = oprom16[3];
+ ea = ((ea2&0xff)<<8) | (ea1&0xff);
+ sprintf(buffer,"XORI #%04X, R%01d",ea,subop&7);
+ size += 3;
+ break;
+ default:
+ size += 1;
+ sprintf(buffer, "SDBD ????");
+ }
+ break;
+ case 0x002: /* 0 000 000 010 */
+ sprintf(buffer, "EIS");
+ break;
+ case 0x003: /* 0 000 000 011 */
+ sprintf(buffer, "DIS");
+ break;
+ case 0x004: /* 0 000 000 100 */
+ size += 2;
+ ea1 = oprom16[1];
+ ea2 = oprom16[2];
+ ea = ((ea1<<8)&0xfc00) + (ea2&0x3ff);
+ if ((ea1&0x300) == 0x300)
+ {
+ //?? set direct address
+ switch(ea1 & 0x03)
+ {
+ case 0:
+ sprintf(buffer, "J %04X",ea);
+ break;
+ case 1:
+ sprintf(buffer, "JE %04X",ea);
+ break;
+ case 2:
+ sprintf(buffer, "JD %04X",ea);
+ break;
+ case 3:
+ sprintf(buffer, "????");
+ break;
+ }
+ }
+ else
+ {
+ //?? set R?, return address
+ switch(ea1 & 0x03)
+ {
+ case 0:
+ sprintf(buffer, "JSR R%01d,%04X",((ea1&0x300)>>8)+4,ea);
+ break;
+ case 1:
+ sprintf(buffer, "JSRE R%01d,%04X",((ea1&0x300)>>8)+4,ea);
+ break;
+ case 2:
+ sprintf(buffer, "JSRD R%01d,%04X",((ea1&0x300)>>8)+4,ea);
+ break;
+ case 3:
+ sprintf(buffer, "????");
+ break;
+ }
+ }
+ break;
+ case 0x005: /* 0 000 000 101 */
+ sprintf(buffer, "TCI");
+ break;
+ case 0x006: /* 0 000 000 110 */
+ sprintf(buffer, "CLRC");
+ break;
+ case 0x007: /* 0 000 000 111 */
+ sprintf(buffer, "SETC");
+ break;
+ case 0x008: /* 0 000 001 000 */
+ case 0x009: /* 0 000 001 001 */
+ case 0x00a: /* 0 000 001 010 */
+ case 0x00b: /* 0 000 001 011 */
+ case 0x00c: /* 0 000 001 100 */
+ case 0x00d: /* 0 000 001 101 */
+ case 0x00e: /* 0 000 001 110 */
+ case 0x00f: /* 0 000 001 111 */
+ sprintf(buffer, "INCR R%01d",op&0x7);
+ break;
+ case 0x010: /* 0 000 010 000 */
+ case 0x011: /* 0 000 010 001 */
+ case 0x012: /* 0 000 010 010 */
+ case 0x013: /* 0 000 010 011 */
+ case 0x014: /* 0 000 010 100 */
+ case 0x015: /* 0 000 010 101 */
+ case 0x016: /* 0 000 010 110 */
+ case 0x017: /* 0 000 010 111 */
+ sprintf(buffer, "DECR R%01d",op&0x7);
+ break;
+ case 0x018: /* 0 000 011 000 */
+ case 0x019: /* 0 000 011 001 */
+ case 0x01a: /* 0 000 011 010 */
+ case 0x01b: /* 0 000 011 011 */
+ case 0x01c: /* 0 000 011 100 */
+ case 0x01d: /* 0 000 011 101 */
+ case 0x01e: /* 0 000 011 110 */
+ case 0x01f: /* 0 000 011 111 */
+ sprintf(buffer, "COMR R%01d",op&0x7);
+ break;
+ case 0x020: /* 0 000 100 000 */
+ case 0x021: /* 0 000 100 001 */
+ case 0x022: /* 0 000 100 010 */
+ case 0x023: /* 0 000 100 011 */
+ case 0x024: /* 0 000 100 100 */
+ case 0x025: /* 0 000 100 101 */
+ case 0x026: /* 0 000 100 110 */
+ case 0x027: /* 0 000 100 111 */
+ sprintf(buffer, "NEGR R%01d",op&0x7);
+ break;
+ case 0x028: /* 0 000 101 000 */
+ case 0x029: /* 0 000 101 001 */
+ case 0x02a: /* 0 000 101 010 */
+ case 0x02b: /* 0 000 101 011 */
+ case 0x02c: /* 0 000 101 100 */
+ case 0x02d: /* 0 000 101 101 */
+ case 0x02e: /* 0 000 101 110 */
+ case 0x02f: /* 0 000 101 111 */
+ sprintf(buffer, "ADCR R%01d",op&0x7);
+ break;
+ case 0x030: /* 0 000 110 000 */
+ case 0x031: /* 0 000 110 001 */
+ case 0x032: /* 0 000 110 010 */
+ case 0x033: /* 0 000 110 011 */
+ sprintf(buffer, "GSWD R%01d",op&0x3);
+ break;
+ case 0x034: /* 0 000 110 100 */
+ case 0x035: /* 0 000 110 101 */
+ sprintf(buffer, "NOP (%01d)",op&0x1); //???
+ break;
+ case 0x036: /* 0 000 110 110 */
+ case 0x037: /* 0 000 110 111 */
+ sprintf(buffer, "SIN");
+ break;
+ case 0x038: /* 0 000 111 000 */
+ case 0x039: /* 0 000 111 001 */
+ case 0x03a: /* 0 000 111 010 */
+ case 0x03b: /* 0 000 111 011 */
+ case 0x03c: /* 0 000 111 100 */
+ case 0x03d: /* 0 000 111 101 */
+ case 0x03e: /* 0 000 111 110 */
+ case 0x03f: /* 0 000 111 111 */
+ sprintf(buffer, "RSWD R%01d",op&0x7);
+ break;
+ case 0x040: /* 0 001 000 000 */
+ case 0x041: /* 0 001 000 001 */
+ case 0x042: /* 0 001 000 010 */
+ case 0x043: /* 0 001 000 011 */
+ sprintf(buffer, "SWAP R%01d,1",op&0x3);
+ break;
+ case 0x044: /* 0 001 000 100 */
+ case 0x045: /* 0 001 000 101 */
+ case 0x046: /* 0 001 000 110 */
+ case 0x047: /* 0 001 000 111 */
+ sprintf(buffer, "SWAP R%01d,2",op&0x3);
+ break;
+ case 0x048: /* 0 001 001 000 */
+ case 0x049: /* 0 001 001 001 */
+ case 0x04a: /* 0 001 001 010 */
+ case 0x04b: /* 0 001 001 011 */
+ sprintf(buffer, "SLL R%01d,1",op&0x3);
+ break;
+ case 0x04c: /* 0 001 001 100 */
+ case 0x04d: /* 0 001 001 101 */
+ case 0x04e: /* 0 001 001 110 */
+ case 0x04f: /* 0 001 001 111 */
+ sprintf(buffer, "SLL R%01d,2",op&0x3);
+ break;
+ case 0x050: /* 0 001 010 000 */
+ case 0x051: /* 0 001 010 001 */
+ case 0x052: /* 0 001 010 010 */
+ case 0x053: /* 0 001 010 011 */
+ sprintf(buffer, "RLC R%01d,1",op&0x3);
+ break;
+ case 0x054: /* 0 001 010 100 */
+ case 0x055: /* 0 001 010 101 */
+ case 0x056: /* 0 001 010 110 */
+ case 0x057: /* 0 001 010 111 */
+ sprintf(buffer, "RLC R%01d,2",op&0x3);
+ break;
+ case 0x058: /* 0 001 011 000 */
+ case 0x059: /* 0 001 011 001 */
+ case 0x05a: /* 0 001 011 010 */
+ case 0x05b: /* 0 001 011 011 */
+ sprintf(buffer, "SLLC R%01d,1",op&0x3);
+ break;
+ case 0x05c: /* 0 001 011 100 */
+ case 0x05d: /* 0 001 011 101 */
+ case 0x05e: /* 0 001 011 110 */
+ case 0x05f: /* 0 001 011 111 */
+ sprintf(buffer, "SLLC R%01d,2",op&0x3);
+ break;
+ case 0x060: /* 0 001 100 000 */
+ case 0x061: /* 0 001 100 001 */
+ case 0x062: /* 0 001 100 010 */
+ case 0x063: /* 0 001 100 011 */
+ sprintf(buffer, "SLR R%01d,1",op&0x3);
+ break;
+ case 0x064: /* 0 001 100 100 */
+ case 0x065: /* 0 001 100 101 */
+ case 0x066: /* 0 001 100 110 */
+ case 0x067: /* 0 001 100 111 */
+ sprintf(buffer, "SLR R%01d,2",op&0x3);
+ break;
+ case 0x068: /* 0 001 101 000 */
+ case 0x069: /* 0 001 101 001 */
+ case 0x06a: /* 0 001 101 010 */
+ case 0x06b: /* 0 001 101 011 */
+ sprintf(buffer, "SAR R%01d,1",op&0x3);
+ break;
+ case 0x06c: /* 0 001 101 100 */
+ case 0x06d: /* 0 001 101 101 */
+ case 0x06e: /* 0 001 101 110 */
+ case 0x06f: /* 0 001 101 111 */
+ sprintf(buffer, "SAR R%01d,2",op&0x3);
+ break;
+ case 0x070: /* 0 001 110 000 */
+ case 0x071: /* 0 001 110 001 */
+ case 0x072: /* 0 001 110 010 */
+ case 0x073: /* 0 001 110 011 */
+ sprintf(buffer, "RRC R%01d,1",op&0x3);
+ break;
+ case 0x074: /* 0 001 110 100 */
+ case 0x075: /* 0 001 110 101 */
+ case 0x076: /* 0 001 110 110 */
+ case 0x077: /* 0 001 110 111 */
+ sprintf(buffer, "RRC R%01d,2",op&0x3);
+ break;
+ case 0x078: /* 0 001 111 000 */
+ case 0x079: /* 0 001 111 001 */
+ case 0x07a: /* 0 001 111 010 */
+ case 0x07b: /* 0 001 111 011 */
+ sprintf(buffer, "SARC R%01d,1",op&0x3);
+ break;
+ case 0x07c: /* 0 001 111 100 */
+ case 0x07d: /* 0 001 111 101 */
+ case 0x07e: /* 0 001 111 110 */
+ case 0x07f: /* 0 001 111 111 */
+ sprintf(buffer, "SARC R%01d,2",op&0x3);
+ break;
+ case 0x080: /* 0 010 000 000 */
+ case 0x089: /* 0 010 001 001 */
+ case 0x092: /* 0 010 010 010 */
+ case 0x09b: /* 0 010 011 011 */
+ case 0x0a4: /* 0 010 100 100 */
+ case 0x0ad: /* 0 010 101 101 */
+ case 0x0b6: /* 0 010 110 110 */
+ case 0x0bf: /* 0 010 111 111 */
+ sprintf(buffer, "TSTR R%01d",op&0x7);
+ break;
+ case 0x087: /* 0 010 000 111 */
+ case 0x08f: /* 0 010 001 111 */
+ case 0x097: /* 0 010 010 111 */
+ case 0x09f: /* 0 010 011 111 */
+ case 0x0a7: /* 0 010 100 111 */
+ case 0x0af: /* 0 010 101 111 */
+ case 0x0b7: /* 0 010 110 111 */
+ sprintf(buffer, "JR R%01d",(op&0x38)>>3);
+ break;
+ case 0x081: /* 0 010 000 001 */
+ case 0x082: /* 0 010 000 010 */
+ case 0x083: /* 0 010 000 011 */
+ case 0x084: /* 0 010 000 100 */
+ case 0x085: /* 0 010 000 101 */
+ case 0x086: /* 0 010 000 110 */
+ case 0x088: /* 0 010 001 000 */
+ case 0x08a: /* 0 010 001 010 */
+ case 0x08b: /* 0 010 001 011 */
+ case 0x08c: /* 0 010 001 100 */
+ case 0x08d: /* 0 010 001 101 */
+ case 0x08e: /* 0 010 001 110 */
+ case 0x090: /* 0 010 010 000 */
+ case 0x091: /* 0 010 010 001 */
+ case 0x093: /* 0 010 010 011 */
+ case 0x094: /* 0 010 010 100 */
+ case 0x095: /* 0 010 010 101 */
+ case 0x096: /* 0 010 010 110 */
+ case 0x098: /* 0 010 011 000 */
+ case 0x099: /* 0 010 011 001 */
+ case 0x09a: /* 0 010 011 010 */
+ case 0x09c: /* 0 010 011 100 */
+ case 0x09d: /* 0 010 011 101 */
+ case 0x09e: /* 0 010 011 110 */
+ case 0x0a0: /* 0 010 100 000 */
+ case 0x0a1: /* 0 010 100 001 */
+ case 0x0a2: /* 0 010 100 010 */
+ case 0x0a3: /* 0 010 100 011 */
+ case 0x0a5: /* 0 010 100 101 */
+ case 0x0a6: /* 0 010 100 110 */
+ case 0x0a8: /* 0 010 101 000 */
+ case 0x0a9: /* 0 010 101 001 */
+ case 0x0aa: /* 0 010 101 010 */
+ case 0x0ab: /* 0 010 101 011 */
+ case 0x0ac: /* 0 010 101 100 */
+ case 0x0ae: /* 0 010 101 110 */
+ case 0x0b0: /* 0 010 110 000 */
+ case 0x0b1: /* 0 010 110 001 */
+ case 0x0b2: /* 0 010 110 010 */
+ case 0x0b3: /* 0 010 110 011 */
+ case 0x0b4: /* 0 010 110 100 */
+ case 0x0b5: /* 0 010 110 101 */
+ case 0x0b8: /* 0 010 111 000 */
+ case 0x0b9: /* 0 010 111 001 */
+ case 0x0ba: /* 0 010 111 010 */
+ case 0x0bb: /* 0 010 111 011 */
+ case 0x0bc: /* 0 010 111 100 */
+ case 0x0bd: /* 0 010 111 101 */
+ case 0x0be: /* 0 010 111 110 */
+ sprintf(buffer, "MOVR R%01d,R%01d",(op&0x38)>>3,op&0x7);
+ break;
+ case 0x0c0: /* 0 011 000 000 */
+ case 0x0c1: /* 0 011 000 001 */
+ case 0x0c2: /* 0 011 000 010 */
+ case 0x0c3: /* 0 011 000 011 */
+ case 0x0c4: /* 0 011 000 100 */
+ case 0x0c5: /* 0 011 000 101 */
+ case 0x0c6: /* 0 011 000 110 */
+ case 0x0c7: /* 0 011 000 111 */
+ case 0x0c8: /* 0 011 001 000 */
+ case 0x0c9: /* 0 011 001 001 */
+ case 0x0ca: /* 0 011 001 010 */
+ case 0x0cb: /* 0 011 001 011 */
+ case 0x0cc: /* 0 011 001 100 */
+ case 0x0cd: /* 0 011 001 101 */
+ case 0x0ce: /* 0 011 001 110 */
+ case 0x0cf: /* 0 011 001 111 */
+ case 0x0d0: /* 0 011 010 000 */
+ case 0x0d1: /* 0 011 010 001 */
+ case 0x0d2: /* 0 011 010 010 */
+ case 0x0d3: /* 0 011 010 011 */
+ case 0x0d4: /* 0 011 010 100 */
+ case 0x0d5: /* 0 011 010 101 */
+ case 0x0d6: /* 0 011 010 110 */
+ case 0x0d7: /* 0 011 010 111 */
+ case 0x0d8: /* 0 011 011 000 */
+ case 0x0d9: /* 0 011 011 001 */
+ case 0x0da: /* 0 011 011 010 */
+ case 0x0db: /* 0 011 011 011 */
+ case 0x0dc: /* 0 011 011 100 */
+ case 0x0dd: /* 0 011 011 101 */
+ case 0x0de: /* 0 011 011 110 */
+ case 0x0df: /* 0 011 011 111 */
+ case 0x0e0: /* 0 011 100 000 */
+ case 0x0e1: /* 0 011 100 001 */
+ case 0x0e2: /* 0 011 100 010 */
+ case 0x0e3: /* 0 011 100 011 */
+ case 0x0e4: /* 0 011 100 100 */
+ case 0x0e5: /* 0 011 100 101 */
+ case 0x0e6: /* 0 011 100 110 */
+ case 0x0e7: /* 0 011 100 111 */
+ case 0x0e8: /* 0 011 101 000 */
+ case 0x0e9: /* 0 011 101 001 */
+ case 0x0ea: /* 0 011 101 010 */
+ case 0x0eb: /* 0 011 101 011 */
+ case 0x0ec: /* 0 011 101 100 */
+ case 0x0ed: /* 0 011 101 101 */
+ case 0x0ee: /* 0 011 101 110 */
+ case 0x0ef: /* 0 011 101 111 */
+ case 0x0f0: /* 0 011 110 000 */
+ case 0x0f1: /* 0 011 110 001 */
+ case 0x0f2: /* 0 011 110 010 */
+ case 0x0f3: /* 0 011 110 011 */
+ case 0x0f4: /* 0 011 110 100 */
+ case 0x0f5: /* 0 011 110 101 */
+ case 0x0f6: /* 0 011 110 110 */
+ case 0x0f7: /* 0 011 110 111 */
+ case 0x0f8: /* 0 011 111 000 */
+ case 0x0f9: /* 0 011 111 001 */
+ case 0x0fa: /* 0 011 111 010 */
+ case 0x0fb: /* 0 011 111 011 */
+ case 0x0fc: /* 0 011 111 100 */
+ case 0x0fd: /* 0 011 111 101 */
+ case 0x0fe: /* 0 011 111 110 */
+ case 0x0ff: /* 0 011 111 111 */
+ sprintf(buffer, "ADDR R%01d,R%01d",(op&0x38)>>3,op&7);
+ break;
+ case 0x100: /* 0 100 000 000 */
+ case 0x101: /* 0 100 000 001 */
+ case 0x102: /* 0 100 000 010 */
+ case 0x103: /* 0 100 000 011 */
+ case 0x104: /* 0 100 000 100 */
+ case 0x105: /* 0 100 000 101 */
+ case 0x106: /* 0 100 000 110 */
+ case 0x107: /* 0 100 000 111 */
+ case 0x108: /* 0 100 001 000 */
+ case 0x109: /* 0 100 001 001 */
+ case 0x10a: /* 0 100 001 010 */
+ case 0x10b: /* 0 100 001 011 */
+ case 0x10c: /* 0 100 001 100 */
+ case 0x10d: /* 0 100 001 101 */
+ case 0x10e: /* 0 100 001 110 */
+ case 0x10f: /* 0 100 001 111 */
+ case 0x110: /* 0 100 010 000 */
+ case 0x111: /* 0 100 010 001 */
+ case 0x112: /* 0 100 010 010 */
+ case 0x113: /* 0 100 010 011 */
+ case 0x114: /* 0 100 010 100 */
+ case 0x115: /* 0 100 010 101 */
+ case 0x116: /* 0 100 010 110 */
+ case 0x117: /* 0 100 010 111 */
+ case 0x118: /* 0 100 011 000 */
+ case 0x119: /* 0 100 011 001 */
+ case 0x11a: /* 0 100 011 010 */
+ case 0x11b: /* 0 100 011 011 */
+ case 0x11c: /* 0 100 011 100 */
+ case 0x11d: /* 0 100 011 101 */
+ case 0x11e: /* 0 100 011 110 */
+ case 0x11f: /* 0 100 011 111 */
+ case 0x120: /* 0 100 100 000 */
+ case 0x121: /* 0 100 100 001 */
+ case 0x122: /* 0 100 100 010 */
+ case 0x123: /* 0 100 100 011 */
+ case 0x124: /* 0 100 100 100 */
+ case 0x125: /* 0 100 100 101 */
+ case 0x126: /* 0 100 100 110 */
+ case 0x127: /* 0 100 100 111 */
+ case 0x128: /* 0 100 101 000 */
+ case 0x129: /* 0 100 101 001 */
+ case 0x12a: /* 0 100 101 010 */
+ case 0x12b: /* 0 100 101 011 */
+ case 0x12c: /* 0 100 101 100 */
+ case 0x12d: /* 0 100 101 101 */
+ case 0x12e: /* 0 100 101 110 */
+ case 0x12f: /* 0 100 101 111 */
+ case 0x130: /* 0 100 110 000 */
+ case 0x131: /* 0 100 110 001 */
+ case 0x132: /* 0 100 110 010 */
+ case 0x133: /* 0 100 110 011 */
+ case 0x134: /* 0 100 110 100 */
+ case 0x135: /* 0 100 110 101 */
+ case 0x136: /* 0 100 110 110 */
+ case 0x137: /* 0 100 110 111 */
+ case 0x138: /* 0 100 111 000 */
+ case 0x139: /* 0 100 111 001 */
+ case 0x13a: /* 0 100 111 010 */
+ case 0x13b: /* 0 100 111 011 */
+ case 0x13c: /* 0 100 111 100 */
+ case 0x13d: /* 0 100 111 101 */
+ case 0x13e: /* 0 100 111 110 */
+ case 0x13f: /* 0 100 111 111 */
+ sprintf(buffer, "SUBR R%01d,R%01d",(op&0x38)>>3,op&7);
+ break;
+ case 0x140: /* 0 101 000 000 */
+ case 0x141: /* 0 101 000 001 */
+ case 0x142: /* 0 101 000 010 */
+ case 0x143: /* 0 101 000 011 */
+ case 0x144: /* 0 101 000 100 */
+ case 0x145: /* 0 101 000 101 */
+ case 0x146: /* 0 101 000 110 */
+ case 0x147: /* 0 101 000 111 */
+ case 0x148: /* 0 101 001 000 */
+ case 0x149: /* 0 101 001 001 */
+ case 0x14a: /* 0 101 001 010 */
+ case 0x14b: /* 0 101 001 011 */
+ case 0x14c: /* 0 101 001 100 */
+ case 0x14d: /* 0 101 001 101 */
+ case 0x14e: /* 0 101 001 110 */
+ case 0x14f: /* 0 101 001 111 */
+ case 0x150: /* 0 101 010 000 */
+ case 0x151: /* 0 101 010 001 */
+ case 0x152: /* 0 101 010 010 */
+ case 0x153: /* 0 101 010 011 */
+ case 0x154: /* 0 101 010 100 */
+ case 0x155: /* 0 101 010 101 */
+ case 0x156: /* 0 101 010 110 */
+ case 0x157: /* 0 101 010 111 */
+ case 0x158: /* 0 101 011 000 */
+ case 0x159: /* 0 101 011 001 */
+ case 0x15a: /* 0 101 011 010 */
+ case 0x15b: /* 0 101 011 011 */
+ case 0x15c: /* 0 101 011 100 */
+ case 0x15d: /* 0 101 011 101 */
+ case 0x15e: /* 0 101 011 110 */
+ case 0x15f: /* 0 101 011 111 */
+ case 0x160: /* 0 101 100 000 */
+ case 0x161: /* 0 101 100 001 */
+ case 0x162: /* 0 101 100 010 */
+ case 0x163: /* 0 101 100 011 */
+ case 0x164: /* 0 101 100 100 */
+ case 0x165: /* 0 101 100 101 */
+ case 0x166: /* 0 101 100 110 */
+ case 0x167: /* 0 101 100 111 */
+ case 0x168: /* 0 101 101 000 */
+ case 0x169: /* 0 101 101 001 */
+ case 0x16a: /* 0 101 101 010 */
+ case 0x16b: /* 0 101 101 011 */
+ case 0x16c: /* 0 101 101 100 */
+ case 0x16d: /* 0 101 101 101 */
+ case 0x16e: /* 0 101 101 110 */
+ case 0x16f: /* 0 101 101 111 */
+ case 0x170: /* 0 101 110 000 */
+ case 0x171: /* 0 101 110 001 */
+ case 0x172: /* 0 101 110 010 */
+ case 0x173: /* 0 101 110 011 */
+ case 0x174: /* 0 101 110 100 */
+ case 0x175: /* 0 101 110 101 */
+ case 0x176: /* 0 101 110 110 */
+ case 0x177: /* 0 101 110 111 */
+ case 0x178: /* 0 101 111 000 */
+ case 0x179: /* 0 101 111 001 */
+ case 0x17a: /* 0 101 111 010 */
+ case 0x17b: /* 0 101 111 011 */
+ case 0x17c: /* 0 101 111 100 */
+ case 0x17d: /* 0 101 111 101 */
+ case 0x17e: /* 0 101 111 110 */
+ case 0x17f: /* 0 101 111 111 */
+ sprintf(buffer, "CMPR R%01d,R%01d",(op&0x38)>>3,op&7);
+ break;
+ case 0x180: /* 0 110 000 000 */
+ case 0x181: /* 0 110 000 001 */
+ case 0x182: /* 0 110 000 010 */
+ case 0x183: /* 0 110 000 011 */
+ case 0x184: /* 0 110 000 100 */
+ case 0x185: /* 0 110 000 101 */
+ case 0x186: /* 0 110 000 110 */
+ case 0x187: /* 0 110 000 111 */
+ case 0x188: /* 0 110 001 000 */
+ case 0x189: /* 0 110 001 001 */
+ case 0x18a: /* 0 110 001 010 */
+ case 0x18b: /* 0 110 001 011 */
+ case 0x18c: /* 0 110 001 100 */
+ case 0x18d: /* 0 110 001 101 */
+ case 0x18e: /* 0 110 001 110 */
+ case 0x18f: /* 0 110 001 111 */
+ case 0x190: /* 0 110 010 000 */
+ case 0x191: /* 0 110 010 001 */
+ case 0x192: /* 0 110 010 010 */
+ case 0x193: /* 0 110 010 011 */
+ case 0x194: /* 0 110 010 100 */
+ case 0x195: /* 0 110 010 101 */
+ case 0x196: /* 0 110 010 110 */
+ case 0x197: /* 0 110 010 111 */
+ case 0x198: /* 0 110 011 000 */
+ case 0x199: /* 0 110 011 001 */
+ case 0x19a: /* 0 110 011 010 */
+ case 0x19b: /* 0 110 011 011 */
+ case 0x19c: /* 0 110 011 100 */
+ case 0x19d: /* 0 110 011 101 */
+ case 0x19e: /* 0 110 011 110 */
+ case 0x19f: /* 0 110 011 111 */
+ case 0x1a0: /* 0 110 100 000 */
+ case 0x1a1: /* 0 110 100 001 */
+ case 0x1a2: /* 0 110 100 010 */
+ case 0x1a3: /* 0 110 100 011 */
+ case 0x1a4: /* 0 110 100 100 */
+ case 0x1a5: /* 0 110 100 101 */
+ case 0x1a6: /* 0 110 100 110 */
+ case 0x1a7: /* 0 110 100 111 */
+ case 0x1a8: /* 0 110 101 000 */
+ case 0x1a9: /* 0 110 101 001 */
+ case 0x1aa: /* 0 110 101 010 */
+ case 0x1ab: /* 0 110 101 011 */
+ case 0x1ac: /* 0 110 101 100 */
+ case 0x1ad: /* 0 110 101 101 */
+ case 0x1ae: /* 0 110 101 110 */
+ case 0x1af: /* 0 110 101 111 */
+ case 0x1b0: /* 0 110 110 000 */
+ case 0x1b1: /* 0 110 110 001 */
+ case 0x1b2: /* 0 110 110 010 */
+ case 0x1b3: /* 0 110 110 011 */
+ case 0x1b4: /* 0 110 110 100 */
+ case 0x1b5: /* 0 110 110 101 */
+ case 0x1b6: /* 0 110 110 110 */
+ case 0x1b7: /* 0 110 110 111 */
+ case 0x1b8: /* 0 110 111 000 */
+ case 0x1b9: /* 0 110 111 001 */
+ case 0x1ba: /* 0 110 111 010 */
+ case 0x1bb: /* 0 110 111 011 */
+ case 0x1bc: /* 0 110 111 100 */
+ case 0x1bd: /* 0 110 111 101 */
+ case 0x1be: /* 0 110 111 110 */
+ case 0x1bf: /* 0 110 111 111 */
+ sprintf(buffer, "ANDR R%01d,R%01d",(op&0x38)>>3,op&7);
+ break;
+ case 0x1c0: /* 0 111 000 000 */
+ case 0x1c9: /* 0 111 001 001 */
+ case 0x1d2: /* 0 111 010 010 */
+ case 0x1db: /* 0 111 011 011 */
+ case 0x1e4: /* 0 111 100 100 */
+ case 0x1ed: /* 0 111 101 101 */
+ case 0x1f6: /* 0 111 110 110 */
+ case 0x1ff: /* 0 111 111 111 */
+ sprintf(buffer, "CLRR R%01d",op&7);
+ break;
+ case 0x1c1: /* 0 111 000 001 */
+ case 0x1c2: /* 0 111 000 010 */
+ case 0x1c3: /* 0 111 000 011 */
+ case 0x1c4: /* 0 111 000 100 */
+ case 0x1c5: /* 0 111 000 101 */
+ case 0x1c6: /* 0 111 000 110 */
+ case 0x1c7: /* 0 111 000 111 */
+ case 0x1c8: /* 0 111 001 000 */
+ case 0x1ca: /* 0 111 001 010 */
+ case 0x1cb: /* 0 111 001 011 */
+ case 0x1cc: /* 0 111 001 100 */
+ case 0x1cd: /* 0 111 001 101 */
+ case 0x1ce: /* 0 111 001 110 */
+ case 0x1cf: /* 0 111 001 111 */
+ case 0x1d0: /* 0 111 010 000 */
+ case 0x1d1: /* 0 111 010 001 */
+ case 0x1d3: /* 0 111 010 011 */
+ case 0x1d4: /* 0 111 010 100 */
+ case 0x1d5: /* 0 111 010 101 */
+ case 0x1d6: /* 0 111 010 110 */
+ case 0x1d7: /* 0 111 010 111 */
+ case 0x1d8: /* 0 111 011 000 */
+ case 0x1d9: /* 0 111 011 001 */
+ case 0x1da: /* 0 111 011 010 */
+ case 0x1dc: /* 0 111 011 100 */
+ case 0x1dd: /* 0 111 011 101 */
+ case 0x1de: /* 0 111 011 110 */
+ case 0x1df: /* 0 111 011 111 */
+ case 0x1e0: /* 0 111 100 000 */
+ case 0x1e1: /* 0 111 100 001 */
+ case 0x1e2: /* 0 111 100 010 */
+ case 0x1e3: /* 0 111 100 011 */
+ case 0x1e5: /* 0 111 100 101 */
+ case 0x1e6: /* 0 111 100 110 */
+ case 0x1e7: /* 0 111 100 111 */
+ case 0x1e8: /* 0 111 101 000 */
+ case 0x1e9: /* 0 111 101 001 */
+ case 0x1ea: /* 0 111 101 010 */
+ case 0x1eb: /* 0 111 101 011 */
+ case 0x1ec: /* 0 111 101 100 */
+ case 0x1ee: /* 0 111 101 110 */
+ case 0x1ef: /* 0 111 101 111 */
+ case 0x1f0: /* 0 111 110 000 */
+ case 0x1f1: /* 0 111 110 001 */
+ case 0x1f2: /* 0 111 110 010 */
+ case 0x1f3: /* 0 111 110 011 */
+ case 0x1f4: /* 0 111 110 100 */
+ case 0x1f5: /* 0 111 110 101 */
+ case 0x1f7: /* 0 111 110 111 */
+ case 0x1f8: /* 0 111 111 000 */
+ case 0x1f9: /* 0 111 111 001 */
+ case 0x1fa: /* 0 111 111 010 */
+ case 0x1fb: /* 0 111 111 011 */
+ case 0x1fc: /* 0 111 111 100 */
+ case 0x1fd: /* 0 111 111 101 */
+ case 0x1fe: /* 0 111 111 110 */
+ sprintf(buffer, "XORR R%01d,R%01d",(op&0x38)>>3,op&7);
+ break;
+ case 0x200: /* 1 000 000 000 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "B %04X",pc+2+ea);
+ break;
+ case 0x201: /* 1 000 000 001 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "BC %04X",pc+2+ea);
+ break;
+ case 0x202: /* 1 000 000 010 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "BOV %04X",pc+2+ea);
+ break;
+ case 0x203: /* 1 000 000 011 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "BPL %04X",pc+2+ea);
+ break;
+ case 0x204: /* 1 000 000 100 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "BZE %04X",pc+2+ea);
+ break;
+ case 0x205: /* 1 000 000 101 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "BLT %04X",pc+2+ea);
+ break;
+ case 0x206: /* 1 000 000 110 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "BLE %04X",pc+2+ea);
+ break;
+ case 0x207: /* 1 000 000 111 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "BUSC %04X",pc+2+ea);
+ break;
+ case 0x208: /* 1 000 001 000 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "NOPP %04X",pc+2+ea);
+ break;
+ case 0x209: /* 1 000 001 001 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "BNC %04X",pc+2+ea);
+ break;
+ case 0x20a: /* 1 000 001 010 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "BNOV %04X",pc+2+ea);
+ break;
+ case 0x20b: /* 1 000 001 011 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "BMI %04X",pc+2+ea);
+ break;
+ case 0x20c: /* 1 000 001 100 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "BNZE %04X",pc+2+ea);
+ break;
+ case 0x20d: /* 1 000 001 101 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "BGE %04X",pc+2+ea);
+ break;
+ case 0x20e: /* 1 000 001 110 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "BGT %04X",pc+2+ea);
+ break;
+ case 0x20f: /* 1 000 001 111 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "BESC %04X",pc+2+ea);
+ break;
+ case 0x210: /* 1 000 010 000 */
+ case 0x211: /* 1 000 010 001 */
+ case 0x212: /* 1 000 010 010 */
+ case 0x213: /* 1 000 010 011 */
+ case 0x214: /* 1 000 010 100 */
+ case 0x215: /* 1 000 010 101 */
+ case 0x216: /* 1 000 010 110 */
+ case 0x217: /* 1 000 010 111 */
+ case 0x218: /* 1 000 011 000 */
+ case 0x219: /* 1 000 011 001 */
+ case 0x21a: /* 1 000 011 010 */
+ case 0x21b: /* 1 000 011 011 */
+ case 0x21c: /* 1 000 011 100 */
+ case 0x21d: /* 1 000 011 101 */
+ case 0x21e: /* 1 000 011 110 */
+ case 0x21f: /* 1 000 011 111 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "BEXT %04X,%01X",pc+2+ea,op&0x0f);
+ break;
+ case 0x220: /* 1 000 100 000 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "B %04X",pc+1-ea);
+ break;
+ case 0x221: /* 1 000 100 001 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "BC %04X",pc+1-ea);
+ break;
+ case 0x222: /* 1 000 100 010 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "BOV %04X",pc+1-ea);
+ break;
+ case 0x223: /* 1 000 100 011 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "BPL %04X",pc+1-ea);
+ break;
+ case 0x224: /* 1 000 100 100 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "BZE %04X",pc+1-ea);
+ break;
+ case 0x225: /* 1 000 100 101 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "BLT %04X",pc+1-ea);
+ break;
+ case 0x226: /* 1 000 100 110 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "BLE %04X",pc+1-ea);
+ break;
+ case 0x227: /* 1 000 100 111 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "BUSC %04X",pc+1-ea);
+ break;
+ case 0x228: /* 1 000 101 000 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "NOPP %04X",pc+1-ea);
+ break;
+ case 0x229: /* 1 000 101 001 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "BNC %04X",pc+1-ea);
+ break;
+ case 0x22a: /* 1 000 101 010 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "BNOV %04X",pc+1-ea);
+ break;
+ case 0x22b: /* 1 000 101 011 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "BMI %04X",pc+1-ea);
+ break;
+ case 0x22c: /* 1 000 101 100 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "BNZE %04X",pc+1-ea);
+ break;
+ case 0x22d: /* 1 000 101 101 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "BGE %04X",pc+1-ea);
+ break;
+ case 0x22e: /* 1 000 101 110 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "BGT %04X",pc+1-ea);
+ break;
+ case 0x22f: /* 1 000 101 111 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "BESC %04X",pc+1-ea);
+ break;
+ case 0x230: /* 1 000 110 000 */
+ case 0x231: /* 1 000 110 001 */
+ case 0x232: /* 1 000 110 010 */
+ case 0x233: /* 1 000 110 011 */
+ case 0x234: /* 1 000 110 100 */
+ case 0x235: /* 1 000 110 101 */
+ case 0x236: /* 1 000 110 110 */
+ case 0x237: /* 1 000 110 111 */
+ case 0x238: /* 1 000 111 000 */
+ case 0x239: /* 1 000 111 001 */
+ case 0x23a: /* 1 000 111 010 */
+ case 0x23b: /* 1 000 111 011 */
+ case 0x23c: /* 1 000 111 100 */
+ case 0x23d: /* 1 000 111 101 */
+ case 0x23e: /* 1 000 111 110 */
+ case 0x23f: /* 1 000 111 111 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "BEXT %04X,%01X",pc+1-ea,op&0x0f);
+ break;
+ case 0x240: /* 1 001 000 000 */
+ case 0x241: /* 1 001 000 001 */
+ case 0x242: /* 1 001 000 010 */
+ case 0x243: /* 1 001 000 011 */
+ case 0x244: /* 1 001 000 100 */
+ case 0x245: /* 1 001 000 101 */
+ case 0x246: /* 1 001 000 110 */
+ case 0x247: /* 1 001 000 111 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "MVO R%01d,(%04X)",op&0x7,ea);
+ break;
+ case 0x248: /* 1 001 001 000 */
+ case 0x249: /* 1 001 001 001 */
+ case 0x24a: /* 1 001 001 010 */
+ case 0x24b: /* 1 001 001 011 */
+ case 0x24c: /* 1 001 001 100 */
+ case 0x24d: /* 1 001 001 101 */
+ case 0x24e: /* 1 001 001 110 */
+ case 0x24f: /* 1 001 001 111 */
+ case 0x250: /* 1 001 010 000 */
+ case 0x251: /* 1 001 010 001 */
+ case 0x252: /* 1 001 010 010 */
+ case 0x253: /* 1 001 010 011 */
+ case 0x254: /* 1 001 010 100 */
+ case 0x255: /* 1 001 010 101 */
+ case 0x256: /* 1 001 010 110 */
+ case 0x257: /* 1 001 010 111 */
+ case 0x258: /* 1 001 011 000 */
+ case 0x259: /* 1 001 011 001 */
+ case 0x25a: /* 1 001 011 010 */
+ case 0x25b: /* 1 001 011 011 */
+ case 0x25c: /* 1 001 011 100 */
+ case 0x25d: /* 1 001 011 101 */
+ case 0x25e: /* 1 001 011 110 */
+ case 0x25f: /* 1 001 011 111 */
+ case 0x260: /* 1 001 100 000 */
+ case 0x261: /* 1 001 100 001 */
+ case 0x262: /* 1 001 100 010 */
+ case 0x263: /* 1 001 100 011 */
+ case 0x264: /* 1 001 100 100 */
+ case 0x265: /* 1 001 100 101 */
+ case 0x266: /* 1 001 100 110 */
+ case 0x267: /* 1 001 100 111 */
+ case 0x268: /* 1 001 101 000 */
+ case 0x269: /* 1 001 101 001 */
+ case 0x26a: /* 1 001 101 010 */
+ case 0x26b: /* 1 001 101 011 */
+ case 0x26c: /* 1 001 101 100 */
+ case 0x26d: /* 1 001 101 101 */
+ case 0x26e: /* 1 001 101 110 */
+ case 0x26f: /* 1 001 101 111 */
+ sprintf(buffer, "MVO@ R%01d,(R%01d)",op&0x7,(op&0x38)>>3);
+ break;
+ case 0x270: /* 1 001 110 000 */
+ case 0x271: /* 1 001 110 001 */
+ case 0x272: /* 1 001 110 010 */
+ case 0x273: /* 1 001 110 011 */
+ case 0x274: /* 1 001 110 100 */
+ case 0x275: /* 1 001 110 101 */
+ case 0x276: /* 1 001 110 110 */
+ case 0x277: /* 1 001 110 111 */
+ sprintf(buffer, "PSHR R%01d",op&0x7);
+ break;
+ case 0x278: /* 1 001 111 000 */
+ case 0x279: /* 1 001 111 001 */
+ case 0x27a: /* 1 001 111 010 */
+ case 0x27b: /* 1 001 111 011 */
+ case 0x27c: /* 1 001 111 100 */
+ case 0x27d: /* 1 001 111 101 */
+ case 0x27e: /* 1 001 111 110 */
+ case 0x27f: /* 1 001 111 111 */
+ size += 1;
+ sprintf(buffer, "MVOI R%01d,(%04X)",op&0x7,pc+1);
+ break;
+ case 0x280: /* 1 010 000 000 */
+ case 0x281: /* 1 010 000 001 */
+ case 0x282: /* 1 010 000 010 */
+ case 0x283: /* 1 010 000 011 */
+ case 0x284: /* 1 010 000 100 */
+ case 0x285: /* 1 010 000 101 */
+ case 0x286: /* 1 010 000 110 */
+ case 0x287: /* 1 010 000 111 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "MVI (%04X),R%01d",ea,op&0x7);
+ break;
+ case 0x288: /* 1 010 001 000 */
+ case 0x289: /* 1 010 001 001 */
+ case 0x28a: /* 1 010 001 010 */
+ case 0x28b: /* 1 010 001 011 */
+ case 0x28c: /* 1 010 001 100 */
+ case 0x28d: /* 1 010 001 101 */
+ case 0x28e: /* 1 010 001 110 */
+ case 0x28f: /* 1 010 001 111 */
+ case 0x290: /* 1 010 010 000 */
+ case 0x291: /* 1 010 010 001 */
+ case 0x292: /* 1 010 010 010 */
+ case 0x293: /* 1 010 010 011 */
+ case 0x294: /* 1 010 010 100 */
+ case 0x295: /* 1 010 010 101 */
+ case 0x296: /* 1 010 010 110 */
+ case 0x297: /* 1 010 010 111 */
+ case 0x298: /* 1 010 011 000 */
+ case 0x299: /* 1 010 011 001 */
+ case 0x29a: /* 1 010 011 010 */
+ case 0x29b: /* 1 010 011 011 */
+ case 0x29c: /* 1 010 011 100 */
+ case 0x29d: /* 1 010 011 101 */
+ case 0x29e: /* 1 010 011 110 */
+ case 0x29f: /* 1 010 011 111 */
+ case 0x2a0: /* 1 010 100 000 */
+ case 0x2a1: /* 1 010 100 001 */
+ case 0x2a2: /* 1 010 100 010 */
+ case 0x2a3: /* 1 010 100 011 */
+ case 0x2a4: /* 1 010 100 100 */
+ case 0x2a5: /* 1 010 100 101 */
+ case 0x2a6: /* 1 010 100 110 */
+ case 0x2a7: /* 1 010 100 111 */
+ case 0x2a8: /* 1 010 101 000 */
+ case 0x2a9: /* 1 010 101 001 */
+ case 0x2aa: /* 1 010 101 010 */
+ case 0x2ab: /* 1 010 101 011 */
+ case 0x2ac: /* 1 010 101 100 */
+ case 0x2ad: /* 1 010 101 101 */
+ case 0x2ae: /* 1 010 101 110 */
+ case 0x2af: /* 1 010 101 111 */
+ sprintf(buffer, "MVI@ (R%01d),R%01d",(op&0x38)>>3,op&0x7);
+ break;
+ case 0x2b0: /* 1 010 110 000 */
+ case 0x2b1: /* 1 010 110 001 */
+ case 0x2b2: /* 1 010 110 010 */
+ case 0x2b3: /* 1 010 110 011 */
+ case 0x2b4: /* 1 010 110 100 */
+ case 0x2b5: /* 1 010 110 101 */
+ case 0x2b6: /* 1 010 110 110 */
+ case 0x2b7: /* 1 010 110 111 */
+ sprintf(buffer, "PULR R%01d",op&0x7);
+ break;
+ case 0x2b8: /* 1 010 111 000 */
+ case 0x2b9: /* 1 010 111 001 */
+ case 0x2ba: /* 1 010 111 010 */
+ case 0x2bb: /* 1 010 111 011 */
+ case 0x2bc: /* 1 010 111 100 */
+ case 0x2bd: /* 1 010 111 101 */
+ case 0x2be: /* 1 010 111 110 */
+ case 0x2bf: /* 1 010 111 111 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "MVII #%04X,R%01d",ea,op&0x7);
+ break;
+ case 0x2c0: /* 1 011 010 000 */
+ case 0x2c1: /* 1 011 010 001 */
+ case 0x2c2: /* 1 011 010 010 */
+ case 0x2c3: /* 1 011 010 011 */
+ case 0x2c4: /* 1 011 010 100 */
+ case 0x2c5: /* 1 011 010 101 */
+ case 0x2c6: /* 1 011 010 110 */
+ case 0x2c7: /* 1 011 010 111 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "ADD (%04X),R%01d",ea,op&0x7);
+ break;
+ case 0x2c8: /* 1 011 001 000 */
+ case 0x2c9: /* 1 011 001 001 */
+ case 0x2ca: /* 1 011 001 010 */
+ case 0x2cb: /* 1 011 001 011 */
+ case 0x2cc: /* 1 011 001 100 */
+ case 0x2cd: /* 1 011 001 101 */
+ case 0x2ce: /* 1 011 001 110 */
+ case 0x2cf: /* 1 011 001 111 */
+ case 0x2d0: /* 1 011 010 000 */
+ case 0x2d1: /* 1 011 010 001 */
+ case 0x2d2: /* 1 011 010 010 */
+ case 0x2d3: /* 1 011 010 011 */
+ case 0x2d4: /* 1 011 010 100 */
+ case 0x2d5: /* 1 011 010 101 */
+ case 0x2d6: /* 1 011 010 110 */
+ case 0x2d7: /* 1 011 010 111 */
+ case 0x2d8: /* 1 011 011 000 */
+ case 0x2d9: /* 1 011 011 001 */
+ case 0x2da: /* 1 011 011 010 */
+ case 0x2db: /* 1 011 011 011 */
+ case 0x2dc: /* 1 011 011 100 */
+ case 0x2dd: /* 1 011 011 101 */
+ case 0x2de: /* 1 011 011 110 */
+ case 0x2df: /* 1 011 011 111 */
+ case 0x2e0: /* 1 011 100 000 */
+ case 0x2e1: /* 1 011 100 001 */
+ case 0x2e2: /* 1 011 100 010 */
+ case 0x2e3: /* 1 011 100 011 */
+ case 0x2e4: /* 1 011 100 100 */
+ case 0x2e5: /* 1 011 100 101 */
+ case 0x2e6: /* 1 011 100 110 */
+ case 0x2e7: /* 1 011 100 111 */
+ case 0x2e8: /* 1 011 101 000 */
+ case 0x2e9: /* 1 011 101 001 */
+ case 0x2ea: /* 1 011 101 010 */
+ case 0x2eb: /* 1 011 101 011 */
+ case 0x2ec: /* 1 011 101 100 */
+ case 0x2ed: /* 1 011 101 101 */
+ case 0x2ee: /* 1 011 101 110 */
+ case 0x2ef: /* 1 011 101 111 */
+ case 0x2f0: /* 1 011 110 000 */
+ case 0x2f1: /* 1 011 110 001 */
+ case 0x2f2: /* 1 011 110 010 */
+ case 0x2f3: /* 1 011 110 011 */
+ case 0x2f4: /* 1 011 110 100 */
+ case 0x2f5: /* 1 011 110 101 */
+ case 0x2f6: /* 1 011 110 110 */
+ case 0x2f7: /* 1 011 110 111 */
+ sprintf(buffer, "ADD@ (R%01d),R%01d",(op&0x38)>>3,op&0x7);
+ break;
+ case 0x2f8: /* 1 011 111 000 */
+ case 0x2f9: /* 1 011 111 001 */
+ case 0x2fa: /* 1 011 111 010 */
+ case 0x2fb: /* 1 011 111 011 */
+ case 0x2fc: /* 1 011 111 100 */
+ case 0x2fd: /* 1 011 111 101 */
+ case 0x2fe: /* 1 011 111 110 */
+ case 0x2ff: /* 1 011 111 111 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "ADDI #%04X,R%01d",ea,op&0x7);
+ break;
+ case 0x300: /* 1 100 000 000 */
+ case 0x301: /* 1 100 000 001 */
+ case 0x302: /* 1 100 000 010 */
+ case 0x303: /* 1 100 000 011 */
+ case 0x304: /* 1 100 000 100 */
+ case 0x305: /* 1 100 000 101 */
+ case 0x306: /* 1 100 000 110 */
+ case 0x307: /* 1 100 000 111 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "SUB (%04X),R%01d",ea,op&0x7);
+ break;
+ case 0x308: /* 1 100 001 000 */
+ case 0x309: /* 1 100 001 001 */
+ case 0x30a: /* 1 100 001 010 */
+ case 0x30b: /* 1 100 001 011 */
+ case 0x30c: /* 1 100 001 100 */
+ case 0x30d: /* 1 100 001 101 */
+ case 0x30e: /* 1 100 001 110 */
+ case 0x30f: /* 1 100 001 111 */
+ case 0x310: /* 1 100 010 000 */
+ case 0x311: /* 1 100 010 001 */
+ case 0x312: /* 1 100 010 010 */
+ case 0x313: /* 1 100 010 011 */
+ case 0x314: /* 1 100 010 100 */
+ case 0x315: /* 1 100 010 101 */
+ case 0x316: /* 1 100 010 110 */
+ case 0x317: /* 1 100 010 111 */
+ case 0x318: /* 1 100 011 000 */
+ case 0x319: /* 1 100 011 001 */
+ case 0x31a: /* 1 100 011 010 */
+ case 0x31b: /* 1 100 011 011 */
+ case 0x31c: /* 1 100 011 100 */
+ case 0x31d: /* 1 100 011 101 */
+ case 0x31e: /* 1 100 011 110 */
+ case 0x31f: /* 1 100 011 111 */
+ case 0x320: /* 1 100 100 000 */
+ case 0x321: /* 1 100 100 001 */
+ case 0x322: /* 1 100 100 010 */
+ case 0x323: /* 1 100 100 011 */
+ case 0x324: /* 1 100 100 100 */
+ case 0x325: /* 1 100 100 101 */
+ case 0x326: /* 1 100 100 110 */
+ case 0x327: /* 1 100 100 111 */
+ case 0x328: /* 1 100 101 000 */
+ case 0x329: /* 1 100 101 001 */
+ case 0x32a: /* 1 100 101 010 */
+ case 0x32b: /* 1 100 101 011 */
+ case 0x32c: /* 1 100 101 100 */
+ case 0x32d: /* 1 100 101 101 */
+ case 0x32e: /* 1 100 101 110 */
+ case 0x32f: /* 1 100 101 111 */
+ case 0x330: /* 1 100 110 000 */
+ case 0x331: /* 1 100 110 001 */
+ case 0x332: /* 1 100 110 010 */
+ case 0x333: /* 1 100 110 011 */
+ case 0x334: /* 1 100 110 100 */
+ case 0x335: /* 1 100 110 101 */
+ case 0x336: /* 1 100 110 110 */
+ case 0x337: /* 1 100 110 111 */
+ sprintf(buffer, "SUB@ (R%01d),R%01d",(op&0x38)>>3,op&0x7);
+ break;
+ case 0x338: /* 1 100 111 000 */
+ case 0x339: /* 1 100 111 001 */
+ case 0x33a: /* 1 100 111 010 */
+ case 0x33b: /* 1 100 111 011 */
+ case 0x33c: /* 1 100 111 100 */
+ case 0x33d: /* 1 100 111 101 */
+ case 0x33e: /* 1 100 111 110 */
+ case 0x33f: /* 1 100 111 111 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "SUBI #%04X,R%01d",ea,op&0x7);
+ break;
+ case 0x340: /* 1 101 000 000 */
+ case 0x341: /* 1 101 000 001 */
+ case 0x342: /* 1 101 000 010 */
+ case 0x343: /* 1 101 000 011 */
+ case 0x344: /* 1 101 000 100 */
+ case 0x345: /* 1 101 000 101 */
+ case 0x346: /* 1 101 000 110 */
+ case 0x347: /* 1 101 000 111 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "CMP (%04X),R%01d",ea,op&0x7);
+ break;
+ case 0x348: /* 1 101 001 000 */
+ case 0x349: /* 1 101 001 001 */
+ case 0x34a: /* 1 101 001 010 */
+ case 0x34b: /* 1 101 001 011 */
+ case 0x34c: /* 1 101 001 100 */
+ case 0x34d: /* 1 101 001 101 */
+ case 0x34e: /* 1 101 001 110 */
+ case 0x34f: /* 1 101 001 111 */
+ case 0x350: /* 1 101 010 000 */
+ case 0x351: /* 1 101 010 001 */
+ case 0x352: /* 1 101 010 010 */
+ case 0x353: /* 1 101 010 011 */
+ case 0x354: /* 1 101 010 100 */
+ case 0x355: /* 1 101 010 101 */
+ case 0x356: /* 1 101 010 110 */
+ case 0x357: /* 1 101 010 111 */
+ case 0x358: /* 1 101 011 000 */
+ case 0x359: /* 1 101 011 001 */
+ case 0x35a: /* 1 101 011 010 */
+ case 0x35b: /* 1 101 011 011 */
+ case 0x35c: /* 1 101 011 100 */
+ case 0x35d: /* 1 101 011 101 */
+ case 0x35e: /* 1 101 011 110 */
+ case 0x35f: /* 1 101 011 111 */
+ case 0x360: /* 1 101 100 000 */
+ case 0x361: /* 1 101 100 001 */
+ case 0x362: /* 1 101 100 010 */
+ case 0x363: /* 1 101 100 011 */
+ case 0x364: /* 1 101 100 100 */
+ case 0x365: /* 1 101 100 101 */
+ case 0x366: /* 1 101 100 110 */
+ case 0x367: /* 1 101 100 111 */
+ case 0x368: /* 1 101 101 000 */
+ case 0x369: /* 1 101 101 001 */
+ case 0x36a: /* 1 101 101 010 */
+ case 0x36b: /* 1 101 101 011 */
+ case 0x36c: /* 1 101 101 100 */
+ case 0x36d: /* 1 101 101 101 */
+ case 0x36e: /* 1 101 101 110 */
+ case 0x36f: /* 1 101 101 111 */
+ case 0x370: /* 1 101 110 000 */
+ case 0x371: /* 1 101 110 001 */
+ case 0x372: /* 1 101 110 010 */
+ case 0x373: /* 1 101 110 011 */
+ case 0x374: /* 1 101 110 100 */
+ case 0x375: /* 1 101 110 101 */
+ case 0x376: /* 1 101 110 110 */
+ case 0x377: /* 1 101 110 111 */
+ sprintf(buffer, "CMP@ (R%01d),R%01d",(op&0x38)>>3,op&0x7);
+ break;
+ case 0x378: /* 1 101 111 000 */
+ case 0x379: /* 1 101 111 001 */
+ case 0x37a: /* 1 101 111 010 */
+ case 0x37b: /* 1 101 111 011 */
+ case 0x37c: /* 1 101 111 100 */
+ case 0x37d: /* 1 101 111 101 */
+ case 0x37e: /* 1 101 111 110 */
+ case 0x37f: /* 1 101 111 111 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "CMPI #%04X,R%01d",ea,op&0x7);
+ break;
+ case 0x380: /* 1 110 000 000 */
+ case 0x381: /* 1 110 000 001 */
+ case 0x382: /* 1 110 000 010 */
+ case 0x383: /* 1 110 000 011 */
+ case 0x384: /* 1 110 000 100 */
+ case 0x385: /* 1 110 000 101 */
+ case 0x386: /* 1 110 000 110 */
+ case 0x387: /* 1 110 000 111 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "AND (%04X),R%01d",ea,op&0x7);
+ break;
+ case 0x388: /* 1 110 001 000 */
+ case 0x389: /* 1 110 001 001 */
+ case 0x38a: /* 1 110 001 010 */
+ case 0x38b: /* 1 110 001 011 */
+ case 0x38c: /* 1 110 001 100 */
+ case 0x38d: /* 1 110 001 101 */
+ case 0x38e: /* 1 110 001 110 */
+ case 0x38f: /* 1 110 001 111 */
+ case 0x390: /* 1 110 010 000 */
+ case 0x391: /* 1 110 010 001 */
+ case 0x392: /* 1 110 010 010 */
+ case 0x393: /* 1 110 010 011 */
+ case 0x394: /* 1 110 010 100 */
+ case 0x395: /* 1 110 010 101 */
+ case 0x396: /* 1 110 010 110 */
+ case 0x397: /* 1 110 010 111 */
+ case 0x398: /* 1 110 011 000 */
+ case 0x399: /* 1 110 011 001 */
+ case 0x39a: /* 1 110 011 010 */
+ case 0x39b: /* 1 110 011 011 */
+ case 0x39c: /* 1 110 011 100 */
+ case 0x39d: /* 1 110 011 101 */
+ case 0x39e: /* 1 110 011 110 */
+ case 0x39f: /* 1 110 011 111 */
+ case 0x3a0: /* 1 110 100 000 */
+ case 0x3a1: /* 1 110 100 001 */
+ case 0x3a2: /* 1 110 100 010 */
+ case 0x3a3: /* 1 110 100 011 */
+ case 0x3a4: /* 1 110 100 100 */
+ case 0x3a5: /* 1 110 100 101 */
+ case 0x3a6: /* 1 110 100 110 */
+ case 0x3a7: /* 1 110 100 111 */
+ case 0x3a8: /* 1 110 101 000 */
+ case 0x3a9: /* 1 110 101 001 */
+ case 0x3aa: /* 1 110 101 010 */
+ case 0x3ab: /* 1 110 101 011 */
+ case 0x3ac: /* 1 110 101 100 */
+ case 0x3ad: /* 1 110 101 101 */
+ case 0x3ae: /* 1 110 101 110 */
+ case 0x3af: /* 1 110 101 111 */
+ case 0x3b0: /* 1 110 110 000 */
+ case 0x3b1: /* 1 110 110 001 */
+ case 0x3b2: /* 1 110 110 010 */
+ case 0x3b3: /* 1 110 110 011 */
+ case 0x3b4: /* 1 110 110 100 */
+ case 0x3b5: /* 1 110 110 101 */
+ case 0x3b6: /* 1 110 110 110 */
+ case 0x3b7: /* 1 110 110 111 */
+ sprintf(buffer, "AND@ (R%01d),R%01d",(op&0x38)>>3,op&0x7);
+ break;
+ case 0x3b8: /* 1 110 111 000 */
+ case 0x3b9: /* 1 110 111 001 */
+ case 0x3ba: /* 1 110 111 010 */
+ case 0x3bb: /* 1 110 111 011 */
+ case 0x3bc: /* 1 110 111 100 */
+ case 0x3bd: /* 1 110 111 101 */
+ case 0x3be: /* 1 110 111 110 */
+ case 0x3bf: /* 1 110 111 111 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "ANDI #%04X,R%01d",ea,op&0x7);
+ break;
+ case 0x3c0: /* 1 111 000 000 */
+ case 0x3c1: /* 1 111 000 001 */
+ case 0x3c2: /* 1 111 000 010 */
+ case 0x3c3: /* 1 111 000 011 */
+ case 0x3c4: /* 1 111 000 100 */
+ case 0x3c5: /* 1 111 000 101 */
+ case 0x3c6: /* 1 111 000 110 */
+ case 0x3c7: /* 1 111 000 111 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "XOR (%04X),R%01d",ea,op&0x7);
+ break;
+ case 0x3c8: /* 1 111 001 000 */
+ case 0x3c9: /* 1 111 001 001 */
+ case 0x3ca: /* 1 111 001 010 */
+ case 0x3cb: /* 1 111 001 011 */
+ case 0x3cc: /* 1 111 001 100 */
+ case 0x3cd: /* 1 111 001 101 */
+ case 0x3ce: /* 1 111 001 110 */
+ case 0x3cf: /* 1 111 001 111 */
+ case 0x3d0: /* 1 111 010 000 */
+ case 0x3d1: /* 1 111 010 001 */
+ case 0x3d2: /* 1 111 010 010 */
+ case 0x3d3: /* 1 111 010 011 */
+ case 0x3d4: /* 1 111 010 100 */
+ case 0x3d5: /* 1 111 010 101 */
+ case 0x3d6: /* 1 111 010 110 */
+ case 0x3d7: /* 1 111 010 111 */
+ case 0x3d8: /* 1 111 011 000 */
+ case 0x3d9: /* 1 111 011 001 */
+ case 0x3da: /* 1 111 011 010 */
+ case 0x3db: /* 1 111 011 011 */
+ case 0x3dc: /* 1 111 011 100 */
+ case 0x3dd: /* 1 111 011 101 */
+ case 0x3de: /* 1 111 011 110 */
+ case 0x3df: /* 1 111 011 111 */
+ case 0x3e0: /* 1 111 100 000 */
+ case 0x3e1: /* 1 111 100 001 */
+ case 0x3e2: /* 1 111 100 010 */
+ case 0x3e3: /* 1 111 100 011 */
+ case 0x3e4: /* 1 111 100 100 */
+ case 0x3e5: /* 1 111 100 101 */
+ case 0x3e6: /* 1 111 100 110 */
+ case 0x3e7: /* 1 111 100 111 */
+ case 0x3e8: /* 1 111 101 000 */
+ case 0x3e9: /* 1 111 101 001 */
+ case 0x3ea: /* 1 111 101 010 */
+ case 0x3eb: /* 1 111 101 011 */
+ case 0x3ec: /* 1 111 101 100 */
+ case 0x3ed: /* 1 111 101 101 */
+ case 0x3ee: /* 1 111 101 110 */
+ case 0x3ef: /* 1 111 101 111 */
+ case 0x3f0: /* 1 111 110 000 */
+ case 0x3f1: /* 1 111 110 001 */
+ case 0x3f2: /* 1 111 110 010 */
+ case 0x3f3: /* 1 111 110 011 */
+ case 0x3f4: /* 1 111 110 100 */
+ case 0x3f5: /* 1 111 110 101 */
+ case 0x3f6: /* 1 111 110 110 */
+ case 0x3f7: /* 1 111 110 111 */
+ sprintf(buffer, "XOR@ (R%01d),R%01d",(op&0x38)>>3,op&0x7);
+ break;
+ case 0x3f8: /* 1 111 111 000 */
+ case 0x3f9: /* 1 111 111 001 */
+ case 0x3fa: /* 1 111 111 010 */
+ case 0x3fb: /* 1 111 111 011 */
+ case 0x3fc: /* 1 111 111 100 */
+ case 0x3fd: /* 1 111 111 101 */
+ case 0x3fe: /* 1 111 111 110 */
+ case 0x3ff: /* 1 111 111 111 */
+ size += 1;
+ ea = oprom16[1];
+ sprintf(buffer, "XORI #%04X,R%01d",ea,op&0x7);
+ break;
+ default:
+ sprintf(buffer, "????");
+ }
+
+ return size;
+}
diff --git a/trunk/src/emu/cpu/cp1610/cp1610.c b/trunk/src/emu/cpu/cp1610/cp1610.c
new file mode 100644
index 00000000000..796cd7e75dc
--- /dev/null
+++ b/trunk/src/emu/cpu/cp1610/cp1610.c
@@ -0,0 +1,3536 @@
+/*****************************************************************************
+ *
+ * cp1610.c
+ * Portable CP1610 emulator (General Instrument CP1610)
+ *
+ * Copyright Frank Palazzolo, all rights reserved.
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * palazzol@comcast.net
+ * - This entire notice must remain in the source code.
+ *
+ * This work is based on Juergen Buchmueller's F8 emulation,
+ * and the 'General Instruments CP1610' data sheets.
+ * Special thanks to Joe Zbiciak for his GPL'd CP1610 emulator
+ *
+ *****************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "cp1610.h"
+
+#define S 0x80
+#define Z 0x40
+#define OV 0x20
+#define C 0x10
+
+typedef struct _cp1610_state cp1610_state;
+struct _cp1610_state
+{
+ UINT16 r[8]; /* registers */
+ UINT8 flags; /* flags */
+ int intr_enabled;
+ //int (*reset_callback)(cp1610_state *cpustate);
+ device_irq_callback irq_callback;
+ UINT16 intr_vector;
+ int reset_state;
+ int intr_state;
+ int intrm_state;
+ int reset_pending;
+ int intr_pending;
+ int intrm_pending;
+ int mask_interrupts;
+ legacy_cpu_device *device;
+ address_space *program;
+ int icount;
+};
+
+INLINE cp1610_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == CP1610);
+ return (cp1610_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+#define cp1610_readop(A) cpustate->program->read_word((A)<<1)
+#define cp1610_readmem16(A) cpustate->program->read_word((A)<<1)
+#define cp1610_writemem16(A,B) cpustate->program->write_word((A)<<1,B)
+
+/* clear all flags */
+#define CLR_SZOC \
+ cpustate->flags &= ~(S|Z|C|OV)
+
+/* clear sign and zero flags */
+#define CLR_SZ \
+ cpustate->flags &= ~(S|Z)
+
+/* clear sign,zero, and carry flags */
+#define CLR_SZC \
+ cpustate->flags &= ~(S|Z|C)
+
+/* set sign and zero flags */
+#define SET_SZ(n) \
+ if (n == 0) \
+ cpustate->flags |= Z; \
+ else \
+ if (n & 0x8000) \
+ cpustate->flags |= S
+
+/* set sign zero, and carry flags */
+#define SET_SZC(n,m) \
+ if (n == 0) \
+ cpustate->flags |= Z; \
+ else \
+ if (n & 0x8000) \
+ cpustate->flags |= S; \
+ if ((n + m) & 0x10000) \
+ cpustate->flags |= C
+
+/* set carry and overflow flags */
+#define SET_COV(n,m,qq) \
+ { unsigned int pp = n + m; \
+ if (pp & 0x10000) \
+ cpustate->flags |= C; \
+ if (qq) \
+ { \
+ if ((n^pp)&(~(m^n))&0x8000) \
+ cpustate->flags |= OV; \
+ if (m == 0x8000) \
+ cpustate->flags ^= OV; \
+ } \
+ else \
+ { \
+ if ((n^pp)&(~(m^n))&0x8000) \
+ cpustate->flags |= OV; \
+ } \
+ }
+
+#if 0
+#define SET_COV(n,m) \
+ if ((n&0x7fff)+(m&0x7fff) > 0x7fff) \
+ { \
+ if (!(cpustate->flags & C))\
+ cpustate->flags |= OV; \
+ } \
+ else \
+ { \
+ if (cpustate->flags & C) \
+ cpustate->flags |= OV; \
+ }
+#endif
+
+/***********************************
+ * illegal opcodes
+ ***********************************/
+static void cp1610_illegal(cp1610_state *cpustate)
+{
+ logerror("cp1610 illegal opcode at 0x%04x\n", cpustate->r[7]);
+}
+
+/***************************************************
+ * S Z C OV 0 000 000 000
+ * - - - - HLT
+ ***************************************************/
+static void cp1610_hlt(cp1610_state *cpustate)
+{
+ /* TBD */
+ cpustate->icount -= 4;
+}
+
+/***************************************************
+ * S Z C OV 0 000 000 010
+ * - - - - EIS
+ ***************************************************/
+static void cp1610_eis(cp1610_state *cpustate)
+{
+ cpustate->mask_interrupts = 1;
+ cpustate->intr_enabled = 1;
+ cpustate->icount -= 4;
+}
+
+/***************************************************
+ * S Z C OV 0 000 000 011
+ * - - - - DIS
+ ***************************************************/
+static void cp1610_dis(cp1610_state *cpustate)
+{
+ cpustate->mask_interrupts = 1;
+ cpustate->intr_enabled = 0;
+ cpustate->icount -= 4;
+}
+
+/***************************************************
+ * S Z C OV 0 000 000 101
+ * - - - - TCI
+ ***************************************************/
+static void cp1610_tci(cp1610_state *cpustate)
+{
+ /* TBD */
+ cpustate->mask_interrupts = 1;
+ cpustate->icount -= 4;
+}
+
+/***************************************************
+ * S Z C OV 0 000 000 110
+ * - - 0 - CLRC
+ ***************************************************/
+static void cp1610_clrc(cp1610_state *cpustate)
+{
+ cpustate->mask_interrupts = 1;
+ cpustate->flags &= ~C;
+ cpustate->icount -= 4;
+}
+
+/***************************************************
+ * S Z C OV 0 000 000 111
+ * - - 1 - SETC
+ ***************************************************/
+static void cp1610_setc(cp1610_state *cpustate)
+{
+ cpustate->mask_interrupts = 1;
+ cpustate->flags |= C;
+ cpustate->icount -= 6;
+}
+
+/***************************************************
+ * S Z C OV 0 000 001 ddd
+ * x x - - INCR Rd
+ ***************************************************/
+static void cp1610_incr(cp1610_state *cpustate, int n)
+{
+ cpustate->r[n]++;
+ CLR_SZ;
+ SET_SZ(cpustate->r[n]);
+ cpustate->icount -= 6;
+}
+
+/***************************************************
+ * S Z C OV 0 000 010 ddd
+ * x x - - DECR Rd
+ ***************************************************/
+static void cp1610_decr(cp1610_state *cpustate, int n)
+{
+ cpustate->r[n]--;
+ CLR_SZ;
+ SET_SZ(cpustate->r[n]);
+ cpustate->icount -= 6;
+}
+
+/***************************************************
+ * S Z C OV 0 000 011 ddd
+ * x x - - COMR Rd
+ ***************************************************/
+static void cp1610_comr(cp1610_state *cpustate, int n)
+{
+ cpustate->r[n] ^= 0xffff;
+ CLR_SZ;
+ SET_SZ(cpustate->r[n]);
+ cpustate->icount -= 6;
+}
+
+/***************************************************
+ * S Z C OV 0 000 100 ddd
+ * x x x x NEGR Rd
+ ***************************************************/
+static void cp1610_negr(cp1610_state *cpustate, int n)
+{
+ UINT32 temp;
+ CLR_SZOC;
+ temp = (cpustate->r[n] ^ 0xffff) + 1;
+ SET_COV(0,temp,1);
+ cpustate->r[n] = temp&0xffff;
+ SET_SZ(cpustate->r[n]);
+ cpustate->icount -= 6;
+}
+
+/***************************************************
+ * S Z C OV 0 000 101 ddd
+ * x x x x ADCR Rd
+ ***************************************************/
+static void cp1610_adcr(cp1610_state *cpustate, int n)
+{
+ UINT16 offset = 0;
+ if (cpustate->flags & C)
+ offset = 1;
+ CLR_SZOC;
+ SET_COV(cpustate->r[n],offset,0);
+ cpustate->r[n] += offset;
+ SET_SZ(cpustate->r[n]);
+ cpustate->icount -= 6;
+}
+
+/***************************************************
+ * S Z C OV 0 000 110 0dd
+ * - - - - GSWD Rd
+ ***************************************************/
+static void cp1610_gswd(cp1610_state *cpustate, int n)
+{
+ cpustate->r[n] = (cpustate->flags << 8) + cpustate->flags;
+ cpustate->icount -= 6;
+}
+
+/***************************************************
+ * S Z C OV 0 000 110 10x
+ * - - - - NOP
+ ***************************************************/
+static void cp1610_nop(cp1610_state *cpustate)
+{
+ cpustate->icount -= 6;
+}
+
+/***************************************************
+ * S Z C OV 0 000 110 11x
+ * - - - - SIN
+ ***************************************************/
+static void cp1610_sin(cp1610_state *cpustate)
+{
+ /* TBD */
+ cpustate->icount -= 6;
+}
+
+/***************************************************
+ * S Z C OV 0 000 111 sss
+ * x x x x RSWD Rs
+ ***************************************************/
+static void cp1610_rswd(cp1610_state *cpustate, int n)
+{
+ cpustate->flags = cpustate->r[n];
+ cpustate->icount -= 6;
+}
+
+/***************************************************
+ * S Z C OV 0 001 000 0rr
+ * x x - - SWAP Rr,1
+ ***************************************************/
+static void cp1610_swap(cp1610_state *cpustate, int r)
+{
+ UINT8 temp;
+ cpustate->mask_interrupts = 1;
+ CLR_SZ;
+ temp = cpustate->r[r] >> 8;
+ cpustate->r[r] = (cpustate->r[r] << 8) | temp;
+ SET_SZ(cpustate->r[r]);
+ /* S flag is set on bit 7 not bit 15 */
+ cpustate->flags &= ~S;
+ if (cpustate->r[r] & 0x80)
+ cpustate->flags |= S;
+ cpustate->icount -= 6;
+}
+
+/***************************************************
+ * S Z C OV 0 001 000 1rr
+ * x x - - SWAP Rr,2
+ ***************************************************/
+static void cp1610_dswap(cp1610_state *cpustate, int r)
+{
+ /* This instruction was not officially supported by GI */
+ UINT16 temp;
+ cpustate->mask_interrupts = 1;
+ CLR_SZ;
+ temp = cpustate->r[r] & 0xff;
+ cpustate->r[r] = (temp << 8) | temp;
+ SET_SZ(cpustate->r[r]);
+ /* S flag is set on bit 7 not bit 15 */
+ cpustate->flags &= ~S;
+ if (cpustate->r[r] & 0x80)
+ cpustate->flags |= S;
+ cpustate->icount -= 8;
+}
+
+/***************************************************
+ * S Z C OV 0 001 001 0rr
+ * x x - - SLL Rr,1
+ ***************************************************/
+static void cp1610_sll_1(cp1610_state *cpustate, int r)
+{
+ cpustate->mask_interrupts = 1;
+ CLR_SZ;
+ cpustate->r[r] <<= 1;
+ SET_SZ(cpustate->r[r]);
+ cpustate->icount -= 6;
+}
+
+/***************************************************
+ * S Z C OV 0 001 001 1rr
+ * x x - - SLL Rr,2
+ ***************************************************/
+static void cp1610_sll_2(cp1610_state *cpustate, int r)
+{
+ cpustate->mask_interrupts = 1;
+ CLR_SZ;
+ cpustate->r[r] <<= 2;
+ SET_SZ(cpustate->r[r]);
+ cpustate->icount -= 8;
+}
+
+/***************************************************
+ * S Z C OV 0 001 010 0rr
+ * x x x - RLC Rr,1
+ ***************************************************/
+static void cp1610_rlc_1(cp1610_state *cpustate, int r)
+{
+ UINT16 offset = 0;
+ cpustate->mask_interrupts = 1;
+ if (cpustate->flags & C)
+ offset = 1;
+ CLR_SZC;
+ if (cpustate->r[r] & 0x8000)
+ cpustate->flags |= C;
+ cpustate->r[r] = (cpustate->r[r] << 1) + offset;
+ SET_SZ(cpustate->r[r]);
+ cpustate->icount -= 6;
+}
+
+/***************************************************
+ * S Z C OV 0 001 010 1rr
+ * x x x x RLC Rr,2
+ ***************************************************/
+static void cp1610_rlc_2(cp1610_state *cpustate, int r)
+{
+ UINT16 offset = 0;
+ cpustate->mask_interrupts = 1;
+ switch(cpustate->flags & (C | OV))
+ {
+ case 0:
+ offset = 0;
+ break;
+ case OV:
+ offset = 1;
+ break;
+ case C:
+ offset = 2;
+ break;
+ case (C | OV):
+ offset = 3;
+ break;
+ }
+
+ CLR_SZOC;
+ if (cpustate->r[r] & 0x8000)
+ cpustate->flags |= C;
+ if (cpustate->r[r] & 0x4000)
+ cpustate->flags |= OV;
+ cpustate->r[r] <<= 2;
+ cpustate->r[r] += offset;
+ SET_SZ(cpustate->r[r]);
+ cpustate->icount -= 8;
+}
+
+/***************************************************
+ * S Z C OV 0 001 011 0rr
+ * x x x - SLLC Rr,1
+ ***************************************************/
+static void cp1610_sllc_1(cp1610_state *cpustate, int r)
+{
+ cpustate->mask_interrupts = 1;
+ CLR_SZC;
+ if (cpustate->r[r] & 0x8000)
+ cpustate->flags |= C;
+ cpustate->r[r] <<= 1;
+ SET_SZ(cpustate->r[r]);
+ cpustate->icount -= 6;
+}
+
+/***************************************************
+ * S Z C OV 0 001 011 1rr
+ * x x x x SLLC Rr,2
+ ***************************************************/
+static void cp1610_sllc_2(cp1610_state *cpustate, int r)
+{
+ cpustate->mask_interrupts = 1;
+ CLR_SZOC;
+ if (cpustate->r[r] & 0x8000)
+ cpustate->flags |= C;
+ if (cpustate->r[r] & 0x4000)
+ cpustate->flags |= OV;
+ cpustate->r[r] <<= 2;
+ SET_SZ(cpustate->r[r]);
+ cpustate->icount -= 8;
+}
+
+/***************************************************
+ * S Z C OV 0 001 100 0rr
+ * x x - - SLR Rr,1
+ ***************************************************/
+static void cp1610_slr_1(cp1610_state *cpustate, int r)
+{
+ cpustate->mask_interrupts = 1;
+ CLR_SZ;
+ cpustate->r[r] >>= 1;
+ SET_SZ(cpustate->r[r]);
+ /* S flag is set on bit 7 not bit 15 */
+ cpustate->flags &= ~S;
+ if (cpustate->r[r] & 0x80)
+ cpustate->flags |= S;
+ cpustate->icount -= 6;
+}
+
+/***************************************************
+ * S Z C OV 0 001 100 1rr
+ * x x - - SLR Rr,2
+ ***************************************************/
+static void cp1610_slr_2(cp1610_state *cpustate, int r)
+{
+ cpustate->mask_interrupts = 1;
+ CLR_SZ;
+ cpustate->r[r] >>= 2;
+ SET_SZ(cpustate->r[r]);
+ /* S flag is set on bit 7 not bit 15 */
+ cpustate->flags &= ~S;
+ if (cpustate->r[r] & 0x80)
+ cpustate->flags |= S;
+ cpustate->icount -= 8;
+}
+
+/***************************************************
+ * S Z C OV 0 001 101 0rr
+ * x x - - SAR Rr,1
+ ***************************************************/
+static void cp1610_sar_1(cp1610_state *cpustate, int r)
+{
+ cpustate->mask_interrupts = 1;
+ CLR_SZ;
+ cpustate->r[r] = (UINT16)(((INT16)(cpustate->r[r])) >> 1);
+ SET_SZ(cpustate->r[r]);
+ /* S flag is set on bit 7 not bit 15 */
+ cpustate->flags &= ~S;
+ if (cpustate->r[r] & 0x80)
+ cpustate->flags |= S;
+ cpustate->icount -= 6;
+}
+
+/***************************************************
+ * S Z C OV 0 001 101 1rr
+ * x x - - SAR Rr,2
+ ***************************************************/
+static void cp1610_sar_2(cp1610_state *cpustate, int r)
+{
+ cpustate->mask_interrupts = 1;
+ CLR_SZ;
+ cpustate->r[r] = (UINT16)(((INT16)(cpustate->r[r])) >> 2);
+ SET_SZ(cpustate->r[r]);
+ /* S flag is set on bit 7 not bit 15 */
+ cpustate->flags &= ~S;
+ if (cpustate->r[r] & 0x80)
+ cpustate->flags |= S;
+ cpustate->icount -= 8;
+}
+
+/***************************************************
+ * S Z C OV 0 001 110 0rr
+ * x x x - RRC Rr,1
+ ***************************************************/
+static void cp1610_rrc_1(cp1610_state *cpustate, int r)
+{
+ UINT16 offset = 0;
+ cpustate->mask_interrupts = 1;
+ if (cpustate->flags & C)
+ offset = 0x8000;
+ CLR_SZC;
+ if (cpustate->r[r] & 1)
+ cpustate->flags |= C;
+ cpustate->r[r] >>= 1;
+ cpustate->r[r] += offset;
+ SET_SZ(cpustate->r[r]);
+ /* S flag is set on bit 7 not bit 15 */
+ cpustate->flags &= ~S;
+ if (cpustate->r[r] & 0x80)
+ cpustate->flags |= S;
+ cpustate->icount -= 6;
+}
+
+/***************************************************
+ * S Z C OV 0 001 110 1rr
+ * x x x x RRC Rr,2
+ ***************************************************/
+static void cp1610_rrc_2(cp1610_state *cpustate, int r)
+{
+ UINT16 offset = 0;
+ cpustate->mask_interrupts = 1;
+ if (cpustate->flags & C)
+ offset |= 0x4000;
+ if (cpustate->flags & OV)
+ offset |= 0x8000;
+ CLR_SZOC;
+ if (cpustate->r[r] & 1)
+ cpustate->flags |= C;
+ if (cpustate->r[r] & 2)
+ cpustate->flags |= OV;
+ cpustate->r[r] >>= 2;
+ cpustate->r[r] += offset;
+ SET_SZ(cpustate->r[r]);
+ /* S flag is set on bit 7 not bit 15 */
+ cpustate->flags &= ~S;
+ if (cpustate->r[r] & 0x80)
+ cpustate->flags |= S;
+ cpustate->icount -= 8;
+}
+
+/***************************************************
+ * S Z C OV 0 001 111 0rr
+ * x x x - SARC Rr,1
+ ***************************************************/
+static void cp1610_sarc_1(cp1610_state *cpustate, int r)
+{
+ cpustate->mask_interrupts = 1;
+ CLR_SZC;
+ if (cpustate->r[r] & 1)
+ cpustate->flags |= C;
+ cpustate->r[r] = (UINT16)(((INT16)cpustate->r[r]) >> 1);
+ SET_SZ(cpustate->r[r]);
+ /* S flag is set on bit 7 not bit 15 */
+ cpustate->flags &= ~S;
+ if (cpustate->r[r] & 0x80)
+ cpustate->flags |= S;
+ cpustate->icount -= 6;
+}
+
+/***************************************************
+ * S Z C OV 0 001 111 1rr
+ * x x x x SARC Rr,2
+ ***************************************************/
+static void cp1610_sarc_2(cp1610_state *cpustate, int r)
+{
+ cpustate->mask_interrupts = 1;
+ CLR_SZOC;
+ if (cpustate->r[r] & 1)
+ cpustate->flags |= C;
+ if (cpustate->r[r] & 2)
+ cpustate->flags |= OV;
+ cpustate->r[r] = (UINT16)(((INT16)cpustate->r[r]) >> 2);
+ SET_SZ(cpustate->r[r]);
+ /* S flag is set on bit 7 not bit 15 */
+ cpustate->flags &= ~S;
+ if (cpustate->r[r] & 0x80)
+ cpustate->flags |= S;
+ cpustate->icount -= 6;
+}
+
+/***************************************************
+ * S Z C OV 0 010 sss sss
+ * x x - - TSTR Rs
+ ***************************************************/
+static void cp1610_tstr(cp1610_state *cpustate, int n)
+{
+ CLR_SZ;
+ SET_SZ(cpustate->r[n]);
+ cpustate->icount -= 6;
+ if (n > 5)
+ cpustate->icount -= 1;
+}
+
+/***************************************************
+ * S Z C OV 0 010 sss ddd (sss != ddd)
+ * x x - - MOVR Rs,Rd
+ ***************************************************/
+static void cp1610_movr(cp1610_state *cpustate, int s, int d)
+{
+ CLR_SZ;
+ cpustate->r[d] = cpustate->r[s];
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 6;
+ if (d > 5)
+ cpustate->icount -= 1;
+}
+
+/***************************************************
+ * S Z C OV 0 011 sss ddd
+ * x x x x ADDR Rs, Rd
+ ***************************************************/
+static void cp1610_addr(cp1610_state *cpustate, int s, int d)
+{
+ CLR_SZOC;
+ SET_COV(cpustate->r[s],cpustate->r[d],0);
+ cpustate->r[d] += cpustate->r[s];
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 6;
+}
+
+/***************************************************
+ * S Z C OV 0 100 sss ddd
+ * x x x x SUBR Rs, Rd
+ ***************************************************/
+static void cp1610_subr(cp1610_state *cpustate, int s, int d)
+{
+ CLR_SZOC;
+ SET_COV(cpustate->r[d],(UINT32)((cpustate->r[s]^0xffff)+1),1);
+ cpustate->r[d] -= cpustate->r[s];
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 6;
+}
+
+/***************************************************
+ * S Z C OV 0 101 sss ddd
+ * x x x x CMPR Rs, Rd
+ ***************************************************/
+static void cp1610_cmpr(cp1610_state *cpustate, int s, int d)
+{
+ UINT16 temp;
+ CLR_SZOC;
+ SET_COV(cpustate->r[d],(UINT32)((cpustate->r[s]^0xffff)+1),1);
+ temp = cpustate->r[d] - cpustate->r[s];
+ SET_SZ(temp);
+ cpustate->icount -= 6;
+}
+
+/***************************************************
+ * S Z C OV 0 110 sss ddd
+ * x x - - ANDR Rs, Rd
+ ***************************************************/
+static void cp1610_andr(cp1610_state *cpustate, int s, int d)
+{
+ CLR_SZ;
+ cpustate->r[d] &= cpustate->r[s];
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 6;
+}
+
+/***************************************************
+ * S Z C OV 0 111 sss ddd (sss != ddd)
+ * x x - - XORR Rs, Rd
+ ***************************************************/
+static void cp1610_xorr(cp1610_state *cpustate, int s, int d)
+{
+ CLR_SZ;
+ cpustate->r[d] ^= cpustate->r[s];
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 6;
+}
+
+/***************************************************
+ * S Z C OV 0 111 ddd ddd
+ * x x - - CLRR Rd
+ ***************************************************/
+static void cp1610_clrr(cp1610_state *cpustate, int d)
+{
+ CLR_SZ;
+ cpustate->r[d] = 0;
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 6;
+}
+
+/***************************************************
+ * S Z C OV 1 000 s00 000 p ppp ppp ppp ppp ppp
+ * - - - - B ADDR
+ ***************************************************/
+static void cp1610_b(cp1610_state *cpustate, int dir)
+{
+ UINT16 offset = cp1610_readop(cpustate->r[7]);
+ cpustate->r[7]++;
+ cpustate->r[7] += (offset ^ dir);
+ cpustate->icount -= 9;
+}
+
+/***************************************************
+ * S Z C OV 1 000 s01 000 p ppp ppp ppp ppp ppp
+ * - - - - NOPP
+ ***************************************************/
+static void cp1610_nopp(cp1610_state *cpustate, int dir)
+{
+ cp1610_readop(cpustate->r[7]);
+ cpustate->r[7]++;
+ cpustate->icount -= 7;
+}
+
+/***************************************************
+ * S Z C OV 1 000 s00 001 p ppp ppp ppp ppp ppp
+ * - - - - BC ADDR
+ ***************************************************/
+static void cp1610_bc(cp1610_state *cpustate, int dir)
+{
+ UINT16 offset = cp1610_readop(cpustate->r[7]);
+ cpustate->r[7]++;
+ if (cpustate->flags & C)
+ {
+ cpustate->r[7] += (offset ^ dir);
+ cpustate->icount -= 9;
+ }
+ else
+ {
+ cpustate->icount -= 7;
+ }
+}
+
+/***************************************************
+ * S Z C OV 1 000 s01 001 p ppp ppp ppp ppp ppp
+ * - - - - BNC ADDR
+ ***************************************************/
+static void cp1610_bnc(cp1610_state *cpustate, int dir)
+{
+ UINT16 offset = cp1610_readop(cpustate->r[7]);
+ cpustate->r[7]++;
+ if (!(cpustate->flags & C))
+ {
+ cpustate->r[7] += (offset ^ dir);
+ cpustate->icount -= 9;
+ }
+ else
+ {
+ cpustate->icount -= 7;
+ }
+}
+
+/***************************************************
+ * S Z C OV 1 000 s00 010 p ppp ppp ppp ppp ppp
+ * - - - - BOV ADDR
+ ***************************************************/
+static void cp1610_bov(cp1610_state *cpustate, int dir)
+{
+ UINT16 offset = cp1610_readop(cpustate->r[7]);
+ cpustate->r[7]++;
+ if (cpustate->flags & OV)
+ {
+ cpustate->r[7] += (offset ^ dir);
+ cpustate->icount -= 9;
+ }
+ else
+ {
+ cpustate->icount -= 7;
+ }
+}
+
+/***************************************************
+ * S Z C OV 1 000 s01 010 p ppp ppp ppp ppp ppp
+ * - - - - BNOV ADDR
+ ***************************************************/
+static void cp1610_bnov(cp1610_state *cpustate, int dir)
+{
+ UINT16 offset = cp1610_readop(cpustate->r[7]);
+ cpustate->r[7]++;
+ if (!(cpustate->flags & OV))
+ {
+ cpustate->r[7] += (offset ^ dir);
+ cpustate->icount -= 9;
+ }
+ else
+ {
+ cpustate->icount -= 7;
+ }
+}
+
+/***************************************************
+ * S Z C OV 1 000 s00 011 p ppp ppp ppp ppp ppp
+ * - - - - BPL ADDR
+ ***************************************************/
+static void cp1610_bpl(cp1610_state *cpustate, int dir)
+{
+ UINT16 offset = cp1610_readop(cpustate->r[7]);
+ cpustate->r[7]++;
+ if (!(cpustate->flags & S))
+ {
+ cpustate->r[7] += (offset ^ dir);
+ cpustate->icount -= 9;
+ }
+ else
+ {
+ cpustate->icount -= 7;
+ }
+}
+
+/***************************************************
+ * S Z C OV 1 000 s01 011 p ppp ppp ppp ppp ppp
+ * - - - - BMI ADDR
+ ***************************************************/
+static void cp1610_bmi(cp1610_state *cpustate, int dir)
+{
+ UINT16 offset = cp1610_readop(cpustate->r[7]);
+ cpustate->r[7]++;
+ if (cpustate->flags & S)
+ {
+ cpustate->r[7] += (offset ^ dir);
+ cpustate->icount -= 9;
+ }
+ else
+ {
+ cpustate->icount -= 7;
+ }
+}
+
+/***************************************************
+ * S Z C OV 1 000 s00 100 p ppp ppp ppp ppp ppp
+ * - - - - BZE ADDR
+ ***************************************************/
+static void cp1610_bze(cp1610_state *cpustate, int dir)
+{
+ UINT16 offset = cp1610_readop(cpustate->r[7]);
+ cpustate->r[7]++;
+ if (cpustate->flags & Z)
+ {
+ cpustate->r[7] += (offset ^ dir);
+ cpustate->icount -= 9;
+ }
+ else
+ {
+ cpustate->icount -= 7;
+ }
+}
+
+/***************************************************
+ * S Z C OV 1 000 s01 100 p ppp ppp ppp ppp ppp
+ * - - - - BNZE ADDR
+ ***************************************************/
+static void cp1610_bnze(cp1610_state *cpustate, int dir)
+{
+ UINT16 offset = cp1610_readop(cpustate->r[7]);
+ cpustate->r[7]++;
+ if (!(cpustate->flags & Z))
+ {
+ cpustate->r[7] += (offset ^ dir);
+ cpustate->icount -= 9;
+ }
+ else
+ {
+ cpustate->icount -= 7;
+ }
+}
+
+/***************************************************
+ * S Z C OV 1 000 s00 101 p ppp ppp ppp ppp ppp
+ * - - - - BLT ADDR
+ ***************************************************/
+static void cp1610_blt(cp1610_state *cpustate, int dir)
+{
+ int condition1 = 0;
+ int condition2 = 0;
+ UINT16 offset = cp1610_readop(cpustate->r[7]);
+ cpustate->r[7]++;
+ if (cpustate->flags & S) condition1 = 1;
+ if (cpustate->flags & OV) condition2 = 1;
+ if (condition1 ^ condition2)
+ {
+ cpustate->r[7] += (offset ^ dir);
+ cpustate->icount -= 9;
+ }
+ else
+ {
+ cpustate->icount -= 7;
+ }
+}
+
+/***************************************************
+ * S Z C OV 1 000 s01 101 p ppp ppp ppp ppp ppp
+ * - - - - BGE ADDR
+ ***************************************************/
+static void cp1610_bge(cp1610_state *cpustate, int dir)
+{
+ int condition1 = 0;
+ int condition2 = 0;
+ UINT16 offset = cp1610_readop(cpustate->r[7]);
+ cpustate->r[7]++;
+ if (cpustate->flags & S) condition1 = 1;
+ if (cpustate->flags & OV) condition2 = 1;
+ if (!(condition1 ^ condition2))
+ {
+ cpustate->r[7] += (offset ^ dir);
+ cpustate->icount -= 9;
+ }
+ else
+ {
+ cpustate->icount -= 7;
+ }
+}
+
+/***************************************************
+ * S Z C OV 1 000 s00 110 p ppp ppp ppp ppp ppp
+ * - - - - BLE ADDR
+ ***************************************************/
+static void cp1610_ble(cp1610_state *cpustate, int dir)
+{
+ int condition1 = 0;
+ int condition2 = 0;
+ UINT16 offset = cp1610_readop(cpustate->r[7]);
+ cpustate->r[7]++;
+ if (cpustate->flags & S) condition1 = 1;
+ if (cpustate->flags & OV) condition2 = 1;
+ if ((cpustate->flags & Z) || (condition1 ^ condition2))
+ {
+ cpustate->r[7] += (offset ^ dir);
+ cpustate->icount -= 9;
+ }
+ else
+ {
+ cpustate->icount -= 7;
+ }
+}
+
+/***************************************************
+ * S Z C OV 1 000 s01 110 p ppp ppp ppp ppp ppp
+ * - - - - BGT ADDR
+ ***************************************************/
+static void cp1610_bgt(cp1610_state *cpustate, int dir)
+{
+ int condition1 = 0;
+ int condition2 = 0;
+ UINT16 offset = cp1610_readop(cpustate->r[7]);
+ cpustate->r[7]++;
+ if (cpustate->flags & S) condition1 = 1;
+ if (cpustate->flags & OV) condition2 = 1;
+ if (!((cpustate->flags & Z) || (condition1 ^ condition2)))
+ {
+ cpustate->r[7] += (offset ^ dir);
+ cpustate->icount -= 9;
+ }
+ else
+ {
+ cpustate->icount -= 7;
+ }
+}
+
+/***************************************************
+ * S Z C OV 1 000 s00 111 p ppp ppp ppp ppp ppp
+ * - - - - BUSC ADDR
+ ***************************************************/
+static void cp1610_busc(cp1610_state *cpustate, int dir)
+{
+ int condition1 = 0;
+ int condition2 = 0;
+ UINT16 offset = cp1610_readop(cpustate->r[7]);
+ cpustate->r[7]++;
+ if (cpustate->flags & C) condition1 = 1;
+ if (cpustate->flags & S) condition2 = 1;
+ if (condition1 ^ condition2)
+ {
+ cpustate->r[7] += (offset ^ dir);
+ cpustate->icount -= 9;
+ }
+ else
+ {
+ cpustate->icount -= 7;
+ }
+}
+
+/***************************************************
+ * S Z C OV 1 000 s01 111 p ppp ppp ppp ppp ppp
+ * - - - - BESC ADDR
+ ***************************************************/
+static void cp1610_besc(cp1610_state *cpustate, int dir)
+{
+ int condition1 = 0;
+ int condition2 = 0;
+ UINT16 offset = cp1610_readop(cpustate->r[7]);
+ cpustate->r[7]++;
+ if (cpustate->flags & C) condition1 = 1;
+ if (cpustate->flags & S) condition2 = 1;
+ if (!(condition1 ^ condition2))
+ {
+ cpustate->r[7] += (offset ^ dir);
+ cpustate->icount -= 9;
+ }
+ else
+ {
+ cpustate->icount -= 7;
+ }
+}
+
+/***************************************************
+ * S Z C OV 1 000 s1e e p ppp ppp ppp ppp ppp
+ * - - - - BEXT ADDR, eeee
+ ***************************************************/
+static void cp1610_bext(cp1610_state *cpustate, int ext, int dir)
+{
+ UINT16 offset = cp1610_readop(cpustate->r[7]);
+ cpustate->r[7]++;
+ /* TBD */
+ if (0)
+ {
+ cpustate->r[7] += (offset ^ dir);
+ cpustate->icount -= 9;
+ }
+ else
+ {
+ cpustate->icount -= 7;
+ }
+}
+
+/***************************************************
+ * S Z C OV 1 001 000 sss a aaa aaa aaa aaa aaa
+ * - - - - MVO Rs, ADDR
+ ***************************************************/
+static void cp1610_mvo(cp1610_state *cpustate, int s)
+{
+ UINT16 addr;
+ cpustate->mask_interrupts = 1;
+ addr = cp1610_readop(cpustate->r[7]);
+ cpustate->r[7]++;
+ cp1610_writemem16(addr,cpustate->r[s]);
+ cpustate->icount -= 11;
+}
+
+/***************************************************
+ * S Z C OV 1 001 mmm sss (mmm = 0xx)
+ * - - - - MVO@ Rs, Rm
+ ***************************************************/
+static void cp1610_mvoat(cp1610_state *cpustate, int s, int m)
+{
+ cpustate->mask_interrupts = 1;
+ cp1610_writemem16(cpustate->r[m],cpustate->r[s]);
+ cpustate->icount -= 9;
+}
+
+/***************************************************
+ * S Z C OV 1 001 mmm sss (m = 10x or 110)
+ * - - - - MVO@ Rs, Rm
+ ***************************************************/
+static void cp1610_mvoat_i(cp1610_state *cpustate, int s, int m)
+{
+ cpustate->mask_interrupts = 1;
+ cp1610_writemem16(cpustate->r[m],cpustate->r[s]);
+ cpustate->r[m]++;
+ cpustate->icount -= 9;
+}
+
+/***************************************************
+ * S Z C OV 1 001 111 sss I III III III III III
+ * - - - - MVOI Rs, II
+ ***************************************************/
+static void cp1610_mvoi(cp1610_state *cpustate, int s)
+{
+ cpustate->mask_interrupts = 1;
+ cp1610_writemem16(cpustate->r[7],cpustate->r[s]);
+ cpustate->r[7]++;
+ cpustate->icount -= 9;
+}
+
+/***************************************************
+ * S Z C OV 1 010 000 ddd a aaa aaa aaa aaa aaa
+ * - - - - MVI ADDR, Rd
+ ***************************************************/
+static void cp1610_mvi(cp1610_state *cpustate, int d)
+{
+ UINT16 addr = cp1610_readop(cpustate->r[7]);
+ cpustate->r[7]++;
+ cpustate->r[d] = cp1610_readmem16(addr);
+ cpustate->icount -= 10;
+}
+
+/***************************************************
+ * S Z C OV 1 010 mmm ddd (mmm = 0xx)
+ * - - - - MVI@ Rm, Rd
+ ***************************************************/
+static void cp1610_mviat(cp1610_state *cpustate, int m, int d)
+{
+ cpustate->r[d] = cp1610_readmem16(cpustate->r[m]);
+ cpustate->icount -= 8;
+}
+
+/***************************************************
+ * S Z C OV 1 010 mmm ddd (mmm = 10x)
+ * - - - - MVI@ Rm, Rd
+ ***************************************************/
+static void cp1610_mviat_i(cp1610_state *cpustate, int m, int d)
+{
+ UINT16 temp = cp1610_readmem16(cpustate->r[m]);
+ cpustate->r[m]++;
+ cpustate->r[d] = temp;
+ cpustate->icount -= 8;
+
+ //cpustate->r[d] = cp1610_readmem16(cpustate->r[m]);
+ //cpustate->r[m]++;
+ //cpustate->icount -= 8;
+}
+
+/***************************************************
+ * S Z C OV 1 010 110 ddd
+ * - - - - PULR Rd
+ ***************************************************/
+static void cp1610_pulr(cp1610_state *cpustate, int d)
+{
+ cpustate->r[6]--;
+ cpustate->r[d] = cp1610_readmem16(cpustate->r[6]);
+ cpustate->icount -= 11;
+}
+
+/***************************************************
+ * S Z C OV 1 010 111 ddd I III III III III III
+ * - - - - MVII II, Rd
+ ***************************************************/
+static void cp1610_mvii(cp1610_state *cpustate, int d)
+{
+ UINT16 temp = cp1610_readop(cpustate->r[7]);
+ cpustate->r[7]++;
+ cpustate->r[d] = temp;
+ cpustate->icount -= 8;
+}
+
+/***************************************************
+ * S Z C OV 1 011 000 ddd a aaa aaa aaa aaa aaa
+ * x x x x ADD ADDR, Rd
+ ***************************************************/
+static void cp1610_add(cp1610_state *cpustate, int d)
+{
+ UINT16 addr = cp1610_readop(cpustate->r[7]);
+ UINT16 data = cp1610_readmem16(addr);
+ cpustate->r[7]++;
+ CLR_SZOC;
+ SET_COV(cpustate->r[d],data,0);
+ cpustate->r[d] += data;
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 10;
+}
+
+/***************************************************
+ * S Z C OV 1 011 mmm ddd (mmm = 0xx)
+ * x x x x ADD@ Rm, Rd
+ ***************************************************/
+static void cp1610_addat(cp1610_state *cpustate, int m, int d)
+{
+ UINT16 data = cp1610_readmem16(cpustate->r[m]);
+ CLR_SZOC;
+ SET_COV(cpustate->r[d],data,0);
+ cpustate->r[d] += data;
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 8;
+}
+
+/***************************************************
+ * S Z C OV 1 011 mmm ddd (mmm = 10x)
+ * x x x x ADD@ Rm, Rd
+ ***************************************************/
+static void cp1610_addat_i(cp1610_state *cpustate, int m, int d)
+{
+ UINT16 data = cp1610_readmem16(cpustate->r[m]);
+ cpustate->r[m]++;
+ CLR_SZOC;
+ SET_COV(cpustate->r[d],data,0);
+ cpustate->r[d] += data;
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 8;
+}
+
+/***************************************************
+ * S Z C OV 1 011 mmm ddd (mmm = 110)
+ * x x x x ADD@ Rm, Rd
+ ***************************************************/
+static void cp1610_addat_d(cp1610_state *cpustate, int m, int d)
+{
+ UINT16 data;
+ cpustate->r[m]--;
+ data = cp1610_readmem16(cpustate->r[m]);
+ CLR_SZOC;
+ SET_COV(cpustate->r[d],data,0);
+ cpustate->r[d] += data;
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 11;
+}
+
+/***************************************************
+ * S Z C OV 1 011 111 ddd I III III III III III
+ * x x x x ADDI II, Rd
+ ***************************************************/
+static void cp1610_addi(cp1610_state *cpustate, int d)
+{
+ UINT16 data;
+ data = cp1610_readop(cpustate->r[7]);
+ cpustate->r[7]++;
+ CLR_SZOC;
+ SET_COV(cpustate->r[d],data,0);
+ cpustate->r[d] += data;
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 8;
+}
+
+/***************************************************
+ * S Z C OV 1 100 000 ddd a aaa aaa aaa aaa aaa
+ * x x x x SUB ADDR, Rd
+ ***************************************************/
+static void cp1610_sub(cp1610_state *cpustate, int d)
+{
+ UINT16 addr = cp1610_readop(cpustate->r[7]);
+ UINT32 data = cp1610_readmem16(addr);
+ cpustate->r[7]++;
+ CLR_SZOC;
+ data = (data ^ 0xffff) + 1;
+ SET_COV(cpustate->r[d],data,1);
+ data &= 0xffff;
+ cpustate->r[d] += data;
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 10;
+}
+
+/***************************************************
+ * S Z C OV 1 100 mmm ddd (mmm = 0xx)
+ * x x x x SUB@ Rm, Rd
+ ***************************************************/
+static void cp1610_subat(cp1610_state *cpustate, int m, int d)
+{
+ UINT32 data = cp1610_readmem16(cpustate->r[m]);
+ CLR_SZOC;
+ data = (data ^ 0xffff) + 1;
+ SET_COV(cpustate->r[d],data,1);
+ data &= 0xffff;
+ cpustate->r[d] += data;
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 8;
+}
+
+/***************************************************
+ * S Z C OV 1 100 mmm ddd (mmm = 10x)
+ * x x x x SUB@ Rm, Rd
+ ***************************************************/
+static void cp1610_subat_i(cp1610_state *cpustate, int m, int d)
+{
+ UINT32 data = cp1610_readmem16(cpustate->r[m]);
+ cpustate->r[m]++;
+ CLR_SZOC;
+ data = (data ^ 0xffff) + 1;
+ SET_COV(cpustate->r[d],data,1);
+ data &= 0xffff;
+ cpustate->r[d] += data;
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 8;
+}
+
+/***************************************************
+ * S Z C OV 1 100 mmm ddd (mmm = 110)
+ * x x x x SUB@ Rm, Rd
+ ***************************************************/
+static void cp1610_subat_d(cp1610_state *cpustate, int m, int d)
+{
+ UINT32 data;
+ cpustate->r[m]--;
+ data = cp1610_readmem16(cpustate->r[m]);
+ CLR_SZOC;
+ data = (data ^ 0xffff) + 1;
+ SET_COV(cpustate->r[d],data,1);
+ data &= 0xffff;
+ cpustate->r[d] += data;
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 11;
+}
+
+/***************************************************
+ * S Z C OV 1 100 111 ddd I III III III III III
+ * x x x x SUBI II, Rd
+ ***************************************************/
+static void cp1610_subi(cp1610_state *cpustate, int d)
+{
+ UINT32 data;
+ data = cp1610_readop(cpustate->r[7]);
+ cpustate->r[7]++;
+ data = (data ^ 0xffff) + 1;
+ CLR_SZOC;
+ SET_COV(cpustate->r[d],data,1);
+ data &= 0xffff;
+ cpustate->r[d] += data;
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 8;
+}
+
+/***************************************************
+ * S Z C OV 1 101 000 ddd a aaa aaa aaa aaa aaa
+ * x x x x CMP ADDR, Rd
+ ***************************************************/
+static void cp1610_cmp(cp1610_state *cpustate, int d)
+{
+ UINT16 addr = cp1610_readop(cpustate->r[7]);
+ UINT32 data = cp1610_readmem16(addr);
+ UINT16 res;
+ cpustate->r[7]++;
+ CLR_SZOC;
+ data = (data ^ 0xffff) + 1;
+ SET_COV(cpustate->r[d],data,1);
+ data &= 0xffff;
+ res = cpustate->r[d] + data;
+ SET_SZ(res);
+ cpustate->icount -= 10;
+}
+
+/***************************************************
+ * S Z C OV 1 101 mmm ddd (mmm = 0xx)
+ * x x x x CMP@ Rm, Rd
+ ***************************************************/
+static void cp1610_cmpat(cp1610_state *cpustate, int m, int d)
+{
+ UINT32 data = cp1610_readmem16(cpustate->r[m]);
+ UINT16 res;
+ CLR_SZOC;
+ data = (data ^ 0xffff) + 1;
+ SET_COV(cpustate->r[d],data,1);
+ data &= 0xffff;
+ res = cpustate->r[d] + data;
+ SET_SZ(res);
+ cpustate->icount -= 8;
+}
+
+/***************************************************
+ * S Z C OV 1 101 mmm ddd (mmm = 10x)
+ * x x x x CMP@ Rm, Rd
+ ***************************************************/
+static void cp1610_cmpat_i(cp1610_state *cpustate, int m, int d)
+{
+ UINT32 data = cp1610_readmem16(cpustate->r[m]);
+ UINT16 res;
+ cpustate->r[m]++;
+ CLR_SZOC;
+ data = (data ^ 0xffff) + 1;
+ SET_COV(cpustate->r[d],data,1);
+ data &= 0xffff;
+ res = cpustate->r[d] + data;
+ SET_SZ(res);
+ cpustate->icount -= 8;
+}
+
+/***************************************************
+ * S Z C OV 1 101 mmm ddd (mmm = 110)
+ * x x x x CMP@ Rm, Rd
+ ***************************************************/
+static void cp1610_cmpat_d(cp1610_state *cpustate, int m, int d)
+{
+ UINT32 data;
+ UINT16 res;
+ cpustate->r[m]--;
+ data = cp1610_readmem16(cpustate->r[m]);
+ CLR_SZOC;
+ data = (data ^ 0xffff) + 1;
+ SET_COV(cpustate->r[d],data,1);
+ data &= 0xffff;
+ res = cpustate->r[d] + data;
+ SET_SZ(res);
+ cpustate->icount -= 11;
+}
+
+/***************************************************
+ * S Z C OV 1 101 111 ddd I III III III III III
+ * x x x x CMPI II, Rd
+ ***************************************************/
+static void cp1610_cmpi(cp1610_state *cpustate, int d)
+{
+ UINT32 data;
+ UINT16 res;
+ data = cp1610_readop(cpustate->r[7]);
+ cpustate->r[7]++;
+ data = (data ^ 0xffff) + 1;
+ CLR_SZOC;
+ SET_COV(cpustate->r[d],data,1);
+ data &= 0xffff;
+ res = cpustate->r[d] + data;
+ SET_SZ(res);
+ cpustate->icount -= 8;
+}
+
+/***************************************************
+ * S Z C OV 1 110 000 ddd a aaa aaa aaa aaa aaa
+ * x x - - AND ADDR, Rd
+ ***************************************************/
+static void cp1610_and(cp1610_state *cpustate, int d)
+{
+ UINT16 addr = cp1610_readop(cpustate->r[7]);
+ UINT16 data = cp1610_readmem16(addr);
+ cpustate->r[7]++;
+ CLR_SZ;
+ cpustate->r[d] &= data;
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 10;
+}
+
+/***************************************************
+ * S Z C OV 1 110 mmm ddd (mmm = 0xx)
+ * x x - - AND@ Rm, Rd
+ ***************************************************/
+static void cp1610_andat(cp1610_state *cpustate, int m, int d)
+{
+ UINT16 data = cp1610_readmem16(cpustate->r[m]);
+ CLR_SZ;
+ cpustate->r[d] &= data;
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 8;
+}
+
+/***************************************************
+ * S Z C OV 1 110 mmm ddd (mmm = 10x)
+ * x x - - AND@ Rm, Rd
+ ***************************************************/
+static void cp1610_andat_i(cp1610_state *cpustate, int m, int d)
+{
+ UINT16 data = cp1610_readmem16(cpustate->r[m]);
+ cpustate->r[m]++;
+ CLR_SZ;
+ cpustate->r[d] &= data;
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 8;
+}
+
+/***************************************************
+ * S Z C OV 1 110 mmm ddd (mmm = 110)
+ * x x - - AND@ Rm, Rd
+ ***************************************************/
+static void cp1610_andat_d(cp1610_state *cpustate, int m, int d)
+{
+ UINT16 data;
+ cpustate->r[m]--;
+ data = cp1610_readmem16(cpustate->r[m]);
+ CLR_SZ;
+ cpustate->r[d] &= data;
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 11;
+}
+
+/***************************************************
+ * S Z C OV 1 110 111 ddd I III III III III III
+ * x x - - AND II, Rd
+ ***************************************************/
+static void cp1610_andi(cp1610_state *cpustate, int d)
+{
+ UINT16 data;
+ data = cp1610_readop(cpustate->r[7]);
+ cpustate->r[7]++;
+ CLR_SZ;
+ cpustate->r[d] &= data;
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 8;
+}
+
+/***************************************************
+ * S Z C OV 1 111 000 ddd a aaa aaa aaa aaa aaa
+ * x x - - XOR ADDR, Rd
+ ***************************************************/
+static void cp1610_xor(cp1610_state *cpustate, int d)
+{
+ UINT16 addr = cp1610_readop(cpustate->r[7]);
+ UINT16 data = cp1610_readmem16(addr);
+ cpustate->r[7]++;
+ CLR_SZ;
+ cpustate->r[d] ^= data;
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 10;
+}
+
+/***************************************************
+ * S Z C OV 1 111 mmm ddd (mmm = 0xx)
+ * x x - - XOR@ Rm, Rd
+ ***************************************************/
+static void cp1610_xorat(cp1610_state *cpustate, int m, int d)
+{
+ UINT16 data = cp1610_readmem16(cpustate->r[m]);
+ CLR_SZ;
+ cpustate->r[d] ^= data;
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 8;
+}
+
+/***************************************************
+ * S Z C OV 1 111 mmm ddd (mmm = 10x)
+ * x x - - XOR@ Rm, Rd
+ ***************************************************/
+static void cp1610_xorat_i(cp1610_state *cpustate, int m, int d)
+{
+ UINT16 data = cp1610_readmem16(cpustate->r[m]);
+ cpustate->r[m]++;
+ CLR_SZ;
+ cpustate->r[d] ^= data;
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 8;
+}
+
+/***************************************************
+ * S Z C OV 1 111 mmm ddd (mmm = 110)
+ * x x - - XOR@ Rm, Rd
+ ***************************************************/
+static void cp1610_xorat_d(cp1610_state *cpustate, int m, int d)
+{
+ UINT16 data;
+ cpustate->r[m]--;
+ data = cp1610_readmem16(cpustate->r[m]);
+ CLR_SZ;
+ cpustate->r[d] ^= data;
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 11;
+}
+
+/***************************************************
+ * S Z C OV 1 111 111 ddd I III III III III III
+ * x x - - XOR II, Rd
+ ***************************************************/
+static void cp1610_xori(cp1610_state *cpustate, int d)
+{
+ UINT16 data;
+ data = cp1610_readop(cpustate->r[7]);
+ cpustate->r[7]++;
+ CLR_SZ;
+ cpustate->r[d] ^= data;
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 8;
+}
+
+static CPU_RESET( cp1610 )
+{
+ /* This is how we set the reset vector */
+ device_set_input_line(device, CP1610_RESET, PULSE_LINE);
+}
+
+/***************************************************
+ * S Z C OV 0x001 1 010 mmm ddd (mmm = 0xx)
+ * - - - - SDBD, MVI@ Rm, Rd
+ ***************************************************/
+static void cp1610_sdbd_mviat(cp1610_state *cpustate, int r, int d)
+{
+ cpustate->r[d] = cp1610_readmem16(cpustate->r[r]) & 0xff;
+ cpustate->r[d] |= (cp1610_readmem16(cpustate->r[r]) << 8);
+ cpustate->icount -= 14;
+}
+
+/***************************************************
+ * S Z C OV 0x001 1 010 mmm ddd (mmm = 10x)
+ * - - - - SDBD, MVI@ Rm, Rd
+ ***************************************************/
+static void cp1610_sdbd_mviat_i(cp1610_state *cpustate, int r, int d)
+{
+ UINT16 temp;
+ temp = cp1610_readmem16(cpustate->r[r]) & 0xff;
+ cpustate->r[r]++;
+ cpustate->r[d] = temp;
+ temp = (cp1610_readmem16(cpustate->r[r]) << 8);
+ cpustate->r[r]++;
+ cpustate->r[d] |= temp;
+ cpustate->icount -= 14;
+}
+
+/***************************************************
+ * S Z C OV 0x001 1 010 mmm ddd (mmm = 101)
+ * - - - - SDBD, MVI@ Rm, Rd
+ ***************************************************/
+static void cp1610_sdbd_mviat_d(cp1610_state *cpustate, int r, int d)
+{
+ cpustate->r[r]--;
+ cpustate->r[d] = cp1610_readmem16(cpustate->r[r]) & 0xff;
+ cpustate->r[r]--;
+ cpustate->r[d] |= (cp1610_readmem16(cpustate->r[r]) << 8);
+ cpustate->icount -= 17;
+}
+
+/************************************************************************
+ * S Z C OV 0x001 1 010 111 ddd x xxx xLL LLL LLL x xxx xUU UUU UUU
+ * - - - - SDBD, MVII I-I, Rd
+ ************************************************************************/
+static void cp1610_sdbd_mvii(cp1610_state *cpustate, int d)
+{
+ UINT16 addr;
+ addr = cp1610_readop(cpustate->r[7]) & 0xff;
+ cpustate->r[7]++;
+ addr |= (cp1610_readop(cpustate->r[7]) << 8);
+ cpustate->r[7]++;
+ cpustate->r[d] = addr;
+ cpustate->icount -= 14;
+}
+
+/***************************************************
+ * S Z C OV 0x001 1 011 mmm ddd (mmm = 0xx)
+ * x x x x SDBD, ADD@ Rm, Rd
+ ***************************************************/
+static void cp1610_sdbd_addat(cp1610_state *cpustate, int r, int d)
+{
+ UINT16 temp;
+ CLR_SZOC;
+ temp = cp1610_readmem16(cpustate->r[r]) & 0xff;
+ temp |= (cp1610_readmem16(cpustate->r[r]) << 8);
+ SET_COV(cpustate->r[d],temp,0);
+ cpustate->r[d] += temp;
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 14;
+}
+
+/***************************************************
+ * S Z C OV 0x001 1 011 mmm ddd (mmm = 10x)
+ * x x x x SDBD, ADD@ Rm, Rd
+ ***************************************************/
+static void cp1610_sdbd_addat_i(cp1610_state *cpustate, int r, int d)
+{
+ UINT16 temp;
+ CLR_SZOC;
+ temp = cp1610_readmem16(cpustate->r[r]) & 0xff;
+ cpustate->r[r]++;
+ temp |= (cp1610_readmem16(cpustate->r[r]) << 8);
+ cpustate->r[r]++;
+ SET_COV(cpustate->r[d],temp,0);
+ cpustate->r[d] += temp;
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 14;
+}
+
+/***************************************************
+ * S Z C OV 0x001 1 011 mmm ddd (mmm = 101)
+ * x x x x SDBD, ADD@ Rm, Rd
+ ***************************************************/
+static void cp1610_sdbd_addat_d(cp1610_state *cpustate, int r, int d)
+{
+ UINT16 temp;
+ CLR_SZOC;
+ cpustate->r[r]--;
+ temp = cp1610_readmem16(cpustate->r[r]) & 0xff;
+ cpustate->r[r]--;
+ temp |= (cp1610_readmem16(cpustate->r[r]) << 8);
+ SET_COV(cpustate->r[d],temp,0);
+ cpustate->r[d] += temp;
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 17;
+}
+
+/************************************************************************
+ * S Z C OV 0x001 1 011 111 ddd x xxx xLL LLL LLL x xxx xUU UUU UUU
+ * x x x x SDBD, ADDI I-I, Rd
+ ************************************************************************/
+static void cp1610_sdbd_addi(cp1610_state *cpustate, int d)
+{
+ UINT16 addr;
+ UINT16 temp;
+ CLR_SZOC;
+ addr = cp1610_readop(cpustate->r[7]) & 0xff;
+ cpustate->r[7]++;
+ addr |= (cp1610_readop(cpustate->r[7]) << 8);
+ cpustate->r[7]++;
+ temp = addr;
+ SET_COV(cpustate->r[d],temp,0);
+ cpustate->r[d] += temp;
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 14;
+}
+
+/***************************************************
+ * S Z C OV 0x001 1 100 mmm ddd (mmm = 0xx)
+ * x x x x SDBD, SUB@ Rm, Rd
+ ***************************************************/
+static void cp1610_sdbd_subat(cp1610_state *cpustate, int r, int d)
+{
+ UINT32 temp;
+ CLR_SZOC;
+ temp = cp1610_readmem16(cpustate->r[r]) & 0xff;
+ temp |= (cp1610_readmem16(cpustate->r[r]) << 8);
+ temp = (temp ^ 0xffff) + 1;
+ SET_COV(cpustate->r[d],temp,1);
+ temp &= 0xffff;
+ cpustate->r[d] += temp;
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 14;
+}
+
+/***************************************************
+ * S Z C OV 0x001 1 100 mmm ddd (mmm = 10x)
+ * x x x x SDBD, SUB@ Rm, Rd
+ ***************************************************/
+static void cp1610_sdbd_subat_i(cp1610_state *cpustate, int r, int d)
+{
+ UINT32 temp;
+ CLR_SZOC;
+ temp = cp1610_readmem16(cpustate->r[r]) & 0xff;
+ cpustate->r[r]++;
+ temp |= (cp1610_readmem16(cpustate->r[r]) << 8);
+ cpustate->r[r]++;
+ temp = (temp ^ 0xffff) + 1;
+ SET_COV(cpustate->r[d],temp,1);
+ temp &= 0xffff;
+ cpustate->r[d] += temp;
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 14;
+}
+
+/***************************************************
+ * S Z C OV 0x001 1 100 mmm ddd (mmm = 101)
+ * x x x x SDBD, SUB@ Rm, Rd
+ ***************************************************/
+static void cp1610_sdbd_subat_d(cp1610_state *cpustate, int r, int d)
+{
+ UINT32 temp;
+ CLR_SZOC;
+ cpustate->r[r]--;
+ temp = cp1610_readmem16(cpustate->r[r]) & 0xff;
+ cpustate->r[r]--;
+ temp |= (cp1610_readmem16(cpustate->r[r]) << 8);
+ temp = (temp ^ 0xffff) + 1;
+ SET_COV(cpustate->r[d],temp,1);
+ temp &= 0xffff;
+ cpustate->r[d] += temp;
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 17;
+}
+
+/************************************************************************
+ * S Z C OV 0x001 1 100 111 ddd x xxx xLL LLL LLL x xxx xUU UUU UUU
+ * x x x x SDBD, SUBI I-I, Rd
+ ************************************************************************/
+static void cp1610_sdbd_subi(cp1610_state *cpustate, int d)
+{
+ UINT16 addr;
+ UINT32 temp;
+ CLR_SZOC;
+ addr = cp1610_readop(cpustate->r[7]) & 0xff;
+ cpustate->r[7]++;
+ addr |= (cp1610_readop(cpustate->r[7]) << 8);
+ cpustate->r[7]++;
+ temp = addr;
+ temp = (temp ^ 0xffff) + 1;
+ SET_COV(cpustate->r[d],temp,1);
+ temp &= 0xffff;
+ cpustate->r[d] += temp;
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 14;
+}
+
+/***************************************************
+ * S Z C OV 0x001 1 101 mmm ddd (mmm = 0xx)
+ * x x x x SDBD, CMP@ Rm, Rd
+ ***************************************************/
+static void cp1610_sdbd_cmpat(cp1610_state *cpustate, int r, int d)
+{
+ UINT32 temp;
+ UINT16 temp2;
+ CLR_SZOC;
+ temp = cp1610_readmem16(cpustate->r[r]) & 0xff;
+ temp |= (cp1610_readmem16(cpustate->r[r]) << 8);
+ temp = (temp ^ 0xffff) + 1;
+ SET_COV(cpustate->r[d],temp,1);
+ temp &= 0xffff;
+ temp2 = cpustate->r[d] + temp;
+ SET_SZ(temp2);
+ cpustate->icount -= 14;
+}
+
+/***************************************************
+ * S Z C OV 0x001 1 101 mmm ddd (mmm = 10x)
+ * x x x x SDBD, CMP@ Rm, Rd
+ ***************************************************/
+static void cp1610_sdbd_cmpat_i(cp1610_state *cpustate, int r, int d)
+{
+ UINT32 temp;
+ UINT16 temp2;
+ CLR_SZOC;
+ temp = cp1610_readmem16(cpustate->r[r]) & 0xff;
+ cpustate->r[r]++;
+ temp |= (cp1610_readmem16(cpustate->r[r]) << 8);
+ cpustate->r[r]++;
+ temp = (temp ^ 0xffff) + 1;
+ SET_COV(cpustate->r[d],temp,1);
+ temp &= 0xffff;
+ temp2 = cpustate->r[d] + temp;
+ SET_SZ(temp2);
+ cpustate->icount -= 14;
+}
+
+/***************************************************
+ * S Z C OV 0x001 1 101 mmm ddd (mmm = 101)
+ * x x x x SDBD, CMP@ Rm, Rd
+ ***************************************************/
+static void cp1610_sdbd_cmpat_d(cp1610_state *cpustate, int r, int d)
+{
+ UINT32 temp;
+ UINT16 temp2;
+ CLR_SZOC;
+ cpustate->r[r]--;
+ temp = cp1610_readmem16(cpustate->r[r]) & 0xff;
+ cpustate->r[r]--;
+ temp |= (cp1610_readmem16(cpustate->r[r]) << 8);
+ temp = (temp ^ 0xffff) + 1;
+ SET_COV(cpustate->r[d],temp,1);
+ temp &= 0xffff;
+ temp2 = cpustate->r[d] + temp;
+ SET_SZ(temp2);
+ cpustate->icount -= 17;
+}
+
+/************************************************************************
+ * S Z C OV 0x001 1 101 111 ddd x xxx xLL LLL LLL x xxx xUU UUU UUU
+ * x x x x SDBD, CMPI I-I, Rd
+ ************************************************************************/
+static void cp1610_sdbd_cmpi(cp1610_state *cpustate, int d)
+{
+ UINT16 addr;
+ UINT32 temp;
+ UINT16 temp2;
+ CLR_SZOC;
+ addr = cp1610_readop(cpustate->r[7]) & 0xff;
+ cpustate->r[7]++;
+ addr |= (cp1610_readop(cpustate->r[7]) << 8);
+ cpustate->r[7]++;
+ temp = addr;
+ temp = (temp ^ 0xffff) + 1;
+ SET_COV(cpustate->r[d],temp,1);
+ temp &= 0xffff;
+ temp2 = cpustate->r[d] + temp;
+ SET_SZ(temp2);
+ cpustate->icount -= 14;
+}
+
+/***************************************************
+ * S Z C OV 0x001 1 110 mmm ddd (mmm = 0xx)
+ * x x - - SDBD, AND@ Rm, Rd
+ ***************************************************/
+static void cp1610_sdbd_andat(cp1610_state *cpustate, int r, int d)
+{
+ UINT16 temp;
+ CLR_SZ;
+ temp = cp1610_readmem16(cpustate->r[r]) & 0xff;
+ temp |= (cp1610_readmem16(cpustate->r[r]) << 8);
+ cpustate->r[d] &= temp;
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 14;
+}
+
+/***************************************************
+ * S Z C OV 0x001 1 110 mmm ddd (mmm = 10x)
+ * x x - - SDBD, AND@ Rm, Rd
+ ***************************************************/
+static void cp1610_sdbd_andat_i(cp1610_state *cpustate, int r, int d)
+{
+ UINT16 temp;
+ CLR_SZ;
+ temp = cp1610_readmem16(cpustate->r[r]) & 0xff;
+ cpustate->r[r]++;
+ temp |= (cp1610_readmem16(cpustate->r[r]) << 8);
+ cpustate->r[r]++;
+ cpustate->r[d] &= temp;
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 14;
+}
+
+/***************************************************
+ * S Z C OV 0x001 1 110 mmm ddd (mmm = 101)
+ * x x - - SDBD, AND@ Rm, Rd
+ ***************************************************/
+static void cp1610_sdbd_andat_d(cp1610_state *cpustate, int r, int d)
+{
+ UINT16 temp;
+ CLR_SZ;
+ cpustate->r[r]--;
+ temp = cp1610_readmem16(cpustate->r[r]) & 0xff;
+ cpustate->r[r]--;
+ temp |= (cp1610_readmem16(cpustate->r[r]) << 8);
+ cpustate->r[d] &= temp;
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 17;
+}
+
+/************************************************************************
+ * S Z C OV 0x001 1 110 111 ddd x xxx xLL LLL LLL x xxx xUU UUU UUU
+ * x x - - SDBD, ANDI I-I, Rd
+ ************************************************************************/
+static void cp1610_sdbd_andi(cp1610_state *cpustate, int d)
+{
+ UINT16 addr;
+ CLR_SZ;
+ addr = cp1610_readop(cpustate->r[7]) & 0xff;
+ cpustate->r[7]++;
+ addr |= (cp1610_readop(cpustate->r[7]) << 8);
+ cpustate->r[7]++;
+ cpustate->r[d] &= addr;
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 14;
+}
+
+/***************************************************
+ * S Z C OV 0x001 1 111 mmm ddd (mmm = 0xx)
+ * x x - - SDBD, XOR@ Rm, Rd
+ ***************************************************/
+static void cp1610_sdbd_xorat(cp1610_state *cpustate, int r, int d)
+{
+ UINT16 temp;
+ CLR_SZ;
+ temp = cp1610_readmem16(cpustate->r[r]) & 0xff;
+ temp |= (cp1610_readmem16(cpustate->r[r]) << 8);
+ cpustate->r[d] ^= temp;
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 14;
+}
+
+/***************************************************
+ * S Z C OV 0x001 1 111 mmm ddd (mmm = 10x)
+ * x x - - SDBD, XOR@ Rm, Rd
+ ***************************************************/
+static void cp1610_sdbd_xorat_i(cp1610_state *cpustate, int r, int d)
+{
+ UINT16 temp;
+ CLR_SZ;
+ temp = cp1610_readmem16(cpustate->r[r]) & 0xff;
+ cpustate->r[r]++;
+ temp |= (cp1610_readmem16(cpustate->r[r]) << 8);
+ cpustate->r[r]++;
+ cpustate->r[d] ^= temp;
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 14;
+}
+
+/***************************************************
+ * S Z C OV 0x001 1 111 mmm ddd (mmm = 101)
+ * x x - - SDBD, XOR@ Rm, Rd
+ ***************************************************/
+static void cp1610_sdbd_xorat_d(cp1610_state *cpustate, int r, int d)
+{
+ UINT16 temp;
+ CLR_SZ;
+ cpustate->r[r]--;
+ temp = cp1610_readmem16(cpustate->r[r]) & 0xff;
+ cpustate->r[r]--;
+ temp |= (cp1610_readmem16(cpustate->r[r]) << 8);
+ cpustate->r[d] ^= temp;
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 17;
+}
+
+/************************************************************************
+ * S Z C OV 0x001 1 111 111 ddd x xxx xLL LLL LLL x xxx xUU UUU UUU
+ * x x - - SDBD, XORI I-I, Rd
+ ************************************************************************/
+static void cp1610_sdbd_xori(cp1610_state *cpustate, int d)
+{
+ UINT16 addr;
+ CLR_SZ;
+ addr = cp1610_readop(cpustate->r[7]) & 0xff;
+ cpustate->r[7]++;
+ addr |= (cp1610_readop(cpustate->r[7]) << 8);
+ cpustate->r[7]++;
+ cpustate->r[d] ^= addr;
+ SET_SZ(cpustate->r[d]);
+ cpustate->icount -= 14;
+}
+
+/***************************************************
+ * S Z C OV b baa aaa a00 x xxx xxa aaa aaa aaa
+ * - - - - JSR R1bb, ADDR
+ ***************************************************/
+static void cp1610_jsr(cp1610_state *cpustate, int r, UINT16 addr)
+{
+ cpustate->r[r] = cpustate->r[7];
+ cpustate->r[7] = addr;
+}
+
+/***************************************************
+ * S Z C OV b baa aaa a01 x xxx xxa aaa aaa aaa
+ * - - - - JSRE R1bb, ADDR
+ ***************************************************/
+static void cp1610_jsre(cp1610_state *cpustate, int r, UINT16 addr)
+{
+ cpustate->r[r] = cpustate->r[7];
+ cpustate->r[7] = addr;
+ cpustate->intr_enabled = 1;
+}
+
+/***************************************************
+ * S Z C OV b baa aaa a10 x xxx xxa aaa aaa aaa
+ * - - - - JSRD R1bb, ADDR
+ ***************************************************/
+static void cp1610_jsrd(cp1610_state *cpustate, int r, UINT16 addr)
+{
+ cpustate->r[r] = cpustate->r[7];
+ cpustate->r[7] = addr;
+ cpustate->intr_enabled = 0;
+}
+
+/***************************************************
+ * S Z C OV 1 1aa aaa a00 x xxx xxa aaa aaa aaa
+ * - - - - J ADDR
+ ***************************************************/
+static void cp1610_j(cp1610_state *cpustate, UINT16 addr)
+{
+ cpustate->r[7] = addr;
+}
+
+/***************************************************
+ * S Z C OV 1 1aa aaa a01 x xxx xxa aaa aaa aaa
+ * - - - - JE ADDR
+ ***************************************************/
+static void cp1610_je(cp1610_state *cpustate, UINT16 addr)
+{
+ cpustate->r[7] = addr;
+ cpustate->intr_enabled = 1;
+}
+
+/***************************************************
+ * S Z C OV 1 1aa aaa a10 x xxx xxa aaa aaa aaa
+ * - - - - JD ADDR
+ ***************************************************/
+static void cp1610_jd(cp1610_state *cpustate, UINT16 addr)
+{
+ cpustate->r[7] = addr;
+ cpustate->intr_enabled = 0;
+}
+
+static void cp1610_do_sdbd(cp1610_state *cpustate)
+{
+ UINT16 sdbdtype, dest;
+
+ /* Even though SDBD is uninterruptable, we don't need to set the mask bit,
+ * because we already treat the SDBD prefixed instructions as uninterruptable
+ */
+ //cpustate->mask_interrupts = 1;
+
+ sdbdtype = cp1610_readop(cpustate->r[7]);
+ dest = sdbdtype & 0x07;
+ cpustate->r[7]++;
+
+ switch (sdbdtype & 0x3f8)
+ {
+ case 0x240: /* Not supporting SDBD MVO@ or SDBD MVOI for now */
+ case 0x248:
+ case 0x250:
+ case 0x258:
+ case 0x260:
+ case 0x268:
+ case 0x270:
+ case 0x278: /* 1 001 xxx xxx */ cp1610_illegal(cpustate); break;
+
+ case 0x280: /* 1 010 000 xxx */ cp1610_sdbd_mviat(cpustate, 0,dest); break;
+ case 0x288: /* 1 010 001 xxx */ cp1610_sdbd_mviat(cpustate, 1,dest); break;
+ case 0x290: /* 1 010 010 xxx */ cp1610_sdbd_mviat(cpustate, 2,dest); break;
+ case 0x298: /* 1 010 011 xxx */ cp1610_sdbd_mviat(cpustate, 3,dest); break;
+ case 0x2a0: /* 1 010 100 xxx */ cp1610_sdbd_mviat_i(cpustate, 4,dest); break;
+ case 0x2a8: /* 1 010 101 xxx */ cp1610_sdbd_mviat_i(cpustate, 5,dest); break;
+ case 0x2b0: /* 1 010 110 xxx */ cp1610_sdbd_mviat_d(cpustate, 6,dest); break; /* ??? */
+ case 0x2b8: /* 1 010 111 xxx */ cp1610_sdbd_mvii(cpustate, dest); break;
+
+ case 0x2c0: /* 1 011 000 xxx */ cp1610_sdbd_addat(cpustate, 0,dest); break;
+ case 0x2c8: /* 1 011 001 xxx */ cp1610_sdbd_addat(cpustate, 1,dest); break;
+ case 0x2d0: /* 1 011 010 xxx */ cp1610_sdbd_addat(cpustate, 2,dest); break;
+ case 0x2d8: /* 1 011 011 xxx */ cp1610_sdbd_addat(cpustate, 3,dest); break;
+ case 0x2e0: /* 1 011 100 xxx */ cp1610_sdbd_addat_i(cpustate, 4,dest); break;
+ case 0x2e8: /* 1 011 101 xxx */ cp1610_sdbd_addat_i(cpustate, 5,dest); break;
+ case 0x2f0: /* 1 011 110 xxx */ cp1610_sdbd_addat_d(cpustate, 6,dest); break; /* ??? */
+ case 0x2f8: /* 1 011 111 xxx */ cp1610_sdbd_addi(cpustate, dest); break;
+
+ case 0x300: /* 1 100 000 xxx */ cp1610_sdbd_subat(cpustate, 0,dest); break;
+ case 0x308: /* 1 100 001 xxx */ cp1610_sdbd_subat(cpustate, 1,dest); break;
+ case 0x310: /* 1 100 010 xxx */ cp1610_sdbd_subat(cpustate, 2,dest); break;
+ case 0x318: /* 1 100 011 xxx */ cp1610_sdbd_subat(cpustate, 3,dest); break;
+ case 0x320: /* 1 100 100 xxx */ cp1610_sdbd_subat_i(cpustate, 4,dest); break;
+ case 0x328: /* 1 100 101 xxx */ cp1610_sdbd_subat_i(cpustate, 5,dest); break;
+ case 0x330: /* 1 100 110 xxx */ cp1610_sdbd_subat_d(cpustate, 6,dest); break; /* ??? */
+ case 0x338: /* 1 100 111 xxx */ cp1610_sdbd_subi(cpustate, dest); break;
+
+ case 0x340: /* 1 101 000 xxx */ cp1610_sdbd_cmpat(cpustate, 0,dest); break;
+ case 0x348: /* 1 101 001 xxx */ cp1610_sdbd_cmpat(cpustate, 1,dest); break;
+ case 0x350: /* 1 101 010 xxx */ cp1610_sdbd_cmpat(cpustate, 2,dest); break;
+ case 0x358: /* 1 101 011 xxx */ cp1610_sdbd_cmpat(cpustate, 3,dest); break;
+ case 0x360: /* 1 101 100 xxx */ cp1610_sdbd_cmpat_i(cpustate, 4,dest); break;
+ case 0x368: /* 1 101 101 xxx */ cp1610_sdbd_cmpat_i(cpustate, 5,dest); break;
+ case 0x370: /* 1 101 110 xxx */ cp1610_sdbd_cmpat_d(cpustate, 6,dest); break; /* ??? */
+ case 0x378: /* 1 101 111 xxx */ cp1610_sdbd_cmpi(cpustate, dest); break;
+
+ case 0x380: /* 1 110 000 xxx */ cp1610_sdbd_andat(cpustate, 0,dest); break;
+ case 0x388: /* 1 110 001 xxx */ cp1610_sdbd_andat(cpustate, 1,dest); break;
+ case 0x390: /* 1 110 010 xxx */ cp1610_sdbd_andat(cpustate, 2,dest); break;
+ case 0x398: /* 1 110 011 xxx */ cp1610_sdbd_andat(cpustate, 3,dest); break;
+ case 0x3a0: /* 1 110 100 xxx */ cp1610_sdbd_andat_i(cpustate, 4,dest); break;
+ case 0x3a8: /* 1 110 101 xxx */ cp1610_sdbd_andat_i(cpustate, 5,dest); break;
+ case 0x3b0: /* 1 110 110 xxx */ cp1610_sdbd_andat_d(cpustate, 6,dest); break; /* ??? */
+ case 0x3b8: /* 1 110 111 xxx */ cp1610_sdbd_andi(cpustate, dest); break;
+
+ case 0x3c0: /* 1 110 000 xxx */ cp1610_sdbd_xorat(cpustate, 0,dest); break;
+ case 0x3c8: /* 1 110 001 xxx */ cp1610_sdbd_xorat(cpustate, 1,dest); break;
+ case 0x3d0: /* 1 110 010 xxx */ cp1610_sdbd_xorat(cpustate, 2,dest); break;
+ case 0x3d8: /* 1 110 011 xxx */ cp1610_sdbd_xorat(cpustate, 3,dest); break;
+ case 0x3e0: /* 1 110 100 xxx */ cp1610_sdbd_xorat_i(cpustate, 4,dest); break;
+ case 0x3e8: /* 1 110 101 xxx */ cp1610_sdbd_xorat_i(cpustate, 5,dest); break;
+ case 0x3f0: /* 1 110 110 xxx */ cp1610_sdbd_xorat_d(cpustate, 6,dest); break; /* ??? */
+ case 0x3f8: /* 1 110 111 xxx */ cp1610_sdbd_xori(cpustate, dest); break;
+ default: cp1610_illegal(cpustate); break;
+ }
+}
+
+static void cp1610_do_jumps(cp1610_state *cpustate)
+{
+ UINT16 jumptype, arg1, arg2, addr;
+
+ arg1 = cp1610_readop(cpustate->r[7]);
+ cpustate->r[7]++;
+
+ arg2 = cp1610_readop(cpustate->r[7]);
+ cpustate->r[7]++;
+
+ /*logerror("jumps: pc = 0x%04x, arg1 = 0x%04x, arg2 = 0x%04x\n",cpustate->r[7]-1,arg1,arg2);*/
+ jumptype = arg1 & 0x303;
+ addr = ((arg1 & 0x0fc) << 8) | (arg2 & 0x3ff);
+
+ switch( jumptype )
+ {
+ case 0x000: /* 0 0xx xxx x00 */ cp1610_jsr(cpustate, 4,addr); break;
+ case 0x001: /* 0 0xx xxx x01 */ cp1610_jsre(cpustate, 4,addr); break;
+ case 0x002: /* 0 0xx xxx x10 */ cp1610_jsrd(cpustate, 4,addr); break;
+ case 0x003: /* 0 0xx xxx x11 */ cp1610_illegal(cpustate); break;
+
+ case 0x100: /* 0 1xx xxx x00 */ cp1610_jsr(cpustate, 5,addr); break;
+ case 0x101: /* 0 1xx xxx x01 */ cp1610_jsre(cpustate, 5,addr); break;
+ case 0x102: /* 0 1xx xxx x10 */ cp1610_jsrd(cpustate, 5,addr); break;
+ case 0x103: /* 0 1xx xxx x11 */ cp1610_illegal(cpustate); break;
+
+ case 0x200: /* 1 0xx xxx x00 */ cp1610_jsr(cpustate, 6,addr); break;
+ case 0x201: /* 1 0xx xxx x01 */ cp1610_jsre(cpustate, 6,addr); break;
+ case 0x202: /* 1 0xx xxx x10 */ cp1610_jsrd(cpustate, 6,addr); break;
+ case 0x203: /* 1 0xx xxx x11 */ cp1610_illegal(cpustate); break;
+
+ case 0x300: /* 1 1xx xxx x00 */ cp1610_j(cpustate, addr); break;
+ case 0x301: /* 1 1xx xxx x01 */ cp1610_je(cpustate, addr); break;
+ case 0x302: /* 1 1xx xxx x10 */ cp1610_jd(cpustate, addr); break;
+ case 0x303: /* 1 1xx xxx x11 */ cp1610_illegal(cpustate); break;
+ }
+
+ cpustate->icount -= 12;
+}
+
+/* Execute cycles - returns number of cycles actually run */
+static CPU_EXECUTE( cp1610 )
+{
+ cp1610_state *cpustate = get_safe_token(device);
+ UINT16 opcode;
+
+ do
+ {
+ debugger_instruction_hook(device, cpustate->r[7]);
+
+ cpustate->mask_interrupts = 0;
+
+ opcode = cp1610_readop(cpustate->r[7]);
+ cpustate->r[7]++;
+#if 0
+ logerror("PC:0x%04x, opcode = 0x%03x, ",cpustate->r[7]-1,opcode);
+ logerror("R0:0x%04x, ",cpustate->r[0]);
+ logerror("R1:0x%04x, ",cpustate->r[1]);
+ logerror("R2:0x%04x, ",cpustate->r[2]);
+ logerror("R3:0x%04x, ",cpustate->r[3]);
+ logerror("R4:0x%04x, ",cpustate->r[4]);
+ logerror("R5:0x%04x, ",cpustate->r[5]);
+ logerror("R6:0x%04x\n",cpustate->r[6]);
+#endif
+
+ switch( opcode )
+ {
+ /* opcode bitmask */
+ case 0x000: /* 0 000 000 000 */ cp1610_hlt(cpustate); break; /* TBD */
+ case 0x001: /* 0 000 000 001 */ cp1610_do_sdbd(cpustate); break;
+ case 0x002: /* 0 000 000 010 */ cp1610_eis(cpustate); break; /* TBD */
+ case 0x003: /* 0 000 000 011 */ cp1610_dis(cpustate); break; /* TBD */
+ case 0x004: /* 0 000 000 100 */ cp1610_do_jumps(cpustate); break;
+ case 0x005: /* 0 000 000 101 */ cp1610_tci(cpustate); break; /* TBD */
+ case 0x006: /* 0 000 000 110 */ cp1610_clrc(cpustate); break;
+ case 0x007: /* 0 000 000 111 */ cp1610_setc(cpustate); break;
+
+ case 0x008: /* 0 000 001 000 */ cp1610_incr(cpustate, 0); break;
+ case 0x009: /* 0 000 001 001 */ cp1610_incr(cpustate, 1); break;
+ case 0x00a: /* 0 000 001 010 */ cp1610_incr(cpustate, 2); break;
+ case 0x00b: /* 0 000 001 011 */ cp1610_incr(cpustate, 3); break;
+ case 0x00c: /* 0 000 001 100 */ cp1610_incr(cpustate, 4); break;
+ case 0x00d: /* 0 000 001 101 */ cp1610_incr(cpustate, 5); break;
+ case 0x00e: /* 0 000 001 110 */ cp1610_incr(cpustate, 6); break;
+ case 0x00f: /* 0 000 001 111 */ cp1610_incr(cpustate, 7); break;
+
+ case 0x010: /* 0 000 010 000 */ cp1610_decr(cpustate, 0); break;
+ case 0x011: /* 0 000 010 001 */ cp1610_decr(cpustate, 1); break;
+ case 0x012: /* 0 000 010 010 */ cp1610_decr(cpustate, 2); break;
+ case 0x013: /* 0 000 010 011 */ cp1610_decr(cpustate, 3); break;
+ case 0x014: /* 0 000 010 100 */ cp1610_decr(cpustate, 4); break;
+ case 0x015: /* 0 000 010 101 */ cp1610_decr(cpustate, 5); break;
+ case 0x016: /* 0 000 010 110 */ cp1610_decr(cpustate, 6); break;
+ case 0x017: /* 0 000 010 111 */ cp1610_decr(cpustate, 7); break;
+
+ case 0x018: /* 0 000 011 000 */ cp1610_comr(cpustate, 0); break;
+ case 0x019: /* 0 000 011 001 */ cp1610_comr(cpustate, 1); break;
+ case 0x01a: /* 0 000 011 010 */ cp1610_comr(cpustate, 2); break;
+ case 0x01b: /* 0 000 011 011 */ cp1610_comr(cpustate, 3); break;
+ case 0x01c: /* 0 000 011 100 */ cp1610_comr(cpustate, 4); break;
+ case 0x01d: /* 0 000 011 101 */ cp1610_comr(cpustate, 5); break;
+ case 0x01e: /* 0 000 011 110 */ cp1610_comr(cpustate, 6); break;
+ case 0x01f: /* 0 000 011 111 */ cp1610_comr(cpustate, 7); break;
+
+ case 0x020: /* 0 000 100 000 */ cp1610_negr(cpustate, 0); break;
+ case 0x021: /* 0 000 100 001 */ cp1610_negr(cpustate, 1); break;
+ case 0x022: /* 0 000 100 010 */ cp1610_negr(cpustate, 2); break;
+ case 0x023: /* 0 000 100 011 */ cp1610_negr(cpustate, 3); break;
+ case 0x024: /* 0 000 100 100 */ cp1610_negr(cpustate, 4); break;
+ case 0x025: /* 0 000 100 101 */ cp1610_negr(cpustate, 5); break;
+ case 0x026: /* 0 000 100 110 */ cp1610_negr(cpustate, 6); break;
+ case 0x027: /* 0 000 100 111 */ cp1610_negr(cpustate, 7); break;
+
+ case 0x028: /* 0 000 101 000 */ cp1610_adcr(cpustate, 0); break;
+ case 0x029: /* 0 000 101 001 */ cp1610_adcr(cpustate, 1); break;
+ case 0x02a: /* 0 000 101 010 */ cp1610_adcr(cpustate, 2); break;
+ case 0x02b: /* 0 000 101 011 */ cp1610_adcr(cpustate, 3); break;
+ case 0x02c: /* 0 000 101 100 */ cp1610_adcr(cpustate, 4); break;
+ case 0x02d: /* 0 000 101 101 */ cp1610_adcr(cpustate, 5); break;
+ case 0x02e: /* 0 000 101 110 */ cp1610_adcr(cpustate, 6); break;
+ case 0x02f: /* 0 000 101 111 */ cp1610_adcr(cpustate, 7); break;
+
+ case 0x030: /* 0 000 110 000 */ cp1610_gswd(cpustate, 0); break;
+ case 0x031: /* 0 000 110 001 */ cp1610_gswd(cpustate, 1); break;
+ case 0x032: /* 0 000 110 010 */ cp1610_gswd(cpustate, 2); break;
+ case 0x033: /* 0 000 110 011 */ cp1610_gswd(cpustate, 3); break;
+ case 0x034: /* 0 000 110 100 */ cp1610_nop(cpustate); break;
+ case 0x035: /* 0 000 110 101 */ cp1610_nop(cpustate); break;
+ case 0x036: /* 0 000 110 110 */ cp1610_sin(cpustate); break; /* TBD */
+ case 0x037: /* 0 000 110 111 */ cp1610_sin(cpustate); break; /* TBD */
+
+ case 0x038: /* 0 000 111 000 */ cp1610_rswd(cpustate, 0); break;
+ case 0x039: /* 0 000 111 001 */ cp1610_rswd(cpustate, 1); break;
+ case 0x03a: /* 0 000 111 010 */ cp1610_rswd(cpustate, 2); break;
+ case 0x03b: /* 0 000 111 011 */ cp1610_rswd(cpustate, 3); break;
+ case 0x03c: /* 0 000 111 100 */ cp1610_rswd(cpustate, 4); break;
+ case 0x03d: /* 0 000 111 101 */ cp1610_rswd(cpustate, 5); break;
+ case 0x03e: /* 0 000 111 110 */ cp1610_rswd(cpustate, 6); break;
+ case 0x03f: /* 0 000 111 111 */ cp1610_rswd(cpustate, 7); break;
+
+ case 0x040: /* 0 001 000 000 */ cp1610_swap(cpustate, 0); break;
+ case 0x041: /* 0 001 000 001 */ cp1610_swap(cpustate, 1); break;
+ case 0x042: /* 0 001 000 010 */ cp1610_swap(cpustate, 2); break;
+ case 0x043: /* 0 001 000 011 */ cp1610_swap(cpustate, 3); break;
+ case 0x044: /* 0 001 000 100 */ cp1610_dswap(cpustate, 0); break;
+ case 0x045: /* 0 001 000 101 */ cp1610_dswap(cpustate, 1); break;
+ case 0x046: /* 0 001 000 110 */ cp1610_dswap(cpustate, 2); break;
+ case 0x047: /* 0 001 000 111 */ cp1610_dswap(cpustate, 3); break;
+
+ case 0x048: /* 0 001 001 000 */ cp1610_sll_1(cpustate, 0); break;
+ case 0x049: /* 0 001 001 001 */ cp1610_sll_1(cpustate, 1); break;
+ case 0x04a: /* 0 001 001 010 */ cp1610_sll_1(cpustate, 2); break;
+ case 0x04b: /* 0 001 001 011 */ cp1610_sll_1(cpustate, 3); break;
+ case 0x04c: /* 0 001 001 100 */ cp1610_sll_2(cpustate, 0); break;
+ case 0x04d: /* 0 001 001 101 */ cp1610_sll_2(cpustate, 1); break;
+ case 0x04e: /* 0 001 001 110 */ cp1610_sll_2(cpustate, 2); break;
+ case 0x04f: /* 0 001 001 111 */ cp1610_sll_2(cpustate, 3); break;
+
+ case 0x050: /* 0 001 010 000 */ cp1610_rlc_1(cpustate, 0); break;
+ case 0x051: /* 0 001 010 001 */ cp1610_rlc_1(cpustate, 1); break;
+ case 0x052: /* 0 001 010 010 */ cp1610_rlc_1(cpustate, 2); break;
+ case 0x053: /* 0 001 010 011 */ cp1610_rlc_1(cpustate, 3); break;
+ case 0x054: /* 0 001 010 100 */ cp1610_rlc_2(cpustate, 0); break;
+ case 0x055: /* 0 001 010 101 */ cp1610_rlc_2(cpustate, 1); break;
+ case 0x056: /* 0 001 010 110 */ cp1610_rlc_2(cpustate, 2); break;
+ case 0x057: /* 0 001 010 111 */ cp1610_rlc_2(cpustate, 3); break;
+
+ case 0x058: /* 0 001 011 000 */ cp1610_sllc_1(cpustate, 0); break;
+ case 0x059: /* 0 001 011 001 */ cp1610_sllc_1(cpustate, 1); break;
+ case 0x05a: /* 0 001 011 010 */ cp1610_sllc_1(cpustate, 2); break;
+ case 0x05b: /* 0 001 011 011 */ cp1610_sllc_1(cpustate, 3); break;
+ case 0x05c: /* 0 001 011 100 */ cp1610_sllc_2(cpustate, 0); break;
+ case 0x05d: /* 0 001 011 101 */ cp1610_sllc_2(cpustate, 1); break;
+ case 0x05e: /* 0 001 011 110 */ cp1610_sllc_2(cpustate, 2); break;
+ case 0x05f: /* 0 001 011 111 */ cp1610_sllc_2(cpustate, 3); break;
+
+ case 0x060: /* 0 001 100 000 */ cp1610_slr_1(cpustate, 0); break;
+ case 0x061: /* 0 001 100 001 */ cp1610_slr_1(cpustate, 1); break;
+ case 0x062: /* 0 001 100 010 */ cp1610_slr_1(cpustate, 2); break;
+ case 0x063: /* 0 001 100 011 */ cp1610_slr_1(cpustate, 3); break;
+ case 0x064: /* 0 001 100 100 */ cp1610_slr_2(cpustate, 0); break;
+ case 0x065: /* 0 001 100 101 */ cp1610_slr_2(cpustate, 1); break;
+ case 0x066: /* 0 001 100 110 */ cp1610_slr_2(cpustate, 2); break;
+ case 0x067: /* 0 001 100 111 */ cp1610_slr_2(cpustate, 3); break;
+
+ case 0x068: /* 0 001 101 000 */ cp1610_sar_1(cpustate, 0); break;
+ case 0x069: /* 0 001 101 001 */ cp1610_sar_1(cpustate, 1); break;
+ case 0x06a: /* 0 001 101 010 */ cp1610_sar_1(cpustate, 2); break;
+ case 0x06b: /* 0 001 101 011 */ cp1610_sar_1(cpustate, 3); break;
+ case 0x06c: /* 0 001 101 100 */ cp1610_sar_2(cpustate, 0); break;
+ case 0x06d: /* 0 001 101 101 */ cp1610_sar_2(cpustate, 1); break;
+ case 0x06e: /* 0 001 101 110 */ cp1610_sar_2(cpustate, 2); break;
+ case 0x06f: /* 0 001 101 111 */ cp1610_sar_2(cpustate, 3); break;
+
+ case 0x070: /* 0 001 110 000 */ cp1610_rrc_1(cpustate, 0); break;
+ case 0x071: /* 0 001 110 001 */ cp1610_rrc_1(cpustate, 1); break;
+ case 0x072: /* 0 001 110 010 */ cp1610_rrc_1(cpustate, 2); break;
+ case 0x073: /* 0 001 110 011 */ cp1610_rrc_1(cpustate, 3); break;
+ case 0x074: /* 0 001 110 100 */ cp1610_rrc_2(cpustate, 0); break;
+ case 0x075: /* 0 001 110 101 */ cp1610_rrc_2(cpustate, 1); break;
+ case 0x076: /* 0 001 110 110 */ cp1610_rrc_2(cpustate, 2); break;
+ case 0x077: /* 0 001 110 111 */ cp1610_rrc_2(cpustate, 3); break;
+
+ case 0x078: /* 0 001 111 000 */ cp1610_sarc_1(cpustate, 0); break;
+ case 0x079: /* 0 001 111 001 */ cp1610_sarc_1(cpustate, 1); break;
+ case 0x07a: /* 0 001 111 010 */ cp1610_sarc_1(cpustate, 2); break;
+ case 0x07b: /* 0 001 111 011 */ cp1610_sarc_1(cpustate, 3); break;
+ case 0x07c: /* 0 001 111 100 */ cp1610_sarc_2(cpustate, 0); break;
+ case 0x07d: /* 0 001 111 101 */ cp1610_sarc_2(cpustate, 1); break;
+ case 0x07e: /* 0 001 111 110 */ cp1610_sarc_2(cpustate, 2); break;
+ case 0x07f: /* 0 001 111 111 */ cp1610_sarc_2(cpustate, 3); break;
+
+ case 0x080: /* 0 010 000 000 */ cp1610_tstr(cpustate, 0); break;
+ case 0x081: /* 0 010 000 001 */ cp1610_movr(cpustate, 0,1); break;
+ case 0x082: /* 0 010 000 010 */ cp1610_movr(cpustate, 0,2); break;
+ case 0x083: /* 0 010 000 011 */ cp1610_movr(cpustate, 0,3); break;
+ case 0x084: /* 0 010 000 100 */ cp1610_movr(cpustate, 0,4); break;
+ case 0x085: /* 0 010 000 101 */ cp1610_movr(cpustate, 0,5); break;
+ case 0x086: /* 0 010 000 110 */ cp1610_movr(cpustate, 0,6); break;
+ case 0x087: /* 0 010 000 111 */ cp1610_movr(cpustate, 0,7); break; /* jr */
+
+ case 0x088: /* 0 010 001 000 */ cp1610_movr(cpustate, 1,0); break;
+ case 0x089: /* 0 010 001 001 */ cp1610_tstr(cpustate, 1); break;
+ case 0x08a: /* 0 010 001 010 */ cp1610_movr(cpustate, 1,2); break;
+ case 0x08b: /* 0 010 001 011 */ cp1610_movr(cpustate, 1,3); break;
+ case 0x08c: /* 0 010 001 100 */ cp1610_movr(cpustate, 1,4); break;
+ case 0x08d: /* 0 010 001 101 */ cp1610_movr(cpustate, 1,5); break;
+ case 0x08e: /* 0 010 001 110 */ cp1610_movr(cpustate, 1,6); break;
+ case 0x08f: /* 0 010 001 111 */ cp1610_movr(cpustate, 1,7); break; /* jr */
+
+ case 0x090: /* 0 010 010 000 */ cp1610_movr(cpustate, 2,0); break;
+ case 0x091: /* 0 010 010 001 */ cp1610_movr(cpustate, 2,1); break;
+ case 0x092: /* 0 010 010 010 */ cp1610_tstr(cpustate, 2); break;
+ case 0x093: /* 0 010 010 011 */ cp1610_movr(cpustate, 2,3); break;
+ case 0x094: /* 0 010 010 100 */ cp1610_movr(cpustate, 2,4); break;
+ case 0x095: /* 0 010 010 101 */ cp1610_movr(cpustate, 2,5); break;
+ case 0x096: /* 0 010 010 110 */ cp1610_movr(cpustate, 2,6); break;
+ case 0x097: /* 0 010 010 111 */ cp1610_movr(cpustate, 2,7); break; /* jr */
+
+ case 0x098: /* 0 010 011 000 */ cp1610_movr(cpustate, 3,0); break;
+ case 0x099: /* 0 010 011 001 */ cp1610_movr(cpustate, 3,1); break;
+ case 0x09a: /* 0 010 011 010 */ cp1610_movr(cpustate, 3,2); break;
+ case 0x09b: /* 0 010 011 011 */ cp1610_tstr(cpustate, 3); break;
+ case 0x09c: /* 0 010 011 100 */ cp1610_movr(cpustate, 3,4); break;
+ case 0x09d: /* 0 010 011 101 */ cp1610_movr(cpustate, 3,5); break;
+ case 0x09e: /* 0 010 011 110 */ cp1610_movr(cpustate, 3,6); break;
+ case 0x09f: /* 0 010 011 111 */ cp1610_movr(cpustate, 3,7); break; /* jr */
+
+ case 0x0a0: /* 0 010 100 000 */ cp1610_movr(cpustate, 4,0); break;
+ case 0x0a1: /* 0 010 100 001 */ cp1610_movr(cpustate, 4,1); break;
+ case 0x0a2: /* 0 010 100 010 */ cp1610_movr(cpustate, 4,2); break;
+ case 0x0a3: /* 0 010 100 011 */ cp1610_movr(cpustate, 4,3); break;
+ case 0x0a4: /* 0 010 100 100 */ cp1610_tstr(cpustate, 4); break;
+ case 0x0a5: /* 0 010 100 101 */ cp1610_movr(cpustate, 4,5); break;
+ case 0x0a6: /* 0 010 100 110 */ cp1610_movr(cpustate, 4,6); break;
+ case 0x0a7: /* 0 010 100 111 */ cp1610_movr(cpustate, 4,7); break; /* jr */
+
+ case 0x0a8: /* 0 010 101 000 */ cp1610_movr(cpustate, 5,0); break;
+ case 0x0a9: /* 0 010 101 001 */ cp1610_movr(cpustate, 5,1); break;
+ case 0x0aa: /* 0 010 101 010 */ cp1610_movr(cpustate, 5,2); break;
+ case 0x0ab: /* 0 010 101 011 */ cp1610_movr(cpustate, 5,3); break;
+ case 0x0ac: /* 0 010 101 100 */ cp1610_movr(cpustate, 5,4); break;
+ case 0x0ad: /* 0 010 101 101 */ cp1610_tstr(cpustate, 5); break;
+ case 0x0ae: /* 0 010 101 110 */ cp1610_movr(cpustate, 5,6); break;
+ case 0x0af: /* 0 010 101 111 */ cp1610_movr(cpustate, 5,7); break; /* jr */
+
+ case 0x0b0: /* 0 010 110 000 */ cp1610_movr(cpustate, 6,0); break;
+ case 0x0b1: /* 0 010 110 001 */ cp1610_movr(cpustate, 6,1); break;
+ case 0x0b2: /* 0 010 110 010 */ cp1610_movr(cpustate, 6,2); break;
+ case 0x0b3: /* 0 010 110 011 */ cp1610_movr(cpustate, 6,3); break;
+ case 0x0b4: /* 0 010 110 100 */ cp1610_movr(cpustate, 6,4); break;
+ case 0x0b5: /* 0 010 110 101 */ cp1610_movr(cpustate, 6,5); break;
+ case 0x0b6: /* 0 010 110 110 */ cp1610_tstr(cpustate, 6); break;
+ case 0x0b7: /* 0 010 110 111 */ cp1610_movr(cpustate, 6,7); break; /* jr */
+
+ case 0x0b8: /* 0 010 111 000 */ cp1610_movr(cpustate, 7,0); break;
+ case 0x0b9: /* 0 010 111 001 */ cp1610_movr(cpustate, 7,1); break;
+ case 0x0ba: /* 0 010 111 010 */ cp1610_movr(cpustate, 7,2); break;
+ case 0x0bb: /* 0 010 111 011 */ cp1610_movr(cpustate, 7,3); break;
+ case 0x0bc: /* 0 010 111 100 */ cp1610_movr(cpustate, 7,4); break;
+ case 0x0bd: /* 0 010 111 101 */ cp1610_movr(cpustate, 7,5); break;
+ case 0x0be: /* 0 010 111 110 */ cp1610_movr(cpustate, 7,6); break;
+ case 0x0bf: /* 0 010 111 111 */ cp1610_tstr(cpustate, 7); break;
+
+ case 0x0c0: /* 0 011 000 000 */ cp1610_addr(cpustate, 0,0); break;
+ case 0x0c1: /* 0 011 000 001 */ cp1610_addr(cpustate, 0,1); break;
+ case 0x0c2: /* 0 011 000 010 */ cp1610_addr(cpustate, 0,2); break;
+ case 0x0c3: /* 0 011 000 011 */ cp1610_addr(cpustate, 0,3); break;
+ case 0x0c4: /* 0 011 000 100 */ cp1610_addr(cpustate, 0,4); break;
+ case 0x0c5: /* 0 011 000 101 */ cp1610_addr(cpustate, 0,5); break;
+ case 0x0c6: /* 0 011 000 110 */ cp1610_addr(cpustate, 0,6); break;
+ case 0x0c7: /* 0 011 000 111 */ cp1610_addr(cpustate, 0,7); break;
+
+ case 0x0c8: /* 0 011 001 000 */ cp1610_addr(cpustate, 1,0); break;
+ case 0x0c9: /* 0 011 001 001 */ cp1610_addr(cpustate, 1,1); break;
+ case 0x0ca: /* 0 011 001 010 */ cp1610_addr(cpustate, 1,2); break;
+ case 0x0cb: /* 0 011 001 011 */ cp1610_addr(cpustate, 1,3); break;
+ case 0x0cc: /* 0 011 001 100 */ cp1610_addr(cpustate, 1,4); break;
+ case 0x0cd: /* 0 011 001 101 */ cp1610_addr(cpustate, 1,5); break;
+ case 0x0ce: /* 0 011 001 110 */ cp1610_addr(cpustate, 1,6); break;
+ case 0x0cf: /* 0 011 001 111 */ cp1610_addr(cpustate, 1,7); break;
+
+ case 0x0d0: /* 0 011 010 000 */ cp1610_addr(cpustate, 2,0); break;
+ case 0x0d1: /* 0 011 010 001 */ cp1610_addr(cpustate, 2,1); break;
+ case 0x0d2: /* 0 011 010 010 */ cp1610_addr(cpustate, 2,2); break;
+ case 0x0d3: /* 0 011 010 011 */ cp1610_addr(cpustate, 2,3); break;
+ case 0x0d4: /* 0 011 010 100 */ cp1610_addr(cpustate, 2,4); break;
+ case 0x0d5: /* 0 011 010 101 */ cp1610_addr(cpustate, 2,5); break;
+ case 0x0d6: /* 0 011 010 110 */ cp1610_addr(cpustate, 2,6); break;
+ case 0x0d7: /* 0 011 010 111 */ cp1610_addr(cpustate, 2,7); break;
+
+ case 0x0d8: /* 0 011 011 000 */ cp1610_addr(cpustate, 3,0); break;
+ case 0x0d9: /* 0 011 011 001 */ cp1610_addr(cpustate, 3,1); break;
+ case 0x0da: /* 0 011 011 010 */ cp1610_addr(cpustate, 3,2); break;
+ case 0x0db: /* 0 011 011 011 */ cp1610_addr(cpustate, 3,3); break;
+ case 0x0dc: /* 0 011 011 100 */ cp1610_addr(cpustate, 3,4); break;
+ case 0x0dd: /* 0 011 011 101 */ cp1610_addr(cpustate, 3,5); break;
+ case 0x0de: /* 0 011 011 110 */ cp1610_addr(cpustate, 3,6); break;
+ case 0x0df: /* 0 011 011 111 */ cp1610_addr(cpustate, 3,7); break;
+
+ case 0x0e0: /* 0 011 100 000 */ cp1610_addr(cpustate, 4,0); break;
+ case 0x0e1: /* 0 011 100 001 */ cp1610_addr(cpustate, 4,1); break;
+ case 0x0e2: /* 0 011 100 010 */ cp1610_addr(cpustate, 4,2); break;
+ case 0x0e3: /* 0 011 100 011 */ cp1610_addr(cpustate, 4,3); break;
+ case 0x0e4: /* 0 011 100 100 */ cp1610_addr(cpustate, 4,4); break;
+ case 0x0e5: /* 0 011 100 101 */ cp1610_addr(cpustate, 4,5); break;
+ case 0x0e6: /* 0 011 100 110 */ cp1610_addr(cpustate, 4,6); break;
+ case 0x0e7: /* 0 011 100 111 */ cp1610_addr(cpustate, 4,7); break;
+
+ case 0x0e8: /* 0 011 101 000 */ cp1610_addr(cpustate, 5,0); break;
+ case 0x0e9: /* 0 011 101 001 */ cp1610_addr(cpustate, 5,1); break;
+ case 0x0ea: /* 0 011 101 010 */ cp1610_addr(cpustate, 5,2); break;
+ case 0x0eb: /* 0 011 101 011 */ cp1610_addr(cpustate, 5,3); break;
+ case 0x0ec: /* 0 011 101 100 */ cp1610_addr(cpustate, 5,4); break;
+ case 0x0ed: /* 0 011 101 101 */ cp1610_addr(cpustate, 5,5); break;
+ case 0x0ee: /* 0 011 101 110 */ cp1610_addr(cpustate, 5,6); break;
+ case 0x0ef: /* 0 011 101 111 */ cp1610_addr(cpustate, 5,7); break;
+
+ case 0x0f0: /* 0 011 110 000 */ cp1610_addr(cpustate, 6,0); break;
+ case 0x0f1: /* 0 011 110 001 */ cp1610_addr(cpustate, 6,1); break;
+ case 0x0f2: /* 0 011 110 010 */ cp1610_addr(cpustate, 6,2); break;
+ case 0x0f3: /* 0 011 110 011 */ cp1610_addr(cpustate, 6,3); break;
+ case 0x0f4: /* 0 011 110 100 */ cp1610_addr(cpustate, 6,4); break;
+ case 0x0f5: /* 0 011 110 101 */ cp1610_addr(cpustate, 6,5); break;
+ case 0x0f6: /* 0 011 110 110 */ cp1610_addr(cpustate, 6,6); break;
+ case 0x0f7: /* 0 011 110 111 */ cp1610_addr(cpustate, 6,7); break;
+
+ case 0x0f8: /* 0 011 111 000 */ cp1610_addr(cpustate, 7,0); break;
+ case 0x0f9: /* 0 011 111 001 */ cp1610_addr(cpustate, 7,1); break;
+ case 0x0fa: /* 0 011 111 010 */ cp1610_addr(cpustate, 7,2); break;
+ case 0x0fb: /* 0 011 111 011 */ cp1610_addr(cpustate, 7,3); break;
+ case 0x0fc: /* 0 011 111 100 */ cp1610_addr(cpustate, 7,4); break;
+ case 0x0fd: /* 0 011 111 101 */ cp1610_addr(cpustate, 7,5); break;
+ case 0x0fe: /* 0 011 111 110 */ cp1610_addr(cpustate, 7,6); break;
+ case 0x0ff: /* 0 011 111 111 */ cp1610_addr(cpustate, 7,7); break;
+
+ case 0x100: /* 0 100 000 000 */ cp1610_subr(cpustate, 0,0); break;
+ case 0x101: /* 0 100 000 001 */ cp1610_subr(cpustate, 0,1); break;
+ case 0x102: /* 0 100 000 010 */ cp1610_subr(cpustate, 0,2); break;
+ case 0x103: /* 0 100 000 011 */ cp1610_subr(cpustate, 0,3); break;
+ case 0x104: /* 0 100 000 100 */ cp1610_subr(cpustate, 0,4); break;
+ case 0x105: /* 0 100 000 101 */ cp1610_subr(cpustate, 0,5); break;
+ case 0x106: /* 0 100 000 110 */ cp1610_subr(cpustate, 0,6); break;
+ case 0x107: /* 0 100 000 111 */ cp1610_subr(cpustate, 0,7); break;
+
+ case 0x108: /* 0 100 001 000 */ cp1610_subr(cpustate, 1,0); break;
+ case 0x109: /* 0 100 001 001 */ cp1610_subr(cpustate, 1,1); break;
+ case 0x10a: /* 0 100 001 010 */ cp1610_subr(cpustate, 1,2); break;
+ case 0x10b: /* 0 100 001 011 */ cp1610_subr(cpustate, 1,3); break;
+ case 0x10c: /* 0 100 001 100 */ cp1610_subr(cpustate, 1,4); break;
+ case 0x10d: /* 0 100 001 101 */ cp1610_subr(cpustate, 1,5); break;
+ case 0x10e: /* 0 100 001 110 */ cp1610_subr(cpustate, 1,6); break;
+ case 0x10f: /* 0 100 001 111 */ cp1610_subr(cpustate, 1,7); break;
+
+ case 0x110: /* 0 100 010 000 */ cp1610_subr(cpustate, 2,0); break;
+ case 0x111: /* 0 100 010 001 */ cp1610_subr(cpustate, 2,1); break;
+ case 0x112: /* 0 100 010 010 */ cp1610_subr(cpustate, 2,2); break;
+ case 0x113: /* 0 100 010 011 */ cp1610_subr(cpustate, 2,3); break;
+ case 0x114: /* 0 100 010 100 */ cp1610_subr(cpustate, 2,4); break;
+ case 0x115: /* 0 100 010 101 */ cp1610_subr(cpustate, 2,5); break;
+ case 0x116: /* 0 100 010 110 */ cp1610_subr(cpustate, 2,6); break;
+ case 0x117: /* 0 100 010 111 */ cp1610_subr(cpustate, 2,7); break;
+
+ case 0x118: /* 0 100 011 000 */ cp1610_subr(cpustate, 3,0); break;
+ case 0x119: /* 0 100 011 001 */ cp1610_subr(cpustate, 3,1); break;
+ case 0x11a: /* 0 100 011 010 */ cp1610_subr(cpustate, 3,2); break;
+ case 0x11b: /* 0 100 011 011 */ cp1610_subr(cpustate, 3,3); break;
+ case 0x11c: /* 0 100 011 100 */ cp1610_subr(cpustate, 3,4); break;
+ case 0x11d: /* 0 100 011 101 */ cp1610_subr(cpustate, 3,5); break;
+ case 0x11e: /* 0 100 011 110 */ cp1610_subr(cpustate, 3,6); break;
+ case 0x11f: /* 0 100 011 111 */ cp1610_subr(cpustate, 3,7); break;
+
+ case 0x120: /* 0 100 100 000 */ cp1610_subr(cpustate, 4,0); break;
+ case 0x121: /* 0 100 100 001 */ cp1610_subr(cpustate, 4,1); break;
+ case 0x122: /* 0 100 100 010 */ cp1610_subr(cpustate, 4,2); break;
+ case 0x123: /* 0 100 100 011 */ cp1610_subr(cpustate, 4,3); break;
+ case 0x124: /* 0 100 100 100 */ cp1610_subr(cpustate, 4,4); break;
+ case 0x125: /* 0 100 100 101 */ cp1610_subr(cpustate, 4,5); break;
+ case 0x126: /* 0 100 100 110 */ cp1610_subr(cpustate, 4,6); break;
+ case 0x127: /* 0 100 100 111 */ cp1610_subr(cpustate, 4,7); break;
+
+ case 0x128: /* 0 100 101 000 */ cp1610_subr(cpustate, 5,0); break;
+ case 0x129: /* 0 100 101 001 */ cp1610_subr(cpustate, 5,1); break;
+ case 0x12a: /* 0 100 101 010 */ cp1610_subr(cpustate, 5,2); break;
+ case 0x12b: /* 0 100 101 011 */ cp1610_subr(cpustate, 5,3); break;
+ case 0x12c: /* 0 100 101 100 */ cp1610_subr(cpustate, 5,4); break;
+ case 0x12d: /* 0 100 101 101 */ cp1610_subr(cpustate, 5,5); break;
+ case 0x12e: /* 0 100 101 110 */ cp1610_subr(cpustate, 5,6); break;
+ case 0x12f: /* 0 100 101 111 */ cp1610_subr(cpustate, 5,7); break;
+
+ case 0x130: /* 0 100 110 000 */ cp1610_subr(cpustate, 6,0); break;
+ case 0x131: /* 0 100 110 001 */ cp1610_subr(cpustate, 6,1); break;
+ case 0x132: /* 0 100 110 010 */ cp1610_subr(cpustate, 6,2); break;
+ case 0x133: /* 0 100 110 011 */ cp1610_subr(cpustate, 6,3); break;
+ case 0x134: /* 0 100 110 100 */ cp1610_subr(cpustate, 6,4); break;
+ case 0x135: /* 0 100 110 101 */ cp1610_subr(cpustate, 6,5); break;
+ case 0x136: /* 0 100 110 110 */ cp1610_subr(cpustate, 6,6); break;
+ case 0x137: /* 0 100 110 111 */ cp1610_subr(cpustate, 6,7); break;
+
+ case 0x138: /* 0 100 111 000 */ cp1610_subr(cpustate, 7,0); break;
+ case 0x139: /* 0 100 111 001 */ cp1610_subr(cpustate, 7,1); break;
+ case 0x13a: /* 0 100 111 010 */ cp1610_subr(cpustate, 7,2); break;
+ case 0x13b: /* 0 100 111 011 */ cp1610_subr(cpustate, 7,3); break;
+ case 0x13c: /* 0 100 111 100 */ cp1610_subr(cpustate, 7,4); break;
+ case 0x13d: /* 0 100 111 101 */ cp1610_subr(cpustate, 7,5); break;
+ case 0x13e: /* 0 100 111 110 */ cp1610_subr(cpustate, 7,6); break;
+ case 0x13f: /* 0 100 111 111 */ cp1610_subr(cpustate, 7,7); break;
+
+ case 0x140: /* 0 101 000 000 */ cp1610_cmpr(cpustate, 0,0); break;
+ case 0x141: /* 0 101 000 001 */ cp1610_cmpr(cpustate, 0,1); break;
+ case 0x142: /* 0 101 000 010 */ cp1610_cmpr(cpustate, 0,2); break;
+ case 0x143: /* 0 101 000 011 */ cp1610_cmpr(cpustate, 0,3); break;
+ case 0x144: /* 0 101 000 100 */ cp1610_cmpr(cpustate, 0,4); break;
+ case 0x145: /* 0 101 000 101 */ cp1610_cmpr(cpustate, 0,5); break;
+ case 0x146: /* 0 101 000 110 */ cp1610_cmpr(cpustate, 0,6); break;
+ case 0x147: /* 0 101 000 111 */ cp1610_cmpr(cpustate, 0,7); break;
+
+ case 0x148: /* 0 101 001 000 */ cp1610_cmpr(cpustate, 1,0); break;
+ case 0x149: /* 0 101 001 001 */ cp1610_cmpr(cpustate, 1,1); break;
+ case 0x14a: /* 0 101 001 010 */ cp1610_cmpr(cpustate, 1,2); break;
+ case 0x14b: /* 0 101 001 011 */ cp1610_cmpr(cpustate, 1,3); break;
+ case 0x14c: /* 0 101 001 100 */ cp1610_cmpr(cpustate, 1,4); break;
+ case 0x14d: /* 0 101 001 101 */ cp1610_cmpr(cpustate, 1,5); break;
+ case 0x14e: /* 0 101 001 110 */ cp1610_cmpr(cpustate, 1,6); break;
+ case 0x14f: /* 0 101 001 111 */ cp1610_cmpr(cpustate, 1,7); break;
+
+ case 0x150: /* 0 101 010 000 */ cp1610_cmpr(cpustate, 2,0); break;
+ case 0x151: /* 0 101 010 001 */ cp1610_cmpr(cpustate, 2,1); break;
+ case 0x152: /* 0 101 010 010 */ cp1610_cmpr(cpustate, 2,2); break;
+ case 0x153: /* 0 101 010 011 */ cp1610_cmpr(cpustate, 2,3); break;
+ case 0x154: /* 0 101 010 100 */ cp1610_cmpr(cpustate, 2,4); break;
+ case 0x155: /* 0 101 010 101 */ cp1610_cmpr(cpustate, 2,5); break;
+ case 0x156: /* 0 101 010 110 */ cp1610_cmpr(cpustate, 2,6); break;
+ case 0x157: /* 0 101 010 111 */ cp1610_cmpr(cpustate, 2,7); break;
+
+ case 0x158: /* 0 101 011 000 */ cp1610_cmpr(cpustate, 3,0); break;
+ case 0x159: /* 0 101 011 001 */ cp1610_cmpr(cpustate, 3,1); break;
+ case 0x15a: /* 0 101 011 010 */ cp1610_cmpr(cpustate, 3,2); break;
+ case 0x15b: /* 0 101 011 011 */ cp1610_cmpr(cpustate, 3,3); break;
+ case 0x15c: /* 0 101 011 100 */ cp1610_cmpr(cpustate, 3,4); break;
+ case 0x15d: /* 0 101 011 101 */ cp1610_cmpr(cpustate, 3,5); break;
+ case 0x15e: /* 0 101 011 110 */ cp1610_cmpr(cpustate, 3,6); break;
+ case 0x15f: /* 0 101 011 111 */ cp1610_cmpr(cpustate, 3,7); break;
+
+ case 0x160: /* 0 101 100 000 */ cp1610_cmpr(cpustate, 4,0); break;
+ case 0x161: /* 0 101 100 001 */ cp1610_cmpr(cpustate, 4,1); break;
+ case 0x162: /* 0 101 100 010 */ cp1610_cmpr(cpustate, 4,2); break;
+ case 0x163: /* 0 101 100 011 */ cp1610_cmpr(cpustate, 4,3); break;
+ case 0x164: /* 0 101 100 100 */ cp1610_cmpr(cpustate, 4,4); break;
+ case 0x165: /* 0 101 100 101 */ cp1610_cmpr(cpustate, 4,5); break;
+ case 0x166: /* 0 101 100 110 */ cp1610_cmpr(cpustate, 4,6); break;
+ case 0x167: /* 0 101 100 111 */ cp1610_cmpr(cpustate, 4,7); break;
+
+ case 0x168: /* 0 101 101 000 */ cp1610_cmpr(cpustate, 5,0); break;
+ case 0x169: /* 0 101 101 001 */ cp1610_cmpr(cpustate, 5,1); break;
+ case 0x16a: /* 0 101 101 010 */ cp1610_cmpr(cpustate, 5,2); break;
+ case 0x16b: /* 0 101 101 011 */ cp1610_cmpr(cpustate, 5,3); break;
+ case 0x16c: /* 0 101 101 100 */ cp1610_cmpr(cpustate, 5,4); break;
+ case 0x16d: /* 0 101 101 101 */ cp1610_cmpr(cpustate, 5,5); break;
+ case 0x16e: /* 0 101 101 110 */ cp1610_cmpr(cpustate, 5,6); break;
+ case 0x16f: /* 0 101 101 111 */ cp1610_cmpr(cpustate, 5,7); break;
+
+ case 0x170: /* 0 101 110 000 */ cp1610_cmpr(cpustate, 6,0); break;
+ case 0x171: /* 0 101 110 001 */ cp1610_cmpr(cpustate, 6,1); break;
+ case 0x172: /* 0 101 110 010 */ cp1610_cmpr(cpustate, 6,2); break;
+ case 0x173: /* 0 101 110 011 */ cp1610_cmpr(cpustate, 6,3); break;
+ case 0x174: /* 0 101 110 100 */ cp1610_cmpr(cpustate, 6,4); break;
+ case 0x175: /* 0 101 110 101 */ cp1610_cmpr(cpustate, 6,5); break;
+ case 0x176: /* 0 101 110 110 */ cp1610_cmpr(cpustate, 6,6); break;
+ case 0x177: /* 0 101 110 111 */ cp1610_cmpr(cpustate, 6,7); break;
+
+ case 0x178: /* 0 101 111 000 */ cp1610_cmpr(cpustate, 7,0); break;
+ case 0x179: /* 0 101 111 001 */ cp1610_cmpr(cpustate, 7,1); break;
+ case 0x17a: /* 0 101 111 010 */ cp1610_cmpr(cpustate, 7,2); break;
+ case 0x17b: /* 0 101 111 011 */ cp1610_cmpr(cpustate, 7,3); break;
+ case 0x17c: /* 0 101 111 100 */ cp1610_cmpr(cpustate, 7,4); break;
+ case 0x17d: /* 0 101 111 101 */ cp1610_cmpr(cpustate, 7,5); break;
+ case 0x17e: /* 0 101 111 110 */ cp1610_cmpr(cpustate, 7,6); break;
+ case 0x17f: /* 0 101 111 111 */ cp1610_cmpr(cpustate, 7,7); break;
+
+ case 0x180: /* 0 110 000 000 */ cp1610_andr(cpustate, 0,0); break;
+ case 0x181: /* 0 110 000 001 */ cp1610_andr(cpustate, 0,1); break;
+ case 0x182: /* 0 110 000 010 */ cp1610_andr(cpustate, 0,2); break;
+ case 0x183: /* 0 110 000 011 */ cp1610_andr(cpustate, 0,3); break;
+ case 0x184: /* 0 110 000 100 */ cp1610_andr(cpustate, 0,4); break;
+ case 0x185: /* 0 110 000 101 */ cp1610_andr(cpustate, 0,5); break;
+ case 0x186: /* 0 110 000 110 */ cp1610_andr(cpustate, 0,6); break;
+ case 0x187: /* 0 110 000 111 */ cp1610_andr(cpustate, 0,7); break;
+
+ case 0x188: /* 0 110 001 000 */ cp1610_andr(cpustate, 1,0); break;
+ case 0x189: /* 0 110 001 001 */ cp1610_andr(cpustate, 1,1); break;
+ case 0x18a: /* 0 110 001 010 */ cp1610_andr(cpustate, 1,2); break;
+ case 0x18b: /* 0 110 001 011 */ cp1610_andr(cpustate, 1,3); break;
+ case 0x18c: /* 0 110 001 100 */ cp1610_andr(cpustate, 1,4); break;
+ case 0x18d: /* 0 110 001 101 */ cp1610_andr(cpustate, 1,5); break;
+ case 0x18e: /* 0 110 001 110 */ cp1610_andr(cpustate, 1,6); break;
+ case 0x18f: /* 0 110 001 111 */ cp1610_andr(cpustate, 1,7); break;
+
+ case 0x190: /* 0 110 010 000 */ cp1610_andr(cpustate, 2,0); break;
+ case 0x191: /* 0 110 010 001 */ cp1610_andr(cpustate, 2,1); break;
+ case 0x192: /* 0 110 010 010 */ cp1610_andr(cpustate, 2,2); break;
+ case 0x193: /* 0 110 010 011 */ cp1610_andr(cpustate, 2,3); break;
+ case 0x194: /* 0 110 010 100 */ cp1610_andr(cpustate, 2,4); break;
+ case 0x195: /* 0 110 010 101 */ cp1610_andr(cpustate, 2,5); break;
+ case 0x196: /* 0 110 010 110 */ cp1610_andr(cpustate, 2,6); break;
+ case 0x197: /* 0 110 010 111 */ cp1610_andr(cpustate, 2,7); break;
+
+ case 0x198: /* 0 110 011 000 */ cp1610_andr(cpustate, 3,0); break;
+ case 0x199: /* 0 110 011 001 */ cp1610_andr(cpustate, 3,1); break;
+ case 0x19a: /* 0 110 011 010 */ cp1610_andr(cpustate, 3,2); break;
+ case 0x19b: /* 0 110 011 011 */ cp1610_andr(cpustate, 3,3); break;
+ case 0x19c: /* 0 110 011 100 */ cp1610_andr(cpustate, 3,4); break;
+ case 0x19d: /* 0 110 011 101 */ cp1610_andr(cpustate, 3,5); break;
+ case 0x19e: /* 0 110 011 110 */ cp1610_andr(cpustate, 3,6); break;
+ case 0x19f: /* 0 110 011 111 */ cp1610_andr(cpustate, 3,7); break;
+
+ case 0x1a0: /* 0 110 100 000 */ cp1610_andr(cpustate, 4,0); break;
+ case 0x1a1: /* 0 110 100 001 */ cp1610_andr(cpustate, 4,1); break;
+ case 0x1a2: /* 0 110 100 010 */ cp1610_andr(cpustate, 4,2); break;
+ case 0x1a3: /* 0 110 100 011 */ cp1610_andr(cpustate, 4,3); break;
+ case 0x1a4: /* 0 110 100 100 */ cp1610_andr(cpustate, 4,4); break;
+ case 0x1a5: /* 0 110 100 101 */ cp1610_andr(cpustate, 4,5); break;
+ case 0x1a6: /* 0 110 100 110 */ cp1610_andr(cpustate, 4,6); break;
+ case 0x1a7: /* 0 110 100 111 */ cp1610_andr(cpustate, 4,7); break;
+
+ case 0x1a8: /* 0 110 101 000 */ cp1610_andr(cpustate, 5,0); break;
+ case 0x1a9: /* 0 110 101 001 */ cp1610_andr(cpustate, 5,1); break;
+ case 0x1aa: /* 0 110 101 010 */ cp1610_andr(cpustate, 5,2); break;
+ case 0x1ab: /* 0 110 101 011 */ cp1610_andr(cpustate, 5,3); break;
+ case 0x1ac: /* 0 110 101 100 */ cp1610_andr(cpustate, 5,4); break;
+ case 0x1ad: /* 0 110 101 101 */ cp1610_andr(cpustate, 5,5); break;
+ case 0x1ae: /* 0 110 101 110 */ cp1610_andr(cpustate, 5,6); break;
+ case 0x1af: /* 0 110 101 111 */ cp1610_andr(cpustate, 5,7); break;
+
+ case 0x1b0: /* 0 110 110 000 */ cp1610_andr(cpustate, 6,0); break;
+ case 0x1b1: /* 0 110 110 001 */ cp1610_andr(cpustate, 6,1); break;
+ case 0x1b2: /* 0 110 110 010 */ cp1610_andr(cpustate, 6,2); break;
+ case 0x1b3: /* 0 110 110 011 */ cp1610_andr(cpustate, 6,3); break;
+ case 0x1b4: /* 0 110 110 100 */ cp1610_andr(cpustate, 6,4); break;
+ case 0x1b5: /* 0 110 110 101 */ cp1610_andr(cpustate, 6,5); break;
+ case 0x1b6: /* 0 110 110 110 */ cp1610_andr(cpustate, 6,6); break;
+ case 0x1b7: /* 0 110 110 111 */ cp1610_andr(cpustate, 6,7); break;
+
+ case 0x1b8: /* 0 110 111 000 */ cp1610_andr(cpustate, 7,0); break;
+ case 0x1b9: /* 0 110 111 001 */ cp1610_andr(cpustate, 7,1); break;
+ case 0x1ba: /* 0 110 111 010 */ cp1610_andr(cpustate, 7,2); break;
+ case 0x1bb: /* 0 110 111 011 */ cp1610_andr(cpustate, 7,3); break;
+ case 0x1bc: /* 0 110 111 100 */ cp1610_andr(cpustate, 7,4); break;
+ case 0x1bd: /* 0 110 111 101 */ cp1610_andr(cpustate, 7,5); break;
+ case 0x1be: /* 0 110 111 110 */ cp1610_andr(cpustate, 7,6); break;
+ case 0x1bf: /* 0 110 111 111 */ cp1610_andr(cpustate, 7,7); break;
+
+ case 0x1c0: /* 0 111 000 000 */ cp1610_clrr(cpustate, 0); break;
+ case 0x1c1: /* 0 111 000 001 */ cp1610_xorr(cpustate, 0,1); break;
+ case 0x1c2: /* 0 111 000 010 */ cp1610_xorr(cpustate, 0,2); break;
+ case 0x1c3: /* 0 111 000 011 */ cp1610_xorr(cpustate, 0,3); break;
+ case 0x1c4: /* 0 111 000 100 */ cp1610_xorr(cpustate, 0,4); break;
+ case 0x1c5: /* 0 111 000 101 */ cp1610_xorr(cpustate, 0,5); break;
+ case 0x1c6: /* 0 111 000 110 */ cp1610_xorr(cpustate, 0,6); break;
+ case 0x1c7: /* 0 111 000 111 */ cp1610_xorr(cpustate, 0,7); break;
+
+ case 0x1c8: /* 0 111 001 000 */ cp1610_xorr(cpustate, 1,0); break;
+ case 0x1c9: /* 0 111 001 001 */ cp1610_clrr(cpustate, 1); break;
+ case 0x1ca: /* 0 111 001 010 */ cp1610_xorr(cpustate, 1,2); break;
+ case 0x1cb: /* 0 111 001 011 */ cp1610_xorr(cpustate, 1,3); break;
+ case 0x1cc: /* 0 111 001 100 */ cp1610_xorr(cpustate, 1,4); break;
+ case 0x1cd: /* 0 111 001 101 */ cp1610_xorr(cpustate, 1,5); break;
+ case 0x1ce: /* 0 111 001 110 */ cp1610_xorr(cpustate, 1,6); break;
+ case 0x1cf: /* 0 111 001 111 */ cp1610_xorr(cpustate, 1,7); break;
+
+ case 0x1d0: /* 0 111 010 000 */ cp1610_xorr(cpustate, 2,0); break;
+ case 0x1d1: /* 0 111 010 001 */ cp1610_xorr(cpustate, 2,1); break;
+ case 0x1d2: /* 0 111 010 010 */ cp1610_clrr(cpustate, 2); break;
+ case 0x1d3: /* 0 111 010 011 */ cp1610_xorr(cpustate, 2,3); break;
+ case 0x1d4: /* 0 111 010 100 */ cp1610_xorr(cpustate, 2,4); break;
+ case 0x1d5: /* 0 111 010 101 */ cp1610_xorr(cpustate, 2,5); break;
+ case 0x1d6: /* 0 111 010 110 */ cp1610_xorr(cpustate, 2,6); break;
+ case 0x1d7: /* 0 111 010 111 */ cp1610_xorr(cpustate, 2,7); break;
+
+ case 0x1d8: /* 0 111 011 000 */ cp1610_xorr(cpustate, 3,0); break;
+ case 0x1d9: /* 0 111 011 001 */ cp1610_xorr(cpustate, 3,1); break;
+ case 0x1da: /* 0 111 011 010 */ cp1610_xorr(cpustate, 3,2); break;
+ case 0x1db: /* 0 111 011 011 */ cp1610_clrr(cpustate, 3); break;
+ case 0x1dc: /* 0 111 011 100 */ cp1610_xorr(cpustate, 3,4); break;
+ case 0x1dd: /* 0 111 011 101 */ cp1610_xorr(cpustate, 3,5); break;
+ case 0x1de: /* 0 111 011 110 */ cp1610_xorr(cpustate, 3,6); break;
+ case 0x1df: /* 0 111 011 111 */ cp1610_xorr(cpustate, 3,7); break;
+
+ case 0x1e0: /* 0 111 100 000 */ cp1610_xorr(cpustate, 4,0); break;
+ case 0x1e1: /* 0 111 100 001 */ cp1610_xorr(cpustate, 4,1); break;
+ case 0x1e2: /* 0 111 100 010 */ cp1610_xorr(cpustate, 4,2); break;
+ case 0x1e3: /* 0 111 100 011 */ cp1610_xorr(cpustate, 4,3); break;
+ case 0x1e4: /* 0 111 100 100 */ cp1610_clrr(cpustate, 4); break;
+ case 0x1e5: /* 0 111 100 101 */ cp1610_xorr(cpustate, 4,5); break;
+ case 0x1e6: /* 0 111 100 110 */ cp1610_xorr(cpustate, 4,6); break;
+ case 0x1e7: /* 0 111 100 111 */ cp1610_xorr(cpustate, 4,7); break;
+
+ case 0x1e8: /* 0 111 101 000 */ cp1610_xorr(cpustate, 5,0); break;
+ case 0x1e9: /* 0 111 101 001 */ cp1610_xorr(cpustate, 5,1); break;
+ case 0x1ea: /* 0 111 101 010 */ cp1610_xorr(cpustate, 5,2); break;
+ case 0x1eb: /* 0 111 101 011 */ cp1610_xorr(cpustate, 5,3); break;
+ case 0x1ec: /* 0 111 101 100 */ cp1610_xorr(cpustate, 5,4); break;
+ case 0x1ed: /* 0 111 101 101 */ cp1610_clrr(cpustate, 5); break;
+ case 0x1ee: /* 0 111 101 110 */ cp1610_xorr(cpustate, 5,6); break;
+ case 0x1ef: /* 0 111 101 111 */ cp1610_xorr(cpustate, 5,7); break;
+
+ case 0x1f0: /* 0 111 110 000 */ cp1610_xorr(cpustate, 6,0); break;
+ case 0x1f1: /* 0 111 110 001 */ cp1610_xorr(cpustate, 6,1); break;
+ case 0x1f2: /* 0 111 110 010 */ cp1610_xorr(cpustate, 6,2); break;
+ case 0x1f3: /* 0 111 110 011 */ cp1610_xorr(cpustate, 6,3); break;
+ case 0x1f4: /* 0 111 110 100 */ cp1610_xorr(cpustate, 6,4); break;
+ case 0x1f5: /* 0 111 110 101 */ cp1610_xorr(cpustate, 6,5); break;
+ case 0x1f6: /* 0 111 110 110 */ cp1610_clrr(cpustate, 6); break;
+ case 0x1f7: /* 0 111 110 111 */ cp1610_xorr(cpustate, 6,7); break;
+
+ case 0x1f8: /* 0 111 111 000 */ cp1610_xorr(cpustate, 7,0); break;
+ case 0x1f9: /* 0 111 111 001 */ cp1610_xorr(cpustate, 7,1); break;
+ case 0x1fa: /* 0 111 111 010 */ cp1610_xorr(cpustate, 7,2); break;
+ case 0x1fb: /* 0 111 111 011 */ cp1610_xorr(cpustate, 7,3); break;
+ case 0x1fc: /* 0 111 111 100 */ cp1610_xorr(cpustate, 7,4); break;
+ case 0x1fd: /* 0 111 111 101 */ cp1610_xorr(cpustate, 7,5); break;
+ case 0x1fe: /* 0 111 111 110 */ cp1610_xorr(cpustate, 7,6); break;
+ case 0x1ff: /* 0 110 111 111 */ cp1610_clrr(cpustate, 7); break;
+
+ case 0x200: /* 1 000 000 000 */ cp1610_b(cpustate, 0); break;
+ case 0x201: /* 1 000 000 001 */ cp1610_bc(cpustate, 0); break; /* aka BLGE */
+ case 0x202: /* 1 000 000 010 */ cp1610_bov(cpustate, 0); break;
+ case 0x203: /* 1 000 000 011 */ cp1610_bpl(cpustate, 0); break;
+ case 0x204: /* 1 000 000 100 */ cp1610_bze(cpustate, 0); break; /* aka BEQ */
+ case 0x205: /* 1 000 000 101 */ cp1610_blt(cpustate, 0); break;
+ case 0x206: /* 1 000 000 110 */ cp1610_ble(cpustate, 0); break;
+ case 0x207: /* 1 000 000 111 */ cp1610_busc(cpustate, 0); break;
+
+ case 0x208: /* 1 000 001 000 */ cp1610_nopp(cpustate, 0); break;
+ case 0x209: /* 1 000 001 001 */ cp1610_bnc(cpustate, 0); break; /* aka BLLT */
+ case 0x20a: /* 1 000 001 010 */ cp1610_bnov(cpustate, 0); break;
+ case 0x20b: /* 1 000 001 011 */ cp1610_bmi(cpustate, 0); break;
+ case 0x20c: /* 1 000 001 100 */ cp1610_bnze(cpustate, 0); break; /* aka BNEQ */
+ case 0x20d: /* 1 000 001 101 */ cp1610_bge(cpustate, 0); break;
+ case 0x20e: /* 1 000 001 110 */ cp1610_bgt(cpustate, 0); break;
+ case 0x20f: /* 1 000 001 111 */ cp1610_besc(cpustate, 0); break;
+
+ case 0x210: /* 1 000 010 000 */ cp1610_bext(cpustate, 0,0); break;
+ case 0x211: /* 1 000 010 001 */ cp1610_bext(cpustate, 1,0); break;
+ case 0x212: /* 1 000 010 010 */ cp1610_bext(cpustate, 2,0); break;
+ case 0x213: /* 1 000 010 011 */ cp1610_bext(cpustate, 3,0); break;
+ case 0x214: /* 1 000 010 100 */ cp1610_bext(cpustate, 4,0); break;
+ case 0x215: /* 1 000 010 101 */ cp1610_bext(cpustate, 5,0); break;
+ case 0x216: /* 1 000 010 110 */ cp1610_bext(cpustate, 6,0); break;
+ case 0x217: /* 1 000 010 111 */ cp1610_bext(cpustate, 7,0); break;
+
+ case 0x218: /* 1 000 011 000 */ cp1610_bext(cpustate, 8,0); break;
+ case 0x219: /* 1 000 011 001 */ cp1610_bext(cpustate, 9,0); break;
+ case 0x21a: /* 1 000 011 010 */ cp1610_bext(cpustate, 10,0); break;
+ case 0x21b: /* 1 000 011 011 */ cp1610_bext(cpustate, 11,0); break;
+ case 0x21c: /* 1 000 011 100 */ cp1610_bext(cpustate, 12,0); break;
+ case 0x21d: /* 1 000 011 101 */ cp1610_bext(cpustate, 13,0); break;
+ case 0x21e: /* 1 000 011 110 */ cp1610_bext(cpustate, 14,0); break;
+ case 0x21f: /* 1 000 011 111 */ cp1610_bext(cpustate, 15,0); break;
+
+ case 0x220: /* 1 000 100 000 */ cp1610_b(cpustate, 0xffff); break;
+ case 0x221: /* 1 000 100 001 */ cp1610_bc(cpustate, 0xffff); break; /* aka BLGE */
+ case 0x222: /* 1 000 100 010 */ cp1610_bov(cpustate, 0xffff); break;
+ case 0x223: /* 1 000 100 011 */ cp1610_bpl(cpustate, 0xffff); break;
+ case 0x224: /* 1 000 100 100 */ cp1610_bze(cpustate, 0xffff); break; /* aka BEQ */
+ case 0x225: /* 1 000 100 101 */ cp1610_blt(cpustate, 0xffff); break;
+ case 0x226: /* 1 000 100 110 */ cp1610_ble(cpustate, 0xffff); break;
+ case 0x227: /* 1 000 100 111 */ cp1610_busc(cpustate, 0xffff); break;
+
+ case 0x228: /* 1 000 101 000 */ cp1610_nopp(cpustate, 0xffff); break;
+ case 0x229: /* 1 000 101 001 */ cp1610_bnc(cpustate, 0xffff); break; /* aka BLLT */
+ case 0x22a: /* 1 000 101 010 */ cp1610_bnov(cpustate, 0xffff); break;
+ case 0x22b: /* 1 000 101 011 */ cp1610_bmi(cpustate, 0xffff); break;
+ case 0x22c: /* 1 000 101 100 */ cp1610_bnze(cpustate, 0xffff); break; /* aka BNEQ */
+ case 0x22d: /* 1 000 101 101 */ cp1610_bge(cpustate, 0xffff); break;
+ case 0x22e: /* 1 000 101 110 */ cp1610_bgt(cpustate, 0xffff); break;
+ case 0x22f: /* 1 000 101 111 */ cp1610_besc(cpustate, 0xffff); break;
+
+ case 0x230: /* 1 000 110 000 */ cp1610_bext(cpustate, 0,0xffff); break;
+ case 0x231: /* 1 000 110 001 */ cp1610_bext(cpustate, 1,0xffff); break;
+ case 0x232: /* 1 000 110 010 */ cp1610_bext(cpustate, 2,0xffff); break;
+ case 0x233: /* 1 000 110 011 */ cp1610_bext(cpustate, 3,0xffff); break;
+ case 0x234: /* 1 000 110 100 */ cp1610_bext(cpustate, 4,0xffff); break;
+ case 0x235: /* 1 000 110 101 */ cp1610_bext(cpustate, 5,0xffff); break;
+ case 0x236: /* 1 000 110 110 */ cp1610_bext(cpustate, 6,0xffff); break;
+ case 0x237: /* 1 000 110 111 */ cp1610_bext(cpustate, 7,0xffff); break;
+
+ case 0x238: /* 1 000 111 000 */ cp1610_bext(cpustate, 8,0xffff); break;
+ case 0x239: /* 1 000 111 001 */ cp1610_bext(cpustate, 9,0xffff); break;
+ case 0x23a: /* 1 000 111 010 */ cp1610_bext(cpustate, 10,0xffff); break;
+ case 0x23b: /* 1 000 111 011 */ cp1610_bext(cpustate, 11,0xffff); break;
+ case 0x23c: /* 1 000 111 100 */ cp1610_bext(cpustate, 12,0xffff); break;
+ case 0x23d: /* 1 000 111 101 */ cp1610_bext(cpustate, 13,0xffff); break;
+ case 0x23e: /* 1 000 111 110 */ cp1610_bext(cpustate, 14,0xffff); break;
+ case 0x23f: /* 1 000 111 111 */ cp1610_bext(cpustate, 15,0xffff); break;
+
+ case 0x240: /* 1 001 000 000 */ cp1610_mvo(cpustate, 0); break;
+ case 0x241: /* 1 001 000 001 */ cp1610_mvo(cpustate, 1); break;
+ case 0x242: /* 1 001 000 010 */ cp1610_mvo(cpustate, 2); break;
+ case 0x243: /* 1 001 000 011 */ cp1610_mvo(cpustate, 3); break;
+ case 0x244: /* 1 001 000 100 */ cp1610_mvo(cpustate, 4); break;
+ case 0x245: /* 1 001 000 101 */ cp1610_mvo(cpustate, 5); break;
+ case 0x246: /* 1 001 000 110 */ cp1610_mvo(cpustate, 6); break;
+ case 0x247: /* 1 001 000 111 */ cp1610_mvo(cpustate, 7); break;
+
+ case 0x248: /* 1 001 001 000 */ cp1610_mvoat(cpustate, 0,1); break;
+ case 0x249: /* 1 001 001 001 */ cp1610_mvoat(cpustate, 1,1); break;
+ case 0x24a: /* 1 001 001 010 */ cp1610_mvoat(cpustate, 2,1); break;
+ case 0x24b: /* 1 001 001 011 */ cp1610_mvoat(cpustate, 3,1); break;
+ case 0x24c: /* 1 001 001 100 */ cp1610_mvoat(cpustate, 4,1); break;
+ case 0x24d: /* 1 001 001 101 */ cp1610_mvoat(cpustate, 5,1); break;
+ case 0x24e: /* 1 001 001 110 */ cp1610_mvoat(cpustate, 6,1); break;
+ case 0x24f: /* 1 001 001 111 */ cp1610_mvoat(cpustate, 7,1); break;
+
+ case 0x250: /* 1 001 010 000 */ cp1610_mvoat(cpustate, 0,2); break;
+ case 0x251: /* 1 001 010 001 */ cp1610_mvoat(cpustate, 1,2); break;
+ case 0x252: /* 1 001 010 010 */ cp1610_mvoat(cpustate, 2,2); break;
+ case 0x253: /* 1 001 010 011 */ cp1610_mvoat(cpustate, 3,2); break;
+ case 0x254: /* 1 001 010 100 */ cp1610_mvoat(cpustate, 4,2); break;
+ case 0x255: /* 1 001 010 101 */ cp1610_mvoat(cpustate, 5,2); break;
+ case 0x256: /* 1 001 010 110 */ cp1610_mvoat(cpustate, 6,2); break;
+ case 0x257: /* 1 001 010 111 */ cp1610_mvoat(cpustate, 7,2); break;
+
+ case 0x258: /* 1 001 011 000 */ cp1610_mvoat(cpustate, 0,3); break;
+ case 0x259: /* 1 001 011 001 */ cp1610_mvoat(cpustate, 1,3); break;
+ case 0x25a: /* 1 001 011 010 */ cp1610_mvoat(cpustate, 2,3); break;
+ case 0x25b: /* 1 001 011 011 */ cp1610_mvoat(cpustate, 3,3); break;
+ case 0x25c: /* 1 001 011 100 */ cp1610_mvoat(cpustate, 4,3); break;
+ case 0x25d: /* 1 001 011 101 */ cp1610_mvoat(cpustate, 5,3); break;
+ case 0x25e: /* 1 001 011 110 */ cp1610_mvoat(cpustate, 6,3); break;
+ case 0x25f: /* 1 001 011 111 */ cp1610_mvoat(cpustate, 7,3); break;
+
+ case 0x260: /* 1 001 100 000 */ cp1610_mvoat_i(cpustate, 0,4); break;
+ case 0x261: /* 1 001 100 001 */ cp1610_mvoat_i(cpustate, 1,4); break;
+ case 0x262: /* 1 001 100 010 */ cp1610_mvoat_i(cpustate, 2,4); break;
+ case 0x263: /* 1 001 100 011 */ cp1610_mvoat_i(cpustate, 3,4); break;
+ case 0x264: /* 1 001 100 100 */ cp1610_mvoat_i(cpustate, 4,4); break;
+ case 0x265: /* 1 001 100 101 */ cp1610_mvoat_i(cpustate, 5,4); break;
+ case 0x266: /* 1 001 100 110 */ cp1610_mvoat_i(cpustate, 6,4); break;
+ case 0x267: /* 1 001 100 111 */ cp1610_mvoat_i(cpustate, 7,4); break;
+
+ case 0x268: /* 1 001 101 000 */ cp1610_mvoat_i(cpustate, 0,5); break;
+ case 0x269: /* 1 001 101 001 */ cp1610_mvoat_i(cpustate, 1,5); break;
+ case 0x26a: /* 1 001 101 010 */ cp1610_mvoat_i(cpustate, 2,5); break;
+ case 0x26b: /* 1 001 101 011 */ cp1610_mvoat_i(cpustate, 3,5); break;
+ case 0x26c: /* 1 001 101 100 */ cp1610_mvoat_i(cpustate, 4,5); break;
+ case 0x26d: /* 1 001 101 101 */ cp1610_mvoat_i(cpustate, 5,5); break;
+ case 0x26e: /* 1 001 101 110 */ cp1610_mvoat_i(cpustate, 6,5); break;
+ case 0x26f: /* 1 001 101 111 */ cp1610_mvoat_i(cpustate, 7,5); break;
+
+ case 0x270: /* 1 001 110 000 */ cp1610_mvoat_i(cpustate, 0,6); break; /* pshr */
+ case 0x271: /* 1 001 110 001 */ cp1610_mvoat_i(cpustate, 1,6); break; /* pshr */
+ case 0x272: /* 1 001 110 010 */ cp1610_mvoat_i(cpustate, 2,6); break; /* pshr */
+ case 0x273: /* 1 001 110 011 */ cp1610_mvoat_i(cpustate, 3,6); break; /* pshr */
+ case 0x274: /* 1 001 110 100 */ cp1610_mvoat_i(cpustate, 4,6); break; /* pshr */
+ case 0x275: /* 1 001 110 101 */ cp1610_mvoat_i(cpustate, 5,6); break; /* pshr */
+ case 0x276: /* 1 001 110 110 */ cp1610_mvoat_i(cpustate, 6,6); break; /* pshr */
+ case 0x277: /* 1 001 110 111 */ cp1610_mvoat_i(cpustate, 7,6); break; /* pshr */
+
+ case 0x278: /* 1 001 111 000 */ cp1610_mvoi(cpustate, 0); break;
+ case 0x279: /* 1 001 111 001 */ cp1610_mvoi(cpustate, 1); break;
+ case 0x27a: /* 1 001 111 010 */ cp1610_mvoi(cpustate, 2); break;
+ case 0x27b: /* 1 001 111 011 */ cp1610_mvoi(cpustate, 3); break;
+ case 0x27c: /* 1 001 111 100 */ cp1610_mvoi(cpustate, 4); break;
+ case 0x27d: /* 1 001 111 101 */ cp1610_mvoi(cpustate, 5); break;
+ case 0x27e: /* 1 001 111 110 */ cp1610_mvoi(cpustate, 6); break;
+ case 0x27f: /* 1 001 111 111 */ cp1610_mvoi(cpustate, 7); break;
+
+ case 0x280: /* 1 010 000 000 */ cp1610_mvi(cpustate, 0); break;
+ case 0x281: /* 1 010 000 001 */ cp1610_mvi(cpustate, 1); break;
+ case 0x282: /* 1 010 000 010 */ cp1610_mvi(cpustate, 2); break;
+ case 0x283: /* 1 010 000 011 */ cp1610_mvi(cpustate, 3); break;
+ case 0x284: /* 1 010 000 100 */ cp1610_mvi(cpustate, 4); break;
+ case 0x285: /* 1 010 000 101 */ cp1610_mvi(cpustate, 5); break;
+ case 0x286: /* 1 010 000 110 */ cp1610_mvi(cpustate, 6); break;
+ case 0x287: /* 1 010 000 111 */ cp1610_mvi(cpustate, 7); break;
+
+ case 0x288: /* 1 010 001 000 */ cp1610_mviat(cpustate, 1,0); break;
+ case 0x289: /* 1 010 001 001 */ cp1610_mviat(cpustate, 1,1); break;
+ case 0x28a: /* 1 010 001 010 */ cp1610_mviat(cpustate, 1,2); break;
+ case 0x28b: /* 1 010 001 011 */ cp1610_mviat(cpustate, 1,3); break;
+ case 0x28c: /* 1 010 001 100 */ cp1610_mviat(cpustate, 1,4); break;
+ case 0x28d: /* 1 010 001 101 */ cp1610_mviat(cpustate, 1,5); break;
+ case 0x28e: /* 1 010 001 110 */ cp1610_mviat(cpustate, 1,6); break;
+ case 0x28f: /* 1 010 001 111 */ cp1610_mviat(cpustate, 1,7); break;
+
+ case 0x290: /* 1 010 010 000 */ cp1610_mviat(cpustate, 2,0); break;
+ case 0x291: /* 1 010 010 001 */ cp1610_mviat(cpustate, 2,1); break;
+ case 0x292: /* 1 010 010 010 */ cp1610_mviat(cpustate, 2,2); break;
+ case 0x293: /* 1 010 010 011 */ cp1610_mviat(cpustate, 2,3); break;
+ case 0x294: /* 1 010 010 100 */ cp1610_mviat(cpustate, 2,4); break;
+ case 0x295: /* 1 010 010 101 */ cp1610_mviat(cpustate, 2,5); break;
+ case 0x296: /* 1 010 010 110 */ cp1610_mviat(cpustate, 2,6); break;
+ case 0x297: /* 1 010 010 111 */ cp1610_mviat(cpustate, 2,7); break;
+
+ case 0x298: /* 1 010 011 000 */ cp1610_mviat(cpustate, 3,0); break;
+ case 0x299: /* 1 010 011 001 */ cp1610_mviat(cpustate, 3,1); break;
+ case 0x29a: /* 1 010 011 010 */ cp1610_mviat(cpustate, 3,2); break;
+ case 0x29b: /* 1 010 011 011 */ cp1610_mviat(cpustate, 3,3); break;
+ case 0x29c: /* 1 010 011 100 */ cp1610_mviat(cpustate, 3,4); break;
+ case 0x29d: /* 1 010 011 101 */ cp1610_mviat(cpustate, 3,5); break;
+ case 0x29e: /* 1 010 011 110 */ cp1610_mviat(cpustate, 3,6); break;
+ case 0x29f: /* 1 010 011 111 */ cp1610_mviat(cpustate, 3,7); break;
+
+ case 0x2a0: /* 1 010 100 000 */ cp1610_mviat_i(cpustate, 4,0); break;
+ case 0x2a1: /* 1 010 100 001 */ cp1610_mviat_i(cpustate, 4,1); break;
+ case 0x2a2: /* 1 010 100 010 */ cp1610_mviat_i(cpustate, 4,2); break;
+ case 0x2a3: /* 1 010 100 011 */ cp1610_mviat_i(cpustate, 4,3); break;
+ case 0x2a4: /* 1 010 100 100 */ cp1610_mviat_i(cpustate, 4,4); break;
+ case 0x2a5: /* 1 010 100 101 */ cp1610_mviat_i(cpustate, 4,5); break;
+ case 0x2a6: /* 1 010 100 110 */ cp1610_mviat_i(cpustate, 4,6); break;
+ case 0x2a7: /* 1 010 100 111 */ cp1610_mviat_i(cpustate, 4,7); break;
+
+ case 0x2a8: /* 1 010 101 000 */ cp1610_mviat_i(cpustate, 5,0); break;
+ case 0x2a9: /* 1 010 101 001 */ cp1610_mviat_i(cpustate, 5,1); break;
+ case 0x2aa: /* 1 010 101 010 */ cp1610_mviat_i(cpustate, 5,2); break;
+ case 0x2ab: /* 1 010 101 011 */ cp1610_mviat_i(cpustate, 5,3); break;
+ case 0x2ac: /* 1 010 101 100 */ cp1610_mviat_i(cpustate, 5,4); break;
+ case 0x2ad: /* 1 010 101 101 */ cp1610_mviat_i(cpustate, 5,5); break;
+ case 0x2ae: /* 1 010 101 110 */ cp1610_mviat_i(cpustate, 5,6); break;
+ case 0x2af: /* 1 010 101 111 */ cp1610_mviat_i(cpustate, 5,7); break;
+
+ case 0x2b0: /* 1 010 110 000 */ cp1610_pulr(cpustate, 0); break;
+ case 0x2b1: /* 1 010 110 001 */ cp1610_pulr(cpustate, 1); break;
+ case 0x2b2: /* 1 010 110 010 */ cp1610_pulr(cpustate, 2); break;
+ case 0x2b3: /* 1 010 110 011 */ cp1610_pulr(cpustate, 3); break;
+ case 0x2b4: /* 1 010 110 100 */ cp1610_pulr(cpustate, 4); break;
+ case 0x2b5: /* 1 010 110 101 */ cp1610_pulr(cpustate, 5); break;
+ case 0x2b6: /* 1 010 110 110 */ cp1610_pulr(cpustate, 6); break;
+ case 0x2b7: /* 1 010 110 111 */ cp1610_pulr(cpustate, 7); break;
+
+ case 0x2b8: /* 1 010 111 000 */ cp1610_mvii(cpustate, 0); break;
+ case 0x2b9: /* 1 010 111 001 */ cp1610_mvii(cpustate, 1); break;
+ case 0x2ba: /* 1 010 111 010 */ cp1610_mvii(cpustate, 2); break;
+ case 0x2bb: /* 1 010 111 011 */ cp1610_mvii(cpustate, 3); break;
+ case 0x2bc: /* 1 010 111 100 */ cp1610_mvii(cpustate, 4); break;
+ case 0x2bd: /* 1 010 111 101 */ cp1610_mvii(cpustate, 5); break;
+ case 0x2be: /* 1 010 111 110 */ cp1610_mvii(cpustate, 6); break;
+ case 0x2bf: /* 1 010 111 111 */ cp1610_mvii(cpustate, 7); break;
+
+ case 0x2c0: /* 1 011 000 000 */ cp1610_add(cpustate, 0); break;
+ case 0x2c1: /* 1 011 000 001 */ cp1610_add(cpustate, 1); break;
+ case 0x2c2: /* 1 011 000 010 */ cp1610_add(cpustate, 2); break;
+ case 0x2c3: /* 1 011 000 011 */ cp1610_add(cpustate, 3); break;
+ case 0x2c4: /* 1 011 000 100 */ cp1610_add(cpustate, 4); break;
+ case 0x2c5: /* 1 011 000 101 */ cp1610_add(cpustate, 5); break;
+ case 0x2c6: /* 1 011 000 110 */ cp1610_add(cpustate, 6); break;
+ case 0x2c7: /* 1 011 000 111 */ cp1610_add(cpustate, 7); break;
+
+ case 0x2c8: /* 1 011 001 000 */ cp1610_addat(cpustate, 1,0); break;
+ case 0x2c9: /* 1 011 001 001 */ cp1610_addat(cpustate, 1,1); break;
+ case 0x2ca: /* 1 011 001 010 */ cp1610_addat(cpustate, 1,2); break;
+ case 0x2cb: /* 1 011 001 011 */ cp1610_addat(cpustate, 1,3); break;
+ case 0x2cc: /* 1 011 001 100 */ cp1610_addat(cpustate, 1,4); break;
+ case 0x2cd: /* 1 011 001 101 */ cp1610_addat(cpustate, 1,5); break;
+ case 0x2ce: /* 1 011 001 110 */ cp1610_addat(cpustate, 1,6); break;
+ case 0x2cf: /* 1 011 001 111 */ cp1610_addat(cpustate, 1,7); break;
+
+ case 0x2d0: /* 1 011 010 000 */ cp1610_addat(cpustate, 2,0); break;
+ case 0x2d1: /* 1 011 010 001 */ cp1610_addat(cpustate, 2,1); break;
+ case 0x2d2: /* 1 011 010 010 */ cp1610_addat(cpustate, 2,2); break;
+ case 0x2d3: /* 1 011 010 011 */ cp1610_addat(cpustate, 2,3); break;
+ case 0x2d4: /* 1 011 010 100 */ cp1610_addat(cpustate, 2,4); break;
+ case 0x2d5: /* 1 011 010 101 */ cp1610_addat(cpustate, 2,5); break;
+ case 0x2d6: /* 1 011 010 110 */ cp1610_addat(cpustate, 2,6); break;
+ case 0x2d7: /* 1 011 010 111 */ cp1610_addat(cpustate, 2,7); break;
+
+ case 0x2d8: /* 1 011 011 000 */ cp1610_addat(cpustate, 3,0); break;
+ case 0x2d9: /* 1 011 011 001 */ cp1610_addat(cpustate, 3,1); break;
+ case 0x2da: /* 1 011 011 010 */ cp1610_addat(cpustate, 3,2); break;
+ case 0x2db: /* 1 011 011 011 */ cp1610_addat(cpustate, 3,3); break;
+ case 0x2dc: /* 1 011 011 100 */ cp1610_addat(cpustate, 3,4); break;
+ case 0x2dd: /* 1 011 011 101 */ cp1610_addat(cpustate, 3,5); break;
+ case 0x2de: /* 1 011 011 110 */ cp1610_addat(cpustate, 3,6); break;
+ case 0x2df: /* 1 011 011 111 */ cp1610_addat(cpustate, 3,7); break;
+
+ case 0x2e0: /* 1 011 100 000 */ cp1610_addat_i(cpustate, 4,0); break;
+ case 0x2e1: /* 1 011 100 001 */ cp1610_addat_i(cpustate, 4,1); break;
+ case 0x2e2: /* 1 011 100 010 */ cp1610_addat_i(cpustate, 4,2); break;
+ case 0x2e3: /* 1 011 100 011 */ cp1610_addat_i(cpustate, 4,3); break;
+ case 0x2e4: /* 1 011 100 100 */ cp1610_addat_i(cpustate, 4,4); break;
+ case 0x2e5: /* 1 011 100 101 */ cp1610_addat_i(cpustate, 4,5); break;
+ case 0x2e6: /* 1 011 100 110 */ cp1610_addat_i(cpustate, 4,6); break;
+ case 0x2e7: /* 1 011 100 111 */ cp1610_addat_i(cpustate, 4,7); break;
+
+ case 0x2e8: /* 1 011 101 000 */ cp1610_addat_i(cpustate, 5,0); break;
+ case 0x2e9: /* 1 011 101 001 */ cp1610_addat_i(cpustate, 5,1); break;
+ case 0x2ea: /* 1 011 101 010 */ cp1610_addat_i(cpustate, 5,2); break;
+ case 0x2eb: /* 1 011 101 011 */ cp1610_addat_i(cpustate, 5,3); break;
+ case 0x2ec: /* 1 011 101 100 */ cp1610_addat_i(cpustate, 5,4); break;
+ case 0x2ed: /* 1 011 101 101 */ cp1610_addat_i(cpustate, 5,5); break;
+ case 0x2ee: /* 1 011 101 110 */ cp1610_addat_i(cpustate, 5,6); break;
+ case 0x2ef: /* 1 011 101 111 */ cp1610_addat_i(cpustate, 5,7); break;
+
+ case 0x2f0: /* 1 011 110 000 */ cp1610_addat_d(cpustate, 6,0); break;
+ case 0x2f1: /* 1 011 110 001 */ cp1610_addat_d(cpustate, 6,1); break;
+ case 0x2f2: /* 1 011 110 010 */ cp1610_addat_d(cpustate, 6,2); break;
+ case 0x2f3: /* 1 011 110 011 */ cp1610_addat_d(cpustate, 6,3); break;
+ case 0x2f4: /* 1 011 110 100 */ cp1610_addat_d(cpustate, 6,4); break;
+ case 0x2f5: /* 1 011 110 101 */ cp1610_addat_d(cpustate, 6,5); break;
+ case 0x2f6: /* 1 011 110 110 */ cp1610_addat_d(cpustate, 6,6); break;
+ case 0x2f7: /* 1 011 110 111 */ cp1610_addat_d(cpustate, 6,7); break;
+
+ case 0x2f8: /* 1 011 111 000 */ cp1610_addi(cpustate, 0); break;
+ case 0x2f9: /* 1 011 111 001 */ cp1610_addi(cpustate, 1); break;
+ case 0x2fa: /* 1 011 111 010 */ cp1610_addi(cpustate, 2); break;
+ case 0x2fb: /* 1 011 111 011 */ cp1610_addi(cpustate, 3); break;
+ case 0x2fc: /* 1 011 111 100 */ cp1610_addi(cpustate, 4); break;
+ case 0x2fd: /* 1 011 111 101 */ cp1610_addi(cpustate, 5); break;
+ case 0x2fe: /* 1 011 111 110 */ cp1610_addi(cpustate, 6); break;
+ case 0x2ff: /* 1 011 111 111 */ cp1610_addi(cpustate, 7); break;
+
+ case 0x300: /* 1 100 000 000 */ cp1610_sub(cpustate, 0); break;
+ case 0x301: /* 1 100 000 001 */ cp1610_sub(cpustate, 1); break;
+ case 0x302: /* 1 100 000 010 */ cp1610_sub(cpustate, 2); break;
+ case 0x303: /* 1 100 000 011 */ cp1610_sub(cpustate, 3); break;
+ case 0x304: /* 1 100 000 100 */ cp1610_sub(cpustate, 4); break;
+ case 0x305: /* 1 100 000 101 */ cp1610_sub(cpustate, 5); break;
+ case 0x306: /* 1 100 000 110 */ cp1610_sub(cpustate, 6); break;
+ case 0x307: /* 1 100 000 111 */ cp1610_sub(cpustate, 7); break;
+
+ case 0x308: /* 1 100 001 000 */ cp1610_subat(cpustate, 1,0); break;
+ case 0x309: /* 1 100 001 001 */ cp1610_subat(cpustate, 1,1); break;
+ case 0x30a: /* 1 100 001 010 */ cp1610_subat(cpustate, 1,2); break;
+ case 0x30b: /* 1 100 001 011 */ cp1610_subat(cpustate, 1,3); break;
+ case 0x30c: /* 1 100 001 100 */ cp1610_subat(cpustate, 1,4); break;
+ case 0x30d: /* 1 100 001 101 */ cp1610_subat(cpustate, 1,5); break;
+ case 0x30e: /* 1 100 001 110 */ cp1610_subat(cpustate, 1,6); break;
+ case 0x30f: /* 1 100 001 111 */ cp1610_subat(cpustate, 1,7); break;
+
+ case 0x310: /* 1 100 010 000 */ cp1610_subat(cpustate, 2,0); break;
+ case 0x311: /* 1 100 010 001 */ cp1610_subat(cpustate, 2,1); break;
+ case 0x312: /* 1 100 010 010 */ cp1610_subat(cpustate, 2,2); break;
+ case 0x313: /* 1 100 010 011 */ cp1610_subat(cpustate, 2,3); break;
+ case 0x314: /* 1 100 010 100 */ cp1610_subat(cpustate, 2,4); break;
+ case 0x315: /* 1 100 010 101 */ cp1610_subat(cpustate, 2,5); break;
+ case 0x316: /* 1 100 010 110 */ cp1610_subat(cpustate, 2,6); break;
+ case 0x317: /* 1 100 010 111 */ cp1610_subat(cpustate, 2,7); break;
+
+ case 0x318: /* 1 100 011 000 */ cp1610_subat(cpustate, 3,0); break;
+ case 0x319: /* 1 100 011 001 */ cp1610_subat(cpustate, 3,1); break;
+ case 0x31a: /* 1 100 011 010 */ cp1610_subat(cpustate, 3,2); break;
+ case 0x31b: /* 1 100 011 011 */ cp1610_subat(cpustate, 3,3); break;
+ case 0x31c: /* 1 100 011 100 */ cp1610_subat(cpustate, 3,4); break;
+ case 0x31d: /* 1 100 011 101 */ cp1610_subat(cpustate, 3,5); break;
+ case 0x31e: /* 1 100 011 110 */ cp1610_subat(cpustate, 3,6); break;
+ case 0x31f: /* 1 100 011 111 */ cp1610_subat(cpustate, 3,7); break;
+
+ case 0x320: /* 1 100 100 000 */ cp1610_subat_i(cpustate, 4,0); break;
+ case 0x321: /* 1 100 100 001 */ cp1610_subat_i(cpustate, 4,1); break;
+ case 0x322: /* 1 100 100 010 */ cp1610_subat_i(cpustate, 4,2); break;
+ case 0x323: /* 1 100 100 011 */ cp1610_subat_i(cpustate, 4,3); break;
+ case 0x324: /* 1 100 100 100 */ cp1610_subat_i(cpustate, 4,4); break;
+ case 0x325: /* 1 100 100 101 */ cp1610_subat_i(cpustate, 4,5); break;
+ case 0x326: /* 1 100 100 110 */ cp1610_subat_i(cpustate, 4,6); break;
+ case 0x327: /* 1 100 100 111 */ cp1610_subat_i(cpustate, 4,7); break;
+
+ case 0x328: /* 1 100 101 000 */ cp1610_subat_i(cpustate, 5,0); break;
+ case 0x329: /* 1 100 101 001 */ cp1610_subat_i(cpustate, 5,1); break;
+ case 0x32a: /* 1 100 101 010 */ cp1610_subat_i(cpustate, 5,2); break;
+ case 0x32b: /* 1 100 101 011 */ cp1610_subat_i(cpustate, 5,3); break;
+ case 0x32c: /* 1 100 101 100 */ cp1610_subat_i(cpustate, 5,4); break;
+ case 0x32d: /* 1 100 101 101 */ cp1610_subat_i(cpustate, 5,5); break;
+ case 0x32e: /* 1 100 101 110 */ cp1610_subat_i(cpustate, 5,6); break;
+ case 0x32f: /* 1 100 101 111 */ cp1610_subat_i(cpustate, 5,7); break;
+
+ case 0x330: /* 1 100 110 000 */ cp1610_subat_d(cpustate, 6,0); break;
+ case 0x331: /* 1 100 110 001 */ cp1610_subat_d(cpustate, 6,1); break;
+ case 0x332: /* 1 100 110 010 */ cp1610_subat_d(cpustate, 6,2); break;
+ case 0x333: /* 1 100 110 011 */ cp1610_subat_d(cpustate, 6,3); break;
+ case 0x334: /* 1 100 110 100 */ cp1610_subat_d(cpustate, 6,4); break;
+ case 0x335: /* 1 100 110 101 */ cp1610_subat_d(cpustate, 6,5); break;
+ case 0x336: /* 1 100 110 110 */ cp1610_subat_d(cpustate, 6,6); break;
+ case 0x337: /* 1 100 110 111 */ cp1610_subat_d(cpustate, 6,7); break;
+
+ case 0x338: /* 1 100 111 000 */ cp1610_subi(cpustate, 0); break;
+ case 0x339: /* 1 100 111 001 */ cp1610_subi(cpustate, 1); break;
+ case 0x33a: /* 1 100 111 010 */ cp1610_subi(cpustate, 2); break;
+ case 0x33b: /* 1 100 111 011 */ cp1610_subi(cpustate, 3); break;
+ case 0x33c: /* 1 100 111 100 */ cp1610_subi(cpustate, 4); break;
+ case 0x33d: /* 1 100 111 101 */ cp1610_subi(cpustate, 5); break;
+ case 0x33e: /* 1 100 111 110 */ cp1610_subi(cpustate, 6); break;
+ case 0x33f: /* 1 100 111 111 */ cp1610_subi(cpustate, 7); break;
+
+ case 0x340: /* 1 101 000 000 */ cp1610_cmp(cpustate, 0); break;
+ case 0x341: /* 1 101 000 001 */ cp1610_cmp(cpustate, 1); break;
+ case 0x342: /* 1 101 000 010 */ cp1610_cmp(cpustate, 2); break;
+ case 0x343: /* 1 101 000 011 */ cp1610_cmp(cpustate, 3); break;
+ case 0x344: /* 1 101 000 100 */ cp1610_cmp(cpustate, 4); break;
+ case 0x345: /* 1 101 000 101 */ cp1610_cmp(cpustate, 5); break;
+ case 0x346: /* 1 101 000 110 */ cp1610_cmp(cpustate, 6); break;
+ case 0x347: /* 1 101 000 111 */ cp1610_cmp(cpustate, 7); break;
+
+ case 0x348: /* 1 101 001 000 */ cp1610_cmpat(cpustate, 1,0); break;
+ case 0x349: /* 1 101 001 001 */ cp1610_cmpat(cpustate, 1,1); break;
+ case 0x34a: /* 1 101 001 010 */ cp1610_cmpat(cpustate, 1,2); break;
+ case 0x34b: /* 1 101 001 011 */ cp1610_cmpat(cpustate, 1,3); break;
+ case 0x34c: /* 1 101 001 100 */ cp1610_cmpat(cpustate, 1,4); break;
+ case 0x34d: /* 1 101 001 101 */ cp1610_cmpat(cpustate, 1,5); break;
+ case 0x34e: /* 1 101 001 110 */ cp1610_cmpat(cpustate, 1,6); break;
+ case 0x34f: /* 1 101 001 111 */ cp1610_cmpat(cpustate, 1,7); break;
+
+ case 0x350: /* 1 101 010 000 */ cp1610_cmpat(cpustate, 2,0); break;
+ case 0x351: /* 1 101 010 001 */ cp1610_cmpat(cpustate, 2,1); break;
+ case 0x352: /* 1 101 010 010 */ cp1610_cmpat(cpustate, 2,2); break;
+ case 0x353: /* 1 101 010 011 */ cp1610_cmpat(cpustate, 2,3); break;
+ case 0x354: /* 1 101 010 100 */ cp1610_cmpat(cpustate, 2,4); break;
+ case 0x355: /* 1 101 010 101 */ cp1610_cmpat(cpustate, 2,5); break;
+ case 0x356: /* 1 101 010 110 */ cp1610_cmpat(cpustate, 2,6); break;
+ case 0x357: /* 1 101 010 111 */ cp1610_cmpat(cpustate, 2,7); break;
+
+ case 0x358: /* 1 101 011 000 */ cp1610_cmpat(cpustate, 3,0); break;
+ case 0x359: /* 1 101 011 001 */ cp1610_cmpat(cpustate, 3,1); break;
+ case 0x35a: /* 1 101 011 010 */ cp1610_cmpat(cpustate, 3,2); break;
+ case 0x35b: /* 1 101 011 011 */ cp1610_cmpat(cpustate, 3,3); break;
+ case 0x35c: /* 1 101 011 100 */ cp1610_cmpat(cpustate, 3,4); break;
+ case 0x35d: /* 1 101 011 101 */ cp1610_cmpat(cpustate, 3,5); break;
+ case 0x35e: /* 1 101 011 110 */ cp1610_cmpat(cpustate, 3,6); break;
+ case 0x35f: /* 1 101 011 111 */ cp1610_cmpat(cpustate, 3,7); break;
+
+ case 0x360: /* 1 101 100 000 */ cp1610_cmpat_i(cpustate, 4,0); break;
+ case 0x361: /* 1 101 100 001 */ cp1610_cmpat_i(cpustate, 4,1); break;
+ case 0x362: /* 1 101 100 010 */ cp1610_cmpat_i(cpustate, 4,2); break;
+ case 0x363: /* 1 101 100 011 */ cp1610_cmpat_i(cpustate, 4,3); break;
+ case 0x364: /* 1 101 100 100 */ cp1610_cmpat_i(cpustate, 4,4); break;
+ case 0x365: /* 1 101 100 101 */ cp1610_cmpat_i(cpustate, 4,5); break;
+ case 0x366: /* 1 101 100 110 */ cp1610_cmpat_i(cpustate, 4,6); break;
+ case 0x367: /* 1 101 100 111 */ cp1610_cmpat_i(cpustate, 4,7); break;
+
+ case 0x368: /* 1 101 101 000 */ cp1610_cmpat_i(cpustate, 5,0); break;
+ case 0x369: /* 1 101 101 001 */ cp1610_cmpat_i(cpustate, 5,1); break;
+ case 0x36a: /* 1 101 101 010 */ cp1610_cmpat_i(cpustate, 5,2); break;
+ case 0x36b: /* 1 101 101 011 */ cp1610_cmpat_i(cpustate, 5,3); break;
+ case 0x36c: /* 1 101 101 100 */ cp1610_cmpat_i(cpustate, 5,4); break;
+ case 0x36d: /* 1 101 101 101 */ cp1610_cmpat_i(cpustate, 5,5); break;
+ case 0x36e: /* 1 101 101 110 */ cp1610_cmpat_i(cpustate, 5,6); break;
+ case 0x36f: /* 1 101 101 111 */ cp1610_cmpat_i(cpustate, 5,7); break;
+
+ case 0x370: /* 1 101 110 000 */ cp1610_cmpat_d(cpustate, 6,0); break;
+ case 0x371: /* 1 101 110 001 */ cp1610_cmpat_d(cpustate, 6,1); break;
+ case 0x372: /* 1 101 110 010 */ cp1610_cmpat_d(cpustate, 6,2); break;
+ case 0x373: /* 1 101 110 011 */ cp1610_cmpat_d(cpustate, 6,3); break;
+ case 0x374: /* 1 101 110 100 */ cp1610_cmpat_d(cpustate, 6,4); break;
+ case 0x375: /* 1 101 110 101 */ cp1610_cmpat_d(cpustate, 6,5); break;
+ case 0x376: /* 1 101 110 110 */ cp1610_cmpat_d(cpustate, 6,6); break;
+ case 0x377: /* 1 101 110 111 */ cp1610_cmpat_d(cpustate, 6,7); break;
+
+ case 0x378: /* 1 101 111 000 */ cp1610_cmpi(cpustate, 0); break;
+ case 0x379: /* 1 101 111 001 */ cp1610_cmpi(cpustate, 1); break;
+ case 0x37a: /* 1 101 111 010 */ cp1610_cmpi(cpustate, 2); break;
+ case 0x37b: /* 1 101 111 011 */ cp1610_cmpi(cpustate, 3); break;
+ case 0x37c: /* 1 101 111 100 */ cp1610_cmpi(cpustate, 4); break;
+ case 0x37d: /* 1 101 111 101 */ cp1610_cmpi(cpustate, 5); break;
+ case 0x37e: /* 1 101 111 110 */ cp1610_cmpi(cpustate, 6); break;
+ case 0x37f: /* 1 101 111 111 */ cp1610_cmpi(cpustate, 7); break;
+
+ case 0x380: /* 1 110 000 000 */ cp1610_and(cpustate, 0); break;
+ case 0x381: /* 1 110 000 001 */ cp1610_and(cpustate, 1); break;
+ case 0x382: /* 1 110 000 010 */ cp1610_and(cpustate, 2); break;
+ case 0x383: /* 1 110 000 011 */ cp1610_and(cpustate, 3); break;
+ case 0x384: /* 1 110 000 100 */ cp1610_and(cpustate, 4); break;
+ case 0x385: /* 1 110 000 101 */ cp1610_and(cpustate, 5); break;
+ case 0x386: /* 1 110 000 110 */ cp1610_and(cpustate, 6); break;
+ case 0x387: /* 1 110 000 111 */ cp1610_and(cpustate, 7); break;
+
+ case 0x388: /* 1 110 001 000 */ cp1610_andat(cpustate, 1,0); break;
+ case 0x389: /* 1 110 001 001 */ cp1610_andat(cpustate, 1,1); break;
+ case 0x38a: /* 1 110 001 010 */ cp1610_andat(cpustate, 1,2); break;
+ case 0x38b: /* 1 110 001 011 */ cp1610_andat(cpustate, 1,3); break;
+ case 0x38c: /* 1 110 001 100 */ cp1610_andat(cpustate, 1,4); break;
+ case 0x38d: /* 1 110 001 101 */ cp1610_andat(cpustate, 1,5); break;
+ case 0x38e: /* 1 110 001 110 */ cp1610_andat(cpustate, 1,6); break;
+ case 0x38f: /* 1 110 001 111 */ cp1610_andat(cpustate, 1,7); break;
+
+ case 0x390: /* 1 110 010 000 */ cp1610_andat(cpustate, 2,0); break;
+ case 0x391: /* 1 110 010 001 */ cp1610_andat(cpustate, 2,1); break;
+ case 0x392: /* 1 110 010 010 */ cp1610_andat(cpustate, 2,2); break;
+ case 0x393: /* 1 110 010 011 */ cp1610_andat(cpustate, 2,3); break;
+ case 0x394: /* 1 110 010 100 */ cp1610_andat(cpustate, 2,4); break;
+ case 0x395: /* 1 110 010 101 */ cp1610_andat(cpustate, 2,5); break;
+ case 0x396: /* 1 110 010 110 */ cp1610_andat(cpustate, 2,6); break;
+ case 0x397: /* 1 110 010 111 */ cp1610_andat(cpustate, 2,7); break;
+
+ case 0x398: /* 1 110 011 000 */ cp1610_andat(cpustate, 3,0); break;
+ case 0x399: /* 1 110 011 001 */ cp1610_andat(cpustate, 3,1); break;
+ case 0x39a: /* 1 110 011 010 */ cp1610_andat(cpustate, 3,2); break;
+ case 0x39b: /* 1 110 011 011 */ cp1610_andat(cpustate, 3,3); break;
+ case 0x39c: /* 1 110 011 100 */ cp1610_andat(cpustate, 3,4); break;
+ case 0x39d: /* 1 110 011 101 */ cp1610_andat(cpustate, 3,5); break;
+ case 0x39e: /* 1 110 011 110 */ cp1610_andat(cpustate, 3,6); break;
+ case 0x39f: /* 1 110 011 111 */ cp1610_andat(cpustate, 3,7); break;
+
+ case 0x3a0: /* 1 110 100 000 */ cp1610_andat_i(cpustate, 4,0); break;
+ case 0x3a1: /* 1 110 100 001 */ cp1610_andat_i(cpustate, 4,1); break;
+ case 0x3a2: /* 1 110 100 010 */ cp1610_andat_i(cpustate, 4,2); break;
+ case 0x3a3: /* 1 110 100 011 */ cp1610_andat_i(cpustate, 4,3); break;
+ case 0x3a4: /* 1 110 100 100 */ cp1610_andat_i(cpustate, 4,4); break;
+ case 0x3a5: /* 1 110 100 101 */ cp1610_andat_i(cpustate, 4,5); break;
+ case 0x3a6: /* 1 110 100 110 */ cp1610_andat_i(cpustate, 4,6); break;
+ case 0x3a7: /* 1 110 100 111 */ cp1610_andat_i(cpustate, 4,7); break;
+
+ case 0x3a8: /* 1 110 101 000 */ cp1610_andat_i(cpustate, 5,0); break;
+ case 0x3a9: /* 1 110 101 001 */ cp1610_andat_i(cpustate, 5,1); break;
+ case 0x3aa: /* 1 110 101 010 */ cp1610_andat_i(cpustate, 5,2); break;
+ case 0x3ab: /* 1 110 101 011 */ cp1610_andat_i(cpustate, 5,3); break;
+ case 0x3ac: /* 1 110 101 100 */ cp1610_andat_i(cpustate, 5,4); break;
+ case 0x3ad: /* 1 110 101 101 */ cp1610_andat_i(cpustate, 5,5); break;
+ case 0x3ae: /* 1 110 101 110 */ cp1610_andat_i(cpustate, 5,6); break;
+ case 0x3af: /* 1 110 101 111 */ cp1610_andat_i(cpustate, 5,7); break;
+
+ case 0x3b0: /* 1 110 110 000 */ cp1610_andat_d(cpustate, 6,0); break;
+ case 0x3b1: /* 1 110 110 001 */ cp1610_andat_d(cpustate, 6,1); break;
+ case 0x3b2: /* 1 110 110 010 */ cp1610_andat_d(cpustate, 6,2); break;
+ case 0x3b3: /* 1 110 110 011 */ cp1610_andat_d(cpustate, 6,3); break;
+ case 0x3b4: /* 1 110 110 100 */ cp1610_andat_d(cpustate, 6,4); break;
+ case 0x3b5: /* 1 110 110 101 */ cp1610_andat_d(cpustate, 6,5); break;
+ case 0x3b6: /* 1 110 110 110 */ cp1610_andat_d(cpustate, 6,6); break;
+ case 0x3b7: /* 1 110 110 111 */ cp1610_andat_d(cpustate, 6,7); break;
+
+ case 0x3b8: /* 1 110 111 000 */ cp1610_andi(cpustate, 0); break;
+ case 0x3b9: /* 1 110 111 001 */ cp1610_andi(cpustate, 1); break;
+ case 0x3ba: /* 1 110 111 010 */ cp1610_andi(cpustate, 2); break;
+ case 0x3bb: /* 1 110 111 011 */ cp1610_andi(cpustate, 3); break;
+ case 0x3bc: /* 1 110 111 100 */ cp1610_andi(cpustate, 4); break;
+ case 0x3bd: /* 1 110 111 101 */ cp1610_andi(cpustate, 5); break;
+ case 0x3be: /* 1 110 111 110 */ cp1610_andi(cpustate, 6); break;
+ case 0x3bf: /* 1 110 111 111 */ cp1610_andi(cpustate, 7); break;
+
+ case 0x3c0: /* 1 111 000 000 */ cp1610_xor(cpustate, 0); break;
+ case 0x3c1: /* 1 111 000 001 */ cp1610_xor(cpustate, 1); break;
+ case 0x3c2: /* 1 111 000 010 */ cp1610_xor(cpustate, 2); break;
+ case 0x3c3: /* 1 111 000 011 */ cp1610_xor(cpustate, 3); break;
+ case 0x3c4: /* 1 111 000 100 */ cp1610_xor(cpustate, 4); break;
+ case 0x3c5: /* 1 111 000 101 */ cp1610_xor(cpustate, 5); break;
+ case 0x3c6: /* 1 111 000 110 */ cp1610_xor(cpustate, 6); break;
+ case 0x3c7: /* 1 111 000 111 */ cp1610_xor(cpustate, 7); break;
+
+ case 0x3c8: /* 1 111 001 000 */ cp1610_xorat(cpustate, 1,0); break;
+ case 0x3c9: /* 1 111 001 001 */ cp1610_xorat(cpustate, 1,1); break;
+ case 0x3ca: /* 1 111 001 010 */ cp1610_xorat(cpustate, 1,2); break;
+ case 0x3cb: /* 1 111 001 011 */ cp1610_xorat(cpustate, 1,3); break;
+ case 0x3cc: /* 1 111 001 100 */ cp1610_xorat(cpustate, 1,4); break;
+ case 0x3cd: /* 1 111 001 101 */ cp1610_xorat(cpustate, 1,5); break;
+ case 0x3ce: /* 1 111 001 110 */ cp1610_xorat(cpustate, 1,6); break;
+ case 0x3cf: /* 1 111 001 111 */ cp1610_xorat(cpustate, 1,7); break;
+
+ case 0x3d0: /* 1 111 010 000 */ cp1610_xorat(cpustate, 2,0); break;
+ case 0x3d1: /* 1 111 010 001 */ cp1610_xorat(cpustate, 2,1); break;
+ case 0x3d2: /* 1 111 010 010 */ cp1610_xorat(cpustate, 2,2); break;
+ case 0x3d3: /* 1 111 010 011 */ cp1610_xorat(cpustate, 2,3); break;
+ case 0x3d4: /* 1 111 010 100 */ cp1610_xorat(cpustate, 2,4); break;
+ case 0x3d5: /* 1 111 010 101 */ cp1610_xorat(cpustate, 2,5); break;
+ case 0x3d6: /* 1 111 010 110 */ cp1610_xorat(cpustate, 2,6); break;
+ case 0x3d7: /* 1 111 010 111 */ cp1610_xorat(cpustate, 2,7); break;
+
+ case 0x3d8: /* 1 111 011 000 */ cp1610_xorat(cpustate, 3,0); break;
+ case 0x3d9: /* 1 111 011 001 */ cp1610_xorat(cpustate, 3,1); break;
+ case 0x3da: /* 1 111 011 010 */ cp1610_xorat(cpustate, 3,2); break;
+ case 0x3db: /* 1 111 011 011 */ cp1610_xorat(cpustate, 3,3); break;
+ case 0x3dc: /* 1 111 011 100 */ cp1610_xorat(cpustate, 3,4); break;
+ case 0x3dd: /* 1 111 011 101 */ cp1610_xorat(cpustate, 3,5); break;
+ case 0x3de: /* 1 111 011 110 */ cp1610_xorat(cpustate, 3,6); break;
+ case 0x3df: /* 1 111 011 111 */ cp1610_xorat(cpustate, 3,7); break;
+
+ case 0x3e0: /* 1 111 100 000 */ cp1610_xorat_i(cpustate, 4,0); break;
+ case 0x3e1: /* 1 111 100 001 */ cp1610_xorat_i(cpustate, 4,1); break;
+ case 0x3e2: /* 1 111 100 010 */ cp1610_xorat_i(cpustate, 4,2); break;
+ case 0x3e3: /* 1 111 100 011 */ cp1610_xorat_i(cpustate, 4,3); break;
+ case 0x3e4: /* 1 111 100 100 */ cp1610_xorat_i(cpustate, 4,4); break;
+ case 0x3e5: /* 1 111 100 101 */ cp1610_xorat_i(cpustate, 4,5); break;
+ case 0x3e6: /* 1 111 100 110 */ cp1610_xorat_i(cpustate, 4,6); break;
+ case 0x3e7: /* 1 111 100 111 */ cp1610_xorat_i(cpustate, 4,7); break;
+
+ case 0x3e8: /* 1 111 101 000 */ cp1610_xorat_i(cpustate, 5,0); break;
+ case 0x3e9: /* 1 111 101 001 */ cp1610_xorat_i(cpustate, 5,1); break;
+ case 0x3ea: /* 1 111 101 010 */ cp1610_xorat_i(cpustate, 5,2); break;
+ case 0x3eb: /* 1 111 101 011 */ cp1610_xorat_i(cpustate, 5,3); break;
+ case 0x3ec: /* 1 111 101 100 */ cp1610_xorat_i(cpustate, 5,4); break;
+ case 0x3ed: /* 1 111 101 101 */ cp1610_xorat_i(cpustate, 5,5); break;
+ case 0x3ee: /* 1 111 101 110 */ cp1610_xorat_i(cpustate, 5,6); break;
+ case 0x3ef: /* 1 111 101 111 */ cp1610_xorat_i(cpustate, 5,7); break;
+
+ case 0x3f0: /* 1 111 110 000 */ cp1610_xorat_d(cpustate, 6,0); break;
+ case 0x3f1: /* 1 111 110 001 */ cp1610_xorat_d(cpustate, 6,1); break;
+ case 0x3f2: /* 1 111 110 010 */ cp1610_xorat_d(cpustate, 6,2); break;
+ case 0x3f3: /* 1 111 110 011 */ cp1610_xorat_d(cpustate, 6,3); break;
+ case 0x3f4: /* 1 111 110 100 */ cp1610_xorat_d(cpustate, 6,4); break;
+ case 0x3f5: /* 1 111 110 101 */ cp1610_xorat_d(cpustate, 6,5); break;
+ case 0x3f6: /* 1 111 110 110 */ cp1610_xorat_d(cpustate, 6,6); break;
+ case 0x3f7: /* 1 111 110 111 */ cp1610_xorat_d(cpustate, 6,7); break;
+
+ case 0x3f8: /* 1 111 111 000 */ cp1610_xori(cpustate, 0); break;
+ case 0x3f9: /* 1 111 111 001 */ cp1610_xori(cpustate, 1); break;
+ case 0x3fa: /* 1 111 111 010 */ cp1610_xori(cpustate, 2); break;
+ case 0x3fb: /* 1 111 111 011 */ cp1610_xori(cpustate, 3); break;
+ case 0x3fc: /* 1 111 111 100 */ cp1610_xori(cpustate, 4); break;
+ case 0x3fd: /* 1 111 111 101 */ cp1610_xori(cpustate, 5); break;
+ case 0x3fe: /* 1 111 111 110 */ cp1610_xori(cpustate, 6); break;
+ case 0x3ff: /* 1 111 111 111 */ cp1610_xori(cpustate, 7); break;
+ }
+
+ if (cpustate->mask_interrupts == 0)
+ {
+ if (cpustate->intr_pending == 1)
+ {
+ /* PSHR R7 */
+ cp1610_writemem16(cpustate->r[6],cpustate->r[7]);
+ cpustate->r[6]++;
+ cpustate->icount -= 9;
+ cpustate->intr_pending = 0;
+ cpustate->r[7] = cpustate->irq_callback(cpustate->device, CP1610_INT_INTR);
+ }
+ if ((cpustate->intrm_pending == 1) && (cpustate->intr_enabled))
+ {
+ /* PSHR R7 */
+ cp1610_writemem16(cpustate->r[6],cpustate->r[7]);
+ cpustate->r[6]++;
+ cpustate->icount -= 9;
+ cpustate->intrm_pending = 0;
+ cpustate->r[7] = cpustate->irq_callback(cpustate->device, CP1610_INT_INTRM);
+ }
+ if (cpustate->reset_pending == 1)
+ {
+ cpustate->reset_pending = 0;
+ cpustate->r[7] = cpustate->irq_callback(cpustate->device, CP1610_RESET);
+ }
+ }
+
+ } while( cpustate->icount > 0 );
+}
+
+static CPU_INIT( cp1610 )
+{
+ cp1610_state *cpustate = get_safe_token(device);
+ cpustate->intr_enabled = 0;
+ cpustate->reset_pending = 0;
+ cpustate->intr_pending = 0;
+ cpustate->intrm_pending = 0;
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+
+ device->save_item(NAME(cpustate->r));
+ device->save_item(NAME(cpustate->flags));
+ device->save_item(NAME(cpustate->intr_enabled));
+ device->save_item(NAME(cpustate->intr_vector));
+ device->save_item(NAME(cpustate->reset_state));
+ device->save_item(NAME(cpustate->intr_state));
+ device->save_item(NAME(cpustate->intrm_state));
+ device->save_item(NAME(cpustate->reset_pending));
+ device->save_item(NAME(cpustate->intr_pending));
+ device->save_item(NAME(cpustate->intrm_pending));
+ device->save_item(NAME(cpustate->mask_interrupts));
+}
+
+static void cp1610_set_irq_line(cp1610_state *cpustate, UINT32 irqline, int state)
+{
+ switch(irqline)
+ {
+ case CP1610_INT_INTRM:
+ cpustate->intrm_pending = (state == ASSERT_LINE);
+ cpustate->intrm_state = state;
+ break;
+ case CP1610_RESET:
+ if (state == ASSERT_LINE)
+ cpustate->reset_pending = 1;
+ cpustate->reset_state = state;
+ break;
+ case CP1610_INT_INTR:
+ if (state == ASSERT_LINE)
+ cpustate->intr_pending = 1;
+ cpustate->intr_state = state;
+ break;
+ }
+}
+
+static CPU_SET_INFO( cp1610 )
+{
+ cp1610_state *cpustate = get_safe_token(device);
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_PREVIOUSPC: break; /* TODO? */
+ case CPUINFO_INT_INPUT_STATE + CP1610_INT_INTRM:
+ case CPUINFO_INT_INPUT_STATE + CP1610_RESET:
+ case CPUINFO_INT_INPUT_STATE + CP1610_INT_INTR:
+ cp1610_set_irq_line(cpustate, state-CPUINFO_INT_INPUT_STATE, info->i); break;
+
+ case CPUINFO_INT_REGISTER + CP1610_R0: cpustate->r[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + CP1610_R1: cpustate->r[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + CP1610_R2: cpustate->r[2] = info->i; break;
+ case CPUINFO_INT_REGISTER + CP1610_R3: cpustate->r[3] = info->i; break;
+ case CPUINFO_INT_REGISTER + CP1610_R4: cpustate->r[4] = info->i; break;
+ case CPUINFO_INT_REGISTER + CP1610_R5: cpustate->r[5] = info->i; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + CP1610_R6: cpustate->r[6] = info->i; break;
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + CP1610_R7: cpustate->r[7] = info->i; break;
+ }
+ return;
+}
+
+CPU_GET_INFO( cp1610 )
+{
+ cp1610_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(cp1610_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 2; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 2; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 8; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 7; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = -1; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = 0; /* TODO??? */ break;
+
+ case CPUINFO_INT_INPUT_STATE + CP1610_INT_INTRM: info->i = cpustate->intrm_state; break;
+ case CPUINFO_INT_INPUT_STATE + CP1610_RESET: info->i = cpustate->reset_state; break;
+ case CPUINFO_INT_INPUT_STATE + CP1610_INT_INTR: info->i = cpustate->intr_state; break;
+
+ case CPUINFO_INT_REGISTER + CP1610_R0: info->i = cpustate->r[0]; break;
+ case CPUINFO_INT_REGISTER + CP1610_R1: info->i = cpustate->r[1]; break;
+ case CPUINFO_INT_REGISTER + CP1610_R2: info->i = cpustate->r[2]; break;
+ case CPUINFO_INT_REGISTER + CP1610_R3: info->i = cpustate->r[3]; break;
+ case CPUINFO_INT_REGISTER + CP1610_R4: info->i = cpustate->r[4]; break;
+ case CPUINFO_INT_REGISTER + CP1610_R5: info->i = cpustate->r[5]; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + CP1610_R6: info->i = cpustate->r[6]; break;
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + CP1610_R7: info->i = cpustate->r[7]; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(cp1610); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(cp1610); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(cp1610); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(cp1610); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(cp1610); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "CP1610"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, ""); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s,
+ "Copyright Frank Palazzolo, all rights reserved.");
+ break;
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c%c%c",
+ cpustate->flags & 0x80 ? 'S':'.',
+ cpustate->flags & 0x40 ? 'Z':'.',
+ cpustate->flags & 0x20 ? 'V':'.',
+ cpustate->flags & 0x10 ? 'C':'.');
+ break;
+ case CPUINFO_STR_REGISTER+CP1610_R0: sprintf(info->s, "R0:%04X", cpustate->r[0]); break;
+ case CPUINFO_STR_REGISTER+CP1610_R1: sprintf(info->s, "R1:%04X", cpustate->r[1]); break;
+ case CPUINFO_STR_REGISTER+CP1610_R2: sprintf(info->s, "R2:%04X", cpustate->r[2]); break;
+ case CPUINFO_STR_REGISTER+CP1610_R3: sprintf(info->s, "R3:%04X", cpustate->r[3]); break;
+ case CPUINFO_STR_REGISTER+CP1610_R4: sprintf(info->s, "R4:%04X", cpustate->r[4]); break;
+ case CPUINFO_STR_REGISTER+CP1610_R5: sprintf(info->s, "R5:%04X", cpustate->r[5]); break;
+ case CPUINFO_STR_REGISTER+CP1610_R6: sprintf(info->s, "R6:%04X", cpustate->r[6]); break;
+ case CPUINFO_STR_REGISTER+CP1610_R7: sprintf(info->s, "R7:%04X", cpustate->r[7]); break;
+ }
+
+ return;
+}
+
+DEFINE_LEGACY_CPU_DEVICE(CP1610, cp1610);
diff --git a/trunk/src/emu/cpu/cp1610/cp1610.h b/trunk/src/emu/cpu/cp1610/cp1610.h
new file mode 100644
index 00000000000..47246109cc8
--- /dev/null
+++ b/trunk/src/emu/cpu/cp1610/cp1610.h
@@ -0,0 +1,41 @@
+/*****************************************************************************
+ *
+ * cp1610.h
+ * Portable General Instruments CP1610 emulator interface
+ *
+ * Copyright Frank Palazzolo, all rights reserved.
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * palazzol@comcast.net
+ * - This entire notice must remain in the source code.
+ *
+ *****************************************************************************/
+
+#pragma once
+
+#ifndef __CP1610_H__
+#define __CP1610_H__
+
+enum
+{
+ CP1610_R0=1, CP1610_R1, CP1610_R2, CP1610_R3,
+ CP1610_R4, CP1610_R5, CP1610_R6, CP1610_R7
+};
+
+#define CP1610_INT_NONE 0
+#define CP1610_INT_INTRM 1 /* Maskable */
+#define CP1610_RESET INPUT_LINE_RESET /* Non-Maskable */
+#define CP1610_INT_INTR INPUT_LINE_NMI /* Non-Maskable */
+
+
+DECLARE_LEGACY_CPU_DEVICE(CP1610, cp1610);
+
+CPU_DISASSEMBLE( cp1610 );
+
+#endif /* __CP1610_H__ */
diff --git a/trunk/src/emu/cpu/cpu.mak b/trunk/src/emu/cpu/cpu.mak
new file mode 100644
index 00000000000..52c655aff12
--- /dev/null
+++ b/trunk/src/emu/cpu/cpu.mak
@@ -0,0 +1,1865 @@
+###########################################################################
+#
+# cpu.mak
+#
+# Rules for building CPU cores
+#
+# Copyright Nicola Salmoria and the MAME Team.
+# Visit http://mamedev.org for licensing and usage restrictions.
+#
+###########################################################################
+
+
+CPUSRC = $(EMUSRC)/cpu
+CPUOBJ = $(EMUOBJ)/cpu
+
+
+#-------------------------------------------------
+# Shared code
+#-------------------------------------------------
+
+OBJDIRS += $(CPUOBJ)
+CPUOBJS += $(CPUOBJ)/vtlb.o
+
+
+
+#-------------------------------------------------
+# Dynamic recompiler objects
+#-------------------------------------------------
+
+DRCOBJ = \
+ $(CPUOBJ)/drcbec.o \
+ $(CPUOBJ)/drcbeut.o \
+ $(CPUOBJ)/drccache.o \
+ $(CPUOBJ)/drcfe.o \
+ $(CPUOBJ)/drcuml.o \
+ $(CPUOBJ)/uml.o \
+ $(CPUOBJ)/i386/i386dasm.o \
+ $(CPUOBJ)/x86log.o \
+ $(CPUOBJ)/drcbex86.o \
+ $(CPUOBJ)/drcbex64.o \
+
+DRCDEPS = \
+ $(CPUSRC)/drcbec.h \
+ $(CPUSRC)/drcbeut.h \
+ $(CPUSRC)/drccache.h \
+ $(CPUSRC)/drcfe.h \
+ $(CPUSRC)/drcuml.h \
+ $(CPUSRC)/drcumlsh.h \
+ $(CPUSRC)/uml.h \
+ $(CPUSRC)/drcbex86.h \
+ $(CPUSRC)/drcbex64.h \
+ $(CPUSRC)/x86emit.h \
+
+# fixme - need to make this work for other target architectures (PPC)
+
+ifndef FORCE_DRC_C_BACKEND
+ifeq ($(PTR64),1)
+DEFS += -DNATIVE_DRC=drcbe_x64
+else
+DEFS += -DNATIVE_DRC=drcbe_x86
+endif
+endif
+
+
+$(DRCOBJ): $(DRCDEPS)
+
+
+
+#-------------------------------------------------
+# Acorn ARM series
+#-------------------------------------------------
+
+ifneq ($(filter ARM,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/arm
+CPUOBJS += $(CPUOBJ)/arm/arm.o
+DASMOBJS += $(CPUOBJ)/arm/armdasm.o
+endif
+
+ifneq ($(filter ARM7,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/arm7
+CPUOBJS += $(CPUOBJ)/arm7/arm7.o
+DASMOBJS += $(CPUOBJ)/arm7/arm7dasm.o
+endif
+
+$(CPUOBJ)/arm/arm.o: $(CPUSRC)/arm/arm.c \
+ $(CPUSRC)/arm/arm.h
+
+$(CPUOBJ)/arm7/arm7.o: $(CPUSRC)/arm7/arm7.c \
+ $(CPUSRC)/arm7/arm7.h \
+ $(CPUSRC)/arm7/arm7exec.c \
+ $(CPUSRC)/arm7/arm7core.c
+
+
+
+#-------------------------------------------------
+# Advanced Digital Chips SE3208
+#-------------------------------------------------
+
+ifneq ($(filter SE3208,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/se3208
+CPUOBJS += $(CPUOBJ)/se3208/se3208.o
+DASMOBJS += $(CPUOBJ)/se3208/se3208dis.o
+endif
+
+$(CPUOBJ)/se3208/se3208.o: $(CPUSRC)/se3208/se3208.c \
+ $(CPUSRC)/se3208/se3208.h
+
+
+
+#-------------------------------------------------
+# Alpha 8201
+#-------------------------------------------------
+
+ifneq ($(filter ALPHA8201,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/alph8201
+CPUOBJS += $(CPUOBJ)/alph8201/alph8201.o
+DASMOBJS += $(CPUOBJ)/alph8201/8201dasm.o
+endif
+
+$(CPUOBJ)/alph8201/alph8201.o: $(CPUSRC)/alph8201/alph8201.c \
+ $(CPUSRC)/alph8201/alph8201.h
+
+
+
+#-------------------------------------------------
+# Analog Devices ADSP21xx series
+#-------------------------------------------------
+
+ifneq ($(filter ADSP21XX,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/adsp2100
+CPUOBJS += $(CPUOBJ)/adsp2100/adsp2100.o
+DASMOBJS += $(CPUOBJ)/adsp2100/2100dasm.o
+endif
+
+$(CPUOBJ)/adsp2100/adsp2100.o: $(CPUSRC)/adsp2100/adsp2100.c \
+ $(CPUSRC)/adsp2100/adsp2100.h \
+ $(CPUSRC)/adsp2100/2100ops.c
+
+
+
+#-------------------------------------------------
+# Analog Devices "Sharc" ADSP21062
+#-------------------------------------------------
+
+ifneq ($(filter ADSP21062,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/sharc
+CPUOBJS += $(CPUOBJ)/sharc/sharc.o
+DASMOBJS += $(CPUOBJ)/sharc/sharcdsm.o
+endif
+
+$(CPUOBJ)/sharc/sharc.o: $(CPUSRC)/sharc/sharc.c \
+ $(CPUSRC)/sharc/sharc.h \
+ $(CPUSRC)/sharc/sharcops.c \
+ $(CPUSRC)/sharc/sharcops.h \
+ $(CPUSRC)/sharc/sharcdsm.c \
+ $(CPUSRC)/sharc/sharcdsm.h \
+ $(CPUSRC)/sharc/compute.c \
+ $(CPUSRC)/sharc/sharcdma.c \
+ $(CPUSRC)/sharc/sharcmem.c
+
+
+
+#-------------------------------------------------
+# APEXC
+#-------------------------------------------------
+
+ifneq ($(filter APEXC,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/apexc
+CPUOBJS += $(CPUOBJ)/apexc/apexc.o
+DASMOBJS += $(CPUOBJ)/apexc/apexcdsm.o
+endif
+
+$(CPUOBJ)/apexc/apexc.o: $(CPUSRC)/apexc/apexc.c \
+ $(CPUSRC)/apexc/apexc.h
+
+
+
+#-------------------------------------------------
+# AT&T DSP16A
+#-------------------------------------------------
+
+ifneq ($(filter DSP16A,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/dsp16
+CPUOBJS += $(CPUOBJ)/dsp16/dsp16.o
+DASMOBJS += $(CPUOBJ)/dsp16/dsp16dis.o
+endif
+
+$(CPUOBJ)/dsp16/dsp16.o: $(CPUSRC)/dsp16/dsp16.c \
+ $(CPUSRC)/dsp16/dsp16.h
+
+
+#-------------------------------------------------
+# AT&T DSP32C
+#-------------------------------------------------
+
+ifneq ($(filter DSP32C,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/dsp32
+CPUOBJS += $(CPUOBJ)/dsp32/dsp32.o
+DASMOBJS += $(CPUOBJ)/dsp32/dsp32dis.o
+endif
+
+$(CPUOBJ)/dsp32/dsp32.o: $(CPUSRC)/dsp32/dsp32.c \
+ $(CPUSRC)/dsp32/dsp32.h \
+ $(CPUSRC)/dsp32/dsp32ops.c
+
+
+
+#-------------------------------------------------
+# Atari custom RISC processor
+#-------------------------------------------------
+
+ifneq ($(filter ASAP,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/asap
+CPUOBJS += $(CPUOBJ)/asap/asap.o
+DASMOBJS += $(CPUOBJ)/asap/asapdasm.o
+endif
+
+$(CPUOBJ)/asap/asap.o: $(CPUSRC)/asap/asap.c \
+ $(CPUSRC)/asap/asap.h
+
+
+
+#-------------------------------------------------
+# AMD Am29000
+#-------------------------------------------------
+
+ifneq ($(filter AM29000,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/am29000
+CPUOBJS += $(CPUOBJ)/am29000/am29000.o
+DASMOBJS += $(CPUOBJ)/am29000/am29dasm.o
+endif
+
+$(CPUOBJ)/am29000/am29000.o: $(CPUSRC)/am29000/am29000.c \
+ $(CPUSRC)/am29000/am29000.h \
+ $(CPUSRC)/am29000/am29ops.h \
+
+
+
+#-------------------------------------------------
+# Atari Jaguar custom DSPs
+#-------------------------------------------------
+
+ifneq ($(filter JAGUAR,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/jaguar
+CPUOBJS += $(CPUOBJ)/jaguar/jaguar.o
+DASMOBJS += $(CPUOBJ)/jaguar/jagdasm.o
+endif
+
+$(CPUOBJ)/jaguar/jaguar.o: $(CPUSRC)/jaguar/jaguar.c \
+ $(CPUSRC)/jaguar/jaguar.h
+
+
+
+#-------------------------------------------------
+# Simutrek Cube Quest bit-sliced CPUs
+#-------------------------------------------------
+
+ifneq ($(filter CUBEQCPU,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/cubeqcpu
+CPUOBJS += $(CPUOBJ)/cubeqcpu/cubeqcpu.o
+DASMOBJS += $(CPUOBJ)/cubeqcpu/cubedasm.o
+endif
+
+$(CPUOBJ)/cubeqcpu/cubeqcpu.o: $(CPUSRC)/cubeqcpu/cubeqcpu.c \
+ $(CPUSRC)/cubeqcpu/cubeqcpu.h
+
+
+
+#-------------------------------------------------
+# Entertainment Sciences AM29116-based RIP
+#-------------------------------------------------
+
+ifneq ($(filter ESRIP,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/esrip
+CPUOBJS += $(CPUOBJ)/esrip/esrip.o
+DASMOBJS += $(CPUOBJ)/esrip/esripdsm.o
+endif
+
+$(CPUOBJ)/esrip/esrip.o: $(CPUSRC)/esrip/esrip.c \
+ $(CPUSRC)/esrip/esrip.h
+
+
+
+#-------------------------------------------------
+# RCA COSMAC
+#-------------------------------------------------
+
+ifneq ($(filter COSMAC,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/cosmac
+CPUOBJS += $(CPUOBJ)/cosmac/cosmac.o
+DASMOBJS += $(CPUOBJ)/cosmac/cosdasm.o
+endif
+
+$(CPUOBJ)/cosmac/cosmac.o: $(CPUSRC)/cosmac/cosmac.c \
+ $(CPUSRC)/cosmac/cosmac.h
+
+
+
+#-------------------------------------------------
+# National Semiconductor COP400 family
+#-------------------------------------------------
+
+ifneq ($(filter COP400,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/cop400
+CPUOBJS += $(CPUOBJ)/cop400/cop400.o
+DASMOBJS += $(CPUOBJ)/cop400/cop410ds.o
+DASMOBJS += $(CPUOBJ)/cop400/cop420ds.o
+DASMOBJS += $(CPUOBJ)/cop400/cop440ds.o
+endif
+
+$(CPUOBJ)/cop400/cop400.o: $(CPUSRC)/cop400/cop400.c \
+ $(CPUSRC)/cop400/cop400.h \
+ $(CPUSRC)/cop400/cop400op.c
+
+
+
+#-------------------------------------------------
+# CP1610
+#-------------------------------------------------
+
+ifneq ($(filter CP1610,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/cp1610
+CPUOBJS += $(CPUOBJ)/cp1610/cp1610.o
+DASMOBJS += $(CPUOBJ)/cp1610/1610dasm.o
+endif
+
+$(CPUOBJ)/cp1610/cp1610.o: $(CPUSRC)/cp1610/cp1610.c \
+ $(CPUSRC)/cp1610/cp1610.h
+
+
+
+#-------------------------------------------------
+# Cinematronics vector "CPU"
+#-------------------------------------------------
+
+ifneq ($(filter CCPU,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/ccpu
+CPUOBJS += $(CPUOBJ)/ccpu/ccpu.o
+DASMOBJS += $(CPUOBJ)/ccpu/ccpudasm.o
+endif
+
+$(CPUOBJ)/ccpu/ccpu.o: $(CPUSRC)/ccpu/ccpu.c \
+ $(CPUSRC)/ccpu/ccpu.h
+
+
+
+#-------------------------------------------------
+# DEC T-11
+#-------------------------------------------------
+
+ifneq ($(filter T11,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/t11
+CPUOBJS += $(CPUOBJ)/t11/t11.o
+DASMOBJS += $(CPUOBJ)/t11/t11dasm.o
+endif
+
+$(CPUOBJ)/t11/t11.o: $(CPUSRC)/t11/t11.c \
+ $(CPUSRC)/t11/t11.h \
+ $(CPUSRC)/t11/t11ops.c \
+ $(CPUSRC)/t11/t11table.c
+
+
+
+#-------------------------------------------------
+# F8
+#-------------------------------------------------
+
+ifneq ($(filter F8,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/f8
+CPUOBJS += $(CPUOBJ)/f8/f8.o
+DASMOBJS += $(CPUOBJ)/f8/f8dasm.o
+endif
+
+$(CPUOBJ)/f8/f8.o: $(CPUSRC)/f8/f8.c \
+ $(CPUSRC)/f8/f8.h
+
+
+
+#-------------------------------------------------
+# G65816
+#-------------------------------------------------
+
+ifneq ($(filter G65816,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/g65816
+CPUOBJS += \
+ $(CPUOBJ)/g65816/g65816.o \
+ $(CPUOBJ)/g65816/g65816o0.o \
+ $(CPUOBJ)/g65816/g65816o1.o \
+ $(CPUOBJ)/g65816/g65816o2.o \
+ $(CPUOBJ)/g65816/g65816o3.o \
+ $(CPUOBJ)/g65816/g65816o4.o
+DASMOBJS += $(CPUOBJ)/g65816/g65816ds.o
+endif
+
+G65816DEPS = \
+ $(CPUSRC)/g65816/g65816.h \
+ $(CPUSRC)/g65816/g65816cm.h \
+ $(CPUSRC)/g65816/g65816op.h
+
+$(CPUOBJ)/g65816/g65816.o: $(CPUSRC)/g65816/g65816.c \
+ $(G65816DEPS)
+
+$(CPUOBJ)/g65816/g65816o0.o: $(CPUSRC)/g65816/g65816o0.c \
+ $(G65816DEPS)
+
+$(CPUOBJ)/g65816/g65816o1.o: $(CPUSRC)/g65816/g65816o1.c \
+ $(G65816DEPS)
+
+$(CPUOBJ)/g65816/g65816o2.o: $(CPUSRC)/g65816/g65816o2.c \
+ $(G65816DEPS)
+
+$(CPUOBJ)/g65816/g65816o3.o: $(CPUSRC)/g65816/g65816o3.c \
+ $(G65816DEPS)
+
+$(CPUOBJ)/g65816/g65816o4.o: $(CPUSRC)/g65816/g65816o4.c \
+ $(G65816DEPS)
+
+
+
+#-------------------------------------------------
+# Hitachi 6309
+#-------------------------------------------------
+
+ifneq ($(filter HD6309,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/hd6309
+CPUOBJS += $(CPUOBJ)/hd6309/hd6309.o
+DASMOBJS += $(CPUOBJ)/hd6309/6309dasm.o
+endif
+
+$(CPUOBJ)/hd6309/hd6309.o: $(CPUSRC)/hd6309/hd6309.c \
+ $(CPUSRC)/hd6309/hd6309.h \
+ $(CPUSRC)/hd6309/6309ops.c \
+ $(CPUSRC)/hd6309/6309tbl.c
+
+
+#-------------------------------------------------
+# Hitachi H8/30xx (16/32-bit H8/3xx series)
+#-------------------------------------------------
+
+ifneq ($(filter H83002,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/h83002
+CPUOBJS += $(CPUOBJ)/h83002/h8_16.o $(CPUOBJ)/h83002/h8periph.o $(CPUOBJ)/h83002/h8speriph.o
+DASMOBJS += $(CPUOBJ)/h83002/h8disasm.o
+endif
+
+$(CPUOBJ)/h83002/h8_16.o: $(CPUSRC)/h83002/h8_16.c \
+ $(CPUSRC)/h83002/h8.h \
+ $(CPUSRC)/h83002/h8ops.h \
+ $(CPUSRC)/h83002/h8priv.h
+
+$(CPUOBJ)/h83002/h8disasm.o: $(CPUSRC)/h83002/h8disasm.c
+
+$(CPUOBJ)/h83002/h8periph.o: $(CPUSRC)/h83002/h8periph.c \
+ $(CPUSRC)/h83002/h8priv.h \
+ $(CPUSRC)/h83002/h8.h
+
+$(CPUOBJ)/h83002/h8speriph.o: $(CPUSRC)/h83002/h8speriph.c \
+ $(CPUSRC)/h83002/h8priv.h \
+ $(CPUSRC)/h83002/h8.h
+
+
+#-------------------------------------------------
+# Hitachi H8/3334 (8/16-bit H8/3xx series)
+#-------------------------------------------------
+
+ifneq ($(filter H83334,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/h83002
+CPUOBJS += $(CPUOBJ)/h83002/h8_8.o $(CPUOBJ)/h83002/h8periph.o $(CPUOBJ)/h83002/h8speriph.o
+DASMOBJS += $(CPUOBJ)/h83002/h8disasm.o
+endif
+
+$(CPUOBJ)/h83002/h8_8.o: $(CPUSRC)/h83002/h8_8.c \
+ $(CPUSRC)/h83002/h8.h \
+ $(CPUSRC)/h83002/h8ops.h \
+ $(CPUSRC)/h83002/h8priv.h
+
+$(CPUOBJ)/h83002/h8disasm.o: $(CPUSRC)/h83002/h8disasm.c
+
+$(CPUOBJ)/h83002/h8periph.o: $(CPUSRC)/h83002/h8periph.c \
+ $(CPUSRC)/h83002/h8priv.h \
+ $(CPUSRC)/h83002/h8.h
+
+$(CPUOBJ)/h83002/h8speriph.o: $(CPUSRC)/h83002/h8speriph.c \
+ $(CPUSRC)/h83002/h8priv.h \
+ $(CPUSRC)/h83002/h8.h
+
+#-------------------------------------------------
+# Hitachi HCD62121
+#-------------------------------------------------
+
+ifneq ($(filter HCD62121,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/hcd62121
+CPUOBJS += $(CPUOBJ)/hcd62121/hcd62121.o
+DASMOBJS += $(CPUOBJ)/hcd62121/hcd62121d.o
+endif
+
+$(CPUOBJ)/hcd62121/hcd62121.o: $(CPUSRC)/hcd62121/hcd62121.c \
+ $(CPUSRC)/hcd62121/hcd62121.h \
+ $(CPUSRC)/hcd62121/hcd62121_ops.h
+
+
+#-------------------------------------------------
+# Hitachi SH1/SH2
+#-------------------------------------------------
+
+ifneq ($(filter SH2,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/sh2
+CPUOBJS += $(CPUOBJ)/sh2/sh2.o $(CPUOBJ)/sh2/sh2comn.o $(CPUOBJ)/sh2/sh2drc.o $(CPUOBJ)/sh2/sh2fe.o $(DRCOBJ)
+DASMOBJS += $(CPUOBJ)/sh2/sh2dasm.o
+endif
+
+$(CPUOBJ)/sh2/sh2.o: $(CPUSRC)/sh2/sh2.c \
+ $(CPUSRC)/sh2/sh2.h \
+ $(CPUSRC)/sh2/sh2comn.h
+
+$(CPUOBJ)/sh2/sh2comn.o: $(CPUSRC)/sh2/sh2comn.c \
+ $(CPUSRC)/sh2/sh2comn.h \
+ $(CPUSRC)/sh2/sh2.h
+
+$(CPUOBJ)/sh2/sh2drc.o: $(CPUSRC)/sh2/sh2drc.c \
+ $(CPUSRC)/sh2/sh2.h \
+ $(CPUSRC)/sh2/sh2comn.h \
+ $(DRCDEPS)
+
+$(CPUOBJ)/sh2/sh2fe.o: $(CPUSRC)/sh2/sh2fe.c \
+ $(CPUSRC)/sh2/sh2.h \
+ $(CPUSRC)/sh2/sh2comn.h
+
+#-------------------------------------------------
+# Hitachi SH4
+#-------------------------------------------------
+
+ifneq ($(filter SH4,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/sh4
+CPUOBJS += $(CPUOBJ)/sh4/sh4.o $(CPUOBJ)/sh4/sh4comn.o
+DASMOBJS += $(CPUOBJ)/sh4/sh4dasm.o
+endif
+
+$(CPUOBJ)/sh4/sh4.o: $(CPUSRC)/sh4/sh4.c \
+ $(CPUSRC)/sh4/sh4.h \
+ $(CPUSRC)/sh4/sh4regs.h \
+ $(CPUSRC)/sh4/sh4comn.h
+
+$(CPUOBJ)/sh4/sh4comn.o: $(CPUSRC)/sh4/sh4comn.c \
+ $(CPUSRC)/sh4/sh4comn.h \
+ $(CPUSRC)/sh4/sh4regs.h \
+ $(CPUSRC)/sh4/sh4.h
+
+#-------------------------------------------------
+# Hudsonsoft 6280
+#-------------------------------------------------
+
+ifneq ($(filter H6280,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/h6280
+CPUOBJS += $(CPUOBJ)/h6280/h6280.o
+DASMOBJS += $(CPUOBJ)/h6280/6280dasm.o
+endif
+
+$(CPUOBJ)/h6280/h6280.o: $(CPUSRC)/h6280/h6280.c \
+ $(CPUSRC)/h6280/h6280.h \
+ $(CPUSRC)/h6280/h6280ops.h \
+ $(CPUSRC)/h6280/tblh6280.c
+
+
+
+#-------------------------------------------------
+# Hyperstone E1 series
+#-------------------------------------------------
+
+ifneq ($(filter E1,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/e132xs
+CPUOBJS += $(CPUOBJ)/e132xs/e132xs.o
+DASMOBJS += $(CPUOBJ)/e132xs/32xsdasm.o
+endif
+
+$(CPUOBJ)/e132xs/e132xs.o: $(CPUSRC)/e132xs/e132xs.c \
+ $(CPUSRC)/e132xs/e132xs.h \
+ $(CPUSRC)/e132xs/e132xsop.c
+
+
+
+#-------------------------------------------------
+# Intel 4004
+#-------------------------------------------------
+
+ifneq ($(filter I4004,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/i4004
+CPUOBJS += $(CPUOBJ)/i4004/i4004.o
+DASMOBJS += $(CPUOBJ)/i4004/4004dasm.o
+endif
+
+$(CPUOBJ)/i4004/i4004.o: $(CPUSRC)/i4004/i4004.c \
+ $(CPUSRC)/i4004/i4004.h
+
+
+#-------------------------------------------------
+# Intel 8008
+#-------------------------------------------------
+
+ifneq ($(filter I8008,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/i8008
+CPUOBJS += $(CPUOBJ)/i8008/i8008.o
+DASMOBJS += $(CPUOBJ)/i8008/8008dasm.o
+endif
+
+$(CPUOBJ)/i8008/i8008.o: $(CPUSRC)/i8008/i8008.c \
+ $(CPUSRC)/i8008/i8008.h
+
+#-------------------------------------------------
+# National Semiconductor SC/MP
+#-------------------------------------------------
+
+ifneq ($(filter SCMP,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/scmp
+CPUOBJS += $(CPUOBJ)/scmp/scmp.o
+DASMOBJS += $(CPUOBJ)/scmp/scmpdasm.o
+endif
+
+$(CPUOBJ)/scmp/scmp.o: $(CPUSRC)/scmp/scmp.c \
+ $(CPUSRC)/scmp/scmp.h
+
+
+#-------------------------------------------------
+# Intel 8080/8085A
+#-------------------------------------------------
+
+ifneq ($(filter I8085,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/i8085
+CPUOBJS += $(CPUOBJ)/i8085/i8085.o
+DASMOBJS += $(CPUOBJ)/i8085/8085dasm.o
+endif
+
+$(CPUOBJ)/i8085/i8085.o: $(CPUSRC)/i8085/i8085.c \
+ $(CPUSRC)/i8085/i8085.h \
+ $(CPUSRC)/i8085/i8085cpu.h
+
+
+
+#-------------------------------------------------
+# Intel MCS-48 (8039 and derivatives)
+#-------------------------------------------------
+
+ifneq ($(filter MCS48,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/mcs48
+CPUOBJS += $(CPUOBJ)/mcs48/mcs48.o
+DASMOBJS += $(CPUOBJ)/mcs48/mcs48dsm.o
+endif
+
+$(CPUOBJ)/mcs48/mcs48.o: $(CPUSRC)/mcs48/mcs48.c \
+ $(CPUSRC)/mcs48/mcs48.h
+
+
+
+#-------------------------------------------------
+# Intel 8051 and derivatives
+#-------------------------------------------------
+
+ifneq ($(filter MCS51,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/mcs51
+CPUOBJS += $(CPUOBJ)/mcs51/mcs51.o
+DASMOBJS += $(CPUOBJ)/mcs51/mcs51dasm.o
+endif
+
+$(CPUOBJ)/mcs51/mcs51.o: $(CPUSRC)/mcs51/mcs51.c \
+ $(CPUSRC)/mcs51/mcs51.h \
+ $(CPUSRC)/mcs51/mcs51ops.c
+
+#-------------------------------------------------
+# Intel 80x86 series
+#-------------------------------------------------
+
+ifneq ($(filter I86,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/i86 $(CPUOBJ)/i386
+CPUOBJS += $(CPUOBJ)/i86/i86.o
+CPUOBJS += $(CPUOBJ)/i86/i286.o
+DASMOBJS += $(CPUOBJ)/i386/i386dasm.o
+endif
+
+ifneq ($(filter I386,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/i386
+CPUOBJS += $(CPUOBJ)/i386/i386.o
+DASMOBJS += $(CPUOBJ)/i386/i386dasm.o
+endif
+
+I86DEPS = \
+ $(CPUSRC)/i86/i86priv.h \
+ $(CPUSRC)/i86/ea.h \
+ $(CPUSRC)/i86/host.h \
+ $(CPUSRC)/i86/modrm.h
+
+$(CPUOBJ)/i86/i86.o: $(CPUSRC)/i86/i86.c \
+ $(CPUSRC)/i86/i86.h \
+ $(CPUSRC)/i86/i86time.c \
+ $(CPUSRC)/i86/instr86.c \
+ $(CPUSRC)/i86/instr186.c \
+ $(I86DEPS)
+
+$(CPUOBJ)/i86/i286.o: $(CPUSRC)/i86/i286.c \
+ $(CPUSRC)/i86/i286.h \
+ $(CPUSRC)/i86/i86time.c \
+ $(CPUSRC)/i86/instr86.c \
+ $(CPUSRC)/i86/instr186.c \
+ $(CPUSRC)/i86/instr286.c \
+ $(CPUSRC)/i86/modrm286.h \
+ $(I86DEPS)
+
+$(CPUOBJ)/i386/i386.o: $(CPUSRC)/i386/i386.c \
+ $(CPUSRC)/i386/i386.h \
+ $(CPUSRC)/i386/i386priv.h \
+ $(CPUSRC)/i386/i386op16.c \
+ $(CPUSRC)/i386/i386op32.c \
+ $(CPUSRC)/i386/i386ops.c \
+ $(CPUSRC)/i386/i486ops.c \
+ $(CPUSRC)/i386/pentops.c \
+ $(CPUSRC)/i386/x87ops.c \
+ $(CPUSRC)/i386/i386ops.h \
+ $(CPUSRC)/i386/cycles.h
+
+
+
+#-------------------------------------------------
+# Intel i860
+#-------------------------------------------------
+
+ifneq ($(filter I860,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/i860
+CPUOBJS += $(CPUOBJ)/i860/i860.o
+DASMOBJS += $(CPUOBJ)/i860/i860dis.o
+endif
+
+$(CPUOBJ)/i860/i860.o: $(CPUSRC)/i860/i860.c \
+ $(CPUSRC)/i860/i860.h \
+ $(CPUSRC)/i860/i860dec.c
+
+#-------------------------------------------------
+# Intel i960
+#-------------------------------------------------
+
+ifneq ($(filter I960,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/i960
+CPUOBJS += $(CPUOBJ)/i960/i960.o
+DASMOBJS += $(CPUOBJ)/i960/i960dis.o
+endif
+
+$(CPUOBJ)/i960/i960.o: $(CPUSRC)/i960/i960.c \
+ $(CPUSRC)/i960/i960.h
+
+
+
+#-------------------------------------------------
+# Konami custom CPU (6809-based)
+#-------------------------------------------------
+
+ifneq ($(filter KONAMI,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/konami
+CPUOBJS += $(CPUOBJ)/konami/konami.o
+DASMOBJS += $(CPUOBJ)/konami/knmidasm.o
+endif
+
+$(CPUOBJ)/konami/konami.o: $(CPUSRC)/konami/konami.c \
+ $(CPUSRC)/konami/konami.h \
+ $(CPUSRC)/konami/konamops.c \
+ $(CPUSRC)/konami/konamtbl.c
+
+
+
+#-------------------------------------------------
+# LH5801
+#-------------------------------------------------
+
+ifneq ($(filter LH5801,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/lh5801
+CPUOBJS += $(CPUOBJ)/lh5801/lh5801.o
+DASMOBJS += $(CPUOBJ)/lh5801/5801dasm.o
+endif
+
+$(CPUOBJ)/lh5801/lh5801.o: $(CPUSRC)/lh5801/lh5801.c \
+ $(CPUSRC)/lh5801/5801tbl.c \
+ $(CPUSRC)/lh5801/lh5801.h
+
+
+
+#-------------------------------------------------
+# Manchester Small-Scale Experimental Machine
+#-------------------------------------------------
+
+ifneq ($(filter SSEM,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/ssem
+CPUOBJS += $(CPUOBJ)/ssem/ssem.o
+DASMOBJS += $(CPUOBJ)/ssem/ssemdasm.o
+endif
+
+$(CPUOBJ)/ssem/ssem.o: $(CPUSRC)/ssem/ssem.c \
+ $(CPUSRC)/ssem/ssem.h
+
+
+
+#-------------------------------------------------
+# Fujitsu MB88xx
+#-------------------------------------------------
+
+ifneq ($(filter MB88XX,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/mb88xx
+CPUOBJS += $(CPUOBJ)/mb88xx/mb88xx.o
+DASMOBJS += $(CPUOBJ)/mb88xx/mb88dasm.o
+endif
+
+$(CPUOBJ)/mb88xx/mb88xx.o: $(CPUSRC)/mb88xx/mb88xx.c \
+ $(CPUSRC)/mb88xx/mb88xx.h
+
+
+
+#-------------------------------------------------
+# Fujitsu MB86233
+#-------------------------------------------------
+
+ifneq ($(filter MB86233,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/mb86233
+CPUOBJS += $(CPUOBJ)/mb86233/mb86233.o
+DASMOBJS += $(CPUOBJ)/mb86233/mb86233d.o
+endif
+
+$(CPUOBJ)/mb86233/mb86233.o: $(CPUSRC)/mb86233/mb86233.c \
+ $(CPUSRC)/mb86233/mb86233.h
+
+
+
+#-------------------------------------------------
+# Microchip PIC16C5x
+#-------------------------------------------------
+
+ifneq ($(filter PIC16C5X,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/pic16c5x
+CPUOBJS += $(CPUOBJ)/pic16c5x/pic16c5x.o
+DASMOBJS += $(CPUOBJ)/pic16c5x/16c5xdsm.o
+endif
+
+$(CPUOBJ)/pic16c5x/pic16c5x.o: $(CPUSRC)/pic16c5x/pic16c5x.c \
+ $(CPUSRC)/pic16c5x/pic16c5x.h
+
+
+
+#-------------------------------------------------
+# Microchip PIC16C62x
+#-------------------------------------------------
+
+ifneq ($(filter PIC16C62X,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/pic16c62x
+CPUOBJS += $(CPUOBJ)/pic16c62x/pic16c62x.o
+DASMOBJS += $(CPUOBJ)/pic16c62x/16c62xdsm.o
+endif
+
+$(CPUOBJ)/pic16c62x/pic16c62x.o: $(CPUSRC)/pic16c62x/pic16c62x.c \
+ $(CPUSRC)/pic16c62x/pic16c62x.h
+
+
+
+#-------------------------------------------------
+# MIPS R3000 (MIPS I/II) series
+# MIPS R4000 (MIPS III/IV) series
+#-------------------------------------------------
+
+ifneq ($(filter MIPS,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/mips
+CPUOBJS += $(CPUOBJ)/mips/r3000.o
+CPUOBJS += $(CPUOBJ)/mips/mips3com.o $(CPUOBJ)/mips/mips3.o $(CPUOBJ)/mips/mips3fe.o $(CPUOBJ)/mips/mips3drc.o $(DRCOBJ)
+DASMOBJS += $(CPUOBJ)/mips/r3kdasm.o
+DASMOBJS += $(CPUOBJ)/mips/mips3dsm.o
+endif
+
+$(CPUOBJ)/mips/r3000.o: $(CPUSRC)/mips/r3000.c \
+ $(CPUSRC)/mips/r3000.h
+
+$(CPUOBJ)/mips/mips3.o: $(CPUSRC)/mips/mips3.h $(CPUSRC)/mips/mips3com.h \
+ $(CPUSRC)/mips/mips3.c
+
+$(CPUOBJ)/mips/mips3com.o: $(CPUSRC)/mips/mips3.h \
+ $(CPUSRC)/mips/mips3com.h
+
+$(CPUOBJ)/mips/mips3fe.o: $(CPUSRC)/mips/mips3.h \
+ $(CPUSRC)/mips/mips3com.h \
+ $(CPUSRC)/mips/mips3fe.h
+
+$(CPUOBJ)/mips/mips3drc.o: $(CPUSRC)/mips/mips3drc.c \
+ $(CPUSRC)/mips/mips3.h \
+ $(CPUSRC)/mips/mips3com.h \
+ $(CPUSRC)/mips/mips3fe.h \
+ $(DRCDEPS)
+
+
+
+#-------------------------------------------------
+# Sony PlayStation CPU (R3000-based + GTE)
+#-------------------------------------------------
+
+ifneq ($(filter PSX,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/psx
+CPUOBJS += $(CPUOBJ)/psx/psx.o $(CPUOBJ)/psx/gte.o $(CPUOBJ)/psx/dma.o $(CPUOBJ)/psx/irq.o $(CPUOBJ)/psx/mdec.o $(CPUOBJ)/psx/rcnt.o $(CPUOBJ)/psx/sio.o
+DASMOBJS += $(CPUOBJ)/psx/psxdasm.o
+endif
+
+$(CPUOBJ)/psx/psx.o: $(CPUSRC)/psx/psx.c \
+ $(CPUSRC)/psx/psx.h \
+ $(CPUSRC)/psx/dma.h \
+ $(CPUSRC)/psx/gte.h \
+ $(CPUSRC)/psx/mdec.h \
+ $(CPUSRC)/psx/rcnt.h \
+ $(CPUSRC)/psx/sio.h
+
+$(CPUOBJ)/psx/dma.o: $(CPUSRC)/psx/dma.c \
+ $(CPUSRC)/psx/dma.h
+
+$(CPUOBJ)/psx/gte.o: $(CPUSRC)/psx/gte.c \
+ $(CPUSRC)/psx/gte.h
+
+$(CPUOBJ)/psx/mdec.o: $(CPUSRC)/psx/mdec.c \
+ $(CPUSRC)/psx/dma.h \
+ $(CPUSRC)/psx/mdec.h
+
+$(CPUOBJ)/psx/sio.o: $(CPUSRC)/psx/sio.c \
+ $(CPUSRC)/psx/sio.h
+
+
+#-------------------------------------------------
+# Mitsubishi M37702 and M37710 (based on 65C816)
+#-------------------------------------------------
+
+ifneq ($(filter M37710,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/m37710
+CPUOBJS += \
+ $(CPUOBJ)/m37710/m37710.o \
+ $(CPUOBJ)/m37710/m37710o0.o \
+ $(CPUOBJ)/m37710/m37710o1.o \
+ $(CPUOBJ)/m37710/m37710o2.o \
+ $(CPUOBJ)/m37710/m37710o3.o
+DASMOBJS += $(CPUOBJ)/m37710/m7700ds.o
+endif
+
+M37710DEPS = \
+ $(CPUSRC)/m37710/m37710.h \
+ $(CPUSRC)/m37710/m37710op.h \
+ $(CPUSRC)/m37710/m7700ds.h
+
+$(CPUOBJ)/m37710/m37710.o: $(CPUSRC)/m37710/m37710.c \
+ $(M37710DEPS)
+
+$(CPUOBJ)/m37710/m37710o0.o: $(CPUSRC)/m37710/m37710o0.c \
+ $(M37710DEPS)
+
+$(CPUOBJ)/m37710/m37710o1.o: $(CPUSRC)/m37710/m37710o1.c \
+ $(M37710DEPS)
+
+$(CPUOBJ)/m37710/m37710o2.o: $(CPUSRC)/m37710/m37710o2.c \
+ $(M37710DEPS)
+
+$(CPUOBJ)/m37710/m37710o3.o: $(CPUSRC)/m37710/m37710o3.c \
+ $(M37710DEPS)
+
+$(CPUOBJ)/m37710/m7700ds.o: $(CPUSRC)/m37710/m7700ds.c \
+ $(CPUSRC)/m37710/m7700ds.h
+
+
+
+#-------------------------------------------------
+# Mostek 6502 and its many derivatives
+#-------------------------------------------------
+
+ifneq ($(filter M6502,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/m6502
+CPUOBJS += $(CPUOBJ)/m6502/m6502.o
+CPUOBJS += $(CPUOBJ)/m6502/m6509.o
+CPUOBJS += $(CPUOBJ)/m6502/m65ce02.o
+CPUOBJS += $(CPUOBJ)/m6502/m4510.o
+DASMOBJS += $(CPUOBJ)/m6502/6502dasm.o
+endif
+
+$(CPUOBJ)/m6502/m4510.o: $(CPUSRC)/m6502/m4510.c \
+ $(CPUSRC)/m6502/t65ce02.c
+
+$(CPUOBJ)/m6502/m6502.o: $(CPUSRC)/m6502/m6502.c \
+ $(CPUSRC)/m6502/m6502.h \
+ $(CPUSRC)/m6502/ops02.h \
+ $(CPUSRC)/m6502/t6502.c \
+ $(CPUSRC)/m6502/t65c02.c \
+ $(CPUSRC)/m6502/t65sc02.c \
+ $(CPUSRC)/m6502/t6510.c \
+ $(CPUSRC)/m6502/tn2a03.c \
+ $(CPUSRC)/m6502/tdeco16.c
+
+$(CPUOBJ)/m6502/m65ce02.o: $(CPUSRC)/m6502/m65ce02.c \
+ $(CPUSRC)/m6502/m65ce02.h \
+ $(CPUSRC)/m6502/opsce02.h \
+ $(CPUSRC)/m6502/t65ce02.c
+
+$(CPUOBJ)/m6502/m6509.o: $(CPUSRC)/m6502/m6509.c \
+ $(CPUSRC)/m6502/m6509.h \
+ $(CPUSRC)/m6502/ops09.h \
+ $(CPUSRC)/m6502/t6509.c
+
+
+
+#-------------------------------------------------
+# Motorola 680x
+#-------------------------------------------------
+
+ifneq ($(filter M6800,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/m6800
+CPUOBJS += $(CPUOBJ)/m6800/m6800.o
+DASMOBJS += $(CPUOBJ)/m6800/6800dasm.o
+endif
+
+$(CPUOBJ)/m6800/m6800.o: $(CPUSRC)/m6800/m6800.c \
+ $(CPUSRC)/m6800/m6800.h \
+ $(CPUSRC)/m6800/6800ops.c \
+ $(CPUSRC)/m6800/6800tbl.c
+
+
+
+#-------------------------------------------------
+# Motorola 6805
+#-------------------------------------------------
+
+ifneq ($(filter M6805,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/m6805
+CPUOBJS += $(CPUOBJ)/m6805/m6805.o
+DASMOBJS += $(CPUOBJ)/m6805/6805dasm.o
+endif
+
+$(CPUOBJ)/m6805/m6805.o: $(CPUSRC)/m6805/m6805.c \
+ $(CPUSRC)/m6805/m6805.h \
+ $(CPUSRC)/m6805/6805ops.c
+
+
+
+#-------------------------------------------------
+# Motorola 6809
+#-------------------------------------------------
+
+ifneq ($(filter M6809,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/m6809
+CPUOBJS += $(CPUOBJ)/m6809/m6809.o
+DASMOBJS += $(CPUOBJ)/m6809/6809dasm.o
+endif
+
+$(CPUOBJ)/m6809/m6809.o: $(CPUSRC)/m6809/m6809.c \
+ $(CPUSRC)/m6809/m6809.h \
+ $(CPUSRC)/m6809/6809ops.c \
+ $(CPUSRC)/m6809/6809tbl.c
+
+
+
+#-------------------------------------------------
+# Motorola 68HC11
+#-------------------------------------------------
+
+ifneq ($(filter MC68HC11,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/mc68hc11
+CPUOBJS += $(CPUOBJ)/mc68hc11/mc68hc11.o
+DASMOBJS += $(CPUOBJ)/mc68hc11/hc11dasm.o
+endif
+
+$(CPUOBJ)/mc68hc11/mc68hc11.o: $(CPUSRC)/mc68hc11/mc68hc11.c \
+ $(CPUSRC)/mc68hc11/hc11ops.c
+
+
+
+#-------------------------------------------------
+# Motorola 68000 series
+#-------------------------------------------------
+
+ifneq ($(filter M680X0,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/m68000
+CPUOBJS += $(CPUOBJ)/m68000/m68kcpu.o $(CPUOBJ)/m68000/m68kops.o
+DASMOBJS += $(CPUOBJ)/m68000/m68kdasm.o
+M68KMAKE = $(BUILDOUT)/m68kmake$(BUILD_EXE)
+endif
+
+# when we compile source files we need to include generated files from the OBJ directory
+$(CPUOBJ)/m68000/%.o: $(CPUSRC)/m68000/%.c | $(OSPREBUILD)
+ @echo Compiling $<...
+ $(CC) $(CDEFS) $(CFLAGS) -I$(CPUOBJ)/m68000 -c $< -o $@
+
+# when we compile generated files we need to include stuff from the src directory
+$(CPUOBJ)/m68000/%.o: $(CPUOBJ)/m68000/%.c | $(OSPREBUILD)
+ @echo Compiling $<...
+ $(CC) $(CDEFS) $(CFLAGS) -I$(CPUSRC)/m68000 -c $< -o $@
+
+# rule to generate the C files
+$(CPUOBJ)/m68000/m68kops.c: $(M68KMAKE) $(CPUSRC)/m68000/m68k_in.c
+ @echo Generating M68K source files...
+ $(M68KMAKE) $(CPUOBJ)/m68000 $(CPUSRC)/m68000/m68k_in.c
+
+# rule to build the generator
+ifneq ($(CROSS_BUILD),1)
+
+BUILD += $(M68KMAKE)
+
+$(M68KMAKE): $(CPUOBJ)/m68000/m68kmake.o $(LIBOCORE)
+ @echo Linking $@...
+ $(LD) $(LDFLAGS) $(OSDBGLDFLAGS) $^ $(LIBS) -o $@
+endif
+
+# rule to ensure we build the header before building the core CPU file
+$(CPUOBJ)/m68000/m68kcpu.o: $(CPUOBJ)/m68000/m68kops.c \
+ $(CPUSRC)/m68000/m68kcpu.h $(CPUSRC)/m68000/m68kfpu.c $(CPUSRC)/m68000/m68kmmu.h
+
+
+
+#-------------------------------------------------
+# Motorola/Freescale dsp56k
+#-------------------------------------------------
+
+ifneq ($(filter DSP56156,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/dsp56k
+CPUOBJS += $(CPUOBJ)/dsp56k/dsp56k.o
+CPUOBJS += $(CPUOBJ)/dsp56k/dsp56mem.o
+CPUOBJS += $(CPUOBJ)/dsp56k/dsp56pcu.o
+DASMOBJS += $(CPUOBJ)/dsp56k/dsp56dsm.o
+DASMOBJS += $(CPUOBJ)/dsp56k/opcode.o
+DASMOBJS += $(CPUOBJ)/dsp56k/inst.o
+DASMOBJS += $(CPUOBJ)/dsp56k/pmove.o
+DASMOBJS += $(CPUOBJ)/dsp56k/tables.o
+endif
+
+$(CPUOBJ)/dsp56k/dsp56mem.o: $(CPUSRC)/dsp56k/dsp56mem.c \
+ $(CPUSRC)/dsp56k/dsp56mem.h
+
+$(CPUOBJ)/dsp56k/dsp56pcu.o: $(CPUSRC)/dsp56k/dsp56pcu.c \
+ $(CPUSRC)/dsp56k/dsp56pcu.h
+
+$(CPUOBJ)/dsp56k/dsp56k.o: $(CPUSRC)/dsp56k/dsp56k.c \
+ $(CPUSRC)/dsp56k/dsp56k.h
+
+$(CPUOBJ)/dsp56k/opcode.o: $(CPUSRC)/dsp56k/opcode.c \
+ $(CPUSRC)/dsp56k/opcode.h
+
+$(CPUOBJ)/dsp56k/inst.o: $(CPUSRC)/dsp56k/inst.c \
+ $(CPUSRC)/dsp56k/inst.h
+
+$(CPUOBJ)/dsp56k/pmove.o: $(CPUSRC)/dsp56k/pmove.c \
+ $(CPUSRC)/dsp56k/pmove.h
+
+$(CPUOBJ)/dsp56k/tables.o: $(CPUSRC)/dsp56k/tables.c \
+ $(CPUSRC)/dsp56k/tables.h
+
+$(CPUOBJ)/dsp56k/dsp56dsm.o: $(CPUSRC)/dsp56k/opcode.c \
+ $(CPUSRC)/dsp56k/opcode.h \
+ $(CPUSRC)/dsp56k/inst.c \
+ $(CPUSRC)/dsp56k/inst.h \
+ $(CPUSRC)/dsp56k/pmove.c \
+ $(CPUSRC)/dsp56k/pmove.h \
+ $(CPUSRC)/dsp56k/tables.c \
+ $(CPUSRC)/dsp56k/tables.h
+
+
+#-------------------------------------------------
+# PDP-1
+# TX0
+#-------------------------------------------------
+
+ifneq ($(filter PDP1,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/pdp1
+CPUOBJS += $(CPUOBJ)/pdp1/pdp1.o
+CPUOBJS += $(CPUOBJ)/pdp1/tx0.o
+DASMOBJS += $(CPUOBJ)/pdp1/pdp1dasm.o
+DASMOBJS += $(CPUOBJ)/pdp1/tx0dasm.o
+endif
+
+$(CPUOBJ)/pdp1/pdp1.o: $(CPUSRC)/pdp1/pdp1.c \
+ $(CPUSRC)/pdp1/pdp1.h
+
+$(CPUOBJ)/pdp1/tx0.o: $(CPUSRC)/pdp1/tx0.h \
+ $(CPUSRC)/pdp1/tx0.c
+
+$(CPUOBJ)/pdp1/tx0dasm.o: $(CPUSRC)/pdp1/tx0.h \
+ $(CPUSRC)/pdp1/tx0dasm.c
+
+
+#-------------------------------------------------
+# Motorola PowerPC series
+#-------------------------------------------------
+
+ifneq ($(filter POWERPC,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/powerpc
+CPUOBJS += $(CPUOBJ)/powerpc/ppccom.o $(CPUOBJ)/powerpc/ppcfe.o $(CPUOBJ)/powerpc/ppcdrc.o $(DRCOBJ)
+DASMOBJS += $(CPUOBJ)/powerpc/ppc_dasm.o
+endif
+
+$(CPUOBJ)/powerpc/ppccom.o: $(CPUSRC)/powerpc/ppc.h \
+ $(CPUSRC)/powerpc/ppccom.h
+
+$(CPUOBJ)/powerpc/ppcfe.o: $(CPUSRC)/powerpc/ppc.h \
+ $(CPUSRC)/powerpc/ppccom.h \
+ $(CPUSRC)/powerpc/ppcfe.h
+
+$(CPUOBJ)/powerpc/ppcdrc.o: $(CPUSRC)/powerpc/ppcdrc.c \
+ $(CPUSRC)/powerpc/ppc.h \
+ $(CPUSRC)/powerpc/ppccom.h \
+ $(CPUSRC)/powerpc/ppcfe.h \
+ $(DRCDEPS)
+
+
+
+#-------------------------------------------------
+# NEC V-series Intel-compatible
+#-------------------------------------------------
+
+ifneq ($(filter NEC,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/nec
+CPUOBJS += $(CPUOBJ)/nec/nec.o
+CPUOBJS += $(CPUOBJ)/nec/v25.o
+CPUOBJS += $(CPUOBJ)/nec/v25sfr.o
+DASMOBJS += $(CPUOBJ)/nec/necdasm.o
+endif
+
+ifneq ($(filter V30MZ,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/v30mz $(CPUOBJ)/nec
+CPUOBJS += $(CPUOBJ)/v30mz/v30mz.o
+DASMOBJS += $(CPUOBJ)/nec/necdasm.o
+endif
+
+$(CPUOBJ)/nec/nec.o: $(CPUSRC)/nec/nec.c \
+ $(CPUSRC)/nec/nec.h \
+ $(CPUSRC)/nec/necea.h \
+ $(CPUSRC)/nec/necinstr.c \
+ $(CPUSRC)/nec/necinstr.h \
+ $(CPUSRC)/nec/necmacro.h \
+ $(CPUSRC)/nec/necmodrm.h \
+ $(CPUSRC)/nec/necpriv.h
+
+$(CPUOBJ)/nec/v25.o: $(CPUSRC)/nec/v25.c \
+ $(CPUSRC)/nec/nec.h \
+ $(CPUSRC)/nec/necea.h \
+ $(CPUSRC)/nec/necinstr.c \
+ $(CPUSRC)/nec/v25instr.c \
+ $(CPUSRC)/nec/v25instr.h \
+ $(CPUSRC)/nec/necmacro.h \
+ $(CPUSRC)/nec/necmodrm.h \
+ $(CPUSRC)/nec/v25priv.h
+
+$(CPUOBJ)/nec/v25sfr.o: $(CPUSRC)/nec/v25sfr.c \
+ $(CPUSRC)/nec/nec.h \
+ $(CPUSRC)/nec/v25priv.h
+
+$(CPUOBJ)/v30mz/v30mz.o: $(CPUSRC)/v30mz/v30mz.c \
+ $(CPUSRC)/v30mz/v30mz.h \
+ $(CPUSRC)/v30mz/necmodrm.h \
+ $(CPUSRC)/v30mz/necinstr.h \
+ $(CPUSRC)/v30mz/necea.h \
+ $(CPUSRC)/v30mz/nechost.h \
+ $(CPUSRC)/v30mz/nec.h
+
+
+
+#-------------------------------------------------
+# NEC V60/V70
+#-------------------------------------------------
+
+ifneq ($(filter V60,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/v60
+CPUOBJS += $(CPUOBJ)/v60/v60.o
+DASMOBJS += $(CPUOBJ)/v60/v60d.o
+endif
+
+$(CPUOBJ)/v60/v60.o: $(CPUSRC)/v60/am.c \
+ $(CPUSRC)/v60/am1.c \
+ $(CPUSRC)/v60/am2.c \
+ $(CPUSRC)/v60/am3.c \
+ $(CPUSRC)/v60/op12.c \
+ $(CPUSRC)/v60/op2.c \
+ $(CPUSRC)/v60/op3.c \
+ $(CPUSRC)/v60/op4.c \
+ $(CPUSRC)/v60/op5.c \
+ $(CPUSRC)/v60/op6.c \
+ $(CPUSRC)/v60/op7a.c \
+ $(CPUSRC)/v60/optable.c \
+ $(CPUSRC)/v60/v60.c \
+ $(CPUSRC)/v60/v60.h \
+ $(CPUSRC)/v60/v60d.c
+
+
+
+#-------------------------------------------------
+# NEC V810 (uPD70732)
+#-------------------------------------------------
+
+ifneq ($(filter V810,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/v810
+CPUOBJS += $(CPUOBJ)/v810/v810.o
+DASMOBJS += $(CPUOBJ)/v810/v810dasm.o
+endif
+
+$(CPUOBJ)/v810/v810.o: $(CPUSRC)/v810/v810.c \
+ $(CPUSRC)/v810/v810.h
+
+
+#-------------------------------------------------
+# NEC uPD7725
+#-------------------------------------------------
+
+ifneq ($(filter UPD7725,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/upd7725
+CPUOBJS += $(CPUOBJ)/upd7725/upd7725.o
+DASMOBJS += $(CPUOBJ)/upd7725/dasm7725.o
+endif
+
+$(CPUOBJ)/upd7725/upd7725.o: $(CPUSRC)/upd7725/upd7725.c \
+ $(CPUSRC)/upd7725/upd7725.h
+
+
+#-------------------------------------------------
+# NEC uPD7810 series
+#-------------------------------------------------
+
+ifneq ($(filter UPD7810,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/upd7810
+CPUOBJS += $(CPUOBJ)/upd7810/upd7810.o
+DASMOBJS += $(CPUOBJ)/upd7810/7810dasm.o
+endif
+
+$(CPUOBJ)/upd7810/upd7810.o: $(CPUSRC)/upd7810/upd7810.c \
+ $(CPUSRC)/upd7810/7810tbl.c \
+ $(CPUSRC)/upd7810/7810ops.c \
+ $(CPUSRC)/upd7810/upd7810.h
+
+
+
+#-------------------------------------------------
+# Nintendo Minx
+#-------------------------------------------------
+
+ifneq ($(filter MINX,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/minx
+CPUOBJS += $(CPUOBJ)/minx/minx.o
+DASMOBJS += $(CPUOBJ)/minx/minxd.o
+endif
+
+$(CPUOBJ)/minx/minx.o: $(CPUSRC)/minx/minx.c \
+ $(CPUSRC)/minx/minx.h \
+ $(CPUSRC)/minx/minxd.c \
+ $(CPUSRC)/minx/minxopce.h \
+ $(CPUSRC)/minx/minxopcf.h \
+ $(CPUSRC)/minx/minxops.h \
+ $(CPUSRC)/minx/minxfunc.h
+
+
+#-------------------------------------------------
+# Nintendo/SGI RSP (R3000-based + vector processing)
+#-------------------------------------------------
+
+ifneq ($(filter RSP,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/rsp
+CPUOBJS += $(CPUOBJ)/rsp/rsp.o $(CPUOBJ)/rsp/rspdrc.o $(CPUOBJ)/rsp/rspfe.o $(DRCOBJ)
+DASMOBJS += $(CPUOBJ)/rsp/rsp_dasm.o
+endif
+
+$(CPUOBJ)/rsp/rsp.o: $(CPUSRC)/rsp/rsp.c \
+ $(CPUSRC)/rsp/rsp.h
+
+$(CPUOBJ)/rsp/rspdrc.o: $(CPUSRC)/rsp/rspdrc.c \
+ $(CPUSRC)/rsp/rsp.h \
+ $(CPUSRC)/rsp/rspfe.h \
+ $(DRCDEPS)
+
+$(CPUOBJ)/rsp/rspfe.o: $(CPUSRC)/rsp/rspfe.c \
+ $(CPUSRC)/rsp/rspfe.h
+
+
+#-------------------------------------------------
+# Panasonic MN10200
+#-------------------------------------------------
+
+ifneq ($(filter MN10200,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/mn10200
+CPUOBJS += $(CPUOBJ)/mn10200/mn10200.o
+DASMOBJS += $(CPUOBJ)/mn10200/mn102dis.o
+endif
+
+$(CPUOBJ)/mn10200/mn10200.o: $(CPUSRC)/mn10200/mn10200.c \
+ $(CPUSRC)/mn10200/mn10200.h
+
+
+#-------------------------------------------------
+# Saturn
+#-------------------------------------------------
+
+ifneq ($(filter SATURN,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/saturn
+CPUOBJS += $(CPUOBJ)/saturn/saturn.o
+DASMOBJS += $(CPUOBJ)/saturn/saturnds.o
+endif
+
+$(CPUOBJ)/saturn/saturn.o: $(CPUSRC)/saturn/saturn.c \
+ $(CPUSRC)/saturn/sattable.c \
+ $(CPUSRC)/saturn/satops.c \
+ $(CPUSRC)/saturn/saturn.h
+
+
+
+#-------------------------------------------------
+# Signetics 2650
+#-------------------------------------------------
+
+ifneq ($(filter S2650,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/s2650
+CPUOBJS += $(CPUOBJ)/s2650/s2650.o
+DASMOBJS += $(CPUOBJ)/s2650/2650dasm.o
+endif
+
+$(CPUOBJ)/s2650/s2650.o: $(CPUSRC)/s2650/s2650.c \
+ $(CPUSRC)/s2650/s2650.h \
+ $(CPUSRC)/s2650/s2650cpu.h
+
+
+
+#-------------------------------------------------
+# SC61860
+#-------------------------------------------------
+
+ifneq ($(filter SC61860,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/sc61860
+CPUOBJS += $(CPUOBJ)/sc61860/sc61860.o
+DASMOBJS += $(CPUOBJ)/sc61860/scdasm.o
+endif
+
+$(CPUOBJ)/sc61860/sc61860.o: $(CPUSRC)/sc61860/sc61860.h \
+ $(CPUSRC)/sc61860/sc.h \
+ $(CPUSRC)/sc61860/scops.c \
+ $(CPUSRC)/sc61860/sctable.c
+
+
+
+#-------------------------------------------------
+# SM8500
+#-------------------------------------------------
+
+ifneq ($(filter SM8500,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/sm8500
+CPUOBJS += $(CPUOBJ)/sm8500/sm8500.o
+DASMOBJS += $(CPUOBJ)/sm8500/sm8500d.o
+endif
+
+$(CPUOBJ)/sm8500/sm8500.o: $(CPUSRC)/sm8500/sm8500.c \
+ $(CPUSRC)/sm8500/sm8500.h \
+ $(CPUSRC)/sm8500/sm85ops.h
+
+
+
+#-------------------------------------------------
+# Sony/Nintendo SPC700
+#-------------------------------------------------
+
+ifneq ($(filter SPC700,$(CPUS)),)
+SPCD = cpu/spc700
+OBJDIRS += $(CPUOBJ)/spc700
+CPUOBJS += $(CPUOBJ)/spc700/spc700.o
+DASMOBJS += $(CPUOBJ)/spc700/spc700ds.o
+endif
+
+$(CPUOBJ)/spc700/spc700.o: $(CPUSRC)/spc700/spc700.c \
+ $(CPUSRC)/spc700/spc700.h
+
+
+
+#-------------------------------------------------
+# SSP1601
+#-------------------------------------------------
+
+ifneq ($(filter SSP1601,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/ssp1601
+CPUOBJS += $(CPUOBJ)/ssp1601/ssp1601.o
+DASMOBJS += $(CPUOBJ)/ssp1601/ssp1601d.o
+endif
+
+$(CPUOBJ)/ssp1610/ssp1601.o: $(CPUSRC)/ssp1601/ssp1601.c \
+ $(CPUSRC)/ssp1610/ssp1601.h
+
+
+
+#-------------------------------------------------
+# SunPlus u'nSP
+#-------------------------------------------------
+
+ifneq ($(filter UNSP,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/unsp
+CPUOBJS += $(CPUOBJ)/unsp/unsp.o
+DASMOBJS += $(CPUOBJ)/unsp/unspdasm.o
+endif
+
+$(CPUOBJ)/unsp/unsp.o: $(CPUSRC)/unsp/unsp.c \
+ $(CPUSRC)/unsp/unsp.h
+
+
+
+#-------------------------------------------------
+# Atmel 8-bit AVR
+#-------------------------------------------------
+
+ifneq ($(filter AVR8,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/avr8
+CPUOBJS += $(CPUOBJ)/avr8/avr8.o
+DASMOBJS += $(CPUOBJ)/avr8/avr8dasm.o
+endif
+
+$(CPUOBJ)/avr8/avr8.o: $(CPUSRC)/avr8/avr8.c \
+ $(CPUSRC)/avr8/avr8.h
+
+
+
+#-------------------------------------------------
+# Texas Instruments TMS0980
+#-------------------------------------------------
+
+ifneq ($(filter TMS0980,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/tms0980
+CPUOBJS += $(CPUOBJ)/tms0980/tms0980.o
+DASMOBJS += $(CPUOBJ)/tms0980/tms0980d.o
+endif
+
+$(CPUOBJ)/tms0980/tms0980.o: $(CPUSRC)/tms0980/tms0980.h \
+ $(CPUSRC)/tms0980/tms0980.c
+
+$(CPUOBJ)/tms0980/tms0980d.o: $(CPUSRC)/tms0980/tms0980.h \
+ $(CPUSRC)/tms0980/tms0980d.c
+
+
+
+#-------------------------------------------------
+# Texas Instruments TMS7000 series
+#-------------------------------------------------
+
+ifneq ($(filter TMS7000,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/tms7000
+CPUOBJS += $(CPUOBJ)/tms7000/tms7000.o
+DASMOBJS += $(CPUOBJ)/tms7000/7000dasm.o
+endif
+
+$(CPUOBJ)/tms7000/tms7000.o: $(CPUSRC)/tms7000/tms7000.h \
+ $(CPUSRC)/tms7000/tms7000.c \
+ $(CPUSRC)/tms7000/tms70op.c \
+ $(CPUSRC)/tms7000/tms70tb.c
+
+$(CPUOBJ)/tms7000/7000dasm.o: $(CPUSRC)/tms7000/tms7000.h \
+ $(CPUSRC)/tms7000/7000dasm.c
+
+
+
+#-------------------------------------------------
+# Texas Instruments TMS99xx series
+#-------------------------------------------------
+
+ifneq ($(filter TMS9900,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/tms9900
+CPUOBJS += $(CPUOBJ)/tms9900/tms9900.o
+CPUOBJS += $(CPUOBJ)/tms9900/tms9980a.o
+CPUOBJS += $(CPUOBJ)/tms9900/tms9995.o
+CPUOBJS += $(CPUOBJ)/tms9900/ti990_10.o
+DASMOBJS += $(CPUOBJ)/tms9900/9900dasm.o
+endif
+
+$(CPUOBJ)/tms9900/tms9900.o: $(CPUSRC)/tms9900/tms9900.c \
+ $(CPUSRC)/tms9900/tms9900.h \
+ $(CPUSRC)/tms9900/99xxcore.h \
+ $(CPUSRC)/tms9900/99xxstat.h
+
+$(CPUOBJ)/tms9900/tms9980a.o: $(CPUSRC)/tms9900/tms9980a.c \
+ $(CPUSRC)/tms9900/tms9900.h \
+ $(CPUSRC)/tms9900/99xxcore.h \
+ $(CPUSRC)/tms9900/99xxstat.h
+
+$(CPUOBJ)/tms9900/tms9995.o: $(CPUSRC)/tms9900/tms9995.c \
+ $(CPUSRC)/tms9900/tms9900.h \
+ $(CPUSRC)/tms9900/99xxcore.h \
+ $(CPUSRC)/tms9900/99xxstat.h
+
+$(CPUOBJ)/tms9900/ti990_10.o: $(CPUSRC)/tms9900/ti990_10.c \
+ $(CPUSRC)/tms9900/tms9900.h \
+ $(CPUSRC)/tms9900/99xxcore.h \
+ $(CPUSRC)/tms9900/99xxstat.h
+
+
+
+#-------------------------------------------------
+# Texas Instruments TMS340x0 graphics controllers
+#-------------------------------------------------
+
+ifneq ($(filter TMS340X0,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/tms34010
+CPUOBJS += $(CPUOBJ)/tms34010/tms34010.o
+DASMOBJS += $(CPUOBJ)/tms34010/34010dsm.o
+endif
+
+$(CPUOBJ)/tms34010/tms34010.o: $(CPUSRC)/tms34010/tms34010.c \
+ $(CPUSRC)/tms34010/tms34010.h \
+ $(CPUSRC)/tms34010/34010ops.c \
+ $(CPUSRC)/tms34010/34010gfx.c \
+ $(CPUSRC)/tms34010/34010fld.c \
+ $(CPUSRC)/tms34010/34010tbl.c
+
+
+
+#-------------------------------------------------
+# Texas Instruments TMS3201x DSP
+#-------------------------------------------------
+
+ifneq ($(filter TMS32010,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/tms32010
+CPUOBJS += $(CPUOBJ)/tms32010/tms32010.o
+DASMOBJS += $(CPUOBJ)/tms32010/32010dsm.o
+endif
+
+$(CPUOBJ)/tms32010/tms32010.o: $(CPUSRC)/tms32010/tms32010.c \
+ $(CPUSRC)/tms32010/tms32010.h
+
+
+
+#-------------------------------------------------
+# Texas Instruments TMS3202x DSP
+#-------------------------------------------------
+
+ifneq ($(filter TMS32025,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/tms32025
+CPUOBJS += $(CPUOBJ)/tms32025/tms32025.o
+DASMOBJS += $(CPUOBJ)/tms32025/32025dsm.o
+endif
+
+$(CPUOBJ)/tms32025/tms32025.o: $(CPUSRC)/tms32025/tms32025.c \
+ $(CPUSRC)/tms32025/tms32025.h
+
+
+
+#-------------------------------------------------
+# Texas Instruments TMS3203x DSP
+#-------------------------------------------------
+
+ifneq ($(filter TMS32031,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/tms32031
+CPUOBJS += $(CPUOBJ)/tms32031/tms32031.o
+DASMOBJS += $(CPUOBJ)/tms32031/dis32031.o
+endif
+
+$(CPUOBJ)/tms32031/tms32031.o: $(CPUSRC)/tms32031/tms32031.c \
+ $(CPUSRC)/tms32031/tms32031.h \
+ $(CPUSRC)/tms32031/32031ops.c
+
+
+
+#-------------------------------------------------
+# Texas Instruments TMS3205x DSP
+#-------------------------------------------------
+
+ifneq ($(filter TMS32051,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/tms32051
+CPUOBJS += $(CPUOBJ)/tms32051/tms32051.o
+DASMOBJS += $(CPUOBJ)/tms32051/dis32051.o
+endif
+
+$(CPUOBJ)/tms32051/tms32051.o: $(CPUSRC)/tms32051/tms32051.c \
+ $(CPUSRC)/tms32051/tms32051.h \
+ $(CPUSRC)/tms32051/32051ops.c
+
+
+
+#-------------------------------------------------
+# Texas Instruments TMS57002 DSP
+#-------------------------------------------------
+
+ifneq ($(filter TMS57002,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/tms57002
+CPUOBJS += $(CPUOBJ)/tms57002/tms57002.o $(CPUOBJ)/tms57002/tms57kdec.o
+DASMOBJS += $(CPUOBJ)/tms57002/57002dsm.o
+TMSMAKE += $(BUILDOUT)/tmsmake$(BUILD_EXE)
+endif
+
+$(CPUOBJ)/tms57002/tms57002.o: $(CPUSRC)/tms57002/tms57002.c \
+ $(CPUSRC)/tms57002/tms57002.h \
+ $(CPUSRC)/tms57002/tms57kpr.h \
+ $(CPUOBJ)/tms57002/tms57002.inc
+
+$(CPUOBJ)/tms57002/tms57kdec.o: $(CPUSRC)/tms57002/tms57kdec.c \
+ $(CPUSRC)/tms57002/tms57002.h \
+ $(CPUSRC)/tms57002/tms57kpr.h \
+ $(CPUOBJ)/tms57002/tms57002.inc
+
+$(CPUOBJ)/tms57002/57002dsm.o: $(CPUSRC)/tms57002/57002dsm.c \
+ $(CPUOBJ)/tms57002/tms57002.inc
+
+# rule to generate the C file
+$(CPUOBJ)/tms57002/tms57002.inc: $(TMSMAKE) $(CPUSRC)/tms57002/tmsinstr.lst
+ @echo Generating TMS57002 source file...
+ $(TMSMAKE) $(CPUSRC)/tms57002/tmsinstr.lst $@
+
+# rule to build the generator
+ifneq ($(CROSS_BUILD),1)
+
+BUILD += $(TMSMAKE)
+
+$(TMSMAKE): $(CPUOBJ)/tms57002/tmsmake.o $(LIBOCORE)
+ @echo Linking $@...
+ $(LD) $(LDFLAGS) $(OSDBGLDFLAGS) $^ $(LIBS) -o $@
+
+endif
+
+
+#-------------------------------------------------
+# Toshiba TLCS-90 Series
+#-------------------------------------------------
+
+ifneq ($(filter TLCS90,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/tlcs90
+CPUOBJS += $(CPUOBJ)/tlcs90/tlcs90.o
+#DASMOBJS += $(CPUOBJ)/tlcs90/tlcs90.o
+endif
+
+$(CPUOBJ)/tlcs90/tlcs90.o: $(CPUSRC)/tlcs90/tlcs90.c \
+ $(CPUSRC)/tlcs90/tlcs90.h
+
+
+
+#-------------------------------------------------
+# Toshiba TLCS-900 Series
+#-------------------------------------------------
+
+ifneq ($(filter TLCS900,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/tlcs900
+CPUOBJS += $(CPUOBJ)/tlcs900/tlcs900.o
+DASMOBJS += $(CPUOBJ)/tlcs900/dasm900.o
+endif
+
+$(CPUOBJ)/tlcs900/tlcs900.o: $(CPUSRC)/tlcs900/tlcs900.c \
+ $(CPUSRC)/tlcs900/900tbl.c \
+ $(CPUSRC)/tlcs900/tlcs900.h
+
+$(CPUOBJ)/tlcs900/dasm900.o: $(CPUSRC)/tlcs900/dasm900.c
+
+
+
+#-------------------------------------------------
+# Zilog Z80
+#-------------------------------------------------
+
+ifneq ($(filter Z80,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/z80
+CPUOBJS += $(CPUOBJ)/z80/z80.o $(CPUOBJ)/z80/z80daisy.o
+DASMOBJS += $(CPUOBJ)/z80/z80dasm.o
+endif
+
+$(CPUOBJ)/z80/z80.o: $(CPUSRC)/z80/z80.c \
+ $(CPUSRC)/z80/z80.h
+
+
+
+#-------------------------------------------------
+# Sharp LR35902 (Game Boy CPU)
+#-------------------------------------------------
+
+ifneq ($(filter LR35902,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/lr35902
+CPUOBJS += $(CPUOBJ)/lr35902/lr35902.o
+DASMOBJS += $(CPUOBJ)/lr35902/lr35902d.o
+endif
+
+$(CPUOBJ)/lr35902/lr35902.o: $(CPUSRC)/lr35902/lr35902.c \
+ $(CPUSRC)/lr35902/lr35902.h \
+ $(CPUSRC)/lr35902/opc_cb.h \
+ $(CPUSRC)/lr35902/opc_main.h
+
+
+
+#-------------------------------------------------
+# Zilog Z180
+#-------------------------------------------------
+
+ifneq ($(filter Z180,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/z180 $(CPUOBJ)/z80
+CPUOBJS += $(CPUOBJ)/z180/z180.o $(CPUOBJ)/z80/z80daisy.o
+DASMOBJS += $(CPUOBJ)/z180/z180dasm.o
+endif
+
+$(CPUOBJ)/z180/z180.o: $(CPUSRC)/z180/z180.c \
+ $(CPUSRC)/z180/z180.h \
+ $(CPUSRC)/z180/z180op.c \
+ $(CPUSRC)/z180/z180ops.h \
+ $(CPUSRC)/z180/z180tbl.h \
+ $(CPUSRC)/z180/z180cb.c \
+ $(CPUSRC)/z180/z180dd.c \
+ $(CPUSRC)/z180/z180ed.c \
+ $(CPUSRC)/z180/z180fd.c \
+ $(CPUSRC)/z180/z180xy.c
+
+
+
+#-------------------------------------------------
+# Zilog Z8000
+#-------------------------------------------------
+
+ifneq ($(filter Z8000,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/z8000
+CPUOBJS += $(CPUOBJ)/z8000/z8000.o
+DASMOBJS += $(CPUOBJ)/z8000/8000dasm.o
+endif
+
+$(CPUOBJ)/z8000/z8000.o: $(CPUSRC)/z8000/z8000.c \
+ $(CPUSRC)/z8000/z8000.h \
+ $(CPUSRC)/z8000/z8000cpu.h \
+ $(CPUSRC)/z8000/z8000dab.h \
+ $(CPUSRC)/z8000/z8000ops.c \
+ $(CPUSRC)/z8000/z8000tbl.c
+
+
+
+#-------------------------------------------------
+# Zilog Z8
+#-------------------------------------------------
+
+ifneq ($(filter Z8,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/z8
+CPUOBJS += $(CPUOBJ)/z8/z8.o
+DASMOBJS += $(CPUOBJ)/z8/z8dasm.o
+endif
+
+$(CPUOBJ)/z8/z8.o: $(CPUSRC)/z8/z8.c \
+ $(CPUSRC)/z8/z8ops.c \
+ $(CPUSRC)/z8/z8.h
+
+
+
+#-------------------------------------------------
+# Argonaut SuperFX
+#-------------------------------------------------
+
+ifneq ($(filter SUPERFX,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/superfx
+CPUOBJS += $(CPUOBJ)/superfx/superfx.o
+DASMOBJS += $(CPUOBJ)/superfx/sfx_dasm.o
+endif
+
+$(CPUOBJ)/superfx/superfx.o:$(CPUSRC)/superfx/superfx.c \
+ $(CPUSRC)/superfx/superfx.h
+
+#-------------------------------------------------
+# Rockwell PPS-4
+#-------------------------------------------------
+
+ifneq ($(filter PPS4,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/pps4
+CPUOBJS += $(CPUOBJ)/pps4/pps4.o
+DASMOBJS += $(CPUOBJ)/pps4/pps4dasm.o
+endif
+
+$(CPUOBJ)/pps4/pps4.o: $(CPUSRC)/pps4/pps4.c \
+ $(CPUSRC)/pps4/pps4.h
+
+#-------------------------------------------------
+# Hitachi HD61700
+#-------------------------------------------------
+
+ifneq ($(filter HD61700,$(CPUS)),)
+OBJDIRS += $(CPUOBJ)/hd61700
+CPUOBJS += $(CPUOBJ)/hd61700/hd61700.o
+DASMOBJS += $(CPUOBJ)/hd61700/hd61700d.o
+endif
+
+$(CPUOBJ)/hd61700/hd61700.o: $(CPUSRC)/hd61700/hd61700.c \
+ $(CPUSRC)/hd61700/hd61700.h
diff --git a/trunk/src/emu/cpu/cubeqcpu/cubedasm.c b/trunk/src/emu/cpu/cubeqcpu/cubedasm.c
new file mode 100644
index 00000000000..8a808fd9e95
--- /dev/null
+++ b/trunk/src/emu/cpu/cubeqcpu/cubedasm.c
@@ -0,0 +1,304 @@
+/***************************************************************************
+
+ cubedasm.c
+
+ Implementation of the Cube Quest AM2901-based CPUs
+
+***************************************************************************/
+
+#include "emu.h"
+#include "cubeqcpu.h"
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+/* Am2901 Instruction Fields */
+static const char *const ins[] =
+{
+ "ADD ",
+ "SUBR ",
+ "SUBS ",
+ "OR ",
+ "AND ",
+ "NOTRS",
+ "EXOR ",
+ "EXNOR",
+};
+
+static const char *const src[] =
+{
+ "A,Q",
+ "A,B",
+ "0,Q",
+ "0,B",
+ "0,A",
+ "D,A",
+ "D,Q",
+ "D,0",
+};
+
+static const char *const dst[] =
+{
+ "QREG ",
+ "NOP ",
+ "RAMA ",
+ "RAMF ",
+ "RAMQD",
+ "RAMD ",
+ "RAMQU",
+ "RAMU ",
+};
+
+
+/***************************************************************************
+ SOUND DISASSEMBLY HOOK
+***************************************************************************/
+
+CPU_DISASSEMBLE( cquestsnd )
+{
+ static const char *const jmps[] =
+ {
+ "JUMP ",
+ " ",
+ "JMSB ",
+ "JNMSB",
+ " ",
+ "JZERO",
+ "JOVR ",
+ "JLOOP",
+ };
+
+
+ static const char *const latches[] =
+ {
+ "PLTCH ",
+ "DAC ",
+ "ADLATCH",
+ " ",
+ };
+
+ UINT64 inst = BIG_ENDIANIZE_INT64(*(UINT64 *)oprom);
+ UINT32 inslow = inst & 0xffffffff;
+ UINT32 inshig = inst >> 32;
+
+ int t = (inshig >> 24) & 0xff;
+ int b = (inshig >> 20) & 0xf;
+ int a = (inshig >> 16) & 0xf;
+ int ci = (inshig >> 15) & 1;
+ int i5_3 = (inshig >> 12) & 7;
+ int _ramen = (inshig >> 11) & 1;
+ int i2_0 = (inshig >> 8) & 7;
+ int rtnltch = (inshig >> 7) & 1;
+ int jmp = (inshig >> 4) & 7;
+ int inca = (inshig >> 3) & 1;
+ int i8_6 = (inshig >> 0) & 7;
+ int _ipram = (inslow >> 31) & 1;
+ int _ipwrt = (inslow >> 30) & 1;
+ int latch = (inslow >> 28) & 3;
+ int rtn = (inslow >> 27) & 1;
+ int _rin = (inslow >> 26) & 1;
+
+
+ sprintf(buffer, "%s %s %s %x,%x,%c %.2x %s %s %.2x %s %s %s %c %c %c",
+ ins[i5_3],
+ src[i2_0],
+ dst[i8_6],
+ a,
+ b,
+ ci ? 'C' : ' ',
+ _rin,
+ jmps[jmp],
+ rtn ? "RET" : " ",
+ t,
+ latches[latch],
+ rtnltch ? "RTLATCH" : " ",
+ _ramen ? "PROM" : "RAM ",
+ _ipram ? ' ' : 'R',
+ _ipwrt ? ' ' : 'W',
+ inca ? 'I' : ' ');
+
+ return 1 | DASMFLAG_SUPPORTED;
+}
+
+
+/***************************************************************************
+ ROTATE DISASSEMBLY HOOK
+***************************************************************************/
+
+CPU_DISASSEMBLE( cquestrot )
+{
+ static const char *const jmps[] =
+ {
+ " ",
+ "JSEQ ",
+ "JC ",
+ "JSYNC ",
+ "JLDWAIT",
+ "JMSB ",
+ "JGEONE ",
+ "JZERO ",
+
+ "JUMP ",
+ "JNSEQ ",
+ "JNC ",
+ "JNSYNC ",
+ "JNLDWAI",
+ "JNMSB ",
+ "JLTONE ",
+ "JNZERO ",
+ };
+
+ static const char *const youts[] =
+ {
+ " ",
+ " ",
+ "Y2LDA",
+ "Y2LDD",
+ "Y2DAD",
+ "Y2DIN",
+ "Y2R ",
+ "Y2D ",
+ };
+
+ static const char *const spfs[] =
+ {
+ " ",
+ " ",
+ "OP ",
+ "RET ",
+ "SQLTCH",
+ "SWRT ",
+ "DIV ",
+ "MULT ",
+
+ "DRED ",
+ "DWRT ",
+ "??? ",
+ "??? ",
+ "??? ",
+ "??? ",
+ "??? ",
+ "??? "
+ };
+
+ UINT64 inst = BIG_ENDIANIZE_INT64(*(UINT64 *)oprom);
+ UINT32 inslow = inst & 0xffffffff;
+ UINT32 inshig = inst >> 32;
+
+ int t = (inshig >> 20) & 0xfff;
+ int jmp = (inshig >> 16) & 0xf;
+ int spf = (inshig >> 12) & 0xf;
+// int rsrc = (inshig >> 11) & 0x1;
+ int yout = (inshig >> 8) & 0x7;
+ int sel = (inshig >> 6) & 0x3;
+// int dsrc = (inshig >> 4) & 0x3;
+ int b = (inshig >> 0) & 0xf;
+ int a = (inslow >> 28) & 0xf;
+ int i8_6 = (inslow >> 24) & 0x7;
+ int ci = (inslow >> 23) & 0x1;
+ int i5_3 = (inslow >> 20) & 0x7;
+// int _sex = (inslow >> 19) & 0x1;
+ int i2_0 = (inslow >> 16) & 0x7;
+
+ sprintf(buffer, "%s %s,%s %x,%x,%c %d %s %s %s %.2x",
+ ins[i5_3],
+ src[i2_0],
+ dst[i8_6],
+ a,
+ b,
+ ci ? 'C' : ' ',
+ sel,
+ jmps[jmp],
+ youts[yout],
+ spfs[spf],
+ t);
+
+ return 1 | DASMFLAG_SUPPORTED;
+}
+
+/***************************************************************************
+ LINE DRAWER DISASSEMBLY HOOK
+***************************************************************************/
+
+CPU_DISASSEMBLE( cquestlin )
+{
+ static const char *const jmps[] =
+ {
+ " ",
+ "JMSB ",
+ "JSEQ ",
+ "JGTZ ",
+ "JC ",
+ "JZ ",
+ "?????",
+ "?????",
+
+ "JUMP ",
+ "JNMSB",
+ "JNSEQ",
+ "JLEZ ",
+ "JNC ",
+ "JNZ ",
+ "?????",
+ "?????",
+ };
+
+ static const char *const latches[] =
+ {
+ " ",
+ "SEQLTCH",
+ "XLTCH ",
+ "YLTCH ",
+ "BGLTCH ",
+ "FGLTCH ",
+ "CLTCH ",
+ "ZLTCH ",
+ };
+
+ static const char *const spfs[] =
+ {
+ " ",
+ "FSTOP ",
+ "FREG ",
+ "FSTART",
+ "PWRT ",
+ "MULT ",
+ "LSTOP ",
+ "BRES ",
+ };
+
+ UINT64 inst = BIG_ENDIANIZE_INT64(*(UINT64 *)oprom);
+ UINT32 inslow = inst & 0xffffffff;
+ UINT32 inshig = inst >> 32;
+
+ int t = (inshig >> 24) & 0xff;
+ int jmp = (inshig >> 20) & 0xf;
+ int latch = (inshig >> 16) & 0x7;
+ int op = (inshig >> 15) & 0x1;
+ int spf = (inshig >> 12) & 0x7;
+ int b = (inshig >> 8) & 0xf;
+ int a = (inshig >> 4) & 0xf;
+ int i8_6 = (inshig >> 0) & 0x7;
+ int ci = (inslow >> 31) & 0x1;
+ int i5_3 = (inslow >> 28) & 0x7;
+ int _pbcs = (inslow >> 27) & 0x1;
+ int i2_0 = (inslow >> 24) & 0x7;
+
+ sprintf(buffer, "%s %s,%s %x,%x %c %s %.2x %s %s %s %s",
+ ins[i5_3],
+ src[i2_0],
+ dst[i8_6],
+ a,
+ b,
+ ci ? 'C' : ' ',
+ jmps[jmp],
+ t,
+ latches[latch],
+ op ? "OP" : " ",
+ _pbcs ? " " : "PB",
+ spfs[spf]);
+
+ return 1 | DASMFLAG_SUPPORTED;
+}
diff --git a/trunk/src/emu/cpu/cubeqcpu/cubeqcpu.c b/trunk/src/emu/cpu/cubeqcpu/cubeqcpu.c
new file mode 100644
index 00000000000..e64e917e5cd
--- /dev/null
+++ b/trunk/src/emu/cpu/cubeqcpu/cubeqcpu.c
@@ -0,0 +1,1885 @@
+/***************************************************************************
+
+ cubeqcpu.c
+
+ Implementation of the Cube Quest AM2901-based CPUs
+
+ TODO:
+
+ * Tidy up diassembly (split into different files?)
+
+***************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "cubeqcpu.h"
+
+
+CPU_DISASSEMBLE( cquestsnd );
+CPU_DISASSEMBLE( cquestrot );
+CPU_DISASSEMBLE( cquestlin );
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+/* Am2901 Instruction Fields */
+enum alu_src
+{
+ AQ = 0,
+ AB = 1,
+ ZQ = 2,
+ ZB = 3,
+ ZA = 4,
+ DA = 5,
+ DQ = 6,
+ DZ = 7,
+};
+
+enum alu_ins
+{
+ ADD = 0,
+ SUBR = 1,
+ SUBS = 2,
+ OR = 3,
+ AND = 4,
+ NOTRS = 5,
+ EXOR = 6,
+ EXNOR = 7,
+};
+
+enum alu_dst
+{
+ QREG = 0,
+ NOP = 1,
+ RAMA = 2,
+ RAMF = 3,
+ RAMQD = 4,
+ RAMD = 5,
+ RAMQU = 6,
+ RAMU = 7,
+};
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+#define _BIT(x, n) ((x) & (1 << (n)))
+
+/***************************************************************************
+ STRUCTURES & TYPEDEFS
+***************************************************************************/
+
+typedef struct
+{
+ /* AM2901 internals */
+ UINT16 ram[16];
+ UINT16 q;
+ UINT16 f;
+ UINT16 y;
+ UINT32 cflag;
+ UINT32 vflag;
+
+ UINT8 pc; /* 2 x LS161 @ 6E, 6F */
+ UINT16 platch;
+ UINT8 rtnlatch; /* LS374 @ 5F */
+ UINT8 adrcntr; /* 2 x LS161 */
+ UINT16 adrlatch;
+ UINT16 dinlatch;
+ UINT16 ramwlatch;
+
+ UINT16 *sram;
+
+ int prev_ipram;
+ int prev_ipwrt;
+
+ cubeqst_dac_w_func dac_w;
+ UINT16 *sound_data;
+
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ int icount;
+} cquestsnd_state;
+
+
+typedef struct
+{
+ /* AM2901 internals */
+ UINT16 ram[16];
+ UINT16 q;
+ UINT16 f;
+ UINT16 y;
+ UINT32 cflag;
+ UINT32 vflag;
+
+ UINT16 pc; /* 12-bit, but only 9 used */
+ UINT8 seqcnt; /* 4-bit counter */
+
+ UINT8 dsrclatch;
+ UINT8 rsrclatch;
+ UINT16 dynaddr; /* LS374 at 2D, 8D */
+ UINT16 dyndata; /* LS374 at 10B, 9B */
+ UINT16 yrlatch; /* LS374 at 9D, 10D */
+ UINT16 ydlatch; /* LS374 at 9C, 10C */
+ UINT16 dinlatch;
+ UINT8 divreg; /* LS74 at ? */
+
+ UINT16 linedata;
+ UINT16 lineaddr;
+
+ UINT16 *dram;
+ UINT16 *sram;
+
+ UINT8 prev_dred;
+ UINT8 prev_dwrt;
+ UINT8 wc;
+ UINT8 rc;
+ UINT8 clkcnt;
+
+ legacy_cpu_device *device;
+ legacy_cpu_device *lindevice;
+ address_space *program;
+ direct_read_data *direct;
+ int icount;
+} cquestrot_state;
+
+
+typedef struct
+{
+ /* 12-bit AM2901 internals */
+ UINT16 ram[16];
+ UINT16 q;
+ UINT16 f;
+ UINT16 y;
+ UINT32 cflag;
+ UINT32 vflag;
+
+ UINT8 pc[2]; /* Two program counters; one for FG, other for BG */
+
+ UINT16 seqcnt; /* 12-bit */
+ UINT16 clatch; /* LS374 at 9E and 1-bit FF */
+ UINT8 zlatch; /* LS374 at 4H */
+
+ UINT16 xcnt;
+ UINT16 ycnt;
+ UINT8 sreg;
+
+ UINT16 fadlatch;
+ UINT16 badlatch;
+
+ UINT16 sramdlatch;
+
+ UINT8 fglatch;
+ UINT8 bglatch;
+ UINT8 gt0reg;
+ UINT8 fdxreg;
+ UINT32 field;
+
+ UINT32 clkcnt;
+
+ /* RAM */
+ UINT16 *sram;
+ UINT8 *ptr_ram;
+ UINT32 *e_stack;
+ UINT32 *o_stack;
+
+ legacy_cpu_device *device;
+ legacy_cpu_device *rotdevice;
+ address_space *program;
+ direct_read_data *direct;
+ int icount;
+} cquestlin_state;
+
+/***************************************************************************
+ STATE ACCESSORS
+***************************************************************************/
+
+INLINE cquestsnd_state *get_safe_token_snd(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == CQUESTSND);
+ return (cquestsnd_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+INLINE cquestrot_state *get_safe_token_rot(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == CQUESTROT);
+ return (cquestrot_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+INLINE cquestlin_state *get_safe_token_lin(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == CQUESTLIN);
+ return (cquestlin_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+/***************************************************************************
+ MEMORY ACCESSORS FOR 68000
+***************************************************************************/
+
+WRITE16_DEVICE_HANDLER( cubeqcpu_sndram_w )
+{
+ cquestsnd_state *cpustate = get_safe_token_snd(device);
+ COMBINE_DATA(&cpustate->sram[offset]);
+}
+
+READ16_DEVICE_HANDLER( cubeqcpu_sndram_r )
+{
+ cquestsnd_state *cpustate = get_safe_token_snd(device);
+ return cpustate->sram[offset];
+}
+
+
+WRITE16_DEVICE_HANDLER( cubeqcpu_rotram_w )
+{
+ cquestrot_state *cpustate = get_safe_token_rot(device);
+ COMBINE_DATA(&cpustate->dram[offset]);
+}
+
+READ16_DEVICE_HANDLER( cubeqcpu_rotram_r )
+{
+ cquestrot_state *cpustate = get_safe_token_rot(device);
+ return cpustate->dram[offset];
+}
+
+/***************************************************************************
+ SOUND INITIALIZATION AND SHUTDOWN
+***************************************************************************/
+
+static void cquestsnd_state_register(device_t *device)
+{
+ cquestsnd_state *cpustate = get_safe_token_snd(device);
+ device->save_item(NAME(cpustate->ram));
+ device->save_item(NAME(cpustate->q));
+ device->save_item(NAME(cpustate->f));
+ device->save_item(NAME(cpustate->y));
+ device->save_item(NAME(cpustate->cflag));
+ device->save_item(NAME(cpustate->vflag));
+
+ device->save_item(NAME(cpustate->pc));
+ device->save_item(NAME(cpustate->platch));
+ device->save_item(NAME(cpustate->rtnlatch));
+ device->save_item(NAME(cpustate->adrcntr));
+ device->save_item(NAME(cpustate->adrlatch));
+ device->save_item(NAME(cpustate->dinlatch));
+ device->save_item(NAME(cpustate->ramwlatch));
+ device->save_item(NAME(cpustate->prev_ipram));
+ device->save_item(NAME(cpustate->prev_ipwrt));
+}
+
+static CPU_INIT( cquestsnd )
+{
+ cquestsnd_state *cpustate = get_safe_token_snd(device);
+ cubeqst_snd_config* _config = (cubeqst_snd_config*)device->static_config();
+
+ memset(cpustate, 0, sizeof(*cpustate));
+
+ cpustate->dac_w = _config->dac_w;
+ cpustate->sound_data = (UINT16*)device->machine().region(_config->sound_data_region)->base();
+
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+
+ /* Allocate RAM shared with 68000 */
+ cpustate->sram = auto_alloc_array(device->machine(), UINT16, 4096/2);
+
+ cquestsnd_state_register(device);
+}
+
+
+static CPU_RESET( cquestsnd )
+{
+ cquestsnd_state *cpustate = get_safe_token_snd(device);
+ cpustate->pc = 0;
+}
+
+
+static CPU_EXIT( cquestsnd )
+{
+}
+
+
+/***************************************************************************
+ ROTATE INITIALIZATION AND SHUTDOWN
+***************************************************************************/
+
+static void cquestrot_state_register(device_t *device)
+{
+ cquestrot_state *cpustate = get_safe_token_rot(device);
+ device->save_item(NAME(cpustate->ram));
+ device->save_item(NAME(cpustate->q));
+ device->save_item(NAME(cpustate->f));
+ device->save_item(NAME(cpustate->y));
+ device->save_item(NAME(cpustate->cflag));
+ device->save_item(NAME(cpustate->vflag));
+
+ device->save_item(NAME(cpustate->pc));
+ device->save_item(NAME(cpustate->seqcnt));
+ device->save_item(NAME(cpustate->dsrclatch));
+ device->save_item(NAME(cpustate->rsrclatch));
+ device->save_item(NAME(cpustate->dynaddr));
+ device->save_item(NAME(cpustate->dyndata));
+ device->save_item(NAME(cpustate->yrlatch));
+ device->save_item(NAME(cpustate->ydlatch));
+ device->save_item(NAME(cpustate->dinlatch));
+ device->save_item(NAME(cpustate->divreg));
+ device->save_item(NAME(cpustate->linedata));
+ device->save_item(NAME(cpustate->lineaddr));
+ device->save_item(NAME(cpustate->prev_dred));
+ device->save_item(NAME(cpustate->prev_dwrt));
+ device->save_item(NAME(cpustate->wc));
+
+ device->save_pointer(NAME(cpustate->dram), 16384);
+ device->save_pointer(NAME(cpustate->sram), 2048);
+}
+
+static CPU_INIT( cquestrot )
+{
+ const cubeqst_rot_config *rotconfig = (const cubeqst_rot_config *)device->static_config();
+ cquestrot_state *cpustate = get_safe_token_rot(device);
+ memset(cpustate, 0, sizeof(*cpustate));
+
+ /* Allocate RAM */
+ cpustate->dram = auto_alloc_array(device->machine(), UINT16, 16384); /* Shared with 68000 */
+ cpustate->sram = auto_alloc_array(device->machine(), UINT16, 2048); /* Private */
+
+ cpustate->device = device;
+ cpustate->lindevice = device->machine().device<legacy_cpu_device>(rotconfig->lin_cpu_tag);
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+
+ cquestrot_state_register(device);
+}
+
+
+static CPU_RESET( cquestrot )
+{
+ cquestrot_state *cpustate = get_safe_token_rot(device);
+ cpustate->pc = 0;
+ cpustate->wc = 0;
+ cpustate->prev_dred = 1;
+ cpustate->prev_dwrt = 1;
+}
+
+
+static CPU_EXIT( cquestrot )
+{
+}
+
+
+/***************************************************************************
+ LINE DRAWER INITIALIZATION AND SHUTDOWN
+***************************************************************************/
+#define FOREGROUND 0
+#define BACKGROUND 1
+#define ODD_FIELD 0
+#define EVEN_FIELD 1
+
+static void cquestlin_state_register(device_t *device)
+{
+ cquestlin_state *cpustate = get_safe_token_lin(device);
+
+ device->save_item(NAME(cpustate->ram));
+ device->save_item(NAME(cpustate->q));
+ device->save_item(NAME(cpustate->f));
+ device->save_item(NAME(cpustate->y));
+ device->save_item(NAME(cpustate->cflag));
+ device->save_item(NAME(cpustate->vflag));
+
+ device->save_item(NAME(cpustate->pc[0]));
+ device->save_item(NAME(cpustate->pc[1]));
+ device->save_item(NAME(cpustate->seqcnt));
+ device->save_item(NAME(cpustate->clatch));
+ device->save_item(NAME(cpustate->zlatch));
+ device->save_item(NAME(cpustate->xcnt));
+ device->save_item(NAME(cpustate->ycnt));
+ device->save_item(NAME(cpustate->sreg));
+ device->save_item(NAME(cpustate->fadlatch));
+ device->save_item(NAME(cpustate->badlatch));
+ device->save_item(NAME(cpustate->sramdlatch));
+ device->save_item(NAME(cpustate->fglatch));
+ device->save_item(NAME(cpustate->bglatch));
+ device->save_item(NAME(cpustate->gt0reg));
+ device->save_item(NAME(cpustate->fdxreg));
+ device->save_item(NAME(cpustate->field));
+ device->save_item(NAME(cpustate->clkcnt));
+
+ device->save_pointer(NAME(cpustate->sram), 4096);
+ device->save_pointer(NAME(cpustate->ptr_ram), 1024);
+ device->save_pointer(NAME(cpustate->e_stack), 32768);
+ device->save_pointer(NAME(cpustate->o_stack), 32768);
+}
+
+static CPU_INIT( cquestlin )
+{
+ const cubeqst_lin_config *linconfig = (const cubeqst_lin_config *)device->static_config();
+ cquestlin_state *cpustate = get_safe_token_lin(device);
+ memset(cpustate, 0, sizeof(*cpustate));
+
+ /* Allocate RAM */
+ cpustate->sram = auto_alloc_array(device->machine(), UINT16, 4096); /* Shared with rotate CPU */
+ cpustate->ptr_ram = auto_alloc_array(device->machine(), UINT8, 1024); /* Pointer RAM */
+ cpustate->e_stack = auto_alloc_array(device->machine(), UINT32, 32768); /* Stack DRAM: 32kx20 */
+ cpustate->o_stack = auto_alloc_array(device->machine(), UINT32, 32768); /* Stack DRAM: 32kx20 */
+
+ cpustate->device = device;
+ cpustate->rotdevice = device->machine().device<legacy_cpu_device>(linconfig->rot_cpu_tag);
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+
+ cquestlin_state_register(device);
+}
+
+
+static CPU_RESET( cquestlin )
+{
+ cquestlin_state *cpustate = get_safe_token_lin(device);
+ cpustate->clkcnt = 0;
+ cpustate->pc[FOREGROUND] = 0;
+ cpustate->pc[BACKGROUND] = 0x80;
+}
+
+
+static CPU_EXIT( cquestlin )
+{
+}
+
+
+/***************************************************************************
+ SOUND CORE EXECUTION LOOP
+***************************************************************************/
+
+#define SND_PC (cpustate->pc)
+#define SND_DATA_IN (_ramen ? cpustate->sound_data[cpustate->platch] : cpustate->dinlatch)
+
+enum snd_latch_type
+{
+ PLTCH = 0,
+ DAC = 1,
+ ADLATCH = 2,
+};
+
+static int do_sndjmp(cquestsnd_state *cpustate, int jmp)
+{
+ switch (jmp)
+ {
+ /* JUMP */ case 0: return 1;
+ /* MSB */ case 2: return cpustate->f & 0x8000 ? 0 : 1;
+ /* !MSB */ case 3: return cpustate->f & 0x8000 ? 1 : 0;
+ /* ZERO */ case 5: return cpustate->f == 0 ? 0 : 1;
+ /* OVR */ case 6: return cpustate->vflag ? 0 : 1;
+ /* LOOP */ case 7: return cpustate->adrcntr & 0x80 ? 0: 1;
+ }
+
+ return 0;
+}
+
+static CPU_EXECUTE( cquestsnd )
+{
+ cquestsnd_state *cpustate = get_safe_token_snd(device);
+ int calldebugger = ((device->machine().debug_flags & DEBUG_FLAG_ENABLED) != 0);
+
+ /* Core execution loop */
+ do
+ {
+ /* Decode the instruction */
+ UINT64 inst = cpustate->direct->read_decrypted_qword(SND_PC << 3);
+ UINT32 inslow = inst & 0xffffffff;
+ UINT32 inshig = inst >> 32;
+
+ int t = (inshig >> 24) & 0xff;
+ int b = (inshig >> 20) & 0xf;
+ int a = (inshig >> 16) & 0xf;
+ int ci = (inshig >> 15) & 1;
+ int i5_3 = (inshig >> 12) & 7;
+ int _ramen = (inshig >> 11) & 1;
+ int i2_0 = (inshig >> 8) & 7;
+ int rtnltch = (inshig >> 7) & 1;
+ int jmp = (inshig >> 4) & 7;
+ int inca = (inshig >> 3) & 1;
+ int i8_6 = (inshig >> 0) & 7;
+ int _ipram = (inslow >> 31) & 1;
+ int _ipwrt = (inslow >> 30) & 1;
+ int latch = (inslow >> 28) & 3;
+ int rtn = (inslow >> 27) & 1;
+ int _rin = (inslow >> 26) & 1;
+
+ if (calldebugger)
+ debugger_instruction_hook(device, cpustate->pc);
+
+ /* Don't think this matters, but just in case */
+ if (rtn)
+ t = cpustate->rtnlatch;
+
+ /* Handle the AM2901 ALU instruction */
+ {
+ UINT16 r = 0;
+ UINT16 s = 0;
+
+ UINT32 res = 0;
+ UINT32 cflag = 0;
+ UINT32 vflag = 0;
+
+ /* Determine the ALU sources */
+ switch (i2_0)
+ {
+ case AQ: r = cpustate->ram[a]; s = cpustate->q; break;
+ case AB: r = cpustate->ram[a]; s = cpustate->ram[b]; break;
+ case ZQ: r = 0; s = cpustate->q; break;
+ case ZB: r = 0; s = cpustate->ram[b]; break;
+ case ZA: r = 0; s = cpustate->ram[a]; break;
+ case DA: r = SND_DATA_IN; s = cpustate->ram[a]; break;
+ case DQ: r = SND_DATA_IN; s = cpustate->q; break;
+ case DZ: r = SND_DATA_IN; s = 0; break;
+ }
+
+ /* Perform the ALU operation */
+ switch (i5_3)
+ {
+ case ADD:
+ res = r + s + ci;
+ cflag = (res >> 16) & 1;
+ vflag = (((r & 0x7fff) + (s & 0x7fff) + ci) >> 15) ^ cflag;
+ break;
+ case SUBR:
+ res = ~r + s + ci;
+ cflag = (res >> 16) & 1;
+ vflag = (((s & 0x7fff) + (~r & 0x7fff) + ci) >> 15) ^ cflag;
+ break;
+ case SUBS:
+ res = r + ~s + ci;
+ cflag = (res >> 16) & 1;
+ vflag = (((r & 0x7fff) + (~s & 0x7fff) + ci) >> 15) ^ cflag;
+ break;
+ case OR:
+ res = r | s;
+ break;
+ case AND:
+ res = r & s;
+ break;
+ case NOTRS:
+ res = ~r & s;
+ break;
+ case EXOR:
+ res = r ^ s;
+ break;
+ case EXNOR:
+ res = ~(r ^ s);
+ break;
+ }
+
+ cpustate->f = res;
+ cpustate->cflag = cflag;
+ cpustate->vflag = vflag;
+
+ switch (i8_6)
+ {
+ case QREG:
+ cpustate->q = cpustate->f;
+ cpustate->y = cpustate->f;
+ break;
+ case NOP:
+ cpustate->y = cpustate->f;
+ break;
+ case RAMA:
+ cpustate->y = cpustate->ram[a];
+ cpustate->ram[b] = cpustate->f;
+ break;
+ case RAMF:
+ cpustate->ram[b] = cpustate->f;
+ cpustate->y = cpustate->f;
+ break;
+ case RAMQD:
+ {
+ UINT16 qin;
+
+ cpustate->ram[b] = (_rin ? 0 : 0x8000) | (cpustate->f >> 1);
+ cpustate->q >>= 1;
+ cpustate->y = cpustate->f;
+
+ /* When right shifting Q, we need to OR in a value */
+ qin = (((cpustate->y >> 15) ^ (cpustate->y >> 1)) & 1) ? 0 : 0x8000;
+
+ cpustate->q |= qin;
+ break;
+ }
+ case RAMD:
+ cpustate->ram[b] = (_rin ? 0 : 0x8000) | (cpustate->f >> 1);
+ cpustate->y = cpustate->f;
+ break;
+ case RAMQU:
+ cpustate->ram[b] = (cpustate->f << 1) | (_rin ? 0 : 0x0001);
+ cpustate->q <<= 1;
+ cpustate->y = cpustate->f;
+ break;
+ case RAMU:
+ cpustate->ram[b] = (cpustate->f << 1) | (_rin ? 0 : 0x0001);
+ cpustate->y = cpustate->f;
+ break;
+ }
+ }
+
+ /* Now handle any SRAM accesses from the previous cycle */
+ if (!cpustate->prev_ipram)
+ {
+ UINT16 addr = cpustate->adrlatch | (cpustate->adrcntr & 0x7f);
+
+ if (!cpustate->prev_ipwrt)
+ cpustate->sram[addr] = cpustate->ramwlatch;
+ else
+ cpustate->dinlatch = cpustate->sram[addr];
+ }
+
+ /* Handle latches */
+ if (latch == PLTCH)
+ {
+ cpustate->platch = ((t & 3) << 9) | ((cpustate->y >> 6) & 0x1ff);
+ }
+ else if (latch == DAC)
+ {
+ cpustate->dac_w(cpustate->device, (cpustate->y & 0xfff0) | ((cpustate->adrcntr >> 3) & 0xf));
+ }
+ else if (latch == ADLATCH)
+ {
+ /* Load the SRAM address counter - this value is instantly loaded */
+ cpustate->adrcntr = cpustate->y & 0x7f;
+
+ /* Also load the SRAM address latch */
+ cpustate->adrlatch = cpustate->y & 0x780;
+ }
+
+ /* Check for jump/return */
+ if ( do_sndjmp(cpustate, jmp) )
+ cpustate->pc = rtn ? cpustate->rtnlatch : t;
+ else
+ cpustate->pc++;
+
+ /* Load the return latch? (Obviously a load and a ret in the same cycle are invalid) */
+ if (rtnltch)
+ cpustate->rtnlatch = t;
+
+ /* Only increment the sound counter if not loading */
+ if (inca && latch != ADLATCH)
+ cpustate->adrcntr++;
+
+ /* Latch data for a RAM write (do actual write on the next cycle) */
+ if (!_ipwrt)
+ cpustate->ramwlatch = cpustate->y;
+
+ /* Save level sensitive bits */
+ cpustate->prev_ipram = _ipram;
+ cpustate->prev_ipwrt = _ipwrt;
+
+ cpustate->icount--;
+ } while (cpustate->icount > 0);
+}
+
+
+/***************************************************************************
+ ROTATE CORE EXECUTION LOOP
+***************************************************************************/
+
+#define ROT_PC (cpustate->pc & 0x1ff)
+
+enum rot_spf
+{
+ SPF_UNUSED0 = 0,
+ SPF_UNUSED1 = 1,
+ SPF_OP = 2,
+ SPF_RET = 3,
+ SPF_SQLTCH = 4,
+ SPF_SWRT = 5,
+ SPF_DIV = 6,
+ SPF_MULT = 7,
+ SPF_DRED = 8,
+ SPF_DWRT = 9,
+};
+
+enum rot_yout
+{
+ YOUT_UNUSED0 = 0,
+ YOUT_UNUSED1 = 1,
+ YOUT_Y2LDA = 2,
+ YOUT_Y2LDD = 3,
+ YOUT_Y2DAD = 4,
+ YOUT_Y2DYN = 5,
+ YOUT_Y2R = 6,
+ YOUT_Y2D = 7,
+};
+
+/* Sync is asserted for the duration of every fourth cycle */
+/* The Dynamic RAM latch clocks in a value at the end of this cycle */
+/* So CPU waits for sync before reading from DRAM */
+
+INLINE int do_rotjmp(cquestrot_state *cpustate, int jmp)
+{
+ int ret = 0;
+
+ switch (jmp & 7)
+ {
+ /* */ case 0: ret = 0; break;
+ /* SEQ */ case 1: ret = (cpustate->seqcnt == 0xf); break;
+ /* CAROUT */ case 2: ret = cpustate->cflag; break;
+ /* SYNC */ case 3: ret = !(cpustate->clkcnt & 0x3); break;
+ /* LDWAIT */ case 4: ret = 0; break;
+ /* MSB */ case 5: ret = BIT(cpustate->f, 15); break;
+ /* >=1 */ case 6: ret = (!_BIT(cpustate->f, 15) && !(cpustate->f == 0)); break;
+ /* ZERO */ case 7: ret = (cpustate->f == 0); break;
+ }
+
+ return !(!ret ^ BIT(jmp, 3));
+}
+
+
+#define ROT_SRAM_ADDRESS ((cpustate->dsrclatch & 2) ? cpustate->yrlatch : (cpustate->rsrclatch | 0x700))
+
+
+static CPU_EXECUTE( cquestrot )
+{
+ cquestrot_state *cpustate = get_safe_token_rot(device);
+ cquestlin_state *lincpustate = get_safe_token_lin(cpustate->lindevice);
+ int calldebugger = ((device->machine().debug_flags & DEBUG_FLAG_ENABLED) != 0);
+
+ /* Core execution loop */
+ do
+ {
+ /* Decode the instruction */
+ UINT64 inst = cpustate->direct->read_decrypted_qword(ROT_PC << 3);
+
+ UINT32 inslow = inst & 0xffffffff;
+ UINT32 inshig = inst >> 32;
+
+ int t = (inshig >> 20) & 0xfff;
+ int jmp = (inshig >> 16) & 0xf;
+ int spf = (inshig >> 12) & 0xf;
+ int rsrc = (inshig >> 11) & 0x1;
+ int yout = (inshig >> 8) & 0x7;
+ int sel = (inshig >> 6) & 0x3;
+ int dsrc = (inshig >> 4) & 0x3;
+ int b = (inshig >> 0) & 0xf;
+ int a = (inslow >> 28) & 0xf;
+ int i8_6 = (inslow >> 24) & 0x7;
+ int ci = (inslow >> 23) & 0x1;
+ int i5_3 = (inslow >> 20) & 0x7;
+ int _sex = (inslow >> 19) & 0x1;
+ int i2_0 = (inslow >> 16) & 0x7;
+
+ int dsrclatch;
+ UINT16 data_in = 0xffff;
+
+ if (calldebugger)
+ debugger_instruction_hook(device, ROT_PC);
+
+ /* Handle DRAM accesses - I ought to check this... */
+ if (!(cpustate->clkcnt & 3))
+ {
+ if (cpustate->wc)
+ {
+ cpustate->wc = 0;
+ cpustate->dram[cpustate->dynaddr & 0x3fff] = cpustate->dyndata;
+ }
+ if (cpustate->rc)
+ {
+ cpustate->rc = 0;
+ cpustate->dinlatch = cpustate->dram[cpustate->dynaddr & 0x3fff];
+ }
+ }
+
+ /* Flag pending DRAM accesses */
+ if (!cpustate->prev_dwrt)
+ cpustate->wc = 1;
+ else if (!cpustate->prev_dred)
+ cpustate->rc = 1;
+
+ /* What's on the D-Bus? */
+ if (~cpustate->dsrclatch & 0x10)
+ data_in = cpustate->dinlatch;
+ else if (~cpustate->dsrclatch & 0x20)
+ data_in = cpustate->sram[ROT_SRAM_ADDRESS];
+ else if (~cpustate->dsrclatch & 0x40)
+ data_in = cpustate->ydlatch;
+ else if (~cpustate->dsrclatch & 0x80)
+ data_in = t & 0xfff;
+
+ /* What's on the T-Bus? */
+ if ((spf == SPF_RET) && (cpustate->dsrclatch & 0x80))
+ t = data_in;
+ else if (spf == SPF_OP)
+ t = (t & ~0xf) | (data_in >> 12);
+
+
+ if (~cpustate->dsrclatch & 1)
+ cpustate->sram[ROT_SRAM_ADDRESS] = data_in;
+
+
+ /* Sign extend ALU input? */
+ if (!_sex)
+ data_in = (data_in & ~0xf000) | ((data_in & 0x800) ? 0xf000 : 0);
+
+ /* No do the ALU operation */
+ {
+ UINT16 r = 0;
+ UINT16 s = 0;
+
+ UINT32 res = 0;
+ UINT32 cflag = 0;
+ UINT32 vflag = 0;
+
+ /* First, determine correct I1 bit */
+ if ((spf == SPF_MULT) && !_BIT(cpustate->q, 0))
+ i2_0 |= 2;
+
+ /* Determine the ALU sources */
+ switch (i2_0)
+ {
+ case 0: r = cpustate->ram[a]; s = cpustate->q; break;
+ case 1: r = cpustate->ram[a]; s = cpustate->ram[b]; break;
+ case 2: r = 0; s = cpustate->q; break;
+ case 3: r = 0; s = cpustate->ram[b]; break;
+ case 4: r = 0; s = cpustate->ram[a]; break;
+ case 5: r = data_in; s = cpustate->ram[a]; break;
+ case 6: r = data_in; s = cpustate->q; break;
+ case 7: r = data_in; s = 0; break;
+ }
+
+ /* Next, determine the I3 and carry bits */
+ if ((spf == SPF_DIV) && cpustate->divreg)
+ {
+ i5_3 |= 1;
+ ci = 1;
+ }
+
+ /* Perform the ALU operation */
+ switch (i5_3)
+ {
+ case ADD:
+ res = r + s + ci;
+ cflag = (res >> 16) & 1;
+ vflag = (((r & 0x7fff) + (s & 0x7fff) + ci) >> 15) ^ cflag;
+ break;
+ case SUBR:
+ res = ~r + s + ci;
+ cflag = (res >> 16) & 1;
+ vflag = (((s & 0x7fff) + (~r & 0x7fff) + ci) >> 15) ^ cflag;
+ break;
+ case SUBS:
+ res = r + ~s + ci;
+ cflag = (res >> 16) & 1;
+ vflag = (((r & 0x7fff) + (~s & 0x7fff) + ci) >> 15) ^ cflag;
+ break;
+ case OR:
+ res = r | s;
+ break;
+ case AND:
+ res = r & s;
+ break;
+ case NOTRS:
+ res = ~r & s;
+ break;
+ case EXOR:
+ res = r ^ s;
+ break;
+ case EXNOR:
+ res = ~(r ^ s);
+ break;
+ }
+
+ cpustate->f = res;
+ cpustate->cflag = cflag;
+ cpustate->vflag = vflag;
+
+ switch (i8_6)
+ {
+ case QREG:
+ cpustate->q = cpustate->f;
+ cpustate->y = cpustate->f;
+ break;
+ case NOP:
+ cpustate->y = cpustate->f;
+ break;
+ case RAMA:
+ cpustate->y = cpustate->ram[a];
+ cpustate->ram[b] = cpustate->f;
+ break;
+ case RAMF:
+ cpustate->ram[b] = cpustate->f;
+ cpustate->y = cpustate->f;
+ break;
+ case RAMQD:
+ {
+ UINT16 q0 = cpustate->q & 1;
+ UINT16 r0 = cpustate->f & 1;
+ UINT16 q15 = 0;
+ UINT16 r15 = 0;
+
+ /* Determine Q15 and RAM15 */
+ switch (sel)
+ {
+ case 0: q15 = r15 = 0;
+ break;
+ case 1: q15 = r15 = 0x8000;
+ break;
+ case 2: q15 = q0 << 15;
+ r15 = r0 << 15;
+ break;
+ case 3: q15 = r0 << 15;
+ r15 = (cpustate->vflag ^ BIT(cpustate->f, 15)) << 15;
+ break;
+ }
+
+ cpustate->ram[b] = r15 | (cpustate->f >> 1);
+ cpustate->q = q15 | (cpustate->q >> 1);
+ cpustate->y = cpustate->f;
+ break;
+ }
+ case RAMD:
+ {
+ UINT16 r0 = cpustate->f & 1;
+ UINT16 r15 = 0;
+
+ switch (sel)
+ {
+ case 0: r15 = 0; break;
+ case 1: r15 = 0x8000; break;
+ case 2: r15 = r0 << 15; break;
+ case 3:
+ r15 = (cpustate->vflag ^ BIT(cpustate->f, 15)) << 15;
+ break;
+ }
+
+ cpustate->ram[b] = r15 | (cpustate->f >> 1);
+ cpustate->y = cpustate->f;
+ break;
+ }
+ case RAMQU:
+ {
+ UINT16 q15 = BIT(cpustate->q, 15);
+ UINT16 r15 = BIT(cpustate->f, 15);
+ UINT16 q0 = 0;
+ UINT16 r0 = 0;
+
+ switch (sel)
+ {
+ case 0: q0 = 0; r0 = 0; break;
+ case 1: q0 = 1; r0 = 1; break;
+ case 2: q0 = q15; r0 = r15; break;
+ case 3:
+ {
+ q0 = (spf == SPF_DIV) && !BIT(cpustate->f, 15);
+ r0 = q15;
+ break;
+ }
+ }
+
+ cpustate->ram[b] = (cpustate->f << 1) | r0;
+ cpustate->q = (cpustate->q << 1) | q0;
+ cpustate->y = cpustate->f;
+ break;
+ }
+ case RAMU:
+ {
+
+ UINT16 q15 = BIT(cpustate->q, 15);
+ UINT16 r15 = BIT(cpustate->f, 15);
+ UINT16 r0 = 0;
+
+ switch (sel)
+ {
+ case 0: r0 = 0; break;
+ case 1: r0 = 1; break;
+ case 2: r0 = r15; break;
+ case 3: r0 = q15; break;
+ }
+
+ cpustate->ram[b] = (cpustate->f << 1) | r0;
+ cpustate->y = cpustate->f;
+ break;
+ }
+ }
+ }
+
+ /* Check for jump */
+ if ( do_rotjmp(cpustate, jmp) )
+ cpustate->pc = t;
+ else
+ cpustate->pc = (cpustate->pc + 1) & 0xfff;
+
+ /* Rising edge; update the sequence counter */
+ if (spf == SPF_SQLTCH)
+ cpustate->seqcnt = t & 0xf;
+ else if ( (spf == SPF_MULT) || (spf == SPF_DIV) )
+ cpustate->seqcnt = (cpustate->seqcnt + 1) & 0xf;
+
+ /* Rising edge; write data source reg */
+ dsrclatch =
+ (~(0x10 << dsrc) & 0xf0)
+ | (rsrc ? 0x04 : 0x02)
+ | !(spf == SPF_SWRT);
+
+ /* R-latch is written on rising edge of dsrclatch bit 2 */
+ if (!_BIT(cpustate->dsrclatch, 2) && _BIT(dsrclatch, 2))
+ cpustate->rsrclatch = t & 0xff;
+
+ cpustate->dsrclatch = dsrclatch;
+
+ /* Handle latching on rising edge */
+ switch (yout)
+ {
+ case YOUT_Y2LDA:
+ {
+ cpustate->lineaddr = cpustate->y & 0xfff;
+ break;
+ }
+ case YOUT_Y2LDD:
+ {
+ cpustate->linedata = ((t & 0xf) << 12) | (cpustate->y & 0xfff);
+ lincpustate->sram[cpustate->lineaddr] = cpustate->linedata;
+ break;
+ }
+ case YOUT_Y2DAD: cpustate->dynaddr = cpustate->y & 0x3fff; break;
+ case YOUT_Y2DYN: cpustate->dyndata = cpustate->y & 0xffff; break;
+ case YOUT_Y2R: cpustate->yrlatch = cpustate->y & 0x7ff; break;
+ case YOUT_Y2D: cpustate->ydlatch = cpustate->y; break;
+ }
+
+ /* Clock in the divide register */
+ cpustate->divreg = (spf == SPF_DIV) && !_BIT(cpustate->f, 15);
+
+ /* DRAM accessing */
+ cpustate->prev_dred = !(spf == SPF_DRED);
+ cpustate->prev_dwrt = !(spf == SPF_DWRT);
+
+ cpustate->clkcnt++;
+ cpustate->icount--;
+ } while (cpustate->icount > 0);
+}
+
+
+/***************************************************************************
+ LINE DRAWER CORE EXECUTION LOOP
+***************************************************************************/
+
+#define VISIBLE_FIELD !cpustate->field
+
+enum line_spf
+{
+ LSPF_UNUSED = 0,
+ LSPF_FSTOP = 1,
+ LSPF_SREG = 2,
+ LSPF_FSTRT = 3,
+ LSPF_PWRT = 4,
+ LSPF_MULT = 5,
+ LSPF_LSTOP = 6,
+ LSPF_BRES = 7,
+};
+
+enum line_latch
+{
+ LLATCH_UNUSED = 0,
+ LLATCH_SEQLATCH = 1,
+ LLATCH_XLATCH = 2,
+ LLATCH_YLATCH = 3,
+ LLATCH_BADLATCH = 4,
+ LLATCH_FADLATCH = 5,
+ LLATCH_CLATCH = 6,
+ LLATCH_ZLATCH = 7,
+};
+
+enum sreg_bits
+{
+ SREG_E0 = 0,
+ SREG_DX_DY = 1,
+ SREG_DY = 2,
+ SREG_DX = 3,
+ SREG_LE0 = 4,
+ SREG_LDX_DY = 5,
+ SREG_LDY = 6,
+ SREG_LDX = 7,
+};
+
+INLINE int do_linjmp(cquestlin_state *cpustate, int jmp)
+{
+ int ret = 0;
+
+ switch (jmp & 7)
+ {
+ /* */ case 0: ret = 0; break;
+ /* MSB */ case 1: ret = BIT(cpustate->f, 11); break;
+ /* SEQ */ case 2: ret = (cpustate->seqcnt == 0xfff); break;
+ /* >0 */ case 3: ret = !(cpustate->f == 0) && !_BIT(cpustate->f, 11); break;
+ /* CAROUT */ case 4: ret = (cpustate->cflag); break;
+ /* ZERO */ case 5: ret = (cpustate->f == 0); break;
+ }
+
+ return !(!ret ^ BIT(jmp, 3));
+}
+
+
+
+void cubeqcpu_swap_line_banks(device_t *device)
+{
+ cquestlin_state *cpustate = get_safe_token_lin(device);
+ cpustate->field = cpustate->field ^ 1;
+}
+
+
+void cubeqcpu_clear_stack(device_t *device)
+{
+ cquestlin_state *cpustate = get_safe_token_lin(device);
+ memset(&cpustate->ptr_ram[cpustate->field * 256], 0, 256);
+}
+
+UINT8 cubeqcpu_get_ptr_ram_val(device_t *device, int i)
+{
+ cquestlin_state *cpustate = get_safe_token_lin(device);
+ return cpustate->ptr_ram[(VISIBLE_FIELD * 256) + i];
+}
+
+UINT32* cubeqcpu_get_stack_ram(device_t *device)
+{
+ cquestlin_state *cpustate = get_safe_token_lin(device);
+ if (VISIBLE_FIELD == ODD_FIELD)
+ return cpustate->o_stack;
+ else
+ return cpustate->e_stack;
+}
+
+
+static CPU_EXECUTE( cquestlin )
+{
+#define LINE_PC ((cpustate->pc[prog] & 0x7f) | ((prog == BACKGROUND) ? 0x80 : 0))
+
+ cquestlin_state *cpustate = get_safe_token_lin(device);
+ cquestrot_state *rotcpustate = get_safe_token_rot(cpustate->rotdevice);
+ int calldebugger = ((device->machine().debug_flags & DEBUG_FLAG_ENABLED) != 0);
+ UINT32 *stack_ram;
+ UINT8 *ptr_ram;
+
+ /* Check the field and set the stack/pointer RAM pointers appropriately */
+ if (cpustate->field == ODD_FIELD)
+ {
+ stack_ram = cpustate->o_stack;
+ ptr_ram = &cpustate->ptr_ram[0];
+ }
+ else
+ {
+ stack_ram = cpustate->e_stack;
+ ptr_ram = &cpustate->ptr_ram[0x100];
+ }
+
+ /* Core execution loop */
+ do
+ {
+ /* Are we executing the foreground or backgroud program? */
+ int prog = (cpustate->clkcnt & 3) ? BACKGROUND : FOREGROUND;
+
+ UINT64 inst = cpustate->direct->read_decrypted_qword(LINE_PC << 3);
+
+ UINT32 inslow = inst & 0xffffffff;
+ UINT32 inshig = inst >> 32;
+
+ int t = (inshig >> 24) & 0xff;
+ int jmp = (inshig >> 20) & 0xf;
+ int latch = (inshig >> 16) & 0x7;
+ int op = (inshig >> 15) & 0x1;
+ int spf = (inshig >> 12) & 0x7;
+ int b = (inshig >> 8) & 0xf;
+ int a = (inshig >> 4) & 0xf;
+ int i8_6 = (inshig >> 0) & 0x7;
+ int ci = (inslow >> 31) & 0x1;
+ int i5_3 = (inslow >> 28) & 0x7;
+ int _pbcs = (inslow >> 27) & 0x1;
+ int i2_0 = (inslow >> 24) & 0x7;
+
+ UINT16 data_in = 0;
+
+ if (calldebugger)
+ debugger_instruction_hook(device, cpustate->pc[prog]);
+
+ /* Handle accesses to and from shared SRAM */
+ if (prog == FOREGROUND)
+ {
+ if (!_BIT(cpustate->fglatch, 5))
+ data_in = cpustate->sram[cpustate->fadlatch];
+ else
+ data_in = rotcpustate->linedata;
+ }
+ else
+ {
+ if (!_BIT(cpustate->bglatch, 4))
+ cpustate->sram[cpustate->badlatch] = cpustate->sramdlatch;
+ else if (_BIT(cpustate->bglatch, 2))
+ data_in = cpustate->sram[cpustate->badlatch];
+ else
+ data_in = rotcpustate->linedata;
+ }
+
+ /* Handle a write to stack RAM (/DOWRT) */
+ if ((cpustate->clkcnt & 3) == 1)
+ {
+ if (_BIT(cpustate->fglatch, 4) && (cpustate->ycnt < 256))
+ {
+ /* 20-bit words */
+ UINT32 data;
+ UINT16 h = cpustate->xcnt;
+ UINT8 v = cpustate->ycnt & 0xff;
+
+ /* Clamp H between 0 and 319 */
+ if (h >= 320)
+ h = (h & 0x800) ? 0 : 319;
+
+ /* Stack word type depends on STOP/#START bit */
+ if ( _BIT(cpustate->fglatch, 3) )
+ data = (0 << 19) | (h << 8) | cpustate->zlatch;
+ else
+ data = (1 << 19) | ((cpustate->clatch & 0x100) << 9) | (h << 8) | (cpustate->clatch & 0xff);
+
+ stack_ram[(v << 7) | (ptr_ram[v] & 0x7f)] = data;
+
+ /* Also increment the pointer RAM entry. Note that it cannot exceed 128 */
+ ptr_ram[v] = (ptr_ram[v] + 1) & 0x7f;
+ }
+ }
+
+ /* Override T3-0? */
+ if (op)
+ t = (t & ~0xf) | (data_in >> 12);
+
+ /* Determine the correct I1 bit */
+ if ((spf == LSPF_MULT) && !_BIT(cpustate->q, 0))
+ i2_0 |= 2;
+
+ /* Determine A0 (BRESA0) */
+ if ((prog == FOREGROUND) && !_BIT(cpustate->fglatch, 2))
+ a |= cpustate->gt0reg;
+
+ /* Now do the ALU operation */
+ {
+ UINT16 r = 0;
+ UINT16 s = 0;
+
+ UINT16 res = 0;
+ UINT32 cflag = 0;
+ UINT32 vflag = 0;
+
+ /* Determine the ALU sources */
+ switch (i2_0)
+ {
+ case 0: r = cpustate->ram[a]; s = cpustate->q; break;
+ case 1: r = cpustate->ram[a]; s = cpustate->ram[b]; break;
+ case 2: r = 0; s = cpustate->q; break;
+ case 3: r = 0; s = cpustate->ram[b]; break;
+ case 4: r = 0; s = cpustate->ram[a]; break;
+ case 5: r = data_in; s = cpustate->ram[a]; break;
+ case 6: r = data_in; s = cpustate->q; break;
+ case 7: r = data_in; s = 0; break;
+ }
+
+ /* 12-bits */
+ r &= 0xfff;
+ s &= 0xfff;
+
+ /* Perform the 12-bit ALU operation */
+ switch (i5_3)
+ {
+ case ADD:
+ res = r + s + ci;
+ cflag = (res >> 12) & 1;
+ vflag = (((r & 0x7ff) + (s & 0x7ff) + ci) >> 11) ^ cflag;
+ break;
+ case SUBR:
+ res = (r ^ 0x0FFF) + s + ci;
+ cflag = (res >> 12) & 1;
+ vflag = (((s & 0x7ff) + (~r & 0x7ff) + ci) >> 11) ^ cflag;
+ break;
+ case SUBS:
+ res = r + (s ^ 0x0FFF) + ci;
+ cflag = (res >> 12) & 1;
+ vflag = (((r & 0x7ff) + (~s & 0x7ff) + ci) >> 11) ^ cflag;
+ break;
+ case OR:
+ res = r | s;
+ break;
+ case AND:
+ res = r & s;
+ break;
+ case NOTRS:
+ res = ~r & s;
+ break;
+ case EXOR:
+ res = r ^ s;
+ break;
+ case EXNOR:
+ res = ~(r ^ s);
+ break;
+ }
+
+ cpustate->f = res & 0xfff;
+ cpustate->cflag = cflag;
+ cpustate->vflag = vflag;
+
+ switch (i8_6)
+ {
+ case QREG:
+ cpustate->q = cpustate->f;
+ cpustate->y = cpustate->f;
+ break;
+ case NOP:
+ cpustate->y = cpustate->f;
+ break;
+ case RAMA:
+ cpustate->y = cpustate->ram[a];
+ cpustate->ram[b] = cpustate->f;
+ break;
+ case RAMF:
+ cpustate->ram[b] = cpustate->f;
+ cpustate->y = cpustate->f;
+ break;
+ case RAMQD:
+ {
+ UINT16 r11 = (BIT(cpustate->f, 11) ^ cpustate->vflag) ? 0x800 : 0;
+ UINT16 q11 = (prog == BACKGROUND) ? 0x800 : 0;
+
+ cpustate->ram[b] = r11 | (cpustate->f >> 1);
+ cpustate->q = q11 | (cpustate->q >> 1);
+ cpustate->y = cpustate->f;
+ break;
+ }
+ case RAMD:
+ {
+ UINT16 r11 = (BIT(cpustate->f, 11) ^ cpustate->vflag) ? 0x800 : 0;
+
+ cpustate->ram[b] = r11 | (cpustate->f >> 1);
+ cpustate->y = cpustate->f;
+ break;
+ }
+ case RAMQU:
+ {
+ /* Determine shift inputs */
+ UINT16 r0 = (prog == BACKGROUND);
+
+ /* This should never happen - Q0 will be invalid */
+ cpustate->ram[b] = (cpustate->f << 1) | r0;
+ cpustate->q = (cpustate->q << 1) | 0;
+ cpustate->y = cpustate->f;
+ break;
+ }
+ case RAMU:
+ {
+ UINT16 r0 = (prog == BACKGROUND);
+
+ cpustate->ram[b] = (cpustate->f << 1) | r0;
+ cpustate->y = cpustate->f;
+ break;
+ }
+ }
+ }
+
+ /* Adjust program counter */
+ if ( do_linjmp(cpustate, jmp) )
+ cpustate->pc[prog] = t & 0x7f;
+ else
+ cpustate->pc[prog] = (cpustate->pc[prog] + 1) & 0x7f;
+
+ if (prog == BACKGROUND)
+ cpustate->pc[prog] |= 0x80;
+ else
+ {
+ /* Handle events that happen during FG execution */
+ if (latch == LLATCH_XLATCH)
+ cpustate->xcnt = cpustate->y & 0xfff;
+ else
+ {
+ int _xcet;
+ int mux_sel = (BIT(cpustate->sreg, SREG_DX_DY) << 1) | (BIT(cpustate->sreg, SREG_DX) ^ BIT(cpustate->sreg, SREG_DY));
+
+ if (mux_sel == 0)
+ _xcet = !(spf == LSPF_BRES);
+ else if (mux_sel == 1)
+ _xcet = _BIT(cpustate->fglatch, 1);
+ else if (mux_sel == 2)
+ _xcet = !(cpustate->gt0reg && (spf == LSPF_BRES));
+ else
+ _xcet = _BIT(cpustate->fglatch, 0);
+
+ if (!_xcet)
+ cpustate->xcnt = (cpustate->xcnt + (_BIT(cpustate->sreg, SREG_DX) ? 1 : -1)) & 0xfff;
+ }
+
+ if (latch == LLATCH_YLATCH)
+ cpustate->ycnt = cpustate->y & 0xfff;
+ else
+ {
+ int _ycet;
+ int mux_sel = (BIT(cpustate->sreg, SREG_DX_DY) << 1) | (BIT(cpustate->sreg, SREG_DX) ^ BIT(cpustate->sreg, SREG_DY));
+
+ if (mux_sel == 0)
+ _ycet = !(cpustate->gt0reg && (spf == LSPF_BRES));
+ else if (mux_sel == 1)
+ _ycet = _BIT(cpustate->fglatch, 0);
+ else if (mux_sel == 2)
+ _ycet = !(spf == LSPF_BRES);
+ else
+ _ycet = _BIT(cpustate->fglatch, 1);
+
+ if (!_ycet)
+ cpustate->ycnt = (cpustate->ycnt + (_BIT(cpustate->sreg, SREG_DY) ? 1 : -1)) & 0xfff;
+ }
+ }
+
+ if (latch == LLATCH_CLATCH)
+ cpustate->clatch = cpustate->y & 0x1ff;
+ else if (latch == LLATCH_ZLATCH)
+ cpustate->zlatch = cpustate->y & 0xff;
+ else if (latch == LLATCH_FADLATCH)
+ cpustate->fadlatch = cpustate->y & 0xfff;
+ else if (latch == LLATCH_BADLATCH)
+ cpustate->badlatch = cpustate->y & 0xfff;
+
+ /* What about the SRAM dlatch? */
+ if ( !_BIT(cpustate->bglatch, 5) )
+ cpustate->sramdlatch = ((t & 0xf) << 12) | (cpustate->y & 0x0fff);
+
+ /* BG and FG latches */
+ if (prog == FOREGROUND)
+ {
+ int mux_sel = (!(spf == LSPF_FSTOP) << 1) | !(spf == LSPF_LSTOP);
+ int dowrt;
+ int start_stop;
+
+ /* Handle the stack write and start/stop mux */
+ if (mux_sel == 0)
+ {
+ dowrt = 0;
+ start_stop = 0;
+ }
+ else if (mux_sel == 1)
+ {
+ dowrt = cpustate->fdxreg ^ BIT(cpustate->sreg, SREG_DX);
+ start_stop = cpustate->fdxreg;
+ }
+ else if (mux_sel == 2)
+ {
+ dowrt = BIT(cpustate->sreg, SREG_LDX) ^ BIT(cpustate->sreg, SREG_DX);
+ start_stop = BIT(cpustate->sreg, SREG_DX);
+ }
+ else
+ {
+ dowrt = (spf == LSPF_BRES) && (_BIT(cpustate->sreg, SREG_DX_DY) || cpustate->gt0reg);
+ start_stop = BIT(cpustate->sreg, SREG_DY);
+ }
+
+ cpustate->fglatch =
+ (!(latch == LLATCH_FADLATCH) << 5)
+ | (dowrt << 4)
+ | (start_stop << 3)
+ | (_pbcs << 2)
+ | (!(spf == LSPF_BRES) << 1)
+ | !(cpustate->gt0reg && (spf == LSPF_BRES));
+ }
+ else
+ {
+ int _lpwrt = BIT(cpustate->bglatch, 5);
+
+ cpustate->bglatch =
+ (!(spf == LSPF_PWRT) << 5)
+ | (_lpwrt << 4)
+ | ((!_lpwrt || (!(spf == LSPF_PWRT) && (latch == LLATCH_BADLATCH))) << 2);
+ }
+
+ /* Clock-in another bit into the sign bit shifter? */
+ if (spf == LSPF_SREG)
+ {
+ /* The sign bit is inverted */
+ cpustate->sreg = (cpustate->sreg << 1) | !BIT(cpustate->f, 11);
+
+ /* Also latch the >0 reg */
+ cpustate->gt0reg = !(cpustate->f == 0) && !_BIT(cpustate->f, 11);
+ }
+ else if (spf == LSPF_FSTRT)
+ {
+ cpustate->fdxreg = BIT(cpustate->sreg, 3);
+ }
+
+ /* Load or increment sequence counter? */
+ if (latch == LLATCH_SEQLATCH)
+ {
+ cpustate->seqcnt = cpustate->y & 0xfff;
+ }
+ else if (spf == LSPF_BRES)
+ {
+ cpustate->seqcnt = (cpustate->seqcnt + 1) & 0xfff;
+
+ /* Also latch the >0 reg */
+ cpustate->gt0reg = !(cpustate->f == 0) && !_BIT(cpustate->f, 11);
+ }
+
+ cpustate->icount--;
+ cpustate->clkcnt++;
+ } while (cpustate->icount > 0);
+}
+
+
+/**************************************************************************
+ * Sound set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( cquestsnd )
+{
+ cquestsnd_state *cpustate = get_safe_token_snd(device);
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + CQUESTSND_PC: cpustate->pc = info->i; break;
+ case CPUINFO_INT_REGISTER + CQUESTSND_Q: cpustate->q = info->i; break;
+ case CPUINFO_INT_REGISTER + CQUESTSND_RTNLATCH: cpustate->rtnlatch = info->i; break;
+ case CPUINFO_INT_REGISTER + CQUESTSND_ADRCNTR: cpustate->adrcntr = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTSND_DINLATCH: cpustate->dinlatch = info->i; break;
+
+ case CPUINFO_STR_REGISTER + CQUESTSND_RAM0: cpustate->ram[0x0] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTSND_RAM1: cpustate->ram[0x1] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTSND_RAM2: cpustate->ram[0x2] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTSND_RAM3: cpustate->ram[0x3] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTSND_RAM4: cpustate->ram[0x4] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTSND_RAM5: cpustate->ram[0x5] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTSND_RAM6: cpustate->ram[0x6] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTSND_RAM7: cpustate->ram[0x7] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTSND_RAM8: cpustate->ram[0x8] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTSND_RAM9: cpustate->ram[0x9] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTSND_RAMA: cpustate->ram[0xa] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTSND_RAMB: cpustate->ram[0xb] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTSND_RAMC: cpustate->ram[0xc] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTSND_RAMD: cpustate->ram[0xd] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTSND_RAME: cpustate->ram[0xe] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTSND_RAMF: cpustate->ram[0xf] = info->i; break;
+ }
+}
+
+/**************************************************************************
+ * Sound get_info
+ **************************************************************************/
+
+CPU_GET_INFO( cquestsnd )
+{
+ cquestsnd_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token_snd(device) : NULL;
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(cquestsnd_state); break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 8; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 8; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 1; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 64; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = -3; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + CQUESTSND_PC: info->i = cpustate->pc; break;
+ case CPUINFO_INT_REGISTER + CQUESTSND_RTNLATCH: info->i = cpustate->rtnlatch; break;
+ case CPUINFO_INT_REGISTER + CQUESTSND_ADRCNTR: info->i = cpustate->adrcntr; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(cquestsnd); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(cquestsnd); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(cquestsnd); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(cquestsnd); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(cquestsnd); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(cquestsnd); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "Sound CPU");break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Cube Quest"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Philip J Bennett"); break;
+
+ case CPUINFO_STR_FLAGS: sprintf(info->s, "......."); break;
+ case CPUINFO_STR_REGISTER + CQUESTSND_PC: sprintf(info->s, "PC: %02X", cpustate->pc); break;
+ case CPUINFO_STR_REGISTER + CQUESTSND_Q: sprintf(info->s, "Q: %04X", cpustate->q); break;
+ case CPUINFO_STR_REGISTER + CQUESTSND_RTNLATCH: sprintf(info->s, "RTN: %02X", cpustate->rtnlatch); break;
+ case CPUINFO_STR_REGISTER + CQUESTSND_ADRCNTR: sprintf(info->s, "CNT: %02X", cpustate->adrcntr); break;
+ case CPUINFO_STR_REGISTER + CQUESTSND_DINLATCH: sprintf(info->s, "DIN: %04X", cpustate->dinlatch); break;
+ case CPUINFO_STR_REGISTER + CQUESTSND_RAM0: sprintf(info->s, "RAM[0]: %04X", cpustate->ram[0x0]); break;
+ case CPUINFO_STR_REGISTER + CQUESTSND_RAM1: sprintf(info->s, "RAM[1]: %04X", cpustate->ram[0x1]); break;
+ case CPUINFO_STR_REGISTER + CQUESTSND_RAM2: sprintf(info->s, "RAM[2]: %04X", cpustate->ram[0x2]); break;
+ case CPUINFO_STR_REGISTER + CQUESTSND_RAM3: sprintf(info->s, "RAM[3]: %04X", cpustate->ram[0x3]); break;
+ case CPUINFO_STR_REGISTER + CQUESTSND_RAM4: sprintf(info->s, "RAM[4]: %04X", cpustate->ram[0x4]); break;
+ case CPUINFO_STR_REGISTER + CQUESTSND_RAM5: sprintf(info->s, "RAM[5]: %04X", cpustate->ram[0x5]); break;
+ case CPUINFO_STR_REGISTER + CQUESTSND_RAM6: sprintf(info->s, "RAM[6]: %04X", cpustate->ram[0x6]); break;
+ case CPUINFO_STR_REGISTER + CQUESTSND_RAM7: sprintf(info->s, "RAM[7]: %04X", cpustate->ram[0x7]); break;
+ case CPUINFO_STR_REGISTER + CQUESTSND_RAM8: sprintf(info->s, "RAM[8]: %04X", cpustate->ram[0x8]); break;
+ case CPUINFO_STR_REGISTER + CQUESTSND_RAM9: sprintf(info->s, "RAM[9]: %04X", cpustate->ram[0x9]); break;
+ case CPUINFO_STR_REGISTER + CQUESTSND_RAMA: sprintf(info->s, "RAM[A]: %04X", cpustate->ram[0xa]); break;
+ case CPUINFO_STR_REGISTER + CQUESTSND_RAMB: sprintf(info->s, "RAM[B]: %04X", cpustate->ram[0xb]); break;
+ case CPUINFO_STR_REGISTER + CQUESTSND_RAMC: sprintf(info->s, "RAM[C]: %04X", cpustate->ram[0xc]); break;
+ case CPUINFO_STR_REGISTER + CQUESTSND_RAMD: sprintf(info->s, "RAM[D]: %04X", cpustate->ram[0xd]); break;
+ case CPUINFO_STR_REGISTER + CQUESTSND_RAME: sprintf(info->s, "RAM[E]: %04X", cpustate->ram[0xe]); break;
+ case CPUINFO_STR_REGISTER + CQUESTSND_RAMF: sprintf(info->s, "RAM[F]: %04X", cpustate->ram[0xf]); break;
+ }
+}
+
+
+/**************************************************************************
+ * Rotate set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( cquestrot )
+{
+ cquestrot_state *cpustate = get_safe_token_rot(device);
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + CQUESTROT_PC: cpustate->pc = info->i; break;
+ case CPUINFO_INT_REGISTER + CQUESTROT_Q: cpustate->q = info->i; break;
+
+ case CPUINFO_STR_REGISTER + CQUESTROT_RAM0: cpustate->ram[0x0] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_RAM1: cpustate->ram[0x1] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_RAM2: cpustate->ram[0x2] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_RAM3: cpustate->ram[0x3] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_RAM4: cpustate->ram[0x4] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_RAM5: cpustate->ram[0x5] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_RAM6: cpustate->ram[0x6] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_RAM7: cpustate->ram[0x7] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_RAM8: cpustate->ram[0x8] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_RAM9: cpustate->ram[0x9] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_RAMA: cpustate->ram[0xa] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_RAMB: cpustate->ram[0xb] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_RAMC: cpustate->ram[0xc] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_RAMD: cpustate->ram[0xd] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_RAME: cpustate->ram[0xe] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_RAMF: cpustate->ram[0xf] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_SEQCNT: cpustate->seqcnt = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_DYNADDR: cpustate->dynaddr = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_DYNDATA: cpustate->dyndata = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_YRLATCH: cpustate->yrlatch = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_YDLATCH: cpustate->ydlatch = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_DINLATCH: cpustate->dinlatch = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_DSRCLATCH:cpustate->dsrclatch = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_RSRCLATCH:cpustate->rsrclatch = info->i; break;
+ }
+}
+
+/**************************************************************************
+ * Rotate get_info
+ **************************************************************************/
+
+CPU_GET_INFO( cquestrot )
+{
+ cquestrot_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token_rot(device) : NULL;
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(cquestrot_state); break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 8; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 8; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 1; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 64; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 9; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = -3; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + CQUESTROT_PC: info->i = cpustate->pc; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(cquestrot); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(cquestrot); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(cquestrot); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(cquestrot); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(cquestrot); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(cquestrot); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "Rotate CPU");break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Cube Quest"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Philip J Bennett"); break;
+
+ case CPUINFO_STR_FLAGS: sprintf(info->s, "%c%c%c", cpustate->cflag ? 'C' : '.',
+ cpustate->vflag ? 'V' : '.',
+ cpustate->f ? '.' : 'Z'); break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_PC: sprintf(info->s, "PC: %02X", cpustate->pc); break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_Q: sprintf(info->s, "Q: %04X", cpustate->q); break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_RAM0: sprintf(info->s, "RAM[0]: %04X", cpustate->ram[0x0]); break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_RAM1: sprintf(info->s, "RAM[1]: %04X", cpustate->ram[0x1]); break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_RAM2: sprintf(info->s, "RAM[2]: %04X", cpustate->ram[0x2]); break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_RAM3: sprintf(info->s, "RAM[3]: %04X", cpustate->ram[0x3]); break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_RAM4: sprintf(info->s, "RAM[4]: %04X", cpustate->ram[0x4]); break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_RAM5: sprintf(info->s, "RAM[5]: %04X", cpustate->ram[0x5]); break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_RAM6: sprintf(info->s, "RAM[6]: %04X", cpustate->ram[0x6]); break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_RAM7: sprintf(info->s, "RAM[7]: %04X", cpustate->ram[0x7]); break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_RAM8: sprintf(info->s, "RAM[8]: %04X", cpustate->ram[0x8]); break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_RAM9: sprintf(info->s, "RAM[9]: %04X", cpustate->ram[0x9]); break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_RAMA: sprintf(info->s, "RAM[A]: %04X", cpustate->ram[0xa]); break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_RAMB: sprintf(info->s, "RAM[B]: %04X", cpustate->ram[0xb]); break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_RAMC: sprintf(info->s, "RAM[C]: %04X", cpustate->ram[0xc]); break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_RAMD: sprintf(info->s, "RAM[D]: %04X", cpustate->ram[0xd]); break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_RAME: sprintf(info->s, "RAM[E]: %04X", cpustate->ram[0xe]); break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_RAMF: sprintf(info->s, "RAM[F]: %04X", cpustate->ram[0xf]); break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_SEQCNT: sprintf(info->s, "SEQCNT: %01X", cpustate->seqcnt); break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_DYNADDR: sprintf(info->s, "DYNADDR: %04X", cpustate->dynaddr); break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_DYNDATA: sprintf(info->s, "DYNDATA: %04X", cpustate->dyndata); break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_YRLATCH: sprintf(info->s, "YRLATCH: %04X", cpustate->yrlatch); break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_YDLATCH: sprintf(info->s, "YDLATCH: %04X", cpustate->ydlatch); break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_DINLATCH: sprintf(info->s, "DINLATCH: %04X", cpustate->dinlatch); break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_DSRCLATCH:sprintf(info->s, "DSRCLATCH: %04X", cpustate->dsrclatch); break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_RSRCLATCH:sprintf(info->s, "RSRCLATCH: %04X", cpustate->rsrclatch); break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_LDADDR: sprintf(info->s, "LDADDR : %04X", cpustate->lineaddr); break;
+ case CPUINFO_STR_REGISTER + CQUESTROT_LDDATA: sprintf(info->s, "LDDATA : %04X", cpustate->linedata); break;
+ }
+}
+
+
+/**************************************************************************
+ * Line drawer set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( cquestlin )
+{
+ cquestlin_state *cpustate = get_safe_token_lin(device);
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + CQUESTLIN_FGPC: cpustate->pc[FOREGROUND] = info->i; break;
+ case CPUINFO_INT_REGISTER + CQUESTLIN_BGPC: cpustate->pc[BACKGROUND] = info->i; break;
+ case CPUINFO_INT_REGISTER + CQUESTLIN_Q: cpustate->q = info->i; break;
+
+ case CPUINFO_STR_REGISTER + CQUESTLIN_RAM0: cpustate->ram[0x0] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTLIN_RAM1: cpustate->ram[0x1] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTLIN_RAM2: cpustate->ram[0x2] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTLIN_RAM3: cpustate->ram[0x3] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTLIN_RAM4: cpustate->ram[0x4] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTLIN_RAM5: cpustate->ram[0x5] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTLIN_RAM6: cpustate->ram[0x6] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTLIN_RAM7: cpustate->ram[0x7] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTLIN_RAM8: cpustate->ram[0x8] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTLIN_RAM9: cpustate->ram[0x9] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTLIN_RAMA: cpustate->ram[0xa] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTLIN_RAMB: cpustate->ram[0xb] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTLIN_RAMC: cpustate->ram[0xc] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTLIN_RAMD: cpustate->ram[0xd] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTLIN_RAME: cpustate->ram[0xe] = info->i; break;
+ case CPUINFO_STR_REGISTER + CQUESTLIN_RAMF: cpustate->ram[0xf] = info->i; break;
+ }
+}
+
+/**************************************************************************
+ * Line drawer get_info
+ **************************************************************************/
+
+CPU_GET_INFO( cquestlin )
+{
+ cquestlin_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token_lin(device) : NULL;
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(cquestlin_state); break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 8; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 8; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 1; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 64; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = -3; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + CQUESTLIN_FGPC: info->i = cpustate->pc[cpustate->clkcnt & 3 ? BACKGROUND : FOREGROUND]; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(cquestlin); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(cquestlin); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(cquestlin); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(cquestlin); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(cquestlin); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(cquestlin); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "Line CPU"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Cube Quest"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Philip J Bennett"); break;
+
+ case CPUINFO_STR_FLAGS: sprintf(info->s, "%c%c%c|%cG", cpustate->cflag ? 'C' : '.',
+ cpustate->vflag ? 'V' : '.',
+ cpustate->f ? '.' : 'Z',
+ cpustate->clkcnt & 3 ? 'B' : 'F'); break;
+ case CPUINFO_STR_REGISTER + CQUESTLIN_FGPC: sprintf(info->s, "FPC: %02X", cpustate->pc[FOREGROUND]); break;
+ case CPUINFO_STR_REGISTER + CQUESTLIN_BGPC: sprintf(info->s, "BPC: %02X", cpustate->pc[BACKGROUND]); break;
+ case CPUINFO_STR_REGISTER + CQUESTLIN_Q: sprintf(info->s, "Q: %04X", cpustate->q); break;
+ case CPUINFO_STR_REGISTER + CQUESTLIN_RAM0: sprintf(info->s, "RAM[0]: %04X", cpustate->ram[0x0]); break;
+ case CPUINFO_STR_REGISTER + CQUESTLIN_RAM1: sprintf(info->s, "RAM[1]: %04X", cpustate->ram[0x1]); break;
+ case CPUINFO_STR_REGISTER + CQUESTLIN_RAM2: sprintf(info->s, "RAM[2]: %04X", cpustate->ram[0x2]); break;
+ case CPUINFO_STR_REGISTER + CQUESTLIN_RAM3: sprintf(info->s, "RAM[3]: %04X", cpustate->ram[0x3]); break;
+ case CPUINFO_STR_REGISTER + CQUESTLIN_RAM4: sprintf(info->s, "RAM[4]: %04X", cpustate->ram[0x4]); break;
+ case CPUINFO_STR_REGISTER + CQUESTLIN_RAM5: sprintf(info->s, "RAM[5]: %04X", cpustate->ram[0x5]); break;
+ case CPUINFO_STR_REGISTER + CQUESTLIN_RAM6: sprintf(info->s, "RAM[6]: %04X", cpustate->ram[0x6]); break;
+ case CPUINFO_STR_REGISTER + CQUESTLIN_RAM7: sprintf(info->s, "RAM[7]: %04X", cpustate->ram[0x7]); break;
+ case CPUINFO_STR_REGISTER + CQUESTLIN_RAM8: sprintf(info->s, "RAM[8]: %04X", cpustate->ram[0x8]); break;
+ case CPUINFO_STR_REGISTER + CQUESTLIN_RAM9: sprintf(info->s, "RAM[9]: %04X", cpustate->ram[0x9]); break;
+ case CPUINFO_STR_REGISTER + CQUESTLIN_RAMA: sprintf(info->s, "RAM[A]: %04X", cpustate->ram[0xa]); break;
+ case CPUINFO_STR_REGISTER + CQUESTLIN_RAMB: sprintf(info->s, "RAM[B]: %04X", cpustate->ram[0xb]); break;
+ case CPUINFO_STR_REGISTER + CQUESTLIN_RAMC: sprintf(info->s, "RAM[C]: %04X", cpustate->ram[0xc]); break;
+ case CPUINFO_STR_REGISTER + CQUESTLIN_RAMD: sprintf(info->s, "RAM[D]: %04X", cpustate->ram[0xd]); break;
+ case CPUINFO_STR_REGISTER + CQUESTLIN_RAME: sprintf(info->s, "RAM[E]: %04X", cpustate->ram[0xe]); break;
+ case CPUINFO_STR_REGISTER + CQUESTLIN_RAMF: sprintf(info->s, "RAM[F]: %04X", cpustate->ram[0xf]); break;
+
+ case CPUINFO_STR_REGISTER + CQUESTLIN_FADLATCH: sprintf(info->s, "FADDR: %04X", cpustate->fadlatch); break;
+ case CPUINFO_STR_REGISTER + CQUESTLIN_BADLATCH: sprintf(info->s, "BADDR: %04X", cpustate->badlatch); break;
+ case CPUINFO_STR_REGISTER + CQUESTLIN_SREG: sprintf(info->s, "SREG: %04X", cpustate->sreg); break;
+ case CPUINFO_STR_REGISTER + CQUESTLIN_XCNT: sprintf(info->s, "XCNT: %03X", cpustate->xcnt); break;
+ case CPUINFO_STR_REGISTER + CQUESTLIN_YCNT: sprintf(info->s, "YCNT: %03X", cpustate->ycnt); break;
+ case CPUINFO_STR_REGISTER + CQUESTLIN_CLATCH: sprintf(info->s, "CLATCH: %04X", cpustate->clatch); break;
+ case CPUINFO_STR_REGISTER + CQUESTLIN_ZLATCH: sprintf(info->s, "ZLATCH: %04X", cpustate->zlatch); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(CQUESTSND, cquestsnd);
+DEFINE_LEGACY_CPU_DEVICE(CQUESTROT, cquestrot);
+DEFINE_LEGACY_CPU_DEVICE(CQUESTLIN, cquestlin);
diff --git a/trunk/src/emu/cpu/cubeqcpu/cubeqcpu.h b/trunk/src/emu/cpu/cubeqcpu/cubeqcpu.h
new file mode 100644
index 00000000000..8b0abd60e31
--- /dev/null
+++ b/trunk/src/emu/cpu/cubeqcpu/cubeqcpu.h
@@ -0,0 +1,161 @@
+/***************************************************************************
+
+ cubeqcpu.h
+ Interface file for the Cube Quest CPUs
+ Written by Phil Bennett
+
+***************************************************************************/
+
+#ifndef _CUBEQCPU_H
+#define _CUBEQCPU_H
+
+
+/***************************************************************************
+ COMPILE-TIME DEFINITIONS
+***************************************************************************/
+
+
+/***************************************************************************
+ GLOBAL CONSTANTS
+***************************************************************************/
+
+
+/***************************************************************************
+ REGISTER ENUMERATION
+***************************************************************************/
+
+enum
+{
+ CQUESTSND_PC = 1,
+ CQUESTSND_Q,
+ CQUESTSND_RAM0,
+ CQUESTSND_RAM1,
+ CQUESTSND_RAM2,
+ CQUESTSND_RAM3,
+ CQUESTSND_RAM4,
+ CQUESTSND_RAM5,
+ CQUESTSND_RAM6,
+ CQUESTSND_RAM7,
+ CQUESTSND_RAM8,
+ CQUESTSND_RAM9,
+ CQUESTSND_RAMA,
+ CQUESTSND_RAMB,
+ CQUESTSND_RAMC,
+ CQUESTSND_RAMD,
+ CQUESTSND_RAME,
+ CQUESTSND_RAMF,
+ CQUESTSND_RTNLATCH,
+ CQUESTSND_ADRCNTR,
+ CQUESTSND_DINLATCH,
+};
+
+enum
+{
+ CQUESTROT_PC = 1,
+ CQUESTROT_Q,
+ CQUESTROT_RAM0,
+ CQUESTROT_RAM1,
+ CQUESTROT_RAM2,
+ CQUESTROT_RAM3,
+ CQUESTROT_RAM4,
+ CQUESTROT_RAM5,
+ CQUESTROT_RAM6,
+ CQUESTROT_RAM7,
+ CQUESTROT_RAM8,
+ CQUESTROT_RAM9,
+ CQUESTROT_RAMA,
+ CQUESTROT_RAMB,
+ CQUESTROT_RAMC,
+ CQUESTROT_RAMD,
+ CQUESTROT_RAME,
+ CQUESTROT_RAMF,
+ CQUESTROT_SEQCNT,
+ CQUESTROT_DYNADDR,
+ CQUESTROT_DYNDATA,
+ CQUESTROT_YRLATCH,
+ CQUESTROT_YDLATCH,
+ CQUESTROT_DINLATCH,
+ CQUESTROT_DSRCLATCH,
+ CQUESTROT_RSRCLATCH,
+ CQUESTROT_LDADDR,
+ CQUESTROT_LDDATA,
+};
+
+enum
+{
+ CQUESTLIN_FGPC = 1,
+ CQUESTLIN_BGPC,
+ CQUESTLIN_Q,
+ CQUESTLIN_RAM0,
+ CQUESTLIN_RAM1,
+ CQUESTLIN_RAM2,
+ CQUESTLIN_RAM3,
+ CQUESTLIN_RAM4,
+ CQUESTLIN_RAM5,
+ CQUESTLIN_RAM6,
+ CQUESTLIN_RAM7,
+ CQUESTLIN_RAM8,
+ CQUESTLIN_RAM9,
+ CQUESTLIN_RAMA,
+ CQUESTLIN_RAMB,
+ CQUESTLIN_RAMC,
+ CQUESTLIN_RAMD,
+ CQUESTLIN_RAME,
+ CQUESTLIN_RAMF,
+ CQUESTLIN_FADLATCH,
+ CQUESTLIN_BADLATCH,
+ CQUESTLIN_SREG,
+ CQUESTLIN_XCNT,
+ CQUESTLIN_YCNT,
+ CQUESTLIN_CLATCH,
+ CQUESTLIN_ZLATCH,
+};
+
+
+/***************************************************************************
+ CONFIGURATION STRUCTURE
+***************************************************************************/
+
+typedef void (*cubeqst_dac_w_func)(device_t *, UINT16);
+
+typedef struct _cubeqst_snd_config cubeqst_snd_config;
+struct _cubeqst_snd_config
+{
+ cubeqst_dac_w_func dac_w;
+ const char * sound_data_region;
+
+};
+
+typedef struct _cubeqst_lin_config cubeqst_lin_config;
+struct _cubeqst_lin_config
+{
+ const char * rot_cpu_tag;
+};
+
+typedef struct _cubeqst_rot_config cubeqst_rot_config;
+struct _cubeqst_rot_config
+{
+ const char * lin_cpu_tag;
+};
+
+/***************************************************************************
+ PUBLIC FUNCTIONS
+***************************************************************************/
+
+extern READ16_DEVICE_HANDLER( cubeqcpu_sndram_r );
+extern WRITE16_DEVICE_HANDLER( cubeqcpu_sndram_w );
+
+extern READ16_DEVICE_HANDLER( cubeqcpu_rotram_r );
+extern WRITE16_DEVICE_HANDLER( cubeqcpu_rotram_w );
+
+void cubeqcpu_swap_line_banks(device_t *device);
+
+void cubeqcpu_clear_stack(device_t *device);
+UINT8 cubeqcpu_get_ptr_ram_val(device_t *device, int i);
+UINT32* cubeqcpu_get_stack_ram(device_t *device);
+
+DECLARE_LEGACY_CPU_DEVICE(CQUESTSND, cquestsnd);
+DECLARE_LEGACY_CPU_DEVICE(CQUESTROT, cquestrot);
+DECLARE_LEGACY_CPU_DEVICE(CQUESTLIN, cquestlin);
+
+#endif /* _CUBEQCPU_H */
diff --git a/trunk/src/emu/cpu/drcbec.c b/trunk/src/emu/cpu/drcbec.c
new file mode 100644
index 00000000000..491175a9145
--- /dev/null
+++ b/trunk/src/emu/cpu/drcbec.c
@@ -0,0 +1,2281 @@
+/***************************************************************************
+
+ drcbec.c
+
+ Interpreted C core back-end for the universal machine language.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "drcbec.h"
+
+#ifdef _MSC_VER
+#include <float.h>
+#define isnan _isnan
+#endif
+
+using namespace uml;
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// define a bit to match each possible condition, starting at bit 12
+#define ZBIT (0x1000 << (COND_Z & 15))
+#define NZBIT (0x1000 << (COND_NZ & 15))
+#define SBIT (0x1000 << (COND_S & 15))
+#define NSBIT (0x1000 << (COND_NS & 15))
+#define CBIT (0x1000 << (COND_C & 15))
+#define NCBIT (0x1000 << (COND_NC & 15))
+#define VBIT (0x1000 << (COND_V & 15))
+#define NVBIT (0x1000 << (COND_NV & 15))
+#define UBIT (0x1000 << (COND_U & 15))
+#define NUBIT (0x1000 << (COND_NU & 15))
+#define ABIT (0x1000 << (COND_A & 15))
+#define BEBIT (0x1000 << (COND_BE & 15))
+#define GBIT (0x1000 << (COND_G & 15))
+#define GEBIT (0x1000 << (COND_GE & 15))
+#define LBIT (0x1000 << (COND_L & 15))
+#define LEBIT (0x1000 << (COND_LE & 15))
+
+
+// internal opcodes
+enum
+{
+ OP_LOAD1 = OP_MAX,
+ OP_LOAD1x2,
+ OP_LOAD1x4,
+ OP_LOAD1x8,
+ OP_LOAD2x1,
+ OP_LOAD2,
+ OP_LOAD2x4,
+ OP_LOAD2x8,
+ OP_LOAD4x1,
+ OP_LOAD4x2,
+ OP_LOAD4,
+ OP_LOAD4x8,
+ OP_LOAD8x1,
+ OP_LOAD8x2,
+ OP_LOAD8x4,
+ OP_LOAD8,
+ OP_LOADS1,
+ OP_LOADS1x2,
+ OP_LOADS1x4,
+ OP_LOADS1x8,
+ OP_LOADS2x1,
+ OP_LOADS2,
+ OP_LOADS2x4,
+ OP_LOADS2x8,
+ OP_LOADS4x1,
+ OP_LOADS4x2,
+ OP_LOADS4,
+ OP_LOADS4x8,
+ OP_LOADS8x1,
+ OP_LOADS8x2,
+ OP_LOADS8x4,
+ OP_LOADS8,
+ OP_STORE1,
+ OP_STORE1x2,
+ OP_STORE1x4,
+ OP_STORE1x8,
+ OP_STORE2x1,
+ OP_STORE2,
+ OP_STORE2x4,
+ OP_STORE2x8,
+ OP_STORE4x1,
+ OP_STORE4x2,
+ OP_STORE4,
+ OP_STORE4x8,
+ OP_STORE8x1,
+ OP_STORE8x2,
+ OP_STORE8x4,
+ OP_STORE8,
+ OP_READ1,
+ OP_READ2,
+ OP_READ4,
+ OP_READ8,
+ OP_READM1,
+ OP_READM2,
+ OP_READM4,
+ OP_READM8,
+ OP_WRITE1,
+ OP_WRITE2,
+ OP_WRITE4,
+ OP_WRITE8,
+ OP_WRITEM1,
+ OP_WRITEM2,
+ OP_WRITEM4,
+ OP_WRITEM8,
+ OP_SEXT1,
+ OP_SEXT2,
+ OP_SEXT4,
+ OP_SEXT8,
+ OP_FTOI4T,
+ OP_FTOI4R,
+ OP_FTOI4C,
+ OP_FTOI4F,
+ OP_FTOI4,
+ OP_FTOI8T,
+ OP_FTOI8R,
+ OP_FTOI8C,
+ OP_FTOI8F,
+ OP_FTOI8,
+ OP_FFRI4,
+ OP_FFRI8,
+ OP_FFRFS,
+ OP_FFRFD,
+};
+
+
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+//
+// opcode format:
+//
+// bits 31..28 == number of words following the opcode itself (0-15)
+// bits 27..12 == bitmask specify which condition code we care about
+// bits 11.. 2 == opcode
+// bit 1 == flags/condition summary (0 if no condition/flags, 1 otherwise)
+// bit 0 == operation size (0=32-bit, 1=64-bit)
+//
+
+// build a short opcode from the raw opcode and size
+#define MAKE_OPCODE_SHORT(op, size, conditionorflags) \
+ ((((size) == 8) << 0) | (((conditionorflags) != 0) << 1) | ((op) << 2))
+
+// build a full opcode from the raw opcode, size, condition/flags, and immediate count
+#define MAKE_OPCODE_FULL(op, size, condition, flags, pwords) \
+ (MAKE_OPCODE_SHORT(op, size, (condition | flags)) | ((condition != COND_ALWAYS) ? (0x1000 << ((condition) & 15)) : 0) | ((pwords) << 28))
+
+// extract various parts of the opcode
+#define OPCODE_GET_SHORT(op) ((op) & 0xfff)
+#define OPCODE_PASS_CONDITION(op,f) (((op) & s_condition_map[f]) != 0)
+#define OPCODE_FAIL_CONDITION(op,f) (((op) & s_condition_map[f]) == 0)
+#define OPCODE_GET_PWORDS(op) ((op) >> 28)
+
+// shorthand for accessing parameters in the instruction stream
+#define PARAM0 (*inst[0].puint32)
+#define PARAM1 (*inst[1].puint32)
+#define PARAM2 (*inst[2].puint32)
+#define PARAM3 (*inst[3].puint32)
+
+#define DPARAM0 (*inst[0].puint64)
+#define DPARAM1 (*inst[1].puint64)
+#define DPARAM2 (*inst[2].puint64)
+#define DPARAM3 (*inst[3].puint64)
+
+#define FSPARAM0 (*inst[0].pfloat)
+#define FSPARAM1 (*inst[1].pfloat)
+#define FSPARAM2 (*inst[2].pfloat)
+#define FSPARAM3 (*inst[3].pfloat)
+
+#define FDPARAM0 (*inst[0].pdouble)
+#define FDPARAM1 (*inst[1].pdouble)
+#define FDPARAM2 (*inst[2].pdouble)
+#define FDPARAM3 (*inst[3].pdouble)
+
+// compute C and V flags for 32-bit add/subtract
+#define FLAGS32_C_ADD(a,b) ((UINT32)~(a) < (UINT32)(b))
+#define FLAGS32_C_SUB(a,b) ((UINT32)(b) > (UINT32)(a))
+#define FLAGS32_V_SUB(r,a,b) (((((a) ^ (b)) & ((a) ^ (r))) >> 30) & FLAG_V)
+#define FLAGS32_V_ADD(r,a,b) (((~((a) ^ (b)) & ((a) ^ (r))) >> 30) & FLAG_V)
+
+// compute N and Z flags for 32-bit operations
+#define FLAGS32_NZ(v) ((((v) >> 28) & FLAG_S) | (((UINT32)(v) == 0) << 2))
+#define FLAGS32_NZCV_ADD(r,a,b) (FLAGS32_NZ(r) | FLAGS32_C_ADD(a,b) | FLAGS32_V_ADD(r,a,b))
+#define FLAGS32_NZCV_SUB(r,a,b) (FLAGS32_NZ(r) | FLAGS32_C_SUB(a,b) | FLAGS32_V_SUB(r,a,b))
+
+// compute C and V flags for 64-bit add/subtract
+#define FLAGS64_C_ADD(a,b) ((UINT64)~(a) < (UINT64)(b))
+#define FLAGS64_C_SUB(a,b) ((UINT64)(b) > (UINT64)(a))
+#define FLAGS64_V_SUB(r,a,b) (((((a) ^ (b)) & ((a) ^ (r))) >> 62) & FLAG_V)
+#define FLAGS64_V_ADD(r,a,b) (((~((a) ^ (b)) & ((a) ^ (r))) >> 62) & FLAG_V)
+
+// compute N and Z flags for 64-bit operations
+#define FLAGS64_NZ(v) ((((v) >> 60) & FLAG_S) | (((UINT64)(v) == 0) << 2))
+#define FLAGS64_NZCV_ADD(r,a,b) (FLAGS64_NZ(r) | FLAGS64_C_ADD(a,b) | FLAGS64_V_ADD(r,a,b))
+#define FLAGS64_NZCV_SUB(r,a,b) (FLAGS64_NZ(r) | FLAGS64_C_SUB(a,b) | FLAGS64_V_SUB(r,a,b))
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// union to simplify accessing data via the instruction stream
+union drcbec_instruction
+{
+ UINT32 i;
+ void * v;
+ char * c;
+ UINT8 * puint8;
+ INT8 * pint8;
+ UINT16 * puint16;
+ INT16 * pint16;
+ UINT32 * puint32;
+ INT32 * pint32;
+ UINT64 * puint64;
+ INT64 * pint64;
+ float * pfloat;
+ double * pdouble;
+ void (*cfunc)(void *);
+ drcuml_machine_state *state;
+ const code_handle * handle;
+ const drcbec_instruction *inst;
+ const drcbec_instruction **pinst;
+};
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+UINT64 drcbe_c::s_immediate_zero = 0;
+
+const UINT32 drcbe_c::s_condition_map[] =
+{
+ /* ..... */ NCBIT | NVBIT | NZBIT | NSBIT | NUBIT | ABIT | GBIT | GEBIT,
+ /* ....C */ CBIT | NVBIT | NZBIT | NSBIT | NUBIT | BEBIT | GBIT | GEBIT,
+ /* ...V. */ NCBIT | VBIT | NZBIT | NSBIT | NUBIT | ABIT | LEBIT | LBIT,
+ /* ...VC */ CBIT | VBIT | NZBIT | NSBIT | NUBIT | BEBIT | LEBIT | LBIT,
+ /* ..Z.. */ NCBIT | NVBIT | ZBIT | NSBIT | NUBIT | BEBIT | LEBIT | GEBIT,
+ /* ..Z.C */ CBIT | NVBIT | ZBIT | NSBIT | NUBIT | BEBIT | LEBIT | GEBIT,
+ /* ..ZV. */ NCBIT | VBIT | ZBIT | NSBIT | NUBIT | BEBIT | LEBIT | LBIT,
+ /* ..ZVC */ CBIT | VBIT | ZBIT | NSBIT | NUBIT | BEBIT | LEBIT | LBIT,
+ /* .S... */ NCBIT | NVBIT | NZBIT | SBIT | NUBIT | ABIT | LEBIT | LBIT,
+ /* .S..C */ CBIT | NVBIT | NZBIT | SBIT | NUBIT | BEBIT | LEBIT | LBIT,
+ /* .S.V. */ NCBIT | VBIT | NZBIT | SBIT | NUBIT | ABIT | GBIT | GEBIT,
+ /* .S.VC */ CBIT | VBIT | NZBIT | SBIT | NUBIT | BEBIT | GBIT | GEBIT,
+ /* .SZ.. */ NCBIT | NVBIT | ZBIT | SBIT | NUBIT | BEBIT | LEBIT | LBIT,
+ /* .SZ.C */ CBIT | NVBIT | ZBIT | SBIT | NUBIT | BEBIT | LEBIT | LBIT,
+ /* .SZV. */ NCBIT | VBIT | ZBIT | SBIT | NUBIT | BEBIT | LEBIT | GEBIT,
+ /* .SZVC */ CBIT | VBIT | ZBIT | SBIT | NUBIT | BEBIT | LEBIT | GEBIT,
+ /* U.... */ NCBIT | NVBIT | NZBIT | NSBIT | UBIT | ABIT | GBIT | GEBIT,
+ /* U...C */ CBIT | NVBIT | NZBIT | NSBIT | UBIT | BEBIT | GBIT | GEBIT,
+ /* U..V. */ NCBIT | VBIT | NZBIT | NSBIT | UBIT | ABIT | LEBIT | LBIT,
+ /* U..VC */ CBIT | VBIT | NZBIT | NSBIT | UBIT | BEBIT | LEBIT | LBIT,
+ /* U.Z.. */ NCBIT | NVBIT | ZBIT | NSBIT | UBIT | BEBIT | LEBIT | GEBIT,
+ /* U.Z.C */ CBIT | NVBIT | ZBIT | NSBIT | UBIT | BEBIT | LEBIT | GEBIT,
+ /* U.ZV. */ NCBIT | VBIT | ZBIT | NSBIT | UBIT | BEBIT | LEBIT | LBIT,
+ /* U.ZVC */ CBIT | VBIT | ZBIT | NSBIT | UBIT | BEBIT | LEBIT | LBIT,
+ /* US... */ NCBIT | NVBIT | NZBIT | SBIT | UBIT | ABIT | LEBIT | LBIT,
+ /* US..C */ CBIT | NVBIT | NZBIT | SBIT | UBIT | BEBIT | LEBIT | LBIT,
+ /* US.V. */ NCBIT | VBIT | NZBIT | SBIT | UBIT | ABIT | GBIT | GEBIT,
+ /* US.VC */ CBIT | VBIT | NZBIT | SBIT | UBIT | BEBIT | GBIT | GEBIT,
+ /* USZ.. */ NCBIT | NVBIT | ZBIT | SBIT | UBIT | BEBIT | LEBIT | LBIT,
+ /* USZ.C */ CBIT | NVBIT | ZBIT | SBIT | UBIT | BEBIT | LEBIT | LBIT,
+ /* USZV. */ NCBIT | VBIT | ZBIT | SBIT | UBIT | BEBIT | LEBIT | GEBIT,
+ /* USZVC */ CBIT | VBIT | ZBIT | SBIT | UBIT | BEBIT | LEBIT | GEBIT
+};
+
+
+
+//**************************************************************************
+// C BACKEND
+//**************************************************************************
+
+//-------------------------------------------------
+// drcbe_c - constructor
+//-------------------------------------------------
+
+drcbe_c::drcbe_c(drcuml_state &drcuml, device_t &device, drc_cache &cache, UINT32 flags, int modes, int addrbits, int ignorebits)
+ : drcbe_interface(drcuml, cache, device),
+ m_hash(cache, modes, addrbits, ignorebits),
+ m_map(cache, 0),
+ m_labels(cache),
+ m_fixup_delegate(FUNC(drcbe_c::fixup_label), this)
+{
+}
+
+
+//-------------------------------------------------
+// ~drcbe_c - destructor
+//-------------------------------------------------
+
+drcbe_c::~drcbe_c()
+{
+}
+
+
+//-------------------------------------------------
+// reset - reset back-end specific state
+//-------------------------------------------------
+
+void drcbe_c::reset()
+{
+ // reset our hash tables
+ m_hash.reset();
+ m_hash.set_default_codeptr(NULL);
+}
+
+
+//-------------------------------------------------
+// drcbec_generate - generate code
+//-------------------------------------------------
+
+void drcbe_c::generate(drcuml_block &block, const instruction *instlist, UINT32 numinst)
+{
+ // tell all of our utility objects that a block is beginning
+ m_hash.block_begin(block, instlist, numinst);
+ m_labels.block_begin(block);
+ m_map.block_begin(block);
+
+ // begin codegen; fail if we can't
+ drccodeptr *cachetop = m_cache.begin_codegen(numinst * sizeof(drcbec_instruction) * 4);
+ if (cachetop == NULL)
+ block.abort();
+
+ // compute the base by aligning the cache top to an even multiple of drcbec_instruction
+ drcbec_instruction *base = (drcbec_instruction *)(((FPTR)*cachetop + sizeof(drcbec_instruction) - 1) & ~(sizeof(drcbec_instruction) - 1));
+ drcbec_instruction *dst = base;
+
+ // generate code by copying the instructions and extracting immediates
+ for (int inum = 0; inum < numinst; inum++)
+ {
+ const instruction &inst = instlist[inum];
+ UINT8 psize[instruction::MAX_PARAMS];
+
+ // handle most instructions generally, but a few special cases
+ opcode_t opcode = inst.opcode();
+ switch (opcode)
+ {
+ // when we hit a HANDLE opcode, register the current pointer for the handle
+ case OP_HANDLE:
+ inst.param(0).handle().set_codeptr((drccodeptr)dst);
+ break;
+
+ // when we hit a HASH opcode, register the current pointer for the mode/PC
+ case OP_HASH:
+ m_hash.set_codeptr(inst.param(0).immediate(), inst.param(1).immediate(), (drccodeptr)dst);
+ break;
+
+ // when we hit a LABEL opcode, register the current pointer for the label
+ case OP_LABEL:
+ m_labels.set_codeptr(inst.param(0).label(), (drccodeptr)dst);
+ break;
+
+ // ignore COMMENT and NOP opcodes
+ case OP_COMMENT:
+ case OP_NOP:
+ break;
+
+ // when we hit a MAPVAR opcode, log the change for the current PC
+ case OP_MAPVAR:
+ m_map.set_value((drccodeptr)dst, inst.param(0).mapvar(), inst.param(1).immediate());
+ break;
+
+ // JMP instructions need to resolve their labels
+ case OP_JMP:
+ (dst++)->i = MAKE_OPCODE_FULL(opcode, inst.size(), inst.condition(), inst.flags(), 1);
+ dst->inst = (drcbec_instruction *)m_labels.get_codeptr(inst.param(0).label(), m_fixup_delegate, dst);
+ dst++;
+ break;
+
+ // generically handle everything else
+ default:
+
+ // determine the operand size for each operand; mostly this is just the instruction size
+ for (int pnum = 0; pnum < inst.numparams(); pnum++)
+ psize[pnum] = inst.size();
+ if (opcode == OP_LOAD || opcode == OP_FLOAD)
+ psize[2] = 4;
+ if (opcode == OP_STORE || opcode == OP_FSTORE)
+ psize[1] = 4;
+ if (opcode == OP_READ || opcode == OP_READM || opcode == OP_FREAD)
+ psize[1] = psize[2] = 4;
+ if (opcode == OP_WRITE || opcode == OP_WRITEM || opcode == OP_FWRITE)
+ psize[0] = psize[2] = 4;
+ if (opcode == OP_SEXT && inst.param(2).size() != SIZE_QWORD)
+ psize[1] = 4;
+ if (opcode == OP_FTOINT)
+ psize[0] = 1 << inst.param(2).size();
+ if (opcode == OP_FFRINT || opcode == OP_FFRFLT)
+ psize[1] = 1 << inst.param(2).size();
+
+ // pre-expand opcodes that encode size/scale in them
+ if (opcode == OP_LOAD)
+ opcode = (opcode_t)(OP_LOAD1 + inst.param(3).size() * 4 + inst.param(3).scale());
+ if (opcode == OP_LOADS)
+ opcode = (opcode_t)(OP_LOADS1 + inst.param(3).size() * 4 + inst.param(3).scale());
+ if (opcode == OP_STORE)
+ opcode = (opcode_t)(OP_STORE1 + inst.param(3).size() * 4 + inst.param(3).scale());
+ if (opcode == OP_READ)
+ opcode = (opcode_t)(OP_READ1 + inst.param(2).size());
+ if (opcode == OP_READM)
+ opcode = (opcode_t)(OP_READM1 + inst.param(3).size());
+ if (opcode == OP_WRITE)
+ opcode = (opcode_t)(OP_WRITE1 + inst.param(2).size());
+ if (opcode == OP_WRITEM)
+ opcode = (opcode_t)(OP_WRITEM1 + inst.param(3).size());
+ if (opcode == OP_SEXT)
+ opcode = (opcode_t)(OP_SEXT1 + inst.param(2).size());
+ if (opcode == OP_FTOINT)
+ opcode = (opcode_t)(OP_FTOI4T + 5 * (inst.param(2).size() - 2) + inst.param(3).rounding());
+ if (opcode == OP_FFRINT)
+ opcode = (opcode_t)(OP_FFRI4 + (inst.param(2).size() - 2));
+ if (opcode == OP_FFRFLT)
+ opcode = (opcode_t)(OP_FFRFS + (inst.param(2).size() - 2));
+
+ // count how many bytes of immediates we need
+ int immedbytes = 0;
+ for (int pnum = 0; pnum < inst.numparams(); pnum++)
+ if (inst.param(pnum).is_mapvar() ||
+ (inst.param(pnum).is_immediate() && inst.param(pnum).immediate() != 0) ||
+ (inst.param(pnum).is_size_space() && inst.param(pnum).space() != 0))
+ immedbytes += psize[pnum];
+
+ // compute how many instruction words we need for that
+ int immedwords = (immedbytes + sizeof(drcbec_instruction) - 1) / sizeof(drcbec_instruction);
+
+ // first item is the opcode, size, condition flags and length
+ (dst++)->i = MAKE_OPCODE_FULL(opcode, inst.size(), inst.condition(), inst.flags(), inst.numparams() + immedwords);
+
+ // immediates start after parameters
+ void *immed = dst + inst.numparams();
+
+ // output each of the parameters
+ for (int pnum = 0; pnum < inst.numparams(); pnum++)
+ output_parameter(&dst, &immed, psize[pnum], inst.param(pnum));
+
+ // point past the end of the immediates
+ dst += immedwords;
+ break;
+ }
+ }
+
+ // complete codegen
+ *cachetop = (drccodeptr)dst;
+ m_cache.end_codegen();
+
+ // tell all of our utility objects that the block is finished
+ m_hash.block_end(block);
+ m_labels.block_end(block);
+ m_map.block_end(block);
+}
+
+
+//-------------------------------------------------
+// hash_exists - return true if the given mode/pc
+// exists in the hash table
+//-------------------------------------------------
+
+bool drcbe_c::hash_exists(UINT32 mode, UINT32 pc)
+{
+ return m_hash.code_exists(mode, pc);
+}
+
+
+//-------------------------------------------------
+// get_info - return information about the
+// back-end implementation
+//-------------------------------------------------
+
+void drcbe_c::get_info(drcbe_info &info)
+{
+ info.direct_iregs = 0;
+ info.direct_fregs = 0;
+}
+
+
+//-------------------------------------------------
+// execute - execute a block of code registered
+// at the given mode/pc
+//-------------------------------------------------
+
+int drcbe_c::execute(code_handle &entry)
+{
+ // get the entry point
+ const drcbec_instruction *inst = (const drcbec_instruction *)entry.codeptr();
+ assert_in_cache(m_cache, inst);
+
+ // loop while we have cycles
+ const drcbec_instruction *callstack[32];
+ const drcbec_instruction *newinst;
+ UINT32 temp32;
+ UINT64 temp64;
+ int shift;
+ UINT8 flags = 0;
+ UINT8 sp = 0;
+ while (true)
+ {
+ UINT32 opcode = (inst++)->i;
+
+ switch (OPCODE_GET_SHORT(opcode))
+ {
+ // ----------------------- Control Flow Operations -----------------------
+
+ case MAKE_OPCODE_SHORT(OP_HANDLE, 4, 0): // HANDLE handle
+ case MAKE_OPCODE_SHORT(OP_HASH, 4, 0): // HASH mode,pc
+ case MAKE_OPCODE_SHORT(OP_LABEL, 4, 0): // LABEL imm
+ case MAKE_OPCODE_SHORT(OP_COMMENT, 4, 0): // COMMENT string
+ case MAKE_OPCODE_SHORT(OP_MAPVAR, 4, 0): // MAPVAR mapvar,value
+
+ // these opcodes should be processed at compile-time only
+ fatalerror("Unexpected opcode");
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_DEBUG, 4, 0): // DEBUG pc
+ debugger_instruction_hook(&m_device, PARAM0);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_HASHJMP, 4, 0): // HASHJMP mode,pc,handle
+ sp = 0;
+ newinst = (const drcbec_instruction *)m_hash.get_codeptr(PARAM0, PARAM1);
+ if (newinst == NULL)
+ {
+ assert(sp < ARRAY_LENGTH(callstack));
+ m_state.exp = PARAM1;
+ newinst = (const drcbec_instruction *)inst[2].handle->codeptr();
+ callstack[sp++] = inst;
+ }
+ assert_in_cache(m_cache, newinst);
+ inst = newinst;
+ continue;
+
+ case MAKE_OPCODE_SHORT(OP_EXIT, 4, 1): // EXIT src1[,c]
+ if (OPCODE_FAIL_CONDITION(opcode, flags))
+ break;
+ // fall through...
+
+ case MAKE_OPCODE_SHORT(OP_EXIT, 4, 0):
+ return PARAM0;
+
+ case MAKE_OPCODE_SHORT(OP_JMP, 4, 1): // JMP imm[,c]
+ if (OPCODE_FAIL_CONDITION(opcode, flags))
+ break;
+ // fall through...
+
+ case MAKE_OPCODE_SHORT(OP_JMP, 4, 0):
+ newinst = inst[0].inst;
+ assert_in_cache(m_cache, newinst);
+ inst = newinst;
+ continue;
+
+ case MAKE_OPCODE_SHORT(OP_CALLH, 4, 1): // CALLH handle[,c]
+ if (OPCODE_FAIL_CONDITION(opcode, flags))
+ break;
+ // fall through...
+
+ case MAKE_OPCODE_SHORT(OP_CALLH, 4, 0):
+ assert(sp < ARRAY_LENGTH(callstack));
+ newinst = (const drcbec_instruction *)inst[0].handle->codeptr();
+ assert_in_cache(m_cache, newinst);
+ callstack[sp++] = inst + OPCODE_GET_PWORDS(opcode);
+ inst = newinst;
+ continue;
+
+ case MAKE_OPCODE_SHORT(OP_RET, 4, 1): // RET [c]
+ if (OPCODE_FAIL_CONDITION(opcode, flags))
+ break;
+ // fall through...
+
+ case MAKE_OPCODE_SHORT(OP_RET, 4, 0):
+ assert(sp > 0);
+ newinst = callstack[--sp];
+ assert_in_cache(m_cache, newinst);
+ inst = newinst;
+ continue;
+
+ case MAKE_OPCODE_SHORT(OP_EXH, 4, 1): // EXH handle,param[,c]
+ if (OPCODE_FAIL_CONDITION(opcode, flags))
+ break;
+ // fall through...
+
+ case MAKE_OPCODE_SHORT(OP_EXH, 4, 0):
+ assert(sp < ARRAY_LENGTH(callstack));
+ newinst = (const drcbec_instruction *)inst[0].handle->codeptr();
+ assert_in_cache(m_cache, newinst);
+ m_state.exp = PARAM1;
+ callstack[sp++] = inst;
+ inst = newinst;
+ continue;
+
+ case MAKE_OPCODE_SHORT(OP_CALLC, 4, 1): // CALLC func,ptr[,c]
+ if (OPCODE_FAIL_CONDITION(opcode, flags))
+ break;
+ // fall through...
+
+ case MAKE_OPCODE_SHORT(OP_CALLC, 4, 0):
+ (*inst[0].cfunc)(inst[1].v);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_RECOVER, 4, 0): // RECOVER dst,mapvar
+ assert(sp > 0);
+ PARAM0 = m_map.get_value((drccodeptr)callstack[0], PARAM1);
+ break;
+
+
+ // ----------------------- Internal Register Operations -----------------------
+
+ case MAKE_OPCODE_SHORT(OP_SETFMOD, 4, 0): // SETFMOD src
+ m_state.fmod = PARAM0;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_GETFMOD, 4, 0): // GETFMOD dst
+ PARAM0 = m_state.fmod;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_GETEXP, 4, 0): // GETEXP dst
+ PARAM0 = m_state.exp;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_GETFLGS, 4, 0): // GETFLGS dst[,f]
+ PARAM0 = flags & PARAM1;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_SAVE, 4, 0): // SAVE dst
+ *inst[0].state = m_state;
+ inst[0].state->flags = flags;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_RESTORE, 4, 0): // RESTORE dst
+ case MAKE_OPCODE_SHORT(OP_RESTORE, 4, 1): // RESTORE dst
+ m_state = *inst[0].state;
+ flags = inst[0].state->flags;
+ break;
+
+
+ // ----------------------- 32-Bit Integer Operations -----------------------
+
+ case MAKE_OPCODE_SHORT(OP_LOAD1, 4, 0): // LOAD dst,base,index,BYTE
+ PARAM0 = inst[1].puint8[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOAD1x2, 4, 0): // LOAD dst,base,index,BYTE_x2
+ PARAM0 = *(UINT8 *)&inst[1].puint16[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOAD1x4, 4, 0): // LOAD dst,base,index,BYTE_x4
+ PARAM0 = *(UINT8 *)&inst[1].puint32[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOAD1x8, 4, 0): // LOAD dst,base,index,BYTE_x8
+ PARAM0 = *(UINT8 *)&inst[1].puint64[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOAD2x1, 4, 0): // LOAD dst,base,index,WORD_x1
+ PARAM0 = *(UINT16 *)&inst[1].puint8[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOAD2, 4, 0): // LOAD dst,base,index,WORD
+ PARAM0 = inst[1].puint16[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOAD2x4, 4, 0): // LOAD dst,base,index,WORD_x4
+ PARAM0 = *(UINT16 *)&inst[1].puint32[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOAD2x8, 4, 0): // LOAD dst,base,index,WORD_x8
+ PARAM0 = *(UINT16 *)&inst[1].puint64[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOAD4x1, 4, 0): // LOAD dst,base,index,DWORD_x1
+ PARAM0 = *(UINT32 *)&inst[1].puint8[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOAD4x2, 4, 0): // LOAD dst,base,index,DWORD_x2
+ PARAM0 = *(UINT32 *)&inst[1].puint16[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOAD4, 4, 0): // LOAD dst,base,index,DWORD
+ PARAM0 = inst[1].puint32[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOAD4x8, 4, 0): // LOAD dst,base,index,DWORD_x8
+ PARAM0 = *(UINT32 *)&inst[1].puint64[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOADS1, 4, 0): // LOADS dst,base,index,BYTE
+ PARAM0 = inst[1].pint8[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOADS1x2, 4, 0): // LOADS dst,base,index,BYTE_x2
+ PARAM0 = *(INT8 *)&inst[1].pint16[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOADS1x4, 4, 0): // LOADS dst,base,index,BYTE_x4
+ PARAM0 = *(INT8 *)&inst[1].pint32[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOADS1x8, 4, 0): // LOADS dst,base,index,BYTE_x8
+ PARAM0 = *(INT8 *)&inst[1].pint64[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOADS2x1, 4, 0): // LOADS dst,base,index,WORD_x1
+ PARAM0 = *(INT16 *)&inst[1].pint8[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOADS2, 4, 0): // LOADS dst,base,index,WORD
+ PARAM0 = inst[1].pint16[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOADS2x4, 4, 0): // LOADS dst,base,index,WORD_x4
+ PARAM0 = *(INT16 *)&inst[1].pint32[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOADS2x8, 4, 0): // LOADS dst,base,index,WORD_x8
+ PARAM0 = *(INT16 *)&inst[1].pint64[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOADS4x1, 4, 0): // LOADS dst,base,index,DWORD_x1
+ PARAM0 = *(INT32 *)&inst[1].pint8[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOADS4x2, 4, 0): // LOADS dst,base,index,DWORD_x2
+ PARAM0 = *(INT32 *)&inst[1].pint16[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOADS4, 4, 0): // LOADS dst,base,index,DWORD
+ PARAM0 = inst[1].pint32[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOADS4x8, 4, 0): // LOADS dst,base,index,DWORD_x8
+ PARAM0 = *(INT32 *)&inst[1].pint64[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_STORE1, 4, 0): // STORE dst,base,index,BYTE
+ inst[0].puint8[PARAM1] = PARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_STORE1x2, 4, 0): // STORE dst,base,index,BYTE_x2
+ *(UINT8 *)&inst[0].puint16[PARAM1] = PARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_STORE1x4, 4, 0): // STORE dst,base,index,BYTE_x4
+ *(UINT8 *)&inst[0].puint32[PARAM1] = PARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_STORE1x8, 4, 0): // STORE dst,base,index,BYTE_x8
+ *(UINT8 *)&inst[0].puint64[PARAM1] = PARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_STORE2x1, 4, 0): // STORE dst,base,index,WORD_x1
+ *(UINT16 *)&inst[0].puint8[PARAM1] = PARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_STORE2, 4, 0): // STORE dst,base,index,WORD
+ inst[0].puint16[PARAM1] = PARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_STORE2x4, 4, 0): // STORE dst,base,index,WORD_x4
+ *(UINT16 *)&inst[0].puint32[PARAM1] = PARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_STORE2x8, 4, 0): // STORE dst,base,index,WORD_x8
+ *(UINT16 *)&inst[0].puint64[PARAM1] = PARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_STORE4x1, 4, 0): // STORE dst,base,index,DWORD_x1
+ *(UINT32 *)&inst[0].puint8[PARAM1] = PARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_STORE4x2, 4, 0): // STORE dst,base,index,DWORD_x2
+ *(UINT32 *)&inst[0].puint16[PARAM1] = PARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_STORE4, 4, 0): // STORE dst,base,index,DWORD
+ inst[0].puint32[PARAM1] = PARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_STORE4x8, 4, 0): // STORE dst,base,index,DWORD_x8
+ *(UINT32 *)&inst[0].puint64[PARAM1] = PARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_READ1, 4, 0): // READ dst,src1,space_BYTE
+ PARAM0 = m_space[PARAM2]->read_byte(PARAM1);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_READ2, 4, 0): // READ dst,src1,space_WORD
+ PARAM0 = m_space[PARAM2]->read_word(PARAM1);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_READ4, 4, 0): // READ dst,src1,space_DWORD
+ PARAM0 = m_space[PARAM2]->read_dword(PARAM1);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_READM2, 4, 0): // READM dst,src1,mask,space_WORD
+ PARAM0 = m_space[PARAM3]->read_word(PARAM1, PARAM2);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_READM4, 4, 0): // READM dst,src1,mask,space_DWORD
+ PARAM0 = m_space[PARAM3]->read_dword(PARAM1, PARAM2);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_WRITE1, 4, 0): // WRITE dst,src1,space_BYTE
+ m_space[PARAM2]->write_byte(PARAM0, PARAM1);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_WRITE2, 4, 0): // WRITE dst,src1,space_WORD
+ m_space[PARAM2]->write_word(PARAM0, PARAM1);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_WRITE4, 4, 0): // WRITE dst,src1,space_DWORD
+ m_space[PARAM2]->write_dword(PARAM0, PARAM1);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_WRITEM2, 4, 0): // WRITEM dst,src1,mask,space_WORD
+ m_space[PARAM3]->write_word(PARAM0, PARAM1, PARAM2);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_WRITEM4, 4, 0): // WRITEM dst,src1,mask,space_DWORD
+ m_space[PARAM3]->write_dword(PARAM0, PARAM1, PARAM2);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_CARRY, 4, 1): // CARRY src,bitnum
+ flags = (flags & ~FLAG_C) | ((PARAM0 >> (PARAM1 & 31)) & FLAG_C);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_MOV, 4, 1): // MOV dst,src[,c]
+ if (OPCODE_FAIL_CONDITION(opcode, flags))
+ break;
+ // fall through...
+
+ case MAKE_OPCODE_SHORT(OP_MOV, 4, 0):
+ PARAM0 = PARAM1;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_SET, 4, 1): // SET dst,c
+ PARAM0 = OPCODE_FAIL_CONDITION(opcode, flags) ? 0 : 1;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_SEXT1, 4, 0): // SEXT1 dst,src
+ PARAM0 = (INT8)PARAM1;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_SEXT1, 4, 1):
+ temp32 = (INT8)PARAM1;
+ flags = FLAGS32_NZ(temp32);
+ PARAM0 = temp32;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_SEXT2, 4, 0): // SEXT2 dst,src
+ PARAM0 = (INT16)PARAM1;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_SEXT2, 4, 1):
+ temp32 = (INT16)PARAM1;
+ flags = FLAGS32_NZ(temp32);
+ PARAM0 = temp32;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_ROLAND, 4, 0): // ROLAND dst,src,count,mask[,f]
+ shift = PARAM2 & 31;
+ PARAM0 = ((PARAM1 << shift) | (PARAM1 >> (32 - shift))) & PARAM3;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_ROLAND, 4, 1):
+ shift = PARAM2 & 31;
+ temp32 = ((PARAM1 << shift) | (PARAM1 >> (32 - shift))) & PARAM3;
+ flags = FLAGS32_NZ(temp32);
+ PARAM0 = temp32;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_ROLINS, 4, 0): // ROLINS dst,src,count,mask[,f]
+ shift = PARAM2 & 31;
+ PARAM0 = (PARAM0 & ~PARAM3) | (((PARAM1 << shift) | (PARAM1 >> (32 - shift))) & PARAM3);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_ROLINS, 4, 1):
+ shift = PARAM2 & 31;
+ temp32 = (PARAM0 & ~PARAM3) | (((PARAM1 << shift) | (PARAM1 >> (32 - shift))) & PARAM3);
+ flags = FLAGS32_NZ(temp32);
+ PARAM0 = temp32;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_ADD, 4, 0): // ADD dst,src1,src2[,f]
+ PARAM0 = PARAM1 + PARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_ADD, 4, 1):
+ temp32 = PARAM1 + PARAM2;
+ flags = FLAGS32_NZCV_ADD(temp32, PARAM1, PARAM2);
+ PARAM0 = temp32;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_ADDC, 4, 0): // ADDC dst,src1,src2[,f]
+ PARAM0 = PARAM1 + PARAM2 + (flags & FLAG_C);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_ADDC, 4, 1):
+ temp32 = PARAM1 + PARAM2 + (flags & FLAG_C);
+ if (PARAM2 + 1 != 0)
+ flags = FLAGS32_NZCV_ADD(temp32, PARAM1, PARAM2 + (flags & FLAG_C));
+ else
+ flags = FLAGS32_NZCV_ADD(temp32, PARAM1 + (flags & FLAG_C), PARAM2);
+ PARAM0 = temp32;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_SUB, 4, 0): // SUB dst,src1,src2[,f]
+ PARAM0 = PARAM1 - PARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_SUB, 4, 1):
+ temp32 = PARAM1 - PARAM2;
+ flags = FLAGS32_NZCV_SUB(temp32, PARAM1, PARAM2);
+ PARAM0 = temp32;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_SUBB, 4, 0): // SUBB dst,src1,src2[,f]
+ PARAM0 = PARAM1 - PARAM2 - (flags & FLAG_C);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_SUBB, 4, 1):
+ temp32 = PARAM1 - PARAM2 - (flags & FLAG_C);
+ if (PARAM2 + 1 != 0)
+ flags = FLAGS32_NZCV_SUB(temp32, PARAM1, PARAM2 + (flags & FLAG_C));
+ else
+ flags = FLAGS32_NZCV_SUB(temp32, PARAM1 - (flags & FLAG_C), PARAM2);
+ PARAM0 = temp32;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_CMP, 4, 1): // CMP src1,src2[,f]
+ temp32 = PARAM0 - PARAM1;
+ flags = FLAGS32_NZCV_SUB(temp32, PARAM0, PARAM1);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_MULU, 4, 0): // MULU dst,edst,src1,src2[,f]
+ temp64 = (UINT64)(UINT32)PARAM2 * (UINT64)(UINT32)PARAM3;
+ PARAM1 = temp64 >> 32;
+ PARAM0 = (UINT32)temp64;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_MULU, 4, 1):
+ temp64 = (UINT64)(UINT32)PARAM2 * (UINT64)(UINT32)PARAM3;
+ flags = FLAGS64_NZ(temp64);
+ PARAM1 = temp64 >> 32;
+ PARAM0 = (UINT32)temp64;
+ if (temp64 != (UINT32)temp64)
+ flags |= FLAG_V;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_MULS, 4, 0): // MULS dst,edst,src1,src2[,f]
+ temp64 = (INT64)(INT32)PARAM2 * (INT64)(INT32)PARAM3;
+ PARAM1 = temp64 >> 32;
+ PARAM0 = (UINT32)temp64;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_MULS, 4, 1):
+ temp64 = (INT64)(INT32)PARAM2 * (INT64)(INT32)PARAM3;
+ flags = FLAGS64_NZ(temp64);
+ PARAM1 = temp64 >> 32;
+ PARAM0 = (UINT32)temp64;
+ if (temp64 != (INT32)temp64)
+ flags |= FLAG_V;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_DIVU, 4, 0): // DIVU dst,edst,src1,src2[,f]
+ if (PARAM3 != 0)
+ {
+ temp32 = (UINT32)PARAM2 / (UINT32)PARAM3;
+ PARAM1 = (UINT32)PARAM2 % (UINT32)PARAM3;
+ PARAM0 = temp32;
+ }
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_DIVU, 4, 1):
+ if (PARAM3 != 0)
+ {
+ temp32 = (UINT32)PARAM2 / (UINT32)PARAM3;
+ PARAM1 = (UINT32)PARAM2 % (UINT32)PARAM3;
+ flags = FLAGS32_NZ(temp32);
+ PARAM0 = temp32;
+ }
+ else
+ flags = FLAG_V;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_DIVS, 4, 0): // DIVS dst,edst,src1,src2[,f]
+ if (PARAM3 != 0)
+ {
+ temp32 = (INT32)PARAM2 / (INT32)PARAM3;
+ PARAM1 = (INT32)PARAM2 % (INT32)PARAM3;
+ PARAM0 = temp32;
+ }
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_DIVS, 4, 1):
+ if (PARAM3 != 0)
+ {
+ temp32 = (INT32)PARAM2 / (INT32)PARAM3;
+ PARAM1 = (INT32)PARAM2 % (INT32)PARAM3;
+ flags = FLAGS32_NZ(temp32);
+ PARAM0 = temp32;
+ }
+ else
+ flags = FLAG_V;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_AND, 4, 0): // AND dst,src1,src2[,f]
+ PARAM0 = PARAM1 & PARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_AND, 4, 1):
+ temp32 = PARAM1 & PARAM2;
+ flags = FLAGS32_NZ(temp32);
+ PARAM0 = temp32;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_TEST, 4, 1): // TEST src1,src2[,f]
+ temp32 = PARAM0 & PARAM1;
+ flags = FLAGS32_NZ(temp32);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_OR, 4, 0): // OR dst,src1,src2[,f]
+ PARAM0 = PARAM1 | PARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_OR, 4, 1):
+ temp32 = PARAM1 | PARAM2;
+ flags = FLAGS32_NZ(temp32);
+ PARAM0 = temp32;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_XOR, 4, 0): // XOR dst,src1,src2[,f]
+ PARAM0 = PARAM1 ^ PARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_XOR, 4, 1):
+ temp32 = PARAM1 ^ PARAM2;
+ flags = FLAGS32_NZ(temp32);
+ PARAM0 = temp32;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LZCNT, 4, 0): // LZCNT dst,src
+ PARAM0 = count_leading_zeros(PARAM1);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LZCNT, 4, 1):
+ temp32 = count_leading_zeros(PARAM1);
+ flags = FLAGS32_NZ(temp32);
+ PARAM0 = temp32;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_BSWAP, 4, 0): // BSWAP dst,src
+ temp32 = PARAM1;
+ PARAM0 = FLIPENDIAN_INT32(temp32);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_BSWAP, 4, 1):
+ temp32 = PARAM1;
+ flags = FLAGS32_NZ(temp32);
+ PARAM0 = FLIPENDIAN_INT32(temp32);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_SHL, 4, 0): // SHL dst,src,count[,f]
+ PARAM0 = PARAM1 << (PARAM2 & 31);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_SHL, 4, 1):
+ shift = PARAM2 & 31;
+ temp32 = PARAM1 << shift;
+ flags = FLAGS32_NZ(temp32);
+ if (shift != 0) flags |= ((PARAM1 << (shift - 1)) >> 31) & FLAG_C;
+ PARAM0 = temp32;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_SHR, 4, 0): // SHR dst,src,count[,f]
+ PARAM0 = PARAM1 >> (PARAM2 & 31);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_SHR, 4, 1):
+ shift = PARAM2 & 31;
+ temp32 = PARAM1 >> shift;
+ flags = FLAGS32_NZ(temp32);
+ if (shift != 0) flags |= (PARAM1 >> (shift - 1)) & FLAG_C;
+ PARAM0 = temp32;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_SAR, 4, 0): // SAR dst,src,count[,f]
+ PARAM0 = (INT32)PARAM1 >> (PARAM2 & 31);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_SAR, 4, 1):
+ shift = PARAM2 & 31;
+ temp32 = (INT32)PARAM1 >> shift;
+ flags = FLAGS32_NZ(temp32);
+ if (shift != 0) flags |= (PARAM1 >> (shift - 1)) & FLAG_C;
+ PARAM0 = temp32;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_ROL, 4, 0): // ROL dst,src,count[,f]
+ shift = PARAM2 & 31;
+ PARAM0 = (PARAM1 << shift) | (PARAM1 >> ((32 - shift) & 31));
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_ROL, 4, 1):
+ shift = PARAM2 & 31;
+ temp32 = (PARAM1 << shift) | (PARAM1 >> ((32 - shift) & 31));
+ flags = FLAGS32_NZ(temp32);
+ if (shift != 0) flags |= ((PARAM1 << (shift - 1)) >> 31) & FLAG_C;
+ PARAM0 = temp32;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_ROLC, 4, 0): // ROLC dst,src,count[,f]
+ shift = PARAM2 & 31;
+ if (shift > 1)
+ PARAM0 = (PARAM1 << shift) | ((flags & FLAG_C) << (shift - 1)) | (PARAM1 >> (33 - shift));
+ else if (shift == 1)
+ PARAM0 = (PARAM1 << shift) | (flags & FLAG_C);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_ROLC, 4, 1):
+ shift = PARAM2 & 31;
+ if (shift > 1)
+ temp32 = (PARAM1 << shift) | ((flags & FLAG_C) << (shift - 1)) | (PARAM1 >> (33 - shift));
+ else if (shift == 1)
+ temp32 = (PARAM1 << shift) | (flags & FLAG_C);
+ else
+ temp32 = PARAM1;
+ flags = FLAGS32_NZ(temp32);
+ if (shift != 0) flags |= ((PARAM1 << (shift - 1)) >> 31) & FLAG_C;
+ PARAM0 = temp32;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_ROR, 4, 0): // ROR dst,src,count[,f]
+ shift = PARAM2 & 31;
+ PARAM0 = (PARAM1 >> shift) | (PARAM1 << ((32 - shift) & 31));
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_ROR, 4, 1):
+ shift = PARAM2 & 31;
+ temp32 = (PARAM1 >> shift) | (PARAM1 << ((32 - shift) & 31));
+ flags = FLAGS32_NZ(temp32);
+ if (shift != 0) flags |= (PARAM1 >> (shift - 1)) & FLAG_C;
+ PARAM0 = temp32;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_RORC, 4, 0): // RORC dst,src,count[,f]
+ shift = PARAM2 & 31;
+ if (shift > 1)
+ PARAM0 = (PARAM1 >> shift) | (((flags & FLAG_C) << 31) >> (shift - 1)) | (PARAM1 << (33 - shift));
+ else if (shift == 1)
+ PARAM0 = (PARAM1 >> shift) | ((flags & FLAG_C) << 31);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_RORC, 4, 1):
+ shift = PARAM2 & 31;
+ if (shift > 1)
+ temp32 = (PARAM1 >> shift) | (((flags & FLAG_C) << 31) >> (shift - 1)) | (PARAM1 << (33 - shift));
+ else if (shift == 1)
+ temp32 = (PARAM1 >> shift) | ((flags & FLAG_C) << 31);
+ else
+ temp32 = PARAM1;
+ flags = FLAGS32_NZ(temp32);
+ if (shift != 0) flags |= (PARAM1 >> (shift - 1)) & FLAG_C;
+ PARAM0 = temp32;
+ break;
+
+
+ // ----------------------- 64-Bit Integer Operations -----------------------
+
+ case MAKE_OPCODE_SHORT(OP_LOAD1, 8, 0): // DLOAD dst,base,index,BYTE
+ DPARAM0 = inst[1].puint8[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOAD1x2, 8, 0): // DLOAD dst,base,index,BYTE_x2
+ DPARAM0 = *(UINT8 *)&inst[1].puint16[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOAD1x4, 8, 0): // DLOAD dst,base,index,BYTE_x4
+ DPARAM0 = *(UINT8 *)&inst[1].puint32[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOAD1x8, 8, 0): // DLOAD dst,base,index,BYTE_x8
+ DPARAM0 = *(UINT8 *)&inst[1].puint64[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOAD2x1, 8, 0): // DLOAD dst,base,index,WORD_x1
+ DPARAM0 = *(UINT16 *)&inst[1].puint8[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOAD2, 8, 0): // DLOAD dst,base,index,WORD
+ DPARAM0 = inst[1].puint16[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOAD2x4, 8, 0): // DLOAD dst,base,index,WORD_x4
+ DPARAM0 = *(UINT16 *)&inst[1].puint32[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOAD2x8, 8, 0): // DLOAD dst,base,index,WORD_x8
+ DPARAM0 = *(UINT16 *)&inst[1].puint64[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOAD4x1, 8, 0): // DLOAD dst,base,index,DWORD_x1
+ DPARAM0 = *(UINT32 *)&inst[1].puint8[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOAD4x2, 8, 0): // DLOAD dst,base,index,DWORD_x2
+ DPARAM0 = *(UINT32 *)&inst[1].puint16[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOAD4, 8, 0): // DLOAD dst,base,index,DWORD
+ DPARAM0 = inst[1].puint32[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOAD4x8, 8, 0): // DLOAD dst,base,index,DWORD_x8
+ DPARAM0 = *(UINT32 *)&inst[1].puint64[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOAD8x1, 8, 0): // DLOAD dst,base,index,QWORD_x1
+ DPARAM0 = *(UINT64 *)&inst[1].puint8[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOAD8x2, 8, 0): // DLOAD dst,base,index,QWORD_x2
+ DPARAM0 = *(UINT64 *)&inst[1].puint16[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOAD8x4, 8, 0): // DLOAD dst,base,index,QWORD_x4
+ DPARAM0 = *(UINT64 *)&inst[1].puint32[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOAD8, 8, 0): // DLOAD dst,base,index,QWORD
+ DPARAM0 = inst[1].puint64[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOADS1, 8, 0): // DLOADS dst,base,index,BYTE
+ DPARAM0 = inst[1].pint8[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOADS1x2, 8, 0): // DLOADS dst,base,index,BYTE_x2
+ DPARAM0 = *(INT8 *)&inst[1].pint16[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOADS1x4, 8, 0): // DLOADS dst,base,index,BYTE_x4
+ DPARAM0 = *(INT8 *)&inst[1].pint32[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOADS1x8, 8, 0): // DLOADS dst,base,index,BYTE_x8
+ DPARAM0 = *(INT8 *)&inst[1].pint64[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOADS2x1, 8, 0): // DLOADS dst,base,index,WORD_x1
+ DPARAM0 = *(INT16 *)&inst[1].pint8[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOADS2, 8, 0): // DLOADS dst,base,index,WORD
+ DPARAM0 = inst[1].pint16[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOADS2x4, 8, 0): // DLOADS dst,base,index,WORD_x4
+ DPARAM0 = *(INT16 *)&inst[1].pint32[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOADS2x8, 8, 0): // DLOADS dst,base,index,WORD_x8
+ DPARAM0 = *(INT16 *)&inst[1].pint64[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOADS4x1, 8, 0): // DLOADS dst,base,index,DWORD_x1
+ DPARAM0 = *(INT32 *)&inst[1].pint8[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOADS4x2, 8, 0): // DLOADS dst,base,index,DWORD_x2
+ DPARAM0 = *(INT32 *)&inst[1].pint16[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOADS4, 8, 0): // DLOADS dst,base,index,DWORD
+ DPARAM0 = inst[1].pint32[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOADS4x8, 8, 0): // DLOADS dst,base,index,DWORD_x8
+ DPARAM0 = *(INT32 *)&inst[1].pint64[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOADS8x1, 8, 0): // DLOADS dst,base,index,QWORD_x1
+ DPARAM0 = *(INT64 *)&inst[1].pint8[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOADS8x2, 8, 0): // DLOADS dst,base,index,QWORD_x2
+ DPARAM0 = *(INT64 *)&inst[1].pint16[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOADS8x4, 8, 0): // DLOADS dst,base,index,QWORD_x4
+ DPARAM0 = *(INT64 *)&inst[1].pint32[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LOADS8, 8, 0): // DLOADS dst,base,index,QWORD
+ DPARAM0 = inst[1].pint64[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_STORE1, 8, 0): // DSTORE dst,base,index,BYTE
+ inst[0].puint8[PARAM1] = DPARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_STORE1x2, 8, 0): // DSTORE dst,base,index,BYTE_x2
+ *(UINT8 *)&inst[0].puint16[PARAM1] = DPARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_STORE1x4, 8, 0): // DSTORE dst,base,index,BYTE_x4
+ *(UINT8 *)&inst[0].puint32[PARAM1] = DPARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_STORE1x8, 8, 0): // DSTORE dst,base,index,BYTE_x8
+ *(UINT8 *)&inst[0].puint64[PARAM1] = DPARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_STORE2x1, 8, 0): // DSTORE dst,base,index,WORD_x1
+ *(UINT16 *)&inst[0].puint8[PARAM1] = DPARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_STORE2, 8, 0): // DSTORE dst,base,index,WORD
+ inst[0].puint16[PARAM1] = DPARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_STORE2x4, 8, 0): // DSTORE dst,base,index,WORD_x4
+ *(UINT16 *)&inst[0].puint32[PARAM1] = DPARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_STORE2x8, 8, 0): // DSTORE dst,base,index,WORD_x8
+ *(UINT16 *)&inst[0].puint64[PARAM1] = DPARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_STORE4x1, 8, 0): // DSTORE dst,base,index,DWORD_x1
+ *(UINT32 *)&inst[0].puint8[PARAM1] = DPARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_STORE4x2, 8, 0): // DSTORE dst,base,index,DWORD_x2
+ *(UINT32 *)&inst[0].puint16[PARAM1] = DPARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_STORE4, 8, 0): // DSTORE dst,base,index,DWORD
+ inst[0].puint32[PARAM1] = DPARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_STORE4x8, 8, 0): // DSTORE dst,base,index,DWORD_x8
+ *(UINT32 *)&inst[0].puint64[PARAM1] = DPARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_STORE8x1, 8, 0): // DSTORE dst,base,index,QWORD_x1
+ *(UINT64 *)&inst[0].puint8[PARAM1] = DPARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_STORE8x2, 8, 0): // DSTORE dst,base,index,QWORD_x2
+ *(UINT64 *)&inst[0].puint16[PARAM1] = DPARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_STORE8x4, 8, 0): // DSTORE dst,base,index,QWORD_x4
+ *(UINT64 *)&inst[0].puint32[PARAM1] = DPARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_STORE8, 8, 0): // DSTORE dst,base,index,QWORD
+ inst[0].puint64[PARAM1] = DPARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_READ1, 8, 0): // DREAD dst,src1,space_BYTE
+ DPARAM0 = m_space[PARAM2]->read_byte(PARAM1);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_READ2, 8, 0): // DREAD dst,src1,space_WORD
+ DPARAM0 = m_space[PARAM2]->read_word(PARAM1);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_READ4, 8, 0): // DREAD dst,src1,space_DWORD
+ DPARAM0 = m_space[PARAM2]->read_dword(PARAM1);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_READ8, 8, 0): // DREAD dst,src1,space_QOWRD
+ DPARAM0 = m_space[PARAM2]->read_qword(PARAM1);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_READM2, 8, 0): // DREADM dst,src1,mask,space_WORD
+ DPARAM0 = m_space[PARAM3]->read_word(PARAM1, PARAM2);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_READM4, 8, 0): // DREADM dst,src1,mask,space_DWORD
+ DPARAM0 = m_space[PARAM3]->read_dword(PARAM1, PARAM2);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_READM8, 8, 0): // DREADM dst,src1,mask,space_QWORD
+ DPARAM0 = m_space[PARAM3]->read_qword(PARAM1, PARAM2);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_WRITE1, 8, 0): // DWRITE dst,src1,space_BYTE
+ m_space[PARAM2]->write_byte(PARAM0, PARAM1);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_WRITE2, 8, 0): // DWRITE dst,src1,space_WORD
+ m_space[PARAM2]->write_word(PARAM0, PARAM1);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_WRITE4, 8, 0): // DWRITE dst,src1,space_DWORD
+ m_space[PARAM2]->write_dword(PARAM0, PARAM1);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_WRITE8, 8, 0): // DWRITE dst,src1,space_QWORD
+ m_space[PARAM2]->write_qword(PARAM0, DPARAM1);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_WRITEM2, 8, 0): // DWRITEM dst,src1,mask,space_WORD
+ m_space[PARAM3]->write_word(PARAM0, DPARAM1, DPARAM2);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_WRITEM4, 8, 0): // DWRITEM dst,src1,mask,space_DWORD
+ m_space[PARAM3]->write_dword(PARAM0, DPARAM1, DPARAM2);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_WRITEM8, 8, 0): // DWRITEM dst,src1,mask,space_QWORD
+ m_space[PARAM3]->write_qword(PARAM0, DPARAM1, DPARAM2);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_CARRY, 8, 0): // DCARRY src,bitnum
+ flags = (flags & ~FLAG_C) | ((DPARAM0 >> (DPARAM1 & 63)) & FLAG_C);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_MOV, 8, 1): // DMOV dst,src[,c]
+ if (OPCODE_FAIL_CONDITION(opcode, flags))
+ break;
+ // fall through...
+
+ case MAKE_OPCODE_SHORT(OP_MOV, 8, 0):
+ DPARAM0 = DPARAM1;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_SET, 8, 1): // DSET dst,c
+ DPARAM0 = OPCODE_FAIL_CONDITION(opcode, flags) ? 0 : 1;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_SEXT1, 8, 0): // DSEXT dst,src,BYTE
+ DPARAM0 = (INT8)PARAM1;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_SEXT1, 8, 1):
+ temp64 = (INT8)PARAM1;
+ flags = FLAGS64_NZ(temp64);
+ DPARAM0 = temp64;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_SEXT2, 8, 0): // DSEXT dst,src,WORD
+ DPARAM0 = (INT16)PARAM1;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_SEXT2, 8, 1):
+ temp64 = (INT16)PARAM1;
+ flags = FLAGS64_NZ(temp64);
+ DPARAM0 = temp64;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_SEXT4, 8, 0): // DSEXT dst,src,DWORD
+ DPARAM0 = (INT32)PARAM1;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_SEXT4, 8, 1):
+ temp64 = (INT32)PARAM1;
+ flags = FLAGS64_NZ(temp64);
+ DPARAM0 = temp64;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_ROLAND, 8, 0): // DROLAND dst,src,count,mask[,f]
+ shift = DPARAM2 & 63;
+ DPARAM0 = ((DPARAM1 << shift) | (DPARAM1 >> (64 - shift))) & DPARAM3;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_ROLAND, 8, 1):
+ shift = DPARAM2 & 63;
+ temp64 = ((DPARAM1 << shift) | (DPARAM1 >> (64 - shift))) & DPARAM3;
+ flags = FLAGS64_NZ(temp64);
+ DPARAM0 = temp64;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_ROLINS, 8, 0): // DROLINS dst,src,count,mask[,f]
+ shift = DPARAM2 & 63;
+ DPARAM0 = (DPARAM0 & ~DPARAM3) | (((DPARAM1 << shift) | (DPARAM1 >> (64 - shift))) & DPARAM3);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_ROLINS, 8, 1):
+ shift = DPARAM2 & 63;
+ temp64 = (DPARAM0 & ~DPARAM3) | (((DPARAM1 << shift) | (DPARAM1 >> (64 - shift))) & DPARAM3);
+ flags = FLAGS64_NZ(temp64);
+ DPARAM0 = temp64;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_ADD, 8, 0): // DADD dst,src1,src2[,f]
+ DPARAM0 = DPARAM1 + DPARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_ADD, 8, 1):
+ temp64 = DPARAM1 + DPARAM2;
+ flags = FLAGS64_NZCV_ADD(temp64, DPARAM1, DPARAM2);
+ DPARAM0 = temp64;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_ADDC, 8, 0): // DADDC dst,src1,src2[,f]
+ DPARAM0 = DPARAM1 + DPARAM2 + (flags & FLAG_C);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_ADDC, 8, 1):
+ temp64 = DPARAM1 + DPARAM2 + (flags & FLAG_C);
+ if (DPARAM2 + 1 != 0)
+ flags = FLAGS64_NZCV_ADD(temp64, DPARAM1, DPARAM2 + (flags & FLAG_C));
+ else
+ flags = FLAGS64_NZCV_ADD(temp64, DPARAM1 + (flags & FLAG_C), DPARAM2);
+ DPARAM0 = temp64;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_SUB, 8, 0): // DSUB dst,src1,src2[,f]
+ DPARAM0 = DPARAM1 - DPARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_SUB, 8, 1):
+ temp64 = DPARAM1 - DPARAM2;
+ flags = FLAGS64_NZCV_SUB(temp64, DPARAM1, DPARAM2);
+ DPARAM0 = temp64;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_SUBB, 8, 0): // DSUBB dst,src1,src2[,f]
+ DPARAM0 = DPARAM1 - DPARAM2 - (flags & FLAG_C);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_SUBB, 8, 1):
+ temp64 = DPARAM1 - DPARAM2 - (flags & FLAG_C);
+ if (DPARAM2 + 1 != 0)
+ flags = FLAGS64_NZCV_SUB(temp64, DPARAM1, DPARAM2 + (flags & FLAG_C));
+ else
+ flags = FLAGS64_NZCV_SUB(temp64, DPARAM1 - (flags & FLAG_C), DPARAM2);
+ DPARAM0 = temp64;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_CMP, 8, 1): // DCMP src1,src2[,f]
+ temp64 = DPARAM0 - DPARAM1;
+ flags = FLAGS64_NZCV_SUB(temp64, DPARAM0, DPARAM1);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_MULU, 8, 0): // DMULU dst,edst,src1,src2[,f]
+ dmulu(*inst[0].puint64, *inst[1].puint64, DPARAM2, DPARAM3, FALSE);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_MULU, 8, 1):
+ flags = dmulu(*inst[0].puint64, *inst[1].puint64, DPARAM2, DPARAM3, TRUE);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_MULS, 8, 0): // DMULS dst,edst,src1,src2[,f]
+ dmuls(*inst[0].puint64, *inst[1].puint64, DPARAM2, DPARAM3, FALSE);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_MULS, 8, 1):
+ flags = dmuls(*inst[0].puint64, *inst[1].puint64, DPARAM2, DPARAM3, TRUE);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_DIVU, 8, 0): // DDIVU dst,edst,src1,src2[,f]
+ if (DPARAM3 != 0)
+ {
+ temp64 = (UINT64)DPARAM2 / (UINT64)DPARAM3;
+ DPARAM1 = (UINT64)DPARAM2 % (UINT64)DPARAM3;
+ DPARAM0 = temp64;
+ }
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_DIVU, 8, 1):
+ if (DPARAM3 != 0)
+ {
+ temp64 = (UINT64)DPARAM2 / (UINT64)DPARAM3;
+ DPARAM1 = (UINT64)DPARAM2 % (UINT64)DPARAM3;
+ flags = FLAGS64_NZ(temp64);
+ DPARAM0 = temp64;
+ }
+ else
+ flags = FLAG_V;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_DIVS, 8, 0): // DDIVS dst,edst,src1,src2[,f]
+ if (DPARAM3 != 0)
+ {
+ temp64 = (INT64)DPARAM2 / (INT64)DPARAM3;
+ DPARAM1 = (INT64)DPARAM2 % (INT64)DPARAM3;
+ DPARAM0 = temp64;
+ }
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_DIVS, 8, 1):
+ if (DPARAM3 != 0)
+ {
+ temp64 = (INT64)DPARAM2 / (INT64)DPARAM3;
+ DPARAM1 = (INT64)DPARAM2 % (INT64)DPARAM3;
+ flags = FLAGS64_NZ(temp64);
+ DPARAM0 = temp64;
+ }
+ else
+ flags = FLAG_V;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_AND, 8, 0): // DAND dst,src1,src2[,f]
+ DPARAM0 = DPARAM1 & DPARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_AND, 8, 1):
+ temp64 = DPARAM1 & DPARAM2;
+ flags = FLAGS64_NZ(temp64);
+ DPARAM0 = temp64;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_TEST, 8, 1): // DTEST src1,src2[,f]
+ temp64 = DPARAM1 & DPARAM2;
+ flags = FLAGS64_NZ(temp64);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_OR, 8, 0): // DOR dst,src1,src2[,f]
+ DPARAM0 = DPARAM1 | DPARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_OR, 8, 1):
+ temp64 = DPARAM1 | DPARAM2;
+ flags = FLAGS64_NZ(temp64);
+ DPARAM0 = temp64;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_XOR, 8, 0): // DXOR dst,src1,src2[,f]
+ DPARAM0 = DPARAM1 ^ DPARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_XOR, 8, 1):
+ temp64 = DPARAM1 ^ DPARAM2;
+ flags = FLAGS64_NZ(temp64);
+ DPARAM0 = temp64;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LZCNT, 8, 0): // DLZCNT dst,src
+ if ((UINT32)(DPARAM1 >> 32) != 0)
+ DPARAM0 = count_leading_zeros(DPARAM1 >> 32);
+ else
+ DPARAM0 = 32 + count_leading_zeros(DPARAM1);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_LZCNT, 8, 1):
+ if ((UINT32)(DPARAM1 >> 32) != 0)
+ temp64 = count_leading_zeros(DPARAM1 >> 32);
+ else
+ temp64 = 32 + count_leading_zeros(DPARAM1);
+ flags = FLAGS64_NZ(temp64);
+ DPARAM0 = temp64;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_BSWAP, 8, 0): // DBSWAP dst,src
+ temp64 = DPARAM1;
+ DPARAM0 = FLIPENDIAN_INT64(temp64);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_BSWAP, 8, 1):
+ temp64 = DPARAM1;
+ flags = FLAGS64_NZ(temp64);
+ DPARAM0 = FLIPENDIAN_INT64(temp64);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_SHL, 8, 0): // DSHL dst,src,count[,f]
+ DPARAM0 = DPARAM1 << (DPARAM2 & 63);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_SHL, 8, 1):
+ shift = DPARAM2 & 63;
+ temp64 = DPARAM1 << shift;
+ flags = FLAGS64_NZ(temp64);
+ if (shift != 0) flags |= ((DPARAM1 << (shift - 1)) >> 63) & FLAG_C;
+ DPARAM0 = temp64;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_SHR, 8, 0): // DSHR dst,src,count[,f]
+ DPARAM0 = DPARAM1 >> (DPARAM2 & 63);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_SHR, 8, 1):
+ shift = DPARAM2 & 63;
+ temp64 = DPARAM1 >> shift;
+ flags = FLAGS64_NZ(temp64);
+ if (shift != 0) flags |= (DPARAM1 >> (shift - 1)) & FLAG_C;
+ DPARAM0 = temp64;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_SAR, 8, 0): // DSAR dst,src,count[,f]
+ DPARAM0 = (INT64)DPARAM1 >> (DPARAM2 & 63);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_SAR, 8, 1):
+ shift = DPARAM2 & 63;
+ temp64 = (INT32)DPARAM1 >> shift;
+ flags = FLAGS64_NZ(temp64);
+ if (shift != 0) flags |= (DPARAM1 >> (shift - 1)) & FLAG_C;
+ DPARAM0 = temp64;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_ROL, 8, 0): // DROL dst,src,count[,f]
+ shift = DPARAM2 & 31;
+ DPARAM0 = (DPARAM1 << shift) | (DPARAM1 >> ((64 - shift) & 63));
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_ROL, 8, 1):
+ shift = DPARAM2 & 63;
+ temp64 = (DPARAM1 << shift) | (DPARAM1 >> ((64 - shift) & 63));
+ flags = FLAGS64_NZ(temp64);
+ if (shift != 0) flags |= ((DPARAM1 << (shift - 1)) >> 63) & FLAG_C;
+ DPARAM0 = temp64;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_ROLC, 8, 0): // DROLC dst,src,count[,f]
+ shift = DPARAM2 & 63;
+ if (shift > 1)
+ DPARAM0 = (DPARAM1 << shift) | ((flags & FLAG_C) << (shift - 1)) | (DPARAM1 >> (65 - shift));
+ else if (shift == 1)
+ DPARAM0 = (DPARAM1 << shift) | (flags & FLAG_C);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_ROLC, 8, 1):
+ shift = DPARAM2 & 63;
+ if (shift > 1)
+ temp64 = (DPARAM1 << shift) | ((flags & FLAG_C) << (shift - 1)) | (DPARAM1 >> (65 - shift));
+ else if (shift == 1)
+ temp64 = (DPARAM1 << shift) | (flags & FLAG_C);
+ else
+ temp64 = DPARAM1;
+ flags = FLAGS64_NZ(temp64);
+ if (shift != 0) flags |= ((DPARAM1 << (shift - 1)) >> 63) & FLAG_C;
+ DPARAM0 = temp64;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_ROR, 8, 0): // DROR dst,src,count[,f]
+ shift = DPARAM2 & 63;
+ DPARAM0 = (DPARAM1 >> shift) | (DPARAM1 << ((64 - shift) & 63));
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_ROR, 8, 1):
+ shift = DPARAM2 & 63;
+ temp64 = (DPARAM1 >> shift) | (DPARAM1 << ((64 - shift) & 63));
+ flags = FLAGS64_NZ(temp64);
+ if (shift != 0) flags |= (DPARAM1 >> (shift - 1)) & FLAG_C;
+ DPARAM0 = temp64;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_RORC, 8, 0): // DRORC dst,src,count[,f]
+ shift = DPARAM2 & 63;
+ if (shift > 1)
+ DPARAM0 = (DPARAM1 >> shift) | ((((UINT64)flags & FLAG_C) << 63) >> (shift - 1)) | (DPARAM1 << (65 - shift));
+ else if (shift == 1)
+ DPARAM0 = (DPARAM1 >> shift) | (((UINT64)flags & FLAG_C) << 63);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_RORC, 8, 1):
+ shift = DPARAM2 & 63;
+ if (shift > 1)
+ temp64 = (DPARAM1 >> shift) | ((((UINT64)flags & FLAG_C) << 63) >> (shift - 1)) | (DPARAM1 << (65 - shift));
+ else if (shift == 1)
+ temp64 = (DPARAM1 >> shift) | (((UINT64)flags & FLAG_C) << 63);
+ else
+ temp64 = DPARAM1;
+ flags = FLAGS64_NZ(temp64);
+ if (shift != 0) flags |= (DPARAM1 >> (shift - 1)) & FLAG_C;
+ DPARAM0 = temp64;
+ break;
+
+
+ // ----------------------- 32-Bit Floating Point Operations -----------------------
+
+ case MAKE_OPCODE_SHORT(OP_FLOAD, 4, 0): // FSLOAD dst,base,index
+ FSPARAM0 = inst[1].pfloat[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FSTORE, 4, 0): // FSSTORE dst,base,index
+ inst[0].pfloat[PARAM1] = FSPARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FREAD, 4, 0): // FSREAD dst,src1,space
+ PARAM0 = m_space[PARAM2]->read_dword(PARAM1);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FWRITE, 4, 0): // FSWRITE dst,src1,space
+ m_space[PARAM2]->write_dword(PARAM0, PARAM1);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FMOV, 4, 1): // FSMOV dst,src[,c]
+ if (OPCODE_FAIL_CONDITION(opcode, flags))
+ break;
+ // fall through...
+
+ case MAKE_OPCODE_SHORT(OP_FMOV, 4, 0):
+ FSPARAM0 = FSPARAM1;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FTOI4T, 4, 0): // FSTOI4T dst,src1
+ if (FSPARAM1 >= 0)
+ *inst[0].pint32 = floor(FSPARAM1);
+ else
+ *inst[0].pint32 = ceil(FSPARAM1);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FTOI4R, 4, 0): // FSTOI4R dst,src1
+ if (FSPARAM1 >= 0)
+ *inst[0].pint32 = floor(FSPARAM1 + 0.5f);
+ else
+ *inst[0].pint32 = ceil(FSPARAM1 - 0.5f);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FTOI4F, 4, 0): // FSTOI4F dst,src1
+ *inst[0].pint32 = floor(FSPARAM1);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FTOI4C, 4, 0): // FSTOI4C dst,src1
+ *inst[0].pint32 = ceil(FSPARAM1);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FTOI4, 4, 0): // FSTOI4 dst,src1
+ *inst[0].pint32 = FSPARAM1;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FTOI8T, 4, 0): // FSTOI8T dst,src1
+ if (FSPARAM1 >= 0)
+ *inst[0].pint64 = floor(FSPARAM1);
+ else
+ *inst[0].pint64 = ceil(FSPARAM1);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FTOI8R, 4, 0): // FSTOI8R dst,src1
+ if (FSPARAM1 >= 0)
+ *inst[0].pint64 = floor(FSPARAM1 + 0.5f);
+ else
+ *inst[0].pint64 = ceil(FSPARAM1 - 0.5f);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FTOI8F, 4, 0): // FSTOI8F dst,src1
+ *inst[0].pint64 = floor(FSPARAM1);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FTOI8C, 4, 0): // FSTOI8C dst,src1
+ *inst[0].pint64 = ceil(FSPARAM1);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FTOI8, 4, 0): // FSTOI8 dst,src1
+ *inst[0].pint64 = FSPARAM1;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FFRI4, 4, 0): // FSFRI4 dst,src1
+ FSPARAM0 = *inst[1].pint32;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FFRI8, 4, 0): // FSFRI8 dst,src1
+ FSPARAM0 = *inst[1].pint64;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FFRFD, 4, 0): // FSFRFD dst,src1
+ FSPARAM0 = FDPARAM1;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FADD, 4, 0): // FSADD dst,src1,src2
+ FSPARAM0 = FSPARAM1 + FSPARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FSUB, 4, 0): // FSSUB dst,src1,src2
+ FSPARAM0 = FSPARAM1 - FSPARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FCMP, 4, 1): // FSCMP src1,src2
+ if (isnan(FSPARAM0) || isnan(FSPARAM1))
+ flags = FLAG_U;
+ else
+ flags = (FSPARAM0 < FSPARAM1) | ((FSPARAM0 == FSPARAM1) << 2);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FMUL, 4, 0): // FSMUL dst,src1,src2
+ FSPARAM0 = FSPARAM1 * FSPARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FDIV, 4, 0): // FSDIV dst,src1,src2
+ FSPARAM0 = FSPARAM1 / FSPARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FNEG, 4, 0): // FSNEG dst,src1
+ FSPARAM0 = -FSPARAM1;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FABS, 4, 0): // FSABS dst,src1
+ FSPARAM0 = fabs(FSPARAM1);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FSQRT, 4, 0): // FSSQRT dst,src1
+ FSPARAM0 = sqrt(FSPARAM1);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FRECIP, 4, 0): // FSRECIP dst,src1
+ FSPARAM0 = 1.0f / FSPARAM1;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FRSQRT, 4, 0): // FSRSQRT dst,src1
+ FSPARAM0 = 1.0f / sqrt(FSPARAM1);
+ break;
+
+
+ // ----------------------- 64-Bit Floating Point Operations -----------------------
+
+ case MAKE_OPCODE_SHORT(OP_FLOAD, 8, 0): // FDLOAD dst,base,index
+ FDPARAM0 = inst[1].pdouble[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FSTORE, 8, 0): // FDSTORE dst,base,index
+ inst[0].pdouble[PARAM1] = FDPARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FREAD, 8, 0): // FDREAD dst,src1,space
+ DPARAM0 = m_space[PARAM2]->read_qword(PARAM1);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FWRITE, 8, 0): // FDWRITE dst,src1,space
+ m_space[PARAM2]->write_qword(PARAM0, DPARAM1);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FMOV, 8, 1): // FDMOV dst,src[,c]
+ if (OPCODE_FAIL_CONDITION(opcode, flags))
+ break;
+ // fall through...
+
+ case MAKE_OPCODE_SHORT(OP_FMOV, 8, 0):
+ FDPARAM0 = FDPARAM1;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FTOI4T, 8, 0): // FDTOI4T dst,src1
+ if (FDPARAM1 >= 0)
+ *inst[0].pint32 = floor(FDPARAM1);
+ else
+ *inst[0].pint32 = ceil(FDPARAM1);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FTOI4R, 8, 0): // FDTOI4R dst,src1
+ if (FDPARAM1 >= 0)
+ *inst[0].pint32 = floor(FDPARAM1 + 0.5);
+ else
+ *inst[0].pint32 = ceil(FDPARAM1 - 0.5);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FTOI4F, 8, 0): // FDTOI4F dst,src1
+ *inst[0].pint32 = floor(FDPARAM1);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FTOI4C, 8, 0): // FDTOI4C dst,src1
+ *inst[0].pint32 = ceil(FDPARAM1);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FTOI4, 8, 0): // FDTOI4 dst,src1
+ *inst[0].pint32 = FDPARAM1;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FTOI8T, 8, 0): // FDTOI8T dst,src1
+ if (FDPARAM1 >= 0)
+ *inst[0].pint64 = floor(FDPARAM1);
+ else
+ *inst[0].pint64 = ceil(FDPARAM1);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FTOI8R, 8, 0): // FDTOI8R dst,src1
+ if (FDPARAM1 >= 0)
+ *inst[0].pint64 = floor(FDPARAM1 + 0.5);
+ else
+ *inst[0].pint64 = ceil(FDPARAM1 - 0.5);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FTOI8F, 8, 0): // FDTOI8F dst,src1
+ *inst[0].pint64 = floor(FDPARAM1);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FTOI8C, 8, 0): // FDTOI8C dst,src1
+ *inst[0].pint64 = ceil(FDPARAM1);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FTOI8, 8, 0): // FDTOI8 dst,src1
+ *inst[0].pint64 = FDPARAM1;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FFRI4, 8, 0): // FDFRI4 dst,src1
+ FDPARAM0 = *inst[1].pint32;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FFRI8, 8, 0): // FDFRI8 dst,src1
+ FDPARAM0 = *inst[1].pint64;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FFRFS, 8, 0): // FDFRFS dst,src1
+ FDPARAM0 = FSPARAM1;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FRNDS, 8, 0): // FDRNDS dst,src1
+ FDPARAM0 = (float)FDPARAM1;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FADD, 8, 0): // FDADD dst,src1,src2
+ FDPARAM0 = FDPARAM1 + FDPARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FSUB, 8, 0): // FDSUB dst,src1,src2
+ FDPARAM0 = FDPARAM1 - FDPARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FCMP, 8, 1): // FDCMP src1,src2
+ if (isnan(FDPARAM0) || isnan(FDPARAM1))
+ flags = FLAG_U;
+ else
+ flags = (FDPARAM0 < FDPARAM1) | ((FDPARAM0 == FDPARAM1) << 2);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FMUL, 8, 0): // FDMUL dst,src1,src2
+ FDPARAM0 = FDPARAM1 * FDPARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FDIV, 8, 0): // FDDIV dst,src1,src2
+ FDPARAM0 = FDPARAM1 / FDPARAM2;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FNEG, 8, 0): // FDNEG dst,src1
+ FDPARAM0 = -FDPARAM1;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FABS, 8, 0): // FDABS dst,src1
+ FDPARAM0 = fabs(FDPARAM1);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FSQRT, 8, 0): // FDSQRT dst,src1
+ FDPARAM0 = sqrt(FDPARAM1);
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FRECIP, 8, 0): // FDRECIP dst,src1
+ FDPARAM0 = 1.0 / FDPARAM1;
+ break;
+
+ case MAKE_OPCODE_SHORT(OP_FRSQRT, 8, 0): // FDRSQRT dst,src1
+ FDPARAM0 = 1.0 / sqrt(FDPARAM1);
+ break;
+
+ default:
+ fatalerror("Unexpected opcode!");
+ break;
+ }
+
+ // advance past the parameters and immediates
+ inst += OPCODE_GET_PWORDS(opcode);
+ }
+
+ return 0;
+}
+
+
+//-------------------------------------------------
+// output_parameter - output a parameter
+//-------------------------------------------------
+
+void drcbe_c::output_parameter(drcbec_instruction **dstptr, void **immedptr, int size, const parameter &param)
+{
+ drcbec_instruction *dst = *dstptr;
+ void *immed = *immedptr;
+ parameter temp_param;
+
+ switch (param.type())
+ {
+ // immediates store a pointer to the immediate data, which is stored at the end of the instruction
+ case parameter::PTYPE_IMMEDIATE:
+ if (param.immediate() == 0)
+ (dst++)->v = &s_immediate_zero;
+ else
+ {
+ (dst++)->v = immed;
+ if (size == 4)
+ *(UINT32 *)immed = (UINT32)param.immediate();
+ else
+ *(UINT64 *)immed = (UINT64)param.immediate();
+ immed = (UINT8 *)immed + size;
+ }
+ break;
+
+ // int registers point to the appropriate part of the integer register state
+ case parameter::PTYPE_INT_REGISTER:
+ if (size == 4)
+ (dst++)->puint32 = &m_state.r[param.ireg() - REG_I0].w.l;
+ else
+ (dst++)->puint64 = &m_state.r[param.ireg() - REG_I0].d;
+ break;
+
+ // float registers point to the appropriate part of the floating point register state
+ case parameter::PTYPE_FLOAT_REGISTER:
+ if (size == 4)
+ (dst++)->pfloat = &m_state.f[param.freg() - REG_F0].s.l;
+ else
+ (dst++)->pdouble = &m_state.f[param.freg() - REG_F0].d;
+ break;
+
+ // convert mapvars to immediates
+ case parameter::PTYPE_MAPVAR:
+ temp_param = m_map.get_last_value(param.mapvar());
+ return output_parameter(dstptr, immedptr, size, temp_param);
+
+ // memory just points to the memory
+ case parameter::PTYPE_MEMORY:
+ (dst++)->v = param.memory();
+ break;
+
+ // ignore these parameters: they are directly encoded in the opcode
+ case parameter::PTYPE_SIZE:
+ case parameter::PTYPE_SIZE_SCALE:
+ case parameter::PTYPE_ROUNDING:
+ case parameter::PTYPE_STRING:
+ return output_parameter(dstptr, immedptr, size, 0);
+
+ // space/size parameters; sizes are built into our opcodes, but space needs to be encoded
+ case parameter::PTYPE_SIZE_SPACE:
+ return output_parameter(dstptr, immedptr, size, param.space());
+
+ // code handle just points to the handle
+ case parameter::PTYPE_CODE_HANDLE:
+ (dst++)->handle = &param.handle();
+ break;
+
+ // code label just contains the label value
+ case parameter::PTYPE_CODE_LABEL:
+ return output_parameter(dstptr, immedptr, size, UINT32(param.label()));
+
+ // c_function just points to the C function
+ case parameter::PTYPE_C_FUNCTION:
+ (dst++)->cfunc = param.cfunc();
+ break;
+
+ default:
+ fatalerror("Unexpected param->type");
+ break;
+ }
+
+ *dstptr = dst;
+ *immedptr = immed;
+}
+
+
+//-------------------------------------------------
+// fixup_label - callback to fixup forward-
+// referenced labels
+//-------------------------------------------------
+
+void drcbe_c::fixup_label(void *parameter, drccodeptr labelcodeptr)
+{
+ drcbec_instruction *dst = (drcbec_instruction *)parameter;
+ dst->inst = (drcbec_instruction *)labelcodeptr;
+}
+
+
+//-------------------------------------------------
+// dmulu - perform a double-wide unsigned multiply
+//-------------------------------------------------
+
+int drcbe_c::dmulu(UINT64 &dstlo, UINT64 &dsthi, UINT64 src1, UINT64 src2, int flags)
+{
+ // shortcut if we don't care about the high bits or the flags
+ if (&dstlo == &dsthi && flags == 0)
+ {
+ dstlo = src1 * src2;
+ return 0;
+ }
+
+ // fetch source values
+ UINT64 a = src1;
+ UINT64 b = src2;
+ if (a == 0 || b == 0)
+ {
+ dsthi = dstlo = 0;
+ return FLAG_Z;
+ }
+
+ // compute high and low parts first
+ UINT64 lo = (UINT64)(UINT32)(a >> 0) * (UINT64)(UINT32)(b >> 0);
+ UINT64 hi = (UINT64)(UINT32)(a >> 32) * (UINT64)(UINT32)(b >> 32);
+
+ // compute middle parts
+ UINT64 prevlo = lo;
+ UINT64 temp = (UINT64)(UINT32)(a >> 32) * (UINT64)(UINT32)(b >> 0);
+ lo += temp << 32;
+ hi += (temp >> 32) + (lo < prevlo);
+
+ prevlo = lo;
+ temp = (UINT64)(UINT32)(a >> 0) * (UINT64)(UINT32)(b >> 32);
+ lo += temp << 32;
+ hi += (temp >> 32) + (lo < prevlo);
+
+ // store the results
+ dsthi = hi;
+ dstlo = lo;
+ return ((hi >> 60) & FLAG_S) | ((dsthi != 0) << 1);
+}
+
+
+//-------------------------------------------------
+// dmuls - perform a double-wide signed multiply
+//-------------------------------------------------
+
+int drcbe_c::dmuls(UINT64 &dstlo, UINT64 &dsthi, INT64 src1, INT64 src2, int flags)
+{
+ // shortcut if we don't care about the high bits or the flags
+ if (&dstlo == &dsthi && flags == 0)
+ {
+ dstlo = src1 * src2;
+ return 0;
+ }
+
+ // fetch absolute source values
+ UINT64 a = src1; if ((INT64)a < 0) a = -a;
+ UINT64 b = src2; if ((INT64)b < 0) b = -b;
+ if (a == 0 || b == 0)
+ {
+ dsthi = dstlo = 0;
+ return FLAG_Z;
+ }
+
+ // compute high and low parts first
+ UINT64 lo = (UINT64)(UINT32)(a >> 0) * (UINT64)(UINT32)(b >> 0);
+ UINT64 hi = (UINT64)(UINT32)(a >> 32) * (UINT64)(UINT32)(b >> 32);
+
+ // compute middle parts
+ UINT64 prevlo = lo;
+ UINT64 temp = (UINT64)(UINT32)(a >> 32) * (UINT64)(UINT32)(b >> 0);
+ lo += temp << 32;
+ hi += (temp >> 32) + (lo < prevlo);
+
+ prevlo = lo;
+ temp = (UINT64)(UINT32)(a >> 0) * (UINT64)(UINT32)(b >> 32);
+ lo += temp << 32;
+ hi += (temp >> 32) + (lo < prevlo);
+
+ // adjust for signage
+ if ((INT64)(src1 ^ src2) < 0)
+ {
+ hi = ~hi + (lo == 0);
+ lo = ~lo + 1;
+ }
+
+ // store the results
+ dsthi = hi;
+ dstlo = lo;
+ return ((hi >> 60) & FLAG_S) | ((dsthi != ((INT64)lo >> 63)) << 1);
+}
diff --git a/trunk/src/emu/cpu/drcbec.h b/trunk/src/emu/cpu/drcbec.h
new file mode 100644
index 00000000000..ada16d7f055
--- /dev/null
+++ b/trunk/src/emu/cpu/drcbec.h
@@ -0,0 +1,88 @@
+/***************************************************************************
+
+ drcbec.h
+
+ Interpreted C core back-end for the universal machine language.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __DRCBEC_H__
+#define __DRCBEC_H__
+
+#include "drcuml.h"
+#include "drcbeut.h"
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+union drcbec_instruction;
+
+class drcbe_c : public drcbe_interface
+{
+public:
+ // construction/destruction
+ drcbe_c(drcuml_state &drcuml, device_t &device, drc_cache &cache, UINT32 flags, int modes, int addrbits, int ignorebits);
+ virtual ~drcbe_c();
+
+ // required overrides
+ virtual void reset();
+ virtual int execute(uml::code_handle &entry);
+ virtual void generate(drcuml_block &block, const uml::instruction *instlist, UINT32 numinst);
+ virtual bool hash_exists(UINT32 mode, UINT32 pc);
+ virtual void get_info(drcbe_info &info);
+
+private:
+ // helpers
+ void output_parameter(drcbec_instruction **dstptr, void **immedptr, int size, const uml::parameter &param);
+ void fixup_label(void *parameter, drccodeptr labelcodeptr);
+ int dmulu(UINT64 &dstlo, UINT64 &dsthi, UINT64 src1, UINT64 src2, int flags);
+ int dmuls(UINT64 &dstlo, UINT64 &dsthi, INT64 src1, INT64 src2, int flags);
+
+ // internal state
+ drc_hash_table m_hash; // hash table state
+ drc_map_variables m_map; // code map
+ drc_label_list m_labels; // label list
+ drc_label_fixup_delegate m_fixup_delegate; // precomputed delegate
+
+ static const UINT32 s_condition_map[32];
+ static UINT64 s_immediate_zero;
+};
+
+
+#endif /* __DRCBEC_H__ */
diff --git a/trunk/src/emu/cpu/drcbeut.c b/trunk/src/emu/cpu/drcbeut.c
new file mode 100644
index 00000000000..30f2861b78f
--- /dev/null
+++ b/trunk/src/emu/cpu/drcbeut.c
@@ -0,0 +1,606 @@
+/***************************************************************************
+
+ drcbeut.c
+
+ Utility functions for dynamic recompiling backends.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "drcbeut.h"
+
+using namespace uml;
+
+
+//**************************************************************************
+// DEBUGGING
+//**************************************************************************
+
+#define LOG_RECOVER (0)
+
+
+
+//**************************************************************************
+// DRC HASH TABLE
+//**************************************************************************
+
+//-------------------------------------------------
+// drc_hash_table - constructor
+//-------------------------------------------------
+
+drc_hash_table::drc_hash_table(drc_cache &cache, UINT32 modes, UINT8 addrbits, UINT8 ignorebits)
+ : m_cache(cache),
+ m_modes(modes),
+ m_nocodeptr(NULL),
+ m_l1bits((addrbits - ignorebits) / 2),
+ m_l2bits((addrbits - ignorebits) - m_l1bits),
+ m_l1shift(ignorebits + m_l2bits),
+ m_l2shift(ignorebits),
+ m_l1mask((1 << m_l1bits) - 1),
+ m_l2mask((1 << m_l2bits) - 1),
+ m_base(reinterpret_cast<drccodeptr ***>(cache.alloc(modes * sizeof(**m_base)))),
+ m_emptyl1(NULL),
+ m_emptyl2(NULL)
+{
+ reset();
+}
+
+
+//-------------------------------------------------
+// reset - flush existing hash tables and create
+// new ones
+//-------------------------------------------------
+
+bool drc_hash_table::reset()
+{
+ // allocate an empty l2 hash table
+ m_emptyl2 = (drccodeptr *)m_cache.alloc_temporary(sizeof(drccodeptr) << m_l2bits);
+ if (m_emptyl2 == NULL)
+ return false;
+
+ // populate it with pointers to the recompile_exit code
+ for (int entry = 0; entry < (1 << m_l2bits); entry++)
+ m_emptyl2[entry] = m_nocodeptr;
+
+ // allocate an empty l1 hash table
+ m_emptyl1 = (drccodeptr **)m_cache.alloc_temporary(sizeof(drccodeptr *) << m_l1bits);
+ if (m_emptyl1 == NULL)
+ return false;
+
+ // populate it with pointers to the empty l2 table
+ for (int entry = 0; entry < (1 << m_l1bits); entry++)
+ m_emptyl1[entry] = m_emptyl2;
+
+ // reset the hash tables
+ for (int modenum = 0; modenum < m_modes; modenum++)
+ m_base[modenum] = m_emptyl1;
+
+ return true;
+}
+
+
+//-------------------------------------------------
+// block_begin - note the beginning of a block
+//-------------------------------------------------
+
+void drc_hash_table::block_begin(drcuml_block &block, const uml::instruction *instlist, UINT32 numinst)
+{
+ // before generating code, pre-allocate any hash entries; we do this by setting dummy hash values
+ for (int inum = 0; inum < numinst; inum++)
+ {
+ const uml::instruction &inst = instlist[inum];
+
+ // if the opcode is a hash, verify that it makes sense and then set a NULL entry
+ if (inst.opcode() == OP_HASH)
+ {
+ assert(inst.numparams() == 2);
+
+ // if we fail to allocate, we must abort the block
+ if (!set_codeptr(inst.param(0).immediate(), inst.param(1).immediate(), NULL))
+ block.abort();
+ }
+
+ // if the opcode is a hashjmp to a fixed location, make sure we preallocate the tables
+ if (inst.opcode() == OP_HASHJMP && inst.param(0).is_immediate() && inst.param(1).is_immediate())
+ {
+ // if we fail to allocate, we must abort the block
+ drccodeptr code = get_codeptr(inst.param(0).immediate(), inst.param(1).immediate());
+ if (!set_codeptr(inst.param(0).immediate(), inst.param(1).immediate(), code))
+ block.abort();
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// block_end - note the end of a block
+//-------------------------------------------------
+
+void drc_hash_table::block_end(drcuml_block &block)
+{
+ // nothing to do here, yet
+}
+
+
+//-------------------------------------------------
+// set_default_codeptr - change the default
+// codeptr
+//-------------------------------------------------
+
+void drc_hash_table::set_default_codeptr(drccodeptr nocodeptr)
+{
+ // nothing to do if the same
+ drccodeptr old = m_nocodeptr;
+ if (old == nocodeptr)
+ return;
+ m_nocodeptr = nocodeptr;
+
+ // update the empty L2 table first
+ for (int l2entry = 0; l2entry < (1 << m_l2bits); l2entry++)
+ m_emptyl2[l2entry] = nocodeptr;
+
+ // now scan all existing hashtables for entries
+ for (int modenum = 0; modenum < m_modes; modenum++)
+ if (m_base[modenum] != m_emptyl1)
+ for (int l1entry = 0; l1entry < (1 << m_l1bits); l1entry++)
+ if (m_base[modenum][l1entry] != m_emptyl2)
+ for (int l2entry = 0; l2entry < (1 << m_l2bits); l2entry++)
+ if (m_base[modenum][l1entry][l2entry] == old)
+ m_base[modenum][l1entry][l2entry] = nocodeptr;
+}
+
+
+//-------------------------------------------------
+// set_codeptr - set the codeptr for the given
+// mode/pc
+//-------------------------------------------------
+
+bool drc_hash_table::set_codeptr(UINT32 mode, UINT32 pc, drccodeptr code)
+{
+ // copy-on-write for the l1 hash table
+ assert(mode < m_modes);
+ if (m_base[mode] == m_emptyl1)
+ {
+ drccodeptr **newtable = (drccodeptr **)m_cache.alloc_temporary(sizeof(drccodeptr *) << m_l1bits);
+ if (newtable == NULL)
+ return false;
+ memcpy(newtable, m_emptyl1, sizeof(drccodeptr *) << m_l1bits);
+ m_base[mode] = newtable;
+ }
+
+ // copy-on-write for the l2 hash table
+ UINT32 l1 = (pc >> m_l1shift) & m_l1mask;
+ if (m_base[mode][l1] == m_emptyl2)
+ {
+ drccodeptr *newtable = (drccodeptr *)m_cache.alloc_temporary(sizeof(drccodeptr) << m_l2bits);
+ if (newtable == NULL)
+ return false;
+ memcpy(newtable, m_emptyl2, sizeof(drccodeptr) << m_l2bits);
+ m_base[mode][l1] = newtable;
+ }
+
+ // set the new entry
+ UINT32 l2 = (pc >> m_l2shift) & m_l2mask;
+ m_base[mode][l1][l2] = code;
+ return true;
+}
+
+
+
+//**************************************************************************
+// DRC MAP VARIABLES
+//**************************************************************************
+
+//-------------------------------------------------
+// drc_map_variables - constructor
+//-------------------------------------------------
+
+drc_map_variables::drc_map_variables(drc_cache &cache, UINT64 uniquevalue)
+ : m_cache(cache),
+ m_uniquevalue(uniquevalue)
+{
+ memset(m_mapvalue, 0, sizeof(m_mapvalue));
+}
+
+
+//-------------------------------------------------
+// ~drc_map_variables - destructor
+//-------------------------------------------------
+
+drc_map_variables::~drc_map_variables()
+{
+ // must detach all items from the entry list so that the list object
+ // doesn't try to free them on exit
+ m_entry_list.detach_all();
+}
+
+
+//-------------------------------------------------
+// block_begin - note the beginning of a block
+//-------------------------------------------------
+
+void drc_map_variables::block_begin(drcuml_block &block)
+{
+ // release any remaining live entries
+ map_entry *entry;
+ while ((entry = m_entry_list.detach_head()) != NULL)
+ m_cache.dealloc(entry, sizeof(*entry));
+
+ // reset the variable values
+ memset(m_mapvalue, 0, sizeof(m_mapvalue));
+}
+
+
+//-------------------------------------------------
+// block_end - note the end of a block
+//-------------------------------------------------
+
+void drc_map_variables::block_end(drcuml_block &block)
+{
+ // only process if we have data
+ if (m_entry_list.first() == NULL)
+ return;
+
+ // begin "code generation" aligned to an 8-byte boundary
+ drccodeptr *top = m_cache.begin_codegen(sizeof(UINT64) + sizeof(UINT32) + 2 * sizeof(UINT32) * m_entry_list.count());
+ if (top == NULL)
+ block.abort();
+ UINT32 *dest = (UINT32 *)(((FPTR)*top + 7) & ~7);
+
+ // store the cookie first
+ *(UINT64 *)dest = m_uniquevalue;
+ dest += 2;
+
+ // get the pointer to the first item and store an initial backwards offset
+ drccodeptr lastptr = m_entry_list.first()->m_codeptr;
+ *dest = (drccodeptr)dest - lastptr;
+ dest++;
+
+ // now iterate over entries and store them
+ UINT32 curvalue[MAPVAR_COUNT] = { 0 };
+ bool changed[MAPVAR_COUNT] = { false };
+ for (map_entry *entry = m_entry_list.first(); entry != NULL; entry = entry->next())
+ {
+ // update the current value of the variable and detect changes
+ if (curvalue[entry->m_mapvar] != entry->m_newval)
+ {
+ curvalue[entry->m_mapvar] = entry->m_newval;
+ changed[entry->m_mapvar] = true;
+ }
+
+ // if the next code pointer is different, or if we're at the end, flush changes
+ if (entry->next() == NULL || entry->next()->m_codeptr != entry->m_codeptr)
+ {
+ // build a mask of changed variables
+ int numchanged = 0;
+ UINT32 varmask = 0;
+ for (int varnum = 0; varnum < ARRAY_LENGTH(changed); varnum++)
+ if (changed[varnum])
+ {
+ changed[varnum] = false;
+ varmask |= 1 << varnum;
+ numchanged++;
+ }
+
+ // if nothing really changed, skip it
+ if (numchanged == 0)
+ continue;
+
+ // first word is a code delta plus mask of changed variables
+ UINT32 codedelta = entry->m_codeptr - lastptr;
+ while (codedelta > 0xffff)
+ {
+ *dest++ = 0xffff << 16;
+ codedelta -= 0xffff;
+ }
+ *dest++ = (codedelta << 16) | (varmask << 4) | numchanged;
+
+ // now output updated variable values
+ for (int varnum = 0; varnum < ARRAY_LENGTH(changed); varnum++)
+ if ((varmask >> varnum) & 1)
+ *dest++ = curvalue[varnum];
+
+ // remember our lastptr
+ lastptr = entry->m_codeptr;
+ }
+ }
+
+ // add a terminator
+ *dest++ = 0;
+
+ // complete codegen
+ *top = (drccodeptr)dest;
+ m_cache.end_codegen();
+}
+
+
+//-------------------------------------------------
+// set_value - set a map value for the given
+// code pointer
+//-------------------------------------------------
+
+void drc_map_variables::set_value(drccodeptr codebase, UINT32 mapvar, UINT32 newvalue)
+{
+ assert(mapvar >= MAPVAR_M0 && mapvar < MAPVAR_END);
+
+ // if this value isn't different, skip it
+ if (m_mapvalue[mapvar - MAPVAR_M0] == newvalue)
+ return;
+
+ // allocate a new entry and fill it in
+ map_entry *entry = (map_entry *)m_cache.alloc(sizeof(*entry));
+ entry->m_next = NULL;
+ entry->m_codeptr = codebase;
+ entry->m_mapvar = mapvar - MAPVAR_M0;
+ entry->m_newval = newvalue;
+
+ // hook us into the end of the list
+ m_entry_list.append(*entry);
+
+ // update our state in the table as well
+ m_mapvalue[mapvar - MAPVAR_M0] = newvalue;
+}
+
+
+//-------------------------------------------------
+// get_value - return a map value for the given
+// code pointer
+//-------------------------------------------------
+
+UINT32 drc_map_variables::get_value(drccodeptr codebase, UINT32 mapvar) const
+{
+ assert(mapvar >= MAPVAR_M0 && mapvar < MAPVAR_END);
+ mapvar -= MAPVAR_M0;
+
+ // get an aligned pointer to start scanning
+ UINT64 *curscan = (UINT64 *)(((FPTR)codebase | 7) + 1);
+ UINT64 *endscan = (UINT64 *)m_cache.top();
+
+ // look for the signature
+ while (curscan < endscan && *curscan++ != m_uniquevalue) ;
+ if (curscan >= endscan)
+ return 0;
+
+ // switch to 32-bit pointers for processing the rest
+ UINT32 *data = (UINT32 *)curscan;
+
+ // first get the 32-bit starting offset to the code
+ drccodeptr curcode = (drccodeptr)data - *data;
+ data++;
+
+ // now loop until we advance past our target
+ UINT32 varmask = 0x10 << mapvar;
+ UINT32 result = 0;
+ while (true)
+ {
+ // a 0 is a terminator
+ UINT32 controlword = *data++;
+ if (controlword == 0)
+ break;
+
+ // update the codeptr; if this puts us past the end, we're done
+ curcode += (controlword >> 16) & 0xffff;
+ if (curcode > codebase)
+ break;
+
+ // if our mapvar has changed, process this word
+ if ((controlword & varmask) != 0)
+ {
+ // count how many words precede the one we care about
+ int dataoffs = 0;
+ for (UINT32 skipmask = (controlword & (varmask - 1)) >> 4; skipmask != 0; skipmask = skipmask & (skipmask - 1))
+ dataoffs++;
+
+ // fetch the one we want
+ result = data[dataoffs];
+ }
+
+ // low 4 bits contain the total number of words of data
+ data += controlword & 0x0f;
+ }
+ if (LOG_RECOVER)
+ printf("recover %d @ %p = %08X\n", mapvar, codebase, result);
+ return result;
+}
+
+UINT32 drc_map_variables::static_get_value(drc_map_variables &map, drccodeptr codebase, UINT32 mapvar)
+{
+ return map.get_value(codebase, mapvar);
+}
+
+
+
+//-------------------------------------------------
+// get_last_value - return the most recently set
+// map value
+//-------------------------------------------------
+
+UINT32 drc_map_variables::get_last_value(UINT32 mapvar)
+{
+ assert(mapvar >= MAPVAR_M0 && mapvar < MAPVAR_END);
+ return m_mapvalue[mapvar - MAPVAR_M0];
+}
+
+
+
+//**************************************************************************
+// DRC LABEL LIST
+//**************************************************************************
+
+//-------------------------------------------------
+// drc_label_list - constructor
+//-------------------------------------------------
+
+drc_label_list::drc_label_list(drc_cache &cache)
+ : m_cache(cache),
+ m_oob_callback_delegate(FUNC(drc_label_list::oob_callback), this)
+{
+}
+
+
+//-------------------------------------------------
+// ~drc_label_list - destructor
+//-------------------------------------------------
+
+drc_label_list::~drc_label_list()
+{
+ // must detach all items from the entry list so that the list object
+ // doesn't try to free them on exit
+ m_list.detach_all();
+}
+
+
+//-------------------------------------------------
+// block_begin - note the beginning of a block
+//-------------------------------------------------
+
+void drc_label_list::block_begin(drcuml_block &block)
+{
+ // make sure the label list is clear, but don't fatalerror
+ reset(false);
+}
+
+
+//-------------------------------------------------
+// block_end - note the end of a block
+//-------------------------------------------------
+
+void drc_label_list::block_end(drcuml_block &block)
+{
+ // can't free until the cache is clean of our OOB requests
+ assert(!m_cache.generating_code());
+
+ // free all of the pending fixup requests
+ label_fixup *fixup;
+ while ((fixup = m_fixup_list.detach_head()) != NULL)
+ m_cache.dealloc(fixup, sizeof(*fixup));
+
+ // make sure the label list is clear, and fatalerror if we missed anything
+ reset(true);
+}
+
+
+//-------------------------------------------------
+// get_codeptr - find or allocate a new label;
+// returns NULL and requests an OOB callback if
+// undefined
+//-------------------------------------------------
+
+drccodeptr drc_label_list::get_codeptr(uml::code_label label, drc_label_fixup_delegate callback, void *param)
+{
+ label_entry *curlabel = find_or_allocate(label);
+
+ // if no code pointer, request an OOB callback
+ if (curlabel->m_codeptr == NULL && !callback.isnull())
+ {
+ label_fixup *fixup = reinterpret_cast<label_fixup *>(m_cache.alloc(sizeof(*fixup)));
+ fixup->m_callback = callback;
+ fixup->m_label = curlabel;
+ m_fixup_list.append(*fixup);
+ m_cache.request_oob_codegen(m_oob_callback_delegate, fixup, param);
+ }
+
+ return curlabel->m_codeptr;
+}
+
+
+//-------------------------------------------------
+// set_codeptr - set the pointer to a new label
+//-------------------------------------------------
+
+void drc_label_list::set_codeptr(uml::code_label label, drccodeptr codeptr)
+{
+ // set the code pointer
+ label_entry *curlabel = find_or_allocate(label);
+ assert(curlabel->m_codeptr == NULL);
+ curlabel->m_codeptr = codeptr;
+}
+
+
+//-------------------------------------------------
+// reset - reset a label list (add all entries to
+// the free list)
+//-------------------------------------------------
+
+void drc_label_list::reset(bool fatal_on_leftovers)
+{
+ // loop until out of labels
+ label_entry *curlabel;
+ while ((curlabel = m_list.detach_head()) != NULL)
+ {
+ // fatal if we were a leftover
+ if (fatal_on_leftovers && curlabel->m_codeptr == NULL)
+ fatalerror("Label %08X never defined!", curlabel->m_label.label());
+
+ // free the label
+ m_cache.dealloc(curlabel, sizeof(*curlabel));
+ }
+}
+
+
+//-------------------------------------------------
+// find_or_allocate - look up a label and
+// allocate a new one if not found
+//-------------------------------------------------
+
+drc_label_list::label_entry *drc_label_list::find_or_allocate(uml::code_label label)
+{
+ // find the label, or else allocate a new one
+ label_entry *curlabel;
+ for (curlabel = m_list.first(); curlabel != NULL; curlabel = curlabel->next())
+ if (curlabel->m_label == label)
+ break;
+
+ // if none found, allocate
+ if (curlabel == NULL)
+ {
+ curlabel = (label_entry *)m_cache.alloc(sizeof(*curlabel));
+ curlabel->m_label = label;
+ curlabel->m_codeptr = NULL;
+ m_list.append(*curlabel);
+ }
+ return curlabel;
+}
+
+
+//-------------------------------------------------
+// oob_callback - out-of-band codegen callback
+// for labels
+//-------------------------------------------------
+
+void drc_label_list::oob_callback(drccodeptr *codeptr, void *param1, void *param2)
+{
+ label_fixup *fixup = reinterpret_cast<label_fixup *>(param1);
+ fixup->m_callback(param2, fixup->m_label->m_codeptr);
+}
diff --git a/trunk/src/emu/cpu/drcbeut.h b/trunk/src/emu/cpu/drcbeut.h
new file mode 100644
index 00000000000..83710ff82b3
--- /dev/null
+++ b/trunk/src/emu/cpu/drcbeut.h
@@ -0,0 +1,195 @@
+/***************************************************************************
+
+ drcbeut.h
+
+ Utility functions for dynamic recompiling backends.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __DRCBEUT_H__
+#define __DRCBEUT_H__
+
+#include "drcuml.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> drc_hash_table
+
+// common hash table management
+class drc_hash_table
+{
+public:
+ // construction/destruction
+ drc_hash_table(drc_cache &cache, UINT32 modes, UINT8 addrbits, UINT8 ignorebits);
+
+ // getters
+ drccodeptr ***base() const { return m_base; }
+ UINT8 l1bits() const { return m_l1bits; }
+ UINT8 l2bits() const { return m_l2bits; }
+ UINT8 l1shift() const { return m_l1shift; }
+ UINT8 l2shift() const { return m_l2shift; }
+ offs_t l1mask() const { return m_l1mask; }
+ offs_t l2mask() const { return m_l2mask; }
+ bool is_mode_populated(UINT32 mode) const { return m_base[mode] != m_emptyl1; }
+
+ // set up and configuration
+ bool reset();
+ void set_default_codeptr(drccodeptr code);
+
+ // block begin/end
+ void block_begin(drcuml_block &block, const uml::instruction *instlist, UINT32 numinst);
+ void block_end(drcuml_block &block);
+
+ // code pointer access
+ bool set_codeptr(UINT32 mode, UINT32 pc, drccodeptr code);
+ drccodeptr get_codeptr(UINT32 mode, UINT32 pc) { assert(mode < m_modes); return m_base[mode][(pc >> m_l1shift) & m_l1mask][(pc >> m_l2shift) & m_l2mask]; }
+ bool code_exists(UINT32 mode, UINT32 pc) { return get_codeptr(mode, pc) != m_nocodeptr; }
+
+private:
+ // internal state
+ drc_cache & m_cache; // cache where allocations come from
+ UINT32 m_modes; // number of modes supported
+
+ drccodeptr m_nocodeptr; // pointer to code which will handle missing entries
+
+ UINT8 m_l1bits; // bits worth of entries in l1 hash tables
+ UINT8 m_l2bits; // bits worth of entries in l2 hash tables
+ UINT8 m_l1shift; // shift to apply to the PC to get the l1 hash entry
+ UINT8 m_l2shift; // shift to apply to the PC to get the l2 hash entry
+ offs_t m_l1mask; // mask to apply after shifting
+ offs_t m_l2mask; // mask to apply after shifting
+
+ drccodeptr *** m_base; // pointer to the l1 table for each mode
+ drccodeptr ** m_emptyl1; // pointer to empty l1 hash table
+ drccodeptr * m_emptyl2; // pointer to empty l2 hash table
+};
+
+
+// ======================> drc_map_variables
+
+// common map variable management
+class drc_map_variables
+{
+public:
+ // construction/destruction
+ drc_map_variables(drc_cache &cache, UINT64 uniquevalue);
+ ~drc_map_variables();
+
+ // block begin/end
+ void block_begin(drcuml_block &block);
+ void block_end(drcuml_block &block);
+
+ // get/set values
+ void set_value(drccodeptr codebase, UINT32 mapvar, UINT32 newvalue);
+ UINT32 get_value(drccodeptr codebase, UINT32 mapvar) const;
+ UINT32 get_last_value(UINT32 mapvar);
+
+ // static accessors to be called directly by generated code
+ static UINT32 static_get_value(drc_map_variables &map, drccodeptr codebase, UINT32 mapvar);
+
+private:
+ // internal state
+ drc_cache & m_cache; // pointer to the cache
+ UINT64 m_uniquevalue; // unique value used to find the table
+ UINT32 m_mapvalue[uml::MAPVAR_END - uml::MAPVAR_M0]; // array of current values
+
+ // list of entries
+ struct map_entry
+ {
+ map_entry *next() const { return m_next; }
+ map_entry * m_next; // pointer to next map entry
+ drccodeptr m_codeptr; // pointer to the relevant code
+ UINT32 m_mapvar; // map variable id
+ UINT32 m_newval; // value of the variable starting at codeptr
+ };
+ simple_list<map_entry> m_entry_list; // list of entries
+};
+
+
+// ======================> drc_label_list
+
+typedef delegate<void (void *, drccodeptr)> drc_label_fixup_delegate;
+
+// structure holding a live list of labels
+class drc_label_list
+{
+public:
+ // construction/destruction
+ drc_label_list(drc_cache &cache);
+ ~drc_label_list();
+
+ // block begin/end
+ void block_begin(drcuml_block &block);
+ void block_end(drcuml_block &block);
+
+ // get/set values
+ drccodeptr get_codeptr(uml::code_label label, drc_label_fixup_delegate fixup, void *param);
+ void set_codeptr(uml::code_label label, drccodeptr codeptr);
+
+private:
+ struct label_entry
+ {
+ label_entry *next() const { return m_next; }
+ label_entry * m_next; // pointer to next label
+ uml::code_label m_label; // the label specified
+ drccodeptr m_codeptr; // pointer to the relevant code
+ };
+
+ struct label_fixup
+ {
+ label_fixup *next() const { return m_next; }
+ label_fixup * m_next; // pointer to the next oob
+ label_entry * m_label; // the label in question
+ drc_label_fixup_delegate m_callback; // callback
+ };
+
+ // internal helpers
+ void reset(bool fatal_on_leftovers);
+ label_entry *find_or_allocate(uml::code_label label);
+ void oob_callback(drccodeptr *codeptr, void *param1, void *param2);
+
+ // internal state
+ drc_cache & m_cache; // pointer to the cache
+ simple_list<label_entry> m_list; // head of the live list
+ simple_list<label_fixup> m_fixup_list; // list of pending oob fixups
+ drc_oob_delegate m_oob_callback_delegate; // pre-computed delegate
+};
+
+
+#endif /* __DRCBEUT_H__ */
diff --git a/trunk/src/emu/cpu/drcbex64.c b/trunk/src/emu/cpu/drcbex64.c
new file mode 100644
index 00000000000..8de426aef91
--- /dev/null
+++ b/trunk/src/emu/cpu/drcbex64.c
@@ -0,0 +1,6735 @@
+/***************************************************************************
+
+ drcbex64.c
+
+ 64-bit x64 back-end for the universal machine language.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+****************************************************************************
+
+ Future improvements/changes:
+
+ * Add support for FP registers
+
+ * Optimize to avoid unnecessary reloads
+
+ * Identify common pairs and optimize output
+
+ * Convert SUB a,0,b to NEG
+
+ * Optimize, e.g., and [r5],i0,$FF to use rbx as temporary register
+ (avoid initial move) if i0 is not needed going forward
+
+****************************************************************************
+
+ -------------------------
+ ABI/conventions (Windows)
+ -------------------------
+
+ Registers:
+ RAX - volatile, function return value
+ RBX - non-volatile
+ RCX - volatile, integer function parameter 1
+ RDX - volatile, integer function parameter 2
+ RSI - non-volatile
+ RDI - non-volatile
+ RBP - non-volatile
+ R8 - volatile, integer function parameter 3
+ R9 - volatile, integer function parameter 4
+ R10 - volatile
+ R11 - volatile, scratch immediate storage
+ R12 - non-volatile
+ R13 - non-volatile
+ R14 - non-volatile
+ R15 - non-volatile
+
+ XMM0 - volatile, FP function parameter 1
+ XMM1 - volatile, FP function parameter 2
+ XMM2 - volatile, FP function parameter 3
+ XMM3 - volatile, FP function parameter 4
+ XMM4 - volatile
+ XMM5 - volatile
+ XMM6 - non-volatile
+ XMM7 - non-volatile
+ XMM8 - non-volatile
+ XMM9 - non-volatile
+ XMM10 - non-volatile
+ XMM11 - non-volatile
+ XMM12 - non-volatile
+ XMM13 - non-volatile
+ XMM14 - non-volatile
+ XMM15 - non-volatile
+
+
+ -----------------------------
+ ABI/conventions (Linux/MacOS)
+ -----------------------------
+
+ Registers:
+ RAX - volatile, function return value
+ RBX - non-volatile
+ RCX - volatile, integer function parameter 4
+ RDX - volatile, integer function parameter 3
+ RSI - volatile, integer function parameter 2
+ RDI - volatile, integer function parameter 1
+ RBP - non-volatile
+ R8 - volatile, integer function parameter 5
+ R9 - volatile, integer function parameter 6
+ R10 - volatile
+ R11 - volatile, scratch immediate storage
+ R12 - non-volatile
+ R13 - non-volatile
+ R14 - non-volatile
+ R15 - non-volatile
+
+ XMM0 - volatile, FP function parameter 1
+ XMM1 - volatile, FP function parameter 2
+ XMM2 - volatile, FP function parameter 3
+ XMM3 - volatile, FP function parameter 4
+ XMM4 - volatile
+ XMM5 - volatile
+ XMM6 - volatile
+ XMM7 - volatile
+ XMM8 - volatile
+ XMM9 - volatile
+ XMM10 - volatile
+ XMM11 - volatile
+ XMM12 - volatile
+ XMM13 - volatile
+ XMM14 - volatile
+ XMM15 - volatile
+
+
+ ---------------
+ Execution model
+ ---------------
+
+ Registers (Windows):
+ RAX - scratch register
+ RBX - maps to I0
+ RCX - scratch register
+ RDX - scratch register
+ RSI - maps to I1
+ RDI - maps to I2
+ RBP - pointer to code cache
+ R8 - scratch register
+ R9 - scratch register
+ R10 - scratch register
+ R11 - scratch register
+ R12 - maps to I3
+ R13 - maps to I4
+ R14 - maps to I5
+ R15 - maps to I6
+
+ Registers (Linux/MacOS):
+ RAX - scratch register
+ RBX - maps to I0
+ RCX - scratch register
+ RDX - scratch register
+ RSI - unused
+ RDI - unused
+ RBP - pointer to code cache
+ R8 - scratch register
+ R9 - scratch register
+ R10 - scratch register
+ R11 - scratch register
+ R12 - maps to I1
+ R13 - maps to I2
+ R14 - maps to I3
+ R15 - maps to I4
+
+ Entry point:
+ Assumes 1 parameter passed, which is the codeptr of the code
+ to execute once the environment is set up.
+
+ Exit point:
+ Assumes exit value is in RAX.
+
+ Entry stack:
+ [rsp] - return
+
+ Runtime stack:
+ [rsp] - r9 home
+ [rsp+8] - r8 home
+ [rsp+16] - rdx home
+ [rsp+24] - rcx home
+ [rsp+40] - saved r15
+ [rsp+48] - saved r14
+ [rsp+56] - saved r13
+ [rsp+64] - saved r12
+ [rsp+72] - saved ebp
+ [rsp+80] - saved edi
+ [rsp+88] - saved esi
+ [rsp+96] - saved ebx
+ [rsp+104] - ret
+
+***************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "drcuml.h"
+#include "drcbex64.h"
+
+using namespace uml;
+using namespace x64emit;
+
+
+
+//**************************************************************************
+// DEBUGGING
+//**************************************************************************
+
+#define LOG_HASHJMPS (0)
+
+#define USE_RCPSS_FOR_SINGLES (0)
+#define USE_RSQRTSS_FOR_SINGLES (0)
+#define USE_RCPSS_FOR_DOUBLES (0)
+#define USE_RSQRTSS_FOR_DOUBLES (0)
+
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+const UINT32 PTYPE_M = 1 << parameter::PTYPE_MEMORY;
+const UINT32 PTYPE_I = 1 << parameter::PTYPE_IMMEDIATE;
+const UINT32 PTYPE_R = 1 << parameter::PTYPE_INT_REGISTER;
+const UINT32 PTYPE_F = 1 << parameter::PTYPE_FLOAT_REGISTER;
+const UINT32 PTYPE_MI = PTYPE_M | PTYPE_I;
+const UINT32 PTYPE_RI = PTYPE_R | PTYPE_I;
+const UINT32 PTYPE_MR = PTYPE_M | PTYPE_R;
+const UINT32 PTYPE_MRI = PTYPE_M | PTYPE_R | PTYPE_I;
+const UINT32 PTYPE_MF = PTYPE_M | PTYPE_F;
+
+#ifdef X64_WINDOWS_ABI
+
+const int REG_PARAM1 = REG_RCX;
+const int REG_PARAM2 = REG_RDX;
+const int REG_PARAM3 = REG_R8;
+const int REG_PARAM4 = REG_R9;
+
+#else
+
+const int REG_PARAM1 = REG_RDI;
+const int REG_PARAM2 = REG_RSI;
+const int REG_PARAM3 = REG_RDX;
+const int REG_PARAM4 = REG_RCX;
+
+#endif
+
+
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+#define X86_CONDITION(condition) (condition_map[condition - uml::COND_Z])
+#define X86_NOT_CONDITION(condition) (condition_map[condition - uml::COND_Z] ^ 1)
+
+inline x86_memref drcbe_x64::MABS(const void *ptr)
+{
+ return MBD(REG_BP, offset_from_rbp(ptr));
+}
+
+#define assert_no_condition(inst) assert((inst).condition() == uml::COND_ALWAYS)
+#define assert_any_condition(inst) assert((inst).condition() == uml::COND_ALWAYS || ((inst).condition() >= uml::COND_Z && (inst).condition() < uml::COND_MAX))
+#define assert_no_flags(inst) assert((inst).flags() == 0)
+#define assert_flags(inst, valid) assert(((inst).flags() & ~(valid)) == 0)
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+drcbe_x64::opcode_generate_func drcbe_x64::s_opcode_table[OP_MAX];
+
+// size-to-mask table
+static const UINT64 size_to_mask[] = { 0, 0xff, 0xffff, 0, 0xffffffff, 0, 0, 0, U64(0xffffffffffffffff) };
+
+// register mapping tables
+static const UINT8 int_register_map[REG_I_COUNT] =
+{
+#ifdef X64_WINDOWS_ABI
+ REG_RBX, REG_RSI, REG_RDI, REG_R12, REG_R13, REG_R14, REG_R15
+#else
+ REG_RBX, REG_R12, REG_R13, REG_R14, REG_R15
+#endif
+};
+
+static UINT8 float_register_map[REG_F_COUNT] =
+{
+ 0
+};
+
+// condition mapping table
+static const UINT8 condition_map[uml::COND_MAX - uml::COND_Z] =
+{
+ x64emit::COND_Z, // COND_Z = 0x80, requires Z
+ x64emit::COND_NZ, // COND_NZ, requires Z
+ x64emit::COND_S, // COND_S, requires S
+ x64emit::COND_NS, // COND_NS, requires S
+ x64emit::COND_C, // COND_C, requires C
+ x64emit::COND_NC, // COND_NC, requires C
+ x64emit::COND_O, // COND_V, requires V
+ x64emit::COND_NO, // COND_NV, requires V
+ x64emit::COND_P, // COND_U, requires U
+ x64emit::COND_NP, // COND_NU, requires U
+ x64emit::COND_A, // COND_A, requires CZ
+ x64emit::COND_BE, // COND_BE, requires CZ
+ x64emit::COND_G, // COND_G, requires SVZ
+ x64emit::COND_LE, // COND_LE, requires SVZ
+ x64emit::COND_L, // COND_L, requires SV
+ x64emit::COND_GE, // COND_GE, requires SV
+};
+
+// rounding mode mapping table
+static const UINT8 fprnd_map[4] =
+{
+ FPRND_CHOP, // ROUND_TRUNC, truncate
+ FPRND_NEAR, // ROUND_ROUND, round
+ FPRND_UP, // ROUND_CEIL, round up
+ FPRND_DOWN // ROUND_FLOOR round down
+};
+
+
+
+//**************************************************************************
+// TABLES
+//**************************************************************************
+
+const drcbe_x64::opcode_table_entry drcbe_x64::s_opcode_table_source[] =
+{
+ // Compile-time opcodes
+ { uml::OP_HANDLE, &drcbe_x64::op_handle }, // HANDLE handle
+ { uml::OP_HASH, &drcbe_x64::op_hash }, // HASH mode,pc
+ { uml::OP_LABEL, &drcbe_x64::op_label }, // LABEL imm
+ { uml::OP_COMMENT, &drcbe_x64::op_comment }, // COMMENT string
+ { uml::OP_MAPVAR, &drcbe_x64::op_mapvar }, // MAPVAR mapvar,value
+
+ // Control Flow Operations
+ { uml::OP_NOP, &drcbe_x64::op_nop }, // NOP
+ { uml::OP_DEBUG, &drcbe_x64::op_debug }, // DEBUG pc
+ { uml::OP_EXIT, &drcbe_x64::op_exit }, // EXIT src1[,c]
+ { uml::OP_HASHJMP, &drcbe_x64::op_hashjmp }, // HASHJMP mode,pc,handle
+ { uml::OP_JMP, &drcbe_x64::op_jmp }, // JMP imm[,c]
+ { uml::OP_EXH, &drcbe_x64::op_exh }, // EXH handle,param[,c]
+ { uml::OP_CALLH, &drcbe_x64::op_callh }, // CALLH handle[,c]
+ { uml::OP_RET, &drcbe_x64::op_ret }, // RET [c]
+ { uml::OP_CALLC, &drcbe_x64::op_callc }, // CALLC func,ptr[,c]
+ { uml::OP_RECOVER, &drcbe_x64::op_recover }, // RECOVER dst,mapvar
+
+ // Internal Register Operations
+ { uml::OP_SETFMOD, &drcbe_x64::op_setfmod }, // SETFMOD src
+ { uml::OP_GETFMOD, &drcbe_x64::op_getfmod }, // GETFMOD dst
+ { uml::OP_GETEXP, &drcbe_x64::op_getexp }, // GETEXP dst
+ { uml::OP_GETFLGS, &drcbe_x64::op_getflgs }, // GETFLGS dst[,f]
+ { uml::OP_SAVE, &drcbe_x64::op_save }, // SAVE dst
+ { uml::OP_RESTORE, &drcbe_x64::op_restore }, // RESTORE dst
+
+ // Integer Operations
+ { uml::OP_LOAD, &drcbe_x64::op_load }, // LOAD dst,base,index,size
+ { uml::OP_LOADS, &drcbe_x64::op_loads }, // LOADS dst,base,index,size
+ { uml::OP_STORE, &drcbe_x64::op_store }, // STORE base,index,src,size
+ { uml::OP_READ, &drcbe_x64::op_read }, // READ dst,src1,spacesize
+ { uml::OP_READM, &drcbe_x64::op_readm }, // READM dst,src1,mask,spacesize
+ { uml::OP_WRITE, &drcbe_x64::op_write }, // WRITE dst,src1,spacesize
+ { uml::OP_WRITEM, &drcbe_x64::op_writem }, // WRITEM dst,src1,spacesize
+ { uml::OP_CARRY, &drcbe_x64::op_carry }, // CARRY src,bitnum
+ { uml::OP_SET, &drcbe_x64::op_set }, // SET dst,c
+ { uml::OP_MOV, &drcbe_x64::op_mov }, // MOV dst,src[,c]
+ { uml::OP_SEXT, &drcbe_x64::op_sext }, // SEXT dst,src
+ { uml::OP_ROLAND, &drcbe_x64::op_roland }, // ROLAND dst,src1,src2,src3
+ { uml::OP_ROLINS, &drcbe_x64::op_rolins }, // ROLINS dst,src1,src2,src3
+ { uml::OP_ADD, &drcbe_x64::op_add }, // ADD dst,src1,src2[,f]
+ { uml::OP_ADDC, &drcbe_x64::op_addc }, // ADDC dst,src1,src2[,f]
+ { uml::OP_SUB, &drcbe_x64::op_sub }, // SUB dst,src1,src2[,f]
+ { uml::OP_SUBB, &drcbe_x64::op_subc }, // SUBB dst,src1,src2[,f]
+ { uml::OP_CMP, &drcbe_x64::op_cmp }, // CMP src1,src2[,f]
+ { uml::OP_MULU, &drcbe_x64::op_mulu }, // MULU dst,edst,src1,src2[,f]
+ { uml::OP_MULS, &drcbe_x64::op_muls }, // MULS dst,edst,src1,src2[,f]
+ { uml::OP_DIVU, &drcbe_x64::op_divu }, // DIVU dst,edst,src1,src2[,f]
+ { uml::OP_DIVS, &drcbe_x64::op_divs }, // DIVS dst,edst,src1,src2[,f]
+ { uml::OP_AND, &drcbe_x64::op_and }, // AND dst,src1,src2[,f]
+ { uml::OP_TEST, &drcbe_x64::op_test }, // TEST src1,src2[,f]
+ { uml::OP_OR, &drcbe_x64::op_or }, // OR dst,src1,src2[,f]
+ { uml::OP_XOR, &drcbe_x64::op_xor }, // XOR dst,src1,src2[,f]
+ { uml::OP_LZCNT, &drcbe_x64::op_lzcnt }, // LZCNT dst,src[,f]
+ { uml::OP_BSWAP, &drcbe_x64::op_bswap }, // BSWAP dst,src
+ { uml::OP_SHL, &drcbe_x64::op_shl }, // SHL dst,src,count[,f]
+ { uml::OP_SHR, &drcbe_x64::op_shr }, // SHR dst,src,count[,f]
+ { uml::OP_SAR, &drcbe_x64::op_sar }, // SAR dst,src,count[,f]
+ { uml::OP_ROL, &drcbe_x64::op_rol }, // ROL dst,src,count[,f]
+ { uml::OP_ROLC, &drcbe_x64::op_rolc }, // ROLC dst,src,count[,f]
+ { uml::OP_ROR, &drcbe_x64::op_ror }, // ROR dst,src,count[,f]
+ { uml::OP_RORC, &drcbe_x64::op_rorc }, // RORC dst,src,count[,f]
+
+ // Floating Point Operations
+ { uml::OP_FLOAD, &drcbe_x64::op_fload }, // FLOAD dst,base,index
+ { uml::OP_FSTORE, &drcbe_x64::op_fstore }, // FSTORE base,index,src
+ { uml::OP_FREAD, &drcbe_x64::op_fread }, // FREAD dst,space,src1
+ { uml::OP_FWRITE, &drcbe_x64::op_fwrite }, // FWRITE space,dst,src1
+ { uml::OP_FMOV, &drcbe_x64::op_fmov }, // FMOV dst,src1[,c]
+ { uml::OP_FTOINT, &drcbe_x64::op_ftoint }, // FTOINT dst,src1,size,round
+ { uml::OP_FFRINT, &drcbe_x64::op_ffrint }, // FFRINT dst,src1,size
+ { uml::OP_FFRFLT, &drcbe_x64::op_ffrflt }, // FFRFLT dst,src1,size
+ { uml::OP_FRNDS, &drcbe_x64::op_frnds }, // FRNDS dst,src1
+ { uml::OP_FADD, &drcbe_x64::op_fadd }, // FADD dst,src1,src2
+ { uml::OP_FSUB, &drcbe_x64::op_fsub }, // FSUB dst,src1,src2
+ { uml::OP_FCMP, &drcbe_x64::op_fcmp }, // FCMP src1,src2
+ { uml::OP_FMUL, &drcbe_x64::op_fmul }, // FMUL dst,src1,src2
+ { uml::OP_FDIV, &drcbe_x64::op_fdiv }, // FDIV dst,src1,src2
+ { uml::OP_FNEG, &drcbe_x64::op_fneg }, // FNEG dst,src1
+ { uml::OP_FABS, &drcbe_x64::op_fabs }, // FABS dst,src1
+ { uml::OP_FSQRT, &drcbe_x64::op_fsqrt }, // FSQRT dst,src1
+ { uml::OP_FRECIP, &drcbe_x64::op_frecip }, // FRECIP dst,src1
+ { uml::OP_FRSQRT, &drcbe_x64::op_frsqrt } // FRSQRT dst,src1
+};
+
+
+
+//**************************************************************************
+// INLINE FUNCTIONS
+//**************************************************************************
+
+//-------------------------------------------------
+// param_normalize - convert a full parameter
+// into a reduced set
+//-------------------------------------------------
+
+drcbe_x64::be_parameter::be_parameter(drcbe_x64 &drcbe, const parameter &param, UINT32 allowed)
+{
+ int regnum;
+
+ switch (param.type())
+ {
+ // immediates pass through
+ case parameter::PTYPE_IMMEDIATE:
+ assert(allowed & PTYPE_I);
+ *this = param.immediate();
+ break;
+
+ // memory passes through
+ case parameter::PTYPE_MEMORY:
+ assert(allowed & PTYPE_M);
+ *this = make_memory(param.memory());
+ break;
+
+ // if a register maps to a register, keep it as a register; otherwise map it to memory
+ case parameter::PTYPE_INT_REGISTER:
+ assert(allowed & PTYPE_R);
+ assert(allowed & PTYPE_M);
+ regnum = int_register_map[param.ireg() - REG_I0];
+ if (regnum != 0)
+ *this = make_ireg(regnum);
+ else
+ *this = make_memory(&drcbe.m_state.r[param.ireg() - REG_I0]);
+ break;
+
+ // if a register maps to a register, keep it as a register; otherwise map it to memory
+ case parameter::PTYPE_FLOAT_REGISTER:
+ assert(allowed & PTYPE_F);
+ assert(allowed & PTYPE_M);
+ regnum = float_register_map[param.freg() - REG_F0];
+ if (regnum != 0)
+ *this = make_freg(regnum);
+ else
+ *this = make_memory(&drcbe.m_state.f[param.freg() - REG_F0]);
+ break;
+
+ // everything else is unexpected
+ default:
+ fatalerror("Unexpected parameter type");
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// select_register - select a register to use,
+// avoiding conflicts with the optional
+// checkparam
+//-------------------------------------------------
+
+inline int drcbe_x64::be_parameter::select_register(int defreg) const
+{
+ if (m_type == PTYPE_INT_REGISTER || m_type == PTYPE_FLOAT_REGISTER || m_type == PTYPE_VECTOR_REGISTER)
+ return m_value;
+ return defreg;
+}
+
+inline int drcbe_x64::be_parameter::select_register(int defreg, const be_parameter &checkparam) const
+{
+ if (*this == checkparam)
+ return defreg;
+ return select_register(defreg);
+}
+
+inline int drcbe_x64::be_parameter::select_register(int defreg, const be_parameter &checkparam, const be_parameter &checkparam2) const
+{
+ if (*this == checkparam || *this == checkparam2)
+ return defreg;
+ return select_register(defreg);
+}
+
+
+//-------------------------------------------------
+// select_register - select a register to use,
+// avoiding conflicts with the optional
+// checkparam
+//-------------------------------------------------
+
+inline void drcbe_x64::normalize_commutative(be_parameter &inner, be_parameter &outer)
+{
+ // if the inner parameter is a memory operand, push it to the outer
+ if (inner.is_memory())
+ {
+ be_parameter temp = inner;
+ inner = outer;
+ outer = temp;
+ }
+
+ // if the inner parameter is an immediate, push it to the outer
+ if (inner.is_immediate())
+ {
+ be_parameter temp = inner;
+ inner = outer;
+ outer = temp;
+ }
+}
+
+
+//-------------------------------------------------
+// offset_from_rbp - return the verified offset
+// from rbp
+//-------------------------------------------------
+
+inline INT32 drcbe_x64::offset_from_rbp(const void *ptr)
+{
+ INT64 delta = reinterpret_cast<UINT8 *>(const_cast<void *>(ptr)) - m_rbpvalue;
+ assert_always((INT32)delta == delta, "offset_from_rbp: delta out of range");
+ return (INT32)delta;
+}
+
+
+//-------------------------------------------------
+// get_base_register_and_offset - determine right
+// base register and offset to access the given
+// target address
+//-------------------------------------------------
+
+inline int drcbe_x64::get_base_register_and_offset(x86code *&dst, void *target, UINT8 reg, INT32 &offset)
+{
+ INT64 delta = (UINT8 *)target - m_rbpvalue;
+ if (short_immediate(delta))
+ {
+ offset = delta;
+ return REG_RBP;
+ }
+ else
+ {
+ offset = 0;
+ emit_mov_r64_imm(dst, reg, (FPTR)target); // mov reg,target
+ return reg;
+ }
+}
+
+
+//-------------------------------------------------
+// emit_smart_call_r64 - generate a call either
+// directly or via a call through pointer
+//-------------------------------------------------
+
+inline void drcbe_x64::emit_smart_call_r64(x86code *&dst, x86code *target, UINT8 reg)
+{
+ INT64 delta = target - (dst + 5);
+ if (short_immediate(delta))
+ emit_call(dst, target); // call target
+ else
+ {
+ emit_mov_r64_imm(dst, reg, (FPTR)target); // mov reg,target
+ emit_call_r64(dst, reg); // call reg
+ }
+}
+
+
+//-------------------------------------------------
+// emit_smart_call_m64 - generate a call either
+// directly or via a call through pointer
+//-------------------------------------------------
+
+inline void drcbe_x64::emit_smart_call_m64(x86code *&dst, x86code **target)
+{
+ INT64 delta = *target - (dst + 5);
+ if (short_immediate(delta))
+ emit_call(dst, *target); // call *target
+ else
+ emit_call_m64(dst, MABS(target)); // call [target]
+}
+
+
+
+//**************************************************************************
+// BACKEND CALLBACKS
+//**************************************************************************
+
+//-------------------------------------------------
+// drcbe_x64 - constructor
+//-------------------------------------------------
+
+drcbe_x64::drcbe_x64(drcuml_state &drcuml, device_t &device, drc_cache &cache, UINT32 flags, int modes, int addrbits, int ignorebits)
+ : drcbe_interface(drcuml, cache, device),
+ m_hash(cache, modes, addrbits, ignorebits),
+ m_map(cache, 0),
+ m_labels(cache),
+ m_log(NULL),
+ m_sse41(false),
+ m_absmask32((UINT32 *)cache.alloc_near(16*2 + 15)),
+ m_absmask64(NULL),
+ m_rbpvalue(cache.near() + 0x80),
+ m_entry(NULL),
+ m_exit(NULL),
+ m_nocode(NULL),
+ m_fixup_label(FUNC(drcbe_x64::fixup_label), this),
+ m_fixup_exception(FUNC(drcbe_x64::fixup_exception), this),
+ m_near(*(near_state *)cache.alloc_near(sizeof(m_near)))
+{
+ // build up necessary arrays
+ static const UINT32 sse_control[4] =
+ {
+ 0xffc0, // ROUND_TRUNC
+ 0x9fc0, // ROUND_ROUND
+ 0xdfc0, // ROUND_CEIL
+ 0xbfc0 // ROUND_FLOOR
+ };
+ memcpy(m_near.ssecontrol, sse_control, sizeof(m_near.ssecontrol));
+ m_near.single1 = 1.0f;
+ m_near.double1 = 1.0;
+
+ // create absolute value masks that are aligned to SSE boundaries
+ m_absmask32 = (UINT32 *)(((FPTR)m_absmask32 + 15) & ~15);
+ m_absmask32[0] = m_absmask32[1] = m_absmask32[2] = m_absmask32[3] = 0x7fffffff;
+ m_absmask64 = (UINT64 *)&m_absmask32[4];
+ m_absmask64[0] = m_absmask64[1] = U64(0x7fffffffffffffff);
+
+ // get pointers to C functions we need to call
+ m_near.debug_cpu_instruction_hook = (x86code *)debugger_instruction_hook;
+ if (LOG_HASHJMPS)
+ {
+ m_near.debug_log_hashjmp = (x86code *)debug_log_hashjmp;
+ m_near.debug_log_hashjmp_fail = (x86code *)debug_log_hashjmp_fail;
+ }
+ m_near.drcmap_get_value = (x86code *)&drc_map_variables::static_get_value;
+
+ // build the flags map
+ for (int entry = 0; entry < ARRAY_LENGTH(m_near.flagsmap); entry++)
+ {
+ UINT8 flags = 0;
+ if (entry & 0x001) flags |= FLAG_C;
+ if (entry & 0x004) flags |= FLAG_U;
+ if (entry & 0x040) flags |= FLAG_Z;
+ if (entry & 0x080) flags |= FLAG_S;
+ if (entry & 0x800) flags |= FLAG_V;
+ m_near.flagsmap[entry] = flags;
+ }
+ for (int entry = 0; entry < ARRAY_LENGTH(m_near.flagsunmap); entry++)
+ {
+ UINT64 flags = 0;
+ if (entry & FLAG_C) flags |= 0x001;
+ if (entry & FLAG_U) flags |= 0x004;
+ if (entry & FLAG_Z) flags |= 0x040;
+ if (entry & FLAG_S) flags |= 0x080;
+ if (entry & FLAG_V) flags |= 0x800;
+ m_near.flagsunmap[entry] = flags;
+ }
+
+ // build the opcode table (static but it doesn't hurt to regenerate it)
+ for (int opnum = 0; opnum < ARRAY_LENGTH(s_opcode_table_source); opnum++)
+ s_opcode_table[s_opcode_table_source[opnum].opcode] = s_opcode_table_source[opnum].func;
+
+ // create the log
+ if (flags & DRCUML_OPTION_LOG_NATIVE)
+ m_log = x86log_create_context("drcbex64.asm");
+}
+
+
+//-------------------------------------------------
+// ~drcbe_x64 - destructor
+//-------------------------------------------------
+
+drcbe_x64::~drcbe_x64()
+{
+ // free the log context
+ if (m_log != NULL)
+ x86log_free_context(m_log);
+}
+
+
+//-------------------------------------------------
+// reset - reset back-end specific state
+//-------------------------------------------------
+
+void drcbe_x64::reset()
+{
+ // output a note to the log
+ if (m_log != NULL)
+ x86log_printf(m_log, "\n\n===========\nCACHE RESET\n===========\n\n");
+
+ // generate a little bit of glue code to set up the environment
+ drccodeptr *cachetop = m_cache.begin_codegen(500);
+ if (cachetop == NULL)
+ fatalerror("Out of cache space after a reset!");
+
+ x86code *dst = (x86code *)*cachetop;
+
+ // generate a simple CPUID stub
+ UINT32 (*cpuid_ecx_stub)(void) = (UINT32 (*)(void))dst;
+ emit_push_r64(dst, REG_RBX); // push rbx
+ emit_mov_r32_imm(dst, REG_EAX, 1); // mov eax,1
+ emit_cpuid(dst); // cpuid
+ emit_mov_r32_r32(dst, REG_EAX, REG_ECX); // mov eax,ecx
+ emit_pop_r64(dst, REG_RBX); // pop rbx
+ emit_ret(dst); // ret
+
+ // call it to determine if we have SSE4.1 support
+ m_sse41 = (((*cpuid_ecx_stub)() & 0x80000) != 0);
+
+ // generate an entry point
+ m_entry = (x86_entry_point_func)dst;
+ emit_push_r64(dst, REG_RBX); // push rbx
+ emit_push_r64(dst, REG_RSI); // push rsi
+ emit_push_r64(dst, REG_RDI); // push rdi
+ emit_push_r64(dst, REG_RBP); // push rbp
+ emit_push_r64(dst, REG_R12); // push r12
+ emit_push_r64(dst, REG_R13); // push r13
+ emit_push_r64(dst, REG_R14); // push r14
+ emit_push_r64(dst, REG_R15); // push r15
+ emit_mov_r64_r64(dst, REG_RBP, REG_PARAM1); // mov rbp,param1
+ emit_sub_r64_imm(dst, REG_RSP, 32); // sub rsp,32
+ emit_mov_m64_r64(dst, MABS(&m_near.hashstacksave), REG_RSP); // mov [hashstacksave],rsp
+ emit_sub_r64_imm(dst, REG_RSP, 8); // sub rsp,8
+ emit_mov_m64_r64(dst, MABS(&m_near.stacksave), REG_RSP); // mov [stacksave],rsp
+ emit_stmxcsr_m32(dst, MABS(&m_near.ssemode)); // stmxcsr [ssemode]
+ emit_jmp_r64(dst, REG_PARAM2); // jmp param2
+ if (m_log != NULL)
+ x86log_disasm_code_range(m_log, "entry_point", (x86code *)m_entry, dst);
+
+ // generate an exit point
+ m_exit = dst;
+ emit_ldmxcsr_m32(dst, MABS(&m_near.ssemode)); // ldmxcsr [ssemode]
+ emit_mov_r64_m64(dst, REG_RSP, MABS(&m_near.hashstacksave)); // mov rsp,[hashstacksave]
+ emit_add_r64_imm(dst, REG_RSP, 32); // add rsp,32
+ emit_pop_r64(dst, REG_R15); // pop r15
+ emit_pop_r64(dst, REG_R14); // pop r14
+ emit_pop_r64(dst, REG_R13); // pop r13
+ emit_pop_r64(dst, REG_R12); // pop r12
+ emit_pop_r64(dst, REG_RBP); // pop rbp
+ emit_pop_r64(dst, REG_RDI); // pop rdi
+ emit_pop_r64(dst, REG_RSI); // pop rsi
+ emit_pop_r64(dst, REG_RBX); // pop rbx
+ emit_ret(dst); // ret
+ if (m_log != NULL)
+ x86log_disasm_code_range(m_log, "exit_point", m_exit, dst);
+
+ // generate a no code point
+ m_nocode = dst;
+ emit_ret(dst); // ret
+ if (m_log != NULL)
+ x86log_disasm_code_range(m_log, "nocode", m_nocode, dst);
+
+ // finish up codegen
+ *cachetop = (drccodeptr)dst;
+ m_cache.end_codegen();
+
+ // reset our hash tables
+ m_hash.reset();
+ m_hash.set_default_codeptr(m_nocode);
+}
+
+
+//-------------------------------------------------
+// execute - execute a block of code referenced
+// by the given handle
+//-------------------------------------------------
+
+int drcbe_x64::execute(code_handle &entry)
+{
+ // call our entry point which will jump to the destination
+ return (*m_entry)(m_rbpvalue, (x86code *)entry.codeptr());
+}
+
+
+//-------------------------------------------------
+// drcbex64_generate - generate code
+//-------------------------------------------------
+
+void drcbe_x64::generate(drcuml_block &block, const instruction *instlist, UINT32 numinst)
+{
+ // tell all of our utility objects that a block is beginning
+ m_hash.block_begin(block, instlist, numinst);
+ m_labels.block_begin(block);
+ m_map.block_begin(block);
+
+ // begin codegen; fail if we can't
+ drccodeptr *cachetop = m_cache.begin_codegen(numinst * 8 * 4);
+ if (cachetop == NULL)
+ block.abort();
+
+ // compute the base by aligning the cache top to a cache line (assumed to be 64 bytes)
+ x86code *base = (x86code *)(((FPTR)*cachetop + 63) & ~63);
+ x86code *dst = base;
+
+ // generate code
+ astring tempstring;
+ const char *blockname = NULL;
+ for (int inum = 0; inum < numinst; inum++)
+ {
+ const instruction &inst = instlist[inum];
+ assert(inst.opcode() < ARRAY_LENGTH(s_opcode_table));
+
+ // add a comment
+ if (m_log != NULL)
+ {
+ astring dasm;
+ inst.disasm(dasm, &m_drcuml);
+ x86log_add_comment(m_log, dst, "%s", dasm.cstr());
+ }
+
+ // extract a blockname
+ if (blockname == NULL)
+ {
+ if (inst.opcode() == OP_HANDLE)
+ blockname = inst.param(0).handle().string();
+ else if (inst.opcode() == OP_HASH)
+ blockname = tempstring.format("Code: mode=%d PC=%08X", (UINT32)inst.param(0).immediate(), (offs_t)inst.param(1).immediate());
+ }
+
+ // generate code
+ (this->*s_opcode_table[inst.opcode()])(dst, inst);
+ }
+
+ // complete codegen
+ *cachetop = (drccodeptr)dst;
+ m_cache.end_codegen();
+
+ // log it
+ if (m_log != NULL)
+ x86log_disasm_code_range(m_log, (blockname == NULL) ? "Unknown block" : blockname, base, m_cache.top());
+
+ // tell all of our utility objects that the block is finished
+ m_hash.block_end(block);
+ m_labels.block_end(block);
+ m_map.block_end(block);
+}
+
+
+//-------------------------------------------------
+// hash_exists - return true if the given mode/pc
+// exists in the hash table
+//-------------------------------------------------
+
+bool drcbe_x64::hash_exists(UINT32 mode, UINT32 pc)
+{
+ return m_hash.code_exists(mode, pc);
+}
+
+
+//-------------------------------------------------
+// get_info - return information about the
+// back-end implementation
+//-------------------------------------------------
+
+void drcbe_x64::get_info(drcbe_info &info)
+{
+ for (info.direct_iregs = 0; info.direct_iregs < REG_I_COUNT; info.direct_iregs++)
+ if (int_register_map[info.direct_iregs] == 0)
+ break;
+ for (info.direct_fregs = 0; info.direct_fregs < REG_F_COUNT; info.direct_fregs++)
+ if (float_register_map[info.direct_fregs] == 0)
+ break;
+}
+
+
+
+/***************************************************************************
+ EMITTERS FOR 32-BIT OPERATIONS WITH PARAMETERS
+***************************************************************************/
+
+//-------------------------------------------------
+// emit_mov_r32_p32 - move a 32-bit parameter
+// into a register
+//-------------------------------------------------
+
+void drcbe_x64::emit_mov_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param)
+{
+ if (param.is_immediate())
+ {
+ if (param.immediate() == 0)
+ emit_xor_r32_r32(dst, reg, reg); // xor reg,reg
+ else
+ emit_mov_r32_imm(dst, reg, param.immediate()); // mov reg,param
+ }
+ else if (param.is_memory())
+ emit_mov_r32_m32(dst, reg, MABS(param.memory())); // mov reg,[param]
+ else if (param.is_int_register())
+ {
+ if (reg != param.ireg())
+ emit_mov_r32_r32(dst, reg, param.ireg()); // mov reg,param
+ }
+}
+
+
+//-------------------------------------------------
+// emit_movsx_r64_p32 - move a 32-bit parameter
+// sign-extended into a register
+//-------------------------------------------------
+
+void drcbe_x64::emit_movsx_r64_p32(x86code *&dst, UINT8 reg, const be_parameter &param)
+{
+ if (param.is_immediate())
+ {
+ if (param.immediate() == 0)
+ emit_xor_r32_r32(dst, reg, reg); // xor reg,reg
+ else if ((INT32)param.immediate() >= 0)
+ emit_mov_r32_imm(dst, reg, param.immediate()); // mov reg,param
+ else
+ emit_mov_r64_imm(dst, reg, (INT32)param.immediate()); // mov reg,param
+ }
+ else if (param.is_memory())
+ emit_movsxd_r64_m32(dst, reg, MABS(param.memory())); // movsxd reg,[param]
+ else if (param.is_int_register())
+ emit_movsxd_r64_r32(dst, reg, param.ireg()); // movsdx reg,param
+}
+
+
+//-------------------------------------------------
+// emit_mov_r32_p32_keepflags - move a 32-bit
+// parameter into a register without affecting
+// any flags
+//-------------------------------------------------
+
+void drcbe_x64::emit_mov_r32_p32_keepflags(x86code *&dst, UINT8 reg, const be_parameter &param)
+{
+ if (param.is_immediate())
+ emit_mov_r32_imm(dst, reg, param.immediate()); // mov reg,param
+ else if (param.is_memory())
+ emit_mov_r32_m32(dst, reg, MABS(param.memory())); // mov reg,[param]
+ else if (param.is_int_register())
+ {
+ if (reg != param.ireg())
+ emit_mov_r32_r32(dst, reg, param.ireg()); // mov reg,param
+ }
+}
+
+
+//-------------------------------------------------
+// emit_mov_m32_p32 - move a 32-bit parameter
+// into a memory location
+//-------------------------------------------------
+
+void drcbe_x64::emit_mov_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param)
+{
+ if (param.is_immediate())
+ emit_mov_m32_imm(dst, memref, param.immediate()); // mov [mem],param
+ else if (param.is_memory())
+ {
+ emit_mov_r32_m32(dst, REG_EAX, MABS(param.memory())); // mov eax,[param]
+ emit_mov_m32_r32(dst, memref, REG_EAX); // mov [mem],eax
+ }
+ else if (param.is_int_register())
+ emit_mov_m32_r32(dst, memref, param.ireg()); // mov [mem],param
+}
+
+
+//-------------------------------------------------
+// emit_mov_p32_r32 - move a register into a
+// 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_mov_p32_r32(x86code *&dst, const be_parameter &param, UINT8 reg)
+{
+ assert(!param.is_immediate());
+ if (param.is_memory())
+ emit_mov_m32_r32(dst, MABS(param.memory()), reg); // mov [param],reg
+ else if (param.is_int_register())
+ {
+ if (reg != param.ireg())
+ emit_mov_r32_r32(dst, param.ireg(), reg); // mov param,reg
+ }
+}
+
+
+//-------------------------------------------------
+// emit_add_r32_p32 - add operation to a 32-bit
+// register from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_add_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() != 0 || param.immediate() != 0)
+ emit_add_r32_imm(dst, reg, param.immediate()); // add reg,param
+ }
+ else if (param.is_memory())
+ emit_add_r32_m32(dst, reg, MABS(param.memory())); // add reg,[param]
+ else if (param.is_int_register())
+ emit_add_r32_r32(dst, reg, param.ireg()); // add reg,param
+}
+
+
+//-------------------------------------------------
+// emit_add_m32_p32 - add operation to a 32-bit
+// memory location from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_add_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() != 0 || param.immediate() != 0)
+ emit_add_m32_imm(dst, memref, param.immediate()); // add [dest],param
+ }
+ else
+ {
+ int reg = param.select_register(REG_EAX);
+ emit_mov_r32_p32(dst, reg, param); // mov reg,param
+ emit_add_m32_r32(dst, memref, reg); // add [dest],reg
+ }
+}
+
+
+//-------------------------------------------------
+// emit_adc_r32_p32 - adc operation to a 32-bit
+// register from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_adc_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ emit_adc_r32_imm(dst, reg, param.immediate()); // adc reg,param
+ else if (param.is_memory())
+ emit_adc_r32_m32(dst, reg, MABS(param.memory())); // adc reg,[param]
+ else if (param.is_int_register())
+ emit_adc_r32_r32(dst, reg, param.ireg()); // adc reg,param
+}
+
+
+//-------------------------------------------------
+// emit_adc_m32_p32 - adc operation to a 32-bit
+// memory location from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_adc_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ emit_adc_m32_imm(dst, memref, param.immediate()); // adc [dest],param
+ else
+ {
+ int reg = param.select_register(REG_EAX);
+ emit_mov_r32_p32_keepflags(dst, reg, param); // mov reg,param
+ emit_adc_m32_r32(dst, memref, reg); // adc [dest],reg
+ }
+}
+
+
+//-------------------------------------------------
+// emit_sub_r32_p32 - sub operation to a 32-bit
+// register from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_sub_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() != 0 || param.immediate() != 0)
+ emit_sub_r32_imm(dst, reg, param.immediate()); // sub reg,param
+ }
+ else if (param.is_memory())
+ emit_sub_r32_m32(dst, reg, MABS(param.memory())); // sub reg,[param]
+ else if (param.is_int_register())
+ emit_sub_r32_r32(dst, reg, param.ireg()); // sub reg,param
+}
+
+
+//-------------------------------------------------
+// emit_sub_m32_p32 - sub operation to a 32-bit
+// memory location from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_sub_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() != 0 || param.immediate() != 0)
+ emit_sub_m32_imm(dst, memref, param.immediate()); // sub [dest],param
+ }
+ else
+ {
+ int reg = param.select_register(REG_EAX);
+ emit_mov_r32_p32(dst, reg, param); // mov reg,param
+ emit_sub_m32_r32(dst, memref, reg); // sub [dest],reg
+ }
+}
+
+
+//-------------------------------------------------
+// emit_sbb_r32_p32 - sbb operation to a 32-bit
+// register from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_sbb_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ emit_sbb_r32_imm(dst, reg, param.immediate()); // sbb reg,param
+ else if (param.is_memory())
+ emit_sbb_r32_m32(dst, reg, MABS(param.memory())); // sbb reg,[param]
+ else if (param.is_int_register())
+ emit_sbb_r32_r32(dst, reg, param.ireg()); // sbb reg,param
+}
+
+
+//-------------------------------------------------
+// emit_sbb_m32_p32 - sbb operation to a 32-bit
+// memory location from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_sbb_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ emit_sbb_m32_imm(dst, memref, param.immediate()); // sbb [dest],param
+ else
+ {
+ int reg = param.select_register(REG_EAX);
+ emit_mov_r32_p32_keepflags(dst, reg, param); // mov reg,param
+ emit_sbb_m32_r32(dst, memref, reg); // sbb [dest],reg
+ }
+}
+
+
+//-------------------------------------------------
+// emit_cmp_r32_p32 - cmp operation to a 32-bit
+// register from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_cmp_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ emit_cmp_r32_imm(dst, reg, param.immediate()); // cmp reg,param
+ else if (param.is_memory())
+ emit_cmp_r32_m32(dst, reg, MABS(param.memory())); // cmp reg,[param]
+ else if (param.is_int_register())
+ emit_cmp_r32_r32(dst, reg, param.ireg()); // cmp reg,param
+}
+
+
+//-------------------------------------------------
+// emit_cmp_m32_p32 - cmp operation to a 32-bit
+// memory location from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_cmp_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ emit_cmp_m32_imm(dst, memref, param.immediate()); // cmp [dest],param
+ else
+ {
+ int reg = param.select_register(REG_EAX);
+ emit_mov_r32_p32(dst, reg, param); // mov reg,param
+ emit_cmp_m32_r32(dst, memref, reg); // cmp [dest],reg
+ }
+}
+
+
+//-------------------------------------------------
+// emit_and_r32_p32 - and operation to a 32-bit
+// register from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_and_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
+ ;// skip
+ else if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ emit_xor_r32_r32(dst, reg, reg); // xor reg,reg
+ else
+ emit_and_r32_imm(dst, reg, param.immediate()); // and reg,param
+ }
+ else if (param.is_memory())
+ emit_and_r32_m32(dst, reg, MABS(param.memory())); // and reg,[param]
+ else if (param.is_int_register())
+ emit_and_r32_r32(dst, reg, param.ireg()); // and reg,param
+}
+
+
+//-------------------------------------------------
+// emit_and_m32_p32 - and operation to a 32-bit
+// memory location from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_and_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
+ ;// skip
+ else if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ emit_mov_m32_imm(dst, memref, 0); // mov [dest],0
+ else
+ emit_and_m32_imm(dst, memref, param.immediate()); // and [dest],param
+ }
+ else
+ {
+ int reg = param.select_register(REG_EAX);
+ emit_mov_r32_p32(dst, reg, param); // mov reg,param
+ emit_and_m32_r32(dst, memref, reg); // and [dest],reg
+ }
+}
+
+
+//-------------------------------------------------
+// emit_test_r32_p32 - test operation to a 32-bit
+// register from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_test_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ emit_test_r32_imm(dst, reg, param.immediate()); // test reg,param
+ else if (param.is_memory())
+ emit_test_m32_r32(dst, MABS(param.memory()), reg); // test [param],reg
+ else if (param.is_int_register())
+ emit_test_r32_r32(dst, reg, param.ireg()); // test reg,param
+}
+
+
+//-------------------------------------------------
+// emit_test_m32_p32 - test operation to a 32-bit
+// memory location from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_test_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ emit_test_m32_imm(dst, memref, param.immediate()); // test [dest],param
+ else if (param.is_memory())
+ {
+ emit_mov_r32_p32(dst, REG_EAX, param); // mov reg,param
+ emit_test_m32_r32(dst, memref, REG_EAX); // test [dest],reg
+ }
+ else if (param.is_int_register())
+ emit_test_m32_r32(dst, memref, param.ireg()); // test [dest],param
+}
+
+
+//-------------------------------------------------
+// emit_or_r32_p32 - or operation to a 32-bit
+// register from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_or_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
+ emit_mov_r32_imm(dst, reg, 0xffffffff); // mov reg,-1
+ else
+ emit_or_r32_imm(dst, reg, param.immediate()); // or reg,param
+ }
+ else if (param.is_memory())
+ emit_or_r32_m32(dst, reg, MABS(param.memory())); // or reg,[param]
+ else if (param.is_int_register())
+ emit_or_r32_r32(dst, reg, param.ireg()); // or reg,param
+}
+
+
+//-------------------------------------------------
+// emit_or_m32_p32 - or operation to a 32-bit
+// memory location from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_or_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
+ emit_mov_m32_imm(dst, memref, 0xffffffff); // mov [dest],-1
+ else
+ emit_or_m32_imm(dst, memref, param.immediate()); // or [dest],param
+ }
+ else
+ {
+ int reg = param.select_register(REG_EAX);
+ emit_mov_r32_p32(dst, reg, param); // mov reg,param
+ emit_or_m32_r32(dst, memref, reg); // or [dest],reg
+ }
+}
+
+
+//-------------------------------------------------
+// emit_xor_r32_p32 - xor operation to a 32-bit
+// register from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_xor_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
+ emit_not_r32(dst, reg); // not reg
+ else
+ emit_xor_r32_imm(dst, reg, param.immediate()); // xor reg,param
+ }
+ else if (param.is_memory())
+ emit_xor_r32_m32(dst, reg, MABS(param.memory())); // xor reg,[param]
+ else if (param.is_int_register())
+ emit_xor_r32_r32(dst, reg, param.ireg()); // xor reg,param
+}
+
+
+//-------------------------------------------------
+// emit_xor_m32_p32 - xor operation to a 32-bit
+// memory location from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_xor_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
+ emit_not_m32(dst, memref); // not [dest]
+ else
+ emit_xor_m32_imm(dst, memref, param.immediate()); // xor [dest],param
+ }
+ else
+ {
+ int reg = param.select_register(REG_EAX);
+ emit_mov_r32_p32(dst, reg, param); // mov reg,param
+ emit_xor_m32_r32(dst, memref, reg); // xor [dest],reg
+ }
+}
+
+
+//-------------------------------------------------
+// emit_shl_r32_p32 - shl operation to a 32-bit
+// register from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_shl_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else
+ emit_shl_r32_imm(dst, reg, param.immediate()); // shl reg,param
+ }
+ else
+ {
+ emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param
+ emit_shl_r32_cl(dst, reg); // shl reg,cl
+ }
+}
+
+
+//-------------------------------------------------
+// emit_shl_m32_p32 - shl operation to a 32-bit
+// memory location from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_shl_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else
+ emit_shl_m32_imm(dst, memref, param.immediate()); // shl [dest],param
+ }
+ else
+ {
+ emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param
+ emit_shl_m32_cl(dst, memref); // shl [dest],cl
+ }
+}
+
+
+//-------------------------------------------------
+// emit_shr_r32_p32 - shr operation to a 32-bit
+// register from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_shr_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else
+ emit_shr_r32_imm(dst, reg, param.immediate()); // shr reg,param
+ }
+ else
+ {
+ emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param
+ emit_shr_r32_cl(dst, reg); // shr reg,cl
+ }
+}
+
+
+//-------------------------------------------------
+// emit_shr_m32_p32 - shr operation to a 32-bit
+// memory location from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_shr_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else
+ emit_shr_m32_imm(dst, memref, param.immediate()); // shr [dest],param
+ }
+ else
+ {
+ emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param
+ emit_shr_m32_cl(dst, memref); // shr [dest],cl
+ }
+}
+
+
+//-------------------------------------------------
+// emit_sar_r32_p32 - sar operation to a 32-bit
+// register from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_sar_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else
+ emit_sar_r32_imm(dst, reg, param.immediate()); // sar reg,param
+ }
+ else
+ {
+ emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param
+ emit_sar_r32_cl(dst, reg); // sar reg,cl
+ }
+}
+
+
+//-------------------------------------------------
+// emit_sar_m32_p32 - sar operation to a 32-bit
+// memory location from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_sar_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else
+ emit_sar_m32_imm(dst, memref, param.immediate()); // sar [dest],param
+ }
+ else
+ {
+ emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param
+ emit_sar_m32_cl(dst, memref); // sar [dest],cl
+ }
+}
+
+
+//-------------------------------------------------
+// emit_rol_r32_p32 - rol operation to a 32-bit
+// register from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_rol_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else
+ emit_rol_r32_imm(dst, reg, param.immediate()); // rol reg,param
+ }
+ else
+ {
+ emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param
+ emit_rol_r32_cl(dst, reg); // rol reg,cl
+ }
+}
+
+
+//-------------------------------------------------
+// emit_rol_m32_p32 - rol operation to a 32-bit
+// memory location from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_rol_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else
+ emit_rol_m32_imm(dst, memref, param.immediate()); // rol [dest],param
+ }
+ else
+ {
+ emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param
+ emit_rol_m32_cl(dst, memref); // rol [dest],cl
+ }
+}
+
+
+//-------------------------------------------------
+// emit_ror_r32_p32 - ror operation to a 32-bit
+// register from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_ror_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else
+ emit_ror_r32_imm(dst, reg, param.immediate()); // ror reg,param
+ }
+ else
+ {
+ emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param
+ emit_ror_r32_cl(dst, reg); // ror reg,cl
+ }
+}
+
+
+//-------------------------------------------------
+// emit_ror_m32_p32 - ror operation to a 32-bit
+// memory location from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_ror_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else
+ emit_ror_m32_imm(dst, memref, param.immediate()); // ror [dest],param
+ }
+ else
+ {
+ emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param
+ emit_ror_m32_cl(dst, memref); // ror [dest],cl
+ }
+}
+
+
+//-------------------------------------------------
+// emit_rcl_r32_p32 - rcl operation to a 32-bit
+// register from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_rcl_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else
+ emit_rcl_r32_imm(dst, reg, param.immediate()); // rcl reg,param
+ }
+ else
+ {
+ emit_mov_r32_p32_keepflags(dst, REG_ECX, param); // mov ecx,param
+ emit_rcl_r32_cl(dst, reg); // rcl reg,cl
+ }
+}
+
+
+//-------------------------------------------------
+// emit_rcl_m32_p32 - rcl operation to a 32-bit
+// memory location from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_rcl_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else
+ emit_rcl_m32_imm(dst, memref, param.immediate()); // rcl [dest],param
+ }
+ else
+ {
+ emit_mov_r32_p32_keepflags(dst, REG_ECX, param); // mov ecx,param
+ emit_rcl_m32_cl(dst, memref); // rcl [dest],cl
+ }
+}
+
+
+//-------------------------------------------------
+// emit_rcr_r32_p32 - rcr operation to a 32-bit
+// register from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_rcr_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else
+ emit_rcr_r32_imm(dst, reg, param.immediate()); // rcr reg,param
+ }
+ else
+ {
+ emit_mov_r32_p32_keepflags(dst, REG_ECX, param); // mov ecx,param
+ emit_rcr_r32_cl(dst, reg); // rcr reg,cl
+ }
+}
+
+
+//-------------------------------------------------
+// emit_rcr_m32_p32 - rcr operation to a 32-bit
+// memory location from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_rcr_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else
+ emit_rcr_m32_imm(dst, memref, param.immediate()); // rcr [dest],param
+ }
+ else
+ {
+ emit_mov_r32_p32_keepflags(dst, REG_ECX, param); // mov ecx,param
+ emit_rcr_m32_cl(dst, memref); // rcr [dest],cl
+ }
+}
+
+
+
+/***************************************************************************
+ EMITTERS FOR 64-BIT OPERATIONS WITH PARAMETERS
+***************************************************************************/
+
+//-------------------------------------------------
+// emit_mov_r64_p64 - move a 64-bit parameter
+// into a register
+//-------------------------------------------------
+
+void drcbe_x64::emit_mov_r64_p64(x86code *&dst, UINT8 reg, const be_parameter &param)
+{
+ if (param.is_immediate())
+ {
+ if (param.immediate() == 0)
+ emit_xor_r32_r32(dst, reg, reg); // xor reg,reg
+ else
+ emit_mov_r64_imm(dst, reg, param.immediate()); // mov reg,param
+ }
+ else if (param.is_memory())
+ emit_mov_r64_m64(dst, reg, MABS(param.memory())); // mov reg,[param]
+ else if (param.is_int_register())
+ {
+ if (reg != param.ireg())
+ emit_mov_r64_r64(dst, reg, param.ireg()); // mov reg,param
+ }
+}
+
+
+//-------------------------------------------------
+// emit_mov_r64_p64_keepflags - move a 64-bit
+// parameter into a register without affecting
+// any flags
+//-------------------------------------------------
+
+void drcbe_x64::emit_mov_r64_p64_keepflags(x86code *&dst, UINT8 reg, const be_parameter &param)
+{
+ if (param.is_immediate())
+ emit_mov_r64_imm(dst, reg, param.immediate()); // mov reg,param
+ else if (param.is_memory())
+ emit_mov_r64_m64(dst, reg, MABS(param.memory())); // mov reg,[param]
+ else if (param.is_int_register())
+ {
+ if (reg != param.ireg())
+ emit_mov_r64_r64(dst, reg, param.ireg()); // mov reg,param
+ }
+}
+
+
+//-------------------------------------------------
+// emit_mov_p64_r64 - move a registers into a
+// 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_mov_p64_r64(x86code *&dst, const be_parameter &param, UINT8 reg)
+{
+ assert(!param.is_immediate());
+ if (param.is_memory())
+ emit_mov_m64_r64(dst, MABS(param.memory()), reg); // mov [param],reg
+ else if (param.is_int_register())
+ {
+ if (reg != param.ireg())
+ emit_mov_r64_r64(dst, param.ireg(), reg); // mov param,reg
+ }
+}
+
+
+//-------------------------------------------------
+// emit_add_r64_p64 - add operation to a 64-bit
+// register from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_add_r64_p64(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() != 0 || param.immediate() != 0)
+ {
+ if (short_immediate(param.immediate()))
+ emit_add_r64_imm(dst, reg, param.immediate()); // add reg,param
+ else
+ {
+ emit_mov_r64_imm(dst, REG_R11, param.immediate()); // mov r11,param
+ emit_add_r64_r64(dst, reg, REG_R11); // add reg,r11
+ }
+ }
+ }
+ else if (param.is_memory())
+ emit_add_r64_m64(dst, reg, MABS(param.memory())); // add reg,[param]
+ else if (param.is_int_register())
+ emit_add_r64_r64(dst, reg, param.ireg()); // add reg,param
+}
+
+
+//-------------------------------------------------
+// emit_add_m64_p64 - add operation to a 64-bit
+// memory location from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_add_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() != 0 || param.immediate() != 0)
+ {
+ if (short_immediate(param.immediate()))
+ emit_add_m64_imm(dst, memref, param.immediate()); // add [mem],param
+ else
+ {
+ emit_mov_r64_imm(dst, REG_R11, param.immediate()); // mov r11,param
+ emit_add_m64_r64(dst, memref, REG_R11); // add [mem],r11
+ }
+ }
+ }
+ else
+ {
+ int reg = param.select_register(REG_EAX);
+ emit_mov_r64_p64(dst, reg, param); // mov reg,param
+ emit_add_m64_r64(dst, memref, reg); // add [dest],reg
+ }
+}
+
+
+//-------------------------------------------------
+// emit_adc_r64_p64 - adc operation to a 64-bit
+// register from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_adc_r64_p64(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (short_immediate(param.immediate()))
+ emit_adc_r64_imm(dst, reg, param.immediate()); // adc reg,param
+ else
+ {
+ emit_mov_r64_imm(dst, REG_R11, param.immediate()); // mov r11,param
+ emit_adc_r64_r64(dst, reg, REG_R11); // adc reg,r11
+ }
+ }
+ else if (param.is_memory())
+ emit_adc_r64_m64(dst, reg, MABS(param.memory())); // adc reg,[param]
+ else if (param.is_int_register())
+ emit_adc_r64_r64(dst, reg, param.ireg()); // adc reg,param
+}
+
+
+//-------------------------------------------------
+// emit_adc_m64_p64 - adc operation to a 64-bit
+// memory locaiton from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_adc_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate() && short_immediate(param.immediate()))
+ emit_adc_m64_imm(dst, memref, param.immediate()); // adc [mem],param
+ else
+ {
+ int reg = param.select_register(REG_EAX);
+ emit_mov_r64_p64_keepflags(dst, reg, param); // mov reg,param
+ emit_adc_m64_r64(dst, memref, reg); // adc [dest],reg
+ }
+}
+
+
+//-------------------------------------------------
+// emit_sub_r64_p64 - sub operation to a 64-bit
+// register from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_sub_r64_p64(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() != 0 || param.immediate() != 0)
+ {
+ if (short_immediate(param.immediate()))
+ emit_sub_r64_imm(dst, reg, param.immediate()); // sub reg,param
+ else
+ {
+ emit_mov_r64_imm(dst, REG_R11, param.immediate()); // mov r11,param
+ emit_sub_r64_r64(dst, reg, REG_R11); // sub reg,r11
+ }
+ }
+ }
+ else if (param.is_memory())
+ emit_sub_r64_m64(dst, reg, MABS(param.memory())); // sub reg,[param]
+ else if (param.is_int_register())
+ emit_sub_r64_r64(dst, reg, param.ireg()); // sub reg,param
+}
+
+
+//-------------------------------------------------
+// emit_sub_m64_p64 - sub operation to a 64-bit
+// memory location from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_sub_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() != 0 || param.immediate() != 0)
+ {
+ if (short_immediate(param.immediate()))
+ emit_sub_m64_imm(dst, memref, param.immediate()); // sub [mem],param
+ else
+ {
+ emit_mov_r64_imm(dst, REG_R11, param.immediate()); // mov r11,param
+ emit_sub_m64_r64(dst, memref, REG_R11); // sub [mem],r11
+ }
+ }
+ }
+ else
+ {
+ int reg = param.select_register(REG_EAX);
+ emit_mov_r64_p64(dst, reg, param); // mov reg,param
+ emit_sub_m64_r64(dst, memref, reg); // sub [dest],reg
+ }
+}
+
+
+//-------------------------------------------------
+// emit_sbb_r64_p64 - sbb operation to a 64-bit
+// register from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_sbb_r64_p64(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (short_immediate(param.immediate()))
+ emit_sbb_r64_imm(dst, reg, param.immediate()); // sbb reg,param
+ else
+ {
+ emit_mov_r64_imm(dst, REG_R11, param.immediate()); // mov r11,param
+ emit_sbb_r64_r64(dst, reg, REG_R11); // sbb reg,r11
+ }
+ }
+ else if (param.is_memory())
+ emit_sbb_r64_m64(dst, reg, MABS(param.memory())); // sbb reg,[param]
+ else if (param.is_int_register())
+ emit_sbb_r64_r64(dst, reg, param.ireg()); // sbb reg,param
+}
+
+
+//-------------------------------------------------
+// emit_sbb_m64_p64 - sbb operation to a 64-bit
+// memory location from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_sbb_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate() && short_immediate(param.immediate()))
+ emit_sbb_m64_imm(dst, memref, param.immediate()); // sbb [mem],param
+ else
+ {
+ int reg = param.select_register(REG_EAX);
+ emit_mov_r64_p64_keepflags(dst, reg, param); // mov reg,param
+ emit_sbb_m64_r64(dst, memref, reg); // sbb [dest],reg
+ }
+}
+
+
+//-------------------------------------------------
+// emit_cmp_r64_p64 - cmp operation to a 64-bit
+// register from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_cmp_r64_p64(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (short_immediate(param.immediate()))
+ emit_cmp_r64_imm(dst, reg, param.immediate()); // cmp reg,param
+ else
+ {
+ emit_mov_r64_imm(dst, REG_R11, param.immediate()); // mov r11,param
+ emit_cmp_r64_r64(dst, reg, REG_R11); // cmp reg,r11
+ }
+ }
+ else if (param.is_memory())
+ emit_cmp_r64_m64(dst, reg, MABS(param.memory())); // cmp reg,[param]
+ else if (param.is_int_register())
+ emit_cmp_r64_r64(dst, reg, param.ireg()); // cmp reg,param
+}
+
+
+//-------------------------------------------------
+// emit_cmp_m64_p64 - cmp operation to a 64-bit
+// memory location from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_cmp_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate() && short_immediate(param.immediate()))
+ emit_cmp_m64_imm(dst, memref, param.immediate()); // cmp [dest],param
+ else
+ {
+ int reg = param.select_register(REG_EAX);
+ emit_mov_r64_p64(dst, reg, param); // mov reg,param
+ emit_cmp_m64_r64(dst, memref, reg); // cmp [dest],reg
+ }
+}
+
+
+//-------------------------------------------------
+// emit_and_r64_p64 - and operation to a 64-bit
+// register from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_and_r64_p64(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() != 0 || param.immediate() != U64(0xffffffffffffffff))
+ {
+ if (short_immediate(param.immediate()))
+ emit_and_r64_imm(dst, reg, param.immediate()); // and reg,param
+ else
+ {
+ emit_mov_r64_imm(dst, REG_R11, param.immediate()); // mov r11,param
+ emit_and_r64_r64(dst, reg, REG_R11); // and reg,r11
+ }
+ }
+ }
+ else if (param.is_memory())
+ emit_and_r64_m64(dst, reg, MABS(param.memory())); // and reg,[param]
+ else if (param.is_int_register())
+ emit_and_r64_r64(dst, reg, param.ireg()); // and reg,param
+}
+
+
+//-------------------------------------------------
+// emit_and_m64_p64 - and operation to a 64-bit
+// memory location from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_and_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() != 0 || param.immediate() != U64(0xffffffffffffffff))
+ {
+ if (short_immediate(param.immediate()))
+ emit_and_m64_imm(dst, memref, param.immediate()); // and [mem],param
+ else
+ {
+ emit_mov_r64_imm(dst, REG_R11, param.immediate()); // mov r11,param
+ emit_and_m64_r64(dst, memref, REG_R11); // and [mem],r11
+ }
+ }
+ }
+ else
+ {
+ int reg = param.select_register(REG_EAX);
+ emit_mov_r64_p64(dst, reg, param); // mov reg,param
+ emit_and_m64_r64(dst, memref, reg); // and [dest],reg
+ }
+}
+
+
+//-------------------------------------------------
+// emit_test_r64_p64 - test operation to a 64-bit
+// register from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_test_r64_p64(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (short_immediate(param.immediate()))
+ emit_test_r64_imm(dst, reg, param.immediate()); // test reg,param
+ else
+ {
+ emit_mov_r64_imm(dst, REG_R11, param.immediate()); // mov r11,param
+ emit_test_r64_r64(dst, reg, REG_R11); // test reg,r11
+ }
+ }
+ else if (param.is_memory())
+ emit_test_m64_r64(dst, MABS(param.memory()), reg); // test [param],reg
+ else if (param.is_int_register())
+ emit_test_r64_r64(dst, reg, param.ireg()); // test reg,param
+}
+
+
+//-------------------------------------------------
+// emit_test_m64_p64 - test operation to a 64-bit
+// memory location from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_test_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate() && short_immediate(param.immediate()))
+ emit_test_m64_imm(dst, memref, param.immediate()); // test [dest],param
+ else if (param.is_memory())
+ {
+ emit_mov_r64_p64(dst, REG_EAX, param); // mov reg,param
+ emit_test_m64_r64(dst, memref, REG_EAX); // test [dest],reg
+ }
+ else if (param.is_int_register())
+ emit_test_m64_r64(dst, memref, param.ireg()); // test [dest],param
+}
+
+
+//-------------------------------------------------
+// emit_or_r64_p64 - or operation to a 64-bit
+// register from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_or_r64_p64(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() != 0 || param.immediate() != 0)
+ {
+ if (short_immediate(param.immediate()))
+ emit_or_r64_imm(dst, reg, param.immediate()); // or reg,param
+ else
+ {
+ emit_mov_r64_imm(dst, REG_R11, param.immediate()); // mov r11,param
+ emit_or_r64_r64(dst, reg, REG_R11); // or reg,r11
+ }
+ }
+ }
+ else if (param.is_memory())
+ emit_or_r64_m64(dst, reg, MABS(param.memory())); // or reg,[param]
+ else if (param.is_int_register())
+ emit_or_r64_r64(dst, reg, param.ireg()); // or reg,param
+}
+
+
+//-------------------------------------------------
+// emit_or_m64_p64 - or operation to a 64-bit
+// memory location from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_or_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() != 0 || param.immediate() != 0)
+ {
+ if (short_immediate(param.immediate()))
+ emit_or_m64_imm(dst, memref, param.immediate()); // or [mem],param
+ else
+ {
+ emit_mov_r64_imm(dst, REG_R11, param.immediate()); // mov r11,param
+ emit_or_m64_r64(dst, memref, REG_R11); // or [mem],r11
+ }
+ }
+ }
+ else
+ {
+ int reg = param.select_register(REG_EAX);
+ emit_mov_r64_p64(dst, reg, param); // mov reg,param
+ emit_or_m64_r64(dst, memref, reg); // or [dest],reg
+ }
+}
+
+
+//-------------------------------------------------
+// emit_xor_r64_p64 - xor operation to a 64-bit
+// register from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_xor_r64_p64(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() != 0 || param.immediate() != 0)
+ {
+ if (param.immediate() == U64(0xffffffffffffffff))
+ emit_not_r64(dst, reg); // not reg
+ else if (short_immediate(param.immediate()))
+ emit_xor_r64_imm(dst, reg, param.immediate()); // xor reg,param
+ else
+ {
+ emit_mov_r64_imm(dst, REG_R11, param.immediate()); // mov r11,param
+ emit_xor_r64_r64(dst, reg, REG_R11); // xor reg,r11
+ }
+ }
+ }
+ else if (param.is_memory())
+ emit_xor_r64_m64(dst, reg, MABS(param.memory())); // xor reg,[param]
+ else if (param.is_int_register())
+ emit_xor_r64_r64(dst, reg, param.ireg()); // xor reg,param
+}
+
+
+//-------------------------------------------------
+// emit_xor_m64_p64 - xor operation to a 64-bit
+// memory location from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_xor_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() != 0 || param.immediate() != 0)
+ {
+ if (param.immediate() == U64(0xffffffffffffffff))
+ emit_not_m64(dst, memref); // not [mem]
+ else if (short_immediate(param.immediate()))
+ emit_xor_m64_imm(dst, memref, param.immediate()); // xor [mem],param
+ else
+ {
+ emit_mov_r64_imm(dst, REG_R11, param.immediate()); // mov r11,param
+ emit_xor_m64_r64(dst, memref, REG_R11); // xor [mem],r11
+ }
+ }
+ }
+ else
+ {
+ int reg = param.select_register(REG_EAX);
+ emit_mov_r64_p64(dst, reg, param); // mov reg,param
+ emit_xor_m64_r64(dst, memref, reg); // xor [dest],reg
+ }
+}
+
+
+//-------------------------------------------------
+// emit_shl_r64_p64 - shl operation to a 64-bit
+// register from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_shl_r64_p64(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else
+ emit_shl_r64_imm(dst, reg, param.immediate()); // shl reg,param
+ }
+ else
+ {
+ emit_mov_r64_p64(dst, REG_RCX, param); // mov rcx,param
+ emit_shl_r64_cl(dst, reg); // shl reg,cl
+ }
+}
+
+
+//-------------------------------------------------
+// emit_shl_m64_p64 - shl operation to a 64-bit
+// memory location from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_shl_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT64)param.immediate() == 0)
+ ;// skip
+ else
+ emit_shl_m64_imm(dst, memref, param.immediate()); // shl [dest],param
+ }
+ else
+ {
+ emit_mov_r64_p64(dst, REG_RCX, param); // mov rcx,param
+ emit_shl_m64_cl(dst, memref); // shl [dest],cl
+ }
+}
+
+
+//-------------------------------------------------
+// emit_shr_r64_p64 - shr operation to a 64-bit
+// register from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_shr_r64_p64(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else
+ emit_shr_r64_imm(dst, reg, param.immediate()); // shr reg,param
+ }
+ else
+ {
+ emit_mov_r64_p64(dst, REG_RCX, param); // mov rcx,param
+ emit_shr_r64_cl(dst, reg); // shr reg,cl
+ }
+}
+
+
+//-------------------------------------------------
+// emit_shr_m64_p64 - shr operation to a 64-bit
+// memory location from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_shr_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT64)param.immediate() == 0)
+ ;// skip
+ else
+ emit_shr_m64_imm(dst, memref, param.immediate()); // shr [dest],param
+ }
+ else
+ {
+ emit_mov_r64_p64(dst, REG_RCX, param); // mov rcx,param
+ emit_shr_m64_cl(dst, memref); // shr [dest],cl
+ }
+}
+
+
+//-------------------------------------------------
+// emit_sar_r64_p64 - sar operation to a 64-bit
+// register from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_sar_r64_p64(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else
+ emit_sar_r64_imm(dst, reg, param.immediate()); // sar reg,param
+ }
+ else
+ {
+ emit_mov_r64_p64(dst, REG_RCX, param); // mov rcx,param
+ emit_sar_r64_cl(dst, reg); // sar reg,cl
+ }
+}
+
+
+//-------------------------------------------------
+// emit_sar_m64_p64 - sar operation to a 64-bit
+// memory location from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_sar_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT64)param.immediate() == 0)
+ ;// skip
+ else
+ emit_sar_m64_imm(dst, memref, param.immediate()); // sar [dest],param
+ }
+ else
+ {
+ emit_mov_r64_p64(dst, REG_RCX, param); // mov rcx,param
+ emit_sar_m64_cl(dst, memref); // sar [dest],cl
+ }
+}
+
+
+//-------------------------------------------------
+// emit_rol_r64_p64 - rol operation to a 64-bit
+// register from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_rol_r64_p64(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else
+ emit_rol_r64_imm(dst, reg, param.immediate()); // rol reg,param
+ }
+ else
+ {
+ emit_mov_r64_p64(dst, REG_RCX, param); // mov rcx,param
+ emit_rol_r64_cl(dst, reg); // rol reg,cl
+ }
+}
+
+
+//-------------------------------------------------
+// emit_rol_m64_p64 - rol operation to a 64-bit
+// memory location from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_rol_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT64)param.immediate() == 0)
+ ;// skip
+ else
+ emit_rol_m64_imm(dst, memref, param.immediate()); // rol [dest],param
+ }
+ else
+ {
+ emit_mov_r64_p64(dst, REG_RCX, param); // mov rcx,param
+ emit_rol_m64_cl(dst, memref); // rol [dest],cl
+ }
+}
+
+
+//-------------------------------------------------
+// emit_ror_r64_p64 - ror operation to a 64-bit
+// register from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_ror_r64_p64(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else
+ emit_ror_r64_imm(dst, reg, param.immediate()); // ror reg,param
+ }
+ else
+ {
+ emit_mov_r64_p64(dst, REG_RCX, param); // mov rcx,param
+ emit_ror_r64_cl(dst, reg); // ror reg,cl
+ }
+}
+
+
+//-------------------------------------------------
+// emit_ror_m64_p64 - ror operation to a 64-bit
+// memory location from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_ror_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT64)param.immediate() == 0)
+ ;// skip
+ else
+ emit_ror_m64_imm(dst, memref, param.immediate()); // ror [dest],param
+ }
+ else
+ {
+ emit_mov_r64_p64(dst, REG_RCX, param); // mov rcx,param
+ emit_ror_m64_cl(dst, memref); // ror [dest],cl
+ }
+}
+
+
+//-------------------------------------------------
+// emit_rcl_r64_p64 - rcl operation to a 64-bit
+// register from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_rcl_r64_p64(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else
+ emit_rcl_r64_imm(dst, reg, param.immediate()); // rcl reg,param
+ }
+ else
+ {
+ emit_mov_r64_p64_keepflags(dst, REG_RCX, param); // mov rcx,param
+ emit_rcl_r64_cl(dst, reg); // rcl reg,cl
+ }
+}
+
+
+//-------------------------------------------------
+// emit_rcl_m64_p64 - rcl operation to a 64-bit
+// memory location from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_rcl_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT64)param.immediate() == 0)
+ ;// skip
+ else
+ emit_rcl_m64_imm(dst, memref, param.immediate()); // rcl [dest],param
+ }
+ else
+ {
+ emit_mov_r64_p64_keepflags(dst, REG_RCX, param); // mov rcx,param
+ emit_rcl_m64_cl(dst, memref); // rcl [dest],cl
+ }
+}
+
+
+//-------------------------------------------------
+// emit_rcr_r64_p64 - rcr operation to a 64-bit
+// register from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_rcr_r64_p64(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else
+ emit_rcr_r64_imm(dst, reg, param.immediate()); // rcr reg,param
+ }
+ else
+ {
+ emit_mov_r64_p64_keepflags(dst, REG_RCX, param); // mov rcx,param
+ emit_rcr_r64_cl(dst, reg); // rcr reg,cl
+ }
+}
+
+
+//-------------------------------------------------
+// emit_rcr_m64_p64 - rcr operation to a 64-bit
+// memory location from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_rcr_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT64)param.immediate() == 0)
+ ;// skip
+ else
+ emit_rcr_m64_imm(dst, memref, param.immediate()); // rcr [dest],param
+ }
+ else
+ {
+ emit_mov_r64_p64_keepflags(dst, REG_RCX, param); // mov rcx,param
+ emit_rcr_m64_cl(dst, memref); // rcr [dest],cl
+ }
+}
+
+
+
+/***************************************************************************
+ EMITTERS FOR FLOATING POINT OPERATIONS WITH PARAMETERS
+***************************************************************************/
+
+//-------------------------------------------------
+// emit_movss_r128_p32 - move a 32-bit parameter
+// into a register
+//-------------------------------------------------
+
+void drcbe_x64::emit_movss_r128_p32(x86code *&dst, UINT8 reg, const be_parameter &param)
+{
+ assert(!param.is_immediate());
+ if (param.is_memory())
+ emit_movss_r128_m32(dst, reg, MABS(param.memory())); // movss reg,[param]
+ else if (param.is_float_register())
+ {
+ if (reg != param.freg())
+ emit_movss_r128_r128(dst, reg, param.freg()); // movss reg,param
+ }
+}
+
+
+//-------------------------------------------------
+// emit_movss_p32_r128 - move a register into a
+// 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_movss_p32_r128(x86code *&dst, const be_parameter &param, UINT8 reg)
+{
+ assert(!param.is_immediate());
+ if (param.is_memory())
+ emit_movss_m32_r128(dst, MABS(param.memory()), reg); // movss [param],reg
+ else if (param.is_float_register())
+ {
+ if (reg != param.freg())
+ emit_movss_r128_r128(dst, param.freg(), reg); // movss param,reg
+ }
+}
+
+
+//-------------------------------------------------
+// emit_movsd_r128_p64 - move a 64-bit parameter
+// into a register
+//-------------------------------------------------
+
+void drcbe_x64::emit_movsd_r128_p64(x86code *&dst, UINT8 reg, const be_parameter &param)
+{
+ assert(!param.is_immediate());
+ if (param.is_memory())
+ emit_movsd_r128_m64(dst, reg, MABS(param.memory())); // movsd reg,[param]
+ else if (param.is_float_register())
+ {
+ if (reg != param.freg())
+ emit_movsd_r128_r128(dst, reg, param.freg()); // movsd reg,param
+ }
+}
+
+
+//-------------------------------------------------
+// emit_movsd_p64_r128 - move a register into a
+// 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x64::emit_movsd_p64_r128(x86code *&dst, const be_parameter &param, UINT8 reg)
+{
+ assert(!param.is_immediate());
+ if (param.is_memory())
+ emit_movsd_m64_r128(dst, MABS(param.memory()), reg); // movsd [param],reg
+ else if (param.is_float_register())
+ {
+ if (reg != param.freg())
+ emit_movsd_r128_r128(dst, param.freg(), reg); // movsd param,reg
+ }
+}
+
+
+
+/***************************************************************************
+ OUT-OF-BAND CODE FIXUP CALLBACKS
+***************************************************************************/
+
+//-------------------------------------------------
+// fixup_label - callback to fixup forward-
+// referenced labels
+//-------------------------------------------------
+
+void drcbe_x64::fixup_label(void *parameter, drccodeptr labelcodeptr)
+{
+ drccodeptr src = (drccodeptr)parameter;
+
+ // find the end of the instruction
+ if (src[0] == 0xe3)
+ {
+ src += 1 + 1;
+ src[-1] = labelcodeptr - src;
+ }
+ else if (src[0] == 0xe9)
+ {
+ src += 1 + 4;
+ ((UINT32 *)src)[-1] = labelcodeptr - src;
+ }
+ else if (src[0] == 0x0f && (src[1] & 0xf0) == 0x80)
+ {
+ src += 2 + 4;
+ ((UINT32 *)src)[-1] = labelcodeptr - src;
+ }
+ else
+ fatalerror("fixup_label called with invalid jmp source!");
+}
+
+
+//-------------------------------------------------
+// fixup_exception - callback to perform cleanup
+// and jump to an exception handler
+//-------------------------------------------------
+
+void drcbe_x64::fixup_exception(drccodeptr *codeptr, void *param1, void *param2)
+{
+ drccodeptr src = (drccodeptr)param1;
+ const instruction &inst = *(const instruction *)param2;
+
+ // normalize parameters
+ const parameter &handp = inst.param(0);
+ assert(handp.is_code_handle());
+ be_parameter exp(*this, inst.param(1), PTYPE_MRI);
+
+ // look up the handle target
+ drccodeptr *targetptr = handp.handle().codeptr_addr();
+
+ // first fixup the jump to get us here
+ drccodeptr dst = *codeptr;
+ ((UINT32 *)src)[-1] = dst - src;
+
+ // then store the exception parameter
+ emit_mov_m32_p32(dst, MABS(&m_state.exp), exp); // mov [exp],exp
+
+ // push the original return address on the stack
+ emit_lea_r64_m64(dst, REG_RAX, MABS(src)); // lea rax,[return]
+ emit_push_r64(dst, REG_RAX); // push rax
+ if (*targetptr != NULL)
+ emit_jmp(dst, *targetptr); // jmp *targetptr
+ else
+ emit_jmp_m64(dst, MABS(targetptr)); // jmp [targetptr]
+
+ *codeptr = dst;
+}
+
+
+
+//**************************************************************************
+// DEBUG HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// debug_log_hashjmp - callback to handle
+// logging of hashjmps
+//-------------------------------------------------
+
+void drcbe_x64::debug_log_hashjmp(offs_t pc, int mode)
+{
+ printf("mode=%d PC=%08X\n", mode, pc);
+}
+
+
+//-------------------------------------------------
+// debug_log_hashjmp - callback to handle
+// logging of hashjmps
+//-------------------------------------------------
+
+void drcbe_x64::debug_log_hashjmp_fail()
+{
+ printf(" (FAIL)\n");
+}
+
+
+
+/***************************************************************************
+ COMPILE-TIME OPCODES
+***************************************************************************/
+
+//-------------------------------------------------
+// op_handle - process a HANDLE opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_handle(x86code *&dst, const instruction &inst)
+{
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+ assert(inst.numparams() == 1);
+ assert(inst.param(0).is_code_handle());
+
+ // emit a jump around the stack adjust in case code falls through here
+ emit_link skip;
+ emit_jmp_short_link(dst, skip); // jmp skip
+
+ // register the current pointer for the handle
+ inst.param(0).handle().set_codeptr(dst);
+
+ // by default, the handle points to prolog code that moves the stack pointer
+ emit_lea_r64_m64(dst, REG_RSP, MBD(REG_RSP, -40)); // lea rsp,[rsp-40]
+ resolve_link(dst, skip); // skip:
+}
+
+
+//-------------------------------------------------
+// op_hash - process a HASH opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_hash(x86code *&dst, const instruction &inst)
+{
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+ assert(inst.numparams() == 2);
+ assert(inst.param(0).is_immediate());
+ assert(inst.param(1).is_immediate());
+
+ // register the current pointer for the mode/PC
+ m_hash.set_codeptr(inst.param(0).immediate(), inst.param(1).immediate(), dst);
+}
+
+
+//-------------------------------------------------
+// op_label - process a LABEL opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_label(x86code *&dst, const instruction &inst)
+{
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+ assert(inst.numparams() == 1);
+ assert(inst.param(0).is_code_label());
+
+ // register the current pointer for the label
+ m_labels.set_codeptr(inst.param(0).label(), dst);
+}
+
+
+//-------------------------------------------------
+// op_comment - process a COMMENT opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_comment(x86code *&dst, const instruction &inst)
+{
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+ assert(inst.numparams() == 1);
+ assert(inst.param(0).is_string());
+
+ // do nothing
+}
+
+
+//-------------------------------------------------
+// op_mapvar - process a MAPVAR opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_mapvar(x86code *&dst, const instruction &inst)
+{
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+ assert(inst.numparams() == 2);
+ assert(inst.param(0).is_mapvar());
+ assert(inst.param(1).is_immediate());
+
+ // set the value of the specified mapvar
+ m_map.set_value(dst, inst.param(0).mapvar(), inst.param(1).immediate());
+}
+
+
+
+/***************************************************************************
+ CONTROL FLOW OPCODES
+***************************************************************************/
+
+//-------------------------------------------------
+// op_nop - process a NOP opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_nop(x86code *&dst, const instruction &inst)
+{
+ // nothing
+}
+
+
+//-------------------------------------------------
+// op_debug - process a DEBUG opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_debug(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ if ((m_device.machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ {
+ // normalize parameters
+ be_parameter pcp(*this, inst.param(0), PTYPE_MRI);
+
+ // test and branch
+ emit_mov_r64_imm(dst, REG_RAX, (FPTR)&m_device.machine().debug_flags); // mov rax,&debug_flags
+ emit_test_m32_imm(dst, MBD(REG_RAX, 0), DEBUG_FLAG_CALL_HOOK); // test [debug_flags],DEBUG_FLAG_CALL_HOOK
+ emit_link skip = { 0 };
+ emit_jcc_short_link(dst, x64emit::COND_Z, skip); // jz skip
+
+ // push the parameter
+ emit_mov_r64_imm(dst, REG_PARAM1, (FPTR)&m_device); // mov param1,device
+ emit_mov_r32_p32(dst, REG_PARAM2, pcp); // mov param2,pcp
+ emit_smart_call_m64(dst, &m_near.debug_cpu_instruction_hook); // call debug_cpu_instruction_hook
+
+ resolve_link(dst, skip); // skip:
+ }
+}
+
+
+//-------------------------------------------------
+// op_exit - process an EXIT opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_exit(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4);
+ assert_any_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter retp(*this, inst.param(0), PTYPE_MRI);
+
+ // load the parameter into EAX
+ emit_mov_r32_p32(dst, REG_EAX, retp); // mov eax,retp
+ if (inst.condition() == uml::COND_ALWAYS)
+ emit_jmp(dst, m_exit); // jmp exit
+ else
+ emit_jcc(dst, X86_CONDITION(inst.condition()), m_exit); // jcc exit
+}
+
+
+//-------------------------------------------------
+// op_hashjmp - process a HASHJMP opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_hashjmp(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter modep(*this, inst.param(0), PTYPE_MRI);
+ be_parameter pcp(*this, inst.param(1), PTYPE_MRI);
+ const parameter &exp = inst.param(2);
+ assert(exp.is_code_handle());
+
+ if (LOG_HASHJMPS)
+ {
+ emit_mov_r32_p32(dst, REG_PARAM1, pcp);
+ emit_mov_r32_p32(dst, REG_PARAM2, modep);
+ emit_smart_call_m64(dst, &m_near.debug_log_hashjmp);
+ }
+
+ // load the stack base one word early so we end up at the right spot after our call below
+ emit_mov_r64_m64(dst, REG_RSP, MABS(&m_near.hashstacksave)); // mov rsp,[hashstacksave]
+
+ // fixed mode cases
+ if (modep.is_immediate() && m_hash.is_mode_populated(modep.immediate()))
+ {
+ // a straight immediate jump is direct, though we need the PC in EAX in case of failure
+ if (pcp.is_immediate())
+ {
+ UINT32 l1val = (pcp.immediate() >> m_hash.l1shift()) & m_hash.l1mask();
+ UINT32 l2val = (pcp.immediate() >> m_hash.l2shift()) & m_hash.l2mask();
+ emit_call_m64(dst, MABS(&m_hash.base()[modep.immediate()][l1val][l2val]));
+ // call hash[modep][l1val][l2val]
+ }
+
+ // a fixed mode but variable PC
+ else
+ {
+ emit_mov_r32_p32(dst, REG_EAX, pcp); // mov eax,pcp
+ emit_mov_r32_r32(dst, REG_EDX, REG_EAX); // mov edx,eax
+ emit_shr_r32_imm(dst, REG_EDX, m_hash.l1shift()); // shr edx,l1shift
+ emit_and_r32_imm(dst, REG_EAX, m_hash.l2mask() << m_hash.l2shift()); // and eax,l2mask << l2shift
+ emit_mov_r64_m64(dst, REG_RDX, MBISD(REG_RBP, REG_RDX, 8, offset_from_rbp(&m_hash.base()[modep.immediate()][0])));
+ // mov rdx,hash[modep+edx*8]
+ emit_call_m64(dst, MBISD(REG_RDX, REG_RAX, 8 >> m_hash.l2shift(), 0)); // call [rdx+rax*shift]
+ }
+ }
+ else
+ {
+ // variable mode
+ int modereg = modep.select_register(REG_ECX);
+ emit_mov_r32_p32(dst, modereg, modep); // mov modereg,modep
+ emit_mov_r64_m64(dst, REG_RCX, MBISD(REG_RBP, modereg, 8, offset_from_rbp(m_hash.base())));
+ // mov rcx,hash[modereg*8]
+
+ // fixed PC
+ if (pcp.is_immediate())
+ {
+ UINT32 l1val = (pcp.immediate() >> m_hash.l1shift()) & m_hash.l1mask();
+ UINT32 l2val = (pcp.immediate() >> m_hash.l2shift()) & m_hash.l2mask();
+ emit_mov_r64_m64(dst, REG_RDX, MBD(REG_RCX, l1val*8)); // mov rdx,[rcx+l1val*8]
+ emit_call_m64(dst, MBD(REG_RDX, l2val*8)); // call [l2val*8]
+ }
+
+ // variable PC
+ else
+ {
+ emit_mov_r32_p32(dst, REG_EAX, pcp); // mov eax,pcp
+ emit_mov_r32_r32(dst, REG_EDX, REG_EAX); // mov edx,eax
+ emit_shr_r32_imm(dst, REG_EDX, m_hash.l1shift()); // shr edx,l1shift
+ emit_mov_r64_m64(dst, REG_RDX, MBISD(REG_RCX, REG_RDX, 8, 0)); // mov rdx,[rcx+rdx*8]
+ emit_and_r32_imm(dst, REG_EAX, m_hash.l2mask() << m_hash.l2shift()); // and eax,l2mask << l2shift
+ emit_call_m64(dst, MBISD(REG_RDX, REG_RAX, 8 >> m_hash.l2shift(), 0)); // call [rdx+rax*shift]
+ }
+ }
+
+ // in all cases, if there is no code, we return here to generate the exception
+ if (LOG_HASHJMPS)
+ emit_smart_call_m64(dst, &m_near.debug_log_hashjmp_fail);
+
+ emit_mov_m32_p32(dst, MABS(&m_state.exp), pcp); // mov [exp],param
+ emit_sub_r64_imm(dst, REG_RSP, 8); // sub rsp,8
+ emit_call_m64(dst, MABS(exp.handle().codeptr_addr())); // call [exp]
+}
+
+
+//-------------------------------------------------
+// op_jmp - process a JMP opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_jmp(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4);
+ assert_any_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ const parameter &labelp = inst.param(0);
+ assert(labelp.is_code_label());
+
+ // look up the jump target and jump there
+ x86code *jmptarget = (x86code *)m_labels.get_codeptr(labelp.label(), m_fixup_label, dst);
+ if (jmptarget == NULL)
+ jmptarget = dst + 0x7ffffff0;
+ if (inst.condition() == uml::COND_ALWAYS)
+ emit_jmp(dst, jmptarget); // jmp target
+ else
+ emit_jcc(dst, X86_CONDITION(inst.condition()), jmptarget); // jcc target
+
+}
+
+
+//-------------------------------------------------
+// op_exh - process an EXH opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_exh(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4);
+ assert_any_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ const parameter &handp = inst.param(0);
+ assert(handp.is_code_handle());
+ be_parameter exp(*this, inst.param(1), PTYPE_MRI);
+
+ // look up the handle target
+ drccodeptr *targetptr = handp.handle().codeptr_addr();
+
+ // perform the exception processing inline if unconditional
+ if (inst.condition() == uml::COND_ALWAYS)
+ {
+ emit_mov_m32_p32(dst, MABS(&m_state.exp), exp); // mov [exp],exp
+ if (*targetptr != NULL)
+ emit_call(dst, *targetptr); // call *targetptr
+ else
+ emit_call_m64(dst, MABS(targetptr)); // call [targetptr]
+ }
+
+ // otherwise, jump to an out-of-band handler
+ else
+ {
+ emit_jcc(dst, X86_CONDITION(inst.condition()), dst + 0x7ffffff0); // jcc exception
+ m_cache.request_oob_codegen(m_fixup_exception, dst, &const_cast<instruction &>(inst));
+ }
+}
+
+
+//-------------------------------------------------
+// op_callh - process a CALLH opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_callh(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4);
+ assert_any_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ const parameter &handp = inst.param(0);
+ assert(handp.is_code_handle());
+
+ // look up the handle target
+ drccodeptr *targetptr = handp.handle().codeptr_addr();
+
+ // skip if conditional
+ emit_link skip = { 0 };
+ if (inst.condition() != uml::COND_ALWAYS)
+ emit_jcc_short_link(dst, X86_NOT_CONDITION(inst.condition()), skip); // jcc skip
+
+ // jump through the handle; directly if a normal jump
+ if (*targetptr != NULL)
+ emit_call(dst, *targetptr); // call *targetptr
+ else
+ emit_call_m64(dst, MABS(targetptr)); // call [targetptr]
+
+ // resolve the conditional link
+ if (inst.condition() != uml::COND_ALWAYS)
+ resolve_link(dst, skip); // skip:
+}
+
+
+//-------------------------------------------------
+// op_ret - process a RET opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_ret(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4);
+ assert_any_condition(inst);
+ assert_no_flags(inst);
+ assert(inst.numparams() == 0);
+
+ // skip if conditional
+ emit_link skip = { 0 };
+ if (inst.condition() != uml::COND_ALWAYS)
+ emit_jcc_short_link(dst, X86_NOT_CONDITION(inst.condition()), skip); // jcc skip
+
+ // return
+ emit_lea_r64_m64(dst, REG_RSP, MBD(REG_RSP, 40)); // lea rsp,[rsp+40]
+ emit_ret(dst); // ret
+
+ // resolve the conditional link
+ if (inst.condition() != uml::COND_ALWAYS)
+ resolve_link(dst, skip); // skip:
+}
+
+
+//-------------------------------------------------
+// op_callc - process a CALLC opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_callc(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4);
+ assert_any_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ const parameter &funcp = inst.param(0);
+ assert(funcp.is_c_function());
+ be_parameter paramp(*this, inst.param(1), PTYPE_M);
+
+ // skip if conditional
+ emit_link skip = { 0 };
+ if (inst.condition() != uml::COND_ALWAYS)
+ emit_jcc_short_link(dst, X86_NOT_CONDITION(inst.condition()), skip); // jcc skip
+
+ // perform the call
+ emit_mov_r64_imm(dst, REG_PARAM1, (FPTR)paramp.memory()); // mov param1,paramp
+ emit_smart_call_r64(dst, (x86code *)(FPTR)funcp.cfunc(), REG_RAX); // call funcp
+
+ // resolve the conditional link
+ if (inst.condition() != uml::COND_ALWAYS)
+ resolve_link(dst, skip); // skip:
+}
+
+
+//-------------------------------------------------
+// op_recover - process a RECOVER opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_recover(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+
+ // call the recovery code
+ emit_mov_r64_m64(dst, REG_RAX, MABS(&m_near.stacksave)); // mov rax,stacksave
+ emit_mov_r64_m64(dst, REG_RAX, MBD(REG_RAX, -8)); // mov rax,[rax-4]
+ emit_mov_r64_imm(dst, REG_PARAM1, (FPTR)&m_map); // mov param1,m_map
+ emit_lea_r64_m64(dst, REG_PARAM2, MBD(REG_RAX, -1)); // lea param2,[rax-1]
+ emit_mov_r64_imm(dst, REG_PARAM3, inst.param(1).mapvar()); // mov param3,param[1].value
+ emit_smart_call_m64(dst, &m_near.drcmap_get_value); // call drcmap_get_value
+ emit_mov_p32_r32(dst, dstp, REG_EAX); // mov dstp,eax
+
+}
+
+
+
+/***************************************************************************
+ INTERNAL REGISTER OPCODES
+***************************************************************************/
+
+//-------------------------------------------------
+// op_setfmod - process a SETFMOD opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_setfmod(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter srcp(*this, inst.param(0), PTYPE_MRI);
+
+ // immediate case
+ if (srcp.is_immediate())
+ {
+ int value = srcp.immediate() & 3;
+ emit_mov_m8_imm(dst, MABS(&m_state.fmod), value); // mov [fmod],srcp
+ emit_ldmxcsr_m32(dst, MABS(&m_near.ssecontrol[value])); // ldmxcsr fp_control[srcp]
+ }
+
+ // register/memory case
+ else
+ {
+ emit_mov_r32_p32(dst, REG_EAX, srcp); // mov eax,srcp
+ emit_and_r32_imm(dst, REG_EAX, 3); // and eax,3
+ emit_mov_m8_r8(dst, MABS(&m_state.fmod), REG_AL); // mov [fmod],al
+ emit_ldmxcsr_m32(dst, MBISD(REG_RBP, REG_RAX, 4, offset_from_rbp(&m_near.ssecontrol[0])));
+ // ldmxcsr fp_control[eax]
+ }
+}
+
+
+//-------------------------------------------------
+// op_getfmod - process a GETFMOD opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_getfmod(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+
+ // fetch the current mode and store to the destination
+ if (dstp.is_int_register())
+ emit_movzx_r32_m8(dst, dstp.ireg(), MABS(&m_state.fmod)); // movzx reg,[fmod]
+ else
+ {
+ emit_movzx_r32_m8(dst, REG_EAX, MABS(&m_state.fmod)); // movzx eax,[fmod]
+ emit_mov_m32_r32(dst, MABS(dstp.memory()), REG_EAX); // mov [dstp],eax
+ }
+}
+
+
+//-------------------------------------------------
+// op_getexp - process a GETEXP opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_getexp(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+
+ // fetch the exception parameter and store to the destination
+ if (dstp.is_int_register())
+ emit_mov_r32_m32(dst, dstp.ireg(), MABS(&m_state.exp)); // mov reg,[exp]
+ else
+ {
+ emit_mov_r32_m32(dst, REG_EAX, MABS(&m_state.exp)); // mov eax,[exp]
+ emit_mov_m32_r32(dst, MABS(dstp.memory()), REG_EAX); // mov [dstp],eax
+ }
+}
+
+
+//-------------------------------------------------
+// op_getflgs - process a GETFLGS opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_getflgs(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter maskp(*this, inst.param(1), PTYPE_I);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX);
+
+ // compute mask for flags
+ UINT32 flagmask = 0;
+ if (maskp.immediate() & FLAG_C) flagmask |= 0x001;
+ if (maskp.immediate() & FLAG_V) flagmask |= 0x800;
+ if (maskp.immediate() & FLAG_Z) flagmask |= 0x040;
+ if (maskp.immediate() & FLAG_S) flagmask |= 0x080;
+ if (maskp.immediate() & FLAG_U) flagmask |= 0x004;
+
+ switch (maskp.immediate())
+ {
+ // single flags only
+ case FLAG_C:
+ emit_setcc_r8(dst, x64emit::COND_C, REG_AL); // setc al
+ emit_movzx_r32_r8(dst, dstreg, REG_AL); // movzx dstreg,al
+ break;
+
+ case FLAG_V:
+ emit_setcc_r8(dst, x64emit::COND_O, REG_AL); // seto al
+ emit_movzx_r32_r8(dst, dstreg, REG_AL); // movzx dstreg,al
+ emit_shl_r32_imm(dst, dstreg, 1); // shl dstreg,1
+ break;
+
+ case FLAG_Z:
+ emit_setcc_r8(dst, x64emit::COND_Z, REG_AL); // setz al
+ emit_movzx_r32_r8(dst, dstreg, REG_AL); // movzx dstreg,al
+ emit_shl_r32_imm(dst, dstreg, 2); // shl dstreg,2
+ break;
+
+ case FLAG_S:
+ emit_setcc_r8(dst, x64emit::COND_S, REG_AL); // sets al
+ emit_movzx_r32_r8(dst, dstreg, REG_AL); // movzx dstreg,al
+ emit_shl_r32_imm(dst, dstreg, 3); // shl dstreg,3
+ break;
+
+ case FLAG_U:
+ emit_setcc_r8(dst, x64emit::COND_P, REG_AL); // setp al
+ emit_movzx_r32_r8(dst, dstreg, REG_AL); // movzx dstreg,al
+ emit_shl_r32_imm(dst, dstreg, 4); // shl dstreg,4
+ break;
+
+ // carry plus another flag
+ case FLAG_C | FLAG_V:
+ emit_setcc_r8(dst, x64emit::COND_C, REG_AL); // setc al
+ emit_setcc_r8(dst, x64emit::COND_O, REG_CL); // seto cl
+ emit_movzx_r32_r8(dst, REG_EAX, REG_AL); // movzx eax,al
+ emit_movzx_r32_r8(dst, REG_ECX, REG_CL); // movzx ecx,al
+ emit_lea_r32_m32(dst, dstreg, MBISD(REG_EAX, REG_ECX, 2, 0)); // lea dstreg,[eax+ecx*2]
+ break;
+
+ case FLAG_C | FLAG_Z:
+ emit_setcc_r8(dst, x64emit::COND_C, REG_AL); // setc al
+ emit_setcc_r8(dst, x64emit::COND_Z, REG_CL); // setz cl
+ emit_movzx_r32_r8(dst, REG_EAX, REG_AL); // movzx eax,al
+ emit_movzx_r32_r8(dst, REG_ECX, REG_CL); // movzx ecx,al
+ emit_lea_r32_m32(dst, dstreg, MBISD(REG_EAX, REG_ECX, 4, 0)); // lea dstreg,[eax+ecx*4]
+ break;
+
+ case FLAG_C | FLAG_S:
+ emit_setcc_r8(dst, x64emit::COND_C, REG_AL); // setc al
+ emit_setcc_r8(dst, x64emit::COND_S, REG_CL); // sets cl
+ emit_movzx_r32_r8(dst, REG_EAX, REG_AL); // movzx eax,al
+ emit_movzx_r32_r8(dst, REG_ECX, REG_CL); // movzx ecx,al
+ emit_lea_r32_m32(dst, dstreg, MBISD(REG_EAX, REG_ECX, 8, 0)); // lea dstreg,[eax+ecx*8]
+ break;
+
+ // overflow plus another flag
+ case FLAG_V | FLAG_Z:
+ emit_setcc_r8(dst, x64emit::COND_O, REG_AL); // seto al
+ emit_setcc_r8(dst, x64emit::COND_Z, REG_CL); // setz cl
+ emit_movzx_r32_r8(dst, REG_EAX, REG_AL); // movzx eax,al
+ emit_movzx_r32_r8(dst, REG_ECX, REG_CL); // movzx ecx,al
+ emit_lea_r32_m32(dst, dstreg, MBISD(REG_EAX, REG_ECX, 2, 0)); // lea dstreg,[eax+ecx*2]
+ emit_shl_r32_imm(dst, dstreg, 1); // shl dstreg,1
+ break;
+
+ case FLAG_V | FLAG_S:
+ emit_setcc_r8(dst, x64emit::COND_O, REG_AL); // seto al
+ emit_setcc_r8(dst, x64emit::COND_S, REG_CL); // sets cl
+ emit_movzx_r32_r8(dst, REG_EAX, REG_AL); // movzx eax,al
+ emit_movzx_r32_r8(dst, REG_ECX, REG_CL); // movzx ecx,al
+ emit_lea_r32_m32(dst, dstreg, MBISD(REG_EAX, REG_ECX, 4, 0)); // lea dstreg,[eax+ecx*4]
+ emit_shl_r32_imm(dst, dstreg, 1); // shl dstreg,1
+ break;
+
+ // zero plus another flag
+ case FLAG_Z | FLAG_S:
+ emit_setcc_r8(dst, x64emit::COND_Z, REG_AL); // setz al
+ emit_setcc_r8(dst, x64emit::COND_S, REG_CL); // sets cl
+ emit_movzx_r32_r8(dst, REG_EAX, REG_AL); // movzx eax,al
+ emit_movzx_r32_r8(dst, REG_ECX, REG_CL); // movzx ecx,al
+ emit_lea_r32_m32(dst, dstreg, MBISD(REG_EAX, REG_ECX, 2, 0)); // lea dstreg,[eax+ecx*2]
+ emit_shl_r32_imm(dst, dstreg, 2); // shl dstreg,2
+ break;
+
+ // default cases
+ default:
+ emit_pushf(dst); // pushf
+ emit_pop_r64(dst, REG_EAX); // pop eax
+ emit_and_r32_imm(dst, REG_EAX, flagmask); // and eax,flagmask
+ emit_movzx_r32_m8(dst, dstreg, MBISD(REG_RBP, REG_RAX, 1, offset_from_rbp(&m_near.flagsmap[0])));
+ // movzx dstreg,[flags_map]
+ break;
+ }
+
+ // 32-bit form
+ if (inst.size() == 4)
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg
+}
+
+
+//-------------------------------------------------
+// op_save - process a SAVE opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_save(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_M);
+
+ // copy live state to the destination
+ emit_mov_r64_imm(dst, REG_RCX, (FPTR)dstp.memory()); // mov rcx,dstp
+
+ // copy flags
+ emit_pushf(dst); // pushf
+ emit_pop_r64(dst, REG_RAX); // pop rax
+ emit_and_r32_imm(dst, REG_EAX, 0x8c5); // and eax,0x8c5
+ emit_mov_r8_m8(dst, REG_AL, MBISD(REG_RBP, REG_RAX, 1, offset_from_rbp(&m_near.flagsmap[0])));
+ // mov al,[flags_map]
+ emit_mov_m8_r8(dst, MBD(REG_RCX, offsetof(drcuml_machine_state, flags)), REG_AL); // mov state->flags,al
+
+ // copy fmod and exp
+ emit_mov_r8_m8(dst, REG_AL, MABS(&m_state.fmod)); // mov al,[fmod]
+ emit_mov_m8_r8(dst, MBD(REG_RCX, offsetof(drcuml_machine_state, fmod)), REG_AL); // mov state->fmod,al
+ emit_mov_r32_m32(dst, REG_EAX, MABS(&m_state.exp)); // mov eax,[exp]
+ emit_mov_m32_r32(dst, MBD(REG_RCX, offsetof(drcuml_machine_state, exp)), REG_EAX); // mov state->exp,eax
+
+ // copy integer registers
+ int regoffs = offsetof(drcuml_machine_state, r);
+ for (int regnum = 0; regnum < ARRAY_LENGTH(m_state.r); regnum++)
+ {
+ if (int_register_map[regnum] != 0)
+ emit_mov_m64_r64(dst, MBD(REG_RCX, regoffs + 8 * regnum), int_register_map[regnum]);
+ else
+ {
+ emit_mov_r64_m64(dst, REG_RAX, MABS(&m_state.r[regnum].d));
+ emit_mov_m64_r64(dst, MBD(REG_RCX, regoffs + 8 * regnum), REG_RAX);
+ }
+ }
+
+ // copy FP registers
+ regoffs = offsetof(drcuml_machine_state, f);
+ for (int regnum = 0; regnum < ARRAY_LENGTH(m_state.f); regnum++)
+ {
+ if (float_register_map[regnum] != 0)
+ emit_movsd_m64_r128(dst, MBD(REG_RCX, regoffs + 8 * regnum), float_register_map[regnum]);
+ else
+ {
+ emit_mov_r64_m64(dst, REG_RAX, MABS(&m_state.f[regnum].d));
+ emit_mov_m64_r64(dst, MBD(REG_RCX, regoffs + 8 * regnum), REG_RAX);
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// op_restore - process a RESTORE opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_restore(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4);
+ assert_no_condition(inst);
+
+ // normalize parameters
+ be_parameter srcp(*this, inst.param(0), PTYPE_M);
+
+ // copy live state from the destination
+ emit_mov_r64_imm(dst, REG_ECX, (FPTR)srcp.memory()); // mov rcx,dstp
+
+ // copy integer registers
+ int regoffs = offsetof(drcuml_machine_state, r);
+ for (int regnum = 0; regnum < ARRAY_LENGTH(m_state.r); regnum++)
+ {
+ if (int_register_map[regnum] != 0)
+ emit_mov_r64_m64(dst, int_register_map[regnum], MBD(REG_RCX, regoffs + 8 * regnum));
+ else
+ {
+ emit_mov_r64_m64(dst, REG_RAX, MBD(REG_RCX, regoffs + 8 * regnum));
+ emit_mov_m64_r64(dst, MABS(&m_state.r[regnum].d), REG_RAX);
+ }
+ }
+
+ // copy FP registers
+ regoffs = offsetof(drcuml_machine_state, f);
+ for (int regnum = 0; regnum < ARRAY_LENGTH(m_state.f); regnum++)
+ {
+ if (float_register_map[regnum] != 0)
+ emit_movsd_r128_m64(dst, float_register_map[regnum], MBD(REG_RCX, regoffs + 8 * regnum));
+ else
+ {
+ emit_mov_r64_m64(dst, REG_RAX, MBD(REG_RCX, regoffs + 8 * regnum));
+ emit_mov_m64_r64(dst, MABS(&m_state.f[regnum].d), REG_RAX);
+ }
+ }
+
+ // copy fmod and exp
+ emit_movzx_r32_m8(dst, REG_EAX, MBD(REG_RCX, offsetof(drcuml_machine_state, fmod)));// movzx eax,state->fmod
+ emit_and_r32_imm(dst, REG_EAX, 3); // and eax,3
+ emit_mov_m8_r8(dst, MABS(&m_state.fmod), REG_AL); // mov [fmod],al
+ emit_ldmxcsr_m32(dst, MBISD(REG_RBP, REG_RAX, 4, offset_from_rbp(&m_near.ssecontrol[0])));
+ emit_mov_r32_m32(dst, REG_EAX, MBD(REG_RCX, offsetof(drcuml_machine_state, exp))); // mov eax,state->exp
+ emit_mov_m32_r32(dst, MABS(&m_state.exp), REG_EAX); // mov [exp],eax
+
+ // copy flags
+ emit_movzx_r32_m8(dst, REG_EAX, MBD(REG_RCX, offsetof(drcuml_machine_state, flags)));// movzx eax,state->flags
+ emit_push_m64(dst, MBISD(REG_RBP, REG_RAX, 8, offset_from_rbp(&m_near.flagsunmap[0])));
+ // push flags_unmap[eax*8]
+ emit_popf(dst); // popf
+}
+
+
+
+/***************************************************************************
+ INTEGER OPERATIONS
+***************************************************************************/
+
+//-------------------------------------------------
+// op_load - process a LOAD opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_load(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter basep(*this, inst.param(1), PTYPE_M);
+ be_parameter indp(*this, inst.param(2), PTYPE_MRI);
+ const parameter &scalesizep = inst.param(3);
+ assert(scalesizep.is_size_scale());
+ int scale = 1 << scalesizep.scale();
+ int size = scalesizep.size();
+
+ // determine the pointer base
+ INT32 baseoffs;
+ int basereg = get_base_register_and_offset(dst, basep.memory(), REG_RDX, baseoffs);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX);
+
+ // immediate index
+ if (indp.is_immediate())
+ {
+ if (size == SIZE_BYTE)
+ emit_movzx_r32_m8(dst, dstreg, MBD(basereg, baseoffs + scale*indp.immediate()));// movzx dstreg,[basep + scale*indp]
+ else if (size == SIZE_WORD)
+ emit_movzx_r32_m16(dst, dstreg, MBD(basereg, baseoffs + scale*indp.immediate()));// movzx dstreg,[basep + scale*indp]
+ else if (size == SIZE_DWORD)
+ emit_mov_r32_m32(dst, dstreg, MBD(basereg, baseoffs + scale*indp.immediate())); // mov dstreg,[basep + scale*indp]
+ else if (size == SIZE_QWORD)
+ emit_mov_r64_m64(dst, dstreg, MBD(basereg, baseoffs + scale*indp.immediate())); // mov dstreg,[basep + scale*indp]
+ }
+
+ // other index
+ else
+ {
+ int indreg = indp.select_register(REG_ECX);
+ emit_movsx_r64_p32(dst, indreg, indp);
+ if (size == SIZE_BYTE)
+ emit_movzx_r32_m8(dst, dstreg, MBISD(basereg, indreg, scale, baseoffs)); // movzx dstreg,[basep + scale*indp]
+ else if (size == SIZE_WORD)
+ emit_movzx_r32_m16(dst, dstreg, MBISD(basereg, indreg, scale, baseoffs)); // movzx dstreg,[basep + scale*indp]
+ else if (size == SIZE_DWORD)
+ emit_mov_r32_m32(dst, dstreg, MBISD(basereg, indreg, scale, baseoffs)); // mov dstreg,[basep + scale*indp]
+ else if (size == SIZE_QWORD)
+ emit_mov_r64_m64(dst, dstreg, MBISD(basereg, indreg, scale, baseoffs)); // mov dstreg,[basep + scale*indp]
+ }
+
+ // store result
+ if (inst.size() == 4)
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ else
+ emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg
+
+}
+
+
+//-------------------------------------------------
+// op_loads - process a LOADS opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_loads(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter basep(*this, inst.param(1), PTYPE_M);
+ be_parameter indp(*this, inst.param(2), PTYPE_MRI);
+ const parameter &scalesizep = inst.param(3);
+ assert(scalesizep.is_size_scale());
+ int scale = 1 << scalesizep.scale();
+ int size = scalesizep.size();
+
+ // determine the pointer base
+ INT32 baseoffs;
+ int basereg = get_base_register_and_offset(dst, basep.memory(), REG_RDX, baseoffs);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX);
+
+ // immediate index
+ if (indp.is_immediate())
+ {
+ if (inst.size() == 4)
+ {
+ if (size == SIZE_BYTE)
+ emit_movsx_r32_m8(dst, dstreg, MBD(basereg, baseoffs + scale*indp.immediate()));// movsx dstreg,[basep + scale*indp]
+ else if (size == SIZE_WORD)
+ emit_movsx_r32_m16(dst, dstreg, MBD(basereg, baseoffs + scale*indp.immediate()));// movsx dstreg,[basep + scale*indp]
+ else if (size == SIZE_DWORD)
+ emit_mov_r32_m32(dst, dstreg, MBD(basereg, baseoffs + scale*indp.immediate())); // mov dstreg,[basep + scale*indp]
+ }
+ else if (inst.size() == 8)
+ {
+ if (size == SIZE_BYTE)
+ emit_movsx_r64_m8(dst, dstreg, MBD(basereg, baseoffs + scale*indp.immediate()));// movzx dstreg,[basep + scale*indp]
+ else if (size == SIZE_WORD)
+ emit_movsx_r64_m16(dst, dstreg, MBD(basereg, baseoffs + scale*indp.immediate()));// movzx dstreg,[basep + scale*indp]
+ else if (size == SIZE_DWORD)
+ emit_movsxd_r64_m32(dst, dstreg, MBD(basereg, baseoffs + scale*indp.immediate()));// movsxd dstreg,[basep + scale*indp]
+ else if (size == SIZE_QWORD)
+ emit_mov_r64_m64(dst, dstreg, MBD(basereg, baseoffs + scale*indp.immediate())); // mov dstreg,[basep + scale*indp]
+ }
+ }
+
+ // other index
+ else
+ {
+ int indreg = indp.select_register(REG_ECX);
+ emit_movsx_r64_p32(dst, indreg, indp);
+ if (inst.size() == 4)
+ {
+ if (size == SIZE_BYTE)
+ emit_movsx_r32_m8(dst, dstreg, MBISD(basereg, indreg, scale, baseoffs));// movsx dstreg,[basep + scale*indp]
+ else if (size == SIZE_WORD)
+ emit_movsx_r32_m16(dst, dstreg, MBISD(basereg, indreg, scale, baseoffs));// movsx dstreg,[basep + scale*indp]
+ else if (size == SIZE_DWORD)
+ emit_mov_r32_m32(dst, dstreg, MBISD(basereg, indreg, scale, baseoffs)); // mov dstreg,[basep + scale*indp]
+ }
+ else if (inst.size() == 8)
+ {
+ if (size == SIZE_BYTE)
+ emit_movsx_r64_m8(dst, dstreg, MBISD(basereg, indreg, scale, baseoffs));// movsx dstreg,[basep + scale*indp]
+ else if (size == SIZE_WORD)
+ emit_movsx_r64_m16(dst, dstreg, MBISD(basereg, indreg, scale, baseoffs));// movsx dstreg,[basep + scale*indp]
+ else if (size == SIZE_DWORD)
+ emit_movsxd_r64_m32(dst, dstreg, MBISD(basereg, indreg, scale, baseoffs));// movsxd dstreg,[basep + scale*indp]
+ else if (size == SIZE_QWORD)
+ emit_mov_r64_m64(dst, dstreg, MBISD(basereg, indreg, scale, baseoffs)); // mov dstreg,[basep + scale*indp]
+ }
+ }
+
+ // store result
+ if (inst.size() == 4)
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ else
+ emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg
+
+}
+
+
+//-------------------------------------------------
+// op_store - process a STORE opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_store(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter basep(*this, inst.param(0), PTYPE_M);
+ be_parameter indp(*this, inst.param(1), PTYPE_MRI);
+ be_parameter srcp(*this, inst.param(2), PTYPE_MRI);
+ const parameter &scalesizep = inst.param(3);
+ int scale = 1 << (scalesizep.scale());
+ int size = scalesizep.size();
+
+ // determine the pointer base
+ INT32 baseoffs;
+ int basereg = get_base_register_and_offset(dst, basep.memory(), REG_RDX, baseoffs);
+
+ // pick a source register for the general case
+ int srcreg = srcp.select_register(REG_EAX);
+
+ // degenerate case: constant index
+ if (indp.is_immediate())
+ {
+ // immediate source
+ if (srcp.is_immediate())
+ {
+ if (size == SIZE_BYTE)
+ emit_mov_m8_imm(dst, MBD(basereg, baseoffs + scale*indp.immediate()), srcp.immediate());// mov [basep + scale*indp],srcp
+ else if (size == SIZE_WORD)
+ emit_mov_m16_imm(dst, MBD(basereg, baseoffs + scale*indp.immediate()), srcp.immediate());// mov [basep + scale*indp],srcp
+ else if (size == SIZE_DWORD)
+ emit_mov_m32_imm(dst, MBD(basereg, baseoffs + scale*indp.immediate()), srcp.immediate());// mov [basep + scale*indp],srcp
+ else if (size == SIZE_QWORD)
+ {
+ if (short_immediate(srcp.immediate()))
+ emit_mov_m64_imm(dst, MBD(basereg, baseoffs + scale*indp.immediate()), srcp.immediate());// mov [basep + scale*indp],srcp
+ else
+ {
+ emit_mov_m32_imm(dst, MBD(basereg, baseoffs + scale*indp.immediate()), srcp.immediate());// mov [basep + scale*indp],srcp
+ emit_mov_m32_imm(dst, MBD(basereg, baseoffs + scale*indp.immediate() + 4), srcp.immediate() >> 32);
+ // mov [basep + scale*indp + 4],srcp >> 32
+ }
+ }
+ }
+
+ // variable source
+ else
+ {
+ if (size != SIZE_QWORD)
+ emit_mov_r32_p32(dst, srcreg, srcp); // mov srcreg,srcp
+ else
+ emit_mov_r64_p64(dst, srcreg, srcp); // mov srcreg,srcp
+ if (size == SIZE_BYTE)
+ emit_mov_m8_r8(dst, MBD(basereg, baseoffs + scale*indp.immediate()), srcreg); // mov [basep + scale*indp],srcreg
+ else if (size == SIZE_WORD)
+ emit_mov_m16_r16(dst, MBD(basereg, baseoffs + scale*indp.immediate()), srcreg); // mov [basep + scale*indp],srcreg
+ else if (size == SIZE_DWORD)
+ emit_mov_m32_r32(dst, MBD(basereg, baseoffs + scale*indp.immediate()), srcreg); // mov [basep + scale*indp],srcreg
+ else if (size == SIZE_QWORD)
+ emit_mov_m64_r64(dst, MBD(basereg, baseoffs + scale*indp.immediate()), srcreg); // mov [basep + scale*indp],srcreg
+ }
+ }
+
+ // normal case: variable index
+ else
+ {
+ int indreg = indp.select_register(REG_ECX);
+ emit_movsx_r64_p32(dst, indreg, indp); // mov indreg,indp
+
+ // immediate source
+ if (srcp.is_immediate())
+ {
+ if (size == SIZE_BYTE)
+ emit_mov_m8_imm(dst, MBISD(basereg, indreg, scale, baseoffs), srcp.immediate());// mov [basep + scale*ecx],srcp
+ else if (size == SIZE_WORD)
+ emit_mov_m16_imm(dst, MBISD(basereg, indreg, scale, baseoffs), srcp.immediate());// mov [basep + scale*ecx],srcp
+ else if (size == SIZE_DWORD)
+ emit_mov_m32_imm(dst, MBISD(basereg, indreg, scale, baseoffs), srcp.immediate());// mov [basep + scale*ecx],srcp
+ else if (size == SIZE_QWORD)
+ {
+ if (short_immediate(srcp.immediate()))
+ emit_mov_m64_imm(dst, MBISD(basereg, indreg, scale, baseoffs), srcp.immediate());// mov [basep + scale*indp],srcp
+ else
+ {
+ emit_mov_m32_imm(dst, MBISD(basereg, indreg, scale, baseoffs), srcp.immediate());// mov [basep + scale*ecx],srcp
+ emit_mov_m32_imm(dst, MBISD(basereg, indreg, scale, baseoffs + 4), srcp.immediate() >> 32);
+ // mov [basep + scale*ecx + 4],srcp >> 32
+ }
+ }
+ }
+
+ // variable source
+ else
+ {
+ if (size != SIZE_QWORD)
+ emit_mov_r32_p32(dst, srcreg, srcp); // mov srcreg,srcp
+ else
+ emit_mov_r64_p64(dst, srcreg, srcp); // mov edx:srcreg,srcp
+ if (size == SIZE_BYTE)
+ emit_mov_m8_r8(dst, MBISD(basereg, indreg, scale, baseoffs), srcreg); // mov [basep + scale*ecx],srcreg
+ else if (size == SIZE_WORD)
+ emit_mov_m16_r16(dst, MBISD(basereg, indreg, scale, baseoffs), srcreg); // mov [basep + scale*ecx],srcreg
+ else if (size == SIZE_DWORD)
+ emit_mov_m32_r32(dst, MBISD(basereg, indreg, scale, baseoffs), srcreg); // mov [basep + scale*ecx],srcreg
+ else if (size == SIZE_QWORD)
+ emit_mov_m64_r64(dst, MBISD(basereg, indreg, scale, baseoffs), srcreg); // mov [basep + scale*ecx],srcreg
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// op_read - process a READ opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_read(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter addrp(*this, inst.param(1), PTYPE_MRI);
+ const parameter &spacesizep = inst.param(2);
+ assert(spacesizep.is_size_space());
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX);
+
+ // set up a call to the read byte handler
+ emit_mov_r64_imm(dst, REG_PARAM1, (FPTR)(m_space[spacesizep.space()])); // mov param1,space
+ emit_mov_r32_p32(dst, REG_PARAM2, addrp); // mov param2,addrp
+ if (spacesizep.size() == SIZE_BYTE)
+ {
+ emit_smart_call_m64(dst, (x86code **)&m_accessors[spacesizep.space()].read_byte);
+ // call read_byte
+ emit_movzx_r32_r8(dst, dstreg, REG_AL); // movzx dstreg,al
+ }
+ else if (spacesizep.size() == SIZE_WORD)
+ {
+ emit_smart_call_m64(dst, (x86code **)&m_accessors[spacesizep.space()].read_word);
+ // call read_word
+ emit_movzx_r32_r16(dst, dstreg, REG_AX); // movzx dstreg,ax
+ }
+ else if (spacesizep.size() == SIZE_DWORD)
+ {
+ emit_smart_call_m64(dst, (x86code **)&m_accessors[spacesizep.space()].read_dword);
+ // call read_dword
+ if (dstreg != REG_EAX || inst.size() == 8)
+ emit_mov_r32_r32(dst, dstreg, REG_EAX); // mov dstreg,eax
+ }
+ else if (spacesizep.size() == SIZE_QWORD)
+ {
+ emit_smart_call_m64(dst, (x86code **)&m_accessors[spacesizep.space()].read_qword);
+ // call read_qword
+ if (dstreg != REG_RAX)
+ emit_mov_r64_r64(dst, dstreg, REG_RAX); // mov dstreg,rax
+ }
+
+ // store result
+ if (inst.size() == 4)
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ else
+ emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg
+}
+
+
+//-------------------------------------------------
+// op_readm - process a READM opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_readm(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter addrp(*this, inst.param(1), PTYPE_MRI);
+ be_parameter maskp(*this, inst.param(2), PTYPE_MRI);
+ const parameter &spacesizep = inst.param(3);
+ assert(spacesizep.is_size_space());
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX);
+
+ // set up a call to the read byte handler
+ emit_mov_r64_imm(dst, REG_PARAM1, (FPTR)(m_space[spacesizep.space()])); // mov param1,space
+ emit_mov_r32_p32(dst, REG_PARAM2, addrp); // mov param2,addrp
+ if (spacesizep.size() != SIZE_QWORD)
+ emit_mov_r32_p32(dst, REG_PARAM3, maskp); // mov param3,maskp
+ else
+ emit_mov_r64_p64(dst, REG_PARAM3, maskp); // mov param3,maskp
+ if (spacesizep.size() == SIZE_WORD)
+ {
+ emit_smart_call_m64(dst, (x86code **)&m_accessors[spacesizep.space()].read_word_masked);
+ // call read_word_masked
+ emit_movzx_r32_r16(dst, dstreg, REG_AX); // movzx dstreg,ax
+ }
+ else if (spacesizep.size() == SIZE_DWORD)
+ {
+ emit_smart_call_m64(dst, (x86code **)&m_accessors[spacesizep.space()].read_dword_masked);
+ // call read_dword_masked
+ if (dstreg != REG_EAX || inst.size() == 8)
+ emit_mov_r32_r32(dst, dstreg, REG_EAX); // mov dstreg,eax
+ }
+ else if (spacesizep.size() == SIZE_QWORD)
+ {
+ emit_smart_call_m64(dst, (x86code **)&m_accessors[spacesizep.space()].read_qword_masked);
+ // call read_qword_masked
+ if (dstreg != REG_RAX)
+ emit_mov_r64_r64(dst, dstreg, REG_RAX); // mov dstreg,rax
+ }
+
+ // store result
+ if (inst.size() == 4)
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ else
+ emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg
+}
+
+
+//-------------------------------------------------
+// op_write - process a WRITE opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_write(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter addrp(*this, inst.param(0), PTYPE_MRI);
+ be_parameter srcp(*this, inst.param(1), PTYPE_MRI);
+ const parameter &spacesizep = inst.param(2);
+ assert(spacesizep.is_size_space());
+
+ // set up a call to the write byte handler
+ emit_mov_r64_imm(dst, REG_PARAM1, (FPTR)(m_space[spacesizep.space()])); // mov param1,space
+ emit_mov_r32_p32(dst, REG_PARAM2, addrp); // mov param2,addrp
+ if (spacesizep.size() != SIZE_QWORD)
+ emit_mov_r32_p32(dst, REG_PARAM3, srcp); // mov param3,srcp
+ else
+ emit_mov_r64_p64(dst, REG_PARAM3, srcp); // mov param3,srcp
+ if (spacesizep.size() == SIZE_BYTE)
+ emit_smart_call_m64(dst, (x86code **)&m_accessors[spacesizep.space()].write_byte);
+ // call write_byte
+ else if (spacesizep.size() == SIZE_WORD)
+ emit_smart_call_m64(dst, (x86code **)&m_accessors[spacesizep.space()].write_word);
+ // call write_word
+ else if (spacesizep.size() == SIZE_DWORD)
+ emit_smart_call_m64(dst, (x86code **)&m_accessors[spacesizep.space()].write_dword);
+ // call write_dword
+ else if (spacesizep.size() == SIZE_QWORD)
+ emit_smart_call_m64(dst, (x86code **)&m_accessors[spacesizep.space()].write_qword);
+ // call write_qword
+}
+
+
+//-------------------------------------------------
+// op_writem - process a WRITEM opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_writem(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter addrp(*this, inst.param(0), PTYPE_MRI);
+ be_parameter srcp(*this, inst.param(1), PTYPE_MRI);
+ be_parameter maskp(*this, inst.param(2), PTYPE_MRI);
+ const parameter &spacesizep = inst.param(3);
+ assert(spacesizep.is_size_space());
+
+ // set up a call to the write byte handler
+ emit_mov_r64_imm(dst, REG_PARAM1, (FPTR)(m_space[spacesizep.space()])); // mov param1,space
+ emit_mov_r32_p32(dst, REG_PARAM2, addrp); // mov param2,addrp
+ if (spacesizep.size() != SIZE_QWORD)
+ {
+ emit_mov_r32_p32(dst, REG_PARAM3, srcp); // mov param3,srcp
+ emit_mov_r32_p32(dst, REG_PARAM4, maskp); // mov param4,maskp
+ }
+ else
+ {
+ emit_mov_r64_p64(dst, REG_PARAM3, srcp); // mov param3,srcp
+ emit_mov_r64_p64(dst, REG_PARAM4, maskp); // mov param4,maskp
+ }
+ if (spacesizep.size() == SIZE_WORD)
+ emit_smart_call_m64(dst, (x86code **)&m_accessors[spacesizep.space()].write_word_masked);
+ // call write_word_masked
+ else if (spacesizep.size() == SIZE_DWORD)
+ emit_smart_call_m64(dst, (x86code **)&m_accessors[spacesizep.space()].write_dword_masked);
+ // call write_dword_masked
+ else if (spacesizep.size() == SIZE_QWORD)
+ emit_smart_call_m64(dst, (x86code **)&m_accessors[spacesizep.space()].write_qword_masked);
+ // call write_qword_masked
+}
+
+
+//-------------------------------------------------
+// op_carry - process a CARRY opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_carry(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_C);
+
+ // normalize parameters
+ be_parameter srcp(*this, inst.param(0), PTYPE_MRI);
+ be_parameter bitp(*this, inst.param(1), PTYPE_MRI);
+
+ // degenerate case: source is immediate
+ if (srcp.is_immediate() && bitp.is_immediate())
+ {
+ if (srcp.immediate() & ((UINT64)1 << bitp.immediate()))
+ emit_stc(dst);
+ else
+ emit_clc(dst);
+ }
+
+ // load non-immediate bit numbers into a register
+ if (!bitp.is_immediate())
+ {
+ emit_mov_r32_p32(dst, REG_ECX, bitp);
+ emit_and_r32_imm(dst, REG_ECX, inst.size() * 8 - 1);
+ }
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ if (bitp.is_immediate())
+ {
+ if (srcp.is_memory())
+ emit_bt_m32_imm(dst, MABS(srcp.memory()), bitp.immediate()); // bt [srcp],bitp
+ else if (srcp.is_int_register())
+ emit_bt_r32_imm(dst, srcp.ireg(), bitp.immediate()); // bt srcp,bitp
+ }
+ else
+ {
+ if (srcp.is_memory())
+ emit_bt_m32_r32(dst, MABS(srcp.memory()), REG_ECX); // bt [srcp],ecx
+ else if (srcp.is_int_register())
+ emit_bt_r32_r32(dst, srcp.ireg(), REG_ECX); // bt srcp,ecx
+ }
+ }
+
+ // 64-bit form
+ else
+ {
+ if (bitp.is_immediate())
+ {
+ if (srcp.is_memory())
+ emit_bt_m64_imm(dst, MABS(srcp.memory()), bitp.immediate()); // bt [srcp],bitp
+ else if (srcp.is_int_register())
+ emit_bt_r64_imm(dst, srcp.ireg(), bitp.immediate()); // bt srcp,bitp
+ }
+ else
+ {
+ if (srcp.is_memory())
+ emit_bt_m64_r64(dst, MABS(srcp.memory()), REG_ECX); // bt [srcp],ecx
+ else if (srcp.is_int_register())
+ emit_bt_r64_r64(dst, srcp.ireg(), REG_ECX); // bt srcp,ecx
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// op_set - process a SET opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_set(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_any_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX);
+
+ // set to AL
+ emit_setcc_r8(dst, X86_CONDITION(inst.condition()), REG_AL); // setcc al
+ emit_movzx_r32_r8(dst, dstreg, REG_AL); // movzx dstreg,al
+
+ // 32-bit form
+ if (inst.size() == 4)
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg
+
+}
+
+
+//-------------------------------------------------
+// op_mov - process a MOV opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_mov(x86code *&dst, const instruction &inst)
+{
+ x86code *savedst = dst;
+
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_any_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter srcp(*this, inst.param(1), PTYPE_MRI);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX);
+
+ // always start with a jmp
+ emit_link skip = { 0 };
+ if (inst.condition() != uml::COND_ALWAYS)
+ emit_jcc_short_link(dst, X86_NOT_CONDITION(inst.condition()), skip); // jcc skip
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // register to memory
+ if (dstp.is_memory() && srcp.is_int_register())
+ emit_mov_m32_r32(dst, MABS(dstp.memory()), srcp.ireg()); // mov [dstp],srcp
+
+ // immediate to memory
+ else if (dstp.is_memory() && srcp.is_immediate())
+ emit_mov_m32_imm(dst, MABS(dstp.memory()), srcp.immediate()); // mov [dstp],srcp
+
+ // conditional memory to register
+ else if (inst.condition() != 0 && dstp.is_int_register() && srcp.is_memory())
+ {
+ dst = savedst;
+ skip.target = NULL;
+ emit_cmovcc_r32_m32(dst, X86_CONDITION(inst.condition()), dstp.ireg(), MABS(srcp.memory()));
+ // cmovcc dstp,[srcp]
+ }
+
+ // conditional register to register
+ else if (inst.condition() != 0 && dstp.is_int_register() && srcp.is_int_register())
+ {
+ dst = savedst;
+ skip.target = NULL;
+ emit_cmovcc_r32_r32(dst, X86_CONDITION(inst.condition()), dstp.ireg(), srcp.ireg());
+ // cmovcc dstp,srcp
+ }
+
+ // general case
+ else
+ {
+ emit_mov_r32_p32_keepflags(dst, dstreg, srcp); // mov dstreg,srcp
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // register to memory
+ if (dstp.is_memory() && srcp.is_int_register())
+ emit_mov_m64_r64(dst, MABS(dstp.memory()), srcp.ireg()); // mov [dstp],srcp
+
+ // immediate to memory
+ else if (dstp.is_memory() && srcp.is_immediate() && short_immediate(srcp.immediate()))
+ emit_mov_m64_imm(dst, MABS(dstp.memory()), srcp.immediate()); // mov [dstp],srcp
+
+ // conditional memory to register
+ else if (inst.condition() != 0 && dstp.is_int_register() && srcp.is_memory())
+ {
+ dst = savedst;
+ skip.target = NULL;
+ emit_cmovcc_r64_m64(dst, X86_CONDITION(inst.condition()), dstp.ireg(), MABS(srcp.memory()));
+ // cmovcc dstp,[srcp]
+ }
+
+ // conditional register to register
+ else if (inst.condition() != 0 && dstp.is_int_register() && srcp.is_int_register())
+ {
+ dst = savedst;
+ skip.target = NULL;
+ emit_cmovcc_r64_r64(dst, X86_CONDITION(inst.condition()), dstp.ireg(), srcp.ireg());
+ // cmovcc dstp,srcp
+ }
+
+ // general case
+ else
+ {
+ emit_mov_r64_p64_keepflags(dst, dstreg, srcp); // mov dstreg,srcp
+ emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+
+ // resolve the jump
+ if (skip.target != NULL)
+ resolve_link(dst, skip);
+}
+
+
+//-------------------------------------------------
+// op_sext - process a SEXT opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_sext(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_S | FLAG_Z);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter srcp(*this, inst.param(1), PTYPE_MRI);
+ const parameter &sizep = inst.param(2);
+ assert(sizep.is_size());
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // general case
+ if (srcp.is_memory())
+ {
+ if (sizep.size() == SIZE_BYTE)
+ emit_movsx_r32_m8(dst, dstreg, MABS(srcp.memory())); // movsx dstreg,[srcp]
+ else if (sizep.size() == SIZE_WORD)
+ emit_movsx_r32_m16(dst, dstreg, MABS(srcp.memory())); // movsx dstreg,[srcp]
+ else if (sizep.size() == SIZE_DWORD)
+ emit_mov_r32_m32(dst, dstreg, MABS(srcp.memory())); // mov dstreg,[srcp]
+ }
+ else if (srcp.is_int_register())
+ {
+ if (sizep.size() == SIZE_BYTE)
+ emit_movsx_r32_r8(dst, dstreg, srcp.ireg()); // movsx dstreg,srcp
+ else if (sizep.size() == SIZE_WORD)
+ emit_movsx_r32_r16(dst, dstreg, srcp.ireg()); // movsx dstreg,srcp
+ else if (sizep.size() == SIZE_DWORD)
+ emit_mov_r32_r32(dst, dstreg, srcp.ireg()); // mov dstreg,srcp
+ }
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ if (inst.flags() != 0)
+ emit_test_r32_r32(dst, dstreg, dstreg); // test dstreg,dstreg
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // general case
+ if (srcp.is_memory())
+ {
+ if (sizep.size() == SIZE_BYTE)
+ emit_movsx_r64_m8(dst, dstreg, MABS(srcp.memory())); // movsx dstreg,[srcp]
+ else if (sizep.size() == SIZE_WORD)
+ emit_movsx_r64_m16(dst, dstreg, MABS(srcp.memory())); // movsx dstreg,[srcp]
+ else if (sizep.size() == SIZE_DWORD)
+ emit_movsxd_r64_m32(dst, dstreg, MABS(srcp.memory())); // movsxd dstreg,[srcp]
+ else if (sizep.size() == SIZE_QWORD)
+ emit_mov_r64_m64(dst, dstreg, MABS(srcp.memory())); // mov dstreg,[srcp]
+ }
+ else if (srcp.is_int_register())
+ {
+ if (sizep.size() == SIZE_BYTE)
+ emit_movsx_r64_r8(dst, dstreg, srcp.ireg()); // movsx dstreg,srcp
+ else if (sizep.size() == SIZE_WORD)
+ emit_movsx_r64_r16(dst, dstreg, srcp.ireg()); // movsx dstreg,srcp
+ else if (sizep.size() == SIZE_DWORD)
+ emit_movsxd_r64_r32(dst, dstreg, srcp.ireg()); // movsxd dstreg,srcp
+ else if (sizep.size() == SIZE_QWORD)
+ emit_mov_r64_r64(dst, dstreg, srcp.ireg()); // mov dstreg,srcp
+ }
+ emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg
+ if (inst.flags() != 0)
+ emit_test_r64_r64(dst, dstreg, dstreg); // test dstreg,dstreg
+ }
+}
+
+
+//-------------------------------------------------
+// op_roland - process an ROLAND opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_roland(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_S | FLAG_Z);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter srcp(*this, inst.param(1), PTYPE_MRI);
+ be_parameter shiftp(*this, inst.param(2), PTYPE_MRI);
+ be_parameter maskp(*this, inst.param(3), PTYPE_MRI);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX, shiftp, maskp);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ emit_mov_r32_p32(dst, dstreg, srcp); // mov dstreg,srcp
+ emit_rol_r32_p32(dst, dstreg, shiftp, inst); // rol dstreg,shiftp
+ emit_and_r32_p32(dst, dstreg, maskp, inst); // and dstreg,maskp
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ emit_mov_r64_p64(dst, dstreg, srcp); // mov dstreg,srcp
+ emit_rol_r64_p64(dst, dstreg, shiftp, inst); // rol dstreg,shiftp
+ emit_and_r64_p64(dst, dstreg, maskp, inst); // and dstreg,maskp
+ emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+}
+
+
+//-------------------------------------------------
+// op_rolins - process an ROLINS opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_rolins(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_S | FLAG_Z);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter srcp(*this, inst.param(1), PTYPE_MRI);
+ be_parameter shiftp(*this, inst.param(2), PTYPE_MRI);
+ be_parameter maskp(*this, inst.param(3), PTYPE_MRI);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_ECX, shiftp, maskp);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ emit_mov_r32_p32(dst, REG_EAX, srcp); // mov eax,srcp
+ emit_rol_r32_p32(dst, REG_EAX, shiftp, inst); // rol eax,shiftp
+ emit_mov_r32_p32(dst, dstreg, dstp); // mov dstreg,dstp
+ if (maskp.is_immediate())
+ {
+ emit_and_r32_imm(dst, REG_EAX, maskp.immediate()); // and eax,maskp
+ emit_and_r32_imm(dst, dstreg, ~maskp.immediate()); // and dstreg,~maskp
+ }
+ else
+ {
+ emit_mov_r32_p32(dst, REG_EDX, maskp); // mov edx,maskp
+ emit_and_r32_r32(dst, REG_EAX, REG_EDX); // and eax,edx
+ emit_not_r32(dst, REG_EDX); // not edx
+ emit_and_r32_r32(dst, dstreg, REG_EDX); // and dstreg,edx
+ }
+ emit_or_r32_r32(dst, dstreg, REG_EAX); // or dstreg,eax
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ emit_mov_r64_p64(dst, REG_RAX, srcp); // mov rax,srcp
+ emit_mov_r64_p64(dst, REG_RDX, maskp); // mov rdx,maskp
+ emit_rol_r64_p64(dst, REG_RAX, shiftp, inst); // rol rax,shiftp
+ emit_mov_r64_p64(dst, dstreg, dstp); // mov dstreg,dstp
+ emit_and_r64_r64(dst, REG_RAX, REG_RDX); // and eax,rdx
+ emit_not_r64(dst, REG_RDX); // not rdx
+ emit_and_r64_r64(dst, dstreg, REG_RDX); // and dstreg,rdx
+ emit_or_r64_r64(dst, dstreg, REG_RAX); // or dstreg,rax
+ emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+}
+
+
+//-------------------------------------------------
+// op_add - process a ADD opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_add(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_C | FLAG_V | FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
+ be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
+ normalize_commutative(src1p, src2p);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX, src2p);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_add_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // add [dstp],src2p
+
+ // reg = reg + imm
+ else if (dstp.is_int_register() && src1p.is_int_register() && src2p.is_immediate() && inst.flags() == 0)
+ emit_lea_r32_m32(dst, dstp.ireg(), MBD(src1p.ireg(), src2p.immediate())); // lea dstp,[src1p+src2p]
+
+ // reg = reg + reg
+ else if (dstp.is_int_register() && src1p.is_int_register() && src2p.is_int_register() && inst.flags() == 0)
+ emit_lea_r32_m32(dst, dstp.ireg(), MBISD(src1p.ireg(), src2p.ireg(), 1, 0));// lea dstp,[src1p+src2p]
+
+ // general case
+ else
+ {
+ emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_add_r32_p32(dst, dstreg, src2p, inst); // add dstreg,src2p
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_add_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // add [dstp],src2p
+
+ // reg = reg + imm
+ else if (dstp.is_int_register() && src1p.is_int_register() && src2p.is_immediate() && short_immediate(src2p.immediate()) && inst.flags() == 0)
+ emit_lea_r64_m64(dst, dstp.ireg(), MBD(src1p.ireg(), src2p.immediate())); // lea dstp,[src1p+src2p]
+
+ // reg = reg + reg
+ else if (dstp.is_int_register() && src1p.is_int_register() && src2p.is_int_register() && inst.flags() == 0)
+ emit_lea_r64_m64(dst, dstp.ireg(), MBISD(src1p.ireg(), src2p.ireg(), 1, 0));// lea dstp,[src1p+src2p]
+
+ // general case
+ else
+ {
+ emit_mov_r64_p64(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_add_r64_p64(dst, dstreg, src2p, inst); // add dstreg,src2p
+ emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// op_addc - process a ADDC opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_addc(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_C | FLAG_V | FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
+ be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
+ normalize_commutative(src1p, src2p);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX, src2p);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_adc_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // adc [dstp],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r32_p32_keepflags(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_adc_r32_p32(dst, dstreg, src2p, inst); // adc dstreg,src2p
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_adc_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // adc [dstp],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r64_p64_keepflags(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_adc_r64_p64(dst, dstreg, src2p, inst); // adc dstreg,src2p
+ emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// op_sub - process a SUB opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_sub(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_C | FLAG_V | FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
+ be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX, src2p);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_sub_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // sub [dstp],src2p
+
+ // reg = reg - imm
+ else if (dstp.is_int_register() && src1p.is_int_register() && src2p.is_immediate() && inst.flags() == 0)
+ emit_lea_r32_m32(dst, dstp.ireg(), MBD(src1p.ireg(), -src2p.immediate())); // lea dstp,[src1p-src2p]
+
+ // general case
+ else
+ {
+ emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_sub_r32_p32(dst, dstreg, src2p, inst); // sub dstreg,src2p
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_sub_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // sub [dstp],src2p
+
+ // reg = reg - imm
+ else if (dstp.is_int_register() && src1p.is_int_register() && src2p.is_immediate() && short_immediate(src2p.immediate()) && inst.flags() == 0)
+ emit_lea_r64_m64(dst, dstp.ireg(), MBD(src1p.ireg(), -src2p.immediate())); // lea dstp,[src1p-src2p]
+
+ // general case
+ else
+ {
+ emit_mov_r64_p64(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_sub_r64_p64(dst, dstreg, src2p, inst); // sub dstreg,src2p
+ emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// op_subc - process a SUBC opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_subc(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_C | FLAG_V | FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
+ be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX, src2p);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_sbb_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // sbb [dstp],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r32_p32_keepflags(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_sbb_r32_p32(dst, dstreg, src2p, inst); // sbb dstreg,src2p
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_sbb_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // sbb [dstp],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r64_p64_keepflags(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_sbb_r64_p64(dst, dstreg, src2p, inst); // sbb dstreg,src2p
+ emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// op_cmp - process a CMP opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_cmp(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_C | FLAG_V | FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter src1p(*this, inst.param(0), PTYPE_MRI);
+ be_parameter src2p(*this, inst.param(1), PTYPE_MRI);
+
+ // pick a target register for the general case
+ int src1reg = src1p.select_register(REG_EAX);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // memory versus anything
+ if (src1p.is_memory())
+ emit_cmp_m32_p32(dst, MABS(src1p.memory()), src2p, inst); // cmp [dstp],src2p
+
+ // general case
+ else
+ {
+ if (src1p.is_immediate())
+ emit_mov_r32_imm(dst, src1reg, src1p.immediate()); // mov src1reg,imm
+ emit_cmp_r32_p32(dst, src1reg, src2p, inst); // cmp src1reg,src2p
+ }
+ }
+
+ // 64-bit form
+ else
+ {
+ // memory versus anything
+ if (src1p.is_memory())
+ emit_cmp_m64_p64(dst, MABS(src1p.memory()), src2p, inst); // cmp [dstp],src2p
+
+ // general case
+ else
+ {
+ if (src1p.is_immediate())
+ emit_mov_r64_imm(dst, src1reg, src1p.immediate()); // mov src1reg,imm
+ emit_cmp_r64_p64(dst, src1reg, src2p, inst); // cmp src1reg,src2p
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// op_mulu - process a MULU opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_mulu(x86code *&dst, const instruction &inst)
+{
+ UINT8 zsflags = inst.flags() & (FLAG_Z | FLAG_S);
+ UINT8 vflag = inst.flags() & FLAG_V;
+
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_V | FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter edstp(*this, inst.param(1), PTYPE_MR);
+ be_parameter src1p(*this, inst.param(2), PTYPE_MRI);
+ be_parameter src2p(*this, inst.param(3), PTYPE_MRI);
+ normalize_commutative(src1p, src2p);
+ bool compute_hi = (dstp != edstp);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // general case
+ emit_mov_r32_p32(dst, REG_EAX, src1p); // mov eax,src1p
+ if (src2p.is_memory())
+ emit_mul_m32(dst, MABS(src2p.memory())); // mul [src2p]
+ else if (src2p.is_int_register())
+ emit_mul_r32(dst, src2p.ireg()); // mul src2p
+ else if (src2p.is_immediate())
+ {
+ emit_mov_r32_imm(dst, REG_EDX, src2p.immediate()); // mov edx,src2p
+ emit_mul_r32(dst, REG_EDX); // mul edx
+ }
+ emit_mov_p32_r32(dst, dstp, REG_EAX); // mov dstp,eax
+ if (compute_hi)
+ emit_mov_p32_r32(dst, edstp, REG_EDX); // mov edstp,edx
+
+ // compute flags
+ if (inst.flags() != 0)
+ {
+ if (zsflags != 0)
+ {
+ if (vflag)
+ emit_pushf(dst); // pushf
+ if (compute_hi)
+ {
+ if (zsflags == FLAG_Z)
+ emit_or_r32_r32(dst, REG_EDX, REG_EAX); // or edx,eax
+ else if (zsflags == FLAG_S)
+ emit_test_r32_r32(dst, REG_EDX, REG_EDX); // test edx,edx
+ else
+ {
+ emit_movzx_r32_r16(dst, REG_ECX, REG_AX); // movzx ecx,ax
+ emit_shr_r32_imm(dst, REG_EAX, 16); // shr eax,16
+ emit_or_r32_r32(dst, REG_EDX, REG_ECX); // or edx,ecx
+ emit_or_r32_r32(dst, REG_EDX, REG_EAX); // or edx,eax
+ }
+ }
+ else
+ emit_test_r32_r32(dst, REG_EAX, REG_EAX); // test eax,eax
+
+ // we rely on the fact that OF is cleared by all logical operations above
+ if (vflag)
+ {
+ emit_pushf(dst); // pushf
+ emit_pop_r64(dst, REG_RAX); // pop rax
+ emit_and_m64_imm(dst, MBD(REG_RSP, 0), ~0x84); // and [rsp],~0x84
+ emit_or_m64_r64(dst, MBD(REG_RSP, 0), REG_RAX); // or [rsp],rax
+ emit_popf(dst); // popf
+ }
+ }
+ }
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // general case
+ emit_mov_r64_p64(dst, REG_RAX, src1p); // mov rax,src1p
+ if (src2p.is_memory())
+ emit_mul_m64(dst, MABS(src2p.memory())); // mul [src2p]
+ else if (src2p.is_int_register())
+ emit_mul_r64(dst, src2p.ireg()); // mul src2p
+ else if (src2p.is_immediate())
+ {
+ emit_mov_r64_imm(dst, REG_RDX, src2p.immediate()); // mov rdx,src2p
+ emit_mul_r64(dst, REG_RDX); // mul rdx
+ }
+ emit_mov_p64_r64(dst, dstp, REG_RAX); // mov dstp,rax
+ if (compute_hi)
+ emit_mov_p64_r64(dst, edstp, REG_RDX); // mov edstp,rdx
+
+ // compute flags
+ if (inst.flags() != 0)
+ {
+ if (zsflags != 0)
+ {
+ if (vflag)
+ emit_pushf(dst); // pushf
+ if (compute_hi)
+ {
+ if (zsflags == FLAG_Z)
+ emit_or_r64_r64(dst, REG_RDX, REG_RAX); // or rdx,rax
+ else if (zsflags == FLAG_S)
+ emit_test_r64_r64(dst, REG_RDX, REG_RDX); // test rdx,rdx
+ else
+ {
+ emit_mov_r32_r32(dst, REG_ECX, REG_EAX); // mov ecx,eax
+ emit_shr_r64_imm(dst, REG_RAX, 32); // shr rax,32
+ emit_or_r64_r64(dst, REG_RDX, REG_RCX); // or rdx,rcx
+ emit_or_r64_r64(dst, REG_RDX, REG_RAX); // or rdx,rax
+ }
+ }
+ else
+ emit_test_r64_r64(dst, REG_RAX, REG_RAX); // test rax,rax
+
+ // we rely on the fact that OF is cleared by all logical operations above
+ if (vflag)
+ {
+ emit_pushf(dst); // pushf
+ emit_pop_r64(dst, REG_RAX); // pop rax
+ emit_and_m64_imm(dst, MBD(REG_RSP, 0), ~0x84); // and [rsp],~0x84
+ emit_or_m64_r64(dst, MBD(REG_RSP, 0), REG_RAX); // or [rsp],rax
+ emit_popf(dst); // popf
+ }
+ }
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// op_muls - process a MULS opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_muls(x86code *&dst, const instruction &inst)
+{
+ UINT8 zsflags = inst.flags() & (FLAG_Z | FLAG_S);
+ UINT8 vflag = inst.flags() & FLAG_V;
+
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_V | FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter edstp(*this, inst.param(1), PTYPE_MR);
+ be_parameter src1p(*this, inst.param(2), PTYPE_MRI);
+ be_parameter src2p(*this, inst.param(3), PTYPE_MRI);
+ normalize_commutative(src1p, src2p);
+ bool compute_hi = (dstp != edstp);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // 32-bit destination with memory/immediate or register/immediate
+ if (!compute_hi && !src1p.is_immediate() && src2p.is_immediate())
+ {
+ if (src1p.is_memory())
+ emit_imul_r32_m32_imm(dst, REG_EAX, MABS(src1p.memory()), src2p.immediate()); // imul eax,[src1p],src2p
+ else if (src1p.is_int_register())
+ emit_imul_r32_r32_imm(dst, REG_EAX, src1p.ireg(), src2p.immediate()); // imul eax,src1p,src2p
+ emit_mov_p32_r32(dst, dstp, REG_EAX); // mov dstp,eax
+ }
+
+ // 32-bit destination, general case
+ else if (!compute_hi)
+ {
+ emit_mov_r32_p32(dst, REG_EAX, src1p); // mov eax,src1p
+ if (src2p.is_memory())
+ emit_imul_r32_m32(dst, REG_EAX, MABS(src2p.memory())); // imul eax,[src2p]
+ else if (src2p.is_int_register())
+ emit_imul_r32_r32(dst, REG_EAX, src2p.ireg()); // imul eax,src2p
+ emit_mov_p32_r32(dst, dstp, REG_EAX); // mov dstp,eax
+ }
+
+ // 64-bit destination, general case
+ else
+ {
+ emit_mov_r32_p32(dst, REG_EAX, src1p); // mov eax,src1p
+ if (src2p.is_memory())
+ emit_imul_m32(dst, MABS(src2p.memory())); // imul [src2p]
+ else if (src2p.is_int_register())
+ emit_imul_r32(dst, src2p.ireg()); // imul src2p
+ else if (src2p.is_immediate())
+ {
+ emit_mov_r32_imm(dst, REG_EDX, src2p.immediate()); // mov edx,src2p
+ emit_imul_r32(dst, REG_EDX); // imul edx
+ }
+ emit_mov_p32_r32(dst, dstp, REG_EAX); // mov dstp,eax
+ emit_mov_p32_r32(dst, edstp, REG_EDX); // mov edstp,edx
+ }
+
+ // compute flags
+ if (inst.flags() != 0)
+ {
+ if (zsflags != 0)
+ {
+ if (vflag)
+ emit_pushf(dst); // pushf
+ if (compute_hi)
+ {
+ if (zsflags == FLAG_Z)
+ emit_or_r32_r32(dst, REG_EDX, REG_EAX); // or edx,eax
+ else if (zsflags == FLAG_S)
+ emit_test_r32_r32(dst, REG_EDX, REG_EDX); // test edx,edx
+ else
+ {
+ emit_movzx_r32_r16(dst, REG_ECX, REG_AX); // movzx ecx,ax
+ emit_shr_r32_imm(dst, REG_EAX, 16); // shr eax,16
+ emit_or_r32_r32(dst, REG_EDX, REG_ECX); // or edx,ecx
+ emit_or_r32_r32(dst, REG_EDX, REG_EAX); // or edx,eax
+ }
+ }
+ else
+ emit_test_r32_r32(dst, REG_EAX, REG_EAX); // test eax,eax
+
+ // we rely on the fact that OF is cleared by all logical operations above
+ if (vflag)
+ {
+ emit_pushf(dst); // pushf
+ emit_pop_r64(dst, REG_RAX); // pop rax
+ emit_and_m64_imm(dst, MBD(REG_RSP, 0), ~0x84); // and [rsp],~0x84
+ emit_or_m64_r64(dst, MBD(REG_RSP, 0), REG_RAX); // or [rsp],rax
+ emit_popf(dst); // popf
+ }
+ }
+ }
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // 64-bit destination with memory/immediate or register/immediate
+ if (!compute_hi && !src1p.is_immediate() && src2p.is_immediate() && short_immediate(src2p.immediate()))
+ {
+ if (src1p.is_memory())
+ emit_imul_r64_m64_imm(dst, REG_RAX, MABS(src1p.memory()), src2p.immediate());// imul rax,[src1p],src2p
+ else if (src1p.is_int_register())
+ emit_imul_r64_r64_imm(dst, REG_RAX, src1p.ireg(), src2p.immediate()); // imul rax,src1p,src2p
+ emit_mov_p64_r64(dst, dstp, REG_RAX); // mov dstp,rax
+ }
+
+ // 64-bit destination, general case
+ else if (!compute_hi)
+ {
+ emit_mov_r64_p64(dst, REG_RAX, src1p); // mov rax,src1p
+ if (src2p.is_memory())
+ emit_imul_r64_m64(dst, REG_RAX, MABS(src2p.memory())); // imul rax,[src2p]
+ else if (src2p.is_int_register())
+ emit_imul_r64_r64(dst, REG_RAX, src2p.ireg()); // imul rax,src2p
+ emit_mov_p64_r64(dst, dstp, REG_RAX); // mov dstp,rax
+ }
+
+ // 128-bit destination, general case
+ else
+ {
+ emit_mov_r64_p64(dst, REG_RAX, src1p); // mov rax,src1p
+ if (src2p.is_memory())
+ emit_imul_m64(dst, MABS(src2p.memory())); // imul [src2p]
+ else if (src2p.is_int_register())
+ emit_imul_r64(dst, src2p.ireg()); // imul src2p
+ else if (src2p.is_immediate())
+ {
+ emit_mov_r64_imm(dst, REG_RDX, src2p.immediate()); // mov rdx,src2p
+ emit_imul_r64(dst, REG_RDX); // imul rdx
+ }
+ emit_mov_p64_r64(dst, dstp, REG_RAX); // mov dstp,rax
+ emit_mov_p64_r64(dst, edstp, REG_RDX); // mov edstp,rdx
+ }
+
+ // compute flags
+ if (inst.flags() != 0)
+ {
+ if (zsflags != 0)
+ {
+ if (vflag)
+ emit_pushf(dst); // pushf
+ if (compute_hi)
+ {
+ if (zsflags == FLAG_Z)
+ emit_or_r64_r64(dst, REG_RDX, REG_RAX); // or rdx,rax
+ else if (zsflags == FLAG_S)
+ emit_test_r64_r64(dst, REG_RDX, REG_RDX); // test rdx,rdx
+ else
+ {
+ emit_mov_r32_r32(dst, REG_ECX, REG_EAX); // mov ecx,eax
+ emit_shr_r64_imm(dst, REG_RAX, 32); // shr rax,32
+ emit_or_r64_r64(dst, REG_RDX, REG_RCX); // or rdx,rcx
+ emit_or_r64_r64(dst, REG_RDX, REG_RAX); // or rdx,rax
+ }
+ }
+ else
+ emit_test_r64_r64(dst, REG_RAX, REG_RAX); // test rax,rax
+
+ // we rely on the fact that OF is cleared by all logical operations above
+ if (vflag)
+ {
+ emit_pushf(dst); // pushf
+ emit_pop_r64(dst, REG_RAX); // pop rax
+ emit_and_m64_imm(dst, MBD(REG_RSP, 0), ~0x84); // and [rsp],~0x84
+ emit_or_m64_r64(dst, MBD(REG_RSP, 0), REG_RAX); // or [rsp],rax
+ emit_popf(dst); // popf
+ }
+ }
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// op_divu - process a DIVU opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_divu(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_V | FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter edstp(*this, inst.param(1), PTYPE_MR);
+ be_parameter src1p(*this, inst.param(2), PTYPE_MRI);
+ be_parameter src2p(*this, inst.param(3), PTYPE_MRI);
+ bool compute_rem = (dstp != edstp);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // general case
+ emit_mov_r32_p32(dst, REG_ECX, src2p); // mov ecx,src2p
+ if (inst.flags() != 0)
+ {
+ emit_mov_r32_imm(dst, REG_EAX, 0xa0000000); // mov eax,0xa0000000
+ emit_add_r32_r32(dst, REG_EAX, REG_EAX); // add eax,eax
+ }
+ emit_link skip;
+ emit_jecxz_link(dst, skip); // jecxz skip
+ emit_mov_r32_p32(dst, REG_EAX, src1p); // mov eax,src1p
+ emit_xor_r32_r32(dst, REG_EDX, REG_EDX); // xor edx,edx
+ emit_div_r32(dst, REG_ECX); // div ecx
+ emit_mov_p32_r32(dst, dstp, REG_EAX); // mov dstp,eax
+ if (compute_rem)
+ emit_mov_p32_r32(dst, edstp, REG_EDX); // mov edstp,edx
+ if (inst.flags() != 0)
+ emit_test_r32_r32(dst, REG_EAX, REG_EAX); // test eax,eax
+ resolve_link(dst, skip); // skip:
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // general case
+ emit_mov_r64_p64(dst, REG_RCX, src2p); // mov rcx,src2p
+ if (inst.flags() != 0)
+ {
+ emit_mov_r32_imm(dst, REG_EAX, 0xa0000000); // mov eax,0xa0000000
+ emit_add_r32_r32(dst, REG_EAX, REG_EAX); // add eax,eax
+ }
+ emit_link skip;
+ emit_jrcxz_link(dst, skip); // jrcxz skip
+ emit_mov_r64_p64(dst, REG_RAX, src1p); // mov rax,src1p
+ emit_xor_r32_r32(dst, REG_EDX, REG_EDX); // xor edx,edx
+ emit_div_r64(dst, REG_RCX); // div rcx
+ emit_mov_p64_r64(dst, dstp, REG_RAX); // mov dstp,rax
+ if (compute_rem)
+ emit_mov_p64_r64(dst, edstp, REG_RDX); // mov edstp,rdx
+ if (inst.flags() != 0)
+ emit_test_r64_r64(dst, REG_RAX, REG_RAX); // test eax,eax
+ resolve_link(dst, skip); // skip:
+ }
+}
+
+
+//-------------------------------------------------
+// op_divs - process a DIVS opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_divs(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_V | FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter edstp(*this, inst.param(1), PTYPE_MR);
+ be_parameter src1p(*this, inst.param(2), PTYPE_MRI);
+ be_parameter src2p(*this, inst.param(3), PTYPE_MRI);
+ bool compute_rem = (dstp != edstp);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // general case
+ emit_mov_r32_p32(dst, REG_ECX, src2p); // mov ecx,src2p
+ if (inst.flags() != 0)
+ {
+ emit_mov_r32_imm(dst, REG_EAX, 0xa0000000); // mov eax,0xa0000000
+ emit_add_r32_r32(dst, REG_EAX, REG_EAX); // add eax,eax
+ }
+ emit_link skip;
+ emit_jecxz_link(dst, skip); // jecxz skip
+ emit_mov_r32_p32(dst, REG_EAX, src1p); // mov eax,src1p
+ emit_cdq(dst); // cdq
+ emit_idiv_r32(dst, REG_ECX); // idiv ecx
+ emit_mov_p32_r32(dst, dstp, REG_EAX); // mov dstp,eax
+ if (compute_rem)
+ emit_mov_p32_r32(dst, edstp, REG_EDX); // mov edstp,edx
+ if (inst.flags() != 0)
+ emit_test_r32_r32(dst, REG_EAX, REG_EAX); // test eax,eax
+ resolve_link(dst, skip); // skip:
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // general case
+ emit_mov_r64_p64(dst, REG_RCX, src2p); // mov rcx,src2p
+ if (inst.flags() != 0)
+ {
+ emit_mov_r32_imm(dst, REG_EAX, 0xa0000000); // mov eax,0xa0000000
+ emit_add_r32_r32(dst, REG_EAX, REG_EAX); // add eax,eax
+ }
+ emit_link skip;
+ emit_jrcxz_link(dst, skip); // jrcxz skip
+ emit_mov_r64_p64(dst, REG_RAX, src1p); // mov rax,src1p
+ emit_cqo(dst); // cqo
+ emit_idiv_r64(dst, REG_RCX); // idiv rcx
+ emit_mov_p64_r64(dst, dstp, REG_RAX); // mov dstp,rax
+ if (compute_rem)
+ emit_mov_p64_r64(dst, edstp, REG_RDX); // mov edstp,rdx
+ if (inst.flags() != 0)
+ emit_test_r64_r64(dst, REG_RAX, REG_RAX); // test eax,eax
+ resolve_link(dst, skip); // skip:
+ }
+}
+
+
+//-------------------------------------------------
+// op_and - process a AND opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_and(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
+ be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
+ normalize_commutative(src1p, src2p);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX, src2p);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_and_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // and [dstp],src2p
+
+ // AND with immediate 0xff
+ else if (src2p.is_immediate_value(0xff) && inst.flags() == 0)
+ {
+ if (src1p.is_int_register())
+ emit_movzx_r32_r8(dst, dstreg, src1p.ireg()); // movzx dstreg,src1p
+ else if (src1p.is_memory())
+ emit_movzx_r32_m8(dst, dstreg, MABS(src1p.memory())); // movzx dstreg,[src1p]
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+
+ // AND with immediate 0xffff
+ else if (src2p.is_immediate_value(0xffff) && inst.flags() == 0)
+ {
+ if (src1p.is_int_register())
+ emit_movzx_r32_r16(dst, dstreg, src1p.ireg()); // movzx dstreg,src1p
+ else if (src1p.is_memory())
+ emit_movzx_r32_m16(dst, dstreg, MABS(src1p.memory())); // movzx dstreg,[src1p]
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+
+ // general case
+ else
+ {
+ emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_and_r32_p32(dst, dstreg, src2p, inst); // and dstreg,src2p
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_and_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // and [dstp],src2p
+
+ // AND with immediate 0xff
+ else if (src2p.is_immediate_value(0xff) && inst.flags() == 0)
+ {
+ if (src1p.is_int_register())
+ emit_movzx_r32_r8(dst, dstreg, src1p.ireg()); // movzx dstreg,src1p
+ else if (src1p.is_memory())
+ emit_movzx_r32_m8(dst, dstreg, MABS(src1p.memory())); // movzx dstreg,[src1p]
+ emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+
+ // AND with immediate 0xffff
+ else if (src2p.is_immediate_value(0xffff) && inst.flags() == 0)
+ {
+ if (src1p.is_int_register())
+ emit_movzx_r32_r16(dst, dstreg, src1p.ireg()); // movzx dstreg,src1p
+ else if (src1p.is_memory())
+ emit_movzx_r32_m16(dst, dstreg, MABS(src1p.memory())); // movzx dstreg,[src1p]
+ emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+
+ // AND with immediate 0xffffffff
+ else if (src2p.is_immediate_value(0xffffffff) && inst.flags() == 0)
+ {
+ if (dstp.is_int_register() && src1p == dstp)
+ emit_mov_r32_r32(dst, dstreg, dstreg); // mov dstreg,dstreg
+ else
+ {
+ emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+
+ // general case
+ else
+ {
+ emit_mov_r64_p64(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_and_r64_p64(dst, dstreg, src2p, inst); // and dstreg,src2p
+ emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// op_test - process a TEST opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_test(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter src1p(*this, inst.param(0), PTYPE_MRI);
+ be_parameter src2p(*this, inst.param(1), PTYPE_MRI);
+ normalize_commutative(src1p, src2p);
+
+ // pick a target register for the general case
+ int src1reg = src1p.select_register(REG_EAX);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // src1p in memory
+ if (src1p.is_memory())
+ emit_test_m32_p32(dst, MABS(src1p.memory()), src2p, inst); // test [src1p],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r32_p32(dst, src1reg, src1p); // mov src1reg,src1p
+ emit_test_r32_p32(dst, src1reg, src2p, inst); // test src1reg,src2p
+ }
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // src1p in memory
+ if (src1p.is_memory())
+ emit_test_m64_p64(dst, MABS(src1p.memory()), src2p, inst); // test [src1p],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r64_p64(dst, src1reg, src1p); // mov src1reg,src1p
+ emit_test_r64_p64(dst, src1reg, src2p, inst); // test src1reg,src2p
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// op_or - process a OR opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_or(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
+ be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
+ normalize_commutative(src1p, src2p);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX, src2p);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_or_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // or [dstp],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_or_r32_p32(dst, dstreg, src2p, inst); // or dstreg,src2p
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_or_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // or [dstp],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r64_p64(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_or_r64_p64(dst, dstreg, src2p, inst); // or dstreg,src2p
+ emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// op_xor - process a XOR opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_xor(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
+ be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
+ normalize_commutative(src1p, src2p);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX, src2p);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_xor_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // xor [dstp],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_xor_r32_p32(dst, dstreg, src2p, inst); // xor dstreg,src2p
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_xor_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // xor [dstp],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r64_p64(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_xor_r64_p64(dst, dstreg, src2p, inst); // xor dstreg,src2p
+ emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// op_lzcnt - process a LZCNT opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_lzcnt(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter srcp(*this, inst.param(1), PTYPE_MRI);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ emit_mov_r32_p32(dst, dstreg, srcp); // mov dstreg,src1p
+ emit_mov_r32_imm(dst, REG_ECX, 32 ^ 31); // mov ecx,32 ^ 31
+ emit_bsr_r32_r32(dst, dstreg, dstreg); // bsr dstreg,dstreg
+ emit_cmovcc_r32_r32(dst, x64emit::COND_Z, dstreg, REG_ECX); // cmovz dstreg,ecx
+ emit_xor_r32_imm(dst, dstreg, 31); // xor dstreg,31
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ emit_mov_r64_p64(dst, dstreg, srcp); // mov dstreg,src1p
+ emit_mov_r64_imm(dst, REG_RCX, 64 ^ 63); // mov rcx,64 ^ 63
+ emit_bsr_r64_r64(dst, dstreg, dstreg); // bsr dstreg,dstreg
+ emit_cmovcc_r64_r64(dst, x64emit::COND_Z, dstreg, REG_RCX); // cmovz dstreg,rcx
+ emit_xor_r32_imm(dst, dstreg, 63); // xor dstreg,63
+ emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+}
+
+
+//-------------------------------------------------
+// op_bswap - process a BSWAP opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_bswap(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter srcp(*this, inst.param(1), PTYPE_MRI);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_RAX);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ emit_mov_r32_p32(dst, dstreg, srcp); // mov dstreg,src1p
+ emit_bswap_r32(dst, dstreg); // bswap dstreg
+ if (inst.flags() != 0)
+ emit_test_r32_r32(dst, dstreg, dstreg); // test dstreg,dstreg
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ emit_mov_r64_p64(dst, dstreg, srcp); // mov dstreg,src1p
+ emit_bswap_r64(dst, dstreg); // bswap dstreg
+ if (inst.flags() != 0)
+ emit_test_r64_r64(dst, dstreg, dstreg); // test dstreg,dstreg
+ emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+}
+
+
+//-------------------------------------------------
+// op_shl - process a SHL opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_shl(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_C | FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
+ be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX, src2p);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_shl_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // shl [dstp],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_shl_r32_p32(dst, dstreg, src2p, inst); // shl dstreg,src2p
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_shl_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // shl [dstp],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r64_p64(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_shl_r64_p64(dst, dstreg, src2p, inst); // shl dstreg,src2p
+ emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// op_shr - process a SHR opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_shr(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_C | FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
+ be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX, src2p);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_shr_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // shr [dstp],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_shr_r32_p32(dst, dstreg, src2p, inst); // shr dstreg,src2p
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_shr_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // shr [dstp],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r64_p64(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_shr_r64_p64(dst, dstreg, src2p, inst); // shr dstreg,src2p
+ emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// op_sar - process a SAR opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_sar(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_C | FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
+ be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX, src2p);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_sar_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // sar [dstp],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_sar_r32_p32(dst, dstreg, src2p, inst); // sar dstreg,src2p
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_sar_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // sar [dstp],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r64_p64(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_sar_r64_p64(dst, dstreg, src2p, inst); // sar dstreg,src2p
+ emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// op_rol - process a rol opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_rol(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_C | FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
+ be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX, src2p);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_rol_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // rol [dstp],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_rol_r32_p32(dst, dstreg, src2p, inst); // rol dstreg,src2p
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_rol_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // rol [dstp],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r64_p64(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_rol_r64_p64(dst, dstreg, src2p, inst); // rol dstreg,src2p
+ emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// op_ror - process a ROR opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_ror(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_C | FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
+ be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX, src2p);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_ror_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // ror [dstp],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_ror_r32_p32(dst, dstreg, src2p, inst); // ror dstreg,src2p
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_ror_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // ror [dstp],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r64_p64(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_ror_r64_p64(dst, dstreg, src2p, inst); // ror dstreg,src2p
+ emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// op_rolc - process a ROLC opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_rolc(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_C | FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
+ be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX, src2p);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_rcl_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // rcl [dstp],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r32_p32_keepflags(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_rcl_r32_p32(dst, dstreg, src2p, inst); // rcl dstreg,src2p
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_rcl_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // rcl [dstp],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r64_p64_keepflags(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_rcl_r64_p64(dst, dstreg, src2p, inst); // rcl dstreg,src2p
+ emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// op_rorc - process a RORC opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_rorc(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_C | FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
+ be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX, src2p);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_rcr_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // rcr [dstp],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r32_p32_keepflags(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_rcr_r32_p32(dst, dstreg, src2p, inst); // rcr dstreg,src2p
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_rcr_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // rcr [dstp],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r64_p64_keepflags(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_rcr_r64_p64(dst, dstreg, src2p, inst); // rcr dstreg,src2p
+ emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+}
+
+
+
+/***************************************************************************
+ FLOATING POINT OPERATIONS
+***************************************************************************/
+
+//-------------------------------------------------
+// op_fload - process a FLOAD opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_fload(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MF);
+ be_parameter basep(*this, inst.param(1), PTYPE_M);
+ be_parameter indp(*this, inst.param(2), PTYPE_MRI);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_XMM0);
+
+ // determine the pointer base
+ INT32 baseoffs;
+ int basereg = get_base_register_and_offset(dst, basep.memory(), REG_RDX, baseoffs);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ if (indp.is_immediate())
+ emit_movss_r128_m32(dst, dstreg, MBD(basereg, baseoffs + 4*indp.immediate())); // movss dstreg,[basep + 4*indp]
+ else
+ {
+ int indreg = indp.select_register(REG_ECX);
+ emit_mov_r32_p32(dst, indreg, indp); // mov indreg,indp
+ emit_movss_r128_m32(dst, dstreg, MBISD(basereg, indreg, 4, baseoffs)); // movss dstreg,[basep + 4*indp]
+ }
+ emit_movss_p32_r128(dst, dstp, dstreg); // movss dstp,dstreg
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ if (indp.is_immediate())
+ emit_movsd_r128_m64(dst, dstreg, MBD(basereg, baseoffs + 8*indp.immediate())); // movsd dstreg,[basep + 8*indp]
+ else
+ {
+ int indreg = indp.select_register(REG_ECX);
+ emit_mov_r32_p32(dst, indreg, indp); // mov indreg,indp
+ emit_movsd_r128_m64(dst, dstreg, MBISD(basereg, indreg, 8, baseoffs)); // movsd dstreg,[basep + 8*indp]
+ }
+ emit_movsd_p64_r128(dst, dstp, dstreg); // movsd dstp,dstreg
+ }
+}
+
+
+//-------------------------------------------------
+// op_fstore - process a FSTORE opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_fstore(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter basep(*this, inst.param(0), PTYPE_M);
+ be_parameter indp(*this, inst.param(1), PTYPE_MRI);
+ be_parameter srcp(*this, inst.param(2), PTYPE_MF);
+
+ // pick a target register for the general case
+ int srcreg = srcp.select_register(REG_XMM0);
+
+ // determine the pointer base
+ INT32 baseoffs;
+ int basereg = get_base_register_and_offset(dst, basep.memory(), REG_RDX, baseoffs);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ emit_movss_r128_p32(dst, srcreg, srcp); // movss srcreg,srcp
+ if (indp.is_immediate())
+ emit_movss_m32_r128(dst, MBD(basereg, baseoffs + 4*indp.immediate()), srcreg); // movss [basep + 4*indp],srcreg
+ else
+ {
+ int indreg = indp.select_register(REG_ECX);
+ emit_mov_r32_p32(dst, indreg, indp); // mov indreg,indp
+ emit_movss_m32_r128(dst, MBISD(basereg, indreg, 4, baseoffs), srcreg); // movss [basep + 4*indp],srcreg
+ }
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ emit_movsd_r128_p64(dst, srcreg, srcp); // movsd srcreg,srcp
+ if (indp.is_immediate())
+ emit_movsd_m64_r128(dst, MBD(basereg, baseoffs + 8*indp.immediate()), srcreg); // movsd [basep + 8*indp],srcreg
+ else
+ {
+ int indreg = indp.select_register(REG_ECX);
+ emit_mov_r32_p32(dst, indreg, indp); // mov indreg,indp
+ emit_movsd_m64_r128(dst, MBISD(basereg, indreg, 8, baseoffs), srcreg); // movsd [basep + 8*indp],srcreg
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// op_fread - process a FREAD opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_fread(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MF);
+ be_parameter addrp(*this, inst.param(1), PTYPE_MRI);
+ const parameter &spacep = inst.param(2);
+ assert(spacep.is_size_space());
+ assert((1 << spacep.size()) == inst.size());
+
+ // set up a call to the read dword/qword handler
+ emit_mov_r64_imm(dst, REG_PARAM1, (FPTR)(m_space[spacep.space()])); // mov param1,space
+ emit_mov_r32_p32(dst, REG_PARAM2, addrp); // mov param2,addrp
+ if (inst.size() == 4)
+ emit_smart_call_m64(dst, (x86code **)&m_accessors[spacep.space()].read_dword); // call read_dword
+ else if (inst.size() == 8)
+ emit_smart_call_m64(dst, (x86code **)&m_accessors[spacep.space()].read_qword); // call read_qword
+
+ // store result
+ if (inst.size() == 4)
+ {
+ if (dstp.is_memory())
+ emit_mov_m32_r32(dst, MABS(dstp.memory()), REG_EAX); // mov [dstp],eax
+ else if (dstp.is_float_register())
+ emit_movd_r128_r32(dst, dstp.freg(), REG_EAX); // movd dstp,eax
+ }
+ else if (inst.size() == 8)
+ {
+ if (dstp.is_memory())
+ emit_mov_m64_r64(dst, MABS(dstp.memory()), REG_RAX); // mov [dstp],rax
+ else if (dstp.is_float_register())
+ emit_movq_r128_r64(dst, dstp.freg(), REG_RAX); // movq dstp,rax
+ }
+}
+
+
+//-------------------------------------------------
+// op_fwrite - process a FWRITE opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_fwrite(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter addrp(*this, inst.param(0), PTYPE_MRI);
+ be_parameter srcp(*this, inst.param(1), PTYPE_MF);
+ const parameter &spacep = inst.param(2);
+ assert(spacep.is_size_space());
+ assert((1 << spacep.size()) == inst.size());
+
+ // general case
+ emit_mov_r64_imm(dst, REG_PARAM1, (FPTR)(m_space[spacep.space()])); // mov param1,space
+ emit_mov_r32_p32(dst, REG_PARAM2, addrp); // mov param21,addrp
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ if (srcp.is_memory())
+ emit_mov_r32_m32(dst, REG_PARAM3, MABS(srcp.memory())); // mov param3,[srcp]
+ else if (srcp.is_float_register())
+ emit_movd_r32_r128(dst, REG_PARAM3, srcp.freg()); // movd param3,srcp
+ emit_smart_call_m64(dst, (x86code **)&m_accessors[spacep.space()].write_dword); // call write_dword
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ if (srcp.is_memory())
+ emit_mov_r64_m64(dst, REG_PARAM3, MABS(srcp.memory())); // mov param3,[srcp]
+ else if (srcp.is_float_register())
+ emit_movq_r64_r128(dst, REG_PARAM3, srcp.freg()); // movq param3,srcp
+ emit_smart_call_m64(dst, (x86code **)&m_accessors[spacep.space()].write_qword); // call write_qword
+ }
+}
+
+
+//-------------------------------------------------
+// op_fmov - process a FMOV opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_fmov(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_any_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MF);
+ be_parameter srcp(*this, inst.param(1), PTYPE_MF);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_XMM0);
+
+ // always start with a jmp
+ emit_link skip = { 0 };
+ if (inst.condition() != uml::COND_ALWAYS)
+ emit_jcc_short_link(dst, X86_NOT_CONDITION(inst.condition()), skip); // jcc skip
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ emit_movss_r128_p32(dst, dstreg, srcp); // movss dstreg,srcp
+ emit_movss_p32_r128(dst, dstp, dstreg); // movss dstp,dstreg
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ emit_movsd_r128_p64(dst, dstreg, srcp); // movsd dstreg,srcp
+ emit_movsd_p64_r128(dst, dstp, dstreg); // movsd dstp,dstreg
+ }
+
+ // resolve the jump
+ if (inst.condition() != uml::COND_ALWAYS)
+ resolve_link(dst, skip); // skip:
+}
+
+
+//-------------------------------------------------
+// op_ftoint - process a FTOINT opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_ftoint(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter srcp(*this, inst.param(1), PTYPE_MF);
+ const parameter &sizep = inst.param(2);
+ assert(sizep.is_size());
+ const parameter &roundp = inst.param(3);
+ assert(roundp.is_rounding());
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX);
+
+ // set rounding mode if necessary
+ if (roundp.rounding() != ROUND_DEFAULT && roundp.rounding() != ROUND_TRUNC)
+ {
+ emit_stmxcsr_m32(dst, MABS(&m_near.ssemodesave)); // stmxcsr [ssemodesave]
+ emit_ldmxcsr_m32(dst, MABS(&m_near.ssecontrol[roundp.rounding()])); // ldmxcsr fpcontrol[mode]
+ }
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // 32-bit integer source
+ if (sizep.size() == SIZE_DWORD)
+ {
+ if (srcp.is_memory())
+ {
+ if (roundp.rounding() != ROUND_TRUNC)
+ emit_cvtss2si_r32_m32(dst, dstreg, MABS(srcp.memory())); // cvtss2si dstreg,[srcp]
+ else
+ emit_cvttss2si_r32_m32(dst, dstreg, MABS(srcp.memory())); // cvttss2si dstreg,[srcp]
+ }
+ else if (srcp.is_float_register())
+ {
+ if (roundp.rounding() != ROUND_TRUNC)
+ emit_cvtss2si_r32_r128(dst, dstreg, srcp.freg()); // cvtss2si dstreg,srcp
+ else
+ emit_cvttss2si_r32_r128(dst, dstreg, srcp.freg()); // cvttss2si dstreg,srcp
+ }
+ }
+
+ // 64-bit integer source
+ else if (sizep.size() == SIZE_QWORD)
+ {
+ if (srcp.is_memory())
+ {
+ if (roundp.rounding() != ROUND_TRUNC)
+ emit_cvtss2si_r64_m32(dst, dstreg, MABS(srcp.memory())); // cvtss2si dstreg,[srcp]
+ else
+ emit_cvttss2si_r64_m32(dst, dstreg, MABS(srcp.memory())); // cvttss2si dstreg,[srcp]
+ }
+ else if (srcp.is_float_register())
+ {
+ if (roundp.rounding() != ROUND_TRUNC)
+ emit_cvtss2si_r64_r128(dst, dstreg, srcp.freg()); // cvtss2si dstreg,srcp
+ else
+ emit_cvttss2si_r64_r128(dst, dstreg, srcp.freg()); // cvttss2si dstreg,srcp
+ }
+ }
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // 32-bit integer source
+ if (sizep.size() == SIZE_DWORD)
+ {
+ if (srcp.is_memory())
+ {
+ if (roundp.rounding() != ROUND_TRUNC)
+ emit_cvtsd2si_r32_m64(dst, dstreg, MABS(srcp.memory())); // cvtsd2si dstreg,[srcp]
+ else
+ emit_cvttsd2si_r32_m64(dst, dstreg, MABS(srcp.memory())); // cvttsd2si dstreg,[srcp]
+ }
+ else if (srcp.is_float_register())
+ {
+ if (roundp.rounding() != ROUND_TRUNC)
+ emit_cvtsd2si_r32_r128(dst, dstreg, srcp.freg()); // cvtsd2si dstreg,srcp
+ else
+ emit_cvttsd2si_r32_r128(dst, dstreg, srcp.freg()); // cvttsd2si dstreg,srcp
+ }
+ }
+
+ // 64-bit integer source
+ else if (sizep.size() == SIZE_QWORD)
+ {
+ if (srcp.is_memory())
+ {
+ if (roundp.rounding() != ROUND_TRUNC)
+ emit_cvtsd2si_r64_m64(dst, dstreg, MABS(srcp.memory())); // cvtsd2si dstreg,[srcp]
+ else
+ emit_cvttsd2si_r64_m64(dst, dstreg, MABS(srcp.memory())); // cvttsd2si dstreg,[srcp]
+ }
+ else if (srcp.is_float_register())
+ {
+ if (roundp.rounding() != ROUND_TRUNC)
+ emit_cvtsd2si_r64_r128(dst, dstreg, srcp.freg()); // cvtsd2si dstreg,srcp
+ else
+ emit_cvttsd2si_r64_r128(dst, dstreg, srcp.freg()); // cvttsd2si dstreg,srcp
+ }
+ }
+ }
+
+ // general case
+ if (sizep.size() == SIZE_DWORD)
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ else
+ emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg
+
+ // restore rounding mode
+ if (roundp.rounding() != ROUND_DEFAULT && roundp.rounding() != ROUND_TRUNC)
+ emit_ldmxcsr_m32(dst, MABS(&m_near.ssemodesave)); // ldmxcsr [ssemodesave]
+}
+
+
+//-------------------------------------------------
+// op_ffrint - process a FFRINT opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_ffrint(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MF);
+ be_parameter srcp(*this, inst.param(1), PTYPE_MRI);
+ const parameter &sizep = inst.param(2);
+ assert(sizep.is_size());
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_XMM0);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // 32-bit integer source
+ if (sizep.size() == SIZE_DWORD)
+ {
+ if (srcp.is_memory())
+ emit_cvtsi2ss_r128_m32(dst, dstreg, MABS(srcp.memory())); // cvtsi2ss dstreg,[srcp]
+ else
+ {
+ int srcreg = srcp.select_register(REG_EAX);
+ emit_mov_r32_p32(dst, srcreg, srcp); // mov srcreg,srcp
+ emit_cvtsi2ss_r128_r32(dst, dstreg, srcreg); // cvtsi2ss dstreg,srcreg
+ }
+ }
+
+ // 64-bit integer source
+ else
+ {
+ if (srcp.is_memory())
+ emit_cvtsi2ss_r128_m64(dst, dstreg, MABS(srcp.memory())); // cvtsi2ss dstreg,[srcp]
+ else
+ {
+ int srcreg = srcp.select_register(REG_RAX);
+ emit_mov_r64_p64(dst, srcreg, srcp); // mov srcreg,srcp
+ emit_cvtsi2ss_r128_r64(dst, dstreg, srcreg); // cvtsi2ss dstreg,srcreg
+ }
+ }
+ emit_movss_p32_r128(dst, dstp, dstreg); // movss dstp,dstreg
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // 32-bit integer source
+ if (sizep.size() == SIZE_DWORD)
+ {
+ if (srcp.is_memory())
+ emit_cvtsi2sd_r128_m32(dst, dstreg, MABS(srcp.memory())); // cvtsi2sd dstreg,[srcp]
+ else
+ {
+ int srcreg = srcp.select_register(REG_EAX);
+ emit_mov_r32_p32(dst, srcreg, srcp); // mov srcreg,srcp
+ emit_cvtsi2sd_r128_r32(dst, dstreg, srcreg); // cvtsi2sd dstreg,srcreg
+ }
+ }
+
+ // 64-bit integer source
+ else
+ {
+ if (srcp.is_memory())
+ emit_cvtsi2sd_r128_m64(dst, dstreg, MABS(srcp.memory())); // cvtsi2sd dstreg,[srcp]
+ else
+ {
+ int srcreg = srcp.select_register(REG_EAX);
+ emit_mov_r64_p64(dst, srcreg, srcp); // mov srcreg,srcp
+ emit_cvtsi2sd_r128_r64(dst, dstreg, srcreg); // cvtsi2sd dstreg,srcreg
+ }
+ }
+ emit_movsd_p64_r128(dst, dstp, dstreg); // movsd dstp,dstreg
+ }
+}
+
+
+//-------------------------------------------------
+// op_ffrflt - process a FFRFLT opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_ffrflt(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MF);
+ be_parameter srcp(*this, inst.param(1), PTYPE_MF);
+ const parameter &sizep = inst.param(2);
+ assert(sizep.is_size());
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_XMM0);
+
+ // single-to-double
+ if (inst.size() == 8 && sizep.size() == SIZE_DWORD)
+ {
+ if (srcp.is_memory())
+ emit_cvtss2sd_r128_m32(dst, dstreg, MABS(srcp.memory())); // cvtss2sd dstreg,[srcp]
+ else if (srcp.is_float_register())
+ emit_cvtss2sd_r128_r128(dst, dstreg, srcp.freg()); // cvtss2sd dstreg,srcp
+ emit_movsd_p64_r128(dst, dstp, dstreg); // movsd dstp,dstreg
+ }
+
+ // double-to-single
+ else if (inst.size() == 4 && sizep.size() == SIZE_QWORD)
+ {
+ if (srcp.is_memory())
+ emit_cvtsd2ss_r128_m64(dst, dstreg, MABS(srcp.memory())); // cvtsd2ss dstreg,[srcp]
+ else if (srcp.is_float_register())
+ emit_cvtsd2ss_r128_r128(dst, dstreg, srcp.freg()); // cvtsd2ss dstreg,srcp
+ emit_movss_p32_r128(dst, dstp, dstreg); // movss dstp,dstreg
+ }
+}
+
+
+//-------------------------------------------------
+// op_frnds - process a FRNDS opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_frnds(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MF);
+ be_parameter srcp(*this, inst.param(1), PTYPE_MF);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_XMM0);
+
+ // 64-bit form
+ if (srcp.is_memory())
+ emit_cvtsd2ss_r128_m64(dst, dstreg, MABS(srcp.memory())); // cvtsd2ss dstreg,[srcp]
+ else if (srcp.is_float_register())
+ emit_cvtsd2ss_r128_r128(dst, dstreg, srcp.freg()); // cvtsd2ss dstreg,srcp
+ emit_cvtss2sd_r128_r128(dst, dstreg, dstreg); // cvtss2sd dstreg,dstreg
+ emit_movsd_p64_r128(dst, dstp, dstreg); // movsd dstp,dstreg
+}
+
+
+//-------------------------------------------------
+// op_fadd - process a FADD opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_fadd(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MF);
+ be_parameter src1p(*this, inst.param(1), PTYPE_MF);
+ be_parameter src2p(*this, inst.param(2), PTYPE_MF);
+ normalize_commutative(src1p, src2p);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_XMM0, src2p);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ emit_movss_r128_p32(dst, dstreg, src1p); // movss dstreg,src1p
+ if (src2p.is_memory())
+ emit_addss_r128_m32(dst, dstreg, MABS(src2p.memory())); // addss dstreg,[src2p]
+ else if (src2p.is_float_register())
+ emit_addss_r128_r128(dst, dstreg, src2p.freg()); // addss dstreg,src2p
+ emit_movss_p32_r128(dst, dstp, dstreg); // movss dstp,dstreg
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ emit_movsd_r128_p64(dst, dstreg, src1p); // movsd dstreg,src1p
+ if (src2p.is_memory())
+ emit_addsd_r128_m64(dst, dstreg, MABS(src2p.memory())); // addsd dstreg,[src2p]
+ else if (src2p.is_float_register())
+ emit_addsd_r128_r128(dst, dstreg, src2p.freg()); // addsd dstreg,src2p
+ emit_movsd_p64_r128(dst, dstp, dstreg); // movsd dstp,dstreg
+ }
+}
+
+
+//-------------------------------------------------
+// op_fsub - process a FSUB opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_fsub(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MF);
+ be_parameter src1p(*this, inst.param(1), PTYPE_MF);
+ be_parameter src2p(*this, inst.param(2), PTYPE_MF);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_XMM0, src2p);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ emit_movss_r128_p32(dst, dstreg, src1p); // movss dstreg,src1p
+ if (src2p.is_memory())
+ emit_subss_r128_m32(dst, dstreg, MABS(src2p.memory())); // subss dstreg,[src2p]
+ else if (src2p.is_float_register())
+ emit_subss_r128_r128(dst, dstreg, src2p.freg()); // subss dstreg,src2p
+ emit_movss_p32_r128(dst, dstp, dstreg); // movss dstp,dstreg
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ emit_movsd_r128_p64(dst, dstreg, src1p); // movsd dstreg,src1p
+ if (src2p.is_memory())
+ emit_subsd_r128_m64(dst, dstreg, MABS(src2p.memory())); // subsd dstreg,[src2p]
+ else if (src2p.is_float_register())
+ emit_subsd_r128_r128(dst, dstreg, src2p.freg()); // subsd dstreg,src2p
+ emit_movsd_p64_r128(dst, dstp, dstreg); // movsd dstp,dstreg
+ }
+}
+
+
+//-------------------------------------------------
+// op_fcmp - process a FCMP opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_fcmp(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_C | FLAG_Z | FLAG_U);
+
+ // normalize parameters
+ be_parameter src1p(*this, inst.param(0), PTYPE_MF);
+ be_parameter src2p(*this, inst.param(1), PTYPE_MF);
+
+ // pick a target register for the general case
+ int src1reg = src1p.select_register(REG_XMM0);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ emit_movss_r128_p32(dst, src1reg, src1p); // movss src1reg,src1p
+ if (src2p.is_memory())
+ emit_comiss_r128_m32(dst, src1reg, MABS(src2p.memory())); // comiss src1reg,[src2p]
+ else if (src2p.is_float_register())
+ emit_comiss_r128_r128(dst, src1reg, src2p.freg()); // comiss src1reg,src2p
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ emit_movsd_r128_p64(dst, src1reg, src1p); // movsd src1reg,src1p
+ if (src2p.is_memory())
+ emit_comisd_r128_m64(dst, src1reg, MABS(src2p.memory())); // comisd src1reg,[src2p]
+ else if (src2p.is_float_register())
+ emit_comisd_r128_r128(dst, src1reg, src2p.freg()); // comisd src1reg,src2p
+ }
+}
+
+
+//-------------------------------------------------
+// op_fmul - process a FMUL opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_fmul(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MF);
+ be_parameter src1p(*this, inst.param(1), PTYPE_MF);
+ be_parameter src2p(*this, inst.param(2), PTYPE_MF);
+ normalize_commutative(src1p, src2p);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_XMM0, src2p);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ emit_movss_r128_p32(dst, dstreg, src1p); // movss dstreg,src1p
+ if (src2p.is_memory())
+ emit_mulss_r128_m32(dst, dstreg, MABS(src2p.memory())); // mulss dstreg,[src2p]
+ else if (src2p.is_float_register())
+ emit_mulss_r128_r128(dst, dstreg, src2p.freg()); // mulss dstreg,src2p
+ emit_movss_p32_r128(dst, dstp, dstreg); // movss dstp,dstreg
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ emit_movsd_r128_p64(dst, dstreg, src1p); // movsd dstreg,src1p
+ if (src2p.is_memory())
+ emit_mulsd_r128_m64(dst, dstreg, MABS(src2p.memory())); // mulsd dstreg,[src2p]
+ else if (src2p.is_float_register())
+ emit_mulsd_r128_r128(dst, dstreg, src2p.freg()); // mulsd dstreg,src2p
+ emit_movsd_p64_r128(dst, dstp, dstreg); // movsd dstp,dstreg
+ }
+}
+
+
+//-------------------------------------------------
+// op_fdiv - process a FDIV opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_fdiv(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MF);
+ be_parameter src1p(*this, inst.param(1), PTYPE_MF);
+ be_parameter src2p(*this, inst.param(2), PTYPE_MF);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_XMM0, src2p);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ emit_movss_r128_p32(dst, dstreg, src1p); // movss dstreg,src1p
+ if (src2p.is_memory())
+ emit_divss_r128_m32(dst, dstreg, MABS(src2p.memory())); // divss dstreg,[src2p]
+ else if (src2p.is_float_register())
+ emit_divss_r128_r128(dst, dstreg, src2p.freg()); // divss dstreg,src2p
+ emit_movss_p32_r128(dst, dstp, dstreg); // movss dstp,dstreg
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ emit_movsd_r128_p64(dst, dstreg, src1p); // movsd dstreg,src1p
+ if (src2p.is_memory())
+ emit_divsd_r128_m64(dst, dstreg, MABS(src2p.memory())); // divsd dstreg,[src2p]
+ else if (src2p.is_float_register())
+ emit_divsd_r128_r128(dst, dstreg, src2p.freg()); // divsd dstreg,src2p
+ emit_movsd_p64_r128(dst, dstp, dstreg); // movsd dstp,dstreg
+ }
+}
+
+
+//-------------------------------------------------
+// op_fneg - process a FNEG opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_fneg(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MF);
+ be_parameter srcp(*this, inst.param(1), PTYPE_MF);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_XMM0, srcp);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ emit_xorps_r128_r128(dst, dstreg, dstreg); // xorps dstreg,dstreg
+ if (srcp.is_memory())
+ emit_subss_r128_m32(dst, dstreg, MABS(srcp.memory())); // subss dstreg,[srcp]
+ else if (srcp.is_float_register())
+ emit_subss_r128_r128(dst, dstreg, srcp.freg()); // subss dstreg,srcp
+ emit_movss_p32_r128(dst, dstp, dstreg); // movss dstp,dstreg
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ emit_xorpd_r128_r128(dst, dstreg, dstreg); // xorpd dstreg,dstreg
+ if (srcp.is_memory())
+ emit_subsd_r128_m64(dst, dstreg, MABS(srcp.memory())); // subsd dstreg,[srcp]
+ else if (srcp.is_float_register())
+ emit_subsd_r128_r128(dst, dstreg, srcp.freg()); // subsd dstreg,srcp
+ emit_movsd_p64_r128(dst, dstp, dstreg); // movsd dstp,dstreg
+ }
+}
+
+
+//-------------------------------------------------
+// op_fabs - process a FABS opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_fabs(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MF);
+ be_parameter srcp(*this, inst.param(1), PTYPE_MF);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_XMM0, srcp);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ emit_movss_r128_p32(dst, dstreg, srcp); // movss dstreg,srcp
+ emit_andps_r128_m128(dst, dstreg, MABS(m_absmask32)); // andps dstreg,[absmask32]
+ emit_movss_p32_r128(dst, dstp, dstreg); // movss dstp,dstreg
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ emit_movsd_r128_p64(dst, dstreg, srcp); // movsd dstreg,srcp
+ emit_andpd_r128_m128(dst, dstreg, MABS(m_absmask64)); // andpd dstreg,[absmask64]
+ emit_movsd_p64_r128(dst, dstp, dstreg); // movsd dstp,dstreg
+ }
+}
+
+
+//-------------------------------------------------
+// op_fsqrt - process a FSQRT opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_fsqrt(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MF);
+ be_parameter srcp(*this, inst.param(1), PTYPE_MF);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_XMM0);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ if (srcp.is_memory())
+ emit_sqrtss_r128_m32(dst, dstreg, MABS(srcp.memory())); // sqrtss dstreg,[srcp]
+ else if (srcp.is_float_register())
+ emit_sqrtss_r128_r128(dst, dstreg, srcp.freg()); // sqrtss dstreg,srcp
+ emit_movss_p32_r128(dst, dstp, dstreg); // movss dstp,dstreg
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ if (srcp.is_memory())
+ emit_sqrtsd_r128_m64(dst, dstreg, MABS(srcp.memory())); // sqrtsd dstreg,[srcp]
+ else if (srcp.is_float_register())
+ emit_sqrtsd_r128_r128(dst, dstreg, srcp.freg()); // sqrtsd dstreg,srcp
+ emit_movsd_p64_r128(dst, dstp, dstreg); // movsd dstp,dstreg
+ }
+}
+
+
+//-------------------------------------------------
+// op_frecip - process a FRECIP opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_frecip(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MF);
+ be_parameter srcp(*this, inst.param(1), PTYPE_MF);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_XMM0);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ if (USE_RCPSS_FOR_SINGLES)
+ {
+ if (srcp.is_memory())
+ emit_rcpss_r128_m32(dst, dstreg, MABS(srcp.memory())); // rcpss dstreg,[srcp]
+ else if (srcp.is_float_register())
+ emit_rcpss_r128_r128(dst, dstreg, srcp.freg()); // rcpss dstreg,srcp
+ emit_movss_p32_r128(dst, dstp, dstreg); // movss dstp,dstreg
+ }
+ else
+ {
+ emit_movss_r128_m32(dst, REG_XMM1, MABS(&m_near.single1)); // movss xmm1,1.0
+ if (srcp.is_memory())
+ emit_divss_r128_m32(dst, REG_XMM1, MABS(srcp.memory())); // divss xmm1,[srcp]
+ else if (srcp.is_float_register())
+ emit_divss_r128_r128(dst, REG_XMM1, srcp.freg()); // divss xmm1,srcp
+ emit_movss_p32_r128(dst, dstp, REG_XMM1); // movss dstp,xmm1
+ }
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ if (USE_RCPSS_FOR_DOUBLES)
+ {
+ if (srcp.is_memory())
+ emit_cvtsd2ss_r128_m64(dst, dstreg, MABS(srcp.memory())); // cvtsd2ss dstreg,[srcp]
+ else if (srcp.is_float_register())
+ emit_cvtsd2ss_r128_r128(dst, dstreg, srcp.freg()); // cvtsd2ss dstreg,srcp
+ emit_rcpss_r128_r128(dst, dstreg, dstreg); // rcpss dstreg,dstreg
+ emit_cvtss2sd_r128_r128(dst, dstreg, dstreg); // cvtss2sd dstreg,dstreg
+ emit_movsd_p64_r128(dst, dstp, REG_XMM1); // movsd dstp,dstreg
+ }
+ else
+ {
+ emit_movsd_r128_m64(dst, REG_XMM1, MABS(&m_near.double1)); // movsd xmm1,1.0
+ if (srcp.is_memory())
+ emit_divsd_r128_m64(dst, REG_XMM1, MABS(srcp.memory())); // divsd xmm1,[srcp]
+ else if (srcp.is_float_register())
+ emit_divsd_r128_r128(dst, REG_XMM1, srcp.freg()); // divsd xmm1,srcp
+ emit_movsd_p64_r128(dst, dstp, REG_XMM1); // movsd dstp,xmm1
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// op_frsqrt - process a FRSQRT opcode
+//-------------------------------------------------
+
+void drcbe_x64::op_frsqrt(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MF);
+ be_parameter srcp(*this, inst.param(1), PTYPE_MF);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_XMM0);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ if (USE_RSQRTSS_FOR_SINGLES)
+ {
+ if (srcp.is_memory())
+ emit_rsqrtss_r128_m32(dst, dstreg, MABS(srcp.memory())); // rsqrtss dstreg,[srcp]
+ else if (srcp.is_float_register())
+ emit_rsqrtss_r128_r128(dst, dstreg, srcp.freg()); // rsqrtss dstreg,srcp
+ }
+ else
+ {
+ if (srcp.is_memory())
+ emit_sqrtss_r128_m32(dst, REG_XMM1, MABS(srcp.memory())); // sqrtss xmm1,[srcp]
+ else if (srcp.is_float_register())
+ emit_sqrtss_r128_r128(dst, REG_XMM1, srcp.freg()); // sqrtss xmm1,srcp
+ emit_movss_r128_m32(dst, dstreg, MABS(&m_near.single1)); // movss dstreg,1.0
+ emit_divss_r128_r128(dst, dstreg, REG_XMM1); // divss dstreg,xmm1
+ }
+ emit_movss_p32_r128(dst, dstp, dstreg); // movss dstp,dstreg
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ if (USE_RSQRTSS_FOR_DOUBLES)
+ {
+ if (srcp.is_memory())
+ emit_cvtsd2ss_r128_m64(dst, dstreg, MABS(srcp.memory())); // cvtsd2ss dstreg,[srcp]
+ else if (srcp.is_float_register())
+ emit_cvtsd2ss_r128_r128(dst, dstreg, srcp.freg()); // cvtsd2ss dstreg,srcp
+ emit_rsqrtss_r128_r128(dst, dstreg, dstreg); // rsqrtss dstreg,dstreg
+ emit_cvtss2sd_r128_r128(dst, dstreg, dstreg); // cvtss2sd dstreg,dstreg
+ }
+ else
+ {
+ if (srcp.is_memory())
+ emit_sqrtsd_r128_m64(dst, REG_XMM1, MABS(srcp.memory())); // sqrtsd xmm1,[srcp]
+ else if (srcp.is_float_register())
+ emit_sqrtsd_r128_r128(dst, REG_XMM1, srcp.freg()); // sqrtsd xmm1,srcp
+ emit_movsd_r128_m64(dst, dstreg, MABS(&m_near.double1)); // movsd dstreg,1.0
+ emit_divsd_r128_r128(dst, dstreg, REG_XMM1); // divsd dstreg,xmm1
+ }
+ emit_movsd_p64_r128(dst, dstp, dstreg); // movsd dstp,dstreg
+ }
+}
diff --git a/trunk/src/emu/cpu/drcbex64.h b/trunk/src/emu/cpu/drcbex64.h
new file mode 100644
index 00000000000..13de4221f02
--- /dev/null
+++ b/trunk/src/emu/cpu/drcbex64.h
@@ -0,0 +1,373 @@
+/***************************************************************************
+
+ drcbex64.h
+
+ 64-bit x64 back-end for the universal machine language.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __DRCBEX64_H__
+#define __DRCBEX64_H__
+
+#include "drcuml.h"
+#include "drcbeut.h"
+#include "x86log.h"
+
+#define X86EMIT_SIZE 64
+#include "x86emit.h"
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class drcbe_x64 : public drcbe_interface
+{
+ typedef UINT32 (*x86_entry_point_func)(UINT8 *rbpvalue, x86code *entry);
+
+public:
+ // construction/destruction
+ drcbe_x64(drcuml_state &drcuml, device_t &device, drc_cache &cache, UINT32 flags, int modes, int addrbits, int ignorebits);
+ virtual ~drcbe_x64();
+
+ // required overrides
+ virtual void reset();
+ virtual int execute(uml::code_handle &entry);
+ virtual void generate(drcuml_block &block, const uml::instruction *instlist, UINT32 numinst);
+ virtual bool hash_exists(UINT32 mode, UINT32 pc);
+ virtual void get_info(drcbe_info &info);
+
+private:
+ // a be_parameter is similar to a uml::parameter but maps to native registers/memory
+ class be_parameter
+ {
+ public:
+ // parameter types
+ enum be_parameter_type
+ {
+ PTYPE_NONE = 0, // invalid
+ PTYPE_IMMEDIATE, // immediate; value = sign-extended to 64 bits
+ PTYPE_INT_REGISTER, // integer register; value = 0-REG_MAX
+ PTYPE_FLOAT_REGISTER, // floating point register; value = 0-REG_MAX
+ PTYPE_VECTOR_REGISTER, // vector register; value = 0-REG_MAX
+ PTYPE_MEMORY, // memory; value = pointer to memory
+ PTYPE_MAX
+ };
+
+ // represents the value of a parameter
+ typedef UINT64 be_parameter_value;
+
+ // construction
+ be_parameter() : m_type(PTYPE_NONE), m_value(0) { }
+ be_parameter(const be_parameter &param) : m_type(param.m_type), m_value(param.m_value) { }
+ be_parameter(UINT64 val) : m_type(PTYPE_IMMEDIATE), m_value(val) { }
+ be_parameter(drcbe_x64 &drcbe, const uml::parameter &param, UINT32 allowed);
+
+ // creators for types that don't safely default
+ static inline be_parameter make_ireg(int regnum) { assert(regnum >= 0 && regnum < x64emit::REG_MAX); return be_parameter(PTYPE_INT_REGISTER, regnum); }
+ static inline be_parameter make_freg(int regnum) { assert(regnum >= 0 && regnum < x64emit::REG_MAX); return be_parameter(PTYPE_FLOAT_REGISTER, regnum); }
+ static inline be_parameter make_vreg(int regnum) { assert(regnum >= 0 && regnum < x64emit::REG_MAX); return be_parameter(PTYPE_VECTOR_REGISTER, regnum); }
+ static inline be_parameter make_memory(void *base) { return be_parameter(PTYPE_MEMORY, reinterpret_cast<be_parameter_value>(base)); }
+ static inline be_parameter make_memory(const void *base) { return be_parameter(PTYPE_MEMORY, reinterpret_cast<be_parameter_value>(const_cast<void *>(base))); }
+
+ // operators
+ bool operator==(const be_parameter &rhs) const { return (m_type == rhs.m_type && m_value == rhs.m_value); }
+ bool operator!=(const be_parameter &rhs) const { return (m_type != rhs.m_type || m_value != rhs.m_value); }
+
+ // getters
+ be_parameter_type type() const { return m_type; }
+ UINT64 immediate() const { assert(m_type == PTYPE_IMMEDIATE); return m_value; }
+ int ireg() const { assert(m_type == PTYPE_INT_REGISTER); assert(m_value >= 0 && m_value < x64emit::REG_MAX); return m_value; }
+ int freg() const { assert(m_type == PTYPE_FLOAT_REGISTER); assert(m_value >= 0 && m_value < x64emit::REG_MAX); return m_value; }
+ int vreg() const { assert(m_type == PTYPE_VECTOR_REGISTER); assert(m_value >= 0 && m_value < x64emit::REG_MAX); return m_value; }
+ void *memory() const { assert(m_type == PTYPE_MEMORY); return reinterpret_cast<void *>(m_value); }
+
+ // type queries
+ bool is_immediate() const { return (m_type == PTYPE_IMMEDIATE); }
+ bool is_int_register() const { return (m_type == PTYPE_INT_REGISTER); }
+ bool is_float_register() const { return (m_type == PTYPE_FLOAT_REGISTER); }
+ bool is_vector_register() const { return (m_type == PTYPE_VECTOR_REGISTER); }
+ bool is_memory() const { return (m_type == PTYPE_MEMORY); }
+
+ // other queries
+ bool is_immediate_value(UINT64 value) const { return (m_type == PTYPE_IMMEDIATE && m_value == value); }
+
+ // helpers
+ int select_register(int defreg) const;
+ int select_register(int defreg, const be_parameter &checkparam) const;
+ int select_register(int defreg, const be_parameter &checkparam, const be_parameter &checkparam2) const;
+
+ private:
+ // private constructor
+ be_parameter(be_parameter_type type, be_parameter_value value) : m_type(type), m_value(value) { }
+
+ // internals
+ be_parameter_type m_type; // parameter type
+ be_parameter_value m_value; // parameter value
+ };
+
+ // helpers
+ x86_memref MABS(const void *ptr);
+ bool short_immediate(INT64 immediate) const { return (INT32)immediate == immediate; }
+ void normalize_commutative(be_parameter &inner, be_parameter &outer);
+ INT32 offset_from_rbp(const void *ptr);
+ int get_base_register_and_offset(x86code *&dst, void *target, UINT8 reg, INT32 &offset);
+ void emit_smart_call_r64(x86code *&dst, x86code *target, UINT8 reg);
+ void emit_smart_call_m64(x86code *&dst, x86code **target);
+
+ void fixup_label(void *parameter, drccodeptr labelcodeptr);
+ void fixup_exception(drccodeptr *codeptr, void *param1, void *param2);
+
+ static void debug_log_hashjmp(offs_t pc, int mode);
+ static void debug_log_hashjmp_fail();
+
+ // code generators
+ void op_handle(x86code *&dst, const uml::instruction &inst);
+ void op_hash(x86code *&dst, const uml::instruction &inst);
+ void op_label(x86code *&dst, const uml::instruction &inst);
+ void op_comment(x86code *&dst, const uml::instruction &inst);
+ void op_mapvar(x86code *&dst, const uml::instruction &inst);
+
+ void op_nop(x86code *&dst, const uml::instruction &inst);
+ void op_debug(x86code *&dst, const uml::instruction &inst);
+ void op_exit(x86code *&dst, const uml::instruction &inst);
+ void op_hashjmp(x86code *&dst, const uml::instruction &inst);
+ void op_jmp(x86code *&dst, const uml::instruction &inst);
+ void op_exh(x86code *&dst, const uml::instruction &inst);
+ void op_callh(x86code *&dst, const uml::instruction &inst);
+ void op_ret(x86code *&dst, const uml::instruction &inst);
+ void op_callc(x86code *&dst, const uml::instruction &inst);
+ void op_recover(x86code *&dst, const uml::instruction &inst);
+
+ void op_setfmod(x86code *&dst, const uml::instruction &inst);
+ void op_getfmod(x86code *&dst, const uml::instruction &inst);
+ void op_getexp(x86code *&dst, const uml::instruction &inst);
+ void op_getflgs(x86code *&dst, const uml::instruction &inst);
+ void op_save(x86code *&dst, const uml::instruction &inst);
+ void op_restore(x86code *&dst, const uml::instruction &inst);
+
+ void op_load(x86code *&dst, const uml::instruction &inst);
+ void op_loads(x86code *&dst, const uml::instruction &inst);
+ void op_store(x86code *&dst, const uml::instruction &inst);
+ void op_read(x86code *&dst, const uml::instruction &inst);
+ void op_readm(x86code *&dst, const uml::instruction &inst);
+ void op_write(x86code *&dst, const uml::instruction &inst);
+ void op_writem(x86code *&dst, const uml::instruction &inst);
+ void op_carry(x86code *&dst, const uml::instruction &inst);
+ void op_set(x86code *&dst, const uml::instruction &inst);
+ void op_mov(x86code *&dst, const uml::instruction &inst);
+ void op_sext(x86code *&dst, const uml::instruction &inst);
+ void op_roland(x86code *&dst, const uml::instruction &inst);
+ void op_rolins(x86code *&dst, const uml::instruction &inst);
+ void op_add(x86code *&dst, const uml::instruction &inst);
+ void op_addc(x86code *&dst, const uml::instruction &inst);
+ void op_sub(x86code *&dst, const uml::instruction &inst);
+ void op_subc(x86code *&dst, const uml::instruction &inst);
+ void op_cmp(x86code *&dst, const uml::instruction &inst);
+ void op_mulu(x86code *&dst, const uml::instruction &inst);
+ void op_muls(x86code *&dst, const uml::instruction &inst);
+ void op_divu(x86code *&dst, const uml::instruction &inst);
+ void op_divs(x86code *&dst, const uml::instruction &inst);
+ void op_and(x86code *&dst, const uml::instruction &inst);
+ void op_test(x86code *&dst, const uml::instruction &inst);
+ void op_or(x86code *&dst, const uml::instruction &inst);
+ void op_xor(x86code *&dst, const uml::instruction &inst);
+ void op_lzcnt(x86code *&dst, const uml::instruction &inst);
+ void op_bswap(x86code *&dst, const uml::instruction &inst);
+ void op_shl(x86code *&dst, const uml::instruction &inst);
+ void op_shr(x86code *&dst, const uml::instruction &inst);
+ void op_sar(x86code *&dst, const uml::instruction &inst);
+ void op_ror(x86code *&dst, const uml::instruction &inst);
+ void op_rol(x86code *&dst, const uml::instruction &inst);
+ void op_rorc(x86code *&dst, const uml::instruction &inst);
+ void op_rolc(x86code *&dst, const uml::instruction &inst);
+
+ void op_fload(x86code *&dst, const uml::instruction &inst);
+ void op_fstore(x86code *&dst, const uml::instruction &inst);
+ void op_fread(x86code *&dst, const uml::instruction &inst);
+ void op_fwrite(x86code *&dst, const uml::instruction &inst);
+ void op_fmov(x86code *&dst, const uml::instruction &inst);
+ void op_ftoint(x86code *&dst, const uml::instruction &inst);
+ void op_ffrint(x86code *&dst, const uml::instruction &inst);
+ void op_ffrflt(x86code *&dst, const uml::instruction &inst);
+ void op_frnds(x86code *&dst, const uml::instruction &inst);
+ void op_fadd(x86code *&dst, const uml::instruction &inst);
+ void op_fsub(x86code *&dst, const uml::instruction &inst);
+ void op_fcmp(x86code *&dst, const uml::instruction &inst);
+ void op_fmul(x86code *&dst, const uml::instruction &inst);
+ void op_fdiv(x86code *&dst, const uml::instruction &inst);
+ void op_fneg(x86code *&dst, const uml::instruction &inst);
+ void op_fabs(x86code *&dst, const uml::instruction &inst);
+ void op_fsqrt(x86code *&dst, const uml::instruction &inst);
+ void op_frecip(x86code *&dst, const uml::instruction &inst);
+ void op_frsqrt(x86code *&dst, const uml::instruction &inst);
+
+ // 32-bit code emission helpers
+ void emit_mov_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param);
+ void emit_movsx_r64_p32(x86code *&dst, UINT8 reg, const be_parameter &param);
+ void emit_mov_r32_p32_keepflags(x86code *&dst, UINT8 reg, const be_parameter &param);
+ void emit_mov_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param);
+ void emit_mov_p32_r32(x86code *&dst, const be_parameter &param, UINT8 reg);
+ void emit_add_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_add_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_adc_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_adc_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_sub_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_sub_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_sbb_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_sbb_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_cmp_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_cmp_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_and_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_and_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_test_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_test_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_or_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_or_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_xor_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_xor_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_shl_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_shl_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_shr_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_shr_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_sar_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_sar_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_rol_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_rol_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_ror_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_ror_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_rcl_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_rcl_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_rcr_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_rcr_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+
+ // 64-bit code emission helpers
+ void emit_mov_r64_p64(x86code *&dst, UINT8 reg, const be_parameter &param);
+ void emit_mov_r64_p64_keepflags(x86code *&dst, UINT8 reg, const be_parameter &param);
+ void emit_mov_p64_r64(x86code *&dst, const be_parameter &param, UINT8 reg);
+ void emit_add_r64_p64(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_add_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_adc_r64_p64(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_adc_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_sub_r64_p64(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_sub_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_sbb_r64_p64(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_sbb_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_cmp_r64_p64(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_cmp_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_and_r64_p64(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_and_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_test_r64_p64(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_test_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_or_r64_p64(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_or_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_xor_r64_p64(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_xor_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_shl_r64_p64(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_shl_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_shr_r64_p64(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_shr_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_sar_r64_p64(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_sar_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_rol_r64_p64(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_rol_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_ror_r64_p64(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_ror_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_rcl_r64_p64(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_rcl_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_rcr_r64_p64(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_rcr_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+
+ // floating-point code emission helpers
+ void emit_movss_r128_p32(x86code *&dst, UINT8 reg, const be_parameter &param);
+ void emit_movss_p32_r128(x86code *&dst, const be_parameter &param, UINT8 reg);
+ void emit_movsd_r128_p64(x86code *&dst, UINT8 reg, const be_parameter &param);
+ void emit_movsd_p64_r128(x86code *&dst, const be_parameter &param, UINT8 reg);
+
+ // internal state
+ drc_hash_table m_hash; // hash table state
+ drc_map_variables m_map; // code map
+ drc_label_list m_labels; // label list
+ x86log_context * m_log; // logging
+ bool m_sse41; // do we have SSE4.1 support?
+
+ UINT32 * m_absmask32; // absolute value mask (32-bit)
+ UINT64 * m_absmask64; // absolute value mask (32-bit)
+ UINT8 * m_rbpvalue; // value of RBP
+
+ x86_entry_point_func m_entry; // entry point
+ x86code * m_exit; // exit point
+ x86code * m_nocode; // nocode handler
+
+ drc_label_fixup_delegate m_fixup_label; // precomputed delegate for fixups
+ drc_oob_delegate m_fixup_exception; // precomputed delegate for exception fixups
+
+ // state to live in the near cache
+ struct near_state
+ {
+ x86code * debug_cpu_instruction_hook;// debugger callback
+ x86code * debug_log_hashjmp; // hashjmp debugging
+ x86code * debug_log_hashjmp_fail; // hashjmp debugging
+ x86code * drcmap_get_value; // map lookup helper
+
+ UINT32 ssemode; // saved SSE mode
+ UINT32 ssemodesave; // temporary location for saving
+ UINT32 ssecontrol[4]; // copy of the sse_control array
+ float single1; // 1.0 is single-precision
+ double double1; // 1.0 in double-precision
+
+ void * stacksave; // saved stack pointer
+ void * hashstacksave; // saved stack pointer for hashjmp
+
+ UINT8 flagsmap[0x1000]; // flags map
+ UINT64 flagsunmap[0x20]; // flags unmapper
+ };
+ near_state & m_near;
+
+ // globals
+ typedef void (drcbe_x64::*opcode_generate_func)(x86code *&dst, const uml::instruction &inst);
+ struct opcode_table_entry
+ {
+ uml::opcode_t opcode; // opcode in question
+ opcode_generate_func func; // function pointer to the work
+ };
+ static const opcode_table_entry s_opcode_table_source[];
+ static opcode_generate_func s_opcode_table[uml::OP_MAX];
+};
+
+
+#endif /* __DRCBEC_H__ */
diff --git a/trunk/src/emu/cpu/drcbex86.c b/trunk/src/emu/cpu/drcbex86.c
new file mode 100644
index 00000000000..7d0687c7a86
--- /dev/null
+++ b/trunk/src/emu/cpu/drcbex86.c
@@ -0,0 +1,6615 @@
+/***************************************************************************
+
+ drcbex86.c
+
+ 32-bit x86 back-end for the universal machine language.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+****************************************************************************
+
+ Future improvements/changes:
+
+ * Optimize to avoid unnecessary reloads
+ - especially EDX for 64-bit operations
+ - also FCMP/FLAGS has unnecessary PUSHF/POP EAX
+
+ * Identify common pairs and optimize output
+
+ * Convert SUB a,0,b to NEG
+
+ * Optimize, e.g., and [r5],i0,$FF to use ebx as temporary register
+ (avoid initial move) if i0 is not needed going forward
+
+****************************************************************************
+
+ ---------------
+ ABI/conventions
+ ---------------
+
+ Registers:
+ EAX - volatile, function return value
+ EBX - non-volatile
+ ECX - volatile
+ EDX - volatile, function return value (upper 32 bits)
+ ESI - non-volatile
+ EDI - non-volatile
+ EBP - non-volatile
+
+ FP stack - volatile
+
+
+ ---------------
+ Execution model
+ ---------------
+
+ Registers:
+ EAX - scratch register
+ EBX - maps to I0 (low 32 bits)
+ ECX - scratch register
+ EDX - scratch register
+ ESI - maps to I1 (low 32 bits)
+ EDI - maps to I2 (low 32 bits)
+ EBP - maps to I3 (low 32 bits)
+
+ FP stack - scratch registers
+
+ Entry point:
+ Assumes 1 parameter passed, which is the codeptr of the code
+ to execute once the environment is set up.
+
+ Exit point:
+ Assumes exit value is in EAX.
+
+ Entry stack:
+ [esp] - return
+ [esp+4] - input parameter (entry handle)
+
+ Runtime stack:
+ [esp] - param 0
+ [esp+4] - param 1
+ [esp+8] - param 2
+ [esp+12] - param 3
+ [esp+16] - param 4
+ [esp+20] - alignment
+ [esp+24] - alignment
+ [esp+28] - saved ebp
+ [esp+32] - saved edi
+ [esp+36] - saved esi
+ [esp+40] - saved ebx
+ [esp+44] - ret
+ [esp+48] - input parameter (entry handle)
+
+**************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "drcuml.h"
+#include "drcbex86.h"
+
+using namespace uml;
+using namespace x86emit;
+
+
+//**************************************************************************
+// DEBUGGING
+//**************************************************************************
+
+#define LOG_HASHJMPS (0)
+
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+const UINT32 PTYPE_M = 1 << parameter::PTYPE_MEMORY;
+const UINT32 PTYPE_I = 1 << parameter::PTYPE_IMMEDIATE;
+const UINT32 PTYPE_R = 1 << parameter::PTYPE_INT_REGISTER;
+const UINT32 PTYPE_F = 1 << parameter::PTYPE_FLOAT_REGISTER;
+const UINT32 PTYPE_MI = PTYPE_M | PTYPE_I;
+const UINT32 PTYPE_RI = PTYPE_R | PTYPE_I;
+const UINT32 PTYPE_MR = PTYPE_M | PTYPE_R;
+const UINT32 PTYPE_MRI = PTYPE_M | PTYPE_R | PTYPE_I;
+const UINT32 PTYPE_MF = PTYPE_M | PTYPE_F;
+
+
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+#define X86_CONDITION(condition) (condition_map[condition - uml::COND_Z])
+#define X86_NOT_CONDITION(condition) (condition_map[condition - uml::COND_Z] ^ 1)
+
+#define assert_no_condition(inst) assert((inst).condition() == uml::COND_ALWAYS)
+#define assert_any_condition(inst) assert((inst).condition() == uml::COND_ALWAYS || ((inst).condition() >= uml::COND_Z && (inst).condition() < uml::COND_MAX))
+#define assert_no_flags(inst) assert((inst).flags() == 0)
+#define assert_flags(inst, valid) assert(((inst).flags() & ~(valid)) == 0)
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+drcbe_x86::opcode_generate_func drcbe_x86::s_opcode_table[OP_MAX];
+
+// size-to-mask table
+static const UINT64 size_to_mask[] = { 0, 0xff, 0xffff, 0, 0xffffffff, 0, 0, 0, U64(0xffffffffffffffff) };
+
+// register mapping tables
+static const UINT8 int_register_map[REG_I_COUNT] =
+{
+ REG_EBX, REG_ESI, REG_EDI, REG_EBP
+};
+
+// flags mapping tables
+static UINT8 flags_map[0x1000];
+static UINT32 flags_unmap[0x20];
+
+// condition mapping table
+static const UINT8 condition_map[uml::COND_MAX - uml::COND_Z] =
+{
+ x86emit::COND_Z, // COND_Z = 0x80, requires Z
+ x86emit::COND_NZ, // COND_NZ, requires Z
+ x86emit::COND_S, // COND_S, requires S
+ x86emit::COND_NS, // COND_NS, requires S
+ x86emit::COND_C, // COND_C, requires C
+ x86emit::COND_NC, // COND_NC, requires C
+ x86emit::COND_O, // COND_V, requires V
+ x86emit::COND_NO, // COND_NV, requires V
+ x86emit::COND_P, // COND_U, requires U
+ x86emit::COND_NP, // COND_NU, requires U
+ x86emit::COND_A, // COND_A, requires CZ
+ x86emit::COND_BE, // COND_BE, requires CZ
+ x86emit::COND_G, // COND_G, requires SVZ
+ x86emit::COND_LE, // COND_LE, requires SVZ
+ x86emit::COND_L, // COND_L, requires SV
+ x86emit::COND_GE, // COND_GE, requires SV
+};
+
+// FPU control register mapping
+static const UINT16 fp_control[4] =
+{
+ 0x0e3f, // ROUND_TRUNC
+ 0x023f, // ROUND_ROUND
+ 0x0a3f, // ROUND_CEIL
+ 0x063f // ROUND_FLOOR
+};
+
+
+
+//**************************************************************************
+// TABLES
+//**************************************************************************
+
+const drcbe_x86::opcode_table_entry drcbe_x86::s_opcode_table_source[] =
+{
+ // Compile-time opcodes
+ { uml::OP_HANDLE, &drcbe_x86::op_handle }, // HANDLE handle
+ { uml::OP_HASH, &drcbe_x86::op_hash }, // HASH mode,pc
+ { uml::OP_LABEL, &drcbe_x86::op_label }, // LABEL imm
+ { uml::OP_COMMENT, &drcbe_x86::op_comment }, // COMMENT string
+ { uml::OP_MAPVAR, &drcbe_x86::op_mapvar }, // MAPVAR mapvar,value
+
+ // Control Flow Operations
+ { uml::OP_NOP, &drcbe_x86::op_nop }, // NOP
+ { uml::OP_DEBUG, &drcbe_x86::op_debug }, // DEBUG pc
+ { uml::OP_EXIT, &drcbe_x86::op_exit }, // EXIT src1[,c]
+ { uml::OP_HASHJMP, &drcbe_x86::op_hashjmp }, // HASHJMP mode,pc,handle
+ { uml::OP_JMP, &drcbe_x86::op_jmp }, // JMP imm[,c]
+ { uml::OP_EXH, &drcbe_x86::op_exh }, // EXH handle,param[,c]
+ { uml::OP_CALLH, &drcbe_x86::op_callh }, // CALLH handle[,c]
+ { uml::OP_RET, &drcbe_x86::op_ret }, // RET [c]
+ { uml::OP_CALLC, &drcbe_x86::op_callc }, // CALLC func,ptr[,c]
+ { uml::OP_RECOVER, &drcbe_x86::op_recover }, // RECOVER dst,mapvar
+
+ // Internal Register Operations
+ { uml::OP_SETFMOD, &drcbe_x86::op_setfmod }, // SETFMOD src
+ { uml::OP_GETFMOD, &drcbe_x86::op_getfmod }, // GETFMOD dst
+ { uml::OP_GETEXP, &drcbe_x86::op_getexp }, // GETEXP dst
+ { uml::OP_GETFLGS, &drcbe_x86::op_getflgs }, // GETFLGS dst[,f]
+ { uml::OP_SAVE, &drcbe_x86::op_save }, // SAVE dst
+ { uml::OP_RESTORE, &drcbe_x86::op_restore }, // RESTORE dst
+
+ // Integer Operations
+ { uml::OP_LOAD, &drcbe_x86::op_load }, // LOAD dst,base,index,size
+ { uml::OP_LOADS, &drcbe_x86::op_loads }, // LOADS dst,base,index,size
+ { uml::OP_STORE, &drcbe_x86::op_store }, // STORE base,index,src,size
+ { uml::OP_READ, &drcbe_x86::op_read }, // READ dst,src1,spacesize
+ { uml::OP_READM, &drcbe_x86::op_readm }, // READM dst,src1,mask,spacesize
+ { uml::OP_WRITE, &drcbe_x86::op_write }, // WRITE dst,src1,spacesize
+ { uml::OP_WRITEM, &drcbe_x86::op_writem }, // WRITEM dst,src1,spacesize
+ { uml::OP_CARRY, &drcbe_x86::op_carry }, // CARRY src,bitnum
+ { uml::OP_SET, &drcbe_x86::op_set }, // SET dst,c
+ { uml::OP_MOV, &drcbe_x86::op_mov }, // MOV dst,src[,c]
+ { uml::OP_SEXT, &drcbe_x86::op_sext }, // SEXT dst,src
+ { uml::OP_ROLAND, &drcbe_x86::op_roland }, // ROLAND dst,src1,src2,src3
+ { uml::OP_ROLINS, &drcbe_x86::op_rolins }, // ROLINS dst,src1,src2,src3
+ { uml::OP_ADD, &drcbe_x86::op_add }, // ADD dst,src1,src2[,f]
+ { uml::OP_ADDC, &drcbe_x86::op_addc }, // ADDC dst,src1,src2[,f]
+ { uml::OP_SUB, &drcbe_x86::op_sub }, // SUB dst,src1,src2[,f]
+ { uml::OP_SUBB, &drcbe_x86::op_subc }, // SUBB dst,src1,src2[,f]
+ { uml::OP_CMP, &drcbe_x86::op_cmp }, // CMP src1,src2[,f]
+ { uml::OP_MULU, &drcbe_x86::op_mulu }, // MULU dst,edst,src1,src2[,f]
+ { uml::OP_MULS, &drcbe_x86::op_muls }, // MULS dst,edst,src1,src2[,f]
+ { uml::OP_DIVU, &drcbe_x86::op_divu }, // DIVU dst,edst,src1,src2[,f]
+ { uml::OP_DIVS, &drcbe_x86::op_divs }, // DIVS dst,edst,src1,src2[,f]
+ { uml::OP_AND, &drcbe_x86::op_and }, // AND dst,src1,src2[,f]
+ { uml::OP_TEST, &drcbe_x86::op_test }, // TEST src1,src2[,f]
+ { uml::OP_OR, &drcbe_x86::op_or }, // OR dst,src1,src2[,f]
+ { uml::OP_XOR, &drcbe_x86::op_xor }, // XOR dst,src1,src2[,f]
+ { uml::OP_LZCNT, &drcbe_x86::op_lzcnt }, // LZCNT dst,src[,f]
+ { uml::OP_BSWAP, &drcbe_x86::op_bswap }, // BSWAP dst,src
+ { uml::OP_SHL, &drcbe_x86::op_shl }, // SHL dst,src,count[,f]
+ { uml::OP_SHR, &drcbe_x86::op_shr }, // SHR dst,src,count[,f]
+ { uml::OP_SAR, &drcbe_x86::op_sar }, // SAR dst,src,count[,f]
+ { uml::OP_ROL, &drcbe_x86::op_rol }, // ROL dst,src,count[,f]
+ { uml::OP_ROLC, &drcbe_x86::op_rolc }, // ROLC dst,src,count[,f]
+ { uml::OP_ROR, &drcbe_x86::op_ror }, // ROR dst,src,count[,f]
+ { uml::OP_RORC, &drcbe_x86::op_rorc }, // RORC dst,src,count[,f]
+
+ // Floating Point Operations
+ { uml::OP_FLOAD, &drcbe_x86::op_fload }, // FLOAD dst,base,index
+ { uml::OP_FSTORE, &drcbe_x86::op_fstore }, // FSTORE base,index,src
+ { uml::OP_FREAD, &drcbe_x86::op_fread }, // FREAD dst,space,src1
+ { uml::OP_FWRITE, &drcbe_x86::op_fwrite }, // FWRITE space,dst,src1
+ { uml::OP_FMOV, &drcbe_x86::op_fmov }, // FMOV dst,src1[,c]
+ { uml::OP_FTOINT, &drcbe_x86::op_ftoint }, // FTOINT dst,src1,size,round
+ { uml::OP_FFRINT, &drcbe_x86::op_ffrint }, // FFRINT dst,src1,size
+ { uml::OP_FFRFLT, &drcbe_x86::op_ffrflt }, // FFRFLT dst,src1,size
+ { uml::OP_FRNDS, &drcbe_x86::op_frnds }, // FRNDS dst,src1
+ { uml::OP_FADD, &drcbe_x86::op_fadd }, // FADD dst,src1,src2
+ { uml::OP_FSUB, &drcbe_x86::op_fsub }, // FSUB dst,src1,src2
+ { uml::OP_FCMP, &drcbe_x86::op_fcmp }, // FCMP src1,src2
+ { uml::OP_FMUL, &drcbe_x86::op_fmul }, // FMUL dst,src1,src2
+ { uml::OP_FDIV, &drcbe_x86::op_fdiv }, // FDIV dst,src1,src2
+ { uml::OP_FNEG, &drcbe_x86::op_fneg }, // FNEG dst,src1
+ { uml::OP_FABS, &drcbe_x86::op_fabs }, // FABS dst,src1
+ { uml::OP_FSQRT, &drcbe_x86::op_fsqrt }, // FSQRT dst,src1
+ { uml::OP_FRECIP, &drcbe_x86::op_frecip }, // FRECIP dst,src1
+ { uml::OP_FRSQRT, &drcbe_x86::op_frsqrt } // FRSQRT dst,src1
+};
+
+
+
+//**************************************************************************
+// INLINE FUNCTIONS
+//**************************************************************************
+
+//-------------------------------------------------
+// param_normalize - convert a full parameter
+// into a reduced set
+//-------------------------------------------------
+
+drcbe_x86::be_parameter::be_parameter(drcbe_x86 &drcbe, const parameter &param, UINT32 allowed)
+{
+ int regnum;
+
+ switch (param.type())
+ {
+ // immediates pass through
+ case parameter::PTYPE_IMMEDIATE:
+ assert(allowed & PTYPE_I);
+ *this = param.immediate();
+ break;
+
+ // memory passes through
+ case parameter::PTYPE_MEMORY:
+ assert(allowed & PTYPE_M);
+ *this = make_memory(param.memory());
+ break;
+
+ // if a register maps to a register, keep it as a register; otherwise map it to memory
+ case parameter::PTYPE_INT_REGISTER:
+ assert(allowed & PTYPE_R);
+ assert(allowed & PTYPE_M);
+ regnum = int_register_map[param.ireg() - REG_I0];
+ if (regnum != 0)
+ *this = make_ireg(regnum);
+ else
+ *this = make_memory(&drcbe.m_state.r[param.ireg() - REG_I0]);
+ break;
+
+ // if a register maps to a register, keep it as a register; otherwise map it to memory
+ case parameter::PTYPE_FLOAT_REGISTER:
+ assert(allowed & PTYPE_F);
+ assert(allowed & PTYPE_M);
+ *this = make_memory(&drcbe.m_state.f[param.freg() - REG_F0]);
+ break;
+
+ // everything else is unexpected
+ default:
+ fatalerror("Unexpected parameter type");
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// select_register - select a register to use,
+// avoiding conflicts with the optional
+// checkparam
+//-------------------------------------------------
+
+inline int drcbe_x86::be_parameter::select_register(int defreg) const
+{
+ if (m_type == PTYPE_INT_REGISTER || m_type == PTYPE_FLOAT_REGISTER || m_type == PTYPE_VECTOR_REGISTER)
+ return m_value;
+ return defreg;
+}
+
+inline int drcbe_x86::be_parameter::select_register(int defreg, const be_parameter &checkparam) const
+{
+ if (*this == checkparam)
+ return defreg;
+ return select_register(defreg);
+}
+
+inline int drcbe_x86::be_parameter::select_register(int defreg, const be_parameter &checkparam, const be_parameter &checkparam2) const
+{
+ if (*this == checkparam || *this == checkparam2)
+ return defreg;
+ return select_register(defreg);
+}
+
+
+//-------------------------------------------------
+// select_register - select a register to use,
+// avoiding conflicts with the optional
+// checkparam
+//-------------------------------------------------
+
+inline void drcbe_x86::normalize_commutative(be_parameter &inner, be_parameter &outer)
+{
+ // if the inner parameter is a memory operand, push it to the outer
+ if (inner.is_memory())
+ {
+ be_parameter temp = inner;
+ inner = outer;
+ outer = temp;
+ }
+
+ // if the inner parameter is an immediate, push it to the outer
+ if (inner.is_immediate())
+ {
+ be_parameter temp = inner;
+ inner = outer;
+ outer = temp;
+ }
+}
+
+
+//-------------------------------------------------
+// emit_combine_z_flags - combine the Z flag from
+// two 32-bit operations
+//-------------------------------------------------
+
+inline void drcbe_x86::emit_combine_z_flags(x86code *&dst)
+{
+ // this assumes that the flags from the low 32-bit op are on the stack
+ // and the flags from the high 32-bit op are live
+ emit_pushf(dst); // pushf
+ emit_mov_r32_m32(dst, REG_ECX, MBD(REG_ESP, 4)); // mov ecx,[esp+4]
+ emit_or_r32_imm(dst, REG_ECX, ~0x40); // or ecx,~0x40
+ emit_and_m32_r32(dst, MBD(REG_ESP, 0), REG_ECX); // and [esp],ecx
+ emit_popf(dst); // popf
+ emit_lea_r32_m32(dst, REG_ESP, MBD(REG_ESP, 4)); // lea esp,[esp+4]
+}
+
+
+//-------------------------------------------------
+// emit_combine_z_shl_flags - combine the Z
+// flags from two 32-bit shift left operations
+//-------------------------------------------------
+
+inline void drcbe_x86::emit_combine_z_shl_flags(x86code *&dst)
+{
+ // this assumes that the flags from the high 32-bit op are on the stack
+ // and the flags from the low 32-bit op are live
+ emit_pushf(dst); // pushf
+ emit_pop_r32(dst, REG_ECX); // pop ecx
+ emit_or_r32_imm(dst, REG_ECX, ~0x40); // or ecx,~0x40
+ emit_and_m32_r32(dst, MBD(REG_ESP, 0), REG_ECX); // and [esp],ecx
+ emit_popf(dst); // popf
+}
+
+
+//-------------------------------------------------
+// reset_last_upper_lower_reg - reset the last
+// upper/lower register state
+//-------------------------------------------------
+
+inline void drcbe_x86::reset_last_upper_lower_reg()
+{
+ m_last_lower_reg = REG_NONE;
+ m_last_upper_reg = REG_NONE;
+}
+
+
+//-------------------------------------------------
+// set_last_lower_reg - note that we have just
+// loaded a lower register
+//-------------------------------------------------
+
+inline void drcbe_x86::set_last_lower_reg(x86code *&dst, const be_parameter &param, UINT8 reglo)
+{
+ if (param.is_memory())
+ {
+ m_last_lower_reg = reglo;
+ m_last_lower_addr = (UINT32 *)((FPTR)param.memory());
+ m_last_lower_pc = dst;
+ }
+}
+
+
+//-------------------------------------------------
+// set_last_upper_reg - note that we have just
+// loaded an upper register
+//-------------------------------------------------
+
+inline void drcbe_x86::set_last_upper_reg(x86code *&dst, const be_parameter &param, UINT8 reghi)
+{
+ m_last_upper_reg = reghi;
+ m_last_upper_addr = (param.is_int_register()) ? m_reghi[param.ireg()] : (UINT32 *)((FPTR)param.memory(4));
+ m_last_upper_pc = dst;
+}
+
+
+//-------------------------------------------------
+// can_skip_lower_load - return true if we can
+// skip re-loading a lower half of a register
+//-------------------------------------------------
+
+inline bool drcbe_x86::can_skip_lower_load(x86code *&dst, UINT32 *memref, UINT8 reglo)
+{
+ return (dst == m_last_lower_pc && memref == m_last_lower_addr && reglo == m_last_lower_reg);
+}
+
+
+//-------------------------------------------------
+// can_skip_upper_load - return true if we can
+// skip re-loading an upper half of a register
+//-------------------------------------------------
+
+inline bool drcbe_x86::can_skip_upper_load(x86code *&dst, UINT32 *memref, UINT8 reghi)
+{
+ return (dst == m_last_upper_pc && memref == m_last_upper_addr && reghi == m_last_upper_reg);
+}
+
+
+//-------------------------------------------------
+// track_resolve_link - wrapper for resolve_link
+// that resets all register tracking info
+//-------------------------------------------------
+
+inline void drcbe_x86::track_resolve_link(x86code *&destptr, const emit_link &linkinfo)
+{
+ reset_last_upper_lower_reg();
+ resolve_link(destptr, linkinfo);
+}
+
+#define resolve_link INVALID
+
+
+
+//**************************************************************************
+// BACKEND CALLBACKS
+//**************************************************************************
+
+//-------------------------------------------------
+// drcbe_x86 - constructor
+//-------------------------------------------------
+
+drcbe_x86::drcbe_x86(drcuml_state &drcuml, device_t &device, drc_cache &cache, UINT32 flags, int modes, int addrbits, int ignorebits)
+ : drcbe_interface(drcuml, cache, device),
+ m_hash(cache, modes, addrbits, ignorebits),
+ m_map(cache, 0),
+ m_labels(cache),
+ m_log(NULL),
+ m_logged_common(false),
+ m_sse3(false),
+ m_entry(NULL),
+ m_exit(NULL),
+ m_nocode(NULL),
+ m_save(NULL),
+ m_restore(NULL),
+ m_last_lower_reg(REG_NONE),
+ m_last_lower_pc(NULL),
+ m_last_lower_addr(NULL),
+ m_last_upper_reg(REG_NONE),
+ m_last_upper_pc(NULL),
+ m_last_upper_addr(NULL),
+ m_fptemp(0),
+ m_fpumode(0),
+ m_fmodesave(0),
+ m_stacksave(0),
+ m_hashstacksave(0),
+ m_reslo(0),
+ m_reshi(0),
+ m_fixup_label(FUNC(drcbe_x86::fixup_label), this),
+ m_fixup_exception(FUNC(drcbe_x86::fixup_exception), this)
+{
+ // compute hi pointers for each register
+ for (int regnum = 0; regnum < ARRAY_LENGTH(int_register_map); regnum++)
+ if (int_register_map[regnum] != 0)
+ {
+ m_reglo[int_register_map[regnum]] = &m_state.r[regnum].w.l;
+ m_reghi[int_register_map[regnum]] = &m_state.r[regnum].w.h;
+ }
+
+ // build the flags map (static but it doesn't hurt to regenerate it)
+ for (int entry = 0; entry < ARRAY_LENGTH(flags_map); entry++)
+ {
+ UINT8 flags = 0;
+ if (entry & 0x001) flags |= FLAG_C;
+ if (entry & 0x004) flags |= FLAG_U;
+ if (entry & 0x040) flags |= FLAG_Z;
+ if (entry & 0x080) flags |= FLAG_S;
+ if (entry & 0x800) flags |= FLAG_V;
+ flags_map[entry] = flags;
+ }
+ for (int entry = 0; entry < ARRAY_LENGTH(flags_unmap); entry++)
+ {
+ UINT32 flags = 0;
+ if (entry & FLAG_C) flags |= 0x001;
+ if (entry & FLAG_U) flags |= 0x004;
+ if (entry & FLAG_Z) flags |= 0x040;
+ if (entry & FLAG_S) flags |= 0x080;
+ if (entry & FLAG_V) flags |= 0x800;
+ flags_unmap[entry] = flags;
+ }
+
+ // build the opcode table (static but it doesn't hurt to regenerate it)
+ for (int opnum = 0; opnum < ARRAY_LENGTH(s_opcode_table_source); opnum++)
+ s_opcode_table[s_opcode_table_source[opnum].opcode] = s_opcode_table_source[opnum].func;
+
+ // create the log
+ if (flags & DRCUML_OPTION_LOG_NATIVE)
+ m_log = x86log_create_context("drcbex86.asm");
+}
+
+
+//-------------------------------------------------
+// ~drcbe_x86 - destructor
+//-------------------------------------------------
+
+drcbe_x86::~drcbe_x86()
+{
+ // free the log context
+ if (m_log != NULL)
+ x86log_free_context(m_log);
+}
+
+
+//-------------------------------------------------
+// reset - reset back-end specific state
+//-------------------------------------------------
+
+void drcbe_x86::reset()
+{
+ // output a note to the log
+ if (m_log != NULL)
+ x86log_printf(m_log, "\n\n===========\nCACHE RESET\n===========\n\n");
+
+ // generate a little bit of glue code to set up the environment
+ drccodeptr *cachetop = m_cache.begin_codegen(500);
+ if (cachetop == NULL)
+ fatalerror("Out of cache space after a reset!");
+
+ x86code *dst = (x86code *)*cachetop;
+
+ // generate a simple CPUID stub
+ UINT32 (*cpuid_ecx_stub)(void) = (UINT32 (*)(void))dst;
+ emit_push_r32(dst, REG_EBX); // push ebx
+ emit_mov_r32_imm(dst, REG_EAX, 1); // mov eax,1
+ emit_cpuid(dst); // cpuid
+ emit_mov_r32_r32(dst, REG_EAX, REG_ECX); // mov eax,ecx
+ emit_pop_r32(dst, REG_EBX); // pop ebx
+ emit_ret(dst); // ret
+
+ // call it to determine if we have SSE3 support
+ m_sse3 = (((*cpuid_ecx_stub)() & 1) != 0);
+
+ // generate an entry point
+ m_entry = (x86_entry_point_func)dst;
+ emit_mov_r32_m32(dst, REG_EAX, MBD(REG_ESP, 4)); // mov eax,[esp+4]
+ emit_push_r32(dst, REG_EBX); // push ebx
+ emit_push_r32(dst, REG_ESI); // push esi
+ emit_push_r32(dst, REG_EDI); // push edi
+ emit_push_r32(dst, REG_EBP); // push ebp
+ emit_sub_r32_imm(dst, REG_ESP, 24); // sub esp,24
+ emit_mov_m32_r32(dst, MABS(&m_hashstacksave), REG_ESP); // mov [hashstacksave],esp
+ emit_sub_r32_imm(dst, REG_ESP, 4); // sub esp,4
+ emit_mov_m32_r32(dst, MABS(&m_stacksave), REG_ESP); // mov [stacksave],esp
+ emit_fstcw_m16(dst, MABS(&m_fpumode)); // fstcw [fpumode]
+ emit_jmp_r32(dst, REG_EAX); // jmp eax
+ if (m_log != NULL && !m_logged_common)
+ x86log_disasm_code_range(m_log, "entry_point", (x86code *)m_entry, dst);
+
+ // generate an exit point
+ m_exit = dst;
+ emit_fldcw_m16(dst, MABS(&m_fpumode)); // fldcw [fpumode]
+ emit_mov_r32_m32(dst, REG_ESP, MABS(&m_hashstacksave)); // mov esp,[hashstacksave]
+ emit_add_r32_imm(dst, REG_ESP, 24); // add esp,24
+ emit_pop_r32(dst, REG_EBP); // pop ebp
+ emit_pop_r32(dst, REG_EDI); // pop edi
+ emit_pop_r32(dst, REG_ESI); // pop esi
+ emit_pop_r32(dst, REG_EBX); // pop ebx
+ emit_ret(dst); // ret
+ if (m_log != NULL && !m_logged_common)
+ x86log_disasm_code_range(m_log, "exit_point", m_exit, dst);
+
+ // generate a no code point
+ m_nocode = dst;
+ emit_ret(dst); // ret
+ if (m_log != NULL && !m_logged_common)
+ x86log_disasm_code_range(m_log, "nocode", m_nocode, dst);
+
+ // generate a save subroutine
+ m_save = dst;
+ emit_pushf(dst); // pushf
+ emit_pop_r32(dst, REG_EAX); // pop eax
+ emit_and_r32_imm(dst, REG_EAX, 0x8c5); // and eax,0x8c5
+ emit_mov_r8_m8(dst, REG_AL, MABSI(flags_map, REG_EAX)); // mov al,[flags_map]
+ emit_mov_m8_r8(dst, MBD(REG_ECX, offsetof(drcuml_machine_state, flags)), REG_AL); // mov state->flags,al
+ emit_mov_r8_m8(dst, REG_AL, MABS(&m_state.fmod)); // mov al,[fmod]
+ emit_mov_m8_r8(dst, MBD(REG_ECX, offsetof(drcuml_machine_state, fmod)), REG_AL); // mov state->fmod,al
+ emit_mov_r32_m32(dst, REG_EAX, MABS(&m_state.exp)); // mov eax,[exp]
+ emit_mov_m32_r32(dst, MBD(REG_ECX, offsetof(drcuml_machine_state, exp)), REG_EAX); // mov state->exp,eax
+ for (int regnum = 0; regnum < ARRAY_LENGTH(m_state.r); regnum++)
+ {
+ FPTR regoffsl = (FPTR)&((drcuml_machine_state *)NULL)->r[regnum].w.l;
+ FPTR regoffsh = (FPTR)&((drcuml_machine_state *)NULL)->r[regnum].w.h;
+ if (int_register_map[regnum] != 0)
+ emit_mov_m32_r32(dst, MBD(REG_ECX, regoffsl), int_register_map[regnum]);
+ else
+ {
+ emit_mov_r32_m32(dst, REG_EAX, MABS(&m_state.r[regnum].w.l));
+ emit_mov_m32_r32(dst, MBD(REG_ECX, regoffsl), REG_EAX);
+ }
+ emit_mov_r32_m32(dst, REG_EAX, MABS(&m_state.r[regnum].w.h));
+ emit_mov_m32_r32(dst, MBD(REG_ECX, regoffsh), REG_EAX);
+ }
+ for (int regnum = 0; regnum < ARRAY_LENGTH(m_state.f); regnum++)
+ {
+ FPTR regoffsl = (FPTR)&((drcuml_machine_state *)NULL)->f[regnum].s.l;
+ FPTR regoffsh = (FPTR)&((drcuml_machine_state *)NULL)->f[regnum].s.h;
+ emit_mov_r32_m32(dst, REG_EAX, MABS(&m_state.f[regnum].s.l));
+ emit_mov_m32_r32(dst, MBD(REG_ECX, regoffsl), REG_EAX);
+ emit_mov_r32_m32(dst, REG_EAX, MABS(&m_state.f[regnum].s.h));
+ emit_mov_m32_r32(dst, MBD(REG_ECX, regoffsh), REG_EAX);
+ }
+ emit_ret(dst); // ret
+ if (m_log != NULL && !m_logged_common)
+ x86log_disasm_code_range(m_log, "save", m_save, dst);
+
+ // generate a restore subroutine
+ m_restore = dst;
+ for (int regnum = 0; regnum < ARRAY_LENGTH(m_state.r); regnum++)
+ {
+ FPTR regoffsl = (FPTR)&((drcuml_machine_state *)NULL)->r[regnum].w.l;
+ FPTR regoffsh = (FPTR)&((drcuml_machine_state *)NULL)->r[regnum].w.h;
+ if (int_register_map[regnum] != 0)
+ emit_mov_r32_m32(dst, int_register_map[regnum], MBD(REG_ECX, regoffsl));
+ else
+ {
+ emit_mov_r32_m32(dst, REG_EAX, MBD(REG_ECX, regoffsl));
+ emit_mov_m32_r32(dst, MABS(&m_state.r[regnum].w.l), REG_EAX);
+ }
+ emit_mov_r32_m32(dst, REG_EAX, MBD(REG_ECX, regoffsh));
+ emit_mov_m32_r32(dst, MABS(&m_state.r[regnum].w.h), REG_EAX);
+ }
+ for (int regnum = 0; regnum < ARRAY_LENGTH(m_state.f); regnum++)
+ {
+ FPTR regoffsl = (FPTR)&((drcuml_machine_state *)NULL)->f[regnum].s.l;
+ FPTR regoffsh = (FPTR)&((drcuml_machine_state *)NULL)->f[regnum].s.h;
+ emit_mov_r32_m32(dst, REG_EAX, MBD(REG_ECX, regoffsl));
+ emit_mov_m32_r32(dst, MABS(&m_state.f[regnum].s.l), REG_EAX);
+ emit_mov_r32_m32(dst, REG_EAX, MBD(REG_ECX, regoffsh));
+ emit_mov_m32_r32(dst, MABS(&m_state.f[regnum].s.h), REG_EAX);
+ }
+ emit_movzx_r32_m8(dst, REG_EAX, MBD(REG_ECX, offsetof(drcuml_machine_state, fmod)));// movzx eax,state->fmod
+ emit_and_r32_imm(dst, REG_EAX, 3); // and eax,3
+ emit_mov_m8_r8(dst, MABS(&m_state.fmod), REG_AL); // mov [fmod],al
+ emit_fldcw_m16(dst, MABSI(&fp_control[0], REG_EAX, 2)); // fldcw fp_control[eax]
+ emit_mov_r32_m32(dst, REG_EAX, MBD(REG_ECX, offsetof(drcuml_machine_state, exp))); // mov eax,state->exp
+ emit_mov_m32_r32(dst, MABS(&m_state.exp), REG_EAX); // mov [exp],eax
+ emit_movzx_r32_m8(dst, REG_EAX, MBD(REG_ECX, offsetof(drcuml_machine_state, flags)));// movzx eax,state->flags
+ emit_push_m32(dst, MABSI(flags_unmap, REG_EAX, 4)); // push flags_unmap[eax*4]
+ emit_popf(dst); // popf
+ emit_ret(dst); // ret
+ if (m_log != NULL && !m_logged_common)
+ x86log_disasm_code_range(m_log, "restore", m_restore, dst);
+
+ // finish up codegen
+ *cachetop = dst;
+ m_cache.end_codegen();
+ m_logged_common = true;
+
+ // reset our hash tables
+ m_hash.reset();
+ m_hash.set_default_codeptr(m_nocode);
+}
+
+
+//-------------------------------------------------
+// drcbex86_execute - execute a block of code
+// referenced by the given handle
+//-------------------------------------------------
+
+int drcbe_x86::execute(code_handle &entry)
+{
+ // call our entry point which will jump to the destination
+ return (*m_entry)((x86code *)entry.codeptr());
+}
+
+
+//-------------------------------------------------
+// drcbex86_generate - generate code
+//-------------------------------------------------
+
+void drcbe_x86::generate(drcuml_block &block, const instruction *instlist, UINT32 numinst)
+{
+ // tell all of our utility objects that a block is beginning
+ m_hash.block_begin(block, instlist, numinst);
+ m_labels.block_begin(block);
+ m_map.block_begin(block);
+
+ // begin codegen; fail if we can't
+ drccodeptr *cachetop = m_cache.begin_codegen(numinst * 8 * 4);
+ if (cachetop == NULL)
+ block.abort();
+
+ // compute the base by aligning the cache top to a cache line (assumed to be 64 bytes)
+ x86code *base = (x86code *)(((FPTR)*cachetop + 63) & ~63);
+ x86code *dst = base;
+
+ // generate code
+ astring tempstring;
+ const char *blockname = NULL;
+ for (int inum = 0; inum < numinst; inum++)
+ {
+ const instruction &inst = instlist[inum];
+ assert(inst.opcode() < ARRAY_LENGTH(s_opcode_table));
+
+ // add a comment
+ if (m_log != NULL)
+ {
+ astring dasm;
+ inst.disasm(dasm, &m_drcuml);
+ x86log_add_comment(m_log, dst, "%s", dasm.cstr());
+ }
+
+ // extract a blockname
+ if (blockname == NULL)
+ {
+ if (inst.opcode() == OP_HANDLE)
+ blockname = inst.param(0).handle().string();
+ else if (inst.opcode() == OP_HASH)
+ blockname = tempstring.format("Code: mode=%d PC=%08X", (UINT32)inst.param(0).immediate(), (offs_t)inst.param(1).immediate());
+ }
+
+ // generate code
+ (this->*s_opcode_table[inst.opcode()])(dst, inst);
+ }
+
+ // complete codegen
+ *cachetop = (drccodeptr)dst;
+ m_cache.end_codegen();
+
+ // log it
+ if (m_log != NULL)
+ x86log_disasm_code_range(m_log, (blockname == NULL) ? "Unknown block" : blockname, base, m_cache.top());
+
+ // tell all of our utility objects that the block is finished
+ m_hash.block_end(block);
+ m_labels.block_end(block);
+ m_map.block_end(block);
+}
+
+
+//-------------------------------------------------
+// drcbex86_hash_exists - return true if the
+// given mode/pc exists in the hash table
+//-------------------------------------------------
+
+bool drcbe_x86::hash_exists(UINT32 mode, UINT32 pc)
+{
+ return m_hash.code_exists(mode, pc);
+}
+
+
+//-------------------------------------------------
+// drcbex86_get_info - return information about
+// the back-end implementation
+//-------------------------------------------------
+
+void drcbe_x86::get_info(drcbe_info &info)
+{
+ for (info.direct_iregs = 0; info.direct_iregs < REG_I_COUNT; info.direct_iregs++)
+ if (int_register_map[info.direct_iregs] == 0)
+ break;
+ info.direct_fregs = 0;
+}
+
+
+
+//**************************************************************************
+// EMITTERS FOR 32-BIT OPERATIONS WITH PARAMETERS
+//**************************************************************************
+
+//-------------------------------------------------
+// emit_mov_r32_p32 - move a 32-bit parameter
+// into a register
+//-------------------------------------------------
+
+void drcbe_x86::emit_mov_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param)
+{
+ if (param.is_immediate())
+ {
+ if (param.immediate() == 0)
+ emit_xor_r32_r32(dst, reg, reg); // xor reg,reg
+ else
+ emit_mov_r32_imm(dst, reg, param.immediate()); // mov reg,param
+ }
+ else if (param.is_memory())
+ emit_mov_r32_m32(dst, reg, MABS(param.memory())); // mov reg,[param]
+ else if (param.is_int_register())
+ {
+ if (reg != param.ireg())
+ emit_mov_r32_r32(dst, reg, param.ireg()); // mov reg,param
+ }
+}
+
+
+//-------------------------------------------------
+// emit_mov_r32_p32_keepflags - move a 32-bit
+// parameter into a register without affecting
+// any flags
+//-------------------------------------------------
+
+void drcbe_x86::emit_mov_r32_p32_keepflags(x86code *&dst, UINT8 reg, const be_parameter &param)
+{
+ if (param.is_immediate())
+ emit_mov_r32_imm(dst, reg, param.immediate()); // mov reg,param
+ else if (param.is_memory())
+ {
+ if (!can_skip_lower_load(dst, (UINT32 *)((FPTR)param.memory()), reg))
+ emit_mov_r32_m32(dst, reg, MABS(param.memory())); // mov reg,[param]
+ }
+ else if (param.is_int_register())
+ {
+ if (reg != param.ireg())
+ emit_mov_r32_r32(dst, reg, param.ireg()); // mov reg,param
+ }
+}
+
+
+//-------------------------------------------------
+// emit_mov_m32_p32 - move a 32-bit parameter
+// into a memory location
+//-------------------------------------------------
+
+void drcbe_x86::emit_mov_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param)
+{
+ if (param.is_immediate())
+ emit_mov_m32_imm(dst, memref, param.immediate()); // mov [mem],param
+ else if (param.is_memory())
+ {
+ if (!can_skip_lower_load(dst, (UINT32 *)((FPTR)param.memory()), REG_EAX))
+ emit_mov_r32_m32(dst, REG_EAX, MABS(param.memory())); // mov eax,[param]
+ emit_mov_m32_r32(dst, memref, REG_EAX); // mov [mem],eax
+ }
+ else if (param.is_int_register())
+ emit_mov_m32_r32(dst, memref, param.ireg()); // mov [mem],param
+}
+
+
+//-------------------------------------------------
+// emit_mov_p32_r32 - move a register into a
+// 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_mov_p32_r32(x86code *&dst, const be_parameter &param, UINT8 reg)
+{
+ assert(!param.is_immediate());
+ if (param.is_memory())
+ {
+ emit_mov_m32_r32(dst, MABS(param.memory()), reg); // mov [param],reg
+ set_last_lower_reg(dst, param, reg);
+ }
+ else if (param.is_int_register())
+ {
+ if (reg != param.ireg())
+ emit_mov_r32_r32(dst, param.ireg(), reg); // mov param,reg
+ }
+}
+
+
+//-------------------------------------------------
+// emit_add_r32_p32 - add operation to a 32-bit
+// register from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_add_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() != 0 || param.immediate() != 0)
+ emit_add_r32_imm(dst, reg, param.immediate()); // add reg,param
+ }
+ else if (param.is_memory())
+ emit_add_r32_m32(dst, reg, MABS(param.memory())); // add reg,[param]
+ else if (param.is_int_register())
+ emit_add_r32_r32(dst, reg, param.ireg()); // add reg,param
+}
+
+
+//-------------------------------------------------
+// emit_add_m32_p32 - add operation to a 32-bit
+// memory location from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_add_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() != 0 || param.immediate() != 0)
+ emit_add_m32_imm(dst, memref, param.immediate()); // add [dest],param
+ }
+ else
+ {
+ int reg = param.select_register(REG_EAX);
+ emit_mov_r32_p32(dst, reg, param); // mov reg,param
+ emit_add_m32_r32(dst, memref, reg); // add [dest],reg
+ }
+}
+
+
+//-------------------------------------------------
+// emit_adc_r32_p32 - adc operation to a 32-bit
+// register from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_adc_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ emit_adc_r32_imm(dst, reg, param.immediate()); // adc reg,param
+ else if (param.is_memory())
+ emit_adc_r32_m32(dst, reg, MABS(param.memory())); // adc reg,[param]
+ else if (param.is_int_register())
+ emit_adc_r32_r32(dst, reg, param.ireg()); // adc reg,param
+}
+
+
+//-------------------------------------------------
+// emit_adc_m32_p32 - adc operation to a 32-bit
+// memory location from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_adc_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ emit_adc_m32_imm(dst, memref, param.immediate()); // adc [dest],param
+ else
+ {
+ int reg = param.select_register(REG_EAX);
+ emit_mov_r32_p32_keepflags(dst, reg, param); // mov reg,param
+ emit_adc_m32_r32(dst, memref, reg); // adc [dest],reg
+ }
+}
+
+
+//-------------------------------------------------
+// emit_sub_r32_p32 - sub operation to a 32-bit
+// register from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_sub_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() != 0 || param.immediate() != 0)
+ emit_sub_r32_imm(dst, reg, param.immediate()); // sub reg,param
+ }
+ else if (param.is_memory())
+ emit_sub_r32_m32(dst, reg, MABS(param.memory())); // sub reg,[param]
+ else if (param.is_int_register())
+ emit_sub_r32_r32(dst, reg, param.ireg()); // sub reg,param
+}
+
+
+//-------------------------------------------------
+// emit_sub_m32_p32 - sub operation to a 32-bit
+// memory location from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_sub_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() != 0 || param.immediate() != 0)
+ emit_sub_m32_imm(dst, memref, param.immediate()); // sub [dest],param
+ }
+ else
+ {
+ int reg = param.select_register(REG_EAX);
+ emit_mov_r32_p32(dst, reg, param); // mov reg,param
+ emit_sub_m32_r32(dst, memref, reg); // sub [dest],reg
+ }
+}
+
+
+//-------------------------------------------------
+// emit_sbb_r32_p32 - sbb operation to a 32-bit
+// register from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_sbb_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ emit_sbb_r32_imm(dst, reg, param.immediate()); // sbb reg,param
+ else if (param.is_memory())
+ emit_sbb_r32_m32(dst, reg, MABS(param.memory())); // sbb reg,[param]
+ else if (param.is_int_register())
+ emit_sbb_r32_r32(dst, reg, param.ireg()); // sbb reg,param
+}
+
+
+//-------------------------------------------------
+// emit_sbb_m32_p32 - sbb operation to a 32-bit
+// memory location from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_sbb_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ emit_sbb_m32_imm(dst, memref, param.immediate()); // sbb [dest],param
+ else
+ {
+ int reg = param.select_register(REG_EAX);
+ emit_mov_r32_p32_keepflags(dst, reg, param); // mov reg,param
+ emit_sbb_m32_r32(dst, memref, reg); // sbb [dest],reg
+ }
+}
+
+
+//-------------------------------------------------
+// emit_cmp_r32_p32 - cmp operation to a 32-bit
+// register from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_cmp_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ emit_cmp_r32_imm(dst, reg, param.immediate()); // cmp reg,param
+ else if (param.is_memory())
+ emit_cmp_r32_m32(dst, reg, MABS(param.memory())); // cmp reg,[param]
+ else if (param.is_int_register())
+ emit_cmp_r32_r32(dst, reg, param.ireg()); // cmp reg,param
+}
+
+
+//-------------------------------------------------
+// emit_cmp_m32_p32 - cmp operation to a 32-bit
+// memory location from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_cmp_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ emit_cmp_m32_imm(dst, memref, param.immediate()); // cmp [dest],param
+ else
+ {
+ int reg = param.select_register(REG_EAX);
+ emit_mov_r32_p32(dst, reg, param); // mov reg,param
+ emit_cmp_m32_r32(dst, memref, reg); // cmp [dest],reg
+ }
+}
+
+
+//-------------------------------------------------
+// emit_and_r32_p32 - and operation to a 32-bit
+// register from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_and_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
+ ;// skip
+ else if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ emit_xor_r32_r32(dst, reg, reg); // xor reg,reg
+ else
+ emit_and_r32_imm(dst, reg, param.immediate()); // and reg,param
+ }
+ else if (param.is_memory())
+ emit_and_r32_m32(dst, reg, MABS(param.memory())); // and reg,[param]
+ else if (param.is_int_register())
+ emit_and_r32_r32(dst, reg, param.ireg()); // and reg,param
+}
+
+
+//-------------------------------------------------
+// emit_and_m32_p32 - and operation to a 32-bit
+// memory location from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_and_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
+ ;// skip
+ else if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ emit_mov_m32_imm(dst, memref, 0); // mov [dest],0
+ else
+ emit_and_m32_imm(dst, memref, param.immediate()); // and [dest],param
+ }
+ else
+ {
+ int reg = param.select_register(REG_EAX);
+ emit_mov_r32_p32(dst, reg, param); // mov reg,param
+ emit_and_m32_r32(dst, memref, reg); // and [dest],reg
+ }
+}
+
+
+//-------------------------------------------------
+// emit_test_r32_p32 - test operation to a 32-bit
+// register from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_test_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ emit_test_r32_imm(dst, reg, param.immediate()); // test reg,param
+ else if (param.is_memory())
+ emit_test_m32_r32(dst, MABS(param.memory()), reg); // test [param],reg
+ else if (param.is_int_register())
+ emit_test_r32_r32(dst, reg, param.ireg()); // test reg,param
+}
+
+
+//-------------------------------------------------
+// emit_test_m32_p32 - test operation to a 32-bit
+// memory location from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_test_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ emit_test_m32_imm(dst, memref, param.immediate()); // test [dest],param
+ else if (param.is_memory())
+ {
+ emit_mov_r32_p32(dst, REG_EAX, param); // mov reg,param
+ emit_test_m32_r32(dst, memref, REG_EAX); // test [dest],reg
+ }
+ else if (param.is_int_register())
+ emit_test_m32_r32(dst, memref, param.ireg()); // test [dest],param
+}
+
+
+//-------------------------------------------------
+// emit_or_r32_p32 - or operation to a 32-bit
+// register from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_or_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
+ emit_mov_r32_imm(dst, reg, ~0); // mov reg,-1
+ else
+ emit_or_r32_imm(dst, reg, param.immediate()); // or reg,param
+ }
+ else if (param.is_memory())
+ emit_or_r32_m32(dst, reg, MABS(param.memory())); // or reg,[param]
+ else if (param.is_int_register())
+ emit_or_r32_r32(dst, reg, param.ireg()); // or reg,param
+}
+
+
+//-------------------------------------------------
+// emit_or_m32_p32 - or operation to a 32-bit
+// memory location from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_or_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
+ emit_mov_m32_imm(dst, memref, ~0); // mov [dest],-1
+ else
+ emit_or_m32_imm(dst, memref, param.immediate()); // or [dest],param
+ }
+ else
+ {
+ int reg = param.select_register(REG_EAX);
+ emit_mov_r32_p32(dst, reg, param); // mov reg,param
+ emit_or_m32_r32(dst, memref, reg); // or [dest],reg
+ }
+}
+
+
+//-------------------------------------------------
+// emit_xor_r32_p32 - xor operation to a 32-bit
+// register from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_xor_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
+ emit_not_r32(dst, reg); // not reg
+ else
+ emit_xor_r32_imm(dst, reg, param.immediate()); // xor reg,param
+ }
+ else if (param.is_memory())
+ emit_xor_r32_m32(dst, reg, MABS(param.memory())); // xor reg,[param]
+ else if (param.is_int_register())
+ emit_xor_r32_r32(dst, reg, param.ireg()); // xor reg,param
+}
+
+
+//-------------------------------------------------
+// emit_xor_m32_p32 - xor operation to a 32-bit
+// memory location from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_xor_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
+ emit_not_m32(dst, memref); // not [dest]
+ else
+ emit_xor_m32_imm(dst, memref, param.immediate()); // xor [dest],param
+ }
+ else
+ {
+ int reg = param.select_register(REG_EAX);
+ emit_mov_r32_p32(dst, reg, param); // mov reg,param
+ emit_xor_m32_r32(dst, memref, reg); // xor [dest],reg
+ }
+}
+
+
+//-------------------------------------------------
+// emit_shl_r32_p32 - shl operation to a 32-bit
+// register from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_shl_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else
+ emit_shl_r32_imm(dst, reg, param.immediate()); // shl reg,param
+ }
+ else
+ {
+ emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param
+ emit_shl_r32_cl(dst, reg); // shl reg,cl
+ }
+}
+
+
+//-------------------------------------------------
+// emit_shl_m32_p32 - shl operation to a 32-bit
+// memory location from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_shl_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else
+ emit_shl_m32_imm(dst, memref, param.immediate()); // shl [dest],param
+ }
+ else
+ {
+ emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param
+ emit_shl_m32_cl(dst, memref); // shl [dest],cl
+ }
+}
+
+
+//-------------------------------------------------
+// emit_shr_r32_p32 - shr operation to a 32-bit
+// register from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_shr_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else
+ emit_shr_r32_imm(dst, reg, param.immediate()); // shr reg,param
+ }
+ else
+ {
+ emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param
+ emit_shr_r32_cl(dst, reg); // shr reg,cl
+ }
+}
+
+
+//-------------------------------------------------
+// emit_shr_m32_p32 - shr operation to a 32-bit
+// memory location from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_shr_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else
+ emit_shr_m32_imm(dst, memref, param.immediate()); // shr [dest],param
+ }
+ else
+ {
+ emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param
+ emit_shr_m32_cl(dst, memref); // shr [dest],cl
+ }
+}
+
+
+//-------------------------------------------------
+// emit_sar_r32_p32 - sar operation to a 32-bit
+// register from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_sar_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else
+ emit_sar_r32_imm(dst, reg, param.immediate()); // sar reg,param
+ }
+ else
+ {
+ emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param
+ emit_sar_r32_cl(dst, reg); // sar reg,cl
+ }
+}
+
+
+//-------------------------------------------------
+// emit_sar_m32_p32 - sar operation to a 32-bit
+// memory location from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_sar_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else
+ emit_sar_m32_imm(dst, memref, param.immediate()); // sar [dest],param
+ }
+ else
+ {
+ emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param
+ emit_sar_m32_cl(dst, memref); // sar [dest],cl
+ }
+}
+
+
+//-------------------------------------------------
+// emit_rol_r32_p32 - rol operation to a 32-bit
+// register from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_rol_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else
+ emit_rol_r32_imm(dst, reg, param.immediate()); // rol reg,param
+ }
+ else
+ {
+ emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param
+ emit_rol_r32_cl(dst, reg); // rol reg,cl
+ }
+}
+
+
+//-------------------------------------------------
+// emit_rol_m32_p32 - rol operation to a 32-bit
+// memory location from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_rol_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else
+ emit_rol_m32_imm(dst, memref, param.immediate()); // rol [dest],param
+ }
+ else
+ {
+ emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param
+ emit_rol_m32_cl(dst, memref); // rol [dest],cl
+ }
+}
+
+
+//-------------------------------------------------
+// emit_ror_r32_p32 - ror operation to a 32-bit
+// register from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_ror_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else
+ emit_ror_r32_imm(dst, reg, param.immediate()); // ror reg,param
+ }
+ else
+ {
+ emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param
+ emit_ror_r32_cl(dst, reg); // ror reg,cl
+ }
+}
+
+
+//-------------------------------------------------
+// emit_ror_m32_p32 - ror operation to a 32-bit
+// memory location from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_ror_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else
+ emit_ror_m32_imm(dst, memref, param.immediate()); // ror [dest],param
+ }
+ else
+ {
+ emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param
+ emit_ror_m32_cl(dst, memref); // ror [dest],cl
+ }
+}
+
+
+//-------------------------------------------------
+// emit_rcl_r32_p32 - rcl operation to a 32-bit
+// register from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_rcl_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else
+ emit_rcl_r32_imm(dst, reg, param.immediate()); // rcl reg,param
+ }
+ else
+ {
+ emit_mov_r32_p32_keepflags(dst, REG_ECX, param); // mov ecx,param
+ emit_rcl_r32_cl(dst, reg); // rcl reg,cl
+ }
+}
+
+
+//-------------------------------------------------
+// emit_rcl_m32_p32 - rcl operation to a 32-bit
+// memory location from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_rcl_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else
+ emit_rcl_m32_imm(dst, memref, param.immediate()); // rcl [dest],param
+ }
+ else
+ {
+ emit_mov_r32_p32_keepflags(dst, REG_ECX, param); // mov ecx,param
+ emit_rcl_m32_cl(dst, memref); // rcl [dest],cl
+ }
+}
+
+
+//-------------------------------------------------
+// emit_rcr_r32_p32 - rcr operation to a 32-bit
+// register from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_rcr_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else
+ emit_rcr_r32_imm(dst, reg, param.immediate()); // rcr reg,param
+ }
+ else
+ {
+ emit_mov_r32_p32_keepflags(dst, REG_ECX, param); // mov ecx,param
+ emit_rcr_r32_cl(dst, reg); // rcr reg,cl
+ }
+}
+
+
+//-------------------------------------------------
+// emit_rcr_m32_p32 - rcr operation to a 32-bit
+// memory location from a 32-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_rcr_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else
+ emit_rcr_m32_imm(dst, memref, param.immediate()); // rcr [dest],param
+ }
+ else
+ {
+ emit_mov_r32_p32_keepflags(dst, REG_ECX, param); // mov ecx,param
+ emit_rcr_m32_cl(dst, memref); // rcr [dest],cl
+ }
+}
+
+
+
+//**************************************************************************
+// EMITTERS FOR 64-BIT OPERATIONS WITH PARAMETERS
+//**************************************************************************
+
+//-------------------------------------------------
+// emit_mov_r64_p64 - move a 64-bit parameter
+// into a pair of registers
+//-------------------------------------------------
+
+void drcbe_x86::emit_mov_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param)
+{
+ if (param.is_immediate())
+ {
+ if (reglo == REG_NONE)
+ ;
+ else if ((UINT32)param.immediate() == 0)
+ emit_xor_r32_r32(dst, reglo, reglo); // xor reglo,reglo
+ else
+ emit_mov_r32_imm(dst, reglo, param.immediate()); // mov reglo,param
+ if (reghi == REG_NONE)
+ ;
+ else if ((UINT32)(param.immediate() >> 32) == 0)
+ emit_xor_r32_r32(dst, reghi, reghi); // xor reghi,reghi
+ else
+ emit_mov_r32_imm(dst, reghi, param.immediate() >> 32); // mov reghi,param >> 32
+ }
+ else if (param.is_memory())
+ {
+ int skip_lower = can_skip_lower_load(dst, (UINT32 *)((FPTR)param.memory()), reglo);
+ int skip_upper = can_skip_upper_load(dst, (UINT32 *)((FPTR)param.memory(4)), reghi);
+ if (reglo != REG_NONE && !skip_lower)
+ emit_mov_r32_m32(dst, reglo, MABS(param.memory())); // mov reglo,[param]
+ if (reghi != REG_NONE && !skip_upper)
+ emit_mov_r32_m32(dst, reghi, MABS(param.memory(4))); // mov reghi,[param+4]
+ }
+ else if (param.is_int_register())
+ {
+ int skip_upper = can_skip_upper_load(dst, m_reghi[param.ireg()], reghi);
+ if (reglo != REG_NONE && reglo != param.ireg())
+ emit_mov_r32_r32(dst, reglo, param.ireg()); // mov reglo,param
+ if (reghi != REG_NONE && !skip_upper)
+ emit_mov_r32_m32(dst, reghi, MABS(m_reghi[param.ireg()])); // mov reghi,reghi[param]
+ }
+}
+
+
+//-------------------------------------------------
+// emit_mov_r64_p64_keepflags - move a 64-bit
+// parameter into a pair of registers without
+// affecting any flags
+//-------------------------------------------------
+
+void drcbe_x86::emit_mov_r64_p64_keepflags(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param)
+{
+ if (param.is_immediate())
+ {
+ if (reglo != REG_NONE)
+ emit_mov_r32_imm(dst, reglo, param.immediate()); // mov reglo,param
+ if (reghi != REG_NONE)
+ emit_mov_r32_imm(dst, reghi, param.immediate() >> 32); // mov reghi,param >> 32
+ }
+ else if (param.is_memory())
+ {
+ int skip_lower = can_skip_lower_load(dst, (UINT32 *)((FPTR)param.memory()), reglo);
+ int skip_upper = can_skip_upper_load(dst, (UINT32 *)((FPTR)param.memory(4)), reghi);
+ if (reglo != REG_NONE && !skip_lower)
+ emit_mov_r32_m32(dst, reglo, MABS(param.memory())); // mov reglo,[param]
+ if (reghi != REG_NONE && !skip_upper)
+ emit_mov_r32_m32(dst, reghi, MABS(param.memory(4))); // mov reghi,[param+4]
+ }
+ else if (param.is_int_register())
+ {
+ int skip_upper = can_skip_upper_load(dst, m_reghi[param.ireg()], reghi);
+ if (reglo != REG_NONE && reglo != param.ireg())
+ emit_mov_r32_r32(dst, reglo, param.ireg()); // mov reglo,param
+ if (reghi != REG_NONE && !skip_upper)
+ emit_mov_r32_m32(dst, reghi, MABS(m_reghi[param.ireg()])); // mov reghi,reghi[param]
+ }
+}
+
+
+//-------------------------------------------------
+// emit_mov_m64_p64 - move a 64-bit parameter
+// into a memory location
+//-------------------------------------------------
+
+void drcbe_x86::emit_mov_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param)
+{
+ if (param.is_immediate())
+ {
+ emit_mov_m32_imm(dst, memref + 0, param.immediate()); // mov [mem],param
+ emit_mov_m32_imm(dst, memref + 4, param.immediate() >> 32); // mov [mem],param >> 32
+ }
+ else if (param.is_memory())
+ {
+ int skip_lower = can_skip_lower_load(dst, (UINT32 *)((FPTR)param.memory()), REG_EAX);
+ if (!skip_lower)
+ emit_mov_r32_m32(dst, REG_EAX, MABS(param.memory())); // mov eax,[param]
+ emit_mov_m32_r32(dst, memref + 0, REG_EAX); // mov [mem],eax
+ emit_mov_r32_m32(dst, REG_EAX, MABS(param.memory(4))); // mov eax,[param+4]
+ emit_mov_m32_r32(dst, memref + 4, REG_EAX); // mov [mem+4],eax
+ }
+ else if (param.is_int_register())
+ {
+ emit_mov_m32_r32(dst, memref + 0, param.ireg()); // mov [mem],param
+ emit_mov_r32_m32(dst, REG_EAX, MABS(m_reghi[param.ireg()])); // mov eax,[param.hi]
+ emit_mov_m32_r32(dst, memref + 4, REG_EAX); // mov [mem+4],eax
+ }
+}
+
+
+//-------------------------------------------------
+// emit_mov_p64_r64 - move a pair of registers
+// into a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_mov_p64_r64(x86code *&dst, const be_parameter &param, UINT8 reglo, UINT8 reghi)
+{
+ assert(!param.is_immediate());
+ if (param.is_memory())
+ {
+ emit_mov_m32_r32(dst, MABS(param.memory()), reglo); // mov [param],reglo
+ emit_mov_m32_r32(dst, MABS(param.memory(4)), reghi); // mov [param+4],reghi
+ }
+ else if (param.is_int_register())
+ {
+ if (reglo != param.ireg())
+ emit_mov_r32_r32(dst, param.ireg(), reglo); // mov param,reglo
+ emit_mov_m32_r32(dst, MABS(m_reghi[param.ireg()]), reghi); // mov reghi[param],reghi
+ }
+ set_last_lower_reg(dst, param, reglo);
+ set_last_upper_reg(dst, param, reghi);
+}
+
+
+//-------------------------------------------------
+// emit_add_r64_p64 - add operation to a 64-bit
+// pair of registers from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_add_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const instruction &inst)
+{
+ int saveflags = ((inst.flags() & FLAG_Z) != 0);
+ if (param.is_memory())
+ {
+ emit_add_r32_m32(dst, reglo, MABS(param.memory())); // add reglo,[param]
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_adc_r32_m32(dst, reghi, MABS(param.memory(4))); // adc reghi,[param]
+ }
+ else if (param.is_immediate())
+ {
+ emit_add_r32_imm(dst, reglo, param.immediate()); // add reglo,param
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_adc_r32_imm(dst, reghi, param.immediate() >> 32); // adc reghi,param >> 32
+ }
+ else if (param.is_int_register())
+ {
+ emit_add_r32_r32(dst, reglo, param.ireg()); // add reglo,param
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_adc_r32_m32(dst, reghi, MABS(m_reghi[param.ireg()])); // adc reghi,reghi[param]
+ }
+ if (saveflags)
+ emit_combine_z_flags(dst);
+}
+
+
+//-------------------------------------------------
+// emit_add_m64_p64 - add operation to a 64-bit
+// memory location from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_add_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ int saveflags = ((inst.flags() & FLAG_Z) != 0);
+ if (param.is_immediate())
+ {
+ emit_add_m32_imm(dst, memref, param.immediate()); // add [dest],param
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_adc_m32_imm(dst, memref + 4, param.immediate() >> 32); // adc [dest+4],param >> 32
+ }
+ else
+ {
+ int reglo = (param.is_int_register()) ? param.ireg() : REG_EAX;
+ emit_mov_r64_p64(dst, reglo, REG_EDX, param); // mov edx:reglo,param
+ emit_add_m32_r32(dst, memref, reglo); // add [dest],reglo
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_adc_m32_r32(dst, memref + 4, REG_EDX); // adc [dest+4],edx
+ }
+ if (saveflags)
+ emit_combine_z_flags(dst);
+}
+
+
+//-------------------------------------------------
+// emit_adc_r64_p64 - adc operation to a 64-bit
+// pair of registers from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_adc_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const instruction &inst)
+{
+ int saveflags = ((inst.flags() & FLAG_Z) != 0);
+ if (param.is_memory())
+ {
+ emit_adc_r32_m32(dst, reglo, MABS(param.memory())); // adc reglo,[param]
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_adc_r32_m32(dst, reghi, MABS(param.memory(4))); // adc reghi,[param]
+ }
+ else if (param.is_immediate())
+ {
+ emit_adc_r32_imm(dst, reglo, param.immediate()); // adc reglo,param
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_adc_r32_imm(dst, reghi, param.immediate() >> 32); // adc reghi,param >> 32
+ }
+ else if (param.is_int_register())
+ {
+ emit_adc_r32_r32(dst, reglo, param.ireg()); // adc reglo,param
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_adc_r32_m32(dst, reghi, MABS(m_reghi[param.ireg()])); // adc reghi,reghi[param]
+ }
+ if (saveflags)
+ emit_combine_z_flags(dst);
+}
+
+
+//-------------------------------------------------
+// emit_adc_m64_p64 - adc operation to a 64-bit
+// memory location from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_adc_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ int saveflags = ((inst.flags() & FLAG_Z) != 0);
+ if (param.is_immediate())
+ {
+ emit_adc_m32_imm(dst, memref, param.immediate()); // adc [dest],param
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_adc_m32_imm(dst, memref + 4, param.immediate() >> 32); // adc [dest+4],param >> 32
+ }
+ else
+ {
+ int reglo = (param.is_int_register()) ? param.ireg() : REG_EAX;
+ emit_mov_r64_p64_keepflags(dst, reglo, REG_EDX, param); // mov edx:reglo,param
+ emit_adc_m32_r32(dst, memref, reglo); // adc [dest],reglo
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_adc_m32_r32(dst, memref + 4, REG_EDX); // adc [dest+4],edx
+ }
+ if (saveflags)
+ emit_combine_z_flags(dst);
+}
+
+
+//-------------------------------------------------
+// emit_sub_r64_p64 - sub operation to a 64-bit
+// pair of registers from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_sub_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const instruction &inst)
+{
+ int saveflags = ((inst.flags() & FLAG_Z) != 0);
+ if (param.is_memory())
+ {
+ emit_sub_r32_m32(dst, reglo, MABS(param.memory())); // sub reglo,[param]
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_sbb_r32_m32(dst, reghi, MABS(param.memory(4))); // sbb reghi,[param]
+ }
+ else if (param.is_immediate())
+ {
+ emit_sub_r32_imm(dst, reglo, param.immediate()); // sub reglo,param
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_sbb_r32_imm(dst, reghi, param.immediate() >> 32); // sbb reghi,param >> 32
+ }
+ else if (param.is_int_register())
+ {
+ emit_sub_r32_r32(dst, reglo, param.ireg()); // sub reglo,param
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_sbb_r32_m32(dst, reghi, MABS(m_reghi[param.ireg()])); // sbb reghi,reghi[param]
+ }
+ if (saveflags)
+ emit_combine_z_flags(dst);
+}
+
+
+//-------------------------------------------------
+// emit_sub_m64_p64 - sub operation to a 64-bit
+// memory location from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_sub_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ int saveflags = ((inst.flags() & FLAG_Z) != 0);
+ if (param.is_immediate())
+ {
+ emit_sub_m32_imm(dst, memref, param.immediate()); // sub [dest],param
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_sbb_m32_imm(dst, memref + 4, param.immediate() >> 32); // sbb [dest+4],param >> 32
+ }
+ else
+ {
+ int reglo = (param.is_int_register()) ? param.ireg() : REG_EAX;
+ emit_mov_r64_p64(dst, reglo, REG_EDX, param); // mov edx:reglo,param
+ emit_sub_m32_r32(dst, memref, reglo); // sub [dest],reglo
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_sbb_m32_r32(dst, memref + 4, REG_EDX); // sbb [dest+4],edx
+ }
+ if (saveflags)
+ emit_combine_z_flags(dst);
+}
+
+
+//-------------------------------------------------
+// emit_sbb_r64_p64 - sbb operation to a 64-bit
+// pair of registers from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_sbb_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const instruction &inst)
+{
+ int saveflags = ((inst.flags() & FLAG_Z) != 0);
+ if (param.is_memory())
+ {
+ emit_sbb_r32_m32(dst, reglo, MABS(param.memory())); // sbb reglo,[param]
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_sbb_r32_m32(dst, reghi, MABS(param.memory(4))); // sbb reghi,[param]
+ }
+ else if (param.is_immediate())
+ {
+ emit_sbb_r32_imm(dst, reglo, param.immediate()); // sbb reglo,param
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_sbb_r32_imm(dst, reghi, param.immediate() >> 32); // sbb reghi,param >> 32
+ }
+ else if (param.is_int_register())
+ {
+ emit_sbb_r32_r32(dst, reglo, param.ireg()); // sbb reglo,param
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_sbb_r32_m32(dst, reghi, MABS(m_reghi[param.ireg()])); // sbb reghi,reghi[param]
+ }
+ if (saveflags)
+ emit_combine_z_flags(dst);
+}
+
+
+//-------------------------------------------------
+// emit_sbb_m64_p64 - sbb operation to a 64-bit
+// memory location from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_sbb_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ int saveflags = ((inst.flags() & FLAG_Z) != 0);
+ if (param.is_immediate())
+ {
+ emit_sbb_m32_imm(dst, memref, param.immediate()); // sbb [dest],param
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_sbb_m32_imm(dst, memref + 4, param.immediate() >> 32); // sbb [dest+4],param >> 32
+ }
+ else
+ {
+ int reglo = (param.is_int_register()) ? param.ireg() : REG_EAX;
+ emit_mov_r64_p64_keepflags(dst, reglo, REG_EDX, param); // mov edx:reglo,param
+ emit_sbb_m32_r32(dst, memref, reglo); // sbb [dest],reglo
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_sbb_m32_r32(dst, memref + 4, REG_EDX); // sbb [dest+4],edx
+ }
+ if (saveflags)
+ emit_combine_z_flags(dst);
+}
+
+
+//-------------------------------------------------
+// emit_cmp_r64_p64 - sub operation to a 64-bit
+// pair of registers from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_cmp_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const instruction &inst)
+{
+ int saveflags = (inst.flags() != FLAG_Z && (inst.flags() & FLAG_Z) != 0);
+ if (param.is_memory())
+ {
+ emit_sub_r32_m32(dst, reglo, MABS(param.memory())); // sub reglo,[param]
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_sbb_r32_m32(dst, reghi, MABS(param.memory(4))); // sbb reghi,[param]
+ }
+ else if (param.is_immediate())
+ {
+ emit_sub_r32_imm(dst, reglo, param.immediate()); // sub reglo,param
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_sbb_r32_imm(dst, reghi, param.immediate() >> 32); // sbb reghi,param >> 32
+ }
+ else if (param.is_int_register())
+ {
+ emit_sub_r32_r32(dst, reglo, param.ireg()); // sub reglo,param
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_sbb_r32_m32(dst, reghi, MABS(m_reghi[param.ireg()])); // sbb reghi,reghi[param]
+ }
+ if (inst.flags() == FLAG_Z)
+ emit_or_r32_r32(dst, reghi, reglo); // or reghi,reglo
+ else if (saveflags)
+ emit_combine_z_flags(dst);
+}
+
+
+//-------------------------------------------------
+// emit_and_r64_p64 - and operation to a 64-bit
+// pair of registers from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_and_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const instruction &inst)
+{
+ int saveflags = ((inst.flags() & FLAG_Z) != 0);
+ if (param.is_memory())
+ {
+ emit_and_r32_m32(dst, reglo, MABS(param.memory())); // and reglo,[param]
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_and_r32_m32(dst, reghi, MABS(param.memory(4))); // and reghi,[param]
+ }
+ else if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
+ ;// skip
+ else if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ emit_xor_r32_r32(dst, reglo, reglo); // xor reglo,reglo
+ else
+ emit_and_r32_imm(dst, reglo, param.immediate()); // and reglo,param
+ if (saveflags) emit_pushf(dst); // pushf
+ if (inst.flags() == 0 && (UINT32)(param.immediate() >> 32) == 0xffffffff)
+ ;// skip
+ else if (inst.flags() == 0 && (UINT32)(param.immediate() >> 32) == 0)
+ emit_xor_r32_r32(dst, reghi, reghi); // xor reghi,reghi
+ else
+ emit_and_r32_imm(dst, reghi, param.immediate() >> 32); // and reghi,param >> 32
+ }
+ else if (param.is_int_register())
+ {
+ emit_and_r32_r32(dst, reglo, param.ireg()); // and reglo,param
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_and_r32_m32(dst, reghi, MABS(m_reghi[param.ireg()])); // and reghi,reghi[param]
+ }
+ if (saveflags)
+ emit_combine_z_flags(dst);
+}
+
+
+//-------------------------------------------------
+// emit_and_m64_p64 - and operation to a 64-bit
+// memory location from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_and_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ int saveflags = ((inst.flags() & FLAG_Z) != 0);
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
+ ;// skip
+ else if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ emit_mov_m32_imm(dst, memref, 0); // mov [dest],0
+ else
+ emit_and_m32_imm(dst, memref, param.immediate()); // and [dest],param
+ if (saveflags) emit_pushf(dst); // pushf
+ if (inst.flags() == 0 && (UINT32)(param.immediate() >> 32) == 0xffffffff)
+ ;// skip
+ else if (inst.flags() == 0 && (UINT32)(param.immediate() >> 32) == 0)
+ emit_mov_m32_imm(dst, memref + 4, 0); // mov [dest+4],0
+ else
+ emit_and_m32_imm(dst, memref + 4, param.immediate() >> 32); // and [dest+4],param >> 32
+ }
+ else
+ {
+ int reglo = (param.is_int_register()) ? param.ireg() : REG_EAX;
+ emit_mov_r64_p64(dst, reglo, REG_EDX, param); // mov edx:reglo,param
+ emit_and_m32_r32(dst, memref, reglo); // and [dest],reglo
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_and_m32_r32(dst, memref + 4, REG_EDX); // and [dest+4],edx
+ }
+ if (saveflags)
+ emit_combine_z_flags(dst);
+}
+
+
+//-------------------------------------------------
+// emit_test_r64_p64 - test operation to a 64-bit
+// pair of registers from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_test_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const instruction &inst)
+{
+ int saveflags = ((inst.flags() & FLAG_Z) != 0);
+ if (param.is_memory())
+ {
+ emit_test_m32_r32(dst, MABS(param.memory()), reglo); // test [param],reglo
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_test_m32_r32(dst, MABS(param.memory(4)), reghi); // test [param],reghi
+ }
+ else if (param.is_immediate())
+ {
+ emit_test_r32_imm(dst, reglo, param.immediate()); // test reglo,param
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_test_r32_imm(dst, reghi, param.immediate() >> 32); // test reghi,param >> 32
+ }
+ else if (param.is_int_register())
+ {
+ emit_test_r32_r32(dst, reglo, param.ireg()); // test reglo,param
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_test_m32_r32(dst, MABS(m_reghi[param.ireg()]), reghi); // test reghi[param],reghi
+ }
+ if (saveflags)
+ emit_combine_z_flags(dst);
+}
+
+
+//-------------------------------------------------
+// emit_test_m64_p64 - test operation to a 64-bit
+// memory location from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_test_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ int saveflags = ((inst.flags() & FLAG_Z) != 0);
+ if (param.is_immediate())
+ {
+ emit_test_m32_imm(dst, memref, param.immediate()); // test [dest],param
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_test_m32_imm(dst, memref + 4, param.immediate() >> 32); // test [dest+4],param >> 32
+ }
+ else
+ {
+ int reglo = (param.is_int_register()) ? param.ireg() : REG_EAX;
+ emit_mov_r64_p64(dst, reglo, REG_EDX, param); // mov edx:reglo,param
+ emit_test_m32_r32(dst, memref, reglo); // test [dest],reglo
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_test_m32_r32(dst, memref + 4, REG_EDX); // test [dest+4],edx
+ }
+ if (saveflags)
+ emit_combine_z_flags(dst);
+}
+
+
+//-------------------------------------------------
+// emit_or_r64_p64 - or operation to a 64-bit
+// pair of registers from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_or_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const instruction &inst)
+{
+ int saveflags = ((inst.flags() & FLAG_Z) != 0);
+ if (param.is_memory())
+ {
+ emit_or_r32_m32(dst, reglo, MABS(param.memory())); // or reglo,[param]
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_or_r32_m32(dst, reghi, MABS(param.memory(4))); // or reghi,[param]
+ }
+ else if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
+ emit_mov_r32_imm(dst, reglo, ~0); // mov reglo,-1
+ else
+ emit_or_r32_imm(dst, reglo, param.immediate()); // or reglo,param
+ if (saveflags) emit_pushf(dst); // pushf
+ if (inst.flags() == 0 && (UINT32)(param.immediate() >> 32) == 0)
+ ;// skip
+ else if (inst.flags() == 0 && (UINT32)(param.immediate() >> 32) == 0xffffffff)
+ emit_mov_r32_imm(dst, reghi, ~0); // mov reghi,-1
+ else
+ emit_or_r32_imm(dst, reghi, param.immediate() >> 32); // or reghi,param >> 32
+ }
+ else if (param.is_int_register())
+ {
+ emit_or_r32_r32(dst, reglo, param.ireg()); // or reglo,param
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_or_r32_m32(dst, reghi, MABS(m_reghi[param.ireg()])); // or reghi,reghi[param]
+ }
+ if (saveflags)
+ emit_combine_z_flags(dst);
+}
+
+
+//-------------------------------------------------
+// emit_or_m64_p64 - or operation to a 64-bit
+// memory location from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_or_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ int saveflags = ((inst.flags() & FLAG_Z) != 0);
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
+ emit_mov_m32_imm(dst, memref, ~0); // mov [dest],-1
+ else
+ emit_or_m32_imm(dst, memref, param.immediate()); // or [dest],param
+ if (saveflags) emit_pushf(dst); // pushf
+ if (inst.flags() == 0 && (UINT32)(param.immediate() >> 32) == 0)
+ ;// skip
+ else if (inst.flags() == 0 && (UINT32)(param.immediate() >> 32) == 0xffffffff)
+ emit_mov_m32_imm(dst, memref + 4, ~0); // mov [dest+4],-1
+ else
+ emit_or_m32_imm(dst, memref + 4, param.immediate() >> 32); // or [dest+4],param >> 32
+ }
+ else
+ {
+ int reglo = (param.is_int_register()) ? param.ireg() : REG_EAX;
+ emit_mov_r64_p64(dst, reglo, REG_EDX, param); // mov edx:reglo,param
+ emit_or_m32_r32(dst, memref, reglo); // or [dest],reglo
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_or_m32_r32(dst, memref + 4, REG_EDX); // or [dest+4],edx
+ }
+ if (saveflags)
+ emit_combine_z_flags(dst);
+}
+
+
+//-------------------------------------------------
+// emit_xor_r64_p64 - xor operation to a 64-bit
+// pair of registers from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_xor_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const instruction &inst)
+{
+ int saveflags = ((inst.flags() & FLAG_Z) != 0);
+ if (param.is_memory())
+ {
+ emit_xor_r32_m32(dst, reglo, MABS(param.memory())); // xor reglo,[param]
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_xor_r32_m32(dst, reghi, MABS(param.memory(4))); // xor reghi,[param]
+ }
+ else if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
+ emit_not_r32(dst, reglo); // not reglo
+ else
+ emit_xor_r32_imm(dst, reglo, param.immediate()); // xor reglo,param
+ if (saveflags) emit_pushf(dst); // pushf
+ if (inst.flags() == 0 && (UINT32)(param.immediate() >> 32) == 0)
+ ;// skip
+ else if (inst.flags() == 0 && (UINT32)(param.immediate() >> 32) == 0xffffffff)
+ emit_not_r32(dst, reghi); // not reghi
+ else
+ emit_xor_r32_imm(dst, reghi, param.immediate() >> 32); // xor reghi,param >> 32
+ }
+ else if (param.is_int_register())
+ {
+ emit_xor_r32_r32(dst, reglo, param.ireg()); // xor reglo,param
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_xor_r32_m32(dst, reghi, MABS(m_reghi[param.ireg()])); // xor reghi,reghi[param]
+ }
+ if (saveflags)
+ emit_combine_z_flags(dst);
+}
+
+
+//-------------------------------------------------
+// emit_xor_m64_p64 - xor operation to a 64-bit
+// memory location from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_xor_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const instruction &inst)
+{
+ int saveflags = ((inst.flags() & FLAG_Z) != 0);
+ if (param.is_immediate())
+ {
+ if (inst.flags() == 0 && (UINT32)param.immediate() == 0)
+ ;// skip
+ else if (inst.flags() == 0 && (UINT32)param.immediate() == 0xffffffff)
+ emit_not_m32(dst, memref); // not [dest]
+ else
+ emit_xor_m32_imm(dst, memref, param.immediate()); // xor [dest],param
+ if (saveflags) emit_pushf(dst); // pushf
+ if (inst.flags() == 0 && (UINT32)(param.immediate() >> 32) == 0)
+ ;// skip
+ else if (inst.flags() == 0 && (UINT32)(param.immediate() >> 32) == 0xffffffff)
+ emit_not_m32(dst, memref + 4); // not [dest+4]
+ else
+ emit_xor_m32_imm(dst, memref + 4, param.immediate() >> 32); // xor [dest+4],param >> 32
+ }
+ else
+ {
+ int reglo = (param.is_int_register()) ? param.ireg() : REG_EAX;
+ emit_mov_r64_p64(dst, reglo, REG_EDX, param); // mov edx:reglo,param
+ emit_xor_m32_r32(dst, memref, reglo); // xor [dest],reglo
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_xor_m32_r32(dst, memref + 4, REG_EDX); // xor [dest+4],edx
+ }
+ if (saveflags)
+ emit_combine_z_flags(dst);
+}
+
+
+//-------------------------------------------------
+// emit_shl_r64_p64 - shl operation to a 64-bit
+// pair of registers from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_shl_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const instruction &inst)
+{
+ int saveflags = (inst.flags() != 0);
+ if (param.is_immediate())
+ {
+ int count = param.immediate() & 63;
+ if (inst.flags() == 0 && count == 0)
+ ;// skip
+ else
+ {
+ while (count >= 32)
+ {
+ if (inst.flags() != 0)
+ {
+ emit_shld_r32_r32_imm(dst, reghi, reglo, 31); // shld reghi,reglo,31
+ emit_shl_r32_imm(dst, reglo, 31); // shl reglo,31
+ count -= 31;
+ }
+ else
+ {
+ emit_mov_r32_r32(dst, reghi, reglo); // mov reghi,reglo
+ emit_xor_r32_r32(dst, reglo, reglo); // xor reglo,reglo
+ count -= 32;
+ }
+ }
+ if (inst.flags() != 0 || count > 0)
+ {
+ emit_shld_r32_r32_imm(dst, reghi, reglo, count); // shld reghi,reglo,count
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_shl_r32_imm(dst, reglo, count); // shl reglo,count
+ }
+ }
+ }
+ else
+ {
+ emit_link skip1, skip2;
+ emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param
+ emit_test_r32_imm(dst, REG_ECX, 0x20); // test ecx,0x20
+ emit_jcc_short_link(dst, x86emit::COND_Z, skip1); // jz skip1
+ if (inst.flags() != 0)
+ {
+ emit_sub_r32_imm(dst, REG_ECX, 31); // sub ecx,31
+ emit_shld_r32_r32_imm(dst, reghi, reglo, 31); // shld reghi,reglo,31
+ emit_shl_r32_imm(dst, reglo, 31); // shl reglo,31
+ emit_test_r32_imm(dst, REG_ECX, 0x20); // test ecx,0x20
+ emit_jcc_short_link(dst, x86emit::COND_Z, skip2); // jz skip2
+ emit_sub_r32_imm(dst, REG_ECX, 31); // sub ecx,31
+ emit_shld_r32_r32_imm(dst, reghi, reglo, 31); // shld reghi,reglo,31
+ emit_shl_r32_imm(dst, reglo, 31); // shl reglo,31
+ track_resolve_link(dst, skip2); // skip2:
+ }
+ else
+ {
+ emit_mov_r32_r32(dst, reghi, reglo); // mov reghi,reglo
+ emit_xor_r32_r32(dst, reglo, reglo); // xor reglo,reglo
+ }
+ track_resolve_link(dst, skip1); // skip1:
+ emit_shld_r32_r32_cl(dst, reghi, reglo); // shld reghi,reglo,cl
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_shl_r32_cl(dst, reglo); // shl reglo,cl
+ }
+ if (saveflags)
+ emit_combine_z_shl_flags(dst);
+}
+
+
+//-------------------------------------------------
+// emit_shr_r64_p64 - shr operation to a 64-bit
+// pair of registers from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_shr_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const instruction &inst)
+{
+ int saveflags = ((inst.flags() & FLAG_Z) != 0);
+ if (param.is_immediate())
+ {
+ int count = param.immediate() & 63;
+ if (inst.flags() == 0 && count == 0)
+ ;// skip
+ else
+ {
+ while (count >= 32)
+ {
+ if (inst.flags() != 0)
+ {
+ emit_shrd_r32_r32_imm(dst, reglo, reghi, 31); // shrd reglo,reghi,31
+ emit_shr_r32_imm(dst, reghi, 31); // shr reghi,31
+ count -= 31;
+ }
+ else
+ {
+ emit_mov_r32_r32(dst, reglo, reghi); // mov reglo,reghi
+ emit_xor_r32_r32(dst, reghi, reghi); // xor reghi,reghi
+ count -= 32;
+ }
+ }
+ if (inst.flags() != 0 || count > 0)
+ {
+ emit_shrd_r32_r32_imm(dst, reglo, reghi, count); // shrd reglo,reghi,count
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_shr_r32_imm(dst, reghi, count); // shr reghi,count
+ }
+ }
+ }
+ else
+ {
+ emit_link skip1, skip2;
+ emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param
+ emit_test_r32_imm(dst, REG_ECX, 0x20); // test ecx,0x20
+ emit_jcc_short_link(dst, x86emit::COND_Z, skip1); // jz skip1
+ if (inst.flags() != 0)
+ {
+ emit_sub_r32_imm(dst, REG_ECX, 31); // sub ecx,31
+ emit_shrd_r32_r32_imm(dst, reglo, reghi, 31); // shrd reglo,reghi,31
+ emit_shr_r32_imm(dst, reghi, 31); // shr reghi,31
+ emit_test_r32_imm(dst, REG_ECX, 0x20); // test ecx,0x20
+ emit_jcc_short_link(dst, x86emit::COND_Z, skip2); // jz skip2
+ emit_sub_r32_imm(dst, REG_ECX, 31); // sub ecx,31
+ emit_shrd_r32_r32_imm(dst, reglo, reghi, 31); // shrd reglo,reghi,31
+ emit_shr_r32_imm(dst, reghi, 31); // shr reghi,31
+ track_resolve_link(dst, skip2); // skip2:
+ }
+ else
+ {
+ emit_mov_r32_r32(dst, reglo, reghi); // mov reglo,reghi
+ emit_xor_r32_r32(dst, reghi, reghi); // xor reghi,reghi
+ }
+ track_resolve_link(dst, skip1); // skip1:
+ emit_shrd_r32_r32_cl(dst, reglo, reghi); // shrd reglo,reghi,cl
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_shr_r32_cl(dst, reghi); // shr reghi,cl
+ }
+ if (saveflags)
+ emit_combine_z_flags(dst);
+}
+
+
+//-------------------------------------------------
+// emit_sar_r64_p64 - sar operation to a 64-bit
+// pair of registers from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_sar_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const instruction &inst)
+{
+ int saveflags = ((inst.flags() & FLAG_Z) != 0);
+ if (param.is_immediate())
+ {
+ int count = param.immediate() & 63;
+ if (inst.flags() == 0 && count == 0)
+ ;// skip
+ else
+ {
+ while (count >= 32)
+ {
+ if (inst.flags() != 0)
+ {
+ emit_shrd_r32_r32_imm(dst, reglo, reghi, 31); // shrd reglo,reghi,31
+ emit_sar_r32_imm(dst, reghi, 31); // sar reghi,31
+ count -= 31;
+ }
+ else
+ {
+ emit_mov_r32_r32(dst, reglo, reghi); // mov reglo,reghi
+ emit_sar_r32_imm(dst, reghi, 31); // sar reghi,31
+ count -= 32;
+ }
+ }
+ if (inst.flags() != 0 || count > 0)
+ {
+ emit_shrd_r32_r32_imm(dst, reglo, reghi, count); // shrd reglo,reghi,count
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_sar_r32_imm(dst, reghi, count); // sar reghi,count
+ }
+ }
+ }
+ else
+ {
+ emit_link skip1, skip2;
+ emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param
+ emit_test_r32_imm(dst, REG_ECX, 0x20); // test ecx,0x20
+ emit_jcc_short_link(dst, x86emit::COND_Z, skip1); // jz skip1
+ if (inst.flags() != 0)
+ {
+ emit_sub_r32_imm(dst, REG_ECX, 31); // sub ecx,31
+ emit_shrd_r32_r32_imm(dst, reglo, reghi, 31); // shrd reglo,reghi,31
+ emit_sar_r32_imm(dst, reghi, 31); // sar reghi,31
+ emit_test_r32_imm(dst, REG_ECX, 0x20); // test ecx,0x20
+ emit_jcc_short_link(dst, x86emit::COND_Z, skip2); // jz skip
+ emit_sub_r32_imm(dst, REG_ECX, 31); // sub ecx,31
+ emit_shrd_r32_r32_imm(dst, reglo, reghi, 31); // shrd reglo,reghi,31
+ emit_sar_r32_imm(dst, reghi, 31); // sar reghi,31
+ track_resolve_link(dst, skip2); // skip2:
+ }
+ else
+ {
+ emit_mov_r32_r32(dst, reglo, reghi); // mov reglo,reghi
+ emit_sar_r32_imm(dst, reghi, 31); // sar reghi,31
+ }
+ track_resolve_link(dst, skip1); // skip1:
+ emit_shrd_r32_r32_cl(dst, reglo, reghi); // shrd reglo,reghi,cl
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_sar_r32_cl(dst, reghi); // sar reghi,cl
+ }
+ if (saveflags)
+ emit_combine_z_flags(dst);
+}
+
+
+//-------------------------------------------------
+// emit_rol_r64_p64 - rol operation to a 64-bit
+// pair of registers from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_rol_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const instruction &inst)
+{
+ int saveflags = ((inst.flags() & FLAG_Z) != 0);
+ if (param.is_immediate())
+ {
+ int count = param.immediate() & 63;
+ if (inst.flags() == 0 && count == 0)
+ ;// skip
+ else
+ {
+ while (count >= 32)
+ {
+ if (inst.flags() != 0)
+ {
+ emit_mov_r32_r32(dst, REG_ECX, reglo); // mov ecx,reglo
+ emit_shld_r32_r32_imm(dst, reglo, reghi, 31); // shld reglo,reghi,31
+ emit_shld_r32_r32_imm(dst, reghi, REG_ECX, 31); // shld reghi,ecx,31
+ count -= 31;
+ }
+ else
+ {
+ emit_xchg_r32_r32(dst, reghi, reglo); // xchg reghi,reglo
+ count -= 32;
+ }
+ }
+ if (inst.flags() != 0 || count > 0)
+ {
+ emit_mov_r32_r32(dst, REG_ECX, reglo); // mov ecx,reglo
+ emit_shld_r32_r32_imm(dst, reglo, reghi, count); // shld reglo,reghi,count
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_shld_r32_r32_imm(dst, reghi, REG_ECX, count); // shld reghi,ecx,count
+ }
+ }
+ }
+ else
+ {
+ emit_link skip1, skip2;
+ int tempreg = REG_EBX;
+ emit_mov_m32_r32(dst, MBD(REG_ESP, -8), tempreg); // mov [esp-8],ebx
+ emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param
+ emit_test_r32_imm(dst, REG_ECX, 0x20); // test ecx,0x20
+ emit_jcc_short_link(dst, x86emit::COND_Z, skip1); // jz skip1
+ if (inst.flags() != 0)
+ {
+ emit_sub_r32_imm(dst, REG_ECX, 31); // sub ecx,31
+ emit_mov_r32_r32(dst, tempreg, reglo); // mov ebx,reglo
+ emit_shld_r32_r32_imm(dst, reglo, reghi, 31); // shld reglo,reghi,31
+ emit_shld_r32_r32_imm(dst, reghi, tempreg, 31); // shld reghi,ebx,31
+ emit_test_r32_imm(dst, REG_ECX, 0x20); // test ecx,0x20
+ emit_jcc_short_link(dst, x86emit::COND_Z, skip2); // jz skip2
+ emit_sub_r32_imm(dst, REG_ECX, 31); // sub ecx,31
+ emit_mov_r32_r32(dst, tempreg, reglo); // mov ebx,reglo
+ emit_shld_r32_r32_imm(dst, reglo, reghi, 31); // shld reglo,reghi,31
+ emit_shld_r32_r32_imm(dst, reghi, tempreg, 31); // shld reghi,ebx,31
+ track_resolve_link(dst, skip2); // skip2:
+ }
+ else
+ emit_xchg_r32_r32(dst, reghi, reglo); // xchg reghi,reglo
+ track_resolve_link(dst, skip1); // skip1:
+ emit_mov_r32_r32(dst, tempreg, reglo); // mov ebx,reglo
+ emit_shld_r32_r32_cl(dst, reglo, reghi); // shld reglo,reghi,cl
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_shld_r32_r32_cl(dst, reghi, tempreg); // shld reghi,ebx,cl
+ emit_mov_r32_m32(dst, tempreg, MBD(REG_ESP, saveflags ? -4 : -8)); // mov ebx,[esp-8]
+ }
+ if (saveflags)
+ emit_combine_z_flags(dst);
+}
+
+
+//-------------------------------------------------
+// emit_ror_r64_p64 - ror operation to a 64-bit
+// pair of registers from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_ror_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const instruction &inst)
+{
+ int saveflags = ((inst.flags() & FLAG_Z) != 0);
+ if (param.is_immediate())
+ {
+ int count = param.immediate() & 63;
+ if (inst.flags() == 0 && count == 0)
+ ;// skip
+ else
+ {
+ while (count >= 32)
+ {
+ if (inst.flags() != 0)
+ {
+ emit_mov_r32_r32(dst, REG_ECX, reglo); // mov ecx,reglo
+ emit_shrd_r32_r32_imm(dst, reglo, reghi, 31); // shrd reglo,reghi,31
+ emit_shrd_r32_r32_imm(dst, reghi, REG_ECX, 31); // shrd reghi,ecx,31
+ count -= 31;
+ }
+ else
+ {
+ emit_xchg_r32_r32(dst, reghi, reglo); // xchg reghi,reglo
+ count -= 32;
+ }
+ }
+ if (inst.flags() != 0 || count > 0)
+ {
+ emit_mov_r32_r32(dst, REG_ECX, reglo); // mov ecx,reglo
+ emit_shrd_r32_r32_imm(dst, reglo, reghi, count); // shrd reglo,reghi,count
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_shrd_r32_r32_imm(dst, reghi, REG_ECX, count); // shrd reghi,ecx,count
+ }
+ }
+ }
+ else
+ {
+ emit_link skip1, skip2;
+ int tempreg = REG_EBX;
+ emit_mov_m32_r32(dst, MBD(REG_ESP, -8), tempreg); // mov [esp-8],ebx
+ emit_mov_r32_p32(dst, REG_ECX, param); // mov ecx,param
+ emit_test_r32_imm(dst, REG_ECX, 0x20); // test ecx,0x20
+ emit_jcc_short_link(dst, x86emit::COND_Z, skip1); // jz skip1
+ if (inst.flags() != 0)
+ {
+ emit_sub_r32_imm(dst, REG_ECX, 31); // sub ecx,31
+ emit_mov_r32_r32(dst, tempreg, reglo); // mov ebx,reglo
+ emit_shrd_r32_r32_imm(dst, reglo, reghi, 31); // shrd reglo,reghi,31
+ emit_shrd_r32_r32_imm(dst, reghi, tempreg, 31); // shrd reghi,ebx,31
+ emit_test_r32_imm(dst, REG_ECX, 0x20); // test ecx,0x20
+ emit_jcc_short_link(dst, x86emit::COND_Z, skip2); // jz skip2
+ emit_sub_r32_imm(dst, REG_ECX, 31); // sub ecx,31
+ emit_mov_r32_r32(dst, tempreg, reglo); // mov ebx,reglo
+ emit_shrd_r32_r32_imm(dst, reglo, reghi, 31); // shrd reglo,reghi,31
+ emit_shrd_r32_r32_imm(dst, reghi, tempreg, 31); // shrd reghi,ebx,31
+ track_resolve_link(dst, skip2); // skip2:
+ }
+ else
+ emit_xchg_r32_r32(dst, reghi, reglo); // xchg reghi,reglo
+ track_resolve_link(dst, skip1); // skip1:
+ emit_mov_r32_r32(dst, tempreg, reglo); // mov ebx,reglo
+ emit_shrd_r32_r32_cl(dst, reglo, reghi); // shrd reglo,reghi,cl
+ if (saveflags) emit_pushf(dst); // pushf
+ emit_shrd_r32_r32_cl(dst, reghi, tempreg); // shrd reghi,ebx,cl
+ emit_mov_r32_m32(dst, tempreg, MBD(REG_ESP, saveflags ? -4 : -8)); // mov ebx,[esp-8]
+ }
+ if (saveflags)
+ emit_combine_z_flags(dst);
+}
+
+
+//-------------------------------------------------
+// emit_rcl_r64_p64 - rcl operation to a 64-bit
+// pair of registers from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_rcl_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const instruction &inst)
+{
+ int saveflags = ((inst.flags() & FLAG_Z) != 0);
+ emit_link skipall, skiploop;
+ x86code *loop;
+
+ emit_mov_r32_p32_keepflags(dst, REG_ECX, param); // mov ecx,param
+ if (!saveflags)
+ {
+ loop = dst; // loop:
+ emit_jecxz_link(dst, skipall); // jecxz skipall
+ emit_lea_r32_m32(dst, REG_ECX, MBD(REG_ECX, -1)); // lea ecx,[ecx-1]
+ emit_rcl_r32_imm(dst, reglo, 1); // rcl reglo,1
+ emit_rcl_r32_imm(dst, reghi, 1); // rcl reghi,1
+ emit_jmp(dst, loop); // jmp loop
+ track_resolve_link(dst, skipall); // skipall:
+ }
+ else
+ {
+ emit_jecxz_link(dst, skipall); // jecxz skipall
+ emit_lea_r32_m32(dst, REG_ECX, MBD(REG_ECX, -1)); // lea ecx,[ecx-1]
+ loop = dst; // loop:
+ emit_jecxz_link(dst, skiploop); // jecxz skiploop
+ emit_lea_r32_m32(dst, REG_ECX, MBD(REG_ECX, -1)); // lea ecx,[ecx-1]
+ emit_rcl_r32_imm(dst, reglo, 1); // rcl reglo,1
+ emit_rcl_r32_imm(dst, reghi, 1); // rcl reghi,1
+ emit_jmp(dst, loop); // jmp loop
+ track_resolve_link(dst, skiploop); // skiploop:
+ emit_rcl_r32_imm(dst, reglo, 1); // rcl reglo,1
+ emit_pushf(dst); // pushf
+ emit_rcl_r32_imm(dst, reghi, 1); // rcl reghi,1
+ track_resolve_link(dst, skipall); // skipall:
+ emit_combine_z_flags(dst);
+ }
+}
+
+
+//-------------------------------------------------
+// emit_rcr_r64_p64 - rcr operation to a 64-bit
+// pair of registers from a 64-bit parameter
+//-------------------------------------------------
+
+void drcbe_x86::emit_rcr_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const instruction &inst)
+{
+ int saveflags = (inst.flags() != 0);
+ emit_link skipall, skiploop;
+ x86code *loop;
+
+ emit_mov_r32_p32_keepflags(dst, REG_ECX, param); // mov ecx,param
+ if (!saveflags)
+ {
+ loop = dst; // loop:
+ emit_jecxz_link(dst, skipall); // jecxz skipall
+ emit_lea_r32_m32(dst, REG_ECX, MBD(REG_ECX, -1)); // lea ecx,[ecx-1]
+ emit_rcr_r32_imm(dst, reghi, 1); // rcr reghi,1
+ emit_rcr_r32_imm(dst, reglo, 1); // rcr reglo,1
+ emit_jmp(dst, loop); // jmp loop
+ track_resolve_link(dst, skipall); // skipall:
+ }
+ else
+ {
+ emit_jecxz_link(dst, skipall); // jecxz skipall
+ emit_lea_r32_m32(dst, REG_ECX, MBD(REG_ECX, -1)); // lea ecx,[ecx-1]
+ loop = dst; // loop:
+ emit_jecxz_link(dst, skiploop); // jecxz skiploop
+ emit_lea_r32_m32(dst, REG_ECX, MBD(REG_ECX, -1)); // lea ecx,[ecx-1]
+ emit_rcr_r32_imm(dst, reghi, 1); // rcr reghi,1
+ emit_rcr_r32_imm(dst, reglo, 1); // rcr reglo,1
+ emit_jmp(dst, loop); // jmp loop
+ track_resolve_link(dst, skiploop); // skiploop:
+ emit_rcr_r32_imm(dst, reghi, 1); // rcr reghi,1
+ emit_pushf(dst); // pushf
+ emit_rcr_r32_imm(dst, reglo, 1); // rcr reglo,1
+ track_resolve_link(dst, skipall); // skipall:
+ emit_combine_z_shl_flags(dst);
+ }
+}
+
+
+
+//**************************************************************************
+// EMITTERS FOR FLOATING POINT
+//**************************************************************************
+
+//-------------------------------------------------
+// emit_fld_p - load a floating point parameter
+// onto the stack
+//-------------------------------------------------
+
+void drcbe_x86::emit_fld_p(x86code *&dst, int size, const be_parameter &param)
+{
+ assert(param.is_memory());
+ assert(size == 4 || size == 8);
+ if (size == 4)
+ emit_fld_m32(dst, MABS(param.memory()));
+ else if (size == 8)
+ emit_fld_m64(dst, MABS(param.memory()));
+}
+
+
+//-------------------------------------------------
+// emit_fstp_p - store a floating point parameter
+// from the stack and pop it
+//-------------------------------------------------
+
+void drcbe_x86::emit_fstp_p(x86code *&dst, int size, const be_parameter &param)
+{
+ assert(param.is_memory());
+ assert(size == 4 || size == 8);
+ if (size == 4)
+ emit_fstp_m32(dst, MABS(param.memory()));
+ else if (size == 8)
+ emit_fstp_m64(dst, MABS(param.memory()));
+}
+
+
+
+//**************************************************************************
+// OUT-OF-BAND CODE FIXUP CALLBACKS
+//**************************************************************************
+
+//-------------------------------------------------
+// fixup_label - callback to fixup forward-
+// referenced labels
+//-------------------------------------------------
+
+void drcbe_x86::fixup_label(void *parameter, drccodeptr labelcodeptr)
+{
+ drccodeptr src = (drccodeptr)parameter;
+
+ // find the end of the instruction
+ if (src[0] == 0xe3)
+ {
+ src += 1 + 1;
+ src[-1] = labelcodeptr - src;
+ }
+ else if (src[0] == 0xe9)
+ {
+ src += 1 + 4;
+ ((UINT32 *)src)[-1] = labelcodeptr - src;
+ }
+ else if (src[0] == 0x0f && (src[1] & 0xf0) == 0x80)
+ {
+ src += 2 + 4;
+ ((UINT32 *)src)[-1] = labelcodeptr - src;
+ }
+ else
+ fatalerror("fixup_label called with invalid jmp source!");
+}
+
+
+//-------------------------------------------------
+// fixup_exception - callback to perform cleanup
+// and jump to an exception handler
+//-------------------------------------------------
+
+void drcbe_x86::fixup_exception(drccodeptr *codeptr, void *param1, void *param2)
+{
+ drccodeptr src = (drccodeptr)param1;
+ const instruction &inst = *(const instruction *)param2;
+
+ // normalize parameters
+ const parameter &handp = inst.param(0);
+ assert(handp.is_code_handle());
+ be_parameter exp(*this, inst.param(1), PTYPE_MRI);
+
+ // look up the handle target
+ drccodeptr *targetptr = handp.handle().codeptr_addr();
+
+ // first fixup the jump to get us here
+ drccodeptr dst = *codeptr;
+ ((UINT32 *)src)[-1] = dst - src;
+
+ // then store the exception parameter
+ emit_mov_m32_p32(dst, MABS(&m_state.exp), exp); // mov [exp],exp
+
+ // push the original return address on the stack
+ emit_push_imm(dst, (FPTR)src); // push <return>
+ if (*targetptr != NULL)
+ emit_jmp(dst, *targetptr); // jmp *targetptr
+ else
+ emit_jmp_m32(dst, MABS(targetptr)); // jmp [targetptr]
+
+ *codeptr = dst;
+}
+
+
+
+//**************************************************************************
+// DEBUG HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// debug_log_hashjmp - callback to handle
+// logging of hashjmps
+//-------------------------------------------------
+
+void drcbe_x86::debug_log_hashjmp(int mode, offs_t pc)
+{
+ printf("mode=%d PC=%08X\n", mode, pc);
+}
+
+
+
+//**************************************************************************
+// COMPILE-TIME OPCODES
+//**************************************************************************
+
+//-------------------------------------------------
+// op_handle - process a HANDLE opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_handle(x86code *&dst, const instruction &inst)
+{
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+ assert(inst.numparams() == 1);
+ assert(inst.param(0).is_code_handle());
+
+ reset_last_upper_lower_reg();
+
+ // emit a jump around the stack adjust in case code falls through here
+ emit_link skip;
+ emit_jmp_short_link(dst, skip); // jmp skip
+
+ // register the current pointer for the handle
+ inst.param(0).handle().set_codeptr(dst);
+
+ // by default, the handle points to prolog code that moves the stack pointer
+ emit_lea_r32_m32(dst, REG_ESP, MBD(REG_ESP, -28)); // lea rsp,[rsp-28]
+ track_resolve_link(dst, skip); // skip:
+}
+
+
+//-------------------------------------------------
+// op_hash - process a HASH opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_hash(x86code *&dst, const instruction &inst)
+{
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+ assert(inst.numparams() == 2);
+ assert(inst.param(0).is_immediate());
+ assert(inst.param(1).is_immediate());
+
+ // register the current pointer for the mode/PC
+ m_hash.set_codeptr(inst.param(0).immediate(), inst.param(1).immediate(), dst);
+ reset_last_upper_lower_reg();
+}
+
+
+//-------------------------------------------------
+// op_label - process a LABEL opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_label(x86code *&dst, const instruction &inst)
+{
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+ assert(inst.numparams() == 1);
+ assert(inst.param(0).is_code_label());
+
+ // register the current pointer for the label
+ m_labels.set_codeptr(inst.param(0).label(), dst);
+ reset_last_upper_lower_reg();
+}
+
+
+//-------------------------------------------------
+// op_comment - process a COMMENT opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_comment(x86code *&dst, const instruction &inst)
+{
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+ assert(inst.numparams() == 1);
+ assert(inst.param(0).is_string());
+
+ // do nothing
+}
+
+
+//-------------------------------------------------
+// op_mapvar - process a MAPVAR opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_mapvar(x86code *&dst, const instruction &inst)
+{
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+ assert(inst.numparams() == 2);
+ assert(inst.param(0).is_mapvar());
+ assert(inst.param(1).is_immediate());
+
+ // set the value of the specified mapvar
+ m_map.set_value(dst, inst.param(0).mapvar(), inst.param(1).immediate());
+}
+
+
+
+//**************************************************************************
+// CONTROL FLOW OPCODES
+//**************************************************************************
+
+//-------------------------------------------------
+// op_nop - process a NOP opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_nop(x86code *&dst, const instruction &inst)
+{
+ // nothing
+}
+
+
+//-------------------------------------------------
+// op_debug - process a DEBUG opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_debug(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ if ((m_device.machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ {
+ // normalize parameters
+ be_parameter pcp(*this, inst.param(0), PTYPE_MRI);
+
+ // test and branch
+ emit_test_m32_imm(dst, MABS(&m_device.machine().debug_flags), DEBUG_FLAG_CALL_HOOK); // test [debug_flags],DEBUG_FLAG_CALL_HOOK
+ emit_link skip = { 0 };
+ emit_jcc_short_link(dst, x86emit::COND_Z, skip); // jz skip
+
+ // push the parameter
+ emit_mov_m32_p32(dst, MBD(REG_ESP, 4), pcp); // mov [esp+4],pcp
+ emit_mov_m32_imm(dst, MBD(REG_ESP, 0), (FPTR)&m_device); // mov [esp],device
+ emit_call(dst, (x86code *)debugger_instruction_hook); // call debug_cpu_instruction_hook
+
+ track_resolve_link(dst, skip); // skip:
+ }
+}
+
+
+//-------------------------------------------------
+// op_exit - process an EXIT opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_exit(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4);
+ assert_any_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter retp(*this, inst.param(0), PTYPE_MRI);
+
+ // load the parameter into EAX
+ emit_mov_r32_p32(dst, REG_EAX, retp); // mov eax,retp
+ if (inst.condition() == uml::COND_ALWAYS)
+ emit_jmp(dst, m_exit); // jmp exit
+ else
+ emit_jcc(dst, X86_CONDITION(inst.condition()), m_exit); // jcc exit
+}
+
+
+//-------------------------------------------------
+// op_hashjmp - process a HASHJMP opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_hashjmp(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter modep(*this, inst.param(0), PTYPE_MRI);
+ be_parameter pcp(*this, inst.param(1), PTYPE_MRI);
+ const parameter &exp = inst.param(2);
+ assert(exp.is_code_handle());
+
+ if (LOG_HASHJMPS)
+ {
+ emit_mov_m32_p32(dst, MBD(REG_ESP, 4), pcp);
+ emit_mov_m32_p32(dst, MBD(REG_ESP, 0), modep);
+ emit_call(dst, (x86code *)debug_log_hashjmp);
+ }
+
+ // load the stack base one word early so we end up at the right spot after our call below
+ emit_mov_r32_m32(dst, REG_ESP, MABS(&m_hashstacksave)); // mov esp,[hashstacksave]
+
+ // fixed mode cases
+ if (modep.is_immediate() && m_hash.is_mode_populated(modep.immediate()))
+ {
+ // a straight immediate jump is direct, though we need the PC in EAX in case of failure
+ if (pcp.is_immediate())
+ {
+ UINT32 l1val = (pcp.immediate() >> m_hash.l1shift()) & m_hash.l1mask();
+ UINT32 l2val = (pcp.immediate() >> m_hash.l2shift()) & m_hash.l2mask();
+ emit_call_m32(dst, MABS(&m_hash.base()[modep.immediate()][l1val][l2val])); // call hash[modep][l1val][l2val]
+ }
+
+ // a fixed mode but variable PC
+ else
+ {
+ emit_mov_r32_p32(dst, REG_EAX, pcp); // mov eax,pcp
+ emit_mov_r32_r32(dst, REG_EDX, REG_EAX); // mov edx,eax
+ emit_shr_r32_imm(dst, REG_EDX, m_hash.l1shift()); // shr edx,l1shift
+ emit_and_r32_imm(dst, REG_EAX, m_hash.l2mask() << m_hash.l2shift());// and eax,l2mask << l2shift
+ emit_mov_r32_m32(dst, REG_EDX, MABSI(&m_hash.base()[modep.immediate()][0], REG_EDX, 4));
+ // mov edx,hash[modep+edx*4]
+ emit_call_m32(dst, MBISD(REG_EDX, REG_EAX, 4 >> m_hash.l2shift(), 0));// call [edx+eax*shift]
+ }
+ }
+ else
+ {
+ // variable mode
+ int modereg = modep.select_register(REG_ECX);
+ emit_mov_r32_p32(dst, modereg, modep); // mov modereg,modep
+ emit_mov_r32_m32(dst, REG_ECX, MABSI(m_hash.base(), modereg, 4)); // mov ecx,hash[modereg*4]
+
+ // fixed PC
+ if (pcp.is_immediate())
+ {
+ UINT32 l1val = (pcp.immediate() >> m_hash.l1shift()) & m_hash.l1mask();
+ UINT32 l2val = (pcp.immediate() >> m_hash.l2shift()) & m_hash.l2mask();
+ emit_mov_r32_m32(dst, REG_EDX, MBD(REG_ECX, l1val*4)); // mov edx,[ecx+l1val*4]
+ emit_call_m32(dst, MBD(REG_EDX, l2val*4)); // call [l2val*4]
+ }
+
+ // variable PC
+ else
+ {
+ emit_mov_r32_p32(dst, REG_EAX, pcp); // mov eax,pcp
+ emit_mov_r32_r32(dst, REG_EDX, REG_EAX); // mov edx,eax
+ emit_shr_r32_imm(dst, REG_EDX, m_hash.l1shift()); // shr edx,l1shift
+ emit_mov_r32_m32(dst, REG_EDX, MBISD(REG_ECX, REG_EDX, 4, 0)); // mov edx,[ecx+edx*4]
+ emit_and_r32_imm(dst, REG_EAX, m_hash.l2mask() << m_hash.l2shift());// and eax,l2mask << l2shift
+ emit_call_m32(dst, MBISD(REG_EDX, REG_EAX, 4 >> m_hash.l2shift(), 0));// call [edx+eax*shift]
+ }
+ }
+
+ // in all cases, if there is no code, we return here to generate the exception
+ emit_mov_m32_p32(dst, MABS(&m_state.exp), pcp); // mov [exp],param
+ emit_sub_r32_imm(dst, REG_ESP, 4); // sub esp,4
+ emit_call_m32(dst, MABS(exp.handle().codeptr_addr())); // call [exp]
+}
+
+
+//-------------------------------------------------
+// op_jmp - process a JMP opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_jmp(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4);
+ assert_any_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ const parameter &labelp = inst.param(0);
+ assert(labelp.is_code_label());
+
+ // look up the jump target and jump there
+ x86code *jmptarget = (x86code *)m_labels.get_codeptr(labelp.label(), m_fixup_label, dst);
+ if (inst.condition() == uml::COND_ALWAYS)
+ emit_jmp(dst, jmptarget); // jmp target
+ else
+ emit_jcc(dst, X86_CONDITION(inst.condition()), jmptarget); // jcc target
+}
+
+
+//-------------------------------------------------
+// op_exh - process an EXH opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_exh(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4);
+ assert_any_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ const parameter &handp = inst.param(0);
+ assert(handp.is_code_handle());
+ be_parameter exp(*this, inst.param(1), PTYPE_MRI);
+
+ // look up the handle target
+ drccodeptr *targetptr = handp.handle().codeptr_addr();
+
+ // perform the exception processing inline if unconditional
+ if (inst.condition() == uml::COND_ALWAYS)
+ {
+ emit_mov_m32_p32(dst, MABS(&m_state.exp), exp); // mov [exp],exp
+ if (*targetptr != NULL)
+ emit_call(dst, *targetptr); // call *targetptr
+ else
+ emit_call_m32(dst, MABS(targetptr)); // call [targetptr]
+ }
+
+ // otherwise, jump to an out-of-band handler
+ else
+ {
+ emit_jcc(dst, X86_CONDITION(inst.condition()), 0); // jcc exception
+ m_cache.request_oob_codegen(m_fixup_exception, dst, &const_cast<instruction &>(inst));
+ }
+}
+
+
+//-------------------------------------------------
+// op_callh - process a CALLH opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_callh(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4);
+ assert_any_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ const parameter &handp = inst.param(0);
+ assert(handp.is_code_handle());
+
+ // look up the handle target
+ drccodeptr *targetptr = handp.handle().codeptr_addr();
+
+ // skip if conditional
+ emit_link skip = { 0 };
+ if (inst.condition() != uml::COND_ALWAYS)
+ emit_jcc_short_link(dst, X86_NOT_CONDITION(inst.condition()), skip); // jcc skip
+
+ // jump through the handle; directly if a normal jump
+ if (*targetptr != NULL)
+ emit_call(dst, *targetptr); // call *targetptr
+ else
+ emit_call_m32(dst, MABS(targetptr)); // call [targetptr]
+
+ // resolve the conditional link
+ if (inst.condition() != uml::COND_ALWAYS)
+ track_resolve_link(dst, skip); // skip:
+}
+
+
+//-------------------------------------------------
+// op_ret - process a RET opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_ret(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4);
+ assert_any_condition(inst);
+ assert_no_flags(inst);
+ assert(inst.numparams() == 0);
+
+ // skip if conditional
+ emit_link skip = { 0 };
+ if (inst.condition() != uml::COND_ALWAYS)
+ emit_jcc_short_link(dst, X86_NOT_CONDITION(inst.condition()), skip); // jcc skip
+
+ // return
+ emit_lea_r32_m32(dst, REG_ESP, MBD(REG_ESP, 28)); // lea rsp,[rsp+28]
+ emit_ret(dst); // ret
+
+ // resolve the conditional link
+ if (inst.condition() != uml::COND_ALWAYS)
+ track_resolve_link(dst, skip); // skip:
+}
+
+
+//-------------------------------------------------
+// op_callc - process a CALLC opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_callc(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4);
+ assert_any_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ const parameter &funcp = inst.param(0);
+ assert(funcp.is_c_function());
+ be_parameter paramp(*this, inst.param(1), PTYPE_M);
+
+ // skip if conditional
+ emit_link skip = { 0 };
+ if (inst.condition() != uml::COND_ALWAYS)
+ emit_jcc_short_link(dst, X86_NOT_CONDITION(inst.condition()), skip); // jcc skip
+
+ // perform the call
+ emit_mov_m32_imm(dst, MBD(REG_ESP, 0), (FPTR)paramp.memory()); // mov [esp],paramp
+ emit_call(dst, (x86code *)(FPTR)funcp.cfunc()); // call funcp
+
+ // resolve the conditional link
+ if (inst.condition() != uml::COND_ALWAYS)
+ track_resolve_link(dst, skip); // skip:
+}
+
+
+//-------------------------------------------------
+// op_recover - process a RECOVER opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_recover(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+
+ // call the recovery code
+ emit_mov_r32_m32(dst, REG_EAX, MABS(&m_stacksave)); // mov eax,stacksave
+ emit_mov_r32_m32(dst, REG_EAX, MBD(REG_EAX, -4)); // mov eax,[eax-4]
+ emit_sub_r32_imm(dst, REG_EAX, 1); // sub eax,1
+ emit_mov_m32_imm(dst, MBD(REG_ESP, 8), inst.param(1).mapvar()); // mov [esp+8],param1
+ emit_mov_m32_r32(dst, MBD(REG_ESP, 4), REG_EAX); // mov [esp+4],eax
+ emit_mov_m32_imm(dst, MBD(REG_ESP, 0), (FPTR)&m_map); // mov [esp],m_map
+ emit_call(dst, (x86code *)&drc_map_variables::static_get_value); // call drcmap_get_value
+ emit_mov_p32_r32(dst, dstp, REG_EAX); // mov dstp,eax
+}
+
+
+
+//**************************************************************************
+// INTERNAL REGISTER OPCODES
+//**************************************************************************
+
+//-------------------------------------------------
+// op_setfmod - process a SETFMOD opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_setfmod(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter srcp(*this, inst.param(0), PTYPE_MRI);
+
+ // immediate case
+ if (srcp.is_immediate())
+ {
+ int value = srcp.immediate() & 3;
+ emit_mov_m8_imm(dst, MABS(&m_state.fmod), value); // mov [fmod],srcp
+ emit_fldcw_m16(dst, MABS(&fp_control[value])); // fldcw fp_control[srcp]
+ }
+
+ // register/memory case
+ else
+ {
+ emit_mov_r32_p32(dst, REG_EAX, srcp); // mov eax,srcp
+ emit_and_r32_imm(dst, REG_EAX, 3); // and eax,3
+ emit_mov_m8_r8(dst, MABS(&m_state.fmod), REG_AL); // mov [fmod],al
+ emit_fldcw_m16(dst, MABSI(&fp_control[0], REG_EAX, 2)); // fldcw fp_control[eax]
+ }
+}
+
+
+//-------------------------------------------------
+// op_getfmod - process a GETFMOD opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_getfmod(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+
+ // fetch the current mode and store to the destination
+ if (dstp.is_int_register())
+ emit_movzx_r32_m8(dst, dstp.ireg(), MABS(&m_state.fmod)); // movzx reg,[fmod]
+ else
+ {
+ emit_movzx_r32_m8(dst, REG_EAX, MABS(&m_state.fmod)); // movzx eax,[fmod]
+ emit_mov_m32_r32(dst, MABS(dstp.memory()), REG_EAX); // mov [dstp],eax
+ }
+}
+
+
+//-------------------------------------------------
+// op_getexp - process a GETEXP opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_getexp(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+
+ // fetch the exception parameter and store to the destination
+ if (dstp.is_int_register())
+ emit_mov_r32_m32(dst, dstp.ireg(), MABS(&m_state.exp)); // mov reg,[exp]
+ else
+ {
+ emit_mov_r32_m32(dst, REG_EAX, MABS(&m_state.exp)); // mov eax,[exp]
+ emit_mov_m32_r32(dst, MABS(dstp.memory()), REG_EAX); // mov [dstp],eax
+ }
+}
+
+
+//-------------------------------------------------
+// op_getflgs - process a GETFLGS opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_getflgs(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter maskp(*this, inst.param(1), PTYPE_I);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX);
+
+ // compute mask for flags
+ UINT32 flagmask = 0;
+ if (maskp.immediate() & FLAG_C) flagmask |= 0x001;
+ if (maskp.immediate() & FLAG_V) flagmask |= 0x800;
+ if (maskp.immediate() & FLAG_Z) flagmask |= 0x040;
+ if (maskp.immediate() & FLAG_S) flagmask |= 0x080;
+ if (maskp.immediate() & FLAG_U) flagmask |= 0x004;
+
+ switch (maskp.immediate())
+ {
+ // single flags only
+ case FLAG_C:
+ emit_setcc_r8(dst, x86emit::COND_C, REG_AL); // setc al
+ emit_movzx_r32_r8(dst, dstreg, REG_AL); // movzx dstreg,al
+ break;
+
+ case FLAG_V:
+ emit_setcc_r8(dst, x86emit::COND_O, REG_AL); // seto al
+ emit_movzx_r32_r8(dst, dstreg, REG_AL); // movzx dstreg,al
+ emit_shl_r32_imm(dst, dstreg, 1); // shl dstreg,1
+ break;
+
+ case FLAG_Z:
+ emit_setcc_r8(dst, x86emit::COND_Z, REG_AL); // setz al
+ emit_movzx_r32_r8(dst, dstreg, REG_AL); // movzx dstreg,al
+ emit_shl_r32_imm(dst, dstreg, 2); // shl dstreg,2
+ break;
+
+ case FLAG_S:
+ emit_setcc_r8(dst, x86emit::COND_S, REG_AL); // sets al
+ emit_movzx_r32_r8(dst, dstreg, REG_AL); // movzx dstreg,al
+ emit_shl_r32_imm(dst, dstreg, 3); // shl dstreg,3
+ break;
+
+ case FLAG_U:
+ emit_setcc_r8(dst, x86emit::COND_P, REG_AL); // setp al
+ emit_movzx_r32_r8(dst, dstreg, REG_AL); // movzx dstreg,al
+ emit_shl_r32_imm(dst, dstreg, 4); // shl dstreg,4
+ break;
+
+ // carry plus another flag
+ case FLAG_C | FLAG_V:
+ emit_setcc_r8(dst, x86emit::COND_C, REG_AL); // setc al
+ emit_setcc_r8(dst, x86emit::COND_O, REG_CL); // seto cl
+ emit_movzx_r32_r8(dst, REG_EAX, REG_AL); // movzx eax,al
+ emit_movzx_r32_r8(dst, REG_ECX, REG_CL); // movzx ecx,al
+ emit_lea_r32_m32(dst, dstreg, MBISD(REG_EAX, REG_ECX, 2, 0)); // lea dstreg,[eax+ecx*2]
+ break;
+
+ case FLAG_C | FLAG_Z:
+ emit_setcc_r8(dst, x86emit::COND_C, REG_AL); // setc al
+ emit_setcc_r8(dst, x86emit::COND_Z, REG_CL); // setz cl
+ emit_movzx_r32_r8(dst, REG_EAX, REG_AL); // movzx eax,al
+ emit_movzx_r32_r8(dst, REG_ECX, REG_CL); // movzx ecx,al
+ emit_lea_r32_m32(dst, dstreg, MBISD(REG_EAX, REG_ECX, 4, 0)); // lea dstreg,[eax+ecx*4]
+ break;
+
+ case FLAG_C | FLAG_S:
+ emit_setcc_r8(dst, x86emit::COND_C, REG_AL); // setc al
+ emit_setcc_r8(dst, x86emit::COND_S, REG_CL); // sets cl
+ emit_movzx_r32_r8(dst, REG_EAX, REG_AL); // movzx eax,al
+ emit_movzx_r32_r8(dst, REG_ECX, REG_CL); // movzx ecx,al
+ emit_lea_r32_m32(dst, dstreg, MBISD(REG_EAX, REG_ECX, 8, 0)); // lea dstreg,[eax+ecx*8]
+ break;
+
+ // overflow plus another flag
+ case FLAG_V | FLAG_Z:
+ emit_setcc_r8(dst, x86emit::COND_O, REG_AL); // seto al
+ emit_setcc_r8(dst, x86emit::COND_Z, REG_CL); // setz cl
+ emit_movzx_r32_r8(dst, REG_EAX, REG_AL); // movzx eax,al
+ emit_movzx_r32_r8(dst, REG_ECX, REG_CL); // movzx ecx,al
+ emit_lea_r32_m32(dst, dstreg, MBISD(REG_EAX, REG_ECX, 2, 0)); // lea dstreg,[eax+ecx*2]
+ emit_shl_r32_imm(dst, dstreg, 1); // shl dstreg,1
+ break;
+
+ case FLAG_V | FLAG_S:
+ emit_setcc_r8(dst, x86emit::COND_O, REG_AL); // seto al
+ emit_setcc_r8(dst, x86emit::COND_S, REG_CL); // sets cl
+ emit_movzx_r32_r8(dst, REG_EAX, REG_AL); // movzx eax,al
+ emit_movzx_r32_r8(dst, REG_ECX, REG_CL); // movzx ecx,al
+ emit_lea_r32_m32(dst, dstreg, MBISD(REG_EAX, REG_ECX, 4, 0)); // lea dstreg,[eax+ecx*4]
+ emit_shl_r32_imm(dst, dstreg, 1); // shl dstreg,1
+ break;
+
+ // zero plus another flag
+ case FLAG_Z | FLAG_S:
+ emit_setcc_r8(dst, x86emit::COND_Z, REG_AL); // setz al
+ emit_setcc_r8(dst, x86emit::COND_S, REG_CL); // sets cl
+ emit_movzx_r32_r8(dst, REG_EAX, REG_AL); // movzx eax,al
+ emit_movzx_r32_r8(dst, REG_ECX, REG_CL); // movzx ecx,al
+ emit_lea_r32_m32(dst, dstreg, MBISD(REG_EAX, REG_ECX, 2, 0)); // lea dstreg,[eax+ecx*2]
+ emit_shl_r32_imm(dst, dstreg, 2); // shl dstreg,2
+ break;
+
+ // default cases
+ default:
+ emit_pushf(dst); // pushf
+ emit_pop_r32(dst, REG_EAX); // pop eax
+ emit_and_r32_imm(dst, REG_EAX, flagmask); // and eax,flagmask
+ emit_movzx_r32_m8(dst, dstreg, MABSI(flags_map, REG_EAX)); // movzx dstreg,[flags_map]
+ break;
+ }
+
+ // store low 32 bits
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+
+ // 64-bit form stores upper 32 bits
+ if (inst.size() == 8)
+ {
+ // general case
+ if (dstp.is_memory())
+ emit_mov_m32_imm(dst, MABS(dstp.memory(4)), 0); // mov [dstp+4],0
+ else if (dstp.is_int_register())
+ emit_mov_m32_imm(dst, MABS(m_reghi[dstp.ireg()]), 0); // mov [reghi],0
+ }
+}
+
+
+//-------------------------------------------------
+// op_save - process a SAVE opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_save(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_M);
+
+ // copy live state to the destination
+ emit_mov_r32_imm(dst, REG_ECX, (FPTR)dstp.memory()); // mov ecx,dstp
+ emit_call(dst, m_save); // call save
+}
+
+
+//-------------------------------------------------
+// op_restore - process a RESTORE opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_restore(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4);
+ assert_no_condition(inst);
+
+ // normalize parameters
+ be_parameter srcp(*this, inst.param(0), PTYPE_M);
+
+ // copy live state from the destination
+ emit_mov_r32_imm(dst, REG_ECX, (FPTR)srcp.memory()); // mov ecx,dstp
+ emit_call(dst, m_restore); // call restore
+}
+
+
+
+//**************************************************************************
+// INTEGER OPERATIONS
+//**************************************************************************
+
+//-------------------------------------------------
+// op_load - process a LOAD opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_load(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter basep(*this, inst.param(1), PTYPE_M);
+ be_parameter indp(*this, inst.param(2), PTYPE_MRI);
+ const parameter &scalesizep = inst.param(3);
+ assert(scalesizep.is_size_scale());
+ int scale = 1 << scalesizep.scale();
+ int size = scalesizep.size();
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX);
+
+ // immediate index
+ if (indp.is_immediate())
+ {
+ if (size == SIZE_BYTE)
+ emit_movzx_r32_m8(dst, dstreg, MABS(basep.memory(scale*indp.immediate()))); // movzx dstreg,[basep + scale*indp]
+ else if (size == SIZE_WORD)
+ emit_movzx_r32_m16(dst, dstreg, MABS(basep.memory(scale*indp.immediate()))); // movzx dstreg,[basep + scale*indp]
+ else if (size == SIZE_DWORD)
+ emit_mov_r32_m32(dst, dstreg, MABS(basep.memory(scale*indp.immediate()))); // mov dstreg,[basep + scale*indp]
+ else if (size == SIZE_QWORD)
+ {
+ emit_mov_r32_m32(dst, REG_EDX, MABS(basep.memory(scale*indp.immediate() + 4))); // mov edx,[basep + scale*indp + 4]
+ emit_mov_r32_m32(dst, dstreg, MABS(basep.memory(scale*indp.immediate()))); // mov dstreg,[basep + scale*indp]
+ }
+ }
+
+ // other index
+ else
+ {
+ int indreg = indp.select_register(REG_ECX);
+ emit_mov_r32_p32(dst, indreg, indp);
+ if (size == SIZE_BYTE)
+ emit_movzx_r32_m8(dst, dstreg, MABSI(basep.memory(), indreg, scale)); // movzx dstreg,[basep + scale*indp]
+ else if (size == SIZE_WORD)
+ emit_movzx_r32_m16(dst, dstreg, MABSI(basep.memory(), indreg, scale)); // movzx dstreg,[basep + scale*indp]
+ else if (size == SIZE_DWORD)
+ emit_mov_r32_m32(dst, dstreg, MABSI(basep.memory(), indreg, scale)); // mov dstreg,[basep + scale*indp]
+ else if (size == SIZE_QWORD)
+ {
+ emit_mov_r32_m32(dst, REG_EDX, MABSI(basep.memory(4), indreg, scale)); // mov edx,[basep + scale*indp + 4]
+ emit_mov_r32_m32(dst, dstreg, MABSI(basep.memory(), indreg, scale)); // mov dstreg,[basep + scale*indp]
+ }
+ }
+
+ // store low 32 bits
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+
+ // 64-bit form stores upper 32 bits
+ if (inst.size() == 8)
+ {
+ // 1, 2, or 4-byte case
+ if (size != SIZE_QWORD)
+ {
+ if (dstp.is_memory())
+ emit_mov_m32_imm(dst, MABS(dstp.memory(4)), 0); // mov [dstp+4],0
+ else if (dstp.is_int_register())
+ emit_mov_m32_imm(dst, MABS(m_reghi[dstp.ireg()]), 0); // mov [reghi],0
+ }
+
+ // 8-byte case
+ else
+ {
+ if (dstp.is_memory())
+ emit_mov_m32_r32(dst, MABS(dstp.memory(4)), REG_EDX); // mov [dstp+4],edx
+ else if (dstp.is_int_register())
+ emit_mov_m32_r32(dst, MABS(m_reghi[dstp.ireg()]), REG_EDX); // mov [reghi],edx
+ set_last_upper_reg(dst, dstp, REG_EDX);
+ }
+ }
+ set_last_lower_reg(dst, dstp, dstreg);
+}
+
+
+//-------------------------------------------------
+// op_loads - process a LOADS opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_loads(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter basep(*this, inst.param(1), PTYPE_M);
+ be_parameter indp(*this, inst.param(2), PTYPE_MRI);
+ const parameter &scalesizep = inst.param(3);
+ assert(scalesizep.is_size_scale());
+ int scale = 1 << scalesizep.scale();
+ int size = scalesizep.size();
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX);
+
+ // immediate index
+ if (indp.is_immediate())
+ {
+ if (size == SIZE_BYTE)
+ emit_movsx_r32_m8(dst, dstreg, MABS(basep.memory(scale*indp.immediate()))); // movsx dstreg,[basep + scale*indp]
+ else if (size == SIZE_WORD)
+ emit_movsx_r32_m16(dst, dstreg, MABS(basep.memory(scale*indp.immediate()))); // movsx dstreg,[basep + scale*indp]
+ else if (size == SIZE_DWORD)
+ emit_mov_r32_m32(dst, dstreg, MABS(basep.memory(scale*indp.immediate()))); // mov dstreg,[basep + scale*indp]
+ else if (size == SIZE_QWORD)
+ {
+ emit_mov_r32_m32(dst, REG_EDX, MABS(basep.memory(scale*indp.immediate() + 4))); // mov edx,[basep + scale*indp + 4]
+ emit_mov_r32_m32(dst, dstreg, MABS(basep.memory(scale*indp.immediate()))); // mov dstreg,[basep + scale*indp]
+ }
+ }
+
+ // other index
+ else
+ {
+ int indreg = indp.select_register(REG_ECX);
+ emit_mov_r32_p32(dst, indreg, indp);
+ if (size == SIZE_BYTE)
+ emit_movsx_r32_m8(dst, dstreg, MABSI(basep.memory(), indreg, scale)); // movsx dstreg,[basep + scale*indp]
+ else if (size == SIZE_WORD)
+ emit_movsx_r32_m16(dst, dstreg, MABSI(basep.memory(), indreg, scale)); // movsx dstreg,[basep + scale*indp]
+ else if (size == SIZE_DWORD)
+ emit_mov_r32_m32(dst, dstreg, MABSI(basep.memory(), indreg, scale)); // mov dstreg,[basep + scale*indp]
+ else if (size == SIZE_QWORD)
+ {
+ emit_mov_r32_m32(dst, REG_EDX, MABSI(basep.memory(4), indreg, scale)); // mov edx,[basep + scale*indp + 4]
+ emit_mov_r32_m32(dst, dstreg, MABSI(basep.memory(), indreg, scale)); // mov dstreg,[basep + scale*indp]
+ }
+ }
+
+ // store low 32 bits
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+
+ // 64-bit form stores upper 32 bits
+ if (inst.size() == 8)
+ {
+ emit_cdq(dst); // cdq
+ if (dstp.is_memory())
+ emit_mov_m32_r32(dst, MABS(dstp.memory(4)), REG_EDX); // mov [dstp+4],edx
+ else if (dstp.is_int_register())
+ emit_mov_m32_r32(dst, MABS(m_reghi[dstp.ireg()]), REG_EDX); // mov [reghi],edx
+ set_last_upper_reg(dst, dstp, REG_EDX);
+ }
+ set_last_lower_reg(dst, dstp, dstreg);
+}
+
+
+//-------------------------------------------------
+// op_store - process a STORE opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_store(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter basep(*this, inst.param(0), PTYPE_M);
+ be_parameter indp(*this, inst.param(1), PTYPE_MRI);
+ be_parameter srcp(*this, inst.param(2), PTYPE_MRI);
+ const parameter &scalesizep = inst.param(3);
+ int scale = 1 << (scalesizep.scale());
+ int size = scalesizep.size();
+
+ // pick a source register for the general case
+ int srcreg = srcp.select_register(REG_EAX);
+ if (size == SIZE_BYTE && (srcreg & 4))
+ srcreg = REG_EAX;
+
+ // degenerate case: constant index
+ if (indp.is_immediate())
+ {
+ // immediate source
+ if (srcp.is_immediate())
+ {
+ if (size == SIZE_BYTE)
+ emit_mov_m8_imm(dst, MABS(basep.memory(scale*indp.immediate())), srcp.immediate()); // mov [basep + scale*indp],srcp
+ else if (size == SIZE_WORD)
+ emit_mov_m16_imm(dst, MABS(basep.memory(scale*indp.immediate())), srcp.immediate()); // mov [basep + scale*indp],srcp
+ else if (size == SIZE_DWORD)
+ emit_mov_m32_imm(dst, MABS(basep.memory(scale*indp.immediate())), srcp.immediate()); // mov [basep + scale*indp],srcp
+ else if (size == SIZE_QWORD)
+ {
+ emit_mov_m32_imm(dst, MABS(basep.memory(scale*indp.immediate())), srcp.immediate()); // mov [basep + scale*indp],srcp
+ emit_mov_m32_imm(dst, MABS(basep.memory(scale*indp.immediate() + 4)), srcp.immediate() >> 32);
+ // mov [basep + scale*indp + 4],srcp >> 32
+ }
+ }
+
+ // variable source
+ else
+ {
+ if (size != SIZE_QWORD)
+ emit_mov_r32_p32(dst, srcreg, srcp); // mov srcreg,srcp
+ else
+ emit_mov_r64_p64(dst, srcreg, REG_EDX, srcp); // mov edx:srcreg,srcp
+ if (size == SIZE_BYTE)
+ emit_mov_m8_r8(dst, MABS(basep.memory(scale*indp.immediate())), srcreg); // mov [basep + scale*indp],srcreg
+ else if (size == SIZE_WORD)
+ emit_mov_m16_r16(dst, MABS(basep.memory(scale*indp.immediate())), srcreg); // mov [basep + scale*indp],srcreg
+ else if (size == SIZE_DWORD)
+ emit_mov_m32_r32(dst, MABS(basep.memory(scale*indp.immediate())), srcreg); // mov [basep + scale*indp],srcreg
+ else if (size == SIZE_QWORD)
+ {
+ emit_mov_m32_r32(dst, MABS(basep.memory(scale*indp.immediate())), srcreg); // mov [basep + scale*indp],srcreg
+ emit_mov_m32_r32(dst, MABS(basep.memory(scale*indp.immediate() + 4)), REG_EDX); // mov [basep + scale*indp + 4],edx
+ }
+ }
+ }
+
+ // normal case: variable index
+ else
+ {
+ int indreg = indp.select_register(REG_ECX);
+ emit_mov_r32_p32(dst, indreg, indp); // mov indreg,indp
+
+ // immediate source
+ if (srcp.is_immediate())
+ {
+ if (size == SIZE_BYTE)
+ emit_mov_m8_imm(dst, MABSI(basep.memory(), indreg, scale), srcp.immediate()); // mov [basep + 1*ecx],srcp
+ else if (size == SIZE_WORD)
+ emit_mov_m16_imm(dst, MABSI(basep.memory(), indreg, scale), srcp.immediate()); // mov [basep + 2*ecx],srcp
+ else if (size == SIZE_DWORD)
+ emit_mov_m32_imm(dst, MABSI(basep.memory(), indreg, scale), srcp.immediate()); // mov [basep + 4*ecx],srcp
+ else if (size == SIZE_QWORD)
+ {
+ emit_mov_m32_imm(dst, MABSI(basep.memory(), indreg, scale), srcp.immediate()); // mov [basep + 8*ecx],srcp
+ emit_mov_m32_imm(dst, MABSI(basep.memory(4), indreg, scale), srcp.immediate() >> 32);
+ // mov [basep + 8*ecx + 4],srcp >> 32
+ }
+ }
+
+ // variable source
+ else
+ {
+ if (size != SIZE_QWORD)
+ emit_mov_r32_p32(dst, srcreg, srcp); // mov srcreg,srcp
+ else
+ emit_mov_r64_p64(dst, srcreg, REG_EDX, srcp); // mov edx:srcreg,srcp
+ if (size == SIZE_BYTE)
+ emit_mov_m8_r8(dst, MABSI(basep.memory(), indreg, scale), srcreg); // mov [basep + 1*ecx],srcreg
+ else if (size == SIZE_WORD)
+ emit_mov_m16_r16(dst, MABSI(basep.memory(), indreg, scale), srcreg); // mov [basep + 2*ecx],srcreg
+ else if (size == SIZE_DWORD)
+ emit_mov_m32_r32(dst, MABSI(basep.memory(), indreg, scale), srcreg); // mov [basep + 4*ecx],srcreg
+ else if (size == SIZE_QWORD)
+ {
+ emit_mov_m32_r32(dst, MABSI(basep.memory(), indreg, scale), srcreg); // mov [basep + 8*ecx],srcreg
+ emit_mov_m32_r32(dst, MABSI(basep.memory(4), indreg, scale), REG_EDX); // mov [basep + 8*ecx],edx
+ }
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// op_read - process a READ opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_read(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter addrp(*this, inst.param(1), PTYPE_MRI);
+ const parameter &spacesizep = inst.param(2);
+ assert(spacesizep.is_size_space());
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX);
+
+ // set up a call to the read byte handler
+ emit_mov_m32_p32(dst, MBD(REG_ESP, 4), addrp); // mov [esp+4],addrp
+ emit_mov_m32_imm(dst, MBD(REG_ESP, 0), (FPTR)m_space[spacesizep.space()]); // mov [esp],space
+ if (spacesizep.size() == SIZE_BYTE)
+ {
+ emit_call(dst, (x86code *)m_accessors[spacesizep.space()].read_byte);
+ // call read_byte
+ emit_movzx_r32_r8(dst, dstreg, REG_AL); // movzx dstreg,al
+ }
+ else if (spacesizep.size() == SIZE_WORD)
+ {
+ emit_call(dst, (x86code *)m_accessors[spacesizep.space()].read_word);
+ // call read_word
+ emit_movzx_r32_r16(dst, dstreg, REG_AX); // movzx dstreg,ax
+ }
+ else if (spacesizep.size() == SIZE_DWORD)
+ {
+ emit_call(dst, (x86code *)m_accessors[spacesizep.space()].read_dword);
+ // call read_dword
+ emit_mov_r32_r32(dst, dstreg, REG_EAX); // mov dstreg,eax
+ }
+ else if (spacesizep.size() == SIZE_QWORD)
+ {
+ emit_call(dst, (x86code *)m_accessors[spacesizep.space()].read_qword);
+ // call read_qword
+ emit_mov_r32_r32(dst, dstreg, REG_EAX); // mov dstreg,eax
+ }
+
+ // store low 32 bits
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+
+ // 64-bit form stores upper 32 bits
+ if (inst.size() == 8)
+ {
+ // 1, 2, or 4-byte case
+ if (spacesizep.size() != SIZE_QWORD)
+ {
+ if (dstp.is_memory())
+ emit_mov_m32_imm(dst, MABS(dstp.memory(4)), 0); // mov [dstp+4],0
+ else if (dstp.is_int_register())
+ emit_mov_m32_imm(dst, MABS(m_reghi[dstp.ireg()]), 0); // mov [reghi],0
+ }
+
+ // 8-byte case
+ else
+ {
+ if (dstp.is_memory())
+ emit_mov_m32_r32(dst, MABS(dstp.memory(4)), REG_EDX); // mov [dstp+4],edx
+ else if (dstp.is_int_register())
+ emit_mov_m32_r32(dst, MABS(m_reghi[dstp.ireg()]), REG_EDX); // mov [reghi],edx
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// op_readm - process a READM opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_readm(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter addrp(*this, inst.param(1), PTYPE_MRI);
+ be_parameter maskp(*this, inst.param(2), PTYPE_MRI);
+ const parameter &spacesizep = inst.param(3);
+ assert(spacesizep.is_size_space());
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX);
+
+ // set up a call to the read byte handler
+ if (spacesizep.size() != SIZE_QWORD)
+ emit_mov_m32_p32(dst, MBD(REG_ESP, 8), maskp); // mov [esp+8],maskp
+ else
+ emit_mov_m64_p64(dst, MBD(REG_ESP, 8), maskp); // mov [esp+8],maskp
+ emit_mov_m32_p32(dst, MBD(REG_ESP, 4), addrp); // mov [esp+4],addrp
+ emit_mov_m32_imm(dst, MBD(REG_ESP, 0), (FPTR)m_space[spacesizep.space()]); // mov [esp],space
+ if (spacesizep.size() == SIZE_WORD)
+ {
+ emit_call(dst, (x86code *)m_accessors[spacesizep.space()].read_word_masked);
+ // call read_word_masked
+ emit_movzx_r32_r16(dst, dstreg, REG_AX); // movzx dstreg,ax
+ }
+ else if (spacesizep.size() == SIZE_DWORD)
+ {
+ emit_call(dst, (x86code *)m_accessors[spacesizep.space()].read_dword_masked);
+ // call read_dword_masked
+ emit_mov_r32_r32(dst, dstreg, REG_EAX); // mov dstreg,eax
+ }
+ else if (spacesizep.size() == SIZE_QWORD)
+ {
+ emit_call(dst, (x86code *)m_accessors[spacesizep.space()].read_qword_masked);
+ // call read_qword_masked
+ emit_mov_r32_r32(dst, dstreg, REG_EAX); // mov dstreg,eax
+ }
+
+ // store low 32 bits
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+
+ // 64-bit form stores upper 32 bits
+ if (inst.size() == 8)
+ {
+ // 1, 2, or 4-byte case
+ if (spacesizep.size() != SIZE_QWORD)
+ {
+ if (dstp.is_memory())
+ emit_mov_m32_imm(dst, MABS(dstp.memory(4)), 0); // mov [dstp+4],0
+ else if (dstp.is_int_register())
+ emit_mov_m32_imm(dst, MABS(m_reghi[dstp.ireg()]), 0); // mov [reghi],0
+ }
+
+ // 8-byte case
+ else
+ {
+ if (dstp.is_memory())
+ emit_mov_m32_r32(dst, MABS(dstp.memory(4)), REG_EDX); // mov [dstp+4],edx
+ else if (dstp.is_int_register())
+ emit_mov_m32_r32(dst, MABS(m_reghi[dstp.ireg()]), REG_EDX); // mov [reghi],edx
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// op_write - process a WRITE opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_write(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter addrp(*this, inst.param(0), PTYPE_MRI);
+ be_parameter srcp(*this, inst.param(1), PTYPE_MRI);
+ const parameter &spacesizep = inst.param(2);
+ assert(spacesizep.is_size_space());
+
+ // set up a call to the write byte handler
+ if (spacesizep.size() != SIZE_QWORD)
+ emit_mov_m32_p32(dst, MBD(REG_ESP, 8), srcp); // mov [esp+8],srcp
+ else
+ emit_mov_m64_p64(dst, MBD(REG_ESP, 8), srcp); // mov [esp+8],srcp
+ emit_mov_m32_p32(dst, MBD(REG_ESP, 4), addrp); // mov [esp+4],addrp
+ emit_mov_m32_imm(dst, MBD(REG_ESP, 0), (FPTR)m_space[spacesizep.space()]); // mov [esp],space
+ if (spacesizep.size() == SIZE_BYTE)
+ emit_call(dst, (x86code *)m_accessors[spacesizep.space()].write_byte);
+ // call write_byte
+ else if (spacesizep.size() == SIZE_WORD)
+ emit_call(dst, (x86code *)m_accessors[spacesizep.space()].write_word);
+ // call write_word
+ else if (spacesizep.size() == SIZE_DWORD)
+ emit_call(dst, (x86code *)m_accessors[spacesizep.space()].write_dword);
+ // call write_dword
+ else if (spacesizep.size() == SIZE_QWORD)
+ emit_call(dst, (x86code *)m_accessors[spacesizep.space()].write_qword);
+ // call write_qword
+}
+
+
+//-------------------------------------------------
+// op_writem - process a WRITEM opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_writem(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter addrp(*this, inst.param(0), PTYPE_MRI);
+ be_parameter srcp(*this, inst.param(1), PTYPE_MRI);
+ be_parameter maskp(*this, inst.param(2), PTYPE_MRI);
+ const parameter &spacesizep = inst.param(3);
+ assert(spacesizep.is_size_space());
+
+ // set up a call to the write byte handler
+ if (spacesizep.size() != SIZE_QWORD)
+ {
+ emit_mov_m32_p32(dst, MBD(REG_ESP, 12), maskp); // mov [esp+12],maskp
+ emit_mov_m32_p32(dst, MBD(REG_ESP, 8), srcp); // mov [esp+8],srcp
+ }
+ else
+ {
+ emit_mov_m64_p64(dst, MBD(REG_ESP, 16), maskp); // mov [esp+16],maskp
+ emit_mov_m64_p64(dst, MBD(REG_ESP, 8), srcp); // mov [esp+8],srcp
+ }
+ emit_mov_m32_p32(dst, MBD(REG_ESP, 4), addrp); // mov [esp+4],addrp
+ emit_mov_m32_imm(dst, MBD(REG_ESP, 0), (FPTR)m_space[spacesizep.space()]); // mov [esp],space
+ if (spacesizep.size() == SIZE_WORD)
+ emit_call(dst, (x86code *)m_accessors[spacesizep.space()].write_word_masked);
+ // call write_word_masked
+ else if (spacesizep.size() == SIZE_DWORD)
+ emit_call(dst, (x86code *)m_accessors[spacesizep.space()].write_dword_masked);
+ // call write_dword_masked
+ else if (spacesizep.size() == SIZE_QWORD)
+ emit_call(dst, (x86code *)m_accessors[spacesizep.space()].write_qword_masked);
+ // call write_qword_masked
+}
+
+
+//-------------------------------------------------
+// op_carry - process a CARRY opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_carry(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_C);
+
+ // normalize parameters
+ be_parameter srcp(*this, inst.param(0), PTYPE_MRI);
+ be_parameter bitp(*this, inst.param(1), PTYPE_MRI);
+
+ // degenerate case: source is immediate
+ if (srcp.is_immediate() && bitp.is_immediate())
+ {
+ if (srcp.immediate() & ((UINT64)1 << bitp.immediate()))
+ emit_stc(dst);
+ else
+ emit_clc(dst);
+ }
+
+ // load non-immediate bit numbers into a register
+ if (!bitp.is_immediate())
+ {
+ emit_mov_r32_p32(dst, REG_ECX, bitp);
+ emit_and_r32_imm(dst, REG_ECX, inst.size() * 8 - 1);
+ }
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ if (bitp.is_immediate())
+ {
+ if (srcp.is_memory())
+ emit_bt_m32_imm(dst, MABS(srcp.memory()), bitp.immediate()); // bt [srcp],bitp
+ else if (srcp.is_int_register())
+ emit_bt_r32_imm(dst, srcp.ireg(), bitp.immediate()); // bt srcp,bitp
+ }
+ else
+ {
+ if (srcp.is_memory())
+ emit_bt_m32_r32(dst, MABS(srcp.memory()), REG_ECX); // bt [srcp],ecx
+ else if (srcp.is_int_register())
+ emit_bt_r32_r32(dst, srcp.ireg(), REG_ECX); // bt [srcp],ecx
+ }
+ }
+
+ // 64-bit form
+ else
+ {
+ if (bitp.is_immediate())
+ {
+ if (srcp.is_memory())
+ emit_bt_m32_imm(dst, MABS(srcp.memory()), bitp.immediate()); // bt [srcp],bitp
+ else if (srcp.is_int_register() && bitp.immediate() < 32)
+ emit_bt_r32_imm(dst, srcp.ireg(), bitp.immediate()); // bt srcp,bitp
+ else if (srcp.is_int_register() && bitp.immediate() >= 32)
+ emit_bt_m32_imm(dst, MABS(m_reghi[srcp.ireg()]), bitp.immediate() - 32); // bt [srcp.hi],bitp
+ }
+ else
+ {
+ if (srcp.is_memory())
+ emit_bt_m32_r32(dst, MABS(srcp.memory()), REG_ECX); // bt [srcp],ecx
+ else if (srcp.is_int_register())
+ {
+ emit_mov_m32_r32(dst, MABS(m_reglo[srcp.ireg()]), srcp.ireg()); // mov [srcp.lo],srcp
+ emit_bt_m32_r32(dst, MABS(m_reglo[srcp.ireg()]), REG_ECX); // bt [srcp],ecx
+ }
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// op_set - process a SET opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_set(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_any_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX);
+
+ // set to AL
+ emit_setcc_r8(dst, X86_CONDITION(inst.condition()), REG_AL); // setcc al
+ emit_movzx_r32_r8(dst, dstreg, REG_AL); // movzx dstreg,al
+
+ // store low 32 bits
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+
+ // 64-bit form stores upper 32 bits
+ if (inst.size() == 8)
+ {
+ // general case
+ if (dstp.is_memory())
+ emit_mov_m32_imm(dst, MABS(dstp.memory(4)), 0); // mov [dstp+4],0
+ else if (dstp.is_int_register())
+ emit_mov_m32_imm(dst, MABS(m_reghi[dstp.ireg()]), 0); // mov [reghi],0
+ }
+}
+
+
+//-------------------------------------------------
+// op_mov - process a MOV opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_mov(x86code *&dst, const instruction &inst)
+{
+ x86code *savedst = dst;
+
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_any_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter srcp(*this, inst.param(1), PTYPE_MRI);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX);
+
+ // always start with a jmp
+ emit_link skip = { 0 };
+ if (inst.condition() != uml::COND_ALWAYS)
+ emit_jcc_short_link(dst, X86_NOT_CONDITION(inst.condition()), skip); // jcc skip
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // register to memory
+ if (dstp.is_memory() && srcp.is_int_register())
+ emit_mov_m32_r32(dst, MABS(dstp.memory()), srcp.ireg()); // mov [dstp],srcp
+
+ // immediate to memory
+ else if (dstp.is_memory() && srcp.is_immediate())
+ emit_mov_m32_imm(dst, MABS(dstp.memory()), srcp.immediate()); // mov [dstp],srcp
+
+ // conditional memory to register
+ else if (inst.condition() != uml::COND_ALWAYS && dstp.is_int_register() && srcp.is_memory())
+ {
+ dst = savedst;
+ skip.target = NULL;
+ emit_cmovcc_r32_m32(dst, X86_CONDITION(inst.condition()), dstp.ireg(), MABS(srcp.memory()));
+ // cmovcc dstp,[srcp]
+ }
+
+ // conditional register to register
+ else if (inst.condition() != uml::COND_ALWAYS && dstp.is_int_register() && srcp.is_int_register())
+ {
+ dst = savedst;
+ skip.target = NULL;
+ emit_cmovcc_r32_r32(dst, X86_CONDITION(inst.condition()), dstp.ireg(), srcp.ireg());
+ // cmovcc dstp,srcp
+ }
+
+ // general case
+ else
+ {
+ emit_mov_r32_p32_keepflags(dst, dstreg, srcp); // mov dstreg,srcp
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // register to memory
+ if (dstp.is_memory() && srcp.is_int_register())
+ {
+ emit_mov_r32_m32(dst, REG_EAX, MABS(m_reghi[srcp.ireg()])); // mov eax,reghi[srcp]
+ emit_mov_m32_r32(dst, MABS(dstp.memory()), srcp.ireg()); // mov [dstp],srcp
+ emit_mov_m32_r32(dst, MABS(dstp.memory(4)), REG_EAX); // mov [dstp+4],eax
+ }
+
+ // immediate to memory
+ else if (dstp.is_memory() && srcp.is_immediate())
+ {
+ emit_mov_m32_imm(dst, MABS(dstp.memory()), srcp.immediate()); // mov [dstp],srcp
+ emit_mov_m32_imm(dst, MABS(dstp.memory(4)), srcp.immediate() >> 32); // mov [dstp+4],srcp >> 32
+ }
+
+ // general case
+ else
+ {
+ emit_mov_r64_p64(dst, dstreg, REG_EDX, srcp); // mov edx:dstreg,srcp
+ emit_mov_p64_r64(dst, dstp, dstreg, REG_EDX); // mov dstp,edx:dstreg
+ }
+ }
+
+ // resolve the jump
+ if (skip.target != NULL)
+ track_resolve_link(dst, skip);
+}
+
+
+//-------------------------------------------------
+// op_sext - process a SEXT opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_sext(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_S | FLAG_Z);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter srcp(*this, inst.param(1), PTYPE_MRI);
+ const parameter &sizep = inst.param(2);
+ assert(sizep.is_size());
+
+ // pick a target register for the general case
+ int dstreg = (inst.size() == 8) ? REG_EAX : dstp.select_register(REG_EAX);
+
+ // convert 8-bit source registers to EAX
+ if (sizep.size() == SIZE_BYTE && srcp.is_int_register() && (srcp.ireg() & 4))
+ {
+ emit_mov_r32_r32(dst, REG_EAX, srcp.ireg()); // mov eax,srcp
+ srcp = be_parameter::make_ireg(REG_EAX);
+ }
+
+ // general case
+ if (srcp.is_memory())
+ {
+ if (sizep.size() == SIZE_BYTE)
+ emit_movsx_r32_m8(dst, dstreg, MABS(srcp.memory())); // movsx dstreg,[srcp]
+ else if (sizep.size() == SIZE_WORD)
+ emit_movsx_r32_m16(dst, dstreg, MABS(srcp.memory())); // movsx dstreg,[srcp]
+ else if (sizep.size() == SIZE_DWORD)
+ emit_mov_r32_m32(dst, dstreg, MABS(srcp.memory())); // mov dstreg,[srcp]
+ }
+ else if (srcp.is_int_register())
+ {
+ if (sizep.size() == SIZE_BYTE)
+ emit_movsx_r32_r8(dst, dstreg, srcp.ireg()); // movsx dstreg,srcp
+ else if (sizep.size() == SIZE_WORD)
+ emit_movsx_r32_r16(dst, dstreg, srcp.ireg()); // movsx dstreg,srcp
+ else if (sizep.size() == SIZE_DWORD && dstreg != srcp.ireg())
+ emit_mov_r32_r32(dst, dstreg, srcp.ireg()); // mov dstreg,srcp
+ }
+ if (inst.flags() != 0)
+ emit_test_r32_r32(dst, dstreg, dstreg); // test dstreg,dstreg
+
+ // 32-bit form: store the low 32 bits
+ if (inst.size() == 4)
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+
+ // 64-bit form: sign extend to 64 bits and store edx:eax
+ else if (inst.size() == 8)
+ {
+ emit_cdq(dst); // cdq
+ emit_mov_p64_r64(dst, dstp, REG_EAX, REG_EDX); // mov dstp,edx:eax
+ }
+}
+
+
+//-------------------------------------------------
+// op_roland - process an ROLAND opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_roland(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_S | FLAG_Z);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter srcp(*this, inst.param(1), PTYPE_MRI);
+ be_parameter shiftp(*this, inst.param(2), PTYPE_MRI);
+ be_parameter maskp(*this, inst.param(3), PTYPE_MRI);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX, shiftp, maskp);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ emit_mov_r32_p32(dst, dstreg, srcp); // mov dstreg,srcp
+ emit_rol_r32_p32(dst, dstreg, shiftp, inst); // rol dstreg,shiftp
+ emit_and_r32_p32(dst, dstreg, maskp, inst); // and dstreg,maskp
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ emit_mov_r64_p64(dst, dstreg, REG_EDX, srcp); // mov edx:dstreg,srcp
+ emit_rol_r64_p64(dst, dstreg, REG_EDX, shiftp, inst); // rol edx:dstreg,shiftp
+ emit_and_r64_p64(dst, dstreg, REG_EDX, maskp, inst); // and edx:dstreg,maskp
+ emit_mov_p64_r64(dst, dstp, dstreg, REG_EDX); // mov dstp,edx:dstreg
+ }
+}
+
+
+//-------------------------------------------------
+// op_rolins - process an ROLINS opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_rolins(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_S | FLAG_Z);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter srcp(*this, inst.param(1), PTYPE_MRI);
+ be_parameter shiftp(*this, inst.param(2), PTYPE_MRI);
+ be_parameter maskp(*this, inst.param(3), PTYPE_MRI);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_ECX, shiftp, maskp);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ emit_mov_r32_p32(dst, REG_EAX, srcp); // mov eax,srcp
+ emit_rol_r32_p32(dst, REG_EAX, shiftp, inst); // rol eax,shiftp
+ emit_mov_r32_p32(dst, dstreg, dstp); // mov dstreg,dstp
+ if (maskp.is_immediate())
+ {
+ emit_and_r32_imm(dst, REG_EAX, maskp.immediate()); // and eax,maskp
+ emit_and_r32_imm(dst, dstreg, ~maskp.immediate()); // and dstreg,~maskp
+ }
+ else
+ {
+ emit_mov_r32_p32(dst, REG_EDX, maskp); // mov edx,maskp
+ emit_and_r32_r32(dst, REG_EAX, REG_EDX); // and eax,edx
+ emit_not_r32(dst, REG_EDX); // not edx
+ emit_and_r32_r32(dst, dstreg, REG_EDX); // and dstreg,edx
+ }
+ emit_or_r32_r32(dst, dstreg, REG_EAX); // or dstreg,eax
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ emit_mov_r64_p64(dst, REG_EAX, REG_EDX, srcp); // mov edx:eax,srcp
+ emit_rol_r64_p64(dst, REG_EAX, REG_EDX, shiftp, inst); // rol edx:eax,shiftp
+ if (maskp.is_immediate())
+ {
+ emit_and_r32_imm(dst, REG_EAX, maskp.immediate()); // and eax,maskp
+ emit_and_r32_imm(dst, REG_EDX, maskp.immediate() >> 32); // and edx,maskp >> 32
+ if (dstp.is_int_register())
+ {
+ emit_and_r32_imm(dst, dstp.ireg(), ~maskp.immediate()); // and dstp.lo,~maskp
+ emit_and_m32_imm(dst, MABS(m_reghi[dstp.ireg()]), ~maskp.immediate() >> 32);// and dstp.hi,~maskp >> 32
+ emit_or_r32_r32(dst, dstp.ireg(), REG_EAX); // or dstp.lo,eax
+ emit_or_m32_r32(dst, MABS(m_reghi[dstp.ireg()]), REG_EDX); // or dstp.hi,edx
+ }
+ else
+ {
+ emit_and_m32_imm(dst, MABS(dstp.memory()), ~maskp.immediate()); // and dstp.lo,~maskp
+ emit_and_m32_imm(dst, MABS(dstp.memory(4)), ~maskp.immediate() >> 32); // and dstp.hi,~maskp >> 32
+ emit_or_m32_r32(dst, MABS(dstp.memory()), REG_EAX); // or dstp.lo,eax
+ emit_or_m32_r32(dst, MABS(dstp.memory(4)), REG_EDX); // or dstp.hi,edx
+ }
+ }
+ else
+ {
+ int tempreg = REG_EBX;
+ emit_mov_m32_r32(dst, MBD(REG_ESP, -8), tempreg); // mov [esp-8],ebx
+ emit_mov_r64_p64(dst, tempreg, REG_ECX, maskp); // mov ecx:ebx,maskp
+ emit_and_r32_r32(dst, REG_EAX, tempreg); // and eax,ebx
+ emit_and_r32_r32(dst, REG_EDX, REG_ECX); // and edx,ecx
+ emit_not_r32(dst, tempreg); // not ebx
+ emit_not_r32(dst, REG_ECX); // not ecx
+ if (dstp.is_int_register())
+ {
+ emit_and_r32_r32(dst, dstp.ireg(), tempreg); // and dstp.lo,ebx
+ emit_and_m32_r32(dst, MABS(m_reghi[dstp.ireg()]), REG_ECX); // and dstp.hi,ecx
+ emit_or_r32_r32(dst, dstp.ireg(), REG_EAX); // or dstp.lo,eax
+ emit_or_m32_r32(dst, MABS(m_reghi[dstp.ireg()]), REG_EDX); // or dstp.hi,edx
+ }
+ else
+ {
+ emit_and_m32_r32(dst, MABS(dstp.memory()), tempreg); // and dstp.lo,ebx
+ emit_and_m32_r32(dst, MABS(dstp.memory(4)), REG_ECX); // and dstp.hi,ecx
+ emit_or_m32_r32(dst, MABS(dstp.memory()), REG_EAX); // or dstp.lo,eax
+ emit_or_m32_r32(dst, MABS(dstp.memory(4)), REG_EDX); // or dstp.hi,edx
+ }
+ emit_mov_r32_m32(dst, tempreg, MBD(REG_ESP, -8)); // mov ebx,[esp-8]
+ }
+ if (inst.flags() == FLAG_Z)
+ emit_or_r32_r32(dst, REG_EAX, REG_EDX); // or eax,edx
+ else if (inst.flags() == FLAG_S)
+ ;// do nothing -- final OR will have the right result
+ else if (inst.flags() == (FLAG_Z | FLAG_S))
+ {
+ emit_movzx_r32_r16(dst, REG_ECX, REG_AX); // movzx ecx,ax
+ emit_shr_r32_imm(dst, REG_EAX, 16); // shr eax,16
+ emit_or_r32_r32(dst, REG_EDX, REG_ECX); // or edx,ecx
+ emit_or_r32_r32(dst, REG_EDX, REG_EAX); // or edx,eax
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// op_add - process a ADD opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_add(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_C | FLAG_V | FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
+ be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
+ normalize_commutative(src1p, src2p);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX, src2p);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_add_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // add [dstp],src2p
+
+ // reg = reg + imm
+ else if (dstp.is_int_register() && src1p.is_int_register() && src2p.is_immediate() && inst.flags() == 0)
+ emit_lea_r32_m32(dst, dstp.ireg(), MBD(src1p.ireg(), src2p.immediate())); // lea dstp,[src1p+src2p]
+
+ // reg = reg + reg
+ else if (dstp.is_int_register() && src1p.is_int_register() && src2p.is_int_register() && inst.flags() == 0)
+ emit_lea_r32_m32(dst, dstp.ireg(), MBISD(src1p.ireg(), src2p.ireg(), 1, 0)); // lea dstp,[src1p+src2p]
+
+ // general case
+ else
+ {
+ emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_add_r32_p32(dst, dstreg, src2p, inst); // add dstreg,src2p
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_add_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // add [dstp],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r64_p64(dst, dstreg, REG_EDX, src1p); // mov dstreg:dstp,[src1p]
+ emit_add_r64_p64(dst, dstreg, REG_EDX, src2p, inst); // add dstreg:dstp,src2p
+ emit_mov_p64_r64(dst, dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// op_addc - process a ADDC opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_addc(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_C | FLAG_V | FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
+ be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
+ normalize_commutative(src1p, src2p);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX, src2p);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_adc_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // adc [dstp],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r32_p32_keepflags(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_adc_r32_p32(dst, dstreg, src2p, inst); // adc dstreg,src2p
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_adc_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // adc [dstp],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r64_p64_keepflags(dst, dstreg, REG_EDX, src1p); // mov dstreg:dstp,[src1p]
+ emit_adc_r64_p64(dst, dstreg, REG_EDX, src2p, inst); // adc dstreg:dstp,src2p
+ emit_mov_p64_r64(dst, dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// op_sub - process a SUB opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_sub(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_C | FLAG_V | FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
+ be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX, src2p);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_sub_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // sub [dstp],src2p
+
+ // reg = reg - imm
+ else if (dstp.is_int_register() && src1p.is_int_register() && src2p.is_immediate() && inst.flags() == 0)
+ emit_lea_r32_m32(dst, dstp.ireg(), MBD(src1p.ireg(), -src2p.immediate())); // lea dstp,[src1p-src2p]
+
+ // general case
+ else
+ {
+ emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_sub_r32_p32(dst, dstreg, src2p, inst); // sub dstreg,src2p
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_sub_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // sub [dstp],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r64_p64(dst, dstreg, REG_EDX, src1p); // mov dstreg:dstp,[src1p]
+ emit_sub_r64_p64(dst, dstreg, REG_EDX, src2p, inst); // sub dstreg:dstp,src2p
+ emit_mov_p64_r64(dst, dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// op_subc - process a SUBC opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_subc(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_C | FLAG_V | FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
+ be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX, src2p);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_sbb_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // sbb [dstp],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r32_p32_keepflags(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_sbb_r32_p32(dst, dstreg, src2p, inst); // sbb dstreg,src2p
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_sbb_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // sbb [dstp],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r64_p64_keepflags(dst, dstreg, REG_EDX, src1p); // mov dstreg:dstp,[src1p]
+ emit_sbb_r64_p64(dst, dstreg, REG_EDX, src2p, inst); // sbb dstreg:dstp,src2p
+ emit_mov_p64_r64(dst, dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// op_cmp - process a CMP opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_cmp(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_C | FLAG_V | FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter src1p(*this, inst.param(0), PTYPE_MRI);
+ be_parameter src2p(*this, inst.param(1), PTYPE_MRI);
+
+ // pick a target register for the general case
+ int src1reg = src1p.select_register(REG_EAX);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // memory versus anything
+ if (src1p.is_memory())
+ emit_cmp_m32_p32(dst, MABS(src1p.memory()), src2p, inst); // cmp [dstp],src2p
+
+ // general case
+ else
+ {
+ if (src1p.is_immediate())
+ emit_mov_r32_imm(dst, src1reg, src1p.immediate()); // mov src1reg,imm
+ emit_cmp_r32_p32(dst, src1reg, src2p, inst); // cmp src1reg,src2p
+ }
+ }
+
+ // 64-bit form
+ else
+ {
+ // general case
+ emit_mov_r64_p64(dst, REG_EAX, REG_EDX, src1p); // mov eax:dstp,[src1p]
+ emit_cmp_r64_p64(dst, REG_EAX, REG_EDX, src2p, inst); // cmp eax:dstp,src2p
+ }
+}
+
+
+//-------------------------------------------------
+// op_mulu - process a MULU opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_mulu(x86code *&dst, const instruction &inst)
+{
+ UINT8 zsflags = inst.flags() & (FLAG_Z | FLAG_S);
+ UINT8 vflag = inst.flags() & FLAG_V;
+
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_V | FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter edstp(*this, inst.param(1), PTYPE_MR);
+ be_parameter src1p(*this, inst.param(2), PTYPE_MRI);
+ be_parameter src2p(*this, inst.param(3), PTYPE_MRI);
+ normalize_commutative(src1p, src2p);
+ bool compute_hi = (dstp != edstp);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // general case
+ emit_mov_r32_p32(dst, REG_EAX, src1p); // mov eax,src1p
+ if (src2p.is_memory())
+ emit_mul_m32(dst, MABS(src2p.memory())); // mul [src2p]
+ else if (src2p.is_int_register())
+ emit_mul_r32(dst, src2p.ireg()); // mul src2p
+ else if (src2p.is_immediate())
+ {
+ emit_mov_r32_imm(dst, REG_EDX, src2p.immediate()); // mov edx,src2p
+ emit_mul_r32(dst, REG_EDX); // mul edx
+ }
+ emit_mov_p32_r32(dst, dstp, REG_EAX); // mov dstp,eax
+ if (compute_hi)
+ emit_mov_p32_r32(dst, edstp, REG_EDX); // mov edstp,edx
+
+ // compute flags
+ if (inst.flags() != 0)
+ {
+ if (zsflags != 0)
+ {
+ if (vflag)
+ emit_pushf(dst); // pushf
+ if (compute_hi)
+ {
+ if (zsflags == FLAG_Z)
+ emit_or_r32_r32(dst, REG_EDX, REG_EAX); // or edx,eax
+ else if (zsflags == FLAG_S)
+ emit_test_r32_r32(dst, REG_EDX, REG_EDX); // test edx,edx
+ else
+ {
+ emit_movzx_r32_r16(dst, REG_ECX, REG_AX); // movzx ecx,ax
+ emit_shr_r32_imm(dst, REG_EAX, 16); // shr eax,16
+ emit_or_r32_r32(dst, REG_EDX, REG_ECX); // or edx,ecx
+ emit_or_r32_r32(dst, REG_EDX, REG_EAX); // or edx,eax
+ }
+ }
+ else
+ emit_test_r32_r32(dst, REG_EAX, REG_EAX); // test eax,eax
+
+ // we rely on the fact that OF is cleared by all logical operations above
+ if (vflag)
+ {
+ emit_pushf(dst); // pushf
+ emit_pop_r32(dst, REG_EAX); // pop eax
+ emit_and_m32_imm(dst, MBD(REG_ESP, 0), ~0x84); // and [esp],~0x84
+ emit_or_m32_r32(dst, MBD(REG_ESP, 0), REG_EAX); // or [esp],eax
+ emit_popf(dst); // popf
+ }
+ }
+ }
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // general case
+ emit_mov_m32_imm(dst, MBD(REG_ESP, 24), inst.flags()); // mov [esp+24],flags
+ emit_mov_m64_p64(dst, MBD(REG_ESP, 16), src2p); // mov [esp+16],src2p
+ emit_mov_m64_p64(dst, MBD(REG_ESP, 8), src1p); // mov [esp+8],src1p
+ if (!compute_hi)
+ emit_mov_m32_imm(dst, MBD(REG_ESP, 4), (FPTR)&m_reslo); // mov [esp+4],&reslo
+ else
+ emit_mov_m32_imm(dst, MBD(REG_ESP, 4), (FPTR)&m_reshi); // mov [esp+4],&reshi
+ emit_mov_m32_imm(dst, MBD(REG_ESP, 0), (FPTR)&m_reslo); // mov [esp],&reslo
+ emit_call(dst, (x86code *)dmulu); // call dmulu
+ if (inst.flags() != 0)
+ emit_push_m32(dst, MABSI(flags_unmap, REG_EAX, 4)); // push flags_unmap[eax*4]
+ emit_mov_r32_m32(dst, REG_EAX, MABS((UINT32 *)&m_reslo + 0)); // mov eax,reslo.lo
+ emit_mov_r32_m32(dst, REG_EDX, MABS((UINT32 *)&m_reslo + 1)); // mov edx,reslo.hi
+ emit_mov_p64_r64(dst, dstp, REG_EAX, REG_EDX); // mov dstp,edx:eax
+ if (compute_hi)
+ {
+ emit_mov_r32_m32(dst, REG_EAX, MABS((UINT32 *)&m_reshi + 0)); // mov eax,reshi.lo
+ emit_mov_r32_m32(dst, REG_ECX, MABS((UINT32 *)&m_reshi + 1)); // mov ecx,reshi.hi
+ emit_mov_p64_r64(dst, edstp, REG_EAX, REG_ECX); // mov edstp,ecx:eax
+ }
+ if (inst.flags() != 0)
+ emit_popf(dst); // popf
+ }
+}
+
+
+//-------------------------------------------------
+// op_muls - process a MULS opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_muls(x86code *&dst, const instruction &inst)
+{
+ UINT8 zsflags = inst.flags() & (FLAG_Z | FLAG_S);
+ UINT8 vflag = inst.flags() & FLAG_V;
+
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_V | FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter edstp(*this, inst.param(1), PTYPE_MR);
+ be_parameter src1p(*this, inst.param(2), PTYPE_MRI);
+ be_parameter src2p(*this, inst.param(3), PTYPE_MRI);
+ normalize_commutative(src1p, src2p);
+ bool compute_hi = (dstp != edstp);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // 32-bit destination with memory/immediate or register/immediate
+ if (!compute_hi && !src1p.is_immediate() && src2p.is_immediate())
+ {
+ if (src1p.is_memory())
+ emit_imul_r32_m32_imm(dst, REG_EAX, MABS(src1p.memory()), src2p.immediate()); // imul eax,[src1p],src2p
+ else if (src1p.is_int_register())
+ emit_imul_r32_r32_imm(dst, REG_EAX, src1p.ireg(), src2p.immediate()); // imul eax,src1p,src2p
+ emit_mov_p32_r32(dst, dstp, REG_EAX); // mov dstp,eax
+ }
+
+ // 32-bit destination, general case
+ else if (!compute_hi)
+ {
+ emit_mov_r32_p32(dst, REG_EAX, src1p); // mov eax,src1p
+ if (src2p.is_memory())
+ emit_imul_r32_m32(dst, REG_EAX, MABS(src2p.memory())); // imul eax,[src2p]
+ else if (src2p.is_int_register())
+ emit_imul_r32_r32(dst, REG_EAX, src2p.ireg()); // imul eax,src2p
+ emit_mov_p32_r32(dst, dstp, REG_EAX); // mov dstp,eax
+ }
+
+ // 64-bit destination, general case
+ else
+ {
+ emit_mov_r32_p32(dst, REG_EAX, src1p); // mov eax,src1p
+ if (src2p.is_memory())
+ emit_imul_m32(dst, MABS(src2p.memory())); // imul [src2p]
+ else if (src2p.is_int_register())
+ emit_imul_r32(dst, src2p.ireg()); // imul src2p
+ else if (src2p.is_immediate())
+ {
+ emit_mov_r32_imm(dst, REG_EDX, src2p.immediate()); // mov edx,src2p
+ emit_imul_r32(dst, REG_EDX); // imul edx
+ }
+ emit_mov_p32_r32(dst, dstp, REG_EAX); // mov dstp,eax
+ emit_mov_p32_r32(dst, edstp, REG_EDX); // mov edstp,edx
+ }
+
+ // compute flags
+ if (inst.flags() != 0)
+ {
+ if (zsflags != 0)
+ {
+ if (vflag)
+ emit_pushf(dst); // pushf
+ if (compute_hi)
+ {
+ if (inst.flags() == FLAG_Z)
+ emit_or_r32_r32(dst, REG_EDX, REG_EAX); // or edx,eax
+ else if (inst.flags() == FLAG_S)
+ emit_test_r32_r32(dst, REG_EDX, REG_EDX); // test edx,edx
+ else
+ {
+ emit_movzx_r32_r16(dst, REG_ECX, REG_AX); // movzx ecx,ax
+ emit_shr_r32_imm(dst, REG_EAX, 16); // shr eax,16
+ emit_or_r32_r32(dst, REG_EDX, REG_ECX); // or edx,ecx
+ emit_or_r32_r32(dst, REG_EDX, REG_EAX); // or edx,eax
+ }
+ }
+ else
+ emit_test_r32_r32(dst, REG_EAX, REG_EAX); // test eax,eax
+
+ // we rely on the fact that OF is cleared by all logical operations above
+ if (vflag)
+ {
+ emit_pushf(dst); // pushf
+ emit_pop_r32(dst, REG_EAX); // pop eax
+ emit_and_m32_imm(dst, MBD(REG_ESP, 0), ~0x84); // and [esp],~0x84
+ emit_or_m32_r32(dst, MBD(REG_ESP, 0), REG_EAX); // or [esp],eax
+ emit_popf(dst); // popf
+ }
+ }
+ }
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // general case
+ emit_mov_m32_imm(dst, MBD(REG_ESP, 24), inst.flags()); // mov [esp+24],flags
+ emit_mov_m64_p64(dst, MBD(REG_ESP, 16), src2p); // mov [esp+16],src2p
+ emit_mov_m64_p64(dst, MBD(REG_ESP, 8), src1p); // mov [esp+8],src1p
+ if (!compute_hi)
+ emit_mov_m32_imm(dst, MBD(REG_ESP, 4), (FPTR)&m_reslo); // mov [esp+4],&reslo
+ else
+ emit_mov_m32_imm(dst, MBD(REG_ESP, 4), (FPTR)&m_reshi); // push [esp+4],&reshi
+ emit_mov_m32_imm(dst, MBD(REG_ESP, 0), (FPTR)&m_reslo); // mov [esp],&reslo
+ emit_call(dst, (x86code *)dmuls); // call dmuls
+ if (inst.flags() != 0)
+ emit_push_m32(dst, MABSI(flags_unmap, REG_EAX, 4)); // push flags_unmap[eax*4]
+ emit_mov_r32_m32(dst, REG_EAX, MABS((UINT32 *)&m_reslo + 0)); // mov eax,reslo.lo
+ emit_mov_r32_m32(dst, REG_EDX, MABS((UINT32 *)&m_reslo + 1)); // mov edx,reslo.hi
+ emit_mov_p64_r64(dst, dstp, REG_EAX, REG_EDX); // mov dstp,edx:eax
+ if (compute_hi)
+ {
+ emit_mov_r32_m32(dst, REG_EAX, MABS((UINT32 *)&m_reshi + 0)); // mov eax,reshi.lo
+ emit_mov_r32_m32(dst, REG_EDX, MABS((UINT32 *)&m_reshi + 1)); // mov edx,reshi.hi
+ emit_mov_p64_r64(dst, edstp, REG_EAX, REG_EDX); // mov edstp,edx:eax
+ }
+ if (inst.flags() != 0)
+ emit_popf(dst); // popf
+ }
+}
+
+
+//-------------------------------------------------
+// op_divu - process a DIVU opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_divu(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_V | FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter edstp(*this, inst.param(1), PTYPE_MR);
+ be_parameter src1p(*this, inst.param(2), PTYPE_MRI);
+ be_parameter src2p(*this, inst.param(3), PTYPE_MRI);
+ bool compute_rem = (dstp != edstp);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // general case
+ emit_mov_r32_p32(dst, REG_ECX, src2p); // mov ecx,src2p
+ if (inst.flags() != 0)
+ {
+ emit_mov_r32_imm(dst, REG_EAX, 0xa0000000); // mov eax,0xa0000000
+ emit_add_r32_r32(dst, REG_EAX, REG_EAX); // add eax,eax
+ }
+ emit_link skip;
+ emit_jecxz_link(dst, skip); // jecxz skip
+ emit_mov_r32_p32(dst, REG_EAX, src1p); // mov eax,src1p
+ emit_xor_r32_r32(dst, REG_EDX, REG_EDX); // xor edx,edx
+ emit_div_r32(dst, REG_ECX); // div ecx
+ emit_mov_p32_r32(dst, dstp, REG_EAX); // mov dstp,eax
+ if (compute_rem)
+ emit_mov_p32_r32(dst, edstp, REG_EDX); // mov edstp,edx
+ if (inst.flags() != 0)
+ emit_test_r32_r32(dst, REG_EAX, REG_EAX); // test eax,eax
+ track_resolve_link(dst, skip); // skip:
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // general case
+ emit_mov_m64_p64(dst, MBD(REG_ESP, 16), src2p); // mov [esp+16],src2p
+ emit_mov_m64_p64(dst, MBD(REG_ESP, 8), src1p); // mov [esp+8],src1p
+ if (!compute_rem)
+ emit_mov_m32_imm(dst, MBD(REG_ESP, 4), (FPTR)&m_reslo); // mov [esp+4],&reslo
+ else
+ emit_mov_m32_imm(dst, MBD(REG_ESP, 4), (FPTR)&m_reshi); // push [esp+4],&reshi
+ emit_mov_m32_imm(dst, MBD(REG_ESP, 0), (FPTR)&m_reslo); // mov [esp],&reslo
+ emit_call(dst, (x86code *)ddivu); // call ddivu
+ if (inst.flags() != 0)
+ emit_push_m32(dst, MABSI(flags_unmap, REG_EAX, 4)); // push flags_unmap[eax*4]
+ emit_mov_r32_m32(dst, REG_EAX, MABS((UINT32 *)&m_reslo + 0)); // mov eax,reslo.lo
+ emit_mov_r32_m32(dst, REG_EDX, MABS((UINT32 *)&m_reslo + 1)); // mov edx,reslo.hi
+ emit_mov_p64_r64(dst, dstp, REG_EAX, REG_EDX); // mov dstp,edx:eax
+ if (compute_rem)
+ {
+ emit_mov_r32_m32(dst, REG_EAX, MABS((UINT32 *)&m_reshi + 0)); // mov eax,reshi.lo
+ emit_mov_r32_m32(dst, REG_EDX, MABS((UINT32 *)&m_reshi + 1)); // mov edx,reshi.hi
+ emit_mov_p64_r64(dst, edstp, REG_EAX, REG_EDX); // mov edstp,edx:eax
+ }
+ if (inst.flags() != 0)
+ emit_popf(dst); // popf
+ }
+}
+
+
+//-------------------------------------------------
+// op_divs - process a DIVS opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_divs(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_V | FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter edstp(*this, inst.param(1), PTYPE_MR);
+ be_parameter src1p(*this, inst.param(2), PTYPE_MRI);
+ be_parameter src2p(*this, inst.param(3), PTYPE_MRI);
+ bool compute_rem = (dstp != edstp);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // general case
+ emit_mov_r32_p32(dst, REG_ECX, src2p); // mov ecx,src2p
+ if (inst.flags() != 0)
+ {
+ emit_mov_r32_imm(dst, REG_EAX, 0xa0000000); // mov eax,0xa0000000
+ emit_add_r32_r32(dst, REG_EAX, REG_EAX); // add eax,eax
+ }
+ emit_link skip;
+ emit_jecxz_link(dst, skip); // jecxz skip
+ emit_mov_r32_p32(dst, REG_EAX, src1p); // mov eax,src1p
+ emit_cdq(dst); // cdq
+ emit_idiv_r32(dst, REG_ECX); // idiv ecx
+ emit_mov_p32_r32(dst, dstp, REG_EAX); // mov dstp,eax
+ if (compute_rem)
+ emit_mov_p32_r32(dst, edstp, REG_EDX); // mov edstp,edx
+ if (inst.flags() != 0)
+ emit_test_r32_r32(dst, REG_EAX, REG_EAX); // test eax,eax
+ track_resolve_link(dst, skip); // skip:
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // general case
+ emit_mov_m64_p64(dst, MBD(REG_ESP, 16), src2p); // mov [esp+16],src2p
+ emit_mov_m64_p64(dst, MBD(REG_ESP, 8), src1p); // mov [esp+8],src1p
+ if (!compute_rem)
+ emit_mov_m32_imm(dst, MBD(REG_ESP, 4), (FPTR)&m_reslo); // mov [esp+4],&reslo
+ else
+ emit_mov_m32_imm(dst, MBD(REG_ESP, 4), (FPTR)&m_reshi); // push [esp+4],&reshi
+ emit_mov_m32_imm(dst, MBD(REG_ESP, 0), (FPTR)&m_reslo); // mov [esp],&reslo
+ emit_call(dst, (x86code *)ddivs); // call ddivs
+ if (inst.flags() != 0)
+ emit_push_m32(dst, MABSI(flags_unmap, REG_EAX, 4)); // push flags_unmap[eax*4]
+ emit_mov_r32_m32(dst, REG_EAX, MABS((UINT32 *)&m_reslo + 0)); // mov eax,reslo.lo
+ emit_mov_r32_m32(dst, REG_EDX, MABS((UINT32 *)&m_reslo + 1)); // mov edx,reslo.hi
+ emit_mov_p64_r64(dst, dstp, REG_EAX, REG_EDX); // mov dstp,edx:eax
+ if (compute_rem)
+ {
+ emit_mov_r32_m32(dst, REG_EAX, MABS((UINT32 *)&m_reshi + 0)); // mov eax,reshi.lo
+ emit_mov_r32_m32(dst, REG_EDX, MABS((UINT32 *)&m_reshi + 1)); // mov edx,reshi.hi
+ emit_mov_p64_r64(dst, edstp, REG_EAX, REG_EDX); // mov edstp,edx:eax
+ }
+ if (inst.flags() != 0)
+ emit_popf(dst); // popf
+ }
+}
+
+
+//-------------------------------------------------
+// op_and - process a AND opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_and(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
+ be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
+ normalize_commutative(src1p, src2p);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX, src2p);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_and_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // and [dstp],src2p
+
+ // AND with immediate 0xff
+ else if (src2p.is_immediate_value(0xff) && inst.flags() == 0)
+ {
+ if (src1p.is_int_register())
+ emit_movzx_r32_r8(dst, dstreg, src1p.ireg()); // movzx dstreg,src1p
+ else if (src1p.is_memory())
+ emit_movzx_r32_m8(dst, dstreg, MABS(src1p.memory())); // movzx dstreg,[src1p]
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+
+ // AND with immediate 0xffff
+ else if (src2p.is_immediate_value(0xffff) && inst.flags() == 0)
+ {
+ if (src1p.is_int_register())
+ emit_movzx_r32_r16(dst, dstreg, src1p.ireg()); // movzx dstreg,src1p
+ else if (src1p.is_memory())
+ emit_movzx_r32_m16(dst, dstreg, MABS(src1p.memory())); // movzx dstreg,[src1p]
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+
+ // general case
+ else
+ {
+ emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_and_r32_p32(dst, dstreg, src2p, inst); // and dstreg,src2p
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_and_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // and [dstp],src2p
+
+ // AND with immediate 0xff
+ else if (src2p.is_immediate_value(0xff) && inst.flags() == 0)
+ {
+ if (src1p.is_int_register())
+ emit_movzx_r32_r8(dst, dstreg, src1p.ireg()); // movzx dstreg,src1p
+ else if (src1p.is_memory())
+ emit_movzx_r32_m8(dst, dstreg, MABS(src1p.memory())); // movzx dstreg,[src1p]
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ if (dstp.is_int_register())
+ emit_mov_m32_imm(dst, MABS(m_reghi[dstp.ireg()]), 0); // mov dsthi,0
+ else if (dstp.is_memory())
+ emit_mov_m32_imm(dst, MABS(dstp.memory(4)), 0); // mov dsthi,0
+ }
+
+ // AND with immediate 0xffff
+ else if (src2p.is_immediate_value(0xffff) && inst.flags() == 0)
+ {
+ if (src1p.is_int_register())
+ emit_movzx_r32_r16(dst, dstreg, src1p.ireg()); // movzx dstreg,src1p
+ else if (src1p.is_memory())
+ emit_movzx_r32_m16(dst, dstreg, MABS(src1p.memory())); // movzx dstreg,[src1p]
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ if (dstp.is_int_register())
+ emit_mov_m32_imm(dst, MABS(m_reghi[dstp.ireg()]), 0); // mov dsthi,0
+ else if (dstp.is_memory())
+ emit_mov_m32_imm(dst, MABS(dstp.memory(4)), 0); // mov dsthi,0
+ }
+
+ // AND with immediate 0xffffffff
+ else if (src2p.is_immediate_value(0xffffffff) && inst.flags() == 0)
+ {
+ emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ if (dstp.is_int_register())
+ emit_mov_m32_imm(dst, MABS(m_reghi[dstp.ireg()]), 0); // mov dsthi,0
+ else if (dstp.is_memory())
+ emit_mov_m32_imm(dst, MABS(dstp.memory(4)), 0); // mov dsthi,0
+ }
+
+ // AND with immediate 0xffffffff00000000
+ else if (src2p.is_immediate_value(U64(0xffffffff00000000)) && inst.flags() == 0)
+ {
+ if (src1p != dstp)
+ {
+ emit_mov_r64_p64(dst, REG_NONE, REG_EDX, src1p); // mov dstreg,src1p
+ emit_mov_p64_r64(dst, dstp, REG_NONE, REG_EDX); // mov dstp,dstreg
+ }
+ if (dstp.is_int_register())
+ emit_xor_r32_r32(dst, dstp.ireg(), dstp.ireg()); // xor dstlo,dstlo
+ else if (dstp.is_memory())
+ emit_mov_m32_imm(dst, MABS(dstp.memory()), 0); // mov dstlo,0
+ }
+
+ // AND with immediate <= 0xffffffff
+ else if (src2p.is_immediate() && src2p.immediate() <= 0xffffffff && inst.flags() == 0)
+ {
+ emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_and_r32_p32(dst, dstreg, src2p, inst); // and dstreg,src2p
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ if (dstp.is_int_register())
+ emit_mov_m32_imm(dst, MABS(m_reghi[dstp.ireg()]), 0); // mov dsthi,0
+ else if (dstp.is_memory())
+ emit_mov_m32_imm(dst, MABS(dstp.memory(4)), 0); // mov dsthi,0
+ }
+
+ // general case
+ else
+ {
+ emit_mov_r64_p64(dst, dstreg, REG_EDX, src1p); // mov dstreg:dstp,[src1p]
+ emit_and_r64_p64(dst, dstreg, REG_EDX, src2p, inst); // and dstreg:dstp,src2p
+ emit_mov_p64_r64(dst, dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// op_test - process a TEST opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_test(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter src1p(*this, inst.param(0), PTYPE_MRI);
+ be_parameter src2p(*this, inst.param(1), PTYPE_MRI);
+ normalize_commutative(src1p, src2p);
+
+ // pick a target register for the general case
+ int src1reg = src1p.select_register(REG_EAX);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // src1p in memory
+ if (src1p.is_memory())
+ emit_test_m32_p32(dst, MABS(src1p.memory()), src2p, inst); // test [src1p],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r32_p32(dst, src1reg, src1p); // mov src1reg,src1p
+ emit_test_r32_p32(dst, src1reg, src2p, inst); // test src1reg,src2p
+ }
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // src1p in memory
+ if (src1p.is_memory())
+ emit_test_m64_p64(dst, MABS(src1p.memory()), src2p, inst); // test [dstp],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r64_p64(dst, src1reg, REG_EDX, src1p); // mov src1reg:dstp,[src1p]
+ emit_test_r64_p64(dst, src1reg, REG_EDX, src2p, inst); // test src1reg:dstp,src2p
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// op_or - process a OR opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_or(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
+ be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
+ normalize_commutative(src1p, src2p);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX, src2p);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_or_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // or [dstp],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_or_r32_p32(dst, dstreg, src2p, inst); // or dstreg,src2p
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_or_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // or [dstp],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r64_p64(dst, dstreg, REG_EDX, src1p); // mov dstreg:dstp,[src1p]
+ emit_or_r64_p64(dst, dstreg, REG_EDX, src2p, inst); // or dstreg:dstp,src2p
+ emit_mov_p64_r64(dst, dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// op_xor - process a XOR opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_xor(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
+ be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
+ normalize_commutative(src1p, src2p);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX, src2p);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_xor_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // xor [dstp],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_xor_r32_p32(dst, dstreg, src2p, inst); // xor dstreg,src2p
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_xor_m64_p64(dst, MABS(dstp.memory()), src2p, inst); // xor [dstp],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r64_p64(dst, dstreg, REG_EDX, src1p); // mov dstreg:dstp,[src1p]
+ emit_xor_r64_p64(dst, dstreg, REG_EDX, src2p, inst); // xor dstreg:dstp,src2p
+ emit_mov_p64_r64(dst, dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// op_lzcnt - process a LZCNT opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_lzcnt(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter srcp(*this, inst.param(1), PTYPE_MRI);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ emit_mov_r32_p32(dst, dstreg, srcp); // mov dstreg,src1p
+ emit_mov_r32_imm(dst, REG_ECX, 32 ^ 31); // mov ecx,32 ^ 31
+ emit_bsr_r32_r32(dst, dstreg, dstreg); // bsr dstreg,dstreg
+ emit_cmovcc_r32_r32(dst, x86emit::COND_Z, dstreg, REG_ECX); // cmovz dstreg,ecx
+ emit_xor_r32_imm(dst, dstreg, 31); // xor dstreg,31
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ emit_mov_r64_p64(dst, REG_EDX, dstreg, srcp); // mov dstreg:edx,srcp
+ emit_bsr_r32_r32(dst, dstreg, dstreg); // bsr dstreg,dstreg
+ emit_link skip;
+ emit_jcc_short_link(dst, x86emit::COND_NZ, skip); // jnz skip
+ emit_mov_r32_imm(dst, REG_ECX, 32 ^ 31); // mov ecx,32 ^ 31
+ emit_bsr_r32_r32(dst, dstreg, REG_EDX); // bsr dstreg,edx
+ emit_cmovcc_r32_r32(dst, x86emit::COND_Z, dstreg, REG_ECX); // cmovz dstreg,ecx
+ emit_add_r32_imm(dst, REG_ECX, 32); // add ecx,32
+ track_resolve_link(dst, skip); // skip:
+ emit_xor_r32_r32(dst, REG_EDX, REG_EDX); // xor edx,edx
+ emit_xor_r32_imm(dst, dstreg, 31); // xor dstreg,31
+ emit_mov_p64_r64(dst, dstp, dstreg, REG_EDX); // mov dstp,edx:dstreg
+ }
+}
+
+
+//-------------------------------------------------
+// op_bswap - process a BSWAP opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_bswap(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter srcp(*this, inst.param(1), PTYPE_MRI);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ emit_mov_r32_p32(dst, dstreg, srcp); // mov dstreg,src1p
+ emit_bswap_r32(dst, dstreg); // bswap dstreg
+ if (inst.flags() != 0)
+ emit_test_r32_r32(dst, dstreg, dstreg); // test dstreg,dstreg
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ emit_mov_r64_p64(dst, REG_EDX, dstreg, srcp); // mov dstreg:edx,srcp
+ emit_bswap_r32(dst, dstreg); // bswap dstreg
+ emit_bswap_r32(dst, REG_EDX); // bswap edx
+ emit_mov_p64_r64(dst, dstp, dstreg, REG_EDX); // mov dstp,edx:dstreg
+ if (inst.flags() == FLAG_Z)
+ emit_or_r32_r32(dst, REG_EDX, dstreg); // or edx,eax
+ else if (inst.flags() == FLAG_S)
+ emit_test_r32_r32(dst, REG_EDX, REG_EDX); // test edx,edx
+ else
+ {
+ emit_movzx_r32_r16(dst, REG_ECX, dstreg); // movzx ecx,dstreg
+ emit_or_r32_r32(dst, REG_EDX, REG_ECX); // or edx,ecx
+ emit_mov_r32_r32(dst, REG_ECX, dstreg); // mov ecx,dstreg
+ emit_shr_r32_imm(dst, REG_ECX, 16); // shr ecx,16
+ emit_or_r32_r32(dst, REG_EDX, REG_ECX); // or edx,ecx
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// op_shl - process a SHL opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_shl(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_C | FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
+ be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX, src2p);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_shl_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // shl [dstp],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_shl_r32_p32(dst, dstreg, src2p, inst); // shl dstreg,src2p
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // general case
+ emit_mov_r64_p64(dst, dstreg, REG_EDX, src1p); // mov dstreg:dstp,[src1p]
+ emit_shl_r64_p64(dst, dstreg, REG_EDX, src2p, inst); // shl dstreg:dstp,src2p
+ emit_mov_p64_r64(dst, dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
+ }
+}
+
+
+//-------------------------------------------------
+// op_shr - process a SHR opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_shr(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_C | FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
+ be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX, src2p);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_shr_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // shr [dstp],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_shr_r32_p32(dst, dstreg, src2p, inst); // shr dstreg,src2p
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // general case
+ emit_mov_r64_p64(dst, dstreg, REG_EDX, src1p); // mov dstreg:dstp,[src1p]
+ emit_shr_r64_p64(dst, dstreg, REG_EDX, src2p, inst); // shr dstreg:dstp,src2p
+ emit_mov_p64_r64(dst, dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
+ }
+}
+
+
+//-------------------------------------------------
+// op_sar - process a SAR opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_sar(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_C | FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
+ be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX, src2p);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_sar_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // sar [dstp],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_sar_r32_p32(dst, dstreg, src2p, inst); // sar dstreg,src2p
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // general case
+ emit_mov_r64_p64(dst, dstreg, REG_EDX, src1p); // mov dstreg:dstp,[src1p]
+ emit_sar_r64_p64(dst, dstreg, REG_EDX, src2p, inst); // sar dstreg:dstp,src2p
+ emit_mov_p64_r64(dst, dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
+ }
+}
+
+
+//-------------------------------------------------
+// op_rol - process a rol opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_rol(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_C | FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
+ be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX, src2p);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_rol_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // rol [dstp],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_rol_r32_p32(dst, dstreg, src2p, inst); // rol dstreg,src2p
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // general case
+ emit_mov_r64_p64(dst, dstreg, REG_EDX, src1p); // mov dstreg:dstp,[src1p]
+ emit_rol_r64_p64(dst, dstreg, REG_EDX, src2p, inst); // rol dstreg:dstp,src2p
+ emit_mov_p64_r64(dst, dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
+ }
+}
+
+
+//-------------------------------------------------
+// op_ror - process a ROR opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_ror(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_C | FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
+ be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX, src2p);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_ror_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // ror [dstp],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r32_p32(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_ror_r32_p32(dst, dstreg, src2p, inst); // ror dstreg,src2p
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // general case
+ emit_mov_r64_p64(dst, dstreg, REG_EDX, src1p); // mov dstreg:dstp,[src1p]
+ emit_ror_r64_p64(dst, dstreg, REG_EDX, src2p, inst); // ror dstreg:dstp,src2p
+ emit_mov_p64_r64(dst, dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
+ }
+}
+
+
+//-------------------------------------------------
+// op_rolc - process a ROLC opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_rolc(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_C | FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
+ be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX, src2p);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_rcl_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // rcl [dstp],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r32_p32_keepflags(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_rcl_r32_p32(dst, dstreg, src2p, inst); // rcl dstreg,src2p
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // general case
+ emit_mov_r64_p64_keepflags(dst, dstreg, REG_EDX, src1p); // mov dstreg:dstp,[src1p]
+ emit_rcl_r64_p64(dst, dstreg, REG_EDX, src2p, inst); // rcl dstreg:dstp,src2p
+ emit_mov_p64_r64(dst, dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
+ }
+}
+
+
+//-------------------------------------------------
+// op_rorc - process a RORC opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_rorc(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_C | FLAG_Z | FLAG_S);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter src1p(*this, inst.param(1), PTYPE_MRI);
+ be_parameter src2p(*this, inst.param(2), PTYPE_MRI);
+
+ // pick a target register for the general case
+ int dstreg = dstp.select_register(REG_EAX, src2p);
+
+ // 32-bit form
+ if (inst.size() == 4)
+ {
+ // dstp == src1p in memory
+ if (dstp.is_memory() && dstp == src1p)
+ emit_rcr_m32_p32(dst, MABS(dstp.memory()), src2p, inst); // rcr [dstp],src2p
+
+ // general case
+ else
+ {
+ emit_mov_r32_p32_keepflags(dst, dstreg, src1p); // mov dstreg,src1p
+ emit_rcr_r32_p32(dst, dstreg, src2p, inst); // rcr dstreg,src2p
+ emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
+ }
+ }
+
+ // 64-bit form
+ else if (inst.size() == 8)
+ {
+ // general case
+ emit_mov_r64_p64_keepflags(dst, dstreg, REG_EDX, src1p); // mov dstreg:dstp,[src1p]
+ emit_rcr_r64_p64(dst, dstreg, REG_EDX, src2p, inst); // rcr dstreg:dstp,src2p
+ emit_mov_p64_r64(dst, dstp, dstreg, REG_EDX); // mov dstp,dstreg:eax
+ }
+}
+
+
+
+//**************************************************************************
+// FLOATING POINT OPERATIONS
+//**************************************************************************
+
+//-------------------------------------------------
+// op_fload - process a FLOAD opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_fload(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MF);
+ be_parameter basep(*this, inst.param(1), PTYPE_M);
+ be_parameter indp(*this, inst.param(2), PTYPE_MRI);
+
+ // immediate index
+ if (indp.is_immediate())
+ {
+ emit_mov_r32_m32(dst, REG_EAX, MABS(basep.memory(4*indp.immediate()))); // mov eax,[basep + 4*indp]
+ if (inst.size() == 8)
+ emit_mov_r32_m32(dst, REG_EDX, MABS(basep.memory(4 + 4*indp.immediate()))); // mov edx,[basep + 4*indp + 4]
+ }
+
+ // other index
+ else
+ {
+ int indreg = indp.select_register(REG_ECX);
+ emit_mov_r32_p32(dst, indreg, indp);
+ emit_mov_r32_m32(dst, REG_EAX, MABSI(basep.memory(), indreg, 4)); // mov eax,[basep + 4*indp]
+ if (inst.size() == 8)
+ emit_mov_r32_m32(dst, REG_EDX, MABSI(basep.memory(4), indreg, 4)); // mov edx,[basep + 4*indp + 4]
+ }
+
+ // general case
+ emit_mov_m32_r32(dst, MABS(dstp.memory()), REG_EAX); // mov [dstp],eax
+ if (inst.size() == 8)
+ emit_mov_m32_r32(dst, MABS(dstp.memory(4)), REG_EDX); // mov [dstp + 4],edx
+}
+
+
+//-------------------------------------------------
+// op_fstore - process a FSTORE opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_fstore(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter basep(*this, inst.param(0), PTYPE_M);
+ be_parameter indp(*this, inst.param(1), PTYPE_MRI);
+ be_parameter srcp(*this, inst.param(2), PTYPE_MF);
+
+ // general case
+ emit_mov_r32_m32(dst, REG_EAX, MABS(srcp.memory())); // mov eax,[srcp]
+ if (inst.size() == 8)
+ emit_mov_r32_m32(dst, REG_EDX, MABS(srcp.memory(4))); // mov edx,[srcp + 4]
+
+ // immediate index
+ if (indp.is_immediate())
+ {
+ emit_mov_m32_r32(dst, MABS(basep.memory(4*indp.immediate())), REG_EAX); // mov [basep + 4*indp],eax
+ if (inst.size() == 8)
+ emit_mov_m32_r32(dst, MABS(basep.memory(4 + 4*indp.immediate())), REG_EDX); // mov [basep + 4*indp + 4],edx
+ }
+
+ // other index
+ else
+ {
+ int indreg = indp.select_register(REG_ECX);
+ emit_mov_r32_p32(dst, indreg, indp);
+ emit_mov_m32_r32(dst, MABSI(basep.memory(), indreg, 4), REG_EAX); // mov [basep + 4*indp],eax
+ if (inst.size() == 8)
+ emit_mov_m32_r32(dst, MABSI(basep.memory(4), indreg, 4), REG_EDX); // mov [basep + 4*indp + 4],edx
+ }
+}
+
+
+//-------------------------------------------------
+// op_fread - process a FREAD opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_fread(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MF);
+ be_parameter addrp(*this, inst.param(1), PTYPE_MRI);
+ const parameter &spacep = inst.param(2);
+ assert(spacep.is_size_space());
+ assert((1 << spacep.size()) == inst.size());
+
+ // set up a call to the read dword/qword handler
+ emit_mov_m32_p32(dst, MBD(REG_ESP, 4), addrp); // mov [esp+4],addrp
+ emit_mov_m32_imm(dst, MBD(REG_ESP, 0), (FPTR)m_space[spacep.space()]); // mov [esp],space
+ if (inst.size() == 4)
+ emit_call(dst, (x86code *)m_accessors[spacep.space()].read_dword); // call read_dword
+ else if (inst.size() == 8)
+ emit_call(dst, (x86code *)m_accessors[spacep.space()].read_qword); // call read_qword
+
+ // store result
+ if (inst.size() == 4)
+ emit_mov_p32_r32(dst, dstp, REG_EAX); // mov dstp,eax
+ else if (inst.size() == 8)
+ emit_mov_p64_r64(dst, dstp, REG_EAX, REG_EDX); // mov dstp,edx:eax
+}
+
+
+//-------------------------------------------------
+// op_fwrite - process a FWRITE opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_fwrite(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter addrp(*this, inst.param(0), PTYPE_MRI);
+ be_parameter srcp(*this, inst.param(1), PTYPE_MF);
+ const parameter &spacep = inst.param(2);
+ assert(spacep.is_size_space());
+ assert((1 << spacep.size()) == inst.size());
+
+ // set up a call to the write dword/qword handler
+ if (inst.size() == 4)
+ emit_mov_m32_p32(dst, MBD(REG_ESP, 8), srcp); // mov [esp+8],srcp
+ else if (inst.size() == 8)
+ emit_mov_m64_p64(dst, MBD(REG_ESP, 8), srcp); // mov [esp+8],srcp
+ emit_mov_m32_p32(dst, MBD(REG_ESP, 4), addrp); // mov [esp+4],addrp
+ emit_mov_m32_imm(dst, MBD(REG_ESP, 0), (FPTR)m_space[spacep.space()]); // mov [esp],space
+ if (inst.size() == 4)
+ emit_call(dst, (x86code *)m_accessors[spacep.space()].write_dword); // call write_dword
+ else if (inst.size() == 8)
+ emit_call(dst, (x86code *)m_accessors[spacep.space()].write_qword); // call write_qword
+}
+
+
+//-------------------------------------------------
+// op_fmov - process a FMOV opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_fmov(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_any_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MF);
+ be_parameter srcp(*this, inst.param(1), PTYPE_MF);
+
+ // always start with a jmp
+ emit_link skip = { 0 };
+ if (inst.condition() != uml::COND_ALWAYS)
+ emit_jcc_short_link(dst, X86_NOT_CONDITION(inst.condition()), skip); // jcc skip
+
+ // general case
+ emit_mov_r32_m32(dst, REG_EAX, MABS(srcp.memory())); // mov eax,[srcp]
+ if (inst.size() == 8)
+ emit_mov_r32_m32(dst, REG_EDX, MABS(srcp.memory(4))); // mov edx,[srcp + 4]
+ emit_mov_m32_r32(dst, MABS(dstp.memory()), REG_EAX); // mov [dstp],eax
+ if (inst.size() == 8)
+ emit_mov_m32_r32(dst, MABS(dstp.memory(4)), REG_EDX); // mov [dstp + 4],edx
+
+ // resolve the jump
+ if (skip.target != NULL)
+ track_resolve_link(dst, skip); // skip:
+}
+
+
+//-------------------------------------------------
+// op_ftoint - process a FTOINT opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_ftoint(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MR);
+ be_parameter srcp(*this, inst.param(1), PTYPE_MF);
+ const parameter &sizep = inst.param(2);
+ assert(sizep.is_size());
+ const parameter &roundp = inst.param(3);
+ assert(roundp.is_rounding());
+
+ // set rounding mode if necessary
+ if (roundp.rounding() != ROUND_DEFAULT && (!m_sse3 || roundp.rounding() != ROUND_TRUNC))
+ {
+ emit_fstcw_m16(dst, MABS(&m_fmodesave)); // fstcw [fmodesave]
+ emit_fldcw_m16(dst, MABS(&fp_control[roundp.rounding()])); // fldcw fpcontrol[roundp]
+ }
+
+ // general case
+ emit_fld_p(dst, inst.size(), srcp); // fld srcp
+
+ // 4-byte integer case
+ if (sizep.size() == SIZE_DWORD)
+ {
+ if (dstp.is_memory())
+ {
+ if (!m_sse3 || roundp.rounding() != ROUND_TRUNC)
+ emit_fistp_m32(dst, MABS(dstp.memory())); // fistp [dstp]
+ else
+ emit_fisttp_m32(dst, MABS(dstp.memory())); // fisttp [dstp]
+ }
+ else if (dstp.is_int_register())
+ {
+ if (!m_sse3 || roundp.rounding() != ROUND_TRUNC)
+ emit_fistp_m32(dst, MABS(m_reglo[dstp.ireg()])); // fistp reglo[dstp]
+ else
+ emit_fisttp_m32(dst, MABS(m_reglo[dstp.ireg()])); // fisttp reglo[dstp]
+ emit_mov_r32_m32(dst, dstp.ireg(), MABS(m_reglo[dstp.ireg()])); // mov dstp,reglo[dstp]
+ }
+ }
+
+ // 8-byte integer case
+ else if (sizep.size() == SIZE_QWORD)
+ {
+ if (dstp.is_memory())
+ {
+ if (!m_sse3 || roundp.rounding() != ROUND_TRUNC)
+ emit_fistp_m64(dst, MABS(dstp.memory())); // fistp [dstp]
+ else
+ emit_fisttp_m64(dst, MABS(dstp.memory())); // fisttp [dstp]
+ }
+ else if (dstp.is_int_register())
+ {
+ if (!m_sse3 || roundp.rounding() != ROUND_TRUNC)
+ emit_fistp_m64(dst, MABS(m_reglo[dstp.ireg()])); // fistp reglo[dstp]
+ else
+ emit_fisttp_m64(dst, MABS(m_reglo[dstp.ireg()])); // fisttp reglo[dstp]
+ emit_mov_r32_m32(dst, dstp.ireg(), MABS(m_reglo[dstp.ireg()])); // mov dstp,reglo[dstp]
+ }
+ }
+
+ // restore control word and proceed
+ if (roundp.rounding() != ROUND_DEFAULT && (!m_sse3 || roundp.rounding() != ROUND_TRUNC))
+ emit_fldcw_m16(dst, MABS(&m_fmodesave)); // fldcw [fmodesave]
+}
+
+
+//-------------------------------------------------
+// op_ffrint - process a FFRINT opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_ffrint(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MF);
+ be_parameter srcp(*this, inst.param(1), PTYPE_MRI);
+ const parameter &sizep = inst.param(2);
+ assert(sizep.is_size());
+
+ // 4-byte integer case
+ if (sizep.size() == SIZE_DWORD)
+ {
+ if (srcp.is_immediate())
+ {
+ emit_mov_m32_imm(dst, MABS(&m_fptemp), srcp.immediate()); // mov [fptemp],srcp
+ emit_fild_m32(dst, MABS(&m_fptemp)); // fild [fptemp]
+ }
+ else if (srcp.is_memory())
+ emit_fild_m32(dst, MABS(srcp.memory())); // fild [srcp]
+ else if (srcp.is_int_register())
+ {
+ emit_mov_m32_r32(dst, MABS(m_reglo[srcp.ireg()]), srcp.ireg()); // mov reglo[srcp],srcp
+ emit_fild_m32(dst, MABS(m_reglo[srcp.ireg()])); // fild reglo[srcp]
+ }
+ }
+
+ // 8-bit integer case
+ else if (sizep.size() == SIZE_QWORD)
+ {
+ if (srcp.is_immediate())
+ {
+ emit_mov_m32_imm(dst, MABS(&m_fptemp), srcp.immediate()); // mov [fptemp],srcp
+ emit_mov_m32_imm(dst, MABS((UINT8 *)&m_fptemp + 4), srcp.immediate()); // mov [fptemp+4],srcp
+ emit_fild_m64(dst, MABS(&m_fptemp)); // fild [fptemp]
+ }
+ else if (srcp.is_memory())
+ emit_fild_m64(dst, MABS(srcp.memory())); // fild [srcp]
+ else if (srcp.is_int_register())
+ {
+ emit_mov_m32_r32(dst, MABS(m_reglo[srcp.ireg()]), srcp.ireg()); // mov reglo[srcp],srcp
+ emit_fild_m64(dst, MABS(m_reglo[srcp.ireg()])); // fild reglo[srcp]
+ }
+ }
+
+ // store the result and be done
+ emit_fstp_p(dst, inst.size(), dstp); // fstp [dstp]
+}
+
+
+//-------------------------------------------------
+// op_ffrflt - process a FFRFLT opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_ffrflt(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MF);
+ be_parameter srcp(*this, inst.param(1), PTYPE_MF);
+ const parameter &sizep = inst.param(2);
+ assert(sizep.is_size());
+
+ // general case
+ if (sizep.size() == SIZE_DWORD)
+ emit_fld_m32(dst, MABS(srcp.memory())); // fld [srcp]
+ else if (sizep.size() == SIZE_QWORD)
+ emit_fld_m64(dst, MABS(srcp.memory())); // fld [srcp]
+ emit_fstp_p(dst, inst.size(), dstp); // fstp dstp
+}
+
+
+//-------------------------------------------------
+// op_frnds - process a FRNDS opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_frnds(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MF);
+ be_parameter srcp(*this, inst.param(1), PTYPE_MF);
+
+ // general case
+ emit_fld_p(dst, inst.size(), srcp); // fld srcp
+ emit_fstp_m32(dst, MABS(&m_fptemp)); // fstp [fptemp]
+ emit_fld_m32(dst, MABS(&m_fptemp)); // fld [fptemp]
+ emit_fstp_p(dst, inst.size(), dstp); // fstp [dstp]
+}
+
+
+//-------------------------------------------------
+// op_fadd - process a FADD opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_fadd(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MF);
+ be_parameter src1p(*this, inst.param(1), PTYPE_MF);
+ be_parameter src2p(*this, inst.param(2), PTYPE_MF);
+ normalize_commutative(src1p, src2p);
+
+ // general case
+ emit_fld_p(dst, inst.size(), src1p); // fld src1p
+ emit_fld_p(dst, inst.size(), src2p); // fld src2p
+ emit_faddp(dst); // faddp
+ emit_fstp_p(dst, inst.size(), dstp); // fstp dstp
+}
+
+
+//-------------------------------------------------
+// op_fsub - process a FSUB opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_fsub(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MF);
+ be_parameter src1p(*this, inst.param(1), PTYPE_MF);
+ be_parameter src2p(*this, inst.param(2), PTYPE_MF);
+
+ // general case
+ emit_fld_p(dst, inst.size(), src1p); // fld src1p
+ emit_fld_p(dst, inst.size(), src2p); // fld src2p
+ emit_fsubp(dst); // fsubp
+ emit_fstp_p(dst, inst.size(), dstp); // fstp dstp
+}
+
+
+//-------------------------------------------------
+// op_fcmp - process a FCMP opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_fcmp(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_flags(inst, FLAG_C | FLAG_Z | FLAG_U);
+
+ // normalize parameters
+ be_parameter src1p(*this, inst.param(0), PTYPE_MF);
+ be_parameter src2p(*this, inst.param(1), PTYPE_MF);
+
+ // general case
+ emit_fld_p(dst, inst.size(), src2p); // fld src2p
+ emit_fld_p(dst, inst.size(), src1p); // fld src1p
+ emit_fcompp(dst); // fcompp
+ emit_fstsw_ax(dst); // fnstsw ax
+ emit_sahf(dst); // sahf
+}
+
+
+//-------------------------------------------------
+// op_fmul - process a FMUL opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_fmul(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MF);
+ be_parameter src1p(*this, inst.param(1), PTYPE_MF);
+ be_parameter src2p(*this, inst.param(2), PTYPE_MF);
+ normalize_commutative(src1p, src2p);
+
+ // general case
+ emit_fld_p(dst, inst.size(), src1p); // fld src1p
+ emit_fld_p(dst, inst.size(), src2p); // fld src2p
+ emit_fmulp(dst); // fmulp
+ emit_fstp_p(dst, inst.size(), dstp); // fstp dstp
+}
+
+
+//-------------------------------------------------
+// op_fdiv - process a FDIV opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_fdiv(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MF);
+ be_parameter src1p(*this, inst.param(1), PTYPE_MF);
+ be_parameter src2p(*this, inst.param(2), PTYPE_MF);
+
+ // general case
+ emit_fld_p(dst, inst.size(), src1p); // fld src1p
+ emit_fld_p(dst, inst.size(), src2p); // fld src2p
+ emit_fdivp(dst); // fdivp
+ emit_fstp_p(dst, inst.size(), dstp); // fstp dstp
+}
+
+
+//-------------------------------------------------
+// op_fneg - process a FNEG opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_fneg(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MF);
+ be_parameter srcp(*this, inst.param(1), PTYPE_MF);
+
+ // general case
+ emit_fld_p(dst, inst.size(), srcp); // fld srcp
+ emit_fchs(dst); // fchs
+ emit_fstp_p(dst, inst.size(), dstp); // fstp dstp
+}
+
+
+//-------------------------------------------------
+// op_fabs - process a FABS opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_fabs(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MF);
+ be_parameter srcp(*this, inst.param(1), PTYPE_MF);
+
+ // general case
+ emit_fld_p(dst, inst.size(), srcp); // fld srcp
+ emit_fabs(dst); // fabs
+ emit_fstp_p(dst, inst.size(), dstp); // fstp dstp
+}
+
+
+//-------------------------------------------------
+// op_fsqrt - process a FSQRT opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_fsqrt(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MF);
+ be_parameter srcp(*this, inst.param(1), PTYPE_MF);
+
+ // general case
+ emit_fld_p(dst, inst.size(), srcp); // fld srcp
+ emit_fsqrt(dst); // fsqrt
+ emit_fstp_p(dst, inst.size(), dstp); // fstp dstp
+}
+
+
+//-------------------------------------------------
+// op_frecip - process a FRECIP opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_frecip(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MF);
+ be_parameter srcp(*this, inst.param(1), PTYPE_MF);
+
+ // general case
+ emit_fld1(dst); // fld1
+ emit_fld_p(dst, inst.size(), srcp); // fld srcp
+ emit_fdivp(dst); // fdivp
+ emit_fstp_p(dst, inst.size(), dstp); // fstp dstp
+}
+
+
+//-------------------------------------------------
+// op_frsqrt - process a FRSQRT opcode
+//-------------------------------------------------
+
+void drcbe_x86::op_frsqrt(x86code *&dst, const instruction &inst)
+{
+ // validate instruction
+ assert(inst.size() == 4 || inst.size() == 8);
+ assert_no_condition(inst);
+ assert_no_flags(inst);
+
+ // normalize parameters
+ be_parameter dstp(*this, inst.param(0), PTYPE_MF);
+ be_parameter srcp(*this, inst.param(1), PTYPE_MF);
+
+ // general case
+ emit_fld1(dst); // fld1
+ emit_fld_p(dst, inst.size(), srcp); // fld srcp
+ emit_fsqrt(dst); // fsqrt
+ emit_fdivp(dst); // fdivp
+ emit_fstp_p(dst, inst.size(), dstp); // fstp dstp
+}
+
+
+
+//**************************************************************************
+// MISCELLAENOUS FUNCTIONS
+//**************************************************************************
+
+//-------------------------------------------------
+// dmulu - perform a double-wide unsigned multiply
+//-------------------------------------------------
+
+int drcbe_x86::dmulu(UINT64 &dstlo, UINT64 &dsthi, UINT64 src1, UINT64 src2, int flags)
+{
+ // shortcut if we don't care about the high bits or the flags
+ if (&dstlo == &dsthi && flags == 0)
+ {
+ dstlo = src1 * src2;
+ return 0;
+ }
+
+ // fetch source values
+ UINT64 a = src1;
+ UINT64 b = src2;
+ if (a == 0 || b == 0)
+ {
+ dsthi = dstlo = 0;
+ return FLAG_Z;
+ }
+
+ // compute high and low parts first
+ UINT64 lo = (UINT64)(UINT32)(a >> 0) * (UINT64)(UINT32)(b >> 0);
+ UINT64 hi = (UINT64)(UINT32)(a >> 32) * (UINT64)(UINT32)(b >> 32);
+
+ // compute middle parts
+ UINT64 prevlo = lo;
+ UINT64 temp = (UINT64)(UINT32)(a >> 32) * (UINT64)(UINT32)(b >> 0);
+ lo += temp << 32;
+ hi += (temp >> 32) + (lo < prevlo);
+
+ prevlo = lo;
+ temp = (UINT64)(UINT32)(a >> 0) * (UINT64)(UINT32)(b >> 32);
+ lo += temp << 32;
+ hi += (temp >> 32) + (lo < prevlo);
+
+ // store the results
+ dsthi = hi;
+ dstlo = lo;
+ return ((hi >> 60) & FLAG_S) | ((dsthi != 0) << 1);
+}
+
+
+//-------------------------------------------------
+// dmuls - perform a double-wide signed multiply
+//-------------------------------------------------
+
+int drcbe_x86::dmuls(UINT64 &dstlo, UINT64 &dsthi, INT64 src1, INT64 src2, int flags)
+{
+ UINT64 lo, hi, prevlo;
+ UINT64 a, b, temp;
+
+ // shortcut if we don't care about the high bits or the flags
+ if (&dstlo == &dsthi && flags == 0)
+ {
+ dstlo = src1 * src2;
+ return 0;
+ }
+
+ // fetch absolute source values
+ a = src1; if ((INT64)a < 0) a = -a;
+ b = src2; if ((INT64)b < 0) b = -b;
+ if (a == 0 || b == 0)
+ {
+ dsthi = dstlo = 0;
+ return FLAG_Z;
+ }
+
+ // compute high and low parts first
+ lo = (UINT64)(UINT32)(a >> 0) * (UINT64)(UINT32)(b >> 0);
+ hi = (UINT64)(UINT32)(a >> 32) * (UINT64)(UINT32)(b >> 32);
+
+ // compute middle parts
+ prevlo = lo;
+ temp = (UINT64)(UINT32)(a >> 32) * (UINT64)(UINT32)(b >> 0);
+ lo += temp << 32;
+ hi += (temp >> 32) + (lo < prevlo);
+
+ prevlo = lo;
+ temp = (UINT64)(UINT32)(a >> 0) * (UINT64)(UINT32)(b >> 32);
+ lo += temp << 32;
+ hi += (temp >> 32) + (lo < prevlo);
+
+ // adjust for signage
+ if ((INT64)(src1 ^ src2) < 0)
+ {
+ hi = ~hi + (lo == 0);
+ lo = ~lo + 1;
+ }
+
+ // store the results
+ dsthi = hi;
+ dstlo = lo;
+ return ((hi >> 60) & FLAG_S) | ((dsthi != ((INT64)lo >> 63)) << 1);
+}
+
+
+//-------------------------------------------------
+// ddivu - perform a double-wide unsigned divide
+//-------------------------------------------------
+
+int drcbe_x86::ddivu(UINT64 &dstlo, UINT64 &dsthi, UINT64 src1, UINT64 src2)
+{
+ // do nothing if src2 == 0
+ if (src2 == 0)
+ return FLAG_V;
+
+ // shortcut if no remainder
+ dstlo = src1 / src2;
+ if (dstlo != dsthi)
+ dsthi = src1 % src2;
+ return ((dstlo == 0) << 2) | ((dstlo >> 60) & FLAG_S);
+}
+
+
+//-------------------------------------------------
+// ddivs - perform a double-wide signed divide
+//-------------------------------------------------
+
+int drcbe_x86::ddivs(UINT64 &dstlo, UINT64 &dsthi, INT64 src1, INT64 src2)
+{
+ // do nothing if src2 == 0
+ if (src2 == 0)
+ return FLAG_V;
+
+ // shortcut if no remainder
+ dstlo = src1 / src2;
+ if (dstlo != dsthi)
+ dsthi = src1 % src2;
+ return ((dstlo == 0) << 2) | ((dstlo >> 60) & FLAG_S);
+}
diff --git a/trunk/src/emu/cpu/drcbex86.h b/trunk/src/emu/cpu/drcbex86.h
new file mode 100644
index 00000000000..cd7359c3d25
--- /dev/null
+++ b/trunk/src/emu/cpu/drcbex86.h
@@ -0,0 +1,374 @@
+/***************************************************************************
+
+ drcbex86.h
+
+ 32-bit x86 back-end for the universal machine language.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __DRCBEX86_H__
+#define __DRCBEX86_H__
+
+#include "drcuml.h"
+#include "drcbeut.h"
+#include "x86log.h"
+
+#define X86EMIT_SIZE 32
+#include "x86emit.h"
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class drcbe_x86 : public drcbe_interface
+{
+ typedef UINT32 (*x86_entry_point_func)(x86code *entry);
+
+public:
+ // construction/destruction
+ drcbe_x86(drcuml_state &drcuml, device_t &device, drc_cache &cache, UINT32 flags, int modes, int addrbits, int ignorebits);
+ virtual ~drcbe_x86();
+
+ // required overrides
+ virtual void reset();
+ virtual int execute(uml::code_handle &entry);
+ virtual void generate(drcuml_block &block, const uml::instruction *instlist, UINT32 numinst);
+ virtual bool hash_exists(UINT32 mode, UINT32 pc);
+ virtual void get_info(drcbe_info &info);
+
+private:
+ // a be_parameter is similar to a uml::parameter but maps to native registers/memory
+ class be_parameter
+ {
+ public:
+ // parameter types
+ enum be_parameter_type
+ {
+ PTYPE_NONE = 0, // invalid
+ PTYPE_IMMEDIATE, // immediate; value = sign-extended to 64 bits
+ PTYPE_INT_REGISTER, // integer register; value = 0-REG_MAX
+ PTYPE_FLOAT_REGISTER, // floating point register; value = 0-REG_MAX
+ PTYPE_VECTOR_REGISTER, // vector register; value = 0-REG_MAX
+ PTYPE_MEMORY, // memory; value = pointer to memory
+ PTYPE_MAX
+ };
+
+ // represents the value of a parameter
+ typedef UINT64 be_parameter_value;
+
+ // construction
+ be_parameter() : m_type(PTYPE_NONE), m_value(0) { }
+ be_parameter(const be_parameter &param) : m_type(param.m_type), m_value(param.m_value) { }
+ be_parameter(UINT64 val) : m_type(PTYPE_IMMEDIATE), m_value(val) { }
+ be_parameter(drcbe_x86 &drcbe, const uml::parameter &param, UINT32 allowed);
+
+ // creators for types that don't safely default
+ static inline be_parameter make_ireg(int regnum) { assert(regnum >= 0 && regnum < x86emit::REG_MAX); return be_parameter(PTYPE_INT_REGISTER, regnum); }
+ static inline be_parameter make_freg(int regnum) { assert(regnum >= 0 && regnum < x86emit::REG_MAX); return be_parameter(PTYPE_FLOAT_REGISTER, regnum); }
+ static inline be_parameter make_vreg(int regnum) { assert(regnum >= 0 && regnum < x86emit::REG_MAX); return be_parameter(PTYPE_VECTOR_REGISTER, regnum); }
+ static inline be_parameter make_memory(void *base) { return be_parameter(PTYPE_MEMORY, reinterpret_cast<be_parameter_value>(base)); }
+ static inline be_parameter make_memory(const void *base) { return be_parameter(PTYPE_MEMORY, reinterpret_cast<be_parameter_value>(const_cast<void *>(base))); }
+
+ // operators
+ bool operator==(const be_parameter &rhs) const { return (m_type == rhs.m_type && m_value == rhs.m_value); }
+ bool operator!=(const be_parameter &rhs) const { return (m_type != rhs.m_type || m_value != rhs.m_value); }
+
+ // getters
+ be_parameter_type type() const { return m_type; }
+ UINT64 immediate() const { assert(m_type == PTYPE_IMMEDIATE); return m_value; }
+ int ireg() const { assert(m_type == PTYPE_INT_REGISTER); assert(m_value >= 0 && m_value < x86emit::REG_MAX); return m_value; }
+ int freg() const { assert(m_type == PTYPE_FLOAT_REGISTER); assert(m_value >= 0 && m_value < x86emit::REG_MAX); return m_value; }
+ int vreg() const { assert(m_type == PTYPE_VECTOR_REGISTER); assert(m_value >= 0 && m_value < x86emit::REG_MAX); return m_value; }
+ void *memory(UINT32 offset = 0) const { assert(m_type == PTYPE_MEMORY); return reinterpret_cast<void *>(m_value + offset); }
+
+ // type queries
+ bool is_immediate() const { return (m_type == PTYPE_IMMEDIATE); }
+ bool is_int_register() const { return (m_type == PTYPE_INT_REGISTER); }
+ bool is_float_register() const { return (m_type == PTYPE_FLOAT_REGISTER); }
+ bool is_vector_register() const { return (m_type == PTYPE_VECTOR_REGISTER); }
+ bool is_memory() const { return (m_type == PTYPE_MEMORY); }
+
+ // other queries
+ bool is_immediate_value(UINT64 value) const { return (m_type == PTYPE_IMMEDIATE && m_value == value); }
+
+ // helpers
+ int select_register(int defreg) const;
+ int select_register(int defreg, const be_parameter &checkparam) const;
+ int select_register(int defreg, const be_parameter &checkparam, const be_parameter &checkparam2) const;
+
+ private:
+ // private constructor
+ be_parameter(be_parameter_type type, be_parameter_value value) : m_type(type), m_value(value) { }
+
+ // internals
+ be_parameter_type m_type; // parameter type
+ be_parameter_value m_value; // parameter value
+ };
+
+ // helpers
+ void normalize_commutative(be_parameter &inner, be_parameter &outer);
+ void emit_combine_z_flags(x86code *&dst);
+ void emit_combine_z_shl_flags(x86code *&dst);
+ void reset_last_upper_lower_reg();
+ void set_last_lower_reg(x86code *&dst, const be_parameter &param, UINT8 reglo);
+ void set_last_upper_reg(x86code *&dst, const be_parameter &param, UINT8 reghi);
+ bool can_skip_lower_load(x86code *&dst, UINT32 *memref, UINT8 reglo);
+ bool can_skip_upper_load(x86code *&dst, UINT32 *memref, UINT8 reghi);
+ void track_resolve_link(x86code *&destptr, const emit_link &linkinfo);
+
+ void fixup_label(void *parameter, drccodeptr labelcodeptr);
+ void fixup_exception(drccodeptr *codeptr, void *param1, void *param2);
+
+ static void debug_log_hashjmp(int mode, offs_t pc);
+ static void debug_log_hashjmp_fail();
+
+ // code generators
+ void op_handle(x86code *&dst, const uml::instruction &inst);
+ void op_hash(x86code *&dst, const uml::instruction &inst);
+ void op_label(x86code *&dst, const uml::instruction &inst);
+ void op_comment(x86code *&dst, const uml::instruction &inst);
+ void op_mapvar(x86code *&dst, const uml::instruction &inst);
+
+ void op_nop(x86code *&dst, const uml::instruction &inst);
+ void op_debug(x86code *&dst, const uml::instruction &inst);
+ void op_exit(x86code *&dst, const uml::instruction &inst);
+ void op_hashjmp(x86code *&dst, const uml::instruction &inst);
+ void op_jmp(x86code *&dst, const uml::instruction &inst);
+ void op_exh(x86code *&dst, const uml::instruction &inst);
+ void op_callh(x86code *&dst, const uml::instruction &inst);
+ void op_ret(x86code *&dst, const uml::instruction &inst);
+ void op_callc(x86code *&dst, const uml::instruction &inst);
+ void op_recover(x86code *&dst, const uml::instruction &inst);
+
+ void op_setfmod(x86code *&dst, const uml::instruction &inst);
+ void op_getfmod(x86code *&dst, const uml::instruction &inst);
+ void op_getexp(x86code *&dst, const uml::instruction &inst);
+ void op_getflgs(x86code *&dst, const uml::instruction &inst);
+ void op_save(x86code *&dst, const uml::instruction &inst);
+ void op_restore(x86code *&dst, const uml::instruction &inst);
+
+ void op_load(x86code *&dst, const uml::instruction &inst);
+ void op_loads(x86code *&dst, const uml::instruction &inst);
+ void op_store(x86code *&dst, const uml::instruction &inst);
+ void op_read(x86code *&dst, const uml::instruction &inst);
+ void op_readm(x86code *&dst, const uml::instruction &inst);
+ void op_write(x86code *&dst, const uml::instruction &inst);
+ void op_writem(x86code *&dst, const uml::instruction &inst);
+ void op_carry(x86code *&dst, const uml::instruction &inst);
+ void op_set(x86code *&dst, const uml::instruction &inst);
+ void op_mov(x86code *&dst, const uml::instruction &inst);
+ void op_sext(x86code *&dst, const uml::instruction &inst);
+ void op_roland(x86code *&dst, const uml::instruction &inst);
+ void op_rolins(x86code *&dst, const uml::instruction &inst);
+ void op_add(x86code *&dst, const uml::instruction &inst);
+ void op_addc(x86code *&dst, const uml::instruction &inst);
+ void op_sub(x86code *&dst, const uml::instruction &inst);
+ void op_subc(x86code *&dst, const uml::instruction &inst);
+ void op_cmp(x86code *&dst, const uml::instruction &inst);
+ void op_mulu(x86code *&dst, const uml::instruction &inst);
+ void op_muls(x86code *&dst, const uml::instruction &inst);
+ void op_divu(x86code *&dst, const uml::instruction &inst);
+ void op_divs(x86code *&dst, const uml::instruction &inst);
+ void op_and(x86code *&dst, const uml::instruction &inst);
+ void op_test(x86code *&dst, const uml::instruction &inst);
+ void op_or(x86code *&dst, const uml::instruction &inst);
+ void op_xor(x86code *&dst, const uml::instruction &inst);
+ void op_lzcnt(x86code *&dst, const uml::instruction &inst);
+ void op_bswap(x86code *&dst, const uml::instruction &inst);
+ void op_shl(x86code *&dst, const uml::instruction &inst);
+ void op_shr(x86code *&dst, const uml::instruction &inst);
+ void op_sar(x86code *&dst, const uml::instruction &inst);
+ void op_ror(x86code *&dst, const uml::instruction &inst);
+ void op_rol(x86code *&dst, const uml::instruction &inst);
+ void op_rorc(x86code *&dst, const uml::instruction &inst);
+ void op_rolc(x86code *&dst, const uml::instruction &inst);
+
+ void op_fload(x86code *&dst, const uml::instruction &inst);
+ void op_fstore(x86code *&dst, const uml::instruction &inst);
+ void op_fread(x86code *&dst, const uml::instruction &inst);
+ void op_fwrite(x86code *&dst, const uml::instruction &inst);
+ void op_fmov(x86code *&dst, const uml::instruction &inst);
+ void op_ftoint(x86code *&dst, const uml::instruction &inst);
+ void op_ffrint(x86code *&dst, const uml::instruction &inst);
+ void op_ffrflt(x86code *&dst, const uml::instruction &inst);
+ void op_frnds(x86code *&dst, const uml::instruction &inst);
+ void op_fadd(x86code *&dst, const uml::instruction &inst);
+ void op_fsub(x86code *&dst, const uml::instruction &inst);
+ void op_fcmp(x86code *&dst, const uml::instruction &inst);
+ void op_fmul(x86code *&dst, const uml::instruction &inst);
+ void op_fdiv(x86code *&dst, const uml::instruction &inst);
+ void op_fneg(x86code *&dst, const uml::instruction &inst);
+ void op_fabs(x86code *&dst, const uml::instruction &inst);
+ void op_fsqrt(x86code *&dst, const uml::instruction &inst);
+ void op_frecip(x86code *&dst, const uml::instruction &inst);
+ void op_frsqrt(x86code *&dst, const uml::instruction &inst);
+
+ // 32-bit code emission helpers
+ void emit_mov_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param);
+ void emit_mov_r32_p32_keepflags(x86code *&dst, UINT8 reg, const be_parameter &param);
+ void emit_mov_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param);
+ void emit_mov_p32_r32(x86code *&dst, const be_parameter &param, UINT8 reg);
+ void emit_add_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_add_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_adc_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_adc_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_sub_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_sub_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_sbb_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_sbb_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_cmp_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_cmp_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_and_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_and_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_test_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_test_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_or_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_or_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_xor_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_xor_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_shl_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_shl_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_shr_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_shr_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_sar_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_sar_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_rol_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_rol_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_ror_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_ror_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_rcl_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_rcl_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_rcr_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param, const uml::instruction &inst);
+ void emit_rcr_m32_p32(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+
+ // 64-bit code emission helpers
+ void emit_mov_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param);
+ void emit_mov_r64_p64_keepflags(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param);
+ void emit_mov_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param);
+ void emit_mov_p64_r64(x86code *&dst, const be_parameter &param, UINT8 reglo, UINT8 reghi);
+ void emit_add_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const uml::instruction &inst);
+ void emit_add_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_adc_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const uml::instruction &inst);
+ void emit_adc_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_sub_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const uml::instruction &inst);
+ void emit_sub_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_sbb_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const uml::instruction &inst);
+ void emit_sbb_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_cmp_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const uml::instruction &inst);
+ void emit_cmp_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_and_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const uml::instruction &inst);
+ void emit_and_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_test_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const uml::instruction &inst);
+ void emit_test_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_or_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const uml::instruction &inst);
+ void emit_or_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_xor_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const uml::instruction &inst);
+ void emit_xor_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_shl_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const uml::instruction &inst);
+ void emit_shl_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_shr_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const uml::instruction &inst);
+ void emit_shr_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_sar_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const uml::instruction &inst);
+ void emit_sar_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_rol_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const uml::instruction &inst);
+ void emit_rol_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_ror_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const uml::instruction &inst);
+ void emit_ror_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_rcl_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const uml::instruction &inst);
+ void emit_rcl_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+ void emit_rcr_r64_p64(x86code *&dst, UINT8 reglo, UINT8 reghi, const be_parameter &param, const uml::instruction &inst);
+ void emit_rcr_m64_p64(x86code *&dst, x86_memref memref, const be_parameter &param, const uml::instruction &inst);
+
+ // floating-point code emission helpers
+ void emit_fld_p(x86code *&dst, int size, const be_parameter &param);
+ void emit_fstp_p(x86code *&dst, int size, const be_parameter &param);
+
+ // callback helpers
+ static int dmulu(UINT64 &dstlo, UINT64 &dsthi, UINT64 src1, UINT64 src2, int flags);
+ static int dmuls(UINT64 &dstlo, UINT64 &dsthi, INT64 src1, INT64 src2, int flags);
+ static int ddivu(UINT64 &dstlo, UINT64 &dsthi, UINT64 src1, UINT64 src2);
+ static int ddivs(UINT64 &dstlo, UINT64 &dsthi, INT64 src1, INT64 src2);
+
+ // internal state
+ drc_hash_table m_hash; // hash table state
+ drc_map_variables m_map; // code map
+ drc_label_list m_labels; // label list
+ x86log_context * m_log; // logging
+ bool m_logged_common; // logged common code already?
+ bool m_sse3; // do we have SSE3 support?
+
+ x86_entry_point_func m_entry; // entry point
+ x86code * m_exit; // exit point
+ x86code * m_nocode; // nocode handler
+ x86code * m_save; // save handler
+ x86code * m_restore; // restore handler
+
+ UINT32 * m_reglo[x86emit::REG_MAX];// pointer to low part of data for each register
+ UINT32 * m_reghi[x86emit::REG_MAX];// pointer to high part of data for each register
+ UINT8 m_last_lower_reg; // last register we stored a lower from
+ x86code * m_last_lower_pc; // PC after instruction where we last stored a lower register
+ UINT32 * m_last_lower_addr; // address where we last stored an lower register
+ UINT8 m_last_upper_reg; // last register we stored an upper from
+ x86code * m_last_upper_pc; // PC after instruction where we last stored an upper register
+ UINT32 * m_last_upper_addr; // address where we last stored an upper register
+ double m_fptemp; // temporary storage for floating point
+
+ UINT16 m_fpumode; // saved FPU mode
+ UINT16 m_fmodesave; // temporary location for saving
+
+ void * m_stacksave; // saved stack pointer
+ void * m_hashstacksave; // saved stack pointer for hashjmp
+ UINT64 m_reslo; // extended low result
+ UINT64 m_reshi; // extended high result
+
+ drc_label_fixup_delegate m_fixup_label; // precomputed delegate for fixups
+ drc_oob_delegate m_fixup_exception; // precomputed delegate for exception fixups
+
+ // globals
+ typedef void (drcbe_x86::*opcode_generate_func)(x86code *&dst, const uml::instruction &inst);
+ struct opcode_table_entry
+ {
+ uml::opcode_t opcode; // opcode in question
+ opcode_generate_func func; // function pointer to the work
+ };
+ static const opcode_table_entry s_opcode_table_source[];
+ static opcode_generate_func s_opcode_table[uml::OP_MAX];
+};
+
+
+#endif /* __DRCBEC_H__ */
diff --git a/trunk/src/emu/cpu/drccache.c b/trunk/src/emu/cpu/drccache.c
new file mode 100644
index 00000000000..b9922c3dc7b
--- /dev/null
+++ b/trunk/src/emu/cpu/drccache.c
@@ -0,0 +1,281 @@
+/***************************************************************************
+
+ drccache.c
+
+ Universal dynamic recompiler cache management.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "drccache.h"
+
+
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+// ensure that all memory allocated is aligned to an 8-byte boundary
+#define ALIGN_PTR_UP(p) ((void *)(((FPTR)(p) + (CACHE_ALIGNMENT - 1)) & ~(CACHE_ALIGNMENT - 1)))
+#define ALIGN_PTR_DOWN(p) ((void *)((FPTR)(p) & ~(CACHE_ALIGNMENT - 1)))
+
+
+
+//**************************************************************************
+// DRC CACHE
+//**************************************************************************
+
+//-------------------------------------------------
+// drc_cache - constructor
+//-------------------------------------------------
+
+drc_cache::drc_cache(size_t bytes)
+ : m_near((drccodeptr)osd_alloc_executable(bytes)),
+ m_neartop(m_near),
+ m_base(m_near + NEAR_CACHE_SIZE),
+ m_top(m_base),
+ m_end(m_near + bytes),
+ m_codegen(0),
+ m_size(bytes)
+{
+ memset(m_free, 0, sizeof(m_free));
+ memset(m_nearfree, 0, sizeof(m_nearfree));
+}
+
+
+//-------------------------------------------------
+// ~drc_cache - destructor
+//-------------------------------------------------
+
+drc_cache::~drc_cache()
+{
+ // release the memory
+ osd_free_executable(m_near, m_size);
+}
+
+
+
+//-------------------------------------------------
+// flush - flush the cache contents
+//-------------------------------------------------
+
+void drc_cache::flush()
+{
+ // can't flush in the middle of codegen
+ assert(m_codegen == NULL);
+
+ // just reset the top back to the base and re-seed
+ m_top = m_base;
+}
+
+
+//-------------------------------------------------
+// alloc - allocate permanent memory from the
+// cache
+//-------------------------------------------------
+
+void *drc_cache::alloc(size_t bytes)
+{
+ assert(bytes > 0);
+
+ // pick first from the free list
+ if (bytes < MAX_PERMANENT_ALLOC)
+ {
+ free_link **linkptr = &m_free[(bytes + CACHE_ALIGNMENT - 1) / CACHE_ALIGNMENT];
+ free_link *link = *linkptr;
+ if (link != NULL)
+ {
+ *linkptr = link->m_next;
+ return link;
+ }
+ }
+
+ // if no space, we just fail
+ drccodeptr ptr = (drccodeptr)ALIGN_PTR_DOWN(m_end - bytes);
+ if (m_top > ptr)
+ return NULL;
+
+ // otherwise update the end of the cache
+ m_end = ptr;
+ return ptr;
+}
+
+
+//-------------------------------------------------
+// alloc_near - allocate permanent memory from
+// the near part of the cache
+//-------------------------------------------------
+
+void *drc_cache::alloc_near(size_t bytes)
+{
+ assert(bytes > 0);
+
+ // pick first from the free list
+ if (bytes < MAX_PERMANENT_ALLOC)
+ {
+ free_link **linkptr = &m_nearfree[(bytes + CACHE_ALIGNMENT - 1) / CACHE_ALIGNMENT];
+ free_link *link = *linkptr;
+ if (link != NULL)
+ {
+ *linkptr = link->m_next;
+ return link;
+ }
+ }
+
+ // if no space, we just fail
+ drccodeptr ptr = (drccodeptr)ALIGN_PTR_UP(m_neartop);
+ if (ptr + bytes > m_base)
+ return NULL;
+
+ // otherwise update the top of the near part of the cache
+ m_neartop = ptr + bytes;
+ return ptr;
+}
+
+
+//-------------------------------------------------
+// alloc_temporary - allocate temporary memory
+// from the cache
+//-------------------------------------------------
+
+void *drc_cache::alloc_temporary(size_t bytes)
+{
+ // can't allocate in the middle of codegen
+ assert(m_codegen == NULL);
+
+ // if no space, we just fail
+ drccodeptr ptr = m_top;
+ if (ptr + bytes >= m_end)
+ return NULL;
+
+ // otherwise, update the cache top
+ m_top = (drccodeptr)ALIGN_PTR_UP(ptr + bytes);
+ return ptr;
+}
+
+
+//-------------------------------------------------
+// free - release permanent memory allocated from
+// the cache
+//-------------------------------------------------
+
+void drc_cache::dealloc(void *memory, size_t bytes)
+{
+ assert(bytes < MAX_PERMANENT_ALLOC);
+ assert(((drccodeptr)memory >= m_near && (drccodeptr)memory < m_base) || ((drccodeptr)memory >= m_end && (drccodeptr)memory < m_near + m_size));
+
+ // determine which free list to add to
+ free_link **linkptr;
+ if ((drccodeptr)memory < m_base)
+ linkptr = &m_nearfree[(bytes + CACHE_ALIGNMENT - 1) / CACHE_ALIGNMENT];
+ else
+ linkptr = &m_free[(bytes + CACHE_ALIGNMENT - 1) / CACHE_ALIGNMENT];
+
+ // link is into the free list for our size
+ free_link *link = (free_link *)memory;
+ link->m_next = *linkptr;
+ *linkptr = link;
+}
+
+
+//-------------------------------------------------
+// begin_codegen - begin code generation
+//-------------------------------------------------
+
+drccodeptr *drc_cache::begin_codegen(UINT32 reserve_bytes)
+{
+ // can't restart in the middle of codegen
+ assert(m_codegen == NULL);
+ assert(m_ooblist.first() == NULL);
+
+ // if still no space, we just fail
+ drccodeptr ptr = m_top;
+ if (ptr + reserve_bytes >= m_end)
+ return NULL;
+
+ // otherwise, return a pointer to the cache top
+ m_codegen = m_top;
+ return &m_top;
+}
+
+
+//-------------------------------------------------
+// end_codegen - complete code generation
+//-------------------------------------------------
+
+drccodeptr drc_cache::end_codegen()
+{
+ drccodeptr result = m_codegen;
+
+ // run the OOB handlers
+ oob_handler *oob;
+ while ((oob = m_ooblist.detach_head()) != NULL)
+ {
+ // call the callback
+ oob->m_callback(&m_top, oob->m_param1, oob->m_param2);
+ assert(m_top - m_codegen < CODEGEN_MAX_BYTES);
+
+ // release our memory
+ dealloc(oob, sizeof(*oob));
+ }
+
+ // update the cache top
+ m_top = (drccodeptr)ALIGN_PTR_UP(m_top);
+ m_codegen = NULL;
+
+ return result;
+}
+
+
+//-------------------------------------------------
+// request_oob_codegen - request callback for
+// out-of-band codegen
+//-------------------------------------------------
+
+void drc_cache::request_oob_codegen(drc_oob_delegate callback, void *param1, void *param2)
+{
+ assert(m_codegen != NULL);
+
+ // pull an item from the free list
+ oob_handler *oob = (oob_handler *)alloc(sizeof(*oob));
+ assert(oob != NULL);
+
+ // fill it in
+ oob->m_callback = callback;
+ oob->m_param1 = param1;
+ oob->m_param2 = param2;
+
+ // add to the tail
+ m_ooblist.append(*oob);
+}
diff --git a/trunk/src/emu/cpu/drccache.h b/trunk/src/emu/cpu/drccache.h
new file mode 100644
index 00000000000..ae90ca0aea1
--- /dev/null
+++ b/trunk/src/emu/cpu/drccache.h
@@ -0,0 +1,143 @@
+/***************************************************************************
+
+ drccache.h
+
+ Universal dynamic recompiler cache management.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __DRCCACHE_H__
+#define __DRCCACHE_H__
+
+
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+// ensure that a given pointer is within the cache boundaries
+#define assert_in_cache(c,p) assert((c).contains_pointer(p))
+#define assert_in_near_cache(c,p) assert((c).contains_near_pointer(p))
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// generic code pointer
+typedef UINT8 *drccodeptr;
+
+
+// helper template for oob codegen
+typedef delegate<void (drccodeptr *, void *, void *)> drc_oob_delegate;
+
+
+// drc_cache
+class drc_cache
+{
+public:
+ // construction/destruction
+ drc_cache(size_t bytes);
+ ~drc_cache();
+
+ // getters
+ drccodeptr near() const { return m_near; }
+ drccodeptr base() const { return m_base; }
+ drccodeptr top() const { return m_top; }
+
+ // pointer checking
+ bool contains_pointer(const void *ptr) const { return ((const drccodeptr)ptr >= m_near && (const drccodeptr)ptr < m_near + m_size); }
+ bool contains_near_pointer(const void *ptr) const { return ((const drccodeptr)ptr >= m_near && (const drccodeptr)ptr < m_neartop); }
+ bool generating_code() const { return (m_codegen != NULL); }
+
+ // memory management
+ void flush();
+ void *alloc(size_t bytes);
+ void *alloc_near(size_t bytes);
+ void *alloc_temporary(size_t bytes);
+ void dealloc(void *memory, size_t bytes);
+
+ // codegen helpers
+ drccodeptr *begin_codegen(UINT32 reserve_bytes);
+ drccodeptr end_codegen();
+ void request_oob_codegen(drc_oob_delegate callback, void *param1 = NULL, void *param2 = NULL);
+
+private:
+ // largest block of code that can be generated at once
+ static const size_t CODEGEN_MAX_BYTES = 65536;
+
+ // minimum alignment, in bytes (must be power of 2)
+ static const size_t CACHE_ALIGNMENT = 8;
+
+ // largest permanent allocation we allow
+ static const size_t MAX_PERMANENT_ALLOC = 1024;
+
+ // size of "near" area at the base of the cache
+ static const size_t NEAR_CACHE_SIZE = 65536;
+
+ // core parameters
+ drccodeptr m_near; // pointer to the near part of the cache
+ drccodeptr m_neartop; // top of the near part of the cache
+ drccodeptr m_base; // base pointer to the compiler cache
+ drccodeptr m_top; // current top of cache
+ drccodeptr m_end; // end of cache memory
+ drccodeptr m_codegen; // start of generated code
+ size_t m_size; // size of the cache in bytes
+
+ // oob management
+ struct oob_handler
+ {
+ oob_handler *next() const { return m_next; }
+
+ oob_handler * m_next; // next handler
+ drc_oob_delegate m_callback; // callback function
+ void * m_param1; // 1st pointer parameter
+ void * m_param2; // 2nd pointer parameter
+ };
+ simple_list<oob_handler> m_ooblist; // list of oob handlers
+
+ // free lists
+ struct free_link
+ {
+ free_link * m_next; // pointer to the next guy
+ };
+ free_link * m_free[MAX_PERMANENT_ALLOC / CACHE_ALIGNMENT];
+ free_link * m_nearfree[MAX_PERMANENT_ALLOC / CACHE_ALIGNMENT];
+};
+
+
+#endif /* __DRCCACHE_H__ */
diff --git a/trunk/src/emu/cpu/drcfe.c b/trunk/src/emu/cpu/drcfe.c
new file mode 100644
index 00000000000..03000e151a9
--- /dev/null
+++ b/trunk/src/emu/cpu/drcfe.c
@@ -0,0 +1,401 @@
+/***************************************************************************
+
+ drcfe.c
+
+ Generic dynamic recompiler frontend structures and utilities.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+****************************************************************************
+
+ Future improvements/changes:
+
+ * more aggressive handling of needed registers for conditional
+ intrablock branches
+
+***************************************************************************/
+
+#include "emu.h"
+#include "drcfe.h"
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+const UINT32 MAX_STACK_DEPTH = 100;
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// an entry that maps branches for our code walking
+struct pc_stack_entry
+{
+ offs_t targetpc;
+ offs_t srcpc;
+};
+
+
+
+//**************************************************************************
+// DRC FRONTEND
+//**************************************************************************
+
+//-------------------------------------------------
+// drc_frontend - constructor
+//-------------------------------------------------
+
+drc_frontend::drc_frontend(device_t &cpu, UINT32 window_start, UINT32 window_end, UINT32 max_sequence)
+ : m_window_start(window_start),
+ m_window_end(window_end),
+ m_max_sequence(max_sequence),
+ m_cpudevice(downcast<cpu_device &>(cpu)),
+ m_program(m_cpudevice.space(AS_PROGRAM)),
+ m_pageshift(m_cpudevice.space_config(AS_PROGRAM)->m_page_shift),
+ m_desc_live_list(cpu.machine().respool()),
+ m_desc_allocator(cpu.machine().respool()),
+ m_desc_array(auto_alloc_array_clear(cpu.machine(), opcode_desc *, window_end + window_start + 2))
+{
+}
+
+
+//-------------------------------------------------
+// ~drc_frontend - destructor
+//-------------------------------------------------
+
+drc_frontend::~drc_frontend()
+{
+ // release any descriptions we've accumulated
+ release_descriptions();
+
+ // free the description array
+ auto_free(m_cpudevice.machine(), m_desc_array);
+}
+
+
+//-------------------------------------------------
+// describe_code - describe a sequence of code
+// that falls within the configured window
+// relative to the specified startpc
+//-------------------------------------------------
+
+const opcode_desc *drc_frontend::describe_code(offs_t startpc)
+{
+ // release any descriptions we've accumulated
+ release_descriptions();
+
+ // add the initial PC to the stack
+ pc_stack_entry pcstack[MAX_STACK_DEPTH];
+ pc_stack_entry *pcstackptr = &pcstack[0];
+ pcstackptr->srcpc = 0;
+ pcstackptr->targetpc = startpc;
+ pcstackptr++;
+
+ // loop while we still have a stack
+ offs_t minpc = startpc - MIN(m_window_start, startpc);
+ offs_t maxpc = startpc + MIN(m_window_end, 0xffffffff - startpc);
+ while (pcstackptr != &pcstack[0])
+ {
+ // if we've already hit this PC, just mark it a branch target and continue
+ pc_stack_entry *curstack = --pcstackptr;
+ opcode_desc *curdesc = m_desc_array[curstack->targetpc - minpc];
+ if (curdesc != NULL)
+ {
+ curdesc->flags |= OPFLAG_IS_BRANCH_TARGET;
+
+ // if the branch crosses a page boundary, mark the target as needing to revalidate
+ if (m_pageshift != 0 && ((curstack->srcpc ^ curdesc->pc) >> m_pageshift) != 0)
+ curdesc->flags |= OPFLAG_VALIDATE_TLB | OPFLAG_CAN_CAUSE_EXCEPTION;
+
+ // continue processing
+ continue;
+ }
+
+ // loop until we exit the block
+ for (offs_t curpc = curstack->targetpc; curpc >= minpc && curpc < maxpc && m_desc_array[curpc - minpc] == NULL; curpc += m_desc_array[curpc - minpc]->length)
+ {
+ // allocate a new description and describe this instruction
+ m_desc_array[curpc - minpc] = curdesc = describe_one(curpc, curdesc);
+
+ // first instruction in a sequence is always a branch target
+ if (curpc == curstack->targetpc)
+ curdesc->flags |= OPFLAG_IS_BRANCH_TARGET;
+
+ // stop if we hit a page fault
+ if (curdesc->flags & OPFLAG_COMPILER_PAGE_FAULT)
+ break;
+
+ // if we are the first instruction in the whole window, we must validate the TLB
+ if (curpc == startpc && m_pageshift != 0)
+ curdesc->flags |= OPFLAG_VALIDATE_TLB | OPFLAG_CAN_CAUSE_EXCEPTION;
+
+ // if we are a branch within the block range, add the branch target to our stack
+ if ((curdesc->flags & OPFLAG_IS_BRANCH) && curdesc->targetpc >= minpc && curdesc->targetpc < maxpc && pcstackptr < &pcstack[MAX_STACK_DEPTH])
+ {
+ curdesc->flags |= OPFLAG_INTRABLOCK_BRANCH;
+ pcstackptr->srcpc = curdesc->pc;
+ pcstackptr->targetpc = curdesc->targetpc;
+ pcstackptr++;
+ }
+
+ // if we're done, we're done
+ if (curdesc->flags & OPFLAG_END_SEQUENCE)
+ break;
+ }
+ }
+
+ // now build the list of descriptions in order
+ // first from startpc -> maxpc, then from minpc -> startpc
+ build_sequence(startpc - minpc, maxpc - minpc, OPFLAG_REDISPATCH);
+ build_sequence(minpc - minpc, startpc - minpc, OPFLAG_RETURN_TO_START);
+ return m_desc_live_list.first();
+}
+
+
+//-------------------------------------------------
+// describe_one - describe a single instruction,
+// recursively describing opcodes in delay
+// slots of branches as well
+//-------------------------------------------------
+
+opcode_desc *drc_frontend::describe_one(offs_t curpc, const opcode_desc *prevdesc)
+{
+ // initialize the description
+ opcode_desc *desc = m_desc_allocator.alloc();
+ memset(desc, 0, sizeof(*desc));
+ desc->pc = curpc;
+ desc->physpc = curpc;
+ desc->targetpc = BRANCH_TARGET_DYNAMIC;
+
+ // call the callback to describe an instruction
+ if (!describe(*desc, prevdesc))
+ {
+ desc->flags |= OPFLAG_WILL_CAUSE_EXCEPTION | OPFLAG_INVALID_OPCODE;
+ return desc;
+ }
+
+ // validate the TLB if we are exactly at the start of a page, or if we cross a page boundary
+ if (m_pageshift != 0 && (((curpc - 1) ^ (curpc + desc->length - 1)) >> m_pageshift) != 0)
+ desc->flags |= OPFLAG_VALIDATE_TLB | OPFLAG_CAN_CAUSE_EXCEPTION;
+
+ // validate stuff
+ assert(desc->length > 0 || (desc->flags & OPFLAG_VIRTUAL_NOOP) != 0);
+
+ // if we are a branch with delay slots, recursively walk those
+ if (desc->flags & OPFLAG_IS_BRANCH)
+ {
+ // iterate over slots and describe them
+ offs_t delaypc = curpc + desc->length;
+ opcode_desc *prev = desc;
+ for (UINT8 slotnum = 0; slotnum < desc->delayslots; slotnum++)
+ {
+ // recursively describe the next instruction
+ opcode_desc *delaydesc = describe_one(delaypc, prev);
+ if (delaydesc == NULL)
+ break;
+ desc->delay.append(*delaydesc);
+ prev = desc;
+
+ // set the delay slot flag and a pointer back to the original branch
+ delaydesc->flags |= OPFLAG_IN_DELAY_SLOT;
+ delaydesc->branch = desc;
+
+ // stop if we hit a page fault
+ if (delaydesc->flags & OPFLAG_COMPILER_PAGE_FAULT)
+ break;
+
+ // otherwise, advance
+ delaypc += delaydesc->length;
+ }
+ }
+ return desc;
+}
+
+
+//-------------------------------------------------
+// build_sequence - build an ordered sequence
+// of instructions
+//-------------------------------------------------
+
+void drc_frontend::build_sequence(int start, int end, UINT32 endflag)
+{
+ // iterate in order from start to end, picking up all non-NULL instructions
+ int consecutive = 0;
+ int seqstart = -1;
+ int skipsleft = 0;
+ for (int descnum = start; descnum < end; descnum++)
+ if (m_desc_array[descnum] != NULL)
+ {
+ // determine the next instruction, taking skips into account
+ opcode_desc *curdesc = m_desc_array[descnum];
+ int nextdescnum = descnum + curdesc->length;
+ opcode_desc *nextdesc = (nextdescnum < end) ? m_desc_array[nextdescnum] : NULL;
+ for (UINT8 skipnum = 0; skipnum < curdesc->skipslots && nextdesc != NULL; skipnum++)
+ {
+ nextdescnum = nextdescnum + nextdesc->length;
+ nextdesc = (nextdescnum < end) ? m_desc_array[nextdescnum] : NULL;
+ }
+
+ // start a new sequence if we aren't already in the middle of one
+ if (seqstart == -1 && skipsleft == 0)
+ {
+ // tag all start-of-sequence instructions as needing TLB verification
+ curdesc->flags |= OPFLAG_VALIDATE_TLB | OPFLAG_CAN_CAUSE_EXCEPTION;
+ seqstart = descnum;
+ }
+
+ // if we are the last instruction, indicate end-of-sequence and redispatch
+ if (nextdesc == NULL)
+ {
+ curdesc->flags |= OPFLAG_END_SEQUENCE;
+ if (endflag != OPFLAG_RETURN_TO_START || nextdescnum == end)
+ curdesc->flags |= endflag;
+ }
+
+ // otherwise, do some analysis based on the next instruction
+ else
+ {
+ // if there are instructions between us and the next instruction, we must end our sequence here
+ int scandescnum;
+ opcode_desc *scandesc = NULL;
+ for (scandescnum = descnum + 1; scandescnum < end; scandescnum++)
+ {
+ scandesc = m_desc_array[scandescnum];
+ if (scandesc != NULL || scandesc == nextdesc)
+ break;
+ }
+ if (scandesc != nextdesc)
+ curdesc->flags |= OPFLAG_END_SEQUENCE;
+
+ // if the next instruction is a branch target, mark this instruction as end of sequence
+ if (nextdesc->flags & OPFLAG_IS_BRANCH_TARGET)
+ curdesc->flags |= OPFLAG_END_SEQUENCE;
+ }
+
+ // if we exceed the maximum consecutive count, cut off the sequence
+ if (++consecutive >= m_max_sequence)
+ curdesc->flags |= OPFLAG_END_SEQUENCE;
+ if (curdesc->flags & OPFLAG_END_SEQUENCE)
+ consecutive = 0;
+
+ // if this is the end of a sequence, work backwards
+ if (curdesc->flags & OPFLAG_END_SEQUENCE)
+ {
+ // figure out which registers we *must* generate, assuming at the end all must be
+ UINT32 reqmask[4] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff };
+ if (seqstart != -1)
+ for (int backdesc = descnum; backdesc != seqstart - 1; backdesc--)
+ if (m_desc_array[backdesc] != NULL)
+ accumulate_required_backwards(*m_desc_array[backdesc], reqmask);
+
+ // reset the register states
+ seqstart = -1;
+ }
+
+ // if we have instructions remaining to be skipped, and this instruction is a branch target
+ // belay the skip order
+ if (skipsleft > 0 && (curdesc->flags & OPFLAG_IS_BRANCH_TARGET))
+ skipsleft = 0;
+
+ // if we're not getting skipped, add us to the end of the list and clear our array slot
+ if (skipsleft == 0)
+ m_desc_live_list.append(*curdesc);
+ else
+ m_desc_allocator.reclaim(*curdesc);
+
+ // if the current instruction starts skipping, reset our skip count
+ // otherwise, just decrement
+ if (curdesc->skipslots > 0)
+ skipsleft = curdesc->skipslots;
+ else if (skipsleft > 0)
+ skipsleft--;
+ }
+
+ // zap the array
+ memset(&m_desc_array[start], 0, (end - start) * sizeof(m_desc_array[0]));
+}
+
+
+//-------------------------------------------------
+// accumulate_required_backwards - recursively
+// accumulate live register liveness information
+// walking in a backwards direction
+//-------------------------------------------------
+
+void drc_frontend::accumulate_required_backwards(opcode_desc &desc, UINT32 *reqmask)
+{
+ // recursively handle delay slots
+ if (desc.delay.first() != NULL)
+ accumulate_required_backwards(*desc.delay.first(), reqmask);
+
+ // if this is a branch, we have to reset our requests
+ if (desc.flags & OPFLAG_IS_BRANCH)
+ reqmask[0] = reqmask[1] = reqmask[2] = reqmask[3] = 0xffffffff;
+
+ // determine the required registers
+ desc.regreq[0] = desc.regout[0] & reqmask[0];
+ desc.regreq[1] = desc.regout[1] & reqmask[1];
+ desc.regreq[2] = desc.regout[2] & reqmask[2];
+ desc.regreq[3] = desc.regout[3] & reqmask[3];
+
+ // any registers modified by this instruction aren't required upstream until referenced
+ reqmask[0] &= ~desc.regout[0];
+ reqmask[1] &= ~desc.regout[1];
+ reqmask[2] &= ~desc.regout[2];
+ reqmask[3] &= ~desc.regout[3];
+
+ // any registers required by this instruction now get marked required
+ reqmask[0] |= desc.regin[0];
+ reqmask[1] |= desc.regin[1];
+ reqmask[2] |= desc.regin[2];
+ reqmask[3] |= desc.regin[3];
+}
+
+
+//-------------------------------------------------
+// release_descriptions - release any
+// descriptions we've allocated back to the
+// free list
+//------------------------------------------------
+
+void drc_frontend::release_descriptions()
+{
+ // release all delay slots first
+ for (opcode_desc *curdesc = m_desc_live_list.first(); curdesc != NULL; curdesc = curdesc->next())
+ m_desc_allocator.reclaim_all(curdesc->delay);
+
+ // reclaim all the descriptors
+ m_desc_allocator.reclaim_all(m_desc_live_list);
+}
diff --git a/trunk/src/emu/cpu/drcfe.h b/trunk/src/emu/cpu/drcfe.h
new file mode 100644
index 00000000000..68b94ffd481
--- /dev/null
+++ b/trunk/src/emu/cpu/drcfe.h
@@ -0,0 +1,193 @@
+/***************************************************************************
+
+ drcfe.h
+
+ Generic dynamic recompiler frontend structures and utilities.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+****************************************************************************
+
+ Concepts:
+
+ Dynamic recompiling cores are generally broken into a platform-neutral
+ "frontend", which performs some level of analysis on the code, and a
+ platform-specific "backend", which generates the recompiled machine
+ code.
+
+ The frontend's job is generally to walk through the instruction stream,
+ identifying basic blocks, or "sequences" of code that can be compiled
+ and optimized as a unit. This scanning involves recursively walking
+ the instruction stream, following branches, etc., within a specific
+ "code window", relative to the current PC.
+
+ As the frontend walks through the code, it generates a list of opcode
+ "descriptions", one per visited opcode, providing information about
+ code flow, exception handling, and other characteristics. Once the
+ walkthrough is finished, these descriptions are assembled together into
+ a linked list and returned for further processing by the backend.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __DRCFE_H__
+#define __DRCFE_H__
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// this defines a branch targetpc that is dynamic at runtime
+const offs_t BRANCH_TARGET_DYNAMIC = ~0;
+
+
+// opcode branch flags
+const UINT32 OPFLAG_IS_UNCONDITIONAL_BRANCH = 0x00000001; // instruction is unconditional branch
+const UINT32 OPFLAG_IS_CONDITIONAL_BRANCH = 0x00000002; // instruction is conditional branch
+const UINT32 OPFLAG_IS_BRANCH = (OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_IS_CONDITIONAL_BRANCH);
+const UINT32 OPFLAG_IS_BRANCH_TARGET = 0x00000004; // instruction is the target of a branch
+const UINT32 OPFLAG_IN_DELAY_SLOT = 0x00000008; // instruction is in the delay slot of a branch
+const UINT32 OPFLAG_INTRABLOCK_BRANCH = 0x00000010; // instruction branches within the block
+
+// opcode exception flags
+const UINT32 OPFLAG_CAN_TRIGGER_SW_INT = 0x00000020; // instruction can trigger a software interrupt
+const UINT32 OPFLAG_CAN_EXPOSE_EXTERNAL_INT = 0x00000040; // instruction can expose an external interrupt
+const UINT32 OPFLAG_CAN_CAUSE_EXCEPTION = 0x00000080; // instruction may generate exception
+const UINT32 OPFLAG_WILL_CAUSE_EXCEPTION = 0x00000100; // instruction will generate exception
+const UINT32 OPFLAG_PRIVILEGED = 0x00000200; // instruction is privileged
+
+// opcode virtual->physical translation flags
+const UINT32 OPFLAG_VALIDATE_TLB = 0x00000400; // instruction must validate TLB before execution
+const UINT32 OPFLAG_MODIFIES_TRANSLATION = 0x00000800; // instruction modifies the TLB
+const UINT32 OPFLAG_COMPILER_PAGE_FAULT = 0x00001000; // compiler hit a page fault when parsing
+const UINT32 OPFLAG_COMPILER_UNMAPPED = 0x00002000; // compiler hit unmapped memory when parsing
+
+// opcode flags
+const UINT32 OPFLAG_INVALID_OPCODE = 0x00004000; // instruction is invalid
+const UINT32 OPFLAG_VIRTUAL_NOOP = 0x00008000; // instruction is a virtual no-op
+
+// opcode sequence flow flags
+const UINT32 OPFLAG_REDISPATCH = 0x00010000; // instruction must redispatch after completion
+const UINT32 OPFLAG_RETURN_TO_START = 0x00020000; // instruction must jump back to the beginning after completion
+const UINT32 OPFLAG_END_SEQUENCE = 0x00040000; // this is the last instruction in a sequence
+const UINT32 OPFLAG_CAN_CHANGE_MODES = 0x00080000; // instruction can change modes
+
+// execution semantics
+const UINT32 OPFLAG_READS_MEMORY = 0x00100000; // instruction reads memory
+const UINT32 OPFLAG_WRITES_MEMORY = 0x00200000; // instruction writes memory
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// description of a given opcode
+struct opcode_desc
+{
+ opcode_desc *next() const { return m_next; }
+
+ // links to other descriptions
+ opcode_desc * m_next; // pointer to next description
+ opcode_desc * branch; // pointer back to branch description for delay slots
+ simple_list<opcode_desc> delay; // pointer to delay slot description
+
+ // information about the current PC
+ offs_t pc; // PC of this opcode
+ offs_t physpc; // physical PC of this opcode
+ offs_t targetpc; // target PC if we are a branch, or BRANCH_TARGET_DYNAMIC
+
+ // copy of up to 16 bytes of opcode
+ union
+ {
+ UINT8 b[16];
+ UINT16 w[8];
+ UINT32 l[4];
+ UINT64 q[2];
+ } opptr; // pointer to opcode memory
+
+ // information about this instruction's execution
+ UINT8 length; // length in bytes of this opcode
+ UINT8 delayslots; // number of delay slots (for branches)
+ UINT8 skipslots; // number of skip slots (for branches)
+ UINT32 flags; // OPFLAG_* opcode flags
+ UINT32 cycles; // number of cycles needed to execute
+
+ // register usage information
+ UINT32 regin[4]; // input registers
+ UINT32 regout[4]; // output registers
+ UINT32 regreq[4]; // required output registers
+};
+
+
+// DRC frontend state
+class drc_frontend
+{
+public:
+ // construction/destruction
+ drc_frontend(device_t &cpu, UINT32 window_start, UINT32 window_end, UINT32 max_sequence);
+ virtual ~drc_frontend();
+
+ // describe a block
+ const opcode_desc *describe_code(offs_t startpc);
+
+protected:
+ // required overrides
+ virtual bool describe(opcode_desc &desc, const opcode_desc *prev) = 0;
+
+private:
+ // internal helpers
+ opcode_desc *describe_one(offs_t curpc, const opcode_desc *prevdesc);
+ void build_sequence(int start, int end, UINT32 endflag);
+ void accumulate_required_backwards(opcode_desc &desc, UINT32 *reqmask);
+ void release_descriptions();
+
+ // configuration parameters
+ UINT32 m_window_start; // code window start offset = startpc - window_start
+ UINT32 m_window_end; // code window end offset = startpc + window_end
+ UINT32 m_max_sequence; // maximum instructions to include in a sequence
+
+ // CPU parameters
+ cpu_device & m_cpudevice; // CPU device object
+ address_space * m_program; // program address space for this CPU
+ offs_t m_pageshift; // shift to convert address to a page index
+
+ // opcode descriptor arrays
+ simple_list<opcode_desc> m_desc_live_list; // list of live descriptions
+ fixed_allocator<opcode_desc> m_desc_allocator; // fixed allocator for descriptions
+ opcode_desc ** m_desc_array; // array of descriptions in PC order
+};
+
+
+#endif /* __DRCFE_H__ */
diff --git a/trunk/src/emu/cpu/drcuml.c b/trunk/src/emu/cpu/drcuml.c
new file mode 100644
index 00000000000..b19ff71f555
--- /dev/null
+++ b/trunk/src/emu/cpu/drcuml.c
@@ -0,0 +1,1169 @@
+/***************************************************************************
+
+ drcuml.c
+
+ Universal machine language for dynamic recompiling CPU cores.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+****************************************************************************
+
+ Future improvements/changes:
+
+ * UML optimizer:
+ - constant folding
+
+ * Write a back-end validator:
+ - checks all combinations of memory/register/immediate on all params
+ - checks behavior of all opcodes
+
+ * Extend registers to 16? Depends on if PPC can use them
+
+ * Support for FPU exceptions
+
+ * New instructions?
+ - FCOPYI, ICOPYF
+ copy raw between float and integer registers
+
+ - VALID opcode_desc,handle,param
+ checksum/compare code referenced by opcode_desc; if not
+ matching, generate exception with handle,param
+
+ - RECALL handle
+ change code at caller to call handle in the future
+
+***************************************************************************/
+
+#include "emu.h"
+#include "drcuml.h"
+#include "drcbec.h"
+#include "drcbex86.h"
+#include "drcbex64.h"
+
+using namespace uml;
+
+
+
+//**************************************************************************
+// DEBUGGING
+//**************************************************************************
+
+#define VALIDATE_BACKEND (0)
+#define LOG_SIMPLIFICATIONS (0)
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// structure describing back-end validation test
+struct bevalidate_test
+{
+ opcode_t opcode;
+ UINT8 size;
+ UINT8 iflags;
+ UINT8 flags;
+ UINT64 param[4];
+};
+
+
+
+//**************************************************************************
+// DRC BACKEND INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// drcbe_interface - constructor
+//-------------------------------------------------
+
+drcbe_interface::drcbe_interface(drcuml_state &drcuml, drc_cache &cache, device_t &device)
+ : m_drcuml(drcuml),
+ m_cache(cache),
+ m_device(device),
+ m_state(*(drcuml_machine_state *)cache.alloc_near(sizeof(m_state))),
+ m_accessors((data_accessors *)cache.alloc_near(sizeof(*m_accessors) * ADDRESS_SPACES))
+{
+ // reset the machine state
+ memset(m_accessors, 0, sizeof(*m_accessors) * ADDRESS_SPACES);
+ memset(&m_state, 0, sizeof(m_state));
+
+ // find the spaces and fetch memory accessors
+ device_memory_interface *memory;
+ if (device.interface(memory))
+ for (address_spacenum spacenum = AS_0; spacenum < ARRAY_LENGTH(m_space); spacenum++)
+ {
+ m_space[spacenum] = memory->space(spacenum);
+ if (m_space[spacenum] != NULL)
+ m_space[spacenum]->accessors(m_accessors[spacenum]);
+ }
+}
+
+
+//-------------------------------------------------
+// ~drcbe_interface - destructor
+//-------------------------------------------------
+
+drcbe_interface::~drcbe_interface()
+{
+}
+
+
+
+//**************************************************************************
+// DRCUML STATE
+//**************************************************************************
+
+//-------------------------------------------------
+// drcuml_state - constructor
+//-------------------------------------------------
+
+drcuml_state::drcuml_state(device_t &device, drc_cache &cache, UINT32 flags, int modes, int addrbits, int ignorebits)
+ : m_device(device),
+ m_cache(cache),
+ m_beintf((flags & DRCUML_OPTION_USE_C) ?
+ *static_cast<drcbe_interface *>(auto_alloc(device.machine(), drcbe_c(*this, device, cache, flags, modes, addrbits, ignorebits))) :
+ *static_cast<drcbe_interface *>(auto_alloc(device.machine(), drcbe_native(*this, device, cache, flags, modes, addrbits, ignorebits)))),
+ m_umllog(NULL),
+ m_blocklist(device.machine().respool()),
+ m_symlist(device.machine().respool())
+{
+ // if we're to log, create the logfile
+ if (flags & DRCUML_OPTION_LOG_UML)
+ m_umllog = fopen("drcuml.asm", "w");
+}
+
+
+//-------------------------------------------------
+// ~drcuml_state - destructor
+//-------------------------------------------------
+
+drcuml_state::~drcuml_state()
+{
+ // free the back-end
+ auto_free(m_device.machine(), &m_beintf);
+
+ // close any files
+ if (m_umllog != NULL)
+ fclose(m_umllog);
+}
+
+
+//-------------------------------------------------
+// reset - reset the state completely, flushing
+// the cache and all information
+//-------------------------------------------------
+
+void drcuml_state::reset()
+{
+ // if we error here, we are screwed
+ try
+ {
+ // flush the cache
+ m_cache.flush();
+
+ // reset all handle code pointers
+ for (code_handle *handle = m_handlelist.first(); handle != NULL; handle = handle->next())
+ *handle->m_code = NULL;
+
+ // call the backend to reset
+ m_beintf.reset();
+
+ // do a one-time validation if requested
+/* if (VALIDATE_BACKEND)
+ {
+ static bool validated = false;
+ if (!validated)
+ {
+ validated = true;
+ validate_backend(this);
+ }
+ }*/
+ }
+ catch (drcuml_block::abort_compilation &)
+ {
+ fatalerror("Out of cache space in drcuml_state::reset");
+ }
+}
+
+
+//-------------------------------------------------
+// begin_block - begin a new code block
+//-------------------------------------------------
+
+drcuml_block *drcuml_state::begin_block(UINT32 maxinst)
+{
+ // find an inactive block that matches our qualifications
+ drcuml_block *bestblock = NULL;
+ for (drcuml_block *block = m_blocklist.first(); block != NULL; block = block->next())
+ if (!block->inuse() && block->maxinst() >= maxinst && (bestblock == NULL || block->maxinst() < bestblock->maxinst()))
+ bestblock = block;
+
+ // if we failed to find one, allocate a new one
+ if (bestblock == NULL)
+ bestblock = &m_blocklist.append(*auto_alloc(m_device.machine(), drcuml_block(*this, maxinst * 3/2)));
+
+ // start the block
+ bestblock->begin();
+ return bestblock;
+}
+
+
+//-------------------------------------------------
+// handle_alloc - allocate a new handle
+//-------------------------------------------------
+
+code_handle *drcuml_state::handle_alloc(const char *name)
+{
+ // allocate the handle, add it to our list, and return it
+ return &m_handlelist.append(*auto_alloc(m_device.machine(), code_handle(*this, name)));
+}
+
+
+//-------------------------------------------------
+// symbol_add - add a symbol to the internal
+// symbol table
+//-------------------------------------------------
+
+void drcuml_state::symbol_add(void *base, UINT32 length, const char *name)
+{
+ m_symlist.append(*auto_alloc(m_device.machine(), symbol(base, length, name)));
+}
+
+
+//-------------------------------------------------
+// symbol_find - look up a symbol from the
+// internal symbol table or return NULL if not
+// found
+//-------------------------------------------------
+
+const char *drcuml_state::symbol_find(void *base, UINT32 *offset)
+{
+ drccodeptr search = drccodeptr(base);
+
+ // simple linear search
+ for (symbol *cursym = m_symlist.first(); cursym != NULL; cursym = cursym->next())
+ if (search >= cursym->m_base && search < cursym->m_base + cursym->m_length)
+ {
+ // if no offset pointer, only match perfectly
+ if (offset == NULL && search != cursym->m_base)
+ continue;
+
+ // return the offset and name
+ if (offset != NULL)
+ *offset = search - cursym->m_base;
+ return cursym->m_name;
+ }
+
+ // not found; return NULL
+ return NULL;
+}
+
+
+//-------------------------------------------------
+// log_printf - directly printf to the UML log
+// if generated
+//-------------------------------------------------
+
+void drcuml_state::log_printf(const char *format, ...)
+{
+ // if we have a file, print to it
+ if (m_umllog != NULL)
+ {
+ va_list va;
+
+ // do the printf
+ va_start(va, format);
+ vfprintf(m_umllog, format, va);
+ va_end(va);
+ }
+}
+
+
+
+//**************************************************************************
+// DRCUML BLOCK
+//**************************************************************************
+
+//-------------------------------------------------
+// drcuml_block - constructor
+//-------------------------------------------------
+
+drcuml_block::drcuml_block(drcuml_state &drcuml, UINT32 maxinst)
+ : m_drcuml(drcuml),
+ m_next(NULL),
+ m_nextinst(0),
+ m_maxinst(maxinst * 3/2),
+ m_inst(auto_alloc_array(drcuml.device().machine(), instruction, m_maxinst)),
+ m_inuse(false)
+{
+}
+
+
+//-------------------------------------------------
+// ~drcuml_block - destructor
+//-------------------------------------------------
+
+drcuml_block::~drcuml_block()
+{
+ // free the instruction list
+ auto_free(m_drcuml.device().machine(), m_inst);
+}
+
+
+//-------------------------------------------------
+// begin - begin code generation
+//-------------------------------------------------
+
+void drcuml_block::begin()
+{
+ // set up the block information and return it
+ m_inuse = true;
+ m_nextinst = 0;
+}
+
+
+//-------------------------------------------------
+// end - complete a code block and commit it to
+// the cache via the back-end
+//-------------------------------------------------
+
+void drcuml_block::end()
+{
+ assert(m_inuse);
+
+ // optimize the resulting code first
+ optimize();
+
+ // if we have a logfile, generate a disassembly of the block
+ if (m_drcuml.logging())
+ disassemble();
+
+ // generate the code via the back-end
+ m_drcuml.generate(*this, m_inst, m_nextinst);
+
+ // block is no longer in use
+ m_inuse = false;
+}
+
+
+//-------------------------------------------------
+// abort - abort a code block in progress
+//-------------------------------------------------
+
+void drcuml_block::abort()
+{
+ assert(m_inuse);
+
+ // block is no longer in use
+ m_inuse = false;
+
+ // unwind
+ throw abort_compilation();
+}
+
+
+//-------------------------------------------------
+// append - append an opcode to the block
+//-------------------------------------------------
+
+uml::instruction &drcuml_block::append()
+{
+ // get a pointer to the next instruction
+ instruction &curinst = m_inst[m_nextinst++];
+ if (m_nextinst > m_maxinst)
+ fatalerror("Overran maxinst in drcuml_block_append");
+
+ return curinst;
+}
+
+
+//-------------------------------------------------
+// comment - attach a comment to the current
+// output location in the specified block
+//-------------------------------------------------
+
+void drcuml_block::append_comment(const char *format, ...)
+{
+ // do the printf
+ astring temp;
+ va_list va;
+ va_start(va, format);
+ temp.vprintf(format, va);
+ va_end(va);
+
+ // allocate space in the cache to hold the comment
+ char *comment = (char *)m_drcuml.cache().alloc_temporary(temp.len() + 1);
+ if (comment == NULL)
+ return;
+ strcpy(comment, temp);
+
+ // add an instruction with a pointer
+ append().comment(comment);
+}
+
+
+//-------------------------------------------------
+// optimize - apply various optimizations to a
+// block of code
+//-------------------------------------------------
+
+void drcuml_block::optimize()
+{
+ UINT32 mapvar[MAPVAR_COUNT] = { 0 };
+
+ // iterate over instructions
+ for (int instnum = 0; instnum < m_nextinst; instnum++)
+ {
+ instruction &inst = m_inst[instnum];
+
+ // first compute what flags we need
+ UINT8 accumflags = 0;
+ UINT8 remainingflags = inst.output_flags();
+
+ // scan ahead until we run out of possible remaining flags
+ for (int scannum = instnum + 1; remainingflags != 0 && scannum < m_nextinst; scannum++)
+ {
+ // any input flags are required
+ const instruction &scan = m_inst[scannum];
+ accumflags |= scan.input_flags();
+
+ // if the scanahead instruction is unconditional, assume his flags are modified
+ if (scan.condition() == COND_ALWAYS)
+ remainingflags &= ~scan.modified_flags();
+ }
+ inst.set_flags(accumflags);
+
+ // track mapvars
+ if (inst.opcode() == OP_MAPVAR)
+ mapvar[inst.param(0).mapvar() - MAPVAR_M0] = inst.param(1).immediate();
+
+ // convert all mapvar parameters to immediates
+ else if (inst.opcode() != OP_RECOVER)
+ for (int pnum = 0; pnum < inst.numparams(); pnum++)
+ if (inst.param(pnum).is_mapvar())
+ inst.set_mapvar(pnum, mapvar[inst.param(pnum).mapvar() - MAPVAR_M0]);
+
+ // now that flags are correct, simplify the instruction
+ inst.simplify();
+ }
+}
+
+
+//-------------------------------------------------
+// disassemble - disassemble a block of
+// instructions to the log
+//-------------------------------------------------
+
+void drcuml_block::disassemble()
+{
+ astring comment;
+ astring dasm;
+
+ // iterate over instructions and output
+ int firstcomment = -1;
+ for (int instnum = 0; instnum < m_nextinst; instnum++)
+ {
+ const instruction &inst = m_inst[instnum];
+ bool flushcomments = false;
+
+ // remember comments and mapvars for later
+ if (inst.opcode() == OP_COMMENT || inst.opcode() == OP_MAPVAR)
+ {
+ if (firstcomment == -1)
+ firstcomment = instnum;
+ }
+
+ // print labels, handles, and hashes left justified
+ else if (inst.opcode() == OP_LABEL)
+ m_drcuml.log_printf("$%X:\n", UINT32(inst.param(0).label()));
+ else if (inst.opcode() == OP_HANDLE)
+ m_drcuml.log_printf("%s:\n", inst.param(0).handle().string());
+ else if (inst.opcode() == OP_HASH)
+ m_drcuml.log_printf("(%X,%X):\n", UINT32(inst.param(0).immediate()), UINT32(inst.param(1).immediate()));
+
+ // indent everything else with a tab
+ else
+ {
+ m_inst[instnum].disasm(dasm, &m_drcuml);
+
+ // include the first accumulated comment with this line
+ if (firstcomment != -1)
+ {
+ m_drcuml.log_printf("\t%-50.50s; %s\n", dasm.cstr(), get_comment_text(m_inst[firstcomment], comment));
+ firstcomment++;
+ flushcomments = TRUE;
+ }
+ else
+ m_drcuml.log_printf("\t%s\n", dasm.cstr());
+ }
+
+ // flush any comments pending
+ if (firstcomment != -1 && (flushcomments || instnum == m_nextinst - 1))
+ {
+ while (firstcomment <= instnum)
+ {
+ const char *text = get_comment_text(m_inst[firstcomment++], comment);
+ if (text != NULL)
+ m_drcuml.log_printf("\t%50s; %s\n", "", text);
+ }
+ firstcomment = -1;
+ }
+ }
+ m_drcuml.log_printf("\n\n");
+ m_drcuml.log_flush();
+}
+
+
+//-------------------------------------------------
+// get_comment_text - determine the text
+// associated with a comment or mapvar
+//-------------------------------------------------
+
+const char *drcuml_block::get_comment_text(const instruction &inst, astring &comment)
+{
+ // comments return their strings
+ if (inst.opcode() == OP_COMMENT)
+ return comment.cpy(inst.param(0).string());
+
+ // mapvars comment about their values
+ else if (inst.opcode() == OP_MAPVAR)
+ return comment.format("m%d = $%X", (int)inst.param(0).mapvar() - MAPVAR_M0, (UINT32)inst.param(1).immediate());
+
+ // everything else is NULL
+ return NULL;
+}
+
+
+
+#if 0
+
+/***************************************************************************
+ BACK-END VALIDATION
+***************************************************************************/
+
+//-------------------------------------------------
+// effective_test_psize - return the effective
+// parameter size based on the size and fixed
+// array of parameter values
+//-------------------------------------------------
+
+inline UINT8 effective_test_psize(const opcode_info &opinfo, int pnum, int instsize, const UINT64 *params)
+{
+ switch (opinfo.param[pnum].size)
+ {
+ case PSIZE_4: return 4;
+ case PSIZE_8: return 8;
+ case PSIZE_OP: return instsize;
+ case PSIZE_P1: return 1 << (params[0] & 3);
+ case PSIZE_P2: return 1 << (params[1] & 3);
+ case PSIZE_P3: return 1 << (params[2] & 3);
+ case PSIZE_P4: return 1 << (params[3] & 3);
+ }
+ return instsize;
+}
+
+#define TEST_ENTRY_2(op, size, p1, p2, flags) { OP_##op, size, 0, flags, { U64(p1), U64(p2) } },
+#define TEST_ENTRY_2F(op, size, p1, p2, iflags, flags) { OP_##op, size, iflags, flags, { U64(p1), U64(p2) } },
+#define TEST_ENTRY_3(op, size, p1, p2, p3, flags) { OP_##op, size, 0, flags, { U64(p1), U64(p2), U64(p3) } },
+#define TEST_ENTRY_3F(op, size, p1, p2, p3, iflags, flags) { OP_##op, size, iflags, flags, { U64(p1), U64(p2), U64(p3) } },
+#define TEST_ENTRY_4(op, size, p1, p2, p3, p4, flags) { OP_##op, size, 0, flags, { U64(p1), U64(p2), U64(p3), U64(p4) } },
+#define TEST_ENTRY_4F(op, size, p1, p2, p3, p4, iflags, flags) { OP_##op, size, iflags, flags, { U64(p1), U64(p2), U64(p3), U64(p4) } },
+
+static const bevalidate_test bevalidate_test_list[] =
+{
+ TEST_ENTRY_3(ADD, 4, 0x7fffffff, 0x12345678, 0x6dcba987, 0)
+ TEST_ENTRY_3(ADD, 4, 0x80000000, 0x12345678, 0x6dcba988, FLAG_V | FLAG_S)
+ TEST_ENTRY_3(ADD, 4, 0xffffffff, 0x92345678, 0x6dcba987, FLAG_S)
+ TEST_ENTRY_3(ADD, 4, 0x00000000, 0x92345678, 0x6dcba988, FLAG_C | FLAG_Z)
+
+ TEST_ENTRY_3(ADD, 8, 0x7fffffffffffffff, 0x0123456789abcdef, 0x7edcba9876543210, 0)
+ TEST_ENTRY_3(ADD, 8, 0x8000000000000000, 0x0123456789abcdef, 0x7edcba9876543211, FLAG_V | FLAG_S)
+ TEST_ENTRY_3(ADD, 8, 0xffffffffffffffff, 0x8123456789abcdef, 0x7edcba9876543210, FLAG_S)
+ TEST_ENTRY_3(ADD, 8, 0x0000000000000000, 0x8123456789abcdef, 0x7edcba9876543211, FLAG_C | FLAG_Z)
+
+ TEST_ENTRY_3F(ADDC, 4, 0x7fffffff, 0x12345678, 0x6dcba987, 0, 0)
+ TEST_ENTRY_3F(ADDC, 4, 0x7fffffff, 0x12345678, 0x6dcba986, FLAG_C, 0)
+ TEST_ENTRY_3F(ADDC, 4, 0x80000000, 0x12345678, 0x6dcba988, 0, FLAG_V | FLAG_S)
+ TEST_ENTRY_3F(ADDC, 4, 0x80000000, 0x12345678, 0x6dcba987, FLAG_C, FLAG_V | FLAG_S)
+ TEST_ENTRY_3F(ADDC, 4, 0xffffffff, 0x92345678, 0x6dcba987, 0, FLAG_S)
+ TEST_ENTRY_3F(ADDC, 4, 0xffffffff, 0x92345678, 0x6dcba986, FLAG_C, FLAG_S)
+ TEST_ENTRY_3F(ADDC, 4, 0x00000000, 0x92345678, 0x6dcba988, 0, FLAG_C | FLAG_Z)
+ TEST_ENTRY_3F(ADDC, 4, 0x00000000, 0x92345678, 0x6dcba987, FLAG_C, FLAG_C | FLAG_Z)
+ TEST_ENTRY_3F(ADDC, 4, 0x12345678, 0x12345678, 0xffffffff, FLAG_C, FLAG_C)
+
+ TEST_ENTRY_3F(ADDC, 8, 0x7fffffffffffffff, 0x0123456789abcdef, 0x7edcba9876543210, 0, 0)
+ TEST_ENTRY_3F(ADDC, 8, 0x7fffffffffffffff, 0x0123456789abcdef, 0x7edcba987654320f, FLAG_C, 0)
+ TEST_ENTRY_3F(ADDC, 8, 0x8000000000000000, 0x0123456789abcdef, 0x7edcba9876543211, 0, FLAG_V | FLAG_S)
+ TEST_ENTRY_3F(ADDC, 8, 0x8000000000000000, 0x0123456789abcdef, 0x7edcba9876543210, FLAG_C, FLAG_V | FLAG_S)
+ TEST_ENTRY_3F(ADDC, 8, 0xffffffffffffffff, 0x8123456789abcdef, 0x7edcba9876543210, 0, FLAG_S)
+ TEST_ENTRY_3F(ADDC, 8, 0xffffffffffffffff, 0x8123456789abcdef, 0x7edcba987654320f, FLAG_C, FLAG_S)
+ TEST_ENTRY_3F(ADDC, 8, 0x0000000000000000, 0x8123456789abcdef, 0x7edcba9876543211, 0, FLAG_C | FLAG_Z)
+ TEST_ENTRY_3F(ADDC, 8, 0x0000000000000000, 0x8123456789abcdef, 0x7edcba9876543210, FLAG_C, FLAG_C | FLAG_Z)
+ TEST_ENTRY_3F(ADDC, 8, 0x123456789abcdef0, 0x123456789abcdef0, 0xffffffffffffffff, FLAG_C, FLAG_C)
+
+ TEST_ENTRY_3(SUB, 4, 0x12345678, 0x7fffffff, 0x6dcba987, 0)
+ TEST_ENTRY_3(SUB, 4, 0x12345678, 0x80000000, 0x6dcba988, FLAG_V)
+ TEST_ENTRY_3(SUB, 4, 0x92345678, 0xffffffff, 0x6dcba987, FLAG_S)
+ TEST_ENTRY_3(SUB, 4, 0x92345678, 0x00000000, 0x6dcba988, FLAG_C | FLAG_S)
+ TEST_ENTRY_3(SUB, 4, 0x00000000, 0x12345678, 0x12345678, FLAG_Z)
+
+ TEST_ENTRY_3(SUB, 8, 0x0123456789abcdef, 0x7fffffffffffffff, 0x7edcba9876543210, 0)
+ TEST_ENTRY_3(SUB, 8, 0x0123456789abcdef, 0x8000000000000000, 0x7edcba9876543211, FLAG_V)
+ TEST_ENTRY_3(SUB, 8, 0x8123456789abcdef, 0xffffffffffffffff, 0x7edcba9876543210, FLAG_S)
+ TEST_ENTRY_3(SUB, 8, 0x8123456789abcdef, 0x0000000000000000, 0x7edcba9876543211, FLAG_C | FLAG_S)
+ TEST_ENTRY_3(SUB, 8, 0x0000000000000000, 0x0123456789abcdef, 0x0123456789abcdef, FLAG_Z)
+
+ TEST_ENTRY_3F(SUBB, 4, 0x12345678, 0x7fffffff, 0x6dcba987, 0, 0)
+ TEST_ENTRY_3F(SUBB, 4, 0x12345678, 0x7fffffff, 0x6dcba986, FLAG_C, 0)
+ TEST_ENTRY_3F(SUBB, 4, 0x12345678, 0x80000000, 0x6dcba988, 0, FLAG_V)
+ TEST_ENTRY_3F(SUBB, 4, 0x12345678, 0x80000000, 0x6dcba987, FLAG_C, FLAG_V)
+ TEST_ENTRY_3F(SUBB, 4, 0x92345678, 0xffffffff, 0x6dcba987, 0, FLAG_S)
+ TEST_ENTRY_3F(SUBB, 4, 0x92345678, 0xffffffff, 0x6dcba986, FLAG_C, FLAG_S)
+ TEST_ENTRY_3F(SUBB, 4, 0x92345678, 0x00000000, 0x6dcba988, 0, FLAG_C | FLAG_S)
+ TEST_ENTRY_3F(SUBB, 4, 0x92345678, 0x00000000, 0x6dcba987, FLAG_C, FLAG_C | FLAG_S)
+ TEST_ENTRY_3F(SUBB, 4, 0x12345678, 0x12345678, 0xffffffff, FLAG_C, FLAG_C)
+ TEST_ENTRY_3F(SUBB, 4, 0x00000000, 0x12345678, 0x12345677, FLAG_C, FLAG_Z)
+
+ TEST_ENTRY_3F(SUBB, 8, 0x0123456789abcdef, 0x7fffffffffffffff, 0x7edcba9876543210, 0, 0)
+ TEST_ENTRY_3F(SUBB, 8, 0x0123456789abcdef, 0x7fffffffffffffff, 0x7edcba987654320f, FLAG_C, 0)
+ TEST_ENTRY_3F(SUBB, 8, 0x0123456789abcdef, 0x8000000000000000, 0x7edcba9876543211, 0, FLAG_V)
+ TEST_ENTRY_3F(SUBB, 8, 0x0123456789abcdef, 0x8000000000000000, 0x7edcba9876543210, FLAG_C, FLAG_V)
+ TEST_ENTRY_3F(SUBB, 8, 0x8123456789abcdef, 0xffffffffffffffff, 0x7edcba9876543210, 0, FLAG_S)
+ TEST_ENTRY_3F(SUBB, 8, 0x8123456789abcdef, 0xffffffffffffffff, 0x7edcba987654320f, FLAG_C, FLAG_S)
+ TEST_ENTRY_3F(SUBB, 8, 0x8123456789abcdef, 0x0000000000000000, 0x7edcba9876543211, 0, FLAG_C | FLAG_S)
+ TEST_ENTRY_3F(SUBB, 8, 0x8123456789abcdef, 0x0000000000000000, 0x7edcba9876543210, FLAG_C, FLAG_C | FLAG_S)
+ TEST_ENTRY_3F(SUBB, 8, 0x123456789abcdef0, 0x123456789abcdef0, 0xffffffffffffffff, FLAG_C, FLAG_C)
+ TEST_ENTRY_3F(SUBB, 8, 0x0000000000000000, 0x123456789abcdef0, 0x123456789abcdeef, FLAG_C, FLAG_Z)
+
+ TEST_ENTRY_2(CMP, 4, 0x7fffffff, 0x6dcba987, 0)
+ TEST_ENTRY_2(CMP, 4, 0x80000000, 0x6dcba988, FLAG_V)
+ TEST_ENTRY_2(CMP, 4, 0xffffffff, 0x6dcba987, FLAG_S)
+ TEST_ENTRY_2(CMP, 4, 0x00000000, 0x6dcba988, FLAG_C | FLAG_S)
+ TEST_ENTRY_2(CMP, 4, 0x12345678, 0x12345678, FLAG_Z)
+
+ TEST_ENTRY_2(CMP, 8, 0x7fffffffffffffff, 0x7edcba9876543210, 0)
+ TEST_ENTRY_2(CMP, 8, 0x8000000000000000, 0x7edcba9876543211, FLAG_V)
+ TEST_ENTRY_2(CMP, 8, 0xffffffffffffffff, 0x7edcba9876543210, FLAG_S)
+ TEST_ENTRY_2(CMP, 8, 0x0000000000000000, 0x7edcba9876543211, FLAG_C | FLAG_S)
+ TEST_ENTRY_2(CMP, 8, 0x0123456789abcdef, 0x0123456789abcdef, FLAG_Z)
+
+ TEST_ENTRY_4(MULU, 4, 0x77777777, 0x00000000, 0x11111111, 0x00000007, 0)
+ TEST_ENTRY_4(MULU, 4, 0xffffffff, 0x00000000, 0x11111111, 0x0000000f, 0)
+ TEST_ENTRY_4(MULU, 4, 0x00000000, 0x00000000, 0x11111111, 0x00000000, FLAG_Z)
+ TEST_ENTRY_4(MULU, 4, 0xea61d951, 0x37c048d0, 0x77777777, 0x77777777, FLAG_V)
+ TEST_ENTRY_4(MULU, 4, 0x32323233, 0xcdcdcdcc, 0xcdcdcdcd, 0xffffffff, FLAG_V | FLAG_S)
+
+ TEST_ENTRY_4(MULU, 8, 0x7777777777777777, 0x0000000000000000, 0x1111111111111111, 0x0000000000000007, 0)
+ TEST_ENTRY_4(MULU, 8, 0xffffffffffffffff, 0x0000000000000000, 0x1111111111111111, 0x000000000000000f, 0)
+ TEST_ENTRY_4(MULU, 8, 0x0000000000000000, 0x0000000000000000, 0x1111111111111111, 0x0000000000000000, FLAG_Z)
+ TEST_ENTRY_4(MULU, 8, 0x0c83fb72ea61d951, 0x37c048d159e26af3, 0x7777777777777777, 0x7777777777777777, FLAG_V)
+ TEST_ENTRY_4(MULU, 8, 0x3232323232323233, 0xcdcdcdcdcdcdcdcc, 0xcdcdcdcdcdcdcdcd, 0xffffffffffffffff, FLAG_V | FLAG_S)
+
+ TEST_ENTRY_4(MULS, 4, 0x77777777, 0x00000000, 0x11111111, 0x00000007, 0)
+ TEST_ENTRY_4(MULS, 4, 0xffffffff, 0x00000000, 0x11111111, 0x0000000f, FLAG_V)
+ TEST_ENTRY_4(MULS, 4, 0x00000000, 0x00000000, 0x11111111, 0x00000000, FLAG_Z)
+ TEST_ENTRY_4(MULS, 4, 0x9e26af38, 0xc83fb72e, 0x77777777, 0x88888888, FLAG_V | FLAG_S)
+ TEST_ENTRY_4(MULS, 4, 0x32323233, 0x00000000, 0xcdcdcdcd, 0xffffffff, 0)
+
+ TEST_ENTRY_4(MULS, 8, 0x7777777777777777, 0x0000000000000000, 0x1111111111111111, 0x0000000000000007, 0)
+ TEST_ENTRY_4(MULS, 8, 0xffffffffffffffff, 0x0000000000000000, 0x1111111111111111, 0x000000000000000f, FLAG_V)
+ TEST_ENTRY_4(MULS, 8, 0x0000000000000000, 0x0000000000000000, 0x1111111111111111, 0x0000000000000000, FLAG_Z)
+ TEST_ENTRY_4(MULS, 8, 0x7c048d159e26af38, 0xc83fb72ea61d950c, 0x7777777777777777, 0x8888888888888888, FLAG_V | FLAG_S)
+ TEST_ENTRY_4(MULS, 8, 0x3232323232323233, 0x0000000000000000, 0xcdcdcdcdcdcdcdcd, 0xffffffffffffffff, 0)
+
+ TEST_ENTRY_4(DIVU, 4, 0x02702702, 0x00000003, 0x11111111, 0x00000007, 0)
+ TEST_ENTRY_4(DIVU, 4, 0x00000000, 0x11111111, 0x11111111, 0x11111112, FLAG_Z)
+ TEST_ENTRY_4(DIVU, 4, 0x7fffffff, 0x00000000, 0xfffffffe, 0x00000002, 0)
+ TEST_ENTRY_4(DIVU, 4, 0xfffffffe, 0x00000000, 0xfffffffe, 0x00000001, FLAG_S)
+ TEST_ENTRY_4(DIVU, 4, UNDEFINED, UNDEFINED, 0xffffffff, 0x00000000, FLAG_V)
+
+ TEST_ENTRY_4(DIVU, 8, 0x0270270270270270, 0x0000000000000001, 0x1111111111111111, 0x0000000000000007, 0)
+ TEST_ENTRY_4(DIVU, 8, 0x0000000000000000, 0x1111111111111111, 0x1111111111111111, 0x1111111111111112, FLAG_Z)
+ TEST_ENTRY_4(DIVU, 8, 0x7fffffffffffffff, 0x0000000000000000, 0xfffffffffffffffe, 0x0000000000000002, 0)
+ TEST_ENTRY_4(DIVU, 8, 0xfffffffffffffffe, 0x0000000000000000, 0xfffffffffffffffe, 0x0000000000000001, FLAG_S)
+ TEST_ENTRY_4(DIVU, 8, UNDEFINED, UNDEFINED, 0xffffffffffffffff, 0x0000000000000000, FLAG_V)
+
+ TEST_ENTRY_4(DIVS, 4, 0x02702702, 0x00000003, 0x11111111, 0x00000007, 0)
+ TEST_ENTRY_4(DIVS, 4, 0x00000000, 0x11111111, 0x11111111, 0x11111112, FLAG_Z)
+ TEST_ENTRY_4(DIVS, 4, 0xffffffff, 0x00000000, 0xfffffffe, 0x00000002, FLAG_S)
+ TEST_ENTRY_4(DIVS, 4, UNDEFINED, UNDEFINED, 0xffffffff, 0x00000000, FLAG_V)
+
+ TEST_ENTRY_4(DIVS, 8, 0x0270270270270270, 0x0000000000000001, 0x1111111111111111, 0x0000000000000007, 0)
+ TEST_ENTRY_4(DIVS, 8, 0x0000000000000000, 0x1111111111111111, 0x1111111111111111, 0x1111111111111112, FLAG_Z)
+ TEST_ENTRY_4(DIVS, 8, 0xffffffffffffffff, 0x0000000000000000, 0xfffffffffffffffe, 0x0000000000000002, FLAG_S)
+ TEST_ENTRY_4(DIVS, 8, UNDEFINED, UNDEFINED, 0xffffffffffffffff, 0x0000000000000000, FLAG_V)
+};
+
+
+/*-------------------------------------------------
+ validate_backend - execute a number of
+ generic tests on the backend code generator
+-------------------------------------------------*/
+
+static void validate_backend(drcuml_state *drcuml)
+{
+ code_handle *handles[3];
+ int tnum;
+
+ // allocate handles for the code
+ handles[0] = drcuml->handle_alloc("test_entry");
+ handles[1] = drcuml->handle_alloc("code_start");
+ handles[2] = drcuml->handle_alloc("code_end");
+
+ // iterate over test entries
+ printf("Backend validation....\n");
+ for (tnum = 31; tnum < ARRAY_LENGTH(bevalidate_test_list); tnum++)
+ {
+ const bevalidate_test *test = &bevalidate_test_list[tnum];
+ parameter param[ARRAY_LENGTH(test->param)];
+ char mnemonic[20], *dst;
+ const char *src;
+
+ // progress
+ dst = mnemonic;
+ for (src = opcode_info_table[test->opcode()]->mnemonic; *src != 0; src++)
+ {
+ if (*src == '!')
+ {
+ if (test->size == 8)
+ *dst++ = 'd';
+ }
+ else if (*src == '#')
+ *dst++ = (test->size == 8) ? 'd' : 's';
+ else
+ *dst++ = *src;
+ }
+ *dst = 0;
+ printf("Executing test %d/%d (%s)", tnum + 1, (int)ARRAY_LENGTH(bevalidate_test_list), mnemonic);
+
+ // reset parameter list and iterate
+ memset(param, 0, sizeof(param));
+ bevalidate_iterate_over_params(drcuml, handles, test, param, 0);
+ printf("\n");
+ }
+ fatalerror("All tests passed!");
+}
+
+
+/*-------------------------------------------------
+ bevalidate_iterate_over_params - iterate over
+ all supported types and values of a parameter
+ and recursively hand off to the next parameter,
+ or else move on to iterate over the flags
+-------------------------------------------------*/
+
+static void bevalidate_iterate_over_params(drcuml_state *drcuml, code_handle **handles, const bevalidate_test *test, parameter *paramlist, int pnum)
+{
+ const opcode_info *opinfo = opcode_info_table[test->opcode()];
+ drcuml_ptype ptype;
+
+ // if no parameters, execute now
+ if (pnum >= ARRAY_LENGTH(opinfo->param) || opinfo->param[pnum].typemask == PTYPES_NONE)
+ {
+ bevalidate_iterate_over_flags(drcuml, handles, test, paramlist);
+ return;
+ }
+
+ // iterate over valid parameter types
+ for (ptype = parameter::PTYPE_IMMEDIATE; ptype < parameter::PTYPE_MAX; ptype++)
+ if (opinfo->param[pnum].typemask & (1 << ptype))
+ {
+ int pindex, pcount;
+
+ // mapvars can only do 32-bit tests
+ if (ptype == parameter::PTYPE_MAPVAR && effective_test_psize(opinfo, pnum, test->size, test->param) == 8)
+ continue;
+
+ // for some parameter types, we wish to iterate over all possibilities
+ switch (ptype)
+ {
+ case parameter::PTYPE_INT_REGISTER: pcount = REG_I_END - REG_I0; break;
+ case parameter::PTYPE_FLOAT_REGISTER: pcount = REG_F_END - REG_F0; break;
+ default: pcount = 1; break;
+ }
+
+ // iterate over possibilities
+ for (pindex = 0; pindex < pcount; pindex++)
+ {
+ int skip = FALSE;
+ int pscannum;
+
+ // for param 0, print a dot
+ if (pnum == 0)
+ printf(".");
+
+ // can't duplicate multiple source parameters unless they are immediates
+ if (ptype != parameter::PTYPE_IMMEDIATE && (opinfo->param[pnum].output & PIO_IN))
+
+ // loop over all parameters we've done before; if the parameter is a source and matches us, skip this case
+ for (pscannum = 0; pscannum < pnum; pscannum++)
+ if ((opinfo->param[pscannum].output & PIO_IN) && ptype == paramlist[pscannum].type && pindex == paramlist[pscannum].value)
+ skip = TRUE;
+
+ // can't duplicate multiple dest parameters
+ if (opinfo->param[pnum].output & PIO_OUT)
+
+ // loop over all parameters we've done before; if the parameter is a source and matches us, skip this case
+ for (pscannum = 0; pscannum < pnum; pscannum++)
+ if ((opinfo->param[pscannum].output & PIO_OUT) && ptype == paramlist[pscannum].type && pindex == paramlist[pscannum].value)
+ skip = TRUE;
+
+ // iterate over the next parameter in line
+ if (!skip)
+ {
+ paramlist[pnum].type = ptype;
+ paramlist[pnum].value = pindex;
+ bevalidate_iterate_over_params(drcuml, handles, test, paramlist, pnum + 1);
+ }
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ bevalidate_iterate_over_flags - iterate over
+ all supported flag masks
+-------------------------------------------------*/
+
+static void bevalidate_iterate_over_flags(drcuml_state *drcuml, code_handle **handles, const bevalidate_test *test, parameter *paramlist)
+{
+ const opcode_info *opinfo = opcode_info_table[test->opcode()];
+ UINT8 flagmask = opinfo->outflags;
+ UINT8 curmask;
+
+ // iterate over all possible flag combinations
+ for (curmask = 0; curmask <= flagmask; curmask++)
+ if ((curmask & flagmask) == curmask)
+ bevalidate_execute(drcuml, handles, test, paramlist, curmask);
+}
+
+
+/*-------------------------------------------------
+ bevalidate_execute - execute a single instance
+ of a test, generating code and verifying the
+ results
+-------------------------------------------------*/
+
+static void bevalidate_execute(drcuml_state *drcuml, code_handle **handles, const bevalidate_test *test, const parameter *paramlist, UINT8 flagmask)
+{
+ parameter params[ARRAY_LENGTH(test->param)];
+ drcuml_machine_state istate, fstate;
+ instruction testinst;
+ drcuml_block *block;
+ UINT64 *parammem;
+ int numparams;
+
+ // allocate memory for parameters
+ parammem = (UINT64 *)drcuml->cache->alloc_near(sizeof(UINT64) * (ARRAY_LENGTH(test->param) + 1));
+
+ // flush the cache
+ drcuml->reset();
+
+ // start a new block
+ block = drcuml->block_begin(30);
+ UML_HANDLE(block, handles[0]);
+
+ // set up a random initial state
+ bevalidate_initialize_random_state(drcuml, block, &istate);
+
+ // then populate the state with the parameters
+ numparams = bevalidate_populate_state(block, &istate, test, paramlist, params, parammem);
+
+ // generate the code
+ UML_RESTORE(block, &istate);
+ UML_HANDLE(block, handles[1]);
+ switch (numparams)
+ {
+ case 0:
+ block->append(test->opcode(), test->size);
+ break;
+
+ case 1:
+ block->append(test->opcode(), test->size, params[0]);
+ break;
+
+ case 2:
+ block->append(test->opcode(), test->size, params[0], params[1]);
+ break;
+
+ case 3:
+ block->append(test->opcode(), test->size, params[0], params[1], params[2]);
+ break;
+
+ case 4:
+ block->append(test->opcode(), test->size, params[0], params[1], params[2], params[3]);
+ break;
+ }
+ testinst = block->inst[block->nextinst - 1];
+ UML_HANDLE(block, handles[2]);
+ UML_GETFLGS(block, MEM(&parammem[ARRAY_LENGTH(test->param)]), flagmask);
+ UML_SAVE(block, &fstate);
+ UML_EXIT(block, IMM(0));
+
+ // end the block
+ block->end();
+
+ // execute
+ drcuml->execute(*handles[0]);
+
+ // verify the results
+ bevalidate_verify_state(drcuml, &istate, &fstate, test, *(UINT32 *)&parammem[ARRAY_LENGTH(test->param)], params, &testinst, handles[1]->code, handles[2]->code, flagmask);
+
+ // free memory
+ drcuml->cache->dealloc(parammem, sizeof(UINT64) * (ARRAY_LENGTH(test->param) + 1));
+}
+
+
+/*-------------------------------------------------
+ bevalidate_initialize_random_state -
+ initialize the machine state to randomness
+-------------------------------------------------*/
+
+static void bevalidate_initialize_random_state(drcuml_state *drcuml, drcuml_block *block, drcuml_machine_state *state)
+{
+ running_machine &machine = drcuml->device->machine();
+ int regnum;
+
+ // initialize core state to random values
+ state->fmod = machine.rand() & 0x03;
+ state->flags = machine.rand() & 0x1f;
+ state->exp = machine.rand();
+
+ // initialize integer registers to random values
+ for (regnum = 0; regnum < ARRAY_LENGTH(state->r); regnum++)
+ {
+ state->r[regnum].w.h = machine.rand();
+ state->r[regnum].w.l = machine.rand();
+ }
+
+ // initialize float registers to random values
+ for (regnum = 0; regnum < ARRAY_LENGTH(state->f); regnum++)
+ {
+ *(UINT32 *)&state->f[regnum].s.h = machine.rand();
+ *(UINT32 *)&state->f[regnum].s.l = machine.rand();
+ }
+
+ // initialize map variables to random values
+ for (regnum = 0; regnum < MAPVAR_COUNT; regnum++)
+ UML_MAPVAR(block, MVAR(regnum), machine.rand());
+}
+
+
+/*-------------------------------------------------
+ bevalidate_populate_state - populate the
+ machine state with the proper values prior
+ to executing a test
+-------------------------------------------------*/
+
+static int bevalidate_populate_state(drcuml_block *block, drcuml_machine_state *state, const bevalidate_test *test, const parameter *paramlist, parameter *params, UINT64 *parammem)
+{
+ const opcode_info *opinfo = opcode_info_table[test->opcode()];
+ int numparams = ARRAY_LENGTH(test->param);
+ int pnum;
+
+ // copy flags as-is
+ state->flags = test->iflags;
+
+ // iterate over parameters
+ for (pnum = 0; pnum < ARRAY_LENGTH(test->param); pnum++)
+ {
+ int psize = effective_test_psize(opinfo, pnum, test->size, test->param);
+ parameter *curparam = &params[pnum];
+
+ // start with a copy of the parameter from the list
+ *curparam = paramlist[pnum];
+
+ // switch off the type
+ switch (curparam->type)
+ {
+ // immediate parameters: take the value from the test entry
+ case parameter::PTYPE_IMMEDIATE:
+ curparam->value = test->param[pnum];
+ break;
+
+ // register parameters: set the register value in the state and set the parameter value to the register index
+ case parameter::PTYPE_INT_REGISTER:
+ state->r[curparam->value].d = test->param[pnum];
+ curparam->value += REG_I0;
+ break;
+
+ // register parameters: set the register value in the state and set the parameter value to the register index
+ case parameter::PTYPE_FLOAT_REGISTER:
+ state->f[curparam->value].d = test->param[pnum];
+ curparam->value += REG_F0;
+ break;
+
+ // memory parameters: set the memory value in the parameter space and set the parameter value to point to it
+ case parameter::PTYPE_MEMORY:
+ curparam->value = (FPTR)&parammem[pnum];
+ if (psize == 4)
+ *(UINT32 *)(FPTR)curparam->value = test->param[pnum];
+ else
+ *(UINT64 *)(FPTR)curparam->value = test->param[pnum];
+ break;
+
+ // map variables: issue a MAPVAR instruction to set the value and set the parameter value to the mapvar index
+ case parameter::PTYPE_MAPVAR:
+ UML_MAPVAR(block, MVAR(curparam->value), test->param[pnum]);
+ curparam->value += MAPVAR_M0;
+ break;
+
+ // use anything else to count the number of parameters
+ default:
+ numparams = MIN(numparams, pnum);
+ break;
+ }
+ }
+
+ // return the total number of parameters
+ return numparams;
+}
+
+
+/*-------------------------------------------------
+ bevalidate_verify_state - verify the final
+ state after executing a test, and report any
+ discrepancies
+-------------------------------------------------*/
+
+static int bevalidate_verify_state(drcuml_state *drcuml, const drcuml_machine_state *istate, drcuml_machine_state *state, const bevalidate_test *test, UINT32 flags, const parameter *params, const instruction *testinst, drccodeptr codestart, drccodeptr codeend, UINT8 flagmask)
+{
+ const opcode_info *opinfo = opcode_info_table[test->opcode()];
+ UINT8 ireg[REG_I_END - REG_I0] = { 0 };
+ UINT8 freg[REG_F_END - REG_F0] = { 0 };
+ char errorbuf[1024];
+ char *errend = errorbuf;
+ int pnum, regnum;
+
+ *errend = 0;
+
+ // check flags
+ if (flags != (test->flags & flagmask))
+ {
+ errend += sprintf(errend, " Flags ... result:%c%c%c%c%c expected:%c%c%c%c%c\n",
+ (flagmask & FLAG_U) ? ((flags & FLAG_U) ? 'U' : '.') : '-',
+ (flagmask & FLAG_S) ? ((flags & FLAG_S) ? 'S' : '.') : '-',
+ (flagmask & FLAG_Z) ? ((flags & FLAG_Z) ? 'Z' : '.') : '-',
+ (flagmask & FLAG_V) ? ((flags & FLAG_V) ? 'V' : '.') : '-',
+ (flagmask & FLAG_C) ? ((flags & FLAG_C) ? 'C' : '.') : '-',
+ (flagmask & FLAG_U) ? ((test->flags & FLAG_U) ? 'U' : '.') : '-',
+ (flagmask & FLAG_S) ? ((test->flags & FLAG_S) ? 'S' : '.') : '-',
+ (flagmask & FLAG_Z) ? ((test->flags & FLAG_Z) ? 'Z' : '.') : '-',
+ (flagmask & FLAG_V) ? ((test->flags & FLAG_V) ? 'V' : '.') : '-',
+ (flagmask & FLAG_C) ? ((test->flags & FLAG_C) ? 'C' : '.') : '-');
+ }
+
+ // check destination parameters
+ for (pnum = 0; pnum < ARRAY_LENGTH(test->param); pnum++)
+ if (opinfo->param[pnum].output & PIO_OUT)
+ {
+ int psize = effective_test_psize(opinfo, pnum, test->size, test->param);
+ UINT64 mask = U64(0xffffffffffffffff) >> (64 - 8 * psize);
+ UINT64 result = 0;
+
+ // fetch the result from the parameters
+ switch (params[pnum].type)
+ {
+ // integer registers fetch from the state
+ case parameter::PTYPE_INT_REGISTER:
+ ireg[params[pnum].value - REG_I0] = 1;
+ result = state->r[params[pnum].value - REG_I0].d;
+ break;
+
+ // float registers fetch from the state
+ case parameter::PTYPE_FLOAT_REGISTER:
+ freg[params[pnum].value - REG_I0] = 1;
+ result = state->f[params[pnum].value - REG_F0].d;
+ break;
+
+ // memory registers fetch from the memory address
+ case parameter::PTYPE_MEMORY:
+ if (psize == 4)
+ result = *(UINT32 *)(FPTR)params[pnum].value;
+ else
+ result = *(UINT64 *)(FPTR)params[pnum].value;
+ break;
+
+ default:
+ break;
+ }
+
+ // check against the mask
+ if (test->param[pnum] != UNDEFINED_U64 && (result & mask) != (test->param[pnum] & mask))
+ {
+ if ((UINT32)mask == mask)
+ errend += sprintf(errend, " Parameter %d ... result:%08X expected:%08X\n", pnum,
+ (UINT32)(result & mask), (UINT32)(test->param[pnum] & mask));
+ else
+ errend += sprintf(errend, " Parameter %d ... result:%08X%08X expected:%08X%08X\n", pnum,
+ (UINT32)((result & mask) >> 32), (UINT32)(result & mask),
+ (UINT32)((test->param[pnum] & mask) >> 32), (UINT32)(test->param[pnum] & mask));
+ }
+ }
+
+ // check source integer parameters for unexpected alterations
+ for (regnum = 0; regnum < ARRAY_LENGTH(state->r); regnum++)
+ if (ireg[regnum] == 0 && istate->r[regnum].d != state->r[regnum].d)
+ errend += sprintf(errend, " Register i%d ... result:%08X%08X originally:%08X%08X\n", regnum,
+ (UINT32)(state->r[regnum].d >> 32), (UINT32)state->r[regnum].d,
+ (UINT32)(istate->r[regnum].d >> 32), (UINT32)istate->r[regnum].d);
+
+ // check source float parameters for unexpected alterations
+ for (regnum = 0; regnum < ARRAY_LENGTH(state->f); regnum++)
+ if (freg[regnum] == 0 && *(UINT64 *)&istate->f[regnum].d != *(UINT64 *)&state->f[regnum].d)
+ errend += sprintf(errend, " Register f%d ... result:%08X%08X originally:%08X%08X\n", regnum,
+ (UINT32)(*(UINT64 *)&state->f[regnum].d >> 32), (UINT32)*(UINT64 *)&state->f[regnum].d,
+ (UINT32)(*(UINT64 *)&istate->f[regnum].d >> 32), (UINT32)*(UINT64 *)&istate->f[regnum].d);
+
+ // output the error if we have one
+ if (errend != errorbuf)
+ {
+ char disasm[256];
+
+ // disassemble the test instruction
+ testinst->disasm(disasm, drcuml);
+
+ // output a description of what went wrong
+ printf("\n");
+ printf("----------------------------------------------\n");
+ printf("Backend validation error:\n");
+ printf(" %s\n", disasm);
+ printf("\n");
+ printf("Errors:\n");
+ printf("%s\n", errorbuf);
+ fatalerror("Error during validation");
+ }
+ return errend != errorbuf;
+}
+
+#endif
diff --git a/trunk/src/emu/cpu/drcuml.h b/trunk/src/emu/cpu/drcuml.h
new file mode 100644
index 00000000000..6cb0cab285a
--- /dev/null
+++ b/trunk/src/emu/cpu/drcuml.h
@@ -0,0 +1,268 @@
+/***************************************************************************
+
+ drcuml.h
+
+ Universal machine language for dynamic recompiling CPU cores.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __DRCUML_H__
+#define __DRCUML_H__
+
+#include "drccache.h"
+#include "uml.h"
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// these options are passed into drcuml_alloc() and control global behaviors
+const UINT32 DRCUML_OPTION_USE_C = 0x0001; // always use the C back-end
+const UINT32 DRCUML_OPTION_LOG_UML = 0x0002; // generate a UML disassembly of each block
+const UINT32 DRCUML_OPTION_LOG_NATIVE = 0x0004; // tell the back-end to generate a native disassembly of each block
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// determine the type of the native DRC, falling back to C
+#ifndef NATIVE_DRC
+class drcbe_c;
+typedef drcbe_c drcbe_native;
+#else
+class NATIVE_DRC;
+typedef NATIVE_DRC drcbe_native;
+#endif
+
+
+// opaque structure describing UML generation state
+class drcuml_state;
+
+
+// an integer register, with low/high parts
+union drcuml_ireg
+{
+#ifdef LSB_FIRST
+ struct { UINT32 l,h; } w; // 32-bit low, high parts of the register
+#else
+ struct { UINT32 h,l; } w; // 32-bit low, high parts of the register
+#endif
+ UINT64 d; // 64-bit full register
+};
+
+
+// a floating-point register, with low/high parts
+union drcuml_freg
+{
+#ifdef LSB_FIRST
+ struct { float l,h; } s; // 32-bit low, high parts of the register
+#else
+ struct { float h,l; } s; // 32-bit low, high parts of the register
+#endif
+ double d; // 64-bit full register
+};
+
+
+// the collected machine state of a system
+struct drcuml_machine_state
+{
+ drcuml_ireg r[uml::REG_I_COUNT]; // integer registers
+ drcuml_freg f[uml::REG_F_COUNT]; // floating-point registers
+ UINT32 exp; // exception parameter register
+ UINT8 fmod; // fmod (floating-point mode) register
+ UINT8 flags; // flags state
+};
+
+
+// hints and information about the back-end
+struct drcbe_info
+{
+ UINT8 direct_iregs; // number of direct-mapped integer registers
+ UINT8 direct_fregs; // number of direct-mapped floating point registers
+};
+
+
+// a drcuml_block describes a basic block of instructions
+class drcuml_block
+{
+ friend class simple_list<drcuml_block>;
+
+public:
+ // construction/destruction
+ drcuml_block(drcuml_state &drcuml, UINT32 maxinst);
+ ~drcuml_block();
+
+ // getters
+ drcuml_block *next() const { return m_next; }
+ bool inuse() const { return m_inuse; }
+ UINT32 maxinst() const { return m_maxinst; }
+
+ // code generation
+ void begin();
+ void end();
+ void abort();
+
+ // instruction appending
+ uml::instruction &append();
+ void append_comment(const char *format, ...);
+
+ // this class is thrown if abort() is called
+ class abort_compilation : public emu_exception
+ {
+ friend class drcuml_block;
+ abort_compilation() { }
+ };
+
+private:
+ // internal helpers
+ void optimize();
+ void disassemble();
+ const char *get_comment_text(const uml::instruction &inst, astring &comment);
+
+ // internal state
+ drcuml_state & m_drcuml; // pointer back to the owning UML
+ drcuml_block * m_next; // pointer to next block
+ UINT32 m_nextinst; // next instruction to fill in the cache
+ UINT32 m_maxinst; // maximum number of instructions
+ uml::instruction * m_inst; // pointer to the instruction list
+ bool m_inuse; // this block is in use
+};
+
+
+// interface structure for a back-end
+class drcbe_interface
+{
+public:
+ // construction/destruction
+ drcbe_interface(drcuml_state &drcuml, drc_cache &cache, device_t &device);
+ virtual ~drcbe_interface();
+
+ // required overrides
+ virtual void reset() = 0;
+ virtual int execute(uml::code_handle &entry) = 0;
+ virtual void generate(drcuml_block &block, const uml::instruction *instlist, UINT32 numinst) = 0;
+ virtual bool hash_exists(UINT32 mode, UINT32 pc) = 0;
+ virtual void get_info(drcbe_info &info) = 0;
+
+protected:
+ // internal state
+ drcuml_state & m_drcuml; // pointer back to our owner
+ drc_cache & m_cache; // pointer to the cache
+ device_t & m_device; // CPU device we are associated with
+ address_space * m_space[ADDRESS_SPACES];// pointers to CPU's address space
+ drcuml_machine_state & m_state; // state of the machine (in near cache)
+ data_accessors * m_accessors; // memory accessors (in near cache)
+};
+
+
+// structure describing UML generation state
+class drcuml_state
+{
+public:
+ // construction/destruction
+ drcuml_state(device_t &device, drc_cache &cache, UINT32 flags, int modes, int addrbits, int ignorebits);
+ ~drcuml_state();
+
+ // getters
+ device_t &device() const { return m_device; }
+ drc_cache &cache() const { return m_cache; }
+
+ // reset the state
+ void reset();
+ int execute(uml::code_handle &entry) { return m_beintf.execute(entry); }
+
+ // code generation
+ drcuml_block *begin_block(UINT32 maxinst);
+
+ // back-end interface
+ void get_backend_info(drcbe_info &info) { m_beintf.get_info(info); }
+ bool hash_exists(UINT32 mode, UINT32 pc) { return m_beintf.hash_exists(mode, pc); }
+ void generate(drcuml_block &block, uml::instruction *instructions, UINT32 count) { m_beintf.generate(block, instructions, count); }
+
+ // handle management
+ uml::code_handle *handle_alloc(const char *name);
+
+ // symbol management
+ void symbol_add(void *base, UINT32 length, const char *name);
+ const char *symbol_find(void *base, UINT32 *offset = NULL);
+
+ // logging
+ bool logging() const { return (m_umllog != NULL); }
+ void log_printf(const char *format, ...);
+ void log_flush() { if (logging()) fflush(m_umllog); }
+
+private:
+ // symbol class
+ class symbol
+ {
+ friend class drcuml_state;
+ friend class simple_list<symbol>;
+
+ // construction/destruction
+ symbol(void *base, UINT32 length, const char *name)
+ : m_next(NULL),
+ m_base(drccodeptr(base)),
+ m_length(length),
+ m_name(name) { }
+
+ public:
+ // getters
+ symbol *next() const { return m_next; }
+
+ private:
+ // internal state
+ symbol * m_next; // link to the next symbol
+ drccodeptr m_base; // base of the symbol
+ UINT32 m_length; // length of the region covered
+ astring m_name; // name of the symbol
+ };
+
+ // internal state
+ device_t & m_device; // CPU device we are associated with
+ drc_cache & m_cache; // pointer to the codegen cache
+ drcbe_interface & m_beintf; // backend interface pointer
+ FILE * m_umllog; // handle to the UML logfile
+ simple_list<drcuml_block> m_blocklist; // list of active blocks
+ simple_list<uml::code_handle> m_handlelist; // list of active handles
+ simple_list<symbol> m_symlist; // list of symbols
+};
+
+
+
+#endif /* __DRCUML_H__ */
diff --git a/trunk/src/emu/cpu/drcumlsh.h b/trunk/src/emu/cpu/drcumlsh.h
new file mode 100644
index 00000000000..c02ac68a882
--- /dev/null
+++ b/trunk/src/emu/cpu/drcumlsh.h
@@ -0,0 +1,186 @@
+/***************************************************************************
+
+ drcumlsh.h
+
+ Shorthand definitions for the universal machine language.
+
+ Copyright Aaron Giles
+ Released for general non-commercial use under the MAME license
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __DRCUMLSH_H__
+#define __DRCUMLSH_H__
+
+#include "drcuml.h"
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+/* ----- Compile-time Opcodes ----- */
+#define UML_HANDLE(block, _handle) do { block->append().handle(_handle); } while (0)
+#define UML_HASH(block, mode, pc) do { block->append().hash(mode, pc); } while (0)
+#define UML_LABEL(block, _label) do { block->append().label(_label); } while (0)
+#define UML_MAPVAR(block, _mapvar, _value) do { block->append().mapvar(_mapvar, _value); } while (0)
+
+
+/* ----- Control Flow Operations ----- */
+#define UML_NOP(block) do { block->append().nop(); } while (0)
+#define UML_DEBUG(block, pc) do { block->append().debug(pc); } while (0)
+#define UML_EXIT(block, param) do { block->append().exit(param); } while (0)
+#define UML_EXITc(block, cond, param) do { block->append().exit(param, cond); } while (0)
+#define UML_HASHJMP(block, mode, pc, handle) do { block->append().hashjmp(mode, pc, handle); } while (0)
+#define UML_JMP(block, label) do { block->append().jmp(label); } while (0)
+#define UML_JMPc(block, cond, label) do { block->append().jmp(cond, label); } while (0)
+#define UML_JMPH(block, handle) do { block->append().jmph(handle); } while (0)
+#define UML_JMPHc(block, cond, handle) do { block->append().jmph(cond, handle); } while (0)
+#define UML_EXH(block, handle, param) do { block->append().exh(handle, param); } while (0)
+#define UML_EXHc(block, cond, handle, param) do { block->append().exh(cond, handle, param); } while (0)
+#define UML_CALLH(block, handle) do { block->append().callh(handle); } while (0)
+#define UML_CALLHc(block, cond, handle) do { block->append().callh(cond, handle); } while (0)
+#define UML_RET(block) do { block->append().ret(); } while (0)
+#define UML_RETc(block, cond) do { block->append().ret(cond); } while (0)
+#define UML_CALLC(block, func, ptr) do { block->append().callc(func, ptr); } while (0)
+#define UML_CALLCc(block, cond, func, ptr) do { block->append().callc(cond, func, ptr); } while (0)
+#define UML_RECOVER(block, dst, mapvar) do { block->append().recover(dst, mapvar); } while (0)
+
+
+/* ----- Internal Register Operations ----- */
+#define UML_SETFMOD(block, mode) do { block->append().setfmod(mode); } while (0)
+#define UML_GETFMOD(block, dst) do { block->append().getfmod(dst); } while (0)
+#define UML_GETEXP(block, dst) do { block->append().getexp(dst); } while (0)
+#define UML_GETFLGS(block, dst, flags) do { block->append().getflgs(dst, flags); } while (0)
+#define UML_SAVE(block, dst) do { block->append().save(dst); } while (0)
+#define UML_RESTORE(block, src) do { block->append().restore(src); } while (0)
+
+
+/* ----- 32-Bit Integer Operations ----- */
+#define UML_LOAD(block, dst, base, index, size, scale) do { block->append().load(dst, base, index, size, scale); } while (0)
+#define UML_LOADS(block, dst, base, index, size, scale) do { block->append().loads(dst, base, index, size, scale); } while (0)
+#define UML_STORE(block, base, index, src1, size, scale) do { block->append().store(base, index, src1, size, scale); } while (0)
+#define UML_READ(block, dst, src1, size, space) do { block->append().read(dst, src1, size, space); } while (0)
+#define UML_READM(block, dst, src1, mask, size, space) do { block->append().readm(dst, src1, mask, size, space); } while (0)
+#define UML_WRITE(block, dst, src1, size, space) do { block->append().write(dst, src1, size, space); } while (0)
+#define UML_WRITEM(block, dst, src1, mask, size, space) do { block->append().writem(dst, src1, mask, size, space); } while (0)
+#define UML_CARRY(block, src, bitnum) do { block->append().carry(src, bitnum); } while (0)
+#define UML_SETc(block, cond, dst) do { block->append().set(cond, dst); } while (0)
+#define UML_MOV(block, dst, src1) do { block->append().mov(dst, src1); } while (0)
+#define UML_MOVc(block, cond, dst, src1) do { block->append().mov(cond, dst, src1); } while (0)
+#define UML_SEXT(block, dst, src1, size) do { block->append().sext(dst, src1, size); } while (0)
+#define UML_ROLAND(block, dst, src, shift, mask) do { block->append().roland(dst, src, shift, mask); } while (0)
+#define UML_ROLINS(block, dst, src, shift, mask) do { block->append().rolins(dst, src, shift, mask); } while (0)
+#define UML_ADD(block, dst, src1, src2) do { block->append().add(dst, src1, src2); } while (0)
+#define UML_ADDC(block, dst, src1, src2) do { block->append().addc(dst, src1, src2); } while (0)
+#define UML_SUB(block, dst, src1, src2) do { block->append().sub(dst, src1, src2); } while (0)
+#define UML_SUBB(block, dst, src1, src2) do { block->append().subb(dst, src1, src2); } while (0)
+#define UML_CMP(block, src1, src2) do { block->append().cmp(src1, src2); } while (0)
+#define UML_MULU(block, dst, edst, src1, src2) do { block->append().mulu(dst, edst, src1, src2); } while (0)
+#define UML_MULS(block, dst, edst, src1, src2) do { block->append().muls(dst, edst, src1, src2); } while (0)
+#define UML_DIVU(block, dst, edst, src1, src2) do { block->append().divu(dst, edst, src1, src2); } while (0)
+#define UML_DIVS(block, dst, edst, src1, src2) do { block->append().divs(dst, edst, src1, src2); } while (0)
+#define UML_AND(block, dst, src1, src2) do { block->append()._and(dst, src1, src2); } while (0)
+#define UML_TEST(block, src1, src2) do { block->append().test(src1, src2); } while (0)
+#define UML_OR(block, dst, src1, src2) do { block->append()._or(dst, src1, src2); } while (0)
+#define UML_XOR(block, dst, src1, src2) do { block->append()._xor(dst, src1, src2); } while (0)
+#define UML_LZCNT(block, dst, src) do { block->append().lzcnt(dst, src); } while (0)
+#define UML_BSWAP(block, dst, src) do { block->append().bswap(dst, src); } while (0)
+#define UML_SHL(block, dst, src, count) do { block->append().shl(dst, src, count); } while (0)
+#define UML_SHR(block, dst, src, count) do { block->append().shr(dst, src, count); } while (0)
+#define UML_SAR(block, dst, src, count) do { block->append().sar(dst, src, count); } while (0)
+#define UML_ROL(block, dst, src, count) do { block->append().rol(dst, src, count); } while (0)
+#define UML_ROLC(block, dst, src, count) do { block->append().rolc(dst, src, count); } while (0)
+#define UML_ROR(block, dst, src, count) do { block->append().ror(dst, src, count); } while (0)
+#define UML_RORC(block, dst, src, count) do { block->append().rorc(dst, src, count); } while (0)
+
+
+/* ----- 64-Bit Integer Operations ----- */
+#define UML_DLOAD(block, dst, base, index, size, scale) do { block->append().dload(dst, base, index, size, scale); } while (0)
+#define UML_DLOADS(block, dst, base, index, size, scale) do { block->append().dloads(dst, base, index, size, scale); } while (0)
+#define UML_DSTORE(block, base, index, src1, size, scale) do { block->append().dstore(base, index, src1, size, scale); } while (0)
+#define UML_DREAD(block, dst, src1, size, space) do { block->append().dread(dst, src1, size, space); } while (0)
+#define UML_DREADM(block, dst, src1, mask, size, space) do { block->append().dreadm(dst, src1, mask, size, space); } while (0)
+#define UML_DWRITE(block, dst, src1, size, space) do { block->append().dwrite(dst, src1, size, space); } while (0)
+#define UML_DWRITEM(block, dst, src1, mask, size, space) do { block->append().dwritem(dst, src1, mask, size, space); } while (0)
+#define UML_DCARRY(block, src, bitnum) do { block->append().dcarry(src, bitnum); } while (0)
+#define UML_DSETc(block, cond, dst) do { block->append().dset(cond, dst); } while (0)
+#define UML_DMOV(block, dst, src1) do { block->append().dmov(dst, src1); } while (0)
+#define UML_DMOVc(block, cond, dst, src1) do { block->append().dmov(cond, dst, src1); } while (0)
+#define UML_DSEXT(block, dst, src1, size) do { block->append().dsext(dst, src1, size); } while (0)
+#define UML_DROLAND(block, dst, src, shift, mask) do { block->append().droland(dst, src, shift, mask); } while (0)
+#define UML_DROLINS(block, dst, src, shift, mask) do { block->append().drolins(dst, src, shift, mask); } while (0)
+#define UML_DADD(block, dst, src1, src2) do { block->append().dadd(dst, src1, src2); } while (0)
+#define UML_DADDC(block, dst, src1, src2) do { block->append().daddc(dst, src1, src2); } while (0)
+#define UML_DSUB(block, dst, src1, src2) do { block->append().dsub(dst, src1, src2); } while (0)
+#define UML_DSUBB(block, dst, src1, src2) do { block->append().dsubb(dst, src1, src2); } while (0)
+#define UML_DCMP(block, src1, src2) do { block->append().dcmp(src1, src2); } while (0)
+#define UML_DMULU(block, dst, edst, src1, src2) do { block->append().dmulu(dst, edst, src1, src2); } while (0)
+#define UML_DMULS(block, dst, edst, src1, src2) do { block->append().dmuls(dst, edst, src1, src2); } while (0)
+#define UML_DDIVU(block, dst, edst, src1, src2) do { block->append().ddivu(dst, edst, src1, src2); } while (0)
+#define UML_DDIVS(block, dst, edst, src1, src2) do { block->append().ddivs(dst, edst, src1, src2); } while (0)
+#define UML_DAND(block, dst, src1, src2) do { block->append().dand(dst, src1, src2); } while (0)
+#define UML_DTEST(block, src1, src2) do { block->append().dtest(src1, src2); } while (0)
+#define UML_DOR(block, dst, src1, src2) do { block->append().dor(dst, src1, src2); } while (0)
+#define UML_DXOR(block, dst, src1, src2) do { block->append().dxor(dst, src1, src2); } while (0)
+#define UML_DLZCNT(block, dst, src) do { block->append().dlzcnt(dst, src); } while (0)
+#define UML_DBSWAP(block, dst, src) do { block->append().dbswap(dst, src); } while (0)
+#define UML_DSHL(block, dst, src, count) do { block->append().dshl(dst, src, count); } while (0)
+#define UML_DSHR(block, dst, src, count) do { block->append().dshr(dst, src, count); } while (0)
+#define UML_DSAR(block, dst, src, count) do { block->append().dsar(dst, src, count); } while (0)
+#define UML_DROL(block, dst, src, count) do { block->append().drol(dst, src, count); } while (0)
+#define UML_DROLC(block, dst, src, count) do { block->append().drolc(dst, src, count); } while (0)
+#define UML_DROR(block, dst, src, count) do { block->append().dror(dst, src, count); } while (0)
+#define UML_DRORC(block, dst, src, count) do { block->append().drorc(dst, src, count); } while (0)
+
+
+/* ----- 32-bit Floating Point Arithmetic Operations ----- */
+#define UML_FSLOAD(block, dst, base, index) do { block->append().fsload(dst, base, index); } while (0)
+#define UML_FSSTORE(block, base, index, src1) do { block->append().fsstore(base, index, src1); } while (0)
+#define UML_FSREAD(block, dst, src1, space) do { block->append().fsread(dst, src1, AS_##space); } while (0)
+#define UML_FSWRITE(block, dst, src1, space) do { block->append().fswrite(dst, src1, AS_##space); } while (0)
+#define UML_FSMOV(block, dst, src1) do { block->append().fsmov(dst, src1); } while (0)
+#define UML_FSMOVc(block, cond, dst, src1) do { block->append().fsmov(cond, dst, src1); } while (0)
+#define UML_FSTOINT(block, dst, src1, size, round) do { block->append().fstoint(dst, src1, size, round); } while (0)
+#define UML_FSFRINT(block, dst, src1, size) do { block->append().fsfrint(dst, src1, size); } while (0)
+#define UML_FSFRFLT(block, dst, src1, size) do { block->append().fsfrflt(dst, src1, size); } while (0)
+#define UML_FSADD(block, dst, src1, src2) do { block->append().fsadd(dst, src1, src2); } while (0)
+#define UML_FSSUB(block, dst, src1, src2) do { block->append().fssub(dst, src1, src2); } while (0)
+#define UML_FSCMP(block, src1, src2) do { block->append().fscmp(src1, src2); } while (0)
+#define UML_FSMUL(block, dst, src1, src2) do { block->append().fsmul(dst, src1, src2); } while (0)
+#define UML_FSDIV(block, dst, src1, src2) do { block->append().fsdiv(dst, src1, src2); } while (0)
+#define UML_FSNEG(block, dst, src1) do { block->append().fsneg(dst, src1); } while (0)
+#define UML_FSABS(block, dst, src1) do { block->append().fsabs(dst, src1); } while (0)
+#define UML_FSSQRT(block, dst, src1) do { block->append().fssqrt(dst, src1); } while (0)
+#define UML_FSRECIP(block, dst, src1) do { block->append().fsrecip(dst, src1); } while (0)
+#define UML_FSRSQRT(block, dst, src1) do { block->append().fsrsqrt(dst, src1); } while (0)
+
+
+/* ----- 64-bit Floating Point Arithmetic Operations ----- */
+#define UML_FDLOAD(block, dst, base, index) do { block->append().fdload(dst, base, index); } while (0)
+#define UML_FDSTORE(block, base, index, src1) do { block->append().fdstore(base, index, src1); } while (0)
+#define UML_FDREAD(block, dst, src1, space) do { block->append().fdread(dst, src1, AS_##space); } while (0)
+#define UML_FDWRITE(block, dst, src1, space) do { block->append().fdwrite(dst, src1, AS_##space); } while (0)
+#define UML_FDMOV(block, dst, src1) do { block->append().fdmov(dst, src1); } while (0)
+#define UML_FDMOVc(block, cond, dst, src1) do { block->append().fdmov(cond, dst, src1); } while (0)
+#define UML_FDTOINT(block, dst, src1, size, round) do { block->append().fdtoint(dst, src1, size, round); } while (0)
+#define UML_FDFRINT(block, dst, src1, size) do { block->append().fdfrint(dst, src1, size); } while (0)
+#define UML_FDFRFLT(block, dst, src1, size) do { block->append().fdfrflt(dst, src1, size); } while (0)
+#define UML_FDRNDS(block, dst, src1) do { block->append().fdrnds(dst, src1); } while (0)
+#define UML_FDADD(block, dst, src1, src2) do { block->append().fdadd(dst, src1, src2); } while (0)
+#define UML_FDSUB(block, dst, src1, src2) do { block->append().fdsub(dst, src1, src2); } while (0)
+#define UML_FDCMP(block, src1, src2) do { block->append().fdcmp(src1, src2); } while (0)
+#define UML_FDMUL(block, dst, src1, src2) do { block->append().fdmul(dst, src1, src2); } while (0)
+#define UML_FDDIV(block, dst, src1, src2) do { block->append().fddiv(dst, src1, src2); } while (0)
+#define UML_FDNEG(block, dst, src1) do { block->append().fdneg(dst, src1); } while (0)
+#define UML_FDABS(block, dst, src1) do { block->append().fdabs(dst, src1); } while (0)
+#define UML_FDSQRT(block, dst, src1) do { block->append().fdsqrt(dst, src1); } while (0)
+#define UML_FDRECIP(block, dst, src1) do { block->append().fdrecip(dst, src1); } while (0)
+#define UML_FDRSQRT(block, dst, src1) do { block->append().fdrsqrt(dst, src1); } while (0)
+
+
+#endif /* __DRCUMLSH_H__ */
diff --git a/trunk/src/emu/cpu/dsp16/dsp16.c b/trunk/src/emu/cpu/dsp16/dsp16.c
new file mode 100644
index 00000000000..61c160a3366
--- /dev/null
+++ b/trunk/src/emu/cpu/dsp16/dsp16.c
@@ -0,0 +1,215 @@
+/***************************************************************************
+
+ dsp16.h
+
+ WE|AT&T DSP16 series emulator.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "dsp16.h"
+
+
+//**************************************************************************
+// DEVICE INTERFACE
+//**************************************************************************
+
+// device type definition
+const device_type DSP16 = &device_creator<dsp16_device>;
+
+
+//-------------------------------------------------
+// dsp16_device - constructor
+//-------------------------------------------------
+
+dsp16_device::dsp16_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : cpu_device(mconfig, DSP16, "DSP16", tag, owner, clock),
+ m_program_config("program", ENDIANNESS_LITTLE, 16, 16, -1),
+ m_pc(0),
+ m_ppc(0),
+ m_icount(0)
+{
+ // Allocate & setup
+}
+
+
+
+//-------------------------------------------------
+// device_start - start up the device
+//-------------------------------------------------
+
+void dsp16_device::device_start()
+{
+ // get our address spaces
+ m_program = space(AS_PROGRAM);
+ m_direct = &m_program->direct();
+
+ save_item(NAME(m_pc));
+
+ // register state with the debugger
+ state_add(DSP16_PC, "PC", m_pc);
+
+ // set our instruction counter
+ m_icountptr = &m_icount;
+}
+
+
+//-------------------------------------------------
+// device_reset - reset the device
+//-------------------------------------------------
+
+void dsp16_device::device_reset()
+{
+ m_pc = m_ppc = 0x0000;
+}
+
+
+//-------------------------------------------------
+// memory_space_config - return the configuration
+// of the specified address space, or NULL if
+// the space doesn't exist
+//-------------------------------------------------
+
+const address_space_config *dsp16_device::memory_space_config(address_spacenum spacenum) const
+{
+ return (spacenum == AS_PROGRAM) ? &m_program_config : NULL;
+}
+
+
+//-------------------------------------------------
+// state_import - import state into the device,
+// after it has been set
+//-------------------------------------------------
+
+void dsp16_device::state_import(const device_state_entry &entry)
+{
+
+}
+
+
+//-------------------------------------------------
+// state_string_export - export state as a string
+// for the debugger
+//-------------------------------------------------
+
+void dsp16_device::state_string_export(const device_state_entry &entry, astring &string)
+{
+ string.printf("");
+}
+
+
+//-------------------------------------------------
+// disasm_min_opcode_bytes - return the length
+// of the shortest instruction, in bytes
+//-------------------------------------------------
+
+UINT32 dsp16_device::disasm_min_opcode_bytes() const
+{
+ return 2;
+}
+
+
+//-------------------------------------------------
+// disasm_max_opcode_bytes - return the length
+// of the longest instruction, in bytes
+//-------------------------------------------------
+
+UINT32 dsp16_device::disasm_max_opcode_bytes() const
+{
+ return 4;
+}
+
+
+//-------------------------------------------------
+// disasm_disassemble - call the disassembly
+// helper function
+//-------------------------------------------------
+
+offs_t dsp16_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
+{
+ extern CPU_DISASSEMBLE( dsp16 );
+ return CPU_DISASSEMBLE_NAME(dsp16)(NULL, buffer, pc, oprom, opram, 0);
+}
+
+
+
+/***************************************************************************
+ MEMORY ACCESSORS
+***************************************************************************/
+
+inline UINT32 dsp16_device::program_read(UINT32 addr)
+{
+ return m_program->read_dword(addr << 1);
+}
+
+inline void dsp16_device::program_write(UINT32 addr, UINT32 data)
+{
+ m_program->write_dword(addr << 1, data & 0xffff);
+}
+
+inline UINT32 dsp16_device::opcode_read()
+{
+ return m_direct->read_decrypted_dword(m_pc << 1);
+}
+
+
+/***************************************************************************
+ CORE EXECUTION LOOP
+***************************************************************************/
+
+//-------------------------------------------------
+// execute_min_cycles - return minimum number of
+// cycles it takes for one instruction to execute
+//-------------------------------------------------
+
+UINT32 dsp16_device::execute_min_cycles() const
+{
+ return 1;
+}
+
+
+//-------------------------------------------------
+// execute_max_cycles - return maximum number of
+// cycles it takes for one instruction to execute
+//-------------------------------------------------
+
+UINT32 dsp16_device::execute_max_cycles() const
+{
+ return 1;
+}
+
+
+//-------------------------------------------------
+// execute_input_lines - return the number of
+// input/interrupt lines
+//-------------------------------------------------
+
+UINT32 dsp16_device::execute_input_lines() const
+{
+ return 1; // TODO
+}
+
+
+void dsp16_device::execute_set_input(int inputnum, int state)
+{
+}
+
+
+void dsp16_device::execute_run()
+{
+ bool check_debugger = ((device_t::machine().debug_flags & DEBUG_FLAG_ENABLED) != 0);
+
+ do
+ {
+ // debugging
+ m_ppc = m_pc; // copy PC to previous PC
+ if (check_debugger)
+ debugger_instruction_hook(this, m_pc);
+
+ // instruction fetch
+ //UINT16 op = opcode_read();
+
+ m_icount--;
+ } while (m_icount > 0);
+}
diff --git a/trunk/src/emu/cpu/dsp16/dsp16.h b/trunk/src/emu/cpu/dsp16/dsp16.h
new file mode 100644
index 00000000000..ff063ba8164
--- /dev/null
+++ b/trunk/src/emu/cpu/dsp16/dsp16.h
@@ -0,0 +1,100 @@
+/***************************************************************************
+
+ dsp16.h
+
+ WE|AT&T DSP16 series emulator.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __DSP16_H__
+#define __DSP16_H__
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+//#define MCFG_DSP16_CONFIG(_config)
+// dsp16_device::static_set_config(*device, _config);
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> dsp16_device
+
+class dsp16_device : public cpu_device
+{
+public:
+ // construction/destruction
+ dsp16_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // public interfaces
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ // device_execute_interface overrides
+ virtual UINT32 execute_min_cycles() const;
+ virtual UINT32 execute_max_cycles() const;
+ virtual UINT32 execute_input_lines() const;
+ virtual void execute_run();
+ virtual void execute_set_input(int inputnum, int state);
+
+ // device_memory_interface overrides
+ virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const;
+
+ // device_state_interface overrides
+ virtual void state_import(const device_state_entry &entry);
+ virtual void state_export(const device_state_entry &entry);
+ virtual void state_string_export(const device_state_entry &entry, astring &string);
+
+ // device_disasm_interface overrides
+ virtual UINT32 disasm_min_opcode_bytes() const;
+ virtual UINT32 disasm_max_opcode_bytes() const;
+ virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);
+
+ // address spaces
+ const address_space_config m_program_config;
+
+ // CPU registers
+ UINT16 m_pc;
+
+ // internal stuff
+ UINT16 m_ppc;
+
+ // memory access
+ inline UINT32 program_read(UINT32 addr);
+ inline void program_write(UINT32 addr, UINT32 data);
+ inline UINT32 opcode_read();
+
+ // address spaces
+ address_space* m_program;
+ direct_read_data* m_direct;
+
+ // other internal states
+ int m_icount;
+};
+
+
+// device type definition
+extern const device_type DSP16;
+
+
+/***************************************************************************
+ REGISTER ENUMERATION
+***************************************************************************/
+
+enum
+{
+ DSP16_PC
+};
+
+
+#endif /* __DSP16_H__ */
diff --git a/trunk/src/emu/cpu/dsp16/dsp16dis.c b/trunk/src/emu/cpu/dsp16/dsp16dis.c
new file mode 100644
index 00000000000..1c8ab0f0c7a
--- /dev/null
+++ b/trunk/src/emu/cpu/dsp16/dsp16dis.c
@@ -0,0 +1,567 @@
+#include "emu.h"
+#include "dsp16.h"
+
+astring disasmF1Field(const UINT8& F1, const UINT8& D, const UINT8& S)
+{
+ astring ret = "";
+ switch (F1)
+ {
+ case 0x00: ret.printf("a%d = p, p = x*y", D); break;
+ case 0x01: ret.printf("a%d = a%d + p, p = x*y", D, S); break;
+ case 0x02: ret.printf("p = x*y"); break;
+ case 0x03: ret.printf("a%d = a%d - p, p = x*y", D, S); break;
+ case 0x04: ret.printf("a$d = p", D); break;
+ case 0x05: ret.printf("a%d = a%d + p", D, S); break;
+ case 0x06: ret.printf("NOP"); break;
+ case 0x07: ret.printf("a%d = a%d - p", D, S); break;
+ case 0x08: ret.printf("a%d = a%d | y", D, S); break;
+ case 0x09: ret.printf("a%d = a%d ^ y", D, S); break;
+ case 0x0a: ret.printf("a%d & y", S); break;
+ case 0x0b: ret.printf("a%d - y", S); break;
+ case 0x0c: ret.printf("a%d = y", D); break;
+ case 0x0d: ret.printf("a%d = a%d + y", D, S); break;
+ case 0x0e: ret.printf("a%d = a%d & y", D, S); break;
+ case 0x0f: ret.printf("a%d = a%d - y", D, S); break;
+
+ default: return "UNKNOWN";
+ }
+ return ret;
+}
+
+astring disasmYField(const UINT8& Y)
+{
+ switch (Y)
+ {
+ case 0x00: return "*r0";
+ case 0x01: return "*r0++";
+ case 0x02: return "*r0--";
+ case 0x03: return "*r0++j";
+
+ case 0x04: return "*r1";
+ case 0x05: return "*r1++";
+ case 0x06: return "*r1--";
+ case 0x07: return "*r1++j";
+
+ case 0x08: return "*r2";
+ case 0x09: return "*r2++";
+ case 0x0a: return "*r2--";
+ case 0x0b: return "*r2++j";
+
+ case 0x0c: return "*r3";
+ case 0x0d: return "*r3++";
+ case 0x0e: return "*r3--";
+ case 0x0f: return "*r3++j";
+
+ default: return "UNKNOWN";
+ }
+ return "";
+}
+
+astring disasmZField(const UINT8& Z)
+{
+ switch (Z)
+ {
+ case 0x00: return "*r0zp";
+ case 0x01: return "*r0pz";
+ case 0x02: return "*r0m2";
+ case 0x03: return "*r0jk";
+
+ case 0x04: return "*r1zp";
+ case 0x05: return "*r1pz";
+ case 0x06: return "*r1m2";
+ case 0x07: return "*r1jk";
+
+ case 0x08: return "*r2zp";
+ case 0x09: return "*r2pz";
+ case 0x0a: return "*r2m2";
+ case 0x0b: return "*r2jk";
+
+ case 0x0c: return "*r3zp";
+ case 0x0d: return "*r3pz";
+ case 0x0e: return "*r3m2";
+ case 0x0f: return "*r3jk";
+
+ default: return "UNKNOWN";
+ }
+ return "";
+}
+
+astring disasmF2Field(const UINT8& F2, const UINT8& D, const UINT8& S)
+{
+ astring ret = "";
+ switch (F2)
+ {
+ case 0x00: ret.printf("a%d = a%d >> 1", D, S); break;
+ case 0x01: ret.printf("a%d = a%d << 1", D, S); break;
+ case 0x02: ret.printf("a%d = a%d >> 4", D, S); break;
+ case 0x03: ret.printf("a%d = a%d << 4", D, S); break;
+ case 0x04: ret.printf("a%d = a%d >> 8", D, S); break;
+ case 0x05: ret.printf("a%d = a%d << 8", D, S); break;
+ case 0x06: ret.printf("a%d = a%d >> 16", D, S); break;
+ case 0x07: ret.printf("a%d = a%d << 16", D, S); break;
+
+ case 0x08: ret.printf("a%d = p", D); break;
+ case 0x09: ret.printf("a%dh = a%dh + 1", D, S); break;
+ case 0x0a: ret.printf("RESERVED"); break;
+ case 0x0b: ret.printf("a%d = rnd(a%d)", D, S); break;
+ case 0x0c: ret.printf("a%d = y", D); break;
+ case 0x0d: ret.printf("a%d = a%d + 1", D, S); break;
+ case 0x0e: ret.printf("a%d = a%d", D, S); break;
+ case 0x0f: ret.printf("a%d = -a%d", D, S); break;
+
+ default: return "UNKNOWN";
+ }
+ return "";
+}
+
+astring disasmCONField(const UINT8& CON)
+{
+ switch (CON)
+ {
+ case 0x00: return "mi";
+ case 0x01: return "pl";
+ case 0x02: return "eq";
+ case 0x03: return "ne";
+ case 0x04: return "lvs";
+ case 0x05: return "lvc";
+ case 0x06: return "mvs";
+ case 0x07: return "mvc";
+ case 0x08: return "heads";
+ case 0x09: return "tails";
+ case 0x0a: return "c0ge";
+ case 0x0b: return "c0lt";
+ case 0x0c: return "c1ge";
+ case 0x0d: return "c1lt";
+ case 0x0e: return "true";
+ case 0x0f: return "false";
+ case 0x10: return "gt";
+ case 0x11: return "le";
+
+ default: return "RESERVED";
+ }
+ return "";
+}
+
+astring disasmBField(const UINT8& B)
+{
+ switch (B)
+ {
+ case 0x00: return "return";
+ case 0x01: return "ireturn";
+ case 0x02: return "goto pt";
+ case 0x03: return "call pt";
+ case 0x04:
+ case 0x05:
+ case 0x06:
+ case 0x07: return "RESERVED";
+
+ default: return "UNKNOWN";
+ }
+ return "";
+}
+
+astring disasmRImmediateField(const UINT8& R)
+{
+ switch (R)
+ {
+ case 0x00: return "j";
+ case 0x01: return "k";
+ case 0x02: return "rb";
+ case 0x03: return "re";
+ case 0x04: return "r0";
+ case 0x05: return "r1";
+ case 0x06: return "r2";
+ case 0x07: return "r3";
+
+ default: return "UNKNOWN";
+ }
+ return "";
+}
+
+astring disasmRField(const UINT8& R)
+{
+ switch (R)
+ {
+ case 0x00: return "r0";
+ case 0x01: return "r1";
+ case 0x02: return "r2";
+ case 0x03: return "r3";
+ case 0x04: return "j";
+ case 0x05: return "k";
+ case 0x06: return "rb";
+ case 0x07: return "re";
+ case 0x08: return "pt";
+ case 0x09: return "pr";
+ case 0x0a: return "pi";
+ case 0x0b: return "i";
+
+ case 0x10: return "x";
+ case 0x11: return "y";
+ case 0x12: return "yl";
+ case 0x13: return "auc";
+ case 0x14: return "psw";
+ case 0x15: return "c0";
+ case 0x16: return "c1";
+ case 0x17: return "c2";
+ case 0x18: return "soic";
+ case 0x19: return "srta";
+ case 0x1a: return "sdx";
+ case 0x1b: return "tdms";
+ case 0x1c: return "pioc";
+ case 0x1d: return "pdx0";
+ case 0x1e: return "pdx1";
+
+ default: return "RESERVED";
+ }
+ return "";
+}
+
+astring disasmIField(const UINT8& I)
+{
+ switch (I)
+ {
+ case 0x00: return "r0/j";
+ case 0x01: return "r1/k";
+ case 0x02: return "r2/rb";
+ case 0x03: return "r3/re";
+
+ default: return "UNKNOWN";
+ }
+ return "";
+}
+
+bool disasmSIField(const UINT8& SI)
+{
+ switch (SI)
+ {
+ case 0x00: return 0; // Not a software interrupt
+ case 0x01: return 1; // Software Interrupt
+ }
+ return false;
+}
+
+
+/* execute instructions on this CPU until icount expires */
+CPU_DISASSEMBLE( dsp16a )
+{
+ UINT8 opSize = 1;
+ UINT32 dasmflags = 0;
+ UINT16 op = oprom[0] | (oprom[1] << 8);
+ UINT16 op2 = oprom[2] | (oprom[3] << 8);
+
+ // TODO: Test for previous "if CON" instruction and tab the next instruction in?
+
+ const UINT8 opcode = (op >> 11) & 0x1f;
+ switch(opcode)
+ {
+ // Format 1: Multiply/ALU Read/Write Group
+ case 0x06:
+ {
+ // F1, Y
+ const UINT8 Y = (op & 0x000f);
+ const UINT8 S = (op & 0x0200) >> 9;
+ const UINT8 D = (op & 0x0400) >> 10;
+ const UINT8 F1 = (op & 0x01e0) >> 5;
+ astring yString = disasmYField(Y);
+ astring fString = disasmF1Field(F1, D, S);
+ sprintf(buffer, "%s, %s", fString.cstr(), yString.cstr());
+ break;
+ }
+ case 0x04: case 0x1c:
+ {
+ // F1 Y=a0[1] | F1 Y=a1[1]
+ const UINT8 Y = (op & 0x000f);
+ const UINT8 S = (op & 0x0200) >> 9;
+ const UINT8 D = (op & 0x0400) >> 10;
+ const UINT8 F1 = (op & 0x01e0) >> 5;
+ astring yString = disasmYField(Y);
+ astring fString = disasmF1Field(F1, D, S);
+ astring aString = (opcode == 0x1c) ? "a0" : "a1";
+ sprintf(buffer, "%s = %s, %s", yString.cstr(), aString.cstr(), fString.cstr());
+ break;
+ }
+ case 0x16:
+ {
+ // F1, x = Y
+ const UINT8 Y = (op & 0x000f);
+ const UINT8 S = (op & 0x0200) >> 9;
+ const UINT8 D = (op & 0x0400) >> 10;
+ const UINT8 F1 = (op & 0x01e0) >> 5;
+ astring yString = disasmYField(Y);
+ astring fString = disasmF1Field(F1, D, S);
+ sprintf(buffer, "%s, x = %s", fString.cstr(), yString.cstr());
+ break;
+ }
+ case 0x17:
+ {
+ // F1, y[l] = Y
+ const UINT8 Y = (op & 0x000f);
+ const UINT8 X = (op & 0x0010) >> 4;
+ const UINT8 S = (op & 0x0200) >> 9;
+ const UINT8 D = (op & 0x0400) >> 10;
+ const UINT8 F1 = (op & 0x01e0) >> 5;
+ astring yString = disasmYField(Y);
+ astring fString = disasmF1Field(F1, D, S);
+ astring xString = (X ? "y" : "y1");
+ sprintf(buffer, "%s, %s = %s", fString.cstr(), xString.cstr(), yString.cstr());
+ break;
+ }
+ case 0x1f:
+ {
+ // F1, y = Y, x = *pt++[i]
+ const UINT8 Y = (op & 0x000f);
+ const UINT8 X = (op & 0x0010) >> 4;
+ const UINT8 S = (op & 0x0200) >> 9;
+ const UINT8 D = (op & 0x0400) >> 10;
+ const UINT8 F1 = (op & 0x01e0) >> 5;
+ astring yString = disasmYField(Y);
+ astring fString = disasmF1Field(F1, D, S);
+ astring xString = (X ? "*pt++i" : "*pt++");
+ sprintf(buffer, "%s, y = %s, x = %s", fString.cstr(), yString.cstr(), xString.cstr());
+ break;
+ }
+ case 0x19: case 0x1b:
+ {
+ // F1, y = a0|1, x = *pt++[i]
+ const UINT8 Y = (op & 0x000f);
+ const UINT8 X = (op & 0x0010) >> 4;
+ const UINT8 S = (op & 0x0200) >> 9;
+ const UINT8 D = (op & 0x0400) >> 10;
+ const UINT8 F1 = (op & 0x01e0) >> 5;
+ astring fString = disasmF1Field(F1, D, S);
+ astring xString = (X ? "*pt++i" : "*pt++");
+ astring aString = (opcode == 0x19) ? "a0" : "a1";
+ sprintf(buffer, "%s, y = %s, x = %s", fString.cstr(), aString.cstr(), xString.cstr());
+ if (Y != 0x00) sprintf(buffer, "UNKNOWN");
+ break;
+ }
+ case 0x14:
+ {
+ // F1, Y = y[1]
+ const UINT8 Y = (op & 0x000f);
+ const UINT8 X = (op & 0x0010) >> 4;
+ const UINT8 S = (op & 0x0200) >> 9;
+ const UINT8 D = (op & 0x0400) >> 10;
+ const UINT8 F1 = (op & 0x01e0) >> 5;
+ astring yString = disasmYField(Y);
+ astring xString = (X ? "y" : "y1");
+ astring fString = disasmF1Field(F1, D, S);
+ sprintf(buffer, "%s, %s = %s", fString.cstr(), yString.cstr(), xString.cstr());
+ break;
+ }
+
+ // Format 1a: Multiply/ALU Read/Write Group (major typo in docs on p3-51)
+ case 0x07:
+ {
+ // F1, At[1] = Y
+ const UINT8 Y = (op & 0x000f);
+ const UINT8 S = (op & 0x0200) >> 9;
+ const UINT8 aT = (op & 0x0400) >> 10;
+ const UINT8 F1 = (op & 0x01e0) >> 5;
+ astring yString = disasmYField(Y);
+ astring atString = (aT ? "a0" : "a1");
+ astring fString = disasmF1Field(F1, aT, S);
+ sprintf(buffer, "%s, %s = %s", fString.cstr(), atString.cstr(), yString.cstr());
+ break;
+ }
+
+ // Format 2: Multiply/ALU Read/Write Group
+ case 0x15:
+ {
+ // F1, Z : y[1]
+ const UINT8 Z = (op & 0x000f);
+ const UINT8 X = (op & 0x0010) >> 4;
+ const UINT8 S = (op & 0x0200) >> 9;
+ const UINT8 D = (op & 0x0400) >> 10;
+ const UINT8 F1 = (op & 0x01e0) >> 5;
+ astring zString = disasmZField(Z);
+ astring xString = (X ? "y" : "y1");
+ astring fString = disasmF1Field(F1, D, S);
+ sprintf(buffer, "%s, %s <=> %s", fString.cstr(), xString.cstr(), zString.cstr());
+ break;
+ }
+ case 0x1d:
+ {
+ // F1, Z : y, x=*pt++[i]
+ const UINT8 Z = (op & 0x000f);
+ const UINT8 X = (op & 0x0010) >> 4;
+ const UINT8 S = (op & 0x0200) >> 9;
+ const UINT8 D = (op & 0x0400) >> 10;
+ const UINT8 F1 = (op & 0x01e0) >> 5;
+ astring zString = disasmZField(Z);
+ astring xString = (X ? "*pt++i" : "*pt++");
+ astring fString = disasmF1Field(F1, D, S);
+ sprintf(buffer, "%s, %s <=> y, x = %s", fString.cstr(), zString.cstr(), xString.cstr());
+ break;
+ }
+
+ // Format 2a: Multiply/ALU Read/Write Group
+ case 0x05:
+ {
+ // F1, Z : aT[1]
+ const UINT8 Z = (op & 0x000f);
+ const UINT8 X = (op & 0x0010) >> 4;
+ const UINT8 S = (op & 0x0200) >> 9;
+ const UINT8 aT = (op & 0x0400) >> 10;
+ const UINT8 F1 = (op & 0x01e0) >> 5;
+ astring zString = disasmZField(Z);
+ astring atString = (aT ? "a0" : "a1");
+ atString += X ? "" : "1"; // TODO: Figure out unclear wording.
+ astring fString = disasmF1Field(F1, aT, S);
+ sprintf(buffer, "%s, %s <=> %s", fString.cstr(), zString.cstr(), atString.cstr());
+ break;
+ }
+
+ // Format 3: Special Functions
+ case 0x12:
+ case 0x13:
+ {
+ // if|ifc CON F2
+ const UINT8 CON = (op & 0x001f);
+ const UINT8 S = (op & 0x0200) >> 9;
+ const UINT8 D = (op & 0x0400) >> 10;
+ const UINT8 F2 = (op & 0x01e0) >> 5;
+ astring fString = disasmF2Field(F2, D, S);
+ astring conString = disasmCONField(CON);
+ if (op & 0x0800) sprintf(buffer, "if %s : %s", conString.cstr(), fString.cstr());
+ else sprintf(buffer, "ifc %s : %s", conString.cstr(), fString.cstr());
+ break;
+ }
+
+ // Format 4: Branch Direct Group
+ case 0x00: case 0x01:
+ case 0x10: case 0x11:
+ {
+ // goto|call JA
+ const UINT16 JA = (op & 0x0fff) | (pc & 0xf000);
+ if (op & 0x8000) sprintf(buffer, "call 0x%04x", JA);
+ else sprintf(buffer, "goto 0x%04x", JA);
+ break;
+ }
+
+ // Format 5: Branch Indirect Group
+ case 0x18:
+ {
+ // goto B
+ const UINT8 B = (op & 0x0700) >> 8;
+ astring bString = disasmBField(B);
+ sprintf(buffer, "%s", bString.cstr());
+ break;
+ }
+
+ // Format 6: Contitional Branch Qualifier/Software Interrupt (icall)
+ case 0x1a:
+ {
+ // if CON [goto/call/return]
+ const UINT8 CON = (op & 0x001f);
+ astring conString = disasmCONField(CON);
+ sprintf(buffer, "if %s:", conString.cstr());
+ // TODO: Test for invalid ops
+ // icall
+ if (op == 0xd40e) sprintf(buffer, "icall");
+ break;
+ }
+
+ // Format 7: Data Move Group
+ case 0x09: case 0x0b:
+ {
+ // R = aS
+ const UINT8 R = (op & 0x03f0) >> 4;
+ const UINT8 S = (op & 0x1000) >> 12;
+ astring rString = disasmRField(R);
+ sprintf(buffer, "%s = %s", rString.cstr(), (S ? "a1" : "a0"));
+ break;
+ }
+ case 0x08:
+ {
+ // aT = R
+ const UINT8 R = (op & 0x03f0) >> 4;
+ const UINT8 aT = (op & 0x0400) >> 10;
+ astring rString = disasmRField(R);
+ sprintf(buffer, "%s = %s", (aT ? "a0" : "a1"), rString.cstr());
+ break;
+ }
+ case 0x0f:
+ {
+ // R = Y
+ const UINT8 Y = (op & 0x000f);
+ const UINT8 R = (op & 0x03f0) >> 4;
+ astring yString = disasmYField(Y);
+ astring rString = disasmRField(R);
+ sprintf(buffer, "%s = %s", rString.cstr(), yString.cstr());
+ // TODO: Special case the R == [y, y1, or x] case
+ break;
+ }
+ case 0x0c:
+ {
+ // Y = R
+ const UINT8 Y = (op & 0x000f);
+ const UINT8 R = (op & 0x03f0) >> 4;
+ astring yString = disasmYField(Y);
+ astring rString = disasmRField(R);
+ sprintf(buffer, "%s = %s", yString.cstr(), rString.cstr());
+ break;
+ }
+ case 0x0d:
+ {
+ // Z : R
+ const UINT8 Z = (op & 0x000f);
+ const UINT8 R = (op & 0x03f0) >> 4;
+ astring zString = disasmZField(Z);
+ astring rString = disasmRField(R);
+ sprintf(buffer, "%s <=> %s", zString.cstr(), rString.cstr());
+ break;
+ }
+
+ // Format 8: Data Move (immediate operand - 2 words)
+ case 0x0a:
+ {
+ // R = N
+ const UINT8 R = (op & 0x03f0) >> 4;
+ astring rString = disasmRField(R);
+ sprintf(buffer, "%s = 0x%x", rString.cstr(), op2);
+ opSize = 2;
+ break;
+ }
+
+ // Format 9: Short Immediate Group
+ case 0x02: case 0x03:
+ {
+ // R = M
+ const UINT8 M = (op & 0x00ff);
+ const UINT8 R = (op & 0x0e00) >> 9;
+ astring rString = disasmRImmediateField(R);
+ sprintf(buffer, "%s = 0x%02x", rString.cstr(), M);
+ break;
+ }
+
+ // Format 10: do - redo
+ case 0x0e:
+ {
+ // do|redo K
+ const UINT8 K = (op & 0x007f);
+ const UINT8 NI = (op & 0x0780) >> 7;
+ sprintf(buffer, "do (next %d inst) %d times", NI, K);
+ // TODO: Limits on K & NI
+ if (NI == 0x00)
+ sprintf(buffer, "redo %d\n", K);
+ break;
+ }
+
+ // RESERVED
+ case 0x1e:
+ {
+ sprintf(buffer, "RESERVED");
+ break;
+ }
+
+ // UNKNOWN
+ default:
+ {
+ sprintf(buffer, "UNKNOWN");
+ break;
+ }
+ }
+
+ return opSize | dasmflags | DASMFLAG_SUPPORTED;
+}
diff --git a/trunk/src/emu/cpu/dsp32/dsp32.c b/trunk/src/emu/cpu/dsp32/dsp32.c
new file mode 100644
index 00000000000..5bd0cd810fb
--- /dev/null
+++ b/trunk/src/emu/cpu/dsp32/dsp32.c
@@ -0,0 +1,889 @@
+/***************************************************************************
+
+ dsp32.c
+ Core implementation for the portable DSP32 emulator.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+****************************************************************************
+
+ Important note:
+
+ At this time, the emulator is rather incomplete. However, it is
+ sufficiently complete to run both Race Drivin' and Hard Drivin's
+ Airborne, which is all I was after.
+
+ Things that still need to be implemented:
+
+ * interrupts
+ * carry-reverse add operations
+ * do loops
+ * ieee/dsp conversions
+ * input/output conversion
+ * serial I/O
+
+ In addition, there are several optimizations enabled which make
+ assumptions about the code which may not be valid for other
+ applications. Check dsp32ops.c for details.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "dsp32.h"
+
+
+//**************************************************************************
+// DEBUGGING
+//**************************************************************************
+
+#define DETECT_MISALIGNED_MEMORY 0
+
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// internal register numbering for PIO registers
+#define PIO_PAR 0
+#define PIO_PDR 1
+#define PIO_EMR 2
+#define PIO_ESR 3
+#define PIO_PCR 4
+#define PIO_PIR 5
+#define PIO_PARE 6
+#define PIO_PDR2 7
+#define PIO_RESERVED 8
+
+#define UPPER (0x00ff << 8)
+#define LOWER (0xff00 << 8)
+
+// bits in the PCR register
+#define PCR_RESET 0x001
+#define PCR_REGMAP 0x002
+#define PCR_ENI 0x004
+#define PCR_DMA 0x008
+#define PCR_AUTO 0x010
+#define PCR_PDFs 0x020
+#define PCR_PIFs 0x040
+#define PCR_RES 0x080
+#define PCR_DMA32 0x100
+#define PCR_PIO16 0x200
+#define PCR_FLG 0x400
+
+// internal flag bits
+#define UFLAGBIT 1
+#define VFLAGBIT 2
+
+
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+// register mapping
+#define R0 m_r[0]
+#define R1 m_r[1]
+#define R2 m_r[2]
+#define R3 m_r[3]
+#define R4 m_r[4]
+#define R5 m_r[5]
+#define R6 m_r[6]
+#define R7 m_r[7]
+#define R8 m_r[8]
+#define R9 m_r[9]
+#define R10 m_r[10]
+#define R11 m_r[11]
+#define R12 m_r[12]
+#define R13 m_r[13]
+#define R14 m_r[14]
+#define PC m_r[15]
+#define R0_ALT m_r[16]
+#define R15 m_r[17]
+#define R16 m_r[18]
+#define R17 m_r[19]
+#define R18 m_r[20]
+#define R19 m_r[21]
+#define RMM m_r[22]
+#define RPP m_r[23]
+#define R20 m_r[24]
+#define R21 m_r[25]
+#define DAUC m_r[26]
+#define IOC m_r[27]
+#define R22 m_r[29]
+#define PCSH m_r[30]
+
+#define A0 m_a[0]
+#define A1 m_a[1]
+#define A2 m_a[2]
+#define A3 m_a[3]
+#define A_0 m_a[4]
+#define A_1 m_a[5]
+
+#define zFLAG ((m_nzcflags & 0xffffff) == 0)
+#define nFLAG ((m_nzcflags & 0x800000) != 0)
+#define cFLAG ((m_nzcflags & 0x1000000) != 0)
+#define vFLAG ((m_vflags & 0x800000) != 0)
+#define ZFLAG (m_NZflags == 0)
+#define NFLAG (m_NZflags < 0)
+#define UFLAG (m_VUflags & UFLAGBIT)
+#define VFLAG (m_VUflags & VFLAGBIT)
+
+
+
+//**************************************************************************
+// DEVICE INTERFACE
+//**************************************************************************
+
+const device_type DSP32C = &device_creator<dsp32c_device>;
+
+//-------------------------------------------------
+// dsp32c_device - constructor
+//-------------------------------------------------
+
+dsp32c_device::dsp32c_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : cpu_device(mconfig, DSP32C, "DSP32C", tag, owner, clock),
+ m_program_config("program", ENDIANNESS_LITTLE, 32, 24),
+ m_pin(0),
+ m_pout(0),
+ m_ivtp(0),
+ m_nzcflags(0),
+ m_vflags(0),
+ m_NZflags(0),
+ m_VUflags(0),
+ m_abuf_index(0),
+ m_mbuf_index(0),
+ m_par(0),
+ m_pare(0),
+ m_pdr(0),
+ m_pdr2(0),
+ m_pir(0),
+ m_pcr(0),
+ m_emr(0),
+ m_esr(0),
+ m_pcw(0),
+ m_piop(0),
+ m_ibuf(0),
+ m_isr(0),
+ m_obuf(0),
+ m_osr(0),
+ m_iotemp(0),
+ m_lastp(0),
+ m_icount(0),
+ m_lastpins(0),
+ m_ppc(0),
+ m_program(NULL),
+ m_direct(NULL)
+{
+ m_output_pins_changed = NULL;
+
+ // set our instruction counter
+ m_icountptr = &m_icount;
+}
+
+
+//-------------------------------------------------
+// static_set_config - set the configuration
+// structure
+//-------------------------------------------------
+
+void dsp32c_device::static_set_config(device_t &device, const dsp32_config &config)
+{
+ dsp32c_device &dsp = downcast<dsp32c_device &>(device);
+ static_cast<dsp32_config &>(dsp) = config;
+}
+
+
+//-------------------------------------------------
+// device_start - start up the device
+//-------------------------------------------------
+
+void dsp32c_device::device_start()
+{
+ // get our address spaces
+ m_program = space(AS_PROGRAM);
+ m_direct = &m_program->direct();
+
+ // register our state for the debugger
+ astring tempstr;
+ state_add(STATE_GENPC, "GENPC", m_r[15]).noshow();
+ state_add(STATE_GENPCBASE, "GENPCBASE", m_ppc).noshow();
+ state_add(STATE_GENSP, "GENSP", m_r[21]).noshow();
+ state_add(STATE_GENFLAGS, "GENFLAGS", m_iotemp).callimport().callexport().formatstr("%6s").noshow();
+ state_add(DSP32_PC, "PC", m_r[15]).mask(0xffffff);
+ for (int regnum = 0; regnum <= 14; regnum++)
+ state_add(DSP32_R0 + regnum, tempstr.format("R%d", regnum), m_r[regnum]).mask(0xffffff);
+ state_add(DSP32_R15, "R15", m_r[17]).mask(0xffffff);
+ state_add(DSP32_R16, "R16", m_r[18]).mask(0xffffff);
+ state_add(DSP32_R17, "R17", m_r[19]).mask(0xffffff);
+ state_add(DSP32_R18, "R18", m_r[20]).mask(0xffffff);
+ state_add(DSP32_R19, "R19", m_r[21]).mask(0xffffff);
+ state_add(DSP32_R20, "R20", m_r[24]).mask(0xffffff);
+ state_add(DSP32_R21, "R21", m_r[25]).mask(0xffffff);
+ state_add(DSP32_R22, "R22", m_r[29]).mask(0xffffff);
+ state_add(DSP32_PIN, "PIN", m_pin).mask(0xffffff);
+ state_add(DSP32_POUT, "POUT", m_pout).mask(0xffffff);
+ state_add(DSP32_IVTP, "IVTP", m_ivtp).mask(0xffffff);
+ state_add(DSP32_A0, "A0", m_a[0]).formatstr("%8s");
+ state_add(DSP32_A1, "A1", m_a[1]).formatstr("%8s");
+ state_add(DSP32_A2, "A2", m_a[2]).formatstr("%8s");
+ state_add(DSP32_A3, "A3", m_a[3]).formatstr("%8s");
+ state_add(DSP32_DAUC, "DAUC", m_r[26]).mask(0xff);
+ state_add(DSP32_PAR, "PAR", m_par);
+ state_add(DSP32_PDR, "PDR", m_pdr);
+ state_add(DSP32_PIR, "PIR", m_pir);
+ state_add(DSP32_PCR, "PCR", m_iotemp).mask(0x3ff).callimport();
+ state_add(DSP32_EMR, "EMR", m_emr);
+ state_add(DSP32_ESR, "ESR", m_esr);
+ state_add(DSP32_PCW, "PCW", m_pcw);
+ state_add(DSP32_PIOP, "PIOP", m_piop);
+ state_add(DSP32_IBUF, "IBUF", m_ibuf);
+ state_add(DSP32_ISR, "ISR", m_isr);
+ state_add(DSP32_OBUF, "OBUF", m_obuf);
+ state_add(DSP32_OSR, "OSR" , m_osr);
+ state_add(DSP32_IOC, "IOC", m_r[27]).mask(0xfffff);
+
+ // register our state for saving
+ save_item(NAME(m_r));
+ save_item(NAME(m_pin));
+ save_item(NAME(m_pout));
+ save_item(NAME(m_ivtp));
+ save_item(NAME(m_nzcflags));
+ save_item(NAME(m_vflags));
+ save_item(NAME(m_a));
+ save_item(NAME(m_NZflags));
+ save_item(NAME(m_VUflags));
+ save_item(NAME(m_abuf));
+ save_item(NAME(m_abufreg));
+ save_item(NAME(m_abufVUflags));
+ save_item(NAME(m_abufNZflags));
+ save_item(NAME(m_abufcycle));
+ save_item(NAME(m_abuf_index));
+ save_item(NAME(m_mbufaddr));
+ save_item(NAME(m_mbufdata));
+ save_item(NAME(m_par));
+ save_item(NAME(m_pare));
+ save_item(NAME(m_pdr));
+ save_item(NAME(m_pdr2));
+ save_item(NAME(m_pir));
+ save_item(NAME(m_pcr));
+ save_item(NAME(m_emr));
+ save_item(NAME(m_esr));
+ save_item(NAME(m_pcw));
+ save_item(NAME(m_piop));
+ save_item(NAME(m_ibuf));
+ save_item(NAME(m_isr));
+ save_item(NAME(m_obuf));
+ save_item(NAME(m_osr));
+ save_item(NAME(m_lastpins));
+ save_item(NAME(m_ppc));
+}
+
+
+//-------------------------------------------------
+// device_reset - reset the device
+//-------------------------------------------------
+
+void dsp32c_device::device_reset()
+{
+ // reset goes to 0
+ PC = 0;
+
+ // clear some registers
+ m_pcw &= 0x03ff;
+ update_pcr(m_pcr & PCR_RESET);
+ m_esr = 0;
+ m_emr = 0xffff;
+
+ // initialize fixed registers
+ R0 = R0_ALT = 0;
+ RMM = -1;
+ RPP = 1;
+ A_0 = 0.0;
+ A_1 = 1.0;
+
+ // init internal stuff
+ m_abufcycle[0] = m_abufcycle[1] = m_abufcycle[2] = m_abufcycle[3] = 12345678;
+ m_mbufaddr[0] = m_mbufaddr[1] = m_mbufaddr[2] = m_mbufaddr[3] = 1;
+}
+
+
+//-------------------------------------------------
+// memory_space_config - return the configuration
+// of the specified address space, or NULL if
+// the space doesn't exist
+//-------------------------------------------------
+
+const address_space_config *dsp32c_device::memory_space_config(address_spacenum spacenum) const
+{
+ return (spacenum == AS_PROGRAM) ? &m_program_config : NULL;
+}
+
+
+//-------------------------------------------------
+// state_import - import state into the device,
+// after it has been set
+//-------------------------------------------------
+
+void dsp32c_device::state_import(const device_state_entry &entry)
+{
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ break;
+
+ case DSP32_PCR:
+ update_pcr(m_iotemp);
+ break;
+
+ default:
+ fatalerror("dsp32c_device::state_import called for unexpected value\n");
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// state_export - export state out of the device
+//-------------------------------------------------
+
+void dsp32c_device::state_export(const device_state_entry &entry)
+{
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ // no actual flags register, so just make something up
+ m_iotemp = ((zFLAG != 0) << 0) |
+ ((nFLAG != 0) << 1) |
+ ((cFLAG != 0) << 2) |
+ ((vFLAG != 0) << 3) |
+ ((ZFLAG != 0) << 4) |
+ ((NFLAG != 0) << 5) |
+ ((UFLAG != 0) << 6) |
+ ((VFLAG != 0) << 7);
+ break;
+
+ case DSP32_PCR:
+ m_iotemp = m_pcr;
+ break;
+
+ default:
+ fatalerror("dsp32c_device::state_export called for unexpected value\n");
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// state_string_export - export state as a string
+// for the debugger
+//-------------------------------------------------
+
+void dsp32c_device::state_string_export(const device_state_entry &entry, astring &string)
+{
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ string.printf("%c%c%c%c%c%c%c%c",
+ NFLAG ? 'N':'.',
+ ZFLAG ? 'Z':'.',
+ UFLAG ? 'U':'.',
+ VFLAG ? 'V':'.',
+ nFLAG ? 'n':'.',
+ zFLAG ? 'z':'.',
+ cFLAG ? 'c':'.',
+ vFLAG ? 'v':'.');
+ break;
+
+ case DSP32_A0:
+ case DSP32_A1:
+ case DSP32_A2:
+ case DSP32_A3:
+ string.printf("%8g", *(double *)entry.dataptr());
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// disasm_min_opcode_bytes - return the length
+// of the shortest instruction, in bytes
+//-------------------------------------------------
+
+UINT32 dsp32c_device::disasm_min_opcode_bytes() const
+{
+ return 4;
+}
+
+
+//-------------------------------------------------
+// disasm_max_opcode_bytes - return the length
+// of the longest instruction, in bytes
+//-------------------------------------------------
+
+UINT32 dsp32c_device::disasm_max_opcode_bytes() const
+{
+ return 4;
+}
+
+
+//-------------------------------------------------
+// disasm_disassemble - call the disassembly
+// helper function
+//-------------------------------------------------
+
+offs_t dsp32c_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
+{
+ extern CPU_DISASSEMBLE( dsp32c );
+ return CPU_DISASSEMBLE_NAME(dsp32c)(NULL, buffer, pc, oprom, opram, 0);
+}
+
+
+
+
+//**************************************************************************
+// MEMORY ACCESSORS
+//**************************************************************************
+
+inline UINT32 dsp32c_device::ROPCODE(offs_t pc)
+{
+ return m_direct->read_decrypted_dword(pc);
+}
+
+inline UINT8 dsp32c_device::RBYTE(offs_t addr)
+{
+ return m_program->read_byte(addr);
+}
+
+inline void dsp32c_device::WBYTE(offs_t addr, UINT8 data)
+{
+ m_program->write_byte(addr, data);
+}
+
+inline UINT16 dsp32c_device::RWORD(offs_t addr)
+{
+#if DETECT_MISALIGNED_MEMORY
+ if (addr & 1) fprintf(stderr, "Unaligned word read @ %06X, PC=%06X\n", addr, PC);
+#endif
+ return m_program->read_word(addr);
+}
+
+inline UINT32 dsp32c_device::RLONG(offs_t addr)
+{
+#if DETECT_MISALIGNED_MEMORY
+ if (addr & 3) fprintf(stderr, "Unaligned long read @ %06X, PC=%06X\n", addr, PC);
+#endif
+ return m_program->read_dword(addr);
+}
+
+inline void dsp32c_device::WWORD(offs_t addr, UINT16 data)
+{
+#if DETECT_MISALIGNED_MEMORY
+ if (addr & 1) fprintf(stderr, "Unaligned word write @ %06X, PC=%06X\n", addr, PC);
+#endif
+ m_program->write_word(addr, data);
+}
+
+inline void dsp32c_device::WLONG(offs_t addr, UINT32 data)
+{
+#if DETECT_MISALIGNED_MEMORY
+ if (addr & 3) fprintf(stderr, "Unaligned long write @ %06X, PC=%06X\n", addr, PC);
+#endif
+ m_program->write_dword(addr, data);
+}
+
+
+
+//**************************************************************************
+// IRQ HANDLING
+//**************************************************************************
+
+void dsp32c_device::check_irqs()
+{
+ // finish me!
+}
+
+
+void dsp32c_device::set_irq_line(int irqline, int state)
+{
+ // finish me!
+}
+
+
+
+//**************************************************************************
+// REGISTER HANDLING
+//**************************************************************************
+
+void dsp32c_device::update_pcr(UINT16 newval)
+{
+ UINT16 oldval = m_pcr;
+ m_pcr = newval;
+
+ // reset the chip if we get a reset
+ if ((oldval & PCR_RESET) == 0 && (newval & PCR_RESET) != 0)
+ reset();
+
+ // track the state of the output pins
+ if (m_output_pins_changed != NULL)
+ {
+ UINT16 newoutput = ((newval & (PCR_PIFs | PCR_ENI)) == (PCR_PIFs | PCR_ENI)) ? DSP32_OUTPUT_PIF : 0;
+ if (newoutput != m_lastpins)
+ {
+ m_lastpins = newoutput;
+ (*m_output_pins_changed)(*this, newoutput);
+ }
+ }
+}
+
+
+
+//**************************************************************************
+// CORE INCLUDE
+//**************************************************************************
+
+#include "dsp32ops.c"
+
+
+
+//**************************************************************************
+// CORE EXECUTION LOOP
+//**************************************************************************
+
+//-------------------------------------------------
+// execute_min_cycles - return minimum number of
+// cycles it takes for one instruction to execute
+//-------------------------------------------------
+
+UINT32 dsp32c_device::execute_min_cycles() const
+{
+ return 4;
+}
+
+
+//-------------------------------------------------
+// execute_max_cycles - return maximum number of
+// cycles it takes for one instruction to execute
+//-------------------------------------------------
+
+UINT32 dsp32c_device::execute_max_cycles() const
+{
+ return 4;
+}
+
+
+//-------------------------------------------------
+// execute_input_lines - return the number of
+// input/interrupt lines
+//-------------------------------------------------
+
+UINT32 dsp32c_device::execute_input_lines() const
+{
+ return 2;
+}
+
+
+void dsp32c_device::execute_set_input(int inputnum, int state)
+{
+}
+
+
+void dsp32c_device::execute_run()
+{
+ // skip if halted
+ if ((m_pcr & PCR_RESET) == 0)
+ {
+ m_icount = 0;
+ return;
+ }
+
+ // update buffered accumulator values
+ m_abufcycle[0] += m_icount;
+ m_abufcycle[1] += m_icount;
+ m_abufcycle[2] += m_icount;
+ m_abufcycle[3] += m_icount;
+
+ // handle interrupts
+ check_irqs();
+
+ while (m_icount > 0)
+ execute_one();
+
+ // normalize buffered accumulator values
+ m_abufcycle[0] -= m_icount;
+ m_abufcycle[1] -= m_icount;
+ m_abufcycle[2] -= m_icount;
+ m_abufcycle[3] -= m_icount;
+}
+
+
+
+//**************************************************************************
+// PARALLEL INTERFACE WRITES
+//**************************************************************************
+
+const UINT32 dsp32c_device::s_regmap[4][16] =
+{
+ { // DSP32 compatible mode
+ PIO_PAR|LOWER, PIO_PAR|UPPER, PIO_PDR|LOWER, PIO_PDR|UPPER,
+ PIO_EMR|LOWER, PIO_EMR|UPPER, PIO_ESR|LOWER, PIO_PCR|LOWER,
+ PIO_PIR|UPPER, PIO_PIR|UPPER, PIO_PIR|UPPER, PIO_PIR|UPPER,
+ PIO_PIR|UPPER, PIO_PIR|UPPER, PIO_PIR|UPPER, PIO_PIR|UPPER
+ },
+ { // DSP32C 8-bit mode
+ PIO_PAR|LOWER, PIO_PAR|UPPER, PIO_PDR|LOWER, PIO_PDR|UPPER,
+ PIO_EMR|LOWER, PIO_EMR|UPPER, PIO_ESR|LOWER, PIO_PCR|LOWER,
+ PIO_PIR|LOWER, PIO_PIR|UPPER, PIO_PCR|UPPER, PIO_PARE|LOWER,
+ PIO_PDR2|LOWER,PIO_PDR2|UPPER,PIO_RESERVED, PIO_RESERVED
+ },
+ { // DSP32C illegal mode
+ PIO_RESERVED, PIO_RESERVED, PIO_RESERVED, PIO_RESERVED,
+ PIO_RESERVED, PIO_RESERVED, PIO_RESERVED, PIO_RESERVED,
+ PIO_RESERVED, PIO_RESERVED, PIO_RESERVED, PIO_RESERVED,
+ PIO_RESERVED, PIO_RESERVED, PIO_RESERVED, PIO_RESERVED
+ },
+ { // DSP32C 16-bit mode
+ PIO_PAR, PIO_RESERVED, PIO_PDR, PIO_RESERVED,
+ PIO_EMR, PIO_RESERVED, PIO_ESR|LOWER, PIO_PCR,
+ PIO_PIR, PIO_RESERVED, PIO_RESERVED, PIO_PARE|LOWER,
+ PIO_PDR2, PIO_RESERVED, PIO_RESERVED, PIO_RESERVED
+ }
+};
+
+
+
+//**************************************************************************
+// PARALLEL INTERFACE WRITES
+//**************************************************************************
+
+void dsp32c_device::dma_increment()
+{
+ if (m_pcr & PCR_AUTO)
+ {
+ int amount = (m_pcr & PCR_DMA32) ? 4 : 2;
+ m_par += amount;
+ if (m_par < amount)
+ m_pare++;
+ }
+}
+
+
+void dsp32c_device::dma_load()
+{
+ // only process if DMA is enabled
+ if (m_pcr & PCR_DMA)
+ {
+ UINT32 addr = m_par | (m_pare << 16);
+
+ // 16-bit case
+ if (!(m_pcr & PCR_DMA32))
+ m_pdr = RWORD(addr & 0xfffffe);
+
+ // 32-bit case
+ else
+ {
+ UINT32 temp = RLONG(addr & 0xfffffc);
+ m_pdr = temp >> 16;
+ m_pdr2 = temp & 0xffff;
+ }
+
+ // set the PDF flag to indicate we have data ready
+ update_pcr(m_pcr | PCR_PDFs);
+ }
+}
+
+
+void dsp32c_device::dma_store()
+{
+ // only process if DMA is enabled
+ if (m_pcr & PCR_DMA)
+ {
+ UINT32 addr = m_par | (m_pare << 16);
+
+ // 16-bit case
+ if (!(m_pcr & PCR_DMA32))
+ WWORD(addr & 0xfffffe, m_pdr);
+
+ // 32-bit case
+ else
+ WLONG(addr & 0xfffffc, (m_pdr << 16) | m_pdr2);
+
+ // clear the PDF flag to indicate we have taken the data
+ update_pcr(m_pcr & ~PCR_PDFs);
+ }
+}
+
+
+void dsp32c_device::pio_w(int reg, int data)
+{
+ UINT16 mask;
+ UINT8 mode;
+
+ // look up register and mask
+ mode = ((m_pcr >> 8) & 2) | ((m_pcr >> 1) & 1);
+ reg = s_regmap[mode][reg];
+ mask = reg >> 8;
+ if (mask == 0x00ff) data <<= 8;
+ data &= ~mask;
+ reg &= 0xff;
+
+ // switch off the register
+ switch (reg)
+ {
+ case PIO_PAR:
+ m_par = (m_par & mask) | data;
+
+ // trigger a load on the upper half
+ if (!(mask & 0xff00))
+ dma_load();
+ break;
+
+ case PIO_PARE:
+ m_pare = (m_pare & mask) | data;
+ break;
+
+ case PIO_PDR:
+ m_pdr = (m_pdr & mask) | data;
+
+ // trigger a write and PDF setting on the upper half
+ if (!(mask & 0xff00))
+ {
+ dma_store();
+ dma_increment();
+ }
+ break;
+
+ case PIO_PDR2:
+ m_pdr2 = (m_pdr2 & mask) | data;
+ break;
+
+ case PIO_EMR:
+ m_emr = (m_emr & mask) | data;
+ break;
+
+ case PIO_ESR:
+ m_esr = (m_esr & mask) | data;
+ break;
+
+ case PIO_PCR:
+ mask |= 0x0060;
+ data &= ~mask;
+ update_pcr((m_pcr & mask) | data);
+ break;
+
+ case PIO_PIR:
+ m_pir = (m_pir & mask) | data;
+
+ // set PIF on upper half
+ if (!(mask & 0xff00))
+ update_pcr(m_pcr | PCR_PIFs);
+ break;
+
+ // error case
+ default:
+ logerror("dsp32_pio_w called on invalid register %d\n", reg);
+ break;
+ }
+}
+
+
+
+//**************************************************************************
+// PARALLEL INTERFACE READS
+//**************************************************************************
+
+int dsp32c_device::pio_r(int reg)
+{
+ UINT16 mask, result = 0xffff;
+ UINT8 mode, shift = 0;
+
+ // look up register and mask
+ mode = ((m_pcr >> 8) & 2) | ((m_pcr >> 1) & 1);
+ reg = s_regmap[mode][reg];
+ mask = reg >> 8;
+ if (mask == 0x00ff) mask = 0xff00, shift = 8;
+ reg &= 0xff;
+
+ // switch off the register
+ switch (reg)
+ {
+ case PIO_PAR:
+ result = m_par | 1;
+ break;
+
+ case PIO_PARE:
+ result = m_pare;
+ break;
+
+ case PIO_PDR:
+ result = m_pdr;
+
+ // trigger an increment on the lower half
+ if (shift != 8)
+ dma_increment();
+
+ // trigger a fetch on the upper half
+ if (!(mask & 0xff00))
+ dma_load();
+ break;
+
+ case PIO_PDR2:
+ result = m_pdr2;
+ break;
+
+ case PIO_EMR:
+ result = m_emr;
+ break;
+
+ case PIO_ESR:
+ result = m_esr;
+ break;
+
+ case PIO_PCR:
+ result = m_pcr;
+ break;
+
+ case PIO_PIR:
+ if (!(mask & 0xff00))
+ update_pcr(m_pcr & ~PCR_PIFs); // clear PIFs
+ result = m_pir;
+ break;
+
+ // error case
+ default:
+ logerror("dsp32_pio_w called on invalid register %d\n", reg);
+ break;
+ }
+
+ return (result >> shift) & ~mask;
+}
diff --git a/trunk/src/emu/cpu/dsp32/dsp32.h b/trunk/src/emu/cpu/dsp32/dsp32.h
new file mode 100644
index 00000000000..b5cd059d256
--- /dev/null
+++ b/trunk/src/emu/cpu/dsp32/dsp32.h
@@ -0,0 +1,484 @@
+/***************************************************************************
+
+ dsp32.h
+ Interface file for the portable DSP32 emulator.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __DSP32_H__
+#define __DSP32_H__
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_DSP32C_CONFIG(_config) \
+ dsp32c_device::static_set_config(*device, _config); \
+
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+// IRQ sources
+const int DSP32_IRQ0 = 0; // IRQ0
+const int DSP32_IRQ1 = 1; // IRQ1
+
+// pin signal bits
+const int DSP32_OUTPUT_PIF = 0x01;
+
+// register enumeration
+enum
+{
+ // CAU
+ DSP32_PC=1,
+ DSP32_R0,
+ DSP32_R1,
+ DSP32_R2,
+ DSP32_R3,
+ DSP32_R4,
+ DSP32_R5,
+ DSP32_R6,
+ DSP32_R7,
+ DSP32_R8,
+ DSP32_R9,
+ DSP32_R10,
+ DSP32_R11,
+ DSP32_R12,
+ DSP32_R13,
+ DSP32_R14,
+ DSP32_R15,
+ DSP32_R16,
+ DSP32_R17,
+ DSP32_R18,
+ DSP32_R19,
+ DSP32_R20,
+ DSP32_R21,
+ DSP32_R22,
+ DSP32_PIN,
+ DSP32_POUT,
+ DSP32_IVTP,
+
+ // DAU
+ DSP32_A0,
+ DSP32_A1,
+ DSP32_A2,
+ DSP32_A3,
+ DSP32_DAUC,
+
+ // PIO
+ DSP32_PAR,
+ DSP32_PDR,
+ DSP32_PIR,
+ DSP32_PCR,
+ DSP32_EMR,
+ DSP32_ESR,
+ DSP32_PCW,
+ DSP32_PIOP,
+
+ // SIO
+ DSP32_IBUF,
+ DSP32_ISR,
+ DSP32_OBUF,
+ DSP32_OSR,
+ DSP32_IOC
+};
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class dsp32c_device;
+
+
+// ======================> dsp32_config
+
+struct dsp32_config
+{
+ void (*m_output_pins_changed)(dsp32c_device &device, UINT32 pins); // a change has occurred on an output pin
+};
+
+
+
+// ======================> dsp32c_device
+
+class dsp32c_device : public cpu_device,
+ public dsp32_config
+{
+public:
+ // construction/destruction
+ dsp32c_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // inline configuration helpers
+ static void static_set_config(device_t &device, const dsp32_config &config);
+
+ // public interfaces
+ void pio_w(int reg, int data);
+ int pio_r(int reg);
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ // device_execute_interface overrides
+ virtual UINT32 execute_min_cycles() const;
+ virtual UINT32 execute_max_cycles() const;
+ virtual UINT32 execute_input_lines() const;
+ virtual void execute_run();
+ virtual void execute_set_input(int inputnum, int state);
+
+ // device_memory_interface overrides
+ virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const;
+
+ // device_state_interface overrides
+ virtual void state_import(const device_state_entry &entry);
+ virtual void state_export(const device_state_entry &entry);
+ virtual void state_string_export(const device_state_entry &entry, astring &string);
+
+ // device_disasm_interface overrides
+ virtual UINT32 disasm_min_opcode_bytes() const;
+ virtual UINT32 disasm_max_opcode_bytes() const;
+ virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);
+
+ // memory accessors
+ UINT32 ROPCODE(offs_t pc);
+ UINT8 RBYTE(offs_t addr);
+ void WBYTE(offs_t addr, UINT8 data);
+ UINT16 RWORD(offs_t addr);
+ UINT32 RLONG(offs_t addr);
+ void WWORD(offs_t addr, UINT16 data);
+ void WLONG(offs_t addr, UINT32 data);
+
+ // interrupts
+ void check_irqs();
+ void set_irq_line(int irqline, int state);
+
+ void update_pcr(UINT16 newval);
+ void illegal(UINT32 op);
+ void unimplemented(UINT32 op);
+ void execute_one();
+
+ // CAU helpers
+ UINT32 cau_read_pi_special(UINT8 i);
+ void cau_write_pi_special(UINT8 i, UINT32 val);
+ UINT8 cau_read_pi_1byte(int pi);
+ UINT16 cau_read_pi_2byte(int pi);
+ UINT32 cau_read_pi_4byte(int pi);
+ void cau_write_pi_1byte(int pi, UINT8 val);
+ void cau_write_pi_2byte(int pi, UINT16 val);
+ void cau_write_pi_4byte(int pi, UINT32 val);
+
+ // DAU helpers
+ double dau_get_amult(int aidx);
+ double dau_get_anzflags();
+ UINT8 dau_get_avuflags();
+ void remember_last_dau(int aidx);
+ void dau_set_val_noflags(int aidx, double res);
+ void dau_set_val_flags(int aidx, double res);
+ double dsp_to_double(UINT32 val);
+ UINT32 double_to_dsp(double val);
+ double dau_read_pi_special(int i);
+ void dau_write_pi_special(int i, double val);
+ double dau_read_pi_double_1st(int pi, int multiplier);
+ double dau_read_pi_double_2nd(int pi, int multiplier, double xval);
+ UINT32 dau_read_pi_4bytes(int pi);
+ UINT16 dau_read_pi_2bytes(int pi);
+ void dau_write_pi_double(int pi, double val);
+ void dau_write_pi_4bytes(int pi, UINT32 val);
+ void dau_write_pi_2bytes(int pi, UINT16 val);
+
+ // common condition routine
+ int condition(int cond);
+
+ // CAU branch instruction implementation
+ void nop(UINT32 op);
+ void goto_t(UINT32 op);
+ void goto_pl(UINT32 op);
+ void goto_mi(UINT32 op);
+ void goto_ne(UINT32 op);
+ void goto_eq(UINT32 op);
+ void goto_vc(UINT32 op);
+ void goto_vs(UINT32 op);
+ void goto_cc(UINT32 op);
+ void goto_cs(UINT32 op);
+ void goto_ge(UINT32 op);
+ void goto_lt(UINT32 op);
+ void goto_gt(UINT32 op);
+ void goto_le(UINT32 op);
+ void goto_hi(UINT32 op);
+ void goto_ls(UINT32 op);
+ void goto_auc(UINT32 op);
+ void goto_aus(UINT32 op);
+ void goto_age(UINT32 op);
+ void goto_alt(UINT32 op);
+ void goto_ane(UINT32 op);
+ void goto_aeq(UINT32 op);
+ void goto_avc(UINT32 op);
+ void goto_avs(UINT32 op);
+ void goto_agt(UINT32 op);
+ void goto_ale(UINT32 op);
+ void goto_ibe(UINT32 op);
+ void goto_ibf(UINT32 op);
+ void goto_obf(UINT32 op);
+ void goto_obe(UINT32 op);
+ void goto_pde(UINT32 op);
+ void goto_pdf(UINT32 op);
+ void goto_pie(UINT32 op);
+ void goto_pif(UINT32 op);
+ void goto_syc(UINT32 op);
+ void goto_sys(UINT32 op);
+ void goto_fbc(UINT32 op);
+ void goto_fbs(UINT32 op);
+ void goto_irq1lo(UINT32 op);
+ void goto_irq1hi(UINT32 op);
+ void goto_irq2lo(UINT32 op);
+ void goto_irq2hi(UINT32 op);
+ void dec_goto(UINT32 op);
+ void call(UINT32 op);
+ void goto24(UINT32 op);
+ void call24(UINT32 op);
+ void do_i(UINT32 op);
+ void do_r(UINT32 op);
+
+ // CAU 16-bit arithmetic implementation
+ void add_si(UINT32 op);
+ void add_ss(UINT32 op);
+ void mul2_s(UINT32 op);
+ void subr_ss(UINT32 op);
+ void addr_ss(UINT32 op);
+ void sub_ss(UINT32 op);
+ void neg_s(UINT32 op);
+ void andc_ss(UINT32 op);
+ void cmp_ss(UINT32 op);
+ void xor_ss(UINT32 op);
+ void rcr_s(UINT32 op);
+ void or_ss(UINT32 op);
+ void rcl_s(UINT32 op);
+ void shr_s(UINT32 op);
+ void div2_s(UINT32 op);
+ void and_ss(UINT32 op);
+ void test_ss(UINT32 op);
+ void add_di(UINT32 op);
+ void subr_di(UINT32 op);
+ void addr_di(UINT32 op);
+ void sub_di(UINT32 op);
+ void andc_di(UINT32 op);
+ void cmp_di(UINT32 op);
+ void xor_di(UINT32 op);
+ void or_di(UINT32 op);
+ void and_di(UINT32 op);
+ void test_di(UINT32 op);
+
+ // CAU 24-bit arithmetic implementation
+ void adde_si(UINT32 op);
+ void adde_ss(UINT32 op);
+ void mul2e_s(UINT32 op);
+ void subre_ss(UINT32 op);
+ void addre_ss(UINT32 op);
+ void sube_ss(UINT32 op);
+ void nege_s(UINT32 op);
+ void andce_ss(UINT32 op);
+ void cmpe_ss(UINT32 op);
+ void xore_ss(UINT32 op);
+ void rcre_s(UINT32 op);
+ void ore_ss(UINT32 op);
+ void rcle_s(UINT32 op);
+ void shre_s(UINT32 op);
+ void div2e_s(UINT32 op);
+ void ande_ss(UINT32 op);
+ void teste_ss(UINT32 op);
+ void adde_di(UINT32 op);
+ void subre_di(UINT32 op);
+ void addre_di(UINT32 op);
+ void sube_di(UINT32 op);
+ void andce_di(UINT32 op);
+ void cmpe_di(UINT32 op);
+ void xore_di(UINT32 op);
+ void ore_di(UINT32 op);
+ void ande_di(UINT32 op);
+ void teste_di(UINT32 op);
+
+ // CAU load/store implementation
+ void load_hi(UINT32 op);
+ void load_li(UINT32 op);
+ void load_i(UINT32 op);
+ void load_ei(UINT32 op);
+ void store_hi(UINT32 op);
+ void store_li(UINT32 op);
+ void store_i(UINT32 op);
+ void store_ei(UINT32 op);
+ void load_hr(UINT32 op);
+ void load_lr(UINT32 op);
+ void load_r(UINT32 op);
+ void load_er(UINT32 op);
+ void store_hr(UINT32 op);
+ void store_lr(UINT32 op);
+ void store_r(UINT32 op);
+ void store_er(UINT32 op);
+ void load24(UINT32 op);
+
+ // DAU form 1 implementation
+ void d1_aMpp(UINT32 op);
+ void d1_aMpm(UINT32 op);
+ void d1_aMmp(UINT32 op);
+ void d1_aMmm(UINT32 op);
+ void d1_0px(UINT32 op);
+ void d1_0mx(UINT32 op);
+ void d1_1pp(UINT32 op);
+ void d1_1pm(UINT32 op);
+ void d1_1mp(UINT32 op);
+ void d1_1mm(UINT32 op);
+ void d1_aMppr(UINT32 op);
+ void d1_aMpmr(UINT32 op);
+ void d1_aMmpr(UINT32 op);
+ void d1_aMmmr(UINT32 op);
+
+ // DAU form 2 implementation
+ void d2_aMpp(UINT32 op);
+ void d2_aMpm(UINT32 op);
+ void d2_aMmp(UINT32 op);
+ void d2_aMmm(UINT32 op);
+ void d2_aMppr(UINT32 op);
+ void d2_aMpmr(UINT32 op);
+ void d2_aMmpr(UINT32 op);
+ void d2_aMmmr(UINT32 op);
+
+ // DAU form 3 implementation
+ void d3_aMpp(UINT32 op);
+ void d3_aMpm(UINT32 op);
+ void d3_aMmp(UINT32 op);
+ void d3_aMmm(UINT32 op);
+ void d3_aMppr(UINT32 op);
+ void d3_aMpmr(UINT32 op);
+ void d3_aMmpr(UINT32 op);
+ void d3_aMmmr(UINT32 op);
+
+ // DAU form 4 implementation
+ void d4_pp(UINT32 op);
+ void d4_pm(UINT32 op);
+ void d4_mp(UINT32 op);
+ void d4_mm(UINT32 op);
+ void d4_ppr(UINT32 op);
+ void d4_pmr(UINT32 op);
+ void d4_mpr(UINT32 op);
+ void d4_mmr(UINT32 op);
+
+ // DAU form 5 implementation
+ void d5_ic(UINT32 op);
+ void d5_oc(UINT32 op);
+ void d5_float(UINT32 op);
+ void d5_int(UINT32 op);
+ void d5_round(UINT32 op);
+ void d5_ifalt(UINT32 op);
+ void d5_ifaeq(UINT32 op);
+ void d5_ifagt(UINT32 op);
+ void d5_float24(UINT32 op);
+ void d5_int24(UINT32 op);
+ void d5_ieee(UINT32 op);
+ void d5_dsp(UINT32 op);
+ void d5_seed(UINT32 op);
+
+ // dma helpers
+ void dma_increment();
+ void dma_load();
+ void dma_store();
+
+ // configuration
+ const address_space_config m_program_config;
+
+ // internal state
+ UINT32 m_r[32];
+ UINT32 m_pin, m_pout;
+ UINT32 m_ivtp;
+ UINT32 m_nzcflags;
+ UINT32 m_vflags;
+
+ double m_a[6];
+ double m_NZflags;
+ UINT8 m_VUflags;
+
+ double m_abuf[4];
+ UINT8 m_abufreg[4];
+ UINT8 m_abufVUflags[4];
+ UINT8 m_abufNZflags[4];
+ int m_abufcycle[4];
+ int m_abuf_index;
+
+ INT32 m_mbufaddr[4];
+ UINT32 m_mbufdata[4];
+ int m_mbuf_index;
+
+ UINT16 m_par;
+ UINT8 m_pare;
+ UINT16 m_pdr;
+ UINT16 m_pdr2;
+ UINT16 m_pir;
+ UINT16 m_pcr;
+ UINT16 m_emr;
+ UINT8 m_esr;
+ UINT16 m_pcw;
+ UINT8 m_piop;
+
+ UINT32 m_ibuf;
+ UINT32 m_isr;
+ UINT32 m_obuf;
+ UINT32 m_osr;
+
+ UINT32 m_iotemp;
+
+ // internal stuff
+ int m_lastp;
+ int m_icount;
+ UINT8 m_lastpins;
+ UINT32 m_ppc;
+ address_space * m_program;
+ direct_read_data *m_direct;
+
+ // tables
+ static void (dsp32c_device::*const s_dsp32ops[])(UINT32 op);
+ static const UINT32 s_regmap[4][16];
+};
+
+
+extern const device_type DSP32C;
+
+
+
+#endif /* __DSP32_H__ */
diff --git a/trunk/src/emu/cpu/dsp32/dsp32dis.c b/trunk/src/emu/cpu/dsp32/dsp32dis.c
new file mode 100644
index 00000000000..80d0c2ea11a
--- /dev/null
+++ b/trunk/src/emu/cpu/dsp32/dsp32dis.c
@@ -0,0 +1,702 @@
+/***************************************************************************
+
+ dsp32dis.c
+ Disassembler for the portable AT&T/Lucent DSP32C emulator.
+ Written by Aaron Giles
+
+***************************************************************************/
+
+#include "emu.h"
+#include "dsp32.h"
+
+
+/***************************************************************************
+ MEMORY ACCESSORS
+***************************************************************************/
+
+#define ABS(x) (((x) >= 0) ? (x) : -(x))
+
+
+/***************************************************************************
+ CODE CODE
+***************************************************************************/
+
+static const char *const sizesuffix[] = { "", "e" };
+static const char *const unarysign[] = { "", "-" };
+static const char *const sign[] = { "+", "-" };
+static const char *const aMvals[] = { "a0", "a1", "a2", "a3", "0.0", "1.0", "Format 4", "Reserved" };
+static const char *const memsuffix[] = { "h", "l", "", "e" };
+static const char *const functable[] =
+{
+ "ic", "oc", "float", "int", "round", "ifalt", "ifaeq", "ifagt",
+ "reserved8", "reserved9", "float24", "int24", "ieee", "dsp", "seed", "reservedf"
+};
+static const char *const condtable[] =
+{
+ "false", "true",
+ "pl", "mi",
+ "ne", "eq",
+ "vc", "vs",
+ "cc", "cs",
+ "ge", "lt",
+ "gt", "le",
+ "hi", "ls",
+ "auc", "aus",
+ "age", "alt",
+ "ane", "aeq",
+ "avc", "avs",
+ "agt", "ale",
+ "!resd", "resd",
+ "!rese", "rese",
+ "!resf", "resf",
+ "ibe", "ibf",
+ "obf", "obe",
+ "pde", "pdf",
+ "pie", "pif",
+ "syc", "sys",
+ "fbc", "fbs",
+ "ireq1_lo", "ireq1_hi",
+ "ireq2_lo", "ireq2_hi",
+ "!?18", "?18",
+ "!?19", "?19",
+ "!?1a", "?1a",
+ "!?1b", "?1b",
+ "!?1c", "?1c",
+ "!?1d", "?1d",
+ "!?1e", "?1e",
+ "!?1f", "?1f"
+};
+static const char *const regname[] =
+{
+ "0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc",
+ "0", "r15", "r16", "r17", "r18", "r19", "-1", "1",
+ "r20", "r21", "dauc", "ioc", "res1c", "r22", "pcsh", "res1f"
+};
+static const char *const regnamee[] =
+{
+ "0", "r1e", "r2e", "r3e", "r4e", "r5e", "r6e", "r7e",
+ "r8e", "r9e", "r10e", "r11e", "r12e", "r13e", "r14e", "pce",
+ "0", "r15e", "r16e", "r17e", "r18e", "r19e", "--", "++",
+ "r20e", "r21e", "dauce", "ioce", "res1ce", "r22e", "pcshe", "res1fe"
+};
+
+static char tempbuf[10][40];
+
+INLINE char *signed_16bit_unary(INT16 val)
+{
+ static char temp[10];
+ if (val < 0)
+ sprintf(temp, "-$%x", -val);
+ else
+ sprintf(temp, "$%x", val);
+ return temp;
+}
+
+INLINE char *signed_16bit_sep(INT16 val)
+{
+ static char temp[10];
+ if (val < 0)
+ sprintf(temp, " - $%x", -val);
+ else
+ sprintf(temp, " + $%x", val);
+ return temp;
+}
+
+INLINE char *signed_16bit_sep_nospace(INT16 val)
+{
+ static char temp[10];
+ if (val < 0)
+ sprintf(temp, "-$%x", -val);
+ else
+ sprintf(temp, "+$%x", val);
+ return temp;
+}
+
+INLINE char *unsigned_16bit_size(INT16 val, UINT8 size)
+{
+ static char temp[10];
+ if (size)
+ sprintf(temp, "$%06x", (INT32)val & 0xffffff);
+ else
+ sprintf(temp, "$%04x", val & 0xffff);
+ return temp;
+}
+
+static UINT8 lastp;
+static const char *dasm_XYZ(UINT8 bits, char *buffer)
+{
+ UINT8 p = bits >> 3;
+ UINT8 i = bits & 7;
+
+ if (p)
+ {
+ if (p == 15) p = lastp; /* P=15 means Z inherits from Y, Y inherits from X */
+ lastp = p;
+ switch (i)
+ {
+ case 0: sprintf(buffer, "*r%d", p); break;
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5: sprintf(buffer, "*r%d++r%d", p, i + 14); break;
+ case 6: sprintf(buffer, "*r%d--", p); break;
+ case 7: sprintf(buffer, "*r%d++", p); break;
+ }
+ }
+ else
+ {
+ switch (i)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3: sprintf(buffer, "a%d", i); break;
+ case 4: sprintf(buffer, "ibuf"); break;
+ case 5: sprintf(buffer, "obuf"); break;
+ case 6: sprintf(buffer, "pdr"); break;
+ case 7: buffer[0] = 0; break;
+ }
+ }
+ return buffer;
+}
+
+
+static const char *dasm_PI(UINT16 bits, char *buffer)
+{
+ UINT8 p = bits >> 5;
+ UINT8 i = bits & 0x1f;
+
+ if (p)
+ {
+ switch (i)
+ {
+ case 0:
+ case 16: sprintf(buffer, "*%s", regname[p]); break;
+ case 22: sprintf(buffer, "*%s--", regname[p]); break;
+ case 23: sprintf(buffer, "*%s++", regname[p]); break;
+ default: sprintf(buffer, "*%s++%s", regname[p], regname[i]); break;
+ }
+ }
+ else
+ {
+ switch (i)
+ {
+ case 4: sprintf(buffer, "ibuf"); break;
+ case 5: sprintf(buffer, "obuf"); break;
+ case 6: sprintf(buffer, "pdr"); break;
+ case 14: sprintf(buffer, "piop"); break;
+ case 20: sprintf(buffer, "pdr2"); break;
+ case 22: sprintf(buffer, "pir"); break;
+ case 30: sprintf(buffer, "pcw"); break;
+ default: sprintf(buffer, "????"); break;
+ }
+ }
+ return buffer;
+}
+
+
+static unsigned dasm_dsp32(char *buffer, unsigned pc, UINT32 op)
+{
+ UINT32 flags = 0;
+
+ switch (op >> 25)
+ {
+ /* DA format 1 */
+ case 0x10: case 0x11: case 0x12: case 0x13:
+ case 0x14: case 0x15: case 0x16: case 0x17:
+ case 0x18: case 0x19: case 0x1a: case 0x1b:
+ {
+ const char *X = dasm_XYZ((op >> 14) & 0x7f, tempbuf[0]);
+ const char *Y = dasm_XYZ((op >> 7) & 0x7f, tempbuf[1]);
+ const char *Z = dasm_XYZ((op >> 0) & 0x7f, tempbuf[2]);
+ const char *aM = aMvals[(op >> 26) & 7];
+ UINT8 aN = (op >> 21) & 3;
+ if ((op & 0x7f) == 7)
+ {
+ if (aM[0] == '0')
+ sprintf(buffer, "a%d = %s%s", aN, unarysign[(op >> 24) & 1], Y);
+ else if (aM[0] == '1')
+ sprintf(buffer, "a%d = %s%s %s %s", aN, unarysign[(op >> 24) & 1], Y, sign[(op >> 23) & 1], X);
+ else
+ sprintf(buffer, "a%d = %s%s %s %s * %s", aN, unarysign[(op >> 24) & 1], Y, sign[(op >> 23) & 1], aM, X);
+ }
+ else
+ {
+ if (aM[0] == '0')
+ sprintf(buffer, "%s = a%d = %s%s", Z, aN, unarysign[(op >> 24) & 1], Y);
+ else if (aM[0] == '1')
+ sprintf(buffer, "%s = a%d = %s%s %s %s", Z, aN, unarysign[(op >> 24) & 1], Y, sign[(op >> 23) & 1], X);
+ else
+ sprintf(buffer, "%s = a%d = %s%s %s %s * %s", Z, aN, unarysign[(op >> 24) & 1], Y, sign[(op >> 23) & 1], aM, X);
+ }
+ break;
+ }
+
+ /* DA format 2 */
+ case 0x20: case 0x21: case 0x22: case 0x23:
+ case 0x24: case 0x25: case 0x26: case 0x27:
+ case 0x28: case 0x29: case 0x2a: case 0x2b:
+ {
+ const char *X = dasm_XYZ((op >> 14) & 0x7f, tempbuf[0]);
+ const char *Y = dasm_XYZ((op >> 7) & 0x7f, tempbuf[1]);
+ const char *Z = dasm_XYZ((op >> 0) & 0x7f, tempbuf[2]);
+ const char *aM = aMvals[(op >> 26) & 7];
+ UINT8 aN = (op >> 21) & 3;
+
+ if ((op & 0x7f) == 7)
+ {
+ if (aM[0] == '0')
+ sprintf(buffer, "a%d = %s%s * %s", aN, unarysign[(op >> 23) & 1], Y, X);
+ else
+ sprintf(buffer, "a%d = %s%s %s %s * %s", aN, unarysign[(op >> 24) & 1], aM, sign[(op >> 23) & 1], Y, X);
+ }
+ else
+ {
+ if (aM[0] == '0')
+ sprintf(buffer, "a%d = %s(%s=%s) * %s", aN, unarysign[(op >> 23) & 1], Z, Y, X);
+ else
+ sprintf(buffer, "a%d = %s%s %s (%s=%s) * %s", aN, unarysign[(op >> 24) & 1], aM, sign[(op >> 23) & 1], Z, Y, X);
+ }
+ break;
+ }
+
+ /* DA format 3 */
+ case 0x30: case 0x31: case 0x32: case 0x33:
+ case 0x34: case 0x35: case 0x36: case 0x37:
+ case 0x38: case 0x39: case 0x3a: case 0x3b:
+ {
+ const char *X = dasm_XYZ((op >> 14) & 0x7f, tempbuf[0]);
+ const char *Y = dasm_XYZ((op >> 7) & 0x7f, tempbuf[1]);
+ const char *Z = dasm_XYZ((op >> 0) & 0x7f, tempbuf[2]);
+ const char *aM = aMvals[(op >> 26) & 7];
+ UINT8 aN = (op >> 21) & 3;
+
+ if ((op & 0x7f) == 7)
+ {
+ if (aM[0] == '0')
+ sprintf(buffer, "a%d = %s%s * %s", aN, unarysign[(op >> 23) & 1], Y, X);
+ else
+ sprintf(buffer, "a%d = %s%s %s %s * %s", aN, unarysign[(op >> 24) & 1], aM, sign[(op >> 23) & 1], Y, X);
+ }
+ else
+ {
+ if (aM[0] == '0')
+ sprintf(buffer, "%s = a%d = %s%s * %s", Z, aN, unarysign[(op >> 23) & 1], Y, X);
+ else
+ sprintf(buffer, "%s = a%d = %s%s %s %s * %s", Z, aN, unarysign[(op >> 24) & 1], aM, sign[(op >> 23) & 1], Y, X);
+ }
+ break;
+ }
+
+ /* DA format 4 */
+ case 0x1c: case 0x1d:
+ {
+ const char *X = dasm_XYZ((op >> 14) & 0x7f, tempbuf[0]);
+ const char *Y = dasm_XYZ((op >> 7) & 0x7f, tempbuf[1]);
+ const char *Z = dasm_XYZ((op >> 0) & 0x7f, tempbuf[2]);
+ UINT8 aN = (op >> 21) & 3;
+
+ if ((op & 0x7f) == 7)
+ sprintf(buffer, "a%d = %s%s %s %s", aN, unarysign[(op >> 24) & 1], Y, sign[(op >> 23) & 1], X);
+ else
+ sprintf(buffer, "a%d = %s(%s=%s) %s %s", aN, unarysign[(op >> 24) & 1], Z, Y, sign[(op >> 23) & 1], X);
+ break;
+ }
+
+ /* DA format 5 */
+ case 0x3c: case 0x3d: case 0x3e: case 0x3f:
+ if ((op & 0x7f) == 7)
+ sprintf(buffer, "a%d = %s(%s)",
+ (op >> 21) & 3, // aN
+ functable[(op >> 23) & 15], // G
+ dasm_XYZ((op >> 7) & 0x7f, tempbuf[0])); // Y
+ else
+ sprintf(buffer, "%s = a%d = %s(%s)",
+ dasm_XYZ((op >> 0) & 0x7f, tempbuf[2]), // Z
+ (op >> 21) & 3, // aN
+ functable[(op >> 23) & 15], // G
+ dasm_XYZ((op >> 7) & 0x7f, tempbuf[0])); // Y
+ break;
+
+ /* CA formats 0/1 */
+ case 0x00: case 0x01: case 0x02: case 0x03:
+ {
+ const char *rH = regname[(op >> 16) & 0x1f];
+ UINT8 C = (op >> 21) & 0x3f;
+ INT16 N = (INT16)op;
+
+ if (op == 0)
+ sprintf(buffer, "nop");
+ else if (C == 1 && N == 0 && ((op >> 16) & 0x1f) == 0x1e)
+ sprintf(buffer, "ireturn");
+ else if (C == 1)
+ {
+ if (((op >> 16) & 0x1f) == 15)
+ sprintf(buffer, "goto %s%s [%x]", rH, signed_16bit_sep_nospace(N), (pc + 8 + N) & 0xffffff);
+ else if (N && rH[0] != '0')
+ sprintf(buffer, "goto %s%s", rH, signed_16bit_sep_nospace(N));
+ else if (N)
+ sprintf(buffer, "goto $%x", ((INT32)N & 0xffffff));
+ else
+ {
+ if (((op >> 16) & 0x1f) == 20)
+ flags = DASMFLAG_STEP_OUT;
+ sprintf(buffer, "goto %s", rH);
+ }
+ }
+ else
+ {
+ if (((op >> 16) & 0x1f) == 15)
+ sprintf(buffer, "if (%s) goto %s%s [%x]", condtable[C], rH, signed_16bit_sep_nospace(N), (pc + 8 + N) & 0xffffff);
+ else if (N && rH[0] != '0')
+ sprintf(buffer, "if (%s) goto %s%s", condtable[C], rH, signed_16bit_sep_nospace(N));
+ else if (N)
+ sprintf(buffer, "if (%s) goto $%x", condtable[C], ((INT32)N & 0xffffff));
+ else
+ {
+ if (((op >> 16) & 0x1f) == 20)
+ flags = DASMFLAG_STEP_OUT;
+ sprintf(buffer, "if (%s) goto %s", condtable[C], rH);
+ }
+ }
+ break;
+ }
+
+ /* CA format 3a */
+ case 0x06: case 0x07:
+ {
+ const char *rH = regname[(op >> 16) & 0x1f];
+ const char *rM = regname[(op >> 21) & 0x1f];
+ INT16 N = (INT16)op;
+
+ if (((op >> 16) & 0x1f) == 15)
+ {
+ sprintf(buffer, "if (%s-- >= 0) goto %s%s [%x]", rM, rH, signed_16bit_sep_nospace(N), (pc + 8 + N) & 0xffffff);
+ if (((pc + 8 + N) & 0xffffff) < pc)
+ flags = DASMFLAG_STEP_OVER;
+ }
+ else if (N && rH[0] != '0')
+ sprintf(buffer, "if (%s-- >= 0) goto %s%s", rM, rH, signed_16bit_sep_nospace(N));
+ else if (N)
+ {
+ sprintf(buffer, "if (%s-- >= 0) goto $%x", rM, ((INT32)N & 0xffffff));
+ if (((INT32)N & 0xffffff) < pc)
+ flags = DASMFLAG_STEP_OVER;
+ }
+ else
+ {
+ sprintf(buffer, "if (%s-- >= 0) goto %s", rM, rH);
+ if (((op >> 16) & 0x1f) == 20)
+ flags = DASMFLAG_STEP_OUT;
+ }
+ break;
+ }
+
+ /* CA format 3b/3c */
+ case 0x46:
+ if (((op >> 21) & 0x1f) == 0)
+ sprintf(buffer, "do %d,%d", (op >> 16) & 0x1f, op & 0x7ff);
+ else if (((op >> 21) & 0x1f) == 1)
+ sprintf(buffer, "do %d,%s", (op >> 16) & 0x1f, regname[op & 0x1f]);
+ break;
+
+ /* CA format 4 */
+ case 0x08: case 0x09:
+ {
+ const char *rH = regname[(op >> 16) & 0x1f];
+ const char *rM = regname[(op >> 21) & 0x1f];
+ INT16 N = (INT16)op;
+
+ if (((op >> 16) & 0x1f) == 15)
+ sprintf(buffer, "call %s%s (%s) [%x]", rH, signed_16bit_sep_nospace(N), rM, (pc + 8 + N) & 0xffffff);
+ else if (N && rH[0] != '0')
+ sprintf(buffer, "call %s%s (%s)", rH, signed_16bit_sep_nospace(N), rM);
+ else if (N)
+ sprintf(buffer, "call $%x (%s)", ((INT32)N & 0xffffff), rM);
+ else
+ sprintf(buffer, "call %s (%s)", rH, rM);
+ flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1);
+ break;
+ }
+
+ /* CA format 5a/5b */
+ case 0x0a: case 0x0b:
+ case 0x4a: case 0x4b:
+ {
+ const char *rD = regname[(op >> 21) & 0x1f];
+ const char *rH = regname[(op >> 16) & 0x1f];
+ const char *s = sizesuffix[(op >> 31) & 1];
+ INT16 N = (INT16)op;
+ if (N == 0)
+ sprintf(buffer, "%s%s = %s%s", rD, s, rH, s);
+ else if (rH[0] == '0')
+ sprintf(buffer, "%s%s = %s", rD, s, signed_16bit_unary(N));
+ else
+ sprintf(buffer, "%s%s = %s%s%s", rD, s, rH, s, signed_16bit_sep((INT16)op));
+ break;
+ }
+
+ /* CA format 6a/6b */
+ case 0x0c: case 0x4c:
+ {
+ const char *rD = regname[(op >> 16) & 0x1f];
+ const char *rS1 = regname[(op >> 5) & 0x1f];
+ const char *rS2 = regname[(op >> 0) & 0x1f];
+ const char *s = sizesuffix[(op >> 31) & 1];
+ UINT8 threeop = (op >> 11) & 1;
+ char condbuf[40] = { 0 };
+
+ if ((op >> 10) & 1)
+ sprintf(condbuf, "if (%s) ", condtable[(op >> 12) & 15]);
+
+ switch ((op >> 21) & 15)
+ {
+ /* add */
+ case 0:
+ if (threeop)
+ {
+ if (rS1[0] == '0' && rS2[0] == '0')
+ sprintf(buffer, "%s%s%s = 0", condbuf, rD, s);
+ else if (rS1[0] == '0')
+ sprintf(buffer, "%s%s%s = %s%s", condbuf, rD, s, rS2, s);
+ else if (rS2[0] == '0')
+ sprintf(buffer, "%s%s%s = %s%s", condbuf, rD, s, rS1, s);
+ else
+ sprintf(buffer, "%s%s%s = %s%s + %s%s", condbuf, rD, s, rS2, s, rS1, s);
+ }
+ else
+ {
+ if (rS1[0] == '0')
+ sprintf(buffer, "%s%s%s = %s%s", condbuf, rD, s, rD, s);
+ else
+ sprintf(buffer, "%s%s%s = %s%s + %s%s", condbuf, rD, s, rD, s, rS1, s);
+ }
+ break;
+
+ case 1:
+ sprintf(buffer, "%s%s%s = %s%s * 2", condbuf, rD, s, rS1, s);
+ break;
+
+ case 2:
+ if (threeop)
+ sprintf(buffer, "%s%s%s = %s%s - %s%s", condbuf, rD, s, rS1, s, rS2, s);
+ else
+ sprintf(buffer, "%s%s%s = %s%s - %s%s", condbuf, rD, s, rS1, s, rD, s);
+ break;
+
+ case 3:
+ if (threeop)
+ sprintf(buffer, "%s%s%s = %s%s # %s%s", condbuf, rD, s, rS2, s, rS1, s);
+ else
+ sprintf(buffer, "%s%s%s = %s%s # %s%s", condbuf, rD, s, rD, s, rS1, s);
+ break;
+
+ case 4:
+ if (threeop)
+ sprintf(buffer, "%s%s%s = %s%s - %s%s", condbuf, rD, s, rS2, s, rS1, s);
+ else
+ sprintf(buffer, "%s%s%s = %s%s - %s%s", condbuf, rD, s, rD, s, rS1, s);
+ break;
+
+ case 5:
+ sprintf(buffer, "%s%s%s = -%s%s", condbuf, rD, s, rS1, s);
+ break;
+
+ case 6:
+ if (threeop)
+ sprintf(buffer, "%s%s%s = %s%s &~ %s%s", condbuf, rD, s, rS2, s, rS1, s);
+ else
+ sprintf(buffer, "%s%s%s = %s%s &~ %s%s", condbuf, rD, s, rD, s, rS1, s);
+ break;
+
+ case 7:
+// if (threeop)
+// sprintf(buffer, "%s%s%s - %s%s", condbuf, rS2, s, rS1, s);
+// else
+ sprintf(buffer, "%s%s%s - %s%s", condbuf, rD, s, rS1, s);
+ break;
+
+ case 8:
+ if (threeop)
+ sprintf(buffer, "%s%s%s = %s%s ^ %s%s", condbuf, rD, s, rS2, s, rS1, s);
+ else
+ sprintf(buffer, "%s%s%s = %s%s ^ %s%s", condbuf, rD, s, rD, s, rS1, s);
+ break;
+
+ case 9:
+ sprintf(buffer, "%s%s%s = %s%s >>> 1", condbuf, rD, s, rS1, s);
+ break;
+
+ case 10:
+ if (threeop)
+ sprintf(buffer, "%s%s%s = %s%s | %s%s", condbuf, rD, s, rS2, s, rS1, s);
+ else
+ sprintf(buffer, "%s%s%s = %s%s | %s%s", condbuf, rD, s, rD, s, rS1, s);
+ break;
+
+ case 11:
+ sprintf(buffer, "%s%s%s = %s%s <<< 1", condbuf, rD, s, rS1, s);
+ break;
+
+ case 12:
+ sprintf(buffer, "%s%s%s = %s%s >> 1", condbuf, rD, s, rS1, s);
+ break;
+
+ case 13:
+ sprintf(buffer, "%s%s%s = %s%s / 2", condbuf, rD, s, rS1, s);
+ break;
+
+ case 14:
+ if (threeop)
+ sprintf(buffer, "%s%s%s = %s%s & %s%s", condbuf, rD, s, rS2, s, rS1, s);
+ else
+ sprintf(buffer, "%s%s%s = %s%s & %s%s", condbuf, rD, s, rD, s, rS1, s);
+ break;
+
+ case 15:
+// if (threeop)
+// sprintf(buffer, "%s%s%s & %s%s", condbuf, rS1, s, rS2, s);
+// else
+ sprintf(buffer, "%s%s%s & %s%s", condbuf, rD, s, rS1, s);
+ break;
+ }
+ break;
+ }
+
+ /* CA format 6c/6d */
+ case 0x0d: case 0x4d:
+ {
+ const char *rD = regname[(op >> 16) & 0x1f];
+ const char *s = sizesuffix[(op >> 31) & 1];
+ INT16 N = (INT16)op;
+
+ switch ((op >> 21) & 15)
+ {
+ case 0:
+ case 1:
+ case 5:
+ case 9:
+ case 11:
+ case 12:
+ case 13:
+ sprintf(buffer, "Unexpected: %08X", op);
+ break;
+
+ case 2:
+ sprintf(buffer, "%s%s = %s - %s%s", rD, s, signed_16bit_unary(N), rD, s);
+ break;
+
+ case 3:
+ sprintf(buffer, "%s%s = %s%s # %s", rD, s, rD, s, signed_16bit_unary(N));
+ break;
+
+ case 4:
+ sprintf(buffer, "%s%s = %s%s - %s", rD, s, rD, s, signed_16bit_unary(N));
+ break;
+
+ case 6:
+ sprintf(buffer, "%s%s = %s%s &~ %s", rD, s, rD, s, unsigned_16bit_size(N, (op >> 31) & 1));
+ break;
+
+ case 7:
+ sprintf(buffer, "%s%s - %s", rD, s, signed_16bit_unary(N));
+ break;
+
+ case 8:
+ sprintf(buffer, "%s%s = %s%s ^ %s", rD, s, rD, s, unsigned_16bit_size(N, (op >> 31) & 1));
+ break;
+
+ case 10:
+ sprintf(buffer, "%s%s = %s%s | %s", rD, s, rD, s, unsigned_16bit_size(N, (op >> 31) & 1));
+ break;
+
+ case 14:
+ sprintf(buffer, "%s%s = %s%s & %s", rD, s, rD, s, unsigned_16bit_size(N, (op >> 31) & 1));
+ break;
+
+ case 15:
+ sprintf(buffer, "%s%s & %s", rD, s, unsigned_16bit_size(N, (op >> 31) & 1));
+ break;
+ }
+ break;
+ }
+
+ /* CA format 7a */
+ case 0x0e:
+ if ((op >> 24) & 1)
+ sprintf(buffer, "*%08X = %s%s", (INT16)op, regname[(op >> 16) & 0x1f], memsuffix[(op >> 22) & 3]);
+ else
+ sprintf(buffer, "%s%s = *%08X", regname[(op >> 16) & 0x1f], memsuffix[(op >> 22) & 3], (INT16)op);
+ break;
+
+ /* CA format 7b */
+ case 0x0f:
+ if ((op >> 24) & 1)
+ sprintf(buffer, "%s = %s%s", dasm_PI(op & 0x3ff, tempbuf[0]), regname[(op >> 16) & 0x1f], memsuffix[(op >> 22) & 3]);
+ else
+ sprintf(buffer, "%s%s = %s", regname[(op >> 16) & 0x1f], memsuffix[(op >> 22) & 3], dasm_PI(op & 0x3ff, tempbuf[0]));
+ break;
+
+ /* CA format 8a */
+ case 0x50: case 0x51: case 0x52: case 0x53:
+ case 0x54: case 0x55: case 0x56: case 0x57:
+ case 0x58: case 0x59: case 0x5a: case 0x5b:
+ case 0x5c: case 0x5d: case 0x5e: case 0x5f:
+ {
+ INT32 N = (op & 0xffff) | ((INT32)((op & 0x1fe00000) << 3) >> 8);
+ const char *rH = regname[(op >> 16) & 0x1f];
+
+ if (((op >> 16) & 0x1f) == 15)
+ sprintf(buffer, "goto %s%s [%x]", rH, signed_16bit_sep_nospace(N), (pc + 8 + N) & 0xffffff);
+ else if (N && rH[0] != '0')
+ sprintf(buffer, "goto %s%s", rH, signed_16bit_sep_nospace(N));
+ else if (N)
+ sprintf(buffer, "goto $%x", ((INT32)N & 0xffffff));
+ else
+ {
+ if (((op >> 16) & 0x1f) == 20)
+ flags = DASMFLAG_STEP_OUT;
+ sprintf(buffer, "goto %s", rH);
+ }
+ break;
+ }
+
+ /* CA format 8b */
+ case 0x60: case 0x61: case 0x62: case 0x63:
+ case 0x64: case 0x65: case 0x66: case 0x67:
+ case 0x68: case 0x69: case 0x6a: case 0x6b:
+ case 0x6c: case 0x6d: case 0x6e: case 0x6f:
+ {
+ INT32 immed = (op & 0xffff) | ((INT32)((op & 0x1fe00000) << 3) >> 8);
+ sprintf(buffer, "%s = $%x", regnamee[(op >> 16) & 0x1f], immed & 0xffffff);
+ break;
+ }
+
+ /* CA format 8c */
+ case 0x70: case 0x71: case 0x72: case 0x73:
+ case 0x74: case 0x75: case 0x76: case 0x77:
+ case 0x78: case 0x79: case 0x7a: case 0x7b:
+ case 0x7c: case 0x7d: case 0x7e: case 0x7f:
+ {
+ INT32 N = (op & 0xffff) | ((INT32)((op & 0x1fe00000) << 3) >> 8);
+ const char *rM = regname[(op >> 16) & 0x1f];
+ sprintf(buffer, "call $%x (%s)", N & 0xffffff, rM);
+ flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1);
+ break;
+ }
+ }
+
+ return 4 | flags | DASMFLAG_SUPPORTED;
+}
+
+
+/***************************************************************************
+ DISASSEMBLY HOOK
+***************************************************************************/
+
+CPU_DISASSEMBLE( dsp32c )
+{
+ return dasm_dsp32(buffer, pc, oprom[0] | (oprom[1] << 8) | (oprom[2] << 16) | (oprom[3] << 24));
+}
diff --git a/trunk/src/emu/cpu/dsp32/dsp32ops.c b/trunk/src/emu/cpu/dsp32/dsp32ops.c
new file mode 100644
index 00000000000..bf1fcf5213b
--- /dev/null
+++ b/trunk/src/emu/cpu/dsp32/dsp32ops.c
@@ -0,0 +1,2859 @@
+/***************************************************************************
+
+ dsp32ops.c
+ Core implementation for the portable DSP32 emulator.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+****************************************************************************/
+
+
+
+//**************************************************************************
+// COMPILE-TIME OPTIONS
+//**************************************************************************
+
+// these defined latencies are a pain to implement, but are necessary
+#define EMULATE_MEMORY_LATENCY (1)
+#define EMULATE_MULTIPLIER_LATENCY (1)
+#define EMULATE_AFLAGS_LATENCY (1)
+
+// these optimizations should have some effect, but they don't really, so
+// leave them off
+#define IGNORE_DAU_UV_FLAGS (0)
+#define ASSUME_WRITEABLE (0)
+#define ASSUME_UNCONDITIONAL_CAU (0)
+
+
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+#define SET_V_16(a,b,r) m_vflags = (((a) ^ (b) ^ (r) ^ ((r) >> 1)) << 8)
+#define SET_NZC_16(r) m_nzcflags = ((r) << 8)
+#define SET_NZCV_16(a,b,r) SET_NZC_16(r); SET_V_16(a,b,r)
+#define SET_NZ00_16(r) m_nzcflags = (((r) << 8) & 0xffffff); m_vflags = 0
+
+#define SET_V_24(a,b,r) m_vflags = ((a) ^ (b) ^ (r) ^ ((r) >> 1))
+#define SET_NZC_24(r) m_nzcflags = (r)
+#define SET_NZCV_24(a,b,r) SET_NZC_24(r); SET_V_24(a,b,r)
+#define SET_NZ00_24(r) m_nzcflags = ((r) & 0xffffff); m_vflags = 0
+
+#define TRUNCATE24(a) ((a) & 0xffffff)
+#define EXTEND16_TO_24(a) TRUNCATE24((INT32)(INT16)(a))
+#define REG16(a) ((UINT16)m_r[a])
+#define REG24(a) (m_r[a])
+
+#define WRITEABLE_REGS (0x6f3efffe)
+#if ASSUME_WRITEABLE
+#define IS_WRITEABLE(r) (1)
+#else
+#define IS_WRITEABLE(r) (WRITEABLE_REGS & (1 << (r)))
+#endif
+
+#if ASSUME_UNCONDITIONAL_CAU
+#define CONDITION_IS_TRUE() (1)
+#else
+#define CONDITION_IS_TRUE() (!(op & 0x400) || (condition((op >> 12) & 15)))
+#endif
+
+#if EMULATE_MEMORY_LATENCY
+#define WWORD_DEFERRED(a,v) do { int bufidx = m_mbuf_index & 3; m_mbufaddr[bufidx] = -(a); m_mbufdata[bufidx] = (v); } while (0)
+#define WLONG_DEFERRED(a,v) do { int bufidx = m_mbuf_index & 3; m_mbufaddr[bufidx] = (a); m_mbufdata[bufidx] = (v); } while (0)
+#define PROCESS_DEFERRED_MEMORY() \
+ if (m_mbufaddr[++m_mbuf_index & 3] != 1) \
+ { \
+ int bufidx = m_mbuf_index & 3; \
+ if (m_mbufaddr[bufidx] >= 0) \
+ WLONG(m_mbufaddr[bufidx], m_mbufdata[bufidx]); \
+ else \
+ WWORD(-m_mbufaddr[bufidx], m_mbufdata[bufidx]); \
+ m_mbufaddr[bufidx] = 1; \
+ }
+#else
+#define WWORD_DEFERRED(a,v) WWORD(a,v)
+#define WLONG_DEFERRED(a,v) WLONG(a,v)
+#define PROCESS_DEFERRED_MEMORY()
+#endif
+
+#if EMULATE_MULTIPLIER_LATENCY
+#define DEFERRED_MULTIPLIER(x) dau_get_amult(x)
+#else
+#define DEFERRED_MULTIPLIER(x) m_a[x]
+#endif
+
+#if EMULATE_AFLAGS_LATENCY
+#define DEFERRED_NZFLAGS() dau_get_anzflags()
+#define DEFERRED_VUFLAGS() dau_get_avuflags()
+#else
+#define DEFERRED_NZFLAGS() m_NZflags
+#define DEFERRED_VUFLAGS() m_VUflags
+#endif
+
+
+
+//**************************************************************************
+// TYPEDEFS
+//**************************************************************************
+
+union int_double
+{
+ double d;
+ UINT32 i[2];
+};
+
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+void dsp32c_device::illegal(UINT32 op)
+{
+}
+
+
+void dsp32c_device::unimplemented(UINT32 op)
+{
+ fatalerror("Unimplemented op @ %06X: %08X (dis=%02X, tbl=%03X)", PC - 4, op, op >> 25, op >> 21);
+}
+
+
+inline void dsp32c_device::execute_one()
+{
+ UINT32 op;
+
+ PROCESS_DEFERRED_MEMORY();
+ debugger_instruction_hook(this, PC);
+ op = ROPCODE(PC);
+ m_icount -= 4; // 4 clocks per cycle
+ PC += 4;
+ if (op)
+ (this->*s_dsp32ops[op >> 21])(op);
+}
+
+
+
+//**************************************************************************
+// CAU HELPERS
+//**************************************************************************
+
+UINT32 dsp32c_device::cau_read_pi_special(UINT8 i)
+{
+ switch (i)
+ {
+ case 4: return m_ibuf;
+ case 5: return m_obuf;
+ case 6: update_pcr(m_pcr & ~PCR_PDFs); return m_pdr;
+ case 14: return m_piop;
+ case 20: return m_pdr2;
+ case 22: update_pcr(m_pcr & ~PCR_PIFs); return m_pir;
+ case 30: return m_pcw;
+ default: fprintf(stderr, "Unimplemented CAU PI read = %X\n", i);
+ }
+ return 0;
+}
+
+
+void dsp32c_device::cau_write_pi_special(UINT8 i, UINT32 val)
+{
+ switch (i)
+ {
+ case 4: m_ibuf = val; break;
+ case 5: m_obuf = val; break;
+ case 6: m_pdr = val; update_pcr(m_pcr | PCR_PDFs); break;
+ case 14: m_piop = val; break;
+ case 20: m_pdr2 = val; break;
+ case 22: m_pir = val; update_pcr(m_pcr | PCR_PIFs); break;
+ case 30: m_pcw = val; break;
+ default: fprintf(stderr, "Unimplemented CAU PI write = %X\n", i);
+ }
+}
+
+
+inline UINT8 dsp32c_device::cau_read_pi_1byte(int pi)
+{
+ int p = (pi >> 5) & 0x1f;
+ int i = (pi >> 0) & 0x1f;
+ if (p)
+ {
+ UINT32 result = RBYTE(m_r[p]);
+ m_r[p] = TRUNCATE24(m_r[p] + m_r[i]);
+ return result;
+ }
+ else
+ return cau_read_pi_special(i);
+}
+
+
+inline UINT16 dsp32c_device::cau_read_pi_2byte(int pi)
+{
+ int p = (pi >> 5) & 0x1f;
+ int i = (pi >> 0) & 0x1f;
+ if (p)
+ {
+ UINT32 result = RWORD(m_r[p]);
+ if (i < 22 || i > 23)
+ m_r[p] = TRUNCATE24(m_r[p] + m_r[i]);
+ else
+ m_r[p] = TRUNCATE24(m_r[p] + m_r[i] * 2);
+ return result;
+ }
+ else
+ return cau_read_pi_special(i);
+}
+
+
+inline UINT32 dsp32c_device::cau_read_pi_4byte(int pi)
+{
+ int p = (pi >> 5) & 0x1f;
+ int i = (pi >> 0) & 0x1f;
+ if (p)
+ {
+ UINT32 result = RLONG(m_r[p]);
+ if (i < 22 || i > 23)
+ m_r[p] = TRUNCATE24(m_r[p] + m_r[i]);
+ else
+ m_r[p] = TRUNCATE24(m_r[p] + m_r[i] * 4);
+ return result;
+ }
+ else
+ return cau_read_pi_special(i);
+}
+
+
+inline void dsp32c_device::cau_write_pi_1byte(int pi, UINT8 val)
+{
+ int p = (pi >> 5) & 0x1f;
+ int i = (pi >> 0) & 0x1f;
+ if (p)
+ {
+ WBYTE(m_r[p], val);
+ m_r[p] = TRUNCATE24(m_r[p] + m_r[i]);
+ }
+ else
+ cau_write_pi_special(i, val);
+}
+
+
+inline void dsp32c_device::cau_write_pi_2byte(int pi, UINT16 val)
+{
+ int p = (pi >> 5) & 0x1f;
+ int i = (pi >> 0) & 0x1f;
+ if (p)
+ {
+ WWORD(m_r[p], val);
+ if (i < 22 || i > 23)
+ m_r[p] = TRUNCATE24(m_r[p] + m_r[i]);
+ else
+ m_r[p] = TRUNCATE24(m_r[p] + m_r[i] * 2);
+ }
+ else
+ cau_write_pi_special(i, val);
+}
+
+
+inline void dsp32c_device::cau_write_pi_4byte(int pi, UINT32 val)
+{
+ int p = (pi >> 5) & 0x1f;
+ int i = (pi >> 0) & 0x1f;
+ if (p)
+ {
+ WLONG(m_r[p], (INT32)(val << 8) >> 8);
+ if (i < 22 || i > 23)
+ m_r[p] = TRUNCATE24(m_r[p] + m_r[i]);
+ else
+ m_r[p] = TRUNCATE24(m_r[p] + m_r[i] * 4);
+ }
+ else
+ cau_write_pi_special(i, val);
+}
+
+
+
+//**************************************************************************
+// DAU HELPERS
+//**************************************************************************
+
+inline double dsp32c_device::dau_get_amult(int aidx)
+{
+ int bufidx = (m_abuf_index - 1) & 3;
+ double val = m_a[aidx];
+ while (m_icount >= m_abufcycle[bufidx] - 2 * 4)
+ {
+ if (m_abufreg[bufidx] == aidx)
+ val = m_abuf[bufidx];
+ bufidx = (bufidx - 1) & 3;
+ }
+ return val;
+}
+
+
+inline double dsp32c_device::dau_get_anzflags()
+{
+ int bufidx = (m_abuf_index - 1) & 3;
+ double nzflags = m_NZflags;
+ while (m_icount >= m_abufcycle[bufidx] - 3 * 4)
+ {
+ nzflags = m_abufNZflags[bufidx];
+ bufidx = (bufidx - 1) & 3;
+ }
+ return nzflags;
+}
+
+
+inline UINT8 dsp32c_device::dau_get_avuflags()
+{
+#if (!IGNORE_DAU_UV_FLAGS)
+ int bufidx = (m_abuf_index - 1) & 3;
+ UINT8 vuflags = m_VUflags;
+ while (m_icount >= m_abufcycle[bufidx] - 3 * 4)
+ {
+ vuflags = m_abufVUflags[bufidx];
+ bufidx = (bufidx - 1) & 3;
+ }
+ return vuflags;
+#else
+ return 0;
+#endif
+}
+
+
+inline void dsp32c_device::remember_last_dau(int aidx)
+{
+#if (EMULATE_MULTIPLIER_LATENCY || EMULATE_AFLAGS_LATENCY)
+ int bufidx = m_abuf_index++ & 3;
+ m_abuf[bufidx] = m_a[aidx];
+ m_abufreg[bufidx] = aidx;
+ m_abufNZflags[bufidx] = m_NZflags;
+#if (!IGNORE_DAU_UV_FLAGS)
+ m_abufVUflags[bufidx] = m_VUflags;
+#endif
+ m_abufcycle[bufidx] = m_icount;
+#endif
+}
+
+
+inline void dsp32c_device::dau_set_val_noflags(int aidx, double res)
+{
+ remember_last_dau(aidx);
+ m_a[aidx] = res;
+}
+
+
+inline void dsp32c_device::dau_set_val_flags(int aidx, double res)
+{
+ remember_last_dau(aidx);
+#if (!IGNORE_DAU_UV_FLAGS)
+{
+ double absres = (res < 0) ? -res : res;
+ m_VUflags = 0;
+ if (absres < 5.87747e-39)
+ {
+ if (absres != 0)
+ m_VUflags = UFLAGBIT;
+ res = 0.0;
+ }
+ else if (absres > 3.40282e38)
+ {
+ m_VUflags = VFLAGBIT;
+// debugger_break(Machine);
+// fprintf(stderr, "Result = %g\n", absres);
+ res = (res < 0) ? -3.40282e38 : 3.40282e38;
+ }
+}
+#endif
+ m_NZflags = res;
+ m_a[aidx] = res;
+}
+
+
+inline double dsp32c_device::dsp_to_double(UINT32 val)
+{
+ int_double id;
+
+ if (val == 0)
+ return 0;
+ else if ((INT32)val > 0)
+ {
+ int exponent = ((val & 0xff) - 128 + 1023) << 20;
+ id.i[BYTE_XOR_BE(0)] = exponent + (val >> 11);
+ id.i[BYTE_XOR_BE(1)] = (val << 21) & 0xe0000000;
+ }
+ else
+ {
+ int exponent = ((val & 0xff) - 128 + 1023) << 20;
+ val = -(val & 0xffffff00);
+ id.i[BYTE_XOR_BE(0)] = 0x80000000 + exponent + ((val >> 11) & 0x001fffff);
+ id.i[BYTE_XOR_BE(1)] = (val << 21) & 0xe0000000;
+ }
+ return id.d;
+}
+
+
+inline UINT32 dsp32c_device::double_to_dsp(double val)
+{
+ int mantissa, exponent;
+ int_double id;
+ id.d = val;
+ mantissa = ((id.i[BYTE_XOR_BE(0)] & 0x000fffff) << 11) | ((id.i[BYTE_XOR_BE(1)] & 0xe0000000) >> 21);
+ exponent = ((id.i[BYTE_XOR_BE(0)] & 0x7ff00000) >> 20) - 1023 + 128;
+ if (exponent < 0)
+ return 0x00000000;
+ else if (exponent > 255)
+ {
+// debugger_break(Machine);
+// fprintf(stderr, "Exponent = %d\n", exponent);
+ return ((INT32)id.i[BYTE_XOR_BE(0)] >= 0) ? 0x7fffffff : 0x800000ff;
+ }
+ else if ((INT32)id.i[BYTE_XOR_BE(0)] >= 0)
+ return exponent | mantissa;
+ else
+ {
+ mantissa = -mantissa;
+ if (mantissa == 0) { mantissa = 0x80000000; exponent--; }
+ return 0x80000000 | exponent | (mantissa & 0xffffff00);
+ }
+}
+
+
+double dsp32c_device::dau_read_pi_special(int i)
+{
+ fatalerror("Unimplemented dau_read_pi_special(%d)", i);
+ return 0;
+}
+
+
+void dsp32c_device::dau_write_pi_special(int i, double val)
+{
+ fatalerror("Unimplemented dau_write_pi_special(%d)", i);
+}
+
+
+inline double dsp32c_device::dau_read_pi_double_1st(int pi, int multiplier)
+{
+ int p = (pi >> 3) & 15;
+ int i = (pi >> 0) & 7;
+
+ m_lastp = p;
+ if (p)
+ {
+ UINT32 result = RLONG(m_r[p]);
+ if (i < 6)
+ m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16]);
+ else
+ m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16] * 4);
+ return dsp_to_double(result);
+ }
+ else if (i < 4)
+ return multiplier ? DEFERRED_MULTIPLIER(i) : m_a[i];
+ else
+ return dau_read_pi_special(i);
+}
+
+
+inline double dsp32c_device::dau_read_pi_double_2nd(int pi, int multiplier, double xval)
+{
+ int p = (pi >> 3) & 15;
+ int i = (pi >> 0) & 7;
+
+ if (p == 15) p = m_lastp; // P=15 means Z inherits from Y, Y inherits from X
+ m_lastp = p;
+ if (p)
+ {
+ UINT32 result;
+ result = RLONG(m_r[p]);
+ if (i < 6)
+ m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16]);
+ else
+ m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16] * 4);
+ return dsp_to_double(result);
+ }
+ else if (i < 4)
+ return multiplier ? DEFERRED_MULTIPLIER(i) : m_a[i];
+ else
+ return dau_read_pi_special(i);
+}
+
+
+inline UINT32 dsp32c_device::dau_read_pi_4bytes(int pi)
+{
+ int p = (pi >> 3) & 15;
+ int i = (pi >> 0) & 7;
+
+ m_lastp = p;
+ if (p)
+ {
+ UINT32 result = RLONG(m_r[p]);
+ if (i < 6)
+ m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16]);
+ else
+ m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16] * 4);
+ return result;
+ }
+ else if (i < 4)
+ return double_to_dsp(m_a[i]);
+ else
+ return dau_read_pi_special(i);
+}
+
+
+inline UINT16 dsp32c_device::dau_read_pi_2bytes(int pi)
+{
+ int p = (pi >> 3) & 15;
+ int i = (pi >> 0) & 7;
+
+ m_lastp = p;
+ if (p)
+ {
+ UINT32 result = RWORD(m_r[p]);
+ if (i < 6)
+ m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16]);
+ else
+ m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16] * 2);
+ return result;
+ }
+ else if (i < 4)
+ return double_to_dsp(m_a[i]);
+ else
+ return dau_read_pi_special(i);
+}
+
+
+inline void dsp32c_device::dau_write_pi_double(int pi, double val)
+{
+ int p = (pi >> 3) & 15;
+ int i = (pi >> 0) & 7;
+
+ if (p == 15) p = m_lastp; // P=15 means Z inherits from Y, Y inherits from X
+ if (p)
+ {
+ WLONG_DEFERRED(m_r[p], double_to_dsp(val));
+ if (i < 6)
+ m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16]);
+ else
+ m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16] * 4);
+ }
+ else if (i < 4)
+ dau_set_val_noflags(i, val);
+ else
+ dau_write_pi_special(i, val);
+}
+
+
+inline void dsp32c_device::dau_write_pi_4bytes(int pi, UINT32 val)
+{
+ int p = (pi >> 3) & 15;
+ int i = (pi >> 0) & 7;
+
+ if (p == 15) p = m_lastp; // P=15 means Z inherits from Y, Y inherits from X
+ if (p)
+ {
+ m_lastp = p;
+ WLONG_DEFERRED(m_r[p], val);
+ if (i < 6)
+ m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16]);
+ else
+ m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16] * 4);
+ }
+ else if (i < 4)
+ dau_set_val_noflags(i, dsp_to_double(val));
+ else
+ dau_write_pi_special(i, val);
+}
+
+
+inline void dsp32c_device::dau_write_pi_2bytes(int pi, UINT16 val)
+{
+ int p = (pi >> 3) & 15;
+ int i = (pi >> 0) & 7;
+
+ if (p == 15) p = m_lastp; // P=15 means Z inherits from Y, Y inherits from X
+ if (p)
+ {
+ m_lastp = p;
+ WWORD_DEFERRED(m_r[p], val);
+ if (i < 6)
+ m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16]);
+ else
+ m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16] * 2);
+ }
+ else if (i < 4)
+ dau_set_val_noflags(i, dsp_to_double(val << 16));
+ else
+ dau_write_pi_special(i, val);
+}
+
+
+
+//**************************************************************************
+// COMMON CONDITION ROUTINE
+//**************************************************************************
+
+#if (!ASSUME_UNCONDITIONAL_CAU)
+int dsp32c_device::condition(int cond)
+{
+ switch (cond)
+ {
+ case 0:
+ return 0;
+ case 1:
+ return 1;
+ case 2:
+ return !nFLAG;
+ case 3:
+ return nFLAG;
+ case 4:
+ return !zFLAG;
+ case 5:
+ return zFLAG;
+ case 6:
+ return !vFLAG;
+ case 7:
+ return vFLAG;
+ case 8:
+ return !cFLAG;
+ case 9:
+ return cFLAG;
+ case 10:
+ return !(nFLAG ^ cFLAG);
+ case 11:
+ return (nFLAG ^ cFLAG);
+ case 12:
+ return !(zFLAG | (nFLAG ^ vFLAG));
+ case 13:
+ return (zFLAG | (nFLAG ^ vFLAG));
+ case 14:
+ return !(cFLAG | zFLAG);
+ case 15:
+ return (cFLAG | zFLAG);
+
+ case 16:
+ return !(DEFERRED_VUFLAGS() & UFLAGBIT);
+ case 17:
+ return (DEFERRED_VUFLAGS() & UFLAGBIT);
+ case 18:
+ return !(DEFERRED_NZFLAGS() < 0);
+ case 19:
+ return (DEFERRED_NZFLAGS() < 0);
+ case 20:
+ return !(DEFERRED_NZFLAGS() == 0);
+ case 21:
+ return (DEFERRED_NZFLAGS() == 0);
+ case 22:
+ return !(DEFERRED_VUFLAGS() & VFLAGBIT);
+ case 23:
+ return (DEFERRED_VUFLAGS() & VFLAGBIT);
+ case 24:
+ return !(DEFERRED_NZFLAGS() <= 0);
+ case 25:
+ return (DEFERRED_NZFLAGS() <= 0);
+
+ case 32: // !ibf
+ case 33: // ibf
+ case 34: // !obe
+ case 35: // obe
+ case 36: // !pdf
+ case 37: // pdf
+ case 38: // !pif
+ case 39: // pif
+ case 40: // !sy
+ case 41: // sy
+ case 42: // !fb
+ case 43: // fb
+ case 44: // !ireq1
+ case 45: // ireq1
+ case 46: // !ireq2
+ case 47: // ireq2
+ default:
+ fatalerror("Unimplemented condition: %X", cond);
+ }
+}
+#endif
+
+
+
+//**************************************************************************
+// CAU BRANCH INSTRUCTION IMPLEMENTATION
+//**************************************************************************
+
+void dsp32c_device::nop(UINT32 op)
+{
+ if (op == 0)
+ return;
+ execute_one();
+ PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op);
+}
+
+
+void dsp32c_device::goto_t(UINT32 op)
+{
+ execute_one();
+ PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op);
+}
+
+
+void dsp32c_device::goto_pl(UINT32 op)
+{
+ if (!nFLAG)
+ {
+ execute_one();
+ PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op);
+ }
+}
+
+
+void dsp32c_device::goto_mi(UINT32 op)
+{
+ if (nFLAG)
+ {
+ execute_one();
+ PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op);
+ }
+}
+
+
+void dsp32c_device::goto_ne(UINT32 op)
+{
+ if (!zFLAG)
+ {
+ execute_one();
+ PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op);
+ }
+}
+
+
+void dsp32c_device::goto_eq(UINT32 op)
+{
+ if (zFLAG)
+ {
+ execute_one();
+ PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op);
+ }
+}
+
+
+void dsp32c_device::goto_vc(UINT32 op)
+{
+ if (!vFLAG)
+ {
+ execute_one();
+ PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op);
+ }
+}
+
+
+void dsp32c_device::goto_vs(UINT32 op)
+{
+ if (vFLAG)
+ {
+ execute_one();
+ PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op);
+ }
+}
+
+
+void dsp32c_device::goto_cc(UINT32 op)
+{
+ if (!cFLAG)
+ {
+ execute_one();
+ PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op);
+ }
+}
+
+
+void dsp32c_device::goto_cs(UINT32 op)
+{
+ if (cFLAG)
+ {
+ execute_one();
+ PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op);
+ }
+}
+
+
+void dsp32c_device::goto_ge(UINT32 op)
+{
+ if (!(nFLAG ^ vFLAG))
+ {
+ execute_one();
+ PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op);
+ }
+}
+
+
+void dsp32c_device::goto_lt(UINT32 op)
+{
+ if (nFLAG ^ vFLAG)
+ {
+ execute_one();
+ PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op);
+ }
+}
+
+
+void dsp32c_device::goto_gt(UINT32 op)
+{
+ if (!(zFLAG | (nFLAG ^ vFLAG)))
+ {
+ execute_one();
+ PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op);
+ }
+}
+
+
+void dsp32c_device::goto_le(UINT32 op)
+{
+ if (zFLAG | (nFLAG ^ vFLAG))
+ {
+ execute_one();
+ PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op);
+ }
+}
+
+
+void dsp32c_device::goto_hi(UINT32 op)
+{
+ if (!cFLAG && !zFLAG)
+ {
+ execute_one();
+ PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op);
+ }
+}
+
+
+void dsp32c_device::goto_ls(UINT32 op)
+{
+ if (cFLAG || zFLAG)
+ {
+ execute_one();
+ PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op);
+ }
+}
+
+
+void dsp32c_device::goto_auc(UINT32 op)
+{
+ if (!(DEFERRED_VUFLAGS() & UFLAGBIT))
+ {
+ execute_one();
+ PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op);
+ }
+}
+
+
+void dsp32c_device::goto_aus(UINT32 op)
+{
+ if (DEFERRED_VUFLAGS() & UFLAGBIT)
+ {
+ execute_one();
+ PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op);
+ }
+}
+
+
+void dsp32c_device::goto_age(UINT32 op)
+{
+ if (DEFERRED_NZFLAGS() >= 0)
+ {
+ execute_one();
+ PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op);
+ }
+}
+
+
+void dsp32c_device::goto_alt(UINT32 op)
+{
+ if (DEFERRED_NZFLAGS() < 0)
+ {
+ execute_one();
+ PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op);
+ }
+}
+
+
+void dsp32c_device::goto_ane(UINT32 op)
+{
+ if (DEFERRED_NZFLAGS() != 0)
+ {
+ execute_one();
+ PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op);
+ }
+}
+
+
+void dsp32c_device::goto_aeq(UINT32 op)
+{
+ if (DEFERRED_NZFLAGS() == 0)
+ {
+ execute_one();
+ PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op);
+ }
+}
+
+
+void dsp32c_device::goto_avc(UINT32 op)
+{
+ if (!(DEFERRED_VUFLAGS() & VFLAGBIT))
+ {
+ execute_one();
+ PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op);
+ }
+}
+
+
+void dsp32c_device::goto_avs(UINT32 op)
+{
+ if (DEFERRED_VUFLAGS() & VFLAGBIT)
+ {
+ execute_one();
+ PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op);
+ }
+}
+
+
+void dsp32c_device::goto_agt(UINT32 op)
+{
+ if (DEFERRED_NZFLAGS() > 0)
+ {
+ execute_one();
+ PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op);
+ }
+}
+
+
+void dsp32c_device::goto_ale(UINT32 op)
+{
+ if (DEFERRED_NZFLAGS() <= 0)
+ {
+ execute_one();
+ PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op);
+ }
+}
+
+
+void dsp32c_device::goto_ibe(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+void dsp32c_device::goto_ibf(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+void dsp32c_device::goto_obf(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+void dsp32c_device::goto_obe(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+void dsp32c_device::goto_pde(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+void dsp32c_device::goto_pdf(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+void dsp32c_device::goto_pie(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+void dsp32c_device::goto_pif(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+void dsp32c_device::goto_syc(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+void dsp32c_device::goto_sys(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+void dsp32c_device::goto_fbc(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+void dsp32c_device::goto_fbs(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+void dsp32c_device::goto_irq1lo(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+void dsp32c_device::goto_irq1hi(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+void dsp32c_device::goto_irq2lo(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+void dsp32c_device::goto_irq2hi(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+void dsp32c_device::dec_goto(UINT32 op)
+{
+ int hr = (op >> 21) & 0x1f;
+ int old = (INT16)m_r[hr];
+ m_r[hr] = EXTEND16_TO_24(m_r[hr] - 1);
+ if (old >= 0)
+ {
+ execute_one();
+ PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op);
+ }
+}
+
+
+void dsp32c_device::call(UINT32 op)
+{
+ int mr = (op >> 21) & 0x1f;
+ if (IS_WRITEABLE(mr))
+ m_r[mr] = PC + 4;
+ execute_one();
+ PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op);
+}
+
+
+void dsp32c_device::goto24(UINT32 op)
+{
+ execute_one();
+ PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (op & 0xffff) + ((op >> 5) & 0xff0000));
+}
+
+
+void dsp32c_device::call24(UINT32 op)
+{
+ int mr = (op >> 16) & 0x1f;
+ if (IS_WRITEABLE(mr))
+ m_r[mr] = PC + 4;
+ execute_one();
+ PC = (op & 0xffff) + ((op >> 5) & 0xff0000);
+}
+
+
+void dsp32c_device::do_i(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+void dsp32c_device::do_r(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+
+//**************************************************************************
+// CAU 16-BIT ARITHMETIC IMPLEMENTATION
+//**************************************************************************
+
+void dsp32c_device::add_si(UINT32 op)
+{
+ int dr = (op >> 21) & 0x1f;
+ int hrval = REG16((op >> 16) & 0x1f);
+ int res = hrval + (UINT16)op;
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = EXTEND16_TO_24(res);
+ SET_NZCV_16(hrval, op, res);
+}
+
+
+void dsp32c_device::add_ss(UINT32 op)
+{
+ if (CONDITION_IS_TRUE())
+ {
+ int dr = (op >> 16) & 0x1f;
+ int s1rval = REG16((op >> 5) & 0x1f);
+ int s2rval = (op & 0x800) ? REG16((op >> 0) & 0x1f) : REG16(dr);
+ int res = s2rval + s1rval;
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = EXTEND16_TO_24(res);
+ SET_NZCV_16(s1rval, s2rval, res);
+ }
+}
+
+
+void dsp32c_device::mul2_s(UINT32 op)
+{
+ if (CONDITION_IS_TRUE())
+ {
+ int dr = (op >> 16) & 0x1f;
+ int s1rval = REG16((op >> 5) & 0x1f);
+ int res = s1rval * 2;
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = EXTEND16_TO_24(res);
+ SET_NZCV_16(s1rval, 0, res);
+ }
+}
+
+
+void dsp32c_device::subr_ss(UINT32 op)
+{
+ if (CONDITION_IS_TRUE())
+ {
+ int dr = (op >> 16) & 0x1f;
+ int s1rval = REG16((op >> 5) & 0x1f);
+ int s2rval = (op & 0x800) ? REG16((op >> 0) & 0x1f) : REG16(dr);
+ int res = s1rval - s2rval;
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = EXTEND16_TO_24(res);
+ SET_NZCV_16(s1rval, s2rval, res);
+ }
+}
+
+
+void dsp32c_device::addr_ss(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+void dsp32c_device::sub_ss(UINT32 op)
+{
+ if (CONDITION_IS_TRUE())
+ {
+ int dr = (op >> 16) & 0x1f;
+ int s1rval = REG16((op >> 5) & 0x1f);
+ int s2rval = (op & 0x800) ? REG16((op >> 0) & 0x1f) : REG16(dr);
+ int res = s2rval - s1rval;
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = EXTEND16_TO_24(res);
+ SET_NZCV_16(s1rval, s2rval, res);
+ }
+}
+
+
+void dsp32c_device::neg_s(UINT32 op)
+{
+ if (CONDITION_IS_TRUE())
+ {
+ int dr = (op >> 16) & 0x1f;
+ int s1rval = REG16((op >> 5) & 0x1f);
+ int res = -s1rval;
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = EXTEND16_TO_24(res);
+ SET_NZCV_16(s1rval, 0, res);
+ }
+}
+
+
+void dsp32c_device::andc_ss(UINT32 op)
+{
+ if (CONDITION_IS_TRUE())
+ {
+ int dr = (op >> 16) & 0x1f;
+ int s1rval = REG16((op >> 5) & 0x1f);
+ int s2rval = (op & 0x800) ? REG16((op >> 0) & 0x1f) : REG16(dr);
+ int res = s2rval & ~s1rval;
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = EXTEND16_TO_24(res);
+ SET_NZ00_16(res);
+ }
+}
+
+
+void dsp32c_device::cmp_ss(UINT32 op)
+{
+ if (CONDITION_IS_TRUE())
+ {
+ int drval = REG16((op >> 16) & 0x1f);
+ int s1rval = REG16((op >> 5) & 0x1f);
+ int res = drval - s1rval;
+ SET_NZCV_16(drval, s1rval, res);
+ }
+}
+
+
+void dsp32c_device::xor_ss(UINT32 op)
+{
+ if (CONDITION_IS_TRUE())
+ {
+ int dr = (op >> 16) & 0x1f;
+ int s1rval = REG16((op >> 5) & 0x1f);
+ int s2rval = (op & 0x800) ? REG16((op >> 0) & 0x1f) : REG16(dr);
+ int res = s2rval ^ s1rval;
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = EXTEND16_TO_24(res);
+ SET_NZ00_16(res);
+ }
+}
+
+
+void dsp32c_device::rcr_s(UINT32 op)
+{
+ if (CONDITION_IS_TRUE())
+ {
+ int dr = (op >> 16) & 0x1f;
+ int s1rval = REG16((op >> 5) & 0x1f);
+ int res = ((m_nzcflags >> 9) & 0x8000) | (s1rval >> 1);
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = EXTEND16_TO_24(res);
+ m_nzcflags = ((res & 0xffff) << 8) | ((s1rval & 1) << 24);
+ m_vflags = 0;
+ }
+}
+
+
+void dsp32c_device::or_ss(UINT32 op)
+{
+ if (CONDITION_IS_TRUE())
+ {
+ int dr = (op >> 16) & 0x1f;
+ int s1rval = REG16((op >> 5) & 0x1f);
+ int s2rval = (op & 0x800) ? REG16((op >> 0) & 0x1f) : REG16(dr);
+ int res = s2rval | s1rval;
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = EXTEND16_TO_24(res);
+ SET_NZ00_16(res);
+ }
+}
+
+
+void dsp32c_device::rcl_s(UINT32 op)
+{
+ if (CONDITION_IS_TRUE())
+ {
+ int dr = (op >> 16) & 0x1f;
+ int s1rval = REG16((op >> 5) & 0x1f);
+ int res = ((m_nzcflags >> 24) & 0x0001) | (s1rval << 1);
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = EXTEND16_TO_24(res);
+ m_nzcflags = ((res & 0xffff) << 8) | ((s1rval & 0x8000) << 9);
+ m_vflags = 0;
+ }
+}
+
+
+void dsp32c_device::shr_s(UINT32 op)
+{
+ if (CONDITION_IS_TRUE())
+ {
+ int dr = (op >> 16) & 0x1f;
+ int s1rval = REG16((op >> 5) & 0x1f);
+ int res = s1rval >> 1;
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = EXTEND16_TO_24(res);
+ m_nzcflags = ((res & 0xffff) << 8) | ((s1rval & 1) << 24);
+ m_vflags = 0;
+ }
+}
+
+
+void dsp32c_device::div2_s(UINT32 op)
+{
+ if (CONDITION_IS_TRUE())
+ {
+ int dr = (op >> 16) & 0x1f;
+ int s1rval = REG16((op >> 5) & 0x1f);
+ int res = (s1rval & 0x8000) | (s1rval >> 1);
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = EXTEND16_TO_24(res);
+ m_nzcflags = ((res & 0xffff) << 8) | ((s1rval & 1) << 24);
+ m_vflags = 0;
+ }
+}
+
+
+void dsp32c_device::and_ss(UINT32 op)
+{
+ if (CONDITION_IS_TRUE())
+ {
+ int dr = (op >> 16) & 0x1f;
+ int s1rval = REG16((op >> 5) & 0x1f);
+ int s2rval = (op & 0x800) ? REG16((op >> 0) & 0x1f) : REG16(dr);
+ int res = s2rval & s1rval;
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = EXTEND16_TO_24(res);
+ SET_NZ00_16(res);
+ }
+}
+
+
+void dsp32c_device::test_ss(UINT32 op)
+{
+ if (CONDITION_IS_TRUE())
+ {
+ int drval = REG16((op >> 16) & 0x1f);
+ int s1rval = REG16((op >> 5) & 0x1f);
+ int res = drval & s1rval;
+ SET_NZ00_16(res);
+ }
+}
+
+
+void dsp32c_device::add_di(UINT32 op)
+{
+ int dr = (op >> 16) & 0x1f;
+ int drval = REG16(dr);
+ int res = drval + (UINT16)op;
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = EXTEND16_TO_24(res);
+ SET_NZCV_16(drval, op, res);
+}
+
+
+void dsp32c_device::subr_di(UINT32 op)
+{
+ int dr = (op >> 16) & 0x1f;
+ int drval = REG16(dr);
+ int res = (UINT16)op - drval;
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = EXTEND16_TO_24(res);
+ SET_NZCV_16(drval, op, res);
+}
+
+
+void dsp32c_device::addr_di(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+void dsp32c_device::sub_di(UINT32 op)
+{
+ int dr = (op >> 16) & 0x1f;
+ int drval = REG16(dr);
+ int res = drval - (UINT16)op;
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = EXTEND16_TO_24(res);
+ SET_NZCV_16(drval, op, res);
+}
+
+
+void dsp32c_device::andc_di(UINT32 op)
+{
+ int dr = (op >> 16) & 0x1f;
+ int drval = REG16(dr);
+ int res = drval & ~(UINT16)op;
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = EXTEND16_TO_24(res);
+ SET_NZ00_16(res);
+}
+
+
+void dsp32c_device::cmp_di(UINT32 op)
+{
+ int drval = REG16((op >> 16) & 0x1f);
+ int res = drval - (UINT16)op;
+ SET_NZCV_16(drval, op, res);
+}
+
+
+void dsp32c_device::xor_di(UINT32 op)
+{
+ int dr = (op >> 16) & 0x1f;
+ int drval = REG16(dr);
+ int res = drval ^ (UINT16)op;
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = EXTEND16_TO_24(res);
+ SET_NZ00_16(res);
+}
+
+
+void dsp32c_device::or_di(UINT32 op)
+{
+ int dr = (op >> 16) & 0x1f;
+ int drval = REG16(dr);
+ int res = drval | (UINT16)op;
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = EXTEND16_TO_24(res);
+ SET_NZ00_16(res);
+}
+
+
+void dsp32c_device::and_di(UINT32 op)
+{
+ int dr = (op >> 16) & 0x1f;
+ int drval = REG16(dr);
+ int res = drval & (UINT16)op;
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = EXTEND16_TO_24(res);
+ SET_NZ00_16(res);
+}
+
+
+void dsp32c_device::test_di(UINT32 op)
+{
+ int drval = REG16((op >> 16) & 0x1f);
+ int res = drval & (UINT16)op;
+ SET_NZ00_16(res);
+}
+
+
+
+//**************************************************************************
+// CAU 24-BIT ARITHMETIC IMPLEMENTATION
+//**************************************************************************
+
+void dsp32c_device::adde_si(UINT32 op)
+{
+ int dr = (op >> 21) & 0x1f;
+ int hrval = REG24((op >> 16) & 0x1f);
+ int res = hrval + EXTEND16_TO_24(op);
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = TRUNCATE24(res);
+ SET_NZCV_24(hrval, op << 8, res);
+}
+
+
+void dsp32c_device::adde_ss(UINT32 op)
+{
+ if (CONDITION_IS_TRUE())
+ {
+ int dr = (op >> 16) & 0x1f;
+ int s1rval = REG24((op >> 5) & 0x1f);
+ int s2rval = (op & 0x800) ? REG24((op >> 0) & 0x1f) : REG24(dr);
+ int res = s2rval + s1rval;
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = TRUNCATE24(res);
+ SET_NZCV_24(s1rval, s2rval, res);
+ }
+}
+
+
+void dsp32c_device::mul2e_s(UINT32 op)
+{
+ if (CONDITION_IS_TRUE())
+ {
+ int dr = (op >> 16) & 0x1f;
+ int s1rval = REG24((op >> 5) & 0x1f);
+ int res = s1rval * 2;
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = TRUNCATE24(res);
+ SET_NZCV_24(s1rval, 0, res);
+ }
+}
+
+
+void dsp32c_device::subre_ss(UINT32 op)
+{
+ if (CONDITION_IS_TRUE())
+ {
+ int dr = (op >> 16) & 0x1f;
+ int s1rval = REG24((op >> 5) & 0x1f);
+ int s2rval = (op & 0x800) ? REG24((op >> 0) & 0x1f) : REG24(dr);
+ int res = s1rval - s2rval;
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = TRUNCATE24(res);
+ SET_NZCV_24(s1rval, s2rval, res);
+ }
+}
+
+
+void dsp32c_device::addre_ss(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+void dsp32c_device::sube_ss(UINT32 op)
+{
+ if (CONDITION_IS_TRUE())
+ {
+ int dr = (op >> 16) & 0x1f;
+ int s1rval = REG24((op >> 5) & 0x1f);
+ int s2rval = (op & 0x800) ? REG24((op >> 0) & 0x1f) : REG24(dr);
+ int res = s2rval - s1rval;
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = TRUNCATE24(res);
+ SET_NZCV_24(s1rval, s2rval, res);
+ }
+}
+
+
+void dsp32c_device::nege_s(UINT32 op)
+{
+ if (CONDITION_IS_TRUE())
+ {
+ int dr = (op >> 16) & 0x1f;
+ int s1rval = REG24((op >> 5) & 0x1f);
+ int res = -s1rval;
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = TRUNCATE24(res);
+ SET_NZCV_24(s1rval, 0, res);
+ }
+}
+
+
+void dsp32c_device::andce_ss(UINT32 op)
+{
+ if (CONDITION_IS_TRUE())
+ {
+ int dr = (op >> 16) & 0x1f;
+ int s1rval = REG24((op >> 5) & 0x1f);
+ int s2rval = (op & 0x800) ? REG24((op >> 0) & 0x1f) : REG24(dr);
+ int res = s2rval & ~s1rval;
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = res;
+ SET_NZ00_24(res);
+ }
+}
+
+
+void dsp32c_device::cmpe_ss(UINT32 op)
+{
+ if (CONDITION_IS_TRUE())
+ {
+ int drval = REG24((op >> 16) & 0x1f);
+ int s1rval = REG24((op >> 5) & 0x1f);
+ int res = drval - s1rval;
+ SET_NZCV_24(drval, s1rval, res);
+ }
+}
+
+
+void dsp32c_device::xore_ss(UINT32 op)
+{
+ if (CONDITION_IS_TRUE())
+ {
+ int dr = (op >> 16) & 0x1f;
+ int s1rval = REG24((op >> 5) & 0x1f);
+ int s2rval = (op & 0x800) ? REG24((op >> 0) & 0x1f) : REG24(dr);
+ int res = s2rval ^ s1rval;
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = res;
+ SET_NZ00_24(res);
+ }
+}
+
+
+void dsp32c_device::rcre_s(UINT32 op)
+{
+ if (CONDITION_IS_TRUE())
+ {
+ int dr = (op >> 16) & 0x1f;
+ int s1rval = REG24((op >> 5) & 0x1f);
+ int res = ((m_nzcflags >> 1) & 0x800000) | (s1rval >> 1);
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = TRUNCATE24(res);
+ m_nzcflags = res | ((s1rval & 1) << 24);
+ m_vflags = 0;
+ }
+}
+
+
+void dsp32c_device::ore_ss(UINT32 op)
+{
+ if (CONDITION_IS_TRUE())
+ {
+ int dr = (op >> 16) & 0x1f;
+ int s1rval = REG24((op >> 5) & 0x1f);
+ int s2rval = (op & 0x800) ? REG24((op >> 0) & 0x1f) : REG24(dr);
+ int res = s2rval | s1rval;
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = res;
+ SET_NZ00_24(res);
+ }
+}
+
+
+void dsp32c_device::rcle_s(UINT32 op)
+{
+ if (CONDITION_IS_TRUE())
+ {
+ int dr = (op >> 16) & 0x1f;
+ int s1rval = REG24((op >> 5) & 0x1f);
+ int res = ((m_nzcflags >> 24) & 0x000001) | (s1rval << 1);
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = TRUNCATE24(res);
+ m_nzcflags = res | ((s1rval & 0x800000) << 1);
+ m_vflags = 0;
+ }
+}
+
+
+void dsp32c_device::shre_s(UINT32 op)
+{
+ if (CONDITION_IS_TRUE())
+ {
+ int dr = (op >> 16) & 0x1f;
+ int s1rval = REG24((op >> 5) & 0x1f);
+ int res = s1rval >> 1;
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = res;
+ m_nzcflags = res | ((s1rval & 1) << 24);
+ m_vflags = 0;
+ }
+}
+
+
+void dsp32c_device::div2e_s(UINT32 op)
+{
+ if (CONDITION_IS_TRUE())
+ {
+ int dr = (op >> 16) & 0x1f;
+ int s1rval = REG24((op >> 5) & 0x1f);
+ int res = (s1rval & 0x800000) | (s1rval >> 1);
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = TRUNCATE24(res);
+ m_nzcflags = res | ((s1rval & 1) << 24);
+ m_vflags = 0;
+ }
+}
+
+
+void dsp32c_device::ande_ss(UINT32 op)
+{
+ if (CONDITION_IS_TRUE())
+ {
+ int dr = (op >> 16) & 0x1f;
+ int s1rval = REG24((op >> 5) & 0x1f);
+ int s2rval = (op & 0x800) ? REG24((op >> 0) & 0x1f) : REG24(dr);
+ int res = s2rval & s1rval;
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = res;
+ SET_NZ00_24(res);
+ }
+}
+
+
+void dsp32c_device::teste_ss(UINT32 op)
+{
+ if (CONDITION_IS_TRUE())
+ {
+ int drval = REG24((op >> 16) & 0x1f);
+ int s1rval = REG24((op >> 5) & 0x1f);
+ int res = drval & s1rval;
+ SET_NZ00_24(res);
+ }
+}
+
+
+void dsp32c_device::adde_di(UINT32 op)
+{
+ int dr = (op >> 16) & 0x1f;
+ int drval = REG24(dr);
+ int res = drval + EXTEND16_TO_24(op);
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = TRUNCATE24(res);
+ SET_NZCV_24(drval, op << 8, res);
+}
+
+
+void dsp32c_device::subre_di(UINT32 op)
+{
+ int dr = (op >> 16) & 0x1f;
+ int drval = REG24(dr);
+ int res = EXTEND16_TO_24(op) - drval;
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = TRUNCATE24(res);
+ SET_NZCV_24(drval, op << 8, res);
+}
+
+
+void dsp32c_device::addre_di(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+void dsp32c_device::sube_di(UINT32 op)
+{
+ int dr = (op >> 16) & 0x1f;
+ int drval = REG24(dr);
+ int res = drval - EXTEND16_TO_24(op);
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = TRUNCATE24(res);
+ SET_NZCV_24(drval, op << 8, res);
+}
+
+
+void dsp32c_device::andce_di(UINT32 op)
+{
+ int dr = (op >> 16) & 0x1f;
+ int drval = REG24(dr);
+ int res = drval & ~EXTEND16_TO_24(op);
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = res;
+ SET_NZ00_24(res);
+}
+
+
+void dsp32c_device::cmpe_di(UINT32 op)
+{
+ int drval = REG24((op >> 16) & 0x1f);
+ int res = drval - EXTEND16_TO_24(op);
+ SET_NZCV_24(drval, op << 8, res);
+}
+
+
+void dsp32c_device::xore_di(UINT32 op)
+{
+ int dr = (op >> 16) & 0x1f;
+ int drval = REG24(dr);
+ int res = drval ^ EXTEND16_TO_24(op);
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = res;
+ SET_NZ00_24(res);
+}
+
+
+void dsp32c_device::ore_di(UINT32 op)
+{
+ int dr = (op >> 16) & 0x1f;
+ int drval = REG24(dr);
+ int res = drval | EXTEND16_TO_24(op);
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = res;
+ SET_NZ00_24(res);
+}
+
+
+void dsp32c_device::ande_di(UINT32 op)
+{
+ int dr = (op >> 16) & 0x1f;
+ int drval = REG24(dr);
+ int res = drval & EXTEND16_TO_24(op);
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = res;
+ SET_NZ00_24(res);
+}
+
+
+void dsp32c_device::teste_di(UINT32 op)
+{
+ int drval = REG24((op >> 16) & 0x1f);
+ int res = drval & EXTEND16_TO_24(op);
+ SET_NZ00_24(res);
+}
+
+
+
+//**************************************************************************
+// CAU LOAD/STORE IMPLEMENTATION
+//**************************************************************************
+
+void dsp32c_device::load_hi(UINT32 op)
+{
+ int dr = (op >> 16) & 0x1f;
+ UINT32 res = RBYTE(EXTEND16_TO_24(op));
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = EXTEND16_TO_24(res);
+ m_nzcflags = res << 8;
+ m_vflags = 0;
+}
+
+
+void dsp32c_device::load_li(UINT32 op)
+{
+ int dr = (op >> 16) & 0x1f;
+ UINT32 res = RBYTE(EXTEND16_TO_24(op));
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = res;
+ m_nzcflags = res << 8;
+ m_vflags = 0;
+}
+
+
+void dsp32c_device::load_i(UINT32 op)
+{
+ UINT32 res = RWORD(EXTEND16_TO_24(op));
+ int dr = (op >> 16) & 0x1f;
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = EXTEND16_TO_24(res);
+ m_nzcflags = res << 8;
+ m_vflags = 0;
+}
+
+
+void dsp32c_device::load_ei(UINT32 op)
+{
+ UINT32 res = TRUNCATE24(RLONG(EXTEND16_TO_24(op)));
+ int dr = (op >> 16) & 0x1f;
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = res;
+ m_nzcflags = res;
+ m_vflags = 0;
+}
+
+
+void dsp32c_device::store_hi(UINT32 op)
+{
+ WBYTE(EXTEND16_TO_24(op), m_r[(op >> 16) & 0x1f] >> 8);
+}
+
+
+void dsp32c_device::store_li(UINT32 op)
+{
+ WBYTE(EXTEND16_TO_24(op), m_r[(op >> 16) & 0x1f]);
+}
+
+
+void dsp32c_device::store_i(UINT32 op)
+{
+ WWORD(EXTEND16_TO_24(op), REG16((op >> 16) & 0x1f));
+}
+
+
+void dsp32c_device::store_ei(UINT32 op)
+{
+ WLONG(EXTEND16_TO_24(op), (INT32)(REG24((op >> 16) & 0x1f) << 8) >> 8);
+}
+
+
+void dsp32c_device::load_hr(UINT32 op)
+{
+ if (!(op & 0x400))
+ {
+ int dr = (op >> 16) & 0x1f;
+ UINT32 res = cau_read_pi_1byte(op) << 8;
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = EXTEND16_TO_24(res);
+ m_nzcflags = res << 8;
+ m_vflags = 0;
+ }
+ else
+ unimplemented(op);
+}
+
+
+void dsp32c_device::load_lr(UINT32 op)
+{
+ if (!(op & 0x400))
+ {
+ int dr = (op >> 16) & 0x1f;
+ UINT32 res = cau_read_pi_1byte(op);
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = res;
+ m_nzcflags = res << 8;
+ m_vflags = 0;
+ }
+ else
+ unimplemented(op);
+}
+
+
+void dsp32c_device::load_r(UINT32 op)
+{
+ if (!(op & 0x400))
+ {
+ UINT32 res = cau_read_pi_2byte(op);
+ int dr = (op >> 16) & 0x1f;
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = EXTEND16_TO_24(res);
+ m_nzcflags = res << 8;
+ m_vflags = 0;
+ }
+ else
+ unimplemented(op);
+}
+
+
+void dsp32c_device::load_er(UINT32 op)
+{
+ if (!(op & 0x400))
+ {
+ UINT32 res = TRUNCATE24(cau_read_pi_4byte(op));
+ int dr = (op >> 16) & 0x1f;
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = res;
+ m_nzcflags = res;
+ m_vflags = 0;
+ }
+ else
+ unimplemented(op);
+}
+
+
+void dsp32c_device::store_hr(UINT32 op)
+{
+ if (!(op & 0x400))
+ cau_write_pi_1byte(op, m_r[(op >> 16) & 0x1f] >> 8);
+ else
+ unimplemented(op);
+}
+
+
+void dsp32c_device::store_lr(UINT32 op)
+{
+ if (!(op & 0x400))
+ cau_write_pi_1byte(op, m_r[(op >> 16) & 0x1f]);
+ else
+ unimplemented(op);
+}
+
+
+void dsp32c_device::store_r(UINT32 op)
+{
+ if (!(op & 0x400))
+ cau_write_pi_2byte(op, REG16((op >> 16) & 0x1f));
+ else
+ unimplemented(op);
+}
+
+
+void dsp32c_device::store_er(UINT32 op)
+{
+ if (!(op & 0x400))
+ cau_write_pi_4byte(op, REG24((op >> 16) & 0x1f));
+ else
+ unimplemented(op);
+}
+
+
+void dsp32c_device::load24(UINT32 op)
+{
+ int dr = (op >> 16) & 0x1f;
+ UINT32 res = (op & 0xffff) + ((op >> 5) & 0xff0000);
+ if (IS_WRITEABLE(dr))
+ m_r[dr] = res;
+}
+
+
+
+//**************************************************************************
+// DAU FORM 1 IMPLEMENTATION
+//**************************************************************************
+
+void dsp32c_device::d1_aMpp(UINT32 op)
+{
+ double xval = dau_read_pi_double_1st(op >> 14, 1);
+ double yval = dau_read_pi_double_2nd(op >> 7, 0, xval);
+ double res = yval + DEFERRED_MULTIPLIER((op >> 26) & 7) * xval;
+ int zpi = (op >> 0) & 0x7f;
+ if (zpi != 7)
+ dau_write_pi_double(zpi, res);
+ dau_set_val_flags((op >> 21) & 3, res);
+}
+
+
+void dsp32c_device::d1_aMpm(UINT32 op)
+{
+ double xval = dau_read_pi_double_1st(op >> 14, 1);
+ double yval = dau_read_pi_double_2nd(op >> 7, 0, xval);
+ double res = yval - DEFERRED_MULTIPLIER((op >> 26) & 7) * xval;
+ int zpi = (op >> 0) & 0x7f;
+ if (zpi != 7)
+ dau_write_pi_double(zpi, res);
+ dau_set_val_flags((op >> 21) & 3, res);
+}
+
+
+void dsp32c_device::d1_aMmp(UINT32 op)
+{
+ double xval = dau_read_pi_double_1st(op >> 14, 1);
+ double yval = dau_read_pi_double_2nd(op >> 7, 0, xval);
+ double res = -yval + DEFERRED_MULTIPLIER((op >> 26) & 7) * xval;
+ int zpi = (op >> 0) & 0x7f;
+ if (zpi != 7)
+ dau_write_pi_double(zpi, res);
+ dau_set_val_flags((op >> 21) & 3, res);
+}
+
+
+void dsp32c_device::d1_aMmm(UINT32 op)
+{
+ double xval = dau_read_pi_double_1st(op >> 14, 1);
+ double yval = dau_read_pi_double_2nd(op >> 7, 0, xval);
+ double res = -yval - DEFERRED_MULTIPLIER((op >> 26) & 7) * xval;
+ int zpi = (op >> 0) & 0x7f;
+ if (zpi != 7)
+ dau_write_pi_double(zpi, res);
+ dau_set_val_flags((op >> 21) & 3, res);
+}
+
+
+void dsp32c_device::d1_0px(UINT32 op)
+{
+ double xval = dau_read_pi_double_1st(op >> 14, 1);
+ double yval = dau_read_pi_double_2nd(op >> 7, 0, xval);
+ double res = yval;
+ int zpi = (op >> 0) & 0x7f;
+ if (zpi != 7)
+ dau_write_pi_double(zpi, res);
+ dau_set_val_flags((op >> 21) & 3, res);
+ (void)xval;
+}
+
+
+void dsp32c_device::d1_0mx(UINT32 op)
+{
+ double xval = dau_read_pi_double_1st(op >> 14, 1);
+ double yval = dau_read_pi_double_2nd(op >> 7, 0, xval);
+ double res = -yval;
+ int zpi = (op >> 0) & 0x7f;
+ if (zpi != 7)
+ dau_write_pi_double(zpi, res);
+ dau_set_val_flags((op >> 21) & 3, res);
+ (void)xval;
+}
+
+
+void dsp32c_device::d1_1pp(UINT32 op)
+{
+ double xval = dau_read_pi_double_1st(op >> 14, 1);
+ double yval = dau_read_pi_double_2nd(op >> 7, 0, xval);
+ double res = yval + xval;
+ int zpi = (op >> 0) & 0x7f;
+ if (zpi != 7)
+ dau_write_pi_double(zpi, res);
+ dau_set_val_flags((op >> 21) & 3, res);
+}
+
+
+void dsp32c_device::d1_1pm(UINT32 op)
+{
+ double xval = dau_read_pi_double_1st(op >> 14, 1);
+ double yval = dau_read_pi_double_2nd(op >> 7, 0, xval);
+ double res = yval - xval;
+ int zpi = (op >> 0) & 0x7f;
+ if (zpi != 7)
+ dau_write_pi_double(zpi, res);
+ dau_set_val_flags((op >> 21) & 3, res);
+}
+
+
+void dsp32c_device::d1_1mp(UINT32 op)
+{
+ double xval = dau_read_pi_double_1st(op >> 14, 1);
+ double yval = dau_read_pi_double_2nd(op >> 7, 0, xval);
+ double res = -yval + xval;
+ int zpi = (op >> 0) & 0x7f;
+ if (zpi != 7)
+ dau_write_pi_double(zpi, res);
+ dau_set_val_flags((op >> 21) & 3, res);
+}
+
+
+void dsp32c_device::d1_1mm(UINT32 op)
+{
+ double xval = dau_read_pi_double_1st(op >> 14, 1);
+ double yval = dau_read_pi_double_2nd(op >> 7, 0, xval);
+ double res = -yval - xval;
+ int zpi = (op >> 0) & 0x7f;
+ if (zpi != 7)
+ dau_write_pi_double(zpi, res);
+ dau_set_val_flags((op >> 21) & 3, res);
+}
+
+
+void dsp32c_device::d1_aMppr(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+void dsp32c_device::d1_aMpmr(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+void dsp32c_device::d1_aMmpr(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+void dsp32c_device::d1_aMmmr(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+
+//**************************************************************************
+// DAU FORM 2 IMPLEMENTATION
+//**************************************************************************
+
+void dsp32c_device::d2_aMpp(UINT32 op)
+{
+ double xval = dau_read_pi_double_1st(op >> 14, 1);
+ double yval = dau_read_pi_double_2nd(op >> 7, 1, xval);
+ double res = m_a[(op >> 26) & 7] + yval * xval;
+ int zpi = (op >> 0) & 0x7f;
+ if (zpi != 7)
+ dau_write_pi_double(zpi, yval);
+ dau_set_val_flags((op >> 21) & 3, res);
+}
+
+
+void dsp32c_device::d2_aMpm(UINT32 op)
+{
+ double xval = dau_read_pi_double_1st(op >> 14, 1);
+ double yval = dau_read_pi_double_2nd(op >> 7, 1, xval);
+ double res = m_a[(op >> 26) & 7] - yval * xval;
+ int zpi = (op >> 0) & 0x7f;
+ if (zpi != 7)
+ dau_write_pi_double(zpi, yval);
+ dau_set_val_flags((op >> 21) & 3, res);
+}
+
+
+void dsp32c_device::d2_aMmp(UINT32 op)
+{
+ double xval = dau_read_pi_double_1st(op >> 14, 1);
+ double yval = dau_read_pi_double_2nd(op >> 7, 1, xval);
+ double res = -m_a[(op >> 26) & 7] + yval * xval;
+ int zpi = (op >> 0) & 0x7f;
+ if (zpi != 7)
+ dau_write_pi_double(zpi, yval);
+ dau_set_val_flags((op >> 21) & 3, res);
+}
+
+
+void dsp32c_device::d2_aMmm(UINT32 op)
+{
+ double xval = dau_read_pi_double_1st(op >> 14, 1);
+ double yval = dau_read_pi_double_2nd(op >> 7, 1, xval);
+ double res = -m_a[(op >> 26) & 7] - yval * xval;
+ int zpi = (op >> 0) & 0x7f;
+ if (zpi != 7)
+ dau_write_pi_double(zpi, yval);
+ dau_set_val_flags((op >> 21) & 3, res);
+}
+
+
+void dsp32c_device::d2_aMppr(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+void dsp32c_device::d2_aMpmr(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+void dsp32c_device::d2_aMmpr(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+void dsp32c_device::d2_aMmmr(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+
+//**************************************************************************
+// DAU FORM 3 IMPLEMENTATION
+//**************************************************************************
+
+void dsp32c_device::d3_aMpp(UINT32 op)
+{
+ double xval = dau_read_pi_double_1st(op >> 14, 1);
+ double yval = dau_read_pi_double_2nd(op >> 7, 1, xval);
+ double res = m_a[(op >> 26) & 7] + yval * xval;
+ int zpi = (op >> 0) & 0x7f;
+ if (zpi != 7)
+ dau_write_pi_double(zpi, res);
+ dau_set_val_flags((op >> 21) & 3, res);
+}
+
+
+void dsp32c_device::d3_aMpm(UINT32 op)
+{
+ double xval = dau_read_pi_double_1st(op >> 14, 1);
+ double yval = dau_read_pi_double_2nd(op >> 7, 1, xval);
+ double res = m_a[(op >> 26) & 7] - yval * xval;
+ int zpi = (op >> 0) & 0x7f;
+ if (zpi != 7)
+ dau_write_pi_double(zpi, res);
+ dau_set_val_flags((op >> 21) & 3, res);
+}
+
+
+void dsp32c_device::d3_aMmp(UINT32 op)
+{
+ double xval = dau_read_pi_double_1st(op >> 14, 1);
+ double yval = dau_read_pi_double_2nd(op >> 7, 1, xval);
+ double res = -m_a[(op >> 26) & 7] + yval * xval;
+ int zpi = (op >> 0) & 0x7f;
+ if (zpi != 7)
+ dau_write_pi_double(zpi, res);
+ dau_set_val_flags((op >> 21) & 3, res);
+}
+
+
+void dsp32c_device::d3_aMmm(UINT32 op)
+{
+ double xval = dau_read_pi_double_1st(op >> 14, 1);
+ double yval = dau_read_pi_double_2nd(op >> 7, 1, xval);
+ double res = -m_a[(op >> 26) & 7] - yval * xval;
+ int zpi = (op >> 0) & 0x7f;
+ if (zpi != 7)
+ dau_write_pi_double(zpi, res);
+ dau_set_val_flags((op >> 21) & 3, res);
+}
+
+
+void dsp32c_device::d3_aMppr(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+void dsp32c_device::d3_aMpmr(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+void dsp32c_device::d3_aMmpr(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+void dsp32c_device::d3_aMmmr(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+
+//**************************************************************************
+// DAU FORM 4 IMPLEMENTATION
+//**************************************************************************
+
+void dsp32c_device::d4_pp(UINT32 op)
+{
+ double xval = dau_read_pi_double_1st(op >> 14, 1);
+ double yval = dau_read_pi_double_2nd(op >> 7, 0, xval);
+ double res = yval + xval;
+ int zpi = (op >> 0) & 0x7f;
+ if (zpi != 7)
+ dau_write_pi_double(zpi, yval);
+ dau_set_val_flags((op >> 21) & 3, res);
+}
+
+
+void dsp32c_device::d4_pm(UINT32 op)
+{
+ double xval = dau_read_pi_double_1st(op >> 14, 1);
+ double yval = dau_read_pi_double_2nd(op >> 7, 0, xval);
+ double res = yval - xval;
+ int zpi = (op >> 0) & 0x7f;
+ if (zpi != 7)
+ dau_write_pi_double(zpi, yval);
+ dau_set_val_flags((op >> 21) & 3, res);
+}
+
+
+void dsp32c_device::d4_mp(UINT32 op)
+{
+ double xval = dau_read_pi_double_1st(op >> 14, 1);
+ double yval = dau_read_pi_double_2nd(op >> 7, 0, xval);
+ double res = -yval + xval;
+ int zpi = (op >> 0) & 0x7f;
+ if (zpi != 7)
+ dau_write_pi_double(zpi, yval);
+ dau_set_val_flags((op >> 21) & 3, res);
+}
+
+
+void dsp32c_device::d4_mm(UINT32 op)
+{
+ double xval = dau_read_pi_double_1st(op >> 14, 1);
+ double yval = dau_read_pi_double_2nd(op >> 7, 0, xval);
+ double res = -yval - xval;
+ int zpi = (op >> 0) & 0x7f;
+ if (zpi != 7)
+ dau_write_pi_double(zpi, yval);
+ dau_set_val_flags((op >> 21) & 3, res);
+}
+
+
+void dsp32c_device::d4_ppr(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+void dsp32c_device::d4_pmr(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+void dsp32c_device::d4_mpr(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+void dsp32c_device::d4_mmr(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+
+//**************************************************************************
+// DAU FORM 5 IMPLEMENTATION
+//**************************************************************************
+
+void dsp32c_device::d5_ic(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+void dsp32c_device::d5_oc(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+void dsp32c_device::d5_float(UINT32 op)
+{
+ double res = (double)(INT16)dau_read_pi_2bytes(op >> 7);
+ int zpi = (op >> 0) & 0x7f;
+ if (zpi != 7)
+ dau_write_pi_double(zpi, res);
+ dau_set_val_flags((op >> 21) & 3, res);
+}
+
+
+void dsp32c_device::d5_int(UINT32 op)
+{
+ double val = dau_read_pi_double_1st(op >> 7, 0);
+ int zpi = (op >> 0) & 0x7f;
+ INT16 res;
+ if (!(DAUC & 0x10)) val = floor(val + 0.5);
+ else val = ceil(val - 0.5);
+ res = (INT16)val;
+ if (zpi != 7)
+ dau_write_pi_2bytes(zpi, res);
+ dau_set_val_noflags((op >> 21) & 3, dsp_to_double(res << 16));
+}
+
+
+void dsp32c_device::d5_round(UINT32 op)
+{
+ double res = (double)(float)dau_read_pi_double_1st(op >> 7, 0);
+ int zpi = (op >> 0) & 0x7f;
+ if (zpi != 7)
+ dau_write_pi_double(zpi, res);
+ dau_set_val_flags((op >> 21) & 3, res);
+}
+
+
+void dsp32c_device::d5_ifalt(UINT32 op)
+{
+ int ar = (op >> 21) & 3;
+ double res = m_a[ar];
+ int zpi = (op >> 0) & 0x7f;
+ if (NFLAG)
+ res = dau_read_pi_double_1st(op >> 7, 0);
+ if (zpi != 7)
+ dau_write_pi_double(zpi, res);
+ dau_set_val_noflags(ar, res);
+}
+
+
+void dsp32c_device::d5_ifaeq(UINT32 op)
+{
+ int ar = (op >> 21) & 3;
+ double res = m_a[ar];
+ int zpi = (op >> 0) & 0x7f;
+ if (ZFLAG)
+ res = dau_read_pi_double_1st(op >> 7, 0);
+ if (zpi != 7)
+ dau_write_pi_double(zpi, res);
+ dau_set_val_noflags(ar, res);
+}
+
+
+void dsp32c_device::d5_ifagt(UINT32 op)
+{
+ int ar = (op >> 21) & 3;
+ double res = m_a[ar];
+ int zpi = (op >> 0) & 0x7f;
+ if (!NFLAG && !ZFLAG)
+ res = dau_read_pi_double_1st(op >> 7, 0);
+ if (zpi != 7)
+ dau_write_pi_double(zpi, res);
+ dau_set_val_noflags(ar, res);
+}
+
+
+void dsp32c_device::d5_float24(UINT32 op)
+{
+ double res = (double)((INT32)(dau_read_pi_4bytes(op >> 7) << 8) >> 8);
+ int zpi = (op >> 0) & 0x7f;
+ if (zpi != 7)
+ dau_write_pi_double(zpi, res);
+ dau_set_val_flags((op >> 21) & 3, res);
+}
+
+
+void dsp32c_device::d5_int24(UINT32 op)
+{
+ double val = dau_read_pi_double_1st(op >> 7, 0);
+ int zpi = (op >> 0) & 0x7f;
+ INT32 res;
+ if (!(DAUC & 0x10)) val = floor(val + 0.5);
+ else val = ceil(val - 0.5);
+ res = (INT32)val;
+ if (res > 0x7fffff) res = 0x7fffff;
+ else if (res < -0x800000) res = -0x800000;
+ if (zpi != 7)
+ dau_write_pi_4bytes(zpi, (INT32)(res << 8) >> 8);
+ dau_set_val_noflags((op >> 21) & 3, dsp_to_double(res << 8));
+}
+
+
+void dsp32c_device::d5_ieee(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+void dsp32c_device::d5_dsp(UINT32 op)
+{
+ unimplemented(op);
+}
+
+
+void dsp32c_device::d5_seed(UINT32 op)
+{
+ UINT32 val = dau_read_pi_4bytes(op >> 7);
+ INT32 res = val ^ 0x7fffffff;
+ int zpi = (op >> 0) & 0x7f;
+ if (zpi != 7)
+ dau_write_pi_4bytes(zpi, res);
+ dau_set_val_flags((op >> 21) & 3, dsp_to_double((INT32)res));
+}
+
+
+
+//**************************************************************************
+// FUNCTION TABLE
+//**************************************************************************
+
+void (dsp32c_device::*const dsp32c_device::s_dsp32ops[])(UINT32 op) =
+{
+ &dsp32c_device::nop, &dsp32c_device::goto_t, &dsp32c_device::goto_pl, &dsp32c_device::goto_mi, &dsp32c_device::goto_ne, &dsp32c_device::goto_eq, &dsp32c_device::goto_vc, &dsp32c_device::goto_vs, // 00
+ &dsp32c_device::goto_cc, &dsp32c_device::goto_cs, &dsp32c_device::goto_ge, &dsp32c_device::goto_lt, &dsp32c_device::goto_gt, &dsp32c_device::goto_le, &dsp32c_device::goto_hi, &dsp32c_device::goto_ls,
+ &dsp32c_device::goto_auc, &dsp32c_device::goto_aus, &dsp32c_device::goto_age, &dsp32c_device::goto_alt, &dsp32c_device::goto_ane, &dsp32c_device::goto_aeq, &dsp32c_device::goto_avc, &dsp32c_device::goto_avs, // 01
+ &dsp32c_device::goto_agt, &dsp32c_device::goto_ale, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal,
+ &dsp32c_device::goto_ibe, &dsp32c_device::goto_ibf, &dsp32c_device::goto_obf, &dsp32c_device::goto_obe, &dsp32c_device::goto_pde, &dsp32c_device::goto_pdf, &dsp32c_device::goto_pie, &dsp32c_device::goto_pif, // 02
+ &dsp32c_device::goto_syc, &dsp32c_device::goto_sys, &dsp32c_device::goto_fbc, &dsp32c_device::goto_fbs, &dsp32c_device::goto_irq1lo,&dsp32c_device::goto_irq1hi,&dsp32c_device::goto_irq2lo,&dsp32c_device::goto_irq2hi,
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 03
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal,
+
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 04
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal,
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 05
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal,
+ &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, // 06
+ &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto,
+ &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, // 07
+ &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto,
+
+ &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, // 08
+ &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call,
+ &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, // 09
+ &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call,
+ &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, // 0a
+ &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si,
+ &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, // 0b
+ &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si,
+
+ &dsp32c_device::add_ss, &dsp32c_device::mul2_s, &dsp32c_device::subr_ss, &dsp32c_device::addr_ss, &dsp32c_device::sub_ss, &dsp32c_device::neg_s, &dsp32c_device::andc_ss, &dsp32c_device::cmp_ss, // 0c
+ &dsp32c_device::xor_ss, &dsp32c_device::rcr_s, &dsp32c_device::or_ss, &dsp32c_device::rcl_s, &dsp32c_device::shr_s, &dsp32c_device::div2_s, &dsp32c_device::and_ss, &dsp32c_device::test_ss,
+ &dsp32c_device::add_di, &dsp32c_device::illegal, &dsp32c_device::subr_di, &dsp32c_device::addr_di, &dsp32c_device::sub_di, &dsp32c_device::illegal, &dsp32c_device::andc_di, &dsp32c_device::cmp_di, // 0d
+ &dsp32c_device::xor_di, &dsp32c_device::illegal, &dsp32c_device::or_di, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::and_di, &dsp32c_device::test_di,
+ &dsp32c_device::load_hi, &dsp32c_device::load_hi, &dsp32c_device::load_li, &dsp32c_device::load_li, &dsp32c_device::load_i, &dsp32c_device::load_i, &dsp32c_device::load_ei, &dsp32c_device::load_ei, // 0e
+ &dsp32c_device::store_hi, &dsp32c_device::store_hi, &dsp32c_device::store_li, &dsp32c_device::store_li, &dsp32c_device::store_i, &dsp32c_device::store_i, &dsp32c_device::store_ei, &dsp32c_device::store_ei,
+ &dsp32c_device::load_hr, &dsp32c_device::load_hr, &dsp32c_device::load_lr, &dsp32c_device::load_lr, &dsp32c_device::load_r, &dsp32c_device::load_r, &dsp32c_device::load_er, &dsp32c_device::load_er, // 0f
+ &dsp32c_device::store_hr, &dsp32c_device::store_hr, &dsp32c_device::store_lr, &dsp32c_device::store_lr, &dsp32c_device::store_r, &dsp32c_device::store_r, &dsp32c_device::store_er, &dsp32c_device::store_er,
+
+ &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpm, &dsp32c_device::d1_aMpm, &dsp32c_device::d1_aMpm, &dsp32c_device::d1_aMpm, // 10
+ &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmm, &dsp32c_device::d1_aMmm, &dsp32c_device::d1_aMmm, &dsp32c_device::d1_aMmm,
+ &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, // 11
+ &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr,
+ &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpm, &dsp32c_device::d1_aMpm, &dsp32c_device::d1_aMpm, &dsp32c_device::d1_aMpm, // 12
+ &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmm, &dsp32c_device::d1_aMmm, &dsp32c_device::d1_aMmm, &dsp32c_device::d1_aMmm,
+ &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, // 13
+ &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr,
+
+ &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpm, &dsp32c_device::d1_aMpm, &dsp32c_device::d1_aMpm, &dsp32c_device::d1_aMpm, // 14
+ &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmm, &dsp32c_device::d1_aMmm, &dsp32c_device::d1_aMmm, &dsp32c_device::d1_aMmm,
+ &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, // 15
+ &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr,
+ &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpm, &dsp32c_device::d1_aMpm, &dsp32c_device::d1_aMpm, &dsp32c_device::d1_aMpm, // 16
+ &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmm, &dsp32c_device::d1_aMmm, &dsp32c_device::d1_aMmm, &dsp32c_device::d1_aMmm,
+ &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, // 17
+ &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr,
+
+ &dsp32c_device::d1_0px, &dsp32c_device::d1_0px, &dsp32c_device::d1_0px, &dsp32c_device::d1_0px, &dsp32c_device::d1_0px, &dsp32c_device::d1_0px, &dsp32c_device::d1_0px, &dsp32c_device::d1_0px, // 18
+ &dsp32c_device::d1_0mx, &dsp32c_device::d1_0mx, &dsp32c_device::d1_0mx, &dsp32c_device::d1_0mx, &dsp32c_device::d1_0mx, &dsp32c_device::d1_0mx, &dsp32c_device::d1_0mx, &dsp32c_device::d1_0mx,
+ &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, // 19
+ &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr,
+ &dsp32c_device::d1_1pp, &dsp32c_device::d1_1pp, &dsp32c_device::d1_1pp, &dsp32c_device::d1_1pp, &dsp32c_device::d1_1pm, &dsp32c_device::d1_1pm, &dsp32c_device::d1_1pm, &dsp32c_device::d1_1pm, // 1a
+ &dsp32c_device::d1_1mp, &dsp32c_device::d1_1mp, &dsp32c_device::d1_1mp, &dsp32c_device::d1_1mp, &dsp32c_device::d1_1mm, &dsp32c_device::d1_1mm, &dsp32c_device::d1_1mm, &dsp32c_device::d1_1mm,
+ &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, // 1b
+ &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr,
+
+ &dsp32c_device::d4_pp, &dsp32c_device::d4_pp, &dsp32c_device::d4_pp, &dsp32c_device::d4_pp, &dsp32c_device::d4_pm, &dsp32c_device::d4_pm, &dsp32c_device::d4_pm, &dsp32c_device::d4_pm, // 1c
+ &dsp32c_device::d4_mp, &dsp32c_device::d4_mp, &dsp32c_device::d4_mp, &dsp32c_device::d4_mp, &dsp32c_device::d4_mm, &dsp32c_device::d4_mm, &dsp32c_device::d4_mm, &dsp32c_device::d4_mm,
+ &dsp32c_device::d4_ppr, &dsp32c_device::d4_ppr, &dsp32c_device::d4_ppr, &dsp32c_device::d4_ppr, &dsp32c_device::d4_pmr, &dsp32c_device::d4_pmr, &dsp32c_device::d4_pmr, &dsp32c_device::d4_pmr, // 1d
+ &dsp32c_device::d4_mpr, &dsp32c_device::d4_mpr, &dsp32c_device::d4_mpr, &dsp32c_device::d4_mpr, &dsp32c_device::d4_mmr, &dsp32c_device::d4_mmr, &dsp32c_device::d4_mmr, &dsp32c_device::d4_mmr,
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 1e
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal,
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 1f
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal,
+
+ &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, // 20
+ &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm,
+ &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, // 21
+ &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr,
+ &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, // 22
+ &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm,
+ &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, // 23
+ &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr,
+
+ &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, // 24
+ &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm,
+ &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, // 25
+ &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr,
+ &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, // 26
+ &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm,
+ &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, // 27
+ &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr,
+
+ &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, // 28
+ &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm,
+ &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, // 29
+ &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr,
+ &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, // 2a
+ &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm,
+ &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, // 2b
+ &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr,
+
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 2c
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal,
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 2d
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal,
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 2e
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal,
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 2f
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal,
+
+ &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, // 30
+ &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm,
+ &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, // 31
+ &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr,
+ &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, // 32
+ &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm,
+ &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, // 33
+ &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr,
+
+ &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, // 34
+ &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm,
+ &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, // 35
+ &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr,
+ &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, // 36
+ &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm,
+ &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, // 37
+ &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr,
+
+ &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, // 38
+ &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm,
+ &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, // 39
+ &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr,
+ &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, // 3a
+ &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm,
+ &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, // 3b
+ &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr,
+
+ &dsp32c_device::d5_ic, &dsp32c_device::d5_ic, &dsp32c_device::d5_ic, &dsp32c_device::d5_ic, &dsp32c_device::d5_oc, &dsp32c_device::d5_oc, &dsp32c_device::d5_oc, &dsp32c_device::d5_oc, // 3c
+ &dsp32c_device::d5_float, &dsp32c_device::d5_float, &dsp32c_device::d5_float, &dsp32c_device::d5_float, &dsp32c_device::d5_int, &dsp32c_device::d5_int, &dsp32c_device::d5_int, &dsp32c_device::d5_int,
+ &dsp32c_device::d5_round, &dsp32c_device::d5_round, &dsp32c_device::d5_round, &dsp32c_device::d5_round, &dsp32c_device::d5_ifalt, &dsp32c_device::d5_ifalt, &dsp32c_device::d5_ifalt, &dsp32c_device::d5_ifalt, // 3d
+ &dsp32c_device::d5_ifaeq, &dsp32c_device::d5_ifaeq, &dsp32c_device::d5_ifaeq, &dsp32c_device::d5_ifaeq, &dsp32c_device::d5_ifagt, &dsp32c_device::d5_ifagt, &dsp32c_device::d5_ifagt, &dsp32c_device::d5_ifagt,
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 3e
+ &dsp32c_device::d5_float24, &dsp32c_device::d5_float24, &dsp32c_device::d5_float24, &dsp32c_device::d5_float24, &dsp32c_device::d5_int24, &dsp32c_device::d5_int24, &dsp32c_device::d5_int24, &dsp32c_device::d5_int24,
+ &dsp32c_device::d5_ieee, &dsp32c_device::d5_ieee, &dsp32c_device::d5_ieee, &dsp32c_device::d5_ieee, &dsp32c_device::d5_dsp, &dsp32c_device::d5_dsp, &dsp32c_device::d5_dsp, &dsp32c_device::d5_dsp, // 3f
+ &dsp32c_device::d5_seed, &dsp32c_device::d5_seed, &dsp32c_device::d5_seed, &dsp32c_device::d5_seed, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal,
+
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 40
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal,
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 41
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal,
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 42
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal,
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 43
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal,
+
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 44
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal,
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 45
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal,
+ &dsp32c_device::do_i, &dsp32c_device::do_r, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 46
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal,
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 47
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal,
+
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 48
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal,
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 49
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal,
+ &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, // 4a
+ &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si,
+ &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, // 4b
+ &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si,
+
+ &dsp32c_device::adde_ss, &dsp32c_device::mul2e_s, &dsp32c_device::subre_ss, &dsp32c_device::addre_ss, &dsp32c_device::sube_ss, &dsp32c_device::nege_s, &dsp32c_device::andce_ss, &dsp32c_device::cmpe_ss, // 4c
+ &dsp32c_device::xore_ss, &dsp32c_device::rcre_s, &dsp32c_device::ore_ss, &dsp32c_device::rcle_s, &dsp32c_device::shre_s, &dsp32c_device::div2e_s, &dsp32c_device::ande_ss, &dsp32c_device::teste_ss,
+ &dsp32c_device::adde_di, &dsp32c_device::illegal, &dsp32c_device::subre_di, &dsp32c_device::addre_di, &dsp32c_device::sube_di, &dsp32c_device::illegal, &dsp32c_device::andce_di, &dsp32c_device::cmpe_di, // 4d
+ &dsp32c_device::xore_di, &dsp32c_device::illegal, &dsp32c_device::ore_di, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::ande_di, &dsp32c_device::teste_di,
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 4e
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal,
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 4f
+ &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal,
+
+ &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 50
+ &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24,
+ &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 51
+ &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24,
+ &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 52
+ &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24,
+ &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 53
+ &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24,
+
+ &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 54
+ &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24,
+ &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 55
+ &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24,
+ &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 56
+ &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24,
+ &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 57
+ &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24,
+
+ &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 58
+ &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24,
+ &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 59
+ &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24,
+ &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 5a
+ &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24,
+ &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 5b
+ &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24,
+
+ &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 5c
+ &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24,
+ &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 5d
+ &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24,
+ &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 5e
+ &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24,
+ &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 5f
+ &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24,
+
+ &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 60
+ &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24,
+ &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 61
+ &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24,
+ &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 62
+ &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24,
+ &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 63
+ &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24,
+
+ &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 64
+ &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24,
+ &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 65
+ &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24,
+ &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 66
+ &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24,
+ &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 67
+ &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24,
+
+ &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 68
+ &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24,
+ &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 69
+ &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24,
+ &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 6a
+ &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24,
+ &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 6b
+ &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24,
+
+ &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 6c
+ &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24,
+ &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 6d
+ &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24,
+ &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 6e
+ &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24,
+ &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 6f
+ &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24,
+
+ &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 70
+ &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24,
+ &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 71
+ &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24,
+ &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 72
+ &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24,
+ &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 73
+ &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24,
+
+ &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 74
+ &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24,
+ &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 75
+ &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24,
+ &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 76
+ &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24,
+ &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 77
+ &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24,
+
+ &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 78
+ &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24,
+ &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 79
+ &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24,
+ &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 7a
+ &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24,
+ &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 7b
+ &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24,
+
+ &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 7c
+ &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24,
+ &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 7d
+ &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24,
+ &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 7e
+ &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24,
+ &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 7f
+ &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24
+};
+
+
+/*
+
+ Most common OPs in Race Drivin':
+
+301681217 - op 0 - nop
+164890391 - op 4A1 - adde_si
+99210113 - op 661 - load24
+86010010 - op F7 - load_er
+61148739 - op 4D4 - sube_di
+52693763 - op 180 - d1_0px
+41525754 - op FF - store_er
+35033321 - op 380 - d3_aMpp
+31621151 - op 4C0 - adde_ss
+28076244 - op 660 - load24
+19190505 - op 4C1 - mul2e_s
+13270852 - op F5 - load_r
+12535169 - op 1A4 - d1_1pm
+12265141 - op 4C4 - sube_ss
+10748211 - op 4CD - div2e_s
+10493660 - op FD - store_r
+ 9721263 - op 189
+ 9415685 - op 3C8
+ 9294148 - op 3D5
+ 8887846 - op 1A1
+ 8788648 - op 381
+ 8185239 - op 300
+ 7241256 - op 383
+ 6877349 - op 4A3
+ 6832295 - op 181
+ 6601270 - op 3E8
+ 6562483 - op 4A4
+ 6553514 - op 3C9
+ 6270430 - op 280
+ 6041485 - op 1A0
+ 5299529 - op 304
+ 5110926 - op 382
+ 4922253 - op 363
+ 4603670 - op 4D7
+ 4164327 - op 4AE
+ 3980085 - op 3EC
+ 3599198 - op 3CC
+ 3543878 - op 3D0
+ 3489158 - op 4
+ 3463235 - op 321
+ 3335995 - op 3F9
+ 3001546 - op 4CE
+ 2882940 - op 129
+ 2882940 - op 1A5
+ 2882940 - op 342
+ 2841981 - op 360
+ 2663417 - op FB
+ 2059640 - op 3ED
+ 1867166 - op 1A8
+ 1830789 - op 305
+ 1753312 - op 301
+ 1726866 - op 5
+ 1594991 - op 12
+ 1571286 - op 19
+ 1507644 - op A2
+ 1418846 - op 3CD
+ 1273134 - op F3
+ 1177914 - op 4C7
+ 1175720 - op 188
+ 1091848 - op 3E9
+ 1088206 - op 6FF
+ 1088204 - op 4CA
+ 1012639 - op 101
+ 939617 - op 4C5
+
+*/
diff --git a/trunk/src/emu/cpu/dsp56k/dsp56def.h b/trunk/src/emu/cpu/dsp56k/dsp56def.h
new file mode 100644
index 00000000000..416653e7cd9
--- /dev/null
+++ b/trunk/src/emu/cpu/dsp56k/dsp56def.h
@@ -0,0 +1,55 @@
+///////////////////////////////////////////
+// All the macros that are fit to print. //
+///////////////////////////////////////////
+
+#ifndef __DSP56_DEF_H__
+#define __DSP56_DEF_H__
+
+#include "dsp56k.h"
+
+namespace DSP56K
+{
+
+/***************************************************************************
+ ALU
+***************************************************************************/
+#define X cpustate->ALU.x.d
+#define X1 cpustate->ALU.x.w.h
+#define X0 cpustate->ALU.x.w.l
+#define Y cpustate->ALU.y.d
+#define Y1 cpustate->ALU.y.w.h
+#define Y0 cpustate->ALU.y.w.l
+
+#define A cpustate->ALU.a.q
+#define A2 cpustate->ALU.a.b.h4
+#define A1 cpustate->ALU.a.w.h
+#define A0 cpustate->ALU.a.w.l
+#define B cpustate->ALU.b.q
+#define B2 cpustate->ALU.b.b.h4
+#define B1 cpustate->ALU.b.w.h
+#define B0 cpustate->ALU.b.w.l
+
+
+/***************************************************************************
+ AGU
+***************************************************************************/
+#define R0 cpustate->AGU.r0
+#define R1 cpustate->AGU.r1
+#define R2 cpustate->AGU.r2
+#define R3 cpustate->AGU.r3
+
+#define N0 cpustate->AGU.n0
+#define N1 cpustate->AGU.n1
+#define N2 cpustate->AGU.n2
+#define N3 cpustate->AGU.n3
+
+#define M0 cpustate->AGU.m0
+#define M1 cpustate->AGU.m1
+#define M2 cpustate->AGU.m2
+#define M3 cpustate->AGU.m3
+
+#define TEMP cpustate->AGU.temp
+
+} // namespace DSP56K
+
+#endif
diff --git a/trunk/src/emu/cpu/dsp56k/dsp56dsm.c b/trunk/src/emu/cpu/dsp56k/dsp56dsm.c
new file mode 100644
index 00000000000..1321b92c851
--- /dev/null
+++ b/trunk/src/emu/cpu/dsp56k/dsp56dsm.c
@@ -0,0 +1,28 @@
+/***************************************************************************
+
+ dsp56dsm.c
+ Disassembler for the portable Motorola/Freescale dsp56k emulator.
+ Written by Andrew Gardner
+
+***************************************************************************/
+
+#include "opcode.h"
+
+#include "emu.h"
+#include "dsp56k.h"
+
+/*****************************/
+/* Main disassembly function */
+/*****************************/
+CPU_DISASSEMBLE( dsp56k )
+{
+ const UINT16 w0 = oprom[0] | (oprom[1] << 8);
+ const UINT16 w1 = oprom[2] | (oprom[3] << 8);
+
+ // Decode and disassemble.
+ DSP56K::Opcode op(w0, w1);
+ sprintf(buffer, "%s", op.disassemble().cstr());
+
+ const unsigned size = op.size();
+ return (size | DASMFLAG_SUPPORTED);
+}
diff --git a/trunk/src/emu/cpu/dsp56k/dsp56k.c b/trunk/src/emu/cpu/dsp56k/dsp56k.c
new file mode 100644
index 00000000000..565ac5484e8
--- /dev/null
+++ b/trunk/src/emu/cpu/dsp56k/dsp56k.c
@@ -0,0 +1,677 @@
+/***************************************************************************
+
+ dsp56k.c
+ Core implementation for the portable DSP56k emulator.
+ Written by Andrew Gardner
+
+****************************************************************************
+
+ Note:
+ This CPU emulator is very much a work-in-progress.
+
+ DONE:
+ 1: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+ 11, , , , , , ,18, , ,
+
+ TODO:
+ X 1-6 Explore CORE naming scheme.
+ - 1-9 paragraph 1 : memory access timings
+ - 1-9 Data ALU arithmetic operations generally use fractional two's complement arithmetic
+ (Unsigned numbers are only supported by the multiply and multiply-accumulate instruction)
+ - 1-9 For fractional arithmetic, the 31-bit product is added to the 40-bit contents of A or B. No pipeline!
+ - 1-10 Two types of rounding: convergent rounding and two's complement rounding. See status register bit R.
+ - 1-10 Logic unit is 16-bits wide and works on MSP portion of accum register
+ - 1-10 The AGU can implement three types of arithmetic: linear, modulo, and reverse carry.
+ - 1-12 "Two external interrupt pins!!!"
+ - 1-12 Take care of all interrupt priority (IPR) stuff!
+ - 1-19 Memory WAIT states
+ - 1-20 The timer's interesting!
+ - 1-21 Vectored exception requests on the Host Interface!
+***************************************************************************/
+
+#include "opcode.h"
+
+#include "emu.h"
+#include "debugger.h"
+#include "dsp56k.h"
+
+#include "dsp56def.h"
+
+using namespace DSP56K;
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+static CPU_RESET( dsp56k );
+
+
+/***************************************************************************
+ COMPONENT FUNCTIONALITY
+***************************************************************************/
+/* 1-9 ALU */
+// #include "dsp56alu.h"
+
+/* 1-10 Address Generation Unit (AGU) */
+// #include "dsp56agu.h"
+
+/* 1-11 Program Control Unit (PCU) */
+#include "dsp56pcu.h"
+
+/* 5-1 Host Interface (HI) */
+//#include "dsp56hi.h"
+
+/* 4-8 Memory handlers for on-chip peripheral memory. */
+#include "dsp56mem.h"
+
+
+/***************************************************************************
+ Direct Update Handler
+***************************************************************************/
+DIRECT_UPDATE_HANDLER( dsp56k_direct_handler )
+{
+ if (address >= (0x0000<<1) && address <= (0x07ff<<1))
+ {
+ dsp56k_core* cpustate = get_safe_token(&direct.space().device());
+ direct.explicit_configure(0x0000<<1, 0x07ff<<1, (0x07ff<<1) | 1, cpustate->program_ram);
+ return ~0;
+ }
+
+ return address;
+}
+
+
+/***************************************************************************
+ MEMORY ACCESSORS
+***************************************************************************/
+#define ROPCODE(pc) cpustate->direct->read_decrypted_word(pc)
+
+
+/***************************************************************************
+ IRQ HANDLING
+***************************************************************************/
+static void set_irq_line(dsp56k_core* cpustate, int irqline, int state)
+{
+ //logerror("DSP56k set irq line %d %d\n", irqline, state);
+
+ switch(irqline)
+ {
+ case DSP56K_IRQ_MODA:
+ // TODO: 1-12 Get this triggering right
+ if (irqa_trigger(cpustate))
+ logerror("DSP56k IRQA is set to fire on the \"Negative Edge\".\n");
+
+ if (state != CLEAR_LINE)
+ cpustate->modA_state = TRUE;
+ else
+ cpustate->modA_state = FALSE;
+
+ if (cpustate->reset_state != TRUE)
+ dsp56k_add_pending_interrupt(cpustate, "IRQA");
+ break;
+
+ case DSP56K_IRQ_MODB:
+ // TODO: 1-12 Get this triggering right
+ if (irqb_trigger(cpustate))
+ logerror("DSP56k IRQB is set to fire on the \"Negative Edge\".\n");
+
+ if (state != CLEAR_LINE)
+ cpustate->modB_state = TRUE;
+ else
+ cpustate->modB_state = FALSE;
+
+ if (cpustate->reset_state != TRUE)
+ dsp56k_add_pending_interrupt(cpustate, "IRQB");
+ break;
+
+ case DSP56K_IRQ_MODC:
+ if (state != CLEAR_LINE)
+ cpustate->modC_state = TRUE;
+ else
+ cpustate->modC_state = FALSE;
+
+ // TODO : Set bus mode or whatever
+ break;
+
+ case DSP56K_IRQ_RESET:
+ if (state != CLEAR_LINE)
+ cpustate->reset_state = TRUE;
+ else
+ {
+ /* If it changes state from asserted to cleared. Call the reset function. */
+ if (cpustate->reset_state == TRUE)
+ CPU_RESET_NAME(dsp56k)(cpustate->device);
+
+ cpustate->reset_state = FALSE;
+ }
+
+ // dsp56k_add_pending_interrupt("Hardware RESET");
+ break;
+
+ default:
+ logerror("DSP56k setting some weird irq line : %d", irqline);
+ break;
+ }
+
+ /* If the reset line isn't asserted, service interrupts */
+ // TODO: Is it right to immediately service interrupts?
+ //if (cpustate->reset_state != TRUE)
+ // pcu_service_interrupts();
+}
+
+
+/***************************************************************************
+ INITIALIZATION AND SHUTDOWN
+***************************************************************************/
+static void agu_init(dsp56k_core* cpustate, device_t *device)
+{
+ /* save states - dsp56k_agu members */
+ device->save_item(NAME(cpustate->AGU.r0));
+ device->save_item(NAME(cpustate->AGU.r1));
+ device->save_item(NAME(cpustate->AGU.r2));
+ device->save_item(NAME(cpustate->AGU.r3));
+ device->save_item(NAME(cpustate->AGU.n0));
+ device->save_item(NAME(cpustate->AGU.n1));
+ device->save_item(NAME(cpustate->AGU.n2));
+ device->save_item(NAME(cpustate->AGU.n3));
+ device->save_item(NAME(cpustate->AGU.m0));
+ device->save_item(NAME(cpustate->AGU.m1));
+ device->save_item(NAME(cpustate->AGU.m2));
+ device->save_item(NAME(cpustate->AGU.m3));
+ device->save_item(NAME(cpustate->AGU.temp));
+}
+
+static void alu_init(dsp56k_core* cpustate, device_t *device)
+{
+ /* save states - dsp56k_alu members */
+ device->save_item(NAME(cpustate->ALU.x));
+ device->save_item(NAME(cpustate->ALU.y));
+ device->save_item(NAME(cpustate->ALU.a));
+ device->save_item(NAME(cpustate->ALU.b));
+}
+
+static CPU_INIT( dsp56k )
+{
+ dsp56k_core* cpustate = get_safe_token(device);
+
+ /* Call specific module inits */
+ pcu_init(cpustate, device);
+ agu_init(cpustate, device);
+ alu_init(cpustate, device);
+
+ /* HACK - You're not in bootstrap mode upon bootup */
+ cpustate->bootstrap_mode = BOOTSTRAP_OFF;
+
+ /* Clear the irq states */
+ cpustate->modA_state = FALSE;
+ cpustate->modB_state = FALSE;
+ cpustate->modC_state = FALSE;
+ cpustate->reset_state = FALSE;
+
+ /* save states - dsp56k_core members */
+ device->save_item(NAME(cpustate->modA_state));
+ device->save_item(NAME(cpustate->modB_state));
+ device->save_item(NAME(cpustate->modC_state));
+ device->save_item(NAME(cpustate->reset_state));
+ device->save_item(NAME(cpustate->bootstrap_mode));
+ device->save_item(NAME(cpustate->repFlag));
+ device->save_item(NAME(cpustate->repAddr));
+ device->save_item(NAME(cpustate->icount));
+ device->save_item(NAME(cpustate->ppc));
+ device->save_item(NAME(cpustate->op));
+ device->save_item(NAME(cpustate->interrupt_cycles));
+
+ /* save states - dsp56k_host_interface members */
+ device->save_item(NAME(cpustate->HI.icr));
+ device->save_item(NAME(cpustate->HI.cvr));
+ device->save_item(NAME(cpustate->HI.isr));
+ device->save_item(NAME(cpustate->HI.ivr));
+ device->save_item(NAME(cpustate->HI.trxh));
+ device->save_item(NAME(cpustate->HI.trxl));
+ device->save_item(NAME(cpustate->HI.bootstrap_offset));
+
+ //cpustate->config = device->static_config();
+ //cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+ cpustate->data = device->space(AS_DATA);
+
+ /* Setup the direct memory handler for this CPU */
+ /* NOTE: Be sure to grab this guy and call him if you ever install another direct_update_hander in a driver! */
+ cpustate->program->set_direct_update_handler(direct_update_delegate(FUNC(dsp56k_direct_handler), &device->machine()));
+}
+
+
+/***************************************************************************
+ RESET BEHAVIOR
+***************************************************************************/
+static void agu_reset(dsp56k_core* cpustate)
+{
+ /* FM.4-3 */
+ R0 = 0x0000;
+ R1 = 0x0000;
+ R2 = 0x0000;
+ R3 = 0x0000;
+
+ N0 = 0x0000;
+ N1 = 0x0000;
+ N2 = 0x0000;
+ N3 = 0x0000;
+
+ M0 = 0xffff;
+ M1 = 0xffff;
+ M2 = 0xffff;
+ M3 = 0xffff;
+
+ TEMP = 0x0000;
+}
+
+static void alu_reset(dsp56k_core* cpustate)
+{
+ X = 0x00000000;
+ Y = 0x00000000;
+ A = 0x0000000000;
+ B = 0x0000000000;
+}
+
+static CPU_RESET( dsp56k )
+{
+ dsp56k_core* cpustate = get_safe_token(device);
+ logerror("Dsp56k reset\n");
+
+ cpustate->interrupt_cycles = 0;
+ cpustate->ppc = 0x0000;
+
+ cpustate->repFlag = 0;
+ cpustate->repAddr = 0x0000;
+
+ pcu_reset(cpustate);
+ mem_reset(cpustate);
+ agu_reset(cpustate);
+ alu_reset(cpustate);
+
+ /* HACK - Put a jump to 0x0000 at 0x0000 - this keeps the CPU locked to the instruction at address 0x0000 */
+ cpustate->program->write_word(0x0000, 0x0124);
+}
+
+
+static CPU_EXIT( dsp56k )
+{
+}
+
+
+
+/***************************************************************************
+ CORE INCLUDE
+***************************************************************************/
+#include "dsp56ops.c"
+
+
+/***************************************************************************
+ CORE EXECUTION LOOP
+***************************************************************************/
+// Execute a single opcode and return how many cycles it took.
+static size_t execute_one_new(dsp56k_core* cpustate)
+{
+ // For MAME
+ cpustate->op = ROPCODE(ADDRESS(PC));
+ debugger_instruction_hook(cpustate->device, PC);
+
+ UINT16 w0 = ROPCODE(ADDRESS(PC));
+ UINT16 w1 = ROPCODE(ADDRESS(PC) + ADDRESS(1));
+
+ Opcode op(w0, w1);
+ op.evaluate(cpustate);
+ PC += op.evalSize(); // Special size function needed to handle jmps, etc.
+
+ // TODO: Currently all operations take up 4 cycles (inst->cycles()).
+ return 4;
+}
+
+static CPU_EXECUTE( dsp56k )
+{
+ dsp56k_core* cpustate = get_safe_token(device);
+
+ /* If reset line is asserted, do nothing */
+ if (cpustate->reset_state)
+ {
+ cpustate->icount = 0;
+ return;
+ }
+
+ /* HACK - if you're in bootstrap mode, simply pretend you ate up all your cycles waiting for data. */
+ if (cpustate->bootstrap_mode != BOOTSTRAP_OFF)
+ {
+ cpustate->icount = 0;
+ return;
+ }
+
+ //cpustate->icount -= cpustate->interrupt_cycles;
+ //cpustate->interrupt_cycles = 0;
+
+ while(cpustate->icount > 0)
+ {
+ execute_one(cpustate);
+ if (0) cpustate->icount -= execute_one_new(cpustate);
+ pcu_service_interrupts(cpustate); // TODO: Is it incorrect to service after each instruction?
+ }
+}
+
+
+
+/***************************************************************************
+ DISASSEMBLY HOOK
+***************************************************************************/
+extern CPU_DISASSEMBLE( dsp56k );
+
+
+/****************************************************************************
+ * Internal Memory Maps
+ ****************************************************************************/
+static ADDRESS_MAP_START( dsp56156_program_map, AS_PROGRAM, 16 )
+ AM_RANGE(0x0000,0x07ff) AM_READWRITE(DSP56K::program_r, DSP56K::program_w) /* 1-5 */
+// AM_RANGE(0x2f00,0x2fff) AM_ROM /* 1-5 PROM reserved memory. Is this the right spot for it? */
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( dsp56156_x_data_map, AS_DATA, 16 )
+ AM_RANGE(0x0000,0x07ff) AM_RAM /* 1-5 */
+ AM_RANGE(0xffc0,0xffff) AM_READWRITE(DSP56K::peripheral_register_r, DSP56K::peripheral_register_w) /* 1-5 On-chip peripheral registers memory mapped in data space */
+ADDRESS_MAP_END
+
+
+/**************************************************************************
+ * Generic set_info/get_info
+ **************************************************************************/
+enum
+{
+ // PCU
+ DSP56K_PC=1,
+ DSP56K_SR,
+ DSP56K_LC,
+ DSP56K_LA,
+ DSP56K_SP,
+ DSP56K_OMR,
+
+ // ALU
+ DSP56K_X, DSP56K_Y,
+ DSP56K_A, DSP56K_B,
+
+ // AGU
+ DSP56K_R0,DSP56K_R1,DSP56K_R2,DSP56K_R3,
+ DSP56K_N0,DSP56K_N1,DSP56K_N2,DSP56K_N3,
+ DSP56K_M0,DSP56K_M1,DSP56K_M2,DSP56K_M3,
+ DSP56K_TEMP,
+ DSP56K_STATUS,
+
+ // CPU STACK
+ DSP56K_ST0,
+ DSP56K_ST1,
+ DSP56K_ST2,
+ DSP56K_ST3,
+ DSP56K_ST4,
+ DSP56K_ST5,
+ DSP56K_ST6,
+ DSP56K_ST7,
+ DSP56K_ST8,
+ DSP56K_ST9,
+ DSP56K_ST10,
+ DSP56K_ST11,
+ DSP56K_ST12,
+ DSP56K_ST13,
+ DSP56K_ST14,
+ DSP56K_ST15
+};
+
+static CPU_SET_INFO( dsp56k )
+{
+ dsp56k_core* cpustate = get_safe_token(device);
+
+ switch (state)
+ {
+ case CPUINFO_INT_INPUT_STATE + DSP56K_IRQ_MODA: set_irq_line(cpustate, DSP56K_IRQ_MODA, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + DSP56K_IRQ_MODB: set_irq_line(cpustate, DSP56K_IRQ_MODB, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + DSP56K_IRQ_MODC: set_irq_line(cpustate, DSP56K_IRQ_MODC, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + DSP56K_IRQ_RESET: set_irq_line(cpustate, DSP56K_IRQ_RESET, info->i); break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + DSP56K_PC: PC = info->i & 0xffff; break;
+
+ case CPUINFO_INT_REGISTER + DSP56K_SR: SR = info->i & 0xffff; break;
+ case CPUINFO_INT_REGISTER + DSP56K_LC: LC = info->i & 0xffff; break;
+ case CPUINFO_INT_REGISTER + DSP56K_LA: LA = info->i & 0xffff; break;
+
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + DSP56K_SP: SP = info->i & 0xff; break;
+
+ case CPUINFO_INT_REGISTER + DSP56K_OMR: OMR = info->i & 0xff; break;
+
+ case CPUINFO_INT_REGISTER + DSP56K_X: X = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + DSP56K_Y: Y = info->i & 0xffffffff; break;
+
+ case CPUINFO_INT_REGISTER + DSP56K_A: A = info->i & (UINT64)U64(0xffffffffffffffff); break; /* could benefit from a better mask? */
+ case CPUINFO_INT_REGISTER + DSP56K_B: B = info->i & (UINT64)U64(0xffffffffffffffff); break; /* could benefit from a better mask? */
+
+ case CPUINFO_INT_REGISTER + DSP56K_R0: R0 = info->i & 0xffff; break;
+ case CPUINFO_INT_REGISTER + DSP56K_R1: R1 = info->i & 0xffff; break;
+ case CPUINFO_INT_REGISTER + DSP56K_R2: R2 = info->i & 0xffff; break;
+ case CPUINFO_INT_REGISTER + DSP56K_R3: R3 = info->i & 0xffff; break;
+
+ case CPUINFO_INT_REGISTER + DSP56K_N0: N0 = info->i & 0xffff; break;
+ case CPUINFO_INT_REGISTER + DSP56K_N1: N1 = info->i & 0xffff; break;
+ case CPUINFO_INT_REGISTER + DSP56K_N2: N2 = info->i & 0xffff; break;
+ case CPUINFO_INT_REGISTER + DSP56K_N3: N3 = info->i & 0xffff; break;
+
+ case CPUINFO_INT_REGISTER + DSP56K_M0: M0 = info->i & 0xffff; break;
+ case CPUINFO_INT_REGISTER + DSP56K_M1: M1 = info->i & 0xffff; break;
+ case CPUINFO_INT_REGISTER + DSP56K_M2: M2 = info->i & 0xffff; break;
+ case CPUINFO_INT_REGISTER + DSP56K_M3: M3 = info->i & 0xffff; break;
+
+ /* case CPUINFO_INT_REGISTER + DSP56K_TEMP: TEMP = info->i & 0xffff; break; */
+ /* case CPUINFO_INT_REGISTER + DSP56K_STATUS: STATUS = info->i & 0xff; break; */
+
+ /* The CPU stack */
+ case CPUINFO_INT_REGISTER + DSP56K_ST0: ST0 = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + DSP56K_ST1: ST1 = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + DSP56K_ST2: ST2 = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + DSP56K_ST3: ST3 = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + DSP56K_ST4: ST4 = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + DSP56K_ST5: ST5 = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + DSP56K_ST6: ST6 = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + DSP56K_ST7: ST7 = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + DSP56K_ST8: ST8 = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + DSP56K_ST9: ST9 = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + DSP56K_ST10: ST10 = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + DSP56K_ST11: ST11 = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + DSP56K_ST12: ST12 = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + DSP56K_ST13: ST13 = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + DSP56K_ST14: ST14 = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + DSP56K_ST15: ST15 = info->i & 0xffffffff; break;
+ }
+}
+
+
+CPU_GET_INFO( dsp56k )
+{
+ dsp56k_core* cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(dsp56k_core); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 4; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0x0000; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 2; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 2; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; // ? break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 8; // ? break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = -1; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = -1; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_INPUT_STATE + DSP56K_IRQ_MODA: info->i = DSP56K_IRQ_MODA; break;
+ case CPUINFO_INT_INPUT_STATE + DSP56K_IRQ_MODB: info->i = DSP56K_IRQ_MODB; break;
+ case CPUINFO_INT_INPUT_STATE + DSP56K_IRQ_MODC: info->i = DSP56K_IRQ_MODC; break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + DSP56K_PC: info->i = PC; break;
+ case CPUINFO_INT_PREVIOUSPC: info->i = cpustate->ppc; break;
+
+ case CPUINFO_INT_REGISTER + DSP56K_SR: info->i = SR; break;
+ case CPUINFO_INT_REGISTER + DSP56K_LC: info->i = LC; break;
+ case CPUINFO_INT_REGISTER + DSP56K_LA: info->i = LA; break;
+
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + DSP56K_SP: info->i = SP; break;
+
+ case CPUINFO_INT_REGISTER + DSP56K_OMR: info->i = OMR; break;
+
+ case CPUINFO_INT_REGISTER + DSP56K_X: info->i = X; break;
+ case CPUINFO_INT_REGISTER + DSP56K_Y: info->i = Y; break;
+
+ case CPUINFO_INT_REGISTER + DSP56K_A: info->i = A; break;
+ case CPUINFO_INT_REGISTER + DSP56K_B: info->i = B; break;
+
+ case CPUINFO_INT_REGISTER + DSP56K_R0: info->i = R0; break;
+ case CPUINFO_INT_REGISTER + DSP56K_R1: info->i = R1; break;
+ case CPUINFO_INT_REGISTER + DSP56K_R2: info->i = R2; break;
+ case CPUINFO_INT_REGISTER + DSP56K_R3: info->i = R3; break;
+
+ case CPUINFO_INT_REGISTER + DSP56K_N0: info->i = N0; break;
+ case CPUINFO_INT_REGISTER + DSP56K_N1: info->i = N1; break;
+ case CPUINFO_INT_REGISTER + DSP56K_N2: info->i = N2; break;
+ case CPUINFO_INT_REGISTER + DSP56K_N3: info->i = N3; break;
+
+ case CPUINFO_INT_REGISTER + DSP56K_M0: info->i = M0; break;
+ case CPUINFO_INT_REGISTER + DSP56K_M1: info->i = M1; break;
+ case CPUINFO_INT_REGISTER + DSP56K_M2: info->i = M2; break;
+ case CPUINFO_INT_REGISTER + DSP56K_M3: info->i = M3; break;
+
+ /* case CPUINFO_INT_REGISTER + DSP56K_TEMP: info->i = TEMP; break; */
+ /* case CPUINFO_INT_REGISTER + DSP56K_STATUS: info->i = STATUS; break; */
+
+ /* The CPU stack */
+ case CPUINFO_INT_REGISTER + DSP56K_ST0: info->i = ST0; break;
+ case CPUINFO_INT_REGISTER + DSP56K_ST1: info->i = ST1; break;
+ case CPUINFO_INT_REGISTER + DSP56K_ST2: info->i = ST2; break;
+ case CPUINFO_INT_REGISTER + DSP56K_ST3: info->i = ST3; break;
+ case CPUINFO_INT_REGISTER + DSP56K_ST4: info->i = ST4; break;
+ case CPUINFO_INT_REGISTER + DSP56K_ST5: info->i = ST5; break;
+ case CPUINFO_INT_REGISTER + DSP56K_ST6: info->i = ST6; break;
+ case CPUINFO_INT_REGISTER + DSP56K_ST7: info->i = ST7; break;
+ case CPUINFO_INT_REGISTER + DSP56K_ST8: info->i = ST8; break;
+ case CPUINFO_INT_REGISTER + DSP56K_ST9: info->i = ST9; break;
+ case CPUINFO_INT_REGISTER + DSP56K_ST10: info->i = ST10; break;
+ case CPUINFO_INT_REGISTER + DSP56K_ST11: info->i = ST11; break;
+ case CPUINFO_INT_REGISTER + DSP56K_ST12: info->i = ST12; break;
+ case CPUINFO_INT_REGISTER + DSP56K_ST13: info->i = ST13; break;
+ case CPUINFO_INT_REGISTER + DSP56K_ST14: info->i = ST14; break;
+ case CPUINFO_INT_REGISTER + DSP56K_ST15: info->i = ST15; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(dsp56k); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(dsp56k); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(dsp56k); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(dsp56k); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(dsp56k); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(dsp56k); break;
+ case CPUINFO_FCT_DEBUG_INIT: info->debug_init = NULL; break;
+ case CPUINFO_FCT_TRANSLATE: info->translate = NULL; break;
+ case CPUINFO_FCT_READ: info->read = NULL; break;
+ case CPUINFO_FCT_WRITE: info->write = NULL; break;
+ case CPUINFO_FCT_READOP: info->readop = NULL; break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA:
+ info->internal_map16 = ADDRESS_MAP_NAME(dsp56156_x_data_map); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM:
+ info->internal_map16 = ADDRESS_MAP_NAME(dsp56156_program_map); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "DSP56156"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Motorola DSP56156"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "0.1"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Andrew Gardner"); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%s%s %s%s%s%s%s%s%s%s %s%s",
+ /* Status Register */
+ LF_bit(cpustate) ? "L" : ".",
+ FV_bit(cpustate) ? "F" : ".",
+
+ S_bit(cpustate) ? "S" : ".",
+ L_bit(cpustate) ? "L" : ".",
+ E_bit(cpustate) ? "E" : ".",
+ U_bit(cpustate) ? "U" : ".",
+ N_bit(cpustate) ? "N" : ".",
+ Z_bit(cpustate) ? "Z" : ".",
+ V_bit(cpustate) ? "V" : ".",
+ C_bit(cpustate) ? "C" : ".",
+
+ /* Stack Pointer */
+ UF_bit(cpustate) ? "U" : ".",
+ SE_bit(cpustate) ? "S" : ".");
+ break;
+
+ case CPUINFO_STR_REGISTER + DSP56K_PC: sprintf(info->s, "PC : %04x", PC); break;
+ case CPUINFO_STR_REGISTER + DSP56K_SR: sprintf(info->s, "SR : %04x", SR); break;
+ case CPUINFO_STR_REGISTER + DSP56K_LC: sprintf(info->s, "LC : %04x", LC); break;
+ case CPUINFO_STR_REGISTER + DSP56K_LA: sprintf(info->s, "LA : %04x", LA); break;
+ case CPUINFO_STR_REGISTER + DSP56K_SP: sprintf(info->s, "SP : %02x", SP); break;
+ case CPUINFO_STR_REGISTER + DSP56K_OMR: sprintf(info->s, "OMR: %02x", OMR); break;
+
+ case CPUINFO_STR_REGISTER + DSP56K_X: sprintf(info->s, "X : %04x %04x", X1, X0); break;
+ case CPUINFO_STR_REGISTER + DSP56K_Y: sprintf(info->s, "Y : %04x %04x", Y1, Y0); break;
+
+ case CPUINFO_STR_REGISTER + DSP56K_A: sprintf(info->s, "A : %02x %04x %04x", A2,A1,A0); break;
+ case CPUINFO_STR_REGISTER + DSP56K_B: sprintf(info->s, "B : %02x %04x %04x", B2,B1,B0); break;
+
+ case CPUINFO_STR_REGISTER + DSP56K_R0: sprintf(info->s, "R0 : %04x", R0); break;
+ case CPUINFO_STR_REGISTER + DSP56K_R1: sprintf(info->s, "R1 : %04x", R1); break;
+ case CPUINFO_STR_REGISTER + DSP56K_R2: sprintf(info->s, "R2 : %04x", R2); break;
+ case CPUINFO_STR_REGISTER + DSP56K_R3: sprintf(info->s, "R3 : %04x", R3); break;
+
+ case CPUINFO_STR_REGISTER + DSP56K_N0: sprintf(info->s, "N0 : %04x", N0); break;
+ case CPUINFO_STR_REGISTER + DSP56K_N1: sprintf(info->s, "N1 : %04x", N1); break;
+ case CPUINFO_STR_REGISTER + DSP56K_N2: sprintf(info->s, "N2 : %04x", N2); break;
+ case CPUINFO_STR_REGISTER + DSP56K_N3: sprintf(info->s, "N3 : %04x", N3); break;
+
+ case CPUINFO_STR_REGISTER + DSP56K_M0: sprintf(info->s, "M0 : %04x", M0); break;
+ case CPUINFO_STR_REGISTER + DSP56K_M1: sprintf(info->s, "M1 : %04x", M1); break;
+ case CPUINFO_STR_REGISTER + DSP56K_M2: sprintf(info->s, "M2 : %04x", M2); break;
+ case CPUINFO_STR_REGISTER + DSP56K_M3: sprintf(info->s, "M3 : %04x", M3); break;
+
+ /* case CPUINFO_STR_REGISTER + DSP56K_TEMP: sprintf(info->s, "TMP: %04x", TEMP); break; */
+ /* case CPUINFO_STR_REGISTER + DSP56K_STATUS: sprintf(info->s, "STS: %02x", STATUS); break; */
+
+ /* The CPU stack */
+ case CPUINFO_STR_REGISTER + DSP56K_ST0: sprintf(info->s, "ST0 : %08x", ST0); break;
+ case CPUINFO_STR_REGISTER + DSP56K_ST1: sprintf(info->s, "ST1 : %08x", ST1); break;
+ case CPUINFO_STR_REGISTER + DSP56K_ST2: sprintf(info->s, "ST2 : %08x", ST2); break;
+ case CPUINFO_STR_REGISTER + DSP56K_ST3: sprintf(info->s, "ST3 : %08x", ST3); break;
+ case CPUINFO_STR_REGISTER + DSP56K_ST4: sprintf(info->s, "ST4 : %08x", ST4); break;
+ case CPUINFO_STR_REGISTER + DSP56K_ST5: sprintf(info->s, "ST5 : %08x", ST5); break;
+ case CPUINFO_STR_REGISTER + DSP56K_ST6: sprintf(info->s, "ST6 : %08x", ST6); break;
+ case CPUINFO_STR_REGISTER + DSP56K_ST7: sprintf(info->s, "ST7 : %08x", ST7); break;
+ case CPUINFO_STR_REGISTER + DSP56K_ST8: sprintf(info->s, "ST8 : %08x", ST8); break;
+ case CPUINFO_STR_REGISTER + DSP56K_ST9: sprintf(info->s, "ST9 : %08x", ST9); break;
+ case CPUINFO_STR_REGISTER + DSP56K_ST10: sprintf(info->s, "ST10: %08x", ST10); break;
+ case CPUINFO_STR_REGISTER + DSP56K_ST11: sprintf(info->s, "ST11: %08x", ST11); break;
+ case CPUINFO_STR_REGISTER + DSP56K_ST12: sprintf(info->s, "ST12: %08x", ST12); break;
+ case CPUINFO_STR_REGISTER + DSP56K_ST13: sprintf(info->s, "ST13: %08x", ST13); break;
+ case CPUINFO_STR_REGISTER + DSP56K_ST14: sprintf(info->s, "ST14: %08x", ST14); break;
+ case CPUINFO_STR_REGISTER + DSP56K_ST15: sprintf(info->s, "ST15: %08x", ST15); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(DSP56156, dsp56k);
diff --git a/trunk/src/emu/cpu/dsp56k/dsp56k.h b/trunk/src/emu/cpu/dsp56k/dsp56k.h
new file mode 100644
index 00000000000..16f768d8a89
--- /dev/null
+++ b/trunk/src/emu/cpu/dsp56k/dsp56k.h
@@ -0,0 +1,219 @@
+/***************************************************************************
+
+ dsp56k.h
+ Interface file for the portable Motorola/Freescale DSP56k emulator.
+ Written by Andrew Gardner
+
+***************************************************************************/
+
+
+#pragma once
+
+#ifndef __DSP56K_H__
+#define __DSP56K_H__
+
+#include "emu.h"
+
+
+// IRQ Lines
+// MODA and MODB are also known as IRQA and IRQB
+#define DSP56K_IRQ_MODA 0
+#define DSP56K_IRQ_MODB 1
+#define DSP56K_IRQ_MODC 2
+#define DSP56K_IRQ_RESET 3 /* Is this needed? */
+
+// Needed for MAME
+DECLARE_LEGACY_CPU_DEVICE(DSP56156, dsp56k);
+
+
+/***************************************************************************
+ STRUCTURES & TYPEDEFS
+***************************************************************************/
+// 5-4 Host Interface
+typedef struct
+{
+ // **** Dsp56k side **** //
+ // Host Control Register
+ UINT16* hcr;
+
+ // Host Status Register
+ UINT16* hsr;
+
+ // Host Transmit/Receive Data
+ UINT16* htrx;
+
+ // **** Host CPU side **** //
+ // Interrupt Control Register
+ UINT8 icr;
+
+ // Command Vector Register
+ UINT8 cvr;
+
+ // Interrupt Status Register
+ UINT8 isr;
+
+ // Interrupt Vector Register
+ UINT8 ivr;
+
+ // Transmit / Receive Registers
+ UINT8 trxh;
+ UINT8 trxl;
+
+ // HACK - Host interface bootstrap write offset
+ UINT16 bootstrap_offset;
+
+} dsp56k_host_interface;
+
+// 1-9 ALU
+typedef struct
+{
+ // Four 16-bit input registers (can be accessed as 2 32-bit registers)
+ PAIR x;
+ PAIR y;
+
+ // Two 32-bit accumulator registers + 8-bit accumulator extension registers
+ PAIR64 a;
+ PAIR64 b;
+
+ // An accumulation shifter
+ // One data bus shifter/limiter
+ // A parallel, single cycle, non-pipelined Multiply-Accumulator (MAC) unit
+ // Basics
+} dsp56k_data_alu;
+
+// 1-10 Address Generation Unit (AGU)
+typedef struct
+{
+ // Four address registers
+ UINT16 r0;
+ UINT16 r1;
+ UINT16 r2;
+ UINT16 r3;
+
+ // Four offset registers
+ UINT16 n0;
+ UINT16 n1;
+ UINT16 n2;
+ UINT16 n3;
+
+ // Four modifier registers
+ UINT16 m0;
+ UINT16 m1;
+ UINT16 m2;
+ UINT16 m3;
+
+ // Used in loop processing
+ UINT16 temp;
+
+ // FM.4-5 - hmmm?
+ // UINT8 status;
+
+ // Basics
+} dsp56k_agu;
+
+// 1-11 Program Control Unit (PCU)
+typedef struct
+{
+ // Program Counter
+ UINT16 pc;
+
+ // Loop Address
+ UINT16 la;
+
+ // Loop Counter
+ UINT16 lc;
+
+ // Status Register
+ UINT16 sr;
+
+ // Operating Mode Register
+ UINT16 omr;
+
+ // Stack Pointer
+ UINT16 sp;
+
+ // Stack (TODO: 15-level?)
+ PAIR ss[16];
+
+ // Controls IRQ processing
+ void (*service_interrupts)(void);
+
+ // A list of pending interrupts (indices into dsp56k_interrupt_sources array)
+ INT8 pending_interrupts[32];
+
+ // Basics
+
+ // Other PCU internals
+ UINT16 reset_vector;
+
+} dsp56k_pcu;
+
+// 1-8 The dsp56156 CORE
+typedef struct
+{
+ // PROGRAM CONTROLLER
+ dsp56k_pcu PCU;
+
+ // ADR ALU (AGU)
+ dsp56k_agu AGU;
+
+ // CLOCK GEN
+ //static emu_timer *dsp56k_timer; // 1-5, 1-8 - Clock gen
+
+ // DATA ALU
+ dsp56k_data_alu ALU;
+
+ // OnCE
+
+ // IBS and BITFIELD UNIT
+
+ // Host Interface
+ dsp56k_host_interface HI;
+
+ // IRQ line states
+ UINT8 modA_state;
+ UINT8 modB_state;
+ UINT8 modC_state;
+ UINT8 reset_state;
+
+ // HACK - Bootstrap mode state variable.
+ UINT8 bootstrap_mode;
+
+ UINT8 repFlag; // Knowing if we're in a 'repeat' state (dunno how the processor does this)
+ UINT32 repAddr; // The address of the instruction to repeat...
+
+
+ /* MAME internal stuff */
+ int icount;
+
+ UINT32 ppc;
+ UINT32 op;
+ int interrupt_cycles;
+ void (*output_pins_changed)(UINT32 pins);
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ address_space *data;
+
+ UINT16 peripheral_ram[0x40];
+ UINT16 program_ram[0x800];
+} dsp56k_core;
+
+
+INLINE dsp56k_core *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == DSP56156);
+ return (dsp56k_core *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+
+/***************************************************************************
+ PUBLIC FUNCTIONS - ACCESSIBLE TO DRIVERS
+***************************************************************************/
+void dsp56k_host_interface_write(device_t* device, UINT8 offset, UINT8 data);
+UINT8 dsp56k_host_interface_read(device_t* device, UINT8 offset);
+
+UINT16 dsp56k_get_peripheral_memory(device_t* device, UINT16 addr);
+
+#endif /* __DSP56K_H__ */
diff --git a/trunk/src/emu/cpu/dsp56k/dsp56mem.c b/trunk/src/emu/cpu/dsp56k/dsp56mem.c
new file mode 100644
index 00000000000..2106b90511e
--- /dev/null
+++ b/trunk/src/emu/cpu/dsp56k/dsp56mem.c
@@ -0,0 +1,962 @@
+// This file contains functions which handle the On-Chip peripheral Memory Map
+// as well as the Host Interface and the SSI0/SSI1 Serial Interfaces.
+
+#include "dsp56mem.h"
+#include "dsp56pcu.h"
+
+namespace DSP56K
+{
+
+/* IPR Accessor Implementations */
+void IPR_set(dsp56k_core* cpustate, UINT16 value)
+{
+ /* TODO: Is there anything else? */
+ IPR = value;
+}
+
+INT8 irqa_ipl(dsp56k_core* cpustate) { return ((IPR & 0x0003) >> 0) - 1; }
+UINT8 irqa_trigger(dsp56k_core* cpustate){ return (IPR & 0x0004) >> 2; }
+INT8 irqb_ipl(dsp56k_core* cpustate) { return ((IPR & 0x0018) >> 3) - 1; }
+UINT8 irqb_trigger(dsp56k_core* cpustate){ return (IPR & 0x0002) >> 5; }
+INT8 codec_ipl(dsp56k_core* cpustate) { return ((IPR & 0x00c0) >> 6) - 1; }
+INT8 host_ipl(dsp56k_core* cpustate) { return ((IPR & 0x0300) >> 8) - 1; }
+INT8 ssi0_ipl(dsp56k_core* cpustate) { return ((IPR & 0x0c00) >> 10) - 1; }
+INT8 ssi1_ipl(dsp56k_core* cpustate) { return ((IPR & 0x3000) >> 12) - 1; }
+INT8 tm_ipl(dsp56k_core* cpustate) { return ((IPR & 0xc000) >> 14) - 1; }
+
+void mem_reset(dsp56k_core* cpustate)
+{
+ // Reset the HI registers
+ dsp56k_host_interface_reset(cpustate);
+
+ // Reset the IO registers
+ dsp56k_io_reset(cpustate);
+}
+
+
+/***************************************************************************
+ HOST INTERFACE
+***************************************************************************/
+/***************/
+/* DSP56k SIDE */
+/***************/
+/************************************/
+/* Host Control Register (HCR) Bits */
+/************************************/
+void HCR_set(dsp56k_core* cpustate, UINT16 value)
+{
+ HF3_bit_set (cpustate, (value & 0x0010) >> 4);
+ HF2_bit_set (cpustate, (value & 0x0008) >> 3);
+ HCIE_bit_set(cpustate, (value & 0x0004) >> 2);
+ HTIE_bit_set(cpustate, (value & 0x0002) >> 1);
+ HRIE_bit_set(cpustate, (value & 0x0001) >> 0);
+}
+//UINT16 HF3_bit(dsp56k_core* cpustate) { return ((HCR & 0x0010) != 0); }
+//UINT16 HF2_bit(dsp56k_core* cpustate) { return ((HCR & 0x0008) != 0); }
+UINT16 HCIE_bit(dsp56k_core* cpustate) { return ((HCR & 0x0004) != 0); }
+UINT16 HTIE_bit(dsp56k_core* cpustate) { return ((HCR & 0x0002) != 0); }
+UINT16 HRIE_bit(dsp56k_core* cpustate) { return ((HCR & 0x0001) != 0); }
+
+void HF3_bit_set(dsp56k_core* cpustate, UINT16 value)
+{
+ value = value & 0x01;
+ HCR &= ~(0x0010);
+ HCR |= (value << 4);
+
+ HF3_bit_host_set(cpustate, value);
+}
+void HF2_bit_set(dsp56k_core* cpustate, UINT16 value)
+{
+ value = value & 0x01;
+ HCR &= ~(0x0008);
+ HCR |= (value << 3);
+
+ HF2_bit_host_set(cpustate, value);
+}
+void HCIE_bit_set(dsp56k_core* cpustate, UINT16 value)
+{
+ value = value & 0x01;
+ HCR &= ~(0x0004);
+ HCR |= (value << 2);
+}
+void HTIE_bit_set(dsp56k_core* cpustate, UINT16 value)
+{
+ value = value & 0x01;
+ HCR &= ~(0x0002);
+ HCR |= (value << 1);
+}
+void HRIE_bit_set(dsp56k_core* cpustate, UINT16 value)
+{
+ value = value & 0x01;
+ HCR &= ~(0x0001);
+ HCR |= (value << 0);
+}
+
+/***********************************/
+/* Host Status Register (HSR) Bits */
+/***********************************/
+//UINT16 DMA_bit(dsp56k_core* cpustate) { return ((HSR & 0x0080) != 0); }
+//UINT16 HF1_bit(dsp56k_core* cpustate) { return ((HSR & 0x0010) != 0); }
+//UINT16 HF0_bit(dsp56k_core* cpustate) { return ((HSR & 0x0008) != 0); }
+//UINT16 HCP_bit(dsp56k_core* cpustate) { return ((HSR & 0x0004) != 0); }
+UINT16 HTDE_bit(dsp56k_core* cpustate) { return ((HSR & 0x0002) != 0); }
+UINT16 HRDF_bit(dsp56k_core* cpustate) { return ((HSR & 0x0001) != 0); }
+
+void DMA_bit_set(dsp56k_core* cpustate, UINT16 value)
+{
+ value = value & 0x01;
+ HSR &= ~(0x0080);
+ HSR |= (value << 7);
+ // TODO: 5-12 When the DMA bit is set, the DMA mode is enabled by the Host Mode bits HM0 & HM1
+}
+void HF1_bit_set(dsp56k_core* cpustate, UINT16 value)
+{
+ value = value & 0x01;
+ HSR &= ~(0x0010);
+ HSR |= (value << 4);
+}
+void HF0_bit_set(dsp56k_core* cpustate, UINT16 value)
+{
+ value = value & 0x01;
+ HSR &= ~(0x0008);
+ HSR |= (value << 3);
+}
+void HCP_bit_set(dsp56k_core* cpustate, UINT16 value)
+{
+ value = value & 0x01;
+ HSR &= ~(0x0004);
+ HSR |= (value << 2);
+
+ if (value && HCIE_bit(cpustate))
+ dsp56k_add_pending_interrupt(cpustate, "Host Command");
+}
+void HTDE_bit_set(dsp56k_core* cpustate, UINT16 value)
+{
+ value = value & 0x01;
+ HSR &= ~(0x0002);
+ HSR |= (value << 1);
+
+ // 5-10 If HTIE bit is set, whip out a Host Transmit Data interrupt
+ if (value && HTIE_bit(cpustate))
+ dsp56k_add_pending_interrupt(cpustate, "Host Transmit Data");
+
+ // 5-5 If both me and RXDF are cleared, transmit data to the host
+ if (!value && !RXDF_bit(cpustate))
+ dsp56k_host_interface_HTX_to_host(cpustate);
+}
+void HRDF_bit_set(dsp56k_core* cpustate, UINT16 value)
+{
+ value = value & 0x01;
+ HSR &= ~(0x0001);
+ HSR |= (value << 0);
+
+ // 5-10 If HRIE is set, whip out a Host Receive Data interrupt
+ if (value && HRIE_bit(cpustate))
+ dsp56k_add_pending_interrupt(cpustate, "Host Receive Data");
+
+ // 5-5 If both me and TXDE are cleared, transmit data to the dsp56k
+ if (!value && !TXDE_bit(cpustate))
+ dsp56k_host_interface_host_to_HTX(cpustate);
+}
+
+
+
+/*************/
+/* HOST SIDE */
+/*************/
+/*****************************************/
+/* Interrupt Control Register (ICR) Bits */
+/*****************************************/
+void ICR_set(dsp56k_core* cpustate, UINT8 value)
+{
+ HF1_bit_host_set(cpustate, (value & 0x10) >> 4);
+ HF0_bit_host_set(cpustate, (value & 0x08) >> 3);
+ TREQ_bit_set(cpustate, (value & 0x02) >> 1);
+ RREQ_bit_set(cpustate, (value & 0x01) >> 0);
+}
+
+//UINT8 INIT_bit(dsp56k_core* cpustate); #define x_initBIT ((dsp56k.HI.ICR & 0x0080) != 0)
+//UINT8 HM1_bit(dsp56k_core* cpustate); #define x_hm1BIT ((dsp56k.HI.ICR & 0x0040) != 0)
+//UINT8 HM0_bit(dsp56k_core* cpustate); #define x_hm0BIT ((dsp56k.HI.ICR & 0x0020) != 0)
+//UINT8 HF1_bit_host(dsp56k_core* cpustate); #define x_hf1BIT ((dsp56k.HI.ICR & 0x0010) != 0)
+//UINT8 HF0_bit_host(dsp56k_core* cpustate); #define x_hf0BIT ((dsp56k.HI.ICR & 0x0008) != 0)
+//UINT8 TREQ_bit(dsp56k_core* cpustate); #define x_treqBIT ((dsp56k.HI.ICR & 0x0002) != 0)
+//UINT8 RREQ_bit(dsp56k_core* cpustate); #define x_rreqBIT ((dsp56k.HI.ICR & 0x0001) != 0)
+
+//void INIT_bit_set(dsp56k_core* cpustate, UINT8 value); #define CLEAR_x_initBIT() (dsp56k.HI.ICR &= (~0x0080))
+//void HM1_bit_set(dsp56k_core* cpustate, UINT8 value); #define CLEAR_x_hm1BIT() (dsp56k.HI.ICR &= (~0x0040))
+//void HM0_bit_set(dsp56k_core* cpustate, UINT8 value); #define CLEAR_x_hm0BIT() (dsp56k.HI.ICR &= (~0x0020))
+void HF1_bit_host_set(dsp56k_core* cpustate, UINT8 value)
+{
+ value = value & 0x01;
+ ICR &= ~(0x10);
+ ICR |= (value << 4);
+
+ HF1_bit_set(cpustate, value); // 5-14
+}
+void HF0_bit_host_set(dsp56k_core* cpustate, UINT8 value)
+{
+ value = value & 0x01;
+ ICR &= ~(0x08);
+ ICR |= (value << 3);
+
+ HF0_bit_set(cpustate, value); // 5-13
+}
+void TREQ_bit_set(dsp56k_core* cpustate, UINT8 value)
+{
+ value = value & 0x01;
+ ICR &= ~(0x02);
+ ICR |= (value << 1);
+}
+void RREQ_bit_set(dsp56k_core* cpustate, UINT8 value)
+{
+ value = value & 0x01;
+ ICR &= ~(0x01);
+ ICR |= (value << 0);
+
+ // 5-12
+ if (value)
+ {
+ // TODO : HREQ_assert();
+ }
+}
+
+
+
+/**************************************/
+/* Command Vector Register (CVR) Bits */
+/**************************************/
+UINT8 HV_bits(dsp56k_core* cpustate) { return (CVR & 0x1f); }
+
+void CVR_set(dsp56k_core* cpustate, UINT8 value)
+{
+ /* A single, unified place to run all callbacks for each of the bits */
+ HC_bit_set(cpustate, (value & 0x80) >> 7);
+ HV_bits_set(cpustate, (value & 0x1f));
+}
+
+void HC_bit_set(dsp56k_core* cpustate, UINT8 value)
+{
+ value = value & 0x01;
+ CVR &= ~(0x80);
+ CVR |= (value << 7);
+
+ HCP_bit_set(cpustate, value); // 5-9 & 5-11
+}
+void HV_bits_set(dsp56k_core* cpustate, UINT8 value)
+{
+ value = value & 0x1f;
+ CVR &= ~(0x1f);
+ CVR |= (value << 0);
+}
+
+
+/****************************************/
+/* Interrupt Status Register (ISR) Bits */
+/****************************************/
+UINT8 TXDE_bit(dsp56k_core* cpustate) { return ((ISR & 0x0002) != 0); }
+UINT8 RXDF_bit(dsp56k_core* cpustate) { return ((ISR & 0x0001) != 0); }
+
+void HF3_bit_host_set(dsp56k_core* cpustate, UINT8 value)
+{
+ value = value & 0x01;
+ ISR &= ~(0x0010);
+ ISR |= (value << 4);
+}
+void HF2_bit_host_set(dsp56k_core* cpustate, UINT8 value)
+{
+ value = value & 0x01;
+ ISR &= ~(0x0008);
+ ISR |= (value << 3);
+}
+
+void TXDE_bit_set(dsp56k_core* cpustate, UINT8 value)
+{
+ value = value & 0x01;
+ ISR &= ~(0x0002);
+ ISR |= (value << 1);
+
+ // If both me and the HRDF are cleared, transmit data to the dsp56k
+ if (!value && !HRDF_bit(cpustate))
+ dsp56k_host_interface_host_to_HTX(cpustate);
+}
+
+void RXDF_bit_set(dsp56k_core* cpustate, UINT8 value)
+{
+ value = value & 0x01;
+ ISR &= ~(0x0001);
+ ISR |= (value << 0);
+
+ // If both me and HTDE are cleared, transmit data to the host
+ if (!value && !HTDE_bit(cpustate))
+ dsp56k_host_interface_HTX_to_host(cpustate);
+}
+
+
+// TODO: 5-11 What is the host processor Initialize function?
+
+void dsp56k_host_interface_reset(dsp56k_core* cpustate)
+{
+ // Hook up the CPU-side pointers properly.
+ cpustate->HI.hcr = &cpustate->peripheral_ram[A2O(0xffc4)];
+ cpustate->HI.hsr = &cpustate->peripheral_ram[A2O(0xffe4)];
+ cpustate->HI.htrx = &cpustate->peripheral_ram[A2O(0xffe5)];
+
+ // The Bootstrap hack is initialized to write to address 0x0000
+ cpustate->HI.bootstrap_offset = 0x0000;
+
+ /* HCR */
+ HCR_set(cpustate, 0x0000); // 5-10
+
+ /* HSR */
+ HRDF_bit_set(cpustate, 0); // 5-11
+ HTDE_bit_set(cpustate, 1); // 5-11
+ HCP_bit_set(cpustate, 0); // 5-11
+ HF0_bit_set(cpustate, 0); // 5-12
+ HF1_bit_set(cpustate, 0); // 5-12
+ DMA_bit_set(cpustate, 0); // 5-12
+
+ /* CVR*/
+ HV_bits_set(cpustate, 0x16); // 5-7
+ HC_bit_set(cpustate, 0); // 5-9
+
+ /* TODO: ISR (at least) */
+}
+
+void dsp56k_host_interface_HTX_to_host(dsp56k_core* cpustate)
+{
+ RXH = ((HTX & 0xff00) >> 8);
+ RXL = ((HTX & 0x00ff));
+ RXDF_bit_set(cpustate, 1);
+ HTDE_bit_set(cpustate, 1);
+}
+
+void dsp56k_host_interface_host_to_HTX(dsp56k_core* cpustate)
+{
+ HRX &= 0x00ff;
+ HRX |= (TXH << 8);
+ HRX &= 0xff00;
+ HRX |= TXL;
+ TXDE_bit_set(cpustate, 1);
+ HRDF_bit_set(cpustate, 1);
+}
+
+
+/***************************************************************************
+ I/O INTERFACE
+***************************************************************************/
+/* BCR */
+void BCR_set(dsp56k_core* cpustate, UINT16 value)
+{
+ RH_bit_set(cpustate, (value & 0x8000) >> 15);
+ BS_bit_set(cpustate, (value & 0x4000) >> 14);
+ external_x_wait_states_set(cpustate, (value & 0x03e0) >> 5);
+ external_p_wait_states_set(cpustate, (value & 0x001f) >> 0);
+}
+
+//UINT16 RH_bit(dsp56k_core* cpustate);
+//UINT16 BS_bit(dsp56k_core* cpustate);
+//UINT16 external_x_wait_states(dsp56k_core* cpustate);
+//UINT16 external_p_wait_states(dsp56k_core* cpustate);
+
+void RH_bit_set(dsp56k_core* cpustate, UINT16 value)
+{
+ value = value & 0x0001;
+ BCR &= ~(0x8000);
+ BCR |= (value << 15);
+
+ // TODO: 4-6 Assert BR pin?
+}
+void BS_bit_set(dsp56k_core* cpustate, UINT16 value)
+{
+ value = value & 0x0001;
+ BCR &= ~(0x4000);
+ BCR |= (value << 14);
+
+ // TODO: 4-6 Respond to BR pin?
+}
+void external_x_wait_states_set(dsp56k_core* cpustate, UINT16 value)
+{
+ value = value & 0x001f;
+ BCR &= ~(0x03e0);
+ BCR |= (value << 5);
+}
+void external_p_wait_states_set(dsp56k_core* cpustate, UINT16 value)
+{
+ value = value & 0x001f;
+ BCR &= ~(0x001f);
+ BCR |= (value << 0);
+}
+
+
+/* Port B Control Register PBC */
+void PBC_set(dsp56k_core* cpustate, UINT16 value)
+{
+ if (value & 0xfffe)
+ logerror("Dsp56k : Attempting to set reserved bits in the PBC. Ignoring.\n");
+
+ value = value & 0x0001;
+ PBC &= ~(0x0001);
+ PBC |= (value << 0);
+}
+
+#ifdef UNUSED_FUNCTION
+int host_interface_active(dsp56k_core* cpustate)
+{
+ /* The host interface is active if the 0th bit in the PBC is set */
+ return PBC & 0x0001;
+}
+#endif
+
+/* Port B Data Direction Register (PBDDR) */
+void PBDDR_set(dsp56k_core* cpustate, UINT16 value)
+{
+ if (value & 0x8000)
+ logerror("Dsp56k : Attempting to set reserved bits in the PBDDR. Ignoring.\n");
+
+ value = value & 0x7fff;
+ PBDDR &= ~(0x7fff);
+ PBDDR |= (value << 0);
+
+ /* TODO: Implement dsp56k io restrictions, etc. */
+}
+
+/* Port B Data Register (PBD) */
+void PBD_set(dsp56k_core* cpustate, UINT16 value)
+{
+ if (value & 0x8000)
+ logerror("Dsp56k : Attempting to set reserved bits in the PBD. Ignoring.\n");
+
+ value = value & 0x7fff;
+ PBD &= ~(0x7fff);
+ PBD |= (value << 0);
+
+ /* TODO: Implement dsp56k io restrictions, etc. */
+}
+
+/* Port C Control Register (PCC) */
+void PCC_set(dsp56k_core* cpustate, UINT16 value)
+{
+ if (value & 0xf000)
+ logerror("Dsp56k : Attempting to set reserved bits in the PCC. Ignoring.\n");
+
+ value = value & 0x0fff;
+ PCC &= ~(0x0fff);
+ PCC |= (value << 0);
+
+ /* TODO: Implement dsp56k timer and control glue */
+}
+
+/* Port C Data Direction Register (PCDDR) */
+void PCDDR_set(dsp56k_core* cpustate, UINT16 value)
+{
+ if (value & 0xf000)
+ logerror("Dsp56k : Attempting to set reserved bits in the PCDDR. Ignoring.\n");
+
+ value = value & 0x0fff;
+ PCDDR &= ~(0x0fff);
+ PCDDR |= (value << 0);
+
+ /* TODO: Implement dsp56k io restrictions, etc. */
+}
+
+/* Port C Data Register (PCD) */
+void PCD_set(dsp56k_core* cpustate, UINT16 value)
+{
+ if (value & 0xf000)
+ logerror("Dsp56k : Attempting to set reserved bits in the PCD. Ignoring.\n");
+
+ /* TODO: Temporary */
+ logerror("Dsp56k : Setting general output port C data to 0x%04x\n", value);
+
+ value = value & 0x0fff;
+ PCD &= ~(0x0fff);
+ PCD |= (value << 0);
+}
+
+void dsp56k_io_reset(dsp56k_core* cpustate)
+{
+ /* The BCR = 0x43ff */
+ RH_bit_set(cpustate, 0);
+ BS_bit_set(cpustate, 1);
+ external_x_wait_states_set(cpustate, 0x1f);
+ external_p_wait_states_set(cpustate, 0x1f);
+}
+
+READ16_HANDLER( program_r )
+{
+ dsp56k_core* cpustate = get_safe_token(&space->device());
+ return cpustate->program_ram[offset];
+}
+
+WRITE16_HANDLER( program_w )
+{
+ dsp56k_core* cpustate = get_safe_token(&space->device());
+ cpustate->program_ram[offset] = data;
+}
+
+/* Work */
+READ16_HANDLER( peripheral_register_r )
+{
+ dsp56k_core* cpustate = get_safe_token(&space->device());
+ // (printf) logerror("Peripheral read 0x%04x\n", O2A(offset));
+
+ switch (O2A(offset))
+ {
+ // Port B Control Register (PBC)
+ case 0xffc0: break;
+
+ // Port C Control Register (PCC)
+ case 0xffc1: break;
+
+ // Port B Data Direction Register (PBDDR)
+ case 0xffc2: break;
+
+ // Port C Data Direction Register (PCDDR)
+ case 0xffc3: break;
+
+ // HCR: Host Control Register
+ case 0xffc4: break;
+
+ // COCR
+ case 0xffc8: break;
+
+ // reserved for test
+ case 0xffc9: break;
+
+ // CRA-SSI0 Control Register A
+ case 0xffd0: break;
+
+ // CRB-SSI0 Control Register B
+ case 0xffd1: break;
+
+ // CRA-SSI1 Control Register A
+ case 0xffd8: break;
+
+ // CRB-SSI1 Control Register B
+ case 0xffd9: break;
+
+ // PLCR
+ case 0xffdc: break;
+
+ // reserved for future use
+ case 0xffdd: break;
+
+ // BCR: Bus Control Register
+ case 0xffde: break;
+
+ // IPR: Interrupt Priority Register
+ case 0xffdf: break;
+
+ // Port B Data Register (PBD)
+ case 0xffe2: break;
+
+ // Port C Data Register (PCD)
+ case 0xffe3: break;
+
+ // HSR: Host Status Register
+ case 0xffe4: break;
+
+ // HTX/HRX: Host TX/RX Register
+ case 0xffe5:
+ // 5-5
+ if (!DSP56K::HRDF_bit(cpustate))
+ return 0xbeef;
+ else
+ {
+ UINT16 value = HRX; // TODO: Maybe not exactly right? Just being safe.
+ DSP56K::HRDF_bit_set(cpustate, 0);
+ return value;
+ }
+ break;
+ // COSR
+ case 0xffe8: break;
+
+ // CRX/CTX
+ case 0xffe9: break;
+
+ // Timer Control Register (TCR)
+ case 0xffec: break;
+
+ // Timer Count Register (TCTR)
+ case 0xffed: break;
+
+ // Timer Compare Register (TCPR)
+ case 0xffee: break;
+
+ // Timer Preload Register (TPR)
+ case 0xffef: break;
+
+ // SR/TSR SSI0 Status Register
+ case 0xfff0: break;
+
+ // TX/RX SSI0 Tx/RX Registers
+ case 0xfff1: break;
+
+ // RSMA0 SSI0 Register
+ case 0xfff2: break;
+
+ // RSMB0 SSI0 Register
+ case 0xfff3: break;
+
+ // TSMA0 SSI0 Register
+ case 0xfff4: break;
+
+ // TSMB0 SSI0 Register
+ case 0xfff5: break;
+
+ // SR/TSR SSI1 Status Register
+ case 0xfff8: break;
+
+ // TX/RX SSI1 TX/RX Registers
+ case 0xfff9: break;
+
+ // RSMA1 SSI1 Register
+ case 0xfffa: break;
+
+ // RSMB1 SSI1 Register
+ case 0xfffb: break;
+
+ // TSMA1 SSI1 Register
+ case 0xfffc: break;
+
+ // TSMB1 SSI1 Register
+ case 0xfffd: break;
+
+ // Reserved for on-chip emulation
+ case 0xffff: break;
+ }
+
+ // Its primary behavior is RAM
+ return cpustate->peripheral_ram[offset];
+}
+
+WRITE16_HANDLER( peripheral_register_w )
+{
+ dsp56k_core* cpustate = get_safe_token(&space->device());
+
+ // Its primary behavior is RAM
+ // COMBINE_DATA(&cpustate->peripheral_ram[offset]);
+
+ // (printf) logerror("Peripheral write 0x%04x = %04x\n", O2A(offset), data);
+
+ // 4-8
+ switch (O2A(offset))
+ {
+ // Port B Control Register (PBC)
+ case 0xffc0:
+ DSP56K::PBC_set(cpustate, data);
+ break;
+
+ // Port C Control Register (PCC)
+ case 0xffc1:
+ DSP56K::PCC_set(cpustate, data);
+ break;
+
+ // Port B Data Direction Register (PBDDR)
+ case 0xffc2:
+ DSP56K::PBDDR_set(cpustate, data);
+ break;
+
+ // Port C Data Direction Register (PCDDR)
+ case 0xffc3:
+ DSP56K::PCDDR_set(cpustate, data);
+ break;
+
+ // HCR: Host Control Register
+ case 0xffc4:
+ DSP56K::HCR_set(cpustate, data);
+ break;
+
+ // COCR
+ case 0xffc8: break;
+
+ // reserved for test
+ case 0xffc9:
+ logerror("DSP56k : Warning write to 0xffc9 reserved for test.\n");
+ break;
+
+ // CRA-SSI0 Control Register A
+ case 0xffd0: break;
+
+ // CRB-SSI0 Control Register B
+ case 0xffd1: break;
+
+ // CRA-SSI1 Control Register A
+ case 0xffd8: break;
+
+ // CRB-SSI1 Control Register B
+ case 0xffd9: break;
+
+ // PLCR
+ case 0xffdc: break;
+
+ // reserved for future use
+ case 0xffdd:
+ logerror("DSP56k : Warning write to 0xffdd reserved for future use.\n");
+ break;
+
+ // BCR: Bus Control Register
+ case 0xffde:
+ DSP56K::BCR_set(cpustate, data);
+ break;
+
+ // IPR: Interrupt Priority Register
+ case 0xffdf:
+ DSP56K::IPR_set(cpustate, data);
+ break;
+
+ // Port B Data Register (PBD)
+ case 0xffe2:
+ DSP56K::PBD_set(cpustate, data);
+ break;
+
+ // Port C Data Register (PCD)
+ case 0xffe3:
+ DSP56K::PCD_set(cpustate, data);
+ break;
+
+ // HSR: Host Status Register
+ case 0xffe4: break;
+
+ // HTX/HRX: Host TX/RX Register
+ case 0xffe5:
+ HTX = data;
+ DSP56K::HTDE_bit_set(cpustate, 0); // 5-5
+ break;
+
+ // COSR
+ case 0xffe8: break;
+
+ // CRX/CTX
+ case 0xffe9: break;
+
+ // Timer Control Register (TCR)
+ case 0xffec: break;
+
+ // Timer Count Register (TCTR)
+ case 0xffed: break;
+
+ // Timer Compare Register (TCPR)
+ case 0xffee: break;
+
+ // Timer Preload Register (TPR)
+ case 0xffef: break;
+
+ // SR/TSR SSI0 Status Register
+ case 0xfff0: break;
+
+ // TX/RX SSI0 Tx/RX Registers
+ case 0xfff1: break;
+
+ // RSMA0 SSI0 Register
+ case 0xfff2: break;
+
+ // RSMB0 SSI0 Register
+ case 0xfff3: break;
+
+ // TSMA0 SSI0 Register
+ case 0xfff4: break;
+
+ // TSMB0 SSI0 Register
+ case 0xfff5: break;
+
+ // SR/TSR SSI1 Status Register
+ case 0xfff8: break;
+
+ // TX/RX SSI1 TX/RX Registers
+ case 0xfff9: break;
+
+ // RSMA1 SSI1 Register
+ case 0xfffa: break;
+
+ // RSMB1 SSI1 Register
+ case 0xfffb: break;
+
+ // TSMA1 SSI1 Register
+ case 0xfffc: break;
+
+ // TSMB1 SSI1 Register
+ case 0xfffd: break;
+
+ // Reserved for on-chip emulation
+ case 0xffff:
+ logerror("DSP56k : Warning write to 0xffff reserved for on-chip emulation.\n");
+ break;
+ }
+}
+
+} // namespace DSP56K
+
+/* These two functions are exposed to the outside world */
+/* They represent the host side of the dsp56k's host interface */
+void dsp56k_host_interface_write(device_t* device, UINT8 offset, UINT8 data)
+{
+ dsp56k_core* cpustate = get_safe_token(device);
+
+ /* Not exactly correct since the bootstrap hack doesn't need this to be true */
+ /*
+ if (!host_interface_active())
+ logerror("Dsp56k : Host interface write called without HI being set active by the PBC.\n");
+ */
+
+ switch (offset)
+ {
+ // Interrupt Control Register (ICR)
+ case 0x00:
+ // HACK
+ if (cpustate->bootstrap_mode == BOOTSTRAP_HI)
+ {
+ // A-4 If they set HF0 while in bootstrap mode, it stops the bootstrap short.
+ if (data & 0x08)
+ {
+ cpustate->bootstrap_mode = BOOTSTRAP_OFF;
+ PC = 0x0000;
+ // TODO: Do we set HF0 then, or let it slide?
+ // TODO: Do I allow it to do an ICR_set(), or intercept it and throw everything away?
+ break;
+ }
+ }
+ DSP56K::ICR_set(cpustate, data);
+ break;
+
+ // Command Vector Register (CVR)
+ case 0x01:
+ DSP56K::CVR_set(cpustate, data);
+ break;
+
+ // Interrupt status register (ISR) - Read only!
+ case 0x02:
+ logerror("DSP56k : Interrupt status register is read only.\n");
+ break;
+
+ // Interrupt vector register (IVR)
+ case 0x03: break;
+
+ // Not used
+ case 0x04:
+ logerror("DSP56k : Address 0x4 on the host side of the host interface is not used.\n");
+ break;
+
+ // Reserved
+ case 0x05: break;
+ logerror("DSP56k : Address 0x5 on the host side of the host interface is reserved.\n");
+ break;
+
+ // Transmit byte register - high byte (TXH)
+ case 0x06:
+ // HACK
+ if (cpustate->bootstrap_mode == BOOTSTRAP_HI)
+ {
+ cpustate->program_ram[cpustate->HI.bootstrap_offset] &= 0x00ff;
+ cpustate->program_ram[cpustate->HI.bootstrap_offset] |= (data << 8);
+ break; /* Probably the right thing to do, given this is a hack */
+ }
+
+ if (DSP56K::TXDE_bit(cpustate)) // 5-5
+ {
+ TXH = data;
+ }
+ break;
+
+ // Transmit byte register - low byte (TXL)
+ case 0x07:
+ // HACK
+ if (cpustate->bootstrap_mode == BOOTSTRAP_HI)
+ {
+ cpustate->program_ram[cpustate->HI.bootstrap_offset] &= 0xff00;
+ cpustate->program_ram[cpustate->HI.bootstrap_offset] |= data;
+ cpustate->HI.bootstrap_offset++;
+
+ if (cpustate->HI.bootstrap_offset == 0x800)
+ {
+ cpustate->bootstrap_mode = BOOTSTRAP_OFF;
+ }
+ break; /* Probably the right thing to do, given this is a hack */
+ }
+
+ if (DSP56K::TXDE_bit(cpustate)) // 5-5
+ {
+ TXL = data;
+ DSP56K::TXDE_bit_set(cpustate, 0);
+ }
+ break;
+
+ default: logerror("DSP56k : dsp56k_host_interface_write called with invalid address 0x%02x.\n", offset);
+ }
+}
+
+UINT8 dsp56k_host_interface_read(device_t* device, UINT8 offset)
+{
+ dsp56k_core* cpustate = get_safe_token(device);
+
+ /* Not exactly correct since the bootstrap hack doesn't need this to be true */
+ /*
+ if (!host_interface_active())
+ logerror("Dsp56k : Host interface write called without HI being set active by the PBC.\n");
+ */
+
+ switch (offset)
+ {
+ // Interrupt Control Register (ICR)
+ case 0x00:
+ return ICR;
+
+ // Command Vector Register (CVR)
+ case 0x01:
+ return CVR;
+
+ // Interrupt status register (ISR)
+ case 0x02:
+ return ISR;
+
+ // Interrupt vector register (IVR)
+ case 0x03:
+ return IVR;
+
+ // Read zeroes
+ case 0x04:
+ return 0x00;
+
+ // Reserved
+ case 0x05:
+ logerror("DSP56k : Address 0x5 on the host side of the host interface is reserved.\n");
+ break;
+
+ // Receive byte register - high byte (RXH)
+ case 0x06:
+ // 5-5
+ if (!DSP56K::RXDF_bit(cpustate))
+ return 0xbf;
+ else
+ return RXH;
+ break;
+
+ // Receive byte register - low byte (RXL)
+ case 0x07:
+ // 5-5
+ if (!DSP56K::RXDF_bit(cpustate))
+ return 0xbf;
+ else
+ {
+ UINT8 value = RXL; // TODO: Maybe not exactly right? I'm just being safe.
+ DSP56K::RXDF_bit_set(cpustate, 0);
+ return value;
+ }
+ break;
+
+ default: logerror("DSP56k : dsp56k_host_interface_read called with invalid address 0x%02x.\n", offset);
+ }
+
+ /* Shouldn't get here */
+ return 0xff;
+}
+
+/* MISC*/
+UINT16 dsp56k_get_peripheral_memory(device_t* device, UINT16 addr)
+{
+ dsp56k_core* cpustate = get_safe_token(device);
+ return cpustate->peripheral_ram[A2O(addr)];
+}
+
+
diff --git a/trunk/src/emu/cpu/dsp56k/dsp56mem.h b/trunk/src/emu/cpu/dsp56k/dsp56mem.h
new file mode 100644
index 00000000000..67509e6e2c5
--- /dev/null
+++ b/trunk/src/emu/cpu/dsp56k/dsp56mem.h
@@ -0,0 +1,245 @@
+#ifndef __DSP56_MEM_H__
+#define __DSP56_MEM_H__
+
+#include "dsp56k.h"
+
+namespace DSP56K
+{
+
+/***************************************************************************
+ MEMORY
+***************************************************************************/
+void mem_reset(dsp56k_core* cpustate);
+
+// Adjusts the documented address to match the offset in peripheral RAM
+#define A2O(a) (a-0xffc0)
+
+// Adjusts the offset in peripheral RAM to match the documented address
+#define O2A(a) (a+0xffc0)
+
+// The memory 'registers'
+#define PBC (cpustate->peripheral_ram[A2O(0xffc0)])
+#define PCC (cpustate->peripheral_ram[A2O(0xffc1)])
+#define PBDDR (cpustate->peripheral_ram[A2O(0xffc2)])
+#define PCDDR (cpustate->peripheral_ram[A2O(0xffc3)])
+#define HCR (cpustate->peripheral_ram[A2O(0xffc4)])
+#define COCR (cpustate->peripheral_ram[A2O(0xffc8)])
+#define CRASSI0 (cpustate->peripheral_ram[A2O(0xffd0)])
+#define CRBSSI0 (cpustate->peripheral_ram[A2O(0xffd1)])
+#define CRASSI1 (cpustate->peripheral_ram[A2O(0xffd8)])
+#define CRBSSI1 (cpustate->peripheral_ram[A2O(0xffd9)])
+#define PLCR (cpustate->peripheral_ram[A2O(0xffdc)])
+#define BCR (cpustate->peripheral_ram[A2O(0xffde)])
+#define IPR (cpustate->peripheral_ram[A2O(0xffdf)])
+#define PBD (cpustate->peripheral_ram[A2O(0xffe2)])
+#define PCD (cpustate->peripheral_ram[A2O(0xffe3)])
+#define HSR (cpustate->peripheral_ram[A2O(0xffe4)])
+#define HTXHRX (cpustate->peripheral_ram[A2O(0xffe5)])
+#define COSR (cpustate->peripheral_ram[A2O(0xffe8)])
+#define CRXCTX (cpustate->peripheral_ram[A2O(0xffe9)])
+#define TCR (cpustate->peripheral_ram[A2O(0xffec)])
+#define TCTR (cpustate->peripheral_ram[A2O(0xffed)])
+#define TCPR (cpustate->peripheral_ram[A2O(0xffee)])
+#define TPR (cpustate->peripheral_ram[A2O(0xffef)])
+#define TSRSSI0 (cpustate->peripheral_ram[A2O(0xfff0)])
+#define TRXSSI0 (cpustate->peripheral_ram[A2O(0xfff1)])
+#define RSMA0 (cpustate->peripheral_ram[A2O(0xfff2)])
+#define RSMB0 (cpustate->peripheral_ram[A2O(0xfff3)])
+#define TSMA0 (cpustate->peripheral_ram[A2O(0xfff4)])
+#define TSMB0 (cpustate->peripheral_ram[A2O(0xfff5)])
+#define TSRSSI1 (cpustate->peripheral_ram[A2O(0xfff8)])
+#define TRXSSI1 (cpustate->peripheral_ram[A2O(0xfff9)])
+#define RSMA1 (cpustate->peripheral_ram[A2O(0xfffa)])
+#define RSMB1 (cpustate->peripheral_ram[A2O(0xfffb)])
+#define TSMA1 (cpustate->peripheral_ram[A2O(0xfffc)])
+#define TSMB1 (cpustate->peripheral_ram[A2O(0xfffd)])
+
+/* Interrupt priority register (IPR) bits */
+void IPR_set(dsp56k_core* cpustate, UINT16 value);
+
+/* A return value of -1 means disabled */
+INT8 irqa_ipl(dsp56k_core* cpustate);
+INT8 irqb_ipl(dsp56k_core* cpustate);
+UINT8 irqa_trigger(dsp56k_core* cpustate);
+UINT8 irqb_trigger(dsp56k_core* cpustate);
+
+INT8 codec_ipl(dsp56k_core* cpustate);
+INT8 host_ipl(dsp56k_core* cpustate);
+INT8 ssi0_ipl(dsp56k_core* cpustate);
+INT8 ssi1_ipl(dsp56k_core* cpustate);
+INT8 tm_ipl(dsp56k_core* cpustate);
+
+
+/***************************************************************************
+ HOST INTERFACE
+***************************************************************************/
+void dsp56k_host_interface_reset(dsp56k_core* cpustate);
+#define HTX (HTXHRX)
+#define HRX (HTXHRX)
+
+#define ICR (cpustate->HI.icr)
+#define CVR (cpustate->HI.cvr)
+#define ISR (cpustate->HI.isr)
+#define IVR (cpustate->HI.ivr)
+#define TXH (cpustate->HI.trxh)
+#define TXL (cpustate->HI.trxl)
+#define RXH (cpustate->HI.trxh)
+#define RXL (cpustate->HI.trxl)
+
+/***************/
+/* DSP56k SIDE */
+/***************/
+/* Host Control Register (HCR) Bits */
+void HCR_set(dsp56k_core* cpustate, UINT16 value);
+
+//UINT16 HF3_bit(dsp56k_core* cpustate); #define hf3BIT ((HCR & 0x0010) != 0)
+//UINT16 HF2_bit(dsp56k_core* cpustate); #define hf2BIT ((HCR & 0x0008) != 0)
+UINT16 HCIE_bit(dsp56k_core* cpustate);
+UINT16 HTIE_bit(dsp56k_core* cpustate);
+UINT16 HRIE_bit(dsp56k_core* cpustate);
+
+void HF3_bit_set(dsp56k_core* cpustate, UINT16 value);
+void HF2_bit_set(dsp56k_core* cpustate, UINT16 value);
+void HCIE_bit_set(dsp56k_core* cpustate, UINT16 value);
+void HTIE_bit_set(dsp56k_core* cpustate, UINT16 value);
+void HRIE_bit_set(dsp56k_core* cpustate, UINT16 value);
+
+/* Host Status Register (HSR) Bits */
+//void HSR_set(dsp56k_core* cpustate, UINT16 value);
+
+//UINT16 DMA_bit(dsp56k_core* cpustate); #define dmaBIT ((HSR & 0x0080) != 0)
+//UINT16 HF1_bit(dsp56k_core* cpustate); #define hf1BIT ((HSR & 0x0010) != 0)
+//UINT16 HF0_bit(dsp56k_core* cpustate); #define hf0BIT ((HSR & 0x0008) != 0)
+//UINT16 HCP_bit(dsp56k_core* cpustate); #define hcpBIT ((HSR & 0x0004) != 0)
+UINT16 HTDE_bit(dsp56k_core* cpustate);
+UINT16 HRDF_bit(dsp56k_core* cpustate);
+
+void DMA_bit_set(dsp56k_core* cpustate, UINT16 value);
+void HF1_bit_set(dsp56k_core* cpustate, UINT16 value);
+void HF0_bit_set(dsp56k_core* cpustate, UINT16 value);
+void HCP_bit_set(dsp56k_core* cpustate, UINT16 value);
+void HTDE_bit_set(dsp56k_core* cpustate, UINT16 value);
+void HRDF_bit_set(dsp56k_core* cpustate, UINT16 value);
+
+/*************/
+/* HOST SIDE */
+/*************/
+/* Interrupt Control Register (ICR) Bits */
+void ICR_set(dsp56k_core* cpustate, UINT8 value);
+
+//UINT8 INIT_bit(dsp56k_core* cpustate); #define x_initBIT ((dsp56k.HI.ICR & 0x0080) != 0)
+//UINT8 HM1_bit(dsp56k_core* cpustate); #define x_hm1BIT ((dsp56k.HI.ICR & 0x0040) != 0)
+//UINT8 HM0_bit(dsp56k_core* cpustate); #define x_hm0BIT ((dsp56k.HI.ICR & 0x0020) != 0)
+//UINT8 HF1_bit_host(dsp56k_core* cpustate); #define x_hf1BIT ((dsp56k.HI.ICR & 0x0010) != 0)
+//UINT8 HF0_bit_host(dsp56k_core* cpustate); #define x_hf0BIT ((dsp56k.HI.ICR & 0x0008) != 0)
+//UINT8 TREQ_bit(dsp56k_core* cpustate); #define x_treqBIT ((dsp56k.HI.ICR & 0x0002) != 0)
+//UINT8 RREQ_bit(dsp56k_core* cpustate); #define x_rreqBIT ((dsp56k.HI.ICR & 0x0001) != 0)
+
+//void INIT_bit_set(dsp56k_core* cpustate, UINT8 value); #define CLEAR_x_initBIT() (dsp56k.HI.ICR &= (~0x0080))
+//void HM1_bit_set(dsp56k_core* cpustate, UINT8 value); #define CLEAR_x_hm1BIT() (dsp56k.HI.ICR &= (~0x0040))
+//void HM0_bit_set(dsp56k_core* cpustate, UINT8 value); #define CLEAR_x_hm0BIT() (dsp56k.HI.ICR &= (~0x0020))
+void HF1_bit_host_set(dsp56k_core* cpustate, UINT8 value);
+void HF0_bit_host_set(dsp56k_core* cpustate, UINT8 value);
+void TREQ_bit_set(dsp56k_core* cpustate, UINT8 value);
+void RREQ_bit_set(dsp56k_core* cpustate, UINT8 value);
+
+/* Command Vector Register (CVR) Bits */
+void CVR_set(dsp56k_core* cpustate, UINT8 value);
+
+//UINT8 HC_bit();
+UINT8 HV_bits(dsp56k_core* cpustate);
+
+void HC_bit_set(dsp56k_core* cpustate, UINT8 value);
+void HV_bits_set(dsp56k_core* cpustate, UINT8 value);
+
+/* Interrupt Status Register (ISR) Bits */
+// void ISR_set(dsp56k_core* cpustate, UINT8 value);
+
+//UINT8 HREQ_bit(dsp56k_core* cpustate); #define x_hreqBIT ((dsp56k.HI.ISR & 0x0080) != 0)
+//UINT8 DMA_bit(dsp56k_core* cpustate); #define x_dmaBIT ((dsp56k.HI.ISR & 0x0040) != 0)
+//UINT8 HF3_bit_host(dsp56k_core* cpustate); #define x_hf3BIT ((dsp56k.HI.ISR & 0x0010) != 0)
+//UINT8 HF2_bit_host(dsp56k_core* cpustate); #define x_hf2BIT ((dsp56k.HI.ISR & 0x0008) != 0)
+//UINT8 TRDY_bit(dsp56k_core* cpustate); #define x_trdyBIT ((dsp56k.HI.ISR & 0x0004) != 0)
+UINT8 TXDE_bit(dsp56k_core* cpustate);
+UINT8 RXDF_bit(dsp56k_core* cpustate);
+
+//void HREQ_bit_set(dsp56k_core* cpustate, UINT8 value); #define CLEAR_x_hreqBIT() (dsp56k.HI.ISR &= (~0x0080))
+//void DMA_bit_set(dsp56k_core* cpustate, UINT8 value); #define CLEAR_x_dmaBIT() (dsp56k.HI.ISR &= (~0x0040))
+void HF3_bit_host_set(dsp56k_core* cpustate, UINT8 value);
+void HF2_bit_host_set(dsp56k_core* cpustate, UINT8 value);
+//void TRDY_bit_set(dsp56k_core* cpustate, UINT8 value); #define CLEAR_x_trdyBIT() (dsp56k.HI.ISR &= (~0x0004))
+void TXDE_bit_set(dsp56k_core* cpustate, UINT8 value);
+void RXDF_bit_set(dsp56k_core* cpustate, UINT8 value);
+
+/* Interrupt Vector Register (IVR) Bits */
+//void IVR_set(dsp56k_core* cpustate, UINT8 value);
+
+//UINT8 IV7_bit(dsp56k_core* cpustate);
+//UINT8 IV6_bit(dsp56k_core* cpustate);
+//UINT8 IV5_bit(dsp56k_core* cpustate);
+//UINT8 IV4_bit(dsp56k_core* cpustate);
+//UINT8 IV3_bit(dsp56k_core* cpustate);
+//UINT8 IV2_bit(dsp56k_core* cpustate);
+//UINT8 IV1_bit(dsp56k_core* cpustate);
+//UINT8 IV0_bit(dsp56k_core* cpustate);
+
+//void IV7_bit_set(dsp56k_core* cpustate, UINT8 value);
+//void IV6_bit_set(dsp56k_core* cpustate, UINT8 value);
+//void IV5_bit_set(dsp56k_core* cpustate, UINT8 value);
+//void IV4_bit_set(dsp56k_core* cpustate, UINT8 value);
+//void IV3_bit_set(dsp56k_core* cpustate, UINT8 value);
+//void IV2_bit_set(dsp56k_core* cpustate, UINT8 value);
+//void IV1_bit_set(dsp56k_core* cpustate, UINT8 value);
+//void IV0_bit_set(dsp56k_core* cpustate, UINT8 value);
+
+
+/* PROTOTYPES */
+void dsp56k_host_interface_HTX_to_host(dsp56k_core* cpustate);
+void dsp56k_host_interface_host_to_HTX(dsp56k_core* cpustate);
+
+
+/***************************************************************************
+ I/O INTERFACE
+***************************************************************************/
+void dsp56k_io_reset(dsp56k_core* cpustate);
+
+/* Port A Bus Control Register (BCR) */
+void BCR_set(dsp56k_core* cpustate, UINT16 value);
+
+//UINT16 RH_bit(dsp56k_core* cpustate);
+//UINT16 BS_bit(dsp56k_core* cpustate);
+//UINT16 external_x_wait_states(dsp56k_core* cpustate);
+//UINT16 external_p_wait_states(dsp56k_core* cpustate);
+
+void RH_bit_set(dsp56k_core* cpustate, UINT16 value);
+void BS_bit_set(dsp56k_core* cpustate, UINT16 value);
+void external_x_wait_states_set(dsp56k_core* cpustate, UINT16 value);
+void external_p_wait_states_set(dsp56k_core* cpustate, UINT16 value);
+
+/* Port B Control Register (PBC) */
+void PBC_set(dsp56k_core* cpustate, UINT16 value);
+//int host_interface_active(dsp56k_core* cpustate);
+
+/* Port B Data Direction Register (PBDDR) */
+void PBDDR_set(dsp56k_core* cpustate, UINT16 value);
+
+/* Port B Data Register (PBD) */
+void PBD_set(dsp56k_core* cpustate, UINT16 value);
+
+/* Port C Control Register (PCC) */
+void PCC_set(dsp56k_core* cpustate, UINT16 value);
+
+/* Port C Data Direction Register (PCDDR) */
+void PCDDR_set(dsp56k_core* cpustate, UINT16 value);
+
+/* Port C Dtaa Register (PCD) */
+void PCD_set(dsp56k_core* cpustate, UINT16 value);
+
+READ16_HANDLER( peripheral_register_r );
+WRITE16_HANDLER( peripheral_register_w );
+READ16_HANDLER( program_r );
+WRITE16_HANDLER( program_w );
+
+} // namespace DSP56K
+
+#endif
diff --git a/trunk/src/emu/cpu/dsp56k/dsp56ops.c b/trunk/src/emu/cpu/dsp56k/dsp56ops.c
new file mode 100644
index 00000000000..a57966ec3b2
--- /dev/null
+++ b/trunk/src/emu/cpu/dsp56k/dsp56ops.c
@@ -0,0 +1,4922 @@
+/***************************************************************************
+
+ dsp56ops.c
+ Core implementation for the portable Motorola/Freescale DSP56k emulator.
+ Written by Andrew Gardner
+
+***************************************************************************/
+
+/* NOTES For register setting:
+ FM.3-4 : When A2 or B2 is read, the register contents occupy the low-order portion
+ (bits 7-0) of the word; the high-order portion (bits 16-8) is sign-extended. When A2 or B2
+ is written, the register receives the low-order portion of the word; the high-order portion is not used
+ : ...much more!
+ : ...shifter/limiter/overflow notes too.
+
+*/
+
+/*
+TODO:
+ - 0x01ee: should this move sign extend? otherwise the test-against-minus means nothing.
+ - Restore only the proper bits upon loop termination!
+ - BFCLR has some errata in the docs that may need to be applied.
+*/
+
+/************************/
+/* Datatypes and macros */
+/************************/
+enum addSubOpType { OP_ADD,
+ OP_SUB,
+ OP_OTHER };
+
+enum dataType { DT_BYTE,
+ DT_WORD,
+ DT_DOUBLE_WORD,
+ DT_LONG_WORD };
+
+struct _typed_pointer
+{
+ void* addr;
+ char data_type;
+};
+typedef struct _typed_pointer typed_pointer;
+
+//#define ADDRESS(X) (X<<1)
+#define BITS(CUR,MASK) (Dsp56kOpMask(CUR,MASK))
+
+/*********************/
+/* Opcode prototypes */
+/*********************/
+static size_t dsp56k_op_addsub_2 (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles);
+static size_t dsp56k_op_mac_1 (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles);
+static size_t dsp56k_op_macr_1 (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles);
+static size_t dsp56k_op_move_1 (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles);
+static size_t dsp56k_op_mpy_1 (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles);
+static size_t dsp56k_op_mpyr_1 (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles);
+static size_t dsp56k_op_tfr_2 (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles);
+static size_t dsp56k_op_mpy_2 (dsp56k_core* cpustate, const UINT16 op_byte, UINT8* cycles);
+static size_t dsp56k_op_mac_2 (dsp56k_core* cpustate, const UINT16 op_byte, UINT8* cycles);
+static size_t dsp56k_op_clr (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles);
+static size_t dsp56k_op_add (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles);
+static size_t dsp56k_op_move (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles);
+static size_t dsp56k_op_tfr (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles);
+static size_t dsp56k_op_rnd (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles);
+static size_t dsp56k_op_tst (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles);
+static size_t dsp56k_op_inc (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles);
+static size_t dsp56k_op_inc24 (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles);
+static size_t dsp56k_op_or (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles);
+static size_t dsp56k_op_asr (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles);
+static size_t dsp56k_op_asl (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles);
+static size_t dsp56k_op_lsr (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles);
+static size_t dsp56k_op_lsl (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles);
+static size_t dsp56k_op_eor (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles);
+static size_t dsp56k_op_subl (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles);
+static size_t dsp56k_op_sub (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles);
+static size_t dsp56k_op_clr24 (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles);
+static size_t dsp56k_op_sbc (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles);
+static size_t dsp56k_op_cmp (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles);
+static size_t dsp56k_op_neg (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles);
+static size_t dsp56k_op_not (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles);
+static size_t dsp56k_op_dec (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles);
+static size_t dsp56k_op_dec24 (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles);
+static size_t dsp56k_op_and (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles);
+static size_t dsp56k_op_abs (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles);
+static size_t dsp56k_op_ror (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles);
+static size_t dsp56k_op_rol (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles);
+static size_t dsp56k_op_cmpm (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles);
+static size_t dsp56k_op_mpy (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles);
+static size_t dsp56k_op_mpyr (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles);
+static size_t dsp56k_op_mac (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles);
+static size_t dsp56k_op_macr (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles);
+static size_t dsp56k_op_adc (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_andi (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_asl4 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_asr4 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_asr16 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_bfop (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles);
+static size_t dsp56k_op_bfop_1 (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles);
+static size_t dsp56k_op_bfop_2 (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles);
+static size_t dsp56k_op_bcc (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles);
+static size_t dsp56k_op_bcc_1 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_bcc_2 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_bra (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles);
+static size_t dsp56k_op_bra_1 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_bra_2 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_brkcc (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_bscc (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles);
+static size_t dsp56k_op_bscc_1 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_bsr (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles);
+static size_t dsp56k_op_bsr_1 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_chkaau (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_debug (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_debugcc (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_div (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_dmac (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_do (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles);
+static size_t dsp56k_op_do_1 (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles);
+static size_t dsp56k_op_do_2 (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles);
+static size_t dsp56k_op_doforever(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles);
+static size_t dsp56k_op_enddo (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_ext (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_illegal (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_imac (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_impy (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_jcc (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles);
+static size_t dsp56k_op_jcc_1 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_jmp (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles);
+static size_t dsp56k_op_jmp_1 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_jscc (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles);
+static size_t dsp56k_op_jscc_1 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_jsr (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles);
+static size_t dsp56k_op_jsr_1 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_jsr_2 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_lea (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_lea_1 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_macsuuu (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_move_2 (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles);
+static size_t dsp56k_op_movec (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_movec_1 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_movec_2 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_movec_3 (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles);
+static size_t dsp56k_op_movec_4 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_movec_5 (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles);
+static size_t dsp56k_op_movei (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_movem (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_movem_1 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_movem_2 (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles);
+static size_t dsp56k_op_movep (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_movep_1 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_moves (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_mpysuuu (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_negc (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_nop (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_norm (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_ori (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_rep (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_rep_1 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_rep_2 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_repcc (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_reset (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_rti (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_rts (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_stop (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_swap (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_swi (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_tcc (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_tfr2 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_tfr3 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_tst2 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_wait (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+static size_t dsp56k_op_zero (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles);
+
+
+static void execute_register_to_register_data_move(dsp56k_core* cpustate, const UINT16 op, typed_pointer* d_register, UINT64* prev_accum_value);
+static void execute_address_register_update(dsp56k_core* cpustate, const UINT16 op, typed_pointer* d_register, UINT64* prev_accum_value);
+static void execute_x_memory_data_move (dsp56k_core* cpustate, const UINT16 op, typed_pointer* d_register, UINT64* prev_accum_value);
+static void execute_x_memory_data_move2(dsp56k_core* cpustate, const UINT16 op, typed_pointer* d_register);
+static void execute_dual_x_memory_data_read(dsp56k_core* cpustate, const UINT16 op, typed_pointer* d_register);
+static void execute_x_memory_data_move_with_short_displacement(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2);
+
+static UINT16 decode_BBB_bitmask(dsp56k_core* cpustate, UINT16 BBB, UINT16 *iVal);
+static int decode_cccc_table(dsp56k_core* cpustate, UINT16 cccc);
+static void decode_DDDDD_table(dsp56k_core* cpustate, UINT16 DDDDD, typed_pointer* ret);
+static void decode_DD_table(dsp56k_core* cpustate, UINT16 DD, typed_pointer* ret);
+static void decode_DDF_table(dsp56k_core* cpustate, UINT16 DD, UINT16 F, typed_pointer* src_ret, typed_pointer* dst_ret);
+static void decode_F_table(dsp56k_core* cpustate, UINT16 F, typed_pointer* ret);
+static void decode_h0hF_table(dsp56k_core* cpustate, UINT16 h0h, UINT16 F, typed_pointer* src_ret, typed_pointer* dst_ret);
+static void decode_HH_table(dsp56k_core* cpustate, UINT16 HH, typed_pointer* ret);
+static void decode_HHH_table(dsp56k_core* cpustate, UINT16 HHH, typed_pointer* ret);
+static void decode_IIII_table(dsp56k_core* cpustate, UINT16 IIII, typed_pointer* src_ret, typed_pointer* dst_ret, void* working);
+static void decode_JJJF_table(dsp56k_core* cpustate, UINT16 JJJ, UINT16 F, typed_pointer* src_ret, typed_pointer* dst_ret);
+static void decode_JJF_table(dsp56k_core* cpustate, UINT16 JJ, UINT16 F, typed_pointer* src_ret, typed_pointer* dst_ret);
+static void decode_JF_table(dsp56k_core* cpustate, UINT16 JJ, UINT16 F, typed_pointer* src_ret, typed_pointer* dst_ret);
+static void decode_KKK_table(dsp56k_core* cpustate, UINT16 KKK, typed_pointer* dst_ret1, typed_pointer* dst_ret2, void* working);
+static void decode_QQF_table(dsp56k_core* cpustate, UINT16 QQ, UINT16 F, void **S1, void **S2, void **D);
+static void decode_QQF_special_table(dsp56k_core* cpustate, UINT16 QQ, UINT16 F, void **S1, void **S2, void **D);
+static void decode_QQQF_table(dsp56k_core* cpustate, UINT16 QQQ, UINT16 F, void **S1, void **S2, void **D);
+static void decode_RR_table(dsp56k_core* cpustate, UINT16 RR, typed_pointer* ret);
+static void decode_TT_table(dsp56k_core* cpustate, UINT16 TT, typed_pointer* ret);
+static void decode_uuuuF_table(dsp56k_core* cpustate, UINT16 uuuu, UINT16 F, UINT8 add_sub_other, typed_pointer* src_ret, typed_pointer* dst_ret);
+static void decode_Z_table(dsp56k_core* cpustate, UINT16 Z, typed_pointer* ret);
+
+static void execute_m_table(dsp56k_core* cpustate, int x, UINT16 m);
+static void execute_mm_table(dsp56k_core* cpustate, UINT16 rnum, UINT16 mm);
+static void execute_MM_table(dsp56k_core* cpustate, UINT16 rnum, UINT16 MM);
+static UINT16 execute_q_table(dsp56k_core* cpustate, int RR, UINT16 q);
+static void execute_z_table(dsp56k_core* cpustate, int RR, UINT16 z);
+
+static UINT16 assemble_address_from_Pppppp_table(dsp56k_core* cpustate, UINT16 P, UINT16 ppppp);
+static UINT16 assemble_address_from_IO_short_address(dsp56k_core* cpustate, UINT16 pp);
+static UINT16 assemble_address_from_6bit_signed_relative_short_address(dsp56k_core* cpustate, UINT16 srs);
+
+static void dsp56k_process_loop(dsp56k_core* cpustate);
+static void dsp56k_process_rep(dsp56k_core* cpustate, size_t repSize);
+
+
+
+/********************/
+/* Helper Functions */
+/********************/
+static UINT16 Dsp56kOpMask(UINT16 op, UINT16 mask);
+
+/* These arguments are written source->destination to fall in line with the processor's paradigm. */
+static void SetDestinationValue(typed_pointer source, typed_pointer dest);
+
+static void SetDataMemoryValue(dsp56k_core* cpustate, typed_pointer source, UINT32 destinationAddr);
+static void SetProgramMemoryValue(dsp56k_core* cpustate, typed_pointer source, UINT32 destinationAddr);
+
+
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
+
+static void execute_one(dsp56k_core* cpustate)
+{
+ UINT16 op;
+ UINT16 op2;
+ size_t size = 0x1337;
+ UINT8 cycle_count = 0;
+
+ /* For MAME */
+ cpustate->op = ROPCODE(ADDRESS(PC));
+ debugger_instruction_hook(cpustate->device, PC);
+
+ /* The words we're going to be working with */
+ op = ROPCODE(ADDRESS(PC));
+ op2 = ROPCODE(ADDRESS(PC) + ADDRESS(1));
+
+
+ /* DECODE */
+ /* Dual X Memory Data Read : 011m mKKK .rr. .... : A-142*/
+ if ((op & 0xe000) == 0x6000)
+ {
+ typed_pointer d_register = {NULL, DT_BYTE};
+
+ /* Quote: (MOVE, MAC(R), MPY(R), ADD, SUB, TFR) */
+ UINT16 op_byte = op & 0x00ff;
+
+ /* ADD : 011m mKKK 0rru Fuuu : A-22 */
+ /* SUB : 011m mKKK 0rru Fuuu : A-202 */
+ /* Note: 0x0094 check allows command to drop through to MOVE and TFR */
+ if (((op & 0xe080) == 0x6000) && ((op & 0x0094) != 0x0010))
+ {
+ size = dsp56k_op_addsub_2(cpustate, op_byte, &d_register, &cycle_count);
+ }
+ /* MAC : 011m mKKK 1xx0 F1QQ : A-122 */
+ else if ((op & 0xe094) == 0x6084)
+ {
+ size = dsp56k_op_mac_1(cpustate, op_byte, &d_register, &cycle_count);
+ }
+ /* MACR: 011m mKKK 1--1 F1QQ : A-124 */
+ else if ((op & 0xe094) == 0x6094)
+ {
+ size = dsp56k_op_macr_1(cpustate, op_byte, &d_register, &cycle_count);
+ }
+ /* TFR : 011m mKKK 0rr1 F0DD : A-212 */
+ else if ((op & 0xe094) == 0x6010)
+ {
+ size = dsp56k_op_tfr_2(cpustate, op_byte, &d_register, &cycle_count);
+ }
+ /* MOVE : 011m mKKK 0rr1 0000 : A-128 */
+ else if ((op & 0xe09f) == 0x6010)
+ {
+ /* Note: The opcode encoding : 011x xxxx 0xx1 0000 (move + double memory read)
+ is .identical. to (tfr X0,A + two parallel reads). This sparks the notion
+ that these 'move' opcodes don't actually exist and are just there as
+ documentation. Real-world examples would need to be examined to come
+ to a satisfactory conclusion, but as it stands, tfr will override this
+ move operation. */
+ size = dsp56k_op_move_1(cpustate, op_byte, &d_register, &cycle_count);
+ }
+ /* MPY : 011m mKKK 1xx0 F0QQ : A-160 */
+ else if ((op & 0xe094) == 0x6080)
+ {
+ size = dsp56k_op_mpy_1(cpustate, op_byte, &d_register, &cycle_count);
+ }
+ /* MPYR : 011m mKKK 1--1 F0QQ : A-162 */
+ else if ((op & 0xe094) == 0x6090)
+ {
+ size = dsp56k_op_mpyr_1(cpustate, op_byte, &d_register, &cycle_count);
+ }
+
+ /* Now evaluate the parallel data move */
+ execute_dual_x_memory_data_read(cpustate, op, &d_register);
+ }
+ /* X Memory Data Write and Register Data Move : 0001 011k RRDD .... : A-140 */
+ else if ((op & 0xfe00) == 0x1600)
+ {
+ /* Quote: (MPY or MAC) */
+ UINT16 op_byte = op & 0x00ff;
+
+ /* MPY : 0001 0110 RRDD FQQQ : A-160 */
+ if ((op & 0xff00) == 0x1600)
+ {
+ size = dsp56k_op_mpy_2(cpustate, op_byte, &cycle_count);
+ }
+ /* MAC : 0001 0111 RRDD FQQQ : A-122 */
+ else if ((op & 0xff00) == 0x1700)
+ {
+ size = dsp56k_op_mac_2(cpustate, op_byte, &cycle_count);
+ }
+
+ /* Now evaluate the parallel data move */
+ /* TODO // decode_x_memory_data_write_and_register_data_move(op, parallel_move_str, parallel_move_str2); */
+ logerror("DSP56k: Unemulated Dual X Memory Data And Register Data Move @ 0x%x\n", PC);
+ }
+
+ /* Handle Other parallel types */
+ else
+ {
+ /***************************************/
+ /* 32 General parallel move operations */
+ /***************************************/
+
+ enum pType { kNoParallelDataMove,
+ kRegisterToRegister,
+ kAddressRegister,
+ kXMemoryDataMove,
+ kXMemoryDataMove2,
+ kXMemoryDataMoveWithDisp };
+
+ int parallelType = -1;
+ UINT16 op_byte = 0x0000;
+ typed_pointer d_register = {NULL, DT_BYTE};
+ UINT64 prev_accum_value = U64(0x0000000000000000);
+
+ /* Note: it's important that NPDM comes before RtRDM here */
+ /* No Parallel Data Move : 0100 1010 .... .... : A-131 */
+ if ((op & 0xff00) == 0x4a00)
+ {
+ op_byte = op & 0x00ff;
+ parallelType = kNoParallelDataMove;
+ }
+ /* Register to Register Data Move : 0100 IIII .... .... : A-133 */
+ else if ((op & 0xf000) == 0x4000)
+ {
+ op_byte = op & 0x00ff;
+ parallelType = kRegisterToRegister;
+ }
+ /* Address Register Update : 0011 0zRR .... .... : A-135 */
+ else if ((op & 0xf800) == 0x3000)
+ {
+ op_byte = op & 0x00ff;
+ parallelType = kAddressRegister;
+ }
+ /* X Memory Data Move : 1mRR HHHW .... .... : A-137 */
+ else if ((op & 0x8000) == 0x8000)
+ {
+ op_byte = op & 0x00ff;
+ parallelType = kXMemoryDataMove;
+ }
+ /* X Memory Data Move : 0101 HHHW .... .... : A-137 */
+ else if ((op & 0xf000) == 0x5000)
+ {
+ op_byte = op & 0x00ff;
+ parallelType = kXMemoryDataMove2;
+ }
+ /* X Memory Data Move with short displacement : 0000 0101 BBBB BBBB ---- HHHW .... .... : A-139 */
+ else if ((op & 0xff00) == 0x0500)
+ {
+ /* Now check it against all the other potential collisions */
+ /* This is necessary because "don't care bits" get in the way. */
+ /*
+ MOVE(M) : 0000 0101 BBBB BBBB 0000 001W --0- -HHH : A-152
+ MOVE(C) : 0000 0101 BBBB BBBB 0011 1WDD DDD0 ---- : A-144
+ MOVE : 0000 0101 BBBB BBBB ---- HHHW 0001 0001 : A-128
+ */
+ if (((op2 & 0xfe20) != 0x0200) &&
+ ((op2 & 0xf810) != 0x3800) &&
+ ((op2 & 0x00ff) != 0x0011))
+ {
+ op_byte = op2 & 0x00ff;
+ parallelType = kXMemoryDataMoveWithDisp;
+ }
+ }
+
+
+ if (parallelType != -1)
+ {
+ /* Note: There is much overlap between opcodes down here */
+ /* To this end, certain ops must come before others in the list */
+
+ /* CLR : .... .... 0000 F001 : A-60 */
+ if ((op_byte & 0x00f7) == 0x0001)
+ {
+ size = dsp56k_op_clr(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* ADD : .... .... 0000 FJJJ : A-22 */
+ else if ((op_byte & 0x00f0) == 0x0000)
+ {
+ size = dsp56k_op_add(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+
+
+ /* MOVE : .... .... 0001 0001 : A-128 */
+ else if ((op_byte & 0x00ff) == 0x0011)
+ {
+ size = dsp56k_op_move(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* TFR : .... .... 0001 FJJJ : A-212 */
+ else if ((op_byte & 0x00f0) == 0x0010)
+ {
+ size = dsp56k_op_tfr(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+
+
+ /* RND : .... .... 0010 F000 : A-188 */
+ else if ((op_byte & 0x00f7) == 0x0020)
+ {
+ size = dsp56k_op_rnd(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* TST : .... .... 0010 F001 : A-218 */
+ else if ((op_byte & 0x00f7) == 0x0021)
+ {
+ size = dsp56k_op_tst(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* INC : .... .... 0010 F010 : A-104 */
+ else if ((op_byte & 0x00f7) == 0x0022)
+ {
+ size = dsp56k_op_inc(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* INC24 : .... .... 0010 F011 : A-106 */
+ else if ((op_byte & 0x00f7) == 0x0023)
+ {
+ size = dsp56k_op_inc24(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* OR : .... .... 0010 F1JJ : A-176 */
+ else if ((op_byte & 0x00f4) == 0x0024)
+ {
+ size = dsp56k_op_or(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+
+
+ /* ASR : .... .... 0011 F000 : A-32 */
+ else if ((op_byte & 0x00f7) == 0x0030)
+ {
+ size = dsp56k_op_asr(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* ASL : .... .... 0011 F001 : A-28 */
+ else if ((op_byte & 0x00f7) == 0x0031)
+ {
+ size = dsp56k_op_asl(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* LSR : .... .... 0011 F010 : A-120 */
+ else if ((op_byte & 0x00f7) == 0x0032)
+ {
+ size = dsp56k_op_lsr(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* LSL : .... .... 0011 F011 : A-118 */
+ else if ((op_byte & 0x00f7) == 0x0033)
+ {
+ size = dsp56k_op_lsl(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* EOR : .... .... 0011 F1JJ : A-94 */
+ else if ((op_byte & 0x00f4) == 0x0034)
+ {
+ size = dsp56k_op_eor(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+
+
+ /* SUBL : .... .... 0100 F001 : A-204 */
+ else if ((op_byte & 0x00f7) == 0x0041)
+ {
+ size = dsp56k_op_subl(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* SUB : .... .... 0100 FJJJ : A-202 */
+ else if ((op_byte & 0x00f0) == 0x0040)
+ {
+ size = dsp56k_op_sub(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+
+
+ /* CLR24 : .... .... 0101 F001 : A-62 */
+ else if ((op_byte & 0x00f7) == 0x0051)
+ {
+ size = dsp56k_op_clr24(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* SBC : .... .... 0101 F01J : A-198 */
+ else if ((op_byte & 0x00f6) == 0x0052)
+ {
+ size = dsp56k_op_sbc(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* CMP : .... .... 0101 FJJJ : A-64 */
+ else if ((op_byte & 0x00f0) == 0x0050)
+ {
+ size = dsp56k_op_cmp(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+
+
+ /* NEG : .... .... 0110 F000 : A-166 */
+ else if ((op_byte & 0x00f7) == 0x0060)
+ {
+ size = dsp56k_op_neg(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* NOT : .... .... 0110 F001 : A-174 */
+ else if ((op_byte & 0x00f7) == 0x0061)
+ {
+ size = dsp56k_op_not(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* DEC : .... .... 0110 F010 : A-72 */
+ else if ((op_byte & 0x00f7) == 0x0062)
+ {
+ size = dsp56k_op_dec(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* DEC24 : .... .... 0110 F011 : A-74 */
+ else if ((op_byte & 0x00f7) == 0x0063)
+ {
+ size = dsp56k_op_dec24(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* AND : .... .... 0110 F1JJ : A-24 */
+ else if ((op_byte & 0x00f4) == 0x0064)
+ {
+ size = dsp56k_op_and(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+
+
+ /* ABS : .... .... 0111 F001 : A-18 */
+ if ((op_byte & 0x00f7) == 0x0071)
+ {
+ size = dsp56k_op_abs(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* ROR : .... .... 0111 F010 : A-192 */
+ else if ((op_byte & 0x00f7) == 0x0072)
+ {
+ size = dsp56k_op_ror(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* ROL : .... .... 0111 F011 : A-190 */
+ else if ((op_byte & 0x00f7) == 0x0073)
+ {
+ size = dsp56k_op_rol(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* CMPM : .... .... 0111 FJJJ : A-66 */
+ else if ((op_byte & 0x00f0) == 0x0070)
+ {
+ size = dsp56k_op_cmpm(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+
+
+ /* MPY : .... .... 1k00 FQQQ : A-160 -- CONFIRMED TYPO IN DOCS (HHHH vs HHHW) */
+ else if ((op_byte & 0x00b0) == 0x0080)
+ {
+ size = dsp56k_op_mpy(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* MPYR : .... .... 1k01 FQQQ : A-162 */
+ else if ((op_byte & 0x00b0) == 0x0090)
+ {
+ size = dsp56k_op_mpyr(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* MAC : .... .... 1k10 FQQQ : A-122 */
+ else if ((op_byte & 0x00b0) == 0x00a0)
+ {
+ size = dsp56k_op_mac(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+ /* MACR : .... .... 1k11 FQQQ : A-124 -- DRAMA - rr vs xx (805) */
+ else if ((op_byte & 0x00b0) == 0x00b0)
+ {
+ size = dsp56k_op_macr(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count);
+ }
+
+
+ /* Now evaluate the parallel data move */
+ switch (parallelType)
+ {
+ case kNoParallelDataMove:
+ /* DO NOTHING */
+ break;
+ case kRegisterToRegister:
+ execute_register_to_register_data_move(cpustate, op, &d_register, &prev_accum_value);
+ break;
+ case kAddressRegister:
+ execute_address_register_update(cpustate, op, &d_register, &prev_accum_value);
+ break;
+ case kXMemoryDataMove:
+ execute_x_memory_data_move(cpustate, op, &d_register, &prev_accum_value);
+ break;
+ case kXMemoryDataMove2:
+ execute_x_memory_data_move2(cpustate, op, &d_register);
+ break;
+ case kXMemoryDataMoveWithDisp:
+ execute_x_memory_data_move_with_short_displacement(cpustate, op, op2);
+ size = 2;
+ break;
+ }
+ }
+ }
+
+ /* Drop out if you've already completed your work. */
+ if (size != 0x1337)
+ {
+ PC += size;
+
+ dsp56k_process_loop(cpustate);
+ dsp56k_process_rep(cpustate, size);
+
+ cpustate->icount -= 4; /* Temporarily hard-coded at 4 clocks per opcode */ /* cycle_count */
+ return;
+ }
+
+
+ /******************************/
+ /* Remaining non-parallel ops */
+ /******************************/
+
+ /* ADC : 0001 0101 0000 F01J : A-20 */
+ if ((op & 0xfff6) == 0x1502)
+ {
+ size = dsp56k_op_adc(cpustate, op, &cycle_count);
+ }
+ /* ANDI : 0001 1EE0 iiii iiii : A-26 */
+ /* (MoveP sneaks in here if you don't check 0x0600) */
+ else if (((op & 0xf900) == 0x1800) & ((op & 0x0600) != 0x0000))
+ {
+ size = dsp56k_op_andi(cpustate, op, &cycle_count);
+ }
+ /* ASL4 : 0001 0101 0011 F001 : A-30 */
+ else if ((op & 0xfff7) == 0x1531)
+ {
+ size = dsp56k_op_asl4(cpustate, op, &cycle_count);
+ }
+ /* ASR4 : 0001 0101 0011 F000 : A-34 */
+ else if ((op & 0xfff7) == 0x1530)
+ {
+ size = dsp56k_op_asr4(cpustate, op, &cycle_count);
+ }
+ /* ASR16 : 0001 0101 0111 F000 : A-36 */
+ else if ((op & 0xfff7) == 0x1570)
+ {
+ size = dsp56k_op_asr16(cpustate, op, &cycle_count);
+ }
+ /* BFCHG : 0001 0100 11Pp pppp BBB1 0010 iiii iiii : A-38 */
+ else if (((op & 0xffc0) == 0x14c0) && ((op2 & 0x1f00) == 0x1200))
+ {
+ size = dsp56k_op_bfop(cpustate, op, op2, &cycle_count);
+ }
+ /* BFCHG : 0001 0100 101- --RR BBB1 0010 iiii iiii : A-38 */
+ else if (((op & 0xffe0) == 0x14a0) && ((op2 & 0x1f00) == 0x1200))
+ {
+ size = dsp56k_op_bfop_1(cpustate, op, op2, &cycle_count);
+ }
+ /* BFCHG : 0001 0100 100D DDDD BBB1 0010 iiii iiii : A-38 */
+ else if (((op & 0xffe0) == 0x1480) && ((op2 & 0x1f00) == 0x1200))
+ {
+ size = dsp56k_op_bfop_2(cpustate, op, op2, &cycle_count);
+ }
+ /* BFCLR : 0001 0100 11Pp pppp BBB0 0100 iiii iiii : A-40 */
+ else if (((op & 0xffc0) == 0x14c0) && ((op2 & 0x1f00) == 0x0400))
+ {
+ size = dsp56k_op_bfop(cpustate, op, op2, &cycle_count);
+ }
+ /* BFCLR : 0001 0100 101- --RR BBB0 0100 iiii iiii : A-40 */
+ else if (((op & 0xffe0) == 0x14a0) && ((op2 & 0x1f00) == 0x0400))
+ {
+ size = dsp56k_op_bfop_1(cpustate, op, op2, &cycle_count);
+ }
+ /* BFCLR : 0001 0100 100D DDDD BBB0 0100 iiii iiii : A-40 */
+ else if (((op & 0xffe0) == 0x1480) && ((op2 & 0x1f00) == 0x0400))
+ {
+ size = dsp56k_op_bfop_2(cpustate, op, op2, &cycle_count);
+ }
+ /* BFSET : 0001 0100 11Pp pppp BBB1 1000 iiii iiii : A-42 */
+ else if (((op & 0xffc0) == 0x14c0) && ((op2 & 0x1f00) == 0x1800))
+ {
+ size = dsp56k_op_bfop(cpustate, op, op2, &cycle_count);
+ }
+ /* BFSET : 0001 0100 101- --RR BBB1 1000 iiii iiii : A-42 */
+ else if (((op & 0xffe0) == 0x14a0) && ((op2 & 0x1f00) == 0x1800))
+ {
+ size = dsp56k_op_bfop_1(cpustate, op, op2, &cycle_count);
+ }
+ /* BFSET : 0001 0100 100D DDDD BBB1 1000 iiii iiii : A-42 */
+ else if (((op & 0xffe0) == 0x1480) && ((op2 & 0x1f00) == 0x1800))
+ {
+ size = dsp56k_op_bfop_2(cpustate, op, op2, &cycle_count);
+ }
+ /* BFTSTH : 0001 0100 01Pp pppp BBB1 0000 iiii iiii : A-44 */
+ else if (((op & 0xffc0) == 0x1440) && ((op2 & 0x1f00) == 0x1000))
+ {
+ size = dsp56k_op_bfop(cpustate, op, op2, &cycle_count);
+ }
+ /* BFTSTH : 0001 0100 001- --RR BBB1 0000 iiii iiii : A-44 */
+ else if (((op & 0xffe0) == 0x1420) && ((op2 & 0x1f00) == 0x1000))
+ {
+ size = dsp56k_op_bfop_1(cpustate, op, op2, &cycle_count);
+ }
+ /* BFTSTH : 0001 0100 000D DDDD BBB1 0000 iiii iiii : A-44 */
+ else if (((op & 0xffe0) == 0x1400) && ((op2 & 0x1f00) == 0x1000))
+ {
+ size = dsp56k_op_bfop_2(cpustate, op, op2, &cycle_count);
+ }
+ /* BFTSTL : 0001 0100 01Pp pppp BBB0 0000 iiii iiii : A-46 */
+ else if (((op & 0xffc0) == 0x1440) && ((op2 & 0x1f00) == 0x0000))
+ {
+ size = dsp56k_op_bfop(cpustate, op, op2, &cycle_count);
+ }
+ /* BFTSTL : 0001 0100 001- --RR BBB0 0000 iiii iiii : A-46 */
+ else if (((op & 0xffe0) == 0x1420) && ((op2 & 0x1f00) == 0x0000))
+ {
+ size = dsp56k_op_bfop_1(cpustate, op, op2, &cycle_count);
+ }
+ /* BFTSTL : 0001 0100 000D DDDD BBB0 0000 iiii iiii : A-46 */
+ else if (((op & 0xffe0) == 0x1400) && ((op2 & 0x1f00) == 0x0000))
+ {
+ size = dsp56k_op_bfop_2(cpustate, op, op2, &cycle_count);
+ }
+ /* Bcc : 0000 0111 --11 cccc xxxx xxxx xxxx xxxx : A-48 */
+ else if (((op & 0xff30) == 0x0730) && ((op2 & 0x0000) == 0x0000))
+ {
+ size = dsp56k_op_bcc(cpustate, op, op2, &cycle_count);
+ }
+ /* Bcc : 0010 11cc ccee eeee : A-48 */
+ else if ((op & 0xfc00) == 0x2c00)
+ {
+ size = dsp56k_op_bcc_1(cpustate, op, &cycle_count);
+ }
+ /* Bcc : 0000 0111 RR10 cccc : A-48 */
+ else if ((op & 0xff30) == 0x0720)
+ {
+ size = dsp56k_op_bcc_2(cpustate, op, &cycle_count);
+ }
+ /* BRA : 0000 0001 0011 11-- xxxx xxxx xxxx xxxx : A-50 */
+ else if (((op & 0xfffc) == 0x013c) && ((op2 & 0x0000) == 0x0000))
+ {
+ size = dsp56k_op_bra(cpustate, op, op2, &cycle_count);
+ }
+ /* BRA : 0000 1011 aaaa aaaa : A-50 */
+ else if ((op & 0xff00) == 0x0b00)
+ {
+ size = dsp56k_op_bra_1(cpustate, op, &cycle_count);
+ }
+ /* BRA : 0000 0001 0010 11RR : A-50 */
+ else if ((op & 0xfffc) == 0x012c)
+ {
+ size = dsp56k_op_bra_2(cpustate, op, &cycle_count);
+ }
+ /* BRKc : 0000 0001 0001 cccc : A-52 */
+ else if ((op & 0xfff0) == 0x0110)
+ {
+ size = dsp56k_op_brkcc(cpustate, op, &cycle_count);
+ }
+ /* BScc : 0000 0111 --01 cccc xxxx xxxx xxxx xxxx : A-54 */
+ else if (((op & 0xff30) == 0x0710) && ((op2 & 0x0000) == 0x0000))
+ {
+ size = dsp56k_op_bscc(cpustate, op, op2, &cycle_count);
+ }
+ /* BScc : 0000 0111 RR00 cccc : A-54 */
+ else if ((op & 0xff30) == 0x0700)
+ {
+ size = dsp56k_op_bscc_1(cpustate, op, &cycle_count);
+ }
+ /* BSR : 0000 0001 0011 10-- xxxx xxxx xxxx xxxx : A-56 */
+ else if (((op & 0xfffc) == 0x0138) && ((op2 & 0x0000) == 0x0000))
+ {
+ size = dsp56k_op_bsr(cpustate, op, op2, &cycle_count);
+ }
+ /* BSR : 0000 0001 0010 10RR : A-56 */
+ else if ((op & 0xfffc) == 0x0128)
+ {
+ size = dsp56k_op_bsr_1(cpustate, op, &cycle_count);
+ }
+ /* CHKAAU : 0000 0000 0000 0100 : A-58 */
+ else if ((op & 0xffff) == 0x0004)
+ {
+ size = dsp56k_op_chkaau(cpustate, op, &cycle_count);
+ }
+ /* DEBUG : 0000 0000 0000 0001 : A-68 */
+ else if ((op & 0xffff) == 0x0001)
+ {
+ size = dsp56k_op_debug(cpustate, op, &cycle_count);
+ }
+ /* DEBUGcc : 0000 0000 0101 cccc : A-70 */
+ else if ((op & 0xfff0) == 0x0050)
+ {
+ size = dsp56k_op_debugcc(cpustate, op, &cycle_count);
+ }
+ /* DIV : 0001 0101 0--0 F1DD : A-76 */
+ else if ((op & 0xff94) == 0x1504)
+ {
+ size = dsp56k_op_div(cpustate, op, &cycle_count);
+ }
+ /* DMAC : 0001 0101 10s1 FsQQ : A-80 */
+ else if ((op & 0xffd0) == 0x1590)
+ {
+ size = dsp56k_op_dmac(cpustate, op, &cycle_count);
+ }
+ /* DO : 0000 0000 110- --RR xxxx xxxx xxxx xxxx : A-82 */
+ else if (((op & 0xffe0) == 0x00c0) && ((op2 & 0x0000) == 0x0000))
+ {
+ size = dsp56k_op_do(cpustate, op, op2, &cycle_count);
+ }
+ /* DO : 0000 1110 iiii iiii xxxx xxxx xxxx xxxx : A-82 */
+ else if (((op & 0xff00) == 0x0e00) && ((op2 & 0x0000) == 0x0000))
+ {
+ size = dsp56k_op_do_1(cpustate, op, op2, &cycle_count);
+ }
+ /* DO : 0000 0100 000D DDDD xxxx xxxx xxxx xxxx : A-82 */
+ else if (((op & 0xffe0) == 0x0400) && ((op2 & 0x0000) == 0x0000))
+ {
+ size = dsp56k_op_do_2(cpustate, op, op2, &cycle_count);
+ }
+ /* DO FOREVER : 0000 0000 0000 0010 xxxx xxxx xxxx xxxx : A-88 */
+ else if (((op & 0xffff) == 0x0002) && ((op2 & 0x0000) == 0x0000))
+ {
+ size = dsp56k_op_doforever(cpustate, op, op2, &cycle_count);
+ }
+ /* ENDDO : 0000 0000 0000 1001 : A-92 */
+ else if ((op & 0xffff) == 0x0009)
+ {
+ size = dsp56k_op_enddo(cpustate, op, &cycle_count);
+ }
+ /* EXT : 0001 0101 0101 F010 : A-96 */
+ else if ((op & 0xfff7) == 0x1552)
+ {
+ size = dsp56k_op_ext(cpustate, op, &cycle_count);
+ }
+ /* ILLEGAL : 0000 0000 0000 1111 : A-98 */
+ else if ((op & 0xffff) == 0x000f)
+ {
+ size = dsp56k_op_illegal(cpustate, op, &cycle_count);
+ }
+ /* IMAC : 0001 0101 1010 FQQQ : A-100 */
+ else if ((op & 0xfff0) == 0x15a0)
+ {
+ size = dsp56k_op_imac(cpustate, op, &cycle_count);
+ }
+ /* IMPY : 0001 0101 1000 FQQQ : A-102 */
+ else if ((op & 0xfff0) == 0x1580)
+ {
+ size = dsp56k_op_impy(cpustate, op, &cycle_count);
+ }
+ /* Jcc : 0000 0110 --11 cccc xxxx xxxx xxxx xxxx : A-108 */
+ else if (((op & 0xff30) == 0x0630) && ((op2 & 0x0000) == 0x0000))
+ {
+ size = dsp56k_op_jcc(cpustate, op, op2, &cycle_count);
+ }
+ /* Jcc : 0000 0110 RR10 cccc : A-108 */
+ else if ((op & 0xff30) == 0x0620 )
+ {
+ size = dsp56k_op_jcc_1(cpustate, op, &cycle_count);
+ }
+ /* JMP : 0000 0001 0011 01-- xxxx xxxx xxxx xxxx : A-110 */
+ else if (((op & 0xfffc) == 0x0134) && ((op2 & 0x0000) == 0x0000))
+ {
+ size = dsp56k_op_jmp(cpustate, op, op2, &cycle_count);
+ }
+ /* JMP : 0000 0001 0010 01RR : A-110 */
+ else if ((op & 0xfffc) == 0x0124)
+ {
+ size = dsp56k_op_jmp_1(cpustate, op, &cycle_count);
+ }
+ /* JScc : 0000 0110 --01 cccc xxxx xxxx xxxx xxxx : A-112 */
+ else if (((op & 0xff30) == 0x0610) && ((op2 & 0x0000) == 0x0000))
+ {
+ size = dsp56k_op_jscc(cpustate, op, op2, &cycle_count);
+ }
+ /* JScc : 0000 0110 RR00 cccc : A-112 */
+ else if ((op & 0xff30) == 0x0600)
+ {
+ size = dsp56k_op_jscc_1(cpustate, op, &cycle_count);
+ }
+ /* JSR : 0000 0001 0011 00-- xxxx xxxx xxxx xxxx : A-114 */
+ else if (((op & 0xfffc) == 0x0130) && ((op2 & 0x0000) == 0x0000))
+ {
+ size = dsp56k_op_jsr(cpustate, op, op2, &cycle_count);
+ }
+ /* JSR : 0000 1010 AAAA AAAA : A-114 */
+ else if ((op & 0xff00) == 0x0a00)
+ {
+ size = dsp56k_op_jsr_1(cpustate, op, &cycle_count);
+ }
+ /* JSR : 0000 0001 0010 00RR : A-114 */
+ else if ((op & 0xfffc) == 0x0120)
+ {
+ size = dsp56k_op_jsr_2(cpustate, op, &cycle_count);
+ }
+ /* LEA : 0000 0001 11TT MMRR : A-116 */
+ else if ((op & 0xffc0) == 0x01c0)
+ {
+ size = dsp56k_op_lea(cpustate, op, &cycle_count);
+ }
+ /* LEA : 0000 0001 10NN MMRR : A-116 */
+ else if ((op & 0xffc0) == 0x0180)
+ {
+ size = dsp56k_op_lea_1(cpustate, op, &cycle_count);
+ }
+ /* MAC(su,uu) : 0001 0101 1110 FsQQ : A-126 */
+ else if ((op & 0xfff0) == 0x15e0)
+ {
+ size = dsp56k_op_macsuuu(cpustate, op, &cycle_count);
+ }
+ /* MOVE : 0000 0101 BBBB BBBB ---- HHHW 0001 0001 : A-128 */
+ else if (((op & 0xff00) == 0x0500) && ((op2 & 0x00ff) == 0x0011))
+ {
+ size = dsp56k_op_move_2(cpustate, op, op2, &cycle_count);
+ }
+ /* MOVE(C) : 0011 1WDD DDD0 MMRR : A-144 */
+ else if ((op & 0xf810) == 0x3800)
+ {
+ size = dsp56k_op_movec(cpustate, op, &cycle_count);
+ }
+ /* MOVE(C) : 0011 1WDD DDD1 q0RR : A-144 */
+ else if ((op & 0xf814) == 0x3810)
+ {
+ size = dsp56k_op_movec_1(cpustate, op, &cycle_count);
+ }
+ /* MOVE(C) : 0011 1WDD DDD1 Z11- : A-144 */
+ else if ((op & 0xf816) == 0x3816)
+ {
+ size = dsp56k_op_movec_2(cpustate, op, &cycle_count);
+ }
+ /* MOVE(C) : 0011 1WDD DDD1 t10- xxxx xxxx xxxx xxxx : A-144 */
+ else if (((op & 0xf816) == 0x3814) && ((op2 & 0x0000) == 0x0000))
+ {
+ size = dsp56k_op_movec_3(cpustate, op, op2, &cycle_count);
+ }
+ /* MOVE(C) : 0010 10dd dddD DDDD : A-144 */
+ else if ((op & 0xfc00) == 0x2800)
+ {
+ size = dsp56k_op_movec_4(cpustate, op, &cycle_count);
+ }
+ /* MOVE(C) : 0000 0101 BBBB BBBB 0011 1WDD DDD0 ---- : A-144 */
+ else if (((op & 0xff00) == 0x0500) && ((op2 & 0xf810) == 0x3800))
+ {
+ size = dsp56k_op_movec_5(cpustate, op, op2, &cycle_count);
+ }
+ /* MOVE(I) : 0010 00DD BBBB BBBB : A-150 */
+ else if ((op & 0xfc00) == 0x2000)
+ {
+ size = dsp56k_op_movei(cpustate, op, &cycle_count);
+ }
+ /* MOVE(M) : 0000 001W RR0M MHHH : A-152 */
+ else if ((op & 0xfe20) == 0x0200)
+ {
+ size = dsp56k_op_movem(cpustate, op, &cycle_count);
+ }
+ /* MOVE(M) : 0000 001W RR11 mmRR : A-152 */
+ else if ((op & 0xfe30) == 0x0230)
+ {
+ size = dsp56k_op_movem_1(cpustate, op, &cycle_count);
+ }
+ /* MOVE(M) : 0000 0101 BBBB BBBB 0000 001W --0- -HHH : A-152 */
+ else if (((op & 0xff00) == 0x0500) && ((op2 & 0xfe20) == 0x0200))
+ {
+ size = dsp56k_op_movem_2(cpustate, op, op2, &cycle_count);
+ }
+ /* MOVE(P) : 0001 100W HH1p pppp : A-156 */
+ else if ((op & 0xfe20) == 0x1820)
+ {
+ size = dsp56k_op_movep(cpustate, op, &cycle_count);
+ }
+ /* MOVE(P) : 0000 110W RRmp pppp : A-156 */
+ else if ((op & 0xfe00) == 0x0c00)
+ {
+ size = dsp56k_op_movep_1(cpustate, op, &cycle_count);
+ }
+ /* MOVE(S) : 0001 100W HH0a aaaa : A-158 */
+ else if ((op & 0xfe20) == 0x1800)
+ {
+ size = dsp56k_op_moves(cpustate, op, &cycle_count);
+ }
+ /* MPY(su,uu) : 0001 0101 1100 FsQQ : A-164 */
+ else if ((op & 0xfff0) == 0x15c0)
+ {
+ size = dsp56k_op_mpysuuu(cpustate, op, &cycle_count);
+ }
+ /* NEGC : 0001 0101 0110 F000 : A-168 */
+ else if ((op & 0xfff7) == 0x1560)
+ {
+ size = dsp56k_op_negc(cpustate, op, &cycle_count);
+ }
+ /* NOP : 0000 0000 0000 0000 : A-170 */
+ else if ((op & 0xffff) == 0x0000)
+ {
+ size = dsp56k_op_nop(cpustate, op, &cycle_count);
+ }
+ /* NORM : 0001 0101 0010 F0RR : A-172 */
+ else if ((op & 0xfff4) == 0x1520)
+ {
+ size = dsp56k_op_norm(cpustate, op, &cycle_count);
+ }
+ /* ORI : 0001 1EE1 iiii iiii : A-178 */
+ else if ((op & 0xf900) == 0x1900)
+ {
+ size = dsp56k_op_ori(cpustate, op, &cycle_count);
+ }
+ /* REP : 0000 0000 111- --RR : A-180 */
+ else if ((op & 0xffe0) == 0x00e0)
+ {
+ size = dsp56k_op_rep(cpustate, op, &cycle_count);
+ }
+ /* REP : 0000 1111 iiii iiii : A-180 */
+ else if ((op & 0xff00) == 0x0f00)
+ {
+ size = dsp56k_op_rep_1(cpustate, op, &cycle_count);
+ }
+ /* REP : 0000 0100 001D DDDD : A-180 */
+ else if ((op & 0xffe0) == 0x0420)
+ {
+ size = dsp56k_op_rep_2(cpustate, op, &cycle_count);
+ }
+ /* REPcc : 0000 0001 0101 cccc : A-184 */
+ else if ((op & 0xfff0) == 0x0150)
+ {
+ size = dsp56k_op_repcc(cpustate, op, &cycle_count);
+ }
+ /* RESET : 0000 0000 0000 1000 : A-186 */
+ else if ((op & 0xffff) == 0x0008)
+ {
+ size = dsp56k_op_reset(cpustate, op, &cycle_count);
+ }
+ /* RTI : 0000 0000 0000 0111 : A-194 */
+ else if ((op & 0xffff) == 0x0007)
+ {
+ size = dsp56k_op_rti(cpustate, op, &cycle_count);
+ }
+ /* RTS : 0000 0000 0000 0110 : A-196 */
+ else if ((op & 0xffff) == 0x0006)
+ {
+ size = dsp56k_op_rts(cpustate, op, &cycle_count);
+ }
+ /* STOP : 0000 0000 0000 1010 : A-200 */
+ else if ((op & 0xffff) == 0x000a)
+ {
+ size = dsp56k_op_stop(cpustate, op, &cycle_count);
+ }
+ /* SWAP : 0001 0101 0111 F001 : A-206 */
+ else if ((op & 0xfff7) == 0x1571)
+ {
+ size = dsp56k_op_swap(cpustate, op, &cycle_count);
+ }
+ /* SWI : 0000 0000 0000 0101 : A-208 */
+ else if ((op & 0xffff) == 0x0005)
+ {
+ size = dsp56k_op_swi(cpustate, op, &cycle_count);
+ }
+ /* Tcc : 0001 00cc ccTT Fh0h : A-210 */
+ else if ((op & 0xfc02) == 0x1000)
+ {
+ size = dsp56k_op_tcc(cpustate, op, &cycle_count);
+ }
+ /* TFR(2) : 0001 0101 0000 F00J : A-214 */
+ else if ((op & 0xfff6) == 0x1500)
+ {
+ size = dsp56k_op_tfr2(cpustate, op, &cycle_count);
+ }
+ /* TFR(3) : 0010 01mW RRDD FHHH : A-216 */
+ else if ((op & 0xfc00) == 0x2400)
+ {
+ size = dsp56k_op_tfr3(cpustate, op, &cycle_count);
+ }
+ /* TST(2) : 0001 0101 0001 -1DD : A-220 */
+ else if ((op & 0xfff4) == 0x1514)
+ {
+ size = dsp56k_op_tst2(cpustate, op, &cycle_count);
+ }
+ /* WAIT : 0000 0000 0000 1011 : A-222 */
+ else if ((op & 0xffff) == 0x000b)
+ {
+ size = dsp56k_op_wait(cpustate, op, &cycle_count);
+ }
+ /* ZERO : 0001 0101 0101 F000 : A-224 */
+ else if ((op & 0xfff7) == 0x1550)
+ {
+ size = dsp56k_op_zero(cpustate, op, &cycle_count);
+ }
+
+
+ /* Not recognized? Nudge debugger onto the next word */
+ if (size == 0x1337)
+ {
+ logerror("DSP56k: Unimplemented opcode at 0x%04x : %04x\n", PC, op);
+ size = 1 ; /* Just to get the debugger past the bad opcode */
+ }
+
+ /* Must have been a good opcode */
+ PC += size;
+
+ dsp56k_process_loop(cpustate);
+ dsp56k_process_rep(cpustate, size);
+
+ cpustate->icount -= 4; /* Temporarily hard-coded at 4 clocks per opcode */ /* cycle_count */
+}
+
+
+
+
+/***************************************************************************
+ Opcode implementations
+***************************************************************************/
+
+/*******************************/
+/* 32 Parallel move operations */
+/*******************************/
+
+/* ADD : 011m mKKK 0rru Fuuu : A-22 */
+/* SUB : 011m mKKK 0rru Fuuu : A-202 */
+static size_t dsp56k_op_addsub_2(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles)
+{
+ UINT64 useVal = 0;
+ UINT8 op_type = OP_OTHER;
+ typed_pointer S = {NULL, DT_BYTE};
+ typed_pointer D = {NULL, DT_BYTE};
+
+ decode_uuuuF_table(cpustate, BITS(op_byte,0x0017), BITS(op_byte,0x0008), op_type, &S, &D);
+
+ /* If you gave an invalid operation type, presume it's a nop and move on with the parallel move */
+ if (op_type == OP_OTHER)
+ {
+ d_register->addr = NULL;
+ d_register->data_type = DT_BYTE;
+ cycles += 2;
+ return 1;
+ }
+
+ /* It's a real operation. Get on with it. */
+ switch(S.data_type)
+ {
+ case DT_WORD: useVal = (UINT64)*((UINT16*)S.addr) << 16; break;
+ case DT_DOUBLE_WORD: useVal = (UINT64)*((UINT32*)S.addr); break;
+ case DT_LONG_WORD: useVal = (UINT64)*((UINT64*)S.addr); break;
+ }
+
+ /* Sign-extend word for proper add/sub op */
+ if ((S.data_type == DT_WORD) && useVal & U64(0x0000000080000000))
+ useVal |= U64(0x000000ff00000000);
+
+ /* Operate*/
+ if (op_type == OP_ADD)
+ *((UINT64*)D.addr) += useVal;
+ else if (op_type == OP_SUB)
+ *((UINT64*)D.addr) -= useVal;
+
+ d_register->addr = D.addr;
+ d_register->data_type = D.data_type;
+
+ /* S L E U N Z V C */
+ /* * * * * * * * * */
+ /* TODO S, L, E, U, V, C */
+ if (*((UINT64*)D.addr) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR();
+ if (*((UINT64*)D.addr) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR();
+
+ cycles += 2; /* TODO: + mv oscillator cycles */
+ return 1;
+}
+
+/* MAC : 011m mKKK 1xx0 F1QQ : A-122 */
+static size_t dsp56k_op_mac_1(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles)
+{
+ INT64 opD = 0;
+ INT64 result = 0;
+
+ INT32 s1 = 0;
+ INT32 s2 = 0;
+
+ void* D = NULL;
+ void* S1 = NULL;
+ void* S2 = NULL;
+
+ decode_QQF_table(cpustate, BITS(op_byte,0x0003), BITS(op_byte,0x0008), &S1, &S2, &D);
+
+ /* Cast both values as being signed */
+ s1 = *((INT16*)S1);
+ s2 = *((INT16*)S2);
+
+ /* Fixed-point 2's complement multiplication requires a shift */
+ result = (s1 * s2) << 1;
+
+ /* Sign extend D into a temp variable */
+ opD = (*((UINT64*)D));
+ if (opD & U64(0x0000008000000000))
+ opD |= U64(0xffffff0000000000);
+ else
+ opD &= U64(0x000000ffffffffff);
+
+ /* Accumulate */
+ opD += result;
+
+ /* And out the bits that don't live in the register */
+ opD &= U64(0x000000ffffffffff);
+
+ (*((UINT64*)D)) = (UINT64)opD;
+
+ /* For the parallel move */
+ d_register->addr = D;
+ d_register->data_type = DT_LONG_WORD;
+
+ /* S L E U N Z V C */
+ /* * * * * * * * - */
+ /* TODO: S, L, E, V */
+ if ( *((UINT64*)D) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR();
+ if ((*((UINT64*)D) & U64(0x000000ffffffffff)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR();
+
+ cycles += 2; /* TODO: +mv oscillator cycles */
+ return 1;
+}
+
+/* MACR: 011m mKKK 1--1 F1QQ : A-124 */
+static size_t dsp56k_op_macr_1(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * * * * * * - */
+ return 0;
+}
+
+/* MOVE : 011m mKKK 0rr1 0000 : A-128 */
+static size_t dsp56k_op_move_1(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * - - - - - - */
+ return 0;
+}
+
+/* MPY : 011m mKKK 1xx0 F0QQ : A-160 */
+static size_t dsp56k_op_mpy_1(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles)
+{
+ INT64 result = 0;
+
+ INT32 s1 = 0;
+ INT32 s2 = 0;
+
+ void* D = NULL;
+ void* S1 = NULL;
+ void* S2 = NULL;
+
+ decode_QQF_table(cpustate, BITS(op_byte,0x0003), BITS(op_byte,0x0008), &S1, &S2, &D);
+
+ /* Cast both values as being signed */
+ s1 = *((INT16*)S1);
+ s2 = *((INT16*)S2);
+
+ /* Fixed-point 2's complement multiplication requires a shift */
+ result = (s1 * s2) << 1;
+
+ /* And out the bits that don't live in the register */
+ (*((UINT64*)D)) = result & U64(0x000000ffffffffff);
+
+ /* For the parallel move */
+ d_register->addr = D;
+ d_register->data_type = DT_LONG_WORD;
+
+ /* S L E U N Z V C */
+ /* * * * * * * * - */
+ /* TODO: S, L, E, V */
+ if ( *((UINT64*)D) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR();
+ if ((*((UINT64*)D) & U64(0x000000ffffffffff)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR();
+
+ cycles += 2; /* TODO: +mv oscillator cycles */
+ return 1;
+}
+
+/* MPYR : 011m mKKK 1--1 F0QQ : A-162 */
+static size_t dsp56k_op_mpyr_1(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * * * * * * - */
+ return 0;
+}
+
+/* TFR : 011m mKKK 0rr1 F0DD : A-212 */
+static size_t dsp56k_op_tfr_2(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* MPY : 0001 0110 RRDD FQQQ : A-160 */
+static size_t dsp56k_op_mpy_2(dsp56k_core* cpustate, const UINT16 op_byte, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * * * * * * - */
+ return 0;
+}
+
+/* MAC : 0001 0111 RRDD FQQQ : A-122 */
+static size_t dsp56k_op_mac_2(dsp56k_core* cpustate, const UINT16 op_byte, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * * * * * * - */
+ return 0;
+}
+
+/* CLR : .... .... 0000 F001 : A-60 */
+static size_t dsp56k_op_clr(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles)
+{
+ typed_pointer D = {NULL, DT_LONG_WORD};
+ typed_pointer clear = {NULL, DT_LONG_WORD};
+ UINT64 clear_val = U64(0x0000000000000000);
+
+ decode_F_table(cpustate, BITS(op_byte,0x0008), &D);
+
+ *p_accum = *((UINT64*)D.addr);
+
+ clear.addr = &clear_val;
+ clear.data_type = DT_LONG_WORD;
+ SetDestinationValue(clear, D);
+
+ d_register->addr = D.addr;
+ d_register->data_type = D.data_type;
+
+ /* S L E U N Z V C */
+ /* * * * * * * 0 - */
+ /* TODO - S, L */
+ DSP56K_E_CLEAR();
+ DSP56K_U_SET();
+ DSP56K_N_CLEAR();
+ DSP56K_Z_SET();
+ DSP56K_V_CLEAR();
+
+ cycles += 2; /* TODO: + mv oscillator clock cycles */
+ return 1;
+}
+
+/* ADD : .... .... 0000 FJJJ : A-22 */
+static size_t dsp56k_op_add(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles)
+{
+ UINT64 addVal = 0;
+
+ typed_pointer S = {NULL, DT_BYTE};
+ typed_pointer D = {NULL, DT_BYTE};
+ decode_JJJF_table(cpustate, BITS(op_byte,0x0007),BITS(op_byte,0x0008), &S, &D);
+
+ *p_accum = *((UINT64*)D.addr);
+
+ switch(S.data_type)
+ {
+ case DT_WORD: addVal = (UINT64)*((UINT16*)S.addr) << 16; break;
+ case DT_DOUBLE_WORD: addVal = (UINT64)*((UINT32*)S.addr); break;
+ case DT_LONG_WORD: addVal = (UINT64)*((UINT64*)S.addr); break;
+ }
+
+ /* Sign-extend word for proper add/sub op */
+ if ((S.data_type == DT_WORD) && addVal & U64(0x0000000080000000))
+ addVal |= U64(0x000000ff00000000);
+
+ /* Operate*/
+ *((UINT64*)D.addr) += addVal;
+
+ d_register->addr = D.addr;
+ d_register->data_type = D.data_type;
+
+ /* S L E U N Z V C */
+ /* * * * * * * * * */
+ /* TODO S, L, E, U, V, C */
+ if (*((UINT64*)D.addr) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR();
+ if (*((UINT64*)D.addr) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR();
+
+ cycles += 2; /* TODO: + mv oscillator cycles */
+ return 1;
+}
+
+/* MOVE : .... .... 0001 0001 : A-128 */
+static size_t dsp56k_op_move(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles)
+{
+ /* Equivalent to a nop with a parallel move */
+ /* These can't be used later. Hopefully compilers would pick this up. */
+ *p_accum = 0;
+ d_register->addr = NULL;
+ d_register->data_type = DT_BYTE;
+
+ /* S L E U N Z V C */
+ /* * * - - - - - - */
+ /* TODO: S, L */
+ cycles += 2; /* TODO: + mv oscillator cycles */
+ return 1;
+}
+
+/* TFR : .... .... 0001 FJJJ : A-212 */
+static size_t dsp56k_op_tfr(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles)
+{
+ typed_pointer S = {NULL, DT_BYTE};
+ typed_pointer D = {NULL, DT_BYTE};
+
+ decode_JJJF_table(cpustate, BITS(op_byte,0x0007),BITS(op_byte,0x0008), &S, &D);
+
+ *p_accum = *((UINT64*)D.addr);
+
+ SetDestinationValue(S, D);
+
+ d_register->addr = D.addr;
+ d_register->data_type = D.data_type;
+
+ /* S L E U N Z V C */
+ /* * * - - - - - - */
+ /* TODO: S, L */
+ cycles += 2; /* TODO: + mv oscillator cycles */
+ return 1;
+}
+
+/* RND : .... .... 0010 F000 : A-188 */
+static size_t dsp56k_op_rnd(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles)
+{
+ typed_pointer D = {NULL, DT_BYTE};
+
+ decode_F_table(cpustate, BITS(op_byte,0x0008), &D);
+
+ *p_accum = *((UINT64*)D.addr);
+
+ /* WARNING : ROUNDING NOT FULLY IMPLEMENTED YET! */
+ if ((*((UINT64*)D.addr) & U64(0x000000000000ffff)) >= 0x8000)
+ *((UINT64*)D.addr) += U64(0x0000000000010000);
+
+ *((UINT64*)D.addr) = *((UINT64*)D.addr) & U64(0x000000ffffff0000);
+
+ d_register->addr = D.addr;
+ d_register->data_type = D.data_type;
+
+ /* S L E U N Z V C */
+ /* * * * * * * * - */
+ /* TODO: S, L, E, U, V */
+ if ((*((UINT64*)D.addr)) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR();
+ if ((*((UINT64*)D.addr)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR();
+
+ cycles += 2; /* TODO: + mv oscillator clock cycles */
+ return 1;
+}
+
+/* TST : .... .... 0010 F001 : A-218 */
+static size_t dsp56k_op_tst(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles)
+{
+ typed_pointer D = {NULL, DT_LONG_WORD};
+
+ decode_F_table(cpustate, BITS(op_byte,0x0008), &D);
+
+ *p_accum = *((UINT64*)D.addr);
+
+ d_register->addr = D.addr;
+ d_register->data_type = D.data_type;
+
+ /* S L E U N Z V C */
+ /* 0 * * * * * 0 0 */
+ /* TODO: S, L, E, U */
+ if ((*((UINT64*)D.addr)) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR();
+ if ((*((UINT64*)D.addr)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR();
+ DSP56K_V_CLEAR();
+ DSP56K_C_CLEAR();
+
+ cycles += 2; /* TODO: + mv oscillator clock cycles */
+ return 1;
+}
+
+/* INC : .... .... 0010 F010 : A-104 */
+static size_t dsp56k_op_inc(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles)
+{
+ typed_pointer D = {NULL, DT_BYTE};
+ decode_F_table(cpustate, BITS(op_byte,0x0008), &D);
+
+ /* Save some data for the parallel move */
+ *p_accum = *((UINT64*)D.addr);
+
+ /* Make sure the destination is a real 40-bit value */
+ *((UINT64*)D.addr) &= U64(0x000000ffffffffff);
+
+ /* Increment */
+ *((UINT64*)D.addr) = *((UINT64*)D.addr) + 1;
+
+ d_register->addr = D.addr;
+ d_register->data_type = D.data_type;
+
+ /* S L E U N Z V C */
+ /* * * * * * * * * */
+ /* TODO: S, L, E, U */
+ if ( *((UINT64*)D.addr) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR();
+ if ((*((UINT64*)D.addr) & U64(0x000000ffffff0000)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR();
+ if ((*((UINT64*)D.addr) & U64(0xffffff0000000000)) != 0) DSP56K_V_SET(); else DSP56K_V_CLEAR();
+ if ((*((UINT64*)D.addr) & U64(0xffffff0000000000)) != 0) DSP56K_C_SET(); else DSP56K_C_CLEAR();
+
+ cycles += 2; /* TODO: +mv oscillator cycles */
+ return 1;
+}
+
+/* INC24 : .... .... 0010 F011 : A-106 */
+static size_t dsp56k_op_inc24(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles)
+{
+ UINT32 workBits24;
+
+ typed_pointer D = {NULL, DT_BYTE};
+ decode_F_table(cpustate, BITS(op_byte,0x0008), &D);
+
+ /* Save some data for the parallel move */
+ *p_accum = *((UINT64*)D.addr);
+
+ /* TODO: I wonder if workBits24 should be signed? */
+ workBits24 = ((*((UINT64*)D.addr)) & U64(0x000000ffffff0000)) >> 16;
+ workBits24++;
+ //workBits24 &= 0x00ffffff; /* Solves -x issues - TODO: huh? */
+
+ /* Set the D bits with the dec result */
+ *((UINT64*)D.addr) &= U64(0x000000000000ffff);
+ *((UINT64*)D.addr) |= (((UINT64)(workBits24)) << 16);
+
+ d_register->addr = D.addr;
+ d_register->data_type = D.data_type;
+
+ /* S L E U N Z V C */
+ /* * * * * * ? * * */
+ /* TODO: S, L, E, U */
+ if ( *((UINT64*)D.addr) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR();
+ if ((*((UINT64*)D.addr) & U64(0x000000ffffff0000)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR();
+ if ((workBits24 & 0xff000000) != 0) DSP56K_V_SET(); else DSP56K_V_CLEAR();
+ if ((workBits24 & 0xff000000) != 0) DSP56K_C_SET(); else DSP56K_C_CLEAR();
+
+ cycles += 2; /* TODO: + mv oscillator clock cycles */
+ return 1;
+}
+
+/* OR : .... .... 0010 F1JJ : A-176 */
+static size_t dsp56k_op_or(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles)
+{
+ typed_pointer S = {NULL, DT_BYTE};
+ typed_pointer D = {NULL, DT_BYTE};
+
+ decode_JJF_table(cpustate, BITS(op_byte,0x0003), BITS(op_byte,0x0008), &S, &D);
+
+ /* Save some data for the parallel move */
+ *p_accum = *((UINT64*)D.addr);
+
+ /* OR a word of S with A1|B1 */
+ ((PAIR64*)D.addr)->w.h = *((UINT16*)S.addr) | ((PAIR64*)D.addr)->w.h;
+
+ d_register->addr = D.addr;
+ d_register->data_type = D.data_type;
+
+ /* S L E U N Z V C */
+ /* * * - - ? ? 0 - */
+ /* TODO: S, L */
+ if ( *((UINT64*)D.addr) & U64(0x0000000080000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR();
+ if ((*((UINT64*)D.addr) & U64(0x00000000ffff0000)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR();
+ DSP56K_V_CLEAR();
+
+ cycles += 2; /* TODO: + mv oscillator cycles */
+ return 1;
+}
+
+/* ASR : .... .... 0011 F000 : A-32 */
+static size_t dsp56k_op_asr(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles)
+{
+ typed_pointer D = {NULL, DT_BYTE};
+ decode_F_table(cpustate, BITS(op_byte,0x0008), &D);
+
+ *p_accum = *((UINT64*)D.addr);
+
+ *((UINT64*)D.addr) = (*((UINT64*)D.addr)) >> 1;
+
+ /* Make sure the MSB is maintained */
+ if (*p_accum & U64(0x0000008000000000))
+ *((UINT64*)D.addr) |= U64(0x0000008000000000);
+ else
+ *((UINT64*)D.addr) &= (~U64(0x0000008000000000));
+
+ /* For the parallel move */
+ d_register->addr = D.addr;
+ d_register->data_type = D.data_type;
+
+ /* S L E U N Z V C */
+ /* * * * * * * 0 ? */
+ /* TODO: S, L, E, U */
+ if (*((UINT64*)D.addr) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR();
+ if (*((UINT64*)D.addr) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR();
+ DSP56K_V_CLEAR();
+ if (*p_accum & U64(0x0000000000000001)) DSP56K_C_SET(); else DSP56K_C_CLEAR();
+
+ cycles += 2; /* TODO: + mv oscillator cycles */
+ return 1;
+}
+
+/* ASL : .... .... 0011 F001 : A-28 */
+static size_t dsp56k_op_asl(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * * * * * ? ? */
+ /* V - Set if an arithmetic overflow occurs in the 40 bit result. Also set if the most significant
+ bit of the destination operand is changed as a result of the left shift. Cleared otherwise. */
+ /* C - Set if bit 39 of source operand is set. Cleared otherwise. */
+ return 0;
+}
+
+/* LSR : .... .... 0011 F010 : A-120 */
+static size_t dsp56k_op_lsr(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles)
+{
+ typed_pointer D = {NULL, DT_BYTE};
+ decode_F_table(cpustate, BITS(op_byte,0x0008), &D);
+
+ *p_accum = *((UINT64*)D.addr);
+
+ ((PAIR64*)D.addr)->w.h = (((PAIR64*)D.addr)->w.h) >> 1;
+
+ /* Make sure bit 31 gets a 0 */
+ ((PAIR64*)D.addr)->w.h &= (~0x8000);
+
+ /* For the parallel move */
+ d_register->addr = D.addr;
+ d_register->data_type = D.data_type;
+
+ /* S L E U N Z V C */
+ /* * * - - ? ? 0 ? */
+ /* TODO: S, L */
+ DSP56K_N_CLEAR();
+ if (((PAIR64*)D.addr)->w.h == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR();
+ DSP56K_V_CLEAR();
+ if (*p_accum & U64(0x0000000000010000)) DSP56K_C_SET(); else DSP56K_C_CLEAR();
+
+ cycles += 2; /* TODO: + mv oscillator cycles */
+ return 1;
+}
+
+/* LSL : .... .... 0011 F011 : A-118 */
+static size_t dsp56k_op_lsl(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * - - ? ? 0 ? */
+ /* N - Set if bit 31 of the result is set. Cleared otherwise. */
+ /* Z - Set if bits 16-31 of the result are zero. Cleared otherwise. */
+ /* C - Set if bit 31 of the source operand is set. Cleared otherwise. */
+ return 0;
+}
+
+/* EOR : .... .... 0011 F1JJ : A-94 */
+static size_t dsp56k_op_eor(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * - - ? ? 0 - */
+ /* N - Set if bit 31 of the result is set. Cleared otherwise. */
+ /* Z - Set if bits 16-31 of the result are zero. Cleared otherwise. */
+ return 0;
+}
+
+/* SUBL : .... .... 0100 F001 : A-204 */
+static size_t dsp56k_op_subl(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * * * * * ? * */
+ /* V - Set if an arithmetic overflow occurs in the 40 bit result. Also set if the most significant
+ bit of the destination operand is changed as a result of the left shift. Cleared otherwise. */
+ return 0;
+}
+
+/* SUB : .... .... 0100 FJJJ : A-202 */
+static size_t dsp56k_op_sub(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles)
+{
+ UINT64 useVal = 0;
+ typed_pointer S = {NULL, DT_BYTE};
+ typed_pointer D = {NULL, DT_BYTE};
+
+ decode_JJJF_table(cpustate, BITS(op_byte,0x0007), BITS(op_byte,0x0008), &S, &D);
+
+ /* Get on with it. */
+ switch(S.data_type)
+ {
+ case DT_WORD: useVal = (UINT64)*((UINT16*)S.addr) << 16; break;
+ case DT_DOUBLE_WORD: useVal = (UINT64)*((UINT32*)S.addr); break;
+ case DT_LONG_WORD: useVal = (UINT64)*((UINT64*)S.addr); break;
+ }
+
+ /* Sign-extend word for proper sub op */
+ if ((S.data_type == DT_WORD) && useVal & U64(0x0000000080000000))
+ useVal |= U64(0x000000ff00000000);
+
+ /* Make sure they're both real 40-bit values */
+ useVal &= U64(0x000000ffffffffff);
+ *((UINT64*)D.addr) &= U64(0x000000ffffffffff);
+
+ /* Operate*/
+ *((UINT64*)D.addr) -= useVal;
+
+ d_register->addr = D.addr;
+ d_register->data_type = D.data_type;
+
+ /* S L E U N Z V C */
+ /* * * * * * * * * */
+ /* TODO S, L, E, U */
+ if ( *((UINT64*)D.addr) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR();
+ if ( *((UINT64*)D.addr) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR();
+ if ((*((UINT64*)D.addr) & U64(0xffffff0000000000)) != 0) DSP56K_V_SET(); else DSP56K_V_CLEAR();
+ if ((*((UINT64*)D.addr) & U64(0xffffff0000000000)) != 0) DSP56K_C_SET(); else DSP56K_C_CLEAR();
+
+ cycles += 2; /* TODO: + mv oscillator cycles */
+ return 1;
+}
+
+/* CLR24 : .... .... 0101 F001 : A-62 */
+static size_t dsp56k_op_clr24(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * * * * ? 0 - */
+ /* Z - Set if the 24 most significant bits of the destination result are all zeroes. */
+ return 0;
+}
+
+/* SBC : .... .... 0101 F01J : A-198 */
+static size_t dsp56k_op_sbc(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * * * * * * * */
+ return 0;
+}
+
+/* CMP : .... .... 0101 FJJJ : A-64 */
+static size_t dsp56k_op_cmp(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles)
+{
+ UINT64 cmpVal = 0;
+ UINT64 result = 0;
+
+ typed_pointer S = {NULL, DT_BYTE};
+ typed_pointer D = {NULL, DT_BYTE};
+
+ decode_JJJF_table(cpustate, BITS(op_byte,0x0007),BITS(op_byte,0x0008), &S, &D);
+
+ *p_accum = *((UINT64*)D.addr);
+
+ switch(S.data_type)
+ {
+ case DT_WORD: cmpVal = (UINT64)*((UINT16*)S.addr) << 16; break;
+ case DT_DOUBLE_WORD: cmpVal = (UINT64)*((UINT32*)S.addr); break;
+ case DT_LONG_WORD: cmpVal = (UINT64)*((UINT64*)S.addr); break;
+ }
+
+ /* Sign-extend word for proper subtraction op */
+ if ((S.data_type == DT_WORD) && cmpVal & U64(0x0000000080000000))
+ cmpVal |= U64(0x000000ff00000000);
+
+ /* Make sure they're both real 40-bit values */
+ cmpVal &= U64(0x000000ffffffffff);
+ *((UINT64*)D.addr) &= U64(0x000000ffffffffff);
+
+ /* Operate */
+ result = *((UINT64*)D.addr) - cmpVal;
+
+ d_register->addr = D.addr;
+ d_register->data_type = D.data_type;
+
+ /* S L E U N Z V C */
+ /* * * * * * * * * */
+ /* TODO: S, L, E, U */
+ if ( result & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR();
+ if ( result == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR();
+ if ((result & U64(0xffffff0000000000)) != 0) DSP56K_V_SET(); else DSP56K_V_CLEAR();
+ if ((result & U64(0xffffff0000000000)) != 0) DSP56K_C_SET(); else DSP56K_C_CLEAR();
+
+
+ cycles += 2; /* TODO: + mv oscillator clock cycles */
+ return 1;
+}
+
+/* NEG : .... .... 0110 F000 : A-166 */
+static size_t dsp56k_op_neg(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * * * * * * * */
+ return 0;
+}
+
+/* NOT : .... .... 0110 F001 : A-174 */
+static size_t dsp56k_op_not(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles)
+{
+ typed_pointer D = {NULL, DT_BYTE};
+ decode_F_table(cpustate, BITS(op_byte,0x0008), &D);
+
+ *p_accum = *((UINT64*)D.addr);
+
+ /* Invert bits [16:31] of D */
+ ((PAIR64*)D.addr)->w.h = ~(((PAIR64*)D.addr)->w.h);
+
+ d_register->addr = D.addr;
+ d_register->data_type = D.data_type;
+
+ /* S L E U N Z V C */
+ /* * * - - ? ? 0 - */
+ /* TODO: S?, L */
+ if ( *((UINT64*)D.addr) & U64(0x0000000080000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR();
+ if ((*((UINT64*)D.addr) & U64(0x00000000ffff0000)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR();
+ DSP56K_V_CLEAR();
+
+ cycles += 2; /* TODO: + mv oscillator cycles */
+ return 1;
+}
+
+/* DEC : .... .... 0110 F010 : A-72 */
+static size_t dsp56k_op_dec(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * * * * * * * */
+ return 0;
+}
+
+/* DEC24 : .... .... 0110 F011 : A-74 */
+static size_t dsp56k_op_dec24(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles)
+{
+ UINT32 workBits24;
+
+ typed_pointer D = {NULL, DT_BYTE};
+ decode_F_table(cpustate, BITS(op_byte,0x0008), &D);
+
+ /* Save some data for the parallel move */
+ *p_accum = *((UINT64*)D.addr);
+
+ /* TODO: I wonder if workBits24 should be signed? */
+ workBits24 = ((*((UINT64*)D.addr)) & U64(0x000000ffffff0000)) >> 16;
+ workBits24--;
+ workBits24 &= 0x00ffffff; /* Solves -x issues */
+
+ /* Set the D bits with the dec result */
+ *((UINT64*)D.addr) &= U64(0x000000000000ffff);
+ *((UINT64*)D.addr) |= (((UINT64)(workBits24)) << 16);
+
+ d_register->addr = D.addr;
+ d_register->data_type = D.data_type;
+
+ /* S L E U N Z V C */
+ /* * * * * * ? * * */
+ /* TODO: S, L, E, U, V, C */
+ if ( *((UINT64*)D.addr) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR();
+ if ((*((UINT64*)D.addr) & U64(0x000000ffffff0000)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR();
+
+ cycles += 2; /* TODO: + mv oscillator clock cycles */
+ return 1;
+}
+
+/* AND : .... .... 0110 F1JJ : A-24 */
+static size_t dsp56k_op_and(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles)
+{
+ typed_pointer S = {NULL, DT_BYTE};
+ typed_pointer D = {NULL, DT_BYTE};
+
+ decode_JJF_table(cpustate, BITS(op_byte,0x0003), BITS(op_byte,0x0008), &S, &D);
+
+ /* Save some data for the parallel move */
+ *p_accum = *((UINT64*)D.addr);
+
+ /* AND a word of S with A1|B1 */
+ ((PAIR64*)D.addr)->w.h = *((UINT16*)S.addr) & ((PAIR64*)D.addr)->w.h;
+
+ d_register->addr = D.addr;
+ d_register->data_type = D.data_type;
+
+ /* S L E U N Z V C */
+ /* * * - - ? ? 0 - */
+ /* TODO: S, L */
+ if ( *((UINT64*)D.addr) & U64(0x0000000080000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR();
+ if ((*((UINT64*)D.addr) & U64(0x00000000ffff0000)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR();
+ DSP56K_V_CLEAR();
+
+ cycles += 2; /* TODO: + mv oscillator cycles */
+ return 1;
+}
+
+/* ABS : .... .... 0111 F001 : A-18 */
+static size_t dsp56k_op_abs(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles)
+{
+ INT64 opD = 0;
+ typed_pointer D = {NULL, DT_LONG_WORD};
+
+ decode_F_table(cpustate, BITS(op_byte,0x0008), &D);
+
+ *p_accum = *((UINT64*)D.addr);
+
+ /* Sign extend D into a temp variable */
+ opD = *p_accum;
+ if (opD & U64(0x0000008000000000))
+ opD |= U64(0xffffff0000000000);
+ else
+ opD &= U64(0x000000ffffffffff);
+
+ /* Take the absolute value and clean up */
+ opD = (opD < 0) ? -opD : opD;
+ opD &= U64(0x000000ffffffffff);
+
+ /* Reassign */
+ *((UINT64*)D.addr) = opD;
+
+ /* Special overflow case */
+ if ((*p_accum) == U64(0x0000008000000000))
+ *((UINT64*)D.addr) = U64(0x0000007fffffffff);
+
+ /* S L E U N Z V C */
+ /* * * * * * * * - */
+ /* TODO: S, L, E, U */
+ if ( *((UINT64*)D.addr) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR();
+ if ((*((UINT64*)D.addr) & U64(0x000000ffffffffff)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR();
+ if ((*p_accum) == U64(0x0000008000000000)) DSP56K_V_SET(); else DSP56K_V_CLEAR();
+
+ cycles += 2; /* TODO: + mv oscillator clock cycles */
+ return 1;
+}
+
+/* ROR : .... .... 0111 F010 : A-192 */
+static size_t dsp56k_op_ror(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * - - ? ? 0 ? */
+ /* N - Set if bit 31 of the result is set. Cleared otherwise. */
+ /* Z - Set if bits 16-31 of the result are zero. Cleared otherwise. */
+ /* C - Set if bit 16 of the source operand is set. Cleared otherwise. */
+ return 0;
+}
+
+/* ROL : .... .... 0111 F011 : A-190 */
+static size_t dsp56k_op_rol(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * - - ? ? 0 ? */
+ /* N - Set if bit 31 of the result is set. Cleared otherwise. */
+ /* Z - Set if bits 16-31 of the result are zero. Cleared otherwise. */
+ /* C - Set if bit 31 of the source operand is set. Cleared otherwise. */
+ return 0;
+}
+
+/* CMPM : .... .... 0111 FJJJ : A-66 */
+static size_t dsp56k_op_cmpm(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles)
+{
+ INT64 absS;
+ INT64 absD;
+ INT64 absResult;
+
+ typed_pointer S = {NULL, DT_BYTE};
+ typed_pointer D = {NULL, DT_BYTE};
+
+ decode_JJJF_table(cpustate, BITS(op_byte,0x0007),BITS(op_byte,0x0008), &S, &D);
+
+ *p_accum = *((UINT64*)D.addr);
+
+ /* Sign extend and get absolute value of the source */
+ if (S.addr == &A || S.addr == &B)
+ {
+ absS = *((UINT64*)S.addr);
+ if (absS & U64(0x0000008000000000))
+ absS |= U64(0xffffff8000000000);
+ }
+ else
+ {
+ absS = (*((UINT16*)S.addr)) << 16;
+ if (absS & U64(0x0000000080000000))
+ absS |= U64(0xffffffff80000000);
+ }
+ absS = (absS < 0) ? -absS : absS;
+
+ /* Sign extend and get absolute value of the destination */
+ if (D.addr == &A || D.addr == &B)
+ {
+ absD = *((UINT64*)D.addr);
+ if (absD & U64(0x0000008000000000))
+ absD |= U64(0xffffff8000000000);
+ }
+ else
+ {
+ absD = (*((UINT16*)D.addr)) << 16;
+ if (absS & U64(0x0000000080000000))
+ absS |= U64(0xffffffff80000000);
+ }
+ absD = (absD < 0) ? -absD : absD;
+
+ /* Compare */
+ absResult = absD - absS;
+
+ d_register->addr = D.addr;
+ d_register->data_type = D.data_type;
+
+ /* S L E U N Z V C */
+ /* * * * * * * * * */
+ /* TODO: S, L, E, U */
+ if ( (absResult) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR();
+ if (((absResult) & U64(0x000000ffffffffff)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR();
+ if ( (absResult & U64(0xffffff0000000000)) != 0) DSP56K_V_SET(); else DSP56K_V_CLEAR();
+ if ( (absResult & U64(0xffffff0000000000)) != 0) DSP56K_C_SET(); else DSP56K_C_CLEAR();
+
+ cycles += 2; /* TODO: +mv oscillator cycles */
+ return 1;
+}
+
+/* MPY : .... .... 1k00 FQQQ : A-160 -- CONFIRMED TYPO IN DOCS (HHHH vs HHHW) */
+static size_t dsp56k_op_mpy(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles)
+{
+ UINT16 k = 0;
+ INT64 result = 0;
+
+ INT32 s1 = 0;
+ INT32 s2 = 0;
+
+ void* D = NULL;
+ void* S1 = NULL;
+ void* S2 = NULL;
+
+ decode_QQQF_table(cpustate, BITS(op_byte,0x0007), BITS(op_byte,0x0008), &S1, &S2, &D);
+
+ k = BITS(op_byte,0x0040);
+
+ /* Cast both values as being signed */
+ s1 = *((INT16*)S1);
+ s2 = *((INT16*)S2);
+
+ /* Fixed-point 2's complement multiplication requires a shift */
+ result = (s1 * s2) << 1;
+
+ /* Negate the product if necessary */
+ if (k)
+ result *= -1;
+
+ (*((UINT64*)D)) = result & U64(0x000000ffffffffff);
+
+ /* S L E U N Z V C */
+ /* * * * * * * * - */
+ /* TODO: S, L, E, V */
+ if ( *((UINT64*)D) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR();
+ if ((*((UINT64*)D) & U64(0x000000ffffffffff)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR();
+
+ cycles += 2; /* TODO: +mv oscillator cycles */
+ return 1;
+}
+
+/* MPYR : .... .... 1k01 FQQQ : A-162 */
+static size_t dsp56k_op_mpyr(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * * * * * * - */
+ return 0;
+}
+
+/* MAC : .... .... 1k10 FQQQ : A-122 */
+static size_t dsp56k_op_mac(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles)
+{
+ UINT16 k = 0;
+ INT64 opD = 0;
+ INT64 result = 0;
+
+ INT32 s1 = 0;
+ INT32 s2 = 0;
+
+ void* D = NULL;
+ void* S1 = NULL;
+ void* S2 = NULL;
+
+ decode_QQQF_table(cpustate, BITS(op_byte,0x0007), BITS(op_byte,0x0008), &S1, &S2, &D);
+
+ k = BITS(op_byte,0x0040);
+
+ /* Cast both values as being signed */
+ s1 = *((INT16*)S1);
+ s2 = *((INT16*)S2);
+
+ /* Fixed-point 2's complement multiplication requires a shift */
+ result = (s1 * s2) << 1;
+
+ /* Sign extend D into a temp variable */
+ opD = (*((UINT64*)D));
+ if (opD & U64(0x0000008000000000))
+ opD |= U64(0xffffff0000000000);
+ else
+ opD &= U64(0x000000ffffffffff);
+
+ /* Negate if necessary */
+ if (k)
+ result *= -1;
+
+ /* Accumulate */
+ opD += result;
+
+ /* And out the bits that don't live in the register */
+ opD &= U64(0x000000ffffffffff);
+
+ (*((UINT64*)D)) = (UINT64)opD;
+
+ /* For the parallel move */
+ d_register->addr = D;
+ d_register->data_type = DT_LONG_WORD;
+
+ /* S L E U N Z V C */
+ /* * * * * * * * - */
+ /* TODO: S, L, E, V */
+ if ( *((UINT64*)D) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR();
+ if ((*((UINT64*)D) & U64(0x000000ffffffffff)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR();
+
+ cycles += 2; /* TODO: +mv oscillator cycles */
+ return 1;
+}
+
+/* MACR : .... .... 1k11 FQQQ : A-124 -- DRAMA - rr vs xx (805) */
+static size_t dsp56k_op_macr(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles)
+{
+ UINT16 k = 0;
+ INT64 opD = 0;
+ INT64 result = 0;
+
+ INT32 s1 = 0;
+ INT32 s2 = 0;
+
+ void* D = NULL;
+ void* S1 = NULL;
+ void* S2 = NULL;
+
+ decode_QQQF_table(cpustate, BITS(op_byte,0x0007), BITS(op_byte,0x0008), &S1, &S2, &D);
+
+ k = BITS(op_byte,0x0040);
+
+ /* Cast both values as being signed */
+ s1 = *((INT16*)S1);
+ s2 = *((INT16*)S2);
+
+ /* Fixed-point 2's complement multiplication requires a shift */
+ result = (s1 * s2) << 1;
+
+ /* Sign extend D into a temp variable */
+ opD = (*((UINT64*)D));
+ if (opD & U64(0x0000008000000000))
+ opD |= U64(0xffffff0000000000);
+ else
+ opD &= U64(0x000000ffffffffff);
+
+ /* Negate if necessary */
+ if (k)
+ result *= -1;
+
+ /* Accumulate */
+ opD += result;
+
+ /* Round the result */
+ /* WARNING : ROUNDING NOT FULLY IMPLEMENTED YET! */
+ if ((opD & U64(0x000000000000ffff)) >= 0x8000)
+ opD += U64(0x0000000000010000);
+
+ opD &= U64(0x000000ffffff0000);
+
+ /* And out the bits that don't live in the register */
+ opD &= U64(0x000000ffffffffff);
+
+ /* Store the result */
+ (*((UINT64*)D)) = (UINT64)opD;
+
+ /* For the parallel move */
+ d_register->addr = D;
+ d_register->data_type = DT_LONG_WORD;
+
+ /* S L E U N Z V C */
+ /* * * * * * * * - */
+ /* TODO: S, L, E, V */
+ if ( *((UINT64*)D) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR();
+ if ((*((UINT64*)D) & U64(0x000000ffffffffff)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR();
+
+ cycles += 2; /* TODO: +mv oscillator cycles */
+ return 1;
+}
+
+
+/******************************/
+/* Remaining non-parallel ops */
+/******************************/
+
+/* ADC : 0001 0101 0000 F01J : A-20 */
+static size_t dsp56k_op_adc(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* - * * * * * * * */
+ return 0;
+}
+
+/* ANDI : 0001 1EE0 iiii iiii : A-26 */
+static size_t dsp56k_op_andi(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ UINT16 immediate = BITS(op,0x00ff);
+
+ /* There is not currently a good way to refer to CCR or MR. Explicitly decode here. */
+ switch(BITS(op,0x0600))
+ {
+ case 0x01: /* MR */
+ SR &= ((immediate << 8) | 0x00ff);
+ break;
+
+ case 0x02: /* CCR */
+ SR &= (immediate | 0xff00);
+ break;
+
+ case 0x03: /* OMR */
+ OMR &= (UINT8)(immediate);
+ break;
+
+ default:
+ fatalerror("DSP56k - BAD EE value in andi operation") ;
+ }
+
+ /* S L E U N Z V C */
+ /* - ? ? ? ? ? ? ? */
+ /* All ? bits - Cleared if the corresponding bit in the immediate data is cleared and if the operand
+ is the CCR. Not affected otherwise. */
+ cycles += 2;
+ return 1;
+}
+
+/* ASL4 : 0001 0101 0011 F001 : A-30 */
+static size_t dsp56k_op_asl4(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ UINT64 p_accum = 0;
+ typed_pointer D = {NULL, DT_BYTE};
+ decode_F_table(cpustate, BITS(op,0x0008), &D);
+
+ p_accum = *((UINT64*)D.addr);
+
+ *((UINT64*)D.addr) = (*((UINT64*)D.addr)) << 4;
+ *((UINT64*)D.addr) = (*((UINT64*)D.addr)) & U64(0x000000ffffffffff);
+
+ /* S L E U N Z V C */
+ /* - ? * * * * ? ? */
+ /* TODO: L, E, U */
+ /* V - Set if an arithmetic overflow occurs in the 40 bit result. Also set if bit 35 through 39 are
+ not the same. */
+ /* C - Set if bit 36 of source operand is set. Cleared otherwise. */
+ if (*((UINT64*)D.addr) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR();
+ if (*((UINT64*)D.addr) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR();
+ if ( (*((UINT64*)D.addr) & U64(0x000000ff00000000)) != (p_accum & U64(0x000000ff00000000)) ) DSP56K_V_SET(); else DSP56K_V_CLEAR();
+ if (p_accum & U64(0x0000001000000000)) DSP56K_C_SET(); else DSP56K_C_CLEAR();
+
+ cycles += 2;
+ return 1;
+}
+
+/* ASR4 : 0001 0101 0011 F000 : A-34 */
+static size_t dsp56k_op_asr4(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ UINT64 p_accum = 0;
+ typed_pointer D = {NULL, DT_BYTE};
+ decode_F_table(cpustate, BITS(op,0x0008), &D);
+
+ p_accum = *((UINT64*)D.addr);
+
+ *((UINT64*)D.addr) = (*((UINT64*)D.addr)) >> 4;
+ *((UINT64*)D.addr) = (*((UINT64*)D.addr)) & U64(0x000000ffffffffff);
+
+ /* The top 4 bits become the old bit 39 */
+ if (p_accum & U64(0x0000008000000000))
+ *((UINT64*)D.addr) |= U64(0x000000f000000000);
+ else
+ *((UINT64*)D.addr) &= (~U64(0x000000f000000000));
+
+ /* S L E U N Z V C */
+ /* - * * * * * 0 ? */
+ /* TODO: E, U */
+ /* C - Set if bit 3 of source operand is set. Cleared otherwise. */
+ if (*((UINT64*)D.addr) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR();
+ if (*((UINT64*)D.addr) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR();
+ DSP56K_V_CLEAR();
+ if (p_accum & U64(0x0000000000000008)) DSP56K_C_SET(); else DSP56K_C_CLEAR();
+
+ cycles += 2;
+ return 1;
+}
+
+/* ASR16 : 0001 0101 0111 F000 : A-36 */
+static size_t dsp56k_op_asr16(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ UINT64 backupVal;
+ typed_pointer D = {NULL, DT_BYTE};
+
+ decode_F_table(cpustate, BITS(op,0x0008), &D);
+
+ backupVal = *((UINT64*)D.addr);
+
+ *((UINT64*)D.addr) = *((UINT64*)D.addr) >> 16;
+
+ if(backupVal & U64(0x0000008000000000))
+ *((UINT64*)D.addr) |= U64(0x000000ffff000000);
+ else
+ *((UINT64*)D.addr) &= U64(0x0000000000ffffff);
+
+ /* S L E U N Z V C */
+ /* - * * * * * 0 ? */
+ /* TODO: E, U */
+ if (*((UINT64*)D.addr) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR();
+ if (*((UINT64*)D.addr) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR();
+ DSP56K_V_CLEAR();
+ if (backupVal & U64(0x0000000000008000)) DSP56K_C_SET(); else DSP56K_C_CLEAR();
+
+ cycles += 2;
+ return 1;
+}
+
+/* BFCHG : 0001 0100 11Pp pppp BBB1 0010 iiii iiii : A-38 */
+/* BFCLR : 0001 0100 11Pp pppp BBB0 0100 iiii iiii : A-40 */
+/* BFSET : 0001 0100 11Pp pppp BBB1 1000 iiii iiii : A-42 */
+/* BFTSTH : 0001 0100 01Pp pppp BBB1 0000 iiii iiii : A-44 */
+/* BFTSTL : 0001 0100 01Pp pppp BBB0 0000 iiii iiii : A-46 */
+static size_t dsp56k_op_bfop(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles)
+{
+ UINT16 workAddr = 0x0000;
+ UINT16 workingWord = 0x0000;
+ UINT16 previousValue = 0x0000;
+ typed_pointer tempTP = { NULL, DT_BYTE };
+
+ UINT16 iVal = op2 & 0x00ff;
+ decode_BBB_bitmask(cpustate, BITS(op2,0xe000), &iVal);
+
+ workAddr = assemble_address_from_Pppppp_table(cpustate, BITS(op,0x0020), BITS(op,0x001f));
+ previousValue = cpustate->data->read_word(ADDRESS(workAddr));
+ workingWord = previousValue;
+
+ switch(BITS(op2, 0x1f00))
+ {
+ case 0x12: /* BFCHG */
+ workingWord ^= iVal;
+ break;
+ case 0x04: /* BFCLR */
+ workingWord = workingWord & (~iVal);
+ break;
+ case 0x18: /* BFSET */
+ workingWord = workingWord | iVal;
+ break;
+ case 0x10: /* BFTSTH */
+ /* Just the test below */
+ break;
+ case 0x00: /* BFTSTL */
+ /* Just the test below */
+ break;
+ }
+
+ tempTP.addr = &workingWord;
+ tempTP.data_type = DT_WORD;
+ SetDataMemoryValue(cpustate, tempTP, ADDRESS(workAddr));
+
+ /* S L E U N Z V C */
+ /* - * - - - - - ? */
+ /* TODO: L */
+ switch(BITS(op2, 0x1f00))
+ {
+ case 0x12: /* BFCHG */
+ if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break;
+ case 0x04: /* BFCLR */
+ if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break;
+ case 0x18: /* BFSET */
+ if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break;
+ case 0x10: /* BFTSTH */
+ if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break;
+ case 0x00: /* BFTSTL */
+ if ((iVal & previousValue) == 0x0000) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break;
+ }
+
+ cycles += 4; /* TODO: + mvb oscillator clock cycles */
+ return 2;
+}
+
+/* BFCHG : 0001 0100 101- --RR BBB1 0010 iiii iiii : A-38 */
+/* BFCLR : 0001 0100 101- --RR BBB0 0100 iiii iiii : A-40 */
+/* BFSET : 0001 0100 101- --RR BBB1 1000 iiii iiii : A-42 */
+/* BFTSTH : 0001 0100 001- --RR BBB1 0000 iiii iiii : A-44 */
+/* BFTSTL : 0001 0100 001- --RR BBB0 0000 iiii iiii : A-46 */
+static size_t dsp56k_op_bfop_1(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles)
+{
+ UINT16 workAddr = 0x0000;
+ UINT16 workingWord = 0x0000;
+ UINT16 previousValue = 0x0000;
+ typed_pointer R = { NULL, DT_BYTE };
+ typed_pointer tempTP = { NULL, DT_BYTE };
+
+ UINT16 iVal = op2 & 0x00ff;
+ decode_BBB_bitmask(cpustate, BITS(op2,0xe000), &iVal);
+
+ decode_RR_table(cpustate, BITS(op,0x0003), &R);
+
+ workAddr = *((UINT16*)R.addr);
+ previousValue = cpustate->data->read_word(ADDRESS(workAddr));
+ workingWord = previousValue;
+
+ switch(BITS(op2, 0x1f00))
+ {
+ case 0x12: /* BFCHG */
+ workingWord ^= iVal;
+ break;
+ case 0x04: /* BFCLR */
+ workingWord = workingWord & (~iVal);
+ break;
+ case 0x18: /* BFSET */
+ workingWord = workingWord | iVal;
+ break;
+ case 0x10: /* BFTSTH */
+ /* Just the test below */
+ break;
+ case 0x00: /* BFTSTL */
+ /* Just the test below */
+ break;
+ }
+
+ tempTP.addr = &workingWord;
+ tempTP.data_type = DT_WORD;
+ SetDataMemoryValue(cpustate, tempTP, ADDRESS(workAddr));
+
+ /* S L E U N Z V C */
+ /* - * - - - - - ? */
+ /* TODO: L */
+ switch(BITS(op2, 0x1f00))
+ {
+ case 0x12: /* BFCHG */
+ if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break;
+ case 0x04: /* BFCLR */
+ if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break;
+ case 0x18: /* BFSET */
+ if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break;
+ case 0x10: /* BFTSTH */
+ if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break;
+ case 0x00: /* BFTSTL */
+ if ((iVal & previousValue) == 0x0000) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break;
+ }
+
+ cycles += 4; /* TODO: + mvb oscillator clock cycles */
+ return 2;
+}
+
+/* BFCHG : 0001 0100 100D DDDD BBB1 0010 iiii iiii : A-38 */
+/* BFCLR : 0001 0100 100D DDDD BBB0 0100 iiii iiii : A-40 */
+/* BFSET : 0001 0100 100D DDDD BBB1 1000 iiii iiii : A-42 */
+/* BFTSTH : 0001 0100 000D DDDD BBB1 0000 iiii iiii : A-44 */
+/* BFTSTL : 0001 0100 000D DDDD BBB0 0000 iiii iiii : A-46 */
+static size_t dsp56k_op_bfop_2(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles)
+{
+ UINT16 workingWord = 0x0000;
+ UINT16 previousValue = 0x0000;
+
+ UINT16 iVal = op2 & 0x00ff;
+ typed_pointer S = { NULL, DT_BYTE };
+
+ decode_BBB_bitmask(cpustate, BITS(op2,0xe000), &iVal);
+ decode_DDDDD_table(cpustate, BITS(op,0x001f), &S);
+
+ /* A & B are special */
+ if (S.data_type == DT_LONG_WORD)
+ previousValue = ((PAIR64*)S.addr)->w.h;
+ else
+ previousValue = *((UINT16*)S.addr);
+
+ workingWord = previousValue;
+
+ switch(BITS(op2, 0x1f00))
+ {
+ case 0x12: /* BFCHG */
+ workingWord ^= iVal;
+ break;
+ case 0x04: /* BFCLR */
+ workingWord = workingWord & (~iVal);
+ break;
+ case 0x18: /* BFSET */
+ workingWord = workingWord | iVal;
+ break;
+ case 0x10: /* BFTSTH */
+ /* Just the test below */
+ break;
+ case 0x00: /* BFTSTL */
+ /* Just the test below */
+ break;
+ }
+
+ /* Put the data back where it belongs (A & B are special) */
+ if (S.data_type == DT_LONG_WORD)
+ ((PAIR64*)S.addr)->w.h = workingWord;
+ else
+ *((UINT16*)S.addr) = workingWord;
+
+ /* S L E U N Z V C */
+ /* - * - - - - - ? */
+ /* TODO: L */
+ switch(BITS(op2, 0x1f00))
+ {
+ case 0x12: /* BFCHG */
+ if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break;
+ case 0x04: /* BFCLR */
+ if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break;
+ case 0x18: /* BFSET */
+ if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break;
+ case 0x10: /* BFTSTH */
+ if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break;
+ case 0x00: /* BFTSTL */
+ if ((iVal & previousValue) == 0x0000) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break;
+ }
+
+ cycles += 4; /* TODO: + mvb oscillator clock cycles */
+ return 2;
+}
+
+/* Bcc : 0000 0111 --11 cccc xxxx xxxx xxxx xxxx : A-48 */
+static size_t dsp56k_op_bcc(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles)
+{
+ int shouldBranch = decode_cccc_table(cpustate, BITS(op,0x000f));
+
+ if (shouldBranch)
+ {
+ INT16 offset = (INT16)op2;
+
+ PC += 2;
+
+ cpustate->ppc = PC;
+ PC += offset;
+
+ cycles += 4;
+ return 0;
+ }
+ else
+ {
+ cycles += 4;
+ return 2;
+ }
+
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* Bcc : 0010 11cc ccee eeee : A-48 */
+static size_t dsp56k_op_bcc_1(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ int shouldBranch = decode_cccc_table(cpustate, BITS(op,0x03c0));
+
+ if (shouldBranch)
+ {
+ INT16 offset = (INT16)assemble_address_from_6bit_signed_relative_short_address(cpustate, BITS(op,0x003f));
+
+ PC += 1;
+
+ cpustate->ppc = PC;
+ PC += offset;
+
+ cycles += 4;
+ return 0;
+ }
+ else
+ {
+ cycles += 4;
+ return 1;
+ }
+
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* Bcc : 0000 0111 RR10 cccc : A-48 */
+static size_t dsp56k_op_bcc_2(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* BRA : 0000 0001 0011 11-- xxxx xxxx xxxx xxxx : A-50 */
+static size_t dsp56k_op_bra(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* BRA : 0000 1011 aaaa aaaa : A-50 */
+static size_t dsp56k_op_bra_1(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ /* 8 bit immediate, relative offset */
+ INT8 branchOffset = (INT8)BITS(op,0x00ff);
+
+ /* "The PC Contains the address of the next instruction" */
+ PC += 1;
+
+ /* Jump */
+ cpustate->ppc = PC;
+ PC += branchOffset;
+
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ cycles += 4; /* TODO: + jx oscillator clock cycles */
+ return 0;
+}
+
+/* BRA : 0000 0001 0010 11RR : A-50 */
+static size_t dsp56k_op_bra_2(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* BRKcc : 0000 0001 0001 cccc : A-52 */
+static size_t dsp56k_op_brkcc(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ int shouldBreak = decode_cccc_table(cpustate, BITS(op,0x000f));
+
+ if (shouldBreak)
+ {
+ /* TODO: I think this PC = LA thing is off-by-1, but it's working this way because its consistently so */
+ cpustate->ppc = PC;
+ PC = LA;
+
+ SR = SSL; /* TODO: A-83. I believe only the Loop Flag and Forever Flag come back here. */
+ SP--;
+
+ LA = SSH;
+ LC = SSL;
+ SP--;
+
+ cycles += 8;
+ return 0;
+ }
+ else
+ {
+ cycles += 2;
+ return 1;
+ }
+
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* BScc : 0000 0111 --01 cccc xxxx xxxx xxxx xxxx : A-54 */
+static size_t dsp56k_op_bscc(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles)
+{
+ int shouldBranch = decode_cccc_table(cpustate, BITS(op,0x000f));
+
+ if (shouldBranch)
+ {
+ /* The PC Contains the address of the next instruction */
+ PC += 2;
+
+ /* Push */
+ SP++;
+ SSH = PC;
+ SSL = SR;
+
+ /* Change */
+ cpustate->ppc = PC;
+ PC = PC + (INT16)op2;
+
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ cycles += 4; /* TODO: + jx oscillator clock cycles */
+ return 0;
+ }
+
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ cycles += 4; /* TODO: + jx oscillator clock cycles */
+ return 2;
+}
+
+/* BScc : 0000 0111 RR00 cccc : A-54 */
+static size_t dsp56k_op_bscc_1(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* BSR : 0000 0001 0011 10-- xxxx xxxx xxxx xxxx : A-56 */
+static size_t dsp56k_op_bsr(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles)
+{
+ /* The PC Contains the address of the next instruction */
+ PC += 2;
+
+ /* Push */
+ SP++;
+ SSH = PC;
+ SSL = SR;
+
+ /* Change */
+ cpustate->ppc = PC;
+ PC = PC + (INT16)op2;
+
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ cycles += 4; /* TODO: + jx oscillator clock cycles */
+ return 0;
+}
+
+/* BSR : 0000 0001 0010 10RR : A-56 */
+static size_t dsp56k_op_bsr_1(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* CHKAAU : 0000 0000 0000 0100 : A-58 */
+static size_t dsp56k_op_chkaau(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - ? ? ? - */
+ /* V - Set if the result of the last address ALU update performed a modulo wrap. Cleared if
+ result of the last address ALU did not perform a modulo wrap.*/
+ /* Z - Set if the result of the last address ALU update is 0. Cleared if the result of the last
+ address ALU is positive. */
+ /* N - Set if the result of the last address ALU update is negative. Cleared if the result of the
+ last address ALU is positive. */
+ return 0;
+}
+
+/* DEBUG : 0000 0000 0000 0001 : A-68 */
+static size_t dsp56k_op_debug(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* DEBUGcc : 0000 0000 0101 cccc : A-70 */
+static size_t dsp56k_op_debugcc(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* DIV : 0001 0101 0--0 F1DD : A-76 */
+/* WARNING : DOCS SAY THERE IS A PARALLEL MOVE HERE !!! */
+static size_t dsp56k_op_div(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ /* WARNING : THIS DOES NOT WORK. IT DOESN'T EVEN TRY !!! */
+ typed_pointer S = {NULL, DT_BYTE};
+ typed_pointer D = {NULL, DT_BYTE};
+
+ decode_DDF_table(cpustate, BITS(op,0x0003), BITS(op,0x0008), &S, &D);
+
+ /* S L E U N Z V C */
+ /* - * - - - - ? ? */
+ /* V - Set if an arithmetic overflow occurs in the 40 bit result. Also set if the most significantst
+ bit of the destination operand is changed as a result of the left shift. Cleared otherwise. */
+ /* C - Set if bit 39 of the result is cleared. Cleared otherwise. */
+ cycles += 2;
+ return 1;
+}
+
+/* DMAC : 0001 0101 10s1 FsQQ : A-80 */
+static size_t dsp56k_op_dmac(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ UINT8 ss = 0;
+ INT64 result = 0;
+
+ void* D = NULL;
+ void* S1 = NULL;
+ void* S2 = NULL;
+
+ decode_QQF_special_table(cpustate, BITS(op,0x0003), BITS(op,0x0008), &S1, &S2, &D);
+
+ ss = BITS(op,0x0024);
+
+ /* Fixed-point 2's complement multiplication requires a shift */
+ if (ss == 0x00 || ss == 0x01)
+ {
+ /* Signed * Signed */
+ INT32 s1 = ((INT32)(*((UINT16*)S1)));
+ INT32 s2 = ((INT32)(*((UINT16*)S2)));
+ result = ( s1 * s2 ) << 1;
+ }
+ else if (ss == 0x2)
+ {
+ /* Signed * Unsigned */
+ /* WARNING : THERE IS A HUGE CHANCE THIS DOESN'T WORK RIGHT */
+ INT32 s1 = ((INT32)(*((UINT16*)S1)));
+ INT32 s2 = (UINT32)(*((UINT16*)S2));
+ result = ( s1 * s2 ) << 1;
+ }
+ else if (ss == 0x3)
+ {
+ /* Unsigned * Unsigned */
+ UINT32 s1 = (UINT32)(*((UINT16*)S1));
+ UINT32 s2 = (UINT32)(*((UINT16*)S2));
+ result = ( s1 * s2 ) << 1;
+ }
+
+ /* Shift right, then accumulate */
+ (*((UINT64*)D)) = (*((UINT64*)D)) >> 16;
+ (*((UINT64*)D)) += result;
+
+ /* S L E U N Z V C */
+ /* - * * * * * * - */
+ /* TODO: L, E, U, V */
+ if ( *((UINT64*)D) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR();
+ if ((*((UINT64*)D) & U64(0x000000ffffffffff)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR();
+
+ cycles += 2;
+ return 1;
+}
+
+/* DO : 0000 0000 110- --RR xxxx xxxx xxxx xxxx : A-82 */
+static size_t dsp56k_op_do(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* - * - - - - - - */
+ return 0;
+}
+
+/* DO : 0000 1110 iiii iiii xxxx xxxx xxxx xxxx : A-82 */
+static size_t dsp56k_op_do_1(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles)
+{
+ UINT8 retSize = 0;
+ UINT8 iValue = BITS(op,0x00ff);
+
+ /* Don't execute if the loop counter == 0 */
+ if (iValue != 0x00)
+ {
+ /* First instruction cycle */
+ SP++; /* TODO: Should i really inc here first? */
+ SSH = LA;
+ SSL = LC;
+ LC = (UINT16)iValue;
+
+
+ /* Second instruction cycle */
+ SP++; /* TODO: See above */
+ SSH = PC + 2; /* Keep these stack entries in 'word-based-index' space */
+ SSL = SR;
+ LA = PC + 2 + op2; /* TODO: The docs subtract 1 from here? */
+
+
+ /* Third instruction cycle */
+ LF_bit_set(cpustate, 1);
+
+ /* Undocumented, but it must be true to nest Dos in DoForevers */
+ FV_bit_set(cpustate, 0);
+
+
+ /* S L E U N Z V C */
+ /* - * - - - - - - */
+ /* TODO : L */
+
+ cycles += 6; /* TODO: + mv oscillator cycles */
+ retSize = 2;
+ }
+ else
+ {
+ /* Skip over the contents of the loop */
+ cpustate->ppc = PC;
+ PC = PC + 2 + op2;
+
+ cycles += 10; /* TODO: + mv oscillator cycles */
+ retSize = 0;
+ }
+
+ return retSize;
+}
+
+/* DO : 0000 0100 000D DDDD xxxx xxxx xxxx xxxx : A-82 */
+static size_t dsp56k_op_do_2(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles)
+{
+ UINT8 retSize = 0;
+ UINT16 lValue = 0x0000;
+ typed_pointer S = {NULL, DT_BYTE};
+ decode_DDDDD_table(cpustate, BITS(op,0x001f), &S);
+
+ /* TODO: Does not properly shift-limit sources A&B - Fix per the docs. */
+ /* TODO: There are other cases besides A&B this code won't work. */
+ if (S.addr == &A) lValue = *((UINT16*)(&A1));
+ else if (S.addr == &B) lValue = *((UINT16*)(&B1));
+ else lValue = *((UINT16*)S.addr);
+
+ /* HACK */
+ if (lValue >= 0xfff0)
+ {
+ logerror("Dsp56k : DO_2 operation changed %04x to 0000.\n", lValue);
+ lValue = 0x0000;
+ }
+
+ /* TODO: Fix for special cased SP S */
+ if (S.addr == &SP)
+ logerror("DSP56k: do with SP as the source not properly implemented yet.\n");
+
+ /* TODO: Fix for special cased SSSL S */
+ if (S.addr == &SSL)
+ logerror("DSP56k: do with SP as the source not properly implemented yet.\n");
+
+ /* Don't execute if the loop counter == 0 */
+ if (lValue != 0x00)
+ {
+ /* First instruction cycle */
+ SP++; /* TODO: Should i really inc here first? */
+ SSH = LA;
+ SSL = LC;
+ LC = (UINT16)lValue;
+
+
+ /* Second instruction cycle */
+ SP++; /* TODO: See above */
+ SSH = PC + 2; /* Keep these stack entries in 'word-based-index' space */
+ SSL = SR;
+ LA = PC + 2 + op2; /* TODO: The docs subtract 1 from here? */
+
+
+ /* Third instruction cycle */
+ LF_bit_set(cpustate, 1);
+
+
+ /* S L E U N Z V C */
+ /* - * - - - - - - */
+ /* TODO : L */
+
+ cycles += 6; /* TODO: + mv oscillator cycles */
+ retSize = 2;
+ }
+ else
+ {
+ /* Skip over the contents of the loop */
+ cpustate->ppc = PC;
+ PC = PC + 2 + op2;
+
+ cycles += 10; /* TODO: + mv oscillator cycles */
+ retSize = 0;
+ }
+
+ return retSize;
+}
+
+/* DO FOREVER : 0000 0000 0000 0010 xxxx xxxx xxxx xxxx : A-88 */
+static size_t dsp56k_op_doforever(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles)
+{
+ /* First instruction cycle */
+ SP++;
+ SSH = LA;
+ SSL = LC;
+
+ /* Second instruction cycle */
+ SP++;
+ SSH = PC + 2;
+ SSL = SR;
+ LA = PC + 2 + op2;
+
+ /* Third instruction cycle */
+ LF_bit_set(cpustate, 1);
+ FV_bit_set(cpustate, 1);
+
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ cycles += 6;
+ return 2;
+}
+
+/* ENDDO : 0000 0000 0000 1001 : A-92 */
+static size_t dsp56k_op_enddo(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* EXT : 0001 0101 0101 F010 : A-96 */
+static size_t dsp56k_op_ext(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* - * * * * * * - */
+ return 0;
+}
+
+/* ILLEGAL : 0000 0000 0000 1111 : A-98 */
+static size_t dsp56k_op_illegal(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* IMAC : 0001 0101 1010 FQQQ : A-100 */
+static size_t dsp56k_op_imac(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ INT64 opD = 0;
+ INT64 result = 0;
+
+ INT32 s1 = 0;
+ INT32 s2 = 0;
+
+ void* D = NULL;
+ void* S1 = NULL;
+ void* S2 = NULL;
+
+ decode_QQQF_table(cpustate, BITS(op,0x0007), BITS(op,0x0008), &S1, &S2, &D);
+
+ /* Cast both values as being signed */
+ s1 = *((INT16*)S1);
+ s2 = *((INT16*)S2);
+
+ /* Integral multiply doesn't require the shift */
+ result = (s1 * s2);
+
+ /* Shift result 16 bits to the left before adding to destination */
+ result = (result << 16) & 0xffff0000;
+
+ /* Sign extend D into a temp variable */
+ opD = (*((UINT64*)D));
+ if (opD & U64(0x0000008000000000))
+ opD |= U64(0xffffff0000000000);
+ else
+ opD &= U64(0x000000ffffffffff);
+
+ /* Accumulate */
+ opD += result;
+
+ /* And out the bits that don't live in the register */
+ opD &= U64(0x000000ffffffffff);
+
+ (*((UINT64*)D)) = (UINT64)opD;
+
+ /* S L E U N Z V C */
+ /* - * ? ? * ? ? - */
+ /* TODO: L */
+ /* U,E - Will not be set correctly by this instruction*/
+ if ( *((UINT64*)D) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR();
+ if ((*((UINT64*)D) & U64(0x000000ffffff0000)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR();
+ DSP56K_V_CLEAR();
+
+ cycles += 2;
+ return 1;
+}
+
+/* IMPY : 0001 0101 1000 FQQQ : A-102 */
+static size_t dsp56k_op_impy(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* - * ? ? * ? ? - */
+ /* Z - Set if the 24 most significant bits of the destination result are all zeroes. */
+ /* U,E - Will not be set correctly by this instruction*/
+ /* V - Set to zero regardless of the overflow */
+ return 0;
+}
+
+/* Jcc : 0000 0110 --11 cccc xxxx xxxx xxxx xxxx : A-108 */
+static size_t dsp56k_op_jcc(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* Jcc : 0000 0110 RR10 cccc : A-108 */
+static size_t dsp56k_op_jcc_1(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* JMP : 0000 0001 0011 01-- xxxx xxxx xxxx xxxx : A-110 */
+static size_t dsp56k_op_jmp(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles)
+{
+ cpustate->ppc = PC;
+ PC = op2;
+
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+
+ cycles += 4; /* TODO: + jx */
+ return 0;
+}
+
+/* JMP : 0000 0001 0010 01RR : A-110 */
+static size_t dsp56k_op_jmp_1(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ typed_pointer R = { NULL, DT_BYTE };
+ decode_RR_table(cpustate, BITS(op,0x0003), &R);
+
+ cpustate->ppc = PC;
+ PC = *((UINT16*)R.addr);
+
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+
+ cycles += 4; /* TODO: + jx */
+ return 0;
+}
+
+/* JScc : 0000 0110 --01 cccc xxxx xxxx xxxx xxxx : A-112 */
+static size_t dsp56k_op_jscc(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles)
+{
+ int shouldJump = decode_cccc_table(cpustate, BITS(op,0x000f));
+
+ if(shouldJump)
+ {
+ /* TODO: It says "signed" absolute offset. Weird. */
+ UINT16 branchOffset = op2;
+
+ /* TODO: Verify, since it's not in the docs, but it must be true */
+ PC += 2;
+
+ SP++;
+ SSH = PC;
+ SSL = SR;
+
+ cpustate->ppc = PC;
+ PC = branchOffset;
+
+ cycles += 4; /* TODO: +jx oscillator clock cycles */
+ return 0;
+ }
+ else
+ {
+ cycles += 4; /* TODO: +jx oscillator clock cycles */
+ return 2;
+ }
+
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* JScc : 0000 0110 RR00 cccc : A-112 */
+static size_t dsp56k_op_jscc_1(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* JSR : 0000 0001 0011 00-- xxxx xxxx xxxx xxxx : A-114 */
+static size_t dsp56k_op_jsr(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles)
+{
+ /* TODO: It says "signed" absolute offset. Weird. */
+ UINT16 branchOffset = op2;
+
+ /* TODO: Verify, since it's not in the docs, but it must be true */
+ PC += 2;
+
+ /* TODO: This is a hacky implementation of Long vs Fast Interrupts. Do it right someday! */
+ if (PC < ADDRESS(0x40))
+ {
+ /* Long interrupt gets the previous PC, not the current one */
+ SP++;
+ SSH = cpustate->ppc;
+ SSL = SR;
+
+ cpustate->ppc = cpustate->ppc;
+ PC = branchOffset;
+ }
+ else
+ {
+ /* Normal operation */
+ SP++;
+ SSH = PC;
+ SSL = SR;
+
+ cpustate->ppc = PC;
+ PC = branchOffset;
+ }
+
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ cycles += 4; /* TODO: + jx oscillator cycles */
+ return 0;
+}
+
+/* JSR : 0000 1010 AAAA AAAA : A-114 */
+static size_t dsp56k_op_jsr_1(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* JSR : 0000 0001 0010 00RR : A-114 */
+static size_t dsp56k_op_jsr_2(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* LEA : 0000 0001 11TT MMRR : A-116 */
+static size_t dsp56k_op_lea(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ UINT16 ea = 0;
+ UINT16 *rX = NULL;
+ UINT16 *nX = NULL;
+ typed_pointer D = {NULL, DT_BYTE};
+ decode_TT_table(cpustate, BITS(op,0x0030), &D);
+
+ /* TODO: change the execute_mm_functions to return values. Maybe */
+ /* Because this calculation isn't applied, do everything locally */
+ /* RR table */
+ switch(BITS(op,0x0003))
+ {
+ case 0x0: rX = &R0; nX = &N0; break;
+ case 0x1: rX = &R1; nX = &N1; break;
+ case 0x2: rX = &R2; nX = &N2; break;
+ case 0x3: rX = &R3; nX = &N3; break;
+ }
+
+ /* MM table */
+ switch(BITS(op,0x000c))
+ {
+ case 0x0: ea = *rX; break;
+ case 0x1: ea = *rX + 1; break;
+ case 0x2: ea = *rX - 1; break;
+ case 0x3: ea = *rX + *nX; break;
+ }
+
+ *((UINT16*)D.addr) = ea;
+
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 1;
+}
+
+/* LEA : 0000 0001 10NN MMRR : A-116 */
+static size_t dsp56k_op_lea_1(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* MAC(su,uu) : 0001 0101 1110 FsQQ : A-126 */
+static size_t dsp56k_op_macsuuu(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ UINT8 s = 0;
+ INT64 result = 0;
+
+ void* D = NULL;
+ void* S1 = NULL;
+ void* S2 = NULL;
+
+ decode_QQF_special_table(cpustate, BITS(op,0x0003), BITS(op,0x0008), &S1, &S2, &D);
+
+ s = BITS(op,0x0004);
+
+ /* Fixed-point 2's complement multiplication requires a shift */
+ if (s)
+ {
+ /* Unsigned * Unsigned */
+ UINT32 s1 = (UINT32)(*((UINT16*)S1));
+ UINT32 s2 = (UINT32)(*((UINT16*)S2));
+ result = ( s1 * s2 ) << 1;
+ }
+ else
+ {
+ /* Signed * Unsigned */
+ /* WARNING : THERE IS A HUGE CHANCE THIS DOESN'T WORK RIGHT */
+ INT32 s1 = ((INT32)(*((UINT16*)S1)));
+ INT32 s2 = (UINT32)(*((UINT16*)S2));
+ result = ( s1 * s2 ) << 1;
+ }
+
+ (*((UINT64*)D)) += result;
+
+ /* And out the bits that don't live in the register */
+ (*((UINT64*)D)) &= U64(0x000000ffffffffff);
+
+ /* S L E U N Z V C */
+ /* - * * * * * * - */
+ /* TODO: L, E, U, V */
+ if ( *((UINT64*)D) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR();
+ if ((*((UINT64*)D) & U64(0x000000ffffffffff)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR();
+
+ cycles += 2;
+ return 1;
+}
+
+/* MOVE : 0000 0101 BBBB BBBB ---- HHHW 0001 0001 : A-128 */
+static size_t dsp56k_op_move_2(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * - - - - - - */
+ return 0;
+}
+
+/* MOVE(C) : 0011 1WDD DDD0 MMRR : A-144 */
+static size_t dsp56k_op_movec(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ UINT8 W;
+ typed_pointer R = { NULL, DT_BYTE };
+ typed_pointer SD = { NULL, DT_BYTE };
+
+ W = BITS(op,0x0400);
+ decode_DDDDD_table(cpustate, BITS(op,0x03e0), &SD);
+ decode_RR_table(cpustate, BITS(op,0x0003), &R);
+
+ if (W)
+ {
+ /* Write D */
+ UINT16 value = cpustate->data->read_word(ADDRESS(*((UINT16*)R.addr))) ;
+ typed_pointer temp_src = { &value, DT_WORD };
+ SetDestinationValue(temp_src, SD);
+ }
+ else
+ {
+ /* Read S */
+ UINT16 dataMemOffset = *((UINT16*)R.addr);
+ SetDataMemoryValue(cpustate, SD, ADDRESS(dataMemOffset));
+ }
+
+ execute_MM_table(cpustate, BITS(op,0x0003), BITS(op,0x000c));
+
+ /* S L E U N Z V C */
+ /* * ? ? ? ? ? ? ? */
+ /* All ? bits - If SR is specified as a destination operand, set according to the corresponding
+ bit of the source operand. If SR is not specified as a destination operand, L is set if data
+ limiting occurred. All ? bits are not affected otherwise.*/
+ if (W && (SD.addr != &SR))
+ {
+ /* If you're writing to something other than the SR */
+ /* TODO */
+ }
+
+ cycles += 2; /* TODO: + mvc */
+ return 1;
+}
+
+/* MOVE(C) : 0011 1WDD DDD1 q0RR : A-144 */
+static size_t dsp56k_op_movec_1(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ UINT8 W;
+ UINT16 memOffset;
+ typed_pointer SD = {NULL, DT_BYTE};
+
+ W = BITS(op,0x0400);
+ decode_DDDDD_table(cpustate, BITS(op,0x03e0), &SD);
+ memOffset = execute_q_table(cpustate, BITS(op,0x0003), BITS(op,0x0008));
+
+ if (W)
+ {
+ /* Write D */
+ UINT16 tempData = cpustate->data->read_word(ADDRESS(memOffset));
+ typed_pointer temp_src = { (void*)&tempData, DT_WORD };
+ SetDestinationValue(temp_src, SD);
+ }
+ else
+ {
+ /* Read S */
+ UINT16 tempData = *((UINT16*)SD.addr);
+ typed_pointer temp_src = { (void*)&tempData, DT_WORD };
+ SetDataMemoryValue(cpustate, temp_src, ADDRESS(memOffset));
+ }
+
+ /* S L E U N Z V C */
+ /* * ? ? ? ? ? ? ? */
+ /* All ? bits - If SR is specified as a destination operand, set according to the corresponding
+ bit of the source operand. If SR is not specified as a destination operand, L is set if data
+ limiting occurred. All ? bits are not affected otherwise.*/
+ if (W && (SD.addr != &SR))
+ {
+ /* If you're writing to something other than the SR */
+ /* TODO */
+ }
+
+ cycles += 2; /* + mvc oscillator clock cycles */
+ return 1;
+}
+
+/* MOVE(C) : 0011 1WDD DDD1 Z11- : A-144 */
+static size_t dsp56k_op_movec_2(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ UINT8 W;
+ UINT16 memOffset;
+ typed_pointer SD = {NULL, DT_BYTE};
+ typed_pointer XMemOffset = {NULL, DT_BYTE};
+
+ W = BITS(op,0x0400);
+ decode_Z_table(cpustate, BITS(op,0x0008), &XMemOffset);
+ decode_DDDDD_table(cpustate, BITS(op,0x03e0), &SD);
+
+ memOffset = *((UINT16*)XMemOffset.addr);
+
+ if (W)
+ {
+ /* Write D */
+ UINT16 tempData = cpustate->data->read_word(ADDRESS(memOffset));
+ typed_pointer temp_src = { (void*)&tempData, DT_WORD };
+ SetDestinationValue(temp_src, SD);
+ }
+ else
+ {
+ /* Read S */
+ UINT16 tempData = *((UINT16*)SD.addr);
+ typed_pointer temp_src = { (void*)&tempData, DT_WORD };
+ SetDataMemoryValue(cpustate, temp_src, ADDRESS(memOffset));
+ }
+
+
+ /* S L E U N Z V C */
+ /* * ? ? ? ? ? ? ? */
+ /* All ? bits - If SR is specified as a destination operand, set according to the corresponding
+ bit of the source operand. If SR is not specified as a destination operand, L is set if data
+ limiting occurred. All ? bits are not affected otherwise.*/
+ if (W && (SD.addr != &SR))
+ {
+ /* If you're writing to something other than the SR */
+ /* TODO */
+ }
+
+ cycles += 2; /* + mvc oscillator clock cycles */
+ return 1;
+}
+
+/* MOVE(C) : 0011 1WDD DDD1 t10- xxxx xxxx xxxx xxxx : A-144 */
+static size_t dsp56k_op_movec_3(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles)
+{
+ UINT8 W;
+ UINT8 t;
+ typed_pointer SD = { NULL, DT_BYTE };
+
+ W = BITS(op,0x0400);
+ t = BITS(op,0x0008);
+ decode_DDDDD_table(cpustate, BITS(op,0x03e0), &SD);
+
+ if (W)
+ {
+ /* Write D */
+ if (t)
+ {
+ /* 16-bit long data */
+ typed_pointer temp_src = { (void*)&op2, DT_WORD };
+ SetDestinationValue(temp_src, SD);
+ }
+ else
+ {
+ /* 16-bit long address */
+ UINT16 tempD = cpustate->data->read_word(ADDRESS(op2));
+ typed_pointer tempTP = {&tempD, DT_WORD};
+ SetDestinationValue(tempTP, SD);
+ }
+ }
+ else
+ {
+ /* Read S */
+ if (t)
+ {
+ /* 16-bit long data */
+ logerror("DSP56k: Movec - I don't think this exists?");
+ }
+ else
+ {
+ /* 16-bit long address */
+ SetDataMemoryValue(cpustate, SD, ADDRESS(op2));
+ }
+ }
+
+ /* S L E U N Z V C */
+ /* * ? ? ? ? ? ? ? */
+ /* All ? bits - If SR is specified as a destination operand, set according to the corresponding
+ bit of the source operand. If SR is not specified as a destination operand, L is set if data
+ limiting occurred. All ? bits are not affected otherwise.*/
+ if (W && (SD.addr != &SR))
+ {
+ /* If you're writing to something other than the SR */
+ /* TODO */
+ }
+
+ cycles += 2; /* TODO: + mvc */
+ return 2;
+}
+
+/* MOVE(C) : 0010 10dd dddD DDDD : A-144 */
+static size_t dsp56k_op_movec_4(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ typed_pointer S = {NULL, DT_BYTE};
+ typed_pointer D = {NULL, DT_BYTE};
+
+ decode_DDDDD_table(cpustate, BITS(op,0x03e0), &S);
+ decode_DDDDD_table(cpustate, BITS(op,0x001f), &D);
+
+ SetDestinationValue(S, D);
+
+ /* S L E U N Z V C */
+ /* * ? ? ? ? ? ? ? */
+ /* All ? bits - If SR is specified as a destination operand, set according to the corresponding
+ bit of the source operand. If SR is not specified as a destination operand, L is set if data
+ limiting occurred. All ? bits are not affected otherwise.*/
+ if (D.addr != &SR)
+ {
+ /* If you're writing to something other than the SR */
+ /* TODO */
+ }
+
+ cycles += 2;
+ return 1;
+}
+
+/* MOVE(C) : 0000 0101 BBBB BBBB 0011 1WDD DDD0 ---- : A-144 */
+static size_t dsp56k_op_movec_5(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles)
+{
+ INT8 xx;
+ UINT8 W;
+ UINT16 memOffset;
+ typed_pointer SD = { NULL, DT_BYTE };
+
+ xx = (INT8)(op & 0x00ff);
+ W = BITS(op2,0x0400);
+ decode_DDDDD_table(cpustate, BITS(op2,0x03e0), &SD);
+
+ memOffset = R2 + (INT16)xx;
+
+ if (W)
+ {
+ /* Write D */
+ UINT16 tempData = cpustate->data->read_word(ADDRESS(memOffset));
+ typed_pointer temp_src = { (void*)&tempData, DT_WORD };
+ SetDestinationValue(temp_src, SD);
+ }
+ else
+ {
+ /* Read S */
+ UINT16 tempData = *((UINT16*)SD.addr);
+ typed_pointer temp_src = { (void*)&tempData, DT_WORD };
+ SetDataMemoryValue(cpustate, temp_src, ADDRESS(memOffset));
+ }
+
+ /* S L E U N Z V C */
+ /* * ? ? ? ? ? ? ? */
+ /* All ? bits - If SR is specified as a destination operand, set according to the corresponding
+ bit of the source operand. If SR is not specified as a destination operand, L is set if data
+ limiting occurred. All ? bits are not affected otherwise.*/
+ if (W && (SD.addr != &SR))
+ {
+ /* If you're writing to something other than the SR */
+ /* TODO */
+ }
+
+ cycles += 2; /* TODO: + mvc oscillator clock cycles */
+ return 2;
+}
+
+/* MOVE(I) : 0010 00DD BBBB BBBB : A-150 */
+static size_t dsp56k_op_movei(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ typed_pointer D = {NULL, DT_BYTE};
+ typed_pointer immTP = {NULL, DT_BYTE};
+
+ /* Typecasting to INT16 sign-extends the BBBBBBBB operand */
+ UINT16 immediateSignExtended = (INT16)(op & 0x00ff);
+ immTP.addr = &immediateSignExtended;
+ immTP.data_type = DT_WORD;
+
+ decode_DD_table(cpustate, BITS(op,0x0300), &D);
+
+ SetDestinationValue(immTP, D);
+
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ cycles += 2;
+ return 1;
+}
+
+/* MOVE(M) : 0000 001W RR0M MHHH : A-152 */
+static size_t dsp56k_op_movem(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ UINT8 W;
+ typed_pointer R = { NULL, DT_BYTE };
+ typed_pointer SD = { NULL, DT_BYTE };
+
+ W = BITS(op,0x0100);
+ decode_RR_table(cpustate, BITS(op,0x00c0), &R);
+ decode_HHH_table(cpustate, BITS(op,0x0007), &SD);
+
+ if (W)
+ {
+ /* Read from Program Memory */
+ typed_pointer data;
+ UINT16 ldata = cpustate->program->read_word(ADDRESS(*((UINT16*)R.addr)));
+
+ data.addr = &ldata;
+ data.data_type = DT_WORD;
+ SetDestinationValue(data, SD) ;
+ }
+ else
+ {
+ /* Write to Program Memory */
+ SetProgramMemoryValue(cpustate, SD, ADDRESS(*((UINT16*)R.addr))) ;
+ }
+
+ execute_MM_table(cpustate, BITS(op,0x00c0), BITS(op,0x0018));
+
+ /* S L E U N Z V C */
+ /* * * - - - - - - */
+ /* TODO: S, L */
+ cycles += 2; /* TODO: + mvm oscillator clock cycles */
+ return 1;
+}
+
+/* MOVE(M) : 0000 001W RR11 mmRR : A-152 */
+static size_t dsp56k_op_movem_1(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * - - - - - - */
+ return 0;
+}
+
+/* MOVE(M) : 0000 0101 BBBB BBBB 0000 001W --0- -HHH : A-152 */
+static size_t dsp56k_op_movem_2(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * - - - - - - */
+ return 0;
+}
+
+/* MOVE(P) : 0001 100W HH1p pppp : A-156 */
+static size_t dsp56k_op_movep(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ UINT16 W;
+ UINT16 pp;
+ typed_pointer SD = {NULL, DT_BYTE};
+
+ decode_HH_table(cpustate, BITS(op,0x00c0), &SD);
+ /* TODO: Special cases for A & B */
+
+ pp = op & 0x001f;
+ pp = assemble_address_from_IO_short_address(cpustate, pp);
+
+ W = BITS(op,0x0100);
+
+ if (W)
+ {
+ UINT16 data = cpustate->data->read_word(ADDRESS(pp));
+
+ typed_pointer tempTP;
+ tempTP.addr = &data;
+ tempTP.data_type = DT_WORD;
+
+ SetDestinationValue(tempTP, SD);
+ }
+ else
+ {
+ SetDataMemoryValue(cpustate, SD, ADDRESS(pp));
+ }
+
+ /* S L E U N Z V C */
+ /* * * - - - - - - */
+ /* TODO: S, L */
+
+ cycles += 4; /* TODO: + mvp oscillator cycles */
+ return 1;
+}
+
+/* MOVE(P) : 0000 110W RRmp pppp : A-156 */
+static size_t dsp56k_op_movep_1(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ /* X:<Rx> and X:<pp> */
+ UINT16 W;
+ UINT16 pp;
+
+ typed_pointer SD = {NULL, DT_BYTE};
+ decode_RR_table(cpustate, BITS(op,0x00c0), &SD);
+
+ pp = op & 0x001f;
+ pp = assemble_address_from_IO_short_address(cpustate, pp);
+
+ W = BITS(op,0x0100);
+
+ /* A little different than most W if's - opposite read and write */
+ if (W)
+ {
+ UINT16 data = cpustate->data->read_word(ADDRESS(*((UINT16*)SD.addr)));
+
+ typed_pointer tempTP;
+ tempTP.addr = &data;
+ tempTP.data_type = DT_WORD;
+
+ SetDataMemoryValue(cpustate, tempTP, ADDRESS(pp));
+ }
+ else
+ {
+ /* TODO */
+ fatalerror("dsp56k : move(p) NOTHING HERE (yet)\n") ;
+ }
+
+ /* Postincrement */
+ execute_m_table(cpustate, BITS(op,0x00c0), BITS(op,0x0020));
+
+ /* S L E U N Z V C */
+ /* * * - - - - - - */
+ /* TODO: S, L */
+ cycles += 4; /* TODO: + mvp oscillator cycles */
+ return 1;
+}
+
+/* MOVE(S) : 0001 100W HH0a aaaa : A-158 */
+static size_t dsp56k_op_moves(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * - - - - - - */
+ return 0;
+}
+
+/* MPY(su,uu) : 0001 0101 1100 FsQQ : A-164 */
+static size_t dsp56k_op_mpysuuu(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ UINT8 s = 0;
+ INT64 result = 0;
+
+ void* D = NULL;
+ void* S1 = NULL;
+ void* S2 = NULL;
+
+ decode_QQF_special_table(cpustate, BITS(op,0x0003), BITS(op,0x0008), &S1, &S2, &D);
+
+ s = BITS(op,0x0004);
+
+ /* Fixed-point 2's complement multiplication requires a shift */
+ if (s)
+ {
+ /* Unsigned * Unsigned */
+ UINT32 s1 = (UINT32)(*((UINT16*)S1));
+ UINT32 s2 = (UINT32)(*((UINT16*)S2));
+ result = ( s1 * s2 ) << 1;
+ }
+ else
+ {
+ /* Signed * Unsigned */
+ /* WARNING : THERE IS A HUGE CHANCE THIS DOESN'T WORK RIGHT */
+ INT32 s1 = ((INT32)(*((UINT16*)S1)));
+ INT32 s2 = (UINT32)(*((UINT16*)S2));
+ result = ( s1 * s2 ) << 1;
+ }
+
+ (*((UINT64*)D)) = result;
+
+ /* And out the bits that don't live in the register */
+ (*((UINT64*)D)) &= U64(0x000000ffffffffff);
+
+ /* S L E U N Z V C */
+ /* - * * * * * * - */
+ /* TODO: L, E, U, V */
+ if ( *((UINT64*)D) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR();
+ if ((*((UINT64*)D) & U64(0x000000ffffffffff)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR();
+
+ cycles += 2;
+ return 1;
+}
+
+/* NEGC : 0001 0101 0110 F000 : A-168 */
+static size_t dsp56k_op_negc(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* - * * * * * * * */
+ return 0;
+}
+
+/* NOP : 0000 0000 0000 0000 : A-170 */
+static size_t dsp56k_op_nop(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 1;
+}
+
+/* NORM : 0001 0101 0010 F0RR : A-172 */
+static size_t dsp56k_op_norm(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* - * * * * * ? - */
+ /* V - Set if an arithmetic overflow occurs in the 40 bit result. Also set if the most significantst
+ bit of the destination operand is changed as a result of the left shift. Cleared otherwise. */
+ return 0;
+}
+
+/* ORI : 0001 1EE1 iiii iiii : A-178 */
+static size_t dsp56k_op_ori(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* - ? ? ? ? ? ? ? */
+ /* All ? bits - Set if the corresponding bit in the immediate data is set and if the operand is the
+ CCR. Not affected otherwise. */
+ return 0;
+}
+
+/* REP : 0000 0000 111- --RR : A-180 */
+static size_t dsp56k_op_rep(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* - * - - - - - - */
+ return 0;
+}
+
+/* REP : 0000 1111 iiii iiii : A-180 */
+static size_t dsp56k_op_rep_1(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ /* TODO: This is non-interruptable, probably have to turn off interrupts here */
+ UINT16 iVal = op & 0x00ff;
+
+ if (iVal != 0)
+ {
+ TEMP = LC;
+ LC = iVal;
+
+ cpustate->repFlag = 1;
+ cpustate->repAddr = PC + ADDRESS(1);
+
+ cycles += 4; /* TODO: + mv oscillator clock cycles */
+ }
+ else
+ {
+ cycles += 6; /* TODO: + mv oscillator clock cycles */
+ }
+
+
+ /* S L E U N Z V C */
+ /* - * - - - - - - */
+ /* TODO: L */
+ return 1;
+}
+
+/* REP : 0000 0100 001D DDDD : A-180 */
+static size_t dsp56k_op_rep_2(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ /* TODO: This is non-interruptable, probably have to turn off interrupts here */
+ UINT16 repValue;
+ typed_pointer D = {NULL, DT_BYTE};
+ decode_DDDDD_table(cpustate, BITS(op,0x001f), &D);
+
+ /* TODO: handle special A&B source cases */
+ if (D.addr == &A || D.addr == &B)
+ logerror("DSP56k ERROR : Rep with A or B instruction not implemented yet!\n");
+
+ repValue = *((UINT16*)D.addr);
+
+ if (repValue != 0)
+ {
+ TEMP = LC;
+ LC = repValue;
+
+ cpustate->repFlag = 1;
+ cpustate->repAddr = PC + ADDRESS(1);
+
+ cycles += 4; /* TODO: + mv oscillator clock cycles */
+ }
+ else
+ {
+ cycles += 6; /* TODO: + mv oscillator clock cycles */
+ }
+
+ /* S L E U N Z V C */
+ /* - * - - - - - - */
+ /* TODO: L */
+ return 1;
+}
+
+/* REPcc : 0000 0001 0101 cccc : A-184 */
+static size_t dsp56k_op_repcc(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* RESET : 0000 0000 0000 1000 : A-186 */
+static size_t dsp56k_op_reset(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* RTI : 0000 0000 0000 0111 : A-194 */
+static size_t dsp56k_op_rti(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ /* WARNING : THERE SHOULD BE A MORE GENERAL HANDLING OF STACK ERRORS. */
+ if (SP == 0)
+ {
+ dsp56k_add_pending_interrupt(cpustate, "Stack Error");
+ return 0;
+ }
+
+ cpustate->ppc = PC;
+ PC = SSH;
+
+ SR = SSL;
+ SP = SP - 1;
+
+ /* S L E U N Z V C */
+ /* ? ? ? ? ? ? ? ? */
+ /* All ? bits - Set according to value pulled from the stack. */
+ cycles += 4; /* TODO: + rx oscillator clock cycles */
+ return 0;
+}
+
+/* RTS : 0000 0000 0000 0110 : A-196 */
+static size_t dsp56k_op_rts(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ /* Pop */
+ cpustate->ppc = PC;
+ PC = SSH;
+
+ /* SR = SSL; The status register is not affected. */
+
+ SP--;
+
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ cycles += 4; /* TODO: + rx oscillator clock cycles */
+ return 0;
+}
+
+/* STOP : 0000 0000 0000 1010 : A-200 */
+static size_t dsp56k_op_stop(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* SWAP : 0001 0101 0111 F001 : A-206 */
+static size_t dsp56k_op_swap(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* SWI : 0000 0000 0000 0101 : A-208 */
+static size_t dsp56k_op_swi(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* Tcc : 0001 00cc ccTT Fh0h : A-210 */
+static size_t dsp56k_op_tcc(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ int shouldTransfer = decode_cccc_table(cpustate, BITS(op,0x03c0));
+
+ if (shouldTransfer)
+ {
+ typed_pointer S = {NULL, DT_BYTE};
+ typed_pointer D = {NULL, DT_BYTE};
+ typed_pointer S2 = {&R0, DT_WORD};
+ typed_pointer D2 = {NULL, DT_BYTE};
+
+ decode_h0hF_table(cpustate, BITS(op,0x0007),BITS(op,0x0008), &S, &D);
+ SetDestinationValue(S, D);
+
+ /* TODO: What's up with that A,A* thing in the docs? Can you only ignore the R0->RX transfer if you do an A,A? */
+ decode_RR_table(cpustate, BITS(op,0x0030), &D2); /* TT is the same as RR */
+ SetDestinationValue(S2, D2);
+ }
+
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ cycles += 2;
+ return 1;
+}
+
+/* TFR(2) : 0001 0101 0000 F00J : A-214 */
+static size_t dsp56k_op_tfr2(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ typed_pointer S = {NULL, DT_BYTE};
+ typed_pointer D = {NULL, DT_BYTE};
+
+ decode_JF_table(cpustate, BITS(op,0x0001), BITS(op,0x0008), &S, &D);
+
+ SetDestinationValue(S, D);
+
+ /* S L E U N Z V C */
+ /* - * - - - - - - */
+ /* TODO: L */
+ cycles += 2;
+ return 1;
+}
+
+/* TFR(3) : 0010 01mW RRDD FHHH : A-216 */
+static size_t dsp56k_op_tfr3(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* * * - - - - - - */
+ return 0;
+}
+
+/* TST(2) : 0001 0101 0001 -1DD : A-220 */
+static size_t dsp56k_op_tst2(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ typed_pointer D = {NULL, DT_BYTE};
+ decode_DD_table(cpustate, BITS(op,0x0003), &D);
+
+ /* S L E U N Z V C */
+ /* - * * * * * 0 0 */
+ /* (L,E,U should be set to 0) */
+ DSP56K_L_CLEAR();
+ DSP56K_E_CLEAR();
+ /* U_CLEAR(); */ /* TODO: Conflicting opinions? "Set if unnormalized." Documentation is weird (A&B?) */
+ if ((*((UINT16*)D.addr)) & 0x8000) DSP56K_N_SET(); else DSP56K_N_CLEAR();
+ if ((*((UINT16*)D.addr)) == 0x0000) DSP56K_Z_SET(); else DSP56K_Z_CLEAR();
+ /* DSP56K_V_CLEAR(); */ /* Unaffected */
+ DSP56K_C_CLEAR();
+
+ cycles += 2;
+ return 1;
+}
+
+/* WAIT : 0000 0000 0000 1011 : A-222 */
+static size_t dsp56k_op_wait(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ return 0;
+}
+
+/* ZERO : 0001 0101 0101 F000 : A-224 */
+static size_t dsp56k_op_zero(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles)
+{
+ /* S L E U N Z V C */
+ /* - * * * * * * - */
+ return 0;
+}
+
+
+
+/***************************************************************************
+ Table decoding
+***************************************************************************/
+static UINT16 decode_BBB_bitmask(dsp56k_core* cpustate, UINT16 BBB, UINT16 *iVal)
+{
+ UINT16 retVal = 0x0000;
+
+ switch(BBB)
+ {
+ case 0x4: retVal = 0xff00; *iVal <<= 8; break;
+ case 0x2: retVal = 0x0ff0; *iVal <<= 4; break;
+ case 0x1: retVal = 0x00ff; *iVal <<= 0; break;
+ }
+
+ return retVal;
+}
+
+static int decode_cccc_table(dsp56k_core* cpustate, UINT16 cccc)
+{
+ int retVal = 0;
+
+ /* Not fully tested */
+ switch (cccc)
+ {
+ /* Arranged according to mnemonic table - not decoding table */
+ case 0x0: if( C() == 0) retVal = 1; break; /* cc(hs) */
+ case 0x8: if( C() == 1) retVal = 1; break; /* cs(lo) */
+ case 0x5: if( E() == 0) retVal = 1; break; /* ec */
+ case 0xa: if( Z() == 1) retVal = 1; break; /* eq */
+ case 0xd: if( E() == 1) retVal = 1; break; /* es */
+ case 0x1: if((N() ^ V()) == 0) retVal = 1; break; /* ge */
+ case 0x7: if((Z() | (N() ^ V())) == 0) retVal = 1; break; /* gt */
+ case 0x6: if( L() == 0) retVal = 1; break; /* lc */
+ case 0xf: if((Z() | (N() ^ V())) == 1) retVal = 1; break; /* le */
+ case 0xe: if( L() == 1) retVal = 1; break; /* ls */
+ case 0x9: if((N() ^ V()) == 1) retVal = 1; break; /* lt */
+ case 0xb: if( N() == 1) retVal = 1; break; /* mi */
+ case 0x2: if( Z() == 0) retVal = 1; break; /* ne */
+ case 0xc: if((Z() | ((!U()) & (!E()))) == 1) retVal = 1; break; /* nr */
+ case 0x3: if( N() == 0) retVal = 1; break; /* pl */
+ case 0x4: if((Z() | ((!U()) & (!E()))) == 0) retVal = 1; break; /* nn */
+ }
+
+ return retVal;
+}
+
+static void decode_DDDDD_table(dsp56k_core* cpustate, UINT16 DDDDD, typed_pointer* ret)
+{
+ switch(DDDDD)
+ {
+ case 0x00: ret->addr = &X0; ret->data_type = DT_WORD; break;
+ case 0x01: ret->addr = &Y0; ret->data_type = DT_WORD; break;
+ case 0x02: ret->addr = &X1; ret->data_type = DT_WORD; break;
+ case 0x03: ret->addr = &Y1; ret->data_type = DT_WORD; break;
+ case 0x04: ret->addr = &A ; ret->data_type = DT_LONG_WORD; break;
+ case 0x05: ret->addr = &B ; ret->data_type = DT_LONG_WORD; break;
+ case 0x06: ret->addr = &A0; ret->data_type = DT_WORD; break;
+ case 0x07: ret->addr = &B0; ret->data_type = DT_WORD; break;
+ case 0x08: ret->addr = &LC; ret->data_type = DT_WORD; break;
+ case 0x09: ret->addr = &SR; ret->data_type = DT_WORD; break;
+ case 0x0a: ret->addr = &OMR; ret->data_type = DT_BYTE; break;
+ case 0x0b: ret->addr = &SP; ret->data_type = DT_BYTE; break;
+ case 0x0c: ret->addr = &A1; ret->data_type = DT_WORD; break;
+ case 0x0d: ret->addr = &B1; ret->data_type = DT_WORD; break;
+ case 0x0e: ret->addr = &A2; ret->data_type = DT_BYTE; break;
+ case 0x0f: ret->addr = &B2; ret->data_type = DT_BYTE; break;
+
+ case 0x10: ret->addr = &R0; ret->data_type = DT_WORD; break;
+ case 0x11: ret->addr = &R1; ret->data_type = DT_WORD; break;
+ case 0x12: ret->addr = &R2; ret->data_type = DT_WORD; break;
+ case 0x13: ret->addr = &R3; ret->data_type = DT_WORD; break;
+ case 0x14: ret->addr = &M0; ret->data_type = DT_WORD; break;
+ case 0x15: ret->addr = &M1; ret->data_type = DT_WORD; break;
+ case 0x16: ret->addr = &M2; ret->data_type = DT_WORD; break;
+ case 0x17: ret->addr = &M3; ret->data_type = DT_WORD; break;
+ case 0x18: ret->addr = &SSH; ret->data_type = DT_WORD; break;
+ case 0x19: ret->addr = &SSL; ret->data_type = DT_WORD; break;
+ case 0x1a: ret->addr = &LA; ret->data_type = DT_WORD; break;
+ /*no 0x1b */
+ case 0x1c: ret->addr = &N0; ret->data_type = DT_WORD; break;
+ case 0x1d: ret->addr = &N1; ret->data_type = DT_WORD; break;
+ case 0x1e: ret->addr = &N2; ret->data_type = DT_WORD; break;
+ case 0x1f: ret->addr = &N3; ret->data_type = DT_WORD; break;
+ }
+}
+
+static void decode_DD_table(dsp56k_core* cpustate, UINT16 DD, typed_pointer* ret)
+{
+ switch(DD)
+ {
+ case 0x00: ret->addr = &X0; ret->data_type = DT_WORD; break;
+ case 0x01: ret->addr = &Y0; ret->data_type = DT_WORD; break;
+ case 0x02: ret->addr = &X1; ret->data_type = DT_WORD; break;
+ case 0x03: ret->addr = &Y1; ret->data_type = DT_WORD; break;
+ }
+}
+
+static void decode_DDF_table(dsp56k_core* cpustate, UINT16 DD, UINT16 F, typed_pointer* src_ret, typed_pointer* dst_ret)
+{
+ UINT16 switchVal = (DD << 1) | F;
+
+ switch (switchVal)
+ {
+ case 0x0: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x1: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x2: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x3: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x4: src_ret->addr = &X1; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x5: src_ret->addr = &X1; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x6: src_ret->addr = &Y1; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x7: src_ret->addr = &Y1; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ }
+}
+
+static void decode_F_table(dsp56k_core* cpustate, UINT16 F, typed_pointer* ret)
+{
+ switch(F)
+ {
+ case 0x0: ret->addr = &A; ret->data_type = DT_LONG_WORD; break;
+ case 0x1: ret->addr = &B; ret->data_type = DT_LONG_WORD; break;
+ }
+}
+
+static void decode_h0hF_table(dsp56k_core* cpustate, UINT16 h0h, UINT16 F, typed_pointer* src_ret, typed_pointer* dst_ret)
+{
+ UINT16 switchVal = (h0h << 1) | F ;
+
+ switch (switchVal)
+ {
+ case 0x8: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x9: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0xa: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0xb: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x2: src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x1: src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x0: src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x3: src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ }
+}
+
+static void decode_HH_table(dsp56k_core* cpustate, UINT16 HH, typed_pointer* ret)
+{
+ switch(HH)
+ {
+ case 0x0: ret->addr = &X0; ret->data_type = DT_WORD; break;
+ case 0x1: ret->addr = &Y0; ret->data_type = DT_WORD; break;
+ case 0x2: ret->addr = &A; ret->data_type = DT_LONG_WORD; break;
+ case 0x3: ret->addr = &B; ret->data_type = DT_LONG_WORD; break;
+ }
+}
+
+static void decode_HHH_table(dsp56k_core* cpustate, UINT16 HHH, typed_pointer* ret)
+{
+ switch(HHH)
+ {
+ case 0x0: ret->addr = &X0; ret->data_type = DT_WORD; break;
+ case 0x1: ret->addr = &Y0; ret->data_type = DT_WORD; break;
+ case 0x2: ret->addr = &X1; ret->data_type = DT_WORD; break;
+ case 0x3: ret->addr = &Y1; ret->data_type = DT_WORD; break;
+ case 0x4: ret->addr = &A; ret->data_type = DT_LONG_WORD; break;
+ case 0x5: ret->addr = &B; ret->data_type = DT_LONG_WORD; break;
+ case 0x6: ret->addr = &A0; ret->data_type = DT_WORD; break;
+ case 0x7: ret->addr = &B0; ret->data_type = DT_WORD; break;
+ }
+}
+
+static void decode_IIII_table(dsp56k_core* cpustate, UINT16 IIII, typed_pointer* src_ret, typed_pointer* dst_ret, void *working)
+{
+ void *opposite = 0x00 ;
+
+ if (working == &A) opposite = &B ;
+ else opposite = &A ;
+
+ switch(IIII)
+ {
+ case 0x0: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = opposite; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x1: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = opposite; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x2: src_ret->addr = &X1; src_ret->data_type = DT_WORD; dst_ret->addr = opposite; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x3: src_ret->addr = &Y1; src_ret->data_type = DT_WORD; dst_ret->addr = opposite; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x4: src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &X0; dst_ret->data_type = DT_WORD; break;
+ case 0x5: src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &Y0; dst_ret->data_type = DT_WORD; break;
+ case 0x6: src_ret->addr = &A0; src_ret->data_type = DT_WORD; dst_ret->addr = &X0; dst_ret->data_type = DT_WORD; break;
+ case 0x7: src_ret->addr = &B0; src_ret->data_type = DT_WORD; dst_ret->addr = &Y0; dst_ret->data_type = DT_WORD; break;
+ case 0x8: src_ret->addr = working; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = opposite; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x9: src_ret->addr = working; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = opposite; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0xc: src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &X1; dst_ret->data_type = DT_WORD; break;
+ case 0xd: src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &Y1; dst_ret->data_type = DT_WORD; break;
+ case 0xe: src_ret->addr = &A0; src_ret->data_type = DT_WORD; dst_ret->addr = &X1; dst_ret->data_type = DT_WORD; break;
+ case 0xf: src_ret->addr = &B0; src_ret->data_type = DT_WORD; dst_ret->addr = &Y1; dst_ret->data_type = DT_WORD; break;
+ }
+}
+
+static void decode_JJJF_table(dsp56k_core* cpustate, UINT16 JJJ, UINT16 F, typed_pointer* src_ret, typed_pointer* dst_ret)
+{
+ UINT16 switchVal = (JJJ << 1) | F ;
+
+ switch(switchVal)
+ {
+ case 0x0: src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x1: src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x4: src_ret->addr = &X; src_ret->data_type = DT_DOUBLE_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x5: src_ret->addr = &X; src_ret->data_type = DT_DOUBLE_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x6: src_ret->addr = &Y; src_ret->data_type = DT_DOUBLE_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x7: src_ret->addr = &Y; src_ret->data_type = DT_DOUBLE_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x8: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x9: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0xa: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0xb: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0xc: src_ret->addr = &X1; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0xd: src_ret->addr = &X1; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0xe: src_ret->addr = &Y1; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0xf: src_ret->addr = &Y1; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ }
+}
+
+static void decode_JJF_table(dsp56k_core* cpustate, UINT16 JJ, UINT16 F, typed_pointer* src_ret, typed_pointer* dst_ret)
+{
+ UINT16 switchVal = (JJ << 1) | F ;
+
+ switch (switchVal)
+ {
+ case 0x0: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x1: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x2: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x3: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x4: src_ret->addr = &X1; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x5: src_ret->addr = &X1; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x6: src_ret->addr = &Y1; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x7: src_ret->addr = &Y1; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ }
+}
+
+static void decode_JF_table(dsp56k_core* cpustate, UINT16 J, UINT16 F, typed_pointer* src_ret, typed_pointer* dst_ret)
+{
+ UINT16 switchVal = (J << 1) | F ;
+
+ switch (switchVal)
+ {
+ case 0x0: src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &X; dst_ret->data_type = DT_DOUBLE_WORD; break;
+ case 0x1: src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &X; dst_ret->data_type = DT_DOUBLE_WORD; break;
+ case 0x2: src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &Y; dst_ret->data_type = DT_DOUBLE_WORD; break;
+ case 0x3: src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &Y; dst_ret->data_type = DT_DOUBLE_WORD; break;
+ }
+}
+
+static void decode_KKK_table(dsp56k_core* cpustate, UINT16 KKK, typed_pointer* dst_ret1, typed_pointer* dst_ret2, void* working)
+{
+ void *opposite = 0x00 ;
+
+ if (working == &A) opposite = &B ;
+ else opposite = &A ;
+
+ switch(KKK)
+ {
+ case 0x0: dst_ret1->addr = opposite; dst_ret1->data_type = DT_LONG_WORD; dst_ret2->addr = &X0; dst_ret2->data_type = DT_WORD; break;
+ case 0x1: dst_ret1->addr = &Y0; dst_ret1->data_type = DT_WORD; dst_ret2->addr = &X0; dst_ret2->data_type = DT_WORD; break;
+ case 0x2: dst_ret1->addr = &X1; dst_ret1->data_type = DT_WORD; dst_ret2->addr = &X0; dst_ret2->data_type = DT_WORD; break;
+ case 0x3: dst_ret1->addr = &Y1; dst_ret1->data_type = DT_WORD; dst_ret2->addr = &X0; dst_ret2->data_type = DT_WORD; break;
+ case 0x4: dst_ret1->addr = &X0; dst_ret1->data_type = DT_WORD; dst_ret2->addr = &X1; dst_ret2->data_type = DT_WORD; break;
+ case 0x5: dst_ret1->addr = &Y0; dst_ret1->data_type = DT_WORD; dst_ret2->addr = &X1; dst_ret2->data_type = DT_WORD; break;
+ case 0x6: dst_ret1->addr = opposite; dst_ret1->data_type = DT_LONG_WORD; dst_ret2->addr = &Y0; dst_ret2->data_type = DT_WORD; break;
+ case 0x7: dst_ret1->addr = &Y1; dst_ret1->data_type = DT_WORD; dst_ret2->addr = &X1; dst_ret2->data_type = DT_WORD; break;
+ }
+}
+
+static void decode_QQF_table(dsp56k_core* cpustate, UINT16 QQ, UINT16 F, void **S1, void **S2, void **D)
+{
+ UINT16 switchVal = (QQ << 1) | F ;
+
+ switch(switchVal)
+ {
+ case 0x0: *S1 = &X0; *S2 = &Y0; *D = &A; break;
+ case 0x1: *S1 = &X0; *S2 = &Y0; *D = &B; break;
+ case 0x2: *S1 = &X0; *S2 = &Y1; *D = &A; break;
+ case 0x3: *S1 = &X0; *S2 = &Y1; *D = &B; break;
+ case 0x4: *S1 = &X1; *S2 = &Y0; *D = &A; break;
+ case 0x5: *S1 = &X1; *S2 = &Y0; *D = &B; break;
+ case 0x6: *S1 = &X1; *S2 = &Y1; *D = &A; break;
+ case 0x7: *S1 = &X1; *S2 = &Y1; *D = &B; break;
+ }
+}
+
+static void decode_QQF_special_table(dsp56k_core* cpustate, UINT16 QQ, UINT16 F, void **S1, void **S2, void **D)
+{
+ UINT16 switchVal = (QQ << 1) | F ;
+
+ switch(switchVal)
+ {
+ case 0x0: *S1 = &Y0; *S2 = &X0; *D = &A; break;
+ case 0x1: *S1 = &Y0; *S2 = &X0; *D = &B; break;
+ case 0x2: *S1 = &Y1; *S2 = &X0; *D = &A; break;
+ case 0x3: *S1 = &Y1; *S2 = &X0; *D = &B; break;
+ case 0x4: *S1 = &X1; *S2 = &Y0; *D = &A; break;
+ case 0x5: *S1 = &X1; *S2 = &Y0; *D = &B; break;
+ case 0x6: *S1 = &X1; *S2 = &Y1; *D = &A; break;
+ case 0x7: *S1 = &X1; *S2 = &Y1; *D = &B; break;
+ }
+}
+
+static void decode_QQQF_table(dsp56k_core* cpustate, UINT16 QQQ, UINT16 F, void **S1, void **S2, void **D)
+{
+ UINT16 switchVal = (QQQ << 1) | F;
+
+ switch(switchVal)
+ {
+ case 0x0: *S1 = &X0; *S2 = &X0; *D = &A; break;
+ case 0x1: *S1 = &X0; *S2 = &X0; *D = &B; break;
+ case 0x2: *S1 = &X1; *S2 = &X0; *D = &A; break;
+ case 0x3: *S1 = &X1; *S2 = &X0; *D = &B; break;
+ case 0x4: *S1 = &A1; *S2 = &Y0; *D = &A; break;
+ case 0x5: *S1 = &A1; *S2 = &Y0; *D = &B; break;
+ case 0x6: *S1 = &B1; *S2 = &X0; *D = &A; break;
+ case 0x7: *S1 = &B1; *S2 = &X0; *D = &B; break;
+ case 0x8: *S1 = &Y0; *S2 = &X0; *D = &A; break;
+ case 0x9: *S1 = &Y0; *S2 = &X0; *D = &B; break;
+ case 0xa: *S1 = &Y1; *S2 = &X0; *D = &A; break;
+ case 0xb: *S1 = &Y1; *S2 = &X0; *D = &B; break;
+ case 0xc: *S1 = &Y0; *S2 = &X1; *D = &A; break;
+ case 0xd: *S1 = &Y0; *S2 = &X1; *D = &B; break;
+ case 0xe: *S1 = &Y1; *S2 = &X1; *D = &A; break;
+ case 0xf: *S1 = &Y1; *S2 = &X1; *D = &B; break;
+ }
+}
+
+static void decode_RR_table(dsp56k_core* cpustate, UINT16 RR, typed_pointer* ret)
+{
+ switch(RR)
+ {
+ case 0x00: ret->addr = &R0; ret->data_type = DT_WORD; break;
+ case 0x01: ret->addr = &R1; ret->data_type = DT_WORD; break;
+ case 0x02: ret->addr = &R2; ret->data_type = DT_WORD; break;
+ case 0x03: ret->addr = &R3; ret->data_type = DT_WORD; break;
+ }
+}
+
+static void decode_TT_table(dsp56k_core* cpustate, UINT16 TT, typed_pointer* ret)
+{
+ switch(TT)
+ {
+ case 0x00: ret->addr = &R0; ret->data_type = DT_WORD; break;
+ case 0x01: ret->addr = &R1; ret->data_type = DT_WORD; break;
+ case 0x02: ret->addr = &R2; ret->data_type = DT_WORD; break;
+ case 0x03: ret->addr = &R3; ret->data_type = DT_WORD; break;
+ }
+}
+
+
+static void decode_uuuuF_table(dsp56k_core* cpustate, UINT16 uuuu, UINT16 F, UINT8 add_sub_other, typed_pointer* src_ret, typed_pointer* dst_ret)
+{
+ UINT16 switchVal = (uuuu << 1) | F;
+
+ /* Unknown uuuuFs have been seen in the wild */
+ add_sub_other = OP_OTHER;
+ src_ret->addr = NULL; src_ret->data_type = DT_BYTE;
+ dst_ret->addr = NULL; dst_ret->data_type = DT_BYTE;
+
+ switch(switchVal)
+ {
+ case 0x00: add_sub_other = OP_ADD;
+ src_ret->addr = &X0; src_ret->data_type = DT_WORD;
+ dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x08: add_sub_other = OP_SUB;
+ src_ret->addr = &X0; src_ret->data_type = DT_WORD;
+ dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x01: add_sub_other = OP_ADD;
+ src_ret->addr = &X0; src_ret->data_type = DT_WORD;
+ dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x09: add_sub_other = OP_SUB;
+ src_ret->addr = &X0; src_ret->data_type = DT_WORD;
+ dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x02: add_sub_other = OP_ADD;
+ src_ret->addr = &Y0; src_ret->data_type = DT_WORD;
+ dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x0a: add_sub_other = OP_SUB;
+ src_ret->addr = &Y0; src_ret->data_type = DT_WORD;
+ dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x03: add_sub_other = OP_ADD;
+ src_ret->addr = &Y0; src_ret->data_type = DT_WORD;
+ dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x0b: add_sub_other = OP_SUB;
+ src_ret->addr = &Y0; src_ret->data_type = DT_WORD;
+ dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x04: add_sub_other = OP_ADD;
+ src_ret->addr = &X1; src_ret->data_type = DT_WORD;
+ dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x0c: add_sub_other = OP_SUB;
+ src_ret->addr = &X1; src_ret->data_type = DT_WORD;
+ dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x05: add_sub_other = OP_ADD;
+ src_ret->addr = &X1; src_ret->data_type = DT_WORD;
+ dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x0d: add_sub_other = OP_SUB;
+ src_ret->addr = &X1; src_ret->data_type = DT_WORD;
+ dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x06: add_sub_other = OP_ADD;
+ src_ret->addr = &Y1; src_ret->data_type = DT_WORD;
+ dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x0e: add_sub_other = OP_SUB;
+ src_ret->addr = &Y1; src_ret->data_type = DT_WORD;
+ dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x07: add_sub_other = OP_ADD;
+ src_ret->addr = &Y1; src_ret->data_type = DT_WORD;
+ dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x0f: add_sub_other = OP_SUB;
+ src_ret->addr = &Y1; src_ret->data_type = DT_WORD;
+ dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x18: add_sub_other = OP_ADD;
+ src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD;
+ dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x1a: add_sub_other = OP_SUB;
+ src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD;
+ dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x19: add_sub_other = OP_ADD;
+ src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD;
+ dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ case 0x1b: add_sub_other = OP_SUB;
+ src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD;
+ dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break;
+ }
+}
+
+static void decode_Z_table(dsp56k_core* cpustate, UINT16 Z, typed_pointer* ret)
+{
+ switch(Z)
+ {
+ /* Fixed as per the Family Manual addendum */
+ case 0x01: ret->addr = &A1; ret->data_type = DT_WORD; break;
+ case 0x00: ret->addr = &B1; ret->data_type = DT_WORD; break;
+ }
+}
+
+static void execute_m_table(dsp56k_core* cpustate, int x, UINT16 m)
+{
+ UINT16 *rX = 0x00 ;
+ UINT16 *nX = 0x00 ;
+
+ switch(x)
+ {
+ case 0x0: rX = &R0; nX = &N0; break;
+ case 0x1: rX = &R1; nX = &N1; break;
+ case 0x2: rX = &R2; nX = &N2; break;
+ case 0x3: rX = &R3; nX = &N3; break;
+ }
+
+ switch(m)
+ {
+ case 0x0: (*rX)++; break;
+ case 0x1: (*rX) = (*rX)+(*nX); break;
+ }
+}
+
+static void execute_mm_table(dsp56k_core* cpustate, UINT16 rnum, UINT16 mm)
+{
+ UINT16 *rX = NULL;
+ UINT16 *nX = NULL;
+
+ switch(rnum)
+ {
+ case 0x0: rX = &R0; nX = &N0; break;
+ case 0x1: rX = &R1; nX = &N1; break;
+ case 0x2: rX = &R2; nX = &N2; break;
+ case 0x3: fatalerror("Dsp56k: Error. execute_mm_table specified R3 as its first source!"); break;
+ }
+
+ switch(mm)
+ {
+ case 0x0: (*rX)++; R3++; break;
+ case 0x1: (*rX)++; R3 = R3 + N3; break;
+ case 0x2: (*rX) = (*rX) + (*nX); R3++; break;
+ case 0x3: (*rX) = (*rX) + (*nX); R3 = R3 + N3; break;
+ }
+}
+
+static void execute_MM_table(dsp56k_core* cpustate, UINT16 rnum, UINT16 MM)
+{
+ UINT16 *rX = 0x00 ;
+ UINT16 *nX = 0x00 ;
+
+ switch(rnum)
+ {
+ case 0x0: rX = &R0; nX = &N0; break;
+ case 0x1: rX = &R1; nX = &N1; break;
+ case 0x2: rX = &R2; nX = &N2; break;
+ case 0x3: rX = &R3; nX = &N3; break;
+ }
+
+ switch(MM)
+ {
+ case 0x0: /* do nothing */ break;
+ case 0x1: (*rX)++ ; break;
+ case 0x2: (*rX)-- ; break;
+ case 0x3: (*rX) = (*rX)+(*nX) ; break;
+ }
+}
+
+/* Returns R value */
+static UINT16 execute_q_table(dsp56k_core* cpustate, int RR, UINT16 q)
+{
+ UINT16 *rX = 0x0000;
+ UINT16 *nX = 0x0000;
+
+ switch(RR)
+ {
+ case 0x0: rX = &R0; nX = &N0; break;
+ case 0x1: rX = &R1; nX = &N1; break;
+ case 0x2: rX = &R2; nX = &N2; break;
+ case 0x3: rX = &R3; nX = &N3; break;
+ }
+
+ switch(q)
+ {
+ case 0x0: /* No permanent changes */ ; return (*rX)+(*nX);
+ case 0x1: (*rX)--; return (*rX); /* This one is special - it's a *PRE-decrement*! */
+ }
+
+ /* Should not get here */
+ fatalerror("dsp56k: execute_q_table did something impossible!");
+ return 0;
+}
+
+static void execute_z_table(dsp56k_core* cpustate, int RR, UINT16 z)
+{
+ UINT16 *rX = 0x00;
+ UINT16 *nX = 0x00;
+
+ switch(RR)
+ {
+ case 0x0: rX = &R0; nX = &N0; break;
+ case 0x1: rX = &R1; nX = &N1; break;
+ case 0x2: rX = &R2; nX = &N2; break;
+ case 0x3: rX = &R3; nX = &N3; break;
+ }
+
+ switch(z)
+ {
+ case 0x0: (*rX)--; break;
+ case 0x1: (*rX) = (*rX) + (*nX); break;
+ }
+}
+
+static UINT16 assemble_address_from_Pppppp_table(dsp56k_core* cpustate, UINT16 P, UINT16 ppppp)
+{
+ UINT16 destAddr = 0x00 ;
+
+ switch (P)
+ {
+ case 0x0: destAddr = ppppp; break; /* TODO: Does this really only address up to 0x32? */
+ case 0x1: destAddr = assemble_address_from_IO_short_address(cpustate, ppppp); break;
+ }
+
+ return destAddr ;
+}
+
+static UINT16 assemble_address_from_IO_short_address(dsp56k_core* cpustate, UINT16 pp)
+{
+ UINT16 fullAddy = 0xffe0;
+ fullAddy |= pp;
+ return fullAddy;
+}
+
+static UINT16 assemble_address_from_6bit_signed_relative_short_address(dsp56k_core* cpustate, UINT16 srs)
+{
+ UINT16 fullAddy = srs ;
+ if (fullAddy & 0x0020)
+ fullAddy |= 0xffc0 ;
+
+ return fullAddy ;
+}
+
+static void dsp56k_process_loop(dsp56k_core* cpustate)
+{
+ /* TODO: This might not work for dos nested in doForevers */
+ if (LF_bit(cpustate) && FV_bit(cpustate))
+ {
+ /* Do Forever*/
+ if (PC == LA)
+ {
+ LC--;
+
+ cpustate->ppc = PC;
+ PC = SSH;
+ }
+ }
+ else if (LF_bit(cpustate))
+ {
+ /* Do */
+ if (PC == LA)
+ {
+ if (LC == 1)
+ {
+ /* End of loop processing */
+ SR = SSL; /* TODO: A-83. I believe only the Loop Flag comes back here. And maybe the do forever bit too. */
+ SP--;
+
+ LA = SSH;
+ LC = SSL;
+ SP--;
+ }
+ else
+ {
+ LC--;
+ PC = SSH;
+ }
+ }
+ }
+}
+
+static void dsp56k_process_rep(dsp56k_core* cpustate, size_t repSize)
+{
+ if (cpustate->repFlag)
+ {
+ if (PC == cpustate->repAddr)
+ {
+ if (LC == 1)
+ {
+ /* End of rep processing */
+ LC = TEMP;
+ cpustate->repFlag = 0;
+ cpustate->repAddr = 0x0000;
+ }
+ else
+ {
+ LC--;
+ PC -= repSize; /* A little strange - rewind by the size of the rep'd op */
+ }
+ }
+ }
+}
+
+
+/***************************************************************************
+ Parallel Memory Ops
+***************************************************************************/
+/* Register to Register Data Move : 0100 IIII .... .... : A-132 */
+static void execute_register_to_register_data_move(dsp56k_core* cpustate, const UINT16 op, typed_pointer* d_register, UINT64* prev_accum_value)
+{
+ typed_pointer S = {NULL, DT_BYTE};
+ typed_pointer D = {NULL, DT_BYTE};
+
+ decode_IIII_table(cpustate, BITS(op,0x0f00), &S, &D, d_register->addr);
+
+ /* If the source is the same as the ALU destination, use the previous accumulator value */
+ if (d_register->addr == S.addr)
+ {
+ typed_pointer tempTP;
+ tempTP.addr = prev_accum_value;
+ tempTP.data_type = DT_LONG_WORD;
+ SetDestinationValue(tempTP, D);
+ }
+ else
+ {
+ SetDestinationValue(S, D);
+ }
+}
+
+/* Address Register Update : 0011 0zRR .... .... : A-135 */
+static void execute_address_register_update(dsp56k_core* cpustate, const UINT16 op, typed_pointer* d_register, UINT64* prev_accum_value)
+{
+ execute_z_table(cpustate, BITS(op,0x0300), BITS(op,0x0400));
+}
+
+/* X Memory Data Move : 1mRR HHHW .... .... : A-137 */
+static void execute_x_memory_data_move(dsp56k_core* cpustate, const UINT16 op, typed_pointer* d_register, UINT64* prev_accum_value)
+{
+ UINT16 W;
+ typed_pointer R = {NULL, DT_BYTE};
+ typed_pointer SD = {NULL, DT_BYTE};
+
+ W = BITS(op,0x0100);
+ decode_HHH_table(cpustate, BITS(op,0x0e00), &SD);
+ decode_RR_table(cpustate, BITS(op,0x3000),&R);
+
+ if (W)
+ {
+ /* From X:<ea> to SD */
+ UINT16 data = cpustate->data->read_word(ADDRESS(*((UINT16*)R.addr)));
+
+ typed_pointer tempTP;
+ tempTP.addr = &data;
+ tempTP.data_type = DT_WORD;
+
+ SetDestinationValue(tempTP, SD);
+ }
+ else
+ {
+ /* From SD to X:<ea> */
+ /* If the source is the same as the ALU destination, use the previous accumulator value */
+ if (d_register->addr == SD.addr)
+ {
+ typed_pointer tempTP;
+ tempTP.addr = prev_accum_value;
+ tempTP.data_type = DT_LONG_WORD;
+
+ SetDataMemoryValue(cpustate, tempTP, ADDRESS(*((UINT16*)R.addr))) ;
+ }
+ else
+ {
+ SetDataMemoryValue(cpustate, SD, ADDRESS(*((UINT16*)R.addr))) ;
+ }
+ }
+
+ execute_m_table(cpustate, BITS(op,0x3000), BITS(op,0x4000));
+}
+
+/* X Memory Data Move : 0101 HHHW .... .... : A-137 */
+/* NOTE: previous accumulator value is not needed since ^F1 is always the opposite accumulator */
+static void execute_x_memory_data_move2(dsp56k_core* cpustate, const UINT16 op, typed_pointer* d_register)
+{
+ UINT16 W;
+ UINT16* mem_offset = NULL;
+ typed_pointer SD = {NULL, DT_BYTE};
+
+ W = BITS(op,0x0100);
+ decode_HHH_table(cpustate, BITS(op,0x0e000), &SD);
+
+ if (d_register->addr == &A)
+ mem_offset = &B1;
+ else
+ mem_offset = &A1;
+
+ if (W)
+ {
+ /* Write D */
+ UINT16 value = cpustate->data->read_word(ADDRESS(*mem_offset));
+ typed_pointer tempV = {&value, DT_WORD};
+ SetDestinationValue(tempV, SD);
+ }
+ else
+ {
+ /* Read S */
+ SetDataMemoryValue(cpustate, SD, ADDRESS(*mem_offset));
+ }
+}
+
+/* X Memory Data Move With Short Displacement : 0000 0101 BBBB BBBB ---- HHHW .... .... : A-139 */
+static void execute_x_memory_data_move_with_short_displacement(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2)
+{
+ INT8 xx;
+ UINT8 W;
+ UINT16 memOffset;
+ typed_pointer SD = { NULL, DT_BYTE };
+
+ xx = (INT8)(op & 0x00ff);
+ W = BITS(op2,0x0100);
+ decode_HHH_table(cpustate, BITS(op2,0x0e00), &SD);
+
+ memOffset = R2 + (INT16)xx;
+
+ if (W)
+ {
+ /* Write D */
+ UINT16 tempData = cpustate->data->read_word(ADDRESS(memOffset));
+ typed_pointer temp_src = { (void*)&tempData, DT_WORD };
+ SetDestinationValue(temp_src, SD);
+ }
+ else
+ {
+ /* Read S */
+ UINT16 tempData = *((UINT16*)SD.addr);
+ typed_pointer temp_src = { (void*)&tempData, DT_WORD };
+ SetDataMemoryValue(cpustate, temp_src, ADDRESS(memOffset));
+ }
+}
+
+/* Dual X Memory Data Read : 011m mKKK .rr. .... : A-142*/
+static void execute_dual_x_memory_data_read(dsp56k_core* cpustate, const UINT16 op, typed_pointer* d_register)
+{
+ typed_pointer tempV;
+ UINT16 srcVal1 = 0x0000;
+ UINT16 srcVal2 = 0x0000;
+ typed_pointer R = {NULL, DT_BYTE};
+ typed_pointer D1 = {NULL, DT_BYTE};
+ typed_pointer D2 = {NULL, DT_BYTE};
+
+ decode_RR_table(cpustate, BITS(op,0x0060), &R);
+ decode_KKK_table(cpustate, BITS(op,0x0700), &D1, &D2, d_register->addr);
+
+ /* Can't do an R3 for S1 */
+ if (R.addr == &R3)
+ fatalerror("Dsp56k: Error. Dual x memory data read specified R3 as its first source!");
+
+ /* The note on A-142 is very interesting.
+ You can effectively access external memory in the last 64 bytes of X data memory! */
+ if (*((UINT16*)D2.addr) >= 0xffc0)
+ fatalerror("Dsp56k: Unimplemented access to external X Data Memory >= 0xffc0 in Dual X Memory Data Read.");
+
+ /* First memmove */
+ srcVal1 = cpustate->data->read_word(ADDRESS(*((UINT16*)R.addr)));
+ tempV.addr = &srcVal1;
+ tempV.data_type = DT_WORD;
+ SetDestinationValue(tempV, D1);
+
+ /* Second memmove */
+ srcVal2 = cpustate->data->read_word(ADDRESS(R3));
+ tempV.addr = &srcVal2;
+ tempV.data_type = DT_WORD;
+ SetDestinationValue(tempV, D2);
+
+ /* Touch up the R regs after all the moves */
+ execute_mm_table(cpustate, BITS(op,0x0060), BITS(op,0x1800));
+}
+
+/***************************************************************************
+ Helper Functions
+***************************************************************************/
+static UINT16 Dsp56kOpMask(UINT16 cur, UINT16 mask)
+{
+ int i ;
+
+ UINT16 retVal = (cur & mask) ;
+ UINT16 temp = 0x0000 ;
+ int offsetCount = 0 ;
+
+ /* Shift everything right, eliminating 'whitespace' */
+ for (i = 0; i < 16; i++)
+ {
+ if (mask & (0x1<<i)) /* If mask bit is non-zero */
+ {
+ temp |= (((retVal >> i) & 0x1) << offsetCount) ;
+ offsetCount++ ;
+ }
+ }
+
+ return temp ;
+}
+
+static void SetDestinationValue(typed_pointer source, typed_pointer dest)
+{
+ UINT64 destinationValue = 0 ;
+
+ switch(dest.data_type)
+ {
+ /* Copying to an 8-bit value */
+ case DT_BYTE:
+ switch(source.data_type)
+ {
+ /* From a ? */
+ case DT_BYTE: *((UINT8*)dest.addr) = (*((UINT8*) source.addr)) & 0xff; break;
+ case DT_WORD: *((UINT8*)dest.addr) = (*((UINT16*)source.addr)) & 0x00ff; break;
+ case DT_DOUBLE_WORD: *((UINT8*)dest.addr) = (*((UINT32*)source.addr)) & 0x000000ff; break;
+ case DT_LONG_WORD: *((UINT8*)dest.addr) = (*((UINT64*)source.addr)) & U64(0x00000000000000ff); break;
+ }
+ break ;
+
+ /* Copying to a 16-bit value */
+ case DT_WORD:
+ switch(source.data_type)
+ {
+ case DT_BYTE: *((UINT16*)dest.addr) = (*((UINT8*) source.addr)) & 0xff; break;
+ case DT_WORD: *((UINT16*)dest.addr) = (*((UINT16*)source.addr)) & 0xffff; break;
+ case DT_DOUBLE_WORD: *((UINT16*)dest.addr) = (*((UINT32*)source.addr)) & 0x0000ffff; break;
+ case DT_LONG_WORD: *((UINT16*)dest.addr) = (*((UINT64*)source.addr)) & U64(0x000000000000ffff); break; /* TODO: Shift limiter action! A-147 */
+ }
+ break ;
+
+ /* Copying to a 32-bit value */
+ case DT_DOUBLE_WORD:
+ switch(source.data_type)
+ {
+ case DT_BYTE: *((UINT32*)dest.addr) = (*((UINT8*) source.addr)) & 0xff; break;
+ case DT_WORD: *((UINT32*)dest.addr) = (*((UINT16*)source.addr)) & 0xffff; break;
+ case DT_DOUBLE_WORD: *((UINT32*)dest.addr) = (*((UINT32*)source.addr)) & 0xffffffff; break;
+ case DT_LONG_WORD: *((UINT32*)dest.addr) = (*((UINT64*)source.addr)) & U64(0x00000000ffffffff); break;
+ }
+ break ;
+
+ /* Copying to a 64-bit value */
+ case DT_LONG_WORD:
+ switch(source.data_type)
+ {
+ case DT_BYTE: *((UINT64*)dest.addr) = (*((UINT8*)source.addr)) & 0xff; break;
+
+ case DT_WORD: destinationValue = (*((UINT16*)source.addr)) << 16;
+ if (destinationValue & U64(0x0000000080000000))
+ destinationValue |= U64(0x000000ff00000000);
+ *((UINT64*)dest.addr) = (UINT64)destinationValue; break; /* Forget not, yon shift register */
+
+ case DT_DOUBLE_WORD: *((UINT64*)dest.addr) = (*((UINT32*)source.addr)) & 0xffffffff; break;
+ case DT_LONG_WORD: *((UINT64*)dest.addr) = (*((UINT64*)source.addr)) & U64(0x000000ffffffffff); break;
+ }
+ break ;
+ }
+}
+
+/* TODO: Wait-state timings! */
+static void SetDataMemoryValue(dsp56k_core* cpustate, typed_pointer source, UINT32 destinationAddr)
+{
+ switch(source.data_type)
+ {
+ case DT_BYTE: cpustate->data->write_word(destinationAddr, (UINT16)( (*((UINT8*) source.addr) & 0xff) ) ) ; break ;
+ case DT_WORD: cpustate->data->write_word(destinationAddr, (UINT16)( (*((UINT16*)source.addr) & 0xffff) ) ) ; break ;
+ case DT_DOUBLE_WORD: cpustate->data->write_word(destinationAddr, (UINT16)( (*((UINT32*)source.addr) & 0x0000ffff) ) ) ; break ;
+
+ /* !!! Is this universal ??? */
+ /* !!! Forget not, yon shift-limiter !!! */
+ case DT_LONG_WORD: cpustate->data->write_word(destinationAddr, (UINT16)( ((*((UINT64*)source.addr)) & U64(0x00000000ffff0000)) >> 16) ) ; break ;
+ }
+}
+
+/* TODO: Wait-state timings! */
+static void SetProgramMemoryValue(dsp56k_core* cpustate, typed_pointer source, UINT32 destinationAddr)
+{
+ switch(source.data_type)
+ {
+ case DT_BYTE: cpustate->program->write_word(destinationAddr, (UINT16)( (*((UINT8*) source.addr) & 0xff) ) ) ; break ;
+ case DT_WORD: cpustate->program->write_word(destinationAddr, (UINT16)( (*((UINT16*)source.addr) & 0xffff) ) ) ; break ;
+ case DT_DOUBLE_WORD: cpustate->program->write_word(destinationAddr, (UINT16)( (*((UINT32*)source.addr) & 0x0000ffff) ) ) ; break ;
+
+ /* !!! Is this universal ??? */
+ /* !!! Forget not, yon shift-limiter !!! */
+ case DT_LONG_WORD: cpustate->program->write_word(destinationAddr, (UINT16)( ((*((UINT64*)source.addr)) & U64(0x00000000ffff0000)) >> 16) ) ; break ;
+ }
+}
+
diff --git a/trunk/src/emu/cpu/dsp56k/dsp56pcu.c b/trunk/src/emu/cpu/dsp56k/dsp56pcu.c
new file mode 100644
index 00000000000..2460beb056c
--- /dev/null
+++ b/trunk/src/emu/cpu/dsp56k/dsp56pcu.c
@@ -0,0 +1,486 @@
+#include "dsp56pcu.h"
+#include "dsp56mem.h"
+
+namespace DSP56K
+{
+
+/* ************************************************************************* */
+/* Status Register */
+/* ************************************************************************* */
+/* MR CCR */
+/* |-------------------------------------| |-------------------------------| */
+/* | LF | FV | * | * | S1 | S0 | I1 | I0 | | S | L | E | U | N | Z | V | C | */
+/* |-------------------------------------| |-------------------------------| */
+/* */
+/* ************************************************************************* */
+UINT8 LF_bit(dsp56k_core* cpustate) { return (SR & 0x8000) >> 15; }
+UINT8 FV_bit(dsp56k_core* cpustate) { return (SR & 0x4000) >> 14; }
+// UINT8 S_bits(dsp56k_core* cpustate) { return (SR & 0x0c00) >> 10; }
+UINT8 I_bits(dsp56k_core* cpustate) { return (SR & 0x0300) >> 8; }
+UINT8 S_bit (dsp56k_core* cpustate) { return (SR & 0x0080) >> 7; }
+UINT8 L_bit (dsp56k_core* cpustate) { return (SR & 0x0040) >> 6; }
+UINT8 E_bit (dsp56k_core* cpustate) { return (SR & 0x0020) >> 5; }
+UINT8 U_bit (dsp56k_core* cpustate) { return (SR & 0x0010) >> 4; }
+UINT8 N_bit (dsp56k_core* cpustate) { return (SR & 0x0008) >> 3; }
+UINT8 Z_bit (dsp56k_core* cpustate) { return (SR & 0x0004) >> 2; }
+UINT8 V_bit (dsp56k_core* cpustate) { return (SR & 0x0002) >> 1; }
+UINT8 C_bit (dsp56k_core* cpustate) { return (SR & 0x0001) >> 0; }
+
+/* MR setters */
+void LF_bit_set(dsp56k_core* cpustate, UINT8 value) { if (value) (SR |= 0x8000); else (SR &= (~0x8000)); }
+void FV_bit_set(dsp56k_core* cpustate, UINT8 value) { if (value) (SR |= 0x4000); else (SR &= (~0x4000)); }
+void S_bits_set(dsp56k_core* cpustate, UINT8 value) { value = value & 0x03; SR &= ~(0x0c00); SR |= (value << 10); }
+void I_bits_set(dsp56k_core* cpustate, UINT8 value) { value = value & 0x03; SR &= ~(0x0300); SR |= (value << 8); }
+
+/* CCR setters */
+void S_bit_set(dsp56k_core* cpustate, UINT8 value) { if (value) (SR |= 0x0080); else (SR &= (~0x0080)); }
+void L_bit_set(dsp56k_core* cpustate, UINT8 value) { if (value) (SR |= 0x0040); else (SR &= (~0x0040)); }
+void E_bit_set(dsp56k_core* cpustate, UINT8 value) { if (value) (SR |= 0x0020); else (SR &= (~0x0020)); }
+void U_bit_set(dsp56k_core* cpustate, UINT8 value) { if (value) (SR |= 0x0010); else (SR &= (~0x0010)); }
+void N_bit_set(dsp56k_core* cpustate, UINT8 value) { if (value) (SR |= 0x0008); else (SR &= (~0x0008)); }
+void Z_bit_set(dsp56k_core* cpustate, UINT8 value) { if (value) (SR |= 0x0004); else (SR &= (~0x0004)); }
+void V_bit_set(dsp56k_core* cpustate, UINT8 value) { if (value) (SR |= 0x0002); else (SR &= (~0x0002)); }
+void C_bit_set(dsp56k_core* cpustate, UINT8 value) { if (value) (SR |= 0x0001); else (SR &= (~0x0001)); }
+
+
+
+/* ************************************************************************* */
+/* Operating Mode Register */
+/* ************************************************************************* */
+/* */
+/* |---------------------------------------------------------------------| */
+/* | * | * | * | * | * | * | * | * | CD | SD | R | SA | * | MC | MB | MA | */
+/* |---------------------------------------------------------------------| */
+/* */
+/* ************************************************************************* */
+// UINT8 CD_bit(dsp56k_core* cpustate) { return ((OMR & 0x0080) != 0); }
+// UINT8 SD_bit(dsp56k_core* cpustate) { return ((OMR & 0x0040) != 0); }
+// UINT8 R_bit(dsp56k_core* cpustate) { return ((OMR & 0x0020) != 0); }
+// UINT8 SA_bit(dsp56k_core* cpustate) { return ((OMR & 0x0010) != 0); }
+// UINT8 MC_bit(dsp56k_core* cpustate) { return ((OMR & 0x0004) != 0); }
+UINT8 MB_bit(dsp56k_core* cpustate) { return ((OMR & 0x0002) != 0); }
+UINT8 MA_bit(dsp56k_core* cpustate) { return ((OMR & 0x0001) != 0); }
+
+void CD_bit_set(dsp56k_core* cpustate, UINT8 value) { if (value) (OMR |= 0x0080); else (OMR &= (~0x0080)); }
+void SD_bit_set(dsp56k_core* cpustate, UINT8 value) { if (value) (OMR |= 0x0040); else (OMR &= (~0x0040)); }
+void R_bit_set(dsp56k_core* cpustate, UINT8 value) { if (value) (OMR |= 0x0020); else (OMR &= (~0x0020)); }
+void SA_bit_set(dsp56k_core* cpustate, UINT8 value) { if (value) (OMR |= 0x0010); else (OMR &= (~0x0010)); }
+void MC_bit_set(dsp56k_core* cpustate, UINT8 value) { if (value) (OMR |= 0x0004); else (OMR &= (~0x0004)); }
+void MB_bit_set(dsp56k_core* cpustate, UINT8 value) { if (value) (OMR |= 0x0002); else (OMR &= (~0x0002)); }
+void MA_bit_set(dsp56k_core* cpustate, UINT8 value) { if (value) (OMR |= 0x0001); else (OMR &= (~0x0001)); }
+
+UINT8 dsp56k_operating_mode(dsp56k_core* cpustate)
+{
+ return ((MB_bit(cpustate) << 1) | MA_bit(cpustate));
+}
+
+
+
+/* ************************************************************************* */
+/* Stack Pointer */
+/* ************************************************************************* */
+/* */
+/* |---------------------------------------------------------------------| */
+/* | * | * | * | * | * | * | * | * | * | * | UF | SE | P3 | P2 | P1 | P0 | */
+/* |---------------------------------------------------------------------| */
+/* */
+/* ************************************************************************* */
+UINT8 UF_bit(dsp56k_core* cpustate) { return ((SP & 0x0020) != 0); }
+UINT8 SE_bit(dsp56k_core* cpustate) { return ((SP & 0x0010) != 0); }
+
+//void UF_bit_set(dsp56k_core* cpustate, UINT8 value) {};
+//void SE_bit_set(dsp56k_core* cpustate, UINT8 value) {};
+
+
+
+/***************************************************************************
+ INITIALIZATION AND RESET
+***************************************************************************/
+void pcu_init(dsp56k_core* cpustate, device_t *device)
+{
+ /* Init the irq table */
+ dsp56k_irq_table_init();
+
+ /* save states - dsp56k_pcu members */
+ device->save_item(NAME(cpustate->PCU.pc));
+ device->save_item(NAME(cpustate->PCU.la));
+ device->save_item(NAME(cpustate->PCU.lc));
+ device->save_item(NAME(cpustate->PCU.sr));
+ device->save_item(NAME(cpustate->PCU.omr));
+ device->save_item(NAME(cpustate->PCU.sp));
+ device->save_item(NAME(cpustate->PCU.ss));
+ device->save_item(NAME(cpustate->PCU.pending_interrupts));
+ device->save_item(NAME(cpustate->PCU.reset_vector));
+}
+
+void pcu_reset(dsp56k_core* cpustate)
+{
+ int i;
+
+ /* When reset is deasserted, set MA, MB, and MC from MODA, MODB, and MODC lines. */
+ MA_bit_set(cpustate, cpustate->modA_state);
+ MB_bit_set(cpustate, cpustate->modB_state);
+ MC_bit_set(cpustate, cpustate->modC_state);
+
+ /* Reset based on the operating mode. */
+ switch(dsp56k_operating_mode(cpustate))
+ {
+ case 0x00:
+ logerror("Dsp56k in Special Bootstrap Mode 1\n");
+
+ /* HACK - We don't need to put the bootstrap mode on here since */
+ /* we'll simulate it entirely in this function */
+ cpustate->bootstrap_mode = BOOTSTRAP_OFF;
+
+ /* HACK - Simply copy over 0x1000 bytes of data located at program memory 0xc000. */
+ /* This, in actuality, is handled with the internal boot ROM. */
+ for (i = 0; i < 0x800; i++)
+ {
+ UINT32 mem_offset = (0xc000<<1) + (i<<1); /* TODO: TEST */
+
+ /* TODO - DO I HAVE TO FLIP THIS WORD? */
+ /* P:$c000 -> Internal P:$0000 low byte */
+ /* P:$c001 -> Internal P:$0000 high byte */
+ /* ... */
+ /* P:$cffe -> Internal P:$07ff low byte */
+ /* P:$cfff -> Internal P:$07ff high byte */
+ UINT8 mem_value_low = cpustate->program->read_byte(mem_offset); /* TODO: IS THIS READING RIGHT? */
+ UINT8 mem_value_high = cpustate->program->read_byte(mem_offset);
+ cpustate->program_ram[i] = (mem_value_high << 8) || mem_value_low;
+ }
+
+ /* HACK - Set the PC to 0x0000 as per the boot ROM. */
+ PC = 0x0000;
+
+ /* HACK - All done! Set the Operating Mode to 2 as per the boot ROM. */
+ MB_bit_set(cpustate, 1);
+ MA_bit_set(cpustate, 0);
+ cpustate->PCU.reset_vector = 0xe000;
+ break;
+
+ case 0x01:
+ logerror("Dsp56k in Special Bootstrap Mode 2\n");
+
+ /* HACK - Turn bootstrap mode on. This hijacks the CPU execute loop and lets */
+ /* Either the host interface or the SSIO interface suck in all the data */
+ /* they need. Once they've had their fill, they turn bootstrap mode off */
+ /* and the CPU begins execution at 0x0000; */
+ /* HACK - Read bit 15 at 0xc000 to see if we're working with the SSIO or host interface. */
+ if (cpustate->program->read_word(0xc000<<1) & 0x8000)
+ {
+ cpustate->bootstrap_mode = BOOTSTRAP_SSIX;
+ logerror("DSP56k : Currently in (hacked) bootstrap mode - reading from SSIx.\n");
+ }
+ else
+ {
+ cpustate->bootstrap_mode = BOOTSTRAP_HI;
+ logerror("DSP56k : Currently in (hacked) bootstrap mode - reading from Host Interface.\n");
+ }
+
+ /* HACK - Set the PC to 0x0000 as per the boot ROM. */
+ PC = 0x0000;
+
+ /* HACK - Not done yet, but set the Operating Mode to 2 in preparation. */
+ MB_bit_set(cpustate, 1);
+ MA_bit_set(cpustate, 0);
+ cpustate->PCU.reset_vector = 0xe000;
+ break;
+
+ case 0x02:
+ logerror("Dsp56k in Normal Expanded Mode\n");
+ PC = 0xe000;
+ cpustate->PCU.reset_vector = 0xe000;
+ break;
+
+ case 0x03:
+ logerror("Dsp56k in Development Expanded Mode\n");
+ /* TODO: Disable internal ROM, etc. Likely a tricky thing for MAME? */
+ PC = 0x0000;
+ cpustate->PCU.reset_vector = 0x0000;
+ break;
+ }
+
+ /* Set registers properly */
+ /* 1-17 Clear Interrupt Priority Register (IPR) */
+ IPR = 0x0000;
+
+ /* FM.5-4 */
+ I_bits_set(cpustate, 0x03);
+ S_bits_set(cpustate, 0);
+ L_bit_set(cpustate, 0);
+ S_bit_set(cpustate, 0);
+ FV_bit_set(cpustate, 0);
+
+ /* FM.7-25 */
+ E_bit_set(cpustate, 0);
+ U_bit_set(cpustate, 0);
+ N_bit_set(cpustate, 0);
+ V_bit_set(cpustate, 0);
+ Z_bit_set(cpustate, 0);
+
+ /* FM.5-4+ */
+ C_bit_set(cpustate, 0);
+ LF_bit_set(cpustate, 0);
+ SP = 0x0000;
+
+ /* FM.5-14 (OMR) */
+ SA_bit_set(cpustate, 0);
+ R_bit_set(cpustate, 0);
+ SD_bit_set(cpustate, 0);
+ CD_bit_set(cpustate, 0);
+
+ /* Clear out the pending interrupt list */
+ dsp56k_clear_pending_interrupts(cpustate);
+}
+
+/***************************************************************************
+ INTERRUPT HANDLING
+***************************************************************************/
+typedef struct
+{
+ UINT16 irq_vector;
+ char irq_source[128];
+} dsp56k_irq_data;
+
+dsp56k_irq_data dsp56k_interrupt_sources[32];
+
+/* TODO: Figure out how to switch on level versus edge-triggered. */
+void pcu_service_interrupts(dsp56k_core* cpustate)
+{
+ int i;
+
+ /* Count list of pending interrupts */
+ int num_servicable = dsp56k_count_pending_interrupts(cpustate);
+
+ if (num_servicable == 0)
+ return;
+
+ /* Sort list according to priority */
+ dsp56k_sort_pending_interrupts(cpustate, num_servicable);
+
+ /* Service each interrupt in order */
+ /* TODO: This just *can't* be right :) */
+ for (i = 0; i < num_servicable; i++)
+ {
+ const int interrupt_index = cpustate->PCU.pending_interrupts[i];
+
+ /* Get the priority of the interrupt - a return value of -1 means disabled! */
+ INT8 priority = dsp56k_get_irq_priority(cpustate, interrupt_index);
+
+ /* 1-12 Make sure you're not masked out against the Interrupt Mask Bits (disabled is handled for free here) */
+ if (priority >= I_bits(cpustate))
+ {
+ /* TODO: Implement long interrupts & fast interrupts correctly! */
+ /* Right now they are handled in the JSR & BSR ops. SupahLame. */
+ cpustate->ppc = PC;
+
+ /* Are you anything but the Host Command interrupt? */
+ if (interrupt_index != 22)
+ {
+ /* Execute a normal interrupt */
+ PC = dsp56k_interrupt_sources[interrupt_index].irq_vector;
+ }
+ else
+ {
+ /* The host command input has a floating vector. */
+ const UINT16 irq_vector = HV_bits(cpustate) << 1;
+
+ PC = irq_vector;
+
+ /* TODO: 5-9 5-11 Gotta' Clear HC (HCP gets it too) when taking this exception! */
+ HC_bit_set(cpustate, 0);
+ }
+ }
+ }
+
+ dsp56k_clear_pending_interrupts(cpustate);
+}
+
+
+/* Register an interrupt */
+void dsp56k_add_pending_interrupt(dsp56k_core* cpustate, const char* name)
+{
+ int i;
+ int irq_index = dsp56k_get_irq_index_by_tag(name);
+
+ for (i = 0; i < 32; i++)
+ {
+ if (cpustate->PCU.pending_interrupts[i] == -1)
+ {
+ cpustate->PCU.pending_interrupts[i] = irq_index;
+ break;
+ }
+ }
+}
+
+/* Utility function to construct IRQ table */
+void dsp56k_set_irq_source(UINT8 irq_num, UINT16 iv, const char* source)
+{
+ dsp56k_interrupt_sources[irq_num].irq_vector = iv;
+ strcpy(dsp56k_interrupt_sources[irq_num].irq_source, source);
+}
+
+/* Construct a table containing pertient IRQ information */
+void dsp56k_irq_table_init(void)
+{
+ /* 1-14 + 1-18 */
+ /* TODO: Cull host command stuff appropriately */
+ /* array index . vector . token */
+ dsp56k_set_irq_source(0, 0x0000, "Hardware RESET");
+ dsp56k_set_irq_source(1, 0x0002, "Illegal Instruction");
+ dsp56k_set_irq_source(2, 0x0004, "Stack Error");
+ dsp56k_set_irq_source(3, 0x0006, "Reserved");
+ dsp56k_set_irq_source(4, 0x0008, "SWI");
+ dsp56k_set_irq_source(5, 0x000a, "IRQA");
+ dsp56k_set_irq_source(6, 0x000c, "IRQB");
+ dsp56k_set_irq_source(7, 0x000e, "Reserved");
+ dsp56k_set_irq_source(8, 0x0010, "SSI0 Receive Data with Exception");
+ dsp56k_set_irq_source(9, 0x0012, "SSI0 Receive Data");
+ dsp56k_set_irq_source(10, 0x0014, "SSI0 Transmit Data with Exception");
+ dsp56k_set_irq_source(11, 0x0016, "SSI0 Transmit Data");
+ dsp56k_set_irq_source(12, 0x0018, "SSI1 Receive Data with Exception");
+ dsp56k_set_irq_source(13, 0x001a, "SSI1 Receive Data");
+ dsp56k_set_irq_source(14, 0x001c, "SSI1 Transmit Data with Exception");
+ dsp56k_set_irq_source(15, 0x001e, "SSI1 Transmit Data");
+ dsp56k_set_irq_source(16, 0x0020, "Timer Overflow");
+ dsp56k_set_irq_source(17, 0x0022, "Timer Compare");
+ dsp56k_set_irq_source(18, 0x0024, "Host DMA Receive Data");
+ dsp56k_set_irq_source(19, 0x0026, "Host DMA Transmit Data");
+ dsp56k_set_irq_source(20, 0x0028, "Host Receive Data");
+ dsp56k_set_irq_source(21, 0x002a, "Host Transmit Data");
+ dsp56k_set_irq_source(22, 0x002c, "Host Command"); /* Default vector for the host command */
+ dsp56k_set_irq_source(23, 0x002e, "Codec Receive/Transmit");
+ dsp56k_set_irq_source(24, 0x0030, "Host Command 1");
+ dsp56k_set_irq_source(25, 0x0032, "Host Command 2");
+ dsp56k_set_irq_source(26, 0x0034, "Host Command 3");
+ dsp56k_set_irq_source(27, 0x0036, "Host Command 4");
+ dsp56k_set_irq_source(28, 0x0038, "Host Command 5");
+ dsp56k_set_irq_source(29, 0x003a, "Host Command 6");
+ dsp56k_set_irq_source(30, 0x003c, "Host Command 7");
+ dsp56k_set_irq_source(31, 0x003e, "Host Command 8");
+}
+
+/* Clear all entries from the pending table */
+void dsp56k_clear_pending_interrupts(dsp56k_core* cpustate)
+{
+ int i;
+ for (i = 0; i < 32; i++)
+ {
+ cpustate->PCU.pending_interrupts[i] = -1;
+ }
+}
+
+/* Recover number of pending irqs */
+int dsp56k_count_pending_interrupts(dsp56k_core* cpustate)
+{
+ int numI = 0;
+ while (cpustate->PCU.pending_interrupts[numI] != -1)
+ {
+ numI++;
+ }
+
+ return numI;
+}
+
+/* Sort the pending irqs by priority */
+void dsp56k_sort_pending_interrupts(dsp56k_core* cpustate, int num)
+{
+ int i, j;
+
+ /* We're going to be sorting the priorities */
+ int priority_list[32];
+ for (i = 0; i < num; i++)
+ {
+ priority_list[i] = dsp56k_get_irq_priority(cpustate, cpustate->PCU.pending_interrupts[i]);
+ }
+
+ /* Bubble sort should be good enough for us */
+ for (i = 0; i < num; i++)
+ {
+ for(j = 0; j < num-1; j++)
+ {
+ if (priority_list[j] > priority_list[j+1])
+ {
+ int holder;
+
+ /* Swap priorities */
+ holder = priority_list[j+1];
+ priority_list[j+1] = priority_list[j];
+ priority_list[j] = holder;
+
+ /* Swap irq indices. */
+ holder = cpustate->PCU.pending_interrupts[j+1];
+ cpustate->PCU.pending_interrupts[j+1] = cpustate->PCU.pending_interrupts[j];
+ cpustate->PCU.pending_interrupts[j] = holder;
+ }
+ }
+ }
+
+ /* TODO: 1-17 Now sort each of the priority levels within their categories. */
+}
+
+/* Given an index into the irq table, return the interrupt's current priority */
+INT8 dsp56k_get_irq_priority(dsp56k_core* cpustate, int index)
+{
+ /* 1-12 */
+ switch (index)
+ {
+ /* Non-maskable */
+ case 0: return 3; /* Hardware RESET */
+ case 1: return 3; /* Illegal Instruction */
+ case 2: return 3; /* Stack Error */
+ case 3: return 3; /* Reserved */
+ case 4: return 3; /* SWI */
+
+ /* Poll the IPR for these guys. */
+ case 5: return irqa_ipl(cpustate); /* IRQA */
+ case 6: return irqb_ipl(cpustate); /* IRQB */
+ case 7: return -1; /* Reserved */
+ case 8: return ssi0_ipl(cpustate); /* SSI0 Receive Data with Exception */
+ case 9: return ssi0_ipl(cpustate); /* SSI0 Receive Data */
+ case 10: return ssi0_ipl(cpustate); /* SSI0 Transmit Data with Exception */
+ case 11: return ssi0_ipl(cpustate); /* SSI0 Transmit Data */
+ case 12: return ssi1_ipl(cpustate); /* SSI1 Receive Data with Exception */
+ case 13: return ssi1_ipl(cpustate); /* SSI1 Receive Data */
+ case 14: return ssi1_ipl(cpustate); /* SSI1 Transmit Data with Exception */
+ case 15: return ssi1_ipl(cpustate); /* SSI1 Transmit Data */
+ case 16: return tm_ipl(cpustate); /* Timer Overflow */
+ case 17: return tm_ipl(cpustate); /* Timer Compare */
+ case 18: return host_ipl(cpustate); /* Host DMA Receive Data */
+ case 19: return host_ipl(cpustate); /* Host DMA Transmit Data */
+ case 20: return host_ipl(cpustate); /* Host Receive Data */
+ case 21: return host_ipl(cpustate); /* Host Transmit Data */
+ case 22: return host_ipl(cpustate); /* Host Command 0 (Default) */
+ case 23: return codec_ipl(cpustate); /* Codec Receive/Transmit */
+ case 24: return host_ipl(cpustate); /* Host Command 1 // TODO: Are all host ipl's the same? */
+ case 25: return host_ipl(cpustate); /* Host Command 2 */
+ case 26: return host_ipl(cpustate); /* Host Command 3 */
+ case 27: return host_ipl(cpustate); /* Host Command 4 */
+ case 28: return host_ipl(cpustate); /* Host Command 5 */
+ case 29: return host_ipl(cpustate); /* Host Command 6 */
+ case 30: return host_ipl(cpustate); /* Host Command 7 */
+ case 31: return host_ipl(cpustate); /* Host Command 8 */
+
+ default: break;
+ }
+
+ return -1;
+}
+
+/* Given an IRQ name, return its index in the irq table */
+int dsp56k_get_irq_index_by_tag(const char* tag)
+{
+ int i;
+ for (i = 0; i < 32; i++)
+ {
+ if (strcmp(tag, dsp56k_interrupt_sources[i].irq_source) == 0)
+ {
+ return i;
+ }
+ }
+
+ fatalerror("DSP56K ERROR : IRQ TAG specified incorrectly (get_vector_by_tag) : %s.\n", tag);
+ return -1;
+}
+
+} // namespace DSP56K
diff --git a/trunk/src/emu/cpu/dsp56k/dsp56pcu.h b/trunk/src/emu/cpu/dsp56k/dsp56pcu.h
new file mode 100644
index 00000000000..b7e72a1e5f9
--- /dev/null
+++ b/trunk/src/emu/cpu/dsp56k/dsp56pcu.h
@@ -0,0 +1,149 @@
+#ifndef __DSP56_PCU_H__
+#define __DSP56_PCU_H__
+
+#include "dsp56k.h"
+
+namespace DSP56K
+{
+
+/***************************************************************************
+ PCU
+***************************************************************************/
+void pcu_reset(dsp56k_core* cpustate);
+void pcu_init(dsp56k_core* cpustate, device_t *device);
+#define PC (cpustate->PCU.pc)
+#define LA (cpustate->PCU.la)
+#define LC (cpustate->PCU.lc)
+#define SR (cpustate->PCU.sr)
+#define OMR (cpustate->PCU.omr)
+#define SP (cpustate->PCU.sp)
+#define SS (cpustate->PCU.ss)
+
+#define SSH (SS[SP].w.h)
+#define SSL (SS[SP].w.l)
+
+#define ST0 (SS[0].d)
+#define ST1 (SS[1].d)
+#define ST2 (SS[2].d)
+#define ST3 (SS[3].d)
+#define ST4 (SS[4].d)
+#define ST5 (SS[5].d)
+#define ST6 (SS[6].d)
+#define ST7 (SS[7].d)
+#define ST8 (SS[8].d)
+#define ST9 (SS[9].d)
+#define ST10 (SS[10].d)
+#define ST11 (SS[11].d)
+#define ST12 (SS[12].d)
+#define ST13 (SS[13].d)
+#define ST14 (SS[14].d)
+#define ST15 (SS[15].d)
+
+/* STATUS REGISTER (SR) BITS (1-25) */
+/* MR */
+UINT8 LF_bit(dsp56k_core* cpustate);
+UINT8 FV_bit(dsp56k_core* cpustate);
+//UINT8 S_bits(dsp56k_core* cpustate);
+UINT8 I_bits(dsp56k_core* cpustate);
+
+/* CCR - with macros for easy access */
+#define S() (S_bit(cpustate))
+UINT8 S_bit(dsp56k_core* cpustate);
+#define L() (L_bit(cpustate))
+UINT8 L_bit(dsp56k_core* cpustate);
+#define E() (E_bit(cpustate))
+UINT8 E_bit(dsp56k_core* cpustate);
+#define U() (U_bit(cpustate))
+UINT8 U_bit(dsp56k_core* cpustate);
+#define N() (N_bit(cpustate))
+UINT8 N_bit(dsp56k_core* cpustate);
+#define Z() (Z_bit(cpustate))
+UINT8 Z_bit(dsp56k_core* cpustate);
+#define V() (V_bit(cpustate))
+UINT8 V_bit(dsp56k_core* cpustate);
+#define C() (C_bit(cpustate))
+UINT8 C_bit(dsp56k_core* cpustate);
+
+/* MR setters */
+void LF_bit_set(dsp56k_core* cpustate, UINT8 value);
+void FV_bit_set(dsp56k_core* cpustate, UINT8 value);
+void S_bits_set(dsp56k_core* cpustate, UINT8 value);
+void I_bits_set(dsp56k_core* cpustate, UINT8 value);
+
+/* CCR setters - with macros for easy access */
+#define DSP56K_S_SET() (S_bit_set(cpustate, 1))
+#define DSP56K_S_CLEAR() (S_bit_set(cpustate, 0))
+void S_bit_set(dsp56k_core* cpustate, UINT8 value);
+#define DSP56K_L_SET() (L_bit_set(cpustate, 1))
+#define DSP56K_L_CLEAR() (L_bit_set(cpustate, 0))
+void L_bit_set(dsp56k_core* cpustate, UINT8 value);
+#define DSP56K_E_SET() (E_bit_set(cpustate, 1))
+#define DSP56K_E_CLEAR() (E_bit_set(cpustate, 0))
+void E_bit_set(dsp56k_core* cpustate, UINT8 value);
+#define DSP56K_U_SET() (U_bit_set(cpustate, 1))
+#define DSP56K_U_CLEAR() (U_bit_set(cpustate, 0))
+void U_bit_set(dsp56k_core* cpustate, UINT8 value);
+#define DSP56K_N_SET() (N_bit_set(cpustate, 1))
+#define DSP56K_N_CLEAR() (N_bit_set(cpustate, 0))
+void N_bit_set(dsp56k_core* cpustate, UINT8 value);
+#define DSP56K_Z_SET() (Z_bit_set(cpustate, 1))
+#define DSP56K_Z_CLEAR() (Z_bit_set(cpustate, 0))
+void Z_bit_set(dsp56k_core* cpustate, UINT8 value);
+#define DSP56K_V_SET() (V_bit_set(cpustate, 1))
+#define DSP56K_V_CLEAR() (V_bit_set(cpustate, 0))
+void V_bit_set(dsp56k_core* cpustate, UINT8 value);
+#define DSP56K_C_SET() (C_bit_set(cpustate, 1))
+#define DSP56K_C_CLEAR() (C_bit_set(cpustate, 0))
+void C_bit_set(dsp56k_core* cpustate, UINT8 value);
+
+// TODO: Maybe some functions for Interrupt Mask and Scaling Mode go here?
+
+
+/* 1-28 OPERATING MODE REGISTER (OMR) BITS */
+//UINT8 CD_bit(dsp56k_core* cpustate);
+//UINT8 SD_bit(dsp56k_core* cpustate);
+//UINT8 R_bit(dsp56k_core* cpustate);
+//UINT8 SA_bit(dsp56k_core* cpustate);
+//UINT8 MC_bit(dsp56k_core* cpustate);
+UINT8 MB_bit(dsp56k_core* cpustate);
+UINT8 MA_bit(dsp56k_core* cpustate);
+
+void CD_bit_set(dsp56k_core* cpustate, UINT8 value);
+void SD_bit_set(dsp56k_core* cpustate, UINT8 value);
+void R_bit_set(dsp56k_core* cpustate, UINT8 value);
+void SA_bit_set(dsp56k_core* cpustate, UINT8 value);
+void MC_bit_set(dsp56k_core* cpustate, UINT8 value);
+void MB_bit_set(dsp56k_core* cpustate, UINT8 value);
+void MA_bit_set(dsp56k_core* cpustate, UINT8 value);
+
+/* 1-27 STACK POINTER (SP) BITS */
+UINT8 UF_bit(dsp56k_core* cpustate);
+UINT8 SE_bit(dsp56k_core* cpustate);
+
+//void UF_bit_set(dsp56k_core* cpustate, UINT8 value) {};
+//void SE_bit_set(dsp56k_core* cpustate, UINT8 value) {};
+
+
+// HACK - Bootstrap modes
+#define BOOTSTRAP_OFF (0)
+#define BOOTSTRAP_SSIX (1)
+#define BOOTSTRAP_HI (2)
+
+
+/* PCU IRQ goodies */
+void pcu_service_interrupts(dsp56k_core* cpustate);
+
+void dsp56k_irq_table_init(void);
+void dsp56k_set_irq_source(UINT8 irq_num, UINT16 iv, const char* source);
+int dsp56k_get_irq_index_by_tag(const char* tag);
+
+void dsp56k_add_pending_interrupt(dsp56k_core* cpustate, const char* name); // Call me to add an interrupt to the queue
+
+void dsp56k_clear_pending_interrupts(dsp56k_core* cpustate);
+int dsp56k_count_pending_interrupts(dsp56k_core* cpustate);
+void dsp56k_sort_pending_interrupts(dsp56k_core* cpustate, int num);
+INT8 dsp56k_get_irq_priority(dsp56k_core* cpustate, int index);
+
+} // namespace DSP56K
+
+#endif
diff --git a/trunk/src/emu/cpu/dsp56k/inst.c b/trunk/src/emu/cpu/dsp56k/inst.c
new file mode 100644
index 00000000000..c2d1e81df46
--- /dev/null
+++ b/trunk/src/emu/cpu/dsp56k/inst.c
@@ -0,0 +1,786 @@
+#include "inst.h"
+#include "emu.h"
+
+namespace DSP56K
+{
+
+// Factory
+Instruction* Instruction::decodeInstruction(const Opcode* opc,
+ const UINT16 word0,
+ const UINT16 word1,
+ bool shifted)
+{
+ UINT16 w0 = word0;
+ UINT16 w1 = word1;
+
+ if (shifted)
+ {
+ w0 = w1;
+ w1 = 0x0000;
+ }
+
+ /**************************************************************************/
+ /* The very funky case of the XMemoryDataMoveWithShortDisplacement */
+ /**************************************************************************/
+ if ((w0 & 0xff00) == 0x0500)
+ {
+ // Avoid "05-- 05--" recursion
+ if (shifted) return NULL;
+
+ Instruction* op = decodeInstruction(opc, w0, w1, true);
+ if (op)
+ {
+ // This parallel move only works for certain trailing instructions.
+ if (dynamic_cast<Add*>(op) ||
+ dynamic_cast<Asr*>(op) ||
+ dynamic_cast<Eor*>(op) ||
+ dynamic_cast<Mac*>(op) ||
+ dynamic_cast<Macr*>(op) ||
+ dynamic_cast<Mpy*>(op) ||
+ dynamic_cast<Neg*>(op) ||
+ dynamic_cast<Sub*>(op) ||
+ dynamic_cast<Tfr*>(op) ||
+ dynamic_cast<Tst*>(op)
+ /* TODO: More? */)
+ {
+ op->m_sizeIncrement = 1;
+ return op;
+ }
+ }
+
+ global_free(op);
+ }
+
+
+ /**************************************************************************/
+ /* Dual X Memory Data Read : 011m mKKK .rr. .... : A-142 */
+ /* Quote: (MOVE, MAC(R), MPY(R), ADD, SUB, TFR) */
+ /**************************************************************************/
+ /* TFR : 011m mKKK 0rr1 F0DD : A-212 */
+ if ((w0 & 0xe094) == 0x6010)
+ {
+ return global_alloc(Tfr_2(opc, w0, w1));
+ }
+ /* MOVE : 011m mKKK 0rr1 0000 : A-128 */
+ if ((w0 & 0xe097) == 0x6017)
+ {
+ return global_alloc(Move_2(opc, w0, w1));
+ }
+ /* MAC : 011m mKKK 1xx0 F1QQ : A-122 */
+ else if ((w0 & 0xe094) == 0x6084)
+ {
+ return global_alloc(Mac_3(opc, w0, w1));
+ }
+ /* MACR: 011m mKKK 1--1 F1QQ : A-124 */
+ else if ((w0 & 0xe094) == 0x6094)
+ {
+ return global_alloc(Macr_2(opc, w0, w1));
+ }
+ /* MPY : 011m mKKK 1xx0 F0QQ : A-160 */
+ else if ((w0 & 0xe094) == 0x6080)
+ {
+ return global_alloc(Mpy_2(opc, w0, w1));
+ }
+ /* MPYR : 011m mKKK 1--1 F0QQ : A-162 */
+ else if ((w0 & 0xe094) == 0x6090)
+ {
+ return global_alloc(Mpyr_2(opc, w0, w1));
+ }
+ /* ADD : 011m mKKK 0rru Fuuu : A-22 */
+ /* SUB : 011m mKKK 0rru Fuuu : A-202 */
+ else if ((w0 & 0xe080) == 0x6000)
+ {
+ return global_alloc(Add_2(opc, w0, w1));
+ }
+
+ /****************************************************************************/
+ /* X Memory Data Write and Register Data Move : 0001 011k RRDD .... : A-140 */
+ /* Quote: (MPY or MAC) */
+ /****************************************************************************/
+ /* MPY : 0001 0110 RRDD FQQQ : A-160 */
+ else if ((w0 & 0xff00) == 0x1600)
+ {
+ return global_alloc(Mpy_3(opc, w0, w1));
+ }
+ /* MAC : 0001 0111 RRDD FQQQ : A-122 */
+ else if ((w0 & 0xff00) == 0x1700)
+ {
+ return global_alloc(Mac_3(opc, w0, w1));
+ }
+
+ /****************************************************************/
+ /* No Parallel Data Move : 0100 1010 .... .... : A-131 */
+ /* Register to Register Data Move : 0100 IIII .... .... : A-133 */
+ /* Address Register Update : 0011 0zRR .... .... : A-135 */
+ /* X Memory Data Move : 1mRR HHHW .... .... : A-137 */
+ /* X Memory Data Move : 0101 HHHW .... .... : A-137 */
+ /* Quote: (32 General parallel move instructions) */
+ /****************************************************************/
+ else if (((w0 & 0xff00) == 0x4a00) ||
+ ((w0 & 0xf000) == 0x4000) ||
+ ((w0 & 0xf800) == 0x3000) ||
+ ((w0 & 0x8000) == 0x8000) ||
+ ((w0 & 0xf000) == 0x5000))
+ {
+ /* Note: There is much overlap down here, so certain ops must come before others */
+
+ /* CLR : .... .... 0000 F001 : A-60 */
+ if ((w0 & 0x00f7) == 0x0001)
+ {
+ return global_alloc(Clr(opc, w0, w1));
+ }
+ /* ADD : .... .... 0000 FJJJ : A-22 */
+ else if ((w0 & 0x00f0) == 0x0000)
+ {
+ return global_alloc(Add(opc, w0, w1));
+ }
+
+ /* MOVE : .... .... 0001 0001 : A-128 */
+ else if ((w0 & 0x00ff) == 0x0011 || (w0 & 0x00ff) == 0x0019)
+ // NEW // else if ((w0 & 0x00ff) == 0x0011)
+ {
+ return global_alloc(Move(opc, w0, w1));
+ }
+ /* TFR : .... .... 0001 FJJJ : A-212 */
+ else if ((w0 & 0x00f0) == 0x0010)
+ {
+ return global_alloc(Tfr(opc, w0, w1));
+ }
+
+ /* RND : .... .... 0010 F000 : A-188 */
+ else if ((w0 & 0x00f7) == 0x0020)
+ {
+ return global_alloc(Rnd(opc, w0, w1));
+ }
+ /* TST : .... .... 0010 F001 : A-218 */
+ else if ((w0 & 0x00f7) == 0x0021)
+ {
+ return global_alloc(Tst(opc, w0, w1));
+ }
+ /* INC : .... .... 0010 F010 : A-104 */
+ else if ((w0 & 0x00f7) == 0x0022)
+ {
+ return global_alloc(Inc(opc, w0, w1));
+ }
+ /* INC24 : .... .... 0010 F011 : A-106 */
+ else if ((w0 & 0x00f7) == 0x0023)
+ {
+ return global_alloc(Inc24(opc, w0, w1));
+ }
+ /* OR : .... .... 0010 F1JJ : A-176 */
+ else if ((w0 & 0x00f4) == 0x0024)
+ {
+ return global_alloc(Or(opc, w0, w1));
+ }
+
+ /* ASR : .... .... 0011 F000 : A-32 */
+ else if ((w0 & 0x00f7) == 0x0030)
+ {
+ return global_alloc(Asr(opc, w0, w1));
+ }
+ /* ASL : .... .... 0011 F001 : A-28 */
+ else if ((w0 & 0x00f7) == 0x0031)
+ {
+ return global_alloc(Asl(opc, w0, w1));
+ }
+ /* LSR : .... .... 0011 F010 : A-120 */
+ else if ((w0 & 0x00f7) == 0x0032)
+ {
+ return global_alloc(Lsr(opc, w0, w1));
+ }
+ /* LSL : .... .... 0011 F011 : A-118 */
+ else if ((w0 & 0x00f7) == 0x0033)
+ {
+ return global_alloc(Lsl(opc, w0, w1));
+ }
+ /* EOR : .... .... 0011 F1JJ : A-94 */
+ else if ((w0 & 0x00f4) == 0x0034)
+ {
+ return global_alloc(Eor(opc, w0, w1));
+ }
+
+ /* SUBL : .... .... 0100 F001 : A-204 */
+ else if ((w0 & 0x00f7) == 0x0041)
+ {
+ return global_alloc(Subl(opc, w0, w1));
+ }
+ /* SUB : .... .... 0100 FJJJ : A-202 */
+ else if ((w0 & 0x00f0) == 0x0040)
+ {
+ return global_alloc(Sub(opc, w0, w1));
+ }
+
+ /* CLR24 : .... .... 0101 F001 : A-62 */
+ else if ((w0 & 0x00f7) == 0x0051)
+ {
+ return global_alloc(Clr24(opc, w0, w1));
+ }
+ /* SBC : .... .... 0101 F01J : A-198 */
+ else if ((w0 & 0x00f6) == 0x0052)
+ {
+ return global_alloc(Sbc(opc, w0, w1));
+ }
+ /* CMP : .... .... 0101 FJJJ : A-64 */
+ else if ((w0 & 0x00f0) == 0x0050)
+ {
+ return global_alloc(Cmp(opc, w0, w1));
+ }
+
+ /* NEG : .... .... 0110 F000 : A-166 */
+ else if ((w0 & 0x00f7) == 0x0060)
+ {
+ return global_alloc(Neg(opc, w0, w1));
+ }
+ /* NOT : .... .... 0110 F001 : A-174 */
+ else if ((w0 & 0x00f7) == 0x0061)
+ {
+ return global_alloc(Not(opc, w0, w1));
+ }
+ /* DEC : .... .... 0110 F010 : A-72 */
+ else if ((w0 & 0x00f7) == 0x0062)
+ {
+ return global_alloc(Dec(opc, w0, w1));
+ }
+ /* DEC24 : .... .... 0110 F011 : A-74 */
+ else if ((w0 & 0x00f7) == 0x0063)
+ {
+ return global_alloc(Dec24(opc, w0, w1));
+ }
+ /* AND : .... .... 0110 F1JJ : A-24 */
+ else if ((w0 & 0x00f4) == 0x0064)
+ {
+ return global_alloc(And(opc, w0, w1));
+ }
+
+ /* ABS : .... .... 0111 F001 : A-18 */
+ if ((w0 & 0x00f7) == 0x0071)
+ {
+ return global_alloc(Abs(opc, w0, w1));
+ }
+ /* ROR : .... .... 0111 F010 : A-192 */
+ else if ((w0 & 0x00f7) == 0x0072)
+ {
+ return global_alloc(Ror(opc, w0, w1));
+ }
+ /* ROL : .... .... 0111 F011 : A-190 */
+ else if ((w0 & 0x00f7) == 0x0073)
+ {
+ return global_alloc(Rol(opc, w0, w1));
+ }
+ /* CMPM : .... .... 0111 FJJJ : A-66 */
+ else if ((w0 & 0x00f0) == 0x0070)
+ {
+ return global_alloc(Cmpm(opc, w0, w1));
+ }
+
+ /* MPY : .... .... 1k00 FQQQ : A-160 */
+ else if ((w0 & 0x00b0) == 0x0080)
+ {
+ return global_alloc(Mpy(opc, w0, w1));
+ }
+ /* MPYR : .... .... 1k01 FQQQ : A-162 */
+ else if ((w0 & 0x00b0) == 0x0090)
+ {
+ return global_alloc(Mpyr(opc, w0, w1));
+ }
+ /* MAC : .... .... 1k10 FQQQ : A-122 */
+ else if ((w0 & 0x00b0) == 0x00a0)
+ {
+ return global_alloc(Mac(opc, w0, w1));
+ }
+ /* MACR : .... .... 1k11 FQQQ : A-124 */
+ else if ((w0 & 0x00b0) == 0x00b0)
+ {
+ return global_alloc(Macr(opc, w0, w1));
+ }
+ }
+
+ /******************************/
+ /* Remaining non-parallel ops */
+ /******************************/
+ /* ADC : 0001 0101 0000 F01J : A-20 */
+ else if ((w0 & 0xfff6) == 0x1502)
+ {
+ return global_alloc(Adc(opc, w0, w1));
+ }
+ /* ANDI : 0001 1EE0 iiii iiii : A-26 */
+ /* Note: MoveP sneaks in here if you don't check 0x0600 */
+ else if (((w0 & 0xf900) == 0x1800) & ((w0 & 0x0600) != 0x0000))
+ {
+ return global_alloc(Andi(opc, w0, w1));
+ }
+ /* ASL4 : 0001 0101 0011 F001 : A-30 */
+ else if ((w0 & 0xfff7) == 0x1531)
+ {
+ return global_alloc(Asl4(opc, w0, w1));
+ }
+ /* ASR4 : 0001 0101 0011 F000 : A-34 */
+ else if ((w0 & 0xfff7) == 0x1530)
+ {
+ return global_alloc(Asr4(opc, w0, w1));
+ }
+ /* ASR16 : 0001 0101 0111 F000 : A-36 */
+ else if ((w0 & 0xfff7) == 0x1570)
+ {
+ return global_alloc(Asr16(opc, w0, w1));
+ }
+ /* BFCHG : 0001 0100 11Pp pppp BBB1 0010 iiii iiii : A-38 */
+ else if (((w0 & 0xffc0) == 0x14c0) && ((w1 & 0x1f00) == 0x1200))
+ {
+ return global_alloc(BfInstruction(opc, w0, w1));
+ }
+ /* BFCHG : 0001 0100 101- --RR BBB1 0010 iiii iiii : A-38 */
+ else if (((w0 & 0xfff0) == 0x14b0) && ((w1 & 0x1f00) == 0x1200))
+ // NEW // else if (((w0 & 0xffe0) == 0x14a0) && ((w1 & 0x1f00) == 0x1200))
+ {
+ return global_alloc(BfInstruction_2(opc, w0, w1));
+ }
+ /* BFCHG : 0001 0100 100D DDDD BBB1 0010 iiii iiii : A-38 */
+ else if (((w0 & 0xffe0) == 0x1480) && ((w1 & 0x1f00) == 0x1200))
+ {
+ return global_alloc(BfInstruction_3(opc, w0, w1));
+ }
+ /* BFCLR : 0001 0100 11Pp pppp BBB0 0100 iiii iiii : A-40 */
+ else if (((w0 & 0xffc0) == 0x14c0) && ((w1 & 0x1f00) == 0x0400))
+ {
+ return global_alloc(BfInstruction(opc, w0, w1));
+ }
+ /* BFCLR : 0001 0100 101- --RR BBB0 0100 iiii iiii : A-40 */
+ else if (((w0 & 0xfff0) == 0x14b0) && ((w1 & 0x1f00) == 0x0400))
+ // NEW // else if (((w0 & 0xffe0) == 0x14a0) && ((w1 & 0x1f00) == 0x0400))
+ {
+ return global_alloc(BfInstruction_2(opc, w0, w1));
+ }
+ /* BFCLR : 0001 0100 100D DDDD BBB0 0100 iiii iiii : A-40 */
+ else if (((w0 & 0xffe0) == 0x1480) && ((w1 & 0x1f00) == 0x0400))
+ {
+ return global_alloc(BfInstruction_3(opc, w0, w1));
+ }
+ /* BFSET : 0001 0100 11Pp pppp BBB1 1000 iiii iiii : A-42 */
+ else if (((w0 & 0xffc0) == 0x14c0) && ((w1 & 0x1f00) == 0x1800))
+ {
+ return global_alloc(BfInstruction(opc, w0, w1));
+ }
+ /* BFSET : 0001 0100 101- --RR BBB1 1000 iiii iiii : A-42 */
+ else if (((w0 & 0xfff0) == 0x14b0) && ((w1 & 0x1f00) == 0x1800))
+ // NEW // else if (((w0 & 0xffe0) == 0x14a0) && ((w1 & 0x1f00) == 0x1800))
+ {
+ return global_alloc(BfInstruction_2(opc, w0, w1));
+ }
+ /* BFSET : 0001 0100 100D DDDD BBB1 1000 iiii iiii : A-42 */
+ else if (((w0 & 0xffe0) == 0x1480) && ((w1 & 0x1f00) == 0x1800))
+ {
+ return global_alloc(BfInstruction_3(opc, w0, w1));
+ }
+ /* BFTSTH : 0001 0100 01Pp pppp BBB1 0000 iiii iiii : A-44 */
+ else if (((w0 & 0xffc0) == 0x1440) && ((w1 & 0x1f00) == 0x1000))
+ {
+ return global_alloc(BfInstruction(opc, w0, w1));
+ }
+ /* BFTSTH : 0001 0100 001- --RR BBB1 0000 iiii iiii : A-44 */
+ else if (((w0 & 0xfff0) == 0x1430) && ((w1 & 0x1f00) == 0x1000))
+ // NEW // else if (((w0 & 0xffe0) == 0x1420) && ((w1 & 0x1f00) == 0x1000))
+ {
+ return global_alloc(BfInstruction_2(opc, w0, w1));
+ }
+ /* BFTSTH : 0001 0100 000D DDDD BBB1 0000 iiii iiii : A-44 */
+ else if (((w0 & 0xffe0) == 0x1400) && ((w1 & 0x1f00) == 0x1000))
+ {
+ return global_alloc(BfInstruction_3(opc, w0, w1));
+ }
+ /* BFTSTL : 0001 0100 01Pp pppp BBB0 0000 iiii iiii : A-46 */
+ else if (((w0 & 0xffc0) == 0x1440) && ((w1 & 0x1f00) == 0x0000))
+ {
+ return global_alloc(BfInstruction(opc, w0, w1));
+ }
+ /* BFTSTL : 0001 0100 001- --RR BBB0 0000 iiii iiii : A-46 */
+ else if (((w0 & 0xfff0) == 0x1430) && ((w1 & 0x1f00) == 0x0000))
+ // NEW // else if (((w0 & 0xffe0) == 0x1420) && ((w1 & 0x1f00) == 0x0000))
+ {
+ return global_alloc(BfInstruction_2(opc, w0, w1));
+ }
+ /* BFTSTL : 0001 0100 000D DDDD BBB0 0000 iiii iiii : A-46 */
+ else if (((w0 & 0xffe0) == 0x1400) && ((w1 & 0x1f00) == 0x0000))
+ {
+ return global_alloc(BfInstruction_3(opc, w0, w1));
+ }
+ /* Bcc : 0000 0111 --11 cccc xxxx xxxx xxxx xxxx : A-48 */
+ else if (((w0 & 0xff30) == 0x0730) && ((w1 & 0x0000) == 0x0000))
+ {
+ return global_alloc(Bcc(opc, w0, w1));
+ }
+ /* Bcc : 0010 11cc ccee eeee : A-48 */
+ else if ((w0 & 0xfc00) == 0x2c00)
+ {
+ return global_alloc(Bcc_2(opc, w0, w1));
+ }
+ /* Bcc : 0000 0111 RR10 cccc : A-48 */
+ else if ((w0 & 0xff30) == 0x0720)
+ {
+ return global_alloc(Bcc_3(opc, w0, w1));
+ }
+ /* BRA : 0000 0001 0011 11-- xxxx xxxx xxxx xxxx : A-50 */
+ else if (((w0 & 0xfffc) == 0x013c) && ((w1 & 0x0000) == 0x0000))
+ {
+ return global_alloc(Bra(opc, w0, w1));
+ }
+ /* BRA : 0000 1011 aaaa aaaa : A-50 */
+ else if ((w0 & 0xff00) == 0x0b00)
+ {
+ return global_alloc(Bra_2(opc, w0, w1));
+ }
+ /* BRA : 0000 0001 0010 11RR : A-50 */
+ else if ((w0 & 0xfffc) == 0x012c)
+ {
+ return global_alloc(Bra_3(opc, w0, w1));
+ }
+ /* BRKc : 0000 0001 0001 cccc : A-52 */
+ else if ((w0 & 0xfff0) == 0x0110)
+ {
+ return global_alloc(Brkcc(opc, w0, w1));
+ }
+ /* BScc : 0000 0111 --01 cccc xxxx xxxx xxxx xxxx : A-54 */
+ else if (((w0 & 0xff30) == 0x0710) && ((w1 & 0x0000) == 0x0000))
+ {
+ return global_alloc(Bscc(opc, w0, w1));
+ }
+ /* BScc : 0000 0111 RR00 cccc : A-54 */
+ else if ((w0 & 0xff30) == 0x0700)
+ {
+ return global_alloc(Bscc_2(opc, w0, w1));
+ }
+ /* BSR : 0000 0001 0011 10-- xxxx xxxx xxxx xxxx : A-56 */
+ else if (((w0 & 0xfffc) == 0x0138) && ((w1 & 0x0000) == 0x0000))
+ {
+ return global_alloc(Bsr(opc, w0, w1));
+ }
+ /* BSR : 0000 0001 0010 10RR : A-56 */
+ else if ((w0 & 0xfffc) == 0x0128)
+ {
+ return global_alloc(Bsr_2(opc, w0, w1));
+ }
+ /* CHKAAU : 0000 0000 0000 0100 : A-58 */
+ else if ((w0 & 0xffff) == 0x0004)
+ {
+ return global_alloc(Chkaau(opc, w0, w1));
+ }
+ /* DEBUG : 0000 0000 0000 0001 : A-68 */
+ else if ((w0 & 0xffff) == 0x0001)
+ {
+ return global_alloc(Debug(opc, w0, w1));
+ }
+ /* DEBUGcc : 0000 0000 0101 cccc : A-70 */
+ else if ((w0 & 0xfff0) == 0x0050)
+ {
+ return global_alloc(Debugcc(opc, w0, w1));
+ }
+ /* DIV : 0001 0101 0--0 F1DD : A-76 */
+ else if ((w0 & 0xfff4) == 0x1504)
+ // NEW // else if ((w0 & 0xff94) == 0x1504)
+ {
+ return global_alloc(Div(opc, w0, w1));
+ }
+ /* DMAC : 0001 0101 10s1 FsQQ : A-80 */
+ else if ((w0 & 0xffd0) == 0x1590)
+ {
+ return global_alloc(Dmac(opc, w0, w1));
+ }
+ /* DO : 0000 0000 110- --RR xxxx xxxx xxxx xxxx : A-82 */
+ else if (((w0 & 0xffe0) == 0x00c0) && ((w1 & 0x0000) == 0x0000)) // Wait. Huh?
+ {
+ return global_alloc(Do(opc, w0, w1));
+ }
+ /* DO : 0000 1110 iiii iiii xxxx xxxx xxxx xxxx : A-82 */
+ else if (((w0 & 0xff00) == 0x0e00) && ((w1 & 0x0000) == 0x0000)) // Wait. Huh?
+ {
+ return global_alloc(Do_2(opc, w0, w1));
+ }
+ /* DO : 0000 0100 000D DDDD xxxx xxxx xxxx xxxx : A-82 */
+ else if (((w0 & 0xffe0) == 0x0400) && ((w1 & 0x0000) == 0x0000)) // Wait. Huh?
+ {
+ return global_alloc(Do_3(opc, w0, w1));
+ }
+ /* DO FOREVER : 0000 0000 0000 0010 xxxx xxxx xxxx xxxx : A-88 */
+ else if (((w0 & 0xffff) == 0x0002) && ((w1 & 0x0000) == 0x0000)) // Wait. Huh?
+ {
+ return global_alloc(DoForever(opc, w0, w1));
+ }
+ /* ENDDO : 0000 0000 0000 1001 : A-92 */
+ else if ((w0 & 0xffff) == 0x0009)
+ {
+ return global_alloc(Enddo(opc, w0, w1));
+ }
+ /* EXT : 0001 0101 0101 F010 : A-96 */
+ else if ((w0 & 0xfff7) == 0x1552)
+ {
+ return global_alloc(Ext(opc, w0, w1));
+ }
+ /* ILLEGAL : 0000 0000 0000 1111 : A-98 */
+ else if ((w0 & 0xffff) == 0x000f)
+ {
+ return global_alloc(Illegal(opc, w0, w1));
+ }
+ /* IMAC : 0001 0101 1010 FQQQ : A-100 */
+ else if ((w0 & 0xfff0) == 0x15a0)
+ {
+ return global_alloc(Imac(opc, w0, w1));
+ }
+ /* IMPY : 0001 0101 1000 FQQQ : A-102 */
+ else if ((w0 & 0xfff0) == 0x1580)
+ {
+ return global_alloc(Impy(opc, w0, w1));
+ }
+ /* Jcc : 0000 0110 --11 cccc xxxx xxxx xxxx xxxx : A-108 */
+ else if (((w0 & 0xff30) == 0x0630) && ((w1 & 0x0000) == 0x0000))
+ {
+ return global_alloc(Jcc(opc, w0, w1));
+ }
+ /* Jcc : 0000 0110 RR10 cccc : A-108 */
+ else if ((w0 & 0xff30) == 0x0620 )
+ {
+ return global_alloc(Jcc_2(opc, w0, w1));
+ }
+ /* JMP : 0000 0001 0011 01-- xxxx xxxx xxxx xxxx : A-110 */
+ else if (((w0 & 0xfffc) == 0x0134) && ((w1 & 0x0000) == 0x0000))
+ {
+ return global_alloc(Jmp(opc, w0, w1));
+ }
+ /* JMP : 0000 0001 0010 01RR : A-110 */
+ else if ((w0 & 0xfffc) == 0x0124)
+ {
+ //JMP2->m_oco = opc;
+ //JMP2->decode(w0, w1);
+ //return JMP2;
+ return global_alloc(Jmp_2(opc, w0, w1));
+ }
+ /* JScc : 0000 0110 --01 cccc xxxx xxxx xxxx xxxx : A-112 */
+ else if (((w0 & 0xff30) == 0x0610) && ((w1 & 0x0000) == 0x0000))
+ {
+ return global_alloc(Jscc(opc, w0, w1));
+ }
+ /* JScc : 0000 0110 RR00 cccc : A-112 */
+ else if ((w0 & 0xff30) == 0x0600)
+ {
+ return global_alloc(Jscc_2(opc, w0, w1));
+ }
+ /* JSR : 0000 0001 0011 00-- xxxx xxxx xxxx xxxx : A-114 */
+ else if (((w0 & 0xfffc) == 0x0130) && ((w1 & 0x0000) == 0x0000))
+ {
+ return global_alloc(Jsr(opc, w0, w1));
+ }
+ /* JSR : 0000 1010 AAAA AAAA : A-114 */
+ else if ((w0 & 0xff00) == 0x0a00)
+ {
+ return global_alloc(Jsr_2(opc, w0, w1));
+ }
+ /* JSR : 0000 0001 0010 00RR : A-114 */
+ else if ((w0 & 0xfffc) == 0x0120)
+ {
+ return global_alloc(Jsr_3(opc, w0, w1));
+ }
+ /* LEA : 0000 0001 11TT MMRR : A-116 */
+ else if ((w0 & 0xffc0) == 0x01c0)
+ {
+ return global_alloc(Lea(opc, w0, w1));
+ }
+ /* LEA : 0000 0001 10NN MMRR : A-116 */
+ else if ((w0 & 0xffc0) == 0x0180)
+ {
+ return global_alloc(Lea_2(opc, w0, w1));
+ }
+ /* MAC(su,uu) : 0001 0101 1110 FsQQ : A-126 */
+ else if ((w0 & 0xfff0) == 0x15e0)
+ {
+ return global_alloc(Macsuuu(opc, w0, w1));
+ }
+ /* MOVE : 0000 0101 BBBB BBBB ---- HHHW 0001 0001 : A-128 */
+// NEW // else if (((w0 & 0xff00) == 0x0500) && ((w1 & 0x00ff) == 0x0011))
+// NEW // {
+// NEW // return global_alloc(Move_3(opc, w0, w1));
+// NEW // }
+ /* MOVE(C) : 0011 1WDD DDD0 MMRR : A-144 */
+ else if ((w0 & 0xf810) == 0x3800)
+ {
+ return global_alloc(Movec(opc, w0, w1));
+ }
+ /* MOVE(C) : 0011 1WDD DDD1 q0RR : A-144 */
+ else if ((w0 & 0xf814) == 0x3810)
+ {
+ return global_alloc(Movec_2(opc, w0, w1));
+ }
+ /* MOVE(C) : 0011 1WDD DDD1 Z11- : A-144 */
+ else if ((w0 & 0xf816) == 0x3816)
+ {
+ return global_alloc(Movec_3(opc, w0, w1));
+ }
+ /* MOVE(C) : 0011 1WDD DDD1 t10- xxxx xxxx xxxx xxxx : A-144 */
+ else if (((w0 & 0xf816) == 0x3814) && ((w1 & 0x0000) == 0x0000))
+ {
+ return global_alloc(Movec_4(opc, w0, w1));
+ }
+ /* MOVE(C) : 0010 10dd dddD DDDD : A-144 */
+ else if ((w0 & 0xfc00) == 0x2800)
+ {
+ return global_alloc(Movec_5(opc, w0, w1));
+ }
+ /* MOVE(C) : 0000 0101 BBBB BBBB 0011 1WDD DDD0 ---- : A-144 */
+ else if (((w0 & 0xff00) == 0x0500) && ((w1 & 0xf810) == 0x3800))
+ {
+ return global_alloc(Movec_6(opc, w0, w1));
+ }
+ /* MOVE(I) : 0010 00DD BBBB BBBB : A-150 */
+ else if ((w0 & 0xfc00) == 0x2000)
+ {
+ return global_alloc(Movei(opc, w0, w1));
+ }
+ /* MOVE(M) : 0000 001W RR0M MHHH : A-152 */
+ else if ((w0 & 0xfe20) == 0x0200)
+ {
+ return global_alloc(Movem(opc, w0, w1));
+ }
+ /* MOVE(M) : 0000 001W RR11 mmRR : A-152 */
+ else if ((w0 & 0xfe30) == 0x0230)
+ {
+ return global_alloc(Movem_2(opc, w0, w1));
+ }
+ /* MOVE(M) : 0000 0101 BBBB BBBB 0000 001W --0- -HHH : A-152 */
+ else if (((w0 & 0xff00) == 0x0500) && ((w1 & 0xfe20) == 0x0200))
+ {
+ return global_alloc(Movem_3(opc, w0, w1));
+ }
+ /* MOVE(P) : 0001 100W HH1p pppp : A-156 */
+ else if ((w0 & 0xfe20) == 0x1820)
+ {
+ return global_alloc(Movep(opc, w0, w1));
+ }
+ /* MOVE(P) : 0000 110W RRmp pppp : A-156 */
+ else if ((w0 & 0xfe00) == 0x0c00)
+ {
+ return global_alloc(Movep_2(opc, w0, w1));
+ }
+ /* MOVE(S) : 0001 100W HH0a aaaa : A-158 */
+ else if ((w0 & 0xfe20) == 0x1800)
+ {
+ return global_alloc(Moves(opc, w0, w1));
+ }
+ /* MPY(su,uu) : 0001 0101 1100 FsQQ : A-164 */
+ else if ((w0 & 0xfff0) == 0x15c0)
+ {
+ return global_alloc(Mpysuuu(opc, w0, w1));
+ }
+ /* NEGC : 0001 0101 0110 F000 : A-168 */
+ else if ((w0 & 0xfff7) == 0x1560)
+ {
+ return global_alloc(Negc(opc, w0, w1));
+ }
+ /* NOP : 0000 0000 0000 0000 : A-170 */
+ else if ((w0 & 0xffff) == 0x0000)
+ {
+ return global_alloc(Nop(opc, w0, w1));
+ }
+ /* NORM : 0001 0101 0010 F0RR : A-172 */
+ else if ((w0 & 0xfff4) == 0x1520)
+ {
+ return global_alloc(Norm(opc, w0, w1));
+ }
+ /* ORI : 0001 1EE1 iiii iiii : A-178 */
+ else if ((w0 & 0xf900) == 0x1900)
+ {
+ return global_alloc(Ori(opc, w0, w1));
+ }
+ /* REP : 0000 0000 111- --RR : A-180 */
+ else if ((w0 & 0xffe0) == 0x00e0)
+ {
+ return global_alloc(Rep(opc, w0, w1));
+ }
+ /* REP : 0000 1111 iiii iiii : A-180 */
+ else if ((w0 & 0xff00) == 0x0f00)
+ {
+ return global_alloc(Rep_2(opc, w0, w1));
+ }
+ /* REP : 0000 0100 001D DDDD : A-180 */
+ else if ((w0 & 0xffe0) == 0x0420)
+ {
+ return global_alloc(Rep_3(opc, w0, w1));
+ }
+ /* REPcc : 0000 0001 0101 cccc : A-184 */
+ else if ((w0 & 0xfff0) == 0x0150)
+ {
+ return global_alloc(Repcc(opc, w0, w1));
+ }
+ /* RESET : 0000 0000 0000 1000 : A-186 */
+ else if ((w0 & 0xffff) == 0x0008)
+ {
+ return global_alloc(Reset(opc, w0, w1));
+ }
+ /* RTI : 0000 0000 0000 0111 : A-194 */
+ else if ((w0 & 0xffff) == 0x0007)
+ {
+ return global_alloc(Rti(opc, w0, w1));
+ }
+ /* RTS : 0000 0000 0000 0110 : A-196 */
+ else if ((w0 & 0xffff) == 0x0006)
+ {
+ return global_alloc(Rts(opc, w0, w1));
+ }
+ /* STOP : 0000 0000 0000 1010 : A-200 */
+ else if ((w0 & 0xffff) == 0x000a)
+ {
+ return global_alloc(Stop(opc, w0, w1));
+ }
+ /* SWAP : 0001 0101 0111 F001 : A-206 */
+ else if ((w0 & 0xfff7) == 0x1571)
+ {
+ return global_alloc(Swap(opc, w0, w1));
+ }
+ /* SWI : 0000 0000 0000 0101 : A-208 */
+ else if ((w0 & 0xffff) == 0x0005)
+ {
+ return global_alloc(Swi(opc, w0, w1));
+ }
+ /* Tcc : 0001 00cc ccTT Fh0h : A-210 */
+ else if ((w0 & 0xfc02) == 0x1000)
+ {
+ return global_alloc(Tcc(opc, w0, w1));
+ }
+ /* TFR(2) : 0001 0101 0000 F00J : A-214 */
+ else if ((w0 & 0xfff6) == 0x1500)
+ {
+ return global_alloc(Tfr2(opc, w0, w1));
+ }
+ /* TFR(3) : 0010 01mW RRDD FHHH : A-216 */
+ else if ((w0 & 0xfc00) == 0x2400)
+ {
+ return global_alloc(Tfr3(opc, w0, w1));
+ }
+ /* TST(2) : 0001 0101 0001 -1DD : A-220 */
+ else if ((w0 & 0xfffc) == 0x1514)
+ // NEW // else if ((w0 & 0xfff4) == 0x1514)
+ {
+ return global_alloc(Tst2(opc, w0, w1));
+ }
+ /* WAIT : 0000 0000 0000 1011 : A-222 */
+ else if ((w0 & 0xffff) == 0x000b)
+ {
+ return global_alloc(Wait(opc, w0, w1));
+ }
+ /* ZERO : 0001 0101 0101 F000 : A-224 */
+ else if ((w0 & 0xfff7) == 0x1550)
+ {
+ return global_alloc(Zero(opc, w0, w1));
+ }
+ /* SHFL : 0001 0101 1101 FQQQ : !!UNDOCUMENTED!! */
+ else if ((w0 & 0xfff0) == 0x15d0)
+ {
+ return global_alloc(Shfl(opc, w0, w1));
+ }
+ /* SHFR : 0001 0101 1111 FQQQ : !!UNDOCUMENTED!! */
+ else if ((w0 & 0xfff0) == 0x15f0)
+ {
+ return global_alloc(Shfr(opc, w0, w1));
+ }
+
+ return NULL;
+}
+
+}
diff --git a/trunk/src/emu/cpu/dsp56k/inst.h b/trunk/src/emu/cpu/dsp56k/inst.h
new file mode 100644
index 00000000000..b50bd09f592
--- /dev/null
+++ b/trunk/src/emu/cpu/dsp56k/inst.h
@@ -0,0 +1,3776 @@
+#ifndef __DSP56K_INSTRUCTION_H__
+#define __DSP56K_INSTRUCTION_H__
+
+#include "opcode.h"
+#include "tables.h"
+
+#include "dsp56k.h"
+#include "dsp56def.h"
+#include "dsp56pcu.h"
+
+//
+// An Instruction is the base class all regular ops inherit from.
+//
+namespace DSP56K
+{
+
+#define ADDRESS(X) ((X)<<1)
+#define UNIMPLEMENTED_OPCODE() mame_printf_error("Unimplemented opcode: PC=%04x | %s;\n", PC, __PRETTY_FUNCTION__);
+
+class Opcode;
+
+class Instruction
+{
+public:
+ Instruction(const Opcode* oco) : m_valid(false),
+ m_oco(oco),
+ m_sizeIncrement(0),
+ m_source(iINVALID),
+ m_destination(iINVALID) { }
+ virtual ~Instruction() {}
+
+ virtual bool decode(const UINT16 word0, const UINT16 word1) = 0;
+ virtual void disassemble(astring& retString) const = 0;
+ virtual void evaluate(dsp56k_core* cpustate) = 0;
+
+ virtual size_t size() const = 0;
+ virtual size_t evalSize() const { return size(); }
+ virtual size_t accumulatorBitsModified() const = 0; // Potentially make this always return ALL (like flags)
+ virtual size_t flags() const { return 0; }
+
+ static Instruction* decodeInstruction(const Opcode* opc,
+ const UINT16 word0,
+ const UINT16 word1,
+ bool shifted=false);
+
+ const bool valid() const { return m_valid; }
+
+ const reg_id& source() const { return m_source; }
+ const reg_id& destination() const { return m_destination; }
+
+ size_t sizeIncrement() const { return m_sizeIncrement; }
+
+protected:
+ bool m_valid;
+ const Opcode* m_oco;
+ size_t m_sizeIncrement;
+
+ // Parameters nearly everyone has
+ reg_id m_source;
+ reg_id m_destination;
+};
+
+
+////////////////////////////////////////////////////////////////////////////////
+// OPS ////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+// ABS : .... .... 0111 F001 : A-18 ////////////////////////////////////////////
+class Abs: public Instruction
+{
+public:
+ Abs(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_F_table(BITSn(word0,0x08), m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "abs " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// ADC : 0001 0101 0000 F01J : A-20 ////////////////////////////////////////////
+class Adc: public Instruction
+{
+public:
+ Adc(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_JF_table(BITSn(word0,0x0001), BITSn(word0,0x0008),
+ m_source, m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "adc " + regIdAsString(m_source) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// ADD : .... .... 0000 FJJJ : A-22 ////////////////////////////////////////////
+class Add: public Instruction
+{
+public:
+ Add(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_JJJF_table(BITSn(word0,0x07), BITSn(word0,0x08),
+ m_source, m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "add " + regIdAsString(m_source) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// ??? Odd that i should put the 011m mKKK everywhere ??? TODO
+// ADD : 011m mKKK 0rru Fuuu : A-22 ////////////////////////////////////////////
+class Add_2: public Instruction
+{
+public:
+ Add_2(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_arg = "";
+ m_opcode = "";
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_uuuuF_table(BITSn(word0,0x17), BITSn(word0,0x08),
+ m_opcode, m_source, m_destination);
+ // TODO: m_opcode = "add";
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = m_opcode + " " + regIdAsString(m_source) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ astring m_opcode;
+ astring m_arg; // TODO: get rid of this Add|Sub thing.
+};
+
+// AND : .... .... 0110 F1JJ : A-24 ////////////////////////////////////////////
+class And: public Instruction
+{
+public:
+ And(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_JJF_table(BITSn(word0,0x03),BITSn(word0,0x08),
+ m_source, m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "and " + regIdAsString(m_source) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE; }
+};
+
+// ANDI : 0001 1EE0 iiii iiii : A-26 ///////////////////////////////////////////
+class Andi: public Instruction
+{
+public:
+ Andi(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_immediate = 0;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ m_immediate = BITSn(word0,0x00ff);
+ decode_EE_table(BITSn(word0,0x0600), m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ char temp[32];
+ sprintf(temp, "#$%x,%s", m_immediate, regIdAsString(m_destination).cstr());
+ retString = "andi " + astring(temp);
+ // NEW // sprintf(opcode_str, "and(i)");
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ UINT8 m_immediate;
+};
+
+// ASL : .... .... 0011 F001 : A-28 ////////////////////////////////////////////
+class Asl: public Instruction
+{
+public:
+ Asl(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_F_table(BITSn(word0,0x08), m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "asl " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// ASL4 : 0001 0101 0011 F001 : A-30 ///////////////////////////////////////////
+class Asl4: public Instruction
+{
+public:
+ Asl4(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_F_table(BITSn(word0,0x0008), m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "asl4 " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// ASR : .... .... 0011 F000 : A-32 ////////////////////////////////////////////
+class Asr: public Instruction
+{
+public:
+ Asr(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_F_table(BITSn(word0,0x08), m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "asr " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// ASR4 : 0001 0101 0011 F000 : A-34 ///////////////////////////////////////////
+class Asr4: public Instruction
+{
+public:
+ Asr4(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_F_table(BITSn(word0,0x0008), m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "asr4 " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// ASR16 : 0001 0101 0111 F000 : A-36 //////////////////////////////////////////
+class Asr16: public Instruction
+{
+public:
+ Asr16(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_F_table(BITSn(word0,0x0008), m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "asr16 " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+/* BFCHG : 0001 0100 11Pp pppp BBB1 0010 iiii iiii : A-38 */
+/* BFCLR : 0001 0100 11Pp pppp BBB0 0100 iiii iiii : A-40 */
+/* BFSET : 0001 0100 11Pp pppp BBB1 1000 iiii iiii : A-42 */
+/* BFTSTH : 0001 0100 01Pp pppp BBB1 0000 iiii iiii : A-44 */
+/* BFTSTL : 0001 0100 01Pp pppp BBB0 0000 iiii iiii : A-46 */
+class BfInstruction: public Instruction
+{
+public:
+ BfInstruction(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ dString = "";
+ m_opcode = "";
+ m_iVal = 0x0000;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ /* Decode the common parts */
+ m_iVal = BITSn(word1,0x00ff);
+
+ bfShift upperMiddleLower = decode_BBB_table(BITSn(word1,0xe000));
+ switch(upperMiddleLower)
+ {
+ case BBB_UPPER: m_iVal <<= 8; break;
+ case BBB_MIDDLE: m_iVal <<= 4; break;
+ case BBB_LOWER: m_iVal <<= 0; break;
+
+ case BBB_INVALID: return false; break;
+ }
+
+ assemble_D_from_P_table(BITSn(word0,0x0020), BITSn(word0,0x001f), dString);
+
+ if (dString == "!!")
+ return false;
+
+ switch(BITSn(word1,0x1f00))
+ {
+ case 0x12: m_opcode = "bfchg"; break;
+ case 0x04: m_opcode = "bfclr"; break;
+ case 0x18: m_opcode = "bfset"; break;
+ case 0x10: m_opcode = "bftsth"; break;
+ case 0x00: m_opcode = "bftstl"; break;
+ }
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ char temp[32];
+ sprintf(temp, "#$%x", m_iVal);
+ retString = m_opcode + " " + astring(temp) + "," + dString;
+ // NEW // sprintf(temp, "#$%04x", iVal);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 2; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+private:
+ UINT16 m_iVal;
+ astring m_opcode;
+ astring dString;
+};
+
+/* BFCHG : 0001 0100 101- --RR BBB1 0010 iiii iiii : A-38 */
+/* BFCLR : 0001 0100 101- --RR BBB0 0100 iiii iiii : A-40 */
+/* BFSET : 0001 0100 101- --RR BBB1 1000 iiii iiii : A-42 */
+/* BFTSTH : 0001 0100 001- --RR BBB1 0000 iiii iiii : A-44 */
+/* BFTSTL : 0001 0100 001- --RR BBB0 0000 iiii iiii : A-46 */
+class BfInstruction_2: public Instruction
+{
+public:
+ BfInstruction_2(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_opcode = "";
+ m_r = iINVALID;
+ m_iVal = 0x0000;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ /* Decode the common parts */
+ m_iVal = BITSn(word1,0x00ff);
+
+ bfShift upperMiddleLower = decode_BBB_table(BITSn(word1,0xe000));
+ switch(upperMiddleLower)
+ {
+ case BBB_UPPER: m_iVal <<= 8; break;
+ case BBB_MIDDLE: m_iVal <<= 4; break;
+ case BBB_LOWER: m_iVal <<= 0; break;
+
+ case BBB_INVALID: return false; break;
+ }
+
+ decode_RR_table(BITSn(word0,0x0003), m_r);
+
+ if (m_r == iINVALID)
+ return false;
+
+ switch(BITSn(word1,0x1f00))
+ {
+ case 0x12: m_opcode = "bfchg"; break;
+ case 0x04: m_opcode = "bfclr"; break;
+ case 0x18: m_opcode = "bfset"; break;
+ case 0x10: m_opcode = "bftsth"; break;
+ case 0x00: m_opcode = "bftstl"; break;
+ }
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ char temp[32];
+ sprintf(temp, "#$%x", m_iVal);
+ astring source = temp;
+
+ sprintf(temp, "X:(%s)", regIdAsString(m_r).cstr());
+ astring destination = temp;
+
+ retString = m_opcode + " " + source + "," + destination;
+ // NEW // sprintf(temp, "#$%04x", m_iVal);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 2; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ reg_id m_r;
+ UINT16 m_iVal;
+ astring m_opcode;
+};
+
+/* BFCHG : 0001 0100 100D DDDD BBB1 0010 iiii iiii : A-38 */
+/* BFCLR : 0001 0100 100D DDDD BBB0 0100 iiii iiii : A-40 */
+/* BFSET : 0001 0100 100D DDDD BBB1 1000 iiii iiii : A-42 */
+/* BFTSTH : 0001 0100 000D DDDD BBB1 0000 iiii iiii : A-44 */
+/* BFTSTL : 0001 0100 000D DDDD BBB0 0000 iiii iiii : A-46 */
+class BfInstruction_3: public Instruction
+{
+public:
+ BfInstruction_3(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_opcode = "";
+ m_iVal = 0x0000;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ /* Decode the common parts */
+ m_iVal = BITSn(word1,0x00ff);
+
+ bfShift upperMiddleLower = decode_BBB_table(BITSn(word1,0xe000));
+ switch(upperMiddleLower)
+ {
+ case BBB_UPPER: m_iVal <<= 8; break;
+ case BBB_MIDDLE: m_iVal <<= 4; break;
+ case BBB_LOWER: m_iVal <<= 0; break;
+
+ case BBB_INVALID: return false; break;
+ }
+
+ decode_DDDDD_table(BITSn(word0,0x001f), m_destination);
+
+ if (m_destination == iINVALID)
+ return false;
+
+ switch(BITSn(word1,0x1f00))
+ {
+ case 0x12: m_opcode = "bfchg"; break;
+ case 0x04: m_opcode = "bfclr"; break;
+ case 0x18: m_opcode = "bfset"; break;
+ case 0x10: m_opcode = "bftsth"; break;
+ case 0x00: m_opcode = "bftstl"; break;
+ }
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ char temp[32];
+ sprintf(temp, "#$%x", m_iVal);
+ astring source = temp;
+
+ retString = m_opcode + " " + source + "," + regIdAsString(m_destination);
+ // NEW // sprintf(temp, "#$%04x", m_iVal);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 2; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ UINT16 m_iVal;
+ astring m_opcode;
+};
+
+// Bcc : 0000 0111 --11 cccc xxxx xxxx xxxx xxxx : A-48 ////////////////////////
+class Bcc: public Instruction
+{
+public:
+ Bcc(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_mnem = oINVALID;
+ m_immediate = 0;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ m_immediate = (INT16)word1;
+ decode_cccc_table(BITSn(word0,0x000f), m_mnem);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ astring opcode = "b" + opMnemonicAsString(m_mnem);
+ // NEW // sprintf(opcode_str, "b.%s", M);
+
+ char temp[32];
+ sprintf(temp, ">*+$%x", 2 + m_immediate);
+ // NEW // sprintf(temp, "$%04x (%d)", pc + 2 + (INT16)word1, (INT16)word1);
+ retString = opcode + " " + astring(temp);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 2; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ op_mnem m_mnem;
+ INT16 m_immediate;
+};
+
+// Bcc : 0010 11cc ccee eeee : A-48 ////////////////////////////////////////////
+class Bcc_2: public Instruction
+{
+public:
+ Bcc_2(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_immediate = 0;
+ m_mnem = oINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_cccc_table(BITSn(word0,0x3c0), m_mnem);
+ m_immediate = get_6_bit_signed_value(BITSn(word0,0x003f));
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ astring opcode = "b" + opMnemonicAsString(m_mnem);
+ // NEW // sprintf(opcode_str, "b.%s", M);
+
+ char temp[32];
+ if (m_immediate >= 0) sprintf(temp, "<*+$%x", m_immediate + 1);
+ else sprintf(temp, "<*-$%x", 1 - m_immediate - 2);
+ // NEW // sprintf(temp, "$%04x (%d)", pc + 1 + relativeInt, relativeInt);
+
+ retString = opcode + " " + astring(temp);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ op_mnem m_mnem;
+ INT8 m_immediate;
+};
+
+// Bcc : 0000 0111 RR10 cccc : A-48 ////////////////////////////////////////////
+class Bcc_3: public Instruction
+{
+public:
+ Bcc_3(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_mnem = oINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_RR_table(BITSn(word0,0x00c0), m_destination);
+ decode_cccc_table(BITSn(word0,0x000f), m_mnem);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ astring opcode = "b" + opMnemonicAsString(m_mnem);
+ retString = opcode + " " + regIdAsString(m_destination);
+ // NEW // sprintf(opcode_str, "b.%s", M);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ op_mnem m_mnem;
+};
+
+// BRA : 0000 0001 0011 11-- xxxx xxxx xxxx xxxx : A-50 ////////////////////////
+class Bra: public Instruction
+{
+public:
+ Bra(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_immediate = 0;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ m_immediate = (INT16)word1;
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ char temp[32];
+ sprintf(temp, ">*+$%x", 2 + m_immediate);
+ // NEW // sprintf(temp, "$%04x (%d)", pc + 2 + word1, (INT16)word1);
+ retString = "bra " + astring(temp);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 2; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ INT16 m_immediate;
+};
+
+// BRA : 0000 1011 aaaa aaaa : A-50 ////////////////////////////////////////////
+class Bra_2: public Instruction
+{
+public:
+ Bra_2(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_immediate = 0;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ m_immediate = (INT8)BITSn(word0,0x00ff);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ char temp[32];
+ if (m_immediate >= 0) sprintf(temp, "<*+$%x", 1 + m_immediate);
+ else sprintf(temp, "<*-$%x", 1 - m_immediate - 2);
+ // NEW // sprintf(temp, "$%04x (%d)", pc + 1 + iVal, iVal);
+ retString = "bra " + astring(temp);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ INT8 m_immediate;
+};
+
+// BRA : 0000 0001 0010 11RR : A-50 ////////////////////////////////////////////
+class Bra_3: public Instruction
+{
+public:
+ Bra_3(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_RR_table(BITSn(word0,0x0003), m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "bra " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// BRKcc : 0000 0001 0001 cccc : A-52 //////////////////////////////////////////
+class Brkcc: public Instruction
+{
+public:
+ Brkcc(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_mnem = oINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_cccc_table(BITSn(word0,0x000f), m_mnem);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ astring opcode = "brk" + opMnemonicAsString(m_mnem);
+ retString = opcode;
+ // NEW // sprintf(opcode_str, "brk.%s", M);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ op_mnem m_mnem;
+};
+
+// BScc : 0000 0111 --01 cccc xxxx xxxx xxxx xxxx : A-54 ///////////////////////
+class Bscc: public Instruction
+{
+public:
+ Bscc(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_immediate = 0;
+ m_mnem = oINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ m_immediate = (INT16)word1;
+ decode_cccc_table(BITSn(word0,0x000f), m_mnem);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ astring opcode = "bs" + opMnemonicAsString(m_mnem);
+ // NEW // sprintf(opcode_str, "bs.%s", M);
+
+ char temp[32];
+ if (m_immediate >= 0) sprintf(temp, ">*+$%x", 2 + m_immediate);
+ else sprintf(temp, ">*-$%x", 1 - m_immediate - 1 - 2);
+ //sprintf(temp, ">*+$%x", 2 + m_immediate);
+ // NEW // sprintf(temp, "$%04x (%d)", pc + 2 + (INT16)word1, (INT16)word1);
+ retString = opcode + " " + astring(temp);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 2; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+ size_t flags() const { return DASMFLAG_STEP_OVER; }
+
+private:
+ op_mnem m_mnem;
+ INT16 m_immediate;
+};
+
+// BScc : 0000 0111 RR00 cccc : A-54 ///////////////////////////////////////////
+class Bscc_2: public Instruction
+{
+public:
+ Bscc_2(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_mnem = oINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_RR_table(BITSn(word0,0x00c0), m_destination);
+ decode_cccc_table(BITSn(word0,0x000f), m_mnem);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ astring opcode = "bs" + opMnemonicAsString(m_mnem);
+ retString = opcode + " " + regIdAsString(m_destination);
+ // NEW // sprintf(opcode_str, "bs.%s", M);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+ size_t flags() const { return DASMFLAG_STEP_OVER; }
+
+private:
+ op_mnem m_mnem;
+};
+
+// BSR : 0000 0001 0011 10-- xxxx xxxx xxxx xxxx : A-56 ////////////////////////
+class Bsr: public Instruction
+{
+public:
+ Bsr(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_immediate = 0;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ m_immediate = (INT16)word1;
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ char temp[32];
+ if (m_immediate >= 0) sprintf(temp, ">*+$%x", 2 + m_immediate);
+ else sprintf(temp, ">*-$%x", 1 - m_immediate - 1 - 2);
+ // NEW // sprintf(temp, "$%04x (%d)", pc + 2 + (INT16)word1, (INT16)word1);
+ retString = "bsr " + astring(temp);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 2; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+ size_t flags() const { return DASMFLAG_STEP_OVER; }
+
+private:
+ INT16 m_immediate;
+};
+
+// BSR : 0000 0001 0010 10RR : A-56 ////////////////////////////////////////////
+class Bsr_2: public Instruction
+{
+public:
+ Bsr_2(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_RR_table(BITSn(word0,0x0003), m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "bsr " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+ size_t flags() const { return DASMFLAG_STEP_OVER; }
+};
+
+// CHKAAU : 0000 0000 0000 0100 : A-58 /////////////////////////////////////////
+class Chkaau: public Instruction
+{
+public:
+ Chkaau(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "chkaau";
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// CLR : .... .... 0000 F001 : A-60 ////////////////////////////////////////////
+class Clr: public Instruction
+{
+public:
+ Clr(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_F_table(BITSn(word0,0x08), m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "clr " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// CLR24 : .... .... 0101 F001 : A-62 //////////////////////////////////////////
+class Clr24: public Instruction
+{
+public:
+ Clr24(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_F_table(BITSn(word0,0x08), m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "clr24 " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE; }
+};
+
+// CMP : .... .... 0101 FJJJ : A-64 ////////////////////////////////////////////
+class Cmp: public Instruction
+{
+public:
+ Cmp(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ /* Note: This is a JJJF limited in the docs, but other opcodes sneak
+ in before cmp, so the same decode function can be used. */
+ decode_JJJF_table(BITSn(word0,0x07), BITSn(word0,0x08),
+ m_source, m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "cmp " + regIdAsString(m_source) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_NONE; }
+};
+
+// CMPM : .... .... 0111 FJJJ : A-66 ///////////////////////////////////////////
+class Cmpm: public Instruction
+{
+public:
+ Cmpm(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ /* Note: This is a JJJF limited in the docs, but other opcodes sneak
+ in before cmp, so the same decode function can be used. */
+ decode_JJJF_table(BITSn(word0,0x07), BITSn(word0,0x08),
+ m_source, m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "cmpm " + regIdAsString(m_source) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_NONE; }
+};
+
+// DEBUG : 0000 0000 0000 0001 : A-68 //////////////////////////////////////////
+class Debug: public Instruction
+{
+public:
+ Debug(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "debug";
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// DEBUGcc : 0000 0000 0101 cccc : A-70 ////////////////////////////////////////
+class Debugcc: public Instruction
+{
+public:
+ Debugcc(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_mnem = oINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_cccc_table(BITSn(word0,0x000f), m_mnem);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ astring opcode = "debug" + opMnemonicAsString(m_mnem);
+ retString = opcode;
+ // NEW // sprintf(opcode_str, "debug.%s", M);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ op_mnem m_mnem;
+};
+
+// DEC : .... .... 0110 F010 : A-72 ////////////////////////////////////////////
+class Dec: public Instruction
+{
+public:
+ Dec(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_F_table(BITSn(word0,0x08), m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "dec " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// DEC24 : .... .... 0110 F011 : A-74 //////////////////////////////////////////
+class Dec24: public Instruction
+{
+public:
+ Dec24(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_F_table(BITSn(word0,0x08), m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "dec24 " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE; }
+};
+
+// DIV : 0001 0101 0--0 F1DD : A-76 ////////////////////////////////////////////
+class Div: public Instruction
+{
+public:
+ Div(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_DDF_table(BITSn(word0,0x0003), BITSn(word0,0x0008),
+ m_source, m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "div " + regIdAsString(m_source) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// DMAC : 0001 0101 10s1 FsQQ : A-80 ///////////////////////////////////////////
+class Dmac: public Instruction
+{
+public:
+ Dmac(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_mnem = oINVALID;
+ m_source2 = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_QQF_special_table(BITSn(word0,0x0003), BITSn(word0,0x0008),
+ m_source, m_source2, m_destination);
+
+ decode_ss_table(BITSn(word0,0x0024), m_mnem);
+ if (m_mnem == oINVALID) return false;
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ astring opcode = "dmac" + opMnemonicAsString(m_mnem);
+
+ retString = opcode + " " +
+ regIdAsString(m_source) + "," +
+ regIdAsString(m_source2) + "," + regIdAsString(m_destination);
+ // NEW // sprintf(opcode_str, "dmac(%s)", A);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ op_mnem m_mnem;
+ reg_id m_source2;
+};
+
+// DO : 0000 0000 110- --RR xxxx xxxx xxxx xxxx : A-82 /////////////////////////
+class Do: public Instruction
+{
+public:
+ Do(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_immediate = 0;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ m_immediate = word1;
+ decode_RR_table(BITSn(word0,0x0003), m_source);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ char temp[32];
+ sprintf(temp, "*+$%x", 2 + m_immediate);
+ astring destination = temp;
+ // NEW // sprintf(temp, "X:(R%d),$%02x", Rnum, pc + 2 + word1);
+
+ sprintf(temp, "X:(%s)", regIdAsString(m_source).cstr());
+ astring source = temp;
+
+ retString = "do " + source + "," + destination;
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 2; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ UINT16 m_immediate;
+};
+
+// DO : 0000 1110 iiii iiii xxxx xxxx xxxx xxxx : A-82 /////////////////////////
+class Do_2: public Instruction
+{
+public:
+ Do_2(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_immediate = 0;
+ m_displacement = 0;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ m_immediate = BITSn(word0,0x00ff);
+ m_displacement = word1;
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ char temp[32];
+ sprintf(temp, "#<$%x,*+$%x", m_immediate, 2 + m_displacement);
+ // NEW // sprintf(temp, "#$%02x,$%04x", BITSn(word0,0x00ff), pc + 2 + word1);
+ retString = "do " + astring(temp);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 2; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ UINT8 m_immediate;
+ UINT16 m_displacement;
+};
+
+// DO : 0000 0100 000D DDDD xxxx xxxx xxxx xxxx : A-82 /////////////////////////
+class Do_3: public Instruction
+{
+public:
+ Do_3(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_displacement = 0;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ m_displacement = word1;
+
+ decode_DDDDD_table(BITSn(word0,0x001f), m_source);
+ if (m_source == iSSH) return false;
+ if (m_source == iINVALID) return false;
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ char temp[32];
+ sprintf(temp, "*+$%x", 2 + m_displacement);
+ // NEW // sprintf(temp, "%s,$%04x", S1, pc + 2 + word1);
+ retString = "do " + regIdAsString(m_source) + "," + astring(temp);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 2; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ UINT16 m_displacement;
+};
+
+// DO FOREVER : 0000 0000 0000 0010 xxxx xxxx xxxx xxxx : A-88 /////////////////
+class DoForever: public Instruction
+{
+public:
+ DoForever(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_displacement = 0;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ m_displacement = word1;
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ char temp[32];
+ sprintf(temp, "*+$%x", m_displacement + 2);
+ // NEW // sprintf(temp, "*+$%x", pc + word1);
+ // NEW // sprintf(temp, "$%04x", pc + 2 + word1);
+ retString = "do forever, " + astring(temp);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 2; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ UINT16 m_displacement;
+};
+
+// ENDDO : 0000 0000 0000 1001 : A-92 //////////////////////////////////////////
+class Enddo: public Instruction
+{
+public:
+ Enddo(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "enddo";
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// EOR : .... .... 0011 F1JJ : A-94 ////////////////////////////////////////////
+class Eor: public Instruction
+{
+public:
+ Eor(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_JJF_table(BITSn(word0,0x03),BITSn(word0,0x08),
+ m_source, m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "eor " + regIdAsString(m_source) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE; }
+};
+
+// EXT : 0001 0101 0101 F010 : A-96 ////////////////////////////////////////////
+class Ext: public Instruction
+{
+public:
+ Ext(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_F_table(BITSn(word0,0x0008), m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "ext " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// ILLEGAL : 0000 0000 0000 1111 : A-98 ////////////////////////////////////////
+class Illegal: public Instruction
+{
+public:
+ Illegal(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "illegal";
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// IMAC : 0001 0101 1010 FQQQ : A-100 //////////////////////////////////////////
+class Imac: public Instruction
+{
+public:
+ Imac(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_source2 = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_QQQF_table(BITSn(word0,0x0007), BITSn(word0,0x0008),
+ m_source, m_source2, m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "imac " +
+ regIdAsString(m_source) + "," +
+ regIdAsString(m_source2) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ reg_id m_source2;
+};
+
+// IMPY : 0001 0101 1000 FQQQ : A-102 //////////////////////////////////////////
+class Impy: public Instruction
+{
+public:
+ Impy(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_source2 = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_QQQF_table(BITSn(word0,0x0007), BITSn(word0,0x0008),
+ m_source, m_source2, m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "impy " +
+ regIdAsString(m_source) + "," +
+ regIdAsString(m_source2) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ reg_id m_source2;
+};
+
+// INC : .... .... 0010 F010 : A-104 ///////////////////////////////////////////
+class Inc: public Instruction
+{
+public:
+ Inc(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_F_table(BITSn(word0,0x08), m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "inc " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// INC24 : .... .... 0010 F011 : A-106 /////////////////////////////////////////
+class Inc24: public Instruction
+{
+public:
+ Inc24(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_F_table(BITSn(word0,0x08), m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "inc24 " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE; }
+};
+
+// Jcc : 0000 0110 --11 cccc xxxx xxxx xxxx xxxx : A-108 ///////////////////////
+class Jcc: public Instruction
+{
+public:
+ Jcc(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_mnem = oINVALID;
+ m_displacement = 0;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ m_displacement = word1;
+ decode_cccc_table(BITSn(word0,0x000f), m_mnem);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ astring opcode = "j" + opMnemonicAsString(m_mnem);
+ // NEW // sprintf(opcode_str, "j.%s", M);
+
+ char temp[32];
+ sprintf(temp, ">$%x", m_displacement);
+ // NEW // sprintf(temp, "$%04x", word1);
+ retString = opcode + " " + astring(temp);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 2; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ op_mnem m_mnem;
+ UINT16 m_displacement;
+};
+
+// Jcc : 0000 0110 RR10 cccc : A-108 ///////////////////////////////////////////
+class Jcc_2: public Instruction
+{
+public:
+ Jcc_2(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_mnem = oINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_RR_table(BITSn(word0,0x00c0), m_destination);
+ decode_cccc_table(BITSn(word0,0x000f), m_mnem);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ astring opcode = "j" + opMnemonicAsString(m_mnem);
+ retString = opcode + " " + regIdAsString(m_destination);
+ // NEW // sprintf(opcode_str, "j.%s", M);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ op_mnem m_mnem;
+};
+
+// JMP : 0000 0001 0011 01-- xxxx xxxx xxxx xxxx : A-110 ///////////////////////
+class Jmp: public Instruction
+{
+public:
+ Jmp(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_displacement = 0;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ m_displacement = word1;
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ char temp[32];
+ sprintf(temp, ">$%x", m_displacement);
+ // NEW // sprintf(temp, "$%04x", word1);
+ retString = "jmp " + astring(temp);
+ }
+ void evaluate(dsp56k_core* cpustate)
+ {
+ cpustate->ppc = PC;
+ PC = m_displacement;
+
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ }
+ size_t size() const { return 2; }
+ size_t evalSize() const { return 0; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ UINT16 m_displacement;
+};
+
+// JMP : 0000 0001 0010 01RR : A-110 ///////////////////////////////////////////
+class Jmp_2: public Instruction
+{
+public:
+ Jmp_2(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_RR_table(BITSn(word0,0x0003), m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "jmp " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate)
+ {
+ cpustate->ppc = PC;
+ PC = regValue16(cpustate, m_destination);
+
+ /* S L E U N Z V C */
+ /* - - - - - - - - */
+ }
+ size_t size() const { return 1; }
+ size_t evalSize() const { return 0; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+//static Jmp_2* JMP2 = new Jmp_2(NULL, 0x0000, 0x0000);
+
+// JScc : 0000 0110 --01 cccc xxxx xxxx xxxx xxxx : A-112 //////////////////////
+class Jscc: public Instruction
+{
+public:
+ Jscc(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_mnem = oINVALID;
+ m_displacement = 0;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ m_displacement = word1;
+ decode_cccc_table(BITSn(word0,0x000f), m_mnem);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ astring opcode = "js" + opMnemonicAsString(m_mnem);
+ // NEW // sprintf(opcode_str, "js.%s", M);
+
+ char temp[32];
+ sprintf(temp, ">$%x", m_displacement);
+ // NEW // sprintf(temp, "$%04x", word1);
+ retString = opcode + " " + astring(temp);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 2; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+ size_t flags() const { return DASMFLAG_STEP_OVER; }
+
+private:
+ op_mnem m_mnem;
+ UINT16 m_displacement;
+};
+
+// JScc : 0000 0110 RR00 cccc : A-112 //////////////////////////////////////////
+class Jscc_2: public Instruction
+{
+public:
+ Jscc_2(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_mnem = oINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_RR_table(BITSn(word0,0x00c0), m_destination);
+ decode_cccc_table(BITSn(word0,0x000f), m_mnem);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ astring opcode = "js" + opMnemonicAsString(m_mnem);
+ retString = opcode + " " + regIdAsString(m_destination);
+ // NEW // sprintf(opcode_str, "js.%s", M);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+ size_t flags() const { return DASMFLAG_STEP_OVER; }
+
+private:
+ op_mnem m_mnem;
+};
+
+// JSR : 0000 0001 0011 00-- xxxx xxxx xxxx xxxx : A-114 ///////////////////////
+class Jsr: public Instruction
+{
+public:
+ Jsr(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_displacement = 0;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ m_displacement = word1;
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ char temp[32];
+ sprintf(temp, ">$%x", m_displacement);
+ // NEW // sprintf(temp, "$%04x", word1);
+ retString = "jsr " + astring(temp);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 2; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+ size_t flags() const { return DASMFLAG_STEP_OVER; }
+
+private:
+ UINT16 m_displacement;
+};
+
+// JSR : 0000 1010 AAAA AAAA : A-114 ///////////////////////////////////////////
+class Jsr_2: public Instruction
+{
+public:
+ Jsr_2(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_bAddr = 0;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ m_bAddr = BITSn(word0,0x00ff);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ char temp[32];
+ sprintf(temp, "<$%x", m_bAddr);
+ // NEW // sprintf(temp, "#$%02x", BITSn(word0,0x00ff));
+ retString = "jsr " + astring(temp);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+ size_t flags() const { return DASMFLAG_STEP_OVER; }
+
+private:
+ UINT8 m_bAddr;
+};
+
+// JSR : 0000 0001 0010 00RR : A-114 ///////////////////////////////////////////
+class Jsr_3: public Instruction
+{
+public:
+ Jsr_3(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_RR_table(BITSn(word0,0x0003), m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "jsr " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+ size_t flags() const { return DASMFLAG_STEP_OVER; }
+};
+
+// LEA : 0000 0001 11TT MMRR : A-116 ///////////////////////////////////////////
+class Lea: public Instruction
+{
+public:
+ Lea(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_ea = "";
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ if ((word0 & 0x000c) == 0) return false; // NEW TODO //
+
+ decode_TT_table(BITSn(word0,0x0030), m_destination);
+
+ INT8 rNum = BITSn(word0,0x0003);
+ assemble_ea_from_MM_table(BITSn(word0,0x000c), rNum, m_ea);
+
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ // HACK
+ retString = "lea " + m_ea + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ astring m_ea;
+};
+
+// LEA : 0000 0001 10NN MMRR : A-116 ///////////////////////////////////////////
+class Lea_2: public Instruction
+{
+public:
+ Lea_2(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ if ((word0 & 0x000c) == 0) return false; // NEW TODO //
+
+ decode_NN_table(BITSn(word0,0x0030), m_destination);
+
+ INT8 rNum = BITSn(word0,0x0003);
+ assemble_ea_from_MM_table(BITSn(word0,0x000c), rNum, m_ea);
+
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ // HACK
+ retString = "lea " + m_ea + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ astring m_ea;
+};
+
+// LSL : .... .... 0011 F011 : A-118 ///////////////////////////////////////////
+class Lsl: public Instruction
+{
+public:
+ Lsl(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_F_table(BITSn(word0,0x08), m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "lsl " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE; }
+};
+
+// LSR : .... .... 0011 F010 : A-120 ///////////////////////////////////////////
+class Lsr: public Instruction
+{
+public:
+ Lsr(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_F_table(BITSn(word0,0x08), m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "lsr " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE; }
+};
+
+// MAC : .... .... 1k10 FQQQ : A-122 ///////////////////////////////////////////
+class Mac: public Instruction
+{
+public:
+ Mac(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_sign = "";
+ m_source2 = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_QQQF_table(BITSn(word0,0x07), BITSn(word0,0x08),
+ m_source, m_source2, m_destination);
+
+ decode_kSign_table(BITSn(word0,0x40), m_sign);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ astring ts = m_sign;
+ if (ts != "-") ts = "";
+ retString = "mac " +
+ ts +
+ regIdAsString(m_source) + "," +
+ regIdAsString(m_source2) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ reg_id m_source2;
+ astring m_sign;
+};
+
+// MAC : 011m mKKK 1xx0 F1QQ : A-122 ///////////////////////////////////////////
+class Mac_2: public Instruction
+{
+public:
+ Mac_2(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_source2 = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_QQF_table(BITSn(word0,0x03), BITSn(word0,0x08),
+ m_source, m_source2, m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "mac " +
+ regIdAsString(m_source) + "," +
+ regIdAsString(m_source2) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ reg_id m_source2;
+};
+
+// MAC : 0001 0111 RRDD FQQQ : A-122 ///////////////////////////////////////////
+class Mac_3: public Instruction
+{
+public:
+ Mac_3(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_source2 = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_QQQF_table(BITSn(word0,0x0007), BITSn(word0,0x0008),
+ m_source, m_source2, m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "mac " +
+ regIdAsString(m_source) + "," +
+ regIdAsString(m_source2) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ reg_id m_source2;
+};
+
+// MACR : .... .... 1k11 FQQQ : A-124 //////////////////////////////////////////
+class Macr: public Instruction
+{
+public:
+ Macr(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_sign = "";
+ m_source2 = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_QQQF_table(BITSn(word0,0x07), BITSn(word0,0x08),
+ m_source, m_source2, m_destination);
+
+ decode_kSign_table(BITSn(word0,0x40), m_sign);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ astring ts = m_sign;
+ if (ts != "-") ts = "";
+ retString = "macr " +
+ ts +
+ regIdAsString(m_source) + "," +
+ regIdAsString(m_source2) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ astring m_sign;
+ reg_id m_source2;
+};
+
+// MACR : 011m mKKK 1--1 F1QQ : A-124 //////////////////////////////////////////
+class Macr_2: public Instruction
+{
+public:
+ Macr_2(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_source2 = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_QQF_table(BITSn(word0,0x03), BITSn(word0,0x08),
+ m_source, m_source2, m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "macr " +
+ regIdAsString(m_source) + "," +
+ regIdAsString(m_source2) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ reg_id m_source2;
+};
+
+// MAC(su,uu) : 0001 0101 1110 FsQQ : A-126 ////////////////////////////////////
+class Macsuuu: public Instruction
+{
+public:
+ Macsuuu(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_mnem = oINVALID;
+ m_source2 = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ // Special QQF
+ decode_QQF_special_table(BITSn(word0,0x0003), BITSn(word0,0x0008),
+ m_source, m_source2, m_destination);
+
+ decode_s_table(BITSn(word0,0x0004), m_mnem);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ astring opcode = "mac" + opMnemonicAsString(m_mnem);
+
+ retString = opcode + " " +
+ regIdAsString(m_source) + "," +
+ regIdAsString(m_source2) + "," + regIdAsString(m_destination);
+ // NEW // sprintf(opcode_str, "mac(%s)", A);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ op_mnem m_mnem;
+ reg_id m_source2;
+};
+
+// MOVE : .... .... 0001 0001 : A-128 //////////////////////////////////////////
+class Move: public Instruction
+{
+public:
+ Move(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_isNop = false;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ // Equivalent to a NOP (+ parallel move)
+
+ // This insures the debugger matches the reference disassembler
+ // for the undocumented .... .... 0001 1001 Instruction.
+ if(BITSn(word0, 0x000f) == 0x0001)
+ m_destination = iA;
+ else
+ m_destination = iB;
+
+ // Hack to match reference disassembler
+ UINT8 BITSn = (word0 & 0xff00) >> 8;
+ if (BITSn == 0x4a || BITSn == 0x4b)
+ m_isNop = true;
+
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ if (m_isNop)
+ retString = "nop";
+ else
+ retString = "move";
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_NONE; }
+
+private:
+ bool m_isNop;
+};
+
+// MOVE : 011m mKKK 0rr1 0000 : A-128 //////////////////////////////////////////
+class Move_2: public Instruction
+{
+public:
+ Move_2(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ // Amounts to a nop with two parallel moves.
+ // This insures the debugger matches the reference disassembler
+ if((word0 & 0x0008) == 0x0008)
+ m_destination = iB;
+ else
+ m_destination = iA;
+
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "move";
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// MOVE : 0000 0101 BBBB BBBB ---- HHHW 0001 0001 : A-128 //////////////////////
+class Move_3: public Instruction
+{
+public:
+ Move_3(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_W = 0;
+ m_b = 0;
+ m_SD = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ m_b = BITSn(word0,0x00ff);
+ m_W = BITSn(word1,0x0100);
+ decode_HHH_table(BITSn(word1,0x0e00), m_SD);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ astring source;
+ astring destination;
+ assemble_reg_from_W_table(m_W, 'X', m_SD, m_b, source, destination);
+ retString = "move " + source + "," + destination;
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 2; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ INT8 m_b;
+ UINT8 m_W;
+ reg_id m_SD;
+};
+
+// MOVE(C) : 0011 1WDD DDD0 MMRR : A-144 ///////////////////////////////////////
+class Movec: public Instruction
+{
+public:
+ Movec(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_W = 0;
+ m_ea = "";
+ m_SD = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ INT8 rNum = BITSn(word0,0x0003);
+ assemble_ea_from_MM_table(BITSn(word0,0x000c), rNum, m_ea);
+
+ m_W = BITSn(word0,0x0400);
+ decode_DDDDD_table(BITSn(word0,0x03e0), m_SD);
+ if (m_SD == iINVALID) return false;
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ astring source;
+ astring destination;
+ assemble_arguments_from_W_table(m_W, 'X', m_SD, m_ea, source, destination);
+ retString = "move " + source + "," + destination;
+ // NEW // sprintf(opcode_str, "move(c)");
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ INT8 m_W;
+ reg_id m_SD;
+ astring m_ea;
+};
+
+// MOVE(C) : 0011 1WDD DDD1 q0RR : A-144 ///////////////////////////////////////
+class Movec_2: public Instruction
+{
+public:
+ Movec_2(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_W = 0;
+ m_ea = "";
+ m_SD = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ INT8 rNum = BITSn(word0,0x0003);
+ assemble_ea_from_q_table(BITSn(word0,0x0008), rNum, m_ea);
+
+ decode_DDDDD_table(BITSn(word0,0x03e0), m_SD);
+ m_W = BITSn(word0,0x0400);
+ if (m_SD == iINVALID) return false;
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ astring source;
+ astring destination;
+ assemble_arguments_from_W_table(m_W, 'X', m_SD, m_ea, source, destination);
+ retString = "move " + source + "," + destination;
+ // NEW // sprintf(opcode_str, "move(c)");
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ INT8 m_W;
+ reg_id m_SD;
+ astring m_ea;
+};
+
+// MOVE(C) : 0011 1WDD DDD1 Z11- : A-144 ///////////////////////////////////////
+class Movec_3: public Instruction
+{
+public:
+ Movec_3(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_W = 0;
+ m_ea = "";
+ m_SD = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_Z_table(BITSn(word0,0x0008), m_ea);
+
+ decode_DDDDD_table(BITSn(word0,0x03e0), m_SD);
+ m_W = BITSn(word0,0x0400);
+ if (m_SD == iINVALID) return false;
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ astring source;
+ astring destination;
+ assemble_arguments_from_W_table(m_W, 'X', m_SD, m_ea, source, destination);
+ retString = "move " + source + "," + destination;
+ // NEW // sprintf(opcode_str, "move(c)");
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ INT8 m_W;
+ reg_id m_SD;
+ astring m_ea;
+};
+
+// MOVE(C) : 0011 1WDD DDD1 t10- xxxx xxxx xxxx xxxx : A-144 ///////////////////
+class Movec_4: public Instruction
+{
+public:
+ Movec_4(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_t = 0;
+ m_W = 0;
+ m_sd = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ m_value = word1;
+ m_t = BITSn(word0,0x0008);
+ m_W = BITSn(word0,0x0400);
+
+ decode_DDDDD_table(BITSn(word0,0x03e0), m_sd);
+ if (m_sd == iINVALID) return false;
+
+ // TODO: Figure out what this means, exactly.
+ if ((word0 & 0x000c) == 0x000c && (word0 & 0x0400) == 0x0000)
+ return false;
+
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ astring ea;
+ assemble_ea_from_t_table(m_t, m_value, ea);
+
+ retString = "move ";
+ if (m_W) retString += ea + "," + regIdAsString(m_sd);
+ else retString += regIdAsString(m_sd) + "," + ea;
+ // NEW // sprintf(opcode_str, "move(c)");
+ }
+ void evaluate(dsp56k_core* cpustate)
+ {
+ if (m_W)
+ {
+ if (m_t)
+ {
+ setReg16(cpustate, m_value, m_sd);
+ }
+ else
+ {
+ //UINT16 memValue = memory_read_word_16le(cpustate->data, ADDRESS(m_value));
+ //setReg16(cpustate, memValue, m_sd);
+ }
+ }
+ else
+ {
+ if (m_t)
+ {
+ logerror("DSP561xx|Movec_4: This sure seems like it can't happen.");
+ }
+ else
+ {
+ //UINT16 regValue = regValue16(cpustate, m_sd);
+ //memory_write_word_16le(cpustate->data, m_value, regValue);
+ }
+ }
+
+ /* S L E U N Z V C */
+ /* * ? ? ? ? ? ? ? */
+ // All ? bits - If SR is specified as a destination operand, set according to the corresponding
+ // bit of the source operand. If SR is not specified as a destination operand, L is set if data
+ // limiting occurred. All ? bits are not affected otherwise.
+ }
+ size_t size() const { return 2; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ UINT8 m_t;
+ UINT8 m_W;
+ UINT16 m_value;
+ reg_id m_sd;
+};
+
+// MOVE(C) : 0010 10dd dddD DDDD : A-144 ///////////////////////////////////////
+class Movec_5: public Instruction
+{
+public:
+ Movec_5(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_DDDDD_table(BITSn(word0,0x03e0), m_source);
+ decode_DDDDD_table(BITSn(word0,0x001f), m_destination);
+
+ if (m_source == iINVALID || m_destination == iINVALID) return false;
+ if (m_source == iSSH && m_destination == iSSH) return false;
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "move " + regIdAsString(m_source) + "," + regIdAsString(m_destination);
+ // NEW // sprintf(opcode_str, "move(c)");
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// MOVE(C) : 0000 0101 BBBB BBBB 0011 1WDD DDD0 ---- : A-144 ///////////////////
+class Movec_6: public Instruction
+{
+public:
+ Movec_6(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_W = 0;
+ m_b = 0;
+ m_SD = iINVALID;
+ m_mnem = oINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ m_b = BITSn(word0,0x00ff);
+ m_W = BITSn(word1,0x0400);
+ decode_DDDDD_table(BITSn(word1,0x03e0), m_SD);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ astring source;
+ astring destination;
+ assemble_reg_from_W_table(m_W, 'X', m_SD, m_b, source, destination);
+ retString = "move " + source + "," + destination;
+ // NEW // opcode = "move(c)";
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 2; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ INT8 m_b;
+ UINT8 m_W;
+ reg_id m_SD;
+ op_mnem m_mnem;
+};
+
+// MOVE(I) : 0010 00DD BBBB BBBB : A-150 ///////////////////////////////////////
+class Movei: public Instruction
+{
+public:
+ Movei(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_immediate = 0;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ m_immediate = (INT8)BITSn(word0,0x00ff);
+ decode_DD_table(BITSn(word0,0x0300), m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ char temp[32];
+ if (m_immediate >= 0) sprintf(temp, "#<+$%x", m_immediate);
+ else sprintf(temp, "#<-$%x", 1 - m_immediate - 1);
+ // NEW // sprintf(temp, "#$%02x,%s", BITSn(word0,0x00ff), D1);
+
+ retString = "move " +
+ astring(temp) + "," + regIdAsString(m_destination);
+ // NEW // sprintf(opcode_str, "move(i)");
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ INT8 m_immediate;
+};
+
+// MOVE(M) : 0000 001W RR0M MHHH : A-152 ///////////////////////////////////////
+class Movem: public Instruction
+{
+public:
+ Movem(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_W = 0;
+ m_ea = "";
+ m_SD = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ INT8 rNum = BITSn(word0,0x00c0);
+
+ decode_HHH_table(BITSn(word0,0x0007), m_SD);
+ assemble_ea_from_MM_table(BITSn(word0,0x0018), rNum, m_ea);
+ m_W = BITSn(word0,0x0100);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ astring source;
+ astring destination;
+ assemble_arguments_from_W_table(m_W, 'P', m_SD, m_ea, source, destination);
+ retString = "move " + source + "," + destination;
+ // NEW // sprintf(opcode_str, "move(m)");
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ INT8 m_W;
+ reg_id m_SD;
+ astring m_ea;
+};
+
+// MOVE(M) : 0000 001W RR11 mmRR : A-152 ///////////////////////////////////////
+class Movem_2: public Instruction
+{
+public:
+ Movem_2(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_W = 0;
+ m_ea = "";
+ m_ea2 = "";
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ m_W = BITSn(word0,0x0100);
+ assemble_eas_from_mm_table(BITSn(word0,0x000c), BITSn(word0,0x00c0), BITSn(word0,0x0003), m_ea, m_ea2);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ astring source;
+ astring destination;
+ if (m_W)
+ {
+ source = "X:" + m_ea;
+ destination = "P:" + m_ea2;
+ }
+ else
+ {
+ source = "P:" + m_ea;
+ destination = "X:" + m_ea2;
+ }
+ retString = "move " + source + "," + destination;
+ // NEW // sprintf(opcode_str, "move(m)*");
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ UINT8 m_W;
+ astring m_ea;
+ astring m_ea2;
+};
+
+// MOVE(M) : 0000 0101 BBBB BBBB 0000 001W --0- -HHH : A-152 ///////////////////
+class Movem_3: public Instruction
+{
+public:
+ Movem_3(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_b = 0;
+ m_SD = iINVALID;
+ m_mnem = oINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ m_b = BITSn(word0,0x00ff);
+ m_W = BITSn(word1,0x0100);
+ decode_HHH_table(BITSn(word1,0x0007), m_SD);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ astring source;
+ astring destination;
+ assemble_reg_from_W_table(m_W, 'P', m_SD, m_b, source, destination);
+ retString = "move " + source + "," + destination;
+ // NEW // opcode = "move(m)";
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 2; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ INT8 m_b;
+ UINT8 m_W;
+ reg_id m_SD;
+ op_mnem m_mnem;
+};
+
+// MOVE(P) : 0001 100W HH1p pppp : A-156 ///////////////////////////////////////
+class Movep: public Instruction
+{
+public:
+ Movep(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_W = 0;
+ m_ea = "";
+ m_SD = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_HH_table(BITSn(word0,0x00c0), m_SD);
+
+ assemble_address_from_IO_short_address(BITSn(word0,0x001f), m_ea);
+ m_ea = "<<$" + m_ea;
+
+ m_W = BITSn(word0,0x0100);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ astring source;
+ astring destination;
+ assemble_arguments_from_W_table(m_W, 'X', m_SD, m_ea, source, destination);
+ retString = "movep " + source + "," + destination;
+ // NEW // sprintf(opcode_str, "move(p)");
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ INT8 m_W;
+ reg_id m_SD;
+ astring m_ea;
+};
+
+// MOVE(P) : 0000 110W RRmp pppp : A-156 ///////////////////////////////////////
+class Movep_2: public Instruction
+{
+public:
+ Movep_2(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_W = 0;
+ m_ea = "";
+ m_SD = "";
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ INT8 rNum = BITSn(word0,0x00c0);
+
+ assemble_ea_from_m_table(BITSn(word0,0x0020), rNum, m_ea);
+
+ astring fullAddy; /* Convert Short Absolute Address to full 16-bit */
+ assemble_address_from_IO_short_address(BITSn(word0,0x001f), fullAddy);
+
+ m_W = BITSn(word0,0x0100);
+ m_SD = "X:<<$" + fullAddy;
+ // NEW // sprintf(SD, "X:$%s", fullAddy);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ astring source;
+ astring destination;
+ assemble_arguments_from_W_table(m_W, 'X', m_SD, m_ea, source, destination);
+ retString = "movep " + source + "," + destination;
+ // NEW // sprintf(opcode_str, "move(p)*");
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ INT8 m_W;
+ astring m_SD;
+ astring m_ea;
+};
+
+// MOVE(S) : 0001 100W HH0a aaaa : A-158 ///////////////////////////////////////
+class Moves: public Instruction
+{
+public:
+ Moves(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_W = 0;
+ m_ea = "";
+ m_SD = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_HH_table(BITSn(word0,0x00c0), m_SD);
+
+ char temp[32];
+ sprintf(temp, "<$%x", BITSn(word0,0x001f));
+ m_ea = temp;
+
+ m_W = BITSn(word0,0x0100);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ astring source;
+ astring destination;
+ assemble_arguments_from_W_table(m_W, 'X', m_SD, m_ea, source, destination);
+ retString = "moves " + source + "," + destination;
+ // NEW // sprintf(opcode_str, "move(s)");
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ INT8 m_W;
+ reg_id m_SD;
+ astring m_ea;
+};
+
+// MPY : .... .... 1k00 FQQQ : A-160 ///////////////////////////////////////////
+class Mpy: public Instruction
+{
+public:
+ Mpy(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_sign = "";
+ m_source2 = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ /* There are inconsistencies with the S1 & S2 operand ordering in the docs,
+ but since it's a multiply it doesn't matter */
+ decode_QQQF_table(BITSn(word0,0x07), BITSn(word0,0x08),
+ m_source, m_source2, m_destination);
+
+ decode_kSign_table(BITSn(word0,0x40), m_sign);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ astring ts = m_sign;
+ if (ts != "-") ts = "";
+ retString = "mpy " +
+ ts +
+ regIdAsString(m_source) + "," +
+ regIdAsString(m_source2) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ astring m_sign;
+ reg_id m_source2;
+};
+
+// MPY : 011m mKKK 1xx0 F0QQ : A-160 ///////////////////////////////////////////
+class Mpy_2: public Instruction
+{
+public:
+ Mpy_2(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_source2 = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_QQF_table(BITSn(word0,0x03), BITSn(word0,0x08),
+ m_source, m_source2, m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "mpy " +
+ regIdAsString(m_source) + "," +
+ regIdAsString(m_source2) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ reg_id m_source2;
+};
+
+// MPY : 0001 0110 RRDD FQQQ : A-160 ///////////////////////////////////////////
+class Mpy_3: public Instruction
+{
+public:
+ Mpy_3(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_source2 = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_QQQF_table(BITSn(word0,0x0007), BITSn(word0,0x0008),
+ m_source, m_source2, m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "mpy " +
+ regIdAsString(m_source) + "," +
+ regIdAsString(m_source2) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ reg_id m_source2;
+};
+
+// MPYR : .... .... 1k01 FQQQ : A-162 //////////////////////////////////////////
+class Mpyr: public Instruction
+{
+public:
+ Mpyr(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_sign = "-";
+ m_source2 = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ /* There are inconsistencies with the S1 & S2 operand ordering in the docs,
+ but since it's a multiply it doesn't matter */
+ decode_QQQF_table(BITSn(word0,0x07), BITSn(word0,0x08),
+ m_source, m_source2, m_destination);
+
+ decode_kSign_table(BITSn(word0,0x40), m_sign);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ astring ts = m_sign;
+ if (ts != "-") ts = "";
+ retString = "mpyr " +
+ ts +
+ regIdAsString(m_source) + "," +
+ regIdAsString(m_source2) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ astring m_sign;
+ reg_id m_source2;
+};
+
+// MPYR : 011m mKKK 1--1 F0QQ : A-162 //////////////////////////////////////////
+class Mpyr_2: public Instruction
+{
+public:
+ Mpyr_2(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_source2 = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_QQF_table(BITSn(word0,0x03), BITSn(word0,0x08),
+ m_source, m_source2, m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "mpyr " +
+ regIdAsString(m_source) + "," +
+ regIdAsString(m_source2) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ reg_id m_source2;
+};
+
+// MPY(su,uu) : 0001 0101 1100 FsQQ : A-164 ////////////////////////////////////
+class Mpysuuu: public Instruction
+{
+public:
+ Mpysuuu(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_mnem = oINVALID;
+ m_source2 = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_QQF_special_table(BITSn(word0,0x0003), BITSn(word0,0x0008),
+ m_source, m_source2, m_destination);
+
+ decode_s_table(BITSn(word0,0x0004), m_mnem);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ astring opcode = "mpy" + opMnemonicAsString(m_mnem);
+
+ retString = opcode + " " +
+ regIdAsString(m_source) + "," +
+ regIdAsString(m_source2) + "," + regIdAsString(m_destination);
+ // NEW // sprintf(opcode_str, "mpy(%s)", A);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ op_mnem m_mnem;
+ reg_id m_source2;
+};
+
+// NEG : .... .... 0110 F000 : A-166 ///////////////////////////////////////////
+class Neg: public Instruction
+{
+public:
+ Neg(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_F_table(BITSn(word0,0x08), m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "neg " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// NEGC : 0001 0101 0110 F000 : A-168 //////////////////////////////////////////
+class Negc: public Instruction
+{
+public:
+ Negc(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_F_table(BITSn(word0,0x0008), m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "negc " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// NOP : 0000 0000 0000 0000 : A-170 ///////////////////////////////////////////
+class Nop: public Instruction
+{
+public:
+ Nop(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "nop";
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// NORM : 0001 0101 0010 F0RR : A-172 //////////////////////////////////////////
+class Norm: public Instruction
+{
+public:
+ Norm(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_F_table(BITSn(word0,0x0008), m_destination);
+
+ decode_RR_table(BITSn(word0,0x0003), m_source);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "norm " + regIdAsString(m_source) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// NOT : .... .... 0110 F001 : A-174 ///////////////////////////////////////////
+class Not: public Instruction
+{
+public:
+ Not(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_F_table(BITSn(word0,0x08), m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "not " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE; }
+};
+
+// OR : .... .... 0010 F1JJ : A-176 ////////////////////////////////////////////
+class Or: public Instruction
+{
+public:
+ Or(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_JJF_table(BITSn(word0,0x03),BITSn(word0,0x08),
+ m_source, m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "or " + regIdAsString(m_source) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE; }
+};
+
+// ORI : 0001 1EE1 iiii iiii : A-178 ///////////////////////////////////////////
+class Ori: public Instruction
+{
+public:
+ Ori(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_immediate = 0;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ m_immediate = BITSn(word0,0x00ff);
+ decode_EE_table(BITSn(word0,0x0600), m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ char temp[32];
+ sprintf(temp, "#$%x", m_immediate);
+ // NEW // sprintf(temp, "#$%02x", BITSn(word0,0x00ff));
+ retString = "ori " + astring(temp) + "," + regIdAsString(m_destination);
+ // NEW // sprintf(opcode_str, "or(i)");
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ UINT8 m_immediate;
+};
+
+// REP : 0000 0000 111- --RR : A-180 ///////////////////////////////////////////
+class Rep: public Instruction
+{
+public:
+ Rep(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_RR_table(BITSn(word0,0x0003), m_source);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ char temp[32];
+ sprintf(temp, "X:(%s)", regIdAsString(m_source).cstr());
+ retString = "rep " + astring(temp);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// REP : 0000 1111 iiii iiii : A-180 ///////////////////////////////////////////
+class Rep_2: public Instruction
+{
+public:
+ Rep_2(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_immediate = 0;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ m_immediate = BITSn(word0,0x00ff);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ char temp[32];
+ sprintf(temp, "#$%x", m_immediate);
+ // NEW // sprintf(temp, "#$%02x (%d)", BITSn(word0,0x00ff), BITSn(word0,0x00ff));
+ retString = "rep " + astring(temp);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ UINT8 m_immediate;
+};
+
+// REP : 0000 0100 001D DDDD : A-180 ///////////////////////////////////////////
+class Rep_3: public Instruction
+{
+public:
+ Rep_3(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_DDDDD_table(BITSn(word0,0x001f), m_source);
+ if (m_source == iINVALID) return false;
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "rep " + regIdAsString(m_source);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// REPcc : 0000 0001 0101 cccc : A-184 /////////////////////////////////////////
+class Repcc: public Instruction
+{
+public:
+ Repcc(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_mnem = oINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_cccc_table(BITSn(word0,0x000f), m_mnem);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ astring opcode = "rep" + opMnemonicAsString(m_mnem);
+ retString = opcode;
+ // NEW // sprintf(opcode_str, "rep.%s", M);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ op_mnem m_mnem;
+};
+
+// RESET : 0000 0000 0000 1000 : A-186 /////////////////////////////////////////
+class Reset: public Instruction
+{
+public:
+ Reset(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "reset";
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// RND : .... .... 0010 F000 : A-188 ///////////////////////////////////////////
+class Rnd: public Instruction
+{
+public:
+ Rnd(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_F_table(BITSn(word0,0x08), m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "rnd " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// ROL : .... .... 0111 F011 : A-190 ///////////////////////////////////////////
+class Rol: public Instruction
+{
+public:
+ Rol(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_F_table(BITSn(word0,0x08), m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "rol " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE; }
+};
+
+// ROR : .... .... 0111 F010 : A-192 ///////////////////////////////////////////
+class Ror: public Instruction
+{
+public:
+ Ror(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_F_table(BITSn(word0,0x08), m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "ror " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE; }
+};
+
+// RTI : 0000 0000 0000 0111 : A-194 ///////////////////////////////////////////
+class Rti: public Instruction
+{
+public:
+ Rti(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "rti";
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+ size_t flags() const { return DASMFLAG_STEP_OUT; }
+};
+
+// RTS : 0000 0000 0000 0110 : A-196 ///////////////////////////////////////////
+class Rts: public Instruction
+{
+public:
+ Rts(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "rts";
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+ size_t flags() const { return DASMFLAG_STEP_OUT; }
+};
+
+// SBC : .... .... 0101 F01J : A-198 ///////////////////////////////////////////
+class Sbc: public Instruction
+{
+public:
+ Sbc(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_JF_table(BITSn(word0,0x01), BITSn(word0,0x08),
+ m_source, m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "sbc " + regIdAsString(m_source) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// STOP : 0000 0000 0000 1010 : A-200 //////////////////////////////////////////
+class Stop: public Instruction
+{
+public:
+ Stop(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "stop";
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// SUB : .... .... 0100 FJJJ : A-202 ///////////////////////////////////////////
+class Sub: public Instruction
+{
+public:
+ Sub(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_JJJF_table(BITSn(word0,0x07), BITSn(word0,0x08),
+ m_source, m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "sub " + regIdAsString(m_source) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// SUB : 011m mKKK 0rru Fuuu : A-202 ///////////////////////////////////////////
+class Sub_2: public Instruction
+{
+public:
+ Sub_2(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_opcode = "";
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_uuuuF_table(BITSn(word0,0x17), BITSn(word0,0x08),
+ m_opcode, m_source, m_destination);
+
+ // TODO // m_opcode = "sub";
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = m_opcode + " " + regIdAsString(m_source) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ astring m_opcode;
+};
+
+// SUBL : .... .... 0100 F001 : A-204 //////////////////////////////////////////
+class Subl: public Instruction
+{
+public:
+ Subl(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ /* There is only one option for the F table. This is a very strange opcode. */
+ if (!BITSn(word0,0x0008))
+ {
+ m_source = iB;
+ m_destination = iA;
+ }
+ else
+ {
+ m_source = iA;
+ m_destination = iB;
+ }
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "subl " + regIdAsString(m_source) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// SWAP : 0001 0101 0111 F001 : A-206 //////////////////////////////////////////
+class Swap: public Instruction
+{
+public:
+ Swap(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_F_table(BITSn(word0,0x0008), m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "swap " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// SWI : 0000 0000 0000 0101 : A-208 ///////////////////////////////////////////
+class Swi: public Instruction
+{
+public:
+ Swi(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "swi";
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// Tcc : 0001 00cc ccTT Fh0h : A-210 ///////////////////////////////////////////
+class Tcc: public Instruction
+{
+public:
+ Tcc(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_mnem = oINVALID;
+ m_destination2 = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_h0hF_table(BITSn(word0,0x0007),BITSn(word0,0x0008),
+ m_source, m_destination);
+
+ decode_RR_table(BITSn(word0,0x0030), m_destination2);
+
+ decode_cccc_table(BITSn(word0,0x03c0), m_mnem);
+ if (m_source != m_destination)
+ return true;
+ if (m_destination2 != iR0)
+ return true;
+
+ return false;
+ }
+ void disassemble(astring& retString) const
+ {
+ astring opcode = "t" + opMnemonicAsString(m_mnem);
+ // NEW // sprintf(opcode_str, "t.%s", M);
+
+ retString = opcode;
+ if (m_source != m_destination)
+ retString += astring(" ") + regIdAsString(m_source) + "," + regIdAsString(m_destination);
+
+ if (m_destination2 != iR0)
+ retString += astring(" R0,") + regIdAsString(m_destination2);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ op_mnem m_mnem;
+ reg_id m_destination2;
+};
+
+// TFR : .... .... 0001 FJJJ : A-212 ///////////////////////////////////////////
+class Tfr: public Instruction
+{
+public:
+ Tfr(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_JJJF_table(BITSn(word0,0x07), BITSn(word0,0x08),
+ m_source, m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "tfr " + regIdAsString(m_source) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// TFR : 011m mKKK 0rr1 F0DD : A-212 ///////////////////////////////////////////
+class Tfr_2: public Instruction
+{
+public:
+ Tfr_2(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_DDF_table(BITSn(word0,0x03), BITSn(word0,0x08),
+ m_source, m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "tfr " + regIdAsString(m_source) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// TFR(2) : 0001 0101 0000 F00J : A-214 ////////////////////////////////////////
+class Tfr2: public Instruction
+{
+public:
+ Tfr2(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_JF_table(BITSn(word0,0x0001),BITSn(word0,0x0008),
+ m_destination, m_source);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "tfr2 " + regIdAsString(m_source) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// TFR(3) : 0010 01mW RRDD FHHH : A-216 ////////////////////////////////////////
+class Tfr3: public Instruction
+{
+public:
+ Tfr3(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_W = 0;
+ m_ea = "";
+ m_SD = iINVALID;
+ m_source2 = iINVALID;
+ m_destination2 = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_DDF_table(BITSn(word0,0x0030), BITSn(word0,0x0008),
+ m_destination, m_source);
+
+ decode_HHH_table(BITSn(word0,0x0007), m_SD);
+ // If the destination of the second move is the same as the first, you're invalid
+ if (m_SD == m_destination && BITSn(word0,0x0100)) return false;
+
+ INT8 rNum = BITSn(word0,0x00c0);
+ assemble_ea_from_m_table(BITSn(word0,0x0200), rNum, m_ea);
+
+ m_W = BITSn(word0,0x0100);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ astring source2;
+ astring destination2;
+ assemble_arguments_from_W_table(m_W, 'X', m_SD, m_ea, source2, destination2);
+ retString = "tfr3 " +
+ regIdAsString(m_source) + "," + regIdAsString(m_destination) + " " +
+ source2 + "," + destination2;
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ INT8 m_W;
+ reg_id m_SD;
+ astring m_ea;
+ reg_id m_source2;
+ reg_id m_destination2;
+};
+
+// TST : .... .... 0010 F001 : A-218 ///////////////////////////////////////////
+class Tst: public Instruction
+{
+public:
+ Tst(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_F_table(BITSn(word0,0x08), m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "tst " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_NONE; }
+};
+
+// TST(2) : 0001 0101 0001 -1DD : A-220 ////////////////////////////////////////
+class Tst2: public Instruction
+{
+public:
+ Tst2(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_DD_table(BITSn(word0,0x0003), m_source);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "tst2 " + regIdAsString(m_source);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// WAIT : 0000 0000 0000 1011 : A-222 //////////////////////////////////////////
+class Wait: public Instruction
+{
+public:
+ Wait(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "wait";
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// ZERO : 0001 0101 0101 F000 : A-224 //////////////////////////////////////////
+class Zero: public Instruction
+{
+public:
+ Zero(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_F_table(BITSn(word0,0x0008), m_destination);
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "zero " + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+};
+
+// SHFL : 0001 0101 1101 FQQQ : !!UNDOCUMENTED!! ///////////////////////////////
+class Shfl: public Instruction
+{
+public:
+ Shfl(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_source2 = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_QQQF_table(BITSn(word0,0x0007), BITSn(word0,0x0008),
+ m_source, m_source2, m_destination);
+
+ // This hackery amounts to a very strange QQQF table...
+ if (m_source == iX0 && m_source2 == iX0) return false;
+ if (m_source == iX1 && m_source2 == iX0) return false;
+
+ if (m_source == iY0 && m_source2 == iX1)
+ {
+ m_source = iX1;
+ m_source2 = iY0;
+ }
+ if (m_source == iY1 && m_source2 == iX1)
+ {
+ m_source = iX1;
+ m_source2 = iY1;
+ }
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "shfl " +
+ regIdAsString(m_source) + "," +
+ regIdAsString(m_source2) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ reg_id m_source2;
+};
+
+// SHFR : 0001 0101 1111 FQQQ : !!UNDOCUMENTED!! ///////////////////////////////
+class Shfr: public Instruction
+{
+public:
+ Shfr(const Opcode* oco, const UINT16 word0, const UINT16 word1) : Instruction(oco)
+ {
+ m_source2 = iINVALID;
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_QQQF_table(BITSn(word0,0x0007), BITSn(word0,0x0008),
+ m_source, m_source2, m_destination);
+
+ // This hackery amounts to a very strange QQQF table...
+ if (m_source == iX0 && m_source2 == iX0) return false;
+ if (m_source == iX1 && m_source2 == iX0) return false;
+
+ if (m_source == iY0 && m_source2 == iX1)
+ {
+ m_source = iX1;
+ m_source2 = iY0;
+ }
+ if (m_source == iY1 && m_source2 == iX1)
+ {
+ m_source = iX1;
+ m_source2 = iY1;
+ }
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = "shfr " +
+ regIdAsString(m_source) + "," +
+ regIdAsString(m_source2) + "," + regIdAsString(m_destination);
+ }
+ void evaluate(dsp56k_core* cpustate) {}
+ size_t size() const { return 1; }
+ size_t accumulatorBitsModified() const { return BM_HIGH | BM_MIDDLE | BM_LOW; }
+
+private:
+ reg_id m_source2;
+};
+
+}
+#endif
diff --git a/trunk/src/emu/cpu/dsp56k/opcode.c b/trunk/src/emu/cpu/dsp56k/opcode.c
new file mode 100644
index 00000000000..0e9ad3706dc
--- /dev/null
+++ b/trunk/src/emu/cpu/dsp56k/opcode.c
@@ -0,0 +1,81 @@
+#include <stdio.h>
+
+#include "opcode.h"
+
+namespace DSP56K
+{
+
+Opcode::Opcode(UINT16 w0, UINT16 w1) : m_word0(w0), m_word1(w1)
+{
+ m_instruction = Instruction::decodeInstruction(this, w0, w1);
+ m_parallelMove = ParallelMove::decodeParallelMove(this, w0, w1);
+}
+
+
+Opcode::~Opcode()
+{
+ global_free(m_instruction);
+ global_free(m_parallelMove);
+}
+
+
+astring Opcode::disassemble() const
+{
+ // Duck out early if there isn't a valid op
+ if (!m_instruction)
+ return dcString();
+
+ // Duck out if either has had an explicit error.
+ if (m_instruction && !m_instruction->valid())
+ return dcString();
+ if (m_parallelMove && !m_parallelMove->valid())
+ return dcString();
+
+ // Disassemble what you can.
+ astring opString = "";
+ astring pmString = "";
+ if (m_instruction) m_instruction->disassemble(opString);
+ if (m_parallelMove) m_parallelMove->disassemble(pmString);
+
+ return opString + " " + pmString;
+}
+
+
+void Opcode::evaluate(dsp56k_core* cpustate) const
+{
+ if (m_instruction) m_instruction->evaluate(cpustate);
+ if (m_parallelMove) m_parallelMove->evaluate();
+}
+
+
+size_t Opcode::size() const
+{
+ if (m_instruction && m_instruction->valid())
+ return m_instruction->size() + m_instruction->sizeIncrement();
+
+ // Opcode failed to decode, so push it past dc
+ return 1;
+}
+
+size_t Opcode::evalSize() const
+{
+ if (m_instruction && m_instruction->valid())
+ return m_instruction->evalSize(); // Probably doesn't matter : + m_instruction->sizeIncrement();
+
+ // Opcode failed to decode, so push it past dc
+ return 1;
+}
+
+
+const reg_id& Opcode::instSource() const { return m_instruction->source(); }
+const reg_id& Opcode::instDestination() const { return m_instruction->destination(); }
+const size_t Opcode::instAccumulatorBitsModified() const { return m_instruction->accumulatorBitsModified(); }
+
+astring Opcode::dcString() const
+{
+ char tempStr[1024];
+ sprintf(tempStr, "dc $%x", m_word0);
+ return astring(tempStr);
+}
+
+}
diff --git a/trunk/src/emu/cpu/dsp56k/opcode.h b/trunk/src/emu/cpu/dsp56k/opcode.h
new file mode 100644
index 00000000000..cd841e2d1a8
--- /dev/null
+++ b/trunk/src/emu/cpu/dsp56k/opcode.h
@@ -0,0 +1,46 @@
+#ifndef __DSP56K_OPCODE_H__
+#define __DSP56K_OPCODE_H__
+
+#include "emu.h"
+#include "inst.h"
+#include "pmove.h"
+
+#include "dsp56k.h"
+
+//
+// An Opcode contains an instruction and a parallel move operation.
+//
+namespace DSP56K
+{
+
+class Instruction;
+class ParallelMove;
+
+class Opcode
+{
+public:
+ Opcode(UINT16 w0, UINT16 w1);
+ virtual ~Opcode();
+
+ astring disassemble() const;
+ void evaluate(dsp56k_core* cpustate) const;
+ size_t size() const;
+ size_t evalSize() const;
+
+ // Peek through to the instruction
+ const reg_id& instSource() const;
+ const reg_id& instDestination() const;
+ const size_t instAccumulatorBitsModified() const;
+
+private:
+ Instruction* m_instruction;
+ ParallelMove* m_parallelMove;
+
+ UINT16 m_word0;
+ UINT16 m_word1;
+
+ astring dcString() const;
+};
+
+}
+#endif
diff --git a/trunk/src/emu/cpu/dsp56k/pmove.c b/trunk/src/emu/cpu/dsp56k/pmove.c
new file mode 100644
index 00000000000..a3f6a0dada4
--- /dev/null
+++ b/trunk/src/emu/cpu/dsp56k/pmove.c
@@ -0,0 +1,78 @@
+#include "pmove.h"
+
+namespace DSP56K
+{
+
+const reg_id& ParallelMove::opSource() const { return m_oco->instSource(); }
+const reg_id& ParallelMove::opDestination() const { return m_oco->instDestination(); }
+const size_t ParallelMove::opAccumulatorBitsModified() const { return m_oco->instAccumulatorBitsModified(); }
+
+
+ParallelMove* ParallelMove::decodeParallelMove(const Opcode* opc, const UINT16 word0, const UINT16 word1)
+{
+ const UINT16 w0 = word0;
+ const UINT16 w1 = word1;
+
+ /* Dual X Memory Data Read : 011m mKKK .rr. .... : A-142*/
+ if ((w0 & 0xe000) == 0x6000)
+ {
+ return global_alloc(DualXMemoryDataRead(opc, w0, w1));
+ }
+ /* X Memory Data Write and Register Data Move : 0001 011k RRDD .... : A-140 */
+ else if ((w0 & 0xfe00) == 0x1600)
+ {
+ return global_alloc(XMemoryDataWriteAndRegisterDataMove(opc, w0, w1));
+ }
+ else
+ {
+ /* 32 General parallel move operations */
+ /* Note: It's important that NPDM comes before RtRDM */
+
+ /* No Parallel Data Move : 0100 1010 .... .... : A-131 */
+ if ((w0 & 0xff00) == 0x4a00)
+ {
+ return NULL;
+ }
+ /* Register to Register Data Move : 0100 IIII .... .... : A-133 */
+ else if ((w0 & 0xf000) == 0x4000)
+ {
+ return global_alloc(RegisterToRegisterDataMove(opc, w0, w1));
+ }
+ /* Address Register Update : 0011 0zRR .... .... : A-135 */
+ else if ((w0 & 0xf800) == 0x3000)
+ {
+ return global_alloc(AddressRegisterUpdate(opc, w0, w1));
+ }
+ /* X Memory Data Move : 1mRR HHHW .... .... : A-137 */
+ else if ((w0 & 0x8000) == 0x8000)
+ {
+ return global_alloc(XMemoryDataMove(opc, w0, w1));
+ }
+ /* X Memory Data Move : 0101 HHHW .... .... : A-137 */
+ else if ((w0 & 0xf000) == 0x5000)
+ {
+ return global_alloc(XMemoryDataMove_2(opc, w0, w1));
+ }
+ /* X Memory Data Move with short displacement : 0000 0101 BBBB BBBB ---- HHHW .... .... : A-139 */
+ else if ((w0 & 0xff00) == 0x0500)
+ {
+ // Now check it against all potential double-ups.
+ // These operations can't have an additional parallel move.
+ //
+ // MOVE(M) : 0000 0101 BBBB BBBB 0000 001W --0- -HHH : A-152
+ // MOVE(C) : 0000 0101 BBBB BBBB 0011 1WDD DDD0 ---- : A-144
+ // MOVE : 0000 0101 BBBB BBBB ---- HHHW 0001 0001 : A-128
+ //
+ if (((w1 & 0xfe20) != 0x0200) &&
+ ((w1 & 0xf810) != 0x3800) &&
+ ((w1 & 0x00ff) != 0x0011))
+ {
+ return global_alloc(XMemoryDataMoveWithShortDisplacement(opc, w0, w1));
+ }
+ }
+ }
+
+ return NULL;
+}
+
+}
diff --git a/trunk/src/emu/cpu/dsp56k/pmove.h b/trunk/src/emu/cpu/dsp56k/pmove.h
new file mode 100644
index 00000000000..eb1412be956
--- /dev/null
+++ b/trunk/src/emu/cpu/dsp56k/pmove.h
@@ -0,0 +1,337 @@
+#ifndef __DSP56K_PARALLEL_MOVE_H__
+#define __DSP56K_PARALLEL_MOVE_H__
+
+#include "emu.h"
+#include "opcode.h"
+#include "tables.h"
+
+//
+// A ParallelMove Object is what all parallel move classes inherit from.
+//
+namespace DSP56K
+{
+
+class Opcode;
+
+class ParallelMove
+{
+public:
+ ParallelMove(const Opcode* oco) : m_valid(false), m_oco(oco) { }
+ virtual ~ParallelMove() {}
+
+ virtual bool decode(const UINT16 word0, const UINT16 word1) = 0;
+ virtual void disassemble(astring& retString) const = 0;
+ virtual void evaluate() = 0;
+
+ static ParallelMove* decodeParallelMove(const Opcode* opc, const UINT16 word0, const UINT16 word1);
+
+ const bool valid() const { return m_valid; }
+
+ // Peek through the opcode to see the instruction
+ const reg_id& opSource() const;
+ const reg_id& opDestination() const;
+ const size_t opAccumulatorBitsModified() const;
+
+protected:
+ bool m_valid;
+ const Opcode* m_oco;
+};
+
+
+////////////////////////////////////////////////////////////////////////////////
+// PARALLEL MOVES ////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+/* X Memory Data Move : 1mRR HHHW .... .... : A-137 */
+class XMemoryDataMove: public ParallelMove
+{
+public:
+ XMemoryDataMove(const Opcode* oco, const UINT16 word0, const UINT16 word1) : ParallelMove(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ reg_id r;
+ decode_RR_table(BITSn(word0,0x3000), r);
+
+ reg_id SD;
+ decode_HHH_table(BITSn(word0,0x0e00), SD);
+
+ astring ea;
+ assemble_ea_from_m_table(BITSn(word0,0x4000), regIDAsNum(r), ea);
+
+ assemble_arguments_from_W_table(BITSn(word0,0x0100), 'X', SD, ea,
+ m_source, m_destination);
+
+ // If the destination of the instruction overlaps with our destination, abort.
+ if (registerOverlap(opDestination(), opAccumulatorBitsModified(), stringAsRegID(m_destination)))
+ return false;
+
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = m_source + "," + m_destination;
+ }
+ void evaluate() {}
+
+private:
+ astring m_source;
+ astring m_destination;
+};
+
+
+/* X Memory Data Move : 0101 HHHW .... .... : A-137 */
+class XMemoryDataMove_2: public ParallelMove
+{
+public:
+ XMemoryDataMove_2(const Opcode* oco, const UINT16 word0, const UINT16 word1) : ParallelMove(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ astring ea;
+ if (opDestination() == iB)
+ ea = "(A1)";
+ else if (opDestination() == iA)
+ ea = "(B1)";
+ else
+ ea = "(A1)";
+
+ reg_id SD;
+ decode_HHH_table(BITSn(word0,0x0e00), SD);
+
+ assemble_arguments_from_W_table(BITSn(word0,0x0100), 'X', SD, ea,
+ m_source, m_destination);
+
+ // If the destination of the instruction overlaps with our destination, abort.
+ if (registerOverlap(opDestination(), opAccumulatorBitsModified(), stringAsRegID(m_destination)))
+ return false;
+
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = m_source + "," + m_destination;
+ }
+ void evaluate() {}
+
+private:
+ astring m_source;
+ astring m_destination;
+};
+
+
+/* Dual X Memory Data Read : 011m mKKK .rr. .... : A-142*/
+class DualXMemoryDataRead: public ParallelMove
+{
+public:
+ DualXMemoryDataRead(const Opcode* oco, const UINT16 word0, const UINT16 word1) : ParallelMove(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ reg_id r;
+ reg_id D1;
+ reg_id D2;
+ astring ea1 = "";
+ astring ea2 = "";
+
+ decode_rr_table(BITSn(word0,0x0060), r);
+ decode_KKK_table(BITSn(word0,0x0700), D1, D2);
+ assemble_eas_from_mm_table(BITSn(word0,0x1800), regIDAsNum(r), 3, ea1, ea2);
+
+ /* Not documented, but extrapolated from docs on page A-133 */
+ if (D1 == iFHAT)
+ {
+ if (opDestination() == iB)
+ D1 = iA;
+ else if (opDestination() == iA)
+ D1 = iB;
+ else
+ D1 = iA; /* In the case of no data ALU instruction */
+ }
+
+ /* D1 and D2 may not specify the same register : A-142 */
+ if (r == iR3) return false;
+
+ char temp[32];
+ sprintf(temp, "X:%s,%s", ea1.cstr(), regIdAsString(D1).cstr());
+ parallelMove = temp;
+ sprintf(temp, "X:%s,%s", ea2.cstr(), regIdAsString(D2).cstr());
+ parallelMove2 = temp;
+
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = parallelMove + " " + parallelMove2;
+ }
+ void evaluate() {}
+
+private:
+ astring parallelMove;
+ astring parallelMove2;
+};
+
+
+/* Register to Register Data Move : 0100 IIII .... .... : A-133 */
+class RegisterToRegisterDataMove: public ParallelMove
+{
+public:
+ RegisterToRegisterDataMove(const Opcode* oco, const UINT16 word0, const UINT16 word1) : ParallelMove(oco)
+ {
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ decode_IIIIx_table(BITSn(word0,0x0f00), BITSn(word0,0x0008),
+ m_source, m_destination);
+
+ if (m_source == iINVALID)
+ return false;
+
+ if (m_source == iF)
+ m_source = opDestination();
+
+ if (m_destination == iFHAT)
+ {
+ if (opDestination() == iB)
+ m_destination = iA;
+ else if (opDestination() == iA)
+ m_destination = iB;
+ else
+ m_destination = iA; /* In the case of no data ALU instruction */
+ }
+
+ // Don't return a failure, just let everything fall through (nop).
+ //if (m_source == "?" && m_destination == "?")
+ // return false;
+
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ // (?,?) is a parallel nop
+ if (m_source == iWEIRD && m_destination == iWEIRD)
+ retString = "";
+ else
+ retString = regIdAsString(m_source) + "," + regIdAsString(m_destination);
+ }
+ void evaluate() {}
+
+private:
+ reg_id m_source;
+ reg_id m_destination;
+};
+
+
+/* X Memory Data Write and Register Data Move : 0001 011k RRDD .... : A-140 */
+class XMemoryDataWriteAndRegisterDataMove: public ParallelMove
+{
+public:
+ XMemoryDataWriteAndRegisterDataMove(const Opcode* oco, const UINT16 word0, const UINT16 word1) : ParallelMove(oco)
+ {
+ pms = "";
+ pms2 = "";
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ reg_id r;
+ reg_id S;
+ reg_id Dnot;
+ char parallel_move_str[128];
+ char parallel_move_str2[128];
+
+ if (opDestination() == iA) Dnot = iB;
+ else Dnot = iA;
+
+ // NEW // decode_k_table(BITSn(word0,0x0100), Dnot);
+ decode_RR_table(BITSn(word0,0x00c0), r);
+ decode_DD_table(BITSn(word0,0x0030), S);
+
+ sprintf(parallel_move_str, "%s,X:(R%d)+N%d", regIdAsString(Dnot).cstr(), regIDAsNum(r), regIDAsNum(r));
+ sprintf(parallel_move_str2, "%s,%s", regIdAsString(S).cstr(), regIdAsString(Dnot).cstr());
+ pms = parallel_move_str;
+ pms2 = parallel_move_str2;
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = pms + " " + pms2;
+ }
+ void evaluate() {}
+
+private:
+ astring pms; // TODO
+ astring pms2;
+};
+
+
+/* Address Register Update : 0011 0zRR .... .... : A-135 */
+class AddressRegisterUpdate: public ParallelMove
+{
+public:
+ AddressRegisterUpdate(const Opcode* oco, const UINT16 word0, const UINT16 word1) : ParallelMove(oco)
+ {
+ m_ea = "";
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ reg_id r;
+ decode_RR_table(BITSn(word0,0x0300), r);
+ assemble_ea_from_z_table(BITSn(word0,0x0400), regIDAsNum(r), m_ea);
+
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = m_ea;
+ }
+ void evaluate() {}
+
+private:
+ astring m_ea;
+};
+
+
+/* X Memory Data Move with short displacement : 0000 0101 BBBB BBBB ---- HHHW .... .... : A-139 */
+class XMemoryDataMoveWithShortDisplacement: public ParallelMove
+{
+public:
+ XMemoryDataMoveWithShortDisplacement(const Opcode* oco, const UINT16 word0, const UINT16 word1) : ParallelMove(oco)
+ {
+ m_source = "";
+ m_destination = "";
+ m_valid = decode(word0, word1);
+ }
+ bool decode(const UINT16 word0, const UINT16 word1)
+ {
+ INT8 b;
+ reg_id SD;
+ astring args;
+
+ b = (char)(word0 & 0x00ff);
+ decode_HHH_table(BITSn(word1,0x0e00), SD);
+ assemble_reg_from_W_table(BITSn(word1,0x0100), 'X', SD, b, m_source, m_destination);
+
+ return true;
+ }
+ void disassemble(astring& retString) const
+ {
+ retString = m_source + "," + m_destination;
+ }
+ void evaluate() {}
+
+private:
+ astring m_source;
+ astring m_destination;
+};
+
+}
+#endif
diff --git a/trunk/src/emu/cpu/dsp56k/tables.c b/trunk/src/emu/cpu/dsp56k/tables.c
new file mode 100644
index 00000000000..4e6428d8c6b
--- /dev/null
+++ b/trunk/src/emu/cpu/dsp56k/tables.c
@@ -0,0 +1,899 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "tables.h"
+#include "dsp56def.h"
+
+namespace DSP56K
+{
+
+/******************/
+/* Table decoding */
+/******************/
+bfShift decode_BBB_table(UINT16 BBB)
+{
+ switch(BBB)
+ {
+ case 0x4: return BBB_UPPER;
+ case 0x2: return BBB_MIDDLE;
+ case 0x1: return BBB_LOWER;
+ }
+
+ return BBB_INVALID;
+}
+
+void decode_cccc_table(const UINT16 cccc, op_mnem& mnemonic)
+{
+ switch (cccc)
+ {
+ case 0x0: mnemonic = oCC; break;
+ case 0x1: mnemonic = oGE; break;
+ case 0x2: mnemonic = oNE; break;
+ case 0x3: mnemonic = oPL; break;
+ case 0x4: mnemonic = oNN; break;
+ case 0x5: mnemonic = oEC; break;
+ case 0x6: mnemonic = oLC; break;
+ case 0x7: mnemonic = oGT; break;
+ case 0x8: mnemonic = oCS; break;
+ case 0x9: mnemonic = oLT; break;
+ case 0xa: mnemonic = oEQ; break;
+ case 0xb: mnemonic = oMI; break;
+ case 0xc: mnemonic = oNR; break;
+ case 0xd: mnemonic = oES; break;
+ case 0xe: mnemonic = oLS; break;
+ case 0xf: mnemonic = oLE; break;
+ }
+
+// NEW // switch (cccc)
+// NEW // {
+// NEW // case 0x0: sprintf(mnemonic, "cc(hs)"); break;
+// NEW // case 0x1: sprintf(mnemonic, "ge "); break;
+// NEW // case 0x2: sprintf(mnemonic, "ne "); break;
+// NEW // case 0x3: sprintf(mnemonic, "pl "); break;
+// NEW // case 0x4: sprintf(mnemonic, "nn "); break;
+// NEW // case 0x5: sprintf(mnemonic, "ec "); break;
+// NEW // case 0x6: sprintf(mnemonic, "lc "); break;
+// NEW // case 0x7: sprintf(mnemonic, "gt "); break;
+// NEW // case 0x8: sprintf(mnemonic, "cs(lo)"); break;
+// NEW // case 0x9: sprintf(mnemonic, "lt "); break;
+// NEW // case 0xa: sprintf(mnemonic, "eq "); break;
+// NEW // case 0xb: sprintf(mnemonic, "mi "); break;
+// NEW // case 0xc: sprintf(mnemonic, "nr "); break;
+// NEW // case 0xd: sprintf(mnemonic, "es "); break;
+// NEW // case 0xe: sprintf(mnemonic, "ls "); break;
+// NEW // case 0xf: sprintf(mnemonic, "le "); break;
+// NEW // }
+}
+
+void decode_DDDDD_table(const UINT16 DDDDD, reg_id& SD)
+{
+ switch(DDDDD)
+ {
+ case 0x00: SD = iX0; break;
+ case 0x01: SD = iY0; break;
+ case 0x02: SD = iX1; break;
+ case 0x03: SD = iY1; break;
+ case 0x04: SD = iA; break;
+ case 0x05: SD = iB; break;
+ case 0x06: SD = iA0; break;
+ case 0x07: SD = iB0; break;
+ case 0x08: SD = iLC; break;
+ case 0x09: SD = iSR; break;
+ case 0x0a: SD = iOMR; break;
+ case 0x0b: SD = iSP; break;
+ case 0x0c: SD = iA1; break;
+ case 0x0d: SD = iB1; break;
+ case 0x0e: SD = iA2; break;
+ case 0x0f: SD = iB2; break;
+
+ case 0x10: SD = iR0; break;
+ case 0x11: SD = iR1; break;
+ case 0x12: SD = iR2; break;
+ case 0x13: SD = iR3; break;
+ case 0x14: SD = iM0; break;
+ case 0x15: SD = iM1; break;
+ case 0x16: SD = iM2; break;
+ case 0x17: SD = iM3; break;
+ case 0x18: SD = iSSH; break;
+ case 0x19: SD = iSSL; break;
+ case 0x1a: SD = iLA; break;
+ case 0x1b: SD = iINVALID; break; /* no 0x1b */
+ case 0x1c: SD = iN0; break;
+ case 0x1d: SD = iN1; break;
+ case 0x1e: SD = iN2; break;
+ case 0x1f: SD = iN3; break;
+ }
+}
+
+void decode_DD_table(const UINT16 DD, reg_id& SD)
+{
+ switch (DD)
+ {
+ case 0x0: SD = iX0; break;
+ case 0x1: SD = iY0; break;
+ case 0x2: SD = iX1; break;
+ case 0x3: SD = iY1; break;
+ }
+}
+
+void decode_DDF_table(const UINT16 DD, const UINT16 F, reg_id& S, reg_id& D)
+{
+ const UINT16 switchVal = (DD << 1) | F;
+
+ switch (switchVal)
+ {
+ case 0x0: S = iX0; D = iA; break;
+ case 0x1: S = iX0; D = iB; break;
+ case 0x2: S = iY0; D = iA; break;
+ case 0x3: S = iY0; D = iB; break;
+ case 0x4: S = iX1; D = iA; break;
+ case 0x5: S = iX1; D = iB; break;
+ case 0x6: S = iY1; D = iA; break;
+ case 0x7: S = iY1; D = iB; break;
+ }
+}
+
+void decode_EE_table(const UINT16 EE, reg_id& D)
+{
+ switch(EE)
+ {
+ case 0x1: D = iMR; break;
+ case 0x3: D = iCCR; break;
+ case 0x2: D = iOMR; break;
+ }
+}
+
+void decode_F_table(const UINT16 F, reg_id& SD)
+{
+ switch(F)
+ {
+ case 0x0: SD = iA; break;
+ case 0x1: SD = iB; break;
+ }
+}
+
+void decode_h0hF_table(const UINT16 h0h, UINT16 F, reg_id& S, reg_id& D)
+{
+ const UINT16 switchVal = (h0h << 1) | F;
+
+ switch (switchVal)
+ {
+ case 0x8: S = iX0; D = iA; break;
+ case 0x9: S = iX0; D = iB; break;
+ case 0xa: S = iY0; D = iA; break;
+ case 0xb: S = iY0; D = iB; break;
+ case 0x2: S = iA; D = iA; break;
+ case 0x1: S = iA; D = iB; break;
+ case 0x0: S = iB; D = iA; break;
+ case 0x3: S = iB; D = iB; break;
+ }
+}
+
+void decode_HH_table(const UINT16 HH, reg_id& SD)
+{
+ switch(HH)
+ {
+ case 0x0: SD = iX0; break;
+ case 0x1: SD = iY0; break;
+ case 0x2: SD = iA; break;
+ case 0x3: SD = iB; break;
+ }
+}
+
+void decode_HHH_table(const UINT16 HHH, reg_id& SD)
+{
+ switch(HHH)
+ {
+ case 0x0: SD = iX0; break;
+ case 0x1: SD = iY0; break;
+ case 0x2: SD = iX1; break;
+ case 0x3: SD = iY1; break;
+ case 0x4: SD = iA; break;
+ case 0x5: SD = iB; break;
+ case 0x6: SD = iA0; break;
+ case 0x7: SD = iB0; break;
+ }
+}
+
+void decode_IIIIx_table(const UINT16 IIII, const UINT16 x, reg_id& S, reg_id& D)
+{
+ S = D = iINVALID;
+ switch(IIII)
+ {
+ case 0x0: S = iX0; D = iFHAT; break;
+ case 0x1: S = iY0; D = iFHAT; break;
+ case 0x2: S = iX1; D = iFHAT; break;
+ case 0x3: S = iY1; D = iFHAT; break;
+ case 0x4: S = iA; D = iX0; break;
+ case 0x5: S = iB; D = iY0; break;
+ case 0x6: S = iA0; D = iX0; break;
+ case 0x7: S = iB0; D = iY0; break;
+ case 0x8: if ( x) S = iF; D = iFHAT; break;
+ case 0x9: if (!x) S = iF; D = iFHAT; break;
+ case 0xa: S = iWEIRD; D = iWEIRD; break;
+ case 0xb: S = iWEIRD; D = iWEIRD; break;
+ case 0xc: S = iA; D = iX1; break;
+ case 0xd: S = iB; D = iY1; break;
+ case 0xe: S = iA0; D = iX1; break;
+ case 0xf: S = iB0; D = iY1; break;
+ }
+}
+
+void decode_JJJF_table(const UINT16 JJJ, const UINT16 F, reg_id& S, reg_id& D)
+{
+ const UINT16 switchVal = (JJJ << 1) | F;
+
+ switch(switchVal)
+ {
+ case 0x0: S = iB; D = iA; break;
+ case 0x1: S = iA; D = iB; break;
+ case 0x2: S = iINVALID; D = iINVALID; break;
+ case 0x3: S = iINVALID; D = iINVALID; break;
+ case 0x4: S = iX; D = iA; break;
+ case 0x5: S = iX; D = iB; break;
+ case 0x6: S = iY; D = iA; break;
+ case 0x7: S = iY; D = iB; break;
+ case 0x8: S = iX0; D = iA; break;
+ case 0x9: S = iX0; D = iB; break;
+ case 0xa: S = iY0; D = iA; break;
+ case 0xb: S = iY0; D = iB; break;
+ case 0xc: S = iX1; D = iA; break;
+ case 0xd: S = iX1; D = iB; break;
+ case 0xe: S = iY1; D = iA; break;
+ case 0xf: S = iY1; D = iB; break;
+ }
+}
+
+void decode_JJF_table(const UINT16 JJ, const UINT16 F, reg_id& S, reg_id& D)
+{
+ const UINT16 switchVal = (JJ << 1) | F;
+
+ switch (switchVal)
+ {
+ case 0x0: S = iX0; D = iA; break;
+ case 0x1: S = iX0; D = iB; break;
+ case 0x2: S = iY0; D = iA; break;
+ case 0x3: S = iY0; D = iB; break;
+ case 0x4: S = iX1; D = iA; break;
+ case 0x5: S = iX1; D = iB; break;
+ case 0x6: S = iY1; D = iA; break;
+ case 0x7: S = iY1; D = iB; break;
+ }
+}
+
+void decode_JF_table(const UINT16 J, const UINT16 F, reg_id& S, reg_id& D)
+{
+ const UINT16 switchVal = (J << 1) | F;
+
+ switch(switchVal)
+ {
+ case 0x0: S = iX; D = iA; break;
+ case 0x1: S = iX; D = iB; break;
+ case 0x2: S = iY; D = iA; break;
+ case 0x3: S = iY; D = iB; break;
+ }
+}
+
+// NEW // void decode_k_table(UINT16 k, char *Dnot)
+// NEW // {
+// NEW // switch(k)
+// NEW // {
+// NEW // case 0x0: sprintf(Dnot, "B"); break;
+// NEW // case 0x1: sprintf(Dnot, "A"); break;
+// NEW // }
+// NEW // }
+
+void decode_kSign_table(const UINT16 k, astring& plusMinus)
+{
+ switch(k)
+ {
+ case 0x0: plusMinus = "+"; break;
+ case 0x1: plusMinus = "-"; break;
+ }
+}
+
+void decode_KKK_table(const UINT16 KKK, reg_id& D1, reg_id& D2)
+{
+ switch(KKK)
+ {
+ case 0x0: D1 = iFHAT; D2 = iX0; break;
+ case 0x1: D1 = iY0; D2 = iX0; break;
+ case 0x2: D1 = iX1; D2 = iX0; break;
+ case 0x3: D1 = iY1; D2 = iX0; break;
+ case 0x4: D1 = iX0; D2 = iX1; break;
+ case 0x5: D1 = iY0; D2 = iX1; break;
+ case 0x6: D1 = iFHAT; D2 = iY0; break;
+ case 0x7: D1 = iY1; D2 = iX1; break;
+ }
+}
+
+void decode_NN_table(UINT16 NN, reg_id& ret)
+{
+ switch(NN)
+ {
+ case 0x0: ret = iN0; break;
+ case 0x1: ret = iN1; break;
+ case 0x2: ret = iN2; break;
+ case 0x3: ret = iN3; break;
+ }
+}
+
+void decode_TT_table(UINT16 TT, reg_id& ret)
+{
+ switch(TT)
+ {
+ case 0x0: ret = iR0; break;
+ case 0x1: ret = iR1; break;
+ case 0x2: ret = iR2; break;
+ case 0x3: ret = iR3; break;
+ }
+}
+
+void decode_QQF_table(const UINT16 QQ, const UINT16 F, reg_id& S1, reg_id& S2, reg_id& D)
+{
+ const UINT16 switchVal = (QQ << 1) | F;
+
+ switch(switchVal)
+ {
+ case 0x0: S1 = iY0; S2 = iX0; D = iA; break;
+ case 0x1: S1 = iY0; S2 = iX0; D = iB; break;
+ case 0x2: S1 = iY1; S2 = iX0; D = iA; break;
+ case 0x3: S1 = iY1; S2 = iX0; D = iB; break;
+ case 0x4: S1 = iY0; S2 = iX1; D = iA; break;
+ case 0x5: S1 = iY0; S2 = iX1; D = iB; break;
+ case 0x6: S1 = iY1; S2 = iX1; D = iA; break;
+ case 0x7: S1 = iY1; S2 = iX1; D = iB; break;
+ }
+}
+
+void decode_QQF_special_table(const UINT16 QQ, const UINT16 F, reg_id& S1, reg_id& S2, reg_id& D)
+{
+ const UINT16 switchVal = (QQ << 1) | F;
+
+ switch(switchVal)
+ {
+ case 0x0: S1 = iY0; S2 = iX0; D = iA; break;
+ case 0x1: S1 = iY0; S2 = iX0; D = iB; break;
+ case 0x2: S1 = iY1; S2 = iX0; D = iA; break;
+ case 0x3: S1 = iY1; S2 = iX0; D = iB; break;
+ case 0x4: S1 = iX1; S2 = iY0; D = iA; break;
+ case 0x5: S1 = iX1; S2 = iY0; D = iB; break;
+ case 0x6: S1 = iX1; S2 = iY1; D = iA; break;
+ case 0x7: S1 = iX1; S2 = iY1; D = iB; break;
+ }
+}
+
+void decode_QQQF_table(const UINT16 QQQ, const UINT16 F, reg_id& S1, reg_id& S2, reg_id& D)
+{
+ const UINT16 switchVal = (QQQ << 1) | F;
+
+ switch(switchVal)
+ {
+ case 0x0: S1 = iX0; S2 = iX0; D = iA; break;
+ case 0x1: S1 = iX0; S2 = iX0; D = iB; break;
+ case 0x2: S1 = iX1; S2 = iX0; D = iA; break;
+ case 0x3: S1 = iX1; S2 = iX0; D = iB; break;
+ case 0x4: S1 = iA1; S2 = iY0; D = iA; break;
+ case 0x5: S1 = iA1; S2 = iY0; D = iB; break;
+ case 0x6: S1 = iB1; S2 = iX0; D = iA; break;
+ case 0x7: S1 = iB1; S2 = iX0; D = iB; break;
+ case 0x8: S1 = iY0; S2 = iX0; D = iA; break;
+ case 0x9: S1 = iY0; S2 = iX0; D = iB; break;
+ case 0xa: S1 = iY1; S2 = iX0; D = iA; break;
+ case 0xb: S1 = iY1; S2 = iX0; D = iB; break;
+ case 0xc: S1 = iY0; S2 = iX1; D = iA; break;
+ case 0xd: S1 = iY0; S2 = iX1; D = iB; break;
+ case 0xe: S1 = iY1; S2 = iX1; D = iA; break;
+ case 0xf: S1 = iY1; S2 = iX1; D = iB; break;
+ }
+}
+
+void decode_RR_table(UINT16 RR, reg_id& ret)
+{
+ switch(RR)
+ {
+ case 0x0: ret = iR0; break;
+ case 0x1: ret = iR1; break;
+ case 0x2: ret = iR2; break;
+ case 0x3: ret = iR3; break;
+ }
+}
+
+void decode_rr_table(UINT16 rr, reg_id& ret)
+{
+ switch(rr)
+ {
+ case 0x0: ret = iR0; break;
+ case 0x1: ret = iR1; break;
+ case 0x2: ret = iR2; break;
+ case 0x3: ret = iR3; break;
+ }
+}
+
+void decode_s_table(const UINT16 s, op_mnem& arithmetic)
+{
+ switch(s)
+ {
+ case 0x0: arithmetic = oSU; break;
+ case 0x1: arithmetic = oUU; break;
+ }
+}
+
+void decode_ss_table(const UINT16 ss, op_mnem& arithmetic)
+{
+ switch(ss)
+ {
+ case 0x0: arithmetic = oSS; break;
+ case 0x1: arithmetic = oINVALID; break;
+ // NEW // case 0x1: arithmetic = "ss"; break;
+ case 0x2: arithmetic = oSU; break;
+ case 0x3: arithmetic = oUU; break;
+ }
+}
+
+void decode_uuuuF_table(const UINT16 uuuu, const UINT16 F, astring& arg, reg_id& S, reg_id& D)
+{
+ const UINT16 switchVal = (uuuu << 1) | F;
+
+ //D = "sub?";
+ //S = "add";
+ arg = "invalid";
+
+ switch(switchVal)
+ {
+ case 0x00: arg = "add"; S = iX0; D = iA; break;
+ case 0x01: arg = "add"; S = iX0; D = iB; break;
+ case 0x02: arg = "add"; S = iY0; D = iA; break;
+ case 0x03: arg = "add"; S = iY0; D = iB; break;
+ case 0x04: arg = "add"; S = iX1; D = iA; break;
+ case 0x05: arg = "add"; S = iX1; D = iB; break;
+ case 0x06: arg = "add"; S = iY1; D = iA; break;
+ case 0x07: arg = "add"; S = iY1; D = iB; break;
+
+ case 0x08: arg = "sub"; S = iX0; D = iA; break;
+ case 0x09: arg = "sub"; S = iX0; D = iB; break;
+ case 0x0a: arg = "sub"; S = iY0; D = iA; break;
+ case 0x0b: arg = "sub"; S = iY0; D = iB; break;
+ case 0x0c: arg = "sub"; S = iX1; D = iA; break;
+ case 0x0d: arg = "sub"; S = iX1; D = iB; break;
+ case 0x0e: arg = "sub"; S = iY1; D = iA; break;
+ case 0x0f: arg = "sub"; S = iY1; D = iB; break;
+
+ case 0x18: arg = "add"; S = iB; D = iA; break;
+ case 0x19: arg = "add"; S = iA; D = iB; break;
+
+ case 0x1a: arg = "sub"; S = iB; D = iA; break;
+ case 0x1b: arg = "sub"; S = iA; D = iB; break;
+
+ case 0x1c: arg = "tfr"; S = iB; D = iA; break;
+ case 0x1d: arg = "tfr"; S = iA; D = iB; break;
+
+ case 0x1e: arg = "move"; S = iINVALID; D = iINVALID; break;
+ case 0x1f: arg = "move"; S = iINVALID; D = iINVALID; break;
+ }
+}
+
+void decode_Z_table(const UINT16 Z, astring& ea)
+{
+ /* This is fixed as per the Family Manual errata addendum */
+ switch(Z)
+ {
+ case 0x1: ea = "(A1)"; break;
+ case 0x0: ea = "(B1)"; break;
+ }
+}
+
+void assemble_ea_from_m_table(const UINT16 m, const int n, astring& ea)
+{
+ char temp[32];
+ switch(m)
+ {
+ case 0x0: sprintf(temp, "(R%d)+",n) ; break;
+ case 0x1: sprintf(temp, "(R%d)+N%d", n, n); break;
+ }
+ ea = temp;
+}
+
+void assemble_eas_from_mm_table(UINT16 mm, int n1, int n2, astring& ea1, astring& ea2)
+{
+ char temp1[32];
+ char temp2[32];
+ switch(mm)
+ {
+ case 0x0: sprintf(temp1, "(R%d)+", n1) ;
+ sprintf(temp2, "(R%d)+", n2) ; break;
+ case 0x1: sprintf(temp1, "(R%d)+", n1) ;
+ sprintf(temp2, "(R%d)+N%d", n2, n2); break;
+ case 0x2: sprintf(temp1, "(R%d)+N%d", n1, n1);
+ sprintf(temp2, "(R%d)+", n2) ; break;
+ case 0x3: sprintf(temp1, "(R%d)+N%d", n1, n1);
+ sprintf(temp2, "(R%d)+N%d", n2, n2); break;
+ }
+ ea1 = temp1;
+ ea2 = temp2;
+}
+
+void assemble_ea_from_MM_table(UINT16 MM, int n, astring& ea)
+{
+ char temp[32];
+ switch(MM)
+ {
+ case 0x0: sprintf(temp, "(R%d)", n) ; break;
+ case 0x1: sprintf(temp, "(R%d)+", n) ; break;
+ case 0x2: sprintf(temp, "(R%d)-", n) ; break;
+ case 0x3: sprintf(temp, "(R%d)+N%d", n, n); break;
+ }
+ ea = temp;
+}
+
+void assemble_ea_from_q_table(UINT16 q, int n, astring& ea)
+{
+ char temp[32];
+ switch(q)
+ {
+ case 0x0: sprintf(temp, "(R%d+N%d)", n, n); break;
+ case 0x1: sprintf(temp, "-(R%d)", n) ; break;
+ }
+ ea = temp;
+}
+
+void assemble_ea_from_t_table(UINT16 t, UINT16 val, astring& ea)
+{
+ char temp[32];
+ switch(t)
+ {
+ case 0x0: sprintf(temp, "X:>$%x", val); break;
+ case 0x1: sprintf(temp, "#>$%x", val); break;
+ // NEW // case 0x0: sprintf(ea, "X:$%04x", val); break;
+ // NEW // case 0x1: sprintf(ea, "#$%04x", val); break;
+ }
+ ea = temp;
+}
+
+void assemble_ea_from_z_table(UINT16 z, int n, astring& ea)
+{
+ char temp[32];
+ switch(z)
+ {
+ case 0x0: sprintf(temp, "(R%d)-", n) ; break;
+ case 0x1: sprintf(temp, "(R%d)+N%d", n, n); break;
+ }
+ ea = temp;
+}
+
+void assemble_D_from_P_table(UINT16 P, UINT16 ppppp, astring& D)
+{
+ char temp[32];
+ astring fullAddy; /* Convert Short Absolute Address to full 16-bit */
+
+ switch(P)
+ {
+ case 0x0:
+ sprintf(temp, "X:<$%x", ppppp);
+ // NEW // sprintf(temp, "X:$%02x", ppppp);
+ break;
+ case 0x1:
+ assemble_address_from_IO_short_address(ppppp, fullAddy);
+ sprintf(temp, "X:<<$%s", fullAddy.cstr());
+ // NEW // sprintf(temp, "X:$%s", fullAddy.cstr());
+ break;
+ }
+ D = temp;
+}
+
+void assemble_arguments_from_W_table(UINT16 W, char ma, const reg_id& SD, const astring& ea,
+ astring& source, astring& destination)
+{
+ char temp[32];
+ sprintf(temp, "%c:%s", ma, ea.cstr());
+ switch(W)
+ {
+ case 0x0: source = regIdAsString(SD); destination = temp; break;
+ case 0x1: source = temp; destination = regIdAsString(SD); break;
+ }
+}
+
+void assemble_arguments_from_W_table(UINT16 W, char ma, const astring& SD, const astring& ea,
+ astring& source, astring& destination)
+{
+ char temp[32];
+ sprintf(temp, "%c:%s", ma, ea.cstr());
+ switch(W)
+ {
+ case 0x0: source = SD; destination = temp; break;
+ case 0x1: source = temp; destination = SD; break;
+ }
+}
+
+void assemble_reg_from_W_table(UINT16 W, char ma, const reg_id& SD, const INT8 xx, astring& S, astring& D)
+{
+ UINT8 abs_xx;
+ char temp[32];
+ char operation[32];
+
+ if(xx < 0)
+ sprintf(operation,"-");
+ else
+ sprintf(operation,"+");
+
+ abs_xx = abs(xx);
+
+ sprintf(temp, "%c:(R2%s$%x)", ma, operation, abs_xx);
+ // NEW // sprintf(temp, "%c:(R2%s$%02x)", ma, operation, abs_xx);
+ switch(W)
+ {
+ case 0x0: S = regIdAsString(SD); D = temp; break;
+ case 0x1: S = temp; D = regIdAsString(SD); break;
+ }
+}
+
+void assemble_address_from_IO_short_address(UINT16 pp, astring& ea)
+{
+ char temp[32];
+
+ UINT16 fullAddy = 0xffe0;
+ fullAddy |= pp;
+
+ sprintf(temp, "%.04x", fullAddy);
+ ea = temp;
+}
+
+INT8 get_6_bit_signed_value(UINT16 bits)
+{
+ UINT16 fullAddy = bits;
+ if (fullAddy & 0x0020)
+ fullAddy |= 0xffc0;
+
+ return (INT8)fullAddy;
+}
+
+
+/********************/
+/* HELPER FUNCTIONS */
+/********************/
+
+UINT16 dsp56k_op_maskn(UINT16 cur, UINT16 mask)
+{
+ int i;
+
+ UINT16 retVal = (cur & mask);
+ UINT16 temp = 0x0000;
+ int offsetCount = 0;
+
+ /* Shift everything right, eliminating 'whitespace'... */
+ for (i = 0; i < 16; i++)
+ {
+ if (mask & (0x1<<i)) /* If mask bit is non-zero */
+ {
+ temp |= (((retVal >> i) & 0x1) << offsetCount);
+ offsetCount++;
+ }
+ }
+
+ return temp;
+}
+
+bool registerOverlap(const reg_id& r0, const size_t bmd, const reg_id& r1)
+{
+ if (bmd == BM_NONE)
+ return false;
+
+ if (r0 == r1)
+ return true;
+
+ if (r0 == iA && (bmd & BM_LOW) && r1 == iA0) return true;
+ if (r0 == iA && (bmd & BM_MIDDLE) && r1 == iA1) return true;
+ if (r0 == iA && (bmd & BM_HIGH) && r1 == iA2) return true;
+
+ if (r0 == iB && (bmd & BM_LOW) && r1 == iB0) return true;
+ if (r0 == iB && (bmd & BM_MIDDLE) && r1 == iB1) return true;
+ if (r0 == iB && (bmd & BM_HIGH) && r1 == iB2) return true;
+
+ return false;
+}
+
+UINT16 regValue16(dsp56k_core* cpustate, const reg_id& reg)
+{
+ if (reg == iX0) return X0;
+ if (reg == iX1) return X1;
+ if (reg == iY0) return Y0;
+ if (reg == iY1) return Y1;
+
+ if (reg == iA0) return A0;
+ if (reg == iA1) return A1;
+ if (reg == iB0) return B0;
+ if (reg == iB1) return B1;
+
+ if (reg == iR0) return R0;
+ if (reg == iR1) return R1;
+ if (reg == iR2) return R2;
+ if (reg == iR3) return R3;
+
+ if (reg == iN0) return N0;
+ if (reg == iN1) return N1;
+ if (reg == iN2) return N2;
+ if (reg == iN3) return N3;
+
+ if (reg == iM0) return M0;
+ if (reg == iM1) return M1;
+ if (reg == iM2) return M2;
+ if (reg == iM3) return M3;
+
+ mame_printf_debug("The dsp561xx core is requesting a 16 bit value from non-16 bit register!");
+ return 0xdead;
+}
+
+void setReg16(dsp56k_core* cpustate, const UINT16& value, const reg_id& reg)
+{
+ if (reg == iX0) X0 = value;
+ if (reg == iX1) X1 = value;
+ if (reg == iY0) Y0 = value;
+ if (reg == iY1) Y1 = value;
+
+ if (reg == iA0) A0 = value;
+ if (reg == iA1) A1 = value;
+ if (reg == iB0) B0 = value;
+ if (reg == iB1) B1 = value;
+
+ if (reg == iR0) R0 = value;
+ if (reg == iR1) R1 = value;
+ if (reg == iR2) R2 = value;
+ if (reg == iR3) R3 = value;
+
+ if (reg == iN0) N0 = value;
+ if (reg == iN1) N1 = value;
+ if (reg == iN2) N2 = value;
+ if (reg == iN3) N3 = value;
+
+ if (reg == iM0) M0 = value;
+ if (reg == iM1) M1 = value;
+ if (reg == iM2) M2 = value;
+ if (reg == iM3) M3 = value;
+}
+
+astring regIdAsString(const reg_id& regId)
+{
+ switch(regId)
+ {
+ case iX: return "X"; break;
+ case iX0: return "X0"; break;
+ case iX1: return "X1"; break;
+ case iY: return "Y"; break;
+ case iY0: return "Y0"; break;
+ case iY1: return "Y1"; break;
+ case iA: return "A"; break;
+ case iA0: return "A0"; break;
+ case iA1: return "A1"; break;
+ case iA2: return "A2"; break;
+ case iB: return "B"; break;
+ case iB0: return "B0"; break;
+ case iB1: return "B1"; break;
+ case iB2: return "B2"; break;
+ case iR0: return "R0"; break;
+ case iR1: return "R1"; break;
+ case iR2: return "R2"; break;
+ case iR3: return "R3"; break;
+ case iN0: return "N0"; break;
+ case iN1: return "N1"; break;
+ case iN2: return "N2"; break;
+ case iN3: return "N3"; break;
+ case iM0: return "M0"; break;
+ case iM1: return "M1"; break;
+ case iM2: return "M2"; break;
+ case iM3: return "M3"; break;
+ case iLC: return "LC"; break;
+ case iSR: return "SR"; break;
+ case iOMR: return "OMR"; break;
+ case iSP: return "SP"; break;
+ case iSSH: return "SSH"; break;
+ case iSSL: return "SSL"; break;
+ case iLA: return "LA"; break;
+ case iMR: return "MR"; break;
+ case iCCR: return "CCR"; break;
+ case iF: return "F"; break;
+ case iFHAT: return "^F"; break;
+ case iINVALID: return "!!"; break;
+ case iWEIRD: return "?"; break;
+ }
+
+ return "INVALID_REG_ID";
+}
+
+astring opMnemonicAsString(const op_mnem& mnem)
+{
+ switch(mnem)
+ {
+ case oCC: return "cc"; break;
+ case oGE: return "ge"; break;
+ case oNE: return "ne"; break;
+ case oPL: return "pl"; break;
+ case oNN: return "nn"; break;
+ case oEC: return "ec"; break;
+ case oLC: return "lc"; break;
+ case oGT: return "gt"; break;
+ case oCS: return "cs"; break;
+ case oLT: return "lt"; break;
+ case oEQ: return "eq"; break;
+ case oMI: return "mi"; break;
+ case oNR: return "nr"; break;
+ case oES: return "es"; break;
+ case oLS: return "ls"; break;
+ case oLE: return "le"; break;
+
+ case oSS: return "ss"; break;
+ case oSU: return "su"; break;
+ case oUU: return "uu"; break;
+ case oINVALID: return "!!"; break;
+ }
+
+ return "INVALID_OPCODE_MNEMONIC";
+}
+
+reg_id stringAsRegID(const astring& str)
+{
+ if (str == "X") return iX;
+ if (str == "X0") return iX0;
+ if (str == "X1") return iX1;
+ if (str == "Y") return iY;
+ if (str == "Y0") return iY0;
+ if (str == "Y1") return iY1;
+ if (str == "A") return iA;
+ if (str == "A0") return iA0;
+ if (str == "A1") return iA1;
+ if (str == "A2") return iA2;
+ if (str == "B") return iB;
+ if (str == "B0") return iB0;
+ if (str == "B1") return iB1;
+ if (str == "B2") return iB2;
+ if (str == "R0") return iR0;
+ if (str == "R1") return iR1;
+ if (str == "R2") return iR2;
+ if (str == "R3") return iR3;
+ if (str == "N0") return iN0;
+ if (str == "N1") return iN1;
+ if (str == "N2") return iN2;
+ if (str == "N3") return iN3;
+ if (str == "M0") return iM0;
+ if (str == "M1") return iM1;
+ if (str == "M2") return iM2;
+ if (str == "M3") return iM3;
+ if (str == "LC") return iLC;
+ if (str == "SR") return iSR;
+ if (str == "OMR") return iOMR;
+ if (str == "SP") return iSP;
+ if (str == "SSH") return iSSH;
+ if (str == "SSL") return iSSL;
+ if (str == "LA") return iLA;
+ if (str == "MR") return iMR;
+ if (str == "CCR") return iCCR;
+ if (str == "F") return iF;
+ if (str == "^F") return iFHAT;
+ if (str == "!!") return iINVALID;
+ if (str == "?") return iWEIRD;
+
+ return iINVALID;
+}
+
+UINT8 regIDAsNum(const reg_id& regId)
+{
+ if (regId == iR0) return 0;
+ if (regId == iR1) return 1;
+ if (regId == iR2) return 2;
+ if (regId == iR3) return 3;
+
+ if (regId == iN0) return 0;
+ if (regId == iN1) return 1;
+ if (regId == iN2) return 2;
+ if (regId == iN3) return 3;
+
+ if (regId == iM0) return 0;
+ if (regId == iM1) return 1;
+ if (regId == iM2) return 2;
+ if (regId == iM3) return 3;
+
+ return 255;
+}
+
+}
+
diff --git a/trunk/src/emu/cpu/dsp56k/tables.h b/trunk/src/emu/cpu/dsp56k/tables.h
new file mode 100644
index 00000000000..39efd3092df
--- /dev/null
+++ b/trunk/src/emu/cpu/dsp56k/tables.h
@@ -0,0 +1,93 @@
+#ifndef __DSP56K_OPS_H__
+#define __DSP56K_OPS_H__
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "emu.h"
+#include "dsp56k.h"
+
+namespace DSP56K
+{
+
+#define BITSn(CUR,MASK) (dsp56k_op_maskn(CUR,MASK))
+
+enum bitsModified {BM_NONE = 0x0, BM_LOW = 0x1, BM_MIDDLE = 0x2, BM_HIGH = 0x4};
+
+enum bfShift {BBB_UPPER, BBB_MIDDLE, BBB_LOWER, BBB_INVALID};
+enum reg_id {iX, iX0, iX1,
+ iY, iY0, iY1,
+ iA, iA0, iA1, iA2,
+ iB, iB0, iB1, iB2,
+ iR0, iR1, iR2, iR3,
+ iN0, iN1, iN2, iN3,
+ iM0, iM1, iM2, iM3,
+ iLC, iSR, iOMR, iSP, iSSH, iSSL, iLA, iMR, iCCR,
+ iF, iFHAT,
+ iINVALID, iWEIRD};
+
+enum op_mnem {oCC, oGE, oNE, oPL,
+ oNN, oEC, oLC, oGT,
+ oCS, oLT, oEQ, oMI,
+ oNR, oES, oLS, oLE,
+ oSS, oSU, oUU, oINVALID};
+
+
+bfShift decode_BBB_table(UINT16 BBB);
+void decode_cccc_table(const UINT16 cccc, op_mnem& mnemonic);
+void decode_DDDDD_table(const UINT16 DDDDD, reg_id& SD);
+void decode_DD_table(const UINT16 DD, reg_id& SD);
+void decode_DDF_table(const UINT16 DD, const UINT16 F, reg_id& S, reg_id& D);
+void decode_EE_table(const UINT16 EE, reg_id& D);
+void decode_F_table(const UINT16 F, reg_id& SD);
+void decode_h0hF_table(const UINT16 h0h, UINT16 F, reg_id& S, reg_id& D);
+void decode_HH_table(const UINT16 HH, reg_id& SD);
+void decode_HHH_table(const UINT16 HHH, reg_id& SD);
+void decode_IIIIx_table(const UINT16 IIII, const UINT16 x, reg_id& S, reg_id& D);
+void decode_JJJF_table(const UINT16 JJJ, const UINT16 F, reg_id& S, reg_id& D);
+void decode_JJF_table(const UINT16 JJ, const UINT16 F, reg_id& S, reg_id& D);
+void decode_JF_table(const UINT16 J, const UINT16 F, reg_id& S, reg_id& D);
+void decode_kSign_table(const UINT16 k, astring& plusMinus);
+void decode_KKK_table(const UINT16 KKK, reg_id& D1, reg_id& D2);
+void decode_NN_table(UINT16 NN, reg_id& ret);
+void decode_TT_table(UINT16 TT, reg_id& ret);
+void decode_QQF_table(const UINT16 QQ, const UINT16 F, reg_id& S1, reg_id& S2, reg_id& D);
+void decode_QQF_special_table(const UINT16 QQ, const UINT16 F, reg_id& S1, reg_id& S2, reg_id& D);
+void decode_QQQF_table(const UINT16 QQQ, const UINT16 F, reg_id& S1, reg_id& S2, reg_id& D);
+void decode_RR_table(UINT16 RR, reg_id& ret);
+void decode_rr_table(UINT16 rr, reg_id& ret);
+void decode_s_table(const UINT16 s, op_mnem& arithmetic);
+void decode_ss_table(const UINT16 ss, op_mnem& arithmetic);
+void decode_uuuuF_table(const UINT16 uuuu, const UINT16 F, astring& arg, reg_id& S, reg_id& D);
+void decode_Z_table(const UINT16 Z, astring& ea);
+
+void assemble_ea_from_m_table(const UINT16 m, const int n, astring& ea);
+void assemble_eas_from_mm_table(UINT16 mm, int n1, int n2, astring& ea1, astring& ea2);
+void assemble_ea_from_MM_table(UINT16 MM, int n, astring& ea);
+void assemble_ea_from_q_table(UINT16 q, int n, astring& ea);
+void assemble_ea_from_t_table(UINT16 t, UINT16 val, astring& ea);
+void assemble_ea_from_z_table(UINT16 z, int n, astring& ea);
+void assemble_D_from_P_table(UINT16 P, UINT16 ppppp, astring& D);
+void assemble_arguments_from_W_table(UINT16 W, char ma, const reg_id& SD, const astring& ea, astring& S, astring& D);
+void assemble_arguments_from_W_table(UINT16 W, char ma, const astring& SD, const astring& ea, astring& S, astring& D);
+void assemble_reg_from_W_table(UINT16 W, char ma, const reg_id& SD, const INT8 xx, astring& S, astring& D);
+void assemble_address_from_IO_short_address(UINT16 pp, astring& ea);
+
+INT8 get_6_bit_signed_value(UINT16 bits);
+
+// Helpers
+UINT16 dsp56k_op_maskn(UINT16 cur, UINT16 mask);
+
+bool registerOverlap(const reg_id& r0, const size_t bmd, const reg_id& r1);
+
+UINT16 regValue16(dsp56k_core* cpustate, const reg_id& reg);
+void setReg16(dsp56k_core* cpustate, const UINT16& value, const reg_id& reg);
+
+astring regIdAsString(const reg_id& regId);
+astring opMnemonicAsString(const op_mnem& mnem);
+reg_id stringAsRegID(const astring& str);
+UINT8 regIDAsNum(const reg_id& regId);
+
+
+}
+#endif
diff --git a/trunk/src/emu/cpu/e132xs/32xsdasm.c b/trunk/src/emu/cpu/e132xs/32xsdasm.c
new file mode 100644
index 00000000000..fa89acc69f4
--- /dev/null
+++ b/trunk/src/emu/cpu/e132xs/32xsdasm.c
@@ -0,0 +1,2140 @@
+/*
+
+ Hyperstone disassembler
+ written by Pierpaolo Prazzoli
+
+*/
+
+#include "emu.h"
+#include "debugger.h"
+#include "e132xs.h"
+
+static const char *const L_REG[] =
+{
+ "L0", "L1", "L2", "L3", "L4", "L5", "L6", "L7", "L8", "L9",
+ "L10", "L11", "L12", "L13", "L14", "L15", "L16", "L17", "L18", "L19",
+ "L20", "L21", "L22", "L23", "L24", "L25", "L26", "L27", "L28", "L29",
+ "L30", "L31", "L32", "L33", "L34", "L35", "L36", "L37", "L38", "L39",
+ "L40", "L41", "L42", "L43", "L44", "L45", "L46", "L47", "L48", "L49",
+ "L50", "L51", "L52", "L53", "L54", "L55", "L56", "L57", "L58", "L59",
+ "L60", "L61", "L62", "L63"
+};
+
+static const char *const G_REG[] =
+{
+ "PC", "SR", "FER", "G03", "G04", "G05", "G06", "G07", "G08", "G09",
+ "G10", "G11", "G12", "G13", "G14", "G15", "G16", "G17", "SP", "UB",
+ "BCR", "TPR", "TCR", "TR", "WCR", "ISR", "FCR", "MCR", "G28", "G29",
+ "G30", "G31"
+};
+
+static const char *const SETxx[] =
+{
+ "SETADR", "Reserved", "SET1", "SET0", "SETLE", "SETGT", "SETLT", "SETGE",
+ "SETSE", "SETHT", "SETST", "SETHE", "SETE", "SETNE", "SETV", "SETNV",
+ "Reserved", "Reserved", "SET1M", "Reserved", "SETLEM", "SETGTM", "SETLTM", "SETGEM",
+ "SETSEM", "SETTHM", "SETSTM", "SETHEM", "SETEM", "SETNEM", "SETVM", "SETNVM"
+};
+
+#define DESTCODE(op) ((op & 0x00f0) >> 4)
+#define SOURCECODE(op) (op & 0x000f)
+
+#define SOURCEBIT(op) ((op & 0x100) >> 8)
+#define DESTBIT(op) ((op & 0x200) >> 9)
+
+#define N_VALUE(op) ((((op & 0x100) >> 8) << 4 ) | (op & 0x0f))
+
+static int size, global_fp;
+
+static offs_t base_pc;
+static const UINT8 *base_oprom;
+#define READ_OP_DASM(p) ((base_oprom[(p) - base_pc] << 8) | base_oprom[(p) + 1 - base_pc])
+
+
+static void LL_format(char *source, char *dest, UINT16 op)
+{
+ strcpy(source, L_REG[(SOURCECODE(op)+global_fp)%64]);
+ strcpy(dest, L_REG[(DESTCODE(op)+global_fp)%64]);
+}
+
+static void LR_format(char *source, char *dest, UINT16 op)
+{
+ if( SOURCEBIT(op) )
+ {
+ strcpy(source, L_REG[(SOURCECODE(op)+global_fp)%64]);
+ }
+ else
+ {
+ strcpy(source, G_REG[SOURCECODE(op)]);
+ }
+
+ strcpy(dest, L_REG[(DESTCODE(op)+global_fp)%64]);
+}
+
+static void RR_format(char *source, char *dest, UINT16 op, unsigned h_flag)
+{
+ if( SOURCEBIT(op) )
+ {
+ strcpy(source, L_REG[(SOURCECODE(op)+global_fp)%64]);
+ }
+ else
+ {
+ strcpy(source, G_REG[SOURCECODE(op) + h_flag * 16]);
+ }
+
+ if( DESTBIT(op) )
+ {
+ strcpy(dest, L_REG[(DESTCODE(op)+global_fp)%64]);
+ }
+ else
+ {
+ strcpy(dest, G_REG[DESTCODE(op) + h_flag * 16]);
+ }
+}
+
+static UINT32 LRconst_format(char *source, char *dest, UINT16 op, unsigned *pc)
+{
+ UINT16 next_op;
+ UINT32 const_val;
+
+ if( SOURCEBIT(op) )
+ {
+ strcpy(source, L_REG[(SOURCECODE(op)+global_fp)%64]);
+ }
+ else
+ {
+ strcpy(source, G_REG[SOURCECODE(op)]);
+ }
+
+ strcpy(dest, L_REG[(DESTCODE(op)+global_fp)%64]);
+
+ size = 4;
+
+ *pc += 2;
+ next_op = READ_OP_DASM(*pc);
+
+ if( E_BIT(next_op) )
+ {
+ UINT16 next_op2;
+
+ size = 6;
+
+ *pc += 2;
+ next_op2 = READ_OP_DASM(*pc);
+ const_val = next_op2;
+ const_val |= ((next_op & 0x3fff) << 16 );
+
+ if( S_BIT_CONST(next_op) )
+ {
+ const_val |= 0xc0000000;
+ }
+ }
+ else
+ {
+ const_val = next_op & 0x3fff;
+
+ if( S_BIT_CONST(next_op) )
+ {
+ const_val |= 0xffffc000;
+ }
+ }
+
+ return const_val;
+}
+
+static UINT32 RRconst_format(char *source, char *dest, UINT16 op, unsigned *pc)
+{
+ UINT16 next_op;
+ UINT32 const_val;
+
+ if( SOURCEBIT(op) )
+ {
+ strcpy(source, L_REG[(SOURCECODE(op)+global_fp)%64]);
+ }
+ else
+ {
+ strcpy(source, G_REG[SOURCECODE(op)]);
+ }
+
+ if( DESTBIT(op) )
+ {
+ strcpy(dest, L_REG[(DESTCODE(op)+global_fp)%64]);
+ }
+ else
+ {
+ strcpy(dest, G_REG[DESTCODE(op)]);
+ }
+
+ size = 4;
+
+ *pc += 2;
+ next_op = READ_OP_DASM(*pc);
+
+ if( E_BIT(next_op) )
+ {
+ UINT16 next_op2;
+
+ size = 6;
+
+ *pc += 2;
+ next_op2 = READ_OP_DASM(*pc);
+ const_val = next_op2;
+ const_val |= ((next_op & 0x3fff) << 16 );
+
+ if( S_BIT_CONST(next_op) )
+ {
+ const_val |= 0xc0000000;
+ }
+ }
+ else
+ {
+ const_val = next_op & 0x3fff;
+
+ if( S_BIT_CONST(next_op) )
+ {
+ const_val |= 0xffffc000;
+ }
+ }
+
+ return const_val;
+}
+
+static INT32 Rimm_format(char *dest, UINT16 op, unsigned *pc, unsigned h_flag)
+{
+ UINT16 imm1, imm2;
+ INT32 ret;
+
+ int n = N_VALUE(op);
+
+ if( DESTBIT(op) )
+ {
+ strcpy(dest, L_REG[(DESTCODE(op)+global_fp)%64]);
+ }
+ else
+ {
+ strcpy(dest, G_REG[DESTCODE(op) + h_flag * 16]);
+ }
+
+ switch( n )
+ {
+ case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8:
+ case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 16:
+ return n;
+
+ case 17:
+ *pc += 2;
+ imm1 = READ_OP_DASM(*pc);
+ *pc += 2;
+ imm2 = READ_OP_DASM(*pc);
+ ret = (imm1 << 16) | imm2;
+
+ size = 6;
+ return ret;
+
+
+ case 18:
+ *pc += 2;
+ ret = READ_OP_DASM(*pc);
+
+ size = 4;
+ return ret;
+
+ case 19:
+ *pc += 2;
+ ret = (INT32) (0xffff0000 | READ_OP_DASM(*pc));
+
+ size = 4;
+ return ret;
+
+ case 20:
+ return 32; //bit 5 = 1, others = 0
+
+ case 21:
+ return 64; //bit 6 = 1, others = 0
+
+ case 22:
+ return 128; //bit 7 = 1, others = 0
+
+ case 23:
+ return 0x80000000; //bit 31 = 1, others = 0 (2 at the power of 31)
+
+ case 24:
+ return -8;
+
+ case 25:
+ return -7;
+
+ case 26:
+ return -6;
+
+ case 27:
+ return -5;
+
+ case 28:
+ return -4;
+
+ case 29:
+ return -3;
+
+ case 30:
+ return -2;
+
+ case 31:
+ return -1;
+
+ default:
+ return 0; //should never goes here
+ }
+}
+
+static UINT8 Ln_format(char *dest, UINT16 op)
+{
+ strcpy(dest, L_REG[(DESTCODE(op)+global_fp)%64]);
+
+ return N_VALUE(op);
+}
+
+static UINT8 Rn_format(char *dest, UINT16 op)
+{
+ if( DESTBIT(op) )
+ {
+ strcpy(dest, L_REG[(DESTCODE(op)+global_fp)%64]);
+ }
+ else
+ {
+ strcpy(dest, G_REG[DESTCODE(op)]);
+ }
+
+ return N_VALUE(op);
+}
+
+static INT32 PCrel_format(UINT16 op, unsigned pc)
+{
+ INT32 ret;
+
+ if( op & 0x80 ) //bit 7 = 1
+ {
+ UINT16 next;
+
+ size = 4;
+
+ pc += 2;
+
+ next = READ_OP_DASM(pc);
+
+ ret = (op & 0x7f) << 16;
+
+ ret |= (next & 0xfffe);
+
+ if( next & 1 )
+ ret |= 0xff800000; //ok?
+ }
+ else
+ {
+ ret = op & 0x7e;
+
+ if( op & 1 )
+ ret |= 0xffffff80; //ok?
+ }
+
+ return (pc + ret);
+}
+
+static UINT32 RRdis_format(char *source, char *dest, UINT16 op, UINT16 next_op, unsigned pc)
+{
+ UINT32 ret;
+
+ if( SOURCEBIT(op) )
+ {
+ strcpy(source, L_REG[(SOURCECODE(op)+global_fp)%64]);
+ }
+ else
+ {
+ strcpy(source, G_REG[SOURCECODE(op)]);
+ }
+
+ if( DESTBIT(op) )
+ {
+ strcpy(dest, L_REG[(DESTCODE(op)+global_fp)%64]);
+ }
+ else
+ {
+ strcpy(dest, G_REG[DESTCODE(op)]);
+ }
+
+ if( E_BIT(next_op) )
+ {
+ UINT16 next;
+
+ size = 6;
+
+ next = READ_OP_DASM(pc + 4);
+
+ ret = next;
+ ret |= ( ( next_op & 0xfff ) << 16 );
+
+ if( S_BIT_CONST(next_op) )
+ {
+ ret |= 0xf0000000;
+ }
+ }
+ else
+ {
+ ret = next_op & 0xfff;
+ if( S_BIT_CONST(next_op) )
+ {
+ ret |= 0xfffff000;
+ }
+ }
+
+ return ret;
+}
+
+unsigned dasm_hyperstone(char *buffer, unsigned pc, const UINT8 *oprom, unsigned h_flag, int private_fp)
+{
+ UINT16 op = 0;
+ UINT8 op_num;
+
+ UINT8 source_code, dest_code, source_bit, dest_bit;
+
+ char source[5] = "\0", dest[5] = "\0";
+ UINT32 flags = 0;
+
+ base_pc = pc;
+ base_oprom = oprom;
+
+ op = READ_OP_DASM(pc);
+
+ size = 2;
+
+ source_code = SOURCECODE(op);
+ dest_code = DESTCODE(op);
+ source_bit = SOURCEBIT(op);
+ dest_bit = DESTBIT(op);
+
+ global_fp = private_fp;
+
+ op_num = (op & 0xff00) >> 8;
+
+ switch( op_num )
+ {
+ // CHK - CHKZ - NOP
+ case 0x00: case 0x01: case 0x02: case 0x03:
+
+ if( source_bit && dest_bit && source_code == 0 && dest_code == 0 )
+ {
+ sprintf(buffer, "NOP");
+ }
+ else
+ {
+ RR_format(source, dest, op, 0);
+
+ if( !source_bit && source_code == SR_REGISTER )
+ {
+ sprintf(buffer, "CHKZ %s, 0", dest);
+ }
+ else
+ {
+ sprintf(buffer, "CHK %s, %s", dest, source);
+ }
+ }
+
+ break;
+
+ // MOVD - RET
+ case 0x04: case 0x05: case 0x06: case 0x07:
+
+ RR_format(source, dest, op, 0);
+
+ if( dest_code == PC_REGISTER && !dest_bit )
+ {
+ global_fp = 0;
+ RR_format(source, dest, op, 0);
+ sprintf(buffer, "RET PC, %s", source);
+ flags = DASMFLAG_STEP_OUT;
+ }
+ else if( source_code == SR_REGISTER && !source_bit )
+ {
+ sprintf(buffer, "MOVD %s, 0", dest);
+ }
+ else
+ {
+ sprintf(buffer, "MOVD %s, %s", dest, source);
+ }
+
+ break;
+
+ // DIVU
+ case 0x08: case 0x09: case 0x0a: case 0x0b:
+
+ RR_format(source, dest, op, 0);
+ sprintf(buffer, "DIVU %s, %s", dest, source);
+
+ break;
+
+ // DIVS
+ case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+
+ RR_format(source, dest, op, 0);
+ sprintf(buffer, "DIVS %s, %s", dest, source);
+
+ break;
+
+ // XMx - XXx
+ case 0x10: case 0x11: case 0x12: case 0x13:
+ {
+ int xcode;
+
+ RR_format(source, dest, op, 0);
+
+ size = 4;
+
+ pc += 2;
+ op = READ_OP_DASM(pc);
+
+ xcode = X_CODE(op);
+
+ if( xcode < 4 )
+ {
+ UINT16 lim;
+
+ if( E_BIT(op) )
+ {
+ UINT16 next_op;
+
+ size = 6;
+
+ pc += 2;
+ next_op = READ_OP_DASM(pc);
+
+ lim = ((op & 0xfff) << 16) | next_op;
+ }
+ else
+ {
+ lim = op & 0xfff;
+ }
+
+ sprintf(buffer, "XM%x %s, %s, $%x", (UINT8)(float) pow(2.0, xcode), dest, source, lim);
+
+ }
+ else
+ {
+ sprintf(buffer, "XX%x %s, %s, 0", (UINT8)(float) pow(2.0, (xcode - 4)), dest, source);
+ }
+
+ break;
+ }
+
+ // MASK
+ case 0x14: case 0x15: case 0x16: case 0x17:
+ {
+ UINT32 const_val = RRconst_format(source, dest, op, &pc);
+
+ sprintf(buffer, "MASK %s, %s, $%x", dest, source, const_val);
+
+ break;
+ }
+
+ // SUM
+ case 0x18: case 0x19: case 0x1a: case 0x1b:
+ {
+ UINT32 const_val = RRconst_format(source, dest, op, &pc);
+
+ if( source_code == SR_REGISTER && !source_bit )
+ {
+ sprintf(buffer, "SUM %s, C, $%x", dest, const_val);
+ }
+ else
+ {
+ sprintf(buffer, "SUM %s, %s, $%x", dest, source, const_val);
+ }
+
+ break;
+ }
+
+ // SUMS
+ case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ {
+ UINT32 const_val = RRconst_format(source, dest, op, &pc);
+
+ if( source_code == SR_REGISTER && !source_bit )
+ {
+ sprintf(buffer, "SUMS %s, C, $%x", dest, const_val);
+ }
+ else
+ {
+ sprintf(buffer, "SUMS %s, %s, $%x", dest, source, const_val);
+ }
+
+ break;
+ }
+
+ // CMP
+ case 0x20: case 0x21: case 0x22: case 0x23:
+
+ RR_format(source, dest, op, 0);
+
+ if( source_code == SR_REGISTER && !source_bit )
+ {
+ sprintf(buffer, "CMP %s, C", dest);
+ }
+ else
+ {
+ sprintf(buffer, "CMP %s, %s", dest, source);
+ }
+
+ break;
+
+ // MOV
+ case 0x24: case 0x25: case 0x26: case 0x27:
+
+ RR_format(source, dest, op, h_flag);
+ sprintf(buffer, "MOV %s, %s", dest, source);
+
+ break;
+
+ // ADD
+ case 0x28: case 0x29: case 0x2a: case 0x2b:
+
+ RR_format(source, dest, op, 0);
+
+ if( source_code == SR_REGISTER && !source_bit )
+ {
+ sprintf(buffer, "ADD %s, C", dest);
+ }
+ else
+ {
+ sprintf(buffer, "ADD %s, %s", dest, source);
+ }
+
+ break;
+
+ // ADDS
+ case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+
+ RR_format(source, dest, op, 0);
+
+ if( source_code == SR_REGISTER && !source_bit )
+ {
+ sprintf(buffer, "ADDS %s, C", dest);
+ }
+ else
+ {
+ sprintf(buffer, "ADDS %s, %s", dest, source);
+ }
+
+ break;
+
+ // CMPB
+ case 0x30: case 0x31: case 0x32: case 0x33:
+
+ RR_format(source, dest, op, 0);
+ sprintf(buffer, "CMPB %s, %s", dest, source);
+
+ break;
+
+ // ANDN
+ case 0x34: case 0x35: case 0x36: case 0x37:
+
+ RR_format(source, dest, op, 0);
+ sprintf(buffer, "ANDN %s, %s", dest, source);
+
+ break;
+
+ // OR
+ case 0x38: case 0x39: case 0x3a: case 0x3b:
+
+ RR_format(source, dest, op, 0);
+ sprintf(buffer, "OR %s, %s", dest, source);
+
+ break;
+
+ // XOR
+ case 0x3c: case 0x3d: case 0x3e: case 0x3f:
+
+ RR_format(source, dest, op, 0);
+ sprintf(buffer, "XOR %s, %s", dest, source);
+
+ break;
+
+ // SUBC
+ case 0x40: case 0x41: case 0x42: case 0x43:
+
+ RR_format(source, dest, op, 0);
+
+ if( source_code == SR_REGISTER && !source_bit )
+ {
+ sprintf(buffer, "SUBC %s, C", dest);
+ }
+ else
+ {
+ sprintf(buffer, "SUBC %s, %s", dest, source);
+ }
+
+ break;
+
+ // NOT
+ case 0x44: case 0x45: case 0x46: case 0x47:
+
+ RR_format(source, dest, op, 0);
+
+ sprintf(buffer, "NOT %s, %s", dest, source);
+
+ break;
+
+ // SUB
+ case 0x48: case 0x49: case 0x4a: case 0x4b:
+
+ RR_format(source, dest, op, 0);
+
+ if( source_code == SR_REGISTER && !source_bit )
+ {
+ sprintf(buffer, "SUB %s, C", dest);
+ }
+ else
+ {
+ sprintf(buffer, "SUB %s, %s", dest, source);
+ }
+
+ break;
+
+ // SUBS
+ case 0x4c: case 0x4d: case 0x4e: case 0x4f:
+
+ RR_format(source, dest, op, 0);
+
+ if( source_code == SR_REGISTER && !source_bit )
+ {
+ sprintf(buffer, "SUBS %s, C", dest);
+ }
+ else
+ {
+ sprintf(buffer, "SUBS %s, %s", dest, source);
+ }
+
+ break;
+
+ // ADDC
+ case 0x50: case 0x51: case 0x52: case 0x53:
+
+ RR_format(source, dest, op, 0);
+
+ if( source_code == SR_REGISTER && !source_bit )
+ {
+ sprintf(buffer, "ADDC %s, C", dest);
+ }
+ else
+ {
+ sprintf(buffer, "ADDC %s, %s", dest, source);
+ }
+
+ break;
+
+ // AND
+ case 0x54: case 0x55: case 0x56: case 0x57:
+
+ RR_format(source, dest, op, 0);
+ sprintf(buffer, "AND %s, %s", dest, source);
+
+ break;
+
+ // NEG
+ case 0x58: case 0x59: case 0x5a: case 0x5b:
+
+ RR_format(source, dest, op, 0);
+
+ if( source_code == SR_REGISTER && !source_bit )
+ {
+ sprintf(buffer, "NEG %s, C", dest);
+ }
+ else
+ {
+ sprintf(buffer, "NEG %s, %s", dest, source);
+ }
+
+ break;
+
+ // NEGS
+ case 0x5c: case 0x5d: case 0x5e: case 0x5f:
+
+ RR_format(source, dest, op, 0);
+
+ if( source_code == SR_REGISTER && !source_bit )
+ {
+ sprintf(buffer, "NEGS %s, C", dest);
+ }
+ else
+ {
+ sprintf(buffer, "NEGS %s, %s", dest, source);
+ }
+
+ break;
+
+ // CMPI
+ case 0x60: case 0x61: case 0x62: case 0x63:
+ {
+ UINT32 imm = Rimm_format(dest, op, &pc, 0);
+
+ sprintf(buffer, "CMPI %s, $%x", dest, imm);
+
+ break;
+ }
+
+ // MOVI
+ case 0x64: case 0x65: case 0x66: case 0x67:
+ {
+ UINT32 imm = Rimm_format(dest, op, &pc, h_flag);
+
+ sprintf(buffer, "MOVI %s, $%x", dest, imm);
+
+ break;
+ }
+
+ // ADDI
+ case 0x68: case 0x69: case 0x6a: case 0x6b:
+ {
+ UINT32 imm = Rimm_format(dest, op, &pc, 0);
+
+ if( !N_VALUE(op) )
+ {
+ sprintf(buffer, "ADDI %s, CZ", dest);
+ }
+ else
+ {
+ sprintf(buffer, "ADDI %s, $%x", dest, imm);
+ }
+
+ break;
+ }
+
+ // ADDSI
+ case 0x6c: case 0x6d: case 0x6e: case 0x6f:
+ {
+ UINT32 imm = Rimm_format(dest, op, &pc, 0);
+
+ if( !N_VALUE(op) )
+ {
+ sprintf(buffer, "ADDSI %s, CZ", dest);
+ }
+ else
+ {
+ sprintf(buffer, "ADDSI %s, $%x", dest, imm);
+ }
+
+ break;
+ }
+
+ // CMPBI
+ case 0x70: case 0x71: case 0x72: case 0x73:
+ {
+ UINT32 imm = Rimm_format(dest, op, &pc, 0);
+
+ if( !N_VALUE(op) )
+ {
+ sprintf(buffer, "CMPBI %s, ANYBZ", dest);
+ }
+ else
+ {
+ if( N_VALUE(op) == 31 )
+ imm = 0x7fffffff; //bit 31 = 0, others = 1
+
+ sprintf(buffer, "CMPBI %s, $%x", dest, imm);
+ }
+
+ break;
+ }
+
+ // ANDNI
+ case 0x74: case 0x75: case 0x76: case 0x77:
+ {
+ UINT32 imm = Rimm_format(dest, op, &pc, 0);
+
+ if( N_VALUE(op) == 31 )
+ imm = 0x7fffffff; //bit 31 = 0, others = 1
+
+ sprintf(buffer, "ANDNI %s, $%x", dest, imm);
+
+ break;
+ }
+
+ // ORI
+ case 0x78: case 0x79: case 0x7a: case 0x7b:
+ {
+ UINT32 imm = Rimm_format(dest, op, &pc, 0);
+
+ sprintf(buffer, "ORI %s, $%x", dest, imm);
+
+ break;
+ }
+
+ // XORI
+ case 0x7c: case 0x7d: case 0x7e: case 0x7f:
+ {
+ UINT32 imm = Rimm_format(dest, op, &pc, 0);
+
+ sprintf(buffer, "XORI %s, $%x", dest, imm);
+
+ break;
+ }
+
+ // SHRDI
+ case 0x80: case 0x81:
+ {
+ UINT8 n = Ln_format(dest, op);
+
+ sprintf(buffer, "SHRDI %s, $%x", dest, n);
+
+ break;
+ }
+
+ // SHRD
+ case 0x82:
+
+ LL_format(source, dest, op);
+
+ sprintf(buffer, "SHRD %s, %s", dest, source);
+
+ break;
+
+ // SHR
+ case 0x83:
+
+ LL_format(source, dest, op);
+
+ sprintf(buffer, "SHR %s, %s", dest, source);
+
+ break;
+
+ // SARDI
+ case 0x84: case 0x85:
+ {
+ UINT8 n = Ln_format(dest, op);
+
+ sprintf(buffer, "SARDI %s, $%x", dest, n);
+
+ break;
+ }
+
+ // SARD
+ case 0x86:
+
+ LL_format(source, dest, op);
+
+ sprintf(buffer, "SARD %s, %s", dest, source);
+
+ break;
+
+ // SAR
+ case 0x87:
+
+ LL_format(source, dest, op);
+
+ sprintf(buffer, "SAR %s, %s", dest, source);
+
+ break;
+
+ // SHLDI
+ case 0x88: case 0x89:
+ {
+ UINT8 n = Ln_format(dest, op);
+
+ sprintf(buffer, "SHLDI %s, $%x", dest, n);
+
+ break;
+ }
+
+ // SHLD
+ case 0x8a:
+
+ LL_format(source, dest, op);
+
+ sprintf(buffer, "SHLD %s, %s", dest, source);
+
+ break;
+
+ // SHL
+ case 0x8b:
+
+ LL_format(source, dest, op);
+
+ sprintf(buffer, "SHL %s, %s", dest, source);
+
+ break;
+
+ // RESERVED
+ case 0x8c: case 0x8d:
+ case 0xac: case 0xad: case 0xae: case 0xaf:
+
+ sprintf(buffer, "Reserved");
+
+ break;
+
+ // TESTLZ
+ case 0x8e:
+
+ LL_format(source, dest, op);
+
+ sprintf(buffer, "TESTLZ %s, %s", dest, source);
+
+ break;
+
+ // ROL
+ case 0x8f:
+
+ LL_format(source, dest, op);
+
+ sprintf(buffer, "ROL %s, %s", dest, source);
+
+ break;
+
+ // LDxx.D/A/IOD/IOA
+ case 0x90: case 0x91: case 0x92: case 0x93:
+ {
+ UINT16 next_op = READ_OP_DASM(pc + 2);
+ UINT32 dis = RRdis_format(source, dest, op, next_op, pc);
+
+ if( size == 2 )
+ size = 4;
+
+ if( dest_code == SR_REGISTER && !dest_bit )
+ {
+ switch( DD( next_op ) )
+ {
+ case 0:
+ // LDBS.A
+ sprintf(buffer, "LDBS.A 0, %s, $%x", source, dis);
+ break;
+
+ case 1:
+ // LDBU.A
+ sprintf(buffer, "LDBU.A 0, %s, $%x", source, dis);
+ break;
+
+ case 2:
+ // LDHS.A
+ if( dis & 1 )
+ {
+ sprintf(buffer, "LDHS.A 0, %s, $%x", source, dis & ~1);
+ }
+ // LDHU.A
+ else
+ {
+ sprintf(buffer, "LDHU.A 0, %s, $%x", source, dis & ~1);
+ }
+
+ break;
+
+ case 3:
+ // LDD.IOA
+ if( (dis & 3) == 3 )
+ {
+ sprintf(buffer, "LDD.IOA 0, %s, $%x", source, dis & ~3);
+ }
+ // LDW.IOA
+ else if( (dis & 3) == 2 )
+ {
+ sprintf(buffer, "LDW.IOA 0, %s, $%x", source, dis & ~3);
+ }
+ // LDD.A
+ else if( (dis & 3) == 1 )
+ {
+ sprintf(buffer, "LDD.A 0, %s, $%x", source, dis & ~1);
+ }
+ // LDW.A
+ else
+ {
+ sprintf(buffer, "LDW.A 0, %s, $%x", source, dis & ~1);
+ }
+
+ break;
+ }
+ }
+ else
+ {
+ switch( DD( next_op ) )
+ {
+ case 0:
+ // LDBS.D
+ sprintf(buffer, "LDBS.D %s, %s, $%x", dest, source, dis);
+ break;
+
+ case 1:
+ // LDBU.D
+ sprintf(buffer, "LDBU.D %s, %s, $%x", dest, source, dis);
+ break;
+
+ case 2:
+ // LDHS.D
+ if( dis & 1 )
+ {
+ sprintf(buffer, "LDHS.D %s, %s, $%x", dest, source, dis & ~1);
+ }
+ // LDHU.D
+ else
+ {
+ sprintf(buffer, "LDHU.D %s, %s, $%x", dest, source, dis & ~1);
+ }
+ break;
+
+ case 3:
+ // LDD.IOD
+ if( (dis & 3) == 3 )
+ {
+ sprintf(buffer, "LDD.IOD %s, %s, $%x", dest, source, dis & ~3);
+ }
+ // LDW.IOD
+ else if( (dis & 3) == 2 )
+ {
+ sprintf(buffer, "LDW.IOD %s, %s, $%x", dest, source, dis & ~3);
+ }
+ // LDD.D
+ else if( (dis & 3) == 1 )
+ {
+ sprintf(buffer, "LDD.D %s, %s, $%x", dest, source, dis & ~1);
+ }
+ // LDW.D
+ else
+ {
+ sprintf(buffer, "LDW.D %s, %s, $%x", dest, source, dis & ~1);
+ }
+
+ break;
+ }
+ }
+
+ break;
+ }
+
+ // LDxx.N/S
+ case 0x94: case 0x95: case 0x96: case 0x97:
+ {
+ UINT16 next_op = READ_OP_DASM(pc + 2);
+ UINT32 dis = RRdis_format(source, dest, op, next_op, pc);
+
+ if( size == 2 )
+ size = 4;
+
+ if( (dest_code == PC_REGISTER && !dest_bit) || (dest_code == SR_REGISTER && !dest_bit) )
+ {
+ sprintf(buffer, "Reserved");
+ break;
+ }
+
+ switch( DD( next_op ) )
+ {
+ case 0:
+ // LDBS.N
+ sprintf(buffer, "LDBS.N %s, %s, $%x", dest, source, dis);
+ break;
+
+ case 1:
+ // LDBU.N
+ sprintf(buffer, "LDBU.N %s, %s, $%x", dest, source, dis);
+ break;
+
+ case 2:
+ // LDHS.N
+ if( dis & 1 )
+ {
+ sprintf(buffer, "LDHS.N %s, %s, $%x", dest, source, dis & ~1);
+ }
+ // LDHU.N
+ else
+ {
+ sprintf(buffer, "LDHU.N %s, %s, $%x", dest, source, dis & ~1);
+ }
+
+ break;
+
+ case 3:
+ // LDW.S
+ if( (dis & 3) == 3 )
+ {
+ sprintf(buffer, "LDW.S %s, %s, $%x", dest, source, dis & ~3);
+ }
+ // Reserved
+ else if( (dis & 3) == 2 )
+ {
+ sprintf(buffer, "Reserved");
+ }
+ // LDD.N
+ else if( (dis & 3) == 1 )
+ {
+ sprintf(buffer, "LDD.N %s, %s, $%x", dest, source, dis & ~1);
+ }
+ // LDW.N
+ else
+ {
+ sprintf(buffer, "LDW.N %s, %s, $%x", dest, source, dis & ~1);
+ }
+
+ break;
+ }
+
+ break;
+ }
+
+ // STxx.D/A/IOD/IOA
+ case 0x98: case 0x99: case 0x9a: case 0x9b:
+ {
+ UINT16 next_op = READ_OP_DASM(pc + 2);
+ UINT32 dis = RRdis_format(source, dest, op, next_op, pc);
+
+ if( size == 2 )
+ size = 4;
+
+ if( source_code == SR_REGISTER && !source_bit )
+ strcpy(source,"0");
+
+ if( dest_code == SR_REGISTER && !dest_bit )
+ {
+ switch( DD( next_op ) )
+ {
+ case 0:
+ // STBS.A
+ sprintf(buffer, "STBS.A 0, %s, $%x", source, dis);
+ break;
+
+ case 1:
+ // STBU.A
+ sprintf(buffer, "STBU.A 0, %s, $%x", source, dis);
+ break;
+
+ case 2:
+ // STHS.A
+ if( dis & 1 )
+ {
+ sprintf(buffer, "STHS.A 0, %s, $%x", source, dis & ~1);
+ }
+ // STHU.A
+ else
+ {
+ sprintf(buffer, "STHU.A 0, %s, $%x", source, dis & ~1);
+ }
+
+ break;
+
+ case 3:
+ // STD.IOA
+ if( (dis & 3) == 3 )
+ {
+ sprintf(buffer, "STD.IOA 0, %s, $%x", source, dis & ~3);
+ }
+ // STW.IOA
+ else if( (dis & 3) == 2 )
+ {
+ sprintf(buffer, "STW.IOA 0, %s, $%x", source, dis & ~3);
+ }
+ // STD.A
+ else if( (dis & 3) == 1 )
+ {
+ sprintf(buffer, "STD.A 0, %s, $%x", source, dis & ~1);
+ }
+ // STW.A
+ else
+ {
+ sprintf(buffer, "STW.A 0, %s, $%x", source, dis & ~1);
+ }
+
+ break;
+ }
+ }
+ else
+ {
+ switch( DD( next_op ) )
+ {
+ case 0:
+ // STBS.D
+ sprintf(buffer, "STBS.D %s, %s, $%x", dest, source, dis);
+ break;
+
+ case 1:
+ // STBU.D
+ sprintf(buffer, "STBU.D %s, %s, $%x", dest, source, dis);
+ break;
+
+ case 2:
+ // STHS.D
+ if( dis & 1 )
+ {
+ sprintf(buffer, "STHS.D %s, %s, $%x", dest, source, dis & ~1);
+ }
+ // STHU.D
+ else
+ {
+ sprintf(buffer, "STHU.D %s, %s, $%x", dest, source, dis & ~1);
+ }
+ break;
+
+ case 3:
+ // STD.IOD
+ if( (dis & 3) == 3 )
+ {
+ sprintf(buffer, "STD.IOD %s, %s, $%x", dest, source, dis & ~3);
+ }
+ // STW.IOD
+ else if( (dis & 3) == 2 )
+ {
+ sprintf(buffer, "STW.IOD %s, %s, $%x", dest, source, dis & ~3);
+ }
+ // STD.D
+ else if( (dis & 3) == 1 )
+ {
+ sprintf(buffer, "STD.D %s, %s, $%x", dest, source, dis & ~1);
+ }
+ // STW.D
+ else
+ {
+ sprintf(buffer, "STW.D %s, %s, $%x", dest, source, dis & ~1);
+ }
+
+ break;
+ }
+ }
+
+ break;
+ }
+
+ // STxx.N/S
+ case 0x9c: case 0x9d: case 0x9e: case 0x9f:
+ {
+ UINT16 next_op = READ_OP_DASM(pc + 2);
+ UINT32 dis = RRdis_format(source, dest, op, next_op, pc);
+
+ if( size == 2 )
+ size = 4;
+
+ if( source_code == SR_REGISTER && !source_bit )
+ strcpy(source,"0");
+
+ if( (dest_code == PC_REGISTER && !dest_bit) || (dest_code == SR_REGISTER && !dest_bit) )
+ {
+ sprintf(buffer, "Reserved");
+ break;
+ }
+
+ switch( DD( next_op ) )
+ {
+ case 0:
+ // STBS.N
+ sprintf(buffer, "STBS.N %s, %s, $%x", dest, source, dis);
+ break;
+
+ case 1:
+ // STBU.N
+ sprintf(buffer, "STBU.N %s, %s, $%x", dest, source, dis);
+ break;
+
+ case 2:
+ // STHS.N
+ if( dis & 1 )
+ {
+ sprintf(buffer, "STHS.N %s, %s, $%x", dest, source, dis & ~1);
+ }
+ // STHU.N
+ else
+ {
+ sprintf(buffer, "STHU.N %s, %s, $%x", dest, source, dis & ~1);
+ }
+
+ break;
+
+ case 3:
+ // STW.S
+ if( (dis & 3) == 3 )
+ {
+ sprintf(buffer, "STW.S %s, %s, $%x", dest, source, dis & ~3);
+ }
+ // Reserved
+ else if( (dis & 3) == 2 )
+ {
+ sprintf(buffer, "Reserved");
+ }
+ // STD.N
+ else if( (dis & 3) == 1 )
+ {
+ sprintf(buffer, "STD.N %s, %s, $%x", dest, source, dis & ~1);
+ }
+ // STW.N
+ else
+ {
+ sprintf(buffer, "STW.N %s, %s, $%x", dest, source, dis & ~1);
+ }
+
+ break;
+ }
+
+ break;
+ }
+
+ // SHRI
+ case 0xa0: case 0xa1: case 0xa2: case 0xa3:
+ {
+ UINT8 n = Rn_format(dest, op);
+
+ sprintf(buffer, "SHRI %s, $%x", dest, n);
+
+ break;
+ }
+
+ // SARI
+ case 0xa4: case 0xa5: case 0xa6: case 0xa7:
+ {
+ UINT8 n = Rn_format(dest, op);
+
+ sprintf(buffer, "SARI %s, $%x", dest, n);
+
+ break;
+ }
+
+ // SHLI
+ case 0xa8: case 0xa9: case 0xaa: case 0xab:
+ {
+ UINT8 n = Rn_format(dest, op);
+
+ sprintf(buffer, "SHLI %s, $%x", dest, n);
+
+ break;
+ }
+
+ // MULU
+ case 0xb0: case 0xb1: case 0xb2: case 0xb3:
+
+ RR_format(source, dest, op, 0);
+
+ sprintf(buffer, "MULU %s, %s", dest, source);
+
+ break;
+
+ // MULS
+ case 0xb4: case 0xb5: case 0xb6: case 0xb7:
+
+ RR_format(source, dest, op, 0);
+
+ sprintf(buffer, "MULS %s, %s", dest, source);
+
+ break;
+
+ // SETxx - SETADR - FETCH
+ case 0xb8: case 0xb9: case 0xba: case 0xbb:
+ {
+ UINT8 n = Rn_format(dest, op);
+
+ if( dest_code == PC_REGISTER && !dest_bit )
+ {
+ sprintf(buffer, "Illegal PC: $%x OP: $%x", pc, op);
+ }
+ else if( dest_code == SR_REGISTER && !dest_bit )
+ {
+ sprintf(buffer, "FETCH $%x", (n / 2) + 1);
+ }
+ else
+ {
+ sprintf(buffer, "%s %s", SETxx[n], dest);
+ }
+
+ break;
+ }
+
+ // MUL
+ case 0xbc: case 0xbd: case 0xbe: case 0xbf:
+
+ RR_format(source, dest, op, 0);
+
+ sprintf(buffer, "MUL %s, %s", dest, source);
+
+ break;
+
+ // FADD
+ case 0xc0:
+
+ LL_format(source, dest, op);
+
+ sprintf(buffer, "FADD %s, %s", dest, source);
+
+ break;
+
+ // FADDD
+ case 0xc1:
+
+ LL_format(source, dest, op);
+
+ sprintf(buffer, "FADDD %s, %s", dest, source);
+
+ break;
+
+ // FSUB
+ case 0xc2:
+
+ LL_format(source, dest, op);
+
+ sprintf(buffer, "FSUB %s, %s", dest, source);
+
+ break;
+
+ // FSUBD
+ case 0xc3:
+
+ LL_format(source, dest, op);
+
+ sprintf(buffer, "FSUBD %s, %s", dest, source);
+
+ break;
+
+ // FMUL
+ case 0xc4:
+
+ LL_format(source, dest, op);
+
+ sprintf(buffer, "FMUL %s, %s", dest, source);
+
+ break;
+
+ // FMULD
+ case 0xc5:
+
+ LL_format(source, dest, op);
+
+ sprintf(buffer, "FMULD %s, %s", dest, source);
+
+ break;
+
+ // FDIV
+ case 0xc6:
+
+ LL_format(source, dest, op);
+
+ sprintf(buffer, "FDIV %s, %s", dest, source);
+
+ break;
+
+ // FDIVD
+ case 0xc7:
+
+ LL_format(source, dest, op);
+
+ sprintf(buffer, "FDIVD %s, %s", dest, source);
+
+ break;
+
+ // FCMP
+ case 0xc8:
+
+ LL_format(source, dest, op);
+
+ sprintf(buffer, "FCMP %s, %s", dest, source);
+
+ break;
+
+ // FCMPD
+ case 0xc9:
+
+ LL_format(source, dest, op);
+
+ sprintf(buffer, "FCMPD %s, %s", dest, source);
+
+ break;
+
+ // FCMPU
+ case 0xca:
+
+ LL_format(source, dest, op);
+
+ sprintf(buffer, "FCMPU %s, %s", dest, source);
+
+ break;
+
+ // FCMPUD
+ case 0xcb:
+
+ LL_format(source, dest, op);
+
+ sprintf(buffer, "FCMPUD %s, %s", dest, source);
+
+ break;
+
+ // FCVT
+ case 0xcc:
+
+ LL_format(source, dest, op);
+
+ sprintf(buffer, "FCVT %s, %s", dest, source);
+
+ break;
+
+ // FCVTD
+ case 0xcd:
+
+ LL_format(source, dest, op);
+
+ sprintf(buffer, "FCVTD %s, %s", dest, source);
+
+ break;
+
+ // EXTEND
+ case 0xce:
+ {
+ UINT16 extended_op;
+
+ LL_format(source, dest, op);
+
+ pc += 2;
+ extended_op = READ_OP_DASM(pc);
+
+ size = 4;
+
+ switch( extended_op )
+ {
+ case 0x100:
+ case EMUL:
+ sprintf(buffer, "EMUL %s, %s", dest, source);
+ break;
+
+ case EMULU:
+ sprintf(buffer, "EMULU %s, %s", dest, source);
+ break;
+
+ case EMULS:
+ sprintf(buffer, "EMULS %s, %s", dest, source);
+ break;
+
+ case EMAC:
+ sprintf(buffer, "EMAC %s, %s", dest, source);
+ break;
+
+ case EMACD:
+ sprintf(buffer, "EMACD %s, %s", dest, source);
+ break;
+
+ case EMSUB:
+ sprintf(buffer, "EMSUB %s, %s", dest, source);
+ break;
+
+ case EMSUBD:
+ sprintf(buffer, "EMSUBD %s, %s", dest, source);
+ break;
+
+ case EHMAC:
+ sprintf(buffer, "EHMAC %s, %s", dest, source);
+ break;
+
+ case EHMACD:
+ sprintf(buffer, "EHMACD %s, %s", dest, source);
+ break;
+
+ case EHCMULD:
+ sprintf(buffer, "EHCMULD %s, %s", dest, source);
+ break;
+
+ case EHCMACD:
+ sprintf(buffer, "EHCMACD %s, %s", dest, source);
+ break;
+
+ case EHCSUMD:
+ sprintf(buffer, "EHCSUMD %s, %s", dest, source);
+ break;
+
+ case EHCFFTD:
+ sprintf(buffer, "EHCFFTD %s, %s", dest, source);
+ break;
+
+ case EHCFFTSD:
+ sprintf(buffer, "EHCFFTSD %s, %s", dest, source);
+ break;
+
+ default:
+ sprintf(buffer, "Ext. OP $%x", extended_op);
+ logerror(buffer, "Illegal Extended Opcode: %x\n", extended_op);
+ break;
+ }
+
+ break;
+ }
+
+ // DO
+ case 0xcf:
+
+ LL_format(source, dest, op);
+
+ sprintf(buffer, "DO %s, %s", dest, source);
+
+ break;
+
+ // LDW.R
+ case 0xd0: case 0xd1:
+
+ LR_format(source, dest, op);
+
+ sprintf(buffer, "LDW.R %s, %s", dest, source);
+
+ break;
+
+ // LDD.R
+ case 0xd2: case 0xd3:
+
+ LR_format(source, dest, op);
+
+ sprintf(buffer, "LDD.R %s, %s", dest, source);
+
+ break;
+
+ // LDW.P
+ case 0xd4: case 0xd5:
+
+ LR_format(source, dest, op);
+
+ sprintf(buffer, "LDW.P %s, %s", dest, source);
+
+ break;
+
+ // LDD.P
+ case 0xd6: case 0xd7:
+
+ LR_format(source, dest, op);
+
+ sprintf(buffer, "LDD.P %s, %s", dest, source);
+
+ break;
+
+ // STW.R
+ case 0xd8: case 0xd9:
+
+ LR_format(source, dest, op);
+
+ if( source_code == SR_REGISTER && !source_bit )
+ strcpy(source,"0");
+
+ sprintf(buffer, "STW.R %s, %s", dest, source);
+
+ break;
+
+ // STD.R
+ case 0xda: case 0xdb:
+
+ LR_format(source, dest, op);
+
+ if( source_code == SR_REGISTER && !source_bit )
+ strcpy(source,"0");
+
+ sprintf(buffer, "STD.R %s, %s", dest, source);
+
+ break;
+
+ // STW.P
+ case 0xdc: case 0xdd:
+
+ LR_format(source, dest, op);
+
+ if( source_code == SR_REGISTER && !source_bit )
+ strcpy(source,"0");
+
+ sprintf(buffer, "STW.P %s, %s", dest, source);
+
+ break;
+
+ // STD.P
+ case 0xde: case 0xdf:
+
+ LR_format(source, dest, op);
+
+ if( source_code == SR_REGISTER && !source_bit )
+ strcpy(source,"0");
+
+ sprintf(buffer, "STD.P %s, %s", dest, source);
+
+ break;
+
+ // DBV
+ case 0xe0:
+ {
+ INT32 rel = PCrel_format(op, pc) + 2;
+
+ sprintf(buffer, "DBV $%x", rel);
+ flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1);
+
+ break;
+ }
+
+ // DBNV
+ case 0xe1:
+ {
+ INT32 rel = PCrel_format(op, pc) + 2;
+
+ sprintf(buffer, "DBNV $%x", rel);
+ flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1);
+
+ break;
+ }
+
+ // DBE
+ case 0xe2:
+ {
+ INT32 rel = PCrel_format(op, pc) + 2;
+
+ sprintf(buffer, "DBE $%x", rel);
+ flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1);
+
+ break;
+ }
+
+ // DBNE
+ case 0xe3:
+ {
+ INT32 rel = PCrel_format(op, pc) + 2;
+
+ sprintf(buffer, "DBNE $%x", rel);
+ flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1);
+
+ break;
+ }
+
+ // DBC
+ case 0xe4:
+ {
+ INT32 rel = PCrel_format(op, pc) + 2;
+
+ sprintf(buffer, "DBC $%x", rel);
+ flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1);
+
+ break;
+ }
+
+ // DBNC
+ case 0xe5:
+ {
+ INT32 rel = PCrel_format(op, pc) + 2;
+
+ sprintf(buffer, "DBNC $%x", rel);
+ flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1);
+
+ break;
+ }
+
+ // DBSE
+ case 0xe6:
+ {
+ INT32 rel = PCrel_format(op, pc) + 2;
+
+ sprintf(buffer, "DBSE $%x", rel);
+ flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1);
+
+ break;
+ }
+
+ // DBHT
+ case 0xe7:
+ {
+ INT32 rel = PCrel_format(op, pc) + 2;
+
+ sprintf(buffer, "DBHT $%x", rel);
+ flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1);
+
+ break;
+ }
+
+ // DBN
+ case 0xe8:
+ {
+ INT32 rel = PCrel_format(op, pc) + 2;
+
+ sprintf(buffer, "DBN $%x", rel);
+ flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1);
+
+ break;
+ }
+
+ // DBNN
+ case 0xe9:
+ {
+ INT32 rel = PCrel_format(op, pc) + 2;
+
+ sprintf(buffer, "DBNN $%x", rel);
+ flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1);
+
+ break;
+ }
+
+ // DBLE
+ case 0xea:
+ {
+ INT32 rel = PCrel_format(op, pc) + 2;
+
+ sprintf(buffer, "DBLE $%x", rel);
+ flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1);
+
+ break;
+ }
+
+ // DBGT
+ case 0xeb:
+ {
+ INT32 rel = PCrel_format(op, pc) + 2;
+
+ sprintf(buffer, "DBGT $%x", rel);
+ flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1);
+
+ break;
+ }
+
+ // DBR
+ case 0xec:
+ {
+ INT32 rel = PCrel_format(op, pc) + 2;
+
+ sprintf(buffer, "DBR $%x", rel);
+ flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1);
+
+ break;
+ }
+
+ // FRAME
+ case 0xed:
+
+ global_fp = 0;
+ LL_format(source, dest, op);
+
+ sprintf(buffer, "FRAME %s, %s", dest, source);
+
+ break;
+
+ // CALL
+ case 0xee: case 0xef:
+ {
+ UINT32 const_val = LRconst_format(source, dest, op, &pc);
+
+ if( source_code == SR_REGISTER && !source_bit )
+ {
+ sprintf(buffer, "CALL %s, 0, $%x", dest, const_val);
+ flags = DASMFLAG_STEP_OVER;
+ }
+ else
+ {
+ sprintf(buffer, "CALL %s, %s, $%x", dest, source, const_val);
+ flags = DASMFLAG_STEP_OVER;
+ }
+
+ break;
+ }
+
+ // BV
+ case 0xf0:
+ {
+ INT32 rel = PCrel_format(op, pc) + 2;
+
+ sprintf(buffer, "BV $%x", rel);
+
+ break;
+ }
+
+ // BNV
+ case 0xf1:
+ {
+ INT32 rel = PCrel_format(op, pc) + 2;
+
+ sprintf(buffer, "BNV $%x", rel);
+
+ break;
+ }
+
+ // BE
+ case 0xf2:
+ {
+ INT32 rel = PCrel_format(op, pc) + 2;
+
+ sprintf(buffer, "BE $%x", rel);
+
+ break;
+ }
+
+ // BNE
+ case 0xf3:
+ {
+ INT32 rel = PCrel_format(op, pc) + 2;
+
+ sprintf(buffer, "BNE $%x", rel);
+
+ break;
+ }
+
+ // BC
+ case 0xf4:
+ {
+ INT32 rel = PCrel_format(op, pc) + 2;
+
+ sprintf(buffer, "BC $%x", rel);
+
+ break;
+ }
+
+ // BNC
+ case 0xf5:
+ {
+ INT32 rel = PCrel_format(op, pc) + 2;
+
+ sprintf(buffer, "BNC $%x", rel);
+
+ break;
+ }
+
+ // BSE
+ case 0xf6:
+ {
+ INT32 rel = PCrel_format(op, pc) + 2;
+
+ sprintf(buffer, "BSE $%x", rel);
+
+ break;
+ }
+
+ // BHT
+ case 0xf7:
+ {
+ INT32 rel = PCrel_format(op, pc) + 2;
+
+ sprintf(buffer, "BHT $%x", rel);
+
+ break;
+ }
+
+ // BN
+ case 0xf8:
+ {
+ INT32 rel = PCrel_format(op, pc) + 2;
+
+ sprintf(buffer, "BN $%x", rel);
+
+ break;
+ }
+
+ // BNN
+ case 0xf9:
+ {
+ INT32 rel = PCrel_format(op, pc) + 2;
+
+ sprintf(buffer, "BNN $%x", rel);
+
+ break;
+ }
+
+ // BLE
+ case 0xfa:
+ {
+ INT32 rel = PCrel_format(op, pc) + 2;
+
+ sprintf(buffer, "BLE $%x", rel);
+
+ break;
+ }
+
+ // BGT
+ case 0xfb:
+ {
+ INT32 rel = PCrel_format(op, pc) + 2;
+
+ sprintf(buffer, "BGT $%x", rel);
+
+ break;
+ }
+
+ // BR
+ case 0xfc:
+ {
+ INT32 rel = PCrel_format(op, pc) + 2;
+
+ sprintf(buffer, "BR $%x", rel);
+
+ break;
+ }
+
+ // TRAPxx - TRAP
+ case 0xfd: case 0xfe: case 0xff:
+ {
+ UINT8 code = ((op & 0x300) >> 6) | (op & 0x03);
+ UINT8 trapno = (op & 0xfc) >> 2;
+
+ switch( code )
+ {
+ case TRAPLE:
+ sprintf(buffer, "TRAPLE %d", trapno);
+ flags = DASMFLAG_STEP_OVER;
+
+ break;
+
+ case TRAPGT:
+ sprintf(buffer, "TRAPGT %d", trapno);
+ flags = DASMFLAG_STEP_OVER;
+
+ break;
+
+ case TRAPLT:
+ sprintf(buffer, "TRAPLT %d", trapno);
+ flags = DASMFLAG_STEP_OVER;
+
+ break;
+
+ case TRAPGE:
+ sprintf(buffer, "TRAPGE %d", trapno);
+ flags = DASMFLAG_STEP_OVER;
+
+ break;
+
+ case TRAPSE:
+ sprintf(buffer, "TRAPSE %d", trapno);
+ flags = DASMFLAG_STEP_OVER;
+
+ break;
+
+ case TRAPHT:
+ sprintf(buffer, "TRAPHT %d", trapno);
+ flags = DASMFLAG_STEP_OVER;
+
+ break;
+
+ case TRAPST:
+ sprintf(buffer, "TRAPST %d", trapno);
+ flags = DASMFLAG_STEP_OVER;
+
+ break;
+
+ case TRAPHE:
+ sprintf(buffer, "TRAPHE %d", trapno);
+ flags = DASMFLAG_STEP_OVER;
+
+ break;
+
+ case TRAPE:
+ sprintf(buffer, "TRAPE %d", trapno);
+ flags = DASMFLAG_STEP_OVER;
+
+ break;
+
+ case TRAPNE:
+ sprintf(buffer, "TRAPNE %d", trapno);
+ flags = DASMFLAG_STEP_OVER;
+
+ break;
+
+ case TRAPV:
+ sprintf(buffer, "TRAPV %d", trapno);
+ flags = DASMFLAG_STEP_OVER;
+
+ break;
+
+ case TRAP:
+ sprintf(buffer, "TRAP %d", trapno);
+ flags = DASMFLAG_STEP_OVER;
+
+ break;
+ }
+
+ break;
+ }
+ }
+
+ return size | flags | DASMFLAG_SUPPORTED;
+}
+
+CPU_DISASSEMBLE( hyperstone_generic )
+{
+ return dasm_hyperstone( buffer, pc, oprom, 0, 0 );
+}
diff --git a/trunk/src/emu/cpu/e132xs/e132xs.c b/trunk/src/emu/cpu/e132xs/e132xs.c
new file mode 100644
index 00000000000..d93620aba96
--- /dev/null
+++ b/trunk/src/emu/cpu/e132xs/e132xs.c
@@ -0,0 +1,5449 @@
+/********************************************************************
+ Hyperstone cpu emulator
+ written by Pierpaolo Prazzoli
+
+ All the types are compatible, but they have different IRAM size and cycles
+
+ Hyperstone models:
+
+ 16 bits
+ - E1-16T
+ - E1-16XT
+ - E1-16XS
+ - E1-16XSR
+
+ 32bits
+ - E1-32N or E1-32T
+ - E1-32XN or E1-32XT
+ - E1-32XS
+ - E1-32XSR
+
+ Hynix models:
+
+ 16 bits
+ - GMS30C2116
+ - GMS30C2216
+
+ 32bits
+ - GMS30C2132
+ - GMS30C2232
+
+ TODO:
+ - some wrong cycle counts
+
+ CHANGELOG:
+
+ Pierpaolo Prazzoli
+ - Fixed LDxx.N/P/S opcodes not to increment the destination register when
+ it's the same as the source or "next source" one.
+
+ Pierpaolo Prazzoli
+ - Removed nested delays
+ - Added better delay branch support
+ - Fixed PC seen by a delay instruction, because a delay instruction
+ should use the delayed PC (thus allowing the execution of software
+ opcodes too)
+
+ Tomasz Slanina
+ - Fixed delayed branching for delay instructions longer than 2 bytes
+
+ Pierpaolo Prazzoli
+ - Added and fixed Timer without hack
+
+ Tomasz Slanina
+ - Fixed MULU/MULS
+ - Fixed Carry in ADDC/SUBC
+
+ Pierpaolo Prazzoli
+ - Fixed software opcodes used as delay instructions
+ - Added nested delays
+
+ Tomasz Slanina
+ - Added "undefined" C flag to shift left instructions
+
+ Pierpaolo Prazzoli
+ - Added interrupts-block for delay instructions
+ - Fixed get_emu_code_addr
+ - Added LDW.S and STW.S instructions
+ - Fixed floating point opcodes
+
+ Tomasz Slanina
+ - interrputs after call and before frame are prohibited now
+ - emulation of FCR register
+ - Floating point opcodes (preliminary)
+ - Fixed stack addressing in RET/FRAME opcodes
+ - Fixed bug in SET_RS macro
+ - Fixed bug in return opcode (S flag)
+ - Added C/N flags calculation in add/adc/addi/adds/addsi and some shift opcodes
+ - Added writeback to ROL
+ - Fixed ROL/SAR/SARD/SHR/SHRD/SHL/SHLD opcode decoding (Local/Global regs)
+ - Fixed I and T flag in RET opcode
+ - Fixed XX/XM opcodes
+ - Fixed MOV opcode, when RD = PC
+ - Fixed execute_trap()
+ - Fixed ST opcodes, when when RS = SR
+ - Added interrupts
+ - Fixed I/O addressing
+
+ Pierpaolo Prazzoli
+ - Fixed fetch
+ - Fixed decode of hyperstone_xm opcode
+ - Fixed 7 bits difference number in FRAME / RET instructions
+ - Some debbugger fixes
+ - Added generic registers decode function
+ - Some other little fixes.
+
+ MooglyGuy 29/03/2004
+ - Changed MOVI to use unsigned values instead of signed, correcting
+ an ugly glitch when loading 32-bit immediates.
+ Pierpaolo Prazzoli
+ - Same fix in get_const
+
+ MooglyGuy - 02/27/04
+ - Fixed delayed branching
+ - const_val for CALL should always have bit 0 clear
+
+ Pierpaolo Prazzoli - 02/25/04
+ - Fixed some wrong addresses to address local registers instead of memory
+ - Fixed FRAME and RET instruction
+ - Added preliminary I/O space
+ - Fixed some load / store instructions
+
+ Pierpaolo Prazzoli - 02/20/04
+ - Added execute_exception function
+ - Added FL == 0 always interpreted as 16
+
+ Pierpaolo Prazzoli - 02/19/04
+ - Changed the reset to use the execute_trap(reset) which should be right to set
+ the initiale state of the cpu
+ - Added Trace exception
+ - Set of T flag in RET instruction
+ - Set I flag in interrupts entries and resetted by a RET instruction
+ - Added correct set instruction for SR
+
+ Pierpaolo Prazzoli - 10/26/03
+ - Changed get_lrconst to get_const and changed it to use the removed GET_CONST_RR
+ macro.
+ - Removed the High flag used in some opcodes, it should be used only in
+ MOV and MOVI instruction.
+ - Fixed MOV and MOVI instruction.
+ - Set to 1 FP is SR register at reset.
+ (From the doc: A Call, Trap or Software instruction increments the FP and sets FL
+ to 6, thus creating a new stack frame with the length of 6 registers).
+
+ MooglyGuy - 10/25/03
+ - Fixed CALL enough that it at least jumps to the right address, no word
+ yet as to whether or not it's working enough to return.
+ - Added get_lrconst() to get the const value for the CALL operand, since
+ apparently using immediate_value() was wrong. The code is ugly, but it
+ works properly. Vampire 1/2 now gets far enough to try to test its RAM.
+ - Just from looking at it, CALL apparently doesn't frame properly. I'm not
+ sure about FRAME, but perhaps it doesn't work properly - I'm not entirely
+ positive. The return address when vamphalf's memory check routine is
+ called at FFFFFD7E is stored in register L8, and then the RET instruction
+ at the end of the routine uses L1 as the return address, so that might
+ provide some clues as to how it works.
+ - I'd almost be willing to bet money that there's no framing at all since
+ the values in L0 - L15 as displayed by the debugger would change during a
+ CALL or FRAME operation. I'll look when I'm in the mood.
+ - The mood struck me, and I took a look at SET_L_REG and GET_L_REG.
+ Apparently no matter what the current frame pointer is they'll always use
+ local_regs[0] through local_regs[15].
+
+ MooglyGuy - 08/20/03
+ - Added H flag support for MOV and MOVI
+ - Changed init routine to set S flag on boot. Apparently the CPU defaults to
+ supervisor mode as opposed to user mode when it powers on, as shown by the
+ vamphalf power-on routines. Makes sense, too, since if the machine booted
+ in user mode, it would be impossible to get into supervisor mode.
+
+ Pierpaolo Prazzoli - 08/19/03
+ - Added check for D_BIT and S_BIT where PC or SR must or must not be denoted.
+ (movd, divu, divs, ldxx1, ldxx2, stxx1, stxx2, mulu, muls, set, mul
+ call, chk)
+
+ MooglyGuy - 08/17/03
+ - Working on support for H flag, nothing quite done yet
+ - Added trap Range Error for CHK PC, PC
+ - Fixed relative jumps, they have to be taken from the opcode following the
+ jump minstead of the jump opcode itself.
+
+ Pierpaolo Prazzoli - 08/17/03
+ - Fixed get_pcrel() when OP & 0x80 is set.
+ - Decremented PC by 2 also in MOV, ADD, ADDI, SUM, SUB and added the check if
+ D_BIT is not set. (when pc is changed they are implicit branch)
+
+ MooglyGuy - 08/17/03
+ - Implemented a crude hack to set FL in the SR to 6, since according to the docs
+ that's supposed to happen each time a trap occurs, apparently including when
+ the processor starts up. The 3rd opcode executed in vamphalf checks to see if
+ the FL flag in SR 6, so it's apparently the "correct" behaviour despite the
+ docs not saying anything on it. If FL is not 6, the branch falls through and
+ encounters a CHK PC, L2, which at that point will always throw a range trap.
+ The range trap vector contains 00000000 (CHK PC, PC), which according to the
+ docs will always throw a range trap (which would effectively lock the system).
+ This revealed a bug: CHK PC, PC apparently does not throw a range trap, which
+ needs to be fixed. Now that the "correct" behaviour is hacked in with the FL
+ flags, it reveals yet another bug in that the branch is interpreted as being
+ +0x8700. This means that the PC then wraps around to 000082B0, give or take
+ a few bytes. While it does indeed branch to valid code, I highly doubt that
+ this is the desired effect. Check for signed/unsigned relative branch, maybe?
+
+ MooglyGuy - 08/16/03
+ - Fixed the debugger at least somewhat so that it displays hex instead of decimal,
+ and so that it disassembles opcodes properly.
+ - Fixed hyperstone_execute() to increment PC *after* executing the opcode instead of
+ before. This is probably why vamphalf was booting to fffffff8, but executing at
+ fffffffa instead.
+ - Changed execute_trap to decrement PC by 2 so that the next opcode isn't skipped
+ after a trap
+ - Changed execute_br to decrement PC by 2 so that the next opcode isn't skipped
+ after a branch
+ - Changed hyperstone_movi to decrement PC by 2 when G0 (PC) is modified so that the
+ next opcode isn't skipped after a branch
+ - Changed hyperstone_movi to default to a UINT32 being moved into the register
+ as opposed to a UINT8. This is wrong, the bit width is quite likely to be
+ dependent on the n field in the Rimm instruction type. However, vamphalf uses
+ MOVI G0,[FFFF]FBAC (n=$13) since there's apparently no absolute branch opcode.
+ What kind of CPU is this that it doesn't have an absolute jump in its branch
+ instructions and you have to use an immediate MOV to do an abs. jump!?
+ - Replaced usage of logerror() with smf's verboselog()
+
+*********************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "e132xs.h"
+
+#ifdef MAME_DEBUG
+#define DEBUG_PRINTF(x) do { mame_printf_debug x; } while (0)
+#else
+#define DEBUG_PRINTF(x) do { } while (0)
+#endif
+
+// set C in adds/addsi/subs/sums
+#define SETCARRYS 0
+#define MISSIONCRAFT_FLAGS 1
+
+/* Registers */
+
+enum
+{
+ E132XS_PC = 1,
+ E132XS_SR,
+ E132XS_FER,
+ E132XS_G3,
+ E132XS_G4,
+ E132XS_G5,
+ E132XS_G6,
+ E132XS_G7,
+ E132XS_G8,
+ E132XS_G9,
+ E132XS_G10,
+ E132XS_G11,
+ E132XS_G12,
+ E132XS_G13,
+ E132XS_G14,
+ E132XS_G15,
+ E132XS_G16,
+ E132XS_G17,
+ E132XS_SP,
+ E132XS_UB,
+ E132XS_BCR,
+ E132XS_TPR,
+ E132XS_TCR,
+ E132XS_TR,
+ E132XS_WCR,
+ E132XS_ISR,
+ E132XS_FCR,
+ E132XS_MCR,
+ E132XS_G28,
+ E132XS_G29,
+ E132XS_G30,
+ E132XS_G31,
+ E132XS_CL0, E132XS_CL1, E132XS_CL2, E132XS_CL3,
+ E132XS_CL4, E132XS_CL5, E132XS_CL6, E132XS_CL7,
+ E132XS_CL8, E132XS_CL9, E132XS_CL10,E132XS_CL11,
+ E132XS_CL12,E132XS_CL13,E132XS_CL14,E132XS_CL15,
+ E132XS_L0, E132XS_L1, E132XS_L2, E132XS_L3,
+ E132XS_L4, E132XS_L5, E132XS_L6, E132XS_L7,
+ E132XS_L8, E132XS_L9, E132XS_L10, E132XS_L11,
+ E132XS_L12, E132XS_L13, E132XS_L14, E132XS_L15,
+ E132XS_L16, E132XS_L17, E132XS_L18, E132XS_L19,
+ E132XS_L20, E132XS_L21, E132XS_L22, E132XS_L23,
+ E132XS_L24, E132XS_L25, E132XS_L26, E132XS_L27,
+ E132XS_L28, E132XS_L29, E132XS_L30, E132XS_L31,
+ E132XS_L32, E132XS_L33, E132XS_L34, E132XS_L35,
+ E132XS_L36, E132XS_L37, E132XS_L38, E132XS_L39,
+ E132XS_L40, E132XS_L41, E132XS_L42, E132XS_L43,
+ E132XS_L44, E132XS_L45, E132XS_L46, E132XS_L47,
+ E132XS_L48, E132XS_L49, E132XS_L50, E132XS_L51,
+ E132XS_L52, E132XS_L53, E132XS_L54, E132XS_L55,
+ E132XS_L56, E132XS_L57, E132XS_L58, E132XS_L59,
+ E132XS_L60, E132XS_L61, E132XS_L62, E132XS_L63
+};
+
+
+/* Delay information */
+struct _delay
+{
+ INT32 delay_cmd;
+ UINT32 delay_pc;
+};
+
+/* Internal registers */
+typedef struct _hyperstone_state hyperstone_state;
+struct _hyperstone_state
+{
+ UINT32 global_regs[32];
+ UINT32 local_regs[64];
+
+ /* internal stuff */
+ UINT32 ppc; // previous pc
+ UINT16 op; // opcode
+ UINT32 trap_entry; // entry point to get trap address
+
+ UINT8 clock_scale_mask;
+ UINT8 clock_scale;
+ UINT8 clock_cycles_1;
+ UINT8 clock_cycles_2;
+ UINT8 clock_cycles_4;
+ UINT8 clock_cycles_6;
+
+ UINT64 tr_base_cycles;
+ UINT32 tr_base_value;
+ UINT32 tr_clocks_per_tick;
+ UINT8 timer_int_pending;
+ emu_timer *timer;
+
+ struct _delay delay;
+
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ address_space *io;
+ UINT32 opcodexor;
+
+ INT32 instruction_length;
+ INT32 intblock;
+
+ int icount;
+};
+
+struct regs_decode
+{
+ UINT8 src, dst; // destination and source register code
+ UINT32 src_value; // current source register value
+ UINT32 next_src_value; // current next source register value
+ UINT32 dst_value; // current destination register value
+ UINT32 next_dst_value; // current next destination register value
+ UINT8 sub_type; // sub type opcode (for DD and X_CODE bits)
+ union
+ {
+ UINT32 u;
+ INT32 s;
+ } extra; // extra value such as immediate value, const, pcrel, ...
+ UINT8 src_is_local;
+ UINT8 dst_is_local;
+ UINT8 same_src_dst;
+ UINT8 same_src_dstf;
+ UINT8 same_srcf_dst;
+};
+
+static void check_interrupts(hyperstone_state *cpustate);
+
+#define SREG (decode)->src_value
+#define SREGF (decode)->next_src_value
+#define DREG (decode)->dst_value
+#define DREGF (decode)->next_dst_value
+#define EXTRA_U (decode)->extra.u
+#define EXTRA_S (decode)->extra.s
+
+#define SET_SREG( _data_ ) ((decode)->src_is_local ? set_local_register(cpustate, (decode)->src, (UINT32)_data_) : set_global_register(cpustate, (decode)->src, (UINT32)_data_))
+#define SET_SREGF( _data_ ) ((decode)->src_is_local ? set_local_register(cpustate, (decode)->src + 1, (UINT32)_data_) : set_global_register(cpustate, (decode)->src + 1, (UINT32)_data_))
+#define SET_DREG( _data_ ) ((decode)->dst_is_local ? set_local_register(cpustate, (decode)->dst, (UINT32)_data_) : set_global_register(cpustate, (decode)->dst, (UINT32)_data_))
+#define SET_DREGF( _data_ ) ((decode)->dst_is_local ? set_local_register(cpustate, (decode)->dst + 1, (UINT32)_data_) : set_global_register(cpustate, (decode)->dst + 1, (UINT32)_data_))
+
+#define SRC_IS_PC (!(decode)->src_is_local && (decode)->src == PC_REGISTER)
+#define DST_IS_PC (!(decode)->dst_is_local && (decode)->dst == PC_REGISTER)
+#define SRC_IS_SR (!(decode)->src_is_local && (decode)->src == SR_REGISTER)
+#define DST_IS_SR (!(decode)->dst_is_local && (decode)->dst == SR_REGISTER)
+#define SAME_SRC_DST (decode)->same_src_dst
+#define SAME_SRC_DSTF (decode)->same_src_dstf
+#define SAME_SRCF_DST (decode)->same_srcf_dst
+
+// 4Kb IRAM (On-Chip Memory)
+
+static ADDRESS_MAP_START( e116_4k_iram_map, AS_PROGRAM, 16 )
+ AM_RANGE(0xc0000000, 0xc0000fff) AM_RAM AM_MIRROR(0x1ffff000)
+ADDRESS_MAP_END
+
+
+
+static ADDRESS_MAP_START( e132_4k_iram_map, AS_PROGRAM, 32 )
+ AM_RANGE(0xc0000000, 0xc0000fff) AM_RAM AM_MIRROR(0x1ffff000)
+ADDRESS_MAP_END
+
+
+// 8Kb IRAM (On-Chip Memory)
+
+
+static ADDRESS_MAP_START( e116_8k_iram_map, AS_PROGRAM, 16 )
+ AM_RANGE(0xc0000000, 0xc0001fff) AM_RAM AM_MIRROR(0x1fffe000)
+ADDRESS_MAP_END
+
+
+
+static ADDRESS_MAP_START( e132_8k_iram_map, AS_PROGRAM, 32 )
+ AM_RANGE(0xc0000000, 0xc0001fff) AM_RAM AM_MIRROR(0x1fffe000)
+ADDRESS_MAP_END
+
+
+// 16Kb IRAM (On-Chip Memory)
+
+
+static ADDRESS_MAP_START( e116_16k_iram_map, AS_PROGRAM, 16 )
+ AM_RANGE(0xc0000000, 0xc0003fff) AM_RAM AM_MIRROR(0x1fffc000)
+ADDRESS_MAP_END
+
+
+
+static ADDRESS_MAP_START( e132_16k_iram_map, AS_PROGRAM, 32 )
+ AM_RANGE(0xc0000000, 0xc0003fff) AM_RAM AM_MIRROR(0x1fffc000)
+ADDRESS_MAP_END
+
+
+INLINE hyperstone_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == E116T ||
+ device->type() == E116XT ||
+ device->type() == E116XS ||
+ device->type() == E116XSR ||
+ device->type() == E132N ||
+ device->type() == E132T ||
+ device->type() == E132XN ||
+ device->type() == E132XT ||
+ device->type() == E132XS ||
+ device->type() == E132XSR ||
+ device->type() == GMS30C2116 ||
+ device->type() == GMS30C2132 ||
+ device->type() == GMS30C2216 ||
+ device->type() == GMS30C2232);
+ return (hyperstone_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+/* Return the entry point for a determinated trap */
+static UINT32 get_trap_addr(hyperstone_state *cpustate, UINT8 trapno)
+{
+ UINT32 addr;
+ if( cpustate->trap_entry == 0xffffff00 ) /* @ MEM3 */
+ {
+ addr = trapno * 4;
+ }
+ else
+ {
+ addr = (63 - trapno) * 4;
+ }
+ addr |= cpustate->trap_entry;
+
+ return addr;
+}
+
+/* Return the entry point for a determinated emulated code (the one for "extend" opcode is reserved) */
+static UINT32 get_emu_code_addr(hyperstone_state *cpustate, UINT8 num) /* num is OP */
+{
+ UINT32 addr;
+ if( cpustate->trap_entry == 0xffffff00 ) /* @ MEM3 */
+ {
+ addr = (cpustate->trap_entry - 0x100) | ((num & 0xf) << 4);
+ }
+ else
+ {
+ addr = cpustate->trap_entry | (0x10c | ((0xcf - num) << 4));
+ }
+ return addr;
+}
+
+static void hyperstone_set_trap_entry(hyperstone_state *cpustate, int which)
+{
+ switch( which )
+ {
+ case E132XS_ENTRY_MEM0:
+ cpustate->trap_entry = 0x00000000;
+ break;
+
+ case E132XS_ENTRY_MEM1:
+ cpustate->trap_entry = 0x40000000;
+ break;
+
+ case E132XS_ENTRY_MEM2:
+ cpustate->trap_entry = 0x80000000;
+ break;
+
+ case E132XS_ENTRY_MEM3:
+ cpustate->trap_entry = 0xffffff00;
+ break;
+
+ case E132XS_ENTRY_IRAM:
+ cpustate->trap_entry = 0xc0000000;
+ break;
+
+ default:
+ DEBUG_PRINTF(("Set entry point to a reserved value: %d\n", which));
+ break;
+ }
+}
+
+#define OP cpustate->op
+#define PPC cpustate->ppc //previous pc
+#define PC cpustate->global_regs[0] //Program Counter
+#define SR cpustate->global_regs[1] //Status Register
+#define FER cpustate->global_regs[2] //Floating-Point Exception Register
+// 03 - 15 General Purpose Registers
+// 16 - 17 Reserved
+#define SP cpustate->global_regs[18] //Stack Pointer
+#define UB cpustate->global_regs[19] //Upper Stack Bound
+#define BCR cpustate->global_regs[20] //Bus Control Register
+#define TPR cpustate->global_regs[21] //Timer Prescaler Register
+#define TCR cpustate->global_regs[22] //Timer Compare Register
+#define TR compute_tr(cpustate) //Timer Register
+#define WCR cpustate->global_regs[24] //Watchdog Compare Register
+#define ISR cpustate->global_regs[25] //Input Status Register
+#define FCR cpustate->global_regs[26] //Function Control Register
+#define MCR cpustate->global_regs[27] //Memory Control Register
+// 28 - 31 Reserved
+
+/* SR flags */
+#define GET_C ( SR & 0x00000001) // bit 0 //CARRY
+#define GET_Z ((SR & 0x00000002)>>1) // bit 1 //ZERO
+#define GET_N ((SR & 0x00000004)>>2) // bit 2 //NEGATIVE
+#define GET_V ((SR & 0x00000008)>>3) // bit 3 //OVERFLOW
+#define GET_M ((SR & 0x00000010)>>4) // bit 4 //CACHE-MODE
+#define GET_H ((SR & 0x00000020)>>5) // bit 5 //HIGHGLOBAL
+// bit 6 RESERVED (always 0)
+#define GET_I ((SR & 0x00000080)>>7) // bit 7 //INTERRUPT-MODE
+#define GET_FTE ((SR & 0x00001f00)>>8) // bits 12 - 8 //Floating-Point Trap Enable
+#define GET_FRM ((SR & 0x00006000)>>13) // bits 14 - 13 //Floating-Point Rounding Mode
+#define GET_L ((SR & 0x00008000)>>15) // bit 15 //INTERRUPT-LOCK
+#define GET_T ((SR & 0x00010000)>>16) // bit 16 //TRACE-MODE
+#define GET_P ((SR & 0x00020000)>>17) // bit 17 //TRACE PENDING
+#define GET_S ((SR & 0x00040000)>>18) // bit 18 //SUPERVISOR STATE
+#define GET_ILC ((SR & 0x00180000)>>19) // bits 20 - 19 //INSTRUCTION-LENGTH
+/* if FL is zero it is always interpreted as 16 */
+#define GET_FL ((SR & 0x01e00000) ? ((SR & 0x01e00000)>>21) : 16) // bits 24 - 21 //FRAME LENGTH
+#define GET_FP ((SR & 0xfe000000)>>25) // bits 31 - 25 //FRAME POINTER
+
+#define SET_C(val) (SR = (SR & ~0x00000001) | (val))
+#define SET_Z(val) (SR = (SR & ~0x00000002) | ((val) << 1))
+#define SET_N(val) (SR = (SR & ~0x00000004) | ((val) << 2))
+#define SET_V(val) (SR = (SR & ~0x00000008) | ((val) << 3))
+#define SET_M(val) (SR = (SR & ~0x00000010) | ((val) << 4))
+#define SET_H(val) (SR = (SR & ~0x00000020) | ((val) << 5))
+#define SET_I(val) (SR = (SR & ~0x00000080) | ((val) << 7))
+#define SET_FTE(val) (SR = (SR & ~0x00001f00) | ((val) << 8))
+#define SET_FRM(val) (SR = (SR & ~0x00006000) | ((val) << 13))
+#define SET_L(val) (SR = (SR & ~0x00008000) | ((val) << 15))
+#define SET_T(val) (SR = (SR & ~0x00010000) | ((val) << 16))
+#define SET_P(val) (SR = (SR & ~0x00020000) | ((val) << 17))
+#define SET_S(val) (SR = (SR & ~0x00040000) | ((val) << 18))
+#define SET_ILC(val) (SR = (SR & ~0x00180000) | ((val) << 19))
+#define SET_FL(val) (SR = (SR & ~0x01e00000) | ((val) << 21))
+#define SET_FP(val) (SR = (SR & ~0xfe000000) | ((val) << 25))
+
+#define SET_PC(val) PC = ((val) & 0xfffffffe) //PC(0) = 0
+#define SET_SP(val) SP = ((val) & 0xfffffffc) //SP(0) = SP(1) = 0
+#define SET_UB(val) UB = ((val) & 0xfffffffc) //UB(0) = UB(1) = 0
+
+#define SET_LOW_SR(val) (SR = (SR & 0xffff0000) | ((val) & 0x0000ffff)) // when SR is addressed, only low 16 bits can be changed
+
+
+#define CHECK_C(x) (SR = (SR & ~0x00000001) | (((x) & (((UINT64)1) << 32)) ? 1 : 0 ))
+#define CHECK_VADD(x,y,z) (SR = (SR & ~0x00000008) | ((((x) ^ (z)) & ((y) ^ (z)) & 0x80000000) ? 8: 0))
+#define CHECK_VADD3(x,y,w,z) (SR = (SR & ~0x00000008) | ((((x) ^ (z)) & ((y) ^ (z)) & ((w) ^ (z)) & 0x80000000) ? 8: 0))
+#define CHECK_VSUB(x,y,z) (SR = (SR & ~0x00000008) | ((((z) ^ (y)) & ((y) ^ (x)) & 0x80000000) ? 8: 0))
+
+
+/* FER flags */
+#define GET_ACCRUED (FER & 0x0000001f) //bits 4 - 0 //Floating-Point Accrued Exceptions
+#define GET_ACTUAL (FER & 0x00001f00) //bits 12 - 8 //Floating-Point Actual Exceptions
+//other bits are reversed, in particular 7 - 5 for the operating system.
+//the user program can only changes the above 2 flags
+
+
+
+
+static UINT32 compute_tr(hyperstone_state *cpustate)
+{
+ UINT64 cycles_since_base = cpustate->device->total_cycles() - cpustate->tr_base_cycles;
+ UINT64 clocks_since_base = cycles_since_base >> cpustate->clock_scale;
+ return cpustate->tr_base_value + (clocks_since_base / cpustate->tr_clocks_per_tick);
+}
+
+static void update_timer_prescale(hyperstone_state *cpustate)
+{
+ UINT32 prevtr = compute_tr(cpustate);
+ TPR &= ~0x80000000;
+ cpustate->clock_scale = (TPR >> 26) & cpustate->clock_scale_mask;
+ cpustate->clock_cycles_1 = 1 << cpustate->clock_scale;
+ cpustate->clock_cycles_2 = 2 << cpustate->clock_scale;
+ cpustate->clock_cycles_4 = 4 << cpustate->clock_scale;
+ cpustate->clock_cycles_6 = 6 << cpustate->clock_scale;
+ cpustate->tr_clocks_per_tick = ((TPR >> 16) & 0xff) + 2;
+ cpustate->tr_base_value = prevtr;
+ cpustate->tr_base_cycles = cpustate->device->total_cycles();
+}
+
+static void adjust_timer_interrupt(hyperstone_state *cpustate)
+{
+ UINT64 cycles_since_base = cpustate->device->total_cycles() - cpustate->tr_base_cycles;
+ UINT64 clocks_since_base = cycles_since_base >> cpustate->clock_scale;
+ UINT64 cycles_until_next_clock = cycles_since_base - (clocks_since_base << cpustate->clock_scale);
+
+ if (cycles_until_next_clock == 0)
+ cycles_until_next_clock = (UINT64)(1 << cpustate->clock_scale);
+
+ /* special case: if we have a change pending, set a timer to fire then */
+ if (TPR & 0x80000000)
+ {
+ UINT64 clocks_until_int = cpustate->tr_clocks_per_tick - (clocks_since_base % cpustate->tr_clocks_per_tick);
+ UINT64 cycles_until_int = (clocks_until_int << cpustate->clock_scale) + cycles_until_next_clock;
+ cpustate->timer->adjust(cpustate->device->cycles_to_attotime(cycles_until_int + 1), 1);
+ }
+
+ /* else if the timer interrupt is enabled, configure it to fire at the appropriate time */
+ else if (!(FCR & 0x00800000))
+ {
+ UINT32 curtr = cpustate->tr_base_value + (clocks_since_base / cpustate->tr_clocks_per_tick);
+ UINT32 delta = TCR - curtr;
+ if (delta > 0x80000000)
+ {
+ if (!cpustate->timer_int_pending)
+ cpustate->timer->adjust(attotime::zero);
+ }
+ else
+ {
+ UINT64 clocks_until_int = mulu_32x32(delta, cpustate->tr_clocks_per_tick);
+ UINT64 cycles_until_int = (clocks_until_int << cpustate->clock_scale) + cycles_until_next_clock;
+ cpustate->timer->adjust(cpustate->device->cycles_to_attotime(cycles_until_int));
+ }
+ }
+
+ /* otherwise, disable the timer */
+ else
+ cpustate->timer->adjust(attotime::never);
+}
+
+static TIMER_CALLBACK( e132xs_timer_callback )
+{
+ legacy_cpu_device *device = (legacy_cpu_device *)ptr;
+ hyperstone_state *cpustate = get_safe_token(device);
+ int update = param;
+
+ /* update the values if necessary */
+ if (update)
+ update_timer_prescale(cpustate);
+
+ /* see if the timer is right for firing */
+ if (!((compute_tr(cpustate) - TCR) & 0x80000000))
+ cpustate->timer_int_pending = 1;
+
+ /* adjust ourselves for the next time */
+ else
+ adjust_timer_interrupt(cpustate);
+}
+
+
+
+
+static UINT32 get_global_register(hyperstone_state *cpustate, UINT8 code)
+{
+/*
+ if( code >= 16 )
+ {
+ switch( code )
+ {
+ case 16:
+ case 17:
+ case 28:
+ case 29:
+ case 30:
+ case 31:
+ DEBUG_PRINTF(("read _Reserved_ Global Register %d @ %08X\n",code,PC));
+ break;
+
+ case BCR_REGISTER:
+ DEBUG_PRINTF(("read write-only BCR register @ %08X\n",PC));
+ return 0;
+
+ case TPR_REGISTER:
+ DEBUG_PRINTF(("read write-only TPR register @ %08X\n",PC));
+ return 0;
+
+ case FCR_REGISTER:
+ DEBUG_PRINTF(("read write-only FCR register @ %08X\n",PC));
+ return 0;
+
+ case MCR_REGISTER:
+ DEBUG_PRINTF(("read write-only MCR register @ %08X\n",PC));
+ return 0;
+ }
+ }
+*/
+ if (code == TR_REGISTER)
+ {
+ /* it is common to poll this in a loop */
+ if (cpustate->icount > cpustate->tr_clocks_per_tick / 2)
+ cpustate->icount -= cpustate->tr_clocks_per_tick / 2;
+ return compute_tr(cpustate);
+ }
+ return cpustate->global_regs[code];
+}
+
+INLINE void set_global_register(hyperstone_state *cpustate, UINT8 code, UINT32 val)
+{
+ //TODO: add correct FER set instruction
+
+ if( code == PC_REGISTER )
+ {
+ SET_PC(val);
+ }
+ else if( code == SR_REGISTER )
+ {
+ SET_LOW_SR(val); // only a RET instruction can change the full content of SR
+ SR &= ~0x40; //reserved bit 6 always zero
+ if (cpustate->intblock < 1)
+ cpustate->intblock = 1;
+ }
+ else
+ {
+ UINT32 oldval = cpustate->global_regs[code];
+ if( code != ISR_REGISTER )
+ cpustate->global_regs[code] = val;
+ else
+ DEBUG_PRINTF(("Written to ISR register. PC = %08X\n", PC));
+
+ //are these set only when privilege bit is set?
+ if( code >= 16 )
+ {
+ switch( code )
+ {
+ case 18:
+ SET_SP(val);
+ break;
+
+ case 19:
+ SET_UB(val);
+ break;
+/*
+ case ISR_REGISTER:
+ DEBUG_PRINTF(("written %08X to read-only ISR register\n",val));
+ break;
+
+ case TCR_REGISTER:
+// DEBUG_PRINTF(("written %08X to TCR register\n",val));
+ break;
+
+ case 23:
+// DEBUG_PRINTF(("written %08X to TR register\n",val));
+ break;
+
+ case 24:
+// DEBUG_PRINTF(("written %08X to WCR register\n",val));
+ break;
+
+ case 16:
+ case 17:
+ case 28:
+ case 29:
+ case 30:
+ case 31:
+ DEBUG_PRINTF(("written %08X to _Reserved_ Global Register %d\n",val,code));
+ break;
+
+ case BCR_REGISTER:
+ break;
+*/
+ case TR_REGISTER:
+ cpustate->tr_base_value = val;
+ cpustate->tr_base_cycles = cpustate->device->total_cycles();
+ adjust_timer_interrupt(cpustate);
+ break;
+
+ case TPR_REGISTER:
+ if (!(val & 0x80000000)) /* change immediately */
+ update_timer_prescale(cpustate);
+ adjust_timer_interrupt(cpustate);
+ break;
+
+ case TCR_REGISTER:
+ if (oldval != val)
+ {
+ adjust_timer_interrupt(cpustate);
+ if (cpustate->intblock < 1)
+ cpustate->intblock = 1;
+ }
+ break;
+
+ case FCR_REGISTER:
+ if ((oldval ^ val) & 0x00800000)
+ adjust_timer_interrupt(cpustate);
+ if (cpustate->intblock < 1)
+ cpustate->intblock = 1;
+ break;
+
+ case MCR_REGISTER:
+ // bits 14..12 EntryTableMap
+ hyperstone_set_trap_entry(cpustate, (val & 0x7000) >> 12);
+ break;
+ }
+ }
+ }
+}
+
+INLINE void set_local_register(hyperstone_state *cpustate, UINT8 code, UINT32 val)
+{
+ UINT8 new_code = (code + GET_FP) % 64;
+
+ cpustate->local_regs[new_code] = val;
+}
+
+#define GET_ABS_L_REG(code) cpustate->local_regs[code]
+#define SET_L_REG(code, val) set_local_register(cpustate, code, val)
+#define SET_ABS_L_REG(code, val) cpustate->local_regs[code] = val
+#define GET_G_REG(code) get_global_register(cpustate, code)
+#define SET_G_REG(code, val) set_global_register(cpustate, code, val)
+
+#define S_BIT ((OP & 0x100) >> 8)
+#define N_BIT S_BIT
+#define D_BIT ((OP & 0x200) >> 9)
+#define N_VALUE ((N_BIT << 4) | (OP & 0x0f))
+#define DST_CODE ((OP & 0xf0) >> 4)
+#define SRC_CODE (OP & 0x0f)
+#define SIGN_BIT(val) ((val & 0x80000000) >> 31)
+
+#define LOCAL 1
+
+static const INT32 immediate_values[32] =
+{
+ 0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 0, 0, 0, 32, 64, 128, 0x80000000,
+ -8, -7, -6, -5, -4, -3, -2, -1
+};
+
+#define WRITE_ONLY_REGMASK ((1 << BCR_REGISTER) | (1 << TPR_REGISTER) | (1 << FCR_REGISTER) | (1 << MCR_REGISTER))
+
+#define decode_source(decode, local, hflag) \
+do \
+{ \
+ if(local) \
+ { \
+ UINT8 code = (decode)->src; \
+ (decode)->src_is_local = 1; \
+ code = ((decode)->src + GET_FP) % 64; /* registers offset by frame pointer */\
+ SREG = cpustate->local_regs[code]; \
+ code = ((decode)->src + 1 + GET_FP) % 64; \
+ SREGF = cpustate->local_regs[code]; \
+ } \
+ else \
+ { \
+ (decode)->src_is_local = 0; \
+ \
+ if (!hflag) \
+ { \
+ SREG = get_global_register(cpustate, (decode)->src); \
+ \
+ /* bound safe */ \
+ if ((decode)->src != 15) \
+ SREGF = get_global_register(cpustate, (decode)->src + 1); \
+ } \
+ else \
+ { \
+ (decode)->src += 16; \
+ \
+ SREG = get_global_register(cpustate, (decode)->src); \
+ if ((WRITE_ONLY_REGMASK >> (decode)->src) & 1) \
+ SREG = 0; /* write-only registers */ \
+ else if ((decode)->src == ISR_REGISTER) \
+ DEBUG_PRINTF(("read src ISR. PC = %08X\n",PPC)); \
+ \
+ /* bound safe */ \
+ if ((decode)->src != 31) \
+ SREGF = get_global_register(cpustate, (decode)->src + 1); \
+ } \
+ } \
+} while (0)
+
+#define decode_dest(decode, local, hflag) \
+do \
+{ \
+ if(local) \
+ { \
+ UINT8 code = (decode)->dst; \
+ (decode)->dst_is_local = 1; \
+ code = ((decode)->dst + GET_FP) % 64; /* registers offset by frame pointer */\
+ DREG = cpustate->local_regs[code]; \
+ code = ((decode)->dst + 1 + GET_FP) % 64; \
+ DREGF = cpustate->local_regs[code]; \
+ } \
+ else \
+ { \
+ (decode)->dst_is_local = 0; \
+ \
+ if (!hflag) \
+ { \
+ DREG = get_global_register(cpustate, (decode)->dst); \
+ \
+ /* bound safe */ \
+ if ((decode)->dst != 15) \
+ DREGF = get_global_register(cpustate, (decode)->dst + 1); \
+ } \
+ else \
+ { \
+ (decode)->dst += 16; \
+ \
+ DREG = get_global_register(cpustate, (decode)->dst); \
+ if( (decode)->dst == ISR_REGISTER ) \
+ DEBUG_PRINTF(("read dst ISR. PC = %08X\n",PPC)); \
+ \
+ /* bound safe */ \
+ if ((decode)->dst != 31) \
+ DREGF = get_global_register(cpustate, (decode)->dst + 1); \
+ } \
+ } \
+} while (0)
+
+#define decode_RR(decode, dlocal, slocal) \
+do \
+{ \
+ (decode)->src = SRC_CODE; \
+ (decode)->dst = DST_CODE; \
+ decode_source(decode, slocal, 0); \
+ decode_dest(decode, dlocal, 0); \
+ \
+ if( (slocal) == (dlocal) && SRC_CODE == DST_CODE ) \
+ SAME_SRC_DST = 1; \
+ \
+ if( (slocal) == LOCAL && (dlocal) == LOCAL ) \
+ { \
+ if( SRC_CODE == ((DST_CODE + 1) % 64) ) \
+ SAME_SRC_DSTF = 1; \
+ \
+ if( ((SRC_CODE + 1) % 64) == DST_CODE ) \
+ SAME_SRCF_DST = 1; \
+ } \
+ else if( (slocal) == 0 && (dlocal) == 0 ) \
+ { \
+ if( SRC_CODE == (DST_CODE + 1) ) \
+ SAME_SRC_DSTF = 1; \
+ \
+ if( (SRC_CODE + 1) == DST_CODE ) \
+ SAME_SRCF_DST = 1; \
+ } \
+} while (0)
+
+#define decode_LL(decode) \
+do \
+{ \
+ (decode)->src = SRC_CODE; \
+ (decode)->dst = DST_CODE; \
+ decode_source(decode, LOCAL, 0); \
+ decode_dest(decode, LOCAL, 0); \
+ \
+ if( SRC_CODE == DST_CODE ) \
+ SAME_SRC_DST = 1; \
+ \
+ if( SRC_CODE == ((DST_CODE + 1) % 64) ) \
+ SAME_SRC_DSTF = 1; \
+} while (0)
+
+#define decode_LR(decode, slocal) \
+do \
+{ \
+ (decode)->src = SRC_CODE; \
+ (decode)->dst = DST_CODE; \
+ decode_source(decode, slocal, 0); \
+ decode_dest(decode, LOCAL, 0); \
+ \
+ if( ((SRC_CODE + 1) % 64) == DST_CODE && slocal == LOCAL ) \
+ SAME_SRCF_DST = 1; \
+} while (0)
+
+#define check_delay_PC() \
+do \
+{ \
+ /* if PC is used in a delay instruction, the delayed PC should be used */ \
+ if( cpustate->delay.delay_cmd == DELAY_EXECUTE ) \
+ { \
+ PC = cpustate->delay.delay_pc; \
+ cpustate->delay.delay_cmd = NO_DELAY; \
+ } \
+} while (0)
+
+#define decode_immediate(decode, nbit) \
+do \
+{ \
+ if (!nbit) \
+ EXTRA_U = immediate_values[OP & 0x0f]; \
+ else \
+ switch( OP & 0x0f ) \
+ { \
+ default: \
+ EXTRA_U = immediate_values[0x10 + (OP & 0x0f)]; \
+ break; \
+ \
+ case 1: \
+ cpustate->instruction_length = 3; \
+ EXTRA_U = (READ_OP(cpustate, PC) << 16) | READ_OP(cpustate, PC + 2);\
+ PC += 4; \
+ break; \
+ \
+ case 2: \
+ cpustate->instruction_length = 2; \
+ EXTRA_U = READ_OP(cpustate, PC); \
+ PC += 2; \
+ break; \
+ \
+ case 3: \
+ cpustate->instruction_length = 2; \
+ EXTRA_U = 0xffff0000 | READ_OP(cpustate, PC); \
+ PC += 2; \
+ break; \
+ } \
+} while (0)
+
+#define decode_const(decode) \
+do \
+{ \
+ UINT16 imm_1 = READ_OP(cpustate, PC); \
+ \
+ PC += 2; \
+ cpustate->instruction_length = 2; \
+ \
+ if( E_BIT(imm_1) ) \
+ { \
+ UINT16 imm_2 = READ_OP(cpustate, PC); \
+ \
+ PC += 2; \
+ cpustate->instruction_length = 3; \
+ \
+ EXTRA_S = imm_2; \
+ EXTRA_S |= ((imm_1 & 0x3fff) << 16); \
+ \
+ if( S_BIT_CONST(imm_1) ) \
+ { \
+ EXTRA_S |= 0xc0000000; \
+ } \
+ } \
+ else \
+ { \
+ EXTRA_S = imm_1 & 0x3fff; \
+ \
+ if( S_BIT_CONST(imm_1) ) \
+ { \
+ EXTRA_S |= 0xffffc000; \
+ } \
+ } \
+} while (0)
+
+#define decode_pcrel(decode) \
+do \
+{ \
+ if( OP & 0x80 ) \
+ { \
+ UINT16 next = READ_OP(cpustate, PC); \
+ \
+ PC += 2; \
+ cpustate->instruction_length = 2; \
+ \
+ EXTRA_S = (OP & 0x7f) << 16; \
+ EXTRA_S |= (next & 0xfffe); \
+ \
+ if( next & 1 ) \
+ EXTRA_S |= 0xff800000; \
+ } \
+ else \
+ { \
+ EXTRA_S = OP & 0x7e; \
+ \
+ if( OP & 1 ) \
+ EXTRA_S |= 0xffffff80; \
+ } \
+} while (0)
+
+#define decode_dis(decode) \
+do \
+{ \
+ UINT16 next_1 = READ_OP(cpustate, PC); \
+ \
+ PC += 2; \
+ cpustate->instruction_length = 2; \
+ \
+ (decode)->sub_type = DD(next_1); \
+ \
+ if( E_BIT(next_1) ) \
+ { \
+ UINT16 next_2 = READ_OP(cpustate, PC); \
+ \
+ PC += 2; \
+ cpustate->instruction_length = 3; \
+ \
+ EXTRA_S = next_2; \
+ EXTRA_S |= ((next_1 & 0xfff) << 16); \
+ \
+ if( S_BIT_CONST(next_1) ) \
+ { \
+ EXTRA_S |= 0xf0000000; \
+ } \
+ } \
+ else \
+ { \
+ EXTRA_S = next_1 & 0xfff; \
+ \
+ if( S_BIT_CONST(next_1) ) \
+ { \
+ EXTRA_S |= 0xfffff000; \
+ } \
+ } \
+} while (0)
+
+#define decode_lim(decode) \
+do \
+{ \
+ UINT32 next = READ_OP(cpustate, PC); \
+ PC += 2; \
+ cpustate->instruction_length = 2; \
+ \
+ (decode)->sub_type = X_CODE(next); \
+ \
+ if( E_BIT(next) ) \
+ { \
+ EXTRA_U = ((next & 0xfff) << 16) | READ_OP(cpustate, PC); \
+ PC += 2; \
+ cpustate->instruction_length = 3; \
+ } \
+ else \
+ { \
+ EXTRA_U = next & 0xfff; \
+ } \
+} while (0)
+
+#define RRdecode(decode, dlocal, slocal) \
+do \
+{ \
+ check_delay_PC(); \
+ decode_RR(decode, dlocal, slocal); \
+} while (0)
+
+#define RRlimdecode(decode, dlocal, slocal) \
+do \
+{ \
+ decode_lim(decode); \
+ check_delay_PC(); \
+ decode_RR(decode, dlocal, slocal); \
+} while (0)
+
+#define RRconstdecode(decode, dlocal, slocal) \
+do \
+{ \
+ decode_const(decode); \
+ check_delay_PC(); \
+ decode_RR(decode, dlocal, slocal); \
+} while (0)
+
+#define RRdisdecode(decode, dlocal, slocal) \
+do \
+{ \
+ decode_dis(decode); \
+ check_delay_PC(); \
+ decode_RR(decode, dlocal, slocal); \
+} while (0)
+
+#define RRdecodewithHflag(decode, dlocal, slocal) \
+do \
+{ \
+ check_delay_PC(); \
+ (decode)->src = SRC_CODE; \
+ (decode)->dst = DST_CODE; \
+ decode_source(decode, slocal, GET_H); \
+ decode_dest(decode, dlocal, GET_H); \
+ \
+ if(GET_H) \
+ if(slocal == 0 && dlocal == 0) \
+ DEBUG_PRINTF(("MOV with hflag and 2 GRegs! PC = %08X\n",PPC)); \
+} while (0)
+
+#define Rimmdecode(decode, dlocal, nbit) \
+do \
+{ \
+ decode_immediate(decode, nbit); \
+ check_delay_PC(); \
+ (decode)->dst = DST_CODE; \
+ decode_dest(decode, dlocal, 0); \
+} while (0)
+
+#define Rndecode(decode, dlocal) \
+do \
+{ \
+ check_delay_PC(); \
+ (decode)->dst = DST_CODE; \
+ decode_dest(decode, dlocal, 0); \
+} while (0)
+
+#define RimmdecodewithHflag(decode, dlocal, nbit) \
+do \
+{ \
+ decode_immediate(decode, nbit); \
+ check_delay_PC(); \
+ (decode)->dst = DST_CODE; \
+ decode_dest(decode, dlocal, GET_H); \
+} while (0)
+
+#define Lndecode(decode) \
+do \
+{ \
+ check_delay_PC(); \
+ (decode)->dst = DST_CODE; \
+ decode_dest(decode, LOCAL, 0); \
+} while (0)
+
+#define LLdecode(decode) \
+do \
+{ \
+ check_delay_PC(); \
+ decode_LL(decode); \
+} while (0)
+
+#define LLextdecode(decode) \
+do \
+{ \
+ cpustate->instruction_length = 2; \
+ EXTRA_U = READ_OP(cpustate, PC); \
+ PC += 2; \
+ check_delay_PC(); \
+ decode_LL(decode); \
+} while (0)
+
+#define LRdecode(decode, slocal) \
+do \
+{ \
+ check_delay_PC(); \
+ decode_LR(decode, slocal); \
+} while (0)
+
+#define LRconstdecode(decode, slocal) \
+do \
+{ \
+ decode_const(decode); \
+ check_delay_PC(); \
+ decode_LR(decode, slocal); \
+} while (0)
+
+#define PCreldecode(decode) \
+do \
+{ \
+ decode_pcrel(decode); \
+ check_delay_PC(); \
+} while (0)
+
+#define PCadrdecode(decode) \
+do \
+{ \
+ check_delay_PC(); \
+} while (0)
+
+#define no_decode(decode) \
+do \
+{ \
+} while (0)
+
+
+INLINE void execute_br(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ PPC = PC;
+ PC += EXTRA_S;
+ SET_M(0);
+
+ cpustate->icount -= cpustate->clock_cycles_2;
+}
+
+INLINE void execute_dbr(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ cpustate->delay.delay_cmd = DELAY_EXECUTE;
+ cpustate->delay.delay_pc = PC + EXTRA_S;
+
+ cpustate->intblock = 3;
+}
+
+
+static void execute_trap(hyperstone_state *cpustate, UINT32 addr)
+{
+ UINT8 reg;
+ UINT32 oldSR;
+ reg = GET_FP + GET_FL;
+
+ SET_ILC(cpustate->instruction_length & 3);
+
+ oldSR = SR;
+
+ SET_FL(6);
+ SET_FP(reg);
+
+ SET_L_REG(0, (PC & 0xfffffffe) | GET_S);
+ SET_L_REG(1, oldSR);
+
+ SET_M(0);
+ SET_T(0);
+ SET_L(1);
+ SET_S(1);
+
+ PPC = PC;
+ PC = addr;
+
+ cpustate->icount -= cpustate->clock_cycles_2;
+}
+
+
+static void execute_int(hyperstone_state *cpustate, UINT32 addr)
+{
+ UINT8 reg;
+ UINT32 oldSR;
+ reg = GET_FP + GET_FL;
+
+ SET_ILC(cpustate->instruction_length & 3);
+
+ oldSR = SR;
+
+ SET_FL(2);
+ SET_FP(reg);
+
+ SET_L_REG(0, (PC & 0xfffffffe) | GET_S);
+ SET_L_REG(1, oldSR);
+
+ SET_M(0);
+ SET_T(0);
+ SET_L(1);
+ SET_S(1);
+ SET_I(1);
+
+ PPC = PC;
+ PC = addr;
+
+ cpustate->icount -= cpustate->clock_cycles_2;
+}
+
+/* TODO: mask Parity Error and Extended Overflow exceptions */
+static void execute_exception(hyperstone_state *cpustate, UINT32 addr)
+{
+ UINT8 reg;
+ UINT32 oldSR;
+ reg = GET_FP + GET_FL;
+
+ SET_ILC(cpustate->instruction_length & 3);
+
+ oldSR = SR;
+
+ SET_FP(reg);
+ SET_FL(2);
+
+ SET_L_REG(0, (PC & 0xfffffffe) | GET_S);
+ SET_L_REG(1, oldSR);
+
+ SET_M(0);
+ SET_T(0);
+ SET_L(1);
+ SET_S(1);
+
+ PPC = PC;
+ PC = addr;
+
+ DEBUG_PRINTF(("EXCEPTION! PPC = %08X PC = %08X\n",PPC-2,PC-2));
+ cpustate->icount -= cpustate->clock_cycles_2;
+}
+
+static void execute_software(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ UINT8 reg;
+ UINT32 oldSR;
+ UINT32 addr;
+ UINT32 stack_of_dst;
+
+ SET_ILC(1);
+
+ addr = get_emu_code_addr(cpustate, (OP & 0xff00) >> 8);
+ reg = GET_FP + GET_FL;
+
+ //since it's sure the register is in the register part of the stack,
+ //set the stack address to a value above the highest address
+ //that can be set by a following frame instruction
+ stack_of_dst = (SP & ~0xff) + 64*4 + (((GET_FP + decode->dst) % 64) * 4); //converted to 32bits offset
+
+ oldSR = SR;
+
+ SET_FL(6);
+ SET_FP(reg);
+
+ SET_L_REG(0, stack_of_dst);
+ SET_L_REG(1, SREG);
+ SET_L_REG(2, SREGF);
+ SET_L_REG(3, (PC & 0xfffffffe) | GET_S);
+ SET_L_REG(4, oldSR);
+
+ SET_M(0);
+ SET_T(0);
+ SET_L(1);
+
+ PPC = PC;
+ PC = addr;
+}
+
+
+/*
+ IRQ lines :
+ 0 - IO2 (trap 48)
+ 1 - IO1 (trap 49)
+ 2 - INT4 (trap 50)
+ 3 - INT3 (trap 51)
+ 4 - INT2 (trap 52)
+ 5 - INT1 (trap 53)
+ 6 - IO3 (trap 54)
+ 7 - TIMER (trap 55)
+*/
+
+#define INT1_LINE_STATE ((ISR >> 0) & 1)
+#define INT2_LINE_STATE ((ISR >> 1) & 1)
+#define INT3_LINE_STATE ((ISR >> 2) & 1)
+#define INT4_LINE_STATE ((ISR >> 3) & 1)
+#define IO1_LINE_STATE ((ISR >> 4) & 1)
+#define IO2_LINE_STATE ((ISR >> 5) & 1)
+#define IO3_LINE_STATE ((ISR >> 6) & 1)
+
+static void check_interrupts(hyperstone_state *cpustate)
+{
+ /* Interrupt-Lock flag isn't set */
+ if (GET_L || cpustate->intblock > 0)
+ return;
+
+ /* quick exit if nothing */
+ if (!cpustate->timer_int_pending && (ISR & 0x7f) == 0)
+ return;
+
+ /* IO3 is priority 5; state is in bit 6 of ISR; FCR bit 10 enables input and FCR bit 8 inhibits interrupt */
+ if (IO3_LINE_STATE && (FCR & 0x00000500) == 0x00000400)
+ {
+ execute_int(cpustate, get_trap_addr(cpustate, TRAPNO_IO3));
+ (*cpustate->irq_callback)(cpustate->device, IRQ_IO3);
+ return;
+ }
+
+ /* timer int might be priority 6 if FCR bits 20-21 == 3; FCR bit 23 inhibits interrupt */
+ if (cpustate->timer_int_pending && (FCR & 0x00b00000) == 0x00300000)
+ {
+ cpustate->timer_int_pending = 0;
+ execute_int(cpustate, get_trap_addr(cpustate, TRAPNO_TIMER));
+ return;
+ }
+
+ /* INT1 is priority 7; state is in bit 0 of ISR; FCR bit 28 inhibits interrupt */
+ if (INT1_LINE_STATE && (FCR & 0x10000000) == 0x00000000)
+ {
+ execute_int(cpustate, get_trap_addr(cpustate, TRAPNO_INT1));
+ (*cpustate->irq_callback)(cpustate->device, IRQ_INT1);
+ return;
+ }
+
+ /* timer int might be priority 8 if FCR bits 20-21 == 2; FCR bit 23 inhibits interrupt */
+ if (cpustate->timer_int_pending && (FCR & 0x00b00000) == 0x00200000)
+ {
+ cpustate->timer_int_pending = 0;
+ execute_int(cpustate, get_trap_addr(cpustate, TRAPNO_TIMER));
+ return;
+ }
+
+ /* INT2 is priority 9; state is in bit 1 of ISR; FCR bit 29 inhibits interrupt */
+ if (INT2_LINE_STATE && (FCR & 0x20000000) == 0x00000000)
+ {
+ execute_int(cpustate, get_trap_addr(cpustate, TRAPNO_INT2));
+ (*cpustate->irq_callback)(cpustate->device, IRQ_INT2);
+ return;
+ }
+
+ /* timer int might be priority 10 if FCR bits 20-21 == 1; FCR bit 23 inhibits interrupt */
+ if (cpustate->timer_int_pending && (FCR & 0x00b00000) == 0x00100000)
+ {
+ cpustate->timer_int_pending = 0;
+ execute_int(cpustate, get_trap_addr(cpustate, TRAPNO_TIMER));
+ return;
+ }
+
+ /* INT3 is priority 11; state is in bit 2 of ISR; FCR bit 30 inhibits interrupt */
+ if (INT3_LINE_STATE && (FCR & 0x40000000) == 0x00000000)
+ {
+ execute_int(cpustate, get_trap_addr(cpustate, TRAPNO_INT3));
+ (*cpustate->irq_callback)(cpustate->device, IRQ_INT3);
+ return;
+ }
+
+ /* timer int might be priority 12 if FCR bits 20-21 == 0; FCR bit 23 inhibits interrupt */
+ if (cpustate->timer_int_pending && (FCR & 0x00b00000) == 0x00000000)
+ {
+ cpustate->timer_int_pending = 0;
+ execute_int(cpustate, get_trap_addr(cpustate, TRAPNO_TIMER));
+ return;
+ }
+
+ /* INT4 is priority 13; state is in bit 3 of ISR; FCR bit 31 inhibits interrupt */
+ if (INT4_LINE_STATE && (FCR & 0x80000000) == 0x00000000)
+ {
+ execute_int(cpustate, get_trap_addr(cpustate, TRAPNO_INT4));
+ (*cpustate->irq_callback)(cpustate->device, IRQ_INT4);
+ return;
+ }
+
+ /* IO1 is priority 14; state is in bit 4 of ISR; FCR bit 2 enables input and FCR bit 0 inhibits interrupt */
+ if (IO1_LINE_STATE && (FCR & 0x00000005) == 0x00000004)
+ {
+ execute_int(cpustate, get_trap_addr(cpustate, TRAPNO_IO1));
+ (*cpustate->irq_callback)(cpustate->device, IRQ_IO1);
+ return;
+ }
+
+ /* IO2 is priority 15; state is in bit 5 of ISR; FCR bit 6 enables input and FCR bit 4 inhibits interrupt */
+ if (IO2_LINE_STATE && (FCR & 0x00000050) == 0x00000040)
+ {
+ execute_int(cpustate, get_trap_addr(cpustate, TRAPNO_IO2));
+ (*cpustate->irq_callback)(cpustate->device, IRQ_IO2);
+ return;
+ }
+}
+
+static void set_irq_line(hyperstone_state *cpustate, int irqline, int state)
+{
+ if (state)
+ ISR |= 1 << irqline;
+ else
+ ISR &= ~(1 << irqline);
+}
+
+static void hyperstone_init(legacy_cpu_device *device, device_irq_callback irqcallback, int scale_mask)
+{
+ hyperstone_state *cpustate = get_safe_token(device);
+
+ device->save_item(NAME(cpustate->global_regs));
+ device->save_item(NAME(cpustate->local_regs));
+ device->save_item(NAME(cpustate->ppc));
+ device->save_item(NAME(cpustate->trap_entry));
+ device->save_item(NAME(cpustate->delay.delay_pc));
+ device->save_item(NAME(cpustate->instruction_length));
+ device->save_item(NAME(cpustate->intblock));
+ device->save_item(NAME(cpustate->delay.delay_cmd));
+ device->save_item(NAME(cpustate->tr_clocks_per_tick));
+
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+ cpustate->io = device->space(AS_IO);
+ cpustate->timer = device->machine().scheduler().timer_alloc(FUNC(e132xs_timer_callback), (void *)device);
+ cpustate->clock_scale_mask = scale_mask;
+}
+
+static void e116_init(legacy_cpu_device *device, device_irq_callback irqcallback, int scale_mask)
+{
+ hyperstone_state *cpustate = get_safe_token(device);
+ hyperstone_init(device, irqcallback, scale_mask);
+ cpustate->opcodexor = 0;
+}
+
+static CPU_INIT( e116t )
+{
+ e116_init(device, irqcallback, 0);
+}
+
+static CPU_INIT( e116xt )
+{
+ e116_init(device, irqcallback, 3);
+}
+
+static CPU_INIT( e116xs )
+{
+ e116_init(device, irqcallback, 7);
+}
+
+static CPU_INIT( e116xsr )
+{
+ e116_init(device, irqcallback, 7);
+}
+
+static CPU_INIT( gms30c2116 )
+{
+ e116_init(device, irqcallback, 0);
+}
+
+static CPU_INIT( gms30c2216 )
+{
+ e116_init(device, irqcallback, 0);
+}
+
+static void e132_init(legacy_cpu_device *device, device_irq_callback irqcallback, int scale_mask)
+{
+ hyperstone_state *cpustate = get_safe_token(device);
+ hyperstone_init(device, irqcallback, scale_mask);
+ cpustate->opcodexor = WORD_XOR_BE(0);
+}
+
+static CPU_INIT( e132n )
+{
+ e132_init(device, irqcallback, 0);
+}
+
+static CPU_INIT( e132t )
+{
+ e132_init(device, irqcallback, 0);
+}
+
+static CPU_INIT( e132xn )
+{
+ e132_init(device, irqcallback, 3);
+}
+
+static CPU_INIT( e132xt )
+{
+ e132_init(device, irqcallback, 3);
+}
+
+static CPU_INIT( e132xs )
+{
+ e132_init(device, irqcallback, 7);
+}
+
+static CPU_INIT( e132xsr )
+{
+ e132_init(device, irqcallback, 7);
+}
+
+static CPU_INIT( gms30c2132 )
+{
+ e132_init(device, irqcallback, 0);
+}
+
+static CPU_INIT( gms30c2232 )
+{
+ e132_init(device, irqcallback, 0);
+}
+
+static CPU_RESET( hyperstone )
+{
+ hyperstone_state *cpustate = get_safe_token(device);
+
+ //TODO: Add different reset initializations for BCR, MCR, FCR, TPR
+
+ emu_timer *save_timer;
+ device_irq_callback save_irqcallback;
+ UINT32 save_opcodexor;
+
+ save_timer = cpustate->timer;
+ save_irqcallback = cpustate->irq_callback;
+ save_opcodexor = cpustate->opcodexor;
+ memset(cpustate, 0, sizeof(*cpustate));
+ cpustate->irq_callback = save_irqcallback;
+ cpustate->opcodexor = save_opcodexor;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+ cpustate->io = device->space(AS_IO);
+ cpustate->timer = save_timer;
+
+ cpustate->tr_clocks_per_tick = 2;
+
+ hyperstone_set_trap_entry(cpustate, E132XS_ENTRY_MEM3); /* default entry point @ MEM3 */
+
+ set_global_register(cpustate, BCR_REGISTER, ~0);
+ set_global_register(cpustate, MCR_REGISTER, ~0);
+ set_global_register(cpustate, FCR_REGISTER, ~0);
+ set_global_register(cpustate, TPR_REGISTER, 0xc000000);
+
+ PC = get_trap_addr(cpustate, TRAPNO_RESET);
+
+ SET_FP(0);
+ SET_FL(2);
+
+ SET_M(0);
+ SET_T(0);
+ SET_L(1);
+ SET_S(1);
+
+ SET_L_REG(0, (PC & 0xfffffffe) | GET_S);
+ SET_L_REG(1, SR);
+
+ cpustate->icount -= cpustate->clock_cycles_2;
+}
+
+static CPU_EXIT( hyperstone )
+{
+ // nothing to do
+}
+
+static CPU_DISASSEMBLE( hyperstone )
+{
+ hyperstone_state *cpustate = get_safe_token(device);
+ return dasm_hyperstone( buffer, pc, oprom, GET_H, GET_FP );
+}
+
+/* Opcodes */
+
+INLINE void hyperstone_chk(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ UINT32 addr = get_trap_addr(cpustate, TRAPNO_RANGE_ERROR);
+
+ if( SRC_IS_SR )
+ {
+ if( DREG == 0 )
+ execute_exception(cpustate, addr);
+ }
+ else
+ {
+ if( SRC_IS_PC )
+ {
+ if( DREG >= SREG )
+ execute_exception(cpustate, addr);
+ }
+ else
+ {
+ if( DREG > SREG )
+ execute_exception(cpustate, addr);
+ }
+ }
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_movd(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ if( DST_IS_PC ) // Rd denotes PC
+ {
+ // RET instruction
+
+ UINT8 old_s, old_l;
+ INT8 difference; // really it's 7 bits
+
+ if( SRC_IS_PC || SRC_IS_SR )
+ {
+ DEBUG_PRINTF(("Denoted PC or SR in RET instruction. PC = %08X\n", PC));
+ }
+ else
+ {
+ old_s = GET_S;
+ old_l = GET_L;
+ PPC = PC;
+
+ SET_PC(SREG);
+ SR = (SREGF & 0xffe00000) | ((SREG & 0x01) << 18 ) | (SREGF & 0x3ffff);
+ if (cpustate->intblock < 1)
+ cpustate->intblock = 1;
+
+ cpustate->instruction_length = 0; // undefined
+
+ if( (!old_s && GET_S) || (!GET_S && !old_l && GET_L))
+ {
+ UINT32 addr = get_trap_addr(cpustate, TRAPNO_PRIVILEGE_ERROR);
+ execute_exception(cpustate, addr);
+ }
+
+ difference = GET_FP - ((SP & 0x1fc) >> 2);
+
+ /* convert to 8 bits */
+ if(difference > 63)
+ difference = (INT8)(difference|0x80);
+ else if( difference < -64 )
+ difference = difference & 0x7f;
+
+ if( difference < 0 ) //else it's finished
+ {
+ do
+ {
+ SP -= 4;
+ SET_ABS_L_REG(((SP & 0xfc) >> 2), READ_W(cpustate, SP));
+ difference++;
+
+ } while(difference != 0);
+ }
+ }
+
+ //TODO: no 1!
+ cpustate->icount -= cpustate->clock_cycles_1;
+ }
+ else if( SRC_IS_SR ) // Rd doesn't denote PC and Rs denotes SR
+ {
+ SET_DREG(0);
+ SET_DREGF(0);
+ SET_Z(1);
+ SET_N(0);
+
+ cpustate->icount -= cpustate->clock_cycles_2;
+ }
+ else // Rd doesn't denote PC and Rs doesn't denote SR
+ {
+ UINT64 tmp;
+
+ SET_DREG(SREG);
+ SET_DREGF(SREGF);
+
+ tmp = CONCAT_64(SREG, SREGF);
+ SET_Z( tmp == 0 ? 1 : 0 );
+ SET_N( SIGN_BIT(SREG) );
+
+ cpustate->icount -= cpustate->clock_cycles_2;
+ }
+}
+
+INLINE void hyperstone_divu(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ if( SAME_SRC_DST || SAME_SRC_DSTF )
+ {
+ DEBUG_PRINTF(("Denoted the same register code in hyperstone_divu instruction. PC = %08X\n", PC));
+ }
+ else
+ {
+ if( SRC_IS_PC || SRC_IS_SR )
+ {
+ DEBUG_PRINTF(("Denoted PC or SR as source register in hyperstone_divu instruction. PC = %08X\n", PC));
+ }
+ else
+ {
+ UINT64 dividend;
+
+ dividend = CONCAT_64(DREG, DREGF);
+
+ if( SREG == 0 )
+ {
+ //Rd//Rdf -> undefined
+ //Z -> undefined
+ //N -> undefined
+ UINT32 addr;
+ SET_V(1);
+ addr = get_trap_addr(cpustate, TRAPNO_RANGE_ERROR);
+ execute_exception(cpustate, addr);
+ }
+ else
+ {
+ UINT32 quotient, remainder;
+
+ /* TODO: add quotient overflow */
+ quotient = dividend / SREG;
+ remainder = dividend % SREG;
+
+ SET_DREG(remainder);
+ SET_DREGF(quotient);
+
+ SET_Z( quotient == 0 ? 1 : 0 );
+ SET_N( SIGN_BIT(quotient) );
+ SET_V(0);
+ }
+ }
+ }
+
+ cpustate->icount -= 36 << cpustate->clock_scale;
+}
+
+INLINE void hyperstone_divs(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ if( SAME_SRC_DST || SAME_SRC_DSTF )
+ {
+ DEBUG_PRINTF(("Denoted the same register code in hyperstone_divs instruction. PC = %08X\n", PC));
+ }
+ else
+ {
+ if( SRC_IS_PC || SRC_IS_SR )
+ {
+ DEBUG_PRINTF(("Denoted PC or SR as source register in hyperstone_divs instruction. PC = %08X\n", PC));
+ }
+ else
+ {
+ INT64 dividend;
+
+ dividend = (INT64) CONCAT_64(DREG, DREGF);
+
+ if( SREG == 0 || (DREG & 0x80000000) )
+ {
+ //Rd//Rdf -> undefined
+ //Z -> undefined
+ //N -> undefined
+ UINT32 addr;
+ SET_V(1);
+ addr = get_trap_addr(cpustate, TRAPNO_RANGE_ERROR);
+ execute_exception(cpustate, addr);
+ }
+ else
+ {
+ INT32 quotient, remainder;
+
+ /* TODO: add quotient overflow */
+ quotient = dividend / ((INT32)(SREG));
+ remainder = dividend % ((INT32)(SREG));
+
+ SET_DREG(remainder);
+ SET_DREGF(quotient);
+
+ SET_Z( quotient == 0 ? 1 : 0 );
+ SET_N( SIGN_BIT(quotient) );
+ SET_V(0);
+ }
+ }
+ }
+
+ cpustate->icount -= 36 << cpustate->clock_scale;
+}
+
+INLINE void hyperstone_xm(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ if( SRC_IS_SR || DST_IS_SR || DST_IS_PC )
+ {
+ DEBUG_PRINTF(("Denoted PC or SR in hyperstone_xm. PC = %08X\n", PC));
+ }
+ else
+ {
+ switch( decode->sub_type ) // x_code
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ if( !SRC_IS_PC && (SREG > EXTRA_U) )
+ {
+ UINT32 addr = get_trap_addr(cpustate, TRAPNO_RANGE_ERROR);
+ execute_exception(cpustate, addr);
+ }
+ else if( SRC_IS_PC && (SREG >= EXTRA_U) )
+ {
+ UINT32 addr = get_trap_addr(cpustate, TRAPNO_RANGE_ERROR);
+ execute_exception(cpustate, addr);
+ }
+ else
+ {
+ SREG <<= decode->sub_type;
+ }
+
+ break;
+
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ decode->sub_type -= 4;
+ SREG <<= decode->sub_type;
+
+ break;
+ }
+
+ SET_DREG(SREG);
+ }
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_mask(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ DREG = SREG & EXTRA_U;
+
+ SET_DREG(DREG);
+ SET_Z( DREG == 0 ? 1 : 0 );
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_sum(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ UINT64 tmp;
+
+ if( SRC_IS_SR )
+ SREG = GET_C;
+
+ tmp = (UINT64)(SREG) + (UINT64)(EXTRA_U);
+ CHECK_C(tmp);
+ CHECK_VADD(SREG,EXTRA_U,tmp);
+
+ DREG = SREG + EXTRA_U;
+
+ SET_DREG(DREG);
+
+ if( DST_IS_PC )
+ SET_M(0);
+
+ SET_Z( DREG == 0 ? 1 : 0 );
+ SET_N( SIGN_BIT(DREG) );
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_sums(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ INT32 res;
+ INT64 tmp;
+
+ if( SRC_IS_SR )
+ SREG = GET_C;
+
+ tmp = (INT64)((INT32)(SREG)) + (INT64)(EXTRA_S);
+ CHECK_VADD(SREG,EXTRA_S,tmp);
+
+//#if SETCARRYS
+// CHECK_C(tmp);
+//#endif
+
+ res = (INT32)(SREG) + EXTRA_S;
+
+ SET_DREG(res);
+
+ SET_Z( res == 0 ? 1 : 0 );
+ SET_N( SIGN_BIT(res) );
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+
+ if( GET_V && !SRC_IS_SR )
+ {
+ UINT32 addr = get_trap_addr(cpustate, TRAPNO_RANGE_ERROR);
+ execute_exception(cpustate, addr);
+ }
+}
+
+INLINE void hyperstone_cmp(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ UINT64 tmp;
+
+ if( SRC_IS_SR )
+ SREG = GET_C;
+
+ if( DREG == SREG )
+ SET_Z(1);
+ else
+ SET_Z(0);
+
+ if( (INT32) DREG < (INT32) SREG )
+ SET_N(1);
+ else
+ SET_N(0);
+
+ tmp = (UINT64)(DREG) - (UINT64)(SREG);
+ CHECK_VSUB(SREG,DREG,tmp);
+
+ if( DREG < SREG )
+ SET_C(1);
+ else
+ SET_C(0);
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_mov(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ if( !GET_S && decode->dst >= 16 )
+ {
+ UINT32 addr = get_trap_addr(cpustate, TRAPNO_PRIVILEGE_ERROR);
+ execute_exception(cpustate, addr);
+ }
+
+ SET_DREG(SREG);
+
+ if( DST_IS_PC )
+ SET_M(0);
+
+ SET_Z( SREG == 0 ? 1 : 0 );
+ SET_N( SIGN_BIT(SREG) );
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+
+INLINE void hyperstone_add(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ UINT64 tmp;
+
+ if( SRC_IS_SR )
+ SREG = GET_C;
+
+ tmp = (UINT64)(SREG) + (UINT64)(DREG);
+ CHECK_C(tmp);
+ CHECK_VADD(SREG,DREG,tmp);
+
+ DREG = SREG + DREG;
+ SET_DREG(DREG);
+
+ if( DST_IS_PC )
+ SET_M(0);
+
+ SET_Z( DREG == 0 ? 1 : 0 );
+ SET_N( SIGN_BIT(DREG) );
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_adds(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ INT32 res;
+ INT64 tmp;
+
+ if( SRC_IS_SR )
+ SREG = GET_C;
+
+ tmp = (INT64)((INT32)(SREG)) + (INT64)((INT32)(DREG));
+
+ CHECK_VADD(SREG,DREG,tmp);
+
+//#if SETCARRYS
+// CHECK_C(tmp);
+//#endif
+
+ res = (INT32)(SREG) + (INT32)(DREG);
+
+ SET_DREG(res);
+ SET_Z( res == 0 ? 1 : 0 );
+ SET_N( SIGN_BIT(res) );
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+
+ if( GET_V )
+ {
+ UINT32 addr = get_trap_addr(cpustate, TRAPNO_RANGE_ERROR);
+ execute_exception(cpustate, addr);
+ }
+}
+
+INLINE void hyperstone_cmpb(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ SET_Z( (DREG & SREG) == 0 ? 1 : 0 );
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_andn(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ DREG = DREG & ~SREG;
+
+ SET_DREG(DREG);
+ SET_Z( DREG == 0 ? 1 : 0 );
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_or(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ DREG = DREG | SREG;
+
+ SET_DREG(DREG);
+ SET_Z( DREG == 0 ? 1 : 0 );
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_xor(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ DREG = DREG ^ SREG;
+
+ SET_DREG(DREG);
+ SET_Z( DREG == 0 ? 1 : 0 );
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_subc(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ UINT64 tmp;
+
+ if( SRC_IS_SR )
+ {
+ tmp = (UINT64)(DREG) - (UINT64)(GET_C);
+ CHECK_VSUB(GET_C,DREG,tmp);
+ }
+ else
+ {
+ tmp = (UINT64)(DREG) - ((UINT64)(SREG) + (UINT64)(GET_C));
+ //CHECK!
+ CHECK_VSUB(SREG + GET_C,DREG,tmp);
+ }
+
+
+ if( SRC_IS_SR )
+ {
+ DREG = DREG - GET_C;
+ }
+ else
+ {
+ DREG = DREG - (SREG + GET_C);
+ }
+
+ CHECK_C(tmp);
+
+ SET_DREG(DREG);
+
+ SET_Z( GET_Z & (DREG == 0 ? 1 : 0) );
+ SET_N( SIGN_BIT(DREG) );
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_not(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ SET_DREG(~SREG);
+ SET_Z( ~SREG == 0 ? 1 : 0 );
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_sub(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ UINT64 tmp;
+
+ if( SRC_IS_SR )
+ SREG = GET_C;
+
+ tmp = (UINT64)(DREG) - (UINT64)(SREG);
+ CHECK_C(tmp);
+ CHECK_VSUB(SREG,DREG,tmp);
+
+ DREG = DREG - SREG;
+ SET_DREG(DREG);
+
+ if( DST_IS_PC )
+ SET_M(0);
+
+ SET_Z( DREG == 0 ? 1 : 0 );
+ SET_N( SIGN_BIT(DREG) );
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_subs(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ INT32 res;
+ INT64 tmp;
+
+ if( SRC_IS_SR )
+ SREG = GET_C;
+
+ tmp = (INT64)((INT32)(DREG)) - (INT64)((INT32)(SREG));
+
+//#ifdef SETCARRYS
+// CHECK_C(tmp);
+//#endif
+
+ CHECK_VSUB(SREG,DREG,tmp);
+
+ res = (INT32)(DREG) - (INT32)(SREG);
+
+ SET_DREG(res);
+
+ SET_Z( res == 0 ? 1 : 0 );
+ SET_N( SIGN_BIT(res) );
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+
+ if( GET_V )
+ {
+ UINT32 addr = get_trap_addr(cpustate, TRAPNO_RANGE_ERROR);
+ execute_exception(cpustate, addr);
+ }
+}
+
+INLINE void hyperstone_addc(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ UINT64 tmp;
+
+ if( SRC_IS_SR )
+ {
+ tmp = (UINT64)(DREG) + (UINT64)(GET_C);
+ CHECK_VADD(DREG,GET_C,tmp);
+ }
+ else
+ {
+ tmp = (UINT64)(SREG) + (UINT64)(DREG) + (UINT64)(GET_C);
+
+ //CHECK!
+ //CHECK_VADD1: V = (DREG == 0x7FFF) && (C == 1);
+ //OVERFLOW = CHECK_VADD1(DREG, C, DREG+C) | CHECK_VADD(SREG, DREG+C, SREG+DREG+C)
+ /* check if DREG + GET_C overflows */
+// if( (DREG == 0x7FFFFFFF) && (GET_C == 1) )
+// SET_V(1);
+// else
+// CHECK_VADD(SREG,DREG + GET_C,tmp);
+
+ CHECK_VADD3(SREG,DREG,GET_C,tmp);
+ }
+
+
+
+ if( SRC_IS_SR )
+ DREG = DREG + GET_C;
+ else
+ DREG = SREG + DREG + GET_C;
+
+ CHECK_C(tmp);
+
+ SET_DREG(DREG);
+ SET_Z( GET_Z & (DREG == 0 ? 1 : 0) );
+ SET_N( SIGN_BIT(DREG) );
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_and(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ DREG = DREG & SREG;
+
+ SET_DREG(DREG);
+ SET_Z( DREG == 0 ? 1 : 0 );
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_neg(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ UINT64 tmp;
+
+ if( SRC_IS_SR )
+ SREG = GET_C;
+
+ tmp = -(UINT64)(SREG);
+ CHECK_C(tmp);
+ CHECK_VSUB(SREG,0,tmp);
+
+ DREG = -SREG;
+
+ SET_DREG(DREG);
+
+ SET_Z( DREG == 0 ? 1 : 0 );
+ SET_N( SIGN_BIT(DREG) );
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_negs(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ INT32 res;
+ INT64 tmp;
+
+ if( SRC_IS_SR )
+ SREG = GET_C;
+
+ tmp = -(INT64)((INT32)(SREG));
+ CHECK_VSUB(SREG,0,tmp);
+
+//#if SETCARRYS
+// CHECK_C(tmp);
+//#endif
+
+ res = -(INT32)(SREG);
+
+ SET_DREG(res);
+
+ SET_Z( res == 0 ? 1 : 0 );
+ SET_N( SIGN_BIT(res) );
+
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+
+ if( GET_V && !SRC_IS_SR ) //trap doesn't occur when source is SR
+ {
+ UINT32 addr = get_trap_addr(cpustate, TRAPNO_RANGE_ERROR);
+ execute_exception(cpustate, addr);
+ }
+}
+
+INLINE void hyperstone_cmpi(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ UINT64 tmp;
+
+ tmp = (UINT64)(DREG) - (UINT64)(EXTRA_U);
+ CHECK_VSUB(EXTRA_U,DREG,tmp);
+
+ if( DREG == EXTRA_U )
+ SET_Z(1);
+ else
+ SET_Z(0);
+
+ if( (INT32) DREG < (INT32) EXTRA_U )
+ SET_N(1);
+ else
+ SET_N(0);
+
+ if( DREG < EXTRA_U )
+ SET_C(1);
+ else
+ SET_C(0);
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_movi(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ if( !GET_S && decode->dst >= 16 )
+ {
+ UINT32 addr = get_trap_addr(cpustate, TRAPNO_PRIVILEGE_ERROR);
+ execute_exception(cpustate, addr);
+ }
+
+ SET_DREG(EXTRA_U);
+
+ if( DST_IS_PC )
+ SET_M(0);
+
+ SET_Z( EXTRA_U == 0 ? 1 : 0 );
+ SET_N( SIGN_BIT(EXTRA_U) );
+
+#if MISSIONCRAFT_FLAGS
+ SET_V(0); // or V undefined ?
+#endif
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_addi(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ UINT32 imm;
+ UINT64 tmp;
+
+ if( N_VALUE )
+ imm = EXTRA_U;
+ else
+ imm = GET_C & ((GET_Z == 0 ? 1 : 0) | (DREG & 0x01));
+
+
+ tmp = (UINT64)(imm) + (UINT64)(DREG);
+ CHECK_C(tmp);
+ CHECK_VADD(imm,DREG,tmp);
+
+ DREG = imm + DREG;
+ SET_DREG(DREG);
+
+ if( DST_IS_PC )
+ SET_M(0);
+
+ SET_Z( DREG == 0 ? 1 : 0 );
+ SET_N( SIGN_BIT(DREG) );
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_addsi(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ INT32 imm, res;
+ INT64 tmp;
+
+ if( N_VALUE )
+ imm = EXTRA_S;
+ else
+ imm = GET_C & ((GET_Z == 0 ? 1 : 0) | (DREG & 0x01));
+
+ tmp = (INT64)(imm) + (INT64)((INT32)(DREG));
+ CHECK_VADD(imm,DREG,tmp);
+
+//#if SETCARRYS
+// CHECK_C(tmp);
+//#endif
+
+ res = imm + (INT32)(DREG);
+
+ SET_DREG(res);
+
+ SET_Z( res == 0 ? 1 : 0 );
+ SET_N( SIGN_BIT(res) );
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+
+ if( GET_V )
+ {
+ UINT32 addr = get_trap_addr(cpustate, TRAPNO_RANGE_ERROR);
+ execute_exception(cpustate, addr);
+ }
+}
+
+INLINE void hyperstone_cmpbi(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ UINT32 imm;
+
+ if( N_VALUE )
+ {
+ if( N_VALUE == 31 )
+ {
+ imm = 0x7fffffff; // bit 31 = 0, others = 1
+ }
+ else
+ {
+ imm = EXTRA_U;
+ }
+
+ SET_Z( (DREG & imm) == 0 ? 1 : 0 );
+ }
+ else
+ {
+ if( (DREG & 0xff000000) == 0 || (DREG & 0x00ff0000) == 0 ||
+ (DREG & 0x0000ff00) == 0 || (DREG & 0x000000ff) == 0 )
+ SET_Z(1);
+ else
+ SET_Z(0);
+ }
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_andni(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ UINT32 imm;
+
+ if( N_VALUE == 31 )
+ imm = 0x7fffffff; // bit 31 = 0, others = 1
+ else
+ imm = EXTRA_U;
+
+ DREG = DREG & ~imm;
+
+ SET_DREG(DREG);
+ SET_Z( DREG == 0 ? 1 : 0 );
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_ori(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ DREG = DREG | EXTRA_U;
+
+ SET_DREG(DREG);
+ SET_Z( DREG == 0 ? 1 : 0 );
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_xori(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ DREG = DREG ^ EXTRA_U;
+
+ SET_DREG(DREG);
+ SET_Z( DREG == 0 ? 1 : 0 );
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_shrdi(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ UINT32 low_order, high_order;
+ UINT64 val;
+
+ high_order = DREG;
+ low_order = DREGF;
+
+ val = CONCAT_64(high_order, low_order);
+
+ if( N_VALUE )
+ SET_C((val >> (N_VALUE - 1)) & 1);
+ else
+ SET_C(0);
+
+ val >>= N_VALUE;
+
+ high_order = EXTRACT_64HI(val);
+ low_order = EXTRACT_64LO(val);
+
+ SET_DREG(high_order);
+ SET_DREGF(low_order);
+ SET_Z( val == 0 ? 1 : 0 );
+ SET_N( SIGN_BIT(high_order) );
+
+ cpustate->icount -= cpustate->clock_cycles_2;
+}
+
+INLINE void hyperstone_shrd(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ UINT32 low_order, high_order;
+ UINT64 val;
+ UINT8 n = SREG & 0x1f;
+
+ // result undefined if Ls denotes the same register as Ld or Ldf
+ if( SAME_SRC_DST || SAME_SRC_DSTF )
+ {
+ DEBUG_PRINTF(("Denoted same registers in hyperstone_shrd. PC = %08X\n", PC));
+ }
+ else
+ {
+ high_order = DREG;
+ low_order = DREGF;
+
+ val = CONCAT_64(high_order, low_order);
+
+ if( n )
+ SET_C((val >> (n - 1)) & 1);
+ else
+ SET_C(0);
+
+ val >>= n;
+
+ high_order = EXTRACT_64HI(val);
+ low_order = EXTRACT_64LO(val);
+
+ SET_DREG(high_order);
+ SET_DREGF(low_order);
+
+ SET_Z( val == 0 ? 1 : 0 );
+ SET_N( SIGN_BIT(high_order) );
+ }
+
+ cpustate->icount -= cpustate->clock_cycles_2;
+}
+
+INLINE void hyperstone_shr(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ UINT32 ret;
+ UINT8 n;
+
+ n = SREG & 0x1f;
+ ret = DREG;
+
+ if( n )
+ SET_C((ret >> (n - 1)) & 1);
+ else
+ SET_C(0);
+
+ ret >>= n;
+
+ SET_DREG(ret);
+ SET_Z( ret == 0 ? 1 : 0 );
+ SET_N( SIGN_BIT(ret) );
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_sardi(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ UINT32 low_order, high_order;
+ UINT64 val;
+ UINT8 sign_bit;
+
+ high_order = DREG;
+ low_order = DREGF;
+
+ val = CONCAT_64(high_order, low_order);
+
+ if( N_VALUE )
+ SET_C((val >> (N_VALUE - 1)) & 1);
+ else
+ SET_C(0);
+
+ sign_bit = val >> 63;
+ val >>= N_VALUE;
+
+ if( sign_bit )
+ {
+ int i;
+ for( i = 0; i < N_VALUE; i++ )
+ {
+ val |= (U64(0x8000000000000000) >> i);
+ }
+ }
+
+ high_order = val >> 32;
+ low_order = val & 0xffffffff;
+
+ SET_DREG(high_order);
+ SET_DREGF(low_order);
+
+ SET_Z( val == 0 ? 1 : 0 );
+ SET_N( SIGN_BIT(high_order) );
+
+ cpustate->icount -= cpustate->clock_cycles_2;
+}
+
+INLINE void hyperstone_sard(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ UINT32 low_order, high_order;
+ UINT64 val;
+ UINT8 n, sign_bit;
+
+ n = SREG & 0x1f;
+
+ // result undefined if Ls denotes the same register as Ld or Ldf
+ if( SAME_SRC_DST || SAME_SRC_DSTF )
+ {
+ DEBUG_PRINTF(("Denoted same registers in hyperstone_sard. PC = %08X\n", PC));
+ }
+ else
+ {
+ high_order = DREG;
+ low_order = DREGF;
+
+ val = CONCAT_64(high_order, low_order);
+
+ if( n )
+ SET_C((val >> (n - 1)) & 1);
+ else
+ SET_C(0);
+
+ sign_bit = val >> 63;
+
+ val >>= n;
+
+ if( sign_bit )
+ {
+ int i;
+ for( i = 0; i < n; i++ )
+ {
+ val |= (U64(0x8000000000000000) >> i);
+ }
+ }
+
+ high_order = val >> 32;
+ low_order = val & 0xffffffff;
+
+ SET_DREG(high_order);
+ SET_DREGF(low_order);
+ SET_Z( val == 0 ? 1 : 0 );
+ SET_N( SIGN_BIT(high_order) );
+ }
+
+ cpustate->icount -= cpustate->clock_cycles_2;
+}
+
+INLINE void hyperstone_sar(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ UINT32 ret;
+ UINT8 n, sign_bit;
+
+ n = SREG & 0x1f;
+ ret = DREG;
+ sign_bit = (ret & 0x80000000) >> 31;
+
+ if( n )
+ SET_C((ret >> (n - 1)) & 1);
+ else
+ SET_C(0);
+
+ ret >>= n;
+
+ if( sign_bit )
+ {
+ int i;
+ for( i = 0; i < n; i++ )
+ {
+ ret |= (0x80000000 >> i);
+ }
+ }
+
+ SET_DREG(ret);
+ SET_Z( ret == 0 ? 1 : 0 );
+ SET_N( SIGN_BIT(ret) );
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_shldi(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ UINT32 low_order, high_order, tmp;
+ UINT64 val, mask;
+
+ high_order = DREG;
+ low_order = DREGF;
+
+ val = CONCAT_64(high_order, low_order);
+ SET_C( (N_VALUE)?(((val<<(N_VALUE-1))&U64(0x8000000000000000))?1:0):0);
+ mask = ((((UINT64)1) << (32 - N_VALUE)) - 1) ^ 0xffffffff;
+ tmp = high_order << N_VALUE;
+
+ if( ((high_order & mask) && (!(tmp & 0x80000000))) ||
+ (((high_order & mask) ^ mask) && (tmp & 0x80000000)) )
+ SET_V(1);
+ else
+ SET_V(0);
+
+ val <<= N_VALUE;
+
+ high_order = EXTRACT_64HI(val);
+ low_order = EXTRACT_64LO(val);
+
+ SET_DREG(high_order);
+ SET_DREGF(low_order);
+
+ SET_Z( val == 0 ? 1 : 0 );
+ SET_N( SIGN_BIT(high_order) );
+
+ cpustate->icount -= cpustate->clock_cycles_2;
+}
+
+INLINE void hyperstone_shld(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ UINT32 low_order, high_order, tmp, n;
+ UINT64 val, mask;
+
+ n = SREG & 0x1f;
+
+ // result undefined if Ls denotes the same register as Ld or Ldf
+ if( SAME_SRC_DST || SAME_SRC_DSTF )
+ {
+ DEBUG_PRINTF(("Denoted same registers in hyperstone_shld. PC = %08X\n", PC));
+ }
+ else
+ {
+ high_order = DREG;
+ low_order = DREGF;
+
+ mask = ((((UINT64)1) << (32 - n)) - 1) ^ 0xffffffff;
+
+ val = CONCAT_64(high_order, low_order);
+ SET_C( (n)?(((val<<(n-1))&U64(0x8000000000000000))?1:0):0);
+ tmp = high_order << n;
+
+ if( ((high_order & mask) && (!(tmp & 0x80000000))) ||
+ (((high_order & mask) ^ mask) && (tmp & 0x80000000)) )
+ SET_V(1);
+ else
+ SET_V(0);
+
+ val <<= n;
+
+ high_order = EXTRACT_64HI(val);
+ low_order = EXTRACT_64LO(val);
+
+ SET_DREG(high_order);
+ SET_DREGF(low_order);
+
+ SET_Z( val == 0 ? 1 : 0 );
+ SET_N( SIGN_BIT(high_order) );
+ }
+
+ cpustate->icount -= cpustate->clock_cycles_2;
+}
+
+INLINE void hyperstone_shl(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ UINT32 base, ret, n;
+ UINT64 mask;
+
+ n = SREG & 0x1f;
+ base = DREG;
+ mask = ((((UINT64)1) << (32 - n)) - 1) ^ 0xffffffff;
+ SET_C( (n)?(((base<<(n-1))&0x80000000)?1:0):0);
+ ret = base << n;
+
+ if( ((base & mask) && (!(ret & 0x80000000))) ||
+ (((base & mask) ^ mask) && (ret & 0x80000000)) )
+ SET_V(1);
+ else
+ SET_V(0);
+
+ SET_DREG(ret);
+ SET_Z( ret == 0 ? 1 : 0 );
+ SET_N( SIGN_BIT(ret) );
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+static void reserved(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ DEBUG_PRINTF(("Executed Reserved opcode. PC = %08X OP = %04X\n", PC, OP));
+}
+
+INLINE void hyperstone_testlz(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ UINT8 zeros = 0;
+ UINT32 mask;
+
+ for( mask = 0x80000000; ; mask >>= 1 )
+ {
+ if( SREG & mask )
+ break;
+ else
+ zeros++;
+
+ if( zeros == 32 )
+ break;
+ }
+
+ SET_DREG(zeros);
+
+ cpustate->icount -= cpustate->clock_cycles_2;
+}
+
+INLINE void hyperstone_rol(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ UINT32 val, base;
+ UINT8 n;
+ UINT64 mask;
+
+ n = SREG & 0x1f;
+
+ val = base = DREG;
+
+ mask = ((((UINT64)1) << (32 - n)) - 1) ^ 0xffffffff;
+
+ while( n > 0 )
+ {
+ val = (val << 1) | ((val & 0x80000000) >> 31);
+ n--;
+ }
+
+#ifdef MISSIONCRAFT_FLAGS
+
+ if( ((base & mask) && (!(val & 0x80000000))) ||
+ (((base & mask) ^ mask) && (val & 0x80000000)) )
+ SET_V(1);
+ else
+ SET_V(0);
+
+#endif
+
+ SET_DREG(val);
+
+ SET_Z( val == 0 ? 1 : 0 );
+ SET_N( SIGN_BIT(val) );
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+//TODO: add trap error
+INLINE void hyperstone_ldxx1(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ UINT32 load;
+
+ if( DST_IS_SR )
+ {
+ switch( decode->sub_type )
+ {
+ case 0: // LDBS.A
+
+ load = READ_B(cpustate, EXTRA_S);
+ load |= (load & 0x80) ? 0xffffff00 : 0;
+ SET_SREG(load);
+
+ break;
+
+ case 1: // LDBU.A
+
+ load = READ_B(cpustate, EXTRA_S);
+ SET_SREG(load);
+
+ break;
+
+ case 2:
+
+ load = READ_HW(cpustate, EXTRA_S & ~1);
+
+ if( EXTRA_S & 1 ) // LDHS.A
+ {
+ load |= (load & 0x8000) ? 0xffff0000 : 0;
+ }
+ /*
+ else // LDHU.A
+ {
+ // nothing more
+ }
+ */
+
+ SET_SREG(load);
+
+ break;
+
+ case 3:
+
+ if( (EXTRA_S & 3) == 3 ) // LDD.IOA
+ {
+ load = IO_READ_W(cpustate, EXTRA_S & ~3);
+ SET_SREG(load);
+
+ load = IO_READ_W(cpustate, (EXTRA_S & ~3) + 4);
+ SET_SREGF(load);
+
+ cpustate->icount -= cpustate->clock_cycles_1; // extra cycle
+ }
+ else if( (EXTRA_S & 3) == 2 ) // LDW.IOA
+ {
+ load = IO_READ_W(cpustate, EXTRA_S & ~3);
+ SET_SREG(load);
+ }
+ else if( (EXTRA_S & 3) == 1 ) // LDD.A
+ {
+ load = READ_W(cpustate, EXTRA_S & ~1);
+ SET_SREG(load);
+
+ load = READ_W(cpustate, (EXTRA_S & ~1) + 4);
+ SET_SREGF(load);
+
+ cpustate->icount -= cpustate->clock_cycles_1; // extra cycle
+ }
+ else // LDW.A
+ {
+ load = READ_W(cpustate, EXTRA_S & ~1);
+ SET_SREG(load);
+ }
+
+ break;
+ }
+ }
+ else
+ {
+ switch( decode->sub_type )
+ {
+ case 0: // LDBS.D
+
+ load = READ_B(cpustate, DREG + EXTRA_S);
+ load |= (load & 0x80) ? 0xffffff00 : 0;
+ SET_SREG(load);
+
+ break;
+
+ case 1: // LDBU.D
+
+ load = READ_B(cpustate, DREG + EXTRA_S);
+ SET_SREG(load);
+
+ break;
+
+ case 2:
+
+ load = READ_HW(cpustate, DREG + (EXTRA_S & ~1));
+
+ if( EXTRA_S & 1 ) // LDHS.D
+ {
+ load |= (load & 0x8000) ? 0xffff0000 : 0;
+ }
+ /*
+ else // LDHU.D
+ {
+ // nothing more
+ }
+ */
+
+ SET_SREG(load);
+
+ break;
+
+ case 3:
+
+ if( (EXTRA_S & 3) == 3 ) // LDD.IOD
+ {
+ load = IO_READ_W(cpustate, DREG + (EXTRA_S & ~3));
+ SET_SREG(load);
+
+ load = IO_READ_W(cpustate, DREG + (EXTRA_S & ~3) + 4);
+ SET_SREGF(load);
+
+ cpustate->icount -= cpustate->clock_cycles_1; // extra cycle
+ }
+ else if( (EXTRA_S & 3) == 2 ) // LDW.IOD
+ {
+ load = IO_READ_W(cpustate, DREG + (EXTRA_S & ~3));
+ SET_SREG(load);
+ }
+ else if( (EXTRA_S & 3) == 1 ) // LDD.D
+ {
+ load = READ_W(cpustate, DREG + (EXTRA_S & ~1));
+ SET_SREG(load);
+
+ load = READ_W(cpustate, DREG + (EXTRA_S & ~1) + 4);
+ SET_SREGF(load);
+
+ cpustate->icount -= cpustate->clock_cycles_1; // extra cycle
+ }
+ else // LDW.D
+ {
+ load = READ_W(cpustate, DREG + (EXTRA_S & ~1));
+ SET_SREG(load);
+ }
+
+ break;
+ }
+ }
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_ldxx2(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ UINT32 load;
+
+ if( DST_IS_PC || DST_IS_SR )
+ {
+ DEBUG_PRINTF(("Denoted PC or SR in hyperstone_ldxx2. PC = %08X\n", PC));
+ }
+ else
+ {
+ switch( decode->sub_type )
+ {
+ case 0: // LDBS.N
+
+ if(SAME_SRC_DST)
+ DEBUG_PRINTF(("LDBS.N denoted same regs @ %08X",PPC));
+
+ load = READ_B(cpustate, DREG);
+ load |= (load & 0x80) ? 0xffffff00 : 0;
+ SET_SREG(load);
+
+ if(!SAME_SRC_DST)
+ SET_DREG(DREG + EXTRA_S);
+
+ break;
+
+ case 1: // LDBU.N
+
+ if(SAME_SRC_DST)
+ DEBUG_PRINTF(("LDBU.N denoted same regs @ %08X",PPC));
+
+ load = READ_B(cpustate, DREG);
+ SET_SREG(load);
+
+ if(!SAME_SRC_DST)
+ SET_DREG(DREG + EXTRA_S);
+
+ break;
+
+ case 2:
+
+ load = READ_HW(cpustate, DREG);
+
+ if( EXTRA_S & 1 ) // LDHS.N
+ {
+ load |= (load & 0x8000) ? 0xffff0000 : 0;
+
+ if(SAME_SRC_DST)
+ DEBUG_PRINTF(("LDHS.N denoted same regs @ %08X",PPC));
+ }
+ /*
+ else // LDHU.N
+ {
+ // nothing more
+ }
+ */
+
+ SET_SREG(load);
+
+ if(!SAME_SRC_DST)
+ SET_DREG(DREG + (EXTRA_S & ~1));
+
+ break;
+
+ case 3:
+
+ if( (EXTRA_S & 3) == 3 ) // LDW.S
+ {
+ if(SAME_SRC_DST)
+ DEBUG_PRINTF(("LDW.S denoted same regs @ %08X",PPC));
+
+ if(DREG < SP)
+ SET_SREG(READ_W(cpustate, DREG));
+ else
+ SET_SREG(GET_ABS_L_REG((DREG & 0xfc) >> 2));
+
+ if(!SAME_SRC_DST)
+ SET_DREG(DREG + (EXTRA_S & ~3));
+
+ cpustate->icount -= cpustate->clock_cycles_2; // extra cycles
+ }
+ else if( (EXTRA_S & 3) == 2 ) // Reserved
+ {
+ DEBUG_PRINTF(("Executed Reserved instruction in hyperstone_ldxx2. PC = %08X\n", PC));
+ }
+ else if( (EXTRA_S & 3) == 1 ) // LDD.N
+ {
+ if(SAME_SRC_DST || SAME_SRCF_DST)
+ DEBUG_PRINTF(("LDD.N denoted same regs @ %08X",PPC));
+
+ load = READ_W(cpustate, DREG);
+ SET_SREG(load);
+
+ load = READ_W(cpustate, DREG + 4);
+ SET_SREGF(load);
+
+ if(!SAME_SRC_DST && !SAME_SRCF_DST)
+ SET_DREG(DREG + (EXTRA_S & ~1));
+
+ cpustate->icount -= cpustate->clock_cycles_1; // extra cycle
+ }
+ else // LDW.N
+ {
+ if(SAME_SRC_DST)
+ DEBUG_PRINTF(("LDW.N denoted same regs @ %08X",PPC));
+
+ load = READ_W(cpustate, DREG);
+ SET_SREG(load);
+
+ if(!SAME_SRC_DST)
+ SET_DREG(DREG + (EXTRA_S & ~1));
+ }
+
+ break;
+ }
+ }
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+//TODO: add trap error
+INLINE void hyperstone_stxx1(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ if( SRC_IS_SR )
+ SREG = SREGF = 0;
+
+ if( DST_IS_SR )
+ {
+ switch( decode->sub_type )
+ {
+ case 0: // STBS.A
+
+ /* TODO: missing trap on range error */
+ WRITE_B(cpustate, EXTRA_S, SREG & 0xff);
+
+ break;
+
+ case 1: // STBU.A
+
+ WRITE_B(cpustate, EXTRA_S, SREG & 0xff);
+
+ break;
+
+ case 2:
+
+ WRITE_HW(cpustate, EXTRA_S & ~1, SREG & 0xffff);
+
+ /*
+ if( EXTRA_S & 1 ) // STHS.A
+ {
+ // TODO: missing trap on range error
+ }
+ else // STHU.A
+ {
+ // nothing more
+ }
+ */
+
+ break;
+
+ case 3:
+
+ if( (EXTRA_S & 3) == 3 ) // STD.IOA
+ {
+ IO_WRITE_W(cpustate, EXTRA_S & ~3, SREG);
+ IO_WRITE_W(cpustate, (EXTRA_S & ~3) + 4, SREGF);
+
+ cpustate->icount -= cpustate->clock_cycles_1; // extra cycle
+ }
+ else if( (EXTRA_S & 3) == 2 ) // STW.IOA
+ {
+ IO_WRITE_W(cpustate, EXTRA_S & ~3, SREG);
+ }
+ else if( (EXTRA_S & 3) == 1 ) // STD.A
+ {
+ WRITE_W(cpustate, EXTRA_S & ~1, SREG);
+ WRITE_W(cpustate, (EXTRA_S & ~1) + 4, SREGF);
+
+ cpustate->icount -= cpustate->clock_cycles_1; // extra cycle
+ }
+ else // STW.A
+ {
+ WRITE_W(cpustate, EXTRA_S & ~1, SREG);
+ }
+
+ break;
+ }
+ }
+ else
+ {
+ switch( decode->sub_type )
+ {
+ case 0: // STBS.D
+
+ /* TODO: missing trap on range error */
+ WRITE_B(cpustate, DREG + EXTRA_S, SREG & 0xff);
+
+ break;
+
+ case 1: // STBU.D
+
+ WRITE_B(cpustate, DREG + EXTRA_S, SREG & 0xff);
+
+ break;
+
+ case 2:
+
+ WRITE_HW(cpustate, DREG + (EXTRA_S & ~1), SREG & 0xffff);
+
+ /*
+ if( EXTRA_S & 1 ) // STHS.D
+ {
+ // TODO: missing trap on range error
+ }
+ else // STHU.D
+ {
+ // nothing more
+ }
+ */
+
+ break;
+
+ case 3:
+
+ if( (EXTRA_S & 3) == 3 ) // STD.IOD
+ {
+ IO_WRITE_W(cpustate, DREG + (EXTRA_S & ~3), SREG);
+ IO_WRITE_W(cpustate, DREG + (EXTRA_S & ~3) + 4, SREGF);
+
+ cpustate->icount -= cpustate->clock_cycles_1; // extra cycle
+ }
+ else if( (EXTRA_S & 3) == 2 ) // STW.IOD
+ {
+ IO_WRITE_W(cpustate, DREG + (EXTRA_S & ~3), SREG);
+ }
+ else if( (EXTRA_S & 3) == 1 ) // STD.D
+ {
+ WRITE_W(cpustate, DREG + (EXTRA_S & ~1), SREG);
+ WRITE_W(cpustate, DREG + (EXTRA_S & ~1) + 4, SREGF);
+
+ cpustate->icount -= cpustate->clock_cycles_1; // extra cycle
+ }
+ else // STW.D
+ {
+ WRITE_W(cpustate, DREG + (EXTRA_S & ~1), SREG);
+ }
+
+ break;
+ }
+ }
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_stxx2(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ if( SRC_IS_SR )
+ SREG = SREGF = 0;
+
+ if( DST_IS_PC || DST_IS_SR )
+ {
+ DEBUG_PRINTF(("Denoted PC or SR in hyperstone_stxx2. PC = %08X\n", PC));
+ }
+ else
+ {
+ switch( decode->sub_type )
+ {
+ case 0: // STBS.N
+
+ /* TODO: missing trap on range error */
+ WRITE_B(cpustate, DREG, SREG & 0xff);
+ SET_DREG(DREG + EXTRA_S);
+
+ break;
+
+ case 1: // STBU.N
+
+ WRITE_B(cpustate, DREG, SREG & 0xff);
+ SET_DREG(DREG + EXTRA_S);
+
+ break;
+
+ case 2:
+
+ WRITE_HW(cpustate, DREG, SREG & 0xffff);
+ SET_DREG(DREG + (EXTRA_S & ~1));
+
+ /*
+ if( EXTRA_S & 1 ) // STHS.N
+ {
+ // TODO: missing trap on range error
+ }
+ else // STHU.N
+ {
+ // nothing more
+ }
+ */
+
+ break;
+
+ case 3:
+
+ if( (EXTRA_S & 3) == 3 ) // STW.S
+ {
+ if(DREG < SP)
+ WRITE_W(cpustate, DREG, SREG);
+ else
+ {
+ if(((DREG & 0xfc) >> 2) == ((decode->src + GET_FP) % 64) && S_BIT == LOCAL)
+ DEBUG_PRINTF(("STW.S denoted the same local register @ %08X\n",PPC));
+
+ SET_ABS_L_REG((DREG & 0xfc) >> 2,SREG);
+ }
+
+ SET_DREG(DREG + (EXTRA_S & ~3));
+
+ cpustate->icount -= cpustate->clock_cycles_2; // extra cycles
+
+ }
+ else if( (EXTRA_S & 3) == 2 ) // Reserved
+ {
+ DEBUG_PRINTF(("Executed Reserved instruction in hyperstone_stxx2. PC = %08X\n", PC));
+ }
+ else if( (EXTRA_S & 3) == 1 ) // STD.N
+ {
+ WRITE_W(cpustate, DREG, SREG);
+ SET_DREG(DREG + (EXTRA_S & ~1));
+
+ if( SAME_SRCF_DST )
+ WRITE_W(cpustate, DREG + 4, SREGF + (EXTRA_S & ~1)); // because DREG == SREGF and DREG has been incremented
+ else
+ WRITE_W(cpustate, DREG + 4, SREGF);
+
+ cpustate->icount -= cpustate->clock_cycles_1; // extra cycle
+ }
+ else // STW.N
+ {
+ WRITE_W(cpustate, DREG, SREG);
+ SET_DREG(DREG + (EXTRA_S & ~1));
+ }
+
+ break;
+ }
+ }
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_shri(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ UINT32 val;
+
+ val = DREG;
+
+ if( N_VALUE )
+ SET_C((val >> (N_VALUE - 1)) & 1);
+ else
+ SET_C(0);
+
+ val >>= N_VALUE;
+
+ SET_DREG(val);
+ SET_Z( val == 0 ? 1 : 0 );
+ SET_N( SIGN_BIT(val) );
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_sari(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ UINT32 val;
+ UINT8 sign_bit;
+
+ val = DREG;
+ sign_bit = (val & 0x80000000) >> 31;
+
+ if( N_VALUE )
+ SET_C((val >> (N_VALUE - 1)) & 1);
+ else
+ SET_C(0);
+
+ val >>= N_VALUE;
+
+ if( sign_bit )
+ {
+ int i;
+ for( i = 0; i < N_VALUE; i++ )
+ {
+ val |= (0x80000000 >> i);
+ }
+ }
+
+ SET_DREG(val);
+ SET_Z( val == 0 ? 1 : 0 );
+ SET_N( SIGN_BIT(val) );
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_shli(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ UINT32 val, val2;
+ UINT64 mask;
+
+ val = DREG;
+ SET_C( (N_VALUE)?(((val<<(N_VALUE-1))&0x80000000)?1:0):0);
+ mask = ((((UINT64)1) << (32 - N_VALUE)) - 1) ^ 0xffffffff;
+ val2 = val << N_VALUE;
+
+ if( ((val & mask) && (!(val2 & 0x80000000))) ||
+ (((val & mask) ^ mask) && (val2 & 0x80000000)) )
+ SET_V(1);
+ else
+ SET_V(0);
+
+ SET_DREG(val2);
+ SET_Z( val2 == 0 ? 1 : 0 );
+ SET_N( SIGN_BIT(val2) );
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_mulu(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ UINT32 low_order, high_order;
+ UINT64 double_word;
+
+ // PC or SR aren't denoted, else result is undefined
+ if( SRC_IS_PC || SRC_IS_SR || DST_IS_PC || DST_IS_SR )
+ {
+ DEBUG_PRINTF(("Denoted PC or SR in hyperstone_mulu instruction. PC = %08X\n", PC));
+ }
+ else
+ {
+ double_word = (UINT64)SREG *(UINT64)DREG;
+
+ low_order = double_word & 0xffffffff;
+ high_order = double_word >> 32;
+
+ SET_DREG(high_order);
+ SET_DREGF(low_order);
+
+ SET_Z( double_word == 0 ? 1 : 0 );
+ SET_N( SIGN_BIT(high_order) );
+ }
+
+ if(SREG <= 0xffff && DREG <= 0xffff)
+ cpustate->icount -= cpustate->clock_cycles_4;
+ else
+ cpustate->icount -= cpustate->clock_cycles_6;
+}
+
+INLINE void hyperstone_muls(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ UINT32 low_order, high_order;
+ INT64 double_word;
+
+ // PC or SR aren't denoted, else result is undefined
+ if( SRC_IS_PC || SRC_IS_SR || DST_IS_PC || DST_IS_SR )
+ {
+ DEBUG_PRINTF(("Denoted PC or SR in hyperstone_muls instruction. PC = %08X\n", PC));
+ }
+ else
+ {
+ double_word = (INT64)(INT32)(SREG) * (INT64)(INT32)(DREG);
+ low_order = double_word & 0xffffffff;
+ high_order = double_word >> 32;
+
+ SET_DREG(high_order);
+ SET_DREGF(low_order);
+
+ SET_Z( double_word == 0 ? 1 : 0 );
+ SET_N( SIGN_BIT(high_order) );
+ }
+
+ if((SREG >= 0xffff8000 && SREG <= 0x7fff) && (DREG >= 0xffff8000 && DREG <= 0x7fff))
+ cpustate->icount -= cpustate->clock_cycles_4;
+ else
+ cpustate->icount -= cpustate->clock_cycles_6;
+}
+
+INLINE void hyperstone_set(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ int n = N_VALUE;
+
+ if( DST_IS_PC )
+ {
+ DEBUG_PRINTF(("Denoted PC in hyperstone_set. PC = %08X\n", PC));
+ }
+ else if( DST_IS_SR )
+ {
+ //TODO: add fetch opcode when there's the pipeline
+
+ //TODO: no 1!
+ cpustate->icount -= cpustate->clock_cycles_1;
+ }
+ else
+ {
+ switch( n )
+ {
+ // SETADR
+ case 0:
+ {
+ UINT32 val;
+ val = (SP & 0xfffffe00) | (GET_FP << 2);
+
+ //plus carry into bit 9
+ val += (( (SP & 0x100) && (SIGN_BIT(SR) == 0) ) ? 1 : 0);
+
+ SET_DREG(val);
+
+ break;
+ }
+ // Reserved
+ case 1:
+ case 16:
+ case 17:
+ case 19:
+ DEBUG_PRINTF(("Used reserved N value (%d) in hyperstone_set. PC = %08X\n", n, PC));
+ break;
+
+ // SETxx
+ case 2:
+ SET_DREG(1);
+ break;
+
+ case 3:
+ SET_DREG(0);
+ break;
+
+ case 4:
+ if( GET_N || GET_Z )
+ {
+ SET_DREG(1);
+ }
+ else
+ {
+ SET_DREG(0);
+ }
+
+ break;
+
+ case 5:
+ if( !GET_N && !GET_Z )
+ {
+ SET_DREG(1);
+ }
+ else
+ {
+ SET_DREG(0);
+ }
+
+ break;
+
+ case 6:
+ if( GET_N )
+ {
+ SET_DREG(1);
+ }
+ else
+ {
+ SET_DREG(0);
+ }
+
+ break;
+
+ case 7:
+ if( !GET_N )
+ {
+ SET_DREG(1);
+ }
+ else
+ {
+ SET_DREG(0);
+ }
+
+ break;
+
+ case 8:
+ if( GET_C || GET_Z )
+ {
+ SET_DREG(1);
+ }
+ else
+ {
+ SET_DREG(0);
+ }
+
+ break;
+
+ case 9:
+ if( !GET_C && !GET_Z )
+ {
+ SET_DREG(1);
+ }
+ else
+ {
+ SET_DREG(0);
+ }
+
+ break;
+
+ case 10:
+ if( GET_C )
+ {
+ SET_DREG(1);
+ }
+ else
+ {
+ SET_DREG(0);
+ }
+
+ break;
+
+ case 11:
+ if( !GET_C )
+ {
+ SET_DREG(1);
+ }
+ else
+ {
+ SET_DREG(0);
+ }
+
+ break;
+
+ case 12:
+ if( GET_Z )
+ {
+ SET_DREG(1);
+ }
+ else
+ {
+ SET_DREG(0);
+ }
+
+ break;
+
+ case 13:
+ if( !GET_Z )
+ {
+ SET_DREG(1);
+ }
+ else
+ {
+ SET_DREG(0);
+ }
+
+ break;
+
+ case 14:
+ if( GET_V )
+ {
+ SET_DREG(1);
+ }
+ else
+ {
+ SET_DREG(0);
+ }
+
+ break;
+
+ case 15:
+ if( !GET_V )
+ {
+ SET_DREG(1);
+ }
+ else
+ {
+ SET_DREG(0);
+ }
+
+ break;
+
+ case 18:
+ SET_DREG(-1);
+ break;
+
+ case 20:
+ if( GET_N || GET_Z )
+ {
+ SET_DREG(-1);
+ }
+ else
+ {
+ SET_DREG(0);
+ }
+
+ break;
+
+ case 21:
+ if( !GET_N && !GET_Z )
+ {
+ SET_DREG(-1);
+ }
+ else
+ {
+ SET_DREG(0);
+ }
+
+ break;
+
+ case 22:
+ if( GET_N )
+ {
+ SET_DREG(-1);
+ }
+ else
+ {
+ SET_DREG(0);
+ }
+
+ break;
+
+ case 23:
+ if( !GET_N )
+ {
+ SET_DREG(-1);
+ }
+ else
+ {
+ SET_DREG(0);
+ }
+
+ break;
+
+ case 24:
+ if( GET_C || GET_Z )
+ {
+ SET_DREG(-1);
+ }
+ else
+ {
+ SET_DREG(0);
+ }
+
+ break;
+
+ case 25:
+ if( !GET_C && !GET_Z )
+ {
+ SET_DREG(-1);
+ }
+ else
+ {
+ SET_DREG(0);
+ }
+
+ break;
+
+ case 26:
+ if( GET_C )
+ {
+ SET_DREG(-1);
+ }
+ else
+ {
+ SET_DREG(0);
+ }
+
+ break;
+
+ case 27:
+ if( !GET_C )
+ {
+ SET_DREG(-1);
+ }
+ else
+ {
+ SET_DREG(0);
+ }
+
+ break;
+
+ case 28:
+ if( GET_Z )
+ {
+ SET_DREG(-1);
+ }
+ else
+ {
+ SET_DREG(0);
+ }
+
+ break;
+
+ case 29:
+ if( !GET_Z )
+ {
+ SET_DREG(-1);
+ }
+ else
+ {
+ SET_DREG(0);
+ }
+
+ break;
+
+ case 30:
+ if( GET_V )
+ {
+ SET_DREG(-1);
+ }
+ else
+ {
+ SET_DREG(0);
+ }
+
+ break;
+
+ case 31:
+ if( !GET_V )
+ {
+ SET_DREG(-1);
+ }
+ else
+ {
+ SET_DREG(0);
+ }
+
+ break;
+ }
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+ }
+}
+
+INLINE void hyperstone_mul(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ UINT32 single_word;
+
+ // PC or SR aren't denoted, else result is undefined
+ if( SRC_IS_PC || SRC_IS_SR || DST_IS_PC || DST_IS_SR )
+ {
+ DEBUG_PRINTF(("Denoted PC or SR in hyperstone_mul instruction. PC = %08X\n", PC));
+ }
+ else
+ {
+ single_word = (SREG * DREG);// & 0xffffffff; // only the low-order word is taken
+
+ SET_DREG(single_word);
+
+ SET_Z( single_word == 0 ? 1 : 0 );
+ SET_N( SIGN_BIT(single_word) );
+ }
+
+ if((SREG >= 0xffff8000 && SREG <= 0x7fff) && (DREG >= 0xffff8000 && DREG <= 0x7fff))
+ cpustate->icount -= 3 << cpustate->clock_scale;
+ else
+ cpustate->icount -= 5 << cpustate->clock_scale;
+}
+
+INLINE void hyperstone_fadd(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ execute_software(cpustate, decode);
+ cpustate->icount -= cpustate->clock_cycles_6;
+}
+
+INLINE void hyperstone_faddd(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ execute_software(cpustate, decode);
+ cpustate->icount -= cpustate->clock_cycles_6;
+}
+
+INLINE void hyperstone_fsub(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ execute_software(cpustate, decode);
+ cpustate->icount -= cpustate->clock_cycles_6;
+}
+
+INLINE void hyperstone_fsubd(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ execute_software(cpustate, decode);
+ cpustate->icount -= cpustate->clock_cycles_6;
+}
+
+INLINE void hyperstone_fmul(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ execute_software(cpustate, decode);
+ cpustate->icount -= cpustate->clock_cycles_6;
+}
+
+INLINE void hyperstone_fmuld(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ execute_software(cpustate, decode);
+ cpustate->icount -= cpustate->clock_cycles_6;
+}
+
+INLINE void hyperstone_fdiv(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ execute_software(cpustate, decode);
+ cpustate->icount -= cpustate->clock_cycles_6;
+}
+
+INLINE void hyperstone_fdivd(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ execute_software(cpustate, decode);
+ cpustate->icount -= cpustate->clock_cycles_6;
+}
+
+INLINE void hyperstone_fcmp(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ execute_software(cpustate, decode);
+ cpustate->icount -= cpustate->clock_cycles_6;
+}
+
+INLINE void hyperstone_fcmpd(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ execute_software(cpustate, decode);
+ cpustate->icount -= cpustate->clock_cycles_6;
+}
+
+INLINE void hyperstone_fcmpu(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ execute_software(cpustate, decode);
+ cpustate->icount -= cpustate->clock_cycles_6;
+}
+
+INLINE void hyperstone_fcmpud(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ execute_software(cpustate, decode);
+ cpustate->icount -= cpustate->clock_cycles_6;
+}
+
+INLINE void hyperstone_fcvt(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ execute_software(cpustate, decode);
+ cpustate->icount -= cpustate->clock_cycles_6;
+}
+
+INLINE void hyperstone_fcvtd(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ execute_software(cpustate, decode);
+ cpustate->icount -= cpustate->clock_cycles_6;
+}
+
+INLINE void hyperstone_extend(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ //TODO: add locks, overflow error and other things
+ UINT32 vals, vald;
+
+ vals = SREG;
+ vald = DREG;
+
+ switch( EXTRA_U ) // extended opcode
+ {
+ // signed or unsigned multiplication, single word product
+ case EMUL:
+ case 0x100: // used in "N" type cpu
+ {
+ UINT32 result;
+
+ result = vals * vald;
+ SET_G_REG(15, result);
+
+ break;
+ }
+ // unsigned multiplication, double word product
+ case EMULU:
+ {
+ UINT64 result;
+
+ result = (UINT64)vals * (UINT64)vald;
+ vals = result >> 32;
+ vald = result & 0xffffffff;
+ SET_G_REG(14, vals);
+ SET_G_REG(15, vald);
+
+ break;
+ }
+ // signed multiplication, double word product
+ case EMULS:
+ {
+ INT64 result;
+
+ result = (INT64)(INT32)(vals) * (INT64)(INT32)(vald);
+ vals = result >> 32;
+ vald = result & 0xffffffff;
+ SET_G_REG(14, vals);
+ SET_G_REG(15, vald);
+
+ break;
+ }
+ // signed multiply/add, single word product sum
+ case EMAC:
+ {
+ INT32 result;
+
+ result = (INT32)GET_G_REG(15) + ((INT32)(vals) * (INT32)(vald));
+ SET_G_REG(15, result);
+
+ break;
+ }
+ // signed multiply/add, double word product sum
+ case EMACD:
+ {
+ INT64 result;
+
+ result = (INT64)CONCAT_64(GET_G_REG(14), GET_G_REG(15)) + (INT64)((INT64)(INT32)(vals) * (INT64)(INT32)(vald));
+
+ vals = result >> 32;
+ vald = result & 0xffffffff;
+ SET_G_REG(14, vals);
+ SET_G_REG(15, vald);
+
+ break;
+ }
+ // signed multiply/substract, single word product difference
+ case EMSUB:
+ {
+ INT32 result;
+
+ result = (INT32)GET_G_REG(15) - ((INT32)(vals) * (INT32)(vald));
+ SET_G_REG(15, result);
+
+ break;
+ }
+ // signed multiply/substract, double word product difference
+ case EMSUBD:
+ {
+ INT64 result;
+
+ result = (INT64)CONCAT_64(GET_G_REG(14), GET_G_REG(15)) - (INT64)((INT64)(INT32)(vals) * (INT64)(INT32)(vald));
+
+ vals = result >> 32;
+ vald = result & 0xffffffff;
+ SET_G_REG(14, vals);
+ SET_G_REG(15, vald);
+
+ break;
+ }
+ // signed half-word multiply/add, single word product sum
+ case EHMAC:
+ {
+ INT32 result;
+
+ result = (INT32)GET_G_REG(15) + ((INT32)((vald & 0xffff0000) >> 16) * (INT32)((vals & 0xffff0000) >> 16)) + ((INT32)(vald & 0xffff) * (INT32)(vals & 0xffff));
+ SET_G_REG(15, result);
+
+ break;
+ }
+ // signed half-word multiply/add, double word product sum
+ case EHMACD:
+ {
+ INT64 result;
+
+ result = (INT64)CONCAT_64(GET_G_REG(14), GET_G_REG(15)) + (INT64)((INT64)(INT32)((vald & 0xffff0000) >> 16) * (INT64)(INT32)((vals & 0xffff0000) >> 16)) + ((INT64)(INT32)(vald & 0xffff) * (INT64)(INT32)(vals & 0xffff));
+
+ vals = result >> 32;
+ vald = result & 0xffffffff;
+ SET_G_REG(14, vals);
+ SET_G_REG(15, vald);
+
+ break;
+ }
+ // half-word complex multiply
+ case EHCMULD:
+ {
+ UINT32 result;
+
+ result = (((vald & 0xffff0000) >> 16) * ((vals & 0xffff0000) >> 16)) - ((vald & 0xffff) * (vals & 0xffff));
+ SET_G_REG(14, result);
+
+ result = (((vald & 0xffff0000) >> 16) * (vals & 0xffff)) + ((vald & 0xffff) * ((vals & 0xffff0000) >> 16));
+ SET_G_REG(15, result);
+
+ break;
+ }
+ // half-word complex multiply/add
+ case EHCMACD:
+ {
+ UINT32 result;
+
+ result = GET_G_REG(14) + (((vald & 0xffff0000) >> 16) * ((vals & 0xffff0000) >> 16)) - ((vald & 0xffff) * (vals & 0xffff));
+ SET_G_REG(14, result);
+
+ result = GET_G_REG(15) + (((vald & 0xffff0000) >> 16) * (vals & 0xffff)) + ((vald & 0xffff) * ((vals & 0xffff0000) >> 16));
+ SET_G_REG(15, result);
+
+ break;
+ }
+ // half-word (complex) add/substract
+ // Ls is not used and should denote the same register as Ld
+ case EHCSUMD:
+ {
+ UINT32 result;
+
+ result = ((((vals & 0xffff0000) >> 16) + GET_G_REG(14)) << 16) & 0xffff0000;
+ result |= ((vals & 0xffff) + GET_G_REG(15)) & 0xffff;
+ SET_G_REG(14, result);
+
+ result = ((((vals & 0xffff0000) >> 16) - GET_G_REG(14)) << 16) & 0xffff0000;
+ result |= ((vals & 0xffff) - GET_G_REG(15)) & 0xffff;
+ SET_G_REG(15, result);
+
+ break;
+ }
+ // half-word (complex) add/substract with fixed point adjustment
+ // Ls is not used and should denote the same register as Ld
+ case EHCFFTD:
+ {
+ UINT32 result;
+
+ result = ((((vals & 0xffff0000) >> 16) + (GET_G_REG(14) >> 15)) << 16) & 0xffff0000;
+ result |= ((vals & 0xffff) + (GET_G_REG(15) >> 15)) & 0xffff;
+ SET_G_REG(14, result);
+
+ result = ((((vals & 0xffff0000) >> 16) - (GET_G_REG(14) >> 15)) << 16) & 0xffff0000;
+ result |= ((vals & 0xffff) - (GET_G_REG(15) >> 15)) & 0xffff;
+ SET_G_REG(15, result);
+
+ break;
+ }
+ // half-word (complex) add/substract with fixed point adjustment and shift
+ // Ls is not used and should denote the same register as Ld
+ case EHCFFTSD:
+ {
+ UINT32 result;
+
+ result = (((((vals & 0xffff0000) >> 16) + (GET_G_REG(14) >> 15)) >> 1) << 16) & 0xffff0000;
+ result |= ((((vals & 0xffff) + (GET_G_REG(15) >> 15)) >> 1) & 0xffff);
+ SET_G_REG(14, result);
+
+ result = (((((vals & 0xffff0000) >> 16) - (GET_G_REG(14) >> 15)) >> 1) << 16) & 0xffff0000;
+ result |= ((((vals & 0xffff) - (GET_G_REG(15) >> 15)) >> 1) & 0xffff);
+ SET_G_REG(15, result);
+
+ break;
+ }
+ default:
+ DEBUG_PRINTF(("Executed Illegal extended opcode (%X). PC = %08X\n", EXTRA_U, PC));
+ break;
+ }
+
+ cpustate->icount -= cpustate->clock_cycles_1; //TODO: with the latency it can change
+}
+
+INLINE void hyperstone_do(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ fatalerror("Executed hyperstone_do instruction. PC = %08X", PPC);
+}
+
+INLINE void hyperstone_ldwr(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ SET_SREG(READ_W(cpustate, DREG));
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_lddr(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ SET_SREG(READ_W(cpustate, DREG));
+ SET_SREGF(READ_W(cpustate, DREG + 4));
+
+ cpustate->icount -= cpustate->clock_cycles_2;
+}
+
+INLINE void hyperstone_ldwp(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ SET_SREG(READ_W(cpustate, DREG));
+
+ // post increment the destination register if it's different from the source one
+ // (needed by Hidden Catch)
+ if(!(decode->src == decode->dst && S_BIT == LOCAL))
+ SET_DREG(DREG + 4);
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_lddp(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ SET_SREG(READ_W(cpustate, DREG));
+ SET_SREGF(READ_W(cpustate, DREG + 4));
+
+ // post increment the destination register if it's different from the source one
+ // and from the "next source" one
+ if(!(decode->src == decode->dst && S_BIT == LOCAL) && !SAME_SRCF_DST )
+ {
+ SET_DREG(DREG + 8);
+ }
+ else
+ {
+ DEBUG_PRINTF(("LDD.P denoted same regs @ %08X",PPC));
+ }
+
+ cpustate->icount -= cpustate->clock_cycles_2;
+}
+
+INLINE void hyperstone_stwr(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ if( SRC_IS_SR )
+ SREG = 0;
+
+ WRITE_W(cpustate, DREG, SREG);
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_stdr(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ if( SRC_IS_SR )
+ SREG = SREGF = 0;
+
+ WRITE_W(cpustate, DREG, SREG);
+ WRITE_W(cpustate, DREG + 4, SREGF);
+
+ cpustate->icount -= cpustate->clock_cycles_2;
+}
+
+INLINE void hyperstone_stwp(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ if( SRC_IS_SR )
+ SREG = 0;
+
+ WRITE_W(cpustate, DREG, SREG);
+ SET_DREG(DREG + 4);
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_stdp(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ if( SRC_IS_SR )
+ SREG = SREGF = 0;
+
+ WRITE_W(cpustate, DREG, SREG);
+ SET_DREG(DREG + 8);
+
+ if( SAME_SRCF_DST )
+ WRITE_W(cpustate, DREG + 4, SREGF + 8); // because DREG == SREGF and DREG has been incremented
+ else
+ WRITE_W(cpustate, DREG + 4, SREGF);
+
+ cpustate->icount -= cpustate->clock_cycles_2;
+}
+
+INLINE void hyperstone_dbv(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ if( GET_V )
+ execute_dbr(cpustate, decode);
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_dbnv(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ if( !GET_V )
+ execute_dbr(cpustate, decode);
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_dbe(hyperstone_state *cpustate, struct regs_decode *decode) //or DBZ
+{
+ if( GET_Z )
+ execute_dbr(cpustate, decode);
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_dbne(hyperstone_state *cpustate, struct regs_decode *decode) //or DBNZ
+{
+ if( !GET_Z )
+ execute_dbr(cpustate, decode);
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_dbc(hyperstone_state *cpustate, struct regs_decode *decode) //or DBST
+{
+ if( GET_C )
+ execute_dbr(cpustate, decode);
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_dbnc(hyperstone_state *cpustate, struct regs_decode *decode) //or DBHE
+{
+ if( !GET_C )
+ execute_dbr(cpustate, decode);
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_dbse(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ if( GET_C || GET_Z )
+ execute_dbr(cpustate, decode);
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_dbht(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ if( !GET_C && !GET_Z )
+ execute_dbr(cpustate, decode);
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_dbn(hyperstone_state *cpustate, struct regs_decode *decode) //or DBLT
+{
+ if( GET_N )
+ execute_dbr(cpustate, decode);
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_dbnn(hyperstone_state *cpustate, struct regs_decode *decode) //or DBGE
+{
+ if( !GET_N )
+ execute_dbr(cpustate, decode);
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_dble(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ if( GET_N || GET_Z )
+ execute_dbr(cpustate, decode);
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_dbgt(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ if( !GET_N && !GET_Z )
+ execute_dbr(cpustate, decode);
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_dbr(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ execute_dbr(cpustate, decode);
+}
+
+INLINE void hyperstone_frame(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ INT8 difference; // really it's 7 bits
+ UINT8 realfp = GET_FP - SRC_CODE;
+
+ SET_FP(realfp);
+ SET_FL(DST_CODE);
+ SET_M(0);
+
+ difference = ((SP & 0x1fc) >> 2) + (64 - 10) - (realfp + GET_FL);
+
+ /* convert to 8 bits */
+ if(difference > 63)
+ difference = (INT8)(difference|0x80);
+ else if( difference < -64 )
+ difference = difference & 0x7f;
+
+ if( difference < 0 ) // else it's finished
+ {
+ UINT8 tmp_flag;
+
+ tmp_flag = ( SP >= UB ? 1 : 0 );
+
+ do
+ {
+ WRITE_W(cpustate, SP, GET_ABS_L_REG((SP & 0xfc) >> 2));
+ SP += 4;
+ difference++;
+
+ } while(difference != 0);
+
+ if( tmp_flag )
+ {
+ UINT32 addr = get_trap_addr(cpustate, TRAPNO_FRAME_ERROR);
+ execute_exception(cpustate, addr);
+ }
+ }
+
+ //TODO: no 1!
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_call(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ if( SRC_IS_SR )
+ SREG = 0;
+
+ if( !DST_CODE )
+ decode->dst = 16;
+
+ EXTRA_S = (EXTRA_S & ~1) + SREG;
+
+ SET_ILC(cpustate->instruction_length & 3);
+
+ SET_DREG((PC & 0xfffffffe) | GET_S);
+ SET_DREGF(SR);
+
+ SET_FP(GET_FP + decode->dst);
+
+ SET_FL(6); //default value for call
+ SET_M(0);
+
+ PPC = PC;
+ PC = EXTRA_S; // const value
+
+ cpustate->intblock = 2;
+
+ //TODO: add interrupt locks, errors, ....
+
+ //TODO: no 1!
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_bv(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ if( GET_V )
+ execute_br(cpustate, decode);
+ else
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_bnv(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ if( !GET_V )
+ execute_br(cpustate, decode);
+ else
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_be(hyperstone_state *cpustate, struct regs_decode *decode) //or BZ
+{
+ if( GET_Z )
+ execute_br(cpustate, decode);
+ else
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_bne(hyperstone_state *cpustate, struct regs_decode *decode) //or BNZ
+{
+ if( !GET_Z )
+ execute_br(cpustate, decode);
+ else
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_bc(hyperstone_state *cpustate, struct regs_decode *decode) //or BST
+{
+ if( GET_C )
+ execute_br(cpustate, decode);
+ else
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_bnc(hyperstone_state *cpustate, struct regs_decode *decode) //or BHE
+{
+ if( !GET_C )
+ execute_br(cpustate, decode);
+ else
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_bse(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ if( GET_C || GET_Z )
+ execute_br(cpustate, decode);
+ else
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_bht(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ if( !GET_C && !GET_Z )
+ execute_br(cpustate, decode);
+ else
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_bn(hyperstone_state *cpustate, struct regs_decode *decode) //or BLT
+{
+ if( GET_N )
+ execute_br(cpustate, decode);
+ else
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_bnn(hyperstone_state *cpustate, struct regs_decode *decode) //or BGE
+{
+ if( !GET_N )
+ execute_br(cpustate, decode);
+ else
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_ble(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ if( GET_N || GET_Z )
+ execute_br(cpustate, decode);
+ else
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_bgt(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ if( !GET_N && !GET_Z )
+ execute_br(cpustate, decode);
+ else
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+INLINE void hyperstone_br(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ execute_br(cpustate, decode);
+}
+
+INLINE void hyperstone_trap(hyperstone_state *cpustate, struct regs_decode *decode)
+{
+ UINT8 code, trapno;
+ UINT32 addr;
+
+ trapno = (OP & 0xfc) >> 2;
+
+ addr = get_trap_addr(cpustate, trapno);
+ code = ((OP & 0x300) >> 6) | (OP & 0x03);
+
+ switch( code )
+ {
+ case TRAPLE:
+ if( GET_N || GET_Z )
+ execute_trap(cpustate, addr);
+
+ break;
+
+ case TRAPGT:
+ if( !GET_N && !GET_Z )
+ execute_trap(cpustate, addr);
+
+ break;
+
+ case TRAPLT:
+ if( GET_N )
+ execute_trap(cpustate, addr);
+
+ break;
+
+ case TRAPGE:
+ if( !GET_N )
+ execute_trap(cpustate, addr);
+
+ break;
+
+ case TRAPSE:
+ if( GET_C || GET_Z )
+ execute_trap(cpustate, addr);
+
+ break;
+
+ case TRAPHT:
+ if( !GET_C && !GET_Z )
+ execute_trap(cpustate, addr);
+
+ break;
+
+ case TRAPST:
+ if( GET_C )
+ execute_trap(cpustate, addr);
+
+ break;
+
+ case TRAPHE:
+ if( !GET_C )
+ execute_trap(cpustate, addr);
+
+ break;
+
+ case TRAPE:
+ if( GET_Z )
+ execute_trap(cpustate, addr);
+
+ break;
+
+ case TRAPNE:
+ if( !GET_Z )
+ execute_trap(cpustate, addr);
+
+ break;
+
+ case TRAPV:
+ if( GET_V )
+ execute_trap(cpustate, addr);
+
+ break;
+
+ case TRAP:
+ execute_trap(cpustate, addr);
+
+ break;
+ }
+
+ cpustate->icount -= cpustate->clock_cycles_1;
+}
+
+
+#include "e132xsop.c"
+
+
+static CPU_EXECUTE( hyperstone )
+{
+ hyperstone_state *cpustate = get_safe_token(device);
+
+ if (cpustate->intblock < 0)
+ cpustate->intblock = 0;
+ check_interrupts(cpustate);
+
+ do
+ {
+ UINT32 oldh = SR & 0x00000020;
+
+ PPC = PC; /* copy PC to previous PC */
+ debugger_instruction_hook(device, PC);
+
+ OP = READ_OP(cpustate, PC);
+ PC += 2;
+
+ cpustate->instruction_length = 1;
+
+ /* execute opcode */
+ (*hyperstone_op[(OP & 0xff00) >> 8])(cpustate);
+
+ /* clear the H state if it was previously set */
+ SR ^= oldh;
+
+ SET_ILC(cpustate->instruction_length & 3);
+
+ if( GET_T && GET_P && cpustate->delay.delay_cmd == NO_DELAY ) /* Not in a Delayed Branch instructions */
+ {
+ UINT32 addr = get_trap_addr(cpustate, TRAPNO_TRACE_EXCEPTION);
+ execute_exception(cpustate, addr);
+ }
+
+ if (--cpustate->intblock == 0)
+ check_interrupts(cpustate);
+
+ } while( cpustate->icount > 0 );
+}
+
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( hyperstone )
+{
+ hyperstone_state *cpustate = get_safe_token(device);
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + E132XS_PC: PC = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_SR: SR = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_FER: FER = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_G3: set_global_register(cpustate, 3, info->i); break;
+ case CPUINFO_INT_REGISTER + E132XS_G4: set_global_register(cpustate, 4, info->i); break;
+ case CPUINFO_INT_REGISTER + E132XS_G5: set_global_register(cpustate, 5, info->i); break;
+ case CPUINFO_INT_REGISTER + E132XS_G6: set_global_register(cpustate, 6, info->i); break;
+ case CPUINFO_INT_REGISTER + E132XS_G7: set_global_register(cpustate, 7, info->i); break;
+ case CPUINFO_INT_REGISTER + E132XS_G8: set_global_register(cpustate, 8, info->i); break;
+ case CPUINFO_INT_REGISTER + E132XS_G9: set_global_register(cpustate, 9, info->i); break;
+ case CPUINFO_INT_REGISTER + E132XS_G10: set_global_register(cpustate, 10, info->i); break;
+ case CPUINFO_INT_REGISTER + E132XS_G11: set_global_register(cpustate, 11, info->i); break;
+ case CPUINFO_INT_REGISTER + E132XS_G12: set_global_register(cpustate, 12, info->i); break;
+ case CPUINFO_INT_REGISTER + E132XS_G13: set_global_register(cpustate, 13, info->i); break;
+ case CPUINFO_INT_REGISTER + E132XS_G14: set_global_register(cpustate, 14, info->i); break;
+ case CPUINFO_INT_REGISTER + E132XS_G15: set_global_register(cpustate, 15, info->i); break;
+ case CPUINFO_INT_REGISTER + E132XS_G16: set_global_register(cpustate, 16, info->i); break;
+ case CPUINFO_INT_REGISTER + E132XS_G17: set_global_register(cpustate, 17, info->i); break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + E132XS_SP: SP = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_UB: UB = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_BCR: BCR = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_TPR: TPR = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_TCR: TCR = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_TR: set_global_register(cpustate, TR_REGISTER, info->i); break;
+ case CPUINFO_INT_REGISTER + E132XS_WCR: WCR = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_ISR: ISR = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_FCR: FCR = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_MCR: MCR = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_G28: set_global_register(cpustate, 28, info->i); break;
+ case CPUINFO_INT_REGISTER + E132XS_G29: set_global_register(cpustate, 29, info->i); break;
+ case CPUINFO_INT_REGISTER + E132XS_G30: set_global_register(cpustate, 30, info->i); break;
+ case CPUINFO_INT_REGISTER + E132XS_G31: set_global_register(cpustate, 31, info->i); break;
+ case CPUINFO_INT_REGISTER + E132XS_CL0: cpustate->local_regs[(0 + GET_FP) % 64] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_CL1: cpustate->local_regs[(1 + GET_FP) % 64] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_CL2: cpustate->local_regs[(2 + GET_FP) % 64] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_CL3: cpustate->local_regs[(3 + GET_FP) % 64] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_CL4: cpustate->local_regs[(4 + GET_FP) % 64] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_CL5: cpustate->local_regs[(5 + GET_FP) % 64] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_CL6: cpustate->local_regs[(6 + GET_FP) % 64] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_CL7: cpustate->local_regs[(7 + GET_FP) % 64] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_CL8: cpustate->local_regs[(8 + GET_FP) % 64] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_CL9: cpustate->local_regs[(9 + GET_FP) % 64] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_CL10: cpustate->local_regs[(10 + GET_FP) % 64] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_CL11: cpustate->local_regs[(11 + GET_FP) % 64] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_CL12: cpustate->local_regs[(12 + GET_FP) % 64] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_CL13: cpustate->local_regs[(13 + GET_FP) % 64] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_CL14: cpustate->local_regs[(14 + GET_FP) % 64] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_CL15: cpustate->local_regs[(15 + GET_FP) % 64] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L0: cpustate->local_regs[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L1: cpustate->local_regs[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L2: cpustate->local_regs[2] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L3: cpustate->local_regs[3] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L4: cpustate->local_regs[4] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L5: cpustate->local_regs[5] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L6: cpustate->local_regs[6] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L7: cpustate->local_regs[7] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L8: cpustate->local_regs[8] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L9: cpustate->local_regs[9] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L10: cpustate->local_regs[10] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L11: cpustate->local_regs[11] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L12: cpustate->local_regs[12] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L13: cpustate->local_regs[13] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L14: cpustate->local_regs[14] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L15: cpustate->local_regs[15] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L16: cpustate->local_regs[16] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L17: cpustate->local_regs[17] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L18: cpustate->local_regs[18] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L19: cpustate->local_regs[19] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L20: cpustate->local_regs[20] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L21: cpustate->local_regs[21] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L22: cpustate->local_regs[22] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L23: cpustate->local_regs[23] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L24: cpustate->local_regs[24] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L25: cpustate->local_regs[25] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L26: cpustate->local_regs[26] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L27: cpustate->local_regs[27] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L28: cpustate->local_regs[28] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L29: cpustate->local_regs[29] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L30: cpustate->local_regs[30] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L31: cpustate->local_regs[31] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L32: cpustate->local_regs[32] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L33: cpustate->local_regs[33] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L34: cpustate->local_regs[34] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L35: cpustate->local_regs[35] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L36: cpustate->local_regs[36] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L37: cpustate->local_regs[37] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L38: cpustate->local_regs[38] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L39: cpustate->local_regs[39] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L40: cpustate->local_regs[40] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L41: cpustate->local_regs[41] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L42: cpustate->local_regs[42] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L43: cpustate->local_regs[43] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L44: cpustate->local_regs[44] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L45: cpustate->local_regs[45] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L46: cpustate->local_regs[46] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L47: cpustate->local_regs[47] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L48: cpustate->local_regs[48] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L49: cpustate->local_regs[49] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L50: cpustate->local_regs[50] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L51: cpustate->local_regs[51] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L52: cpustate->local_regs[52] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L53: cpustate->local_regs[53] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L54: cpustate->local_regs[54] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L55: cpustate->local_regs[55] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L56: cpustate->local_regs[56] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L57: cpustate->local_regs[57] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L58: cpustate->local_regs[58] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L59: cpustate->local_regs[59] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L60: cpustate->local_regs[60] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L61: cpustate->local_regs[61] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L62: cpustate->local_regs[62] = info->i; break;
+ case CPUINFO_INT_REGISTER + E132XS_L63: cpustate->local_regs[63] = info->i; break;
+
+ case CPUINFO_INT_INPUT_STATE + 0: set_irq_line(cpustate, 0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + 1: set_irq_line(cpustate, 1, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + 2: set_irq_line(cpustate, 2, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + 3: set_irq_line(cpustate, 3, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + 4: set_irq_line(cpustate, 4, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + 5: set_irq_line(cpustate, 5, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + 6: set_irq_line(cpustate, 6, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + 7: set_irq_line(cpustate, 7, info->i); break;
+ }
+}
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+static CPU_GET_INFO( hyperstone )
+{
+ hyperstone_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(hyperstone_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 8; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 2; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 6; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 36; break;
+
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 15; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_INPUT_STATE + 0: /* not implemented */ break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = PPC; break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + E132XS_PC: info->i = PC; break;
+ case CPUINFO_INT_REGISTER + E132XS_SR: info->i = SR; break;
+ case CPUINFO_INT_REGISTER + E132XS_FER: info->i = FER; break;
+ case CPUINFO_INT_REGISTER + E132XS_G3: info->i = get_global_register(cpustate, 3); break;
+ case CPUINFO_INT_REGISTER + E132XS_G4: info->i = get_global_register(cpustate, 4); break;
+ case CPUINFO_INT_REGISTER + E132XS_G5: info->i = get_global_register(cpustate, 5); break;
+ case CPUINFO_INT_REGISTER + E132XS_G6: info->i = get_global_register(cpustate, 6); break;
+ case CPUINFO_INT_REGISTER + E132XS_G7: info->i = get_global_register(cpustate, 7); break;
+ case CPUINFO_INT_REGISTER + E132XS_G8: info->i = get_global_register(cpustate, 8); break;
+ case CPUINFO_INT_REGISTER + E132XS_G9: info->i = get_global_register(cpustate, 9); break;
+ case CPUINFO_INT_REGISTER + E132XS_G10: info->i = get_global_register(cpustate, 10); break;
+ case CPUINFO_INT_REGISTER + E132XS_G11: info->i = get_global_register(cpustate, 11); break;
+ case CPUINFO_INT_REGISTER + E132XS_G12: info->i = get_global_register(cpustate, 12); break;
+ case CPUINFO_INT_REGISTER + E132XS_G13: info->i = get_global_register(cpustate, 13); break;
+ case CPUINFO_INT_REGISTER + E132XS_G14: info->i = get_global_register(cpustate, 14); break;
+ case CPUINFO_INT_REGISTER + E132XS_G15: info->i = get_global_register(cpustate, 15); break;
+ case CPUINFO_INT_REGISTER + E132XS_G16: info->i = get_global_register(cpustate, 16); break;
+ case CPUINFO_INT_REGISTER + E132XS_G17: info->i = get_global_register(cpustate, 17); break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + E132XS_SP: info->i = SP; break;
+ case CPUINFO_INT_REGISTER + E132XS_UB: info->i = UB; break;
+ case CPUINFO_INT_REGISTER + E132XS_BCR: info->i = BCR; break;
+ case CPUINFO_INT_REGISTER + E132XS_TPR: info->i = TPR; break;
+ case CPUINFO_INT_REGISTER + E132XS_TCR: info->i = TCR; break;
+ case CPUINFO_INT_REGISTER + E132XS_TR: info->i = TR; break;
+ case CPUINFO_INT_REGISTER + E132XS_WCR: info->i = WCR; break;
+ case CPUINFO_INT_REGISTER + E132XS_ISR: info->i = ISR; break;
+ case CPUINFO_INT_REGISTER + E132XS_FCR: info->i = FCR; break;
+ case CPUINFO_INT_REGISTER + E132XS_MCR: info->i = MCR; break;
+ case CPUINFO_INT_REGISTER + E132XS_G28: info->i = get_global_register(cpustate, 28); break;
+ case CPUINFO_INT_REGISTER + E132XS_G29: info->i = get_global_register(cpustate, 29); break;
+ case CPUINFO_INT_REGISTER + E132XS_G30: info->i = get_global_register(cpustate, 30); break;
+ case CPUINFO_INT_REGISTER + E132XS_G31: info->i = get_global_register(cpustate, 31); break;
+ case CPUINFO_INT_REGISTER + E132XS_CL0: info->i = cpustate->local_regs[(0 + GET_FP) % 64]; break;
+ case CPUINFO_INT_REGISTER + E132XS_CL1: info->i = cpustate->local_regs[(1 + GET_FP) % 64]; break;
+ case CPUINFO_INT_REGISTER + E132XS_CL2: info->i = cpustate->local_regs[(2 + GET_FP) % 64]; break;
+ case CPUINFO_INT_REGISTER + E132XS_CL3: info->i = cpustate->local_regs[(3 + GET_FP) % 64]; break;
+ case CPUINFO_INT_REGISTER + E132XS_CL4: info->i = cpustate->local_regs[(4 + GET_FP) % 64]; break;
+ case CPUINFO_INT_REGISTER + E132XS_CL5: info->i = cpustate->local_regs[(5 + GET_FP) % 64]; break;
+ case CPUINFO_INT_REGISTER + E132XS_CL6: info->i = cpustate->local_regs[(6 + GET_FP) % 64]; break;
+ case CPUINFO_INT_REGISTER + E132XS_CL7: info->i = cpustate->local_regs[(7 + GET_FP) % 64]; break;
+ case CPUINFO_INT_REGISTER + E132XS_CL8: info->i = cpustate->local_regs[(8 + GET_FP) % 64]; break;
+ case CPUINFO_INT_REGISTER + E132XS_CL9: info->i = cpustate->local_regs[(9 + GET_FP) % 64]; break;
+ case CPUINFO_INT_REGISTER + E132XS_CL10: info->i = cpustate->local_regs[(10 + GET_FP) % 64]; break;
+ case CPUINFO_INT_REGISTER + E132XS_CL11: info->i = cpustate->local_regs[(11 + GET_FP) % 64]; break;
+ case CPUINFO_INT_REGISTER + E132XS_CL12: info->i = cpustate->local_regs[(12 + GET_FP) % 64]; break;
+ case CPUINFO_INT_REGISTER + E132XS_CL13: info->i = cpustate->local_regs[(13 + GET_FP) % 64]; break;
+ case CPUINFO_INT_REGISTER + E132XS_CL14: info->i = cpustate->local_regs[(14 + GET_FP) % 64]; break;
+ case CPUINFO_INT_REGISTER + E132XS_CL15: info->i = cpustate->local_regs[(15 + GET_FP) % 64]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L0: info->i = cpustate->local_regs[0]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L1: info->i = cpustate->local_regs[1]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L2: info->i = cpustate->local_regs[2]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L3: info->i = cpustate->local_regs[3]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L4: info->i = cpustate->local_regs[4]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L5: info->i = cpustate->local_regs[5]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L6: info->i = cpustate->local_regs[6]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L7: info->i = cpustate->local_regs[7]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L8: info->i = cpustate->local_regs[8]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L9: info->i = cpustate->local_regs[9]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L10: info->i = cpustate->local_regs[10]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L11: info->i = cpustate->local_regs[11]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L12: info->i = cpustate->local_regs[12]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L13: info->i = cpustate->local_regs[13]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L14: info->i = cpustate->local_regs[14]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L15: info->i = cpustate->local_regs[15]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L16: info->i = cpustate->local_regs[16]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L17: info->i = cpustate->local_regs[17]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L18: info->i = cpustate->local_regs[18]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L19: info->i = cpustate->local_regs[19]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L20: info->i = cpustate->local_regs[20]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L21: info->i = cpustate->local_regs[21]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L22: info->i = cpustate->local_regs[22]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L23: info->i = cpustate->local_regs[23]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L24: info->i = cpustate->local_regs[24]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L25: info->i = cpustate->local_regs[25]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L26: info->i = cpustate->local_regs[26]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L27: info->i = cpustate->local_regs[27]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L28: info->i = cpustate->local_regs[28]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L29: info->i = cpustate->local_regs[29]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L30: info->i = cpustate->local_regs[30]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L31: info->i = cpustate->local_regs[31]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L32: info->i = cpustate->local_regs[32]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L33: info->i = cpustate->local_regs[33]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L34: info->i = cpustate->local_regs[34]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L35: info->i = cpustate->local_regs[35]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L36: info->i = cpustate->local_regs[36]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L37: info->i = cpustate->local_regs[37]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L38: info->i = cpustate->local_regs[38]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L39: info->i = cpustate->local_regs[39]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L40: info->i = cpustate->local_regs[40]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L41: info->i = cpustate->local_regs[41]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L42: info->i = cpustate->local_regs[42]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L43: info->i = cpustate->local_regs[43]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L44: info->i = cpustate->local_regs[44]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L45: info->i = cpustate->local_regs[45]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L46: info->i = cpustate->local_regs[46]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L47: info->i = cpustate->local_regs[47]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L48: info->i = cpustate->local_regs[48]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L49: info->i = cpustate->local_regs[49]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L50: info->i = cpustate->local_regs[50]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L51: info->i = cpustate->local_regs[51]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L52: info->i = cpustate->local_regs[52]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L53: info->i = cpustate->local_regs[53]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L54: info->i = cpustate->local_regs[54]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L55: info->i = cpustate->local_regs[55]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L56: info->i = cpustate->local_regs[56]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L57: info->i = cpustate->local_regs[57]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L58: info->i = cpustate->local_regs[58]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L59: info->i = cpustate->local_regs[59]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L60: info->i = cpustate->local_regs[60]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L61: info->i = cpustate->local_regs[61]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L62: info->i = cpustate->local_regs[62]; break;
+ case CPUINFO_INT_REGISTER + E132XS_L63: info->i = cpustate->local_regs[63]; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(hyperstone); break;
+ case CPUINFO_FCT_INIT: info->init = NULL; break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(hyperstone); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(hyperstone); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(hyperstone); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(hyperstone); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map16 = NULL; break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_IO: info->internal_map16 = NULL; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Hyperstone CPU"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "0.9"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Pierpaolo Prazzoli and Ryan Holtz"); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c%c%c%c%c%c%c%c%c%c%c FTE:%X FRM:%X ILC:%d FL:%d FP:%d",
+ GET_S ? 'S':'.',
+ GET_P ? 'P':'.',
+ GET_T ? 'T':'.',
+ GET_L ? 'L':'.',
+ GET_I ? 'I':'.',
+ cpustate->global_regs[1] & 0x00040 ? '?':'.',
+ GET_H ? 'H':'.',
+ GET_M ? 'M':'.',
+ GET_V ? 'V':'.',
+ GET_N ? 'N':'.',
+ GET_Z ? 'Z':'.',
+ GET_C ? 'C':'.',
+ GET_FTE,
+ GET_FRM,
+ GET_ILC,
+ GET_FL,
+ GET_FP);
+ break;
+
+ case CPUINFO_STR_REGISTER + E132XS_PC: sprintf(info->s, "PC :%08X", cpustate->global_regs[0]); break;
+ case CPUINFO_STR_REGISTER + E132XS_SR: sprintf(info->s, "SR :%08X", cpustate->global_regs[1]); break;
+ case CPUINFO_STR_REGISTER + E132XS_FER: sprintf(info->s, "FER :%08X", cpustate->global_regs[2]); break;
+ case CPUINFO_STR_REGISTER + E132XS_G3: sprintf(info->s, "G3 :%08X", cpustate->global_regs[3]); break;
+ case CPUINFO_STR_REGISTER + E132XS_G4: sprintf(info->s, "G4 :%08X", cpustate->global_regs[4]); break;
+ case CPUINFO_STR_REGISTER + E132XS_G5: sprintf(info->s, "G5 :%08X", cpustate->global_regs[5]); break;
+ case CPUINFO_STR_REGISTER + E132XS_G6: sprintf(info->s, "G6 :%08X", cpustate->global_regs[6]); break;
+ case CPUINFO_STR_REGISTER + E132XS_G7: sprintf(info->s, "G7 :%08X", cpustate->global_regs[7]); break;
+ case CPUINFO_STR_REGISTER + E132XS_G8: sprintf(info->s, "G8 :%08X", cpustate->global_regs[8]); break;
+ case CPUINFO_STR_REGISTER + E132XS_G9: sprintf(info->s, "G9 :%08X", cpustate->global_regs[9]); break;
+ case CPUINFO_STR_REGISTER + E132XS_G10: sprintf(info->s, "G10 :%08X", cpustate->global_regs[10]); break;
+ case CPUINFO_STR_REGISTER + E132XS_G11: sprintf(info->s, "G11 :%08X", cpustate->global_regs[11]); break;
+ case CPUINFO_STR_REGISTER + E132XS_G12: sprintf(info->s, "G12 :%08X", cpustate->global_regs[12]); break;
+ case CPUINFO_STR_REGISTER + E132XS_G13: sprintf(info->s, "G13 :%08X", cpustate->global_regs[13]); break;
+ case CPUINFO_STR_REGISTER + E132XS_G14: sprintf(info->s, "G14 :%08X", cpustate->global_regs[14]); break;
+ case CPUINFO_STR_REGISTER + E132XS_G15: sprintf(info->s, "G15 :%08X", cpustate->global_regs[15]); break;
+ case CPUINFO_STR_REGISTER + E132XS_G16: sprintf(info->s, "G16 :%08X", cpustate->global_regs[16]); break;
+ case CPUINFO_STR_REGISTER + E132XS_G17: sprintf(info->s, "G17 :%08X", cpustate->global_regs[17]); break;
+ case CPUINFO_STR_REGISTER + E132XS_SP: sprintf(info->s, "SP :%08X", cpustate->global_regs[18]); break;
+ case CPUINFO_STR_REGISTER + E132XS_UB: sprintf(info->s, "UB :%08X", cpustate->global_regs[19]); break;
+ case CPUINFO_STR_REGISTER + E132XS_BCR: sprintf(info->s, "BCR :%08X", cpustate->global_regs[20]); break;
+ case CPUINFO_STR_REGISTER + E132XS_TPR: sprintf(info->s, "TPR :%08X", cpustate->global_regs[21]); break;
+ case CPUINFO_STR_REGISTER + E132XS_TCR: sprintf(info->s, "TCR :%08X", cpustate->global_regs[22]); break;
+ case CPUINFO_STR_REGISTER + E132XS_TR: sprintf(info->s, "TR :%08X", cpustate->global_regs[23]); break;
+ case CPUINFO_STR_REGISTER + E132XS_WCR: sprintf(info->s, "WCR :%08X", cpustate->global_regs[24]); break;
+ case CPUINFO_STR_REGISTER + E132XS_ISR: sprintf(info->s, "ISR :%08X", cpustate->global_regs[25]); break;
+ case CPUINFO_STR_REGISTER + E132XS_FCR: sprintf(info->s, "FCR :%08X", cpustate->global_regs[26]); break;
+ case CPUINFO_STR_REGISTER + E132XS_MCR: sprintf(info->s, "MCR :%08X", cpustate->global_regs[27]); break;
+ case CPUINFO_STR_REGISTER + E132XS_G28: sprintf(info->s, "G28 :%08X", cpustate->global_regs[28]); break;
+ case CPUINFO_STR_REGISTER + E132XS_G29: sprintf(info->s, "G29 :%08X", cpustate->global_regs[29]); break;
+ case CPUINFO_STR_REGISTER + E132XS_G30: sprintf(info->s, "G30 :%08X", cpustate->global_regs[30]); break;
+ case CPUINFO_STR_REGISTER + E132XS_G31: sprintf(info->s, "G31 :%08X", cpustate->global_regs[31]); break;
+ case CPUINFO_STR_REGISTER + E132XS_CL0: sprintf(info->s, "CL0 :%08X", cpustate->local_regs[(0 + GET_FP) % 64]); break;
+ case CPUINFO_STR_REGISTER + E132XS_CL1: sprintf(info->s, "CL1 :%08X", cpustate->local_regs[(1 + GET_FP) % 64]); break;
+ case CPUINFO_STR_REGISTER + E132XS_CL2: sprintf(info->s, "CL2 :%08X", cpustate->local_regs[(2 + GET_FP) % 64]); break;
+ case CPUINFO_STR_REGISTER + E132XS_CL3: sprintf(info->s, "CL3 :%08X", cpustate->local_regs[(3 + GET_FP) % 64]); break;
+ case CPUINFO_STR_REGISTER + E132XS_CL4: sprintf(info->s, "CL4 :%08X", cpustate->local_regs[(4 + GET_FP) % 64]); break;
+ case CPUINFO_STR_REGISTER + E132XS_CL5: sprintf(info->s, "CL5 :%08X", cpustate->local_regs[(5 + GET_FP) % 64]); break;
+ case CPUINFO_STR_REGISTER + E132XS_CL6: sprintf(info->s, "CL6 :%08X", cpustate->local_regs[(6 + GET_FP) % 64]); break;
+ case CPUINFO_STR_REGISTER + E132XS_CL7: sprintf(info->s, "CL7 :%08X", cpustate->local_regs[(7 + GET_FP) % 64]); break;
+ case CPUINFO_STR_REGISTER + E132XS_CL8: sprintf(info->s, "CL8 :%08X", cpustate->local_regs[(8 + GET_FP) % 64]); break;
+ case CPUINFO_STR_REGISTER + E132XS_CL9: sprintf(info->s, "CL9 :%08X", cpustate->local_regs[(9 + GET_FP) % 64]); break;
+ case CPUINFO_STR_REGISTER + E132XS_CL10: sprintf(info->s, "CL10:%08X", cpustate->local_regs[(10 + GET_FP) % 64]); break;
+ case CPUINFO_STR_REGISTER + E132XS_CL11: sprintf(info->s, "CL11:%08X", cpustate->local_regs[(11 + GET_FP) % 64]); break;
+ case CPUINFO_STR_REGISTER + E132XS_CL12: sprintf(info->s, "CL12:%08X", cpustate->local_regs[(12 + GET_FP) % 64]); break;
+ case CPUINFO_STR_REGISTER + E132XS_CL13: sprintf(info->s, "CL13:%08X", cpustate->local_regs[(13 + GET_FP) % 64]); break;
+ case CPUINFO_STR_REGISTER + E132XS_CL14: sprintf(info->s, "CL14:%08X", cpustate->local_regs[(14 + GET_FP) % 64]); break;
+ case CPUINFO_STR_REGISTER + E132XS_CL15: sprintf(info->s, "CL15:%08X", cpustate->local_regs[(15 + GET_FP) % 64]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L0: sprintf(info->s, "L0 :%08X", cpustate->local_regs[0]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L1: sprintf(info->s, "L1 :%08X", cpustate->local_regs[1]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L2: sprintf(info->s, "L2 :%08X", cpustate->local_regs[2]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L3: sprintf(info->s, "L3 :%08X", cpustate->local_regs[3]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L4: sprintf(info->s, "L4 :%08X", cpustate->local_regs[4]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L5: sprintf(info->s, "L5 :%08X", cpustate->local_regs[5]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L6: sprintf(info->s, "L6 :%08X", cpustate->local_regs[6]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L7: sprintf(info->s, "L7 :%08X", cpustate->local_regs[7]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L8: sprintf(info->s, "L8 :%08X", cpustate->local_regs[8]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L9: sprintf(info->s, "L9 :%08X", cpustate->local_regs[9]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L10: sprintf(info->s, "L10 :%08X", cpustate->local_regs[10]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L11: sprintf(info->s, "L11 :%08X", cpustate->local_regs[11]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L12: sprintf(info->s, "L12 :%08X", cpustate->local_regs[12]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L13: sprintf(info->s, "L13 :%08X", cpustate->local_regs[13]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L14: sprintf(info->s, "L14 :%08X", cpustate->local_regs[14]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L15: sprintf(info->s, "L15 :%08X", cpustate->local_regs[15]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L16: sprintf(info->s, "L16 :%08X", cpustate->local_regs[16]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L17: sprintf(info->s, "L17 :%08X", cpustate->local_regs[17]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L18: sprintf(info->s, "L18 :%08X", cpustate->local_regs[18]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L19: sprintf(info->s, "L19 :%08X", cpustate->local_regs[19]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L20: sprintf(info->s, "L20 :%08X", cpustate->local_regs[20]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L21: sprintf(info->s, "L21 :%08X", cpustate->local_regs[21]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L22: sprintf(info->s, "L22 :%08X", cpustate->local_regs[22]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L23: sprintf(info->s, "L23 :%08X", cpustate->local_regs[23]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L24: sprintf(info->s, "L24 :%08X", cpustate->local_regs[24]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L25: sprintf(info->s, "L25 :%08X", cpustate->local_regs[25]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L26: sprintf(info->s, "L26 :%08X", cpustate->local_regs[26]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L27: sprintf(info->s, "L27 :%08X", cpustate->local_regs[27]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L28: sprintf(info->s, "L28 :%08X", cpustate->local_regs[28]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L29: sprintf(info->s, "L29 :%08X", cpustate->local_regs[29]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L30: sprintf(info->s, "L30 :%08X", cpustate->local_regs[30]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L31: sprintf(info->s, "L31 :%08X", cpustate->local_regs[31]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L32: sprintf(info->s, "L32 :%08X", cpustate->local_regs[32]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L33: sprintf(info->s, "L33 :%08X", cpustate->local_regs[33]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L34: sprintf(info->s, "L34 :%08X", cpustate->local_regs[34]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L35: sprintf(info->s, "L35 :%08X", cpustate->local_regs[35]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L36: sprintf(info->s, "L36 :%08X", cpustate->local_regs[36]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L37: sprintf(info->s, "L37 :%08X", cpustate->local_regs[37]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L38: sprintf(info->s, "L38 :%08X", cpustate->local_regs[38]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L39: sprintf(info->s, "L39 :%08X", cpustate->local_regs[39]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L40: sprintf(info->s, "L40 :%08X", cpustate->local_regs[40]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L41: sprintf(info->s, "L41 :%08X", cpustate->local_regs[41]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L42: sprintf(info->s, "L42 :%08X", cpustate->local_regs[42]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L43: sprintf(info->s, "L43 :%08X", cpustate->local_regs[43]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L44: sprintf(info->s, "L44 :%08X", cpustate->local_regs[44]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L45: sprintf(info->s, "L45 :%08X", cpustate->local_regs[45]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L46: sprintf(info->s, "L46 :%08X", cpustate->local_regs[46]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L47: sprintf(info->s, "L47 :%08X", cpustate->local_regs[47]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L48: sprintf(info->s, "L48 :%08X", cpustate->local_regs[48]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L49: sprintf(info->s, "L49 :%08X", cpustate->local_regs[49]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L50: sprintf(info->s, "L50 :%08X", cpustate->local_regs[50]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L51: sprintf(info->s, "L51 :%08X", cpustate->local_regs[51]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L52: sprintf(info->s, "L52 :%08X", cpustate->local_regs[52]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L53: sprintf(info->s, "L53 :%08X", cpustate->local_regs[53]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L54: sprintf(info->s, "L54 :%08X", cpustate->local_regs[54]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L55: sprintf(info->s, "L55 :%08X", cpustate->local_regs[55]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L56: sprintf(info->s, "L56 :%08X", cpustate->local_regs[56]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L57: sprintf(info->s, "L57 :%08X", cpustate->local_regs[57]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L58: sprintf(info->s, "L58 :%08X", cpustate->local_regs[58]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L59: sprintf(info->s, "L59 :%08X", cpustate->local_regs[59]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L60: sprintf(info->s, "L60 :%08X", cpustate->local_regs[60]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L61: sprintf(info->s, "L61 :%08X", cpustate->local_regs[61]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L62: sprintf(info->s, "L62 :%08X", cpustate->local_regs[62]); break;
+ case CPUINFO_STR_REGISTER + E132XS_L63: sprintf(info->s, "L63 :%08X", cpustate->local_regs[63]); break;
+ }
+}
+
+
+CPU_GET_INFO( e116t )
+{
+ switch (state)
+ {
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 16; break;
+
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map16 = ADDRESS_MAP_NAME(e116_4k_iram_map); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(e116t); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "E1-16T"); break;
+
+ default:
+ CPU_GET_INFO_CALL(hyperstone);
+ }
+}
+
+CPU_GET_INFO( e116xt )
+{
+ switch (state)
+ {
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 16; break;
+
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map16 = ADDRESS_MAP_NAME(e116_8k_iram_map); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(e116xt); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "E1-16XT"); break;
+
+ default:
+ CPU_GET_INFO_CALL(hyperstone);
+ }
+}
+
+CPU_GET_INFO( e116xs )
+{
+ switch (state)
+ {
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 16; break;
+
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map16 = ADDRESS_MAP_NAME(e116_16k_iram_map); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(e116xs); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "E1-16XS"); break;
+
+ default:
+ CPU_GET_INFO_CALL(hyperstone);
+ }
+}
+
+CPU_GET_INFO( e116xsr )
+{
+ switch (state)
+ {
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 16; break;
+
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map16 = ADDRESS_MAP_NAME(e116_16k_iram_map); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(e116xsr); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "E1-16XSR"); break;
+
+ default:
+ CPU_GET_INFO_CALL(hyperstone);
+ }
+}
+
+CPU_GET_INFO( e132n )
+{
+ switch (state)
+ {
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 32; break;
+
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map32 = ADDRESS_MAP_NAME(e132_4k_iram_map); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(e132n); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "E1-32N"); break;
+
+ default:
+ CPU_GET_INFO_CALL(hyperstone);
+ }
+}
+
+CPU_GET_INFO( e132t )
+{
+ switch (state)
+ {
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 32; break;
+
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map32 = ADDRESS_MAP_NAME(e132_4k_iram_map); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(e132t); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "E1-32T"); break;
+
+ default:
+ CPU_GET_INFO_CALL(hyperstone);
+ }
+}
+
+CPU_GET_INFO( e132xn )
+{
+ switch (state)
+ {
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 32; break;
+
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map32 = ADDRESS_MAP_NAME(e132_8k_iram_map); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(e132xn); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "E1-32XN"); break;
+
+ default:
+ CPU_GET_INFO_CALL(hyperstone);
+ }
+}
+
+CPU_GET_INFO( e132xt )
+{
+ switch (state)
+ {
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 32; break;
+
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map32 = ADDRESS_MAP_NAME(e132_8k_iram_map); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(e132xt); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "E1-32XT"); break;
+
+ default:
+ CPU_GET_INFO_CALL(hyperstone);
+ }
+}
+
+CPU_GET_INFO( e132xs )
+{
+ switch (state)
+ {
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 32; break;
+
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map32 = ADDRESS_MAP_NAME(e132_16k_iram_map); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(e132xs); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "E1-32XS"); break;
+
+ default:
+ CPU_GET_INFO_CALL(hyperstone);
+ }
+}
+
+CPU_GET_INFO( e132xsr )
+{
+ switch (state)
+ {
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 32; break;
+
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map32 = ADDRESS_MAP_NAME(e132_16k_iram_map); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(e132xsr); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "E1-32XSR"); break;
+
+ default:
+ CPU_GET_INFO_CALL(hyperstone);
+ }
+}
+
+CPU_GET_INFO( gms30c2116 )
+{
+ switch (state)
+ {
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 16; break;
+
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map16 = ADDRESS_MAP_NAME(e116_4k_iram_map); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(gms30c2116); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "GMS30C2116"); break;
+
+ default:
+ CPU_GET_INFO_CALL(hyperstone);
+ }
+}
+
+CPU_GET_INFO( gms30c2132 )
+{
+ switch (state)
+ {
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 32; break;
+
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map32 = ADDRESS_MAP_NAME(e132_4k_iram_map); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(gms30c2132); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "GMS30C2132"); break;
+
+ default:
+ CPU_GET_INFO_CALL(hyperstone);
+ }
+}
+
+CPU_GET_INFO( gms30c2216 )
+{
+ switch (state)
+ {
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 16; break;
+
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map16 = ADDRESS_MAP_NAME(e116_8k_iram_map); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(gms30c2216); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "GMS30C2216"); break;
+
+ default:
+ CPU_GET_INFO_CALL(hyperstone);
+ }
+}
+
+CPU_GET_INFO( gms30c2232 )
+{
+ switch (state)
+ {
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 32; break;
+
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map32 = ADDRESS_MAP_NAME(e132_8k_iram_map); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(gms30c2232); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "GMS30C2232"); break;
+
+ default:
+ CPU_GET_INFO_CALL(hyperstone);
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(E116T, e116t);
+DEFINE_LEGACY_CPU_DEVICE(E116XT, e116xt);
+DEFINE_LEGACY_CPU_DEVICE(E116XS, e116xs);
+DEFINE_LEGACY_CPU_DEVICE(E116XSR, e116xsr);
+DEFINE_LEGACY_CPU_DEVICE(E132N, e132n);
+DEFINE_LEGACY_CPU_DEVICE(E132T, e132t);
+DEFINE_LEGACY_CPU_DEVICE(E132XN, e132xn);
+DEFINE_LEGACY_CPU_DEVICE(E132XT, e132xt);
+DEFINE_LEGACY_CPU_DEVICE(E132XS, e132xs);
+DEFINE_LEGACY_CPU_DEVICE(E132XSR, e132xsr);
+DEFINE_LEGACY_CPU_DEVICE(GMS30C2116, gms30c2116);
+DEFINE_LEGACY_CPU_DEVICE(GMS30C2132, gms30c2132);
+DEFINE_LEGACY_CPU_DEVICE(GMS30C2216, gms30c2216);
+DEFINE_LEGACY_CPU_DEVICE(GMS30C2232, gms30c2232);
diff --git a/trunk/src/emu/cpu/e132xs/e132xs.h b/trunk/src/emu/cpu/e132xs/e132xs.h
new file mode 100644
index 00000000000..04123db53a0
--- /dev/null
+++ b/trunk/src/emu/cpu/e132xs/e132xs.h
@@ -0,0 +1,156 @@
+#pragma once
+
+#ifndef __E132XS_H__
+#define __E132XS_H__
+
+
+/*
+ A note about clock multipliers and dividers:
+
+ E1-16[T] and E1-32[T] accept a straight clock
+
+ E1-16X[T|N] and E1-32X[T|N] accept a clock and multiply it
+ internally by 4; in the emulator, you MUST specify 4 * XTAL
+ to achieve the correct speed
+
+ E1-16XS[R] and E1-32XS[R] accept a clock and multiply it
+ internally by 8; in the emulator, you MUST specify 8 * XTAL
+ to achieve the correct speed
+*/
+
+
+
+/* Functions */
+
+DECLARE_LEGACY_CPU_DEVICE(E116T, e116t);
+DECLARE_LEGACY_CPU_DEVICE(E116XT, e116xt);
+DECLARE_LEGACY_CPU_DEVICE(E116XS, e116xs);
+DECLARE_LEGACY_CPU_DEVICE(E116XSR, e116xsr);
+DECLARE_LEGACY_CPU_DEVICE(E132N, e132n);
+DECLARE_LEGACY_CPU_DEVICE(E132T, e132t);
+DECLARE_LEGACY_CPU_DEVICE(E132XN, e132xn);
+DECLARE_LEGACY_CPU_DEVICE(E132XT, e132xt);
+DECLARE_LEGACY_CPU_DEVICE(E132XS, e132xs);
+DECLARE_LEGACY_CPU_DEVICE(E132XSR, e132xsr);
+DECLARE_LEGACY_CPU_DEVICE(GMS30C2116, gms30c2116);
+DECLARE_LEGACY_CPU_DEVICE(GMS30C2132, gms30c2132);
+DECLARE_LEGACY_CPU_DEVICE(GMS30C2216, gms30c2216);
+DECLARE_LEGACY_CPU_DEVICE(GMS30C2232, gms30c2232);
+
+
+extern unsigned dasm_hyperstone(char *buffer, unsigned pc, const UINT8 *oprom, unsigned h_flag, int private_fp);
+
+/* Memory access */
+/* read byte */
+#define READ_B(H,addr) (H)->program->read_byte((addr))
+/* read half-word */
+#define READ_HW(H,addr) (H)->program->read_word((addr) & ~1)
+/* read word */
+#define READ_W(H,addr) (H)->program->read_dword((addr) & ~3)
+
+/* write byte */
+#define WRITE_B(H,addr, data) (H)->program->write_byte(addr, data)
+/* write half-word */
+#define WRITE_HW(H,addr, data) (H)->program->write_word((addr) & ~1, data)
+/* write word */
+#define WRITE_W(H,addr, data) (H)->program->write_dword((addr) & ~3, data)
+
+
+/* I/O access */
+/* read word */
+#define IO_READ_W(H,addr) (H)->io->read_dword(((addr) >> 11) & 0x7ffc)
+/* write word */
+#define IO_WRITE_W(H,addr, data) (H)->io->write_dword(((addr) >> 11) & 0x7ffc, data)
+
+
+#define READ_OP(H,addr) (H)->direct->read_decrypted_word((addr), (H)->opcodexor)
+
+
+/* Registers Number */
+#define PC_REGISTER 0
+#define SR_REGISTER 1
+#define BCR_REGISTER 20
+#define TPR_REGISTER 21
+#define TCR_REGISTER 22
+#define TR_REGISTER 23
+#define ISR_REGISTER 25
+#define FCR_REGISTER 26
+#define MCR_REGISTER 27
+
+#define X_CODE(val) ((val & 0x7000) >> 12)
+#define E_BIT(val) ((val & 0x8000) >> 15)
+#define S_BIT_CONST(val) ((val & 0x4000) >> 14)
+#define DD(val) ((val & 0x3000) >> 12)
+
+
+/* Extended DSP instructions */
+#define EMUL 0x102
+#define EMULU 0x104
+#define EMULS 0x106
+#define EMAC 0x10a
+#define EMACD 0x10e
+#define EMSUB 0x11a
+#define EMSUBD 0x11e
+#define EHMAC 0x02a
+#define EHMACD 0x02e
+#define EHCMULD 0x046
+#define EHCMACD 0x04e
+#define EHCSUMD 0x086
+#define EHCFFTD 0x096
+#define EHCFFTSD 0x296
+
+/* Delay values */
+#define NO_DELAY 0
+#define DELAY_EXECUTE 1
+
+/* IRQ numbers */
+#define IRQ_INT1 0
+#define IRQ_INT2 1
+#define IRQ_INT3 2
+#define IRQ_INT4 3
+#define IRQ_IO1 4
+#define IRQ_IO2 5
+#define IRQ_IO3 6
+
+/* Trap numbers */
+#define TRAPNO_IO2 48
+#define TRAPNO_IO1 49
+#define TRAPNO_INT4 50
+#define TRAPNO_INT3 51
+#define TRAPNO_INT2 52
+#define TRAPNO_INT1 53
+#define TRAPNO_IO3 54
+#define TRAPNO_TIMER 55
+#define TRAPNO_RESERVED1 56
+#define TRAPNO_TRACE_EXCEPTION 57
+#define TRAPNO_PARITY_ERROR 58
+#define TRAPNO_EXTENDED_OVERFLOW 59
+#define TRAPNO_RANGE_ERROR 60
+#define TRAPNO_PRIVILEGE_ERROR TRAPNO_RANGE_ERROR
+#define TRAPNO_FRAME_ERROR TRAPNO_RANGE_ERROR
+#define TRAPNO_RESERVED2 61
+#define TRAPNO_RESET 62 // reserved if not mapped @ MEM3
+#define TRAPNO_ERROR_ENTRY 63 // for instruction code of all ones
+
+/* Traps code */
+#define TRAPLE 4
+#define TRAPGT 5
+#define TRAPLT 6
+#define TRAPGE 7
+#define TRAPSE 8
+#define TRAPHT 9
+#define TRAPST 10
+#define TRAPHE 11
+#define TRAPE 12
+#define TRAPNE 13
+#define TRAPV 14
+#define TRAP 15
+
+/* Entry point to get trap locations or emulated code associated */
+#define E132XS_ENTRY_MEM0 0
+#define E132XS_ENTRY_MEM1 1
+#define E132XS_ENTRY_MEM2 2
+#define E132XS_ENTRY_IRAM 3
+#define E132XS_ENTRY_MEM3 7
+
+#endif /* __E132XS_H__ */
diff --git a/trunk/src/emu/cpu/e132xs/e132xsop.c b/trunk/src/emu/cpu/e132xs/e132xsop.c
new file mode 100644
index 00000000000..6b45d15edb3
--- /dev/null
+++ b/trunk/src/emu/cpu/e132xs/e132xsop.c
@@ -0,0 +1,1925 @@
+#define LOCAL_DECODE_INIT \
+ struct regs_decode decode_state; \
+ struct regs_decode *decode = &decode_state; \
+\
+ /* clear 'current regs / flags' */ \
+ decode->src = 0; \
+ decode->dst = 0; \
+ decode->src_value = 0; \
+ decode->next_src_value = 0; \
+ decode->dst_value = 0; \
+ decode->next_dst_value = 0; \
+ decode->sub_type = 0; \
+ decode->extra.u = 0; \
+ decode->src_is_local = 0; \
+ decode->dst_is_local = 0; \
+ decode->same_src_dst = 0; \
+ decode->same_src_dstf = 0; \
+ decode->same_srcf_dst = 0; \
+
+
+static void hyperstone_op00(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 0);
+ hyperstone_chk(cpustate, decode);
+}
+
+static void hyperstone_op01(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 1);
+ hyperstone_chk(cpustate, decode);
+}
+
+static void hyperstone_op02(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 0);
+ hyperstone_chk(cpustate, decode);
+}
+
+static void hyperstone_op03(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 1);
+ hyperstone_chk(cpustate, decode);
+}
+
+static void hyperstone_op04(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 0);
+ hyperstone_movd(cpustate, decode);
+}
+
+static void hyperstone_op05(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 1);
+ hyperstone_movd(cpustate, decode);
+}
+
+static void hyperstone_op06(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 0);
+ hyperstone_movd(cpustate, decode);
+}
+
+static void hyperstone_op07(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 1);
+ hyperstone_movd(cpustate, decode);
+}
+
+static void hyperstone_op08(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 0);
+ hyperstone_divu(cpustate, decode);
+}
+
+static void hyperstone_op09(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 1);
+ hyperstone_divu(cpustate, decode);
+}
+
+static void hyperstone_op0a(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 0);
+ hyperstone_divu(cpustate, decode);
+}
+
+static void hyperstone_op0b(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 1);
+ hyperstone_divu(cpustate, decode);
+}
+
+static void hyperstone_op0c(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 0);
+ hyperstone_divs(cpustate, decode);
+}
+
+static void hyperstone_op0d(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 1);
+ hyperstone_divs(cpustate, decode);
+}
+
+static void hyperstone_op0e(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 0);
+ hyperstone_divs(cpustate, decode);
+}
+
+static void hyperstone_op0f(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 1);
+ hyperstone_divs(cpustate, decode);
+}
+
+
+
+static void hyperstone_op10(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRlimdecode(decode, 0, 0);
+ hyperstone_xm(cpustate, decode);
+}
+
+static void hyperstone_op11(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRlimdecode(decode, 0, 1);
+ hyperstone_xm(cpustate, decode);
+}
+
+static void hyperstone_op12(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRlimdecode(decode, 1, 0);
+ hyperstone_xm(cpustate, decode);
+}
+
+static void hyperstone_op13(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRlimdecode(decode, 1, 1);
+ hyperstone_xm(cpustate, decode);
+}
+
+static void hyperstone_op14(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRconstdecode(decode, 0, 0);
+ hyperstone_mask(cpustate, decode);
+}
+
+static void hyperstone_op15(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRconstdecode(decode, 0, 1);
+ hyperstone_mask(cpustate, decode);
+}
+
+static void hyperstone_op16(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRconstdecode(decode, 1, 0);
+ hyperstone_mask(cpustate, decode);
+}
+
+static void hyperstone_op17(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRconstdecode(decode, 1, 1);
+ hyperstone_mask(cpustate, decode);
+}
+
+static void hyperstone_op18(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRconstdecode(decode, 0, 0);
+ hyperstone_sum(cpustate, decode);
+}
+
+static void hyperstone_op19(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRconstdecode(decode, 0, 1);
+ hyperstone_sum(cpustate, decode);
+}
+
+static void hyperstone_op1a(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRconstdecode(decode, 1, 0);
+ hyperstone_sum(cpustate, decode);
+}
+
+static void hyperstone_op1b(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRconstdecode(decode, 1, 1);
+ hyperstone_sum(cpustate, decode);
+}
+
+static void hyperstone_op1c(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRconstdecode(decode, 0, 0);
+ hyperstone_sums(cpustate, decode);
+}
+
+static void hyperstone_op1d(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRconstdecode(decode, 0, 1);
+ hyperstone_sums(cpustate, decode);
+}
+
+static void hyperstone_op1e(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRconstdecode(decode, 1, 0);
+ hyperstone_sums(cpustate, decode);
+}
+
+static void hyperstone_op1f(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRconstdecode(decode, 1, 1);
+ hyperstone_sums(cpustate, decode);
+}
+
+
+
+static void hyperstone_op20(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 0);
+ hyperstone_cmp(cpustate, decode);
+}
+
+static void hyperstone_op21(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 1);
+ hyperstone_cmp(cpustate, decode);
+}
+
+static void hyperstone_op22(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 0);
+ hyperstone_cmp(cpustate, decode);
+}
+
+static void hyperstone_op23(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 1);
+ hyperstone_cmp(cpustate, decode);
+}
+
+static void hyperstone_op24(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecodewithHflag(decode, 0, 0);
+ hyperstone_mov(cpustate, decode);
+}
+
+static void hyperstone_op25(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecodewithHflag(decode, 0, 1);
+ hyperstone_mov(cpustate, decode);
+}
+
+static void hyperstone_op26(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecodewithHflag(decode, 1, 0);
+ hyperstone_mov(cpustate, decode);
+}
+
+static void hyperstone_op27(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecodewithHflag(decode, 1, 1);
+ hyperstone_mov(cpustate, decode);
+}
+
+static void hyperstone_op28(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 0);
+ hyperstone_add(cpustate, decode);
+}
+
+static void hyperstone_op29(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 1);
+ hyperstone_add(cpustate, decode);
+}
+
+static void hyperstone_op2a(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 0);
+ hyperstone_add(cpustate, decode);
+}
+
+static void hyperstone_op2b(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 1);
+ hyperstone_add(cpustate, decode);
+}
+
+static void hyperstone_op2c(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 0);
+ hyperstone_adds(cpustate, decode);
+}
+
+static void hyperstone_op2d(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 1);
+ hyperstone_adds(cpustate, decode);
+}
+
+static void hyperstone_op2e(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 0);
+ hyperstone_adds(cpustate, decode);
+}
+
+static void hyperstone_op2f(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 1);
+ hyperstone_adds(cpustate, decode);
+}
+
+
+
+static void hyperstone_op30(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 0);
+ hyperstone_cmpb(cpustate, decode);
+}
+
+static void hyperstone_op31(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 1);
+ hyperstone_cmpb(cpustate, decode);
+}
+
+static void hyperstone_op32(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 0);
+ hyperstone_cmpb(cpustate, decode);
+}
+
+static void hyperstone_op33(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 1);
+ hyperstone_cmpb(cpustate, decode);
+}
+
+static void hyperstone_op34(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 0);
+ hyperstone_andn(cpustate, decode);
+}
+
+static void hyperstone_op35(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 1);
+ hyperstone_andn(cpustate, decode);
+}
+
+static void hyperstone_op36(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 0);
+ hyperstone_andn(cpustate, decode);
+}
+
+static void hyperstone_op37(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 1);
+ hyperstone_andn(cpustate, decode);
+}
+
+static void hyperstone_op38(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 0);
+ hyperstone_or(cpustate, decode);
+}
+
+static void hyperstone_op39(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 1);
+ hyperstone_or(cpustate, decode);
+}
+
+static void hyperstone_op3a(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 0);
+ hyperstone_or(cpustate, decode);
+}
+
+static void hyperstone_op3b(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 1);
+ hyperstone_or(cpustate, decode);
+}
+
+static void hyperstone_op3c(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 0);
+ hyperstone_xor(cpustate, decode);
+}
+
+static void hyperstone_op3d(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 1);
+ hyperstone_xor(cpustate, decode);
+}
+
+static void hyperstone_op3e(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 0);
+ hyperstone_xor(cpustate, decode);
+}
+
+static void hyperstone_op3f(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 1);
+ hyperstone_xor(cpustate, decode);
+}
+
+
+
+static void hyperstone_op40(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 0);
+ hyperstone_subc(cpustate, decode);
+}
+
+static void hyperstone_op41(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 1);
+ hyperstone_subc(cpustate, decode);
+}
+
+static void hyperstone_op42(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 0);
+ hyperstone_subc(cpustate, decode);
+}
+
+static void hyperstone_op43(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 1);
+ hyperstone_subc(cpustate, decode);
+}
+
+static void hyperstone_op44(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 0);
+ hyperstone_not(cpustate, decode);
+}
+
+static void hyperstone_op45(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 1);
+ hyperstone_not(cpustate, decode);
+}
+
+static void hyperstone_op46(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 0);
+ hyperstone_not(cpustate, decode);
+}
+
+static void hyperstone_op47(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 1);
+ hyperstone_not(cpustate, decode);
+}
+
+static void hyperstone_op48(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 0);
+ hyperstone_sub(cpustate, decode);
+}
+
+static void hyperstone_op49(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 1);
+ hyperstone_sub(cpustate, decode);
+}
+
+static void hyperstone_op4a(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 0);
+ hyperstone_sub(cpustate, decode);
+}
+
+static void hyperstone_op4b(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 1);
+ hyperstone_sub(cpustate, decode);
+}
+
+static void hyperstone_op4c(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 0);
+ hyperstone_subs(cpustate, decode);
+}
+
+static void hyperstone_op4d(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 1);
+ hyperstone_subs(cpustate, decode);
+}
+
+static void hyperstone_op4e(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 0);
+ hyperstone_subs(cpustate, decode);
+}
+
+static void hyperstone_op4f(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 1);
+ hyperstone_subs(cpustate, decode);
+}
+
+
+
+static void hyperstone_op50(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 0);
+ hyperstone_addc(cpustate, decode);
+}
+
+static void hyperstone_op51(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 1);
+ hyperstone_addc(cpustate, decode);
+}
+
+static void hyperstone_op52(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 0);
+ hyperstone_addc(cpustate, decode);
+}
+
+static void hyperstone_op53(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 1);
+ hyperstone_addc(cpustate, decode);
+}
+
+static void hyperstone_op54(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 0);
+ hyperstone_and(cpustate, decode);
+}
+
+static void hyperstone_op55(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 1);
+ hyperstone_and(cpustate, decode);
+}
+
+static void hyperstone_op56(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 0);
+ hyperstone_and(cpustate, decode);
+}
+
+static void hyperstone_op57(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 1);
+ hyperstone_and(cpustate, decode);
+}
+
+static void hyperstone_op58(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 0);
+ hyperstone_neg(cpustate, decode);
+}
+
+static void hyperstone_op59(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 1);
+ hyperstone_neg(cpustate, decode);
+}
+
+static void hyperstone_op5a(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 0);
+ hyperstone_neg(cpustate, decode);
+}
+
+static void hyperstone_op5b(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 1);
+ hyperstone_neg(cpustate, decode);
+}
+
+static void hyperstone_op5c(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 0);
+ hyperstone_negs(cpustate, decode);
+}
+
+static void hyperstone_op5d(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 1);
+ hyperstone_negs(cpustate, decode);
+}
+
+static void hyperstone_op5e(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 0);
+ hyperstone_negs(cpustate, decode);
+}
+
+static void hyperstone_op5f(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 1);
+ hyperstone_negs(cpustate, decode);
+}
+
+
+
+static void hyperstone_op60(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rimmdecode(decode, 0, 0);
+ hyperstone_cmpi(cpustate, decode);
+}
+
+static void hyperstone_op61(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rimmdecode(decode, 0, 1);
+ hyperstone_cmpi(cpustate, decode);
+}
+
+static void hyperstone_op62(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rimmdecode(decode, 1, 0);
+ hyperstone_cmpi(cpustate, decode);
+}
+
+static void hyperstone_op63(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rimmdecode(decode, 1, 1);
+ hyperstone_cmpi(cpustate, decode);
+}
+
+static void hyperstone_op64(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RimmdecodewithHflag(decode, 0, 0);
+ hyperstone_movi(cpustate, decode);
+}
+
+static void hyperstone_op65(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RimmdecodewithHflag(decode, 0, 1);
+ hyperstone_movi(cpustate, decode);
+}
+
+static void hyperstone_op66(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RimmdecodewithHflag(decode, 1, 0);
+ hyperstone_movi(cpustate, decode);
+}
+
+static void hyperstone_op67(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RimmdecodewithHflag(decode, 1, 1);
+ hyperstone_movi(cpustate, decode);
+}
+
+static void hyperstone_op68(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rimmdecode(decode, 0, 0);
+ hyperstone_addi(cpustate, decode);
+}
+
+static void hyperstone_op69(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rimmdecode(decode, 0, 1);
+ hyperstone_addi(cpustate, decode);
+}
+
+static void hyperstone_op6a(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rimmdecode(decode, 1, 0);
+ hyperstone_addi(cpustate, decode);
+}
+
+static void hyperstone_op6b(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rimmdecode(decode, 1, 1);
+ hyperstone_addi(cpustate, decode);
+}
+
+static void hyperstone_op6c(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rimmdecode(decode, 0, 0);
+ hyperstone_addsi(cpustate, decode);
+}
+
+static void hyperstone_op6d(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rimmdecode(decode, 0, 1);
+ hyperstone_addsi(cpustate, decode);
+}
+
+static void hyperstone_op6e(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rimmdecode(decode, 1, 0);
+ hyperstone_addsi(cpustate, decode);
+}
+
+static void hyperstone_op6f(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rimmdecode(decode, 1, 1);
+ hyperstone_addsi(cpustate, decode);
+}
+
+
+
+static void hyperstone_op70(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rimmdecode(decode, 0, 0);
+ hyperstone_cmpbi(cpustate, decode);
+}
+
+static void hyperstone_op71(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rimmdecode(decode, 0, 1);
+ hyperstone_cmpbi(cpustate, decode);
+}
+
+static void hyperstone_op72(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rimmdecode(decode, 1, 0);
+ hyperstone_cmpbi(cpustate, decode);
+}
+
+static void hyperstone_op73(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rimmdecode(decode, 1, 1);
+ hyperstone_cmpbi(cpustate, decode);
+}
+
+static void hyperstone_op74(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rimmdecode(decode, 0, 0);
+ hyperstone_andni(cpustate, decode);
+}
+
+static void hyperstone_op75(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rimmdecode(decode, 0, 1);
+ hyperstone_andni(cpustate, decode);
+}
+
+static void hyperstone_op76(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rimmdecode(decode, 1, 0);
+ hyperstone_andni(cpustate, decode);
+}
+
+static void hyperstone_op77(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rimmdecode(decode, 1, 1);
+ hyperstone_andni(cpustate, decode);
+}
+
+static void hyperstone_op78(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rimmdecode(decode, 0, 0);
+ hyperstone_ori(cpustate, decode);
+}
+
+static void hyperstone_op79(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rimmdecode(decode, 0, 1);
+ hyperstone_ori(cpustate, decode);
+}
+
+static void hyperstone_op7a(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rimmdecode(decode, 1, 0);
+ hyperstone_ori(cpustate, decode);
+}
+
+static void hyperstone_op7b(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rimmdecode(decode, 1, 1);
+ hyperstone_ori(cpustate, decode);
+}
+
+static void hyperstone_op7c(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rimmdecode(decode, 0, 0);
+ hyperstone_xori(cpustate, decode);
+}
+
+static void hyperstone_op7d(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rimmdecode(decode, 0, 1);
+ hyperstone_xori(cpustate, decode);
+}
+
+static void hyperstone_op7e(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rimmdecode(decode, 1, 0);
+ hyperstone_xori(cpustate, decode);
+}
+
+static void hyperstone_op7f(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rimmdecode(decode, 1, 1);
+ hyperstone_xori(cpustate, decode);
+}
+
+
+
+static void hyperstone_op80(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Lndecode(decode);
+ hyperstone_shrdi(cpustate, decode);
+}
+
+static void hyperstone_op81(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Lndecode(decode);
+ hyperstone_shrdi(cpustate, decode);
+}
+
+static void hyperstone_op82(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LLdecode(decode);
+ hyperstone_shrd(cpustate, decode);
+}
+
+static void hyperstone_op83(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LLdecode(decode);
+ hyperstone_shr(cpustate, decode);
+}
+
+static void hyperstone_op84(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Lndecode(decode);
+ hyperstone_sardi(cpustate, decode);
+}
+
+static void hyperstone_op85(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Lndecode(decode);
+ hyperstone_sardi(cpustate, decode);
+}
+
+static void hyperstone_op86(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LLdecode(decode);
+ hyperstone_sard(cpustate, decode);
+}
+
+static void hyperstone_op87(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LLdecode(decode);
+ hyperstone_sar(cpustate, decode);
+}
+
+static void hyperstone_op88(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Lndecode(decode);
+ hyperstone_shldi(cpustate, decode);
+}
+
+static void hyperstone_op89(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Lndecode(decode);
+ hyperstone_shldi(cpustate, decode);
+}
+
+static void hyperstone_op8a(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LLdecode(decode);
+ hyperstone_shld(cpustate, decode);
+}
+
+static void hyperstone_op8b(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LLdecode(decode);
+ hyperstone_shl(cpustate, decode);
+}
+
+static void hyperstone_op8c(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ no_decode(decode);
+ reserved(cpustate, decode);
+}
+
+static void hyperstone_op8d(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ no_decode(decode);
+ reserved(cpustate, decode);
+}
+
+static void hyperstone_op8e(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LLdecode(decode);
+ hyperstone_testlz(cpustate, decode);
+}
+
+static void hyperstone_op8f(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LLdecode(decode);
+ hyperstone_rol(cpustate, decode);
+}
+
+
+
+static void hyperstone_op90(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdisdecode(decode, 0, 0);
+ hyperstone_ldxx1(cpustate, decode);
+}
+
+static void hyperstone_op91(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdisdecode(decode, 0, 1);
+ hyperstone_ldxx1(cpustate, decode);
+}
+
+static void hyperstone_op92(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdisdecode(decode, 1, 0);
+ hyperstone_ldxx1(cpustate, decode);
+}
+
+static void hyperstone_op93(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdisdecode(decode, 1, 1);
+ hyperstone_ldxx1(cpustate, decode);
+}
+
+static void hyperstone_op94(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdisdecode(decode, 0, 0);
+ hyperstone_ldxx2(cpustate, decode);
+}
+
+static void hyperstone_op95(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdisdecode(decode, 0, 1);
+ hyperstone_ldxx2(cpustate, decode);
+}
+
+static void hyperstone_op96(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdisdecode(decode, 1, 0);
+ hyperstone_ldxx2(cpustate, decode);
+}
+
+static void hyperstone_op97(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdisdecode(decode, 1, 1);
+ hyperstone_ldxx2(cpustate, decode);
+}
+
+static void hyperstone_op98(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdisdecode(decode, 0, 0);
+ hyperstone_stxx1(cpustate, decode);
+}
+
+static void hyperstone_op99(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdisdecode(decode, 0, 1);
+ hyperstone_stxx1(cpustate, decode);
+}
+
+static void hyperstone_op9a(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdisdecode(decode, 1, 0);
+ hyperstone_stxx1(cpustate, decode);
+}
+
+static void hyperstone_op9b(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdisdecode(decode, 1, 1);
+ hyperstone_stxx1(cpustate, decode);
+}
+
+static void hyperstone_op9c(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdisdecode(decode, 0, 0);
+ hyperstone_stxx2(cpustate, decode);
+}
+
+static void hyperstone_op9d(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdisdecode(decode, 0, 1);
+ hyperstone_stxx2(cpustate, decode);
+}
+
+static void hyperstone_op9e(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdisdecode(decode, 1, 0);
+ hyperstone_stxx2(cpustate, decode);
+}
+
+static void hyperstone_op9f(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdisdecode(decode, 1, 1);
+ hyperstone_stxx2(cpustate, decode);
+}
+
+
+
+static void hyperstone_opa0(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rndecode(decode, 0);
+ hyperstone_shri(cpustate, decode);
+}
+
+static void hyperstone_opa1(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rndecode(decode, 0);
+ hyperstone_shri(cpustate, decode);
+}
+
+static void hyperstone_opa2(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rndecode(decode, 1);
+ hyperstone_shri(cpustate, decode);
+}
+
+static void hyperstone_opa3(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rndecode(decode, 1);
+ hyperstone_shri(cpustate, decode);
+}
+
+static void hyperstone_opa4(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rndecode(decode, 0);
+ hyperstone_sari(cpustate, decode);
+}
+
+static void hyperstone_opa5(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rndecode(decode, 0);
+ hyperstone_sari(cpustate, decode);
+}
+
+static void hyperstone_opa6(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rndecode(decode, 1);
+ hyperstone_sari(cpustate, decode);
+}
+
+static void hyperstone_opa7(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rndecode(decode, 1);
+ hyperstone_sari(cpustate, decode);
+}
+
+static void hyperstone_opa8(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rndecode(decode, 0);
+ hyperstone_shli(cpustate, decode);
+}
+
+static void hyperstone_opa9(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rndecode(decode, 0);
+ hyperstone_shli(cpustate, decode);
+}
+
+static void hyperstone_opaa(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rndecode(decode, 1);
+ hyperstone_shli(cpustate, decode);
+}
+
+static void hyperstone_opab(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rndecode(decode, 1);
+ hyperstone_shli(cpustate, decode);
+}
+
+static void hyperstone_opac(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ no_decode(decode);
+ reserved(cpustate, decode);
+}
+
+static void hyperstone_opad(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ no_decode(decode);
+ reserved(cpustate, decode);
+}
+
+static void hyperstone_opae(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ no_decode(decode);
+ reserved(cpustate, decode);
+}
+
+static void hyperstone_opaf(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ no_decode(decode);
+ reserved(cpustate, decode);
+}
+
+
+
+static void hyperstone_opb0(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 0);
+ hyperstone_mulu(cpustate, decode);
+}
+
+static void hyperstone_opb1(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 1);
+ hyperstone_mulu(cpustate, decode);
+}
+
+static void hyperstone_opb2(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 0);
+ hyperstone_mulu(cpustate, decode);
+}
+
+static void hyperstone_opb3(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 1);
+ hyperstone_mulu(cpustate, decode);
+}
+
+static void hyperstone_opb4(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 0);
+ hyperstone_muls(cpustate, decode);
+}
+
+static void hyperstone_opb5(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 1);
+ hyperstone_muls(cpustate, decode);
+}
+
+static void hyperstone_opb6(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 0);
+ hyperstone_muls(cpustate, decode);
+}
+
+static void hyperstone_opb7(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 1);
+ hyperstone_muls(cpustate, decode);
+}
+
+static void hyperstone_opb8(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rndecode(decode, 0);
+ hyperstone_set(cpustate, decode);
+}
+
+static void hyperstone_opb9(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rndecode(decode, 0);
+ hyperstone_set(cpustate, decode);
+}
+
+static void hyperstone_opba(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rndecode(decode, 1);
+ hyperstone_set(cpustate, decode);
+}
+
+static void hyperstone_opbb(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ Rndecode(decode, 1);
+ hyperstone_set(cpustate, decode);
+}
+
+static void hyperstone_opbc(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 0);
+ hyperstone_mul(cpustate, decode);
+}
+
+static void hyperstone_opbd(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 0, 1);
+ hyperstone_mul(cpustate, decode);
+}
+
+static void hyperstone_opbe(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 0);
+ hyperstone_mul(cpustate, decode);
+}
+
+static void hyperstone_opbf(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ RRdecode(decode, 1, 1);
+ hyperstone_mul(cpustate, decode);
+}
+
+
+
+static void hyperstone_opc0(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LLdecode(decode);
+ hyperstone_fadd(cpustate, decode);
+}
+
+static void hyperstone_opc1(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LLdecode(decode);
+ hyperstone_faddd(cpustate, decode);
+}
+
+static void hyperstone_opc2(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LLdecode(decode);
+ hyperstone_fsub(cpustate, decode);
+}
+
+static void hyperstone_opc3(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LLdecode(decode);
+ hyperstone_fsubd(cpustate, decode);
+}
+
+static void hyperstone_opc4(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LLdecode(decode);
+ hyperstone_fmul(cpustate, decode);
+}
+
+static void hyperstone_opc5(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LLdecode(decode);
+ hyperstone_fmuld(cpustate, decode);
+}
+
+static void hyperstone_opc6(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LLdecode(decode);
+ hyperstone_fdiv(cpustate, decode);
+}
+
+static void hyperstone_opc7(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LLdecode(decode);
+ hyperstone_fdivd(cpustate, decode);
+}
+
+static void hyperstone_opc8(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LLdecode(decode);
+ hyperstone_fcmp(cpustate, decode);
+}
+
+static void hyperstone_opc9(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LLdecode(decode);
+ hyperstone_fcmpd(cpustate, decode);
+}
+
+static void hyperstone_opca(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LLdecode(decode);
+ hyperstone_fcmpu(cpustate, decode);
+}
+
+static void hyperstone_opcb(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LLdecode(decode);
+ hyperstone_fcmpud(cpustate, decode);
+}
+
+static void hyperstone_opcc(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LLdecode(decode);
+ hyperstone_fcvt(cpustate, decode);
+}
+
+static void hyperstone_opcd(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LLdecode(decode);
+ hyperstone_fcvtd(cpustate, decode);
+}
+
+static void hyperstone_opce(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LLextdecode(decode);
+ hyperstone_extend(cpustate, decode);
+}
+
+static void hyperstone_opcf(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LLdecode(decode);
+ hyperstone_do(cpustate, decode);
+}
+
+
+
+static void hyperstone_opd0(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LRdecode(decode, 0);
+ hyperstone_ldwr(cpustate, decode);
+}
+
+static void hyperstone_opd1(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LRdecode(decode, 1);
+ hyperstone_ldwr(cpustate, decode);
+}
+
+static void hyperstone_opd2(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LRdecode(decode, 0);
+ hyperstone_lddr(cpustate, decode);
+}
+
+static void hyperstone_opd3(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LRdecode(decode, 1);
+ hyperstone_lddr(cpustate, decode);
+}
+
+static void hyperstone_opd4(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LRdecode(decode, 0);
+ hyperstone_ldwp(cpustate, decode);
+}
+
+static void hyperstone_opd5(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LRdecode(decode, 1);
+ hyperstone_ldwp(cpustate, decode);
+}
+
+static void hyperstone_opd6(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LRdecode(decode, 0);
+ hyperstone_lddp(cpustate, decode);
+}
+
+static void hyperstone_opd7(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LRdecode(decode, 1);
+ hyperstone_lddp(cpustate, decode);
+}
+
+static void hyperstone_opd8(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LRdecode(decode, 0);
+ hyperstone_stwr(cpustate, decode);
+}
+
+static void hyperstone_opd9(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LRdecode(decode, 1);
+ hyperstone_stwr(cpustate, decode);
+}
+
+static void hyperstone_opda(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LRdecode(decode, 0);
+ hyperstone_stdr(cpustate, decode);
+}
+
+static void hyperstone_opdb(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LRdecode(decode, 1);
+ hyperstone_stdr(cpustate, decode);
+}
+
+static void hyperstone_opdc(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LRdecode(decode, 0);
+ hyperstone_stwp(cpustate, decode);
+}
+
+static void hyperstone_opdd(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LRdecode(decode, 1);
+ hyperstone_stwp(cpustate, decode);
+}
+
+static void hyperstone_opde(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LRdecode(decode, 0);
+ hyperstone_stdp(cpustate, decode);
+}
+
+static void hyperstone_opdf(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LRdecode(decode, 1);
+ hyperstone_stdp(cpustate, decode);
+}
+
+
+
+static void hyperstone_ope0(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ PCreldecode(decode);
+ hyperstone_dbv(cpustate, decode);
+}
+
+static void hyperstone_ope1(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ PCreldecode(decode);
+ hyperstone_dbnv(cpustate, decode);
+}
+
+static void hyperstone_ope2(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ PCreldecode(decode);
+ hyperstone_dbe(cpustate, decode);
+}
+
+static void hyperstone_ope3(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ PCreldecode(decode);
+ hyperstone_dbne(cpustate, decode);
+}
+
+static void hyperstone_ope4(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ PCreldecode(decode);
+ hyperstone_dbc(cpustate, decode);
+}
+
+static void hyperstone_ope5(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ PCreldecode(decode);
+ hyperstone_dbnc(cpustate, decode);
+}
+
+static void hyperstone_ope6(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ PCreldecode(decode);
+ hyperstone_dbse(cpustate, decode);
+}
+
+static void hyperstone_ope7(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ PCreldecode(decode);
+ hyperstone_dbht(cpustate, decode);
+}
+
+static void hyperstone_ope8(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ PCreldecode(decode);
+ hyperstone_dbn(cpustate, decode);
+}
+
+static void hyperstone_ope9(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ PCreldecode(decode);
+ hyperstone_dbnn(cpustate, decode);
+}
+
+static void hyperstone_opea(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ PCreldecode(decode);
+ hyperstone_dble(cpustate, decode);
+}
+
+static void hyperstone_opeb(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ PCreldecode(decode);
+ hyperstone_dbgt(cpustate, decode);
+}
+
+static void hyperstone_opec(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ PCreldecode(decode);
+ hyperstone_dbr(cpustate, decode);
+}
+
+static void hyperstone_oped(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LLdecode(decode);
+ hyperstone_frame(cpustate, decode);
+}
+
+static void hyperstone_opee(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LRconstdecode(decode, 0);
+ hyperstone_call(cpustate, decode);
+}
+
+static void hyperstone_opef(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ LRconstdecode(decode, 1);
+ hyperstone_call(cpustate, decode);
+}
+
+
+
+static void hyperstone_opf0(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ PCreldecode(decode);
+ hyperstone_bv(cpustate, decode);
+}
+
+static void hyperstone_opf1(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ PCreldecode(decode);
+ hyperstone_bnv(cpustate, decode);
+}
+
+static void hyperstone_opf2(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ PCreldecode(decode);
+ hyperstone_be(cpustate, decode);
+}
+
+static void hyperstone_opf3(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ PCreldecode(decode);
+ hyperstone_bne(cpustate, decode);
+}
+
+static void hyperstone_opf4(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ PCreldecode(decode);
+ hyperstone_bc(cpustate, decode);
+}
+
+static void hyperstone_opf5(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ PCreldecode(decode);
+ hyperstone_bnc(cpustate, decode);
+}
+
+static void hyperstone_opf6(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ PCreldecode(decode);
+ hyperstone_bse(cpustate, decode);
+}
+
+static void hyperstone_opf7(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ PCreldecode(decode);
+ hyperstone_bht(cpustate, decode);
+}
+
+static void hyperstone_opf8(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ PCreldecode(decode);
+ hyperstone_bn(cpustate, decode);
+}
+
+static void hyperstone_opf9(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ PCreldecode(decode);
+ hyperstone_bnn(cpustate, decode);
+}
+
+static void hyperstone_opfa(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ PCreldecode(decode);
+ hyperstone_ble(cpustate, decode);
+}
+
+static void hyperstone_opfb(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ PCreldecode(decode);
+ hyperstone_bgt(cpustate, decode);
+}
+
+static void hyperstone_opfc(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ PCreldecode(decode);
+ hyperstone_br(cpustate, decode);
+}
+
+static void hyperstone_opfd(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ PCadrdecode(decode);
+ hyperstone_trap(cpustate, decode);
+}
+
+static void hyperstone_opfe(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ PCadrdecode(decode);
+ hyperstone_trap(cpustate, decode);
+}
+
+static void hyperstone_opff(hyperstone_state *cpustate)
+{
+ LOCAL_DECODE_INIT;
+ PCadrdecode(decode);
+ hyperstone_trap(cpustate, decode);
+}
+
+
+static void (*const hyperstone_op[0x100])(hyperstone_state *cpustate) =
+{
+ hyperstone_op00, hyperstone_op01, hyperstone_op02, hyperstone_op03,
+ hyperstone_op04, hyperstone_op05, hyperstone_op06, hyperstone_op07,
+ hyperstone_op08, hyperstone_op09, hyperstone_op0a, hyperstone_op0b,
+ hyperstone_op0c, hyperstone_op0d, hyperstone_op0e, hyperstone_op0f,
+
+ hyperstone_op10, hyperstone_op11, hyperstone_op12, hyperstone_op13,
+ hyperstone_op14, hyperstone_op15, hyperstone_op16, hyperstone_op17,
+ hyperstone_op18, hyperstone_op19, hyperstone_op1a, hyperstone_op1b,
+ hyperstone_op1c, hyperstone_op1d, hyperstone_op1e, hyperstone_op1f,
+
+ hyperstone_op20, hyperstone_op21, hyperstone_op22, hyperstone_op23,
+ hyperstone_op24, hyperstone_op25, hyperstone_op26, hyperstone_op27,
+ hyperstone_op28, hyperstone_op29, hyperstone_op2a, hyperstone_op2b,
+ hyperstone_op2c, hyperstone_op2d, hyperstone_op2e, hyperstone_op2f,
+
+ hyperstone_op30, hyperstone_op31, hyperstone_op32, hyperstone_op33,
+ hyperstone_op34, hyperstone_op35, hyperstone_op36, hyperstone_op37,
+ hyperstone_op38, hyperstone_op39, hyperstone_op3a, hyperstone_op3b,
+ hyperstone_op3c, hyperstone_op3d, hyperstone_op3e, hyperstone_op3f,
+
+ hyperstone_op40, hyperstone_op41, hyperstone_op42, hyperstone_op43,
+ hyperstone_op44, hyperstone_op45, hyperstone_op46, hyperstone_op47,
+ hyperstone_op48, hyperstone_op49, hyperstone_op4a, hyperstone_op4b,
+ hyperstone_op4c, hyperstone_op4d, hyperstone_op4e, hyperstone_op4f,
+
+ hyperstone_op50, hyperstone_op51, hyperstone_op52, hyperstone_op53,
+ hyperstone_op54, hyperstone_op55, hyperstone_op56, hyperstone_op57,
+ hyperstone_op58, hyperstone_op59, hyperstone_op5a, hyperstone_op5b,
+ hyperstone_op5c, hyperstone_op5d, hyperstone_op5e, hyperstone_op5f,
+
+ hyperstone_op60, hyperstone_op61, hyperstone_op62, hyperstone_op63,
+ hyperstone_op64, hyperstone_op65, hyperstone_op66, hyperstone_op67,
+ hyperstone_op68, hyperstone_op69, hyperstone_op6a, hyperstone_op6b,
+ hyperstone_op6c, hyperstone_op6d, hyperstone_op6e, hyperstone_op6f,
+
+ hyperstone_op70, hyperstone_op71, hyperstone_op72, hyperstone_op73,
+ hyperstone_op74, hyperstone_op75, hyperstone_op76, hyperstone_op77,
+ hyperstone_op78, hyperstone_op79, hyperstone_op7a, hyperstone_op7b,
+ hyperstone_op7c, hyperstone_op7d, hyperstone_op7e, hyperstone_op7f,
+
+ hyperstone_op80, hyperstone_op81, hyperstone_op82, hyperstone_op83,
+ hyperstone_op84, hyperstone_op85, hyperstone_op86, hyperstone_op87,
+ hyperstone_op88, hyperstone_op89, hyperstone_op8a, hyperstone_op8b,
+ hyperstone_op8c, hyperstone_op8d, hyperstone_op8e, hyperstone_op8f,
+
+ hyperstone_op90, hyperstone_op91, hyperstone_op92, hyperstone_op93,
+ hyperstone_op94, hyperstone_op95, hyperstone_op96, hyperstone_op97,
+ hyperstone_op98, hyperstone_op99, hyperstone_op9a, hyperstone_op9b,
+ hyperstone_op9c, hyperstone_op9d, hyperstone_op9e, hyperstone_op9f,
+
+ hyperstone_opa0, hyperstone_opa1, hyperstone_opa2, hyperstone_opa3,
+ hyperstone_opa4, hyperstone_opa5, hyperstone_opa6, hyperstone_opa7,
+ hyperstone_opa8, hyperstone_opa9, hyperstone_opaa, hyperstone_opab,
+ hyperstone_opac, hyperstone_opad, hyperstone_opae, hyperstone_opaf,
+
+ hyperstone_opb0, hyperstone_opb1, hyperstone_opb2, hyperstone_opb3,
+ hyperstone_opb4, hyperstone_opb5, hyperstone_opb6, hyperstone_opb7,
+ hyperstone_opb8, hyperstone_opb9, hyperstone_opba, hyperstone_opbb,
+ hyperstone_opbc, hyperstone_opbd, hyperstone_opbe, hyperstone_opbf,
+
+ hyperstone_opc0, hyperstone_opc1, hyperstone_opc2, hyperstone_opc3,
+ hyperstone_opc4, hyperstone_opc5, hyperstone_opc6, hyperstone_opc7,
+ hyperstone_opc8, hyperstone_opc9, hyperstone_opca, hyperstone_opcb,
+ hyperstone_opcc, hyperstone_opcd, hyperstone_opce, hyperstone_opcf,
+
+ hyperstone_opd0, hyperstone_opd1, hyperstone_opd2, hyperstone_opd3,
+ hyperstone_opd4, hyperstone_opd5, hyperstone_opd6, hyperstone_opd7,
+ hyperstone_opd8, hyperstone_opd9, hyperstone_opda, hyperstone_opdb,
+ hyperstone_opdc, hyperstone_opdd, hyperstone_opde, hyperstone_opdf,
+
+ hyperstone_ope0, hyperstone_ope1, hyperstone_ope2, hyperstone_ope3,
+ hyperstone_ope4, hyperstone_ope5, hyperstone_ope6, hyperstone_ope7,
+ hyperstone_ope8, hyperstone_ope9, hyperstone_opea, hyperstone_opeb,
+ hyperstone_opec, hyperstone_oped, hyperstone_opee, hyperstone_opef,
+
+ hyperstone_opf0, hyperstone_opf1, hyperstone_opf2, hyperstone_opf3,
+ hyperstone_opf4, hyperstone_opf5, hyperstone_opf6, hyperstone_opf7,
+ hyperstone_opf8, hyperstone_opf9, hyperstone_opfa, hyperstone_opfb,
+ hyperstone_opfc, hyperstone_opfd, hyperstone_opfe, hyperstone_opff
+};
diff --git a/trunk/src/emu/cpu/esrip/esrip.c b/trunk/src/emu/cpu/esrip/esrip.c
new file mode 100644
index 00000000000..192fe856d7a
--- /dev/null
+++ b/trunk/src/emu/cpu/esrip/esrip.c
@@ -0,0 +1,2000 @@
+/***************************************************************************
+
+ esrip.c
+
+ Implementation of the Entertainment Sciences
+ AM29116-based Real Time Image Processor
+
+***************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "esrip.h"
+
+CPU_DISASSEMBLE( esrip );
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define IPT_RAM_SIZE (8192 * sizeof(UINT16))
+
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+#define RIP_PC (cpustate->pc | ((cpustate->status_out & 1) << 8))
+#define _BIT(x, n) ((x) & (1 << (n)))
+#define RISING_EDGE(old_val, new_val, bit) (!(old_val & (1 << bit)) && (new_val & (1 << bit)))
+
+#define UNHANDLED do {printf("%s:UNHANDLED (%x)\n", __FUNCTION__, inst); assert(0);} while (0)
+#define INVALID do {printf("%s:INVALID (%x)\n", __FUNCTION__, inst); assert(0);} while (0)
+
+#define RAM_ADDR (inst & 0x1f)
+#define MODE (inst & 0x8000)
+#define WORD_MODE (inst & 0x8000)
+#define BYTE_MODE (!WORD_MODE)
+#define N ((inst >> 9) & 0xf)
+#define OPCODE ((inst >> 5) & 0xf)
+#define SRC ((inst >> 9) & 0xf)
+#define DST (inst & 0x1f) // TEST
+
+#define BW_WORD (1 << 15)
+#define BW_BYTE (0 << 15)
+
+#define FLAG_3 (1 << 7)
+#define FLAG_2 (1 << 6)
+#define FLAG_1 (1 << 5)
+#define L_FLAG (1 << 4)
+#define V_FLAG (1 << 3)
+#define N_FLAG (1 << 2)
+#define C_FLAG (1 << 1)
+#define Z_FLAG (1 << 0)
+
+#define CLEAR_FLAGS(a) (cpustate->new_status &= ~(a))
+#define SET_FLAGS(a) (cpustate->new_status |= (a))
+
+
+/***************************************************************************
+ STRUCTURES & TYPEDEFS
+***************************************************************************/
+
+typedef struct
+{
+ UINT16 ram[32];
+ UINT16 acc;
+ UINT16 d_latch;
+ UINT16 i_latch;
+ UINT16 result;
+ UINT8 new_status;
+ UINT8 status;
+ UINT16 inst;
+ UINT8 immflag;
+ UINT8 ct;
+ UINT8 t;
+
+ /* Instruction latches - current and previous values */
+ UINT8 l1, pl1;
+ UINT8 l2, pl2;
+ UINT8 l3, pl3;
+ UINT8 l4, pl4;
+ UINT8 l5, pl5;
+ UINT8 l6, pl6;
+ UINT8 l7, pl7;
+
+ UINT8 pc;
+ UINT8 status_out;
+
+ UINT8 x_scale;
+ UINT8 y_scale;
+ UINT8 img_bank;
+ UINT8 line_latch;
+ UINT16 fig_latch;
+ UINT16 attr_latch;
+ UINT16 adl_latch;
+ UINT16 adr_latch;
+ UINT16 iaddr_latch;
+ UINT8 c_latch;
+
+ UINT16 fdt_cnt;
+ UINT16 ipt_cnt;
+
+ UINT8 fig;
+ UINT16 fig_cycles;
+
+ UINT8 *optable;
+
+ UINT16 *ipt_ram;
+ UINT8 *lbrm;
+
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ int icount;
+
+ read16_device_func fdt_r;
+ write16_device_func fdt_w;
+ UINT8 (*status_in)(running_machine &machine);
+ int (*draw)(running_machine &machine, int l, int r, int fig, int attr, int addr, int col, int x_scale, int bank);
+} esrip_state;
+
+
+INLINE esrip_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == ESRIP);
+ return (esrip_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+
+/***************************************************************************
+ PUBLIC FUNCTIONS
+***************************************************************************/
+
+UINT8 get_rip_status(device_t *cpu)
+{
+ esrip_state *cpustate = get_safe_token(cpu);
+ return cpustate->status_out;
+}
+
+
+/***************************************************************************
+ INITIALIZATION AND SHUTDOWN
+***************************************************************************/
+
+enum ops
+{
+ ROTR1, TOR1, ROTR2, ROTC, ROTM, BOR2, CRCF, CRCR,
+ SVSTR, PRT, SOR, TOR2, SHFTR, TEST, NOP, SETST, RSTST,
+ ROTNR, BONR, BOR1, SONR, SHFTNR, PRTNR, TONR
+};
+
+static void make_ops(esrip_state *cpustate)
+{
+ int inst;
+
+ for (inst = 0; inst < 65536; ++inst)
+ {
+ int quad = (inst >> 13) & 3;
+
+ if (quad == 0)
+ {
+ if (((inst >> 5) & 0xc) == 0xc)
+ cpustate->optable[inst] = ROTR1;
+ else
+ cpustate->optable[inst] = TOR1;
+ }
+ else if (quad == 1)
+ {
+ if (OPCODE < 2)
+ cpustate->optable[inst] = ROTR2;
+ else if (OPCODE < 6)
+ cpustate->optable[inst] = ROTC;
+ else
+ cpustate->optable[inst] = ROTM;
+ }
+ else if (quad == 2)
+ {
+ if (OPCODE > 11)
+ cpustate->optable[inst] = BOR2;
+ else
+ {
+ int tmp = (inst >> 5) & 0xff;
+
+ if (tmp == 0x63)
+ cpustate->optable[inst] = CRCF;
+ else if (tmp == 0x69)
+ cpustate->optable[inst] = CRCR;
+ else if (tmp == 0x7a)
+ cpustate->optable[inst] = SVSTR;
+ else
+ {
+ if ((SRC > 7) && (SRC < 12))
+ cpustate->optable[inst] = PRT;
+ else if (SRC > 11)
+ cpustate->optable[inst] = SOR;
+ else if (SRC < 6)
+ cpustate->optable[inst] = TOR2;
+ else
+ cpustate->optable[inst] = SHFTR;
+ }
+ }
+ }
+ else
+ {
+ if (inst == 0x7140)
+ cpustate->optable[inst] = NOP;
+ else
+ {
+ int x = (inst & 0xffe0);
+ if (x == 0x7340)
+ cpustate->optable[inst] = TEST;
+ else if (x == 0x7740)
+ cpustate->optable[inst] = SETST;
+ else if (x == 0x7540)
+ cpustate->optable[inst] = RSTST;
+ else
+ {
+ int op = OPCODE;
+ if (op == 0xc)
+ {
+ if ((inst & 0x18) == 0x18)
+ cpustate->optable[inst] = ROTNR;
+ else
+ cpustate->optable[inst] = BONR;
+ }
+ else if ((op & 0xc) == 0xc)
+ cpustate->optable[inst] = BOR1;
+ else
+ {
+ int src = SRC;
+
+ if ((src & 0xc) == 0xc)
+ cpustate->optable[inst] = SONR;
+ else if ((src & 0x6) == 0x6)
+ cpustate->optable[inst] = SHFTNR;
+ else if (src & 0x8)
+ cpustate->optable[inst] = PRTNR;
+ else
+ cpustate->optable[inst] = TONR;
+ }
+ }
+ }
+ }
+ }
+}
+
+static CPU_INIT( esrip )
+{
+ esrip_state *cpustate = get_safe_token(device);
+ esrip_config* _config = (esrip_config*)device->static_config();
+
+ memset(cpustate, 0, sizeof(*cpustate));
+
+ /* Register configuration structure callbacks */
+ cpustate->fdt_r = _config->fdt_r;
+ cpustate->fdt_w = _config->fdt_w;
+ cpustate->lbrm = (UINT8*)device->machine().region(_config->lbrm_prom)->base();
+ cpustate->status_in = _config->status_in;
+ cpustate->draw = _config->draw;
+
+ /* Allocate image pointer table RAM */
+ cpustate->ipt_ram = auto_alloc_array(device->machine(), UINT16, IPT_RAM_SIZE/2);
+
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+
+ /* Create the instruction decode lookup table */
+ cpustate->optable = auto_alloc_array(device->machine(), UINT8, 65536);
+ make_ops(cpustate);
+
+ /* Register stuff for state saving */
+ device->save_item(NAME(cpustate->acc));
+ device->save_item(NAME(cpustate->ram));
+ device->save_item(NAME(cpustate->d_latch));
+ device->save_item(NAME(cpustate->i_latch));
+ device->save_item(NAME(cpustate->result));
+ device->save_item(NAME(cpustate->new_status));
+ device->save_item(NAME(cpustate->status));
+ device->save_item(NAME(cpustate->inst));
+ device->save_item(NAME(cpustate->immflag));
+ device->save_item(NAME(cpustate->ct));
+ device->save_item(NAME(cpustate->t));
+ device->save_item(NAME(cpustate->l1));
+ device->save_item(NAME(cpustate->l2));
+ device->save_item(NAME(cpustate->l3));
+ device->save_item(NAME(cpustate->l4));
+ device->save_item(NAME(cpustate->l5));
+ device->save_item(NAME(cpustate->l6));
+ device->save_item(NAME(cpustate->l7));
+ device->save_item(NAME(cpustate->pl1));
+ device->save_item(NAME(cpustate->pl2));
+ device->save_item(NAME(cpustate->pl3));
+ device->save_item(NAME(cpustate->pl4));
+ device->save_item(NAME(cpustate->pl5));
+ device->save_item(NAME(cpustate->pl6));
+ device->save_item(NAME(cpustate->pl7));
+ device->save_item(NAME(cpustate->pc));
+ device->save_item(NAME(cpustate->status_out));
+ device->save_item(NAME(cpustate->x_scale));
+ device->save_item(NAME(cpustate->y_scale));
+ device->save_item(NAME(cpustate->img_bank));
+ device->save_item(NAME(cpustate->line_latch));
+ device->save_item(NAME(cpustate->fig_latch));
+ device->save_item(NAME(cpustate->attr_latch));
+ device->save_item(NAME(cpustate->adl_latch));
+ device->save_item(NAME(cpustate->adr_latch));
+ device->save_item(NAME(cpustate->iaddr_latch));
+ device->save_item(NAME(cpustate->c_latch));
+ device->save_item(NAME(cpustate->fdt_cnt));
+ device->save_item(NAME(cpustate->ipt_cnt));
+ device->save_item(NAME(cpustate->fig));
+ device->save_item(NAME(cpustate->fig_cycles));
+ device->save_pointer(NAME(cpustate->ipt_ram), IPT_RAM_SIZE / sizeof(UINT16));
+}
+
+
+static CPU_RESET( esrip )
+{
+ esrip_state *cpustate = get_safe_token(device);
+
+ cpustate->pc = 0;
+
+ cpustate->pl1 = 0xff;
+ cpustate->pl2 = 0xff;
+ cpustate->pl3 = 0xff;
+ cpustate->pl4 = 0xff;
+ cpustate->pl5 = 0xff;
+ cpustate->pl6 = 0xff;
+ cpustate->pl7 = 0xff;
+
+ cpustate->l1 = 0xff;
+ cpustate->l2 = 0xff;
+ cpustate->l3 = 0xff;
+ cpustate->l4 = 0xff;
+ cpustate->l5 = 0xff;
+ cpustate->l6 = 0xff;
+ cpustate->l7 = 0xff;
+
+ cpustate->status_out = 0;
+ cpustate->immflag = 0;
+}
+
+
+static CPU_EXIT( esrip )
+{
+
+}
+
+
+/***************************************************************************
+ PRIVATE FUNCTIONS
+***************************************************************************/
+
+static int get_hblank(running_machine &machine)
+{
+ return machine.primary_screen->hblank();
+}
+
+/* Return the state of the LBRM line (Y-scaling related) */
+static int get_lbrm(esrip_state *cpustate)
+{
+ int addr = ((cpustate->y_scale & 0x3f) << 3) | ((cpustate->line_latch >> 3) & 7);
+ int sel = (cpustate->line_latch & 7);
+
+ UINT8 val = cpustate->lbrm[addr];
+
+ return (val >> sel) & 1;
+}
+
+INLINE int check_jmp(esrip_state *cpustate, UINT8 jmp_ctrl)
+{
+ int ret = 0;
+
+ if (~jmp_ctrl & 0x10)
+ {
+ switch (jmp_ctrl & 7)
+ {
+ /* CT */ case 0: ret = cpustate->ct; break;
+ /* T1 */ case 4: ret = BIT(cpustate->t, 0); break;
+ /* T2 */ case 2: ret = BIT(cpustate->t, 1); break;
+ /* T3 */ case 6: ret = BIT(cpustate->t, 2); break;
+ /* T4 */ case 1: ret = BIT(cpustate->t, 3); break;
+ /* /LBRM */ case 5: ret = !get_lbrm(cpustate); break;
+ /* /HBLANK */ case 3: ret = !get_hblank(cpustate->device->machine()); break;
+ /* JMP */ case 7: ret = 0; break;
+ }
+
+ ret ^= 1;
+ }
+ else if (~jmp_ctrl & 0x08)
+ {
+ switch (jmp_ctrl & 7)
+ {
+ /* CT */ case 0: ret = cpustate->ct; break;
+ /* T1 */ case 4: ret = BIT(cpustate->t, 0); break;
+ /* T2 */ case 2: ret = BIT(cpustate->t, 1); break;
+ /* T3 */ case 6: ret = BIT(cpustate->t, 2); break;
+ /* T4 */ case 1: ret = BIT(cpustate->t, 3); break;
+ /* /LBRM */ case 5: ret = !get_lbrm(cpustate); break;
+ /* /FIG */ case 3: ret = !cpustate->fig; break;
+ /* JMP */ case 7: ret = 1; break;
+ }
+ }
+ else
+ assert(!"RIP: Invalid jump control");
+
+ return ret;
+}
+
+
+INLINE void calc_z_flag(esrip_state *cpustate, UINT16 res)
+{
+ cpustate->new_status &= ~Z_FLAG;
+ cpustate->new_status |= (res == 0);
+}
+
+INLINE void calc_c_flag_add(esrip_state *cpustate, UINT16 a, UINT16 b)
+{
+ cpustate->new_status &= ~C_FLAG;
+ cpustate->new_status |= ((UINT16)(b) > (UINT16)(~(a))) ? 2 : 0;
+}
+
+INLINE void calc_c_flag_sub(esrip_state *cpustate, UINT16 a, UINT16 b)
+{
+ cpustate->new_status &= ~C_FLAG;
+ cpustate->new_status |= ((UINT16)(b) <= (UINT16)(a)) ? 2 : 0;
+}
+
+INLINE void calc_n_flag(esrip_state *cpustate, UINT16 res)
+{
+ cpustate->new_status &= ~N_FLAG;
+ cpustate->new_status |= (res & 0x8000) ? 4 : 0;
+}
+
+INLINE void calc_v_flag_add(esrip_state *cpustate, UINT16 a, UINT16 b, UINT32 r)
+{
+ cpustate->new_status &= ~V_FLAG;
+ cpustate->new_status |= ((a ^ r) & (b ^ r) & 0x8000) ? 8 : 0;
+}
+
+INLINE void calc_v_flag_sub(esrip_state *cpustate, UINT16 a, UINT16 b, UINT32 r)
+{
+ cpustate->new_status &= ~V_FLAG;
+ cpustate->new_status |= ((a ^ b) & (r ^ b) & 0x8000) ? 8 : 0;
+}
+
+
+/***************************************************************************
+ INSTRUCTIONS
+***************************************************************************/
+
+enum
+{
+ ACC,
+ Y_BUS,
+ STATUS,
+ RAM,
+};
+
+/*************************************
+ *
+ * Single operand
+ *
+ *************************************/
+enum
+{
+ MOVE = 0xc,
+ COMP = 0xd,
+ INC = 0xe,
+ NEG = 0xf
+};
+
+enum
+{
+ SORA = 0x0,
+ SORY = 0x2,
+ SORS = 0x3,
+ SOAR = 0x4,
+ SODR = 0x6,
+ SOIR = 0x7,
+ SOZR = 0x8,
+ SOZER = 0x9,
+ SOSER = 0xa,
+ SORR = 0xb
+};
+
+static UINT16 sor_op(esrip_state *cpustate, UINT16 r, UINT16 opcode)
+{
+ UINT32 res = 0;
+
+ switch (opcode)
+ {
+ case MOVE:
+ {
+ res = r;
+ CLEAR_FLAGS(V_FLAG | C_FLAG);
+ calc_n_flag(cpustate, res);
+ calc_z_flag(cpustate, res);
+ break;
+ }
+ case COMP:
+ {
+ res = r ^ 0xffff;
+ CLEAR_FLAGS(V_FLAG | C_FLAG);
+ calc_n_flag(cpustate, res);
+ calc_z_flag(cpustate, res);
+ break;
+ }
+ case INC:
+ {
+ res = r + 1;
+ calc_v_flag_add(cpustate, r, 1, res);
+ calc_n_flag(cpustate, res);
+ calc_c_flag_add(cpustate, r, 1);
+ calc_z_flag(cpustate, res);
+ break;
+ }
+ case NEG:
+ {
+ res = (r ^ 0xffff) + 1;
+ calc_v_flag_sub(cpustate, 0, r, res);
+ calc_n_flag(cpustate, res);
+ calc_c_flag_sub(cpustate, 0, r);
+ calc_z_flag(cpustate, res);
+ break;
+ }
+ default: assert(0);
+ }
+
+ return res & 0xffff;
+}
+
+static void sor(esrip_state *cpustate, UINT16 inst)
+{
+ UINT16 r = 0;
+ UINT16 dst = 0;
+ UINT16 res = 0;
+
+ if (BYTE_MODE)
+ {
+ printf("Byte Mode! %.4x\n", inst);
+ UNHANDLED;
+ }
+
+ switch ((inst >> 5) & 0xf)
+ {
+ case SORA: r = cpustate->ram[RAM_ADDR]; dst = ACC; break;
+ case SORY: r = cpustate->ram[RAM_ADDR]; dst = Y_BUS; break;
+ case SORS: r = cpustate->ram[RAM_ADDR]; dst = STATUS; break;
+ case SOAR: r = cpustate->acc; dst = RAM; break;
+ case SODR: r = cpustate->d_latch; dst = RAM; break;
+ case SOIR:
+ {
+ if (cpustate->immflag == 0) // Macrofiy this?
+ {
+ cpustate->i_latch = inst;
+ cpustate->immflag = 1;
+ return;
+ }
+ else
+ {
+ r = cpustate->inst;
+ dst = RAM;
+ cpustate->immflag = 0;
+ }
+ break;
+ }
+ case SOZR: r = 0; dst = RAM; break;
+ case SORR: r = cpustate->ram[RAM_ADDR]; dst = RAM; break;
+ default: UNHANDLED;
+ }
+
+ /* Operation */
+ res = sor_op(cpustate, r, (inst >> 9) & 0xf);
+
+ switch (dst)
+ {
+ case Y_BUS: break;
+ case ACC: cpustate->acc = res; break;
+ case RAM: cpustate->ram[RAM_ADDR] = res; break;
+ default: UNHANDLED;
+ }
+
+ cpustate->result = res;
+}
+
+enum
+{
+ SOA = 0x4,
+ SOD = 0x6,
+ SOI = 0x7,
+ SOZ = 0x8,
+ SOZE = 0x9,
+ SOSE = 0xa,
+};
+
+enum
+{
+ NRY = 0,
+ NRA = 1,
+ NRS = 4,
+ NRAS = 5,
+};
+
+static void sonr(esrip_state *cpustate, UINT16 inst)
+{
+ UINT16 r = 0;
+ UINT16 res = 0;
+
+ switch ((inst >> 5) & 0xf)
+ {
+ case SOA: r = cpustate->acc; break;
+ case SOD: r = cpustate->d_latch; break;
+ case SOI:
+ {
+ if (cpustate->immflag == 0)
+ {
+ cpustate->i_latch = inst;
+ cpustate->immflag = 1;
+ return;
+ }
+ else
+ {
+ r = cpustate->inst;
+ cpustate->immflag = 0;
+ }
+ break;
+ }
+ case SOZ: r = 0; break;
+ default: INVALID;
+ }
+
+ /* Operation */
+ res = sor_op(cpustate, r, (inst >> 9) & 0xf);
+
+ /* Destination */
+ switch (inst & 0x1f)
+ {
+ case NRY: break;
+ case NRA: cpustate->acc = res; break;
+ default: UNHANDLED;
+ }
+
+ cpustate->result = res;
+}
+
+/*************************************
+ *
+ * Two operand
+ *
+ *************************************/
+
+enum
+{
+ SUBR = 0x0,
+ SUBRC = 0x1,
+ SUBS = 0x2,
+ SUBSC = 0x3,
+ ADD = 0x4,
+ ADDC = 0x5,
+ AND = 0x6,
+ NAND = 0x7,
+ EXOR = 0x8,
+ NOR = 0x9,
+ OR = 0xa,
+ EXNOR = 0xb
+};
+
+static UINT16 tor_op(esrip_state *cpustate, UINT16 r, UINT16 s, int opcode)
+{
+ UINT32 res = 0;
+
+ switch (opcode)
+ {
+ case SUBR:
+ {
+ res = s - r;
+ calc_v_flag_sub(cpustate, s, r, res);
+ calc_n_flag(cpustate, res);
+ calc_c_flag_sub(cpustate, s, r);
+ calc_z_flag(cpustate, res);
+ break;
+ }
+ case SUBRC: assert(0); break;
+ case SUBS:
+ {
+ res = r - s;
+ calc_v_flag_sub(cpustate, r, s, res);
+ calc_n_flag(cpustate, res);
+ calc_c_flag_sub(cpustate, r, s);
+ calc_z_flag(cpustate, res);
+ break;
+ }
+ case SUBSC: assert(0); break;
+ case ADD:
+ {
+ res = r + s;
+ calc_v_flag_add(cpustate, r, s, res);
+ calc_n_flag(cpustate, res);
+ calc_c_flag_add(cpustate, r, s);
+ calc_z_flag(cpustate, res);
+ break;
+ }
+ case ADDC:
+ {
+ // TODO TODO CHECK ME ETC
+ res = r + s + ((cpustate->status >> 1) & 1);
+ calc_v_flag_add(cpustate, r, s, res);
+ calc_n_flag(cpustate, res);
+ calc_c_flag_add(cpustate, r, s);
+ calc_z_flag(cpustate, res);
+ break;
+ }
+ case AND:
+ {
+ res = r & s;
+ CLEAR_FLAGS(V_FLAG | C_FLAG);
+ calc_n_flag(cpustate, res);
+ calc_z_flag(cpustate, res);
+ break;
+ }
+ case NAND:
+ {
+ res = (r & s) ^ 0xffff;
+ CLEAR_FLAGS(V_FLAG | C_FLAG);
+ calc_n_flag(cpustate, res);
+ calc_z_flag(cpustate, res);
+ break;
+ }
+ case EXOR:
+ {
+ res = r ^ s;
+ CLEAR_FLAGS(V_FLAG | C_FLAG);
+ calc_n_flag(cpustate, res);
+ calc_z_flag(cpustate, res);
+ break;
+ }
+ case NOR:
+ {
+ res = (r | s) ^ 0xffff;
+ CLEAR_FLAGS(V_FLAG | C_FLAG);
+ calc_n_flag(cpustate, res);
+ calc_z_flag(cpustate, res);
+ break;
+ }
+ case OR:
+ {
+ res = r | s;
+ CLEAR_FLAGS(V_FLAG | C_FLAG);
+ calc_n_flag(cpustate, res);
+ calc_z_flag(cpustate, res);
+ break;
+ }
+ case EXNOR:
+ {
+ res = (r ^ s) ^ 0xffff;
+ CLEAR_FLAGS(V_FLAG | N_FLAG | C_FLAG);
+ calc_z_flag(cpustate, res);
+ break;
+ }
+ default: assert(0);
+ }
+
+ return res & 0xffff;
+}
+
+static void tor1(esrip_state *cpustate, UINT16 inst)
+{
+ UINT16 r = 0;
+ UINT16 s = 0;
+ UINT16 dst = 0;
+ UINT16 res = 0;
+
+ enum
+ {
+ TORAA = 0x0,
+ TORIA = 0x2,
+ TODRA = 0x3,
+ TORAY = 0x8,
+ TORIY = 0xa,
+ TODRY = 0xb,
+ TORAR = 0xc,
+ TORIR = 0xe,
+ TODRR = 0xf,
+ };
+
+ switch (SRC)
+ {
+ case TORAA: r = cpustate->ram[RAM_ADDR]; s = cpustate->acc; dst = ACC; break;
+ case TORIA:
+ {
+ if (cpustate->immflag == 0)
+ {
+ cpustate->i_latch = inst;
+ cpustate->immflag = 1;
+ return;
+ }
+ else
+ {
+ r = cpustate->ram[RAM_ADDR];
+ s = cpustate->inst;
+ dst = ACC;
+ cpustate->immflag = 0;
+ }
+ break;
+ }
+ case TODRA: r = cpustate->d_latch; s = cpustate->ram[RAM_ADDR]; dst = ACC; break;
+ case TORAY: r = cpustate->ram[RAM_ADDR]; s = cpustate->acc; dst = Y_BUS;break;
+ case TORIY:
+ {
+ if (cpustate->immflag == 0)
+ {
+ cpustate->i_latch = inst;
+ cpustate->immflag = 1;
+ return;
+ }
+ else
+ {
+ r = cpustate->ram[RAM_ADDR];
+ s = cpustate->inst;
+ dst = Y_BUS;
+ cpustate->immflag = 0;
+ }
+ break;
+ }
+ case TODRY: r = cpustate->d_latch; s = cpustate->ram[RAM_ADDR]; dst = Y_BUS;break;
+ case TORAR: r = cpustate->ram[RAM_ADDR]; s = cpustate->acc; dst = RAM; break;
+ case TORIR:
+ {
+ if (cpustate->immflag == 0)
+ {
+ cpustate->i_latch = inst;
+ cpustate->immflag = 1;
+ return;
+ }
+ else
+ {
+ r = cpustate->ram[RAM_ADDR];
+ s = cpustate->inst;
+ dst = RAM;
+ cpustate->immflag = 0;
+ }
+ break;
+ }
+ case TODRR: r = cpustate->d_latch; s = cpustate->ram[RAM_ADDR]; dst = RAM; break;
+ default: INVALID;
+ }
+
+ /* Operation */
+ res = tor_op(cpustate, r, s, (inst >> 5) & 0xf);
+
+ /* Destination */
+ switch (dst)
+ {
+ case ACC: cpustate->acc = res; break;
+ case Y_BUS: break;
+ case RAM: cpustate->ram[RAM_ADDR] = res; break;
+ default: INVALID;
+ }
+
+ cpustate->result = res;
+}
+
+static void tor2(esrip_state *cpustate, UINT16 inst)
+{
+ UINT16 r = 0;
+ UINT16 s = 0;
+ UINT32 res = 0;
+
+ enum
+ {
+ TODAR = 0x1,
+ TOAIR = 0x2,
+ TODIR = 0x5,
+ };
+
+ switch (SRC)
+ {
+ case TODAR: r = cpustate->d_latch; s = cpustate->acc; break;
+ case TOAIR:
+ {
+ if (cpustate->immflag == 0)
+ {
+ cpustate->i_latch = inst;
+ cpustate->immflag = 1;
+ return;
+ }
+ else
+ {
+ r = cpustate->acc;
+ s = cpustate->inst;
+ cpustate->immflag = 0;
+ }
+ break;
+ }
+ case TODIR:
+ {
+ if (cpustate->immflag == 0)
+ {
+ cpustate->i_latch = inst;
+ cpustate->immflag = 1;
+ return;
+ }
+ else
+ {
+ r = cpustate->d_latch;
+ s = cpustate->inst;
+ cpustate->immflag = 0;
+ }
+ break;
+ }
+ default: INVALID;
+ }
+
+ /* Operation */
+ res = tor_op(cpustate, r, s, (inst >> 5) & 0xf);
+
+ /* Destination is always RAM */
+ cpustate->ram[RAM_ADDR] = res;
+
+ cpustate->result = res;
+}
+
+static void tonr(esrip_state *cpustate, UINT16 inst)
+{
+ enum
+ {
+ TODA = 0x1,
+ TOAI = 0x2,
+ TODI = 0x5
+ };
+
+ enum
+ {
+ NRY = 0,
+ NRA = 1,
+ NRS = 4,
+ NRAS = 5,
+ };
+
+ UINT16 r = 0;
+ UINT16 s = 0;
+ UINT16 res = 0;
+
+ switch (SRC)
+ {
+ case TODA:
+ {
+ r = cpustate->d_latch;
+ s = cpustate->acc;
+ break;
+ }
+ case TOAI:
+ {
+ break;
+ }
+ case TODI:
+ {
+ if (cpustate->immflag == 0)
+ {
+ cpustate->i_latch = inst;
+ cpustate->immflag = 1;
+ return;
+ }
+ else
+ {
+ r = cpustate->d_latch;
+ s = cpustate->inst;
+ cpustate->immflag = 0;
+ }
+ break;
+ }
+ default: INVALID;
+ }
+
+ /* Operation */
+ res = tor_op(cpustate, r, s, (inst >> 5) & 0xf);
+
+ /* Destination */
+ switch (DST)
+ {
+ case NRY:
+ break;
+ case NRA:
+ cpustate->acc = res;
+ break;
+ case NRS:
+ UNHANDLED;
+ break;
+ case NRAS:
+ UNHANDLED;
+ break;
+ default:
+ INVALID;
+ }
+ cpustate->result = res;
+}
+
+/*************************************
+ *
+ * Bit operation
+ *
+ *************************************/
+
+static void bonr(esrip_state *cpustate, UINT16 inst)
+{
+ enum
+ {
+ TSTNA = 0x00,
+ RSTNA = 0x01,
+ SETNA = 0x02,
+ A2NA = 0x04,
+ S2NA = 0x05,
+ LD2NA = 0x06,
+ LDC2NA = 0x07,
+ TSTND = 0x10,
+ RSTND = 0x11,
+ SETND = 0x12,
+ A2NDY = 0x14,
+ S2NDY = 0x15,
+ LD2NY = 0x16,
+ LDC2NY = 0x17,
+ };
+
+ UINT16 res = 0;
+
+ switch (inst & 0x1f)
+ {
+ case TSTNA:
+ {
+ res = cpustate->acc & (1 << N);
+ CLEAR_FLAGS(V_FLAG | C_FLAG);
+ calc_n_flag(cpustate, res);
+ calc_z_flag(cpustate, res);
+ break;
+ }
+ case RSTNA:
+ {
+ res = cpustate->acc & ~(1 << N);
+ CLEAR_FLAGS(V_FLAG | C_FLAG);
+ calc_n_flag(cpustate, res);
+ calc_z_flag(cpustate, res);
+ cpustate->acc = res;
+ break;
+ }
+ case SETNA:
+ {
+ res = cpustate->acc | (1 << N);
+ CLEAR_FLAGS(V_FLAG | C_FLAG | Z_FLAG);
+ calc_n_flag(cpustate, res);
+ cpustate->acc = res;
+ break;
+ }
+ case A2NA:
+ {
+ UINT16 r = cpustate->acc;
+ UINT16 s = 1 << N;
+ res = r + s;
+ calc_z_flag(cpustate, res);
+ calc_n_flag(cpustate, res);
+ calc_c_flag_add(cpustate, r, s);
+ calc_v_flag_add(cpustate, r, s, res);
+ cpustate->acc = res;
+ break;
+ }
+ case S2NA:
+ {
+ UINT16 r = cpustate->acc;
+ UINT16 s = 1 << N;
+ res = r - s;
+ calc_z_flag(cpustate, res);
+ calc_n_flag(cpustate, res);
+ calc_c_flag_sub(cpustate, r, s);
+ calc_v_flag_sub(cpustate, r, s, res);
+ cpustate->acc = res;
+ break;
+ }
+
+ case TSTND:
+ {
+ res = cpustate->d_latch & (1 << N);
+ CLEAR_FLAGS(V_FLAG | C_FLAG);
+ calc_n_flag(cpustate, res);
+ calc_z_flag(cpustate, res);
+ break;
+ }
+
+ case SETND:
+ {
+ UINT16 r = cpustate->d_latch;
+ res = r | (1 << N);
+ cpustate->d_latch = res;
+
+ CLEAR_FLAGS(V_FLAG | C_FLAG | Z_FLAG);
+ calc_n_flag(cpustate, res);
+ break;
+ }
+ case LD2NY:
+ {
+ res = (1 << N);
+ CLEAR_FLAGS(V_FLAG | C_FLAG | Z_FLAG);
+ calc_n_flag(cpustate, res);
+ break;
+ }
+ case LDC2NY:
+ {
+ res = (1 << N) ^ 0xffff;
+ CLEAR_FLAGS(Z_FLAG | C_FLAG | V_FLAG);
+ calc_n_flag(cpustate, res);
+ break;
+ }
+
+ case A2NDY:
+ {
+ UINT16 r = cpustate->d_latch;
+ UINT16 s = 1 << N;
+ res = r + s;
+
+ calc_z_flag(cpustate, res);
+ calc_n_flag(cpustate, res);
+ calc_c_flag_add(cpustate, r, s);
+ calc_v_flag_add(cpustate, r, s, res);
+ break;
+ }
+
+ default:
+ UNHANDLED;
+ }
+
+ cpustate->result = res;
+}
+
+static void bor1(esrip_state *cpustate, UINT16 inst)
+{
+ enum
+ {
+ SETNR = 0xd,
+ RSTNR = 0xe,
+ TSTNR = 0xf,
+ };
+
+ UINT16 res = 0;
+
+ switch ((inst >> 5) & 0xf)
+ {
+ case SETNR:
+ {
+ res = cpustate->ram[RAM_ADDR] | (1 << N);
+ cpustate->ram[RAM_ADDR] = res;
+ CLEAR_FLAGS(V_FLAG | C_FLAG | Z_FLAG);
+ calc_n_flag(cpustate, res);
+ break;
+ }
+ case RSTNR:
+ {
+ res = cpustate->ram[RAM_ADDR] & ~(1 << N);
+ cpustate->ram[RAM_ADDR] = res;
+ CLEAR_FLAGS(V_FLAG | C_FLAG);
+ calc_n_flag(cpustate, res);
+ calc_z_flag(cpustate, res);
+ break;
+ }
+ case TSTNR:
+ {
+ res = cpustate->ram[RAM_ADDR] & (1 << N);
+ CLEAR_FLAGS(V_FLAG | C_FLAG);
+ calc_n_flag(cpustate, res);
+ calc_z_flag(cpustate, res);
+ break;
+ }
+ default: INVALID;
+ }
+
+ cpustate->result = res;
+}
+
+
+
+static void bor2(esrip_state *cpustate, UINT16 inst)
+{
+ enum
+ {
+ LD2NR = 0xc,
+ LDC2NR = 0xd,
+ A2NR = 0xe,
+ S2NR = 0xf,
+ };
+
+ UINT32 res = 0;
+
+ switch ((inst >> 5) & 0xf)
+ {
+ case LD2NR:
+ {
+ res = 1 << N;
+ CLEAR_FLAGS(V_FLAG | C_FLAG | Z_FLAG);
+ calc_n_flag(cpustate, res);
+ break;
+ }
+ case LDC2NR:
+ {
+ res = (1 << N) ^ 0xffff;
+ CLEAR_FLAGS(V_FLAG | C_FLAG | Z_FLAG);
+ calc_n_flag(cpustate, res);
+ break;
+ }
+ case A2NR:
+ {
+ UINT16 r = cpustate->ram[RAM_ADDR];
+ UINT16 s = 1 << N;
+
+ res = r + s;
+ calc_v_flag_add(cpustate, r, s, res);
+ calc_n_flag(cpustate, res);
+ calc_c_flag_add(cpustate, r, s);
+ calc_z_flag(cpustate, res);
+ break;
+ }
+ case S2NR:
+ {
+ UINT16 r = cpustate->ram[RAM_ADDR];
+ UINT16 s = 1 << N;
+
+ res = r - s;
+ calc_v_flag_sub(cpustate, r, s, res);
+ calc_n_flag(cpustate, res);
+ calc_c_flag_sub(cpustate, r, s);
+ calc_z_flag(cpustate, res);
+ break;
+ }
+ default: INVALID;
+ }
+
+ /* Destination is RAM */
+ cpustate->ram[RAM_ADDR] = res;
+ cpustate->result = res;
+}
+
+/*************************************
+ *
+ * Rotate
+ *
+ *************************************/
+
+/* TODO Combine these */
+static void rotr1(esrip_state *cpustate, UINT16 inst)
+{
+ enum
+ {
+ RTRA = 0xc,
+ RTRY = 0xd,
+ RTRR = 0xf,
+ };
+
+ UINT16 u = 0;
+ UINT16 dst = 0;
+ UINT16 res = 0;
+ int n = N;
+
+ switch ((inst >> 5) & 0xf)
+ {
+ case RTRA: u = cpustate->ram[RAM_ADDR]; dst = ACC; break;
+ case RTRY: u = cpustate->ram[RAM_ADDR]; dst = Y_BUS; break;
+ case RTRR: u = cpustate->ram[RAM_ADDR]; dst = RAM; break;
+ default: INVALID;
+ }
+
+ res = (u << n) | (u >> (16 - n));
+ CLEAR_FLAGS(V_FLAG | C_FLAG);
+ calc_n_flag(cpustate, res);
+ calc_z_flag(cpustate, res);
+
+ switch (dst)
+ {
+ case ACC: cpustate->acc = res; break;
+ case RAM: cpustate->ram[RAM_ADDR] = res; break;
+ }
+
+ cpustate->result = res;
+}
+
+static void rotr2(esrip_state *cpustate, UINT16 inst)
+{
+ enum
+ {
+ RTAR = 0,
+ RTDR = 1,
+ };
+
+ UINT16 u = 0;
+ UINT16 res = 0;
+
+ switch ((inst >> 5) & 0xf)
+ {
+ case RTAR: u = cpustate->acc; break;
+ case RTDR: u = cpustate->d_latch; break;
+ default: INVALID;
+ }
+
+ res = (u << N) | (u >> (16 - N));
+ CLEAR_FLAGS(V_FLAG | C_FLAG);
+ calc_n_flag(cpustate, res);
+ calc_z_flag(cpustate, res);
+ cpustate->ram[RAM_ADDR] = res;
+
+ cpustate->result = res;
+}
+
+static void rotnr(esrip_state *cpustate, UINT16 inst)
+{
+ enum
+ {
+ RTDY = 0x18,
+ RTDA = 0x19,
+ RTAY = 0x1c,
+ RTAA = 0x1d,
+ };
+
+ UINT16 u = 0;
+ UINT16 res = 0;
+ UINT16 dst = 0;
+
+ switch (inst & 0x1f)
+ {
+ case RTDY: u = cpustate->d_latch; dst = Y_BUS; break;
+ case RTDA: u = cpustate->d_latch; dst = ACC; break;
+ case RTAY: u = cpustate->acc; dst = Y_BUS; break;
+ case RTAA: u = cpustate->acc; dst = ACC; break;
+ default: INVALID;
+ }
+
+ res = (u << N) | (u >> (16 - N));
+ CLEAR_FLAGS(V_FLAG | C_FLAG);
+ calc_n_flag(cpustate, res);
+ calc_z_flag(cpustate, res);
+
+ switch (dst)
+ {
+ case Y_BUS: break;
+ case ACC: cpustate->acc = res; break;
+ case RAM: cpustate->ram[RAM_ADDR] = res; break;
+ default: UNHANDLED;
+ }
+
+ cpustate->result = res;
+}
+
+/*************************************
+ *
+ * Rotate and compare
+ *
+ *************************************/
+
+static void rotc(esrip_state *cpustate, UINT16 inst)
+{
+ UNHANDLED;
+}
+
+/*************************************
+ *
+ * Rotate and merge
+ *
+ *************************************/
+
+static void rotm(esrip_state *cpustate, UINT16 inst)
+{
+ UNHANDLED;
+}
+
+/*************************************
+ *
+ * Prioritize
+ *
+ *************************************/
+
+static void prt(esrip_state *cpustate, UINT16 inst)
+{
+ UNHANDLED;
+}
+
+static void prtnr(esrip_state *cpustate, UINT16 inst)
+{
+ UNHANDLED;
+}
+
+
+/*************************************
+ *
+ * CRC
+ *
+ *************************************/
+
+static void crcf(esrip_state *cpustate, UINT16 inst)
+{
+ UNHANDLED;
+}
+
+static void crcr(esrip_state *cpustate, UINT16 inst)
+{
+ UNHANDLED;
+}
+
+/*************************************
+ *
+ * Single bit shift
+ *
+ *************************************/
+
+enum
+{
+ SHUPZ = 0,
+ SHUP1 = 1,
+ SHUPL = 2,
+ SHDNZ = 4,
+ SHDN1 = 5,
+ SHDNL = 6,
+ SHDNC = 7,
+ SHDNOV = 8,
+};
+
+#define SET_LINK_flag(cpustate, x) (cpustate->new_status &= ~L_FLAG); \
+ (cpustate->new_status |= x ? L_FLAG : 0)
+
+static UINT16 shift_op(esrip_state *cpustate, UINT16 u, int opcode)
+{
+ UINT32 res = 0;
+
+ switch (opcode)
+ {
+ case SHUPZ:
+ {
+ res = (u << 1);
+ SET_LINK_flag(cpustate, u & 0x8000);
+ CLEAR_FLAGS(V_FLAG | C_FLAG);
+ calc_n_flag(cpustate, res);
+ calc_z_flag(cpustate, res);
+ break;
+ }
+ case SHUP1:
+ {
+ res = (u << 1) | 1;
+ SET_LINK_flag(cpustate, u & 0x8000);
+ CLEAR_FLAGS(V_FLAG | C_FLAG);
+ calc_n_flag(cpustate, res);
+ calc_z_flag(cpustate, res);
+ break;
+ }
+ case SHUPL:
+ {
+ res = (u << 1) | ((cpustate->status & L_FLAG) ? 1 : 0);
+ SET_LINK_flag(cpustate, u & 0x8000);
+ CLEAR_FLAGS(V_FLAG | C_FLAG);
+ calc_n_flag(cpustate, res);
+ calc_z_flag(cpustate, res);
+ break;
+ }
+
+ case SHDNZ:
+ case SHDN1:
+ case SHDNL:
+ case SHDNC:
+ case SHDNOV:
+ default: assert(0);
+ }
+
+ return res;
+}
+
+static void shftr(esrip_state *cpustate, UINT16 inst)
+{
+ enum
+ {
+ SHRR = 6,
+ SHDR = 7,
+ };
+
+ UINT16 u = 0;
+ UINT16 res = 0;
+
+ switch ((inst >> 9) & 0xf)
+ {
+ case SHRR: u = cpustate->ram[RAM_ADDR]; break;
+ case SHDR: u = cpustate->d_latch; break;
+ default: INVALID;
+ }
+
+ res = shift_op(cpustate, u, (inst >> 5) & 0xf);
+
+ /* Destination is always RAM */
+ cpustate->ram[RAM_ADDR] = res;
+ cpustate->result = res;
+}
+
+static void shftnr(esrip_state *cpustate, UINT16 inst)
+{
+ enum
+ {
+ SHA = 6,
+ SHD = 7,
+ };
+
+ UINT16 u = 0;
+ UINT16 res = 0;
+
+ switch ((inst >> 9) & 0xf)
+ {
+ case SHA: u = cpustate->acc; break;
+ case SHD: u = cpustate->d_latch; break;
+ default: INVALID;
+ }
+
+ res = shift_op(cpustate, u, (inst >> 5) & 0xf);
+
+ switch (DST)
+ {
+ case NRY: break;
+ case NRA: cpustate->acc = res; break;
+ default: INVALID;
+ }
+ cpustate->result = res;
+}
+
+
+/*************************************
+ *
+ * Status
+ *
+ *************************************/
+
+static void svstr(esrip_state *cpustate, UINT16 inst)
+{
+ UNHANDLED;
+}
+
+static void rstst(esrip_state *cpustate, UINT16 inst)
+{
+ enum
+ {
+ RONCZ = 0x3,
+ RL = 0x5,
+ RF1 = 0x6,
+ RF2 = 0x9,
+ RF3 = 0xa,
+ };
+
+ switch (inst & 0x1f)
+ {
+ case RONCZ: CLEAR_FLAGS(V_FLAG | N_FLAG | C_FLAG | Z_FLAG); break;
+ case RL: CLEAR_FLAGS(L_FLAG); break;
+ case RF1: CLEAR_FLAGS(FLAG_1); break;
+ case RF2: CLEAR_FLAGS(FLAG_2); break;
+ case RF3: CLEAR_FLAGS(FLAG_3); break;
+ }
+
+ cpustate->result = 0;
+}
+
+static void setst(esrip_state *cpustate, UINT16 inst)
+{
+ enum
+ {
+ SONCZ = 0x3,
+ SL = 0x5,
+ SF1 = 0x6,
+ SF2 = 0x9,
+ SF3 = 0xa,
+ };
+
+ switch (inst & 0x1f)
+ {
+ case SONCZ: SET_FLAGS(V_FLAG | N_FLAG | C_FLAG | Z_FLAG); break;
+ case SL: SET_FLAGS(L_FLAG); break;
+ case SF1: SET_FLAGS(FLAG_1); break;
+ case SF2: SET_FLAGS(FLAG_2); break;
+ case SF3: SET_FLAGS(FLAG_3); break;
+ }
+
+ cpustate->result = 0xffff;
+}
+
+static void test(esrip_state *cpustate, UINT16 inst)
+{
+ enum
+ {
+ TNOZ = 0x00,
+ TNO = 0x02,
+ TZ = 0x04,
+ TOVR = 0x06,
+ TLOW = 0x08,
+ TC = 0x0a,
+ TZC = 0x0c,
+ TN = 0x0e,
+ TL = 0x10,
+ TF1 = 0x12,
+ TF2 = 0x14,
+ TF3 = 0x16
+ };
+
+ UINT32 res = 0;
+
+ switch (inst & 0x1f)
+ {
+ case TNOZ: UNHANDLED; break;
+ case TNO: UNHANDLED; break;
+ case TZ: res = cpustate->status & (Z_FLAG); break;
+ case TOVR: res = cpustate->status & (V_FLAG); break;
+ case TLOW: UNHANDLED; break;
+ case TC: res = cpustate->status & (C_FLAG); break;
+ case TZC: UNHANDLED; break;
+ case TN: res = cpustate->status & (N_FLAG); break;
+ case TL: res = cpustate->status & (L_FLAG); break;
+ case TF1: res = cpustate->status & (FLAG_1); break;
+ case TF2: res = cpustate->status & (FLAG_2); break;
+ case TF3: res = cpustate->status & (FLAG_3); break;
+ default: INVALID;
+ }
+
+ cpustate->ct = res && 1;
+}
+
+
+/*************************************
+ *
+ * No operation
+ *
+ *************************************/
+
+static void nop(esrip_state *cpustate, UINT16 inst)
+{
+ cpustate->result = 0xff; // Undefined
+}
+
+static void (*const operations[24])(esrip_state *cpustate, UINT16 inst) =
+{
+ rotr1, tor1, rotr2, rotc, rotm, bor2, crcf, crcr,
+ svstr, prt, sor, tor2, shftr, test, nop, setst, rstst,
+ rotnr, bonr, bor1, sonr, shftnr, prtnr, tonr
+};
+
+INLINE void am29116_execute(esrip_state *cpustate, UINT16 inst, int _sre)
+{
+ /* Status register shadow */
+ cpustate->new_status = cpustate->status;
+
+ /* Required for immediate source instructions */
+ cpustate->inst = inst;
+
+ if (cpustate->immflag == 1)
+ inst = cpustate->i_latch;
+
+ (*operations[cpustate->optable[inst]])(cpustate, inst);
+
+ if (!_sre)
+ {
+ cpustate->status = cpustate->new_status;
+ cpustate->t = cpustate->status;
+ }
+}
+
+
+static CPU_EXECUTE( esrip )
+{
+ esrip_state *cpustate = get_safe_token(device);
+ int calldebugger = (device->machine().debug_flags & DEBUG_FLAG_ENABLED) != 0;
+ UINT8 status;
+
+ /* I think we can get away with placing this outside of the loop */
+ status = cpustate->status_in(device->machine());
+
+ /* Core execution loop */
+ do
+ {
+ UINT64 inst;
+ UINT8 next_pc;
+ UINT16 x_bus = 0;
+ UINT16 ipt_bus = 0;
+ UINT16 y_bus = 0;
+
+ int yoe = _BIT(cpustate->l5, 1);
+ int bl46 = BIT(cpustate->l4, 6);
+ int bl44 = BIT(cpustate->l4, 4);
+
+ UINT32 in_h;
+ UINT32 in_l;
+
+ if (cpustate->fig_cycles)
+ {
+ if (--cpustate->fig_cycles == 0)
+ cpustate->fig = 0;
+ }
+
+ /* /OEY = 1 : Y-bus is high imped */
+ if (yoe)
+ {
+ /* Status In */
+ if (!_BIT(cpustate->l2, 0))
+ y_bus = status | (!cpustate->fig << 3);
+
+ /* FDT RAM: /Enable, Direction and /RAM OE */
+ else if (!bl44 && !_BIT(cpustate->l2, 3) && bl46)
+ y_bus = cpustate->fdt_r(device, cpustate->fdt_cnt, 0);
+
+ /* IPT RAM: /Enable and /READ */
+ else if (!_BIT(cpustate->l2, 6) && !_BIT(cpustate->l4, 5))
+ y_bus = cpustate->ipt_ram[cpustate->ipt_cnt];
+
+ /* DLE - latch the value on the Y-BUS into the data latch */
+ if (_BIT(cpustate->l5, 0))
+ cpustate->d_latch = y_bus;
+
+ /* Now execute the AM29116 instruction */
+ am29116_execute(cpustate, (cpustate->l7 << 8) | cpustate->l6, BIT(cpustate->l5, 2));
+ }
+ else
+ {
+ am29116_execute(cpustate, (cpustate->l7 << 8) | cpustate->l6, BIT(cpustate->l5, 2));
+
+ y_bus = cpustate->result;
+
+ if (BIT(cpustate->l5, 0))
+ cpustate->d_latch = y_bus;
+ }
+
+ /* Determine what value is on the X-Bus */
+
+ /* FDT RAM */
+ if (!bl44)
+ x_bus = cpustate->fdt_r(device, cpustate->fdt_cnt, 0);
+
+ /* Buffer is enabled - write direction */
+ else if (!BIT(cpustate->l2, 3) && !bl46)
+ {
+ if (!yoe)
+ x_bus = y_bus;
+ else if ( !BIT(cpustate->l2, 6) && !BIT(cpustate->l4, 5) )
+ x_bus = cpustate->ipt_ram[cpustate->ipt_cnt];
+ }
+
+ /* IPT BUS */
+ if (!BIT(cpustate->l2, 6))
+ ipt_bus = cpustate->ipt_ram[cpustate->ipt_cnt];
+ else if (!BIT(cpustate->l4, 5))
+ {
+ if (!BIT(cpustate->l5, 1))
+ ipt_bus = y_bus;
+ else
+ ipt_bus = x_bus;
+ }
+
+
+ /* Write FDT RAM: /Enable, Direction and WRITE */
+ if (!BIT(cpustate->l2, 3) && !bl46 && !BIT(cpustate->l4, 3))
+ cpustate->fdt_w(device, cpustate->fdt_cnt, x_bus, 0);
+
+ /* Write IPT RAM: /Enable and /WR */
+ if (!BIT(cpustate->l2, 7) && !BIT(cpustate->l4, 5))
+ cpustate->ipt_ram[cpustate->ipt_cnt] = ipt_bus;
+
+
+ if ((((cpustate->l5 >> 3) & 0x1f) & 0x18) != 0x18)
+ {
+ if ( check_jmp(cpustate, (cpustate->l5 >> 3) & 0x1f) )
+ next_pc = cpustate->l1;
+ else
+ next_pc = cpustate->pc + 1;
+ }
+ else
+ next_pc = cpustate->pc + 1;
+
+ cpustate->pl1 = cpustate->l1;
+ cpustate->pl2 = cpustate->l2;
+ cpustate->pl3 = cpustate->l3;
+ cpustate->pl4 = cpustate->l4;
+ cpustate->pl5 = cpustate->l5;
+ cpustate->pl6 = cpustate->l6;
+ cpustate->pl7 = cpustate->l7;
+
+ /* Latch instruction */
+ inst = cpustate->direct->read_decrypted_qword(RIP_PC << 3);
+
+ in_h = inst >> 32;
+ in_l = inst & 0xffffffff;
+
+ cpustate->l1 = (in_l >> 8);
+ cpustate->l2 = (in_l >> 16);
+ cpustate->l3 = (in_l >> 24);
+
+ cpustate->l4 = (in_h >> 0);
+ cpustate->l5 = (in_h >> 8);
+ cpustate->l6 = (in_h >> 16);
+ cpustate->l7 = (in_h >> 24);
+
+ /* Colour latch */
+ if (RISING_EDGE(cpustate->pl3, cpustate->l3, 0))
+ cpustate->c_latch = (x_bus >> 12) & 0xf;
+
+ /* Right pixel line buffer address */
+ if (RISING_EDGE(cpustate->pl3, cpustate->l3, 1))
+ cpustate->adr_latch = x_bus & 0xfff;
+
+ /* Left pixel line buffer address */
+ if (RISING_EDGE(cpustate->pl3, cpustate->l3, 2))
+ cpustate->adl_latch = x_bus & 0xfff;
+
+ /* FIGLD: Start the DMA */
+ if (RISING_EDGE(cpustate->pl3, cpustate->l3, 3))
+ {
+ cpustate->attr_latch = x_bus;
+
+ cpustate->fig = 1;
+ cpustate->fig_cycles = cpustate->draw(device->machine(), cpustate->adl_latch, cpustate->adr_latch, cpustate->fig_latch, cpustate->attr_latch, cpustate->iaddr_latch, cpustate->c_latch, cpustate->x_scale, cpustate->img_bank);
+ }
+
+ /* X-scale */
+ if (RISING_EDGE(cpustate->pl3, cpustate->l3, 4))
+ cpustate->x_scale = x_bus >> 8;
+
+ /* Y-scale and image bank */
+ if (RISING_EDGE(cpustate->pl4, cpustate->l4, 2))
+ {
+ cpustate->y_scale = x_bus & 0xff;
+ cpustate->img_bank = (y_bus >> 14) & 3;
+ }
+
+ /* Image ROM address */
+ if (RISING_EDGE(cpustate->pl3, cpustate->l3, 5))
+ cpustate->iaddr_latch = y_bus;
+
+ /* IXLLD */
+ if (RISING_EDGE(cpustate->pl3, cpustate->l3, 6))
+ {
+ cpustate->line_latch = ipt_bus >> 10;
+ cpustate->fig_latch = ipt_bus & 0x3ff;
+ }
+
+ /* Status write */
+ if (RISING_EDGE(cpustate->pl3, cpustate->l3, 7))
+ cpustate->status_out = y_bus & 0xff;
+
+ /* FDT address counter */
+ if (!BIT(cpustate->pl2, 1))
+ cpustate->fdt_cnt = y_bus & 0xfff;
+ else if (BIT(cpustate->pl2, 2))
+ cpustate->fdt_cnt = (cpustate->fdt_cnt + 1) & 0xfff;
+
+ /* Now we can alter the IPT address counter */
+ if (!BIT(cpustate->pl2, 4))
+ cpustate->ipt_cnt = y_bus & 0x1fff;
+ else if (BIT(cpustate->pl2, 5))
+ cpustate->ipt_cnt = (cpustate->ipt_cnt + 1) & 0x1fff;
+
+ if (calldebugger)
+ debugger_instruction_hook(device, RIP_PC);
+
+ cpustate->pc = next_pc;
+
+ cpustate->icount--;
+ } while (cpustate->icount > 0);
+}
+
+
+/**************************************************************************
+ * set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( esrip )
+{
+ esrip_state *cpustate = get_safe_token(device);
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + ESRIP_PC: cpustate->pc = info->i & 0xff;
+ cpustate->status_out &= ~1;
+ cpustate->status_out |= ((info->i >> 8) & 1);
+ break;
+ }
+}
+
+/**************************************************************************
+ * get_info
+ **************************************************************************/
+
+CPU_GET_INFO( esrip )
+{
+ esrip_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(esrip_state); break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 8; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 8; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 1; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 64; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 9; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = -3; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_REGISTER:
+ case CPUINFO_INT_PC: info->i = RIP_PC; break;
+ case CPUINFO_INT_REGISTER + ESRIP_STATW: info->i = cpustate->status_out; break;
+ case CPUINFO_INT_REGISTER + ESRIP_FDTC: info->i = cpustate->fdt_cnt; break;
+ case CPUINFO_INT_REGISTER + ESRIP_IPTC: info->i = cpustate->ipt_cnt; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(esrip); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(esrip); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(esrip); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(esrip); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(esrip); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(esrip); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "Real Time Image Processor"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Entertainment Sciences"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Philip J Bennett"); break;
+
+ case CPUINFO_STR_FLAGS: sprintf(info->s, "%c%c%c%c%c%c%c%c%c",
+ cpustate->status & 0x80 ? '3' : '.',
+ cpustate->status & 0x40 ? '2' : '.',
+ cpustate->status & 0x20 ? '1' : '.',
+ cpustate->status & 0x10 ? 'L' : '.',
+ cpustate->status & 0x08 ? 'V' : '.',
+ cpustate->status & 0x04 ? 'N' : '.',
+ cpustate->status & 0x02 ? 'C' : '.',
+ cpustate->status & 0x01 ? 'Z' : '.',
+ get_hblank(device->machine()) ? 'H' : '.'); break;
+
+ case CPUINFO_STR_REGISTER + ESRIP_PC: sprintf(info->s, "PC: %04X", RIP_PC); break;
+ case CPUINFO_STR_REGISTER + ESRIP_ACC: sprintf(info->s, "ACC: %04X", cpustate->acc); break;
+ case CPUINFO_STR_REGISTER + ESRIP_DLATCH: sprintf(info->s, "DLATCH: %04X", cpustate->d_latch); break;
+ case CPUINFO_STR_REGISTER + ESRIP_ILATCH: sprintf(info->s, "ILATCH: %04X", cpustate->i_latch); break;
+ case CPUINFO_STR_REGISTER + ESRIP_RAM00: sprintf(info->s, "RAM[00]: %04X", cpustate->ram[0x00]); break;
+ case CPUINFO_STR_REGISTER + ESRIP_RAM01: sprintf(info->s, "RAM[01]: %04X", cpustate->ram[0x01]); break;
+ case CPUINFO_STR_REGISTER + ESRIP_RAM02: sprintf(info->s, "RAM[02]: %04X", cpustate->ram[0x02]); break;
+ case CPUINFO_STR_REGISTER + ESRIP_RAM03: sprintf(info->s, "RAM[03]: %04X", cpustate->ram[0x03]); break;
+ case CPUINFO_STR_REGISTER + ESRIP_RAM04: sprintf(info->s, "RAM[04]: %04X", cpustate->ram[0x04]); break;
+ case CPUINFO_STR_REGISTER + ESRIP_RAM05: sprintf(info->s, "RAM[05]: %04X", cpustate->ram[0x05]); break;
+ case CPUINFO_STR_REGISTER + ESRIP_RAM06: sprintf(info->s, "RAM[06]: %04X", cpustate->ram[0x06]); break;
+ case CPUINFO_STR_REGISTER + ESRIP_RAM07: sprintf(info->s, "RAM[07]: %04X", cpustate->ram[0x07]); break;
+ case CPUINFO_STR_REGISTER + ESRIP_RAM08: sprintf(info->s, "RAM[08]: %04X", cpustate->ram[0x08]); break;
+ case CPUINFO_STR_REGISTER + ESRIP_RAM09: sprintf(info->s, "RAM[09]: %04X", cpustate->ram[0x09]); break;
+ case CPUINFO_STR_REGISTER + ESRIP_RAM0A: sprintf(info->s, "RAM[0A]: %04X", cpustate->ram[0x0a]); break;
+ case CPUINFO_STR_REGISTER + ESRIP_RAM0B: sprintf(info->s, "RAM[0B]: %04X", cpustate->ram[0x0b]); break;
+ case CPUINFO_STR_REGISTER + ESRIP_RAM0C: sprintf(info->s, "RAM[0C]: %04X", cpustate->ram[0x0c]); break;
+ case CPUINFO_STR_REGISTER + ESRIP_RAM0D: sprintf(info->s, "RAM[0D]: %04X", cpustate->ram[0x0d]); break;
+ case CPUINFO_STR_REGISTER + ESRIP_RAM0E: sprintf(info->s, "RAM[0E]: %04X", cpustate->ram[0x0e]); break;
+ case CPUINFO_STR_REGISTER + ESRIP_RAM0F: sprintf(info->s, "RAM[0F]: %04X", cpustate->ram[0x0f]); break;
+ case CPUINFO_STR_REGISTER + ESRIP_RAM10: sprintf(info->s, "RAM[10]: %04X", cpustate->ram[0x10]); break;
+ case CPUINFO_STR_REGISTER + ESRIP_RAM11: sprintf(info->s, "RAM[11]: %04X", cpustate->ram[0x11]); break;
+ case CPUINFO_STR_REGISTER + ESRIP_RAM12: sprintf(info->s, "RAM[12]: %04X", cpustate->ram[0x12]); break;
+ case CPUINFO_STR_REGISTER + ESRIP_RAM13: sprintf(info->s, "RAM[13]: %04X", cpustate->ram[0x13]); break;
+ case CPUINFO_STR_REGISTER + ESRIP_RAM14: sprintf(info->s, "RAM[14]: %04X", cpustate->ram[0x14]); break;
+ case CPUINFO_STR_REGISTER + ESRIP_RAM15: sprintf(info->s, "RAM[15]: %04X", cpustate->ram[0x15]); break;
+ case CPUINFO_STR_REGISTER + ESRIP_RAM16: sprintf(info->s, "RAM[16]: %04X", cpustate->ram[0x16]); break;
+ case CPUINFO_STR_REGISTER + ESRIP_RAM17: sprintf(info->s, "RAM[17]: %04X", cpustate->ram[0x17]); break;
+ case CPUINFO_STR_REGISTER + ESRIP_RAM18: sprintf(info->s, "RAM[18]: %04X", cpustate->ram[0x18]); break;
+ case CPUINFO_STR_REGISTER + ESRIP_RAM19: sprintf(info->s, "RAM[19]: %04X", cpustate->ram[0x19]); break;
+ case CPUINFO_STR_REGISTER + ESRIP_RAM1A: sprintf(info->s, "RAM[1A]: %04X", cpustate->ram[0x1a]); break;
+ case CPUINFO_STR_REGISTER + ESRIP_RAM1B: sprintf(info->s, "RAM[1B]: %04X", cpustate->ram[0x1b]); break;
+ case CPUINFO_STR_REGISTER + ESRIP_RAM1C: sprintf(info->s, "RAM[1C]: %04X", cpustate->ram[0x1c]); break;
+ case CPUINFO_STR_REGISTER + ESRIP_RAM1D: sprintf(info->s, "RAM[1D]: %04X", cpustate->ram[0x1d]); break;
+ case CPUINFO_STR_REGISTER + ESRIP_RAM1E: sprintf(info->s, "RAM[1E]: %04X", cpustate->ram[0x1e]); break;
+ case CPUINFO_STR_REGISTER + ESRIP_RAM1F: sprintf(info->s, "RAM[1F]: %04X", cpustate->ram[0x1f]); break;
+ case CPUINFO_STR_REGISTER + ESRIP_STATW: sprintf(info->s, "STAT: %04X", cpustate->status_out); break;
+ case CPUINFO_STR_REGISTER + ESRIP_FDTC: sprintf(info->s, "FDTC: %04X", cpustate->fdt_cnt); break;
+ case CPUINFO_STR_REGISTER + ESRIP_IPTC: sprintf(info->s, "IPTC: %04X", cpustate->ipt_cnt); break;
+ case CPUINFO_STR_REGISTER + ESRIP_XSCALE: sprintf(info->s, "XSCL: %04X", cpustate->x_scale); break;
+ case CPUINFO_STR_REGISTER + ESRIP_YSCALE: sprintf(info->s, "YSCL: %04X", cpustate->y_scale); break;
+ case CPUINFO_STR_REGISTER + ESRIP_BANK: sprintf(info->s, "BANK: %04X", cpustate->img_bank); break;
+ case CPUINFO_STR_REGISTER + ESRIP_LINE: sprintf(info->s, "LINE: %04X", cpustate->line_latch); break;
+ case CPUINFO_STR_REGISTER + ESRIP_FIG: sprintf(info->s, "FIG: %04X", cpustate->fig_latch); break;
+ case CPUINFO_STR_REGISTER + ESRIP_ATTR: sprintf(info->s, "ATTR: %04X", cpustate->attr_latch); break;
+ case CPUINFO_STR_REGISTER + ESRIP_ADRL: sprintf(info->s, "ADRL: %04X", cpustate->adl_latch); break;
+ case CPUINFO_STR_REGISTER + ESRIP_ADRR: sprintf(info->s, "ADRR: %04X", cpustate->adr_latch); break;
+ case CPUINFO_STR_REGISTER + ESRIP_COLR: sprintf(info->s, "COLR: %04X", cpustate->c_latch); break;
+ case CPUINFO_STR_REGISTER + ESRIP_IADDR: sprintf(info->s, "IADR: %04X", cpustate->iaddr_latch); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(ESRIP, esrip);
diff --git a/trunk/src/emu/cpu/esrip/esrip.h b/trunk/src/emu/cpu/esrip/esrip.h
new file mode 100644
index 00000000000..7a06e88bea2
--- /dev/null
+++ b/trunk/src/emu/cpu/esrip/esrip.h
@@ -0,0 +1,101 @@
+/***************************************************************************
+
+ esrip.h
+ Interface file for the Entertainment Sciences RIP
+ Written by Phil Bennett
+
+***************************************************************************/
+
+#ifndef _ESRIP_H
+#define _ESRIP_H
+
+
+/***************************************************************************
+ COMPILE-TIME DEFINITIONS
+***************************************************************************/
+
+
+/***************************************************************************
+ GLOBAL CONSTANTS
+***************************************************************************/
+
+
+/***************************************************************************
+ REGISTER ENUMERATION
+***************************************************************************/
+
+enum
+{
+ ESRIP_PC = 1,
+ ESRIP_ACC,
+ ESRIP_DLATCH,
+ ESRIP_ILATCH,
+ ESRIP_RAM00,
+ ESRIP_RAM01,
+ ESRIP_RAM02,
+ ESRIP_RAM03,
+ ESRIP_RAM04,
+ ESRIP_RAM05,
+ ESRIP_RAM06,
+ ESRIP_RAM07,
+ ESRIP_RAM08,
+ ESRIP_RAM09,
+ ESRIP_RAM0A,
+ ESRIP_RAM0B,
+ ESRIP_RAM0C,
+ ESRIP_RAM0D,
+ ESRIP_RAM0E,
+ ESRIP_RAM0F,
+ ESRIP_RAM10,
+ ESRIP_RAM11,
+ ESRIP_RAM12,
+ ESRIP_RAM13,
+ ESRIP_RAM14,
+ ESRIP_RAM15,
+ ESRIP_RAM16,
+ ESRIP_RAM17,
+ ESRIP_RAM18,
+ ESRIP_RAM19,
+ ESRIP_RAM1A,
+ ESRIP_RAM1B,
+ ESRIP_RAM1C,
+ ESRIP_RAM1D,
+ ESRIP_RAM1E,
+ ESRIP_RAM1F,
+ ESRIP_STATW,
+ ESRIP_FDTC,
+ ESRIP_IPTC,
+ ESRIP_XSCALE,
+ ESRIP_YSCALE,
+ ESRIP_BANK,
+ ESRIP_LINE,
+ ESRIP_FIG,
+ ESRIP_ATTR,
+ ESRIP_ADRL,
+ ESRIP_ADRR,
+ ESRIP_COLR,
+ ESRIP_IADDR,
+};
+
+/***************************************************************************
+ CONFIGURATION STRUCTURE
+***************************************************************************/
+typedef struct _esrip_config_ esrip_config;
+struct _esrip_config_
+{
+ read16_device_func fdt_r;
+ write16_device_func fdt_w;
+ UINT8 (*status_in)(running_machine &machine);
+ int (*draw)(running_machine &machine, int l, int r, int fig, int attr, int addr, int col, int x_scale, int bank);
+ const char* const lbrm_prom;
+};
+
+/***************************************************************************
+ PUBLIC FUNCTIONS
+***************************************************************************/
+
+DECLARE_LEGACY_CPU_DEVICE(ESRIP, esrip);
+
+extern UINT8 get_rip_status(device_t *cpu);
+
+#endif /* _ESRIP_H */
diff --git a/trunk/src/emu/cpu/esrip/esripdsm.c b/trunk/src/emu/cpu/esrip/esripdsm.c
new file mode 100644
index 00000000000..84f8882ad72
--- /dev/null
+++ b/trunk/src/emu/cpu/esrip/esripdsm.c
@@ -0,0 +1,93 @@
+/***************************************************************************
+
+ esripdsm.c
+
+ Implementation of the Entertainment Sciences
+ AM29116-based Real Time Image Processor
+
+***************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+
+
+/***************************************************************************
+ DISASSEMBLY HOOK (TODO: FINISH)
+***************************************************************************/
+
+CPU_DISASSEMBLE( esrip )
+{
+#if 0
+ static const char* const jmp_types[] =
+ {
+ "JCT",
+ "JT1",
+ "JT2",
+ "JT3",
+ "JT4",
+ "JLBRM",
+ "J#HBLANK",
+ "JMP",
+ };
+
+ static const char* const njmp_types[] =
+ {
+ "JNCT",
+ "JNT1",
+ "JNT2",
+ "JNT3",
+ "JNT4",
+ "JNLBRM",
+ "J#HBLANK",
+ " ",
+ };
+#endif
+
+ UINT64 inst = BIG_ENDIANIZE_INT64(*(UINT64 *)oprom);
+
+ UINT32 inst_hi = inst >> 32;
+ UINT32 inst_lo = inst & 0xffffffff;
+
+ UINT16 ins = (inst_hi >> 16) & 0xffff;
+ UINT8 ctrl = (inst_hi >> 8) & 0xff;
+ UINT8 jmp_dest = (inst_lo >> 8) & 0xff;
+
+ UINT8 jmp_ctrl = (ctrl >> 3) & 0x1f;
+
+ UINT8 ctrl1 = (inst_lo >> 16) & 0xff;
+ UINT8 ctrl2 = (inst_lo >> 24) & 0xff;
+ UINT8 ctrl3 = (inst_hi) & 0xff;
+
+ sprintf(buffer, "%.4x %c%c%c%c %.2x %s%s%s%s%s%s%s%s %c%s%s%s %c%c%c%c%c%c%c%c",
+ ins,
+ ctrl & 1 ? 'D' : ' ',
+ ctrl & 2 ? ' ' : 'Y',
+ ctrl & 4 ? 'S' : ' ',
+ (~jmp_ctrl & 0x18) ? 'J' : ' ',
+ jmp_dest,
+ ctrl1 & 0x01 ? " " : "I ",
+ ctrl1 & 0x02 ? " " : "FL",
+ ctrl1 & 0x04 ? "FE" : " ",
+ ctrl1 & 0x08 ? " " : "FR",
+ ctrl1 & 0x10 ? " " : "IL",
+ ctrl1 & 0x20 ? "IE" : " ",
+ ctrl1 & 0x40 ? " " : "IR",
+ ctrl1 & 0x80 ? " " : "IW",
+
+ ctrl2 & 0x80 ? ' ' : 'O',
+ ctrl2 & 0x40 ? " " : "IXLLD",
+ ctrl2 & 0x20 ? " " : "IADLD",
+ ctrl2 & 0x10 ? " " : "SCALD",
+
+ ctrl3 & 0x01 ? ' ' : '0',
+ ctrl3 & 0x02 ? ' ' : '1',
+ ctrl3 & 0x04 ? ' ' : '2',
+ ctrl3 & 0x08 ? ' ' : '3',
+ ctrl3 & 0x10 ? ' ' : '4',
+ ctrl3 & 0x20 ? ' ' : '5',
+ ctrl3 & 0x40 ? ' ' : '6',
+ ctrl3 & 0x80 ? ' ' : '7'
+ );
+
+ return 1 | DASMFLAG_SUPPORTED;
+}
diff --git a/trunk/src/emu/cpu/f8/f8.c b/trunk/src/emu/cpu/f8/f8.c
new file mode 100644
index 00000000000..91c43da9354
--- /dev/null
+++ b/trunk/src/emu/cpu/f8/f8.c
@@ -0,0 +1,2235 @@
+/*****************************************************************************
+ *
+ * f8.c
+ * Portable F8 emulator (Fairchild 3850)
+ *
+ * Copyright Juergen Buchmueller, all rights reserved.
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * pullmoll@t-online.de
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ * This work is based on Frank Palazzolo's F8 emulation in a standalone
+ * Fairchild Channel F emulator and the 'Fairchild F3850 CPU' data sheets.
+ *
+ *****************************************************************************/
+
+/* PeT 25.June 2001
+ added interrupt functionality
+ */
+
+#include "emu.h"
+#include "debugger.h"
+#include "f8.h"
+
+#define S 0x01
+#define C 0x02
+#define Z 0x04
+#define O 0x08
+#define I 0x10
+
+#define cS 4
+#define cL 6
+
+typedef struct _f8_Regs f8_Regs;
+struct _f8_Regs
+{
+ UINT16 pc0; /* program counter 0 */
+ UINT16 pc1; /* program counter 1 */
+ UINT16 dc0; /* data counter 0 */
+ UINT16 dc1; /* data counter 1 */
+ UINT8 a; /* accumulator */
+ UINT8 w; /* processor status */
+ UINT8 is; /* scratchpad pointer */
+ UINT8 dbus; /* data bus value */
+ UINT16 io; /* last I/O address */
+ UINT16 irq_vector;
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ address_space *iospace;
+ int icount;
+ UINT8 r[64]; /* scratchpad RAM */
+ int irq_request;
+};
+
+INLINE f8_Regs *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == F8);
+ return (f8_Regs *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+/* timer shifter polynome values (will be used for timer interrupts) */
+static UINT8 timer_shifter[256];
+
+/* clear all flags */
+#define CLR_OZCS \
+ cpustate->w &= ~(O|Z|C|S)
+
+/* set sign and zero flags (note: the S flag is complementary) */
+#define SET_SZ(n) \
+ if (n == 0) \
+ cpustate->w |= Z | S; \
+ else \
+ if (n < 128) \
+ cpustate->w |= S
+
+/* set overflow and carry flags */
+#define SET_OC(n,m) \
+ if (n + m > 255) \
+ cpustate->w |= C; \
+ if ((n&127)+(m&127) > 127) \
+ { \
+ if (!(cpustate->w & C)) \
+ cpustate->w |= O; \
+ } \
+ else \
+ { \
+ if (cpustate->w & C) \
+ cpustate->w |= O; \
+ }
+
+/******************************************************************************
+ * ROMC (ROM cycles)
+ * This is what the Fairchild F8 CPUs use instead of an address bus
+ * There are 5 control lines and each combination of those lines has
+ * a special meaning. The devices attached to those control lines all
+ * have their own program counters (PC0 and PC1) and at least one
+ * data counter (DC0).
+ * Currently the emulation does not handle distinct PCs and DCs, but
+ * only one instance inside the CPU context.
+ ******************************************************************************/
+static void ROMC_00(f8_Regs *cpustate, int insttim) /* SKR - added parameter to tell if */
+ /* it is long or short based on inst */
+{
+ /*
+ * Instruction Fetch. The device whose address space includes the
+ * contents of the PC0 register must place on the data bus the op
+ * code addressed by PC0; then all devices increment the contents
+ * of PC0.
+ */
+
+ cpustate->dbus = cpustate->direct->read_decrypted_byte(cpustate->pc0);
+ cpustate->pc0 += 1;
+ cpustate->icount -= insttim; /* SKR - ROMC00 is usually short, not short+long, */
+ /* but DS is long */
+}
+
+static void ROMC_01(f8_Regs *cpustate)
+{
+ /*
+ * The device whose address space includes the contents of the PC0
+ * register must place on the data bus the contents of the memory
+ * location addressed by PC0; then all devices add the 8-bit value
+ * on the data bus as signed binary number to PC0.
+ */
+ cpustate->dbus = cpustate->direct->read_raw_byte(cpustate->pc0);
+ cpustate->pc0 += (INT8)cpustate->dbus;
+ cpustate->icount -= cL;
+}
+
+static void ROMC_02(f8_Regs *cpustate)
+{
+ /*
+ * The device whose DC0 addresses a memory word within the address
+ * space of that device must place on the data bus the contents of
+ * the memory location addressed by DC0; then all devices increment
+ * DC0.
+ */
+ cpustate->dbus = cpustate->program->read_byte(cpustate->dc0);
+ cpustate->dc0 += 1;
+ cpustate->icount -= cL;
+}
+
+static void ROMC_03(f8_Regs *cpustate, int insttim) /* SKR - added parameter to tell if */
+{ /* it is long or short based on inst */
+ /*
+ * Similiar to 0x00, except that it is used for immediate operands
+ * fetches (using PC0) instead of instruction fetches.
+ */
+ cpustate->dbus = cpustate->io = cpustate->direct->read_raw_byte(cpustate->pc0);
+ cpustate->pc0 += 1;
+ cpustate->icount -= insttim;
+}
+
+static void ROMC_04(f8_Regs *cpustate)
+{
+ /*
+ * Copy the contents of PC1 into PC0
+ */
+ cpustate->pc0 = cpustate->pc1;
+ cpustate->icount -= cS;
+}
+
+static void ROMC_05(f8_Regs *cpustate)
+{
+ /*
+ * Store the data bus contents into the memory location pointed
+ * to by DC0; increment DC0.
+ */
+ cpustate->program->write_byte(cpustate->dc0, cpustate->dbus);
+ cpustate->dc0 += 1;
+ cpustate->icount -= cL;
+}
+
+static void ROMC_06(f8_Regs *cpustate)
+{
+ /*
+ * Place the high order byte of DC0 on the data bus.
+ */
+ cpustate->dbus = cpustate->dc0 >> 8;
+ cpustate->icount -= cL;
+}
+
+static void ROMC_07(f8_Regs *cpustate)
+{
+ /*
+ * Place the high order byte of PC1 on the data bus.
+ */
+ cpustate->dbus = cpustate->pc1 >> 8;
+ cpustate->icount -= cL;
+}
+
+static void ROMC_08(f8_Regs *cpustate)
+{
+ /*
+ * All devices copy the contents of PC0 into PC1. The CPU outputs
+ * zero on the data bus in this ROMC state. Load the data bus into
+ * both halves of PC0, thus clearing the register.
+ */
+ cpustate->pc1 = cpustate->pc0;
+ cpustate->dbus = 0;
+ cpustate->pc0 = 0;
+ cpustate->icount -= cL;
+}
+
+static void ROMC_09(f8_Regs *cpustate)
+{
+ /*
+ * The device whose address space includes the contents of the DC0
+ * register must place the low order byte of DC0 onto the data bus.
+ */
+ cpustate->dbus = cpustate->dc0 & 0xff;
+ cpustate->icount -= cL;
+}
+
+static void ROMC_0A(f8_Regs *cpustate)
+{
+ /*
+ * All devices add the 8-bit value on the data bus, treated as
+ * signed binary number, to the data counter.
+ */
+ cpustate->dc0 += (INT8)cpustate->dbus;
+ cpustate->icount -= cL;
+}
+
+static void ROMC_0B(f8_Regs *cpustate)
+{
+ /*
+ * The device whose address space includes the value in PC1
+ * must place the low order byte of PC1 onto the data bus.
+ */
+ cpustate->dbus = cpustate->pc1 & 0xff;
+ cpustate->icount -= cL;
+}
+
+static void ROMC_0C(f8_Regs *cpustate)
+{
+ /*
+ * The device whose address space includes the contents of the PC0
+ * register must place the contents of the memory word addressed
+ * by PC0 into the data bus; then all devices move the value that
+ * has just been placed on the data bus into the low order byte of PC0.
+ */
+ cpustate->dbus = cpustate->direct->read_raw_byte(cpustate->pc0);
+ cpustate->pc0 = (cpustate->pc0 & 0xff00) | cpustate->dbus;
+ cpustate->icount -= cL;
+}
+
+static void ROMC_0D(f8_Regs *cpustate)
+{
+ /*
+ * All devices store in PC1 the current contents of PC0, incremented
+ * by 1; PC0 is unaltered.
+ */
+ cpustate->pc1 = cpustate->pc0 + 1;
+ cpustate->icount -= cS;
+}
+
+static void ROMC_0E(f8_Regs *cpustate)
+{
+ /*
+ * The device whose address space includes the contents of the PC0
+ * register must place the word addressed by PC0 into the data bus.
+ * The value on the data bus is then moved to the low order byte
+ * of DC0 by all devices.
+ */
+ cpustate->dbus = cpustate->direct->read_raw_byte(cpustate->pc0);
+ cpustate->dc0 = (cpustate->dc0 & 0xff00) | cpustate->dbus;
+ cpustate->icount -= cL;
+}
+
+static void ROMC_0F(f8_Regs *cpustate)
+{
+ /*
+ * The interrupting device with highest priority must place the
+ * low order byte of the interrupt vector on the data bus.
+ * All devices must copy the contents of PC0 into PC1. All devices
+ * must move the contents of the data bus into the low order
+ * byte of PC0.
+ */
+ cpustate->irq_vector = (*cpustate->irq_callback)(cpustate->device, F8_INPUT_LINE_INT_REQ);
+ cpustate->dbus = cpustate->irq_vector & 0x00ff;
+ cpustate->pc1 = cpustate->pc0;
+ cpustate->pc0 = (cpustate->pc0 & 0xff00) | cpustate->dbus;
+ cpustate->icount -= cL;
+}
+
+#ifdef UNUSED_FUNCTION
+static void ROMC_10(f8_Regs *cpustate)
+{
+ /*
+ * Inhibit any modification to the interrupt priority logic.
+ */
+ cpustate->w |= 0x20; /* ???? */
+ cpustate->icount -= cL;
+}
+#endif
+
+static void ROMC_11(f8_Regs *cpustate)
+{
+ /*
+ * The device whose address space includes the contents of PC0
+ * must place the contents of the addressed memory word on the
+ * data bus. All devices must then move the contents of the
+ * data bus to the upper byte of DC0.
+ */
+ cpustate->dbus = cpustate->direct->read_raw_byte(cpustate->pc0);
+ cpustate->dc0 = (cpustate->dc0 & 0x00ff) | (cpustate->dbus << 8);
+ cpustate->icount -= cL;
+}
+
+static void ROMC_12(f8_Regs *cpustate)
+{
+ /*
+ * All devices copy the contents of PC0 into PC1. All devices then
+ * move the contents of the data bus into the low order byte of PC0.
+ */
+ cpustate->pc1 = cpustate->pc0;
+ cpustate->pc0 = (cpustate->pc0 & 0xff00) | cpustate->dbus;
+ cpustate->icount -= cL;
+}
+
+static void ROMC_13(f8_Regs *cpustate)
+{
+ /*
+ * The interrupting device with highest priority must move the high
+ * order half of the interrupt vector onto the data bus. All devices
+ * must then move the contents of the data bus into the high order
+ * byte of PC0. The interrupting device resets its interrupt circuitry
+ * (so that it is no longer requesting CPU servicing and can respond
+ * to another interrupt).
+ */
+ cpustate->dbus = cpustate->irq_vector >> 8;
+ cpustate->pc0 = (cpustate->pc0 & 0x00ff) | (cpustate->dbus << 8);
+ cpustate->w&=~I;
+ cpustate->icount -= cL;
+}
+
+static void ROMC_14(f8_Regs *cpustate)
+{
+ /*
+ * All devices move the contents of the data bus into the high
+ * order byte of PC0.
+ */
+ cpustate->pc0 = (cpustate->pc0 & 0x00ff) | (cpustate->dbus << 8);
+ cpustate->icount -= cL;
+}
+
+static void ROMC_15(f8_Regs *cpustate)
+{
+ /*
+ * All devices move the contents of the data bus into the high
+ * order byte of PC1.
+ */
+ cpustate->pc1 = (cpustate->pc1 & 0x00ff) | (cpustate->dbus << 8);
+ cpustate->icount -= cL;
+}
+
+static void ROMC_16(f8_Regs *cpustate)
+{
+ /*
+ * All devices move the contents of the data bus into the high
+ * order byte of DC0.
+ */
+ cpustate->dc0 = (cpustate->dc0 & 0x00ff) | (cpustate->dbus << 8);
+ cpustate->icount -= cL;
+}
+
+static void ROMC_17(f8_Regs *cpustate)
+{
+ /*
+ * All devices move the contents of the data bus into the low
+ * order byte of PC0.
+ */
+ cpustate->pc0 = (cpustate->pc0 & 0xff00) | cpustate->dbus;
+ cpustate->icount -= cL;
+}
+
+static void ROMC_18(f8_Regs *cpustate)
+{
+ /*
+ * All devices move the contents of the data bus into the low
+ * order byte of PC1.
+ */
+ cpustate->pc1 = (cpustate->pc1 & 0xff00) | cpustate->dbus;
+ cpustate->icount -= cL;
+}
+
+static void ROMC_19(f8_Regs *cpustate)
+{
+ /*
+ * All devices move the contents of the data bus into the low
+ * order byte of DC0.
+ */
+ cpustate->dc0 = (cpustate->dc0 & 0xff00) | cpustate->dbus;
+ cpustate->icount -= cL;
+}
+
+static void ROMC_1A(f8_Regs *cpustate)
+{
+ /*
+ * During the prior cycle, an I/O port timer or interrupt control
+ * register was addressed; the device containing the addressed port
+ * must place the contents of the data bus into the address port.
+ */
+ cpustate->iospace->write_byte(cpustate->io, cpustate->dbus);
+ cpustate->icount -= cL;
+}
+
+static void ROMC_1B(f8_Regs *cpustate)
+{
+ /*
+ * During the prior cycle, the data bus specified the address of an
+ * I/O port. The device containing the addressed I/O port must place
+ * the contents of the I/O port on the data bus. (Note that the
+ * contents of timer and interrupt control registers cannot be read
+ * back onto the data bus).
+ */
+ cpustate->dbus = cpustate->iospace->read_byte(cpustate->io);
+ cpustate->icount -= cL;
+}
+
+static void ROMC_1C(f8_Regs *cpustate, int insttim) /* SKR - added parameter to tell if */
+ /* it is long or short based on inst */
+{
+ /*
+ * None.
+ */
+ cpustate->icount -= insttim;
+}
+
+static void ROMC_1D(f8_Regs *cpustate)
+{
+ /*
+ * Devices with DC0 and DC1 registers must switch registers.
+ * Devices without a DC1 register perform no operation.
+ */
+ UINT16 tmp = cpustate->dc0;
+ cpustate->dc0 = cpustate->dc1;
+ cpustate->dc1 = tmp;
+ cpustate->icount -= cS;
+}
+
+#ifdef UNUSED_FUNCTION
+static void ROMC_1E(f8_Regs *cpustate)
+{
+ /*
+ * The devices whose address space includes the contents of PC0
+ * must place the low order byte of PC0 onto the data bus.
+ */
+ cpustate->dbus = cpustate->pc0 & 0xff;
+ cpustate->icount -= cL;
+}
+
+static void ROMC_1F(f8_Regs *cpustate)
+{
+ /*
+ * The devices whose address space includes the contents of PC0
+ * must place the high order byte of PC0 onto the data bus.
+ */
+ cpustate->dbus = (cpustate->pc0 >> 8) & 0xff;
+ cpustate->icount -= cL;
+}
+#endif
+
+/***********************************
+ * illegal opcodes
+ ***********************************/
+static void illegal(f8_Regs *cpustate)
+{
+ logerror("f8 illegal opcode at 0x%04x: %02x\n", cpustate->pc0, cpustate->dbus);
+}
+
+/***************************************************
+ * O Z C S 0000 0000
+ * - - - - LR A,KU
+ ***************************************************/
+static void f8_lr_a_ku(f8_Regs *cpustate)
+{
+ cpustate->a = cpustate->r[12];
+}
+
+/***************************************************
+ * O Z C S 0000 0001
+ * - - - - LR A,KL
+ ***************************************************/
+static void f8_lr_a_kl(f8_Regs *cpustate)
+{
+ cpustate->a = cpustate->r[13];
+}
+
+/***************************************************
+ * O Z C S 0000 0010
+ * - - - - LR A,QU
+ ***************************************************/
+static void f8_lr_a_qu(f8_Regs *cpustate)
+{
+ cpustate->a = cpustate->r[14];
+}
+
+/***************************************************
+ * O Z C S 0000 0011
+ * - - - - LR A,QL
+ ***************************************************/
+static void f8_lr_a_ql(f8_Regs *cpustate)
+{
+ cpustate->a = cpustate->r[15];
+}
+
+/***************************************************
+ * O Z C S 0000 0100
+ * - - - - LR KU,A
+ ***************************************************/
+static void f8_lr_ku_a(f8_Regs *cpustate)
+{
+ cpustate->r[12] = cpustate->a;
+}
+
+/***************************************************
+ * O Z C S 0000 0101
+ * - - - - LR KL,A
+ ***************************************************/
+static void f8_lr_kl_a(f8_Regs *cpustate)
+{
+ cpustate->r[13] = cpustate->a;
+}
+
+/***************************************************
+ * O Z C S 0000 0110
+ * - - - - LR QU,A
+ ***************************************************/
+static void f8_lr_qu_a(f8_Regs *cpustate)
+{
+ cpustate->r[14] = cpustate->a;
+}
+
+/***************************************************
+ * O Z C S 0000 0111
+ * - - - - LR QL,A
+ ***************************************************/
+static void f8_lr_ql_a(f8_Regs *cpustate)
+{
+ cpustate->r[15] = cpustate->a;
+}
+
+/***************************************************
+ * O Z C S 0000 1000
+ * - - - - LR K,P
+ ***************************************************/
+static void f8_lr_k_p(f8_Regs *cpustate)
+{
+ ROMC_07(cpustate);
+ cpustate->r[12] = cpustate->dbus;
+ ROMC_0B(cpustate);
+ cpustate->r[13] = cpustate->dbus;
+}
+
+/***************************************************
+ * O Z C S 0000 1001
+ * - - - - LR P,K
+ ***************************************************/
+static void f8_lr_p_k(f8_Regs *cpustate)
+{
+ cpustate->dbus = cpustate->r[12];
+ ROMC_15(cpustate);
+ cpustate->dbus = cpustate->r[13];
+ ROMC_18(cpustate);
+}
+
+/***************************************************
+ * O Z C S 0000 1010
+ * - - - - LR A,IS
+ ***************************************************/
+static void f8_lr_a_is(f8_Regs *cpustate)
+{
+ cpustate->a = cpustate->is;
+}
+
+/***************************************************
+ * O Z C S 0000 1011
+ * - - - - LR IS,A
+ ***************************************************/
+static void f8_lr_is_a(f8_Regs *cpustate)
+{
+ cpustate->is = cpustate->a & 0x3f;
+}
+
+/***************************************************
+ * O Z C S 0000 1100
+ * - - - - PK
+ ***************************************************/
+static void f8_pk(f8_Regs *cpustate)
+{
+ cpustate->dbus = cpustate->r[13];
+ ROMC_12(cpustate);
+ cpustate->dbus = cpustate->r[12];
+ ROMC_14(cpustate);
+}
+
+/***************************************************
+ * O Z C S 0000 1101
+ * - - - - LR P0,Q
+ ***************************************************/
+static void f8_lr_p0_q(f8_Regs *cpustate)
+{
+ cpustate->dbus = cpustate->r[15];
+ ROMC_17(cpustate);
+ cpustate->dbus = cpustate->r[14];
+ ROMC_14(cpustate);
+}
+
+/***************************************************
+ * O Z C S 0000 1110
+ * - - - - LR Q,DC
+ ***************************************************/
+static void f8_lr_q_dc(f8_Regs *cpustate)
+{
+ ROMC_06(cpustate);
+ cpustate->r[14] = cpustate->dbus;
+ ROMC_09(cpustate);
+ cpustate->r[15] = cpustate->dbus;
+}
+
+/***************************************************
+ * O Z C S 0000 1111
+ * - - - - LR DC,Q
+ ***************************************************/
+static void f8_lr_dc_q(f8_Regs *cpustate)
+{
+ cpustate->dbus = cpustate->r[14];
+ ROMC_16(cpustate);
+ cpustate->dbus = cpustate->r[15];
+ ROMC_19(cpustate);
+}
+
+/***************************************************
+ * O Z C S 0001 0000
+ * - - - - LR DC,H
+ ***************************************************/
+static void f8_lr_dc_h(f8_Regs *cpustate)
+{
+ cpustate->dbus = cpustate->r[10];
+ ROMC_16(cpustate);
+ cpustate->dbus = cpustate->r[11];
+ ROMC_19(cpustate);
+}
+
+/***************************************************
+ * O Z C S 0001 0001
+ * - - - - LR H,DC
+ ***************************************************/
+static void f8_lr_h_dc(f8_Regs *cpustate)
+{
+ ROMC_06(cpustate);
+ cpustate->r[10] = cpustate->dbus;
+ ROMC_09(cpustate);
+ cpustate->r[11] = cpustate->dbus;
+}
+
+/***************************************************
+ * O Z C S 0001 0010
+ * 0 x 0 1 SR 1
+ ***************************************************/
+static void f8_sr_1(f8_Regs *cpustate)
+{
+ cpustate->a >>= 1;
+ CLR_OZCS;
+ SET_SZ(cpustate->a);
+}
+
+/***************************************************
+ * O Z C S 0001 0011
+ * 0 x 0 x SL 1
+ ***************************************************/
+static void f8_sl_1(f8_Regs *cpustate)
+{
+ cpustate->a <<= 1;
+ CLR_OZCS;
+ SET_SZ(cpustate->a);
+}
+
+/***************************************************
+ * O Z C S 0001 0100
+ * 0 x 0 1 SR 4
+ ***************************************************/
+static void f8_sr_4(f8_Regs *cpustate)
+{
+ cpustate->a >>= 4;
+ CLR_OZCS;
+ SET_SZ(cpustate->a);
+}
+
+/***************************************************
+ * O Z C S 0001 0101
+ * 0 x 0 x SL 4
+ ***************************************************/
+static void f8_sl_4(f8_Regs *cpustate)
+{
+ cpustate->a <<= 4;
+ CLR_OZCS;
+ SET_SZ(cpustate->a);
+}
+
+/***************************************************
+ * O Z C S 0001 0110
+ * - - - - LM
+ ***************************************************/
+static void f8_lm(f8_Regs *cpustate)
+{
+ ROMC_02(cpustate);
+ cpustate->a = cpustate->dbus;
+}
+
+/***************************************************
+ * O Z C S 0001 0111
+ * - - - - ST
+ ***************************************************/
+static void f8_st(f8_Regs *cpustate)
+{
+ cpustate->dbus = cpustate->a;
+ ROMC_05(cpustate);
+}
+
+/***************************************************
+ * O Z C S 0001 1000
+ * 0 x 0 x COM
+ ***************************************************/
+static void f8_com(f8_Regs *cpustate)
+{
+ cpustate->a = ~cpustate->a;
+ CLR_OZCS;
+ SET_SZ(cpustate->a);
+}
+
+/***************************************************
+ * O Z C S 0001 1001
+ * x x x x LNK
+ ***************************************************/
+static void f8_lnk(f8_Regs *cpustate)
+{
+ if (cpustate->w & C)
+ {
+ CLR_OZCS;
+ SET_OC(cpustate->a,1);
+ cpustate->a += 1;
+ }
+ else
+ {
+ CLR_OZCS;
+ }
+ SET_SZ(cpustate->a);
+}
+
+/***************************************************
+ * O Z C S 0001 1010
+ * DI
+ ***************************************************/
+static void f8_di(f8_Regs *cpustate)
+{
+ ROMC_1C(cpustate, cS);
+ cpustate->w &= ~I;
+}
+
+/***************************************************
+ * O Z C S 0001 1011
+ * EI
+ ***************************************************/
+static void f8_ei(f8_Regs *cpustate)
+{
+ ROMC_1C(cpustate, cS);
+ cpustate->w |= I;
+}
+
+/***************************************************
+ * O Z C S 0001 1100
+ * POP
+ ***************************************************/
+static void f8_pop(f8_Regs *cpustate)
+{
+ ROMC_04(cpustate);
+}
+
+/***************************************************
+ * O Z C S 0001 1101
+ * x x x x LR W,J
+ ***************************************************/
+static void f8_lr_w_j(f8_Regs *cpustate)
+{
+ ROMC_1C(cpustate, cS);
+ cpustate->w = cpustate->r[9];
+}
+
+/***************************************************
+ * O Z C S 0001 1110
+ * - - - - LR J,W
+ ***************************************************/
+static void f8_lr_j_w(f8_Regs *cpustate)
+{
+ cpustate->r[9] = cpustate->w;
+}
+
+/***************************************************
+ * O Z C S 0001 1111
+ * x x x x INC
+ ***************************************************/
+static void f8_inc(f8_Regs *cpustate)
+{
+ CLR_OZCS;
+ SET_OC(cpustate->a,1);
+ cpustate->a += 1;
+ SET_SZ(cpustate->a);
+}
+
+/***************************************************
+ * O Z C S 0010 0000 aaaa aaaa
+ * - - - - LI aa
+ ***************************************************/
+static void f8_li(f8_Regs *cpustate)
+{
+ ROMC_03(cpustate, cL);
+ cpustate->a = cpustate->dbus;
+}
+
+/***************************************************
+ * O Z C S 0010 0001 aaaa aaaa
+ * 0 x 0 x NI aa
+ ***************************************************/
+static void f8_ni(f8_Regs *cpustate)
+{
+ ROMC_03(cpustate, cL);
+ CLR_OZCS;
+ cpustate->a &= cpustate->dbus;
+ SET_SZ(cpustate->a);
+}
+
+/***************************************************
+ * O Z C S 0010 0010 aaaa aaaa
+ * 0 x 0 x OI aa
+ ***************************************************/
+static void f8_oi(f8_Regs *cpustate)
+{
+ ROMC_03(cpustate, cL);
+ CLR_OZCS;
+ cpustate->a |= cpustate->dbus;
+ SET_SZ(cpustate->a);
+}
+
+/***************************************************
+ * O Z C S 0010 0011 aaaa aaaa
+ * 0 x 0 x XI aa
+ ***************************************************/
+static void f8_xi(f8_Regs *cpustate)
+{
+ ROMC_03(cpustate, cL);
+ CLR_OZCS;
+ cpustate->a ^= cpustate->dbus;
+ SET_SZ(cpustate->a);
+}
+
+/***************************************************
+ * O Z C S 0010 0100 aaaa aaaa
+ * x x x x AI aa
+ ***************************************************/
+static void f8_ai(f8_Regs *cpustate)
+{
+ ROMC_03(cpustate, cL);
+ CLR_OZCS;
+ SET_OC(cpustate->a,cpustate->dbus);
+ cpustate->a += cpustate->dbus;
+ SET_SZ(cpustate->a);
+}
+
+/***************************************************
+ * O Z C S 0010 0101 aaaa aaaa
+ * x x x x CI aa
+ ***************************************************/
+static void f8_ci(f8_Regs *cpustate)
+{
+ UINT16 tmp = ((UINT8)~cpustate->a) + 1;
+ ROMC_03(cpustate, cL);
+ CLR_OZCS;
+ SET_OC(tmp,cpustate->dbus);
+ tmp += cpustate->dbus;
+ SET_SZ((UINT8)tmp);
+}
+
+/***************************************************
+ * O Z C S 0010 0110 aaaa aaaa
+ * 0 x 0 x IN aa
+ ***************************************************/
+static void f8_in(f8_Regs *cpustate)
+{
+ ROMC_03(cpustate, cL);
+ CLR_OZCS;
+ ROMC_1B(cpustate);
+ cpustate->a = cpustate->dbus;
+ SET_SZ(cpustate->a);
+}
+
+/***************************************************
+ * O Z C S 0010 0111 aaaa aaaa
+ * - - - - OUT aa
+ ***************************************************/
+static void f8_out(f8_Regs *cpustate)
+{
+ ROMC_03(cpustate, cL);
+ cpustate->dbus = cpustate->a;
+ ROMC_1A(cpustate);
+}
+
+/***************************************************
+ * O Z C S 0010 1000 iiii iiii jjjj jjjj
+ * - - - - PI iijj
+ ***************************************************/
+static void f8_pi(f8_Regs *cpustate)
+{
+ ROMC_03(cpustate, cL);
+ cpustate->a = cpustate->dbus;
+ ROMC_0D(cpustate);
+ ROMC_0C(cpustate);
+ cpustate->dbus = cpustate->a;
+ ROMC_14(cpustate);
+}
+
+/***************************************************
+ * O Z C S 0010 1001 iiii iiii jjjj jjjj
+ * - - - - JMP iijj
+ ***************************************************/
+static void f8_jmp(f8_Regs *cpustate)
+{
+ ROMC_03(cpustate, cL);
+ cpustate->a = cpustate->dbus;
+ ROMC_0C(cpustate);
+ cpustate->dbus = cpustate->a;
+ ROMC_14(cpustate);
+}
+
+/***************************************************
+ * O Z C S 0010 1010 iiii iiii jjjj jjjj
+ * - - - - DCI iijj
+ ***************************************************/
+static void f8_dci(f8_Regs *cpustate)
+{
+ ROMC_11(cpustate);
+ ROMC_03(cpustate, cS);
+ ROMC_0E(cpustate);
+ ROMC_03(cpustate, cS);
+}
+
+/***************************************************
+ * O Z C S 0010 1011
+ * - - - - NOP
+ ***************************************************/
+static void f8_nop(f8_Regs *cpustate)
+{
+}
+
+/***************************************************
+ * O Z C S 0010 1100
+ * - - - - XDC
+ ***************************************************/
+static void f8_xdc(f8_Regs *cpustate)
+{
+ ROMC_1D(cpustate);
+}
+
+/***************************************************
+ * O Z C S 0011 rrrr
+ * x x x x DS r
+ ***************************************************/
+static void f8_ds_r(f8_Regs *cpustate, int r)
+{
+ CLR_OZCS;
+ SET_OC(cpustate->r[r], 0xff);
+ cpustate->r[r] = cpustate->r[r] + 0xff;
+ SET_SZ(cpustate->r[r]);
+}
+
+/***************************************************
+ * O Z C S 0011 1100
+ * x x x x DS ISAR
+ ***************************************************/
+static void f8_ds_isar(f8_Regs *cpustate)
+{
+ CLR_OZCS;
+ SET_OC(cpustate->r[cpustate->is], 0xff);
+ cpustate->r[cpustate->is] = cpustate->r[cpustate->is] + 0xff;
+ SET_SZ(cpustate->r[cpustate->is]);
+}
+
+/***************************************************
+ * O Z C S 0011 1101
+ * x x x x DS ISAR++
+ ***************************************************/
+static void f8_ds_isar_i(f8_Regs *cpustate)
+{
+ CLR_OZCS;
+ SET_OC(cpustate->r[cpustate->is], 0xff);
+ cpustate->r[cpustate->is] = cpustate->r[cpustate->is] + 0xff;
+ SET_SZ(cpustate->r[cpustate->is]);
+ cpustate->is = (cpustate->is & 0x38) | ((cpustate->is + 1) & 0x07);
+}
+
+/***************************************************
+ * O Z C S 0011 1110
+ * x x x x DS ISAR--
+ ***************************************************/
+static void f8_ds_isar_d(f8_Regs *cpustate)
+{
+ CLR_OZCS;
+ SET_OC(cpustate->r[cpustate->is], 0xff);
+ cpustate->r[cpustate->is] = cpustate->r[cpustate->is] + 0xff;
+ SET_SZ(cpustate->r[cpustate->is]);
+ cpustate->is = (cpustate->is & 0x38) | ((cpustate->is - 1) & 0x07);
+}
+
+/***************************************************
+ * O Z C S 0100 rrrr
+ * - - - - LR A,r
+ ***************************************************/
+static void f8_lr_a_r(f8_Regs *cpustate, int r)
+{
+ cpustate->a = cpustate->r[r];
+}
+
+/***************************************************
+ * O Z C S 0100 1100
+ * - - - - LR A,ISAR
+ ***************************************************/
+static void f8_lr_a_isar(f8_Regs *cpustate)
+{
+ cpustate->a = cpustate->r[cpustate->is];
+}
+
+/***************************************************
+ * O Z C S 0100 1101
+ * - - - - LR A,ISAR++
+ ***************************************************/
+static void f8_lr_a_isar_i(f8_Regs *cpustate)
+{
+ cpustate->a = cpustate->r[cpustate->is];
+ cpustate->is = (cpustate->is & 0x38) | ((cpustate->is + 1) & 0x07);
+}
+
+/***************************************************
+ * O Z C S 0100 1110
+ * - - - - LR A,ISAR--
+ ***************************************************/
+static void f8_lr_a_isar_d(f8_Regs *cpustate)
+{
+ cpustate->a = cpustate->r[cpustate->is];
+ cpustate->is = (cpustate->is & 0x38) | ((cpustate->is - 1) & 0x07);
+}
+
+/***************************************************
+ * O Z C S 0101 rrrr
+ * - - - - LR r,A
+ ***************************************************/
+static void f8_lr_r_a(f8_Regs *cpustate, int r)
+{
+ cpustate->r[r] = cpustate->a;
+}
+
+/***************************************************
+ * O Z C S 0101 1100
+ * - - - - LR ISAR,A
+ ***************************************************/
+static void f8_lr_isar_a(f8_Regs *cpustate)
+{
+ cpustate->r[cpustate->is] = cpustate->a;
+}
+
+/***************************************************
+ * O Z C S 0101 1101
+ * - - - - LR ISAR++,A
+ ***************************************************/
+static void f8_lr_isar_i_a(f8_Regs *cpustate)
+{
+ cpustate->r[cpustate->is] = cpustate->a;
+ cpustate->is = (cpustate->is & 0x38) | ((cpustate->is + 1) & 0x07);
+}
+
+/***************************************************
+ * O Z C S 0101 1110
+ * - - - - LR ISAR--,A
+ ***************************************************/
+static void f8_lr_isar_d_a(f8_Regs *cpustate)
+{
+ cpustate->r[cpustate->is] = cpustate->a;
+ cpustate->is = (cpustate->is & 0x38) | ((cpustate->is - 1) & 0x07);
+}
+
+/***************************************************
+ * O Z C S 0110 0eee
+ * - - - - LISU e
+ ***************************************************/
+static void f8_lisu(f8_Regs *cpustate, int e)
+{
+ cpustate->is = (cpustate->is & 0x07) | e;
+}
+
+/***************************************************
+ * O Z C S 0110 1eee
+ * - - - - LISL e
+ ***************************************************/
+static void f8_lisl(f8_Regs *cpustate, int e)
+{
+ cpustate->is = (cpustate->is & 0x38) | e;
+}
+
+/***************************************************
+ * O Z C S 0111 iiii
+ * - - - - LIS i
+ ***************************************************/
+static void f8_lis(f8_Regs *cpustate, int i)
+{
+ cpustate->a = i;
+}
+
+/***************************************************
+ * O Z C S 1000 0eee aaaa aaaa
+ * BT e,aa
+ ***************************************************/
+static void f8_bt(f8_Regs *cpustate, int e)
+{
+ ROMC_1C(cpustate, cS);
+ if (cpustate->w & e)
+ ROMC_01(cpustate); /* take the relative branch */
+ else
+ ROMC_03(cpustate, cS); /* just read the argument on the data bus */
+}
+
+/***************************************************
+ * O Z C S 1000 1000
+ * x x x x AM
+ ***************************************************/
+static void f8_am(f8_Regs *cpustate)
+{
+ ROMC_02(cpustate);
+ CLR_OZCS;
+ SET_OC(cpustate->a, cpustate->dbus);
+ cpustate->a += cpustate->dbus;
+ SET_SZ(cpustate->a);
+}
+
+/***************************************************
+ * O Z C S 1000 1001
+ * x x x x AMD
+ ***************************************************/
+static void f8_amd(f8_Regs *cpustate)
+{
+ UINT8 tmp = cpustate->a - 0x66, adj = 0x00;
+ int sum;
+ ROMC_02(cpustate);
+ sum = (tmp & 0x0f) + (cpustate->dbus & 0x0f);
+ if (sum > 0x09)
+ adj += 0x06;
+ sum = tmp + cpustate->dbus + adj;
+ if (sum > 0x99)
+ adj += 0x60;
+ tmp += adj;
+ CLR_OZCS;
+ SET_OC(tmp,cpustate->dbus);
+ cpustate->a = tmp + cpustate->dbus;
+ SET_SZ(cpustate->a);
+}
+
+/***************************************************
+ * O Z C S 1000 1010
+ * 0 x 0 x NM
+ ***************************************************/
+static void f8_nm(f8_Regs *cpustate)
+{
+ ROMC_02(cpustate);
+ CLR_OZCS;
+ cpustate->a &= cpustate->dbus;
+ SET_SZ(cpustate->a);
+}
+
+/***************************************************
+ * O Z C S 1000 1011
+ * 0 x 0 x OM
+ ***************************************************/
+static void f8_om(f8_Regs *cpustate)
+{
+ ROMC_02(cpustate);
+ CLR_OZCS;
+ cpustate->a |= cpustate->dbus;
+ SET_SZ(cpustate->a);
+}
+
+/***************************************************
+ * O Z C S 1000 1100
+ * 0 x 0 x XM
+ ***************************************************/
+static void f8_xm(f8_Regs *cpustate)
+{
+ ROMC_02(cpustate);
+ CLR_OZCS;
+ cpustate->a ^= cpustate->dbus;
+ SET_SZ(cpustate->a);
+}
+
+/***************************************************
+ * O Z C S 1000 1101
+ * x x x x CM
+ ***************************************************/
+static void f8_cm(f8_Regs *cpustate) /* SKR changed to match f8_ci(cpustate) */
+{
+ UINT16 tmp = ((UINT8)~cpustate->a) + 1;
+ ROMC_02(cpustate);
+ CLR_OZCS;
+ SET_OC(tmp,cpustate->dbus);
+ tmp += cpustate->dbus;
+ SET_SZ((UINT8)tmp);
+}
+
+/***************************************************
+ * O Z C S 1000 1110
+ * - - - - ADC
+ ***************************************************/
+static void f8_adc(f8_Regs *cpustate)
+{
+ cpustate->dbus = cpustate->a;
+ ROMC_0A(cpustate); /* add data bus value to DC0 */
+}
+
+/***************************************************
+ * O Z C S 1000 1111
+ * - - - - BR7
+ ***************************************************/
+static void f8_br7(f8_Regs *cpustate)
+{
+ if ((cpustate->is & 7) == 7)
+ ROMC_03(cpustate, cS); /* just read the argument on the data bus */
+ else
+ ROMC_01(cpustate); /* take the relative branch */
+}
+
+/***************************************************
+ * O Z C S 1001 tttt aaaa aaaa
+ * - - - - BF t,aa
+ ***************************************************/
+static void f8_bf(f8_Regs *cpustate, int t)
+{
+ ROMC_1C(cpustate, cS);
+ if (cpustate->w & t)
+ ROMC_03(cpustate, cS); /* just read the argument on the data bus */
+ else
+ ROMC_01(cpustate); /* take the relative branch */
+}
+
+/***************************************************
+ * O Z C S 1010 000n
+ * 0 x 0 x INS n (n = 0-1)
+ ***************************************************/
+static void f8_ins_0(f8_Regs *cpustate, int n)
+{
+ ROMC_1C(cpustate, cS);
+ CLR_OZCS;
+ cpustate->a = cpustate->iospace->read_byte(n);
+ SET_SZ(cpustate->a);
+}
+
+/***************************************************
+ * O Z C S 1010 nnnn
+ * 0 x 0 x INS n (n = 4-F)
+ ***************************************************/
+static void f8_ins_1(f8_Regs *cpustate, int n)
+{
+ ROMC_1C(cpustate, cL);
+ cpustate->io = n;
+ ROMC_1B(cpustate);
+ CLR_OZCS;
+ cpustate->a = cpustate->dbus;
+ SET_SZ(cpustate->a);
+}
+
+/***************************************************
+ * O Z C S 1011 000n
+ * - - - - OUTS n (n = 0-1)
+ ***************************************************/
+static void f8_outs_0(f8_Regs *cpustate, int n)
+{
+ ROMC_1C(cpustate, cS);
+ cpustate->iospace->write_byte(n, cpustate->a);
+}
+
+/***************************************************
+ * O Z C S 1011 nnnn
+ * - - - - OUTS n (n = 4-F)
+ ***************************************************/
+static void f8_outs_1(f8_Regs *cpustate, int n)
+{
+ ROMC_1C(cpustate, cL);
+ cpustate->io = n;
+ cpustate->dbus = cpustate->a;
+ ROMC_1A(cpustate);
+}
+
+/***************************************************
+ * O Z C S 1100 rrrr
+ * x x x x AS r
+ ***************************************************/
+static void f8_as(f8_Regs *cpustate, int r)
+{
+ CLR_OZCS;
+ SET_OC(cpustate->a, cpustate->r[r]);
+ cpustate->a += cpustate->r[r];
+ SET_SZ(cpustate->a);
+}
+
+/***************************************************
+ * O Z C S 1100 1100
+ * x x x x AS ISAR
+ ***************************************************/
+static void f8_as_isar(f8_Regs *cpustate)
+{
+ CLR_OZCS;
+ SET_OC(cpustate->a, cpustate->r[cpustate->is]);
+ cpustate->a += cpustate->r[cpustate->is];
+ SET_SZ(cpustate->a);
+}
+
+/***************************************************
+ * O Z C S 1100 1101
+ * x x x x AS ISAR++
+ ***************************************************/
+static void f8_as_isar_i(f8_Regs *cpustate)
+{
+ CLR_OZCS;
+ SET_OC(cpustate->a, cpustate->r[cpustate->is]);
+ cpustate->a += cpustate->r[cpustate->is];
+ SET_SZ(cpustate->a);
+ cpustate->is = (cpustate->is & 0x38) | ((cpustate->is + 1) & 0x07);
+}
+
+/***************************************************
+ * O Z C S 1100 1110
+ * x x x x AS ISAR--
+ ***************************************************/
+static void f8_as_isar_d(f8_Regs *cpustate)
+{
+ CLR_OZCS;
+ SET_OC(cpustate->a, cpustate->r[cpustate->is]);
+ cpustate->a += cpustate->r[cpustate->is];
+ SET_SZ(cpustate->a);
+ cpustate->is = (cpustate->is & 0x38) | ((cpustate->is - 1) & 0x07);
+}
+
+/***************************************************
+ * O Z C S 1101 rrrr
+ * x x x x ASD r
+ ***************************************************/
+static void f8_asd(f8_Regs *cpustate, int r)
+{
+ UINT8 tmp = cpustate->a - 0x66, adj = 0x00;
+ int sum;
+ ROMC_1C(cpustate, cS);
+ sum = (tmp & 0x0f) + (cpustate->r[r] & 0x0f);
+ if (sum > 0x09)
+ adj += 0x06;
+ sum = tmp + cpustate->r[r] + adj;
+ if (sum > 0x99)
+ adj += 0x60;
+ tmp += adj;
+ CLR_OZCS;
+ SET_OC(tmp, cpustate->r[r]);
+ cpustate->a = tmp + cpustate->r[r];
+ SET_SZ(cpustate->a);
+}
+
+/***************************************************
+ * O Z C S 1101 1100
+ * x x x x ASD ISAR
+ ***************************************************/
+static void f8_asd_isar(f8_Regs *cpustate)
+{
+ UINT8 tmp = cpustate->a - 0x66, adj = 0x00;
+ int sum;
+ ROMC_1C(cpustate, cS);
+ sum = (tmp & 0x0f) + (cpustate->r[cpustate->is] & 0x0f);
+ if (sum > 0x09)
+ adj += 0x06;
+ sum = tmp + cpustate->r[cpustate->is] + adj;
+ if (sum > 0x99)
+ adj += 0x60;
+ tmp += adj;
+ CLR_OZCS;
+ SET_OC(tmp, cpustate->r[cpustate->is]);
+ cpustate->a = tmp + cpustate->r[cpustate->is];
+ SET_SZ(cpustate->a);
+}
+
+/***************************************************
+ * O Z C S 1101 1101
+ * x x x x ASD ISAR++
+ ***************************************************/
+static void f8_asd_isar_i(f8_Regs *cpustate)
+{
+ UINT8 tmp = cpustate->a - 0x66, adj = 0x00;
+ int sum;
+ ROMC_1C(cpustate, cS);
+ sum = (tmp & 0x0f) + (cpustate->r[cpustate->is] & 0x0f);
+ if (sum > 0x09)
+ adj += 0x06;
+ sum = tmp + cpustate->r[cpustate->is] + adj;
+ if (sum > 0x99)
+ adj += 0x60;
+ tmp += adj;
+ CLR_OZCS;
+ SET_OC(tmp, cpustate->r[cpustate->is]);
+ cpustate->a = tmp + cpustate->r[cpustate->is];
+ SET_SZ(cpustate->a);
+ cpustate->is = (cpustate->is & 0x38) | ((cpustate->is + 1) & 0x07);
+}
+
+/***************************************************
+ * O Z C S 1101 1110
+ * x x x x ASD ISAR--
+ ***************************************************/
+static void f8_asd_isar_d(f8_Regs *cpustate)
+{
+ UINT8 tmp = cpustate->a - 0x66, adj = 0x00;
+ int sum;
+ ROMC_1C(cpustate, cS);
+ sum = (tmp & 0x0f) + (cpustate->r[cpustate->is] & 0x0f);
+ if (sum > 0x09)
+ adj += 0x06;
+ sum = tmp + cpustate->r[cpustate->is] + adj;
+ if (sum > 0x99)
+ adj += 0x60;
+ tmp += adj;
+ CLR_OZCS;
+ SET_OC(tmp, cpustate->r[cpustate->is]);
+ cpustate->a = tmp + cpustate->r[cpustate->is];
+ SET_SZ(cpustate->a);
+ cpustate->is = (cpustate->is & 0x38) | ((cpustate->is - 1) & 0x07);
+}
+
+/***************************************************
+ * O Z C S 1110 rrrr
+ * 0 x 0 x XS r
+ ***************************************************/
+static void f8_xs(f8_Regs *cpustate, int r)
+{
+ CLR_OZCS;
+ cpustate->a ^= cpustate->r[r];
+ SET_SZ(cpustate->a);
+}
+
+/***************************************************
+ * O Z C S 1110 1100
+ * 0 x 0 x XS ISAR
+ ***************************************************/
+static void f8_xs_isar(f8_Regs *cpustate)
+{
+ CLR_OZCS;
+ cpustate->a ^= cpustate->r[cpustate->is];
+ SET_SZ(cpustate->a);
+}
+
+/***************************************************
+ * O Z C S 1110 1101
+ * 0 x 0 x XS ISAR++
+ ***************************************************/
+static void f8_xs_isar_i(f8_Regs *cpustate)
+{
+ CLR_OZCS;
+ cpustate->a ^= cpustate->r[cpustate->is];
+ SET_SZ(cpustate->a);
+ cpustate->is = (cpustate->is & 0x38) | ((cpustate->is + 1) & 0x07);
+}
+
+/***************************************************
+ * O Z C S 1110 1110
+ * 0 x 0 x XS ISAR--
+ ***************************************************/
+static void f8_xs_isar_d(f8_Regs *cpustate)
+{
+ CLR_OZCS;
+ cpustate->a ^= cpustate->r[cpustate->is];
+ SET_SZ(cpustate->a);
+ cpustate->is = (cpustate->is & 0x38) | ((cpustate->is - 1) & 0x07);
+}
+
+/***************************************************
+ * O Z C S 1111 rrrr
+ * 0 x 0 x NS r
+ ***************************************************/
+static void f8_ns(f8_Regs *cpustate, int r)
+{
+ CLR_OZCS;
+ cpustate->a &= cpustate->r[r];
+ SET_SZ(cpustate->a);
+}
+
+/***************************************************
+ * O Z C S 1111 1100
+ * 0 x 0 x NS ISAR
+ ***************************************************/
+static void f8_ns_isar(f8_Regs *cpustate)
+{
+ CLR_OZCS;
+ cpustate->a &= cpustate->r[cpustate->is];
+ SET_SZ(cpustate->a);
+}
+
+/***************************************************
+ * O Z C S 1111 1101
+ * 0 x 0 x NS ISAR++
+ ***************************************************/
+static void f8_ns_isar_i(f8_Regs *cpustate)
+{
+ CLR_OZCS;
+ cpustate->a &= cpustate->r[cpustate->is];
+ SET_SZ(cpustate->a);
+ cpustate->is = (cpustate->is & 0x38) | ((cpustate->is + 1) & 0x07);
+}
+
+/***************************************************
+ * O Z C S 1111 1110
+ * 0 x 0 x NS ISAR--
+ ***************************************************/
+static void f8_ns_isar_d(f8_Regs *cpustate)
+{
+ CLR_OZCS;
+ cpustate->a &= cpustate->r[cpustate->is];
+ SET_SZ(cpustate->a);
+ cpustate->is = (cpustate->is & 0x38) | ((cpustate->is - 1) & 0x07);
+}
+
+static CPU_RESET( f8 )
+{
+ f8_Regs *cpustate = get_safe_token(device);
+ UINT8 data;
+ int i;
+ device_irq_callback save_callback;
+
+ save_callback = cpustate->irq_callback;
+ memset(cpustate, 0, sizeof(f8_Regs));
+ cpustate->irq_callback = save_callback;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+ cpustate->iospace = device->space(AS_IO);
+ cpustate->w&=~I;
+
+ /* save PC0 to PC1 and reset PC0 */
+ ROMC_08(cpustate);
+ /* fetch the first opcode */
+ ROMC_00(cpustate, cS);
+
+ /* initialize the timer shift register
+ * this is an 8 bit polynome counter which can be loaded parallel
+ * with 0xff the outputs never change and thus the timer is disabled.
+ * with 0xfe the shifter starts cycling through 255 states until it
+ * reaches 0xfe again (and then issues an interrupt).
+ * the counter output values are not sequential, but go like this:
+ * 0xfe, 0xfd, 0xfb, 0xf7, 0xee, 0xdc ... etc. :-)
+ * We have to build a lookup table to tell how many cycles a write
+
+ */
+ data = 0xfe; /* initial value */
+ for (i = 0; i < 256; i++)
+ {
+ timer_shifter[i] = data;
+ if ( (((data >> 3) ^ (data >> 4)) ^
+ ((data >> 5) ^ (data >> 7))) & 1 )
+ data <<= 1;
+ else
+ data = (data << 1) | 1;
+ }
+}
+
+/* Execute cycles - returns number of cycles actually run */
+static CPU_EXECUTE( f8 )
+{
+ f8_Regs *cpustate = get_safe_token(device);
+
+ do
+ {
+ UINT8 op=cpustate->dbus;
+ debugger_instruction_hook(device, (cpustate->pc0 - 1) & 0xffff);
+
+ switch( op )
+ {
+ /* opcode bitmask */
+ case 0x00: /* 0000 0000 */ f8_lr_a_ku(cpustate); break;
+ case 0x01: /* 0000 0001 */ f8_lr_a_kl(cpustate); break;
+ case 0x02: /* 0000 0010 */ f8_lr_a_qu(cpustate); break;
+ case 0x03: /* 0000 0011 */ f8_lr_a_ql(cpustate); break;
+ case 0x04: /* 0000 0100 */ f8_lr_ku_a(cpustate); break;
+ case 0x05: /* 0000 0101 */ f8_lr_kl_a(cpustate); break;
+ case 0x06: /* 0000 0110 */ f8_lr_qu_a(cpustate); break;
+ case 0x07: /* 0000 0111 */ f8_lr_ql_a(cpustate); break;
+ case 0x08: /* 0000 1000 */ f8_lr_k_p(cpustate); break;
+ case 0x09: /* 0000 1001 */ f8_lr_p_k(cpustate); break;
+ case 0x0a: /* 0000 1010 */ f8_lr_a_is(cpustate); break;
+ case 0x0b: /* 0000 1011 */ f8_lr_is_a(cpustate); break;
+ case 0x0c: /* 0000 1100 */ f8_pk(cpustate); break;
+ case 0x0d: /* 0000 1101 */ f8_lr_p0_q(cpustate); break;
+ case 0x0e: /* 0000 1110 */ f8_lr_q_dc(cpustate); break;
+ case 0x0f: /* 0000 1111 */ f8_lr_dc_q(cpustate); break;
+
+ case 0x10: /* 0001 0000 */ f8_lr_dc_h(cpustate); break;
+ case 0x11: /* 0001 0001 */ f8_lr_h_dc(cpustate); break;
+ case 0x12: /* 0001 0010 */ f8_sr_1(cpustate); break;
+ case 0x13: /* 0001 0011 */ f8_sl_1(cpustate); break;
+ case 0x14: /* 0001 0100 */ f8_sr_4(cpustate); break;
+ case 0x15: /* 0001 0101 */ f8_sl_4(cpustate); break;
+ case 0x16: /* 0001 0110 */ f8_lm(cpustate); break;
+ case 0x17: /* 0001 0111 */ f8_st(cpustate); break;
+ case 0x18: /* 0001 1000 */ f8_com(cpustate); break;
+ case 0x19: /* 0001 1001 */ f8_lnk(cpustate); break;
+ case 0x1a: /* 0001 1010 */ f8_di(cpustate); break;
+ case 0x1b: /* 0001 1011 */ f8_ei(cpustate); break;
+ case 0x1c: /* 0001 1100 */ f8_pop(cpustate); break;
+ case 0x1d: /* 0001 1101 */ f8_lr_w_j(cpustate); break;
+ case 0x1e: /* 0001 1110 */ f8_lr_j_w(cpustate); break;
+ case 0x1f: /* 0001 1111 */ f8_inc(cpustate); break;
+
+ case 0x20: /* 0010 0000 */ f8_li(cpustate); break;
+ case 0x21: /* 0010 0001 */ f8_ni(cpustate); break;
+ case 0x22: /* 0010 0010 */ f8_oi(cpustate); break;
+ case 0x23: /* 0010 0011 */ f8_xi(cpustate); break;
+ case 0x24: /* 0010 0100 */ f8_ai(cpustate); break;
+ case 0x25: /* 0010 0101 */ f8_ci(cpustate); break;
+ case 0x26: /* 0010 0110 */ f8_in(cpustate); break;
+ case 0x27: /* 0010 0111 */ f8_out(cpustate); break;
+ case 0x28: /* 0010 1000 */ f8_pi(cpustate); break;
+ case 0x29: /* 0010 1001 */ f8_jmp(cpustate); break;
+ case 0x2a: /* 0010 1010 */ f8_dci(cpustate); break;
+ case 0x2b: /* 0010 1011 */ f8_nop(cpustate); break;
+ case 0x2c: /* 0010 1100 */ f8_xdc(cpustate); break;
+ case 0x2d: /* 0010 1101 */ illegal(cpustate); break;
+ case 0x2e: /* 0010 1110 */ illegal(cpustate); break;
+ case 0x2f: /* 0010 1111 */ illegal(cpustate); break;
+
+ case 0x30: /* 0011 0000 */ f8_ds_r(cpustate, 0); break;
+ case 0x31: /* 0011 0001 */ f8_ds_r(cpustate, 1); break;
+ case 0x32: /* 0011 0010 */ f8_ds_r(cpustate, 2); break;
+ case 0x33: /* 0011 0011 */ f8_ds_r(cpustate, 3); break;
+ case 0x34: /* 0011 0100 */ f8_ds_r(cpustate, 4); break;
+ case 0x35: /* 0011 0101 */ f8_ds_r(cpustate, 5); break;
+ case 0x36: /* 0011 0110 */ f8_ds_r(cpustate, 6); break;
+ case 0x37: /* 0011 0111 */ f8_ds_r(cpustate, 7); break;
+ case 0x38: /* 0011 1000 */ f8_ds_r(cpustate, 8); break;
+ case 0x39: /* 0011 1001 */ f8_ds_r(cpustate, 9); break;
+ case 0x3a: /* 0011 1010 */ f8_ds_r(cpustate, 10); break;
+ case 0x3b: /* 0011 1011 */ f8_ds_r(cpustate, 11); break;
+ case 0x3c: /* 0011 1100 */ f8_ds_isar(cpustate); break;
+ case 0x3d: /* 0011 1101 */ f8_ds_isar_i(cpustate); break;
+ case 0x3e: /* 0011 1110 */ f8_ds_isar_d(cpustate); break;
+ case 0x3f: /* 0011 1111 */ illegal(cpustate); break;
+
+ case 0x40: /* 0100 0000 */ f8_lr_a_r(cpustate, 0); break;
+ case 0x41: /* 0100 0001 */ f8_lr_a_r(cpustate, 1); break;
+ case 0x42: /* 0100 0010 */ f8_lr_a_r(cpustate, 2); break;
+ case 0x43: /* 0100 0011 */ f8_lr_a_r(cpustate, 3); break;
+ case 0x44: /* 0100 0100 */ f8_lr_a_r(cpustate, 4); break;
+ case 0x45: /* 0100 0101 */ f8_lr_a_r(cpustate, 5); break;
+ case 0x46: /* 0100 0110 */ f8_lr_a_r(cpustate, 6); break;
+ case 0x47: /* 0100 0111 */ f8_lr_a_r(cpustate, 7); break;
+ case 0x48: /* 0100 1000 */ f8_lr_a_r(cpustate, 8); break;
+ case 0x49: /* 0100 1001 */ f8_lr_a_r(cpustate, 9); break;
+ case 0x4a: /* 0100 1010 */ f8_lr_a_r(cpustate, 10); break;
+ case 0x4b: /* 0100 1011 */ f8_lr_a_r(cpustate, 11); break;
+ case 0x4c: /* 0100 1100 */ f8_lr_a_isar(cpustate); break;
+ case 0x4d: /* 0100 1101 */ f8_lr_a_isar_i(cpustate); break;
+ case 0x4e: /* 0100 1110 */ f8_lr_a_isar_d(cpustate); break;
+ case 0x4f: /* 0100 1111 */ illegal(cpustate); break;
+
+ case 0x50: /* 0101 0000 */ f8_lr_r_a(cpustate, 0); break;
+ case 0x51: /* 0101 0001 */ f8_lr_r_a(cpustate, 1); break;
+ case 0x52: /* 0101 0010 */ f8_lr_r_a(cpustate, 2); break;
+ case 0x53: /* 0101 0011 */ f8_lr_r_a(cpustate, 3); break;
+ case 0x54: /* 0101 0100 */ f8_lr_r_a(cpustate, 4); break;
+ case 0x55: /* 0101 0101 */ f8_lr_r_a(cpustate, 5); break;
+ case 0x56: /* 0101 0110 */ f8_lr_r_a(cpustate, 6); break;
+ case 0x57: /* 0101 0111 */ f8_lr_r_a(cpustate, 7); break;
+ case 0x58: /* 0101 1000 */ f8_lr_r_a(cpustate, 8); break;
+ case 0x59: /* 0101 1001 */ f8_lr_r_a(cpustate, 9); break;
+ case 0x5a: /* 0101 1010 */ f8_lr_r_a(cpustate, 10); break;
+ case 0x5b: /* 0101 1011 */ f8_lr_r_a(cpustate, 11); break;
+ case 0x5c: /* 0101 1100 */ f8_lr_isar_a(cpustate); break;
+ case 0x5d: /* 0101 1101 */ f8_lr_isar_i_a(cpustate); break;
+ case 0x5e: /* 0101 1110 */ f8_lr_isar_d_a(cpustate); break;
+ case 0x5f: /* 0101 1111 */ illegal(cpustate); break;
+
+ case 0x60: /* 0110 0000 */ f8_lisu(cpustate, 0x00); break;
+ case 0x61: /* 0110 0001 */ f8_lisu(cpustate, 0x08); break;
+ case 0x62: /* 0110 0010 */ f8_lisu(cpustate, 0x10); break;
+ case 0x63: /* 0110 0011 */ f8_lisu(cpustate, 0x18); break;
+ case 0x64: /* 0110 0100 */ f8_lisu(cpustate, 0x20); break;
+ case 0x65: /* 0110 0101 */ f8_lisu(cpustate, 0x28); break;
+ case 0x66: /* 0110 0110 */ f8_lisu(cpustate, 0x30); break;
+ case 0x67: /* 0110 0111 */ f8_lisu(cpustate, 0x38); break;
+ case 0x68: /* 0110 1000 */ f8_lisl(cpustate, 0x00); break;
+ case 0x69: /* 0110 1001 */ f8_lisl(cpustate, 0x01); break;
+ case 0x6a: /* 0110 1010 */ f8_lisl(cpustate, 0x02); break;
+ case 0x6b: /* 0110 1011 */ f8_lisl(cpustate, 0x03); break;
+ case 0x6c: /* 0110 1100 */ f8_lisl(cpustate, 0x04); break;
+ case 0x6d: /* 0110 1101 */ f8_lisl(cpustate, 0x05); break;
+ case 0x6e: /* 0110 1110 */ f8_lisl(cpustate, 0x06); break;
+ case 0x6f: /* 0110 1111 */ f8_lisl(cpustate, 0x07); break;
+
+ case 0x70: /* 0111 0000 */ f8_lis(cpustate, 0x0); break;
+ case 0x71: /* 0111 0001 */ f8_lis(cpustate, 0x1); break;
+ case 0x72: /* 0111 0010 */ f8_lis(cpustate, 0x2); break;
+ case 0x73: /* 0111 0011 */ f8_lis(cpustate, 0x3); break;
+ case 0x74: /* 0111 0100 */ f8_lis(cpustate, 0x4); break;
+ case 0x75: /* 0111 0101 */ f8_lis(cpustate, 0x5); break;
+ case 0x76: /* 0111 0110 */ f8_lis(cpustate, 0x6); break;
+ case 0x77: /* 0111 0111 */ f8_lis(cpustate, 0x7); break;
+ case 0x78: /* 0111 1000 */ f8_lis(cpustate, 0x8); break;
+ case 0x79: /* 0111 1001 */ f8_lis(cpustate, 0x9); break;
+ case 0x7a: /* 0111 1010 */ f8_lis(cpustate, 0xa); break;
+ case 0x7b: /* 0111 1011 */ f8_lis(cpustate, 0xb); break;
+ case 0x7c: /* 0111 1100 */ f8_lis(cpustate, 0xc); break;
+ case 0x7d: /* 0111 1101 */ f8_lis(cpustate, 0xd); break;
+ case 0x7e: /* 0111 1110 */ f8_lis(cpustate, 0xe); break;
+ case 0x7f: /* 0111 1111 */ f8_lis(cpustate, 0xf); break;
+
+ case 0x80: /* 1000 0000 */ f8_bt(cpustate, 0); break;
+ case 0x81: /* 1000 0001 */ f8_bt(cpustate, 1); break;
+ case 0x82: /* 1000 0010 */ f8_bt(cpustate, 2); break;
+ case 0x83: /* 1000 0011 */ f8_bt(cpustate, 3); break;
+ case 0x84: /* 1000 0100 */ f8_bt(cpustate, 4); break;
+ case 0x85: /* 1000 0101 */ f8_bt(cpustate, 5); break;
+ case 0x86: /* 1000 0110 */ f8_bt(cpustate, 6); break;
+ case 0x87: /* 1000 0111 */ f8_bt(cpustate, 7); break;
+ case 0x88: /* 1000 1000 */ f8_am(cpustate); break;
+ case 0x89: /* 1000 1001 */ f8_amd(cpustate); break;
+ case 0x8a: /* 1000 1010 */ f8_nm(cpustate); break;
+ case 0x8b: /* 1000 1011 */ f8_om(cpustate); break;
+ case 0x8c: /* 1000 1100 */ f8_xm(cpustate); break;
+ case 0x8d: /* 1000 1101 */ f8_cm(cpustate); break;
+ case 0x8e: /* 1000 1110 */ f8_adc(cpustate); break;
+ case 0x8f: /* 1000 1111 */ f8_br7(cpustate); break;
+
+ case 0x90: /* 1001 0000 */ f8_bf(cpustate, 0x0); break;
+ case 0x91: /* 1001 0001 */ f8_bf(cpustate, 0x1); break;
+ case 0x92: /* 1001 0010 */ f8_bf(cpustate, 0x2); break;
+ case 0x93: /* 1001 0011 */ f8_bf(cpustate, 0x3); break;
+ case 0x94: /* 1001 0100 */ f8_bf(cpustate, 0x4); break;
+ case 0x95: /* 1001 0101 */ f8_bf(cpustate, 0x5); break;
+ case 0x96: /* 1001 0110 */ f8_bf(cpustate, 0x6); break;
+ case 0x97: /* 1001 0111 */ f8_bf(cpustate, 0x7); break;
+ case 0x98: /* 1001 1000 */ f8_bf(cpustate, 0x8); break;
+ case 0x99: /* 1001 1001 */ f8_bf(cpustate, 0x9); break;
+ case 0x9a: /* 1001 1010 */ f8_bf(cpustate, 0xa); break;
+ case 0x9b: /* 1001 1011 */ f8_bf(cpustate, 0xb); break;
+ case 0x9c: /* 1001 1100 */ f8_bf(cpustate, 0xc); break;
+ case 0x9d: /* 1001 1101 */ f8_bf(cpustate, 0xd); break;
+ case 0x9e: /* 1001 1110 */ f8_bf(cpustate, 0xe); break;
+ case 0x9f: /* 1001 1111 */ f8_bf(cpustate, 0xf); break;
+
+ case 0xa0: /* 1010 0000 */ f8_ins_0(cpustate, 0x0); break;
+ case 0xa1: /* 1010 0001 */ f8_ins_0(cpustate, 0x1); break;
+ case 0xa2: /* 1010 0010 */ illegal(cpustate); break;
+ case 0xa3: /* 1010 0011 */ illegal(cpustate); break;
+ case 0xa4: /* 1010 0100 */ f8_ins_1(cpustate, 0x4); break;
+ case 0xa5: /* 1010 0101 */ f8_ins_1(cpustate, 0x5); break;
+ case 0xa6: /* 1010 0110 */ f8_ins_1(cpustate, 0x6); break;
+ case 0xa7: /* 1010 0111 */ f8_ins_1(cpustate, 0x7); break;
+ case 0xa8: /* 1010 1000 */ f8_ins_1(cpustate, 0x8); break;
+ case 0xa9: /* 1010 1001 */ f8_ins_1(cpustate, 0x9); break;
+ case 0xaa: /* 1010 1010 */ f8_ins_1(cpustate, 0xa); break;
+ case 0xab: /* 1010 1011 */ f8_ins_1(cpustate, 0xb); break;
+ case 0xac: /* 1010 1100 */ f8_ins_1(cpustate, 0xc); break;
+ case 0xad: /* 1010 1101 */ f8_ins_1(cpustate, 0xd); break;
+ case 0xae: /* 1010 1110 */ f8_ins_1(cpustate, 0xe); break;
+ case 0xaf: /* 1010 1111 */ f8_ins_1(cpustate, 0xf); break;
+
+ case 0xb0: /* 1011 0000 */ f8_outs_0(cpustate, 0x0); break;
+ case 0xb1: /* 1011 0001 */ f8_outs_0(cpustate, 0x1); break;
+ case 0xb2: /* 1011 0010 */ illegal(cpustate); break;
+ case 0xb3: /* 1011 0011 */ illegal(cpustate); break;
+ case 0xb4: /* 1011 0100 */ f8_outs_1(cpustate, 0x4); break;
+ case 0xb5: /* 1011 0101 */ f8_outs_1(cpustate, 0x5); break;
+ case 0xb6: /* 1011 0110 */ f8_outs_1(cpustate, 0x6); break;
+ case 0xb7: /* 1011 0111 */ f8_outs_1(cpustate, 0x7); break;
+ case 0xb8: /* 1011 1000 */ f8_outs_1(cpustate, 0x8); break;
+ case 0xb9: /* 1011 1001 */ f8_outs_1(cpustate, 0x9); break;
+ case 0xba: /* 1011 1010 */ f8_outs_1(cpustate, 0xa); break;
+ case 0xbb: /* 1011 1011 */ f8_outs_1(cpustate, 0xb); break;
+ case 0xbc: /* 1011 1100 */ f8_outs_1(cpustate, 0xc); break;
+ case 0xbd: /* 1011 1101 */ f8_outs_1(cpustate, 0xd); break;
+ case 0xbe: /* 1011 1110 */ f8_outs_1(cpustate, 0xe); break;
+ case 0xbf: /* 1011 1111 */ f8_outs_1(cpustate, 0xf); break;
+
+ case 0xc0: /* 1100 0000 */ f8_as(cpustate, 0x0); break;
+ case 0xc1: /* 1100 0001 */ f8_as(cpustate, 0x1); break;
+ case 0xc2: /* 1100 0010 */ f8_as(cpustate, 0x2); break;
+ case 0xc3: /* 1100 0011 */ f8_as(cpustate, 0x3); break;
+ case 0xc4: /* 1100 0100 */ f8_as(cpustate, 0x4); break;
+ case 0xc5: /* 1100 0101 */ f8_as(cpustate, 0x5); break;
+ case 0xc6: /* 1100 0110 */ f8_as(cpustate, 0x6); break;
+ case 0xc7: /* 1100 0111 */ f8_as(cpustate, 0x7); break;
+ case 0xc8: /* 1100 1000 */ f8_as(cpustate, 0x8); break;
+ case 0xc9: /* 1100 1001 */ f8_as(cpustate, 0x9); break;
+ case 0xca: /* 1100 1010 */ f8_as(cpustate, 0xa); break;
+ case 0xcb: /* 1100 1011 */ f8_as(cpustate, 0xb); break;
+ case 0xcc: /* 1100 1100 */ f8_as_isar(cpustate); break;
+ case 0xcd: /* 1100 1101 */ f8_as_isar_i(cpustate); break;
+ case 0xce: /* 1100 1110 */ f8_as_isar_d(cpustate); break;
+ case 0xcf: /* 1100 1111 */ illegal(cpustate); break;
+
+ case 0xd0: /* 1101 0000 */ f8_asd(cpustate, 0x0); break;
+ case 0xd1: /* 1101 0001 */ f8_asd(cpustate, 0x1); break;
+ case 0xd2: /* 1101 0010 */ f8_asd(cpustate, 0x2); break;
+ case 0xd3: /* 1101 0011 */ f8_asd(cpustate, 0x3); break;
+ case 0xd4: /* 1101 0100 */ f8_asd(cpustate, 0x4); break;
+ case 0xd5: /* 1101 0101 */ f8_asd(cpustate, 0x5); break;
+ case 0xd6: /* 1101 0110 */ f8_asd(cpustate, 0x6); break;
+ case 0xd7: /* 1101 0111 */ f8_asd(cpustate, 0x7); break;
+ case 0xd8: /* 1101 1000 */ f8_asd(cpustate, 0x8); break;
+ case 0xd9: /* 1101 1001 */ f8_asd(cpustate, 0x9); break;
+ case 0xda: /* 1101 1010 */ f8_asd(cpustate, 0xa); break;
+ case 0xdb: /* 1101 1011 */ f8_asd(cpustate, 0xb); break;
+ case 0xdc: /* 1101 1100 */ f8_asd_isar(cpustate); break;
+ case 0xdd: /* 1101 1101 */ f8_asd_isar_i(cpustate); break;
+ case 0xde: /* 1101 1110 */ f8_asd_isar_d(cpustate); break;
+ case 0xdf: /* 1101 1111 */ illegal(cpustate); break;
+
+ case 0xe0: /* 1110 0000 */ f8_xs(cpustate, 0x0); break;
+ case 0xe1: /* 1110 0001 */ f8_xs(cpustate, 0x1); break;
+ case 0xe2: /* 1110 0010 */ f8_xs(cpustate, 0x2); break;
+ case 0xe3: /* 1110 0011 */ f8_xs(cpustate, 0x3); break;
+ case 0xe4: /* 1110 0100 */ f8_xs(cpustate, 0x4); break;
+ case 0xe5: /* 1110 0101 */ f8_xs(cpustate, 0x5); break;
+ case 0xe6: /* 1110 0110 */ f8_xs(cpustate, 0x6); break;
+ case 0xe7: /* 1110 0111 */ f8_xs(cpustate, 0x7); break;
+ case 0xe8: /* 1110 1000 */ f8_xs(cpustate, 0x8); break;
+ case 0xe9: /* 1110 1001 */ f8_xs(cpustate, 0x9); break;
+ case 0xea: /* 1110 1010 */ f8_xs(cpustate, 0xa); break;
+ case 0xeb: /* 1110 1011 */ f8_xs(cpustate, 0xb); break;
+ case 0xec: /* 1110 1100 */ f8_xs_isar(cpustate); break;
+ case 0xed: /* 1110 1101 */ f8_xs_isar_i(cpustate); break;
+ case 0xee: /* 1110 1110 */ f8_xs_isar_d(cpustate); break;
+ case 0xef: /* 1110 1111 */ illegal(cpustate); break;
+
+ case 0xf0: /* 1111 0000 */ f8_ns(cpustate, 0x0); break;
+ case 0xf1: /* 1111 0001 */ f8_ns(cpustate, 0x1); break;
+ case 0xf2: /* 1111 0010 */ f8_ns(cpustate, 0x2); break;
+ case 0xf3: /* 1111 0011 */ f8_ns(cpustate, 0x3); break;
+ case 0xf4: /* 1111 0100 */ f8_ns(cpustate, 0x4); break;
+ case 0xf5: /* 1111 0101 */ f8_ns(cpustate, 0x5); break;
+ case 0xf6: /* 1111 0110 */ f8_ns(cpustate, 0x6); break;
+ case 0xf7: /* 1111 0111 */ f8_ns(cpustate, 0x7); break;
+ case 0xf8: /* 1111 1000 */ f8_ns(cpustate, 0x8); break;
+ case 0xf9: /* 1111 1001 */ f8_ns(cpustate, 0x9); break;
+ case 0xfa: /* 1111 1010 */ f8_ns(cpustate, 0xa); break;
+ case 0xfb: /* 1111 1011 */ f8_ns(cpustate, 0xb); break;
+ case 0xfc: /* 1111 1100 */ f8_ns_isar(cpustate); break;
+ case 0xfd: /* 1111 1101 */ f8_ns_isar_i(cpustate); break;
+ case 0xfe: /* 1111 1110 */ f8_ns_isar_d(cpustate); break;
+ case 0xff: /* 1111 1111 */ illegal(cpustate); break;
+ }
+ switch (op) {
+ case 0x0d:case 0x1b:case 0x1c:case 0x1d:
+ case 0x27:case 0x28:case 0x29:
+ case 0xb4:case 0xb5:case 0xb6:case 0xb7:
+ case 0xb8:case 0xb9:case 0xba:case 0xbb:
+ case 0xbc:case 0xbd:case 0xbe:case 0xbf:
+ ROMC_00(cpustate, cS);
+ break;
+ default:
+ if (cpustate->w&I && cpustate->irq_request) {
+ ROMC_1C(cpustate, cL);
+ ROMC_0F(cpustate);
+ ROMC_13(cpustate);
+ }
+ if((op>=0x30)&&(op<=0x3f)) /* SKR - DS is a long cycle inst */
+ ROMC_00(cpustate, cL);
+ else
+ ROMC_00(cpustate, cS);
+ break;
+ }
+
+ } while( cpustate->icount > 0 );
+}
+
+CPU_DISASSEMBLE( f8 );
+
+static CPU_INIT( f8 )
+{
+ f8_Regs *cpustate = get_safe_token(device);
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+ cpustate->iospace = device->space(AS_IO);
+
+ device->save_item(NAME(cpustate->pc0));
+ device->save_item(NAME(cpustate->pc1));
+ device->save_item(NAME(cpustate->dc0));
+ device->save_item(NAME(cpustate->dc1));
+ device->save_item(NAME(cpustate->a));
+ device->save_item(NAME(cpustate->w));
+ device->save_item(NAME(cpustate->is));
+ device->save_item(NAME(cpustate->dbus));
+ device->save_item(NAME(cpustate->io));
+ device->save_item(NAME(cpustate->irq_vector));
+ device->save_item(NAME(cpustate->irq_request));
+ device->save_item(NAME(cpustate->r));
+}
+
+static CPU_SET_INFO( f8 )
+{
+ f8_Regs *cpustate = get_safe_token(device);
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_SP: cpustate->pc1 = info->i; break;
+ case CPUINFO_INT_PC:
+ cpustate->pc0 = info->i;
+ cpustate->dbus = cpustate->direct->read_decrypted_byte(cpustate->pc0);
+ cpustate->pc0 += 1;
+ break;
+ case CPUINFO_INT_PREVIOUSPC: break; /* TODO? */
+ case CPUINFO_INT_INPUT_STATE + F8_INPUT_LINE_INT_REQ: cpustate->irq_request = info->i; break;
+ case CPUINFO_INT_REGISTER + F8_PC0:
+ cpustate->pc0 = info->i;
+ cpustate->dbus = cpustate->direct->read_decrypted_byte(cpustate->pc0);
+ cpustate->pc0 += 1;
+ break;
+ case CPUINFO_INT_REGISTER + F8_PC1: cpustate->pc1 = info->i; break;
+ case CPUINFO_INT_REGISTER + F8_DC0: cpustate->dc0 = info->i; break;
+ case CPUINFO_INT_REGISTER + F8_DC1: cpustate->dc1 = info->i; break;
+ case CPUINFO_INT_REGISTER + F8_W: cpustate->w = info->i; break;
+ case CPUINFO_INT_REGISTER + F8_A: cpustate->a = info->i; break;
+ case CPUINFO_INT_REGISTER + F8_IS: cpustate->is = info->i & 0x3f; break;
+ case CPUINFO_INT_REGISTER + F8_J: cpustate->r[ 9] = info->i; break;
+ case CPUINFO_INT_REGISTER + F8_HU: cpustate->r[10] = info->i; break;
+ case CPUINFO_INT_REGISTER + F8_HL: cpustate->r[11] = info->i; break;
+ case CPUINFO_INT_REGISTER + F8_KU: cpustate->r[12] = info->i; break;
+ case CPUINFO_INT_REGISTER + F8_KL: cpustate->r[13] = info->i; break;
+ case CPUINFO_INT_REGISTER + F8_QU: cpustate->r[14] = info->i; break;
+ case CPUINFO_INT_REGISTER + F8_QL: cpustate->r[15] = info->i; break;
+
+ case CPUINFO_INT_REGISTER + F8_R0:
+ case CPUINFO_INT_REGISTER + F8_R1:
+ case CPUINFO_INT_REGISTER + F8_R2:
+ case CPUINFO_INT_REGISTER + F8_R3:
+ case CPUINFO_INT_REGISTER + F8_R4:
+ case CPUINFO_INT_REGISTER + F8_R5:
+ case CPUINFO_INT_REGISTER + F8_R6:
+ case CPUINFO_INT_REGISTER + F8_R7:
+ case CPUINFO_INT_REGISTER + F8_R8:
+ cpustate->r[state - (CPUINFO_INT_REGISTER + F8_R0)]=info->i;
+ break;
+
+ case CPUINFO_INT_REGISTER + F8_R16:
+ case CPUINFO_INT_REGISTER + F8_R17:
+ case CPUINFO_INT_REGISTER + F8_R18:
+ case CPUINFO_INT_REGISTER + F8_R19:
+ case CPUINFO_INT_REGISTER + F8_R20:
+ case CPUINFO_INT_REGISTER + F8_R21:
+ case CPUINFO_INT_REGISTER + F8_R22:
+ case CPUINFO_INT_REGISTER + F8_R23:
+ case CPUINFO_INT_REGISTER + F8_R24:
+ case CPUINFO_INT_REGISTER + F8_R25:
+ case CPUINFO_INT_REGISTER + F8_R26:
+ case CPUINFO_INT_REGISTER + F8_R27:
+ case CPUINFO_INT_REGISTER + F8_R28:
+ case CPUINFO_INT_REGISTER + F8_R29:
+ case CPUINFO_INT_REGISTER + F8_R30:
+ case CPUINFO_INT_REGISTER + F8_R31:
+ case CPUINFO_INT_REGISTER + F8_R32:
+ case CPUINFO_INT_REGISTER + F8_R33:
+ case CPUINFO_INT_REGISTER + F8_R34:
+ case CPUINFO_INT_REGISTER + F8_R35:
+ case CPUINFO_INT_REGISTER + F8_R36:
+ case CPUINFO_INT_REGISTER + F8_R37:
+ case CPUINFO_INT_REGISTER + F8_R38:
+ case CPUINFO_INT_REGISTER + F8_R39:
+ case CPUINFO_INT_REGISTER + F8_R40:
+ case CPUINFO_INT_REGISTER + F8_R41:
+ case CPUINFO_INT_REGISTER + F8_R42:
+ case CPUINFO_INT_REGISTER + F8_R43:
+ case CPUINFO_INT_REGISTER + F8_R44:
+ case CPUINFO_INT_REGISTER + F8_R45:
+ case CPUINFO_INT_REGISTER + F8_R46:
+ case CPUINFO_INT_REGISTER + F8_R47:
+ case CPUINFO_INT_REGISTER + F8_R48:
+ case CPUINFO_INT_REGISTER + F8_R49:
+ case CPUINFO_INT_REGISTER + F8_R50:
+ case CPUINFO_INT_REGISTER + F8_R51:
+ case CPUINFO_INT_REGISTER + F8_R52:
+ case CPUINFO_INT_REGISTER + F8_R53:
+ case CPUINFO_INT_REGISTER + F8_R54:
+ case CPUINFO_INT_REGISTER + F8_R55:
+ case CPUINFO_INT_REGISTER + F8_R56:
+ case CPUINFO_INT_REGISTER + F8_R57:
+ case CPUINFO_INT_REGISTER + F8_R58:
+ case CPUINFO_INT_REGISTER + F8_R59:
+ case CPUINFO_INT_REGISTER + F8_R60:
+ case CPUINFO_INT_REGISTER + F8_R61:
+ case CPUINFO_INT_REGISTER + F8_R62:
+ case CPUINFO_INT_REGISTER + F8_R63:
+ cpustate->r[state - (CPUINFO_INT_REGISTER + F8_R16) + 16]=info->i;
+ break;
+ }
+ return;
+}
+
+CPU_GET_INFO( f8 )
+{
+ f8_Regs *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(f8_Regs); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 1; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 3; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 7; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_SP: info->i = cpustate->pc1; break;
+ case CPUINFO_INT_PC: info->i = (cpustate->pc0 - 1) & 0xffff; break;
+ case CPUINFO_INT_PREVIOUSPC: info->i = 0; /* TODO??? */ break;
+
+ case CPUINFO_INT_INPUT_STATE + F8_INPUT_LINE_INT_REQ: info->i = cpustate->irq_request; break;
+
+ case CPUINFO_INT_REGISTER + F8_PC0: info->i = (cpustate->pc0 - 1) & 0xffff; break;
+ case CPUINFO_INT_REGISTER + F8_PC1: info->i = cpustate->pc1; break;
+ case CPUINFO_INT_REGISTER + F8_DC0: info->i = cpustate->dc0; break;
+ case CPUINFO_INT_REGISTER + F8_DC1: info->i = cpustate->dc1; break;
+ case CPUINFO_INT_REGISTER + F8_W: info->i = cpustate->w; break;
+ case CPUINFO_INT_REGISTER + F8_A: info->i = cpustate->a; break;
+ case CPUINFO_INT_REGISTER + F8_IS: info->i = cpustate->is; break;
+ case CPUINFO_INT_REGISTER + F8_J: info->i = cpustate->r[ 9]; break;
+ case CPUINFO_INT_REGISTER + F8_HU: info->i = cpustate->r[10]; break;
+ case CPUINFO_INT_REGISTER + F8_HL: info->i = cpustate->r[11]; break;
+ case CPUINFO_INT_REGISTER + F8_KU: info->i = cpustate->r[12]; break;
+ case CPUINFO_INT_REGISTER + F8_KL: info->i = cpustate->r[13]; break;
+ case CPUINFO_INT_REGISTER + F8_QU: info->i = cpustate->r[14]; break;
+ case CPUINFO_INT_REGISTER + F8_QL: info->i = cpustate->r[15]; break;
+
+ case CPUINFO_INT_REGISTER + F8_R0:
+ case CPUINFO_INT_REGISTER + F8_R1:
+ case CPUINFO_INT_REGISTER + F8_R2:
+ case CPUINFO_INT_REGISTER + F8_R3:
+ case CPUINFO_INT_REGISTER + F8_R4:
+ case CPUINFO_INT_REGISTER + F8_R5:
+ case CPUINFO_INT_REGISTER + F8_R6:
+ case CPUINFO_INT_REGISTER + F8_R7:
+ case CPUINFO_INT_REGISTER + F8_R8:
+ info->i = cpustate->r[state - (CPUINFO_INT_REGISTER + F8_R0)]; break;
+
+
+ case CPUINFO_INT_REGISTER + F8_R16:
+ case CPUINFO_INT_REGISTER + F8_R17:
+ case CPUINFO_INT_REGISTER + F8_R18:
+ case CPUINFO_INT_REGISTER + F8_R19:
+ case CPUINFO_INT_REGISTER + F8_R20:
+ case CPUINFO_INT_REGISTER + F8_R21:
+ case CPUINFO_INT_REGISTER + F8_R22:
+ case CPUINFO_INT_REGISTER + F8_R23:
+ case CPUINFO_INT_REGISTER + F8_R24:
+ case CPUINFO_INT_REGISTER + F8_R25:
+ case CPUINFO_INT_REGISTER + F8_R26:
+ case CPUINFO_INT_REGISTER + F8_R27:
+ case CPUINFO_INT_REGISTER + F8_R28:
+ case CPUINFO_INT_REGISTER + F8_R29:
+ case CPUINFO_INT_REGISTER + F8_R30:
+ case CPUINFO_INT_REGISTER + F8_R31:
+ case CPUINFO_INT_REGISTER + F8_R32:
+ case CPUINFO_INT_REGISTER + F8_R33:
+ case CPUINFO_INT_REGISTER + F8_R34:
+ case CPUINFO_INT_REGISTER + F8_R35:
+ case CPUINFO_INT_REGISTER + F8_R36:
+ case CPUINFO_INT_REGISTER + F8_R37:
+ case CPUINFO_INT_REGISTER + F8_R38:
+ case CPUINFO_INT_REGISTER + F8_R39:
+ case CPUINFO_INT_REGISTER + F8_R40:
+ case CPUINFO_INT_REGISTER + F8_R41:
+ case CPUINFO_INT_REGISTER + F8_R42:
+ case CPUINFO_INT_REGISTER + F8_R43:
+ case CPUINFO_INT_REGISTER + F8_R44:
+ case CPUINFO_INT_REGISTER + F8_R45:
+ case CPUINFO_INT_REGISTER + F8_R46:
+ case CPUINFO_INT_REGISTER + F8_R47:
+ case CPUINFO_INT_REGISTER + F8_R48:
+ case CPUINFO_INT_REGISTER + F8_R49:
+ case CPUINFO_INT_REGISTER + F8_R50:
+ case CPUINFO_INT_REGISTER + F8_R51:
+ case CPUINFO_INT_REGISTER + F8_R52:
+ case CPUINFO_INT_REGISTER + F8_R53:
+ case CPUINFO_INT_REGISTER + F8_R54:
+ case CPUINFO_INT_REGISTER + F8_R55:
+ case CPUINFO_INT_REGISTER + F8_R56:
+ case CPUINFO_INT_REGISTER + F8_R57:
+ case CPUINFO_INT_REGISTER + F8_R58:
+ case CPUINFO_INT_REGISTER + F8_R59:
+ case CPUINFO_INT_REGISTER + F8_R60:
+ case CPUINFO_INT_REGISTER + F8_R61:
+ case CPUINFO_INT_REGISTER + F8_R62:
+ case CPUINFO_INT_REGISTER + F8_R63:
+ info->i = cpustate->r[state - (CPUINFO_INT_REGISTER + F8_R16) + 16]; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(f8); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(f8); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(f8); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(f8); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(f8); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "F8"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Fairchild F8"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s,
+ "Copyright Juergen Buchmueller, all rights reserved.");
+ break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c%c%c%c",
+ cpustate->w & 0x10 ? 'I':'.',
+ cpustate->w & 0x08 ? 'O':'.',
+ cpustate->w & 0x04 ? 'Z':'.',
+ cpustate->w & 0x02 ? 'C':'.',
+ cpustate->w & 0x01 ? 'S':'.');
+ break;
+
+ case CPUINFO_STR_REGISTER+F8_PC0:sprintf(info->s, "PC0:%04X", ((cpustate->pc0) - 1) & 0xffff); break;
+ case CPUINFO_STR_REGISTER+F8_PC1:sprintf(info->s, "PC1:%04X", cpustate->pc1); break;
+ case CPUINFO_STR_REGISTER+F8_DC0:sprintf(info->s, "DC0:%04X", cpustate->dc0); break;
+ case CPUINFO_STR_REGISTER+F8_DC1:sprintf(info->s, "DC1:%04X", cpustate->dc1); break;
+ case CPUINFO_STR_REGISTER+F8_W: sprintf(info->s, "W :%02X", cpustate->w); break;
+ case CPUINFO_STR_REGISTER+F8_A: sprintf(info->s, "A :%02X", cpustate->a); break;
+ case CPUINFO_STR_REGISTER+F8_IS: sprintf(info->s, "IS :%02X", cpustate->is); break;
+ case CPUINFO_STR_REGISTER+F8_J: sprintf(info->s, "J :%02X", cpustate->r[9]); break;
+ case CPUINFO_STR_REGISTER+F8_HU: sprintf(info->s, "HU :%02X", cpustate->r[10]); break;
+ case CPUINFO_STR_REGISTER+F8_HL: sprintf(info->s, "HL :%02X", cpustate->r[11]); break;
+ case CPUINFO_STR_REGISTER+F8_KU: sprintf(info->s, "KU :%02X", cpustate->r[12]); break;
+ case CPUINFO_STR_REGISTER+F8_KL: sprintf(info->s, "KL :%02X", cpustate->r[13]); break;
+ case CPUINFO_STR_REGISTER+F8_QU: sprintf(info->s, "QU :%02X", cpustate->r[14]); break;
+ case CPUINFO_STR_REGISTER+F8_QL: sprintf(info->s, "QL :%02X", cpustate->r[15]); break;
+ case CPUINFO_STR_REGISTER+F8_R0: sprintf(info->s, "R0 :%02X", cpustate->r[0]); break;
+ case CPUINFO_STR_REGISTER+F8_R1: sprintf(info->s, "R1 :%02X", cpustate->r[1]); break;
+ case CPUINFO_STR_REGISTER+F8_R2: sprintf(info->s, "R2 :%02X", cpustate->r[2]); break;
+ case CPUINFO_STR_REGISTER+F8_R3: sprintf(info->s, "R3 :%02X", cpustate->r[3]); break;
+ case CPUINFO_STR_REGISTER+F8_R4: sprintf(info->s, "R4 :%02X", cpustate->r[4]); break;
+ case CPUINFO_STR_REGISTER+F8_R5: sprintf(info->s, "R5 :%02X", cpustate->r[5]); break;
+ case CPUINFO_STR_REGISTER+F8_R6: sprintf(info->s, "R6 :%02X", cpustate->r[6]); break;
+ case CPUINFO_STR_REGISTER+F8_R7: sprintf(info->s, "R7 :%02X", cpustate->r[7]); break;
+ case CPUINFO_STR_REGISTER+F8_R8: sprintf(info->s, "R8 :%02X", cpustate->r[8]); break;
+ case CPUINFO_STR_REGISTER+F8_R16: sprintf(info->s, "R16 :%02X", cpustate->r[16]); break;
+ case CPUINFO_STR_REGISTER+F8_R17: sprintf(info->s, "R17 :%02X", cpustate->r[17]); break;
+ case CPUINFO_STR_REGISTER+F8_R18: sprintf(info->s, "R18 :%02X", cpustate->r[18]); break;
+ case CPUINFO_STR_REGISTER+F8_R19: sprintf(info->s, "R19 :%02X", cpustate->r[19]); break;
+ case CPUINFO_STR_REGISTER+F8_R20: sprintf(info->s, "R20 :%02X", cpustate->r[20]); break;
+ case CPUINFO_STR_REGISTER+F8_R21: sprintf(info->s, "R21 :%02X", cpustate->r[21]); break;
+ case CPUINFO_STR_REGISTER+F8_R22: sprintf(info->s, "R22 :%02X", cpustate->r[22]); break;
+ case CPUINFO_STR_REGISTER+F8_R23: sprintf(info->s, "R23 :%02X", cpustate->r[23]); break;
+ case CPUINFO_STR_REGISTER+F8_R24: sprintf(info->s, "R24 :%02X", cpustate->r[24]); break;
+ case CPUINFO_STR_REGISTER+F8_R25: sprintf(info->s, "R25 :%02X", cpustate->r[25]); break;
+ case CPUINFO_STR_REGISTER+F8_R26: sprintf(info->s, "R26 :%02X", cpustate->r[26]); break;
+ case CPUINFO_STR_REGISTER+F8_R27: sprintf(info->s, "R27 :%02X", cpustate->r[27]); break;
+ case CPUINFO_STR_REGISTER+F8_R28: sprintf(info->s, "R28 :%02X", cpustate->r[28]); break;
+ case CPUINFO_STR_REGISTER+F8_R29: sprintf(info->s, "R29 :%02X", cpustate->r[29]); break;
+ case CPUINFO_STR_REGISTER+F8_R30: sprintf(info->s, "R30 :%02X", cpustate->r[30]); break;
+ case CPUINFO_STR_REGISTER+F8_R31: sprintf(info->s, "R31 :%02X", cpustate->r[31]); break;
+ case CPUINFO_STR_REGISTER+F8_R32: sprintf(info->s, "R32 :%02X", cpustate->r[32]); break;
+ case CPUINFO_STR_REGISTER+F8_R33: sprintf(info->s, "R33 :%02X", cpustate->r[33]); break;
+ case CPUINFO_STR_REGISTER+F8_R34: sprintf(info->s, "R34 :%02X", cpustate->r[34]); break;
+ case CPUINFO_STR_REGISTER+F8_R35: sprintf(info->s, "R35 :%02X", cpustate->r[35]); break;
+ case CPUINFO_STR_REGISTER+F8_R36: sprintf(info->s, "R36 :%02X", cpustate->r[36]); break;
+ case CPUINFO_STR_REGISTER+F8_R37: sprintf(info->s, "R37 :%02X", cpustate->r[37]); break;
+ case CPUINFO_STR_REGISTER+F8_R38: sprintf(info->s, "R38 :%02X", cpustate->r[38]); break;
+ case CPUINFO_STR_REGISTER+F8_R39: sprintf(info->s, "R39 :%02X", cpustate->r[39]); break;
+ case CPUINFO_STR_REGISTER+F8_R40: sprintf(info->s, "R40 :%02X", cpustate->r[40]); break;
+ case CPUINFO_STR_REGISTER+F8_R41: sprintf(info->s, "R41 :%02X", cpustate->r[41]); break;
+ case CPUINFO_STR_REGISTER+F8_R42: sprintf(info->s, "R42 :%02X", cpustate->r[42]); break;
+ case CPUINFO_STR_REGISTER+F8_R43: sprintf(info->s, "R43 :%02X", cpustate->r[43]); break;
+ case CPUINFO_STR_REGISTER+F8_R44: sprintf(info->s, "R44 :%02X", cpustate->r[44]); break;
+ case CPUINFO_STR_REGISTER+F8_R45: sprintf(info->s, "R45 :%02X", cpustate->r[45]); break;
+ case CPUINFO_STR_REGISTER+F8_R46: sprintf(info->s, "R46 :%02X", cpustate->r[46]); break;
+ case CPUINFO_STR_REGISTER+F8_R47: sprintf(info->s, "R47 :%02X", cpustate->r[47]); break;
+ case CPUINFO_STR_REGISTER+F8_R48: sprintf(info->s, "R48 :%02X", cpustate->r[48]); break;
+ case CPUINFO_STR_REGISTER+F8_R49: sprintf(info->s, "R49 :%02X", cpustate->r[49]); break;
+ case CPUINFO_STR_REGISTER+F8_R50: sprintf(info->s, "R50 :%02X", cpustate->r[50]); break;
+ case CPUINFO_STR_REGISTER+F8_R51: sprintf(info->s, "R51 :%02X", cpustate->r[51]); break;
+ case CPUINFO_STR_REGISTER+F8_R52: sprintf(info->s, "R52 :%02X", cpustate->r[52]); break;
+ case CPUINFO_STR_REGISTER+F8_R53: sprintf(info->s, "R53 :%02X", cpustate->r[53]); break;
+ case CPUINFO_STR_REGISTER+F8_R54: sprintf(info->s, "R54 :%02X", cpustate->r[54]); break;
+ case CPUINFO_STR_REGISTER+F8_R55: sprintf(info->s, "R55 :%02X", cpustate->r[55]); break;
+ case CPUINFO_STR_REGISTER+F8_R56: sprintf(info->s, "R56 :%02X", cpustate->r[56]); break;
+ case CPUINFO_STR_REGISTER+F8_R57: sprintf(info->s, "R57 :%02X", cpustate->r[57]); break;
+ case CPUINFO_STR_REGISTER+F8_R58: sprintf(info->s, "R58 :%02X", cpustate->r[58]); break;
+ case CPUINFO_STR_REGISTER+F8_R59: sprintf(info->s, "R59 :%02X", cpustate->r[59]); break;
+ case CPUINFO_STR_REGISTER+F8_R60: sprintf(info->s, "R60 :%02X", cpustate->r[60]); break;
+ case CPUINFO_STR_REGISTER+F8_R61: sprintf(info->s, "R61 :%02X", cpustate->r[61]); break;
+ case CPUINFO_STR_REGISTER+F8_R62: sprintf(info->s, "R62 :%02X", cpustate->r[62]); break;
+ case CPUINFO_STR_REGISTER+F8_R63: sprintf(info->s, "R63 :%02X", cpustate->r[63]); break;
+
+ }
+
+ return;
+}
+
+DEFINE_LEGACY_CPU_DEVICE(F8, f8);
diff --git a/trunk/src/emu/cpu/f8/f8.h b/trunk/src/emu/cpu/f8/f8.h
new file mode 100644
index 00000000000..51e2e6aeac1
--- /dev/null
+++ b/trunk/src/emu/cpu/f8/f8.h
@@ -0,0 +1,54 @@
+/*****************************************************************************
+ *
+ * f8.h
+ * Portable Fairchild F8 emulator interface
+ *
+ * Copyright Juergen Buchmueller, all rights reserved.
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * pullmoll@t-online.de
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ *****************************************************************************/
+
+#pragma once
+
+#ifndef __F8_H__
+#define _F8_H
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum
+{
+ F8_PC0=1, F8_PC1, F8_DC0, F8_DC1, F8_W, F8_A, F8_IS,
+ F8_J, F8_HU, F8_HL, F8_KU, F8_KL, F8_QU, F8_QL,
+
+ F8_R0, F8_R1, F8_R2, F8_R3, F8_R4, F8_R5, F8_R6, F8_R7, F8_R8,
+ F8_R16, F8_R17, F8_R18, F8_R19, F8_R20, F8_R21, F8_R22, F8_R23,
+ F8_R24, F8_R25, F8_R26, F8_R27, F8_R28, F8_R29, F8_R30, F8_R31,
+ F8_R32, F8_R33, F8_R34, F8_R35, F8_R36, F8_R37, F8_R38, F8_R39,
+ F8_R40, F8_R41, F8_R42, F8_R43, F8_R44, F8_R45, F8_R46, F8_R47,
+ F8_R48, F8_R49, F8_R50, F8_R51, F8_R52, F8_R53, F8_R54, F8_R55,
+ F8_R56, F8_R57, F8_R58, F8_R59, F8_R60, F8_R61, F8_R62, F8_R63
+};
+
+#define F8_INPUT_LINE_INT_REQ 1
+
+DECLARE_LEGACY_CPU_DEVICE(F8, f8);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __F8_H__ */
diff --git a/trunk/src/emu/cpu/f8/f8dasm.c b/trunk/src/emu/cpu/f8/f8dasm.c
new file mode 100644
index 00000000000..187dd53a1e6
--- /dev/null
+++ b/trunk/src/emu/cpu/f8/f8dasm.c
@@ -0,0 +1,533 @@
+#include "emu.h"
+#include "debugger.h"
+#include "f8.h"
+
+static const char *const rname[16] = {
+ "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7",
+ "R8", "J", "HU", "HL", "KU", "KL", "QU", "QL"
+};
+
+CPU_DISASSEMBLE( f8 )
+{
+ unsigned size = 0;
+ UINT8 op = oprom[size++];
+
+ switch( op )
+ {
+ /* opcode bitmask */
+ case 0x00: /* 0000 0000 */
+ sprintf(buffer, "LR A,KU");
+ break;
+ case 0x01: /* 0000 0001 */
+ sprintf(buffer, "LR A,KL");
+ break;
+ case 0x02: /* 0000 0010 */
+ sprintf(buffer, "LR A,QU");
+ break;
+ case 0x03: /* 0000 0011 */
+ sprintf(buffer, "LR A,QL");
+ break;
+ case 0x04: /* 0000 0100 */
+ sprintf(buffer, "LR KU,A");
+ break;
+ case 0x05: /* 0000 0101 */
+ sprintf(buffer, "LR KL,A");
+ break;
+ case 0x06: /* 0000 0110 */
+ sprintf(buffer, "LR QU,A");
+ break;
+ case 0x07: /* 0000 0111 */
+ sprintf(buffer, "LR QL,A");
+ break;
+
+ case 0x08: /* 0000 1000 */
+ sprintf(buffer, "LR K,P");
+ break;
+ case 0x09: /* 0000 1001 */
+ sprintf(buffer, "LR P,K");
+ break;
+ case 0x0a: /* 0000 1010 */
+ sprintf(buffer, "LR A,IS");
+ break;
+ case 0x0b: /* 0000 1011 */
+ sprintf(buffer, "LR IS,A");
+ break;
+
+ case 0x0c: /* 0000 1100 */
+ sprintf(buffer, "PK") ;
+ break;
+ case 0x0d: /* 0000 1101 */
+ sprintf(buffer, "LR P0,Q");
+ break;
+ case 0x0e: /* 0000 1110 */
+ sprintf(buffer, "LR Q,DC");
+ break;
+ case 0x0f: /* 0000 1111 */
+ sprintf(buffer, "LR DC,Q");
+ break;
+ case 0x10: /* 0001 0000 */
+ sprintf(buffer, "LR DC,H");
+ break;
+ case 0x11: /* 0001 0001 */
+ sprintf(buffer, "LR H,DC");
+ break;
+ case 0x12: /* 0001 0010 */
+ sprintf(buffer, "SR 1");
+ break;
+ case 0x13: /* 0001 0011 */
+ sprintf(buffer, "SL 1");
+ break;
+ case 0x14: /* 0001 0100 */
+ sprintf(buffer, "SR 4");
+ break;
+ case 0x15: /* 0001 0101 */
+ sprintf(buffer, "SL 4");
+ break;
+ case 0x16: /* 0001 0110 */
+ sprintf(buffer, "LM") ;
+ break;
+ case 0x17: /* 0001 0111 */
+ sprintf(buffer, "ST");
+ break;
+ case 0x18: /* 0001 1000 */
+ sprintf(buffer, "COM");
+ break;
+ case 0x19: /* 0001 1001 */
+ sprintf(buffer, "LNK");
+ break;
+ case 0x1a: /* 0001 1010 */
+ sprintf(buffer, "DI");
+ break;
+ case 0x1b: /* 0001 1011 */
+ sprintf(buffer, "EI");
+ break;
+ case 0x1c: /* 0001 1100 */
+ sprintf(buffer, "POP");
+ break;
+ case 0x1d: /* 0001 1101 */
+ sprintf(buffer, "LR W,J");
+ break;
+ case 0x1e: /* 0001 1110 */
+ sprintf(buffer, "LR J,W");
+ break;
+ case 0x1f: /* 0001 1111 */
+ sprintf(buffer, "INC");
+ break;
+ case 0x20: /* 0010 0000 */
+ sprintf(buffer, "LI $%02X", oprom[size++]);
+ break;
+ case 0x21: /* 0010 0001 */
+ sprintf(buffer, "NI $%02X", oprom[size++]);
+ break;
+ case 0x22: /* 0010 0010 */
+ sprintf(buffer, "OI $%02X", oprom[size++]);
+ break;
+ case 0x23: /* 0010 0011 */
+ sprintf(buffer, "XI $%02X", oprom[size++]);
+ break;
+ case 0x24: /* 0010 0100 */
+ sprintf(buffer, "AI $%02X", oprom[size++]);
+ break;
+ case 0x25: /* 0010 0101 */
+ sprintf(buffer, "CI $%02X", oprom[size++]);
+ break;
+ case 0x26: /* 0010 0110 */
+ sprintf(buffer, "IN $%02X", oprom[size++]);
+ break;
+ case 0x27: /* 0010 0111 */
+ sprintf(buffer, "OUT $%02X", oprom[size++]);
+ break;
+ case 0x28: /* 0010 1000 */
+ sprintf(buffer, "PI $%02X%02X", oprom[size + 0], oprom[size + 1]);
+ size += 2;
+ break;
+ case 0x29: /* 0010 1001 */
+ sprintf(buffer, "JMP $%02X%02X", oprom[size + 0], oprom[size + 1]);
+ size += 2;
+ break;
+ case 0x2a: /* 0010 1010 */
+ sprintf(buffer, "DCI $%02X%02X", oprom[size + 0], oprom[size + 1]);
+ size += 2;
+ break;
+ case 0x2b: /* 0010 1011 */
+ sprintf(buffer, "NOP");
+ break;
+ case 0x2c: /* 0010 1100 */
+ sprintf(buffer, "XDC");
+ break;
+ case 0x2d: /* 0010 1101 */
+ case 0x2e: /* 0010 1110 */
+ case 0x2f: /* 0010 1111 */
+ sprintf(buffer, "??? $%02X",op);
+ break;
+
+ case 0x30: /* 0011 0000 */
+ case 0x31: /* 0011 0001 */
+ case 0x32: /* 0011 0010 */
+ case 0x33: /* 0011 0011 */
+ case 0x34: /* 0011 0100 */
+ case 0x35: /* 0011 0101 */
+ case 0x36: /* 0011 0110 */
+ case 0x37: /* 0011 0111 */
+ case 0x38: /* 0011 1000 */
+ case 0x39: /* 0011 1001 */
+ case 0x3a: /* 0011 1010 */
+ case 0x3b: /* 0011 1011 */
+ sprintf(buffer, "DS %s",rname[op & 15]);
+ break;
+ case 0x3c: /* 0011 1100 */
+ sprintf(buffer, "DS (IS)");
+ break;
+ case 0x3d: /* 0011 1101 */
+ sprintf(buffer, "DS (IS++)");
+ break;
+ case 0x3e: /* 0011 1110 */
+ sprintf(buffer, "DS (IS--)");
+ break;
+ case 0x3f: /* 0011 1111 */
+ sprintf(buffer, "??? $%02X",op);
+ break;
+
+ case 0x40: /* 0100 0000 */
+ case 0x41: /* 0100 0001 */
+ case 0x42: /* 0100 0010 */
+ case 0x43: /* 0100 0011 */
+ case 0x44: /* 0100 0100 */
+ case 0x45: /* 0100 0101 */
+ case 0x46: /* 0100 0110 */
+ case 0x47: /* 0100 0111 */
+ case 0x48: /* 0100 1000 */
+ case 0x49: /* 0100 1001 */
+ case 0x4a: /* 0100 1010 */
+ case 0x4b: /* 0100 1011 */
+ sprintf(buffer, "LR A,%s",rname[op & 15]);
+ break;
+ case 0x4c: /* 0100 1100 */
+ sprintf(buffer, "LR A,(IS)");
+ break;
+ case 0x4d: /* 0100 1101 */
+ sprintf(buffer, "LR A,(IS++)");
+ break;
+ case 0x4e: /* 0100 1110 */
+ sprintf(buffer, "LR A,(IS--)");
+ break;
+ case 0x4f: /* 0100 1111 */
+ sprintf(buffer, "??? $%02X",op);
+ break;
+
+ case 0x50: /* 0101 0000 */
+ case 0x51: /* 0101 0001 */
+ case 0x52: /* 0101 0010 */
+ case 0x53: /* 0101 0011 */
+ case 0x54: /* 0101 0100 */
+ case 0x55: /* 0101 0101 */
+ case 0x56: /* 0101 0110 */
+ case 0x57: /* 0101 0111 */
+ case 0x58: /* 0101 1000 */
+ case 0x59: /* 0101 1001 */
+ case 0x5a: /* 0101 1010 */
+ case 0x5b: /* 0101 1011 */
+ sprintf(buffer, "LR %s,A",rname[op & 15]);
+ break;
+ case 0x5c: /* 0101 1100 */
+ sprintf(buffer, "LR (IS),A");
+ break;
+ case 0x5d: /* 0101 1101 */
+ sprintf(buffer, "LR (IS++),A");
+ break;
+ case 0x5e: /* 0101 1110 */
+ sprintf(buffer, "LR (IS--),A");
+ break;
+ case 0x5f: /* 0101 1111 */
+ sprintf(buffer, "??? $%02X",op);
+ break;
+
+ case 0x60: /* 0110 0000 */
+ case 0x61: /* 0110 0001 */
+ case 0x62: /* 0110 0010 */
+ case 0x63: /* 0110 0011 */
+ case 0x64: /* 0110 0100 */
+ case 0x65: /* 0110 0101 */
+ case 0x66: /* 0110 0110 */
+ case 0x67: /* 0110 0111 */
+ sprintf(buffer, "LISU $%02X", op & 0x07);
+ break;
+ case 0x68: /* 0110 1000 */
+ case 0x69: /* 0110 1001 */
+ case 0x6a: /* 0110 1010 */
+ case 0x6b: /* 0110 1011 */
+ case 0x6c: /* 0110 1100 */
+ case 0x6d: /* 0110 1101 */
+ case 0x6e: /* 0110 1110 */
+ case 0x6f: /* 0110 1111 */
+ sprintf(buffer, "LISL $%02X", op & 0x07);
+ break;
+
+ case 0x70: /* 0111 0000 */
+ case 0x71: /* 0111 0001 */
+ case 0x72: /* 0111 0010 */
+ case 0x73: /* 0111 0011 */
+ case 0x74: /* 0111 0100 */
+ case 0x75: /* 0111 0101 */
+ case 0x76: /* 0111 0110 */
+ case 0x77: /* 0111 0111 */
+ case 0x78: /* 0111 1000 */
+ case 0x79: /* 0111 1001 */
+ case 0x7a: /* 0111 1010 */
+ case 0x7b: /* 0111 1011 */
+ case 0x7c: /* 0111 1100 */
+ case 0x7d: /* 0111 1101 */
+ case 0x7e: /* 0111 1110 */
+ case 0x7f: /* 0111 1111 */
+ sprintf(buffer, "LIS $%02X", op & 0x0f);
+ break;
+
+ case 0x81: /* 1000 0001 */
+ case 0x85: /* 1000 0101 */
+ sprintf(buffer, "BP $%04X", pc + (INT8)oprom[size++] + 1);
+ break;
+
+ case 0x82: /* 1000 0010 */
+ sprintf(buffer, "BC $%04X", pc + (INT8)oprom[size++] + 1);
+ break;
+
+ case 0x84: /* 1000 0100 */
+ sprintf(buffer, "BZ $%04X", pc + (INT8)oprom[size++] + 1);
+ break;
+
+ case 0x80: /* 1000 0000 */
+ case 0x83: /* 1000 0011 */
+ case 0x86: /* 1000 0110 */
+ case 0x87: /* 1000 0111 */
+ sprintf(buffer, "BT $%02X,$%04X", op & 0x07, pc + (INT8)oprom[size++] + 1);
+ break;
+
+ case 0x88: /* 1000 1000 */
+ sprintf(buffer, "AM");
+ break;
+
+ case 0x89: /* 1000 1001 */
+ sprintf(buffer, "AMD");
+ break;
+
+ case 0x8a: /* 1000 1010 */
+ sprintf(buffer, "NM");
+ break;
+
+ case 0x8b: /* 1000 1011 */
+ sprintf(buffer, "OM");
+ break;
+
+ case 0x8c: /* 1000 1100 */
+ sprintf(buffer, "XM");
+ break;
+
+ case 0x8d: /* 1000 1101 */
+ sprintf(buffer, "CM");
+ break;
+
+ case 0x8e: /* 1000 1110 */
+ sprintf(buffer, "ADC");
+ break;
+
+ case 0x8f: /* 1000 1111 */
+ sprintf(buffer, "BR7 $%04X", pc + (INT8)oprom[size++] + 1);
+ break;
+
+ case 0x90: /* 1001 0000 */
+ sprintf(buffer, "BR $%04X", pc + (INT8)oprom[size++] + 1);
+ break;
+
+ case 0x91: /* 1001 0001 */
+ case 0x95: /* 1001 0101 */
+ sprintf(buffer, "BM $%04X", pc + (INT8)oprom[size++] + 1);
+ break;
+
+ case 0x92: /* 1001 0010 */
+ sprintf(buffer, "BNC $%04X", pc + (INT8)oprom[size++] + 1);
+ break;
+
+ case 0x94: /* 1001 0100 */
+ sprintf(buffer, "BNZ $%04X", pc + (INT8)oprom[size++] + 1);
+ break;
+
+ case 0x98: /* 1001 1000 */
+ sprintf(buffer, "BNO $%04X", pc + (INT8)oprom[size++] + 1);
+ break;
+
+ case 0x93: /* 1001 0011 */
+ case 0x96: /* 1001 0110 */
+ case 0x97: /* 1001 0111 */
+ case 0x99: /* 1001 1001 */
+ case 0x9a: /* 1001 1010 */
+ case 0x9b: /* 1001 1011 */
+ case 0x9c: /* 1001 1100 */
+ case 0x9d: /* 1001 1101 */
+ case 0x9e: /* 1001 1110 */
+ case 0x9f: /* 1001 1111 */
+ sprintf(buffer, "BF $%02X,$%04X", op & 0x0f, pc + (INT8)oprom[size++] + 1);
+ break;
+
+ case 0xa0: /* 1010 0000 */
+ case 0xa1: /* 1010 0001 */
+ sprintf(buffer, "INS $%02X", (unsigned) (INT8) (op & 0x0F));
+ break;
+
+ case 0xa2: /* 1010 0010 */
+ case 0xa3: /* 1010 0011 */
+ sprintf(buffer, "??? $%02X\n", op);
+ break;
+
+ case 0xa4: /* 1010 0100 */
+ case 0xa5: /* 1010 0101 */
+ case 0xa6: /* 1010 0110 */
+ case 0xa7: /* 1010 0111 */
+ case 0xa8: /* 1010 1000 */
+ case 0xa9: /* 1010 1001 */
+ case 0xaa: /* 1010 1010 */
+ case 0xab: /* 1010 1011 */
+ case 0xac: /* 1010 1100 */
+ case 0xad: /* 1010 1101 */
+ case 0xae: /* 1010 1110 */
+ case 0xaf: /* 1010 1111 */
+ sprintf(buffer, "INS $%02X", (INT8) op & 0x0f);
+ break;
+
+ case 0xb0: /* 1011 0000 */
+ case 0xb1: /* 1011 0001 */
+ sprintf(buffer, "OUTS $%02X", (INT8) op & 0x0f);
+ break;
+
+ case 0xb2: /* 1011 0010 */
+ case 0xb3: /* 1011 0011 */
+ sprintf(buffer, "??? $%02X\n", op);
+ break;
+
+ case 0xb4: /* 1011 0100 */
+ case 0xb5: /* 1011 0101 */
+ case 0xb6: /* 1011 0110 */
+ case 0xb7: /* 1011 0111 */
+ case 0xb8: /* 1011 1000 */
+ case 0xb9: /* 1011 1001 */
+ case 0xba: /* 1011 1010 */
+ case 0xbb: /* 1011 1011 */
+ case 0xbc: /* 1011 1100 */
+ case 0xbd: /* 1011 1101 */
+ case 0xbe: /* 1011 1110 */
+ case 0xbf: /* 1011 1111 */
+ sprintf(buffer, "OUTS $%02X", (unsigned) (INT8) op & 0x0f);
+ break;
+
+ case 0xc0: /* 1100 0000 */
+ case 0xc1: /* 1100 0001 */
+ case 0xc2: /* 1100 0010 */
+ case 0xc3: /* 1100 0011 */
+ case 0xc4: /* 1100 0100 */
+ case 0xc5: /* 1100 0101 */
+ case 0xc6: /* 1100 0110 */
+ case 0xc7: /* 1100 0111 */
+ case 0xc8: /* 1100 1000 */
+ case 0xc9: /* 1100 1001 */
+ case 0xca: /* 1100 1010 */
+ case 0xcb: /* 1100 1011 */
+ sprintf(buffer, "AS %s", rname[op & 15]);
+ break;
+ case 0xcc: /* 1100 1100 */
+ sprintf(buffer, "AS (IS)");
+ break;
+ case 0xcd: /* 1100 1101 */
+ sprintf(buffer, "AS (IS++)");
+ break;
+ case 0xce: /* 1100 1110 */
+ sprintf(buffer, "AS (IS--)");
+ break;
+ case 0xcf: /* 1100 1111 */
+ sprintf(buffer, "??? $%02X\n", op);
+ break;
+
+ case 0xd0: /* 1101 0000 */
+ case 0xd1: /* 1101 0001 */
+ case 0xd2: /* 1101 0010 */
+ case 0xd3: /* 1101 0011 */
+ case 0xd4: /* 1101 0100 */
+ case 0xd5: /* 1101 0101 */
+ case 0xd6: /* 1101 0110 */
+ case 0xd7: /* 1101 0111 */
+ case 0xd8: /* 1101 1000 */
+ case 0xd9: /* 1101 1001 */
+ case 0xda: /* 1101 1010 */
+ case 0xdb: /* 1101 1011 */
+ sprintf(buffer, "ASD %s", rname[op & 15]);
+ break;
+ case 0xdc: /* 1101 1100 */
+ sprintf(buffer, "ASD (IS)");
+ break;
+ case 0xdd: /* 1101 1101 */
+ sprintf(buffer, "ASD (IS++)");
+ break;
+ case 0xde: /* 1101 1110 */
+ sprintf(buffer, "ASD (IS--)");
+ break;
+ case 0xdf: /* 1101 1111 */
+ sprintf(buffer, "??? $%02X\n", op);
+ break;
+
+ case 0xe0: /* 1110 0000 */
+ case 0xe1: /* 1110 0001 */
+ case 0xe2: /* 1110 0010 */
+ case 0xe3: /* 1110 0011 */
+ case 0xe4: /* 1110 0100 */
+ case 0xe5: /* 1110 0101 */
+ case 0xe6: /* 1110 0110 */
+ case 0xe7: /* 1110 0111 */
+ case 0xe8: /* 1110 1000 */
+ case 0xe9: /* 1110 1001 */
+ case 0xea: /* 1110 1010 */
+ case 0xeb: /* 1110 1011 */
+ sprintf(buffer, "XS %s", rname[op & 15]);
+ break;
+ case 0xec: /* 1110 1100 */
+ sprintf(buffer, "XS (IS)");
+ break;
+ case 0xed: /* 1110 1101 */
+ sprintf(buffer, "XS (IS++)");
+ break;
+ case 0xee: /* 1110 1110 */
+ sprintf(buffer, "XS (IS--)");
+ break;
+ case 0xef: /* 1110 1111 */
+ sprintf(buffer, "??? $%02X\n", op);
+ break;
+
+
+ case 0xf0: /* 1111 0000 */
+ case 0xf1: /* 1111 0001 */
+ case 0xf2: /* 1111 0010 */
+ case 0xf3: /* 1111 0011 */
+ case 0xf4: /* 1111 0100 */
+ case 0xf5: /* 1111 0101 */
+ case 0xf6: /* 1111 0110 */
+ case 0xf7: /* 1111 0111 */
+ case 0xf8: /* 1111 1000 */
+ case 0xf9: /* 1111 1001 */
+ case 0xfa: /* 1111 1010 */
+ case 0xfb: /* 1111 1011 */
+ sprintf(buffer, "NS %s", rname[op & 15]);
+ break;
+ case 0xfc: /* 1111 1100 */
+ sprintf(buffer, "NS (IS)");
+ break;
+ case 0xfd: /* 1111 1101 */
+ sprintf(buffer, "NS (IS++)");
+ break;
+ case 0xfe: /* 1111 1110 */
+ sprintf(buffer, "NS (IS--)");
+ break;
+ case 0xff: /* 1111 1111 */
+ sprintf(buffer, "??? $%02X\n", op);
+ break;
+ }
+
+ return size;
+}
+
diff --git a/trunk/src/emu/cpu/g65816/g65816.c b/trunk/src/emu/cpu/g65816/g65816.c
new file mode 100644
index 00000000000..bbffa15de2a
--- /dev/null
+++ b/trunk/src/emu/cpu/g65816/g65816.c
@@ -0,0 +1,557 @@
+/* ======================================================================== */
+/* =============================== COPYRIGHT ============================== */
+/* ======================================================================== */
+/*
+
+G65C816 CPU Emulator V1.00
+
+Copyright Karl Stenerud
+All rights reserved.
+
+Permission is granted to use this source code for non-commercial purposes.
+To use this code for commercial purposes, you must get permission from the
+author (Karl Stenerud) at karl@higashiyama-unet.ocn.ne.jp.
+
+
+*/
+/* ======================================================================== */
+/* ================================= NOTES ================================ */
+/* ======================================================================== */
+/*
+
+Changes:
+ 1.01 (2010-04-04):
+ Angelo Salese
+ - Added boundary checks for MVP and MVN in M mode.
+
+ 1.00 (2008-11-27):
+ R. Belmont
+ - Reworked for modern MAME
+
+ 0.94 (2007-06-14):
+ Zsolt Vasvari
+ - Removed unnecessary checks from MVP and MVN
+
+ 0.93 (2003-07-05):
+ Angelo Salese
+ - Fixed the BCD conversion when using the Decimal Flag in ADC and SBC.
+ - Removed the two conversion tables for ADC and SBC as they aren't
+ needed anymore.
+
+ 0.92 (2000-05-28):
+ Lee Hammerton <lee-hammerton@hammerhead.ltd.uk>
+ - Fixed debugger bug that caused D to be misrepresented.
+ - Fixed MVN and MVP (they were reversed)
+
+ 0.91 (2000-05-22):
+ Lee Hammerton <lee-hammerton@hammerhead.ltd.uk>
+ - Fixed reset vector fetch to be little endian
+ - Fixed disassembler call bug
+ - Fixed C flag in SBC (should be inverted before operation)
+ - Fixed JSR to stack PC-1 and RTS to pull PC and add 1
+
+ Karl Stenerud <karl@higashiyama-unet.ocn.ne.jp>
+ - Added correct timing for absolute indexed operations
+ - SBC: fixed corruption of interim values
+
+ 0.90 (2000-05-17):
+ Karl Stenerud <karl@higashiyama-unet.ocn.ne.jp>
+ - first public release
+
+
+Note on timings:
+ - For instructions that write to memory (ASL, ASR, LSL, ROL, ROR, DEC,
+ INC, STA, STZ), the absolute indexed addressing mode takes 1 extra
+ cycle to complete.
+ - The spec says fc (JMP axi) is 6 cyles, but elsewhere says 8 cycles
+ (which is what it should be)
+
+
+TODO general:
+ - WAI will not stop if RDY is held high.
+
+ - RDY internally held low when WAI executed and returned to hi when RES,
+ ABORT, NMI, or IRQ asserted.
+
+ - ABORT will terminate WAI instruction but wil not restart the processor
+
+ - If interrupt occurs after ABORT of WAI, processor returns to WAI
+ instruction.
+
+ - Add one cycle when indexing across page boundary and E=1 except for STA
+ and STZ instructions.
+
+ - Add 1 cycle if branch is taken. In Emulation (E= 1 ) mode only --add 1
+ cycle if the branch is taken and crosses a page boundary.
+
+ - Add 1 cycle in Emulation mode (E=1) for (dir),y; abs,x; and abs,y
+ addressing modes.
+
+*/
+/* ======================================================================== */
+/* ================================= DATA ================================= */
+/* ======================================================================== */
+
+#include "emu.h"
+#include "g65816.h"
+
+INLINE g65816i_cpu_struct *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == G65816 || device->type() == _5A22);
+ return (g65816i_cpu_struct *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+/* Temporary Variables */
+
+static CPU_READOP( g65816 )
+{
+ g65816i_cpu_struct *cpustate = get_safe_token(device);
+
+ *value = g65816_read_8_immediate(offset);
+
+ return 1;
+}
+
+extern void (*const g65816i_opcodes_M0X0[])(g65816i_cpu_struct *cpustate);
+extern uint g65816i_get_reg_M0X0(g65816i_cpu_struct *cpustate, int regnum);
+extern void g65816i_set_reg_M0X0(g65816i_cpu_struct *cpustate, int regnum, uint val);
+extern void g65816i_set_line_M0X0(g65816i_cpu_struct *cpustate, int line, int state);
+extern int g65816i_execute_M0X0(g65816i_cpu_struct *cpustate, int cycles);
+
+extern void (*const g65816i_opcodes_M0X1[])(g65816i_cpu_struct *cpustate);
+extern uint g65816i_get_reg_M0X1(g65816i_cpu_struct *cpustate, int regnum);
+extern void g65816i_set_reg_M0X1(g65816i_cpu_struct *cpustate, int regnum, uint val);
+extern void g65816i_set_line_M0X1(g65816i_cpu_struct *cpustate, int line, int state);
+extern int g65816i_execute_M0X1(g65816i_cpu_struct *cpustate, int cycles);
+
+extern void (*const g65816i_opcodes_M1X0[])(g65816i_cpu_struct *cpustate);
+extern uint g65816i_get_reg_M1X0(g65816i_cpu_struct *cpustate, int regnum);
+extern void g65816i_set_reg_M1X0(g65816i_cpu_struct *cpustate, int regnum, uint val);
+extern void g65816i_set_line_M1X0(g65816i_cpu_struct *cpustate, int line, int state);
+extern int g65816i_execute_M1X0(g65816i_cpu_struct *cpustate, int cycles);
+
+extern void (*const g65816i_opcodes_M1X1[])(g65816i_cpu_struct *cpustate);
+extern uint g65816i_get_reg_M1X1(g65816i_cpu_struct *cpustate, int regnum);
+extern void g65816i_set_reg_M1X1(g65816i_cpu_struct *cpustate, int regnum, uint val);
+extern void g65816i_set_line_M1X1(g65816i_cpu_struct *cpustate, int line, int state);
+extern int g65816i_execute_M1X1(g65816i_cpu_struct *cpustate, int cycles);
+
+extern void (*const g65816i_opcodes_E[])(g65816i_cpu_struct *cpustate);
+extern uint g65816i_get_reg_E(g65816i_cpu_struct *cpustate, int regnum);
+extern void g65816i_set_reg_E(g65816i_cpu_struct *cpustate, int regnum, uint val);
+extern void g65816i_set_line_E(g65816i_cpu_struct *cpustate, int line, int state);
+extern int g65816i_execute_E(g65816i_cpu_struct *cpustate, int cycles);
+
+void (*const *const g65816i_opcodes[5])(g65816i_cpu_struct *cpustate) =
+{
+ g65816i_opcodes_M0X0,
+ g65816i_opcodes_M0X1,
+ g65816i_opcodes_M1X0,
+ g65816i_opcodes_M1X1,
+ g65816i_opcodes_E
+};
+
+uint (*const g65816i_get_reg[5])(g65816i_cpu_struct *cpustate, int regnum) =
+{
+ g65816i_get_reg_M0X0,
+ g65816i_get_reg_M0X1,
+ g65816i_get_reg_M1X0,
+ g65816i_get_reg_M1X1,
+ g65816i_get_reg_E
+};
+
+void (*const g65816i_set_reg[5])(g65816i_cpu_struct *cpustate, int regnum, uint val) =
+{
+ g65816i_set_reg_M0X0,
+ g65816i_set_reg_M0X1,
+ g65816i_set_reg_M1X0,
+ g65816i_set_reg_M1X1,
+ g65816i_set_reg_E
+};
+
+void (*const g65816i_set_line[5])(g65816i_cpu_struct *cpustate, int line, int state) =
+{
+ g65816i_set_line_M0X0,
+ g65816i_set_line_M0X1,
+ g65816i_set_line_M1X0,
+ g65816i_set_line_M1X1,
+ g65816i_set_line_E
+};
+
+int (*const g65816i_execute[5])(g65816i_cpu_struct *cpustate, int cycles) =
+{
+ g65816i_execute_M0X0,
+ g65816i_execute_M0X1,
+ g65816i_execute_M1X0,
+ g65816i_execute_M1X1,
+ g65816i_execute_E
+};
+
+/* ======================================================================== */
+/* ================================= API ================================== */
+/* ======================================================================== */
+
+
+static CPU_RESET( g65816 )
+{
+ g65816i_cpu_struct *cpustate = get_safe_token(device);
+
+ /* Start the CPU */
+ CPU_STOPPED = 0;
+
+ /* Put into emulation mode */
+ REGISTER_D = 0;
+ REGISTER_PB = 0;
+ REGISTER_DB = 0;
+ REGISTER_S = (REGISTER_S & 0xff) | 0x100;
+ REGISTER_X &= 0xff;
+ REGISTER_Y &= 0xff;
+ if(!FLAG_M)
+ {
+ REGISTER_B = REGISTER_A & 0xff00;
+ REGISTER_A &= 0xff;
+ }
+ FLAG_E = EFLAG_SET;
+ FLAG_M = MFLAG_SET;
+ FLAG_X = XFLAG_SET;
+
+ /* Clear D and set I */
+ FLAG_D = DFLAG_CLEAR;
+ FLAG_I = IFLAG_SET;
+
+ /* Clear all pending interrupts (should we really do this?) */
+ LINE_IRQ = 0;
+ LINE_NMI = 0;
+ IRQ_DELAY = 0;
+
+ /* Set the function tables to emulation mode */
+ g65816i_set_execution_mode(cpustate, EXECUTION_MODE_E);
+
+ /* 6502 expects these, but its not in the 65816 spec */
+ FLAG_Z = ZFLAG_CLEAR;
+ REGISTER_S = 0x1ff;
+
+ /* Fetch the reset vector */
+ REGISTER_PC = g65816_read_8(VECTOR_RESET) | (g65816_read_8(VECTOR_RESET+1)<<8);
+ g65816i_jumping(REGISTER_PB | REGISTER_PC);
+}
+
+/* Exit and clean up */
+static CPU_EXIT( g65816 )
+{
+ /* nothing to do yet */
+}
+
+/* Execute some instructions */
+static CPU_EXECUTE( g65816 )
+{
+ g65816i_cpu_struct *cpustate = get_safe_token(device);
+
+ int clocks = cpustate->ICount;
+ cpustate->ICount = clocks - FTABLE_EXECUTE(cpustate, cpustate->ICount);
+}
+
+
+/* Get the current Program Counter */
+static unsigned g65816_get_pc(g65816i_cpu_struct *cpustate)
+{
+ return REGISTER_PB | REGISTER_PC;
+}
+
+/* Set the Program Counter */
+static void g65816_set_pc(g65816i_cpu_struct *cpustate, unsigned val)
+{
+ REGISTER_PC = MAKE_UINT_16(val);
+ REGISTER_PB = (val >> 16) & 0xFF;
+ g65816_jumping(REGISTER_PB | REGISTER_PC);
+}
+
+/* Get the current Stack Pointer */
+static unsigned g65816_get_sp(g65816i_cpu_struct *cpustate)
+{
+ return REGISTER_S;
+}
+
+/* Set the Stack Pointer */
+static void g65816_set_sp(g65816i_cpu_struct *cpustate, unsigned val)
+{
+ REGISTER_S = FLAG_E ? MAKE_UINT_8(val) | 0x100 : MAKE_UINT_16(val);
+}
+
+/* Get a register */
+static unsigned g65816_get_reg(g65816i_cpu_struct *cpustate, int regnum)
+{
+ /* Set the function tables to emulation mode if the FTABLE is NULL */
+ if( FTABLE_GET_REG == NULL )
+ g65816i_set_execution_mode(cpustate, EXECUTION_MODE_E);
+
+ return FTABLE_GET_REG(cpustate, regnum);
+}
+
+/* Set a register */
+static void g65816_set_reg(g65816i_cpu_struct *cpustate, int regnum, unsigned value)
+{
+ FTABLE_SET_REG(cpustate, regnum, value);
+}
+
+/* Set an interrupt line */
+static void g65816_set_irq_line(g65816i_cpu_struct *cpustate, int line, int state)
+{
+ FTABLE_SET_LINE(cpustate, line, state);
+}
+
+/* Set the callback that is called when servicing an interrupt */
+static void g65816_set_irq_callback(g65816i_cpu_struct *cpustate, device_irq_callback callback)
+{
+ INT_ACK = callback;
+}
+
+
+/* Disassemble an instruction */
+#include "g65816ds.h"
+
+static CPU_DISASSEMBLE( g65816 )
+{
+ g65816i_cpu_struct *cpustate = get_safe_token(device);
+
+ return g65816_disassemble(buffer, (pc & 0x00ffff), (pc & 0xff0000) >> 16, oprom, FLAG_M, FLAG_X);
+}
+
+static void g65816_restore_state(g65816i_cpu_struct *cpustate)
+{
+ // restore proper function pointers
+ g65816i_set_execution_mode(cpustate, (FLAG_M>>4) | (FLAG_X>>4));
+
+ // make sure the memory system can keep up
+ g65816i_jumping(REGISTER_PB | REGISTER_PC);
+}
+
+static CPU_INIT( g65816 )
+{
+ g65816i_cpu_struct *cpustate = get_safe_token(device);
+
+ memset(cpustate, 0, sizeof(*cpustate));
+
+ g65816_set_irq_callback(cpustate, irqcallback);
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->cpu_type = CPU_TYPE_G65816;
+
+ device->save_item(NAME(cpustate->a));
+ device->save_item(NAME(cpustate->b));
+ device->save_item(NAME(cpustate->x));
+ device->save_item(NAME(cpustate->y));
+ device->save_item(NAME(cpustate->s));
+ device->save_item(NAME(cpustate->pc));
+ device->save_item(NAME(cpustate->ppc));
+ device->save_item(NAME(cpustate->pb));
+ device->save_item(NAME(cpustate->db));
+ device->save_item(NAME(cpustate->d));
+ device->save_item(NAME(cpustate->flag_e));
+ device->save_item(NAME(cpustate->flag_m));
+ device->save_item(NAME(cpustate->flag_x));
+ device->save_item(NAME(cpustate->flag_n));
+ device->save_item(NAME(cpustate->flag_v));
+ device->save_item(NAME(cpustate->flag_d));
+ device->save_item(NAME(cpustate->flag_i));
+ device->save_item(NAME(cpustate->flag_z));
+ device->save_item(NAME(cpustate->flag_c));
+ device->save_item(NAME(cpustate->line_irq));
+ device->save_item(NAME(cpustate->line_nmi));
+ device->save_item(NAME(cpustate->ir));
+ device->save_item(NAME(cpustate->irq_delay));
+ device->save_item(NAME(cpustate->stopped));
+
+ device->machine().save().register_postload(save_prepost_delegate(FUNC(g65816_restore_state), cpustate));
+}
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( g65816 )
+{
+ g65816i_cpu_struct *cpustate = get_safe_token(device);
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + G65816_LINE_IRQ: g65816_set_irq_line(cpustate, G65816_LINE_IRQ, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + G65816_LINE_NMI: g65816_set_irq_line(cpustate, G65816_LINE_NMI, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + G65816_LINE_ABORT: g65816_set_irq_line(cpustate, G65816_LINE_ABORT, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + G65816_LINE_SO: g65816_set_irq_line(cpustate, G65816_LINE_SO, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + G65816_LINE_RDY: g65816_set_irq_line(cpustate, G65816_LINE_RDY, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + G65816_LINE_RESET: g65816_set_irq_line(cpustate, G65816_LINE_RESET, info->i); break;
+
+ case CPUINFO_INT_PC: g65816_set_pc(cpustate, info->i); break;
+ case CPUINFO_INT_SP: g65816_set_sp(cpustate, info->i); break;
+
+ case CPUINFO_INT_REGISTER + G65816_PC: g65816_set_reg(cpustate, G65816_PC, info->i); break;
+ case CPUINFO_INT_REGISTER + G65816_S: g65816_set_reg(cpustate, G65816_S, info->i); break;
+ case CPUINFO_INT_REGISTER + G65816_P: g65816_set_reg(cpustate, G65816_P, info->i); break;
+ case CPUINFO_INT_REGISTER + G65816_A: g65816_set_reg(cpustate, G65816_A, info->i); break;
+ case CPUINFO_INT_REGISTER + G65816_X: g65816_set_reg(cpustate, G65816_X, info->i); break;
+ case CPUINFO_INT_REGISTER + G65816_Y: g65816_set_reg(cpustate, G65816_Y, info->i); break;
+ case CPUINFO_INT_REGISTER + G65816_PB: g65816_set_reg(cpustate, G65816_PB, info->i); break;
+ case CPUINFO_INT_REGISTER + G65816_DB: g65816_set_reg(cpustate, G65816_DB, info->i); break;
+ case CPUINFO_INT_REGISTER + G65816_D: g65816_set_reg(cpustate, G65816_D, info->i); break;
+ case CPUINFO_INT_REGISTER + G65816_E: g65816_set_reg(cpustate, G65816_E, info->i); break;
+ case CPUINFO_INT_REGISTER + G65816_NMI_STATE: g65816_set_reg(cpustate, G65816_NMI_STATE, info->i); break;
+ case CPUINFO_INT_REGISTER + G65816_IRQ_STATE: g65816_set_reg(cpustate, G65816_IRQ_STATE, info->i); break;
+ }
+}
+
+
+
+void g65816_set_read_vector_callback(device_t *device, read8_space_func read_vector)
+{
+ g65816i_cpu_struct *cpustate = get_safe_token(device);
+ READ_VECTOR = read_vector;
+}
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+CPU_GET_INFO( g65816 )
+{
+ g65816i_cpu_struct *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(g65816i_cpu_struct); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 1; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 20; /* rough guess */ break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 24; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_INPUT_STATE + G65816_LINE_IRQ: info->i = LINE_IRQ; break;
+ case CPUINFO_INT_INPUT_STATE + G65816_LINE_NMI: info->i = LINE_NMI; break;
+ case CPUINFO_INT_INPUT_STATE + G65816_LINE_ABORT: info->i = 0; break;
+ case CPUINFO_INT_INPUT_STATE + G65816_LINE_SO: info->i = 0; break;
+ case CPUINFO_INT_INPUT_STATE + G65816_LINE_RDY: info->i = 0; break;
+ case CPUINFO_INT_INPUT_STATE + G65816_LINE_RESET: info->i = 0; break;
+
+ case CPUINFO_INT_PREVIOUSPC: /* not supported */ break;
+
+ case CPUINFO_INT_PC: info->i = g65816_get_pc(cpustate); break;
+ case CPUINFO_INT_SP: info->i = g65816_get_sp(cpustate); break;
+
+ case CPUINFO_INT_REGISTER + G65816_PC: info->i = g65816_get_pc(cpustate); break;
+ case CPUINFO_INT_REGISTER + G65816_S: info->i = g65816_get_reg(cpustate, G65816_S); break;
+ case CPUINFO_INT_REGISTER + G65816_P: info->i = g65816_get_reg(cpustate, G65816_P); break;
+ case CPUINFO_INT_REGISTER + G65816_A: info->i = g65816_get_reg(cpustate, G65816_A); break;
+ case CPUINFO_INT_REGISTER + G65816_X: info->i = g65816_get_reg(cpustate, G65816_X); break;
+ case CPUINFO_INT_REGISTER + G65816_Y: info->i = g65816_get_reg(cpustate, G65816_Y); break;
+ case CPUINFO_INT_REGISTER + G65816_PB: info->i = g65816_get_reg(cpustate, G65816_PB); break;
+ case CPUINFO_INT_REGISTER + G65816_DB: info->i = g65816_get_reg(cpustate, G65816_DB); break;
+ case CPUINFO_INT_REGISTER + G65816_D: info->i = g65816_get_reg(cpustate, G65816_D); break;
+ case CPUINFO_INT_REGISTER + G65816_E: info->i = g65816_get_reg(cpustate, G65816_E); break;
+ case CPUINFO_INT_REGISTER + G65816_NMI_STATE: info->i = g65816_get_reg(cpustate, G65816_NMI_STATE); break;
+ case CPUINFO_INT_REGISTER + G65816_IRQ_STATE: info->i = g65816_get_reg(cpustate, G65816_IRQ_STATE); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(g65816); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(g65816); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(g65816); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(g65816); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(g65816); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(g65816); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->ICount; break;
+
+ case CPUINFO_FCT_READOP: info->readop = CPU_READOP_NAME(g65816); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "G65C816"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "6500"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Karl Stenerud, all rights reserved."); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c%c%c%c%c%c%c",
+ cpustate->flag_n & NFLAG_SET ? 'N':'.',
+ cpustate->flag_v & VFLAG_SET ? 'V':'.',
+ cpustate->flag_m & MFLAG_SET ? 'M':'.',
+ cpustate->flag_x & XFLAG_SET ? 'X':'.',
+ cpustate->flag_d & DFLAG_SET ? 'D':'.',
+ cpustate->flag_i & IFLAG_SET ? 'I':'.',
+ cpustate->flag_z == 0 ? 'Z':'.',
+ cpustate->flag_c & CFLAG_SET ? 'C':'.');
+ break;
+
+ case CPUINFO_STR_REGISTER + G65816_PC: sprintf(info->s, "PC:%06X", g65816_get_pc(cpustate)); break;
+ case CPUINFO_STR_REGISTER + G65816_PB: sprintf(info->s, "PB:%02X", cpustate->pb>>16); break;
+ case CPUINFO_STR_REGISTER + G65816_DB: sprintf(info->s, "DB:%02X", cpustate->db>>16); break;
+ case CPUINFO_STR_REGISTER + G65816_D: sprintf(info->s, "D:%04X", cpustate->d); break;
+ case CPUINFO_STR_REGISTER + G65816_S: sprintf(info->s, "S:%04X", cpustate->s); break;
+ case CPUINFO_STR_REGISTER + G65816_P: sprintf(info->s, "P:%02X",
+ (cpustate->flag_n&0x80) |
+ ((cpustate->flag_v>>1)&0x40) |
+ cpustate->flag_m |
+ cpustate->flag_x |
+ cpustate->flag_d |
+ cpustate->flag_i |
+ ((!cpustate->flag_z)<<1) |
+ ((cpustate->flag_c>>8)&1)); break;
+ case CPUINFO_STR_REGISTER + G65816_E: sprintf(info->s, "E:%d", cpustate->flag_e); break;
+ case CPUINFO_STR_REGISTER + G65816_A: sprintf(info->s, "A:%04X", cpustate->a | cpustate->b); break;
+ case CPUINFO_STR_REGISTER + G65816_X: sprintf(info->s, "X:%04X", cpustate->x); break;
+ case CPUINFO_STR_REGISTER + G65816_Y: sprintf(info->s, "Y:%04X", cpustate->y); break;
+ case CPUINFO_STR_REGISTER + G65816_NMI_STATE: sprintf(info->s, "NMI:%X", cpustate->line_nmi); break;
+ case CPUINFO_STR_REGISTER + G65816_IRQ_STATE: sprintf(info->s, "IRQ:%X", cpustate->line_irq); break;
+ }
+}
+
+/*
+SNES specific, used to handle master cycles
+*/
+
+static CPU_INIT( 5a22 )
+{
+ g65816i_cpu_struct *cpustate = get_safe_token(device);
+
+ CPU_INIT_CALL(g65816);
+
+ cpustate->cpu_type = CPU_TYPE_5A22;
+}
+
+
+CPU_GET_INFO( _5a22 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(5a22); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "5A22"); break;
+
+ default: CPU_GET_INFO_CALL(g65816); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(G65816, g65816);
+DEFINE_LEGACY_CPU_DEVICE(_5A22, _5a22);
+
+/* ======================================================================== */
+/* ============================== END OF FILE ============================= */
+/* ======================================================================== */
diff --git a/trunk/src/emu/cpu/g65816/g65816.h b/trunk/src/emu/cpu/g65816/g65816.h
new file mode 100644
index 00000000000..941cb4faa8a
--- /dev/null
+++ b/trunk/src/emu/cpu/g65816/g65816.h
@@ -0,0 +1,74 @@
+#pragma once
+
+#ifndef __G65816_H__
+#define __G65816_H__
+
+#include "g65816cm.h"
+
+/* ======================================================================== */
+/* =============================== COPYRIGHT ============================== */
+/* ======================================================================== */
+/*
+
+G65C816 CPU Emulator V0.92
+
+Copyright Karl Stenerud
+All rights reserved.
+
+Permission is granted to use this source code for non-commercial purposes.
+To use this code for commercial purposes, you must get permission from the
+author (Karl Stenerud) at karl@higashiyama-unet.ocn.ne.jp.
+
+
+*/
+/* ======================================================================== */
+/* ============================= Configuration ============================ */
+/* ======================================================================== */
+
+/* GTE Microcircuits G65816 */
+
+/* ======================================================================== */
+/* =============================== DEFINES ================================ */
+/* ======================================================================== */
+
+/* Interrupt lines - used with g65816_set_irq_line() */
+enum
+{
+ G65816_LINE_NONE,
+ G65816_LINE_IRQ,
+ G65816_LINE_NMI,
+ G65816_LINE_ABORT,
+ G65816_LINE_SO,
+ G65816_LINE_RDY,
+ G65816_LINE_RESET
+};
+
+#define G65816_INT_NONE G65816_LINE_NONE
+#define G65816_INT_IRQ G65816_LINE_IRQ
+#define G65816_INT_NMI G65816_LINE_NMI
+
+
+/* Registers - used by g65816_set_reg() and g65816_get_reg() */
+enum
+{
+ G65816_PC=1, G65816_S, G65816_P, G65816_A, G65816_X, G65816_Y,
+ G65816_PB, G65816_DB, G65816_D, G65816_E,
+ G65816_NMI_STATE, G65816_IRQ_STATE
+};
+
+/* Main interface function */
+DECLARE_LEGACY_CPU_DEVICE(G65816, g65816);
+DECLARE_LEGACY_CPU_DEVICE(_5A22, _5a22);
+
+#define CPU_TYPE_G65816 0
+#define CPU_TYPE_5A22 1
+
+
+void g65816_set_read_vector_callback(device_t *device, read8_space_func read_vector);
+
+
+/* ======================================================================== */
+/* ============================== END OF FILE ============================= */
+/* ======================================================================== */
+
+#endif /* __G65816_H__ */
diff --git a/trunk/src/emu/cpu/g65816/g65816cm.h b/trunk/src/emu/cpu/g65816/g65816cm.h
new file mode 100644
index 00000000000..06cbe9f0b83
--- /dev/null
+++ b/trunk/src/emu/cpu/g65816/g65816cm.h
@@ -0,0 +1,318 @@
+#pragma once
+
+#ifndef __G65816CM_H__
+#define __G65816CM_H__
+
+
+#define g65816i_branching(A)
+#define g65816i_jumping(A)
+
+
+#undef G65816_CALL_DEBUGGER
+#define G65816_CALL_DEBUGGER(x) debugger_instruction_hook(cpustate->device, x)
+
+#define g65816_read_8(addr) cpustate->program->read_byte(addr)
+#define g65816_write_8(addr,data) cpustate->program->write_byte(addr,data)
+#define g65816_read_8_immediate(A) cpustate->program->read_byte(A)
+#define g65816_jumping(A)
+#define g65816_branching(A)
+
+
+/* ======================================================================== */
+/* ================================ INCLUDES ============================== */
+/* ======================================================================== */
+
+#include <limits.h>
+
+
+/* ======================================================================== */
+/* ================================ GENERAL =============================== */
+/* ======================================================================== */
+
+/* This should be set to the default size of your processor (min 16 bit) */
+#undef uint
+#define uint unsigned int
+
+#undef uint8
+#define uint8 unsigned char
+
+#undef int8
+
+/* Allow for architectures that don't have 8-bit sizes */
+#if UCHAR_MAX == 0xff
+#define int8 signed char
+#define MAKE_INT_8(A) (int8)((A)&0xff)
+#else
+#define int8 int
+INLINE int MAKE_INT_8(int A) {return (A & 0x80) ? A | ~0xff : A & 0xff;}
+#endif /* UCHAR_MAX == 0xff */
+
+#define MAKE_UINT_8(A) ((A)&0xff)
+#define MAKE_UINT_16(A) ((A)&0xffff)
+#define MAKE_UINT_24(A) ((A)&0xffffff)
+
+/* Bits */
+#define BIT_0 0x01
+#define BIT_1 0x02
+#define BIT_2 0x04
+#define BIT_3 0x08
+#define BIT_4 0x10
+#define BIT_5 0x20
+#define BIT_6 0x40
+#define BIT_7 0x80
+
+
+/* ======================================================================== */
+/* ================================== CPU ================================= */
+/* ======================================================================== */
+
+/* CPU Structure */
+typedef struct _g65816i_cpu_struct g65816i_cpu_struct;
+struct _g65816i_cpu_struct
+{
+ uint a; /* Accumulator */
+ uint b; /* holds high byte of accumulator */
+ uint x; /* Index Register X */
+ uint y; /* Index Register Y */
+ uint s; /* Stack Pointer */
+ uint pc; /* Program Counter */
+ uint ppc; /* Previous Program Counter */
+ uint pb; /* Program Bank (shifted left 16) */
+ uint db; /* Data Bank (shifted left 16) */
+ uint d; /* Direct Register */
+ uint flag_e; /* Emulation Mode Flag */
+ uint flag_m; /* Memory/Accumulator Select Flag */
+ uint flag_x; /* Index Select Flag */
+ uint flag_n; /* Negative Flag */
+ uint flag_v; /* Overflow Flag */
+ uint flag_d; /* Decimal Mode Flag */
+ uint flag_i; /* Interrupt Mask Flag */
+ uint flag_z; /* Zero Flag (inverted) */
+ uint flag_c; /* Carry Flag */
+ uint line_irq; /* Status of the IRQ line */
+ uint line_nmi; /* Status of the NMI line */
+ uint ir; /* Instruction Register */
+ uint irq_delay; /* delay 1 instruction before checking irq */
+ device_irq_callback int_ack; /* Interrupt Acknowledge */
+ legacy_cpu_device *device;
+ address_space *program;
+ read8_space_func read_vector; /* Read vector override */
+ uint stopped; /* Sets how the CPU is stopped */
+ void (*const *opcodes)(g65816i_cpu_struct *cpustate);
+ uint (*get_reg)(g65816i_cpu_struct *cpustate, int regnum);
+ void (*set_reg)(g65816i_cpu_struct *cpustate, int regnum, uint val);
+ void (*set_line)(g65816i_cpu_struct *cpustate, int line, int state);
+ int (*execute)(g65816i_cpu_struct *cpustate, int cycles);
+ uint source;
+ uint destination;
+ int ICount;
+ int cpu_type;
+};
+
+extern void (*const *const g65816i_opcodes[])(g65816i_cpu_struct *cpustate);
+extern uint (*const g65816i_get_reg[])(g65816i_cpu_struct *cpustate, int regnum);
+extern void (*const g65816i_set_reg[])(g65816i_cpu_struct *cpustate, int regnum, uint val);
+extern void (*const g65816i_set_line[])(g65816i_cpu_struct *cpustate, int line, int state);
+extern int (*const g65816i_execute[])(g65816i_cpu_struct *cpustate, int cycles);
+
+#define REGISTER_A cpustate->a /* Accumulator */
+#define REGISTER_B cpustate->b /* Accumulator hi byte */
+#define REGISTER_X cpustate->x /* Index X Register */
+#define REGISTER_Y cpustate->y /* Index Y Register */
+#define REGISTER_S cpustate->s /* Stack Pointer */
+#define REGISTER_PC cpustate->pc /* Program Counter */
+#define REGISTER_PPC cpustate->ppc /* Previous Program Counter */
+#define REGISTER_PB cpustate->pb /* Program Bank */
+#define REGISTER_DB cpustate->db /* Data Bank */
+#define REGISTER_D cpustate->d /* Direct Register */
+#define FLAG_E cpustate->flag_e /* Emulation Mode Flag */
+#define FLAG_M cpustate->flag_m /* Memory/Accumulator Select Flag */
+#define FLAG_X cpustate->flag_x /* Index Select Flag */
+#define FLAG_N cpustate->flag_n /* Negative Flag */
+#define FLAG_V cpustate->flag_v /* Overflow Flag */
+#define FLAG_D cpustate->flag_d /* Decimal Mode Flag */
+#define FLAG_I cpustate->flag_i /* Interrupt Mask Flag */
+#define FLAG_Z cpustate->flag_z /* Zero Flag (inverted) */
+#define FLAG_C cpustate->flag_c /* Carry Flag */
+#define LINE_IRQ cpustate->line_irq /* Status of the IRQ line */
+#define LINE_NMI cpustate->line_nmi /* Status of the NMI line */
+#define REGISTER_IR cpustate->ir /* Instruction Register */
+#define INT_ACK cpustate->int_ack /* Interrupt Acknowledge function pointer */
+#define READ_VECTOR cpustate->read_vector /* Vector reading override */
+#define CLOCKS cpustate->ICount /* Clock cycles remaining */
+#define IRQ_DELAY cpustate->irq_delay /* Delay 1 instruction before checking IRQ */
+#define CPU_STOPPED cpustate->stopped /* Stopped status of the CPU */
+
+#define FTABLE_OPCODES cpustate->opcodes
+#define FTABLE_GET_REG cpustate->get_reg
+#define FTABLE_SET_REG cpustate->set_reg
+#define FTABLE_SET_LINE cpustate->set_line
+#define FTABLE_EXECUTE cpustate->execute
+
+#define SRC cpustate->source /* Source Operand */
+#define DST cpustate->destination /* Destination Operand */
+
+#define STOP_LEVEL_WAI 1
+#define STOP_LEVEL_STOP 2
+
+#define EXECUTION_MODE_M0X0 0
+#define EXECUTION_MODE_M0X1 1
+#define EXECUTION_MODE_M1X0 2
+#define EXECUTION_MODE_M1X1 3
+#define EXECUTION_MODE_E 4
+
+INLINE void g65816i_set_execution_mode(g65816i_cpu_struct *cpustate, uint mode)
+{
+ FTABLE_OPCODES = g65816i_opcodes[mode];
+ FTABLE_GET_REG = g65816i_get_reg[mode];
+ FTABLE_SET_REG = g65816i_set_reg[mode];
+ FTABLE_SET_LINE = g65816i_set_line[mode];
+ FTABLE_EXECUTE = g65816i_execute[mode];
+}
+
+
+
+#define VECTOR_RESET 0xfffc /* Reset */
+#define VECTOR_IRQ_E 0xfffe /* Interrupt Request */
+#define VECTOR_NMI_E 0xfffa /* Non-Maskable Interrupt */
+#define VECTOR_ABORT_E 0xfff8 /* ABORT asserted */
+#define VECTOR_BRK_E 0xfffe /* Break Instruction */
+#define VECTOR_COP_E 0xfff4 /* Coprocessor instruction */
+
+#define VECTOR_IRQ_N 0xffee /* Interrupt Request */
+#define VECTOR_NMI_N 0xffea /* Non-Maskable Interrupt */
+#define VECTOR_ABORT_N 0xffe8 /* ABORT asserted */
+#define VECTOR_BRK_N 0xffe6 /* Break Instruction */
+#define VECTOR_COP_N 0xffe4 /* Coprocessor instruction */
+
+
+/* ======================================================================== */
+/* ================================= CLOCK ================================ */
+/* ======================================================================== */
+
+#define CLK_OP 1
+#define CLK_R8 1
+#define CLK_R16 2
+#define CLK_R24 3
+#define CLK_W8 1
+#define CLK_W16 2
+#define CLK_W24 3
+#define CLK_RMW8 3
+#define CLK_RMW16 5
+
+#define CLK_IMPLIED 1
+#define CLK_IMPLIED 1
+#define CLK_RELATIVE_8 1
+#define CLK_RELATIVE_16 2
+#define CLK_IMM 0
+#define CLK_AI 4
+#define CLK_AXI 4
+#define CLK_A 2
+#define CLK_AL 3
+#define CLK_ALX 3
+#define CLK_AX 2
+#define CLK_AY 2
+#define CLK_D 1
+#define CLK_DI 3
+#define CLK_DIY 3
+#define CLK_DLI 4
+#define CLK_DLIY 4
+#define CLK_DX 2
+#define CLK_DXI 4
+#define CLK_DY 2
+#define CLK_S 2
+#define CLK_SIY 5
+
+/* AX and AY addressing modes take 1 extra cycle when writing */
+#define CLK_W_IMM 0
+#define CLK_W_AI 4
+#define CLK_W_AXI 4
+#define CLK_W_A 2
+#define CLK_W_AL 3
+#define CLK_W_ALX 3
+#define CLK_W_AX 3
+#define CLK_W_AY 3
+#define CLK_W_D 1
+#define CLK_W_DI 3
+#define CLK_W_DIY 3
+#define CLK_W_DLI 4
+#define CLK_W_DLIY 4
+#define CLK_W_DX 2
+#define CLK_W_DXI 4
+#define CLK_W_DY 2
+#define CLK_W_S 2
+#define CLK_W_SIY 5
+
+#define CLK(A) CLOCKS -= (cpustate->cpu_type == CPU_TYPE_G65816 ? A : A*6)
+#define USE_ALL_CLKS() CLOCKS = 0
+
+
+/* ======================================================================== */
+/* ============================ STATUS REGISTER =========================== */
+/* ======================================================================== */
+
+/* Flag positions in Processor Status Register */
+/* common */
+#define FLAGPOS_N BIT_7 /* Negative */
+#define FLAGPOS_V BIT_6 /* Overflow */
+#define FLAGPOS_D BIT_3 /* Decimal Mode */
+#define FLAGPOS_I BIT_2 /* Interrupt Mask */
+#define FLAGPOS_Z BIT_1 /* Zero */
+#define FLAGPOS_C BIT_0 /* Carry */
+/* emulation */
+#define FLAGPOS_R BIT_5 /* Reserved */
+#define FLAGPOS_B BIT_4 /* BRK Instruction */
+/* native */
+#define FLAGPOS_M BIT_5 /* Mem/Reg Select */
+#define FLAGPOS_X BIT_4 /* Index Select */
+
+#define EFLAG_SET 1
+#define EFLAG_CLEAR 0
+#define MFLAG_SET FLAGPOS_M
+#define MFLAG_CLEAR 0
+#define XFLAG_SET FLAGPOS_X
+#define XFLAG_CLEAR 0
+#define NFLAG_SET 0x80
+#define NFLAG_CLEAR 0
+#define VFLAG_SET 0x80
+#define VFLAG_CLEAR 0
+#define DFLAG_SET FLAGPOS_D
+#define DFLAG_CLEAR 0
+#define IFLAG_SET FLAGPOS_I
+#define IFLAG_CLEAR 0
+#define BFLAG_SET FLAGPOS_B
+#define BFLAG_CLEAR 0
+#define ZFLAG_SET 0
+#define ZFLAG_CLEAR 1
+#define CFLAG_SET 0x100
+#define CFLAG_CLEAR 0
+
+/* Codition code tests */
+#define COND_CC() (!(FLAG_C&0x100)) /* Carry Clear */
+#define COND_CS() (FLAG_C&0x100) /* Carry Set */
+#define COND_EQ() (!FLAG_Z) /* Equal */
+#define COND_NE() FLAG_Z /* Not Equal */
+#define COND_MI() (FLAG_N&0x80) /* Minus */
+#define COND_PL() (!(FLAG_N&0x80)) /* Plus */
+#define COND_VC() (!(FLAG_V&0x80)) /* Overflow Clear */
+#define COND_VS() (FLAG_V&0x80) /* Overflow Set */
+
+/* Set Overflow flag in math operations */
+#define VFLAG_ADD_8(S, D, R) ((S^R) & (D^R))
+#define VFLAG_ADD_16(S, D, R) (((S^R) & (D^R))>>8)
+#define VFLAG_SUB_8(S, D, R) ((S^D) & (R^D))
+#define VFLAG_SUB_16(S, D, R) (((S^D) & (R^D))>>8)
+
+#define CFLAG_8(A) (A)
+#define CFLAG_16(A) ((A)>>8)
+#define NFLAG_8(A) (A)
+#define NFLAG_16(A) ((A)>>8)
+
+#define CFLAG_AS_1() ((FLAG_C>>8)&1)
+
+
+
+/* ======================================================================== */
+/* ================================== CPU ================================= */
+/* ======================================================================== */
+#endif /* __G65816CM_H__ */
diff --git a/trunk/src/emu/cpu/g65816/g65816ds.c b/trunk/src/emu/cpu/g65816/g65816ds.c
new file mode 100644
index 00000000000..545132b46e2
--- /dev/null
+++ b/trunk/src/emu/cpu/g65816/g65816ds.c
@@ -0,0 +1,352 @@
+/* ======================================================================== */
+/* =============================== COPYRIGHT ============================== */
+/* ======================================================================== */
+/*
+
+G65C816 CPU Emulator V0.90
+
+Copyright Karl Stenerud
+All rights reserved.
+
+Permission is granted to use this source code for non-commercial purposes.
+To use this code for commercial purposes, you must get permission from the
+author (Karl Stenerud) at karl@higashiyama-unet.ocn.ne.jp.
+
+
+*/
+
+
+#include "emu.h"
+#include "g65816ds.h"
+
+#ifdef SEC
+#undef SEC
+#endif
+
+#define ADDRESS_65816(A) ((A)&0xffffff)
+
+
+typedef struct
+{
+ unsigned char name;
+ unsigned char flag;
+ unsigned char ea;
+} opcode_struct;
+
+enum
+{
+ IMP , ACC , RELB, RELW, IMM , A , AI , AL , ALX , AX , AXI ,
+ AY , D , DI , DIY , DLI , DLIY, DX , DXI , DY , S , SIY ,
+ SIG /*, MVN , MVP , PEA , PEI , PER */
+};
+
+enum
+{
+ I, /* ignore */
+ M, /* check m bit */
+ X /* check x bit */
+};
+
+enum
+{
+ ADC , AND , ASL , BCC , BCS , BEQ , BIT , BMI , BNE , BPL , BRA ,
+ BRK , BRL , BVC , BVS , CLC , CLD , CLI , CLV , CMP , COP , CPX ,
+ CPY , DEA , DEC , DEX , DEY , EOR , INA , INC , INX , INY , JML ,
+ JMP , JSL , JSR , LDA , LDX , LDY , LSR , MVN , MVP , NOP , ORA ,
+ PEA , PEI , PER , PHA , PHB , PHD , PHK , PHP , PHX , PHY , PLA ,
+ PLB , PLD , PLP , PLX , PLY , REP , ROL , ROR , RTI , RTL , RTS ,
+ SBC , SEC , SED , SEI , SEP , STA , STP , STX , STY , STZ , TAX ,
+ TAY , TCS , TCD , TDC , TRB , TSB , TSC , TSX , TXA , TXS , TXY ,
+ TYA , TYX , WAI , WDM , XBA , XCE
+};
+
+static const char *const g_opnames[] =
+{
+ "ADC", "AND", "ASL", "BCC", "BCS", "BEQ", "BIT", "BMI", "BNE", "BPL", "BRA",
+ "BRK", "BRL", "BVC", "BVS", "CLC", "CLD", "CLI", "CLV", "CMP", "COP", "CPX",
+ "CPY", "DEA", "DEC", "DEX", "DEY", "EOR", "INA", "INC", "INX", "INY", "JML",
+ "JMP", "JSL", "JSR", "LDA", "LDX", "LDY", "LSR", "MVN", "MVP", "NOP", "ORA",
+ "PEA", "PEI", "PER", "PHA", "PHB", "PHD", "PHK", "PHP", "PHX", "PHY", "PLA",
+ "PLB", "PLD", "PLP", "PLX", "PLY", "REP", "ROL", "ROR", "RTI", "RTL", "RTS",
+ "SBC", "SEC", "SED", "SEI", "SEP", "STA", "STP", "STX", "STY", "STZ", "TAX",
+ "TAY", "TCS", "TCD", "TDC", "TRB", "TSB", "TSC", "TSX", "TXA", "TXS", "TXY",
+ "TYA", "TYX", "WAI", "WDM", "XBA", "XCE"
+};
+
+static const opcode_struct g_opcodes[256] =
+{
+ {BRK, I, SIG }, {ORA, M, DXI }, {COP, I, SIG }, {ORA, M, S },
+ {TSB, M, D }, {ORA, M, D }, {ASL, M, D }, {ORA, M, DLI },
+ {PHP, I, IMP }, {ORA, M, IMM }, {ASL, M, ACC }, {PHD, I, IMP },
+ {TSB, M, A }, {ORA, M, A }, {ASL, M, A }, {ORA, M, AL },
+ {BPL, I, RELB}, {ORA, M, DIY }, {ORA, M, DI }, {ORA, M, SIY },
+ {TRB, M, D }, {ORA, M, DX }, {ASL, M, DX }, {ORA, M, DLIY},
+ {CLC, I, IMP }, {ORA, M, AY }, {INA, I, IMP }, {TCS, I, IMP },
+ {TRB, M, A }, {ORA, M, AX }, {ASL, M, AX }, {ORA, M, ALX },
+ {JSR, I, A }, {AND, M, DXI }, {JSL, I, AL }, {AND, M, S },
+ {BIT, M, D }, {AND, M, D }, {ROL, M, D }, {AND, M, DLI },
+ {PLP, I, IMP }, {AND, M, IMM }, {ROL, M, ACC }, {PLD, I, IMP },
+ {BIT, M, A }, {AND, M, A }, {ROL, M, A }, {AND, M, AL },
+ {BMI, I, RELB}, {AND, M, DIY }, {AND, M, DI }, {AND, M, SIY },
+ {BIT, M, DX }, {AND, M, DX }, {ROL, M, DX }, {AND, M, DLIY},
+ {SEC, I, IMP }, {AND, M, AY }, {DEA, I, IMP }, {TSC, I, IMP },
+ {BIT, M, AX }, {AND, M, AX }, {ROL, M, AX }, {AND, M, ALX },
+ {RTI, I, IMP }, {EOR, M, DXI }, {WDM, I, IMP }, {EOR, M, S },
+ {MVP, I, MVP }, {EOR, M, D }, {LSR, M, D }, {EOR, M, DLI },
+ {PHA, I, IMP }, {EOR, M, IMM }, {LSR, M, ACC }, {PHK, I, IMP },
+ {JMP, I, A }, {EOR, M, A }, {LSR, M, A }, {EOR, M, AL },
+ {BVC, I, RELB}, {EOR, M, DIY }, {EOR, M, DI }, {EOR, M, SIY },
+ {MVN, I, MVN }, {EOR, M, DX }, {LSR, M, DX }, {EOR, M, DLIY},
+ {CLI, I, IMP }, {EOR, M, AY }, {PHY, I, IMP }, {TCD, I, IMP },
+ {JMP, I, AL }, {EOR, M, AX }, {LSR, M, AX }, {EOR, M, ALX },
+ {RTS, I, IMP }, {ADC, M, DXI }, {PER, I, PER }, {ADC, M, S },
+ {STZ, M, D }, {ADC, M, D }, {ROR, M, D }, {ADC, M, DLI },
+ {PLA, I, IMP }, {ADC, M, IMM }, {ROR, M, ACC }, {RTL, I, IMP },
+ {JMP, I, AI }, {ADC, M, A }, {ROR, M, A }, {ADC, M, AL },
+ {BVS, I, RELB}, {ADC, M, DIY }, {ADC, M, DI }, {ADC, M, SIY },
+ {STZ, M, DX }, {ADC, M, DX }, {ROR, M, DX }, {ADC, M, DLIY},
+ {SEI, I, IMP }, {ADC, M, AY }, {PLY, I, IMP }, {TDC, I, IMP },
+ {JMP, I, AXI }, {ADC, M, AX }, {ROR, M, AX }, {ADC, M, ALX },
+ {BRA, I, RELB}, {STA, M, DXI }, {BRL, I, RELW}, {STA, M, S },
+ {STY, X, D }, {STA, M, D }, {STX, X, D }, {STA, M, DLI },
+ {DEY, I, IMP }, {BIT, M, IMM }, {TXA, I, IMP }, {PHB, I, IMP },
+ {STY, X, A }, {STA, M, A }, {STX, X, A }, {STA, M, AL },
+ {BCC, I, RELB}, {STA, M, DIY }, {STA, M, DI }, {STA, M, SIY },
+ {STY, X, DX }, {STA, M, DX }, {STX, X, DY }, {STA, M, DLIY},
+ {TYA, I, IMP }, {STA, M, AY }, {TXS, I, IMP }, {TXY, I, IMP },
+ {STZ, M, A }, {STA, M, AX }, {STZ, M, AX }, {STA, M, ALX },
+ {LDY, X, IMM }, {LDA, M, DXI }, {LDX, X, IMM }, {LDA, M, S },
+ {LDY, X, D }, {LDA, M, D }, {LDX, X, D }, {LDA, M, DLI },
+ {TAY, I, IMP }, {LDA, M, IMM }, {TAX, I, IMP }, {PLB, I, IMP },
+ {LDY, X, A }, {LDA, M, A }, {LDX, X, A }, {LDA, M, AL },
+ {BCS, I, RELB}, {LDA, M, DIY }, {LDA, M, DI }, {LDA, M, SIY },
+ {LDY, X, DX }, {LDA, M, DX }, {LDX, X, DY }, {LDA, M, DLIY},
+ {CLV, I, IMP }, {LDA, M, AY }, {TSX, I, IMP }, {TYX, I, IMP },
+ {LDY, X, AX }, {LDA, M, AX }, {LDX, X, AY }, {LDA, M, ALX },
+ {CPY, X, IMM }, {CMP, M, DXI }, {REP, I, IMM }, {CMP, M, S },
+ {CPY, X, D }, {CMP, M, D }, {DEC, M, D }, {CMP, M, DLI },
+ {INY, I, IMP }, {CMP, M, IMM }, {DEX, I, IMP }, {WAI, I, IMP },
+ {CPY, X, A }, {CMP, M, A }, {DEC, M, A }, {CMP, M, AL },
+ {BNE, I, RELB}, {CMP, M, DIY }, {CMP, M, DI }, {CMP, M, SIY },
+ {PEI, I, PEI }, {CMP, M, DX }, {DEC, M, DX }, {CMP, M, DLIY},
+ {CLD, I, IMP }, {CMP, M, AY }, {PHX, I, IMP }, {STP, I, IMP },
+ {JML, I, AI }, {CMP, M, AX }, {DEC, M, AX }, {CMP, M, ALX },
+ {CPX, X, IMM }, {SBC, M, DXI }, {SEP, I, IMM }, {SBC, M, S },
+ {CPX, X, D }, {SBC, M, D }, {INC, M, D }, {SBC, M, DLI },
+ {INX, M, IMP }, {SBC, M, IMM }, {NOP, I, IMP }, {XBA, I, IMP },
+ {CPX, X, A }, {SBC, M, A }, {INC, M, A }, {SBC, M, AL },
+ {BEQ, I, RELB}, {SBC, M, DIY }, {SBC, M, DI }, {SBC, M, SIY },
+ {PEA, I, PEA }, {SBC, M, DX }, {INC, M, DX }, {SBC, M, DLIY},
+ {SED, I, IMP }, {SBC, M, AY }, {PLX, I, IMP }, {XCE, I, IMP },
+ {JSR, I, AXI }, {SBC, M, AX }, {INC, M, AX }, {SBC, M, ALX }
+};
+
+static const UINT8 *base_oprom;
+static UINT32 base_pc;
+
+INLINE unsigned int read_8(unsigned int address)
+{
+ address = ADDRESS_65816(address);
+ return base_oprom[address - base_pc];
+}
+
+INLINE unsigned int read_16(unsigned int address)
+{
+ unsigned int val = read_8(address);
+ return val | (read_8(address+1)<<8);
+}
+
+INLINE unsigned int read_24(unsigned int address)
+{
+ unsigned int val = read_8(address);
+ val |= (read_8(address+1)<<8);
+ return val | (read_8(address+2)<<16);
+}
+
+INLINE char* int_8_str(unsigned int val)
+{
+ static char str[20];
+
+ val &= 0xff;
+
+ if(val & 0x80)
+ sprintf(str, "-$%x", (0-val) & 0x7f);
+ else
+ sprintf(str, "$%x", val & 0x7f);
+
+ return str;
+}
+
+INLINE char* int_16_str(unsigned int val)
+{
+ static char str[20];
+
+ val &= 0xffff;
+
+ if(val & 0x8000)
+ sprintf(str, "-$%x", (0-val) & 0x7fff);
+ else
+ sprintf(str, "$%x", val & 0x7fff);
+
+ return str;
+}
+
+
+unsigned g65816_disassemble(char* buff, unsigned int pc, unsigned int pb, const UINT8 *oprom, int m_flag, int x_flag)
+{
+ unsigned int instruction;
+ const opcode_struct* opcode;
+ char* ptr;
+ int var;
+ int length = 1;
+ unsigned int address;
+ unsigned dasm_flags;
+
+ pb <<= 16;
+ address = pc | pb;
+
+ base_oprom = oprom;
+ base_pc = address;
+
+ instruction = read_8(address);
+ opcode = g_opcodes + instruction;
+
+ strcpy(buff, g_opnames[opcode->name]);
+ ptr = buff + strlen(buff);
+
+ switch(opcode->name)
+ {
+ case JSR:
+ case JSL:
+ dasm_flags = DASMFLAG_STEP_OVER;
+ break;
+
+ case RTI:
+ case RTL:
+ case RTS:
+ dasm_flags = DASMFLAG_STEP_OUT;
+ break;
+
+ default:
+ dasm_flags = 0;
+ break;
+ }
+
+ switch(opcode->ea)
+ {
+ case IMP :
+ break;
+ case ACC :
+ sprintf(ptr, "A");
+ break;
+ case RELB:
+ var = (INT8) read_8(address+1);
+ length++;
+ sprintf(ptr, " %06x (%s)", pb | ((pc + length + var)&0xffff), int_8_str(var));
+ break;
+ case RELW:
+ case PER :
+ var = read_16(address+1);
+ length += 2;
+ sprintf(ptr, " %06x (%s)", pb | ((pc + length + var)&0xffff), int_16_str(var));
+ break;
+ case IMM :
+ if((opcode->flag == M && !m_flag) || (opcode->flag == X && !x_flag))
+ {
+ sprintf(ptr, " #$%04x", read_16(address+1));
+ length += 2;
+ }
+ else
+ {
+ sprintf(ptr, " #$%02x", read_8(address+1));
+ length++;
+ }
+ break;
+ case A :
+ case PEA :
+ sprintf(ptr, " $%04x", read_16(address+1));
+ length += 2;
+ break;
+ case AI :
+ sprintf(ptr, " ($%04x)", read_16(address+1));
+ length += 2;
+ break;
+ case AL :
+ sprintf(ptr, " $%06x", read_24(address+1));
+ length += 3;
+ break;
+ case ALX :
+ sprintf(ptr, " $%06x,X", read_24(address+1));
+ length += 3;
+ break;
+ case AX :
+ sprintf(ptr, " $%04x,X", read_16(address+1));
+ length += 2;
+ break;
+ case AXI :
+ sprintf(ptr, " ($%04x,X)", read_16(address+1));
+ length += 2;
+ break;
+ case AY :
+ sprintf(ptr, " $%04x,Y", read_16(address+1));
+ length += 2;
+ break;
+ case D :
+ sprintf(ptr, " $%02x", read_8(address+1));
+ length++;
+ break;
+ case DI :
+ case PEI :
+ sprintf(ptr, " ($%02x)", read_8(address+1));
+ length++;
+ break;
+ case DIY :
+ sprintf(ptr, " ($%02x),Y", read_8(address+1));
+ length++;
+ break;
+ case DLI :
+ sprintf(ptr, " [$%02x]", read_8(address+1));
+ length++;
+ break;
+ case DLIY:
+ sprintf(ptr, " [$%02x],Y", read_8(address+1));
+ length++;
+ break;
+ case DX :
+ sprintf(ptr, " $%02x,X", read_8(address+1));
+ length++;
+ break;
+ case DXI :
+ sprintf(ptr, " ($%02x,X)", read_8(address+1));
+ length++;
+ break;
+ case DY :
+ sprintf(ptr, " $%02x,Y", read_8(address+1));
+ length++;
+ break;
+ case S :
+ sprintf(ptr, " %s,S", int_8_str(read_8(address+1)));
+ length++;
+ break;
+ case SIY :
+ sprintf(ptr, " (%s,S),Y", int_8_str(read_8(address+1)));
+ length++;
+ break;
+ case SIG :
+ sprintf(ptr, " #$%02x", read_8(address+1));
+ length++;
+ break;
+ case MVN :
+ case MVP :
+ sprintf(ptr, " $%02x, $%02x", read_8(address+2), read_8(address+1));
+ length += 2;
+ break;
+ }
+
+ return length | DASMFLAG_SUPPORTED | dasm_flags;
+}
+
+CPU_DISASSEMBLE( g65816_generic )
+{
+ return g65816_disassemble(buffer, (pc & 0x00ffff), (pc & 0xff0000) >> 16, oprom, 0, 0);
+}
diff --git a/trunk/src/emu/cpu/g65816/g65816ds.h b/trunk/src/emu/cpu/g65816/g65816ds.h
new file mode 100644
index 00000000000..af86043726d
--- /dev/null
+++ b/trunk/src/emu/cpu/g65816/g65816ds.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#ifndef __G65816DS_H__
+#define __G65816DS_H__
+/* ======================================================================== */
+/* =============================== COPYRIGHT ============================== */
+/* ======================================================================== */
+/*
+
+G65C816 CPU Emulator V0.92
+
+Copyright Karl Stenerud
+All rights reserved.
+
+Permission is granted to use this source code for non-commercial purposes.
+To use this code for commercial purposes, you must get permission from the
+author (Karl Stenerud) at karl@higashiyama-unet.ocn.ne.jp.
+
+
+*/
+
+unsigned g65816_disassemble(char* buff, unsigned int pc, unsigned int pb, const UINT8 *oprom, int m_flag, int x_flag);
+
+
+#endif /* __G65816DS_H__ */
diff --git a/trunk/src/emu/cpu/g65816/g65816o0.c b/trunk/src/emu/cpu/g65816/g65816o0.c
new file mode 100644
index 00000000000..38872d15915
--- /dev/null
+++ b/trunk/src/emu/cpu/g65816/g65816o0.c
@@ -0,0 +1,6 @@
+#include "emu.h"
+#include "debugger.h"
+#include "g65816.h"
+#include "g65816cm.h"
+#define EXECUTION_MODE EXECUTION_MODE_M0X0
+#include "g65816op.h"
diff --git a/trunk/src/emu/cpu/g65816/g65816o1.c b/trunk/src/emu/cpu/g65816/g65816o1.c
new file mode 100644
index 00000000000..8c31596c947
--- /dev/null
+++ b/trunk/src/emu/cpu/g65816/g65816o1.c
@@ -0,0 +1,6 @@
+#include "emu.h"
+#include "debugger.h"
+#include "g65816.h"
+#include "g65816cm.h"
+#define EXECUTION_MODE EXECUTION_MODE_M0X1
+#include "g65816op.h"
diff --git a/trunk/src/emu/cpu/g65816/g65816o2.c b/trunk/src/emu/cpu/g65816/g65816o2.c
new file mode 100644
index 00000000000..bc8c0103abd
--- /dev/null
+++ b/trunk/src/emu/cpu/g65816/g65816o2.c
@@ -0,0 +1,6 @@
+#include "emu.h"
+#include "debugger.h"
+#include "g65816.h"
+#include "g65816cm.h"
+#define EXECUTION_MODE EXECUTION_MODE_M1X0
+#include "g65816op.h"
diff --git a/trunk/src/emu/cpu/g65816/g65816o3.c b/trunk/src/emu/cpu/g65816/g65816o3.c
new file mode 100644
index 00000000000..d2b8697efe6
--- /dev/null
+++ b/trunk/src/emu/cpu/g65816/g65816o3.c
@@ -0,0 +1,6 @@
+#include "emu.h"
+#include "debugger.h"
+#include "g65816.h"
+#include "g65816cm.h"
+#define EXECUTION_MODE EXECUTION_MODE_M1X1
+#include "g65816op.h"
diff --git a/trunk/src/emu/cpu/g65816/g65816o4.c b/trunk/src/emu/cpu/g65816/g65816o4.c
new file mode 100644
index 00000000000..a66ba011d38
--- /dev/null
+++ b/trunk/src/emu/cpu/g65816/g65816o4.c
@@ -0,0 +1,6 @@
+#include "emu.h"
+#include "debugger.h"
+#include "g65816.h"
+#include "g65816cm.h"
+#define EXECUTION_MODE EXECUTION_MODE_E
+#include "g65816op.h"
diff --git a/trunk/src/emu/cpu/g65816/g65816op.h b/trunk/src/emu/cpu/g65816/g65816op.h
new file mode 100644
index 00000000000..9495214205f
--- /dev/null
+++ b/trunk/src/emu/cpu/g65816/g65816op.h
@@ -0,0 +1,2385 @@
+
+/* ======================================================================== */
+/* ============================= CONFIGURATION ============================ */
+/* ======================================================================== */
+
+#undef FLAG_SET_E
+#undef FLAG_SET_M
+#undef FLAG_SET_X
+#if EXECUTION_MODE == EXECUTION_MODE_E
+#define FLAG_SET_E 1
+#define FLAG_SET_M 1
+#define FLAG_SET_X 1
+#elif EXECUTION_MODE == EXECUTION_MODE_M0X0
+#define FLAG_SET_E 0
+#define FLAG_SET_M 0
+#define FLAG_SET_X 0
+#elif EXECUTION_MODE == EXECUTION_MODE_M0X1
+#define FLAG_SET_E 0
+#define FLAG_SET_M 0
+#define FLAG_SET_X 1
+#elif EXECUTION_MODE == EXECUTION_MODE_M1X0
+#define FLAG_SET_E 0
+#define FLAG_SET_M 1
+#define FLAG_SET_X 0
+#elif EXECUTION_MODE == EXECUTION_MODE_M1X1
+#define FLAG_SET_E 0
+#define FLAG_SET_M 1
+#define FLAG_SET_X 1
+#endif
+
+#undef VECTOR_IRQ
+#undef VECTOR_NMI
+#undef VECTOR_ABORT
+#undef VECTOR_BRK
+#undef VECTOR_COP
+
+#if FLAG_SET_E
+#define VECTOR_IRQ VECTOR_IRQ_E
+#define VECTOR_NMI VECTOR_NMI_E
+#define VECTOR_ABORT VECTOR_ABORT_E
+#define VECTOR_BRK VECTOR_BRK_E
+#define VECTOR_COP VECTOR_COP_E
+#else /* FLAG_SET_E */
+#define VECTOR_IRQ VECTOR_IRQ_N
+#define VECTOR_NMI VECTOR_NMI_N
+#define VECTOR_ABORT VECTOR_ABORT_N
+#define VECTOR_BRK VECTOR_BRK_N
+#define VECTOR_COP VECTOR_COP_N
+#endif
+
+
+
+/* ======================================================================== */
+/* ================================= MEMORY =============================== */
+/* ======================================================================== */
+
+#define ADDRESS_65816(A) ((A)&0x00ffffff)
+
+INLINE uint g65816i_read_8_normal(g65816i_cpu_struct *cpustate, uint address)
+{
+ address = ADDRESS_65816(address);
+ return g65816_read_8(address);
+}
+
+INLINE uint g65816i_read_8_immediate(g65816i_cpu_struct *cpustate, uint address)
+{
+ address = ADDRESS_65816(address);
+ return g65816_read_8_immediate(address);
+}
+
+INLINE uint g65816i_read_8_direct(g65816i_cpu_struct *cpustate, uint address)
+{
+#if FLAG_SET_E
+ /* force address into zero page */
+ address = REGISTER_D + MAKE_UINT_8(address - REGISTER_D);
+#else
+ address = ADDRESS_65816(address);
+#endif
+ return g65816_read_8(address);
+}
+
+INLINE uint g65816i_read_8_vector(g65816i_cpu_struct *cpustate, uint address)
+{
+ if (READ_VECTOR)
+ return READ_VECTOR(cpustate->program, address);
+ else
+ return g65816i_read_8_normal(cpustate, address);
+}
+
+INLINE void g65816i_write_8_normal(g65816i_cpu_struct *cpustate, uint address, uint value)
+{
+ address = ADDRESS_65816(address);
+ g65816_write_8(address, MAKE_UINT_8(value));
+}
+
+INLINE void g65816i_write_8_direct(g65816i_cpu_struct *cpustate, uint address, uint value)
+{
+#if FLAG_SET_E
+ /* force address into zero page */
+ address = REGISTER_D + MAKE_UINT_8(address - REGISTER_D);
+#else
+ address = ADDRESS_65816(address);
+#endif
+ g65816_write_8(address, MAKE_UINT_8(value));
+}
+
+INLINE uint g65816i_read_16_normal(g65816i_cpu_struct *cpustate, uint address)
+{
+ return g65816i_read_8_normal(cpustate, address) |
+ (g65816i_read_8_normal(cpustate, address+1)<<8);
+}
+
+INLINE uint g65816i_read_16_immediate(g65816i_cpu_struct *cpustate, uint address)
+{
+ return g65816i_read_8_immediate(cpustate, address) |
+ (g65816i_read_8_immediate(cpustate, address+1)<<8);
+}
+
+INLINE uint g65816i_read_16_direct(g65816i_cpu_struct *cpustate, uint address)
+{
+ return g65816i_read_8_direct(cpustate, address) |
+ (g65816i_read_8_direct(cpustate, address+1)<<8);
+}
+
+INLINE uint g65816i_read_16_vector(g65816i_cpu_struct *cpustate, uint address)
+{
+ return g65816i_read_8_vector(cpustate, address) |
+ (g65816i_read_8_vector(cpustate, address+1)<<8);
+}
+
+INLINE void g65816i_write_16_normal(g65816i_cpu_struct *cpustate, uint address, uint value)
+{
+ g65816i_write_8_normal(cpustate, address, value&0xff);
+ g65816i_write_8_normal(cpustate, address+1, value>>8);
+}
+
+INLINE void g65816i_write_16_direct(g65816i_cpu_struct *cpustate, uint address, uint value)
+{
+ g65816i_write_8_direct(cpustate, address, value&0xff);
+ g65816i_write_8_direct(cpustate, address+1, value>>8);
+}
+
+INLINE uint g65816i_read_24_normal(g65816i_cpu_struct *cpustate, uint address)
+{
+ return g65816i_read_8_normal(cpustate, address) |
+ (g65816i_read_8_normal(cpustate, address+1)<<8) |
+ (g65816i_read_8_normal(cpustate, address+2)<<16);
+}
+
+INLINE uint g65816i_read_24_immediate(g65816i_cpu_struct *cpustate, uint address)
+{
+ return g65816i_read_8_immediate(cpustate, address) |
+ (g65816i_read_8_immediate(cpustate, address+1)<<8) |
+ (g65816i_read_8_immediate(cpustate, address+2)<<16);
+}
+
+INLINE uint g65816i_read_24_direct(g65816i_cpu_struct *cpustate, uint address)
+{
+ return g65816i_read_8_direct(cpustate, address) |
+ (g65816i_read_8_direct(cpustate, address+1)<<8) |
+ (g65816i_read_8_direct(cpustate, address+2)<<16);
+}
+
+
+
+/* ======================================================================== */
+/* ================================= STACK ================================ */
+/* ======================================================================== */
+
+INLINE void g65816i_push_8(g65816i_cpu_struct *cpustate, uint value)
+{
+ g65816i_write_8_normal(cpustate, REGISTER_S, value);
+#if FLAG_SET_E
+ REGISTER_S = MAKE_UINT_8(REGISTER_S-1) | 0x100;
+#else
+ REGISTER_S = MAKE_UINT_16(REGISTER_S-1);
+#endif
+}
+
+INLINE uint g65816i_pull_8(g65816i_cpu_struct *cpustate)
+{
+#if FLAG_SET_E
+ REGISTER_S = MAKE_UINT_8(REGISTER_S+1) | 0x100;
+#else
+ REGISTER_S = MAKE_UINT_16(REGISTER_S+1);
+#endif
+ return g65816i_read_8_normal(cpustate, REGISTER_S);
+}
+
+INLINE void g65816i_push_16(g65816i_cpu_struct *cpustate, uint value)
+{
+ g65816i_push_8(cpustate, value>>8);
+ g65816i_push_8(cpustate, value&0xff);
+}
+
+INLINE uint g65816i_pull_16(g65816i_cpu_struct *cpustate)
+{
+ uint res = g65816i_pull_8(cpustate);
+ return res | (g65816i_pull_8(cpustate) << 8);
+}
+
+INLINE void g65816i_push_24(g65816i_cpu_struct *cpustate, uint value)
+{
+ g65816i_push_8(cpustate, value>>16);
+ g65816i_push_8(cpustate, (value>>8)&0xff);
+ g65816i_push_8(cpustate, value&0xff);
+}
+
+INLINE uint g65816i_pull_24(g65816i_cpu_struct *cpustate)
+{
+ uint res = g65816i_pull_8(cpustate);
+ res |= g65816i_pull_8(cpustate) << 8;
+ return ((res + 1) & 0xffff) | (g65816i_pull_8(cpustate) << 16);
+}
+
+
+/* ======================================================================== */
+/* ============================ PROGRAM COUNTER =========================== */
+/* ======================================================================== */
+
+INLINE void g65816i_jump_16(g65816i_cpu_struct *cpustate, uint address)
+{
+ REGISTER_PC = MAKE_UINT_16(address);
+ g65816i_jumping(REGISTER_PC);
+}
+
+INLINE void g65816i_jump_24(g65816i_cpu_struct *cpustate, uint address)
+{
+ REGISTER_PB = address&0xff0000;
+ REGISTER_PC = MAKE_UINT_16(address);
+ g65816i_jumping(REGISTER_PC);
+}
+
+INLINE void g65816i_branch_8(g65816i_cpu_struct *cpustate, uint offset)
+{
+#if FLAG_SET_E
+ uint old_pc = REGISTER_PC;
+ REGISTER_PC = MAKE_UINT_16(REGISTER_PC + MAKE_INT_8(offset));
+ if((REGISTER_PC^old_pc)&0xff00)
+ CLK(1);
+#else
+ REGISTER_PC = MAKE_UINT_16(REGISTER_PC + MAKE_INT_8(offset));
+#endif
+ g65816i_branching(REGISTER_PC);
+}
+
+INLINE void g65816i_branch_16(g65816i_cpu_struct *cpustate, uint offset)
+{
+ REGISTER_PC = MAKE_UINT_16(REGISTER_PC + offset);
+ g65816i_branching(REGISTER_PC);
+}
+
+
+/* ======================================================================== */
+/* ============================ STATUS REGISTER =========================== */
+/* ======================================================================== */
+
+#if !FLAG_SET_E
+INLINE void g65816i_set_flag_mx(g65816i_cpu_struct *cpustate, uint value)
+{
+#if FLAG_SET_M
+ if(!(value & FLAGPOS_M))
+ {
+ REGISTER_A |= REGISTER_B;
+ REGISTER_B = 0;
+ FLAG_M = MFLAG_CLEAR;
+ }
+#else
+ if(value & FLAGPOS_M)
+ {
+ REGISTER_B = REGISTER_A & 0xff00;
+ REGISTER_A = MAKE_UINT_8(REGISTER_A);
+ FLAG_M = MFLAG_SET;
+ }
+#endif
+#if FLAG_SET_X
+ if(!(value & FLAGPOS_X))
+ {
+ FLAG_X = XFLAG_CLEAR;
+ }
+#else
+ if(value & FLAGPOS_X)
+ {
+ REGISTER_X = MAKE_UINT_8(REGISTER_X);
+ REGISTER_Y = MAKE_UINT_8(REGISTER_Y);
+ FLAG_X = XFLAG_SET;
+ }
+#endif
+ g65816i_set_execution_mode(cpustate, (FLAG_M>>4) | (FLAG_X>>4));
+}
+#endif
+
+INLINE void g65816i_set_flag_e(g65816i_cpu_struct *cpustate, uint value)
+{
+#if FLAG_SET_E
+ if(!value)
+ {
+ FLAG_E = EFLAG_CLEAR;
+ g65816i_set_execution_mode(cpustate, EXECUTION_MODE_M1X1);
+ }
+#else
+ if(value)
+ {
+#if !FLAG_SET_M
+ REGISTER_B = REGISTER_A & 0xff00;
+ REGISTER_A &= 0x00ff;
+ FLAG_M = MFLAG_SET;
+#endif
+#if !FLAG_SET_X
+ REGISTER_X = MAKE_UINT_8(REGISTER_X);
+ REGISTER_Y = MAKE_UINT_8(REGISTER_Y);
+ FLAG_X = XFLAG_SET;
+#endif
+ REGISTER_S = MAKE_UINT_8(REGISTER_S) | 0x100;
+ FLAG_E = EFLAG_SET;
+ g65816i_set_execution_mode(cpustate, EXECUTION_MODE_E);
+ }
+#endif
+}
+
+//INLINE void g65816i_check_maskable_interrupt(void);
+
+INLINE void g65816i_set_flag_i(g65816i_cpu_struct *cpustate, uint value)
+{
+ value &= FLAGPOS_I;
+ if(!FLAG_I || value)
+ {
+ FLAG_I = value;
+ return;
+ }
+ FLAG_I = value;
+// g65816i_check_maskable_interrupt();
+}
+
+
+
+
+/* Get the Processor Status Register */
+INLINE uint g65816i_get_reg_p(g65816i_cpu_struct *cpustate)
+{
+ return (FLAG_N&0x80) |
+ ((FLAG_V>>1)&0x40) |
+ FLAG_M |
+ FLAG_X |
+ FLAG_D |
+ FLAG_I |
+ ((!FLAG_Z)<<1) |
+ ((FLAG_C>>8)&1);
+}
+
+INLINE void g65816i_set_reg_p(g65816i_cpu_struct *cpustate, uint value)
+{
+#if FLAG_SET_E
+ FLAG_N = value;
+ FLAG_V = value << 1;
+ FLAG_D = value & FLAGPOS_D;
+ FLAG_Z = !(value & FLAGPOS_Z);
+ FLAG_C = value << 8;
+ g65816i_set_flag_i(cpustate, value);
+#else
+ FLAG_N = value;
+ FLAG_V = value << 1;
+ FLAG_D = value & FLAGPOS_D;
+ FLAG_Z = !(value & FLAGPOS_Z);
+ FLAG_C = value << 8;
+ g65816i_set_flag_mx(cpustate, value);
+ g65816i_set_flag_i(cpustate, value);
+#endif
+}
+
+
+/* ======================================================================== */
+/* =============================== INTERRUPTS ============================= */
+/* ======================================================================== */
+
+INLINE void g65816i_interrupt_hardware(g65816i_cpu_struct *cpustate, uint vector)
+{
+#if FLAG_SET_E
+ CLK(7);
+ g65816i_push_16(cpustate, REGISTER_PC);
+ g65816i_push_8(cpustate, g65816i_get_reg_p(cpustate) & ~FLAGPOS_B);
+ FLAG_D = DFLAG_CLEAR;
+ g65816i_set_flag_i(cpustate, IFLAG_SET);
+ REGISTER_PB = 0;
+ g65816i_jump_16(cpustate, g65816i_read_16_vector(cpustate, vector));
+ if(INT_ACK) INT_ACK(cpustate->device, 0);
+#else
+ CLK(8);
+ g65816i_push_8(cpustate, REGISTER_PB>>16);
+ g65816i_push_16(cpustate, REGISTER_PC);
+ g65816i_push_8(cpustate, g65816i_get_reg_p(cpustate));
+ FLAG_D = DFLAG_CLEAR;
+ g65816i_set_flag_i(cpustate, IFLAG_SET);
+ REGISTER_PB = 0;
+ g65816i_jump_16(cpustate, g65816i_read_16_vector(cpustate, vector));
+ if(INT_ACK) INT_ACK(cpustate->device, 0);
+#endif
+}
+
+INLINE void g65816i_interrupt_software(g65816i_cpu_struct *cpustate, uint vector)
+{
+#if FLAG_SET_E
+ CLK(7);
+ g65816i_push_16(cpustate, REGISTER_PC);
+ g65816i_push_8(cpustate, g65816i_get_reg_p(cpustate));
+ FLAG_D = DFLAG_CLEAR;
+ g65816i_set_flag_i(cpustate, IFLAG_SET);
+ REGISTER_PB = 0;
+ g65816i_jump_16(cpustate, g65816i_read_16_normal(cpustate, vector));
+#else
+ CLK(8);
+ g65816i_push_8(cpustate, REGISTER_PB>>16);
+ g65816i_push_16(cpustate, REGISTER_PC);
+ g65816i_push_8(cpustate, g65816i_get_reg_p(cpustate));
+ FLAG_D = DFLAG_CLEAR;
+ g65816i_set_flag_i(cpustate, IFLAG_SET);
+ REGISTER_PB = 0;
+ g65816i_jump_16(cpustate, g65816i_read_16_normal(cpustate, vector));
+#endif
+}
+
+INLINE void g65816i_interrupt_nmi(g65816i_cpu_struct *cpustate)
+{
+#if FLAG_SET_E
+ CLK(7);
+ g65816i_push_16(cpustate, REGISTER_PC);
+ g65816i_push_8(cpustate, g65816i_get_reg_p(cpustate) & ~FLAGPOS_B);
+ FLAG_D = DFLAG_CLEAR;
+ REGISTER_PB = 0;
+ g65816i_jump_16(cpustate, g65816i_read_16_normal(cpustate, VECTOR_NMI));
+#else
+ CLK(8);
+ g65816i_push_8(cpustate, REGISTER_PB>>16);
+ g65816i_push_16(cpustate, REGISTER_PC);
+ g65816i_push_8(cpustate, g65816i_get_reg_p(cpustate));
+ FLAG_D = DFLAG_CLEAR;
+ REGISTER_PB = 0;
+ g65816i_jump_16(cpustate, g65816i_read_16_normal(cpustate, VECTOR_NMI));
+#endif
+}
+
+
+INLINE void g65816i_check_maskable_interrupt(g65816i_cpu_struct *cpustate)
+{
+ if(!(CPU_STOPPED & STOP_LEVEL_STOP) && LINE_IRQ && !FLAG_I)
+ {
+ g65816i_interrupt_hardware(cpustate, VECTOR_IRQ);
+ CPU_STOPPED &= ~STOP_LEVEL_WAI;
+ LINE_IRQ=0;
+ }
+}
+
+
+/* ======================================================================== */
+/* ========================== EFFECTIVE ADDRESSES ========================= */
+/* ======================================================================== */
+
+/* Effective-address based memory access macros */
+#define read_8_NORM(A) g65816i_read_8_normal(cpustate, A)
+#define read_8_IMM(A) g65816i_read_8_immediate(cpustate, A)
+#define read_8_D(A) g65816i_read_8_direct(cpustate, A)
+#define read_8_A(A) g65816i_read_8_normal(cpustate, A)
+#define read_8_AL(A) g65816i_read_8_normal(cpustate, A)
+#define read_8_DX(A) g65816i_read_8_direct(cpustate, A)
+#define read_8_DY(A) g65816i_read_8_direct(cpustate, A)
+#define read_8_AX(A) g65816i_read_8_normal(cpustate, A)
+#define read_8_ALX(A) g65816i_read_8_normal(cpustate, A)
+#define read_8_AY(A) g65816i_read_8_normal(cpustate, A)
+#define read_8_DI(A) g65816i_read_8_normal(cpustate, A)
+#define read_8_DLI(A) g65816i_read_8_normal(cpustate, A)
+#define read_8_AI(A) g65816i_read_8_normal(cpustate, A)
+#define read_8_ALI(A) g65816i_read_8_normal(cpustate, A)
+#define read_8_DXI(A) g65816i_read_8_normal(cpustate, A)
+#define read_8_DIY(A) g65816i_read_8_normal(cpustate, A)
+#define read_8_DLIY(A) g65816i_read_8_normal(cpustate, A)
+#define read_8_AXI(A) g65816i_read_8_normal(cpustate, A)
+#define read_8_S(A) g65816i_read_8_normal(cpustate, A)
+#define read_8_SIY(A) g65816i_read_8_normal(cpustate, A)
+
+#define read_16_NORM(A) g65816i_read_16_normal(cpustate, A)
+#define read_16_IMM(A) g65816i_read_16_immediate(cpustate, A)
+#define read_16_D(A) g65816i_read_16_direct(cpustate, A)
+#define read_16_A(A) g65816i_read_16_normal(cpustate, A)
+#define read_16_AL(A) g65816i_read_16_normal(cpustate, A)
+#define read_16_DX(A) g65816i_read_16_direct(cpustate, A)
+#define read_16_DY(A) g65816i_read_16_direct(cpustate, A)
+#define read_16_AX(A) g65816i_read_16_normal(cpustate, A)
+#define read_16_ALX(A) g65816i_read_16_normal(cpustate, A)
+#define read_16_AY(A) g65816i_read_16_normal(cpustate, A)
+#define read_16_DI(A) g65816i_read_16_normal(cpustate, A)
+#define read_16_DLI(A) g65816i_read_16_normal(cpustate, A)
+#define read_16_AI(A) g65816i_read_16_normal(cpustate, A)
+#define read_16_ALI(A) g65816i_read_16_normal(cpustate, A)
+#define read_16_DXI(A) g65816i_read_16_normal(cpustate, A)
+#define read_16_DIY(A) g65816i_read_16_normal(cpustate, A)
+#define read_16_DLIY(A) g65816i_read_16_normal(cpustate, A)
+#define read_16_AXI(A) g65816i_read_16_normal(cpustate, A)
+#define read_16_S(A) g65816i_read_16_normal(cpustate, A)
+#define read_16_SIY(A) g65816i_read_16_normal(cpustate, A)
+
+#define read_24_NORM(A) g65816i_read_24_normal(cpustate, A)
+#define read_24_IMM(A) g65816i_read_24_immediate(cpustate, A)
+#define read_24_D(A) g65816i_read_24_direct(cpustate, A)
+#define read_24_A(A) g65816i_read_24_normal(cpustate, A)
+#define read_24_AL(A) g65816i_read_24_normal(cpustate, A)
+#define read_24_DX(A) g65816i_read_24_direct(cpustate, A)
+#define read_24_DY(A) g65816i_read_24_direct(cpustate, A)
+#define read_24_AX(A) g65816i_read_24_normal(cpustate, A)
+#define read_24_ALX(A) g65816i_read_24_normal(cpustate, A)
+#define read_24_AY(A) g65816i_read_24_normal(cpustate, A)
+#define read_24_DI(A) g65816i_read_24_normal(cpustate, A)
+#define read_24_DLI(A) g65816i_read_24_normal(cpustate, A)
+#define read_24_AI(A) g65816i_read_24_normal(cpustate, A)
+#define read_24_ALI(A) g65816i_read_24_normal(cpustate, A)
+#define read_24_DXI(A) g65816i_read_24_normal(cpustate, A)
+#define read_24_DIY(A) g65816i_read_24_normal(cpustate, A)
+#define read_24_DLIY(A) g65816i_read_24_normal(cpustate, A)
+#define read_24_AXI(A) g65816i_read_24_normal(cpustate, A)
+#define read_24_S(A) g65816i_read_24_normal(cpustate, A)
+#define read_24_SIY(A) g65816i_read_24_normal(cpustate, A)
+
+#define write_8_NORM(A, V) g65816i_write_8_normal(cpustate, A, V)
+#define write_8_D(A, V) g65816i_write_8_direct(cpustate, A, V)
+#define write_8_A(A, V) g65816i_write_8_normal(cpustate, A, V)
+#define write_8_AL(A, V) g65816i_write_8_normal(cpustate, A, V)
+#define write_8_DX(A, V) g65816i_write_8_direct(cpustate, A, V)
+#define write_8_DY(A, V) g65816i_write_8_direct(cpustate, A, V)
+#define write_8_AX(A, V) g65816i_write_8_normal(cpustate, A, V)
+#define write_8_ALX(A, V) g65816i_write_8_normal(cpustate, A, V)
+#define write_8_AY(A, V) g65816i_write_8_normal(cpustate, A, V)
+#define write_8_DI(A, V) g65816i_write_8_normal(cpustate, A, V)
+#define write_8_DLI(A, V) g65816i_write_8_normal(cpustate, A, V)
+#define write_8_AI(A, V) g65816i_write_8_normal(cpustate, A, V)
+#define write_8_ALI(A, V) g65816i_write_8_normal(cpustate, A, V)
+#define write_8_DXI(A, V) g65816i_write_8_normal(cpustate, A, V)
+#define write_8_DIY(A, V) g65816i_write_8_normal(cpustate, A, V)
+#define write_8_DLIY(A, V) g65816i_write_8_normal(cpustate, A, V)
+#define write_8_AXI(A, V) g65816i_write_8_normal(cpustate, A, V)
+#define write_8_S(A, V) g65816i_write_8_normal(cpustate, A, V)
+#define write_8_SIY(A, V) g65816i_write_8_normal(cpustate, A, V)
+
+#define write_16_NORM(A, V) g65816i_write_16_normal(cpustate, A, V)
+#define write_16_D(A, V) g65816i_write_16_direct(cpustate, A, V)
+#define write_16_A(A, V) g65816i_write_16_normal(cpustate, A, V)
+#define write_16_AL(A, V) g65816i_write_16_normal(cpustate, A, V)
+#define write_16_DX(A, V) g65816i_write_16_direct(cpustate, A, V)
+#define write_16_DY(A, V) g65816i_write_16_direct(cpustate, A, V)
+#define write_16_AX(A, V) g65816i_write_16_normal(cpustate, A, V)
+#define write_16_ALX(A, V) g65816i_write_16_normal(cpustate, A, V)
+#define write_16_AY(A, V) g65816i_write_16_normal(cpustate, A, V)
+#define write_16_DI(A, V) g65816i_write_16_normal(cpustate, A, V)
+#define write_16_DLI(A, V) g65816i_write_16_normal(cpustate, A, V)
+#define write_16_AI(A, V) g65816i_write_16_normal(cpustate, A, V)
+#define write_16_ALI(A, V) g65816i_write_16_normal(cpustate, A, V)
+#define write_16_DXI(A, V) g65816i_write_16_normal(cpustate, A, V)
+#define write_16_DIY(A, V) g65816i_write_16_normal(cpustate, A, V)
+#define write_16_DLIY(A, V) g65816i_write_16_normal(cpustate, A, V)
+#define write_16_AXI(A, V) g65816i_write_16_normal(cpustate, A, V)
+#define write_16_S(A, V) g65816i_write_16_normal(cpustate, A, V)
+#define write_16_SIY(A, V) g65816i_write_16_normal(cpustate, A, V)
+
+
+#define OPER_8_IMM(cpustate) read_8_IMM(EA_IMM8(cpustate))
+#define OPER_8_D(cpustate) read_8_D(EA_D(cpustate))
+#define OPER_8_A(cpustate) read_8_A(EA_A(cpustate))
+#define OPER_8_AL(cpustate) read_8_AL(EA_AL(cpustate))
+#define OPER_8_DX(cpustate) read_8_DX(EA_DX(cpustate))
+#define OPER_8_DY(cpustate) read_8_DY(EA_DY(cpustate))
+#define OPER_8_AX(cpustate) read_8_AX(EA_AX(cpustate))
+#define OPER_8_ALX(cpustate) read_8_ALX(EA_ALX(cpustate))
+#define OPER_8_AY(cpustate) read_8_AY(EA_AY(cpustate))
+#define OPER_8_DI(cpustate) read_8_DI(EA_DI(cpustate))
+#define OPER_8_DLI(cpustate) read_8_DLI(EA_DLI(cpustate))
+#define OPER_8_AI(cpustate) read_8_AI(EA_AI(cpustate))
+#define OPER_8_ALI(cpustate) read_8_ALI(EA_ALI(cpustate))
+#define OPER_8_DXI(cpustate) read_8_DXI(EA_DXI(cpustate))
+#define OPER_8_DIY(cpustate) read_8_DIY(EA_DIY(cpustate))
+#define OPER_8_DLIY(cpustate) read_8_DLIY(EA_DLIY(cpustate))
+#define OPER_8_AXI(cpustate) read_8_AXI(EA_AXI(cpustate))
+#define OPER_8_S(cpustate) read_8_S(EA_S(cpustate))
+#define OPER_8_SIY(cpustate) read_8_SIY(EA_SIY(cpustate))
+
+#define OPER_16_IMM(cpustate) read_16_IMM(EA_IMM16(cpustate))
+#define OPER_16_D(cpustate) read_16_D(EA_D(cpustate))
+#define OPER_16_A(cpustate) read_16_A(EA_A(cpustate))
+#define OPER_16_AL(cpustate) read_16_AL(EA_AL(cpustate))
+#define OPER_16_DX(cpustate) read_16_DX(EA_DX(cpustate))
+#define OPER_16_DY(cpustate) read_16_DY(EA_DY(cpustate))
+#define OPER_16_AX(cpustate) read_16_AX(EA_AX(cpustate))
+#define OPER_16_ALX(cpustate) read_16_ALX(EA_ALX(cpustate))
+#define OPER_16_AY(cpustate) read_16_AY(EA_AY(cpustate))
+#define OPER_16_DI(cpustate) read_16_DI(EA_DI(cpustate))
+#define OPER_16_DLI(cpustate) read_16_DLI(EA_DLI(cpustate))
+#define OPER_16_AI(cpustate) read_16_AI(EA_AI(cpustate))
+#define OPER_16_ALI(cpustate) read_16_ALI(EA_ALI(cpustate))
+#define OPER_16_DXI(cpustate) read_16_DXI(EA_DXI(cpustate))
+#define OPER_16_DIY(cpustate) read_16_DIY(EA_DIY(cpustate))
+#define OPER_16_DLIY(cpustate) read_16_DLIY(EA_DLIY(cpustate))
+#define OPER_16_AXI(cpustate) read_16_AXI(EA_AXI(cpustate))
+#define OPER_16_S(cpustate) read_16_S(EA_S(cpustate))
+#define OPER_16_SIY(cpustate) read_16_SIY(EA_SIY(cpustate))
+
+#define OPER_24_IMM(cpustate) read_24_IMM(EA_IMM24(cpustate))
+#define OPER_24_D(cpustate) read_24_D(EA_D(cpustate))
+#define OPER_24_A(cpustate) read_24_A(EA_A(cpustate))
+#define OPER_24_AL(cpustate) read_24_AL(EA_AL(cpustate))
+#define OPER_24_DX(cpustate) read_24_DX(EA_DX(cpustate))
+#define OPER_24_DY(cpustate) read_24_DY(EA_DY(cpustate))
+#define OPER_24_AX(cpustate) read_24_AX(EA_AX(cpustate))
+#define OPER_24_ALX(cpustate) read_24_ALX(EA_ALX(cpustate))
+#define OPER_24_AY(cpustate) read_24_AY(EA_AY(cpustate))
+#define OPER_24_DI(cpustate) read_24_DI(EA_DI(cpustate))
+#define OPER_24_DLI(cpustate) read_24_DLI(EA_DLI(cpustate))
+#define OPER_24_AI(cpustate) read_24_AI(EA_AI(cpustate))
+#define OPER_24_ALI(cpustate) read_24_ALI(EA_ALI(cpustate))
+#define OPER_24_DXI(cpustate) read_24_DXI(EA_DXI(cpustate))
+#define OPER_24_DIY(cpustate) read_24_DIY(EA_DIY(cpustate))
+#define OPER_24_DLIY(cpustate) read_24_DLIY(EA_DLIY(cpustate))
+#define OPER_24_AXI(cpustate) read_24_AXI(EA_AXI(cpustate))
+#define OPER_24_S(cpustate) read_24_S(EA_S(cpustate))
+#define OPER_24_SIY(cpustate) read_24_SIY(EA_SIY(cpustate))
+
+INLINE uint EA_IMM8(g65816i_cpu_struct *cpustate) {REGISTER_PC += 1; return REGISTER_PB | MAKE_UINT_16(REGISTER_PC-1);}
+INLINE uint EA_IMM16(g65816i_cpu_struct *cpustate) {REGISTER_PC += 2; return REGISTER_PB | MAKE_UINT_16(REGISTER_PC-2);}
+INLINE uint EA_IMM24(g65816i_cpu_struct *cpustate) {REGISTER_PC += 3; return REGISTER_PB | MAKE_UINT_16(REGISTER_PC-3);}
+INLINE uint EA_D(g65816i_cpu_struct *cpustate) {if(MAKE_UINT_8(REGISTER_D)) CLK(1); return MAKE_UINT_16(REGISTER_D + OPER_8_IMM(cpustate));}
+INLINE uint EA_A(g65816i_cpu_struct *cpustate) {return REGISTER_DB | OPER_16_IMM(cpustate);}
+INLINE uint EA_AL(g65816i_cpu_struct *cpustate) {return OPER_24_IMM(cpustate);}
+INLINE uint EA_DX(g65816i_cpu_struct *cpustate) {return MAKE_UINT_16(REGISTER_D + OPER_8_IMM(cpustate) + REGISTER_X);}
+INLINE uint EA_DY(g65816i_cpu_struct *cpustate) {return MAKE_UINT_16(REGISTER_D + OPER_8_IMM(cpustate) + REGISTER_Y);}
+INLINE uint EA_AX(g65816i_cpu_struct *cpustate) {uint tmp = EA_A(cpustate); if((tmp^(tmp+REGISTER_X))&0xff00) CLK(1); return tmp + REGISTER_X;}
+INLINE uint EA_ALX(g65816i_cpu_struct *cpustate) {return EA_AL(cpustate) + REGISTER_X;}
+INLINE uint EA_AY(g65816i_cpu_struct *cpustate) {uint tmp = EA_A(cpustate); if((tmp^(tmp+REGISTER_X))&0xff00) CLK(1); return tmp + REGISTER_Y;}
+INLINE uint EA_DI(g65816i_cpu_struct *cpustate) {return REGISTER_DB | OPER_16_D(cpustate);}
+INLINE uint EA_DLI(g65816i_cpu_struct *cpustate) {return OPER_24_D(cpustate);}
+INLINE uint EA_AI(g65816i_cpu_struct *cpustate) {return read_16_A(OPER_16_IMM(cpustate));}
+INLINE uint EA_ALI(g65816i_cpu_struct *cpustate) {return OPER_24_A(cpustate);}
+INLINE uint EA_DXI(g65816i_cpu_struct *cpustate) {return REGISTER_DB | OPER_16_DX(cpustate);}
+INLINE uint EA_DIY(g65816i_cpu_struct *cpustate) {uint tmp = REGISTER_DB | OPER_16_D(cpustate); if((tmp^(tmp+REGISTER_X))&0xff00) CLK(1); return tmp + REGISTER_Y;}
+INLINE uint EA_DLIY(g65816i_cpu_struct *cpustate) {return OPER_24_D(cpustate) + REGISTER_Y;}
+INLINE uint EA_AXI(g65816i_cpu_struct *cpustate) {return read_16_AXI(MAKE_UINT_16(OPER_16_IMM(cpustate) + REGISTER_X));}
+INLINE uint EA_S(g65816i_cpu_struct *cpustate) {return MAKE_UINT_16(REGISTER_S + OPER_8_IMM(cpustate));}
+INLINE uint EA_SIY(g65816i_cpu_struct *cpustate) {return MAKE_UINT_16(read_16_SIY(REGISTER_S + OPER_8_IMM(cpustate)) + REGISTER_Y) | REGISTER_DB;}
+
+
+
+/* ======================================================================== */
+/* =========================== OPERATION MACROS =========================== */
+/* ======================================================================== */
+
+/* M6502 Add With Carry */
+#undef OP_ADC
+#if FLAG_SET_M
+#define OP_ADC(MODE) \
+ { \
+ unsigned tmp16; \
+ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \
+ SRC = OPER_8_##MODE(cpustate); \
+ if(FLAG_D) \
+ { \
+ INT32 result, r0, r1, carry; \
+ r0 = REGISTER_A; \
+ r1 = SRC; \
+ carry = CFLAG_AS_1(); \
+ result = (r0 & 0x0f) + (r1 & 0x0f) + (carry << 0); \
+ if (result > 0x09) result += 0x06; \
+ carry = result > 0x0f; \
+ result = (r0 & 0xf0) + (r1 & 0xf0) + (carry << 4) + (result & 0x0f); \
+ FLAG_V = ~(r0 ^ SRC) & (r0 ^ result) & 0x80; \
+ if (result > 0x9f) result += 0x60; \
+ FLAG_C = (result > 0xff) ? 0x100 : 0; \
+ FLAG_N = (result & 0x80); \
+ FLAG_Z = REGISTER_A = MAKE_UINT_8(result); \
+ } \
+ else \
+ { \
+ FLAG_C = tmp16 = REGISTER_A + SRC + CFLAG_AS_1(); \
+ FLAG_V = VFLAG_ADD_8(SRC, REGISTER_A, FLAG_C); \
+ FLAG_N = FLAG_Z = REGISTER_A = MAKE_UINT_8(tmp16); \
+ } \
+ }
+
+#else
+#define OP_ADC(MODE) \
+ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \
+ SRC = OPER_16_##MODE(cpustate); \
+ INT32 result, r0, r1, carry; \
+ r0 = REGISTER_A; \
+ r1 = SRC; \
+ carry = CFLAG_AS_1(); \
+ if (!FLAG_D) \
+ { \
+ result = r0 + r1 + carry; \
+ } \
+ else \
+ { \
+ result = (r0 & 0x000f) + (r1 & 0x000f) + (carry << 0); \
+ if(result > 0x0009) result += 0x0006; \
+ carry = result > 0x000f; \
+ result = (r0 & 0x00f0) + (r1 & 0x00f0) + (carry << 4) + (result & 0x000f); \
+ if(result > 0x009f) result += 0x0060; \
+ carry = result > 0x00ff; \
+ result = (r0 & 0x0f00) + (r1 & 0x0f00) + (carry << 8) + (result & 0x00ff); \
+ if(result > 0x09ff) result += 0x0600; \
+ carry = result > 0x0fff; \
+ result = (r0 & 0xf000) + (r1 & 0xf000) + (carry << 12) + (result & 0x0fff); \
+ } \
+ FLAG_V = ~(r0 ^ r1) & (r0 ^ result) & 0x8000; \
+ FLAG_V >>= 8; \
+ if (FLAG_D && result > 0x9fff) result += 0x6000; \
+ FLAG_C = (result > 0xffff) ? 0x100 : 0; \
+ FLAG_Z = REGISTER_A = MAKE_UINT_16(result); \
+ FLAG_N = NFLAG_16(REGISTER_A);
+#endif
+
+/* M6502 Logical AND with accumulator */
+#undef OP_AND
+#if FLAG_SET_M
+#define OP_AND(MODE) \
+ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \
+ FLAG_N = FLAG_Z = REGISTER_A &= OPER_8_##MODE(cpustate)
+#else
+#define OP_AND(MODE) \
+ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \
+ FLAG_Z = REGISTER_A &= OPER_16_##MODE(cpustate); \
+ FLAG_N = NFLAG_16(REGISTER_A)
+#endif
+
+/* M6502 Arithmetic Shift Left accumulator */
+#undef OP_ASL
+#if FLAG_SET_M
+#define OP_ASL() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_C = REGISTER_A << 1; \
+ FLAG_N = FLAG_Z = REGISTER_A = MAKE_UINT_8(FLAG_C)
+#else
+#define OP_ASL() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_C = REGISTER_A << 1; \
+ FLAG_Z = REGISTER_A = MAKE_UINT_16(FLAG_C); \
+ FLAG_N = NFLAG_16(FLAG_C); \
+ FLAG_C = CFLAG_16(FLAG_C)
+#endif
+
+/* M6502 Arithmetic Shift Left operand */
+#undef OP_ASLM
+#if FLAG_SET_M
+#define OP_ASLM(MODE) \
+ CLK(CLK_OP + CLK_RMW8 + CLK_W_##MODE); \
+ DST = EA_##MODE(cpustate); \
+ FLAG_C = read_8_##MODE(DST) << 1; \
+ FLAG_N = FLAG_Z = MAKE_UINT_8(FLAG_C); \
+ write_8_##MODE(DST, FLAG_Z)
+#else
+#define OP_ASLM(MODE) \
+ CLK(CLK_OP + CLK_RMW16 + CLK_W_##MODE); \
+ DST = EA_##MODE(cpustate); \
+ FLAG_C = read_16_##MODE(DST) << 1; \
+ FLAG_Z = MAKE_UINT_16(FLAG_C); \
+ FLAG_N = NFLAG_16(FLAG_C); \
+ FLAG_C = CFLAG_16(FLAG_C); \
+ write_16_##MODE(DST, FLAG_Z)
+#endif
+
+/* M6502 Branch on Condition Code */
+#undef OP_BCC
+#define OP_BCC(COND) \
+ DST = OPER_8_IMM(cpustate); \
+ if(COND) \
+ { \
+ CLK(CLK_OP + CLK_RELATIVE_8 + 1); \
+ g65816i_branch_8(cpustate, DST); \
+ BREAKOUT; \
+ } \
+ CLK(CLK_OP + CLK_RELATIVE_8); \
+
+/* M6502 Set flags according to bits */
+#undef OP_BIT
+#if FLAG_SET_M
+#define OP_BIT(MODE) \
+ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \
+ FLAG_N = OPER_8_##MODE(cpustate); \
+ FLAG_Z = FLAG_N & REGISTER_A; \
+ FLAG_V = FLAG_N << 1
+#else
+#define OP_BIT(MODE) \
+ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \
+ FLAG_N = OPER_16_##MODE(cpustate); \
+ FLAG_Z = FLAG_N & REGISTER_A; \
+ FLAG_N = NFLAG_16(FLAG_N); \
+ FLAG_V = FLAG_N << 1
+#endif
+
+/* G65816 Set flags according to bits (immediate addressing mode) */
+#undef OP_BITI
+#if FLAG_SET_M
+#define OP_BITI() \
+ CLK(CLK_OP + CLK_R8 + CLK_IMM); \
+ FLAG_Z = REGISTER_A & OPER_8_IMM(cpustate)
+#else
+#define OP_BITI() \
+ CLK(CLK_OP + CLK_R16 + CLK_IMM); \
+ FLAG_Z = REGISTER_A & OPER_16_IMM(cpustate)
+#endif
+
+/* M6502 Cause a Break interrupt */
+#undef OP_BRK
+#define OP_BRK() \
+ REGISTER_PC++; \
+ g65816i_interrupt_software(cpustate, VECTOR_BRK)
+
+/* G65816 Branch Always */
+#undef OP_BRA
+#define OP_BRA() \
+ CLK(CLK_OP + CLK_IMPLIED + CLK_RELATIVE_8); \
+ g65816i_branch_8(cpustate, OPER_8_IMM(cpustate))
+
+/* G65816 Branch Always Long */
+#undef OP_BRL
+#define OP_BRL() \
+ CLK(CLK_OP + CLK_IMPLIED + CLK_RELATIVE_16); \
+ g65816i_branch_16(cpustate, OPER_16_IMM(cpustate))
+
+/* M6502 Clear Carry flag */
+#undef OP_CLC
+#define OP_CLC() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_C = CFLAG_CLEAR
+
+/* M6502 Clear Decimal flag */
+#undef OP_CLD
+#define OP_CLD() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_D = DFLAG_CLEAR
+
+/* M6502 Clear Interrupt Mask flag */
+#undef OP_CLI
+#define OP_CLI() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ g65816i_set_flag_i(cpustate, IFLAG_CLEAR)
+
+/* M6502 Clear oVerflow flag */
+#undef OP_CLV
+#define OP_CLV() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_V = VFLAG_CLEAR
+
+/* M6502 Compare operand to accumulator */
+/* Unusual behavior: C flag is inverted */
+#undef OP_CMP
+#if FLAG_SET_M
+#define OP_CMP(MODE) \
+ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \
+ FLAG_C = REGISTER_A - OPER_8_##MODE(cpustate); \
+ FLAG_N = FLAG_Z = MAKE_UINT_8(FLAG_C); \
+ FLAG_C ^= CFLAG_SET
+#else
+#define OP_CMP(MODE) \
+ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \
+ FLAG_C = REGISTER_A - OPER_16_##MODE(cpustate); \
+ FLAG_Z = MAKE_UINT_16(FLAG_C); \
+ FLAG_N = NFLAG_16(FLAG_C); \
+ FLAG_C = ~CFLAG_16(FLAG_C)
+#endif
+
+/* M6502 Compare operand to index register */
+/* Unusual behavior: C flag is inverted */
+#undef OP_CMPX
+#if FLAG_SET_X
+#define OP_CMPX(REG, MODE) \
+ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \
+ FLAG_C = REG - OPER_8_##MODE(cpustate); \
+ FLAG_N = FLAG_Z = MAKE_UINT_8(FLAG_C); \
+ FLAG_C ^= CFLAG_SET
+#else
+#define OP_CMPX(REG, MODE) \
+ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \
+ FLAG_C = REG - OPER_16_##MODE(cpustate); \
+ FLAG_Z = MAKE_UINT_16(FLAG_C); \
+ FLAG_N = NFLAG_16(FLAG_C); \
+ FLAG_C = ~CFLAG_16(FLAG_C)
+#endif
+
+/* G65816 Coprocessor operation */
+#undef OP_COP
+#define OP_COP() \
+ REGISTER_PC++; \
+ g65816i_interrupt_software(cpustate, VECTOR_COP)
+
+/* M6502 Decrement accumulator */
+#undef OP_DEC
+#if FLAG_SET_M
+#define OP_DEC() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_N = FLAG_Z = REGISTER_A = MAKE_UINT_8(REGISTER_A - 1)
+#else
+#define OP_DEC() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REGISTER_A = MAKE_UINT_16(REGISTER_A - 1); \
+ FLAG_N = NFLAG_16(REGISTER_A)
+#endif
+
+/* M6502 Decrement operand */
+#undef OP_DECM
+#if FLAG_SET_M
+#define OP_DECM(MODE) \
+ CLK(CLK_OP + CLK_RMW8 + CLK_W_##MODE); \
+ DST = EA_##MODE(cpustate); \
+ FLAG_N = FLAG_Z = MAKE_UINT_8(read_8_##MODE(DST) - 1); \
+ write_8_##MODE(DST, FLAG_Z)
+#else
+#define OP_DECM(MODE) \
+ CLK(CLK_OP + CLK_RMW16 + CLK_W_##MODE); \
+ DST = EA_##MODE(cpustate); \
+ FLAG_Z = MAKE_UINT_16(read_16_##MODE(DST) - 1); \
+ FLAG_N = NFLAG_16(FLAG_Z); \
+ write_16_##MODE(DST, FLAG_Z)
+#endif
+
+/* M6502 Decrement index register */
+#undef OP_DECX
+#if FLAG_SET_X
+#define OP_DECX(REG) \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_N = FLAG_Z = REG = MAKE_UINT_8(REG - 1)
+#else
+#define OP_DECX(REG) \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REG = MAKE_UINT_16(REG - 1); \
+ FLAG_N = NFLAG_16(REG)
+#endif
+
+/* M6502 Exclusive Or operand to accumulator */
+#undef OP_EOR
+#if FLAG_SET_M
+#define OP_EOR(MODE) \
+ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \
+ FLAG_N = FLAG_Z = REGISTER_A ^= OPER_8_##MODE(cpustate)
+#else
+#define OP_EOR(MODE) \
+ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \
+ FLAG_Z = REGISTER_A ^= OPER_16_##MODE(cpustate); \
+ FLAG_N = NFLAG_16(REGISTER_A)
+#endif
+
+/* M6502 Increment accumulator */
+#undef OP_INC
+#if FLAG_SET_M
+#define OP_INC() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_N = FLAG_Z = REGISTER_A = MAKE_UINT_8(REGISTER_A + 1)
+#else
+#define OP_INC() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REGISTER_A = MAKE_UINT_16(REGISTER_A + 1); \
+ FLAG_N = NFLAG_16(REGISTER_A)
+#endif
+
+/* M6502 Increment operand */
+#undef OP_INCM
+#if FLAG_SET_M
+#define OP_INCM(MODE) \
+ CLK(CLK_OP + CLK_RMW8 + CLK_W_##MODE); \
+ DST = EA_##MODE(cpustate); \
+ FLAG_N = FLAG_Z = MAKE_UINT_8(read_8_##MODE(DST) + 1); \
+ write_8_##MODE(DST, FLAG_Z)
+#else
+#define OP_INCM(MODE) \
+ CLK(CLK_OP + CLK_RMW16 + CLK_W_##MODE); \
+ DST = EA_##MODE(cpustate); \
+ FLAG_Z = MAKE_UINT_16(read_16_##MODE(DST) + 1); \
+ FLAG_N = NFLAG_16(FLAG_Z); \
+ write_16_##MODE(DST, FLAG_Z)
+#endif
+
+/* M6502 Increment index register */
+#undef OP_INCX
+#if FLAG_SET_X
+#define OP_INCX(REG) \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_N = FLAG_Z = REG = MAKE_UINT_8(REG + 1)
+#else
+#define OP_INCX(REG) \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REG = MAKE_UINT_16(REG + 1); \
+ FLAG_N = NFLAG_16(REG)
+#endif
+
+/* G65816 Jump Long */
+#undef OP_JMLAI
+#define OP_JMLAI() \
+ CLK(CLK_OP + CLK_AI + 1); \
+ g65816i_jump_24(cpustate, read_24_A(OPER_16_IMM(cpustate)))
+
+/* M6502 Jump */
+#undef OP_JMP
+#define OP_JMP(MODE) \
+ CLK(CLK_OP + CLK_##MODE); \
+ g65816i_jump_16(cpustate, EA_##MODE(cpustate))
+
+/* M6502 Jump absolute indexed indirect */
+#undef OP_JMPAXI
+#define OP_JMPAXI() \
+ CLK(CLK_OP + CLK_AXI); \
+ g65816i_jump_16(cpustate, read_16_AXI(REGISTER_PB | (MAKE_UINT_16(OPER_16_IMM(cpustate) + REGISTER_X))))
+
+/* G65816 Jump absolute long */
+#undef OP_JMPAL
+#define OP_JMPAL() \
+ CLK(CLK_OP + CLK_AL); \
+ g65816i_jump_24(cpustate, EA_AL(cpustate))
+
+/* G65816 Jump to Subroutine Long */
+/* Unusual behavior: stacks PC-1 */
+#undef OP_JSL
+#define OP_JSL(MODE) \
+ CLK(CLK_OP + CLK_W24 + CLK_##MODE + 1); \
+ DST = EA_##MODE(cpustate); \
+ g65816i_push_8(cpustate, REGISTER_PB>>16); \
+ g65816i_push_16(cpustate, REGISTER_PC-1); \
+ g65816i_jump_24(cpustate, DST)
+
+/* M6502 Jump to Subroutine */
+/* Unusual behavior: stacks PC-1 */
+#undef OP_JSR
+#define OP_JSR(MODE) \
+ CLK(CLK_OP + CLK_W16 + CLK_##MODE); \
+ DST = EA_##MODE(cpustate); \
+ g65816i_push_16(cpustate, REGISTER_PC-1); \
+ g65816i_jump_16(cpustate, DST)
+
+/* M6502 Jump to Subroutine */
+/* Unusual behavior: stacks PC-1 */
+#undef OP_JSRAXI
+#define OP_JSRAXI() \
+ CLK(CLK_OP + CLK_W16 + CLK_AXI); \
+ DST = read_16_AXI(REGISTER_PB | (MAKE_UINT_16(OPER_16_IMM(cpustate) + REGISTER_X))); \
+ g65816i_push_16(cpustate, REGISTER_PC-1); \
+ g65816i_jump_16(cpustate, DST)
+
+/* M6502 Load accumulator with operand */
+#undef OP_LDA
+#if FLAG_SET_M
+#define OP_LDA(MODE) \
+ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \
+ FLAG_N = FLAG_Z = REGISTER_A = OPER_8_##MODE(cpustate)
+#else
+#define OP_LDA(MODE) \
+ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \
+ FLAG_Z = REGISTER_A = OPER_16_##MODE(cpustate); \
+ FLAG_N = NFLAG_16(REGISTER_A)
+#endif
+
+/* M6502 Load index register with operand */
+#undef OP_LDX
+#if FLAG_SET_X
+#define OP_LDX(REG, MODE) \
+ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \
+ FLAG_N = FLAG_Z = REG = OPER_8_##MODE(cpustate)
+#else
+#define OP_LDX(REG, MODE) \
+ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \
+ FLAG_Z = REG = OPER_16_##MODE(cpustate); \
+ FLAG_N = NFLAG_16(REG)
+#endif
+
+/* M6502 Logical Shift Right accumulator */
+#undef OP_LSR
+#if FLAG_SET_M
+#define OP_LSR() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_N = 0; \
+ FLAG_C = REGISTER_A << 8; \
+ FLAG_Z = REGISTER_A >>= 1
+#else
+#define OP_LSR() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_N = 0; \
+ FLAG_C = REGISTER_A << 8; \
+ FLAG_Z = REGISTER_A >>= 1
+#endif
+
+/* M6502 Logical Shift Right operand */
+#undef OP_LSRM
+#if FLAG_SET_M
+#define OP_LSRM(MODE) \
+ CLK(CLK_OP + CLK_RMW8 + CLK_W_##MODE); \
+ DST = EA_##MODE(cpustate); \
+ FLAG_N = 0; \
+ FLAG_Z = read_8_##MODE(DST); \
+ FLAG_C = FLAG_Z << 8; \
+ FLAG_Z >>= 1; \
+ write_8_##MODE(DST, FLAG_Z)
+#else
+#define OP_LSRM(MODE) \
+ CLK(CLK_OP + CLK_RMW16 + CLK_W_##MODE); \
+ DST = EA_##MODE(cpustate); \
+ FLAG_N = 0; \
+ FLAG_Z = read_16_##MODE(DST); \
+ FLAG_C = FLAG_Z << 8; \
+ FLAG_Z >>= 1; \
+ write_16_##MODE(DST, FLAG_Z)
+#endif
+
+/* G65816 Move Block Negative */
+#undef OP_MVN
+#if FLAG_SET_M
+#if FLAG_SET_X
+#define OP_MVN() \
+ DST = OPER_8_IMM(cpustate)<<16; \
+ SRC = OPER_8_IMM(cpustate)<<16; \
+ REGISTER_DB = DST; \
+ CLK(7); \
+ write_8_NORM(DST | REGISTER_Y, read_8_NORM(SRC | REGISTER_X)); \
+ REGISTER_X = MAKE_UINT_8(REGISTER_X+1); \
+ REGISTER_Y = MAKE_UINT_8(REGISTER_Y+1); \
+ REGISTER_A--; \
+ REGISTER_A &= 0xff; \
+ if ((REGISTER_A&0xff) != 0xff) \
+ {\
+ REGISTER_PC -= 3; \
+ }\
+ else \
+ { \
+ REGISTER_B -= 0x100;\
+ REGISTER_B &= 0xff00; \
+ if ((REGISTER_B & 0xff00) != 0xff00)\
+ { \
+ REGISTER_PC -= 3;\
+ } \
+ }
+#else
+#define OP_MVN() \
+ DST = OPER_8_IMM(cpustate)<<16; \
+ SRC = OPER_8_IMM(cpustate)<<16; \
+ REGISTER_DB = DST; \
+ CLK(7); \
+ write_8_NORM(DST | REGISTER_Y, read_8_NORM(SRC | REGISTER_X)); \
+ REGISTER_X = MAKE_UINT_16(REGISTER_X+1); \
+ REGISTER_Y = MAKE_UINT_16(REGISTER_Y+1); \
+ REGISTER_A--; \
+ REGISTER_A &= 0xff; \
+ if ((REGISTER_A&0xff) != 0xff) \
+ {\
+ REGISTER_PC -= 3; \
+ }\
+ else \
+ { \
+ REGISTER_B -= 0x100;\
+ REGISTER_B &= 0xff00; \
+ if ((REGISTER_B & 0xff00) != 0xff00)\
+ { \
+ REGISTER_PC -= 3;\
+ } \
+ }
+#endif
+#else
+#if FLAG_SET_X
+#define OP_MVN() \
+ DST = OPER_8_IMM(cpustate)<<16; \
+ SRC = OPER_8_IMM(cpustate)<<16; \
+ REGISTER_DB = DST; \
+ REGISTER_A |= REGISTER_B; \
+ CLK(7); \
+ write_8_NORM(DST | REGISTER_Y, read_8_NORM(SRC | REGISTER_X)); \
+ REGISTER_X = MAKE_UINT_8(REGISTER_X+1); \
+ REGISTER_Y = MAKE_UINT_8(REGISTER_Y+1); \
+ REGISTER_A--; \
+ if ((REGISTER_A&0xffff) != 0xffff) \
+ {\
+ REGISTER_PC -= 3; \
+ }
+#else
+#define OP_MVN() \
+ DST = OPER_8_IMM(cpustate)<<16; \
+ SRC = OPER_8_IMM(cpustate)<<16; \
+ REGISTER_DB = DST; \
+ REGISTER_A |= REGISTER_B; \
+ CLK(7); \
+ write_8_NORM(DST | REGISTER_Y, read_8_NORM(SRC | REGISTER_X)); \
+ REGISTER_X = MAKE_UINT_16(REGISTER_X+1); \
+ REGISTER_Y = MAKE_UINT_16(REGISTER_Y+1); \
+ REGISTER_A--; \
+ if ((REGISTER_A&0xffff) != 0xffff) \
+ {\
+ REGISTER_PC -= 3; \
+ }
+#endif
+#endif
+
+/* G65816 Move Block Positive */
+#undef OP_MVP
+#if FLAG_SET_M
+#if FLAG_SET_X
+#define OP_MVP() \
+ DST = OPER_8_IMM(cpustate)<<16; \
+ SRC = OPER_8_IMM(cpustate)<<16; \
+ REGISTER_DB = DST; \
+ CLK(7); \
+ write_8_NORM(DST | REGISTER_Y, read_8_NORM(SRC | REGISTER_X)); \
+ REGISTER_X = MAKE_UINT_8(REGISTER_X-1); \
+ REGISTER_Y = MAKE_UINT_8(REGISTER_Y-1); \
+ REGISTER_A--; \
+ REGISTER_A &= 0xff; \
+ if ((REGISTER_A&0xff) != 0xff) \
+ {\
+ REGISTER_PC -= 3; \
+ }\
+ else \
+ { \
+ REGISTER_B -= 0x100;\
+ REGISTER_B &= 0xff00; \
+ if ((REGISTER_B & 0xff00) != 0xff00)\
+ { \
+ REGISTER_PC -= 3;\
+ } \
+ }
+#else
+#define OP_MVP() \
+ DST = OPER_8_IMM(cpustate)<<16; \
+ SRC = OPER_8_IMM(cpustate)<<16; \
+ REGISTER_DB = DST; \
+ CLK(7); \
+ write_8_NORM(DST | REGISTER_Y, read_8_NORM(SRC | REGISTER_X)); \
+ REGISTER_X = MAKE_UINT_16(REGISTER_X-1); \
+ REGISTER_Y = MAKE_UINT_16(REGISTER_Y-1); \
+ REGISTER_A--; \
+ REGISTER_A &= 0xff; \
+ if ((REGISTER_A&0xff) != 0xff) \
+ {\
+ REGISTER_PC -= 3; \
+ }\
+ else \
+ { \
+ REGISTER_B -= 0x100;\
+ REGISTER_B &= 0xff00; \
+ if ((REGISTER_B & 0xff00) != 0xff00)\
+ { \
+ REGISTER_PC -= 3;\
+ } \
+ }
+#endif
+#else
+#if FLAG_SET_X
+#define OP_MVP() \
+ DST = OPER_8_IMM(cpustate)<<16; \
+ SRC = OPER_8_IMM(cpustate)<<16; \
+ REGISTER_DB = DST; \
+ REGISTER_A |= REGISTER_B; \
+ CLK(7); \
+ write_8_NORM(DST | REGISTER_Y, read_8_NORM(SRC | REGISTER_X)); \
+ REGISTER_X = MAKE_UINT_8(REGISTER_X-1); \
+ REGISTER_Y = MAKE_UINT_8(REGISTER_Y-1); \
+ REGISTER_A--; \
+ if ((REGISTER_A&0xffff) != 0xffff) \
+ {\
+ REGISTER_PC -= 3; \
+ }
+#else
+#define OP_MVP() \
+ DST = OPER_8_IMM(cpustate)<<16; \
+ SRC = OPER_8_IMM(cpustate)<<16; \
+ REGISTER_DB = DST; \
+ REGISTER_A |= REGISTER_B; \
+ CLK(7); \
+ write_8_NORM(DST | REGISTER_Y, read_8_NORM(SRC | REGISTER_X)); \
+ REGISTER_X = MAKE_UINT_16(REGISTER_X-1); \
+ REGISTER_Y = MAKE_UINT_16(REGISTER_Y-1); \
+ REGISTER_A--; \
+ if ((REGISTER_A&0xffff) != 0xffff) \
+ {\
+ REGISTER_PC -= 3; \
+ }
+#endif
+#endif
+
+/* M6502 No Operation */
+#undef OP_NOP
+#define OP_NOP() \
+ CLK(CLK_OP + CLK_IMPLIED)
+
+/* M6502 Logical OR operand to accumulator */
+#undef OP_ORA
+#if FLAG_SET_M
+#define OP_ORA(MODE) \
+ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \
+ FLAG_N = FLAG_Z = REGISTER_A |= OPER_8_ ## MODE(cpustate)
+#else
+#define OP_ORA(MODE) \
+ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \
+ FLAG_Z = REGISTER_A |= OPER_16_##MODE(cpustate); \
+ FLAG_N = NFLAG_16(REGISTER_A)
+#endif
+
+/* G65816 Push Effective Address */
+#undef OP_PEA
+#define OP_PEA() \
+ CLK(CLK_OP + CLK_R16 + CLK_W16); \
+ g65816i_push_16(cpustate, OPER_16_IMM(cpustate))
+
+/* G65816 Push Effective Indirect Address */
+#undef OP_PEI
+#define OP_PEI() \
+ CLK(CLK_OP + CLK_R16 + CLK_W16 + CLK_D); \
+ g65816i_push_16(cpustate, EA_DI(cpustate))
+
+/* G65816 Push Effective PC-Relative Address */
+#undef OP_PER
+#define OP_PER() \
+ CLK(CLK_OP + CLK_R16 + CLK_W16 + 1); \
+ SRC = OPER_16_IMM(cpustate); \
+ g65816i_push_16(cpustate, REGISTER_PC + SRC)
+
+/* M6502 Push accumulator to the stack */
+#undef OP_PHA
+#if FLAG_SET_M
+#define OP_PHA() \
+ CLK(CLK_OP + CLK_W8 + 1); \
+ g65816i_push_8(cpustate, REGISTER_A)
+#else
+#define OP_PHA() \
+ CLK(CLK_OP + CLK_W16 + 1); \
+ g65816i_push_16(cpustate, REGISTER_A)
+#endif
+
+/* M6502 Push index register to the stack */
+#undef OP_PHX
+#if FLAG_SET_X
+#define OP_PHX(REG) \
+ CLK(CLK_OP + CLK_W8 + 1); \
+ g65816i_push_8(cpustate, REG)
+#else
+#define OP_PHX(REG) \
+ CLK(CLK_OP + CLK_W16 + 1); \
+ g65816i_push_16(cpustate, REG)
+#endif
+
+/* G65816 Push data bank register */
+#undef OP_PHB
+#define OP_PHB() \
+ CLK(CLK_OP + CLK_W8 + 1); \
+ g65816i_push_8(cpustate, REGISTER_DB>>16)
+
+/* G65816 Push direct register */
+#undef OP_PHD
+#define OP_PHD() \
+ CLK(CLK_OP + CLK_W16 + 1); \
+ g65816i_push_16(cpustate, REGISTER_D)
+
+/* G65816 Push program bank register */
+#undef OP_PHK
+#define OP_PHK() \
+ CLK(CLK_OP + CLK_W8 + 1); \
+ g65816i_push_8(cpustate, REGISTER_PB>>16)
+
+/* M6502 Push the Processor Status Register to the stack */
+#undef OP_PHP
+#define OP_PHP() \
+ CLK(CLK_OP + CLK_W8 + 1); \
+ g65816i_push_8(cpustate, g65816i_get_reg_p(cpustate))
+
+/* M6502 Pull accumulator from the stack */
+#undef OP_PLA
+#if FLAG_SET_M
+#define OP_PLA() \
+ CLK(CLK_OP + CLK_R8 + 2); \
+ FLAG_N = FLAG_Z = REGISTER_A = g65816i_pull_8(cpustate)
+#else
+#define OP_PLA() \
+ CLK(CLK_OP + CLK_R16 + 2); \
+ FLAG_Z = REGISTER_A = g65816i_pull_16(cpustate); \
+ FLAG_N = NFLAG_16(FLAG_Z)
+#endif
+
+/* M6502 Pull index register from the stack */
+#undef OP_PLX
+#if FLAG_SET_X
+#define OP_PLX(REG) \
+ CLK(CLK_OP + CLK_R8 + 2); \
+ FLAG_N = FLAG_Z = REG = g65816i_pull_8(cpustate)
+#else
+#define OP_PLX(REG) \
+ CLK(CLK_OP + CLK_R16 + 2); \
+ FLAG_Z = REG = g65816i_pull_16(cpustate); \
+ FLAG_N = NFLAG_16(FLAG_Z)
+#endif
+
+/* G65816 Pull data bank register */
+#undef OP_PLB
+#define OP_PLB() \
+ CLK(CLK_OP + CLK_R8 + 2); \
+ FLAG_N = FLAG_Z = g65816i_pull_8(cpustate); \
+ REGISTER_DB = FLAG_Z << 16
+
+/* G65816 Pull direct register */
+#undef OP_PLD
+#define OP_PLD() \
+ CLK(CLK_OP + CLK_R16 + 2); \
+ FLAG_Z = REGISTER_D = g65816i_pull_16(cpustate); \
+ FLAG_N = NFLAG_16(FLAG_Z)
+
+/* M6502 Pull the Processor Status Register from the stack */
+#undef OP_PLP
+#define OP_PLP() \
+ CLK(CLK_OP + CLK_R8 + 2); \
+ g65816i_set_reg_p(cpustate, g65816i_pull_8(cpustate))
+
+/* G65816 Reset Program status word */
+#undef OP_REP
+#define OP_REP() \
+ CLK(CLK_OP + CLK_R8 + 1); \
+ g65816i_set_reg_p(cpustate, g65816i_get_reg_p(cpustate) & ~OPER_8_IMM(cpustate))
+
+/* M6502 Rotate Left the accumulator */
+#undef OP_ROL
+#if FLAG_SET_M
+#define OP_ROL() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_C = (REGISTER_A<<1) | CFLAG_AS_1(); \
+ FLAG_N = FLAG_Z = REGISTER_A = MAKE_UINT_8(FLAG_C)
+#else
+#define OP_ROL() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_C = (REGISTER_A<<1) | CFLAG_AS_1(); \
+ FLAG_Z = REGISTER_A = MAKE_UINT_16(FLAG_C); \
+ FLAG_N = NFLAG_16(FLAG_C); \
+ FLAG_C = CFLAG_16(FLAG_C)
+#endif
+
+/* M6502 Rotate Left an operand */
+#undef OP_ROLM
+#if FLAG_SET_M
+#define OP_ROLM(MODE) \
+ CLK(CLK_OP + CLK_RMW8 + CLK_W_##MODE); \
+ DST = EA_##MODE(cpustate); \
+ FLAG_C = (read_8_##MODE(DST)<<1) | CFLAG_AS_1(); \
+ FLAG_N = FLAG_Z = MAKE_UINT_8(FLAG_C); \
+ write_8_##MODE(DST, FLAG_Z)
+#else
+#define OP_ROLM(MODE) \
+ CLK(CLK_OP + CLK_RMW16 + CLK_W_##MODE); \
+ DST = EA_##MODE(cpustate); \
+ FLAG_C = (read_16_##MODE(DST)<<1) | CFLAG_AS_1(); \
+ FLAG_Z = MAKE_UINT_16(FLAG_C); \
+ FLAG_N = NFLAG_16(FLAG_C); \
+ FLAG_C = CFLAG_16(FLAG_C); \
+ write_16_##MODE(DST, FLAG_Z)
+#endif
+
+/* M6502 Rotate Right the accumulator */
+#undef OP_ROR
+#if FLAG_SET_M
+#define OP_ROR() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ REGISTER_A |= FLAG_C & 0x100; \
+ FLAG_C = REGISTER_A << 8; \
+ FLAG_N = FLAG_Z = REGISTER_A >>= 1
+#else
+#define OP_ROR() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ REGISTER_A |= (FLAG_C<<8) & 0x10000; \
+ FLAG_C = REGISTER_A << 8; \
+ FLAG_Z = REGISTER_A >>= 1; \
+ FLAG_N = NFLAG_16(REGISTER_A)
+#endif
+
+/* M6502 Rotate Right an operand */
+#undef OP_RORM
+#if FLAG_SET_M
+#define OP_RORM(MODE) \
+ CLK(CLK_OP + CLK_RMW8 + CLK_W_##MODE); \
+ DST = EA_##MODE(cpustate); \
+ FLAG_Z = read_8_##MODE(DST) | (FLAG_C & 0x100); \
+ FLAG_C = FLAG_Z << 8; \
+ FLAG_N = FLAG_Z >>= 1; \
+ write_8_##MODE(DST, FLAG_Z)
+#else
+#define OP_RORM(MODE) \
+ CLK(CLK_OP + CLK_RMW16 + CLK_W_##MODE); \
+ DST = EA_##MODE(cpustate); \
+ FLAG_Z = read_16_##MODE(DST) | ((FLAG_C<<8) & 0x10000); \
+ FLAG_C = FLAG_Z << 8; \
+ FLAG_Z >>= 1; \
+ FLAG_N = NFLAG_16(FLAG_Z); \
+ write_16_##MODE(DST, FLAG_Z)
+#endif
+
+/* M6502 Return from Interrupt */
+#undef OP_RTI
+#if FLAG_SET_E
+#define OP_RTI() \
+ CLK(7); \
+ g65816i_set_reg_p(cpustate, g65816i_pull_8(cpustate)); \
+ g65816i_jump_16(cpustate, g65816i_pull_16(cpustate))
+#else
+#define OP_RTI() \
+ CLK(8); \
+ g65816i_set_reg_p(cpustate, g65816i_pull_8(cpustate)); \
+ g65816i_jump_16(cpustate, g65816i_pull_16(cpustate)); \
+ REGISTER_PB = g65816i_pull_8(cpustate) << 16
+#endif
+
+/* G65816 Return from Subroutine Long */
+/* Unusual behavior: Gets PC and increments */
+#undef OP_RTL
+#define OP_RTL() \
+ CLK(6); \
+ g65816i_jump_24(cpustate, g65816i_pull_24(cpustate))
+
+/* M6502 Return from Subroutine */
+/* Unusual behavior: Gets PC and increments */
+#undef OP_RTS
+#define OP_RTS() \
+ CLK(6); \
+ g65816i_jump_16(cpustate, g65816i_pull_16(cpustate)+1)
+
+/* M6502 Subtract with Carry */
+/* Unusual behavior: C flag is inverted */
+#undef OP_SBC
+#if FLAG_SET_M
+#define OP_SBC(MODE) \
+ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \
+ SRC = OPER_8_##MODE(cpustate); \
+ if(!FLAG_D) \
+ { \
+ FLAG_C = ~FLAG_C; \
+ FLAG_C = REGISTER_A - SRC - CFLAG_AS_1(); \
+ FLAG_V = VFLAG_SUB_8(SRC, REGISTER_A, FLAG_C); \
+ FLAG_N = FLAG_Z = REGISTER_A = MAKE_UINT_8(FLAG_C); \
+ FLAG_C = ~FLAG_C; \
+ BREAKOUT; \
+ } \
+ else \
+ { \
+ INT32 result, r0, r1, carry; \
+ r0 = REGISTER_A; \
+ r1 = SRC; \
+ r1 ^= 0xff; \
+ carry = CFLAG_AS_1(); \
+ result = (r0 & 0x0f) + (r1 & 0x0f) + (carry << 0); \
+ if (result <= 0x0f) result -= 0x06; \
+ carry = result > 0x0f; \
+ result = (r0 & 0xf0) + (r1 & 0xf0) + (carry << 4) + (result & 0x0f); \
+ FLAG_V = ~(r0 ^ r1) & (r0 ^ result) & 0x80; \
+ if (result <= 0xff) result -= 0x60; \
+ FLAG_C = (result > 0xff) ? 0x100 : 0; \
+ FLAG_N = (result & 0x80); \
+ FLAG_Z = REGISTER_A = MAKE_UINT_8(result); \
+ }
+#else
+#define OP_SBC(MODE) \
+ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \
+ SRC = OPER_16_##MODE(cpustate); \
+ INT32 result, r0, r1, carry; \
+ r0 = REGISTER_A; \
+ r1 = SRC; \
+ r1 ^= 0xffff; \
+ carry = CFLAG_AS_1(); \
+ if (!FLAG_D) \
+ { \
+ result = r0 + r1 + carry; \
+ } \
+ else \
+ { \
+ result = (r0 & 0x000f) + (r1 & 0x000f) + (carry << 0); \
+ if(result <= 0x000f) result -= 0x0006; \
+ carry = result > 0x000f; \
+ result = (r0 & 0x00f0) + (r1 & 0x00f0) + (carry << 4) + (result & 0x000f); \
+ if(result <= 0x00ff) result -= 0x0060; \
+ carry = result > 0x00ff; \
+ result = (r0 & 0x0f00) + (r1 & 0x0f00) + (carry << 8) + (result & 0x00ff); \
+ if(result <= 0x0fff) result -= 0x0600; \
+ carry = result > 0x0fff; \
+ result = (r0 & 0xf000) + (r1 & 0xf000) + (carry << 12) + (result & 0x0fff); \
+ } \
+ FLAG_V = ~(r0 ^ r1) & (r0 ^ result) & 0x8000; \
+ FLAG_V >>= 8; \
+ if (FLAG_D && result <= 0xffff) result -= 0x6000; \
+ FLAG_C = (result > 0xffff) ? 0x100 : 0; \
+ FLAG_Z = REGISTER_A = MAKE_UINT_16(result); \
+ FLAG_N = NFLAG_16(REGISTER_A);
+#endif
+
+
+/* M6502 Set Carry flag */
+#undef OP_SEC
+#define OP_SEC() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_C = CFLAG_SET
+
+/* M6502 Set Decimal flag */
+#undef OP_SED
+#define OP_SED() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_D = DFLAG_SET
+
+/* M6502 Set Interrupt Mask flag */
+#undef OP_SEI
+#define OP_SEI() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ g65816i_set_flag_i(cpustate, IFLAG_SET)
+
+/* G65816 Set Program status word */
+#undef OP_SEP
+#define OP_SEP() \
+ CLK(CLK_OP + CLK_R8 + 1); \
+ g65816i_set_reg_p(cpustate, g65816i_get_reg_p(cpustate) | OPER_8_IMM(cpustate))
+
+/* M6502 Store accumulator to memory */
+#undef OP_STA
+#if FLAG_SET_M
+#define OP_STA(MODE) \
+ CLK(CLK_OP + CLK_W8 + CLK_W_##MODE); \
+ write_8_##MODE(EA_##MODE(cpustate), REGISTER_A)
+#else
+#define OP_STA(MODE) \
+ CLK(CLK_OP + CLK_W16 + CLK_W_##MODE); \
+ write_16_##MODE(EA_##MODE(cpustate), REGISTER_A)
+#endif
+
+/* M6502 Store index register to memory */
+#undef OP_STX
+#if FLAG_SET_X
+#define OP_STX(REG, MODE) \
+ CLK(CLK_OP + CLK_W8 + CLK_W_##MODE); \
+ write_8_##MODE(EA_##MODE(cpustate), REG)
+#else
+#define OP_STX(REG, MODE) \
+ CLK(CLK_OP + CLK_W16 + CLK_W_##MODE); \
+ write_16_##MODE(EA_##MODE(cpustate), REG)
+#endif
+
+/* M6502 Store zero to memory */
+#undef OP_STZ
+#if FLAG_SET_M
+#define OP_STZ(MODE) \
+ CLK(CLK_OP + CLK_W8 + CLK_W_##MODE); \
+ write_8_##MODE(EA_##MODE(cpustate), 0)
+#else
+#define OP_STZ(MODE) \
+ CLK(CLK_OP + CLK_W16 + CLK_W_##MODE); \
+ write_16_##MODE(EA_##MODE(cpustate), 0)
+#endif
+
+/* G65816 Stop the clock */
+#undef OP_STP
+#define OP_STP() \
+ USE_ALL_CLKS(); \
+ CPU_STOPPED |= STOP_LEVEL_STOP
+
+/* M6502 Transfer accumulator to index */
+#undef OP_TAX
+#if FLAG_SET_M
+#if FLAG_SET_X
+#define OP_TAX(REG) \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REG = REGISTER_A; \
+ FLAG_N = NFLAG_8(FLAG_Z)
+#else /* FLAG_SET_X */
+#define OP_TAX(REG) \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REG = REGISTER_B | REGISTER_A; \
+ FLAG_N = NFLAG_16(FLAG_Z)
+#endif /* FLAG_SET_X */
+#else /* FLAG_SET_M */
+#if FLAG_SET_X
+#define OP_TAX(REG) \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REG = MAKE_UINT_8(REGISTER_A); \
+ FLAG_N = NFLAG_8(FLAG_Z)
+#else /* FLAG_SET_X */
+#define OP_TAX(REG) \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REG = REGISTER_A; \
+ FLAG_N = NFLAG_16(FLAG_Z)
+#endif /* FLAG_SET_X */
+#endif /* FLAG_SET_M */
+
+
+/* M6502 Transfer index to accumulator */
+#undef OP_TXA
+#if FLAG_SET_M
+#define OP_TXA(REG) \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REGISTER_A = MAKE_UINT_8(REG); \
+ FLAG_N = NFLAG_8(FLAG_Z)
+#else
+#define OP_TXA(REG) \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REGISTER_A = REG; \
+ FLAG_N = NFLAG_16(FLAG_Z)
+#endif
+
+/* G65816 Transfer C to direct register */
+#undef OP_TCD
+#if FLAG_SET_M
+#define OP_TCD() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REGISTER_D = REGISTER_A | REGISTER_B; \
+ FLAG_N = NFLAG_16(FLAG_Z)
+#else
+#define OP_TCD() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REGISTER_D = REGISTER_A; \
+ FLAG_N = NFLAG_16(FLAG_Z)
+#endif
+
+/* G65816 Transfer direct register to C */
+#undef OP_TDC
+#if FLAG_SET_M
+#define OP_TDC() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REGISTER_D; \
+ FLAG_N = NFLAG_16(FLAG_Z); \
+ REGISTER_A = MAKE_UINT_8(REGISTER_D); \
+ REGISTER_B = REGISTER_D & 0xff00
+#else
+#define OP_TDC() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REGISTER_A = REGISTER_D; \
+ FLAG_N = NFLAG_16(FLAG_Z)
+#endif
+
+/* G65816 Transfer C to stack pointer */
+#undef OP_TCS
+#if FLAG_SET_E
+#define OP_TCS() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ REGISTER_S = MAKE_UINT_8(REGISTER_A) | 0x100
+#else
+#define OP_TCS() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ REGISTER_S = REGISTER_A | REGISTER_B
+#endif
+
+/* G65816 Transfer stack pointer to C */
+#undef OP_TSC
+#if FLAG_SET_M
+#define OP_TSC() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REGISTER_S; \
+ FLAG_N = NFLAG_16(FLAG_Z); \
+ REGISTER_A = MAKE_UINT_8(REGISTER_S); \
+ REGISTER_B = REGISTER_S & 0xff00
+#else
+#define OP_TSC() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REGISTER_A = REGISTER_S; \
+ FLAG_N = NFLAG_16(FLAG_Z)
+#endif
+
+/* M6502 Transfer stack pointer to X */
+#undef OP_TSX
+#if FLAG_SET_X
+#define OP_TSX() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REGISTER_X = MAKE_UINT_8(REGISTER_S); \
+ FLAG_N = NFLAG_8(FLAG_Z)
+#else
+#define OP_TSX() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REGISTER_X = REGISTER_S; \
+ FLAG_N = NFLAG_16(FLAG_Z)
+#endif
+
+/* M6502 Transfer X to stack pointer */
+#undef OP_TXS
+#if FLAG_SET_E
+#define OP_TXS() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ REGISTER_S = MAKE_UINT_8(REGISTER_X) | 0x100
+#else
+#define OP_TXS() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ REGISTER_S = REGISTER_X
+#endif
+
+/* G65816 Transfer X to Y */
+#undef OP_TXY
+#if FLAG_SET_X
+#define OP_TXY() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REGISTER_Y = REGISTER_X; \
+ FLAG_N = NFLAG_8(FLAG_Z)
+#else
+#define OP_TXY() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REGISTER_Y = REGISTER_X; \
+ FLAG_N = NFLAG_16(FLAG_Z)
+#endif
+
+/* G65816 Transfer Y to X */
+#undef OP_TYX
+#if FLAG_SET_X
+#define OP_TYX() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REGISTER_X = REGISTER_Y; \
+ FLAG_N = NFLAG_8(FLAG_Z)
+#else
+#define OP_TYX() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REGISTER_X = REGISTER_Y; \
+ FLAG_N = NFLAG_16(FLAG_Z)
+#endif
+
+/* G65816 Test and reset bit */
+#undef OP_TRB
+#if FLAG_SET_M
+#define OP_TRB(MODE) \
+ CLK(CLK_OP + CLK_RMW8 + CLK_W_##MODE); \
+ DST = EA_##MODE(cpustate); \
+ FLAG_Z = read_8_##MODE(DST); \
+ write_8_##MODE(DST, FLAG_Z & ~REGISTER_A); \
+ FLAG_Z &= REGISTER_A
+#else
+#define OP_TRB(MODE) \
+ CLK(CLK_OP + CLK_RMW16 + CLK_W_##MODE); \
+ DST = EA_##MODE(cpustate); \
+ FLAG_Z = read_16_##MODE(DST); \
+ write_16_##MODE(DST, FLAG_Z & ~REGISTER_A); \
+ FLAG_Z &= REGISTER_A
+#endif
+
+/* G65816 Test and set bit */
+#undef OP_TSB
+#if FLAG_SET_M
+#define OP_TSB(MODE) \
+ CLK(CLK_OP + CLK_RMW8 + CLK_W_##MODE); \
+ DST = EA_##MODE(cpustate); \
+ FLAG_Z = read_8_##MODE(DST); \
+ write_8_##MODE(DST, FLAG_Z | REGISTER_A); \
+ FLAG_Z &= REGISTER_A
+#else
+#define OP_TSB(MODE) \
+ CLK(CLK_OP + CLK_RMW16 + CLK_W_##MODE); \
+ DST = EA_##MODE(cpustate); \
+ FLAG_Z = read_16_##MODE(DST); \
+ write_16_##MODE(DST, FLAG_Z | REGISTER_A); \
+ FLAG_Z &= REGISTER_A
+#endif
+
+/* G65816 Wait for interrupt */
+#undef OP_WAI
+#define OP_WAI() \
+ USE_ALL_CLKS(); \
+ CPU_STOPPED |= STOP_LEVEL_WAI
+
+/* G65816 William D. Mensch, JR. (65816 designer) - future expansion */
+#undef OP_WDM
+#define OP_WDM() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ REGISTER_PC++
+
+/* G65816 Exchange accum high and low bytes */
+#undef OP_XBA
+#if FLAG_SET_M
+#define OP_XBA() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REGISTER_B>>8; \
+ REGISTER_B = REGISTER_A<<8; \
+ REGISTER_A = FLAG_Z; \
+ FLAG_N = NFLAG_8(FLAG_Z)
+#else
+#define OP_XBA() \
+ CLK(CLK_OP + CLK_IMPLIED + 1); \
+ FLAG_Z = REGISTER_A >> 8; \
+ REGISTER_A = MAKE_UINT_16(REGISTER_A<<8) | FLAG_Z; \
+ FLAG_N = NFLAG_8(FLAG_Z)
+#endif
+
+/* G65816 Exchange carry and emulation bits */
+#undef OP_XCE
+#define OP_XCE() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ SRC = CFLAG_AS_1(); \
+ FLAG_C = FLAG_E<<8; \
+ g65816i_set_flag_e(cpustate, SRC)
+
+
+
+
+/* ======================================================================== */
+/* ======================== OPCODE & FUNCTION TABLES ====================== */
+/* ======================================================================== */
+
+#undef OP
+#undef O
+#undef TABLE_OPCODES
+#undef TABLE_FUNCTION
+
+#if FLAG_SET_E
+#define OP(CODE, OPERATION) static void g65816i_ ## CODE ## _E(g65816i_cpu_struct *cpustate) {OPERATION;}
+#define O(CODE) g65816i_ ## CODE ## _E
+#define TABLE_OPCODES void (*const g65816i_opcodes_E[256])(g65816i_cpu_struct *cpustate)
+#define TABLE_FUNCTION(RTYPE, NAME, ARGS) RTYPE g65816i_ ## NAME ## _E ARGS
+
+#else
+
+#if !FLAG_SET_M && !FLAG_SET_X
+#define OP(CODE, OPERATION) static void g65816i_ ## CODE ## _M0X0(g65816i_cpu_struct *cpustate) {OPERATION;}
+#define O(CODE) g65816i_ ## CODE ## _M0X0
+#define TABLE_OPCODES void (*const g65816i_opcodes_M0X0[256])(g65816i_cpu_struct *cpustate)
+#define TABLE_FUNCTION(RTYPE, NAME, ARGS) RTYPE g65816i_ ## NAME ## _M0X0 ARGS
+
+#elif !FLAG_SET_M && FLAG_SET_X
+
+#define OP(CODE, OPERATION) static void g65816i_ ## CODE ## _M0X1(g65816i_cpu_struct *cpustate) {OPERATION;}
+#define O(CODE) g65816i_ ## CODE ## _M0X1
+#define TABLE_OPCODES void (*const g65816i_opcodes_M0X1[256])(g65816i_cpu_struct *cpustate)
+#define TABLE_FUNCTION(RTYPE, NAME, ARGS) RTYPE g65816i_ ## NAME ## _M0X1 ARGS
+
+#elif FLAG_SET_M && !FLAG_SET_X
+
+#define OP(CODE, OPERATION) static void g65816i_ ## CODE ## _M1X0(g65816i_cpu_struct *cpustate) {OPERATION;}
+#define O(CODE) g65816i_ ## CODE ## _M1X0
+#define TABLE_OPCODES void (*const g65816i_opcodes_M1X0[256])(g65816i_cpu_struct *cpustate)
+#define TABLE_FUNCTION(RTYPE, NAME, ARGS) RTYPE g65816i_ ## NAME ## _M1X0 ARGS
+
+#elif FLAG_SET_M && FLAG_SET_X
+
+#define OP(CODE, OPERATION) static void g65816i_ ## CODE ## _M1X1(g65816i_cpu_struct *cpustate) {OPERATION;}
+#define O(CODE) g65816i_ ## CODE ## _M1X1
+#define TABLE_OPCODES void (*const g65816i_opcodes_M1X1[256])(g65816i_cpu_struct *cpustate)
+#define TABLE_FUNCTION(RTYPE, NAME, ARGS) RTYPE g65816i_ ## NAME ## _M1X1 ARGS
+
+#endif
+#endif
+#define BREAKOUT return
+
+
+
+/* OP FUNCTION Comment */
+OP(00, OP_BRK ( ) ) /* BRK */
+OP(01, OP_ORA ( DXI ) ) /* ORA dxi */
+OP(02, OP_COP ( ) ) /* COP (G) */
+OP(03, OP_ORA ( S ) ) /* ORA s (G) */
+OP(04, OP_TSB ( D ) ) /* TSB d (C) */
+OP(05, OP_ORA ( D ) ) /* ORA d */
+OP(06, OP_ASLM ( D ) ) /* ASL d */
+OP(07, OP_ORA ( DLI ) ) /* ORA dli (G) */
+OP(08, OP_PHP ( ) ) /* PHP */
+OP(09, OP_ORA ( IMM ) ) /* ORA imm */
+OP(0a, OP_ASL ( ) ) /* ASL acc */
+OP(0b, OP_PHD ( ) ) /* PHD (G) */
+OP(0c, OP_TSB ( A ) ) /* TSB a (C) */
+OP(0d, OP_ORA ( A ) ) /* ORA a */
+OP(0e, OP_ASLM ( A ) ) /* ASL a */
+OP(0f, OP_ORA ( AL ) ) /* ORA al (G) */
+OP(10, OP_BCC ( COND_PL() ) ) /* BPL */
+OP(11, OP_ORA ( DIY ) ) /* ORA diy */
+OP(12, OP_ORA ( DI ) ) /* ORA di (C) */
+OP(13, OP_ORA ( SIY ) ) /* ORA siy (G) */
+OP(14, OP_TRB ( D ) ) /* TRB d (C) */
+OP(15, OP_ORA ( DX ) ) /* ORA dx */
+OP(16, OP_ASLM ( DX ) ) /* ASL dx */
+OP(17, OP_ORA ( DLIY ) ) /* ORA dliy(C) */
+OP(18, OP_CLC ( ) ) /* CLC */
+OP(19, OP_ORA ( AY ) ) /* ORA ay */
+OP(1a, OP_INC ( ) ) /* INA (C) */
+OP(1b, OP_TCS ( ) ) /* TCS (G) */
+OP(1c, OP_TRB ( A ) ) /* TRB a (C) */
+OP(1d, OP_ORA ( AX ) ) /* ORA ax */
+OP(1e, OP_ASLM ( AX ) ) /* ASL ax */
+OP(1f, OP_ORA ( ALX ) ) /* ORA alx (G) */
+OP(20, OP_JSR ( A ) ) /* JSR a */
+OP(21, OP_AND ( DXI ) ) /* AND dxi */
+OP(22, OP_JSL ( AL ) ) /* JSL al (G) */
+OP(23, OP_AND ( S ) ) /* AND s (G) */
+OP(24, OP_BIT ( D ) ) /* BIT d */
+OP(25, OP_AND ( D ) ) /* AND d */
+OP(26, OP_ROLM ( D ) ) /* ROL d */
+OP(27, OP_AND ( DLI ) ) /* AND dli (G) */
+OP(28, OP_PLP ( ) ) /* PLP */
+OP(29, OP_AND ( IMM ) ) /* AND imm */
+OP(2a, OP_ROL ( ) ) /* ROL acc */
+OP(2b, OP_PLD ( ) ) /* PLD (G) */
+OP(2c, OP_BIT ( A ) ) /* BIT a */
+OP(2d, OP_AND ( A ) ) /* AND a */
+OP(2e, OP_ROLM ( A ) ) /* ROL a */
+OP(2f, OP_AND ( AL ) ) /* AND al (G) */
+OP(30, OP_BCC ( COND_MI() ) ) /* BMI */
+OP(31, OP_AND ( DIY ) ) /* AND diy */
+OP(32, OP_AND ( DI ) ) /* AND di (C) */
+OP(33, OP_AND ( SIY ) ) /* AND siy */
+OP(34, OP_BIT ( DX ) ) /* BIT dx (C) */
+OP(35, OP_AND ( DX ) ) /* AND dx */
+OP(36, OP_ROLM ( DX ) ) /* ROL dx */
+OP(37, OP_AND ( DLIY ) ) /* AND dliy(G) */
+OP(38, OP_SEC ( ) ) /* SEC */
+OP(39, OP_AND ( AY ) ) /* AND ay */
+OP(3a, OP_DEC ( ) ) /* DEA (C) */
+OP(3b, OP_TSC ( ) ) /* TSC (G) */
+OP(3c, OP_BIT ( AX ) ) /* BIT abx (C) */
+OP(3d, OP_AND ( AX ) ) /* AND ax */
+OP(3e, OP_ROLM ( AX ) ) /* ROL ax */
+OP(3f, OP_AND ( ALX ) ) /* AND alx (G) */
+OP(40, OP_RTI ( ) ) /* RTI */
+OP(41, OP_EOR ( DXI ) ) /* EOR dxi */
+OP(42, OP_WDM ( ) ) /* WDM */
+OP(43, OP_EOR ( S ) ) /* EOR s (G) */
+OP(44, OP_MVP ( ) ) /* MVP (G) */
+OP(45, OP_EOR ( D ) ) /* EOR d */
+OP(46, OP_LSRM ( D ) ) /* LSR d */
+OP(47, OP_EOR ( DLI ) ) /* EOR dli (G) */
+OP(48, OP_PHA ( ) ) /* PHA */
+OP(49, OP_EOR ( IMM ) ) /* EOR imm */
+OP(4a, OP_LSR ( ) ) /* LSR acc */
+OP(4b, OP_PHK ( ) ) /* PHK (G) */
+OP(4c, OP_JMP ( A ) ) /* JMP a */
+OP(4d, OP_EOR ( A ) ) /* EOR a */
+OP(4e, OP_LSRM ( A ) ) /* LSR a */
+OP(4f, OP_EOR ( AL ) ) /* EOR al (G) */
+OP(50, OP_BCC ( COND_VC() ) ) /* BVC */
+OP(51, OP_EOR ( DIY ) ) /* EOR diy */
+OP(52, OP_EOR ( DI ) ) /* EOR di (C) */
+OP(53, OP_EOR ( SIY ) ) /* EOR siy (G) */
+OP(54, OP_MVN ( ) ) /* MVN (G) */
+OP(55, OP_EOR ( DX ) ) /* EOR dx */
+OP(56, OP_LSRM ( DX ) ) /* LSR dx */
+OP(57, OP_EOR ( DLIY ) ) /* EOR dliy(G) */
+OP(58, OP_CLI ( ) ) /* CLI */
+OP(59, OP_EOR ( AY ) ) /* EOR ay */
+OP(5a, OP_PHX ( REGISTER_Y ) ) /* PHY (C) */
+OP(5b, OP_TCD ( ) ) /* TCD (G) */
+OP(5c, OP_JMPAL( ) ) /* JMP al (G) */
+OP(5d, OP_EOR ( AX ) ) /* EOR ax */
+OP(5e, OP_LSRM ( AX ) ) /* LSR ax */
+OP(5f, OP_EOR ( ALX ) ) /* EOR alx (G) */
+OP(60, OP_RTS ( ) ) /* RTS */
+OP(61, OP_ADC ( DXI ) ) /* ADC dxi */
+OP(62, OP_PER ( ) ) /* PER (G) */
+OP(63, OP_ADC ( S ) ) /* ADC s (G) */
+OP(64, OP_STZ ( D ) ) /* STZ d (C) */
+OP(65, OP_ADC ( D ) ) /* ADC d */
+OP(66, OP_RORM ( D ) ) /* ROR d */
+OP(67, OP_ADC ( DLI ) ) /* ADC dli (G) */
+OP(68, OP_PLA ( ) ) /* PLA */
+OP(69, OP_ADC ( IMM ) ) /* ADC imm */
+OP(6a, OP_ROR ( ) ) /* ROR acc */
+OP(6b, OP_RTL ( ) ) /* RTL (G) */
+OP(6c, OP_JMP ( AI ) ) /* JMP ai */
+OP(6d, OP_ADC ( A ) ) /* ADC a */
+OP(6e, OP_RORM ( A ) ) /* ROR a */
+OP(6f, OP_ADC ( AL ) ) /* ADC al (G) */
+OP(70, OP_BCC ( COND_VS() ) ) /* BVS */
+OP(71, OP_ADC ( DIY ) ) /* ADC diy */
+OP(72, OP_ADC ( DI ) ) /* ADC di (G) */
+OP(73, OP_ADC ( SIY ) ) /* ADC siy (G) */
+OP(74, OP_STZ ( DX ) ) /* STZ dx (C) */
+OP(75, OP_ADC ( DX ) ) /* ADC dx */
+OP(76, OP_RORM ( DX ) ) /* ROR dx */
+OP(77, OP_ADC ( DLIY ) ) /* ADC dliy(G) */
+OP(78, OP_SEI ( ) ) /* SEI */
+OP(79, OP_ADC ( AY ) ) /* ADC ay */
+OP(7a, OP_PLX ( REGISTER_Y ) ) /* PLY (C) */
+OP(7b, OP_TDC ( ) ) /* TDC (G) */
+OP(7c, OP_JMPAXI( ) ) /* JMP axi (C) */
+OP(7d, OP_ADC ( AX ) ) /* ADC ax */
+OP(7e, OP_RORM ( AX ) ) /* ROR ax */
+OP(7f, OP_ADC ( ALX ) ) /* ADC alx (G) */
+OP(80, OP_BRA ( ) ) /* BRA (C) */
+OP(81, OP_STA ( DXI ) ) /* STA dxi */
+OP(82, OP_BRL ( ) ) /* BRL (G) */
+OP(83, OP_STA ( S ) ) /* STA s (G) */
+OP(84, OP_STX ( REGISTER_Y, D ) ) /* STY d */
+OP(85, OP_STA ( D ) ) /* STA d */
+OP(86, OP_STX ( REGISTER_X, D ) ) /* STX d */
+OP(87, OP_STA ( DLI ) ) /* STA dli (G) */
+OP(88, OP_DECX ( REGISTER_Y ) ) /* DEY */
+OP(89, OP_BITI ( ) ) /* BIT imm (C) */
+OP(8a, OP_TXA ( REGISTER_X ) ) /* TXA */
+OP(8b, OP_PHB ( ) ) /* PHB (G) */
+OP(8c, OP_STX ( REGISTER_Y, A ) ) /* STY a */
+OP(8d, OP_STA ( A ) ) /* STA a */
+OP(8e, OP_STX ( REGISTER_X, A ) ) /* STX a */
+OP(8f, OP_STA ( AL ) ) /* STA al (G) */
+OP(90, OP_BCC ( COND_CC() ) ) /* BCC */
+OP(91, OP_STA ( DIY ) ) /* STA diy */
+OP(92, OP_STA ( DI ) ) /* STA di (C) */
+OP(93, OP_STA ( SIY ) ) /* STA siy (G) */
+OP(94, OP_STX ( REGISTER_Y, DX ) ) /* STY dx */
+OP(95, OP_STA ( DX ) ) /* STA dx */
+OP(96, OP_STX ( REGISTER_X, DY ) ) /* STX dy */
+OP(97, OP_STA ( DLIY ) ) /* STA dliy(G) */
+OP(98, OP_TXA ( REGISTER_Y ) ) /* TYA */
+OP(99, OP_STA ( AY ) ) /* STA ay */
+OP(9a, OP_TXS ( ) ) /* TXS */
+OP(9b, OP_TXY ( ) ) /* TXY (G) */
+OP(9c, OP_STZ ( A ) ) /* STZ a (C) */
+OP(9d, OP_STA ( AX ) ) /* STA ax */
+OP(9e, OP_STZ ( AX ) ) /* STZ ax (C) */
+OP(9f, OP_STA ( ALX ) ) /* STA alx (G) */
+OP(a0, OP_LDX ( REGISTER_Y, IMM ) ) /* LDY imm */
+OP(a1, OP_LDA ( DXI ) ) /* LDA dxi */
+OP(a2, OP_LDX ( REGISTER_X, IMM ) ) /* LDX imm */
+OP(a3, OP_LDA ( S ) ) /* LDA s (G) */
+OP(a4, OP_LDX ( REGISTER_Y, D ) ) /* LDY d */
+OP(a5, OP_LDA ( D ) ) /* LDA d */
+OP(a6, OP_LDX ( REGISTER_X, D ) ) /* LDX d */
+OP(a7, OP_LDA ( DLI ) ) /* LDA dli (G) */
+OP(a8, OP_TAX ( REGISTER_Y ) ) /* TAY */
+OP(a9, OP_LDA ( IMM ) ) /* LDA imm */
+OP(aa, OP_TAX ( REGISTER_X ) ) /* TAX */
+OP(ab, OP_PLB ( ) ) /* PLB (G) */
+OP(ac, OP_LDX ( REGISTER_Y, A ) ) /* LDY a */
+OP(ad, OP_LDA ( A ) ) /* LDA a */
+OP(ae, OP_LDX ( REGISTER_X, A ) ) /* LDX a */
+OP(af, OP_LDA ( AL ) ) /* LDA al (G) */
+OP(b0, OP_BCC ( COND_CS() ) ) /* BCS */
+OP(b1, OP_LDA ( DIY ) ) /* LDA diy */
+OP(b2, OP_LDA ( DI ) ) /* LDA di (C) */
+OP(b3, OP_LDA ( SIY ) ) /* LDA siy (G) */
+OP(b4, OP_LDX ( REGISTER_Y, DX ) ) /* LDY dx */
+OP(b5, OP_LDA ( DX ) ) /* LDA dx */
+OP(b6, OP_LDX ( REGISTER_X, DY ) ) /* LDX dy */
+OP(b7, OP_LDA ( DLIY ) ) /* LDA dliy(G) */
+OP(b8, OP_CLV ( ) ) /* CLV */
+OP(b9, OP_LDA ( AY ) ) /* LDA ay */
+OP(ba, OP_TSX ( ) ) /* TSX */
+OP(bb, OP_TYX ( ) ) /* TYX (G) */
+OP(bc, OP_LDX ( REGISTER_Y, AX ) ) /* LDY ax */
+OP(bd, OP_LDA ( AX ) ) /* LDA ax */
+OP(be, OP_LDX ( REGISTER_X, AY ) ) /* LDX ay */
+OP(bf, OP_LDA ( ALX ) ) /* LDA alx (G) */
+OP(c0, OP_CMPX ( REGISTER_Y, IMM ) ) /* CPY imm */
+OP(c1, OP_CMP ( DXI ) ) /* CMP dxi */
+OP(c2, OP_REP ( ) ) /* REP (G) */
+OP(c3, OP_CMP ( S ) ) /* CMP s (G) */
+OP(c4, OP_CMPX ( REGISTER_Y, D ) ) /* CPY d */
+OP(c5, OP_CMP ( D ) ) /* CMP d */
+OP(c6, OP_DECM ( D ) ) /* DEC d */
+OP(c7, OP_CMP ( DLI ) ) /* CMP dli (G) */
+OP(c8, OP_INCX ( REGISTER_Y ) ) /* INY */
+OP(c9, OP_CMP ( IMM ) ) /* CMP imm */
+OP(ca, OP_DECX ( REGISTER_X ) ) /* DEX */
+OP(cb, OP_WAI ( ) ) /* WAI (G) */
+OP(cc, OP_CMPX ( REGISTER_Y, A ) ) /* CPY a */
+OP(cd, OP_CMP ( A ) ) /* CMP a */
+OP(ce, OP_DECM ( A ) ) /* DEC a */
+OP(cf, OP_CMP ( AL ) ) /* CMP al (G) */
+OP(d0, OP_BCC ( COND_NE() ) ) /* BNE */
+OP(d1, OP_CMP ( DIY ) ) /* CMP diy */
+OP(d2, OP_CMP ( DI ) ) /* CMP di (C) */
+OP(d3, OP_CMP ( SIY ) ) /* CMP siy (G) */
+OP(d4, OP_PEI ( ) ) /* PEI (G) */
+OP(d5, OP_CMP ( DX ) ) /* CMP dx */
+OP(d6, OP_DECM ( DX ) ) /* DEC dx */
+OP(d7, OP_CMP ( DLIY ) ) /* CMP dliy(G) */
+OP(d8, OP_CLD ( ) ) /* CLD */
+OP(d9, OP_CMP ( AY ) ) /* CMP ay */
+OP(da, OP_PHX ( REGISTER_X ) ) /* PHX (C) */
+OP(db, OP_STP ( ) ) /* STP (G) */
+OP(dc, OP_JMLAI( ) ) /* JML ai (G) */
+OP(dd, OP_CMP ( AX ) ) /* CMP ax */
+OP(de, OP_DECM ( AX ) ) /* DEC ax */
+OP(df, OP_CMP ( ALX ) ) /* CMP alx (G) */
+OP(e0, OP_CMPX ( REGISTER_X, IMM ) ) /* CPX imm */
+OP(e1, OP_SBC ( DXI ) ) /* SBC dxi */
+OP(e2, OP_SEP ( ) ) /* SEP imm (G) */
+OP(e3, OP_SBC ( S ) ) /* SBC s (G) */
+OP(e4, OP_CMPX ( REGISTER_X, D ) ) /* CPX d */
+OP(e5, OP_SBC ( D ) ) /* SBC d */
+OP(e6, OP_INCM ( D ) ) /* INC d */
+OP(e7, OP_SBC ( DLI ) ) /* SBC dli (G) */
+OP(e8, OP_INCX ( REGISTER_X ) ) /* INX */
+OP(e9, OP_SBC ( IMM ) ) /* SBC imm */
+OP(ea, OP_NOP ( ) ) /* NOP */
+OP(eb, OP_XBA ( ) ) /* XBA (G) */
+OP(ec, OP_CMPX ( REGISTER_X, A ) ) /* CPX a */
+OP(ed, OP_SBC ( A ) ) /* SBC a */
+OP(ee, OP_INCM ( A ) ) /* INC a */
+OP(ef, OP_SBC ( AL ) ) /* SBC al (G) */
+OP(f0, OP_BCC ( COND_EQ() ) ) /* BEQ */
+OP(f1, OP_SBC ( DIY ) ) /* SBC diy */
+OP(f2, OP_SBC ( DI ) ) /* SBC di (C) */
+OP(f3, OP_SBC ( SIY ) ) /* SBC siy (G) */
+OP(f4, OP_PEA ( ) ) /* PEA (G) */
+OP(f5, OP_SBC ( DX ) ) /* SBC dx */
+OP(f6, OP_INCM ( DX ) ) /* INC dx */
+OP(f7, OP_SBC ( DLIY ) ) /* SBC dliy(G) */
+OP(f8, OP_SED ( ) ) /* SED */
+OP(f9, OP_SBC ( AY ) ) /* SBC ay */
+OP(fa, OP_PLX ( REGISTER_X ) ) /* PLX (C) */
+OP(fb, OP_XCE ( ) ) /* XCE (G) */
+OP(fc, OP_JSRAXI( ) ) /* JSR axi (G) */
+OP(fd, OP_SBC ( AX ) ) /* SBC ax */
+OP(fe, OP_INCM ( AX ) ) /* INC ax */
+OP(ff, OP_SBC ( ALX ) ) /* SBC alx (G) */
+
+
+
+extern TABLE_OPCODES;
+TABLE_OPCODES =
+{
+ O(00),O(01),O(02),O(03),O(04),O(05),O(06),O(07),
+ O(08),O(09),O(0a),O(0b),O(0c),O(0d),O(0e),O(0f),
+ O(10),O(11),O(12),O(13),O(14),O(15),O(16),O(17),
+ O(18),O(19),O(1a),O(1b),O(1c),O(1d),O(1e),O(1f),
+ O(20),O(21),O(22),O(23),O(24),O(25),O(26),O(27),
+ O(28),O(29),O(2a),O(2b),O(2c),O(2d),O(2e),O(2f),
+ O(30),O(31),O(32),O(33),O(34),O(35),O(36),O(37),
+ O(38),O(39),O(3a),O(3b),O(3c),O(3d),O(3e),O(3f),
+ O(40),O(41),O(42),O(43),O(44),O(45),O(46),O(47),
+ O(48),O(49),O(4a),O(4b),O(4c),O(4d),O(4e),O(4f),
+ O(50),O(51),O(52),O(53),O(54),O(55),O(56),O(57),
+ O(58),O(59),O(5a),O(5b),O(5c),O(5d),O(5e),O(5f),
+ O(60),O(61),O(62),O(63),O(64),O(65),O(66),O(67),
+ O(68),O(69),O(6a),O(6b),O(6c),O(6d),O(6e),O(6f),
+ O(70),O(71),O(72),O(73),O(74),O(75),O(76),O(77),
+ O(78),O(79),O(7a),O(7b),O(7c),O(7d),O(7e),O(7f),
+ O(80),O(81),O(82),O(83),O(84),O(85),O(86),O(87),
+ O(88),O(89),O(8a),O(8b),O(8c),O(8d),O(8e),O(8f),
+ O(90),O(91),O(92),O(93),O(94),O(95),O(96),O(97),
+ O(98),O(99),O(9a),O(9b),O(9c),O(9d),O(9e),O(9f),
+ O(a0),O(a1),O(a2),O(a3),O(a4),O(a5),O(a6),O(a7),
+ O(a8),O(a9),O(aa),O(ab),O(ac),O(ad),O(ae),O(af),
+ O(b0),O(b1),O(b2),O(b3),O(b4),O(b5),O(b6),O(b7),
+ O(b8),O(b9),O(ba),O(bb),O(bc),O(bd),O(be),O(bf),
+ O(c0),O(c1),O(c2),O(c3),O(c4),O(c5),O(c6),O(c7),
+ O(c8),O(c9),O(ca),O(cb),O(cc),O(cd),O(ce),O(cf),
+ O(d0),O(d1),O(d2),O(d3),O(d4),O(d5),O(d6),O(d7),
+ O(d8),O(d9),O(da),O(db),O(dc),O(dd),O(de),O(df),
+ O(e0),O(e1),O(e2),O(e3),O(e4),O(e5),O(e6),O(e7),
+ O(e8),O(e9),O(ea),O(eb),O(ec),O(ed),O(ee),O(ef),
+ O(f0),O(f1),O(f2),O(f3),O(f4),O(f5),O(f6),O(f7),
+ O(f8),O(f9),O(fa),O(fb),O(fc),O(fd),O(fe),O(ff)
+};
+
+
+
+/* Assert or clear a line on the CPU */
+TABLE_FUNCTION(void, set_line, (g65816i_cpu_struct *cpustate, int line, int state))
+{
+ switch(line)
+ {
+ case G65816_LINE_IRQ:
+ switch(state)
+ {
+ case CLEAR_LINE:
+ LINE_IRQ = 0;
+ return;
+ case ASSERT_LINE:
+ case HOLD_LINE:
+ LINE_IRQ = 1;
+ }
+ if(FLAG_I)
+ {
+ if(CPU_STOPPED & STOP_LEVEL_WAI)
+ {
+ CPU_STOPPED &= ~STOP_LEVEL_WAI;
+ }
+ return;
+ }
+ return;
+ case G65816_LINE_NMI:
+ if(state == CLEAR_LINE)
+ {
+ LINE_NMI = 0;
+ return;
+ }
+ if(!LINE_NMI)
+ {
+ LINE_NMI = 1;
+ CPU_STOPPED &= ~STOP_LEVEL_WAI;
+ if(!CPU_STOPPED)
+ g65816i_interrupt_nmi(cpustate);
+ }
+ return;
+ case G65816_LINE_SO:
+ FLAG_V = VFLAG_SET;
+ break;
+ case G65816_LINE_RESET:
+ case G65816_LINE_ABORT:
+ case G65816_LINE_RDY:
+ return;
+ }
+
+ LINE_IRQ=1;
+}
+
+
+
+/* Get a register from the CPU core */
+TABLE_FUNCTION(uint, get_reg, (g65816i_cpu_struct *cpustate, int regnum))
+{
+ switch(regnum)
+ {
+ case G65816_A: return REGISTER_B | REGISTER_A;
+ case G65816_X: return REGISTER_X;
+ case G65816_Y: return REGISTER_Y;
+ case STATE_GENSP: return REGISTER_S;
+ case G65816_S: return REGISTER_S;
+ case STATE_GENPC: return REGISTER_PC;
+ case G65816_PC: return REGISTER_PC;
+ case G65816_PB: return REGISTER_PB >> 16;
+ case G65816_DB: return REGISTER_DB >> 16;
+ case G65816_D: return REGISTER_D;
+ case G65816_P: return g65816i_get_reg_p(cpustate);
+ case G65816_NMI_STATE: return LINE_NMI;
+ case G65816_IRQ_STATE: return LINE_IRQ;
+ case STATE_GENPCBASE: return REGISTER_PPC;
+ }
+ return 0;
+}
+
+
+
+TABLE_FUNCTION(void, set_reg, (g65816i_cpu_struct *cpustate, int regnum, uint val))
+{
+ switch(regnum)
+ {
+ case STATE_GENPC: case G65816_PC: REGISTER_PC = MAKE_UINT_16(val); break;
+#if FLAG_SET_E
+ case STATE_GENSP: case G65816_S: REGISTER_S = MAKE_UINT_8(val) | 0x100; break;
+#else
+ case STATE_GENSP: case G65816_S: REGISTER_S = MAKE_UINT_16(val); break;
+#endif
+ case G65816_P: g65816i_set_reg_p(cpustate, val); break;
+#if FLAG_SET_M
+ case G65816_A: REGISTER_A = MAKE_UINT_8(val); REGISTER_B = val&0xff00; break;
+#else
+ case G65816_A: REGISTER_A = MAKE_UINT_16(val); break;
+#endif
+#if FLAG_SET_X
+ case G65816_X: REGISTER_X = MAKE_UINT_8(val); break;
+ case G65816_Y: REGISTER_Y = MAKE_UINT_8(val); break;
+#else
+ case G65816_X: REGISTER_X = MAKE_UINT_16(val); break;
+ case G65816_Y: REGISTER_Y = MAKE_UINT_16(val); break;
+#endif
+ case G65816_DB: REGISTER_DB = MAKE_UINT_8(val); break;
+ case G65816_PB: REGISTER_PB = MAKE_UINT_8(val); break;
+ case G65816_NMI_STATE: FTABLE_SET_LINE(cpustate, G65816_LINE_NMI, val == 0 ? CLEAR_LINE : ASSERT_LINE); break;
+ case G65816_IRQ_STATE: FTABLE_SET_LINE(cpustate, G65816_LINE_IRQ, val == 0 ? CLEAR_LINE : ASSERT_LINE); break;
+ }
+}
+
+
+
+INLINE int g65816i_correct_mode(g65816i_cpu_struct *cpustate)
+{
+#if EXECUTION_MODE == EXECUTION_MODE_E
+ return (FLAG_E == EFLAG_SET);
+#elif EXECUTION_MODE == EXECUTION_MODE_M0X0
+ return (FLAG_E == EFLAG_CLEAR) && (FLAG_M == MFLAG_CLEAR) && (FLAG_X == XFLAG_CLEAR);
+#elif EXECUTION_MODE == EXECUTION_MODE_M0X1
+ return (FLAG_E == EFLAG_CLEAR) && (FLAG_M == MFLAG_CLEAR) && (FLAG_X == XFLAG_SET);
+#elif EXECUTION_MODE == EXECUTION_MODE_M1X0
+ return (FLAG_E == EFLAG_CLEAR) && (FLAG_M == MFLAG_SET) && (FLAG_X == XFLAG_CLEAR);
+#elif EXECUTION_MODE == EXECUTION_MODE_M1X1
+ return (FLAG_E == EFLAG_CLEAR) && (FLAG_M == MFLAG_SET) && (FLAG_X == XFLAG_SET);
+#else
+#error Invalid EXECUTION_MODE
+#endif
+}
+
+
+
+TABLE_FUNCTION(int, execute, (g65816i_cpu_struct *cpustate, int clocks))
+{
+ // do a check here also in case we're in STOP_WAI mode - this'll clear it when the IRQ happens
+ g65816i_check_maskable_interrupt(cpustate);
+
+ if (!CPU_STOPPED)
+ {
+ CLOCKS = clocks;
+ do
+ {
+ /* Note that I'm doing a per-instruction interrupt
+ * check until this core is working well enough
+ * to start trying fancy stuff.
+ */
+ g65816i_check_maskable_interrupt(cpustate);
+
+ REGISTER_PPC = REGISTER_PC;
+ G65816_CALL_DEBUGGER(REGISTER_PB | REGISTER_PC);
+
+ REGISTER_PC++;
+ REGISTER_IR = read_8_IMM(REGISTER_PB | REGISTER_PPC);
+ FTABLE_OPCODES[REGISTER_IR](cpustate);
+ } while((CLOCKS > 0) && g65816i_correct_mode(cpustate));
+ return clocks - CLOCKS;
+ }
+ return clocks;
+}
diff --git a/trunk/src/emu/cpu/h6280/6280dasm.c b/trunk/src/emu/cpu/h6280/6280dasm.c
new file mode 100644
index 00000000000..e20f831766f
--- /dev/null
+++ b/trunk/src/emu/cpu/h6280/6280dasm.c
@@ -0,0 +1,248 @@
+/*****************************************************************************
+
+ 6280dasm.c Hudsonsoft Hu6280 (HuC6280/Hu6280a) disassembler
+
+ Copyright Bryan McPhail, mish@tendril.co.uk
+
+ This source code is based (with permission!) on the 6502 emulator by
+ Juergen Buchmueller. It is released as part of the Mame emulator project.
+ Let me know if you intend to use this code in any other project.
+
+
+ Notes relating to Mame:
+
+ The dasm window shows 'real' memory, as executed by the cpu
+ The data windows show 'physical' memory, as defined in the memory map
+
+******************************************************************************/
+
+#include "emu.h"
+
+#define RDOP(addr) (oprom[addr - pc])
+#define RDBYTE(addr) (opram[addr - pc])
+#define RDWORD(addr) (opram[addr - pc] | ( oprom[(addr) + 1 - pc] << 8 ))
+
+enum addr_mode {
+ _non=0, /* no additional arguments */
+ _acc, /* accumulator */
+ _imp, /* implicit */
+ _imm, /* immediate */
+ _abs, /* absolute */
+ _zpg, /* zero page */
+ _zpx, /* zero page + X */
+ _zpy, /* zero page + Y */
+ _zpi, /* zero page indirect */
+ _abx, /* absolute + X */
+ _aby, /* absolute + Y */
+ _rel, /* relative */
+ _idx, /* zero page pre indexed */
+ _idy, /* zero page post indexed */
+ _ind, /* indirect */
+ _iax, /* indirect + X */
+ _blk, /* block */
+ _zrl, /* zero page relative */
+ _imz, /* immediate, zero page */
+ _izx, /* immediate, zero page + X */
+ _ima, /* immediate, absolute */
+ _imx /* immediate, absolute + X */
+};
+
+enum opcodes {
+
+ /* 6502 opcodes */
+ _adc=0,_and, _asl, _bcc, _bcs, _beq, _bit, _bmi,
+ _bne, _bpl, _brk, _bvc, _bvs, _clc, _cld, _cli,
+ _clv, _cmp, _cpx, _cpy, _dec, _dex, _dey, _eor,
+ _inc, _inx, _iny, _jmp, _jsr, _lda, _ldx, _ldy,
+ _lsr, _nop, _ora, _pha, _php, _pla, _plp, _rol,
+ _ror, _rti, _rts, _sbc, _sec, _sed, _sei, _sta,
+ _stx, _sty, _tax, _tay, _tsx, _txa, _txs, _tya,
+ _ill,
+
+ /* Hu6280 extensions */
+ _bra, _stz, _trb, _tsb, _dea, _ina, _sax, _bsr,
+ _phx, _phy, _plx, _ply, _csh, _csl, _tam, _tma,
+ _cla, _cly, _clx, _st0, _st1, _st2, _tst, _set,
+ _tdd, _tia, _tii, _tin, _tai, _say, _sxy,
+
+ _sm0, _sm1, _sm2, _sm3, _sm4, _sm5, _sm6, _sm7,
+ _rm0, _rm1, _rm2, _rm3, _rm4, _rm5, _rm6, _rm7,
+
+ _bs0, _bs1, _bs2, _bs3, _bs4, _bs5, _bs6, _bs7,
+ _br0, _br1, _br2, _br3, _br4, _br5, _br6, _br7
+
+};
+
+
+static const char *const token[]=
+{
+ /* 6502 opcodes */
+ "adc", "and", "asl", "bcc", "bcs", "beq", "bit", "bmi",
+ "bne", "bpl", "brk", "bvc", "bvs", "clc", "cld", "cli",
+ "clv", "cmp", "cpx", "cpy", "dec", "dex", "dey", "eor",
+ "inc", "inx", "iny", "jmp", "jsr", "lda", "ldx", "ldy",
+ "lsr", "nop", "ora", "pha", "php", "pla", "plp", "rol",
+ "ror", "rti", "rts", "sbc", "sec", "sed", "sei", "sta",
+ "stx", "sty", "tax", "tay", "tsx", "txa", "txs", "tya",
+ "ill",
+
+ /* Hu6280 extensions */
+ "bra", "stz", "trb", "tsb", "dea", "ina", "sax", "bsr",
+ "phx", "phy", "plx", "ply", "csh", "csl", "tam", "tma",
+ "cla", "cly", "clx", "st0", "st1", "st2", "tst", "set",
+ "tdd", "tia", "tii", "tin", "tai", "say", "sxy",
+
+ "smb0", "smb1", "smb2", "smb3", "smb4", "smb5", "smb6", "smb7",
+ "rmb0", "rmb1", "rmb2", "rmb3", "rmb4", "rmb5", "rmb6", "rmb7",
+
+ "bbs0", "bbs1", "bbs2", "bbs3", "bbs4", "bbs5", "bbs6", "bbs7",
+ "bbr0", "bbr1", "bbr2", "bbr3", "bbr4", "bbr5", "bbr6", "bbr7"
+};
+
+static const unsigned char op6280[512]=
+{
+ _brk,_imp, _ora,_idx, _sxy,_imp, _st0,_imm, _tsb,_zpg, _ora,_zpg, _asl,_zpg, _rm0,_zpg, /* 00 */
+ _php,_imp, _ora,_imm, _asl,_acc, _ill,_non, _tsb,_abs, _ora,_abs, _asl,_abs, _br0,_zrl,
+ _bpl,_rel, _ora,_idy, _ora,_zpi, _st1,_imm, _trb,_zpg, _ora,_zpx, _asl,_zpx, _rm1,_zpg, /* 10 */
+ _clc,_imp, _ora,_aby, _ina,_imp, _ill,_non, _trb,_abs, _ora,_abx, _asl,_abx, _br1,_zrl,
+ _jsr,_abs, _and,_idx, _sax,_imp, _st2,_imm, _bit,_zpg, _and,_zpg, _rol,_zpg, _rm2,_zpg, /* 20 */
+ _plp,_imp, _and,_imm, _rol,_acc, _ill,_non, _bit,_abs, _and,_abs, _rol,_abs, _br2,_zrl,
+ _bmi,_rel, _and,_idy, _and,_zpi, _ill,_non, _bit,_zpx, _and,_zpx, _rol,_zpx, _rm3,_zpg, /* 30 */
+ _sec,_imp, _and,_aby, _dea,_imp, _ill,_non, _bit,_abx, _and,_abx, _rol,_abx, _br3,_zrl,
+ _rti,_imp, _eor,_idx, _say,_imp, _tma,_imm, _bsr,_rel, _eor,_zpg, _lsr,_zpg, _rm4,_zpg, /* 40 */
+ _pha,_imp, _eor,_imm, _lsr,_acc, _ill,_non, _jmp,_abs, _eor,_abs, _lsr,_abs, _br4,_zrl,
+ _bvc,_rel, _eor,_idy, _eor,_zpi, _tam,_imm, _csl,_imp, _eor,_zpx, _lsr,_zpx, _rm5,_zpg, /* 50 */
+ _cli,_imp, _eor,_aby, _phy,_imp, _ill,_non, _ill,_non, _eor,_abx, _lsr,_abx, _br5,_zrl,
+ _rts,_imp, _adc,_idx, _cla,_imp, _ill,_non, _stz,_zpg, _adc,_zpg, _ror,_zpg, _rm6,_zpg, /* 60 */
+ _pla,_imp, _adc,_imm, _ror,_acc, _ill,_non, _jmp,_ind, _adc,_abs, _ror,_abs, _br6,_zrl,
+ _bvs,_rel, _adc,_idy, _adc,_zpi, _tii,_blk, _stz,_zpx, _adc,_zpx, _ror,_zpx, _rm7,_zpg, /* 70 */
+ _sei,_imp, _adc,_aby, _ply,_imp, _ill,_non, _jmp,_iax, _adc,_abx, _ror,_abx, _br7,_zrl,
+ _bra,_rel, _sta,_idx, _clx,_imp, _tst,_imz, _sty,_zpg, _sta,_zpg, _stx,_zpg, _sm0,_zpg, /* 80 */
+ _dey,_imp, _bit,_imm, _txa,_imp, _ill,_non, _sty,_abs, _sta,_abs, _stx,_abs, _bs0,_zrl,
+ _bcc,_rel, _sta,_idy, _sta,_zpi, _tst,_ima, _sty,_zpx, _sta,_zpx, _stx,_zpy, _sm1,_zpg, /* 90 */
+ _tya,_imp, _sta,_aby, _txs,_imp, _ill,_non, _stz,_abs, _sta,_abx, _stz,_abx, _bs1,_zrl,
+ _ldy,_imm, _lda,_idx, _ldx,_imm, _tst,_izx, _ldy,_zpg, _lda,_zpg, _ldx,_zpg, _sm2,_zpg, /* a0 */
+ _tay,_imp, _lda,_imm, _tax,_imp, _ill,_non, _ldy,_abs, _lda,_abs, _ldx,_abs, _bs2,_zrl,
+ _bcs,_rel, _lda,_idy, _lda,_zpi, _tst,_imx, _ldy,_zpx, _lda,_zpx, _ldx,_zpy, _sm3,_zpg, /* b0 */
+ _clv,_imp, _lda,_aby, _tsx,_imp, _ill,_non, _ldy,_abx, _lda,_abx, _ldx,_aby, _bs3,_zrl,
+ _cpy,_imm, _cmp,_idx, _cly,_imp, _tdd,_blk, _cpy,_zpg, _cmp,_zpg, _dec,_zpg, _sm4,_zpg, /* c0 */
+ _iny,_imp, _cmp,_imm, _dex,_imp, _ill,_non, _cpy,_abs, _cmp,_abs, _dec,_abs, _bs4,_zrl,
+ _bne,_rel, _cmp,_idy, _cmp,_zpi, _tin,_blk, _csh,_imp, _cmp,_zpx, _dec,_zpx, _sm5,_zpg, /* d0 */
+ _cld,_imp, _cmp,_aby, _phx,_imp, _ill,_non, _ill,_non, _cmp,_abx, _dec,_abx, _bs5,_zrl,
+ _cpx,_imm, _sbc,_idx, _ill,_non, _tia,_blk, _cpx,_zpg, _sbc,_zpg, _inc,_zpg, _sm6,_zpg, /* e0 */
+ _inx,_imp, _sbc,_imm, _nop,_imp, _ill,_non, _cpx,_abs, _sbc,_abs, _inc,_abs, _bs6,_zrl,
+ _beq,_rel, _sbc,_idy, _sbc,_zpi, _tai,_blk, _set,_imp, _sbc,_zpx, _inc,_zpx, _sm7,_zpg, /* f0 */
+ _sed,_imp, _sbc,_aby, _plx,_imp, _ill,_non, _ill,_non, _sbc,_abx, _inc,_abx, _bs7,_zrl
+};
+
+/*****************************************************************************
+ * Disassemble a single command and return the number of bytes it uses.
+ *****************************************************************************/
+CPU_DISASSEMBLE( h6280 )
+{
+ UINT32 flags = 0;
+ int PC, OP, opc, arg;
+
+ PC = pc;
+ OP = RDOP(PC);
+ OP = OP << 1;
+ PC++;
+
+ opc = op6280[OP];
+ arg = op6280[OP+1];
+
+ if (opc == _jsr || opc == _bsr)
+ flags = DASMFLAG_STEP_OVER;
+ else if (opc == _rts)
+ flags = DASMFLAG_STEP_OUT;
+
+ switch(arg)
+ {
+ case _acc:
+ sprintf(buffer,"%-5sa", token[opc]);
+ break;
+ case _imp:
+ sprintf(buffer,"%s", token[opc]);
+ break;
+ case _rel:
+ sprintf(buffer,"%-5s$%04X", token[opc], (PC + 1 + (signed char)RDBYTE(PC)) & 0xffff);
+ PC+=1;
+ break;
+ case _imm:
+ sprintf(buffer,"%-5s#$%02X", token[opc], RDBYTE(PC));
+ PC+=1;
+ break;
+ case _zpg:
+ sprintf(buffer,"%-5s$%02X", token[opc], RDBYTE(PC));
+ PC+=1;
+ break;
+ case _zpx:
+ sprintf(buffer,"%-5s$%02X,x", token[opc], RDBYTE(PC));
+ PC+=1;
+ break;
+ case _zpy:
+ sprintf(buffer,"%-5s$%02X,y", token[opc], RDBYTE(PC));
+ PC+=1;
+ break;
+ case _idx:
+ sprintf(buffer,"%-5s($%02X,x)", token[opc], RDBYTE(PC));
+ PC+=1;
+ break;
+ case _idy:
+ sprintf(buffer,"%-5s($%02X),y", token[opc], RDBYTE(PC));
+ PC+=1;
+ break;
+ case _zpi:
+ sprintf(buffer,"%-5s($%02X)", token[opc], RDBYTE(PC));
+ PC+=1;
+ break;
+ case _abs:
+ sprintf(buffer,"%-5s$%04X", token[opc], RDWORD(PC));
+ PC+=2;
+ break;
+ case _abx:
+ sprintf(buffer,"%-5s$%04X,x", token[opc], RDWORD(PC));
+ PC+=2;
+ break;
+ case _aby:
+ sprintf(buffer,"%-5s$%04X,y", token[opc], RDWORD(PC));
+ PC+=2;
+ break;
+ case _ind:
+ sprintf(buffer,"%-5s($%04X)", token[opc], RDWORD(PC));
+ PC+=2;
+ break;
+ case _iax:
+ sprintf(buffer,"%-5s($%04X),X", token[opc], RDWORD(PC));
+ PC+=2;
+ break;
+ case _blk:
+ sprintf(buffer,"%-5s$%04X $%04X $%04X", token[opc], RDWORD(PC), RDWORD(PC+2), RDWORD(PC+4));
+ PC+=6;
+ break;
+ case _zrl:
+ sprintf(buffer,"%-5s$%02X $%04X", token[opc], RDBYTE(PC), (PC + 2 + (signed char)RDBYTE(PC+1)) & 0xffff);
+ PC+=2;
+ break;
+ case _imz:
+ sprintf(buffer,"%-5s#$%02X $%02X", token[opc], RDBYTE(PC), RDBYTE(PC+1));
+ PC+=2;
+ break;
+ case _izx:
+ sprintf(buffer,"%-5s#$%02X $%02X,x", token[opc], RDBYTE(PC), RDBYTE(PC+1));
+ PC+=2;
+ break;
+ case _ima:
+ sprintf(buffer,"%-5s#$%02X $%04X", token[opc], RDBYTE(PC), RDWORD(PC+1));
+ PC+=3;
+ break;
+ case _imx:
+ sprintf(buffer,"%-5s#$%02X $%04X,x", token[opc], RDBYTE(PC), RDWORD(PC+1));
+ PC+=3;
+ break;
+
+ default:
+ sprintf(buffer,"%-5s$%02X", token[opc], OP >> 1);
+ }
+ return (PC - pc) | flags | DASMFLAG_SUPPORTED;
+}
diff --git a/trunk/src/emu/cpu/h6280/h6280.c b/trunk/src/emu/cpu/h6280/h6280.c
new file mode 100644
index 00000000000..24f918c8b4e
--- /dev/null
+++ b/trunk/src/emu/cpu/h6280/h6280.c
@@ -0,0 +1,535 @@
+/*****************************************************************************
+
+ h6280.c - Portable HuC6280 emulator
+
+ Copyright Bryan McPhail, mish@tendril.co.uk
+
+ This source code is based (with permission!) on the 6502 emulator by
+ Juergen Buchmueller. It is released as part of the Mame emulator project.
+ Let me know if you intend to use this code in any other project.
+
+
+ NOTICE:
+
+ This code is around 99% complete! Several things are unimplemented,
+ some due to lack of time, some due to lack of documentation, mainly
+ due to lack of programs using these features.
+
+ csh, csl opcodes are not supported.
+
+ I am unsure if flag B is set upon execution of rti.
+
+ Cycle counts should be quite accurate.
+
+
+ Changelog, version 1.02:
+ JMP + indirect X (0x7c) opcode fixed.
+ SMB + RMB opcodes fixed in disassembler.
+ change_pc function calls removed.
+ TSB & TRB now set flags properly.
+ BIT opcode altered.
+
+ Changelog, version 1.03:
+ Swapped IRQ mask for IRQ1 & IRQ2 (thanks Yasuhiro)
+
+ Changelog, version 1.04, 28/9/99-22/10/99:
+ Adjusted RTI (thanks Karl)
+ TST opcodes fixed in disassembler (missing break statements in a case!).
+ TST behaviour fixed.
+ SMB/RMB/BBS/BBR fixed in disassembler.
+
+ Changelog, version 1.05, 8/12/99-16/12/99:
+ Added CAB's timer implementation (note: irq ack & timer reload are changed).
+ Fixed STA IDX.
+ Fixed B flag setting on BRK.
+ Assumed CSH & CSL to take 2 cycles each.
+
+ Todo: Performance could be improved by precalculating timer fire position.
+
+ Changelog, version 1.06, 4/5/00 - last opcode bug found?
+ JMP indirect was doing a EAL++; instead of EAD++; - Obviously causing
+ a corrupt read when L = 0xff! This fixes Bloody Wolf and Trio The Punch!
+
+ Changelog, version 1.07, 3/9/00:
+ Changed timer to be single shot - fixes Crude Buster music in level 1.
+
+ Changelog, version 1.08, 8/11/05: (Charles MacDonald)
+
+ Changed timer implementation, no longer single shot and reading the
+ timer registers returns the count only. Fixes the following:
+ - Mesopotamia: Music tempo & in-game timer
+ - Dragon Saber: DDA effects
+ - Magical Chase: Music tempo and speed regulation
+ - Cadash: Allows the first level to start
+ - Turrican: Allows the game to start
+
+ Changed PLX and PLY to set NZ flags. Fixes:
+ - Afterburner: Graphics unpacking
+ - Aoi Blink: Collision detection with background
+
+ Fixed the decimal version of ADC/SBC to *not* update the V flag,
+ only the binary ones do.
+
+ Fixed B flag handling so it is always set outside of an interrupt;
+ even after being set by PLP and RTI.
+
+ Fixed P state after reset to set I and B, leaving T, D cleared and
+ NVZC randomized (cleared in this case).
+
+ Fixed interrupt processing order (Timer has highest priority followed
+ by IRQ1 and finally IRQ2).
+
+ Changelog, version 1.09, 1/07/06: (Rob Bohms)
+
+ Added emulation of the T flag, fixes PCE Ankuku Densetsu title screen
+
+ Changelog, version 1.10, 5/09/07: (Wilbert Pol)
+
+ - Taking of interrupts is delayed to respect a pending instruction already
+ in the instruction pipeline; fixes After Burner.
+ - Added 1 cycle for decimal mode ADC and SBC instructions.
+ - Changed cycle counts for CSH and CSL instructions to 3.
+ - Added T flag support to the SBC instruction.
+ - Fixed ADC T flag to set the Z flag based on the value read.
+ - Added 3 cycle penalty to ADC, AND, EOR, ORA, and SBC instructions
+ when the T flag is set.
+ - Fixed cycle count and support for 65536 byte blocks for the TAI, TDD,
+ TIA, TII, and TIN instructions.
+ - Fixed RDWORD macro in the disassembler.
+ - Fixed setting of N and V flags in the TST instructions.
+ - Removed unneeded debug_mmr code.
+ - Fixed TSB and TRB instructions.
+ - Added 1 delay when accessing the VDC or VCE areas.
+ - Implemented low and high speed cpu modes.
+
+ Changelog, version 1.11, 18/09/07: (Wilbert Pol)
+
+ - Improvements to the handling of taking of delayed interrupts.
+
+******************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "h6280.h"
+
+static void set_irq_line(h6280_Regs* cpustate, int irqline, int state);
+
+/* include the macros */
+#include "h6280ops.h"
+
+INLINE h6280_Regs *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == H6280);
+ return (h6280_Regs *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+/* include the opcode macros, functions and function pointer tables */
+#include "tblh6280.c"
+
+/*****************************************************************************/
+static CPU_INIT( h6280 )
+{
+ h6280_Regs* cpustate = get_safe_token(device);
+
+ device->save_item(NAME(cpustate->ppc.w.l));
+ device->save_item(NAME(cpustate->pc.w.l));
+ device->save_item(NAME(cpustate->sp.w.l));
+ device->save_item(NAME(cpustate->zp.w.l));
+ device->save_item(NAME(cpustate->ea.w.l));
+ device->save_item(NAME(cpustate->a));
+ device->save_item(NAME(cpustate->x));
+ device->save_item(NAME(cpustate->y));
+ device->save_item(NAME(cpustate->p));
+ device->save_item(NAME(cpustate->mmr));
+ device->save_item(NAME(cpustate->irq_mask));
+ device->save_item(NAME(cpustate->timer_status));
+ device->save_item(NAME(cpustate->timer_ack));
+ device->save_item(NAME(cpustate->clocks_per_cycle));
+ device->save_item(NAME(cpustate->timer_value));
+ device->save_item(NAME(cpustate->timer_load));
+ device->save_item(NAME(cpustate->nmi_state));
+ device->save_item(NAME(cpustate->irq_state[0]));
+ device->save_item(NAME(cpustate->irq_state[1]));
+ device->save_item(NAME(cpustate->irq_state[2]));
+ device->save_item(NAME(cpustate->irq_pending));
+
+ #if LAZY_FLAGS
+ device->save_item(NAME(cpustate->NZ));
+ #endif
+ device->save_item(NAME(cpustate->io_buffer));
+
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+ cpustate->io = device->space(AS_IO);
+}
+
+static CPU_RESET( h6280 )
+{
+ h6280_Regs* cpustate = get_safe_token(device);
+
+ device_irq_callback save_irqcallback;
+ int i;
+
+ /* wipe out the h6280 structure */
+ save_irqcallback = cpustate->irq_callback;
+ memset(cpustate, 0, sizeof(h6280_Regs));
+ cpustate->irq_callback = save_irqcallback;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+ cpustate->io = device->space(AS_IO);
+
+ /* set I and B flags */
+ P = _fI | _fB;
+
+ /* stack starts at 0x01ff */
+ cpustate->sp.d = 0x1ff;
+
+ /* read the reset vector into PC */
+ PCL = RDMEM(cpustate, H6280_RESET_VEC);
+ PCH = RDMEM(cpustate, (H6280_RESET_VEC+1));
+
+ /* CPU starts in low speed mode */
+ cpustate->clocks_per_cycle = 4;
+
+ /* timer off by default */
+ cpustate->timer_status=0;
+ cpustate->timer_load = 128 * 1024;
+
+ /* clear pending interrupts */
+ for (i = 0; i < 3; i++)
+ cpustate->irq_state[i] = CLEAR_LINE;
+ cpustate->nmi_state = CLEAR_LINE;
+
+ cpustate->irq_pending = 0;
+}
+
+static CPU_EXIT( h6280 )
+{
+ /* nothing */
+}
+
+static CPU_EXECUTE( h6280 )
+{
+ int in;
+ h6280_Regs* cpustate = get_safe_token(device);
+
+ if ( cpustate->irq_pending == 2 ) {
+ cpustate->irq_pending--;
+ }
+
+ /* Execute instructions */
+ do
+ {
+ cpustate->ppc = cpustate->pc;
+
+ debugger_instruction_hook(device, PCW);
+
+ /* Execute 1 instruction */
+ in=RDOP();
+ PCW++;
+ insnh6280[in](cpustate);
+
+ if ( cpustate->irq_pending ) {
+ if ( cpustate->irq_pending == 1 ) {
+ if ( !(P & _fI) ) {
+ cpustate->irq_pending--;
+ CHECK_AND_TAKE_IRQ_LINES;
+ }
+ } else {
+ cpustate->irq_pending--;
+ }
+ }
+
+ /* Check internal timer */
+ if(cpustate->timer_status)
+ {
+ if(cpustate->timer_value<=0)
+ {
+ if ( ! cpustate->irq_pending )
+ cpustate->irq_pending = 1;
+ while( cpustate->timer_value <= 0 )
+ cpustate->timer_value += cpustate->timer_load;
+ set_irq_line(cpustate, 2,ASSERT_LINE);
+ }
+ }
+ } while (cpustate->ICount > 0);
+}
+
+/*****************************************************************************/
+
+static void set_irq_line(h6280_Regs* cpustate, int irqline, int state)
+{
+ if (irqline == INPUT_LINE_NMI)
+ {
+ if ( state != ASSERT_LINE ) return;
+ cpustate->nmi_state = state;
+ CHECK_IRQ_LINES;
+ }
+ else if (irqline < 3)
+ {
+ /* If the state has not changed, just return */
+ if ( cpustate->irq_state[irqline] == state )
+ return;
+
+ cpustate->irq_state[irqline] = state;
+
+ CHECK_IRQ_LINES;
+ }
+}
+
+
+
+/*****************************************************************************/
+
+READ8_HANDLER( h6280_irq_status_r )
+{
+ int status;
+ h6280_Regs *cpustate = get_safe_token(&space->device());
+
+ switch (offset&3)
+ {
+ default: return cpustate->io_buffer;
+ case 3:
+ {
+ status=0;
+ if(cpustate->irq_state[1]!=CLEAR_LINE) status|=1; /* IRQ 2 */
+ if(cpustate->irq_state[0]!=CLEAR_LINE) status|=2; /* IRQ 1 */
+ if(cpustate->irq_state[2]!=CLEAR_LINE) status|=4; /* TIMER */
+ return status|(cpustate->io_buffer&(~H6280_IRQ_MASK));
+ }
+ case 2: return cpustate->irq_mask|(cpustate->io_buffer&(~H6280_IRQ_MASK));
+ }
+}
+
+WRITE8_HANDLER( h6280_irq_status_w )
+{
+ h6280_Regs *cpustate = get_safe_token(&space->device());
+ cpustate->io_buffer=data;
+ switch (offset&3)
+ {
+ default:cpustate->io_buffer=data;break;
+ case 2: /* Write irq mask */
+ cpustate->irq_mask=data&0x7;
+ CHECK_IRQ_LINES;
+ break;
+
+ case 3: /* Timer irq ack */
+ set_irq_line(cpustate, 2, CLEAR_LINE);
+ break;
+ }
+}
+
+READ8_HANDLER( h6280_timer_r )
+{
+ /* only returns countdown */
+ h6280_Regs *cpustate = get_safe_token(&space->device());
+ return ((cpustate->timer_value >> 10)&0x7F)|(cpustate->io_buffer&0x80);
+}
+
+WRITE8_HANDLER( h6280_timer_w )
+{
+ h6280_Regs *cpustate = get_safe_token(&space->device());
+ cpustate->io_buffer=data;
+ switch (offset & 1) {
+ case 0: /* Counter preload */
+ cpustate->timer_load=cpustate->timer_value=((data&127)+1)*1024;
+ return;
+
+ case 1: /* Counter enable */
+ if(data&1)
+ { /* stop -> start causes reload */
+ if(cpustate->timer_status==0) cpustate->timer_value=cpustate->timer_load;
+ }
+ cpustate->timer_status=data&1;
+ return;
+ }
+}
+
+static CPU_TRANSLATE( h6280 )
+{
+ h6280_Regs* cpustate = get_safe_token(device);
+
+ if (space == AS_PROGRAM)
+ *address = TRANSLATED(*address);
+
+ return TRUE;
+}
+
+UINT8 h6280io_get_buffer(device_t *device)
+{
+ h6280_Regs* cpustate = get_safe_token(device);
+ return cpustate->io_buffer;
+}
+void h6280io_set_buffer(device_t *device, UINT8 data)
+{
+ h6280_Regs* cpustate = get_safe_token(device);
+ cpustate->io_buffer=data;
+}
+
+
+/*****************************************************************************/
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( h6280 )
+{
+ h6280_Regs* cpustate = get_safe_token(device);
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + 0: set_irq_line(cpustate, 0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + 1: set_irq_line(cpustate, 1, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + 2: set_irq_line(cpustate, 2, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: set_irq_line(cpustate, INPUT_LINE_NMI, info->i); break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + H6280_PC: PCW = info->i; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + H6280_S: S = info->i; break;
+ case CPUINFO_INT_REGISTER + H6280_P: P = info->i; break;
+ case CPUINFO_INT_REGISTER + H6280_A: A = info->i; break;
+ case CPUINFO_INT_REGISTER + H6280_X: X = info->i; break;
+ case CPUINFO_INT_REGISTER + H6280_Y: Y = info->i; break;
+ case CPUINFO_INT_REGISTER + H6280_IRQ_MASK: cpustate->irq_mask = info->i; CHECK_IRQ_LINES; break;
+ case CPUINFO_INT_REGISTER + H6280_TIMER_STATE: cpustate->timer_status = info->i; break;
+ case CPUINFO_INT_REGISTER + H6280_NMI_STATE: set_irq_line( cpustate, INPUT_LINE_NMI, info->i ); break;
+ case CPUINFO_INT_REGISTER + H6280_IRQ1_STATE: set_irq_line( cpustate, 0, info->i ); break;
+ case CPUINFO_INT_REGISTER + H6280_IRQ2_STATE: set_irq_line( cpustate, 1, info->i ); break;
+ case CPUINFO_INT_REGISTER + H6280_IRQT_STATE: set_irq_line( cpustate, 2, info->i ); break;
+ case CPUINFO_INT_REGISTER + H6280_M1: cpustate->mmr[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + H6280_M2: cpustate->mmr[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + H6280_M3: cpustate->mmr[2] = info->i; break;
+ case CPUINFO_INT_REGISTER + H6280_M4: cpustate->mmr[3] = info->i; break;
+ case CPUINFO_INT_REGISTER + H6280_M5: cpustate->mmr[4] = info->i; break;
+ case CPUINFO_INT_REGISTER + H6280_M6: cpustate->mmr[5] = info->i; break;
+ case CPUINFO_INT_REGISTER + H6280_M7: cpustate->mmr[6] = info->i; break;
+ case CPUINFO_INT_REGISTER + H6280_M8: cpustate->mmr[7] = info->i; break;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+CPU_GET_INFO( h6280 )
+{
+ h6280_Regs* cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(h6280_Regs); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 3; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 7; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 2; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 17 + 6*65536; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 21; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case CPUINFO_INT_LOGADDR_WIDTH_PROGRAM: info->i = 16; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 2; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_INPUT_STATE + 0: info->i = cpustate->irq_state[0]; break;
+ case CPUINFO_INT_INPUT_STATE + 1: info->i = cpustate->irq_state[1]; break;
+ case CPUINFO_INT_INPUT_STATE + 2: info->i = cpustate->irq_state[2]; break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: info->i = cpustate->nmi_state; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = cpustate->ppc.d; break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + H6280_PC: info->i = PCD; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + H6280_S: info->i = S; break;
+ case CPUINFO_INT_REGISTER + H6280_P: info->i = P; break;
+ case CPUINFO_INT_REGISTER + H6280_A: info->i = A; break;
+ case CPUINFO_INT_REGISTER + H6280_X: info->i = X; break;
+ case CPUINFO_INT_REGISTER + H6280_Y: info->i = Y; break;
+ case CPUINFO_INT_REGISTER + H6280_IRQ_MASK: info->i = cpustate->irq_mask; break;
+ case CPUINFO_INT_REGISTER + H6280_TIMER_STATE: info->i = cpustate->timer_status; break;
+ case CPUINFO_INT_REGISTER + H6280_NMI_STATE: info->i = cpustate->nmi_state; break;
+ case CPUINFO_INT_REGISTER + H6280_IRQ1_STATE: info->i = cpustate->irq_state[0]; break;
+ case CPUINFO_INT_REGISTER + H6280_IRQ2_STATE: info->i = cpustate->irq_state[1]; break;
+ case CPUINFO_INT_REGISTER + H6280_IRQT_STATE: info->i = cpustate->irq_state[2]; break;
+ case CPUINFO_INT_REGISTER + H6280_M1: info->i = cpustate->mmr[0]; break;
+ case CPUINFO_INT_REGISTER + H6280_M2: info->i = cpustate->mmr[1]; break;
+ case CPUINFO_INT_REGISTER + H6280_M3: info->i = cpustate->mmr[2]; break;
+ case CPUINFO_INT_REGISTER + H6280_M4: info->i = cpustate->mmr[3]; break;
+ case CPUINFO_INT_REGISTER + H6280_M5: info->i = cpustate->mmr[4]; break;
+ case CPUINFO_INT_REGISTER + H6280_M6: info->i = cpustate->mmr[5]; break;
+ case CPUINFO_INT_REGISTER + H6280_M7: info->i = cpustate->mmr[6]; break;
+ case CPUINFO_INT_REGISTER + H6280_M8: info->i = cpustate->mmr[7]; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(h6280); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(h6280); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(h6280); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(h6280); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(h6280); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(h6280);break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->ICount; break;
+ case CPUINFO_FCT_TRANSLATE: info->translate = CPU_TRANSLATE_NAME(h6280); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "HuC6280"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Hudsonsoft 6280"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.11"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Bryan McPhail, mish@tendril.co.uk"); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c%c%c%c%c%c%c",
+ cpustate->p & 0x80 ? 'N':'.',
+ cpustate->p & 0x40 ? 'V':'.',
+ cpustate->p & 0x20 ? 'R':'.',
+ cpustate->p & 0x10 ? 'B':'.',
+ cpustate->p & 0x08 ? 'D':'.',
+ cpustate->p & 0x04 ? 'I':'.',
+ cpustate->p & 0x02 ? 'Z':'.',
+ cpustate->p & 0x01 ? 'C':'.');
+ break;
+
+ case CPUINFO_STR_REGISTER + H6280_PC: sprintf(info->s, "PC:%04X", cpustate->pc.d); break;
+ case CPUINFO_STR_REGISTER + H6280_S: sprintf(info->s, "S:%02X", cpustate->sp.b.l); break;
+ case CPUINFO_STR_REGISTER + H6280_P: sprintf(info->s, "P:%02X", cpustate->p); break;
+ case CPUINFO_STR_REGISTER + H6280_A: sprintf(info->s, "A:%02X", cpustate->a); break;
+ case CPUINFO_STR_REGISTER + H6280_X: sprintf(info->s, "X:%02X", cpustate->x); break;
+ case CPUINFO_STR_REGISTER + H6280_Y: sprintf(info->s, "Y:%02X", cpustate->y); break;
+ case CPUINFO_STR_REGISTER + H6280_IRQ_MASK: sprintf(info->s, "IM:%02X", cpustate->irq_mask);break;
+ case CPUINFO_STR_REGISTER + H6280_TIMER_STATE: sprintf(info->s, "TMR:%02X", cpustate->timer_status); break;
+ case CPUINFO_STR_REGISTER + H6280_NMI_STATE: sprintf(info->s, "NMI:%X", cpustate->nmi_state); break;
+ case CPUINFO_STR_REGISTER + H6280_IRQ1_STATE: sprintf(info->s, "IRQ1:%X", cpustate->irq_state[0]); break;
+ case CPUINFO_STR_REGISTER + H6280_IRQ2_STATE: sprintf(info->s, "IRQ2:%X", cpustate->irq_state[1]); break;
+ case CPUINFO_STR_REGISTER + H6280_IRQT_STATE: sprintf(info->s, "IRQT:%X", cpustate->irq_state[2]); break;
+ case CPUINFO_STR_REGISTER + H6280_M1: sprintf(info->s, "M1:%02X", cpustate->mmr[0]); break;
+ case CPUINFO_STR_REGISTER + H6280_M2: sprintf(info->s, "M2:%02X", cpustate->mmr[1]); break;
+ case CPUINFO_STR_REGISTER + H6280_M3: sprintf(info->s, "M3:%02X", cpustate->mmr[2]); break;
+ case CPUINFO_STR_REGISTER + H6280_M4: sprintf(info->s, "M4:%02X", cpustate->mmr[3]); break;
+ case CPUINFO_STR_REGISTER + H6280_M5: sprintf(info->s, "M5:%02X", cpustate->mmr[4]); break;
+ case CPUINFO_STR_REGISTER + H6280_M6: sprintf(info->s, "M6:%02X", cpustate->mmr[5]); break;
+ case CPUINFO_STR_REGISTER + H6280_M7: sprintf(info->s, "M7:%02X", cpustate->mmr[6]); break;
+ case CPUINFO_STR_REGISTER + H6280_M8: sprintf(info->s, "M8:%02X", cpustate->mmr[7]); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(H6280, h6280);
diff --git a/trunk/src/emu/cpu/h6280/h6280.h b/trunk/src/emu/cpu/h6280/h6280.h
new file mode 100644
index 00000000000..568d5b9a3d5
--- /dev/null
+++ b/trunk/src/emu/cpu/h6280/h6280.h
@@ -0,0 +1,90 @@
+/*****************************************************************************
+
+ h6280.h Portable Hu6280 emulator interface
+
+ Copyright Bryan McPhail, mish@tendril.co.uk
+
+ This source code is based (with permission!) on the 6502 emulator by
+ Juergen Buchmueller. It is released as part of the Mame emulator project.
+ Let me know if you intend to use this code in any other project.
+
+******************************************************************************/
+
+#pragma once
+
+#ifndef __H6280_H__
+#define __H6280_H__
+
+
+enum
+{
+ H6280_PC=1, H6280_S, H6280_P, H6280_A, H6280_X, H6280_Y,
+ H6280_IRQ_MASK, H6280_TIMER_STATE,
+ H6280_NMI_STATE, H6280_IRQ1_STATE, H6280_IRQ2_STATE, H6280_IRQT_STATE,
+ H6280_M1, H6280_M2, H6280_M3, H6280_M4,
+ H6280_M5, H6280_M6, H6280_M7, H6280_M8
+};
+
+#define LAZY_FLAGS 0
+
+#define H6280_RESET_VEC 0xfffe
+#define H6280_NMI_VEC 0xfffc
+#define H6280_TIMER_VEC 0xfffa
+#define H6280_IRQ1_VEC 0xfff8
+#define H6280_IRQ2_VEC 0xfff6 /* Aka BRK vector */
+
+
+/****************************************************************************
+ * The 6280 registers.
+ ****************************************************************************/
+typedef struct
+{
+ int ICount;
+
+ PAIR ppc; /* previous program counter */
+ PAIR pc; /* program counter */
+ PAIR sp; /* stack pointer (always 100 - 1FF) */
+ PAIR zp; /* zero page address */
+ PAIR ea; /* effective address */
+ UINT8 a; /* Accumulator */
+ UINT8 x; /* X index register */
+ UINT8 y; /* Y index register */
+ UINT8 p; /* Processor status */
+ UINT8 mmr[8]; /* Hu6280 memory mapper registers */
+ UINT8 irq_mask; /* interrupt enable/disable */
+ UINT8 timer_status; /* timer status */
+ UINT8 timer_ack; /* timer acknowledge */
+ UINT8 clocks_per_cycle; /* 4 = low speed mode, 1 = high speed mode */
+ INT32 timer_value; /* timer interrupt */
+ INT32 timer_load; /* reload value */
+ UINT8 nmi_state;
+ UINT8 irq_state[3];
+ UINT8 irq_pending;
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ address_space *io;
+
+#if LAZY_FLAGS
+ INT32 NZ; /* last value (lazy N and Z flag) */
+#endif
+ UINT8 io_buffer; /* last value written to the PSG, timer, and interrupt pages */
+} h6280_Regs;
+
+
+DECLARE_LEGACY_CPU_DEVICE(H6280, h6280);
+
+READ8_HANDLER( h6280_irq_status_r );
+WRITE8_HANDLER( h6280_irq_status_w );
+
+READ8_HANDLER( h6280_timer_r );
+WRITE8_HANDLER( h6280_timer_w );
+
+/* functions for use by the PSG and joypad port only! */
+UINT8 h6280io_get_buffer(device_t*);
+void h6280io_set_buffer(device_t*, UINT8);
+
+CPU_DISASSEMBLE( h6280 );
+
+#endif /* __H6280_H__ */
diff --git a/trunk/src/emu/cpu/h6280/h6280ops.h b/trunk/src/emu/cpu/h6280/h6280ops.h
new file mode 100644
index 00000000000..8d37ffcd0d0
--- /dev/null
+++ b/trunk/src/emu/cpu/h6280/h6280ops.h
@@ -0,0 +1,1370 @@
+/*****************************************************************************
+
+ h6280ops.h - Addressing modes and opcode macros for the Hu6820 cpu
+
+ Copyright Bryan McPhail, mish@tendril.co.uk
+
+ This source code is based (with permission!) on the 6502 emulator by
+ Juergen Buchmueller. It is released as part of the Mame emulator project.
+ Let me know if you intend to use this code in any other project.
+
+******************************************************************************/
+
+/* 6280 flags */
+#define _fC 0x01
+#define _fZ 0x02
+#define _fI 0x04
+#define _fD 0x08
+#define _fB 0x10
+#define _fT 0x20
+#define _fV 0x40
+#define _fN 0x80
+
+/* some shortcuts for improved readability */
+#define A cpustate->a
+#define X cpustate->x
+#define Y cpustate->y
+#define P cpustate->p
+#define S cpustate->sp.b.l
+
+#define TRANSLATED(addr) ((cpustate->mmr[(addr)>>13] << 13) | ((addr)&0x1fff))
+#define H6280_CYCLES(cyc) \
+ { \
+ cpustate->ICount -= ((cyc) * cpustate->clocks_per_cycle); \
+ cpustate->timer_value -= ((cyc) * cpustate->clocks_per_cycle); \
+ }
+
+#if LAZY_FLAGS
+
+#define NZ cpustate->NZ
+#define SET_NZ(n) \
+ P &= ~_fT; \
+ NZ = ((n & _fN) << 8) | n
+
+#else
+
+#define SET_NZ(n) \
+ P = (P & ~(_fN|_fT|_fZ)) | \
+ (n & _fN) | \
+ ((n == 0) ? _fZ : 0)
+
+#endif
+
+#define EAL cpustate->ea.b.l
+#define EAH cpustate->ea.b.h
+#define EAW cpustate->ea.w.l
+#define EAD cpustate->ea.d
+
+#define ZPL cpustate->zp.b.l
+#define ZPH cpustate->zp.b.h
+#define ZPW cpustate->zp.w.l
+#define ZPD cpustate->zp.d
+
+#define PCL cpustate->pc.b.l
+#define PCH cpustate->pc.b.h
+#define PCW cpustate->pc.w.l
+#define PCD cpustate->pc.d
+
+#define CLEAR_T \
+ P &= ~_fT;
+
+#define DO_INTERRUPT(vector) \
+{ \
+ H6280_CYCLES(7); /* 7 cycles for an int */ \
+ PUSH(PCH); \
+ PUSH(PCL); \
+ COMPOSE_P(0,_fB); \
+ PUSH(P); \
+ P = (P & ~_fD) | _fI; /* knock out D and set I flag */ \
+ PCL = RDMEM(cpustate, vector); \
+ PCH = RDMEM(cpustate, (vector+1)); \
+}
+
+#define CHECK_AND_TAKE_IRQ_LINES \
+ if ( cpustate->nmi_state != CLEAR_LINE ) { \
+ cpustate->nmi_state = CLEAR_LINE; \
+ DO_INTERRUPT(H6280_NMI_VEC); \
+ } \
+ else if( !(P & _fI) ) \
+ { \
+ if ( cpustate->irq_state[2] != CLEAR_LINE && \
+ !(cpustate->irq_mask & 0x4) ) \
+ { \
+ DO_INTERRUPT(H6280_TIMER_VEC); \
+ } else \
+ if ( cpustate->irq_state[0] != CLEAR_LINE && \
+ !(cpustate->irq_mask & 0x2) ) \
+ { \
+ DO_INTERRUPT(H6280_IRQ1_VEC); \
+ (*cpustate->irq_callback)(cpustate->device, 0); \
+ } else \
+ if ( cpustate->irq_state[1] != CLEAR_LINE && \
+ !(cpustate->irq_mask & 0x1) ) \
+ { \
+ DO_INTERRUPT(H6280_IRQ2_VEC); \
+ (*cpustate->irq_callback)(cpustate->device, 1); \
+ } \
+ }
+
+#define CHECK_IRQ_LINES \
+ if ( ! cpustate->irq_pending ) \
+ cpustate->irq_pending = 2;
+
+/***************************************************************
+ * CHECK_VDC_VCE_PENALTY
+ * The CPU inserts 1 clock delay when accessing the VDC or VCE
+ * area.
+ ***************************************************************/
+#define CHECK_VDC_VCE_PENALTY(addr) \
+ if ( ( TRANSLATED(addr) & 0x1FF800 ) == 0x1FE000 ) { \
+ H6280_CYCLES(1); \
+ }
+
+/***************************************************************
+ * RDMEM read memory
+ ***************************************************************/
+INLINE UINT8 RDMEM(h6280_Regs* cpustate, offs_t addr) {
+ CHECK_VDC_VCE_PENALTY(addr);
+ return cpustate->program->read_byte(TRANSLATED(addr));
+}
+
+/***************************************************************
+ * WRMEM write memory
+ ***************************************************************/
+INLINE void WRMEM(h6280_Regs* cpustate, offs_t addr, UINT8 data) {
+ CHECK_VDC_VCE_PENALTY(addr);
+ cpustate->program->write_byte(TRANSLATED(addr),data);
+}
+
+/***************************************************************
+ * RDMEMZ read memory - zero page
+ ***************************************************************/
+#define RDMEMZ(addr) \
+ cpustate->program->read_byte((cpustate->mmr[1] << 13) | ((addr)&0x1fff));
+
+/***************************************************************
+ * WRMEMZ write memory - zero page
+ ***************************************************************/
+#define WRMEMZ(addr,data) \
+ cpustate->program->write_byte((cpustate->mmr[1] << 13) | ((addr)&0x1fff),data);
+
+/***************************************************************
+ * RDMEMW read word from memory
+ ***************************************************************/
+#define RDMEMW(addr) \
+ cpustate->program->read_byte(TRANSLATED(addr)) \
+| ( cpustate->program->read_byte(TRANSLATED(addr+1)) << 8 )
+
+/***************************************************************
+ * RDZPWORD read a word from a zero page address
+ ***************************************************************/
+#define RDZPWORD(addr) \
+ ((addr&0xff)==0xff) ? \
+ cpustate->program->read_byte((cpustate->mmr[1] << 13) | ((addr)&0x1fff)) \
+ +(cpustate->program->read_byte((cpustate->mmr[1] << 13) | ((addr-0xff)&0x1fff))<<8) : \
+ cpustate->program->read_byte((cpustate->mmr[1] << 13) | ((addr)&0x1fff)) \
+ +(cpustate->program->read_byte((cpustate->mmr[1] << 13) | ((addr+1)&0x1fff))<<8)
+
+
+/***************************************************************
+ * push a register onto the stack
+ ***************************************************************/
+#define PUSH(Rg) cpustate->program->write_byte((cpustate->mmr[1] << 13) | cpustate->sp.d,Rg); S--
+
+/***************************************************************
+ * pull a register from the stack
+ ***************************************************************/
+#define PULL(Rg) S++; Rg = cpustate->program->read_byte((cpustate->mmr[1] << 13) | cpustate->sp.d)
+
+/***************************************************************
+ * RDOP read an opcode
+ ***************************************************************/
+#define RDOP() \
+ cpustate->direct->read_decrypted_byte(TRANSLATED(PCW))
+
+/***************************************************************
+ * RDOPARG read an opcode argument
+ ***************************************************************/
+#define RDOPARG() \
+ cpustate->direct->read_raw_byte(TRANSLATED(PCW))
+
+/***************************************************************
+ * BRA branch relative
+ ***************************************************************/
+#define BRA(cond) \
+ CLEAR_T; \
+ if (cond) \
+ { \
+ H6280_CYCLES(4); \
+ tmp = RDOPARG(); \
+ PCW++; \
+ EAW = PCW + (signed char)tmp; \
+ PCD = EAD; \
+ } \
+ else \
+ { \
+ PCW++; \
+ H6280_CYCLES(2); \
+ }
+
+/***************************************************************
+ *
+ * Helper macros to build the effective address
+ *
+ ***************************************************************/
+
+/***************************************************************
+ * EA = zero page address
+ ***************************************************************/
+#define EA_ZPG \
+ ZPL = RDOPARG(); \
+ PCW++; \
+ EAD = ZPD
+
+/***************************************************************
+ * EA = zero page address - T flag
+ ***************************************************************/
+#define EA_TFLG \
+ ZPL = X; \
+ EAD = ZPD
+
+/***************************************************************
+ * EA = zero page address + X
+ ***************************************************************/
+#define EA_ZPX \
+ ZPL = RDOPARG() + X; \
+ PCW++; \
+ EAD = ZPD
+
+/***************************************************************
+ * EA = zero page address + Y
+ ***************************************************************/
+#define EA_ZPY \
+ ZPL = RDOPARG() + Y; \
+ PCW++; \
+ EAD = ZPD
+
+/***************************************************************
+ * EA = absolute address
+ ***************************************************************/
+#define EA_ABS \
+ EAL = RDOPARG(); \
+ PCW++; \
+ EAH = RDOPARG(); \
+ PCW++
+
+/***************************************************************
+ * EA = absolute address + X
+ ***************************************************************/
+#define EA_ABX \
+ EA_ABS; \
+ EAW += X
+
+/***************************************************************
+ * EA = absolute address + Y
+ ***************************************************************/
+#define EA_ABY \
+ EA_ABS; \
+ EAW += Y
+
+/***************************************************************
+ * EA = zero page indirect (65c02 pre indexed w/o X)
+ ***************************************************************/
+#define EA_ZPI \
+ ZPL = RDOPARG(); \
+ PCW++; \
+ EAD = RDZPWORD(ZPD)
+
+/***************************************************************
+ * EA = zero page + X indirect (pre indexed)
+ ***************************************************************/
+#define EA_IDX \
+ ZPL = RDOPARG() + X; \
+ PCW++; \
+ EAD = RDZPWORD(ZPD);
+
+/***************************************************************
+ * EA = zero page indirect + Y (post indexed)
+ ***************************************************************/
+#define EA_IDY \
+ ZPL = RDOPARG(); \
+ PCW++; \
+ EAD = RDZPWORD(ZPD); \
+ EAW += Y
+
+/***************************************************************
+ * EA = indirect (only used by JMP)
+ ***************************************************************/
+#define EA_IND \
+ EA_ABS; \
+ tmp = RDMEM(cpustate, EAD); \
+ EAD++; \
+ EAH = RDMEM(cpustate, EAD); \
+ EAL = tmp
+
+/***************************************************************
+ * EA = indirect plus x (only used by JMP)
+ ***************************************************************/
+#define EA_IAX \
+ EA_ABS; \
+ EAD+=X; \
+ tmp = RDMEM(cpustate, EAD); \
+ EAD++; \
+ EAH = RDMEM(cpustate, EAD); \
+ EAL = tmp
+
+/* read a value into tmp */
+#define RD_IMM tmp = RDOPARG(); PCW++
+#define RD_IMM2 tmp2 = RDOPARG(); PCW++
+#define RD_ACC tmp = A
+#define RD_ZPG EA_ZPG; tmp = RDMEMZ(EAD)
+#define RD_ZPX EA_ZPX; tmp = RDMEMZ(EAD)
+#define RD_ZPY EA_ZPY; tmp = RDMEMZ(EAD)
+#define RD_ABS EA_ABS; tmp = RDMEM(cpustate, EAD)
+#define RD_ABX EA_ABX; tmp = RDMEM(cpustate, EAD)
+#define RD_ABY EA_ABY; tmp = RDMEM(cpustate, EAD)
+#define RD_ZPI EA_ZPI; tmp = RDMEM(cpustate, EAD)
+#define RD_IDX EA_IDX; tmp = RDMEM(cpustate, EAD)
+#define RD_IDY EA_IDY; tmp = RDMEM(cpustate, EAD)
+#define RD_TFL EA_TFLG; tflagtemp = RDMEMZ(EAD)
+
+/* write a value from tmp */
+#define WR_ZPG EA_ZPG; WRMEMZ(EAD, tmp)
+#define WR_ZPX EA_ZPX; WRMEMZ(EAD, tmp)
+#define WR_ZPY EA_ZPY; WRMEMZ(EAD, tmp)
+#define WR_ABS EA_ABS; WRMEM(cpustate, EAD, tmp)
+#define WR_ABX EA_ABX; WRMEM(cpustate, EAD, tmp)
+#define WR_ABY EA_ABY; WRMEM(cpustate, EAD, tmp)
+#define WR_ZPI EA_ZPI; WRMEM(cpustate, EAD, tmp)
+#define WR_IDX EA_IDX; WRMEM(cpustate, EAD, tmp)
+#define WR_IDY EA_IDY; WRMEM(cpustate, EAD, tmp)
+
+/* write back a value from tmp to the last EA */
+#define WB_ACC A = (UINT8)tmp;
+#define WB_EA WRMEM(cpustate, EAD, tmp)
+#define WB_EAZ WRMEMZ(EAD, tmp)
+#define WB_TFL WRMEMZ(EAD, tflagtemp)
+
+/***************************************************************
+ *
+ * Macros to emulate the 6280 opcodes
+ *
+ ***************************************************************/
+
+/***************************************************************
+ * compose the real flag register by
+ * including N and Z and set any
+ * SET and clear any CLR bits also
+ ***************************************************************/
+#if LAZY_FLAGS
+
+#define COMPOSE_P(SET,CLR) \
+ P = (P & ~(_fN | _fZ | CLR)) | \
+ (NZ >> 8) | \
+ ((NZ & 0xff) ? 0 : _fZ) | \
+ SET
+
+#else
+
+#define COMPOSE_P(SET,CLR) \
+ P = (P & ~CLR) | SET
+
+#endif
+
+/* 6280 ********************************************************
+ * ADC Add with carry
+ ***************************************************************/
+#define TADC \
+ { \
+ int tflagtemp; \
+ CLEAR_T; \
+ RD_TFL; \
+ if (P & _fD) \
+ { \
+ int c = (P & _fC); \
+ int lo = (tflagtemp & 0x0f) + (tmp & 0x0f) + c; \
+ int hi = (tflagtemp & 0xf0) + (tmp & 0xf0); \
+ P &= ~_fC; \
+ if (lo > 0x09) \
+ { \
+ hi += 0x10; \
+ lo += 0x06; \
+ } \
+ if (hi > 0x90) \
+ hi += 0x60; \
+ if (hi & 0xff00) \
+ P |= _fC; \
+ tflagtemp = (lo & 0x0f) + (hi & 0xf0); \
+ H6280_CYCLES(1); \
+ } \
+ else \
+ { \
+ int c = (P & _fC); \
+ int sum = tflagtemp + tmp + c; \
+ P &= ~(_fV | _fC); \
+ if (~(tflagtemp^tmp) & (tflagtemp^sum) & _fN) \
+ P |= _fV; \
+ if (sum & 0xff00) \
+ P |= _fC; \
+ tflagtemp = (UINT8) sum; \
+ } \
+ SET_NZ(tflagtemp); \
+ WB_TFL; \
+ H6280_CYCLES(3); \
+ }
+
+
+#define ADC \
+ if(P & _fT) \
+ TADC \
+ else { \
+ if (P & _fD) \
+ { \
+ int c = (P & _fC); \
+ int lo = (A & 0x0f) + (tmp & 0x0f) + c; \
+ int hi = (A & 0xf0) + (tmp & 0xf0); \
+ P &= ~_fC; \
+ if (lo > 0x09) \
+ { \
+ hi += 0x10; \
+ lo += 0x06; \
+ } \
+ if (hi > 0x90) \
+ hi += 0x60; \
+ if (hi & 0xff00) \
+ P |= _fC; \
+ A = (lo & 0x0f) + (hi & 0xf0); \
+ H6280_CYCLES(1); \
+ } \
+ else \
+ { \
+ int c = (P & _fC); \
+ int sum = A + tmp + c; \
+ P &= ~(_fV | _fC); \
+ if (~(A^tmp) & (A^sum) & _fN) \
+ P |= _fV; \
+ if (sum & 0xff00) \
+ P |= _fC; \
+ A = (UINT8) sum; \
+ } \
+ SET_NZ(A); \
+ }
+
+/* 6280 ********************************************************
+ * AND Logical and
+ ***************************************************************/
+#define TAND \
+ { \
+ int tflagtemp; \
+ CLEAR_T; \
+ RD_TFL; \
+ tflagtemp = (UINT8)(tflagtemp & tmp); \
+ WB_TFL; \
+ SET_NZ(tflagtemp); \
+ H6280_CYCLES(3); \
+ }
+
+#define AND \
+ if(P & _fT) \
+ TAND \
+ else { \
+ A = (UINT8)(A & tmp); \
+ SET_NZ(A); \
+ }
+
+/* 6280 ********************************************************
+ * ASL Arithmetic shift left
+ ***************************************************************/
+#define ASL \
+ CLEAR_T; \
+ P = (P & ~_fC) | ((tmp >> 7) & _fC); \
+ tmp = (UINT8)(tmp << 1); \
+ SET_NZ(tmp)
+
+/* 6280 ********************************************************
+ * BBR Branch if bit is reset
+ ***************************************************************/
+#define BBR(bit) \
+ BRA(!(tmp & (1<<bit)))
+
+/* 6280 ********************************************************
+ * BBS Branch if bit is set
+ ***************************************************************/
+#define BBS(bit) \
+ BRA(tmp & (1<<bit))
+
+/* 6280 ********************************************************
+ * BCC Branch if carry clear
+ ***************************************************************/
+#define BCC BRA(!(P & _fC))
+
+/* 6280 ********************************************************
+ * BCS Branch if carry set
+ ***************************************************************/
+#define BCS BRA(P & _fC)
+
+/* 6280 ********************************************************
+ * BEQ Branch if equal
+ ***************************************************************/
+#if LAZY_FLAGS
+#define BEQ BRA(!(NZ & 0xff))
+#else
+#define BEQ BRA(P & _fZ)
+#endif
+
+/* 6280 ********************************************************
+ * BIT Bit test
+ ***************************************************************/
+#undef BIT
+#define BIT \
+ P = (P & ~(_fN|_fV|_fT|_fZ)) \
+ | ((tmp&0x80) ? _fN:0) \
+ | ((tmp&0x40) ? _fV:0) \
+ | ((tmp&A) ? 0:_fZ)
+
+/* 6280 ********************************************************
+ * BMI Branch if minus
+ ***************************************************************/
+#if LAZY_FLAGS
+#define BMI BRA(NZ & 0x8000)
+#else
+#define BMI BRA(P & _fN)
+#endif
+
+/* 6280 ********************************************************
+ * BNE Branch if not equal
+ ***************************************************************/
+#if LAZY_FLAGS
+#define BNE BRA(NZ & 0xff)
+#else
+#define BNE BRA(!(P & _fZ))
+#endif
+
+/* 6280 ********************************************************
+ * BPL Branch if plus
+ ***************************************************************/
+#if LAZY_FLAGS
+#define BPL BRA(!(NZ & 0x8000))
+#else
+#define BPL BRA(!(P & _fN))
+#endif
+
+/* 6280 ********************************************************
+ * BRK Break
+ * increment PC, push PC hi, PC lo, flags (with B bit set),
+ * set I flag, reset D flag and jump via IRQ vector
+ ***************************************************************/
+#define BRK \
+ logerror("BRK %04x\n",PCW); \
+ CLEAR_T; \
+ PCW++; \
+ PUSH(PCH); \
+ PUSH(PCL); \
+ PUSH(P); \
+ P = (P & ~_fD) | _fI; \
+ PCL = RDMEM(cpustate, H6280_IRQ2_VEC); \
+ PCH = RDMEM(cpustate, H6280_IRQ2_VEC+1); \
+
+/* 6280 ********************************************************
+ * BSR Branch to subroutine
+ ***************************************************************/
+#define BSR \
+ PUSH(PCH); \
+ PUSH(PCL); \
+ H6280_CYCLES(4); /* 4 cycles here, 4 in BRA */ \
+ BRA(1)
+
+/* 6280 ********************************************************
+ * BVC Branch if overflow clear
+ ***************************************************************/
+#define BVC BRA(!(P & _fV))
+
+/* 6280 ********************************************************
+ * BVS Branch if overflow set
+ ***************************************************************/
+#define BVS BRA(P & _fV)
+
+/* 6280 ********************************************************
+ * CLA Clear accumulator
+ ***************************************************************/
+#define CLA \
+ CLEAR_T; \
+ A = 0
+
+/* 6280 ********************************************************
+ * CLC Clear carry flag
+ ***************************************************************/
+#define CLC \
+ CLEAR_T; \
+ P &= ~_fC
+
+/* 6280 ********************************************************
+ * CLD Clear decimal flag
+ ***************************************************************/
+#define CLD \
+ CLEAR_T; \
+ P &= ~_fD
+
+/* 6280 ********************************************************
+ * CLI Clear interrupt flag
+ ***************************************************************/
+#define CLI \
+ CLEAR_T; \
+ if( P & _fI ) \
+ { \
+ P &= ~_fI; \
+ CHECK_IRQ_LINES; \
+ }
+
+
+/* 6280 ********************************************************
+ * CLV Clear overflow flag
+ ***************************************************************/
+#define CLV \
+ CLEAR_T; \
+ P &= ~_fV
+
+/* 6280 ********************************************************
+ * CLX Clear index X
+ ***************************************************************/
+#define CLX \
+ CLEAR_T; \
+ X = 0
+
+/* 6280 ********************************************************
+ * CLY Clear index Y
+ ***************************************************************/
+#define CLY \
+ CLEAR_T; \
+ Y = 0
+
+/* 6280 ********************************************************
+ * CMP Compare accumulator
+ ***************************************************************/
+#define CMP \
+ CLEAR_T; \
+ P &= ~_fC; \
+ if (A >= tmp) \
+ P |= _fC; \
+ SET_NZ((UINT8)(A - tmp))
+
+/* 6280 ********************************************************
+ * CPX Compare index X
+ ***************************************************************/
+#define CPX \
+ CLEAR_T; \
+ P &= ~_fC; \
+ if (X >= tmp) \
+ P |= _fC; \
+ SET_NZ((UINT8)(X - tmp))
+
+/* 6280 ********************************************************
+ * CPY Compare index Y
+ ***************************************************************/
+#define CPY \
+ CLEAR_T; \
+ P &= ~_fC; \
+ if (Y >= tmp) \
+ P |= _fC; \
+ SET_NZ((UINT8)(Y - tmp))
+
+/* 6280 ********************************************************
+ * DEA Decrement accumulator
+ ***************************************************************/
+#define DEA \
+ CLEAR_T; \
+ A = (UINT8)(A - 1); \
+ SET_NZ(A)
+
+/* 6280 ********************************************************
+ * DEC Decrement memory
+ ***************************************************************/
+#define DEC \
+ CLEAR_T; \
+ tmp = (UINT8)(tmp-1); \
+ SET_NZ(tmp)
+
+/* 6280 ********************************************************
+ * DEX Decrement index X
+ ***************************************************************/
+#define DEX \
+ CLEAR_T; \
+ X = (UINT8)(X - 1); \
+ SET_NZ(X)
+
+/* 6280 ********************************************************
+ * DEY Decrement index Y
+ ***************************************************************/
+#define DEY \
+ CLEAR_T; \
+ Y = (UINT8)(Y - 1); \
+ SET_NZ(Y)
+
+/* 6280 ********************************************************
+ * EOR Logical exclusive or
+ ***************************************************************/
+#define TEOR \
+ { \
+ int tflagtemp; \
+ CLEAR_T; \
+ RD_TFL; \
+ tflagtemp = (UINT8)(tflagtemp ^ tmp); \
+ WB_TFL; \
+ SET_NZ(tflagtemp); \
+ H6280_CYCLES(3); \
+ }
+
+#define EOR \
+ if(P & _fT) \
+ TEOR \
+ else { \
+ A = (UINT8)(A ^ tmp); \
+ SET_NZ(A); \
+ }
+
+/* 6280 ********************************************************
+ * INA Increment accumulator
+ ***************************************************************/
+#define INA \
+ CLEAR_T; \
+ A = (UINT8)(A + 1); \
+ SET_NZ(A)
+
+/* 6280 ********************************************************
+ * INC Increment memory
+ ***************************************************************/
+#define INC \
+ CLEAR_T; \
+ tmp = (UINT8)(tmp+1); \
+ SET_NZ(tmp)
+
+/* 6280 ********************************************************
+ * INX Increment index X
+ ***************************************************************/
+#define INX \
+ CLEAR_T; \
+ X = (UINT8)(X + 1); \
+ SET_NZ(X)
+
+/* 6280 ********************************************************
+ * INY Increment index Y
+ ***************************************************************/
+#define INY \
+ CLEAR_T; \
+ Y = (UINT8)(Y + 1); \
+ SET_NZ(Y)
+
+/* 6280 ********************************************************
+ * JMP Jump to address
+ * set PC to the effective address
+ ***************************************************************/
+#define JMP \
+ CLEAR_T; \
+ PCD = EAD; \
+
+/* 6280 ********************************************************
+ * JSR Jump to subroutine
+ * decrement PC (sic!) push PC hi, push PC lo and set
+ * PC to the effective address
+ ***************************************************************/
+#define JSR \
+ CLEAR_T; \
+ PCW--; \
+ PUSH(PCH); \
+ PUSH(PCL); \
+ PCD = EAD; \
+
+/* 6280 ********************************************************
+ * LDA Load accumulator
+ ***************************************************************/
+#define LDA \
+ CLEAR_T; \
+ A = (UINT8)tmp; \
+ SET_NZ(A)
+
+/* 6280 ********************************************************
+ * LDX Load index X
+ ***************************************************************/
+#define LDX \
+ CLEAR_T; \
+ X = (UINT8)tmp; \
+ SET_NZ(X)
+
+/* 6280 ********************************************************
+ * LDY Load index Y
+ ***************************************************************/
+#define LDY \
+ CLEAR_T; \
+ Y = (UINT8)tmp; \
+ SET_NZ(Y)
+
+/* 6280 ********************************************************
+ * LSR Logic shift right
+ * 0 -> [7][6][5][4][3][2][1][0] -> C
+ ***************************************************************/
+#define LSR \
+ CLEAR_T; \
+ P = (P & ~_fC) | (tmp & _fC); \
+ tmp = (UINT8)tmp >> 1; \
+ SET_NZ(tmp)
+
+/* 6280 ********************************************************
+ * NOP No operation
+ ***************************************************************/
+#define NOP CLEAR_T;
+
+/* 6280 ********************************************************
+ * ORA Logical inclusive or
+ ***************************************************************/
+
+#define TORA \
+ { \
+ int tflagtemp; \
+ CLEAR_T; \
+ RD_TFL; \
+ tflagtemp = (UINT8)(tflagtemp | tmp); \
+ WB_TFL; \
+ SET_NZ(tflagtemp); \
+ H6280_CYCLES(3); \
+ }
+
+#define ORA \
+ if(P & _fT) \
+ TORA \
+ else { \
+ A = (UINT8)(A | tmp); \
+ SET_NZ(A); \
+ }
+
+/* 6280 ********************************************************
+ * PHA Push accumulator
+ ***************************************************************/
+#define PHA \
+ CLEAR_T; \
+ PUSH(A)
+
+/* 6280 ********************************************************
+ * PHP Push processor status (flags)
+ ***************************************************************/
+#define PHP \
+ CLEAR_T; \
+ COMPOSE_P(0,0); \
+ PUSH(P)
+
+/* 6280 ********************************************************
+ * PHX Push index X
+ ***************************************************************/
+#define PHX \
+ CLEAR_T; \
+ PUSH(X)
+
+/* 6280 ********************************************************
+ * PHY Push index Y
+ ***************************************************************/
+#define PHY \
+ CLEAR_T; \
+ PUSH(Y)
+
+/* 6280 ********************************************************
+ * PLA Pull accumulator
+ ***************************************************************/
+#define PLA \
+ CLEAR_T; \
+ PULL(A); \
+ SET_NZ(A)
+
+/* 6280 ********************************************************
+ * PLP Pull processor status (flags)
+ ***************************************************************/
+#if LAZY_FLAGS
+
+#define PLP \
+ PULL(P); \
+ P |= _fB; \
+ NZ = ((P & _fN) << 8) | \
+ ((P & _fZ) ^ _fZ); \
+ CHECK_IRQ_LINES
+
+#else
+
+#define PLP \
+ PULL(P); \
+ P |= _fB; \
+ CHECK_IRQ_LINES
+#endif
+
+/* 6280 ********************************************************
+ * PLX Pull index X
+ ***************************************************************/
+#define PLX \
+ CLEAR_T; \
+ PULL(X); \
+ SET_NZ(X)
+
+/* 6280 ********************************************************
+ * PLY Pull index Y
+ ***************************************************************/
+#define PLY \
+ CLEAR_T; \
+ PULL(Y); \
+ SET_NZ(Y)
+
+/* 6280 ********************************************************
+ * RMB Reset memory bit
+ ***************************************************************/
+#define RMB(bit) \
+ CLEAR_T; \
+ tmp &= ~(1<<bit)
+
+/* 6280 ********************************************************
+ * ROL Rotate left
+ * new C <- [7][6][5][4][3][2][1][0] <- C
+ ***************************************************************/
+#define ROL \
+ CLEAR_T; \
+ tmp = (tmp << 1) | (P & _fC); \
+ P = (P & ~_fC) | ((tmp >> 8) & _fC); \
+ tmp = (UINT8)tmp; \
+ SET_NZ(tmp)
+
+/* 6280 ********************************************************
+ * ROR Rotate right
+ * C -> [7][6][5][4][3][2][1][0] -> new C
+ ***************************************************************/
+#define ROR \
+ CLEAR_T; \
+ tmp |= (P & _fC) << 8; \
+ P = (P & ~_fC) | (tmp & _fC); \
+ tmp = (UINT8)(tmp >> 1); \
+ SET_NZ(tmp)
+
+/* 6280 ********************************************************
+ * RTI Return from interrupt
+ * pull flags, pull PC lo, pull PC hi and increment PC
+ ***************************************************************/
+#if LAZY_FLAGS
+
+#define RTI \
+ PULL(P); \
+ P |= _fB; \
+ NZ = ((P & _fN) << 8) | \
+ ((P & _fZ) ^ _fZ); \
+ PULL(PCL); \
+ PULL(PCH); \
+ CHECK_IRQ_LINES
+#else
+
+#define RTI \
+ PULL(P); \
+ P |= _fB; \
+ PULL(PCL); \
+ PULL(PCH); \
+ CHECK_IRQ_LINES
+#endif
+
+/* 6280 ********************************************************
+ * RTS Return from subroutine
+ * pull PC lo, PC hi and increment PC
+ ***************************************************************/
+#define RTS \
+ CLEAR_T; \
+ PULL(PCL); \
+ PULL(PCH); \
+ PCW++;
+
+/* 6280 ********************************************************
+ * SAX Swap accumulator and index X
+ ***************************************************************/
+#define SAX \
+ CLEAR_T; \
+ tmp = X; \
+ X = A; \
+ A = tmp
+
+/* 6280 ********************************************************
+ * SAY Swap accumulator and index Y
+ ***************************************************************/
+#define SAY \
+ CLEAR_T; \
+ tmp = Y; \
+ Y = A; \
+ A = tmp
+
+/* 6280 ********************************************************
+ * SBC Subtract with carry
+ ***************************************************************/
+#define TSBC \
+ { \
+ int tflagtemp; \
+ CLEAR_T; \
+ RD_TFL; \
+ if (P & _fD) \
+ { \
+ int c = (P & _fC) ^ _fC; \
+ int sum = tflagtemp - tmp -c; \
+ int lo = (tflagtemp & 0x0f) - (tmp & 0x0f) - c; \
+ int hi = (tflagtemp & 0xf0) - (tmp & 0xf0); \
+ P &= ~_fC; \
+ if (lo & 0xf0) \
+ lo -= 6; \
+ if (lo & 0x80) \
+ hi -= 0x10; \
+ if (hi & 0x0f00) \
+ hi -= 0x60; \
+ if ((sum & 0xff00) == 0) \
+ P |= _fC; \
+ tflagtemp = (lo & 0x0f) + (hi & 0xf0); \
+ H6280_CYCLES(1); \
+ } \
+ else \
+ { \
+ int c = (P & _fC) ^ _fC; \
+ int sum = tflagtemp - tmp - c; \
+ P &= ~(_fV | _fC); \
+ if ((tflagtemp^tmp) & (tflagtemp^sum) & _fN) \
+ P |= _fV; \
+ if ((sum & 0xff00) == 0) \
+ P |= _fC; \
+ tflagtemp = (UINT8) sum; \
+ } \
+ SET_NZ(tflagtemp); \
+ WB_TFL; \
+ H6280_CYCLES(3); \
+ }
+
+#define SBC \
+ if(P & _fT) \
+ TSBC \
+ else { \
+ if (P & _fD) \
+ { \
+ int c = (P & _fC) ^ _fC; \
+ int sum = A - tmp - c; \
+ int lo = (A & 0x0f) - (tmp & 0x0f) - c; \
+ int hi = (A & 0xf0) - (tmp & 0xf0); \
+ P &= ~_fC; \
+ if (lo & 0xf0) \
+ lo -= 6; \
+ if (lo & 0x80) \
+ hi -= 0x10; \
+ if (hi & 0x0f00) \
+ hi -= 0x60; \
+ if ((sum & 0xff00) == 0) \
+ P |= _fC; \
+ A = (lo & 0x0f) + (hi & 0xf0); \
+ H6280_CYCLES(1); \
+ } \
+ else \
+ { \
+ int c = (P & _fC) ^ _fC; \
+ int sum = A - tmp - c; \
+ P &= ~(_fV | _fC); \
+ if ((A^tmp) & (A^sum) & _fN) \
+ P |= _fV; \
+ if ((sum & 0xff00) == 0) \
+ P |= _fC; \
+ A = (UINT8) sum; \
+ } \
+ SET_NZ(A); \
+ }
+
+/* 6280 ********************************************************
+ * SEC Set carry flag
+ ***************************************************************/
+#if defined(SEC)
+#undef SEC
+#endif
+#define SEC \
+ CLEAR_T; \
+ P |= _fC
+
+/* 6280 ********************************************************
+ * SED Set decimal flag
+ ***************************************************************/
+#define SED \
+ CLEAR_T; \
+ P |= _fD
+
+/* 6280 ********************************************************
+ * SEI Set interrupt flag
+ ***************************************************************/
+#define SEI \
+ CLEAR_T; \
+ P |= _fI
+
+/* 6280 ********************************************************
+ * SET Set t flag
+ ***************************************************************/
+#define SET \
+ P |= _fT;
+
+/* 6280 ********************************************************
+ * SMB Set memory bit
+ ***************************************************************/
+#define SMB(bit) \
+ CLEAR_T; \
+ tmp |= (1<<bit)
+
+/* 6280 ********************************************************
+ * ST0 Store at hardware address 0
+ ***************************************************************/
+#define ST0 \
+ CLEAR_T; \
+ cpustate->io->write_byte(0x0000,tmp)
+
+/* 6280 ********************************************************
+ * ST1 Store at hardware address 2
+ ***************************************************************/
+#define ST1 \
+ CLEAR_T; \
+ cpustate->io->write_byte(0x0002,tmp)
+
+/* 6280 ********************************************************
+ * ST2 Store at hardware address 3
+ ***************************************************************/
+#define ST2 \
+ CLEAR_T; \
+ cpustate->io->write_byte(0x0003,tmp)
+
+/* 6280 ********************************************************
+ * STA Store accumulator
+ ***************************************************************/
+#define STA \
+ CLEAR_T; \
+ tmp = A
+
+/* 6280 ********************************************************
+ * STX Store index X
+ ***************************************************************/
+#define STX \
+ CLEAR_T; \
+ tmp = X
+
+/* 6280 ********************************************************
+ * STY Store index Y
+ ***************************************************************/
+#define STY \
+ CLEAR_T; \
+ tmp = Y
+
+/* 6280 ********************************************************
+ * STZ Store zero
+ ***************************************************************/
+#define STZ \
+ CLEAR_T; \
+ tmp = 0
+
+/* H6280 *******************************************************
+ * SXY Swap index X and index Y
+ ***************************************************************/
+#define SXY \
+ CLEAR_T; \
+ tmp = X; \
+ X = Y; \
+ Y = tmp
+
+/* H6280 *******************************************************
+ * TAI Transfer Alternate Increment
+ ***************************************************************/
+#define TAI \
+ CLEAR_T; \
+ from=RDMEMW(PCW); \
+ to =RDMEMW(PCW+2); \
+ length=RDMEMW(PCW+4); \
+ PCW+=6; \
+ alternate=0; \
+ if (!length) length = 0x10000; \
+ H6280_CYCLES( ((6 * length) + 17) ); \
+ while ((length--) != 0) { \
+ WRMEM(cpustate, to,RDMEM(cpustate, from+alternate)); \
+ to++; \
+ alternate ^= 1; \
+ }
+
+/* H6280 *******************************************************
+ * TAM Transfer accumulator to memory mapper register(s)
+ ***************************************************************/
+#define TAM \
+ CLEAR_T; \
+ if (tmp&0x01) cpustate->mmr[0] = A; \
+ if (tmp&0x02) cpustate->mmr[1] = A; \
+ if (tmp&0x04) cpustate->mmr[2] = A; \
+ if (tmp&0x08) cpustate->mmr[3] = A; \
+ if (tmp&0x10) cpustate->mmr[4] = A; \
+ if (tmp&0x20) cpustate->mmr[5] = A; \
+ if (tmp&0x40) cpustate->mmr[6] = A; \
+ if (tmp&0x80) cpustate->mmr[7] = A
+
+/* 6280 ********************************************************
+ * TAX Transfer accumulator to index X
+ ***************************************************************/
+#define TAX \
+ CLEAR_T; \
+ X = A; \
+ SET_NZ(X)
+
+/* 6280 ********************************************************
+ * TAY Transfer accumulator to index Y
+ ***************************************************************/
+#define TAY \
+ CLEAR_T; \
+ Y = A; \
+ SET_NZ(Y)
+
+/* 6280 ********************************************************
+ * TDD Transfer Decrement Decrement
+ ***************************************************************/
+#define TDD \
+ CLEAR_T; \
+ from=RDMEMW(PCW); \
+ to =RDMEMW(PCW+2); \
+ length=RDMEMW(PCW+4); \
+ PCW+=6; \
+ if (!length) length = 0x10000; \
+ H6280_CYCLES( ((6 * length) + 17) ); \
+ while ((length--) != 0) { \
+ WRMEM(cpustate, to,RDMEM(cpustate, from)); \
+ to--; \
+ from--; \
+ }
+
+/* 6280 ********************************************************
+ * TIA Transfer Increment Alternate
+ ***************************************************************/
+#define TIA \
+ CLEAR_T; \
+ from=RDMEMW(PCW); \
+ to =RDMEMW(PCW+2); \
+ length=RDMEMW(PCW+4); \
+ PCW+=6; \
+ alternate=0; \
+ if (!length) length = 0x10000; \
+ H6280_CYCLES( ((6 * length) + 17) ); \
+ while ((length--) != 0) { \
+ WRMEM(cpustate, to+alternate,RDMEM(cpustate, from)); \
+ from++; \
+ alternate ^= 1; \
+ }
+
+/* 6280 ********************************************************
+ * TII Transfer Increment Increment
+ ***************************************************************/
+#define TII \
+ CLEAR_T; \
+ from=RDMEMW(PCW); \
+ to =RDMEMW(PCW+2); \
+ length=RDMEMW(PCW+4); \
+ PCW+=6; \
+ if (!length) length = 0x10000; \
+ H6280_CYCLES( ((6 * length) + 17) ); \
+ while ((length--) != 0) { \
+ WRMEM(cpustate, to,RDMEM(cpustate, from)); \
+ to++; \
+ from++; \
+ }
+
+/* 6280 ********************************************************
+ * TIN Transfer block, source increments every loop
+ ***************************************************************/
+#define TIN \
+ CLEAR_T; \
+ from=RDMEMW(PCW); \
+ to =RDMEMW(PCW+2); \
+ length=RDMEMW(PCW+4); \
+ PCW+=6; \
+ if (!length) length = 0x10000; \
+ H6280_CYCLES( ((6 * length) + 17) ); \
+ while ((length--) != 0) { \
+ WRMEM(cpustate, to,RDMEM(cpustate, from)); \
+ from++; \
+ }
+
+/* 6280 ********************************************************
+ * TMA Transfer memory mapper register(s) to accumulator
+ * the highest bit set in tmp is the one that counts
+ ***************************************************************/
+#define TMA \
+ CLEAR_T; \
+ if (tmp&0x01) A = cpustate->mmr[0]; \
+ if (tmp&0x02) A = cpustate->mmr[1]; \
+ if (tmp&0x04) A = cpustate->mmr[2]; \
+ if (tmp&0x08) A = cpustate->mmr[3]; \
+ if (tmp&0x10) A = cpustate->mmr[4]; \
+ if (tmp&0x20) A = cpustate->mmr[5]; \
+ if (tmp&0x40) A = cpustate->mmr[6]; \
+ if (tmp&0x80) A = cpustate->mmr[7]
+
+/* 6280 ********************************************************
+ * TRB Test and reset bits
+ ***************************************************************/
+#define TRB \
+ CLEAR_T; \
+ P = (P & ~(_fN|_fV|_fT|_fZ)) \
+ | ((tmp&0x80) ? _fN:0) \
+ | ((tmp&0x40) ? _fV:0) \
+ | ((tmp&~A) ? 0:_fZ); \
+ tmp &= ~A
+
+/* 6280 ********************************************************
+ * TSB Test and set bits
+ ***************************************************************/
+#define TSB \
+ CLEAR_T; \
+ P = (P & ~(_fN|_fV|_fT|_fZ)) \
+ | ((tmp&0x80) ? _fN:0) \
+ | ((tmp&0x40) ? _fV:0) \
+ | ((tmp|A) ? 0:_fZ); \
+ tmp |= A
+
+/* 6280 ********************************************************
+ * TSX Transfer stack LSB to index X
+ ***************************************************************/
+#define TSX \
+ CLEAR_T; \
+ X = S; \
+ SET_NZ(X)
+
+/* 6280 ********************************************************
+ * TST
+ ***************************************************************/
+#define TST \
+ P = (P & ~(_fN|_fV|_fT|_fZ)) \
+ | ((tmp&0x80) ? _fN:0) \
+ | ((tmp&0x40) ? _fV:0) \
+ | ((tmp&tmp2) ? 0:_fZ)
+
+/* 6280 ********************************************************
+ * TXA Transfer index X to accumulator
+ ***************************************************************/
+#define TXA \
+ CLEAR_T; \
+ A = X; \
+ SET_NZ(A)
+
+/* 6280 ********************************************************
+ * TXS Transfer index X to stack LSB
+ * no flags changed (sic!)
+ ***************************************************************/
+#define TXS \
+ CLEAR_T; \
+ S = X
+
+/* 6280 ********************************************************
+ * TYA Transfer index Y to accumulator
+ ***************************************************************/
+#define TYA \
+ CLEAR_T; \
+ A = Y; \
+ SET_NZ(A)
+
+/* 6280 ********************************************************
+ * CSH Set CPU in high speed mode
+ ***************************************************************/
+#define CSH \
+ cpustate->clocks_per_cycle = 1;
+
+/* 6280 ********************************************************
+ * CSL Set CPU in low speed mode
+ ***************************************************************/
+#define CSL \
+ cpustate->clocks_per_cycle = 4;
diff --git a/trunk/src/emu/cpu/h6280/tblh6280.c b/trunk/src/emu/cpu/h6280/tblh6280.c
new file mode 100644
index 00000000000..1795741c4ba
--- /dev/null
+++ b/trunk/src/emu/cpu/h6280/tblh6280.c
@@ -0,0 +1,344 @@
+/*****************************************************************************
+
+ tblh6280.c
+
+ Copyright Bryan McPhail, mish@tendril.co.uk
+
+ This source code is based (with permission!) on the 6502 emulator by
+ Juergen Buchmueller. It is released as part of the Mame emulator project.
+ Let me know if you intend to use this code in any other project.
+
+******************************************************************************/
+
+#undef OP
+#define OP(nnn) INLINE void h6280##nnn(h6280_Regs* cpustate)
+
+/*****************************************************************************
+ *****************************************************************************
+ *
+ * Hu6280 opcodes
+ *
+ *****************************************************************************
+ * op temp cycles rdmem opc wrmem ******************/
+OP(_000) { H6280_CYCLES(8); BRK; } // 8 BRK
+OP(_020) { H6280_CYCLES(7); EA_ABS; JSR; } // 7 JSR ABS
+OP(_040) { H6280_CYCLES(7); RTI; } // 7 RTI
+OP(_060) { H6280_CYCLES(7); RTS; } // 7 RTS
+OP(_080) { int tmp; BRA(1); } // 4 BRA REL
+OP(_0a0) { int tmp; H6280_CYCLES(2); RD_IMM; LDY; } // 2 LDY IMM
+OP(_0c0) { int tmp; H6280_CYCLES(2); RD_IMM; CPY; } // 2 CPY IMM
+OP(_0e0) { int tmp; H6280_CYCLES(2); RD_IMM; CPX; } // 2 CPX IMM
+
+OP(_010) { int tmp; BPL; } // 2/4 BPL REL
+OP(_030) { int tmp; BMI; } // 2/4 BMI REL
+OP(_050) { int tmp; BVC; } // 2/4 BVC REL
+OP(_070) { int tmp; BVS; } // 2/4 BVS REL
+OP(_090) { int tmp; BCC; } // 2/4 BCC REL
+OP(_0b0) { int tmp; BCS; } // 2/4 BCS REL
+OP(_0d0) { int tmp; BNE; } // 2/4 BNE REL
+OP(_0f0) { int tmp; BEQ; } // 2/4 BEQ REL
+
+OP(_001) { int tmp; H6280_CYCLES(7); RD_IDX; ORA; } // 7 ORA IDX
+OP(_021) { int tmp; H6280_CYCLES(7); RD_IDX; AND; } // 7 AND IDX
+OP(_041) { int tmp; H6280_CYCLES(7); RD_IDX; EOR; } // 7 EOR IDX
+OP(_061) { int tmp; H6280_CYCLES(7); RD_IDX; ADC; } // 7 ADC IDX
+OP(_081) { int tmp; H6280_CYCLES(7); STA; WR_IDX; } // 7 STA IDX
+OP(_0a1) { int tmp; H6280_CYCLES(7); RD_IDX; LDA; } // 7 LDA IDX
+OP(_0c1) { int tmp; H6280_CYCLES(7); RD_IDX; CMP; } // 7 CMP IDX
+OP(_0e1) { int tmp; H6280_CYCLES(7); RD_IDX; SBC; } // 7 SBC IDX
+
+OP(_011) { int tmp; H6280_CYCLES(7); RD_IDY; ORA; } // 7 ORA IDY
+OP(_031) { int tmp; H6280_CYCLES(7); RD_IDY; AND; } // 7 AND IDY
+OP(_051) { int tmp; H6280_CYCLES(7); RD_IDY; EOR; } // 7 EOR IDY
+OP(_071) { int tmp; H6280_CYCLES(7); RD_IDY; ADC; } // 7 ADC AZP
+OP(_091) { int tmp; H6280_CYCLES(7); STA; WR_IDY; } // 7 STA IDY
+OP(_0b1) { int tmp; H6280_CYCLES(7); RD_IDY; LDA; } // 7 LDA IDY
+OP(_0d1) { int tmp; H6280_CYCLES(7); RD_IDY; CMP; } // 7 CMP IDY
+OP(_0f1) { int tmp; H6280_CYCLES(7); RD_IDY; SBC; } // 7 SBC IDY
+
+OP(_002) { int tmp; H6280_CYCLES(3); SXY; } // 3 SXY
+OP(_022) { int tmp; H6280_CYCLES(3); SAX; } // 3 SAX
+OP(_042) { int tmp; H6280_CYCLES(3); SAY; } // 3 SAY
+OP(_062) { H6280_CYCLES(2); CLA; } // 2 CLA
+OP(_082) { H6280_CYCLES(2); CLX; } // 2 CLX
+OP(_0a2) { int tmp; H6280_CYCLES(2); RD_IMM; LDX; } // 2 LDX IMM
+OP(_0c2) { H6280_CYCLES(2); CLY; } // 2 CLY
+OP(_0e2) { H6280_CYCLES(2); NOP; } // 2 NOP
+
+OP(_012) { int tmp; H6280_CYCLES(7); RD_ZPI; ORA; } // 7 ORA ZPI
+OP(_032) { int tmp; H6280_CYCLES(7); RD_ZPI; AND; } // 7 AND ZPI
+OP(_052) { int tmp; H6280_CYCLES(7); RD_ZPI; EOR; } // 7 EOR ZPI
+OP(_072) { int tmp; H6280_CYCLES(7); RD_ZPI; ADC; } // 7 ADC ZPI
+OP(_092) { int tmp; H6280_CYCLES(7); STA; WR_ZPI; } // 7 STA ZPI
+OP(_0b2) { int tmp; H6280_CYCLES(7); RD_ZPI; LDA; } // 7 LDA ZPI
+OP(_0d2) { int tmp; H6280_CYCLES(7); RD_ZPI; CMP; } // 7 CMP ZPI
+OP(_0f2) { int tmp; H6280_CYCLES(7); RD_ZPI; SBC; } // 7 SBC ZPI
+
+OP(_003) { int tmp; H6280_CYCLES(5); RD_IMM; ST0; } // 4 + 1 penalty cycle ST0 IMM
+OP(_023) { int tmp; H6280_CYCLES(5); RD_IMM; ST2; } // 4 + 1 penalty cycle ST2 IMM
+OP(_043) { int tmp; H6280_CYCLES(4); RD_IMM; TMA; } // 4 TMA
+OP(_063) { H6280_CYCLES(4); NOP; } // 2 NOP
+OP(_083) { int tmp,tmp2; H6280_CYCLES(7); RD_IMM2; RD_ZPG; TST; } // 7 TST IMM,ZPG
+OP(_0a3) { int tmp,tmp2; H6280_CYCLES(7); RD_IMM2; RD_ZPX; TST; } // 7 TST IMM,ZPX
+OP(_0c3) { int to,from,length; TDD; } // 6*l+17 TDD XFER
+OP(_0e3) { int to,from,length,alternate; TIA; } // 6*l+17 TIA XFER
+
+OP(_013) { int tmp; H6280_CYCLES(5); RD_IMM; ST1; } // 4 + 1 penalty cycle ST1
+OP(_033) { H6280_CYCLES(2); NOP; } // 2 NOP
+OP(_053) { int tmp; H6280_CYCLES(5); RD_IMM; TAM; } // 5 TAM IMM
+OP(_073) { int to,from,length; TII; } // 6*l+17 TII XFER
+OP(_093) { int tmp,tmp2; H6280_CYCLES(8); RD_IMM2; RD_ABS; TST; } // 8 TST IMM,ABS
+OP(_0b3) { int tmp,tmp2; H6280_CYCLES(8); RD_IMM2; RD_ABX; TST; } // 8 TST IMM,ABX
+OP(_0d3) { int to,from,length; TIN; } // 6*l+17 TIN XFER
+OP(_0f3) { int to,from,length,alternate; TAI; } // 6*l+17 TAI XFER
+
+OP(_004) { int tmp; H6280_CYCLES(6); RD_ZPG; TSB; WB_EAZ; } // 6 TSB ZPG
+OP(_024) { int tmp; H6280_CYCLES(4); RD_ZPG; BIT; } // 4 BIT ZPG
+OP(_044) { int tmp; BSR; } // 8 BSR REL
+OP(_064) { int tmp; H6280_CYCLES(4); STZ; WR_ZPG; } // 4 STZ ZPG
+OP(_084) { int tmp; H6280_CYCLES(4); STY; WR_ZPG; } // 4 STY ZPG
+OP(_0a4) { int tmp; H6280_CYCLES(4); RD_ZPG; LDY; } // 4 LDY ZPG
+OP(_0c4) { int tmp; H6280_CYCLES(4); RD_ZPG; CPY; } // 4 CPY ZPG
+OP(_0e4) { int tmp; H6280_CYCLES(4); RD_ZPG; CPX; } // 4 CPX ZPG
+
+OP(_014) { int tmp; H6280_CYCLES(6); RD_ZPG; TRB; WB_EAZ; } // 6 TRB ZPG
+OP(_034) { int tmp; H6280_CYCLES(4); RD_ZPX; BIT; } // 4 BIT ZPX
+OP(_054) { H6280_CYCLES(3); CSL; } // 3 CSL
+OP(_074) { int tmp; H6280_CYCLES(4); STZ; WR_ZPX; } // 4 STZ ZPX
+OP(_094) { int tmp; H6280_CYCLES(4); STY; WR_ZPX; } // 4 STY ZPX
+OP(_0b4) { int tmp; H6280_CYCLES(4); RD_ZPX; LDY; } // 4 LDY ZPX
+OP(_0d4) { H6280_CYCLES(3); CSH; } // 3 CSH
+OP(_0f4) { H6280_CYCLES(2); SET; } // 2 SET
+
+OP(_005) { int tmp; H6280_CYCLES(4); RD_ZPG; ORA; } // 4 ORA ZPG
+OP(_025) { int tmp; H6280_CYCLES(4); RD_ZPG; AND; } // 4 AND ZPG
+OP(_045) { int tmp; H6280_CYCLES(4); RD_ZPG; EOR; } // 4 EOR ZPG
+OP(_065) { int tmp; H6280_CYCLES(4); RD_ZPG; ADC; } // 4 ADC ZPG
+OP(_085) { int tmp; H6280_CYCLES(4); STA; WR_ZPG; } // 4 STA ZPG
+OP(_0a5) { int tmp; H6280_CYCLES(4); RD_ZPG; LDA; } // 4 LDA ZPG
+OP(_0c5) { int tmp; H6280_CYCLES(4); RD_ZPG; CMP; } // 4 CMP ZPG
+OP(_0e5) { int tmp; H6280_CYCLES(4); RD_ZPG; SBC; } // 4 SBC ZPG
+
+OP(_015) { int tmp; H6280_CYCLES(4); RD_ZPX; ORA; } // 4 ORA ZPX
+OP(_035) { int tmp; H6280_CYCLES(4); RD_ZPX; AND; } // 4 AND ZPX
+OP(_055) { int tmp; H6280_CYCLES(4); RD_ZPX; EOR; } // 4 EOR ZPX
+OP(_075) { int tmp; H6280_CYCLES(4); RD_ZPX; ADC; } // 4 ADC ZPX
+OP(_095) { int tmp; H6280_CYCLES(4); STA; WR_ZPX; } // 4 STA ZPX
+OP(_0b5) { int tmp; H6280_CYCLES(4); RD_ZPX; LDA; } // 4 LDA ZPX
+OP(_0d5) { int tmp; H6280_CYCLES(4); RD_ZPX; CMP; } // 4 CMP ZPX
+OP(_0f5) { int tmp; H6280_CYCLES(4); RD_ZPX; SBC; } // 4 SBC ZPX
+
+OP(_006) { int tmp; H6280_CYCLES(6); RD_ZPG; ASL; WB_EAZ; } // 6 ASL ZPG
+OP(_026) { int tmp; H6280_CYCLES(6); RD_ZPG; ROL; WB_EAZ; } // 6 ROL ZPG
+OP(_046) { int tmp; H6280_CYCLES(6); RD_ZPG; LSR; WB_EAZ; } // 6 LSR ZPG
+OP(_066) { int tmp; H6280_CYCLES(6); RD_ZPG; ROR; WB_EAZ; } // 6 ROR ZPG
+OP(_086) { int tmp; H6280_CYCLES(4); STX; WR_ZPG; } // 4 STX ZPG
+OP(_0a6) { int tmp; H6280_CYCLES(4); RD_ZPG; LDX; } // 4 LDX ZPG
+OP(_0c6) { int tmp; H6280_CYCLES(6); RD_ZPG; DEC; WB_EAZ; } // 6 DEC ZPG
+OP(_0e6) { int tmp; H6280_CYCLES(6); RD_ZPG; INC; WB_EAZ; } // 6 INC ZPG
+
+OP(_016) { int tmp; H6280_CYCLES(6); RD_ZPX; ASL; WB_EAZ } // 6 ASL ZPX
+OP(_036) { int tmp; H6280_CYCLES(6); RD_ZPX; ROL; WB_EAZ } // 6 ROL ZPX
+OP(_056) { int tmp; H6280_CYCLES(6); RD_ZPX; LSR; WB_EAZ } // 6 LSR ZPX
+OP(_076) { int tmp; H6280_CYCLES(6); RD_ZPX; ROR; WB_EAZ } // 6 ROR ZPX
+OP(_096) { int tmp; H6280_CYCLES(4); STX; WR_ZPY; } // 4 STX ZPY
+OP(_0b6) { int tmp; H6280_CYCLES(4); RD_ZPY; LDX; } // 4 LDX ZPY
+OP(_0d6) { int tmp; H6280_CYCLES(6); RD_ZPX; DEC; WB_EAZ; } // 6 DEC ZPX
+OP(_0f6) { int tmp; H6280_CYCLES(6); RD_ZPX; INC; WB_EAZ; } // 6 INC ZPX
+
+OP(_007) { int tmp; H6280_CYCLES(7); RD_ZPG; RMB(0);WB_EAZ;} // 7 RMB0 ZPG
+OP(_027) { int tmp; H6280_CYCLES(7); RD_ZPG; RMB(2);WB_EAZ;} // 7 RMB2 ZPG
+OP(_047) { int tmp; H6280_CYCLES(7); RD_ZPG; RMB(4);WB_EAZ;} // 7 RMB4 ZPG
+OP(_067) { int tmp; H6280_CYCLES(7); RD_ZPG; RMB(6);WB_EAZ;} // 7 RMB6 ZPG
+OP(_087) { int tmp; H6280_CYCLES(7); RD_ZPG; SMB(0);WB_EAZ;} // 7 SMB0 ZPG
+OP(_0a7) { int tmp; H6280_CYCLES(7); RD_ZPG; SMB(2);WB_EAZ;} // 7 SMB2 ZPG
+OP(_0c7) { int tmp; H6280_CYCLES(7); RD_ZPG; SMB(4);WB_EAZ;} // 7 SMB4 ZPG
+OP(_0e7) { int tmp; H6280_CYCLES(7); RD_ZPG; SMB(6);WB_EAZ;} // 7 SMB6 ZPG
+
+OP(_017) { int tmp; H6280_CYCLES(7); RD_ZPG; RMB(1);WB_EAZ;} // 7 RMB1 ZPG
+OP(_037) { int tmp; H6280_CYCLES(7); RD_ZPG; RMB(3);WB_EAZ;} // 7 RMB3 ZPG
+OP(_057) { int tmp; H6280_CYCLES(7); RD_ZPG; RMB(5);WB_EAZ;} // 7 RMB5 ZPG
+OP(_077) { int tmp; H6280_CYCLES(7); RD_ZPG; RMB(7);WB_EAZ;} // 7 RMB7 ZPG
+OP(_097) { int tmp; H6280_CYCLES(7); RD_ZPG; SMB(1);WB_EAZ;} // 7 SMB1 ZPG
+OP(_0b7) { int tmp; H6280_CYCLES(7); RD_ZPG; SMB(3);WB_EAZ;} // 7 SMB3 ZPG
+OP(_0d7) { int tmp; H6280_CYCLES(7); RD_ZPG; SMB(5);WB_EAZ;} // 7 SMB5 ZPG
+OP(_0f7) { int tmp; H6280_CYCLES(7); RD_ZPG; SMB(7);WB_EAZ;} // 7 SMB7 ZPG
+
+OP(_008) { H6280_CYCLES(3); PHP; } // 3 PHP
+OP(_028) { H6280_CYCLES(4); PLP; } // 4 PLP
+OP(_048) { H6280_CYCLES(3); PHA; } // 3 PHA
+OP(_068) { H6280_CYCLES(4); PLA; } // 4 PLA
+OP(_088) { H6280_CYCLES(2); DEY; } // 2 DEY
+OP(_0a8) { H6280_CYCLES(2); TAY; } // 2 TAY
+OP(_0c8) { H6280_CYCLES(2); INY; } // 2 INY
+OP(_0e8) { H6280_CYCLES(2); INX; } // 2 INX
+
+OP(_018) { H6280_CYCLES(2); CLC; } // 2 CLC
+OP(_038) { H6280_CYCLES(2); SEC; } // 2 SEC
+OP(_058) { H6280_CYCLES(2); CLI; } // 2 CLI
+OP(_078) { H6280_CYCLES(2); SEI; } // 2 SEI
+OP(_098) { H6280_CYCLES(2); TYA; } // 2 TYA
+OP(_0b8) { H6280_CYCLES(2); CLV; } // 2 CLV
+OP(_0d8) { H6280_CYCLES(2); CLD; } // 2 CLD
+OP(_0f8) { H6280_CYCLES(2); SED; } // 2 SED
+
+OP(_009) { int tmp; H6280_CYCLES(2); RD_IMM; ORA; } // 2 ORA IMM
+OP(_029) { int tmp; H6280_CYCLES(2); RD_IMM; AND; } // 2 AND IMM
+OP(_049) { int tmp; H6280_CYCLES(2); RD_IMM; EOR; } // 2 EOR IMM
+OP(_069) { int tmp; H6280_CYCLES(2); RD_IMM; ADC; } // 2 ADC IMM
+OP(_089) { int tmp; H6280_CYCLES(2); RD_IMM; BIT; } // 2 BIT IMM
+OP(_0a9) { int tmp; H6280_CYCLES(2); RD_IMM; LDA; } // 2 LDA IMM
+OP(_0c9) { int tmp; H6280_CYCLES(2); RD_IMM; CMP; } // 2 CMP IMM
+OP(_0e9) { int tmp; H6280_CYCLES(2); RD_IMM; SBC; } // 2 SBC IMM
+
+OP(_019) { int tmp; H6280_CYCLES(5); RD_ABY; ORA; } // 5 ORA ABY
+OP(_039) { int tmp; H6280_CYCLES(5); RD_ABY; AND; } // 5 AND ABY
+OP(_059) { int tmp; H6280_CYCLES(5); RD_ABY; EOR; } // 5 EOR ABY
+OP(_079) { int tmp; H6280_CYCLES(5); RD_ABY; ADC; } // 5 ADC ABY
+OP(_099) { int tmp; H6280_CYCLES(5); STA; WR_ABY; } // 5 STA ABY
+OP(_0b9) { int tmp; H6280_CYCLES(5); RD_ABY; LDA; } // 5 LDA ABY
+OP(_0d9) { int tmp; H6280_CYCLES(5); RD_ABY; CMP; } // 5 CMP ABY
+OP(_0f9) { int tmp; H6280_CYCLES(5); RD_ABY; SBC; } // 5 SBC ABY
+
+OP(_00a) { int tmp; H6280_CYCLES(2); RD_ACC; ASL; WB_ACC; } // 2 ASL A
+OP(_02a) { int tmp; H6280_CYCLES(2); RD_ACC; ROL; WB_ACC; } // 2 ROL A
+OP(_04a) { int tmp; H6280_CYCLES(2); RD_ACC; LSR; WB_ACC; } // 2 LSR A
+OP(_06a) { int tmp; H6280_CYCLES(2); RD_ACC; ROR; WB_ACC; } // 2 ROR A
+OP(_08a) { H6280_CYCLES(2); TXA; } // 2 TXA
+OP(_0aa) { H6280_CYCLES(2); TAX; } // 2 TAX
+OP(_0ca) { H6280_CYCLES(2); DEX; } // 2 DEX
+OP(_0ea) { H6280_CYCLES(2); NOP; } // 2 NOP
+
+OP(_01a) { H6280_CYCLES(2); INA; } // 2 INC A
+OP(_03a) { H6280_CYCLES(2); DEA; } // 2 DEC A
+OP(_05a) { H6280_CYCLES(3); PHY; } // 3 PHY
+OP(_07a) { H6280_CYCLES(4); PLY; } // 4 PLY
+OP(_09a) { H6280_CYCLES(2); TXS; } // 2 TXS
+OP(_0ba) { H6280_CYCLES(2); TSX; } // 2 TSX
+OP(_0da) { H6280_CYCLES(3); PHX; } // 3 PHX
+OP(_0fa) { H6280_CYCLES(4); PLX; } // 4 PLX
+
+OP(_00b) { H6280_CYCLES(2); NOP; } // 2 NOP
+OP(_02b) { H6280_CYCLES(2); NOP; } // 2 NOP
+OP(_04b) { H6280_CYCLES(2); NOP; } // 2 NOP
+OP(_06b) { H6280_CYCLES(2); NOP; } // 2 NOP
+OP(_08b) { H6280_CYCLES(2); NOP; } // 2 NOP
+OP(_0ab) { H6280_CYCLES(2); NOP; } // 2 NOP
+OP(_0cb) { H6280_CYCLES(2); NOP; } // 2 NOP
+OP(_0eb) { H6280_CYCLES(2); NOP; } // 2 NOP
+
+OP(_01b) { H6280_CYCLES(2); NOP; } // 2 NOP
+OP(_03b) { H6280_CYCLES(2); NOP; } // 2 NOP
+OP(_05b) { H6280_CYCLES(2); NOP; } // 2 NOP
+OP(_07b) { H6280_CYCLES(2); NOP; } // 2 NOP
+OP(_09b) { H6280_CYCLES(2); NOP; } // 2 NOP
+OP(_0bb) { H6280_CYCLES(2); NOP; } // 2 NOP
+OP(_0db) { H6280_CYCLES(2); NOP; } // 2 NOP
+OP(_0fb) { H6280_CYCLES(2); NOP; } // 2 NOP
+
+OP(_00c) { int tmp; H6280_CYCLES(7); RD_ABS; TSB; WB_EA; } // 7 TSB ABS
+OP(_02c) { int tmp; H6280_CYCLES(5); RD_ABS; BIT; } // 5 BIT ABS
+OP(_04c) { H6280_CYCLES(4); EA_ABS; JMP; } // 4 JMP ABS
+OP(_06c) { int tmp; H6280_CYCLES(7); EA_IND; JMP; } // 7 JMP IND
+OP(_08c) { int tmp; H6280_CYCLES(5); STY; WR_ABS; } // 5 STY ABS
+OP(_0ac) { int tmp; H6280_CYCLES(5); RD_ABS; LDY; } // 5 LDY ABS
+OP(_0cc) { int tmp; H6280_CYCLES(5); RD_ABS; CPY; } // 5 CPY ABS
+OP(_0ec) { int tmp; H6280_CYCLES(5); RD_ABS; CPX; } // 5 CPX ABS
+
+OP(_01c) { int tmp; H6280_CYCLES(7); RD_ABS; TRB; WB_EA; } // 7 TRB ABS
+OP(_03c) { int tmp; H6280_CYCLES(5); RD_ABX; BIT; } // 5 BIT ABX
+OP(_05c) { H6280_CYCLES(2); NOP; } // 2 NOP
+OP(_07c) { int tmp; H6280_CYCLES(7); EA_IAX; JMP; } // 7 JMP IAX
+OP(_09c) { int tmp; H6280_CYCLES(5); STZ; WR_ABS; } // 5 STZ ABS
+OP(_0bc) { int tmp; H6280_CYCLES(5); RD_ABX; LDY; } // 5 LDY ABX
+OP(_0dc) { H6280_CYCLES(2); NOP; } // 2 NOP
+OP(_0fc) { H6280_CYCLES(2); NOP; } // 2 NOP
+
+OP(_00d) { int tmp; H6280_CYCLES(5); RD_ABS; ORA; } // 5 ORA ABS
+OP(_02d) { int tmp; H6280_CYCLES(5); RD_ABS; AND; } // 5 AND ABS
+OP(_04d) { int tmp; H6280_CYCLES(5); RD_ABS; EOR; } // 5 EOR ABS
+OP(_06d) { int tmp; H6280_CYCLES(5); RD_ABS; ADC; } // 5 ADC ABS
+OP(_08d) { int tmp; H6280_CYCLES(5); STA; WR_ABS; } // 5 STA ABS
+OP(_0ad) { int tmp; H6280_CYCLES(5); RD_ABS; LDA; } // 5 LDA ABS
+OP(_0cd) { int tmp; H6280_CYCLES(5); RD_ABS; CMP; } // 5 CMP ABS
+OP(_0ed) { int tmp; H6280_CYCLES(5); RD_ABS; SBC; } // 5 SBC ABS
+
+OP(_01d) { int tmp; H6280_CYCLES(5); RD_ABX; ORA; } // 5 ORA ABX
+OP(_03d) { int tmp; H6280_CYCLES(5); RD_ABX; AND; } // 5 AND ABX
+OP(_05d) { int tmp; H6280_CYCLES(5); RD_ABX; EOR; } // 5 EOR ABX
+OP(_07d) { int tmp; H6280_CYCLES(5); RD_ABX; ADC; } // 5 ADC ABX
+OP(_09d) { int tmp; H6280_CYCLES(5); STA; WR_ABX; } // 5 STA ABX
+OP(_0bd) { int tmp; H6280_CYCLES(5); RD_ABX; LDA; } // 5 LDA ABX
+OP(_0dd) { int tmp; H6280_CYCLES(5); RD_ABX; CMP; } // 5 CMP ABX
+OP(_0fd) { int tmp; H6280_CYCLES(5); RD_ABX; SBC; } // 5 SBC ABX
+
+OP(_00e) { int tmp; H6280_CYCLES(7); RD_ABS; ASL; WB_EA; } // 7 ASL ABS
+OP(_02e) { int tmp; H6280_CYCLES(7); RD_ABS; ROL; WB_EA; } // 7 ROL ABS
+OP(_04e) { int tmp; H6280_CYCLES(7); RD_ABS; LSR; WB_EA; } // 7 LSR ABS
+OP(_06e) { int tmp; H6280_CYCLES(7); RD_ABS; ROR; WB_EA; } // 7 ROR ABS
+OP(_08e) { int tmp; H6280_CYCLES(5); STX; WR_ABS; } // 5 STX ABS
+OP(_0ae) { int tmp; H6280_CYCLES(5); RD_ABS; LDX; } // 5 LDX ABS
+OP(_0ce) { int tmp; H6280_CYCLES(7); RD_ABS; DEC; WB_EA; } // 7 DEC ABS
+OP(_0ee) { int tmp; H6280_CYCLES(7); RD_ABS; INC; WB_EA; } // 7 INC ABS
+
+OP(_01e) { int tmp; H6280_CYCLES(7); RD_ABX; ASL; WB_EA; } // 7 ASL ABX
+OP(_03e) { int tmp; H6280_CYCLES(7); RD_ABX; ROL; WB_EA; } // 7 ROL ABX
+OP(_05e) { int tmp; H6280_CYCLES(7); RD_ABX; LSR; WB_EA; } // 7 LSR ABX
+OP(_07e) { int tmp; H6280_CYCLES(7); RD_ABX; ROR; WB_EA; } // 7 ROR ABX
+OP(_09e) { int tmp; H6280_CYCLES(5); STZ; WR_ABX; } // 5 STZ ABX
+OP(_0be) { int tmp; H6280_CYCLES(5); RD_ABY; LDX; } // 5 LDX ABY
+OP(_0de) { int tmp; H6280_CYCLES(7); RD_ABX; DEC; WB_EA; } // 7 DEC ABX
+OP(_0fe) { int tmp; H6280_CYCLES(7); RD_ABX; INC; WB_EA; } // 7 INC ABX
+
+OP(_00f) { int tmp; H6280_CYCLES(4); RD_ZPG; BBR(0); } // 6/8 BBR0 ZPG,REL
+OP(_02f) { int tmp; H6280_CYCLES(4); RD_ZPG; BBR(2); } // 6/8 BBR2 ZPG,REL
+OP(_04f) { int tmp; H6280_CYCLES(4); RD_ZPG; BBR(4); } // 6/8 BBR4 ZPG,REL
+OP(_06f) { int tmp; H6280_CYCLES(4); RD_ZPG; BBR(6); } // 6/8 BBR6 ZPG,REL
+OP(_08f) { int tmp; H6280_CYCLES(4); RD_ZPG; BBS(0); } // 6/8 BBS0 ZPG,REL
+OP(_0af) { int tmp; H6280_CYCLES(4); RD_ZPG; BBS(2); } // 6/8 BBS2 ZPG,REL
+OP(_0cf) { int tmp; H6280_CYCLES(4); RD_ZPG; BBS(4); } // 6/8 BBS4 ZPG,REL
+OP(_0ef) { int tmp; H6280_CYCLES(4); RD_ZPG; BBS(6); } // 6/8 BBS6 ZPG,REL
+
+OP(_01f) { int tmp; H6280_CYCLES(4); RD_ZPG; BBR(1); } // 6/8 BBR1 ZPG,REL
+OP(_03f) { int tmp; H6280_CYCLES(4); RD_ZPG; BBR(3); } // 6/8 BBR3 ZPG,REL
+OP(_05f) { int tmp; H6280_CYCLES(4); RD_ZPG; BBR(5); } // 6/8 BBR5 ZPG,REL
+OP(_07f) { int tmp; H6280_CYCLES(4); RD_ZPG; BBR(7); } // 6/8 BBR7 ZPG,REL
+OP(_09f) { int tmp; H6280_CYCLES(4); RD_ZPG; BBS(1); } // 6/8 BBS1 ZPG,REL
+OP(_0bf) { int tmp; H6280_CYCLES(4); RD_ZPG; BBS(3); } // 6/8 BBS3 ZPG,REL
+OP(_0df) { int tmp; H6280_CYCLES(4); RD_ZPG; BBS(5); } // 6/8 BBS5 ZPG,REL
+OP(_0ff) { int tmp; H6280_CYCLES(4); RD_ZPG; BBS(7); } // 6/8 BBS7 ZPG,REL
+
+static void (*const insnh6280[0x100])(h6280_Regs* cpustate) = {
+ h6280_000,h6280_001,h6280_002,h6280_003,h6280_004,h6280_005,h6280_006,h6280_007,
+ h6280_008,h6280_009,h6280_00a,h6280_00b,h6280_00c,h6280_00d,h6280_00e,h6280_00f,
+ h6280_010,h6280_011,h6280_012,h6280_013,h6280_014,h6280_015,h6280_016,h6280_017,
+ h6280_018,h6280_019,h6280_01a,h6280_01b,h6280_01c,h6280_01d,h6280_01e,h6280_01f,
+ h6280_020,h6280_021,h6280_022,h6280_023,h6280_024,h6280_025,h6280_026,h6280_027,
+ h6280_028,h6280_029,h6280_02a,h6280_02b,h6280_02c,h6280_02d,h6280_02e,h6280_02f,
+ h6280_030,h6280_031,h6280_032,h6280_033,h6280_034,h6280_035,h6280_036,h6280_037,
+ h6280_038,h6280_039,h6280_03a,h6280_03b,h6280_03c,h6280_03d,h6280_03e,h6280_03f,
+ h6280_040,h6280_041,h6280_042,h6280_043,h6280_044,h6280_045,h6280_046,h6280_047,
+ h6280_048,h6280_049,h6280_04a,h6280_04b,h6280_04c,h6280_04d,h6280_04e,h6280_04f,
+ h6280_050,h6280_051,h6280_052,h6280_053,h6280_054,h6280_055,h6280_056,h6280_057,
+ h6280_058,h6280_059,h6280_05a,h6280_05b,h6280_05c,h6280_05d,h6280_05e,h6280_05f,
+ h6280_060,h6280_061,h6280_062,h6280_063,h6280_064,h6280_065,h6280_066,h6280_067,
+ h6280_068,h6280_069,h6280_06a,h6280_06b,h6280_06c,h6280_06d,h6280_06e,h6280_06f,
+ h6280_070,h6280_071,h6280_072,h6280_073,h6280_074,h6280_075,h6280_076,h6280_077,
+ h6280_078,h6280_079,h6280_07a,h6280_07b,h6280_07c,h6280_07d,h6280_07e,h6280_07f,
+ h6280_080,h6280_081,h6280_082,h6280_083,h6280_084,h6280_085,h6280_086,h6280_087,
+ h6280_088,h6280_089,h6280_08a,h6280_08b,h6280_08c,h6280_08d,h6280_08e,h6280_08f,
+ h6280_090,h6280_091,h6280_092,h6280_093,h6280_094,h6280_095,h6280_096,h6280_097,
+ h6280_098,h6280_099,h6280_09a,h6280_09b,h6280_09c,h6280_09d,h6280_09e,h6280_09f,
+ h6280_0a0,h6280_0a1,h6280_0a2,h6280_0a3,h6280_0a4,h6280_0a5,h6280_0a6,h6280_0a7,
+ h6280_0a8,h6280_0a9,h6280_0aa,h6280_0ab,h6280_0ac,h6280_0ad,h6280_0ae,h6280_0af,
+ h6280_0b0,h6280_0b1,h6280_0b2,h6280_0b3,h6280_0b4,h6280_0b5,h6280_0b6,h6280_0b7,
+ h6280_0b8,h6280_0b9,h6280_0ba,h6280_0bb,h6280_0bc,h6280_0bd,h6280_0be,h6280_0bf,
+ h6280_0c0,h6280_0c1,h6280_0c2,h6280_0c3,h6280_0c4,h6280_0c5,h6280_0c6,h6280_0c7,
+ h6280_0c8,h6280_0c9,h6280_0ca,h6280_0cb,h6280_0cc,h6280_0cd,h6280_0ce,h6280_0cf,
+ h6280_0d0,h6280_0d1,h6280_0d2,h6280_0d3,h6280_0d4,h6280_0d5,h6280_0d6,h6280_0d7,
+ h6280_0d8,h6280_0d9,h6280_0da,h6280_0db,h6280_0dc,h6280_0dd,h6280_0de,h6280_0df,
+ h6280_0e0,h6280_0e1,h6280_0e2,h6280_0e3,h6280_0e4,h6280_0e5,h6280_0e6,h6280_0e7,
+ h6280_0e8,h6280_0e9,h6280_0ea,h6280_0eb,h6280_0ec,h6280_0ed,h6280_0ee,h6280_0ef,
+ h6280_0f0,h6280_0f1,h6280_0f2,h6280_0f3,h6280_0f4,h6280_0f5,h6280_0f6,h6280_0f7,
+ h6280_0f8,h6280_0f9,h6280_0fa,h6280_0fb,h6280_0fc,h6280_0fd,h6280_0fe,h6280_0ff
+};
diff --git a/trunk/src/emu/cpu/h83002/h8.h b/trunk/src/emu/cpu/h83002/h8.h
new file mode 100644
index 00000000000..0e7a9ffbfab
--- /dev/null
+++ b/trunk/src/emu/cpu/h83002/h8.h
@@ -0,0 +1,401 @@
+/***************************************************************************
+
+ h83002.h : Public constants and function defs for the H8/3002 emulator.
+
+****************************************************************************/
+
+#pragma once
+
+#ifndef __H83002_H__
+#define __H83002_H__
+
+
+#define IFLAG 0x80
+#define UIFLAG 0x40
+#define HFLAG 0x20
+#define UFLAG 0x10
+#define NFLAG 0x08
+#define ZFLAG 0x04
+#define VFLAG 0x02
+#define CFLAG 0x01
+
+enum
+{
+ H8_E0 = 1,
+ H8_E1,
+ H8_E2,
+ H8_E3,
+ H8_E4,
+ H8_E5,
+ H8_E6,
+ H8_E7,
+
+ H8_PC,
+ H8_CCR
+};
+
+// external input lines
+enum
+{
+ H8_IRQ0 = 0,
+ H8_IRQ1,
+ H8_IRQ2,
+ H8_IRQ3,
+ H8_IRQ4,
+ H8_IRQ5,
+ H8_IRQ6, // IRQs 6+ only available on 8-bit H8/3xx
+ H8_IRQ7,
+ H8_NMI,
+
+ H8_METRO_TIMER_HACK, // as described. this needs to be fixed.
+
+ H8_SCI_0_RX, // incoming character on SCI 0
+ H8_SCI_1_RX, // incoming character on SCI 1
+};
+
+// I/O ports
+enum
+{
+ // digital I/O ports
+ // ports 4-B are valid on 16-bit H8/3xx, ports 1-9 on 8-bit H8/3xx
+ H8_PORT_1 = 0, // 0
+ H8_PORT_2, // 1
+ H8_PORT_3, // 2
+ H8_PORT_4, // 3
+ H8_PORT_5, // 4
+ H8_PORT_6, // 5
+ H8_PORT_7, // 6
+ H8_PORT_8, // 7
+ H8_PORT_9, // 8
+ H8_PORT_A, // 9
+ H8_PORT_B, // A
+
+ // analog inputs
+ H8_ADC_0_H = 0x10,
+ H8_ADC_0_L,
+ H8_ADC_1_H,
+ H8_ADC_1_L,
+ H8_ADC_2_H,
+ H8_ADC_2_L,
+ H8_ADC_3_H,
+ H8_ADC_3_L,
+
+ // serial ports
+ H8_SERIAL_0 = 0x20,
+ H8_SERIAL_1,
+};
+
+////////////////////////////
+// INTERNAL I/O REGISTERS //
+////////////////////////////
+
+#define H8S_IO_OFFS(addr) ((addr) - 0xFFFE40) /* convert address to offset */
+#define H8S_IO_ADDR(offs) ((offs) + 0xFFFE40) /* convert offset to address */
+
+#define H8S_IO(xxxx) ((xxxx) - 0xFE40)
+
+// port
+#define H8S_IO_P1DDR H8S_IO(0xFEB0)
+#define H8S_IO_P2DDR H8S_IO(0xFEB1)
+#define H8S_IO_P3DDR H8S_IO(0xFEB2)
+#define H8S_IO_P5DDR H8S_IO(0xFEB4)
+#define H8S_IO_PADDR H8S_IO(0xFEB9)
+#define H8S_IO_PBDDR H8S_IO(0xFEBA)
+#define H8S_IO_PCDDR H8S_IO(0xFEBB)
+#define H8S_IO_PDDDR H8S_IO(0xFEBC)
+#define H8S_IO_PEDDR H8S_IO(0xFEBD)
+#define H8S_IO_PFDDR H8S_IO(0xFEBE)
+#define H8S_IO_PGDDR H8S_IO(0xFEBF)
+// interrupt controller
+#define H8S_IO_ICRA H8S_IO(0xFEC0)
+#define H8S_IO_ICRB H8S_IO(0xFEC1)
+#define H8S_IO_ICRC H8S_IO(0xFEC2)
+// dtc (data transfer controller)
+#define H8S_IO_DTCEA H8S_IO(0xFF30)
+#define H8S_IO_DTCEB H8S_IO(0xFF31)
+#define H8S_IO_DTCEC H8S_IO(0xFF32)
+#define H8S_IO_DTCED H8S_IO(0xFF33)
+#define H8S_IO_DTCEE H8S_IO(0xFF34)
+#define H8S_IO_DTCEF H8S_IO(0xFF35)
+// port
+#define H8S_IO_PORT1 H8S_IO(0xFF50)
+#define H8S_IO_PORT2 H8S_IO(0xFF51)
+#define H8S_IO_PORT3 H8S_IO(0xFF52)
+#define H8S_IO_PORT4 H8S_IO(0xFF53)
+#define H8S_IO_PORT5 H8S_IO(0xFF54)
+#define H8S_IO_PORTA H8S_IO(0xFF59)
+#define H8S_IO_PORTB H8S_IO(0xFF5A)
+#define H8S_IO_PORTC H8S_IO(0xFF5B)
+#define H8S_IO_PORTD H8S_IO(0xFF5C)
+#define H8S_IO_PORTE H8S_IO(0xFF5D)
+#define H8S_IO_PORTF H8S_IO(0xFF5E)
+#define H8S_IO_PORTG H8S_IO(0xFF5F)
+#define H8S_IO_P1DR H8S_IO(0xFF60)
+#define H8S_IO_P2DR H8S_IO(0xFF61)
+#define H8S_IO_P3DR H8S_IO(0xFF62)
+#define H8S_IO_P4DR H8S_IO(0xFF63)
+#define H8S_IO_P5DR H8S_IO(0xFF64)
+#define H8S_IO_PADR H8S_IO(0xFF69)
+#define H8S_IO_PBDR H8S_IO(0xFF6A)
+#define H8S_IO_PCDR H8S_IO(0xFF6B)
+#define H8S_IO_PDDR H8S_IO(0xFF6C)
+#define H8S_IO_PEDR H8S_IO(0xFF6D)
+#define H8S_IO_PFDR H8S_IO(0xFF6E)
+#define H8S_IO_PGDR H8S_IO(0xFF6F)
+// SCI0
+#define H8S_IO_SMR0 H8S_IO(0xFF78)
+#define H8S_IO_BRR0 H8S_IO(0xFF79)
+#define H8S_IO_SCR0 H8S_IO(0xFF7A)
+#define H8S_IO_TDR0 H8S_IO(0xFF7B)
+#define H8S_IO_SSR0 H8S_IO(0xFF7C)
+#define H8S_IO_RDR0 H8S_IO(0xFF7D)
+#define H8S_IO_SCMR0 H8S_IO(0xFF7E)
+// SCI1
+#define H8S_IO_SMR1 H8S_IO(0xFF80)
+#define H8S_IO_BRR1 H8S_IO(0xFF81)
+#define H8S_IO_SCR1 H8S_IO(0xFF82)
+#define H8S_IO_TDR1 H8S_IO(0xFF83)
+#define H8S_IO_SSR1 H8S_IO(0xFF84)
+#define H8S_IO_RDR1 H8S_IO(0xFF85)
+#define H8S_IO_SCMR1 H8S_IO(0xFF86)
+// SCI2
+#define H8S_IO_SMR2 H8S_IO(0xFF88)
+#define H8S_IO_BRR2 H8S_IO(0xFF89)
+#define H8S_IO_SCR2 H8S_IO(0xFF8A)
+#define H8S_IO_TDR2 H8S_IO(0xFF8B)
+#define H8S_IO_SSR2 H8S_IO(0xFF8C)
+#define H8S_IO_RDR2 H8S_IO(0xFF8D)
+#define H8S_IO_SCMR2 H8S_IO(0xFF8E)
+// 8-bit timer (channel 0 & 1)
+#define H8S_IO_TCR0 H8S_IO(0xFFB0)
+#define H8S_IO_TCR1 H8S_IO(0xFFB1)
+#define H8S_IO_TCSR0 H8S_IO(0xFFB2)
+#define H8S_IO_TCSR1 H8S_IO(0xFFB3)
+#define H8S_IO_TCORA0 H8S_IO(0xFFB4)
+#define H8S_IO_TCORA1 H8S_IO(0xFFB5)
+#define H8S_IO_TCORB0 H8S_IO(0xFFB6)
+#define H8S_IO_TCORB1 H8S_IO(0xFFB7)
+#define H8S_IO_TCNT0 H8S_IO(0xFFB8)
+#define H8S_IO_TCNT1 H8S_IO(0xFFB9)
+// TPU
+#define H8S_IO_TSTR H8S_IO(0xFFC0)
+#define H8S_IO_TSYR H8S_IO(0xFFC1)
+// TPU0
+#define H8S_IO_TTCR0 H8S_IO(0xFFD0)
+#define H8S_IO_TMDR0 H8S_IO(0xFFD1)
+#define H8S_IO_TIOR0_H H8S_IO(0xFFD2)
+#define H8S_IO_TIOR0_L H8S_IO(0xFFD3)
+#define H8S_IO_TIER0 H8S_IO(0xFFD4)
+#define H8S_IO_TSR0 H8S_IO(0xFFD5)
+#define H8S_IO_TCNT0_H H8S_IO(0xFFD6)
+#define H8S_IO_TCNT0_L H8S_IO(0xFFD7)
+#define H8S_IO_TGR0A_H H8S_IO(0xFFD8)
+#define H8S_IO_TGR0A_L H8S_IO(0xFFD9)
+#define H8S_IO_TGR0B_H H8S_IO(0xFFDA)
+#define H8S_IO_TGR0B_L H8S_IO(0xFFDB)
+#define H8S_IO_TGR0C_H H8S_IO(0xFFDC)
+#define H8S_IO_TGR0C_L H8S_IO(0xFFDD)
+#define H8S_IO_TGR0D_H H8S_IO(0xFFDE)
+#define H8S_IO_TGR0D_L H8S_IO(0xFFDF)
+// TPU1
+#define H8S_IO_TTCR1 H8S_IO(0xFFE0)
+#define H8S_IO_TMDR1 H8S_IO(0xFFE1)
+#define H8S_IO_TIOR1 H8S_IO(0xFFE2)
+#define H8S_IO_TIER1 H8S_IO(0xFFE4)
+#define H8S_IO_TSR1 H8S_IO(0xFFE5)
+#define H8S_IO_TCNT1_H H8S_IO(0xFFE6)
+#define H8S_IO_TCNT1_L H8S_IO(0xFFE7)
+#define H8S_IO_TGR1A_H H8S_IO(0xFFE8)
+#define H8S_IO_TGR1A_L H8S_IO(0xFFE9)
+#define H8S_IO_TGR1B_H H8S_IO(0xFFEA)
+#define H8S_IO_TGR1B_L H8S_IO(0xFFEB)
+// TPU2
+#define H8S_IO_TTCR2 H8S_IO(0xFFF0)
+#define H8S_IO_TMDR2 H8S_IO(0xFFF1)
+#define H8S_IO_TIOR2 H8S_IO(0xFFF2)
+#define H8S_IO_TIER2 H8S_IO(0xFFF4)
+#define H8S_IO_TSR2 H8S_IO(0xFFF5)
+#define H8S_IO_TCNT2_H H8S_IO(0xFFF6)
+#define H8S_IO_TCNT2_L H8S_IO(0xFFF7)
+#define H8S_IO_TGR2A_H H8S_IO(0xFFF8)
+#define H8S_IO_TGR2A_L H8S_IO(0xFFF9)
+#define H8S_IO_TGR2B_H H8S_IO(0xFFFA)
+#define H8S_IO_TGR2B_L H8S_IO(0xFFFB)
+// TPU3
+#define H8S_IO_TTCR3 H8S_IO(0xFE80)
+#define H8S_IO_TMDR3 H8S_IO(0xFE81)
+#define H8S_IO_TIOR3_H H8S_IO(0xFE82)
+#define H8S_IO_TIOR3_L H8S_IO(0xFE83)
+#define H8S_IO_TIER3 H8S_IO(0xFE84)
+#define H8S_IO_TSR3 H8S_IO(0xFE85)
+#define H8S_IO_TCNT3_H H8S_IO(0xFE86)
+#define H8S_IO_TCNT3_L H8S_IO(0xFE87)
+#define H8S_IO_TGR3A_H H8S_IO(0xFE88)
+#define H8S_IO_TGR3A_L H8S_IO(0xFE89)
+#define H8S_IO_TGR3B_H H8S_IO(0xFE8A)
+#define H8S_IO_TGR3B_L H8S_IO(0xFE8B)
+#define H8S_IO_TGR3C_H H8S_IO(0xFE8C)
+#define H8S_IO_TGR3C_L H8S_IO(0xFE8D)
+#define H8S_IO_TGR3D_H H8S_IO(0xFE8E)
+#define H8S_IO_TGR3D_L H8S_IO(0xFE8F)
+// TPU4
+#define H8S_IO_TTCR4 H8S_IO(0xFE90)
+#define H8S_IO_TMDR4 H8S_IO(0xFE91)
+#define H8S_IO_TIOR4 H8S_IO(0xFE92)
+#define H8S_IO_TIER4 H8S_IO(0xFE94)
+#define H8S_IO_TSR4 H8S_IO(0xFE95)
+#define H8S_IO_TCNT4_H H8S_IO(0xFE96)
+#define H8S_IO_TCNT4_L H8S_IO(0xFE97)
+#define H8S_IO_TGR4A_H H8S_IO(0xFE98)
+#define H8S_IO_TGR4A_L H8S_IO(0xFE99)
+#define H8S_IO_TGR4B_H H8S_IO(0xFE9A)
+#define H8S_IO_TGR4B_L H8S_IO(0xFE9B)
+// TPU5
+#define H8S_IO_TTCR5 H8S_IO(0xFEA0)
+#define H8S_IO_TMDR5 H8S_IO(0xFEA1)
+#define H8S_IO_TIOR5 H8S_IO(0xFEA2)
+#define H8S_IO_TIER5 H8S_IO(0xFEA4)
+#define H8S_IO_TSR5 H8S_IO(0xFEA5)
+#define H8S_IO_TCNT5_H H8S_IO(0xFEA6)
+#define H8S_IO_TCNT5_L H8S_IO(0xFEA7)
+#define H8S_IO_TGR5A_H H8S_IO(0xFEA8)
+#define H8S_IO_TGR5A_L H8S_IO(0xFEA9)
+#define H8S_IO_TGR5B_H H8S_IO(0xFEAA)
+#define H8S_IO_TGR5B_L H8S_IO(0xFEAB)
+// DMA
+#define H8S_IO_MAR1AH H8S_IO(0xFEF0)
+#define H8S_IO_MAR1AL H8S_IO(0xFEF2)
+#define H8S_IO_ETCR1A H8S_IO(0xFEF6)
+#define H8S_IO_MAR1BH H8S_IO(0xFEF8)
+#define H8S_IO_MAR1BL H8S_IO(0xFEFA)
+#define H8S_IO_ETCR1B H8S_IO(0xFEFE)
+#define H8S_IO_DMACR0A H8S_IO(0xFF02)
+#define H8S_IO_DMACR0B H8S_IO(0xFF03)
+#define H8S_IO_DMACR1A H8S_IO(0xFF04)
+#define H8S_IO_DMACR1B H8S_IO(0xFF05)
+#define H8S_IO_DMABCRH H8S_IO(0xFF06)
+#define H8S_IO_DMABCRL H8S_IO(0xFF07)
+
+///////////
+// PORTS //
+///////////
+
+#define H8S_P1_TIOCB2 0x80
+#define H8S_P1_TIOCA2 0x40
+#define H8S_P1_TIOCB1 0x20
+#define H8S_P1_TIOCA1 0x10
+#define H8S_P1_TIOCD0 0x08
+#define H8S_P1_TIOCC0 0x04
+#define H8S_P1_TIOCB0 0x02
+#define H8S_P1_TIOCA0 0x01
+
+#define H8S_P3_SCK1 0x20
+#define H8S_P3_SCK0 0x10
+#define H8S_P3_RXD1 0x08
+#define H8S_P3_RXD0 0x04
+#define H8S_P3_TXD1 0x02
+#define H8S_P3_TXD0 0x01
+
+#define H8S_P5_SCK2 0x04
+#define H8S_P5_RXD2 0x02
+#define H8S_P5_TXD2 0x01
+
+#define H8S_PF_PF6 0x40
+#define H8S_PF_PF2 0x04
+#define H8S_PF_PF1 0x02
+#define H8S_PF_PF0 0x01
+
+///////////////
+// SCI 0/1/2 //
+///////////////
+
+#define H8S_SSR_TDRE 0x80 /* transmit data register empty */
+#define H8S_SSR_RDRF 0x40 /* receive data register full */
+#define H8S_SSR_ORER 0x20 /* overrun error */
+#define H8S_SSR_FER 0x10 /* framing error */
+#define H8S_SSR_PER 0x08 /* parity error */
+#define H8S_SSR_TEND 0x04 /* transmit end */
+#define H8S_SSR_MPB 0x02 /* multiprocessor bit */
+#define H8S_SSR_MPBT 0x01 /* multiprocessor bit transfer */
+
+#define H8S_SCR_TIE 0x80 /* transmit interrupt enable */
+#define H8S_SCR_RIE 0x40 /* receive interrupt enable */
+#define H8S_SCR_TE 0x20 /* transmit enable */
+#define H8S_SCR_RE 0x10 /* receive enable */
+#define H8S_SCR_MPIE 0x08 /* multiprocessor interrupt enable */
+#define H8S_SCR_TEIE 0x04 /* transmit end interrupt enable */
+#define H8S_SCR_CKE1 0x02 /* clock enable 1 */
+#define H8S_SCR_CKE0 0x01 /* clock enable 0 */
+
+////////////////
+// INTERRUPTS //
+////////////////
+
+#define H8S_INT_NMI 0x07
+#define H8S_INT_IRQ0 0x10
+#define H8S_INT_IRQ1 0x11
+#define H8S_INT_IRQ2 0x12
+#define H8S_INT_IRQ3 0x13
+#define H8S_INT_IRQ4 0x14
+#define H8S_INT_IRQ5 0x15
+#define H8S_INT_IRQ6 0x16
+#define H8S_INT_IRQ7 0x17
+#define H8S_INT_SWDTEND 0x18
+#define H8S_INT_WOVI 0x19
+#define H8S_INT_ADI 0x1C
+#define H8S_INT_TGI0A 0x20
+#define H8S_INT_TGI0B 0x21
+#define H8S_INT_TGI0C 0x22
+#define H8S_INT_TGI0D 0x23
+#define H8S_INT_TCI0V 0x24
+#define H8S_INT_TGI1A 0x28
+#define H8S_INT_TGI1B 0x29
+#define H8S_INT_TCI1V 0x2A
+#define H8S_INT_TCI1U 0x2B
+#define H8S_INT_TGI2A 0x2C
+#define H8S_INT_TGI2B 0x2D
+#define H8S_INT_TCI2V 0x2E
+#define H8S_INT_TCI2U 0x2F
+#define H8S_INT_CMIA0 0x40
+#define H8S_INT_CMIB0 0x41
+#define H8S_INT_OVI0 0x42
+#define H8S_INT_CMIA1 0x44
+#define H8S_INT_CMIB1 0x45
+#define H8S_INT_OVI1 0x46
+#define H8S_INT_ERI0 0x50
+#define H8S_INT_RXI0 0x51
+#define H8S_INT_TXI0 0x52
+#define H8S_INT_TEI0 0x53
+#define H8S_INT_ERI1 0x54
+#define H8S_INT_RXI1 0x55
+#define H8S_INT_TXI1 0x56
+#define H8S_INT_TEI1 0x57
+#define H8S_INT_ERI2 0x58
+#define H8S_INT_RXI2 0x59
+#define H8S_INT_TXI2 0x5A
+#define H8S_INT_TEI2 0x5B
+
+#define H8S_INT_TGI3A 48
+#define H8S_INT_TGI3B 49
+#define H8S_INT_TGI3C 50
+#define H8S_INT_TGI3D 51
+#define H8S_INT_TCI3V 52
+#define H8S_INT_TGI4A 56
+#define H8S_INT_TGI4B 57
+#define H8S_INT_TCI4V 58
+#define H8S_INT_TCI4U 59
+#define H8S_INT_TGI5A 60
+#define H8S_INT_TGI5B 61
+#define H8S_INT_TCI5V 62
+#define H8S_INT_TCI5U 63
+
+DECLARE_LEGACY_CPU_DEVICE(H83002, h8_3002);
+DECLARE_LEGACY_CPU_DEVICE(H83007, h8_3007);
+DECLARE_LEGACY_CPU_DEVICE(H83044, h8_3044);
+DECLARE_LEGACY_CPU_DEVICE(H83334, h8_3334);
+
+DECLARE_LEGACY_CPU_DEVICE(H8S2241, h8s_2241);
+DECLARE_LEGACY_CPU_DEVICE(H8S2246, h8s_2246);
+DECLARE_LEGACY_CPU_DEVICE(H8S2323, h8s_2323);
+
+#endif /* __H83002_H__ */
diff --git a/trunk/src/emu/cpu/h83002/h8_16.c b/trunk/src/emu/cpu/h83002/h8_16.c
new file mode 100644
index 00000000000..a506fbb09ca
--- /dev/null
+++ b/trunk/src/emu/cpu/h83002/h8_16.c
@@ -0,0 +1,866 @@
+/***************************************************************************
+
+ h8_16.c: Hitachi H8/3xx series 16/32-bit microcontroller emulator
+
+ Original by The_Author & DynaChicken for the ZiNc emulator.
+ MAME changes by R. Belmont, Luca Elia, and Tomasz Slanina.
+
+ TS 20060412 Added exts.l, sub.l, divxs.w (buggy), jsr @reg, rotxl.l reg, mov.l @(adr, reg), reg
+ LE 20070903 Added divxu.b shal.l extu.w dec.l #Imm,Rd subx.b
+ LE 20080202 Separated 3002/3044/3007, Added or.l shal.l rotl.l not.l neg.l exts.w
+ sub/or/xor.l #Imm:32,ERd bset/bnot/bclr.b Rn,@ERd bst/bist.b #Imm:3,@ERd bnot.b #Imm:3,@ERd
+ LE 20090128 Added mov.l ers,@aa:16; bild #xx:3,rd; eepmov.b; bnot #xx:3,@aa:8
+
+***************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "h8.h"
+#include "h8priv.h"
+
+CPU_DISASSEMBLE(h8_24);
+CPU_DISASSEMBLE(h8_32);
+
+#define H8_SP (7)
+
+#define h8_mem_read8(x) h8->program->read_byte(x)
+#define h8_mem_read16(z, x) h8->program->read_word(x)
+#define h8_mem_write8(x, y) h8->program->write_byte(x, y)
+#define h8_mem_write16(z, x, y) h8->program->write_word(x, y)
+#define h8_readop16(x, y) x->direct->read_decrypted_word(y)
+
+// timing macros
+// note: we assume a system 12 - type setup where external access is 3+1 states
+// timing will be off somewhat for other configurations.
+#define H8_IFETCH_TIMING(x) h8->cyccnt -= (x) * 4;
+#define H8_BRANCH_TIMING(x) h8->cyccnt -= (x) * 4;
+#define H8_STACK_TIMING(x) h8->cyccnt -= (x) * 4;
+#define H8_BYTE_TIMING(x, adr) if (address24 >= 0xffff10) h8->cyccnt -= (x) * 3; else h8->cyccnt -= (x) * 4;
+#define H8_WORD_TIMING(x, adr) if (address24 >= 0xffff10) h8->cyccnt -= (x) * 3; else h8->cyccnt -= (x) * 4;
+#define H8_IOP_TIMING(x) h8->cyccnt -= (x);
+
+INLINE UINT32 h8_mem_read32(h83xx_state *h8, offs_t address)
+{
+ UINT32 result = h8->program->read_word(address) << 16;
+ return result | h8->program->read_word(address + 2);
+}
+
+INLINE void h8_mem_write32(h83xx_state *h8, offs_t address, UINT32 data)
+{
+ h8->program->write_word(address, data >> 16);
+ h8->program->write_word(address + 2, data);
+}
+
+static void h8_check_irqs(h83xx_state *h8);
+
+/* implementation */
+
+void h8_3002_InterruptRequest(h83xx_state *h8, UINT8 source, UINT8 state)
+{
+ int request = source / 32;
+ int bit = source % 32;
+
+ // don't allow clear on external interrupts
+ if ((source <= 17) && (state == 0)) return;
+
+ if (state)
+ {
+ h8->irq_req[request] |= (1<<bit);
+ }
+ else
+ {
+ h8->irq_req[request] &= ~(1<<bit);
+ }
+}
+
+
+static UINT8 h8_get_ccr(h83xx_state *h8)
+{
+ h8->ccr = 0;
+ if(h8->h8nflag)h8->ccr |= NFLAG;
+ if(h8->h8zflag)h8->ccr |= ZFLAG;
+ if(h8->h8vflag)h8->ccr |= VFLAG;
+ if(h8->h8cflag)h8->ccr |= CFLAG;
+ if(h8->h8uflag)h8->ccr |= UFLAG;
+ if(h8->h8hflag)h8->ccr |= HFLAG;
+ if(h8->h8uiflag)h8->ccr |= UIFLAG;
+ if(h8->h8iflag)h8->ccr |= IFLAG;
+ return h8->ccr;
+}
+
+static char *h8_get_ccr_str(h83xx_state *h8)
+{
+ static char res[10];
+
+ memset(res, 0, sizeof(res));
+ if(h8->h8iflag) strcat(res, "I"); else strcat(res, "i");
+ if(h8->h8uiflag)strcat(res, "U"); else strcat(res, "u");
+ if(h8->h8hflag) strcat(res, "H"); else strcat(res, "h");
+ if(h8->h8uflag) strcat(res, "U"); else strcat(res, "u");
+ if(h8->h8nflag) strcat(res, "N"); else strcat(res, "n");
+ if(h8->h8zflag) strcat(res, "Z"); else strcat(res, "z");
+ if(h8->h8vflag) strcat(res, "V"); else strcat(res, "v");
+ if(h8->h8cflag) strcat(res, "C"); else strcat(res, "c");
+
+ return res;
+}
+
+static void h8_set_ccr(h83xx_state *h8, UINT8 data)
+{
+ h8->ccr = data;
+
+ h8->h8nflag = 0;
+ h8->h8zflag = 0;
+ h8->h8vflag = 0;
+ h8->h8cflag = 0;
+ h8->h8hflag = 0;
+ h8->h8iflag = 0;
+ h8->h8uflag = 0;
+ h8->h8uiflag = 0;
+
+ if(h8->ccr & NFLAG) h8->h8nflag = 1;
+ if(h8->ccr & ZFLAG) h8->h8zflag = 1;
+ if(h8->ccr & VFLAG) h8->h8vflag = 1;
+ if(h8->ccr & CFLAG) h8->h8cflag = 1;
+ if(h8->ccr & HFLAG) h8->h8hflag = 1;
+ if(h8->ccr & UFLAG) h8->h8uflag = 1;
+ if(h8->ccr & UIFLAG) h8->h8uiflag = 1;
+ if(h8->ccr & IFLAG) h8->h8iflag = 1;
+
+ if (!h8->incheckirqs) h8_check_irqs(h8);
+}
+
+static INT16 h8_getreg16(h83xx_state *h8, UINT8 reg)
+{
+ if(reg > 7)
+ {
+ return h8->regs[reg-8]>>16;
+ }
+ else
+ {
+ return h8->regs[reg];
+ }
+}
+
+static void h8_setreg16(h83xx_state *h8, UINT8 reg, UINT16 data)
+{
+ if(reg > 7)
+ {
+ h8->regs[reg-8] &= 0xffff;
+ h8->regs[reg-8] |= data<<16;
+ }
+ else
+ {
+ h8->regs[reg] &= 0xffff0000;
+ h8->regs[reg] |= data;
+ }
+}
+
+static UINT8 h8_getreg8(h83xx_state *h8, UINT8 reg)
+{
+ if(reg > 7)
+ {
+ return h8->regs[reg-8];
+ }
+ else
+ {
+ return h8->regs[reg]>>8;
+ }
+}
+
+static void h8_setreg8(h83xx_state *h8, UINT8 reg, UINT8 data)
+{
+ if(reg > 7)
+ {
+ h8->regs[reg-8] &= 0xffffff00;
+ h8->regs[reg-8] |= data;
+ }
+ else
+ {
+ h8->regs[reg] &= 0xffff00ff;
+ h8->regs[reg] |= data<<8;
+ }
+}
+
+static UINT32 h8_getreg32(h83xx_state *h8, UINT8 reg)
+{
+ return h8->regs[reg];
+}
+
+static void h8_setreg32(h83xx_state *h8, UINT8 reg, UINT32 data)
+{
+ h8->regs[reg] = data;
+}
+
+static void h8_onstateload(h83xx_state *h8)
+{
+ h8_set_ccr(h8, h8->ccr);
+}
+
+static CPU_INIT(h8)
+{
+ h83xx_state *h8 = get_safe_token(device);
+
+ h8->h8iflag = 1;
+ h8->irq_cb = irqcallback;
+ h8->device = device;
+
+ h8->mode_8bit = 0;
+
+ h8->program = device->space(AS_PROGRAM);
+ h8->direct = &h8->program->direct();
+ h8->io = device->space(AS_IO);
+
+ device->save_item(NAME(h8->h8err));
+ device->save_item(NAME(h8->regs));
+ device->save_item(NAME(h8->pc));
+ device->save_item(NAME(h8->ppc));
+ device->save_item(NAME(h8->irq_req));
+ device->save_item(NAME(h8->ccr));
+ device->save_item(NAME(h8->mode_8bit));
+
+ device->save_item(NAME(h8->per_regs));
+ device->save_item(NAME(h8->h8TSTR));
+ device->save_item(NAME(h8->h8TCNT));
+
+ device->machine().save().register_postload(save_prepost_delegate(FUNC(h8_onstateload), h8));
+
+ h8_itu_init(h8);
+}
+
+static CPU_INIT(h8_3007)
+{
+ h83xx_state *h8 = get_safe_token(device);
+
+ CPU_INIT_CALL(h8);
+ h8_3007_itu_init(h8);
+}
+
+static CPU_INIT(h8s_2xxx)
+{
+ h83xx_state *h8 = get_safe_token(device);
+
+ CPU_INIT_CALL(h8);
+
+ h8s_tmr_init(h8);
+ h8s_tpu_init(h8);
+ h8s_sci_init(h8);
+}
+
+static CPU_RESET(h8)
+{
+ h83xx_state *h8 = get_safe_token(device);
+
+ h8->h8err = 0;
+ h8->pc = h8_mem_read32(h8, 0) & 0xffffff;
+
+ h8->incheckirqs = 0;
+
+ // disable timers
+ h8->h8TSTR = 0;
+
+ h8_itu_reset(h8);
+
+ h8->has_h8speriphs = false;
+}
+
+static CPU_RESET(h8s_2xxx)
+{
+ h83xx_state *h8 = get_safe_token(device);
+
+ CPU_RESET_CALL(h8);
+
+ h8s_periph_reset(h8);
+ h8->has_h8speriphs = true;
+
+}
+
+static void h8_GenException(h83xx_state *h8, UINT8 vectornr)
+{
+ // push PC on stack
+ // extended mode stack push!
+ h8_setreg32(h8, H8_SP, h8_getreg32(h8, H8_SP)-4);
+ h8_mem_write32(h8, h8_getreg32(h8, H8_SP), h8->pc);
+ // push ccr
+ h8_setreg32(h8, H8_SP, h8_getreg32(h8, H8_SP)-2);
+ h8_mem_write16(h8, h8_getreg32(h8, H8_SP), h8_get_ccr(h8));
+
+ // generate address from vector
+ h8_set_ccr(h8, h8_get_ccr(h8) | 0x80);
+ if (h8->h8uiflag == 0)
+ h8_set_ccr(h8, h8_get_ccr(h8) | 0x40);
+ h8->pc = h8_mem_read32(h8, vectornr * 4) & 0xffffff;
+
+ // I couldn't find timing info for exceptions, so this is a guess (based on JSR/BSR)
+ H8_IFETCH_TIMING(2);
+ H8_STACK_TIMING(2);
+}
+
+static int h8_get_priority(h83xx_state *h8, UINT8 bit)
+{
+ int res = 0;
+ switch(bit)
+ {
+ case 12: // IRQ0
+ if (h8->per_regs[0xF8]&0x80) res = 1; break;
+ case 13: // IRQ1
+ if (h8->per_regs[0xF8]&0x40) res = 1; break;
+ case 14: // IRQ2
+ case 15: // IRQ3
+ if (h8->per_regs[0xF8]&0x20) res = 1; break;
+ case 16: // IRQ4
+ case 17: // IRQ5
+ if (h8->per_regs[0xF8]&0x10) res = 1; break;
+ case 53: // SCI0 Rx
+ if (!(h8->per_regs[0xB2]&0x40)) res = -2;
+ else if (h8->per_regs[0xF9]&0x08) res = 1; break;
+ case 54: // SCI0 Tx Empty
+ if (!(h8->per_regs[0xB2]&0x80)) res = -2;
+ else if (h8->per_regs[0xF9]&0x08) res = 1; break;
+ case 55: // SCI0 Tx End
+ if (!(h8->per_regs[0xB2]&0x04)) res = -2;
+ else if (h8->per_regs[0xF9]&0x08) res = 1; break;
+ case 57: // SCI1 Rx
+ if (!(h8->per_regs[0xBA]&0x40)) res = -2;
+ else if (h8->per_regs[0xF9]&0x04) res = 1; break;
+ case 58: // SCI1 Tx Empty
+ if (!(h8->per_regs[0xBA]&0x80)) res = -2;
+ else if (h8->per_regs[0xF9]&0x04) res = 1; break;
+ case 59: // SCI1 Tx End
+ if (!(h8->per_regs[0xBA]&0x04)) res = -2;
+ else if (h8->per_regs[0xF9]&0x04) res = 1; break;
+ }
+ return res;
+}
+
+static void h8_check_irqs(h83xx_state *h8)
+{
+ int lv = -1;
+
+ h8->incheckirqs = 1;
+
+ if (h8->h8iflag == 0)
+ {
+ lv = 0;
+ }
+ else
+ {
+ if ((h8->per_regs[0xF2]&0x08)/*SYSCR*/ == 0)
+ {
+ if (h8->h8uiflag == 0)
+ lv = 1;
+ }
+ }
+
+ // any interrupts wanted and can accept ?
+ if(((h8->irq_req[0] != 0) || (h8->irq_req[1]!= 0) || (h8->irq_req[2] != 0)) && (lv >= 0))
+ {
+ UINT8 bit, source;
+ // which one ?
+ for(bit = 0, source = 0xff; source == 0xff && bit < 32; bit++)
+ {
+ if( h8->irq_req[0] & (1<<bit) )
+ {
+ if (h8_get_priority(h8, bit) >= lv)
+ {
+ // mask off
+ h8->irq_req[0] &= ~(1<<bit);
+ source = bit;
+ }
+ }
+ }
+ // which one ?
+ for(bit = 0; source == 0xff && bit < 32; bit++)
+ {
+ if( h8->irq_req[1] & (1<<bit) )
+ {
+ if (h8_get_priority(h8, bit + 32) >= lv)
+ {
+ // mask off
+ h8->irq_req[1] &= ~(1<<bit);
+ source = bit + 32;
+ }
+ }
+ }
+ // which one ?
+ for(bit = 0; source == 0xff && bit < 32; bit++)
+ {
+ if( h8->irq_req[2] & (1<<bit) )
+ {
+ if (h8_get_priority(h8, bit + 64) >= lv)
+ {
+ // mask off
+ h8->irq_req[2] &= ~(1<<bit);
+ source = bit + 64;
+ }
+ }
+ }
+
+ // call the MAME callback if it's one of the 6
+ // external IRQs
+ if (source >= 12 && source <= 17)
+ {
+ (*h8->irq_cb)(h8->device, source - 12 + H8_IRQ0);
+ }
+
+ if (source != 0xff)
+ {
+ if (h8->has_h8speriphs)
+ {
+ h8s_dtce_check(h8, source);
+ }
+ h8_GenException(h8, source);
+ }
+ }
+
+ h8->incheckirqs = 0;
+}
+
+#define H8_ADDR_MASK 0xffffff
+#include "h8ops.h"
+
+// MAME interface stuff
+
+static CPU_SET_INFO( h8 )
+{
+ h83xx_state *h8 = get_safe_token(device);
+
+ switch(state) {
+ case CPUINFO_INT_PC: h8->pc = info->i; break;
+ case CPUINFO_INT_REGISTER + H8_PC: h8->pc = info->i; break;
+ case CPUINFO_INT_REGISTER + H8_CCR: h8_set_ccr(h8, info->i); break;
+
+ case CPUINFO_INT_REGISTER + H8_E0: h8->regs[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + H8_E1: h8->regs[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + H8_E2: h8->regs[2] = info->i; break;
+ case CPUINFO_INT_REGISTER + H8_E3: h8->regs[3] = info->i; break;
+ case CPUINFO_INT_REGISTER + H8_E4: h8->regs[4] = info->i; break;
+ case CPUINFO_INT_REGISTER + H8_E5: h8->regs[5] = info->i; break;
+ case CPUINFO_INT_REGISTER + H8_E6: h8->regs[6] = info->i; break;
+ case CPUINFO_INT_REGISTER + H8_E7: h8->regs[7] = info->i; break;
+
+ case CPUINFO_INT_INPUT_STATE + H8_IRQ0: h8_3002_InterruptRequest(h8, 12, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + H8_IRQ1: h8_3002_InterruptRequest(h8, 13, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + H8_IRQ2: h8_3002_InterruptRequest(h8, 14, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + H8_IRQ3: h8_3002_InterruptRequest(h8, 15, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + H8_IRQ4: h8_3002_InterruptRequest(h8, 16, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + H8_IRQ5: h8_3002_InterruptRequest(h8, 17, info->i); break;
+
+ case CPUINFO_INT_INPUT_STATE + H8_METRO_TIMER_HACK: h8_3002_InterruptRequest(h8, 24, info->i); break;
+
+ case CPUINFO_INT_INPUT_STATE + H8_SCI_0_RX: h8_3002_InterruptRequest(h8, 53, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + H8_SCI_1_RX: h8_3002_InterruptRequest(h8, 57, info->i); break;
+
+ default:
+ fatalerror("h8_set_info unknown request %x", state);
+ break;
+ }
+}
+
+static READ16_HANDLER( h8_itu_r )
+{
+ h83xx_state *h8 = get_safe_token(&space->device());
+
+ if (mem_mask == 0xffff)
+ {
+ // 16-bit read
+ return h8_register_read8(h8, offset*2 + 0xffff10)<<8 | h8_register_read8(h8, (offset*2) + 1 + 0xffff10);
+ }
+ else if (mem_mask == 0xff00)
+ {
+ return h8_register_read8(h8, offset*2 + 0xffff10)<<8;
+ }
+ else if (mem_mask == 0x00ff)
+ {
+ return h8_register_read8(h8, (offset*2) + 1 + 0xffff10);
+ }
+
+ return 0;
+}
+
+static WRITE16_HANDLER( h8_itu_w )
+{
+ h83xx_state *h8 = get_safe_token(&space->device());
+
+ if (mem_mask == 0xffff)
+ {
+ // 16-bit write
+ h8_register_write8(h8, offset*2 + 0xffff10, data>>8);
+ h8_register_write8(h8, (offset*2) + 1 + 0xffff10, data&0xff);
+ }
+ else if (mem_mask == 0xff00)
+ {
+ h8_register_write8(h8, offset*2 + 0xffff10, data>>8);
+ }
+ else if (mem_mask == 0x00ff)
+ {
+ h8_register_write8(h8, (offset*2) + 1 + 0xffff10, data&0xff);
+ }
+}
+
+static READ16_HANDLER( h8_3007_itu_r )
+{
+ h83xx_state *h8 = get_safe_token(&space->device());
+
+ if (mem_mask == 0xffff)
+ {
+ // 16-bit read
+ return h8_3007_register_read8(h8, offset*2 + 0xffff20)<<8 | h8_3007_register_read8(h8, (offset*2) + 1 + 0xffff20);
+ }
+ else if (mem_mask == 0xff00)
+ {
+ return h8_3007_register_read8(h8, offset*2 + 0xffff20)<<8;
+ }
+ else if (mem_mask == 0x00ff)
+ {
+ return h8_3007_register_read8(h8, (offset*2) + 1 + 0xffff20);
+ }
+
+ return 0;
+}
+static WRITE16_HANDLER( h8_3007_itu_w )
+{
+ h83xx_state *h8 = get_safe_token(&space->device());
+
+ if (mem_mask == 0xffff)
+ {
+ // 16-bit write
+ h8_3007_register_write8(h8, offset*2 + 0xffff20, data>>8);
+ h8_3007_register_write8(h8, (offset*2) + 1 + 0xffff20, data&0xff);
+ }
+ else if (mem_mask == 0xff00)
+ {
+ h8_3007_register_write8(h8, offset*2 + 0xffff20, data>>8);
+ }
+ else if (mem_mask == 0x00ff)
+ {
+ h8_3007_register_write8(h8, (offset*2) + 1 + 0xffff20, data&0xff);
+ }
+}
+
+static READ16_HANDLER( h8_3007_itu1_r )
+{
+ h83xx_state *h8 = get_safe_token(&space->device());
+
+ if (mem_mask == 0xffff)
+ {
+ // 16-bit read
+ return h8_3007_register1_read8(h8, offset*2 + 0xfee000)<<8 | h8_3007_register1_read8(h8, (offset*2) + 1 + 0xfee000);
+ }
+ else if (mem_mask == 0xff00)
+ {
+ return h8_3007_register1_read8(h8, offset*2 + 0xfee000)<<8;
+ }
+ else if (mem_mask == 0x00ff)
+ {
+ return h8_3007_register1_read8(h8, (offset*2) + 1 + 0xfee000);
+ }
+
+ return 0;
+}
+static WRITE16_HANDLER( h8_3007_itu1_w )
+{
+ h83xx_state *h8 = get_safe_token(&space->device());
+
+ if (mem_mask == 0xffff)
+ {
+ // 16-bit write
+ h8_3007_register1_write8(h8, offset*2 + 0xfee000, data>>8);
+ h8_3007_register1_write8(h8, (offset*2) + 1 + 0xfee000, data&0xff);
+ }
+ else if (mem_mask == 0xff00)
+ {
+ h8_3007_register1_write8(h8, offset*2 + 0xfee000, data>>8);
+ }
+ else if (mem_mask == 0x00ff)
+ {
+ h8_3007_register1_write8(h8, (offset*2) + 1 + 0xfee000, data&0xff);
+ }
+}
+
+WRITE16_HANDLER( h8s2241_per_regs_w )
+{
+ h83xx_state *h8 = get_safe_token(&space->device());
+ if (mem_mask == 0xffff)
+ {
+ h8s2241_per_regs_write_16(h8, (offset << 1), data);
+ }
+ else if (mem_mask & 0xff00)
+ {
+ h8s2241_per_regs_write_8(h8, (offset << 1), (data >> 8) & 0xff);
+ }
+ else if (mem_mask == 0x00ff)
+ {
+ h8s2241_per_regs_write_8(h8, (offset << 1) + 1, data & 0xff);
+ }
+}
+
+WRITE16_HANDLER( h8s2246_per_regs_w )
+{
+ h83xx_state *h8 = get_safe_token(&space->device());
+ if (mem_mask == 0xffff)
+ {
+ h8s2246_per_regs_write_16(h8, (offset << 1), data);
+ }
+ else if (mem_mask == 0xff00)
+ {
+ h8s2246_per_regs_write_8(h8, (offset << 1), (data >> 8) & 0xff);
+ }
+ else if (mem_mask == 0x00ff)
+ {
+ h8s2246_per_regs_write_8(h8, (offset << 1) + 1, data & 0xff);
+ }
+}
+
+WRITE16_HANDLER( h8s2323_per_regs_w )
+{
+ h83xx_state *h8 = get_safe_token(&space->device());
+ if (mem_mask == 0xffff)
+ {
+ h8s2323_per_regs_write_16(h8, (offset << 1), data);
+ }
+ else if (mem_mask & 0xff00)
+ {
+ h8s2323_per_regs_write_8(h8, (offset << 1), (data >> 8) & 0xff);
+ }
+ else if (mem_mask == 0x00ff)
+ {
+ h8s2323_per_regs_write_8(h8, (offset << 1) + 1, data & 0xff);
+ }
+}
+
+READ16_HANDLER( h8s2241_per_regs_r )
+{
+ h83xx_state *h8 = get_safe_token(&space->device());
+ if (mem_mask == 0xffff)
+ {
+ return h8s2241_per_regs_read_16(h8, (offset << 1));
+ }
+ else if (mem_mask == 0xff00)
+ {
+ return h8s2241_per_regs_read_8(h8, (offset << 1)) << 8;
+ }
+ else if (mem_mask == 0x00ff)
+ {
+ return h8s2241_per_regs_read_8(h8, (offset << 1) + 1);
+ }
+ return 0;
+}
+
+READ16_HANDLER( h8s2246_per_regs_r )
+{
+ h83xx_state *h8 = get_safe_token(&space->device());
+ if (mem_mask == 0xffff)
+ {
+ return h8s2246_per_regs_read_16(h8, (offset << 1));
+ }
+ else if (mem_mask == 0xff00)
+ {
+ return h8s2246_per_regs_read_8(h8, (offset << 1)) << 8;
+ }
+ else if (mem_mask == 0x00ff)
+ {
+ return h8s2246_per_regs_read_8(h8, (offset << 1) + 1);
+ }
+ return 0;
+}
+
+READ16_HANDLER( h8s2323_per_regs_r )
+{
+ h83xx_state *h8 = get_safe_token(&space->device());
+ if (mem_mask == 0xffff)
+ {
+ return h8s2323_per_regs_read_16(h8, (offset << 1));
+ }
+ else if (mem_mask == 0xff00)
+ {
+ return h8s2323_per_regs_read_8(h8, (offset << 1)) << 8;
+ }
+ else if (mem_mask == 0x00ff)
+ {
+ return h8s2323_per_regs_read_8(h8, (offset << 1) + 1);
+ }
+ return 0;
+}
+
+// On-board RAM and peripherals
+static ADDRESS_MAP_START( h8_3002_internal_map, AS_PROGRAM, 16 )
+ // 512B RAM
+ AM_RANGE(0xfffd10, 0xffff0f) AM_RAM
+ AM_RANGE(0xffff10, 0xffffff) AM_READWRITE( h8_itu_r, h8_itu_w )
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( h8_3044_internal_map, AS_PROGRAM, 16 )
+ // 32k ROM, 2k RAM
+ AM_RANGE(0xfff710, 0xffff0f) AM_RAM
+ AM_RANGE(0xffff1c, 0xffffff) AM_READWRITE( h8_itu_r, h8_itu_w )
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( h8_3007_internal_map, AS_PROGRAM, 16 )
+ // ROM-less, 4k RAM
+ AM_RANGE(0xfee000, 0xfee0ff) AM_READWRITE( h8_3007_itu1_r, h8_3007_itu1_w )
+ AM_RANGE(0xffef20, 0xffff1f) AM_RAM
+ AM_RANGE(0xffff20, 0xffffe9) AM_READWRITE( h8_3007_itu_r, h8_3007_itu_w )
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( h8s_2241_internal_map, AS_PROGRAM, 16 )
+ AM_RANGE( 0xFFEC00, 0xFFFBFF ) AM_RAM // on-chip ram
+ AM_RANGE( 0xFFFE40, 0xFFFFFF ) AM_READWRITE( h8s2241_per_regs_r, h8s2241_per_regs_w ) // internal i/o registers
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( h8s_2246_internal_map, AS_PROGRAM, 16 )
+ AM_RANGE( 0xFFDC00, 0xFFFBFF ) AM_RAM // on-chip ram
+ AM_RANGE( 0xFFFE40, 0xFFFFFF ) AM_READWRITE( h8s2246_per_regs_r, h8s2246_per_regs_w ) // internal i/o registers
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( h8s_2323_internal_map, AS_PROGRAM, 16 )
+ AM_RANGE( 0xFFDC00, 0xFFFBFF ) AM_RAM // on-chip ram
+ AM_RANGE( 0xFFFE40, 0xFFFFFF ) AM_READWRITE( h8s2323_per_regs_r, h8s2323_per_regs_w ) // internal i/o registers
+ADDRESS_MAP_END
+
+CPU_GET_INFO( h8_3002 )
+{
+ h83xx_state *h8 = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch(state) {
+ // Interface functions and variables
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(h8); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(h8); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(h8); break;
+ case CPUINFO_FCT_EXIT: info->exit = 0; break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(h8); break;
+ case CPUINFO_FCT_BURN: info->burn = 0; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(h8_32); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &h8->cyccnt; break;
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(h83xx_state); break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 2; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 10; break;
+
+ // Bus sizes
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 24; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ // Internal maps
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map16 = ADDRESS_MAP_NAME(h8_3002_internal_map); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map16 = NULL; break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_IO: info->internal_map16 = NULL; break;
+
+ // CPU misc parameters
+ case DEVINFO_STR_NAME: strcpy(info->s, "H8/3002"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case CPUINFO_STR_FLAGS: strcpy(info->s, h8_get_ccr_str(h8)); break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 16; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = -1; break;
+
+ // CPU main state
+ case CPUINFO_INT_PC: info->i = h8->pc; break;
+ case CPUINFO_INT_PREVIOUSPC: info->i = h8->ppc; break;
+
+ case CPUINFO_INT_REGISTER + H8_PC: info->i = h8->pc; break;
+ case CPUINFO_INT_REGISTER + H8_CCR: info->i = h8_get_ccr(h8); break;
+
+ case CPUINFO_INT_REGISTER + H8_E0: info->i = h8->regs[0]; break;
+ case CPUINFO_INT_REGISTER + H8_E1: info->i = h8->regs[1]; break;
+ case CPUINFO_INT_REGISTER + H8_E2: info->i = h8->regs[2]; break;
+ case CPUINFO_INT_REGISTER + H8_E3: info->i = h8->regs[3]; break;
+ case CPUINFO_INT_REGISTER + H8_E4: info->i = h8->regs[4]; break;
+ case CPUINFO_INT_REGISTER + H8_E5: info->i = h8->regs[5]; break;
+ case CPUINFO_INT_REGISTER + H8_E6: info->i = h8->regs[6]; break;
+ case CPUINFO_INT_REGISTER + H8_E7: info->i = h8->regs[7]; break;
+
+ // CPU debug stuff
+ case CPUINFO_STR_REGISTER + H8_PC: sprintf(info->s, "PC :%08x", h8->pc); break;
+ case CPUINFO_STR_REGISTER + H8_CCR: sprintf(info->s, "CCR :%08x", h8_get_ccr(h8)); break;
+
+ case CPUINFO_STR_REGISTER + H8_E0: sprintf(info->s, "ER0 :%08x", h8->regs[0]); break;
+ case CPUINFO_STR_REGISTER + H8_E1: sprintf(info->s, "ER1 :%08x", h8->regs[1]); break;
+ case CPUINFO_STR_REGISTER + H8_E2: sprintf(info->s, "ER2 :%08x", h8->regs[2]); break;
+ case CPUINFO_STR_REGISTER + H8_E3: sprintf(info->s, "ER3 :%08x", h8->regs[3]); break;
+ case CPUINFO_STR_REGISTER + H8_E4: sprintf(info->s, "ER4 :%08x", h8->regs[4]); break;
+ case CPUINFO_STR_REGISTER + H8_E5: sprintf(info->s, "ER5 :%08x", h8->regs[5]); break;
+ case CPUINFO_STR_REGISTER + H8_E6: sprintf(info->s, "ER6 :%08x", h8->regs[6]); break;
+ case CPUINFO_STR_REGISTER + H8_E7: sprintf(info->s, " SP :%08x", h8->regs[7]); break;
+ }
+}
+
+CPU_GET_INFO( h8_3044 )
+{
+ switch (state)
+ {
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map16 = ADDRESS_MAP_NAME(h8_3044_internal_map); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(h8_24); break;
+ case DEVINFO_STR_NAME: strcpy(info->s, "H8/3044"); break;
+ default:
+ CPU_GET_INFO_CALL(h8_3002);
+ }
+}
+
+CPU_GET_INFO( h8_3007 )
+{
+ switch (state)
+ {
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map16 = ADDRESS_MAP_NAME(h8_3007_internal_map); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(h8_3007); break;
+ case DEVINFO_STR_NAME: strcpy(info->s, "H8/3007"); break;
+ default:
+ CPU_GET_INFO_CALL(h8_3002);
+ }
+}
+
+CPU_GET_INFO( h8s_2241 )
+{
+ switch (state)
+ {
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map16 = ADDRESS_MAP_NAME(h8s_2241_internal_map); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(h8s_2xxx); break;
+ case CPUINFO_FCT_RESET: info->reset= CPU_RESET_NAME(h8s_2xxx); break;
+ case DEVINFO_STR_NAME: strcpy(info->s, "H8S/2241"); break;
+ default:
+ CPU_GET_INFO_CALL(h8_3002);
+ }
+}
+
+CPU_GET_INFO( h8s_2246 )
+{
+ switch (state)
+ {
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map16 = ADDRESS_MAP_NAME(h8s_2246_internal_map); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(h8s_2xxx); break;
+ case CPUINFO_FCT_RESET: info->reset= CPU_RESET_NAME(h8s_2xxx); break;
+ case DEVINFO_STR_NAME: strcpy(info->s, "H8S/2246"); break;
+ default:
+ CPU_GET_INFO_CALL(h8_3002);
+ }
+}
+
+CPU_GET_INFO( h8s_2323 )
+{
+ switch (state)
+ {
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map16 = ADDRESS_MAP_NAME(h8s_2323_internal_map); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(h8s_2xxx); break;
+ case CPUINFO_FCT_RESET: info->reset= CPU_RESET_NAME(h8s_2xxx); break;
+ case DEVINFO_STR_NAME: strcpy(info->s, "H8S/2323"); break;
+ default:
+ CPU_GET_INFO_CALL(h8_3002);
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(H83002, h8_3002);
+DEFINE_LEGACY_CPU_DEVICE(H83007, h8_3007);
+DEFINE_LEGACY_CPU_DEVICE(H83044, h8_3044);
+
+DEFINE_LEGACY_CPU_DEVICE(H8S2241, h8s_2241);
+DEFINE_LEGACY_CPU_DEVICE(H8S2246, h8s_2246);
+DEFINE_LEGACY_CPU_DEVICE(H8S2323, h8s_2323);
+
diff --git a/trunk/src/emu/cpu/h83002/h8_8.c b/trunk/src/emu/cpu/h83002/h8_8.c
new file mode 100644
index 00000000000..386305dccb9
--- /dev/null
+++ b/trunk/src/emu/cpu/h83002/h8_8.c
@@ -0,0 +1,816 @@
+/***************************************************************************
+
+ h8_8.c: Hitachi H8/3xx 8/16-bit microcontroller emulator
+
+ Based on H8/300 series 16/32-bit emulator h83002.c.
+ Reference: Renesas Technology H8/3337 Group Hardware Manual
+
+ By R. Belmont
+
+****************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "h8.h"
+#include "h8priv.h"
+
+CPU_DISASSEMBLE(h8);
+
+#define H8_SP (7)
+
+#define h8_mem_read8(x) h8->program->read_byte(x)
+#define h8_mem_write8(x, y) h8->program->write_byte(x, y)
+
+// timing macros
+#define H8_IFETCH_TIMING(x) h8->cyccnt -= (x) * 4;
+#define H8_BRANCH_TIMING(x) h8->cyccnt -= (x) * 4;
+#define H8_STACK_TIMING(x) h8->cyccnt -= (x) * 4;
+#define H8_BYTE_TIMING(x, adr) if (address24 >= 0xff90) h8->cyccnt -= (x) * 3; else h8->cyccnt -= (x) * 4;
+#define H8_WORD_TIMING(x, adr) if (address24 >= 0xff90) h8->cyccnt -= (x) * 3; else h8->cyccnt -= (x) * 4;
+#define H8_IOP_TIMING(x) h8->cyccnt -= (x);
+
+static TIMER_CALLBACK( h8_timer_0_cb );
+static TIMER_CALLBACK( h8_timer_1_cb );
+static TIMER_CALLBACK( h8_timer_2_cb );
+static TIMER_CALLBACK( h8_timer_3_cb );
+
+INLINE UINT16 h8_mem_read16(h83xx_state *h8, offs_t address)
+{
+ UINT16 result = h8->program->read_byte(address)<<8;
+ return result | h8->program->read_byte(address+1);
+}
+
+INLINE UINT16 h8_readop16(h83xx_state *h8, offs_t address)
+{
+ UINT16 result = h8->direct->read_decrypted_byte(address)<<8;
+ return result | h8->direct->read_decrypted_byte(address+1);
+}
+
+INLINE void h8_mem_write16(h83xx_state *h8, offs_t address, UINT16 data)
+{
+ h8->program->write_byte(address, data >> 8);
+ h8->program->write_byte(address+1, data);
+}
+
+INLINE UINT32 h8_mem_read32(h83xx_state *h8, offs_t address)
+{
+ UINT32 result = h8->program->read_byte(address) << 24;
+ result |= h8->program->read_byte(address+1) << 16;
+ result |= h8->program->read_byte(address+2) << 8;
+ result |= h8->program->read_byte(address+3);
+
+ return result;
+}
+
+INLINE void h8_mem_write32(h83xx_state *h8, offs_t address, UINT32 data)
+{
+ h8->program->write_byte(address, data >> 24);
+ h8->program->write_byte(address+1, data >> 16);
+ h8->program->write_byte(address+2, data >> 8);
+ h8->program->write_byte(address+3, data);
+}
+
+static void h8_check_irqs(h83xx_state *h8);
+
+/* implementation */
+
+static void h8_300_InterruptRequest(h83xx_state *h8, UINT8 source, UINT8 state)
+{
+ int request = source / 32;
+ int bit = source % 32;
+
+ if (state)
+ {
+ h8->irq_req[request] |= (1<<bit);
+ }
+ else
+ {
+ h8->irq_req[request] &= ~(1<<bit);
+ }
+}
+
+
+static UINT8 h8_get_ccr(h83xx_state *h8)
+{
+ h8->ccr = 0;
+ if(h8->h8nflag)h8->ccr |= NFLAG;
+ if(h8->h8zflag)h8->ccr |= ZFLAG;
+ if(h8->h8vflag)h8->ccr |= VFLAG;
+ if(h8->h8cflag)h8->ccr |= CFLAG;
+ if(h8->h8uflag)h8->ccr |= UFLAG;
+ if(h8->h8hflag)h8->ccr |= HFLAG;
+ if(h8->h8uiflag)h8->ccr |= UIFLAG;
+ if(h8->h8iflag)h8->ccr |= IFLAG;
+ return h8->ccr;
+}
+
+static char *h8_get_ccr_str(h83xx_state *h8)
+{
+ static char res[10];
+
+ memset(res, 0, sizeof(res));
+ if(h8->h8iflag) strcat(res, "I"); else strcat(res, "i");
+ if(h8->h8uiflag)strcat(res, "U"); else strcat(res, "u");
+ if(h8->h8hflag) strcat(res, "H"); else strcat(res, "h");
+ if(h8->h8uflag) strcat(res, "U"); else strcat(res, "u");
+ if(h8->h8nflag) strcat(res, "N"); else strcat(res, "n");
+ if(h8->h8zflag) strcat(res, "Z"); else strcat(res, "z");
+ if(h8->h8vflag) strcat(res, "V"); else strcat(res, "v");
+ if(h8->h8cflag) strcat(res, "C"); else strcat(res, "c");
+
+ return res;
+}
+
+static void h8_set_ccr(h83xx_state *h8, UINT8 data)
+{
+ h8->ccr = data;
+
+ h8->h8nflag = 0;
+ h8->h8zflag = 0;
+ h8->h8vflag = 0;
+ h8->h8cflag = 0;
+ h8->h8hflag = 0;
+ h8->h8iflag = 0;
+ h8->h8uflag = 0;
+ h8->h8uiflag = 0;
+
+ if(h8->ccr & NFLAG) h8->h8nflag = 1;
+ if(h8->ccr & ZFLAG) h8->h8zflag = 1;
+ if(h8->ccr & VFLAG) h8->h8vflag = 1;
+ if(h8->ccr & CFLAG) h8->h8cflag = 1;
+ if(h8->ccr & HFLAG) h8->h8hflag = 1;
+ if(h8->ccr & UFLAG) h8->h8uflag = 1;
+ if(h8->ccr & UIFLAG) h8->h8uiflag = 1;
+ if(h8->ccr & IFLAG) h8->h8iflag = 1;
+
+ if (!h8->incheckirqs) h8_check_irqs(h8);
+}
+
+static INT16 h8_getreg16(h83xx_state *h8, UINT8 reg)
+{
+ if(reg > 7)
+ {
+ return h8->regs[reg-8]>>16;
+ }
+ else
+ {
+ return h8->regs[reg];
+ }
+}
+
+static void h8_setreg16(h83xx_state *h8, UINT8 reg, UINT16 data)
+{
+ if(reg > 7)
+ {
+ h8->regs[reg-8] &= 0xffff;
+ h8->regs[reg-8] |= data<<16;
+ }
+ else
+ {
+ h8->regs[reg] &= 0xffff0000;
+ h8->regs[reg] |= data;
+ }
+}
+
+static UINT8 h8_getreg8(h83xx_state *h8, UINT8 reg)
+{
+ if(reg > 7)
+ {
+ return h8->regs[reg-8];
+ }
+ else
+ {
+ return h8->regs[reg]>>8;
+ }
+}
+
+static void h8_setreg8(h83xx_state *h8, UINT8 reg, UINT8 data)
+{
+ if(reg > 7)
+ {
+ h8->regs[reg-8] &= 0xffffff00;
+ h8->regs[reg-8] |= data;
+ }
+ else
+ {
+ h8->regs[reg] &= 0xffff00ff;
+ h8->regs[reg] |= data<<8;
+ }
+}
+
+static UINT32 h8_getreg32(h83xx_state *h8, UINT8 reg)
+{
+ return h8->regs[reg];
+}
+
+static void h8_setreg32(h83xx_state *h8, UINT8 reg, UINT32 data)
+{
+ h8->regs[reg] = data;
+}
+
+static void h8_onstateload(h83xx_state *h8)
+{
+ h8_set_ccr(h8, h8->ccr);
+}
+
+static CPU_INIT(h8bit)
+{
+ h83xx_state *h8 = get_safe_token(device);
+
+ h8->h8iflag = 1;
+
+ h8->irq_cb = irqcallback;
+ h8->device = device;
+
+ h8->mode_8bit = 1;
+
+ h8->program = device->space(AS_PROGRAM);
+ h8->direct = &h8->program->direct();
+ h8->io = device->space(AS_IO);
+
+ h8->timer[0] = h8->device->machine().scheduler().timer_alloc(FUNC(h8_timer_0_cb), h8);
+ h8->timer[1] = h8->device->machine().scheduler().timer_alloc(FUNC(h8_timer_1_cb), h8);
+ h8->timer[2] = h8->device->machine().scheduler().timer_alloc(FUNC(h8_timer_2_cb), h8);
+ h8->timer[3] = h8->device->machine().scheduler().timer_alloc(FUNC(h8_timer_3_cb), h8);
+
+ device->save_item(NAME(h8->h8err));
+ device->save_item(NAME(h8->regs));
+ device->save_item(NAME(h8->pc));
+ device->save_item(NAME(h8->ppc));
+ device->save_item(NAME(h8->irq_req));
+ device->save_item(NAME(h8->ccr));
+ device->save_item(NAME(h8->mode_8bit));
+
+ device->save_item(NAME(h8->per_regs));
+ device->save_item(NAME(h8->h8TSTR));
+ device->save_item(NAME(h8->h8TCNT));
+
+ h8->device->machine().save().register_postload(save_prepost_delegate(FUNC(h8_onstateload), h8));
+}
+
+static CPU_RESET(h8bit)
+{
+ h83xx_state *h8 = get_safe_token(device);
+
+ h8->h8err = 0;
+ h8->pc = h8_mem_read16(h8, 0);
+
+ h8->incheckirqs = 0;
+
+ // disable timers
+ h8->h8TSTR = 0;
+ h8->FRC = 0;
+ h8->STCR = 0;
+ h8->TCR[0] = h8->TCR[1] = 0;
+ h8->TCORA[0] = h8->TCORB[0] = 0;
+ h8->TCORA[1] = h8->TCORB[1] = 0;
+ h8->TCNT[0] = h8->TCNT[1] = 0;
+
+ h8->has_h8speriphs = false;
+}
+
+static void h8_GenException(h83xx_state *h8, UINT8 vectornr)
+{
+ // push PC on stack
+ h8_setreg16(h8, H8_SP, h8_getreg16(h8, H8_SP)-2);
+ h8_mem_write16(h8, h8_getreg16(h8, H8_SP), h8->pc);
+ // push ccr
+ h8_setreg16(h8, H8_SP, h8_getreg16(h8, H8_SP)-2);
+ h8_mem_write16(h8, h8_getreg16(h8, H8_SP), h8_get_ccr(h8));
+
+ // generate address from vector
+ h8_set_ccr(h8, h8_get_ccr(h8) | 0x80);
+ if (h8->h8uiflag == 0)
+ h8_set_ccr(h8, h8_get_ccr(h8) | 0x40);
+ h8->pc = h8_mem_read16(h8, vectornr * 2) & 0xffff;
+
+ // these timings are still approximations but much better than before
+ H8_IFETCH_TIMING(8); // 24 cycles
+ H8_STACK_TIMING(3); // 12 cycles
+}
+
+static int h8_get_priority(h83xx_state *h8, UINT8 bit)
+{
+ int res = 0;
+ switch(bit)
+ {
+ case 3: // NMI
+ res = 2; break;
+ case 4: // IRQ0
+ if (h8->per_regs[0xc7]&0x01) res = 1; break;
+ case 5: // IRQ1
+ if (h8->per_regs[0xc7]&0x02) res = 1; break;
+ case 6: // IRQ2
+ if (h8->per_regs[0xc7]&0x04) res = 1; break;
+ case 7: // IRQ3
+ if (h8->per_regs[0xc7]&0x08) res = 1; break;
+ case 8: // IRQ4
+ if (h8->per_regs[0xc7]&0x10) res = 1; break;
+ case 9: // IRQ5
+ if (h8->per_regs[0xc7]&0x20) res = 1; break;
+ case 10: // IRQ6
+ if (h8->per_regs[0xc7]&0x40) res = 1; break;
+ case 11: // IRQ7
+ if (h8->per_regs[0xc7]&0x80) res = 1; break;
+ case 19: // 8-bit timer 0 match A
+ if (h8->TCR[0] & 0x40) res = 1; break;
+ case 20: // 8-bit timer 0 match B
+ if (h8->TCR[0] & 0x80) res = 1; break;
+ case 22: // 8-bit timer 1 match A
+ if (h8->TCR[1] & 0x40) res = 1; break;
+ case 23: // 8-bit timer 1 match B
+ if (h8->TCR[1] & 0x80) res = 1; break;
+ case 28: // SCI0 Rx
+ if (h8->per_regs[0xda]&0x40) res = 1; break;
+ case 32: // SCI1 Rx
+ if (h8->per_regs[0x8a]&0x40) res = 1; break;
+ }
+ return res;
+}
+
+static void h8_check_irqs(h83xx_state *h8)
+{
+ int lv = 0;
+
+ h8->incheckirqs = 1;
+
+ if (h8->h8iflag != 0)
+ {
+ lv = 2;
+ }
+
+ // any interrupts wanted and can accept ?
+ if(((h8->irq_req[0] != 0) || (h8->irq_req[1]!= 0) || (h8->irq_req[2] != 0)) && (lv >= 0))
+ {
+ UINT8 bit, source;
+ // which one ?
+ for(bit = 0, source = 0xff; source == 0xff && bit < 32; bit++)
+ {
+ if( h8->irq_req[0] & (1<<bit) )
+ {
+ if (h8_get_priority(h8, bit) >= lv)
+ {
+ // mask off
+ source = bit;
+ }
+ }
+ }
+ // which one ?
+ for(bit = 0; source == 0xff && bit < 32; bit++)
+ {
+ if( h8->irq_req[1] & (1<<bit) )
+ {
+ if (h8_get_priority(h8, bit + 32) >= lv)
+ {
+ // mask off
+ source = bit + 32;
+ }
+ }
+ }
+
+ // call the MAME callback if it's one of the external IRQs
+ if (source >= 3 && source <= 11)
+ {
+ (*h8->irq_cb)(h8->device, source - 3 + H8_NMI);
+ }
+
+ if (source != 0xff)
+ {
+ h8_GenException(h8, source);
+ }
+ }
+
+ h8->incheckirqs = 0;
+}
+
+#define H8_ADDR_MASK 0xffff
+#include "h8ops.h"
+
+// peripherals
+static void recalc_8bit_timer(h83xx_state *h8, int t)
+{
+ static const INT32 dividers[8] = { 0, 0, 8, 2, 64, 32, 1024, 256 };
+ int div;
+ INT32 time;
+
+ div = (h8->STCR & 1) | ((h8->TCR[t] & 3)<<1);
+
+ // if "no clock source", stop
+ if (div < 2)
+ {
+ h8->timer[(t*2)]->adjust(attotime::never);
+ h8->timer[(t*2)+1]->adjust(attotime::never);
+ return;
+ }
+
+ if (h8->TCORA[t])
+ {
+ time = (h8->device->unscaled_clock() / dividers[div]) / (h8->TCORA[t] - h8->TCNT[t]);
+ h8->timer[(t*2)]->adjust(attotime::from_hz(time));
+ }
+
+ if (h8->TCORB[t])
+ {
+ time = (h8->device->unscaled_clock() / dividers[div]) / (h8->TCORB[t] - h8->TCNT[t]);
+ h8->timer[(t*2)+1]->adjust(attotime::from_hz(time));
+ }
+}
+
+// IRQs: timer 0: 19 A 20 B 21 OV timer1: 22 A 23 B 24 OV
+static void timer_8bit_expire(h83xx_state *h8, int t, int sel)
+{
+ static const int irqbase[2] = { 19, 22 };
+
+ h8->timer[(t*2)+sel]->adjust(attotime::never);
+
+ h8->TCSR[t] |= ((0x40)<<sel);
+
+ // check for interrupts
+ if (h8->TCR[t] & (0x40<<sel))
+ {
+ h8->irq_req[0] |= (1 << (irqbase[t] + sel));
+ }
+
+ switch ((h8->TCR[t]>>3) & 3)
+ {
+ case 0: // no clear
+ break;
+
+ case 1: // clear on match A
+ if (!sel)
+ {
+ h8->TCNT[t] = 0;
+ recalc_8bit_timer(h8, t);
+ }
+ break;
+
+ case 2: // clear on match B
+ if (sel)
+ {
+ h8->TCNT[t] = 0;
+ recalc_8bit_timer(h8, t);
+ }
+ break;
+
+ case 3: // clear on external reset input signal (not implemented)
+ logerror("H8: external reset not implemented for 8-bit timers\n");
+ break;
+ }
+}
+
+
+// MAME interface stuff
+
+static CPU_SET_INFO( h8 )
+{
+ h83xx_state *h8 = get_safe_token(device);
+
+ switch(state) {
+ case CPUINFO_INT_PC: h8->pc = info->i; break;
+ case CPUINFO_INT_REGISTER + H8_PC: h8->pc = info->i; break;
+ case CPUINFO_INT_REGISTER + H8_CCR: h8_set_ccr(h8, info->i); break;
+
+ case CPUINFO_INT_REGISTER + H8_E0: h8->regs[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + H8_E1: h8->regs[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + H8_E2: h8->regs[2] = info->i; break;
+ case CPUINFO_INT_REGISTER + H8_E3: h8->regs[3] = info->i; break;
+ case CPUINFO_INT_REGISTER + H8_E4: h8->regs[4] = info->i; break;
+ case CPUINFO_INT_REGISTER + H8_E5: h8->regs[5] = info->i; break;
+ case CPUINFO_INT_REGISTER + H8_E6: h8->regs[6] = info->i; break;
+ case CPUINFO_INT_REGISTER + H8_E7: h8->regs[7] = info->i; break;
+
+ case CPUINFO_INT_INPUT_STATE + H8_NMI: h8_300_InterruptRequest(h8, 3, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + H8_IRQ0: h8_300_InterruptRequest(h8, 4, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + H8_IRQ1: h8_300_InterruptRequest(h8, 5, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + H8_IRQ2: h8_300_InterruptRequest(h8, 6, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + H8_IRQ3: h8_300_InterruptRequest(h8, 7, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + H8_IRQ4: h8_300_InterruptRequest(h8, 8, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + H8_IRQ5: h8_300_InterruptRequest(h8, 9, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + H8_IRQ6: h8_300_InterruptRequest(h8, 10, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + H8_IRQ7: h8_300_InterruptRequest(h8, 11, info->i); break;
+
+ case CPUINFO_INT_INPUT_STATE + H8_SCI_0_RX: h8_300_InterruptRequest(h8, 28, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + H8_SCI_1_RX: h8_300_InterruptRequest(h8, 32, info->i); break;
+
+ default:
+ fatalerror("h8_set_info unknown request %x", state);
+ break;
+ }
+}
+
+static READ8_HANDLER( h8330_itu_r )
+{
+ UINT8 val;
+ UINT8 reg;
+ UINT64 frc;
+ static const UINT64 divider[4] = { 2, 8, 32, 1 };
+ h83xx_state *h8 = get_safe_token(&space->device());
+
+ reg = (offset + 0x88) & 0xff;
+
+ switch(reg)
+ {
+ case 0x8d: // serial Rx 1
+ val = h8->io->read_byte(H8_SERIAL_1);
+ break;
+ case 0x92: // FRC H
+ frc = h8->device->total_cycles() / divider[h8->per_regs[0x96]];
+ frc %= 65536;
+ return frc>>8;
+ case 0x93: // FRC L
+ frc = h8->device->total_cycles() / divider[h8->per_regs[0x96]];
+ frc %= 65536;
+ return frc&0xff;
+ case 0xb2: // port 1 data
+ val = h8->io->read_byte(H8_PORT_1);
+ break;
+ case 0xb3: // port 2 data
+ val = h8->io->read_byte(H8_PORT_2);
+ break;
+ case 0xb6: // port 3 data
+ val = h8->io->read_byte(H8_PORT_3);
+ break;
+ case 0xb7: // port 4 data
+ val = h8->io->read_byte(H8_PORT_4);
+ break;
+ case 0xba: // port 5 data
+ val = h8->io->read_byte(H8_PORT_5);
+ break;
+ case 0xbb: // port 6 data
+ val = h8->io->read_byte(H8_PORT_6);
+ break;
+ case 0xbe: // port 7 data
+ val = h8->io->read_byte(H8_PORT_7);
+ break;
+ case 0xbf: // port 8 data
+ val = h8->io->read_byte(H8_PORT_8);
+ break;
+ case 0xc1: // port 9 data
+ val = h8->io->read_byte(H8_PORT_9);
+ break;
+ case 0xdc: // serial status
+ val = 0x87;
+ break;
+ case 0xdd: // serial Rx 0
+ val = h8->io->read_byte(H8_SERIAL_0);
+ break;
+ case 0xe0: // ADC 0 low byte
+ val = h8->io->read_byte(H8_ADC_0_L);
+ break;
+ case 0xe1: // ADC 0 high byte
+ val = h8->io->read_byte(H8_ADC_0_H);
+ break;
+ case 0xe2: // ADC 1 low byte
+ val = h8->io->read_byte(H8_ADC_1_L);
+ break;
+ case 0xe3: // ADC 1 high byte
+ val = h8->io->read_byte(H8_ADC_1_H);
+ break;
+ case 0xe4: // ADC 2 low byte
+ val = h8->io->read_byte(H8_ADC_2_L);
+ break;
+ case 0xe5: // ADC 2 high byte
+ val = h8->io->read_byte(H8_ADC_2_H);
+ break;
+ case 0xe6: // ADC 3 low byte
+ val = h8->io->read_byte(H8_ADC_3_L);
+ break;
+ case 0xe7: // ADC 3 high byte
+ val = h8->io->read_byte(H8_ADC_3_H);
+ break;
+ case 0xe8: // ADCSR: A/D control/status
+ val = 0x80; // return conversion completed
+ break;
+ default:
+ val = h8->per_regs[reg];
+ break;
+ }
+
+ return val;
+}
+
+static WRITE8_HANDLER( h8330_itu_w )
+{
+ UINT8 reg;
+ h83xx_state *h8 = get_safe_token(&space->device());
+
+ reg = (offset + 0x88) & 0xff;
+
+ switch (reg)
+ {
+ case 0x80:
+ printf("%02x to flash control or external\n", data);
+ break;
+ case 0x8b: // serial Tx 1
+ h8->io->write_byte(H8_SERIAL_1, data);
+ break;
+ case 0xb2: // port 1 data
+ h8->io->write_byte(H8_PORT_1, data);
+ break;
+ case 0xb3: // port 2 data
+ h8->io->write_byte(H8_PORT_2, data);
+ break;
+ case 0xb6: // port 3 data
+ h8->io->write_byte(H8_PORT_3, data);
+ break;
+ case 0xb7: // port 4 data
+ h8->io->write_byte(H8_PORT_4, data);
+ break;
+ case 0xba: // port 5 data
+ h8->io->write_byte(H8_PORT_5, data);
+ break;
+ case 0xbb: // port 6 data
+ h8->io->write_byte(H8_PORT_6, data);
+ break;
+ case 0xbe: // port 7 data
+ h8->io->write_byte(H8_PORT_7, data);
+ break;
+ case 0xbf: // port 8 data
+ h8->io->write_byte(H8_PORT_8, data);
+ break;
+ case 0xc1: // port 9 data
+ h8->io->write_byte(H8_PORT_9, data);
+ break;
+ case 0xdb: // serial Tx 0
+ h8->io->write_byte(H8_SERIAL_0, data);
+ break;
+
+ case 0xd8:
+ case 0xda:
+ case 0xdc:
+ case 0xd9:
+ break;
+
+ case 0x88:
+ case 0x8a:
+ case 0x8c:
+ case 0x89:
+ break;
+
+ case 0xc7:
+ break;
+
+ case 0xc8:
+ h8->TCR[0] = data;
+ recalc_8bit_timer(h8, 0);
+ break;
+ case 0xc9:
+ h8->TCSR[0] = data;
+ h8->irq_req[0] &= ~(1 << 19);
+ h8->irq_req[0] &= ~(1 << 20);
+ h8->irq_req[0] &= ~(1 << 21);
+ recalc_8bit_timer(h8, 0);
+ break;
+ case 0xca:
+ h8->TCORA[0] = data;
+ recalc_8bit_timer(h8, 0);
+ break;
+ case 0xcb:
+ h8->TCORB[0] = data;
+ recalc_8bit_timer(h8, 0);
+ break;
+ case 0xcc:
+ h8->TCNT[0] = data;
+ recalc_8bit_timer(h8, 0);
+ break;
+
+ case 0xc3:
+ h8->STCR = data;
+ recalc_8bit_timer(h8, 0);
+ recalc_8bit_timer(h8, 1);
+ break;
+
+ case 0xd0:
+ h8->TCR[1] = data;
+ recalc_8bit_timer(h8, 1);
+ break;
+ case 0xd1:
+ h8->TCSR[1] = data;
+ h8->irq_req[0] &= ~(1 << 22);
+ h8->irq_req[0] &= ~(1 << 23);
+ h8->irq_req[0] &= ~(1 << 24);
+ recalc_8bit_timer(h8, 1);
+ break;
+ case 0xd2:
+ h8->TCORA[1] = data;
+ recalc_8bit_timer(h8, 1);
+ break;
+ case 0xd3:
+ h8->TCORB[1] = data;
+ recalc_8bit_timer(h8, 1);
+ break;
+ case 0xd4:
+ h8->TCNT[1] = data;
+ recalc_8bit_timer(h8, 1);
+ break;
+ }
+
+ h8->per_regs[reg] = data;
+}
+
+static TIMER_CALLBACK( h8_timer_0_cb )
+{
+ h83xx_state *h8 = (h83xx_state *)ptr;
+ timer_8bit_expire(h8, 0, 0);
+}
+
+static TIMER_CALLBACK( h8_timer_1_cb )
+{
+ h83xx_state *h8 = (h83xx_state *)ptr;
+ timer_8bit_expire(h8, 0, 1);
+}
+
+static TIMER_CALLBACK( h8_timer_2_cb )
+{
+ h83xx_state *h8 = (h83xx_state *)ptr;
+ timer_8bit_expire(h8, 1, 0);
+}
+
+static TIMER_CALLBACK( h8_timer_3_cb )
+{
+ h83xx_state *h8 = (h83xx_state *)ptr;
+ timer_8bit_expire(h8, 1, 1);
+}
+
+static ADDRESS_MAP_START( h8_3334_internal_map, AS_PROGRAM, 8 )
+ // 512B RAM
+ AM_RANGE(0xfb80, 0xff7f) AM_RAM
+ AM_RANGE(0xff88, 0xffff) AM_READWRITE( h8330_itu_r, h8330_itu_w )
+ADDRESS_MAP_END
+
+CPU_GET_INFO( h8_3334 )
+{
+ h83xx_state *h8 = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch(state) {
+ // Interface functions and variables
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(h8); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(h8bit); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(h8bit); break;
+ case CPUINFO_FCT_EXIT: info->exit = 0; break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(h8); break;
+ case CPUINFO_FCT_BURN: info->burn = 0; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(h8); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &h8->cyccnt; break;
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(h83xx_state); break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 2; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 10; break;
+
+ // Bus sizes
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ // Internal maps
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME(h8_3334_internal_map); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = NULL; break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_IO: info->internal_map16 = NULL; break;
+
+ // CPU misc parameters
+ case DEVINFO_STR_NAME: strcpy(info->s, "H8/3334"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case CPUINFO_STR_FLAGS: strcpy(info->s, h8_get_ccr_str(h8)); break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 16; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = -1; break;
+
+ // CPU main state
+ case CPUINFO_INT_PC: info->i = h8->pc; break;
+ case CPUINFO_INT_PREVIOUSPC: info->i = h8->ppc; break;
+
+ case CPUINFO_INT_REGISTER + H8_PC: info->i = h8->pc; break;
+ case CPUINFO_INT_REGISTER + H8_CCR: info->i = h8_get_ccr(h8); break;
+
+ case CPUINFO_INT_REGISTER + H8_E0: info->i = h8->regs[0]; break;
+ case CPUINFO_INT_REGISTER + H8_E1: info->i = h8->regs[1]; break;
+ case CPUINFO_INT_REGISTER + H8_E2: info->i = h8->regs[2]; break;
+ case CPUINFO_INT_REGISTER + H8_E3: info->i = h8->regs[3]; break;
+ case CPUINFO_INT_REGISTER + H8_E4: info->i = h8->regs[4]; break;
+ case CPUINFO_INT_REGISTER + H8_E5: info->i = h8->regs[5]; break;
+ case CPUINFO_INT_REGISTER + H8_E6: info->i = h8->regs[6]; break;
+ case CPUINFO_INT_REGISTER + H8_E7: info->i = h8->regs[7]; break;
+
+ // CPU debug stuff
+ case CPUINFO_STR_REGISTER + H8_PC: sprintf(info->s, "PC :%08x", h8->pc); break;
+ case CPUINFO_STR_REGISTER + H8_CCR: sprintf(info->s, "CCR :%08x", h8_get_ccr(h8)); break;
+
+ case CPUINFO_STR_REGISTER + H8_E0: sprintf(info->s, " R0 :%08x", h8->regs[0]); break;
+ case CPUINFO_STR_REGISTER + H8_E1: sprintf(info->s, " R1 :%08x", h8->regs[1]); break;
+ case CPUINFO_STR_REGISTER + H8_E2: sprintf(info->s, " R2 :%08x", h8->regs[2]); break;
+ case CPUINFO_STR_REGISTER + H8_E3: sprintf(info->s, " R3 :%08x", h8->regs[3]); break;
+ case CPUINFO_STR_REGISTER + H8_E4: sprintf(info->s, " R4 :%08x", h8->regs[4]); break;
+ case CPUINFO_STR_REGISTER + H8_E5: sprintf(info->s, " R5 :%08x", h8->regs[5]); break;
+ case CPUINFO_STR_REGISTER + H8_E6: sprintf(info->s, " R6 :%08x", h8->regs[6]); break;
+ case CPUINFO_STR_REGISTER + H8_E7: sprintf(info->s, " SP :%08x", h8->regs[7]); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(H83334, h8_3334);
diff --git a/trunk/src/emu/cpu/h83002/h8disasm.c b/trunk/src/emu/cpu/h83002/h8disasm.c
new file mode 100644
index 00000000000..fb4b8c75a5b
--- /dev/null
+++ b/trunk/src/emu/cpu/h83002/h8disasm.c
@@ -0,0 +1,1583 @@
+/***************************************************************************
+
+ h8disasm.c: Hitachi H8/3xx series disassembler
+
+ Original by The_Author & DynaChicken for the ZiNc emulator.
+
+ MAME version, portability cleanups, and bugfixes by R. Belmont
+
+****************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "h8.h"
+
+static const char *const bit_instr[8] = {"bset", "bnot", "bclr", "btst", "bor", "bxor", "band", "bld"};
+static const char *const bit_instr2[8] = {"bset", "bnot", "bclr", "btst", "bior", "bixor", "biand", "bild"};
+static const char *const imm32l_instr[8] = {"mov", "add", "cmp", "sub", "or", "xor", "and", "?"};
+static const char *const branch_instr[16] = {"bt", "bf", "bhi", "bls", "bcc", "bcs", "bne", "beq", "bvc", "bvs", "bpl", "bmi", "bge", "blt", "bgt", "ble"};
+
+static const char *const reg_names32[8] = {"ER0", "ER1", "ER2", "ER3", "ER4", "ER5", "ER6", "SP"};
+static const char *const reg_names16[16] = {"R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7"};
+static const char *const reg_names8[16] = {"R0H", "R1H", "R2H", "R3H", "R4H", "R5H", "R6H", "R7H","R0L", "R1L", "R2L", "R3L", "R4L", "R5L", "R6L", "R7L"};
+
+static UINT32 h8disasm_0(UINT32 address, UINT32 opcode, char *output, const UINT8 *oprom);
+static UINT32 h8disasm_1(UINT32 address, UINT32 opcode, char *output, const UINT8 *oprom);
+static UINT32 h8disasm_5(UINT32 address, UINT32 opcode, char *output, const UINT8 *oprom);
+static UINT32 h8disasm_6(UINT32 address, UINT32 opcode, char *output, const UINT8 *oprom, UINT32 addr_mask);
+static UINT32 h8disasm_7(UINT32 address, UINT32 opcode, char *output, const UINT8 *oprom, UINT32 addr_mask);
+
+#define h8_mem_read16(x) ((oprom[x] << 8) | oprom[(x) + 1])
+#define h8_mem_read32(x) ((oprom[x] << 24) | (oprom[(x) + 1] << 16) | (oprom[(x) + 2] << 8) | oprom[(x) + 3])
+
+static offs_t h8_disasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 addr_mask)
+{
+ UINT32 size = 0;
+ UINT16 opcode;
+
+ opcode = h8_mem_read16(0);
+
+ switch((opcode>>12) & 0xf)
+ {
+ case 0x0:
+ size = h8disasm_0(pc, opcode, buffer, oprom);
+ break;
+ case 0x1:
+ size = h8disasm_1(pc, opcode, buffer, oprom);
+ break;
+ // mov.b @xx:8, Rd (abs)
+ case 0x2:
+ sprintf(buffer, "%4.4x mov.b @%8.8x, %s", opcode, (0xffff00 | (opcode & 0xff))&addr_mask, reg_names8[(opcode>>8) & 0xf]);
+ size = 2;
+ break;
+ // mov.b Rs, @xx:8 (abs)
+ case 0x3:
+ sprintf(buffer, "%4.4x mov.b %s, @%8.8x", opcode, reg_names8[(opcode>>8) & 0xf], (0xfffff00 | (opcode & 0xff))&addr_mask);
+ size = 2;
+ break;
+ // bcc @xx:8
+ case 0x4:
+ pc += 2;
+ sprintf(buffer, "%4.4x %s %8.8x", opcode, branch_instr[(opcode >> 8) & 0xf], (pc + (INT8)(opcode &0xff))&addr_mask);
+ size = 2;
+ break;
+ // group 5
+ case 0x5:
+ size = h8disasm_5(pc, opcode, buffer, oprom);
+ break;
+ case 0x6:
+ size = h8disasm_6(pc, opcode, buffer, oprom, addr_mask);
+ break;
+ case 0x7:
+ size = h8disasm_7(pc, opcode, buffer, oprom, addr_mask);
+ break;
+ case 0x8:
+ // add.b #xx:8, Rd
+ sprintf(buffer, "%4.4x add.b #%2.2x, %s", opcode, opcode & 0xff, reg_names8[(opcode>>8) & 0xf]);
+ size = 2;
+ break;
+ case 0x9:
+ // addx.b #xx:8, Rd
+ sprintf(buffer, "%4.4x addx.b #%2.2x, %s", opcode, opcode & 0xff, reg_names8[(opcode>>8) & 0xf]);
+ size = 2;
+ break;
+ case 0xa:
+ // cmp.b #xx:8, Rd
+ sprintf(buffer, "%4.4x cmp.b #%2.2x, %s", opcode, opcode & 0xff, reg_names8[(opcode>>8) & 0xf]);
+ size = 2;
+ break;
+ case 0xb:
+ // subx.b #xx:8, Rd
+ sprintf(buffer, "%4.4x subx.b #%2.2x, %s", opcode, opcode & 0xff, reg_names8[(opcode>>8) & 0xf]);
+ size = 2;
+ break;
+ case 0xc:
+ // or.b #xx:8, Rd
+ sprintf(buffer, "%4.4x or.b #%2.2x, %s", opcode, opcode & 0xff, reg_names8[(opcode>>8) & 0xf]);
+ size = 2;
+ break;
+ case 0xd:
+ // xor.b #xx:8, Rd
+ sprintf(buffer, "%4.4x xor.b #%2.2x, %s", opcode, opcode & 0xff, reg_names8[(opcode>>8) & 0xf]);
+ size = 2;
+ break;
+ case 0xe:
+ // and.b #xx:8, Rd
+ sprintf(buffer, "%4.4x and.b #%2.2x, %s", opcode, opcode & 0xff, reg_names8[(opcode>>8) & 0xf]);
+ size = 2;
+ break;
+ // mov.b #xx:8, Rd
+ case 0xf:
+ sprintf(buffer, "%4.4x mov.b #%2.2x, %s", opcode, opcode & 0xff, reg_names8[(opcode>>8) & 0xf]);
+ size = 2;
+ break;
+ default:
+ sprintf(buffer, "%4.4x", opcode);
+ size = 2;
+ break;
+ }
+
+ return size | DASMFLAG_SUPPORTED;
+}
+
+static UINT32 h8disasm_0(UINT32 pc, UINT32 opcode, char *buffer, const UINT8 *oprom)
+{
+ UINT32 size = 2;
+ UINT16 data16;
+ INT16 sdata16;
+ INT32 sdata32;
+ UINT16 ext16;
+
+ switch((opcode>>8)&0xf)
+ {
+ // nop
+ case 0:
+ sprintf(buffer, "%4.4x nop", opcode);
+ size = 2;
+ break;
+ case 0x1:
+ // 0140 = LDC/STC.W
+ if (opcode == 0x0140)
+ {
+ data16 = h8_mem_read16(2);
+ switch((data16>>8) & 0xff)
+ {
+ case 0x69:
+ // ERd
+ if (data16 & 0x80)
+ {
+ sprintf(buffer, "%4.4x stc.w ccr, @%s", opcode, reg_names32[(data16>>4)&7]);
+ }
+ else
+ {
+ sprintf(buffer, "%4.4x ldc.w @%s, ccr", opcode, reg_names32[(data16>>4)&7]);
+ }
+ size = 4;
+ break;
+
+ case 0x6f:
+ // @(disp, ERd)
+ sdata16 = h8_mem_read16(4);
+ if (data16 & 0x80)
+ {
+ sprintf(buffer, "%4.4x stc.w ccr, @(%x, %s)", opcode, sdata16, reg_names32[(data16>>4)&7]);
+ }
+ else
+ {
+ sprintf(buffer, "%4.4x ldc.w @(%x, %s), ccr", opcode, sdata16, reg_names32[(data16>>4)&7]);
+ }
+ size = 6;
+ break;
+
+ case 0x78:
+ // @(disp24, ERd)
+ size = 10;
+ ext16 = h8_mem_read16(4);
+ sdata32 = h8_mem_read32(6) & 0xffffff;
+ if (ext16 == 0x6b20)
+ {
+ sprintf(buffer, "%4.4x ldc.w @(%x, %s), ccr", opcode, sdata32, reg_names32[(data16>>4)&7]);
+ }
+ else if (ext16 == 0x6ba0)
+ {
+ sprintf(buffer, "%4.4x stc.w ccr, @(%x, %s)", opcode, sdata32, reg_names32[(data16>>4)&7]);
+ }
+ else
+ {
+ sprintf(buffer, "Unknown stc.w CCR form, prefix 0x78, format %x\n", ext16);
+ }
+ break;
+
+ case 0x6d:
+ // stc.w ccr,-@ERd / ldc @ERd+, ccr
+ if (data16 & 0x80)
+ {
+ sprintf(buffer, "%4.4x stc.w ccr, -@%s", opcode, reg_names32[(data16>>4)&7]);
+ }
+ else
+ {
+ sprintf(buffer, "%4.4x ldc.w @%s+, ccr", opcode, reg_names32[(data16>>4)&7]);
+ }
+ size = 4;
+ break;
+
+ case 0x6b:
+ // stc.w CCR,@abs
+ if ((data16&0xff) == 0x00) // 16 bit absolute
+ {
+ ext16 = h8_mem_read16(4);
+ sprintf(buffer, "%4.4x ldc.w @%04x, ccr", opcode, ext16);
+ size = 6;
+ }
+ else if ((data16&0xff) == 0x20) // 24 bit absolute
+ {
+ sdata32 = h8_mem_read32(4) & 0xffffff;
+ sprintf(buffer, "%4.4x ldc.w @%06x, ccr", opcode, sdata32);
+ size = 8;
+ }
+ else if ((data16&0xff) == 0x80) // 16 bit absolute
+ {
+ ext16 = h8_mem_read16(4);
+ sprintf(buffer, "%4.4x stc.w ccr, @%04x", opcode, ext16);
+ size = 6;
+ }
+ else if ((data16&0xff) == 0xa0) // 24 bit absolute
+ {
+ sdata32 = h8_mem_read32(4) & 0xffffff;
+ sprintf(buffer, "%4.4x stc.w ccr, @%06x", opcode, sdata32);
+ size = 8;
+ }
+ else
+ {
+ sprintf(buffer, "Unknown stc.w CCR form, prefix 0x6b, format %x\n", data16);
+ }
+ break;
+ }
+ break;
+ }
+
+ // 010x where x should always be 0!
+ if((opcode & 0xf) != 0)
+ {
+ sprintf(buffer, "%4.4x default", opcode);
+ break;
+ }
+ switch((opcode>>4) & 0xf)
+ {
+ // 0100 mov.l prefix
+ case 0:
+ data16 = h8_mem_read16(2);
+ switch((data16>>8) & 0xff)
+ {
+ case 0x69:
+ // mov.l @rx, rx
+ if((data16 & 0x80) == 0x80)
+ {
+ sprintf(buffer, "%4.4x mov.l %s, @%s", opcode, reg_names32[data16&7], reg_names32[(data16>>4)&7]);
+ }
+ else
+ {
+ sprintf(buffer, "%4.4x mov.l @%s, %s", opcode, reg_names32[(data16>>4)&7], reg_names32[data16&7]);
+ }
+ size = 4;
+ break;
+ case 0x6b:
+ // mov.l @aa:x, Rx
+ // 24 bit abs ?
+ if((data16 & 0x20 )==0x20)
+ {
+ sdata32 = h8_mem_read32(4);
+ sdata32 &= 0xffffff;
+ size = 8;
+ }
+ else
+ {
+ sdata16 = h8_mem_read16(4);
+ sdata32 = sdata16;
+ size = 6;
+ }
+ if((data16 & 0x80) == 0x80)
+ {
+ sprintf(buffer, "%4.4x %x mov.l %s, @%x", opcode, data16, reg_names32[data16&7], sdata32);
+ }
+ else
+ {
+ sprintf(buffer, "%4.4x %x mov.l @%x, %s", opcode, data16, sdata32, reg_names32[data16&7]);
+ }
+ break;
+ case 0x6d:
+ // mov.l @(Ers+), rd
+ if((data16 & 0x80) == 0x80)
+ {
+ sprintf(buffer, "%4.4x mov.l %s, @-%s", opcode, reg_names32[data16 & 0x7], reg_names32[(data16>>4)&7]);
+ }
+ else
+ {
+ sprintf(buffer, "%4.4x mov.l @%s+, %s", opcode, reg_names32[(data16>>4)&7], reg_names32[data16 & 0x7]);
+ }
+ size = 4;
+ break;
+ case 0x6f:
+ // mov.l @(displ16 + Rs), rd
+ sdata16=h8_mem_read16(4);
+ if((data16 & 0x80) == 0x80)
+ {
+ sprintf(buffer, "%4.4x mov.l %s,@(%x, %s)", opcode, reg_names32[data16 &0x7], sdata16, reg_names32[(data16>>4)&7]);
+ }
+ else
+ {
+ sprintf(buffer, "%4.4x mov.l @(%x, %s), %s", opcode, sdata16, reg_names32[(data16>>4)&7], reg_names32[data16 &0x7]);
+ }
+ size = 6;
+ break;
+ case 0x78:
+ // mov.l @(displ24 + Rs), rd
+ size = 10;
+ ext16 = h8_mem_read16(4);
+ sdata32 = h8_mem_read32(6) & 0xffffff;
+ if ( (data16 & 0x80) && ((ext16 & ~7) == 0x6ba0) )
+ {
+ sprintf(buffer, "%4.4x mov.l %s,@(%x, %s)", opcode, reg_names32[ext16&7], sdata32, reg_names32[(data16>>4)&7]);
+ }
+ else if ( (!(data16 & 0x80)) && ((ext16 & ~7) == 0x6b20) )
+ {
+ sprintf(buffer, "%4.4x mov.l @(%x, %s), %s", opcode, sdata32, reg_names32[(data16>>4)&7], reg_names32[ext16&7]);
+ }
+ else
+ {
+ sprintf(buffer, "%4.4x ? %x", opcode, data16);
+ }
+ break;
+
+ default:
+ sprintf(buffer, "%4.4x ? %x", opcode, data16);
+ break;
+ }
+ break;
+ // ldm/stm.l (ERn-ERn+1), @-SP
+ case 0x1:
+ data16 = h8_mem_read16(2);
+ size = 4;
+ if ((data16&0xfff0) == 0x6df0)
+ {
+ sprintf(buffer, "%4.4x stm.l (%s-%s), @-SP", opcode, reg_names32[data16 & 0x7], reg_names32[(data16 & 0x7)+1]);
+ }
+ else if ((data16&0xfff0) == 0x6d70)
+ {
+ sprintf(buffer, "%4.4x ldm.l @SP+, (%s-%s)", opcode, reg_names32[(data16 & 0x7)-1], reg_names32[(data16 & 0x7)]);
+ }
+ break;
+ // ldm/stm.l (ERn-ERn+2), @-SP
+ case 0x2:
+ data16 = h8_mem_read16(2);
+ size = 4;
+ if ((data16&0xfff0) == 0x6df0)
+ {
+ sprintf(buffer, "%4.4x stm.l (%s-%s), @-SP", opcode, reg_names32[data16 & 0x7], reg_names32[(data16 & 0x7)+2]);
+ }
+ else if ((data16&0xfff0) == 0x6d70)
+ {
+ sprintf(buffer, "%4.4x ldm.l @SP+, (%s-%s)", opcode, reg_names32[(data16 & 0x7)-2], reg_names32[(data16 & 0x7)]);
+ }
+ break;
+ // ldm/stm.l (ERn-ERn+3), @-SP
+ case 0x3:
+ data16 = h8_mem_read16(2);
+ size = 4;
+ if ((data16&0xfff0) == 0x6df0)
+ {
+ sprintf(buffer, "%4.4x stm.l (%s-%s), @-SP", opcode, reg_names32[data16 & 0x7], reg_names32[(data16 & 0x7)+3]);
+ }
+ else if ((data16&0xfff0) == 0x6d70)
+ {
+ sprintf(buffer, "%4.4x ldm.l @SP+, (%s-%s)", opcode, reg_names32[(data16 & 0x7)-3], reg_names32[(data16 & 0x7)]);
+ }
+ break;
+ // ldc
+ case 0x4:
+ break;
+ // sleep
+ case 0x8:
+ sprintf(buffer, "%4.4x sleep", opcode);
+ size = 2;
+ break;
+ // mulxs
+ case 0xc:
+ data16 = h8_mem_read16(2);
+ size = 4;
+ if ((data16&0xff00) == 0x5000)
+ {
+ sprintf(buffer, "mulxs.b %s, %s", reg_names16[(data16>>4)&0xf], reg_names16[data16&0xf]);
+ }
+ else if ((data16&0xff00) == 0x5200)
+ {
+ sprintf(buffer, "mulxs.w %s, %s", reg_names16[(data16>>4)&0xf], reg_names16[data16&0xf]);
+ }
+ else
+ {
+ sprintf(buffer, "%04x %04x unknown\n", opcode, data16);
+ }
+ break;
+ // divxs
+ case 0xd:
+ data16 = h8_mem_read16(2);
+ size = 4;
+ if ((data16&0xff00) == 0x5100)
+ {
+ sprintf(buffer, "divxs.b %s, %s", reg_names16[(data16>>4)&0xf], reg_names16[data16&0xf]);
+ }
+ else if ((data16&0xff00) == 0x5300)
+ {
+ sprintf(buffer, "divxs.w %s, %s", reg_names16[(data16>>4)&0xf], reg_names16[data16&0xf]);
+ }
+ else
+ {
+ sprintf(buffer, "%04x %04x unknown\n", opcode, data16);
+ }
+ break;
+ // 01f0 and.l prefix
+ case 0xf:
+ // or.l/xor.l/and.l rs, rd
+ data16 = h8_mem_read16(2);
+ size = 4;
+ switch((data16>>8)&0xff)
+ {
+ case 0x64: // or.l ERs, ERd
+ sprintf(buffer, "%4.4x or.l %s, %s", opcode, reg_names32[(data16>>4) & 0x7], reg_names32[data16 & 0x7]);
+ break;
+ case 0x65: // xor.l ERs, ERd
+ sprintf(buffer, "%4.4x xor.l %s, %s", opcode, reg_names32[(data16>>4) & 0x7], reg_names32[data16 & 0x7]);
+ break;
+ case 0x66: // and.l ERs, ERd
+ sprintf(buffer, "%4.4x and.l %s, %s", opcode, reg_names32[(data16>>4) & 0x7], reg_names32[data16 & 0x7]);
+ break;
+ default:
+ sprintf(buffer, "%4.4x default", opcode);
+ break;
+ }
+ break;
+ default:
+ sprintf(buffer, "%4.4x default", opcode);
+ break;
+ }
+ break;
+ // stc ccr, rd
+ case 0x2:
+ if(((opcode>>4) & 0xf) == 0)
+ {
+ sprintf(buffer, "%4.4x stc ccr, %s", opcode, reg_names8[opcode & 0xf]);
+ }
+ else
+ {
+ sprintf(buffer, "%4.4x default", opcode);
+ }
+ size = 2;
+ break;
+ // ldc rd, ccr
+ case 0x3:
+ if(((opcode>>4) & 0xf) == 0)
+ {
+ sprintf(buffer, "%4.4x ldc %s, ccr", opcode, reg_names8[opcode & 0xf]);
+ }
+ else
+ {
+ sprintf(buffer, "%4.4x default", opcode);
+ }
+ size = 2;
+ break;
+ // orc
+ case 0x4:
+ sprintf(buffer, "%4.4x orc #%2.2x, ccr", opcode, opcode & 0xff);
+ size = 2;
+ break;
+ // xorc
+ case 0x5:
+ sprintf(buffer, "%4.4x xorc #%2.2x, ccr", opcode, opcode & 0xff);
+ size = 2;
+ break;
+ // andc
+ case 0x6:
+ sprintf(buffer, "%4.4x andc #%2.2x, ccr", opcode, opcode & 0xff);
+ size = 2;
+ break;
+ // ldc
+ case 0x7:
+ sprintf(buffer, "%4.4x ldc #%2.2x, ccr", opcode, opcode & 0xff);
+ size = 2;
+ break;
+ // add.b rx, ry
+ case 0x8:
+ sprintf(buffer, "%4.4x add.b %s, %s", opcode, reg_names8[(opcode>>4) & 0xf], reg_names8[opcode & 0xf]);
+ size = 2;
+ break;
+ // add.w rx, ry
+ case 0x9:
+ sprintf(buffer, "%4.4x add.w %s, %s", opcode, reg_names16[(opcode>>4) & 0xf], reg_names16[opcode & 0xf]);
+ size = 2;
+ break;
+ // inc.b rx
+ case 0xA:
+ if(opcode&0x80)
+ {
+ if(opcode & 0x8)
+ {
+ sprintf(buffer, "%4.4x illegal", opcode);
+ }
+ else
+ {
+ sprintf(buffer, "%4.4x add.l %s, %s", opcode, reg_names32[(opcode>>4) & 7], reg_names32[opcode & 7]);
+ }
+ }
+ else
+ {
+ if(opcode & 0xf0)
+ {
+ sprintf(buffer, "%4.4x illegal", opcode);
+ }
+ else
+ {
+ sprintf(buffer, "%4.4x inc.b %s", opcode, reg_names8[(opcode & 0xf)]);
+ }
+ }
+ size = 2;
+ break;
+ //
+ case 0xb:
+ switch((opcode>>4)& 0xf)
+ {
+ case 0:
+ sprintf(buffer, "%4.4x adds.l #1, %s", opcode, reg_names32[opcode & 0x7]);
+ break;
+ case 5:
+ sprintf(buffer, "%4.4x inc.w #1, %s", opcode, reg_names16[opcode & 0xf]);
+ break;
+ case 7:
+ sprintf(buffer, "%4.4x inc.l #1, %s", opcode, reg_names32[opcode & 0x7]);
+ break;
+ case 8:
+ sprintf(buffer, "%4.4x adds.l #2, %s", opcode, reg_names32[opcode & 0x7]);
+ break;
+ case 9:
+ sprintf(buffer, "%4.4x adds.l #4, %s", opcode, reg_names32[opcode & 0x7]);
+ break;
+ case 0xd:
+ sprintf(buffer, "%4.4x inc.w #2, %s", opcode, reg_names16[opcode & 0xf]);
+ break;
+ case 0xf:
+ sprintf(buffer, "%4.4x inc.l #2, %s", opcode, reg_names32[opcode & 0x7]);
+ break;
+ default:
+ sprintf(buffer, "%4.4x illegal", opcode);
+ break;
+ }
+ size = 2;
+ break;
+ // mov.b rx, ry
+ case 0xc:
+ sprintf(buffer, "%4.4x mov.b %s, %s", opcode, reg_names8[(opcode>>4) & 0xf], reg_names8[opcode & 0xf]);
+ size = 2;
+ break;
+ // mov.w rx, ry
+ case 0xd:
+ sprintf(buffer, "%4.4x mov.w %s, %s", opcode, reg_names16[(opcode>>4) & 0xf], reg_names16[opcode & 0xf]);
+ size = 2;
+ break;
+ // addx.b rx, ry
+ case 0xe:
+ sprintf(buffer, "%4.4x addx.b %s, %s", opcode, reg_names8[(opcode>>4) & 0xf], reg_names8[opcode & 0xf]);
+ size = 2;
+ break;
+ case 0xf:
+ if(opcode & 0x80)
+ {
+ if(opcode & 8)
+ {
+ sprintf(buffer, "%4.4x illegal", opcode);
+ }
+ else
+ {
+ sprintf(buffer, "%4.4x mov.l %s, %s", opcode, reg_names32[(opcode>>4) & 0x7], reg_names32[opcode & 0x7]);
+ }
+ }
+ else
+ {
+ if((opcode & 0xf0) !=0)
+ {
+ sprintf(buffer, "%4.4x illegal", opcode);
+ }
+ else
+ {
+ sprintf(buffer, "%4.4x daa.b %s", opcode, reg_names8[opcode & 0xf]);
+ }
+ }
+ size = 2;
+ break;
+ default:
+ sprintf(buffer, "%4.4x default", opcode);
+ break;
+ }
+ return size;
+}
+
+static UINT32 h8disasm_1(UINT32 pc, UINT32 opcode, char *buffer, const UINT8 *oprom)
+{
+ UINT32 size = 2; //, mode8;
+ switch((opcode>>8)&0xf)
+ {
+ case 0x0:
+ switch((opcode>>4)&0xf)
+ {
+ // shll.b Rx
+ case 0x0:
+ sprintf(buffer, "%4.4x shll.b %s", opcode, reg_names8[opcode & 0xf]);
+ size = 2;
+ break;
+ // shll.w Rx
+ case 0x1:
+ sprintf(buffer, "%4.4x shll.w %s", opcode, reg_names16[opcode & 0xf]);
+ size = 2;
+ break;
+ // shll.l Rx
+ case 0x3:
+ sprintf(buffer, "%4.4x shll.l %s", opcode, reg_names32[opcode & 7]);
+ size = 2;
+ break;
+ // shll.b #2, Rx
+ case 0x4:
+ sprintf(buffer, "%4.4x shll.b #2, %s", opcode, reg_names8[opcode & 0xf]);
+ size = 2;
+ break;
+ // shll.w Rx
+ case 0x5:
+ sprintf(buffer, "%4.4x shll.w #2, %s", opcode, reg_names16[opcode & 0xf]);
+ size = 2;
+ break;
+ // shll.l #2, Rx
+ case 0x7:
+ sprintf(buffer, "%4.4x shll.l #2, %s", opcode, reg_names32[opcode & 7]);
+ size = 2;
+ break;
+ // shal.b Rx
+ case 0x8:
+ sprintf(buffer, "%4.4x shal.b %s", opcode, reg_names8[opcode & 0xf]);
+ size = 2;
+ break;
+ // shal.w Rx
+ case 0x9:
+ sprintf(buffer, "%4.4x shal.w %s", opcode, reg_names16[opcode & 0xf]);
+ size = 2;
+ break;
+ // shal.l Rx
+ case 0xb:
+ sprintf(buffer, "%4.4x shal.l %s", opcode, reg_names32[opcode & 7]);
+ size = 2;
+ break;
+ // shal.b #2, Rx
+ case 0xc:
+ sprintf(buffer, "%4.4x shal.b #2, %s", opcode, reg_names8[opcode & 0xf]);
+ size = 2;
+ break;
+ // shal.w #2, Rx
+ case 0xd:
+ sprintf(buffer, "%4.4x shal.w #2, %s", opcode, reg_names16[opcode & 0xf]);
+ size = 2;
+ break;
+ // shal.l #2, Rx
+ case 0xf:
+ sprintf(buffer, "%4.4x shal.l #2, %s", opcode, reg_names32[opcode & 7]);
+ size = 2;
+ break;
+ default:
+ sprintf(buffer, "%4.4x default", opcode);
+ size = 2;
+ break;
+ }
+ break;
+
+ case 0x1:
+ switch((opcode>>4)&0xf)
+ {
+ // shlr.b rx
+ case 0x0:
+ sprintf(buffer, "%4.4x shlr.b %s", opcode, reg_names8[opcode & 0xf]);
+ size = 2;
+ break;
+ // shlr.w rx
+ case 0x1:
+ sprintf(buffer, "%4.4x shlr.w %s", opcode, reg_names16[opcode & 0xf]);
+ size = 2;
+ break;
+ // shlr.l rx
+ case 0x3:
+ sprintf(buffer, "%4.4x shlr.l %s", opcode, reg_names32[opcode & 7]);
+ size = 2;
+ break;
+ // shlr.b #2, rx
+ case 0x4:
+ sprintf(buffer, "%4.4x shlr.b #2, %s", opcode, reg_names8[opcode & 0xf]);
+ size = 2;
+ break;
+ // shlr.w #2, rx
+ case 0x5:
+ sprintf(buffer, "%4.4x shlr.w #2, %s", opcode, reg_names16[opcode & 0xf]);
+ size = 2;
+ break;
+ // shlr.l #2, rx
+ case 0x7:
+ sprintf(buffer, "%4.4x shlr.l #2, %s", opcode, reg_names32[opcode & 7]);
+ size = 2;
+ break;
+ // shar.b rx
+ case 0x8:
+ sprintf(buffer, "%4.4x shar.b %s", opcode, reg_names8[opcode & 0xf]);
+ size = 2;
+ break;
+ // shar.w rx
+ case 0x9:
+ sprintf(buffer, "%4.4x shar.w %s", opcode, reg_names16[opcode & 0xf]);
+ size = 2;
+ break;
+ // shar.l rx
+ case 0xb:
+ sprintf(buffer, "%4.4x shar.l %s", opcode, reg_names32[opcode & 7]);
+ size = 2;
+ break;
+ // shar.b #2, rx
+ case 0xc:
+ sprintf(buffer, "%4.4x shar.b #2, %s", opcode, reg_names8[opcode & 0xf]);
+ size = 2;
+ break;
+ // shar.w #2, rx
+ case 0xd:
+ sprintf(buffer, "%4.4x shar.w #2, %s", opcode, reg_names16[opcode & 0xf]);
+ size = 2;
+ break;
+ // shar.l #2, rx
+ case 0xf:
+ sprintf(buffer, "%4.4x shar.l #2, %s", opcode, reg_names32[opcode & 7]);
+ size = 2;
+ break;
+ default:
+ sprintf(buffer, "%4.4x illegal ", opcode);
+ size = 2;
+ break;
+ }
+ break;
+ case 0x2:
+ switch((opcode>>4)&0xf)
+ {
+ // rotxl.b Rx
+ case 0x0:
+ sprintf(buffer, "%4.4x rotxl.b %s", opcode, reg_names8[opcode & 0xf]);
+ size = 2;
+ break;
+ // rotxl.w Rx
+ case 0x1:
+ sprintf(buffer, "%4.4x rotxl.w %s", opcode, reg_names16[opcode & 0xf]);
+ size = 2;
+ break;
+ // rotxl.l Rx
+ case 0x3:
+ sprintf(buffer, "%4.4x rotxl.l %s", opcode, reg_names32[opcode & 7]);
+ size = 2;
+ break;
+ // rotl.b Rx
+ case 0x8:
+ sprintf(buffer, "%4.4x rotl.b %s", opcode, reg_names8[opcode & 0xf]);
+ size = 2;
+ break;
+ // rotl.w Rx
+ case 0x9:
+ sprintf(buffer, "%4.4x rotl.w %s", opcode, reg_names16[opcode & 0xf]);
+ size = 2;
+ break;
+ // rotl.l Rx
+ case 0xb:
+ sprintf(buffer, "%4.4x rotl.l %s", opcode, reg_names32[opcode & 7]);
+ size = 2;
+ break;
+ // rotl.b #2, Rx
+ case 0xc:
+ sprintf(buffer, "%4.4x rotl.b #2, %s", opcode, reg_names8[opcode & 0xf]);
+ size = 2;
+ break;
+ // rotl.w #2, Rx
+ case 0xd:
+ sprintf(buffer, "%4.4x rotl.w #2, %s", opcode, reg_names16[opcode & 0xf]);
+ size = 2;
+ break;
+ // rotl.l #2, Rx
+ case 0xf:
+ sprintf(buffer, "%4.4x rotl.l #2, %s", opcode, reg_names32[opcode & 7]);
+ size = 2;
+ break;
+ default:
+ sprintf(buffer, "%4.4x ? ", opcode);
+ size = 2;
+ break;
+ }
+ break;
+ case 0x3:
+ switch((opcode>>4)&0xf)
+ {
+ // rotxr.b Rx
+ case 0x0:
+ sprintf(buffer, "%4.4x rotxr.b %s", opcode, reg_names8[opcode & 0xf]);
+ size = 2;
+ break;
+ // rotxr.w Rx
+ case 0x1:
+ sprintf(buffer, "%4.4x rotxr.w %s", opcode, reg_names16[opcode & 0xf]);
+ size = 2;
+ break;
+ // rotxr.l Rx
+ case 0x3:
+ sprintf(buffer, "%4.4x rotxr.l %s", opcode, reg_names32[opcode & 7]);
+ size = 2;
+ break;
+ // rotr.b Rx
+ case 0x8:
+ sprintf(buffer, "%4.4x rotr.b %s", opcode, reg_names8[opcode & 0xf]);
+ size = 2;
+ break;
+ // rotr.w Rx
+ case 0x9:
+ sprintf(buffer, "%4.4x rotr.w %s", opcode, reg_names16[opcode & 0xf]);
+ size = 2;
+ break;
+ // rotr.l Rx
+ case 0xb:
+ sprintf(buffer, "%4.4x rotr.l %s", opcode, reg_names32[opcode & 7]);
+ size = 2;
+ break;
+ // rotr.b #2, Rx
+ case 0xc:
+ sprintf(buffer, "%4.4x rotr.b #2, %s", opcode, reg_names8[opcode & 0xf]);
+ size = 2;
+ break;
+ // rotr.w #2, Rx
+ case 0xd:
+ sprintf(buffer, "%4.4x rotr.w #2, %s", opcode, reg_names16[opcode & 0xf]);
+ size = 2;
+ break;
+ // rotr.l #2, Rx
+ case 0xf:
+ sprintf(buffer, "%4.4x rotr.l #2, %s", opcode, reg_names32[opcode & 7]);
+ size = 2;
+ break;
+ default:
+ sprintf(buffer, "%4.4x ? ", opcode);
+ size = 2;
+ break;
+ }
+ break;
+ // or.b rs, rd
+ case 0x4:
+ sprintf(buffer, "%4.4x or.b %s, %s", opcode, reg_names8[(opcode>>4) & 0xf], reg_names8[opcode & 0xf]);
+ size = 2;
+ break;
+ // xor.b rs, rd
+ case 0x5:
+ sprintf(buffer, "%4.4x xor.b %s, %s", opcode, reg_names8[(opcode>>4) & 0xf], reg_names8[opcode & 0xf]);
+ size = 2;
+ break;
+ // and.b rs, rd
+ case 0x6:
+ sprintf(buffer, "%4.4x and.b %s, %s", opcode, reg_names8[(opcode>>4) & 0xf], reg_names8[opcode & 0xf]);
+ size = 2;
+ break;
+ // not
+ case 0x7:
+ switch((opcode>>4)&0xf)
+ {
+ // not.b Rx
+ case 0x0:
+ sprintf(buffer, "%4.4x not.b %s", opcode, reg_names8[opcode & 0xf]);
+ size = 2;
+ break;
+ // not.w Rx
+ case 0x1:
+ sprintf(buffer, "%4.4x not.w %s", opcode, reg_names16[opcode & 0xf]);
+ size = 2;
+ break;
+ // not.l Rx
+ case 0x3:
+ sprintf(buffer, "%4.4x not.l %s", opcode, reg_names32[opcode & 7]);
+ size = 2;
+ break;
+ // extu.b Rx
+ case 0x4:
+ sprintf(buffer, "%4.4x extu.b %s", opcode, reg_names8[opcode & 0xf]);
+ size = 2;
+ break;
+ // extu.w Rx
+ case 0x5:
+ sprintf(buffer, "%4.4x extu.w %s", opcode, reg_names16[opcode & 0xf]);
+ size = 2;
+ break;
+ // extu.l Rx
+ case 0x7:
+ sprintf(buffer, "%4.4x extu.l %s", opcode, reg_names32[opcode & 7]);
+ size = 2;
+ break;
+ // neg.b Rx
+ case 0x8:
+ sprintf(buffer, "%4.4x neg.b %s", opcode, reg_names8[opcode & 0xf]);
+ size = 2;
+ break;
+ // neg.w Rx
+ case 0x9:
+ sprintf(buffer, "%4.4x neg.w %s", opcode, reg_names16[opcode & 0xf]);
+ size = 2;
+ break;
+ // neg.l Rx
+ case 0xb:
+ sprintf(buffer, "%4.4x neg.l %s", opcode, reg_names32[opcode & 7]);
+ size = 2;
+ break;
+ // exts.b Rx
+ case 0xc:
+ sprintf(buffer, "%4.4x exts.b %s", opcode, reg_names8[opcode & 0xf]);
+ size = 2;
+ break;
+ // exts.w Rx
+ case 0xd:
+ sprintf(buffer, "%4.4x exts.w %s", opcode, reg_names16[opcode & 0xf]);
+ size = 2;
+ break;
+ // exts.l Rx
+ case 0xf:
+ sprintf(buffer, "%4.4x exts.l %s", opcode, reg_names32[opcode & 7]);
+ size = 2;
+ break;
+ default:
+ sprintf(buffer, "%4.4x default ", opcode);
+ size = 2;
+ break;
+ }
+ break;
+ // sub.b rs, rd
+ case 0x8:
+ sprintf(buffer, "%4.4x sub.b %s, %s", opcode, reg_names8[(opcode>>4) & 0xf], reg_names8[opcode & 0xf]);
+ size = 2;
+ break;
+ // sub.w rs, rd
+ case 0x9:
+ sprintf(buffer, "%4.4x sub.w %s, %s", opcode, reg_names16[(opcode>>4) & 0xf], reg_names16[opcode & 0xf]);
+ size = 2;
+ break;
+ // sub.b rx
+ case 0xA:
+ if(opcode&0x80)
+ {
+ if(opcode & 0x8)
+ {
+ sprintf(buffer, "%4.4x illegal", opcode);
+ }
+ else
+ {
+ sprintf(buffer, "%4.4x sub.l %s, %s", opcode, reg_names32[(opcode>>4) & 7], reg_names32[opcode & 7]);
+ }
+ }
+ else
+ {
+ if(opcode & 0xf0)
+ {
+ sprintf(buffer, "%4.4x illegal", opcode);
+ }
+ else
+ {
+ sprintf(buffer, "%4.4x dec.b %s", opcode, reg_names8[(opcode & 0xf)]);
+ }
+ }
+ size = 2;
+ break;
+ //
+ case 0xb:
+ switch((opcode>>4)& 0xf)
+ {
+ case 0:
+ sprintf(buffer, "%4.4x subs.l #1, %s", opcode, reg_names32[opcode & 0x7]);
+ break;
+ case 5:
+ sprintf(buffer, "%4.4x dec.w #1, %s", opcode, reg_names16[opcode & 0xf]);
+ break;
+ case 7:
+ sprintf(buffer, "%4.4x dec.l #1, %s", opcode, reg_names32[opcode & 0x7]);
+ break;
+ case 8:
+ sprintf(buffer, "%4.4x subs.l #2, %s", opcode, reg_names32[opcode & 0x7]);
+ break;
+ case 9:
+ sprintf(buffer, "%4.4x subs.l #4, %s", opcode, reg_names32[opcode & 0x7]);
+ break;
+ case 0xd:
+ sprintf(buffer, "%4.4x dec.w #2, %s", opcode, reg_names16[opcode & 0xf]);
+ break;
+ case 0xf:
+ sprintf(buffer, "%4.4x dec.l #2, %s", opcode, reg_names32[opcode & 0x7]);
+ break;
+ default:
+ sprintf(buffer, "%4.4x ?", opcode);
+ break;
+ }
+ size = 2;
+ break;
+ // cmp.b rs, rd
+ case 0xc:
+ sprintf(buffer, "%4.4x cmp.b %s, %s", opcode, reg_names8[(opcode>>4) & 0xf], reg_names8[opcode & 0xf]);
+ size = 2;
+ break;
+ // cmp.w rx, ry
+ case 0xd:
+ sprintf(buffer, "%4.4x cmp.w %s, %s", opcode, reg_names16[(opcode>>4) & 0xf], reg_names16[opcode & 0xf]);
+ size = 2;
+ break;
+ // subx.b rx, ry
+ case 0xe:
+ sprintf(buffer, "%4.4x subx.b %s, %s", opcode, reg_names8[(opcode>>4) & 0xf], reg_names8[opcode & 0xf]);
+ size = 2;
+ break;
+ case 0xf:
+ if(opcode & 0x80)
+ {
+ if(opcode & 8)
+ {
+ sprintf(buffer, "%4.4x illegal", opcode);
+ }
+ else
+ {
+ sprintf(buffer, "%4.4x cmp.l %s, %s", opcode, reg_names32[(opcode>>4) & 0x7], reg_names32[opcode & 0x7]);
+ }
+ }
+ else
+ {
+ if((opcode & 0xf0) !=0)
+ {
+ sprintf(buffer, "%4.4x illegal", opcode);
+ }
+ else
+ {
+ sprintf(buffer, "%4.4x das.b %s", opcode, reg_names8[opcode & 0xf]);
+ }
+ }
+ size = 2;
+ break;
+ default:
+ sprintf(buffer, "%4.4x default", opcode);
+ break;
+ }
+
+ return size;
+}
+
+static UINT32 h8disasm_5(UINT32 pc, UINT32 opcode, char *buffer, const UINT8 *oprom)
+{
+ UINT32 size = 2;
+ UINT32 data32;
+ INT16 data16;
+
+ switch((opcode>>8)&0xf)
+ {
+ // mulxu.b
+ case 0x0:
+ sprintf(buffer, "%4.4x mulxu.b %s, %s", opcode, reg_names8[(opcode>>4) & 0xf], reg_names8[opcode & 0xf]);
+ size = 2;
+ break;
+ // divxu.b
+ case 0x1:
+ sprintf(buffer, "%4.4x divxu.b %s, %s", opcode, reg_names8[(opcode>>4) & 0xf], reg_names8[opcode & 0xf]);
+ size = 2;
+ break;
+ // mulxu.w
+ case 0x2:
+ sprintf(buffer, "%4.4x mulxu.w %s, %s", opcode, reg_names16[(opcode>>4) & 0xf], reg_names32[opcode & 7]);
+ size = 2;
+ break;
+ // divxu.w
+ case 0x3:
+ sprintf(buffer, "%4.4x divxu.w %s, %s", opcode, reg_names16[(opcode>>4) & 0xf], reg_names32[opcode & 7]);
+ size = 2;
+ break;
+ // rts
+ case 0x4:
+ if(opcode == 0x5470)
+ {
+ sprintf(buffer, "%4.4x rts", opcode);
+ }
+ else
+ {
+ sprintf(buffer, "%4.4x default", opcode);
+ }
+ size = 2 | DASMFLAG_STEP_OUT;
+ break;
+ // bsr 8
+ case 0x5:
+ sprintf(buffer, "%4.4x bsr %x", opcode, pc+2 + ((INT8)opcode& 0xff));
+ size = 2 | DASMFLAG_STEP_OVER;
+ break;
+ // rte
+ case 0x6:
+ if(opcode == 0x5670)
+ {
+ sprintf(buffer, "%4.4x rte", opcode);
+ }
+ else
+ {
+ sprintf(buffer, "%4.4x default", opcode);
+ }
+ size = 2 | DASMFLAG_STEP_OUT;
+ break;
+ // trapa
+ case 0x7:
+ if(opcode & 0xcf)
+ {
+ sprintf(buffer, "%4.4x illegal", opcode);
+ }
+ else
+ {
+ sprintf(buffer, "%4.4x trapa #%x", opcode, (opcode >> 4) & 3);
+ }
+ size = 2 | DASMFLAG_STEP_OVER;
+ break;
+ // bcc 16
+ case 0x8:
+ if(opcode & 0xf)
+ {
+ sprintf(buffer, "%4.4x illegal", opcode);
+ size = 2;
+ }
+ else
+ {
+ data16 = h8_mem_read16(2);
+ pc += 4;
+ sprintf(buffer, "%4.4x %s %8.8x", opcode, branch_instr[(opcode >> 4) & 0xf], pc + (INT16)(data16));
+ size = 4;
+ }
+ break;
+ // jmp @erd
+ case 0x9:
+ sprintf(buffer, "%4.4x jmp @%s", opcode, reg_names32[(opcode>>4) &7]);
+ size = 2;
+ break;
+ // jmp @aa:24
+ case 0xa:
+ data32=h8_mem_read32(0);
+ sprintf(buffer, "%4.4x jmp %8.8x", opcode, (data32& 0xffffff));
+ size = 4;
+ break;
+ // jmp @aa:8
+ case 0xb:
+ sprintf(buffer, "%4.4x jmp %8.8x", opcode, (opcode & 0xff));
+ size = 2;
+ break;
+ // bsr @aa:16
+ case 0xc:
+ if(opcode & 0xff)
+ {
+ sprintf(buffer, "%4.4x illegal", opcode);
+ size = 2;
+ }
+ else
+ {
+ data16=h8_mem_read16(2);
+ sprintf(buffer, "%4.4x bsr %8.8x", opcode, data16+pc+4);
+ size = 4 | DASMFLAG_STEP_OVER;
+ }
+ break;
+ // jsr @erd
+ case 0xd:
+ sprintf(buffer, "%4.4x jsr @%s", opcode, reg_names32[(opcode>>4) &7]);
+ size = 2 | DASMFLAG_STEP_OVER;
+ break;
+ // jsr @aa:24
+ case 0xe:
+ data32=h8_mem_read32(0);
+ sprintf(buffer, "%4.4x jsr %8.8x", opcode, (data32& 0xffffff));
+ size = 4 | DASMFLAG_STEP_OVER;
+ break;
+ // jsr @aa:8
+ case 0xf:
+ sprintf(buffer, "%4.4x jsr %8.8x", opcode, (opcode & 0xff));
+ size = 2 | DASMFLAG_STEP_OVER;
+ break;
+ default:
+ sprintf(buffer, "%4.4x default", opcode);
+ break;
+ }
+ return size;
+}
+
+static UINT32 h8disasm_6(UINT32 address, UINT32 opcode, char *buffer, const UINT8 *oprom, UINT32 addr_mask)
+{
+ UINT32 size = 2;
+ UINT32 data32;
+ INT16 data16;
+
+ switch((opcode>>8)&0xf)
+ {
+ case 0:case 1:case 2:case 3:
+ if(((opcode>>4)&0x8) == 0)
+ {
+ sprintf(buffer, "%4.4x %s.b %s, %s", opcode, bit_instr[(opcode>>8)&7], reg_names8[(opcode>>4)&0xf], reg_names8[(opcode & 0xf)]);
+ }
+ else
+ {
+ sprintf(buffer, "%4.4x %s.b %s, %s", opcode, bit_instr2[(opcode>>8)&7], reg_names8[(opcode>>4)&0xf], reg_names8[(opcode & 0xf)]);
+ }
+ size = 2;
+ break;
+ // or.w rs, rd
+ case 0x4:
+ sprintf(buffer, "%4.4x or.w %s, %s", opcode, reg_names16[(opcode>>4) & 0xf], reg_names16[opcode & 0xf]);
+ size = 2;
+ break;
+ // xor.w rs, rd
+ case 0x5:
+ sprintf(buffer, "%4.4x xor.w %s, %s", opcode, reg_names16[(opcode>>4) & 0xf], reg_names16[opcode & 0xf]);
+ size = 2;
+ break;
+ // and.w rs, rd
+ case 0x6:
+ sprintf(buffer, "%4.4x and.w %s, %s", opcode, reg_names16[(opcode>>4) & 0xf], reg_names16[opcode & 0xf]);
+ size = 2;
+ break;
+ // bst/bist #imm, rd
+ case 0x7:
+ if(opcode & 0x80)
+ {
+ sprintf(buffer, "%4.4x bist.b #%1.1x, %s", opcode, (opcode>>4)&7, reg_names8[(opcode & 0xf)]);
+ }
+ else
+ {
+ sprintf(buffer, "%4.4x bst.b #%1.1x, %s", opcode, (opcode>>4)&7, reg_names8[(opcode & 0xf)]);
+ }
+ size = 2;
+ break;
+ case 0x8:
+ if(opcode & 0x80)
+ {
+ sprintf(buffer, "%4.4x mov.b %s, @%s", opcode, reg_names8[opcode & 0xf], reg_names32[(opcode >> 4) & 7]);
+ size = 2;
+ }
+ else
+ {
+ sprintf(buffer, "%4.4x mov.b @%s, %s", opcode, reg_names32[(opcode >> 4) & 7], reg_names8[opcode & 0xf]);
+ size = 2;
+ }
+ break;
+ case 0x9:
+ if(opcode & 0x80)
+ {
+ sprintf(buffer, "%4.4x mov.w %s, @%s", opcode, reg_names16[opcode & 0xf], reg_names32[(opcode >> 4) & 7]);
+ size = 2;
+ }
+ else
+ {
+ sprintf(buffer, "%4.4x mov.w @%s, %s", opcode, reg_names32[(opcode >> 4) & 7], reg_names16[opcode & 0xf]);
+ size = 2;
+ }
+ break;
+ case 0xa:
+ // mov.b rx, @xx
+ switch((opcode>>4)&0xf)
+ {
+ case 0x0:
+ data16=h8_mem_read16(2);
+ sprintf(buffer, "%4.4x mov.b @%x, %s", opcode, data16, reg_names8[opcode & 0xf]);
+ size = 4;
+ break;
+ case 0x2:
+ data32=h8_mem_read32(2);
+ sprintf(buffer, "%4.4x mov.b @%8.8x, %s", opcode, data32&addr_mask, reg_names8[opcode & 0xf]);
+ size = 6;
+ break;
+ case 0x3: // bclr #imm, imm:32
+ data32=h8_mem_read32(2);
+ data16=h8_mem_read16(6);
+ switch ((data16 >> 8) & 0xff)
+ {
+ case 0x60 :
+ sprintf(buffer, "%4.4x bset %s, @%8.8x", opcode, reg_names16[(data16>>4)&0xf], data32&addr_mask);
+ break;
+ case 0x61 :
+ sprintf(buffer, "%4.4x bnot %s, @%8.8x", opcode, reg_names16[(data16>>4)&0xf], data32&addr_mask);
+ break;
+ case 0x62 :
+ sprintf(buffer, "%4.4x bclr %s, @%8.8x", opcode, reg_names16[(data16>>4)&0xf], data32&addr_mask);
+ break;
+ case 0x63:
+ sprintf(buffer, "%4.4x btst %s, @%8.8x", opcode, reg_names16[(data16>>4)&0xf], data32&addr_mask);
+ break;
+ case 0x70 :
+ sprintf(buffer, "%4.4x bset #%d, @%8.8x", opcode, (data16>>4)&7, data32&addr_mask);
+ break;
+ case 0x71 :
+ sprintf(buffer, "%4.4x bnot #%d, @%8.8x", opcode, (data16>>4)&7, data32&addr_mask);
+ break;
+ case 0x72 :
+ sprintf(buffer, "%4.4x bclr #%d, @%8.8x", opcode, (data16>>4)&7, data32&addr_mask);
+ break;
+ case 0x73 :
+ sprintf(buffer, "%4.4x btst #%d, @%8.8x", opcode, (data16>>4)&7, data32&addr_mask);
+ break;
+ }
+ size = 8;
+ break;
+ case 0x8:
+ data16=h8_mem_read16(2);
+ sprintf(buffer, "%4.4x mov.b %s, @%8.8x", opcode, reg_names8[opcode & 0xf], data16&addr_mask);
+ size = 4;
+ break;
+ case 0xa:
+ data32=h8_mem_read32(2);
+ sprintf(buffer, "%4.4x mov.b %s, @%8.8x", opcode, reg_names8[opcode & 0xf], data32&addr_mask);
+ size = 6;
+ break;
+ default:
+ sprintf(buffer, "%4.4x 0x6a ? ", opcode);
+ size = 2;
+ break;
+ }
+ break;
+ case 0xb:
+ // mov.w rx, @xx
+ switch((opcode>>4)&0xf)
+ {
+ case 0x0:
+ data16=h8_mem_read16(2);
+ sprintf(buffer, "%4.4x mov.w @%8.8x, %s", opcode, data16&addr_mask, reg_names16[opcode & 0xf]);
+ size = 4;
+ break;
+ case 0x2:
+ data32=h8_mem_read32(2);
+ sprintf(buffer, "%4.4x mov.w @%8.8x, %s", opcode, data32&addr_mask, reg_names16[opcode & 0xf]);
+ size = 6;
+ break;
+ case 0x8:
+ data16=h8_mem_read16(2);
+ sprintf(buffer, "%4.4x mov.w %s, @%8.8x", opcode, reg_names16[opcode & 0xf], data16&addr_mask);
+ size = 4;
+ break;
+ case 0xa:
+ data32=h8_mem_read32(2);
+ sprintf(buffer, "%4.4x mov.w %s, @%8.8x", opcode, reg_names16[opcode & 0xf], data32&addr_mask);
+ size = 6;
+ break;
+ default:
+ sprintf(buffer, "%4.4x 0x6b ? ", opcode);
+ size = 2;
+ break;
+ }
+ break;
+ case 0xc:
+ // mov.b @erx+,rx / mov.b @-erx, rx
+ if(opcode & 0x80)
+ {
+ sprintf(buffer, "%4.4x mov.b %s, @(-%s)", opcode, reg_names8[opcode &0xf], reg_names32[(opcode>>4)&7]);
+ }
+ else
+ {
+ sprintf(buffer, "%4.4x mov.b @(%s+), %s", opcode, reg_names32[(opcode>>4)&7], reg_names8[opcode &0xf]);
+ }
+ size = 2;
+ break;
+ case 0xd:
+ // mov.w @ers+, rd / mov.w rs, @-erd
+ if(opcode & 0x80)
+ {
+ sprintf(buffer, "%4.4x mov.w %s, @-%s", opcode, reg_names16[opcode&0xf], reg_names32[(opcode>>4)&7]);
+ }
+ else
+ {
+ sprintf(buffer, "%4.4x mov.w @%s+, %s", opcode, reg_names32[(opcode>>4)&7], reg_names16[opcode & 0xf]);
+ }
+ size = 2;
+ break;
+ case 0xe:
+ // mov.b @(displ16 + Rs), rd
+ data16=h8_mem_read16(2);
+ if(opcode & 0x80)
+ {
+ sprintf(buffer, "%4.4x mov.b %s,@(%x, %s)", opcode, reg_names8[opcode &0xf], data16, reg_names32[(opcode>>4)&7]);
+ }
+ else
+ {
+ sprintf(buffer, "%4.4x mov.b @(%x, %s), %s", opcode, data16, reg_names32[(opcode>>4)&7], reg_names8[opcode &0xf]);
+ }
+ size = 4;
+ break;
+ case 0xf:
+ // mov.w @(displ16 + Rs), rd
+ data16=h8_mem_read16(2);
+ if(opcode & 0x80)
+ {
+ sprintf(buffer, "%4.4x mov.w %s,@(%x, %s)", opcode, reg_names16[opcode &0xf], data16, reg_names32[(opcode>>4)&7]);
+ }
+ else
+ {
+ sprintf(buffer, "%4.4x mov.w @(%x, %s), %s", opcode, data16, reg_names32[(opcode>>4)&7], reg_names16[opcode &0xf]);
+ }
+ size = 4;
+ break;
+ default:
+ sprintf(buffer, "%4.4x default", opcode);
+ break;
+ }
+ return size;
+}
+
+static UINT32 h8disasm_7(UINT32 address, UINT32 opcode, char *buffer, const UINT8 *oprom, UINT32 addr_mask)
+{
+ UINT32 size = 2;
+ UINT32 data32;
+ UINT16 data16;
+
+ switch((opcode>>8)&0xf)
+ {
+ case 0:case 1:case 2:case 3:case 4:case 5:case 6:case 7:
+ if(((opcode>>4)&0x8) == 0)
+ {
+ sprintf(buffer, "%4.4x %s.b #%1.1x, %s", opcode, bit_instr[(opcode>>8)&7], (opcode>>4)&7, reg_names8[(opcode & 0xf)]);
+ }
+ else
+ {
+ sprintf(buffer, "%4.4x %s.b #%1.1x, %s", opcode, bit_instr2[(opcode>>8)&7], (opcode>>4)&7, reg_names8[(opcode & 0xf)]);
+ }
+ size = 2;
+ break;
+ case 0x8:
+ data16 = h8_mem_read16(2);
+ data32 = h8_mem_read32(4);
+ if(((data16>>8) & 0xf) == 0xa)
+ {
+ if(((data16>>4) & 0xf) == 0xa)
+ {
+ sprintf(buffer, "%4.4x mov.b %s, @(%x, %s)", opcode, reg_names8[(data16 & 0xf)], data32, reg_names32[(opcode>>4)&7]);
+ }
+ else
+ {
+ sprintf(buffer, "%4.4x mov.b @(%x, %s), %s", opcode, data32, reg_names32[(opcode>>4) & 7], reg_names8[(data16 & 0xf)]);
+ }
+ }
+ else
+ {
+ if(((data16>>4) & 0xf) == 0xa)
+ {
+ sprintf(buffer, "%4.4x mov.w %s, @(%x, %s)", opcode, reg_names16[(data16 & 0xf)], data32, reg_names32[(opcode>>4)&7]);
+ }
+ else
+ {
+ sprintf(buffer, "%4.4x mov.w @(%x, %s), %s", opcode, data32, reg_names32[(opcode>>4) & 7], reg_names16[(data16 & 0xf)]);
+ }
+ }
+ size = 8;
+ break;
+ // xxx.w #aa:16, rd
+ case 0x9:
+ if( ((opcode>>4) & 0xf) > 0x6)
+ {
+ sprintf(buffer, "%4.4x illegal", opcode);
+ size = 2;
+ }
+ else
+ {
+ data16 = h8_mem_read16(2);
+ sprintf(buffer, "%4.4x %s.w #%x, %s", opcode, imm32l_instr[(opcode>>4)&7], data16, reg_names16[opcode&0xf]);
+ size = 4;
+ }
+ break;
+ // xxx.l #aa:32, erd
+ case 0xa:
+ if( (((opcode>>4) & 0xf) > 0x6) || (opcode & 0x8))
+ {
+ sprintf(buffer, "%4.4x illegal", opcode);
+ size = 2;
+ }
+ else
+ {
+ data32 = h8_mem_read32(2);
+ sprintf(buffer, "%4.4x %s.l #%x, %s", opcode, imm32l_instr[(opcode>>4)&7], data32, reg_names32[opcode&0x7]);
+ size = 6;
+ }
+ break;
+ // eepmov
+ case 0xb:
+ switch (opcode & 0x00ff)
+ {
+ case 0x5c:
+ sprintf(buffer, "%4.4x eepmov.b", opcode);
+ break;
+ case 0xd4:
+ sprintf(buffer, "%4.4x eepmov.w", opcode);
+ break;
+ default:
+ sprintf(buffer, "%4.4x eepmov UNK!", opcode);
+ break;
+ }
+ size = 4;
+ break;
+ // bxx.b #xx:3, @rd
+ case 0xc:
+ case 0xd:
+ data16 = h8_mem_read16(2);
+ size = 4;
+ switch(data16>>8)
+ {
+ case 0x60: // bset/bnot/bclr.b rn, @erd
+ case 0x61:
+ case 0x62:
+ if (((opcode & 0x8f)!=0)||((data16 & 0x0f)!=0))
+ {
+ sprintf(buffer, "%4.4x default", opcode);
+ break;
+ }
+ sprintf(buffer, "%4.4x %s.b %s, @%s", opcode, bit_instr[(data16>>8)&7], reg_names16[(data16>>4)&0xf], reg_names32[(opcode>>4) & 0x7]);
+ break;
+
+ case 0x67: // bst/bist.b #xx:3, @erd
+ if (((opcode & 0x8f)!=0)||((data16 & 0x0f)!=0))
+ {
+ sprintf(buffer, "%4.4x default", opcode);
+ break;
+ }
+ if ((data16 & 0x80)!=0)
+ sprintf(buffer, "%4.4x bist.b #%1.1x, @%s", opcode, (data16>>4)&7, reg_names32[(opcode>>4) & 0x7]);
+ else
+ sprintf(buffer, "%4.4x bst.b #%1.1x, @%s", opcode, (data16>>4)&7, reg_names32[(opcode>>4) & 0x7]);
+ break;
+
+ case 0x70: // bset/bnot/bclr.b #xx:3, @erd
+ case 0x71:
+ case 0x72:
+ if (((opcode & 0x8f)!=0)||((data16 & 0x8f)!=0))
+ {
+ sprintf(buffer, "%4.4x default", opcode);
+ break;
+ }
+ sprintf(buffer, "%4.4x %s.b #%1.1x, @%s", opcode, bit_instr[(data16>>8)&7], (data16>>4)&7, reg_names32[(opcode>>4) & 0x7]);
+ break;
+
+ case 0x77: // bld #xx:3, @rd
+ sprintf(buffer, "%4.4x bld #%d, @%s", opcode, (data16>>4)&7, reg_names32[(opcode>>4) & 0x7]);
+ break;
+ }
+ break;
+ // bxx.b #imm, @aa:8
+ case 0xe:
+ case 0xf:
+ data16 = h8_mem_read16(2);
+ if(((data16>>4)&0x8) == 0)
+ {
+ sprintf(buffer, "%4.4x %4.4x %s.b #%1.1x, @%x", opcode, data16, bit_instr[(data16>>8)&7], (data16>>4)&7, (0xffffff00 + (opcode & 0xff))&addr_mask);
+ }
+ else
+ {
+ sprintf(buffer, "%4.4x %4.4x %s.b #%1.1x, @%x", opcode, data16, bit_instr2[(data16>>8)&7], (data16>>4)&7, (0xffffff00 + (opcode & 0xff))&addr_mask);
+ }
+ size = 4;
+ break;
+ default:
+ sprintf(buffer, "%4.4x default", opcode);
+ break;
+ }
+ return size;
+}
+
+CPU_DISASSEMBLE(h8)
+{
+ return h8_disasm(buffer, pc, oprom, opram, 0xffff);
+}
+
+// disassembly hook for varients with 24-bit address bus (e.g. H8/3044)
+CPU_DISASSEMBLE(h8_24)
+{
+ return h8_disasm(buffer, pc, oprom, opram, 0xffffff);
+}
+
+// disassembly hook for full 32-bit address bus
+CPU_DISASSEMBLE(h8_32)
+{
+ return h8_disasm(buffer, pc, oprom, opram, 0xffffffff);
+}
+
diff --git a/trunk/src/emu/cpu/h83002/h8ops.h b/trunk/src/emu/cpu/h83002/h8ops.h
new file mode 100644
index 00000000000..d1ae0307481
--- /dev/null
+++ b/trunk/src/emu/cpu/h83002/h8ops.h
@@ -0,0 +1,4220 @@
+static UINT32 udata32, address24;
+static INT32 sdata32;
+static UINT16 udata16, ext16;
+static INT16 sdata16;
+static UINT8 udata8;
+static INT8 sdata8;
+static UINT8 srcreg, dstreg;
+
+static void h8_group0(h83xx_state *h8, UINT16 opcode);
+static void h8_group1(h83xx_state *h8, UINT16 opcode);
+static void h8_group5(h83xx_state *h8, UINT16 opcode);
+static void h8_group6(h83xx_state *h8, UINT16 opcode);
+static void h8_group7(h83xx_state *h8, UINT16 opcode);
+
+static int h8_branch(h83xx_state *h8, UINT8 condition);
+
+static UINT8 h8_mov8(h83xx_state *h8, UINT8 src);
+static UINT16 h8_mov16(h83xx_state *h8, UINT16 src);
+static UINT32 h8_mov32(h83xx_state *h8, UINT32 src);
+
+static UINT8 h8_add8(h83xx_state *h8, UINT8 src, UINT8 dst);
+static UINT16 h8_add16(h83xx_state *h8, UINT16 src, UINT16 dst);
+static UINT32 h8_add32(h83xx_state *h8, UINT32 src, UINT32 dst);
+
+static UINT8 h8_sub8(h83xx_state *h8, UINT8 src, UINT8 dst);
+static UINT16 h8_sub16(h83xx_state *h8, UINT16 src, UINT16 dst);
+static UINT32 h8_sub32(h83xx_state *h8, UINT32 src, UINT32 dst);
+
+static UINT8 h8_addx8(h83xx_state *h8, UINT8 src, UINT8 dst);
+
+static void h8_cmp8(h83xx_state *h8, UINT8 src, UINT8 dst);
+static void h8_cmp16(h83xx_state *h8, UINT16 src, UINT16 dst);
+static void h8_cmp32(h83xx_state *h8, UINT32 src, UINT32 dst);
+static UINT8 h8_subx8(h83xx_state *h8, UINT8 src, UINT8 dst);
+
+static UINT8 h8_or8(h83xx_state *h8, UINT8 src, UINT8 dst);
+static UINT16 h8_or16(h83xx_state *h8, UINT16 src, UINT16 dst);
+static UINT32 h8_or32(h83xx_state *h8, UINT32 src, UINT32 dst);
+
+static UINT8 h8_xor8(h83xx_state *h8, UINT8 src, UINT8 dst);
+static UINT16 h8_xor16(h83xx_state *h8, UINT16 src, UINT16 dst);
+static UINT32 h8_xor32(h83xx_state *h8, UINT32 src, UINT32 dst);
+
+static UINT8 h8_and8(h83xx_state *h8, UINT8 src, UINT8 dst);
+static UINT16 h8_and16(h83xx_state *h8, UINT16 src, UINT16 dst);
+static UINT32 h8_and32(h83xx_state *h8, UINT32 src, UINT32 dst);
+
+static INT8 h8_neg8(h83xx_state *h8, INT8 src);
+static INT16 h8_neg16(h83xx_state *h8, INT16 src);
+static INT32 h8_neg32(h83xx_state *h8, INT32 src);
+
+static UINT16 h8_divxu8 (h83xx_state *h8, UINT16 dst, UINT8 src);
+static UINT32 h8_divxu16(h83xx_state *h8, UINT32 dst, UINT16 src);
+
+static UINT8 h8_not8(h83xx_state *h8, UINT8 src);
+static UINT16 h8_not16(h83xx_state *h8, UINT16 src);
+static UINT32 h8_not32(h83xx_state *h8, UINT32 src);
+
+static UINT8 h8_rotl8(h83xx_state *h8, UINT8 src);
+static UINT16 h8_rotl16(h83xx_state *h8, UINT16 src);
+static UINT32 h8_rotl32(h83xx_state *h8, UINT32 src);
+
+static UINT8 h8_rotxl8(h83xx_state *h8, UINT8 src);
+static UINT16 h8_rotxl16(h83xx_state *h8, UINT16 src);
+static UINT32 h8_rotxl32(h83xx_state *h8, UINT32 src);
+
+static UINT8 h8_rotr8(h83xx_state *h8, UINT8 src);
+static UINT16 h8_rotr16(h83xx_state *h8, UINT16 src);
+static UINT32 h8_rotr32(h83xx_state *h8, UINT32 src);
+
+static UINT8 h8_rotxr8(h83xx_state *h8, UINT8 src);
+static UINT16 h8_rotxr16(h83xx_state *h8, UINT16 src);
+static UINT32 h8_rotxr32(h83xx_state *h8, UINT32 src);
+
+static UINT8 h8_shll8(h83xx_state *h8, UINT8 src);
+static UINT16 h8_shll16(h83xx_state *h8, UINT16 src);
+static UINT32 h8_shll32(h83xx_state *h8, UINT32 src);
+
+static UINT8 h8_shlr8(h83xx_state *h8, UINT8 src);
+static UINT16 h8_shlr16(h83xx_state *h8, UINT16 src);
+static UINT32 h8_shlr32(h83xx_state *h8, UINT32 src);
+
+static INT8 h8_shal8(h83xx_state *h8, INT8 src);
+static INT16 h8_shal16(h83xx_state *h8, INT16 src);
+static INT32 h8_shal32(h83xx_state *h8, INT32 src);
+
+static INT8 h8_shar8(h83xx_state *h8, INT8 src);
+static INT16 h8_shar16(h83xx_state *h8, INT16 src);
+static INT32 h8_shar32(h83xx_state *h8, INT32 src);
+
+static UINT8 h8_dec8(h83xx_state *h8, UINT8 src);
+static UINT16 h8_dec16(h83xx_state *h8, UINT16 src);
+static UINT32 h8_dec32(h83xx_state *h8, UINT32 src);
+
+static UINT8 h8_inc8(h83xx_state *h8, UINT8 src);
+static UINT16 h8_inc16(h83xx_state *h8, UINT16 src);
+static UINT32 h8_inc32(h83xx_state *h8, UINT32 src);
+
+static UINT8 h8_bnot8(h83xx_state *h8, UINT8 src, UINT8 dst);
+static UINT8 h8_bst8(h83xx_state *h8, UINT8 src, UINT8 dst);
+static UINT8 h8_bist8(h83xx_state *h8, UINT8 src, UINT8 dst);
+static UINT8 h8_bset8(h83xx_state *h8, UINT8 src, UINT8 dst);
+static UINT8 h8_bclr8(h83xx_state *h8, UINT8 src, UINT8 dst);
+static void h8_btst8(h83xx_state *h8, UINT8 src, UINT8 dst);
+static void h8_bld8(h83xx_state *h8, UINT8 src, UINT8 dst); // loads to carry
+static void h8_bild8(h83xx_state *h8, UINT8 src, UINT8 dst); // inverts and loads to carry
+static void h8_bor8(h83xx_state *h8, UINT8 src, UINT8 dst); // result in carry
+static void h8_bxor8(h83xx_state *h8, UINT8 src, UINT8 dst);
+static void h8_band8(h83xx_state *h8, UINT8 src, UINT8 dst);
+
+static INT16 h8_mulxs8(h83xx_state *h8, INT8 src, INT8 dst);
+static INT32 h8_mulxs16(h83xx_state *h8, INT16 src, INT16 dst);
+static UINT16 h8_divxs8(h83xx_state *h8, INT8 src, INT16 dst);
+static UINT32 h8_divxs16(h83xx_state *h8, INT16 src, INT32 dst);
+
+static CPU_EXECUTE(h8)
+{
+ h83xx_state *h8 = get_safe_token(device);
+ UINT16 opcode=0;
+
+ h8_check_irqs(h8);
+
+ while ((h8->cyccnt > 0) && (!h8->h8err))
+ {
+ h8->ppc = h8->pc;
+
+ debugger_instruction_hook(device, h8->pc);
+
+ opcode = h8_readop16(h8, h8->pc);
+ h8->pc += 2;
+
+ switch((opcode>>12) & 0xf)
+ {
+ case 0x0:
+ h8_group0(h8, opcode);
+ break;
+ case 0x1:
+ h8_group1(h8, opcode);
+ break;
+ case 0x2:
+ // mov.b @xx:8, Rd (abs)
+ dstreg = (opcode>>8) & 0xf;
+ udata8 = h8_mem_read8(0xffff00+(opcode & 0xff));
+ h8_mov8(h8, udata8); // flags calculation, dont care about others
+ h8_setreg8(h8, dstreg, udata8);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0x3: // pass
+ // mov.b Rs, @xx:8 (abs)
+ srcreg = (opcode>>8) & 0xf;
+ udata8 = h8_getreg8(h8, srcreg);
+ h8_mov8(h8, udata8); // flags calculation, dont care about others
+ h8_mem_write8(0xffff00+(opcode & 0xff), udata8);
+ H8_IFETCH_TIMING(1);
+ H8_BYTE_TIMING(1, 0xffff00+(opcode & 0xff));
+ break;
+ case 0x4:
+ // bcc @xx:8
+ sdata8 = (opcode & 0xff);
+ if( h8_branch(h8, (opcode >> 8) & 0xf) == 1) h8->pc += sdata8;
+ break;
+ case 0x5:
+ h8_group5(h8, opcode);
+ break;
+ case 0x6:
+ h8_group6(h8, opcode);
+ break;
+ case 0x7:
+ h8_group7(h8, opcode);
+ break;
+ case 0x8:
+ // add.b #xx:8, Rd
+ dstreg = (opcode>>8) & 0xf;
+ udata8 = h8_add8(h8, opcode & 0xff, h8_getreg8(h8, dstreg));
+ h8_setreg8(h8, dstreg, udata8);
+ H8_IFETCH_TIMING(1)
+ break;
+ case 0x9:
+ // addx.b #xx:8, Rd
+ dstreg = (opcode>>8) & 0xf;
+ udata8 = h8_addx8(h8, opcode & 0xff, h8_getreg8(h8, dstreg));
+ h8_setreg8(h8, dstreg, udata8);
+ H8_IFETCH_TIMING(1)
+ break;
+ case 0xa:
+ // cmp.b #xx:8, Rd
+ dstreg = (opcode>>8) & 0xf;
+ h8_cmp8(h8, opcode & 0xff, h8_getreg8(h8, dstreg));
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0xb:
+ // subx.b #xx:8, Rd
+ dstreg = (opcode>>8) & 0xf;
+ udata8 = h8_subx8(h8, opcode & 0xff, h8_getreg8(h8, dstreg));
+ h8_setreg8(h8, dstreg, udata8);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0xc:
+ // or.b #xx:8, Rd
+ dstreg = (opcode>>8) & 0xf;
+ udata8 = h8_or8(h8, opcode & 0xff, h8_getreg8(h8, dstreg));
+ h8_setreg8(h8, dstreg, udata8);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0xd:
+ // xor.b #xx:8, Rd
+ dstreg = (opcode>>8) & 0xf;
+ udata8 = h8_xor8(h8, opcode & 0xff, h8_getreg8(h8, dstreg));
+ h8_setreg8(h8, dstreg, udata8);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0xe: // pass
+ // and.b #xx:8, Rd
+ dstreg = (opcode>>8) & 0xf;
+ udata8 = h8_and8(h8, opcode & 0xff, h8_getreg8(h8, dstreg));
+ h8_setreg8(h8, dstreg, udata8);
+ H8_IFETCH_TIMING(1)
+ break;
+ case 0xf: // pass
+ // mov.b #xx:8, Rd
+ dstreg = (opcode>>8) & 0xf;
+ udata8 = h8_mov8(h8, opcode & 0xff);
+ h8_setreg8(h8, dstreg, udata8);
+ H8_IFETCH_TIMING(1);
+ break;
+ }
+ }
+
+ if (h8->h8err)
+ {
+ fatalerror("H8/3xx: Unknown opcode (PC=%x) %x", h8->ppc, opcode);
+ }
+}
+
+static void h8_group0(h83xx_state *h8, UINT16 opcode)
+{
+ switch((opcode>>8)&0xf)
+ {
+ case 0:
+ // nop
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0x1:
+ // 0140 = LDC/STC.W
+ if (opcode == 0x0140)
+ {
+ ext16 = h8_mem_read16(h8, h8->pc);
+ h8->pc+=2;
+ switch((ext16>>8) & 0xff)
+ {
+ case 0x69:
+ // ERd
+ if (ext16 & 0x80)
+ {
+ h8_setreg8(h8, (ext16>>4)&7, h8_get_ccr(h8));
+ }
+ else
+ {
+ udata8 = h8_getreg8(h8, (ext16>>4)&7);
+ h8_set_ccr(h8, udata8);
+ }
+ H8_IFETCH_TIMING(1);
+ break;
+
+ case 0x6f:
+ // @(disp, ERd)
+ sdata16=h8_mem_read16(h8, h8->pc); // sign extend displacements !
+ h8->pc += 2;
+ address24 = (h8_getreg32(h8, (ext16 >> 4)&7)) & H8_ADDR_MASK;
+ address24 += sdata16;
+ H8_IFETCH_TIMING(3);
+ H8_WORD_TIMING(2, address24);
+ if (ext16 & 0x80)
+ {
+ h8_mem_write8(address24, h8_get_ccr(h8));
+ }
+ else
+ {
+ udata8 = h8_mem_read8(address24);
+ h8_set_ccr(h8, udata8);
+ }
+ H8_BYTE_TIMING(1, sdata16);
+ break;
+
+ case 0x78:
+ // @(disp24, ERd)
+ srcreg = (ext16 >> 4) & 7;
+
+ // 6b20
+ udata16 = h8_mem_read16(h8, h8->pc);
+ h8->pc += 2;
+ dstreg = udata16 & 7;
+
+ address24 = h8_mem_read32(h8, h8->pc);
+ h8->pc += 4;
+ address24 += h8_getreg32(h8, srcreg);
+ address24 &= H8_ADDR_MASK;
+ if (udata16 == 0x6b20)
+ {
+ udata8 = h8_mem_read8(address24);
+ h8_set_ccr(h8, udata8);
+ }
+ else if (udata16 == 0x6ba0)
+ {
+ h8_mem_write8(address24, h8_get_ccr(h8));
+ }
+ else
+ {
+ h8->h8err = 1;
+ }
+ H8_IFETCH_TIMING(5);
+ H8_WORD_TIMING(2, address24);
+ break;
+
+ case 0x6d:
+ // stc.w ccr,-@ERd / ldc @ERd+, ccr
+ srcreg = (ext16>>4)&7;
+ if (ext16 & 0x80)
+ {
+ h8_setreg32(h8, srcreg, h8_getreg32(h8, srcreg)-2);
+ address24 = h8_getreg32(h8, srcreg) & H8_ADDR_MASK;
+ h8_mem_write8(address24, h8_get_ccr(h8));
+ }
+ else
+ {
+ address24 = h8_getreg32(h8, srcreg) & H8_ADDR_MASK;
+ h8_setreg32(h8, srcreg, h8_getreg32(h8, srcreg)+2);
+ udata8 = h8_mem_read8(address24);
+ h8_set_ccr(h8, udata8);
+ }
+ H8_IFETCH_TIMING(2);
+ H8_BYTE_TIMING(1, address24);
+ H8_IOP_TIMING(2);
+ break;
+
+ case 0x6b:
+ if ((ext16&0xff) == 0x00) // 16 bit absolute
+ {
+ address24=h8_mem_read16(h8, h8->pc);
+ h8->pc += 2;
+ if (address24 & 0x8000)
+ address24 |= 0xff0000;
+ udata8 = h8_mem_read8(address24);
+ h8_set_ccr(h8, udata8);
+ H8_IFETCH_TIMING(4);
+ H8_BYTE_TIMING(1, address24);
+ }
+ else if ((ext16&0xff) == 0x20) // 24 bit absolute
+ {
+ address24=h8_mem_read32(h8, h8->pc);
+ h8->pc += 4;
+ udata8 = h8_mem_read8(address24);
+ h8_set_ccr(h8, udata8);
+ H8_IFETCH_TIMING(4);
+ H8_BYTE_TIMING(1, address24);
+ }
+ else if ((ext16&0xff) == 0x80) // 16 bit absolute
+ {
+ address24=h8_mem_read16(h8, h8->pc);
+ h8->pc += 2;
+ if (address24 & 0x8000)
+ address24 |= 0xff0000;
+ h8_mem_write8(address24, h8_get_ccr(h8));
+ H8_IFETCH_TIMING(3);
+ H8_BYTE_TIMING(1, address24);
+ }
+ else if ((ext16&0xff) == 0xa0) // 24 bit absolute
+ {
+ address24=h8_mem_read32(h8, h8->pc);
+ h8->pc += 4;
+ h8_mem_write8(address24, h8_get_ccr(h8));
+ H8_IFETCH_TIMING(4);
+ H8_BYTE_TIMING(1, address24);
+ }
+ else
+ {
+ h8->h8err = 1;
+ }
+ break;
+ }
+ break;
+ }
+
+ // 01yx where x should always be 0!
+ if((opcode & 0xf) != 0)
+ {
+ h8->h8err = 1;
+ break;
+ }
+ switch((opcode>>4) & 0xf)
+ {
+ // 0100 mov.l prefix
+ case 0xf: // and.l Rn, Rn
+ ext16 = h8_mem_read16(h8, h8->pc);
+ h8->pc += 2;
+ if (ext16 & 0x88)
+ {
+ h8->h8err = 1;
+ }
+ else
+ {
+ dstreg = ext16 & 0x7;
+ switch((ext16>>8)&0xff)
+ {
+ case 0x64: // or.l ERs, ERd
+ udata32 = h8_or32(h8, h8_getreg32(h8, (ext16>>4) & 0x7), h8_getreg32(h8, dstreg));
+ break;
+ case 0x65: // xor.l ERs, ERd
+ udata32 = h8_xor32(h8, h8_getreg32(h8, (ext16>>4) & 0x7), h8_getreg32(h8, dstreg));
+ break;
+ case 0x66: // and.l ERs, ERd
+ udata32 = h8_and32(h8, h8_getreg32(h8, (ext16>>4) & 0x7), h8_getreg32(h8, dstreg));
+ break;
+ default:
+ h8->h8err = 1;
+ return;
+ }
+ h8_setreg32(h8, dstreg, udata32);
+ H8_IFETCH_TIMING(2);
+ }
+ break;
+
+ case 0:
+ ext16 = h8_mem_read16(h8, h8->pc);
+ h8->pc+=2;
+ switch((ext16 >> 8) & 0xff)
+ {
+ case 0x69:
+ if((ext16 & 0x80) == 0x80)
+ {
+ // mov.l rx, @rx
+ udata32 = h8_mov32(h8, h8_getreg32(h8, ext16 & 7));
+ h8_mem_write32(h8, h8_getreg32(h8, (ext16 >> 4) & 7), udata32);
+ H8_IFETCH_TIMING(2);
+ H8_WORD_TIMING(2, h8_getreg32(h8, (ext16 >> 4) & 7));
+ }
+ else
+ {
+ // mov.l @rx, rx
+ udata32 = h8_mem_read32(h8, h8_getreg32(h8, (ext16 >> 4) &7));
+ h8_mov32(h8, udata32);
+ h8_setreg32(h8, ext16 & 7, udata32);
+ H8_IFETCH_TIMING(2);
+ H8_WORD_TIMING(2, h8_getreg32(h8, (ext16 >> 4) &7));
+ }
+ break;
+ case 0x6b:
+ // mov.l rx, @xx / mov.l @xx, rx
+
+ switch((ext16 >> 4)&0xf)
+ {
+ case 0x0:
+ // mov.l @aa:16, ERx
+ address24=h8_mem_read16(h8, h8->pc);
+ h8->pc += 2;
+ if (address24 & 0x8000)
+ address24 |= 0xff0000;
+ udata32=h8_mem_read32(h8, address24);
+ h8_mov32(h8, udata32); // flags only
+ h8_setreg32(h8, ext16 & 0x7, udata32);
+ H8_IFETCH_TIMING(4);
+ H8_WORD_TIMING(2, address24);
+ break;
+ case 0x2:
+ // mov.l @aa:24, ERx
+ address24=h8_mem_read32(h8, h8->pc);
+ h8->pc += 4;
+ udata32=h8_mem_read32(h8, address24);
+ h8_mov32(h8, udata32); // flags only
+ h8_setreg32(h8, ext16 & 0x7, udata32);
+ H8_IFETCH_TIMING(4);
+ H8_WORD_TIMING(2, address24);
+ break;
+ case 0xa:
+ // mov.l ERx, @aa:24
+ address24=h8_mem_read32(h8, h8->pc);
+ h8->pc += 4;
+ udata32=h8_getreg32(h8, ext16 & 0x7);
+ h8_mov32(h8, udata32); // flags only
+ h8_mem_write32(h8, address24, udata32);
+ H8_IFETCH_TIMING(4);
+ H8_WORD_TIMING(2, address24);
+ break;
+ case 0x8:
+ // mov.l ERx, @aa:16
+ address24=h8_mem_read16(h8, h8->pc);
+ h8->pc += 2;
+ if (address24 & 0x8000)
+ address24 |= 0xff0000;
+ udata32=h8_getreg32(h8, ext16 & 0x7);
+ h8_mov32(h8, udata32); // flags only
+ h8_mem_write32(h8, address24, udata32);
+ H8_IFETCH_TIMING(3);
+ H8_WORD_TIMING(2, address24);
+ break;
+ default:
+ h8->h8err = 1;
+ break;
+ }
+ break;
+ case 0x6d:
+ if(ext16 & 0x80)
+ {
+ // mov.l rs, @-erd
+ srcreg = (ext16>>4)&7;
+ h8_setreg32(h8, srcreg, h8_getreg32(h8, srcreg)-4);
+ address24 = h8_getreg32(h8, srcreg) & H8_ADDR_MASK;
+ udata32 = h8_getreg32(h8, ext16 & 0x7);
+ h8_mem_write32(h8, address24, udata32);
+ H8_IFETCH_TIMING(2);
+ H8_WORD_TIMING(2, address24);
+ H8_IOP_TIMING(2);
+ }
+ else
+ {
+ // mov.l @ers+, rd
+ srcreg = (ext16 >>4)&7;
+ address24 = h8_getreg32(h8, srcreg) & H8_ADDR_MASK;
+ h8_setreg32(h8, srcreg, h8_getreg32(h8, srcreg)+4);
+ udata32 = h8_mem_read32(h8, address24);
+ h8_setreg32(h8, ext16 & 0x7, udata32);
+ H8_IFETCH_TIMING(2);
+ H8_WORD_TIMING(2, address24);
+ H8_IOP_TIMING(2);
+ }
+ h8_mov32(h8, udata32);
+ break;
+ case 0x6f:
+ // mov.l @(displ16 + Rs), rd
+ sdata16=h8_mem_read16(h8, h8->pc); // sign extend displacements !
+ h8->pc += 2;
+ address24 = (h8_getreg32(h8, (ext16 >> 4)&7)) & H8_ADDR_MASK;
+ address24 += sdata16;
+ H8_IFETCH_TIMING(3);
+ H8_WORD_TIMING(2, address24);
+ if(ext16 & 0x80)
+ {
+ udata32 = h8_getreg32(h8, ext16 & 0x7);
+ h8_mem_write32(h8, address24, udata32);
+ }
+ else
+ {
+ udata32 = h8_mem_read32(h8, address24);
+ h8_setreg32(h8, ext16 & 0x7, udata32);
+ }
+ h8_mov32(h8, udata32);
+ break;
+ case 0x78:
+ // prefix for
+ // mov.l (@aa:x, rx), Rx
+ //00000A10 010078606B2600201AC2 MOV.L @($00201AC2,ER6),ER6
+ // mov.l @(displ24 + Rs), rd
+ srcreg = (ext16 >> 4) & 7;
+
+ // 6b20
+ udata16 = h8_mem_read16(h8, h8->pc);
+ h8->pc += 2;
+ dstreg = udata16 & 7;
+
+ address24 = h8_mem_read32(h8, h8->pc);
+ h8->pc += 4;
+ address24 += h8_getreg32(h8, srcreg);
+ address24 &= H8_ADDR_MASK;
+
+ if ( (ext16 & 0x80) && ((udata16 & ~7) == 0x6ba0) )
+ {
+ udata32 = h8_getreg32(h8, dstreg);
+ h8_mem_write32(h8, address24, udata32);
+ }
+ else if ( (!(ext16 & 0x80)) && ((udata16 & ~7) == 0x6b20) )
+ {
+ udata32 = h8_mem_read32(h8, address24);
+ h8_setreg32(h8, dstreg, udata32);
+ }
+ else
+ {
+ h8->h8err = 1;
+ }
+
+ h8_mov32(h8, udata32);
+
+ H8_IFETCH_TIMING(5);
+ H8_WORD_TIMING(2, address24);
+
+ break;
+ default:
+ h8->h8err = 1;
+ break;
+ }
+ break;
+ // ldm/stm
+ case 0x1:
+ case 0x2:
+ case 0x3:
+ ext16 = h8_mem_read16(h8, h8->pc);
+ h8->pc+=2;
+
+ // # of registers to save
+ sdata8 = ((opcode>>4) & 0xf);
+
+ // check LDM or STM
+ if (ext16 & 0x80) // STM
+ {
+ srcreg = (ext16 & 7);
+ for (int i = 0; i <= sdata8; i++)
+ {
+ h8_setreg32(h8, 7, h8_getreg32(h8, 7)-4);
+ address24 = h8_getreg32(h8, 7) & H8_ADDR_MASK;
+ udata32 = h8_getreg32(h8, srcreg+i);
+ h8_mem_write32(h8, address24, udata32);
+ H8_IFETCH_TIMING(2);
+ H8_WORD_TIMING(2, address24);
+ H8_IOP_TIMING(2);
+ }
+ }
+ else // LDM
+ {
+ srcreg = (ext16 & 7);
+ for (int i = 0; i <= sdata8; i++)
+ {
+ address24 = h8_getreg32(h8, 7) & H8_ADDR_MASK;
+ h8_setreg32(h8, 7, h8_getreg32(h8, 7)+4);
+ udata32 = h8_mem_read32(h8, address24);
+ h8_setreg32(h8, srcreg-i, udata32);
+ H8_IFETCH_TIMING(2);
+ H8_WORD_TIMING(2, address24);
+ H8_IOP_TIMING(2);
+ }
+ }
+ break;
+ case 0x8: // sleep
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0xc:
+ // mulxs
+ ext16 = h8_mem_read16(h8, h8->pc);
+ h8->pc+=2;
+ if(((ext16>>8) & 0xf) == 0) // .b (8x8 = 16)
+ {
+ sdata16 = h8_getreg8(h8, ext16 & 0xf); // Rd
+ sdata8 = h8_getreg8(h8, (ext16>>4) & 0xf); // Rs
+ sdata16 = h8_mulxs8(h8, sdata8, sdata16);
+ h8_setreg16(h8, ext16 & 0xf, sdata16);
+ H8_IFETCH_TIMING(2);
+ H8_IOP_TIMING(12);
+ }
+ else if(((ext16>>8) & 0xf) == 2) // .w
+ {
+ sdata32 = h8_getreg32(h8, ext16 & 0x7);
+ sdata16 = h8_getreg16(h8, (ext16>>4) & 0xf);
+ sdata32 = h8_mulxs16(h8, sdata16, sdata32);
+ h8_setreg32(h8, ext16 & 0x7, sdata32);
+ H8_IFETCH_TIMING(2);
+ H8_IOP_TIMING(20);
+ }
+ else
+ {
+ logerror("H8/3xx: Unk. group 0 mulxs %x\n", opcode);
+ h8->h8err = 1;
+ }
+ break;
+
+ case 0xd:
+ //divxs - probably buggy (flags?)
+ ext16 = h8_mem_read16(h8, h8->pc);
+ h8->pc+=2;
+ if(((ext16>>8) & 0xf) == 0)
+ {
+ sdata16 = h8_getreg16(h8, ext16 & 0xf);
+ sdata8 = h8_getreg8(h8, (ext16>>4) & 0xf);
+ sdata16 = h8_divxs8(h8, sdata8, sdata16);
+ h8_setreg16(h8, ext16 & 0xf, sdata16);
+ H8_IFETCH_TIMING(2);
+ H8_IOP_TIMING(12);
+ }
+ else if(((ext16>>8) & 0xf) == 3)
+ {
+ sdata32 = h8_getreg32(h8, ext16 & 0x7);
+ sdata16 = h8_getreg16(h8, (ext16>>4) & 0xf);
+ sdata32 = h8_divxs16(h8, sdata16, sdata32);
+ h8_setreg32(h8, ext16 & 0x7, sdata32);
+ H8_IFETCH_TIMING(2);
+ H8_IOP_TIMING(20);
+ }
+ else
+ {
+ h8->h8err = 1;
+ }
+
+
+ break;
+
+ default:
+ h8->h8err = 1;
+ break;
+ }
+ break;
+ case 0x2:
+ // stc ccr, rd
+ if(((opcode>>4) & 0xf) == 0)
+ {
+ h8_setreg8(h8, opcode & 0xf, h8_get_ccr(h8));
+ H8_IFETCH_TIMING(1);
+ }
+ else
+ {
+ logerror("H8/3xx: Unk. group 0 2 %x\n", opcode);
+ h8->h8err = 1;
+ }
+ break;
+ case 0x3:
+ // ldc rd, ccr
+ if(((opcode>>4) & 0xf) == 0)
+ {
+ udata8 = h8_getreg8(h8, opcode & 0xf);
+ h8_set_ccr(h8, udata8);
+ H8_IFETCH_TIMING(1);
+ }
+ else
+ {
+ logerror("H8/3xx: Unk. group 0 3 %x\n", opcode);
+ h8->h8err = 1;
+ }
+ break;
+ case 0x4: // pass
+ // orc
+ udata8 = h8_or8(h8, opcode & 0xff, h8_get_ccr(h8));
+ h8_set_ccr(h8, udata8);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0x6:
+ // andc
+ udata8 = h8_and8(h8, opcode & 0xff, h8_get_ccr(h8));
+ h8_set_ccr(h8, udata8);
+ H8_IFETCH_TIMING(1)
+ break;
+ case 0x7:
+ // ldc
+ h8_set_ccr(h8, opcode & 0xff);
+ H8_IFETCH_TIMING(1)
+ break;
+ case 0x8:
+ // add.b rx, ry
+ dstreg = opcode & 0xf;
+ udata8 = h8_add8(h8, h8_getreg8(h8, (opcode>>4) &0xf), h8_getreg8(h8, dstreg));
+ h8_setreg8(h8, dstreg, udata8);
+ H8_IFETCH_TIMING(1)
+ break;
+ // add.w rx, ry
+ case 0x9:
+ dstreg = opcode & 0xf;
+ udata16 = h8_add16(h8, h8_getreg16(h8, (opcode>>4) &0xf), h8_getreg16(h8, dstreg));
+ h8_setreg16(h8, dstreg, udata16);
+ H8_IFETCH_TIMING(1)
+ break;
+ // inc.b rx
+ case 0xA:
+ if(opcode&0x80)
+ {
+ if(opcode & 0x8)
+ {
+ logerror("H8/3xx: Unk. group 0 a %x\n", opcode);
+ h8->h8err = 1;
+ }
+ else
+ {
+ dstreg = opcode & 0x7;
+ udata32 = h8_add32(h8, h8_getreg32(h8, (opcode>>4) &0x7), h8_getreg32(h8, dstreg));
+ h8_setreg32(h8, dstreg, udata32);
+ H8_IFETCH_TIMING(1)
+ }
+ }
+ else
+ {
+ if(opcode & 0xf0)
+ {
+ logerror("H8/3xx: Unk. group 0 a2 %x\n", opcode);
+ h8->h8err =1;
+ }
+ else
+ {
+ dstreg = opcode & 0xf;
+ udata8 = h8_inc8(h8, h8_getreg8(h8, dstreg));
+ h8_setreg8(h8, dstreg, udata8);
+ H8_IFETCH_TIMING(1);
+ }
+ }
+ break;
+ case 0xb:
+ switch((opcode>>4)& 0xf)
+ {
+ case 0:
+ if(opcode & 8)
+ {
+ h8->h8err = 1;
+ }
+ else
+ {
+ dstreg = opcode & 7;
+ udata32 = h8_getreg32(h8, dstreg) + 1;
+ h8_setreg32(h8, dstreg, udata32);
+ H8_IFETCH_TIMING(1)
+ }
+ break;
+ case 5:
+ dstreg = opcode & 0xf;
+ udata16 = h8_inc16(h8, h8_getreg16(h8, dstreg));
+ h8_setreg16(h8, dstreg, udata16);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 7:
+ dstreg = opcode & 0x7;
+ udata32 = h8_inc32(h8, h8_getreg32(h8, dstreg));
+ h8_setreg32(h8, dstreg, udata32);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 8:
+ if(opcode & 8)
+ {
+ h8->h8err = 1;
+ }
+ else
+ {
+ dstreg = opcode & 7;
+ udata32 = h8_getreg32(h8, dstreg) + 2;
+ h8_setreg32(h8, dstreg, udata32);
+ H8_IFETCH_TIMING(1)
+ }
+ break;
+ case 9:
+ if(opcode & 8)
+ {
+ h8->h8err = 1;
+ }
+ else
+ {
+ dstreg = opcode & 7;
+ udata32 = h8_getreg32(h8, dstreg) + 4;
+ h8_setreg32(h8, dstreg, udata32);
+ H8_IFETCH_TIMING(1)
+ }
+ break;
+ case 0xd:
+ dstreg = opcode & 0xf;
+ udata16 = h8_inc16(h8, h8_getreg16(h8, dstreg));
+ if(h8->h8vflag)
+ {
+ udata16 = h8_inc16(h8, udata16); // slow and easy
+ h8->h8vflag = 1;
+ }
+ else
+ udata16 = h8_inc16(h8, udata16); // slow and easy
+ h8_setreg16(h8, dstreg, udata16);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0xf:
+ dstreg = opcode & 0x7;
+ udata32 = h8_inc32(h8, h8_getreg32(h8, dstreg));
+ if(h8->h8vflag)
+ {
+ udata32 = h8_inc32(h8, udata32); // slow and easy
+ h8->h8vflag = 1;
+ }
+ else
+ udata32 = h8_inc32(h8, udata32); // slow and easy
+ h8_setreg32(h8, dstreg, udata32);
+ H8_IFETCH_TIMING(1);
+ break;
+ default:
+ logerror("H8/3xx: Unk. group 0 b %x\n", opcode);
+ h8->h8err = 1;
+ break;
+ }
+ break;
+ // mov.b rx, ry
+ case 0xc: // pass
+ dstreg = opcode & 0xf;
+ udata8 = h8_mov8(h8, h8_getreg8(h8, (opcode>>4) &0xf));
+ h8_setreg8(h8, dstreg, udata8);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0xd:
+ // mov.w rx, ry
+ dstreg = opcode & 0xf;
+ udata16 = h8_mov16(h8, h8_getreg16(h8, (opcode>>4) &0xf));
+ h8_setreg16(h8, dstreg, udata16);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0xf:
+ if(opcode & 0x80)
+ {
+ if(opcode & 8)
+ {
+ logerror("H8/3xx: Unk. group 0 f %x\n", opcode);
+ h8->h8err = 1;
+ }
+ else
+ {
+ dstreg = opcode & 0x7;
+ udata32 = h8_mov32(h8, h8_getreg32(h8, (opcode>>4) &0x7));
+ h8_setreg32(h8, dstreg, udata32);
+ H8_IFETCH_TIMING(1);
+ }
+ }
+ else
+ {
+ h8->h8err = 1;
+ logerror("H8/3xx: Unk. group 0 f2 %x\n", opcode);
+ if((opcode & 0xf0) !=0)
+ {
+ h8->h8err = 1;
+ }
+ else
+ {
+ h8->h8err = 1;
+ }
+ }
+ break;
+ default:
+ logerror("H8/3xx: Unk. group 0 tdef %x\n", opcode);
+ h8->h8err = 1;
+ break;
+ }
+}
+
+static void h8_group1(h83xx_state *h8, UINT16 opcode)
+{
+ switch((opcode>>8)&0xf)
+ {
+ case 0x0:
+ switch((opcode>>4)&0xf)
+ {
+ case 0x0:
+ // shll.b Rx
+ udata8 = h8_getreg8(h8, opcode & 0xf);
+ udata8 = h8_shll8(h8, udata8);
+ h8_setreg8(h8, opcode & 0xf, udata8);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0x1:
+ // shll.w Rx
+ udata16 = h8_getreg16(h8, opcode & 0xf);
+ udata16 = h8_shll16(h8, udata16);
+ h8_setreg16(h8, opcode & 0xf, udata16);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0x3:
+ // shll.l Rx
+ udata32 = h8_getreg32(h8, opcode & 0x7);
+ udata32 = h8_shll32(h8, udata32);
+ h8_setreg32(h8, opcode & 0x7, udata32);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0x4:
+ // shll.b #2, Rx
+ udata8 = h8_getreg8(h8, opcode & 0xf);
+ udata8 = h8_shll8(h8, udata8);
+ udata8 = h8_shll8(h8, udata8);
+ h8_setreg8(h8, opcode & 0xf, udata8);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0x5:
+ // shll.w #2, Rx
+ udata16 = h8_getreg16(h8, opcode & 0xf);
+ udata16 = h8_shll16(h8, udata16);
+ udata16 = h8_shll16(h8, udata16);
+ h8_setreg16(h8, opcode & 0xf, udata16);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0x7:
+ // shll.l #2, Rx
+ udata32 = h8_getreg32(h8, opcode & 0x7);
+ udata32 = h8_shll32(h8, udata32);
+ udata32 = h8_shll32(h8, udata32);
+ h8_setreg32(h8, opcode & 0x7, udata32);
+ H8_IFETCH_TIMING(1);
+ break;
+
+ case 0x8:
+ // shal.b Rx
+ udata8 = h8_getreg8(h8, opcode & 0xf);
+ udata8 = h8_shal8(h8, udata8);
+ h8_setreg8(h8, opcode & 0xf, udata8);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0x9:
+ // shal.w Rx
+ udata16 = h8_getreg16(h8, opcode & 0xf);
+ udata16 = h8_shal16(h8, udata16);
+ h8_setreg16(h8, opcode & 0xf, udata16);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0xb:
+ // shal.l ERx
+ udata32 = h8_getreg32(h8, opcode & 0x7);
+ udata32 = h8_shal32(h8, udata32);
+ h8_setreg32(h8, opcode & 0x7, udata32);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0xc:
+ // shal.b #2, Rx
+ udata8 = h8_getreg8(h8, opcode & 0xf);
+ udata8 = h8_shal8(h8, udata8);
+ udata8 = h8_shal8(h8, udata8);
+ h8_setreg8(h8, opcode & 0xf, udata8);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0xd:
+ // shal.w #2, Rx
+ udata16 = h8_getreg16(h8, opcode & 0xf);
+ udata16 = h8_shal16(h8, udata16);
+ udata16 = h8_shal16(h8, udata16);
+ h8_setreg16(h8, opcode & 0xf, udata16);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0xf:
+ // shal.l #2, ERx
+ udata32 = h8_getreg32(h8, opcode & 0x7);
+ udata32 = h8_shal32(h8, udata32);
+ udata32 = h8_shal32(h8, udata32);
+ h8_setreg32(h8, opcode & 0x7, udata32);
+ H8_IFETCH_TIMING(1);
+ break;
+ default:
+ logerror("H8/3xx: Unk. group 1 0 %x\n", opcode);
+ h8->h8err = 1;
+ break;
+ }
+ break;
+ case 0x1:
+ switch((opcode>>4)&0xf)
+ {
+ case 0x0:
+ // shlr.b rx
+ udata8 = h8_getreg8(h8, opcode & 0xf);
+ udata8 = h8_shlr8(h8, udata8);
+ h8_setreg8(h8, opcode & 0xf, udata8);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0x1:
+ // shlr.w rx
+ udata16 = h8_getreg16(h8, opcode & 0xf);
+ udata16 = h8_shlr16(h8, udata16);
+ h8_setreg16(h8, opcode & 0xf, udata16);
+ H8_IFETCH_TIMING(1);
+ break;
+ // shlr.l rx
+ case 0x3:
+ udata32 = h8_getreg32(h8, opcode & 0x7);
+ udata32 = h8_shlr32(h8, udata32);
+ h8_setreg32(h8, opcode & 0x7, udata32);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0x4:
+ // shlr.b #2, rx
+ udata8 = h8_getreg8(h8, opcode & 0xf);
+ udata8 = h8_shlr8(h8, udata8);
+ udata8 = h8_shlr8(h8, udata8);
+ h8_setreg8(h8, opcode & 0xf, udata8);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0x5:
+ // shlr.w #2, rx
+ udata16 = h8_getreg16(h8, opcode & 0xf);
+ udata16 = h8_shlr16(h8, udata16);
+ udata16 = h8_shlr16(h8, udata16);
+ h8_setreg16(h8, opcode & 0xf, udata16);
+ H8_IFETCH_TIMING(1);
+ break;
+ // shlr.l #2, rx
+ case 0x7:
+ udata32 = h8_getreg32(h8, opcode & 0x7);
+ udata32 = h8_shlr32(h8, udata32);
+ udata32 = h8_shlr32(h8, udata32);
+ h8_setreg32(h8, opcode & 0x7, udata32);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0x8:
+ // shar.b rx
+ udata8 = h8_getreg8(h8, opcode & 0xf);
+ udata8 = h8_shar8(h8, udata8);
+ h8_setreg8(h8, opcode & 0xf, udata8);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0x9:
+ // shar.w rx
+ udata16 = h8_getreg16(h8, opcode & 0xf);
+ udata16 = h8_shar16(h8, udata16);
+ h8_setreg16(h8, opcode & 0xf, udata16);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0xb:
+ // shar.l rx
+ udata32 = h8_getreg32(h8, opcode & 0x7);
+ udata32 = h8_shar32(h8, udata32);
+ h8_setreg32(h8, opcode & 0x7, udata32);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0xc:
+ // shar.b #2, rx
+ udata8 = h8_getreg8(h8, opcode & 0xf);
+ udata8 = h8_shar8(h8, udata8);
+ udata8 = h8_shar8(h8, udata8);
+ h8_setreg8(h8, opcode & 0xf, udata8);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0xd:
+ // shar.w #2, rx
+ udata16 = h8_getreg16(h8, opcode & 0xf);
+ udata16 = h8_shar16(h8, udata16);
+ udata16 = h8_shar16(h8, udata16);
+ h8_setreg16(h8, opcode & 0xf, udata16);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0xf:
+ // shar.l #2, rx
+ udata32 = h8_getreg32(h8, opcode & 0x7);
+ udata32 = h8_shar32(h8, udata32);
+ udata32 = h8_shar32(h8, udata32);
+ h8_setreg32(h8, opcode & 0x7, udata32);
+ H8_IFETCH_TIMING(1);
+ break;
+ default:
+ logerror("H8/3xx: Unk. group 1 1 %x\n", opcode);
+ h8->h8err = 1;
+ break;
+ }
+ break;
+ case 0x2:
+ switch((opcode>>4)&0xf)
+ {
+ case 0x0:
+ // rotxl.b Rx
+ udata8 = h8_getreg8(h8, opcode & 0xf);
+ udata8 = h8_rotxl8(h8, udata8);
+ h8_setreg8(h8, opcode & 0xf, udata8);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0x1:
+ // rotxl.w Rx
+ udata16 = h8_getreg16(h8, opcode & 0xf);
+ udata16 = h8_rotxl16(h8, udata16);
+ h8_setreg16(h8, opcode & 0xf, udata16);
+ H8_IFETCH_TIMING(1);
+ break;
+
+ case 0x3:
+ // rotxl.l Rx
+ udata32 = h8_getreg32(h8, opcode & 0x7);
+ udata32 = h8_rotxl32(h8, udata32);
+ h8_setreg32(h8, opcode & 0xf, udata32);
+ H8_IFETCH_TIMING(1);
+ break;
+
+ case 0x8:
+ // rotl.b Rx
+ udata8 = h8_getreg8(h8, opcode & 0xf);
+ udata8 = h8_rotl8(h8, udata8);
+ h8_setreg8(h8, opcode & 0xf, udata8);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0x9:
+ // rotl.w Rx
+ udata16 = h8_getreg16(h8, opcode & 0xf);
+ udata16 = h8_rotl16(h8, udata16);
+ h8_setreg16(h8, opcode & 0xf, udata16);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0xb:
+ // rotl.l ERx
+ udata32 = h8_getreg32(h8, opcode & 0x7);
+ udata32 = h8_rotl32(h8, udata32);
+ h8_setreg32(h8, opcode & 0x7, udata32);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0xc:
+ // rotl.b #2, Rx
+ udata8 = h8_getreg8(h8, opcode & 0xf);
+ udata8 = h8_rotl8(h8, udata8);
+ udata8 = h8_rotl8(h8, udata8);
+ h8_setreg8(h8, opcode & 0xf, udata8);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0xd:
+ // rotl.w #2, Rx
+ udata16 = h8_getreg16(h8, opcode & 0xf);
+ udata16 = h8_rotl16(h8, udata16);
+ udata16 = h8_rotl16(h8, udata16);
+ h8_setreg16(h8, opcode & 0xf, udata16);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0xf:
+ // rotl.l #2, ERx
+ udata32 = h8_getreg32(h8, opcode & 0x7);
+ udata32 = h8_rotl32(h8, udata32);
+ udata32 = h8_rotl32(h8, udata32);
+ h8_setreg32(h8, opcode & 0x7, udata32);
+ H8_IFETCH_TIMING(1);
+ break;
+
+ default:
+ logerror("H8/3xx: Unk. group 1 2 %x\n", opcode);
+ h8->h8err = 1;
+ break;
+ }
+ break;
+ case 0x3:
+ switch((opcode>>4)&0xf)
+ {
+ case 0x0:
+ // rotxr.b Rx
+ udata8 = h8_getreg8(h8, opcode & 0xf);
+ udata8 = h8_rotxr8(h8, udata8);
+ h8_setreg8(h8, opcode & 0xf, udata8);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0x1:
+ // rotxr.w Rx
+ udata16 = h8_getreg16(h8, opcode & 0xf);
+ udata16 = h8_rotxr16(h8, udata16);
+ h8_setreg16(h8, opcode & 0xf, udata16);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0x3:
+ // rotxr.l Rx
+ udata32 = h8_getreg32(h8, opcode & 0xf);
+ udata32 = h8_rotxr32(h8, udata32);
+ h8_setreg32(h8, opcode & 0xf, udata32);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0x8:
+ // rotr.b Rx
+ udata8 = h8_getreg8(h8, opcode & 0xf);
+ udata8 = h8_rotr8(h8, udata8);
+ h8_setreg8(h8, opcode & 0xf, udata8);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0x9:
+ // rotr.w Rx
+ udata16 = h8_getreg16(h8, opcode & 0xf);
+ udata16 = h8_rotr16(h8, udata16);
+ h8_setreg16(h8, opcode & 0xf, udata16);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0xb:
+ // rotr.l Rx
+ udata32 = h8_getreg32(h8, opcode & 0xf);
+ udata32 = h8_rotr32(h8, udata32);
+ h8_setreg32(h8, opcode & 0xf, udata32);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0xc:
+ // rotr.b #2, Rx
+ udata8 = h8_getreg8(h8, opcode & 0xf);
+ udata8 = h8_rotr8(h8, udata8);
+ udata8 = h8_rotr8(h8, udata8);
+ h8_setreg8(h8, opcode & 0xf, udata8);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0xd:
+ // rotr.w #2, Rx
+ udata16 = h8_getreg16(h8, opcode & 0xf);
+ udata16 = h8_rotr16(h8, udata16);
+ udata16 = h8_rotr16(h8, udata16);
+ h8_setreg16(h8, opcode & 0xf, udata16);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0xf:
+ // rotr.l #2, Rx
+ udata32 = h8_getreg32(h8, opcode & 0xf);
+ udata32 = h8_rotr32(h8, udata32);
+ udata32 = h8_rotr32(h8, udata32);
+ h8_setreg32(h8, opcode & 0xf, udata32);
+ H8_IFETCH_TIMING(1);
+ break;
+ default:
+ logerror("H8/3xx: Unk. group 1 3 %x\n", opcode);
+ h8->h8err = 1;
+ break;
+ }
+ break;
+ case 0x4:
+ // or.b rs, rd
+ dstreg = opcode & 0xf;
+ udata8 = h8_or8(h8, h8_getreg8(h8, (opcode>>4) &0xf), h8_getreg8(h8, dstreg));
+ h8_setreg8(h8, dstreg, udata8);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0x5:
+ // xor.b rs, rd
+ dstreg = opcode & 0xf;
+ udata8 = h8_xor8(h8, h8_getreg8(h8, (opcode>>4) &0xf), h8_getreg8(h8, dstreg));
+ h8_setreg8(h8, dstreg, udata8);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0x6:
+ // and.b rs, rd
+ dstreg = opcode & 0xf;
+ udata8 = h8_and8(h8, h8_getreg8(h8, (opcode>>4) &0xf), h8_getreg8(h8, dstreg));
+ h8_setreg8(h8, dstreg, udata8);
+ H8_IFETCH_TIMING(1)
+ break;
+ // not
+ case 0x7:
+ switch((opcode>>4)&0xf)
+ {
+ case 0x0:
+ // not.b Rx
+ dstreg = opcode & 0xf;
+ udata8 = h8_not8(h8, h8_getreg8(h8, dstreg));
+ h8_setreg8(h8, dstreg, udata8);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0x1:
+ // not.w Rx
+ dstreg = opcode & 0xf;
+ udata16 = h8_not16(h8, h8_getreg16(h8, dstreg));
+ h8_setreg16(h8, dstreg, udata16);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0x3:
+ // not.l ERx
+ dstreg = opcode & 0x7;
+ udata32 = h8_not32(h8, h8_getreg32(h8, dstreg));
+ h8_setreg32(h8, dstreg, udata32);
+ H8_IFETCH_TIMING(1);
+ break;
+
+ case 0x5:
+ // extu.w Rx
+ dstreg = opcode & 0xf;
+ udata16 = h8_getreg16(h8, dstreg) & 0x00ff;
+ h8_setreg16(h8, dstreg, udata16);
+ h8->h8nflag = 0;
+ h8->h8vflag = 0;
+ h8->h8zflag = ((udata16 == 0) ? 1 : 0);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0x7:
+ // extu.l Rx
+ dstreg = opcode & 0x7;
+ udata32 = h8_getreg32(h8, dstreg) & 0x0000ffff;
+ h8_setreg32(h8, dstreg, udata32);
+ h8->h8nflag = 0;
+ h8->h8vflag = 0;
+ h8->h8zflag = ((udata32 == 0) ? 1 : 0);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0x8:
+ // neg.b Rx
+ dstreg = opcode & 0xf;
+ sdata8 = h8_neg8(h8, h8_getreg8(h8, dstreg));
+ h8_setreg8(h8, dstreg, sdata8);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0x9:
+ // neg.w Rx
+ dstreg = opcode & 0xf;
+ sdata16 = h8_neg16(h8, h8_getreg16(h8, dstreg));
+ h8_setreg16(h8, dstreg, sdata16);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0xb:
+ // neg.l ERx
+ dstreg = opcode & 0x7;
+ sdata32 = h8_neg32(h8, h8_getreg32(h8, dstreg));
+ h8_setreg32(h8, dstreg, sdata32);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0xd:
+ // exts.w Rx
+ dstreg = opcode & 0xf;
+ udata16=h8_getreg16(h8, dstreg)&0xff;
+ if(udata16&0x80)
+ {
+ udata16|=0xff00;
+ }
+ h8_setreg16(h8, dstreg, udata16);
+
+ h8->h8vflag = 0;
+ h8->h8nflag = (udata16 & 0xff00) ? 1 : 0;
+ h8->h8zflag = (udata16) ? 0 : 1;
+
+ H8_IFETCH_TIMING(1);
+ break;
+
+ case 0xf:
+ // exts.l Rx
+ dstreg = opcode & 0x7;
+ udata32=h8_getreg32(h8, dstreg)&0xffff;
+ if(udata32&0x8000)
+ {
+ udata32|=0xffff0000;
+ }
+ h8_setreg32(h8, dstreg, udata32);
+
+ h8->h8vflag = 0;
+ h8->h8nflag = (udata32 & 0xffff0000) ? 1 : 0;
+ h8->h8zflag = (udata32) ? 0 : 1;
+
+ H8_IFETCH_TIMING(1);
+ break;
+
+ default:
+ logerror("H8/3xx: Unk. group 1 7-9 %x\n", opcode);
+ h8->h8err = 1;
+ break;
+ }
+ break;
+ case 0x8:
+ // sub.b rs, rd
+ dstreg = opcode & 0xf;
+ udata8 = h8_sub8(h8, h8_getreg8(h8, (opcode>>4) &0xf), h8_getreg8(h8, dstreg));
+ h8_setreg8(h8, dstreg, udata8);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0x9:
+ // sub.w rs, rd
+ dstreg = opcode & 0xf;
+ udata16 = h8_sub16(h8, h8_getreg16(h8, (opcode>>4) &0xf), h8_getreg16(h8, dstreg));
+ h8_setreg16(h8, dstreg, udata16);
+ H8_IFETCH_TIMING(1);
+ break;
+ // sub.b rx
+ case 0xA:
+ if(opcode&0x80)
+ {
+ //logerror("H8/3xx: Unk. group 1 A %x\n", opcode);
+
+ // sub.l rs,rd
+ dstreg = opcode & 0x7;
+ udata32=h8_sub32(h8, h8_getreg32(h8, (opcode>>4) &0x7), h8_getreg32(h8, dstreg));
+ h8_setreg32(h8, dstreg, udata32);
+ H8_IFETCH_TIMING(2);
+ break;
+
+ }
+ else
+ {
+ if(opcode & 0xf0)
+ {
+ logerror("H8/3xx: Unk. group A2 0 %x\n", opcode);
+ h8->h8err = 1;
+ }
+ else
+ {
+ udata8 = h8_getreg8(h8, opcode & 0xf);
+ udata8 = h8_dec8(h8, udata8);
+ h8_setreg8(h8, opcode & 0xf, udata8);
+ H8_IFETCH_TIMING(1);
+ }
+ }
+ break;
+ //
+ case 0xb:
+ switch((opcode>>4)& 0xf)
+ {
+ case 0: // subs.l #1, rN (decrement without touching flags)
+ dstreg = opcode & 0x7;
+ udata32 = h8_getreg32(h8, dstreg);
+ udata32--;
+ h8_setreg32(h8, dstreg, udata32);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 5: // dec.w #1, rN
+ dstreg = opcode & 0xf;
+ udata16 = h8_dec16(h8, h8_getreg16(h8, dstreg));
+ h8_setreg16(h8, dstreg, udata16);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 7: // dec.l #1, rN
+ dstreg = opcode & 0x7;
+ udata32 = h8_dec32(h8, h8_getreg32(h8, dstreg));
+ h8_setreg32(h8, dstreg, udata32);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 8: // subs.l #2, rN (decrement without touching flags)
+ dstreg = opcode & 0x7;
+ udata32 = h8_getreg32(h8, dstreg);
+ udata32-=2;
+ h8_setreg32(h8, dstreg, udata32);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 9: // subs.l #4, rN (decrement without touching flags)
+ dstreg = opcode & 0x7;
+ udata32 = h8_getreg32(h8, dstreg);
+ udata32-=4;
+ h8_setreg32(h8, dstreg, udata32);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0xd: // dec.w #2, rN
+ dstreg = opcode & 0xf;
+ udata16 = h8_dec16(h8, h8_getreg16(h8, dstreg));
+ if (h8->h8vflag)
+ {
+ udata16 = h8_dec16(h8, udata16);
+ h8->h8vflag = 1;
+ }
+ else
+ udata16 = h8_dec16(h8, udata16);
+ h8_setreg16(h8, dstreg, udata16);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0xf: // dec.l #2, rN
+ dstreg = opcode & 0x7;
+ udata32 = h8_dec32(h8, h8_getreg32(h8, dstreg));
+ if (h8->h8vflag)
+ {
+ udata32 = h8_dec32(h8, udata32);
+ h8->h8vflag = 1;
+ }
+ else
+ udata32 = h8_dec32(h8, udata32);
+ h8_setreg32(h8, dstreg, udata32);
+ H8_IFETCH_TIMING(1);
+ break;
+
+ default:
+ logerror("H8/3xx: Unk. group 1 B %x\n", opcode);
+ h8->h8err = 1;
+ break;
+ }
+ break;
+ case 0xc:
+ // cmp.b rs, rd
+ h8_cmp8(h8, h8_getreg8(h8, (opcode>>4) &0xf), h8_getreg8(h8, opcode & 0xf));
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0xd:
+ // cmp.w rx, ry
+ h8_cmp16(h8, h8_getreg16(h8, (opcode>>4) &0xf), h8_getreg16(h8, opcode & 0xf));
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0xe:
+ // subx.b rx, ry
+ dstreg = opcode & 0xf;
+ udata8 = h8_subx8(h8, h8_getreg8(h8, (opcode>>4) &0xf), h8_getreg8(h8, dstreg));
+ h8_setreg8(h8, dstreg, udata8);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0xf:
+ if(opcode & 0x80)
+ {
+ if(opcode & 8)
+ {
+ logerror("H8/3xx: Unk. group 1 f %x\n", opcode);
+ h8->h8err = 1;
+ }
+ else
+ {
+ h8_cmp32(h8, h8_getreg32(h8, (opcode>>4) & 0x7), h8_getreg32(h8, opcode & 0x7));
+ H8_IFETCH_TIMING(1);
+ }
+ }
+ else
+ {
+ logerror("H8/3xx: Unk. group 1 f2 %x\n", opcode);
+ h8->h8err = 1;
+ }
+ break;
+ default:
+ logerror("H8/3xx: Unk. group 1 def %x\n", opcode);
+ h8->h8err = 1;
+ break;
+ }
+}
+
+
+static void h8_group5(h83xx_state *h8, UINT16 opcode)
+{
+ switch((opcode>>8)&0xf)
+ {
+ case 0x0:
+ // mulxu.b
+ udata8 = h8_getreg8(h8, (opcode>>4)&0xf);
+ udata16 = h8_getreg16(h8, opcode & 0xf);
+ udata16 &= 0xff;
+ udata16 = udata16*udata8;
+ // no flags modified!
+ h8_setreg16(h8, opcode & 0xf, udata16);
+ H8_IFETCH_TIMING(1);
+ H8_IOP_TIMING(12);
+ break;
+ case 0x1:
+ // divxu.b
+ udata8 = h8_getreg8(h8, (opcode>>4)&0xf);
+ udata16 = h8_getreg16(h8, opcode & 0x0f);
+ udata16 = h8_divxu8(h8, udata16,udata8);
+ h8_setreg16(h8, opcode & 0xf, udata16);
+ H8_IFETCH_TIMING(1);
+ H8_IOP_TIMING(12);
+ break;
+ case 0x2:
+ // mulxu.w
+ udata16 = h8_getreg16(h8, (opcode>>4)&0xf);
+ udata32 = h8_getreg32(h8, opcode & 7);
+ udata32 &= 0xffff;
+ udata32 = udata32*udata16;
+ // no flags modified!
+ h8_setreg32(h8, opcode & 7, udata32);
+ H8_IFETCH_TIMING(1);
+ H8_IOP_TIMING(20);
+ break;
+ case 0x3:
+ // divxu.w
+ udata16 = h8_getreg16(h8, (opcode>>4)&0xf);
+ udata32 = h8_getreg32(h8, opcode & 7);
+ udata32 = h8_divxu16(h8, udata32,udata16);
+ h8_setreg32(h8, opcode & 7, udata32);
+ H8_IFETCH_TIMING(1);
+ H8_IOP_TIMING(20);
+ break;
+ case 0x4:
+ if(opcode == 0x5470)
+ {
+ // rts
+ udata32 = h8_mem_read32(h8, h8_getreg32(h8, H8_SP));
+ h8_setreg32(h8, H8_SP, h8_getreg32(h8, H8_SP)+4);
+ // extended mode
+ h8->pc = udata32 & 0xffffff;
+ H8_IFETCH_TIMING(2);
+ H8_STACK_TIMING(2);
+ H8_IOP_TIMING(2);
+ }
+ else
+ {
+ logerror("H8/3xx: Unk. group 5 1 %x\n", opcode);
+ h8->h8err = 1;
+ }
+ break;
+ case 0x5:
+ // bsr 8
+ sdata8 = opcode & 0xff;
+ // extended mode stack push!
+ h8_setreg32(h8, H8_SP, h8_getreg32(h8, H8_SP)-4);
+ h8_mem_write32(h8, h8_getreg32(h8, H8_SP), h8->pc);
+ h8->pc = h8->pc + sdata8;
+ H8_IFETCH_TIMING(2); H8_STACK_TIMING(2);
+ break;
+ case 0x6:
+ // rte
+ if(opcode == 0x5670)
+ {
+ // restore CCR
+ udata8 = (UINT8)h8_mem_read16(h8, h8_getreg32(h8, H8_SP));
+ h8_setreg32(h8, H8_SP, h8_getreg32(h8, H8_SP)+2);
+
+ // check if PC is 16 or 24/32 bits wide
+ if (h8->mode_8bit)
+ {
+ udata16 = h8_mem_read16(h8, h8_getreg16(h8, H8_SP));
+ h8_setreg16(h8, H8_SP, h8_getreg16(h8, H8_SP)+2);
+
+ h8->pc = udata16;
+ }
+ else
+ {
+ // extended mode restore PC
+ udata32 = h8_mem_read32(h8, h8_getreg32(h8, H8_SP));
+ h8_setreg32(h8, H8_SP, h8_getreg32(h8, H8_SP)+4);
+
+ // extended mode
+ h8->pc = udata32;
+ }
+ // must do this last, because set_ccr() does a check_irq()
+ h8_set_ccr(h8, udata8);
+ H8_IFETCH_TIMING(2);
+ H8_STACK_TIMING(2);
+ H8_IOP_TIMING(2);
+ }
+ else
+ {
+ logerror("H8/3xx: Unk. group 5 6 %x\n", opcode);
+ h8->h8err = 1;
+ }
+ break;
+ // trapa
+ case 0x7:
+ logerror("H8/3xx: Unk. group 5 7 %x\n", opcode);
+ h8->h8err = 1;
+ break;
+ case 0x8:
+ // bcc @xx:16
+ if(opcode & 0xf)
+ {
+ logerror("H8/3xx: Unk. group 5 8 %x\n", opcode);
+ h8->h8err = 1;
+ }
+ else
+ {
+ sdata16 = h8_mem_read16(h8, h8->pc);
+ h8->pc += 2;
+ if( h8_branch(h8, (opcode >> 4) & 0xf) == 1) h8->pc += sdata16;
+ H8_IOP_TIMING(2)
+ }
+ break;
+ case 0x9:
+ // jmp @erd
+ address24 = h8_getreg32(h8, (opcode>>4)&7);
+ address24 &= H8_ADDR_MASK;
+ h8->pc = address24;
+ H8_IFETCH_TIMING(2);
+ break;
+ // jmp @aa:24
+ case 0xa:
+ address24 = h8_mem_read32(h8, h8->pc-2);
+ address24 &= H8_ADDR_MASK;
+ h8->pc = address24;
+ H8_IFETCH_TIMING(2);
+ H8_IOP_TIMING(2);
+ break;
+ // jmp @aa:8
+ case 0xc:
+ if(opcode & 0xff)
+ {
+ logerror("H8/3xx: Unk. group 5 c %x\n", opcode);
+ h8->h8err = 1;
+ }
+ else
+ {
+ // bsr d:16
+ sdata16=h8_mem_read16(h8, h8->pc);
+ h8_setreg32(h8, H8_SP, h8_getreg32(h8, H8_SP)-4);
+ h8_mem_write32(h8, h8_getreg32(h8, H8_SP), h8->pc+2);
+ h8->pc += sdata16 + 2;
+ H8_IFETCH_TIMING(2); H8_STACK_TIMING(2); H8_IOP_TIMING(2);
+ }
+ break;
+ case 0xd:
+ // jsr @reg
+ address24=h8_getreg32(h8, (opcode>>4)&7);
+ address24 &= H8_ADDR_MASK;
+ // extended mode stack push!
+ h8_setreg32(h8, H8_SP, h8_getreg32(h8, H8_SP)-4);
+ h8_mem_write32(h8, h8_getreg32(h8, H8_SP), h8->pc);
+ h8->pc = address24;
+ H8_STACK_TIMING(2);
+ H8_IOP_TIMING(2);
+ break;
+ case 0xe:
+ // jsr @aa:24
+ address24=h8_mem_read32(h8, h8->pc-2);
+ address24 &= H8_ADDR_MASK;
+ // extended mode stack push!
+ h8_setreg32(h8, H8_SP, h8_getreg32(h8, H8_SP)-4);
+ h8_mem_write32(h8, h8_getreg32(h8, H8_SP), h8->pc+2);
+ h8->pc = address24;
+ H8_IFETCH_TIMING(2);
+ H8_STACK_TIMING(2);
+ H8_IOP_TIMING(2);
+ break;
+ // jsr @aa:8
+ default:
+ logerror("H8: Unk. group 5 def %x\n", opcode);
+ h8->h8err = 1;
+ break;
+ }
+}
+
+static void h8_group6(h83xx_state *h8, UINT16 opcode)
+{
+ switch((opcode>>8)&0xf)
+ {
+ case 0:case 1:case 2:case 3:
+ {
+ UINT8 bitnr;
+
+ dstreg = opcode & 0xf;
+ udata8 = h8_getreg8(h8, dstreg);
+ bitnr = h8_getreg8(h8, (opcode>>4)& 0xf)&7;
+
+ switch((opcode>>8)&0xf)
+ {
+ case 0: udata8 = h8_bset8(h8, bitnr, udata8); h8_setreg8(h8, dstreg, udata8); H8_IFETCH_TIMING(1); break;
+ case 2: udata8 = h8_bclr8(h8, bitnr, udata8); h8_setreg8(h8, dstreg, udata8); H8_IFETCH_TIMING(1); break;
+ case 3: h8_btst8(h8, bitnr, udata8); H8_IFETCH_TIMING(1); break;
+ default:
+ logerror("H8/3xx: Unk. group 6 def 0-3-0 %x\n", opcode);
+ h8->h8err = 1;
+ break;
+ }
+ }
+ break;
+ case 0x4:
+ // or.w rs, rd
+ dstreg = opcode & 0xf;
+ udata16 = h8_getreg16(h8, dstreg);
+ udata16 = h8_or16(h8, h8_getreg16(h8, (opcode>>4) & 0xf), udata16);
+ h8_setreg16(h8, dstreg, udata16);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0x5:
+ // xor.w rs, rd
+ dstreg = opcode & 0xf;
+ udata16 = h8_getreg16(h8, dstreg);
+ udata16 = h8_xor16(h8, h8_getreg16(h8, (opcode>>4) & 0xf), udata16);
+ h8_setreg16(h8, dstreg, udata16);
+ H8_IFETCH_TIMING(1);
+ break;
+ case 0x6:
+ // and.w rs, rd
+ dstreg = opcode & 0xf;
+ udata16 = h8_getreg16(h8, dstreg);
+ udata16 = h8_and16(h8, h8_getreg16(h8, (opcode>>4) & 0xf), udata16);
+ h8_setreg16(h8, dstreg, udata16);
+ H8_IFETCH_TIMING(1)
+ break;
+ case 0x7:
+ // bst/bist #imm, rd
+ if(opcode & 0x80)
+ {
+ udata8 = h8_getreg8(h8, opcode & 0xf);
+ udata8 = h8_bist8(h8, (opcode>>4) & 7, udata8);
+ h8_setreg8(h8, opcode & 0xf, udata8);
+ H8_IFETCH_TIMING(1);
+ }
+ else
+ {
+ udata8 = h8_getreg8(h8, opcode & 0xf);
+ udata8 = h8_bst8(h8, (opcode>>4) & 7, udata8);
+ h8_setreg8(h8, opcode & 0xf, udata8);
+ H8_IFETCH_TIMING(1);
+ }
+ break;
+ case 0x8:
+ if(opcode & 0x80)
+ {
+ // mov.b rx, @rx
+ udata8 = h8_getreg8(h8, opcode & 0xf);
+ address24 = h8_getreg32(h8, (opcode>>4)&7) & H8_ADDR_MASK;
+ h8_mov8(h8, udata8);
+ h8_mem_write8(address24, udata8);
+ H8_IFETCH_TIMING(1);
+ H8_BYTE_TIMING(1, address24);
+ }
+ else
+ {
+ // mov.b @rx, rx
+ address24 = h8_getreg32(h8, (opcode>>4)&7) & H8_ADDR_MASK;
+ udata8 = h8_mem_read8(address24);
+ h8_mov8(h8, udata8);
+ h8_setreg8(h8, opcode & 0xf, udata8);
+ H8_IFETCH_TIMING(1);
+ H8_BYTE_TIMING(1, address24);
+ }
+ break;
+ case 0x9:
+ if(opcode & 0x80)
+ {
+ // mov.w rx, @rx
+ address24 = h8_getreg32(h8, (opcode>>4)&7) & H8_ADDR_MASK;
+ udata16 = h8_getreg16(h8, opcode & 0xf);
+ h8_mov16(h8, udata16);
+ h8_mem_write16(h8, address24, udata16);
+ H8_IFETCH_TIMING(1);
+ H8_WORD_TIMING(1, address24);
+ }
+ else
+ {
+ // mov.w @rx, rx
+ address24 = h8_getreg32(h8, (opcode>>4)&7) & H8_ADDR_MASK;
+ udata16 = h8_mem_read16(h8, address24);
+ h8_mov16(h8, udata16);
+ h8_setreg16(h8, opcode & 0xf, udata16);
+ H8_IFETCH_TIMING(1);
+ H8_WORD_TIMING(1, address24);
+ }
+ break;
+ case 0xa:
+ // mov.b rx, @xx
+ switch((opcode>>4)&0xf)
+ {
+ case 0x0:
+ sdata16=h8_mem_read16(h8, h8->pc);
+ h8->pc += 2;
+ address24 = sdata16 & H8_ADDR_MASK;
+ udata8=h8_mem_read8(address24);
+ h8_mov8(h8, udata8); // flags only
+ h8_setreg8(h8, opcode & 0xf, udata8);
+ H8_IFETCH_TIMING(1);
+ H8_BYTE_TIMING(1, address24);
+ break;
+ case 0x2:
+ address24=h8_mem_read32(h8, h8->pc);
+ h8->pc += 4;
+ udata8=h8_mem_read8(address24);
+ h8_mov8(h8, udata8); // flags only
+ h8_setreg8(h8, opcode & 0xf, udata8);
+ H8_IFETCH_TIMING(2);
+ H8_BYTE_TIMING(1, address24);
+ break;
+ case 0x3: // bclr #x, @imm:24
+ address24=h8_mem_read32(h8, h8->pc);
+ h8->pc += 4;
+ udata16 = h8_mem_read16(h8, h8->pc);
+ h8->pc += 2;
+ switch ((udata16 >> 8) & 0xff)
+ {
+ case 0x60 : // bset Rn, @abs:24
+ udata8 = h8_mem_read8(address24);
+ udata8 = h8_bset8(h8, h8_getreg8(h8, (udata16 >> 4) & 0xf), udata8);
+ h8_mem_write8(address24, udata8);
+ H8_BYTE_TIMING(2, address24);
+ break;
+ case 0x61 : // bnot Rn, @abs:24
+ udata8 = h8_mem_read8(address24);
+ udata8 = h8_bnot8(h8, h8_getreg8(h8, (udata16 >> 4) & 0xf), udata8);
+ h8_mem_write8(address24, udata8);
+ H8_BYTE_TIMING(2, address24);
+ break;
+ case 0x62 : // bclr Rn, @abs:24
+ udata8 = h8_mem_read8(address24);
+ udata8 = h8_bclr8(h8, h8_getreg8(h8, (udata16 >> 4) & 0xf), udata8);
+ h8_mem_write8(address24, udata8);
+ H8_IFETCH_TIMING(2);
+ H8_BYTE_TIMING(2, address24);
+ break;
+ case 0x63 : // btst Rn, @abs:24
+ udata8 = h8_mem_read8(address24);
+ h8_btst8(h8, h8_getreg8(h8, (udata16 >> 4) & 0xf), udata8);
+ h8_mem_write8(address24, udata8);
+ H8_IFETCH_TIMING(2);
+ H8_BYTE_TIMING(2, address24);
+ break;
+ case 0x70 : // bset #imm, @abs:24
+ udata8 = h8_mem_read8(address24);
+ udata8 = h8_bset8(h8, (udata16 >> 4) & 7, udata8);
+ h8_mem_write8(address24, udata8);
+ H8_IFETCH_TIMING(2);
+ H8_BYTE_TIMING(2, address24);
+ break;
+ case 0x71 : // bnot #imm, @abs:24
+ udata8 = h8_mem_read8(address24);
+ udata8 = h8_bnot8(h8, (udata16 >> 4) & 7, udata8);
+ h8_mem_write8(address24, udata8);
+ H8_IFETCH_TIMING(2);
+ H8_BYTE_TIMING(2, address24);
+ break;
+ case 0x72 : // bclr #imm, @abs:24
+ udata8 = h8_mem_read8(address24);
+ udata8 = h8_bclr8(h8, (udata16 >> 4) & 7, udata8);
+ h8_mem_write8(address24, udata8);
+ H8_IFETCH_TIMING(2);
+ H8_BYTE_TIMING(2, address24);
+ break;
+ case 0x73 : // btst #imm, @abs:24
+ udata8 = h8_mem_read8(address24);
+ h8_btst8(h8, (udata16 >> 4) & 7, udata8);
+ H8_IFETCH_TIMING(2);
+ H8_BYTE_TIMING(1, address24);
+ break;
+ }
+ break;
+ case 0x8:
+ sdata16=h8_mem_read16(h8, h8->pc);
+ h8->pc += 2;
+ address24 = sdata16 & H8_ADDR_MASK;
+ udata8=h8_getreg8(h8, opcode & 0xf);
+ h8_mov8(h8, udata8); // flags only
+ h8_mem_write8(address24, udata8);
+ H8_IFETCH_TIMING(3);
+ H8_BYTE_TIMING(1, address24);
+ break;
+ case 0xa:
+ address24=h8_mem_read32(h8, h8->pc);
+ h8->pc += 4;
+ udata8=h8_getreg8(h8, opcode & 0xf);
+ h8_mov8(h8, udata8); // flags only
+ h8_mem_write8(address24, udata8);
+ H8_IFETCH_TIMING(3);
+ H8_BYTE_TIMING(1, address24);
+ break;
+ default:
+ logerror("H8/3xx: Unk. group 6 a %x\n", opcode);
+ h8->h8err = 1;
+ break;
+ }
+ break;
+ case 0xb:
+ // mov.w rx, @xx / mov.w @xx, rx
+ switch((opcode>>4)&0xf)
+ {
+ case 0x0:
+ sdata16=h8_mem_read16(h8, h8->pc);
+ address24 = sdata16;
+ address24 &= H8_ADDR_MASK;
+ h8->pc += 2;
+ udata16 = h8_mem_read16(h8, address24);
+ h8_mov16(h8, udata16); // flags only
+ h8_setreg16(h8, opcode & 0xf, udata16);
+ H8_IFETCH_TIMING(2);
+ H8_WORD_TIMING(1, address24);
+ break;
+ case 0x2:
+ address24=h8_mem_read32(h8, h8->pc);
+ h8->pc += 4;
+ udata16=h8_mem_read16(h8, address24);
+ h8_mov16(h8, udata16); // flags only
+ h8_setreg16(h8, opcode & 0xf, udata16);
+ H8_IFETCH_TIMING(4);
+ H8_WORD_TIMING(1, address24);
+ break;
+ case 0x8:
+ sdata16=h8_mem_read16(h8, h8->pc);
+ address24 = sdata16;
+ address24 &= H8_ADDR_MASK;
+ h8->pc += 2;
+ udata16=h8_getreg16(h8, opcode & 0xf);
+ h8_mov16(h8, udata16); // flags only
+ h8_mem_write16(h8, address24, udata16);
+ H8_IFETCH_TIMING(2);
+ H8_WORD_TIMING(1, address24);
+ break;
+ case 0xa: // pass
+ address24=h8_mem_read32(h8, h8->pc);
+ h8->pc += 4;
+ udata16=h8_getreg16(h8, opcode & 0xf);
+ h8_mov16(h8, udata16); // flags only
+ h8_mem_write16(h8, address24, udata16);
+ H8_IFETCH_TIMING(4);
+ H8_WORD_TIMING(1, address24);
+ break;
+ default:
+ logerror("H8/3xx: Unk. group 6b %x\n", opcode);
+ h8->h8err = 1;
+ break;
+ }
+ break;
+ case 0xc:
+ if(opcode & 0x80)
+ {
+ // mov.b rx, @-erx
+ srcreg = (opcode>>4)&7;
+ h8_setreg32(h8, srcreg, h8_getreg32(h8, srcreg)-1);
+ address24 = h8_getreg32(h8, srcreg) & H8_ADDR_MASK;
+ udata8 = h8_getreg8(h8, opcode & 0xf);
+ h8_mem_write8(address24, udata8);
+ H8_IFETCH_TIMING(1);
+ H8_BYTE_TIMING(1, address24);
+ H8_IOP_TIMING(2);
+ }
+ else
+ {
+ // mov.b @erx+,rx
+ srcreg = (opcode>>4)&7;
+ address24 = h8_getreg32(h8, srcreg) & H8_ADDR_MASK;
+ h8_setreg32(h8, srcreg, h8_getreg32(h8, srcreg)+1);
+ udata8 = h8_mem_read8(address24);
+ h8_setreg8(h8, opcode & 0xf, udata8);
+ H8_IFETCH_TIMING(1);
+ H8_BYTE_TIMING(1, address24);
+ H8_IOP_TIMING(2);
+ }
+ h8_mov8(h8, udata8);
+ break;
+ case 0xd:
+ if(opcode & 0x80)
+ {
+ // mov.w rs, @-erd
+ srcreg = (opcode>>4)&7;
+ h8_setreg32(h8, srcreg, h8_getreg32(h8, srcreg)-2);
+ address24 = h8_getreg32(h8, srcreg) & H8_ADDR_MASK;
+ udata16 = h8_getreg16(h8, opcode & 0xf);
+ h8_mem_write16(h8, address24, udata16);
+ H8_IFETCH_TIMING(1);
+ H8_WORD_TIMING(1, address24);
+ H8_IOP_TIMING(2);
+ }
+ else
+ {
+ // mov.w @ers+, rd
+ srcreg = (opcode>>4)&7;
+ address24 = h8_getreg32(h8, srcreg) & H8_ADDR_MASK;
+ h8_setreg32(h8, srcreg, h8_getreg32(h8, srcreg)+2);
+ udata16 = h8_mem_read16(h8, address24);
+ h8_setreg16(h8, opcode & 0xf, udata16);
+ H8_IFETCH_TIMING(1);
+ H8_BYTE_TIMING(1, address24);
+ H8_IOP_TIMING(2);
+ }
+ h8_mov16(h8, udata16);
+ break;
+ case 0xe:
+ // mov.b @(displ16 + Rs), rd
+ sdata16=h8_mem_read16(h8, h8->pc); // sign extend displacements !
+ h8->pc += 2;
+ address24 = (h8_getreg32(h8, (opcode>>4)&7)) & H8_ADDR_MASK;
+ address24 += sdata16;
+ if(opcode & 0x80)
+ {
+ udata8 = h8_getreg8(h8, opcode & 0xf);
+ h8_mem_write8(address24, udata8);
+ }
+ else
+ {
+ udata8 = h8_mem_read8(address24);
+ h8_setreg8(h8, opcode & 0xf, udata8);
+ }
+ h8_mov8(h8, udata8);
+ H8_IFETCH_TIMING(2);
+ H8_BYTE_TIMING(1, address24);
+ break;
+ case 0xf:
+ // mov.w @(displ16 + Rs), rd
+ sdata16=h8_mem_read16(h8, h8->pc); // sign extend displacements !
+ h8->pc += 2;
+ address24 = (h8_getreg32(h8, (opcode>>4)&7)) & H8_ADDR_MASK;
+ address24 += sdata16;
+ if(opcode & 0x80)
+ {
+ udata16 = h8_getreg16(h8, opcode & 0xf);
+ h8_mem_write16(h8, address24, udata16);
+ }
+ else
+ {
+ udata16 = h8_mem_read16(h8, address24);
+ h8_setreg16(h8, opcode & 0xf, udata16);
+ }
+ h8_mov16(h8, udata16);
+ H8_IFETCH_TIMING(2);
+ H8_WORD_TIMING(1, address24);
+ break;
+ default:
+ logerror("H8/3xx: Unk. group 6 def %x\n", opcode);
+ h8->h8err = 1;
+ break;
+ }
+}
+
+static void h8_group7(h83xx_state *h8, UINT16 opcode)
+{
+ switch((opcode>>8)&0xf)
+ {
+ case 0:case 1:case 2:case 3:case 4:case 5:case 6:case 7:
+ {
+ UINT8 bitnr;
+
+ dstreg = opcode & 0xf;
+ udata8 = h8_getreg8(h8, dstreg);
+ bitnr = (opcode>>4)&7;
+
+ if(((opcode>>4)&0x8) == 0)
+ {
+ switch((opcode>>8)&0x7)
+ {
+ case 0: udata8 = h8_bset8(h8, bitnr, udata8); h8_setreg8(h8, dstreg, udata8); H8_IFETCH_TIMING(1); break;
+ case 1: udata8 = h8_bnot8(h8, bitnr, udata8); h8_setreg8(h8, dstreg, udata8); H8_IFETCH_TIMING(1); break;
+ case 2: udata8 = h8_bclr8(h8, bitnr, udata8); h8_setreg8(h8, dstreg, udata8);H8_IFETCH_TIMING(1);break;
+ case 3: h8_btst8(h8, bitnr, udata8); H8_IFETCH_TIMING(1); break;
+ case 4: h8_bor8(h8, bitnr, udata8); H8_IFETCH_TIMING(1); break;
+ case 5: h8_bxor8(h8, bitnr, udata8); H8_IFETCH_TIMING(1); break;
+ case 6: h8_band8(h8, bitnr, udata8); H8_IFETCH_TIMING(1); break;
+ case 7: h8_bld8(h8, bitnr, udata8); H8_IFETCH_TIMING(1); break;
+ default:
+ logerror("H8/3xx: Unk. group 7 0-7 def %x\n", opcode);
+ h8->h8err = 1;
+ break;
+ }
+ }
+ else
+ {
+ switch((opcode>>8)&7)
+ {
+ case 7: h8_bild8(h8, bitnr, udata8); H8_IFETCH_TIMING(1); break;
+ default:
+ logerror("H8/3xx: Unk. group 7 0-7-1 def %x\n", opcode);
+ h8->h8err = 1;
+ break;
+ }
+ }
+ }
+ break;
+ case 0x8:
+ ext16 = h8_mem_read16(h8, h8->pc);
+ h8->pc += 2;
+ udata32 = h8_mem_read32(h8, h8->pc);
+ h8->pc += 4;
+
+ if(((ext16>>8) & 0xf) == 0xa)
+ {
+ if(((ext16>>4) & 0xf) == 0xa)
+ {
+ udata8 = h8_getreg8(h8, ext16 & 0xf);
+ h8_mov8(h8, udata8); // update flags !
+ udata32 += h8_getreg32(h8, (opcode >> 4) & 7);
+ h8_mem_write8(udata32, udata8);
+ }
+ else
+ {
+ udata32 += h8_getreg32(h8, (opcode >> 4) & 7);
+ udata8 = h8_mem_read8(udata32);
+ h8_mov8(h8, udata8); // update flags !
+ h8_setreg8(h8, ext16 & 0xf, udata8);
+ }
+ H8_BYTE_TIMING(1, udata32);
+ H8_IFETCH_TIMING(4);
+ }
+ else if ((ext16 & 0xfff0) == 0x6b20) // mov.w @(24-bit direct, rN), rM
+ {
+ udata32 += h8_getreg32(h8, (opcode >> 4) & 7);
+ udata16 = h8_mem_read16(h8, udata32);
+ h8_setreg16(h8, ext16 & 0xf, udata16);
+ h8_mov16(h8, udata16); // update flags !
+ H8_WORD_TIMING(1, udata32);
+ H8_IFETCH_TIMING(4);
+ }
+ else if ((ext16 & 0xfff0) == 0x6ba0) // mov.w rM, @(24-bit direct, rN)
+ {
+ udata32 += h8_getreg32(h8, (opcode >> 4) & 7);
+ udata16 = h8_getreg16(h8, ext16 & 0xf);
+ h8_mem_write16(h8, udata32, udata16);
+ h8_mov16(h8, udata16); // update flags !
+ H8_WORD_TIMING(1, udata32);
+ H8_IFETCH_TIMING(4);
+ }
+ else
+ {
+ logerror("H8/3xx: Unk. group 7 8 %x\n", opcode);
+ h8->h8err = 1;
+ }
+ break;
+
+
+ // xxx.w #aa:16, rd
+ case 0x9:
+ if( ((opcode>>4) & 0xf) > 0x6)
+ {
+ logerror("H8/3xx: Unk. group 7 9 %x\n", opcode);
+ h8->h8err = 1;
+ }
+ else
+ {
+ UINT16 dst16;
+ udata16 = h8_mem_read16(h8, h8->pc);
+ h8->pc += 2;
+ dstreg = opcode&0xf;
+ dst16 = h8_getreg16(h8, dstreg);
+
+ switch((opcode>>4)&7)
+ {
+ case 0: dst16 = h8_mov16(h8, udata16); h8_setreg16(h8, dstreg, dst16); H8_IFETCH_TIMING(2);break;
+ case 1: dst16 = h8_add16(h8, udata16, dst16); h8_setreg16(h8, dstreg, dst16); H8_IFETCH_TIMING(2); break;
+ case 2: h8_cmp16(h8, udata16, dst16); H8_IFETCH_TIMING(2); break;
+ case 3: dst16 = h8_sub16(h8, udata16, dst16); h8_setreg16(h8, dstreg, dst16); H8_IFETCH_TIMING(2); break;
+ case 4: dst16 = h8_or16(h8, udata16, dst16); h8_setreg16(h8, dstreg, dst16); H8_IFETCH_TIMING(2); break;
+ case 5: dst16 = h8_xor16(h8, udata16, dst16); h8_setreg16(h8, dstreg, dst16); H8_IFETCH_TIMING(2); break;
+ case 6: dst16 = h8_and16(h8, udata16, dst16); h8_setreg16(h8, dstreg, dst16); H8_IFETCH_TIMING(2); break;
+ default:
+ logerror("H8/3xx: Unk. group 7 9 %x\n", opcode);
+ h8->h8err = 1;
+ break;
+ }
+ }
+ break;
+ // xxx.l #aa:32, erd
+ case 0xa:
+ if( (((opcode>>4) & 0xf) > 0x6) || (opcode & 0x8))
+ {
+ logerror("H8/3xx: Unk. group 7 a %x\n", opcode);
+ h8->h8err = 1;
+ }
+ else
+ {
+ UINT32 dst32;
+ udata32 = h8_mem_read32(h8, h8->pc);
+ dstreg = opcode&0x7;
+ h8->pc +=4;
+ dst32 = h8_getreg32(h8, dstreg);
+
+ switch((opcode>>4)&7)
+ {
+ case 0: dst32 = h8_mov32(h8, udata32); h8_setreg32(h8, dstreg, dst32); H8_IFETCH_TIMING(3); break;
+ case 1: dst32 = h8_add32(h8, udata32, dst32); h8_setreg32(h8, dstreg, dst32); H8_IFETCH_TIMING(3); break;
+ case 2: h8_cmp32(h8, udata32, dst32); H8_IFETCH_TIMING(3); break;
+ case 3: dst32 = h8_sub32(h8, udata32, dst32); h8_setreg32(h8, dstreg, dst32); H8_IFETCH_TIMING(3); break;
+ case 4: dst32 = h8_or32(h8, udata32, dst32); h8_setreg32(h8, dstreg, dst32); H8_IFETCH_TIMING(3); break;
+ case 5: dst32 = h8_xor32(h8, udata32, dst32); h8_setreg32(h8, dstreg, dst32); H8_IFETCH_TIMING(3); break;
+ case 6: dst32 = h8_and32(h8, udata32, dst32); h8_setreg32(h8, dstreg, dst32); H8_IFETCH_TIMING(3); break;
+ default:
+ logerror("H8/3xx: Unk. group 7 a2 %x\n", opcode);
+ h8->h8err = 1;
+ break;
+ }
+ }
+ break;
+ // eepmov
+ case 0xb:
+ switch (opcode & 0xff)
+ {
+ case 0xd4: // eepmov.w
+ {
+ ext16 = h8_mem_read16(h8, h8->pc);
+ h8->pc += 2;
+ if (ext16 != 0x598f)
+ {
+ logerror("H8/3xx: Unk. eepmov form\n");
+ h8->h8err = 1;
+ }
+ else
+ {
+ UINT16 cnt = h8_getreg16(h8, 4);
+
+ H8_IFETCH_TIMING(2);
+ H8_BYTE_TIMING((2*cnt)+2, h8->regs[5]);
+
+ while (cnt > 0)
+ {
+ h8_mem_write8(h8->regs[6], h8_mem_read8(h8->regs[5]));
+ h8->regs[5]++;
+ h8->regs[6]++;
+ cnt--;
+ }
+ h8_setreg16(h8, 4, 0);
+ }
+ }
+ break;
+
+ case 0x5c: // eepmov.b
+ {
+ ext16 = h8_mem_read16(h8, h8->pc);
+ h8->pc += 2;
+ if (ext16 != 0x598f)
+ {
+ logerror("H8/3xx: Unk. eepmov form\n");
+ h8->h8err = 1;
+ }
+ else
+ {
+ UINT8 cnt = h8_getreg8(h8, 8+4);
+
+ H8_IFETCH_TIMING(2);
+ H8_BYTE_TIMING((2*cnt)+2, h8->regs[5]);
+
+ while (cnt > 0)
+ {
+ h8_mem_write8(h8->regs[6], h8_mem_read8(h8->regs[5]));
+ h8->regs[5]++;
+ h8->regs[6]++;
+ cnt--;
+ }
+ h8_setreg8(h8, 8+4, 0);
+ }
+ }
+ break;
+
+ default:
+ logerror("H8/3xx: Unk. eepmov form\n");
+ h8->h8err = 1;
+ }
+ break;
+ // bxx.b #xx:3, @rd
+ case 0xc:
+ {
+ UINT8 bitnr;
+
+ address24 = h8_getreg32(h8, (opcode>>4) & 0x7);
+ udata8 = h8_mem_read8(address24);
+ H8_BYTE_TIMING(1, address24);
+
+ ext16 = h8_mem_read16(h8, h8->pc);
+ h8->pc += 2;
+ H8_IFETCH_TIMING(2);
+
+ switch(ext16>>8)
+ {
+ // BTST Rn,@ERd
+ case 0x63:
+ srcreg = (ext16>>4)&0xf;
+ bitnr = h8_getreg8(h8, srcreg)&7;
+ h8_btst8(h8, bitnr, udata8);
+ break;
+ // btst.b #imm, @Rn
+ case 0x73:
+ bitnr = (ext16>>4)&7;
+ h8_btst8(h8, bitnr, udata8);
+ break;
+ // bld.b #imm, @Rn
+ case 0x77:
+ udata16 = h8_mem_read16(h8, h8->pc);
+ h8->pc += 2;
+ dstreg = (opcode>>4) & 7;
+ h8_bld8(h8, (udata16>>4) & 7, h8_mem_read8(h8_getreg16(h8, dstreg)));
+ H8_IFETCH_TIMING(1);
+ H8_WORD_TIMING(1, h8_getreg16(h8, dstreg));
+ break;
+
+
+
+
+ default:
+ h8->h8err=1;
+ }
+ }
+ break;
+ case 0xd:
+ ext16 = h8_mem_read16(h8, h8->pc);
+ h8->pc += 2;
+ address24 = h8_getreg32(h8, (opcode>>4) & 0x7);
+ H8_IFETCH_TIMING(2);
+ H8_BYTE_TIMING(1, address24);
+ switch(ext16>>8)
+ {
+ // bset/bnot/bclr.b Rn, @ERd
+ case 0x60:
+ if (((opcode & 0x8f)!=0)||((ext16 & 0x0f)!=0)) { h8->h8err=1; break; }
+ h8_mem_write8(address24, h8_bset8(h8, h8_getreg16(h8, (ext16>>4)&0xf)&7, h8_mem_read8(address24)));
+ break;
+ case 0x61:
+ if (((opcode & 0x8f)!=0)||((ext16 & 0x0f)!=0)) { h8->h8err=1; break; }
+ h8_mem_write8(address24, h8_bnot8(h8, h8_getreg16(h8, (ext16>>4)&0xf)&7, h8_mem_read8(address24)));
+ break;
+ case 0x62:
+ if (((opcode & 0x8f)!=0)||((ext16 & 0x0f)!=0)) { h8->h8err=1; break; }
+ h8_mem_write8(address24, h8_bclr8(h8, h8_getreg16(h8, (ext16>>4)&0xf)&7, h8_mem_read8(address24)));
+ break;
+
+ case 0x67: // bst/bist.b #Imm:3, @ERd
+ if (((opcode & 0x8f)!=0)||((ext16 & 0x0f)!=0)) { h8->h8err=1; break; }
+ if ((ext16 & 0x80)!=0)
+ {
+ h8_mem_write8(address24, h8_bist8(h8, (ext16>>4)&7, h8_mem_read8(address24)));
+ }
+ else
+ {
+ h8_mem_write8(address24, h8_bst8(h8, (ext16>>4)&7, h8_mem_read8(address24)));
+ }
+ break;
+
+ // bset/bnot/bclr.b #Imm:3, @ERd
+ case 0x70:
+ if (((opcode & 0x8f)!=0)||((ext16 & 0x8f)!=0)) { h8->h8err=1; break; }
+ h8_mem_write8(address24, h8_bset8(h8, (ext16>>4)&7, h8_mem_read8(address24)));
+ break;
+ case 0x71:
+ if (((opcode & 0x8f)!=0)||((ext16 & 0x8f)!=0)) { h8->h8err=1; break; }
+ h8_mem_write8(address24, h8_bnot8(h8, (ext16>>4)&7, h8_mem_read8(address24)));
+ break;
+ case 0x72:
+ if (((opcode & 0x8f)!=0)||((ext16 & 0x8f)!=0)) { h8->h8err=1; break; }
+ h8_mem_write8(address24, h8_bclr8(h8, (ext16>>4)&7, h8_mem_read8(address24)));
+ break;
+ }
+ break;
+
+ // bxxx.b #imm, @aa:8
+ case 0xe:
+ case 0xf:
+ {
+ UINT8 bitnr=0;
+ ext16 = h8_mem_read16(h8, h8->pc);
+ h8->pc += 2;
+ address24 = 0xffff00 + (opcode & 0xff);
+ udata8 = h8_mem_read8(address24);
+
+ switch((ext16>>8)&0xff)
+ {
+ case 0x30:
+ case 0x60:
+ bitnr = (ext16>>4)&7;
+ udata8 = h8_bset8(h8, bitnr, udata8); h8_mem_write8(address24, udata8); H8_IFETCH_TIMING(2); H8_BYTE_TIMING(2, address24);
+ break;
+ case 0x70:
+ bitnr = (ext16>>4)&7;
+ if(ext16&0x80) h8->h8err = 1;
+ udata8 = h8_bset8(h8, bitnr, udata8); h8_mem_write8(address24, udata8); H8_IFETCH_TIMING(2); H8_BYTE_TIMING(2, address24);
+ break;
+ case 0x71:
+ bitnr = (ext16>>4)&7;
+ if(ext16&0x80) h8->h8err = 1;
+ udata8 = h8_bnot8(h8, bitnr, udata8); h8_mem_write8(address24, udata8); H8_IFETCH_TIMING(2); H8_BYTE_TIMING(2, address24);
+ break;
+ case 0x32:
+ case 0x62:
+ bitnr = h8_getreg8(h8, (ext16>>4)&0xf)&7;
+ udata8 = h8_bclr8(h8, bitnr, udata8); h8_mem_write8(address24, udata8); H8_IFETCH_TIMING(2); H8_BYTE_TIMING(2, address24);
+ break;
+ case 0x72:
+ bitnr = (ext16>>4)&7;
+ if(ext16&0x80) h8->h8err = 1;
+ udata8 = h8_bclr8(h8, bitnr, udata8); h8_mem_write8(address24, udata8); H8_IFETCH_TIMING(2); H8_BYTE_TIMING(2, address24);
+ break;
+ case 0x63:
+ bitnr = h8_getreg8(h8, (ext16>>4)&0xf)&7;
+ h8_btst8(h8, bitnr, udata8); H8_IFETCH_TIMING(2); H8_BYTE_TIMING(1, address24);
+ break;
+ case 0x73:
+ bitnr = (ext16>>4)&7;
+ if(ext16&0x80) h8->h8err = 1;
+ h8_btst8(h8, bitnr, udata8); H8_IFETCH_TIMING(2); H8_BYTE_TIMING(1, address24);
+ break;
+ case 0x74:
+ bitnr = (ext16>>4)&7;
+ if(ext16&0x80)
+ {
+ // bior
+ h8->h8err = 1;
+ }
+ else
+ {
+ h8_bor8(h8, bitnr, udata8); H8_IFETCH_TIMING(2); H8_BYTE_TIMING(1, address24);
+ }
+ break;
+ case 0x67:
+ bitnr = (ext16>>4)&7;
+ if(ext16&0x80)
+ {
+ h8_bist8(h8, bitnr, udata8); H8_IFETCH_TIMING(2); H8_BYTE_TIMING(2, address24);
+ }
+ else
+ {
+ h8_bst8(h8, bitnr, udata8); H8_IFETCH_TIMING(2); H8_BYTE_TIMING(2, address24);
+ }
+ break;
+ case 0x77:
+ bitnr = (ext16>>4)&7;
+ if(ext16&0x80)
+ {
+ h8_bild8(h8, bitnr, udata8); H8_IFETCH_TIMING(2); H8_BYTE_TIMING(2, address24);
+ }
+ else
+ {
+ h8_bld8(h8, bitnr, udata8); H8_IFETCH_TIMING(2); H8_BYTE_TIMING(2, address24);
+ }
+ break;
+ default:
+ h8->h8err = 1;
+ break;
+ }
+ if(h8->h8err)
+ logerror("H8/3xx: Unk. group 7 e %x\n", opcode);
+ }
+ break;
+ default:
+ logerror("H8/3xx: Unk. group 7 def %x\n", opcode);
+ h8->h8err = 1;
+ break;
+ }
+}
+
+
+static UINT8 h8_mov8(h83xx_state *h8, UINT8 src)
+{
+ // N and Z modified
+ h8->h8nflag = (src>>7) & 1;
+ h8->h8vflag = 0;
+
+ // zflag
+ if(src==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return src;
+}
+
+static UINT16 h8_mov16(h83xx_state *h8, UINT16 src)
+{
+ // N and Z modified
+ h8->h8nflag = (src>>15) & 1;
+ h8->h8vflag = 0;
+
+ // zflag
+ if(src==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+ return src;
+}
+
+static UINT32 h8_mov32(h83xx_state *h8, UINT32 src)
+{
+ // N and Z modified
+ h8->h8nflag = (src>>31) & 1;
+ h8->h8vflag = 0;
+
+ // zflag
+ if(src==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return src;
+}
+
+static UINT8 h8_sub8(h83xx_state *h8, UINT8 src, UINT8 dst)
+{
+ UINT16 res;
+
+ res = (UINT16)dst - src;
+ // H,N,Z,V,C modified
+ h8->h8nflag = (res>>7) & 1;
+ h8->h8vflag = (((src^dst) & (res^dst))>>7) & 1;
+ h8->h8cflag = (res >> 8) & 1;
+
+ // zflag
+ if((res&0xff)==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ h8->h8hflag = ((src^dst^res) & 0x10) ? 1 : 0;
+
+ return res;
+}
+
+static UINT16 h8_sub16(h83xx_state *h8, UINT16 src, UINT16 dst)
+{
+ UINT32 res;
+
+ res = (UINT32)dst - src;
+ // H,N,Z,V,C modified
+ h8->h8nflag = (res>>15) & 1;
+ h8->h8vflag = (((src^dst) & (res^dst))>>15) & 1;
+ h8->h8cflag = (res >> 16) & 1;
+ // h8->h8hflag = (res>>28) & 1;
+
+ // zflag
+ if((res&0xffff)==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ h8->h8hflag = ((src^dst^res) & 0x1000) ? 1 : 0;
+
+ return res;
+}
+
+static UINT32 h8_sub32(h83xx_state *h8, UINT32 src, UINT32 dst)
+{
+ UINT64 res;
+
+ res = (UINT64)dst - src;
+ // H,N,Z,V,C modified
+ h8->h8nflag = (res>>31) & 1;
+ h8->h8vflag = (((src^dst) & (res^dst))>>31) & 1;
+ h8->h8cflag = (res >> 32) & 1;
+ // h8->h8hflag = (res>>28) & 1;
+
+ // zflag
+ if((res&0xffffffff)==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ h8->h8hflag = ((src^dst^res) & 0x10000000) ? 1 : 0;
+
+ return res;
+}
+
+
+
+
+static UINT8 h8_add8(h83xx_state *h8, UINT8 src, UINT8 dst)
+{
+ UINT16 res;
+
+ res = (UINT16)src + dst;
+ // H,N,Z,V,C modified
+ h8->h8nflag = (res & 0x80) ? 1 : 0;
+ h8->h8vflag = ((src^res) & (dst^res) & 0x80) ? 1 : 0;
+ h8->h8cflag = (res & 0x100) ? 1 : 0;
+ h8->h8zflag = (res & 0xff) ? 0 : 1;
+ h8->h8hflag = ((src^dst^res) & 0x10) ? 1 : 0;
+
+ return (UINT8)res;
+}
+
+static UINT16 h8_add16(h83xx_state *h8, UINT16 src, UINT16 dst)
+{
+ UINT32 res;
+
+ res = (UINT32)src + dst;
+ // H,N,Z,V,C modified
+ h8->h8nflag = (res & 0x8000) ? 1 : 0;
+ h8->h8vflag = ((src^res) & (dst^res) & 0x8000) ? 1 : 0;
+ h8->h8cflag = (res & 0x10000) ? 1 : 0;
+ h8->h8zflag = (res & 0xffff) ? 0 : 1;
+ h8->h8hflag = ((src^dst^res) & 0x1000) ? 1 : 0;
+
+ return res;
+}
+
+static UINT32 h8_add32(h83xx_state *h8, UINT32 src, UINT32 dst)
+{
+ UINT64 res;
+
+ res = (UINT64)src + dst;
+ // H,N,Z,V,C modified
+ h8->h8nflag = (res & 0x80000000) ? 1 : 0;
+ h8->h8vflag = (((src^res) & (dst^res)) & 0x80000000) ? 1 : 0;
+ h8->h8cflag = ((res) & (((UINT64)1) << 32)) ? 1 : 0;
+ h8->h8zflag = (res & 0xffffffff) ? 0 : 1;
+ h8->h8hflag = ((src^dst^res) & 0x10000000) ? 1 : 0;
+
+ return res;
+}
+
+
+static UINT8 h8_addx8(h83xx_state *h8, UINT8 src, UINT8 dst)
+{
+ UINT16 res;
+
+ res = (UINT16)src + dst + h8->h8cflag;
+ // H,N,Z,V,C modified
+ h8->h8nflag = (res & 0x80) ? 1 : 0;
+ h8->h8vflag = ((src^res) & (dst^res) & 0x80) ? 1 : 0;
+ h8->h8cflag = (res >> 8) & 1;
+ h8->h8hflag = ((src^dst^res) & 0x10) ? 1 : 0;
+ h8->h8zflag = (res & 0xff) ? 0 : h8->h8zflag;
+
+ return (UINT8)res;
+}
+
+static void h8_cmp8(h83xx_state *h8, UINT8 src, UINT8 dst)
+{
+ UINT16 res = (UINT16)dst - src;
+
+ h8->h8cflag = (res & 0x100) ? 1 : 0;
+ h8->h8vflag = (((dst) ^ (src)) & ((dst) ^ (res)) & 0x80) ? 1 : 0;
+ h8->h8zflag = ((res & 0xff) == 0) ? 1 : 0;
+ h8->h8nflag = (res & 0x80) ? 1 : 0;
+ h8->h8hflag = ((src^dst^res) & 0x10) ? 1 : 0;
+}
+
+static void h8_cmp16(h83xx_state *h8, UINT16 src, UINT16 dst)
+{
+ UINT32 res = (UINT32)dst - src;
+
+ h8->h8cflag = (res & 0x10000) ? 1 : 0;
+ h8->h8vflag = (((dst) ^ (src)) & ((dst) ^ (res)) & 0x8000) ? 1 : 0;
+ h8->h8zflag = ((res & 0xffff) == 0) ? 1 : 0;
+ h8->h8nflag = (res & 0x8000) ? 1 : 0;
+ h8->h8hflag = ((src^dst^res) & 0x1000) ? 1 : 0;
+}
+
+static void h8_cmp32(h83xx_state *h8, UINT32 src, UINT32 dst)
+{
+ UINT64 res = (UINT64)dst - src;
+
+ h8->h8cflag = (res & (UINT64)U64(0x100000000)) ? 1 : 0;
+ h8->h8vflag = (((dst) ^ (src)) & ((dst) ^ (res)) & 0x80000000) ? 1 : 0;
+ h8->h8zflag = ((res & 0xffffffff) == 0) ? 1 : 0;
+ h8->h8nflag = (res & 0x80000000) ? 1 : 0;
+ h8->h8hflag = ((src^dst^res) & 0x10000000) ? 1 : 0;
+}
+
+
+static UINT8 h8_subx8(h83xx_state *h8, UINT8 src, UINT8 dst)
+{
+ UINT16 res;
+
+ res = (UINT16)dst - src - (h8->h8cflag) ? 1 : 0;
+ // H,N,Z,V,C modified
+ h8->h8nflag = (res>>7) & 1;
+ h8->h8vflag = (((src^dst) & (res^dst))>>7) & 1;
+ h8->h8cflag = (res >> 8) & 1;
+
+ // zflag
+ if((res&0xff)==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ h8->h8hflag = ((src^dst^res) & 0x10) ? 1 : 0;
+
+ return res;
+}
+
+static UINT8 h8_or8(h83xx_state *h8, UINT8 src, UINT8 dst)
+{
+ UINT8 res;
+ res = src | dst;
+
+ h8->h8nflag = (res>>7) & 1;
+ h8->h8vflag = 0;
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static UINT16 h8_or16(h83xx_state *h8, UINT16 src, UINT16 dst)
+{
+ UINT16 res;
+ res = src | dst;
+
+ h8->h8nflag = (res>>15) & 1;
+ h8->h8vflag = 0;
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static UINT32 h8_or32(h83xx_state *h8, UINT32 src, UINT32 dst)
+{
+ UINT32 res;
+ res = src | dst;
+
+ h8->h8nflag = (res>>31) & 1;
+ h8->h8vflag = 0;
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static UINT8 h8_xor8(h83xx_state *h8, UINT8 src, UINT8 dst)
+{
+ UINT8 res;
+ res = src ^ dst;
+
+ h8->h8nflag = (res>>7) & 1;
+ h8->h8vflag = 0;
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static UINT16 h8_xor16(h83xx_state *h8, UINT16 src, UINT16 dst)
+{
+ UINT16 res;
+ res = src ^ dst;
+
+ h8->h8nflag = (res>>15) & 1;
+ h8->h8vflag = 0;
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static UINT32 h8_xor32(h83xx_state *h8, UINT32 src, UINT32 dst)
+{
+ UINT32 res;
+ res = src ^ dst;
+
+ h8->h8nflag = (res>>31) & 1;
+ h8->h8vflag = 0;
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static UINT8 h8_and8(h83xx_state *h8, UINT8 src, UINT8 dst)
+{
+ UINT8 res;
+
+ res = src & dst;
+ // N and Z modified
+ h8->h8nflag = (res>>7) & 1;
+ h8->h8vflag = 0;
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static UINT16 h8_and16(h83xx_state *h8, UINT16 src, UINT16 dst)
+{
+ UINT16 res;
+
+ res = src & dst;
+ // N and Z modified
+ h8->h8nflag = (res>>15) & 1;
+ h8->h8vflag = 0;
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static UINT32 h8_and32(h83xx_state *h8, UINT32 src, UINT32 dst)
+{
+ UINT32 res;
+
+ res = src & dst;
+ // N and Z modified
+ h8->h8nflag = (res>>31) & 1;
+ h8->h8vflag = 0;
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static void h8_btst8(h83xx_state *h8, UINT8 bit, UINT8 dst)
+{
+ // test single bit and update Z flag
+ if( (dst & (1<<bit)) == 0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+}
+
+static void h8_bld8(h83xx_state *h8, UINT8 bit, UINT8 dst)
+{
+ // load bit to carry
+ h8->h8cflag = (dst >> bit) & 1;
+}
+
+static void h8_bild8(h83xx_state *h8, UINT8 bit, UINT8 dst)
+{
+ // load inverted bit to carry
+ h8->h8cflag = ((~dst) >> bit) & 1;
+}
+
+static UINT8 h8_bnot8(h83xx_state *h8, UINT8 src, UINT8 dst)
+{
+ // invert single bit, no effect on C flag
+ return dst ^ (1<<src);
+}
+
+static UINT8 h8_bst8(h83xx_state *h8, UINT8 src, UINT8 dst)
+{
+ UINT8 res;
+
+ // store carry flag in bit position
+ if(h8->h8cflag == 1)
+ {
+ res = dst | (1<<src);
+ }
+ else
+ {
+ res = dst & ~(1<<src); // mask off
+ }
+ return res;
+}
+
+static UINT8 h8_bist8(h83xx_state *h8, UINT8 src, UINT8 dst)
+{
+ UINT8 res;
+
+ // store inverse of carry flag in bit position
+ if(h8->h8cflag == 0)
+ {
+ res = dst | (1<<src);
+ }
+ else
+ {
+ res = dst & ~(1<<src); // mask off
+ }
+ return res;
+}
+
+static UINT8 h8_bset8(h83xx_state *h8, UINT8 src, UINT8 dst)
+{
+ // pass
+ UINT8 res;
+ res = dst | (1<<src);
+ return res;
+}
+
+// does not affect result, res in C flag only
+static void h8_bor8(h83xx_state *h8, UINT8 src, UINT8 dst)
+{
+ dst >>= src;
+ dst &= 0x1;
+ h8->h8cflag |= dst;
+}
+
+// does not affect result, res in C flag only
+static void h8_band8(h83xx_state *h8, UINT8 src, UINT8 dst)
+{
+ dst >>= src;
+ dst &= 0x1;
+ h8->h8cflag &= dst;
+}
+
+// does not affect result, res in C flag only
+static void h8_bxor8(h83xx_state *h8, UINT8 src, UINT8 dst)
+{
+ dst >>= src;
+ dst &= 0x1;
+ h8->h8cflag ^= dst;
+}
+
+static UINT8 h8_bclr8(h83xx_state *h8, UINT8 src, UINT8 dst)
+{
+ // pass
+ UINT8 res;
+ res = dst & ~(1<<src);
+ return res;
+}
+
+static INT8 h8_neg8(h83xx_state *h8, INT8 src)
+{
+ INT8 res;
+
+ if((UINT8)src == 0x80)
+ {
+ // overflow !
+ h8->h8vflag = 1;
+ res = (INT8)0x80;
+ }
+ else
+ {
+ h8->h8vflag = 0;
+ res = 0-src;
+ }
+
+ // N and Z modified
+ h8->h8nflag = (res>>7) & 1;
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ h8->h8hflag = ((src|res)&0x08) ? 1 : 0;
+ h8->h8cflag = ((src|res)&0x80) ? 1 : 0;
+
+ return res;
+}
+
+static INT16 h8_neg16(h83xx_state *h8, INT16 src)
+{
+ INT16 res;
+
+ if((UINT16)src == 0x8000)
+ {
+ // overflow !
+ h8->h8vflag = 1;
+ res = (INT16)0x8000;
+ }
+ else
+ {
+ h8->h8vflag = 0;
+ res = 0-src;
+ }
+
+ // N and Z modified
+ h8->h8nflag = (res>>15) & 1;
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ h8->h8hflag = ((src|res)&0x0800) ? 1 : 0;
+ h8->h8cflag = ((src|res)&0x8000) ? 1 : 0;
+
+ return res;
+}
+
+static INT32 h8_neg32(h83xx_state *h8, INT32 src)
+{
+ INT32 res;
+
+ if((UINT32)src == 0x80000000)
+ {
+ // overflow !
+ h8->h8vflag = 1;
+ res = 0x80000000;
+ }
+ else
+ {
+ h8->h8vflag = 0;
+ res = 0-src;
+ }
+
+ // N and Z modified
+ h8->h8nflag = (res>>31) & 1;
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ h8->h8hflag = ((src|res)&0x08000000) ? 1 : 0;
+ h8->h8cflag = ((src|res)&0x80000000) ? 1 : 0;
+
+ return res;
+}
+
+static UINT8 h8_not8(h83xx_state *h8, UINT8 src)
+{
+ UINT8 res;
+
+ res = ~src;
+
+ // N and Z modified
+ h8->h8nflag = (res>>7) & 1;
+ h8->h8vflag = 0;
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static UINT16 h8_not16(h83xx_state *h8, UINT16 src)
+{
+ UINT16 res;
+
+ res = ~src;
+
+ // N and Z modified
+ h8->h8nflag = (res>>15) & 1;
+ h8->h8vflag = 0;
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static UINT32 h8_not32(h83xx_state *h8, UINT32 src)
+{
+ UINT32 res;
+
+ res = ~src;
+
+ // N and Z modified
+ h8->h8nflag = (res>>31) & 1;
+ h8->h8vflag = 0;
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static UINT8 h8_rotxr8(h83xx_state *h8, UINT8 src)
+{
+ UINT8 res;
+
+ // rotate through carry right
+ res = src>>1;
+ if(h8->h8cflag)res |= 0x80; // put cflag in upper bit
+ h8->h8cflag = src & 1;
+
+ // N and Z modified
+ h8->h8nflag = (res>>7) & 1;
+ h8->h8vflag = 0;
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static UINT8 h8_rotr8(h83xx_state *h8, UINT8 src)
+{
+ UINT8 res;
+
+ // rotate right, not through carry
+ res = src>>1;
+ if (src & 1) res |= 0x80; // put cflag in upper bit
+ h8->h8cflag = src & 1;
+
+ // N and Z modified
+ h8->h8nflag = (res>>7) & 1;
+ h8->h8vflag = 0;
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static UINT16 h8_rotr16(h83xx_state *h8, UINT16 src)
+{
+ UINT16 res;
+
+ // rotate right, not through carry
+ res = src>>1;
+ if (src & 1) res |= 0x8000; // put cflag in upper bit
+ h8->h8cflag = src & 1;
+
+ // N and Z modified
+ h8->h8nflag = (res>>15) & 1;
+ h8->h8vflag = 0;
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static UINT32 h8_rotr32(h83xx_state *h8, UINT32 src)
+{
+ UINT32 res;
+
+ // rotate right, not through carry
+ res = src>>1;
+ if (src & 1) res |= 0x80000000; // put cflag in upper bit
+ h8->h8cflag = src & 1;
+
+ // N and Z modified
+ h8->h8nflag = (res>>31) & 1;
+ h8->h8vflag = 0;
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static UINT16 h8_rotxr16(h83xx_state *h8, UINT16 src)
+{
+ UINT16 res;
+
+ // rotate through carry right
+ res = src>>1;
+ if(h8->h8cflag)res |= 0x8000; // put cflag in upper bit
+ h8->h8cflag = src & 1;
+
+ // N and Z modified
+ h8->h8nflag = (res>>15) & 1;
+ h8->h8vflag = 0;
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static UINT32 h8_rotxr32(h83xx_state *h8, UINT32 src)
+{
+ UINT32 res;
+
+ // rotate through carry right
+ res = src>>1;
+ if(h8->h8cflag)res |= 0x80000000; // put cflag in upper bit
+ h8->h8cflag = src & 1;
+
+ // N and Z modified
+ h8->h8nflag = (res>>31) & 1;
+ h8->h8vflag = 0;
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static UINT8 h8_rotxl8(h83xx_state *h8, UINT8 src)
+{
+ UINT8 res;
+
+ // rotate through carry
+ res = src<<1;
+ res |= (h8->h8cflag & 1);
+ h8->h8cflag = (src>>7) & 1;
+
+ // N and Z modified
+ h8->h8nflag = (res>>7) & 1;
+ h8->h8vflag = 0;
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static UINT16 h8_rotxl16(h83xx_state *h8, UINT16 src)
+{
+ UINT16 res;
+
+ // rotate through carry
+ res = src<<1;
+ res |= (h8->h8cflag & 1);
+ h8->h8cflag = (src>>15) & 1;
+
+ // N and Z modified
+ h8->h8nflag = (res>>15) & 1;
+ h8->h8vflag = 0;
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static UINT32 h8_rotxl32(h83xx_state *h8, UINT32 src)
+{
+ UINT32 res;
+
+ // rotate through carry
+ res = src<<1;
+ res |= (h8->h8cflag & 1);
+ h8->h8cflag = (src>>31) & 1;
+
+ // N and Z modified
+ h8->h8nflag = (res>>31) & 1;
+ h8->h8vflag = 0;
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+
+static UINT8 h8_rotl8(h83xx_state *h8, UINT8 src)
+{
+ UINT8 res;
+
+ // rotate
+ res = src<<1;
+ h8->h8cflag = (src>>7) & 1;
+ res |= (h8->h8cflag & 1);
+
+ // N and Z modified
+ h8->h8nflag = (res>>7) & 1;
+ h8->h8vflag = 0;
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static UINT16 h8_rotl16(h83xx_state *h8, UINT16 src)
+{
+ UINT16 res;
+
+ // rotate
+ res = src<<1;
+ h8->h8cflag = (src>>15) & 1;
+ res |= (h8->h8cflag & 1);
+
+ // N and Z modified
+ h8->h8nflag = (res>>15) & 1;
+ h8->h8vflag = 0;
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static UINT32 h8_rotl32(h83xx_state *h8, UINT32 src)
+{
+ UINT32 res;
+
+ // rotate
+ res = src<<1;
+ h8->h8cflag = (src>>31) & 1;
+ res |= (h8->h8cflag & 1);
+
+ // N and Z modified
+ h8->h8nflag = (res>>31) & 1;
+ h8->h8vflag = 0;
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static UINT8 h8_shll8(h83xx_state *h8, UINT8 src)
+{
+ UINT8 res;
+ h8->h8cflag = (src>>7) & 1;
+ res = src<<1;
+ // N and Z modified
+ h8->h8nflag = (res>>7) & 1;
+ h8->h8vflag = 0;
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static UINT16 h8_shll16(h83xx_state *h8, UINT16 src)
+{
+ UINT16 res;
+ h8->h8cflag = (src>>15) & 1;
+ res = src<<1;
+ // N and Z modified
+ h8->h8nflag = (res>>15) & 1;
+ h8->h8vflag = 0;
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static UINT32 h8_shll32(h83xx_state *h8, UINT32 src)
+{
+ UINT32 res;
+ h8->h8cflag = (src>>31) & 1;
+ res = src<<1;
+ // N and Z modified
+ h8->h8nflag = (res>>31) & 1;
+ h8->h8vflag = 0;
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static UINT8 h8_shlr8(h83xx_state *h8, UINT8 src)
+{
+ UINT8 res;
+ h8->h8cflag = src&1;
+ res = src>>1;
+ // N and Z modified
+ h8->h8nflag = 0;
+ h8->h8vflag = 0;
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static UINT16 h8_shlr16(h83xx_state *h8, UINT16 src)
+{
+ UINT16 res;
+ h8->h8cflag = src&1;
+ res = src>>1;
+ // N and Z modified
+ h8->h8nflag = 0;
+ h8->h8vflag = 0;
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static UINT32 h8_shlr32(h83xx_state *h8, UINT32 src)
+{
+ UINT32 res;
+ h8->h8cflag = src&1;
+ res = src>>1;
+
+ // N and Z modified, V always cleared
+ h8->h8nflag = 0;
+ h8->h8vflag = 0;
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static INT8 h8_shar8(h83xx_state *h8, INT8 src)
+{
+ INT8 res;
+ h8->h8cflag = src&1;
+ res = (src>>1)|(src&0x80);
+ // N and Z modified
+ h8->h8nflag = (res>>7)&1;
+ h8->h8vflag = 0;
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static INT16 h8_shar16(h83xx_state *h8, INT16 src)
+{
+ INT16 res;
+ h8->h8cflag = src&1;
+ res = (src>>1)|(src&0x8000);
+ // N and Z modified
+ h8->h8nflag = (res>>15)&1;
+ h8->h8vflag = 0;
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static INT32 h8_shar32(h83xx_state *h8, INT32 src)
+{
+ INT32 res;
+
+ h8->h8cflag = src&1;
+ res = (src>>1)|(src&0x80000000);
+ // N and Z modified
+ h8->h8nflag = (res>>31) & 1;
+ h8->h8vflag = 0;
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static INT8 h8_shal8(h83xx_state *h8, INT8 src)
+{
+ INT8 res;
+
+ h8->h8cflag = (src>>7)&1;
+ res = src<<1;
+ // N and Z modified
+ h8->h8nflag = (res>>7)&1;
+ h8->h8vflag = (src ^ res) >> 7;
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static INT16 h8_shal16(h83xx_state *h8, INT16 src)
+{
+ INT16 res;
+
+ h8->h8cflag = (src>>15)&1;
+ res = src<<1;
+ // N and Z modified
+ h8->h8nflag = (res>>15)&1;
+ h8->h8vflag = (src ^ res) >> 15;
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static INT32 h8_shal32(h83xx_state *h8, INT32 src)
+{
+ INT32 res;
+
+ h8->h8cflag = (src>>31)&1;
+ res = src<<1;
+ // N and Z modified
+ h8->h8nflag = (res>>31)&1;
+ h8->h8vflag = (src ^ res) >> 31;
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static UINT8 h8_dec8(h83xx_state *h8, UINT8 src)
+{
+ UINT8 res;
+
+ res = src - 1;
+ // N and Z modified
+ h8->h8nflag = (res>>7)&1;
+ if(src == 0x80)
+ {
+ h8->h8vflag = 1;
+ }
+ else
+ {
+ h8->h8vflag = 0;
+ }
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static UINT16 h8_dec16(h83xx_state *h8, UINT16 src)
+{
+ UINT16 res;
+
+ res = src - 1;
+ // N and Z modified
+ h8->h8nflag = (res>>15)&1;
+ if(src == 0x8000)
+ {
+ h8->h8vflag = 1;
+ }
+ else
+ {
+ h8->h8vflag = 0;
+ }
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static UINT32 h8_dec32(h83xx_state *h8, UINT32 src)
+{
+ UINT32 res;
+
+ res = src - 1;
+ // N and Z modified
+ h8->h8nflag = (res>>31)&1;
+ if(src == 0x80000000)
+ {
+ h8->h8vflag = 1;
+ }
+ else
+ {
+ h8->h8vflag = 0;
+ }
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static UINT8 h8_inc8(h83xx_state *h8, UINT8 src)
+{
+ UINT8 res;
+
+ res = src + 1;
+ // N and Z modified
+ h8->h8nflag = (res>>7)&1;
+ if(src == 0x7f)
+ {
+ h8->h8vflag = 1;
+ }
+ else
+ {
+ h8->h8vflag = 0;
+ }
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static UINT16 h8_inc16(h83xx_state *h8, UINT16 src)
+{
+ UINT16 res;
+
+ res = src + 1;
+ // N and Z modified
+ h8->h8nflag = (res>>15)&1;
+ if(src == 0x7fff)
+ {
+ h8->h8vflag = 1;
+ }
+ else
+ {
+ h8->h8vflag = 0;
+ }
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static UINT32 h8_inc32(h83xx_state *h8, UINT32 src)
+{
+ UINT32 res;
+
+ res = src + 1;
+ // N and Z modified
+ h8->h8nflag = (res>>31)&1;
+ if(src == 0x7fffffff)
+ {
+ h8->h8vflag = 1;
+ }
+ else
+ {
+ h8->h8vflag = 0;
+ }
+
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+
+ return res;
+}
+
+static INT16 h8_mulxs8(h83xx_state *h8, INT8 src, INT8 dst)
+{
+ INT16 res;
+
+ res = (INT16)src * dst;
+
+ // N and Z modified
+ h8->h8nflag = (res>>31)&1;
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+ return res;
+}
+
+static INT32 h8_mulxs16(h83xx_state *h8, INT16 src, INT16 dst)
+{
+ INT32 res;
+
+ res = (INT32)src * dst;
+
+ // N and Z modified
+ h8->h8nflag = (res>>31)&1;
+ // zflag
+ if(res==0)
+ {
+ h8->h8zflag = 1;
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ }
+ return res;
+}
+
+static UINT16 h8_divxs8(h83xx_state *h8, INT8 src, INT16 dst)
+{
+ // NOT tested !
+ UINT16 res,r1,r2;
+ INT8 remainder, quotient;
+
+ if(src!=0)
+ {
+ quotient = dst/src;
+ h8->h8zflag = 0;
+ }
+ else
+ {
+ quotient = 0;
+ h8->h8zflag = 1;
+ }
+ remainder = dst%src;
+
+ r1=*(&quotient);
+ r2=*(&remainder);
+ res=(r2<<8)|r1;
+
+ h8->h8nflag = (quotient<0)?1:0;
+
+ return res;
+}
+
+static UINT32 h8_divxs16(h83xx_state *h8, INT16 src, INT32 dst)
+{
+ // NOT tested !
+ UINT32 res,r1,r2;
+ INT16 remainder, quotient;
+
+ if(src!=0)
+ {
+ quotient = dst/src;
+ h8->h8zflag = 0;
+ }
+ else
+ {
+ quotient = 0;
+ h8->h8zflag = 1;
+ }
+ remainder = dst%src;
+
+ r1=*(&quotient);
+ r2=*(&remainder);
+ res=(r2<<16)|r1;
+
+ h8->h8nflag = (quotient<0)?1:0;
+
+ return res;
+}
+
+static UINT16 h8_divxu8(h83xx_state *h8, UINT16 dst, UINT8 src)
+{
+ UINT8 remainder, quotient;
+ UINT16 res = 0;
+ // N and Z modified
+ h8->h8nflag = (src>>7)&1;
+ // zflag
+ if(src==0)
+ {
+ h8->h8zflag = 1;
+ // dont do anything on division by zero !
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ quotient = dst / src;
+ remainder = dst % src;
+ res = (remainder << 8) | quotient;
+ }
+ return res;
+}
+
+static UINT32 h8_divxu16(h83xx_state *h8, UINT32 dst, UINT16 src)
+{
+ UINT16 remainder, quotient;
+ UINT32 res = 0;
+ // N and Z modified
+ h8->h8nflag = (src>>15)&1;
+ // zflag
+ if(src==0)
+ {
+ h8->h8zflag = 1;
+ // dont do anything on division by zero !
+ }
+ else
+ {
+ h8->h8zflag = 0;
+ quotient = dst / src;
+ remainder = dst % src;
+ res = (remainder << 16) | quotient;
+ }
+ return res;
+}
+
+// input: branch condition
+// output: 1 if condition met, 0 if not condition met
+static int h8_branch(h83xx_state *h8, UINT8 condition)
+{
+ int taken = 0;
+
+ // a branch always eats 2 ifetch states, regardless of if it's taken
+ H8_IFETCH_TIMING(2)
+
+ switch(condition)
+ {
+ case 0: // bt
+ taken = 1;
+ break;
+ case 1: // bf
+ break;
+ case 2: // bhi (C | Z) == 0)
+ if((h8->h8cflag | h8->h8zflag) == 0)taken = 1;
+ break;
+ case 3: // bls
+ if((h8->h8cflag | h8->h8zflag) == 1)taken = 1;
+ break;
+ case 4: // bcc C = 0
+ if(h8->h8cflag == 0)taken = 1;
+ break;
+ case 5: // bcs C = 1
+ if(h8->h8cflag == 1)taken = 1;
+ break;
+ case 6: // bne Z = 0
+ if(h8->h8zflag == 0)taken = 1;
+ break;
+ case 7: // beq Z = 1
+ if(h8->h8zflag == 1)taken = 1;
+ break;
+ case 8: // bvc V = 0
+ h8->h8err = 1;
+ if(h8->h8vflag == 0)taken = 1;
+ break;
+ case 9: // bvs V = 1
+ h8->h8err = 1;
+ if(h8->h8vflag == 1)taken = 1;
+ break;
+ case 0xa: // bpl N = 0
+ if(h8->h8nflag == 0)taken = 1;
+ break;
+ case 0xb: // bmi N = 1
+ if(h8->h8nflag == 1)taken = 1;
+ break;
+ case 0xc: // bge (N ^ V) = 0
+ if((h8->h8nflag ^ h8->h8vflag) == 0)taken = 1;
+ break;
+ case 0xd: // blt (N ^ V) = 1
+ if((h8->h8nflag ^ h8->h8vflag) == 1)taken = 1;
+ break;
+ case 0xe: // bgt (Z | (N ^ V)) = 0
+ if((h8->h8zflag | (h8->h8nflag ^ h8->h8vflag)) == 0)taken = 1;
+ break;
+ case 0xf: // ble (Z | (N ^ V)) = 1
+ if((h8->h8zflag | (h8->h8nflag ^ h8->h8vflag)) == 1)taken = 1;
+ break;
+ }
+ return taken;
+}
+
diff --git a/trunk/src/emu/cpu/h83002/h8periph.c b/trunk/src/emu/cpu/h83002/h8periph.c
new file mode 100644
index 00000000000..ec12f2c7a26
--- /dev/null
+++ b/trunk/src/emu/cpu/h83002/h8periph.c
@@ -0,0 +1,794 @@
+/***************************************************************************
+
+ h8periph.c: Implementation of Hitachi H8/3002 on-board MCU functions.
+
+ Original by The_Author & DynaChicken for the ZiNc emulator.
+
+ Rewritten for MAME to use MAME timers and other facilities by R. Belmont
+
+****************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "h8.h"
+#include "h8priv.h"
+
+#define H8_REG_START (0x00ffff10)
+
+// timer registers
+#define TSTR (0x60)
+#define TIER0 (0x66)
+#define TIER1 (0x70)
+#define TIER2 (0x7a)
+#define TIER3 (0x84)
+#define TIER4 (0x94)
+#define TSR0 (0x67)
+#define TSR1 (0x71)
+#define TSR2 (0x7b)
+#define TSR3 (0x85)
+#define TSR4 (0x95)
+#define TCR0 (0x64)
+#define TCR1 (0x6e)
+#define TCR2 (0x78)
+#define TCR3 (0x82)
+#define TCR4 (0x92)
+
+static const UINT8 tsr[5] = { TSR0, TSR1, TSR2, TSR3, TSR4 };
+static const UINT8 tier[5] = { TIER0, TIER1, TIER2, TIER3, TIER4 };
+static const UINT8 tcr[5] = { TCR0, TCR1, TCR2, TCR3, TCR4 };
+static const int tscales[4] = { 1, 2, 4, 8 };
+
+extern void h8_3002_InterruptRequest(h83xx_state *h8, UINT8 source, UINT8 state);
+
+static void h8itu_timer_expire(h83xx_state *h8, int which)
+{
+ h8->timer[which]->adjust(attotime::never);
+ h8->h8TCNT[which] = 0;
+ h8->per_regs[tsr[which]] |= 4;
+ // interrupt on overflow ?
+ if(h8->per_regs[tier[which]] & 4)
+ {
+ h8_3002_InterruptRequest(h8, 26 + 4*which, 1);
+ }
+}
+
+static TIMER_CALLBACK( h8itu_timer_0_cb )
+{
+ h83xx_state *h8 = (h83xx_state *)ptr;
+
+ h8itu_timer_expire(h8, 0);
+}
+
+static TIMER_CALLBACK( h8itu_timer_1_cb )
+{
+ h83xx_state *h8 = (h83xx_state *)ptr;
+
+ h8itu_timer_expire(h8, 1);
+}
+
+static TIMER_CALLBACK( h8itu_timer_2_cb )
+{
+ h83xx_state *h8 = (h83xx_state *)ptr;
+
+ h8itu_timer_expire(h8, 2);
+}
+
+static TIMER_CALLBACK( h8itu_timer_3_cb )
+{
+ h83xx_state *h8 = (h83xx_state *)ptr;
+
+ h8itu_timer_expire(h8, 3);
+}
+
+static TIMER_CALLBACK( h8itu_timer_4_cb )
+{
+ h83xx_state *h8 = (h83xx_state *)ptr;
+
+ h8itu_timer_expire(h8, 4);
+}
+
+static void h8_itu_refresh_timer(h83xx_state *h8, int tnum)
+{
+ int ourTCR = 0;
+ int ourTVAL = 0;
+ attotime period;
+
+ ourTCR = h8->per_regs[tcr[tnum]];
+ ourTVAL = h8->h8TCNT[tnum];
+
+ period = attotime::from_hz(h8->device->unscaled_clock()) * tscales[ourTCR & 3] * (65536 - ourTVAL);
+
+ if (ourTCR & 4)
+ {
+ logerror("H8/3002: Timer %d is using an external clock. Unsupported!\n", tnum);
+ }
+
+ h8->timer[tnum]->adjust(period);
+}
+
+static void h8_itu_sync_timers(h83xx_state *h8, int tnum)
+{
+ int ourTCR = 0;
+ attotime cycle_time, cur;
+ UINT16 ratio;
+
+ ourTCR = h8->per_regs[tcr[tnum]];
+
+ // get the time per unit
+ cycle_time = attotime::from_hz(h8->device->unscaled_clock()) * tscales[ourTCR & 3];
+ cur = h8->timer[tnum]->elapsed();
+
+ ratio = cur.as_double() / cycle_time.as_double();
+
+ h8->h8TCNT[tnum] = ratio;
+}
+
+UINT8 h8_itu_read8(h83xx_state *h8, UINT8 reg)
+{
+ UINT8 val;
+
+ switch(reg)
+ {
+ case 0x60:
+ val = h8->h8TSTR;
+ break;
+ case 0x68:
+ h8_itu_sync_timers(h8, 0);
+ val = h8->h8TCNT[0]>>8;
+ break;
+ case 0x69:
+ h8_itu_sync_timers(h8, 0);
+ val = h8->h8TCNT[0]&0xff;
+ break;
+ case 0x72:
+ h8_itu_sync_timers(h8, 1);
+ val = h8->h8TCNT[1]>>8;
+ break;
+ case 0x73:
+ h8_itu_sync_timers(h8, 1);
+ val = h8->h8TCNT[1]&0xff;
+ break;
+ case 0x7c:
+ h8_itu_sync_timers(h8, 2);
+ val = h8->h8TCNT[2]>>8;
+ break;
+ case 0x7d:
+ h8_itu_sync_timers(h8, 2);
+ val = h8->h8TCNT[2]&0xff;
+ break;
+ case 0x86:
+ h8_itu_sync_timers(h8, 3);
+ val = h8->h8TCNT[3]>>8;
+ break;
+ case 0x87:
+ h8_itu_sync_timers(h8, 3);
+ val = h8->h8TCNT[3]&0xff;
+ break;
+ default:
+ val = h8->per_regs[reg];
+ break;
+ }
+
+
+ return val;
+}
+
+void h8_itu_write8(h83xx_state *h8, UINT8 reg, UINT8 val)
+{
+ h8->per_regs[reg] = val;
+ switch(reg)
+ {
+ case 0x60:
+ if ((val & 1) && !(h8->h8TSTR & 1))
+ {
+ h8_itu_refresh_timer(h8, 0);
+ }
+ if ((val & 2) && !(h8->h8TSTR & 2))
+ {
+ h8_itu_refresh_timer(h8, 1);
+ }
+ if ((val & 4) && !(h8->h8TSTR & 4))
+ {
+ h8_itu_refresh_timer(h8, 2);
+ }
+ if ((val & 8) && !(h8->h8TSTR & 8))
+ {
+ h8_itu_refresh_timer(h8, 3);
+ }
+ if ((val & 0x10) && !(h8->h8TSTR & 0x10))
+ {
+ h8_itu_refresh_timer(h8, 4);
+ }
+ h8->h8TSTR = val;
+ break;
+ case 0x68:
+ h8->h8TCNT[0] = (val<<8) | (h8->h8TCNT[0] & 0xff);
+ if (h8->h8TSTR & 1)
+ {
+ h8_itu_refresh_timer(h8, 0);
+ }
+ break;
+ case 0x69:
+ h8->h8TCNT[0] = (val) | (h8->h8TCNT[0] & 0xff00);
+ if (h8->h8TSTR & 1)
+ {
+ h8_itu_refresh_timer(h8, 0);
+ }
+ break;
+ case 0x72:
+ h8->h8TCNT[1] = (val<<8) | (h8->h8TCNT[1] & 0xff);
+ if (h8->h8TSTR & 2)
+ {
+ h8_itu_refresh_timer(h8, 1);
+ }
+ break;
+ case 0x73:
+ h8->h8TCNT[1] = (val) | (h8->h8TCNT[1] & 0xff00);
+ if (h8->h8TSTR & 2)
+ {
+ h8_itu_refresh_timer(h8, 1);
+ }
+ break;
+ case 0x7c:
+ h8->h8TCNT[2] = (val<<8) | (h8->h8TCNT[2] & 0xff);
+ if (h8->h8TSTR & 4)
+ {
+ h8_itu_refresh_timer(h8, 2);
+ }
+ break;
+ case 0x7d:
+ h8->h8TCNT[2] = (val) | (h8->h8TCNT[2] & 0xff00);
+ if (h8->h8TSTR & 4)
+ {
+ h8_itu_refresh_timer(h8, 2);
+ }
+ break;
+ case 0x86:
+ h8->h8TCNT[3] = (val<<8) | (h8->h8TCNT[3] & 0xff);
+ if (h8->h8TSTR & 8)
+ {
+ h8_itu_refresh_timer(h8, 3);
+ }
+ break;
+ case 0x87:
+ h8->h8TCNT[3] = (val) | (h8->h8TCNT[3] & 0xff00);
+ if (h8->h8TSTR & 8)
+ {
+ h8_itu_refresh_timer(h8, 3);
+ }
+ break;
+ case 0x96:
+ h8->h8TCNT[4] = (val<<8) | (h8->h8TCNT[4] & 0xff);
+ if (h8->h8TSTR & 0x10)
+ {
+ h8_itu_refresh_timer(h8, 4);
+ }
+ break;
+ case 0x97:
+ h8->h8TCNT[4] = (val) | (h8->h8TCNT[4] & 0xff00);
+ if (h8->h8TSTR & 0x10)
+ {
+ h8_itu_refresh_timer(h8, 4);
+ }
+ break;
+ default:
+ val = 0;
+ break;
+ }
+}
+
+#ifdef UNUSED_FUNCTION
+UINT8 h8_debugger_itu_read8(UINT8 reg)
+{
+ UINT8 val;
+ val = 0;
+ return val;
+}
+#endif
+
+
+static UINT8 h8_ISR_r(h83xx_state *h8)
+{
+ UINT8 res = 0;
+
+ int i;
+ for (i = 0; i < 6; i++)
+ if (h8->irq_req[0] & (1 << (12+i))) res |= (1 << i);
+
+ return res;
+}
+
+static void h8_ISR_w(h83xx_state *h8, UINT8 val)
+{
+ int i;
+ for (i = 0; i < 6; i++)
+ if ((~val) & (1 << i)) h8->irq_req[0] &= ~(1 << (12+i));
+}
+
+
+UINT8 h8_register_read8(h83xx_state *h8, UINT32 address)
+{
+ UINT8 val;
+ UINT8 reg;
+
+ address &= 0xffffff;
+
+ reg = address & 0xff;
+
+ if(reg >= 0x60 && reg <= 0x9f)
+ {
+ return h8_itu_read8(h8, reg);
+ }
+ else
+ {
+ switch(reg)
+ {
+ case 0xb4: // serial port A status
+ val = h8->per_regs[reg];
+ val |= 0xc4; // transmit finished, receive ready, no errors
+ break;
+ case 0xb5: // serial port A receive
+ val = h8->io->read_byte(H8_SERIAL_0);
+ break;
+ case 0xbc: // serial port B status
+ val = h8->per_regs[reg];
+ val |= 0xc4; // transmit finished, receive ready, no errors
+ break;
+ case 0xbd: // serial port B receive
+ val = h8->io->read_byte(H8_SERIAL_1);
+ break;
+ case 0xe0:
+ val = h8->io->read_byte(H8_ADC_0_H);
+ break;
+ case 0xe1:
+ val = h8->io->read_byte(H8_ADC_0_L);
+ break;
+ case 0xe2:
+ val = h8->io->read_byte(H8_ADC_1_H);
+ break;
+ case 0xe3:
+ val = h8->io->read_byte(H8_ADC_1_L);
+ break;
+ case 0xe4:
+ val = h8->io->read_byte(H8_ADC_2_H);
+ break;
+ case 0xe5:
+ val = h8->io->read_byte(H8_ADC_2_L);
+ break;
+ case 0xe6:
+ val = h8->io->read_byte(H8_ADC_3_H);
+ break;
+ case 0xe7:
+ val = h8->io->read_byte(H8_ADC_3_L);
+ break;
+ case 0xe8: // adc status
+ val = 0x80;
+ break;
+ case 0xc7: // port 4 data
+ val = h8->io->read_byte(H8_PORT_4);
+ break;
+ case 0xcb: // port 6 data
+ val = h8->io->read_byte(H8_PORT_6);
+ break;
+ case 0xce: // port 7 data
+ val = h8->io->read_byte(H8_PORT_7);
+ break;
+ case 0xcf: // port 8 data
+ val = h8->io->read_byte(H8_PORT_8);
+ break;
+ case 0xd2: // port 9 data
+ val = h8->io->read_byte(H8_PORT_9);
+ break;
+ case 0xd3: // port a data
+ val = h8->io->read_byte(H8_PORT_A);
+ break;
+ case 0xd6: // port b data
+ val = h8->io->read_byte(H8_PORT_B);
+ break;
+ case 0xf6:
+ val = h8_ISR_r(h8);
+ break;
+
+ default:
+ val = h8->per_regs[reg];
+ break;
+ }
+ }
+
+ return val;
+}
+
+void h8_register_write8(h83xx_state *h8, UINT32 address, UINT8 val)
+{
+ UINT8 reg;
+
+ address &= 0xffffff;
+
+ reg = address & 0xff;
+
+ if(reg >= 0x60 && reg <= 0x9f)
+ {
+ h8_itu_write8(h8, reg, val);
+ }
+
+ switch (reg)
+ {
+ case 0xb3: // serial 0 send
+ h8->io->write_byte(H8_SERIAL_0, val);
+ h8_3002_InterruptRequest(h8, 54, 1);
+ h8_3002_InterruptRequest(h8, 55, 1);
+ break;
+ case 0xbb: // serial 1 send
+ h8->io->write_byte(H8_SERIAL_1, val);
+ h8_3002_InterruptRequest(h8, 58, 1);
+ h8_3002_InterruptRequest(h8, 59, 1);
+ break;
+ case 0xc7:
+ h8->io->write_byte(H8_PORT_4, val);
+ break;
+ case 0xcb: // port 6 data
+ h8->io->write_byte(H8_PORT_6, val);
+ break;
+ case 0xce: // port 7 data
+ h8->io->write_byte(H8_PORT_7, val);
+ break;
+ case 0xcf: // port 8 data
+ h8->io->write_byte(H8_PORT_8, val);
+ break;
+ case 0xd2: // port 9 data
+ h8->io->write_byte(H8_PORT_9, val);
+ break;
+ case 0xd3: // port a data
+ h8->io->write_byte(H8_PORT_A, val);
+ break;
+ case 0xd6: // port b data
+ h8->io->write_byte(H8_PORT_B, val);
+ break;
+ case 0xf6:
+ h8_ISR_w(h8, val);
+ break;
+ }
+
+ h8->per_regs[reg] = val;
+}
+
+static void h8_3007_itu_refresh_timer(h83xx_state *h8, int tnum)
+{
+ attotime period;
+ int ourTCR = h8->per_regs[0x68+(tnum*8)];
+
+ period = attotime::from_hz(h8->device->unscaled_clock()) * tscales[ourTCR & 3];
+
+ if (ourTCR & 4)
+ {
+ logerror("H8/3007: Timer %d is using an external clock. Unsupported!\n", tnum);
+ }
+
+ h8->timer[tnum]->adjust(period);
+}
+
+static void h8itu_3007_timer_expire(h83xx_state *h8, int tnum)
+{
+ int base = 0x68 + (tnum*8);
+ UINT16 count;
+
+ count = (h8->per_regs[base + 0x2]<<8) | h8->per_regs[base + 0x3];
+ count++;
+
+ //logerror("h8/3007 timer %d count = %04x\n",tnum,count);
+
+ // GRA match
+ if ((h8->per_regs[base + 0x1] & 0x03) && (count == ((h8->per_regs[base + 0x4]<<8) | h8->per_regs[base + 0x5])))
+ {
+ if ((h8->per_regs[base + 0x0] & 0x60) == 0x20)
+ {
+ //logerror("h8/3007 timer %d GRA match, restarting\n",tnum);
+ count = 0;
+ h8_3007_itu_refresh_timer(h8, tnum);
+ }
+ else
+ {
+ //logerror("h8/3007 timer %d GRA match, stopping\n",tnum);
+ h8->timer[tnum]->adjust(attotime::never);
+ }
+
+ h8->per_regs[0x64] |= 1<<tnum;
+ if(h8->per_regs[0x64] & (4<<tnum)) // interrupt enable
+ {
+ //logerror("h8/3007 timer %d GRA INTERRUPT\n",tnum);
+ h8_3002_InterruptRequest(h8, 24+tnum*4, 1);
+ }
+ }
+ // GRB match
+ if ((h8->per_regs[base + 0x1] & 0x30) && (count == ((h8->per_regs[base + 0x6]<<8) | h8->per_regs[base + 0x7])))
+ {
+ if ((h8->per_regs[base + 0x0] & 0x60) == 0x40)
+ {
+ //logerror("h8/3007 timer %d GRB match, restarting\n",tnum);
+ count = 0;
+ h8_3007_itu_refresh_timer(h8, tnum);
+ }
+ else
+ {
+ //logerror("h8/3007 timer %d GRB match, stopping\n",tnum);
+ h8->timer[tnum]->adjust(attotime::never);
+ }
+
+ h8->per_regs[0x65] |= 1<<tnum;
+ if(h8->per_regs[0x65] & (4<<tnum)) // interrupt enable
+ {
+ //logerror("h8/3007 timer %d GRB INTERRUPT\n",tnum);
+ h8_3002_InterruptRequest(h8, 25+tnum*4, 1);
+ }
+ }
+ // Overflow
+ if (((h8->per_regs[base + 0x1] & 0x33) == 0) && (count == 0))
+ {
+ //logerror("h8/3007 timer %d OVF match, restarting\n",tnum);
+ h8->per_regs[0x66] |= 1<<tnum;
+ if(h8->per_regs[0x66] & (4<<tnum)) // interrupt enable
+ {
+ //logerror("h8/3007 timer %d OVF INTERRUPT\n",tnum);
+ h8_3002_InterruptRequest(h8, 26+tnum*4, 1);
+ }
+ }
+
+ h8->per_regs[base + 0x2] = count >> 8;
+ h8->per_regs[base + 0x3] = count & 0xff;
+}
+
+static TIMER_CALLBACK( h8itu_3007_timer_0_cb )
+{
+ h83xx_state *h8 = (h83xx_state *)ptr;
+
+ h8itu_3007_timer_expire(h8, 0);
+}
+
+static TIMER_CALLBACK( h8itu_3007_timer_1_cb )
+{
+ h83xx_state *h8 = (h83xx_state *)ptr;
+
+ h8itu_3007_timer_expire(h8, 1);
+}
+
+static TIMER_CALLBACK( h8itu_3007_timer_2_cb )
+{
+ h83xx_state *h8 = (h83xx_state *)ptr;
+
+ h8itu_3007_timer_expire(h8, 2);
+}
+
+UINT8 h8_3007_itu_read8(h83xx_state *h8, UINT8 reg)
+{
+ UINT8 val;
+
+ switch(reg)
+ {
+ case 0x60:
+ val = h8->h8TSTR | 0xf8;
+ break;
+ default:
+ val = h8->per_regs[reg];
+ break;
+ }
+
+ return val;
+}
+
+void h8_3007_itu_write8(h83xx_state *h8, UINT8 reg, UINT8 val)
+{
+ logerror("%06x: h8/3007 reg %02x = %02x\n",h8->pc,reg,val);
+ h8->per_regs[reg] = val;
+ switch(reg)
+ {
+ case 0x60:
+ if ((val & 1) && !(h8->h8TSTR & 1))
+ {
+ h8_3007_itu_refresh_timer(h8, 0);
+ }
+ if ((val & 2) && !(h8->h8TSTR & 2))
+ {
+ h8_3007_itu_refresh_timer(h8, 1);
+ }
+ if ((val & 4) && !(h8->h8TSTR & 4))
+ {
+ h8_3007_itu_refresh_timer(h8, 2);
+ }
+ h8->h8TSTR = val;
+ break;
+ default:
+ val = 0;
+ break;
+ }
+}
+
+UINT8 h8_3007_register_read8(h83xx_state *h8, UINT32 address)
+{
+ UINT8 val;
+ UINT8 reg;
+
+ address &= 0xffffff;
+
+ reg = address & 0xff;
+
+ if(reg >= 0x60 && reg <= 0x7f)
+ {
+ return h8_3007_itu_read8(h8, reg);
+ }
+ else
+ {
+ switch(reg)
+ {
+ case 0xb4: // serial port A status
+ val = h8->per_regs[reg];
+ val |= 0xc4; // transmit finished, receive ready, no errors
+ break;
+ case 0xb5: // serial port A receive
+ val = h8->io->read_byte(H8_SERIAL_0);
+ break;
+ case 0xbc: // serial port B status
+ val = h8->per_regs[reg];
+ val |= 0xc4; // transmit finished, receive ready, no errors
+ break;
+ case 0xbd: // serial port B receive
+ val = h8->io->read_byte(H8_SERIAL_1);
+ break;
+ case 0xe0:
+ val = h8->io->read_byte(H8_ADC_0_H);
+ break;
+ case 0xe1:
+ val = h8->io->read_byte(H8_ADC_0_L);
+ break;
+ case 0xe2:
+ val = h8->io->read_byte(H8_ADC_1_H);
+ break;
+ case 0xe3:
+ val = h8->io->read_byte(H8_ADC_1_L);
+ break;
+ case 0xe4:
+ val = h8->io->read_byte(H8_ADC_2_H);
+ break;
+ case 0xe5:
+ val = h8->io->read_byte(H8_ADC_2_L);
+ break;
+ case 0xe6:
+ val = h8->io->read_byte(H8_ADC_3_H);
+ break;
+ case 0xe7:
+ val = h8->io->read_byte(H8_ADC_3_L);
+ break;
+ case 0xe8: // adc status
+ val = 0x80;
+ break;
+
+ case 0xd3: // port 4 data
+ val = h8->io->read_byte(H8_PORT_4);
+ break;
+ case 0xd5: // port 6 data
+ val = h8->io->read_byte(H8_PORT_6);
+ break;
+ case 0xd6: // port 7 data
+ val = h8->io->read_byte(H8_PORT_7);
+ break;
+ case 0xd7: // port 8 data
+ val = h8->io->read_byte(H8_PORT_8);
+ break;
+ case 0xd8: // port 9 data
+ val = h8->io->read_byte(H8_PORT_9);
+ break;
+ case 0xd9: // port a data
+ val = h8->io->read_byte(H8_PORT_A);
+ break;
+ case 0xda: // port b data
+ val = h8->io->read_byte(H8_PORT_B);
+ break;
+ default:
+ val = h8->per_regs[reg];
+ break;
+ }
+ }
+
+ return val;
+}
+
+void h8_3007_register_write8(h83xx_state *h8, UINT32 address, UINT8 val)
+{
+ UINT8 reg;
+
+ address &= 0xffffff;
+
+ reg = address & 0xff;
+
+ h8->per_regs[reg] = val;
+
+ if(reg >= 0x60 && reg <= 0x7f)
+ {
+ h8_3007_itu_write8(h8, reg, val);
+ }
+ else
+ {
+ switch (reg)
+ {
+ case 0xb3:
+ h8->io->write_byte(H8_SERIAL_0, val);
+ break;
+ case 0xbb:
+ h8->io->write_byte(H8_SERIAL_1, val);
+ break;
+ case 0xd3:
+ h8->io->write_byte(H8_PORT_4, val);
+ break;
+ case 0xd5: // port 6 data
+ h8->io->write_byte(H8_PORT_6, val);
+ break;
+ case 0xd6: // port 7 data
+ h8->io->write_byte(H8_PORT_7, val);
+ break;
+ case 0xd7: // port 8 data
+ h8->io->write_byte(H8_PORT_8, val);
+ break;
+ case 0xd8: // port 9 data
+ h8->io->write_byte(H8_PORT_9, val);
+ break;
+ case 0xd9: // port a data
+ h8->io->write_byte(H8_PORT_A, val);
+ break;
+ case 0xda: // port b data
+ h8->io->write_byte(H8_PORT_B, val);
+ break;
+ }
+ }
+}
+
+UINT8 h8_3007_register1_read8(h83xx_state *h8, UINT32 address)
+{
+ switch (address)
+ {
+ case 0xfee012: return h8->per_regs[0xF2]; // SYSCR
+ case 0xfee016: return h8_ISR_r(h8); // ISR
+ case 0xfee018: return h8->per_regs[0xF8]; // IPRA
+ }
+
+ logerror("cpu '%s' (PC=%08X): unmapped I/O(1) byte read from %08X\n",h8->device->tag(),h8->pc,address);
+ return 0;
+}
+
+void h8_3007_register1_write8(h83xx_state *h8, UINT32 address, UINT8 val)
+{
+ switch (address)
+ {
+ case 0xfee012: h8->per_regs[0xF2] = val; return; // SYSCR
+ case 0xfee016: h8_ISR_w(h8, val); return; // ISR
+ case 0xfee018: h8->per_regs[0xF8] = val; return; // IPRA
+ }
+ logerror("cpu '%s' (PC=%08X): unmapped I/O(1) byte write to %08X = %02X\n",h8->device->tag(),h8->pc,address,val);
+}
+
+void h8_3007_itu_init(h83xx_state *h8)
+{
+ h8->timer[0] = h8->device->machine().scheduler().timer_alloc(FUNC(h8itu_3007_timer_0_cb), h8);
+ h8->timer[1] = h8->device->machine().scheduler().timer_alloc(FUNC(h8itu_3007_timer_1_cb), h8);
+ h8->timer[2] = h8->device->machine().scheduler().timer_alloc(FUNC(h8itu_3007_timer_2_cb), h8);
+
+ h8_itu_reset(h8);
+}
+
+void h8_itu_init(h83xx_state *h8)
+{
+ h8->timer[0] = h8->device->machine().scheduler().timer_alloc(FUNC(h8itu_timer_0_cb), h8);
+ h8->timer[1] = h8->device->machine().scheduler().timer_alloc(FUNC(h8itu_timer_1_cb), h8);
+ h8->timer[2] = h8->device->machine().scheduler().timer_alloc(FUNC(h8itu_timer_2_cb), h8);
+ h8->timer[3] = h8->device->machine().scheduler().timer_alloc(FUNC(h8itu_timer_3_cb), h8);
+ h8->timer[4] = h8->device->machine().scheduler().timer_alloc(FUNC(h8itu_timer_4_cb), h8);
+
+ h8_itu_reset(h8);
+}
+
+void h8_itu_reset(h83xx_state *h8)
+{
+ int i;
+
+ // stop all the timers
+ for (i=0; i<5; i++)
+ h8->timer[i]->adjust(attotime::never);
+}
diff --git a/trunk/src/emu/cpu/h83002/h8priv.h b/trunk/src/emu/cpu/h83002/h8priv.h
new file mode 100644
index 00000000000..922ad1e2f4e
--- /dev/null
+++ b/trunk/src/emu/cpu/h83002/h8priv.h
@@ -0,0 +1,131 @@
+/***************************************************************************
+
+ h8priv.h : Private constants and other definitions for the H8/3002 emulator.
+
+****************************************************************************/
+
+#pragma once
+
+#ifndef __H8PRIV_H__
+#define __H8PRIV_H__
+
+typedef struct
+{
+ UINT32 tgr, irq, out;
+} H8S2XXX_TPU_ITEM;
+
+typedef struct
+{
+ emu_timer *timer;
+ int cycles_per_tick;
+ UINT64 timer_cycles;
+} H8S2XXX_TPU;
+
+typedef struct
+{
+ emu_timer *timer;
+ UINT32 bitrate;
+} H8S2XXX_SCI;
+
+typedef struct
+{
+ emu_timer *timer;
+ int cycles_per_tick;
+ UINT64 timer_cycles;
+} H8S2XXX_TMR;
+
+typedef struct _h83xx_state h83xx_state;
+struct _h83xx_state
+{
+ // main CPU stuff
+ UINT32 h8err;
+ UINT32 regs[8];
+ UINT32 pc, ppc;
+
+ UINT32 irq_req[3];
+ INT32 cyccnt;
+
+ UINT8 ccr;
+ UINT8 h8nflag, h8vflag, h8cflag, h8zflag, h8iflag, h8hflag;
+ UINT8 h8uflag, h8uiflag;
+ UINT8 incheckirqs;
+
+ device_irq_callback irq_cb;
+ legacy_cpu_device *device;
+
+ address_space *program;
+ direct_read_data *direct;
+ address_space *io;
+
+ // onboard peripherals stuff
+ UINT8 per_regs[0x1C0];
+
+ UINT16 h8TCNT[5];
+ UINT8 h8TSTR;
+
+ UINT8 STCR, TCR[2], TCSR[2], TCORA[2], TCORB[2], TCNT[2];
+ UINT16 FRC;
+
+ emu_timer *timer[5];
+ emu_timer *frctimer;
+
+ H8S2XXX_TMR tmr[2];
+ H8S2XXX_TPU tpu[6];
+ H8S2XXX_SCI sci[3];
+
+ int mode_8bit;
+ bool has_h8speriphs;
+};
+
+// defined in h8speriph.c
+extern void h8s_tmr_init(h83xx_state *h8);
+extern void h8s_tpu_init(h83xx_state *h8);
+extern void h8s_sci_init(h83xx_state *h8);
+extern void h8s_periph_reset(h83xx_state *h8);
+extern void h8s_dtce_check(h83xx_state *h8, int vecnum);
+
+INLINE h83xx_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == H83002 ||
+ device->type() == H83007 ||
+ device->type() == H83044 ||
+ device->type() == H83334 ||
+ device->type() == H8S2241 ||
+ device->type() == H8S2246 ||
+ device->type() == H8S2323);
+ return (h83xx_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+UINT8 h8_register_read8(h83xx_state *h8, UINT32 address);
+UINT8 h8_3007_register_read8(h83xx_state *h8, UINT32 address);
+UINT8 h8_3007_register1_read8(h83xx_state *h8, UINT32 address);
+void h8_register_write8(h83xx_state *h8, UINT32 address, UINT8 val);
+void h8_3007_register_write8(h83xx_state *h8, UINT32 address, UINT8 val);
+void h8_3007_register1_write8(h83xx_state *h8, UINT32 address, UINT8 val);
+
+void h8_itu_init(h83xx_state *h8);
+void h8_3007_itu_init(h83xx_state *h8);
+void h8_itu_reset(h83xx_state *h8);
+UINT8 h8_itu_read8(h83xx_state *h8, UINT8 reg);
+UINT8 h8_3007_itu_read8(h83xx_state *h8, UINT8 reg);
+void h8_itu_write8(h83xx_state *h8, UINT8 reg, UINT8 val);
+void h8_3007_itu_write8(h83xx_state *h8, UINT8 reg, UINT8 val);
+
+UINT8 h8s2241_per_regs_read_8(h83xx_state *h8, int offset);
+UINT8 h8s2246_per_regs_read_8(h83xx_state *h8, int offset);
+UINT8 h8s2323_per_regs_read_8(h83xx_state *h8, int offset);
+
+UINT16 h8s2241_per_regs_read_16(h83xx_state *h8, int offset);
+UINT16 h8s2246_per_regs_read_16(h83xx_state *h8, int offset);
+UINT16 h8s2323_per_regs_read_16(h83xx_state *h8, int offset);
+
+void h8s2241_per_regs_write_8(h83xx_state *h8, int offset, UINT8 data);
+void h8s2246_per_regs_write_8(h83xx_state *h8, int offset, UINT8 data);
+void h8s2323_per_regs_write_8(h83xx_state *h8, int offset, UINT8 data);
+
+void h8s2241_per_regs_write_16(h83xx_state *h8, int offset, UINT16 data);
+void h8s2246_per_regs_write_16(h83xx_state *h8, int offset, UINT16 data);
+void h8s2323_per_regs_write_16(h83xx_state *h8, int offset, UINT16 data);
+
+#endif /* __H8PRIV_H__ */
diff --git a/trunk/src/emu/cpu/h83002/h8speriph.c b/trunk/src/emu/cpu/h83002/h8speriph.c
new file mode 100644
index 00000000000..458a040b4d1
--- /dev/null
+++ b/trunk/src/emu/cpu/h83002/h8speriph.c
@@ -0,0 +1,1540 @@
+/*
+
+ Hitachi H8S/2xxx MCU peripherals
+
+ (c) 2001-2007 Tim Schuerewegen
+
+ H8S/2241
+ H8S/2246
+ H8S/2323
+
+*/
+
+#include "emu.h"
+#include "debugger.h"
+#include "h8.h"
+#include "h8priv.h"
+
+#define VERBOSE_LEVEL ( 0 )
+
+INLINE void ATTR_PRINTF(3,4) verboselog( running_machine &machine, int n_level, const char *s_fmt, ...)
+{
+ if (VERBOSE_LEVEL >= n_level)
+ {
+ va_list v;
+ char buf[32768];
+ va_start( v, s_fmt);
+ vsprintf( buf, s_fmt, v);
+ va_end( v);
+ logerror( "%s: %s", machine.describe_context( ), buf);
+ }
+}
+
+const UINT8 H8S_RESET_H8S_IO_224x[0x1C0] = // values from "e602100_h8s2245.pdf"
+{
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FE40
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FE50
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FE60
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FE70
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FE80
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FE90
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FEA0
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, // FEB0
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FEC0
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FED0
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FEE0
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FEF0
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FF00
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FF10
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FF20
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x3F, 0xFF, 0x00, 0x00, // FF30
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FF40
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FF50
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FF60
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x84, 0x00, 0xF2, 0x00, // FF70
+ 0x00, 0xFF, 0x00, 0xFF, 0x84, 0x00, 0xF2, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x84, 0x00, 0xF2, 0x00, // FF80
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FF90
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FFA0
+ 0x00, 0x00, 0x00, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FFB0
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FFC0
+ 0x00, 0xC0, 0x00, 0x00, 0x40, 0xC0, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // FFD0
+ 0x00, 0xC0, 0x00, 0x00, 0x40, 0xC0, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, // FFE0
+ 0x00, 0xC0, 0x00, 0x00, 0x40, 0xC0, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, // FFF0
+};
+
+const UINT8 H8S_RESET_H8S_IO_2323[0x1C0] = // values from "rej09b0220_h8s2329.pdf"
+{
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FE40
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FE50
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FE60
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FE70
+ 0x00, 0xC0, 0x00, 0x00, 0x40, 0xC0, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // FE80
+ 0x00, 0xC0, 0x00, 0x00, 0x40, 0xC0, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, // FE90
+ 0x00, 0xC0, 0x00, 0x00, 0x40, 0xC0, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, // FEA0
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, // FEB0
+ 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x00, // FEC0
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0x3C, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FED0
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FEE0
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FEF0
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FF00
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FF10
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FF20
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x3F, 0xFF, 0x00, 0x00, // FF30
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FF40
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FF50
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FF60
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x84, 0x00, 0xF2, 0x00, // FF70
+ 0x00, 0xFF, 0x00, 0xFF, 0x84, 0x00, 0xF2, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x84, 0x00, 0xF2, 0x00, // FF80
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FF90
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, // FFA0
+ 0x00, 0x00, 0x00, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FFB0
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FFC0
+ 0x00, 0xC0, 0x00, 0x00, 0x40, 0xC0, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // FFD0
+ 0x00, 0xC0, 0x00, 0x00, 0x40, 0xC0, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, // FFE0
+ 0x00, 0xC0, 0x00, 0x00, 0x40, 0xC0, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, // FFF0
+};
+
+#define SCR_TIE 0x80
+#define SCR_RIE 0x40
+#define SCR_TE 0x20
+#define SCR_RE 0x10
+
+#define SSR_TDRE 0x80
+#define SSR_RDRF 0x40
+#define SSR_ORER 0x20
+#define SSR_FER 0x10
+#define SSR_PER 0x08
+#define SSR_TEND 0x04
+
+#define SMR_CM 0x80
+#define SMR_CHR 0x40
+#define SMR_PE 0x20
+#define SMR_PM 0x10
+#define SMR_STOP 0x08
+#define SMR_MP 0x04
+#define SMR_CKS1 0x02
+#define SMR_CKS0 0x01
+
+#define TCSR_CMFB 0x80
+#define TCSR_CMFA 0x40
+#define TCSR_OVF 0x20
+
+#define TCR_CMIEB 0x80
+#define TCR_CMIEA 0x40
+#define TCR_OVIE 0x20
+
+#define TSR_TCFD 0x80
+#define TSR_TCFU 0x20
+#define TSR_TCFV 0x10
+#define TSR_TGFD 0x08
+#define TSR_TGFC 0x04
+#define TSR_TGFB 0x02
+#define TSR_TGFA 0x01
+
+#define TIER_TCIEU 0x20
+#define TIER_TCIEV 0x10
+#define TIER_TGIED 0x08
+#define TIER_TGIEC 0x04
+#define TIER_TGIEB 0x02
+#define TIER_TGIEA 0x01
+
+#define DTC_MRA_MD_NORMAL 0
+#define DTC_MRA_MD_REPEAT 1
+#define DTC_MRA_MD_BLOCK 2
+
+#define DTC_MRA_SM1 0x80
+#define DTC_MRA_SM0 0x40
+#define DTC_MRA_DM1 0x20
+#define DTC_MRA_DM0 0x10
+#define DTC_MRA_DTS 0x02
+
+#define DTC_MRB_CHNE 0x80
+#define DTC_MRB_DISEL 0x40
+#define DTC_MRB_CHNS 0x20
+
+#define DMABCRL_DTME1 0x80
+#define DMABCRL_DTE1 0x40
+#define DMABCRL_DTME0 0x20
+#define DMABCRL_DTE0 0x10
+#define DMABCRL_DTIE1B 0x08
+#define DMABCRL_DTIE1A 0x04
+#define DMABCRL_DTIE0B 0x02
+#define DMABCRL_DTIE0A 0x01
+
+#define ADCSR_ADF 0x80
+#define ADCSR_ADIE 0x40
+#define ADCSR_ADST 0x20
+#define ADCSR_SCAN 0x10
+
+enum
+{
+ PIN_P10, PIN_P11, PIN_P12, PIN_P13, PIN_P14, PIN_P15, PIN_P16, PIN_P17,
+ PIN_P20, PIN_P21, PIN_P22, PIN_P23, PIN_P24, PIN_P25, PIN_P26, PIN_P27,
+ PIN_P30, PIN_P31, PIN_P32, PIN_P33, PIN_P34, PIN_P35,
+ PIN_P40, PIN_P41, PIN_P42, PIN_P43, PIN_P44, PIN_P45, PIN_P46, PIN_P47,
+ PIN_P50, PIN_P51, PIN_P52, PIN_P53,
+ PIN_P60, PIN_P61, PIN_P62, PIN_P63, PIN_P64, PIN_P65, PIN_P66, PIN_P67,
+ PIN_PA0, PIN_PA1, PIN_PA2, PIN_PA3, PIN_PA4, PIN_PA5, PIN_PA6, PIN_PA7,
+ PIN_PB0, PIN_PB1, PIN_PB2, PIN_PB3, PIN_PB4, PIN_PB5, PIN_PB6, PIN_PB7,
+ PIN_PC0, PIN_PC1, PIN_PC2, PIN_PC3, PIN_PC4, PIN_PC5, PIN_PC6, PIN_PC7,
+ PIN_PD0, PIN_PD1, PIN_PD2, PIN_PD3, PIN_PD4, PIN_PD5, PIN_PD6, PIN_PD7,
+ PIN_PE0, PIN_PE1, PIN_PE2, PIN_PE3, PIN_PE4, PIN_PE5, PIN_PE6, PIN_PE7,
+ PIN_PF0, PIN_PF1, PIN_PF2, PIN_PF3, PIN_PF4, PIN_PF5, PIN_PF6, PIN_PF7,
+ PIN_PG0, PIN_PG1, PIN_PG2, PIN_PG3, PIN_PG4
+};
+
+#define PIN_TIOCA0 PIN_P10
+#define PIN_TIOCB0 PIN_P11
+#define PIN_TIOCC0 PIN_P12
+#define PIN_TIOCD0 PIN_P13
+#define PIN_TIOCA1 PIN_P14
+#define PIN_TIOCB1 PIN_P15
+#define PIN_TIOCA2 PIN_P16
+#define PIN_TIOCB2 PIN_P17
+
+#define PIN_TCLKA PIN_P12
+#define PIN_TCLKB PIN_P13
+#define PIN_TCLKC PIN_P15
+#define PIN_TCLKD PIN_P17
+
+#define PIN_TXD0 PIN_P30
+#define PIN_TXD1 PIN_P31
+#define PIN_RXD0 PIN_P32
+#define PIN_RXD1 PIN_P33
+#define PIN_SCK0 PIN_P34
+#define PIN_SCK1 PIN_P35
+
+#define PIN_TIOCA3 PIN_P20
+#define PIN_TIOCB3 PIN_P21
+#define PIN_TIOCC3 PIN_P22
+#define PIN_TIOCD3 PIN_P23
+#define PIN_TIOCA4 PIN_P24
+#define PIN_TIOCB4 PIN_P25
+#define PIN_TIOCA5 PIN_P26
+#define PIN_TIOCB5 PIN_P27
+
+#define PIN_TMRI0 PIN_P22
+#define PIN_TMCI0 PIN_P23
+#define PIN_TMRI1 PIN_P24
+#define PIN_TMCI1 PIN_P25
+#define PIN_TMO0 PIN_P26
+#define PIN_TMO1 PIN_P27
+
+const int TPU_0_DIV[] = { 1, 4, 16, 64, 0, 0, 0,0 };
+const int TPU_1_DIV[] = { 1, 4, 16, 64, 0, 0, 256, 0 };
+const int TPU_2_DIV[] = { 1, 4, 16, 64, 0, 0, 0, 1024 };
+const int TPU_3_DIV[] = { 1, 4, 16, 64, 0, 1024, 256, 4096 };
+const int TPU_4_DIV[] = { 1, 4, 16, 64, 0, 0, 1024, 0 };
+const int TPU_5_DIV[] = { 1, 4, 16, 64, 0, 0, 256, 0 };
+
+const int H8S_IO_SMR[] = { H8S_IO_SMR0, H8S_IO_SMR1, H8S_IO_SMR2 };
+const int H8S_IO_BRR[] = { H8S_IO_BRR0, H8S_IO_BRR1, H8S_IO_BRR2 };
+const int H8S_IO_SCR[] = { H8S_IO_SCR0, H8S_IO_SCR1, H8S_IO_SCR2 };
+const int H8S_IO_TDR[] = { H8S_IO_TDR0, H8S_IO_TDR1, H8S_IO_TDR2 };
+const int H8S_IO_SSR[] = { H8S_IO_SSR0, H8S_IO_SSR1, H8S_IO_SSR2 };
+const int H8S_IO_RDR[] = { H8S_IO_RDR0, H8S_IO_RDR1, H8S_IO_RDR2 };
+
+const int H8S_INT_TXI[] = { H8S_INT_TXI0, H8S_INT_TXI1, H8S_INT_TXI2 };
+const int H8S_INT_RXI[] = { H8S_INT_RXI0, H8S_INT_RXI1, H8S_INT_RXI2 };
+
+const int H8S_IO_TCORA[] = { H8S_IO_TCORA0, H8S_IO_TCORA1 };
+const int H8S_IO_TCORB[] = { H8S_IO_TCORB0, H8S_IO_TCORB1 };
+const int H8S_IO_TCR[] = { H8S_IO_TCR0, H8S_IO_TCR1 };
+const int H8S_IO_TCNT[] = { H8S_IO_TCNT0, H8S_IO_TCNT1 };
+const int H8S_IO_TCSR[] = { H8S_IO_TCSR0, H8S_IO_TCSR1 };
+
+const int H8S_INT_OVI[] = { H8S_INT_OVI0, H8S_INT_OVI1 };
+const int H8S_INT_CMIA[] = { H8S_INT_CMIA0, H8S_INT_CMIA1 };
+const int H8S_INT_CMIB[] = { H8S_INT_CMIB0, H8S_INT_CMIB1 };
+
+const int H8S_IO_TGRA_H[] = { H8S_IO_TGR0A_H, H8S_IO_TGR1A_H, H8S_IO_TGR2A_H, H8S_IO_TGR3A_H, H8S_IO_TGR4A_H, H8S_IO_TGR5A_H };
+const int H8S_IO_TGRA_L[] = { H8S_IO_TGR0A_L, H8S_IO_TGR1A_L, H8S_IO_TGR2A_L, H8S_IO_TGR3A_L, H8S_IO_TGR4A_L, H8S_IO_TGR5A_L };
+const int H8S_IO_TGRB_H[] = { H8S_IO_TGR0B_H, H8S_IO_TGR1B_H, H8S_IO_TGR2B_H, H8S_IO_TGR3B_H, H8S_IO_TGR4B_H, H8S_IO_TGR5B_H };
+const int H8S_IO_TGRB_L[] = { H8S_IO_TGR0B_L, H8S_IO_TGR1B_L, H8S_IO_TGR2B_L, H8S_IO_TGR3B_L, H8S_IO_TGR4B_L, H8S_IO_TGR5B_L };
+const int H8S_IO_TGRC_H[] = { H8S_IO_TGR0C_H, 0, 0, H8S_IO_TGR3C_H, 0, 0 };
+const int H8S_IO_TGRC_L[] = { H8S_IO_TGR0C_L, 0, 0, H8S_IO_TGR3C_L, 0, 0 };
+const int H8S_IO_TGRD_H[] = { H8S_IO_TGR0D_H, 0, 0, H8S_IO_TGR3D_H, 0, 0 };
+const int H8S_IO_TGRD_L[] = { H8S_IO_TGR0D_L, 0, 0, H8S_IO_TGR3D_L, 0, 0 };
+const int H8S_IO_TCNT_H[] = { H8S_IO_TCNT0_H, H8S_IO_TCNT1_H, H8S_IO_TCNT2_H, H8S_IO_TCNT3_H, H8S_IO_TCNT4_H, H8S_IO_TCNT5_H };
+const int H8S_IO_TCNT_L[] = { H8S_IO_TCNT0_L, H8S_IO_TCNT1_L, H8S_IO_TCNT2_L, H8S_IO_TCNT3_L, H8S_IO_TCNT4_L, H8S_IO_TCNT5_L };
+const int H8S_IO_TIOR_H[] = { H8S_IO_TIOR0_H, H8S_IO_TIOR1, H8S_IO_TIOR2, H8S_IO_TIOR3_H, H8S_IO_TIOR4, H8S_IO_TIOR5 };
+const int H8S_IO_TIOR_L[] = { H8S_IO_TIOR0_L, 0, 0, H8S_IO_TIOR3_L, 0, 0 };
+const int H8S_IO_TTCR[] = { H8S_IO_TTCR0, H8S_IO_TTCR1, H8S_IO_TTCR2, H8S_IO_TTCR3, H8S_IO_TTCR4, H8S_IO_TTCR5 };
+const int H8S_IO_TIER[] = { H8S_IO_TIER0, H8S_IO_TIER1, H8S_IO_TIER2, H8S_IO_TIER3, H8S_IO_TIER4, H8S_IO_TIER5 };
+const int H8S_IO_TSR[] = { H8S_IO_TSR0, H8S_IO_TSR1, H8S_IO_TSR2, H8S_IO_TSR3, H8S_IO_TSR4, H8S_IO_TSR5 };
+
+const int H8S_INT_TCIV[] = { H8S_INT_TCI0V, H8S_INT_TCI1V, H8S_INT_TCI2V, H8S_INT_TCI3V, H8S_INT_TCI4V, H8S_INT_TCI5V };
+const int H8S_INT_TCIU[] = { 0, H8S_INT_TCI1U, H8S_INT_TCI2U, 0, H8S_INT_TCI4U, H8S_INT_TCI5U };
+const int H8S_INT_TGIA[] = { H8S_INT_TGI0A, H8S_INT_TGI1A, H8S_INT_TGI2A, H8S_INT_TGI3A, H8S_INT_TGI4A, H8S_INT_TGI5A };
+const int H8S_INT_TGIB[] = { H8S_INT_TGI0B, H8S_INT_TGI1B, H8S_INT_TGI2B, H8S_INT_TGI3B, H8S_INT_TGI4B, H8S_INT_TGI5B };
+const int H8S_INT_TGIC[] = { H8S_INT_TGI0C, 0, 0, H8S_INT_TGI3C, 0, 0 };
+const int H8S_INT_TGID[] = { H8S_INT_TGI0D, 0, 0, H8S_INT_TGI3D, 0, 0 };
+
+const int PIN_TIOCA[] = { PIN_TIOCA0, PIN_TIOCA1, PIN_TIOCA2, PIN_TIOCA3, PIN_TIOCA4, PIN_TIOCA5 };
+const int PIN_TIOCB[] = { PIN_TIOCB0, PIN_TIOCB1, PIN_TIOCB2, PIN_TIOCB3, PIN_TIOCB4, PIN_TIOCB5 };
+const int PIN_TIOCC[] = { PIN_TIOCC0, 0, 0, PIN_TIOCC3, 0, 0 };
+const int PIN_TIOCD[] = { PIN_TIOCD0, 0, 0, PIN_TIOCD3, 0, 0 };
+
+const int TCR_CCLR_AND[] = { 7, 3, 3, 7, 3, 3 };
+
+// prototypes
+
+void h8s_tmr_x_reset( h83xx_state *h8, int x);
+void h8s_tpu_x_reset( h83xx_state *h8, int x);
+void h8s_tpu_x_tick( h83xx_state *h8, int x);
+
+////////////
+// DTVECR //
+////////////
+
+#define DTVECR_ADDR(x) (0x400 + (x << 1))
+
+///////////////
+// MEMCONV.H //
+///////////////
+
+static TIMER_CALLBACK( h8s_tmr_callback );
+static TIMER_CALLBACK( h8s_tpu_callback );
+static TIMER_CALLBACK( h8s_sci_callback );
+
+/////////////
+// TIMER.C //
+/////////////
+
+UINT16 ptr_read_16( void *ptr)
+{
+ return (*(((UINT8*)ptr) + 0) << 8) | (*(((UINT8*)ptr) + 1) << 0);
+}
+
+void ptr_write_16( void *ptr, UINT16 data)
+{
+ *(((UINT8*)ptr) + 0) = (data >> 8) & 0xFF;
+ *(((UINT8*)ptr) + 1) = (data >> 0) & 0xFF;
+}
+
+int device_icount_min_timer_icount1( h83xx_state *h8, emu_timer *timer)
+{
+ return (timer->elapsed() * h8->device->unscaled_clock()).as_double();
+}
+
+void h8s2xxx_interrupt_request(h83xx_state *h8, UINT32 vecnum)
+{
+ UINT8 idx, bit;
+ idx = vecnum >> 5;
+ bit = vecnum & 0x1F;
+ h8->irq_req[idx] |= (1 << bit);
+}
+
+void h8s_dtce_execute(h83xx_state *h8, UINT32 addr_dtce, UINT8 mask_dtce, UINT32 addr_dtvecr)
+{
+ UINT32 data[3], dtc_vect, dtc_sar, dtc_dar, cnt, i;
+ UINT8 dtc_mra, dtc_mrb, sz;
+ UINT16 dtc_cra, dtc_crb;
+ // get dtc info
+ dtc_vect = 0xFF0000 | h8->program->read_word(addr_dtvecr);
+ data[0] = h8->program->read_dword( dtc_vect + 0);
+ data[1] = h8->program->read_dword( dtc_vect + 4);
+ data[2] = h8->program->read_dword( dtc_vect + 8);
+ dtc_mra = (data[0] >> 24) & 0xFF;
+ dtc_sar = (data[0] >> 0) & 0xFFFFFF;
+ dtc_mrb = (data[1] >> 24) & 0xFF;
+ dtc_dar = (data[1] >> 0) & 0xFFFFFF;
+ dtc_cra = (data[2] >> 16) & 0xFFFF;
+ dtc_crb = (data[2] >> 0) & 0xFFFF;
+ verboselog( h8->device->machine(), 3, "dtc : vect %08X mra %02X sar %08X mrb %02X dar %08X cra %04X crb %04X\n", dtc_vect, dtc_mra, dtc_sar, dtc_mrb, dtc_dar, dtc_cra, dtc_crb);
+ // execute
+ if ((dtc_mra & 0x0E) != 0x00) fatalerror("H8S: dtc unsupported MRA %x\n", dtc_mra&0x0e);
+ sz = 1 << (dtc_mra & 0x01);
+ cnt = dtc_cra;
+ for (i=0;i<cnt;i++)
+ {
+ if (dtc_sar == H8S_IO_ADDR( H8S_IO_RDR1)) h8->program->write_byte( H8S_IO_ADDR( H8S_IO_SSR1), h8->program->read_byte( H8S_IO_ADDR( H8S_IO_SSR1)) & (~H8S_SSR_TDRE));
+ if (dtc_mra & 0x01) h8->program->write_word( dtc_dar, h8->program->read_word( dtc_sar)); else h8->program->write_byte( dtc_dar, h8->program->read_byte( dtc_sar));
+ if (dtc_dar == H8S_IO_ADDR( H8S_IO_TDR0)) h8->program->write_byte( H8S_IO_ADDR( H8S_IO_SSR0), h8->program->read_byte( H8S_IO_ADDR( H8S_IO_SSR0)) & (~H8S_SSR_TDRE));
+ if (dtc_mra & 0x80) { if (dtc_mra & 0x40) dtc_sar -= sz; else dtc_sar += sz; }
+ if (dtc_mra & 0x20) { if (dtc_mra & 0x10) dtc_dar -= sz; else dtc_dar += sz; }
+ }
+ h8->program->write_byte( addr_dtce, h8->program->read_byte( addr_dtce) & (~mask_dtce));
+}
+
+void h8s_dtce_check(h83xx_state *h8, int vecnum)
+{
+ UINT32 dtce = 0;
+ int bit = 0;
+ // get dtce info
+ switch (vecnum)
+ {
+ // DTCEA
+ case H8S_INT_IRQ0 : dtce = H8S_IO_DTCEA; bit = 7; break;
+ case H8S_INT_IRQ1 : dtce = H8S_IO_DTCEA; bit = 6; break;
+ case H8S_INT_IRQ2 : dtce = H8S_IO_DTCEA; bit = 5; break;
+ case H8S_INT_IRQ3 : dtce = H8S_IO_DTCEA; bit = 4; break;
+ case H8S_INT_IRQ4 : dtce = H8S_IO_DTCEA; bit = 3; break;
+ case H8S_INT_IRQ5 : dtce = H8S_IO_DTCEA; bit = 2; break;
+ case H8S_INT_IRQ6 : dtce = H8S_IO_DTCEA; bit = 1; break;
+ case H8S_INT_IRQ7 : dtce = H8S_IO_DTCEA; bit = 0; break;
+ // DTCEB
+ case H8S_INT_ADI : dtce = H8S_IO_DTCEB; bit = 6; break;
+ case H8S_INT_TGI0A : dtce = H8S_IO_DTCEB; bit = 5; break;
+ case H8S_INT_TGI0B : dtce = H8S_IO_DTCEB; bit = 4; break;
+ case H8S_INT_TGI0C : dtce = H8S_IO_DTCEB; bit = 3; break;
+ case H8S_INT_TGI0D : dtce = H8S_IO_DTCEB; bit = 2; break;
+ case H8S_INT_TGI1A : dtce = H8S_IO_DTCEB; bit = 1; break;
+ case H8S_INT_TGI1B : dtce = H8S_IO_DTCEB; bit = 0; break;
+ // DTCEC
+ case H8S_INT_TGI2A : dtce = H8S_IO_DTCEC; bit = 7; break;
+ case H8S_INT_TGI2B : dtce = H8S_IO_DTCEC; bit = 6; break;
+ // DTCED
+ case H8S_INT_CMIA0 : dtce = H8S_IO_DTCED; bit = 3; break;
+ case H8S_INT_CMIB0 : dtce = H8S_IO_DTCED; bit = 2; break;
+ case H8S_INT_CMIA1 : dtce = H8S_IO_DTCED; bit = 1; break;
+ case H8S_INT_CMIB1 : dtce = H8S_IO_DTCED; bit = 0; break;
+ // DTCEE
+ case H8S_INT_RXI0 : dtce = H8S_IO_DTCEE; bit = 3; break;
+ case H8S_INT_TXI0 : dtce = H8S_IO_DTCEE; bit = 2; break;
+ case H8S_INT_RXI1 : dtce = H8S_IO_DTCEE; bit = 1; break;
+ case H8S_INT_TXI1 : dtce = H8S_IO_DTCEE; bit = 0; break;
+ // DTCEF
+ case H8S_INT_RXI2 : dtce = H8S_IO_DTCEF; bit = 7; break;
+ case H8S_INT_TXI2 : dtce = H8S_IO_DTCEF; bit = 6; break;
+ }
+ // execute
+ if ((dtce != 0) && (h8->per_regs[dtce] & (1 << bit))) h8s_dtce_execute(h8, H8S_IO_ADDR( dtce), (1 << bit), DTVECR_ADDR( vecnum));
+}
+
+void h8s_periph_reset(h83xx_state *h8)
+{
+ const int tpu_max = (h8->device->type() == H8S2323) ? 6 : 3;
+ if ((h8->device->type() == H8S2241) || (h8->device->type() == H8S2246))
+ {
+ memcpy( h8->per_regs, H8S_RESET_H8S_IO_224x, sizeof( h8->per_regs));
+ }
+ else if (h8->device->type() == H8S2323)
+ {
+ memcpy( h8->per_regs, H8S_RESET_H8S_IO_2323, sizeof( h8->per_regs));
+ }
+ for (int i = 0; i < 2; i++) h8s_tmr_x_reset( h8, i);
+ for (int i = 0; i < tpu_max; i++) h8s_tpu_x_reset( h8, i);
+}
+
+/////////////////
+// TIMER 8-BIT //
+/////////////////
+
+void h8s_tmr_init(h83xx_state *h8)
+{
+ for (int i = 0; i < 2; i++)
+ {
+ h8->tmr[i].timer = h8->device->machine().scheduler().timer_alloc(FUNC(h8s_tmr_callback), h8);
+ h8->tmr[i].timer->adjust(attotime::never, i);
+ }
+}
+
+void h8s_tmr_x_reset( h83xx_state *h8, int x)
+{
+ H8S2XXX_TMR *tmr = &h8->tmr[x];
+ tmr->cycles_per_tick = 0;
+ tmr->timer->adjust(attotime::never, x);
+}
+
+UINT64 h8s_tmr_x_calculate_ticks( h83xx_state *h8, int x, UINT8 tcnt)
+{
+ UINT64 cycles1, cycles2;
+ UINT8 tcor;
+ // overflow
+ if (tcnt == 0) cycles1 = 0xFF + 1; else cycles1 = (UINT8)(0xFF - tcnt + 1);
+ // tcora
+ tcor = h8->per_regs[H8S_IO_TCORA[x]];
+ if (tcnt == tcor) cycles2 = 0xFF + 1; else cycles2 = (UINT8)(tcor - tcnt);
+ if ((cycles2 > 0) && (cycles2 < cycles1)) cycles1 = cycles2;
+ // tcorb
+ tcor = h8->per_regs[H8S_IO_TCORB[x]];
+ if (tcnt == tcor) cycles2 = 0xFF + 1; else cycles2 = (UINT8)(tcor - tcnt);
+ if ((cycles2 > 0) && (cycles2 < cycles1)) cycles1 = cycles2;
+ // done
+ return cycles1;
+}
+
+void h8s_tmr_x_update( h83xx_state *h8, int x)
+{
+ H8S2XXX_TMR *tmr = &h8->tmr[x];
+ UINT64 cycles;
+ int div = 0;
+ UINT8 tcr, tcnt;
+ tcr = h8->per_regs[H8S_IO_TCR[x]];
+ switch ((tcr >> 0) & 7)
+ {
+ case 1 : div = 8; break;
+ case 2 : div = 64; break;
+ case 3 : div = 8192; break;
+// default : OS_MessageBox( NULL, "tmr_x_update", "error", 0); break;
+ }
+ tmr->cycles_per_tick = div;
+ tcnt = h8->per_regs[H8S_IO_TCNT[x]];
+ verboselog( h8->device->machine(), 5, "TMR %d - update (div %d tcnt %02X)\n", x, div, tcnt);
+ // update timer
+ cycles = h8s_tmr_x_calculate_ticks( h8, x, tcnt) * tmr->cycles_per_tick;
+ tmr->timer_cycles = cycles;
+ tmr->timer->adjust(attotime::from_hz(h8->device->unscaled_clock() / cycles), x);
+}
+
+UINT8 h8s_tmr_x_calculate_tcnt( h83xx_state *h8, int x)
+{
+ H8S2XXX_TMR *tmr = &h8->tmr[x];
+ UINT8 tcnt;
+ tcnt = h8->per_regs[H8S_IO_TCNT[x]];
+ if (tmr->timer->enabled())
+ {
+ tcnt = (UINT8)(tcnt + ((device_icount_min_timer_icount1( h8, tmr->timer)) / tmr->cycles_per_tick));
+ }
+ return tcnt;
+}
+
+void h8s_tmr_x_start( h83xx_state *h8, int x)
+{
+ verboselog( h8->device->machine(), 5, "TMR %d - start\n", x);
+ // ...
+ h8s_tmr_x_update( h8, x);
+}
+
+void h8s_tmr_x_stop( h83xx_state *h8, int x)
+{
+ H8S2XXX_TMR *tmr = &h8->tmr[x];
+ UINT8 tcnt;
+ // ...
+ verboselog( h8->device->machine(), 5, "TMR %d - stop\n", x);
+ // calculate tcnt
+ tcnt = h8s_tmr_x_calculate_tcnt( h8, x);
+ // update tcnt
+ h8->per_regs[H8S_IO_TCNT[x]] = tcnt;
+ // disable timer
+ tmr->timer->reset();
+}
+
+UINT8 h8s_tmr_x_tcnt_change( h83xx_state *h8, int x, UINT8 tcnt)
+{
+ UINT8 tcr, tcor;
+ int clear = 0;
+ // ...
+ verboselog( h8->device->machine(), 9, "TMR %d - tmr_x_tcnt_change (%02X)\n", x, tcnt);
+ // ...
+ tcr = h8->per_regs[H8S_IO_TCR[x]];
+ // overflow
+ if (tcnt == 0)
+ {
+ verboselog( h8->device->machine(), 9, "TMR %d - overflow match\n", x);
+ h8->per_regs[H8S_IO_TCSR[x]] |= TCSR_OVF;
+ if ((tcr & TCR_OVIE) != 0)
+ {
+ h8s2xxx_interrupt_request( h8, H8S_INT_OVI[x]);
+ }
+ }
+ // tcora
+ tcor = h8->per_regs[H8S_IO_TCORA[x]];
+ if (tcnt == tcor)
+ {
+ verboselog( h8->device->machine(), 9, "TMR %d - tcora match\n", x);
+ h8->per_regs[H8S_IO_TCSR[x]] |= TCSR_CMFA;
+ if ((tcr & TCR_CMIEA) != 0)
+ {
+ h8s2xxx_interrupt_request( h8, H8S_INT_CMIA[x]);
+ }
+ if (((tcr >> 3) & 3) == 1) // CCLR 1 -> "clear by compare match a"
+ {
+ clear = 1;
+ }
+ }
+ // tcorb
+ tcor = h8->per_regs[H8S_IO_TCORB[x]];
+ if (tcnt == tcor)
+ {
+ verboselog( h8->device->machine(), 9, "TMR %d - tcorb match\n", x);
+ h8->per_regs[H8S_IO_TCSR[x]] |= TCSR_CMFB;
+ if ((tcr & TCR_CMIEB) != 0)
+ {
+ h8s2xxx_interrupt_request( h8, H8S_INT_CMIB[x]);
+ }
+ if (((tcr >> 3) & 3) == 2) // CCLR 2 -> "clear by compare match b"
+ {
+ clear = 1;
+ }
+ }
+ // ...
+ if (clear)
+ {
+ verboselog( h8->device->machine(), 5, "TMR %d - tcnt clear\n", x);
+ tcnt = 0;
+ }
+ // ...
+ return tcnt;
+}
+
+void h8s_tmr_x_callback( h83xx_state *h8, int x)
+{
+ H8S2XXX_TMR *tmr = &h8->tmr[x];
+ UINT64 cycles;
+ UINT8 tcnt;
+ // calculate tcnt
+ tcnt = h8->per_regs[H8S_IO_TCNT[x]];
+ tcnt = (UINT8)(tcnt + tmr->timer_cycles / tmr->cycles_per_tick);
+ // ...
+ tcnt = h8s_tmr_x_tcnt_change( h8, x, tcnt);
+ // update tcnt
+ h8->per_regs[H8S_IO_TCNT[x]] = tcnt;
+ // update timer
+ cycles = h8s_tmr_x_calculate_ticks( h8, x, tcnt) * tmr->cycles_per_tick;
+ tmr->timer_cycles = cycles;
+ tmr->timer->adjust(attotime::from_hz(h8->device->unscaled_clock() / cycles), x);
+}
+
+void h8s_tmr_x_write_tcr( h83xx_state *h8, int x, UINT8 data)
+{
+ UINT8 old_data = h8->per_regs[H8S_IO_TCR[x]];
+ h8->per_regs[H8S_IO_TCR[x]] = data;
+ if ((data & 0x07) != (old_data & 0x07))
+ {
+ if ((data & 0x07) != 0)
+ {
+ h8s_tmr_x_start( h8, x);
+ }
+ else
+ {
+ h8s_tmr_x_stop( h8, x);
+ }
+ }
+}
+
+void h8s_tmr_x_write_tcnt( h83xx_state *h8, int x, UINT8 data)
+{
+ H8S2XXX_TMR *tmr = &h8->tmr[x];
+ h8->per_regs[H8S_IO_TCNT[x]] = data;
+ if (tmr->timer->enabled())
+ {
+ h8s_tmr_x_update( h8, x);
+ }
+}
+
+void h8s_tmr_x_write_tcor( h83xx_state *h8, int x)
+{
+ H8S2XXX_TMR *tmr = &h8->tmr[x];
+ if ((tmr->timer->enabled()) && (tmr->cycles_per_tick != 0))
+ {
+ UINT8 tcnt1, tcnt2;
+ UINT64 cycles;
+ tcnt1 = h8->per_regs[H8S_IO_TCNT[x]];
+ tcnt2 = (UINT8)(tcnt1 + ((device_icount_min_timer_icount1( h8, tmr->timer)) / tmr->cycles_per_tick));
+ cycles = h8s_tmr_x_calculate_ticks( h8, x, tcnt2) * tmr->cycles_per_tick;
+ cycles = cycles + (tcnt2 - tcnt1) * tmr->cycles_per_tick;
+ tmr->timer_cycles = cycles;
+ tmr->timer->adjust(attotime::from_hz(h8->device->unscaled_clock() / cycles), x);
+ }
+}
+
+UINT8 h8s_tmr_x_read_tcnt( h83xx_state *h8, int x)
+{
+ return h8s_tmr_x_calculate_tcnt( h8, x);
+}
+
+void h8s_tmr_x_write_tcora( h83xx_state *h8, int x, UINT8 data)
+{
+ h8->per_regs[H8S_IO_TCORA[x]] = data;
+ h8s_tmr_x_write_tcor( h8, x);
+}
+
+void h8s_tmr_x_write_tcorb( h83xx_state *h8, int x, UINT8 data)
+{
+ h8->per_regs[H8S_IO_TCORB[x]] = data;
+ h8s_tmr_x_write_tcor( h8, x);
+}
+
+static TIMER_CALLBACK( h8s_tmr_callback)
+{
+ h83xx_state *h8 = (h83xx_state *)ptr;
+ h8s_tmr_x_callback( h8, param);
+}
+
+//////////////////
+// TIMER 16-BIT //
+//////////////////
+
+void h8s_tpu_init(h83xx_state *h8)
+{
+ const int tpu_max = (h8->device->type() == H8S2323) ? 6 : 3;
+ for (int i = 0; i < tpu_max; i++)
+ {
+ h8->tpu[i].timer = h8->device->machine().scheduler().timer_alloc(FUNC(h8s_tpu_callback), h8);
+ h8->tpu[i].timer->adjust(attotime::never, i);
+ }
+}
+
+void h8s_tpu_x_reset( h83xx_state *h8, int x)
+{
+ H8S2XXX_TPU *tpu = &h8->tpu[x];
+ tpu->cycles_per_tick = 0;
+ tpu->timer->reset();
+}
+
+UINT16 h8s_tpu_x_calculate_tcnt( h83xx_state *h8, int x)
+{
+ H8S2XXX_TPU *tpu = &h8->tpu[x];
+ UINT16 tcnt;
+ tcnt = ptr_read_16( h8->per_regs + H8S_IO_TCNT_H[x]);
+ if ((tpu->timer->enabled()) && (tpu->cycles_per_tick > 0))
+ {
+ tcnt = (UINT16)(tcnt + ((device_icount_min_timer_icount1( h8, tpu->timer)) / tpu->cycles_per_tick));
+ }
+ return tcnt;
+}
+
+UINT64 h8s_tpu_x_calculate_ticks( h83xx_state *h8, int x, UINT16 tcnt)
+{
+ UINT64 cycles1, cycles2;
+ UINT16 tgr;
+ // overflow
+ if (tcnt == 0) cycles1 = 0xFFFF + 1; else cycles1 = (UINT16)(0xFFFF - tcnt + 1);
+ // tgra
+ tgr = ptr_read_16( h8->per_regs + H8S_IO_TGRA_H[x]);
+ if (tcnt == tgr) cycles2 = 0xFFFF + 1; else cycles2 = (UINT16)(tgr - tcnt);
+ if ((cycles2 > 0) && (cycles2 < cycles1)) cycles1 = cycles2;
+ // tgrb
+ tgr = ptr_read_16( h8->per_regs + H8S_IO_TGRB_H[x]);
+ if (tcnt == tgr) cycles2 = 0xFFFF + 1; else cycles2 = (UINT16)(tgr - tcnt);
+ if ((cycles2 > 0) && (cycles2 < cycles1)) cycles1 = cycles2;
+ // tgrc
+ if ((x == 0) || (x == 3))
+ {
+ tgr = ptr_read_16( h8->per_regs + H8S_IO_TGRC_H[x]);
+ if (tcnt == tgr) cycles2 = 0xFFFF + 1; else cycles2 = (UINT16)(tgr - tcnt);
+ if ((cycles2 > 0) && (cycles2 < cycles1)) cycles1 = cycles2;
+ }
+ // tgrd
+ if ((x == 0) || (x == 3))
+ {
+ tgr = ptr_read_16( h8->per_regs + H8S_IO_TGRD_H[x]);
+ if (tcnt == tgr) cycles2 = 0xFFFF + 1; else cycles2 = (UINT16)(tgr - tcnt);
+ if ((cycles2 > 0) && (cycles2 < cycles1)) cycles1 = cycles2;
+ }
+ // done
+ return cycles1;
+}
+
+void h8s_pin_write( h83xx_state *h8, int pin, int data)
+{
+ switch (pin)
+ {
+ case PIN_TIOCB1 :
+ {
+ UINT8 p1dr;
+ p1dr = h8->per_regs[H8S_IO_P1DR];
+ if (data) p1dr |= H8S_P1_TIOCB1; else p1dr &= ~H8S_P1_TIOCB1;
+ h8->io->write_byte(H8S_IO_ADDR(H8S_IO_P1DR), p1dr);
+ h8->per_regs[H8S_IO_P1DR] = p1dr;
+ }
+ break;
+ }
+}
+
+int h8s_pin_read( h83xx_state *h8, int pin)
+{
+ switch (pin)
+ {
+ case PIN_TIOCB1 : return (h8->per_regs[H8S_IO_P1DR] & H8S_P1_TIOCB1) ? 1 : 0;
+ }
+ return 0;
+}
+
+void h8s_tioc_pin_update( h83xx_state *h8, int io, int pin)
+{
+ switch (io)
+ {
+ case 1 : h8s_pin_write( h8, pin, 0); break;
+ case 2 : h8s_pin_write( h8, pin, 1); break;
+ case 3 : h8s_pin_write( h8, pin, h8s_pin_read( h8, pin) ? 0 : 1); break;
+ case 5 : h8s_pin_write( h8, pin, 0); break;
+ case 6 : h8s_pin_write( h8, pin, 1); break;
+ case 7 : h8s_pin_write( h8, pin, h8s_pin_read( h8, pin) ? 0 : 1); break;
+ }
+}
+
+void h8s_tioc_pin_reset( h83xx_state *h8, int io, int pin)
+{
+ switch (io)
+ {
+ case 1 : h8s_pin_write( h8, pin, 0); break;
+ case 2 : h8s_pin_write( h8, pin, 0); break;
+ case 3 : h8s_pin_write( h8, pin, 0); break;
+ case 5 : h8s_pin_write( h8, pin, 1); break;
+ case 6 : h8s_pin_write( h8, pin, 1); break;
+ case 7 : h8s_pin_write( h8, pin, 1); break;
+ }
+}
+
+void h8s_tpu_x_tioc_reset( h83xx_state *h8, int x)
+{
+ UINT8 tior;
+ int cclr;
+ // ...
+ cclr = (h8->per_regs[H8S_IO_TTCR[x]] >> 5) & TCR_CCLR_AND[x];
+ // tioca & tiocb
+ tior = h8->per_regs[H8S_IO_TIOR_H[x]];
+ if (cclr != 1) h8s_tioc_pin_reset( h8, (tior >> 0) & 0x0F, PIN_TIOCA[x]);
+ if (cclr != 2) h8s_tioc_pin_reset( h8, (tior >> 4) & 0x0F, PIN_TIOCB[x]);
+ // tiocc & tiocd
+ if ((x == 0) || (x == 3))
+ {
+ tior = h8->per_regs[H8S_IO_TIOR_L[x]];
+ if (cclr != 5) h8s_tioc_pin_reset( h8, (tior >> 0) & 0x0F, PIN_TIOCC[x]);
+ if (cclr != 6) h8s_tioc_pin_reset( h8, (tior >> 4) & 0x0F, PIN_TIOCD[x]);
+ }
+}
+
+void h8s_tpu_x_overflow( h83xx_state *h8, int x)
+{
+ if (x == 2)
+ {
+ UINT8 tcr = h8->per_regs[H8S_IO_TTCR[1]];
+ if (((tcr >> 0) & 7) == 7)
+ {
+ h8s_tpu_x_tick( h8, 1);
+ }
+ }
+ if (x == 5)
+ {
+ UINT8 tcr = h8->per_regs[H8S_IO_TTCR[4]];
+ if (((tcr >> 0) & 7) == 7)
+ {
+ h8s_tpu_x_tick( h8, 4);
+ }
+ }
+}
+
+UINT16 h8s_tpu_x_tcnt_change( h83xx_state *h8, int x, UINT16 tcnt)
+{
+ UINT16 tgr;
+ UINT8 tcr, tier, tior;
+ int clear = 0;
+ // ...
+ verboselog( h8->device->machine(), 9, "TPU %d - tpu_x_tcnt_change (%04X)\n", x, tcnt);
+ // ...
+ tcr = h8->per_regs[H8S_IO_TTCR[x]];
+ tier = h8->per_regs[H8S_IO_TIER[x]];
+ // overflow
+ if (tcnt == 0)
+ {
+ verboselog( h8->device->machine(), 9, "TPU %d - overflow match\n", x);
+ h8->per_regs[H8S_IO_TSR[x]] |= TSR_TCFV;
+ if (tier & TIER_TCIEV)
+ {
+ h8s2xxx_interrupt_request( h8, H8S_INT_TCIV[x]);
+ }
+ h8s_tpu_x_overflow( h8, x);
+ }
+ // tgra
+ tgr = ptr_read_16( h8->per_regs + H8S_IO_TGRA_H[x]);
+ if (tcnt == tgr)
+ {
+ verboselog( h8->device->machine(), 9, "TPU %d - tgra match\n", x);
+ h8->per_regs[H8S_IO_TSR[x]] |= TSR_TGFA;
+ if (tier & TIER_TGIEA)
+ {
+ h8s2xxx_interrupt_request( h8, H8S_INT_TGIA[x]);
+ }
+ if (((tcr >> 5) & TCR_CCLR_AND[x]) == 1) // CCLR 1 -> "TCNT cleared by TGRA compare match/input capture"
+ {
+ clear = 1;
+ }
+ else
+ {
+ tior = h8->per_regs[H8S_IO_TIOR_H[x]];
+ h8s_tioc_pin_update( h8, (tior >> 0) & 0x0F, PIN_TIOCA[x]);
+ }
+ }
+ // tgrb
+ tgr = ptr_read_16( h8->per_regs + H8S_IO_TGRB_H[x]);
+ if (tcnt == tgr)
+ {
+ verboselog( h8->device->machine(), 9, "TPU %d - tgrb match\n", x);
+ h8->per_regs[H8S_IO_TSR[x]] |= TSR_TGFB;
+ if (tier & TIER_TGIEB)
+ {
+ h8s2xxx_interrupt_request( h8, H8S_INT_TGIB[x]);
+ }
+ if (((tcr >> 5) & TCR_CCLR_AND[x]) == 2) // CCLR 2 -> "TCNT cleared by TGRB compare match/input capture"
+ {
+ clear = 1;
+ }
+ else
+ {
+ tior = h8->per_regs[H8S_IO_TIOR_H[x]];
+ h8s_tioc_pin_update( h8, (tior >> 4) & 0x0F, PIN_TIOCB[x]);
+ }
+ }
+ // tgrc
+ if ((x == 0) || (x == 3))
+ {
+ tgr = ptr_read_16( h8->per_regs + H8S_IO_TGRC_H[x]);
+ if (tcnt == tgr)
+ {
+ verboselog( h8->device->machine(), 9, "TPU %d - tgrc match\n", x);
+ h8->per_regs[H8S_IO_TSR[x]] |= TSR_TGFC;
+ if (tier & TIER_TGIEC)
+ {
+ h8s2xxx_interrupt_request( h8, H8S_INT_TGIC[x]);
+ }
+ if (((tcr >> 5) & TCR_CCLR_AND[x]) == 5) // CCLR 5 -> "TCNT cleared by TGRC compare match/input capture"
+ {
+ clear = 1;
+ }
+ else
+ {
+ tior = h8->per_regs[H8S_IO_TIOR_L[x]];
+ h8s_tioc_pin_update( h8, (tior >> 0) & 0x0F, PIN_TIOCC[x]);
+ }
+ }
+ }
+ // tgrd
+ if ((x == 0) || (x == 3))
+ {
+ tgr = ptr_read_16( h8->per_regs + H8S_IO_TGRD_H[x]);
+ if (tcnt == tgr)
+ {
+ verboselog( h8->device->machine(), 9, "TPU %d - tgrd match\n", x);
+ h8->per_regs[H8S_IO_TSR[x]] |= TSR_TGFD;
+ if (tier & TIER_TGIED)
+ {
+ h8s2xxx_interrupt_request( h8, H8S_INT_TGID[x]);
+ }
+ if (((tcr >> 5) & TCR_CCLR_AND[x]) == 6) // CCLR 6 -> "TCNT cleared by TGRD compare match/input capture"
+ {
+ clear = 1;
+ }
+ else
+ {
+ tior = h8->per_regs[H8S_IO_TIOR_L[x]];
+ h8s_tioc_pin_update( h8, (tior >> 4) & 0x0F, PIN_TIOCD[x]);
+ }
+ }
+ }
+ // ...
+ if (clear)
+ {
+ verboselog( h8->device->machine(), 9, "TPU %d - tcnt clear\n", x);
+ h8s_tpu_x_tioc_reset( h8, x);
+ tcnt = 0;
+ }
+ // ...
+ return tcnt;
+}
+
+void h8s_tpu_x_callback( h83xx_state *h8, int x)
+{
+ H8S2XXX_TPU *tpu = &h8->tpu[x];
+ UINT64 cycles;
+ UINT16 tcnt;
+ // calculate tcnt
+ tcnt = ptr_read_16( h8->per_regs + H8S_IO_TCNT_H[x]);
+ tcnt = (UINT16)(tcnt + tpu->timer_cycles / tpu->cycles_per_tick);
+ // ...
+ tcnt = h8s_tpu_x_tcnt_change( h8, x, tcnt);
+ // update tcnt
+ ptr_write_16( h8->per_regs + H8S_IO_TCNT_H[x], tcnt);
+ // update timer
+ cycles = h8s_tpu_x_calculate_ticks( h8, x, tcnt) * tpu->cycles_per_tick;
+ tpu->timer_cycles = cycles;
+ tpu->timer->adjust(attotime::from_hz(h8->device->unscaled_clock() / cycles), x);
+}
+
+void h8s_tpu_x_tick( h83xx_state *h8, int x)
+{
+ UINT16 tcnt;
+ // calculate tcnt
+ tcnt = ptr_read_16( h8->per_regs + H8S_IO_TCNT_H[x]);
+ tcnt = (UINT16)(tcnt + 1);
+ // ...
+ tcnt = h8s_tpu_x_tcnt_change( h8, x, tcnt);
+ // update tcnt
+ ptr_write_16( h8->per_regs + H8S_IO_TCNT_H[x], tcnt);
+}
+
+int h8s_tpu_x_get_div( h83xx_state *h8, int x)
+{
+ UINT8 tcr;
+ int tpsc;
+ const int *TPU_X_DIV[] = { TPU_0_DIV, TPU_1_DIV, TPU_2_DIV, TPU_3_DIV, TPU_4_DIV, TPU_5_DIV };
+ tcr = h8->per_regs[H8S_IO_TTCR[x]];
+ tpsc = (tcr >> 0) & 7;
+ return TPU_X_DIV[x][tpsc];
+}
+
+void h8s_tpu_x_update( h83xx_state *h8, int x)
+{
+ H8S2XXX_TPU *tpu = &h8->tpu[x];
+ // ...
+ tpu->cycles_per_tick = h8s_tpu_x_get_div( h8, x);
+ // update timer
+ if (tpu->cycles_per_tick != 0)
+ {
+ UINT16 tcnt;
+ UINT64 cycles;
+ tcnt = ptr_read_16( h8->per_regs + H8S_IO_TCNT_H[x]);
+ cycles = h8s_tpu_x_calculate_ticks( h8, x, tcnt) * tpu->cycles_per_tick;
+ tpu->timer_cycles = cycles;
+ tpu->timer->adjust(attotime::from_hz(h8->device->unscaled_clock() / cycles), x);
+ }
+ else
+ {
+ tpu->timer->reset();
+ }
+}
+
+void h8s_tpu_x_start( h83xx_state *h8, int x)
+{
+ verboselog( h8->device->machine(), 5, "TPU %d - start\n", x);
+ // ...
+ h8s_tpu_x_update( h8, x);
+}
+
+void h8s_tpu_x_stop( h83xx_state *h8, int x)
+{
+ H8S2XXX_TPU *tpu = &h8->tpu[x];
+ UINT16 tcnt;
+ // ...
+ verboselog( h8->device->machine(), 5, "TPU %d - stop\n", x);
+ // calculate tcnt
+ tcnt = h8s_tpu_x_calculate_tcnt( h8, x);
+ // update tcnt
+ ptr_write_16( h8->per_regs + H8S_IO_TCNT_H[x], tcnt);
+ // disable timer
+ tpu->timer->reset();
+}
+
+UINT16 h8s_tpu_x_read_tcnt( h83xx_state *h8, int x)
+{
+ return h8s_tpu_x_calculate_tcnt( h8, x);
+}
+
+void h8s_tpu_x_write_tcnt( h83xx_state *h8, int x, UINT16 data)
+{
+ H8S2XXX_TPU *tpu = &h8->tpu[x];
+ verboselog( h8->device->machine(), 9, "TPU %d - write tcnt (%04X)\n", x, data);
+ ptr_write_16( h8->per_regs + H8S_IO_TCNT_H[x], data);
+ if (tpu->timer->enabled())
+ {
+ h8s_tpu_x_update( h8, x);
+ }
+}
+
+void h8s_tpu_x_write_tgr( h83xx_state *h8, int x)
+{
+ H8S2XXX_TPU *tpu = &h8->tpu[x];
+ if ((tpu->timer->enabled()) && (tpu->cycles_per_tick != 0))
+ {
+ UINT16 tcnt1, tcnt2;
+ UINT64 cycles;
+ tcnt1 = ptr_read_16( h8->per_regs + H8S_IO_TCNT_H[x]);
+ tcnt2 = (UINT16)(tcnt1 + ((device_icount_min_timer_icount1( h8, tpu->timer)) / tpu->cycles_per_tick));
+ cycles = h8s_tpu_x_calculate_ticks( h8, x, tcnt2) * tpu->cycles_per_tick;
+ cycles = cycles + (tcnt2 - tcnt1) * tpu->cycles_per_tick;
+ tpu->timer_cycles = cycles;
+ tpu->timer->adjust(attotime::from_hz(h8->device->unscaled_clock() / cycles), x);
+ }
+}
+
+void h8s_tpu_x_write_tgra( h83xx_state *h8, int x, UINT16 data)
+{
+ verboselog( h8->device->machine(), 9, "TPU %d - write tgra (%04X)\n", x, data);
+ ptr_write_16( h8->per_regs + H8S_IO_TGRA_H[x], data);
+ h8s_tpu_x_write_tgr( h8, x);
+}
+
+void h8s_tpu_x_write_tgrb( h83xx_state *h8, int x, UINT16 data)
+{
+ verboselog( h8->device->machine(), 9, "TPU %d - write tgrb (%04X)\n", x, data);
+ ptr_write_16( h8->per_regs + H8S_IO_TGRB_H[x], data);
+ h8s_tpu_x_write_tgr( h8, x);
+}
+
+void h8s_tpu_x_write_tgrc( h83xx_state *h8, int x, UINT16 data)
+{
+ verboselog( h8->device->machine(), 9, "TPU %d - write tgrc (%04X)\n", x, data);
+ ptr_write_16( h8->per_regs + H8S_IO_TGRC_H[x], data);
+ h8s_tpu_x_write_tgr( h8, x);
+}
+
+void h8s_tpu_x_write_tgrd( h83xx_state *h8, int x, UINT16 data)
+{
+ verboselog( h8->device->machine(), 9, "TPU %d - write tgrd (%04X)\n", x, data);
+ ptr_write_16( h8->per_regs + H8S_IO_TGRD_H[x], data);
+ h8s_tpu_x_write_tgr( h8, x);
+}
+
+void h8s_tpu_x_write_tior( h83xx_state *h8, int x)
+{
+ UINT8 tstr;
+ tstr = h8->per_regs[H8S_IO_TSTR];
+ if ((tstr & (1 << x)) == 0)
+ {
+ h8s_tpu_x_tioc_reset( h8, x);
+ }
+}
+
+void h8s_tpu_0_write_tior_h( h83xx_state *h8, UINT8 data)
+{
+ h8->per_regs[H8S_IO_TIOR0_H] = data;
+ h8s_tpu_x_write_tior( h8, 0);
+}
+
+void h8s_tpu_0_write_tior_l( h83xx_state *h8, UINT8 data)
+{
+ h8->per_regs[H8S_IO_TIOR0_L] = data;
+ h8s_tpu_x_write_tior( h8, 0);
+}
+
+void h8s_tpu_1_write_tior( h83xx_state *h8, UINT8 data)
+{
+ h8->per_regs[H8S_IO_TIOR1] = data;
+ h8s_tpu_x_write_tior( h8, 1);
+}
+
+void h8s_tpu_2_write_tior( h83xx_state *h8, UINT8 data)
+{
+ h8->per_regs[H8S_IO_TIOR2] = data;
+ h8s_tpu_x_write_tior( h8, 2);
+}
+
+void h8s_tpu_3_write_tior_h( h83xx_state *h8, UINT8 data)
+{
+ h8->per_regs[H8S_IO_TIOR3_H] = data;
+ h8s_tpu_x_write_tior( h8, 3);
+}
+
+void h8s_tpu_3_write_tior_l( h83xx_state *h8, UINT8 data)
+{
+ h8->per_regs[H8S_IO_TIOR3_L] = data;
+ h8s_tpu_x_write_tior( h8, 3);
+}
+
+void h8s_tpu_4_write_tior( h83xx_state *h8, UINT8 data)
+{
+ h8->per_regs[H8S_IO_TIOR4] = data;
+ h8s_tpu_x_write_tior( h8, 4);
+}
+
+void h8s_tpu_5_write_tior( h83xx_state *h8, UINT8 data)
+{
+ h8->per_regs[H8S_IO_TIOR5] = data;
+ h8s_tpu_x_write_tior( h8, 5);
+}
+
+void h8s_tpu_write_tstr( h83xx_state *h8, UINT8 data)
+{
+ const int tpu_max = (h8->device->type() == H8S2323) ? 6 : 3;
+ UINT8 old_data = h8->per_regs[H8S_IO_TSTR];
+ int i;
+ h8->per_regs[H8S_IO_TSTR] = data;
+ for (i = 0; i < tpu_max; i++)
+ {
+ if ((data & (1 << i)) != (old_data & (1 << i)))
+ {
+ if ((data & (1 << i)) != 0)
+ {
+ h8s_tpu_x_start( h8, i);
+ }
+ else
+ {
+ h8s_tpu_x_stop( h8, i);
+ }
+ }
+ }
+}
+
+static TIMER_CALLBACK( h8s_tpu_callback)
+{
+ h83xx_state *h8 = (h83xx_state *)ptr;
+ h8s_tpu_x_callback( h8, param);
+}
+
+/////////////////////////////////
+// SERIAL CONTROLLER INTERFACE //
+/////////////////////////////////
+
+typedef struct
+{
+ UINT32 reg_smr, reg_brr, reg_scr, reg_tdr, reg_ssr, reg_rdr;
+ UINT32 reg_pdr, reg_port;
+ UINT8 port_mask_sck, port_mask_txd, port_mask_rxd;
+ UINT8 int_tx, int_rx;
+} H8S_SCI_ENTRY;
+
+const H8S_SCI_ENTRY H8S_SCI_TABLE[] =
+{
+ // SCI 0
+ {
+ H8S_IO_SMR0, H8S_IO_BRR0, H8S_IO_SCR0, H8S_IO_TDR0, H8S_IO_SSR0, H8S_IO_RDR0,
+ H8S_IO_P3DR, H8S_IO_PORT3,
+ H8S_P3_SCK0, H8S_P3_TXD0, H8S_P3_RXD0,
+ H8S_INT_TXI0, H8S_INT_RXI0
+ },
+ // SCI 1
+ {
+ H8S_IO_SMR1, H8S_IO_BRR1, H8S_IO_SCR1, H8S_IO_TDR1, H8S_IO_SSR1, H8S_IO_RDR1,
+ H8S_IO_P3DR, H8S_IO_PORT3,
+ H8S_P3_SCK1, H8S_P3_TXD1, H8S_P3_RXD1,
+ H8S_INT_TXI1, H8S_INT_RXI1
+ },
+ // SCI 2
+ {
+ H8S_IO_SMR2, H8S_IO_BRR2, H8S_IO_SCR2, H8S_IO_TDR2, H8S_IO_SSR2, H8S_IO_RDR2,
+ H8S_IO_P5DR, H8S_IO_PORT5,
+ H8S_P5_SCK2, H8S_P5_TXD2, H8S_P5_RXD2,
+ H8S_INT_TXI2, H8S_INT_RXI2
+ }
+};
+
+const H8S_SCI_ENTRY *h8s_sci_entry( int num)
+{
+ return &H8S_SCI_TABLE[num];
+}
+
+void h8s_sci_init(h83xx_state *h8)
+{
+ int i;
+ for (i=0;i<3;i++)
+ {
+ h8->sci[i].timer = h8->device->machine().scheduler().timer_alloc(FUNC(h8s_sci_callback), h8);
+ h8->sci[i].timer->adjust(attotime::never, i);
+ }
+}
+
+static TIMER_CALLBACK(h8s_sci_callback)
+{
+ h83xx_state *h8 = (h83xx_state *)ptr;
+ verboselog( h8->device->machine(), 7, "h8s_sci_callback (%d)\n", param);
+}
+
+void h8s_sci_start(h83xx_state *h8, int num)
+{
+ #if 0
+ h8->sci[num].timer->adjust(h8->sci[num].bitrate, num);
+ #endif
+}
+
+void h8s_sci_stop(h83xx_state *h8, int num)
+{
+ h8->sci[num].timer->adjust(attotime::never, num);
+}
+
+void h8s_sci_execute(h83xx_state *h8, int num)
+{
+ UINT8 scr, tdr, ssr, rdr, tsr, rsr, pdr, port;
+ int i;
+ const H8S_SCI_ENTRY *info = h8s_sci_entry( num);
+ verboselog( h8->device->machine(), 5, "h8s_sci_execute(%d)\n", num);
+ // load regs
+ scr = h8->per_regs[info->reg_scr];
+ tdr = h8->per_regs[info->reg_tdr];
+ ssr = h8->per_regs[info->reg_ssr];
+ rdr = h8->per_regs[info->reg_rdr];
+ tsr = 0;
+ rsr = 0;
+ pdr = h8->per_regs[info->reg_pdr] & (~info->port_mask_sck);
+ // move byte from TDR to TSR
+ if (scr & H8S_SCR_TE)
+ {
+ tsr = tdr;
+ ssr |= H8S_SSR_TDRE;
+ }
+ // generate transmit data empty interrupt
+ if ((scr & H8S_SCR_TIE) && (ssr & H8S_SSR_TDRE)) h8s2xxx_interrupt_request(h8, info->int_tx);
+ // transmit/receive bits
+ for (i=0;i<8;i++)
+ {
+ // write bit
+ if (scr & H8S_SCR_TE)
+ {
+ if (tsr & (1 << i)) pdr = pdr | info->port_mask_txd; else pdr = pdr & (~info->port_mask_txd);
+ h8->io->write_byte( H8S_IO_ADDR( info->reg_pdr), pdr);
+ }
+ // clock high to low
+ h8->io->write_byte( H8S_IO_ADDR( info->reg_pdr), pdr | info->port_mask_sck);
+ h8->io->write_byte( H8S_IO_ADDR( info->reg_pdr), pdr);
+ // read bit
+ if (scr & H8S_SCR_RE)
+ {
+ port = h8->io->read_byte(H8S_IO_ADDR( info->reg_port));
+ if (port & info->port_mask_rxd) rsr = rsr | (1 << i);
+ }
+ }
+ // move byte from RSR to RDR
+ if (scr & H8S_SCR_RE)
+ {
+ rdr = rsr;
+ //ssr |= H8S_SSR_RDRF;
+ }
+ // generate receive data full interrupt
+ if ((scr & H8S_SCR_RIE) && (ssr & H8S_SSR_RDRF)) h8s2xxx_interrupt_request(h8, info->int_rx);
+ // save regs
+ h8->per_regs[info->reg_scr] = scr;
+ h8->per_regs[info->reg_tdr] = tdr;
+ h8->per_regs[info->reg_ssr] = ssr;
+ h8->per_regs[info->reg_rdr] = rdr;
+}
+
+const double SCR_CKE[] = { 0.5, 2, 8, 32 }; // = 2 ^ ((2 * cke) - 1)
+const int SMR_MODE[] = { 64, 8 };
+
+void h8s_sci_rate(h83xx_state *h8, int num)
+{
+ UINT8 brr, scr, smr, cke, mode;
+ UINT32 bitrate;
+ const H8S_SCI_ENTRY *info = h8s_sci_entry( num);
+ // read regs
+ brr = h8->per_regs[info->reg_brr];
+ scr = h8->per_regs[info->reg_scr];
+ smr = h8->per_regs[info->reg_smr];
+ verboselog( h8->device->machine(), 2, "BRR %02X SCR %02X SMR %02X\n", brr, scr, smr);
+ // calculate bitrate
+ cke = (scr >> 0) & 3;
+ mode = (smr >> 7) & 1;
+ bitrate = (UINT32)((h8->device->unscaled_clock() / (brr + 1)) / (SMR_MODE[mode] * SCR_CKE[cke]));
+ verboselog( h8->device->machine(), 2, "SCI%d bitrate %d\n", num, bitrate);
+ // store bitrate
+ h8->sci[num].bitrate = bitrate;
+}
+
+////////////////////////////
+// INTERNAL I/O REGISTERS //
+////////////////////////////
+
+void h8s_onchip_reg_write_8(h83xx_state *h8, int offset, UINT8 data)
+{
+ verboselog( h8->device->machine(), 9, "%08X | %08X <- %02X\n", h8->ppc, H8S_IO_ADDR(offset), data);
+ switch (offset)
+ {
+ // SCI 0
+ case H8S_IO_SSR0 : h8->per_regs[offset] = data; if ((data & H8S_SSR_TDRE) == 0) h8s_sci_execute(h8, 0); break;
+ case H8S_IO_SCR0 : h8->per_regs[offset] = data; if (data & H8S_SCR_TIE) h8s2xxx_interrupt_request(h8, h8s_sci_entry(0)->int_tx); break;
+ case H8S_IO_BRR0 : h8->per_regs[offset] = data; h8s_sci_rate(h8, 0); h8s_sci_start(h8, 0); break;
+ // SCI 1
+ case H8S_IO_SSR1 : h8->per_regs[offset] = data; if ((data & H8S_SSR_TDRE) == 0) h8s_sci_execute(h8, 1); break;
+ case H8S_IO_SCR1 : h8->per_regs[offset] = data; if (data & H8S_SCR_RIE) h8s2xxx_interrupt_request(h8, h8s_sci_entry(1)->int_rx); break;
+ case H8S_IO_BRR1 : h8->per_regs[offset] = data; h8s_sci_rate(h8, 1); h8s_sci_start(h8, 1); break;
+ // SCI 2
+ case H8S_IO_SSR2 : h8->per_regs[offset] = data; if ((data & H8S_SSR_TDRE) == 0) h8s_sci_execute(h8, 2); break;
+ case H8S_IO_SCR2 : h8->per_regs[offset] = data; if (data & H8S_SCR_TIE) h8s2xxx_interrupt_request(h8, h8s_sci_entry(2)->int_tx); break;
+ case H8S_IO_BRR2 : h8->per_regs[offset] = data; h8s_sci_rate(h8, 2); h8s_sci_start(h8, 2); break;
+ // TMR 0
+ case H8S_IO_TCR0 : h8s_tmr_x_write_tcr( h8, 0, data); break;
+ case H8S_IO_TCNT0 : h8s_tmr_x_write_tcnt( h8, 0, data); break;
+ case H8S_IO_TCORA0 : h8s_tmr_x_write_tcora( h8, 0, data); break;
+ case H8S_IO_TCORB0 : h8s_tmr_x_write_tcorb( h8, 0, data); break;
+ // TMR 1
+ case H8S_IO_TCR1 : h8s_tmr_x_write_tcr( h8, 1, data); break;
+ case H8S_IO_TCNT1 : h8s_tmr_x_write_tcnt( h8, 1, data); break;
+ case H8S_IO_TCORA1 : h8s_tmr_x_write_tcora( h8, 1, data); break;
+ case H8S_IO_TCORB1 : h8s_tmr_x_write_tcorb( h8, 1, data); break;
+ // ports
+ case H8S_IO_P1DR : case H8S_IO_P2DR : case H8S_IO_P3DR : case H8S_IO_P4DR : case H8S_IO_P5DR :
+ case H8S_IO_PADR : case H8S_IO_PBDR : case H8S_IO_PCDR : case H8S_IO_PDDR : case H8S_IO_PEDR :
+ case H8S_IO_PFDR : h8->per_regs[offset] = data; h8->io->write_byte( H8S_IO_ADDR( offset), data); break;
+ // ...
+ case H8S_IO_PFDDR : h8->per_regs[offset] = data; h8->io->write_byte( H8S_IO_ADDR( offset), data); break;
+ // TPU
+ case H8S_IO_TSTR : h8s_tpu_write_tstr( h8, data); break;
+ // DMA
+ case H8S_IO_DMABCRL :
+ {
+ h8->per_regs[offset] = data;
+ if (h8->device->type() == H8S2323)
+ {
+ if ((data & 0x40) && (data & 0x80))
+ {
+ UINT32 i, dma_src, dma_dst;
+ UINT16 dma_cnt, dma_con;
+ int sz;
+ dma_src = h8->program->read_dword( H8S_IO_ADDR(H8S_IO_MAR1AH));
+ dma_dst = h8->program->read_dword( H8S_IO_ADDR(H8S_IO_MAR1BH));
+ dma_cnt = h8->program->read_word( H8S_IO_ADDR(H8S_IO_ETCR1A));
+ dma_con = h8->program->read_word( H8S_IO_ADDR(H8S_IO_DMACR1A));
+ sz = (dma_con & 0x8000) ? 2 : 1;
+ for (i=0;i<dma_cnt;i++)
+ {
+ if (dma_con & 0x8000) h8->program->write_word( dma_dst, h8->program->read_word( dma_src)); else h8->program->write_byte( dma_dst, h8->program->read_byte( dma_src));
+ if (dma_con & 0x2000) { if (dma_con & 0x4000) dma_src -= sz; else dma_src += sz; }
+ if (dma_con & 0x0020) { if (dma_con & 0x0040) dma_dst -= sz; else dma_dst += sz; }
+ }
+ h8->per_regs[H8S_IO_DMABCRL] &= ~0x40;
+ }
+ }
+ }
+ break;
+ // ...
+ default :
+ {
+ h8->per_regs[offset] = data;
+ }
+ break;
+ }
+}
+
+void h8s_onchip_reg_write_16(h83xx_state *h8, int offset, UINT16 data)
+{
+ verboselog( h8->device->machine(), 9, "%08X | %08X <- %04X\n", h8->ppc, H8S_IO_ADDR(offset), data);
+ switch (offset)
+ {
+ // TPU 0
+ case H8S_IO_TCNT0_H : h8s_tpu_x_write_tcnt( h8, 0, data); break;
+ case H8S_IO_TGR0A_H : h8s_tpu_x_write_tgra( h8, 0, data); break;
+ case H8S_IO_TGR0B_H : h8s_tpu_x_write_tgrb( h8, 0, data); break;
+ case H8S_IO_TGR0C_H : h8s_tpu_x_write_tgrc( h8, 0, data); break;
+ case H8S_IO_TGR0D_H : h8s_tpu_x_write_tgrd( h8, 0, data); break;
+ // TPU 1
+ case H8S_IO_TCNT1_H : h8s_tpu_x_write_tcnt( h8, 1, data); break;
+ case H8S_IO_TGR1A_H : h8s_tpu_x_write_tgra( h8, 1, data); break;
+ case H8S_IO_TGR1B_H : h8s_tpu_x_write_tgrb( h8, 1, data); break;
+ // TPU 2
+ case H8S_IO_TCNT2_H : h8s_tpu_x_write_tcnt( h8, 2, data); break;
+ case H8S_IO_TGR2A_H : h8s_tpu_x_write_tgra( h8, 2, data); break;
+ case H8S_IO_TGR2B_H : h8s_tpu_x_write_tgrb( h8, 2, data); break;
+ // TPU 3
+ case H8S_IO_TCNT3_H : if (h8->device->type() == H8S2323) h8s_tpu_x_write_tcnt( h8, 3, data); break;
+ case H8S_IO_TGR3A_H : if (h8->device->type() == H8S2323) h8s_tpu_x_write_tgra( h8, 3, data); break;
+ case H8S_IO_TGR3B_H : if (h8->device->type() == H8S2323) h8s_tpu_x_write_tgrb( h8, 3, data); break;
+ case H8S_IO_TGR3C_H : if (h8->device->type() == H8S2323) h8s_tpu_x_write_tgrc( h8, 3, data); break;
+ case H8S_IO_TGR3D_H : if (h8->device->type() == H8S2323) h8s_tpu_x_write_tgrd( h8, 3, data); break;
+ // TPU 4
+ case H8S_IO_TCNT4_H : if (h8->device->type() == H8S2323) h8s_tpu_x_write_tcnt( h8, 4, data); break;
+ case H8S_IO_TGR4A_H : if (h8->device->type() == H8S2323) h8s_tpu_x_write_tgra( h8, 4, data); break;
+ case H8S_IO_TGR4B_H : if (h8->device->type() == H8S2323) h8s_tpu_x_write_tgrb( h8, 4, data); break;
+ // TPU 5
+ case H8S_IO_TCNT5_H : if (h8->device->type() == H8S2323) h8s_tpu_x_write_tcnt( h8, 5, data); break;
+ case H8S_IO_TGR5A_H : if (h8->device->type() == H8S2323) h8s_tpu_x_write_tgra( h8, 5, data); break;
+ case H8S_IO_TGR5B_H : if (h8->device->type() == H8S2323) h8s_tpu_x_write_tgrb( h8, 5, data); break;
+ // ...
+ default :
+ {
+ h8s_onchip_reg_write_8( h8, offset + 0, (data >> 8) & 0xFF);
+ h8s_onchip_reg_write_8( h8, offset + 1, (data >> 0) & 0xFF);
+ }
+ break;
+ }
+}
+
+UINT8 h8s_onchip_reg_read_8(h83xx_state *h8, int offset)
+{
+ UINT8 data;
+ switch (offset)
+ {
+ // SCI 0
+ case H8S_IO_SSR0 : data = H8S_SSR_TDRE | H8S_SSR_TEND; break;
+ case H8S_IO_RDR0 : data = h8->io->read_byte( H8S_IO_ADDR( offset)); break;
+ // SCI 1
+ case H8S_IO_SSR1 : data = H8S_SSR_TDRE | H8S_SSR_TEND; break;
+ // SCI 2
+ case H8S_IO_SSR2 :
+ {
+ data = h8->per_regs[offset];
+ if (!(h8->per_regs[H8S_IO_SCR2] & H8S_SCR_TE)) data |= H8S_SSR_TDRE;
+ }
+ break;
+ // ports
+ case H8S_IO_PORT1 : case H8S_IO_PORT2 : case H8S_IO_PORT3 : case H8S_IO_PORT4 : case H8S_IO_PORT5 :
+ case H8S_IO_PORTA : case H8S_IO_PORTB : case H8S_IO_PORTC : case H8S_IO_PORTD : case H8S_IO_PORTE :
+ case H8S_IO_PORTF : data = h8->io->read_byte( H8S_IO_ADDR( offset)); break;
+ // ...
+ case H8S_IO_P3DR : data = 0; break; // todo: without this cybiko hangs
+ // TMR 0
+ case H8S_IO_TCNT0 : data = h8s_tmr_x_read_tcnt( h8, 0); break;
+ // TMR 1
+ case H8S_IO_TCNT1 : data = h8s_tmr_x_read_tcnt( h8, 1); break;
+ // ...
+ // default
+ default : data = h8->per_regs[offset]; break;
+ }
+ verboselog( h8->device->machine(), 9, "%08X | %08X -> %02X\n", h8->ppc, H8S_IO_ADDR(offset), data);
+ return data;
+}
+
+UINT16 h8s_onchip_reg_read_16(h83xx_state *h8, int offset)
+{
+ UINT16 data = 0;
+ switch (offset)
+ {
+ case H8S_IO_TCNT0_H : data = h8s_tpu_x_read_tcnt( h8, 0); break;
+ case H8S_IO_TCNT1_H : data = h8s_tpu_x_read_tcnt( h8, 1); break;
+ case H8S_IO_TCNT2_H : data = h8s_tpu_x_read_tcnt( h8, 2); break;
+ case H8S_IO_TCNT3_H : if (h8->device->type() == H8S2323) data = h8s_tpu_x_read_tcnt( h8, 3); break;
+ case H8S_IO_TCNT4_H : if (h8->device->type() == H8S2323) data = h8s_tpu_x_read_tcnt( h8, 4); break;
+ case H8S_IO_TCNT5_H : if (h8->device->type() == H8S2323) data = h8s_tpu_x_read_tcnt( h8, 5); break;
+ default :
+ {
+ UINT8 b[2];
+ b[0] = h8s_onchip_reg_read_8( h8, offset + 0);
+ b[1] = h8s_onchip_reg_read_8( h8, offset + 1);
+ data = (b[0] << 8) | (b[1] << 0);
+ }
+ break;
+ }
+ verboselog( h8->device->machine(), 9, "%08X | %08X -> %04X\n", h8->ppc, H8S_IO_ADDR(offset), data);
+ return data;
+}
+
+void h8s2241_per_regs_write_8(h83xx_state *h8, int offset, UINT8 data)
+{
+ h8s_onchip_reg_write_8(h8, offset, data);
+}
+
+UINT8 h8s2241_per_regs_read_8(h83xx_state *h8, int offset)
+{
+ return h8s_onchip_reg_read_8(h8, offset);
+}
+
+void h8s2241_per_regs_write_16(h83xx_state *h8, int offset, UINT16 data)
+{
+ h8s_onchip_reg_write_16(h8, offset, data);
+}
+
+UINT16 h8s2241_per_regs_read_16(h83xx_state *h8, int offset)
+{
+ return h8s_onchip_reg_read_16(h8, offset);
+}
+
+void h8s2246_per_regs_write_8(h83xx_state *h8, int offset, UINT8 data)
+{
+ h8s_onchip_reg_write_8(h8, offset, data);
+}
+
+UINT8 h8s2246_per_regs_read_8(h83xx_state *h8, int offset)
+{
+ return h8s_onchip_reg_read_8(h8, offset);
+}
+
+void h8s2246_per_regs_write_16(h83xx_state *h8, int offset, UINT16 data)
+{
+ h8s_onchip_reg_write_16(h8, offset, data);
+}
+
+UINT16 h8s2246_per_regs_read_16(h83xx_state *h8, int offset)
+{
+ return h8s_onchip_reg_read_16(h8, offset);
+}
+
+void h8s2323_per_regs_write_8(h83xx_state *h8, int offset, UINT8 data)
+{
+ h8s_onchip_reg_write_8(h8, offset, data);
+}
+
+UINT8 h8s2323_per_regs_read_8(h83xx_state *h8, int offset)
+{
+ return h8s_onchip_reg_read_8(h8, offset);
+}
+
+void h8s2323_per_regs_write_16(h83xx_state *h8, int offset, UINT16 data)
+{
+ h8s_onchip_reg_write_16(h8, offset, data);
+}
+
+UINT16 h8s2323_per_regs_read_16(h83xx_state *h8, int offset)
+{
+ return h8s_onchip_reg_read_16(h8, offset);
+}
diff --git a/trunk/src/emu/cpu/hcd62121/hcd62121.c b/trunk/src/emu/cpu/hcd62121/hcd62121.c
new file mode 100644
index 00000000000..1ab2de40414
--- /dev/null
+++ b/trunk/src/emu/cpu/hcd62121/hcd62121.c
@@ -0,0 +1,512 @@
+/**********************************************************************
+
+ Hitachi hcd62121 cpu core emulation.
+
+The Hitachi hcd62121 is the custom cpu which was used in the Casio
+CFX-9850 (and maybe some other things too).
+
+This CPU core is based on the information provided by Martin Poupe.
+Martin Poupe's site can be found at http://prg.rkk.cz/~mpoupe/
+
+**********************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "hcd62121.h"
+
+
+struct _hcd62121_state
+{
+ UINT32 prev_pc;
+ UINT16 sp;
+ UINT16 ip;
+ UINT8 dsize;
+ UINT8 cseg;
+ UINT8 dseg;
+ UINT8 sseg;
+ UINT8 f;
+ UINT16 lar;
+ UINT8 reg[0x80];
+ UINT8 temp1[0x10];
+ UINT8 temp2[0x10];
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ address_space *program;
+ address_space *io;
+ int icount;
+};
+
+typedef struct _hcd62121_state hcd62121_state;
+
+
+/* From the battery check routine at 20:e874 it looks like
+ bit 3 of the flag register should be the Zero flag. */
+#define _FLAG_Z 0x08
+#define _FLAG_C 0x02
+#define _FLAG_ZL 0x04
+#define _FLAG_CL 0x01
+#define _FLAG_ZH 0x10
+
+
+#define mem_readbyte(cs,A) ((UINT8)(cs)->program->read_byte(A))
+#define mem_writebyte(cs,A,V) ((cs)->program->write_byte(A,V))
+#define io_readbyte(cs,A) ((UINT8)(cs)->io->read_byte(A))
+#define io_writebyte(cs,A,V) ((cs)->io->write_byte(A,V))
+
+
+INLINE UINT8 read_op(hcd62121_state *cpustate)
+{
+ UINT8 d = mem_readbyte(cpustate, ( cpustate->cseg << 16 ) | cpustate->ip );
+ cpustate->ip++;
+ return d;
+}
+
+
+INLINE UINT8 datasize( hcd62121_state *cpustate, UINT8 op )
+{
+ switch( op & 0x03 )
+ {
+ case 0:
+ return 1;
+ case 1:
+ return 2;
+ case 2:
+ return ( cpustate->dsize >> 4 ) + 1;
+ case 3:
+ return ( cpustate->dsize & 0x0f ) + 1;
+ }
+ return 1;
+}
+
+
+INLINE void read_reg( hcd62121_state *cpustate, int size, UINT8 op1 )
+{
+ int i;
+
+ if ( op1 & 0x80 )
+ {
+ for ( i = 0; i < size; i++ )
+ cpustate->temp1[i] = cpustate->reg[ ( op1 - i ) & 0x7f ];
+ }
+ else
+ {
+ for ( i = 0; i < size; i++ )
+ cpustate->temp1[i] = cpustate->reg[ ( op1 + i ) & 0x7f ];
+ }
+}
+
+
+INLINE void write_reg( hcd62121_state *cpustate, int size, UINT8 op1 )
+{
+ int i;
+
+ if ( op1 & 0x80 )
+ {
+ for ( i = 0; i < size; i++ )
+ cpustate->reg[ ( op1 - i ) & 0x7f ] = cpustate->temp1[i];
+ }
+ else
+ {
+ for ( i = 0; i < size; i++ )
+ cpustate->reg[ ( op1 + i ) & 0x7f ] = cpustate->temp1[i];
+ }
+}
+
+
+INLINE void read_regreg( hcd62121_state *cpustate, int size, UINT8 op1, UINT8 op2, bool op_is_logical )
+{
+ int i;
+
+ for ( i = 0; i < size; i++ )
+ cpustate->temp1[i] = cpustate->reg[ (op1 + i) & 0x7f];
+
+ if ( op1 & 0x80 )
+ {
+ /* Second operand is an immediate value */
+ cpustate->temp2[0] = op2;
+ for ( i = 1; i < size; i++ )
+ cpustate->temp2[i] = op_is_logical ? op2 : 0;
+ }
+ else
+ {
+ /* Second operand is a register */
+ for ( i = 0; i < size; i++ )
+ cpustate->temp2[i] = cpustate->reg[ (op2 + i) & 0x7f ];
+ }
+
+ if ( ! ( op1 & 0x80 ) && ! ( op2 & 0x80 ) )
+ {
+ /* We need to swap parameters */
+ for ( i = 0; i < size; i++ )
+ {
+ UINT8 v = cpustate->temp1[i];
+ cpustate->temp1[i] = cpustate->temp2[i];
+ cpustate->temp2[i] = v;
+ }
+ }
+}
+
+
+INLINE void write_regreg( hcd62121_state *cpustate, int size, UINT8 op1, UINT8 op2 )
+{
+ int i;
+
+ if ( ( op1 & 0x80 ) || ( op2 & 0x80 ) )
+ {
+ /* store in reg1 */
+ for ( i = 0; i < size; i++ )
+ cpustate->reg[ (op1 + i) & 0x7f] = cpustate->temp1[i];
+ }
+ else
+ {
+ /* store in reg2 */
+ for ( i = 0; i < size; i++ )
+ cpustate->reg[ (op2 + i) & 0x7f] = cpustate->temp1[i];
+ }
+}
+
+
+INLINE void read_iregreg( hcd62121_state *cpustate, int size, UINT8 op1, UINT8 op2 )
+{
+ int i;
+ UINT16 ad;
+
+ ad = cpustate->reg[ ( 0x40 | op1 ) & 0x7f ] | ( cpustate->reg[ ( 0x40 | ( op1 + 1 ) ) & 0x7f ] << 8 );
+
+ for ( i = 0; i < size; i++ )
+ {
+ cpustate->temp1[i] = mem_readbyte( cpustate, ( cpustate->dseg << 16 ) | ad );
+ ad += ( op1 & 0x40 ) ? -1 : 1;
+ }
+ cpustate->lar = ad;
+
+ if ( op1 & 0x80 )
+ {
+ cpustate->temp2[0] = op2;
+ for ( i = 1; i < size; i++ )
+ cpustate->temp2[i] = 0;
+ }
+ else
+ {
+ for ( i = 0; i < size; i++ )
+ cpustate->temp2[i] = cpustate->reg[ (op2 + i) & 0x7f ];
+ }
+
+ if ( ! ( op1 & 0x80 ) && ! ( op2 & 0x80 ) )
+ {
+ /* We need to swap parameters */
+ for ( i = 0; i < size; i++ )
+ {
+ UINT8 v = cpustate->temp1[i];
+ cpustate->temp1[i] = cpustate->temp2[i];
+ cpustate->temp2[i] = v;
+ }
+ }
+}
+
+
+INLINE void write_iregreg( hcd62121_state *cpustate, int size, UINT8 op1, UINT8 op2 )
+{
+ int i;
+
+ if ( ( op1 & 0x80 ) || ( op2 & 0x80 ) )
+ {
+ /* store in (reg1) */
+ UINT16 ad = cpustate->reg[ ( 0x40 | op1 ) & 0x7f ] | ( cpustate->reg[ ( 0x40 | ( op1 + 1 ) ) & 0x7f ] << 8 );
+
+ for ( i = 0; i < size; i++ )
+ {
+ mem_writebyte( cpustate, ( cpustate->dseg << 16 ) | ad, cpustate->temp1[i] );
+ ad += ( op1 & 0x40 ) ? -1 : 1;
+ }
+ cpustate->lar = ad;
+ }
+ else
+ {
+ /* store in reg2 */
+ for ( i = 0; i < size; i++ )
+ cpustate->reg[ (op2 + i) & 0x7f] = cpustate->temp1[i];
+ }
+}
+
+
+INLINE void write_iregreg2( hcd62121_state *cpustate, int size, UINT8 op1, UINT8 op2 )
+{
+ int i;
+
+ if ( ( op1 & 0x80 ) || ( op2 & 0x80 ) )
+ {
+ /* store in reg2 */
+ for ( i = 0; i < size; i++ )
+ cpustate->reg[ (op2 + i) & 0x7f] = cpustate->temp2[i];
+ }
+ else
+ {
+ /* store in (reg1) */
+ UINT16 ad = cpustate->reg[ ( 0x40 | op1 ) & 0x7f ] | ( cpustate->reg[ ( 0x40 | ( op1 + 1 ) ) & 0x7f ] << 8 );
+
+ for ( i = 0; i < size; i++ )
+ {
+ mem_writebyte( cpustate, ( cpustate->dseg << 16 ) | ad, cpustate->temp2[i] );
+ ad += ( op1 & 0x40 ) ? -1 : 1;
+ }
+ cpustate->lar = ad;
+ }
+}
+
+
+INLINE int check_cond( hcd62121_state *cpustate, UINT8 op )
+{
+ switch ( op & 0x07 )
+ {
+ case 0x00: /* ZH set */
+ if ( cpustate->f & _FLAG_ZH )
+ return 1;
+ break;
+
+ case 0x01: /* ZL set */
+ if ( cpustate->f & _FLAG_ZL )
+ return 1;
+ break;
+
+ case 0x02: /* C set */
+ if ( cpustate->f & _FLAG_C )
+ return 1;
+ break;
+
+ case 0x03: /* Z set */
+ if ( cpustate->f & _FLAG_Z )
+ return 1;
+ break;
+
+ case 0x04: /* Z or C set */
+ if ( cpustate->f & ( _FLAG_Z | _FLAG_C ) )
+ return 1;
+ break;
+
+ case 0x05: /* CL set */
+ if ( cpustate->f & _FLAG_CL )
+ return 1;
+ break;
+
+ case 0x06: /* C clear */
+ if ( ! ( cpustate->f & _FLAG_C ) )
+ return 1;
+ break;
+
+ case 0x07: /* Z clear */
+ if ( ! ( cpustate->f & _FLAG_Z ) )
+ return 1;
+ break;
+ }
+
+ return 0;
+}
+
+
+INLINE hcd62121_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == HCD62121);
+ return (hcd62121_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+
+static CPU_INIT( hcd62121 )
+{
+ hcd62121_state *cpustate = get_safe_token(device);
+
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->io = device->space(AS_IO);
+}
+
+
+static CPU_RESET( hcd62121 )
+{
+ hcd62121_state *cpustate = get_safe_token(device);
+
+ cpustate->sp = 0x0000;
+ cpustate->ip = 0x0000;
+ cpustate->cseg = 0;
+ cpustate->dseg = 0;
+ cpustate->sseg = 0;
+ cpustate->lar = 0;
+ cpustate->f = 0;
+ cpustate->dsize = 0;
+
+ for( int i = 0; i < 0x80; i++ )
+ {
+ cpustate->reg[i] = 0;
+ }
+}
+
+
+static CPU_EXECUTE( hcd62121 )
+{
+ hcd62121_state *cpustate = get_safe_token(device);
+
+ do
+ {
+ UINT32 pc = ( cpustate->cseg << 16 ) | cpustate->ip;
+ UINT8 op;
+
+ debugger_instruction_hook(device, pc);
+ cpustate->prev_pc = pc;
+
+ op = read_op( cpustate );
+
+ cpustate->icount -= 4;
+
+ switch ( op )
+ {
+#include "hcd62121_ops.h"
+ };
+
+ } while (cpustate->icount > 0);
+}
+
+
+static CPU_SET_INFO( hcd62121 )
+{
+ hcd62121_state *cpustate = get_safe_token(device);
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + 0:
+ case CPUINFO_INT_INPUT_STATE + 1:
+ break;
+
+ case CPUINFO_INT_SP: cpustate->sp = info->i; break;
+ case CPUINFO_INT_PC: cpustate->ip = info->i; break;
+
+ case CPUINFO_INT_REGISTER + HCD62121_IP: cpustate->ip = info->i; break;
+ case CPUINFO_INT_REGISTER + HCD62121_SP: cpustate->sp = info->i; break;
+ case CPUINFO_INT_REGISTER + HCD62121_LAR: cpustate->lar = info->i; break;
+ case CPUINFO_INT_REGISTER + HCD62121_CS: cpustate->cseg = info->i; break;
+ case CPUINFO_INT_REGISTER + HCD62121_DS: cpustate->dseg = info->i; break;
+ case CPUINFO_INT_REGISTER + HCD62121_SS: cpustate->sseg = info->i; break;
+ case CPUINFO_INT_REGISTER + HCD62121_DSIZE: cpustate->dsize = info->i; break;
+// case CPUINFO_INT_REGISTER + HCD62121_R00: break;
+// case CPUINFO_INT_REGISTER + HCD62121_R02: break;
+ }
+}
+
+
+CPU_GET_INFO( hcd62121 )
+{
+ hcd62121_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(hcd62121_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 2; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0xff; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 18; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 4; /* right? */ break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 48; /* right? */ break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 24; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_SP: info->i = cpustate->sp; break;
+ case CPUINFO_INT_PC: info->i = ( cpustate->cseg << 16 ) | cpustate->ip; break;
+ case CPUINFO_INT_PREVIOUSPC: info->i = cpustate->prev_pc; break;
+
+ case CPUINFO_INT_INPUT_STATE + 0:
+ case CPUINFO_INT_INPUT_STATE + 1:
+ /* TODO */ break;
+
+ case CPUINFO_INT_REGISTER + HCD62121_IP: info->i = cpustate->ip; break;
+ case CPUINFO_INT_REGISTER + HCD62121_SP: info->i = cpustate->sp; break;
+ case CPUINFO_INT_REGISTER + HCD62121_LAR: info->i = cpustate->lar; break;
+ case CPUINFO_INT_REGISTER + HCD62121_CS: info->i = cpustate->cseg; break;
+ case CPUINFO_INT_REGISTER + HCD62121_DS: info->i = cpustate->dseg; break;
+ case CPUINFO_INT_REGISTER + HCD62121_SS: info->i = cpustate->sseg; break;
+ case CPUINFO_INT_REGISTER + HCD62121_DSIZE: info->i = cpustate->dsize; break;
+ case CPUINFO_INT_REGISTER + HCD62121_R00: info->i = ( cpustate->reg[0x00] << 24 ) | ( cpustate->reg[0x01] << 16 ) | ( cpustate->reg[0x02] << 8 ) | cpustate->reg[0x03]; break;
+// case CPUINFO_INT_REGISTER + HCD62121_R02: info->i = cpustate->; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(hcd62121); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(hcd62121); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(hcd62121); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(hcd62121); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(hcd62121); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "HCD62121"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Hitachi HCD62121"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "0.1"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright The MESS Team."); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%s-%s-%s-%c-%c",
+ cpustate->f & _FLAG_ZH ? "ZH":"__",
+ cpustate->f & _FLAG_CL ? "CL":"__",
+ cpustate->f & _FLAG_ZL ? "ZL":"__",
+ cpustate->f & _FLAG_C ? 'C':'_',
+ cpustate->f & _FLAG_Z ? 'Z':'_'
+ );
+ break;
+
+ case CPUINFO_STR_REGISTER + HCD62121_IP: sprintf(info->s, "IP:%04X", cpustate->ip); break;
+ case CPUINFO_STR_REGISTER + HCD62121_SP: sprintf(info->s, "SP:%04X", cpustate->sp); break;
+ case CPUINFO_STR_REGISTER + HCD62121_LAR: sprintf(info->s, "LAR:%04X", cpustate->lar); break;
+ case CPUINFO_STR_REGISTER + HCD62121_CS: sprintf(info->s, "CS:%02X", cpustate->cseg); break;
+ case CPUINFO_STR_REGISTER + HCD62121_DS: sprintf(info->s, "DS:%02X", cpustate->dseg); break;
+ case CPUINFO_STR_REGISTER + HCD62121_SS: sprintf(info->s, "SS:%02X", cpustate->sseg); break;
+ case CPUINFO_STR_REGISTER + HCD62121_DSIZE: sprintf(info->s, "DSIZE:%02X", cpustate->dsize); break;
+ case CPUINFO_STR_REGISTER + HCD62121_R00: sprintf(info->s, "R00:%02X%02X%02X%02X", cpustate->reg[0x00], cpustate->reg[0x01], cpustate->reg[0x02], cpustate->reg[0x03]); break;
+ case CPUINFO_STR_REGISTER + HCD62121_R04: sprintf(info->s, "R04:%02X%02X%02X%02X", cpustate->reg[0x04], cpustate->reg[0x05], cpustate->reg[0x06], cpustate->reg[0x07]); break;
+ case CPUINFO_STR_REGISTER + HCD62121_R08: sprintf(info->s, "R08:%02X%02X%02X%02X", cpustate->reg[0x08], cpustate->reg[0x09], cpustate->reg[0x0a], cpustate->reg[0x0b]); break;
+ case CPUINFO_STR_REGISTER + HCD62121_R0C: sprintf(info->s, "R0C:%02X%02X%02X%02X", cpustate->reg[0x0c], cpustate->reg[0x0d], cpustate->reg[0x0e], cpustate->reg[0x0f]); break;
+ case CPUINFO_STR_REGISTER + HCD62121_R10: sprintf(info->s, "R10:%02X%02X%02X%02X", cpustate->reg[0x10], cpustate->reg[0x11], cpustate->reg[0x12], cpustate->reg[0x13]); break;
+ case CPUINFO_STR_REGISTER + HCD62121_R14: sprintf(info->s, "R14:%02X%02X%02X%02X", cpustate->reg[0x14], cpustate->reg[0x15], cpustate->reg[0x16], cpustate->reg[0x17]); break;
+ case CPUINFO_STR_REGISTER + HCD62121_R18: sprintf(info->s, "R18:%02X%02X%02X%02X", cpustate->reg[0x18], cpustate->reg[0x19], cpustate->reg[0x1a], cpustate->reg[0x1b]); break;
+ case CPUINFO_STR_REGISTER + HCD62121_R1C: sprintf(info->s, "R1C:%02X%02X%02X%02X", cpustate->reg[0x1c], cpustate->reg[0x1d], cpustate->reg[0x1e], cpustate->reg[0x1f]); break;
+ case CPUINFO_STR_REGISTER + HCD62121_R20: sprintf(info->s, "R20:%02X%02X%02X%02X", cpustate->reg[0x20], cpustate->reg[0x21], cpustate->reg[0x22], cpustate->reg[0x23]); break;
+ case CPUINFO_STR_REGISTER + HCD62121_R24: sprintf(info->s, "R24:%02X%02X%02X%02X", cpustate->reg[0x24], cpustate->reg[0x25], cpustate->reg[0x26], cpustate->reg[0x27]); break;
+ case CPUINFO_STR_REGISTER + HCD62121_R28: sprintf(info->s, "R28:%02X%02X%02X%02X", cpustate->reg[0x28], cpustate->reg[0x29], cpustate->reg[0x2a], cpustate->reg[0x2b]); break;
+ case CPUINFO_STR_REGISTER + HCD62121_R2C: sprintf(info->s, "R2C:%02X%02X%02X%02X", cpustate->reg[0x2c], cpustate->reg[0x2d], cpustate->reg[0x2e], cpustate->reg[0x2f]); break;
+ case CPUINFO_STR_REGISTER + HCD62121_R30: sprintf(info->s, "R30:%02X%02X%02X%02X", cpustate->reg[0x30], cpustate->reg[0x31], cpustate->reg[0x32], cpustate->reg[0x33]); break;
+ case CPUINFO_STR_REGISTER + HCD62121_R34: sprintf(info->s, "R34:%02X%02X%02X%02X", cpustate->reg[0x34], cpustate->reg[0x35], cpustate->reg[0x36], cpustate->reg[0x37]); break;
+ case CPUINFO_STR_REGISTER + HCD62121_R38: sprintf(info->s, "R38:%02X%02X%02X%02X", cpustate->reg[0x38], cpustate->reg[0x39], cpustate->reg[0x3a], cpustate->reg[0x3b]); break;
+ case CPUINFO_STR_REGISTER + HCD62121_R3C: sprintf(info->s, "R3C:%02X%02X%02X%02X", cpustate->reg[0x3c], cpustate->reg[0x3d], cpustate->reg[0x3e], cpustate->reg[0x3f]); break;
+ case CPUINFO_STR_REGISTER + HCD62121_R40: sprintf(info->s, "R40:%02X%02X%02X%02X", cpustate->reg[0x40], cpustate->reg[0x41], cpustate->reg[0x42], cpustate->reg[0x43]); break;
+ case CPUINFO_STR_REGISTER + HCD62121_R44: sprintf(info->s, "R44:%02X%02X%02X%02X", cpustate->reg[0x44], cpustate->reg[0x45], cpustate->reg[0x46], cpustate->reg[0x47]); break;
+ case CPUINFO_STR_REGISTER + HCD62121_R48: sprintf(info->s, "R48:%02X%02X%02X%02X", cpustate->reg[0x48], cpustate->reg[0x49], cpustate->reg[0x4a], cpustate->reg[0x4b]); break;
+ case CPUINFO_STR_REGISTER + HCD62121_R4C: sprintf(info->s, "R4C:%02X%02X%02X%02X", cpustate->reg[0x4c], cpustate->reg[0x4d], cpustate->reg[0x4e], cpustate->reg[0x4f]); break;
+ case CPUINFO_STR_REGISTER + HCD62121_R50: sprintf(info->s, "R50:%02X%02X%02X%02X", cpustate->reg[0x50], cpustate->reg[0x51], cpustate->reg[0x52], cpustate->reg[0x53]); break;
+ case CPUINFO_STR_REGISTER + HCD62121_R54: sprintf(info->s, "R54:%02X%02X%02X%02X", cpustate->reg[0x54], cpustate->reg[0x55], cpustate->reg[0x56], cpustate->reg[0x57]); break;
+ case CPUINFO_STR_REGISTER + HCD62121_R58: sprintf(info->s, "R58:%02X%02X%02X%02X", cpustate->reg[0x58], cpustate->reg[0x59], cpustate->reg[0x5a], cpustate->reg[0x5b]); break;
+ case CPUINFO_STR_REGISTER + HCD62121_R5C: sprintf(info->s, "R5C:%02X%02X%02X%02X", cpustate->reg[0x5c], cpustate->reg[0x5d], cpustate->reg[0x5e], cpustate->reg[0x5f]); break;
+ case CPUINFO_STR_REGISTER + HCD62121_R60: sprintf(info->s, "R60:%02X%02X%02X%02X", cpustate->reg[0x60], cpustate->reg[0x61], cpustate->reg[0x62], cpustate->reg[0x63]); break;
+ case CPUINFO_STR_REGISTER + HCD62121_R64: sprintf(info->s, "R64:%02X%02X%02X%02X", cpustate->reg[0x64], cpustate->reg[0x65], cpustate->reg[0x66], cpustate->reg[0x67]); break;
+ case CPUINFO_STR_REGISTER + HCD62121_R68: sprintf(info->s, "R68:%02X%02X%02X%02X", cpustate->reg[0x68], cpustate->reg[0x69], cpustate->reg[0x6a], cpustate->reg[0x6b]); break;
+ case CPUINFO_STR_REGISTER + HCD62121_R6C: sprintf(info->s, "R6C:%02X%02X%02X%02X", cpustate->reg[0x6c], cpustate->reg[0x6d], cpustate->reg[0x6e], cpustate->reg[0x6f]); break;
+ case CPUINFO_STR_REGISTER + HCD62121_R70: sprintf(info->s, "R70:%02X%02X%02X%02X", cpustate->reg[0x70], cpustate->reg[0x71], cpustate->reg[0x72], cpustate->reg[0x73]); break;
+ case CPUINFO_STR_REGISTER + HCD62121_R74: sprintf(info->s, "R74:%02X%02X%02X%02X", cpustate->reg[0x74], cpustate->reg[0x75], cpustate->reg[0x76], cpustate->reg[0x77]); break;
+ case CPUINFO_STR_REGISTER + HCD62121_R78: sprintf(info->s, "R78:%02X%02X%02X%02X", cpustate->reg[0x78], cpustate->reg[0x79], cpustate->reg[0x7a], cpustate->reg[0x7b]); break;
+ case CPUINFO_STR_REGISTER + HCD62121_R7C: sprintf(info->s, "R7C:%02X%02X%02X%02X", cpustate->reg[0x7c], cpustate->reg[0x7d], cpustate->reg[0x7e], cpustate->reg[0x7f]); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(HCD62121, hcd62121);
+
diff --git a/trunk/src/emu/cpu/hcd62121/hcd62121.h b/trunk/src/emu/cpu/hcd62121/hcd62121.h
new file mode 100644
index 00000000000..3301dda59c6
--- /dev/null
+++ b/trunk/src/emu/cpu/hcd62121/hcd62121.h
@@ -0,0 +1,40 @@
+#ifndef __HCD62121_H__
+#define __HCD62121_H__
+
+
+enum
+{
+ HCD62121_IP=1, HCD62121_SP, HCD62121_F, HCD62121_LAR,
+ HCD62121_CS, HCD62121_DS, HCD62121_SS, HCD62121_DSIZE,
+ /* 128 byte register file */
+ HCD62121_R00, HCD62121_R04, HCD62121_R08, HCD62121_R0C,
+ HCD62121_R10, HCD62121_R14, HCD62121_R18, HCD62121_R1C,
+ HCD62121_R20, HCD62121_R24, HCD62121_R28, HCD62121_R2C,
+ HCD62121_R30, HCD62121_R34, HCD62121_R38, HCD62121_R3C,
+ HCD62121_R40, HCD62121_R44, HCD62121_R48, HCD62121_R4C,
+ HCD62121_R50, HCD62121_R54, HCD62121_R58, HCD62121_R5C,
+ HCD62121_R60, HCD62121_R64, HCD62121_R68, HCD62121_R6C,
+ HCD62121_R70, HCD62121_R74, HCD62121_R78, HCD62121_R7C,
+};
+
+
+/* I/O ports */
+enum
+{
+ /* Output ports */
+ HCD62121_KOL=0x00,
+ HCD62121_KOH,
+ /* Input ports */
+ HCD62121_KI,
+ /* Other I/O ports */
+ HCD62121_IN0
+};
+
+
+DECLARE_LEGACY_CPU_DEVICE(HCD62121, hcd62121);
+
+
+extern CPU_DISASSEMBLE( hcd62121 );
+
+#endif /* __HCD62121_H__ */
+
diff --git a/trunk/src/emu/cpu/hcd62121/hcd62121_ops.h b/trunk/src/emu/cpu/hcd62121/hcd62121_ops.h
new file mode 100644
index 00000000000..9eaf6386a9b
--- /dev/null
+++ b/trunk/src/emu/cpu/hcd62121/hcd62121_ops.h
@@ -0,0 +1,1023 @@
+
+#define HCD62121_MSK \
+ { \
+ int i; \
+ UINT8 mskres = 1; \
+ \
+ for ( i = 0; i < size; i++ ) \
+ { \
+ if ( ( cpustate->temp1[i] & cpustate->temp2[i] ) != cpustate->temp2[i] ) \
+ mskres = 0; \
+ } \
+ \
+ if ( mskres ) \
+ cpustate->f &= ~_FLAG_Z; \
+ else \
+ cpustate->f |= _FLAG_Z; \
+ }
+
+#define HCD62121_IMSK \
+ { \
+ int i; \
+ UINT8 mskres = 1; \
+ UINT8 set_zero = 0; \
+ \
+ for ( i = 0; i < size; i++ ) \
+ { \
+ if ( ( cpustate->temp1[i] & ~cpustate->temp2[i] ) != ~cpustate->temp2[i] ) \
+ mskres = 0; \
+ if ( cpustate->temp1[i] | cpustate->temp2[i] ) \
+ set_zero = 1; \
+ } \
+ \
+ if ( set_zero ) \
+ cpustate->f |= _FLAG_Z; \
+ else \
+ cpustate->f &= ~_FLAG_Z; \
+ \
+ if ( mskres ) \
+ cpustate->f &= ~_FLAG_C; \
+ else \
+ cpustate->f |= _FLAG_C; \
+ }
+
+
+#define HCD62121_AND \
+ { \
+ int i; \
+ UINT8 is_zero = 1; \
+ \
+ for ( i = 0; i < size; i++ ) \
+ { \
+ cpustate->temp1[i] = cpustate->temp1[i] & cpustate->temp2[i]; \
+ if ( cpustate->temp1[i] ) \
+ is_zero = 0; \
+ } \
+ \
+ if ( is_zero ) \
+ cpustate->f |= _FLAG_Z; \
+ else \
+ cpustate->f &= ~_FLAG_Z; \
+ \
+ if ( cpustate->temp1[0] & 0x0f ) \
+ cpustate->f &= ~_FLAG_ZL; \
+ else \
+ cpustate->f |= _FLAG_ZL; \
+ \
+ if ( cpustate->temp1[0] & 0xf0 ) \
+ cpustate->f &= ~_FLAG_ZH; \
+ else \
+ cpustate->f |= _FLAG_ZH; \
+ }
+
+#define HCD62121_OR \
+ { \
+ int i; \
+ UINT8 is_zero = 1; \
+ \
+ for ( i = 0; i < size; i++ ) \
+ { \
+ cpustate->temp1[i] = cpustate->temp1[i] | cpustate->temp2[i]; \
+ if ( cpustate->temp1[i] ) \
+ is_zero = 0; \
+ } \
+ \
+ if ( is_zero ) \
+ cpustate->f |= _FLAG_Z; \
+ else \
+ cpustate->f &= ~_FLAG_Z; \
+ \
+ if ( cpustate->temp1[0] & 0x0f ) \
+ cpustate->f &= ~_FLAG_ZL; \
+ else \
+ cpustate->f |= _FLAG_ZL; \
+ \
+ if ( cpustate->temp1[0] & 0xf0 ) \
+ cpustate->f &= ~_FLAG_ZH; \
+ else \
+ cpustate->f |= _FLAG_ZH; \
+ }
+
+#define HCD62121_XOR \
+ { \
+ int i; \
+ UINT8 is_zero = 1; \
+ \
+ for ( i = 0; i < size; i++ ) \
+ { \
+ cpustate->temp1[i] = cpustate->temp1[i] ^ cpustate->temp2[i]; \
+ if ( cpustate->temp1[i] ) \
+ is_zero = 0; \
+ } \
+ \
+ if ( is_zero ) \
+ cpustate->f |= _FLAG_Z; \
+ else \
+ cpustate->f &= ~_FLAG_Z; \
+ \
+ if ( cpustate->temp1[0] & 0x0f ) \
+ cpustate->f &= ~_FLAG_ZL; \
+ else \
+ cpustate->f |= _FLAG_ZL; \
+ \
+ if ( cpustate->temp1[0] & 0xf0 ) \
+ cpustate->f &= ~_FLAG_ZH; \
+ else \
+ cpustate->f |= _FLAG_ZH; \
+ }
+
+#define HCD62121_ADD \
+ { \
+ int i; \
+ UINT8 is_zero = 1, carry = 0; \
+ \
+ if ( ( cpustate->temp1[0] & 0x0f ) + ( cpustate->temp2[0] & 0x0f ) > 15 ) \
+ cpustate->f |= _FLAG_CL; \
+ else \
+ cpustate->f &= ~_FLAG_CL; \
+ \
+ for ( i = 0; i < size; i++ ) \
+ { \
+ UINT16 res = cpustate->temp1[i] + cpustate->temp2[i] + carry; \
+ \
+ cpustate->temp1[i] = res & 0xff; \
+ if ( cpustate->temp1[i] ) \
+ is_zero = 0; \
+ \
+ carry = ( res & 0xff00 ) ? 1 : 0; \
+ } \
+ \
+ if ( is_zero ) \
+ cpustate->f |= _FLAG_Z; \
+ else \
+ cpustate->f &= ~_FLAG_Z; \
+ \
+ if ( carry ) \
+ cpustate->f |= _FLAG_C; \
+ else \
+ cpustate->f &= ~_FLAG_C; \
+ \
+ if ( cpustate->temp1[0] & 0x0f ) \
+ cpustate->f &= ~_FLAG_ZL; \
+ else \
+ cpustate->f |= _FLAG_ZL; \
+ \
+ if ( cpustate->temp1[0] & 0xf0 ) \
+ cpustate->f &= ~_FLAG_ZH; \
+ else \
+ cpustate->f |= _FLAG_ZH; \
+ }
+
+/* BCD ADD */
+#define HCD62121_ADDB \
+ { \
+ int i; \
+ UINT8 is_zero = 1, carry = 0; \
+ \
+ if ( ( cpustate->temp1[0] & 0x0f ) + ( cpustate->temp2[0] & 0x0f ) > 9 ) \
+ cpustate->f |= _FLAG_CL; \
+ else \
+ cpustate->f &= ~_FLAG_CL; \
+ \
+ for ( i = 0; i < size; i++ ) \
+ { \
+ UINT16 res = ( cpustate->temp1[i] & 0x0f ) + ( cpustate->temp2[i] & 0x0f ) + carry; \
+ \
+ carry = 0; \
+ if ( res > 9 ) \
+ { \
+ res += 6; \
+ } \
+ res += ( cpustate->temp1[i] & 0xf0 ) + ( cpustate->temp2[i] & 0xf0 ); \
+ if ( res > 0x9f ) \
+ { \
+ res += 0x60; \
+ } \
+ cpustate->temp1[i] = res & 0xff; \
+ if ( cpustate->temp1[i] ) \
+ is_zero = 0; \
+ \
+ carry = ( res & 0xff00 ) ? 1 : 0; \
+ } \
+ \
+ if ( is_zero ) \
+ cpustate->f |= _FLAG_Z; \
+ else \
+ cpustate->f &= ~_FLAG_Z; \
+ \
+ if ( carry ) \
+ cpustate->f |= _FLAG_C; \
+ else \
+ cpustate->f &= ~_FLAG_C; \
+ \
+ if ( cpustate->temp1[0] & 0x0f ) \
+ cpustate->f &= ~_FLAG_ZL; \
+ else \
+ cpustate->f |= _FLAG_ZL; \
+ \
+ if ( cpustate->temp1[0] & 0xf0 ) \
+ cpustate->f &= ~_FLAG_ZH; \
+ else \
+ cpustate->f |= _FLAG_ZH; \
+ }
+
+#define HCD62121_SUB \
+ { \
+ int i; \
+ UINT8 is_zero = 1, carry = 0; \
+ \
+ if ( ( cpustate->temp1[0] & 0x0f ) < ( cpustate->temp2[0] & 0x0f ) ) \
+ cpustate->f |= _FLAG_CL; \
+ else \
+ cpustate->f &= ~_FLAG_CL; \
+ \
+ for ( i = 0; i < size; i++ ) \
+ { \
+ UINT16 res = cpustate->temp1[i] - cpustate->temp2[i] - carry; \
+ \
+ cpustate->temp1[i] = res & 0xff; \
+ if ( cpustate->temp1[i] ) \
+ is_zero = 0; \
+ \
+ carry = ( res & 0xff00 ) ? 1 : 0; \
+ } \
+ \
+ if ( is_zero ) \
+ cpustate->f |= _FLAG_Z; \
+ else \
+ cpustate->f &= ~_FLAG_Z; \
+ \
+ if ( carry ) \
+ cpustate->f |= _FLAG_C; \
+ else \
+ cpustate->f &= ~_FLAG_C; \
+ \
+ if ( cpustate->temp1[0] & 0x0f ) \
+ cpustate->f &= ~_FLAG_ZL; \
+ else \
+ cpustate->f |= _FLAG_ZL; \
+ \
+ if ( cpustate->temp1[0] & 0xf0 ) \
+ cpustate->f &= ~_FLAG_ZH; \
+ else \
+ cpustate->f |= _FLAG_ZH; \
+ }
+
+#define HCD62121_PUSHW(source) \
+ { \
+ UINT16 address = source; \
+ mem_writebyte( cpustate, ( cpustate->sseg << 16 ) | cpustate->sp, ( address ) & 0xff ); \
+ cpustate->sp--; \
+ mem_writebyte( cpustate, ( cpustate->sseg << 16 ) | cpustate->sp, ( address ) >> 8 ); \
+ cpustate->sp--; \
+ }
+
+#define HCD62121_POPW(dest) \
+ { \
+ UINT16 res; \
+ cpustate->sp++; \
+ res = mem_readbyte( cpustate, ( cpustate->sseg << 16 ) | cpustate->sp ) << 8; \
+ cpustate->sp++; \
+ res |= mem_readbyte( cpustate, ( cpustate->sseg << 16 ) | cpustate->sp ); \
+ dest = res; \
+ }
+
+case 0x04: /* mskb r1,r2 */
+case 0x05: /* mskw r1,r2 */
+case 0x06: /* mskq r1,r2 */
+case 0x07: /* mskt r1,r2 */
+ {
+ int size = datasize( cpustate, op );
+ UINT8 reg1 = read_op( cpustate );
+ UINT8 reg2 = read_op( cpustate );
+
+ read_regreg( cpustate, size, reg1, reg2, false );
+
+ HCD62121_MSK;
+ }
+ break;
+
+case 0x08: /* shb r1,4 */
+case 0x09: /* shw r1,4 */
+case 0x0A: /* shq r1,4 */
+case 0x0B: /* sht r1,4 */
+ /* Shift is a nibble shift! */
+ {
+ int i;
+ int size = datasize( cpustate, op );
+ UINT8 reg1 = read_op( cpustate );
+ UINT8 d1 = 0, d2 = 0;
+
+ read_reg( cpustate, size, reg1 );
+
+ for ( i = 0; i < size; i++ )
+ {
+ if ( reg1 & 0x80 )
+ {
+ d1 = ( cpustate->temp1[i] & 0x0f ) << 4;
+ cpustate->temp1[i] = ( cpustate->temp1[i] >> 4 ) | d2;
+ }
+ else
+ {
+ d1 = ( cpustate->temp1[i] & 0xf0 ) >> 4;
+ cpustate->temp1[i] = ( cpustate->temp1[i] << 4 ) | d2;
+ }
+ d2 = d1;
+ }
+
+ write_reg( cpustate, size, reg1 );
+ }
+ break;
+
+case 0x0C: /* testb r1,r2 */
+case 0x0D: /* testw r1,r2 */
+case 0x0E: /* testq r1,r2 */
+case 0x0F: /* testt r1,r2 */
+ {
+ int size = datasize( cpustate, op );
+ UINT8 reg1 = read_op( cpustate );
+ UINT8 reg2 = read_op( cpustate );
+
+ read_regreg( cpustate, size, reg1, reg2, false );
+
+ HCD62121_AND;
+ }
+ break;
+
+case 0x10: /* xorb r1,r2 */
+case 0x11: /* xorw r1,r2 */
+case 0x12: /* xorq r1,r2 */
+case 0x13: /* xort r1,r2 */
+ {
+ int size = datasize( cpustate, op );
+ UINT8 reg1 = read_op( cpustate );
+ UINT8 reg2 = read_op( cpustate );
+
+ read_regreg( cpustate, size, reg1, reg2, false );
+
+ HCD62121_XOR;
+
+ write_regreg( cpustate, size, reg1, reg2 );
+ }
+ break;
+
+case 0x14: /* cmpb r1,r2 */
+case 0x15: /* cmpw r1,r2 */
+case 0x16: /* cmpq r1,r2 */
+case 0x17: /* cmpt r1,r2 */
+ {
+ int size = datasize( cpustate, op );
+ UINT8 reg1 = read_op( cpustate );
+ UINT8 reg2 = read_op( cpustate );
+
+ read_regreg( cpustate, size, reg1, reg2, false );
+
+ HCD62121_SUB;
+ }
+ break;
+
+case 0x18: /* movb r1,r2 */
+case 0x19: /* movw r1,r2 */
+case 0x1A: /* movq r1,r2 */
+case 0x1B: /* movt r1,r2 */
+ {
+ int i;
+ int size = datasize( cpustate, op );
+ UINT8 reg1 = read_op( cpustate );
+ UINT8 reg2 = read_op( cpustate );
+
+ read_regreg( cpustate, size, reg1, reg2, false );
+
+ for ( i = 0; i < size; i++ )
+ cpustate->temp1[i] = cpustate->temp2[i];
+
+ write_regreg( cpustate, size, reg1, reg2 );
+ }
+ break;
+
+case 0x1C: /* imskb r1,r2 */
+case 0x1D: /* imskw r1,r2 */
+case 0x1E: /* imskq r1,r2 */
+case 0x1F: /* imskt r1,r2 */
+ {
+ int size = datasize( cpustate, op );
+ UINT8 reg1 = read_op( cpustate );
+ UINT8 reg2 = read_op( cpustate );
+
+ read_regreg( cpustate, size, reg1, reg2, false );
+
+ HCD62121_IMSK;
+ }
+ break;
+
+case 0x20: /* shrb r1 */
+case 0x21: /* shrw r1 */
+case 0x22: /* shrq r1 */
+case 0x23: /* shrt r1 */
+ /* Shift is a single shift! */
+ {
+ int i;
+ int size = datasize( cpustate, op );
+ UINT8 reg1 = read_op( cpustate );
+ UINT8 d1 = 0, d2 = 0;
+
+ read_reg( cpustate, size, reg1 );
+
+ for ( i = 0; i < size; i++ )
+ {
+ d1 = ( cpustate->temp1[i] & 0x01 ) << 7;
+ cpustate->temp1[i] = ( cpustate->temp1[i] >> 1 ) | d2;
+ d2 = d1;
+ }
+
+ write_reg( cpustate, size, reg1 );
+ }
+ break;
+
+case 0x24: /* orb r1,r2 */
+case 0x25: /* orw r1,r2 */
+case 0x26: /* orq r1,r2 */
+case 0x27: /* ort r1,r2 */
+ {
+ int size = datasize( cpustate, op );
+ UINT8 reg1 = read_op( cpustate );
+ UINT8 reg2 = read_op( cpustate );
+
+ read_regreg( cpustate, size, reg1, reg2, false );
+
+ HCD62121_OR;
+
+ write_regreg( cpustate, size, reg1, reg2 );
+ }
+ break;
+
+case 0x28: /* shlb r1 */
+case 0x29: /* shlw r1 */
+case 0x2A: /* shlq r1 */
+case 0x2B: /* shlt r1 */
+ /* Shift is a single shift! */
+ {
+ int i;
+ int size = datasize( cpustate, op );
+ UINT8 reg1 = read_op( cpustate );
+ UINT8 d1 = 0, d2 = 0;
+
+ read_reg( cpustate, size, reg1 );
+
+ for ( i = 0; i < size; i++ )
+ {
+ d1 = ( cpustate->temp1[i] & 0x80 ) >> 7;
+ cpustate->temp1[i] = ( cpustate->temp1[i] << 1 ) | d2;
+ d2 = d1;
+ }
+
+ write_reg( cpustate, size, reg1 );
+ }
+ break;
+
+case 0x2C: /* andb r1,r2 */
+case 0x2D: /* andw r1,r2 */
+case 0x2E: /* andq r1,r2 */
+case 0x2F: /* andt r1,r2 */
+ {
+ int size = datasize( cpustate, op );
+ UINT8 reg1 = read_op( cpustate );
+ UINT8 reg2 = read_op( cpustate );
+
+ read_regreg( cpustate, size, reg1, reg2, true );
+
+ HCD62121_AND;
+
+ write_regreg( cpustate, size, reg1, reg2 );
+ }
+ break;
+
+case 0x34: /* subb r1,r2 */
+case 0x35: /* subw r1,r2 */
+case 0x36: /* subq r1,r2 */
+case 0x37: /* subt r1,r2 */
+ {
+ int size = datasize( cpustate, op );
+ UINT8 reg1 = read_op( cpustate );
+ UINT8 reg2 = read_op( cpustate );
+
+ read_regreg( cpustate, size, reg1, reg2, false );
+
+ HCD62121_SUB;
+
+ write_regreg( cpustate, size, reg1, reg2 );
+ }
+ break;
+
+case 0x38: /* adbb r1,r2 */
+case 0x39: /* adbw r1,r2 */
+case 0x3A: /* adbq r1,r2 */
+case 0x3B: /* adbt r1,r2 */
+ {
+ int size = datasize( cpustate, op );
+ UINT8 reg1 = read_op( cpustate );
+ UINT8 reg2 = read_op( cpustate );
+
+ read_regreg( cpustate, size, reg1, reg2, false );
+
+ HCD62121_ADDB;
+
+ write_regreg( cpustate, size, reg1, reg2 );
+ }
+ break;
+
+case 0x3C: /* addb r1,r2 */
+case 0x3D: /* addw r1,r2 */
+case 0x3E: /* addq r1,r2 */
+case 0x3F: /* addt r1,r2 */
+ {
+ int size = datasize( cpustate, op );
+ UINT8 reg1 = read_op( cpustate );
+ UINT8 reg2 = read_op( cpustate );
+
+ read_regreg( cpustate, size, reg1, reg2, false );
+
+ HCD62121_ADD;
+
+ write_regreg( cpustate, size, reg1, reg2 );
+ }
+ break;
+
+case 0x4C: /* testb ir1,r2 */
+case 0x4D: /* testw ir1,r2 */
+case 0x4E: /* testq ir1,r2 */
+case 0x4F: /* testt ir1,r2 */
+ {
+ int size = datasize( cpustate, op );
+ UINT8 reg1 = read_op( cpustate );
+ UINT8 reg2 = read_op( cpustate );
+
+ read_iregreg( cpustate, size, reg1, reg2 );
+
+ HCD62121_AND;
+ }
+ break;
+
+case 0x54: /* cmpb ir1,r2 */
+case 0x55: /* cmpw ir1,r2 */
+case 0x56: /* cmpq ir1,r2 */
+case 0x57: /* cmpt ir1,r2 */
+ {
+ int size = datasize( cpustate, op );
+ UINT8 reg1 = read_op( cpustate );
+ UINT8 reg2 = read_op( cpustate );
+
+ read_iregreg( cpustate, size, reg1, reg2 );
+
+ HCD62121_SUB;
+ }
+ break;
+
+case 0x58: /* movb ir1,r2 */
+case 0x59: /* movw ir1,r2 */
+case 0x5A: /* movq ir1,r2 */
+case 0x5B: /* movt ir1,r2 */
+ {
+ int i;
+ int size = datasize( cpustate, op );
+ UINT8 reg1 = read_op( cpustate );
+ UINT8 reg2 = read_op( cpustate );
+
+ read_iregreg( cpustate, size, reg1, reg2 );
+
+ for ( i = 0; i < size; i++ )
+ cpustate->temp1[i] = cpustate->temp2[i];
+
+ write_iregreg( cpustate, size, reg1, reg2 );
+ }
+ break;
+
+case 0x64: /* orb ir1,r2 */
+case 0x65: /* orb ir1,r2 */
+case 0x66: /* orb ir1,r2 */
+case 0x67: /* orb ir1,r2 */
+ {
+ int size = datasize( cpustate, op );
+ UINT8 reg1 = read_op( cpustate );
+ UINT8 reg2 = read_op( cpustate );
+
+ read_iregreg( cpustate, size, reg1, reg2 );
+
+ HCD62121_OR;
+
+ write_iregreg( cpustate, size, reg1, reg2 );
+ }
+ break;
+
+case 0x6C: /* andb ir1,r2 */
+case 0x6D: /* andw ir1,r2 */
+case 0x6E: /* andq ir1,r2 */
+case 0x6F: /* andt ir1,r2 */
+ {
+ int size = datasize( cpustate, op );
+ UINT8 reg1 = read_op( cpustate );
+ UINT8 reg2 = read_op( cpustate );
+
+ read_iregreg( cpustate, size, reg1, reg2 );
+
+ HCD62121_AND;
+
+ write_iregreg( cpustate, size, reg1, reg2 );
+ }
+ break;
+
+case 0x7C: /* addb ir1,r2 */
+case 0x7D: /* addw ir1,r2 */
+case 0x7E: /* addq ir1,r2 */
+case 0x7F: /* addt ir1,r2 */
+ {
+ int size = datasize( cpustate, op );
+ UINT8 reg1 = read_op( cpustate );
+ UINT8 reg2 = read_op( cpustate );
+
+ read_iregreg( cpustate, size, reg1, reg2 );
+
+ HCD62121_ADD;
+
+ write_iregreg( cpustate, size, reg1, reg2 );
+ }
+ break;
+
+case 0x88: /* jump _a16 */
+ cpustate->ip = ( read_op( cpustate ) << 8 ) | read_op( cpustate );
+ break;
+
+case 0x89: /* jumpf cs:a16 */
+ {
+ UINT8 cs = read_op( cpustate );
+ UINT8 a1 = read_op( cpustate );
+ UINT8 a2 = read_op( cpustate );
+
+ cpustate->cseg = cs;
+ cpustate->ip = ( a1 << 8 ) | a2;
+ }
+ break;
+
+case 0x8A: /* call a16 */
+ {
+ UINT8 a1 = read_op( cpustate );
+ UINT8 a2 = read_op( cpustate );
+
+ HCD62121_PUSHW( cpustate->ip );
+
+ cpustate->ip = ( a1 << 8 ) | a2;
+ }
+ break;
+
+case 0x8C: /* unk_8C */
+case 0x8D: /* unk_8D */
+case 0x8E: /* unk_8E */
+ logerror( "%02x:%04x: unimplemented instruction %02x encountered\n", cpustate->cseg, cpustate->ip-1, op );
+ break;
+
+case 0x90: /* retzh */
+case 0x91: /* retzl */
+case 0x92: /* retc */
+case 0x93: /* retz */
+case 0x94: /* retzc */
+case 0x95: /* retcl */
+case 0x96: /* retnc */
+case 0x97: /* retnz */
+ if ( check_cond( cpustate, op ) )
+ HCD62121_POPW( cpustate->ip );
+ break;
+
+case 0x98: /* jump (r1) */
+ {
+ UINT8 reg1 = read_op( cpustate );
+ UINT16 ad = cpustate->reg[ ( reg1 | 0x40 ) & 0x7f ] << 8;
+
+ if ( reg1 & 0x40 )
+ ad |= cpustate->reg[ ( ( reg1 - 1 ) | 0x40 ) & 0x7f ];
+ else
+ ad |= cpustate->reg[ ( ( reg1 + 1 ) | 0x40 ) & 0x7f ];
+
+ cpustate->ip = ad;
+ }
+ break;
+
+case 0x9F: /* ret */
+ HCD62121_POPW( cpustate->ip );
+ break;
+
+case 0xA0: /* jmpzh a16 */
+case 0xA1: /* jmpzl a16 */
+case 0xA2: /* jmpc a16 */
+case 0xA3: /* jmpz a16 */
+case 0xA4: /* jmpzc a16 */
+case 0xA5: /* jmpcl a16 */
+case 0xA6: /* jmpnc a16 */
+case 0xA7: /* jmpnz a16 */
+ {
+ UINT8 a1 = read_op( cpustate );
+ UINT8 a2 = read_op( cpustate );
+
+ if ( check_cond( cpustate, op ) )
+ cpustate->ip = ( a1 << 8 ) | a2;
+ }
+ break;
+
+case 0xA8: /* callzh a16 */
+case 0xA9: /* callzl a16 */
+case 0xAA: /* callc a16 */
+case 0xAB: /* callz a16 */
+case 0xAC: /* callzc a16 */
+case 0xAD: /* callcl a16 */
+case 0xAE: /* callnc a16 */
+case 0xAF: /* callnz a16 */
+ {
+ UINT8 a1 = read_op( cpustate );
+ UINT8 a2 = read_op( cpustate );
+
+ if ( check_cond( cpustate, op ) )
+ {
+ HCD62121_PUSHW( cpustate->ip );
+
+ cpustate->ip = ( a1 << 8 ) | a2;
+ }
+ }
+ break;
+
+case 0xB1: /* unk_B1 reg/i8 */
+case 0xB3: /* unk_B3 reg/i8 */
+ logerror( "%02x:%04x: unimplemented instruction %02x encountered\n", cpustate->cseg, cpustate->ip-1, op );
+ read_op( cpustate );
+ break;
+
+case 0xB4: /* out koh,reg */
+ io_writebyte( cpustate, HCD62121_KOH, cpustate->reg[ read_op( cpustate ) & 0x7f ] );
+ break;
+
+case 0xB5: /* out koh,i8 */
+ io_writebyte( cpustate, HCD62121_KOH, read_op( cpustate ) );
+ break;
+
+case 0xB6: /* out kol,reg */
+ io_writebyte( cpustate, HCD62121_KOL, cpustate->reg[ read_op( cpustate ) & 0x7f ] );
+ break;
+
+case 0xB7: /* out kol,i8 */
+ io_writebyte( cpustate, HCD62121_KOL, read_op( cpustate ) );
+ break;
+
+case 0xB9: /* unk_B9 reg/i8 */
+ logerror( "%02x:%04x: unimplemented instruction %02x encountered\n", cpustate->cseg, cpustate->ip-1, op );
+ read_op( cpustate );
+ break;
+
+case 0xBB: /* jmpcl? a16 */
+ logerror( "%02x:%04x: unimplemented instruction %02x encountered\n", cpustate->cseg, cpustate->ip-1, op );
+ {
+ UINT8 a1 = read_op( cpustate );
+ UINT8 a2 = read_op( cpustate );
+
+ if ( cpustate->f & _FLAG_CL )
+ cpustate->ip = ( a1 << 8 ) | a2;
+ }
+ break;
+
+case 0xBF: /* jmpncl? a16 */
+ logerror( "%02x:%04x: unimplemented instruction %02x encountered\n", cpustate->cseg, cpustate->ip-1, op );
+ {
+ UINT8 a1 = read_op( cpustate );
+ UINT8 a2 = read_op( cpustate );
+
+ if ( ! ( cpustate->f & _FLAG_CL ) )
+ cpustate->ip = ( a1 << 8 ) | a2;
+ }
+ break;
+
+case 0xC0: /* movb reg,i8 */
+case 0xC1: /* movw reg,i16 */
+case 0xC2: /* movw reg,i64 */
+case 0xC3: /* movw reg,i80 */
+ {
+ int i;
+ int size = datasize( cpustate, op );
+ UINT8 reg = read_op( cpustate );
+
+ for( i = 0; i < size; i++ )
+ {
+ cpustate->reg[(reg + i) & 0x7f] = read_op( cpustate );
+ }
+ }
+ break;
+
+case 0xC4: /* movb (lar),r1 / r1,(lar) */
+case 0xC5: /* movw (lar),r1 / r1,(lar) */
+case 0xC6: /* movq (lar),r1 / r1,(lar) */
+case 0xC7: /* movt (lar),r1 / r1,(lar) */
+ {
+ int i;
+ int size = datasize( cpustate, op );
+ UINT8 reg1 = read_op( cpustate );
+ UINT8 reg2 = read_op( cpustate );
+ int pre_inc = 0;
+ int post_inc = 1;
+
+ switch( reg1 & 0x60 )
+ {
+ case 0x00:
+ pre_inc = 0;
+ post_inc = 1;
+ break;
+ case 0x20:
+ pre_inc = 1;
+ post_inc = 0;
+ break;
+ case 0x40:
+ pre_inc = 0;
+ post_inc = -1;
+ break;
+ case 0x60:
+ pre_inc = -1;
+ post_inc = 0;
+ break;
+ }
+
+ if ( ( reg1 & 0x80 ) || ( reg2 & 0x80 ) )
+ {
+ /* (lar) <- r1 */
+ for ( i = 0; i < size; i++ )
+ {
+ cpustate->lar += pre_inc;
+ mem_writebyte( cpustate, ( cpustate->dseg << 16 ) | cpustate->lar, cpustate->reg[ ( reg2 + i ) & 0x7f ] );
+ cpustate->lar += post_inc;
+ }
+ }
+ else
+ {
+ /* r1 <- (lar) */
+ for ( i = 0; i < size; i++ )
+ {
+ cpustate->lar += pre_inc;
+ cpustate->reg[ ( reg2 + i ) & 0x7f ] = mem_readbyte( cpustate, ( cpustate->dseg << 16 ) | cpustate->lar );
+ cpustate->lar += post_inc;
+ }
+ }
+ }
+ break;
+
+case 0xCC: /* swapb ir1,r2 */
+case 0xCD: /* swapw ir1,r2 */
+case 0xCE: /* swapq ir1,r2 */
+case 0xCF: /* swapt ir1,r2? */
+ {
+ int i;
+ int size = datasize( cpustate, op );
+ UINT8 reg1 = read_op( cpustate );
+ UINT8 reg2 = read_op( cpustate );
+
+ read_iregreg( cpustate, size, reg1, reg2 );
+
+ for ( i = 0; i < size; i++ )
+ {
+ UINT8 d = cpustate->temp1[i];
+ cpustate->temp1[i] = cpustate->temp2[i];
+ cpustate->temp2[i] = d;
+ }
+
+ write_iregreg( cpustate, size, reg1, reg2 );
+ write_iregreg2( cpustate, size, reg1, reg2 );
+ }
+ break;
+
+case 0xD0: /* movb cs,reg */
+ cpustate->cseg = cpustate->reg[ read_op( cpustate ) & 0x7f ];
+ break;
+
+case 0xD1: /* movb cs,i8 */
+ cpustate->cseg = read_op( cpustate );
+ break;
+
+case 0xD2: /* movb dsize,reg */
+ cpustate->dsize = cpustate->reg[ read_op( cpustate ) & 0x7f ];
+ break;
+
+case 0xD3: /* movb dsize,i8 */
+ cpustate->dsize = read_op( cpustate );
+ break;
+
+case 0xD4: /* movb ss,reg */
+ cpustate->sseg = cpustate->reg[ read_op( cpustate ) & 0x7f ];
+ break;
+
+case 0xD5: /* movb ss,i8 */
+ cpustate->sseg = read_op( cpustate );
+ break;
+
+case 0xD6: /* movw sp,reg */
+ {
+ UINT8 reg1 = read_op( cpustate );
+
+ cpustate->sp = cpustate->reg[ reg1 & 0x7f ] | ( cpustate->reg[ ( reg1 + 1 ) & 0x7f ] << 8 );
+ }
+ break;
+
+case 0xD7: /* movw sp,i16 */
+ cpustate->sp = read_op( cpustate) << 8;
+ cpustate->sp |= read_op( cpustate );
+ break;
+
+case 0xD8: /* movb f,reg */
+ cpustate->f = cpustate->reg[ read_op( cpustate ) & 0x7f ];
+ break;
+
+case 0xD9: /* movb f,i8 */
+ cpustate->f = read_op( cpustate );
+ break;
+
+case 0xDC: /* movb ds,reg */
+ cpustate->dseg = cpustate->reg[ read_op( cpustate ) & 0x7f ];
+ break;
+
+case 0xDD: /* movb ds,i8 */
+ cpustate->dseg = read_op( cpustate );
+ break;
+
+case 0xDE: /* movw lar,reg */
+ {
+ UINT8 reg1 = read_op( cpustate );
+
+ cpustate->lar = cpustate->reg[ reg1 & 0x7f ] | ( cpustate->reg[ ( reg1 + 1 ) & 0x7f ] << 8 );
+ }
+ break;
+
+case 0xE0: /* in0 reg */
+ {
+ UINT8 reg1 = read_op( cpustate );
+
+ cpustate->reg[ reg1 & 0x7f ] = io_readbyte( cpustate, HCD62121_IN0 );
+ }
+ break;
+
+case 0xE1: /* unk_E1 reg/i8 (in?) */
+ logerror( "%02x:%04x: unimplemented instruction %02x encountered\n", cpustate->cseg, cpustate->ip-1, op );
+ read_op( cpustate );
+ break;
+
+case 0xE2: /* in kb, reg */
+ cpustate->reg[ read_op( cpustate ) & 0x7f ] = io_readbyte( cpustate, HCD62121_KI );
+ break;
+
+case 0xE3: /* unk_e3 reg/i8 (in?) */
+case 0xE4: /* unk_e4 reg/i8 (in?) */
+case 0xE5: /* unk_e5 reg/i8 (in?) */
+case 0xE6: /* unk_e6 reg/i8 (in?) */
+case 0xE7: /* unk_e7 reg/i8 (in?) */
+ logerror( "%02x:%04x: unimplemented instruction %02x encountered\n", cpustate->cseg, cpustate->ip-1, op );
+ read_op( cpustate );
+ break;
+
+case 0xE8: /* movw r1,lar */
+ {
+ UINT8 reg1 = read_op( cpustate );
+
+ cpustate->reg[ reg1 & 0x7f ] = cpustate->lar & 0xff;
+ cpustate->reg[ ( reg1 + 1 ) & 0x7f ] = cpustate->lar >> 8;
+ }
+ break;
+
+case 0xEB: /* movw reg,ss */
+ {
+ UINT8 reg1 = read_op( cpustate );
+
+ cpustate->reg[ reg1 & 0x7f ] = cpustate->sp & 0xff;
+ cpustate->reg[ ( reg1 + 1 ) & 0x7f ] = cpustate->sp >> 8;
+ }
+ break;
+
+case 0xEF: /* movb reg,ss */
+ cpustate->reg[ read_op( cpustate ) & 0x7f ] = cpustate->sseg;
+ break;
+
+case 0xF0: /* unk_F0 reg/i8 (out?) */
+case 0xF1: /* unk_F1 reg/i8 (out?) */
+case 0xF2: /* unk_F2 reg/i8 (out?) */
+case 0xF3: /* unk_F3 reg/i8 (out?) */
+case 0xF4: /* unk_F4 reg/i8 (out?) */
+case 0xF5: /* unk_F5 reg/i8 (out?) */
+case 0xF6: /* unk_F6 reg/i8 (out?) */
+case 0xF7: /* unk_F7 reg/i8 (out?) */
+ logerror( "%02x:%04x: unimplemented instruction %02x encountered\n", cpustate->cseg, cpustate->ip-1, op );
+ read_op( cpustate );
+ break;
+
+case 0xFC: /* unk_FC */
+case 0xFD: /* unk_FD */
+case 0xFE: /* unk_FE */
+ logerror( "%02x:%04x: unimplemented instruction %02x encountered\n", cpustate->cseg, cpustate->ip-1, op );
+ break;
+
+case 0xFF: /* nop */
+ break;
+
+default:
+ /*logerror*/fatalerror( "%02x:%04x: unimplemented instruction %02x encountered\n", cpustate->cseg, cpustate->ip-1, op );
+ break;
+
diff --git a/trunk/src/emu/cpu/hcd62121/hcd62121d.c b/trunk/src/emu/cpu/hcd62121/hcd62121d.c
new file mode 100644
index 00000000000..6a4c3a6ce55
--- /dev/null
+++ b/trunk/src/emu/cpu/hcd62121/hcd62121d.c
@@ -0,0 +1,352 @@
+
+#include "emu.h"
+#include "debugger.h"
+#include "hcd62121.h"
+
+
+enum
+{
+ _REG=1, /* register */
+ _REGREG, /* register1, register2, or register2, register1 or register1, imm byte */
+ _IRG, /* register indirect */
+ _IRGREG, /* 2 register indirect */
+ _A16, /* 16bit address */
+ _A24, /* seg:address */
+ _F, /* flag register */
+ _CS, /* cs register */
+ _DS, /* ds register */
+ _SS, /* ss register */
+ _PC, /* program counter */
+ _SP, /* stack pointer */
+ _I8, /* immediate 8 bit value */
+ _I16, /* immediate 16 bit value */
+ _I64, /* immediate 64 bit value */
+ _I80, /* immediate 80 bit value */
+ _ILR, /* indirect last address register access */
+ _LAR, /* last address register */
+ _DSZ, /* dsize register? */
+ _TIM, /* timing related register? */
+ _KLO, /* KO1 - KO8 output lines */
+ _KHI, /* KO9 - KO14(?) output lines */
+ _KI, /* K input lines */
+ _4, /* for nibble shifts */
+};
+
+typedef struct
+{
+ const char *str;
+ UINT8 arg1;
+ UINT8 arg2;
+} hcd62121_dasm;
+
+
+static const hcd62121_dasm hcd62121_ops[256] =
+{
+ /* 0x00 */
+ { "un00?", 0, 0 }, { "un01?", 0, 0 }, { "un02?", 0, 0 }, { "un03?", 0, 0 },
+ { "mskb", _REGREG, 0 }, { "mskw", _REGREG, 0 }, { "mskq", _REGREG, 0 }, { "mskt", _REGREG, 0 },
+ { "sh?b", _REG, _4 }, { "sh?w", _REG, _4 }, { "sh?q", _REG, _4 }, { "sh?t", _REG, _4 },
+ { "tstb", _REGREG, 0 }, { "tstw", _REGREG, 0 }, { "tstq", _REGREG, 0 }, { "tstt", _REGREG, 0 },
+ { "xorb", _REGREG, 0 }, { "xorw", _REGREG, 0 }, { "xorq", _REGREG, 0 }, { "xort", _REGREG, 0 },
+ { "cmpb", _REGREG, 0 }, { "cmpw", _REGREG, 0 }, { "cmpq", _REGREG, 0 }, { "cmpt", _REGREG, 0 },
+ { "movb", _REGREG, 0 }, { "movw", _REGREG, 0 }, { "movq", _REGREG, 0 }, { "movt", _REGREG, 0 },
+ { "imskb", _REGREG, 0 }, { "imskw", _REGREG, 0 }, { "imskq", _REGREG, 0 }, { "imskt", _REGREG, 0 },
+
+ /* 0x20 */
+ { "shrb", _REG, 0 }, { "shrw", _REG, 0 }, { "shrq", _REG, 0 }, { "shrt", _REG, 0 },
+ { "orb", _REGREG, 0 }, { "orw", _REGREG, 0 }, { "orq", _REGREG, 0 }, { "ort", _REGREG, 0 },
+ { "shlb", _REG, 0 }, { "shlw", _REG, 0 }, { "shlq", _REG, 0 }, { "shlt", _REG, 0 },
+ { "andb", _REGREG, 0 }, { "andw", _REGREG, 0 }, { "andq", _REGREG, 0 }, { "andt", _REGREG, 0 },
+ { "sbbb", _REGREG, 0 }, { "sbbw", _REGREG, 0 }, { "sbbq", _REGREG, 0 }, { "sbbt", _REGREG, 0 }, /* BCD SUB */
+ { "subb", _REGREG, 0 }, { "subw", _REGREG, 0 }, { "subq", _REGREG, 0 }, { "subt", _REGREG, 0 },
+ { "adbb", _REGREG, 0 }, { "adbw", _REGREG, 0 }, { "adbq", _REGREG, 0 }, { "adbt", _REGREG, 0 }, /* BCD ADD */
+ { "addb", _REGREG, 0 }, { "addw", _REGREG, 0 }, { "addq", _REGREG, 0 }, { "addt", _REGREG, 0 },
+
+ /* 0x40 */
+ { "shrb?", _IRG, 0 }, { "shrw?", _IRG, 0 }, { "shrq?", _IRG, 0 }, { "shrt?", _IRG, 0 },
+ { "mskb", _IRGREG, 0 }, { "mskw", _IRGREG, 0 }, { "mskq", _IRGREG, 0 }, { "mskt", _IRGREG, 0 },
+ { "shrb", _IRG, 0 }, { "shrw", _IRG, 0 }, { "shrq", _IRG, 0 }, { "shrt", _IRG, 0 },
+ { "tstb", _IRGREG, 0 }, { "tstw", _IRGREG, 0 }, { "tstq", _IRGREG, 0 }, { "tstt", _IRGREG, 0 },
+ { "xorb", _IRGREG, 0 }, { "xorw", _IRGREG, 0 }, { "xorq", _IRGREG, 0 }, { "xort", _IRGREG, 0 },
+ { "cmpb", _IRGREG, 0 }, { "cmpw", _IRGREG, 0 }, { "cmpq", _IRGREG, 0 }, { "cmpt", _IRGREG, 0 },
+ { "movb", _IRGREG, 0 }, { "movw", _IRGREG, 0 }, { "movq", _IRGREG, 0 }, { "movt", _IRGREG, 0 },
+ { "imskb", _IRGREG, 0 }, { "imskw", _IRGREG, 0 }, { "imskq", _IRGREG, 0 }, { "imskt", _IRGREG, 0 },
+
+ /* 0x60 */
+ { "shrb", _IRG, 0 }, { "shrw", _IRG, 0 }, { "shrq", _IRG, 0 }, { "shrt", _IRG, 0 },
+ { "orb", _IRGREG, 0 }, { "orw", _IRGREG, 0 }, { "orq", _IRGREG, 0 }, { "ort", _IRGREG, 0 },
+ { "shlb", _IRG, 0 }, { "shlw", _IRG, 0 }, { "shlq", _IRG, 0 }, { "shlt", _IRG, 0 },
+ { "andb", _IRGREG, 0 }, { "andw", _IRGREG, 0 }, { "andq", _IRGREG, 0 }, { "andt", _IRGREG, 0 },
+ { "sbbb", _IRGREG, 0 }, { "sbbw", _IRGREG, 0 }, { "sbbq", _IRGREG, 0 }, { "sbbt", _IRGREG, 0 }, /* BCD SUB */
+ { "subb", _IRGREG, 0 }, { "subw", _IRGREG, 0 }, { "subq", _IRGREG, 0 }, { "subt", _IRGREG, 0 },
+ { "adbb", _IRGREG, 0 }, { "adbw", _IRGREG, 0 }, { "adbq", _IRGREG, 0 }, { "adbt", _IRGREG, 0 }, /* BCD ADD */
+ { "addb", _IRGREG, 0 }, { "addw", _IRGREG, 0 }, { "addq", _IRGREG, 0 }, { "addt", _IRGREG, 0 },
+
+ /* 0x80 */
+ { "un80?", 0, 0 }, { "un81?", 0, 0 }, { "un82?", 0, 0 }, { "un83?", 0, 0 },
+ { "un84?", 0, 0 }, { "un85?", 0, 0 }, { "un86?", 0, 0 }, { "un87?", 0, 0 },
+ { "jump", _A16, 0 }, { "jump", _A24, 0 }, { "call", _A16, 0 }, { "un8b?", 0, 0 },
+ { "un8C?", 0, 0 }, { "un8D?", 0, 0 }, { "un8E?", 0, 0 }, { "un8F?", 0, 0 },
+ { "retzh", 0, 0 }, { "retzl", 0, 0 }, { "retc", 0, 0 }, { "retz", 0, 0 },
+ { "retzc", 0, 0 }, { "retcl", 0, 0 }, { "retnc", 0, 0 }, { "retnz", 0, 0 },
+ { "jump", _IRG, 0 }, { "un99?", 0, 0 }, { "un9A?", 0, 0 }, { "un9b?", 0, 0 },
+ { "un9C?", 0, 0 }, { "un9D?", 0, 0 }, { "reti", 0, 0 }, { "ret", 0, 0 },
+
+ /* 0xa0 */
+ { "jmpzh", _A16, 0 }, { "jmpzl", _A16, 0 }, { "jmpc", _A16, 0 }, { "jmpz", _A16, 0 },
+ { "jmpzc", _A16, 0 }, { "jmpcl", _A16, 0 }, { "jmpnc", _A16, 0 }, { "jmpnz", _A16, 0 },
+ { "callzh", _A16, 0 }, { "callzl", _A16, 0 }, { "callc", _A16, 0 }, { "callz", _A16, 0 },
+ { "callzc", _A16, 0 }, { "callcl", _A16, 0 }, { "callnc", _A16, 0 }, { "callnz", _A16, 0 },
+ { "unB0?", 0, 0 }, { "unB1?", _I8, 0 }, { "unB2?", 0, 0 }, { "unB3?", _I8, 0 },
+ { "out", _KHI, _REG }, { "out", _KHI, _I8 }, { "out", _KLO, _REG }, { "out", _KLO, _I8 },
+ { "unB8?", 0, 0 }, { "unB9?", _I8, 0 }, { "unBA?", 0, 0 }, { "jmpcl?", _A16, 0 },
+ { "unBC?", 0, 0 }, { "unBD?", 0, 0 }, { "unBE?", 0, 0 }, { "jmpncl?", _A16, 0 },
+
+ /* 0xc0 */
+ { "movb", _REG, _I8 }, { "movw", _REG, _I16 }, { "movq", _REG, _I64 }, { "movt", _REG, _I80 },
+ { "movb", _ILR, _ILR }, { "movw", _ILR, _ILR }, { "movq", _ILR, _ILR }, { "movt", _ILR, _ILR },
+ { "unC8?", 0, 0 }, { "unC9?", 0, 0 }, { "unCA?", 0, 0 }, { "unCb?", 0, 0 },
+ { "swapb", _IRGREG, 0 }, { "swapw", _IRGREG, 0 }, { "swapq", _IRGREG, 0 }, { "swapt", _IRGREG, 0 },
+ { "movb", _CS, _REG }, { "movb", _CS, _I8 }, { "movb", _DSZ, _REG }, { "movb", _DSZ, _I8 },
+ { "movb", _SS, _REG }, { "movb", _SS, _I8 }, { "movw", _SP, _REG }, { "movw", _SP, _I16 },
+ { "movb", _F, _REG }, { "movb", _F, _I8 }, { "unDA?", 0, 0 }, { "unDb?", 0, 0 },
+ { "movb", _DS, _REG }, { "movb", _DS, _I8 }, { "movw", _LAR, _REG }, { "movw?", _LAR, _I16 },
+
+ /* 0xe0 */
+ { "in0", _REG, 0 }, { "unE1?", _I8, 0 }, { "in", _REG, _KI }, { "movb", _REG, _DSZ },
+ { "movb", _REG, _F }, { "movb", _REG, _TIM }, { "unE6?", _I8, 0 }, { "unE7?", _I8, 0 },
+ { "movw", _REG, _LAR }, { "movw?", _REG, _LAR }, { "movw", _REG, _PC }, { "movw", _REG, _SP },
+ { "unEC?", 0, 0 }, { "movb", _REG, _DS }, { "movb", _REG, _CS }, { "movb", _REG, _SS },
+ { "unF0?", _I8, 0 }, { "unF1?", _I8, 0 }, { "unF2?", _I8, 0 }, { "unF3?", _I8, 0 },
+ { "unF4?", _I8, 0 }, { "unF5?", _I8, 0 }, { "unF6?", _I8, 0 }, { "unF7?", _I8, 0 },
+ { "unF8?", 0, 0 }, { "unF9?", 0, 0 }, { "unFA?", 0, 0 }, { "unFb?", 0, 0 },
+ { "unFC?", 0, 0 }, { "unFD?", 0, 0 }, { "unFE?", 0, 0 }, { "nop", 0, 0 }
+};
+
+
+CPU_DISASSEMBLE( hcd62121 )
+{
+ UINT8 op, op1=0, op2=0;
+ int pos = 0;
+ const hcd62121_dasm *inst;
+
+ op = oprom[pos++];
+
+ inst = &hcd62121_ops[op];
+
+ /* Special case for nibble shift instruction */
+ if ( inst->arg2 == _4 )
+ buffer += sprintf(buffer,"sh%c%c ", ( oprom[pos] & 0x80 ) ? 'l' : 'r', inst->str[3]);
+ else
+ buffer += sprintf(buffer,"%-8s", inst->str);
+
+ switch( inst->arg1 )
+ {
+ case _REGREG:
+ op1 = oprom[pos++];
+ op2 = oprom[pos++];
+ if ( op1 & 0x80 )
+ {
+ buffer += sprintf( buffer, "r%02x,0x%02x", op1 & 0x7f, op2 );
+ }
+ else
+ {
+ if ( op2 & 0x80 )
+ buffer += sprintf( buffer, "r%02x,r%02x", op1 & 0x7f, op2 & 0x7f );
+ else
+ buffer += sprintf( buffer, "r%02x,r%02x", op2 & 0x7f, op1 & 0x7f );
+ }
+ break;
+ case _REG:
+ buffer += sprintf( buffer, "r%02x", oprom[pos++] & 0x7f );
+ break;
+ case _IRGREG:
+ /* bit 6 = direction. 0 - regular, 1 - reverse */
+ op1 = oprom[pos++];
+ op2 = oprom[pos++];
+ if ( op1 & 0x80 )
+ {
+ buffer += sprintf( buffer, "(r%02x),0x%02x", 0x40 | ( op1 & 0x3f ), op2 );
+ }
+ else
+ {
+ if ( op2 & 0x80 )
+ buffer += sprintf( buffer, "(r%02x%s),r%02x", 0x40 | ( op1 & 0x3f ), (op1 & 0x40) ? ".r" : "", op2 & 0x7f );
+ else
+ buffer += sprintf( buffer, "r%02x,(r%02x%s)", op2 & 0x7f, 0x40 | ( op1 & 0x3f ), (op1 & 0x40) ? ".r" : "" );
+ }
+ break;
+ case _IRG:
+ /* bit 6 = direction. 0 - regular, 1 - reverse */
+ op1 = oprom[pos++];
+ buffer += sprintf( buffer, "(r%02x%s)", 0x40 | ( op1 & 0x3f ), (op1 & 0x40) ? ".r" : "" );
+ break;
+ case _F:
+ buffer += sprintf( buffer, "F" );
+ break;
+ case _CS:
+ buffer += sprintf( buffer, "CS" );
+ break;
+ case _DS:
+ buffer += sprintf( buffer, "DS" );
+ break;
+ case _SS:
+ buffer += sprintf( buffer, "SS" );
+ break;
+ case _PC:
+ buffer += sprintf( buffer, "PC" );
+ break;
+ case _SP:
+ buffer += sprintf( buffer, "SP" );
+ break;
+ case _I8:
+ buffer += sprintf( buffer, "0x%02x", oprom[pos++] );
+ break;
+ case _I16:
+ case _A16:
+ buffer += sprintf( buffer, "0x%02x", oprom[pos++] );
+ buffer += sprintf( buffer, "%02x", oprom[pos++] );
+ break;
+ case _I64:
+ buffer += sprintf( buffer, "0x%02x", oprom[pos++] );
+ buffer += sprintf( buffer, "%02x", oprom[pos++] );
+ buffer += sprintf( buffer, "%02x", oprom[pos++] );
+ buffer += sprintf( buffer, "%02x", oprom[pos++] );
+ buffer += sprintf( buffer, "%02x", oprom[pos++] );
+ buffer += sprintf( buffer, "%02x", oprom[pos++] );
+ buffer += sprintf( buffer, "%02x", oprom[pos++] );
+ buffer += sprintf( buffer, "%02x", oprom[pos++] );
+ break;
+ case _I80:
+ buffer += sprintf( buffer, "0x%02x", oprom[pos++] );
+ buffer += sprintf( buffer, "%02x", oprom[pos++] );
+ buffer += sprintf( buffer, "%02x", oprom[pos++] );
+ buffer += sprintf( buffer, "%02x", oprom[pos++] );
+ buffer += sprintf( buffer, "%02x", oprom[pos++] );
+ buffer += sprintf( buffer, "%02x", oprom[pos++] );
+ buffer += sprintf( buffer, "%02x", oprom[pos++] );
+ buffer += sprintf( buffer, "%02x", oprom[pos++] );
+ buffer += sprintf( buffer, "%02x", oprom[pos++] );
+ buffer += sprintf( buffer, "%02x", oprom[pos++] );
+ break;
+ case _A24:
+ buffer += sprintf( buffer, "0x%02x:", oprom[pos++] );
+ buffer += sprintf( buffer, "0x%02x", oprom[pos++] );
+ buffer += sprintf( buffer, "%02x", oprom[pos++] );
+ break;
+ case _ILR:
+ op1 = oprom[pos++];
+ op2 = oprom[pos++];
+ if ( ( op1 & 0x80 ) || ( op2 & 0x80 ) )
+ {
+ /* (lar),reg */
+ buffer += sprintf( buffer, "(%slar%s),r%02x", (op1 & 0x20) ? ( (op1 & 0x40) ? "--" : "++" ) : "", (op1 & 0x20) ? "" : ( (op1 & 0x40) ? "--" : "++" ), op2 & 0x7f );
+ }
+ else
+ {
+ /* reg,(lar) */
+ buffer += sprintf( buffer, "r%02x,(%slar%s)", op2 & 0x7f, (op1 & 0x20) ? ( (op1 & 0x40) ? "--" : "++" ) : "", (op1 & 0x20) ? "" : ( (op1 & 0x40) ? "--" : "++" ) );
+ }
+ break;
+ case _LAR:
+ buffer += sprintf( buffer, "lar" );
+ break;
+ case _DSZ:
+ buffer += sprintf( buffer, "dsize" );
+ break;
+ case _TIM:
+ buffer += sprintf( buffer, "TIM?" );
+ break;
+ case _KLO:
+ buffer += sprintf( buffer, "KOL" );
+ break;
+ case _KHI:
+ buffer += sprintf( buffer, "KOH" );
+ break;
+ default:
+ break;
+ }
+
+ switch( inst->arg2 )
+ {
+ case _REG:
+ buffer += sprintf( buffer, ",r%02x", oprom[pos++] & 0x7f );
+ break;
+ case _F:
+ buffer += sprintf( buffer, ",F" );
+ break;
+ case _CS:
+ buffer += sprintf( buffer, ",CS" );
+ break;
+ case _DS:
+ buffer += sprintf( buffer, ",DS" );
+ break;
+ case _SS:
+ buffer += sprintf( buffer, ",SS" );
+ break;
+ case _PC:
+ buffer += sprintf( buffer, ",PC" );
+ break;
+ case _SP:
+ buffer += sprintf( buffer, ",SP" );
+ break;
+ case _I8:
+ buffer += sprintf( buffer, ",0x%02x", oprom[pos++] );
+ break;
+ case _I16:
+ case _A16:
+ buffer += sprintf( buffer, ",0x%02x", oprom[pos++] );
+ buffer += sprintf( buffer, "%02x", oprom[pos++] );
+ break;
+ case _I64:
+ buffer += sprintf( buffer, ",0x%02x", oprom[pos++] );
+ buffer += sprintf( buffer, "%02x", oprom[pos++] );
+ buffer += sprintf( buffer, "%02x", oprom[pos++] );
+ buffer += sprintf( buffer, "%02x", oprom[pos++] );
+ buffer += sprintf( buffer, "%02x", oprom[pos++] );
+ buffer += sprintf( buffer, "%02x", oprom[pos++] );
+ buffer += sprintf( buffer, "%02x", oprom[pos++] );
+ buffer += sprintf( buffer, "%02x", oprom[pos++] );
+ break;
+ case _I80:
+ buffer += sprintf( buffer, ",0x%02x", oprom[pos++] );
+ buffer += sprintf( buffer, "%02x", oprom[pos++] );
+ buffer += sprintf( buffer, "%02x", oprom[pos++] );
+ buffer += sprintf( buffer, "%02x", oprom[pos++] );
+ buffer += sprintf( buffer, "%02x", oprom[pos++] );
+ buffer += sprintf( buffer, "%02x", oprom[pos++] );
+ buffer += sprintf( buffer, "%02x", oprom[pos++] );
+ buffer += sprintf( buffer, "%02x", oprom[pos++] );
+ buffer += sprintf( buffer, "%02x", oprom[pos++] );
+ buffer += sprintf( buffer, "%02x", oprom[pos++] );
+ break;
+ case _A24:
+ buffer += sprintf( buffer, ",0x%02x:", oprom[pos++] );
+ buffer += sprintf( buffer, "0x%02x", oprom[pos++] );
+ buffer += sprintf( buffer, "%02x", oprom[pos++] );
+ break;
+ case _ILR:
+ /* Implemented by _ILR section for arg1 */
+ break;
+ case _LAR:
+ buffer += sprintf( buffer, ",lar" );
+ break;
+ case _DSZ:
+ buffer += sprintf( buffer, ",dsize" );
+ break;
+ case _TIM:
+ buffer += sprintf( buffer, ",TIM?" );
+ break;
+ case _KI:
+ buffer += sprintf( buffer, ",KI" );
+ break;
+ case _4:
+ buffer += sprintf( buffer, ",4" );
+ break;
+ default:
+ break;
+ }
+
+ return pos | DASMFLAG_SUPPORTED;
+}
+
diff --git a/trunk/src/emu/cpu/hd61700/hd61700.c b/trunk/src/emu/cpu/hd61700/hd61700.c
new file mode 100644
index 00000000000..7d7e7da92ab
--- /dev/null
+++ b/trunk/src/emu/cpu/hd61700/hd61700.c
@@ -0,0 +1,3020 @@
+/******************************************************************************
+
+ Hitachi HD61700 cpu core emulation.
+ by Sandro Ronco
+
+ This CPU core is based on documentations works done by:
+ - Piotr Piatek ( http://www.pisi.com.pl/piotr433/pb1000he.htm )
+ - BLUE ( http://www.geocities.jp/hd61700lab/ )
+
+ The HD61700 has 0x1800 bytes of internal ROM accessed as 16bit with address
+ shift by -1 (mapped from 0x0000 to 0x0c00), the external memory is accessed
+ with a 8bit data bus, this core emulate all memory as 16bit access with
+ address shifted by -1 and in the memory above 0x0c00 only the lower 8bit
+ are used.
+
+ TODO:
+ - dasm don't decode some mnemonics
+ - CPU fast/slow mode
+ - probably other minor things
+
+******************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "hd61700.h"
+
+// internal ROM
+#define INT_ROM 0x0c00
+
+// 5 bit registers
+#define REG_SX m_regsir[0]
+#define REG_SY m_regsir[1]
+#define REG_SZ m_regsir[2]
+#define READ_SREG(a) (m_regsir[((a)>>5) & 0x03] & 0x1f)
+#define WRITE_SREG(a,d) (m_regsir[((a)>>5) & 0x03] = (d) & 0x1f)
+
+// 8 bit registers
+#define REG_PE m_reg8bit[0]
+#define REG_PD m_reg8bit[1]
+#define REG_IB m_reg8bit[2]
+#define REG_UA m_reg8bit[3]
+#define REG_IA m_reg8bit[4]
+#define REG_IE m_reg8bit[5]
+#define REG_TM m_reg8bit[7]
+#define READ_REG8(a) (m_reg8bit[(a) & 0x07])
+#define WRITE_REG8(a,d) (m_reg8bit[(a) & 0x07] = d)
+
+// 16 bit registers
+#define REG_IX m_reg16bit[0]
+#define REG_IY m_reg16bit[1]
+#define REG_IZ m_reg16bit[2]
+#define REG_US m_reg16bit[3]
+#define REG_SS m_reg16bit[4]
+#define REG_KY m_reg16bit[5]
+
+// main registers
+#define READ_REG(a) (m_regmain[(a) & 0x1f])
+#define WRITE_REG(a,d) (m_regmain[(a) & 0x1f] = d)
+#define COPY_REG(d,s) (m_regmain[(d) & 0x1f] = m_regmain[(s) & 0x1f])
+#define REG_GET16(r) (((m_regmain[((r)) & 0x1f]<<0)) | (m_regmain[((r) + 1) & 0x1f]<<8))
+#define REG_PUT16(r,d) do{(m_regmain[(r) & 0x1f] = (((d)>>0) & 0xff)); (m_regmain[((r)+1)&0x1f]=(((d)>>8)&0xff));}while(0)
+
+// opcode
+#define GET_REG_IDX(a,b) (((a<<2) & 0x04) | ((b>>5) & 0x03))
+#define RESTORE_REG(o,r,pr) r = (o&0x02) ? r : pr
+#define COND_WRITE_REG(o,a,d) if (o&0x08) WRITE_REG(a,d)
+#define GET_IM3(d) (((d>>5)&0x07) + 1)
+
+// flags
+#define SET_FLAG_C m_flags |= FLAG_C
+#define CLEAR_FLAG_Z m_flags |= FLAG_Z
+#define CLEAR_FLAG_LZ m_flags |= FLAG_LZ
+#define CLEAR_FLAG_UZ m_flags |= FLAG_UZ
+#define CLEAR_FLAGS m_flags &= ~(FLAG_Z | FLAG_C | FLAG_LZ | FLAG_UZ)
+
+#define CHECK_FLAG_Z(d) if((d) != 0) CLEAR_FLAG_Z
+#define CHECK_FLAG_C(d,l) if (d > l) SET_FLAG_C
+#define CHECK_FLAGB_LZ(d) if(((d) & 0x0f) != 0) CLEAR_FLAG_LZ
+#define CHECK_FLAGB_UZ(d) if(((d) & 0xf0) != 0) CLEAR_FLAG_UZ
+#define CHECK_FLAGW_LZ(d) if(((d) & 0x0f00) != 0) CLEAR_FLAG_LZ
+#define CHECK_FLAGW_UZ(d) if(((d) & 0xf000) != 0) CLEAR_FLAG_UZ
+#define CHECK_FLAGB_UZ_LZ(d) do{CHECK_FLAGB_LZ(d); CHECK_FLAGB_UZ(d);}while(0)
+#define CHECK_FLAGW_UZ_LZ(d) do{CHECK_FLAGW_LZ(d); CHECK_FLAGW_UZ(d);}while(0)
+
+//CPU state
+#define CPU_FAST 0x01
+#define CPU_SLP 0x02
+
+/* HD61700 IRQ vector */
+static const UINT16 irq_vector[] = {0x0032, 0x0042, 0x0052, 0x0062, 0x0072};
+
+//**************************************************************************
+// HD61700 DEVICE
+//**************************************************************************
+
+const device_type HD61700 = &device_creator<hd61700_cpu_device>;
+
+//-------------------------------------------------
+// hd61700_cpu_device - constructor
+//-------------------------------------------------
+
+hd61700_cpu_device::hd61700_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : cpu_device(mconfig, HD61700, "HD61700", tag, owner, clock),
+ m_program_config("program", ENDIANNESS_BIG, 16, 18, -1)
+{
+ memset(&m_partial_frame_period, 0, sizeof(m_partial_frame_period));
+}
+
+
+//-------------------------------------------------
+// static_set_config - set the configuration
+// structure
+//-------------------------------------------------
+
+void hd61700_cpu_device::static_set_config(device_t &device, const hd61700_config &config)
+{
+ hd61700_cpu_device &conf = downcast<hd61700_cpu_device &>(device);
+ static_cast<hd61700_config &>(conf) = config;
+}
+
+//-------------------------------------------------
+// device_start - start up the device
+//-------------------------------------------------
+
+void hd61700_cpu_device::device_start()
+{
+ m_program = this->space(AS_PROGRAM);
+
+ m_sec_timer = timer_alloc(SEC_TIMER);
+ m_sec_timer->adjust(attotime::from_seconds(1), 0, attotime::from_seconds(1));
+
+ // save state
+ save_item(NAME(m_ppc));
+ save_item(NAME(m_curpc));
+ save_item(NAME(m_pc));
+ save_item(NAME(m_flags));
+ save_item(NAME(m_fetch_addr));
+ save_item(NAME(m_irq_status));
+ save_item(NAME(m_state));
+ save_item(NAME(prev_ua));
+ save_item(NAME(m_icount));
+ save_item(NAME(m_regsir));
+ save_item(NAME(m_reg8bit));
+ save_item(NAME(m_reg16bit));
+ save_item(NAME(m_regmain));
+ save_item(NAME(m_lines_status));
+
+ // register state for debugger
+ state_add(HD61700_PC, "pc", m_pc).callimport().callexport().formatstr("%04X");
+ state_add(HD61700_F, "f", m_flags).callimport().callexport().formatstr("%02X");
+ state_add(HD61700_SX, "SX", REG_SX).callimport().callexport().formatstr("%02X");
+ state_add(HD61700_SY, "SY", REG_SY).callimport().callexport().formatstr("%02X");
+ state_add(HD61700_SZ, "SZ", REG_SZ).callimport().callexport().formatstr("%02X");
+
+ state_add(HD61700_PE, "pe", REG_PE).callimport().callexport().formatstr("%02X");
+ state_add(HD61700_PD, "pd", REG_PD).callimport().callexport().formatstr("%02X");
+ state_add(HD61700_IB, "ib", REG_IB).callimport().callexport().formatstr("%02X");
+ state_add(HD61700_UA, "ua", REG_UA).callimport().callexport().formatstr("%02X");
+ state_add(HD61700_IA, "ia", REG_IA).callimport().callexport().formatstr("%02X");
+ state_add(HD61700_IE, "ie", REG_IE).callimport().callexport().formatstr("%02X");
+ state_add(HD61700_TM, "tm", REG_TM).callimport().callexport().formatstr("%02X");
+
+ state_add(HD61700_IX, "ix", REG_IX).callimport().callexport().formatstr("%04X");
+ state_add(HD61700_IY, "iy", REG_IY).callimport().callexport().formatstr("%04X");
+ state_add(HD61700_IZ, "iz", REG_IZ).callimport().callexport().formatstr("%04X");
+ state_add(HD61700_US, "us", REG_US).callimport().callexport().formatstr("%04X");
+ state_add(HD61700_SS, "ss", REG_SS).callimport().callexport().formatstr("%04X");
+ state_add(HD61700_KY, "ky", REG_KY).callimport().callexport().formatstr("%04X");
+
+ for (int ireg=0; ireg<32; ireg++)
+ {
+ astring tmpstr;
+ state_add(HD61700_MAINREG + ireg, tmpstr.format("R%d", ireg), m_regmain[ireg]).callimport().callexport().formatstr("%02X");
+ }
+
+ state_add(STATE_GENPC, "curpc", m_curpc).callimport().callexport().formatstr("%8s").noshow();
+ state_add(STATE_GENPCBASE, "curpcbase", m_ppc).callimport().callexport().formatstr("%8s").noshow();
+ state_add(STATE_GENFLAGS, "GENFLAGS", m_flags).mask(0xff).formatstr("%8s").noshow();
+
+ // set our instruction counter
+ m_icountptr = &m_icount;
+}
+
+
+//-------------------------------------------------
+// device_reset - reset up the device
+//-------------------------------------------------
+
+void hd61700_cpu_device::device_reset()
+{
+ m_ppc = 0x0000;
+ m_curpc = 0x0000;
+ set_pc(0x0000);
+ m_flags = FLAG_SW;
+ m_icount = 0;
+ m_state = 0;
+ m_irq_status = 0;
+ prev_ua = 0;
+
+ memset(m_regsir, 0, ARRAY_LENGTH(m_regsir));
+ memset(m_reg8bit, 0, ARRAY_LENGTH(m_reg8bit));
+ memset(m_reg16bit, 0, ARRAY_LENGTH(m_reg16bit) * sizeof(UINT16));
+ memset(m_regmain, 0, ARRAY_LENGTH(m_regmain));
+
+ for (int i=0;i<6; i++)
+ m_lines_status[i] = CLEAR_LINE;
+}
+
+
+
+//-------------------------------------------------
+// device_timer - handler timer events
+//-------------------------------------------------
+void hd61700_cpu_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ switch(id)
+ {
+ case SEC_TIMER:
+ REG_TM++;
+ if ((REG_TM&0x3f) == 60)
+ {
+ REG_TM = (REG_TM & 0xc0) + 0x40;
+
+ if (((REG_IE>>3) & (1<<HD61700_TIMER_INT)))
+ {
+ REG_IB |= (1<<HD61700_TIMER_INT);
+
+ if (REG_IB & 0x20)
+ {
+ m_state &= ~CPU_SLP;
+ m_flags |= FLAG_APO;
+ }
+ }
+ }
+ break;
+ }
+}
+
+
+
+//-------------------------------------------------
+// state_import - import state into the device,
+// after it has been set
+//-------------------------------------------------
+
+void hd61700_cpu_device::state_import(const device_state_entry &entry)
+{
+ switch (entry.index())
+ {
+ case HD61700_PC:
+ set_pc(m_pc);
+ break;
+ }
+}
+
+//-------------------------------------------------
+// state_string_export - export state as a string
+// for the debugger
+//-------------------------------------------------
+
+void hd61700_cpu_device::state_string_export(const device_state_entry &entry, astring &string)
+{
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ string.printf("%c%c%c%c%c%c",
+ m_flags & FLAG_Z ? '.' : 'Z',
+ m_flags & FLAG_C ? 'C' : '.',
+ m_flags & FLAG_LZ ? '.' : 'L',
+ m_flags & FLAG_UZ ? '.' : 'U',
+ m_flags & FLAG_SW ? 'S' : '.',
+ m_flags & FLAG_APO ? 'A' : '.'
+ );
+ break;
+ }
+}
+
+
+
+//-------------------------------------------------
+// disasm_disassemble - call the disassembly
+// helper function
+//-------------------------------------------------
+
+offs_t hd61700_cpu_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
+{
+ extern CPU_DISASSEMBLE( hd61700 );
+ return CPU_DISASSEMBLE_NAME(hd61700)(NULL, buffer, pc, oprom, opram, 0);
+}
+
+
+
+//-------------------------------------------------
+// check_irqs - check if need interrupts
+//-------------------------------------------------
+
+bool hd61700_cpu_device::check_irqs(void)
+{
+ for (int i=4; i>=0; i--)
+ {
+ if (REG_IB & (1<<i) && !(m_irq_status & (1<<i)))
+ {
+ m_irq_status |= (1<<i);
+ push(REG_SS, (m_pc>>8)&0xff);
+ push(REG_SS, (m_pc>>0)&0xff);
+
+ set_pc(irq_vector[i]);
+ m_icount -= 12;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+//-------------------------------------------------
+// execute - execute for the provided number of
+// cycles
+//-------------------------------------------------
+
+void hd61700_cpu_device::execute_run()
+{
+ do
+ {
+ debugger_instruction_hook(this, m_curpc);
+
+ // verify that CPU is not in sleep
+ if (m_state & CPU_SLP)
+ {
+ m_icount -= 6;
+ }
+ else
+ {
+ UINT8 op;
+
+ check_irqs();
+
+ m_ppc = m_curpc;
+
+ // instruction fetch
+ op = read_op();
+
+ // execute the instruction
+ switch ( op )
+ {
+ case 0x00: //adc
+ case 0x01: //sbc
+ case 0x08: //ad
+ case 0x09: //sb
+ {
+ UINT8 arg = read_op();
+ UINT8 src = READ_REG(get_sir_im8(arg));
+ UINT16 res = READ_REG(arg) + ((op&1) ? -src : +src);
+
+ COND_WRITE_REG(op, arg, res & 0xff);
+
+ CLEAR_FLAGS;
+ CHECK_FLAG_Z(res & 0xff);
+ CHECK_FLAGB_UZ_LZ(res);
+ CHECK_FLAG_C(res, 0xff);
+
+ check_optional_jr(arg);
+ m_icount -= 3;
+ }
+ break;
+
+ case 0x02: //ld
+ {
+ UINT8 arg = read_op();
+ COPY_REG(arg, get_sir_im8(arg));
+
+ check_optional_jr(arg);
+ m_icount -= 3;
+ }
+ break;
+
+ case 0x04: //anc
+ case 0x05: //nac
+ case 0x06: //orc
+ case 0x07: //xrc
+ case 0x0c: //an
+ case 0x0d: //na
+ case 0x0e: //or
+ case 0x0f: //xr
+ {
+ UINT8 arg = read_op();
+
+ UINT8 res = make_logic(op, READ_REG(arg), READ_REG(get_sir_im8(arg)));
+
+ COND_WRITE_REG(op, arg, res);
+
+ CLEAR_FLAGS;
+ CHECK_FLAG_Z(res & 0xff);
+ CHECK_FLAGB_UZ_LZ(res);
+
+ //na(c) and or(c) always set C flag
+ if ((op&3) == 1 || (op&3) == 2)
+ SET_FLAG_C;
+
+ check_optional_jr(arg);
+ m_icount -= 3;
+ }
+ break;
+
+ case 0x0a: //adb
+ case 0x0b: //sbb
+ {
+ UINT8 arg = read_op();
+ UINT16 res;
+
+ if (op & 0x01)
+ res = make_bcd_sub(READ_REG(arg), READ_REG(get_sir_im8(arg)));
+ else
+ res = make_bcd_add(READ_REG(arg), READ_REG(get_sir_im8(arg)));
+
+ WRITE_REG(arg, res & 0xff);
+
+ CLEAR_FLAGS;
+ CHECK_FLAG_Z(res & 0xff);
+ CHECK_FLAGB_UZ_LZ(res);
+ CHECK_FLAG_C(res, 0xff);
+
+ check_optional_jr(arg);
+ m_icount -= 3;
+ }
+ break;
+
+ case 0x10: //st
+ {
+ UINT8 arg = read_op();
+ UINT8 src = get_sir_im8(arg);
+ UINT16 offset = REG_GET16(src);
+
+ mem_writebyte(REG_UA>>4, offset, READ_REG(arg));
+
+ check_optional_jr(arg);
+ m_icount -= 8;
+ }
+ break;
+
+ case 0x11: //ld
+ {
+ UINT8 arg = read_op();
+ UINT8 src = get_sir_im8(arg);
+ UINT16 offset = REG_GET16(src);
+
+ WRITE_REG(arg, mem_readbyte(REG_UA>>4, offset));
+
+ check_optional_jr(arg);
+ m_icount -= 8;
+ }
+ break;
+
+ case 0x12: //stl
+ {
+ UINT8 arg = read_op();
+
+ if (m_lcd_data_w)
+ (*m_lcd_data_w)(*this, READ_REG(arg));
+
+ check_optional_jr(arg);
+ m_icount -= 11;
+ }
+ break;
+
+ case 0x13: //ldl
+ {
+ UINT8 arg = read_op();
+ UINT8 res = 0xff;
+
+ if (m_lcd_data_r)
+ res = (*m_lcd_data_r)(*this);
+
+ WRITE_REG(arg, res);
+
+ check_optional_jr(arg);
+ m_icount -= 11;
+ }
+ break;
+
+ case 0x14: //ppo/pfl
+ {
+ UINT8 arg = read_op();
+
+ if (arg & 0x40)
+ {
+ m_flags = (m_flags & 0x0f) | (READ_REG(arg) & 0xf0);
+ }
+ else
+ {
+ if (m_lcd_control)
+ (*m_lcd_control)(*this, READ_REG(arg));
+ }
+
+ check_optional_jr(arg);
+ m_icount -= 3;
+ }
+ break;
+
+ case 0x15: //psr
+ {
+ UINT8 arg = read_op();
+ WRITE_SREG(arg, READ_REG(arg)&0x1f);
+
+ check_optional_jr(arg);
+ m_icount -= 3;
+ }
+ break;
+
+ case 0x16: //pst
+ case 0x17: //pst
+ {
+ UINT8 arg = read_op();
+ UINT8 src = READ_REG(arg);
+ UINT8 idx = GET_REG_IDX(op, arg);
+
+ switch (idx)
+ {
+ case 0: //PE
+ case 1: //PD
+ WRITE_REG8(idx, src);
+ if (m_port_w)
+ (*m_port_w)(*this, REG_PD & REG_PE);
+ break;
+ case 2: //IB
+ REG_IB = (REG_IB & 0x1f) | (src & 0xe0);
+ break;
+ case 3: //UA
+ WRITE_REG8(idx, src);
+ break;
+ case 4: //IA
+ if (m_kb_w)
+ (*m_kb_w)(*this, src);
+ WRITE_REG8(idx, src);
+ break;
+ case 5: //IE
+ REG_IB &= (((src>>3)&0x1f) | 0xe0);
+ m_irq_status &= ((src>>3)&0x1f);
+ WRITE_REG8(idx, src);
+ break;
+ case 6: //TM
+ case 7: //TM
+ // read-only
+ break;
+ }
+
+ check_optional_jr(arg);
+ m_icount -= 3;
+ }
+ break;
+
+ case 0x18:
+ {
+ UINT8 arg = read_op();
+ UINT8 op1 = (arg>>5) & 0x03;
+ switch (op1)
+ {
+ case 0x00: //rod
+ case 0x02: //bid
+ {
+ UINT8 src = READ_REG(arg);
+ UINT8 res = (src>>1)&0x7f;
+
+ if (!(op1&0x02))
+ res = res | ((m_flags&FLAG_C) !=0 )<<7;
+
+ WRITE_REG(arg, res);
+
+ CLEAR_FLAGS;
+ CHECK_FLAG_Z(res & 0xff);
+ CHECK_FLAGB_UZ_LZ(res);
+ if (src&0x01) SET_FLAG_C;
+ }
+ break;
+
+ case 0x01: //rou
+ case 0x03: //biu
+ {
+ UINT8 src = READ_REG(arg);
+ UINT8 res = (src<<1)&0xfe;
+
+ if (!(op1&0x02))
+ res = res | ((m_flags&FLAG_C) !=0 )<<0;
+
+ WRITE_REG(arg, res);
+
+ CLEAR_FLAGS;
+ CHECK_FLAG_Z(res & 0xff);
+ CHECK_FLAGB_UZ_LZ(res);
+ if (src&0x80) SET_FLAG_C;
+ }
+ break;
+ }
+
+ check_optional_jr(arg);
+ m_icount -= 3;
+ }
+ break;
+
+ case 0x1a:
+ {
+ UINT8 arg = read_op();
+ UINT8 op1 = (arg>>5) & 0x03;
+ switch (op1)
+ {
+ case 0x00: //did
+ case 0x01: //diu
+ {
+ UINT8 res;
+
+ if (op1&0x01)
+ res = (READ_REG(arg)<<4)&0xf0;
+ else
+ res = (READ_REG(arg)>>4)&0x0f;
+
+ WRITE_REG(arg, res);
+
+ CLEAR_FLAGS;
+ CHECK_FLAG_Z(res & 0xff);
+ CHECK_FLAGB_UZ_LZ(res);
+ }
+ break;
+ case 0x02: //byd
+ case 0x03: //byu
+ {
+ WRITE_REG(arg, 0);
+ CLEAR_FLAGS;
+ break;
+ }
+ }
+
+ check_optional_jr(arg);
+ m_icount -= 3;
+ }
+ break;
+
+ case 0x1b: //cmp/inv
+ {
+ UINT8 arg = read_op();
+ UINT8 res = ~(READ_REG(arg));
+ if (!(arg & 0x40)) res++;
+
+ WRITE_REG(arg, res);
+
+ CLEAR_FLAGS;
+ CHECK_FLAG_Z(res & 0xff);
+ CHECK_FLAGB_UZ_LZ(res);
+ if (res || (arg & 0x40)) SET_FLAG_C;
+
+ check_optional_jr(arg);
+ m_icount -= 3;
+ }
+ break;
+
+ case 0x1c: //gpo/gfl
+ {
+ UINT8 arg = read_op();
+ UINT8 src = 0xff;
+
+ if (arg&0x40)
+ {
+ src = m_flags;
+ }
+ else
+ {
+ if (m_port_r)
+ src = (*m_port_r)(*this);
+
+ src&=(~REG_PE);
+ }
+
+ WRITE_REG(arg, src);
+
+ check_optional_jr(arg);
+ m_icount -= 3;
+ }
+ break;
+
+ case 0x1d: //gsr
+ {
+ UINT8 arg = read_op();
+ WRITE_REG(arg, READ_SREG(arg));
+ check_optional_jr(arg);
+ m_icount -= 3;
+ }
+ break;
+
+ case 0x1e: //gst
+ case 0x1f: //gst
+ {
+ UINT8 arg = read_op();
+ UINT8 idx = GET_REG_IDX(op, arg);
+ WRITE_REG(arg, READ_REG8(idx));
+ check_optional_jr(arg);
+ m_icount -= 3;
+ }
+ break;
+
+ case 0x20: //st
+ case 0x22: //sti
+ {
+ UINT8 arg = read_op();
+ UINT16 prev_ir = REG_IX;
+ REG_IX += get_sign_mreg(arg);
+
+ mem_writebyte(REG_UA>>4, REG_IX++, READ_REG(arg));
+
+ RESTORE_REG(op, REG_IX, prev_ir);
+
+ m_icount -= 8;
+ }
+ break;
+
+ case 0x21: //st
+ case 0x23: //sti
+ {
+ UINT8 arg = read_op();
+ UINT16 prev_ir = REG_IZ;
+ REG_IZ += get_sign_mreg(arg);
+
+ mem_writebyte(REG_UA>>6, REG_IZ++, READ_REG(arg));
+
+ RESTORE_REG(op, REG_IZ, prev_ir);
+
+ m_icount -= 8;
+ }
+ break;
+
+ case 0x24: //std
+ {
+ UINT8 arg = read_op();
+ REG_IX += get_sign_mreg(arg);
+
+ mem_writebyte(REG_UA>>4, REG_IX, READ_REG(arg));
+ m_icount -= 6;
+ }
+ break;
+
+ case 0x25: //std
+ {
+ UINT8 arg = read_op();
+ REG_IZ += get_sign_mreg(arg);
+
+ mem_writebyte(REG_UA>>6, REG_IZ, READ_REG(arg));
+ m_icount -= 6;
+ }
+ break;
+
+ case 0x26: //phs
+ {
+ UINT8 arg = read_op();
+
+ push(REG_SS, READ_REG(arg));
+ m_icount -= 9;
+ }
+ break;
+ case 0x27: //phu
+ {
+ UINT8 arg = read_op();
+
+ push(REG_US, READ_REG(arg));
+ m_icount -= 9;
+ }
+ break;
+
+ case 0x28: //ld
+ case 0x2a: //ldi
+ {
+ UINT8 arg = read_op();
+ UINT16 prev_ir = REG_IX;
+ REG_IX += get_sign_mreg(arg);
+
+ WRITE_REG(arg, mem_readbyte(REG_UA>>4, REG_IX++));
+
+ RESTORE_REG(op, REG_IX, prev_ir);
+
+ m_icount -= 8;
+ }
+ break;
+
+ case 0x29: //ld
+ case 0x2b: //ldi
+ {
+ UINT8 arg = read_op();
+ UINT16 prev_ir = REG_IZ;
+ REG_IZ += get_sign_mreg(arg);
+
+ WRITE_REG(arg, mem_readbyte(REG_UA>>6, REG_IZ++));
+
+ RESTORE_REG(op, REG_IZ, prev_ir);
+
+ m_icount -= 8;
+ }
+ break;
+
+ case 0x2c: //ldd
+ {
+ UINT8 arg = read_op();
+ REG_IX += get_sign_mreg(arg);
+
+ WRITE_REG(arg, mem_readbyte(REG_UA>>4, REG_IX));
+
+ m_icount -= 6;
+ }
+ break;
+
+ case 0x2d: //ldd
+ {
+ UINT8 arg = read_op();
+ REG_IZ += get_sign_mreg(arg);
+
+ WRITE_REG(arg, mem_readbyte(REG_UA>>6, REG_IZ));
+
+ m_icount -= 6;
+ }
+ break;
+
+ case 0x2e: //pps
+ {
+ UINT8 arg = read_op();
+ WRITE_REG(arg, pop(REG_SS));
+
+ m_icount -= 11;
+ }
+ break;
+ case 0x2f: //ppu
+ {
+ UINT8 arg = read_op();
+ WRITE_REG(arg, pop(REG_US));
+
+ m_icount -= 11;
+ }
+ break;
+
+ case 0x30: //jp z
+ case 0x31: //jp nc
+ case 0x32: //jp lz
+ case 0x33: //jp uz
+ case 0x34: //jp nz
+ case 0x35: //jp c
+ case 0x36: //jp nlz
+ case 0x37: //unconditional jp
+ {
+ UINT8 lsb = read_op();
+ if (m_pc < INT_ROM) read_op();
+ UINT8 msb = read_op();
+
+ if (check_cond(op))
+ set_pc((msb<<8) | lsb);
+ m_icount -= 3;
+ }
+ break;
+
+ case 0x38: //adc
+ case 0x3a: //sbc
+ case 0x3c: //ad
+ case 0x3e: //sb
+ {
+ UINT8 arg = read_op();
+ UINT16 offset = REG_IX + get_sign_mreg(arg);
+ UINT8 src = mem_readbyte(REG_UA>>4, offset);
+
+ UINT16 res = src + ((op & 2) ? -READ_REG(arg) : +READ_REG(arg)) ;
+
+ if ((op & 4))
+ mem_writebyte(REG_UA>>4, offset, res & 0xff);
+
+ CLEAR_FLAGS;
+ CHECK_FLAG_Z(res & 0xff);
+ CHECK_FLAGB_UZ_LZ(res);
+ CHECK_FLAG_C(res, 0xff);
+
+ m_icount -= 9;
+ }
+ break;
+
+ case 0x39: //adc
+ case 0x3b: //sbc
+ case 0x3d: //ad
+ case 0x3f: //sb
+ {
+ UINT8 arg = read_op();
+ UINT16 offset = REG_IZ + get_sign_mreg(arg);
+ UINT8 src = mem_readbyte(REG_UA>>6, offset);
+
+ UINT16 res = src + ((op & 2) ? -READ_REG(arg) : +READ_REG(arg)) ;
+
+ if ((op & 4))
+ mem_writebyte(REG_UA>>6, offset, res & 0xff);
+
+ CLEAR_FLAGS;
+ CHECK_FLAG_Z(res & 0xff);
+ CHECK_FLAGB_UZ_LZ(res);
+ CHECK_FLAG_C(res, 0xff);
+
+ m_icount -= 9;
+ }
+ break;
+
+ case 0x40: //adc
+ case 0x41: //sbc
+ case 0x48: //ad
+ case 0x49: //sb
+ {
+ UINT8 arg = read_op();
+ UINT8 src = read_op();
+ UINT16 res = READ_REG(arg) + ((op&1) ? -src : +src);
+
+ COND_WRITE_REG(op, arg, res & 0xff);
+
+ CLEAR_FLAGS;
+ CHECK_FLAG_Z(res & 0xff);
+ CHECK_FLAGB_UZ_LZ(res);
+ CHECK_FLAG_C(res, 0xff);
+
+ check_optional_jr(arg);
+ m_icount -= 3;
+ }
+ break;
+
+ case 0x42: //ld
+ {
+ UINT8 arg = read_op();
+ UINT8 src = read_op() ;
+
+ WRITE_REG(arg, src);
+
+ check_optional_jr(arg);
+ m_icount -= 3;
+ }
+ break;
+
+ case 0x44: //anc
+ case 0x45: //nac
+ case 0x46: //orc
+ case 0x47: //xrc
+ case 0x4c: //an
+ case 0x4d: //na
+ case 0x4e: //or
+ case 0x4f: //xr
+ {
+ UINT8 arg = read_op();
+ UINT8 src = read_op();
+
+ UINT8 res = make_logic(op, READ_REG(arg), src);
+
+ COND_WRITE_REG(op, arg, res);
+
+ CLEAR_FLAGS;
+ CHECK_FLAG_Z(res & 0xff);
+ CHECK_FLAGB_UZ_LZ(res);
+
+ //na(c) and or(c) always set C flag
+ if ((op&3) == 1 || (op&3) == 2)
+ SET_FLAG_C;
+
+ check_optional_jr(arg);
+ m_icount -= 3;
+ }
+ break;
+
+ case 0x4a: //adb
+ case 0x4b: //sbb
+ {
+ UINT8 arg = read_op();
+ UINT8 src = read_op();
+ UINT16 res;
+
+ if (op & 0x01)
+ res = make_bcd_sub(READ_REG(arg), src);
+ else
+ res = make_bcd_add(READ_REG(arg), src);
+
+ WRITE_REG(arg, res & 0xff);
+
+ CLEAR_FLAGS;
+ CHECK_FLAG_Z(res & 0xff);
+ CHECK_FLAGB_UZ_LZ(res);
+ CHECK_FLAG_C(res, 0xff);
+
+ check_optional_jr(arg);
+ m_icount -= 3;
+ }
+ break;
+
+ case 0x50: //st
+ {
+ UINT8 arg = read_op();
+ UINT8 src = read_op();
+ UINT16 offset = REG_GET16(READ_SREG(arg));
+
+ mem_writebyte(REG_UA>>4, offset, src);
+ m_icount -= 8;
+ }
+ break;
+
+ case 0x51: //ld
+ {
+ UINT8 arg = read_op();
+ UINT8 src = read_op();
+
+ WRITE_REG(arg, src);
+ m_icount -= 8;
+ }
+ break;
+
+ case 0x52: //stl
+ {
+ UINT8 arg = read_op();
+
+ if (m_lcd_data_w)
+ (*m_lcd_data_w)(*this, arg);
+
+ m_icount -= 12;
+ }
+ break;
+
+ case 0x54: //ppo/pfl
+ {
+ UINT8 arg = read_op();
+ UINT8 src = read_op();
+
+ if (arg & 0x40)
+ {
+ m_flags = (m_flags & 0x0f) | (src & 0xf0);
+ }
+ else
+ {
+ if (m_lcd_control)
+ (*m_lcd_control)(*this, src);
+ }
+
+ m_icount -= 3;
+ }
+ break;
+
+ case 0x55: //psr
+ {
+ UINT8 arg = read_op();
+ WRITE_SREG(arg, arg&0x1f);
+
+ m_icount -= 3;
+ }
+ break;
+
+ case 0x56: //pst
+ case 0x57: //pst
+ {
+ UINT8 arg = read_op();
+ UINT8 src = read_op();
+ UINT8 idx = GET_REG_IDX(op, arg);
+
+ switch (idx)
+ {
+ case 0: //PE
+ case 1: //PD
+ WRITE_REG8(idx, src);
+ if (m_port_w)
+ (*m_port_w)(*this, REG_PD & REG_PE);
+ break;
+ case 2: //IB
+ REG_IB = (REG_IB & 0x1f) | (src & 0xe0);
+ break;
+ case 3: //UA
+ WRITE_REG8(idx, src);
+ break;
+ case 4: //IA
+ if (m_kb_w)
+ (*m_kb_w)(*this, src);
+ WRITE_REG8(idx, src);
+ break;
+ case 5: //IE
+ REG_IB &= (((src>>3)&0x1f) | 0xe0);
+ m_irq_status &= ((src>>3)&0x1f);
+ WRITE_REG8(idx, src);
+ break;
+ case 6: //TM
+ case 7: //TM
+ // read-only
+ break;
+ }
+
+ m_icount -= 3;
+ }
+ break;
+
+ case 0x58: //bups
+ case 0x59: //bdns
+ {
+ UINT8 arg = read_op();
+ UINT8 tmp;
+ UINT16 res;
+
+ for(;;)
+ {
+ tmp = mem_readbyte(REG_UA>>4, REG_IX);
+ mem_writebyte(REG_UA>>6, REG_IZ, tmp);
+
+ res = tmp - arg;
+ if (REG_IX == REG_IY || !res)
+ break;
+
+ REG_IX += ((op&1) ? -1 : +1);
+ REG_IZ += ((op&1) ? -1 : +1);
+ m_icount -= 6;
+ }
+
+ CLEAR_FLAGS;
+ CHECK_FLAG_Z(res & 0xff);
+ CHECK_FLAGB_UZ_LZ(res);
+ CHECK_FLAG_C(res, 0xff);
+
+ m_icount -= 9;
+ }
+ break;
+
+ case 0x5c: //sup
+ case 0x5d: //sdn
+ {
+ UINT8 arg = read_op();
+ UINT16 res;
+
+ for(;;)
+ {
+ res = mem_readbyte(REG_UA>>4, REG_IX) - arg;
+
+ if (REG_IX == REG_IY || !res)
+ break;
+
+ REG_IX += ((op&1) ? -1 : +1);
+ m_icount -= 6;
+ }
+
+ CLEAR_FLAGS;
+ CHECK_FLAG_Z(res & 0xff);
+ CHECK_FLAGB_UZ_LZ(res);
+ CHECK_FLAG_C(res, 0xff);
+
+ m_icount -= 9;
+ }
+ break;
+
+ case 0x60: //st
+ case 0x62: //sti
+ {
+ UINT8 arg = read_op();
+ UINT16 prev_ir = REG_IX;
+ REG_IX += get_sign_im8(arg);
+
+ mem_writebyte(REG_UA>>4, REG_IX++, READ_REG(arg));
+
+ RESTORE_REG(op, REG_IX, prev_ir);
+
+ m_icount -= 8;
+ }
+ break;
+
+ case 0x61: //st
+ case 0x63: //sti
+ {
+ UINT8 arg = read_op();
+ UINT16 prev_ir = REG_IZ;
+ REG_IZ += get_sign_im8(arg);
+
+ mem_writebyte(REG_UA>>6, REG_IZ++, READ_REG(arg));
+
+ RESTORE_REG(op, REG_IZ, prev_ir);
+ m_icount -= 8;
+ }
+ break;
+
+ case 0x64: //std
+ {
+ UINT8 arg = read_op();
+ REG_IX += get_sign_im8(arg);
+
+ mem_writebyte(REG_UA>>4, REG_IX, READ_REG(arg));
+ m_icount -= 6;
+ }
+ break;
+
+ case 0x65: //std
+ {
+ UINT8 arg = read_op();
+ REG_IZ += get_sign_im8(arg);
+
+ mem_writebyte(REG_UA>>6, REG_IZ, READ_REG(arg));
+ m_icount -= 6;
+ }
+ break;
+
+ case 0x68: //ld
+ case 0x6a: //ldi
+ {
+ UINT8 arg = read_op();
+ UINT16 prev_ir = REG_IX;
+ REG_IX += get_sign_im8(arg);
+
+ WRITE_REG(arg, mem_readbyte(REG_UA>>4, REG_IX++));
+
+ RESTORE_REG(op, REG_IX, prev_ir);
+ m_icount -= 8;
+ }
+ break;
+
+ case 0x69: //ld
+ case 0x6b: //ldi
+ {
+ UINT8 arg = read_op();
+ UINT16 prev_ir = REG_IZ;
+ REG_IZ += get_sign_im8(arg);
+
+ WRITE_REG(arg, mem_readbyte(REG_UA>>6, REG_IZ++));
+
+ RESTORE_REG(op, REG_IZ, prev_ir);
+ m_icount -= 8;
+ }
+ break;
+
+ case 0x6c: //ldd
+ {
+ UINT8 arg = read_op();
+ REG_IX += get_sign_im8(arg);
+
+ WRITE_REG(arg, mem_readbyte(REG_UA>>4, REG_IX));
+ m_icount -= 6;
+ }
+ break;
+
+ case 0x6d: //ldd
+ {
+ UINT8 arg = read_op();
+ REG_IZ += get_sign_im8(arg);
+
+ WRITE_REG(arg, mem_readbyte(REG_UA>>6, REG_IZ));
+ m_icount -= 6;
+ }
+ break;
+
+ case 0x70: //cal z
+ case 0x71: //cal nc
+ case 0x72: //cal lz
+ case 0x73: //cal uz
+ case 0x74: //cal nz
+ case 0x75: //cal c
+ case 0x76: //cal nlz
+ case 0x77: //unconditional cal
+ {
+ UINT8 lsb = read_op();
+ if (m_pc < INT_ROM) read_op();
+ UINT8 msb = read_op();
+
+ if (check_cond(op))
+ {
+ m_pc--;
+ push(REG_SS, (m_pc>>8)&0xff);
+ push(REG_SS, (m_pc>>0)&0xff);
+
+ set_pc((msb<<8) | lsb);
+ m_icount -= 6;
+ }
+ m_icount -= 3;
+ }
+ break;
+
+ case 0x78: //adc
+ case 0x7a: //sbc
+ case 0x7c: //ad
+ case 0x7e: //sb
+ {
+ UINT8 arg = read_op();
+ UINT16 offset = REG_IX + get_sign_im8(arg);
+ UINT8 src = mem_readbyte(REG_UA>>4, offset);
+
+ UINT16 res = src + ((op & 2) ? -READ_REG(arg) : +READ_REG(arg)) ;
+
+ if ((op & 4))
+ mem_writebyte(REG_UA>>4, offset, res & 0xff);
+
+ CLEAR_FLAGS;
+ CHECK_FLAG_Z(res & 0xff);
+ CHECK_FLAGB_UZ_LZ(res);
+ CHECK_FLAG_C(res, 0xff);
+
+ m_icount -= 9;
+ }
+ break;
+
+ case 0x79: //adc
+ case 0x7b: //sbc
+ case 0x7d: //ad
+ case 0x7f: //sb
+ {
+ UINT8 arg = read_op();
+ UINT16 offset = REG_IZ + get_sign_im8(arg);
+ UINT8 src = mem_readbyte(REG_UA>>6, offset);
+
+ UINT16 res = src + ((op & 2) ? -READ_REG(arg) : +READ_REG(arg)) ;
+
+ if ((op & 4))
+ mem_writebyte(REG_UA>>6, offset, res & 0xff);
+
+ CLEAR_FLAGS;
+ CHECK_FLAG_Z(res & 0xff);
+ CHECK_FLAGB_UZ_LZ(res);
+ CHECK_FLAG_C(res, 0xff);
+
+ m_icount -= 9;
+ }
+ break;
+
+ case 0x80: //adcw
+ case 0x81: //sbcw
+ case 0x88: //adw
+ case 0x89: //sbw
+ {
+ UINT8 arg = read_op();
+ UINT8 src = get_sir_im8(arg);
+ UINT32 res = REG_GET16(arg) + ((op & 0x01) ? -REG_GET16(src) : +REG_GET16(src));
+
+ if (op & 0x08) REG_PUT16(arg, res&0xffff);
+
+ CLEAR_FLAGS;
+ CHECK_FLAG_Z(res & 0xffff);
+ CHECK_FLAGW_UZ_LZ(res);
+ CHECK_FLAG_C(res, 0xffff);
+
+ check_optional_jr(arg);
+ m_icount -= 8;
+ }
+ break;
+
+ case 0x82: //ldw
+ {
+ UINT8 arg = read_op();
+ UINT8 src = get_sir_im8(arg);
+
+ COPY_REG(arg, src);
+ COPY_REG(arg+1, src+1);
+
+ check_optional_jr(arg);
+ m_icount -= 8;
+ }
+ break;
+
+ case 0x84: //ancw
+ case 0x85: //nacw
+ case 0x86: //orcw
+ case 0x87: //xrcw
+ case 0x8c: //anw
+ case 0x8d: //naw
+ case 0x8e: //orw
+ case 0x8f: //xrw
+ {
+ UINT8 arg = read_op();
+ UINT8 src = get_sir_im8(arg);
+
+ UINT8 res0 = make_logic(op, READ_REG(arg), READ_REG(src));
+ COND_WRITE_REG(op, arg, res0);
+
+ UINT8 res1 = make_logic(op, READ_REG(arg+1), READ_REG(src+1));
+ COND_WRITE_REG(op, arg+1, res1);
+
+ CLEAR_FLAGS;
+ CHECK_FLAG_Z(res0 || res1);
+ CHECK_FLAGB_UZ_LZ(res1);
+
+ //na(c) and or(c) always set C flag
+ if ((op&3) == 1 || (op&3) == 2)
+ SET_FLAG_C;
+
+ check_optional_jr(arg);
+ m_icount -= 8;
+ }
+ break;
+
+ case 0x8a: //adbw
+ case 0x8b: //sbbw
+ {
+ UINT8 arg = read_op();
+ UINT8 src = get_sir_im8(arg);
+ UINT16 res0, res1;
+
+ if (op & 0x01)
+ res0 = make_bcd_sub(READ_REG(arg), READ_REG(src));
+ else
+ res0 = make_bcd_add(READ_REG(arg), READ_REG(src));
+
+ WRITE_REG(arg, res0 & 0xff);
+
+ res1 = (res0>0xff) ? 1 : 0 ;
+
+ if (op & 0x01)
+ res1 = make_bcd_sub(READ_REG(arg+1), READ_REG(src+1) + res1);
+ else
+ res1 = make_bcd_add(READ_REG(arg+1), READ_REG(src+1) + res1);
+
+ WRITE_REG(arg+1, res1 & 0xff);
+
+ CLEAR_FLAGS;
+ CHECK_FLAG_Z(res0 || res1);
+ CHECK_FLAGB_UZ_LZ(res1);
+ CHECK_FLAG_C(res1, 0xff);
+
+ check_optional_jr(arg);
+ m_icount -= 8;
+ }
+ break;
+
+ case 0x90: //stw
+ {
+ UINT8 arg = read_op();
+ UINT8 src = get_sir_im8(arg);
+ UINT16 offset = REG_GET16(src);
+
+ mem_writebyte(REG_UA>>4, offset+0, READ_REG(arg+0));
+ mem_writebyte(REG_UA>>4, offset+1, READ_REG(arg+1));
+
+ check_optional_jr(arg);
+ m_icount -= 11;
+ }
+ break;
+
+ case 0x91: //ldw
+ {
+ UINT8 arg = read_op();
+ UINT8 src = get_sir_im8(arg);
+ UINT16 offset = REG_GET16(src);
+
+ WRITE_REG(arg+0, mem_readbyte(REG_UA>>4, offset+0));
+ WRITE_REG(arg+1, mem_readbyte(REG_UA>>4, offset+1));
+
+ check_optional_jr(arg);
+ m_icount -= 11;
+ }
+ break;
+
+ case 0x92: //stlw
+ {
+ UINT8 arg = read_op();
+
+ if (m_lcd_data_w)
+ {
+ (*m_lcd_data_w)(*this, READ_REG(arg));
+ (*m_lcd_data_w)(*this, READ_REG(arg+1));
+ }
+
+ check_optional_jr(arg);
+ m_icount -= 19;
+ }
+ break;
+
+ case 0x93: //ldcw
+ {
+ UINT8 arg = read_op();
+ UINT8 reg0, reg1;
+
+ if (m_lcd_data_r)
+ {
+ reg0 = (*m_lcd_data_r)(*this);
+ reg1 = (*m_lcd_data_r)(*this);
+ }
+ else
+ reg0 = reg1 = 0xff;
+
+ WRITE_REG(arg+0, reg0);
+ WRITE_REG(arg+1, reg1);
+
+ check_optional_jr(arg);
+ m_icount -= 19;
+ }
+ break;
+
+ case 0x96: //pre
+ case 0x97: //pre
+ {
+ UINT8 arg = read_op();
+ UINT8 idx = GET_REG_IDX(op, arg);
+
+ if (idx < 5)
+ m_reg16bit[idx] = REG_GET16(arg);
+
+ check_optional_jr(arg);
+ m_icount -= 8;
+ }
+ break;
+
+ case 0x98: //rodw
+ {
+ UINT8 arg = read_op();
+ UINT8 op1 = (arg>>5) & 0x03;
+ switch (op1)
+ {
+ case 0x00: //rodw
+ case 0x02: //bidw
+ {
+ UINT16 src = REG_GET16(arg-1);
+ UINT16 res = (src>>1)&0x7fff;
+
+ if (!(op1&0x02))
+ res = res | ((m_flags&FLAG_C) !=0 )<<15;
+
+ REG_PUT16(arg-1, res);
+
+ CLEAR_FLAGS;
+ CHECK_FLAG_Z(res & 0xffff);
+ CHECK_FLAGB_UZ_LZ(res);
+ if (src&0x01) SET_FLAG_C;
+ }
+ break;
+
+ case 0x01: //rouw
+ case 0x03: //biuw
+ {
+ UINT16 src = REG_GET16(arg);
+ UINT16 res = (src<<1)&0xfffe;
+
+ if (!(op1&0x02))
+ res = res | ((m_flags&FLAG_C) !=0 )<<0;
+
+ REG_PUT16(arg, res);
+
+ CLEAR_FLAGS;
+ CHECK_FLAG_Z(res & 0xffff);
+ CHECK_FLAGW_UZ_LZ(res);
+ if (src&0x8000) SET_FLAG_C;
+ }
+ break;
+ }
+
+ check_optional_jr(arg);
+ m_icount -= 11;
+ }
+ break;
+
+ case 0x9a:
+ {
+ UINT8 arg = read_op();
+ UINT8 op1 = (arg>>5) & 0x03;
+ switch (op1)
+ {
+ case 0x00: //didw
+ {
+ UINT16 src = (REG_GET16(arg-1)>>4)&0x0fff;
+ REG_PUT16(arg-1, src);
+
+ CLEAR_FLAGS;
+ CHECK_FLAG_Z(src & 0xffff);
+ CHECK_FLAGB_UZ_LZ(src);
+ }
+ break;
+
+ case 0x01: //diuw
+ {
+ UINT16 src = (REG_GET16(arg)<<4)&0xfff0;
+ REG_PUT16(arg, src);
+
+ CLEAR_FLAGS;
+ CHECK_FLAG_Z(src & 0xffff);
+ CHECK_FLAGW_UZ_LZ(src);
+ }
+ break;
+
+ case 0x02: //bydw
+ {
+ UINT8 src = READ_REG(arg);
+
+ WRITE_REG(arg, 0);
+ WRITE_REG(arg-1, src);
+
+ CLEAR_FLAGS;
+ CHECK_FLAG_Z(src & 0xff);
+ CHECK_FLAGB_UZ_LZ(src);
+ }
+ break;
+
+ case 0x03: //byuw
+ {
+ UINT8 src = READ_REG(arg);
+
+ WRITE_REG(arg, 0);
+ WRITE_REG(arg+1, src);
+
+ CLEAR_FLAGS;
+ CHECK_FLAG_Z(src & 0xff);
+ CHECK_FLAGB_UZ_LZ(src);
+ }
+ break;
+ }
+
+ check_optional_jr(arg);
+ m_icount -= 11;
+ }
+ break;
+
+ case 0x9b: //cmpw/invw
+ {
+ UINT8 arg = read_op();
+ UINT16 res = ~(REG_GET16(arg));
+ if (!(arg & 0x40)) res++;
+
+ REG_PUT16(arg, res);
+
+ CLEAR_FLAGS;
+ CHECK_FLAG_Z(res & 0xffff);
+ CHECK_FLAGW_UZ_LZ(res);
+
+ if (res || (arg & 0x40)) SET_FLAG_C;
+
+ check_optional_jr(arg);
+ m_icount -= 8;
+ }
+ break;
+
+ case 0x9c: //gpow/gflw
+ {
+ UINT8 arg = read_op();
+ UINT8 reg0, reg1;
+
+ if (arg&0x40)
+ {
+ reg0 = reg1 = m_flags;
+ }
+ else
+ {
+ if (m_port_r)
+ {
+ reg0 = (*m_port_r)(*this);
+ reg1 = (*m_port_r)(*this);
+ }
+ else
+ reg0 = reg1 = 0xff;
+
+ reg0&=(~REG_PE);
+ reg1&=(~REG_PE);
+
+ }
+
+ WRITE_REG(arg+0, reg0);
+ WRITE_REG(arg+1, reg1);
+
+ check_optional_jr(arg);
+ m_icount -= 8;
+ }
+ break;
+
+ case 0x9e: //gre
+ case 0x9f: //gre
+ {
+ UINT8 arg = read_op();
+ UINT8 idx = GET_REG_IDX(op, arg);
+ UINT16 src;
+
+ if (idx >= 5)
+ {
+ UINT16 port = 0xff;
+
+ if (m_kb_r)
+ port = (*m_kb_r)(*this);
+
+ src = (REG_KY & 0x0f00) | (port & 0xf0ff);
+ }
+ else
+ src = m_reg16bit[idx];
+
+ REG_PUT16(arg, src);
+
+ check_optional_jr(arg);
+ m_icount -= 8;
+ }
+ break;
+
+ case 0xa0: //stw
+ case 0xa2: //stiw
+ {
+ UINT8 arg = read_op();
+ UINT16 prev_ir = REG_IX;
+ UINT8 ir_inc = READ_REG(get_sir_im8(arg));
+
+ REG_IX += ((arg & 0x80) ? -ir_inc : +ir_inc);
+
+ mem_writebyte(REG_UA>>4, REG_IX++, READ_REG(arg+0));
+ mem_writebyte(REG_UA>>4, REG_IX++, READ_REG(arg+1));
+
+ RESTORE_REG(op, REG_IX, prev_ir);
+ m_icount -= 11;
+ }
+ break;
+
+ case 0xa1: //stw
+ case 0xa3: //stiw
+ {
+ UINT8 arg = read_op();
+ UINT16 prev_ir = REG_IZ;
+ UINT8 ir_inc = READ_REG(get_sir_im8(arg));
+
+ REG_IZ += ((arg & 0x80) ? -ir_inc : +ir_inc);
+
+ mem_writebyte(REG_UA>>6, REG_IZ++, READ_REG(arg+0));
+ mem_writebyte(REG_UA>>6, REG_IZ++, READ_REG(arg+1));
+
+ RESTORE_REG(op, REG_IZ, prev_ir);
+ m_icount -= 11;
+ }
+ break;
+
+ case 0xa4: //stdw
+ {
+ UINT8 arg = read_op();
+ UINT8 ir_inc = READ_REG(get_sir_im8(arg));
+
+ REG_IX += ((arg & 0x80) ? -ir_inc : +ir_inc);
+
+ mem_writebyte(REG_UA>>4, REG_IX--, READ_REG(arg-0));
+ mem_writebyte(REG_UA>>4, REG_IX, READ_REG(arg-1));
+
+ m_icount -= 9;
+ }
+ break;
+ case 0xa5: //stdw
+ {
+ UINT8 arg = read_op();
+ UINT8 ir_inc = READ_REG(get_sir_im8(arg));
+
+ REG_IZ += ((arg & 0x80) ? -ir_inc : +ir_inc);
+
+ mem_writebyte(REG_UA>>6, REG_IZ--, READ_REG(arg-0));
+ mem_writebyte(REG_UA>>6, REG_IZ, READ_REG(arg-1));
+
+ m_icount -= 9;
+ }
+ break;
+
+ case 0xa6: //phsw
+ {
+ UINT8 arg = read_op();
+ push(REG_SS, READ_REG(arg));
+ push(REG_SS, READ_REG(arg-1));
+
+ m_icount -= 12;
+ }
+ break;
+ case 0xa7: //phuw
+ {
+ UINT8 arg = read_op();
+ push(REG_US, READ_REG(arg));
+ push(REG_US, READ_REG(arg-1));
+
+ m_icount -= 12;
+ }
+ break;
+
+ case 0xa8: //ldw
+ case 0xaa: //ldiw
+ {
+ UINT8 arg = read_op();
+ UINT16 prev_ir = REG_IX;
+ UINT8 ir_inc = READ_REG(get_sir_im8(arg));
+
+ REG_IX += ((arg & 0x80) ? -ir_inc : +ir_inc);
+
+ WRITE_REG(arg+0, mem_readbyte(REG_UA>>4, REG_IX++));
+ WRITE_REG(arg+1, mem_readbyte(REG_UA>>4, REG_IX++));
+
+ RESTORE_REG(op, REG_IX, prev_ir);
+
+ m_icount -= 11;
+ }
+ break;
+
+ case 0xa9: //ldw
+ case 0xab: //ldiw
+ {
+ UINT8 arg = read_op();
+ UINT16 prev_ir = REG_IZ;
+ UINT8 ir_inc = READ_REG(get_sir_im8(arg));
+
+ REG_IZ += ((arg & 0x80) ? -ir_inc : +ir_inc);
+
+ WRITE_REG(arg+0, mem_readbyte(REG_UA>>6, REG_IZ++));
+ WRITE_REG(arg+1, mem_readbyte(REG_UA>>6, REG_IZ++));
+
+ RESTORE_REG(op, REG_IZ, prev_ir);
+
+ m_icount -= 11;
+ }
+ break;
+
+ case 0xac: //lddw
+ {
+ UINT8 arg = read_op();
+ UINT8 ir_inc = READ_REG(get_sir_im8(arg));
+
+ REG_IX += ((arg & 0x80) ? -ir_inc : +ir_inc);
+
+ WRITE_REG(arg-0, mem_readbyte(REG_UA>>4, REG_IX--));
+ WRITE_REG(arg-1, mem_readbyte(REG_UA>>4, REG_IX));
+
+ m_icount -= 9;
+ }
+ break;
+
+ case 0xad: //lddw
+ {
+ UINT8 arg = read_op();
+ UINT8 ir_inc = READ_REG(get_sir_im8(arg));
+
+ REG_IZ += ((arg & 0x80) ? -ir_inc : +ir_inc);
+
+ WRITE_REG(arg-0, mem_readbyte(REG_UA>>6, REG_IZ--));
+ WRITE_REG(arg-1, mem_readbyte(REG_UA>>6, REG_IZ));
+
+ m_icount -= 9;
+ }
+ break;
+
+ case 0xae: //ppsw
+ case 0xaf: //ppuw
+ {
+ UINT8 arg = read_op();
+
+ WRITE_REG(arg, pop((op&1) ? REG_US : REG_SS));
+ WRITE_REG(arg+1, pop((op&1) ? REG_US : REG_SS));
+
+ m_icount -= 14;
+ }
+ break;
+
+ case 0xb0: //jr z
+ case 0xb1: //jr nc
+ case 0xb2: //jr lz
+ case 0xb3: //jr uz
+ case 0xb4: //jr nz
+ case 0xb5: //jr c
+ case 0xb6: //jr nlz
+ case 0xb7: //unconditional jr
+ {
+ UINT8 arg = read_op();
+ UINT32 new_pc = m_pc-1 + get_im_7(arg);
+
+ if (check_cond(op))
+ set_pc(new_pc);
+ m_icount -= 3;
+ }
+ break;
+
+ case 0xb8: //adcw
+ case 0xbc: //adw
+ {
+ UINT8 arg = read_op();
+ UINT8 ir_inc = READ_REG(get_sir_im8(arg));
+
+ UINT16 offset = REG_IX + ((arg & 0x80) ? -ir_inc : +ir_inc);
+
+ UINT16 src0 = mem_readbyte(REG_UA>>4, offset) + READ_REG(arg);
+ UINT16 src1 = mem_readbyte(REG_UA>>4, offset+1) + READ_REG(arg+1) + ((src0>0xff) ? 1 : 0);
+
+ if (op&0x04)
+ {
+ mem_writebyte(REG_UA>>4, offset+0, src0 & 0xff);
+ mem_writebyte(REG_UA>>4, offset+1, src1 & 0xff);
+ }
+
+ CLEAR_FLAGS;
+ CHECK_FLAGB_UZ_LZ(src1);
+ CHECK_FLAG_Z(src0 || src1);
+ CHECK_FLAG_C(src1, 0xff);
+
+ m_icount -= 15;
+ }
+ break;
+
+ case 0xba: //sbcw
+ case 0xbe: //sbw
+ {
+ UINT8 arg = read_op();
+ UINT8 ir_inc = READ_REG(get_sir_im8(arg));
+
+ UINT16 offset = REG_IX + ((arg & 0x80) ? -ir_inc : +ir_inc);
+
+ UINT16 src0 = mem_readbyte(REG_UA>>4, offset) - READ_REG(arg);
+ UINT16 src1 = mem_readbyte(REG_UA>>4, offset+1) - READ_REG(arg+1) - ((src0>0xff) ? 1 : 0);
+
+ if (op&0x04)
+ {
+ mem_writebyte(REG_UA>>4, offset+0, src0 & 0xff);
+ mem_writebyte(REG_UA>>4, offset+1, src1 & 0xff);
+ }
+
+ CLEAR_FLAGS;
+ CHECK_FLAGB_UZ_LZ(src1);
+ CHECK_FLAG_Z(src0 || src1);
+ CHECK_FLAG_C(src1, 0xff);
+
+ m_icount -= 15;
+ }
+ break;
+
+ case 0xb9: //adcw
+ case 0xbd: //adw
+ {
+ UINT8 arg = read_op();
+ UINT8 ir_inc = READ_REG(get_sir_im8(arg));
+
+ UINT16 offset = REG_IZ + ((arg & 0x80) ? -ir_inc : +ir_inc);
+
+ UINT16 src0 = mem_readbyte(REG_UA>>6, offset) + READ_REG(arg);
+ UINT16 src1 = mem_readbyte(REG_UA>>6, offset+1) + READ_REG(arg+1) + ((src0>0xff) ? 1 : 0);
+
+ if (op&0x04)
+ {
+ mem_writebyte(REG_UA>>6, offset+0, src0 & 0xff);
+ mem_writebyte(REG_UA>>6, offset+1, src1 & 0xff);
+ }
+
+ CLEAR_FLAGS;
+ CHECK_FLAGB_UZ_LZ(src1);
+ CHECK_FLAG_Z(src0 || src1);
+ CHECK_FLAG_C(src1, 0xff);
+
+ m_icount -= 15;
+ }
+ break;
+
+ case 0xbb: //sbcw
+ case 0xbf: //sbw
+ {
+ UINT8 arg = read_op();
+ UINT8 ir_inc = READ_REG(get_sir_im8(arg));
+
+ UINT16 offset = REG_IZ + ((arg & 0x80) ? -ir_inc : +ir_inc);
+
+ UINT16 src0 = mem_readbyte(REG_UA>>6, offset) - READ_REG(arg);
+ UINT16 src1 = mem_readbyte(REG_UA>>6, offset+1) - READ_REG(arg+1) - ((src0>0xff) ? 1 : 0);
+
+ if (op&0x04)
+ {
+ mem_writebyte(REG_UA>>6, offset+0, src0 & 0xff);
+ mem_writebyte(REG_UA>>6, offset+1, src1 & 0xff);
+ }
+
+ CLEAR_FLAGS;
+ CHECK_FLAGB_UZ_LZ(src1);
+ CHECK_FLAG_Z(src0 || src1);
+ CHECK_FLAG_C(src1, 0xff);
+
+ m_icount -= 15;
+ }
+ break;
+
+ case 0xc0: //adbcm
+ case 0xc1: //sbbcm
+ case 0xc8: //adbm
+ case 0xc9: //sbbm
+ {
+ UINT8 arg = read_op();
+ UINT8 arg1 = read_op();
+ UINT8 dst = arg;
+ UINT8 src = get_sir_im8(arg, arg1);
+ UINT8 c, f;
+ UINT16 res = 0;
+
+ c = f = 0;
+ for (int n=GET_IM3(arg1); n>0; n--)
+ {
+ if (op & 0x01)
+ res = make_bcd_sub(READ_REG(dst), READ_REG(src) + c);
+ else
+ res = make_bcd_add(READ_REG(dst), READ_REG(src) + c);
+
+ c = (res > 0xff) ? 1 : 0;
+
+ COND_WRITE_REG(op, dst, res&0xff);
+
+ f |= (res&0xff);
+ dst++; src++;
+
+ m_icount -= 5;
+ }
+
+ CLEAR_FLAGS;
+ CHECK_FLAG_Z(f);
+ CHECK_FLAGB_UZ_LZ(res);
+ CHECK_FLAG_C(res, 0xff);
+
+ check_optional_jr(arg);
+ m_icount -= 2;
+ }
+ break;
+
+ case 0xc2: //ldm
+ {
+ UINT8 arg = read_op();
+ UINT8 arg1 = read_op();
+ UINT8 dst = arg;
+ UINT8 src = get_sir_im8(arg, arg1);
+
+ for (int n=GET_IM3(arg1); n>0; n--)
+ {
+ COPY_REG(dst++, src++);
+ m_icount -= 5;
+ }
+
+ check_optional_jr(arg);
+ m_icount -= 2;
+ }
+ break;
+
+ case 0xc4: //ancm
+ case 0xc5: //nacm
+ case 0xc6: //orcm
+ case 0xc7: //xrcm
+ case 0xcc: //anm
+ case 0xcd: //nam
+ case 0xce: //orm
+ case 0xcf: //xrm
+ {
+ UINT8 arg = read_op();
+ UINT8 arg1 = read_op();
+ UINT8 dst = arg;
+ UINT8 src = get_sir_im8(arg, arg1);
+ UINT8 res = 0, f = 0;
+
+ for (int n=GET_IM3(arg1); n>0; n--)
+ {
+ res = make_logic(op, READ_REG(dst), READ_REG(src));
+
+ COND_WRITE_REG(op, dst, res);
+
+ f |= res;
+
+ dst++; src++;
+
+ m_icount -= 3;
+ }
+
+ CLEAR_FLAGS;
+ CHECK_FLAG_Z(f);
+ CHECK_FLAGB_UZ_LZ(res);
+
+ //na(c) and or(c) always set C flag
+ if ((op&3) == 1 || (op&3) == 2)
+ SET_FLAG_C;
+
+ check_optional_jr(arg);
+ }
+ break;
+
+ case 0xca: //adbm
+ case 0xcb: //sbbm
+ {
+ UINT8 arg = read_op();
+ UINT8 arg1 = read_op();
+ UINT8 dst = arg;
+ UINT16 res = 0;
+ UINT8 src, f;
+ src = arg1 & 0x1f;
+ f = 0;
+
+ for (int n=GET_IM3(arg1); n>0; n--)
+ {
+ if (op & 0x01)
+ res = make_bcd_sub(READ_REG(dst), src);
+ else
+ res = make_bcd_add(READ_REG(dst), src);
+
+ src = (res > 0xff) ? 1 : 0;
+
+ COND_WRITE_REG(op, dst, res&0xff);
+
+ f |= (res&0xff);
+ dst++;
+
+ m_icount -= 5;
+ }
+
+ CLEAR_FLAGS;
+ CHECK_FLAG_Z(f);
+ CHECK_FLAGB_UZ_LZ(res);
+ CHECK_FLAG_C(res, 0xff);
+
+ check_optional_jr(arg);
+ m_icount -= 2;
+ }
+ break;
+
+ case 0xd0: //stw
+ {
+ UINT8 arg = read_op();
+ UINT16 offset = REG_GET16(READ_SREG(arg));
+
+ mem_writebyte(REG_UA>>4, offset+0, read_op());
+ mem_writebyte(REG_UA>>4, offset+1, read_op());
+
+ m_icount -= 11;
+ }
+ break;
+
+ case 0xd1: //ldw
+ {
+ UINT8 arg = read_op();
+ UINT8 reg0 = read_op();
+ UINT8 reg1 = read_op();
+
+ WRITE_REG(arg+0, reg0);
+ WRITE_REG(arg+1, reg1);
+ m_icount -= 11;
+ }
+ break;
+
+ case 0xd2: //stlm
+ {
+ UINT8 arg = read_op();
+ UINT8 arg1 = read_op();
+
+ for (int n=GET_IM3(arg1); n>0; n--)
+ {
+ if (m_lcd_data_w)
+ (*m_lcd_data_w)(*this, READ_REG(arg));
+
+ arg++;
+ m_icount -= 8;
+ }
+
+ m_icount -= 3;
+ }
+ break;
+
+ case 0xd3: //ldlm
+ {
+ UINT8 arg = read_op();
+ UINT8 arg1 = read_op();
+ UINT8 src;
+
+ for (int n=GET_IM3(arg1); n>0; n--)
+ {
+ if (m_lcd_data_r)
+ src = (*m_lcd_data_r)(*this);
+ else
+ src = 0xff;
+
+ WRITE_REG(arg, src++);
+
+ m_icount -= 8;
+ }
+
+ m_icount -= 3;
+ }
+ break;
+
+ case 0xd6: //pre
+ case 0xd7: //pre
+ {
+ UINT8 arg = read_op();
+ UINT8 lsb = read_op();
+ UINT8 msb = read_op();
+ UINT8 idx = GET_REG_IDX(op, arg);
+
+ if (idx < 5)
+ m_reg16bit[idx] = (msb<<8) | lsb;
+
+ m_icount -= 8;
+ }
+ break;
+
+ case 0xd8: //bup
+ case 0xd9: //bdn
+ {
+ UINT8 src;
+ for(;;)
+ {
+ src = mem_readbyte(REG_UA>>4, REG_IX);
+ mem_writebyte(REG_UA>>6, REG_IZ, src);
+
+ if (REG_IX == REG_IY)
+ break;
+
+ REG_IX += ((op&1) ? -1 : +1);
+ REG_IZ += ((op&1) ? -1 : +1);
+ m_icount -= 6;
+ }
+
+ m_icount -= 9;
+ }
+ break;
+
+ case 0xda:
+ {
+ UINT8 arg = read_op();
+ UINT8 op1 = (arg>>5) & 0x03;
+ switch (op1)
+ {
+ case 0x00: //didm
+ {
+ UINT8 arg1 = read_op();
+ UINT8 r1 = 0, r2 = 0;
+
+ for (int n=GET_IM3(arg1); n>0; n--)
+ {
+ r2 = r1;
+ r1 = READ_REG(arg);
+ r2 = ((r1>>4)&0x0f) | ((r2<<4)&0xf0);
+ WRITE_REG(arg--, r2);
+ m_icount -= 5;
+ }
+
+ CLEAR_FLAGS;
+ CHECK_FLAGB_UZ_LZ(r2);
+ CHECK_FLAG_Z(r2);
+ }
+ break;
+
+ case 0x01: //dium
+ {
+ UINT8 arg1 = read_op();
+ UINT8 r1 = 0, r2 = 0;
+
+ for (int n=GET_IM3(arg1); n>0; n--)
+ {
+ r2 = r1;
+ r1 = READ_REG(arg);
+ r2 = ((r1<<4)&0xf0) | ((r2>>4)&0x0f);
+ WRITE_REG(arg++, r2);
+ m_icount -= 5;
+ }
+
+ CLEAR_FLAGS;
+ CHECK_FLAGB_UZ_LZ(r2);
+ CHECK_FLAG_Z(r2);
+ }
+ break;
+
+ case 0x02: //bydm
+ {
+ UINT8 arg1 = read_op();
+ UINT8 r1 = 0, r2 = 0, f = 0;
+
+ for (int n=GET_IM3(arg1); n>0; n--)
+ {
+ r2 = r1;
+ r1 = READ_REG(arg);
+ WRITE_REG(arg--, r2);
+ f |= r2;
+ m_icount -= 5;
+ }
+
+ CLEAR_FLAGS;
+ CHECK_FLAGB_UZ_LZ(r2);
+ CHECK_FLAG_Z(f);
+ }
+ break;
+
+ case 0x03: //byum
+ {
+ UINT8 arg1 = read_op();
+ UINT8 r1 = 0, r2 = 0, f = 0;
+
+ for (int n=GET_IM3(arg1); n>0; n--)
+ {
+ r2 = r1;
+ r1 = READ_REG(arg);
+ WRITE_REG(arg++, r2);
+ f |= r2;
+ m_icount -= 5;
+ }
+
+ CLEAR_FLAGS;
+ CHECK_FLAGB_UZ_LZ(r2);
+ CHECK_FLAG_Z(f);
+ }
+ break;
+ }
+ }
+ break;
+
+ case 0xdb: //cmpm/invm
+ {
+ UINT8 arg = read_op();
+ UINT8 arg1 = read_op();
+ UINT8 r1 = 0, r2 = 0, f = 0;
+
+ r2 = (arg&0x40) ? 0 : 1;
+
+ for (int n=GET_IM3(arg1); n>0; n--)
+ {
+ r1 = r2 + (~READ_REG(arg));
+ WRITE_REG(arg++, r1);
+ if (r1) r2 = 0;
+
+ f |= r1;
+
+ m_icount -= 5;
+ }
+
+ CLEAR_FLAGS;
+ CHECK_FLAG_Z(f);
+ CHECK_FLAGB_UZ_LZ(r1);
+ if (f != 0 || (arg & 0x40))
+ SET_FLAG_C;
+ }
+ break;
+
+ case 0xdc: //sup
+ case 0xdd: //sdn
+ {
+ UINT8 arg = read_op();
+ UINT16 res;
+
+ for(;;)
+ {
+ res = mem_readbyte(REG_UA>>4, REG_IX) - READ_REG(arg);
+
+ if (REG_IX == REG_IY || !res)
+ break;
+
+ REG_IX += ((op&1) ? -1 : +1);
+ m_icount -= 6;
+ }
+
+ CLEAR_FLAGS;
+ CHECK_FLAG_Z(res & 0xff);
+ CHECK_FLAGB_UZ_LZ(res);
+ CHECK_FLAG_C(res, 0xff);
+
+ m_icount -= 9;
+ }
+ break;
+
+ case 0xde: //jp
+ {
+ UINT8 arg = read_op();
+ set_pc(REG_GET16(arg));
+
+ m_icount -= 5;
+ }
+ break;
+
+ case 0xdf: //jp
+ {
+ UINT8 arg = read_op();
+ UINT16 offset = REG_GET16(arg);
+ UINT8 lsb = mem_readbyte(REG_UA>>4, offset+0);
+ UINT8 msb = mem_readbyte(REG_UA>>4, offset+1);
+
+ set_pc((msb<<8) | lsb);
+
+ m_icount -= 5;
+ }
+ break;
+
+ case 0xe0: //stm
+ case 0xe2: //stim
+ {
+ UINT8 arg = read_op();
+ UINT8 arg1 = read_op();
+ UINT16 prev_ir = REG_IX;
+ UINT8 ir_inc = READ_REG(get_sir_im8(arg, arg1));
+
+ REG_IX += ((arg & 0x80) ? -ir_inc : +ir_inc);
+
+ for (int n=GET_IM3(arg1); n>0; n--)
+ {
+ mem_writebyte(REG_UA>>4, REG_IX++, READ_REG(arg++));
+ m_icount -= 3;
+ }
+
+ RESTORE_REG(op, REG_IX, prev_ir);
+
+ m_icount -= 5;
+ }
+ break;
+
+ case 0xe1: //stm
+ case 0xe3: //stim
+ {
+ UINT8 arg = read_op();
+ UINT8 arg1 = read_op();
+ UINT16 prev_ir = REG_IZ;
+ UINT8 ir_inc = READ_REG(get_sir_im8(arg, arg1));
+
+ REG_IZ += ((arg & 0x80) ? -ir_inc : +ir_inc);
+
+ for (int n=GET_IM3(arg1); n>0; n--)
+ {
+ mem_writebyte(REG_UA>>6, REG_IZ++, READ_REG(arg++));
+ m_icount -= 3;
+ }
+
+ RESTORE_REG(op, REG_IZ, prev_ir);
+
+ m_icount -= 5;
+ }
+ break;
+
+ case 0xe4: //stdm
+ {
+ UINT8 arg = read_op();
+ UINT8 arg1 = read_op();
+ UINT8 ir_inc = READ_REG(get_sir_im8(arg, arg1));
+
+ REG_IX += ((arg & 0x80) ? -ir_inc : +ir_inc);
+
+ for (int n=GET_IM3(arg1); n>0; n--)
+ {
+ mem_writebyte(REG_UA>>4, REG_IX--, READ_REG(arg--));
+ m_icount -= 3;
+ }
+
+ REG_IX++;//todo
+
+ m_icount -= 3;
+ }
+ break;
+
+ case 0xe5: //stdm
+ {
+ UINT8 arg = read_op();
+ UINT8 arg1 = read_op();
+ UINT8 ir_inc = READ_REG(get_sir_im8(arg, arg1));
+
+ REG_IZ += ((arg & 0x80) ? -ir_inc : +ir_inc);
+
+ for (int n=GET_IM3(arg1); n>0; n--)
+ {
+ mem_writebyte(REG_UA>>6, REG_IZ--, READ_REG(arg--));
+ m_icount -= 3;
+ }
+
+ REG_IZ++;
+
+ m_icount -= 3;
+ }
+ break;
+
+ case 0xe6: //phsm
+ case 0xe7: //phum
+ {
+ UINT8 arg = read_op();
+ UINT8 arg1 = read_op();
+
+ for (int n=GET_IM3(arg1); n>0; n--)
+ {
+ push((op&1) ? REG_US : REG_SS, READ_REG(arg--));
+
+ m_icount -= 3;
+ }
+
+ m_icount -= 3;
+ }
+ break;
+
+ case 0xe8: //ldm
+ case 0xea: //ldim
+ {
+ UINT8 arg = read_op();
+ UINT8 arg1 = read_op();
+ UINT16 prev_ir = REG_IX;
+ UINT8 ir_inc = READ_REG(get_sir_im8(arg, arg1));
+
+ REG_IX += ((arg & 0x80) ? -ir_inc : +ir_inc);
+
+ for (int n=GET_IM3(arg1); n>0; n--)
+ {
+ WRITE_REG(arg++, mem_readbyte(REG_UA>>4, REG_IX++));
+ m_icount -= 3;
+ }
+
+ RESTORE_REG(op, REG_IX, prev_ir);
+
+ m_icount -= 5;
+ }
+ break;
+
+ case 0xe9: //ldm
+ case 0xeb: //ldim
+ {
+ UINT8 arg = read_op();
+ UINT8 arg1 = read_op();
+ UINT16 prev_ir = REG_IZ;
+ UINT8 ir_inc = READ_REG(get_sir_im8(arg, arg1));
+
+ REG_IZ += ((arg & 0x80) ? -ir_inc : +ir_inc);
+
+ for (int n=GET_IM3(arg1); n>0; n--)
+ {
+ WRITE_REG(arg++, mem_readbyte(REG_UA>>6, REG_IZ++));
+ m_icount -= 3;
+ }
+
+ RESTORE_REG(op, REG_IZ, prev_ir);
+
+ m_icount -= 5;
+ }
+ break;
+
+ case 0xec: //lddm
+ {
+ UINT8 arg = read_op();
+ UINT8 arg1 = read_op();
+ UINT8 ir_inc = READ_REG(get_sir_im8(arg, arg1));
+
+ REG_IX += ((arg & 0x80) ? -ir_inc : +ir_inc);
+
+ for (int n=GET_IM3(arg1); n>0; n--)
+ {
+ WRITE_REG(arg--, mem_readbyte(REG_UA>>4, REG_IX--));
+ m_icount -= 3;
+ }
+
+ REG_IX++;
+
+ m_icount -= 3;
+ }
+ break;
+
+ case 0xed: //lddm
+ {
+ UINT8 arg = read_op();
+ UINT8 arg1 = read_op();
+ UINT8 ir_inc = READ_REG(get_sir_im8(arg, arg1));
+
+ REG_IZ += ((arg & 0x80) ? -ir_inc : +ir_inc);
+
+ for (int n=GET_IM3(arg1); n>0; n--)
+ {
+ WRITE_REG(arg--, mem_readbyte(REG_UA>>6, REG_IZ--));
+ m_icount -= 3;
+ }
+
+ REG_IZ++;
+
+ m_icount -= 3;
+ }
+ break;
+
+ case 0xee: //ppsm
+ case 0xef: //ppum
+ {
+ UINT8 arg = read_op();
+ UINT8 arg1 = read_op();
+
+ for (int n=GET_IM3(arg1); n>0; n--)
+ {
+ WRITE_REG(arg++, pop((op&1) ? REG_US : REG_SS));
+ m_icount -= 3;
+ }
+
+ m_icount -= 5;
+ }
+ break;
+
+ case 0xf0: //rtn z
+ case 0xf1: //rtn nc
+ case 0xf2: //rtn lz
+ case 0xf3: //rtn uz
+ case 0xf4: //rtn nz
+ case 0xf5: //rtn c
+ case 0xf6: //rtn nlz
+ case 0xf7: //unconditional rtn
+ {
+ if (check_cond(op))
+ {
+ UINT8 lsb = pop(REG_SS) ;
+ UINT8 msb = pop(REG_SS);
+
+ set_pc((((msb<<8) | (lsb<<0)) + 1));
+ }
+ m_icount -= 3;
+ }
+ break;
+
+ case 0xf8: //nop
+ m_icount -= 3;
+ break;
+
+ case 0xf9: //clt
+ REG_TM = 0;
+ m_icount -= 3;
+ break;
+
+ case 0xfa: //fst
+ m_state |= CPU_FAST;
+ m_icount -= 3;
+ break;
+
+ case 0xfb: //slw
+ m_state &= ~CPU_FAST;
+ m_icount -= 3;
+ break;
+
+ case 0xfd: //rtni
+ {
+ UINT8 lsb = pop(REG_SS);
+ UINT8 msb = pop(REG_SS);
+
+ set_pc((msb<<8) | (lsb<<0));
+
+ m_icount -= 5;
+ }
+ //fall through
+
+ case 0xfc: //cani
+ {
+ for (UINT8 arg=0x10; arg>0; arg>>=1)
+ {
+ if (REG_IB & arg)
+ {
+ REG_IB &= (~arg);
+ m_irq_status &= (~arg);
+ break;
+ }
+ }
+
+ m_icount -= 3;
+ }
+ break;
+
+ case 0xfe: //off
+ {
+ set_pc(0);
+ REG_UA = REG_IA = 0;
+ REG_IX = REG_IY = REG_IZ = 0;
+ REG_PE = 0;
+ REG_IE = (REG_IE&0x0c) | ((REG_IB>>1) & 0x10);
+ REG_IB &= 0xe3;
+ if (m_flags & FLAG_SW)
+ m_flags |= FLAG_APO;
+ else
+ m_flags &= ~FLAG_APO;
+
+ m_state |= CPU_SLP;
+
+ m_irq_status = 0;
+ if (m_lcd_control)
+ (*m_lcd_control)(*this, 0);
+
+ if (m_kb_w)
+ (*m_kb_w)(*this, 0);
+ m_icount -= 3;
+ }
+ break;
+
+ case 0xff: //trp
+ {
+ m_pc--;
+ push(REG_SS, (m_pc>>8)&0xff);
+ push(REG_SS, (m_pc>>0)&0xff);
+ set_pc(0x0022);
+ m_icount -= 9;
+ }
+ break;
+
+ case 0x03:
+ case 0x19:
+ case 0x43:
+ case 0x53:
+ case 0x5a:
+ case 0x5b:
+ case 0x5e:
+ case 0x5f:
+ case 0x66:
+ case 0x67:
+ case 0x6e:
+ case 0x6f:
+ case 0x83:
+ case 0x94:
+ case 0x95:
+ case 0x99:
+ case 0x9d:
+ case 0xc3:
+ case 0xd4:
+ case 0xd5:
+ logerror( "%06x: illegal instruction %02x encountered\n", m_pc, op );
+ break;
+
+ default:
+ logerror( "%06x: unimplemented instruction %02x encountered\n", m_pc, op );
+ break;
+ }
+ }
+
+ //if is in the internal ROM align the pc
+ if ((m_fetch_addr&1) && m_pc < INT_ROM)
+ set_pc((m_fetch_addr+1)>>1);
+
+ m_icount -= 3;
+ } while (m_icount > 0);
+}
+
+
+//-------------------------------------------------
+// execute_set_input
+//-------------------------------------------------
+
+void hd61700_cpu_device::execute_set_input(int inputnum, int state)
+{
+ switch (inputnum)
+ {
+ case INPUT_LINE_RESET:
+ REG_UA = 0;
+ REG_IA = 0;
+ REG_IX = 0;
+ REG_IY = 0;
+ REG_IZ = 0;
+ REG_PE = 0;
+ REG_IE = 0;
+ REG_IB = 0;
+ m_state &= ~(CPU_SLP | CPU_FAST);
+ set_pc(0x0000);
+ break;
+ case HD61700_KEY_INT: //level sensitive line
+ if (((REG_IE>>3) & (1<<inputnum)) && state != CLEAR_LINE)
+ REG_IB |= (1<<inputnum);
+ break;
+
+ case HD61700_INT1: //edge sensitive line
+ if (((REG_IE>>3) & (1<<inputnum)) && (m_lines_status[inputnum] != state))
+ REG_IB |= (1<<inputnum);
+
+ if (m_lines_status[inputnum] == CLEAR_LINE && state != CLEAR_LINE)
+ REG_IE = (REG_IE & 0xfd) | 0x02; //rising edge
+ else if (m_lines_status[inputnum] != CLEAR_LINE && state == CLEAR_LINE)
+ REG_IE = (REG_IE & 0xfd) | 0x00; //falling edge
+
+ REG_KY = (REG_KY & 0xf7ff) | ((state != CLEAR_LINE)<<11);
+ break;
+ case HD61700_INT2: //level sensitive line
+ if (((REG_IE>>3) & (1<<inputnum)) && state != CLEAR_LINE)
+ REG_IB |= (1<<inputnum);
+
+ REG_IE = (REG_IE & 0xfe) | (state != CLEAR_LINE);
+ REG_KY = (REG_KY & 0xfbff) | ((state != CLEAR_LINE)<<10);
+ break;
+ case HD61700_ON_INT: //level sensitive line
+ if ((REG_IE>>3) & (1<<inputnum) && state != CLEAR_LINE)
+ REG_IB |= (1<<inputnum);
+
+ REG_KY = (REG_KY & 0xfdff) | ((state != CLEAR_LINE)<<9);
+ break;
+
+ case HD61700_SW: //level sensitive line
+ if (state != CLEAR_LINE)
+ {
+ if ((m_state & CPU_SLP) || m_lines_status[HD61700_SW] == CLEAR_LINE)
+ {
+ m_state &= ~(CPU_SLP | CPU_FAST);
+ m_flags &= ~FLAG_APO;
+ set_pc(0x0001);
+ }
+ }
+
+ m_flags |= ((state != CLEAR_LINE)<<3);
+ break;
+ }
+
+ m_lines_status[inputnum] = state;
+}
+
+
+//**************************************************************************
+// INLINE HELPERS
+//**************************************************************************
+
+inline void hd61700_cpu_device::set_pc(INT32 new_pc)
+{
+ m_curpc = (m_curpc & 0x30000) | new_pc;
+ m_pc = new_pc & 0xffff;
+ m_fetch_addr = new_pc<<1;
+}
+
+inline UINT8 hd61700_cpu_device::read_op()
+{
+ UINT16 data = 0;
+ UINT32 addr18 = make_18bit_addr((m_irq_status) ? 0 : prev_ua, m_pc);
+
+ if (m_pc <= INT_ROM)
+ {
+ data = m_program->read_word(addr18<<1);
+
+ if (!(m_fetch_addr&1))
+ data = (data>>8) ;
+ }
+ else
+ {
+ if (m_fetch_addr&1)
+ data = m_program->read_word((addr18+1)<<1);
+ else
+ data = m_program->read_word((addr18+0)<<1);
+ }
+
+ m_fetch_addr += ((m_pc > INT_ROM) ? 2 : 1);
+
+ m_pc = m_fetch_addr>>1;
+
+ m_curpc = make_18bit_addr((m_irq_status) ? 0 : prev_ua, m_pc);
+
+ prev_ua = REG_UA;
+
+ return (data&0xff);
+}
+
+inline UINT8 hd61700_cpu_device::mem_readbyte(UINT8 segment, UINT16 offset)
+{
+ return m_program->read_word(make_18bit_addr(segment, offset)<<1) & 0xff;
+}
+
+inline void hd61700_cpu_device::mem_writebyte(UINT8 segment, UINT16 offset, UINT8 data)
+{
+ m_program->write_word(make_18bit_addr(segment, offset)<<1, data);
+}
+
+inline UINT32 hd61700_cpu_device::make_18bit_addr(UINT8 segment, UINT16 offset)
+{
+ if (offset >= ((REG_IB>>6) & 0x03) * 0x4000)
+ return (UINT32)((offset | ((segment&0x03)<<16)) & 0x3ffff);
+ else
+ return offset;
+}
+
+inline void hd61700_cpu_device::push(UINT16 &offset, UINT8 data)
+{
+ offset--;
+ mem_writebyte(REG_UA>>2, offset, data);
+}
+
+inline UINT8 hd61700_cpu_device::pop(UINT16 &offset)
+{
+ UINT8 data = mem_readbyte(REG_UA>>2, offset);
+ offset++;
+ return data;
+}
+
+inline int hd61700_cpu_device::check_cond(UINT32 op)
+{
+ switch ( op & 0x07 )
+ {
+ case 0x00: // Z set
+ if ( !(m_flags & FLAG_Z) )
+ return 1;
+ break;
+
+ case 0x01: // NC set
+ if ( !(m_flags & FLAG_C) )
+ return 1;
+ break;
+
+ case 0x02: // LZ set
+ if ( !(m_flags & FLAG_LZ) )
+ return 1;
+ break;
+
+ case 0x03: // UZ set
+ if ( !(m_flags & FLAG_UZ) )
+ return 1;
+ break;
+
+ case 0x04: // NZ set
+ if ( m_flags & FLAG_Z )
+ return 1;
+ break;
+
+ case 0x05: // C set
+ if ( m_flags & FLAG_C )
+ return 1;
+ break;
+
+ case 0x06: // NLZ clear
+ if ( m_flags & FLAG_LZ )
+ return 1;
+ break;
+
+ case 0x07: // unconditional
+ return 1;
+ break;
+ }
+
+ return 0;
+}
+
+inline UINT8 hd61700_cpu_device::make_logic(UINT8 type, UINT8 d1, UINT8 d2)
+{
+ switch (type&3)
+ {
+ case 0: //and
+ return d1 & d2;
+ case 1: //nand
+ return ~(d1 & d2);
+ case 2: //or
+ return d1 | d2;
+ case 3: //xor
+ return d1 ^ d2;
+ default:
+ return 0x00;
+ }
+}
+
+inline void hd61700_cpu_device::check_optional_jr(UINT8 arg)
+{
+ if (arg & 0x80)
+ {
+ if (m_pc < INT_ROM && !(m_fetch_addr&1)) read_op();
+
+ UINT8 arg1 = read_op();
+
+ UINT32 new_pc = m_pc + get_im_7(arg1) - 1;
+
+ set_pc(new_pc);
+ m_icount -= 3;
+ }
+}
+
+inline UINT8 hd61700_cpu_device::get_sir_im8(UINT8 arg)
+{
+ if (((arg>>5) & 0x03) == 0x03)
+ {
+ UINT8 arg1 = read_op();
+
+ return arg1&0x1f;
+ }
+ else
+ {
+ return READ_SREG(arg)&0x1f;
+ }
+}
+
+inline UINT8 hd61700_cpu_device::get_sir_im8(UINT8 arg, UINT8 arg1)
+{
+ if (((arg>>5) & 0x03) == 0x03)
+ {
+ return arg1&0x1f;
+ }
+ else
+ {
+ return READ_SREG(arg)&0x1f;
+ }
+}
+
+inline int hd61700_cpu_device::get_sign_mreg(UINT8 arg)
+{
+ int res = READ_REG(get_sir_im8(arg));
+
+ if (arg & 0x80) res = -res;
+
+ return res;
+}
+
+inline int hd61700_cpu_device::get_sign_im8(UINT8 arg)
+{
+ int res = read_op();
+
+ if (arg & 0x80) res = -res;
+
+ return res;
+}
+
+inline int hd61700_cpu_device::get_im_7(UINT8 data)
+{
+ if (data&0x80)
+ return 0x80 - data;
+ else
+ return data;
+}
+
+inline UINT16 hd61700_cpu_device::make_bcd_sub(UINT8 arg1, UINT8 arg2)
+{
+
+ UINT32 ret = (arg1&0x0f) - (arg2&0x0f);
+ UINT8 carry;
+
+ if (ret > 0x09)
+ {
+ ret = (ret - 0x06) & 0x0f;
+ carry = 1;
+ }
+ else
+ carry = 0;
+
+ ret += ((arg1&0xf0) - (arg2&0xf0) - (carry<<4));
+
+ if (ret > 0x9f)
+ {
+ ret = (ret - 0x60) & 0x0ff;
+ carry = 1;
+ }
+ else
+ carry = 0;
+
+ ret -= (carry<<8);
+
+ return ret;
+}
+
+inline UINT16 hd61700_cpu_device::make_bcd_add(UINT8 arg1, UINT8 arg2)
+{
+ UINT32 ret = (arg1&0x0f) + (arg2&0x0f);
+ UINT8 carry;
+
+ if (ret > 0x09)
+ {
+ ret = (ret + 0x06) & 0x0f;
+ carry = 1;
+ }
+ else
+ carry = 0;
+
+ ret += ((arg1&0xf0) + (arg2&0xf0) + (carry<<4));
+
+ if (ret > 0x9f)
+ {
+ ret = (ret + 0x60) & 0x0ff;
+ carry = 1;
+ }
+ else
+ carry = 0;
+
+ ret += (carry<<8);
+
+ return ret;
+}
diff --git a/trunk/src/emu/cpu/hd61700/hd61700.h b/trunk/src/emu/cpu/hd61700/hd61700.h
new file mode 100644
index 00000000000..3e69ba97378
--- /dev/null
+++ b/trunk/src/emu/cpu/hd61700/hd61700.h
@@ -0,0 +1,162 @@
+/**********************************************************************
+
+ Hitachi HD61700
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __HD61700_H__
+#define __HD61700_H__
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_HD61700_CONFIG(_config) \
+ hd61700_cpu_device::static_set_config(*device, _config); \
+
+//**************************************************************************
+// DEFINITIONS
+//**************************************************************************
+
+// class definition
+class hd61700_cpu_device;
+
+// cpu port callbacks types
+typedef void (*hd61700_lcd_control_func)(hd61700_cpu_device &device, UINT8 data);
+typedef UINT8 (*hd61700_lcd_data_r_func)(hd61700_cpu_device &device);
+typedef void (*hd61700_lcd_data_w_func)(hd61700_cpu_device &device, UINT8 data);
+typedef UINT16 (*hd61700_kb_r_func)(hd61700_cpu_device &device);
+typedef void (*hd61700_kb_w_func)(hd61700_cpu_device &device, UINT8 matrix);
+typedef UINT8 (*hd61700_port_r_func)(hd61700_cpu_device &device);
+typedef void (*hd61700_port_w_func)(hd61700_cpu_device &device, UINT8 data);
+
+// device config
+struct hd61700_config
+{
+ hd61700_lcd_control_func m_lcd_control; //lcd control
+ hd61700_lcd_data_r_func m_lcd_data_r; //lcd data read
+ hd61700_lcd_data_w_func m_lcd_data_w; //lcd data write
+ hd61700_kb_r_func m_kb_r; //keyboard matrix read
+ hd61700_kb_w_func m_kb_w; //keyboard matrix write
+ hd61700_port_r_func m_port_r; //8 bit port read
+ hd61700_port_w_func m_port_w; //8 bit port write
+};
+
+
+// registers
+enum
+{
+ HD61700_PC=1, HD61700_F, HD61700_SX, HD61700_SY, HD61700_SZ, HD61700_PE, HD61700_PD,
+ HD61700_IB, HD61700_UA, HD61700_IA, HD61700_IE, HD61700_TM, HD61700_IX,
+ HD61700_IY, HD61700_IZ, HD61700_US, HD61700_SS, HD61700_KY, HD61700_MAINREG,
+};
+
+// input lines
+enum
+{
+ HD61700_ON_INT,
+ HD61700_TIMER_INT,
+ HD61700_INT2,
+ HD61700_KEY_INT,
+ HD61700_INT1,
+ HD61700_SW
+};
+
+
+// ======================> hd61700_cpu_device
+
+class hd61700_cpu_device : public cpu_device,
+ public hd61700_config
+{
+public:
+ // construction/destruction
+ hd61700_cpu_device(const machine_config &mconfig, const char *_tag, device_t *_owner, UINT32 _clock);
+
+ static void static_set_config(device_t &device, const hd61700_config &config);
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
+
+ // device_execute_interface overrides
+ virtual UINT32 execute_min_cycles() const { return 1; }
+ virtual UINT32 execute_max_cycles() const { return 52; }
+ virtual UINT32 execute_input_lines() const { return 6; }
+ virtual void execute_run();
+ virtual void execute_set_input(int inputnum, int state);
+
+ // device_state_interface overrides
+ virtual void state_import(const device_state_entry &entry);
+ void state_string_export(const device_state_entry &entry, astring &string);
+
+ // device_memory_interface overrides
+ virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const { return (spacenum == AS_PROGRAM) ? &m_program_config : NULL; }
+
+ // device_disasm_interface overrides
+ virtual UINT32 disasm_min_opcode_bytes() const { return 1; }
+ virtual UINT32 disasm_max_opcode_bytes() const { return 16; }
+ virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);
+
+ // interrupts
+ bool check_irqs(void);
+
+ // inline helpers
+ inline void set_pc(INT32 new_pc);
+ inline UINT8 read_op();
+ inline UINT8 mem_readbyte(UINT8 segment, UINT16 offset);
+ inline void mem_writebyte(UINT8 segment, UINT16 offset, UINT8 data);
+ inline UINT32 make_18bit_addr(UINT8 segment, UINT16 offset);
+ inline int check_cond( UINT32 op );
+ inline void push(UINT16 &offset, UINT8 data);
+ inline UINT8 pop(UINT16 &offset);
+ inline UINT8 make_logic(UINT8 type, UINT8 d1, UINT8 d2);
+ inline void check_optional_jr(UINT8 arg);
+ inline UINT8 get_sir_im8(UINT8 arg);
+ inline UINT8 get_sir_im8(UINT8 arg, UINT8 arg1);
+ inline int get_sign_mreg(UINT8 op1);
+ inline int get_sign_im8(UINT8 op1);
+ inline int get_im_7(UINT8 data);
+ inline UINT16 make_bcd_sub(UINT8 arg1, UINT8 arg2);
+ inline UINT16 make_bcd_add(UINT8 arg1, UINT8 arg2);
+
+protected:
+
+ // internal state
+ address_space_config m_program_config;
+ static const device_timer_id SEC_TIMER = 1;
+ emu_timer *m_sec_timer;
+
+ offs_t m_ppc;
+ offs_t m_curpc;
+ UINT16 m_pc;
+ UINT8 m_flags;
+ UINT32 m_fetch_addr;
+ UINT8 m_regsir[3]; // 5bit register (sx, sy, sz)
+ UINT8 m_reg8bit[8]; // 8bit register (pe, pd, ib, ua, ia, ie, tm, tm)
+ UINT16 m_reg16bit[8]; // 16bit register (ix, iy, iz, us, ss, ky, ky, ky)
+ UINT8 m_regmain[0x20]; // main registers
+ UINT8 m_irq_status;
+ UINT8 m_state;
+ UINT8 prev_ua;
+ int m_lines_status[6];
+ int m_icount;
+
+ address_space *m_program;
+
+ // flag definitions
+ static const int FLAG_Z = 0x80;
+ static const int FLAG_C = 0x40;
+ static const int FLAG_LZ = 0x20;
+ static const int FLAG_UZ = 0x10;
+ static const int FLAG_SW = 0x08;
+ static const int FLAG_APO = 0x04;
+};
+
+extern const device_type HD61700;
+
+
+#endif /* __HD61700_H__ */
diff --git a/trunk/src/emu/cpu/hd61700/hd61700d.c b/trunk/src/emu/cpu/hd61700/hd61700d.c
new file mode 100644
index 00000000000..3cb4cb800c5
--- /dev/null
+++ b/trunk/src/emu/cpu/hd61700/hd61700d.c
@@ -0,0 +1,437 @@
+#include "emu.h"
+#include "debugger.h"
+#include "hd61700.h"
+
+#define EXT_ROM (pc > 0x0c00)
+#define INC_POS pos += (type+1)
+#define POS (pos + type)
+
+static const char *const reg_5b[4] = {"sx", "sy", "sz", "sz"};
+static const char *const reg_8b[8] = {"pe", "pd", "ib", "ua", "ia", "ie", "tm", "tm"};
+static const char *const reg_16b[8] = {"ix", "iy", "iz", "us", "ss", "ky", "ky", "ky"};
+static const char *const jp_cond[8] = {"z", "nc", "lz", "uz", "nz", "c", "nlz"};
+
+enum
+{
+ OP_NULL=0,
+ OP_IM16,
+ OP_IM16A,
+ OP_IM3,
+ OP_IM5,
+ OP_IM7,
+ OP_IM8,
+ OP_IM8I,
+ OP_IM8_,
+ OP_IR_IM3,
+ OP_IR_IM8,
+ OP_IR_IM8_,
+ OP_JX_COND,
+ OP_MREG,
+ OP_MREG2,
+ OP_MR_SIR,
+ OP_MR_SIRI,
+ OP_REG16,
+ OP_REG16_,
+ OP_REG8,
+ OP_REG8_,
+ OP_REGIM8,
+ OP_RMSIM3,
+ OP_RSIR,
+};
+
+typedef struct
+{
+ const char *str;
+ UINT8 arg1;
+ UINT8 arg2;
+ bool optjr;
+} hd61700_dasm;
+
+static const hd61700_dasm hd61700_ops[256] =
+{
+ // 0x00
+ { "adc", OP_MREG, OP_MR_SIR, 1 }, { "sbc", OP_MREG, OP_MR_SIR, 1 },
+ { "ld", OP_MREG, OP_MR_SIR, 1 }, { "illegal", OP_NULL, OP_NULL, 0 },
+ { "anc", OP_MREG, OP_MR_SIR, 1 }, { "nac", OP_MREG, OP_MR_SIR, 1 },
+ { "orc", OP_MREG, OP_MR_SIR, 1 }, { "xrc", OP_MREG, OP_MR_SIR, 1 },
+ { "ad", OP_MREG, OP_MR_SIR, 1 }, { "sb", OP_MREG, OP_MR_SIR, 1 },
+ { "adb", OP_MREG, OP_MR_SIR, 1 }, { "sbb", OP_MREG, OP_MR_SIR, 1 },
+ { "an", OP_MREG, OP_MR_SIR, 1 }, { "na", OP_MREG, OP_MR_SIR, 1 },
+ { "or", OP_MREG, OP_MR_SIR, 1 }, { "xr", OP_MREG, OP_MR_SIR, 1 },
+
+ // 0x10
+ { "st", OP_MREG, OP_MR_SIRI, 1 }, { "ld", OP_MREG, OP_MR_SIRI,1 },
+ { "stl", OP_MREG2, OP_NULL, 1 }, { "ldl", OP_MREG2, OP_NULL, 1 },
+ { "???", OP_MREG2, OP_NULL, 1 }, { "psr", OP_RSIR, OP_MREG2, 1 },
+ { "pst", OP_REG8, OP_MREG2, 1 }, { "pst", OP_REG8, OP_MREG2, 1 },
+ { "???", OP_MREG2, OP_NULL, 1 }, { "illegal", OP_NULL, OP_NULL, 0 },
+ { "???", OP_MREG2, OP_NULL, 1 }, { "???", OP_MREG2, OP_NULL, 1 },
+ { "???", OP_MREG2, OP_NULL, 1 }, { "gsr", OP_RSIR, OP_MREG2, 1 },
+ { "gst", OP_REG8, OP_MREG2, 1 }, { "gst", OP_REG8, OP_MREG2, 1 },
+
+ // 0x20
+ { "st", OP_MREG, OP_IR_IM8_, 0 }, { "st", OP_MREG, OP_IR_IM8_,0 },
+ { "sti", OP_MREG, OP_IR_IM8_, 0 }, { "sti", OP_MREG, OP_IR_IM8_,0 },
+ { "std", OP_MREG, OP_IR_IM8_, 0 }, { "std", OP_MREG, OP_IR_IM8_,0 },
+ { "phs", OP_MREG2, OP_NULL, 0 }, { "phu", OP_MREG2, OP_NULL, 0 },
+ { "ld", OP_MREG, OP_IR_IM8_, 0 }, { "ld", OP_MREG, OP_IR_IM8_,0 },
+ { "ldi", OP_MREG, OP_IR_IM8_, 0 }, { "ldi", OP_MREG, OP_IR_IM8_,0 },
+ { "ldd", OP_MREG, OP_IR_IM8_, 0 }, { "ldd", OP_MREG, OP_IR_IM8_,0 },
+ { "pps", OP_MREG2, OP_NULL, 0 }, { "ppu", OP_MREG2, OP_NULL, 0 },
+
+ // 0x30
+ { "jp", OP_JX_COND, OP_IM16A, 0 }, { "jp", OP_JX_COND, OP_IM16A, 0 },
+ { "jp", OP_JX_COND, OP_IM16A, 0 }, { "jp", OP_JX_COND, OP_IM16A, 0 },
+ { "jp", OP_JX_COND, OP_IM16A, 0 }, { "jp", OP_JX_COND, OP_IM16A, 0 },
+ { "jp", OP_JX_COND, OP_IM16A, 0 }, { "jp", OP_IM16A, OP_NULL, 0 },
+ { "adc", OP_IR_IM8, OP_MREG2, 0 }, { "adc", OP_IR_IM8, OP_MREG2, 0 },
+ { "sbc", OP_IR_IM8, OP_MREG2, 0 }, { "sbc", OP_IR_IM8, OP_MREG2, 0 },
+ { "ad", OP_IR_IM8, OP_MREG2, 0 }, { "ad", OP_IR_IM8, OP_MREG2, 0 },
+ { "sb", OP_IR_IM8, OP_MREG2, 0 }, { "sb", OP_IR_IM8, OP_MREG2, 0 },
+
+ // 0x40
+ { "adc", OP_MREG2, OP_IM8, 1 }, { "sbc", OP_MREG2, OP_IM8, 1 },
+ { "ld", OP_MREG2, OP_IM8, 1 }, { "illegal", OP_NULL, OP_NULL, 0 },
+ { "anc", OP_MREG2, OP_IM8, 1 }, { "nac", OP_MREG2, OP_IM8, 1 },
+ { "orc", OP_MREG2, OP_IM8, 1 }, { "xrc", OP_MREG2, OP_IM8, 1 },
+ { "ad", OP_MREG2, OP_IM8, 1 }, { "sb", OP_MREG2, OP_IM8, 1 },
+ { "adb", OP_MREG2, OP_IM8, 1 }, { "sbb", OP_MREG2, OP_IM8, 1 },
+ { "an", OP_MREG2, OP_IM8, 1 }, { "na", OP_MREG2, OP_IM8, 1 },
+ { "or", OP_MREG2, OP_IM8, 1 }, { "xr", OP_MREG2, OP_IM8, 1 },
+
+ // 0x50
+ { "st", OP_IM8I, OP_MREG2, 0 }, { "st", OP_IM8, OP_MREG2,0 },
+ { "stl", OP_IM8_, OP_NULL, 0 }, { "illegal", OP_NULL, OP_NULL, 0 },
+ { "???", OP_IM8_, OP_NULL, 0 }, { "psr", OP_RSIR, OP_IM5, 0 },
+ { "pst", OP_REG8_, OP_IM8, 0 }, { "pst", OP_REG8_, OP_IM8, 0 },
+ { "bups", OP_IM8_, OP_NULL, 0 }, { "bdns", OP_IM8_, OP_NULL, 0 },
+ { "illegal", OP_NULL, OP_NULL, 0 }, { "illegal", OP_NULL, OP_NULL, 0 },
+ { "sup", OP_IM8_, OP_NULL, 0 }, { "sdn", OP_IM8_, OP_NULL, 0 },
+ { "illegal", OP_NULL, OP_NULL, 0 }, { "illegal", OP_NULL, OP_NULL, 0 },
+
+ // 0x60
+ { "st", OP_MREG2, OP_REGIM8, 0 }, { "st", OP_MREG2, OP_REGIM8, 0 },
+ { "sti", OP_MREG2, OP_REGIM8, 0 }, { "sti", OP_MREG2, OP_REGIM8, 0 },
+ { "std", OP_MREG2, OP_REGIM8, 0 }, { "std", OP_MREG2, OP_REGIM8, 0 },
+ { "illegal", OP_NULL, OP_NULL, 0 }, { "illegal", OP_NULL, OP_NULL, 0 },
+ { "ld", OP_MREG2, OP_REGIM8, 0 }, { "ld", OP_MREG2, OP_REGIM8, 0 },
+ { "ldi", OP_MREG2, OP_REGIM8, 0 }, { "ldi", OP_MREG2, OP_REGIM8, 0 },
+ { "ldd", OP_MREG2, OP_REGIM8, 0 }, { "ldd", OP_MREG2, OP_REGIM8, 0 },
+ { "illegal", OP_NULL, OP_NULL, 0 }, { "illegal", OP_NULL, OP_NULL, 0 },
+
+ // 0x70
+ { "cal", OP_JX_COND, OP_IM16A, 0 }, { "cal", OP_JX_COND, OP_IM16A, 0 },
+ { "cal", OP_JX_COND, OP_IM16A, 0 }, { "cal", OP_JX_COND, OP_IM16A, 0 },
+ { "cal", OP_JX_COND, OP_IM16A, 0 }, { "cal", OP_JX_COND, OP_IM16A, 0 },
+ { "cal", OP_JX_COND, OP_IM16A, 0 }, { "cal", OP_IM16A, OP_NULL, 0 },
+ { "adc", OP_REGIM8, OP_MREG2, 0 }, { "adc", OP_REGIM8, OP_MREG2, 0 },
+ { "sbc", OP_REGIM8, OP_MREG2, 0 }, { "sbc", OP_REGIM8, OP_MREG2, 0 },
+ { "ad", OP_REGIM8, OP_MREG2, 0 }, { "ad ", OP_REGIM8, OP_MREG2, 0 },
+ { "sb", OP_REGIM8, OP_MREG2, 0 }, { "sb", OP_REGIM8, OP_MREG2, 0 },
+
+ // 0x80
+ { "adcw", OP_MREG, OP_MR_SIR, 1 }, { "sbcw", OP_MREG, OP_MR_SIR, 1 },
+ { "ldw", OP_MREG, OP_MR_SIR, 1 }, { "illegal", OP_NULL, OP_NULL, 0 },
+ { "ancw", OP_MREG, OP_MR_SIR, 1 }, { "nacw", OP_MREG, OP_MR_SIR, 1 },
+ { "orcw", OP_MREG, OP_MR_SIR, 1 }, { "xrcw", OP_MREG, OP_MR_SIR, 1 },
+ { "adw", OP_MREG, OP_MR_SIR, 1 }, { "sbw", OP_MREG, OP_MR_SIR, 1 },
+ { "adbw", OP_MREG, OP_MR_SIR, 1 }, { "sbbw", OP_MREG, OP_MR_SIR, 1 },
+ { "anw", OP_MREG, OP_MR_SIR, 1 }, { "naw", OP_MREG, OP_MR_SIR, 1 },
+ { "orw", OP_MREG, OP_MR_SIR, 1 }, { "xrw", OP_MREG, OP_MR_SIR, 1 },
+
+ // 0x90
+ { "stw", OP_MREG, OP_MR_SIRI,1 }, { "ldw", OP_MREG, OP_MR_SIRI,1 },
+ { "stlw", OP_MREG2, OP_NULL, 1 }, { "ldlw", OP_MREG2, OP_NULL, 1 },
+ { "illegal", OP_NULL, OP_NULL, 0 }, { "illegal", OP_NULL, OP_NULL, 0 },
+ { "pre", OP_REG16, OP_MREG2, 1 }, { "pre", OP_REG16, OP_MREG2, 1 },
+ { "???", OP_MREG2, OP_NULL, 1 }, { "illegal", OP_NULL, OP_NULL, 0 },
+ { "???", OP_MREG2, OP_NULL, 1 }, { "???", OP_MREG2, OP_NULL, 1 },
+ { "???", OP_MREG2, OP_NULL, 1 }, { "illegal", OP_NULL, OP_NULL, 0 },
+ { "gre", OP_REG16, OP_MREG2, 1 }, { "gre", OP_REG16, OP_MREG2, 1 },
+
+ // 0xa0
+ { "stw", OP_MREG, OP_IR_IM8_, 0 }, { "stw", OP_MREG, OP_IR_IM8_, 0 },
+ { "stiw", OP_MREG, OP_IR_IM8_, 0 }, { "stiw", OP_MREG, OP_IR_IM8_, 0 },
+ { "stdw", OP_MREG, OP_IR_IM8_, 0 }, { "stdw", OP_MREG, OP_IR_IM8_, 0 },
+ { "phsw", OP_MREG2, OP_NULL, 0 }, { "phuw", OP_MREG2, OP_NULL, 0 },
+ { "ldw", OP_MREG, OP_IR_IM8_, 0 }, { "ldw", OP_MREG, OP_IR_IM8_, 0 },
+ { "ldiw", OP_MREG, OP_IR_IM8_, 0 }, { "ldiw", OP_MREG, OP_IR_IM8_, 0 },
+ { "lddw", OP_MREG, OP_IR_IM8_, 0 }, { "lddw", OP_MREG, OP_IR_IM8_, 0 },
+ { "ppsw", OP_MREG2, OP_NULL, 0 }, { "ppuw", OP_MREG2, OP_NULL, 0 },
+
+ // 0xb0
+ { "jr", OP_JX_COND, OP_IM7, 0 }, { "jr", OP_JX_COND, OP_IM7, 0 },
+ { "jr", OP_JX_COND, OP_IM7, 0 }, { "jr", OP_JX_COND, OP_IM7, 0 },
+ { "jr", OP_JX_COND, OP_IM7, 0 }, { "jr", OP_JX_COND, OP_IM7, 0 },
+ { "jr", OP_JX_COND, OP_IM7, 0 }, { "jr", OP_IM7, OP_NULL, 0 },
+ { "adcw", OP_IR_IM8, OP_MREG, 0 }, { "adcw", OP_IR_IM8, OP_MREG, 0 },
+ { "sbcw", OP_IR_IM8, OP_MREG, 0 }, { "sbcw", OP_IR_IM8, OP_MREG, 0 },
+ { "adw", OP_IR_IM8, OP_MREG, 0 }, { "adw", OP_IR_IM8, OP_MREG, 0 },
+ { "sbw", OP_IR_IM8, OP_MREG, 0 }, { "sbw", OP_IR_IM8, OP_MREG, 0 },
+
+ // 0xc0
+ { "adbcm",OP_MREG, OP_RMSIM3, 1 }, { "sdbcm",OP_MREG, OP_RMSIM3, 1 },
+ { "ldm", OP_MREG, OP_RMSIM3, 1 }, { "illegal", OP_NULL, OP_NULL, 0 },
+ { "ancm", OP_MREG, OP_RMSIM3, 1 }, { "nacm", OP_MREG, OP_RMSIM3, 1 },
+ { "orcm", OP_MREG, OP_RMSIM3, 1 }, { "xrcm", OP_MREG, OP_RMSIM3, 1 },
+ { "adbm", OP_MREG, OP_RMSIM3, 1 }, { "sbbm", OP_MREG, OP_RMSIM3, 1 },
+ { "adbm", OP_MREG, OP_RMSIM3, 1 }, { "sbbm", OP_MREG, OP_RMSIM3, 1 },
+ { "anm", OP_MREG, OP_RMSIM3, 1 }, { "nam", OP_MREG, OP_RMSIM3, 1 },
+ { "orm", OP_MREG, OP_RMSIM3, 1 }, { "xrm", OP_MREG, OP_RMSIM3, 1 },
+
+ // 0xd0
+ { "stw", OP_IM16, OP_MR_SIR, 0 }, { "ldw", OP_MREG2, OP_IM16, 0 },
+ { "stlm", OP_MREG2, OP_IM3, 0 }, { "ldlm", OP_MREG2, OP_IM3, 0 },
+ { "illegal", OP_NULL, OP_NULL, 0 }, { "illegal", OP_NULL, OP_NULL, 0 },
+ { "pre", OP_REG16_, OP_IM16, 0 }, { "pre", OP_REG16_, OP_IM16, 0 },
+ { "bup", OP_NULL, OP_NULL, 0 }, { "bnd", OP_NULL, OP_NULL, 0 },
+ { "???", OP_MREG2, OP_IM3, 0 }, { "???", OP_MREG2, OP_IM3, 0 },
+ { "sup", OP_MREG, OP_NULL, 0 }, { "sdn", OP_MREG, OP_NULL, 0 },
+ { "jp", OP_MREG, OP_NULL, 0 }, { "jp", OP_MREG, OP_NULL, 0 },
+
+ // 0xe0
+ { "stm", OP_MREG, OP_IR_IM3, 0 }, { "stm", OP_MREG, OP_IR_IM3, 0 },
+ { "stim", OP_MREG, OP_IR_IM3, 0 }, { "stim", OP_MREG, OP_IR_IM3, 0 },
+ { "stdm", OP_MREG, OP_IR_IM3, 0 }, { "stdm", OP_MREG, OP_IR_IM3, 0 },
+ { "phsm", OP_MREG2, OP_IM3, 0 }, { "phum", OP_MREG2, OP_IM3, 0 },
+ { "ldm", OP_MREG, OP_IR_IM3, 0 }, { "ldm", OP_MREG, OP_IR_IM3, 0 },
+ { "ldim", OP_MREG, OP_IR_IM3, 0 }, { "ldim", OP_MREG, OP_IR_IM3, 0 },
+ { "lddm", OP_MREG, OP_IR_IM3, 0 }, { "lddm", OP_MREG, OP_IR_IM3, 0 },
+ { "ppsm", OP_MREG2, OP_IM3, 0 }, { "ppum", OP_MREG2, OP_IM3, 0 },
+
+ // 0xf0
+ { "rtn", OP_JX_COND, OP_NULL, 0 }, { "rtn", OP_JX_COND, OP_NULL, 0 },
+ { "rtn", OP_JX_COND, OP_NULL, 0 }, { "rtn", OP_JX_COND, OP_NULL, 0 },
+ { "rtn", OP_JX_COND, OP_NULL, 0 }, { "rtn", OP_JX_COND, OP_NULL, 0 },
+ { "rtn", OP_JX_COND, OP_NULL, 0 }, { "rtn", OP_NULL, OP_NULL, 0 },
+ { "nop", OP_JX_COND, OP_NULL, 0 }, { "clt", OP_NULL, OP_NULL, 0 },
+ { "fst", OP_NULL, OP_NULL, 0 }, { "slw", OP_NULL, OP_NULL, 0 },
+ { "can", OP_NULL, OP_NULL, 0 }, { "rtni", OP_NULL, OP_NULL, 0 },
+ { "off", OP_NULL, OP_NULL, 0 }, { "trp", OP_NULL, OP_NULL, 0 },
+};
+
+
+inline int dasm_im8(char *buffer, UINT16 pc, int arg, const UINT8 *oprom, int &pos, int type)
+{
+ if (((arg>>5) & 0x03) == 0x03)
+ {
+ INC_POS;
+ UINT8 ret = sprintf( buffer, "0x%02x", oprom[POS] & 0x1f );
+ return ret;
+ }
+ else
+ {
+ return sprintf( buffer, "%s", reg_5b[(arg>>5) & 0x03] );
+ }
+}
+
+
+inline int dasm_im8(char *buffer, UINT16 pc, int arg, int arg1, const UINT8 *oprom, int &pos)
+{
+ if (((arg>>5) & 0x03) == 0x03)
+ {
+ return sprintf( buffer, "0x%02x", arg1 & 0x1f );
+ }
+ else
+ {
+ return sprintf( buffer, "%s", reg_5b[(arg>>5) & 0x03] );
+ }
+}
+
+
+int dasm_arg(char *buffer, UINT8 op, UINT16 pc, int arg, const UINT8 *oprom, int &pos)
+{
+ char* buffer_start = buffer;
+ int type = EXT_ROM;
+
+ switch( arg )
+ {
+ case OP_MREG:
+ case OP_MREG2:
+ buffer += sprintf( buffer, "$%02u", oprom[POS] & 0x1f );
+ if (arg == OP_MREG2) INC_POS;
+ break;
+
+ case OP_RSIR:
+ buffer += sprintf( buffer, "%s", reg_5b[(oprom[POS]>>5) & 0x03] );
+ break;
+
+ case OP_REG8:
+ case OP_REG8_:
+ buffer += sprintf( buffer, "%s", reg_8b[(BIT(op,0)<<2) + ((oprom[POS]>>5&3))]);
+ if (arg == OP_REG8_) INC_POS;
+ break;
+
+ case OP_MR_SIR:
+ buffer += dasm_im8(buffer, pc, oprom[POS], oprom, pos, type);
+ INC_POS;
+ break;
+
+ case OP_IR_IM8:
+ case OP_IR_IM8_:
+ buffer += sprintf( buffer, "(%s%s", (op&1) ? "iz": "ix", (oprom[POS]&0x80) ? "-": "+");
+ buffer += dasm_im8(buffer, pc, oprom[POS], oprom, pos, type);
+ buffer += sprintf( buffer, ")");
+ if (arg == OP_IR_IM8_) INC_POS;
+ break;
+
+ case OP_IM8_:
+ INC_POS;
+ case OP_IM8:
+ buffer += sprintf( buffer, "0x%02x", oprom[POS] );
+ INC_POS;
+ break;
+
+ case OP_IM8I:
+ buffer += sprintf( buffer, "(0x%02x)", oprom[POS] );
+ INC_POS;
+ break;
+
+ case OP_REGIM8:
+ buffer += sprintf( buffer, "(%s%s", (op&1) ? "iz": "ix", (oprom[POS]&0x80) ? "-": "+");
+ buffer += sprintf( buffer, "%x)", oprom[POS] & 0x1f);
+ INC_POS;
+ break;
+
+ case OP_JX_COND:
+ buffer += sprintf( buffer, "%s", jp_cond[op & 0x07] );
+ break;
+
+
+ case OP_RMSIM3:
+ {
+ UINT8 tmp = oprom[POS];
+ INC_POS;
+ buffer += dasm_im8(buffer, pc, tmp, oprom[POS], oprom, pos);
+ buffer += sprintf( buffer, ", 0x%02x", ((tmp>>5)&7)+1);
+ INC_POS;
+ }
+ break;
+
+ case OP_IR_IM3:
+ {
+ UINT8 tmp = oprom[POS];
+ INC_POS;
+ buffer += sprintf( buffer, "(%s%s", (op&1) ? "iz": "ix", (tmp&0x80) ? "-": "+");
+ buffer += dasm_im8(buffer, pc, tmp, oprom[POS], oprom, pos);
+ buffer += sprintf( buffer, "), 0x%02x", ((oprom[POS]>>5)&7)+1 );
+ INC_POS;
+ }
+ break;
+
+ case OP_IM3:
+ buffer += sprintf( buffer, "0x%02x", ((oprom[POS]>>5)&7)+1 );
+ INC_POS;
+ break;
+
+ case OP_MR_SIRI:
+ buffer += sprintf( buffer, "(");
+ buffer += dasm_im8(buffer, pc, oprom[POS], oprom, pos, type);
+ buffer += sprintf( buffer, ")");
+ INC_POS;
+ break;
+
+ case OP_IM7:
+ {
+ int tmp = oprom[POS];
+ if (tmp&0x80) tmp = 0x80 - tmp;
+
+ buffer += sprintf( buffer, "0x%04x", (pc + tmp + EXT_ROM) & 0xffff );
+ INC_POS;
+ }
+ break;
+
+ case OP_IM5:
+ buffer += sprintf( buffer, "0x%02x", oprom[POS]&0x1f );
+ INC_POS;
+ break;
+
+ case OP_REG16:
+ case OP_REG16_:
+ buffer += sprintf( buffer, "%s", reg_16b[(BIT(op,0)<<2) + ((oprom[POS]>>5&3))]);
+ if (arg == OP_REG16_) INC_POS;
+ break;
+
+ case OP_IM16:
+ case OP_IM16A:
+ {
+ UINT8 tmp1 = oprom[POS];
+ INC_POS;
+ if (!EXT_ROM && arg == OP_IM16A) INC_POS;
+ UINT8 tmp2 = oprom[POS];
+ buffer += sprintf( buffer, "0x%04x", ((tmp2<<8) | tmp1));
+ INC_POS;
+ }
+ break;
+
+ case OP_NULL:
+ break;
+ }
+
+ return buffer - buffer_start;
+}
+
+UINT32 get_dasmflags(UINT8 op)
+{
+ switch (op)
+ {
+ case 0x30: case 0x31: case 0x32: case 0x33: //jp
+ case 0x34: case 0x35: case 0x36: case 0x37: //jp
+ case 0x70: case 0x71: case 0x72: case 0x73: //cal
+ case 0x74: case 0x75: case 0x76: case 0x77: //cal
+ case 0xb0: case 0xb1: case 0xb2: case 0xb3: //jr
+ case 0xb4: case 0xb5: case 0xb6: case 0xb7: //jr
+ case 0xde: //jp
+ case 0xdf: //jp
+ return DASMFLAG_STEP_OVER;
+ case 0xf0: case 0xf1: case 0xf2: case 0xf3: //rtn
+ case 0xf4: case 0xf5: case 0xf6: case 0xf7: //rtn
+ case 0xfd: //rtni
+ return DASMFLAG_STEP_OUT;
+ }
+
+ return 0;
+}
+
+
+CPU_DISASSEMBLE( hd61700 )
+{
+ const hd61700_dasm *inst;
+ UINT32 dasmflags = 0;
+ UINT8 op, op1;
+ int pos = 0, type = EXT_ROM;
+
+ op = oprom[POS];
+ INC_POS;
+
+ dasmflags = get_dasmflags(op);
+
+ op1 = oprom[POS];
+
+ inst = &hd61700_ops[op];
+
+ buffer += sprintf(buffer,"%-8s", inst->str);
+
+ //dasm first arg
+ buffer += dasm_arg(buffer, op, pc, inst->arg1, oprom, pos);
+
+ //if present dasm second arg
+ if (inst->arg2 != OP_NULL)
+ {
+ buffer += sprintf(buffer,", ");
+ buffer += dasm_arg(buffer, op, pc, inst->arg2, oprom, pos);
+ }
+
+ //if required add the optional jr
+ if (inst->optjr == true && BIT(op1, 7))
+ {
+ buffer += sprintf( buffer, ", jr ");
+ buffer += dasm_arg(buffer, op, pc+1, OP_IM7, oprom, pos);
+
+ dasmflags = DASMFLAG_STEP_OVER;
+ }
+
+ if (pos&1) INC_POS;
+
+ return (pos>>1) | dasmflags | DASMFLAG_SUPPORTED;
+}
diff --git a/trunk/src/emu/cpu/hd6309/6309dasm.c b/trunk/src/emu/cpu/hd6309/6309dasm.c
new file mode 100644
index 00000000000..f15405368c5
--- /dev/null
+++ b/trunk/src/emu/cpu/hd6309/6309dasm.c
@@ -0,0 +1,941 @@
+/*****************************************************************************
+
+ 6309dasm.c - a 6309 opcode disassembler
+ Version 1.0 5-AUG-2000
+ Copyright Tim Lindner
+
+ Based on:
+ 6809dasm.c - a 6809 opcode disassembler
+ Version 1.4 1-MAR-95
+ Copyright Sean Riddle
+
+ Thanks to Franklin Bowen for bug fixes, ideas
+
+ Freely distributable on any medium given all copyrights are retained
+ by the author and no charge greater than $7.00 is made for obtaining
+ this software
+
+ Please send all bug reports, update ideas and data files to:
+ tlindner@ix.netcom.com
+
+*****************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "hd6309.h"
+
+// Opcode structure
+typedef struct
+{
+ UINT8 opcode; // 8-bit opcode value
+ UINT8 length; // Opcode length in bytes
+ char name[6]; // Opcode name
+ UINT8 mode; // Addressing mode
+ unsigned flags; // Disassembly flags
+} opcodeinfo;
+
+enum hd6309_addressing_modes
+{
+ INH, // Inherent
+ DIR, // Direct
+ DIR_IM, // Direct in memory (6309 only)
+ IND, // Indexed
+ REL, // Relative (8 bit)
+ LREL, // Long relative (16 bit)
+ EXT, // Extended
+ IMM, // Immediate
+ IMM_RR, // Register-to-register
+ IMM_BW, // Bitwise operations (6309 only)
+ IMM_TFM, // Transfer from memory (6309 only)
+ PG1, // Switch to page 1 opcodes
+ PG2 // Switch to page 2 opcodes
+};
+
+// Page 0 opcodes (single byte)
+static const opcodeinfo hd6309_pg0opcodes[] =
+{
+ { 0x00, 2, "NEG", DIR },
+ { 0x01, 3, "OIM", DIR_IM },
+ { 0x02, 3, "AIM", DIR_IM },
+ { 0x03, 2, "COM", DIR },
+ { 0x04, 2, "LSR", DIR },
+ { 0x05, 3, "EIM", DIR_IM },
+ { 0x06, 2, "ROR", DIR },
+ { 0x07, 2, "ASR", DIR },
+ { 0x08, 2, "ASL", DIR },
+ { 0x09, 2, "ROL", DIR },
+ { 0x0A, 2, "DEC", DIR },
+ { 0x0B, 3, "TIM", DIR_IM },
+ { 0x0C, 2, "INC", DIR },
+ { 0x0D, 2, "TST", DIR },
+ { 0x0E, 2, "JMP", DIR },
+ { 0x0F, 2, "CLR", DIR },
+
+ { 0x10, 1, "page1", PG1 },
+ { 0x11, 1, "page2", PG2 },
+ { 0x12, 1, "NOP", INH },
+ { 0x13, 1, "SYNC", INH },
+ { 0x14, 1, "SEXW", INH },
+ { 0x16, 3, "LBRA", LREL },
+ { 0x17, 3, "LBSR", LREL , DASMFLAG_STEP_OVER },
+ { 0x19, 1, "DAA", INH },
+ { 0x1A, 2, "ORCC", IMM },
+ { 0x1C, 2, "ANDCC", IMM },
+ { 0x1D, 1, "SEX", INH },
+ { 0x1E, 2, "EXG", IMM_RR },
+ { 0x1F, 2, "TFR", IMM_RR },
+
+ { 0x20, 2, "BRA", REL },
+ { 0x21, 2, "BRN", REL },
+ { 0x22, 2, "BHI", REL },
+ { 0x23, 2, "BLS", REL },
+ { 0x24, 2, "BCC", REL },
+ { 0x25, 2, "BCS", REL },
+ { 0x26, 2, "BNE", REL },
+ { 0x27, 2, "BEQ", REL },
+ { 0x28, 2, "BVC", REL },
+ { 0x29, 2, "BVS", REL },
+ { 0x2A, 2, "BPL", REL },
+ { 0x2B, 2, "BMI", REL },
+ { 0x2C, 2, "BGE", REL },
+ { 0x2D, 2, "BLT", REL },
+ { 0x2E, 2, "BGT", REL },
+ { 0x2F, 2, "BLE", REL },
+
+ { 0x30, 2, "LEAX", IND },
+ { 0x31, 2, "LEAY", IND },
+ { 0x32, 2, "LEAS", IND },
+ { 0x33, 2, "LEAU", IND },
+ { 0x34, 2, "PSHS", INH },
+ { 0x35, 2, "PULS", INH },
+ { 0x36, 2, "PSHU", INH },
+ { 0x37, 2, "PULU", INH },
+ { 0x39, 1, "RTS", INH },
+ { 0x3A, 1, "ABX", INH },
+ { 0x3B, 1, "RTI", INH },
+ { 0x3C, 2, "CWAI", IMM },
+ { 0x3D, 1, "MUL", INH },
+ { 0x3F, 1, "SWI", INH },
+
+ { 0x40, 1, "NEGA", INH },
+ { 0x43, 1, "COMA", INH },
+ { 0x44, 1, "LSRA", INH },
+ { 0x46, 1, "RORA", INH },
+ { 0x47, 1, "ASRA", INH },
+ { 0x48, 1, "ASLA", INH },
+ { 0x49, 1, "ROLA", INH },
+ { 0x4A, 1, "DECA", INH },
+ { 0x4C, 1, "INCA", INH },
+ { 0x4D, 1, "TSTA", INH },
+ { 0x4F, 1, "CLRA", INH },
+
+ { 0x50, 1, "NEGB", INH },
+ { 0x53, 1, "COMB", INH },
+ { 0x54, 1, "LSRB", INH },
+ { 0x56, 1, "RORB", INH },
+ { 0x57, 1, "ASRB", INH },
+ { 0x58, 1, "ASLB", INH },
+ { 0x59, 1, "ROLB", INH },
+ { 0x5A, 1, "DECB", INH },
+ { 0x5C, 1, "INCB", INH },
+ { 0x5D, 1, "TSTB", INH },
+ { 0x5F, 1, "CLRB", INH },
+
+ { 0x60, 2, "NEG", IND },
+ { 0x61, 3, "OIM", IND },
+ { 0x62, 3, "AIM", IND },
+ { 0x63, 2, "COM", IND },
+ { 0x64, 2, "LSR", IND },
+ { 0x65, 3, "EIM", IND },
+ { 0x66, 2, "ROR", IND },
+ { 0x67, 2, "ASR", IND },
+ { 0x68, 2, "ASL", IND },
+ { 0x69, 2, "ROL", IND },
+ { 0x6A, 2, "DEC", IND },
+ { 0x6B, 3, "TIM", IND },
+ { 0x6C, 2, "INC", IND },
+ { 0x6D, 2, "TST", IND },
+ { 0x6E, 2, "JMP", IND },
+ { 0x6F, 2, "CLR", IND },
+
+ { 0x70, 3, "NEG", EXT },
+ { 0x71, 4, "OIM", EXT },
+ { 0x72, 4, "AIM", EXT },
+ { 0x73, 3, "COM", EXT },
+ { 0x74, 3, "LSR", EXT },
+ { 0x75, 4, "EIM", EXT },
+ { 0x76, 3, "ROR", EXT },
+ { 0x77, 3, "ASR", EXT },
+ { 0x78, 3, "ASL", EXT },
+ { 0x79, 3, "ROL", EXT },
+ { 0x7A, 3, "DEC", EXT },
+ { 0x7B, 4, "TIM", EXT },
+ { 0x7C, 3, "INC", EXT },
+ { 0x7D, 3, "TST", EXT },
+ { 0x7E, 3, "JMP", EXT },
+ { 0x7F, 3, "CLR", EXT },
+
+ { 0x80, 2, "SUBA", IMM },
+ { 0x81, 2, "CMPA", IMM },
+ { 0x82, 2, "SBCA", IMM },
+ { 0x83, 3, "SUBD", IMM },
+ { 0x84, 2, "ANDA", IMM },
+ { 0x85, 2, "BITA", IMM },
+ { 0x86, 2, "LDA", IMM },
+ { 0x88, 2, "EORA", IMM },
+ { 0x89, 2, "ADCA", IMM },
+ { 0x8A, 2, "ORA", IMM },
+ { 0x8B, 2, "ADDA", IMM },
+ { 0x8C, 3, "CMPX", IMM },
+ { 0x8D, 2, "BSR", REL , DASMFLAG_STEP_OVER },
+ { 0x8E, 3, "LDX", IMM },
+
+ { 0x90, 2, "SUBA", DIR },
+ { 0x91, 2, "CMPA", DIR },
+ { 0x92, 2, "SBCA", DIR },
+ { 0x93, 2, "SUBD", DIR },
+ { 0x94, 2, "ANDA", DIR },
+ { 0x95, 2, "BITA", DIR },
+ { 0x96, 2, "LDA", DIR },
+ { 0x97, 2, "STA", DIR },
+ { 0x98, 2, "EORA", DIR },
+ { 0x99, 2, "ADCA", DIR },
+ { 0x9A, 2, "ORA", DIR },
+ { 0x9B, 2, "ADDA", DIR },
+ { 0x9C, 2, "CMPX", DIR },
+ { 0x9D, 2, "JSR", DIR , DASMFLAG_STEP_OVER },
+ { 0x9E, 2, "LDX", DIR },
+ { 0x9F, 2, "STX", DIR },
+
+ { 0xA0, 2, "SUBA", IND },
+ { 0xA1, 2, "CMPA", IND },
+ { 0xA2, 2, "SBCA", IND },
+ { 0xA3, 2, "SUBD", IND },
+ { 0xA4, 2, "ANDA", IND },
+ { 0xA5, 2, "BITA", IND },
+ { 0xA6, 2, "LDA", IND },
+ { 0xA7, 2, "STA", IND },
+ { 0xA8, 2, "EORA", IND },
+ { 0xA9, 2, "ADCA", IND },
+ { 0xAA, 2, "ORA", IND },
+ { 0xAB, 2, "ADDA", IND },
+ { 0xAC, 2, "CMPX", IND },
+ { 0xAD, 2, "JSR", IND , DASMFLAG_STEP_OVER },
+ { 0xAE, 2, "LDX", IND },
+ { 0xAF, 2, "STX", IND },
+
+ { 0xB0, 3, "SUBA", EXT },
+ { 0xB1, 3, "CMPA", EXT },
+ { 0xB2, 3, "SBCA", EXT },
+ { 0xB3, 3, "SUBD", EXT },
+ { 0xB4, 3, "ANDA", EXT },
+ { 0xB5, 3, "BITA", EXT },
+ { 0xB6, 3, "LDA", EXT },
+ { 0xB7, 3, "STA", EXT },
+ { 0xB8, 3, "EORA", EXT },
+ { 0xB9, 3, "ADCA", EXT },
+ { 0xBA, 3, "ORA", EXT },
+ { 0xBB, 3, "ADDA", EXT },
+ { 0xBC, 3, "CMPX", EXT },
+ { 0xBD, 3, "JSR", EXT , DASMFLAG_STEP_OVER },
+ { 0xBE, 3, "LDX", EXT },
+ { 0xBF, 3, "STX", EXT },
+
+ { 0xC0, 2, "SUBB", IMM },
+ { 0xC1, 2, "CMPB", IMM },
+ { 0xC2, 2, "SBCB", IMM },
+ { 0xC3, 3, "ADDD", IMM },
+ { 0xC4, 2, "ANDB", IMM },
+ { 0xC5, 2, "BITB", IMM },
+ { 0xC6, 2, "LDB", IMM },
+ { 0xC8, 2, "EORB", IMM },
+ { 0xC9, 2, "ADCB", IMM },
+ { 0xCA, 2, "ORB", IMM },
+ { 0xCB, 2, "ADDB", IMM },
+ { 0xCC, 3, "LDD", IMM },
+ { 0xCD, 5, "LDQ", IMM },
+ { 0xCE, 3, "LDU", IMM },
+
+ { 0xD0, 2, "SUBB", DIR },
+ { 0xD1, 2, "CMPB", DIR },
+ { 0xD2, 2, "SBCB", DIR },
+ { 0xD3, 2, "ADDD", DIR },
+ { 0xD4, 2, "ANDB", DIR },
+ { 0xD5, 2, "BITB", DIR },
+ { 0xD6, 2, "LDB", DIR },
+ { 0xD7, 2, "STB", DIR },
+ { 0xD8, 2, "EORB", DIR },
+ { 0xD9, 2, "ADCB", DIR },
+ { 0xDA, 2, "ORB", DIR },
+ { 0xDB, 2, "ADDB", DIR },
+ { 0xDC, 2, "LDD", DIR },
+ { 0xDD, 2, "STD", DIR },
+ { 0xDE, 2, "LDU", DIR },
+ { 0xDF, 2, "STU", DIR },
+
+ { 0xE0, 2, "SUBB", IND },
+ { 0xE1, 2, "CMPB", IND },
+ { 0xE2, 2, "SBCB", IND },
+ { 0xE3, 2, "ADDD", IND },
+ { 0xE4, 2, "ANDB", IND },
+ { 0xE5, 2, "BITB", IND },
+ { 0xE6, 2, "LDB", IND },
+ { 0xE7, 2, "STB", IND },
+ { 0xE8, 2, "EORB", IND },
+ { 0xE9, 2, "ADCB", IND },
+ { 0xEA, 2, "ORB", IND },
+ { 0xEB, 2, "ADDB", IND },
+ { 0xEC, 2, "LDD", IND },
+ { 0xED, 2, "STD", IND },
+ { 0xEE, 2, "LDU", IND },
+ { 0xEF, 2, "STU", IND },
+
+ { 0xF0, 3, "SUBB", EXT },
+ { 0xF1, 3, "CMPB", EXT },
+ { 0xF2, 3, "SBCB", EXT },
+ { 0xF3, 3, "ADDD", EXT },
+ { 0xF4, 3, "ANDB", EXT },
+ { 0xF5, 3, "BITB", EXT },
+ { 0xF6, 3, "LDB", EXT },
+ { 0xF7, 3, "STB", EXT },
+ { 0xF8, 3, "EORB", EXT },
+ { 0xF9, 3, "ADCB", EXT },
+ { 0xFA, 3, "ORB", EXT },
+ { 0xFB, 3, "ADDB", EXT },
+ { 0xFC, 3, "LDD", EXT },
+ { 0xFD, 3, "STD", EXT },
+ { 0xFE, 3, "LDU", EXT },
+ { 0xFF, 3, "STU", EXT }
+};
+
+// Page 1 opcodes (0x10 0x..)
+static const opcodeinfo hd6309_pg1opcodes[] =
+{
+ { 0x21, 4, "LBRN", LREL },
+ { 0x22, 4, "LBHI", LREL },
+ { 0x23, 4, "LBLS", LREL },
+ { 0x24, 4, "LBCC", LREL },
+ { 0x25, 4, "LBCS", LREL },
+ { 0x26, 4, "LBNE", LREL },
+ { 0x27, 4, "LBEQ", LREL },
+ { 0x28, 4, "LBVC", LREL },
+ { 0x29, 4, "LBVS", LREL },
+ { 0x2A, 4, "LBPL", LREL },
+ { 0x2B, 4, "LBMI", LREL },
+ { 0x2C, 4, "LBGE", LREL },
+ { 0x2D, 4, "LBLT", LREL },
+ { 0x2E, 4, "LBGT", LREL },
+ { 0x2F, 4, "LBLE", LREL },
+
+ { 0x30, 3, "ADDR", IMM_RR },
+ { 0x31, 3, "ADCR", IMM_RR },
+ { 0x32, 3, "SUBR", IMM_RR },
+ { 0x33, 3, "SBCR", IMM_RR },
+ { 0x34, 3, "ANDR", IMM_RR },
+ { 0x35, 3, "ORR", IMM_RR },
+ { 0x36, 3, "EORR", IMM_RR },
+ { 0x37, 3, "CMPR", IMM_RR },
+
+ { 0x38, 2, "PSHSW", INH },
+ { 0x39, 2, "PULSW", INH },
+ { 0x3A, 2, "PSHUW", INH },
+ { 0x3B, 2, "PULUW", INH },
+
+ { 0x3F, 2, "SWI2", INH },
+
+ { 0x40, 2, "NEGD", INH },
+ { 0x43, 2, "COMD", INH },
+ { 0x44, 2, "LSRD", INH },
+ { 0x46, 2, "RORD", INH },
+ { 0x47, 2, "ASRD", INH },
+ { 0x48, 2, "ASLD", INH },
+ { 0x49, 2, "ROLD", INH },
+
+ { 0x4A, 2, "DECD", INH },
+ { 0x4C, 2, "INCD", INH },
+ { 0x4D, 2, "TSTD", INH },
+ { 0x4f, 2, "CLRD", INH },
+
+ { 0x53, 2, "COMW", INH },
+ { 0x54, 2, "LSRW", INH },
+ { 0x56, 2, "RORW", INH },
+ { 0x59, 2, "ROLW", INH },
+ { 0x5A, 2, "DECW", INH },
+ { 0x5C, 2, "INCW", INH },
+ { 0x5D, 2, "TSTW", INH },
+ { 0x5F, 2, "CLRW", INH },
+ { 0x80, 4, "SUBW", IMM },
+ { 0x81, 4, "CMPW", IMM },
+ { 0x82, 4, "SBCD", IMM },
+
+ { 0x83, 4, "CMPD", IMM },
+
+ { 0x84, 4, "ANDD", IMM },
+ { 0x85, 4, "BITD", IMM },
+ { 0x86, 4, "LDW", IMM },
+ { 0x88, 4, "EORD", IMM },
+ { 0x89, 4, "ADCD", IMM },
+ { 0x8A, 4, "ORD", IMM },
+ { 0x8B, 4, "ADDW", IMM },
+
+ { 0x8C, 4, "CMPY", IMM },
+ { 0x8E, 4, "LDY", IMM },
+
+ { 0x90, 3, "SUBW", DIR },
+ { 0x91, 3, "CMPW", DIR },
+ { 0x92, 3, "SBCD", DIR },
+
+ { 0x93, 3, "CMPD", DIR },
+
+ { 0x94, 3, "ANDD", DIR },
+ { 0x95, 3, "BITD", DIR },
+ { 0x96, 3, "LDW", DIR },
+ { 0x97, 3, "STW", DIR },
+ { 0x98, 3, "EORD", DIR },
+ { 0x99, 3, "ADCD", DIR },
+ { 0x9A, 3, "ORD", DIR },
+ { 0x9B, 3, "ADDW", DIR },
+
+ { 0x9C, 3, "CMPY", DIR },
+ { 0x9E, 3, "LDY", DIR },
+ { 0x9F, 3, "STY", DIR },
+
+ { 0xA0, 3, "SUBW", IND },
+ { 0xA1, 3, "CMPW", IND },
+ { 0xA2, 3, "SBCD", IND },
+
+ { 0xA3, 3, "CMPD", IND },
+
+ { 0xA4, 3, "ANDD", IND },
+ { 0xA5, 3, "BITD", IND },
+
+ { 0xA6, 3, "LDW", IND },
+ { 0xA7, 3, "STW", IND },
+ { 0xA8, 3, "EORD", IND },
+ { 0xA9, 3, "ADCD", IND },
+ { 0xAA, 3, "ORD", IND },
+ { 0xAB, 3, "ADDW", IND },
+
+ { 0xAC, 3, "CMPY", IND },
+ { 0xAE, 3, "LDY", IND },
+ { 0xAF, 3, "STY", IND },
+
+ { 0xB0, 4, "SUBW", EXT },
+ { 0xB1, 4, "CMPW", EXT },
+ { 0xB2, 4, "SBCD", EXT },
+
+ { 0xB3, 4, "CMPD", EXT },
+
+ { 0xB4, 4, "ANDD", EXT },
+ { 0xB5, 4, "BITD", EXT },
+ { 0xB6, 4, "LDW", EXT },
+ { 0xB7, 4, "STW", EXT },
+ { 0xB8, 4, "EORD", EXT },
+ { 0xB9, 4, "ADCD", EXT },
+ { 0xBA, 4, "ORD", EXT },
+ { 0xBB, 4, "ADDW", EXT },
+
+ { 0xBC, 4, "CMPY", EXT },
+ { 0xBE, 4, "LDY", EXT },
+ { 0xBF, 4, "STY", EXT },
+ { 0xCE, 4, "LDS", IMM },
+
+ { 0xDC, 3, "LDQ", DIR },
+ { 0xDD, 3, "STQ", DIR },
+
+ { 0xDE, 3, "LDS", DIR },
+ { 0xDF, 3, "STS", DIR },
+
+ { 0xEC, 3, "LDQ", IND },
+ { 0xED, 3, "STQ", IND },
+ { 0xEE, 3, "LDS", IND },
+
+ { 0xEE, 3, "LDS", IND },
+ { 0xEF, 3, "STS", IND },
+
+ { 0xFC, 4, "LDQ", EXT },
+ { 0xFD, 4, "STQ", EXT },
+
+ { 0xFE, 4, "LDS", EXT },
+ { 0xFF, 4, "STS", EXT }
+};
+
+// Page 2 opcodes (0x11 0x..)
+static const opcodeinfo hd6309_pg2opcodes[] =
+{
+ { 0x30, 4, "BAND", IMM_BW },
+ { 0x31, 4, "BIAND", IMM_BW },
+ { 0x32, 4, "BOR", IMM_BW },
+ { 0x33, 4, "BIOR", IMM_BW },
+ { 0x34, 4, "BEOR", IMM_BW },
+ { 0x35, 4, "BIEOR", IMM_BW },
+
+ { 0x36, 4, "LDBT", IMM_BW },
+ { 0x37, 4, "STBT", IMM_BW },
+
+ { 0x38, 3, "TFM", IMM_TFM },
+ { 0x39, 3, "TFM", IMM_TFM },
+ { 0x3A, 3, "TFM", IMM_TFM },
+ { 0x3B, 3, "TFM", IMM_TFM },
+
+ { 0x3C, 3, "BITMD", IMM },
+ { 0x3D, 3, "LDMD", IMM },
+
+ { 0x3F, 2, "SWI3", INH },
+
+ { 0x43, 2, "COME", INH },
+ { 0x4A, 2, "DECE", INH },
+ { 0x4C, 2, "INCE", INH },
+ { 0x4D, 2, "TSTE", INH },
+ { 0x4F, 2, "CLRE", INH },
+ { 0x53, 2, "COMF", INH },
+ { 0x5A, 2, "DECF", INH },
+ { 0x5C, 2, "INCF", INH },
+ { 0x5D, 2, "TSTF", INH },
+ { 0x5F, 2, "CLRF", INH },
+
+ { 0x80, 3, "SUBE", IMM },
+ { 0x81, 3, "CMPE", IMM },
+
+ { 0x83, 4, "CMPU", IMM },
+
+ { 0x86, 3, "LDE", IMM },
+ { 0x8b, 3, "ADDE", IMM },
+
+ { 0x8C, 4, "CMPS", IMM },
+
+ { 0x8D, 3, "DIVD", IMM },
+ { 0x8E, 4, "DIVQ", IMM },
+ { 0x8F, 4, "MULD", IMM },
+ { 0x90, 3, "SUBE", DIR },
+ { 0x91, 3, "CMPE", DIR },
+
+ { 0x93, 3, "CMPU", DIR },
+
+ { 0x96, 3, "LDE", DIR },
+ { 0x97, 3, "STE", DIR },
+ { 0x9B, 3, "ADDE", DIR },
+
+ { 0x9C, 3, "CMPS", DIR },
+
+ { 0x9D, 3, "DIVD", DIR },
+ { 0x9E, 3, "DIVQ", DIR },
+ { 0x9F, 3, "MULD", DIR },
+
+ { 0xA0, 3, "SUBE", IND },
+ { 0xA1, 3, "CMPE", IND },
+
+ { 0xA3, 3, "CMPU", IND },
+
+ { 0xA6, 3, "LDE", IND },
+ { 0xA7, 3, "STE", IND },
+ { 0xAB, 3, "ADDE", IND },
+
+ { 0xAC, 3, "CMPS", IND },
+
+ { 0xAD, 3, "DIVD", IND },
+ { 0xAE, 3, "DIVQ", IND },
+ { 0xAF, 3, "MULD", IND },
+ { 0xB0, 4, "SUBE", EXT },
+ { 0xB1, 4, "CMPE", EXT },
+
+ { 0xB3, 4, "CMPU", EXT },
+
+ { 0xB6, 4, "LDE", EXT },
+ { 0xB7, 4, "STE", EXT },
+
+ { 0xBB, 4, "ADDE", EXT },
+ { 0xBC, 4, "CMPS", EXT },
+
+ { 0xBD, 4, "DIVD", EXT },
+ { 0xBE, 4, "DIVQ", EXT },
+ { 0xBF, 4, "MULD", EXT },
+
+ { 0xC0, 3, "SUBF", IMM },
+ { 0xC1, 3, "CMPF", IMM },
+ { 0xC6, 3, "LDF", IMM },
+ { 0xCB, 3, "ADDF", IMM },
+
+ { 0xD0, 3, "SUBF", DIR },
+ { 0xD1, 3, "CMPF", DIR },
+ { 0xD6, 3, "LDF", DIR },
+ { 0xD7, 3, "STF", DIR },
+ { 0xDB, 3, "ADDF", DIR },
+
+ { 0xE0, 3, "SUBF", IND },
+ { 0xE1, 3, "CMPF", IND },
+ { 0xE6, 3, "LDF", IND },
+ { 0xE7, 3, "STF", IND },
+ { 0xEB, 3, "ADDF", IND },
+
+ { 0xF0, 4, "SUBF", EXT },
+ { 0xF1, 4, "CMPF", EXT },
+ { 0xF6, 4, "LDF", EXT },
+ { 0xF7, 4, "STF", EXT },
+ { 0xFB, 4, "ADDF", EXT }
+};
+
+static const opcodeinfo *const hd6309_pgpointers[3] =
+{
+ hd6309_pg0opcodes, hd6309_pg1opcodes, hd6309_pg2opcodes
+};
+
+static const int hd6309_numops[3] =
+{
+ sizeof(hd6309_pg0opcodes) / sizeof(hd6309_pg0opcodes[0]),
+ sizeof(hd6309_pg1opcodes) / sizeof(hd6309_pg1opcodes[0]),
+ sizeof(hd6309_pg2opcodes) / sizeof(hd6309_pg2opcodes[0])
+};
+
+static const char *const hd6309_regs[5] = { "X", "Y", "U", "S", "PC" };
+
+static const char *const hd6309_btwregs[5] = { "CC", "A", "B", "inv" };
+
+static const char *const hd6309_teregs[16] =
+{
+ "D", "X", "Y", "U", "S", "PC", "W", "V",
+ "A", "B", "CC", "DP", "0", "0", "E", "F"
+};
+
+static const char *const hd6309_tfmregs[16] = {
+ "D", "X", "Y", "U", "S", "inv", "inv", "inv",
+ "inv", "inv", "inv", "inv", "inv", "inv", "inv", "inv"
+};
+
+static const char *const tfm_s[] = { "%s+,%s+", "%s-,%s-", "%s+,%s", "%s,%s+" };
+
+CPU_DISASSEMBLE( hd6309 )
+{
+ UINT8 opcode, mode, pb, pbm, reg;
+ const UINT8 *operandarray;
+ unsigned int ea, flags;
+ int numoperands, offset, indirect;
+
+ int i, p = 0, page = 0, opcode_found = FALSE;
+
+ do
+ {
+ opcode = oprom[p++];
+ for (i = 0; i < hd6309_numops[page]; i++)
+ if (hd6309_pgpointers[page][i].opcode == opcode)
+ break;
+
+ if (i < hd6309_numops[page])
+ opcode_found = TRUE;
+ else
+ {
+ strcpy(buffer, "Illegal Opcode");
+ return p | DASMFLAG_SUPPORTED;
+ }
+
+ if (hd6309_pgpointers[page][i].mode >= PG1)
+ {
+ page = hd6309_pgpointers[page][i].mode - PG1 + 1;
+ opcode_found = FALSE;
+ }
+ } while (!opcode_found);
+
+ if (page == 0)
+ numoperands = hd6309_pgpointers[page][i].length - 1;
+ else
+ numoperands = hd6309_pgpointers[page][i].length - 2;
+
+ operandarray = &opram[p];
+ p += numoperands;
+ pc += p;
+ mode = hd6309_pgpointers[page][i].mode;
+ flags = hd6309_pgpointers[page][i].flags;
+
+ buffer += sprintf(buffer, "%-6s", hd6309_pgpointers[page][i].name);
+
+ switch (mode)
+ {
+ case INH:
+ switch (opcode)
+ {
+ case 0x34: // PSHS
+ case 0x36: // PSHU
+ pb = operandarray[0];
+ if (pb & 0x80)
+ buffer += sprintf(buffer, "PC");
+ if (pb & 0x40)
+ buffer += sprintf(buffer, "%s%s", (pb&0x80)?",":"", (opcode==0x34)?"U":"S");
+ if (pb & 0x20)
+ buffer += sprintf(buffer, "%sY", (pb&0xc0)?",":"");
+ if (pb & 0x10)
+ buffer += sprintf(buffer, "%sX", (pb&0xe0)?",":"");
+ if (pb & 0x08)
+ buffer += sprintf(buffer, "%sDP", (pb&0xf0)?",":"");
+ if (pb & 0x04)
+ buffer += sprintf(buffer, "%sB", (pb&0xf8)?",":"");
+ if (pb & 0x02)
+ buffer += sprintf(buffer, "%sA", (pb&0xfc)?",":"");
+ if (pb & 0x01)
+ buffer += sprintf(buffer, "%sCC", (pb&0xfe)?",":"");
+ break;
+ case 0x35: // PULS
+ case 0x37: // PULU
+ pb = operandarray[0];
+ if (pb & 0x01)
+ buffer += sprintf(buffer, "CC");
+ if (pb & 0x02)
+ buffer += sprintf(buffer, "%sA", (pb&0x01)?",":"");
+ if (pb & 0x04)
+ buffer += sprintf(buffer, "%sB", (pb&0x03)?",":"");
+ if (pb & 0x08)
+ buffer += sprintf(buffer, "%sDP", (pb&0x07)?",":"");
+ if (pb & 0x10)
+ buffer += sprintf(buffer, "%sX", (pb&0x0f)?",":"");
+ if (pb & 0x20)
+ buffer += sprintf(buffer, "%sY", (pb&0x1f)?",":"");
+ if (pb & 0x40)
+ buffer += sprintf(buffer, "%s%s", (pb&0x3f)?",":"", (opcode==0x35)?"U":"S");
+ if (pb & 0x80)
+ buffer += sprintf(buffer, "%sPC ; (PUL? PC=RTS)", (pb&0x7f)?",":"");
+ break;
+ default:
+ // No operands
+ break;
+ }
+ break;
+
+ case DIR:
+ ea = operandarray[0];
+ buffer += sprintf(buffer, "$%02X", ea);
+ break;
+
+ case DIR_IM:
+ buffer += sprintf(buffer, "#$%02X,", operandarray[0]);
+ buffer += sprintf(buffer, "$%02X", operandarray[1]);
+ break;
+
+ case REL:
+ offset = (INT8)operandarray[0];
+ buffer += sprintf(buffer, "$%04X", (pc + offset) & 0xffff);
+ break;
+
+ case LREL:
+ offset = (INT16)((operandarray[0] << 8) + operandarray[1]);
+ buffer += sprintf(buffer, "$%04X", (pc + offset) & 0xffff);
+ break;
+
+ case EXT:
+ if (numoperands == 3)
+ {
+ pb = operandarray[0];
+ ea = (operandarray[1] << 8) + operandarray[2];
+ buffer += sprintf(buffer, "#$%02X,$%04X", pb, ea);
+ }
+ else
+ if (numoperands == 2)
+ {
+ ea = (operandarray[0] << 8) + operandarray[1];
+ buffer += sprintf(buffer, "$%04X", ea);
+ }
+ break;
+
+ case IND:
+ if (numoperands == 2)
+ {
+ buffer += sprintf(buffer, "#$%02X,", operandarray[0]);
+ pb = operandarray[1];
+ }
+ else
+ {
+ pb = operandarray[0];
+ }
+
+ reg = (pb >> 5) & 3;
+ pbm = pb & 0x8f;
+ indirect = ((pb & 0x90) == 0x90 )? TRUE : FALSE;
+
+ // open brackets if indirect
+ if (indirect && pbm != 0x82)
+ buffer += sprintf(buffer, "[");
+
+ switch (pbm)
+ {
+ case 0x80: // ,R+ or operations relative to W
+ if (indirect)
+ {
+ switch (reg)
+ {
+ case 0x00:
+ buffer += sprintf(buffer, ",W");
+ break;
+ case 0x01:
+ offset = (INT16)((opram[p+0] << 8) + opram[p+1]);
+ p += 2;
+ buffer += sprintf(buffer, "%s", (offset < 0) ? "-" : "");
+ buffer += sprintf(buffer, "$%04X,W", (offset < 0) ? -offset : offset);
+ break;
+ case 0x02:
+ buffer += sprintf(buffer, ",W++");
+ break;
+ case 0x03:
+ buffer += sprintf(buffer, ",--W");
+ break;
+ }
+ }
+ else
+ buffer += sprintf(buffer, ",%s+", hd6309_regs[reg]);
+ break;
+
+ case 0x81: // ,R++
+ buffer += sprintf(buffer, ",%s++", hd6309_regs[reg]);
+ break;
+
+ case 0x82: // ,-R
+ if (indirect)
+ strcpy(buffer, "Illegal Postbyte");
+ else
+ buffer += sprintf(buffer, ",-%s", hd6309_regs[reg]);
+ break;
+
+ case 0x83: // ,--R
+ buffer += sprintf(buffer, ",--%s", hd6309_regs[reg]);
+ break;
+
+ case 0x84: // ,R
+ buffer += sprintf(buffer, ",%s", hd6309_regs[reg]);
+ break;
+
+ case 0x85: // (+/- B),R
+ buffer += sprintf(buffer, "B,%s", hd6309_regs[reg]);
+ break;
+
+ case 0x86: // (+/- A),R
+ buffer += sprintf(buffer, "A,%s", hd6309_regs[reg]);
+ break;
+
+ case 0x87: // (+/- E),R
+ buffer += sprintf(buffer, "E,%s", hd6309_regs[reg]);
+ break;
+
+ case 0x88: // (+/- 7 bit offset),R
+ offset = (INT8)opram[p++];
+ buffer += sprintf(buffer, "%s", (offset < 0) ? "-" : "");
+ buffer += sprintf(buffer, "$%02X,", (offset < 0) ? -offset : offset);
+ buffer += sprintf(buffer, "%s", hd6309_regs[reg]);
+ break;
+
+ case 0x89: // (+/- 15 bit offset),R
+ offset = (INT16)((opram[p+0] << 8) + opram[p+1]);
+ p += 2;
+ buffer += sprintf(buffer, "%s", (offset < 0) ? "-" : "");
+ buffer += sprintf(buffer, "$%04X,", (offset < 0) ? -offset : offset);
+ buffer += sprintf(buffer, "%s", hd6309_regs[reg]);
+ break;
+
+ case 0x8a: // (+/- F),R
+ buffer += sprintf(buffer, "F,%s", hd6309_regs[reg]);
+ break;
+
+ case 0x8b: // (+/- D),R
+ buffer += sprintf(buffer, "D,%s", hd6309_regs[reg]);
+ break;
+
+ case 0x8c: // (+/- 7 bit offset),PC
+ offset = (INT8)opram[p++];
+ buffer += sprintf(buffer, "%s", (offset < 0) ? "-" : "");
+ buffer += sprintf(buffer, "$%02X,PC", (offset < 0) ? -offset : offset);
+ break;
+
+ case 0x8d: // (+/- 15 bit offset),PC
+ offset = (INT16)((opram[p+0] << 8) + opram[p+1]);
+ p += 2;
+ buffer += sprintf(buffer, "%s", (offset < 0) ? "-" : "");
+ buffer += sprintf(buffer, "$%04X,PC", (offset < 0) ? -offset : offset);
+ break;
+
+ case 0x8e: // (+/- W),R
+ buffer += sprintf(buffer, "W,%s", hd6309_regs[reg]);
+ break;
+
+ case 0x8f: // address or operations relative to W
+ if (indirect)
+ {
+ ea = (UINT16)((opram[p+0] << 8) + opram[p+1]);
+ p += 2;
+ buffer += sprintf(buffer, "$%04X", ea);
+ break;
+ }
+ else
+ {
+ switch (reg)
+ {
+ case 0x00:
+ buffer += sprintf(buffer, ",W");
+ break;
+ case 0x01:
+ offset = (INT16)((opram[p+0] << 8) + opram[p+1]);
+ p += 2;
+ buffer += sprintf(buffer, "%s", (offset < 0) ? "-" : "");
+ buffer += sprintf(buffer, "$%04X,W", (offset < 0) ? -offset : offset);
+ break;
+ case 0x02:
+ buffer += sprintf(buffer, ",W++");
+ break;
+ case 0x03:
+ buffer += sprintf(buffer, ",--W");
+ break;
+ }
+ }
+ break;
+
+ default: // (+/- 4 bit offset),R
+ offset = pb & 0x1f;
+ if (offset > 15)
+ offset = offset - 32;
+ buffer += sprintf(buffer, "%s", (offset < 0) ? "-" : "");
+ buffer += sprintf(buffer, "$%X,", (offset < 0) ? -offset : offset);
+ buffer += sprintf(buffer, "%s", hd6309_regs[reg]);
+ break;
+ }
+
+ // close brackets if indirect
+ if (indirect && pbm != 0x82)
+ buffer += sprintf(buffer, "]");
+ break;
+
+ case IMM:
+ if (numoperands == 4)
+ {
+ ea = (operandarray[0] << 24) + (operandarray[1] << 16) + (operandarray[2] << 8) + operandarray[3];
+ buffer += sprintf(buffer, "#$%08X", ea);
+ }
+ else
+ if (numoperands == 2)
+ {
+ ea = (operandarray[0] << 8) + operandarray[1];
+ buffer += sprintf(buffer, "#$%04X", ea);
+ }
+ else
+ if (numoperands == 1)
+ {
+ ea = operandarray[0];
+ buffer += sprintf(buffer, "#$%02X", ea);
+ }
+ break;
+
+ case IMM_RR:
+ pb = operandarray[0];
+ buffer += sprintf(buffer, "%s,%s", hd6309_teregs[(pb >> 4) & 0xf], hd6309_teregs[pb & 0xf]);
+ break;
+
+ case IMM_BW:
+ pb = operandarray[0];
+ buffer += sprintf(buffer, "%s,", hd6309_btwregs[((pb & 0xc0) >> 6)]);
+ buffer += sprintf(buffer, "%d,", (pb & 0x38) >> 3);
+ buffer += sprintf(buffer, "%d,", (pb & 0x07));
+ buffer += sprintf(buffer, "$%02X", operandarray[1]);
+ break;
+
+ case IMM_TFM:
+ pb = operandarray[0];
+ buffer += sprintf(buffer, tfm_s[opcode & 0x07], hd6309_tfmregs[(pb >> 4) & 0xf], hd6309_tfmregs[pb & 0xf]);
+ break;
+ }
+
+ return p | flags | DASMFLAG_SUPPORTED;
+}
diff --git a/trunk/src/emu/cpu/hd6309/6309ops.c b/trunk/src/emu/cpu/hd6309/6309ops.c
new file mode 100644
index 00000000000..533185b0e54
--- /dev/null
+++ b/trunk/src/emu/cpu/hd6309/6309ops.c
@@ -0,0 +1,5535 @@
+/*
+
+HNZVC
+
+? = undefined
+* = affected
+- = unaffected
+0 = cleared
+1 = set
+# = CCr directly affected by instruction
+@ = special - carry set if bit 7 is set
+
+*/
+
+#define OP_HANDLER(_name) INLINE void _name (m68_state_t *m68_state)
+
+OP_HANDLER( illegal )
+{
+ LOG(("HD6309: illegal opcode at %04x\nVectoring to [$fff0]\n",PC));
+
+ CC |= CC_E;
+ PUSHWORD(pPC);
+ PUSHWORD(pU);
+ PUSHWORD(pY);
+ PUSHWORD(pX);
+ PUSHBYTE(DP);
+
+ if ( MD & MD_EM )
+ {
+ PUSHBYTE(F);
+ PUSHBYTE(E);
+ m68_state->icount -= 2;
+ }
+
+ PUSHBYTE(B);
+ PUSHBYTE(A);
+ PUSHBYTE(CC);
+
+ PCD = RM16(m68_state, 0xfff0);
+}
+
+static void IIError(m68_state_t *m68_state)
+{
+ SEII; // Set illegal Instruction Flag
+ illegal(m68_state); // Vector to Trap handler
+}
+
+static void DZError(m68_state_t *m68_state)
+{
+ SEDZ; // Set Division by Zero Flag
+ illegal(m68_state); // Vector to Trap handler
+}
+
+/* $00 NEG direct ?**** */
+OP_HANDLER( neg_di )
+{
+ UINT16 r,t;
+ DIRBYTE(t);
+ r = -t;
+ CLR_NZVC;
+ SET_FLAGS8(0,t,r);
+ WM(EAD,r);
+}
+
+/* $01 OIM direct ?**** */
+OP_HANDLER( oim_di )
+{
+ UINT8 r,t,im;
+ IMMBYTE(im);
+ DIRBYTE(t);
+ r = im | t;
+ CLR_NZV;
+ SET_NZ8(r);
+ WM(EAD,r);
+}
+
+/* $02 AIM direct */
+OP_HANDLER( aim_di )
+{
+ UINT8 r,t,im;
+ IMMBYTE(im);
+ DIRBYTE(t);
+ r = im & t;
+ CLR_NZV;
+ SET_NZ8(r);
+ WM(EAD,r);
+}
+
+/* $03 COM direct -**01 */
+OP_HANDLER( com_di )
+{
+ UINT8 t;
+ DIRBYTE(t);
+ t = ~t;
+ CLR_NZV;
+ SET_NZ8(t);
+ SEC;
+ WM(EAD,t);
+}
+
+/* $04 LSR direct -0*-* */
+OP_HANDLER( lsr_di )
+{
+ UINT8 t;
+ DIRBYTE(t);
+ CLR_NZC;
+ CC |= (t & CC_C);
+ t >>= 1;
+ SET_Z8(t);
+ WM(EAD,t);
+}
+
+/* $05 EIM direct */
+OP_HANDLER( eim_di )
+{
+ UINT8 r,t,im;
+ IMMBYTE(im);
+ DIRBYTE(t);
+ r = im ^ t;
+ CLR_NZV;
+ SET_NZ8(r);
+ WM(EAD,r);
+}
+
+/* $06 ROR direct -**-* */
+OP_HANDLER( ror_di )
+{
+ UINT8 t,r;
+ DIRBYTE(t);
+ r= (CC & CC_C) << 7;
+ CLR_NZC;
+ CC |= (t & CC_C);
+ r |= t>>1;
+ SET_NZ8(r);
+ WM(EAD,r);
+}
+
+/* $07 ASR direct ?**-* */
+OP_HANDLER( asr_di )
+{
+ UINT8 t;
+ DIRBYTE(t);
+ CLR_NZC;
+ CC |= (t & CC_C);
+ t = (t & 0x80) | (t >> 1);
+ SET_NZ8(t);
+ WM(EAD,t);
+}
+
+/* $08 ASL direct ?**** */
+OP_HANDLER( asl_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = t << 1;
+ CLR_NZVC;
+ SET_FLAGS8(t,t,r);
+ WM(EAD,r);
+}
+
+/* $09 ROL direct -**** */
+OP_HANDLER( rol_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = (CC & CC_C) | (t << 1);
+ CLR_NZVC;
+ SET_FLAGS8(t,t,r);
+ WM(EAD,r);
+}
+
+/* $0A DEC direct -***- */
+OP_HANDLER( dec_di )
+{
+ UINT8 t;
+ DIRBYTE(t);
+ --t;
+ CLR_NZV;
+ SET_FLAGS8D(t);
+ WM(EAD,t);
+}
+
+/* $0B TIM direct */
+OP_HANDLER( tim_di )
+{
+ UINT8 r,t,im;
+ IMMBYTE(im);
+ DIRBYTE(t);
+ r = im & t;
+ CLR_NZV;
+ SET_NZ8(r);
+}
+
+/* $OC INC direct -***- */
+OP_HANDLER( inc_di )
+{
+ UINT8 t;
+ DIRBYTE(t);
+ ++t;
+ CLR_NZV;
+ SET_FLAGS8I(t);
+ WM(EAD,t);
+}
+
+/* $OD TST direct -**0- */
+OP_HANDLER( tst_di )
+{
+ UINT8 t;
+ DIRBYTE(t);
+ CLR_NZV;
+ SET_NZ8(t);
+}
+
+/* $0E JMP direct ----- */
+OP_HANDLER( jmp_di )
+{
+ DIRECT;
+ PCD = EAD;
+}
+
+/* $0F CLR direct -0100 */
+OP_HANDLER( clr_di )
+{
+ DIRECT;
+ (void)RM(EAD);
+ WM(EAD,0);
+ CLR_NZVC;
+ SEZ;
+}
+
+/* $10 FLAG */
+
+/* $11 FLAG */
+
+/* $12 NOP inherent ----- */
+OP_HANDLER( nop )
+{
+ ;
+}
+
+/* $13 SYNC inherent ----- */
+OP_HANDLER( sync )
+{
+ /* SYNC stops processing instructions until an interrupt request happens. */
+ /* This doesn't require the corresponding interrupt to be enabled: if it */
+ /* is disabled, execution continues with the next instruction. */
+ m68_state->int_state |= M6809_SYNC; /* HJB 990227 */
+ check_irq_lines(m68_state);
+ /* if M6809_SYNC has not been cleared by check_irq_lines(m68_state),
+ * stop execution until the interrupt lines change. */
+ if( m68_state->int_state & M6809_SYNC )
+ if (m68_state->icount > 0) m68_state->icount = 0;
+}
+
+/* $14 sexw inherent */
+OP_HANDLER( sexw )
+{
+ PAIR q;
+ q.d = SIGNED_16(W);
+ D = q.w.h;
+ W = q.w.l;
+ CLR_NZ;
+ SET_N16(D);
+ SET_Z(q.d);
+}
+
+/* $15 ILLEGAL */
+
+/* $16 LBRA relative ----- */
+OP_HANDLER( lbra )
+{
+ IMMWORD(EAP);
+ PC += EA;
+}
+
+/* $17 LBSR relative ----- */
+OP_HANDLER( lbsr )
+{
+ IMMWORD(EAP);
+ PUSHWORD(pPC);
+ PC += EA;
+}
+
+/* $18 ILLEGAL */
+
+/* $19 DAA inherent (A) -**0* */
+OP_HANDLER( daa )
+{
+ UINT8 msn, lsn;
+ UINT16 t, cf = 0;
+ msn = A & 0xf0; lsn = A & 0x0f;
+ if( lsn>0x09 || CC & CC_H) cf |= 0x06;
+ if( msn>0x80 && lsn>0x09 ) cf |= 0x60;
+ if( msn>0x90 || CC & CC_C) cf |= 0x60;
+ t = cf + A;
+ CLR_NZV; /* keep carry from previous operation */
+ SET_NZ8((UINT8)t); SET_C8(t);
+ A = t;
+}
+
+/* $1A ORCC immediate ##### */
+OP_HANDLER( orcc )
+{
+ UINT8 t;
+ IMMBYTE(t);
+ CC |= t;
+ check_irq_lines(m68_state); /* HJB 990116 */
+}
+
+/* $1B ILLEGAL */
+
+/* $1C ANDCC immediate ##### */
+OP_HANDLER( andcc )
+{
+ UINT8 t;
+ IMMBYTE(t);
+ CC &= t;
+ check_irq_lines(m68_state); /* HJB 990116 */
+}
+
+/* $1D SEX inherent -**-- */
+OP_HANDLER( sex )
+{
+ UINT16 t;
+ t = SIGNED(B);
+ D = t;
+ // CLR_NZV; Tim Lindner 20020905: verified that V flag is not affected
+ CLR_NZ;
+ SET_NZ16(t);
+}
+
+/* $1E EXG inherent ----- */
+OP_HANDLER( exg )
+{
+ UINT16 t1,t2;
+ UINT8 tb;
+ int promote = FALSE;
+
+ IMMBYTE(tb);
+ if( (tb^(tb>>4)) & 0x08 ) /* HJB 990225: mixed 8/16 bit case? */
+ {
+ promote = TRUE;
+ }
+
+ switch(tb>>4) {
+ case 0: t1 = D; break;
+ case 1: t1 = X; break;
+ case 2: t1 = Y; break;
+ case 3: t1 = U; break;
+ case 4: t1 = S; break;
+ case 5: t1 = PC; break;
+ case 6: t1 = W; break;
+ case 7: t1 = V; break;
+ case 8: t1 = (promote ? A + ((A) << 8) : A); break;
+ case 9: t1 = (promote ? B + ((B) << 8) : B); break;
+ case 10: t1 = (promote ? CC + ((CC) << 8) : CC); break;
+ case 11: t1 = (promote ? DP + ((DP) << 8) : DP); break;
+ case 12: t1 = 0; break;
+ case 13: t1 = 0; break;
+ case 14: t1 = (promote ? E + ((E) << 8) : E); break;
+ default: t1 = (promote ? F + ((F) << 8) : F); break;
+ }
+ switch(tb&15) {
+ case 0: t2 = D; break;
+ case 1: t2 = X; break;
+ case 2: t2 = Y; break;
+ case 3: t2 = U; break;
+ case 4: t2 = S; break;
+ case 5: t2 = PC; break;
+ case 6: t2 = W; break;
+ case 7: t2 = V; break;
+ case 8: t2 = (promote ? A + ((A) << 8) : A); break;
+ case 9: t2 = (promote ? B + ((B) << 8) : B); break;
+ case 10: t2 = (promote ? CC + ((CC) << 8) : CC); break;
+ case 11: t2 = (promote ? DP + ((DP) << 8) : DP); break;
+ case 12: t2 = 0; break;
+ case 13: t2 = 0; break;
+ case 14: t2 = (promote ? E + ((E) << 8) : E); break;
+ default: t2 = (promote ? F + ((F) << 8) : F); break;
+ }
+
+ switch(tb>>4) {
+ case 0: D = t2; break;
+ case 1: X = t2; break;
+ case 2: Y = t2; break;
+ case 3: U = t2; break;
+ case 4: S = t2; break;
+ case 5: PC = t2; break;
+ case 6: W = t2; break;
+ case 7: V = t2; break;
+ case 8: A = (promote ? t2 >> 8 : t2); break;
+ case 9: B = (promote ? t2 & 0xff : t2); break;
+ case 10: CC = (promote ? t2 & 0xff : t2); break;
+ case 11: DP = (promote ? t2 >> 8 : t2); break;
+ case 12: /* 0 = t2 */ break;
+ case 13: /* 0 = t2 */ break;
+ case 14: E = (promote ? t2 >> 8 : t2); break;
+ case 15: F = (promote ? t2 & 0xff : t2); break;
+ }
+ switch(tb&15) {
+ case 0: D = t1; break;
+ case 1: X = t1; break;
+ case 2: Y = t1; break;
+ case 3: U = t1; break;
+ case 4: S = t1; break;
+ case 5: PC = t1; break;
+ case 6: W = t1; break;
+ case 7: V = t1; break;
+ case 8: A = (promote ? t1 >> 8 : t1); break;
+ case 9: B = (promote ? t1 & 0xff : t1); break;
+ case 10: CC = (promote ? t1 & 0xff : t1); break;
+ case 11: DP = (promote ? t1 >> 8 : t1); break;
+ case 12: /* 0 = t1 */ break;
+ case 13: /* 0 = t1 */ break;
+ case 14: E = (promote ? t1 >> 8 : t1); break;
+ case 15: F = (promote ? t1 & 0xff : t1); break;
+ }
+}
+
+/* $1F TFR inherent ----- */
+OP_HANDLER( tfr )
+{
+ UINT8 tb;
+ UINT16 t;
+ int promote = FALSE;
+
+ IMMBYTE(tb);
+ if( (tb^(tb>>4)) & 0x08 )
+ {
+ promote = TRUE;
+ }
+
+ switch(tb>>4) {
+ case 0: t = D; break;
+ case 1: t = X; break;
+ case 2: t = Y; break;
+ case 3: t = U; break;
+ case 4: t = S; break;
+ case 5: t = PC; break;
+ case 6: t = W; break;
+ case 7: t = V; break;
+ case 8: t = (promote ? A + ((A) << 8) : A); break;
+ case 9: t = (promote ? B + ((B) << 8) : B); break;
+ case 10: t = (promote ? CC + ((CC) << 8) : CC); break;
+ case 11: t = (promote ? DP + ((DP) << 8) : DP); break;
+ case 12: t = 0; break;
+ case 13: t = 0; break;
+ case 14: t = (promote ? E + ((E) << 8) : E); break;
+ default: t = (promote ? F + ((F) << 8) : F); break;
+ }
+
+ switch(tb&15) {
+ case 0: D = t; break;
+ case 1: X = t; break;
+ case 2: Y = t; break;
+ case 3: U = t; break;
+ case 4: S = t; break;
+ case 5: PC = t; break;
+ case 6: W = t; break;
+ case 7: V = t; break;
+ case 8: A = (promote ? t >> 8 : t); break;
+ case 9: B = (promote ? t & 0xff : t); break;
+ case 10: CC = (promote ? t & 0xff : t); break;
+ case 11: DP = (promote ? t >> 8 : t); break;
+ case 12: /* 0 = t */ break;
+ case 13: /* 0 = t */ break;
+ case 14: E = (promote ? t >> 8 : t); break;
+ case 15: F = (promote ? t & 0xff : t); break;
+ }
+}
+
+/* $20 BRA relative ----- */
+OP_HANDLER( bra )
+{
+ UINT8 t;
+ IMMBYTE(t);
+ PC += SIGNED(t);
+}
+
+/* $21 BRN relative ----- */
+static UINT8 brn_temp; // hack around GCC 4.6 error because we need the side effects of IMMBYTE
+OP_HANDLER( brn )
+{
+ IMMBYTE(brn_temp);
+}
+
+/* $1021 LBRN relative ----- */
+OP_HANDLER( lbrn )
+{
+ IMMWORD(EAP);
+}
+
+/* $22 BHI relative ----- */
+OP_HANDLER( bhi )
+{
+ BRANCH( !(CC & (CC_Z|CC_C)) );
+}
+
+/* $1022 LBHI relative ----- */
+OP_HANDLER( lbhi )
+{
+ LBRANCH( !(CC & (CC_Z|CC_C)) );
+}
+
+/* $23 BLS relative ----- */
+OP_HANDLER( bls )
+{
+ BRANCH( (CC & (CC_Z|CC_C)) );
+}
+
+/* $1023 LBLS relative ----- */
+OP_HANDLER( lbls )
+{
+ LBRANCH( (CC&(CC_Z|CC_C)) );
+}
+
+/* $24 BCC relative ----- */
+OP_HANDLER( bcc )
+{
+ BRANCH( !(CC&CC_C) );
+}
+
+/* $1024 LBCC relative ----- */
+OP_HANDLER( lbcc )
+{
+ LBRANCH( !(CC&CC_C) );
+}
+
+/* $25 BCS relative ----- */
+OP_HANDLER( bcs )
+{
+ BRANCH( (CC&CC_C) );
+}
+
+/* $1025 LBCS relative ----- */
+OP_HANDLER( lbcs )
+{
+ LBRANCH( (CC&CC_C) );
+}
+
+/* $26 BNE relative ----- */
+OP_HANDLER( bne )
+{
+ BRANCH( !(CC&CC_Z) );
+}
+
+/* $1026 LBNE relative ----- */
+OP_HANDLER( lbne )
+{
+ LBRANCH( !(CC&CC_Z) );
+}
+
+/* $27 BEQ relative ----- */
+OP_HANDLER( beq )
+{
+ BRANCH( (CC&CC_Z) );
+}
+
+/* $1027 LBEQ relative ----- */
+OP_HANDLER( lbeq )
+{
+ LBRANCH( (CC&CC_Z) );
+}
+
+/* $28 BVC relative ----- */
+OP_HANDLER( bvc )
+{
+ BRANCH( !(CC&CC_V) );
+}
+
+/* $1028 LBVC relative ----- */
+OP_HANDLER( lbvc )
+{
+ LBRANCH( !(CC&CC_V) );
+}
+
+/* $29 BVS relative ----- */
+OP_HANDLER( bvs )
+{
+ BRANCH( (CC&CC_V) );
+}
+
+/* $1029 LBVS relative ----- */
+OP_HANDLER( lbvs )
+{
+ LBRANCH( (CC&CC_V) );
+}
+
+/* $2A BPL relative ----- */
+OP_HANDLER( bpl )
+{
+ BRANCH( !(CC&CC_N) );
+}
+
+/* $102A LBPL relative ----- */
+OP_HANDLER( lbpl )
+{
+ LBRANCH( !(CC&CC_N) );
+}
+
+/* $2B BMI relative ----- */
+OP_HANDLER( bmi )
+{
+ BRANCH( (CC&CC_N) );
+}
+
+/* $102B LBMI relative ----- */
+OP_HANDLER( lbmi )
+{
+ LBRANCH( (CC&CC_N) );
+}
+
+/* $2C BGE relative ----- */
+OP_HANDLER( bge )
+{
+ BRANCH( !NXORV );
+}
+
+/* $102C LBGE relative ----- */
+OP_HANDLER( lbge )
+{
+ LBRANCH( !NXORV );
+}
+
+/* $2D BLT relative ----- */
+OP_HANDLER( blt )
+{
+ BRANCH( NXORV );
+}
+
+/* $102D LBLT relative ----- */
+OP_HANDLER( lblt )
+{
+ LBRANCH( NXORV );
+}
+
+/* $2E BGT relative ----- */
+OP_HANDLER( bgt )
+{
+ BRANCH( !(NXORV || (CC&CC_Z)) );
+}
+
+/* $102E LBGT relative ----- */
+OP_HANDLER( lbgt )
+{
+ LBRANCH( !(NXORV || (CC&CC_Z)) );
+}
+
+/* $2F BLE relative ----- */
+OP_HANDLER( ble )
+{
+ BRANCH( (NXORV || (CC&CC_Z)) );
+}
+
+/* $102F LBLE relative ----- */
+OP_HANDLER( lble )
+{
+ LBRANCH( (NXORV || (CC&CC_Z)) );
+}
+
+#define REGREG_PREAMBLE \
+ IMMBYTE(tb); \
+ if( (tb^(tb>>4)) & 0x08 ) \
+ {promote = TRUE;} \
+ switch(tb>>4) { \
+ case 0: src16Reg = &D; large = TRUE; break; \
+ case 1: src16Reg = &X; large = TRUE; break; \
+ case 2: src16Reg = &Y; large = TRUE; break; \
+ case 3: src16Reg = &U; large = TRUE; break; \
+ case 4: src16Reg = &S; large = TRUE; break; \
+ case 5: src16Reg = &PC; large = TRUE; break; \
+ case 6: src16Reg = &W; large = TRUE; break; \
+ case 7: src16Reg = &V; large = TRUE; break; \
+ case 8: if (promote) src16Reg = &D; else src8Reg = &A; break; \
+ case 9: if (promote) src16Reg = &D; else src8Reg = &B; break; \
+ case 10: if (promote) src16Reg = &z16; else src8Reg = &CC; break; \
+ case 11: if (promote) src16Reg = &z16; else src8Reg = &DP; break; \
+ case 12: if (promote) src16Reg = &z16; else src8Reg = &z8; break; \
+ case 13: if (promote) src16Reg = &z16; else src8Reg = &z8; break; \
+ case 14: if (promote) src16Reg = &W; else src8Reg = &E; break; \
+ default: if (promote) src16Reg = &W; else src8Reg = &F; break; \
+ } \
+ switch(tb&15) { \
+ case 0: dst16Reg = &D; large = TRUE; break; \
+ case 1: dst16Reg = &X; large = TRUE; break; \
+ case 2: dst16Reg = &Y; large = TRUE; break; \
+ case 3: dst16Reg = &U; large = TRUE; break; \
+ case 4: dst16Reg = &S; large = TRUE; break; \
+ case 5: dst16Reg = &PC; large = TRUE; break; \
+ case 6: dst16Reg = &W; large = TRUE; break; \
+ case 7: dst16Reg = &V; large = TRUE; break; \
+ case 8: if (promote) dst16Reg = &D; else dst8Reg = &A; break; \
+ case 9: if (promote) dst16Reg = &D; else dst8Reg = &B; break; \
+ case 10: if (promote) dst16Reg = &z16; else dst8Reg = &CC; break; \
+ case 11: if (promote) dst16Reg = &z16; else dst8Reg = &DP; break; \
+ case 12: if (promote) dst16Reg = &z16; else dst8Reg = &z8; break; \
+ case 13: if (promote) dst16Reg = &z16; else dst8Reg = &z8; break; \
+ case 14: if (promote) dst16Reg = &W; else dst8Reg = &E; break; \
+ default: if (promote) dst16Reg = &W; else dst8Reg = &F; break; \
+ } \
+
+/* $1030 addr_r r1 + r2 -> r2 */
+
+OP_HANDLER( addr_r )
+{
+ UINT8 tb, z8 = 0;
+ UINT16 z16 = 0, r8;
+ UINT32 r16;
+ UINT8 *src8Reg = NULL, *dst8Reg = NULL;
+ UINT16 *src16Reg = NULL, *dst16Reg = NULL;
+ int promote = FALSE, large = FALSE;
+
+ REGREG_PREAMBLE;
+
+ if ( large )
+ {
+ r16 = *src16Reg + *dst16Reg;
+ CLR_NZVC;
+ *dst16Reg = r16;
+ SET_FLAGS16(*src16Reg,*dst16Reg,r16);
+ }
+ else
+ {
+ r8 = *src8Reg + *dst8Reg;
+ CLR_NZVC;
+ /* SET_H(*src8Reg,*src8Reg,r8);*/ /*Experimentation prooved this not to be the case */
+ *dst8Reg = r8;
+ SET_FLAGS8(*src8Reg,*dst8Reg,r8);
+ }
+}
+
+OP_HANDLER( adcr )
+{
+ UINT8 tb, z8 = 0;
+ UINT16 z16 = 0, r8;
+ UINT32 r16;
+ UINT8 *src8Reg = NULL, *dst8Reg = NULL;
+ UINT16 *src16Reg = NULL, *dst16Reg = NULL;
+ int promote = FALSE, large = FALSE;
+
+ REGREG_PREAMBLE;
+
+ if ( large )
+ {
+ r16 = *src16Reg + *dst16Reg + (CC & CC_C);
+ CLR_NZVC;
+ *dst16Reg = r16;
+ SET_FLAGS16(*src16Reg,*dst16Reg,r16);
+ }
+ else
+ {
+ r8 = *src8Reg + *dst8Reg + (CC & CC_C);
+ CLR_NZVC;
+ /* SET_H(*src8Reg,*src8Reg,r8);*/ /*Experimentation prooved this not to be the case */
+ *dst8Reg = r8;
+ SET_FLAGS8(*src8Reg,*dst8Reg,r8);
+ }
+}
+
+/* $1032 SUBR r1 - r2 -> r2 */
+OP_HANDLER( subr )
+{
+ UINT8 tb, z8 = 0;
+ UINT16 z16 = 0, r8;
+ UINT32 r16;
+ UINT8 *src8Reg = NULL, *dst8Reg = NULL;
+ UINT16 *src16Reg = NULL, *dst16Reg = NULL;
+ int promote = FALSE, large = FALSE;
+
+ REGREG_PREAMBLE;
+
+ if ( large )
+ {
+ r16 = (UINT32)*dst16Reg - (UINT32)*src16Reg;
+ CLR_NZVC;
+ *dst16Reg = r16;
+ SET_FLAGS16((UINT32)*dst16Reg,(UINT32)*src16Reg,r16);
+ }
+ else
+ {
+ r8 = *dst8Reg - *src8Reg;
+ CLR_NZVC;
+ *dst8Reg = r8;
+ SET_FLAGS8(*dst8Reg,*src8Reg,r8);
+ }
+}
+
+/* $1033 SBCR r1 - r2 - C -> r2 */
+OP_HANDLER( sbcr )
+{
+ UINT8 tb, z8 = 0;
+ UINT16 z16 = 0, r8;
+ UINT32 r16;
+ UINT8 *src8Reg = NULL, *dst8Reg = NULL;
+ UINT16 *src16Reg = NULL, *dst16Reg = NULL;
+ int promote = FALSE, large = FALSE;
+
+ REGREG_PREAMBLE;
+
+ if ( large )
+ {
+ r16 = (UINT32)*dst16Reg - (UINT32)*src16Reg - (CC & CC_C);
+ CLR_NZVC;
+ *dst16Reg = r16;
+ SET_FLAGS16((UINT32)*dst16Reg,(UINT32)*src16Reg,r16);
+ }
+ else
+ {
+ r8 = *dst8Reg - *src8Reg - (CC & CC_C);
+ CLR_NZVC;
+ *dst8Reg = r8;
+ SET_FLAGS8(*dst8Reg,*src8Reg,r8);
+ }
+}
+
+/* $1034 ANDR r1 & r2 -> r2 */
+OP_HANDLER( andr )
+{
+ UINT8 tb, z8 = 0;
+ UINT16 z16 = 0, r8;
+ UINT32 r16;
+ UINT8 *src8Reg = NULL, *dst8Reg = NULL;
+ UINT16 *src16Reg = NULL, *dst16Reg = NULL;
+ int promote = FALSE, large = FALSE;
+
+ REGREG_PREAMBLE;
+
+ if ( large )
+ {
+ r16 = *src16Reg & *dst16Reg;
+ CLR_NZV;
+ *dst16Reg = r16;
+ SET_NZ16(r16);
+ }
+ else
+ {
+ r8 = *src8Reg & *dst8Reg;
+ CLR_NZV;
+ *dst8Reg = r8;
+ SET_NZ8(r8);
+ }
+}
+
+/* $1035 ORR r1 | r2 -> r2 */
+OP_HANDLER( orr )
+{
+ UINT8 tb, z8 = 0;
+ UINT16 z16 = 0, r8;
+ UINT32 r16;
+ UINT8 *src8Reg = NULL, *dst8Reg = NULL;
+ UINT16 *src16Reg = NULL, *dst16Reg = NULL;
+ int promote = FALSE, large = FALSE;
+
+ REGREG_PREAMBLE;
+
+ if ( large )
+ {
+ r16 = *src16Reg | *dst16Reg;
+ CLR_NZV;
+ *dst16Reg = r16;
+ SET_NZ16(r16);
+ }
+ else
+ {
+ r8 = *src8Reg | *dst8Reg;
+ CLR_NZV;
+ *dst8Reg = r8;
+ SET_NZ8(r8);
+ }
+}
+
+/* $1036 EORR r1 ^ r2 -> r2 */
+OP_HANDLER( eorr )
+{
+ UINT8 tb, z8 = 0;
+ UINT16 z16 = 0, r8;
+ UINT32 r16;
+ UINT8 *src8Reg = NULL, *dst8Reg = NULL;
+ UINT16 *src16Reg = NULL, *dst16Reg = NULL;
+ int promote = FALSE, large = FALSE;
+
+ REGREG_PREAMBLE;
+
+ if ( large )
+ {
+ r16 = *src16Reg ^ *dst16Reg;
+ CLR_NZV;
+ *dst16Reg = r16;
+ SET_NZ16(r16);
+ }
+ else
+ {
+ r8 = *src8Reg ^ *dst8Reg;
+ CLR_NZV;
+ *dst8Reg = r8;
+ SET_NZ8(r8);
+ }
+}
+
+/* $1037 CMPR r1 - r2 */
+OP_HANDLER( cmpr )
+{
+ UINT8 tb, z8 = 0;
+ UINT16 z16 = 0, r8;
+ UINT32 r16;
+ UINT8 *src8Reg = NULL, *dst8Reg = NULL;
+ UINT16 *src16Reg = NULL, *dst16Reg = NULL;
+ int promote = FALSE, large = FALSE;
+
+ REGREG_PREAMBLE;
+
+ if ( large )
+ {
+ r16 = (UINT32)*dst16Reg - (UINT32)*src16Reg;
+ CLR_NZVC;
+ SET_FLAGS16((UINT32)*dst16Reg,(UINT32)*src16Reg,r16);
+ }
+ else
+ {
+ r8 = *dst8Reg - *src8Reg;
+ CLR_NZVC;
+ SET_FLAGS8(*dst8Reg,*src8Reg,r8);
+ }
+}
+
+/* $1138 TFM R0+,R1+ */
+OP_HANDLER( tfmpp )
+{
+ UINT8 tb, srcValue = 0;
+
+ IMMBYTE(tb);
+
+ if ( W != 0 )
+ {
+ switch(tb>>4) {
+ case 0: srcValue = RM(D++); break;
+ case 1: srcValue = RM(X++); break;
+ case 2: srcValue = RM(Y++); break;
+ case 3: srcValue = RM(U++); break;
+ case 4: srcValue = RM(S++); break;
+ default: IIError(m68_state); return; /* reg PC through F */
+ }
+
+ switch(tb&15) {
+ case 0: WM(D++, srcValue); break;
+ case 1: WM(X++, srcValue); break;
+ case 2: WM(Y++, srcValue); break;
+ case 3: WM(U++, srcValue); break;
+ case 4: WM(S++, srcValue); break;
+ default: IIError(m68_state); return; /* reg PC through F */
+ }
+
+ PCD = PCD - 3;
+ W--;
+ }
+ else
+ m68_state->icount -= 6; /* Needs six aditional cycles to get the 6+3n */
+}
+
+/* $1139 TFM R0-,R1- */
+OP_HANDLER( tfmmm )
+{
+ UINT8 tb, srcValue = 0;
+
+ IMMBYTE(tb);
+
+ if ( W != 0 )
+ {
+ switch(tb>>4) {
+ case 0: srcValue = RM(D--); break;
+ case 1: srcValue = RM(X--); break;
+ case 2: srcValue = RM(Y--); break;
+ case 3: srcValue = RM(U--); break;
+ case 4: srcValue = RM(S--); break;
+ default: IIError(m68_state); return; /* reg PC through F */
+ }
+
+ switch(tb&15) {
+ case 0: WM(D--, srcValue); break;
+ case 1: WM(X--, srcValue); break;
+ case 2: WM(Y--, srcValue); break;
+ case 3: WM(U--, srcValue); break;
+ case 4: WM(S--, srcValue); break;
+ default: IIError(m68_state); return; /* reg PC through F */
+ }
+
+ PCD = PCD - 3;
+ W--;
+ }
+ else
+ m68_state->icount -= 6; /* Needs six aditional cycles to get the 6+3n */
+}
+
+/* $113A TFM R0+,R1 */
+OP_HANDLER( tfmpc )
+{
+ UINT8 tb, srcValue = 0;
+
+ IMMBYTE(tb);
+
+ if ( W != 0 )
+ {
+ switch(tb>>4) {
+ case 0: srcValue = RM(D++); break;
+ case 1: srcValue = RM(X++); break;
+ case 2: srcValue = RM(Y++); break;
+ case 3: srcValue = RM(U++); break;
+ case 4: srcValue = RM(S++); break;
+ default: IIError(m68_state); return; /* reg PC through F */
+ }
+
+ switch(tb&15) {
+ case 0: WM(D, srcValue); break;
+ case 1: WM(X, srcValue); break;
+ case 2: WM(Y, srcValue); break;
+ case 3: WM(U, srcValue); break;
+ case 4: WM(S, srcValue); break;
+ default: IIError(m68_state); return; /* reg PC through F */
+ }
+
+ PCD = PCD - 3;
+ W--;
+ }
+ else
+ m68_state->icount -= 6; /* Needs six aditional cycles to get the 6+3n */
+}
+
+/* $113B TFM R0,R1+ */
+OP_HANDLER( tfmcp )
+{
+ UINT8 tb, srcValue = 0;
+
+ IMMBYTE(tb);
+
+ if ( W != 0 )
+ {
+ switch(tb>>4) {
+ case 0: srcValue = RM(D); break;
+ case 1: srcValue = RM(X); break;
+ case 2: srcValue = RM(Y); break;
+ case 3: srcValue = RM(U); break;
+ case 4: srcValue = RM(S); break;
+ default: IIError(m68_state); return; /* reg PC through F */
+ }
+
+ switch(tb&15) {
+ case 0: WM(D++, srcValue); break;
+ case 1: WM(X++, srcValue); break;
+ case 2: WM(Y++, srcValue); break;
+ case 3: WM(U++, srcValue); break;
+ case 4: WM(S++, srcValue); break;
+ default: IIError(m68_state); return; /* reg PC through F */
+ }
+
+ PCD = PCD - 3;
+ W--;
+ }
+ else
+ m68_state->icount -= 6; /* Needs six aditional cycles to get the 6+3n */
+}
+
+/* $30 LEAX indexed --*-- */
+OP_HANDLER( leax )
+{
+ fetch_effective_address(m68_state);
+ X = EA;
+ CLR_Z;
+ SET_Z(X);
+}
+
+/* $31 LEAY indexed --*-- */
+OP_HANDLER( leay )
+{
+ fetch_effective_address(m68_state);
+ Y = EA;
+ CLR_Z;
+ SET_Z(Y);
+}
+
+/* $32 LEAS indexed ----- */
+OP_HANDLER( leas )
+{
+ fetch_effective_address(m68_state);
+ S = EA;
+ m68_state->int_state |= M6809_LDS;
+}
+
+/* $33 LEAU indexed ----- */
+OP_HANDLER( leau )
+{
+ fetch_effective_address(m68_state);
+ U = EA;
+}
+
+/* $34 PSHS inherent ----- */
+OP_HANDLER( pshs )
+{
+ UINT8 t;
+ IMMBYTE(t);
+ if( t&0x80 ) { PUSHWORD(pPC); m68_state->icount -= 2; }
+ if( t&0x40 ) { PUSHWORD(pU); m68_state->icount -= 2; }
+ if( t&0x20 ) { PUSHWORD(pY); m68_state->icount -= 2; }
+ if( t&0x10 ) { PUSHWORD(pX); m68_state->icount -= 2; }
+ if( t&0x08 ) { PUSHBYTE(DP); m68_state->icount -= 1; }
+ if( t&0x04 ) { PUSHBYTE(B); m68_state->icount -= 1; }
+ if( t&0x02 ) { PUSHBYTE(A); m68_state->icount -= 1; }
+ if( t&0x01 ) { PUSHBYTE(CC); m68_state->icount -= 1; }
+}
+
+/* $1038 PSHSW inherent ----- */
+OP_HANDLER( pshsw )
+{
+ PUSHWORD(pW);
+}
+
+/* $103a PSHUW inherent ----- */
+OP_HANDLER( pshuw )
+{
+ PSHUWORD(pW);
+}
+
+/* $35 PULS inherent ----- */
+OP_HANDLER( puls )
+{
+ UINT8 t;
+ IMMBYTE(t);
+ if( t&0x01 ) { PULLBYTE(CC); m68_state->icount -= 1; }
+ if( t&0x02 ) { PULLBYTE(A); m68_state->icount -= 1; }
+ if( t&0x04 ) { PULLBYTE(B); m68_state->icount -= 1; }
+ if( t&0x08 ) { PULLBYTE(DP); m68_state->icount -= 1; }
+ if( t&0x10 ) { PULLWORD(XD); m68_state->icount -= 2; }
+ if( t&0x20 ) { PULLWORD(YD); m68_state->icount -= 2; }
+ if( t&0x40 ) { PULLWORD(UD); m68_state->icount -= 2; }
+ if( t&0x80 ) { PULLWORD(PCD); m68_state->icount -= 2; }
+
+ /* HJB 990225: moved check after all PULLs */
+ if( t&0x01 ) { check_irq_lines(m68_state); }
+}
+
+/* $1039 PULSW inherent ----- */
+OP_HANDLER( pulsw )
+{
+ PULLWORD(W);
+}
+
+/* $103b PULUW inherent ----- */
+OP_HANDLER( puluw )
+{
+ PULUWORD(W);
+}
+
+/* $36 PSHU inherent ----- */
+OP_HANDLER( pshu )
+{
+ UINT8 t;
+ IMMBYTE(t);
+ if( t&0x80 ) { PSHUWORD(pPC); m68_state->icount -= 2; }
+ if( t&0x40 ) { PSHUWORD(pS); m68_state->icount -= 2; }
+ if( t&0x20 ) { PSHUWORD(pY); m68_state->icount -= 2; }
+ if( t&0x10 ) { PSHUWORD(pX); m68_state->icount -= 2; }
+ if( t&0x08 ) { PSHUBYTE(DP); m68_state->icount -= 1; }
+ if( t&0x04 ) { PSHUBYTE(B); m68_state->icount -= 1; }
+ if( t&0x02 ) { PSHUBYTE(A); m68_state->icount -= 1; }
+ if( t&0x01 ) { PSHUBYTE(CC); m68_state->icount -= 1; }
+}
+
+/* 37 PULU inherent ----- */
+OP_HANDLER( pulu )
+{
+ UINT8 t;
+ IMMBYTE(t);
+ if( t&0x01 ) { PULUBYTE(CC); m68_state->icount -= 1; }
+ if( t&0x02 ) { PULUBYTE(A); m68_state->icount -= 1; }
+ if( t&0x04 ) { PULUBYTE(B); m68_state->icount -= 1; }
+ if( t&0x08 ) { PULUBYTE(DP); m68_state->icount -= 1; }
+ if( t&0x10 ) { PULUWORD(XD); m68_state->icount -= 2; }
+ if( t&0x20 ) { PULUWORD(YD); m68_state->icount -= 2; }
+ if( t&0x40 ) { PULUWORD(SD); m68_state->icount -= 2; }
+ if( t&0x80 ) { PULUWORD(PCD); m68_state->icount -= 2; }
+
+ /* HJB 990225: moved check after all PULLs */
+ if( t&0x01 ) { check_irq_lines(m68_state); }
+}
+
+/* $38 ILLEGAL */
+
+/* $39 RTS inherent ----- */
+OP_HANDLER( rts )
+{
+ PULLWORD(PCD);
+}
+
+/* $3A ABX inherent ----- */
+OP_HANDLER( abx )
+{
+ X += B;
+}
+
+/* $3B RTI inherent ##### */
+OP_HANDLER( rti )
+{
+ UINT8 t;
+ PULLBYTE(CC);
+ t = CC & CC_E; /* HJB 990225: entire state saved? */
+ if(t)
+ {
+ m68_state->icount -= 9;
+ PULLBYTE(A);
+ PULLBYTE(B);
+ if ( MD & MD_EM )
+ {
+ PULLBYTE(E);
+ PULLBYTE(F);
+ m68_state->icount -= 2;
+ }
+ PULLBYTE(DP);
+ PULLWORD(XD);
+ PULLWORD(YD);
+ PULLWORD(UD);
+ }
+ PULLWORD(PCD);
+ check_irq_lines(m68_state); /* HJB 990116 */
+}
+
+/* $3C CWAI inherent ----1 */
+OP_HANDLER( cwai )
+{
+ UINT8 t;
+ IMMBYTE(t);
+ CC &= t;
+ /*
+ * CWAI stacks the entire machine state on the hardware stack,
+ * then waits for an interrupt; when the interrupt is taken
+ * later, the state is *not* saved again after CWAI.
+ */
+ CC |= CC_E; /* HJB 990225: save entire state */
+ PUSHWORD(pPC);
+ PUSHWORD(pU);
+ PUSHWORD(pY);
+ PUSHWORD(pX);
+ PUSHBYTE(DP);
+ if ( MD & MD_EM )
+ {
+ PUSHBYTE(E);
+ PUSHBYTE(F);
+ }
+ PUSHBYTE(B);
+ PUSHBYTE(A);
+ PUSHBYTE(CC);
+ m68_state->int_state |= M6809_CWAI; /* HJB 990228 */
+ check_irq_lines(m68_state); /* HJB 990116 */
+ if( m68_state->int_state & M6809_CWAI )
+ if( m68_state->icount > 0 )
+ m68_state->icount = 0;
+}
+
+/* $3D MUL inherent --*-@ */
+OP_HANDLER( mul )
+{
+ UINT16 t;
+ t = A * B;
+ CLR_ZC; SET_Z16(t); if(t&0x80) SEC;
+ D = t;
+}
+
+/* $3E ILLEGAL */
+
+/* $3F SWI (SWI2 SWI3) absolute indirect ----- */
+OP_HANDLER( swi )
+{
+ CC |= CC_E; /* HJB 980225: save entire state */
+ PUSHWORD(pPC);
+ PUSHWORD(pU);
+ PUSHWORD(pY);
+ PUSHWORD(pX);
+ PUSHBYTE(DP);
+ if ( MD & MD_EM )
+ {
+ PUSHBYTE(F);
+ PUSHBYTE(E);
+ }
+ PUSHBYTE(B);
+ PUSHBYTE(A);
+ PUSHBYTE(CC);
+ CC |= CC_IF | CC_II; /* inhibit FIRQ and IRQ */
+ PCD=RM16(m68_state, 0xfffa);
+}
+
+/* $1130 BAND */
+
+#define decodePB_tReg(n) (((n) >> 6) & 0x03)
+#define decodePB_src(n) (((n) >> 3) & 0x07)
+#define decodePB_dst(n) (((n) >> 0) & 0x07)
+
+static const UINT8 bitTable[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
+
+OP_HANDLER( band )
+{
+ UINT8 pb;
+ UINT16 db;
+
+ IMMBYTE(pb);
+
+ DIRBYTE(db);
+
+ if ( ( *(m68_state->regTable[decodePB_tReg(pb)]) & bitTable[decodePB_dst(pb)] ) && ( db & bitTable[decodePB_src(pb)] ))
+ *(m68_state->regTable[decodePB_tReg(pb)]) |= bitTable[decodePB_dst(pb)];
+ else
+ *(m68_state->regTable[decodePB_tReg(pb)]) &= (~bitTable[decodePB_dst(pb)]);
+}
+
+/* $1131 BIAND */
+
+OP_HANDLER( biand )
+{
+ UINT8 pb;
+ UINT16 db;
+
+ IMMBYTE(pb);
+
+ DIRBYTE(db);
+
+ if ( ( *(m68_state->regTable[decodePB_tReg(pb)]) & bitTable[decodePB_dst(pb)] ) && ( (~db) & bitTable[decodePB_src(pb)] ))
+ *(m68_state->regTable[decodePB_tReg(pb)]) |= bitTable[decodePB_dst(pb)];
+ else
+ *(m68_state->regTable[decodePB_tReg(pb)]) &= (~bitTable[decodePB_dst(pb)]);
+}
+
+/* $1132 BOR */
+
+OP_HANDLER( bor )
+{
+ UINT8 pb;
+ UINT16 db;
+
+ IMMBYTE(pb);
+
+ DIRBYTE(db);
+
+ if ( ( *(m68_state->regTable[decodePB_tReg(pb)]) & bitTable[decodePB_dst(pb)] ) || ( db & bitTable[decodePB_src(pb)] ))
+ *(m68_state->regTable[decodePB_tReg(pb)]) |= bitTable[decodePB_dst(pb)];
+ else
+ *(m68_state->regTable[decodePB_tReg(pb)]) &= (~bitTable[decodePB_dst(pb)]);
+}
+
+/* $1133 BIOR */
+
+OP_HANDLER( bior )
+{
+ UINT8 pb;
+ UINT16 db;
+
+ IMMBYTE(pb);
+
+ DIRBYTE(db);
+
+ if ( ( *(m68_state->regTable[decodePB_tReg(pb)]) & bitTable[decodePB_dst(pb)] ) || ( (~db) & bitTable[decodePB_src(pb)] ))
+ *(m68_state->regTable[decodePB_tReg(pb)]) |= bitTable[decodePB_dst(pb)];
+ else
+ *(m68_state->regTable[decodePB_tReg(pb)]) &= (~bitTable[decodePB_dst(pb)]);
+}
+
+/* $1134 BEOR */
+
+OP_HANDLER( beor )
+{
+ UINT8 pb;
+ UINT16 db;
+ UINT8 tReg, tMem;
+
+ IMMBYTE(pb);
+
+ DIRBYTE(db);
+
+ tReg = *(m68_state->regTable[decodePB_tReg(pb)]) & bitTable[decodePB_dst(pb)];
+ tMem = db & bitTable[decodePB_src(pb)];
+
+ if ( (tReg || tMem ) && !(tReg && tMem) )
+ *(m68_state->regTable[decodePB_tReg(pb)]) |= bitTable[decodePB_dst(pb)];
+ else
+ *(m68_state->regTable[decodePB_tReg(pb)]) &= (~bitTable[decodePB_dst(pb)]);
+}
+
+/* $1135 BIEOR */
+
+OP_HANDLER( bieor )
+{
+ UINT8 pb;
+ UINT16 db;
+ UINT8 tReg, tMem;
+
+ IMMBYTE(pb);
+
+ DIRBYTE(db);
+
+ tReg = *(m68_state->regTable[decodePB_tReg(pb)]) & bitTable[decodePB_dst(pb)];
+ tMem = (~db) & bitTable[decodePB_src(pb)];
+
+ if ( (tReg || tMem ) && !(tReg && tMem) )
+ *(m68_state->regTable[decodePB_tReg(pb)]) |= bitTable[decodePB_dst(pb)];
+ else
+ *(m68_state->regTable[decodePB_tReg(pb)]) &= (~bitTable[decodePB_dst(pb)]);
+}
+
+/* $1133 LDBT */
+
+OP_HANDLER( ldbt )
+{
+ UINT8 pb;
+ UINT16 db;
+
+ IMMBYTE(pb);
+
+ DIRBYTE(db);
+
+ if ( ( db & bitTable[decodePB_src(pb)] ) )
+ *(m68_state->regTable[decodePB_tReg(pb)]) |= bitTable[decodePB_dst(pb)];
+ else
+ *(m68_state->regTable[decodePB_tReg(pb)]) &= (~bitTable[decodePB_dst(pb)]);
+}
+
+/* $1134 STBT */
+
+OP_HANDLER( stbt )
+{
+ UINT8 pb;
+ UINT16 db;
+
+ IMMBYTE(pb);
+
+ DIRBYTE(db);
+
+ if ( ( *(m68_state->regTable[decodePB_tReg(pb)]) & bitTable[decodePB_dst(pb)] ) )
+ WM( EAD, db | bitTable[decodePB_src(pb)] );
+ else
+ WM( EAD, db & (~bitTable[decodePB_src(pb)]) );
+}
+
+/* $103F SWI2 absolute indirect ----- */
+OP_HANDLER( swi2 )
+{
+ CC |= CC_E; /* HJB 980225: save entire state */
+ PUSHWORD(pPC);
+ PUSHWORD(pU);
+ PUSHWORD(pY);
+ PUSHWORD(pX);
+ PUSHBYTE(DP);
+ if ( MD & MD_EM )
+ {
+ PUSHBYTE(F);
+ PUSHBYTE(E);
+ }
+ PUSHBYTE(B);
+ PUSHBYTE(A);
+ PUSHBYTE(CC);
+ PCD = RM16(m68_state, 0xfff4);
+}
+
+/* $113F SWI3 absolute indirect ----- */
+OP_HANDLER( swi3 )
+{
+ CC |= CC_E; /* HJB 980225: save entire state */
+ PUSHWORD(pPC);
+ PUSHWORD(pU);
+ PUSHWORD(pY);
+ PUSHWORD(pX);
+ PUSHBYTE(DP);
+ if ( MD & MD_EM )
+ {
+ PUSHBYTE(F);
+ PUSHBYTE(E);
+ }
+ PUSHBYTE(B);
+ PUSHBYTE(A);
+ PUSHBYTE(CC);
+ PCD = RM16(m68_state, 0xfff2);
+}
+
+/* $40 NEGA inherent ?**** */
+OP_HANDLER( nega )
+{
+ UINT16 r;
+ r = -A;
+ CLR_NZVC;
+ SET_FLAGS8(0,A,r);
+ A = r;
+}
+
+/* $41 ILLEGAL */
+
+/* $42 ILLEGAL */
+
+/* $43 COMA inherent -**01 */
+OP_HANDLER( coma )
+{
+ A = ~A;
+ CLR_NZV;
+ SET_NZ8(A);
+ SEC;
+}
+
+/* $44 LSRA inherent -0*-* */
+OP_HANDLER( lsra )
+{
+ CLR_NZC;
+ CC |= (A & CC_C);
+ A >>= 1;
+ SET_Z8(A);
+}
+
+/* $45 ILLEGAL */
+
+/* $46 RORA inherent -**-* */
+OP_HANDLER( rora )
+{
+ UINT8 r;
+ r = (CC & CC_C) << 7;
+ CLR_NZC;
+ CC |= (A & CC_C);
+ r |= A >> 1;
+ SET_NZ8(r);
+ A = r;
+}
+
+/* $47 ASRA inherent ?**-* */
+OP_HANDLER( asra )
+{
+ CLR_NZC;
+ CC |= (A & CC_C);
+ A = (A & 0x80) | (A >> 1);
+ SET_NZ8(A);
+}
+
+/* $48 ASLA inherent ?**** */
+OP_HANDLER( asla )
+{
+ UINT16 r;
+ r = A << 1;
+ CLR_NZVC;
+ SET_FLAGS8(A,A,r);
+ A = r;
+}
+
+/* $49 ROLA inherent -**** */
+OP_HANDLER( rola )
+{
+ UINT16 t,r;
+ t = A;
+ r = (CC & CC_C) | (t<<1);
+ CLR_NZVC; SET_FLAGS8(t,t,r);
+ A = r;
+}
+
+/* $4A DECA inherent -***- */
+OP_HANDLER( deca )
+{
+ --A;
+ CLR_NZV;
+ SET_FLAGS8D(A);
+}
+
+/* $4B ILLEGAL */
+
+/* $4C INCA inherent -***- */
+OP_HANDLER( inca )
+{
+ ++A;
+ CLR_NZV;
+ SET_FLAGS8I(A);
+}
+
+/* $4D TSTA inherent -**0- */
+OP_HANDLER( tsta )
+{
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $4E ILLEGAL */
+
+/* $4F CLRA inherent -0100 */
+OP_HANDLER( clra )
+{
+ A = 0;
+ CLR_NZVC; SEZ;
+}
+
+/* $50 NEGB inherent ?**** */
+OP_HANDLER( negb )
+{
+ UINT16 r;
+ r = -B;
+ CLR_NZVC;
+ SET_FLAGS8(0,B,r);
+ B = r;
+}
+
+/* $1040 NEGD inherent ?**** */
+OP_HANDLER( negd )
+{
+ UINT32 r;
+ r = -D;
+ CLR_NZVC;
+ SET_FLAGS16(0,D,r);
+ D = r;
+}
+
+/* $51 ILLEGAL */
+
+/* $52 ILLEGAL */
+
+/* $53 COMB inherent -**01 */
+OP_HANDLER( comb )
+{
+ B = ~B;
+ CLR_NZV;
+ SET_NZ8(B);
+ SEC;
+}
+
+/* $1143 COME inherent -**01 */
+OP_HANDLER( come )
+{
+ E = ~E;
+ CLR_NZV;
+ SET_NZ8(E);
+ SEC;
+}
+
+/* $1153 COMF inherent -**01 */
+OP_HANDLER( comf )
+{
+ F = ~F;
+ CLR_NZV;
+ SET_NZ8(F);
+ SEC;
+}
+
+/* $1043 COMD inherent -**01 */
+OP_HANDLER( comd )
+{
+ D = ~D;
+ CLR_NZV;
+ SET_NZ16(D);
+ SEC;
+}
+
+/* $1053 COMW inherent -**01 */
+OP_HANDLER( comw )
+{
+ W = ~W;
+ CLR_NZV;
+ SET_NZ16(W);
+ SEC;
+}
+
+/* $54 LSRB inherent -0*-* */
+OP_HANDLER( lsrb )
+{
+ CLR_NZC;
+ CC |= (B & CC_C);
+ B >>= 1;
+ SET_Z8(B);
+}
+
+/* $1044 LSRD inherent -0*-* */
+OP_HANDLER( lsrd )
+{
+ CLR_NZC;
+ CC |= (B & CC_C);
+ D >>= 1;
+ SET_Z16(D);
+}
+
+/* $1054 LSRW inherent -0*-* */
+OP_HANDLER( lsrw )
+{
+ CLR_NZC;
+ CC |= (F & CC_C);
+ W >>= 1;
+ SET_Z16(W);
+}
+
+/* $55 ILLEGAL */
+
+/* $56 RORB inherent -**-* */
+OP_HANDLER( rorb )
+{
+ UINT8 r;
+ r = (CC & CC_C) << 7;
+ CLR_NZC;
+ CC |= (B & CC_C);
+ r |= B >> 1;
+ SET_NZ8(r);
+ B = r;
+}
+
+/* $1046 RORD inherent -**-* */
+OP_HANDLER( rord )
+{
+ UINT16 r;
+ r = (CC & CC_C) << 15;
+ CLR_NZC;
+ CC |= (D & CC_C);
+ r |= D >> 1;
+ SET_NZ16(r);
+ D = r;
+}
+
+/* $1056 RORW inherent -**-* */
+OP_HANDLER( rorw )
+{
+ UINT16 r;
+ r = (CC & CC_C) << 15;
+ CLR_NZC;
+ CC |= (W & CC_C);
+ r |= W >> 1;
+ SET_NZ16(r);
+ W = r;
+}
+
+/* $57 ASRB inherent ?**-* */
+OP_HANDLER( asrb )
+{
+ CLR_NZC;
+ CC |= (B & CC_C);
+ B= (B & 0x80) | (B >> 1);
+ SET_NZ8(B);
+}
+
+/* $1047 ASRD inherent ?**-* */
+OP_HANDLER( asrd )
+{
+ CLR_NZC;
+ CC |= (D & CC_C);
+ D= (D & 0x8000) | (D >> 1);
+ SET_NZ16(D);
+}
+
+/* $58 ASLB inherent ?**** */
+OP_HANDLER( aslb )
+{
+ UINT16 r;
+ r = B << 1;
+ CLR_NZVC;
+ SET_FLAGS8(B,B,r);
+ B = r;
+}
+
+/* $1048 ASLD inherent ?**** */
+OP_HANDLER( asld )
+{
+ UINT32 r;
+ r = D << 1;
+ CLR_NZVC;
+ SET_FLAGS16(D,D,r);
+ D = r;
+}
+
+/* $59 ROLB inherent -**** */
+OP_HANDLER( rolb )
+{
+ UINT16 t,r;
+ t = B;
+ r = CC & CC_C;
+ r |= t << 1;
+ CLR_NZVC;
+ SET_FLAGS8(t,t,r);
+ B = r;
+}
+
+/* $1049 ROLD inherent -**** */
+OP_HANDLER( rold )
+{
+ UINT32 t,r;
+ t = D;
+ r = CC & CC_C;
+ r |= t << 1;
+ CLR_NZVC;
+ SET_FLAGS16(t,t,r);
+ D = r;
+}
+
+/* $1059 ROLW inherent -**** */
+OP_HANDLER( rolw )
+{
+ UINT32 t,r;
+ t = W;
+ r = CC & CC_C;
+ r |= t << 1;
+ CLR_NZVC;
+ SET_FLAGS16(t,t,r);
+ W = r;
+}
+
+/* $5A DECB inherent -***- */
+OP_HANDLER( decb )
+{
+ --B;
+ CLR_NZV;
+ SET_FLAGS8D(B);
+}
+
+/* $114a DECE inherent -***- */
+OP_HANDLER( dece )
+{
+ --E;
+ CLR_NZV;
+ SET_FLAGS8D(E);
+}
+
+/* $115a DECF inherent -***- */
+OP_HANDLER( decf )
+{
+ --F;
+ CLR_NZV;
+ SET_FLAGS8D(F);
+}
+
+/* $104a DECD inherent -***- */
+OP_HANDLER( decd )
+{
+ UINT32 r;
+ r = D - 1;
+ CLR_NZVC;
+ SET_FLAGS16(D,D,r)
+ D = r;
+}
+
+/* $105a DECW inherent -***- */
+OP_HANDLER( decw )
+{
+ UINT32 r;
+ r = W - 1;
+ CLR_NZVC;
+ SET_FLAGS16(W,W,r)
+ W = r;
+}
+
+/* $5B ILLEGAL */
+
+/* $5C INCB inherent -***- */
+OP_HANDLER( incb )
+{
+ ++B;
+ CLR_NZV;
+ SET_FLAGS8I(B);
+}
+
+/* $114c INCE inherent -***- */
+OP_HANDLER( ince )
+{
+ ++E;
+ CLR_NZV;
+ SET_FLAGS8I(E);
+}
+
+/* $115c INCF inherent -***- */
+OP_HANDLER( incf )
+{
+ ++F;
+ CLR_NZV;
+ SET_FLAGS8I(F);
+}
+
+/* $104c INCD inherent -***- */
+OP_HANDLER( incd )
+{
+ UINT32 r;
+ r = D + 1;
+ CLR_NZVC;
+ SET_FLAGS16(D,D,r)
+ D = r;
+}
+
+/* $105c INCW inherent -***- */
+OP_HANDLER( incw )
+{
+ UINT32 r;
+ r = W + 1;
+ CLR_NZVC;
+ SET_FLAGS16(W,W,r)
+ W = r;
+}
+
+/* $5D TSTB inherent -**0- */
+OP_HANDLER( tstb )
+{
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $104d TSTD inherent -**0- */
+OP_HANDLER( tstd )
+{
+ CLR_NZV;
+ SET_NZ16(D);
+}
+
+/* $105d TSTW inherent -**0- */
+OP_HANDLER( tstw )
+{
+ CLR_NZV;
+ SET_NZ16(W);
+}
+
+/* $114d TSTE inherent -**0- */
+OP_HANDLER( tste )
+{
+ CLR_NZV;
+ SET_NZ8(E);
+}
+
+/* $115d TSTF inherent -**0- */
+OP_HANDLER( tstf )
+{
+ CLR_NZV;
+ SET_NZ8(F);
+}
+
+/* $5E ILLEGAL */
+
+/* $5F CLRB inherent -0100 */
+OP_HANDLER( clrb )
+{
+ B = 0;
+ CLR_NZVC; SEZ;
+}
+
+/* $104f CLRD inherent -0100 */
+OP_HANDLER( clrd )
+{
+ D = 0;
+ CLR_NZVC; SEZ;
+}
+
+/* $114f CLRE inherent -0100 */
+OP_HANDLER( clre )
+{
+ E = 0;
+ CLR_NZVC; SEZ;
+}
+
+/* $115f CLRF inherent -0100 */
+OP_HANDLER( clrf )
+{
+ F = 0;
+ CLR_NZVC; SEZ;
+}
+
+/* $105f CLRW inherent -0100 */
+OP_HANDLER( clrw )
+{
+ W = 0;
+ CLR_NZVC; SEZ;
+}
+
+/* $60 NEG indexed ?**** */
+OP_HANDLER( neg_ix )
+{
+ UINT16 r,t;
+ fetch_effective_address(m68_state);
+ t = RM(EAD);
+ r=-t;
+ CLR_NZVC;
+ SET_FLAGS8(0,t,r);
+ WM(EAD,r);
+}
+
+/* $61 OIM indexed */
+OP_HANDLER( oim_ix )
+{
+ UINT8 r,im;
+ IMMBYTE(im);
+ fetch_effective_address(m68_state);
+ r = im | RM(EAD);
+ CLR_NZV;
+ SET_NZ8(r);
+ WM(EAD,r);
+}
+
+/* $62 AIM indexed */
+OP_HANDLER( aim_ix )
+{
+ UINT8 r,im;
+ IMMBYTE(im);
+ fetch_effective_address(m68_state);
+ r = im & RM(EAD);
+ CLR_NZV;
+ SET_NZ8(r);
+ WM(EAD,r);
+}
+
+/* $63 COM indexed -**01 */
+OP_HANDLER( com_ix )
+{
+ UINT8 t;
+ fetch_effective_address(m68_state);
+ t = ~RM(EAD);
+ CLR_NZV;
+ SET_NZ8(t);
+ SEC;
+ WM(EAD,t);
+}
+
+/* $64 LSR indexed -0*-* */
+OP_HANDLER( lsr_ix )
+{
+ UINT8 t;
+ fetch_effective_address(m68_state);
+ t=RM(EAD);
+ CLR_NZC;
+ CC |= (t & CC_C);
+ t>>=1; SET_Z8(t);
+ WM(EAD,t);
+}
+
+/* $65 EIM indexed */
+OP_HANDLER( eim_ix )
+{
+ UINT8 r,im;
+ IMMBYTE(im);
+ fetch_effective_address(m68_state);
+ r = im ^ RM(EAD);
+ CLR_NZV;
+ SET_NZ8(r);
+ WM(EAD,r);
+}
+/* $66 ROR indexed -**-* */
+OP_HANDLER( ror_ix )
+{
+ UINT8 t,r;
+ fetch_effective_address(m68_state);
+ t=RM(EAD);
+ r = (CC & CC_C) << 7;
+ CLR_NZC;
+ CC |= (t & CC_C);
+ r |= t>>1; SET_NZ8(r);
+ WM(EAD,r);
+}
+
+/* $67 ASR indexed ?**-* */
+OP_HANDLER( asr_ix )
+{
+ UINT8 t;
+ fetch_effective_address(m68_state);
+ t=RM(EAD);
+ CLR_NZC;
+ CC |= (t & CC_C);
+ t=(t&0x80)|(t>>1);
+ SET_NZ8(t);
+ WM(EAD,t);
+}
+
+/* $68 ASL indexed ?**** */
+OP_HANDLER( asl_ix )
+{
+ UINT16 t,r;
+ fetch_effective_address(m68_state);
+ t=RM(EAD);
+ r = t << 1;
+ CLR_NZVC;
+ SET_FLAGS8(t,t,r);
+ WM(EAD,r);
+}
+
+/* $69 ROL indexed -**** */
+OP_HANDLER( rol_ix )
+{
+ UINT16 t,r;
+ fetch_effective_address(m68_state);
+ t=RM(EAD);
+ r = CC & CC_C;
+ r |= t << 1;
+ CLR_NZVC;
+ SET_FLAGS8(t,t,r);
+ WM(EAD,r);
+}
+
+/* $6A DEC indexed -***- */
+OP_HANDLER( dec_ix )
+{
+ UINT8 t;
+ fetch_effective_address(m68_state);
+ t = RM(EAD) - 1;
+ CLR_NZV; SET_FLAGS8D(t);
+ WM(EAD,t);
+}
+
+/* $6B TIM indexed */
+OP_HANDLER( tim_ix )
+{
+ UINT8 r,im,m;
+ IMMBYTE(im);
+ fetch_effective_address(m68_state);
+ m = RM(EAD);
+ r = im & m;
+ CLR_NZV;
+ SET_NZ8(r);
+}
+
+/* $6C INC indexed -***- */
+OP_HANDLER( inc_ix )
+{
+ UINT8 t;
+ fetch_effective_address(m68_state);
+ t = RM(EAD) + 1;
+ CLR_NZV; SET_FLAGS8I(t);
+ WM(EAD,t);
+}
+
+/* $6D TST indexed -**0- */
+OP_HANDLER( tst_ix )
+{
+ UINT8 t;
+ fetch_effective_address(m68_state);
+ t = RM(EAD);
+ CLR_NZV;
+ SET_NZ8(t);
+}
+
+/* $6E JMP indexed ----- */
+OP_HANDLER( jmp_ix )
+{
+ fetch_effective_address(m68_state);
+ PCD = EAD;
+}
+
+/* $6F CLR indexed -0100 */
+OP_HANDLER( clr_ix )
+{
+ fetch_effective_address(m68_state);
+ (void)RM(EAD);
+ WM(EAD,0);
+ CLR_NZVC; SEZ;
+}
+
+/* $70 NEG extended ?**** */
+OP_HANDLER( neg_ex )
+{
+ UINT16 r,t;
+ EXTBYTE(t); r=-t;
+ CLR_NZVC; SET_FLAGS8(0,t,r);
+ WM(EAD,r);
+}
+
+/* $71 OIM extended */
+OP_HANDLER( oim_ex )
+{
+ UINT8 r,t,im;
+ IMMBYTE(im);
+ EXTBYTE(t);
+ r = im | t;
+ CLR_NZV;
+ SET_NZ8(r);
+ WM(EAD,r);
+}
+
+/* $72 AIM extended */
+OP_HANDLER( aim_ex )
+{
+ UINT8 r,t,im;
+ IMMBYTE(im);
+ EXTBYTE(t);
+ r = im & t;
+ CLR_NZV;
+ SET_NZ8(r);
+ WM(EAD,r);
+}
+
+/* $73 COM extended -**01 */
+OP_HANDLER( com_ex )
+{
+ UINT8 t;
+ EXTBYTE(t); t = ~t;
+ CLR_NZV; SET_NZ8(t); SEC;
+ WM(EAD,t);
+}
+
+/* $74 LSR extended -0*-* */
+OP_HANDLER( lsr_ex )
+{
+ UINT8 t;
+ EXTBYTE(t); CLR_NZC; CC |= (t & CC_C);
+ t>>=1; SET_Z8(t);
+ WM(EAD,t);
+}
+
+/* $75 EIM extended */
+OP_HANDLER( eim_ex )
+{
+ UINT8 r,t,im;
+ IMMBYTE(im);
+ EXTBYTE(t);
+ r = im ^ t;
+ CLR_NZV;
+ SET_NZ8(r);
+ WM(EAD,r);
+}
+
+/* $76 ROR extended -**-* */
+OP_HANDLER( ror_ex )
+{
+ UINT8 t,r;
+ EXTBYTE(t); r=(CC & CC_C) << 7;
+ CLR_NZC; CC |= (t & CC_C);
+ r |= t>>1; SET_NZ8(r);
+ WM(EAD,r);
+}
+
+/* $77 ASR extended ?**-* */
+OP_HANDLER( asr_ex )
+{
+ UINT8 t;
+ EXTBYTE(t); CLR_NZC; CC |= (t & CC_C);
+ t=(t&0x80)|(t>>1);
+ SET_NZ8(t);
+ WM(EAD,t);
+}
+
+/* $78 ASL extended ?**** */
+OP_HANDLER( asl_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t); r=t<<1;
+ CLR_NZVC; SET_FLAGS8(t,t,r);
+ WM(EAD,r);
+}
+
+/* $79 ROL extended -**** */
+OP_HANDLER( rol_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t); r = (CC & CC_C) | (t << 1);
+ CLR_NZVC; SET_FLAGS8(t,t,r);
+ WM(EAD,r);
+}
+
+/* $7A DEC extended -***- */
+OP_HANDLER( dec_ex )
+{
+ UINT8 t;
+ EXTBYTE(t); --t;
+ CLR_NZV; SET_FLAGS8D(t);
+ WM(EAD,t);
+}
+
+/* $7B TIM extended */
+OP_HANDLER( tim_ex )
+{
+ UINT8 r,t,im;
+ IMMBYTE(im);
+ EXTBYTE(t);
+ r = im & t;
+ CLR_NZV;
+ SET_NZ8(r);
+}
+
+/* $7C INC extended -***- */
+OP_HANDLER( inc_ex )
+{
+ UINT8 t;
+ EXTBYTE(t); ++t;
+ CLR_NZV; SET_FLAGS8I(t);
+ WM(EAD,t);
+}
+
+/* $7D TST extended -**0- */
+OP_HANDLER( tst_ex )
+{
+ UINT8 t;
+ EXTBYTE(t); CLR_NZV; SET_NZ8(t);
+}
+
+/* $7E JMP extended ----- */
+OP_HANDLER( jmp_ex )
+{
+ EXTENDED;
+ PCD = EAD;
+}
+
+/* $7F CLR extended -0100 */
+OP_HANDLER( clr_ex )
+{
+ EXTENDED;
+ (void)RM(EAD);
+ WM(EAD,0);
+ CLR_NZVC; SEZ;
+}
+
+/* $80 SUBA immediate ?**** */
+OP_HANDLER( suba_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t);
+ r = A - t;
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $81 CMPA immediate ?**** */
+OP_HANDLER( cmpa_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t);
+ r = A - t;
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+}
+
+/* $82 SBCA immediate ?**** */
+OP_HANDLER( sbca_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t);
+ r = A - t - (CC & CC_C);
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $83 SUBD (CMPD CMPU) immediate -**** */
+OP_HANDLER( subd_im )
+{
+ UINT32 r,d;
+ PAIR b;
+ IMMWORD(b);
+ d = D;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ D = r;
+}
+
+/* $1080 SUBW immediate -**** */
+OP_HANDLER( subw_im )
+{
+ UINT32 r,d;
+ PAIR b;
+ IMMWORD(b);
+ d = W;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ W = r;
+}
+
+/* $1083 CMPD immediate -**** */
+OP_HANDLER( cmpd_im )
+{
+ UINT32 r,d;
+ PAIR b;
+ IMMWORD(b);
+ d = D;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $1081 CMPW immediate -**** */
+OP_HANDLER( cmpw_im )
+{
+ UINT32 r,d;
+ PAIR b;
+ IMMWORD(b);
+ d = W;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $1183 CMPU immediate -**** */
+OP_HANDLER( cmpu_im )
+{
+ UINT32 r, d;
+ PAIR b;
+ IMMWORD(b);
+ d = U;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $84 ANDA immediate -**0- */
+OP_HANDLER( anda_im )
+{
+ UINT8 t;
+ IMMBYTE(t);
+ A &= t;
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $85 BITA immediate -**0- */
+OP_HANDLER( bita_im )
+{
+ UINT8 t,r;
+ IMMBYTE(t);
+ r = A & t;
+ CLR_NZV;
+ SET_NZ8(r);
+}
+
+/* $86 LDA immediate -**0- */
+OP_HANDLER( lda_im )
+{
+ IMMBYTE(A);
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $88 EORA immediate -**0- */
+OP_HANDLER( eora_im )
+{
+ UINT8 t;
+ IMMBYTE(t);
+ A ^= t;
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $89 ADCA immediate ***** */
+OP_HANDLER( adca_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t);
+ r = A + t + (CC & CC_C);
+ CLR_HNZVC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $8A ORA immediate -**0- */
+OP_HANDLER( ora_im )
+{
+ UINT8 t;
+ IMMBYTE(t);
+ A |= t;
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $8B ADDA immediate ***** */
+OP_HANDLER( adda_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t);
+ r = A + t;
+ CLR_HNZVC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $8C CMPX (CMPY CMPS) immediate -**** */
+OP_HANDLER( cmpx_im )
+{
+ UINT32 r,d;
+ PAIR b;
+ IMMWORD(b);
+ d = X;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $108C CMPY immediate -**** */
+OP_HANDLER( cmpy_im )
+{
+ UINT32 r,d;
+ PAIR b;
+ IMMWORD(b);
+ d = Y;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $118C CMPS immediate -**** */
+OP_HANDLER( cmps_im )
+{
+ UINT32 r,d;
+ PAIR b;
+ IMMWORD(b);
+ d = S;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $8D BSR ----- */
+OP_HANDLER( bsr )
+{
+ UINT8 t;
+ IMMBYTE(t);
+ PUSHWORD(pPC);
+ PC += SIGNED(t);
+}
+
+/* $8E LDX (LDY) immediate -**0- */
+OP_HANDLER( ldx_im )
+{
+ IMMWORD(pX);
+ CLR_NZV;
+ SET_NZ16(X);
+}
+
+/* $CD LDQ immediate -**0- */
+OP_HANDLER( ldq_im )
+{
+ PAIR q;
+
+ IMMLONG(q);
+ D = q.w.h;
+ W = q.w.l;
+ CLR_NZV;
+ SET_N8(A);
+ SET_Z(q.d);
+}
+
+/* $108E LDY immediate -**0- */
+OP_HANDLER( ldy_im )
+{
+ IMMWORD(pY);
+ CLR_NZV;
+ SET_NZ16(Y);
+}
+
+/* $118f MULD immediate */
+OP_HANDLER( muld_im )
+{
+ PAIR t, q;
+
+ IMMWORD( t );
+ q.d = (INT16) D * (INT16)t.w.l;
+ D = q.w.h;
+ W = q.w.l;
+ CLR_NZVC;
+ SET_NZ16(D);
+}
+
+/* $118d DIVD immediate */
+OP_HANDLER( divd_im )
+{
+ UINT8 t;
+ INT16 v, oldD;
+
+ IMMBYTE( t );
+
+ if( t != 0 )
+ {
+ oldD = D;
+ v = (INT16) D / (INT8) t;
+ A = (INT16) D % (INT8) t;
+ B = v;
+
+ CLR_NZVC;
+ SET_NZ8(B);
+
+ if( B & 0x01 )
+ SEC;
+
+ if( (INT16)D < 0 )
+ SEN;
+
+ if ( (v > 127) || (v < -128) ) /* soft overflow */
+ {
+ SEV;
+
+ if( (v > 255) || (v < -256) ) /* hard overflow - division is aborted */
+ {
+ SET_NZ16( oldD );
+ D = abs( oldD );
+ }
+ }
+ }
+ else
+ {
+ m68_state->icount -= 8;
+ DZError(m68_state);
+ }
+}
+
+/* $118e DIVQ immediate */
+OP_HANDLER( divq_im )
+{
+ PAIR t,q, oldQ;
+ INT32 v;
+
+ IMMWORD( t );
+
+ q.w.h = D;
+ q.w.l = W;
+
+ if( t.w.l != 0 )
+ {
+ oldQ = q;
+
+ v = (INT32) q.d / (INT16) t.w.l;
+ D = (INT32) q.d % (INT16) t.w.l;
+ W = v;
+
+ CLR_NZVC;
+ SET_NZ16(W);
+
+ if( W & 0x0001 )
+ SEC;
+
+ if ( (v > 32768) || (v < -32767) ) /* soft overflow */
+ {
+ SEV;
+
+ if( (v > 65536 ) || (v < -65535 ) ) /* hard overflow - division is aborted */
+ {
+ if( (INT32)oldQ.d < 0 )
+ SEN;
+ else if( oldQ.d == 0 )
+ SEZ;
+
+ t.w.l = abs( t.w.l );
+ D = oldQ.w.h;
+ W = oldQ.w.l;
+ }
+ }
+ }
+ else
+ DZError(m68_state);
+}
+
+/* $90 SUBA direct ?**** */
+OP_HANDLER( suba_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = A - t;
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $91 CMPA direct ?**** */
+OP_HANDLER( cmpa_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = A - t;
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+}
+
+/* $92 SBCA direct ?**** */
+OP_HANDLER( sbca_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = A - t - (CC & CC_C);
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $93 SUBD (CMPD CMPU) direct -**** */
+OP_HANDLER( subd_di )
+{
+ UINT32 r,d;
+ PAIR b;
+ DIRWORD(b);
+ d = D;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ D = r;
+}
+
+/* $1090 SUBW direct -**** */
+OP_HANDLER( subw_di )
+{
+ UINT32 r,d;
+ PAIR b;
+ DIRWORD(b);
+ d = W;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ W = r;
+}
+
+/* $1093 CMPD direct -**** */
+OP_HANDLER( cmpd_di )
+{
+ UINT32 r,d;
+ PAIR b;
+ DIRWORD(b);
+ d = D;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $1091 CMPW direct -**** */
+OP_HANDLER( cmpw_di )
+{
+ UINT32 r,d;
+ PAIR b;
+ DIRWORD(b);
+ d = W;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $1193 CMPU direct -**** */
+OP_HANDLER( cmpu_di )
+{
+ UINT32 r,d;
+ PAIR b;
+ DIRWORD(b);
+ d = U;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(U,b.d,r);
+}
+
+/* $94 ANDA direct -**0- */
+OP_HANDLER( anda_di )
+{
+ UINT8 t;
+ DIRBYTE(t);
+ A &= t;
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $95 BITA direct -**0- */
+OP_HANDLER( bita_di )
+{
+ UINT8 t,r;
+ DIRBYTE(t);
+ r = A & t;
+ CLR_NZV;
+ SET_NZ8(r);
+}
+
+/* $96 LDA direct -**0- */
+OP_HANDLER( lda_di )
+{
+ DIRBYTE(A);
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $97 STA direct -**0- */
+OP_HANDLER( sta_di )
+{
+ CLR_NZV;
+ SET_NZ8(A);
+ DIRECT;
+ WM(EAD,A);
+}
+
+/* $98 EORA direct -**0- */
+OP_HANDLER( eora_di )
+{
+ UINT8 t;
+ DIRBYTE(t);
+ A ^= t;
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $99 ADCA direct ***** */
+OP_HANDLER( adca_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = A + t + (CC & CC_C);
+ CLR_HNZVC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $9A ORA direct -**0- */
+OP_HANDLER( ora_di )
+{
+ UINT8 t;
+ DIRBYTE(t);
+ A |= t;
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $9B ADDA direct ***** */
+OP_HANDLER( adda_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = A + t;
+ CLR_HNZVC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $9C CMPX (CMPY CMPS) direct -**** */
+OP_HANDLER( cmpx_di )
+{
+ UINT32 r,d;
+ PAIR b;
+ DIRWORD(b);
+ d = X;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $109C CMPY direct -**** */
+OP_HANDLER( cmpy_di )
+{
+ UINT32 r,d;
+ PAIR b;
+ DIRWORD(b);
+ d = Y;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $119C CMPS direct -**** */
+OP_HANDLER( cmps_di )
+{
+ UINT32 r,d;
+ PAIR b;
+ DIRWORD(b);
+ d = S;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $9D JSR direct ----- */
+OP_HANDLER( jsr_di )
+{
+ DIRECT;
+ PUSHWORD(pPC);
+ PCD = EAD;
+}
+
+/* $9E LDX (LDY) direct -**0- */
+OP_HANDLER( ldx_di )
+{
+ DIRWORD(pX);
+ CLR_NZV;
+ SET_NZ16(X);
+}
+
+/* $119f MULD direct -**0- */
+OP_HANDLER( muld_di )
+{
+ PAIR t,q;
+
+ DIRWORD(t);
+ q.d = (INT16) D * (INT16)t.w.l;
+
+ D = q.w.h;
+ W = q.w.l;
+ CLR_NZVC;
+ SET_NZ16(D);
+}
+
+/* $119d DIVD direct -**0- */
+OP_HANDLER( divd_di )
+{
+ UINT8 t;
+ INT16 v, oldD;
+
+ DIRBYTE(t);
+
+ if( t != 0 )
+ {
+ oldD = D;
+ v = (INT16) D / (INT8) t;
+ A = (INT16) D % (INT8) t;
+ B = v;
+
+ CLR_NZVC;
+ SET_NZ8(B);
+
+ if( B & 0x01 )
+ SEC;
+
+ if( (INT16)D < 0 )
+ SEN;
+
+ if ( (v > 127) || (v < -128) ) /* soft overflow */
+ {
+ SEV;
+
+ if( (v > 255) || (v < -256) ) /* hard overflow - division is aborted */
+ {
+ SET_NZ16( oldD );
+ D = abs( oldD );
+ }
+ }
+ }
+ else
+ {
+ m68_state->icount -= 8;
+ DZError(m68_state);
+ }
+}
+
+/* $119e DIVQ direct -**0- */
+OP_HANDLER( divq_di )
+{
+ PAIR t,q, oldQ;
+ INT32 v;
+
+ DIRWORD(t);
+
+ q.w.h = D;
+ q.w.l = W;
+
+ if( t.w.l != 0 )
+ {
+ oldQ = q;
+
+ v = (INT32) q.d / (INT16) t.w.l;
+ D = (INT32) q.d % (INT16) t.w.l;
+ W = v;
+
+ CLR_NZVC;
+ SET_NZ16(W);
+
+ if( W & 0x0001 )
+ SEC;
+
+ if ( (v > 32767) || (v < -32768) ) /* soft overflow */
+ {
+ SEV;
+
+ if( (v > 65535 ) || (v < -65536 ) ) /* hard overflow - division is aborted */
+ {
+ if( (INT32)oldQ.d < 0 )
+ SEN;
+ else if( oldQ.d == 0 )
+ SEZ;
+
+ t.w.l = abs( t.w.l );
+ D = oldQ.w.h;
+ W = oldQ.w.l;
+ }
+ }
+ }
+ else
+ DZError(m68_state);
+}
+/* $10dc LDQ direct -**0- */
+OP_HANDLER( ldq_di )
+{
+ PAIR q;
+
+ DIRLONG(q);
+ D = q.w.h;
+ W = q.w.l;
+ CLR_NZV;
+ SET_N8(A);
+ SET_Z(q.d);
+}
+
+/* $109E LDY direct -**0- */
+OP_HANDLER( ldy_di )
+{
+ DIRWORD(pY);
+ CLR_NZV;
+ SET_NZ16(Y);
+}
+
+/* $9F STX (STY) direct -**0- */
+OP_HANDLER( stx_di )
+{
+ CLR_NZV;
+ SET_NZ16(X);
+ DIRECT;
+ WM16(m68_state, EAD,&pX);
+}
+
+/* $10dd STQ direct -**0- */
+OP_HANDLER( stq_di )
+{
+ PAIR q;
+
+ q.w.h = D;
+ q.w.l = W;
+ DIRECT;
+ WM32(m68_state, EAD,&q);
+ CLR_NZV;
+ SET_N8(A);
+ SET_Z(q.d);
+}
+
+/* $109F STY direct -**0- */
+OP_HANDLER( sty_di )
+{
+ CLR_NZV;
+ SET_NZ16(Y);
+ DIRECT;
+ WM16(m68_state, EAD,&pY);
+}
+
+/* $a0 SUBA indexed ?**** */
+OP_HANDLER( suba_ix )
+{
+ UINT16 t,r;
+ fetch_effective_address(m68_state);
+ t = RM(EAD);
+ r = A - t;
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $a1 CMPA indexed ?**** */
+OP_HANDLER( cmpa_ix )
+{
+ UINT16 t,r;
+ fetch_effective_address(m68_state);
+ t = RM(EAD);
+ r = A - t;
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+}
+
+/* $a2 SBCA indexed ?**** */
+OP_HANDLER( sbca_ix )
+{
+ UINT16 t,r;
+ fetch_effective_address(m68_state);
+ t = RM(EAD);
+ r = A - t - (CC & CC_C);
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $a3 SUBD (CMPD CMPU) indexed -**** */
+OP_HANDLER( subd_ix )
+{
+ UINT32 r,d;
+ PAIR b;
+ fetch_effective_address(m68_state);
+ b.d=RM16(m68_state, EAD);
+ d = D;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ D = r;
+}
+
+/* $10a0 SUBW indexed -**** */
+OP_HANDLER( subw_ix )
+{
+ UINT32 r,d;
+ PAIR b;
+ fetch_effective_address(m68_state);
+ b.d=RM16(m68_state, EAD);
+ d = W;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ W = r;
+}
+
+/* $10a1 CMPW indexed -**** */
+OP_HANDLER( cmpw_ix )
+{
+ UINT32 r,d;
+ PAIR b;
+ fetch_effective_address(m68_state);
+ b.d=RM16(m68_state, EAD);
+ d = W;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $10a3 CMPD indexed -**** */
+OP_HANDLER( cmpd_ix )
+{
+ UINT32 r,d;
+ PAIR b;
+ fetch_effective_address(m68_state);
+ b.d=RM16(m68_state, EAD);
+ d = D;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $11a3 CMPU indexed -**** */
+OP_HANDLER( cmpu_ix )
+{
+ UINT32 r;
+ PAIR b;
+ fetch_effective_address(m68_state);
+ b.d=RM16(m68_state, EAD);
+ r = U - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(U,b.d,r);
+}
+
+/* $a4 ANDA indexed -**0- */
+OP_HANDLER( anda_ix )
+{
+ fetch_effective_address(m68_state);
+ A &= RM(EAD);
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $a5 BITA indexed -**0- */
+OP_HANDLER( bita_ix )
+{
+ UINT8 r;
+ fetch_effective_address(m68_state);
+ r = A & RM(EAD);
+ CLR_NZV;
+ SET_NZ8(r);
+}
+
+/* $a6 LDA indexed -**0- */
+OP_HANDLER( lda_ix )
+{
+ fetch_effective_address(m68_state);
+ A = RM(EAD);
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $a7 STA indexed -**0- */
+OP_HANDLER( sta_ix )
+{
+ fetch_effective_address(m68_state);
+ CLR_NZV;
+ SET_NZ8(A);
+ WM(EAD,A);
+}
+
+/* $a8 EORA indexed -**0- */
+OP_HANDLER( eora_ix )
+{
+ fetch_effective_address(m68_state);
+ A ^= RM(EAD);
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $a9 ADCA indexed ***** */
+OP_HANDLER( adca_ix )
+{
+ UINT16 t,r;
+ fetch_effective_address(m68_state);
+ t = RM(EAD);
+ r = A + t + (CC & CC_C);
+ CLR_HNZVC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $aA ORA indexed -**0- */
+OP_HANDLER( ora_ix )
+{
+ fetch_effective_address(m68_state);
+ A |= RM(EAD);
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $aB ADDA indexed ***** */
+OP_HANDLER( adda_ix )
+{
+ UINT16 t,r;
+ fetch_effective_address(m68_state);
+ t = RM(EAD);
+ r = A + t;
+ CLR_HNZVC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $aC CMPX (CMPY CMPS) indexed -**** */
+OP_HANDLER( cmpx_ix )
+{
+ UINT32 r,d;
+ PAIR b;
+ fetch_effective_address(m68_state);
+ b.d=RM16(m68_state, EAD);
+ d = X;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $10aC CMPY indexed -**** */
+OP_HANDLER( cmpy_ix )
+{
+ UINT32 r,d;
+ PAIR b;
+ fetch_effective_address(m68_state);
+ b.d=RM16(m68_state, EAD);
+ d = Y;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $11aC CMPS indexed -**** */
+OP_HANDLER( cmps_ix )
+{
+ UINT32 r,d;
+ PAIR b;
+ fetch_effective_address(m68_state);
+ b.d=RM16(m68_state, EAD);
+ d = S;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $aD JSR indexed ----- */
+OP_HANDLER( jsr_ix )
+{
+ fetch_effective_address(m68_state);
+ PUSHWORD(pPC);
+ PCD = EAD;
+}
+
+/* $aE LDX (LDY) indexed -**0- */
+OP_HANDLER( ldx_ix )
+{
+ fetch_effective_address(m68_state);
+ X=RM16(m68_state, EAD);
+ CLR_NZV;
+ SET_NZ16(X);
+}
+
+/* $11af MULD indexed -**0- */
+OP_HANDLER( muld_ix )
+{
+ PAIR q;
+ UINT16 t;
+
+ fetch_effective_address(m68_state);
+ t=RM16(m68_state, EAD);
+ q.d = (INT16) D * (INT16)t;
+
+ D = q.w.h;
+ W = q.w.l;
+ CLR_NZVC;
+ SET_NZ16(D);
+}
+
+/* $11ad DIVD indexed -**0- */
+OP_HANDLER( divd_ix )
+{
+ UINT8 t;
+ INT16 v, oldD;
+
+ fetch_effective_address(m68_state);
+ t=RM(EAD);
+
+ if( t != 0 )
+ {
+ oldD = D;
+ v = (INT16) D / (INT8) t;
+ A = (INT16) D % (INT8) t;
+ B = v;
+
+ CLR_NZVC;
+ SET_NZ8(B);
+
+ if( B & 0x01 )
+ SEC;
+
+ if( (INT16)D < 0 )
+ SEN;
+
+ if ( (v > 127) || (v < -128) ) /* soft overflow */
+ {
+ SEV;
+
+ if( (v > 255) || (v < -256) ) /* hard overflow - division is aborted */
+ {
+ SET_NZ16( oldD );
+ D = abs( oldD );
+ }
+ }
+ }
+ else
+ {
+ m68_state->icount -= 8;
+ DZError(m68_state);
+ }
+}
+
+/* $11ae DIVQ indexed -**0- */
+OP_HANDLER( divq_ix )
+{
+ PAIR t,q, oldQ;
+ INT32 v;
+
+ fetch_effective_address(m68_state);
+ t.w.l=RM16(m68_state, EAD);
+
+ q.w.h = D;
+ q.w.l = W;
+
+ if( t.w.l != 0 )
+ {
+ oldQ = q;
+
+ v = (INT32) q.d / (INT16) t.w.l;
+ D = (INT32) q.d % (INT16) t.w.l;
+ W = v;
+
+ CLR_NZVC;
+ SET_NZ16(W);
+
+ if( W & 0x0001 )
+ SEC;
+
+ if ( (v > 32767) || (v < -32768) ) /* soft overflow */
+ {
+ SEV;
+
+ if( (v > 65535 ) || (v < -65536 ) ) /* hard overflow - division is aborted */
+ {
+ if( (INT32)oldQ.d < 0 )
+ SEN;
+ else if( oldQ.d == 0 )
+ SEZ;
+
+ t.w.l = abs( t.w.l );
+ D = oldQ.w.h;
+ W = oldQ.w.l;
+ }
+ }
+ }
+ else
+ DZError(m68_state);
+}
+
+/* $10ec LDQ indexed -**0- */
+OP_HANDLER( ldq_ix )
+{
+ PAIR q;
+
+ fetch_effective_address(m68_state);
+ q.d=RM32(m68_state, EAD);
+ D = q.w.h;
+ W = q.w.l;
+ CLR_NZV;
+ SET_N8(A);
+ SET_Z(q.d);
+}
+
+/* $10aE LDY indexed -**0- */
+OP_HANDLER( ldy_ix )
+{
+ fetch_effective_address(m68_state);
+ Y=RM16(m68_state, EAD);
+ CLR_NZV;
+ SET_NZ16(Y);
+}
+
+/* $aF STX (STY) indexed -**0- */
+OP_HANDLER( stx_ix )
+{
+ fetch_effective_address(m68_state);
+ CLR_NZV;
+ SET_NZ16(X);
+ WM16(m68_state, EAD,&pX);
+}
+
+/* $10ed STQ indexed -**0- */
+OP_HANDLER( stq_ix )
+{
+ PAIR q;
+
+ q.w.h = D;
+ q.w.l = W;
+ fetch_effective_address(m68_state);
+ WM32(m68_state, EAD,&q);
+ CLR_NZV;
+ SET_N8(A);
+ SET_Z(q.d);
+}
+
+/* $10aF STY indexed -**0- */
+OP_HANDLER( sty_ix )
+{
+ fetch_effective_address(m68_state);
+ CLR_NZV;
+ SET_NZ16(Y);
+ WM16(m68_state, EAD,&pY);
+}
+
+/* $b0 SUBA extended ?**** */
+OP_HANDLER( suba_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = A - t;
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $b1 CMPA extended ?**** */
+OP_HANDLER( cmpa_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = A - t;
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+}
+
+/* $b2 SBCA extended ?**** */
+OP_HANDLER( sbca_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = A - t - (CC & CC_C);
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $b3 SUBD (CMPD CMPU) extended -**** */
+OP_HANDLER( subd_ex )
+{
+ UINT32 r,d;
+ PAIR b;
+ EXTWORD(b);
+ d = D;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ D = r;
+}
+
+/* $10b0 SUBW extended -**** */
+OP_HANDLER( subw_ex )
+{
+ UINT32 r,d;
+ PAIR b = {{0,}};
+ EXTWORD(b);
+ d = W;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ W = r;
+}
+
+/* $10b3 CMPD extended -**** */
+OP_HANDLER( cmpd_ex )
+{
+ UINT32 r,d;
+ PAIR b;
+ EXTWORD(b);
+ d = D;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $10b1 CMPW extended -**** */
+OP_HANDLER( cmpw_ex )
+{
+ UINT32 r,d;
+ PAIR b = {{0,}};
+ EXTWORD(b);
+ d = W;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $11b3 CMPU extended -**** */
+OP_HANDLER( cmpu_ex )
+{
+ UINT32 r,d;
+ PAIR b;
+ EXTWORD(b);
+ d = U;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $b4 ANDA extended -**0- */
+OP_HANDLER( anda_ex )
+{
+ UINT8 t;
+ EXTBYTE(t);
+ A &= t;
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $b5 BITA extended -**0- */
+OP_HANDLER( bita_ex )
+{
+ UINT8 t,r;
+ EXTBYTE(t);
+ r = A & t;
+ CLR_NZV; SET_NZ8(r);
+}
+
+/* $b6 LDA extended -**0- */
+OP_HANDLER( lda_ex )
+{
+ EXTBYTE(A);
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $b7 STA extended -**0- */
+OP_HANDLER( sta_ex )
+{
+ CLR_NZV;
+ SET_NZ8(A);
+ EXTENDED;
+ WM(EAD,A);
+}
+
+/* $b8 EORA extended -**0- */
+OP_HANDLER( eora_ex )
+{
+ UINT8 t;
+ EXTBYTE(t);
+ A ^= t;
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $b9 ADCA extended ***** */
+OP_HANDLER( adca_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = A + t + (CC & CC_C);
+ CLR_HNZVC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $bA ORA extended -**0- */
+OP_HANDLER( ora_ex )
+{
+ UINT8 t;
+ EXTBYTE(t);
+ A |= t;
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $bB ADDA extended ***** */
+OP_HANDLER( adda_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = A + t;
+ CLR_HNZVC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $bC CMPX (CMPY CMPS) extended -**** */
+OP_HANDLER( cmpx_ex )
+{
+ UINT32 r,d;
+ PAIR b;
+ EXTWORD(b);
+ d = X;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $10bC CMPY extended -**** */
+OP_HANDLER( cmpy_ex )
+{
+ UINT32 r,d;
+ PAIR b;
+ EXTWORD(b);
+ d = Y;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $11bC CMPS extended -**** */
+OP_HANDLER( cmps_ex )
+{
+ UINT32 r,d;
+ PAIR b;
+ EXTWORD(b);
+ d = S;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $bD JSR extended ----- */
+OP_HANDLER( jsr_ex )
+{
+ EXTENDED;
+ PUSHWORD(pPC);
+ PCD = EAD;
+}
+
+/* $bE LDX (LDY) extended -**0- */
+OP_HANDLER( ldx_ex )
+{
+ EXTWORD(pX);
+ CLR_NZV;
+ SET_NZ16(X);
+}
+
+/* $11bf MULD extended -**0- */
+OP_HANDLER( muld_ex )
+{
+ PAIR t, q;
+
+ EXTWORD(t);
+ q.d = (INT16) D * (INT16)t.w.l;
+
+ D = q.w.h;
+ W = q.w.l;
+ CLR_NZVC;
+ SET_NZ16(D);
+}
+
+/* $11bd DIVD extended -**0- */
+OP_HANDLER( divd_ex )
+{
+ UINT8 t;
+ INT16 v, oldD;
+
+ EXTBYTE(t);
+
+ if( t != 0 )
+ {
+ oldD = D;
+ v = (INT16) D / (INT8) t;
+ A = (INT16) D % (INT8) t;
+ B = v;
+
+ CLR_NZVC;
+ SET_NZ8(B);
+
+ if( B & 0x01 )
+ SEC;
+
+ if( (INT16)D < 0 )
+ SEN;
+
+ if ( (v > 127) || (v < -128) ) /* soft overflow */
+ {
+ SEV;
+
+ if( (v > 255) || (v < -256) ) /* hard overflow - division is aborted */
+ {
+ SET_NZ16( oldD );
+ D = abs( oldD );
+ }
+ }
+ }
+ else
+ {
+ m68_state->icount -= 8;
+ DZError(m68_state);
+ }
+}
+
+/* $11be DIVQ extended -**0- */
+OP_HANDLER( divq_ex )
+{
+ PAIR t,q, oldQ;
+ INT32 v;
+
+ EXTWORD(t);
+
+ q.w.h = D;
+ q.w.l = W;
+
+ if( t.w.l != 0 )
+ {
+ oldQ = q;
+
+ v = (INT32) q.d / (INT16) t.w.l;
+ D = (INT32) q.d % (INT16) t.w.l;
+ W = v;
+
+ CLR_NZVC;
+ SET_NZ16(W);
+
+ if( W & 0x0001 )
+ SEC;
+
+ if ( (v > 32767) || (v < -32768) ) /* soft overflow */
+ {
+ SEV;
+
+ if( (v > 65535 ) || (v < -65536 ) ) /* hard overflow - division is aborted */
+ {
+ if( (INT32)oldQ.d < 0 )
+ SEN;
+ else if( oldQ.d == 0 )
+ SEZ;
+
+ t.w.l = abs( t.w.l );
+ D = oldQ.w.h;
+ W = oldQ.w.l;
+ }
+ }
+ }
+ else
+ DZError(m68_state);
+}
+
+/* $10fc LDQ extended -**0- */
+OP_HANDLER( ldq_ex )
+{
+ PAIR q;
+
+ EXTLONG(q);
+ D = q.w.h;
+ W = q.w.l;
+ CLR_NZV;
+ SET_N8(A);
+ SET_Z(q.d);
+}
+
+/* $10bE LDY extended -**0- */
+OP_HANDLER( ldy_ex )
+{
+ EXTWORD(pY);
+ CLR_NZV;
+ SET_NZ16(Y);
+}
+
+/* $bF STX (STY) extended -**0- */
+OP_HANDLER( stx_ex )
+{
+ CLR_NZV;
+ SET_NZ16(X);
+ EXTENDED;
+ WM16(m68_state, EAD,&pX);
+}
+
+/* $10fd STQ extended -**0- */
+OP_HANDLER( stq_ex )
+{
+ PAIR q;
+
+ q.w.h = D;
+ q.w.l = W;
+ EXTENDED;
+ WM32(m68_state, EAD,&q);
+ CLR_NZV;
+ SET_N8(A);
+ SET_Z(q.d);
+}
+
+/* $10bF STY extended -**0- */
+OP_HANDLER( sty_ex )
+{
+ CLR_NZV;
+ SET_NZ16(Y);
+ EXTENDED;
+ WM16(m68_state, EAD,&pY);
+}
+
+/* $c0 SUBB immediate ?**** */
+OP_HANDLER( subb_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t);
+ r = B - t;
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+ B = r;
+}
+
+/* $1180 SUBE immediate ?**** */
+OP_HANDLER( sube_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t);
+ r = E - t;
+ CLR_NZVC;
+ SET_FLAGS8(E,t,r);
+ E = r;
+}
+
+/* $11C0 SUBF immediate ?**** */
+OP_HANDLER( subf_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t);
+ r = F - t;
+ CLR_NZVC;
+ SET_FLAGS8(F,t,r);
+ F = r;
+}
+
+/* $c1 CMPB immediate ?**** */
+OP_HANDLER( cmpb_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t);
+ r = B - t;
+ CLR_NZVC; SET_FLAGS8(B,t,r);
+}
+
+/* $1181 CMPE immediate ?**** */
+OP_HANDLER( cmpe_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t);
+ r = E - t;
+ CLR_NZVC; SET_FLAGS8(E,t,r);
+}
+
+/* $11C1 CMPF immediate ?**** */
+OP_HANDLER( cmpf_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t);
+ r = F - t;
+ CLR_NZVC; SET_FLAGS8(F,t,r);
+}
+
+/* $c2 SBCB immediate ?**** */
+OP_HANDLER( sbcb_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t);
+ r = B - t - (CC & CC_C);
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+ B = r;
+}
+
+/* $1082 SBCD immediate ?**** */
+OP_HANDLER( sbcd_im )
+{
+ PAIR t;
+ UINT32 r;
+ IMMWORD(t);
+ r = D - t.w.l - (CC & CC_C);
+ CLR_NZVC;
+ SET_FLAGS16(D,t.w.l,r);
+ D = r;
+}
+
+/* $c3 ADDD immediate -**** */
+OP_HANDLER( addd_im )
+{
+ UINT32 r,d;
+ PAIR b;
+ IMMWORD(b);
+ d = D;
+ r = d + b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ D = r;
+}
+
+/* $108b ADDW immediate -**** */
+OP_HANDLER( addw_im )
+{
+ UINT32 r,d;
+ PAIR b;
+ IMMWORD(b);
+ d = W;
+ r = d + b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ W = r;
+}
+
+/* $118b ADDE immediate -**** */
+OP_HANDLER( adde_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t);
+ r = E + t;
+ CLR_HNZVC;
+ SET_FLAGS8(E,t,r);
+ SET_H(E,t,r);
+ E = r;
+}
+
+/* $11Cb ADDF immediate -**** */
+OP_HANDLER( addf_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t);
+ r = F + t;
+ CLR_HNZVC;
+ SET_FLAGS8(F,t,r);
+ SET_H(F,t,r);
+ F = r;
+}
+
+/* $c4 ANDB immediate -**0- */
+OP_HANDLER( andb_im )
+{
+ UINT8 t;
+ IMMBYTE(t);
+ B &= t;
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $1084 ANDD immediate -**0- */
+OP_HANDLER( andd_im )
+{
+ PAIR t;
+ IMMWORD(t);
+ D &= t.w.l;
+ CLR_NZV;
+ SET_NZ16(D);
+}
+
+/* $c5 BITB immediate -**0- */
+OP_HANDLER( bitb_im )
+{
+ UINT8 t,r;
+ IMMBYTE(t);
+ r = B & t;
+ CLR_NZV;
+ SET_NZ8(r);
+}
+
+/* $1085 BITD immediate -**0- */
+OP_HANDLER( bitd_im )
+{
+ PAIR t;
+ UINT16 r;
+ IMMWORD(t);
+ r = B & t.w.l;
+ CLR_NZV;
+ SET_NZ16(r);
+}
+
+/* $113c BITMD immediate -**0- */
+OP_HANDLER( bitmd_im )
+{
+ /*
+ The following is from Darren A.
+
+ The Z flag is the only condition code that should be affected by BITMD.
+ For example, when the "Divide-By-Zero" flag (bit 7) is set, BITMD should
+ not set the N flag. It should also NOT clear the V flag (unlike the other
+ BIT instructions).
+
+ His comments come from experimentation and differ from Chris Burke
+ */
+
+ UINT8 t,r;
+ IMMBYTE(t);
+ r = MD & t;
+ CLR_Z;
+ SET_Z8(r);
+
+ MD &= ~(r & 0xc0); /* clear the tested high bits */
+
+}
+
+/* $c6 LDB immediate -**0- */
+OP_HANDLER( ldb_im )
+{
+ IMMBYTE(B);
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $113d LDMD immediate -**0- */
+OP_HANDLER( ldmd_im )
+{
+ IMMBYTE(MD);
+ UpdateState(m68_state);
+}
+
+/* $1186 LDE immediate -**0- */
+OP_HANDLER( lde_im )
+{
+ IMMBYTE(E);
+ CLR_NZV;
+ SET_NZ8(E);
+}
+
+/* $11C6 LDF immediate -**0- */
+OP_HANDLER( ldf_im )
+{
+ IMMBYTE(F);
+ CLR_NZV;
+ SET_NZ8(F);
+}
+
+/* $c8 EORB immediate -**0- */
+OP_HANDLER( eorb_im )
+{
+ UINT8 t;
+ IMMBYTE(t);
+ B ^= t;
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $1088 EORD immediate -**0- */
+OP_HANDLER( eord_im )
+{
+ PAIR t;
+ IMMWORD(t);
+ D ^= t.w.l;
+ CLR_NZV;
+ SET_NZ16(D);
+}
+
+/* $c9 ADCB immediate ***** */
+OP_HANDLER( adcb_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t);
+ r = B + t + (CC & CC_C);
+ CLR_HNZVC;
+ SET_FLAGS8(B,t,r);
+ SET_H(B,t,r);
+ B = r;
+}
+
+/* $1089 ADCD immediate ***** */
+OP_HANDLER( adcd_im )
+{
+ PAIR t;
+ UINT32 r;
+ IMMWORD(t);
+ r = D + t.w.l + (CC & CC_C);
+ CLR_NZVC;
+ SET_FLAGS16(D,t.w.l,r);
+ D = r;
+}
+
+/* $cA ORB immediate -**0- */
+OP_HANDLER( orb_im )
+{
+ UINT8 t;
+ IMMBYTE(t);
+ B |= t;
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $108a ORD immediate -**0- */
+OP_HANDLER( ord_im )
+{
+ PAIR t;
+ IMMWORD(t);
+ D |= t.w.l;
+ CLR_NZV;
+ SET_NZ16(D);
+}
+
+/* $cB ADDB immediate ***** */
+OP_HANDLER( addb_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t);
+ r = B + t;
+ CLR_HNZVC;
+ SET_FLAGS8(B,t,r);
+ SET_H(B,t,r);
+ B = r;
+}
+
+/* $cC LDD immediate -**0- */
+OP_HANDLER( ldd_im )
+{
+ PAIR t;
+
+ IMMWORD(t);
+ D=t.w.l;
+ CLR_NZV;
+ SET_NZ16(D);
+}
+
+/* $1086 LDW immediate -**0- */
+OP_HANDLER( ldw_im )
+{
+ PAIR t;
+ IMMWORD(t);
+ W=t.w.l;
+ CLR_NZV;
+ SET_NZ16(W);
+}
+
+/* $cE LDU (LDS) immediate -**0- */
+OP_HANDLER( ldu_im )
+{
+ IMMWORD(pU);
+ CLR_NZV;
+ SET_NZ16(U);
+}
+
+/* $10cE LDS immediate -**0- */
+OP_HANDLER( lds_im )
+{
+ IMMWORD(pS);
+ CLR_NZV;
+ SET_NZ16(S);
+ m68_state->int_state |= M6809_LDS;
+}
+
+/* $d0 SUBB direct ?**** */
+OP_HANDLER( subb_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = B - t;
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+ B = r;
+}
+
+/* $1190 SUBE direct ?**** */
+OP_HANDLER( sube_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = E - t;
+ CLR_NZVC;
+ SET_FLAGS8(E,t,r);
+ E = r;
+}
+
+/* $11d0 SUBF direct ?**** */
+OP_HANDLER( subf_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = F - t;
+ CLR_NZVC;
+ SET_FLAGS8(F,t,r);
+ F = r;
+}
+
+/* $d1 CMPB direct ?**** */
+OP_HANDLER( cmpb_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = B - t;
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+}
+
+/* $1191 CMPE direct ?**** */
+OP_HANDLER( cmpe_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = E - t;
+ CLR_NZVC;
+ SET_FLAGS8(E,t,r);
+}
+
+/* $11D1 CMPF direct ?**** */
+OP_HANDLER( cmpf_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = F - t;
+ CLR_NZVC;
+ SET_FLAGS8(F,t,r);
+}
+
+/* $d2 SBCB direct ?**** */
+OP_HANDLER( sbcb_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = B - t - (CC & CC_C);
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+ B = r;
+}
+
+/* $1092 SBCD direct ?**** */
+OP_HANDLER( sbcd_di )
+{
+ PAIR t;
+ UINT32 r;
+ DIRWORD(t);
+ r = D - t.w.l - (CC & CC_C);
+ CLR_NZVC;
+ SET_FLAGS16(D,t.w.l,r);
+ D = r;
+}
+
+/* $d3 ADDD direct -**** */
+OP_HANDLER( addd_di )
+{
+ UINT32 r,d;
+ PAIR b;
+ DIRWORD(b);
+ d = D;
+ r = d + b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ D = r;
+}
+
+/* $109b ADDW direct -**** */
+OP_HANDLER( addw_di )
+{
+ UINT32 r,d;
+ PAIR b;
+ DIRWORD(b);
+ d = W;
+ r = d + b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ W = r;
+}
+
+/* $119b ADDE direct -**** */
+OP_HANDLER( adde_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = E + t;
+ CLR_HNZVC;
+ SET_FLAGS8(E,t,r);
+ SET_H(E,t,r);
+ E = r;
+}
+
+/* $11db ADDF direct -**** */
+OP_HANDLER( addf_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = F + t;
+ CLR_HNZVC;
+ SET_FLAGS8(F,t,r);
+ SET_H(F,t,r);
+ F = r;
+}
+
+/* $d4 ANDB direct -**0- */
+OP_HANDLER( andb_di )
+{
+ UINT8 t;
+ DIRBYTE(t);
+ B &= t;
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $1094 ANDD direct -**0- */
+OP_HANDLER( andd_di )
+{
+ PAIR t;
+ DIRWORD(t);
+ D &= t.w.l;
+ CLR_NZV;
+ SET_NZ16(D);
+}
+
+/* $d5 BITB direct -**0- */
+OP_HANDLER( bitb_di )
+{
+ UINT8 t,r;
+ DIRBYTE(t);
+ r = B & t;
+ CLR_NZV;
+ SET_NZ8(r);
+}
+
+/* $1095 BITD direct -**0- */
+OP_HANDLER( bitd_di )
+{
+ PAIR t;
+ UINT16 r;
+ DIRWORD(t);
+ r = B & t.w.l;
+ CLR_NZV;
+ SET_NZ16(r);
+}
+
+/* $d6 LDB direct -**0- */
+OP_HANDLER( ldb_di )
+{
+ DIRBYTE(B);
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $1196 LDE direct -**0- */
+OP_HANDLER( lde_di )
+{
+ DIRBYTE(E);
+ CLR_NZV;
+ SET_NZ8(E);
+}
+
+/* $11d6 LDF direct -**0- */
+OP_HANDLER( ldf_di )
+{
+ DIRBYTE(F);
+ CLR_NZV;
+ SET_NZ8(F);
+}
+
+/* $d7 STB direct -**0- */
+OP_HANDLER( stb_di )
+{
+ CLR_NZV;
+ SET_NZ8(B);
+ DIRECT;
+ WM(EAD,B);
+}
+
+/* $1197 STE direct -**0- */
+OP_HANDLER( ste_di )
+{
+ CLR_NZV;
+ SET_NZ8(E);
+ DIRECT;
+ WM(EAD,E);
+}
+
+/* $11D7 STF direct -**0- */
+OP_HANDLER( stf_di )
+{
+ CLR_NZV;
+ SET_NZ8(F);
+ DIRECT;
+ WM(EAD,F);
+}
+
+/* $d8 EORB direct -**0- */
+OP_HANDLER( eorb_di )
+{
+ UINT8 t;
+ DIRBYTE(t);
+ B ^= t;
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $1098 EORD direct -**0- */
+OP_HANDLER( eord_di )
+{
+ PAIR t;
+ DIRWORD(t);
+ D ^= t.w.l;
+ CLR_NZV;
+ SET_NZ16(D);
+}
+
+/* $d9 ADCB direct ***** */
+OP_HANDLER( adcb_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = B + t + (CC & CC_C);
+ CLR_HNZVC;
+ SET_FLAGS8(B,t,r);
+ SET_H(B,t,r);
+ B = r;
+}
+
+/* $1099 adcd direct ***** */
+OP_HANDLER( adcd_di )
+{
+ UINT32 r;
+ PAIR t;
+
+ DIRWORD(t);
+ r = D + t.w.l + (CC & CC_C);
+ CLR_NZVC;
+ SET_FLAGS16(D,t.w.l,r);
+ D = r;
+}
+
+/* $dA ORB direct -**0- */
+OP_HANDLER( orb_di )
+{
+ UINT8 t;
+ DIRBYTE(t);
+ B |= t;
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $109a ORD direct -**0- */
+OP_HANDLER( ord_di )
+{
+ PAIR t;
+ DIRWORD(t);
+ D |= t.w.l;
+ CLR_NZV;
+ SET_NZ16(D);
+}
+
+/* $dB ADDB direct ***** */
+OP_HANDLER( addb_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = B + t;
+ CLR_HNZVC;
+ SET_FLAGS8(B,t,r);
+ SET_H(B,t,r);
+ B = r;
+}
+
+/* $dC LDD direct -**0- */
+OP_HANDLER( ldd_di )
+{
+ PAIR t;
+ DIRWORD(t);
+ D=t.w.l;
+ CLR_NZV;
+ SET_NZ16(D);
+}
+
+/* $1096 LDW direct -**0- */
+OP_HANDLER( ldw_di )
+{
+ PAIR t;
+ DIRWORD(t);
+ W=t.w.l;
+ CLR_NZV;
+ SET_NZ16(W);
+}
+
+/* $dD STD direct -**0- */
+OP_HANDLER( std_di )
+{
+ CLR_NZV;
+ SET_NZ16(D);
+ DIRECT;
+ WM16(m68_state, EAD,&pD);
+}
+
+/* $1097 STW direct -**0- */
+OP_HANDLER( stw_di )
+{
+ CLR_NZV;
+ SET_NZ16(W);
+ DIRECT;
+ WM16(m68_state, EAD,&pW);
+}
+
+/* $dE LDU (LDS) direct -**0- */
+OP_HANDLER( ldu_di )
+{
+ DIRWORD(pU);
+ CLR_NZV;
+ SET_NZ16(U);
+}
+
+/* $10dE LDS direct -**0- */
+OP_HANDLER( lds_di )
+{
+ DIRWORD(pS);
+ CLR_NZV;
+ SET_NZ16(S);
+ m68_state->int_state |= M6809_LDS;
+}
+
+/* $dF STU (STS) direct -**0- */
+OP_HANDLER( stu_di )
+{
+ CLR_NZV;
+ SET_NZ16(U);
+ DIRECT;
+ WM16(m68_state, EAD,&pU);
+}
+
+/* $10dF STS direct -**0- */
+OP_HANDLER( sts_di )
+{
+ CLR_NZV;
+ SET_NZ16(S);
+ DIRECT;
+ WM16(m68_state, EAD,&pS);
+}
+
+/* $e0 SUBB indexed ?**** */
+OP_HANDLER( subb_ix )
+{
+ UINT16 t,r;
+ fetch_effective_address(m68_state);
+ t = RM(EAD);
+ r = B - t;
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+ B = r;
+}
+
+/* $11a0 SUBE indexed ?**** */
+OP_HANDLER( sube_ix )
+{
+ UINT16 t,r;
+ fetch_effective_address(m68_state);
+ t = RM(EAD);
+ r = E - t;
+ CLR_NZVC;
+ SET_FLAGS8(E,t,r);
+ E = r;
+}
+
+/* $11e0 SUBF indexed ?**** */
+OP_HANDLER( subf_ix )
+{
+ UINT16 t,r;
+ fetch_effective_address(m68_state);
+ t = RM(EAD);
+ r = F - t;
+ CLR_NZVC;
+ SET_FLAGS8(F,t,r);
+ F = r;
+}
+
+/* $e1 CMPB indexed ?**** */
+OP_HANDLER( cmpb_ix )
+{
+ UINT16 t,r;
+ fetch_effective_address(m68_state);
+ t = RM(EAD);
+ r = B - t;
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+}
+
+/* $11a1 CMPE indexed ?**** */
+OP_HANDLER( cmpe_ix )
+{
+ UINT16 t,r;
+ fetch_effective_address(m68_state);
+ t = RM(EAD);
+ r = E - t;
+ CLR_NZVC;
+ SET_FLAGS8(E,t,r);
+}
+
+/* $11e1 CMPF indexed ?**** */
+OP_HANDLER( cmpf_ix )
+{
+ UINT16 t,r;
+ fetch_effective_address(m68_state);
+ t = RM(EAD);
+ r = F - t;
+ CLR_NZVC;
+ SET_FLAGS8(F,t,r);
+}
+
+/* $e2 SBCB indexed ?**** */
+OP_HANDLER( sbcb_ix )
+{
+ UINT16 t,r;
+ fetch_effective_address(m68_state);
+ t = RM(EAD);
+ r = B - t - (CC & CC_C);
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+ B = r;
+}
+
+/* $10a2 SBCD indexed ?**** */
+OP_HANDLER( sbcd_ix )
+{
+ UINT32 t,r;
+ fetch_effective_address(m68_state);
+ t = RM16(m68_state, EAD);
+ r = D - t - (CC & CC_C);
+ CLR_NZVC;
+ SET_FLAGS16(D,t,r);
+ D = r;
+}
+
+/* $e3 ADDD indexed -**** */
+OP_HANDLER( addd_ix )
+{
+ UINT32 r,d;
+ PAIR b;
+ fetch_effective_address(m68_state);
+ b.d=RM16(m68_state, EAD);
+ d = D;
+ r = d + b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ D = r;
+}
+
+/* $10ab ADDW indexed -**** */
+OP_HANDLER( addw_ix )
+{
+ UINT32 r,d;
+ PAIR b;
+ fetch_effective_address(m68_state);
+ b.d=RM16(m68_state, EAD);
+ d = W;
+ r = d + b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ W = r;
+}
+
+/* $11ab ADDE indexed -**** */
+OP_HANDLER( adde_ix )
+{
+ UINT16 t,r;
+ fetch_effective_address(m68_state);
+ t = RM(EAD);
+ r = E + t;
+ CLR_HNZVC;
+ SET_FLAGS8(E,t,r);
+ SET_H(E,t,r);
+ E = r;
+}
+
+/* $11eb ADDF indexed -**** */
+OP_HANDLER( addf_ix )
+{
+ UINT16 t,r;
+ fetch_effective_address(m68_state);
+ t = RM(EAD);
+ r = F + t;
+ CLR_HNZVC;
+ SET_FLAGS8(F,t,r);
+ SET_H(F,t,r);
+ F = r;
+}
+
+/* $e4 ANDB indexed -**0- */
+OP_HANDLER( andb_ix )
+{
+ fetch_effective_address(m68_state);
+ B &= RM(EAD);
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $10a4 ANDD indexed -**0- */
+OP_HANDLER( andd_ix )
+{
+ fetch_effective_address(m68_state);
+ D &= RM16(m68_state, EAD);
+ CLR_NZV;
+ SET_NZ16(D);
+}
+
+/* $e5 BITB indexed -**0- */
+OP_HANDLER( bitb_ix )
+{
+ UINT8 r;
+ fetch_effective_address(m68_state);
+ r = B & RM(EAD);
+ CLR_NZV;
+ SET_NZ8(r);
+}
+
+/* $10a5 BITD indexed -**0- */
+OP_HANDLER( bitd_ix )
+{
+ UINT16 r;
+ fetch_effective_address(m68_state);
+ r = D & RM16(m68_state, EAD);
+ CLR_NZV;
+ SET_NZ16(r);
+}
+
+/* $e6 LDB indexed -**0- */
+OP_HANDLER( ldb_ix )
+{
+ fetch_effective_address(m68_state);
+ B = RM(EAD);
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $11a6 LDE indexed -**0- */
+OP_HANDLER( lde_ix )
+{
+ fetch_effective_address(m68_state);
+ E = RM(EAD);
+ CLR_NZV;
+ SET_NZ8(E);
+}
+
+/* $11e6 LDF indexed -**0- */
+OP_HANDLER( ldf_ix )
+{
+ fetch_effective_address(m68_state);
+ F = RM(EAD);
+ CLR_NZV;
+ SET_NZ8(F);
+}
+
+/* $e7 STB indexed -**0- */
+OP_HANDLER( stb_ix )
+{
+ fetch_effective_address(m68_state);
+ CLR_NZV;
+ SET_NZ8(B);
+ WM(EAD,B);
+}
+
+/* $11a7 STE indexed -**0- */
+OP_HANDLER( ste_ix )
+{
+ fetch_effective_address(m68_state);
+ CLR_NZV;
+ SET_NZ8(E);
+ WM(EAD,E);
+}
+
+/* $11e7 STF indexed -**0- */
+OP_HANDLER( stf_ix )
+{
+ fetch_effective_address(m68_state);
+ CLR_NZV;
+ SET_NZ8(F);
+ WM(EAD,F);
+}
+
+/* $e8 EORB indexed -**0- */
+OP_HANDLER( eorb_ix )
+{
+ fetch_effective_address(m68_state);
+ B ^= RM(EAD);
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $10a8 EORD indexed -**0- */
+OP_HANDLER( eord_ix )
+{
+ fetch_effective_address(m68_state);
+ D ^= RM16(m68_state, EAD);
+ CLR_NZV;
+ SET_NZ16(D);
+}
+
+/* $e9 ADCB indexed ***** */
+OP_HANDLER( adcb_ix )
+{
+ UINT16 t,r;
+ fetch_effective_address(m68_state);
+ t = RM(EAD);
+ r = B + t + (CC & CC_C);
+ CLR_HNZVC;
+ SET_FLAGS8(B,t,r);
+ SET_H(B,t,r);
+ B = r;
+}
+
+/* $10a9 ADCD indexed ***** */
+OP_HANDLER( adcd_ix )
+{
+ UINT32 r;
+ PAIR t;
+ fetch_effective_address(m68_state);
+ t.d = RM16(m68_state, EAD);
+ r = D + t.d + (CC & CC_C);
+ CLR_NZVC;
+ SET_FLAGS16(D,t.d,r);
+ D = r;
+}
+
+/* $eA ORB indexed -**0- */
+OP_HANDLER( orb_ix )
+{
+ fetch_effective_address(m68_state);
+ B |= RM(EAD);
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $10aa ORD indexed -**0- */
+OP_HANDLER( ord_ix )
+{
+ fetch_effective_address(m68_state);
+ D |= RM16(m68_state, EAD);
+ CLR_NZV;
+ SET_NZ16(D);
+}
+
+/* $eB ADDB indexed ***** */
+OP_HANDLER( addb_ix )
+{
+ UINT16 t,r;
+ fetch_effective_address(m68_state);
+ t = RM(EAD);
+ r = B + t;
+ CLR_HNZVC;
+ SET_FLAGS8(B,t,r);
+ SET_H(B,t,r);
+ B = r;
+}
+
+/* $eC LDD indexed -**0- */
+OP_HANDLER( ldd_ix )
+{
+ fetch_effective_address(m68_state);
+ D=RM16(m68_state, EAD);
+ CLR_NZV; SET_NZ16(D);
+}
+
+/* $10a6 LDW indexed -**0- */
+OP_HANDLER( ldw_ix )
+{
+ fetch_effective_address(m68_state);
+ W=RM16(m68_state, EAD);
+ CLR_NZV; SET_NZ16(W);
+}
+
+/* $eD STD indexed -**0- */
+OP_HANDLER( std_ix )
+{
+ fetch_effective_address(m68_state);
+ CLR_NZV;
+ SET_NZ16(D);
+ WM16(m68_state, EAD,&pD);
+}
+
+/* $10a7 STW indexed -**0- */
+OP_HANDLER( stw_ix )
+{
+ fetch_effective_address(m68_state);
+ CLR_NZV;
+ SET_NZ16(W);
+ WM16(m68_state, EAD,&pW);
+}
+
+/* $eE LDU (LDS) indexed -**0- */
+OP_HANDLER( ldu_ix )
+{
+ fetch_effective_address(m68_state);
+ U=RM16(m68_state, EAD);
+ CLR_NZV;
+ SET_NZ16(U);
+}
+
+/* $10eE LDS indexed -**0- */
+OP_HANDLER( lds_ix )
+{
+ fetch_effective_address(m68_state);
+ S=RM16(m68_state, EAD);
+ CLR_NZV;
+ SET_NZ16(S);
+ m68_state->int_state |= M6809_LDS;
+}
+
+/* $eF STU (STS) indexed -**0- */
+OP_HANDLER( stu_ix )
+{
+ fetch_effective_address(m68_state);
+ CLR_NZV;
+ SET_NZ16(U);
+ WM16(m68_state, EAD,&pU);
+}
+
+/* $10eF STS indexed -**0- */
+OP_HANDLER( sts_ix )
+{
+ fetch_effective_address(m68_state);
+ CLR_NZV;
+ SET_NZ16(S);
+ WM16(m68_state, EAD,&pS);
+}
+
+/* $f0 SUBB extended ?**** */
+OP_HANDLER( subb_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = B - t;
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+ B = r;
+}
+
+/* $11b0 SUBE extended ?**** */
+OP_HANDLER( sube_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = E - t;
+ CLR_NZVC;
+ SET_FLAGS8(E,t,r);
+ E = r;
+}
+
+/* $11f0 SUBF extended ?**** */
+OP_HANDLER( subf_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = F - t;
+ CLR_NZVC;
+ SET_FLAGS8(F,t,r);
+ F = r;
+}
+
+/* $f1 CMPB extended ?**** */
+OP_HANDLER( cmpb_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = B - t;
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+}
+
+/* $11b1 CMPE extended ?**** */
+OP_HANDLER( cmpe_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = E - t;
+ CLR_NZVC;
+ SET_FLAGS8(E,t,r);
+}
+
+/* $11f1 CMPF extended ?**** */
+OP_HANDLER( cmpf_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = F - t;
+ CLR_NZVC;
+ SET_FLAGS8(F,t,r);
+}
+
+/* $f2 SBCB extended ?**** */
+OP_HANDLER( sbcb_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = B - t - (CC & CC_C);
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+ B = r;
+}
+
+/* $10b2 SBCD extended ?**** */
+OP_HANDLER( sbcd_ex )
+{
+ PAIR t = {{0,}};
+ UINT32 r;
+
+ EXTWORD(t);
+ r = D - t.w.l - (CC & CC_C);
+ CLR_NZVC;
+ SET_FLAGS16(D,t.w.l,r);
+ D = r;
+}
+
+/* $f3 ADDD extended -**** */
+OP_HANDLER( addd_ex )
+{
+ UINT32 r,d;
+ PAIR b;
+ EXTWORD(b);
+ d = D;
+ r = d + b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ D = r;
+}
+
+/* $10bb ADDW extended -**** */
+OP_HANDLER( addw_ex )
+{
+ UINT32 r,d;
+ PAIR b = {{0,}};
+ EXTWORD(b);
+ d = W;
+ r = d + b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ W = r;
+}
+
+/* $11bb ADDE extended -**** */
+OP_HANDLER( adde_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = E + t;
+ CLR_HNZVC;
+ SET_FLAGS8(E,t,r);
+ SET_H(E,t,r);
+ E = r;
+}
+
+/* $11fb ADDF extended -**** */
+OP_HANDLER( addf_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = F + t;
+ CLR_HNZVC;
+ SET_FLAGS8(F,t,r);
+ SET_H(F,t,r);
+ F = r;
+}
+
+/* $f4 ANDB extended -**0- */
+OP_HANDLER( andb_ex )
+{
+ UINT8 t;
+ EXTBYTE(t);
+ B &= t;
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $10b4 ANDD extended -**0- */
+OP_HANDLER( andd_ex )
+{
+ PAIR t = {{0,}};
+ EXTWORD(t);
+ D &= t.w.l;
+ CLR_NZV;
+ SET_NZ16(D);
+}
+
+/* $f5 BITB extended -**0- */
+OP_HANDLER( bitb_ex )
+{
+ UINT8 t,r;
+ EXTBYTE(t);
+ r = B & t;
+ CLR_NZV;
+ SET_NZ8(r);
+}
+
+/* $10b5 BITD extended -**0- */
+OP_HANDLER( bitd_ex )
+{
+ PAIR t = {{0,}};
+ UINT8 r;
+ EXTWORD(t);
+ r = B & t.w.l;
+ CLR_NZV;
+ SET_NZ16(r);
+}
+
+/* $f6 LDB extended -**0- */
+OP_HANDLER( ldb_ex )
+{
+ EXTBYTE(B);
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $11b6 LDE extended -**0- */
+OP_HANDLER( lde_ex )
+{
+ EXTBYTE(E);
+ CLR_NZV;
+ SET_NZ8(E);
+}
+
+/* $11f6 LDF extended -**0- */
+OP_HANDLER( ldf_ex )
+{
+ EXTBYTE(F);
+ CLR_NZV;
+ SET_NZ8(F);
+}
+
+/* $f7 STB extended -**0- */
+OP_HANDLER( stb_ex )
+{
+ CLR_NZV;
+ SET_NZ8(B);
+ EXTENDED;
+ WM(EAD,B);
+}
+
+/* $11b7 STE extended -**0- */
+OP_HANDLER( ste_ex )
+{
+ CLR_NZV;
+ SET_NZ8(E);
+ EXTENDED;
+ WM(EAD,E);
+}
+
+/* $11f7 STF extended -**0- */
+OP_HANDLER( stf_ex )
+{
+ CLR_NZV;
+ SET_NZ8(F);
+ EXTENDED;
+ WM(EAD,F);
+}
+
+/* $f8 EORB extended -**0- */
+OP_HANDLER( eorb_ex )
+{
+ UINT8 t;
+ EXTBYTE(t);
+ B ^= t;
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $10b8 EORD extended -**0- */
+OP_HANDLER( eord_ex )
+{
+ PAIR t = {{0,}};
+ EXTWORD(t);
+ D ^= t.w.l;
+ CLR_NZV;
+ SET_NZ16(D);
+}
+
+/* $f9 ADCB extended ***** */
+OP_HANDLER( adcb_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = B + t + (CC & CC_C);
+ CLR_HNZVC;
+ SET_FLAGS8(B,t,r);
+ SET_H(B,t,r);
+ B = r;
+}
+
+/* $10b9 ADCD extended ***** */
+OP_HANDLER( adcd_ex )
+{
+ UINT32 r;
+ PAIR t;
+ EXTWORD(t);
+ r = D + t.w.l + (CC & CC_C);
+ CLR_NZVC;
+ SET_FLAGS16(D,t.w.l,r);
+ D = r;
+}
+
+/* $fA ORB extended -**0- */
+OP_HANDLER( orb_ex )
+{
+ UINT8 t;
+ EXTBYTE(t);
+ B |= t;
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $10ba ORD extended -**0- */
+OP_HANDLER( ord_ex )
+{
+ PAIR t = {{0,}};
+ EXTWORD(t);
+ D |= t.w.l;
+ CLR_NZV;
+ SET_NZ8(D);
+}
+
+/* $fB ADDB extended ***** */
+OP_HANDLER( addb_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = B + t;
+ CLR_HNZVC;
+ SET_FLAGS8(B,t,r);
+ SET_H(B,t,r);
+ B = r;
+}
+
+/* $fC LDD extended -**0- */
+OP_HANDLER( ldd_ex )
+{
+ EXTWORD(pD);
+ CLR_NZV;
+ SET_NZ16(D);
+}
+
+/* $10b6 LDW extended -**0- */
+OP_HANDLER( ldw_ex )
+{
+ EXTWORD(pW);
+ CLR_NZV;
+ SET_NZ16(W);
+}
+
+/* $fD STD extended -**0- */
+OP_HANDLER( std_ex )
+{
+ CLR_NZV;
+ SET_NZ16(D);
+ EXTENDED;
+ WM16(m68_state, EAD,&pD);
+}
+
+/* $10b7 STW extended -**0- */
+OP_HANDLER( stw_ex )
+{
+ CLR_NZV;
+ SET_NZ16(W);
+ EXTENDED;
+ WM16(m68_state, EAD,&pW);
+}
+
+/* $fE LDU (LDS) extended -**0- */
+OP_HANDLER( ldu_ex )
+{
+ EXTWORD(pU);
+ CLR_NZV;
+ SET_NZ16(U);
+}
+
+/* $10fE LDS extended -**0- */
+OP_HANDLER( lds_ex )
+{
+ EXTWORD(pS);
+ CLR_NZV;
+ SET_NZ16(S);
+ m68_state->int_state |= M6809_LDS;
+}
+
+/* $fF STU (STS) extended -**0- */
+OP_HANDLER( stu_ex )
+{
+ CLR_NZV;
+ SET_NZ16(U);
+ EXTENDED;
+ WM16(m68_state, EAD,&pU);
+}
+
+/* $10fF STS extended -**0- */
+OP_HANDLER( sts_ex )
+{
+ CLR_NZV;
+ SET_NZ16(S);
+ EXTENDED;
+ WM16(m68_state, EAD,&pS);
+}
+
+/* $10xx opcodes */
+OP_HANDLER( pref10 )
+{
+ UINT8 ireg2 = ROP(PCD);
+ PC++;
+
+#if BIG_SWITCH
+ switch( ireg2 )
+ {
+ case 0x21: lbrn(m68_state); break;
+ case 0x22: lbhi(m68_state); break;
+ case 0x23: lbls(m68_state); break;
+ case 0x24: lbcc(m68_state); break;
+ case 0x25: lbcs(m68_state); break;
+ case 0x26: lbne(m68_state); break;
+ case 0x27: lbeq(m68_state); break;
+ case 0x28: lbvc(m68_state); break;
+ case 0x29: lbvs(m68_state); break;
+ case 0x2a: lbpl(m68_state); break;
+ case 0x2b: lbmi(m68_state); break;
+ case 0x2c: lbge(m68_state); break;
+ case 0x2d: lblt(m68_state); break;
+ case 0x2e: lbgt(m68_state); break;
+ case 0x2f: lble(m68_state); break;
+
+ case 0x30: addr_r(m68_state); break;
+ case 0x31: adcr(m68_state); break;
+ case 0x32: subr(m68_state); break;
+ case 0x33: sbcr(m68_state); break;
+ case 0x34: andr(m68_state); break;
+ case 0x35: orr(m68_state); break;
+ case 0x36: eorr(m68_state); break;
+ case 0x37: cmpr(m68_state); break;
+ case 0x38: pshsw(m68_state); break;
+ case 0x39: pulsw(m68_state); break;
+ case 0x3a: pshuw(m68_state); break;
+ case 0x3b: puluw(m68_state); break;
+ case 0x3f: swi2(m68_state); break;
+
+ case 0x40: negd(m68_state); break;
+ case 0x43: comd(m68_state); break;
+ case 0x44: lsrd(m68_state); break;
+ case 0x46: rord(m68_state); break;
+ case 0x47: asrd(m68_state); break;
+ case 0x48: asld(m68_state); break;
+ case 0x49: rold(m68_state); break;
+ case 0x4a: decd(m68_state); break;
+ case 0x4c: incd(m68_state); break;
+ case 0x4d: tstd(m68_state); break;
+ case 0x4f: clrd(m68_state); break;
+
+ case 0x53: comw(m68_state); break;
+ case 0x54: lsrw(m68_state); break;
+ case 0x56: rorw(m68_state); break;
+ case 0x59: rolw(m68_state); break;
+ case 0x5a: decw(m68_state); break;
+ case 0x5c: incw(m68_state); break;
+ case 0x5d: tstw(m68_state); break;
+ case 0x5f: clrw(m68_state); break;
+
+ case 0x80: subw_im(m68_state); break;
+ case 0x81: cmpw_im(m68_state); break;
+ case 0x82: sbcd_im(m68_state); break;
+ case 0x83: cmpd_im(m68_state); break;
+ case 0x84: andd_im(m68_state); break;
+ case 0x85: bitd_im(m68_state); break;
+ case 0x86: ldw_im(m68_state); break;
+ case 0x88: eord_im(m68_state); break;
+ case 0x89: adcd_im(m68_state); break;
+ case 0x8a: ord_im(m68_state); break;
+ case 0x8b: addw_im(m68_state); break;
+ case 0x8c: cmpy_im(m68_state); break;
+ case 0x8e: ldy_im(m68_state); break;
+
+ case 0x90: subw_di(m68_state); break;
+ case 0x91: cmpw_di(m68_state); break;
+ case 0x92: sbcd_di(m68_state); break;
+ case 0x93: cmpd_di(m68_state); break;
+ case 0x94: andd_di(m68_state); break;
+ case 0x95: bitd_di(m68_state); break;
+ case 0x96: ldw_di(m68_state); break;
+ case 0x97: stw_di(m68_state); break;
+ case 0x98: eord_di(m68_state); break;
+ case 0x99: adcd_di(m68_state); break;
+ case 0x9a: ord_di(m68_state); break;
+ case 0x9b: addw_di(m68_state); break;
+ case 0x9c: cmpy_di(m68_state); break;
+ case 0x9e: ldy_di(m68_state); break;
+ case 0x9f: sty_di(m68_state); break;
+
+ case 0xa0: subw_ix(m68_state); break;
+ case 0xa1: cmpw_ix(m68_state); break;
+ case 0xa2: sbcd_ix(m68_state); break;
+ case 0xa3: cmpd_ix(m68_state); break;
+ case 0xa4: andd_ix(m68_state); break;
+ case 0xa5: bitd_ix(m68_state); break;
+ case 0xa6: ldw_ix(m68_state); break;
+ case 0xa7: stw_ix(m68_state); break;
+ case 0xa8: eord_ix(m68_state); break;
+ case 0xa9: adcd_ix(m68_state); break;
+ case 0xaa: ord_ix(m68_state); break;
+ case 0xab: addw_ix(m68_state); break;
+ case 0xac: cmpy_ix(m68_state); break;
+ case 0xae: ldy_ix(m68_state); break;
+ case 0xaf: sty_ix(m68_state); break;
+
+ case 0xb0: subw_ex(m68_state); break;
+ case 0xb1: cmpw_ex(m68_state); break;
+ case 0xb2: sbcd_ex(m68_state); break;
+ case 0xb3: cmpd_ex(m68_state); break;
+ case 0xb4: andd_ex(m68_state); break;
+ case 0xb5: bitd_ex(m68_state); break;
+ case 0xb6: ldw_ex(m68_state); break;
+ case 0xb7: stw_ex(m68_state); break;
+ case 0xb8: eord_ex(m68_state); break;
+ case 0xb9: adcd_ex(m68_state); break;
+ case 0xba: ord_ex(m68_state); break;
+ case 0xbb: addw_ex(m68_state); break;
+ case 0xbc: cmpy_ex(m68_state); break;
+ case 0xbe: ldy_ex(m68_state); break;
+ case 0xbf: sty_ex(m68_state); break;
+
+ case 0xce: lds_im(m68_state); break;
+
+ case 0xdc: ldq_di(m68_state); break;
+ case 0xdd: stq_di(m68_state); break;
+ case 0xde: lds_di(m68_state); break;
+ case 0xdf: sts_di(m68_state); break;
+
+ case 0xec: ldq_ix(m68_state); break;
+ case 0xed: stq_ix(m68_state); break;
+ case 0xee: lds_ix(m68_state); break;
+ case 0xef: sts_ix(m68_state); break;
+
+ case 0xfc: ldq_ex(m68_state); break;
+ case 0xfd: stq_ex(m68_state); break;
+ case 0xfe: lds_ex(m68_state); break;
+ case 0xff: sts_ex(m68_state); break;
+
+ default: IIError(m68_state); break;
+ }
+#else
+
+ (*hd6309_page01[ireg2])(m68_state);
+
+#endif /* BIG_SWITCH */
+
+ m68_state->icount -= m68_state->cycle_counts_page01[ireg2];
+}
+
+/* $11xx opcodes */
+OP_HANDLER( pref11 )
+{
+ UINT8 ireg2 = ROP(PCD);
+ PC++;
+
+#if BIG_SWITCH
+ switch( ireg2 )
+ {
+ case 0x30: band(m68_state); break;
+ case 0x31: biand(m68_state); break;
+ case 0x32: bor(m68_state); break;
+ case 0x33: bior(m68_state); break;
+ case 0x34: beor(m68_state); break;
+ case 0x35: bieor(m68_state); break;
+ case 0x36: ldbt(m68_state); break;
+ case 0x37: stbt(m68_state); break;
+ case 0x38: tfmpp(m68_state); break; /* Timing for TFM is actually 6+3n. */
+ case 0x39: tfmmm(m68_state); break; /* To avoid saving the state, I decided */
+ case 0x3a: tfmpc(m68_state); break; /* to push the initial 6 cycles to the end */
+ case 0x3b: tfmcp(m68_state); break; /* We will soon see how this fairs! */
+ case 0x3c: bitmd_im(m68_state); break;
+ case 0x3d: ldmd_im(m68_state); break;
+ case 0x3f: swi3(m68_state); break;
+
+ case 0x43: come(m68_state); break;
+ case 0x4a: dece(m68_state); break;
+ case 0x4c: ince(m68_state); break;
+ case 0x4d: tste(m68_state); break;
+ case 0x4f: clre(m68_state); break;
+
+ case 0x53: comf(m68_state); break;
+ case 0x5a: decf(m68_state); break;
+ case 0x5c: incf(m68_state); break;
+ case 0x5d: tstf(m68_state); break;
+ case 0x5f: clrf(m68_state); break;
+
+ case 0x80: sube_im(m68_state); break;
+ case 0x81: cmpe_im(m68_state); break;
+ case 0x83: cmpu_im(m68_state); break;
+ case 0x86: lde_im(m68_state); break;
+ case 0x8b: adde_im(m68_state); break;
+ case 0x8c: cmps_im(m68_state); break;
+ case 0x8d: divd_im(m68_state); break;
+ case 0x8e: divq_im(m68_state); break;
+ case 0x8f: muld_im(m68_state); break;
+
+ case 0x90: sube_di(m68_state); break;
+ case 0x91: cmpe_di(m68_state); break;
+ case 0x93: cmpu_di(m68_state); break;
+ case 0x96: lde_di(m68_state); break;
+ case 0x97: ste_di(m68_state); break;
+ case 0x9b: adde_di(m68_state); break;
+ case 0x9c: cmps_di(m68_state); break;
+ case 0x9d: divd_di(m68_state); break;
+ case 0x9e: divq_di(m68_state); break;
+ case 0x9f: muld_di(m68_state); break;
+
+ case 0xa0: sube_ix(m68_state); break;
+ case 0xa1: cmpe_ix(m68_state); break;
+ case 0xa3: cmpu_ix(m68_state); break;
+ case 0xa6: lde_ix(m68_state); break;
+ case 0xa7: ste_ix(m68_state); break;
+ case 0xab: adde_ix(m68_state); break;
+ case 0xac: cmps_ix(m68_state); break;
+ case 0xad: divd_ix(m68_state); break;
+ case 0xae: divq_ix(m68_state); break;
+ case 0xaf: muld_ix(m68_state); break;
+
+ case 0xb0: sube_ex(m68_state); break;
+ case 0xb1: cmpe_ex(m68_state); break;
+ case 0xb3: cmpu_ex(m68_state); break;
+ case 0xb6: lde_ex(m68_state); break;
+ case 0xb7: ste_ex(m68_state); break;
+ case 0xbb: adde_ex(m68_state); break;
+ case 0xbc: cmps_ex(m68_state); break;
+ case 0xbd: divd_ex(m68_state); break;
+ case 0xbe: divq_ex(m68_state); break;
+ case 0xbf: muld_ex(m68_state); break;
+
+ case 0xc0: subf_im(m68_state); break;
+ case 0xc1: cmpf_im(m68_state); break;
+ case 0xc6: ldf_im(m68_state); break;
+ case 0xcb: addf_im(m68_state); break;
+
+ case 0xd0: subf_di(m68_state); break;
+ case 0xd1: cmpf_di(m68_state); break;
+ case 0xd6: ldf_di(m68_state); break;
+ case 0xd7: stf_di(m68_state); break;
+ case 0xdb: addf_di(m68_state); break;
+
+ case 0xe0: subf_ix(m68_state); break;
+ case 0xe1: cmpf_ix(m68_state); break;
+ case 0xe6: ldf_ix(m68_state); break;
+ case 0xe7: stf_ix(m68_state); break;
+ case 0xeb: addf_ix(m68_state); break;
+
+ case 0xf0: subf_ex(m68_state); break;
+ case 0xf1: cmpf_ex(m68_state); break;
+ case 0xf6: ldf_ex(m68_state); break;
+ case 0xf7: stf_ex(m68_state); break;
+ case 0xfb: addf_ex(m68_state); break;
+
+ default: IIError(m68_state); break;
+ }
+#else
+
+ (*hd6309_page11[ireg2])(m68_state);
+
+#endif /* BIG_SWITCH */
+ m68_state->icount -= m68_state->cycle_counts_page11[ireg2];
+}
+
diff --git a/trunk/src/emu/cpu/hd6309/6309tbl.c b/trunk/src/emu/cpu/hd6309/6309tbl.c
new file mode 100644
index 00000000000..4ae82172247
--- /dev/null
+++ b/trunk/src/emu/cpu/hd6309/6309tbl.c
@@ -0,0 +1,814 @@
+INLINE void abx(m68_state_t *m68_state);
+INLINE void adca_di(m68_state_t *m68_state);
+INLINE void adca_ex(m68_state_t *m68_state);
+INLINE void adca_im(m68_state_t *m68_state);
+INLINE void adca_ix(m68_state_t *m68_state);
+INLINE void adcb_di(m68_state_t *m68_state);
+INLINE void adcb_ex(m68_state_t *m68_state);
+INLINE void adcb_im(m68_state_t *m68_state);
+INLINE void adcb_ix(m68_state_t *m68_state);
+INLINE void adcd_di(m68_state_t *m68_state);
+INLINE void adcd_ex(m68_state_t *m68_state);
+INLINE void adcd_im(m68_state_t *m68_state);
+INLINE void adcd_ix(m68_state_t *m68_state);
+INLINE void adcr(m68_state_t *m68_state);
+INLINE void adda_di(m68_state_t *m68_state);
+INLINE void adda_ex(m68_state_t *m68_state);
+INLINE void adda_im(m68_state_t *m68_state);
+INLINE void adda_ix(m68_state_t *m68_state);
+INLINE void addb_di(m68_state_t *m68_state);
+INLINE void addb_ex(m68_state_t *m68_state);
+INLINE void addb_im(m68_state_t *m68_state);
+INLINE void addb_ix(m68_state_t *m68_state);
+INLINE void addd_di(m68_state_t *m68_state);
+INLINE void addd_ex(m68_state_t *m68_state);
+INLINE void addd_im(m68_state_t *m68_state);
+INLINE void addd_ix(m68_state_t *m68_state);
+INLINE void adde_di(m68_state_t *m68_state);
+INLINE void adde_ex(m68_state_t *m68_state);
+INLINE void adde_im(m68_state_t *m68_state);
+INLINE void adde_ix(m68_state_t *m68_state);
+INLINE void addf_di(m68_state_t *m68_state);
+INLINE void addf_ex(m68_state_t *m68_state);
+INLINE void addf_im(m68_state_t *m68_state);
+INLINE void addf_ix(m68_state_t *m68_state);
+INLINE void addr_r(m68_state_t *m68_state);
+INLINE void addw_di(m68_state_t *m68_state);
+INLINE void addw_ex(m68_state_t *m68_state);
+INLINE void addw_im(m68_state_t *m68_state);
+INLINE void addw_ix(m68_state_t *m68_state);
+INLINE void aim_di(m68_state_t *m68_state);
+INLINE void aim_ex(m68_state_t *m68_state);
+INLINE void aim_ix(m68_state_t *m68_state);
+INLINE void anda_di(m68_state_t *m68_state);
+INLINE void anda_ex(m68_state_t *m68_state);
+INLINE void anda_im(m68_state_t *m68_state);
+INLINE void anda_ix(m68_state_t *m68_state);
+INLINE void andb_di(m68_state_t *m68_state);
+INLINE void andb_ex(m68_state_t *m68_state);
+INLINE void andb_im(m68_state_t *m68_state);
+INLINE void andb_ix(m68_state_t *m68_state);
+INLINE void andcc(m68_state_t *m68_state);
+INLINE void andd_di(m68_state_t *m68_state);
+INLINE void andd_ex(m68_state_t *m68_state);
+INLINE void andd_im(m68_state_t *m68_state);
+INLINE void andd_ix(m68_state_t *m68_state);
+INLINE void andr(m68_state_t *m68_state);
+INLINE void asla(m68_state_t *m68_state);
+INLINE void aslb(m68_state_t *m68_state);
+INLINE void asl_di(m68_state_t *m68_state);
+INLINE void asld(m68_state_t *m68_state);
+INLINE void asl_ex(m68_state_t *m68_state);
+INLINE void asl_ix(m68_state_t *m68_state);
+INLINE void asra(m68_state_t *m68_state);
+INLINE void asrb(m68_state_t *m68_state);
+INLINE void asr_di(m68_state_t *m68_state);
+INLINE void asrd(m68_state_t *m68_state);
+INLINE void asr_ex(m68_state_t *m68_state);
+INLINE void asr_ix(m68_state_t *m68_state);
+INLINE void band(m68_state_t *m68_state);
+INLINE void bcc(m68_state_t *m68_state);
+INLINE void bcs(m68_state_t *m68_state);
+INLINE void beor(m68_state_t *m68_state);
+INLINE void beq(m68_state_t *m68_state);
+INLINE void bge(m68_state_t *m68_state);
+INLINE void bgt(m68_state_t *m68_state);
+INLINE void bhi(m68_state_t *m68_state);
+INLINE void biand(m68_state_t *m68_state);
+INLINE void bieor(m68_state_t *m68_state);
+INLINE void bior(m68_state_t *m68_state);
+INLINE void bita_di(m68_state_t *m68_state);
+INLINE void bita_ex(m68_state_t *m68_state);
+INLINE void bita_im(m68_state_t *m68_state);
+INLINE void bita_ix(m68_state_t *m68_state);
+INLINE void bitb_di(m68_state_t *m68_state);
+INLINE void bitb_ex(m68_state_t *m68_state);
+INLINE void bitb_im(m68_state_t *m68_state);
+INLINE void bitb_ix(m68_state_t *m68_state);
+INLINE void bitd_di(m68_state_t *m68_state);
+INLINE void bitd_ex(m68_state_t *m68_state);
+INLINE void bitd_im(m68_state_t *m68_state);
+INLINE void bitd_ix(m68_state_t *m68_state);
+INLINE void bitmd_im(m68_state_t *m68_state);
+INLINE void ble(m68_state_t *m68_state);
+INLINE void bls(m68_state_t *m68_state);
+INLINE void blt(m68_state_t *m68_state);
+INLINE void bmi(m68_state_t *m68_state);
+INLINE void bne(m68_state_t *m68_state);
+INLINE void bor(m68_state_t *m68_state);
+INLINE void bpl(m68_state_t *m68_state);
+INLINE void bra(m68_state_t *m68_state);
+INLINE void brn(m68_state_t *m68_state);
+INLINE void bsr(m68_state_t *m68_state);
+INLINE void bvc(m68_state_t *m68_state);
+INLINE void bvs(m68_state_t *m68_state);
+INLINE void clra(m68_state_t *m68_state);
+INLINE void clrb(m68_state_t *m68_state);
+INLINE void clr_di(m68_state_t *m68_state);
+INLINE void clrd(m68_state_t *m68_state);
+INLINE void clre(m68_state_t *m68_state);
+INLINE void clr_ex(m68_state_t *m68_state);
+INLINE void clrf(m68_state_t *m68_state);
+INLINE void clr_ix(m68_state_t *m68_state);
+INLINE void clrw(m68_state_t *m68_state);
+INLINE void cmpa_di(m68_state_t *m68_state);
+INLINE void cmpa_ex(m68_state_t *m68_state);
+INLINE void cmpa_im(m68_state_t *m68_state);
+INLINE void cmpa_ix(m68_state_t *m68_state);
+INLINE void cmpb_di(m68_state_t *m68_state);
+INLINE void cmpb_ex(m68_state_t *m68_state);
+INLINE void cmpb_im(m68_state_t *m68_state);
+INLINE void cmpb_ix(m68_state_t *m68_state);
+INLINE void cmpd_di(m68_state_t *m68_state);
+INLINE void cmpd_ex(m68_state_t *m68_state);
+INLINE void cmpd_im(m68_state_t *m68_state);
+INLINE void cmpd_ix(m68_state_t *m68_state);
+INLINE void cmpe_di(m68_state_t *m68_state);
+INLINE void cmpe_ex(m68_state_t *m68_state);
+INLINE void cmpe_im(m68_state_t *m68_state);
+INLINE void cmpe_ix(m68_state_t *m68_state);
+INLINE void cmpf_di(m68_state_t *m68_state);
+INLINE void cmpf_ex(m68_state_t *m68_state);
+INLINE void cmpf_im(m68_state_t *m68_state);
+INLINE void cmpf_ix(m68_state_t *m68_state);
+INLINE void cmpr(m68_state_t *m68_state);
+INLINE void cmps_di(m68_state_t *m68_state);
+INLINE void cmps_ex(m68_state_t *m68_state);
+INLINE void cmps_im(m68_state_t *m68_state);
+INLINE void cmps_ix(m68_state_t *m68_state);
+INLINE void cmpu_di(m68_state_t *m68_state);
+INLINE void cmpu_ex(m68_state_t *m68_state);
+INLINE void cmpu_im(m68_state_t *m68_state);
+INLINE void cmpu_ix(m68_state_t *m68_state);
+INLINE void cmpw_di(m68_state_t *m68_state);
+INLINE void cmpw_ex(m68_state_t *m68_state);
+INLINE void cmpw_im(m68_state_t *m68_state);
+INLINE void cmpw_ix(m68_state_t *m68_state);
+INLINE void cmpx_di(m68_state_t *m68_state);
+INLINE void cmpx_ex(m68_state_t *m68_state);
+INLINE void cmpx_im(m68_state_t *m68_state);
+INLINE void cmpx_ix(m68_state_t *m68_state);
+INLINE void cmpy_di(m68_state_t *m68_state);
+INLINE void cmpy_ex(m68_state_t *m68_state);
+INLINE void cmpy_im(m68_state_t *m68_state);
+INLINE void cmpy_ix(m68_state_t *m68_state);
+INLINE void coma(m68_state_t *m68_state);
+INLINE void comb(m68_state_t *m68_state);
+INLINE void com_di(m68_state_t *m68_state);
+INLINE void comd(m68_state_t *m68_state);
+INLINE void come(m68_state_t *m68_state);
+INLINE void com_ex(m68_state_t *m68_state);
+INLINE void comf(m68_state_t *m68_state);
+INLINE void com_ix(m68_state_t *m68_state);
+INLINE void comw(m68_state_t *m68_state);
+INLINE void cwai(m68_state_t *m68_state);
+INLINE void daa(m68_state_t *m68_state);
+INLINE void daa(m68_state_t *m68_state);
+INLINE void deca(m68_state_t *m68_state);
+INLINE void decb(m68_state_t *m68_state);
+INLINE void dec_di(m68_state_t *m68_state);
+INLINE void decd(m68_state_t *m68_state);
+INLINE void dece(m68_state_t *m68_state);
+INLINE void dec_ex(m68_state_t *m68_state);
+INLINE void decf(m68_state_t *m68_state);
+INLINE void dec_ix(m68_state_t *m68_state);
+INLINE void decw(m68_state_t *m68_state);
+INLINE void divd_di(m68_state_t *m68_state);
+INLINE void divd_ex(m68_state_t *m68_state);
+INLINE void divd_im(m68_state_t *m68_state);
+INLINE void divd_ix(m68_state_t *m68_state);
+INLINE void divq_di(m68_state_t *m68_state);
+INLINE void divq_ex(m68_state_t *m68_state);
+INLINE void divq_im(m68_state_t *m68_state);
+INLINE void divq_ix(m68_state_t *m68_state);
+INLINE void eim_di(m68_state_t *m68_state);
+INLINE void eim_ex(m68_state_t *m68_state);
+INLINE void eim_ix(m68_state_t *m68_state);
+INLINE void eora_di(m68_state_t *m68_state);
+INLINE void eora_ex(m68_state_t *m68_state);
+INLINE void eora_im(m68_state_t *m68_state);
+INLINE void eora_ix(m68_state_t *m68_state);
+INLINE void eorb_di(m68_state_t *m68_state);
+INLINE void eorb_ex(m68_state_t *m68_state);
+INLINE void eorb_im(m68_state_t *m68_state);
+INLINE void eorb_ix(m68_state_t *m68_state);
+INLINE void eord_di(m68_state_t *m68_state);
+INLINE void eord_ex(m68_state_t *m68_state);
+INLINE void eord_im(m68_state_t *m68_state);
+INLINE void eord_ix(m68_state_t *m68_state);
+INLINE void eorr(m68_state_t *m68_state);
+INLINE void exg(m68_state_t *m68_state);
+INLINE void illegal(m68_state_t *m68_state);
+INLINE void inca(m68_state_t *m68_state);
+INLINE void incb(m68_state_t *m68_state);
+INLINE void inc_di(m68_state_t *m68_state);
+INLINE void incd(m68_state_t *m68_state);
+INLINE void ince(m68_state_t *m68_state);
+INLINE void inc_ex(m68_state_t *m68_state);
+INLINE void incf(m68_state_t *m68_state);
+INLINE void inc_ix(m68_state_t *m68_state);
+INLINE void incw(m68_state_t *m68_state);
+INLINE void jmp_di(m68_state_t *m68_state);
+INLINE void jmp_ex(m68_state_t *m68_state);
+INLINE void jmp_ix(m68_state_t *m68_state);
+INLINE void jsr_di(m68_state_t *m68_state);
+INLINE void jsr_ex(m68_state_t *m68_state);
+INLINE void jsr_ix(m68_state_t *m68_state);
+INLINE void lbcc(m68_state_t *m68_state);
+INLINE void lbcs(m68_state_t *m68_state);
+INLINE void lbeq(m68_state_t *m68_state);
+INLINE void lbge(m68_state_t *m68_state);
+INLINE void lbgt(m68_state_t *m68_state);
+INLINE void lbhi(m68_state_t *m68_state);
+INLINE void lble(m68_state_t *m68_state);
+INLINE void lbls(m68_state_t *m68_state);
+INLINE void lblt(m68_state_t *m68_state);
+INLINE void lbmi(m68_state_t *m68_state);
+INLINE void lbne(m68_state_t *m68_state);
+INLINE void lbpl(m68_state_t *m68_state);
+INLINE void lbra(m68_state_t *m68_state);
+INLINE void lbrn(m68_state_t *m68_state);
+INLINE void lbsr(m68_state_t *m68_state);
+INLINE void lbvc(m68_state_t *m68_state);
+INLINE void lbvs(m68_state_t *m68_state);
+INLINE void lda_di(m68_state_t *m68_state);
+INLINE void lda_ex(m68_state_t *m68_state);
+INLINE void lda_im(m68_state_t *m68_state);
+INLINE void lda_ix(m68_state_t *m68_state);
+INLINE void ldb_di(m68_state_t *m68_state);
+INLINE void ldb_ex(m68_state_t *m68_state);
+INLINE void ldb_im(m68_state_t *m68_state);
+INLINE void ldb_ix(m68_state_t *m68_state);
+INLINE void ldbt(m68_state_t *m68_state);
+INLINE void ldd_di(m68_state_t *m68_state);
+INLINE void ldd_ex(m68_state_t *m68_state);
+INLINE void ldd_im(m68_state_t *m68_state);
+INLINE void ldd_ix(m68_state_t *m68_state);
+INLINE void lde_di(m68_state_t *m68_state);
+INLINE void lde_ex(m68_state_t *m68_state);
+INLINE void lde_im(m68_state_t *m68_state);
+INLINE void lde_ix(m68_state_t *m68_state);
+INLINE void ldf_di(m68_state_t *m68_state);
+INLINE void ldf_ex(m68_state_t *m68_state);
+INLINE void ldf_im(m68_state_t *m68_state);
+INLINE void ldf_ix(m68_state_t *m68_state);
+INLINE void ldmd_im(m68_state_t *m68_state);
+INLINE void ldq_di(m68_state_t *m68_state);
+INLINE void ldq_ex(m68_state_t *m68_state);
+INLINE void ldq_im(m68_state_t *m68_state);
+INLINE void ldq_ix(m68_state_t *m68_state);
+INLINE void lds_di(m68_state_t *m68_state);
+INLINE void lds_ex(m68_state_t *m68_state);
+INLINE void lds_im(m68_state_t *m68_state);
+INLINE void lds_ix(m68_state_t *m68_state);
+INLINE void ldu_di(m68_state_t *m68_state);
+INLINE void ldu_ex(m68_state_t *m68_state);
+INLINE void ldu_im(m68_state_t *m68_state);
+INLINE void ldu_ix(m68_state_t *m68_state);
+INLINE void ldw_di(m68_state_t *m68_state);
+INLINE void ldw_ex(m68_state_t *m68_state);
+INLINE void ldw_im(m68_state_t *m68_state);
+INLINE void ldw_ix(m68_state_t *m68_state);
+INLINE void ldx_di(m68_state_t *m68_state);
+INLINE void ldx_ex(m68_state_t *m68_state);
+INLINE void ldx_im(m68_state_t *m68_state);
+INLINE void ldx_ix(m68_state_t *m68_state);
+INLINE void ldy_di(m68_state_t *m68_state);
+INLINE void ldy_ex(m68_state_t *m68_state);
+INLINE void ldy_im(m68_state_t *m68_state);
+INLINE void ldy_ix(m68_state_t *m68_state);
+INLINE void leas(m68_state_t *m68_state);
+INLINE void leau(m68_state_t *m68_state);
+INLINE void leax(m68_state_t *m68_state);
+INLINE void leay(m68_state_t *m68_state);
+INLINE void lsra(m68_state_t *m68_state);
+INLINE void lsrb(m68_state_t *m68_state);
+INLINE void lsr_di(m68_state_t *m68_state);
+INLINE void lsrd(m68_state_t *m68_state);
+INLINE void lsr_ex(m68_state_t *m68_state);
+INLINE void lsr_ix(m68_state_t *m68_state);
+INLINE void lsrw(m68_state_t *m68_state);
+INLINE void muld_di(m68_state_t *m68_state);
+INLINE void muld_ex(m68_state_t *m68_state);
+INLINE void muld_im(m68_state_t *m68_state);
+INLINE void muld_ix(m68_state_t *m68_state);
+INLINE void mul(m68_state_t *m68_state);
+INLINE void nega(m68_state_t *m68_state);
+INLINE void negb(m68_state_t *m68_state);
+INLINE void neg_di(m68_state_t *m68_state);
+INLINE void negd(m68_state_t *m68_state);
+INLINE void neg_ex(m68_state_t *m68_state);
+INLINE void neg_ix(m68_state_t *m68_state);
+INLINE void nop(m68_state_t *m68_state);
+INLINE void oim_di(m68_state_t *m68_state);
+INLINE void oim_ex(m68_state_t *m68_state);
+INLINE void oim_ix(m68_state_t *m68_state);
+INLINE void ora_di(m68_state_t *m68_state);
+INLINE void ora_ex(m68_state_t *m68_state);
+INLINE void ora_im(m68_state_t *m68_state);
+INLINE void ora_ix(m68_state_t *m68_state);
+INLINE void orb_di(m68_state_t *m68_state);
+INLINE void orb_ex(m68_state_t *m68_state);
+INLINE void orb_im(m68_state_t *m68_state);
+INLINE void orb_ix(m68_state_t *m68_state);
+INLINE void orcc(m68_state_t *m68_state);
+INLINE void ord_di(m68_state_t *m68_state);
+INLINE void ord_ex(m68_state_t *m68_state);
+INLINE void ord_im(m68_state_t *m68_state);
+INLINE void ord_ix(m68_state_t *m68_state);
+INLINE void orr(m68_state_t *m68_state);
+INLINE void pref10(m68_state_t *m68_state);
+INLINE void pref11(m68_state_t *m68_state);
+INLINE void pshs(m68_state_t *m68_state);
+INLINE void pshsw(m68_state_t *m68_state);
+INLINE void pshu(m68_state_t *m68_state);
+INLINE void pshuw(m68_state_t *m68_state);
+INLINE void puls(m68_state_t *m68_state);
+INLINE void pulsw(m68_state_t *m68_state);
+INLINE void pulu(m68_state_t *m68_state);
+INLINE void puluw(m68_state_t *m68_state);
+INLINE void rola(m68_state_t *m68_state);
+INLINE void rolb(m68_state_t *m68_state);
+INLINE void rol_di(m68_state_t *m68_state);
+INLINE void rold(m68_state_t *m68_state);
+INLINE void rol_ex(m68_state_t *m68_state);
+INLINE void rol_ix(m68_state_t *m68_state);
+INLINE void rolw(m68_state_t *m68_state);
+INLINE void rora(m68_state_t *m68_state);
+INLINE void rorb(m68_state_t *m68_state);
+INLINE void ror_di(m68_state_t *m68_state);
+INLINE void rord(m68_state_t *m68_state);
+INLINE void ror_ex(m68_state_t *m68_state);
+INLINE void ror_ix(m68_state_t *m68_state);
+INLINE void rorw(m68_state_t *m68_state);
+INLINE void rti(m68_state_t *m68_state);
+INLINE void rts(m68_state_t *m68_state);
+INLINE void sbca_di(m68_state_t *m68_state);
+INLINE void sbca_ex(m68_state_t *m68_state);
+INLINE void sbca_im(m68_state_t *m68_state);
+INLINE void sbca_ix(m68_state_t *m68_state);
+INLINE void sbcb_di(m68_state_t *m68_state);
+INLINE void sbcb_ex(m68_state_t *m68_state);
+INLINE void sbcb_im(m68_state_t *m68_state);
+INLINE void sbcb_ix(m68_state_t *m68_state);
+INLINE void sbcd_di(m68_state_t *m68_state);
+INLINE void sbcd_ex(m68_state_t *m68_state);
+INLINE void sbcd_im(m68_state_t *m68_state);
+INLINE void sbcd_ix(m68_state_t *m68_state);
+INLINE void sbcr(m68_state_t *m68_state);
+INLINE void sex(m68_state_t *m68_state);
+INLINE void sexw(m68_state_t *m68_state);
+INLINE void sta_di(m68_state_t *m68_state);
+INLINE void sta_ex(m68_state_t *m68_state);
+INLINE void sta_ix(m68_state_t *m68_state);
+INLINE void stb_di(m68_state_t *m68_state);
+INLINE void stb_ex(m68_state_t *m68_state);
+INLINE void stb_ix(m68_state_t *m68_state);
+INLINE void stbt(m68_state_t *m68_state);
+INLINE void std_di(m68_state_t *m68_state);
+INLINE void std_ex(m68_state_t *m68_state);
+INLINE void std_ix(m68_state_t *m68_state);
+INLINE void ste_di(m68_state_t *m68_state);
+INLINE void ste_ex(m68_state_t *m68_state);
+INLINE void ste_ix(m68_state_t *m68_state);
+INLINE void stf_di(m68_state_t *m68_state);
+INLINE void stf_ex(m68_state_t *m68_state);
+INLINE void stf_ix(m68_state_t *m68_state);
+INLINE void stq_di(m68_state_t *m68_state);
+INLINE void stq_ex(m68_state_t *m68_state);
+INLINE void stq_ix(m68_state_t *m68_state);
+INLINE void sts_di(m68_state_t *m68_state);
+INLINE void sts_ex(m68_state_t *m68_state);
+INLINE void sts_ix(m68_state_t *m68_state);
+INLINE void stu_di(m68_state_t *m68_state);
+INLINE void stu_ex(m68_state_t *m68_state);
+INLINE void stu_ix(m68_state_t *m68_state);
+INLINE void stw_di(m68_state_t *m68_state);
+INLINE void stw_ex(m68_state_t *m68_state);
+INLINE void stw_ix(m68_state_t *m68_state);
+INLINE void stx_di(m68_state_t *m68_state);
+INLINE void stx_ex(m68_state_t *m68_state);
+INLINE void stx_ix(m68_state_t *m68_state);
+INLINE void sty_di(m68_state_t *m68_state);
+INLINE void sty_ex(m68_state_t *m68_state);
+INLINE void sty_ix(m68_state_t *m68_state);
+INLINE void suba_di(m68_state_t *m68_state);
+INLINE void suba_ex(m68_state_t *m68_state);
+INLINE void suba_im(m68_state_t *m68_state);
+INLINE void suba_ix(m68_state_t *m68_state);
+INLINE void subb_di(m68_state_t *m68_state);
+INLINE void subb_ex(m68_state_t *m68_state);
+INLINE void subb_im(m68_state_t *m68_state);
+INLINE void subb_ix(m68_state_t *m68_state);
+INLINE void subd_di(m68_state_t *m68_state);
+INLINE void subd_ex(m68_state_t *m68_state);
+INLINE void subd_im(m68_state_t *m68_state);
+INLINE void subd_ix(m68_state_t *m68_state);
+INLINE void sube_di(m68_state_t *m68_state);
+INLINE void sube_ex(m68_state_t *m68_state);
+INLINE void sube_im(m68_state_t *m68_state);
+INLINE void sube_ix(m68_state_t *m68_state);
+INLINE void subf_di(m68_state_t *m68_state);
+INLINE void subf_ex(m68_state_t *m68_state);
+INLINE void subf_im(m68_state_t *m68_state);
+INLINE void subf_ix(m68_state_t *m68_state);
+INLINE void subr(m68_state_t *m68_state);
+INLINE void subw_di(m68_state_t *m68_state);
+INLINE void subw_ex(m68_state_t *m68_state);
+INLINE void subw_im(m68_state_t *m68_state);
+INLINE void subw_ix(m68_state_t *m68_state);
+INLINE void swi2(m68_state_t *m68_state);
+INLINE void swi3(m68_state_t *m68_state);
+INLINE void swi(m68_state_t *m68_state);
+INLINE void sync(m68_state_t *m68_state);
+INLINE void tfmcp(m68_state_t *m68_state);
+INLINE void tfmmm(m68_state_t *m68_state);
+INLINE void tfmpc(m68_state_t *m68_state);
+INLINE void tfmpp(m68_state_t *m68_state);
+INLINE void tfr(m68_state_t *m68_state);
+INLINE void tim_di(m68_state_t *m68_state);
+INLINE void tim_ex(m68_state_t *m68_state);
+INLINE void tim_ix(m68_state_t *m68_state);
+INLINE void tsta(m68_state_t *m68_state);
+INLINE void tstb(m68_state_t *m68_state);
+INLINE void tst_di(m68_state_t *m68_state);
+INLINE void tstd(m68_state_t *m68_state);
+INLINE void tste(m68_state_t *m68_state);
+INLINE void tst_ex(m68_state_t *m68_state);
+INLINE void tstf(m68_state_t *m68_state);
+INLINE void tst_ix(m68_state_t *m68_state);
+INLINE void tstw(m68_state_t *m68_state);
+
+static const UINT8 flags8i[256]= /* increment */
+{
+CC_Z,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+CC_N|CC_V,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N
+};
+static const UINT8 flags8d[256]= /* decrement */
+{
+CC_Z,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,CC_V,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N
+};
+
+static const UINT8 index_cycle_em[256] = { /* Index Loopup cycle counts, emulated 6809 */
+/* 0xX0, 0xX1, 0xX2, 0xX3, 0xX4, 0xX5, 0xX6, 0xX7, 0xX8, 0xX9, 0xXA, 0xXB, 0xXC, 0xXD, 0xXE, 0xXF */
+
+/* 0x0X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+/* 0x1X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+/* 0x2X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+/* 0x3X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+/* 0x4X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+/* 0x5X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+/* 0x6X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+/* 0x7X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+/* 0x8X */ 2, 3, 2, 3, 0, 1, 1, 1, 1, 4, 1, 4, 1, 5, 4, 0,
+/* 0x9X */ 3, 6, 20, 6, 3, 4, 4, 4, 4, 7, 4, 7, 4, 8, 7, 5,
+/* 0xAX */ 2, 3, 2, 3, 0, 1, 1, 1, 1, 4, 1, 4, 1, 5, 4, 5,
+/* 0xBX */ 5, 6, 20, 6, 3, 4, 4, 4, 4, 7, 4, 7, 4, 8, 7, 20,
+/* 0xCX */ 2, 3, 2, 3, 0, 1, 1, 1, 1, 4, 1, 4, 1, 5, 4, 3,
+/* 0xDX */ 4, 6, 20, 6, 3, 4, 4, 4, 4, 7, 4, 7, 4, 8, 7, 20,
+/* 0xEX */ 2, 3, 2, 3, 0, 1, 1, 1, 1, 4, 1, 4, 1, 5, 4, 3,
+/* 0xFX */ 4, 6, 20, 6, 3, 4, 4, 4, 4, 7, 4, 7, 4, 8, 7, 20
+};
+
+static const UINT8 index_cycle_na[256] = { /* Index Loopup cycle counts,
+native 6309 */
+/* X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, XA, XB, XC, XD, XE, XF */
+
+/* 0x0X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+/* 0x1X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+/* 0x2X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+/* 0x3X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+/* 0x4X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+/* 0x5X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+/* 0x6X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+/* 0x7X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+/* 0x8X */ 1, 2, 1, 2, 0, 1, 1, 1, 1, 3, 1, 2, 1, 3, 1, 0,
+/* 0x9X */ 3, 5, 19, 5, 3, 4, 4, 4, 4, 7, 4, 5, 4, 6, 4, 5,
+/* 0xAX */ 1, 2, 1, 2, 0, 1, 1, 1, 1, 3, 1, 2, 1, 3, 1, 2,
+/* 0xBX */ 5, 5, 19, 5, 3, 4, 4, 4, 4, 7, 4, 5, 4, 6, 4, 19,
+/* 0xCX */ 1, 2, 1, 2, 0, 1, 1, 1, 1, 3, 1, 2, 1, 3, 1, 1,
+/* 0xDX */ 4, 5, 19, 5, 3, 4, 4, 4, 4, 7, 4, 5, 4, 6, 4, 19,
+/* 0xEX */ 1, 2, 1, 2, 0, 1, 1, 1, 1, 3, 1, 2, 1, 3, 1, 1,
+/* 0xFX */ 4, 5, 19, 5, 3, 4, 4, 4, 4, 7, 4, 5, 4, 6, 4, 19
+};
+
+#define IIP0 19 /* Illegal instruction cycle count page 0 */
+#define IIP1 20 /* Illegal instruction cycle count page 01 & 11 */
+
+static const UINT8 ccounts_page0_em[256] = /* Cycle Counts Page zero, Emulated 6809 */
+{
+/* 0xX0, 0xX1, 0xX2, 0xX3, 0xX4, 0xX5, 0xX6, 0xX7, 0xX8, 0xX9, 0xXA, 0xXB, 0xXC, 0xXD, 0xXE, 0xXF */
+/* 0x0X */ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 6,
+/* 0x1X */ 0, 0, 2, 4, 4, IIP0, 5, 9, IIP0, 2, 3, IIP0, 3, 2, 8, 6,
+/* 0x2X */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+/* 0x3X */ 4, 4, 4, 4, 5, 5, 5, 5, IIP0, 5, 3, 6, 20, 11, IIP0, 19,
+/* 0x4X */ 2, IIP0, IIP0, 2, 2, IIP0, 2, 2, 2, 2, 2, IIP0, 2, 2, IIP0, 2,
+/* 0x5X */ 2, IIP0, IIP0, 2, 2, IIP0, 2, 2, 2, 2, 2, IIP0, 2, 2, IIP0, 2,
+/* 0x6X */ 6, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 7, 6, 6, 3, 6,
+/* 0x7X */ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5, 7, 7, 4, 7,
+/* 0x8X */ 2, 2, 2, 4, 2, 2, 2, IIP0, 2, 2, 2, 2, 4, 7, 3, IIP0,
+/* 0x9X */ 4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 4, 6, 7, 5, 5,
+/* 0xAX */ 4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 4, 6, 7, 5, 5,
+/* 0xBX */ 5, 5, 5, 7, 5, 5, 5, 5, 5, 5, 5, 5, 7, 8, 6, 6,
+/* 0xCX */ 2, 2, 2, 4, 2, 2, 2, IIP0, 2, 2, 2, 2, 3, 5, 3, IIP0,
+/* 0xDX */ 4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5,
+/* 0xEX */ 4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5,
+/* 0xFX */ 5, 5, 5, 7, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6
+};
+
+static const UINT8 ccounts_page0_na[256] = /* Cycle Counts Page zero, Native 6309 */
+{
+/* 0xX0, 0xX1, 0xX2, 0xX3, 0xX4, 0xX5, 0xX6, 0xX7, 0xX8, 0xX9, 0xXA, 0xXB, 0xXC, 0xXD, 0xXE, 0xXF */
+/* 0x0X */ 5, 6, 6, 5, 5, 6, 5, 5, 5, 5, 5, 6, 5, 4, 2, 5,
+/* 0x1X */ 0, 0, 1, 4, 4, IIP0, 4, 7, IIP0, 1, 2, IIP0, 3, 1, 5, 4,
+/* 0x2X */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+/* 0x3X */ 4, 4, 4, 4, 4, 4, 4, 4, IIP0, 4, 1, 6, 22, 10, IIP0, 21,
+/* 0x4X */ 1, IIP0, IIP0, 1, 1, IIP0, 1, 1, 1, 1, 1, IIP0, 1, 1, IIP0, 1,
+/* 0x5X */ 1, IIP0, IIP0, 1, 1, IIP0, 1, 1, 1, 1, 1, IIP0, 1, 1, IIP0, 1,
+/* 0x6X */ 6, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 7, 6, 5, 3, 6,
+/* 0x7X */ 6, 7, 7, 6, 6, 7, 6, 6, 6, 6, 6, 5, 6, 5, 3, 6,
+/* 0x8X */ 2, 2, 2, 3, 2, 2, 2, IIP0, 2, 2, 2, 2, 3, 6, 3, IIP0,
+/* 0x9X */ 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 4, 6, 4, 4,
+/* 0xAX */ 4, 4, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 5, 6, 5, 5,
+/* 0xBX */ 4, 4, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 5, 7, 5, 5,
+/* 0xCX */ 2, 2, 2, 3, 2, 2, 2, IIP0, 2, 2, 2, 2, 3, 5, 3, IIP0,
+/* 0xDX */ 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4,
+/* 0xEX */ 4, 4, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5,
+/* 0xFX */ 4, 4, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5
+};
+
+static const UINT8 ccounts_page01_em[256] = /* Cycle Counts Page 01, Emulated 6809 */
+{
+/* 0xX0, 0xX1, 0xX2, 0xX3, 0xX4, 0xX5, 0xX6, 0xX7, 0xX8, 0xX9, 0xXA, 0xXB, 0xXC, 0xXD, 0xXE, 0xXF */
+/* 0x0X */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1,
+/* 0x1X */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1,
+/* 0x2X */ IIP1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+/* 0x3X */ 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 6, IIP1, IIP1, IIP1, 20,
+/* 0x4X */ 2, IIP1,IIP1, 2, 2, IIP1, 2, 2, 2, 2, 2, IIP1, 2, 2, IIP1, 2,
+/* 0x5X */ IIP1, IIP1, IIP1, 3, 3, IIP1, 3, IIP1, IIP1, 3, 3, IIP1, 3, 3, IIP1, 3,
+/* 0x6X */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1,
+/* 0x7X */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1,
+/* 0x8X */ 5, 5, 5, 5, 5, 5, 4, IIP1, 5, 5, 5, 5, 5, IIP1, 4, IIP1,
+/* 0x9X */ 7, 7, 7, 7, 7, 7, 6, 6, 7, 7, 7, 7, 7, IIP1, 6, 6,
+/* 0xAX */ 7, 7, 7, 7, 7, 7, 6, 6, 7, 7, 7, 7, 7, IIP1, 6, 6,
+/* 0xBX */ 8, 8, 8, 8, 8, 8, 7, 7, 8, 8, 8, 8, 8, IIP1, 7, 7,
+/* 0xCX */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, 4, IIP1,
+/* 0xDX */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, 8, 8, 6, 6,
+/* 0xEX */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, 8, 8, 6, 6,
+/* 0xFX */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, 9, 9, 7, 7
+};
+
+static const UINT8 ccounts_page01_na[256] = /* Cycle Counts Page 01, Native 6309 */
+{
+/* 0xX0, 0xX1, 0xX2, 0xX3, 0xX4, 0xX5, 0xX6, 0xX7, 0xX8, 0xX9, 0xXA, 0xXB, 0xXC, 0xXD, 0xXE, 0xXF */
+/* 0x0X */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1,
+/* 0x1X */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1,
+/* 0x2X */ IIP1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+/* 0x3X */ 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 6, IIP1, IIP1, IIP1, 22,
+/* 0x4X */ 1, IIP1, IIP1, 1, 1, IIP1, 1, 1, 1, 1, 1, IIP1, 1, 1, IIP1, 1,
+/* 0x5X */ IIP1, IIP1, IIP1, 2, 2, IIP1, 2, IIP1, IIP1, 2, 2, IIP1, 2, 2, IIP1, 1,
+/* 0x6X */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1,
+/* 0x7X */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1,
+/* 0x8X */ 4, 4, 4, 4, 4, 4, 4, IIP1, 4, 4, 4, 4, 4, IIP1, 4, IIP1,
+/* 0x9X */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, IIP1, 5, 5,
+/* 0xAX */ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, IIP1, 6, 6,
+/* 0xBX */ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, IIP1, 6, 6,
+/* 0xCX */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, 4, IIP1,
+/* 0xDX */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, 7, 7, 5, 5,
+/* 0xEX */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, 8, 8, 6, 6,
+/* 0xFX */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, 8, 8, 6, 6
+};
+
+static const UINT8 ccounts_page11_em[256] = /* Cycle Counts Page 11, Emulated 6809 */
+{
+/* 0xX0, 0xX1, 0xX2, 0xX3, 0xX4, 0xX5, 0xX6, 0xX7, 0xX8, 0xX9, 0xXA, 0xXB, 0xXC, 0xXD, 0xXE, 0xXF */
+/* 0x0X */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1,
+/* 0x1X */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1,
+/* 0x2X */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1,
+/* 0x3X */ 7, 7, 7, 7, 7, 7, 7, 8, 3, 3, 3, 3, 4, 5, IIP1, 20,
+/* 0x4X */ IIP1, IIP1, IIP1, 2, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, 2, IIP1, 2, 2, IIP1, 2,
+/* 0x5X */ IIP1, IIP1, IIP1, 2, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, 2, IIP1, 2, 2, IIP1, 2,
+/* 0x6X */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1,
+/* 0x7X */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1,
+/* 0x8X */ 3, 3, IIP1, 5, IIP1, IIP1, 3, IIP1, IIP1, IIP1, IIP1, 3, 5, 25, 34, 28,
+/* 0x9X */ 5, 5, IIP1, 7, IIP1, IIP1, 5, 5, IIP1, IIP1, IIP1, 5, 7, 27, 36, 30,
+/* 0xAX */ 5, 5, IIP1, 7, IIP1, IIP1, 5, 5, IIP1, IIP1, IIP1, 5, 7, 27, 36, 30,
+/* 0xBX */ 6, 6, IIP1, 8, IIP1, IIP1, 6, 6, IIP1, IIP1, IIP1, 6, 8, 28, 37, 31,
+/* 0xCX */ 3, 3, IIP1, IIP1, IIP1, IIP1, 3, IIP1, IIP1, IIP1, IIP1, 3, IIP1, IIP1, IIP1, IIP1,
+/* 0xDX */ 5, 5, IIP1, IIP1, IIP1, IIP1, 5, 5, IIP1, IIP1, IIP1, 5, IIP1, IIP1, IIP1, IIP1,
+/* 0xEX */ 5, 5, IIP1, IIP1, IIP1, IIP1, 5, 5, IIP1, IIP1, IIP1, 5, IIP1, IIP1, IIP1, IIP1,
+/* 0xFX */ 6, 6, IIP1, IIP1, IIP1, IIP1, 6, 6, IIP1, IIP1, IIP1, 6, IIP1, IIP1, IIP1, IIP1
+};
+
+static const UINT8 ccounts_page11_na[256] = /* Cycle Counts Page 11, Native 6309 */
+{
+/* 0xX0, 0xX1, 0xX2, 0xX3, 0xX4, 0xX5, 0xX6, 0xX7, 0xX8, 0xX9, 0xXA, 0xXB, 0xXC, 0xXD, 0xXE, 0xXF */
+/* 0x0X */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1,
+/* 0x1X */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1,
+/* 0x2X */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1,
+/* 0x3X */ 6, 6, 6, 6, 6, 6, 6, 7, 3, 3, 3, 3, 4, 5, IIP1, 22,
+/* 0x4X */ IIP1, IIP1, IIP1, 2, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, 2, IIP1, 2, 2, IIP1, 2,
+/* 0x5X */ IIP1, IIP1, IIP1, 2, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, 2, IIP1, 2, 2, IIP1, 2,
+/* 0x6X */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1,
+/* 0x7X */ IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1, IIP1,
+/* 0x8X */ 3, 3, IIP1, 4, IIP1, IIP1, 3, IIP1, IIP1, IIP1, IIP1, 3, 4, 25, 34, 28,
+/* 0x9X */ 4, 4, IIP1, 5, IIP1, IIP1, 4, 4, IIP1, IIP1, IIP1, 4, 5, 26, 35, 29,
+/* 0xAX */ 5, 5, IIP1, 6, IIP1, IIP1, 5, 5, IIP1, IIP1, IIP1, 5, 6, 27, 36, 30,
+/* 0xBX */ 5, 5, IIP1, 6, IIP1, IIP1, 5, 5, IIP1, IIP1, IIP1, 5, 6, 27, 36, 30,
+/* 0xCX */ 3, 3, IIP1, IIP1, IIP1, IIP1, 3, IIP1, IIP1, IIP1, IIP1, 3, IIP1, IIP1, IIP1, IIP1,
+/* 0xDX */ 4, 4, IIP1, IIP1, IIP1, IIP1, 4, 4, IIP1, IIP1, IIP1, 4, IIP1, IIP1, IIP1, IIP1,
+/* 0xEX */ 5, 5, IIP1, IIP1, IIP1, IIP1, 5, 5, IIP1, IIP1, IIP1, 5, IIP1, IIP1, IIP1, IIP1,
+/* 0xFX */ 5, 5, IIP1, IIP1, IIP1, IIP1, 5, 5, IIP1, IIP1, IIP1, 5, IIP1, IIP1, IIP1, IIP1
+};
+
+#if !BIG_SWITCH
+
+static void (*const hd6309_main[0x100])(m68_state_t *) = {
+/* 0xX0, 0xX1, 0xX2, 0xX3, 0xX4, 0xX5, 0xX6, 0xX7,
+ 0xX8, 0xX9, 0xXA, 0xXB, 0xXC, 0xXD, 0xXE, 0xXF */
+
+/* 0x0X */ neg_di, oim_di, aim_di, com_di, lsr_di, eim_di, ror_di, asr_di,
+ asl_di, rol_di, dec_di, tim_di, inc_di, tst_di, jmp_di, clr_di,
+
+/* 0x1X */ pref10, pref11, nop, sync, sexw, IIError, lbra, lbsr,
+ IIError, daa, orcc, IIError, andcc, sex, exg, tfr,
+
+/* 0x2X */ bra, brn, bhi, bls, bcc, bcs, bne, beq,
+ bvc, bvs, bpl, bmi, bge, blt, bgt, ble,
+
+/* 0x3X */ leax, leay, leas, leau, pshs, puls, pshu, pulu,
+ IIError, rts, abx, rti, cwai, mul, IIError, swi,
+
+/* 0x4X */ nega, IIError, IIError, coma, lsra, IIError, rora, asra,
+ asla, rola, deca, IIError, inca, tsta, IIError, clra,
+
+/* 0x5X */ negb, IIError, IIError, comb, lsrb, IIError, rorb, asrb,
+ aslb, rolb, decb, IIError, incb, tstb, IIError, clrb,
+
+/* 0x6X */ neg_ix, oim_ix, aim_ix, com_ix, lsr_ix, eim_ix, ror_ix, asr_ix,
+ asl_ix, rol_ix, dec_ix, tim_ix, inc_ix, tst_ix, jmp_ix, clr_ix,
+
+/* 0x7X */ neg_ex, oim_ex, aim_ex, com_ex, lsr_ex, eim_ex, ror_ex, asr_ex,
+ asl_ex, rol_ex, dec_ex, tim_ex, inc_ex, tst_ex, jmp_ex, clr_ex,
+
+/* 0x8X */ suba_im, cmpa_im, sbca_im, subd_im, anda_im, bita_im, lda_im, IIError,
+ eora_im, adca_im, ora_im, adda_im, cmpx_im, bsr, ldx_im, IIError,
+
+/* 0x9X */ suba_di, cmpa_di, sbca_di, subd_di, anda_di, bita_di, lda_di, sta_di,
+ eora_di, adca_di, ora_di, adda_di, cmpx_di, jsr_di, ldx_di, stx_di,
+
+/* 0xAX */ suba_ix, cmpa_ix, sbca_ix, subd_ix, anda_ix, bita_ix, lda_ix, sta_ix,
+ eora_ix, adca_ix, ora_ix, adda_ix, cmpx_ix, jsr_ix, ldx_ix, stx_ix,
+
+/* 0xBX */ suba_ex, cmpa_ex, sbca_ex, subd_ex, anda_ex, bita_ex, lda_ex, sta_ex,
+ eora_ex, adca_ex, ora_ex, adda_ex, cmpx_ex, jsr_ex, ldx_ex, stx_ex,
+
+/* 0xCX */ subb_im, cmpb_im, sbcb_im, addd_im, andb_im, bitb_im, ldb_im, IIError,
+ eorb_im, adcb_im, orb_im, addb_im, ldd_im, ldq_im, ldu_im, IIError,
+
+/* 0xDX */ subb_di, cmpb_di, sbcb_di, addd_di, andb_di, bitb_di, ldb_di, stb_di,
+ eorb_di, adcb_di, orb_di, addb_di, ldd_di, std_di, ldu_di, stu_di,
+
+/* 0xEX */ subb_ix, cmpb_ix, sbcb_ix, addd_ix, andb_ix, bitb_ix, ldb_ix, stb_ix,
+ eorb_ix, adcb_ix, orb_ix, addb_ix, ldd_ix, std_ix, ldu_ix, stu_ix,
+
+/* 0xFX */ subb_ex, cmpb_ex, sbcb_ex, addd_ex, andb_ex, bitb_ex, ldb_ex, stb_ex,
+ eorb_ex, adcb_ex, orb_ex, addb_ex, ldd_ex, std_ex, ldu_ex, stu_ex
+};
+
+static void (*const hd6309_page01[0x100])(m68_state_t *) = {
+/* 0xX0, 0xX1, 0xX2, 0xX3, 0xX4, 0xX5, 0xX6, 0xX7,
+ 0xX8, 0xX9, 0xXA, 0xXB, 0xXC, 0xXD, 0xXE, 0xXF */
+
+/* 0x0X */ IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError,
+ IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError,
+
+/* 0x1X */ IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError,
+ IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError,
+
+/* 0x2X */ IIError, lbrn, lbhi, lbls, lbcc, lbcs, lbne, lbeq,
+ lbvc, lbvs, lbpl, lbmi, lbge, lblt, lbgt, lble,
+
+/* 0x3X */ addr_r, adcr, subr, sbcr, andr, orr, eorr, cmpr,
+ pshsw, pulsw, pshuw, puluw, IIError, IIError, IIError, swi2,
+
+/* 0x4X */ negd, IIError, IIError, comd, lsrd, IIError, rord, asrd,
+ asld, rold, decd, IIError, incd, tstd, IIError, clrd,
+
+/* 0x5X */ IIError, IIError, IIError, comw, lsrw, IIError, rorw, IIError,
+ IIError, rolw, decw, IIError, incw, tstw, IIError, clrw,
+
+/* 0x6X */ IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError,
+ IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError,
+
+/* 0x7X */ IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError,
+ IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError,
+
+/* 0x8X */ subw_im, cmpw_im, sbcd_im, cmpd_im, andd_im, bitd_im, ldw_im, IIError,
+ eord_im, adcd_im, ord_im, addw_im, cmpy_im, IIError, ldy_im, IIError,
+
+/* 0x9X */ subw_di, cmpw_di, sbcd_di, cmpd_di, andd_di, bitd_di, ldw_di, stw_di,
+ eord_di, adcd_di, ord_di, addw_di, cmpy_di, IIError, ldy_di, sty_di,
+
+/* 0xAX */ subw_ix, cmpw_ix, sbcd_ix, cmpd_ix, andd_ix, bitd_ix, ldw_ix, stw_ix,
+ eord_ix, adcd_ix, ord_ix, addw_ix, cmpy_ix, IIError, ldy_ix, sty_ix,
+
+/* 0xBX */ subw_ex, cmpw_ex, sbcd_ex, cmpd_ex, andd_ex, bitd_ex, ldw_ex, stw_ex,
+ eord_ex, adcd_ex, ord_ex, addw_ex, cmpy_ex, IIError, ldy_ex, sty_ex,
+
+/* 0xCX */ IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError,
+ IIError, IIError, IIError, IIError, IIError, IIError, lds_im, IIError,
+
+/* 0xDX */ IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError,
+ IIError, IIError, IIError, IIError, ldq_di, stq_di, lds_di, sts_di,
+
+/* 0xEX */ IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError,
+ IIError, IIError, IIError, IIError, ldq_ix, stq_ix, lds_ix, sts_ix,
+
+/* 0xFX */ IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError,
+ IIError, IIError, IIError, IIError, ldq_ex, stq_ex, lds_ex, sts_ex
+};
+static void (*const hd6309_page11[0x100])(m68_state_t *) = {
+/* 0xX0, 0xX1, 0xX2, 0xX3, 0xX4, 0xX5, 0xX6, 0xX7,
+ 0xX8, 0xX9, 0xXA, 0xXB, 0xXC, 0xXD, 0xXE, 0xXF */
+
+/* 0x0X */ IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError,
+ IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError,
+
+/* 0x1X */ IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError,
+ IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError,
+
+/* 0x2X */ IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError,
+ IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError,
+
+/* 0x3X */ band, biand, bor, bior, beor, bieor, ldbt, stbt,
+ tfmpp, tfmmm, tfmpc, tfmcp, bitmd_im,ldmd_im, IIError, swi3,
+
+/* 0x4X */ IIError, IIError, IIError, come, IIError, IIError, IIError, IIError,
+ IIError, IIError, dece, IIError, ince, tste, IIError, clre,
+
+/* 0x5X */ IIError, IIError, IIError, comf, IIError, IIError, IIError, IIError,
+ IIError, IIError, decf, IIError, incf, tstf, IIError, clrf,
+
+/* 0x6X */ IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError,
+ IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError,
+
+/* 0x7X */ IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError,
+ IIError, IIError, IIError, IIError, IIError, IIError, IIError, IIError,
+
+/* 0x8X */ sube_im, cmpe_im, IIError, cmpu_im, IIError, IIError, lde_im, IIError,
+ IIError, IIError, IIError, adde_im, cmps_im, divd_im, divq_im, muld_im,
+
+/* 0x9X */ sube_di, cmpe_di, IIError, cmpu_di, IIError, IIError, lde_di, ste_di,
+ IIError, IIError, IIError, adde_di, cmps_di, divd_di, divq_di, muld_di,
+
+/* 0xAX */ sube_ix, cmpe_ix, IIError, cmpu_ix, IIError, IIError, lde_ix, ste_ix,
+ IIError, IIError, IIError, adde_ix, cmps_ix, divd_ix, divq_ix, muld_ix,
+
+/* 0xBX */ sube_ex, cmpe_ex, IIError, cmpu_ex, IIError, IIError, lde_ex, ste_ex,
+ IIError, IIError, IIError, adde_ex, cmps_ex, divd_ex, divq_ex, muld_ex,
+
+/* 0xCX */ subf_im, cmpf_im, IIError, IIError, IIError, IIError, ldf_im, IIError,
+ IIError, IIError, IIError, addf_im, IIError, IIError, IIError, IIError,
+
+/* 0xDX */ subf_di, cmpf_di, IIError, IIError, IIError, IIError, ldf_di, stf_di,
+ IIError, IIError, IIError, addf_di, IIError, IIError, IIError, IIError,
+
+/* 0xEX */ subf_ix, cmpf_ix, IIError, IIError, IIError, IIError, ldf_ix, stf_ix,
+ IIError, IIError, IIError, addf_ix, IIError, IIError, IIError, IIError,
+
+/* 0xFX */ subf_ex, cmpf_ex, IIError, IIError, IIError, IIError, ldf_ex, stf_ex,
+ IIError, IIError, IIError, addf_ex, IIError, IIError, IIError, IIError
+
+};
+
+#endif /* BIG_SWITCH */
diff --git a/trunk/src/emu/cpu/hd6309/hd6309.c b/trunk/src/emu/cpu/hd6309/hd6309.c
new file mode 100644
index 00000000000..4e31116ad08
--- /dev/null
+++ b/trunk/src/emu/cpu/hd6309/hd6309.c
@@ -0,0 +1,1355 @@
+/*** hd6309: Portable 6309 emulator ******************************************
+
+ Copyright John Butler
+ Copyright Tim Lindner
+
+ References:
+
+ HD63B09EP Technical Reference Guide, by Chet Simpson with addition
+ by Alan Dekok
+ 6809 Simulator V09, By L.C. Benschop, Eidnhoven The Netherlands.
+
+ m6809: Portable 6809 emulator, DS (6809 code in MAME, derived from
+ the 6809 Simulator V09)
+
+ 6809 Microcomputer Programming & Interfacing with Experiments"
+ by Andrew C. Staugaard, Jr.; Howard W. Sams & Co., Inc.
+
+ System dependencies: UINT16 must be 16 bit unsigned int
+ UINT8 must be 8 bit unsigned int
+ UINT32 must be more than 16 bits
+ arrays up to 65536 bytes must be supported
+ machine must be twos complement
+
+ History:
+070614 ZV:
+ Fixed N flag setting in DIV overflow
+
+991026 HJB:
+ Fixed missing calls to cpu_changepc() for the TFR and EXG ocpodes.
+ Replaced m6809_slapstic checks by a macro (CHANGE_PC). ESB still
+ needs the tweaks.
+
+991024 HJB:
+ Tried to improve speed: Using bit7 of cycles1/2 as flag for multi
+ byte opcodes is gone, those opcodes now call fetch_effective_address().
+ Got rid of the slow/fast flags for stack (S and U) memory accesses.
+ Minor changes to use 32 bit values as arguments to memory functions
+ and added defines for that purpose (e.g. X = 16bit XD = 32bit).
+
+990312 HJB:
+ Added bugfixes according to Aaron's findings.
+ Reset only sets CC_II and CC_IF, DP to zero and PC from reset vector.
+990311 HJB:
+ Added _info functions. Now uses static m6808_Regs struct instead
+ of single statics. Changed the 16 bit registers to use the generic
+ PAIR union. Registers defined using macros. Split the core into
+ four execution loops for M6802, M6803, M6808 and HD63701.
+ TST, TSTA and TSTB opcodes reset carry flag.
+ Modified the read/write stack handlers to push LSB first then MSB
+ and pull MSB first then LSB.
+
+990228 HJB:
+ Changed the interrupt handling again. Now interrupts are taken
+ either right at the moment the lines are asserted or whenever
+ an interrupt is enabled and the corresponding line is still
+ asserted. That way the pending_interrupts checks are not
+ needed anymore. However, the CWAI and SYNC flags still need
+ some flags, so I changed the name to 'int_state'.
+ This core also has the code for the old interrupt system removed.
+
+990225 HJB:
+ Cleaned up the code here and there, added some comments.
+ Slightly changed the SAR opcodes (similiar to other CPU cores).
+ Added symbolic names for the flag bits.
+ Changed the way CWAI/Interrupt() handle CPU state saving.
+ A new flag M6809_STATE in pending_interrupts is used to determine
+ if a state save is needed on interrupt entry or already done by CWAI.
+ Added M6809_IRQ_LINE and M6809_FIRQ_LINE defines to m6809.h
+ Moved the internal interrupt_pending flags from m6809.h to m6809.c
+ Changed CWAI cycles2[0x3c] to be 2 (plus all or at least 19 if
+ CWAI actually pushes the entire state).
+ Implemented undocumented TFR/EXG for undefined source and mixed 8/16
+ bit transfers (they should transfer/exchange the constant $ff).
+ Removed unused jmp/jsr _slap functions from 6809ops.c,
+ m6809_slapstick check moved into the opcode functions.
+
+000809 TJL:
+ Started converting m6809 into hd6309
+
+001217 TJL:
+ Finished:
+ All opcodes
+ Dual Timing
+ To Do:
+ Verify new DIV opcodes.
+
+070805 TJL:
+ Fixed ADDR and ADCR opcodes not to clear the H condition code. Fixed ANDR,
+ EORR, ORR, ADDR, ADCR, SBCR, and SUBR to evaluate condition codes after
+ the destination register was set. Fixed BITMD opcode to only effect the Z
+ condition code. Fixed BITMD opcode to clear only tested flags. Fixed EXG
+ and TFR register promotion and demotion. Fixed illegal instruction handler
+ to not set I and F condition codes. Credit to Darren Atkinson for the
+ discovery of these bugs.
+
+090907 TJL:
+ The SEXW instruction is clearing the Overflow flag (V). It should not do
+ that. When an invalid source or destination register is specified for
+ the TFM instructions, real hardware invokes the Illegal Instruction
+ trap, whereas the emulator simply ignores the instruction. Credit to
+ Darren Atkinson for the discovery of these bugs.
+
+*****************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "hd6309.h"
+
+#define BIG_SWITCH 0
+
+#define VERBOSE 0
+
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+/* 6309 Registers */
+typedef struct _m68_state_t m68_state_t;
+struct _m68_state_t
+{
+ PAIR pc; /* Program counter */
+ PAIR ppc; /* Previous program counter */
+ PAIR d; /* Accumulator a and b */
+ PAIR w; /* Accumlator e and f */
+ /* abef = q */
+ PAIR dp; /* Direct Page register (page in MSB) */
+ PAIR u, s; /* Stack pointers */
+ PAIR x, y; /* Index registers */
+ UINT8 cc;
+ PAIR v; /* New 6309 register */
+ UINT8 md; /* Special mode register */
+ UINT8 ireg; /* First opcode */
+ UINT8 irq_state[2];
+
+ int extra_cycles; /* cycles used up by interrupts */
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ int icount;
+ PAIR ea; /* effective address */
+
+ /* Memory spaces */
+ address_space *program;
+ direct_read_data *direct;
+
+ UINT8 int_state; /* SYNC and CWAI flags */
+ UINT8 nmi_state;
+
+ UINT8 dummy_byte;
+ UINT8 *regTable[4];
+
+ UINT8 const *cycle_counts_page0;
+ UINT8 const *cycle_counts_page01;
+ UINT8 const *cycle_counts_page11;
+ UINT8 const *index_cycle;
+};
+
+INLINE m68_state_t *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == HD6309);
+ return (m68_state_t *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+static void check_irq_lines( m68_state_t *m68_state );
+static void IIError(m68_state_t *m68_state);
+static void DZError(m68_state_t *m68_state);
+
+INLINE void fetch_effective_address( m68_state_t *m68_state );
+
+/* flag bits in the cc register */
+#define CC_C 0x01 /* Carry */
+#define CC_V 0x02 /* Overflow */
+#define CC_Z 0x04 /* Zero */
+#define CC_N 0x08 /* Negative */
+#define CC_II 0x10 /* Inhibit IRQ */
+#define CC_H 0x20 /* Half (auxiliary) carry */
+#define CC_IF 0x40 /* Inhibit FIRQ */
+#define CC_E 0x80 /* entire state pushed */
+
+/* flag bits in the md register */
+#define MD_EM 0x01 /* Execution mode */
+#define MD_FM 0x02 /* FIRQ mode */
+#define MD_II 0x40 /* Illegal instruction */
+#define MD_DZ 0x80 /* Division by zero */
+
+#define pPPC m68_state->ppc
+#define pPC m68_state->pc
+#define pU m68_state->u
+#define pS m68_state->s
+#define pX m68_state->x
+#define pY m68_state->y
+#define pD m68_state->d
+
+#define pV m68_state->v
+#define pW m68_state->w
+
+/* #define pQ m68_state->q */
+/* #define pZ m68_state->z */
+
+#define PPC m68_state->ppc.w.l
+#define PC m68_state->pc.w.l
+#define PCD m68_state->pc.d
+#define U m68_state->u.w.l
+#define UD m68_state->u.d
+#define S m68_state->s.w.l
+#define SD m68_state->s.d
+#define X m68_state->x.w.l
+#define XD m68_state->x.d
+#define Y m68_state->y.w.l
+#define YD m68_state->y.d
+#define V m68_state->v.w.l
+#define VD m68_state->v.d
+#define D m68_state->d.w.l
+#define A m68_state->d.b.h
+#define B m68_state->d.b.l
+#define W m68_state->w.w.l
+#define E m68_state->w.b.h
+#define F m68_state->w.b.l
+#define DP m68_state->dp.b.h
+#define DPD m68_state->dp.d
+#define CC m68_state->cc
+#define MD m68_state->md
+
+#define EA m68_state->ea.w.l
+#define EAD m68_state->ea.d
+#define EAP m68_state->ea
+
+#define M6809_CWAI 8 /* set when CWAI is waiting for an interrupt */
+#define M6809_SYNC 16 /* set when SYNC is waiting for an interrupt */
+#define M6809_LDS 32 /* set when LDS occurred at least once */
+
+/****************************************************************************/
+/* Read a byte from given memory location */
+/****************************************************************************/
+#define RM(Addr) ((unsigned)m68_state->program->read_byte(Addr))
+
+/****************************************************************************/
+/* Write a byte to given memory location */
+/****************************************************************************/
+#define WM(Addr,Value) (m68_state->program->write_byte(Addr,Value))
+
+/****************************************************************************/
+/* Z80_RDOP() is identical to Z80_RDMEM() except it is used for reading */
+/* opcodes. In case of system with memory mapped I/O, this function can be */
+/* used to greatly speed up emulation */
+/****************************************************************************/
+#define ROP(Addr) ((unsigned)m68_state->direct->read_decrypted_byte(Addr))
+
+/****************************************************************************/
+/* Z80_RDOP_ARG() is identical to Z80_RDOP() except it is used for reading */
+/* opcode arguments. This difference can be used to support systems that */
+/* use different encoding mechanisms for opcodes and opcode arguments */
+/****************************************************************************/
+#define ROP_ARG(Addr) ((unsigned)m68_state->direct->read_raw_byte(Addr))
+
+/* macros to access memory */
+#define IMMBYTE(b) b = ROP_ARG(PCD); PC++
+#define IMMWORD(w) w.d = (ROP_ARG(PCD)<<8) | ROP_ARG((PCD+1)&0xffff); PC+=2
+#define IMMLONG(w) w.d = (ROP_ARG(PCD)<<24) + (ROP_ARG(PCD+1)<<16) + (ROP_ARG(PCD+2)<<8) + (ROP_ARG(PCD+3)); PC+=4
+
+#define PUSHBYTE(b) --S; WM(SD,b)
+#define PUSHWORD(w) --S; WM(SD,w.b.l); --S; WM(SD,w.b.h)
+#define PULLBYTE(b) b = RM(SD); S++
+#define PULLWORD(w) w = RM(SD)<<8; S++; w |= RM(SD); S++
+
+#define PSHUBYTE(b) --U; WM(UD,b);
+#define PSHUWORD(w) --U; WM(UD,w.b.l); --U; WM(UD,w.b.h)
+#define PULUBYTE(b) b = RM(UD); U++
+#define PULUWORD(w) w = RM(UD)<<8; U++; w |= RM(UD); U++
+
+#define CLR_HNZVC CC&=~(CC_H|CC_N|CC_Z|CC_V|CC_C)
+#define CLR_NZV CC&=~(CC_N|CC_Z|CC_V)
+#define CLR_NZ CC&=~(CC_N|CC_Z)
+#define CLR_HNZC CC&=~(CC_H|CC_N|CC_Z|CC_C)
+#define CLR_NZVC CC&=~(CC_N|CC_Z|CC_V|CC_C)
+#define CLR_Z CC&=~(CC_Z)
+#define CLR_N CC&=~(CC_N)
+#define CLR_NZC CC&=~(CC_N|CC_Z|CC_C)
+#define CLR_ZC CC&=~(CC_Z|CC_C)
+
+/* macros for CC -- CC bits affected should be reset before calling */
+#define SET_Z(a) if(!a)SEZ
+#define SET_Z8(a) SET_Z((UINT8)a)
+#define SET_Z16(a) SET_Z((UINT16)a)
+#define SET_N8(a) CC|=((a&0x80)>>4)
+#define SET_N16(a) CC|=((a&0x8000)>>12)
+#define SET_N32(a) CC|=((a&0x8000)>>20)
+#define SET_H(a,b,r) CC|=(((a^b^r)&0x10)<<1)
+#define SET_C8(a) CC|=((a&0x100)>>8)
+#define SET_C16(a) CC|=((a&0x10000)>>16)
+#define SET_V8(a,b,r) CC|=(((a^b^r^(r>>1))&0x80)>>6)
+#define SET_V16(a,b,r) CC|=(((a^b^r^(r>>1))&0x8000)>>14)
+
+#define SET_FLAGS8I(a) {CC|=flags8i[(a)&0xff];}
+#define SET_FLAGS8D(a) {CC|=flags8d[(a)&0xff];}
+
+/* combos */
+#define SET_NZ8(a) {SET_N8(a);SET_Z(a);}
+#define SET_NZ16(a) {SET_N16(a);SET_Z(a);}
+#define SET_FLAGS8(a,b,r) {SET_N8(r);SET_Z8(r);SET_V8(a,b,r);SET_C8(r);}
+#define SET_FLAGS16(a,b,r) {SET_N16(r);SET_Z16(r);SET_V16(a,b,r);SET_C16(r);}
+
+#define NXORV ((CC&CC_N)^((CC&CC_V)<<2))
+
+/* for treating an unsigned byte as a signed word */
+#define SIGNED(b) ((UINT16)(b&0x80?b|0xff00:b))
+
+/* for treating an unsigned short as a signed long */
+#define SIGNED_16(b) ((UINT32)(b&0x8000?b|0xffff0000:b))
+
+/* macros for addressing modes (postbytes have their own code) */
+#define DIRECT EAD = DPD; IMMBYTE(m68_state->ea.b.l)
+#define IMM8 EAD = PCD; PC++
+#define IMM16 EAD = PCD; PC+=2
+#define EXTENDED IMMWORD(EAP)
+
+/* macros to set status flags */
+#if defined(SEC)
+#undef SEC
+#endif
+#define SEC CC|=CC_C
+#define CLC CC&=~CC_C
+#define SEZ CC|=CC_Z
+#define CLZ CC&=~CC_Z
+#define SEN CC|=CC_N
+#define CLN CC&=~CC_N
+#define SEV CC|=CC_V
+#define CLV CC&=~CC_V
+#define SEH CC|=CC_H
+#define CLH CC&=~CC_H
+
+/* Macros to set mode flags */
+#define SEDZ MD|=MD_DZ
+#define CLDZ MD&=~MD_DZ
+#define SEII MD|=MD_II
+#define CLII MD&=~MD_II
+#define SEFM MD|=MD_FM
+#define CLFM MD&=~MD_FM
+#define SEEM MD|=MD_EM
+#define CLEM MD&=~MD_EM
+
+/* macros for convenience */
+#define DIRBYTE(b) {DIRECT;b=RM(EAD);}
+#define DIRWORD(w) {DIRECT;w.d=RM16(m68_state, EAD);}
+#define EXTBYTE(b) {EXTENDED;b=RM(EAD);}
+#define EXTWORD(w) {EXTENDED;w.d=RM16(m68_state, EAD);}
+
+#define DIRLONG(lng) {DIRECT;lng.w.h=RM16(m68_state, EAD);lng.w.l=RM16(m68_state, EAD+2);}
+#define EXTLONG(lng) {EXTENDED;lng.w.h=RM16(m68_state, EAD);lng.w.l=RM16(m68_state, EAD+2);}
+
+/* includes the static function prototypes and other tables */
+#include "6309tbl.c"
+
+/* macros for branch instructions */
+#define BRANCH(f) { \
+ UINT8 t; \
+ IMMBYTE(t); \
+ if( f ) \
+ { \
+ PC += SIGNED(t); \
+ } \
+}
+
+#define LBRANCH(f) { \
+ PAIR t; \
+ IMMWORD(t); \
+ if( f ) \
+ { \
+ if( !(MD & MD_EM) ) \
+ m68_state->icount -= 1; \
+ PC += t.w.l; \
+ } \
+}
+
+/* macros for setting/getting registers in TFR/EXG instructions */
+
+INLINE UINT32 RM16(m68_state_t *m68_state, UINT32 Addr )
+{
+ UINT32 result = RM(Addr) << 8;
+ return result | RM((Addr+1)&0xffff);
+}
+
+INLINE UINT32 RM32(m68_state_t *m68_state, UINT32 Addr )
+{
+ UINT32 result = RM(Addr) << 24;
+ result += RM(Addr+1) << 16;
+ result += RM(Addr+2) << 8;
+ result += RM(Addr+3);
+ return result;
+}
+
+INLINE void WM16(m68_state_t *m68_state, UINT32 Addr, PAIR *p )
+{
+ WM( Addr, p->b.h );
+ WM( (Addr+1)&0xffff, p->b.l );
+}
+
+INLINE void WM32(m68_state_t *m68_state, UINT32 Addr, PAIR *p )
+{
+ WM( Addr, p->b.h3 );
+ WM( (Addr+1)&0xffff, p->b.h2 );
+ WM( (Addr+2)&0xffff, p->b.h );
+ WM( (Addr+3)&0xffff, p->b.l );
+}
+
+static void UpdateState(m68_state_t *m68_state)
+{
+ if ( m68_state->md & MD_EM )
+ {
+ m68_state->cycle_counts_page0 = ccounts_page0_na;
+ m68_state->cycle_counts_page01 = ccounts_page01_na;
+ m68_state->cycle_counts_page11 = ccounts_page11_na;
+ m68_state->index_cycle = index_cycle_na;
+ }
+ else
+ {
+ m68_state->cycle_counts_page0 = ccounts_page0_em;
+ m68_state->cycle_counts_page01 = ccounts_page01_em;
+ m68_state->cycle_counts_page11 = ccounts_page11_em;
+ m68_state->index_cycle = index_cycle_em;
+ }
+}
+
+static void check_irq_lines( m68_state_t *m68_state )
+{
+ if( m68_state->irq_state[HD6309_IRQ_LINE] != CLEAR_LINE ||
+ m68_state->irq_state[HD6309_FIRQ_LINE] != CLEAR_LINE )
+ m68_state->int_state &= ~M6809_SYNC; /* clear SYNC flag */
+ if( m68_state->irq_state[HD6309_FIRQ_LINE]!=CLEAR_LINE && !(CC & CC_IF))
+ {
+ /* fast IRQ */
+ /* HJB 990225: state already saved by CWAI? */
+ if( m68_state->int_state & M6809_CWAI )
+ {
+ m68_state->int_state &= ~M6809_CWAI;
+ m68_state->extra_cycles += 7; /* subtract +7 cycles */
+ }
+ else
+ {
+ if ( MD & MD_FM )
+ {
+ CC |= CC_E; /* save entire state */
+ PUSHWORD(pPC);
+ PUSHWORD(pU);
+ PUSHWORD(pY);
+ PUSHWORD(pX);
+ PUSHBYTE(DP);
+ if ( MD & MD_EM )
+ {
+ PUSHBYTE(F);
+ PUSHBYTE(E);
+ m68_state->extra_cycles += 2; /* subtract +2 cycles */
+ }
+ PUSHBYTE(B);
+ PUSHBYTE(A);
+ PUSHBYTE(CC);
+ m68_state->extra_cycles += 19; /* subtract +19 cycles */
+ }
+ else
+ {
+ CC &= ~CC_E; /* save 'short' state */
+ PUSHWORD(pPC);
+ PUSHBYTE(CC);
+ m68_state->extra_cycles += 10; /* subtract +10 cycles */
+ }
+ }
+ CC |= CC_IF | CC_II; /* inhibit FIRQ and IRQ */
+ PCD=RM16(m68_state, 0xfff6);
+ (void)(*m68_state->irq_callback)(m68_state->device, HD6309_FIRQ_LINE);
+ }
+ else
+ if( m68_state->irq_state[HD6309_IRQ_LINE]!=CLEAR_LINE && !(CC & CC_II) )
+ {
+ /* standard IRQ */
+ /* HJB 990225: state already saved by CWAI? */
+ if( m68_state->int_state & M6809_CWAI )
+ {
+ m68_state->int_state &= ~M6809_CWAI; /* clear CWAI flag */
+ m68_state->extra_cycles += 7; /* subtract +7 cycles */
+ }
+ else
+ {
+ CC |= CC_E; /* save entire state */
+ PUSHWORD(pPC);
+ PUSHWORD(pU);
+ PUSHWORD(pY);
+ PUSHWORD(pX);
+ PUSHBYTE(DP);
+ if ( MD & MD_EM )
+ {
+ PUSHBYTE(F);
+ PUSHBYTE(E);
+ m68_state->extra_cycles += 2; /* subtract +2 cycles */
+ }
+ PUSHBYTE(B);
+ PUSHBYTE(A);
+ PUSHBYTE(CC);
+ m68_state->extra_cycles += 19; /* subtract +19 cycles */
+ }
+ CC |= CC_II; /* inhibit IRQ */
+ PCD=RM16(m68_state, 0xfff8);
+ (void)(*m68_state->irq_callback)(m68_state->device, HD6309_IRQ_LINE);
+ }
+}
+
+
+
+static void hd6309_postload(m68_state_t *m68_state)
+{
+ UpdateState(m68_state);
+}
+
+
+/****************************************************************************/
+/* Reset registers to their initial values */
+/****************************************************************************/
+static CPU_INIT( hd6309 )
+{
+ m68_state_t *m68_state = get_safe_token(device);
+
+ m68_state->irq_callback = irqcallback;
+ m68_state->device = device;
+
+ m68_state->program = device->space(AS_PROGRAM);
+ m68_state->direct = &m68_state->program->direct();
+
+ /* setup regtable */
+
+ m68_state->regTable[0] = &(CC);
+ m68_state->regTable[1] = &(A);
+ m68_state->regTable[2] = &(B);
+ m68_state->regTable[3] = &m68_state->dummy_byte;
+
+ device->save_item(NAME(PC));
+ device->save_item(NAME(U));
+ device->save_item(NAME(S));
+ device->save_item(NAME(X));
+ device->save_item(NAME(Y));
+ device->save_item(NAME(V));
+ device->save_item(NAME(DP));
+ device->save_item(NAME(CC));
+ device->save_item(NAME(MD));
+ device->machine().save().register_postload(save_prepost_delegate(FUNC(hd6309_postload), m68_state));
+ device->save_item(NAME(m68_state->int_state));
+ device->save_item(NAME(m68_state->nmi_state));
+ device->save_item(NAME(m68_state->irq_state[0]));
+ device->save_item(NAME(m68_state->irq_state[1]));
+}
+
+/****************************************************************************/
+/* Reset registers to their initial values */
+/****************************************************************************/
+static CPU_RESET( hd6309 )
+{
+ m68_state_t *m68_state = get_safe_token(device);
+
+ m68_state->int_state = 0;
+ m68_state->nmi_state = CLEAR_LINE;
+ m68_state->irq_state[0] = CLEAR_LINE;
+ m68_state->irq_state[1] = CLEAR_LINE;
+
+ DPD = 0; /* Reset direct page register */
+
+ MD = 0; /* Mode register gets reset */
+ CC |= CC_II; /* IRQ disabled */
+ CC |= CC_IF; /* FIRQ disabled */
+
+ PCD = RM16(m68_state, 0xfffe);
+ UpdateState(m68_state);
+}
+
+static CPU_EXIT( hd6309 )
+{
+ /* nothing to do ? */
+}
+
+/****************************************************************************
+ * Set IRQ line state
+ ****************************************************************************/
+static void set_irq_line(m68_state_t *m68_state, int irqline, int state)
+{
+ if (irqline == INPUT_LINE_NMI)
+ {
+ if (m68_state->nmi_state == state) return;
+ m68_state->nmi_state = state;
+ LOG(("HD6309 '%s' set_irq_line (NMI) %d (PC=%4.4X)\n", m68_state->device->tag(), state, pPC.d));
+ if( state == CLEAR_LINE ) return;
+
+ /* if the stack was not yet initialized */
+ if( !(m68_state->int_state & M6809_LDS) ) return;
+
+ m68_state->int_state &= ~M6809_SYNC;
+ /* HJB 990225: state already saved by CWAI? */
+ if( m68_state->int_state & M6809_CWAI )
+ {
+ m68_state->int_state &= ~M6809_CWAI;
+ m68_state->extra_cycles += 7; /* subtract +7 cycles next time */
+ }
+ else
+ {
+ CC |= CC_E; /* save entire state */
+ PUSHWORD(pPC);
+ PUSHWORD(pU);
+ PUSHWORD(pY);
+ PUSHWORD(pX);
+ PUSHBYTE(DP);
+ if ( MD & MD_EM )
+ {
+ PUSHBYTE(F);
+ PUSHBYTE(E);
+ m68_state->extra_cycles += 2; /* subtract +2 cycles */
+ }
+
+ PUSHBYTE(B);
+ PUSHBYTE(A);
+ PUSHBYTE(CC);
+ m68_state->extra_cycles += 19; /* subtract +19 cycles next time */
+ }
+ CC |= CC_IF | CC_II; /* inhibit FIRQ and IRQ */
+ PCD = RM16(m68_state, 0xfffc);
+ }
+ else if (irqline < 2)
+ {
+ LOG(("HD6309 '%s' set_irq_line %d, %d (PC=%4.4X)\n", m68_state->device->tag(), irqline, state, pPC.d));
+ m68_state->irq_state[irqline] = state;
+ if (state == CLEAR_LINE) return;
+ check_irq_lines(m68_state);
+ }
+}
+
+/****************************************************************************
+ * includes the actual opcode implementations
+ ****************************************************************************/
+#include "6309ops.c"
+
+/* execute instructions on this CPU until icount expires */
+static CPU_EXECUTE( hd6309 ) /* NS 970908 */
+{
+ m68_state_t *m68_state = get_safe_token(device);
+
+ m68_state->icount -= m68_state->extra_cycles;
+ m68_state->extra_cycles = 0;
+
+ check_irq_lines(m68_state);
+
+ if (m68_state->int_state & (M6809_CWAI | M6809_SYNC))
+ {
+ debugger_instruction_hook(device, PCD);
+ m68_state->icount = 0;
+ }
+ else
+ {
+ do
+ {
+ pPPC = pPC;
+
+ debugger_instruction_hook(device, PCD);
+
+ m68_state->ireg = ROP(PCD);
+ PC++;
+#if BIG_SWITCH
+ switch( m68_state->ireg )
+ {
+ case 0x00: neg_di(m68_state); break;
+ case 0x01: oim_di(m68_state); break;
+ case 0x02: aim_di(m68_state); break;
+ case 0x03: com_di(m68_state); break;
+ case 0x04: lsr_di(m68_state); break;
+ case 0x05: eim_di(m68_state); break;
+ case 0x06: ror_di(m68_state); break;
+ case 0x07: asr_di(m68_state); break;
+ case 0x08: asl_di(m68_state); break;
+ case 0x09: rol_di(m68_state); break;
+ case 0x0a: dec_di(m68_state); break;
+ case 0x0b: tim_di(m68_state); break;
+ case 0x0c: inc_di(m68_state); break;
+ case 0x0d: tst_di(m68_state); break;
+ case 0x0e: jmp_di(m68_state); break;
+ case 0x0f: clr_di(m68_state); break;
+ case 0x10: pref10(m68_state); break;
+ case 0x11: pref11(m68_state); break;
+ case 0x12: nop(m68_state); break;
+ case 0x13: sync(m68_state); break;
+ case 0x14: sexw(m68_state); break;
+ case 0x15: IIError(m68_state); break;
+ case 0x16: lbra(m68_state); break;
+ case 0x17: lbsr(m68_state); break;
+ case 0x18: IIError(m68_state); break;
+ case 0x19: daa(m68_state); break;
+ case 0x1a: orcc(m68_state); break;
+ case 0x1b: IIError(m68_state); break;
+ case 0x1c: andcc(m68_state); break;
+ case 0x1d: sex(m68_state); break;
+ case 0x1e: exg(m68_state); break;
+ case 0x1f: tfr(m68_state); break;
+ case 0x20: bra(m68_state); break;
+ case 0x21: brn(m68_state); break;
+ case 0x22: bhi(m68_state); break;
+ case 0x23: bls(m68_state); break;
+ case 0x24: bcc(m68_state); break;
+ case 0x25: bcs(m68_state); break;
+ case 0x26: bne(m68_state); break;
+ case 0x27: beq(m68_state); break;
+ case 0x28: bvc(m68_state); break;
+ case 0x29: bvs(m68_state); break;
+ case 0x2a: bpl(m68_state); break;
+ case 0x2b: bmi(m68_state); break;
+ case 0x2c: bge(m68_state); break;
+ case 0x2d: blt(m68_state); break;
+ case 0x2e: bgt(m68_state); break;
+ case 0x2f: ble(m68_state); break;
+ case 0x30: leax(m68_state); break;
+ case 0x31: leay(m68_state); break;
+ case 0x32: leas(m68_state); break;
+ case 0x33: leau(m68_state); break;
+ case 0x34: pshs(m68_state); break;
+ case 0x35: puls(m68_state); break;
+ case 0x36: pshu(m68_state); break;
+ case 0x37: pulu(m68_state); break;
+ case 0x38: IIError(m68_state); break;
+ case 0x39: rts(m68_state); break;
+ case 0x3a: abx(m68_state); break;
+ case 0x3b: rti(m68_state); break;
+ case 0x3c: cwai(m68_state); break;
+ case 0x3d: mul(m68_state); break;
+ case 0x3e: IIError(m68_state); break;
+ case 0x3f: swi(m68_state); break;
+ case 0x40: nega(m68_state); break;
+ case 0x41: IIError(m68_state); break;
+ case 0x42: IIError(m68_state); break;
+ case 0x43: coma(m68_state); break;
+ case 0x44: lsra(m68_state); break;
+ case 0x45: IIError(m68_state); break;
+ case 0x46: rora(m68_state); break;
+ case 0x47: asra(m68_state); break;
+ case 0x48: asla(m68_state); break;
+ case 0x49: rola(m68_state); break;
+ case 0x4a: deca(m68_state); break;
+ case 0x4b: IIError(m68_state); break;
+ case 0x4c: inca(m68_state); break;
+ case 0x4d: tsta(m68_state); break;
+ case 0x4e: IIError(m68_state); break;
+ case 0x4f: clra(m68_state); break;
+ case 0x50: negb(m68_state); break;
+ case 0x51: IIError(m68_state); break;
+ case 0x52: IIError(m68_state); break;
+ case 0x53: comb(m68_state); break;
+ case 0x54: lsrb(m68_state); break;
+ case 0x55: IIError(m68_state); break;
+ case 0x56: rorb(m68_state); break;
+ case 0x57: asrb(m68_state); break;
+ case 0x58: aslb(m68_state); break;
+ case 0x59: rolb(m68_state); break;
+ case 0x5a: decb(m68_state); break;
+ case 0x5b: IIError(m68_state); break;
+ case 0x5c: incb(m68_state); break;
+ case 0x5d: tstb(m68_state); break;
+ case 0x5e: IIError(m68_state); break;
+ case 0x5f: clrb(m68_state); break;
+ case 0x60: neg_ix(m68_state); break;
+ case 0x61: oim_ix(m68_state); break;
+ case 0x62: aim_ix(m68_state); break;
+ case 0x63: com_ix(m68_state); break;
+ case 0x64: lsr_ix(m68_state); break;
+ case 0x65: eim_ix(m68_state); break;
+ case 0x66: ror_ix(m68_state); break;
+ case 0x67: asr_ix(m68_state); break;
+ case 0x68: asl_ix(m68_state); break;
+ case 0x69: rol_ix(m68_state); break;
+ case 0x6a: dec_ix(m68_state); break;
+ case 0x6b: tim_ix(m68_state); break;
+ case 0x6c: inc_ix(m68_state); break;
+ case 0x6d: tst_ix(m68_state); break;
+ case 0x6e: jmp_ix(m68_state); break;
+ case 0x6f: clr_ix(m68_state); break;
+ case 0x70: neg_ex(m68_state); break;
+ case 0x71: oim_ex(m68_state); break;
+ case 0x72: aim_ex(m68_state); break;
+ case 0x73: com_ex(m68_state); break;
+ case 0x74: lsr_ex(m68_state); break;
+ case 0x75: eim_ex(m68_state); break;
+ case 0x76: ror_ex(m68_state); break;
+ case 0x77: asr_ex(m68_state); break;
+ case 0x78: asl_ex(m68_state); break;
+ case 0x79: rol_ex(m68_state); break;
+ case 0x7a: dec_ex(m68_state); break;
+ case 0x7b: tim_ex(m68_state); break;
+ case 0x7c: inc_ex(m68_state); break;
+ case 0x7d: tst_ex(m68_state); break;
+ case 0x7e: jmp_ex(m68_state); break;
+ case 0x7f: clr_ex(m68_state); break;
+ case 0x80: suba_im(m68_state); break;
+ case 0x81: cmpa_im(m68_state); break;
+ case 0x82: sbca_im(m68_state); break;
+ case 0x83: subd_im(m68_state); break;
+ case 0x84: anda_im(m68_state); break;
+ case 0x85: bita_im(m68_state); break;
+ case 0x86: lda_im(m68_state); break;
+ case 0x87: IIError(m68_state); break;
+ case 0x88: eora_im(m68_state); break;
+ case 0x89: adca_im(m68_state); break;
+ case 0x8a: ora_im(m68_state); break;
+ case 0x8b: adda_im(m68_state); break;
+ case 0x8c: cmpx_im(m68_state); break;
+ case 0x8d: bsr(m68_state); break;
+ case 0x8e: ldx_im(m68_state); break;
+ case 0x8f: IIError(m68_state); break;
+ case 0x90: suba_di(m68_state); break;
+ case 0x91: cmpa_di(m68_state); break;
+ case 0x92: sbca_di(m68_state); break;
+ case 0x93: subd_di(m68_state); break;
+ case 0x94: anda_di(m68_state); break;
+ case 0x95: bita_di(m68_state); break;
+ case 0x96: lda_di(m68_state); break;
+ case 0x97: sta_di(m68_state); break;
+ case 0x98: eora_di(m68_state); break;
+ case 0x99: adca_di(m68_state); break;
+ case 0x9a: ora_di(m68_state); break;
+ case 0x9b: adda_di(m68_state); break;
+ case 0x9c: cmpx_di(m68_state); break;
+ case 0x9d: jsr_di(m68_state); break;
+ case 0x9e: ldx_di(m68_state); break;
+ case 0x9f: stx_di(m68_state); break;
+ case 0xa0: suba_ix(m68_state); break;
+ case 0xa1: cmpa_ix(m68_state); break;
+ case 0xa2: sbca_ix(m68_state); break;
+ case 0xa3: subd_ix(m68_state); break;
+ case 0xa4: anda_ix(m68_state); break;
+ case 0xa5: bita_ix(m68_state); break;
+ case 0xa6: lda_ix(m68_state); break;
+ case 0xa7: sta_ix(m68_state); break;
+ case 0xa8: eora_ix(m68_state); break;
+ case 0xa9: adca_ix(m68_state); break;
+ case 0xaa: ora_ix(m68_state); break;
+ case 0xab: adda_ix(m68_state); break;
+ case 0xac: cmpx_ix(m68_state); break;
+ case 0xad: jsr_ix(m68_state); break;
+ case 0xae: ldx_ix(m68_state); break;
+ case 0xaf: stx_ix(m68_state); break;
+ case 0xb0: suba_ex(m68_state); break;
+ case 0xb1: cmpa_ex(m68_state); break;
+ case 0xb2: sbca_ex(m68_state); break;
+ case 0xb3: subd_ex(m68_state); break;
+ case 0xb4: anda_ex(m68_state); break;
+ case 0xb5: bita_ex(m68_state); break;
+ case 0xb6: lda_ex(m68_state); break;
+ case 0xb7: sta_ex(m68_state); break;
+ case 0xb8: eora_ex(m68_state); break;
+ case 0xb9: adca_ex(m68_state); break;
+ case 0xba: ora_ex(m68_state); break;
+ case 0xbb: adda_ex(m68_state); break;
+ case 0xbc: cmpx_ex(m68_state); break;
+ case 0xbd: jsr_ex(m68_state); break;
+ case 0xbe: ldx_ex(m68_state); break;
+ case 0xbf: stx_ex(m68_state); break;
+ case 0xc0: subb_im(m68_state); break;
+ case 0xc1: cmpb_im(m68_state); break;
+ case 0xc2: sbcb_im(m68_state); break;
+ case 0xc3: addd_im(m68_state); break;
+ case 0xc4: andb_im(m68_state); break;
+ case 0xc5: bitb_im(m68_state); break;
+ case 0xc6: ldb_im(m68_state); break;
+ case 0xc7: IIError(m68_state); break;
+ case 0xc8: eorb_im(m68_state); break;
+ case 0xc9: adcb_im(m68_state); break;
+ case 0xca: orb_im(m68_state); break;
+ case 0xcb: addb_im(m68_state); break;
+ case 0xcc: ldd_im(m68_state); break;
+ case 0xcd: ldq_im(m68_state); break; /* in m6809 was std_im */
+ case 0xce: ldu_im(m68_state); break;
+ case 0xcf: IIError(m68_state); break;
+ case 0xd0: subb_di(m68_state); break;
+ case 0xd1: cmpb_di(m68_state); break;
+ case 0xd2: sbcb_di(m68_state); break;
+ case 0xd3: addd_di(m68_state); break;
+ case 0xd4: andb_di(m68_state); break;
+ case 0xd5: bitb_di(m68_state); break;
+ case 0xd6: ldb_di(m68_state); break;
+ case 0xd7: stb_di(m68_state); break;
+ case 0xd8: eorb_di(m68_state); break;
+ case 0xd9: adcb_di(m68_state); break;
+ case 0xda: orb_di(m68_state); break;
+ case 0xdb: addb_di(m68_state); break;
+ case 0xdc: ldd_di(m68_state); break;
+ case 0xdd: std_di(m68_state); break;
+ case 0xde: ldu_di(m68_state); break;
+ case 0xdf: stu_di(m68_state); break;
+ case 0xe0: subb_ix(m68_state); break;
+ case 0xe1: cmpb_ix(m68_state); break;
+ case 0xe2: sbcb_ix(m68_state); break;
+ case 0xe3: addd_ix(m68_state); break;
+ case 0xe4: andb_ix(m68_state); break;
+ case 0xe5: bitb_ix(m68_state); break;
+ case 0xe6: ldb_ix(m68_state); break;
+ case 0xe7: stb_ix(m68_state); break;
+ case 0xe8: eorb_ix(m68_state); break;
+ case 0xe9: adcb_ix(m68_state); break;
+ case 0xea: orb_ix(m68_state); break;
+ case 0xeb: addb_ix(m68_state); break;
+ case 0xec: ldd_ix(m68_state); break;
+ case 0xed: std_ix(m68_state); break;
+ case 0xee: ldu_ix(m68_state); break;
+ case 0xef: stu_ix(m68_state); break;
+ case 0xf0: subb_ex(m68_state); break;
+ case 0xf1: cmpb_ex(m68_state); break;
+ case 0xf2: sbcb_ex(m68_state); break;
+ case 0xf3: addd_ex(m68_state); break;
+ case 0xf4: andb_ex(m68_state); break;
+ case 0xf5: bitb_ex(m68_state); break;
+ case 0xf6: ldb_ex(m68_state); break;
+ case 0xf7: stb_ex(m68_state); break;
+ case 0xf8: eorb_ex(m68_state); break;
+ case 0xf9: adcb_ex(m68_state); break;
+ case 0xfa: orb_ex(m68_state); break;
+ case 0xfb: addb_ex(m68_state); break;
+ case 0xfc: ldd_ex(m68_state); break;
+ case 0xfd: std_ex(m68_state); break;
+ case 0xfe: ldu_ex(m68_state); break;
+ case 0xff: stu_ex(m68_state); break;
+ }
+#else
+ (*hd6309_main[m68_state->ireg])(m68_state);
+#endif /* BIG_SWITCH */
+
+ m68_state->icount -= m68_state->cycle_counts_page0[m68_state->ireg];
+
+ } while( m68_state->icount > 0 );
+
+ m68_state->icount -= m68_state->extra_cycles;
+ m68_state->extra_cycles = 0;
+ }
+}
+
+INLINE void fetch_effective_address( m68_state_t *m68_state )
+{
+ UINT8 postbyte = ROP_ARG(PCD);
+ PC++;
+
+ switch(postbyte)
+ {
+ case 0x00: EA=X; break;
+ case 0x01: EA=X+1; break;
+ case 0x02: EA=X+2; break;
+ case 0x03: EA=X+3; break;
+ case 0x04: EA=X+4; break;
+ case 0x05: EA=X+5; break;
+ case 0x06: EA=X+6; break;
+ case 0x07: EA=X+7; break;
+ case 0x08: EA=X+8; break;
+ case 0x09: EA=X+9; break;
+ case 0x0a: EA=X+10; break;
+ case 0x0b: EA=X+11; break;
+ case 0x0c: EA=X+12; break;
+ case 0x0d: EA=X+13; break;
+ case 0x0e: EA=X+14; break;
+ case 0x0f: EA=X+15; break;
+
+ case 0x10: EA=X-16; break;
+ case 0x11: EA=X-15; break;
+ case 0x12: EA=X-14; break;
+ case 0x13: EA=X-13; break;
+ case 0x14: EA=X-12; break;
+ case 0x15: EA=X-11; break;
+ case 0x16: EA=X-10; break;
+ case 0x17: EA=X-9; break;
+ case 0x18: EA=X-8; break;
+ case 0x19: EA=X-7; break;
+ case 0x1a: EA=X-6; break;
+ case 0x1b: EA=X-5; break;
+ case 0x1c: EA=X-4; break;
+ case 0x1d: EA=X-3; break;
+ case 0x1e: EA=X-2; break;
+ case 0x1f: EA=X-1; break;
+
+ case 0x20: EA=Y; break;
+ case 0x21: EA=Y+1; break;
+ case 0x22: EA=Y+2; break;
+ case 0x23: EA=Y+3; break;
+ case 0x24: EA=Y+4; break;
+ case 0x25: EA=Y+5; break;
+ case 0x26: EA=Y+6; break;
+ case 0x27: EA=Y+7; break;
+ case 0x28: EA=Y+8; break;
+ case 0x29: EA=Y+9; break;
+ case 0x2a: EA=Y+10; break;
+ case 0x2b: EA=Y+11; break;
+ case 0x2c: EA=Y+12; break;
+ case 0x2d: EA=Y+13; break;
+ case 0x2e: EA=Y+14; break;
+ case 0x2f: EA=Y+15; break;
+
+ case 0x30: EA=Y-16; break;
+ case 0x31: EA=Y-15; break;
+ case 0x32: EA=Y-14; break;
+ case 0x33: EA=Y-13; break;
+ case 0x34: EA=Y-12; break;
+ case 0x35: EA=Y-11; break;
+ case 0x36: EA=Y-10; break;
+ case 0x37: EA=Y-9; break;
+ case 0x38: EA=Y-8; break;
+ case 0x39: EA=Y-7; break;
+ case 0x3a: EA=Y-6; break;
+ case 0x3b: EA=Y-5; break;
+ case 0x3c: EA=Y-4; break;
+ case 0x3d: EA=Y-3; break;
+ case 0x3e: EA=Y-2; break;
+ case 0x3f: EA=Y-1; break;
+
+ case 0x40: EA=U; break;
+ case 0x41: EA=U+1; break;
+ case 0x42: EA=U+2; break;
+ case 0x43: EA=U+3; break;
+ case 0x44: EA=U+4; break;
+ case 0x45: EA=U+5; break;
+ case 0x46: EA=U+6; break;
+ case 0x47: EA=U+7; break;
+ case 0x48: EA=U+8; break;
+ case 0x49: EA=U+9; break;
+ case 0x4a: EA=U+10; break;
+ case 0x4b: EA=U+11; break;
+ case 0x4c: EA=U+12; break;
+ case 0x4d: EA=U+13; break;
+ case 0x4e: EA=U+14; break;
+ case 0x4f: EA=U+15; break;
+
+ case 0x50: EA=U-16; break;
+ case 0x51: EA=U-15; break;
+ case 0x52: EA=U-14; break;
+ case 0x53: EA=U-13; break;
+ case 0x54: EA=U-12; break;
+ case 0x55: EA=U-11; break;
+ case 0x56: EA=U-10; break;
+ case 0x57: EA=U-9; break;
+ case 0x58: EA=U-8; break;
+ case 0x59: EA=U-7; break;
+ case 0x5a: EA=U-6; break;
+ case 0x5b: EA=U-5; break;
+ case 0x5c: EA=U-4; break;
+ case 0x5d: EA=U-3; break;
+ case 0x5e: EA=U-2; break;
+ case 0x5f: EA=U-1; break;
+
+ case 0x60: EA=S; break;
+ case 0x61: EA=S+1; break;
+ case 0x62: EA=S+2; break;
+ case 0x63: EA=S+3; break;
+ case 0x64: EA=S+4; break;
+ case 0x65: EA=S+5; break;
+ case 0x66: EA=S+6; break;
+ case 0x67: EA=S+7; break;
+ case 0x68: EA=S+8; break;
+ case 0x69: EA=S+9; break;
+ case 0x6a: EA=S+10; break;
+ case 0x6b: EA=S+11; break;
+ case 0x6c: EA=S+12; break;
+ case 0x6d: EA=S+13; break;
+ case 0x6e: EA=S+14; break;
+ case 0x6f: EA=S+15; break;
+
+ case 0x70: EA=S-16; break;
+ case 0x71: EA=S-15; break;
+ case 0x72: EA=S-14; break;
+ case 0x73: EA=S-13; break;
+ case 0x74: EA=S-12; break;
+ case 0x75: EA=S-11; break;
+ case 0x76: EA=S-10; break;
+ case 0x77: EA=S-9; break;
+ case 0x78: EA=S-8; break;
+ case 0x79: EA=S-7; break;
+ case 0x7a: EA=S-6; break;
+ case 0x7b: EA=S-5; break;
+ case 0x7c: EA=S-4; break;
+ case 0x7d: EA=S-3; break;
+ case 0x7e: EA=S-2; break;
+ case 0x7f: EA=S-1; break;
+
+ case 0x80: EA=X; X++; break;
+ case 0x81: EA=X; X+=2; break;
+ case 0x82: X--; EA=X; break;
+ case 0x83: X-=2; EA=X; break;
+ case 0x84: EA=X; break;
+ case 0x85: EA=X+SIGNED(B); break;
+ case 0x86: EA=X+SIGNED(A); break;
+ case 0x87: EA=X+SIGNED(E); break;
+ case 0x88: IMMBYTE(EA); EA=X+SIGNED(EA); break;
+ case 0x89: IMMWORD(EAP); EA+=X; break;
+ case 0x8a: EA=X+SIGNED(F); break;
+ case 0x8b: EA=X+D; break;
+ case 0x8c: IMMBYTE(EA); EA=PC+SIGNED(EA); break;
+ case 0x8d: IMMWORD(EAP); EA+=PC; break;
+ case 0x8e: EA=X+W; break;
+ case 0x8f: EA=W; break;
+
+ case 0x90: EA=W; EAD=RM16(m68_state, EAD); break;
+ case 0x91: EA=X; X+=2; EAD=RM16(m68_state, EAD); break;
+ case 0x92: IIError(m68_state); break;
+ case 0x93: X-=2; EA=X; EAD=RM16(m68_state, EAD); break;
+ case 0x94: EA=X; EAD=RM16(m68_state, EAD); break;
+ case 0x95: EA=X+SIGNED(B); EAD=RM16(m68_state, EAD); break;
+ case 0x96: EA=X+SIGNED(A); EAD=RM16(m68_state, EAD); break;
+ case 0x97: EA=X+SIGNED(E); EAD=RM16(m68_state, EAD); break;
+ case 0x98: IMMBYTE(EA); EA=X+SIGNED(EA); EAD=RM16(m68_state, EAD); break;
+ case 0x99: IMMWORD(EAP); EA+=X; EAD=RM16(m68_state, EAD); break;
+ case 0x9a: EA=X+SIGNED(F); EAD=RM16(m68_state, EAD); break;
+ case 0x9b: EA=X+D; EAD=RM16(m68_state, EAD); break;
+ case 0x9c: IMMBYTE(EA); EA=PC+SIGNED(EA); EAD=RM16(m68_state, EAD); break;
+ case 0x9d: IMMWORD(EAP); EA+=PC; EAD=RM16(m68_state, EAD); break;
+ case 0x9e: EA=X+W; EAD=RM16(m68_state, EAD); break;
+ case 0x9f: IMMWORD(EAP); EAD=RM16(m68_state, EAD); break;
+
+ case 0xa0: EA=Y; Y++; break;
+ case 0xa1: EA=Y; Y+=2; break;
+ case 0xa2: Y--; EA=Y; break;
+ case 0xa3: Y-=2; EA=Y; break;
+ case 0xa4: EA=Y; break;
+ case 0xa5: EA=Y+SIGNED(B); break;
+ case 0xa6: EA=Y+SIGNED(A); break;
+ case 0xa7: EA=Y+SIGNED(E); break;
+ case 0xa8: IMMBYTE(EA); EA=Y+SIGNED(EA); break;
+ case 0xa9: IMMWORD(EAP); EA+=Y; break;
+ case 0xaa: EA=Y+SIGNED(F); break;
+ case 0xab: EA=Y+D; break;
+ case 0xac: IMMBYTE(EA); EA=PC+SIGNED(EA); break;
+ case 0xad: IMMWORD(EAP); EA+=PC; break;
+ case 0xae: EA=Y+W; break;
+ case 0xaf: IMMWORD(EAP); EA+=W; break;
+
+ case 0xb0: IMMWORD(EAP); EA+=W; EAD=RM16(m68_state, EAD); break;
+ case 0xb1: EA=Y; Y+=2; EAD=RM16(m68_state, EAD); break;
+ case 0xb2: IIError(m68_state); break;
+ case 0xb3: Y-=2; EA=Y; EAD=RM16(m68_state, EAD); break;
+ case 0xb4: EA=Y; EAD=RM16(m68_state, EAD); break;
+ case 0xb5: EA=Y+SIGNED(B); EAD=RM16(m68_state, EAD); break;
+ case 0xb6: EA=Y+SIGNED(A); EAD=RM16(m68_state, EAD); break;
+ case 0xb7: EA=Y+SIGNED(E); EAD=RM16(m68_state, EAD); break;
+ case 0xb8: IMMBYTE(EA); EA=Y+SIGNED(EA); EAD=RM16(m68_state, EAD); break;
+ case 0xb9: IMMWORD(EAP); EA+=Y; EAD=RM16(m68_state, EAD); break;
+ case 0xba: EA=Y+SIGNED(F); EAD=RM16(m68_state, EAD); break;
+ case 0xbb: EA=Y+D; EAD=RM16(m68_state, EAD); break;
+ case 0xbc: IMMBYTE(EA); EA=PC+SIGNED(EA); EAD=RM16(m68_state, EAD); break;
+ case 0xbd: IMMWORD(EAP); EA+=PC; EAD=RM16(m68_state, EAD); break;
+ case 0xbe: EA=Y+W; EAD=RM16(m68_state, EAD); break;
+ case 0xbf: IIError(m68_state); break;
+
+ case 0xc0: EA=U; U++; break;
+ case 0xc1: EA=U; U+=2; break;
+ case 0xc2: U--; EA=U; break;
+ case 0xc3: U-=2; EA=U; break;
+ case 0xc4: EA=U; break;
+ case 0xc5: EA=U+SIGNED(B); break;
+ case 0xc6: EA=U+SIGNED(A); break;
+ case 0xc7: EA=U+SIGNED(E); break;
+ case 0xc8: IMMBYTE(EA); EA=U+SIGNED(EA); break;
+ case 0xc9: IMMWORD(EAP); EA+=U; break;
+ case 0xca: EA=U+SIGNED(F); break;
+ case 0xcb: EA=U+D; break;
+ case 0xcc: IMMBYTE(EA); EA=PC+SIGNED(EA); break;
+ case 0xcd: IMMWORD(EAP); EA+=PC; break;
+ case 0xce: EA=U+W; break;
+ case 0xcf: EA=W; W+=2; break;
+
+ case 0xd0: EA=W; W+=2; EAD=RM16(m68_state, EAD); break;
+ case 0xd1: EA=U; U+=2; EAD=RM16(m68_state, EAD); break;
+ case 0xd2: IIError(m68_state); break;
+ case 0xd3: U-=2; EA=U; EAD=RM16(m68_state, EAD); break;
+ case 0xd4: EA=U; EAD=RM16(m68_state, EAD); break;
+ case 0xd5: EA=U+SIGNED(B); EAD=RM16(m68_state, EAD); break;
+ case 0xd6: EA=U+SIGNED(A); EAD=RM16(m68_state, EAD); break;
+ case 0xd7: EA=U+SIGNED(E); EAD=RM16(m68_state, EAD); break;
+ case 0xd8: IMMBYTE(EA); EA=U+SIGNED(EA); EAD=RM16(m68_state, EAD); break;
+ case 0xd9: IMMWORD(EAP); EA+=U; EAD=RM16(m68_state, EAD); break;
+ case 0xda: EA=U+SIGNED(F); EAD=RM16(m68_state, EAD); break;
+ case 0xdb: EA=U+D; EAD=RM16(m68_state, EAD); break;
+ case 0xdc: IMMBYTE(EA); EA=PC+SIGNED(EA); EAD=RM16(m68_state, EAD); break;
+ case 0xdd: IMMWORD(EAP); EA+=PC; EAD=RM16(m68_state, EAD); break;
+ case 0xde: EA=U+W; EAD=RM16(m68_state, EAD); break;
+ case 0xdf: IIError(m68_state); break;
+
+ case 0xe0: EA=S; S++; break;
+ case 0xe1: EA=S; S+=2; break;
+ case 0xe2: S--; EA=S; break;
+ case 0xe3: S-=2; EA=S; break;
+ case 0xe4: EA=S; break;
+ case 0xe5: EA=S+SIGNED(B); break;
+ case 0xe6: EA=S+SIGNED(A); break;
+ case 0xe7: EA=S+SIGNED(E); break;
+ case 0xe8: IMMBYTE(EA); EA=S+SIGNED(EA); break;
+ case 0xe9: IMMWORD(EAP); EA+=S; break;
+ case 0xea: EA=S+SIGNED(F); break;
+ case 0xeb: EA=S+D; break;
+ case 0xec: IMMBYTE(EA); EA=PC+SIGNED(EA); break;
+ case 0xed: IMMWORD(EAP); EA+=PC; break;
+ case 0xee: EA=S+W; break;
+ case 0xef: W-=2; EA=W; break;
+
+ case 0xf0: W-=2; EA=W; EAD=RM16(m68_state, EAD); break;
+ case 0xf1: EA=S; S+=2; EAD=RM16(m68_state, EAD); break;
+ case 0xf2: IIError(m68_state); break;
+ case 0xf3: S-=2; EA=S; EAD=RM16(m68_state, EAD); break;
+ case 0xf4: EA=S; EAD=RM16(m68_state, EAD); break;
+ case 0xf5: EA=S+SIGNED(B); EAD=RM16(m68_state, EAD); break;
+ case 0xf6: EA=S+SIGNED(A); EAD=RM16(m68_state, EAD); break;
+ case 0xf7: EA=S+SIGNED(E); EAD=RM16(m68_state, EAD); break;
+ case 0xf8: IMMBYTE(EA); EA=S+SIGNED(EA); EAD=RM16(m68_state, EAD); break;
+ case 0xf9: IMMWORD(EAP); EA+=S; EAD=RM16(m68_state, EAD); break;
+ case 0xfa: EA=S+SIGNED(F); EAD=RM16(m68_state, EAD); break;
+ case 0xfb: EA=S+D; EAD=RM16(m68_state, EAD); break;
+ case 0xfc: IMMBYTE(EA); EA=PC+SIGNED(EA); EAD=RM16(m68_state, EAD); break;
+ case 0xfd: IMMWORD(EAP); EA+=PC; EAD=RM16(m68_state, EAD); break;
+ case 0xfe: EA=S+W; EAD=RM16(m68_state, EAD); break;
+ case 0xff: IIError(m68_state); break;
+ }
+
+ m68_state->icount -= m68_state->index_cycle[postbyte];
+}
+
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( hd6309 )
+{
+ m68_state_t *m68_state = get_safe_token(device);
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + HD6309_IRQ_LINE: set_irq_line(m68_state, HD6309_IRQ_LINE, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + HD6309_FIRQ_LINE:set_irq_line(m68_state, HD6309_FIRQ_LINE, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: set_irq_line(m68_state, INPUT_LINE_NMI, info->i); break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + HD6309_PC: PC = info->i; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + HD6309_S: S = info->i; break;
+ case CPUINFO_INT_REGISTER + HD6309_CC: CC = info->i; check_irq_lines(m68_state); break;
+ case CPUINFO_INT_REGISTER + HD6309_MD: MD = info->i; UpdateState(m68_state); break;
+ case CPUINFO_INT_REGISTER + HD6309_U: U = info->i; break;
+ case CPUINFO_INT_REGISTER + HD6309_A: A = info->i; break;
+ case CPUINFO_INT_REGISTER + HD6309_B: B = info->i; break;
+ case CPUINFO_INT_REGISTER + HD6309_E: E = info->i; break;
+ case CPUINFO_INT_REGISTER + HD6309_F: F = info->i; break;
+ case CPUINFO_INT_REGISTER + HD6309_X: X = info->i; break;
+ case CPUINFO_INT_REGISTER + HD6309_Y: Y = info->i; break;
+ case CPUINFO_INT_REGISTER + HD6309_V: V = info->i; break;
+ case CPUINFO_INT_REGISTER + HD6309_DP: DP = info->i; break;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+CPU_GET_INFO( hd6309 )
+{
+ m68_state_t *m68_state = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(m68_state_t); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 2; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 4; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 5; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 20; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_INPUT_STATE + HD6309_IRQ_LINE: info->i = m68_state->irq_state[HD6309_IRQ_LINE]; break;
+ case CPUINFO_INT_INPUT_STATE + HD6309_FIRQ_LINE:info->i = m68_state->irq_state[HD6309_FIRQ_LINE]; break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: info->i = m68_state->nmi_state; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = PPC; break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + HD6309_PC: info->i = PC; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + HD6309_S: info->i = S; break;
+ case CPUINFO_INT_REGISTER + HD6309_CC: info->i = CC; break;
+ case CPUINFO_INT_REGISTER + HD6309_MD: info->i = MD; break;
+ case CPUINFO_INT_REGISTER + HD6309_U: info->i = U; break;
+ case CPUINFO_INT_REGISTER + HD6309_A: info->i = A; break;
+ case CPUINFO_INT_REGISTER + HD6309_B: info->i = B; break;
+ case CPUINFO_INT_REGISTER + HD6309_E: info->i = E; break;
+ case CPUINFO_INT_REGISTER + HD6309_F: info->i = F; break;
+ case CPUINFO_INT_REGISTER + HD6309_X: info->i = X; break;
+ case CPUINFO_INT_REGISTER + HD6309_Y: info->i = Y; break;
+ case CPUINFO_INT_REGISTER + HD6309_V: info->i = V; break;
+ case CPUINFO_INT_REGISTER + HD6309_DP: info->i = DP; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(hd6309); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(hd6309); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(hd6309); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(hd6309); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(hd6309); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(hd6309); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &m68_state->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "HD6309"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Hitachi 6309"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.01"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright John Butler and Tim Lindner"); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c%c%c%c%c%c%c (MD:%c%c%c%c)",
+ m68_state->cc & 0x80 ? 'E':'.',
+ m68_state->cc & 0x40 ? 'F':'.',
+ m68_state->cc & 0x20 ? 'H':'.',
+ m68_state->cc & 0x10 ? 'I':'.',
+ m68_state->cc & 0x08 ? 'N':'.',
+ m68_state->cc & 0x04 ? 'Z':'.',
+ m68_state->cc & 0x02 ? 'V':'.',
+ m68_state->cc & 0x01 ? 'C':'.',
+
+ m68_state->md & 0x80 ? 'E':'e',
+ m68_state->md & 0x40 ? 'F':'f',
+ m68_state->md & 0x02 ? 'I':'i',
+ m68_state->md & 0x01 ? 'Z':'z');
+ break;
+
+ case CPUINFO_STR_REGISTER + HD6309_PC: sprintf(info->s, "PC:%04X", m68_state->pc.w.l); break;
+ case CPUINFO_STR_REGISTER + HD6309_S: sprintf(info->s, "S:%04X", m68_state->s.w.l); break;
+ case CPUINFO_STR_REGISTER + HD6309_CC: sprintf(info->s, "CC:%02X", m68_state->cc); break;
+ case CPUINFO_STR_REGISTER + HD6309_MD: sprintf(info->s, "MD:%02X", m68_state->md); break;
+ case CPUINFO_STR_REGISTER + HD6309_U: sprintf(info->s, "U:%04X", m68_state->u.w.l); break;
+ case CPUINFO_STR_REGISTER + HD6309_A: sprintf(info->s, "A:%02X", m68_state->d.b.h); break;
+ case CPUINFO_STR_REGISTER + HD6309_B: sprintf(info->s, "B:%02X", m68_state->d.b.l); break;
+ case CPUINFO_STR_REGISTER + HD6309_E: sprintf(info->s, "E:%02X", m68_state->w.b.h); break;
+ case CPUINFO_STR_REGISTER + HD6309_F: sprintf(info->s, "F:%02X", m68_state->w.b.l); break;
+ case CPUINFO_STR_REGISTER + HD6309_X: sprintf(info->s, "X:%04X", m68_state->x.w.l); break;
+ case CPUINFO_STR_REGISTER + HD6309_Y: sprintf(info->s, "Y:%04X", m68_state->y.w.l); break;
+ case CPUINFO_STR_REGISTER + HD6309_V: sprintf(info->s, "V:%04X", m68_state->v.w.l); break;
+ case CPUINFO_STR_REGISTER + HD6309_DP: sprintf(info->s, "DP:%02X", m68_state->dp.b.h); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(HD6309, hd6309);
diff --git a/trunk/src/emu/cpu/hd6309/hd6309.h b/trunk/src/emu/cpu/hd6309/hd6309.h
new file mode 100644
index 00000000000..8fceaaccdae
--- /dev/null
+++ b/trunk/src/emu/cpu/hd6309/hd6309.h
@@ -0,0 +1,25 @@
+/*** hd6309: Portable 6309 emulator ******************************************/
+
+#pragma once
+
+#ifndef __HD6309_H__
+#define __HD6309_H__
+
+
+enum
+{
+ HD6309_PC=1, HD6309_S, HD6309_CC ,HD6309_A, HD6309_B, HD6309_U, HD6309_X, HD6309_Y, HD6309_DP,
+ HD6309_E, HD6309_F, HD6309_V, HD6309_MD
+};
+
+#define HD6309_IRQ_LINE 0 /* IRQ line number */
+#define HD6309_FIRQ_LINE 1 /* FIRQ line number */
+
+
+/* PUBLIC FUNCTIONS */
+DECLARE_LEGACY_CPU_DEVICE(HD6309, hd6309);
+
+
+CPU_DISASSEMBLE( hd6309 );
+
+#endif /* __HD6309_H__ */
diff --git a/trunk/src/emu/cpu/i386/cycles.h b/trunk/src/emu/cpu/i386/cycles.h
new file mode 100644
index 00000000000..f459cbb9f20
--- /dev/null
+++ b/trunk/src/emu/cpu/i386/cycles.h
@@ -0,0 +1,674 @@
+#pragma once
+
+#ifndef __CYCLES_H__
+#define __CYCLES_H__
+
+typedef enum
+{
+ CYCLES_MOV_REG_REG,
+ CYCLES_MOV_REG_MEM,
+ CYCLES_MOV_MEM_REG,
+ CYCLES_MOV_IMM_REG,
+ CYCLES_MOV_IMM_MEM,
+ CYCLES_MOV_ACC_MEM,
+ CYCLES_MOV_MEM_ACC,
+ CYCLES_MOV_REG_SREG,
+ CYCLES_MOV_MEM_SREG,
+ CYCLES_MOV_SREG_REG,
+ CYCLES_MOV_SREG_MEM,
+ CYCLES_MOVSX_REG_REG,
+ CYCLES_MOVSX_MEM_REG,
+ CYCLES_MOVZX_REG_REG,
+ CYCLES_MOVZX_MEM_REG,
+ CYCLES_PUSH_RM,
+ CYCLES_PUSH_REG_SHORT,
+ CYCLES_PUSH_SREG,
+ CYCLES_PUSH_IMM,
+ CYCLES_PUSHA,
+ CYCLES_POP_RM,
+ CYCLES_POP_REG_SHORT,
+ CYCLES_POP_SREG,
+ CYCLES_POPA,
+ CYCLES_XCHG_REG_REG,
+ CYCLES_XCHG_REG_MEM,
+ CYCLES_IN,
+ CYCLES_IN_VAR,
+ CYCLES_OUT,
+ CYCLES_OUT_VAR,
+ CYCLES_LEA,
+ CYCLES_LDS,
+ CYCLES_LES,
+ CYCLES_LFS,
+ CYCLES_LGS,
+ CYCLES_LSS,
+ CYCLES_CLC,
+ CYCLES_CLD,
+ CYCLES_CLI,
+ CYCLES_CLTS,
+ CYCLES_CMC,
+ CYCLES_LAHF,
+ CYCLES_POPF,
+ CYCLES_PUSHF,
+ CYCLES_SAHF,
+ CYCLES_STC,
+ CYCLES_STD,
+ CYCLES_STI,
+ CYCLES_ALU_REG_REG,
+ CYCLES_ALU_REG_MEM,
+ CYCLES_ALU_MEM_REG,
+ CYCLES_ALU_IMM_REG,
+ CYCLES_ALU_IMM_MEM,
+ CYCLES_ALU_IMM_ACC,
+ CYCLES_INC_REG,
+ CYCLES_INC_MEM,
+ CYCLES_DEC_REG,
+ CYCLES_DEC_MEM,
+ CYCLES_CMP_REG_REG,
+ CYCLES_CMP_REG_MEM,
+ CYCLES_CMP_MEM_REG,
+ CYCLES_CMP_IMM_REG,
+ CYCLES_CMP_IMM_MEM,
+ CYCLES_CMP_IMM_ACC,
+ CYCLES_TEST_REG_REG,
+ CYCLES_TEST_REG_MEM,
+ CYCLES_TEST_IMM_REG,
+ CYCLES_TEST_IMM_MEM,
+ CYCLES_TEST_IMM_ACC,
+ CYCLES_NEG_REG,
+ CYCLES_NEG_MEM,
+ CYCLES_AAA,
+ CYCLES_AAS,
+ CYCLES_DAA,
+ CYCLES_DAS,
+ CYCLES_MUL8_ACC_REG,
+ CYCLES_MUL8_ACC_MEM,
+ CYCLES_MUL16_ACC_REG,
+ CYCLES_MUL16_ACC_MEM,
+ CYCLES_MUL32_ACC_REG,
+ CYCLES_MUL32_ACC_MEM,
+ CYCLES_IMUL8_ACC_REG,
+ CYCLES_IMUL8_ACC_MEM,
+ CYCLES_IMUL16_ACC_REG,
+ CYCLES_IMUL16_ACC_MEM,
+ CYCLES_IMUL32_ACC_REG,
+ CYCLES_IMUL32_ACC_MEM,
+ CYCLES_IMUL8_REG_REG,
+ CYCLES_IMUL8_REG_MEM,
+ CYCLES_IMUL16_REG_REG,
+ CYCLES_IMUL16_REG_MEM,
+ CYCLES_IMUL32_REG_REG,
+ CYCLES_IMUL32_REG_MEM,
+ CYCLES_IMUL16_REG_IMM_REG,
+ CYCLES_IMUL16_MEM_IMM_REG,
+ CYCLES_IMUL32_REG_IMM_REG,
+ CYCLES_IMUL32_MEM_IMM_REG,
+ CYCLES_DIV8_ACC_REG,
+ CYCLES_DIV8_ACC_MEM,
+ CYCLES_DIV16_ACC_REG,
+ CYCLES_DIV16_ACC_MEM,
+ CYCLES_DIV32_ACC_REG,
+ CYCLES_DIV32_ACC_MEM,
+ CYCLES_IDIV8_ACC_REG,
+ CYCLES_IDIV8_ACC_MEM,
+ CYCLES_IDIV16_ACC_REG,
+ CYCLES_IDIV16_ACC_MEM,
+ CYCLES_IDIV32_ACC_REG,
+ CYCLES_IDIV32_ACC_MEM,
+ CYCLES_AAD,
+ CYCLES_AAM,
+ CYCLES_CBW,
+ CYCLES_CWD,
+ CYCLES_ROTATE_REG,
+ CYCLES_ROTATE_MEM,
+ CYCLES_ROTATE_CARRY_REG,
+ CYCLES_ROTATE_CARRY_MEM,
+ CYCLES_SHLD_REG,
+ CYCLES_SHLD_MEM,
+ CYCLES_SHRD_REG,
+ CYCLES_SHRD_MEM,
+ CYCLES_NOT_REG,
+ CYCLES_NOT_MEM,
+ CYCLES_CMPS,
+ CYCLES_INS,
+ CYCLES_LODS,
+ CYCLES_MOVS,
+ CYCLES_OUTS,
+ CYCLES_SCAS,
+ CYCLES_STOS,
+ CYCLES_XLAT,
+ CYCLES_REP_CMPS_BASE,
+ CYCLES_REP_INS_BASE,
+ CYCLES_REP_LODS_BASE,
+ CYCLES_REP_MOVS_BASE,
+ CYCLES_REP_OUTS_BASE,
+ CYCLES_REP_SCAS_BASE,
+ CYCLES_REP_STOS_BASE,
+ CYCLES_REP_CMPS,
+ CYCLES_REP_INS,
+ CYCLES_REP_LODS,
+ CYCLES_REP_MOVS,
+ CYCLES_REP_OUTS,
+ CYCLES_REP_SCAS,
+ CYCLES_REP_STOS,
+ CYCLES_BSF_BASE,
+ CYCLES_BSF,
+ CYCLES_BSR_BASE,
+ CYCLES_BSR,
+ CYCLES_BT_IMM_REG,
+ CYCLES_BT_IMM_MEM,
+ CYCLES_BT_REG_REG,
+ CYCLES_BT_REG_MEM,
+ CYCLES_BTC_IMM_REG,
+ CYCLES_BTC_IMM_MEM,
+ CYCLES_BTC_REG_REG,
+ CYCLES_BTC_REG_MEM,
+ CYCLES_BTR_IMM_REG,
+ CYCLES_BTR_IMM_MEM,
+ CYCLES_BTR_REG_REG,
+ CYCLES_BTR_REG_MEM,
+ CYCLES_BTS_IMM_REG,
+ CYCLES_BTS_IMM_MEM,
+ CYCLES_BTS_REG_REG,
+ CYCLES_BTS_REG_MEM,
+ CYCLES_CALL, // E8
+ CYCLES_CALL_REG, // FF /2
+ CYCLES_CALL_MEM, // FF /2
+ CYCLES_CALL_INTERSEG, // 9A
+ CYCLES_CALL_REG_INTERSEG, // FF /3
+ CYCLES_CALL_MEM_INTERSEG, // FF /3
+ CYCLES_JMP_SHORT, // EB
+ CYCLES_JMP, // E9
+ CYCLES_JMP_REG, // FF /4
+ CYCLES_JMP_MEM, // FF /4
+ CYCLES_JMP_INTERSEG, // EA
+ CYCLES_JMP_REG_INTERSEG, // FF /5
+ CYCLES_JMP_MEM_INTERSEG, // FF /5
+ CYCLES_RET, // C3
+ CYCLES_RET_IMM, // C2
+ CYCLES_RET_INTERSEG, // CB
+ CYCLES_RET_IMM_INTERSEG, // CA
+ CYCLES_JCC_DISP8,
+ CYCLES_JCC_FULL_DISP,
+ CYCLES_JCC_DISP8_NOBRANCH,
+ CYCLES_JCC_FULL_DISP_NOBRANCH,
+ CYCLES_JCXZ,
+ CYCLES_JCXZ_NOBRANCH,
+ CYCLES_LOOP,
+ CYCLES_LOOPZ,
+ CYCLES_LOOPNZ,
+ CYCLES_SETCC_REG,
+ CYCLES_SETCC_MEM,
+ CYCLES_ENTER,
+ CYCLES_LEAVE,
+ CYCLES_INT,
+ CYCLES_INT3,
+ CYCLES_INTO_OF1,
+ CYCLES_INTO_OF0,
+ CYCLES_BOUND_IN_RANGE,
+ CYCLES_BOUND_OUT_RANGE,
+ CYCLES_IRET,
+ CYCLES_HLT,
+ CYCLES_MOV_REG_CR0,
+ CYCLES_MOV_REG_CR2,
+ CYCLES_MOV_REG_CR3,
+ CYCLES_MOV_CR_REG,
+ CYCLES_MOV_REG_DR0_3,
+ CYCLES_MOV_REG_DR6_7,
+ CYCLES_MOV_DR6_7_REG,
+ CYCLES_MOV_DR0_3_REG,
+ CYCLES_MOV_REG_TR6_7,
+ CYCLES_MOV_TR6_7_REG,
+ CYCLES_NOP,
+ CYCLES_WAIT,
+ CYCLES_ARPL_REG,
+ CYCLES_ARPL_MEM,
+ CYCLES_LAR_REG,
+ CYCLES_LAR_MEM,
+ CYCLES_LGDT,
+ CYCLES_LIDT,
+ CYCLES_LLDT_REG,
+ CYCLES_LLDT_MEM,
+ CYCLES_LMSW_REG,
+ CYCLES_LMSW_MEM,
+ CYCLES_LSL_REG,
+ CYCLES_LSL_MEM,
+ CYCLES_LTR_REG,
+ CYCLES_LTR_MEM,
+ CYCLES_SGDT,
+ CYCLES_SIDT,
+ CYCLES_SLDT_REG,
+ CYCLES_SLDT_MEM,
+ CYCLES_SMSW_REG,
+ CYCLES_SMSW_MEM,
+ CYCLES_STR_REG,
+ CYCLES_STR_MEM,
+ CYCLES_VERR_REG,
+ CYCLES_VERR_MEM,
+ CYCLES_VERW_REG,
+ CYCLES_VERW_MEM,
+ CYCLES_LOCK,
+
+ CYCLES_BSWAP,
+ CYCLES_CMPXCHG8B,
+ CYCLES_CMPXCHG,
+ CYCLES_CPUID,
+ CYCLES_CPUID_EAX1,
+ CYCLES_INVD,
+ CYCLES_XADD,
+ CYCLES_RDTSC,
+ CYCLES_RSM,
+ CYCLES_RDMSR,
+
+ CYCLES_FABS,
+ CYCLES_FADD,
+ CYCLES_FBLD,
+ CYCLES_FBSTP,
+ CYCLES_FCHS,
+ CYCLES_FCLEX,
+ CYCLES_FCOM,
+ CYCLES_FCOS,
+ CYCLES_FDECSTP,
+ CYCLES_FDISI,
+ CYCLES_FDIV,
+ CYCLES_FDIVR,
+ CYCLES_FENI,
+ CYCLES_FFREE,
+ CYCLES_FIADD,
+ CYCLES_FICOM,
+ CYCLES_FIDIV,
+ CYCLES_FILD,
+ CYCLES_FIMUL,
+ CYCLES_FINCSTP,
+ CYCLES_FINIT,
+ CYCLES_FIST,
+ CYCLES_FISUB,
+ CYCLES_FLD,
+ CYCLES_FLDZ,
+ CYCLES_FLD1,
+ CYCLES_FLDL2E,
+ CYCLES_FLDL2T,
+ CYCLES_FLDLG2,
+ CYCLES_FLDLN2,
+ CYCLES_FLDPI,
+ CYCLES_FLDCW,
+ CYCLES_FLDENV,
+ CYCLES_FMUL,
+ CYCLES_FNOP,
+ CYCLES_FPATAN,
+ CYCLES_FPREM,
+ CYCLES_FPREM1,
+ CYCLES_FPTAN,
+ CYCLES_FRNDINT,
+ CYCLES_FRSTOR,
+ CYCLES_FSAVE,
+ CYCLES_FSCALE,
+ CYCLES_FSETPM,
+ CYCLES_FSIN,
+ CYCLES_FSINCOS,
+ CYCLES_FSQRT,
+ CYCLES_FST,
+ CYCLES_FSTCW,
+ CYCLES_FSTENV,
+ CYCLES_FSTSW,
+ CYCLES_FSUB,
+ CYCLES_FSUBR,
+ CYCLES_FTST,
+ CYCLES_FUCOM,
+ CYCLES_FXAM,
+ CYCLES_FXCH,
+ CYCLES_FXTRACT,
+ CYCLES_FYL2X,
+ CYCLES_FYL2XPI,
+ CYCLES_CMPXCHG_REG_REG_T,
+ CYCLES_CMPXCHG_REG_REG_F,
+ CYCLES_CMPXCHG_REG_MEM_T,
+ CYCLES_CMPXCHG_REG_MEM_F,
+ CYCLES_XADD_REG_REG,
+ CYCLES_XADD_REG_MEM,
+
+ CYCLES_NUM_OPCODES
+} X86_CYCLES;
+
+
+#define X86_NUM_CPUS 4
+#define CPU_CYCLES_I386 0
+#define CPU_CYCLES_I486 1
+#define CPU_CYCLES_PENTIUM 2
+#define CPU_CYCLES_MEDIAGX 3
+
+
+typedef struct
+{
+ X86_CYCLES op;
+ UINT8 cpu_cycles[X86_NUM_CPUS][2];
+} X86_CYCLE_TABLE;
+
+static const X86_CYCLE_TABLE x86_cycle_table[] =
+{
+ // opcode rm/pmode
+ // i386 i486 pentium mediagx
+ { CYCLES_MOV_REG_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_MOV_REG_MEM, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_MOV_MEM_REG, { { 4, 4 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_MOV_IMM_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_MOV_IMM_MEM, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_MOV_ACC_MEM, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_MOV_MEM_ACC, { { 4, 4 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_MOV_REG_SREG, { { 2, 18 }, { 3, 3 }, { 2, 2 }, { 1, 6 } } },
+ { CYCLES_MOV_MEM_SREG, { { 5, 19 }, { 9, 9 }, { 3, 3 }, { 1, 6 } } },
+ { CYCLES_MOV_SREG_REG, { { 2, 2 }, { 3, 3 }, { 1, 1 }, { 1, 6 } } },
+ { CYCLES_MOV_SREG_MEM, { { 2, 2 }, { 3, 3 }, { 1, 1 }, { 1, 6 } } },
+ { CYCLES_MOVSX_REG_REG, { { 3, 3 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } },
+ { CYCLES_MOVSX_MEM_REG, { { 6, 6 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } },
+ { CYCLES_MOVZX_REG_REG, { { 3, 3 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } },
+ { CYCLES_MOVZX_MEM_REG, { { 6, 6 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } },
+ { CYCLES_PUSH_RM, { { 5, 5 }, { 4, 4 }, { 2, 2 }, { 3, 3 } } },
+ { CYCLES_PUSH_REG_SHORT, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_PUSH_SREG, { { 2, 2 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_PUSH_IMM, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_PUSHA, { { 18, 18 }, { 11, 11 }, { 5, 5 }, { 11, 11 } } },
+ { CYCLES_POP_RM, { { 5, 5 }, { 4, 4 }, { 3, 3 }, { 4, 4 } } },
+ { CYCLES_POP_REG_SHORT, { { 4, 4 }, { 4, 4 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_POP_SREG, { { 7, 21 }, { 3, 3 }, { 3, 3 }, { 1, 6 } } },
+ { CYCLES_POPA, { { 24, 24 }, { 9, 9 }, { 5, 5 }, { 9, 9 } } },
+ { CYCLES_XCHG_REG_REG, { { 3, 3 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } },
+ { CYCLES_XCHG_REG_MEM, { { 5, 5 }, { 5, 5 }, { 3, 3 }, { 1, 1 } } },
+ { CYCLES_IN, { { 12, 26 }, { 14, 27 }, { 7, 19 }, { 8, 8 } } },
+ { CYCLES_IN_VAR, { { 13, 27 }, { 14, 27 }, { 7, 19 }, { 8, 8 } } },
+ { CYCLES_OUT, { { 10, 24 }, { 16, 29 }, { 12, 24 }, { 14, 14 } } },
+ { CYCLES_OUT_VAR, { { 11, 25 }, { 16, 29 }, { 12, 24 }, { 14, 14 } } },
+ { CYCLES_LEA, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_LDS, { { 7, 22 }, { 6, 12 }, { 4, 4 }, { 4, 9 } } },
+ { CYCLES_LES, { { 7, 22 }, { 6, 12 }, { 4, 4 }, { 4, 9 } } },
+ { CYCLES_LFS, { { 7, 22 }, { 6, 12 }, { 4, 4 }, { 4, 9 } } },
+ { CYCLES_LGS, { { 7, 22 }, { 6, 12 }, { 4, 4 }, { 4, 9 } } },
+ { CYCLES_LSS, { { 7, 22 }, { 6, 12 }, { 4, 4 }, { 4, 10 } } },
+ { CYCLES_CLC, { { 2, 2 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } },
+ { CYCLES_CLD, { { 2, 2 }, { 2, 2 }, { 2, 2 }, { 4, 4 } } },
+ { CYCLES_CLI, { { 8, 8 }, { 5, 5 }, { 7, 7 }, { 6, 6 } } },
+ { CYCLES_CLTS, { { 6, 6 }, { 7, 7 }, { 10, 10 }, { 7, 7 } } },
+ { CYCLES_CMC, { { 2, 2 }, { 2, 2 }, { 2, 2 }, { 3, 3 } } },
+ { CYCLES_LAHF, { { 2, 2 }, { 3, 3 }, { 2, 2 }, { 2, 2 } } },
+ { CYCLES_POPF, { { 5, 5 }, { 9, 9 }, { 6, 6 }, { 8, 8 } } },
+ { CYCLES_PUSHF, { { 4, 4 }, { 4, 4 }, { 9, 9 }, { 2, 2 } } },
+ { CYCLES_SAHF, { { 3, 3 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } },
+ { CYCLES_STC, { { 2, 2 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } },
+ { CYCLES_STD, { { 2, 2 }, { 2, 2 }, { 2, 2 }, { 4, 4 } } },
+ { CYCLES_STI, { { 8, 8 }, { 5, 5 }, { 7, 7 }, { 6, 6 } } },
+ { CYCLES_ALU_REG_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_ALU_REG_MEM, { { 7, 7 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } },
+ { CYCLES_ALU_MEM_REG, { { 6, 6 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } },
+ { CYCLES_ALU_IMM_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_ALU_IMM_MEM, { { 7, 7 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } },
+ { CYCLES_ALU_IMM_ACC, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_INC_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_INC_MEM, { { 6, 6 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } },
+ { CYCLES_DEC_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_DEC_MEM, { { 6, 6 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } },
+ { CYCLES_CMP_REG_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_CMP_REG_MEM, { { 5, 5 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } },
+ { CYCLES_CMP_MEM_REG, { { 6, 6 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } },
+ { CYCLES_CMP_IMM_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_CMP_IMM_MEM, { { 5, 5 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } },
+ { CYCLES_CMP_IMM_ACC, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_TEST_REG_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_TEST_REG_MEM, { { 5, 5 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } },
+ { CYCLES_TEST_IMM_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_TEST_IMM_MEM, { { 5, 5 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } },
+ { CYCLES_TEST_IMM_ACC, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_NEG_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_NEG_MEM, { { 6, 6 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } },
+ { CYCLES_AAA, { { 4, 4 }, { 3, 3 }, { 3, 3 }, { 3, 3 } } },
+ { CYCLES_AAS, { { 4, 4 }, { 3, 3 }, { 3, 3 }, { 3, 3 } } },
+ { CYCLES_DAA, { { 4, 4 }, { 2, 2 }, { 3, 3 }, { 2, 2 } } },
+ { CYCLES_DAS, { { 4, 4 }, { 2, 2 }, { 3, 3 }, { 2, 2 } } },
+ { CYCLES_MUL8_ACC_REG, { { 17, 17 }, { 13, 13 }, { 11, 11 }, { 4, 4 } } },
+ { CYCLES_MUL8_ACC_MEM, { { 20, 20 }, { 13, 13 }, { 11, 11 }, { 4, 4 } } },
+ { CYCLES_MUL16_ACC_REG, { { 25, 25 }, { 13, 13 }, { 11, 11 }, { 5, 5 } } },
+ { CYCLES_MUL16_ACC_MEM, { { 28, 28 }, { 13, 13 }, { 11, 11 }, { 5, 5 } } },
+ { CYCLES_MUL32_ACC_REG, { { 41, 41 }, { 13, 13 }, { 10, 10 }, { 15, 15 } } },
+ { CYCLES_MUL32_ACC_MEM, { { 44, 44 }, { 13, 13 }, { 10, 10 }, { 15, 15 } } },
+ { CYCLES_IMUL8_ACC_REG, { { 17, 17 }, { 18, 18 }, { 11, 11 }, { 4, 4 } } },
+ { CYCLES_IMUL8_ACC_MEM, { { 20, 20 }, { 18, 18 }, { 11, 11 }, { 4, 4 } } },
+ { CYCLES_IMUL16_ACC_REG, { { 25, 25 }, { 26, 26 }, { 11, 11 }, { 5, 5 } } },
+ { CYCLES_IMUL16_ACC_MEM, { { 28, 28 }, { 26, 26 }, { 11, 11 }, { 5, 5 } } },
+ { CYCLES_IMUL32_ACC_REG, { { 41, 41 }, { 42, 42 }, { 10, 10 }, { 15, 15 } } },
+ { CYCLES_IMUL32_ACC_MEM, { { 44, 44 }, { 42, 42 }, { 10, 10 }, { 15, 15 } } },
+ { CYCLES_IMUL8_REG_REG, { { 17, 17 }, { 13, 13 }, { 10, 10 }, { 4, 4 } } },
+ { CYCLES_IMUL8_REG_MEM, { { 20, 20 }, { 13, 13 }, { 10, 10 }, { 4, 4 } } },
+ { CYCLES_IMUL16_REG_REG, { { 25, 25 }, { 13, 13 }, { 10, 10 }, { 5, 5 } } },
+ { CYCLES_IMUL16_REG_MEM, { { 28, 28 }, { 13, 13 }, { 10, 10 }, { 5, 5 } } },
+ { CYCLES_IMUL32_REG_REG, { { 41, 41 }, { 13, 13 }, { 10, 10 }, { 15, 15 } } },
+ { CYCLES_IMUL32_REG_MEM, { { 44, 44 }, { 13, 13 }, { 10, 10 }, { 15, 15 } } },
+ { CYCLES_IMUL16_REG_IMM_REG,{ { 26, 26 }, { 26, 26 }, { 10, 10 }, { 6, 6 } } },
+ { CYCLES_IMUL16_MEM_IMM_REG,{ { 27, 27 }, { 26, 26 }, { 10, 10 }, { 6, 6 } } },
+ { CYCLES_IMUL32_REG_IMM_REG,{ { 42, 42 }, { 42, 42 }, { 10, 10 }, { 16, 16 } } },
+ { CYCLES_IMUL32_MEM_IMM_REG,{ { 43, 43 }, { 42, 42 }, { 10, 10 }, { 16, 16 } } },
+ { CYCLES_DIV8_ACC_REG, { { 14, 14 }, { 16, 16 }, { 17, 17 }, { 20, 20 } } },
+ { CYCLES_DIV8_ACC_MEM, { { 17, 17 }, { 16, 16 }, { 17, 17 }, { 20, 20 } } },
+ { CYCLES_DIV16_ACC_REG, { { 22, 22 }, { 24, 24 }, { 25, 25 }, { 29, 29 } } },
+ { CYCLES_DIV16_ACC_MEM, { { 25, 25 }, { 24, 24 }, { 25, 25 }, { 29, 29 } } },
+ { CYCLES_DIV32_ACC_REG, { { 38, 38 }, { 40, 40 }, { 41, 41 }, { 45, 45 } } },
+ { CYCLES_DIV32_ACC_MEM, { { 41, 41 }, { 40, 40 }, { 41, 41 }, { 45, 45 } } },
+ { CYCLES_IDIV8_ACC_REG, { { 19, 19 }, { 19, 19 }, { 22, 22 }, { 20, 20 } } },
+ { CYCLES_IDIV8_ACC_MEM, { { 22, 22 }, { 20, 20 }, { 22, 22 }, { 20, 20 } } },
+ { CYCLES_IDIV16_ACC_REG, { { 27, 27 }, { 27, 27 }, { 30, 30 }, { 29, 29 } } },
+ { CYCLES_IDIV16_ACC_MEM, { { 30, 30 }, { 28, 28 }, { 30, 30 }, { 29, 29 } } },
+ { CYCLES_IDIV32_ACC_REG, { { 43, 43 }, { 43, 43 }, { 46, 46 }, { 45, 45 } } },
+ { CYCLES_IDIV32_ACC_MEM, { { 46, 46 }, { 44, 44 }, { 46, 46 }, { 45, 45 } } },
+ { CYCLES_AAD, { { 19, 19 }, { 14, 14 }, { 10, 10 }, { 7, 7 } } },
+ { CYCLES_AAM, { { 17, 17 }, { 15, 15 }, { 18, 18 }, { 19, 19 } } },
+ { CYCLES_CBW, { { 3, 3 }, { 3, 3 }, { 3, 3 }, { 3, 3 } } },
+ { CYCLES_CWD, { { 2, 2 }, { 3, 3 }, { 2, 2 }, { 2, 2 } } },
+ { CYCLES_ROTATE_REG, { { 3, 3 }, { 3, 3 }, { 1, 1 }, { 2, 2 } } },
+ { CYCLES_ROTATE_MEM, { { 7, 7 }, { 4, 4 }, { 3, 3 }, { 2, 2 } } },
+ { CYCLES_ROTATE_CARRY_REG, { { 9, 9 }, { 8, 8 }, { 7, 7 }, { 8, 8 } } },
+ { CYCLES_ROTATE_CARRY_MEM, { { 10, 10 }, { 9, 9 }, { 8, 8 }, { 8, 8 } } },
+ { CYCLES_SHLD_REG, { { 3, 3 }, { 2, 2 }, { 4, 4 }, { 3, 3 } } },
+ { CYCLES_SHLD_MEM, { { 7, 7 }, { 3, 3 }, { 4, 4 }, { 6, 6 } } },
+ { CYCLES_SHRD_REG, { { 3, 3 }, { 2, 2 }, { 4, 4 }, { 3, 3 } } },
+ { CYCLES_SHRD_MEM, { { 7, 7 }, { 3, 3 }, { 4, 4 }, { 6, 6 } } },
+ { CYCLES_NOT_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_NOT_MEM, { { 6, 6 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } },
+ { CYCLES_CMPS, { { 10, 10 }, { 8, 8 }, { 5, 5 }, { 6, 6 } } },
+ { CYCLES_INS, { { 15, 29 }, { 17, 30 }, { 9, 22 }, { 11, 11 } } },
+ { CYCLES_LODS, { { 5, 5 }, { 5, 5 }, { 2, 2 }, { 3, 3 } } },
+ { CYCLES_MOVS, { { 8, 8 }, { 7, 7 }, { 4, 4 }, { 6, 6 } } },
+ { CYCLES_OUTS, { { 14, 28 }, { 17, 30 }, { 13, 25 }, { 15, 15 } } },
+ { CYCLES_SCAS, { { 8, 8 }, { 6, 6 }, { 4, 4 }, { 2, 2 } } },
+ { CYCLES_STOS, { { 5, 5 }, { 5, 5 }, { 3, 3 }, { 2, 2 } } },
+ { CYCLES_XLAT, { { 5, 5 }, { 4, 4 }, { 4, 4 }, { 5, 5 } } },
+ { CYCLES_REP_CMPS_BASE, { { 5, 5 }, { 0, 0 }, { 0, 0 }, { 11, 11 } } },
+ { CYCLES_REP_INS_BASE, { { 14, 8 }, { 0, 0 }, { 0, 0 }, { 17, 17 } } },
+ { CYCLES_REP_LODS_BASE, { { 5, 5 }, { 0, 0 }, { 0, 0 }, { 9, 9 } } },
+ { CYCLES_REP_MOVS_BASE, { { 8, 8 }, { 0, 0 }, { 0, 0 }, { 12, 12 } } },
+ { CYCLES_REP_OUTS_BASE, { { 12, 6 }, { 0, 0 }, { 0, 0 }, { 24, 24 } } },
+ { CYCLES_REP_SCAS_BASE, { { 5, 5 }, { 0, 0 }, { 0, 0 }, { 9, 9 } } },
+ { CYCLES_REP_STOS_BASE, { { 5, 5 }, { 0, 0 }, { 0, 0 }, { 9, 9 } } },
+ { CYCLES_REP_CMPS, { { 5, 5 }, { 8, 8 }, { 5, 5 }, { 4, 4 } } },
+ { CYCLES_REP_INS, { { 14, 8 }, { 17, 30 }, { 9, 22 }, { 4, 4 } } },
+ { CYCLES_REP_LODS, { { 5, 5 }, { 5, 5 }, { 2, 2 }, { 2, 2 } } },
+ { CYCLES_REP_MOVS, { { 8, 8 }, { 7, 7 }, { 4, 4 }, { 2, 2 } } },
+ { CYCLES_REP_OUTS, { { 12, 6 }, { 17, 30 }, { 13, 25 }, { 4, 4 } } },
+ { CYCLES_REP_SCAS, { { 5, 5 }, { 6, 6 }, { 4, 4 }, { 3, 3 } } },
+ { CYCLES_REP_STOS, { { 5, 5 }, { 5, 5 }, { 3, 3 }, { 2, 2 } } },
+ { CYCLES_BSF_BASE, { { 11, 11 }, { 6, 6 }, { 6, 6 }, { 4, 4 } } },
+ { CYCLES_BSF, { { 3, 3 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_BSR_BASE, { { 9, 9 }, { 6, 6 }, { 7, 7 }, { 4, 4 } } },
+ { CYCLES_BSR, { { 3, 3 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_BT_IMM_REG, { { 3, 3 }, { 3, 3 }, { 4, 4 }, { 1, 1 } } },
+ { CYCLES_BT_IMM_MEM, { { 6, 6 }, { 6, 6 }, { 4, 4 }, { 1, 1 } } },
+ { CYCLES_BT_REG_REG, { { 3, 3 }, { 3, 3 }, { 4, 4 }, { 1, 1 } } },
+ { CYCLES_BT_REG_MEM, { { 12, 12 }, { 12, 12 }, { 9, 9 }, { 7, 7 } } },
+ { CYCLES_BTC_IMM_REG, { { 6, 6 }, { 6, 6 }, { 7, 7 }, { 2, 2 } } },
+ { CYCLES_BTC_IMM_MEM, { { 8, 8 }, { 8, 8 }, { 8, 8 }, { 2, 2 } } },
+ { CYCLES_BTC_REG_REG, { { 6, 6 }, { 6, 6 }, { 7, 7 }, { 2, 2 } } },
+ { CYCLES_BTC_REG_MEM, { { 13, 13 }, { 13, 13 }, { 13, 13 }, { 8, 8 } } },
+ { CYCLES_BTR_IMM_REG, { { 6, 6 }, { 6, 6 }, { 7, 7 }, { 2, 2 } } },
+ { CYCLES_BTR_IMM_MEM, { { 8, 8 }, { 8, 8 }, { 8, 8 }, { 2, 2 } } },
+ { CYCLES_BTR_REG_REG, { { 6, 6 }, { 6, 6 }, { 7, 7 }, { 2, 2 } } },
+ { CYCLES_BTR_REG_MEM, { { 13, 13 }, { 13, 13 }, { 13, 13 }, { 8, 8 } } },
+ { CYCLES_BTS_IMM_REG, { { 6, 6 }, { 6, 6 }, { 7, 7 }, { 2, 2 } } },
+ { CYCLES_BTS_IMM_MEM, { { 8, 8 }, { 8, 8 }, { 8, 8 }, { 2, 2 } } },
+ { CYCLES_BTS_REG_REG, { { 6, 6 }, { 6, 6 }, { 7, 7 }, { 2, 2 } } },
+ { CYCLES_BTS_REG_MEM, { { 13, 13 }, { 13, 13 }, { 13, 13 }, { 8, 8 } } },
+ { CYCLES_CALL, { { 7, 7 }, { 3, 3 }, { 1, 1 }, { 3, 3 } } },
+ { CYCLES_CALL_REG, { { 7, 7 }, { 5, 5 }, { 2, 2 }, { 3, 3 } } },
+ { CYCLES_CALL_MEM, { { 10, 10 }, { 5, 5 }, { 2, 2 }, { 4, 4 } } },
+ { CYCLES_CALL_INTERSEG, { { 17, 34 }, { 18, 20 }, { 4, 13 }, { 9, 14 } } },
+ { CYCLES_CALL_REG_INTERSEG, { { 22, 38 }, { 17, 20 }, { 4, 14 }, { 11, 15 } } },
+ { CYCLES_CALL_MEM_INTERSEG, { { 22, 38 }, { 17, 20 }, { 4, 14 }, { 11, 15 } } },
+ { CYCLES_JMP_SHORT, { { 7, 7 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_JMP, { { 7, 7 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_JMP_REG, { { 7, 7 }, { 5, 5 }, { 2, 2 }, { 1, 1 } } },
+ { CYCLES_JMP_MEM, { { 10, 10 }, { 5, 5 }, { 2, 2 }, { 3, 3 } } },
+ { CYCLES_JMP_INTERSEG, { { 12, 27 }, { 17, 19 }, { 3, 3 }, { 8, 12 } } },
+ { CYCLES_JMP_REG_INTERSEG, { { 17, 31 }, { 13, 18 }, { 4, 4 }, { 10, 10 } } },
+ { CYCLES_JMP_MEM_INTERSEG, { { 17, 31 }, { 13, 18 }, { 4, 4 }, { 10, 13 } } },
+ { CYCLES_RET, { { 10, 10 }, { 5, 5 }, { 2, 2 }, { 3, 3 } } },
+ { CYCLES_RET_IMM, { { 10, 10 }, { 5, 5 }, { 2, 2 }, { 3, 3 } } },
+ { CYCLES_RET_INTERSEG, { { 18, 32 }, { 13, 13 }, { 4, 4 }, { 10, 13 } } },
+ { CYCLES_RET_IMM_INTERSEG, { { 18, 32 }, { 14, 14 }, { 4, 4 }, { 10, 13 } } },
+ { CYCLES_JCC_DISP8, { { 7, 7 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_JCC_FULL_DISP, { { 7, 7 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_JCC_DISP8_NOBRANCH,{ { 3, 3 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_JCC_FULL_DISP_NOBRANCH,{ { 3, 3 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_JCXZ, { { 9, 9 }, { 1, 1 }, { 1, 1 }, { 2, 2 } } },
+ { CYCLES_JCXZ_NOBRANCH, { { 5, 5 }, { 1, 1 }, { 1, 1 }, { 2, 2 } } },
+ { CYCLES_LOOP, { { 11, 11 }, { 6, 6 }, { 5, 5 }, { 2, 2 } } },
+ { CYCLES_LOOPZ, { { 11, 11 }, { 9, 9 }, { 8, 8 }, { 2, 2 } } },
+ { CYCLES_LOOPNZ, { { 11, 11 }, { 9, 9 }, { 8, 8 }, { 2, 2 } } },
+ { CYCLES_SETCC_REG, { { 4, 4 }, { 3, 3 }, { 2, 2 }, { 1, 1 } } },
+ { CYCLES_SETCC_MEM, { { 5, 5 }, { 4, 4 }, { 2, 2 }, { 1, 1 } } },
+ { CYCLES_ENTER, { { 10, 10 }, { 14, 14 }, { 11, 11 }, { 13, 13 } } },
+ { CYCLES_LEAVE, { { 4, 4 }, { 5, 5 }, { 3, 3 }, { 1, 1 } } },
+ { CYCLES_INT, { { 37, 37 }, { 30, 30 }, { 16, 16 }, { 19, 19 } } },
+ { CYCLES_INT3, { { 33, 33 }, { 26, 26 }, { 13, 13 }, { 19, 19 } } },
+ { CYCLES_INTO_OF1, { { 35, 35 }, { 28, 28 }, { 13, 13 }, { 19, 19 } } },
+ { CYCLES_INTO_OF0, { { 3, 3 }, { 3, 3 }, { 4, 4 }, { 4, 4 } } },
+ { CYCLES_BOUND_IN_RANGE, { { 10, 10 }, { 7, 7 }, { 8, 8 }, { 7, 7 } } },
+ { CYCLES_BOUND_OUT_RANGE, { { 44, 44 }, { 7, 7 }, { 8, 8 }, { 8, 8 } } },
+ { CYCLES_IRET, { { 22, 22 }, { 15, 15 }, { 8, 8 }, { 13, 13 } } },
+ { CYCLES_HLT, { { 5, 5 }, { 4, 4 }, { 4, 4 }, { 10, 10 } } },
+ { CYCLES_MOV_REG_CR0, { { 11, 11 }, { 16, 16 }, { 16, 16 }, { 20, 18 } } },
+ { CYCLES_MOV_REG_CR2, { { 4, 4 }, { 4, 4 }, { 4, 4 }, { 5, 5 } } },
+ { CYCLES_MOV_REG_CR3, { { 5, 5 }, { 4, 4 }, { 4, 4 }, { 5, 6 } } },
+ { CYCLES_MOV_CR_REG, { { 6, 6 }, { 4, 4 }, { 4, 4 }, { 6, 6 } } },
+ { CYCLES_MOV_REG_DR0_3, { { 22, 22 }, { 10, 10 }, { 10, 10 }, { 10, 10 } } },
+ { CYCLES_MOV_REG_DR6_7, { { 16, 16 }, { 10, 10 }, { 10, 10 }, { 10, 10 } } },
+ { CYCLES_MOV_DR6_7_REG, { { 14, 14 }, { 11, 11 }, { 11, 11 }, { 9, 9 } } },
+ { CYCLES_MOV_DR0_3_REG, { { 22, 22 }, { 11, 11 }, { 11, 11 }, { 9, 9 } } },
+ { CYCLES_MOV_REG_TR6_7, { { 12, 12 }, { 4, 4 }, { 4, 4 }, { 11, 11 } } },
+ { CYCLES_MOV_TR6_7_REG, { { 12, 12 }, { 3, 3 }, { 3, 3 }, { 3, 3 } } },
+ { CYCLES_NOP, { { 3, 3 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_WAIT, { { 7, 7 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_ARPL_REG, { { 0, 20 }, { 0, 9 }, { 0, 7 }, { 0, 9 } } },
+ { CYCLES_ARPL_MEM, { { 0, 21 }, { 0, 9 }, { 0, 7 }, { 0, 9 } } },
+ { CYCLES_LAR_REG, { { 0, 15 }, { 11, 11 }, { 8, 8 }, { 0, 9 } } },
+ { CYCLES_LAR_MEM, { { 0, 16 }, { 11, 11 }, { 8, 8 }, { 0, 9 } } },
+ { CYCLES_LGDT, { { 11, 11 }, { 11, 11 }, { 6, 6 }, { 10, 10 } } },
+ { CYCLES_LIDT, { { 11, 11 }, { 11, 11 }, { 6, 6 }, { 10, 10 } } },
+ { CYCLES_LLDT_REG, { { 0, 20 }, { 11, 11 }, { 9, 9 }, { 0, 8 } } },
+ { CYCLES_LLDT_MEM, { { 0, 24 }, { 11, 11 }, { 9, 9 }, { 0, 8 } } },
+ { CYCLES_LMSW_REG, { { 11, 11 }, { 13, 13 }, { 8, 8 }, { 11, 11 } } },
+ { CYCLES_LMSW_MEM, { { 14, 14 }, { 13, 13 }, { 8, 8 }, { 11, 11 } } },
+ { CYCLES_LSL_REG, { { 0, 21 }, { 10, 10 }, { 8, 8 }, { 0, 9 } } },
+ { CYCLES_LSL_MEM, { { 0, 22 }, { 10, 10 }, { 8, 8 }, { 0, 9 } } },
+ { CYCLES_LTR_REG, { { 0, 23 }, { 20, 20 }, { 10, 10 }, { 0, 9 } } },
+ { CYCLES_LTR_MEM, { { 0, 27 }, { 20, 20 }, { 10, 10 }, { 0, 9 } } },
+ { CYCLES_SGDT, { { 9, 9 }, { 10, 10 }, { 4, 4 }, { 6, 6 } } },
+ { CYCLES_SIDT, { { 9, 9 }, { 10, 10 }, { 4, 4 }, { 6, 6 } } },
+ { CYCLES_SLDT_REG, { { 0, 2 }, { 2, 2 }, { 2, 2 }, { 0, 1 } } },
+ { CYCLES_SLDT_MEM, { { 0, 2 }, { 3, 3 }, { 2, 2 }, { 0, 1 } } },
+ { CYCLES_SMSW_REG, { { 2, 2 }, { 2, 2 }, { 4, 4 }, { 4, 4 } } },
+ { CYCLES_SMSW_MEM, { { 2, 2 }, { 3, 3 }, { 4, 4 }, { 4, 4 } } },
+ { CYCLES_STR_REG, { { 0, 2 }, { 2, 2 }, { 2, 2 }, { 0, 3 } } },
+ { CYCLES_STR_MEM, { { 0, 2 }, { 3, 3 }, { 2, 2 }, { 0, 3 } } },
+ { CYCLES_VERR_REG, { { 0, 10 }, { 11, 11 }, { 7, 7 }, { 0, 8 } } },
+ { CYCLES_VERR_MEM, { { 0, 11 }, { 11, 11 }, { 7, 7 }, { 0, 8 } } },
+ { CYCLES_VERW_REG, { { 0, 15 }, { 11, 11 }, { 7, 7 }, { 0, 8 } } },
+ { CYCLES_VERW_MEM, { { 0, 16 }, { 11, 11 }, { 7, 7 }, { 0, 8 } } },
+ { CYCLES_LOCK, { { 0, 0 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
+
+ // i486+
+ { CYCLES_BSWAP, { { 0, 0 }, { 1, 1 }, { 1, 1 }, { 6, 6 } } },
+ { CYCLES_CMPXCHG, { { 0, 0 }, { 6, 6 }, { 5, 5 }, { 6, 6 } } },
+ { CYCLES_INVD, { { 0, 0 }, { 4, 4 }, { 15, 15 }, { 20, 20 } } },
+ { CYCLES_XADD, { { 0, 0 }, { 4, 4 }, { 4, 4 }, { 2, 2 } } },
+
+ // Pentium+
+ { CYCLES_CMPXCHG8B, { { 0, 0 }, { 0, 0 }, { 10, 10 }, { 6, 6 } } },
+ { CYCLES_CPUID, { { 0, 0 }, { 0, 0 }, { 14, 14 }, { 12, 12 } } },
+ { CYCLES_CPUID_EAX1, { { 0, 0 }, { 0, 0 }, { 14, 14 }, { 12, 12 } } },
+ { CYCLES_RDTSC, { { 0, 0 }, { 0, 0 }, { 20, 20 }, { 1, 1 } } },
+ { CYCLES_RSM, { { 0, 0 }, { 0, 0 }, { 82, 82 }, { 57, 57 } } },
+ { CYCLES_RDMSR, { { 0, 0 }, { 0, 0 }, { 20, 20 }, { 1, 1 } } },
+
+ // FPU
+ { CYCLES_FABS, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_FADD, { { 0, 0 }, { 8, 8 }, { 3, 3 }, { 1, 1 } } },
+ { CYCLES_FBLD, { { 0, 0 }, { 70, 70 }, { 48, 48 }, { 1, 1 } } },
+ { CYCLES_FBSTP, { { 0, 0 }, {172,172 }, {148,148 }, { 1, 1 } } },
+ { CYCLES_FCHS, { { 0, 0 }, { 6, 6 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_FCLEX, { { 0, 0 }, { 7, 7 }, { 9, 9 }, { 1, 1 } } },
+ { CYCLES_FCOM, { { 0, 0 }, { 4, 4 }, { 4, 4 }, { 1, 1 } } },
+ { CYCLES_FCOS, { { 0, 0 }, {255,255 }, {124,124 }, { 1, 1 } } },
+ { CYCLES_FDECSTP, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_FDISI, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_FDIV, { { 0, 0 }, { 73, 73 }, { 39, 39 }, { 1, 1 } } },
+ { CYCLES_FDIVR, { { 0, 0 }, { 73, 73 }, { 39, 39 }, { 1, 1 } } },
+ { CYCLES_FENI, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_FFREE, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_FIADD, { { 0, 0 }, { 20, 20 }, { 7, 7 }, { 1, 1 } } },
+ { CYCLES_FICOM, { { 0, 0 }, { 16, 16 }, { 8, 8 }, { 1, 1 } } },
+ { CYCLES_FIDIV, { { 0, 0 }, { 85, 85 }, { 42, 42 }, { 1, 1 } } },
+ { CYCLES_FILD, { { 0, 0 }, { 13, 13 }, { 3, 3 }, { 1, 1 } } },
+ { CYCLES_FIMUL, { { 0, 0 }, { 23, 23 }, { 7, 7 }, { 1, 1 } } },
+ { CYCLES_FINCSTP, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_FINIT, { { 0, 0 }, { 17, 17 }, { 16, 16 }, { 1, 1 } } },
+ { CYCLES_FIST, { { 0, 0 }, { 29, 29 }, { 6, 6 }, { 1, 1 } } },
+ { CYCLES_FISUB, { { 0, 0 }, { 20, 20 }, { 7, 7 }, { 1, 1 } } },
+ { CYCLES_FLD, { { 0, 0 }, { 4, 4 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_FLDZ, { { 0, 0 }, { 4, 4 }, { 2, 2 }, { 1, 1 } } },
+ { CYCLES_FLD1, { { 0, 0 }, { 4, 4 }, { 2, 2 }, { 1, 1 } } },
+ { CYCLES_FLDL2E, { { 0, 0 }, { 8, 8 }, { 5, 5 }, { 1, 1 } } },
+ { CYCLES_FLDL2T, { { 0, 0 }, { 8, 8 }, { 5, 5 }, { 1, 1 } } },
+ { CYCLES_FLDLG2, { { 0, 0 }, { 8, 8 }, { 5, 5 }, { 1, 1 } } },
+ { CYCLES_FLDLN2, { { 0, 0 }, { 8, 8 }, { 5, 5 }, { 1, 1 } } },
+ { CYCLES_FLDPI, { { 0, 0 }, { 8, 8 }, { 5, 5 }, { 1, 1 } } },
+ { CYCLES_FLDCW, { { 0, 0 }, { 4, 4 }, { 7, 7 }, { 1, 1 } } },
+ { CYCLES_FLDENV, { { 0, 0 }, { 44, 44 }, { 37, 37 }, { 1, 1 } } },
+ { CYCLES_FMUL, { { 0, 0 }, { 16, 16 }, { 3, 3 }, { 1, 1 } } },
+ { CYCLES_FNOP, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_FPATAN, { { 0, 0 }, {218,218 }, {173,173 }, { 1, 1 } } },
+ { CYCLES_FPREM, { { 0, 0 }, { 70, 70 }, { 16, 16 }, { 1, 1 } } },
+ { CYCLES_FPREM1, { { 0, 0 }, { 72, 72 }, { 20, 20 }, { 1, 1 } } },
+ { CYCLES_FPTAN, { { 0, 0 }, {200,200 }, {173,173 }, { 1, 1 } } },
+ { CYCLES_FRNDINT, { { 0, 0 }, { 21, 21 }, { 9, 9 }, { 1, 1 } } },
+ { CYCLES_FRSTOR, { { 0, 0 }, {131,131 }, { 75, 75 }, { 1, 1 } } },
+ { CYCLES_FSAVE, { { 0, 0 }, {154,154 }, {127,127 }, { 1, 1 } } },
+ { CYCLES_FSCALE, { { 0, 0 }, { 30, 30 }, { 20, 20 }, { 1, 1 } } },
+ { CYCLES_FSETPM, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_FSIN, { { 0, 0 }, {255,255 }, {126,126 }, { 1, 1 } } },
+ { CYCLES_FSINCOS, { { 0, 0 }, {255,255 }, {137,137 }, { 1, 1 } } },
+ { CYCLES_FSQRT, { { 0, 0 }, { 83, 83 }, { 70, 70 }, { 1, 1 } } },
+ { CYCLES_FST, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_FSTCW, { { 0, 0 }, { 3, 3 }, { 2, 2 }, { 1, 1 } } },
+ { CYCLES_FSTENV, { { 0, 0 }, { 67, 67 }, { 48, 48 }, { 1, 1 } } },
+ { CYCLES_FSTSW, { { 0, 0 }, { 3, 3 }, { 2, 2 }, { 1, 1 } } },
+ { CYCLES_FSUB, { { 0, 0 }, { 8, 8 }, { 3, 3 }, { 1, 1 } } },
+ { CYCLES_FSUBR, { { 0, 0 }, { 8, 8 }, { 3, 3 }, { 1, 1 } } },
+ { CYCLES_FTST, { { 0, 0 }, { 4, 4 }, { 4, 4 }, { 1, 1 } } },
+ { CYCLES_FUCOM, { { 0, 0 }, { 4, 4 }, { 4, 4 }, { 1, 1 } } },
+ { CYCLES_FXAM, { { 0, 0 }, { 8, 8 }, { 21, 21 }, { 1, 1 } } },
+ { CYCLES_FXCH, { { 0, 0 }, { 4, 4 }, { 1, 1 }, { 1, 1 } } },
+ { CYCLES_FXTRACT, { { 0, 0 }, { 16, 16 }, { 13, 13 }, { 1, 1 } } },
+ { CYCLES_FYL2X, { { 0, 0 }, {196,196 }, {111,111 }, { 1, 1 } } },
+ { CYCLES_FYL2XPI, { { 0, 0 }, {171,171 }, {103,103 }, { 1, 1 } } },
+ { CYCLES_CMPXCHG_REG_REG_T, { { 0, 0 }, { 6, 6 }, { 6, 6 }, { 6, 6 } } },
+ { CYCLES_CMPXCHG_REG_REG_F, { { 0, 0 }, { 9, 9 }, { 9, 9 }, { 9, 9 } } },
+ { CYCLES_CMPXCHG_REG_MEM_T, { { 0, 0 }, { 7, 7 }, { 7, 7 }, { 7, 7 } } },
+ { CYCLES_CMPXCHG_REG_MEM_F, { { 0, 0 }, { 10, 10 }, { 10, 10 }, { 10, 10 } } },
+};
+
+#endif /* __CYCLES_H__ */
diff --git a/trunk/src/emu/cpu/i386/i386.c b/trunk/src/emu/cpu/i386/i386.c
new file mode 100644
index 00000000000..806a6ca8003
--- /dev/null
+++ b/trunk/src/emu/cpu/i386/i386.c
@@ -0,0 +1,3392 @@
+/*
+ Intel 386 emulator
+
+ Written by Ville Linde
+
+ Currently supports:
+ Intel 386
+ Intel 486
+ Intel Pentium
+ Cyrix MediaGX
+*/
+
+#include "emu.h"
+#include "debugger.h"
+#include "i386priv.h"
+#include "i386.h"
+
+#include "debug/debugcpu.h"
+
+/* seems to be defined on mingw-gcc */
+#undef i386
+
+int i386_parity_table[256];
+MODRM_TABLE i386_MODRM_table[256];
+
+static void i386_trap_with_error(i386_state* cpustate, int irq, int irq_gate, int trap_level, UINT32 err);
+static void i286_task_switch(i386_state* cpustate, UINT16 selector, UINT8 nested);
+static void i386_task_switch(i386_state* cpustate, UINT16 selector, UINT8 nested);
+
+#define FAULT(fault,error) {i386_trap_with_error(cpustate,fault,0,0,error); return;}
+#define FAULT_EXP(fault,error) {i386_trap_with_error(cpustate,fault,0,trap_level+1,error); return;}
+
+/*************************************************************************/
+
+#define INT_DEBUG 1
+
+static void i386_load_protected_mode_segment(i386_state *cpustate, I386_SREG *seg )
+{
+ UINT32 v1,v2;
+ UINT32 base, limit;
+ int entry;
+
+ if ( seg->selector & 0x4 )
+ {
+ base = cpustate->ldtr.base;
+ limit = cpustate->ldtr.limit;
+ } else {
+ base = cpustate->gdtr.base;
+ limit = cpustate->gdtr.limit;
+ }
+
+ if (limit == 0 || seg->selector + 7 > limit)
+ return;
+ entry = seg->selector & ~0x7;
+
+ v1 = READ32(cpustate, base + entry );
+ v2 = READ32(cpustate, base + entry + 4 );
+
+ seg->flags = (v2 >> 8) & 0xf0ff;
+ seg->base = (v2 & 0xff000000) | ((v2 & 0xff) << 16) | ((v1 >> 16) & 0xffff);
+ seg->limit = (v2 & 0xf0000) | (v1 & 0xffff);
+ if (seg->flags & 0x8000)
+ seg->limit = (seg->limit << 12) | 0xfff;
+ seg->d = (seg->flags & 0x4000) ? 1 : 0;
+}
+
+static void i386_load_call_gate(i386_state* cpustate, I386_CALL_GATE *gate)
+{
+ UINT32 v1,v2;
+ UINT32 base,limit;
+ int entry;
+
+ if ( gate->segment & 0x4 )
+ {
+ base = cpustate->ldtr.base;
+ limit = cpustate->ldtr.limit;
+ } else {
+ base = cpustate->gdtr.base;
+ limit = cpustate->gdtr.limit;
+ }
+
+ if (limit == 0 || gate->segment + 7 > limit)
+ return;
+
+ entry = gate->segment & ~0x7;
+
+ v1 = READ32(cpustate, base + entry );
+ v2 = READ32(cpustate, base + entry + 4 );
+
+ /* Note that for task gates, offset and dword_count are not used */
+ gate->selector = (v1 >> 16) & 0xffff;
+ gate->offset = (v1 & 0x0000ffff) | (v2 & 0xffff0000);
+ gate->ar = (v2 >> 8) & 0xff;
+ gate->dword_count = v2 & 0x001f;
+ gate->present = (gate->ar >> 7) & 0x01;
+ gate->dpl = (gate->ar >> 5) & 0x03;
+}
+
+static void i386_load_segment_descriptor(i386_state *cpustate, int segment )
+{
+ if (PROTECTED_MODE)
+ {
+ if (!V8086_MODE)
+ i386_load_protected_mode_segment(cpustate, &cpustate->sreg[segment] );
+ else
+ {
+ cpustate->sreg[segment].base = cpustate->sreg[segment].selector << 4;
+ cpustate->sreg[segment].limit = 0xffff;
+ cpustate->sreg[segment].flags = (segment == CS) ? 0x009a : 0x0092;
+ }
+ }
+ else
+ {
+ cpustate->sreg[segment].base = cpustate->sreg[segment].selector << 4;
+
+ if( segment == CS && !cpustate->performed_intersegment_jump )
+ cpustate->sreg[segment].base |= 0xfff00000;
+ }
+}
+
+/* Retrieves the stack selector located in the current TSS */
+static UINT32 i386_get_stack_segment(i386_state* cpustate, UINT8 privilege)
+{
+ if(privilege >= 3)
+ return 0;
+
+ return READ32(cpustate,(cpustate->task.base+8) + (8*privilege));
+}
+
+static UINT16 i286_get_stack_segment(i386_state* cpustate, UINT8 privilege)
+{
+ if(privilege >= 3)
+ return 0;
+
+ return READ16(cpustate,(cpustate->task.base+4) + (4*privilege));
+}
+
+/* Retrieves the stack pointer located in the current TSS */
+static UINT32 i386_get_stack_ptr(i386_state* cpustate, UINT8 privilege)
+{
+ if(privilege >= 3)
+ return 0;
+
+ return READ32(cpustate,(cpustate->task.base+4) + (8*privilege));
+}
+
+static UINT16 i286_get_stack_ptr(i386_state* cpustate, UINT8 privilege)
+{
+ if(privilege >= 3)
+ return 0;
+
+ return READ16(cpustate,(cpustate->task.base+2) + (4*privilege));
+}
+
+static UINT32 get_flags(i386_state *cpustate)
+{
+ UINT32 f = 0x2;
+ f |= cpustate->CF;
+ f |= cpustate->PF << 2;
+ f |= cpustate->AF << 4;
+ f |= cpustate->ZF << 6;
+ f |= cpustate->SF << 7;
+ f |= cpustate->TF << 8;
+ f |= cpustate->IF << 9;
+ f |= cpustate->DF << 10;
+ f |= cpustate->OF << 11;
+ f |= cpustate->IOP1 << 12;
+ f |= cpustate->IOP2 << 13;
+ f |= cpustate->NT << 14;
+ return (cpustate->eflags & cpustate->eflags_mask) | (f & 0xffff);
+}
+
+static void set_flags(i386_state *cpustate, UINT32 f )
+{
+ cpustate->CF = (f & 0x1) ? 1 : 0;
+ cpustate->PF = (f & 0x4) ? 1 : 0;
+ cpustate->AF = (f & 0x10) ? 1 : 0;
+ cpustate->ZF = (f & 0x40) ? 1 : 0;
+ cpustate->SF = (f & 0x80) ? 1 : 0;
+ cpustate->TF = (f & 0x100) ? 1 : 0;
+ cpustate->IF = (f & 0x200) ? 1 : 0;
+ cpustate->DF = (f & 0x400) ? 1 : 0;
+ cpustate->OF = (f & 0x800) ? 1 : 0;
+ cpustate->IOP1 = (f & 0x1000) ? 1 : 0;
+ cpustate->IOP2 = (f & 0x2000) ? 1 : 0;
+ cpustate->NT = (f & 0x4000) ? 1 : 0;
+ cpustate->eflags = f & cpustate->eflags_mask;
+}
+
+static void sib_byte(i386_state *cpustate,UINT8 mod, UINT32* out_ea, UINT8* out_segment)
+{
+ UINT32 ea = 0;
+ UINT8 segment = 0;
+ UINT8 scale, i, base;
+ UINT8 sib = FETCH(cpustate);
+ scale = (sib >> 6) & 0x3;
+ i = (sib >> 3) & 0x7;
+ base = sib & 0x7;
+
+ switch( base )
+ {
+ case 0: ea = REG32(EAX); segment = DS; break;
+ case 1: ea = REG32(ECX); segment = DS; break;
+ case 2: ea = REG32(EDX); segment = DS; break;
+ case 3: ea = REG32(EBX); segment = DS; break;
+ case 4: ea = REG32(ESP); segment = SS; break;
+ case 5:
+ if( mod == 0 ) {
+ ea = FETCH32(cpustate);
+ segment = DS;
+ } else if( mod == 1 ) {
+ ea = REG32(EBP);
+ segment = SS;
+ } else if( mod == 2 ) {
+ ea = REG32(EBP);
+ segment = SS;
+ }
+ break;
+ case 6: ea = REG32(ESI); segment = DS; break;
+ case 7: ea = REG32(EDI); segment = DS; break;
+ }
+ switch( i )
+ {
+ case 0: ea += REG32(EAX) * (1 << scale); break;
+ case 1: ea += REG32(ECX) * (1 << scale); break;
+ case 2: ea += REG32(EDX) * (1 << scale); break;
+ case 3: ea += REG32(EBX) * (1 << scale); break;
+ case 4: break;
+ case 5: ea += REG32(EBP) * (1 << scale); break;
+ case 6: ea += REG32(ESI) * (1 << scale); break;
+ case 7: ea += REG32(EDI) * (1 << scale); break;
+ }
+ *out_ea = ea;
+ *out_segment = segment;
+}
+
+static void modrm_to_EA(i386_state *cpustate,UINT8 mod_rm, UINT32* out_ea, UINT8* out_segment)
+{
+ INT8 disp8;
+ INT16 disp16;
+ INT32 disp32;
+ UINT8 mod = (mod_rm >> 6) & 0x3;
+ UINT8 rm = mod_rm & 0x7;
+ UINT32 ea;
+ UINT8 segment;
+
+ if( mod_rm >= 0xc0 )
+ fatalerror("i386: Called modrm_to_EA with modrm value %02X !",mod_rm);
+
+ if( cpustate->address_size ) {
+ switch( rm )
+ {
+ default:
+ case 0: ea = REG32(EAX); segment = DS; break;
+ case 1: ea = REG32(ECX); segment = DS; break;
+ case 2: ea = REG32(EDX); segment = DS; break;
+ case 3: ea = REG32(EBX); segment = DS; break;
+ case 4: sib_byte(cpustate, mod, &ea, &segment ); break;
+ case 5:
+ if( mod == 0 ) {
+ ea = FETCH32(cpustate); segment = DS;
+ } else {
+ ea = REG32(EBP); segment = SS;
+ }
+ break;
+ case 6: ea = REG32(ESI); segment = DS; break;
+ case 7: ea = REG32(EDI); segment = DS; break;
+ }
+ if( mod == 1 ) {
+ disp8 = FETCH(cpustate);
+ ea += (INT32)disp8;
+ } else if( mod == 2 ) {
+ disp32 = FETCH32(cpustate);
+ ea += disp32;
+ }
+
+ if( cpustate->segment_prefix )
+ segment = cpustate->segment_override;
+
+ *out_ea = ea;
+ *out_segment = segment;
+
+ } else {
+ switch( rm )
+ {
+ default:
+ case 0: ea = REG16(BX) + REG16(SI); segment = DS; break;
+ case 1: ea = REG16(BX) + REG16(DI); segment = DS; break;
+ case 2: ea = REG16(BP) + REG16(SI); segment = SS; break;
+ case 3: ea = REG16(BP) + REG16(DI); segment = SS; break;
+ case 4: ea = REG16(SI); segment = DS; break;
+ case 5: ea = REG16(DI); segment = DS; break;
+ case 6:
+ if( mod == 0 ) {
+ ea = FETCH16(cpustate); segment = DS;
+ } else {
+ ea = REG16(BP); segment = SS;
+ }
+ break;
+ case 7: ea = REG16(BX); segment = DS; break;
+ }
+ if( mod == 1 ) {
+ disp8 = FETCH(cpustate);
+ ea += (INT32)disp8;
+ } else if( mod == 2 ) {
+ disp16 = FETCH16(cpustate);
+ ea += (INT32)disp16;
+ }
+
+ if( cpustate->segment_prefix )
+ segment = cpustate->segment_override;
+
+ *out_ea = ea & 0xffff;
+ *out_segment = segment;
+ }
+}
+
+static UINT32 GetNonTranslatedEA(i386_state *cpustate,UINT8 modrm)
+{
+ UINT8 segment;
+ UINT32 ea;
+ modrm_to_EA(cpustate, modrm, &ea, &segment );
+ return ea;
+}
+
+static UINT32 GetEA(i386_state *cpustate,UINT8 modrm)
+{
+ UINT8 segment;
+ UINT32 ea;
+ modrm_to_EA(cpustate, modrm, &ea, &segment );
+ return i386_translate(cpustate, segment, ea );
+}
+
+/* Check segment register for validity when changing privilege level after an RETF */
+static void i386_check_sreg_validity(i386_state* cpustate, int reg)
+{
+ UINT16 selector = cpustate->sreg[reg].selector;
+ UINT8 CPL = cpustate->CPL;
+ UINT8 DPL,RPL;
+ I386_SREG desc;
+ int invalid = 0;
+
+ memset(&desc, 0, sizeof(desc));
+ desc.selector = selector;
+ i386_load_protected_mode_segment(cpustate,&desc);
+ DPL = (desc.flags >> 5) & 0x03; // descriptor privilege level
+ RPL = selector & 0x03;
+
+ /* Must be within the relevant descriptor table limits */
+ if(selector & 0x04)
+ {
+ if((selector & ~0x07) > cpustate->ldtr.limit)
+ invalid = 1;
+ }
+ else
+ {
+ if((selector & ~0x07) > cpustate->gdtr.limit)
+ invalid = 1;
+ }
+
+ /* Must be either a data or readable code segment */
+ if(((desc.flags & 0x0018) == 0x0018 && (desc.flags & 0x0002)) || (desc.flags & 0x0018) == 0x0010)
+ invalid = 0;
+ else
+ invalid = 1;
+
+ /* If a data segment or non-conforming code segment, then either DPL >= CPL or DPL >= RPL */
+ if(((desc.flags & 0x0018) == 0x0018 && (desc.flags & 0x0004) == 0) || (desc.flags & 0x0018) == 0x0010)
+ {
+ if((DPL < CPL) || (DPL < RPL))
+ invalid = 1;
+ }
+
+ /* if segment is invalid, then segment register is nulled */
+ if(invalid != 0)
+ {
+ cpustate->sreg[reg].selector = 0;
+ i386_load_segment_descriptor(cpustate,reg);
+ }
+}
+
+static void i386_trap(i386_state *cpustate,int irq, int irq_gate, int trap_level)
+{
+ /* I386 Interrupts/Traps/Faults:
+ *
+ * 0x00 Divide by zero
+ * 0x01 Debug exception
+ * 0x02 NMI
+ * 0x03 Int3
+ * 0x04 Overflow
+ * 0x05 Array bounds check
+ * 0x06 Illegal Opcode
+ * 0x07 FPU not available
+ * 0x08 Double fault
+ * 0x09 Coprocessor segment overrun
+ * 0x0a Invalid task state
+ * 0x0b Segment not present
+ * 0x0c Stack exception
+ * 0x0d General Protection Fault
+ * 0x0e Page fault
+ * 0x0f Reserved
+ * 0x10 Coprocessor error
+ */
+ UINT32 v1, v2;
+ UINT32 offset;
+ UINT16 segment;
+ int entry = irq * (PROTECTED_MODE ? 8 : 4);
+ int SetRPL = 0;
+
+ if( !(PROTECTED_MODE) )
+ {
+ /* 16-bit */
+ PUSH16(cpustate, get_flags(cpustate) & 0xffff );
+ PUSH16(cpustate, cpustate->sreg[CS].selector );
+ if(irq == 3 || irq == 4 || irq == 9 || irq_gate == 1)
+ PUSH16(cpustate, cpustate->eip );
+ else
+ PUSH16(cpustate, cpustate->prev_eip );
+
+ cpustate->sreg[CS].selector = READ16(cpustate, cpustate->idtr.base + entry + 2 );
+ cpustate->eip = READ16(cpustate, cpustate->idtr.base + entry );
+
+ cpustate->TF = 0;
+ cpustate->IF = 0;
+ }
+ else
+ {
+ int type;
+ UINT16 flags;
+ I386_SREG desc;
+ UINT8 CPL = 0, DPL = 0; //, RPL = 0;
+ I386_CALL_GATE gate;
+
+ /* 32-bit */
+ v1 = READ32(cpustate, cpustate->idtr.base + entry );
+ v2 = READ32(cpustate, cpustate->idtr.base + entry + 4 );
+ offset = (v2 & 0xffff0000) | (v1 & 0xffff);
+ segment = (v1 >> 16) & 0xffff;
+ type = (v2>>8) & 0x1F;
+ flags = (v2>>8) & 0xf0ff;
+
+ if(trap_level == 2)
+ {
+ logerror("IRQ: Double fault.\n");
+ FAULT_EXP(FAULT_DF,0);
+ }
+ if(trap_level >= 3)
+ {
+ logerror("IRQ: Triple fault. CPU reset.\n");
+ device_set_input_line(cpustate->device, INPUT_LINE_RESET, PULSE_LINE);
+ return;
+ }
+
+ // TODO: support for EXT bit
+ /* segment privilege checks */
+ if(entry > cpustate->idtr.limit)
+ {
+ logerror("IRQ: Vector is past IDT limit.\n");
+ FAULT_EXP(FAULT_GP,entry+2)
+ }
+ /* segment must be interrupt gate, trap gate, or task gate */
+ if(type != 0x05 && type != 0x06 && type != 0x07 && type != 0x0e && type != 0x0f)
+ {
+ logerror("IRQ: Vector segment is not an interrupt, trap or task gate.\n");
+ FAULT_EXP(FAULT_GP,entry+2)
+ }
+
+ /* TODO: if software IRQ, then gate DPL must be less than CPL, else #GP(vector*8+2+EXT) */
+
+ if((flags & 0x0080) == 0)
+ {
+ logerror("IRQ: Vector segment is not present.\n");
+ FAULT_EXP(FAULT_NP,entry+2)
+ }
+
+ if(type == 0x05)
+ {
+ /* Task gate */
+ memset(&gate, 0, sizeof(gate));
+ gate.segment = segment;
+ i386_load_call_gate(cpustate,&gate);
+ memset(&desc, 0, sizeof(desc));
+ desc.selector = gate.selector;
+ i386_load_protected_mode_segment(cpustate,&desc);
+ if(segment & 0x04)
+ {
+ logerror("IRQ: Task gate: TSS is not in the GDT.\n");
+ FAULT_EXP(FAULT_TS,segment & ~0x07);
+ }
+ else
+ {
+ if(segment > cpustate->gdtr.limit)
+ {
+ logerror("IRQ: Task gate: TSS is past GDT limit.\n");
+ FAULT_EXP(FAULT_TS,segment & ~0x07);
+ }
+ }
+ if((desc.flags & 0x000f) != 0x09 && (desc.flags & 0x000f) != 0x01)
+ {
+ logerror("IRQ: Task gate: TSS is not an available TSS.\n");
+ FAULT_EXP(FAULT_TS,segment & ~0x07);
+ }
+ if((desc.flags & 0x0080) == 0)
+ {
+ logerror("IRQ: Task gate: TSS is not present.\n");
+ FAULT_EXP(FAULT_NP,segment & ~0x07);
+ }
+ if(desc.flags & 0x08)
+ i386_task_switch(cpustate,desc.selector,0);
+ else
+ i286_task_switch(cpustate,desc.selector,0);
+ return;
+ }
+ else
+ {
+ /* Interrupt or Trap gate */
+ memset(&desc, 0, sizeof(desc));
+ desc.selector = segment;
+ i386_load_protected_mode_segment(cpustate,&desc);
+ CPL = cpustate->CPL; // current privilege level
+ DPL = (desc.flags >> 5) & 0x03; // descriptor privilege level
+// RPL = segment & 0x03; // requested privilege level
+
+ if((segment & ~0x07) == 0)
+ {
+ logerror("IRQ: Gate segment is null.\n");
+ FAULT_EXP(FAULT_GP,0)
+ }
+ if(segment & 0x04)
+ {
+ if((segment & ~0x07) > cpustate->ldtr.limit)
+ {
+ logerror("IRQ: Gate segment is past LDT limit.\n");
+ FAULT_EXP(FAULT_GP,segment)
+ }
+ }
+ else
+ {
+ if((segment & ~0x07) > cpustate->gdtr.limit)
+ {
+ logerror("IRQ: Gate segment is past GDT limit.\n");
+ FAULT_EXP(FAULT_GP,segment)
+ }
+ }
+ if((desc.flags & 0x0018) != 0x18)
+ {
+ logerror("IRQ: Gate descriptor is not a code segment.\n");
+ FAULT_EXP(FAULT_GP,segment)
+ }
+ if((desc.flags & 0x0080) == 0)
+ {
+ logerror("IRQ: Gate segment is not present.\n");
+ FAULT_EXP(FAULT_NP,segment)
+ }
+ if((desc.flags & 0x0004) == 0 && (DPL < CPL))
+ {
+ /* IRQ to inner privilege */
+ I386_SREG stack;
+ UINT32 newESP,oldSS,oldESP;
+
+ /* Check new stack segment in TSS */
+ memset(&stack, 0, sizeof(stack));
+ if(flags & 0x0008)
+ stack.selector = i386_get_stack_segment(cpustate,DPL);
+ else
+ stack.selector = i286_get_stack_segment(cpustate,DPL);
+ i386_load_protected_mode_segment(cpustate,&stack);
+ oldSS = cpustate->sreg[SS].selector;
+ if(flags & 0x0008)
+ oldESP = REG32(ESP);
+ else
+ oldESP = REG16(SP);
+ if((stack.selector & ~0x07) == 0)
+ {
+ logerror("IRQ: New stack selector is null.\n");
+ FAULT_EXP(FAULT_GP,0) // #GP(EXT)
+ }
+ if(stack.selector & 0x04)
+ {
+ if((stack.selector & ~0x07) > cpustate->ldtr.base)
+ {
+ logerror("IRQ: New stack selector is past LDT limit.\n");
+ FAULT_EXP(FAULT_TS,stack.selector & ~0x07)
+ }
+ }
+ else
+ {
+ if((stack.selector & ~0x07) > cpustate->gdtr.base)
+ {
+ logerror("IRQ: New stack selector is past GDT limit.\n");
+ FAULT_EXP(FAULT_TS,stack.selector & ~0x07) // #TS(stack selector + EXT)
+ }
+ }
+ if((stack.selector & 0x03) != DPL)
+ {
+ logerror("IRQ: New stack selector RPL is not equal to code segment DPL.\n");
+ FAULT_EXP(FAULT_TS,stack.selector & ~0x07) // #TS(stack selector + EXT)
+ }
+ if(((stack.flags >> 5) & 0x03) != DPL)
+ {
+ logerror("IRQ: New stack segment DPL is not equal to code segment DPL.\n");
+ FAULT_EXP(FAULT_TS,stack.selector & ~0x07) // #TS(stack selector + EXT)
+ }
+ if(((stack.flags & 0x0018) != 0x10) && (stack.flags & 0x0002) != 0)
+ {
+ logerror("IRQ: New stack segment is not a writable data segment.\n");
+ FAULT_EXP(FAULT_TS,stack.selector & ~0x07) // #TS(stack selector + EXT)
+ }
+ if((stack.flags & 0x0080) == 0)
+ {
+ logerror("IRQ: New stack segment is not present.\n");
+ FAULT_EXP(FAULT_SS,stack.selector & ~0x07) // #TS(stack selector + EXT)
+ }
+ if(type & 0x08) // 32-bit gate
+ {
+ newESP = i386_get_stack_ptr(cpustate,DPL);
+ if(newESP < 20)
+ {
+ logerror("IRQ: New stack has no space for return addresses.\n");
+ FAULT_EXP(FAULT_SS,0)
+ }
+ }
+ else // 16-bit gate
+ {
+ newESP = i286_get_stack_ptr(cpustate,DPL);
+ if(newESP < 10)
+ {
+ logerror("IRQ: New stack has no space for return addresses.\n");
+ FAULT_EXP(FAULT_SS,0)
+ }
+ }
+ if(offset > desc.limit)
+ {
+ logerror("IRQ: New EIP is past code segment limit.\n");
+ FAULT_EXP(FAULT_GP,0)
+ }
+ /* Load new stack segment descriptor */
+ cpustate->sreg[SS].selector = stack.selector;
+ i386_load_segment_descriptor(cpustate,SS);
+ if(flags & 0x0008)
+ REG32(ESP) = i386_get_stack_ptr(cpustate,DPL);
+ else
+ REG16(SP) = i286_get_stack_ptr(cpustate,DPL);
+ if(type & 0x08)
+ {
+ // 32-bit gate
+ PUSH32(cpustate,oldSS);
+ PUSH32(cpustate,oldESP);
+ }
+ else
+ {
+ // 16-bit gate
+ PUSH16(cpustate,oldSS);
+ PUSH16(cpustate,oldESP);
+ }
+ cpustate->CPL = DPL;
+ SetRPL = 1;
+ }
+ else
+ {
+ int stack_limit;
+ if((desc.flags & 0x0004) || (DPL == CPL))
+ {
+ /* IRQ to same privilege */
+ if(type == 0x0e || type == 0x0f) // 32-bit gate
+ stack_limit = 10;
+ else
+ stack_limit = 6;
+ // TODO: Add check for error code (2 extra bytes)
+ if(REG32(ESP) < stack_limit)
+ {
+ logerror("IRQ: Stack has no space left (needs %i bytes).\n",stack_limit);
+ FAULT_EXP(FAULT_SS,0)
+ }
+ if(offset > desc.limit)
+ {
+ logerror("IRQ: Gate segment offset is past segment limit.\n");
+ FAULT_EXP(FAULT_GP,0)
+ }
+ SetRPL = 1;
+ }
+ else
+ {
+ logerror("IRQ: Gate descriptor is non-conforming, and DPL does not equal CPL.\n");
+ FAULT_EXP(FAULT_GP,segment)
+ }
+ }
+ }
+
+ if(type != 0x0e && type != 0x0f) // if not 386 interrupt or trap gate
+ {
+ PUSH16(cpustate, get_flags(cpustate) & 0xffff );
+ PUSH16(cpustate, cpustate->sreg[CS].selector );
+ if(irq == 3 || irq == 4 || irq == 9 || irq_gate == 1)
+ PUSH16(cpustate, cpustate->eip );
+ else
+ PUSH16(cpustate, cpustate->prev_eip );
+ }
+ else
+ {
+ PUSH32(cpustate, get_flags(cpustate) & 0x00fcffff );
+ PUSH32(cpustate, cpustate->sreg[CS].selector );
+ if(irq == 3 || irq == 4 || irq == 9 || irq_gate == 1)
+ PUSH32(cpustate, cpustate->eip );
+ else
+ PUSH32(cpustate, cpustate->prev_eip );
+ }
+ if(SetRPL != 0)
+ segment = (segment & ~0x03) | cpustate->CPL;
+ cpustate->sreg[CS].selector = segment;
+ cpustate->eip = offset;
+
+ if(type == 0x0e || type == 0x06)
+ cpustate->IF = 0;
+ cpustate->TF = 0;
+ cpustate->NT = 0;
+ }
+
+ i386_load_segment_descriptor(cpustate,CS);
+ CHANGE_PC(cpustate,cpustate->eip);
+
+}
+
+static void i386_trap_with_error(i386_state *cpustate,int irq, int irq_gate, int trap_level, UINT32 error)
+{
+ i386_trap(cpustate,irq,irq_gate,trap_level);
+ if(irq == 8 || irq == 10 || irq == 11 || irq == 12 || irq == 13 || irq == 14)
+ {
+ // for these exceptions, an error code is pushed onto the stack by the processor.
+ // no error code is pushed for software interrupts, either.
+ PUSH32(cpustate,error);
+ }
+}
+
+
+static void i286_task_switch(i386_state *cpustate, UINT16 selector, UINT8 nested)
+{
+ UINT32 tss;
+ I386_SREG seg;
+ UINT16 old_task;
+ UINT8 ar_byte; // access rights byte
+
+ /* TODO: Task State Segment privilege checks */
+
+ /* For tasks that aren't nested, clear the busy bit in the task's descriptor */
+ if(nested == 0)
+ {
+ if(cpustate->task.segment & 0x0004)
+ {
+ ar_byte = READ8(cpustate,cpustate->ldtr.base + (cpustate->task.segment & ~0x0007) + 5);
+ WRITE8(cpustate,cpustate->ldtr.base + (cpustate->task.segment & ~0x0007) + 5,ar_byte & ~0x02);
+ }
+ else
+ {
+ ar_byte = READ8(cpustate,cpustate->gdtr.base + (cpustate->task.segment & ~0x0007) + 5);
+ WRITE8(cpustate,cpustate->gdtr.base + (cpustate->task.segment & ~0x0007) + 5,ar_byte & ~0x02);
+ }
+ }
+
+ /* Save the state of the current task in the current TSS (TR register base) */
+ tss = cpustate->task.base;
+ WRITE16(cpustate,tss+0x0e,cpustate->eip & 0x0000ffff);
+ WRITE16(cpustate,tss+0x10,get_flags(cpustate) & 0x0000ffff);
+ WRITE16(cpustate,tss+0x12,REG16(AX));
+ WRITE16(cpustate,tss+0x14,REG16(CX));
+ WRITE16(cpustate,tss+0x16,REG16(DX));
+ WRITE16(cpustate,tss+0x18,REG16(BX));
+ WRITE16(cpustate,tss+0x1a,REG16(SP));
+ WRITE16(cpustate,tss+0x1c,REG16(BP));
+ WRITE16(cpustate,tss+0x1e,REG16(SI));
+ WRITE16(cpustate,tss+0x20,REG16(DI));
+ WRITE16(cpustate,tss+0x22,cpustate->sreg[ES].selector);
+ WRITE16(cpustate,tss+0x24,cpustate->sreg[CS].selector);
+ WRITE16(cpustate,tss+0x26,cpustate->sreg[SS].selector);
+ WRITE16(cpustate,tss+0x28,cpustate->sreg[DS].selector);
+
+ old_task = cpustate->task.segment;
+
+ /* Load task register with the selector of the incoming task */
+ cpustate->task.segment = selector;
+ memset(&seg, 0, sizeof(seg));
+ seg.selector = cpustate->task.segment;
+ i386_load_protected_mode_segment(cpustate,&seg);
+ cpustate->task.limit = seg.limit;
+ cpustate->task.base = seg.base;
+ cpustate->task.flags = seg.flags;
+
+ /* Set TS bit in CR0 */
+ cpustate->cr[0] |= 0x08;
+
+ /* Load incoming task state from the new task's TSS */
+ tss = cpustate->task.base;
+ cpustate->ldtr.segment = READ16(cpustate,tss+0x2a) & 0xffff;
+ seg.selector = cpustate->ldtr.segment;
+ i386_load_protected_mode_segment(cpustate,&seg);
+ cpustate->ldtr.limit = seg.limit;
+ cpustate->ldtr.base = seg.base;
+ cpustate->ldtr.flags = seg.flags;
+ cpustate->eip = READ16(cpustate,tss+0x0e);
+ set_flags(cpustate,READ16(cpustate,tss+0x10));
+ REG16(AX) = READ16(cpustate,tss+0x12);
+ REG16(CX) = READ16(cpustate,tss+0x14);
+ REG16(DX) = READ16(cpustate,tss+0x16);
+ REG16(BX) = READ16(cpustate,tss+0x18);
+ REG16(SP) = READ16(cpustate,tss+0x1a);
+ REG16(BP) = READ16(cpustate,tss+0x1c);
+ REG16(SI) = READ16(cpustate,tss+0x1e);
+ REG16(DI) = READ16(cpustate,tss+0x20);
+ cpustate->sreg[ES].selector = READ16(cpustate,tss+0x22) & 0xffff;
+ i386_load_segment_descriptor(cpustate, ES);
+ cpustate->sreg[CS].selector = READ16(cpustate,tss+0x24) & 0xffff;
+ i386_load_segment_descriptor(cpustate, CS);
+ cpustate->sreg[SS].selector = READ16(cpustate,tss+0x26) & 0xffff;
+ i386_load_segment_descriptor(cpustate, SS);
+ cpustate->sreg[DS].selector = READ16(cpustate,tss+0x28) & 0xffff;
+ i386_load_segment_descriptor(cpustate, DS);
+
+ /* Set the busy bit in the new task's descriptor */
+ if(selector & 0x0004)
+ {
+ ar_byte = READ8(cpustate,cpustate->ldtr.base + (selector & ~0x0007) + 5);
+ WRITE8(cpustate,cpustate->ldtr.base + (selector & ~0x0007) + 5,ar_byte | 0x02);
+ }
+ else
+ {
+ ar_byte = READ8(cpustate,cpustate->gdtr.base + (selector & ~0x0007) + 5);
+ WRITE8(cpustate,cpustate->gdtr.base + (selector & ~0x0007) + 5,ar_byte | 0x02);
+ }
+
+ /* For nested tasks, we write the outgoing task's selector to the back-link field of the new TSS,
+ and set the NT flag in the EFLAGS register */
+ if(nested != 0)
+ {
+ WRITE16(cpustate,tss+0,old_task);
+ cpustate->NT = 1;
+ }
+ CHANGE_PC(cpustate,cpustate->eip);
+
+ cpustate->CPL = cpustate->sreg[CS].selector & 0x03;
+ printf("286 Task Switch from selector %04x to %04x\n",old_task,selector);
+}
+
+static void i386_task_switch(i386_state *cpustate, UINT16 selector, UINT8 nested)
+{
+ UINT32 tss;
+ I386_SREG seg;
+ UINT16 old_task;
+ UINT8 ar_byte; // access rights byte
+
+ /* TODO: Task State Segment privilege checks */
+
+ /* For tasks that aren't nested, clear the busy bit in the task's descriptor */
+ if(nested == 0)
+ {
+ if(cpustate->task.segment & 0x0004)
+ {
+ ar_byte = READ8(cpustate,cpustate->ldtr.base + (cpustate->task.segment & ~0x0007) + 5);
+ WRITE8(cpustate,cpustate->ldtr.base + (cpustate->task.segment & ~0x0007) + 5,ar_byte & ~0x02);
+ }
+ else
+ {
+ ar_byte = READ8(cpustate,cpustate->gdtr.base + (cpustate->task.segment & ~0x0007) + 5);
+ WRITE8(cpustate,cpustate->gdtr.base + (cpustate->task.segment & ~0x0007) + 5,ar_byte & ~0x02);
+ }
+ }
+
+ /* Save the state of the current task in the current TSS (TR register base) */
+ tss = cpustate->task.base;
+ WRITE32(cpustate,tss+0x1c,cpustate->cr[3]); // correct?
+ WRITE32(cpustate,tss+0x20,cpustate->eip);
+ WRITE32(cpustate,tss+0x24,get_flags(cpustate));
+ WRITE32(cpustate,tss+0x28,REG32(EAX));
+ WRITE32(cpustate,tss+0x2c,REG32(ECX));
+ WRITE32(cpustate,tss+0x30,REG32(EDX));
+ WRITE32(cpustate,tss+0x34,REG32(EBX));
+ WRITE32(cpustate,tss+0x38,REG32(ESP));
+ WRITE32(cpustate,tss+0x3c,REG32(EBP));
+ WRITE32(cpustate,tss+0x40,REG32(ESI));
+ WRITE32(cpustate,tss+0x44,REG32(EDI));
+ WRITE32(cpustate,tss+0x48,cpustate->sreg[ES].selector);
+ WRITE32(cpustate,tss+0x4c,cpustate->sreg[CS].selector);
+ WRITE32(cpustate,tss+0x50,cpustate->sreg[SS].selector);
+ WRITE32(cpustate,tss+0x54,cpustate->sreg[DS].selector);
+ WRITE32(cpustate,tss+0x58,cpustate->sreg[FS].selector);
+ WRITE32(cpustate,tss+0x5c,cpustate->sreg[GS].selector);
+
+ old_task = cpustate->task.segment;
+
+ /* Load task register with the selector of the incoming task */
+ cpustate->task.segment = selector;
+ memset(&seg, 0, sizeof(seg));
+ seg.selector = cpustate->task.segment;
+ i386_load_protected_mode_segment(cpustate,&seg);
+ cpustate->task.limit = seg.limit;
+ cpustate->task.base = seg.base;
+ cpustate->task.flags = seg.flags;
+
+ /* Set TS bit in CR0 */
+ cpustate->cr[0] |= 0x08;
+
+ /* Load incoming task state from the new task's TSS */
+ tss = cpustate->task.base;
+ cpustate->ldtr.segment = READ32(cpustate,tss+0x60) & 0xffff;
+ seg.selector = cpustate->ldtr.segment;
+ i386_load_protected_mode_segment(cpustate,&seg);
+ cpustate->ldtr.limit = seg.limit;
+ cpustate->ldtr.base = seg.base;
+ cpustate->ldtr.flags = seg.flags;
+ cpustate->cr[3] = READ32(cpustate,tss+0x1c); // CR3 (PDBR)
+ cpustate->eip = READ32(cpustate,tss+0x20);
+ set_flags(cpustate,READ32(cpustate,tss+0x24));
+ REG32(EAX) = READ32(cpustate,tss+0x28);
+ REG32(ECX) = READ32(cpustate,tss+0x2c);
+ REG32(EDX) = READ32(cpustate,tss+0x30);
+ REG32(EBX) = READ32(cpustate,tss+0x34);
+ REG32(ESP) = READ32(cpustate,tss+0x38);
+ REG32(EBP) = READ32(cpustate,tss+0x3c);
+ REG32(ESI) = READ32(cpustate,tss+0x40);
+ REG32(EDI) = READ32(cpustate,tss+0x44);
+ cpustate->sreg[ES].selector = READ32(cpustate,tss+0x48) & 0xffff;
+ i386_load_segment_descriptor(cpustate, ES);
+ cpustate->sreg[CS].selector = READ32(cpustate,tss+0x4c) & 0xffff;
+ i386_load_segment_descriptor(cpustate, CS);
+ cpustate->sreg[SS].selector = READ32(cpustate,tss+0x50) & 0xffff;
+ i386_load_segment_descriptor(cpustate, SS);
+ cpustate->sreg[DS].selector = READ32(cpustate,tss+0x54) & 0xffff;
+ i386_load_segment_descriptor(cpustate, DS);
+ cpustate->sreg[FS].selector = READ32(cpustate,tss+0x58) & 0xffff;
+ i386_load_segment_descriptor(cpustate, FS);
+ cpustate->sreg[GS].selector = READ32(cpustate,tss+0x5c) & 0xffff;
+ i386_load_segment_descriptor(cpustate, GS);
+
+ /* Set the busy bit in the new task's descriptor */
+ if(selector & 0x0004)
+ {
+ ar_byte = READ8(cpustate,cpustate->ldtr.base + (selector & ~0x0007) + 5);
+ WRITE8(cpustate,cpustate->ldtr.base + (selector & ~0x0007) + 5,ar_byte | 0x02);
+ }
+ else
+ {
+ ar_byte = READ8(cpustate,cpustate->gdtr.base + (selector & ~0x0007) + 5);
+ WRITE8(cpustate,cpustate->gdtr.base + (selector & ~0x0007) + 5,ar_byte | 0x02);
+ }
+
+ /* For nested tasks, we write the outgoing task's selector to the back-link field of the new TSS,
+ and set the NT flag in the EFLAGS register */
+ if(nested != 0)
+ {
+ WRITE32(cpustate,tss+0,old_task);
+ cpustate->NT = 1;
+ }
+ CHANGE_PC(cpustate,cpustate->eip);
+
+ cpustate->CPL = cpustate->sreg[CS].selector & 0x03;
+ printf("386 Task Switch from selector %04x to %04x\n",old_task,selector);
+}
+
+static void i386_check_irq_line(i386_state *cpustate)
+{
+ /* Check if the interrupts are enabled */
+ if ( (cpustate->irq_state) && cpustate->IF )
+ {
+ cpustate->cycles -= 2;
+ i386_trap(cpustate,cpustate->irq_callback(cpustate->device, 0), 1, 0);
+ }
+}
+
+static void i386_protected_mode_jump(i386_state *cpustate, UINT16 seg, UINT32 off, int indirect, int operand32)
+{
+ I386_SREG desc;
+ I386_CALL_GATE call_gate;
+ UINT8 CPL,DPL,RPL;
+ UINT8 SetRPL = 0;
+ UINT16 segment = seg;
+ UINT32 offset = off;
+
+ /* Check selector is not null */
+ if((segment & ~0x07) == 0)
+ {
+ logerror("JMP: Segment is null.\n");
+ FAULT(FAULT_GP,0)
+ }
+ /* Selector is within descriptor table limit */
+ if((segment & 0x04) == 0)
+ {
+ /* check GDT limit */
+ if((segment & ~0x07) > (cpustate->gdtr.limit))
+ {
+ logerror("JMP: Segment is past GDT limit.\n");
+ FAULT(FAULT_GP,segment & 0xfffc)
+ }
+ }
+ else
+ {
+ /* check LDT limit */
+ if((segment & ~0x07) > (cpustate->ldtr.limit))
+ {
+ logerror("JMP: Segment is past LDT limit.\n");
+ FAULT(FAULT_GP,segment & 0xfffc)
+ }
+ }
+ /* Determine segment type */
+ memset(&desc, 0, sizeof(desc));
+ desc.selector = segment;
+ i386_load_protected_mode_segment(cpustate,&desc);
+ CPL = cpustate->CPL; // current privilege level
+ DPL = (desc.flags >> 5) & 0x03; // descriptor privilege level
+ RPL = segment & 0x03; // requested privilege level
+ if((desc.flags & 0x0018) == 0x0018)
+ {
+ /* code segment */
+ if((desc.flags & 0x0004) == 0)
+ {
+ /* non-conforming */
+ SetRPL = 1;
+ if(RPL > CPL)
+ {
+ logerror("JMP: RPL %i is less than CPL %i\n",RPL,CPL);
+ FAULT(FAULT_GP,segment & 0xfffc)
+ }
+ if(DPL != CPL)
+ {
+ logerror("JMP: DPL %i is not equal CPL %i\n",DPL,CPL);
+ FAULT(FAULT_GP,segment & 0xfffc)
+ }
+ }
+ else
+ {
+ /* conforming */
+ if(DPL > CPL)
+ {
+ logerror("JMP: DPL %i is less than CPL %i\n",DPL,CPL);
+ FAULT(FAULT_GP,segment & 0xfffc)
+ }
+ }
+ if((desc.flags & 0x0080) == 0)
+ {
+ logerror("JMP: Segment is not present\n");
+ FAULT(FAULT_NP,segment & 0xfffc)
+ }
+ if(offset > desc.limit)
+ {
+ logerror("JMP: Offset is past segment limit\n");
+ FAULT(FAULT_GP,0)
+ }
+ }
+ else
+ {
+ if((desc.flags & 0x0010) != 0)
+ {
+ logerror("JMP: Segment is a data segment\n");
+ FAULT(FAULT_GP,segment & 0xfffc) // #GP (cannot execute code in a data segment)
+ }
+ else
+ {
+ switch(desc.flags & 0x000f)
+ {
+ case 0x01: // 286 Available TSS
+ case 0x09: // 386 Available TSS
+ logerror("JMP: Available 386 TSS at %08x\n",cpustate->pc);
+ memset(&desc, 0, sizeof(desc));
+ desc.selector = segment;
+ i386_load_protected_mode_segment(cpustate,&desc);
+ DPL = (desc.flags >> 5) & 0x03; // descriptor privilege level
+ if(DPL < CPL)
+ {
+ logerror("JMP: TSS: DPL %i is less than CPL %i\n",DPL,CPL);
+ FAULT(FAULT_GP,segment & 0xfffc)
+ }
+ if(DPL < RPL)
+ {
+ logerror("JMP: TSS: DPL %i is less than TSS RPL %i\n",DPL,RPL);
+ FAULT(FAULT_GP,segment & 0xfffc)
+ }
+ if((desc.flags & 0x0080) == 0)
+ {
+ logerror("JMP: TSS: Segment is not present\n");
+ FAULT(FAULT_GP,segment & 0xfffc)
+ }
+ if(desc.flags & 0x0008)
+ i386_task_switch(cpustate,desc.selector,0);
+ else
+ i286_task_switch(cpustate,desc.selector,0);
+ return;
+ break;
+ case 0x04: // 286 Call Gate
+ case 0x0c: // 386 Call Gate
+ logerror("JMP: Call gate at %08x\n",cpustate->pc);
+ SetRPL = 1;
+ memset(&call_gate, 0, sizeof(call_gate));
+ call_gate.segment = segment;
+ i386_load_call_gate(cpustate,&call_gate);
+ DPL = call_gate.dpl;
+ if(DPL < CPL)
+ {
+ logerror("JMP: Call Gate: DPL %i is less than CPL %i\n",DPL,CPL);
+ FAULT(FAULT_GP,segment & 0xfffc)
+ }
+ if(DPL < RPL)
+ {
+ logerror("JMP: Call Gate: DPL %i is less than RPL %i\n",DPL,RPL);
+ FAULT(FAULT_GP,segment & 0xfffc)
+ }
+ if((desc.flags & 0x0080) == 0)
+ {
+ logerror("JMP: Call Gate: Segment is not present\n");
+ FAULT(FAULT_NP,segment & 0xfffc)
+ }
+ /* Now we examine the segment that the call gate refers to */
+ if(call_gate.selector == 0)
+ {
+ logerror("JMP: Call Gate: Gate selector is null\n");
+ FAULT(FAULT_GP,0)
+ }
+ if(call_gate.selector & 0x04)
+ {
+ /* check GDT limit */
+ if((call_gate.selector & ~0x07) > cpustate->gdtr.limit)
+ {
+ logerror("JMP: Call Gate: Gate Selector is past GDT segment limit\n");
+ FAULT(FAULT_GP,call_gate.selector & 0xfffc)
+ }
+ }
+ else
+ {
+ /* check LDT limit */
+ if((call_gate.selector & ~0x07) > cpustate->ldtr.limit)
+ {
+ logerror("JMP: Call Gate: Gate Selector is past LDT segment limit\n");
+ FAULT(FAULT_GP,call_gate.selector & 0xfffc)
+ }
+ }
+ desc.selector = call_gate.selector;
+ i386_load_protected_mode_segment(cpustate,&desc);
+ DPL = (desc.flags >> 5) & 0x03;
+ if((desc.flags & 0x0018) != 0x18)
+ {
+ logerror("JMP: Call Gate: Gate does not point to a code segment\n");
+ FAULT(FAULT_GP,call_gate.selector & 0xfffc)
+ }
+ if((desc.flags & 0x0004) == 0)
+ { // non-conforming
+ if(DPL != CPL)
+ {
+ logerror("JMP: Call Gate: Gate DPL does not equal CPL\n");
+ FAULT(FAULT_GP,call_gate.selector & 0xfffc)
+ }
+ }
+ else
+ { // conforming
+ if(DPL > CPL)
+ {
+ logerror("JMP: Call Gate: Gate DPL is greater than CPL\n");
+ FAULT(FAULT_GP,call_gate.selector & 0xfffc)
+ }
+ }
+ if((desc.flags & 0x0080) == 0)
+ {
+ logerror("JMP: Call Gate: Gate Segment is not present\n");
+ FAULT(FAULT_NP,call_gate.selector & 0xfffc)
+ }
+ if(call_gate.offset > desc.limit)
+ {
+ logerror("JMP: Call Gate: Gate offset is past Gate segment limit\n");
+ FAULT(FAULT_GP,call_gate.selector & 0xfffc)
+ }
+ segment = call_gate.selector;
+ offset = call_gate.offset;
+ break;
+ case 0x05: // Task Gate
+ logerror("JMP: Task gate at %08x\n",cpustate->pc);
+ memset(&call_gate, 0, sizeof(call_gate));
+ call_gate.segment = segment;
+ i386_load_call_gate(cpustate,&call_gate);
+ DPL = call_gate.dpl;
+ if(DPL < CPL)
+ {
+ logerror("JMP: Task Gate: Gate DPL %i is less than CPL %i\n",DPL,CPL);
+ FAULT(FAULT_GP,segment & 0xfffc)
+ }
+ if(DPL < RPL)
+ {
+ logerror("JMP: Task Gate: Gate DPL %i is less than CPL %i\n",DPL,CPL);
+ FAULT(FAULT_GP,segment & 0xfffc)
+ }
+ if(call_gate.present == 0)
+ {
+ logerror("JMP: Task Gate: Gate is not present.\n");
+ FAULT(FAULT_GP,segment & 0xfffc)
+ }
+ /* Check the TSS that the task gate points to */
+ desc.selector = call_gate.selector;
+ i386_load_protected_mode_segment(cpustate,&desc);
+ DPL = (desc.flags >> 5) & 0x03; // descriptor privilege level
+ RPL = call_gate.selector & 0x03; // requested privilege level
+ if(call_gate.selector & 0x04)
+ {
+ logerror("JMP: Task Gate TSS: TSS must be global.\n");
+ FAULT(FAULT_GP,call_gate.selector & 0xfffc)
+ }
+ else
+ {
+ if((call_gate.selector & ~0x07) > cpustate->gdtr.limit)
+ {
+ logerror("JMP: Task Gate TSS: TSS is past GDT limit.\n");
+ FAULT(FAULT_GP,call_gate.selector & 0xfffc)
+ }
+ }
+ if((call_gate.ar & 0x000f) == 0x0009 || (call_gate.ar & 0x000f) == 0x0001)
+ {
+ logerror("JMP: Task Gate TSS: Segment is not an available TSS.\n");
+ FAULT(FAULT_GP,call_gate.selector & 0xfffc)
+ }
+ if(call_gate.present == 0)
+ {
+ logerror("JMP: Task Gate TSS: TSS is not present.\n");
+ FAULT(FAULT_NP,call_gate.selector & 0xfffc)
+ }
+ if(call_gate.ar & 0x08)
+ i386_task_switch(cpustate,call_gate.selector,0);
+ else
+ i286_task_switch(cpustate,call_gate.selector,0);
+ return;
+ break;
+ default: // invalid segment type
+ logerror("JMP: Invalid segment type (%i) to jump to.\n",desc.flags & 0x000f);
+ FAULT(FAULT_GP,segment & 0xfffc)
+ }
+ }
+ }
+
+ if(SetRPL != 0)
+ segment = (segment & ~0x03) | cpustate->CPL;
+ if(operand32 == 0)
+ cpustate->eip = offset & 0x0000ffff;
+ else
+ cpustate->eip = offset;
+ cpustate->sreg[CS].selector = segment;
+ cpustate->performed_intersegment_jump = 1;
+ i386_load_segment_descriptor(cpustate,CS);
+ CHANGE_PC(cpustate,cpustate->eip);
+}
+
+static void i386_protected_mode_call(i386_state *cpustate, UINT16 seg, UINT32 off, int indirect, int operand32)
+{
+ I386_SREG desc;
+ I386_CALL_GATE gate;
+ UINT8 SetRPL = 0;
+ UINT8 CPL, DPL, RPL;
+ UINT16 selector = seg;
+ UINT32 offset = off;
+ int x;
+
+ if((selector & ~0x07) == 0)
+ {
+ logerror("CALL: Selector is null.\n");
+ FAULT(FAULT_GP,0) // #GP(0)
+ }
+ if(selector & 0x04)
+ {
+ if((selector & ~0x07) > cpustate->ldtr.limit)
+ {
+ logerror("CALL: Selector is past LDT limit.\n");
+ FAULT(FAULT_GP,selector & ~0x07) // #GP(selector)
+ }
+ }
+ else
+ {
+ if((selector & ~0x07) > cpustate->gdtr.limit)
+ {
+ logerror("CALL: Selector is past GDT limit.\n");
+ FAULT(FAULT_GP,selector & ~0x07) // #GP(selector)
+ }
+ }
+
+ /* Determine segment type */
+ memset(&desc, 0, sizeof(desc));
+ desc.selector = selector;
+ i386_load_protected_mode_segment(cpustate,&desc);
+ CPL = cpustate->CPL; // current privilege level
+ DPL = (desc.flags >> 5) & 0x03; // descriptor privilege level
+ RPL = selector & 0x03; // requested privilege level
+ if((desc.flags & 0x0018) == 0x18) // is a code segment
+ {
+ if(desc.flags & 0x0004)
+ {
+ /* conforming */
+ if(DPL > CPL)
+ {
+ logerror("CALL: Code segment DPL %i is greater than CPL %i\n",DPL,CPL);
+ FAULT(FAULT_GP,selector & ~0x07) // #GP(selector)
+ }
+ }
+ else
+ {
+ /* non-conforming */
+ if(RPL > CPL)
+ {
+ logerror("CALL: RPL %i is greater than CPL %i\n",RPL,CPL);
+ FAULT(FAULT_GP,selector & ~0x07) // #GP(selector)
+ }
+ if(DPL != CPL)
+ {
+ logerror("CALL: Code segment DPL %i is not equal to CPL %i\n",DPL,CPL);
+ FAULT(FAULT_GP,selector & ~0x07) // #GP(selector)
+ }
+ SetRPL = 1;
+ }
+ if((desc.flags & 0x0080) == 0)
+ {
+ logerror("CALL: Code segment is not present.\n");
+ FAULT(FAULT_NP,selector & ~0x07) // #NP(selector)
+ }
+ if (operand32 != 0) // if 32-bit
+ {
+ if(REG32(ESP) < 8)
+ {
+ logerror("CALL: Stack has no room for return address.\n");
+ FAULT(FAULT_SS,0) // #SS(0)
+ }
+ }
+ else
+ {
+ if(REG16(SP) < 4)
+ {
+ logerror("CALL: Stack has no room for return address.\n");
+ FAULT(FAULT_SS,0) // #SS(0)
+ }
+ }
+ if(offset > desc.limit)
+ {
+ logerror("CALL: EIP is past segment limit.\n");
+ FAULT(FAULT_GP,0) // #GP(0)
+ }
+ }
+ else
+ {
+ /* special segment type */
+ if(desc.flags & 0x0010)
+ {
+ logerror("CALL: Segment is a data segment.\n");
+ FAULT(FAULT_GP,desc.selector & ~0x07) // #GP(selector)
+ }
+ else
+ {
+ switch(desc.flags & 0x000f)
+ {
+ case 0x01: // Available 286 TSS
+ case 0x09: // Available 386 TSS
+ logerror("CALL: Available TSS at %08x\n",cpustate->pc);
+ if(DPL < CPL)
+ {
+ logerror("CALL: TSS: DPL is less than CPL.\n");
+ FAULT(FAULT_TS,selector & ~0x07) // #TS(selector)
+ }
+ if(DPL < RPL)
+ {
+ logerror("CALL: TSS: DPL is less than RPL.\n");
+ FAULT(FAULT_TS,selector & ~0x07) // #TS(selector)
+ }
+ if(desc.flags & 0x0002)
+ {
+ logerror("CALL: TSS: TSS is busy.\n");
+ FAULT(FAULT_TS,selector & ~0x07) // #TS(selector)
+ }
+ if(desc.flags & 0x0080)
+ {
+ logerror("CALL: TSS: Segment is not present.\n");
+ FAULT(FAULT_NP,selector & ~0x07) // #NP(selector)
+ }
+ if(desc.flags & 0x08)
+ i386_task_switch(cpustate,desc.selector,1);
+ else
+ i286_task_switch(cpustate,desc.selector,1);
+ return;
+ break;
+ case 0x04: // 286 call gate
+ case 0x0c: // 386 call gate
+ if((desc.flags & 0x000f) == 0x04)
+ operand32 = 0;
+ else
+ operand32 = 1;
+ memset(&gate, 0, sizeof(gate));
+ gate.segment = selector;
+ i386_load_call_gate(cpustate,&gate);
+ DPL = gate.dpl;
+ logerror("CALL: Call gate at %08x (%i parameters)\n",cpustate->pc,gate.dword_count);
+ if(DPL < CPL)
+ {
+ logerror("CALL: Call gate DPL %i is less than CPL %i.\n",DPL,CPL);
+ FAULT(FAULT_GP,desc.selector & ~0x07) // #GP(selector)
+ }
+ if(DPL < RPL)
+ {
+ logerror("CALL: Call gate DPL %i is less than RPL %i.\n",DPL,RPL);
+ FAULT(FAULT_GP,desc.selector & ~0x07) // #GP(selector)
+ }
+ if(gate.present == 0)
+ {
+ logerror("CALL: Call gate is not present.\n");
+ FAULT(FAULT_NP,desc.selector & ~0x07) // #GP(selector)
+ }
+ desc.selector = gate.selector;
+ if((gate.selector & ~0x07) == 0)
+ {
+ logerror("CALL: Call gate: Segment is null.\n");
+ FAULT(FAULT_GP,0) // #GP(0)
+ }
+ if(desc.selector & 0x04)
+ {
+ if((desc.selector & ~0x07) > cpustate->ldtr.limit)
+ {
+ logerror("CALL: Call gate: Segment is past LDT limit\n");
+ FAULT(FAULT_GP,desc.selector & ~0x07) // #GP(selector)
+ }
+ }
+ else
+ {
+ if((desc.selector & ~0x07) > cpustate->gdtr.limit)
+ {
+ logerror("CALL: Call gate: Segment is past GDT limit\n");
+ FAULT(FAULT_GP,desc.selector & ~0x07) // #GP(selector)
+ }
+ }
+ i386_load_protected_mode_segment(cpustate,&desc);
+ if((desc.flags & 0x0018) != 0x18)
+ {
+ logerror("CALL: Call gate: Segment is not a code segment.\n");
+ FAULT(FAULT_GP,desc.selector & ~0x07) // #GP(selector)
+ }
+ DPL = ((desc.flags >> 5) & 0x03);
+ if(DPL > CPL)
+ {
+ logerror("CALL: Call gate: Segment DPL %i is greater than CPL %i.\n",DPL,CPL);
+ FAULT(FAULT_GP,desc.selector & ~0x07) // #GP(selector)
+ }
+ if(DPL < CPL && (desc.flags & 0x0004) == 0)
+ {
+ I386_SREG stack;
+ I386_SREG temp;
+ UINT32 oldSS,oldESP;
+ /* more privilege */
+ /* Check new SS segment for privilege level from TSS */
+ memset(&stack, 0, sizeof(stack));
+ if(operand32 != 0)
+ stack.selector = i386_get_stack_segment(cpustate,DPL);
+ else
+ stack.selector = i286_get_stack_segment(cpustate,DPL);
+ i386_load_protected_mode_segment(cpustate,&stack);
+ if((stack.selector & ~0x07) == 0)
+ {
+ logerror("CALL: Call gate: TSS selector is null\n");
+ FAULT(FAULT_TS,0) // #TS(0)
+ }
+ if(stack.selector & 0x04)
+ {
+ if((stack.selector & ~0x07) > cpustate->ldtr.limit)
+ {
+ logerror("CALL: Call gate: TSS selector is past LDT limit\n");
+ FAULT(FAULT_TS,stack.selector) // #TS(SS selector)
+ }
+ }
+ else
+ {
+ if((stack.selector & ~0x07) > cpustate->gdtr.limit)
+ {
+ logerror("CALL: Call gate: TSS selector is past GDT limit\n");
+ FAULT(FAULT_TS,stack.selector) // #TS(SS selector)
+ }
+ }
+ if((stack.selector & 0x03) != DPL)
+ {
+ logerror("CALL: Call gate: Stack selector RPL does not equal code segment DPL %i\n",DPL);
+ FAULT(FAULT_TS,stack.selector) // #TS(SS selector)
+ }
+ if(((stack.flags >> 5) & 0x03) != DPL)
+ {
+ logerror("CALL: Call gate: Stack DPL does not equal code segment DPL %i\n",DPL);
+ FAULT(FAULT_TS,stack.selector) // #TS(SS selector)
+ }
+ if((stack.flags & 0x0018) != 0x10 && (stack.flags & 0x0002))
+ {
+ logerror("CALL: Call gate: Stack segment is not a writable data segment\n");
+ FAULT(FAULT_TS,stack.selector) // #TS(SS selector)
+ }
+ if((stack.flags & 0x0080) == 0)
+ {
+ logerror("CALL: Call gate: Stack segment is not a writable data segment\n");
+ FAULT(FAULT_SS,stack.selector) // #SS(SS selector)
+ }
+ if(operand32 != 0)
+ {
+ UINT32 newESP = i386_get_stack_ptr(cpustate,DPL);
+ if(newESP < ((gate.dword_count & 0x1f) + 16))
+ {
+ logerror("CALL: Call gate: New stack has no room for 32-bit return address and parameters.\n");
+ FAULT(FAULT_SS,0) // #SS(0)
+ }
+ if(gate.offset > desc.limit)
+ {
+ logerror("CALL: Call gate: EIP is past segment limit.\n");
+ FAULT(FAULT_GP,0) // #GP(0)
+ }
+ }
+ else
+ {
+ UINT32 newESP = i286_get_stack_ptr(cpustate,DPL) & 0x0000ffff;
+ if(newESP < ((gate.dword_count & 0x1f) + 8))
+ {
+ logerror("CALL: Call gate: New stack has no room for 16-bit return address and parameters.\n");
+ FAULT(FAULT_SS,0) // #SS(0)
+ }
+ if((gate.offset & 0xffff) > desc.limit)
+ {
+ logerror("CALL: Call gate: IP is past segment limit.\n");
+ FAULT(FAULT_GP,0) // #GP(0)
+ }
+ }
+ selector = gate.selector;
+ offset = gate.offset;
+
+ /* switch to new stack */
+ oldSS = cpustate->sreg[SS].selector;
+ if(operand32 != 0)
+ {
+ oldESP = REG32(ESP);
+ cpustate->sreg[SS].selector = i386_get_stack_segment(cpustate,gate.selector & 0x03);
+ }
+ else
+ {
+ oldESP = REG16(SP);
+ cpustate->sreg[SS].selector = i286_get_stack_segment(cpustate,gate.selector & 0x03);
+ }
+ i386_load_segment_descriptor(cpustate, SS );
+ if(operand32 != 0)
+ REG32(ESP) = i386_get_stack_ptr(cpustate,gate.selector & 0x03);
+ else
+ REG16(SP) = i286_get_stack_ptr(cpustate,gate.selector & 0x03) & 0x0000ffff;
+
+ if(operand32 != 0)
+ {
+ PUSH32(cpustate,oldSS);
+ PUSH32(cpustate,oldESP);
+ }
+ else
+ {
+ PUSH16(cpustate,oldSS);
+ PUSH16(cpustate,oldESP & 0xffff);
+ }
+
+ memset(&temp, 0, sizeof(temp));
+ temp.selector = oldSS;
+ i386_load_protected_mode_segment(cpustate,&temp);
+ /* copy parameters from old stack to new stack */
+ for(x=(gate.dword_count & 0x1f)-1;x>=0;x--)
+ {
+ UINT32 addr = temp.base + oldESP + (x*2);
+ PUSH16(cpustate,READ16(cpustate,addr));
+ }
+ cpustate->CPL = (stack.flags >> 5) & 0x03;
+ SetRPL = 1;
+ }
+ else
+ {
+ /* same privilege */
+ if (operand32 != 0) // if 32-bit
+ {
+ if(REG32(ESP) < 8)
+ {
+ logerror("CALL: Stack has no room for return address.\n");
+ FAULT(FAULT_SS,0) // #SS(0)
+ }
+ selector = gate.selector;
+ offset = gate.offset;
+ }
+ else
+ {
+ if(REG16(SP) < 4)
+ {
+ logerror("CALL: Stack has no room for return address.\n");
+ FAULT(FAULT_SS,0) // #SS(0)
+ }
+ selector = gate.selector;
+ offset = gate.offset & 0xffff;
+ }
+ if(offset > desc.limit)
+ {
+ logerror("CALL: EIP is past segment limit.\n");
+ FAULT(FAULT_GP,0) // #GP(0)
+ }
+ }
+ break;
+ case 0x05: // task gate
+ logerror("CALL: Task gate at %08x\n",cpustate->pc);
+ memset(&gate, 0, sizeof(gate));
+ gate.segment = selector;
+ i386_load_call_gate(cpustate,&gate);
+ DPL = gate.dpl;
+ if(DPL < CPL)
+ {
+ logerror("CALL: Task Gate: Gate DPL is less than CPL.\n");
+ FAULT(FAULT_TS,selector & ~0x07) // #TS(selector)
+ }
+ if(DPL < RPL)
+ {
+ logerror("CALL: Task Gate: Gate DPL is less than RPL.\n");
+ FAULT(FAULT_TS,selector & ~0x07) // #TS(selector)
+ }
+ if(gate.ar & 0x0080)
+ {
+ logerror("CALL: Task Gate: Gate is not present.\n");
+ FAULT(FAULT_NP,selector & ~0x07) // #NP(selector)
+ }
+ /* Check the TSS that the task gate points to */
+ desc.selector = gate.selector;
+ i386_load_protected_mode_segment(cpustate,&desc);
+ if(gate.selector & 0x04)
+ {
+ logerror("CALL: Task Gate: TSS is not global.\n");
+ FAULT(FAULT_TS,gate.selector & ~0x07) // #TS(selector)
+ }
+ else
+ {
+ if((gate.selector & ~0x07) > cpustate->gdtr.limit)
+ {
+ logerror("CALL: Task Gate: TSS is past GDT limit.\n");
+ FAULT(FAULT_TS,gate.selector & ~0x07) // #TS(selector)
+ }
+ }
+ if(desc.flags & 0x0002)
+ {
+ logerror("CALL: Task Gate: TSS is busy.\n");
+ FAULT(FAULT_TS,gate.selector & ~0x07) // #TS(selector)
+ }
+ if(desc.flags & 0x0080)
+ {
+ logerror("CALL: Task Gate: TSS is not present.\n");
+ FAULT(FAULT_NP,gate.selector & ~0x07) // #TS(selector)
+ }
+ if(desc.flags & 0x08)
+ i386_task_switch(cpustate,desc.selector,1); // with nesting
+ else
+ i286_task_switch(cpustate,desc.selector,1);
+ return;
+ break;
+ default:
+ logerror("CALL: Invalid special segment type (%i) to jump to.\n",desc.flags & 0x000f);
+ FAULT(FAULT_GP,selector & ~0x07) // #GP(selector)
+ }
+ }
+ }
+
+ if(SetRPL != 0)
+ selector = (selector & ~0x03) | cpustate->CPL;
+ if(operand32 == 0)
+ {
+ /* 16-bit operand size */
+ PUSH16(cpustate, cpustate->sreg[CS].selector );
+ PUSH16(cpustate, cpustate->eip & 0x0000ffff );
+ cpustate->sreg[CS].selector = selector;
+ cpustate->performed_intersegment_jump = 1;
+ cpustate->eip = offset;
+ i386_load_segment_descriptor(cpustate,CS);
+ }
+ else
+ {
+ /* 32-bit operand size */
+ PUSH32(cpustate, cpustate->sreg[CS].selector );
+ PUSH32(cpustate, cpustate->eip );
+ cpustate->sreg[CS].selector = selector;
+ cpustate->performed_intersegment_jump = 1;
+ cpustate->eip = offset;
+ i386_load_segment_descriptor(cpustate, CS );
+ }
+ CHANGE_PC(cpustate,cpustate->eip);
+}
+
+static void i386_protected_mode_retf(i386_state* cpustate, UINT8 count, UINT8 operand32)
+{
+ UINT32 newCS, newEIP;
+ UINT32 newSS, newESP; // when changing privilege
+ I386_SREG desc;
+ UINT8 CPL, RPL, DPL;
+
+ if(operand32 == 0)
+ {
+ newEIP = POP16(cpustate) & 0xffff;
+ newCS = POP16(cpustate) & 0xffff;
+ REG16(SP) += count;
+ }
+ else
+ {
+ newEIP = POP32(cpustate);
+ newCS = POP32(cpustate) & 0xffff;
+ REG32(ESP) += count;
+ }
+
+ memset(&desc, 0, sizeof(desc));
+ desc.selector = newCS;
+ i386_load_protected_mode_segment(cpustate,&desc);
+ CPL = cpustate->CPL; // current privilege level
+ DPL = (desc.flags >> 5) & 0x03; // descriptor privilege level
+ RPL = newCS & 0x03;
+
+ if(RPL < CPL)
+ {
+ logerror("RETF: Return segment RPL is less than CPL.\n");
+ FAULT(FAULT_GP,newCS & ~0x07)
+ }
+
+ if(RPL == CPL)
+ {
+ /* same privilege level */
+ if((newCS & ~0x07) == 0)
+ {
+ logerror("RETF: Return segment RPL is less than CPL.\n");
+ FAULT(FAULT_GP,0)
+ }
+ if(newCS & 0x04)
+ {
+ if((newCS & ~0x07) > cpustate->ldtr.limit)
+ {
+ logerror("RETF: Return segment is past LDT limit.\n");
+ FAULT(FAULT_GP,newCS & ~0x07)
+ }
+ }
+ else
+ {
+ if((newCS & ~0x07) > cpustate->gdtr.limit)
+ {
+ logerror("RETF: Return segment is past GDT limit.\n");
+ FAULT(FAULT_GP,newCS & ~0x07)
+ }
+ }
+ if((desc.flags & 0x0018) != 0x0018)
+ {
+ logerror("RETF: Return segment is not a code segment.\n");
+ FAULT(FAULT_GP,newCS & ~0x07)
+ }
+ if(desc.flags & 0x0004)
+ {
+ if(DPL > CPL)
+ {
+ logerror("RETF: Conforming code segment DPL is greater than CPL.\n");
+ FAULT(FAULT_GP,newCS & ~0x07)
+ }
+ }
+ else
+ {
+ if(DPL != CPL)
+ {
+ logerror("RETF: Non-conforming code segment DPL does not equal CPL.\n");
+ FAULT(FAULT_GP,newCS & ~0x07)
+ }
+ }
+ if((desc.flags & 0x0080) == 0)
+ {
+ logerror("RETF: Code segment is not present.\n");
+ FAULT(FAULT_NP,newCS & ~0x07)
+ }
+ if(newEIP > desc.limit)
+ {
+ logerror("RETF: EIP is past code segment limit.\n");
+ FAULT(FAULT_GP,0)
+ }
+ if(operand32 == 0)
+ {
+ if(REG16(SP) > (cpustate->sreg[SS].limit & 0xffff))
+ {
+ logerror("RETF: SP is past stack segment limit.\n");
+ FAULT(FAULT_SS,0)
+ }
+ }
+ else
+ {
+ if(REG32(ESP) > cpustate->sreg[SS].limit)
+ {
+ logerror("RETF: ESP is past stack segment limit.\n");
+ FAULT(FAULT_SS,0)
+ }
+ }
+ }
+ else if(RPL > CPL)
+ {
+ /* outer privilege level */
+ if(operand32 == 0)
+ {
+ newESP = POP16(cpustate) & 0xffff;
+ newSS = POP16(cpustate);
+ if(newESP+8+count > cpustate->sreg[SS].limit)
+ {
+ logerror("RETF: SP is past stack segment limit.\n");
+ FAULT(FAULT_SS,0)
+ }
+ }
+ else
+ {
+ newESP = POP32(cpustate);
+ newSS = POP32(cpustate);
+ if(newESP+16+count > cpustate->sreg[SS].limit)
+ {
+ logerror("RETF: ESP is past stack segment limit.\n");
+ FAULT(FAULT_SS,0)
+ }
+ }
+
+ /* Check CS selector and descriptor */
+ if((newCS & ~0x07) == 0)
+ {
+ logerror("RETF: CS segment is null.\n");
+ FAULT(FAULT_GP,0)
+ }
+ if(newCS & 0x04)
+ {
+ if((newCS & ~0x07) > cpustate->ldtr.limit)
+ {
+ logerror("RETF: CS segment selector is past LDT limit.\n");
+ FAULT(FAULT_GP,newCS & ~0x07)
+ }
+ }
+ else
+ {
+ if((newCS & ~0x07) > cpustate->gdtr.limit)
+ {
+ logerror("RETF: CS segment selector is past GDT limit.\n");
+ FAULT(FAULT_GP,newCS & ~0x07)
+ }
+ }
+ if((desc.flags & 0x0018) != 0x0018)
+ {
+ logerror("RETF: CS segment is not a code segment.\n");
+ FAULT(FAULT_GP,newCS & ~0x07)
+ }
+ if(desc.flags & 0x0004)
+ {
+ if(DPL > RPL)
+ {
+ logerror("RETF: Conforming CS segment DPL is greater than return selector RPL.\n");
+ FAULT(FAULT_GP,newCS & ~0x07)
+ }
+ }
+ else
+ {
+ if(DPL != RPL)
+ {
+ logerror("RETF: Non-conforming CS segment DPL is not equal to return selector RPL.\n");
+ FAULT(FAULT_GP,newCS & ~0x07)
+ }
+ }
+ if((desc.flags & 0x0080) == 0)
+ {
+ logerror("RETF: CS segment is not present.\n");
+ FAULT(FAULT_NP,newCS & ~0x07)
+ }
+ if(newEIP > desc.limit)
+ {
+ logerror("RETF: EIP is past return CS segment limit.\n");
+ FAULT(FAULT_GP,0)
+ }
+ /* Check SS selector and descriptor */
+ desc.selector = newSS;
+ i386_load_protected_mode_segment(cpustate,&desc);
+ DPL = (desc.flags >> 5) & 0x03; // descriptor privilege level
+ if((newSS & ~0x07) == 0)
+ {
+ logerror("RETF: SS segment is null.\n");
+ FAULT(FAULT_GP,0)
+ }
+ if(newSS & 0x04)
+ {
+ if((newSS & ~0x07) > cpustate->ldtr.limit)
+ {
+ logerror("RETF: SS segment selector is past LDT limit.\n");
+ FAULT(FAULT_GP,newSS & ~0x07)
+ }
+ }
+ else
+ {
+ if((newSS & ~0x07) > cpustate->gdtr.limit)
+ {
+ logerror("RETF: SS segment selector is past GDT limit.\n");
+ FAULT(FAULT_GP,newSS & ~0x07)
+ }
+ }
+ if((newSS & 0x03) != RPL)
+ {
+ logerror("RETF: SS segment RPL is not equal to CS segment RPL.\n");
+ FAULT(FAULT_GP,newSS & ~0x07)
+ }
+ if((desc.flags & 0x0018) != 0x0010 || (desc.flags & 0x0002) == 0)
+ {
+ logerror("RETF: SS segment is not a writable data segment.\n");
+ FAULT(FAULT_GP,newSS & ~0x07)
+ }
+ if(((desc.flags >> 5) & 0x03) != RPL)
+ {
+ logerror("RETF: SS DPL is not equal to CS segment RPL.\n");
+ FAULT(FAULT_GP,newSS & ~0x07)
+ }
+ if((desc.flags & 0x0080) == 0)
+ {
+ logerror("RETF: SS segment is not present.\n");
+ FAULT(FAULT_GP,newSS & ~0x07)
+ }
+ cpustate->CPL = newCS & 0x03;
+
+ /* Load new SS:(E)SP */
+ if(operand32 == 0)
+ REG16(SP) = newESP & 0xffff;
+ else
+ REG32(ESP) = newESP;
+ cpustate->sreg[SS].selector = newSS;
+ i386_load_segment_descriptor(cpustate, SS );
+
+ if(operand32 == 0)
+ REG16(SP) += count;
+ else
+ REG32(ESP) += count;
+
+ /* Check that DS, ES, FS and GS are valid for the new privilege level */
+ i386_check_sreg_validity(cpustate,DS);
+ i386_check_sreg_validity(cpustate,ES);
+ i386_check_sreg_validity(cpustate,FS);
+ i386_check_sreg_validity(cpustate,GS);
+ }
+
+ /* Load new CS:(E)IP */
+ if(operand32 == 0)
+ cpustate->eip = newEIP & 0xffff;
+ else
+ cpustate->eip = newEIP;
+ cpustate->sreg[CS].selector = newCS;
+ i386_load_segment_descriptor(cpustate, CS );
+ CHANGE_PC(cpustate,cpustate->eip);
+}
+
+static void i386_protected_mode_iret(i386_state* cpustate, int operand32)
+{
+ UINT32 newCS, newEIP;
+ UINT32 newSS, newESP; // when changing privilege
+ I386_SREG desc;
+ UINT8 CPL, RPL, DPL;
+ UINT32 newflags;
+
+ CPL = cpustate->CPL;
+ if(operand32 == 0)
+ {
+ newEIP = POP16(cpustate);
+ newCS = POP16(cpustate);
+ newflags = POP16(cpustate);
+ }
+ else
+ {
+ newEIP = POP32(cpustate);
+ newCS = POP32(cpustate) & 0xffff;
+ newflags = POP32(cpustate);
+ }
+
+ if(V8086_MODE)
+ {
+ logerror("IRET: Is in Virtual 8086 mode.\n");
+ FAULT(FAULT_GP,0)
+ }
+ else if(NESTED_TASK)
+ {
+ UINT32 task = READ32(cpustate,cpustate->task.base);
+ /* Task Return */
+ popmessage("IRET: Nested task return.");
+ /* Check back-link selector in TSS */
+ if(task & 0x04)
+ {
+ logerror("IRET: Task return: Back-linked TSS is not in GDT.\n");
+ FAULT(FAULT_TS,task & ~0x07)
+ }
+ if((task & ~0x07) > cpustate->gdtr.limit)
+ {
+ logerror("IRET: Task return: Back-linked TSS is not in GDT.\n");
+ FAULT(FAULT_TS,task & ~0x07)
+ }
+ memset(&desc, 0, sizeof(desc));
+ desc.selector = task;
+ i386_load_protected_mode_segment(cpustate,&desc);
+ if((desc.flags & 0x001f) != 0x000b)
+ {
+ logerror("IRET: Task return: Back-linked TSS is not a busy TSS.\n");
+ FAULT(FAULT_TS,task & ~0x07)
+ }
+ if((desc.flags & 0x0080) == 0)
+ {
+ logerror("IRET: Task return: Back-linked TSS is not present.\n");
+ FAULT(FAULT_NP,task & ~0x07)
+ }
+ if(desc.flags & 0x08)
+ i386_task_switch(cpustate,desc.selector,0);
+ else
+ i286_task_switch(cpustate,desc.selector,0);
+ return;
+ }
+ else
+ {
+ if(newflags & 0x00020000) // if returning to virtual 8086 mode
+ {
+ /* Return to v86 mode */
+ popmessage("IRET: Unimplemented return to Virtual 8086 mode.");
+ }
+ else
+ {
+ if(operand32 == 0)
+ {
+ if(REG16(SP)+4 > cpustate->sreg[SS].limit)
+ {
+ logerror("IRET: Data on stack is past SS limit.\n");
+ FAULT(FAULT_SS,0)
+ }
+ }
+ else
+ {
+ if(REG32(ESP)+6 > cpustate->sreg[SS].limit)
+ {
+ logerror("IRET: Data on stack is past SS limit.\n");
+ FAULT(FAULT_SS,0)
+ }
+ }
+ RPL = newCS & 0x03;
+ if(RPL < CPL)
+ {
+ logerror("IRET: Return CS RPL is less than CPL.\n");
+ FAULT(FAULT_GP,newCS & ~0x07)
+ }
+ if(RPL == CPL)
+ {
+ /* return to same privilege level */
+ if(operand32 == 0)
+ {
+ if(REG16(SP)+6 > cpustate->sreg[SS].limit)
+ {
+ logerror("IRET: Data on stack is past SS limit.\n");
+ FAULT(FAULT_SS,0)
+ }
+ }
+ else
+ {
+ if(REG32(ESP)+12 > cpustate->sreg[SS].limit)
+ {
+ logerror("IRET: Data on stack is past SS limit.\n");
+ FAULT(FAULT_SS,0)
+ }
+ }
+ if((newCS & ~0x07) == 0)
+ {
+ logerror("IRET: Return CS selector is null.\n");
+ FAULT(FAULT_GP,0)
+ }
+ if(newCS & 0x04)
+ {
+ if((newCS & ~0x07) > cpustate->ldtr.limit)
+ {
+ logerror("IRET: Return CS selector (%04x) is past LDT limit.\n",newCS);
+ FAULT(FAULT_GP,newCS & ~0x07)
+ }
+ }
+ else
+ {
+ if((newCS & ~0x07) > cpustate->gdtr.limit)
+ {
+ logerror("IRET: Return CS selector is past GDT limit.\n");
+ FAULT(FAULT_GP,newCS & ~0x07)
+ }
+ }
+ memset(&desc, 0, sizeof(desc));
+ desc.selector = newCS;
+ i386_load_protected_mode_segment(cpustate,&desc);
+ DPL = (desc.flags >> 5) & 0x03; // descriptor privilege level
+ RPL = newCS & 0x03;
+ if((desc.flags & 0x0018) != 0x0018)
+ {
+ logerror("IRET: Return CS segment is not a code segment.\n");
+ FAULT(FAULT_GP,newCS & ~0x07)
+ }
+ if(desc.flags & 0x0004)
+ {
+ if(DPL > CPL)
+ {
+ logerror("IRET: Conforming return CS DPL is greater than CPL.\n");
+ FAULT(FAULT_GP,newCS & ~0x07)
+ }
+ }
+ else
+ {
+ if(DPL != CPL)
+ {
+ logerror("IRET: Non-conforming return CS DPL is not equal to CPL.\n");
+ FAULT(FAULT_GP,newCS & ~0x07)
+ }
+ }
+ if((desc.flags & 0x0080) == 0)
+ {
+ logerror("IRET: Return CS segment is not present.\n");
+ FAULT(FAULT_NP,newCS & ~0x07)
+ }
+ if(newEIP > desc.limit)
+ {
+ logerror("IRET: Return EIP is past return CS limit.\n");
+ FAULT(FAULT_GP,0) }
+
+ if(operand32 == 0)
+ {
+ cpustate->eip = newEIP;
+ cpustate->sreg[CS].selector = newCS;
+ set_flags(cpustate,newflags);
+ }
+ else
+ {
+ cpustate->eip = newEIP;
+ cpustate->sreg[CS].selector = newCS & 0xffff;
+ set_flags(cpustate,newflags);
+ }
+ }
+ else if(RPL > CPL)
+ {
+ I386_SREG stack;
+ /* return to outer privilege level */
+ if(operand32 == 0)
+ {
+ newESP = POP16(cpustate);
+ newSS = POP16(cpustate);
+ if(REG16(SP) > cpustate->sreg[SS].limit)
+ {
+ logerror("IRET: ESP is past SS limit.\n");
+ FAULT(FAULT_SS,0) }
+ }
+ else
+ {
+ newESP = POP32(cpustate);
+ newSS = POP32(cpustate) & 0xffff;
+ if(REG32(ESP) > cpustate->sreg[SS].limit)
+ {
+ logerror("IRET: ESP is past SS limit.\n");
+ FAULT(FAULT_SS,0)
+ }
+ }
+ memset(&desc, 0, sizeof(desc));
+ desc.selector = newCS;
+ i386_load_protected_mode_segment(cpustate,&desc);
+ DPL = (desc.flags >> 5) & 0x03; // descriptor privilege level
+ RPL = newCS & 0x03;
+ memset(&stack, 0, sizeof(stack));
+ stack.selector = newSS;
+ i386_load_protected_mode_segment(cpustate,&stack);
+ /* Check CS selector and descriptor */
+ if((newCS & ~0x07) == 0)
+ {
+ logerror("IRET: Return CS selector is null.\n");
+ FAULT(FAULT_GP,0)
+ }
+ if(newCS & 0x04)
+ {
+ if((newCS & ~0x07) > cpustate->ldtr.limit)
+ {
+ logerror("IRET: Return CS selector is past LDT limit.\n");
+ FAULT(FAULT_GP,newCS & ~0x07);
+ }
+ }
+ else
+ {
+ if((newCS & ~0x07) > cpustate->gdtr.limit)
+ {
+ logerror("IRET: Return CS selector is past GDT limit.\n");
+ FAULT(FAULT_GP,newCS & ~0x07);
+ }
+ }
+ if((desc.flags & 0x0018) != 0x0018)
+ {
+ logerror("IRET: Return CS segment is not a code segment.\n");
+ FAULT(FAULT_GP,newCS & ~0x07)
+ }
+ if(desc.flags & 0x0004)
+ {
+ if(DPL <= CPL)
+ {
+ logerror("IRET: Conforming return CS DPL is not greater than CPL.\n");
+ FAULT(FAULT_GP,newCS & ~0x07)
+ }
+ }
+ else
+ {
+ if(DPL != RPL)
+ {
+ logerror("IRET: Non-conforming return CS DPL does not equal CS RPL.\n");
+ FAULT(FAULT_GP,newCS & ~0x07)
+ }
+ }
+ if((desc.flags & 0x0080) == 0)
+ {
+ logerror("IRET: Return CS segment is not present.\n");
+ FAULT(FAULT_NP,newCS & ~0x07)
+ }
+
+ /* Check SS selector and descriptor */
+ DPL = (stack.flags >> 5) & 0x03;
+ if((newSS & ~0x07) == 0)
+ {
+ logerror("IRET: Return SS selector is null.\n");
+ FAULT(FAULT_GP,0)
+ }
+ if(newSS & 0x04)
+ {
+ if((newSS & ~0x07) > cpustate->ldtr.limit)
+ {
+ logerror("IRET: Return SS selector is past LDT limit.\n");
+ FAULT(FAULT_GP,newSS & ~0x07);
+ }
+ }
+ else
+ {
+ if((newSS & ~0x07) > cpustate->gdtr.limit)
+ {
+ logerror("IRET: Return SS selector is past GDT limit.\n");
+ FAULT(FAULT_GP,newSS & ~0x07);
+ }
+ }
+ if((newSS & 0x03) != RPL)
+ {
+ logerror("IRET: Return SS RPL is not equal to return CS RPL.\n");
+ FAULT(FAULT_GP,newSS & ~0x07)
+ }
+ if((stack.flags & 0x0018) != 0x0010)
+ {
+ logerror("IRET: Return SS segment is not a data segment.\n");
+ FAULT(FAULT_GP,newSS & ~0x07)
+ }
+ if((stack.flags & 0x0002) == 0)
+ {
+ logerror("IRET: Return SS segment is not writable.\n");
+ FAULT(FAULT_GP,newSS & ~0x07)
+ }
+ if(DPL != RPL)
+ {
+ logerror("IRET: Return SS DPL does not equal SS RPL.\n");
+ FAULT(FAULT_GP,newSS & ~0x07)
+ }
+ if((stack.flags & 0x0080) == 0)
+ {
+ logerror("IRET: Return SS segment is not present.\n");
+ FAULT(FAULT_NP,newSS & ~0x07)
+ }
+ if(newEIP > desc.limit)
+ {
+ logerror("IRET: EIP is past return CS limit.\n");
+ FAULT(FAULT_GP,0)
+ }
+
+ if(operand32 == 0)
+ {
+ cpustate->eip = newEIP & 0xffff;
+ cpustate->sreg[CS].selector = newCS;
+ set_flags(cpustate,newflags);
+ REG16(SP) = newESP & 0xffff;
+ cpustate->sreg[SS].selector = newSS;
+ }
+ else
+ {
+ cpustate->eip = newEIP;
+ cpustate->sreg[CS].selector = newCS & 0xffff;
+ set_flags(cpustate,newflags);
+ REG32(ESP) = newESP;
+ cpustate->sreg[SS].selector = newSS & 0xffff;
+ }
+ cpustate->CPL = newCS & 0x03;
+ i386_load_segment_descriptor(cpustate,SS);
+
+ /* Check that DS, ES, FS and GS are valid for the new privilege level */
+ i386_check_sreg_validity(cpustate,DS);
+ i386_check_sreg_validity(cpustate,ES);
+ i386_check_sreg_validity(cpustate,FS);
+ i386_check_sreg_validity(cpustate,GS);
+ }
+ }
+ }
+
+ i386_load_segment_descriptor(cpustate,CS);
+ CHANGE_PC(cpustate,cpustate->eip);
+}
+
+#include "cycles.h"
+
+static UINT8 *cycle_table_rm[X86_NUM_CPUS];
+static UINT8 *cycle_table_pm[X86_NUM_CPUS];
+
+#define CYCLES_NUM(x) (cpustate->cycles -= (x))
+
+INLINE void CYCLES(i386_state *cpustate,int x)
+{
+ if (PROTECTED_MODE)
+ {
+ cpustate->cycles -= cpustate->cycle_table_pm[x];
+ }
+ else
+ {
+ cpustate->cycles -= cpustate->cycle_table_rm[x];
+ }
+}
+
+INLINE void CYCLES_RM(i386_state *cpustate,int modrm, int r, int m)
+{
+ if (modrm >= 0xc0)
+ {
+ if (PROTECTED_MODE)
+ {
+ cpustate->cycles -= cpustate->cycle_table_pm[r];
+ }
+ else
+ {
+ cpustate->cycles -= cpustate->cycle_table_rm[r];
+ }
+ }
+ else
+ {
+ if (PROTECTED_MODE)
+ {
+ cpustate->cycles -= cpustate->cycle_table_pm[m];
+ }
+ else
+ {
+ cpustate->cycles -= cpustate->cycle_table_rm[m];
+ }
+ }
+}
+
+static void build_cycle_table(running_machine &machine)
+{
+ int i, j;
+ for (j=0; j < X86_NUM_CPUS; j++)
+ {
+ cycle_table_rm[j] = auto_alloc_array(machine, UINT8, CYCLES_NUM_OPCODES);
+ cycle_table_pm[j] = auto_alloc_array(machine, UINT8, CYCLES_NUM_OPCODES);
+
+ for (i=0; i < sizeof(x86_cycle_table)/sizeof(X86_CYCLE_TABLE); i++)
+ {
+ int opcode = x86_cycle_table[i].op;
+ cycle_table_rm[j][opcode] = x86_cycle_table[i].cpu_cycles[j][0];
+ cycle_table_pm[j][opcode] = x86_cycle_table[i].cpu_cycles[j][1];
+ }
+ }
+}
+
+/* Forward declarations */
+static void I386OP(decode_opcode)(i386_state *cpustate);
+static void I386OP(decode_two_byte)(i386_state *cpustate);
+
+
+
+#include "i386ops.c"
+#include "i386op16.c"
+#include "i386op32.c"
+#include "i486ops.c"
+#include "pentops.c"
+#include "x87ops.c"
+#include "i386ops.h"
+
+static void I386OP(decode_opcode)(i386_state *cpustate)
+{
+ cpustate->opcode = FETCH(cpustate);
+ if( cpustate->operand_size )
+ cpustate->opcode_table1_32[cpustate->opcode](cpustate);
+ else
+ cpustate->opcode_table1_16[cpustate->opcode](cpustate);
+}
+
+/* Two-byte opcode prefix */
+static void I386OP(decode_two_byte)(i386_state *cpustate)
+{
+ cpustate->opcode = FETCH(cpustate);
+ if( cpustate->operand_size )
+ cpustate->opcode_table2_32[cpustate->opcode](cpustate);
+ else
+ cpustate->opcode_table2_16[cpustate->opcode](cpustate);
+}
+
+/*************************************************************************/
+
+static UINT64 i386_debug_segbase(symbol_table &table, void *ref, int params, const UINT64 *param)
+{
+ legacy_cpu_device *device = (legacy_cpu_device *)ref;
+ i386_state *cpustate = get_safe_token(device);
+ UINT32 result;
+ I386_SREG seg;
+
+ if (PROTECTED_MODE)
+ {
+ memset(&seg, 0, sizeof(seg));
+ seg.selector = (UINT16) param[0];
+ i386_load_protected_mode_segment(cpustate,&seg);
+ result = seg.base;
+ }
+ else
+ {
+ result = param[0] << 4;
+ }
+ return result;
+}
+
+static UINT64 i386_debug_seglimit(symbol_table &table, void *ref, int params, const UINT64 *param)
+{
+ legacy_cpu_device *device = (legacy_cpu_device *)ref;
+ i386_state *cpustate = get_safe_token(device);
+ UINT32 result = 0;
+ I386_SREG seg;
+
+ if (PROTECTED_MODE)
+ {
+ memset(&seg, 0, sizeof(seg));
+ seg.selector = (UINT16) param[0];
+ i386_load_protected_mode_segment(cpustate,&seg);
+ result = seg.limit;
+ }
+ return result;
+}
+
+static CPU_DEBUG_INIT( i386 )
+{
+ device->debug()->symtable().add("segbase", (void *)device, 1, 1, i386_debug_segbase);
+ device->debug()->symtable().add("seglimit", (void *)device, 1, 1, i386_debug_seglimit);
+}
+
+/*************************************************************************/
+
+static void i386_postload(i386_state *cpustate)
+{
+ int i;
+ for (i = 0; i < 6; i++)
+ i386_load_segment_descriptor(cpustate,i);
+ CHANGE_PC(cpustate,cpustate->eip);
+}
+
+static CPU_INIT( i386 )
+{
+ int i, j;
+ static const int regs8[8] = {AL,CL,DL,BL,AH,CH,DH,BH};
+ static const int regs16[8] = {AX,CX,DX,BX,SP,BP,SI,DI};
+ static const int regs32[8] = {EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI};
+ i386_state *cpustate = get_safe_token(device);
+
+ build_cycle_table(device->machine());
+
+ for( i=0; i < 256; i++ ) {
+ int c=0;
+ for( j=0; j < 8; j++ ) {
+ if( i & (1 << j) )
+ c++;
+ }
+ i386_parity_table[i] = ~(c & 0x1) & 0x1;
+ }
+
+ for( i=0; i < 256; i++ ) {
+ i386_MODRM_table[i].reg.b = regs8[(i >> 3) & 0x7];
+ i386_MODRM_table[i].reg.w = regs16[(i >> 3) & 0x7];
+ i386_MODRM_table[i].reg.d = regs32[(i >> 3) & 0x7];
+
+ i386_MODRM_table[i].rm.b = regs8[i & 0x7];
+ i386_MODRM_table[i].rm.w = regs16[i & 0x7];
+ i386_MODRM_table[i].rm.d = regs32[i & 0x7];
+ }
+
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+ cpustate->io = device->space(AS_IO);
+
+ device->save_item(NAME( cpustate->reg.d));
+ device->save_item(NAME(cpustate->sreg[ES].selector));
+ device->save_item(NAME(cpustate->sreg[ES].base));
+ device->save_item(NAME(cpustate->sreg[ES].limit));
+ device->save_item(NAME(cpustate->sreg[ES].flags));
+ device->save_item(NAME(cpustate->sreg[CS].selector));
+ device->save_item(NAME(cpustate->sreg[CS].base));
+ device->save_item(NAME(cpustate->sreg[CS].limit));
+ device->save_item(NAME(cpustate->sreg[CS].flags));
+ device->save_item(NAME(cpustate->sreg[SS].selector));
+ device->save_item(NAME(cpustate->sreg[SS].base));
+ device->save_item(NAME(cpustate->sreg[SS].limit));
+ device->save_item(NAME(cpustate->sreg[SS].flags));
+ device->save_item(NAME(cpustate->sreg[DS].selector));
+ device->save_item(NAME(cpustate->sreg[DS].base));
+ device->save_item(NAME(cpustate->sreg[DS].limit));
+ device->save_item(NAME(cpustate->sreg[DS].flags));
+ device->save_item(NAME(cpustate->sreg[FS].selector));
+ device->save_item(NAME(cpustate->sreg[FS].base));
+ device->save_item(NAME(cpustate->sreg[FS].limit));
+ device->save_item(NAME(cpustate->sreg[FS].flags));
+ device->save_item(NAME(cpustate->sreg[GS].selector));
+ device->save_item(NAME(cpustate->sreg[GS].base));
+ device->save_item(NAME(cpustate->sreg[GS].limit));
+ device->save_item(NAME(cpustate->sreg[GS].flags));
+ device->save_item(NAME(cpustate->eip));
+ device->save_item(NAME(cpustate->prev_eip));
+ device->save_item(NAME(cpustate->CF));
+ device->save_item(NAME(cpustate->DF));
+ device->save_item(NAME(cpustate->SF));
+ device->save_item(NAME(cpustate->OF));
+ device->save_item(NAME(cpustate->ZF));
+ device->save_item(NAME(cpustate->PF));
+ device->save_item(NAME(cpustate->AF));
+ device->save_item(NAME(cpustate->IF));
+ device->save_item(NAME(cpustate->TF));
+ device->save_item(NAME( cpustate->cr));
+ device->save_item(NAME( cpustate->dr));
+ device->save_item(NAME( cpustate->tr));
+ device->save_item(NAME(cpustate->idtr.base));
+ device->save_item(NAME(cpustate->idtr.limit));
+ device->save_item(NAME(cpustate->gdtr.base));
+ device->save_item(NAME(cpustate->gdtr.limit));
+ device->save_item(NAME(cpustate->task.base));
+ device->save_item(NAME(cpustate->task.segment));
+ device->save_item(NAME(cpustate->task.limit));
+ device->save_item(NAME(cpustate->task.flags));
+ device->save_item(NAME(cpustate->ldtr.base));
+ device->save_item(NAME(cpustate->ldtr.segment));
+ device->save_item(NAME(cpustate->ldtr.limit));
+ device->save_item(NAME(cpustate->ldtr.flags));
+ device->save_item(NAME(cpustate->irq_state));
+ device->save_item(NAME(cpustate->performed_intersegment_jump));
+ device->machine().save().register_postload(save_prepost_delegate(FUNC(i386_postload), cpustate));
+}
+
+static void build_opcode_table(i386_state *cpustate, UINT32 features)
+{
+ int i;
+ for (i=0; i < 256; i++)
+ {
+ cpustate->opcode_table1_16[i] = I386OP(invalid);
+ cpustate->opcode_table1_32[i] = I386OP(invalid);
+ cpustate->opcode_table2_16[i] = I386OP(invalid);
+ cpustate->opcode_table2_32[i] = I386OP(invalid);
+ }
+
+ for (i=0; i < sizeof(x86_opcode_table)/sizeof(X86_OPCODE); i++)
+ {
+ const X86_OPCODE *op = &x86_opcode_table[i];
+
+ if ((op->flags & features))
+ {
+ if (op->flags & OP_2BYTE)
+ {
+ cpustate->opcode_table2_32[op->opcode] = op->handler32;
+ cpustate->opcode_table2_16[op->opcode] = op->handler16;
+ }
+ else
+ {
+ cpustate->opcode_table1_32[op->opcode] = op->handler32;
+ cpustate->opcode_table1_16[op->opcode] = op->handler16;
+ }
+ }
+ }
+}
+
+static CPU_RESET( i386 )
+{
+ i386_state *cpustate = get_safe_token(device);
+ device_irq_callback save_irqcallback;
+
+ save_irqcallback = cpustate->irq_callback;
+ memset( cpustate, 0, sizeof(*cpustate) );
+ cpustate->irq_callback = save_irqcallback;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+ cpustate->io = device->space(AS_IO);
+
+ cpustate->sreg[CS].selector = 0xf000;
+ cpustate->sreg[CS].base = 0xffff0000;
+ cpustate->sreg[CS].limit = 0xffff;
+
+ cpustate->sreg[DS].base = cpustate->sreg[ES].base = cpustate->sreg[FS].base = cpustate->sreg[GS].base = cpustate->sreg[SS].base = 0x00000000;
+ cpustate->sreg[DS].limit = cpustate->sreg[ES].limit = cpustate->sreg[FS].limit = cpustate->sreg[GS].limit = cpustate->sreg[SS].limit = 0xffff;
+ cpustate->sreg[DS].flags = cpustate->sreg[ES].flags = cpustate->sreg[FS].flags = cpustate->sreg[GS].flags = cpustate->sreg[SS].flags = 0x0092;
+
+ cpustate->idtr.base = 0;
+ cpustate->idtr.limit = 0x3ff;
+
+ cpustate->a20_mask = ~0;
+
+ cpustate->cr[0] = 0x7fffffe0; // reserved bits set to 1
+ cpustate->eflags = 0;
+ cpustate->eflags_mask = 0x00030000;
+ cpustate->eip = 0xfff0;
+
+ // [11:8] Family
+ // [ 7:4] Model
+ // [ 3:0] Stepping ID
+ // Family 3 (386), Model 0 (DX), Stepping 8 (D1)
+ REG32(EAX) = 0;
+ REG32(EDX) = (3 << 8) | (0 << 4) | (8);
+
+ cpustate->CPL = 0;
+
+ build_opcode_table(cpustate, OP_I386);
+ cpustate->cycle_table_rm = cycle_table_rm[CPU_CYCLES_I386];
+ cpustate->cycle_table_pm = cycle_table_pm[CPU_CYCLES_I386];
+
+ CHANGE_PC(cpustate,cpustate->eip);
+}
+
+static void i386_set_irq_line(i386_state *cpustate,int irqline, int state)
+{
+ if (state != CLEAR_LINE && cpustate->halted)
+ {
+ cpustate->halted = 0;
+ }
+
+ if ( irqline == INPUT_LINE_NMI )
+ {
+ /* NMI (I do not think that this is 100% right) */
+ if ( state )
+ i386_trap(cpustate,2, 1, 0);
+ }
+ else
+ {
+ cpustate->irq_state = state;
+ }
+}
+
+static void i386_set_a20_line(i386_state *cpustate,int state)
+{
+ if (state)
+ {
+ cpustate->a20_mask = ~0;
+ }
+ else
+ {
+ cpustate->a20_mask = ~(1 << 20);
+ }
+}
+
+static CPU_EXECUTE( i386 )
+{
+ i386_state *cpustate = get_safe_token(device);
+
+ int cycles = cpustate->cycles;
+ cpustate->base_cycles = cycles;
+ CHANGE_PC(cpustate,cpustate->eip);
+
+ if (cpustate->halted)
+ {
+ cpustate->tsc += cycles;
+ cpustate->cycles = 0;
+ return;
+ }
+
+ while( cpustate->cycles > 0 )
+ {
+ cpustate->operand_size = cpustate->sreg[CS].d;
+ cpustate->address_size = cpustate->sreg[CS].d;
+
+ cpustate->segment_prefix = 0;
+ cpustate->prev_eip = cpustate->eip;
+
+ debugger_instruction_hook(device, cpustate->pc);
+
+ i386_check_irq_line(cpustate);
+ if(cpustate->delayed_interrupt_enable != 0)
+ {
+ cpustate->IF = 1;
+ cpustate->delayed_interrupt_enable = 0;
+ }
+ I386OP(decode_opcode)(cpustate);
+ }
+ cpustate->tsc += (cycles - cpustate->cycles);
+}
+
+/*************************************************************************/
+
+static CPU_TRANSLATE( i386 )
+{
+ i386_state *cpustate = get_safe_token(device);
+ int result = 1;
+ if (space == AS_PROGRAM)
+ {
+ if (cpustate->cr[0] & 0x80000000)
+ result = translate_address(cpustate,address);
+ *address &= cpustate->a20_mask;
+ }
+ return result;
+}
+
+static CPU_DISASSEMBLE( i386 )
+{
+ i386_state *cpustate = get_safe_token(device);
+ return i386_dasm_one(buffer, pc, oprom, cpustate->sreg[CS].d ? 32 : 16);
+}
+
+static CPU_SET_INFO( i386 )
+{
+ i386_state *cpustate = get_safe_token(device);
+
+ if (state == CPUINFO_INT_INPUT_STATE+INPUT_LINE_A20)
+ {
+ i386_set_a20_line(cpustate,info->i);
+ return;
+ }
+ if (state >= CPUINFO_INT_INPUT_STATE && state <= CPUINFO_INT_INPUT_STATE + MAX_INPUT_LINES)
+ {
+ i386_set_irq_line(cpustate,state-CPUINFO_INT_INPUT_STATE, info->i);
+ return;
+ }
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + I386_PC: cpustate->pc = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_EIP: cpustate->eip = info->i; CHANGE_PC(cpustate,cpustate->eip); break;
+ case CPUINFO_INT_REGISTER + I386_AL: REG8(AL) = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_AH: REG8(AH) = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_BL: REG8(BL) = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_BH: REG8(BH) = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_CL: REG8(CL) = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_CH: REG8(CH) = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_DL: REG8(DL) = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_DH: REG8(DH) = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_AX: REG16(AX) = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_BX: REG16(BX) = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_CX: REG16(CX) = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_DX: REG16(DX) = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_SI: REG16(SI) = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_DI: REG16(DI) = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_BP: REG16(BP) = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_SP: REG16(SP) = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_IP: cpustate->eip = (cpustate->eip & ~0xFFFF) | (info->i & 0xFFFF); CHANGE_PC(cpustate,cpustate->eip); break;
+ case CPUINFO_INT_REGISTER + I386_EAX: REG32(EAX) = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_EBX: REG32(EBX) = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_ECX: REG32(ECX) = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_EDX: REG32(EDX) = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_EBP: REG32(EBP) = info->i; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + I386_ESP: REG32(ESP) = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_ESI: REG32(ESI) = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_EDI: REG32(EDI) = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_EFLAGS: cpustate->eflags = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_CS: cpustate->sreg[CS].selector = info->i & 0xffff; i386_load_segment_descriptor(cpustate,CS); break;
+ case CPUINFO_INT_REGISTER + I386_CS_BASE: cpustate->sreg[CS].base = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_CS_LIMIT: cpustate->sreg[CS].limit = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_CS_FLAGS: cpustate->sreg[CS].flags = info->i & 0xf0ff; break;
+ case CPUINFO_INT_REGISTER + I386_SS: cpustate->sreg[SS].selector = info->i & 0xffff; i386_load_segment_descriptor(cpustate,SS); break;
+ case CPUINFO_INT_REGISTER + I386_SS_BASE: cpustate->sreg[SS].base = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_SS_LIMIT: cpustate->sreg[SS].limit = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_SS_FLAGS: cpustate->sreg[SS].flags = info->i & 0xf0ff; break;
+ case CPUINFO_INT_REGISTER + I386_DS: cpustate->sreg[DS].selector = info->i & 0xffff; i386_load_segment_descriptor(cpustate,DS); break;
+ case CPUINFO_INT_REGISTER + I386_DS_BASE: cpustate->sreg[DS].base = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_DS_LIMIT: cpustate->sreg[DS].limit = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_DS_FLAGS: cpustate->sreg[DS].flags = info->i & 0xf0ff; break;
+ case CPUINFO_INT_REGISTER + I386_ES: cpustate->sreg[ES].selector = info->i & 0xffff; i386_load_segment_descriptor(cpustate,ES); break;
+ case CPUINFO_INT_REGISTER + I386_ES_BASE: cpustate->sreg[ES].base = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_ES_LIMIT: cpustate->sreg[ES].limit = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_ES_FLAGS: cpustate->sreg[ES].flags = info->i & 0xf0ff; break;
+ case CPUINFO_INT_REGISTER + I386_FS: cpustate->sreg[FS].selector = info->i & 0xffff; i386_load_segment_descriptor(cpustate,FS); break;
+ case CPUINFO_INT_REGISTER + I386_FS_BASE: cpustate->sreg[FS].base = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_FS_LIMIT: cpustate->sreg[FS].limit = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_FS_FLAGS: cpustate->sreg[FS].flags = info->i & 0xf0ff; break;
+ case CPUINFO_INT_REGISTER + I386_GS: cpustate->sreg[GS].selector = info->i & 0xffff; i386_load_segment_descriptor(cpustate,GS); break;
+ case CPUINFO_INT_REGISTER + I386_GS_BASE: cpustate->sreg[GS].base = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_GS_LIMIT: cpustate->sreg[GS].limit = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_GS_FLAGS: cpustate->sreg[GS].flags = info->i & 0xf0ff; break;
+ case CPUINFO_INT_REGISTER + I386_CR0: cpustate->cr[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_CR1: cpustate->cr[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_CR2: cpustate->cr[2] = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_CR3: cpustate->cr[3] = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_CR4: cpustate->cr[4] = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_DR0: cpustate->dr[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_DR1: cpustate->dr[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_DR2: cpustate->dr[2] = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_DR3: cpustate->dr[3] = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_DR4: cpustate->dr[4] = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_DR5: cpustate->dr[5] = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_DR6: cpustate->dr[6] = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_DR7: cpustate->dr[7] = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_TR6: cpustate->tr[6] = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_TR7: cpustate->tr[7] = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_GDTR_BASE: cpustate->gdtr.base = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_GDTR_LIMIT: cpustate->gdtr.limit = info->i & 0xffff; break;
+ case CPUINFO_INT_REGISTER + I386_IDTR_BASE: cpustate->idtr.base = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_IDTR_LIMIT: cpustate->idtr.limit = info->i & 0xffff; break;
+ case CPUINFO_INT_REGISTER + I386_TR: cpustate->task.segment = info->i & 0xffff; break;
+ case CPUINFO_INT_REGISTER + I386_TR_BASE: cpustate->task.base = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_TR_LIMIT: cpustate->task.limit = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_TR_FLAGS: cpustate->task.flags = info->i & 0xf0ff; break;
+ case CPUINFO_INT_REGISTER + I386_LDTR: cpustate->ldtr.segment = info->i & 0xffff; break;
+ case CPUINFO_INT_REGISTER + I386_LDTR_BASE: cpustate->ldtr.base = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_LDTR_LIMIT: cpustate->ldtr.limit = info->i; break;
+ case CPUINFO_INT_REGISTER + I386_LDTR_FLAGS: cpustate->ldtr.flags = info->i & 0xf0ff; break;
+ }
+}
+
+CPU_GET_INFO( i386 )
+{
+ i386_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(i386_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 32; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 15; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 40; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case CPUINFO_INT_LOGADDR_WIDTH_PROGRAM: info->i = 32; break;
+ case CPUINFO_INT_PAGE_SHIFT_PROGRAM: info->i = 12; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 32; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 32; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_INPUT_STATE: info->i = CLEAR_LINE; break;
+
+ case CPUINFO_INT_PREVIOUSPC: /* not implemented */ break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + I386_PC: info->i = cpustate->pc; break;
+ case CPUINFO_INT_REGISTER + I386_EIP: info->i = cpustate->eip; break;
+ case CPUINFO_INT_REGISTER + I386_AL: info->i = REG8(AL); break;
+ case CPUINFO_INT_REGISTER + I386_AH: info->i = REG8(AH); break;
+ case CPUINFO_INT_REGISTER + I386_BL: info->i = REG8(BL); break;
+ case CPUINFO_INT_REGISTER + I386_BH: info->i = REG8(BH); break;
+ case CPUINFO_INT_REGISTER + I386_CL: info->i = REG8(CL); break;
+ case CPUINFO_INT_REGISTER + I386_CH: info->i = REG8(CH); break;
+ case CPUINFO_INT_REGISTER + I386_DL: info->i = REG8(DL); break;
+ case CPUINFO_INT_REGISTER + I386_DH: info->i = REG8(DH); break;
+ case CPUINFO_INT_REGISTER + I386_AX: info->i = REG16(AX); break;
+ case CPUINFO_INT_REGISTER + I386_BX: info->i = REG16(BX); break;
+ case CPUINFO_INT_REGISTER + I386_CX: info->i = REG16(CX); break;
+ case CPUINFO_INT_REGISTER + I386_DX: info->i = REG16(DX); break;
+ case CPUINFO_INT_REGISTER + I386_SI: info->i = REG16(SI); break;
+ case CPUINFO_INT_REGISTER + I386_DI: info->i = REG16(DI); break;
+ case CPUINFO_INT_REGISTER + I386_BP: info->i = REG16(BP); break;
+ case CPUINFO_INT_REGISTER + I386_SP: info->i = REG16(SP); break;
+ case CPUINFO_INT_REGISTER + I386_IP: info->i = cpustate->eip & 0xFFFF; break;
+ case CPUINFO_INT_REGISTER + I386_EAX: info->i = REG32(EAX); break;
+ case CPUINFO_INT_REGISTER + I386_EBX: info->i = REG32(EBX); break;
+ case CPUINFO_INT_REGISTER + I386_ECX: info->i = REG32(ECX); break;
+ case CPUINFO_INT_REGISTER + I386_EDX: info->i = REG32(EDX); break;
+ case CPUINFO_INT_REGISTER + I386_EBP: info->i = REG32(EBP); break;
+ case CPUINFO_INT_REGISTER + I386_ESP: info->i = REG32(ESP); break;
+ case CPUINFO_INT_REGISTER + I386_ESI: info->i = REG32(ESI); break;
+ case CPUINFO_INT_REGISTER + I386_EDI: info->i = REG32(EDI); break;
+ case CPUINFO_INT_REGISTER + I386_EFLAGS: info->i = cpustate->eflags; break;
+ case CPUINFO_INT_REGISTER + I386_CS: info->i = cpustate->sreg[CS].selector; break;
+ case CPUINFO_INT_REGISTER + I386_CS_BASE: info->i = cpustate->sreg[CS].base; break;
+ case CPUINFO_INT_REGISTER + I386_CS_LIMIT: info->i = cpustate->sreg[CS].limit; break;
+ case CPUINFO_INT_REGISTER + I386_CS_FLAGS: info->i = cpustate->sreg[CS].flags; break;
+ case CPUINFO_INT_REGISTER + I386_SS: info->i = cpustate->sreg[SS].selector; break;
+ case CPUINFO_INT_REGISTER + I386_SS_BASE: info->i = cpustate->sreg[SS].base; break;
+ case CPUINFO_INT_REGISTER + I386_SS_LIMIT: info->i = cpustate->sreg[SS].limit; break;
+ case CPUINFO_INT_REGISTER + I386_SS_FLAGS: info->i = cpustate->sreg[SS].flags; break;
+ case CPUINFO_INT_REGISTER + I386_DS: info->i = cpustate->sreg[DS].selector; break;
+ case CPUINFO_INT_REGISTER + I386_DS_BASE: info->i = cpustate->sreg[DS].base; break;
+ case CPUINFO_INT_REGISTER + I386_DS_LIMIT: info->i = cpustate->sreg[DS].limit; break;
+ case CPUINFO_INT_REGISTER + I386_DS_FLAGS: info->i = cpustate->sreg[DS].flags; break;
+ case CPUINFO_INT_REGISTER + I386_ES: info->i = cpustate->sreg[ES].selector; break;
+ case CPUINFO_INT_REGISTER + I386_ES_BASE: info->i = cpustate->sreg[ES].base; break;
+ case CPUINFO_INT_REGISTER + I386_ES_LIMIT: info->i = cpustate->sreg[ES].limit; break;
+ case CPUINFO_INT_REGISTER + I386_ES_FLAGS: info->i = cpustate->sreg[ES].flags; break;
+ case CPUINFO_INT_REGISTER + I386_FS: info->i = cpustate->sreg[FS].selector; break;
+ case CPUINFO_INT_REGISTER + I386_FS_BASE: info->i = cpustate->sreg[FS].base; break;
+ case CPUINFO_INT_REGISTER + I386_FS_LIMIT: info->i = cpustate->sreg[FS].limit; break;
+ case CPUINFO_INT_REGISTER + I386_FS_FLAGS: info->i = cpustate->sreg[FS].flags; break;
+ case CPUINFO_INT_REGISTER + I386_GS: info->i = cpustate->sreg[GS].selector; break;
+ case CPUINFO_INT_REGISTER + I386_GS_BASE: info->i = cpustate->sreg[GS].base; break;
+ case CPUINFO_INT_REGISTER + I386_GS_LIMIT: info->i = cpustate->sreg[GS].limit; break;
+ case CPUINFO_INT_REGISTER + I386_GS_FLAGS: info->i = cpustate->sreg[GS].flags; break;
+ case CPUINFO_INT_REGISTER + I386_CR0: info->i = cpustate->cr[0]; break;
+ case CPUINFO_INT_REGISTER + I386_CR1: info->i = cpustate->cr[1]; break;
+ case CPUINFO_INT_REGISTER + I386_CR2: info->i = cpustate->cr[2]; break;
+ case CPUINFO_INT_REGISTER + I386_CR3: info->i = cpustate->cr[3]; break;
+ case CPUINFO_INT_REGISTER + I386_CR4: info->i = cpustate->cr[4]; break;
+ case CPUINFO_INT_REGISTER + I386_DR0: info->i = cpustate->dr[0]; break;
+ case CPUINFO_INT_REGISTER + I386_DR1: info->i = cpustate->dr[1]; break;
+ case CPUINFO_INT_REGISTER + I386_DR2: info->i = cpustate->dr[2]; break;
+ case CPUINFO_INT_REGISTER + I386_DR3: info->i = cpustate->dr[3]; break;
+ case CPUINFO_INT_REGISTER + I386_DR4: info->i = cpustate->dr[4]; break;
+ case CPUINFO_INT_REGISTER + I386_DR5: info->i = cpustate->dr[5]; break;
+ case CPUINFO_INT_REGISTER + I386_DR6: info->i = cpustate->dr[6]; break;
+ case CPUINFO_INT_REGISTER + I386_DR7: info->i = cpustate->dr[7]; break;
+ case CPUINFO_INT_REGISTER + I386_TR6: info->i = cpustate->tr[6]; break;
+ case CPUINFO_INT_REGISTER + I386_TR7: info->i = cpustate->tr[7]; break;
+ case CPUINFO_INT_REGISTER + I386_GDTR_BASE: info->i = cpustate->gdtr.base; break;
+ case CPUINFO_INT_REGISTER + I386_GDTR_LIMIT: info->i = cpustate->gdtr.limit; break;
+ case CPUINFO_INT_REGISTER + I386_IDTR_BASE: info->i = cpustate->idtr.base; break;
+ case CPUINFO_INT_REGISTER + I386_IDTR_LIMIT: info->i = cpustate->idtr.limit; break;
+ case CPUINFO_INT_REGISTER + I386_TR: info->i = cpustate->task.segment; break;
+ case CPUINFO_INT_REGISTER + I386_TR_BASE: info->i = cpustate->task.base; break;
+ case CPUINFO_INT_REGISTER + I386_TR_LIMIT: info->i = cpustate->task.limit; break;
+ case CPUINFO_INT_REGISTER + I386_TR_FLAGS: info->i = cpustate->task.flags; break;
+ case CPUINFO_INT_REGISTER + I386_LDTR: info->i = cpustate->ldtr.segment; break;
+ case CPUINFO_INT_REGISTER + I386_LDTR_BASE: info->i = cpustate->ldtr.base; break;
+ case CPUINFO_INT_REGISTER + I386_LDTR_LIMIT: info->i = cpustate->ldtr.limit; break;
+ case CPUINFO_INT_REGISTER + I386_LDTR_FLAGS: info->i = cpustate->ldtr.flags; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(i386); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(i386); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(i386); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(i386); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->cycles; break;
+ case CPUINFO_FCT_TRANSLATE: info->translate = CPU_TRANSLATE_NAME(i386); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(i386); break;
+ case CPUINFO_FCT_DEBUG_INIT: info->debug_init = CPU_DEBUG_INIT_NAME(i386); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "I386"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Intel 386"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Ville Linde"); break;
+
+ case CPUINFO_STR_FLAGS: sprintf(info->s, "%08X", get_flags(cpustate)); break;
+
+ case CPUINFO_STR_REGISTER + I386_PC: sprintf(info->s, "PC: %08X", cpustate->pc); break;
+ case CPUINFO_STR_REGISTER + I386_EIP: sprintf(info->s, "EIP: %08X", cpustate->eip); break;
+ case CPUINFO_STR_REGISTER + I386_AL: sprintf(info->s, "~AL: %02X", REG8(AL)); break;
+ case CPUINFO_STR_REGISTER + I386_AH: sprintf(info->s, "~AH: %02X", REG8(AH)); break;
+ case CPUINFO_STR_REGISTER + I386_BL: sprintf(info->s, "~BL: %02X", REG8(BL)); break;
+ case CPUINFO_STR_REGISTER + I386_BH: sprintf(info->s, "~BH: %02X", REG8(BH)); break;
+ case CPUINFO_STR_REGISTER + I386_CL: sprintf(info->s, "~CL: %02X", REG8(CL)); break;
+ case CPUINFO_STR_REGISTER + I386_CH: sprintf(info->s, "~CH: %02X", REG8(CH)); break;
+ case CPUINFO_STR_REGISTER + I386_DL: sprintf(info->s, "~DL: %02X", REG8(DL)); break;
+ case CPUINFO_STR_REGISTER + I386_DH: sprintf(info->s, "~DH: %02X", REG8(DH)); break;
+ case CPUINFO_STR_REGISTER + I386_AX: sprintf(info->s, "~AX: %04X", REG16(AX)); break;
+ case CPUINFO_STR_REGISTER + I386_BX: sprintf(info->s, "~BX: %04X", REG16(BX)); break;
+ case CPUINFO_STR_REGISTER + I386_CX: sprintf(info->s, "~CX: %04X", REG16(CX)); break;
+ case CPUINFO_STR_REGISTER + I386_DX: sprintf(info->s, "~DX: %04X", REG16(DX)); break;
+ case CPUINFO_STR_REGISTER + I386_SI: sprintf(info->s, "~SI: %04X", REG16(SI)); break;
+ case CPUINFO_STR_REGISTER + I386_DI: sprintf(info->s, "~DI: %04X", REG16(DI)); break;
+ case CPUINFO_STR_REGISTER + I386_BP: sprintf(info->s, "~BP: %04X", REG16(BP)); break;
+ case CPUINFO_STR_REGISTER + I386_SP: sprintf(info->s, "~SP: %04X", REG16(SP)); break;
+ case CPUINFO_STR_REGISTER + I386_IP: sprintf(info->s, "~IP: %04X", cpustate->eip & 0xFFFF); break;
+ case CPUINFO_STR_REGISTER + I386_EAX: sprintf(info->s, "EAX: %08X", cpustate->reg.d[EAX]); break;
+ case CPUINFO_STR_REGISTER + I386_EBX: sprintf(info->s, "EBX: %08X", cpustate->reg.d[EBX]); break;
+ case CPUINFO_STR_REGISTER + I386_ECX: sprintf(info->s, "ECX: %08X", cpustate->reg.d[ECX]); break;
+ case CPUINFO_STR_REGISTER + I386_EDX: sprintf(info->s, "EDX: %08X", cpustate->reg.d[EDX]); break;
+ case CPUINFO_STR_REGISTER + I386_EBP: sprintf(info->s, "EBP: %08X", cpustate->reg.d[EBP]); break;
+ case CPUINFO_STR_REGISTER + I386_ESP: sprintf(info->s, "ESP: %08X", cpustate->reg.d[ESP]); break;
+ case CPUINFO_STR_REGISTER + I386_ESI: sprintf(info->s, "ESI: %08X", cpustate->reg.d[ESI]); break;
+ case CPUINFO_STR_REGISTER + I386_EDI: sprintf(info->s, "EDI: %08X", cpustate->reg.d[EDI]); break;
+ case CPUINFO_STR_REGISTER + I386_EFLAGS: sprintf(info->s, "EFLAGS: %08X", cpustate->eflags); break;
+ case CPUINFO_STR_REGISTER + I386_CS: sprintf(info->s, "CS: %04X", cpustate->sreg[CS].selector); break;
+ case CPUINFO_STR_REGISTER + I386_CS_BASE: sprintf(info->s, "CSBASE: %08X", cpustate->sreg[CS].base); break;
+ case CPUINFO_STR_REGISTER + I386_CS_LIMIT: sprintf(info->s, "CSLIMIT: %08X", cpustate->sreg[CS].limit); break;
+ case CPUINFO_STR_REGISTER + I386_CS_FLAGS: sprintf(info->s, "CSFLAGS: %04X", cpustate->sreg[CS].flags); break;
+ case CPUINFO_STR_REGISTER + I386_SS: sprintf(info->s, "SS: %04X", cpustate->sreg[SS].selector); break;
+ case CPUINFO_STR_REGISTER + I386_SS_BASE: sprintf(info->s, "SSBASE: %08X", cpustate->sreg[SS].base); break;
+ case CPUINFO_STR_REGISTER + I386_SS_LIMIT: sprintf(info->s, "SSLIMIT: %08X", cpustate->sreg[SS].limit); break;
+ case CPUINFO_STR_REGISTER + I386_SS_FLAGS: sprintf(info->s, "SSFLAGS: %04X", cpustate->sreg[SS].flags); break;
+ case CPUINFO_STR_REGISTER + I386_DS: sprintf(info->s, "DS: %04X", cpustate->sreg[DS].selector); break;
+ case CPUINFO_STR_REGISTER + I386_DS_BASE: sprintf(info->s, "DSBASE: %08X", cpustate->sreg[DS].base); break;
+ case CPUINFO_STR_REGISTER + I386_DS_LIMIT: sprintf(info->s, "DSLIMIT: %08X", cpustate->sreg[DS].limit); break;
+ case CPUINFO_STR_REGISTER + I386_DS_FLAGS: sprintf(info->s, "DSFLAGS: %04X", cpustate->sreg[DS].flags); break;
+ case CPUINFO_STR_REGISTER + I386_ES: sprintf(info->s, "ES: %04X", cpustate->sreg[ES].selector); break;
+ case CPUINFO_STR_REGISTER + I386_ES_BASE: sprintf(info->s, "ESBASE: %08X", cpustate->sreg[ES].base); break;
+ case CPUINFO_STR_REGISTER + I386_ES_LIMIT: sprintf(info->s, "ESLIMIT: %08X", cpustate->sreg[ES].limit); break;
+ case CPUINFO_STR_REGISTER + I386_ES_FLAGS: sprintf(info->s, "ESFLAGS: %04X", cpustate->sreg[ES].flags); break;
+ case CPUINFO_STR_REGISTER + I386_FS: sprintf(info->s, "FS: %04X", cpustate->sreg[FS].selector); break;
+ case CPUINFO_STR_REGISTER + I386_FS_BASE: sprintf(info->s, "FSBASE: %08X", cpustate->sreg[FS].base); break;
+ case CPUINFO_STR_REGISTER + I386_FS_LIMIT: sprintf(info->s, "FSLIMIT: %08X", cpustate->sreg[FS].limit); break;
+ case CPUINFO_STR_REGISTER + I386_FS_FLAGS: sprintf(info->s, "FSFLAGS: %04X", cpustate->sreg[FS].flags); break;
+ case CPUINFO_STR_REGISTER + I386_GS: sprintf(info->s, "GS: %04X", cpustate->sreg[GS].selector); break;
+ case CPUINFO_STR_REGISTER + I386_GS_BASE: sprintf(info->s, "GSBASE: %08X", cpustate->sreg[GS].base); break;
+ case CPUINFO_STR_REGISTER + I386_GS_LIMIT: sprintf(info->s, "GSLIMIT: %08X", cpustate->sreg[GS].limit); break;
+ case CPUINFO_STR_REGISTER + I386_GS_FLAGS: sprintf(info->s, "GSFLAGS: %04X", cpustate->sreg[GS].flags); break;
+ case CPUINFO_STR_REGISTER + I386_CR0: sprintf(info->s, "CR0: %08X", cpustate->cr[0]); break;
+ case CPUINFO_STR_REGISTER + I386_CR1: sprintf(info->s, "CR1: %08X", cpustate->cr[1]); break;
+ case CPUINFO_STR_REGISTER + I386_CR2: sprintf(info->s, "CR2: %08X", cpustate->cr[2]); break;
+ case CPUINFO_STR_REGISTER + I386_CR3: sprintf(info->s, "CR3: %08X", cpustate->cr[3]); break;
+ case CPUINFO_STR_REGISTER + I386_CR4: sprintf(info->s, "CR4: %08X", cpustate->cr[4]); break;
+ case CPUINFO_STR_REGISTER + I386_DR0: sprintf(info->s, "DR0: %08X", cpustate->dr[0]); break;
+ case CPUINFO_STR_REGISTER + I386_DR1: sprintf(info->s, "DR1: %08X", cpustate->dr[1]); break;
+ case CPUINFO_STR_REGISTER + I386_DR2: sprintf(info->s, "DR2: %08X", cpustate->dr[2]); break;
+ case CPUINFO_STR_REGISTER + I386_DR3: sprintf(info->s, "DR3: %08X", cpustate->dr[3]); break;
+ case CPUINFO_STR_REGISTER + I386_DR4: sprintf(info->s, "DR4: %08X", cpustate->dr[4]); break;
+ case CPUINFO_STR_REGISTER + I386_DR5: sprintf(info->s, "DR5: %08X", cpustate->dr[5]); break;
+ case CPUINFO_STR_REGISTER + I386_DR6: sprintf(info->s, "DR6: %08X", cpustate->dr[6]); break;
+ case CPUINFO_STR_REGISTER + I386_DR7: sprintf(info->s, "DR7: %08X", cpustate->dr[7]); break;
+ case CPUINFO_STR_REGISTER + I386_TR6: sprintf(info->s, "TR6: %08X", cpustate->tr[6]); break;
+ case CPUINFO_STR_REGISTER + I386_TR7: sprintf(info->s, "TR7: %08X", cpustate->tr[7]); break;
+ case CPUINFO_STR_REGISTER + I386_GDTR_BASE: sprintf(info->s, "GDTRBASE: %08X", cpustate->gdtr.base); break;
+ case CPUINFO_STR_REGISTER + I386_GDTR_LIMIT: sprintf(info->s, "GDTRLIMIT: %04X", cpustate->gdtr.limit); break;
+ case CPUINFO_STR_REGISTER + I386_IDTR_BASE: sprintf(info->s, "IDTRBASE: %08X", cpustate->idtr.base); break;
+ case CPUINFO_STR_REGISTER + I386_IDTR_LIMIT: sprintf(info->s, "IDTRLIMIT: %04X", cpustate->idtr.limit); break;
+ case CPUINFO_STR_REGISTER + I386_LDTR: sprintf(info->s, "LDTR: %04X", cpustate->ldtr.segment); break;
+ case CPUINFO_STR_REGISTER + I386_LDTR_BASE: sprintf(info->s, "LDTRBASE: %08X", cpustate->ldtr.base); break;
+ case CPUINFO_STR_REGISTER + I386_LDTR_LIMIT: sprintf(info->s, "LDTRLIMIT: %08X", cpustate->ldtr.limit); break;
+ case CPUINFO_STR_REGISTER + I386_LDTR_FLAGS: sprintf(info->s, "LDTRFLAGS: %04X", cpustate->ldtr.flags); break;
+ case CPUINFO_STR_REGISTER + I386_TR: sprintf(info->s, "TR: %04X", cpustate->task.segment); break;
+ case CPUINFO_STR_REGISTER + I386_TR_BASE: sprintf(info->s, "TRBASE: %08X", cpustate->task.base); break;
+ case CPUINFO_STR_REGISTER + I386_TR_LIMIT: sprintf(info->s, "TRLIMIT: %08X", cpustate->task.limit); break;
+ case CPUINFO_STR_REGISTER + I386_TR_FLAGS: sprintf(info->s, "TRFLAGS: %04X", cpustate->task.flags); break;
+ case CPUINFO_STR_REGISTER + I386_CPL: sprintf(info->s, "CPL: %01X", cpustate->CPL); break;
+ }
+}
+
+/*****************************************************************************/
+/* Intel 486 */
+
+
+static CPU_INIT( i486 )
+{
+ CPU_INIT_CALL(i386);
+}
+
+static CPU_RESET( i486 )
+{
+ i386_state *cpustate = get_safe_token(device);
+ device_irq_callback save_irqcallback;
+
+ save_irqcallback = cpustate->irq_callback;
+ memset( cpustate, 0, sizeof(*cpustate) );
+ cpustate->irq_callback = save_irqcallback;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+ cpustate->io = device->space(AS_IO);
+
+ cpustate->sreg[CS].selector = 0xf000;
+ cpustate->sreg[CS].base = 0xffff0000;
+ cpustate->sreg[CS].limit = 0xffff;
+ cpustate->sreg[CS].flags = 0x009b;
+
+ cpustate->sreg[DS].base = cpustate->sreg[ES].base = cpustate->sreg[FS].base = cpustate->sreg[GS].base = cpustate->sreg[SS].base = 0x00000000;
+ cpustate->sreg[DS].limit = cpustate->sreg[ES].limit = cpustate->sreg[FS].limit = cpustate->sreg[GS].limit = cpustate->sreg[SS].limit = 0xffff;
+ cpustate->sreg[DS].flags = cpustate->sreg[ES].flags = cpustate->sreg[FS].flags = cpustate->sreg[GS].flags = cpustate->sreg[SS].flags = 0x0092;
+
+ cpustate->idtr.base = 0;
+ cpustate->idtr.limit = 0x3ff;
+
+ cpustate->a20_mask = ~0;
+
+ cpustate->cr[0] = 0x00000010;
+ cpustate->eflags = 0;
+ cpustate->eflags_mask = 0x00070000;
+ cpustate->eip = 0xfff0;
+
+ // [11:8] Family
+ // [ 7:4] Model
+ // [ 3:0] Stepping ID
+ // Family 4 (486), Model 0/1 (DX), Stepping 3
+ REG32(EAX) = 0;
+ REG32(EDX) = (4 << 8) | (0 << 4) | (3);
+
+ build_opcode_table(cpustate, OP_I386 | OP_FPU | OP_I486);
+ cpustate->cycle_table_rm = cycle_table_rm[CPU_CYCLES_I486];
+ cpustate->cycle_table_pm = cycle_table_pm[CPU_CYCLES_I486];
+
+ CHANGE_PC(cpustate,cpustate->eip);
+}
+
+static CPU_EXIT( i486 )
+{
+}
+
+static CPU_SET_INFO( i486 )
+{
+ i386_state *cpustate = get_safe_token(device);
+ switch (state)
+ {
+ case CPUINFO_INT_REGISTER + X87_CTRL: cpustate->fpu_control_word = info->i; break;
+ case CPUINFO_INT_REGISTER + X87_STATUS: cpustate->fpu_status_word = info->i; break;
+ case CPUINFO_INT_REGISTER + X87_ST0: ST(0).f = info->i; break;
+ case CPUINFO_INT_REGISTER + X87_ST1: ST(1).f = info->i; break;
+ case CPUINFO_INT_REGISTER + X87_ST2: ST(2).f = info->i; break;
+ case CPUINFO_INT_REGISTER + X87_ST3: ST(3).f = info->i; break;
+ case CPUINFO_INT_REGISTER + X87_ST4: ST(4).f = info->i; break;
+ case CPUINFO_INT_REGISTER + X87_ST5: ST(5).f = info->i; break;
+ case CPUINFO_INT_REGISTER + X87_ST6: ST(6).f = info->i; break;
+ case CPUINFO_INT_REGISTER + X87_ST7: ST(7).f = info->i; break;
+
+ default: CPU_SET_INFO_CALL(i386); break;
+ }
+}
+
+CPU_GET_INFO( i486 )
+{
+ i386_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+ switch (state)
+ {
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(i486);break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(i486); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(i486); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(i486); break;
+
+ case CPUINFO_INT_REGISTER + X87_CTRL: info->i = cpustate->fpu_control_word; break;
+ case CPUINFO_INT_REGISTER + X87_STATUS: info->i = cpustate->fpu_status_word; break;
+ case CPUINFO_INT_REGISTER + X87_ST0: info->i = ST(0).f; break;
+ case CPUINFO_INT_REGISTER + X87_ST1: info->i = ST(1).f; break;
+ case CPUINFO_INT_REGISTER + X87_ST2: info->i = ST(2).f; break;
+ case CPUINFO_INT_REGISTER + X87_ST3: info->i = ST(3).f; break;
+ case CPUINFO_INT_REGISTER + X87_ST4: info->i = ST(4).f; break;
+ case CPUINFO_INT_REGISTER + X87_ST5: info->i = ST(5).f; break;
+ case CPUINFO_INT_REGISTER + X87_ST6: info->i = ST(6).f; break;
+ case CPUINFO_INT_REGISTER + X87_ST7: info->i = ST(7).f; break;
+
+ case DEVINFO_STR_NAME: strcpy(info->s, "I486"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Intel 486"); break;
+ case CPUINFO_STR_REGISTER + X87_CTRL: sprintf(info->s, "FPU_CW: %04X", cpustate->fpu_control_word); break;
+ case CPUINFO_STR_REGISTER + X87_STATUS: sprintf(info->s, "FPU_SW: %04X", cpustate->fpu_status_word); break;
+ case CPUINFO_STR_REGISTER + X87_ST0: sprintf(info->s, "ST0: %f", ST(0).f); break;
+ case CPUINFO_STR_REGISTER + X87_ST1: sprintf(info->s, "ST1: %f", ST(1).f); break;
+ case CPUINFO_STR_REGISTER + X87_ST2: sprintf(info->s, "ST2: %f", ST(2).f); break;
+ case CPUINFO_STR_REGISTER + X87_ST3: sprintf(info->s, "ST3: %f", ST(3).f); break;
+ case CPUINFO_STR_REGISTER + X87_ST4: sprintf(info->s, "ST4: %f", ST(4).f); break;
+ case CPUINFO_STR_REGISTER + X87_ST5: sprintf(info->s, "ST5: %f", ST(5).f); break;
+ case CPUINFO_STR_REGISTER + X87_ST6: sprintf(info->s, "ST6: %f", ST(6).f); break;
+ case CPUINFO_STR_REGISTER + X87_ST7: sprintf(info->s, "ST7: %f", ST(7).f); break;
+
+ default: CPU_GET_INFO_CALL(i386); break;
+ }
+}
+
+/*****************************************************************************/
+/* Pentium */
+
+
+static CPU_INIT( pentium )
+{
+ CPU_INIT_CALL(i386);
+}
+
+static CPU_RESET( pentium )
+{
+ i386_state *cpustate = get_safe_token(device);
+ device_irq_callback save_irqcallback;
+
+ save_irqcallback = cpustate->irq_callback;
+ memset( cpustate, 0, sizeof(*cpustate) );
+ cpustate->irq_callback = save_irqcallback;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+ cpustate->io = device->space(AS_IO);
+
+ cpustate->sreg[CS].selector = 0xf000;
+ cpustate->sreg[CS].base = 0xffff0000;
+ cpustate->sreg[CS].limit = 0xffff;
+ cpustate->sreg[CS].flags = 0x009b;
+
+ cpustate->sreg[DS].base = cpustate->sreg[ES].base = cpustate->sreg[FS].base = cpustate->sreg[GS].base = cpustate->sreg[SS].base = 0x00000000;
+ cpustate->sreg[DS].limit = cpustate->sreg[ES].limit = cpustate->sreg[FS].limit = cpustate->sreg[GS].limit = cpustate->sreg[SS].limit = 0xffff;
+ cpustate->sreg[DS].flags = cpustate->sreg[ES].flags = cpustate->sreg[FS].flags = cpustate->sreg[GS].flags = cpustate->sreg[SS].flags = 0x0092;
+
+ cpustate->idtr.base = 0;
+ cpustate->idtr.limit = 0x3ff;
+
+ cpustate->a20_mask = ~0;
+
+ cpustate->cr[0] = 0x00000010;
+ cpustate->eflags = 0;
+ cpustate->eflags_mask = 0x003b0000;
+ cpustate->eip = 0xfff0;
+
+ // [11:8] Family
+ // [ 7:4] Model
+ // [ 3:0] Stepping ID
+ // Family 5 (Pentium), Model 2 (75 - 200MHz), Stepping 5
+ REG32(EAX) = 0;
+ REG32(EDX) = (5 << 8) | (2 << 4) | (5);
+
+ build_opcode_table(cpustate, OP_I386 | OP_FPU | OP_I486 | OP_PENTIUM);
+ cpustate->cycle_table_rm = cycle_table_rm[CPU_CYCLES_PENTIUM];
+ cpustate->cycle_table_pm = cycle_table_pm[CPU_CYCLES_PENTIUM];
+
+ cpustate->cpuid_id0 = 0x756e6547; // Genu
+ cpustate->cpuid_id1 = 0x49656e69; // ineI
+ cpustate->cpuid_id2 = 0x6c65746e; // ntel
+
+ cpustate->cpuid_max_input_value_eax = 0x01;
+ cpustate->cpu_version = REG32(EDX);
+
+ // [ 0:0] FPU on chip
+ // [ 2:2] I/O breakpoints
+ // [ 4:4] Time Stamp Counter
+ // [ 5:5] Pentium CPU style model specific registers
+ // [ 7:7] Machine Check Exception
+ // [ 8:8] CMPXCHG8B instruction
+ cpustate->feature_flags = 0x000001bf;
+
+ CHANGE_PC(cpustate,cpustate->eip);
+}
+
+static CPU_EXIT( pentium )
+{
+}
+
+static CPU_SET_INFO( pentium )
+{
+ i386_state *cpustate = get_safe_token(device);
+ switch (state)
+ {
+ case CPUINFO_INT_REGISTER + X87_CTRL: cpustate->fpu_control_word = info->i; break;
+ case CPUINFO_INT_REGISTER + X87_STATUS: cpustate->fpu_status_word = info->i; break;
+ case CPUINFO_INT_REGISTER + X87_ST0: ST(0).f = info->i; break;
+ case CPUINFO_INT_REGISTER + X87_ST1: ST(1).f = info->i; break;
+ case CPUINFO_INT_REGISTER + X87_ST2: ST(2).f = info->i; break;
+ case CPUINFO_INT_REGISTER + X87_ST3: ST(3).f = info->i; break;
+ case CPUINFO_INT_REGISTER + X87_ST4: ST(4).f = info->i; break;
+ case CPUINFO_INT_REGISTER + X87_ST5: ST(5).f = info->i; break;
+ case CPUINFO_INT_REGISTER + X87_ST6: ST(6).f = info->i; break;
+ case CPUINFO_INT_REGISTER + X87_ST7: ST(7).f = info->i; break;
+
+ default: CPU_SET_INFO_CALL(i386); break;
+ }
+}
+
+CPU_GET_INFO( pentium )
+{
+ i386_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+ switch (state)
+ {
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(pentium); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(pentium); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(pentium); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(pentium); break;
+
+ case CPUINFO_INT_REGISTER + X87_CTRL: info->i = cpustate->fpu_control_word; break;
+ case CPUINFO_INT_REGISTER + X87_STATUS: info->i = cpustate->fpu_status_word; break;
+ case CPUINFO_INT_REGISTER + X87_ST0: info->i = ST(0).f; break;
+ case CPUINFO_INT_REGISTER + X87_ST1: info->i = ST(1).f; break;
+ case CPUINFO_INT_REGISTER + X87_ST2: info->i = ST(2).f; break;
+ case CPUINFO_INT_REGISTER + X87_ST3: info->i = ST(3).f; break;
+ case CPUINFO_INT_REGISTER + X87_ST4: info->i = ST(4).f; break;
+ case CPUINFO_INT_REGISTER + X87_ST5: info->i = ST(5).f; break;
+ case CPUINFO_INT_REGISTER + X87_ST6: info->i = ST(6).f; break;
+ case CPUINFO_INT_REGISTER + X87_ST7: info->i = ST(7).f; break;
+
+ case DEVINFO_STR_NAME: strcpy(info->s, "PENTIUM"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Intel Pentium"); break;
+ case CPUINFO_STR_REGISTER + X87_CTRL: sprintf(info->s, "FPU_CW: %04X", cpustate->fpu_control_word); break;
+ case CPUINFO_STR_REGISTER + X87_STATUS: sprintf(info->s, "FPU_SW: %04X", cpustate->fpu_status_word); break;
+ case CPUINFO_STR_REGISTER + X87_ST0: sprintf(info->s, "ST0: %f", ST(0).f); break;
+ case CPUINFO_STR_REGISTER + X87_ST1: sprintf(info->s, "ST1: %f", ST(1).f); break;
+ case CPUINFO_STR_REGISTER + X87_ST2: sprintf(info->s, "ST2: %f", ST(2).f); break;
+ case CPUINFO_STR_REGISTER + X87_ST3: sprintf(info->s, "ST3: %f", ST(3).f); break;
+ case CPUINFO_STR_REGISTER + X87_ST4: sprintf(info->s, "ST4: %f", ST(4).f); break;
+ case CPUINFO_STR_REGISTER + X87_ST5: sprintf(info->s, "ST5: %f", ST(5).f); break;
+ case CPUINFO_STR_REGISTER + X87_ST6: sprintf(info->s, "ST6: %f", ST(6).f); break;
+ case CPUINFO_STR_REGISTER + X87_ST7: sprintf(info->s, "ST7: %f", ST(7).f); break;
+
+ default: CPU_GET_INFO_CALL(i386); break;
+ }
+}
+
+/*****************************************************************************/
+/* Cyrix MediaGX */
+
+
+static CPU_INIT( mediagx )
+{
+ CPU_INIT_CALL(i386);
+}
+
+static CPU_RESET( mediagx )
+{
+ i386_state *cpustate = get_safe_token(device);
+ device_irq_callback save_irqcallback;
+
+ save_irqcallback = cpustate->irq_callback;
+ memset( cpustate, 0, sizeof(*cpustate) );
+ cpustate->irq_callback = save_irqcallback;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+ cpustate->io = device->space(AS_IO);
+
+ cpustate->sreg[CS].selector = 0xf000;
+ cpustate->sreg[CS].base = 0xffff0000;
+ cpustate->sreg[CS].limit = 0xffff;
+ cpustate->sreg[CS].flags = 0x009b;
+
+ cpustate->sreg[DS].base = cpustate->sreg[ES].base = cpustate->sreg[FS].base = cpustate->sreg[GS].base = cpustate->sreg[SS].base = 0x00000000;
+ cpustate->sreg[DS].limit = cpustate->sreg[ES].limit = cpustate->sreg[FS].limit = cpustate->sreg[GS].limit = cpustate->sreg[SS].limit = 0xffff;
+ cpustate->sreg[DS].flags = cpustate->sreg[ES].flags = cpustate->sreg[FS].flags = cpustate->sreg[GS].flags = cpustate->sreg[SS].flags = 0x0092;
+
+ cpustate->idtr.base = 0;
+ cpustate->idtr.limit = 0x3ff;
+
+ cpustate->a20_mask = ~0;
+
+ cpustate->cr[0] = 0x00000010;
+ cpustate->eflags = 0;
+ cpustate->eflags_mask = 0x00270000; /* TODO: is this correct? */
+ cpustate->eip = 0xfff0;
+
+ // [11:8] Family
+ // [ 7:4] Model
+ // [ 3:0] Stepping ID
+ // Family 4, Model 4 (MediaGX)
+ REG32(EAX) = 0;
+ REG32(EDX) = (4 << 8) | (4 << 4) | (1); /* TODO: is this correct? */
+
+ build_opcode_table(cpustate, OP_I386 | OP_FPU | OP_I486 | OP_PENTIUM | OP_CYRIX);
+ cpustate->cycle_table_rm = cycle_table_rm[CPU_CYCLES_MEDIAGX];
+ cpustate->cycle_table_pm = cycle_table_pm[CPU_CYCLES_MEDIAGX];
+
+ cpustate->cpuid_id0 = 0x69727943; // Cyri
+ cpustate->cpuid_id1 = 0x736e4978; // xIns
+ cpustate->cpuid_id2 = 0x6d616574; // tead
+
+ cpustate->cpuid_max_input_value_eax = 0x01;
+ cpustate->cpu_version = REG32(EDX);
+
+ // [ 0:0] FPU on chip
+ cpustate->feature_flags = 0x00000001;
+
+ CHANGE_PC(cpustate,cpustate->eip);
+}
+
+static CPU_EXIT( mediagx )
+{
+}
+
+static CPU_SET_INFO( mediagx )
+{
+ i386_state *cpustate = get_safe_token(device);
+ switch (state)
+ {
+ case CPUINFO_INT_REGISTER + X87_CTRL: cpustate->fpu_control_word = info->i; break;
+ case CPUINFO_INT_REGISTER + X87_STATUS: cpustate->fpu_status_word = info->i; break;
+ case CPUINFO_INT_REGISTER + X87_ST0: ST(0).f = info->i; break;
+ case CPUINFO_INT_REGISTER + X87_ST1: ST(1).f = info->i; break;
+ case CPUINFO_INT_REGISTER + X87_ST2: ST(2).f = info->i; break;
+ case CPUINFO_INT_REGISTER + X87_ST3: ST(3).f = info->i; break;
+ case CPUINFO_INT_REGISTER + X87_ST4: ST(4).f = info->i; break;
+ case CPUINFO_INT_REGISTER + X87_ST5: ST(5).f = info->i; break;
+ case CPUINFO_INT_REGISTER + X87_ST6: ST(6).f = info->i; break;
+ case CPUINFO_INT_REGISTER + X87_ST7: ST(7).f = info->i; break;
+
+ default: CPU_SET_INFO_CALL(i386); break;
+ }
+}
+
+CPU_GET_INFO( mediagx )
+{
+ i386_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+ switch (state)
+ {
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(mediagx); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(mediagx); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(mediagx); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(mediagx); break;
+
+ case CPUINFO_INT_REGISTER + X87_CTRL: info->i = cpustate->fpu_control_word; break;
+ case CPUINFO_INT_REGISTER + X87_STATUS: info->i = cpustate->fpu_status_word; break;
+ case CPUINFO_INT_REGISTER + X87_ST0: info->i = ST(0).f; break;
+ case CPUINFO_INT_REGISTER + X87_ST1: info->i = ST(1).f; break;
+ case CPUINFO_INT_REGISTER + X87_ST2: info->i = ST(2).f; break;
+ case CPUINFO_INT_REGISTER + X87_ST3: info->i = ST(3).f; break;
+ case CPUINFO_INT_REGISTER + X87_ST4: info->i = ST(4).f; break;
+ case CPUINFO_INT_REGISTER + X87_ST5: info->i = ST(5).f; break;
+ case CPUINFO_INT_REGISTER + X87_ST6: info->i = ST(6).f; break;
+ case CPUINFO_INT_REGISTER + X87_ST7: info->i = ST(7).f; break;
+
+ case DEVINFO_STR_NAME: strcpy(info->s, "MEDIAGX"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Cyrix MediaGX"); break;
+ case CPUINFO_STR_REGISTER + X87_CTRL: sprintf(info->s, "FPU_CW: %04X", cpustate->fpu_control_word); break;
+ case CPUINFO_STR_REGISTER + X87_STATUS: sprintf(info->s, "FPU_SW: %04X", cpustate->fpu_status_word); break;
+ case CPUINFO_STR_REGISTER + X87_ST0: sprintf(info->s, "ST0: %f", ST(0).f); break;
+ case CPUINFO_STR_REGISTER + X87_ST1: sprintf(info->s, "ST1: %f", ST(1).f); break;
+ case CPUINFO_STR_REGISTER + X87_ST2: sprintf(info->s, "ST2: %f", ST(2).f); break;
+ case CPUINFO_STR_REGISTER + X87_ST3: sprintf(info->s, "ST3: %f", ST(3).f); break;
+ case CPUINFO_STR_REGISTER + X87_ST4: sprintf(info->s, "ST4: %f", ST(4).f); break;
+ case CPUINFO_STR_REGISTER + X87_ST5: sprintf(info->s, "ST5: %f", ST(5).f); break;
+ case CPUINFO_STR_REGISTER + X87_ST6: sprintf(info->s, "ST6: %f", ST(6).f); break;
+ case CPUINFO_STR_REGISTER + X87_ST7: sprintf(info->s, "ST7: %f", ST(7).f); break;
+
+ default: CPU_GET_INFO_CALL(i386); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(I386, i386);
+DEFINE_LEGACY_CPU_DEVICE(I486, i486);
+DEFINE_LEGACY_CPU_DEVICE(PENTIUM, pentium);
+DEFINE_LEGACY_CPU_DEVICE(MEDIAGX, mediagx);
diff --git a/trunk/src/emu/cpu/i386/i386.h b/trunk/src/emu/cpu/i386/i386.h
new file mode 100644
index 00000000000..f8937c9823f
--- /dev/null
+++ b/trunk/src/emu/cpu/i386/i386.h
@@ -0,0 +1,19 @@
+#pragma once
+
+#ifndef __I386INTF_H__
+#define __I386INTF_H__
+
+#define INPUT_LINE_A20 1
+
+
+// mingw has this defined for 32-bit compiles
+#undef i386
+
+DECLARE_LEGACY_CPU_DEVICE(I386, i386);
+DECLARE_LEGACY_CPU_DEVICE(I486, i486);
+DECLARE_LEGACY_CPU_DEVICE(PENTIUM, pentium);
+DECLARE_LEGACY_CPU_DEVICE(MEDIAGX, mediagx);
+
+
+
+#endif /* __I386INTF_H__ */
diff --git a/trunk/src/emu/cpu/i386/i386dasm.c b/trunk/src/emu/cpu/i386/i386dasm.c
new file mode 100644
index 00000000000..4dc8a42afad
--- /dev/null
+++ b/trunk/src/emu/cpu/i386/i386dasm.c
@@ -0,0 +1,2191 @@
+/*
+ i386 Disassembler
+
+ Written by Ville Linde
+*/
+
+#include "emu.h"
+
+enum
+{
+ PARAM_REG = 1, /* 16 or 32-bit register */
+ PARAM_REG8, /* 8-bit register */
+ PARAM_REG16, /* 16-bit register */
+ PARAM_REG32, /* 32-bit register */
+ PARAM_REG3264, /* 32-bit or 64-bit register */
+ PARAM_REG2_32, /* 32-bit register */
+ PARAM_MMX, /* MMX register */
+ PARAM_XMM, /* XMM register */
+ PARAM_RM, /* 16 or 32-bit memory or register */
+ PARAM_RM8, /* 8-bit memory or register */
+ PARAM_RM16, /* 16-bit memory or register */
+ PARAM_RM32, /* 32-bit memory or register */
+ PARAM_RMPTR, /* 16 or 32-bit memory or register */
+ PARAM_RMPTR8, /* 8-bit memory or register */
+ PARAM_RMPTR16, /* 16-bit memory or register */
+ PARAM_RMPTR32, /* 32-bit memory or register */
+ PARAM_RMXMM, /* 32 or 64-bit memory or register */
+ PARAM_REGORXMM, /* 32 or 64-bit register or XMM register */
+ PARAM_M64, /* 64-bit memory */
+ PARAM_M64PTR, /* 64-bit memory */
+ PARAM_MMXM, /* 64-bit memory or MMX register */
+ PARAM_XMMM, /* 128-bit memory or XMM register */
+ PARAM_I4, /* 4-bit signed immediate */
+ PARAM_I8, /* 8-bit signed immediate */
+ PARAM_I16, /* 16-bit signed immediate */
+ PARAM_UI8, /* 8-bit unsigned immediate */
+ PARAM_UI16, /* 16-bit unsigned immediate */
+ PARAM_IMM, /* 16 or 32-bit immediate */
+ PARAM_IMM64, /* 16, 32 or 64-bit immediate */
+ PARAM_ADDR, /* 16:16 or 16:32 address */
+ PARAM_REL, /* 16 or 32-bit PC-relative displacement */
+ PARAM_REL8, /* 8-bit PC-relative displacement */
+ PARAM_MEM_OFFS, /* 16 or 32-bit mem offset */
+ PARAM_SREG, /* segment register */
+ PARAM_CREG, /* control register */
+ PARAM_DREG, /* debug register */
+ PARAM_TREG, /* test register */
+ PARAM_1, /* used by shift/rotate instructions */
+ PARAM_AL,
+ PARAM_CL,
+ PARAM_DL,
+ PARAM_BL,
+ PARAM_AH,
+ PARAM_CH,
+ PARAM_DH,
+ PARAM_BH,
+ PARAM_DX,
+ PARAM_EAX, /* EAX or AX */
+ PARAM_ECX, /* ECX or CX */
+ PARAM_EDX, /* EDX or DX */
+ PARAM_EBX, /* EBX or BX */
+ PARAM_ESP, /* ESP or SP */
+ PARAM_EBP, /* EBP or BP */
+ PARAM_ESI, /* ESI or SI */
+ PARAM_EDI, /* EDI or DI */
+};
+
+enum
+{
+ MODRM = 1,
+ GROUP,
+ FPU,
+ OP_SIZE,
+ ADDR_SIZE,
+ TWO_BYTE,
+ PREFIX,
+ SEG_CS,
+ SEG_DS,
+ SEG_ES,
+ SEG_FS,
+ SEG_GS,
+ SEG_SS,
+ ISREX
+};
+
+#define FLAGS_MASK 0x0ff
+#define VAR_NAME 0x100
+#define VAR_NAME4 0x200
+#define ALWAYS64 0x400
+#define SPECIAL64 0x800
+#define SPECIAL64_ENT(x) (SPECIAL64 | ((x) << 24))
+
+typedef struct {
+ const char *mnemonic;
+ UINT32 flags;
+ UINT32 param1;
+ UINT32 param2;
+ UINT32 param3;
+ offs_t dasm_flags;
+} I386_OPCODE;
+
+typedef struct {
+ char mnemonic[32];
+ const I386_OPCODE *opcode;
+} GROUP_OP;
+
+static const UINT8 *opcode_ptr;
+static const UINT8 *opcode_ptr_base;
+
+static const I386_OPCODE i386_opcode_table1[256] =
+{
+ // 0x00
+ {"add", MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {"add", MODRM, PARAM_RM, PARAM_REG, 0 },
+ {"add", MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {"add", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"add", 0, PARAM_AL, PARAM_UI8, 0 },
+ {"add", 0, PARAM_EAX, PARAM_IMM, 0 },
+ {"push es", 0, 0, 0, 0 },
+ {"pop es", 0, 0, 0, 0 },
+ {"or", MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {"or", MODRM, PARAM_RM, PARAM_REG, 0 },
+ {"or", MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {"or", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"or", 0, PARAM_AL, PARAM_UI8, 0 },
+ {"or", 0, PARAM_EAX, PARAM_IMM, 0 },
+ {"push cs", 0, 0, 0, 0 },
+ {"two_byte", TWO_BYTE, 0, 0, 0 },
+ // 0x10
+ {"adc", MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {"adc", MODRM, PARAM_RM, PARAM_REG, 0 },
+ {"adc", MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {"adc", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"adc", 0, PARAM_AL, PARAM_UI8, 0 },
+ {"adc", 0, PARAM_EAX, PARAM_IMM, 0 },
+ {"push ss", 0, 0, 0, 0 },
+ {"pop ss", 0, 0, 0, 0 },
+ {"sbb", MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {"sbb", MODRM, PARAM_RM, PARAM_REG, 0 },
+ {"sbb", MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {"sbb", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"sbb", 0, PARAM_AL, PARAM_UI8, 0 },
+ {"sbb", 0, PARAM_EAX, PARAM_IMM, 0 },
+ {"push ds", 0, 0, 0, 0 },
+ {"pop ds", 0, 0, 0, 0 },
+ // 0x20
+ {"and", MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {"and", MODRM, PARAM_RM, PARAM_REG, 0 },
+ {"and", MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {"and", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"and", 0, PARAM_AL, PARAM_UI8, 0 },
+ {"and", 0, PARAM_EAX, PARAM_IMM, 0 },
+ {"seg_es", SEG_ES, 0, 0, 0 },
+ {"daa", 0, 0, 0, 0 },
+ {"sub", MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {"sub", MODRM, PARAM_RM, PARAM_REG, 0 },
+ {"sub", MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {"sub", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"sub", 0, PARAM_AL, PARAM_I8, 0 },
+ {"sub", 0, PARAM_EAX, PARAM_IMM, 0 },
+ {"seg_cs", SEG_CS, 0, 0, 0 },
+ {"das", 0, 0, 0, 0 },
+ // 0x30
+ {"xor", MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {"xor", MODRM, PARAM_RM, PARAM_REG, 0 },
+ {"xor", MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {"xor", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"xor", 0, PARAM_AL, PARAM_UI8, 0 },
+ {"xor", 0, PARAM_EAX, PARAM_IMM, 0 },
+ {"seg_ss", SEG_SS, 0, 0, 0 },
+ {"aaa", 0, 0, 0, 0 },
+ {"cmp", MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {"cmp", MODRM, PARAM_RM, PARAM_REG, 0 },
+ {"cmp", MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {"cmp", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"cmp", 0, PARAM_AL, PARAM_UI8, 0 },
+ {"cmp", 0, PARAM_EAX, PARAM_IMM, 0 },
+ {"seg_ds", SEG_DS, 0, 0, 0 },
+ {"aas", 0, 0, 0, 0 },
+ // 0x40
+ {"inc", ISREX, PARAM_EAX, 0, 0 },
+ {"inc", ISREX, PARAM_ECX, 0, 0 },
+ {"inc", ISREX, PARAM_EDX, 0, 0 },
+ {"inc", ISREX, PARAM_EBX, 0, 0 },
+ {"inc", ISREX, PARAM_ESP, 0, 0 },
+ {"inc", ISREX, PARAM_EBP, 0, 0 },
+ {"inc", ISREX, PARAM_ESI, 0, 0 },
+ {"inc", ISREX, PARAM_EDI, 0, 0 },
+ {"dec", ISREX, PARAM_EAX, 0, 0 },
+ {"dec", ISREX, PARAM_ECX, 0, 0 },
+ {"dec", ISREX, PARAM_EDX, 0, 0 },
+ {"dec", ISREX, PARAM_EBX, 0, 0 },
+ {"dec", ISREX, PARAM_ESP, 0, 0 },
+ {"dec", ISREX, PARAM_EBP, 0, 0 },
+ {"dec", ISREX, PARAM_ESI, 0, 0 },
+ {"dec", ISREX, PARAM_EDI, 0, 0 },
+ // 0x50
+ {"push", ALWAYS64, PARAM_EAX, 0, 0 },
+ {"push", ALWAYS64, PARAM_ECX, 0, 0 },
+ {"push", ALWAYS64, PARAM_EDX, 0, 0 },
+ {"push", ALWAYS64, PARAM_EBX, 0, 0 },
+ {"push", ALWAYS64, PARAM_ESP, 0, 0 },
+ {"push", ALWAYS64, PARAM_EBP, 0, 0 },
+ {"push", ALWAYS64, PARAM_ESI, 0, 0 },
+ {"push", ALWAYS64, PARAM_EDI, 0, 0 },
+ {"pop", ALWAYS64, PARAM_EAX, 0, 0 },
+ {"pop", ALWAYS64, PARAM_ECX, 0, 0 },
+ {"pop", ALWAYS64, PARAM_EDX, 0, 0 },
+ {"pop", ALWAYS64, PARAM_EBX, 0, 0 },
+ {"pop", ALWAYS64, PARAM_ESP, 0, 0 },
+ {"pop", ALWAYS64, PARAM_EBP, 0, 0 },
+ {"pop", ALWAYS64, PARAM_ESI, 0, 0 },
+ {"pop", ALWAYS64, PARAM_EDI, 0, 0 },
+ // 0x60
+ {"pusha\0pushad\0<invalid>",VAR_NAME,0, 0, 0 },
+ {"popa\0popad\0<invalid>", VAR_NAME,0, 0, 0 },
+ {"bound", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"arpl", MODRM | SPECIAL64_ENT(0),PARAM_RM, PARAM_REG16, 0 },
+ {"seg_fs", SEG_FS, 0, 0, 0 },
+ {"seg_gs", SEG_GS, 0, 0, 0 },
+ {"op_size", OP_SIZE, 0, 0, 0 },
+ {"addr_size", ADDR_SIZE, 0, 0, 0 },
+ {"push", 0, PARAM_IMM, 0, 0 },
+ {"imul", MODRM, PARAM_REG, PARAM_RM, PARAM_IMM },
+ {"push", 0, PARAM_I8, 0, 0 },
+ {"imul", MODRM, PARAM_REG, PARAM_RM, PARAM_I8 },
+ {"insb", 0, 0, 0, 0 },
+ {"insw\0insd\0insd",VAR_NAME, 0, 0, 0 },
+ {"outsb", 0, 0, 0, 0 },
+ {"outsw\0outsd\0outsd",VAR_NAME, 0, 0, 0 },
+ // 0x70
+ {"jo", 0, PARAM_REL8, 0, 0 },
+ {"jno", 0, PARAM_REL8, 0, 0 },
+ {"jb", 0, PARAM_REL8, 0, 0 },
+ {"jae", 0, PARAM_REL8, 0, 0 },
+ {"je", 0, PARAM_REL8, 0, 0 },
+ {"jne", 0, PARAM_REL8, 0, 0 },
+ {"jbe", 0, PARAM_REL8, 0, 0 },
+ {"ja", 0, PARAM_REL8, 0, 0 },
+ {"js", 0, PARAM_REL8, 0, 0 },
+ {"jns", 0, PARAM_REL8, 0, 0 },
+ {"jp", 0, PARAM_REL8, 0, 0 },
+ {"jnp", 0, PARAM_REL8, 0, 0 },
+ {"jl", 0, PARAM_REL8, 0, 0 },
+ {"jge", 0, PARAM_REL8, 0, 0 },
+ {"jle", 0, PARAM_REL8, 0, 0 },
+ {"jg", 0, PARAM_REL8, 0, 0 },
+ // 0x80
+ {"group80", GROUP, 0, 0, 0 },
+ {"group81", GROUP, 0, 0, 0 },
+ {"group80", GROUP, 0, 0, 0 },
+ {"group83", GROUP, 0, 0, 0 },
+ {"test", MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {"test", MODRM, PARAM_RM, PARAM_REG, 0 },
+ {"xchg", MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {"xchg", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"mov", MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {"mov", MODRM, PARAM_RM, PARAM_REG, 0 },
+ {"mov", MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {"mov", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"mov", MODRM, PARAM_RM, PARAM_SREG, 0 },
+ {"lea", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"mov", MODRM, PARAM_SREG, PARAM_RM, 0 },
+ {"pop", MODRM, PARAM_RM, 0, 0 },
+ // 0x90
+ {"nop", 0, 0, 0, 0 },
+ {"xchg", 0, PARAM_EAX, PARAM_ECX, 0 },
+ {"xchg", 0, PARAM_EAX, PARAM_EDX, 0 },
+ {"xchg", 0, PARAM_EAX, PARAM_EBX, 0 },
+ {"xchg", 0, PARAM_EAX, PARAM_ESP, 0 },
+ {"xchg", 0, PARAM_EAX, PARAM_EBP, 0 },
+ {"xchg", 0, PARAM_EAX, PARAM_ESI, 0 },
+ {"xchg", 0, PARAM_EAX, PARAM_EDI, 0 },
+ {"cbw\0cwde\0cdqe", VAR_NAME, 0, 0, 0 },
+ {"cwd\0cdq\0cqo", VAR_NAME, 0, 0, 0 },
+ {"call", ALWAYS64, PARAM_ADDR, 0, 0, DASMFLAG_STEP_OVER},
+ {"wait", 0, 0, 0, 0 },
+ {"pushf\0pushfd\0pushfq",VAR_NAME, 0, 0, 0 },
+ {"popf\0popfd\0popfq",VAR_NAME, 0, 0, 0 },
+ {"sahf", 0, 0, 0, 0 },
+ {"lahf", 0, 0, 0, 0 },
+ // 0xa0
+ {"mov", 0, PARAM_AL, PARAM_MEM_OFFS, 0 },
+ {"mov", 0, PARAM_EAX, PARAM_MEM_OFFS, 0 },
+ {"mov", 0, PARAM_MEM_OFFS, PARAM_AL, 0 },
+ {"mov", 0, PARAM_MEM_OFFS, PARAM_EAX, 0 },
+ {"movsb", 0, 0, 0, 0 },
+ {"movsw\0movsd\0movsq",VAR_NAME, 0, 0, 0 },
+ {"cmpsb", 0, 0, 0, 0 },
+ {"cmpsw\0cmpsd\0cmpsq",VAR_NAME, 0, 0, 0 },
+ {"test", 0, PARAM_AL, PARAM_UI8, 0 },
+ {"test", 0, PARAM_EAX, PARAM_IMM, 0 },
+ {"stosb", 0, 0, 0, 0 },
+ {"stosw\0stosd\0stosq",VAR_NAME, 0, 0, 0 },
+ {"lodsb", 0, 0, 0, 0 },
+ {"lodsw\0lodsd\0lodsq",VAR_NAME, 0, 0, 0 },
+ {"scasb", 0, 0, 0, 0 },
+ {"scasw\0scasd\0scasq",VAR_NAME, 0, 0, 0 },
+ // 0xb0
+ {"mov", 0, PARAM_AL, PARAM_UI8, 0 },
+ {"mov", 0, PARAM_CL, PARAM_UI8, 0 },
+ {"mov", 0, PARAM_DL, PARAM_UI8, 0 },
+ {"mov", 0, PARAM_BL, PARAM_UI8, 0 },
+ {"mov", 0, PARAM_AH, PARAM_UI8, 0 },
+ {"mov", 0, PARAM_CH, PARAM_UI8, 0 },
+ {"mov", 0, PARAM_DH, PARAM_UI8, 0 },
+ {"mov", 0, PARAM_BH, PARAM_UI8, 0 },
+ {"mov", 0, PARAM_EAX, PARAM_IMM64, 0 },
+ {"mov", 0, PARAM_ECX, PARAM_IMM64, 0 },
+ {"mov", 0, PARAM_EDX, PARAM_IMM64, 0 },
+ {"mov", 0, PARAM_EBX, PARAM_IMM64, 0 },
+ {"mov", 0, PARAM_ESP, PARAM_IMM64, 0 },
+ {"mov", 0, PARAM_EBP, PARAM_IMM64, 0 },
+ {"mov", 0, PARAM_ESI, PARAM_IMM64, 0 },
+ {"mov", 0, PARAM_EDI, PARAM_IMM64, 0 },
+ // 0xc0
+ {"groupC0", GROUP, 0, 0, 0 },
+ {"groupC1", GROUP, 0, 0, 0 },
+ {"ret", 0, PARAM_I16, 0, 0, DASMFLAG_STEP_OUT},
+ {"ret", 0, 0, 0, 0, DASMFLAG_STEP_OUT},
+ {"les", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"lds", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"mov", MODRM, PARAM_RMPTR8, PARAM_UI8, 0 },
+ {"mov", MODRM, PARAM_RMPTR, PARAM_IMM, 0 },
+ {"enter", 0, PARAM_I16, PARAM_UI8, 0 },
+ {"leave", 0, 0, 0, 0 },
+ {"retf", 0, PARAM_I16, 0, 0, DASMFLAG_STEP_OUT},
+ {"retf", 0, 0, 0, 0, DASMFLAG_STEP_OUT},
+ {"int 3", 0, 0, 0, 0, DASMFLAG_STEP_OVER},
+ {"int", 0, PARAM_UI8, 0, 0, DASMFLAG_STEP_OVER},
+ {"into", 0, 0, 0, 0 },
+ {"iret", 0, 0, 0, 0, DASMFLAG_STEP_OUT},
+ // 0xd0
+ {"groupD0", GROUP, 0, 0, 0 },
+ {"groupD1", GROUP, 0, 0, 0 },
+ {"groupD2", GROUP, 0, 0, 0 },
+ {"groupD3", GROUP, 0, 0, 0 },
+ {"aam", 0, PARAM_I8, 0, 0 },
+ {"aad", 0, PARAM_I8, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"xlat", 0, 0, 0, 0 },
+ {"escape", FPU, 0, 0, 0 },
+ {"escape", FPU, 0, 0, 0 },
+ {"escape", FPU, 0, 0, 0 },
+ {"escape", FPU, 0, 0, 0 },
+ {"escape", FPU, 0, 0, 0 },
+ {"escape", FPU, 0, 0, 0 },
+ {"escape", FPU, 0, 0, 0 },
+ {"escape", FPU, 0, 0, 0 },
+ // 0xe0
+ {"loopne", 0, PARAM_REL8, 0, 0, DASMFLAG_STEP_OVER},
+ {"loopz", 0, PARAM_REL8, 0, 0, DASMFLAG_STEP_OVER},
+ {"loop", 0, PARAM_REL8, 0, 0, DASMFLAG_STEP_OVER},
+ {"jcxz\0jecxz\0jrcxz",VAR_NAME, PARAM_REL8, 0, 0 },
+ {"in", 0, PARAM_AL, PARAM_UI8, 0 },
+ {"in", 0, PARAM_EAX, PARAM_UI8, 0 },
+ {"out", 0, PARAM_UI8, PARAM_AL, 0 },
+ {"out", 0, PARAM_UI8, PARAM_EAX, 0 },
+ {"call", 0, PARAM_REL, 0, 0, DASMFLAG_STEP_OVER},
+ {"jmp", 0, PARAM_REL, 0, 0 },
+ {"jmp", 0, PARAM_ADDR, 0, 0 },
+ {"jmp", 0, PARAM_REL8, 0, 0 },
+ {"in", 0, PARAM_AL, PARAM_DX, 0 },
+ {"in", 0, PARAM_EAX, PARAM_DX, 0 },
+ {"out", 0, PARAM_DX, PARAM_AL, 0 },
+ {"out", 0, PARAM_DX, PARAM_EAX, 0 },
+ // 0xf0
+ {"lock", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"repne", PREFIX, 0, 0, 0 },
+ {"rep", PREFIX, 0, 0, 0 },
+ {"hlt", 0, 0, 0, 0 },
+ {"cmc", 0, 0, 0, 0 },
+ {"groupF6", GROUP, 0, 0, 0 },
+ {"groupF7", GROUP, 0, 0, 0 },
+ {"clc", 0, 0, 0, 0 },
+ {"stc", 0, 0, 0, 0 },
+ {"cli", 0, 0, 0, 0 },
+ {"sti", 0, 0, 0, 0 },
+ {"cld", 0, 0, 0, 0 },
+ {"std", 0, 0, 0, 0 },
+ {"groupFE", GROUP, 0, 0, 0 },
+ {"groupFF", GROUP, 0, 0, 0 }
+};
+
+static const I386_OPCODE x64_opcode_alt[] =
+{
+ {"movsxd", MODRM | ALWAYS64,PARAM_REG, PARAM_RMPTR32, 0 },
+};
+
+static const I386_OPCODE i386_opcode_table2[256] =
+{
+ // 0x00
+ {"group0F00", GROUP, 0, 0, 0 },
+ {"group0F01", GROUP, 0, 0, 0 },
+ {"lar", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"lsl", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"syscall", 0, 0, 0, 0 },
+ {"clts", 0, 0, 0, 0 },
+ {"sysret", 0, 0, 0, 0 },
+ {"invd", 0, 0, 0, 0 },
+ {"wbinvd", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"ud2", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ // 0x10
+ {"movups\0"
+ "movupd\0"
+ "movsd\0"
+ "movss", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"movups\0"
+ "movupd\0"
+ "movsd\0"
+ "movss", MODRM|VAR_NAME4,PARAM_XMMM, PARAM_XMM, 0 },
+ {"movlps\0"
+ "movlpd\0"
+ "movddup\0"
+ "movsldup", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"movlps\0"
+ "movlpd\0"
+ "???\0"
+ "???", MODRM|VAR_NAME4,PARAM_XMMM, PARAM_XMM, 0 },
+ {"unpcklps\0"
+ "unpcklpd\0"
+ "???\0"
+ "???", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"unpckhps\0"
+ "unpckhpd\0"
+ "???\0"
+ "???", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"movhps\0"
+ "movhpd\0"
+ "???\0"
+ "movshdup", MODRM|VAR_NAME4,PARAM_XMMM, PARAM_XMM, 0 },
+ {"movhps\0"
+ "movhpd\0"
+ "???\0"
+ "???", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"group0F18", GROUP, 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 },
+ // 0x20
+ {"mov", MODRM, PARAM_REG2_32, PARAM_CREG, 0 },
+ {"mov", MODRM, PARAM_REG2_32, PARAM_DREG, 0 },
+ {"mov", MODRM, PARAM_CREG, PARAM_REG2_32, 0 },
+ {"mov", MODRM, PARAM_DREG, PARAM_REG2_32, 0 },
+ {"mov", MODRM, PARAM_REG2_32, PARAM_TREG, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"mov", MODRM, PARAM_TREG, PARAM_REG2_32, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"movaps\0"
+ "movapd\0"
+ "???\0"
+ "???", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"movaps\0"
+ "movapd\0"
+ "???\0"
+ "???", MODRM|VAR_NAME4,PARAM_XMMM, PARAM_XMM, 0 },
+ {"cvtpi2ps\0"
+ "cvtpi2pd\0"
+ "cvtsi2sd\0"
+ "cvtsi2ss", MODRM|VAR_NAME4,PARAM_XMM, PARAM_RMXMM, 0 },
+ {"movntps\0"
+ "movntpd\0"
+ "???\0"
+ "???", MODRM|VAR_NAME4,PARAM_XMMM, PARAM_XMM, 0 },
+ {"cvttps2pi\0"
+ "cvttpd2pi\0"
+ "cvttsd2si\0"
+ "cvttss2si", MODRM|VAR_NAME4,PARAM_REGORXMM, PARAM_XMMM, 0 },
+ {"cvtps2pi\0"
+ "cvtpd2pi\0"
+ "cvtsd2si\0"
+ "cvtss2si", MODRM|VAR_NAME4,PARAM_REGORXMM, PARAM_XMMM, 0 },
+ {"ucomiss\0"
+ "ucomisd\0"
+ "???\0"
+ "???", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"comiss\0"
+ "comisd\0"
+ "???\0"
+ "???", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ // 0x30
+ {"wrmsr", 0, 0, 0, 0 },
+ {"rdtsc", 0, 0, 0, 0 },
+ {"rdmsr", 0, 0, 0, 0 },
+ {"rdpmc", 0, 0, 0, 0 },
+ {"sysenter", 0, 0, 0, 0 },
+ {"sysexit", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ // 0x40
+ {"cmovo", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"cmovno", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"cmovb", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"cmovae", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"cmove", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"cmovne", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"cmovbe", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"cmova", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"cmovs", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"cmovns", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"cmovpe", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"cmovpo", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"cmovl", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"cmovge", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"cmovle", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"cmovg", MODRM, PARAM_REG, PARAM_RM, 0 },
+ // 0x50
+ {"movmskps\0"
+ "movmskpd\0"
+ "???\0"
+ "???", MODRM|VAR_NAME4,PARAM_REG3264, PARAM_XMMM, 0 },
+ {"sqrtps\0"
+ "sqrtpd\0"
+ "sqrtsd\0"
+ "sqrtss", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"rsqrtps\0"
+ "???\0"
+ "???\0"
+ "rsqrtss", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"rcpps\0"
+ "???\0"
+ "???\0"
+ "rcpss", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"andps\0"
+ "andpd\0"
+ "???\0"
+ "???", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"andnps\0"
+ "andnpd\0"
+ "???\0"
+ "???", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"orps\0"
+ "orpd\0"
+ "???\0"
+ "???", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"xorps\0"
+ "xorpd\0"
+ "???\0"
+ "???", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"addps\0"
+ "addpd\0"
+ "addsd\0"
+ "addss", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"mulps\0"
+ "mulpd\0"
+ "mulsd\0"
+ "mulss", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"cvtps2pd\0"
+ "cvtpd2ps\0"
+ "cvtsd2ss\0"
+ "cvtss2sd", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"cvtdq2ps\0"
+ "cvtps2dq\0"
+ "???\0"
+ "cvttps2dq", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"subps\0"
+ "subpd\0"
+ "subsd\0"
+ "subss", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"minps\0"
+ "minpd\0"
+ "minsd\0"
+ "minss", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"divps\0"
+ "divpd\0"
+ "divsd\0"
+ "divss", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"maxps\0"
+ "maxpd\0"
+ "maxsd\0"
+ "maxss", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ // 0x60
+ {"punpcklbw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"punpcklwd", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"punpckldq", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"packsswb", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"pcmpgtb", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"pcmpgtw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"pcmpgtd", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"packuswb", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"punpckhbw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"punpckhwd", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"punpckhdq", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"packssdw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"punpcklqdq", MODRM, PARAM_XMM, PARAM_XMMM, 0 },
+ {"punpckhqdq", MODRM, PARAM_XMM, PARAM_XMMM, 0 },
+ {"movd", MODRM, PARAM_MMX, PARAM_RM, 0 },
+ {"movq\0"
+ "movdqa\0"
+ "???\0"
+ "movdqu", MODRM|VAR_NAME4,PARAM_MMX, PARAM_MMXM, 0 },
+ // 0x70
+ {"pshufw\0"
+ "pshufd\0"
+ "pshuflw\0"
+ "pshufhw", MODRM|VAR_NAME4,PARAM_MMX, PARAM_MMXM, PARAM_I8 },
+ {"group0F71", GROUP, 0, 0, 0 },
+ {"group0F72", GROUP, 0, 0, 0 },
+ {"group0F73", GROUP, 0, 0, 0 },
+ {"pcmpeqb", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"pcmpeqw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"pcmpeqd", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"emms", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???\0"
+ "haddpd\0"
+ "haddps\0"
+ "???", MODRM|VAR_NAME4,PARAM_MMX, PARAM_MMXM, 0 },
+ {"???\0"
+ "hsubpd\0"
+ "hsubps\0"
+ "???", MODRM|VAR_NAME4,PARAM_MMX, PARAM_MMXM, 0 },
+ {"movd\0"
+ "movd\0"
+ "???\0"
+ "movq", MODRM|VAR_NAME4,PARAM_RM, PARAM_MMX, 0 },
+ {"movq\0"
+ "movdqa\0"
+ "???\0"
+ "movdqu", MODRM|VAR_NAME4,PARAM_MMXM, PARAM_MMX, 0 },
+ // 0x80
+ {"jo", 0, PARAM_REL, 0, 0 },
+ {"jno", 0, PARAM_REL, 0, 0 },
+ {"jb", 0, PARAM_REL, 0, 0 },
+ {"jae", 0, PARAM_REL, 0, 0 },
+ {"je", 0, PARAM_REL, 0, 0 },
+ {"jne", 0, PARAM_REL, 0, 0 },
+ {"jbe", 0, PARAM_REL, 0, 0 },
+ {"ja", 0, PARAM_REL, 0, 0 },
+ {"js", 0, PARAM_REL, 0, 0 },
+ {"jns", 0, PARAM_REL, 0, 0 },
+ {"jp", 0, PARAM_REL, 0, 0 },
+ {"jnp", 0, PARAM_REL, 0, 0 },
+ {"jl", 0, PARAM_REL, 0, 0 },
+ {"jge", 0, PARAM_REL, 0, 0 },
+ {"jle", 0, PARAM_REL, 0, 0 },
+ {"jg", 0, PARAM_REL, 0, 0 },
+ // 0x90
+ {"seto", MODRM, PARAM_RMPTR8, 0, 0 },
+ {"setno", MODRM, PARAM_RMPTR8, 0, 0 },
+ {"setb", MODRM, PARAM_RMPTR8, 0, 0 },
+ {"setae", MODRM, PARAM_RMPTR8, 0, 0 },
+ {"sete", MODRM, PARAM_RMPTR8, 0, 0 },
+ {"setne", MODRM, PARAM_RMPTR8, 0, 0 },
+ {"setbe", MODRM, PARAM_RMPTR8, 0, 0 },
+ {"seta", MODRM, PARAM_RMPTR8, 0, 0 },
+ {"sets", MODRM, PARAM_RMPTR8, 0, 0 },
+ {"setns", MODRM, PARAM_RMPTR8, 0, 0 },
+ {"setp", MODRM, PARAM_RMPTR8, 0, 0 },
+ {"setnp", MODRM, PARAM_RMPTR8, 0, 0 },
+ {"setl", MODRM, PARAM_RMPTR8, 0, 0 },
+ {"setge", MODRM, PARAM_RMPTR8, 0, 0 },
+ {"setle", MODRM, PARAM_RMPTR8, 0, 0 },
+ {"setg", MODRM, PARAM_RMPTR8, 0, 0 },
+ // 0xa0
+ {"push fs", 0, 0, 0, 0 },
+ {"pop fs", 0, 0, 0, 0 },
+ {"cpuid", 0, 0, 0, 0 },
+ {"bt", MODRM, PARAM_RM, PARAM_REG, 0 },
+ {"shld", MODRM, PARAM_RM, PARAM_REG, PARAM_I8 },
+ {"shld", MODRM, PARAM_RM, PARAM_REG, PARAM_CL },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"push gs", 0, 0, 0, 0 },
+ {"pop gs", 0, 0, 0, 0 },
+ {"rsm", 0, 0, 0, 0 },
+ {"bts", MODRM, PARAM_RM, PARAM_REG, 0 },
+ {"shrd", MODRM, PARAM_RM, PARAM_REG, PARAM_I8 },
+ {"shrd", MODRM, PARAM_RM, PARAM_REG, PARAM_CL },
+ {"group0FAE", GROUP, 0, 0, 0 },
+ {"imul", MODRM, PARAM_REG, PARAM_RM, 0 },
+ // 0xb0
+ {"cmpxchg", MODRM, PARAM_RM8, PARAM_REG, 0 },
+ {"cmpxchg", MODRM, PARAM_RM, PARAM_REG, 0 },
+ {"lss", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"btr", MODRM, PARAM_RM, PARAM_REG, 0 },
+ {"lfs", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"lgs", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"movzx", MODRM, PARAM_REG, PARAM_RMPTR8, 0 },
+ {"movzx", MODRM, PARAM_REG, PARAM_RMPTR16, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"group0FBA", GROUP, 0, 0, 0 },
+ {"btc", MODRM, PARAM_RM, PARAM_REG, 0 },
+ {"bsf", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"bsr", MODRM, PARAM_REG, PARAM_RM, 0, DASMFLAG_STEP_OVER},
+ {"movsx", MODRM, PARAM_REG, PARAM_RMPTR8, 0 },
+ {"movsx", MODRM, PARAM_REG, PARAM_RMPTR16, 0 },
+ // 0xc0
+ {"xadd", MODRM, PARAM_RM8, PARAM_REG, 0 },
+ {"xadd", MODRM, PARAM_RM, PARAM_REG, 0 },
+ {"cmpps\0"
+ "cmppd\0"
+ "cmpsd\0"
+ "cmpss", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"movnti", MODRM, PARAM_RM, PARAM_REG, 0 },
+ {"pinsrw", MODRM, PARAM_MMX, PARAM_MMXM, PARAM_I8 },
+ {"pextrw", MODRM, PARAM_MMX, PARAM_MMXM, PARAM_I8 },
+ {"shufps\0"
+ "shufpd\0"
+ "???\0"
+ "???", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, PARAM_I8 },
+ {"cmpxchg8b", MODRM, PARAM_M64PTR, 0, 0 },
+ {"bswap", 0, PARAM_EAX, 0, 0 },
+ {"bswap", 0, PARAM_ECX, 0, 0 },
+ {"bswap", 0, PARAM_EDX, 0, 0 },
+ {"bswap", 0, PARAM_EBX, 0, 0 },
+ {"bswap", 0, PARAM_ESP, 0, 0 },
+ {"bswap", 0, PARAM_EBP, 0, 0 },
+ {"bswap", 0, PARAM_ESI, 0, 0 },
+ {"bswap", 0, PARAM_EDI, 0, 0 },
+ // 0xd0
+ {"addsubpd\0"
+ "???\0"
+ "addsubps\0"
+ "???\0", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"psrlw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"psrld", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"psrlq", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"paddq", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"pmullw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"movq\0"
+ "???\0"
+ "movdq2q\0"
+ "movq2dq", MODRM|VAR_NAME4,PARAM_MMX, PARAM_MMXM, 0 },
+ {"pmovmskb", MODRM, PARAM_REG3264, PARAM_MMXM, 0 },
+ {"psubusb", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"psubusw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"pminub", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"pand", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"paddub", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"padduw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"pmaxub", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"pandn", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ // 0xe0
+ {"pavgb", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"psraw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"psrad", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"pavgw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"pmulhuw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"pmulhw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"???\0"
+ "cvttpd2dq\0"
+ "cvtpd2dq\0"
+ "cvtdq2pd", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"movntq", MODRM, PARAM_M64, PARAM_MMX, 0 },
+ {"psubsb", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"psubsw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"pminsw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"por", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"paddsb", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"paddsw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"pmaxsw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"pxor", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ // 0xf0
+ {"???\0"
+ "???\0"
+ "lddqu\0"
+ "???", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"psllw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"pslld", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"psllq", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"pmuludq", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"pmaddwd", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"psadbw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"maskmovq\0"
+ "maskmovdqu\0"
+ "???\0"
+ "???", MODRM|VAR_NAME4,PARAM_MMX, PARAM_MMXM, 0 },
+ {"psubb", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"psubw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"psubd", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"psubq", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"paddb", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"paddw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"paddd", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"???", 0, 0, 0, 0 }
+};
+
+static const I386_OPCODE group80_table[8] =
+{
+ {"add", 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {"or", 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {"adc", 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {"sbb", 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {"and", 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {"sub", 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {"xor", 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {"cmp", 0, PARAM_RMPTR8, PARAM_I8, 0 }
+};
+
+static const I386_OPCODE group81_table[8] =
+{
+ {"add", 0, PARAM_RMPTR, PARAM_IMM, 0 },
+ {"or", 0, PARAM_RMPTR, PARAM_IMM, 0 },
+ {"adc", 0, PARAM_RMPTR, PARAM_IMM, 0 },
+ {"sbb", 0, PARAM_RMPTR, PARAM_IMM, 0 },
+ {"and", 0, PARAM_RMPTR, PARAM_IMM, 0 },
+ {"sub", 0, PARAM_RMPTR, PARAM_IMM, 0 },
+ {"xor", 0, PARAM_RMPTR, PARAM_IMM, 0 },
+ {"cmp", 0, PARAM_RMPTR, PARAM_IMM, 0 }
+};
+
+static const I386_OPCODE group83_table[8] =
+{
+ {"add", 0, PARAM_RMPTR, PARAM_I8, 0 },
+ {"or", 0, PARAM_RMPTR, PARAM_I8, 0 },
+ {"adc", 0, PARAM_RMPTR, PARAM_I8, 0 },
+ {"sbb", 0, PARAM_RMPTR, PARAM_I8, 0 },
+ {"and", 0, PARAM_RMPTR, PARAM_I8, 0 },
+ {"sub", 0, PARAM_RMPTR, PARAM_I8, 0 },
+ {"xor", 0, PARAM_RMPTR, PARAM_I8, 0 },
+ {"cmp", 0, PARAM_RMPTR, PARAM_I8, 0 }
+};
+
+static const I386_OPCODE groupC0_table[8] =
+{
+ {"rol", 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {"ror", 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {"rcl", 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {"rcr", 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {"shl", 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {"shr", 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {"sal", 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {"sar", 0, PARAM_RMPTR8, PARAM_I8, 0 }
+};
+
+static const I386_OPCODE groupC1_table[8] =
+{
+ {"rol", 0, PARAM_RMPTR, PARAM_I8, 0 },
+ {"ror", 0, PARAM_RMPTR, PARAM_I8, 0 },
+ {"rcl", 0, PARAM_RMPTR, PARAM_I8, 0 },
+ {"rcr", 0, PARAM_RMPTR, PARAM_I8, 0 },
+ {"shl", 0, PARAM_RMPTR, PARAM_I8, 0 },
+ {"shr", 0, PARAM_RMPTR, PARAM_I8, 0 },
+ {"sal", 0, PARAM_RMPTR, PARAM_I8, 0 },
+ {"sar", 0, PARAM_RMPTR, PARAM_I8, 0 }
+};
+
+static const I386_OPCODE groupD0_table[8] =
+{
+ {"rol", 0, PARAM_RMPTR8, PARAM_1, 0 },
+ {"ror", 0, PARAM_RMPTR8, PARAM_1, 0 },
+ {"rcl", 0, PARAM_RMPTR8, PARAM_1, 0 },
+ {"rcr", 0, PARAM_RMPTR8, PARAM_1, 0 },
+ {"shl", 0, PARAM_RMPTR8, PARAM_1, 0 },
+ {"shr", 0, PARAM_RMPTR8, PARAM_1, 0 },
+ {"sal", 0, PARAM_RMPTR8, PARAM_1, 0 },
+ {"sar", 0, PARAM_RMPTR8, PARAM_1, 0 }
+};
+
+static const I386_OPCODE groupD1_table[8] =
+{
+ {"rol", 0, PARAM_RMPTR, PARAM_1, 0 },
+ {"ror", 0, PARAM_RMPTR, PARAM_1, 0 },
+ {"rcl", 0, PARAM_RMPTR, PARAM_1, 0 },
+ {"rcr", 0, PARAM_RMPTR, PARAM_1, 0 },
+ {"shl", 0, PARAM_RMPTR, PARAM_1, 0 },
+ {"shr", 0, PARAM_RMPTR, PARAM_1, 0 },
+ {"sal", 0, PARAM_RMPTR, PARAM_1, 0 },
+ {"sar", 0, PARAM_RMPTR, PARAM_1, 0 }
+};
+
+static const I386_OPCODE groupD2_table[8] =
+{
+ {"rol", 0, PARAM_RMPTR8, PARAM_CL, 0 },
+ {"ror", 0, PARAM_RMPTR8, PARAM_CL, 0 },
+ {"rcl", 0, PARAM_RMPTR8, PARAM_CL, 0 },
+ {"rcr", 0, PARAM_RMPTR8, PARAM_CL, 0 },
+ {"shl", 0, PARAM_RMPTR8, PARAM_CL, 0 },
+ {"shr", 0, PARAM_RMPTR8, PARAM_CL, 0 },
+ {"sal", 0, PARAM_RMPTR8, PARAM_CL, 0 },
+ {"sar", 0, PARAM_RMPTR8, PARAM_CL, 0 }
+};
+
+static const I386_OPCODE groupD3_table[8] =
+{
+ {"rol", 0, PARAM_RMPTR, PARAM_CL, 0 },
+ {"ror", 0, PARAM_RMPTR, PARAM_CL, 0 },
+ {"rcl", 0, PARAM_RMPTR, PARAM_CL, 0 },
+ {"rcr", 0, PARAM_RMPTR, PARAM_CL, 0 },
+ {"shl", 0, PARAM_RMPTR, PARAM_CL, 0 },
+ {"shr", 0, PARAM_RMPTR, PARAM_CL, 0 },
+ {"sal", 0, PARAM_RMPTR, PARAM_CL, 0 },
+ {"sar", 0, PARAM_RMPTR, PARAM_CL, 0 }
+};
+
+static const I386_OPCODE groupF6_table[8] =
+{
+ {"test", 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"not", 0, PARAM_RMPTR8, 0, 0 },
+ {"neg", 0, PARAM_RMPTR8, 0, 0 },
+ {"mul", 0, PARAM_RMPTR8, 0, 0 },
+ {"imul", 0, PARAM_RMPTR8, 0, 0 },
+ {"div", 0, PARAM_RMPTR8, 0, 0 },
+ {"idiv", 0, PARAM_RMPTR8, 0, 0 }
+};
+
+static const I386_OPCODE groupF7_table[8] =
+{
+ {"test", 0, PARAM_RMPTR, PARAM_IMM, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"not", 0, PARAM_RMPTR, 0, 0 },
+ {"neg", 0, PARAM_RMPTR, 0, 0 },
+ {"mul", 0, PARAM_RMPTR, 0, 0 },
+ {"imul", 0, PARAM_RMPTR, 0, 0 },
+ {"div", 0, PARAM_RMPTR, 0, 0 },
+ {"idiv", 0, PARAM_RMPTR, 0, 0 }
+};
+
+static const I386_OPCODE groupFE_table[8] =
+{
+ {"inc", 0, PARAM_RMPTR8, 0, 0 },
+ {"dec", 0, PARAM_RMPTR8, 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 }
+};
+
+static const I386_OPCODE groupFF_table[8] =
+{
+ {"inc", 0, PARAM_RMPTR, 0, 0 },
+ {"dec", 0, PARAM_RMPTR, 0, 0 },
+ {"call", ALWAYS64, PARAM_RMPTR, 0, 0, DASMFLAG_STEP_OVER},
+ {"call far ptr ",0, PARAM_RM, 0, 0, DASMFLAG_STEP_OVER},
+ {"jmp", ALWAYS64, PARAM_RMPTR, 0, 0 },
+ {"jmp far ptr ",0, PARAM_RM, 0, 0 },
+ {"push", 0, PARAM_RMPTR, 0, 0 },
+ {"???", 0, 0, 0, 0 }
+};
+
+static const I386_OPCODE group0F00_table[8] =
+{
+ {"sldt", 0, PARAM_RM, 0, 0 },
+ {"str", 0, PARAM_RM, 0, 0 },
+ {"lldt", 0, PARAM_RM, 0, 0 },
+ {"ltr", 0, PARAM_RM, 0, 0 },
+ {"verr", 0, PARAM_RM, 0, 0 },
+ {"verw", 0, PARAM_RM, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 }
+};
+
+static const I386_OPCODE group0F01_table[8] =
+{
+ {"sgdt", 0, PARAM_RM, 0, 0 },
+ {"sidt", 0, PARAM_RM, 0, 0 },
+ {"lgdt", 0, PARAM_RM, 0, 0 },
+ {"lidt", 0, PARAM_RM, 0, 0 },
+ {"smsw", 0, PARAM_RM, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"lmsw", 0, PARAM_RM, 0, 0 },
+ {"invlpg", 0, PARAM_RM, 0, 0 }
+};
+
+static const I386_OPCODE group0F18_table[8] =
+{
+ {"prefetchnta", 0, PARAM_RM8, 0, 0 },
+ {"prefetch0", 0, PARAM_RM8, 0, 0 },
+ {"prefetch1", 0, PARAM_RM8, 0, 0 },
+ {"prefetch2", 0, PARAM_RM8, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 }
+};
+
+static const I386_OPCODE group0F71_table[8] =
+{
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"psrlw", 0, PARAM_MMX, PARAM_I8, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"psraw", 0, PARAM_MMX, PARAM_I8, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"psllw", 0, PARAM_MMX, PARAM_I8, 0 },
+ {"???", 0, 0, 0, 0 }
+};
+
+static const I386_OPCODE group0F72_table[8] =
+{
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"psrld", 0, PARAM_MMX, PARAM_I8, 0 },
+ {"psrldq", 0, PARAM_MMX, PARAM_I8, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"pslld", 0, PARAM_MMX, PARAM_I8, 0 },
+ {"pslldq", 0, PARAM_MMX, PARAM_I8, 0 },
+};
+
+static const I386_OPCODE group0F73_table[8] =
+{
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"psrlq", 0, PARAM_MMX, PARAM_I8, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"psraq", 0, PARAM_MMX, PARAM_I8, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"psllq", 0, PARAM_MMX, PARAM_I8, 0 },
+ {"???", 0, 0, 0, 0 }
+};
+
+static const I386_OPCODE group0FAE_table[8] =
+{
+ {"fxsave", 0, PARAM_RM, 0, 0 },
+ {"fxrstor", 0, PARAM_RM, 0, 0 },
+ {"ldmxcsr", 0, PARAM_RM, 0, 0 },
+ {"stmxscr", 0, PARAM_RM, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"lfence", 0, 0, 0, 0 },
+ {"mfence", 0, 0, 0, 0 },
+ {"sfence", 0, 0, 0, 0 }
+};
+
+
+static const I386_OPCODE group0FBA_table[8] =
+{
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"bt", 0, PARAM_RM, PARAM_I8, 0 },
+ {"bts", 0, PARAM_RM, PARAM_I8, 0 },
+ {"btr", 0, PARAM_RM, PARAM_I8, 0 },
+ {"btc", 0, PARAM_RM, PARAM_I8, 0 }
+};
+
+static const GROUP_OP group_op_table[] =
+{
+ { "group80", group80_table },
+ { "group81", group81_table },
+ { "group83", group83_table },
+ { "groupC0", groupC0_table },
+ { "groupC1", groupC1_table },
+ { "groupD0", groupD0_table },
+ { "groupD1", groupD1_table },
+ { "groupD2", groupD2_table },
+ { "groupD3", groupD3_table },
+ { "groupF6", groupF6_table },
+ { "groupF7", groupF7_table },
+ { "groupFE", groupFE_table },
+ { "groupFF", groupFF_table },
+ { "group0F00", group0F00_table },
+ { "group0F01", group0F01_table },
+ { "group0F18", group0F18_table },
+ { "group0F71", group0F71_table },
+ { "group0F72", group0F72_table },
+ { "group0F73", group0F73_table },
+ { "group0FAE", group0FAE_table },
+ { "group0FBA", group0FBA_table }
+};
+
+
+
+static const char *const i386_reg[3][16] =
+{
+ {"ax", "cx", "dx", "bx", "sp", "bp", "si", "di", "r8w", "r9w", "r10w","r11w","r12w","r13w","r14w","r15w"},
+ {"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "r8d", "r9d", "r10d","r11d","r12d","r13d","r14d","r15d"},
+ {"rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"}
+};
+
+static const char *const i386_reg8[8] = {"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"};
+static const char *const i386_reg8rex[16] = {"al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil", "r8l", "r9l", "r10l", "r11l", "r12l", "r13l", "r14l", "r15l"};
+static const char *const i386_sreg[8] = {"es", "cs", "ss", "ds", "fs", "gs", "???", "???"};
+
+static int address_size;
+static int operand_size;
+static int max_length;
+static UINT64 pc;
+static UINT8 modrm;
+static UINT32 segment;
+static offs_t dasm_flags;
+static char modrm_string[256];
+static UINT8 rex, regex, sibex, rmex;
+static UINT8 pre0f;
+static UINT8 curmode;
+
+#define MODRM_REG1 ((modrm >> 3) & 0x7)
+#define MODRM_REG2 (modrm & 0x7)
+
+INLINE UINT8 FETCH(void)
+{
+ if ((opcode_ptr - opcode_ptr_base) + 1 > max_length)
+ return 0xff;
+ pc++;
+ return *opcode_ptr++;
+}
+
+INLINE UINT16 FETCH16(void)
+{
+ UINT16 d;
+ if ((opcode_ptr - opcode_ptr_base) + 2 > max_length)
+ return 0xffff;
+ d = opcode_ptr[0] | (opcode_ptr[1] << 8);
+ opcode_ptr += 2;
+ pc += 2;
+ return d;
+}
+
+INLINE UINT32 FETCH32(void)
+{
+ UINT32 d;
+ if ((opcode_ptr - opcode_ptr_base) + 4 > max_length)
+ return 0xffffffff;
+ d = opcode_ptr[0] | (opcode_ptr[1] << 8) | (opcode_ptr[2] << 16) | (opcode_ptr[3] << 24);
+ opcode_ptr += 4;
+ pc += 4;
+ return d;
+}
+
+INLINE UINT8 FETCHD(void)
+{
+ if ((opcode_ptr - opcode_ptr_base) + 1 > max_length)
+ return 0xff;
+ pc++;
+ return *opcode_ptr++;
+}
+
+INLINE UINT16 FETCHD16(void)
+{
+ UINT16 d;
+ if ((opcode_ptr - opcode_ptr_base) + 2 > max_length)
+ return 0xffff;
+ d = opcode_ptr[0] | (opcode_ptr[1] << 8);
+ opcode_ptr += 2;
+ pc += 2;
+ return d;
+}
+
+INLINE UINT32 FETCHD32(void)
+{
+ UINT32 d;
+ if ((opcode_ptr - opcode_ptr_base) + 4 > max_length)
+ return 0xffffffff;
+ d = opcode_ptr[0] | (opcode_ptr[1] << 8) | (opcode_ptr[2] << 16) | (opcode_ptr[3] << 24);
+ opcode_ptr += 4;
+ pc += 4;
+ return d;
+}
+
+static char *hexstring(UINT32 value, int digits)
+{
+ static char buffer[20];
+ buffer[0] = '0';
+ if (digits)
+ sprintf(&buffer[1], "%0*Xh", digits, value);
+ else
+ sprintf(&buffer[1], "%Xh", value);
+ return (buffer[1] >= '0' && buffer[1] <= '9') ? &buffer[1] : &buffer[0];
+}
+
+static char *hexstring64(UINT32 lo, UINT32 hi)
+{
+ static char buffer[40];
+ buffer[0] = '0';
+ if (hi != 0)
+ sprintf(&buffer[1], "%X%08Xh", hi, lo);
+ else
+ sprintf(&buffer[1], "%Xh", lo);
+ return (buffer[1] >= '0' && buffer[1] <= '9') ? &buffer[1] : &buffer[0];
+}
+
+static char *hexstringpc(UINT64 pc)
+{
+ if (curmode == 64)
+ return hexstring64((UINT32)pc, (UINT32)(pc >> 32));
+ else
+ return hexstring((UINT32)pc, 0);
+}
+
+static char *shexstring(UINT32 value, int digits, int always)
+{
+ static char buffer[20];
+ if (value >= 0x80000000)
+ sprintf(buffer, "-%s", hexstring(-value, digits));
+ else if (always)
+ sprintf(buffer, "+%s", hexstring(value, digits));
+ else
+ return hexstring(value, digits);
+ return buffer;
+}
+
+static char* handle_sib_byte( char* s, UINT8 mod )
+{
+ UINT32 i32;
+ UINT8 scale, i, base;
+ UINT8 sib = FETCHD();
+
+ scale = (sib >> 6) & 0x3;
+ i = ((sib >> 3) & 0x7) | sibex;
+ base = (sib & 0x7) | rmex;
+
+ if (base == 5 && mod == 0) {
+ i32 = FETCH32();
+ s += sprintf( s, "%s", hexstring(i32, 0) );
+ } else if (base != 5 || mod != 3)
+ s += sprintf( s, "%s", i386_reg[address_size][base] );
+
+ if ( i != 4 ) {
+ s += sprintf( s, "+%s", i386_reg[address_size][i] );
+ if (scale)
+ s += sprintf( s, "*%d", 1 << scale );
+ }
+ return s;
+}
+
+static void handle_modrm(char* s)
+{
+ INT8 disp8;
+ INT16 disp16;
+ INT32 disp32;
+ UINT8 mod, rm;
+
+ modrm = FETCHD();
+ mod = (modrm >> 6) & 0x3;
+ rm = (modrm & 0x7) | rmex;
+
+ if( modrm >= 0xc0 )
+ return;
+
+ switch(segment)
+ {
+ case SEG_CS: s += sprintf( s, "cs:" ); break;
+ case SEG_DS: s += sprintf( s, "ds:" ); break;
+ case SEG_ES: s += sprintf( s, "es:" ); break;
+ case SEG_FS: s += sprintf( s, "fs:" ); break;
+ case SEG_GS: s += sprintf( s, "gs:" ); break;
+ case SEG_SS: s += sprintf( s, "ss:" ); break;
+ }
+
+ s += sprintf( s, "[" );
+ if( address_size == 2 ) {
+ if ((rm & 7) == 4)
+ s = handle_sib_byte( s, mod );
+ else if ((rm & 7) == 5 && mod == 0) {
+ disp32 = FETCHD32();
+ s += sprintf( s, "rip%s", shexstring(disp32, 0, TRUE) );
+ } else
+ s += sprintf( s, "%s", i386_reg[2][rm]);
+ if( mod == 1 ) {
+ disp8 = FETCHD();
+ if (disp8 != 0)
+ s += sprintf( s, "%s", shexstring((INT32)disp8, 0, TRUE) );
+ } else if( mod == 2 ) {
+ disp32 = FETCHD32();
+ if (disp32 != 0)
+ s += sprintf( s, "%s", shexstring(disp32, 0, TRUE) );
+ }
+ } else if (address_size == 1) {
+ if ((rm & 7) == 4)
+ s = handle_sib_byte( s, mod );
+ else if ((rm & 7) == 5 && mod == 0) {
+ disp32 = FETCHD32();
+ if (curmode == 64)
+ s += sprintf( s, "eip%s", shexstring(disp32, 0, TRUE) );
+ else
+ s += sprintf( s, "%s", hexstring(disp32, 0) );
+ } else
+ s += sprintf( s, "%s", i386_reg[1][rm]);
+ if( mod == 1 ) {
+ disp8 = FETCHD();
+ if (disp8 != 0)
+ s += sprintf( s, "%s", shexstring((INT32)disp8, 0, TRUE) );
+ } else if( mod == 2 ) {
+ disp32 = FETCHD32();
+ if (disp32 != 0)
+ s += sprintf( s, "%s", shexstring(disp32, 0, TRUE) );
+ }
+ } else {
+ switch( rm )
+ {
+ case 0: s += sprintf( s, "bx+si" ); break;
+ case 1: s += sprintf( s, "bx+di" ); break;
+ case 2: s += sprintf( s, "bp+si" ); break;
+ case 3: s += sprintf( s, "bp+di" ); break;
+ case 4: s += sprintf( s, "si" ); break;
+ case 5: s += sprintf( s, "di" ); break;
+ case 6:
+ if( mod == 0 ) {
+ disp16 = FETCHD16();
+ s += sprintf( s, "%s", hexstring((unsigned) (UINT16) disp16, 0) );
+ } else {
+ s += sprintf( s, "bp" );
+ }
+ break;
+ case 7: s += sprintf( s, "bx" ); break;
+ }
+ if( mod == 1 ) {
+ disp8 = FETCHD();
+ if (disp8 != 0)
+ s += sprintf( s, "%s", shexstring((INT32)disp8, 0, TRUE) );
+ } else if( mod == 2 ) {
+ disp16 = FETCHD16();
+ if (disp16 != 0)
+ s += sprintf( s, "%s", shexstring((INT32)disp16, 0, TRUE) );
+ }
+ }
+ s += sprintf( s, "]" );
+}
+
+static char* handle_param(char* s, UINT32 param)
+{
+ UINT8 i8;
+ UINT16 i16;
+ UINT32 i32;
+ UINT16 ptr;
+ UINT32 addr;
+ INT8 d8;
+ INT16 d16;
+ INT32 d32;
+
+ switch(param)
+ {
+ case PARAM_REG:
+ s += sprintf( s, "%s", i386_reg[operand_size][MODRM_REG1 | regex] );
+ break;
+
+ case PARAM_REG8:
+ s += sprintf( s, "%s", (rex ? i386_reg8rex : i386_reg8)[MODRM_REG1 | regex] );
+ break;
+
+ case PARAM_REG16:
+ s += sprintf( s, "%s", i386_reg[0][MODRM_REG1 | regex] );
+ break;
+
+ case PARAM_REG32:
+ s += sprintf( s, "%s", i386_reg[1][MODRM_REG1 | regex] );
+ break;
+
+ case PARAM_REG3264:
+ s += sprintf( s, "%s", i386_reg[(operand_size == 2) ? 2 : 1][MODRM_REG1 | regex] );
+ break;
+
+ case PARAM_MMX:
+ if (pre0f == 0x66 || pre0f == 0xf2 || pre0f == 0xf3)
+ s += sprintf( s, "xmm%d", MODRM_REG1 | regex );
+ else
+ s += sprintf( s, "mm%d", MODRM_REG1 | regex );
+ break;
+
+ case PARAM_XMM:
+ s += sprintf( s, "xmm%d", MODRM_REG1 | regex );
+ break;
+
+ case PARAM_REGORXMM:
+ if (pre0f != 0xf2 && pre0f != 0xf3)
+ s += sprintf( s, "xmm%d", MODRM_REG1 | regex );
+ else
+ s += sprintf( s, "%s", i386_reg[(operand_size == 2) ? 2 : 1][MODRM_REG1 | regex] );
+ break;
+
+ case PARAM_REG2_32:
+ s += sprintf( s, "%s", i386_reg[1][MODRM_REG2 | rmex] );
+ break;
+
+ case PARAM_RM:
+ case PARAM_RMPTR:
+ if( modrm >= 0xc0 ) {
+ s += sprintf( s, "%s", i386_reg[operand_size][MODRM_REG2 | rmex] );
+ } else {
+ if (param == PARAM_RMPTR)
+ {
+ if( operand_size == 2 )
+ s += sprintf( s, "qword ptr " );
+ else if (operand_size == 1)
+ s += sprintf( s, "dword ptr " );
+ else
+ s += sprintf( s, "word ptr " );
+ }
+ s += sprintf( s, "%s", modrm_string );
+ }
+ break;
+
+ case PARAM_RM8:
+ case PARAM_RMPTR8:
+ if( modrm >= 0xc0 ) {
+ s += sprintf( s, "%s", (rex ? i386_reg8rex : i386_reg8)[MODRM_REG2 | rmex] );
+ } else {
+ if (param == PARAM_RMPTR8)
+ s += sprintf( s, "byte ptr " );
+ s += sprintf( s, "%s", modrm_string );
+ }
+ break;
+
+ case PARAM_RM16:
+ case PARAM_RMPTR16:
+ if( modrm >= 0xc0 ) {
+ s += sprintf( s, "%s", i386_reg[0][MODRM_REG2 | rmex] );
+ } else {
+ if (param == PARAM_RMPTR16)
+ s += sprintf( s, "word ptr " );
+ s += sprintf( s, "%s", modrm_string );
+ }
+ break;
+
+ case PARAM_RM32:
+ case PARAM_RMPTR32:
+ if( modrm >= 0xc0 ) {
+ s += sprintf( s, "%s", i386_reg[1][MODRM_REG2 | rmex] );
+ } else {
+ if (param == PARAM_RMPTR32)
+ s += sprintf( s, "dword ptr " );
+ s += sprintf( s, "%s", modrm_string );
+ }
+ break;
+
+ case PARAM_RMXMM:
+ if( modrm >= 0xc0 ) {
+ if (pre0f != 0xf2 && pre0f != 0xf3)
+ s += sprintf( s, "xmm%d", MODRM_REG2 | rmex );
+ else
+ s += sprintf( s, "%s", i386_reg[(operand_size == 2) ? 2 : 1][MODRM_REG2 | rmex] );
+ } else {
+ if (param == PARAM_RMPTR32)
+ s += sprintf( s, "dword ptr " );
+ s += sprintf( s, "%s", modrm_string );
+ }
+ break;
+
+ case PARAM_M64:
+ case PARAM_M64PTR:
+ if( modrm >= 0xc0 ) {
+ s += sprintf( s, "???" );
+ } else {
+ if (param == PARAM_M64PTR)
+ s += sprintf( s, "qword ptr " );
+ s += sprintf( s, "%s", modrm_string );
+ }
+ break;
+
+ case PARAM_MMXM:
+ if( modrm >= 0xc0 ) {
+ if (pre0f == 0x66 || pre0f == 0xf2 || pre0f == 0xf3)
+ s += sprintf( s, "xmm%d", MODRM_REG2 | rmex );
+ else
+ s += sprintf( s, "mm%d", MODRM_REG2 | rmex );
+ } else {
+ s += sprintf( s, "%s", modrm_string );
+ }
+ break;
+
+ case PARAM_XMMM:
+ if( modrm >= 0xc0 ) {
+ s += sprintf( s, "xmm%d", MODRM_REG2 | rmex );
+ } else {
+ s += sprintf( s, "%s", modrm_string );
+ }
+ break;
+
+ case PARAM_I4:
+ i8 = FETCHD();
+ s += sprintf( s, "%d", i8 & 0x0f );
+ break;
+
+ case PARAM_I8:
+ i8 = FETCHD();
+ s += sprintf( s, "%s", shexstring((INT8)i8, 0, FALSE) );
+ break;
+
+ case PARAM_I16:
+ i16 = FETCHD16();
+ s += sprintf( s, "%s", shexstring((INT16)i16, 0, FALSE) );
+ break;
+
+ case PARAM_UI8:
+ i8 = FETCHD();
+ s += sprintf( s, "%s", shexstring((UINT8)i8, 0, FALSE) );
+ break;
+
+ case PARAM_UI16:
+ i16 = FETCHD16();
+ s += sprintf( s, "%s", shexstring((UINT16)i16, 0, FALSE) );
+ break;
+
+ case PARAM_IMM64:
+ if (operand_size == 2) {
+ UINT32 lo32 = FETCHD32();
+ i32 = FETCHD32();
+ s += sprintf( s, "%s", hexstring64(lo32, i32) );
+ } else if( operand_size ) {
+ i32 = FETCHD32();
+ s += sprintf( s, "%s", hexstring(i32, 0) );
+ } else {
+ i16 = FETCHD16();
+ s += sprintf( s, "%s", hexstring(i16, 0) );
+ }
+ break;
+
+ case PARAM_IMM:
+ if( operand_size ) {
+ i32 = FETCHD32();
+ s += sprintf( s, "%s", hexstring(i32, 0) );
+ } else {
+ i16 = FETCHD16();
+ s += sprintf( s, "%s", hexstring(i16, 0) );
+ }
+ break;
+
+ case PARAM_ADDR:
+ if( operand_size ) {
+ addr = FETCHD32();
+ ptr = FETCHD16();
+ s += sprintf( s, "%s:", hexstring(ptr, 4) );
+ s += sprintf( s, "%s", hexstring(addr, 0) );
+ } else {
+ addr = FETCHD16();
+ ptr = FETCHD16();
+ s += sprintf( s, "%s:", hexstring(ptr, 4) );
+ s += sprintf( s, "%s", hexstring(addr, 0) );
+ }
+ break;
+
+ case PARAM_REL:
+ if( operand_size ) {
+ d32 = FETCHD32();
+ s += sprintf( s, "%s", hexstringpc(pc + d32) );
+ } else {
+ /* make sure to keep the relative offset within the segment */
+ d16 = FETCHD16();
+ s += sprintf( s, "%s", hexstringpc((pc & 0xFFFF0000) | ((pc + d16) & 0x0000FFFF)) );
+ }
+ break;
+
+ case PARAM_REL8:
+ d8 = FETCHD();
+ s += sprintf( s, "%s", hexstringpc(pc + d8) );
+ break;
+
+ case PARAM_MEM_OFFS:
+ switch(segment)
+ {
+ case SEG_CS: s += sprintf( s, "cs:" ); break;
+ case SEG_DS: s += sprintf( s, "ds:" ); break;
+ case SEG_ES: s += sprintf( s, "es:" ); break;
+ case SEG_FS: s += sprintf( s, "fs:" ); break;
+ case SEG_GS: s += sprintf( s, "gs:" ); break;
+ case SEG_SS: s += sprintf( s, "ss:" ); break;
+ }
+
+ if( address_size ) {
+ i32 = FETCHD32();
+ s += sprintf( s, "[%s]", hexstring(i32, 0) );
+ } else {
+ i16 = FETCHD16();
+ s += sprintf( s, "[%s]", hexstring(i16, 0) );
+ }
+ break;
+
+ case PARAM_SREG:
+ s += sprintf( s, "%s", i386_sreg[MODRM_REG1] );
+ break;
+
+ case PARAM_CREG:
+ s += sprintf( s, "cr%d", MODRM_REG1 | regex );
+ break;
+
+ case PARAM_TREG:
+ s += sprintf( s, "tr%d", MODRM_REG1 | regex );
+ break;
+
+ case PARAM_DREG:
+ s += sprintf( s, "dr%d", MODRM_REG1 | regex );
+ break;
+
+ case PARAM_1:
+ s += sprintf( s, "1" );
+ break;
+
+ case PARAM_DX:
+ s += sprintf( s, "dx" );
+ break;
+
+ case PARAM_AL: s += sprintf( s, "al" ); break;
+ case PARAM_CL: s += sprintf( s, "cl" ); break;
+ case PARAM_DL: s += sprintf( s, "dl" ); break;
+ case PARAM_BL: s += sprintf( s, "bl" ); break;
+ case PARAM_AH: s += sprintf( s, "ah" ); break;
+ case PARAM_CH: s += sprintf( s, "ch" ); break;
+ case PARAM_DH: s += sprintf( s, "dh" ); break;
+ case PARAM_BH: s += sprintf( s, "bh" ); break;
+
+ case PARAM_EAX: s += sprintf( s, "%s", i386_reg[operand_size][0 | rmex] ); break;
+ case PARAM_ECX: s += sprintf( s, "%s", i386_reg[operand_size][1 | rmex] ); break;
+ case PARAM_EDX: s += sprintf( s, "%s", i386_reg[operand_size][2 | rmex] ); break;
+ case PARAM_EBX: s += sprintf( s, "%s", i386_reg[operand_size][3 | rmex] ); break;
+ case PARAM_ESP: s += sprintf( s, "%s", i386_reg[operand_size][4 | rmex] ); break;
+ case PARAM_EBP: s += sprintf( s, "%s", i386_reg[operand_size][5 | rmex] ); break;
+ case PARAM_ESI: s += sprintf( s, "%s", i386_reg[operand_size][6 | rmex] ); break;
+ case PARAM_EDI: s += sprintf( s, "%s", i386_reg[operand_size][7 | rmex] ); break;
+ }
+ return s;
+}
+
+static void handle_fpu(char *s, UINT8 op1, UINT8 op2)
+{
+ switch (op1 & 0x7)
+ {
+ case 0: // Group D8
+ {
+ if (op2 < 0xc0)
+ {
+ pc--; // adjust fetch pointer, so modrm byte read again
+ opcode_ptr--;
+ handle_modrm( modrm_string );
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: sprintf(s, "fadd dword ptr %s", modrm_string); break;
+ case 1: sprintf(s, "fmul dword ptr %s", modrm_string); break;
+ case 2: sprintf(s, "fcom dword ptr %s", modrm_string); break;
+ case 3: sprintf(s, "fcomp dword ptr %s", modrm_string); break;
+ case 4: sprintf(s, "fsub dword ptr %s", modrm_string); break;
+ case 5: sprintf(s, "fsubr dword ptr %s", modrm_string); break;
+ case 6: sprintf(s, "fdiv dword ptr %s", modrm_string); break;
+ case 7: sprintf(s, "fdivr dword ptr %s", modrm_string); break;
+ }
+ }
+ else
+ {
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: sprintf(s, "fadd st(0),st(%d)", op2 & 0x7); break;
+ case 1: sprintf(s, "fmul st(0),st(%d)", op2 & 0x7); break;
+ case 2: sprintf(s, "fcom st(0),st(%d)", op2 & 0x7); break;
+ case 3: sprintf(s, "fcomp st(0),st(%d)", op2 & 0x7); break;
+ case 4: sprintf(s, "fsub st(0),st(%d)", op2 & 0x7); break;
+ case 5: sprintf(s, "fsubr st(0),st(%d)", op2 & 0x7); break;
+ case 6: sprintf(s, "fdiv st(0),st(%d)", op2 & 0x7); break;
+ case 7: sprintf(s, "fdivr st(0),st(%d)", op2 & 0x7); break;
+ }
+ }
+ break;
+ }
+
+ case 1: // Group D9
+ {
+ if (op2 < 0xc0)
+ {
+ pc--; // adjust fetch pointer, so modrm byte read again
+ opcode_ptr--;
+ handle_modrm( modrm_string );
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: sprintf(s, "fld dword ptr %s", modrm_string); break;
+ case 1: sprintf(s, "??? (FPU)"); break;
+ case 2: sprintf(s, "fst dword ptr %s", modrm_string); break;
+ case 3: sprintf(s, "fstp dword ptr %s", modrm_string); break;
+ case 4: sprintf(s, "fldenv word ptr %s", modrm_string); break;
+ case 5: sprintf(s, "fldcw word ptr %s", modrm_string); break;
+ case 6: sprintf(s, "fstenv word ptr %s", modrm_string); break;
+ case 7: sprintf(s, "fstcw word ptr %s", modrm_string); break;
+ }
+ }
+ else
+ {
+ switch (op2 & 0x3f)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+ sprintf(s, "fld st(0),st(%d)", op2 & 0x7); break;
+
+ case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ sprintf(s, "fxch st(0),st(%d)", op2 & 0x7); break;
+
+ case 0x10: sprintf(s, "fnop"); break;
+ case 0x20: sprintf(s, "fchs"); break;
+ case 0x21: sprintf(s, "fabs"); break;
+ case 0x24: sprintf(s, "ftst"); break;
+ case 0x25: sprintf(s, "fxam"); break;
+ case 0x28: sprintf(s, "fld1"); break;
+ case 0x29: sprintf(s, "fldl2t"); break;
+ case 0x2a: sprintf(s, "fldl2e"); break;
+ case 0x2b: sprintf(s, "fldpi"); break;
+ case 0x2c: sprintf(s, "fldlg2"); break;
+ case 0x2d: sprintf(s, "fldln2"); break;
+ case 0x2e: sprintf(s, "fldz"); break;
+ case 0x30: sprintf(s, "f2xm1"); break;
+ case 0x31: sprintf(s, "fyl2x"); break;
+ case 0x32: sprintf(s, "fptan"); break;
+ case 0x33: sprintf(s, "fpatan"); break;
+ case 0x34: sprintf(s, "fxtract"); break;
+ case 0x35: sprintf(s, "fprem1"); break;
+ case 0x36: sprintf(s, "fdecstp"); break;
+ case 0x37: sprintf(s, "fincstp"); break;
+ case 0x38: sprintf(s, "fprem"); break;
+ case 0x39: sprintf(s, "fyl2xp1"); break;
+ case 0x3a: sprintf(s, "fsqrt"); break;
+ case 0x3b: sprintf(s, "fsincos"); break;
+ case 0x3c: sprintf(s, "frndint"); break;
+ case 0x3d: sprintf(s, "fscale"); break;
+ case 0x3e: sprintf(s, "fsin"); break;
+ case 0x3f: sprintf(s, "fcos"); break;
+
+ default: sprintf(s, "??? (FPU)"); break;
+ }
+ }
+ break;
+ }
+
+ case 2: // Group DA
+ {
+ if (op2 < 0xc0)
+ {
+ pc--; // adjust fetch pointer, so modrm byte read again
+ opcode_ptr--;
+ handle_modrm( modrm_string );
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: sprintf(s, "fiadd dword ptr %s", modrm_string); break;
+ case 1: sprintf(s, "fimul dword ptr %s", modrm_string); break;
+ case 2: sprintf(s, "ficom dword ptr %s", modrm_string); break;
+ case 3: sprintf(s, "ficomp dword ptr %s", modrm_string); break;
+ case 4: sprintf(s, "fisub dword ptr %s", modrm_string); break;
+ case 5: sprintf(s, "fisubr dword ptr %s", modrm_string); break;
+ case 6: sprintf(s, "fidiv dword ptr %s", modrm_string); break;
+ case 7: sprintf(s, "fidivr dword ptr %s", modrm_string); break;
+ }
+ }
+ else
+ {
+ switch (op2 & 0x3f)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+ sprintf(s, "fcmovb st(0),st(%d)", op2 & 0x7); break;
+
+ case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ sprintf(s, "fcmove st(0),st(%d)", op2 & 0x7); break;
+
+ case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
+ sprintf(s, "fcmovbe st(0),st(%d)", op2 & 0x7); break;
+
+ case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ sprintf(s, "fcmovu st(0),st(%d)", op2 & 0x7); break;
+ case 0x29:
+ sprintf(s, "fucompp"); break;
+
+ default: sprintf(s, "??? (FPU)"); break;
+
+ }
+ }
+ break;
+ }
+
+ case 3: // Group DB
+ {
+ if (op2 < 0xc0)
+ {
+ pc--; // adjust fetch pointer, so modrm byte read again
+ opcode_ptr--;
+ handle_modrm( modrm_string );
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: sprintf(s, "fild dword ptr %s", modrm_string); break;
+ case 1: sprintf(s, "fisttp dword ptr %s", modrm_string); break;
+ case 2: sprintf(s, "fist dword ptr %s", modrm_string); break;
+ case 3: sprintf(s, "fistp dword ptr %s", modrm_string); break;
+ case 4: sprintf(s, "??? (FPU)"); break;
+ case 5: sprintf(s, "fld tword ptr %s", modrm_string); break;
+ case 6: sprintf(s, "??? (FPU)"); break;
+ case 7: sprintf(s, "fstp tword ptr %s", modrm_string); break;
+ }
+ }
+ else
+ {
+ switch (op2 & 0x3f)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+ sprintf(s, "fcmovnb st(0),st(%d)", op2 & 0x7); break;
+
+ case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ sprintf(s, "fcmovne st(0),st(%d)", op2 & 0x7); break;
+
+ case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
+ sprintf(s, "fcmovnbe st(0),st(%d)", op2 & 0x7); break;
+
+ case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ sprintf(s, "fcmovnu st(0),st(%d)", op2 & 0x7); break;
+
+ case 0x22: sprintf(s, "fclex"); break;
+ case 0x23: sprintf(s, "finit"); break;
+
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ sprintf(s, "fucomi st(0),st(%d)", op2 & 0x7); break;
+
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
+ sprintf(s, "fcomi st(0),st(%d)", op2 & 0x7); break;
+
+ default: sprintf(s, "??? (FPU)"); break;
+ }
+ }
+ break;
+ }
+
+ case 4: // Group DC
+ {
+ if (op2 < 0xc0)
+ {
+ pc--; // adjust fetch pointer, so modrm byte read again
+ opcode_ptr--;
+ handle_modrm( modrm_string );
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: sprintf(s, "fadd qword ptr %s", modrm_string); break;
+ case 1: sprintf(s, "fmul qword ptr %s", modrm_string); break;
+ case 2: sprintf(s, "fcom qword ptr %s", modrm_string); break;
+ case 3: sprintf(s, "fcomp qword ptr %s", modrm_string); break;
+ case 4: sprintf(s, "fsub qword ptr %s", modrm_string); break;
+ case 5: sprintf(s, "fsubr qword ptr %s", modrm_string); break;
+ case 6: sprintf(s, "fdiv qword ptr %s", modrm_string); break;
+ case 7: sprintf(s, "fdivr qword ptr %s", modrm_string); break;
+ }
+ }
+ else
+ {
+ switch (op2 & 0x3f)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+ sprintf(s, "fadd st(%d),st(0)", op2 & 0x7); break;
+
+ case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ sprintf(s, "fmul st(%d),st(0)", op2 & 0x7); break;
+
+ case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
+ sprintf(s, "fsubr st(%d),st(0)", op2 & 0x7); break;
+
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ sprintf(s, "fsub st(%d),st(0)", op2 & 0x7); break;
+
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
+ sprintf(s, "fdivr st(%d),st(0)", op2 & 0x7); break;
+
+ case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
+ sprintf(s, "fdiv st(%d),st(0)", op2 & 0x7); break;
+
+ default: sprintf(s, "??? (FPU)"); break;
+ }
+ }
+ break;
+ }
+
+ case 5: // Group DD
+ {
+ if (op2 < 0xc0)
+ {
+ pc--; // adjust fetch pointer, so modrm byte read again
+ opcode_ptr--;
+ handle_modrm( modrm_string );
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: sprintf(s, "fld qword ptr %s", modrm_string); break;
+ case 1: sprintf(s, "fisttp qword ptr %s", modrm_string); break;
+ case 2: sprintf(s, "fst qword ptr %s", modrm_string); break;
+ case 3: sprintf(s, "fstp qword ptr %s", modrm_string); break;
+ case 4: sprintf(s, "frstor %s", modrm_string); break;
+ case 5: sprintf(s, "??? (FPU)"); break;
+ case 6: sprintf(s, "fsave %s", modrm_string); break;
+ case 7: sprintf(s, "fstsw word ptr %s", modrm_string); break;
+ }
+ }
+ else
+ {
+ switch (op2 & 0x3f)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+ sprintf(s, "ffree st(%d)", op2 & 0x7); break;
+
+ case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
+ sprintf(s, "fst st(%d)", op2 & 0x7); break;
+
+ case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ sprintf(s, "fstp st(%d)", op2 & 0x7); break;
+
+ case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
+ sprintf(s, "fucom st(%d), st(0)", op2 & 0x7); break;
+
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ sprintf(s, "fucomp st(%d)", op2 & 0x7); break;
+
+ default: sprintf(s, "??? (FPU)"); break;
+ }
+ }
+ break;
+ }
+
+ case 6: // Group DE
+ {
+ if (op2 < 0xc0)
+ {
+ pc--; // adjust fetch pointer, so modrm byte read again
+ opcode_ptr--;
+ handle_modrm( modrm_string );
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: sprintf(s, "fiadd word ptr %s", modrm_string); break;
+ case 1: sprintf(s, "fimul word ptr %s", modrm_string); break;
+ case 2: sprintf(s, "ficom word ptr %s", modrm_string); break;
+ case 3: sprintf(s, "ficomp word ptr %s", modrm_string); break;
+ case 4: sprintf(s, "fisub word ptr %s", modrm_string); break;
+ case 5: sprintf(s, "fisubr word ptr %s", modrm_string); break;
+ case 6: sprintf(s, "fidiv word ptr %s", modrm_string); break;
+ case 7: sprintf(s, "fidivr word ptr %s", modrm_string); break;
+ }
+ }
+ else
+ {
+ switch (op2 & 0x3f)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+ sprintf(s, "faddp st(%d)", op2 & 0x7); break;
+
+ case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ sprintf(s, "fmulp st(%d)", op2 & 0x7); break;
+
+ case 0x19: sprintf(s, "fcompp"); break;
+
+ case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
+ sprintf(s, "fsubrp st(%d)", op2 & 0x7); break;
+
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ sprintf(s, "fsubp st(%d)", op2 & 0x7); break;
+
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
+ sprintf(s, "fdivrp st(%d), st(0)", op2 & 0x7); break;
+
+ case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
+ sprintf(s, "fdivp st(%d)", op2 & 0x7); break;
+
+ default: sprintf(s, "??? (FPU)"); break;
+ }
+ }
+ break;
+ }
+
+ case 7: // Group DF
+ {
+ if (op2 < 0xc0)
+ {
+ pc--; // adjust fetch pointer, so modrm byte read again
+ opcode_ptr--;
+ handle_modrm( modrm_string );
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: sprintf(s, "fild word ptr %s", modrm_string); break;
+ case 1: sprintf(s, "fisttp word ptr %s", modrm_string); break;
+ case 2: sprintf(s, "fist word ptr %s", modrm_string); break;
+ case 3: sprintf(s, "fistp word ptr %s", modrm_string); break;
+ case 4: sprintf(s, "fbld %s", modrm_string); break;
+ case 5: sprintf(s, "fild qword ptr %s", modrm_string); break;
+ case 6: sprintf(s, "fbstp %s", modrm_string); break;
+ case 7: sprintf(s, "fistp qword ptr %s", modrm_string); break;
+ }
+ }
+ else
+ {
+ switch (op2 & 0x3f)
+ {
+ case 0x20: sprintf(s, "fstsw ax"); break;
+
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ sprintf(s, "fucomip st(%d)", op2 & 0x7); break;
+
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
+ sprintf(s, "fcomip st(%d),st(0)", op2 & 0x7); break;
+
+ default: sprintf(s, "??? (FPU)"); break;
+ }
+ }
+ break;
+ }
+ }
+}
+
+static void decode_opcode(char *s, const I386_OPCODE *op, UINT8 op1)
+{
+ int i;
+ UINT8 op2;
+
+ if (op->flags & SPECIAL64)
+ op = &x64_opcode_alt[op->flags >> 24];
+
+ switch( op->flags & FLAGS_MASK )
+ {
+ case ISREX:
+ if (curmode == 64)
+ {
+ rex = op1;
+ operand_size = (op1 & 8) ? 2 : 1;
+ regex = (op1 << 1) & 8;
+ sibex = (op1 << 2) & 8;
+ rmex = (op1 << 3) & 8;
+ op2 = FETCH();
+ decode_opcode( s, &i386_opcode_table1[op2], op1 );
+ return;
+ }
+ break;
+
+ case OP_SIZE:
+ rex = regex = sibex = rmex = 0;
+ if (operand_size < 2)
+ operand_size ^= 1;
+ op2 = FETCH();
+ decode_opcode( s, &i386_opcode_table1[op2], op2 );
+ return;
+
+ case ADDR_SIZE:
+ rex = regex = sibex = rmex = 0;
+ if (curmode != 64)
+ address_size ^= 1;
+ else
+ address_size ^= 3;
+ op2 = FETCH();
+ decode_opcode( s, &i386_opcode_table1[op2], op2 );
+ return;
+
+ case TWO_BYTE:
+ if (&opcode_ptr[-2] >= opcode_ptr_base)
+ pre0f = opcode_ptr[-2];
+ op2 = FETCHD();
+ decode_opcode( s, &i386_opcode_table2[op2], op1 );
+ return;
+
+ case SEG_CS:
+ case SEG_DS:
+ case SEG_ES:
+ case SEG_FS:
+ case SEG_GS:
+ case SEG_SS:
+ rex = regex = sibex = rmex = 0;
+ segment = op->flags;
+ op2 = FETCH();
+ decode_opcode( s, &i386_opcode_table1[op2], op2 );
+ return;
+
+ case PREFIX:
+ op2 = FETCH();
+ if (op2 != 0x0f)
+ s += sprintf( s, "%-7s ", op->mnemonic );
+ decode_opcode( s, &i386_opcode_table1[op2], op2 );
+ return;
+
+ case GROUP:
+ handle_modrm( modrm_string );
+ for( i=0; i < ARRAY_LENGTH(group_op_table); i++ ) {
+ if( strcmp(op->mnemonic, group_op_table[i].mnemonic) == 0 ) {
+ decode_opcode( s, &group_op_table[i].opcode[MODRM_REG1], op1 );
+ return;
+ }
+ }
+ goto handle_unknown;
+
+ case FPU:
+ op2 = FETCHD();
+ handle_fpu( s, op1, op2);
+ return;
+
+ case MODRM:
+ handle_modrm( modrm_string );
+ break;
+ }
+
+ if ((op->flags & ALWAYS64) && curmode == 64)
+ operand_size = 2;
+
+ if ((op->flags & VAR_NAME) && operand_size > 0)
+ {
+ const char *mnemonic = op->mnemonic + strlen(op->mnemonic) + 1;
+ if (operand_size == 2)
+ mnemonic += strlen(mnemonic) + 1;
+ s += sprintf( s, "%-7s ", mnemonic );
+ }
+ else if (op->flags & VAR_NAME4)
+ {
+ const char *mnemonic = op->mnemonic;
+ int which = (pre0f == 0xf3) ? 3 : (pre0f == 0xf2) ? 2 : (pre0f == 0x66) ? 1 : 0;
+ while (which--)
+ mnemonic += strlen(mnemonic) + 1;
+ s += sprintf( s, "%-7s ", mnemonic );
+ }
+ else
+ s += sprintf( s, "%-7s ", op->mnemonic );
+ dasm_flags = op->dasm_flags;
+
+ if( op->param1 != 0 ) {
+ s = handle_param( s, op->param1 );
+ }
+
+ if( op->param2 != 0 ) {
+ s += sprintf( s, "," );
+ s = handle_param( s, op->param2 );
+ }
+
+ if( op->param3 != 0 ) {
+ s += sprintf( s, "," );
+ s = handle_param( s, op->param3 );
+ }
+ return;
+
+handle_unknown:
+ sprintf(s, "???");
+}
+
+int i386_dasm_one_ex(char *buffer, UINT64 eip, const UINT8 *oprom, int mode)
+{
+ UINT8 op;
+
+ opcode_ptr = opcode_ptr_base = oprom;
+ switch(mode)
+ {
+ case 1: /* 8086/8088/80186/80188 */
+ address_size = 0;
+ operand_size = 0;
+ max_length = 8; /* maximum without redundant prefixes - not enforced by chip */
+ break;
+ case 2: /* 80286 */
+ address_size = 0;
+ operand_size = 0;
+ max_length = 10;
+ break;
+ case 16: /* 80386+ 16-bit code segment */
+ address_size = 0;
+ operand_size = 0;
+ max_length = 15;
+ break;
+ case 32: /* 80386+ 32-bit code segment */
+ address_size = 1;
+ operand_size = 1;
+ max_length = 15;
+ break;
+ case 64: /* x86_64 */
+ address_size = 2;
+ operand_size = 1;
+ max_length = 15;
+ break;
+ }
+ pc = eip;
+ dasm_flags = 0;
+ segment = 0;
+ curmode = mode;
+ pre0f = 0;
+ rex = regex = sibex = rmex = 0;
+
+ op = FETCH();
+
+ decode_opcode( buffer, &i386_opcode_table1[op], op );
+ return (pc-eip) | dasm_flags | DASMFLAG_SUPPORTED;
+}
+
+int i386_dasm_one(char *buffer, offs_t eip, const UINT8 *oprom, int mode)
+{
+ return i386_dasm_one_ex(buffer, eip, oprom, mode);
+}
+
+CPU_DISASSEMBLE( x86_16 )
+{
+ return i386_dasm_one_ex(buffer, pc, oprom, 16);
+}
+
+CPU_DISASSEMBLE( x86_32 )
+{
+ return i386_dasm_one_ex(buffer, pc, oprom, 32);
+}
+
+CPU_DISASSEMBLE( x86_64 )
+{
+ return i386_dasm_one_ex(buffer, pc, oprom, 64);
+}
diff --git a/trunk/src/emu/cpu/i386/i386op16.c b/trunk/src/emu/cpu/i386/i386op16.c
new file mode 100644
index 00000000000..8b265e09761
--- /dev/null
+++ b/trunk/src/emu/cpu/i386/i386op16.c
@@ -0,0 +1,3484 @@
+static UINT16 I386OP(shift_rotate16)(i386_state *cpustate, UINT8 modrm, UINT32 value, UINT8 shift)
+{
+ UINT16 src = value;
+ UINT16 dst = value;
+
+ if( shift == 0 ) {
+ CYCLES_RM(cpustate,modrm, 3, 7);
+ } else if( shift == 1 ) {
+
+ switch( (modrm >> 3) & 0x7 )
+ {
+ case 0: /* ROL rm16, 1 */
+ cpustate->CF = (src & 0x8000) ? 1 : 0;
+ dst = (src << 1) + cpustate->CF;
+ cpustate->OF = ((src ^ dst) & 0x8000) ? 1 : 0;
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
+ break;
+ case 1: /* ROR rm16, 1 */
+ cpustate->CF = (src & 0x1) ? 1 : 0;
+ dst = (cpustate->CF << 15) | (src >> 1);
+ cpustate->OF = ((src ^ dst) & 0x8000) ? 1 : 0;
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
+ break;
+ case 2: /* RCL rm16, 1 */
+ dst = (src << 1) + cpustate->CF;
+ cpustate->CF = (src & 0x8000) ? 1 : 0;
+ cpustate->OF = ((src ^ dst) & 0x8000) ? 1 : 0;
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
+ break;
+ case 3: /* RCR rm16, 1 */
+ dst = (cpustate->CF << 15) | (src >> 1);
+ cpustate->CF = src & 0x1;
+ cpustate->OF = ((src ^ dst) & 0x8000) ? 1 : 0;
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
+ break;
+ case 4: /* SHL/SAL rm16, 1 */
+ case 6:
+ dst = src << 1;
+ cpustate->CF = (src & 0x8000) ? 1 : 0;
+ cpustate->OF = (((cpustate->CF << 15) ^ dst) & 0x8000) ? 1 : 0;
+ SetSZPF16(dst);
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
+ break;
+ case 5: /* SHR rm16, 1 */
+ dst = src >> 1;
+ cpustate->CF = src & 0x1;
+ cpustate->OF = (dst & 0x8000) ? 1 : 0;
+ SetSZPF16(dst);
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
+ break;
+ case 7: /* SAR rm16, 1 */
+ dst = (INT16)(src) >> 1;
+ cpustate->CF = src & 0x1;
+ cpustate->OF = 0;
+ SetSZPF16(dst);
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
+ break;
+ }
+ } else {
+
+ switch( (modrm >> 3) & 0x7 )
+ {
+ case 0: /* ROL rm16, i8 */
+ dst = ((src & ((UINT16)0xffff >> shift)) << shift) |
+ ((src & ((UINT16)0xffff << (16-shift))) >> (16-shift));
+ cpustate->CF = (src >> (16-shift)) & 0x1;
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
+ break;
+ case 1: /* ROR rm16, i8 */
+ dst = ((src & ((UINT16)0xffff << shift)) >> shift) |
+ ((src & ((UINT16)0xffff >> (16-shift))) << (16-shift));
+ cpustate->CF = (src >> (shift-1)) & 0x1;
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
+ break;
+ case 2: /* RCL rm16, i8 */
+ dst = ((src & ((UINT16)0xffff >> shift)) << shift) |
+ ((src & ((UINT16)0xffff << (17-shift))) >> (17-shift)) |
+ (cpustate->CF << (shift-1));
+ cpustate->CF = (src >> (16-shift)) & 0x1;
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
+ break;
+ case 3: /* RCR rm16, i8 */
+ dst = ((src & ((UINT16)0xffff << shift)) >> shift) |
+ ((src & ((UINT16)0xffff >> (16-shift))) << (17-shift)) |
+ (cpustate->CF << (16-shift));
+ cpustate->CF = (src >> (shift-1)) & 0x1;
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
+ break;
+ case 4: /* SHL/SAL rm16, i8 */
+ case 6:
+ dst = src << shift;
+ cpustate->CF = (src & (1 << (16-shift))) ? 1 : 0;
+ SetSZPF16(dst);
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
+ break;
+ case 5: /* SHR rm16, i8 */
+ dst = src >> shift;
+ cpustate->CF = (src & (1 << (shift-1))) ? 1 : 0;
+ SetSZPF16(dst);
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
+ break;
+ case 7: /* SAR rm16, i8 */
+ dst = (INT16)src >> shift;
+ cpustate->CF = (src & (1 << (shift-1))) ? 1 : 0;
+ SetSZPF16(dst);
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
+ break;
+ }
+
+ }
+ return dst;
+}
+
+
+
+static void I386OP(adc_rm16_r16)(i386_state *cpustate) // Opcode 0x11
+{
+ UINT16 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_REG16(modrm);
+ dst = LOAD_RM16(modrm);
+ dst = ADC16(cpustate, dst, src, cpustate->CF);
+ STORE_RM16(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = LOAD_REG16(modrm);
+ dst = READ16(cpustate,ea);
+ dst = ADC16(cpustate, dst, src, cpustate->CF);
+ WRITE16(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+}
+
+static void I386OP(adc_r16_rm16)(i386_state *cpustate) // Opcode 0x13
+{
+ UINT16 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_RM16(modrm);
+ dst = LOAD_REG16(modrm);
+ dst = ADC16(cpustate, dst, src, cpustate->CF);
+ STORE_REG16(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = READ16(cpustate,ea);
+ dst = LOAD_REG16(modrm);
+ dst = ADC16(cpustate, dst, src, cpustate->CF);
+ STORE_REG16(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_MEM_REG);
+ }
+}
+
+static void I386OP(adc_ax_i16)(i386_state *cpustate) // Opcode 0x15
+{
+ UINT16 src, dst;
+ src = FETCH16(cpustate);
+ dst = REG16(AX);
+ dst = ADC16(cpustate, dst, src, cpustate->CF);
+ REG16(AX) = dst;
+ CYCLES(cpustate,CYCLES_ALU_IMM_ACC);
+}
+
+static void I386OP(add_rm16_r16)(i386_state *cpustate) // Opcode 0x01
+{
+ UINT16 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_REG16(modrm);
+ dst = LOAD_RM16(modrm);
+ dst = ADD16(cpustate,dst, src);
+ STORE_RM16(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = LOAD_REG16(modrm);
+ dst = READ16(cpustate,ea);
+ dst = ADD16(cpustate,dst, src);
+ WRITE16(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+}
+
+static void I386OP(add_r16_rm16)(i386_state *cpustate) // Opcode 0x03
+{
+ UINT16 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_RM16(modrm);
+ dst = LOAD_REG16(modrm);
+ dst = ADD16(cpustate,dst, src);
+ STORE_REG16(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = READ16(cpustate,ea);
+ dst = LOAD_REG16(modrm);
+ dst = ADD16(cpustate,dst, src);
+ STORE_REG16(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_MEM_REG);
+ }
+}
+
+static void I386OP(add_ax_i16)(i386_state *cpustate) // Opcode 0x05
+{
+ UINT16 src, dst;
+ src = FETCH16(cpustate);
+ dst = REG16(AX);
+ dst = ADD16(cpustate,dst, src);
+ REG16(AX) = dst;
+ CYCLES(cpustate,CYCLES_ALU_IMM_ACC);
+}
+
+static void I386OP(and_rm16_r16)(i386_state *cpustate) // Opcode 0x21
+{
+ UINT16 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_REG16(modrm);
+ dst = LOAD_RM16(modrm);
+ dst = AND16(cpustate,dst, src);
+ STORE_RM16(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = LOAD_REG16(modrm);
+ dst = READ16(cpustate,ea);
+ dst = AND16(cpustate,dst, src);
+ WRITE16(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+}
+
+static void I386OP(and_r16_rm16)(i386_state *cpustate) // Opcode 0x23
+{
+ UINT16 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_RM16(modrm);
+ dst = LOAD_REG16(modrm);
+ dst = AND16(cpustate,dst, src);
+ STORE_REG16(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = READ16(cpustate,ea);
+ dst = LOAD_REG16(modrm);
+ dst = AND16(cpustate,dst, src);
+ STORE_REG16(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_MEM_REG);
+ }
+}
+
+static void I386OP(and_ax_i16)(i386_state *cpustate) // Opcode 0x25
+{
+ UINT16 src, dst;
+ src = FETCH16(cpustate);
+ dst = REG16(AX);
+ dst = AND16(cpustate,dst, src);
+ REG16(AX) = dst;
+ CYCLES(cpustate,CYCLES_ALU_IMM_ACC);
+}
+
+static void I386OP(bsf_r16_rm16)(i386_state *cpustate) // Opcode 0x0f bc
+{
+ UINT16 src, dst, temp;
+ UINT8 modrm = FETCH(cpustate);
+
+ if( modrm >= 0xc0 ) {
+ src = LOAD_RM16(modrm);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = READ16(cpustate,ea);
+ }
+
+ dst = 0;
+
+ if( src == 0 ) {
+ cpustate->ZF = 1;
+ } else {
+ cpustate->ZF = 0;
+ temp = 0;
+ while( (src & (1 << temp)) == 0 ) {
+ temp++;
+ dst = temp;
+ CYCLES(cpustate,CYCLES_BSF);
+ }
+ }
+ CYCLES(cpustate,CYCLES_BSF_BASE);
+ STORE_REG16(modrm, dst);
+}
+
+static void I386OP(bsr_r16_rm16)(i386_state *cpustate) // Opcode 0x0f bd
+{
+ UINT16 src, dst, temp;
+ UINT8 modrm = FETCH(cpustate);
+
+ if( modrm >= 0xc0 ) {
+ src = LOAD_RM16(modrm);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = READ16(cpustate,ea);
+ }
+
+ dst = 0;
+
+ if( src == 0 ) {
+ cpustate->ZF = 1;
+ } else {
+ cpustate->ZF = 0;
+ dst = temp = 15;
+ while( (src & (1 << temp)) == 0 ) {
+ temp--;
+ dst = temp;
+ CYCLES(cpustate,CYCLES_BSR);
+ }
+ }
+ CYCLES(cpustate,CYCLES_BSR_BASE);
+ STORE_REG16(modrm, dst);
+}
+
+
+static void I386OP(bt_rm16_r16)(i386_state *cpustate) // Opcode 0x0f a3
+{
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ UINT16 dst = LOAD_RM16(modrm);
+ UINT16 bit = LOAD_REG16(modrm);
+
+ if( dst & (1 << bit) )
+ cpustate->CF = 1;
+ else
+ cpustate->CF = 0;
+
+ CYCLES(cpustate,CYCLES_BT_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT16 dst = READ16(cpustate,ea);
+ UINT16 bit = LOAD_REG16(modrm);
+
+ if( dst & (1 << bit) )
+ cpustate->CF = 1;
+ else
+ cpustate->CF = 0;
+
+ CYCLES(cpustate,CYCLES_BT_REG_MEM);
+ }
+}
+
+static void I386OP(btc_rm16_r16)(i386_state *cpustate) // Opcode 0x0f bb
+{
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ UINT16 dst = LOAD_RM16(modrm);
+ UINT16 bit = LOAD_REG16(modrm);
+
+ if( dst & (1 << bit) )
+ cpustate->CF = 1;
+ else
+ cpustate->CF = 0;
+ dst ^= (1 << bit);
+
+ STORE_RM16(modrm, dst);
+ CYCLES(cpustate,CYCLES_BTC_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT16 dst = READ16(cpustate,ea);
+ UINT16 bit = LOAD_REG16(modrm);
+
+ if( dst & (1 << bit) )
+ cpustate->CF = 1;
+ else
+ cpustate->CF = 0;
+ dst ^= (1 << bit);
+
+ WRITE16(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_BTC_REG_MEM);
+ }
+}
+
+static void I386OP(btr_rm16_r16)(i386_state *cpustate) // Opcode 0x0f b3
+{
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ UINT16 dst = LOAD_RM16(modrm);
+ UINT16 bit = LOAD_REG16(modrm);
+
+ if( dst & (1 << bit) )
+ cpustate->CF = 1;
+ else
+ cpustate->CF = 0;
+ dst &= ~(1 << bit);
+
+ STORE_RM16(modrm, dst);
+ CYCLES(cpustate,CYCLES_BTR_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT16 dst = READ16(cpustate,ea);
+ UINT16 bit = LOAD_REG16(modrm);
+
+ if( dst & (1 << bit) )
+ cpustate->CF = 1;
+ else
+ cpustate->CF = 0;
+ dst &= ~(1 << bit);
+
+ WRITE16(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_BTR_REG_MEM);
+ }
+}
+
+static void I386OP(bts_rm16_r16)(i386_state *cpustate) // Opcode 0x0f ab
+{
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ UINT16 dst = LOAD_RM16(modrm);
+ UINT16 bit = LOAD_REG16(modrm);
+
+ if( dst & (1 << bit) )
+ cpustate->CF = 1;
+ else
+ cpustate->CF = 0;
+ dst |= (1 << bit);
+
+ STORE_RM16(modrm, dst);
+ CYCLES(cpustate,CYCLES_BTS_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT16 dst = READ16(cpustate,ea);
+ UINT16 bit = LOAD_REG16(modrm);
+
+ if( dst & (1 << bit) )
+ cpustate->CF = 1;
+ else
+ cpustate->CF = 0;
+ dst |= (1 << bit);
+
+ WRITE16(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_BTS_REG_MEM);
+ }
+}
+
+static void I386OP(call_abs16)(i386_state *cpustate) // Opcode 0x9a
+{
+ UINT16 offset = FETCH16(cpustate);
+ UINT16 ptr = FETCH16(cpustate);
+
+ if( PROTECTED_MODE && !V8086_MODE)
+ {
+ i386_protected_mode_call(cpustate,ptr,offset,0,0);
+ }
+ else
+ {
+ PUSH16(cpustate, cpustate->sreg[CS].selector );
+ PUSH16(cpustate, cpustate->eip );
+ cpustate->sreg[CS].selector = ptr;
+ cpustate->performed_intersegment_jump = 1;
+ cpustate->eip = offset;
+ i386_load_segment_descriptor(cpustate,CS);
+ }
+ CYCLES(cpustate,CYCLES_CALL_INTERSEG); /* TODO: Timing = 17 + m */
+ CHANGE_PC(cpustate,cpustate->eip);
+}
+
+static void I386OP(call_rel16)(i386_state *cpustate) // Opcode 0xe8
+{
+ INT16 disp = FETCH16(cpustate);
+
+ PUSH16(cpustate, cpustate->eip );
+ if (cpustate->sreg[CS].d)
+ {
+ cpustate->eip += disp;
+ }
+ else
+ {
+ cpustate->eip = (cpustate->eip + disp) & 0xffff;
+ }
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_CALL); /* TODO: Timing = 7 + m */
+}
+
+static void I386OP(cbw)(i386_state *cpustate) // Opcode 0x98
+{
+ REG16(AX) = (INT16)((INT8)REG8(AL));
+ CYCLES(cpustate,CYCLES_CBW);
+}
+
+static void I386OP(cmp_rm16_r16)(i386_state *cpustate) // Opcode 0x39
+{
+ UINT16 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_REG16(modrm);
+ dst = LOAD_RM16(modrm);
+ SUB16(cpustate,dst, src);
+ CYCLES(cpustate,CYCLES_CMP_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = LOAD_REG16(modrm);
+ dst = READ16(cpustate,ea);
+ SUB16(cpustate,dst, src);
+ CYCLES(cpustate,CYCLES_CMP_REG_MEM);
+ }
+}
+
+static void I386OP(cmp_r16_rm16)(i386_state *cpustate) // Opcode 0x3b
+{
+ UINT16 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_RM16(modrm);
+ dst = LOAD_REG16(modrm);
+ SUB16(cpustate,dst, src);
+ CYCLES(cpustate,CYCLES_CMP_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = READ16(cpustate,ea);
+ dst = LOAD_REG16(modrm);
+ SUB16(cpustate,dst, src);
+ CYCLES(cpustate,CYCLES_CMP_MEM_REG);
+ }
+}
+
+static void I386OP(cmp_ax_i16)(i386_state *cpustate) // Opcode 0x3d
+{
+ UINT16 src, dst;
+ src = FETCH16(cpustate);
+ dst = REG16(AX);
+ SUB16(cpustate,dst, src);
+ CYCLES(cpustate,CYCLES_CMP_IMM_ACC);
+}
+
+static void I386OP(cmpsw)(i386_state *cpustate) // Opcode 0xa7
+{
+ UINT32 eas, ead;
+ UINT16 src, dst;
+ if( cpustate->segment_prefix ) {
+ eas = i386_translate(cpustate, cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI) );
+ } else {
+ eas = i386_translate(cpustate, DS, cpustate->address_size ? REG32(ESI) : REG16(SI) );
+ }
+ ead = i386_translate(cpustate, ES, cpustate->address_size ? REG32(EDI) : REG16(DI) );
+ src = READ16(cpustate,eas);
+ dst = READ16(cpustate,ead);
+ SUB16(cpustate,dst, src);
+ BUMP_SI(cpustate,2);
+ BUMP_DI(cpustate,2);
+ CYCLES(cpustate,CYCLES_CMPS);
+}
+
+static void I386OP(cwd)(i386_state *cpustate) // Opcode 0x99
+{
+ if( REG16(AX) & 0x8000 ) {
+ REG16(DX) = 0xffff;
+ } else {
+ REG16(DX) = 0x0000;
+ }
+ CYCLES(cpustate,CYCLES_CWD);
+}
+
+static void I386OP(dec_ax)(i386_state *cpustate) // Opcode 0x48
+{
+ REG16(AX) = DEC16(cpustate, REG16(AX) );
+ CYCLES(cpustate,CYCLES_DEC_REG);
+}
+
+static void I386OP(dec_cx)(i386_state *cpustate) // Opcode 0x49
+{
+ REG16(CX) = DEC16(cpustate, REG16(CX) );
+ CYCLES(cpustate,CYCLES_DEC_REG);
+}
+
+static void I386OP(dec_dx)(i386_state *cpustate) // Opcode 0x4a
+{
+ REG16(DX) = DEC16(cpustate, REG16(DX) );
+ CYCLES(cpustate,CYCLES_DEC_REG);
+}
+
+static void I386OP(dec_bx)(i386_state *cpustate) // Opcode 0x4b
+{
+ REG16(BX) = DEC16(cpustate, REG16(BX) );
+ CYCLES(cpustate,CYCLES_DEC_REG);
+}
+
+static void I386OP(dec_sp)(i386_state *cpustate) // Opcode 0x4c
+{
+ REG16(SP) = DEC16(cpustate, REG16(SP) );
+ CYCLES(cpustate,CYCLES_DEC_REG);
+}
+
+static void I386OP(dec_bp)(i386_state *cpustate) // Opcode 0x4d
+{
+ REG16(BP) = DEC16(cpustate, REG16(BP) );
+ CYCLES(cpustate,CYCLES_DEC_REG);
+}
+
+static void I386OP(dec_si)(i386_state *cpustate) // Opcode 0x4e
+{
+ REG16(SI) = DEC16(cpustate, REG16(SI) );
+ CYCLES(cpustate,CYCLES_DEC_REG);
+}
+
+static void I386OP(dec_di)(i386_state *cpustate) // Opcode 0x4f
+{
+ REG16(DI) = DEC16(cpustate, REG16(DI) );
+ CYCLES(cpustate,CYCLES_DEC_REG);
+}
+
+static void I386OP(imul_r16_rm16)(i386_state *cpustate) // Opcode 0x0f af
+{
+ UINT8 modrm = FETCH(cpustate);
+ INT32 result;
+ INT32 src, dst;
+ if( modrm >= 0xc0 ) {
+ src = (INT32)(INT16)LOAD_RM16(modrm);
+ CYCLES(cpustate,CYCLES_IMUL16_REG_REG); /* TODO: Correct multiply timing */
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = (INT32)(INT16)READ16(cpustate,ea);
+ CYCLES(cpustate,CYCLES_IMUL16_REG_MEM); /* TODO: Correct multiply timing */
+ }
+
+ dst = (INT32)(INT16)LOAD_REG16(modrm);
+ result = src * dst;
+
+ STORE_REG16(modrm, (UINT16)result);
+
+ cpustate->CF = cpustate->OF = !(result == (INT32)(INT16)result);
+}
+
+static void I386OP(imul_r16_rm16_i16)(i386_state *cpustate) // Opcode 0x69
+{
+ UINT8 modrm = FETCH(cpustate);
+ INT32 result;
+ INT32 src, dst;
+ if( modrm >= 0xc0 ) {
+ dst = (INT32)(INT16)LOAD_RM16(modrm);
+ CYCLES(cpustate,CYCLES_IMUL16_REG_IMM_REG); /* TODO: Correct multiply timing */
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ dst = (INT32)(INT16)READ16(cpustate,ea);
+ CYCLES(cpustate,CYCLES_IMUL16_MEM_IMM_REG); /* TODO: Correct multiply timing */
+ }
+
+ src = (INT32)(INT16)FETCH16(cpustate);
+ result = src * dst;
+
+ STORE_REG16(modrm, (UINT16)result);
+
+ cpustate->CF = cpustate->OF = !(result == (INT32)(INT16)result);
+}
+
+static void I386OP(imul_r16_rm16_i8)(i386_state *cpustate) // Opcode 0x6b
+{
+ UINT8 modrm = FETCH(cpustate);
+ INT32 result;
+ INT32 src, dst;
+ if( modrm >= 0xc0 ) {
+ dst = (INT32)(INT16)LOAD_RM16(modrm);
+ CYCLES(cpustate,CYCLES_IMUL16_REG_IMM_REG); /* TODO: Correct multiply timing */
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ dst = (INT32)(INT16)READ16(cpustate,ea);
+ CYCLES(cpustate,CYCLES_IMUL16_MEM_IMM_REG); /* TODO: Correct multiply timing */
+ }
+
+ src = (INT32)(INT8)FETCH(cpustate);
+ result = src * dst;
+
+ STORE_REG16(modrm, (UINT16)result);
+
+ cpustate->CF = cpustate->OF = !(result == (INT32)(INT16)result);
+}
+
+static void I386OP(in_ax_i8)(i386_state *cpustate) // Opcode 0xe5
+{
+ UINT16 port = FETCH(cpustate);
+ UINT16 data = READPORT16(cpustate, port);
+ REG16(AX) = data;
+ CYCLES(cpustate,CYCLES_IN_VAR);
+}
+
+static void I386OP(in_ax_dx)(i386_state *cpustate) // Opcode 0xed
+{
+ UINT16 port = REG16(DX);
+ UINT16 data = READPORT16(cpustate, port);
+ REG16(AX) = data;
+ CYCLES(cpustate,CYCLES_IN);
+}
+
+static void I386OP(inc_ax)(i386_state *cpustate) // Opcode 0x40
+{
+ REG16(AX) = INC16(cpustate, REG16(AX) );
+ CYCLES(cpustate,CYCLES_INC_REG);
+}
+
+static void I386OP(inc_cx)(i386_state *cpustate) // Opcode 0x41
+{
+ REG16(CX) = INC16(cpustate, REG16(CX) );
+ CYCLES(cpustate,CYCLES_INC_REG);
+}
+
+static void I386OP(inc_dx)(i386_state *cpustate) // Opcode 0x42
+{
+ REG16(DX) = INC16(cpustate, REG16(DX) );
+ CYCLES(cpustate,CYCLES_INC_REG);
+}
+
+static void I386OP(inc_bx)(i386_state *cpustate) // Opcode 0x43
+{
+ REG16(BX) = INC16(cpustate, REG16(BX) );
+ CYCLES(cpustate,CYCLES_INC_REG);
+}
+
+static void I386OP(inc_sp)(i386_state *cpustate) // Opcode 0x44
+{
+ REG16(SP) = INC16(cpustate, REG16(SP) );
+ CYCLES(cpustate,CYCLES_INC_REG);
+}
+
+static void I386OP(inc_bp)(i386_state *cpustate) // Opcode 0x45
+{
+ REG16(BP) = INC16(cpustate, REG16(BP) );
+ CYCLES(cpustate,CYCLES_INC_REG);
+}
+
+static void I386OP(inc_si)(i386_state *cpustate) // Opcode 0x46
+{
+ REG16(SI) = INC16(cpustate, REG16(SI) );
+ CYCLES(cpustate,CYCLES_INC_REG);
+}
+
+static void I386OP(inc_di)(i386_state *cpustate) // Opcode 0x47
+{
+ REG16(DI) = INC16(cpustate, REG16(DI) );
+ CYCLES(cpustate,CYCLES_INC_REG);
+}
+
+static void I386OP(iret16)(i386_state *cpustate) // Opcode 0xcf
+{
+ if( PROTECTED_MODE )
+ {
+ i386_protected_mode_iret(cpustate,0);
+ }
+ else
+ {
+ /* TODO: #SS(0) exception */
+ /* TODO: #GP(0) exception */
+ cpustate->eip = POP16(cpustate);
+ cpustate->sreg[CS].selector = POP16(cpustate);
+ set_flags(cpustate, POP16(cpustate) );
+ i386_load_segment_descriptor(cpustate,CS);
+ CHANGE_PC(cpustate,cpustate->eip);
+ }
+ CYCLES(cpustate,CYCLES_IRET);
+}
+
+static void I386OP(ja_rel16)(i386_state *cpustate) // Opcode 0x0f 87
+{
+ INT16 disp = FETCH16(cpustate);
+ if( cpustate->CF == 0 && cpustate->ZF == 0 ) {
+ if (cpustate->sreg[CS].d)
+ {
+ cpustate->eip += disp;
+ }
+ else
+ {
+ cpustate->eip = (cpustate->eip + disp) & 0xffff;
+ }
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH);
+ }
+}
+
+static void I386OP(jbe_rel16)(i386_state *cpustate) // Opcode 0x0f 86
+{
+ INT16 disp = FETCH16(cpustate);
+ if( cpustate->CF != 0 || cpustate->ZF != 0 ) {
+ if (cpustate->sreg[CS].d)
+ {
+ cpustate->eip += disp;
+ }
+ else
+ {
+ cpustate->eip = (cpustate->eip + disp) & 0xffff;
+ }
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH);
+ }
+}
+
+static void I386OP(jc_rel16)(i386_state *cpustate) // Opcode 0x0f 82
+{
+ INT16 disp = FETCH16(cpustate);
+ if( cpustate->CF != 0 ) {
+ if (cpustate->sreg[CS].d)
+ {
+ cpustate->eip += disp;
+ }
+ else
+ {
+ cpustate->eip = (cpustate->eip + disp) & 0xffff;
+ }
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH);
+ }
+}
+
+static void I386OP(jg_rel16)(i386_state *cpustate) // Opcode 0x0f 8f
+{
+ INT16 disp = FETCH16(cpustate);
+ if( cpustate->ZF == 0 && (cpustate->SF == cpustate->OF) ) {
+ if (cpustate->sreg[CS].d)
+ {
+ cpustate->eip += disp;
+ }
+ else
+ {
+ cpustate->eip = (cpustate->eip + disp) & 0xffff;
+ }
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH);
+ }
+}
+
+static void I386OP(jge_rel16)(i386_state *cpustate) // Opcode 0x0f 8d
+{
+ INT16 disp = FETCH16(cpustate);
+ if( (cpustate->SF == cpustate->OF) ) {
+ if (cpustate->sreg[CS].d)
+ {
+ cpustate->eip += disp;
+ }
+ else
+ {
+ cpustate->eip = (cpustate->eip + disp) & 0xffff;
+ }
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH);
+ }
+}
+
+static void I386OP(jl_rel16)(i386_state *cpustate) // Opcode 0x0f 8c
+{
+ INT16 disp = FETCH16(cpustate);
+ if( (cpustate->SF != cpustate->OF) ) {
+ if (cpustate->sreg[CS].d)
+ {
+ cpustate->eip += disp;
+ }
+ else
+ {
+ cpustate->eip = (cpustate->eip + disp) & 0xffff;
+ }
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH);
+ }
+}
+
+static void I386OP(jle_rel16)(i386_state *cpustate) // Opcode 0x0f 8e
+{
+ INT16 disp = FETCH16(cpustate);
+ if( cpustate->ZF != 0 || (cpustate->SF != cpustate->OF) ) {
+ if (cpustate->sreg[CS].d)
+ {
+ cpustate->eip += disp;
+ }
+ else
+ {
+ cpustate->eip = (cpustate->eip + disp) & 0xffff;
+ }
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH);
+ }
+}
+
+static void I386OP(jnc_rel16)(i386_state *cpustate) // Opcode 0x0f 83
+{
+ INT16 disp = FETCH16(cpustate);
+ if( cpustate->CF == 0 ) {
+ if (cpustate->sreg[CS].d)
+ {
+ cpustate->eip += disp;
+ }
+ else
+ {
+ cpustate->eip = (cpustate->eip + disp) & 0xffff;
+ }
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH);
+ }
+}
+
+static void I386OP(jno_rel16)(i386_state *cpustate) // Opcode 0x0f 81
+{
+ INT16 disp = FETCH16(cpustate);
+ if( cpustate->OF == 0 ) {
+ if (cpustate->sreg[CS].d)
+ {
+ cpustate->eip += disp;
+ }
+ else
+ {
+ cpustate->eip = (cpustate->eip + disp) & 0xffff;
+ }
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH);
+ }
+}
+
+static void I386OP(jnp_rel16)(i386_state *cpustate) // Opcode 0x0f 8b
+{
+ INT16 disp = FETCH16(cpustate);
+ if( cpustate->PF == 0 ) {
+ if (cpustate->sreg[CS].d)
+ {
+ cpustate->eip += disp;
+ }
+ else
+ {
+ cpustate->eip = (cpustate->eip + disp) & 0xffff;
+ }
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH);
+ }
+}
+
+static void I386OP(jns_rel16)(i386_state *cpustate) // Opcode 0x0f 89
+{
+ INT16 disp = FETCH16(cpustate);
+ if( cpustate->SF == 0 ) {
+ if (cpustate->sreg[CS].d)
+ {
+ cpustate->eip += disp;
+ }
+ else
+ {
+ cpustate->eip = (cpustate->eip + disp) & 0xffff;
+ }
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH);
+ }
+}
+
+static void I386OP(jnz_rel16)(i386_state *cpustate) // Opcode 0x0f 85
+{
+ INT16 disp = FETCH16(cpustate);
+ if( cpustate->ZF == 0 ) {
+ if (cpustate->sreg[CS].d)
+ {
+ cpustate->eip += disp;
+ }
+ else
+ {
+ cpustate->eip = (cpustate->eip + disp) & 0xffff;
+ }
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH);
+ }
+}
+
+static void I386OP(jo_rel16)(i386_state *cpustate) // Opcode 0x0f 80
+{
+ INT16 disp = FETCH16(cpustate);
+ if( cpustate->OF != 0 ) {
+ if (cpustate->sreg[CS].d)
+ {
+ cpustate->eip += disp;
+ }
+ else
+ {
+ cpustate->eip = (cpustate->eip + disp) & 0xffff;
+ }
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH);
+ }
+}
+
+static void I386OP(jp_rel16)(i386_state *cpustate) // Opcode 0x0f 8a
+{
+ INT16 disp = FETCH16(cpustate);
+ if( cpustate->PF != 0 ) {
+ if (cpustate->sreg[CS].d)
+ {
+ cpustate->eip += disp;
+ }
+ else
+ {
+ cpustate->eip = (cpustate->eip + disp) & 0xffff;
+ }
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH);
+ }
+}
+
+static void I386OP(js_rel16)(i386_state *cpustate) // Opcode 0x0f 88
+{
+ INT16 disp = FETCH16(cpustate);
+ if( cpustate->SF != 0 ) {
+ if (cpustate->sreg[CS].d)
+ {
+ cpustate->eip += disp;
+ }
+ else
+ {
+ cpustate->eip = (cpustate->eip + disp) & 0xffff;
+ }
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH);
+ }
+}
+
+static void I386OP(jz_rel16)(i386_state *cpustate) // Opcode 0x0f 84
+{
+ INT16 disp = FETCH16(cpustate);
+ if( cpustate->ZF != 0 ) {
+ if (cpustate->sreg[CS].d)
+ {
+ cpustate->eip += disp;
+ }
+ else
+ {
+ cpustate->eip = (cpustate->eip + disp) & 0xffff;
+ }
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH);
+ }
+}
+
+static void I386OP(jcxz16)(i386_state *cpustate) // Opcode 0xe3
+{
+ INT8 disp = FETCH(cpustate);
+ if( REG16(CX) == 0 ) {
+ if (cpustate->sreg[CS].d)
+ {
+ cpustate->eip += disp;
+ }
+ else
+ {
+ cpustate->eip = (cpustate->eip + disp) & 0xffff;
+ }
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_JCXZ); /* TODO: Timing = 9 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCXZ_NOBRANCH);
+ }
+}
+
+static void I386OP(jmp_rel16)(i386_state *cpustate) // Opcode 0xe9
+{
+ INT16 disp = FETCH16(cpustate);
+
+ if (cpustate->sreg[CS].d)
+ {
+ cpustate->eip += disp;
+ }
+ else
+ {
+ cpustate->eip = (cpustate->eip + disp) & 0xffff;
+ }
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_JMP); /* TODO: Timing = 7 + m */
+}
+
+static void I386OP(jmp_abs16)(i386_state *cpustate) // Opcode 0xea
+{
+ UINT16 address = FETCH16(cpustate);
+ UINT16 segment = FETCH16(cpustate);
+
+ if( PROTECTED_MODE && !V8086_MODE)
+ {
+ i386_protected_mode_jump(cpustate,segment,address,0,0);
+ }
+ else
+ {
+ cpustate->eip = address;
+ cpustate->sreg[CS].selector = segment;
+ cpustate->performed_intersegment_jump = 1;
+ i386_load_segment_descriptor(cpustate,CS);
+ CHANGE_PC(cpustate,cpustate->eip);
+ }
+ CYCLES(cpustate,CYCLES_JMP_INTERSEG);
+}
+
+static void I386OP(lea16)(i386_state *cpustate) // Opcode 0x8d
+{
+ UINT8 modrm = FETCH(cpustate);
+ UINT32 ea = GetNonTranslatedEA(cpustate,modrm);
+ STORE_REG16(modrm, ea);
+ CYCLES(cpustate,CYCLES_LEA);
+}
+
+static void I386OP(enter16)(i386_state *cpustate) // Opcode 0xc8
+{
+ UINT16 framesize = FETCH16(cpustate);
+ UINT8 level = FETCH(cpustate) % 32;
+ UINT8 x;
+ UINT16 frameptr;
+ PUSH16(cpustate,REG16(BP));
+
+ if(!STACK_32BIT)
+ frameptr = REG16(SP);
+ else
+ frameptr = REG32(ESP);
+
+ if(level > 0)
+ {
+ for(x=1;x<level-1;x++)
+ {
+ REG16(BP) -= 2;
+ PUSH16(cpustate,READ16(cpustate,REG16(BP)));
+ }
+ PUSH16(cpustate,frameptr);
+ }
+ REG16(BP) = frameptr;
+ if(!STACK_32BIT)
+ REG16(SP) -= framesize;
+ else
+ REG32(ESP) -= framesize;
+ CYCLES(cpustate,CYCLES_ENTER);
+}
+
+static void I386OP(leave16)(i386_state *cpustate) // Opcode 0xc9
+{
+ if(!STACK_32BIT)
+ REG16(SP) = REG16(BP);
+ else
+ REG32(ESP) = REG32(EBP);
+ REG16(BP) = POP16(cpustate);
+ CYCLES(cpustate,CYCLES_LEAVE);
+}
+
+static void I386OP(lodsw)(i386_state *cpustate) // Opcode 0xad
+{
+ UINT32 eas;
+ if( cpustate->segment_prefix ) {
+ eas = i386_translate(cpustate, cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI) );
+ } else {
+ eas = i386_translate(cpustate, DS, cpustate->address_size ? REG32(ESI) : REG16(SI) );
+ }
+ REG16(AX) = READ16(cpustate,eas);
+ BUMP_SI(cpustate,2);
+ CYCLES(cpustate,CYCLES_LODS);
+}
+
+static void I386OP(loop16)(i386_state *cpustate) // Opcode 0xe2
+{
+ INT8 disp = FETCH(cpustate);
+ REG16(CX)--;
+ if( REG16(CX) != 0 ) {
+ if (cpustate->sreg[CS].d)
+ {
+ cpustate->eip += disp;
+ }
+ else
+ {
+ cpustate->eip = (cpustate->eip + disp) & 0xffff;
+ }
+ CHANGE_PC(cpustate,cpustate->eip);
+ }
+ CYCLES(cpustate,CYCLES_LOOP); /* TODO: Timing = 11 + m */
+}
+
+static void I386OP(loopne16)(i386_state *cpustate) // Opcode 0xe0
+{
+ INT8 disp = FETCH(cpustate);
+ REG16(CX)--;
+ if( REG16(CX) != 0 && cpustate->ZF == 0 ) {
+ if (cpustate->sreg[CS].d)
+ {
+ cpustate->eip += disp;
+ }
+ else
+ {
+ cpustate->eip = (cpustate->eip + disp) & 0xffff;
+ }
+ CHANGE_PC(cpustate,cpustate->eip);
+ }
+ CYCLES(cpustate,CYCLES_LOOPNZ); /* TODO: Timing = 11 + m */
+}
+
+static void I386OP(loopz16)(i386_state *cpustate) // Opcode 0xe1
+{
+ INT8 disp = FETCH(cpustate);
+ REG16(CX)--;
+ if( REG16(CX) != 0 && cpustate->ZF != 0 ) {
+ if (cpustate->sreg[CS].d)
+ {
+ cpustate->eip += disp;
+ }
+ else
+ {
+ cpustate->eip = (cpustate->eip + disp) & 0xffff;
+ }
+ CHANGE_PC(cpustate,cpustate->eip);
+ }
+ CYCLES(cpustate,CYCLES_LOOPZ); /* TODO: Timing = 11 + m */
+}
+
+static void I386OP(mov_rm16_r16)(i386_state *cpustate) // Opcode 0x89
+{
+ UINT16 src;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_REG16(modrm);
+ STORE_RM16(modrm, src);
+ CYCLES(cpustate,CYCLES_MOV_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = LOAD_REG16(modrm);
+ WRITE16(cpustate,ea, src);
+ CYCLES(cpustate,CYCLES_MOV_REG_MEM);
+ }
+}
+
+static void I386OP(mov_r16_rm16)(i386_state *cpustate) // Opcode 0x8b
+{
+ UINT16 src;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_RM16(modrm);
+ STORE_REG16(modrm, src);
+ CYCLES(cpustate,CYCLES_MOV_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = READ16(cpustate,ea);
+ STORE_REG16(modrm, src);
+ CYCLES(cpustate,CYCLES_MOV_MEM_REG);
+ }
+}
+
+static void I386OP(mov_rm16_i16)(i386_state *cpustate) // Opcode 0xc7
+{
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ UINT16 value = FETCH16(cpustate);
+ STORE_RM16(modrm, value);
+ CYCLES(cpustate,CYCLES_MOV_IMM_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT16 value = FETCH16(cpustate);
+ WRITE16(cpustate,ea, value);
+ CYCLES(cpustate,CYCLES_MOV_IMM_MEM);
+ }
+}
+
+static void I386OP(mov_ax_m16)(i386_state *cpustate) // Opcode 0xa1
+{
+ UINT32 offset, ea;
+ if( cpustate->address_size ) {
+ offset = FETCH32(cpustate);
+ } else {
+ offset = FETCH16(cpustate);
+ }
+ /* TODO: Not sure if this is correct... */
+ if( cpustate->segment_prefix ) {
+ ea = i386_translate(cpustate, cpustate->segment_override, offset );
+ } else {
+ ea = i386_translate(cpustate, DS, offset );
+ }
+ REG16(AX) = READ16(cpustate,ea);
+ CYCLES(cpustate,CYCLES_MOV_MEM_ACC);
+}
+
+static void I386OP(mov_m16_ax)(i386_state *cpustate) // Opcode 0xa3
+{
+ UINT32 offset, ea;
+ if( cpustate->address_size ) {
+ offset = FETCH32(cpustate);
+ } else {
+ offset = FETCH16(cpustate);
+ }
+ /* TODO: Not sure if this is correct... */
+ if( cpustate->segment_prefix ) {
+ ea = i386_translate(cpustate, cpustate->segment_override, offset );
+ } else {
+ ea = i386_translate(cpustate, DS, offset );
+ }
+ WRITE16(cpustate, ea, REG16(AX) );
+ CYCLES(cpustate,CYCLES_MOV_ACC_MEM);
+}
+
+static void I386OP(mov_ax_i16)(i386_state *cpustate) // Opcode 0xb8
+{
+ REG16(AX) = FETCH16(cpustate);
+ CYCLES(cpustate,CYCLES_MOV_IMM_REG);
+}
+
+static void I386OP(mov_cx_i16)(i386_state *cpustate) // Opcode 0xb9
+{
+ REG16(CX) = FETCH16(cpustate);
+ CYCLES(cpustate,CYCLES_MOV_IMM_REG);
+}
+
+static void I386OP(mov_dx_i16)(i386_state *cpustate) // Opcode 0xba
+{
+ REG16(DX) = FETCH16(cpustate);
+ CYCLES(cpustate,CYCLES_MOV_IMM_REG);
+}
+
+static void I386OP(mov_bx_i16)(i386_state *cpustate) // Opcode 0xbb
+{
+ REG16(BX) = FETCH16(cpustate);
+ CYCLES(cpustate,CYCLES_MOV_IMM_REG);
+}
+
+static void I386OP(mov_sp_i16)(i386_state *cpustate) // Opcode 0xbc
+{
+ REG16(SP) = FETCH16(cpustate);
+ CYCLES(cpustate,CYCLES_MOV_IMM_REG);
+}
+
+static void I386OP(mov_bp_i16)(i386_state *cpustate) // Opcode 0xbd
+{
+ REG16(BP) = FETCH16(cpustate);
+ CYCLES(cpustate,CYCLES_MOV_IMM_REG);
+}
+
+static void I386OP(mov_si_i16)(i386_state *cpustate) // Opcode 0xbe
+{
+ REG16(SI) = FETCH16(cpustate);
+ CYCLES(cpustate,CYCLES_MOV_IMM_REG);
+}
+
+static void I386OP(mov_di_i16)(i386_state *cpustate) // Opcode 0xbf
+{
+ REG16(DI) = FETCH16(cpustate);
+ CYCLES(cpustate,CYCLES_MOV_IMM_REG);
+}
+
+static void I386OP(movsw)(i386_state *cpustate) // Opcode 0xa5
+{
+ UINT32 eas, ead;
+ UINT16 v;
+ if( cpustate->segment_prefix ) {
+ eas = i386_translate(cpustate, cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI) );
+ } else {
+ eas = i386_translate(cpustate, DS, cpustate->address_size ? REG32(ESI) : REG16(SI) );
+ }
+ ead = i386_translate(cpustate, ES, cpustate->address_size ? REG32(EDI) : REG16(DI) );
+ v = READ16(cpustate,eas);
+ WRITE16(cpustate,ead, v);
+ BUMP_SI(cpustate,2);
+ BUMP_DI(cpustate,2);
+ CYCLES(cpustate,CYCLES_MOVS);
+}
+
+static void I386OP(movsx_r16_rm8)(i386_state *cpustate) // Opcode 0x0f be
+{
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ INT16 src = (INT8)LOAD_RM8(modrm);
+ STORE_REG16(modrm, src);
+ CYCLES(cpustate,CYCLES_MOVSX_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ INT16 src = (INT8)READ8(cpustate,ea);
+ STORE_REG16(modrm, src);
+ CYCLES(cpustate,CYCLES_MOVSX_MEM_REG);
+ }
+}
+
+static void I386OP(movzx_r16_rm8)(i386_state *cpustate) // Opcode 0x0f b6
+{
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ UINT16 src = (UINT8)LOAD_RM8(modrm);
+ STORE_REG16(modrm, src);
+ CYCLES(cpustate,CYCLES_MOVZX_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT16 src = (UINT8)READ8(cpustate,ea);
+ STORE_REG16(modrm, src);
+ CYCLES(cpustate,CYCLES_MOVZX_MEM_REG);
+ }
+}
+
+static void I386OP(or_rm16_r16)(i386_state *cpustate) // Opcode 0x09
+{
+ UINT16 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_REG16(modrm);
+ dst = LOAD_RM16(modrm);
+ dst = OR16(cpustate,dst, src);
+ STORE_RM16(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = LOAD_REG16(modrm);
+ dst = READ16(cpustate,ea);
+ dst = OR16(cpustate,dst, src);
+ WRITE16(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+}
+
+static void I386OP(or_r16_rm16)(i386_state *cpustate) // Opcode 0x0b
+{
+ UINT16 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_RM16(modrm);
+ dst = LOAD_REG16(modrm);
+ dst = OR16(cpustate,dst, src);
+ STORE_REG16(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = READ16(cpustate,ea);
+ dst = LOAD_REG16(modrm);
+ dst = OR16(cpustate,dst, src);
+ STORE_REG16(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_MEM_REG);
+ }
+}
+
+static void I386OP(or_ax_i16)(i386_state *cpustate) // Opcode 0x0d
+{
+ UINT16 src, dst;
+ src = FETCH16(cpustate);
+ dst = REG16(AX);
+ dst = OR16(cpustate,dst, src);
+ REG16(AX) = dst;
+ CYCLES(cpustate,CYCLES_ALU_IMM_ACC);
+}
+
+static void I386OP(out_ax_i8)(i386_state *cpustate) // Opcode 0xe7
+{
+ UINT16 port = FETCH(cpustate);
+ UINT16 data = REG16(AX);
+ WRITEPORT16(cpustate, port, data);
+ CYCLES(cpustate,CYCLES_OUT_VAR);
+}
+
+static void I386OP(out_ax_dx)(i386_state *cpustate) // Opcode 0xef
+{
+ UINT16 port = REG16(DX);
+ UINT16 data = REG16(AX);
+ WRITEPORT16(cpustate, port, data);
+ CYCLES(cpustate,CYCLES_OUT);
+}
+
+static void I386OP(pop_ax)(i386_state *cpustate) // Opcode 0x58
+{
+ REG16(AX) = POP16(cpustate);
+ CYCLES(cpustate,CYCLES_POP_REG_SHORT);
+}
+
+static void I386OP(pop_cx)(i386_state *cpustate) // Opcode 0x59
+{
+ REG16(CX) = POP16(cpustate);
+ CYCLES(cpustate,CYCLES_POP_REG_SHORT);
+}
+
+static void I386OP(pop_dx)(i386_state *cpustate) // Opcode 0x5a
+{
+ REG16(DX) = POP16(cpustate);
+ CYCLES(cpustate,CYCLES_POP_REG_SHORT);
+}
+
+static void I386OP(pop_bx)(i386_state *cpustate) // Opcode 0x5b
+{
+ REG16(BX) = POP16(cpustate);
+ CYCLES(cpustate,CYCLES_POP_REG_SHORT);
+}
+
+static void I386OP(pop_sp)(i386_state *cpustate) // Opcode 0x5c
+{
+ REG16(SP) = POP16(cpustate);
+ CYCLES(cpustate,CYCLES_POP_REG_SHORT);
+}
+
+static void I386OP(pop_bp)(i386_state *cpustate) // Opcode 0x5d
+{
+ REG16(BP) = POP16(cpustate);
+ CYCLES(cpustate,CYCLES_POP_REG_SHORT);
+}
+
+static void I386OP(pop_si)(i386_state *cpustate) // Opcode 0x5e
+{
+ REG16(SI) = POP16(cpustate);
+ CYCLES(cpustate,CYCLES_POP_REG_SHORT);
+}
+
+static void I386OP(pop_di)(i386_state *cpustate) // Opcode 0x5f
+{
+ REG16(DI) = POP16(cpustate);
+ CYCLES(cpustate,CYCLES_POP_REG_SHORT);
+}
+
+static void I386OP(pop_ds16)(i386_state *cpustate) // Opcode 0x1f
+{
+ cpustate->sreg[DS].selector = POP16(cpustate);
+ if( PROTECTED_MODE ) {
+ i386_load_segment_descriptor(cpustate,DS);
+ } else {
+ i386_load_segment_descriptor(cpustate,DS);
+ }
+ CYCLES(cpustate,CYCLES_POP_SREG);
+}
+
+static void I386OP(pop_es16)(i386_state *cpustate) // Opcode 0x07
+{
+ cpustate->sreg[ES].selector = POP16(cpustate);
+ if( PROTECTED_MODE ) {
+ i386_load_segment_descriptor(cpustate,ES);
+ } else {
+ i386_load_segment_descriptor(cpustate,ES);
+ }
+ CYCLES(cpustate,CYCLES_POP_SREG);
+}
+
+static void I386OP(pop_fs16)(i386_state *cpustate) // Opcode 0x0f a1
+{
+ cpustate->sreg[FS].selector = POP16(cpustate);
+ if( PROTECTED_MODE ) {
+ i386_load_segment_descriptor(cpustate,FS);
+ } else {
+ i386_load_segment_descriptor(cpustate,FS);
+ }
+ CYCLES(cpustate,CYCLES_POP_SREG);
+}
+
+static void I386OP(pop_gs16)(i386_state *cpustate) // Opcode 0x0f a9
+{
+ cpustate->sreg[GS].selector = POP16(cpustate);
+ if( PROTECTED_MODE ) {
+ i386_load_segment_descriptor(cpustate,GS);
+ } else {
+ i386_load_segment_descriptor(cpustate,GS);
+ }
+ CYCLES(cpustate,CYCLES_POP_SREG);
+}
+
+static void I386OP(pop_ss16)(i386_state *cpustate) // Opcode 0x17
+{
+ if(cpustate->IF != 0) // if external interrupts are enabled
+ {
+ cpustate->IF = 0; // reset IF for the next instruction
+ cpustate->delayed_interrupt_enable = 1;
+ }
+
+ cpustate->sreg[SS].selector = POP16(cpustate);
+ if( PROTECTED_MODE ) {
+ i386_load_segment_descriptor(cpustate,SS);
+ } else {
+ i386_load_segment_descriptor(cpustate,SS);
+ }
+ CYCLES(cpustate,CYCLES_POP_SREG);
+}
+
+static void I386OP(pop_rm16)(i386_state *cpustate) // Opcode 0x8f
+{
+ UINT8 modrm = FETCH(cpustate);
+ UINT16 value = POP16(cpustate);
+
+ if( modrm >= 0xc0 ) {
+ STORE_RM16(modrm, value);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ WRITE16(cpustate,ea, value);
+ }
+ CYCLES(cpustate,CYCLES_POP_RM);
+}
+
+static void I386OP(popa)(i386_state *cpustate) // Opcode 0x61
+{
+ REG16(DI) = POP16(cpustate);
+ REG16(SI) = POP16(cpustate);
+ REG16(BP) = POP16(cpustate);
+ REG16(SP) += 2;
+ REG16(BX) = POP16(cpustate);
+ REG16(DX) = POP16(cpustate);
+ REG16(CX) = POP16(cpustate);
+ REG16(AX) = POP16(cpustate);
+ CYCLES(cpustate,CYCLES_POPA);
+}
+
+static void I386OP(popf)(i386_state *cpustate) // Opcode 0x9d
+{
+ UINT16 value = POP16(cpustate);
+ set_flags(cpustate,value);
+ CYCLES(cpustate,CYCLES_POPF);
+}
+
+static void I386OP(push_ax)(i386_state *cpustate) // Opcode 0x50
+{
+ PUSH16(cpustate, REG16(AX) );
+ CYCLES(cpustate,CYCLES_PUSH_REG_SHORT);
+}
+
+static void I386OP(push_cx)(i386_state *cpustate) // Opcode 0x51
+{
+ PUSH16(cpustate, REG16(CX) );
+ CYCLES(cpustate,CYCLES_PUSH_REG_SHORT);
+}
+
+static void I386OP(push_dx)(i386_state *cpustate) // Opcode 0x52
+{
+ PUSH16(cpustate, REG16(DX) );
+ CYCLES(cpustate,CYCLES_PUSH_REG_SHORT);
+}
+
+static void I386OP(push_bx)(i386_state *cpustate) // Opcode 0x53
+{
+ PUSH16(cpustate, REG16(BX) );
+ CYCLES(cpustate,CYCLES_PUSH_REG_SHORT);
+}
+
+static void I386OP(push_sp)(i386_state *cpustate) // Opcode 0x54
+{
+ PUSH16(cpustate, REG16(SP) );
+ CYCLES(cpustate,CYCLES_PUSH_REG_SHORT);
+}
+
+static void I386OP(push_bp)(i386_state *cpustate) // Opcode 0x55
+{
+ PUSH16(cpustate, REG16(BP) );
+ CYCLES(cpustate,CYCLES_PUSH_REG_SHORT);
+}
+
+static void I386OP(push_si)(i386_state *cpustate) // Opcode 0x56
+{
+ PUSH16(cpustate, REG16(SI) );
+ CYCLES(cpustate,CYCLES_PUSH_REG_SHORT);
+}
+
+static void I386OP(push_di)(i386_state *cpustate) // Opcode 0x57
+{
+ PUSH16(cpustate, REG16(DI) );
+ CYCLES(cpustate,CYCLES_PUSH_REG_SHORT);
+}
+
+static void I386OP(push_cs16)(i386_state *cpustate) // Opcode 0x0e
+{
+ PUSH16(cpustate, cpustate->sreg[CS].selector );
+ CYCLES(cpustate,CYCLES_PUSH_SREG);
+}
+
+static void I386OP(push_ds16)(i386_state *cpustate) // Opcode 0x1e
+{
+ PUSH16(cpustate, cpustate->sreg[DS].selector );
+ CYCLES(cpustate,CYCLES_PUSH_SREG);
+}
+
+static void I386OP(push_es16)(i386_state *cpustate) // Opcode 0x06
+{
+ PUSH16(cpustate, cpustate->sreg[ES].selector );
+ CYCLES(cpustate,CYCLES_PUSH_SREG);
+}
+
+static void I386OP(push_fs16)(i386_state *cpustate) // Opcode 0x0f a0
+{
+ PUSH16(cpustate, cpustate->sreg[FS].selector );
+ CYCLES(cpustate,CYCLES_PUSH_SREG);
+}
+
+static void I386OP(push_gs16)(i386_state *cpustate) // Opcode 0x0f a8
+{
+ PUSH16(cpustate, cpustate->sreg[GS].selector );
+ CYCLES(cpustate,CYCLES_PUSH_SREG);
+}
+
+static void I386OP(push_ss16)(i386_state *cpustate) // Opcode 0x16
+{
+ PUSH16(cpustate, cpustate->sreg[SS].selector );
+ CYCLES(cpustate,CYCLES_PUSH_SREG);
+}
+
+static void I386OP(push_i16)(i386_state *cpustate) // Opcode 0x68
+{
+ UINT16 value = FETCH16(cpustate);
+ PUSH16(cpustate,value);
+ CYCLES(cpustate,CYCLES_PUSH_IMM);
+}
+
+static void I386OP(pusha)(i386_state *cpustate) // Opcode 0x60
+{
+ UINT16 temp = REG16(SP);
+ PUSH16(cpustate, REG16(AX) );
+ PUSH16(cpustate, REG16(CX) );
+ PUSH16(cpustate, REG16(DX) );
+ PUSH16(cpustate, REG16(BX) );
+ PUSH16(cpustate, temp );
+ PUSH16(cpustate, REG16(BP) );
+ PUSH16(cpustate, REG16(SI) );
+ PUSH16(cpustate, REG16(DI) );
+ CYCLES(cpustate,CYCLES_PUSHA);
+}
+
+static void I386OP(pushf)(i386_state *cpustate) // Opcode 0x9c
+{
+ PUSH16(cpustate, get_flags(cpustate) & 0xffff );
+ CYCLES(cpustate,CYCLES_PUSHF);
+}
+
+static void I386OP(ret_near16_i16)(i386_state *cpustate) // Opcode 0xc2
+{
+ INT16 disp = FETCH16(cpustate);
+ cpustate->eip = POP16(cpustate);
+ REG16(SP) += disp;
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_RET_IMM); /* TODO: Timing = 10 + m */
+}
+
+static void I386OP(ret_near16)(i386_state *cpustate) // Opcode 0xc3
+{
+ cpustate->eip = POP16(cpustate);
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_RET); /* TODO: Timing = 10 + m */
+}
+
+static void I386OP(sbb_rm16_r16)(i386_state *cpustate) // Opcode 0x19
+{
+ UINT16 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_REG16(modrm);
+ dst = LOAD_RM16(modrm);
+ dst = SBB16(cpustate, dst, src, cpustate->CF);
+ STORE_RM16(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = LOAD_REG16(modrm);
+ dst = READ16(cpustate,ea);
+ dst = SBB16(cpustate, dst, src, cpustate->CF);
+ WRITE16(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+}
+
+static void I386OP(sbb_r16_rm16)(i386_state *cpustate) // Opcode 0x1b
+{
+ UINT16 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_RM16(modrm);
+ dst = LOAD_REG16(modrm);
+ dst = SBB16(cpustate, dst, src, cpustate->CF);
+ STORE_REG16(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = READ16(cpustate,ea);
+ dst = LOAD_REG16(modrm);
+ dst = SBB16(cpustate, dst, src, cpustate->CF);
+ STORE_REG16(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_MEM_REG);
+ }
+}
+
+static void I386OP(sbb_ax_i16)(i386_state *cpustate) // Opcode 0x1d
+{
+ UINT16 src, dst;
+ src = FETCH16(cpustate);
+ dst = REG16(AX);
+ dst = SBB16(cpustate, dst, src, cpustate->CF);
+ REG16(AX) = dst;
+ CYCLES(cpustate,CYCLES_ALU_IMM_ACC);
+}
+
+static void I386OP(scasw)(i386_state *cpustate) // Opcode 0xaf
+{
+ UINT32 eas;
+ UINT16 src, dst;
+ eas = i386_translate(cpustate, ES, cpustate->address_size ? REG32(EDI) : REG16(DI) );
+ src = READ16(cpustate,eas);
+ dst = REG16(AX);
+ SUB16(cpustate,dst, src);
+ BUMP_DI(cpustate,2);
+ CYCLES(cpustate,CYCLES_SCAS);
+}
+
+static void I386OP(shld16_i8)(i386_state *cpustate) // Opcode 0x0f a4
+{
+ /* TODO: Correct flags */
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ UINT16 dst = LOAD_RM16(modrm);
+ UINT16 upper = LOAD_REG16(modrm);
+ UINT8 shift = FETCH(cpustate);
+ if( shift > 31 || shift == 0 ) {
+
+ } else if( shift > 15 ) {
+ cpustate->CF = (dst & (1 << (16-shift))) ? 1 : 0;
+ dst = (upper << (shift-16)) | (upper >> (32-shift));
+ SetSZPF16(dst);
+ } else {
+ cpustate->CF = (dst & (1 << (16-shift))) ? 1 : 0;
+ dst = (dst << shift) | (upper >> (16-shift));
+ SetSZPF16(dst);
+ }
+ STORE_RM16(modrm, dst);
+ CYCLES(cpustate,CYCLES_SHLD_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT16 dst = READ16(cpustate,ea);
+ UINT16 upper = LOAD_REG16(modrm);
+ UINT8 shift = FETCH(cpustate);
+ if( shift > 31 || shift == 0 ) {
+
+ } else if( shift > 15 ) {
+ cpustate->CF = (dst & (1 << (16-shift))) ? 1 : 0;
+ dst = (upper << (shift-16)) | (upper >> (32-shift));
+ SetSZPF16(dst);
+ } else {
+ cpustate->CF = (dst & (1 << (16-shift))) ? 1 : 0;
+ dst = (dst << shift) | (upper >> (16-shift));
+ SetSZPF16(dst);
+ }
+ WRITE16(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_SHLD_MEM);
+ }
+}
+
+static void I386OP(shld16_cl)(i386_state *cpustate) // Opcode 0x0f a5
+{
+ /* TODO: Correct flags */
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ UINT16 dst = LOAD_RM16(modrm);
+ UINT16 upper = LOAD_REG16(modrm);
+ UINT8 shift = REG8(CL);
+ if( shift > 31 || shift == 0 ) {
+
+ } else if( shift > 15 ) {
+ cpustate->CF = (dst & (1 << (16-shift))) ? 1 : 0;
+ dst = (upper << (shift-16)) | (upper >> (32-shift));
+ SetSZPF16(dst);
+ } else {
+ cpustate->CF = (dst & (1 << (16-shift))) ? 1 : 0;
+ dst = (dst << shift) | (upper >> (16-shift));
+ SetSZPF16(dst);
+ }
+ STORE_RM16(modrm, dst);
+ CYCLES(cpustate,CYCLES_SHLD_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT16 dst = READ16(cpustate,ea);
+ UINT16 upper = LOAD_REG16(modrm);
+ UINT8 shift = REG8(CL);
+ if( shift > 31 || shift == 0 ) {
+
+ } else if( shift > 15 ) {
+ cpustate->CF = (dst & (1 << (16-shift))) ? 1 : 0;
+ dst = (upper << (shift-16)) | (upper >> (32-shift));
+ SetSZPF16(dst);
+ } else {
+ cpustate->CF = (dst & (1 << (16-shift))) ? 1 : 0;
+ dst = (dst << shift) | (upper >> (16-shift));
+ SetSZPF16(dst);
+ }
+ WRITE16(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_SHLD_MEM);
+ }
+}
+
+static void I386OP(shrd16_i8)(i386_state *cpustate) // Opcode 0x0f ac
+{
+ /* TODO: Correct flags */
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ UINT16 dst = LOAD_RM16(modrm);
+ UINT16 upper = LOAD_REG16(modrm);
+ UINT8 shift = FETCH(cpustate);
+ if( shift > 15 || shift == 0) {
+
+ } else {
+ cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0;
+ dst = (dst >> shift) | (upper << (16-shift));
+ SetSZPF16(dst);
+ }
+ STORE_RM16(modrm, dst);
+ CYCLES(cpustate,CYCLES_SHRD_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT16 dst = READ16(cpustate,ea);
+ UINT16 upper = LOAD_REG16(modrm);
+ UINT8 shift = FETCH(cpustate);
+ if( shift > 15 || shift == 0) {
+
+ } else {
+ cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0;
+ dst = (dst >> shift) | (upper << (16-shift));
+ SetSZPF16(dst);
+ }
+ WRITE16(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_SHRD_MEM);
+ }
+}
+
+static void I386OP(shrd16_cl)(i386_state *cpustate) // Opcode 0x0f ad
+{
+ /* TODO: Correct flags */
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ UINT16 dst = LOAD_RM16(modrm);
+ UINT16 upper = LOAD_REG16(modrm);
+ UINT8 shift = REG8(CL);
+ if( shift > 15 || shift == 0) {
+
+ } else {
+ cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0;
+ dst = (dst >> shift) | (upper << (16-shift));
+ SetSZPF16(dst);
+ }
+ STORE_RM16(modrm, dst);
+ CYCLES(cpustate,CYCLES_SHRD_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT16 dst = READ16(cpustate,ea);
+ UINT16 upper = LOAD_REG16(modrm);
+ UINT8 shift = REG8(CL);
+ if( shift > 15 || shift == 0) {
+
+ } else {
+ cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0;
+ dst = (dst >> shift) | (upper << (16-shift));
+ SetSZPF16(dst);
+ }
+ WRITE16(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_SHRD_MEM);
+ }
+}
+
+static void I386OP(stosw)(i386_state *cpustate) // Opcode 0xab
+{
+ UINT32 ead;
+ ead = i386_translate(cpustate, ES, cpustate->address_size ? REG32(EDI) : REG16(DI) );
+ WRITE16(cpustate,ead, REG16(AX));
+ BUMP_DI(cpustate,2);
+ CYCLES(cpustate,CYCLES_STOS);
+}
+
+static void I386OP(sub_rm16_r16)(i386_state *cpustate) // Opcode 0x29
+{
+ UINT16 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_REG16(modrm);
+ dst = LOAD_RM16(modrm);
+ dst = SUB16(cpustate,dst, src);
+ STORE_RM16(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = LOAD_REG16(modrm);
+ dst = READ16(cpustate,ea);
+ dst = SUB16(cpustate,dst, src);
+ WRITE16(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+}
+
+static void I386OP(sub_r16_rm16)(i386_state *cpustate) // Opcode 0x2b
+{
+ UINT16 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_RM16(modrm);
+ dst = LOAD_REG16(modrm);
+ dst = SUB16(cpustate,dst, src);
+ STORE_REG16(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = READ16(cpustate,ea);
+ dst = LOAD_REG16(modrm);
+ dst = SUB16(cpustate,dst, src);
+ STORE_REG16(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_MEM_REG);
+ }
+}
+
+static void I386OP(sub_ax_i16)(i386_state *cpustate) // Opcode 0x2d
+{
+ UINT16 src, dst;
+ src = FETCH16(cpustate);
+ dst = REG16(AX);
+ dst = SUB16(cpustate,dst, src);
+ REG16(AX) = dst;
+ CYCLES(cpustate,CYCLES_ALU_IMM_ACC);
+}
+
+static void I386OP(test_ax_i16)(i386_state *cpustate) // Opcode 0xa9
+{
+ UINT16 src = FETCH16(cpustate);
+ UINT16 dst = REG16(AX);
+ dst = src & dst;
+ SetSZPF16(dst);
+ cpustate->CF = 0;
+ cpustate->OF = 0;
+ CYCLES(cpustate,CYCLES_TEST_IMM_ACC);
+}
+
+static void I386OP(test_rm16_r16)(i386_state *cpustate) // Opcode 0x85
+{
+ UINT16 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_REG16(modrm);
+ dst = LOAD_RM16(modrm);
+ dst = src & dst;
+ SetSZPF16(dst);
+ cpustate->CF = 0;
+ cpustate->OF = 0;
+ CYCLES(cpustate,CYCLES_TEST_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = LOAD_REG16(modrm);
+ dst = READ16(cpustate,ea);
+ dst = src & dst;
+ SetSZPF16(dst);
+ cpustate->CF = 0;
+ cpustate->OF = 0;
+ CYCLES(cpustate,CYCLES_TEST_REG_MEM);
+ }
+}
+
+static void I386OP(xchg_ax_cx)(i386_state *cpustate) // Opcode 0x91
+{
+ UINT16 temp;
+ temp = REG16(AX);
+ REG16(AX) = REG16(CX);
+ REG16(CX) = temp;
+ CYCLES(cpustate,CYCLES_XCHG_REG_REG);
+}
+
+static void I386OP(xchg_ax_dx)(i386_state *cpustate) // Opcode 0x92
+{
+ UINT16 temp;
+ temp = REG16(AX);
+ REG16(AX) = REG16(DX);
+ REG16(DX) = temp;
+ CYCLES(cpustate,CYCLES_XCHG_REG_REG);
+}
+
+static void I386OP(xchg_ax_bx)(i386_state *cpustate) // Opcode 0x93
+{
+ UINT16 temp;
+ temp = REG16(AX);
+ REG16(AX) = REG16(BX);
+ REG16(BX) = temp;
+ CYCLES(cpustate,CYCLES_XCHG_REG_REG);
+}
+
+static void I386OP(xchg_ax_sp)(i386_state *cpustate) // Opcode 0x94
+{
+ UINT16 temp;
+ temp = REG16(AX);
+ REG16(AX) = REG16(SP);
+ REG16(SP) = temp;
+ CYCLES(cpustate,CYCLES_XCHG_REG_REG);
+}
+
+static void I386OP(xchg_ax_bp)(i386_state *cpustate) // Opcode 0x95
+{
+ UINT16 temp;
+ temp = REG16(AX);
+ REG16(AX) = REG16(BP);
+ REG16(BP) = temp;
+ CYCLES(cpustate,CYCLES_XCHG_REG_REG);
+}
+
+static void I386OP(xchg_ax_si)(i386_state *cpustate) // Opcode 0x96
+{
+ UINT16 temp;
+ temp = REG16(AX);
+ REG16(AX) = REG16(SI);
+ REG16(SI) = temp;
+ CYCLES(cpustate,CYCLES_XCHG_REG_REG);
+}
+
+static void I386OP(xchg_ax_di)(i386_state *cpustate) // Opcode 0x97
+{
+ UINT16 temp;
+ temp = REG16(AX);
+ REG16(AX) = REG16(DI);
+ REG16(DI) = temp;
+ CYCLES(cpustate,CYCLES_XCHG_REG_REG);
+}
+
+static void I386OP(xchg_r16_rm16)(i386_state *cpustate) // Opcode 0x87
+{
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ UINT16 src = LOAD_RM16(modrm);
+ UINT16 dst = LOAD_REG16(modrm);
+ STORE_REG16(modrm, src);
+ STORE_RM16(modrm, dst);
+ CYCLES(cpustate,CYCLES_XCHG_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT16 src = READ16(cpustate,ea);
+ UINT16 dst = LOAD_REG16(modrm);
+ STORE_REG16(modrm, src);
+ WRITE16(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_XCHG_REG_MEM);
+ }
+}
+
+static void I386OP(xor_rm16_r16)(i386_state *cpustate) // Opcode 0x31
+{
+ UINT16 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_REG16(modrm);
+ dst = LOAD_RM16(modrm);
+ dst = XOR16(cpustate,dst, src);
+ STORE_RM16(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = LOAD_REG16(modrm);
+ dst = READ16(cpustate,ea);
+ dst = XOR16(cpustate,dst, src);
+ WRITE16(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+}
+
+static void I386OP(xor_r16_rm16)(i386_state *cpustate) // Opcode 0x33
+{
+ UINT16 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_RM16(modrm);
+ dst = LOAD_REG16(modrm);
+ dst = XOR16(cpustate,dst, src);
+ STORE_REG16(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = READ16(cpustate,ea);
+ dst = LOAD_REG16(modrm);
+ dst = XOR16(cpustate,dst, src);
+ STORE_REG16(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_MEM_REG);
+ }
+}
+
+static void I386OP(xor_ax_i16)(i386_state *cpustate) // Opcode 0x35
+{
+ UINT16 src, dst;
+ src = FETCH16(cpustate);
+ dst = REG16(AX);
+ dst = XOR16(cpustate,dst, src);
+ REG16(AX) = dst;
+ CYCLES(cpustate,CYCLES_ALU_IMM_ACC);
+}
+
+
+
+static void I386OP(group81_16)(i386_state *cpustate) // Opcode 0x81
+{
+ UINT32 ea;
+ UINT16 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+
+ switch( (modrm >> 3) & 0x7 )
+ {
+ case 0: // ADD Rm16, i16
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM16(modrm);
+ src = FETCH16(cpustate);
+ dst = ADD16(cpustate,dst, src);
+ STORE_RM16(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ dst = READ16(cpustate,ea);
+ src = FETCH16(cpustate);
+ dst = ADD16(cpustate,dst, src);
+ WRITE16(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+ break;
+ case 1: // OR Rm16, i16
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM16(modrm);
+ src = FETCH16(cpustate);
+ dst = OR16(cpustate,dst, src);
+ STORE_RM16(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ dst = READ16(cpustate,ea);
+ src = FETCH16(cpustate);
+ dst = OR16(cpustate,dst, src);
+ WRITE16(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+ break;
+ case 2: // ADC Rm16, i16
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM16(modrm);
+ src = FETCH16(cpustate);
+ dst = ADC16(cpustate, dst, src, cpustate->CF);
+ STORE_RM16(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ dst = READ16(cpustate,ea);
+ src = FETCH16(cpustate);
+ dst = ADC16(cpustate, dst, src, cpustate->CF);
+ WRITE16(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+ break;
+ case 3: // SBB Rm16, i16
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM16(modrm);
+ src = FETCH16(cpustate);
+ dst = SBB16(cpustate, dst, src, cpustate->CF);
+ STORE_RM16(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ dst = READ16(cpustate,ea);
+ src = FETCH16(cpustate);
+ dst = SBB16(cpustate, dst, src, cpustate->CF);
+ WRITE16(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+ break;
+ case 4: // AND Rm16, i16
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM16(modrm);
+ src = FETCH16(cpustate);
+ dst = AND16(cpustate,dst, src);
+ STORE_RM16(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ dst = READ16(cpustate,ea);
+ src = FETCH16(cpustate);
+ dst = AND16(cpustate,dst, src);
+ WRITE16(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+ break;
+ case 5: // SUB Rm16, i16
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM16(modrm);
+ src = FETCH16(cpustate);
+ dst = SUB16(cpustate,dst, src);
+ STORE_RM16(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ dst = READ16(cpustate,ea);
+ src = FETCH16(cpustate);
+ dst = SUB16(cpustate,dst, src);
+ WRITE16(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+ break;
+ case 6: // XOR Rm16, i16
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM16(modrm);
+ src = FETCH16(cpustate);
+ dst = XOR16(cpustate,dst, src);
+ STORE_RM16(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ dst = READ16(cpustate,ea);
+ src = FETCH16(cpustate);
+ dst = XOR16(cpustate,dst, src);
+ WRITE16(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+ break;
+ case 7: // CMP Rm16, i16
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM16(modrm);
+ src = FETCH16(cpustate);
+ SUB16(cpustate,dst, src);
+ CYCLES(cpustate,CYCLES_CMP_REG_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ dst = READ16(cpustate,ea);
+ src = FETCH16(cpustate);
+ SUB16(cpustate,dst, src);
+ CYCLES(cpustate,CYCLES_CMP_REG_MEM);
+ }
+ break;
+ }
+}
+
+static void I386OP(group83_16)(i386_state *cpustate) // Opcode 0x83
+{
+ UINT32 ea;
+ UINT16 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+
+ switch( (modrm >> 3) & 0x7 )
+ {
+ case 0: // ADD Rm16, i16
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM16(modrm);
+ src = (UINT16)(INT16)(INT8)FETCH(cpustate);
+ dst = ADD16(cpustate,dst, src);
+ STORE_RM16(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ dst = READ16(cpustate,ea);
+ src = (UINT16)(INT16)(INT8)FETCH(cpustate);
+ dst = ADD16(cpustate,dst, src);
+ WRITE16(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+ break;
+ case 1: // OR Rm16, i16
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM16(modrm);
+ src = (UINT16)(INT16)(INT8)FETCH(cpustate);
+ dst = OR16(cpustate,dst, src);
+ STORE_RM16(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ dst = READ16(cpustate,ea);
+ src = (UINT16)(INT16)(INT8)FETCH(cpustate);
+ dst = OR16(cpustate,dst, src);
+ WRITE16(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+ break;
+ case 2: // ADC Rm16, i16
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM16(modrm);
+ src = (UINT16)(INT16)(INT8)FETCH(cpustate);
+ dst = ADC16(cpustate, dst, src, cpustate->CF);
+ STORE_RM16(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ dst = READ16(cpustate,ea);
+ src = (UINT16)(INT16)(INT8)FETCH(cpustate);
+ dst = ADC16(cpustate, dst, src, cpustate->CF);
+ WRITE16(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+ break;
+ case 3: // SBB Rm16, i16
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM16(modrm);
+ src = ((UINT16)(INT16)(INT8)FETCH(cpustate));
+ dst = SBB16(cpustate, dst, src, cpustate->CF);
+ STORE_RM16(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ dst = READ16(cpustate,ea);
+ src = ((UINT16)(INT16)(INT8)FETCH(cpustate));
+ dst = SBB16(cpustate, dst, src, cpustate->CF);
+ WRITE16(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+ break;
+ case 4: // AND Rm16, i16
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM16(modrm);
+ src = (UINT16)(INT16)(INT8)FETCH(cpustate);
+ dst = AND16(cpustate,dst, src);
+ STORE_RM16(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ dst = READ16(cpustate,ea);
+ src = (UINT16)(INT16)(INT8)FETCH(cpustate);
+ dst = AND16(cpustate,dst, src);
+ WRITE16(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+ break;
+ case 5: // SUB Rm16, i16
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM16(modrm);
+ src = (UINT16)(INT16)(INT8)FETCH(cpustate);
+ dst = SUB16(cpustate,dst, src);
+ STORE_RM16(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ dst = READ16(cpustate,ea);
+ src = (UINT16)(INT16)(INT8)FETCH(cpustate);
+ dst = SUB16(cpustate,dst, src);
+ WRITE16(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+ break;
+ case 6: // XOR Rm16, i16
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM16(modrm);
+ src = (UINT16)(INT16)(INT8)FETCH(cpustate);
+ dst = XOR16(cpustate,dst, src);
+ STORE_RM16(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ dst = READ16(cpustate,ea);
+ src = (UINT16)(INT16)(INT8)FETCH(cpustate);
+ dst = XOR16(cpustate,dst, src);
+ WRITE16(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+ break;
+ case 7: // CMP Rm16, i16
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM16(modrm);
+ src = (UINT16)(INT16)(INT8)FETCH(cpustate);
+ SUB16(cpustate,dst, src);
+ CYCLES(cpustate,CYCLES_CMP_REG_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ dst = READ16(cpustate,ea);
+ src = (UINT16)(INT16)(INT8)FETCH(cpustate);
+ SUB16(cpustate,dst, src);
+ CYCLES(cpustate,CYCLES_CMP_REG_MEM);
+ }
+ break;
+ }
+}
+
+static void I386OP(groupC1_16)(i386_state *cpustate) // Opcode 0xc1
+{
+ UINT16 dst;
+ UINT8 modrm = FETCH(cpustate);
+ UINT8 shift;
+
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM16(modrm);
+ shift = FETCH(cpustate) & 0x1f;
+ dst = i386_shift_rotate16(cpustate, modrm, dst, shift);
+ STORE_RM16(modrm, dst);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ dst = READ16(cpustate,ea);
+ shift = FETCH(cpustate) & 0x1f;
+ dst = i386_shift_rotate16(cpustate, modrm, dst, shift);
+ WRITE16(cpustate,ea, dst);
+ }
+}
+
+static void I386OP(groupD1_16)(i386_state *cpustate) // Opcode 0xd1
+{
+ UINT16 dst;
+ UINT8 modrm = FETCH(cpustate);
+
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM16(modrm);
+ dst = i386_shift_rotate16(cpustate, modrm, dst, 1);
+ STORE_RM16(modrm, dst);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ dst = READ16(cpustate,ea);
+ dst = i386_shift_rotate16(cpustate, modrm, dst, 1);
+ WRITE16(cpustate,ea, dst);
+ }
+}
+
+static void I386OP(groupD3_16)(i386_state *cpustate) // Opcode 0xd3
+{
+ UINT16 dst;
+ UINT8 modrm = FETCH(cpustate);
+
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM16(modrm);
+ dst = i386_shift_rotate16(cpustate, modrm, dst, REG8(CL));
+ STORE_RM16(modrm, dst);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ dst = READ16(cpustate,ea);
+ dst = i386_shift_rotate16(cpustate, modrm, dst, REG8(CL));
+ WRITE16(cpustate,ea, dst);
+ }
+}
+
+static void I386OP(groupF7_16)(i386_state *cpustate) // Opcode 0xf7
+{
+ UINT8 modrm = FETCH(cpustate);
+
+ switch( (modrm >> 3) & 0x7 )
+ {
+ case 0: /* TEST Rm16, i16 */
+ if( modrm >= 0xc0 ) {
+ UINT16 dst = LOAD_RM16(modrm);
+ UINT16 src = FETCH16(cpustate);
+ dst &= src;
+ cpustate->CF = cpustate->OF = cpustate->AF = 0;
+ SetSZPF16(dst);
+ CYCLES(cpustate,CYCLES_TEST_IMM_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT16 dst = READ16(cpustate,ea);
+ UINT16 src = FETCH16(cpustate);
+ dst &= src;
+ cpustate->CF = cpustate->OF = cpustate->AF = 0;
+ SetSZPF16(dst);
+ CYCLES(cpustate,CYCLES_TEST_IMM_MEM);
+ }
+ break;
+ case 2: /* NOT Rm16 */
+ if( modrm >= 0xc0 ) {
+ UINT16 dst = LOAD_RM16(modrm);
+ dst = ~dst;
+ STORE_RM16(modrm, dst);
+ CYCLES(cpustate,CYCLES_NOT_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT16 dst = READ16(cpustate,ea);
+ dst = ~dst;
+ WRITE16(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_NOT_MEM);
+ }
+ break;
+ case 3: /* NEG Rm16 */
+ if( modrm >= 0xc0 ) {
+ UINT16 dst = LOAD_RM16(modrm);
+ dst = SUB16(cpustate, 0, dst );
+ STORE_RM16(modrm, dst);
+ CYCLES(cpustate,CYCLES_NEG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT16 dst = READ16(cpustate,ea);
+ dst = SUB16(cpustate, 0, dst );
+ WRITE16(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_NEG_MEM);
+ }
+ break;
+ case 4: /* MUL AX, Rm16 */
+ {
+ UINT32 result;
+ UINT16 src, dst;
+ if( modrm >= 0xc0 ) {
+ src = LOAD_RM16(modrm);
+ CYCLES(cpustate,CYCLES_MUL16_ACC_REG); /* TODO: Correct multiply timing */
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = READ16(cpustate,ea);
+ CYCLES(cpustate,CYCLES_MUL16_ACC_MEM); /* TODO: Correct multiply timing */
+ }
+
+ dst = REG16(AX);
+ result = (UINT32)src * (UINT32)dst;
+ REG16(DX) = (UINT16)(result >> 16);
+ REG16(AX) = (UINT16)result;
+
+ cpustate->CF = cpustate->OF = (REG16(DX) != 0);
+ }
+ break;
+ case 5: /* IMUL AX, Rm16 */
+ {
+ INT32 result;
+ INT32 src, dst;
+ if( modrm >= 0xc0 ) {
+ src = (INT32)(INT16)LOAD_RM16(modrm);
+ CYCLES(cpustate,CYCLES_IMUL16_ACC_REG); /* TODO: Correct multiply timing */
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = (INT32)(INT16)READ16(cpustate,ea);
+ CYCLES(cpustate,CYCLES_IMUL16_ACC_MEM); /* TODO: Correct multiply timing */
+ }
+
+ dst = (INT32)(INT16)REG16(AX);
+ result = src * dst;
+
+ REG16(DX) = (UINT16)(result >> 16);
+ REG16(AX) = (UINT16)result;
+
+ cpustate->CF = cpustate->OF = !(result == (INT32)(INT16)result);
+ }
+ break;
+ case 6: /* DIV AX, Rm16 */
+ {
+ UINT32 quotient, remainder, result;
+ UINT16 src;
+ if( modrm >= 0xc0 ) {
+ src = LOAD_RM16(modrm);
+ CYCLES(cpustate,CYCLES_DIV16_ACC_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = READ16(cpustate,ea);
+ CYCLES(cpustate,CYCLES_DIV16_ACC_MEM);
+ }
+
+ quotient = ((UINT32)(REG16(DX)) << 16) | (UINT32)(REG16(AX));
+ if( src ) {
+ remainder = quotient % (UINT32)src;
+ result = quotient / (UINT32)src;
+ if( result > 0xffff ) {
+ /* TODO: Divide error */
+ } else {
+ REG16(DX) = (UINT16)remainder;
+ REG16(AX) = (UINT16)result;
+
+ // this flag is actually undefined, enable on non-cyrix
+ if (cpustate->cpuid_id0 != 0x69727943)
+ cpustate->CF = 1;
+ }
+ } else {
+ /* TODO: Divide by zero */
+ }
+ }
+ break;
+ case 7: /* IDIV AX, Rm16 */
+ {
+ INT32 quotient, remainder, result;
+ UINT16 src;
+ if( modrm >= 0xc0 ) {
+ src = LOAD_RM16(modrm);
+ CYCLES(cpustate,CYCLES_IDIV16_ACC_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = READ16(cpustate,ea);
+ CYCLES(cpustate,CYCLES_IDIV16_ACC_MEM);
+ }
+
+ quotient = (((INT32)REG16(DX)) << 16) | ((UINT32)REG16(AX));
+ if( src ) {
+ remainder = quotient % (INT32)(INT16)src;
+ result = quotient / (INT32)(INT16)src;
+ if( result > 0xffff ) {
+ /* TODO: Divide error */
+ } else {
+ REG16(DX) = (UINT16)remainder;
+ REG16(AX) = (UINT16)result;
+
+ // this flag is actually undefined, enable on non-cyrix
+ if (cpustate->cpuid_id0 != 0x69727943)
+ cpustate->CF = 1;
+ }
+ } else {
+ /* TODO: Divide by zero */
+ }
+ }
+ break;
+ }
+}
+
+static void I386OP(groupFF_16)(i386_state *cpustate) // Opcode 0xff
+{
+ UINT8 modrm = FETCH(cpustate);
+
+ switch( (modrm >> 3) & 0x7 )
+ {
+ case 0: /* INC Rm16 */
+ if( modrm >= 0xc0 ) {
+ UINT16 dst = LOAD_RM16(modrm);
+ dst = INC16(cpustate,dst);
+ STORE_RM16(modrm, dst);
+ CYCLES(cpustate,CYCLES_INC_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT16 dst = READ16(cpustate,ea);
+ dst = INC16(cpustate,dst);
+ WRITE16(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_INC_MEM);
+ }
+ break;
+ case 1: /* DEC Rm16 */
+ if( modrm >= 0xc0 ) {
+ UINT16 dst = LOAD_RM16(modrm);
+ dst = DEC16(cpustate,dst);
+ STORE_RM16(modrm, dst);
+ CYCLES(cpustate,CYCLES_DEC_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT16 dst = READ16(cpustate,ea);
+ dst = DEC16(cpustate,dst);
+ WRITE16(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_DEC_MEM);
+ }
+ break;
+ case 2: /* CALL Rm16 */
+ {
+ UINT16 address;
+ if( modrm >= 0xc0 ) {
+ address = LOAD_RM16(modrm);
+ CYCLES(cpustate,CYCLES_CALL_REG); /* TODO: Timing = 7 + m */
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ address = READ16(cpustate,ea);
+ CYCLES(cpustate,CYCLES_CALL_MEM); /* TODO: Timing = 10 + m */
+ }
+ PUSH16(cpustate, cpustate->eip );
+ cpustate->eip = address;
+ CHANGE_PC(cpustate,cpustate->eip);
+ }
+ break;
+ case 3: /* CALL FAR Rm16 */
+ {
+ UINT16 address, selector;
+ if( modrm >= 0xc0 )
+ {
+ fatalerror("i386: groupFF_16 /%d NYI", (modrm >> 3) & 0x7);
+ }
+ else
+ {
+ UINT32 ea = GetEA(cpustate,modrm);
+ address = READ16(cpustate,ea + 0);
+ selector = READ16(cpustate,ea + 2);
+ CYCLES(cpustate,CYCLES_CALL_MEM_INTERSEG); /* TODO: Timing = 10 + m */
+
+ if(PROTECTED_MODE && !V8086_MODE)
+ {
+ i386_protected_mode_call(cpustate,selector,address,1,0);
+ }
+ else
+ {
+ PUSH16(cpustate, cpustate->sreg[CS].selector );
+ PUSH16(cpustate, cpustate->eip );
+ cpustate->sreg[CS].selector = selector;
+ cpustate->performed_intersegment_jump = 1;
+ i386_load_segment_descriptor(cpustate, CS );
+ cpustate->eip = address;
+ CHANGE_PC(cpustate,cpustate->eip);
+ }
+ }
+ }
+ break;
+ case 4: /* JMP Rm16 */
+ {
+ UINT16 address;
+ if( modrm >= 0xc0 ) {
+ address = LOAD_RM16(modrm);
+ CYCLES(cpustate,CYCLES_JMP_REG); /* TODO: Timing = 7 + m */
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ address = READ16(cpustate,ea);
+ CYCLES(cpustate,CYCLES_JMP_MEM); /* TODO: Timing = 10 + m */
+ }
+ cpustate->eip = address;
+ CHANGE_PC(cpustate,cpustate->eip);
+ }
+ break;
+ case 5: /* JMP FAR Rm16 */
+ {
+ UINT16 address, selector;
+
+ if( modrm >= 0xc0 )
+ {
+ fatalerror("i386: groupFF_16 /%d NYI", (modrm >> 3) & 0x7);
+ }
+ else
+ {
+ UINT32 ea = GetEA(cpustate,modrm);
+ address = READ16(cpustate,ea + 0);
+ selector = READ16(cpustate,ea + 2);
+ CYCLES(cpustate,CYCLES_JMP_MEM_INTERSEG); /* TODO: Timing = 10 + m */
+ if(PROTECTED_MODE && !V8086_MODE)
+ {
+ i386_protected_mode_jump(cpustate,selector,address,1,0);
+ }
+ else
+ {
+ cpustate->sreg[CS].selector = selector;
+ cpustate->performed_intersegment_jump = 1;
+ i386_load_segment_descriptor(cpustate, CS );
+ cpustate->eip = address;
+ CHANGE_PC(cpustate,cpustate->eip);
+ }
+ }
+ }
+ break;
+ case 6: /* PUSH Rm16 */
+ {
+ UINT16 value;
+ if( modrm >= 0xc0 ) {
+ value = LOAD_RM16(modrm);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ value = READ16(cpustate,ea);
+ }
+ PUSH16(cpustate,value);
+ CYCLES(cpustate,CYCLES_PUSH_RM);
+ }
+ break;
+ case 7:
+ I386OP(invalid)(cpustate);
+ break;
+ default:
+ fatalerror("i386: groupFF_16 /%d unimplemented", (modrm >> 3) & 0x7);
+ break;
+ }
+}
+
+static void I386OP(group0F00_16)(i386_state *cpustate) // Opcode 0x0f 00
+{
+ UINT32 address, ea;
+ UINT8 modrm = FETCH(cpustate);
+ I386_SREG seg;
+ UINT8 result;
+
+ switch( (modrm >> 3) & 0x7 )
+ {
+ case 0: /* SLDT */
+ if ( PROTECTED_MODE && !V8086_MODE )
+ {
+ if( modrm >= 0xc0 ) {
+ address = LOAD_RM16(modrm);
+ STORE_RM16(address, cpustate->ldtr.segment);
+ CYCLES(cpustate,CYCLES_SLDT_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ WRITE16(cpustate, ea, cpustate->ldtr.segment);
+ CYCLES(cpustate,CYCLES_SLDT_MEM);
+ }
+ }
+ else
+ {
+ i386_trap(cpustate,6, 0, 0);
+ }
+ break;
+ case 1: /* STR */
+ if ( PROTECTED_MODE && !V8086_MODE )
+ {
+ if( modrm >= 0xc0 ) {
+ address = LOAD_RM16(modrm);
+ STORE_RM16(address, cpustate->task.segment);
+ CYCLES(cpustate,CYCLES_STR_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ WRITE16(cpustate, ea, cpustate->task.segment);
+ CYCLES(cpustate,CYCLES_STR_MEM);
+ }
+ }
+ else
+ {
+ i386_trap(cpustate,6, 0, 0);
+ }
+ break;
+ case 2: /* LLDT */
+ if ( PROTECTED_MODE && !V8086_MODE )
+ {
+ if( modrm >= 0xc0 ) {
+ address = LOAD_RM16(modrm);
+ cpustate->ldtr.segment = address;
+ CYCLES(cpustate,CYCLES_LLDT_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ cpustate->ldtr.segment = READ16(cpustate,ea);
+ CYCLES(cpustate,CYCLES_LLDT_MEM);
+ }
+ memset(&seg, 0, sizeof(seg));
+ seg.selector = cpustate->ldtr.segment;
+ i386_load_protected_mode_segment(cpustate,&seg);
+ cpustate->ldtr.limit = seg.limit;
+ cpustate->ldtr.base = seg.base;
+ cpustate->ldtr.flags = seg.flags;
+ }
+ else
+ {
+ i386_trap(cpustate,6, 0, 0);
+ }
+ break;
+
+ case 3: /* LTR */
+ if ( PROTECTED_MODE && !V8086_MODE )
+ {
+ if( modrm >= 0xc0 ) {
+ address = LOAD_RM16(modrm);
+ cpustate->task.segment = address;
+ CYCLES(cpustate,CYCLES_LTR_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ cpustate->task.segment = READ16(cpustate,ea);
+ CYCLES(cpustate,CYCLES_LTR_MEM);
+ }
+ memset(&seg, 0, sizeof(seg));
+ seg.selector = cpustate->task.segment;
+ i386_load_protected_mode_segment(cpustate,&seg);
+ cpustate->task.limit = seg.limit;
+ cpustate->task.base = seg.base;
+ cpustate->task.flags = seg.flags;
+ }
+ else
+ {
+ i386_trap(cpustate,6, 0, 0);
+ }
+ break;
+
+ case 4: /* VERR */
+ if ( PROTECTED_MODE && !V8086_MODE )
+ {
+ result = 1;
+ if( modrm >= 0xc0 ) {
+ address = LOAD_RM16(modrm);
+ CYCLES(cpustate,CYCLES_VERR_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ address = READ16(cpustate,ea);
+ CYCLES(cpustate,CYCLES_VERR_MEM);
+ }
+ memset(&seg, 0, sizeof(seg));
+ seg.selector = address;
+ i386_load_protected_mode_segment(cpustate,&seg);
+ // check if the segment is within the bounds of the GDT or LDT
+ if(seg.selector & 0x04)
+ { // LDT
+ if((seg.selector & 0xf8) > cpustate->ldtr.limit)
+ {
+ result = 0;
+ }
+ }
+ else
+ { // GDT
+ if((seg.selector & 0xf8) > cpustate->gdtr.limit)
+ {
+ result = 0;
+ }
+ }
+ // check if the segment is a code or data segment (not a special segment type, like a TSS, gate, LDT...)
+ if(!(seg.flags & 0x10))
+ result = 0;
+ // check that the segment is readable
+ if(seg.flags & 0x10) // is code or data segment
+ {
+ if(seg.flags & 0x08) // is code segment, so check if it's readable
+ {
+ if(!(seg.flags & 0x02))
+ {
+ result = 0;
+ }
+ else
+ { // check if conforming, these are always readable, regardless of privilege
+ if(!(seg.flags & 0x04))
+ {
+ // if not conforming, then we must check privilege levels (TODO: current privilege level check)
+ if(((seg.flags >> 5) & 0x03) < (address & 0x03))
+ result = 0;
+ }
+ }
+ }
+ }
+ // check that the descriptor privilege is greater or equal to the selector's privilege level and the current privilege (TODO)
+ SetZF(result);
+ }
+ else
+ {
+ i386_trap(cpustate,6, 0, 0);
+ logerror("i386: VERR: Exception - Running in real mode or virtual 8086 mode.\n");
+ }
+ break;
+
+ case 5: /* VERW */
+ if ( PROTECTED_MODE && !V8086_MODE )
+ {
+ result = 1;
+ if( modrm >= 0xc0 ) {
+ address = LOAD_RM16(modrm);
+ CYCLES(cpustate,CYCLES_VERW_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ address = READ16(cpustate,ea);
+ CYCLES(cpustate,CYCLES_VERW_MEM);
+ }
+ memset(&seg, 0, sizeof(seg));
+ seg.selector = address;
+ i386_load_protected_mode_segment(cpustate,&seg);
+ // check if the segment is within the bounds of the GDT or LDT
+ if(seg.selector & 0x04)
+ { // LDT
+ if((seg.selector & 0xf8) > cpustate->ldtr.limit)
+ {
+ result = 0;
+ }
+ }
+ else
+ { // GDT
+ if((seg.selector & 0xf8) > cpustate->gdtr.limit)
+ {
+ result = 0;
+ }
+ }
+ // check if the segment is a code or data segment (not a special segment type, like a TSS, gate, LDT...)
+ if(!(seg.flags & 0x10))
+ result = 0;
+ // check that the segment is writable
+ if(seg.flags & 0x10) // is code or data segment
+ {
+ if(seg.flags & 0x08) // is code segment (and thus, not writable)
+ {
+ result = 0;
+ }
+ else
+ { // is data segment
+ if(!(seg.flags & 0x02))
+ result = 0;
+ }
+ }
+ // check that the descriptor privilege is greater or equal to the selector's privilege level and the current privilege (TODO)
+ if(((seg.flags >> 5) & 0x03) < (address & 0x03))
+ result = 0;
+ SetZF(result);
+ }
+ else
+ {
+ i386_trap(cpustate,6, 0, 0);
+ logerror("i386: VERW: Exception - Running in real mode or virtual 8086 mode.\n");
+ }
+ break;
+
+ default:
+ fatalerror("i386: group0F00_16 /%d unimplemented", (modrm >> 3) & 0x7);
+ break;
+ }
+}
+
+static void I386OP(group0F01_16)(i386_state *cpustate) // Opcode 0x0f 01
+{
+ UINT8 modrm = FETCH(cpustate);
+ UINT16 address;
+ UINT32 ea;
+
+ switch( (modrm >> 3) & 0x7 )
+ {
+ case 0: /* SGDT */
+ {
+ if( modrm >= 0xc0 ) {
+ address = LOAD_RM16(modrm);
+ ea = i386_translate(cpustate, CS, address );
+ } else {
+ ea = GetEA(cpustate,modrm);
+ }
+ WRITE16(cpustate,ea, cpustate->gdtr.limit);
+ WRITE32(cpustate,ea + 2, cpustate->gdtr.base & 0xffffff);
+ CYCLES(cpustate,CYCLES_SGDT);
+ break;
+ }
+ case 1: /* SIDT */
+ {
+ if (modrm >= 0xc0)
+ {
+ address = LOAD_RM16(modrm);
+ ea = i386_translate(cpustate, CS, address );
+ }
+ else
+ {
+ ea = GetEA(cpustate,modrm);
+ }
+ WRITE16(cpustate,ea, cpustate->idtr.limit);
+ WRITE32(cpustate,ea + 2, cpustate->idtr.base & 0xffffff);
+ CYCLES(cpustate,CYCLES_SIDT);
+ break;
+ }
+ case 2: /* LGDT */
+ {
+ if( modrm >= 0xc0 ) {
+ address = LOAD_RM16(modrm);
+ ea = i386_translate(cpustate, CS, address );
+ } else {
+ ea = GetEA(cpustate,modrm);
+ }
+ cpustate->gdtr.limit = READ16(cpustate,ea);
+ cpustate->gdtr.base = READ32(cpustate,ea + 2) & 0xffffff;
+ CYCLES(cpustate,CYCLES_LGDT);
+ break;
+ }
+ case 3: /* LIDT */
+ {
+ if( modrm >= 0xc0 ) {
+ address = LOAD_RM16(modrm);
+ ea = i386_translate(cpustate, CS, address );
+ } else {
+ ea = GetEA(cpustate,modrm);
+ }
+ cpustate->idtr.limit = READ16(cpustate,ea);
+ cpustate->idtr.base = READ32(cpustate,ea + 2) & 0xffffff;
+ CYCLES(cpustate,CYCLES_LIDT);
+ break;
+ }
+ case 4: /* SMSW */
+ {
+ if( modrm >= 0xc0 ) {
+ STORE_RM16(modrm, cpustate->cr[0]);
+ CYCLES(cpustate,CYCLES_SMSW_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ WRITE16(cpustate,ea, cpustate->cr[0]);
+ CYCLES(cpustate,CYCLES_SMSW_MEM);
+ }
+ break;
+ }
+ case 6: /* LMSW */
+ {
+ // TODO: Check for protection fault
+ UINT16 b;
+ if( modrm >= 0xc0 ) {
+ b = LOAD_RM16(modrm);
+ CYCLES(cpustate,CYCLES_LMSW_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ CYCLES(cpustate,CYCLES_LMSW_MEM);
+ b = READ16(cpustate,ea);
+ }
+ if(PROTECTED_MODE)
+ b |= 0x0001; // cannot return to real mode using this instruction.
+ cpustate->cr[0] &= ~0x0000ffff;
+ cpustate->cr[0] |= b & 0x0000ffff;
+ break;
+ }
+ default:
+ fatalerror("i386: unimplemented opcode 0x0f 01 /%d at %08X", (modrm >> 3) & 0x7, cpustate->eip - 2);
+ break;
+ }
+}
+
+static void I386OP(group0FBA_16)(i386_state *cpustate) // Opcode 0x0f ba
+{
+ UINT8 modrm = FETCH(cpustate);
+
+ switch( (modrm >> 3) & 0x7 )
+ {
+ case 4: /* BT Rm16, i8 */
+ if( modrm >= 0xc0 ) {
+ UINT16 dst = LOAD_RM16(modrm);
+ UINT8 bit = FETCH(cpustate);
+
+ if( dst & (1 << bit) )
+ cpustate->CF = 1;
+ else
+ cpustate->CF = 0;
+
+ CYCLES(cpustate,CYCLES_BT_IMM_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT16 dst = READ16(cpustate,ea);
+ UINT8 bit = FETCH(cpustate);
+
+ if( dst & (1 << bit) )
+ cpustate->CF = 1;
+ else
+ cpustate->CF = 0;
+
+ CYCLES(cpustate,CYCLES_BT_IMM_MEM);
+ }
+ break;
+ case 5: /* BTS Rm16, i8 */
+ if( modrm >= 0xc0 ) {
+ UINT16 dst = LOAD_RM16(modrm);
+ UINT8 bit = FETCH(cpustate);
+
+ if( dst & (1 << bit) )
+ cpustate->CF = 1;
+ else
+ cpustate->CF = 0;
+ dst |= (1 << bit);
+
+ STORE_RM16(modrm, dst);
+ CYCLES(cpustate,CYCLES_BTS_IMM_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT16 dst = READ16(cpustate,ea);
+ UINT8 bit = FETCH(cpustate);
+
+ if( dst & (1 << bit) )
+ cpustate->CF = 1;
+ else
+ cpustate->CF = 0;
+ dst |= (1 << bit);
+
+ WRITE16(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_BTS_IMM_MEM);
+ }
+ break;
+ case 6: /* BTR Rm16, i8 */
+ if( modrm >= 0xc0 ) {
+ UINT16 dst = LOAD_RM16(modrm);
+ UINT8 bit = FETCH(cpustate);
+
+ if( dst & (1 << bit) )
+ cpustate->CF = 1;
+ else
+ cpustate->CF = 0;
+ dst &= ~(1 << bit);
+
+ STORE_RM16(modrm, dst);
+ CYCLES(cpustate,CYCLES_BTR_IMM_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT16 dst = READ16(cpustate,ea);
+ UINT8 bit = FETCH(cpustate);
+
+ if( dst & (1 << bit) )
+ cpustate->CF = 1;
+ else
+ cpustate->CF = 0;
+ dst &= ~(1 << bit);
+
+ WRITE16(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_BTR_IMM_MEM);
+ }
+ break;
+ case 7: /* BTC Rm16, i8 */
+ if( modrm >= 0xc0 ) {
+ UINT16 dst = LOAD_RM16(modrm);
+ UINT8 bit = FETCH(cpustate);
+
+ if( dst & (1 << bit) )
+ cpustate->CF = 1;
+ else
+ cpustate->CF = 0;
+ dst ^= (1 << bit);
+
+ STORE_RM16(modrm, dst);
+ CYCLES(cpustate,CYCLES_BTC_IMM_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT16 dst = READ16(cpustate,ea);
+ UINT8 bit = FETCH(cpustate);
+
+ if( dst & (1 << bit) )
+ cpustate->CF = 1;
+ else
+ cpustate->CF = 0;
+ dst ^= (1 << bit);
+
+ WRITE16(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_BTC_IMM_MEM);
+ }
+ break;
+ default:
+ fatalerror("i386: group0FBA_16 /%d unknown", (modrm >> 3) & 0x7);
+ break;
+ }
+}
+
+static void I386OP(lar_r16_rm16)(i386_state *cpustate) // Opcode 0x0f 0x02
+{
+ UINT8 modrm = FETCH(cpustate);
+ I386_SREG seg;
+ UINT8 type;
+
+ if(PROTECTED_MODE && !V8086_MODE)
+ {
+ memset(&seg,0,sizeof(seg));
+ if(modrm >= 0xc0)
+ {
+ seg.selector = LOAD_RM16(modrm);
+ CYCLES(cpustate,CYCLES_LAR_REG);
+ }
+ else
+ {
+ UINT32 ea = GetEA(cpustate,modrm);
+ seg.selector = READ16(cpustate,ea);
+ CYCLES(cpustate,CYCLES_LAR_MEM);
+ }
+ if(seg.selector == 0)
+ {
+ SetZF(0); // not a valid segment
+ logerror("i386: LAR: Selector %04x is invalid type.\n",seg.selector);
+ }
+ else
+ {
+ i386_load_protected_mode_segment(cpustate,&seg);
+ if(!(seg.flags & 0x10)) // special segment
+ {
+ // check for invalid segment types
+ type = seg.flags & 0x000f;
+ if(type == 0x00 || type == 0x08 || type == 0x0a || type == 0x0d)
+ {
+ SetZF(0); // invalid segment type
+ }
+ else
+ {
+ // TODO: check current privilege level
+ STORE_REG16(modrm,(seg.flags << 8) & 0xff00);
+ SetZF(1);
+ }
+ }
+ else
+ { // data or code segment (both are valid for LAR)
+ // TODO: check current privilege level
+ STORE_REG16(modrm,(seg.flags << 8) & 0xff00);
+ SetZF(1);
+ }
+ }
+ }
+ else
+ {
+ // illegal opcode
+ i386_trap(cpustate,6,0, 0);
+ logerror("i386: LAR: Exception - running in real mode or virtual 8086 mode.\n");
+ }
+}
+
+static void I386OP(lsl_r16_rm16)(i386_state *cpustate) // Opcode 0x0f 0x03
+{
+ UINT8 modrm = FETCH(cpustate);
+ UINT32 limit;
+ I386_SREG seg;
+
+ if(PROTECTED_MODE)
+ {
+ memset(&seg, 0, sizeof(seg));
+ if(modrm >= 0xc0)
+ {
+ seg.selector = LOAD_RM16(modrm);
+ }
+ else
+ {
+ UINT32 ea = GetEA(cpustate,modrm);
+ seg.selector = READ16(cpustate,ea);
+ }
+ if(seg.selector == 0)
+ {
+ SetZF(0); // not a valid segment
+ }
+ else
+ {
+ // TODO: check segment type
+ i386_load_protected_mode_segment(cpustate,&seg);
+ limit = seg.limit;
+ STORE_REG16(modrm,limit & 0x0000ffff);
+ SetZF(1);
+ }
+ }
+ else
+ i386_trap(cpustate,6, 0, 0);
+}
+
+static void I386OP(bound_r16_m16_m16)(i386_state *cpustate) // Opcode 0x62
+{
+ UINT8 modrm;
+ INT16 val, low, high;
+
+ modrm = FETCH(cpustate);
+
+ if (modrm >= 0xc0)
+ {
+ low = high = LOAD_RM16(modrm);
+ }
+ else
+ {
+ UINT32 ea = GetEA(cpustate,modrm);
+ low = READ16(cpustate,ea + 0);
+ high = READ16(cpustate,ea + 2);
+ }
+ val = LOAD_REG16(modrm);
+
+ if ((val < low) || (val > high))
+ {
+ CYCLES(cpustate,CYCLES_BOUND_OUT_RANGE);
+ i386_trap(cpustate,5, 0, 0);
+ }
+ else
+ {
+ CYCLES(cpustate,CYCLES_BOUND_IN_RANGE);
+ }
+}
+
+static void I386OP(retf16)(i386_state *cpustate) // Opcode 0xcb
+{
+ if(PROTECTED_MODE && !V8086_MODE)
+ {
+ i386_protected_mode_retf(cpustate,0,0);
+ }
+ else
+ {
+ cpustate->eip = POP16(cpustate);
+ cpustate->sreg[CS].selector = POP16(cpustate);
+ i386_load_segment_descriptor(cpustate, CS );
+ CHANGE_PC(cpustate,cpustate->eip);
+ }
+
+ CYCLES(cpustate,CYCLES_RET_INTERSEG);
+}
+
+static void I386OP(retf_i16)(i386_state *cpustate) // Opcode 0xca
+{
+ UINT16 count = FETCH16(cpustate);
+
+ if(PROTECTED_MODE && !V8086_MODE)
+ {
+ i386_protected_mode_retf(cpustate,count,0);
+ }
+ else
+ {
+ cpustate->eip = POP16(cpustate);
+ cpustate->sreg[CS].selector = POP16(cpustate);
+ i386_load_segment_descriptor(cpustate, CS );
+ CHANGE_PC(cpustate,cpustate->eip);
+ REG16(SP) += count;
+ }
+
+ CYCLES(cpustate,CYCLES_RET_IMM_INTERSEG);
+}
+
+static void I386OP(xlat16)(i386_state *cpustate) // Opcode 0xd7
+{
+ UINT32 ea;
+ if( cpustate->segment_prefix ) {
+ ea = i386_translate(cpustate, cpustate->segment_override, REG16(BX) + REG8(AL) );
+ } else {
+ ea = i386_translate(cpustate, DS, REG16(BX) + REG8(AL) );
+ }
+ REG8(AL) = READ8(cpustate,ea);
+ CYCLES(cpustate,CYCLES_XLAT);
+}
+
+static void I386OP(load_far_pointer16)(i386_state *cpustate, int s)
+{
+ UINT8 modrm = FETCH(cpustate);
+
+ if( modrm >= 0xc0 ) {
+ fatalerror("i386: load_far_pointer16 NYI");
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ STORE_REG16(modrm, READ16(cpustate,ea + 0));
+ cpustate->sreg[s].selector = READ16(cpustate,ea + 2);
+ i386_load_segment_descriptor(cpustate, s );
+ }
+}
+
+static void I386OP(lds16)(i386_state *cpustate) // Opcode 0xc5
+{
+ I386OP(load_far_pointer16)(cpustate, DS);
+ CYCLES(cpustate,CYCLES_LDS);
+}
+
+static void I386OP(lss16)(i386_state *cpustate) // Opcode 0x0f 0xb2
+{
+ I386OP(load_far_pointer16)(cpustate, SS);
+ CYCLES(cpustate,CYCLES_LSS);
+}
+
+static void I386OP(les16)(i386_state *cpustate) // Opcode 0xc4
+{
+ I386OP(load_far_pointer16)(cpustate, ES);
+ CYCLES(cpustate,CYCLES_LES);
+}
+
+static void I386OP(lfs16)(i386_state *cpustate) // Opcode 0x0f 0xb4
+{
+ I386OP(load_far_pointer16)(cpustate, FS);
+ CYCLES(cpustate,CYCLES_LFS);
+}
+
+static void I386OP(lgs16)(i386_state *cpustate) // Opcode 0x0f 0xb5
+{
+ I386OP(load_far_pointer16)(cpustate, GS);
+ CYCLES(cpustate,CYCLES_LGS);
+}
+
diff --git a/trunk/src/emu/cpu/i386/i386op32.c b/trunk/src/emu/cpu/i386/i386op32.c
new file mode 100644
index 00000000000..69ef2d4fd31
--- /dev/null
+++ b/trunk/src/emu/cpu/i386/i386op32.c
@@ -0,0 +1,3300 @@
+static UINT32 I386OP(shift_rotate32)(i386_state *cpustate, UINT8 modrm, UINT32 value, UINT8 shift)
+{
+ UINT32 dst, src;
+ dst = value;
+ src = value;
+
+ if( shift == 0 ) {
+ CYCLES_RM(cpustate,modrm, 3, 7);
+ } else if( shift == 1 ) {
+
+ switch( (modrm >> 3) & 0x7 )
+ {
+ case 0: /* ROL rm32, 1 */
+ cpustate->CF = (src & 0x80000000) ? 1 : 0;
+ dst = (src << 1) + cpustate->CF;
+ cpustate->OF = ((src ^ dst) & 0x80000000) ? 1 : 0;
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
+ break;
+ case 1: /* ROR rm32, 1 */
+ cpustate->CF = (src & 0x1) ? 1 : 0;
+ dst = (cpustate->CF << 31) | (src >> 1);
+ cpustate->OF = ((src ^ dst) & 0x80000000) ? 1 : 0;
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
+ break;
+ case 2: /* RCL rm32, 1 */
+ dst = (src << 1) + cpustate->CF;
+ cpustate->CF = (src & 0x80000000) ? 1 : 0;
+ cpustate->OF = ((src ^ dst) & 0x80000000) ? 1 : 0;
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
+ break;
+ case 3: /* RCR rm32, 1 */
+ dst = (cpustate->CF << 31) | (src >> 1);
+ cpustate->CF = src & 0x1;
+ cpustate->OF = ((src ^ dst) & 0x80000000) ? 1 : 0;
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
+ break;
+ case 4: /* SHL/SAL rm32, 1 */
+ case 6:
+ dst = src << 1;
+ cpustate->CF = (src & 0x80000000) ? 1 : 0;
+ cpustate->OF = (((cpustate->CF << 31) ^ dst) & 0x80000000) ? 1 : 0;
+ SetSZPF32(dst);
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
+ break;
+ case 5: /* SHR rm32, 1 */
+ dst = src >> 1;
+ cpustate->CF = src & 0x1;
+ cpustate->OF = (src & 0x80000000) ? 1 : 0;
+ SetSZPF32(dst);
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
+ break;
+ case 7: /* SAR rm32, 1 */
+ dst = (INT32)(src) >> 1;
+ cpustate->CF = src & 0x1;
+ cpustate->OF = 0;
+ SetSZPF32(dst);
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
+ break;
+ }
+
+ } else {
+
+ switch( (modrm >> 3) & 0x7 )
+ {
+ case 0: /* ROL rm32, i8 */
+ dst = ((src & ((UINT32)0xffffffff >> shift)) << shift) |
+ ((src & ((UINT32)0xffffffff << (32-shift))) >> (32-shift));
+ cpustate->CF = (src >> (32-shift)) & 0x1;
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
+ break;
+ case 1: /* ROR rm32, i8 */
+ dst = ((src & ((UINT32)0xffffffff << shift)) >> shift) |
+ ((src & ((UINT32)0xffffffff >> (32-shift))) << (32-shift));
+ cpustate->CF = (src >> (shift-1)) & 0x1;
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
+ break;
+ case 2: /* RCL rm32, i8 */
+ dst = ((src & ((UINT32)0xffffffff >> shift)) << shift) |
+ ((src & ((UINT32)0xffffffff << (33-shift))) >> (33-shift)) |
+ (cpustate->CF << (shift-1));
+ cpustate->CF = (src >> (32-shift)) & 0x1;
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
+ break;
+ case 3: /* RCR rm32, i8 */
+ dst = ((src & ((UINT32)0xffffffff << shift)) >> shift) |
+ ((src & ((UINT32)0xffffffff >> (32-shift))) << (33-shift)) |
+ (cpustate->CF << (32-shift));
+ cpustate->CF = (src >> (shift-1)) & 0x1;
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
+ break;
+ case 4: /* SHL/SAL rm32, i8 */
+ case 6:
+ dst = src << shift;
+ cpustate->CF = (src & (1 << (32-shift))) ? 1 : 0;
+ SetSZPF32(dst);
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
+ break;
+ case 5: /* SHR rm32, i8 */
+ dst = src >> shift;
+ cpustate->CF = (src & (1 << (shift-1))) ? 1 : 0;
+ SetSZPF32(dst);
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
+ break;
+ case 7: /* SAR rm32, i8 */
+ dst = (INT32)src >> shift;
+ cpustate->CF = (src & (1 << (shift-1))) ? 1 : 0;
+ SetSZPF32(dst);
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
+ break;
+ }
+
+ }
+ return dst;
+}
+
+
+
+static void I386OP(adc_rm32_r32)(i386_state *cpustate) // Opcode 0x11
+{
+ UINT32 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_REG32(modrm);
+ dst = LOAD_RM32(modrm);
+ dst = ADC32(cpustate, dst, src, cpustate->CF);
+ STORE_RM32(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = LOAD_REG32(modrm);
+ dst = READ32(cpustate,ea);
+ dst = ADC32(cpustate, dst, src, cpustate->CF);
+ WRITE32(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+}
+
+static void I386OP(adc_r32_rm32)(i386_state *cpustate) // Opcode 0x13
+{
+ UINT32 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_RM32(modrm);
+ dst = LOAD_REG32(modrm);
+ dst = ADC32(cpustate, dst, src, cpustate->CF);
+ STORE_REG32(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = READ32(cpustate,ea);
+ dst = LOAD_REG32(modrm);
+ dst = ADC32(cpustate, dst, src, cpustate->CF);
+ STORE_REG32(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_MEM_REG);
+ }
+}
+
+static void I386OP(adc_eax_i32)(i386_state *cpustate) // Opcode 0x15
+{
+ UINT32 src, dst;
+ src = FETCH32(cpustate);
+ dst = REG32(EAX);
+ dst = ADC32(cpustate, dst, src, cpustate->CF);
+ REG32(EAX) = dst;
+ CYCLES(cpustate,CYCLES_ALU_IMM_ACC);
+}
+
+static void I386OP(add_rm32_r32)(i386_state *cpustate) // Opcode 0x01
+{
+ UINT32 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_REG32(modrm);
+ dst = LOAD_RM32(modrm);
+ dst = ADD32(cpustate,dst, src);
+ STORE_RM32(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = LOAD_REG32(modrm);
+ dst = READ32(cpustate,ea);
+ dst = ADD32(cpustate,dst, src);
+ WRITE32(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+}
+
+static void I386OP(add_r32_rm32)(i386_state *cpustate) // Opcode 0x03
+{
+ UINT32 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_RM32(modrm);
+ dst = LOAD_REG32(modrm);
+ dst = ADD32(cpustate,dst, src);
+ STORE_REG32(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = READ32(cpustate,ea);
+ dst = LOAD_REG32(modrm);
+ dst = ADD32(cpustate,dst, src);
+ STORE_REG32(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_MEM_REG);
+ }
+}
+
+static void I386OP(add_eax_i32)(i386_state *cpustate) // Opcode 0x05
+{
+ UINT32 src, dst;
+ src = FETCH32(cpustate);
+ dst = REG32(EAX);
+ dst = ADD32(cpustate,dst, src);
+ REG32(EAX) = dst;
+ CYCLES(cpustate,CYCLES_ALU_IMM_ACC);
+}
+
+static void I386OP(and_rm32_r32)(i386_state *cpustate) // Opcode 0x21
+{
+ UINT32 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_REG32(modrm);
+ dst = LOAD_RM32(modrm);
+ dst = AND32(cpustate,dst, src);
+ STORE_RM32(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = LOAD_REG32(modrm);
+ dst = READ32(cpustate,ea);
+ dst = AND32(cpustate,dst, src);
+ WRITE32(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+}
+
+static void I386OP(and_r32_rm32)(i386_state *cpustate) // Opcode 0x23
+{
+ UINT32 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_RM32(modrm);
+ dst = LOAD_REG32(modrm);
+ dst = AND32(cpustate,dst, src);
+ STORE_REG32(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = READ32(cpustate,ea);
+ dst = LOAD_REG32(modrm);
+ dst = AND32(cpustate,dst, src);
+ STORE_REG32(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_MEM_REG);
+ }
+}
+
+static void I386OP(and_eax_i32)(i386_state *cpustate) // Opcode 0x25
+{
+ UINT32 src, dst;
+ src = FETCH32(cpustate);
+ dst = REG32(EAX);
+ dst = AND32(cpustate,dst, src);
+ REG32(EAX) = dst;
+ CYCLES(cpustate,CYCLES_ALU_IMM_ACC);
+}
+
+static void I386OP(bsf_r32_rm32)(i386_state *cpustate) // Opcode 0x0f bc
+{
+ UINT32 src, dst, temp;
+ UINT8 modrm = FETCH(cpustate);
+
+ if( modrm >= 0xc0 ) {
+ src = LOAD_RM32(modrm);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = READ32(cpustate,ea);
+ }
+
+ dst = 0;
+
+ if( src == 0 ) {
+ cpustate->ZF = 1;
+ } else {
+ cpustate->ZF = 0;
+ temp = 0;
+ while( (src & (1 << temp)) == 0 ) {
+ temp++;
+ dst = temp;
+ CYCLES(cpustate,CYCLES_BSF);
+ }
+ }
+ CYCLES(cpustate,CYCLES_BSF_BASE);
+ STORE_REG32(modrm, dst);
+}
+
+static void I386OP(bsr_r32_rm32)(i386_state *cpustate) // Opcode 0x0f bd
+{
+ UINT32 src, dst, temp;
+ UINT8 modrm = FETCH(cpustate);
+
+ if( modrm >= 0xc0 ) {
+ src = LOAD_RM32(modrm);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = READ32(cpustate,ea);
+ }
+
+ dst = 0;
+
+ if( src == 0 ) {
+ cpustate->ZF = 1;
+ } else {
+ cpustate->ZF = 0;
+ dst = temp = 31;
+ while( (src & (1 << temp)) == 0 ) {
+ temp--;
+ dst = temp;
+ CYCLES(cpustate,CYCLES_BSR);
+ }
+ }
+ CYCLES(cpustate,CYCLES_BSR_BASE);
+ STORE_REG32(modrm, dst);
+}
+
+static void I386OP(bt_rm32_r32)(i386_state *cpustate) // Opcode 0x0f a3
+{
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ UINT32 dst = LOAD_RM32(modrm);
+ UINT32 bit = LOAD_REG32(modrm);
+
+ if( dst & (1 << bit) )
+ cpustate->CF = 1;
+ else
+ cpustate->CF = 0;
+
+ CYCLES(cpustate,CYCLES_BT_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT32 dst = READ32(cpustate,ea);
+ UINT32 bit = LOAD_REG32(modrm);
+
+ if( dst & (1 << bit) )
+ cpustate->CF = 1;
+ else
+ cpustate->CF = 0;
+
+ CYCLES(cpustate,CYCLES_BT_REG_MEM);
+ }
+}
+
+static void I386OP(btc_rm32_r32)(i386_state *cpustate) // Opcode 0x0f bb
+{
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ UINT32 dst = LOAD_RM32(modrm);
+ UINT32 bit = LOAD_REG32(modrm);
+
+ if( dst & (1 << bit) )
+ cpustate->CF = 1;
+ else
+ cpustate->CF = 0;
+ dst ^= (1 << bit);
+
+ STORE_RM32(modrm, dst);
+ CYCLES(cpustate,CYCLES_BTC_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT32 dst = READ32(cpustate,ea);
+ UINT32 bit = LOAD_REG32(modrm);
+
+ if( dst & (1 << bit) )
+ cpustate->CF = 1;
+ else
+ cpustate->CF = 0;
+ dst ^= (1 << bit);
+
+ WRITE32(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_BTC_REG_MEM);
+ }
+}
+
+static void I386OP(btr_rm32_r32)(i386_state *cpustate) // Opcode 0x0f b3
+{
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ UINT32 dst = LOAD_RM32(modrm);
+ UINT32 bit = LOAD_REG32(modrm);
+
+ if( dst & (1 << bit) )
+ cpustate->CF = 1;
+ else
+ cpustate->CF = 0;
+ dst &= ~(1 << bit);
+
+ STORE_RM32(modrm, dst);
+ CYCLES(cpustate,CYCLES_BTR_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT32 dst = READ32(cpustate,ea);
+ UINT32 bit = LOAD_REG32(modrm);
+
+ if( dst & (1 << bit) )
+ cpustate->CF = 1;
+ else
+ cpustate->CF = 0;
+ dst &= ~(1 << bit);
+
+ WRITE32(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_BTR_REG_MEM);
+ }
+}
+
+static void I386OP(bts_rm32_r32)(i386_state *cpustate) // Opcode 0x0f ab
+{
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ UINT32 dst = LOAD_RM32(modrm);
+ UINT32 bit = LOAD_REG32(modrm);
+
+ if( dst & (1 << bit) )
+ cpustate->CF = 1;
+ else
+ cpustate->CF = 0;
+ dst |= (1 << bit);
+
+ STORE_RM32(modrm, dst);
+ CYCLES(cpustate,CYCLES_BTS_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT32 dst = READ32(cpustate,ea);
+ UINT32 bit = LOAD_REG32(modrm);
+
+ if( dst & (1 << bit) )
+ cpustate->CF = 1;
+ else
+ cpustate->CF = 0;
+ dst |= (1 << bit);
+
+ WRITE32(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_BTS_REG_MEM);
+ }
+}
+
+static void I386OP(call_abs32)(i386_state *cpustate) // Opcode 0x9a
+{
+ UINT32 offset = FETCH32(cpustate);
+ UINT16 ptr = FETCH16(cpustate);
+
+ if(PROTECTED_MODE && !V8086_MODE)
+ {
+ i386_protected_mode_call(cpustate,ptr,offset,0,1);
+ }
+ else
+ {
+ PUSH32(cpustate, cpustate->sreg[CS].selector );
+ PUSH32(cpustate, cpustate->eip );
+ cpustate->sreg[CS].selector = ptr;
+ cpustate->performed_intersegment_jump = 1;
+ cpustate->eip = offset;
+ i386_load_segment_descriptor(cpustate,CS);
+ }
+ CYCLES(cpustate,CYCLES_CALL_INTERSEG);
+ CHANGE_PC(cpustate,cpustate->eip);
+}
+
+static void I386OP(call_rel32)(i386_state *cpustate) // Opcode 0xe8
+{
+ INT32 disp = FETCH32(cpustate);
+
+ PUSH32(cpustate, cpustate->eip );
+ cpustate->eip += disp;
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_CALL); /* TODO: Timing = 7 + m */
+}
+
+static void I386OP(cdq)(i386_state *cpustate) // Opcode 0x99
+{
+ if( REG32(EAX) & 0x80000000 ) {
+ REG32(EDX) = 0xffffffff;
+ } else {
+ REG32(EDX) = 0x00000000;
+ }
+ CYCLES(cpustate,CYCLES_CWD);
+}
+
+static void I386OP(cmp_rm32_r32)(i386_state *cpustate) // Opcode 0x39
+{
+ UINT32 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_REG32(modrm);
+ dst = LOAD_RM32(modrm);
+ SUB32(cpustate,dst, src);
+ CYCLES(cpustate,CYCLES_CMP_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = LOAD_REG32(modrm);
+ dst = READ32(cpustate,ea);
+ SUB32(cpustate,dst, src);
+ CYCLES(cpustate,CYCLES_CMP_REG_MEM);
+ }
+}
+
+static void I386OP(cmp_r32_rm32)(i386_state *cpustate) // Opcode 0x3b
+{
+ UINT32 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_RM32(modrm);
+ dst = LOAD_REG32(modrm);
+ SUB32(cpustate,dst, src);
+ CYCLES(cpustate,CYCLES_CMP_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = READ32(cpustate,ea);
+ dst = LOAD_REG32(modrm);
+ SUB32(cpustate,dst, src);
+ CYCLES(cpustate,CYCLES_CMP_MEM_REG);
+ }
+}
+
+static void I386OP(cmp_eax_i32)(i386_state *cpustate) // Opcode 0x3d
+{
+ UINT32 src, dst;
+ src = FETCH32(cpustate);
+ dst = REG32(EAX);
+ SUB32(cpustate,dst, src);
+ CYCLES(cpustate,CYCLES_CMP_IMM_ACC);
+}
+
+static void I386OP(cmpsd)(i386_state *cpustate) // Opcode 0xa7
+{
+ UINT32 eas, ead, src, dst;
+ if( cpustate->segment_prefix ) {
+ eas = i386_translate(cpustate, cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI) );
+ } else {
+ eas = i386_translate(cpustate, DS, cpustate->address_size ? REG32(ESI) : REG16(SI) );
+ }
+ ead = i386_translate(cpustate, ES, cpustate->address_size ? REG32(EDI) : REG16(DI) );
+ src = READ32(cpustate,eas);
+ dst = READ32(cpustate,ead);
+ SUB32(cpustate,dst, src);
+ BUMP_SI(cpustate,4);
+ BUMP_DI(cpustate,4);
+ CYCLES(cpustate,CYCLES_CMPS);
+}
+
+static void I386OP(cwde)(i386_state *cpustate) // Opcode 0x98
+{
+ REG32(EAX) = (INT32)((INT16)REG16(AX));
+ CYCLES(cpustate,CYCLES_CBW);
+}
+
+static void I386OP(dec_eax)(i386_state *cpustate) // Opcode 0x48
+{
+ REG32(EAX) = DEC32(cpustate, REG32(EAX) );
+ CYCLES(cpustate,CYCLES_DEC_REG);
+}
+
+static void I386OP(dec_ecx)(i386_state *cpustate) // Opcode 0x49
+{
+ REG32(ECX) = DEC32(cpustate, REG32(ECX) );
+ CYCLES(cpustate,CYCLES_DEC_REG);
+}
+
+static void I386OP(dec_edx)(i386_state *cpustate) // Opcode 0x4a
+{
+ REG32(EDX) = DEC32(cpustate, REG32(EDX) );
+ CYCLES(cpustate,CYCLES_DEC_REG);
+}
+
+static void I386OP(dec_ebx)(i386_state *cpustate) // Opcode 0x4b
+{
+ REG32(EBX) = DEC32(cpustate, REG32(EBX) );
+ CYCLES(cpustate,CYCLES_DEC_REG);
+}
+
+static void I386OP(dec_esp)(i386_state *cpustate) // Opcode 0x4c
+{
+ REG32(ESP) = DEC32(cpustate, REG32(ESP) );
+ CYCLES(cpustate,CYCLES_DEC_REG);
+}
+
+static void I386OP(dec_ebp)(i386_state *cpustate) // Opcode 0x4d
+{
+ REG32(EBP) = DEC32(cpustate, REG32(EBP) );
+ CYCLES(cpustate,CYCLES_DEC_REG);
+}
+
+static void I386OP(dec_esi)(i386_state *cpustate) // Opcode 0x4e
+{
+ REG32(ESI) = DEC32(cpustate, REG32(ESI) );
+ CYCLES(cpustate,CYCLES_DEC_REG);
+}
+
+static void I386OP(dec_edi)(i386_state *cpustate) // Opcode 0x4f
+{
+ REG32(EDI) = DEC32(cpustate, REG32(EDI) );
+ CYCLES(cpustate,CYCLES_DEC_REG);
+}
+
+static void I386OP(imul_r32_rm32)(i386_state *cpustate) // Opcode 0x0f af
+{
+ UINT8 modrm = FETCH(cpustate);
+ INT64 result;
+ INT64 src, dst;
+ if( modrm >= 0xc0 ) {
+ src = (INT64)(INT32)LOAD_RM32(modrm);
+ CYCLES(cpustate,CYCLES_IMUL32_REG_REG); /* TODO: Correct multiply timing */
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = (INT64)(INT32)READ32(cpustate,ea);
+ CYCLES(cpustate,CYCLES_IMUL32_REG_REG); /* TODO: Correct multiply timing */
+ }
+
+ dst = (INT64)(INT32)LOAD_REG32(modrm);
+ result = src * dst;
+
+ STORE_REG32(modrm, (UINT32)result);
+
+ cpustate->CF = cpustate->OF = !(result == (INT64)(INT32)result);
+}
+
+static void I386OP(imul_r32_rm32_i32)(i386_state *cpustate) // Opcode 0x69
+{
+ UINT8 modrm = FETCH(cpustate);
+ INT64 result;
+ INT64 src, dst;
+ if( modrm >= 0xc0 ) {
+ dst = (INT64)(INT32)LOAD_RM32(modrm);
+ CYCLES(cpustate,CYCLES_IMUL32_REG_IMM_REG); /* TODO: Correct multiply timing */
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ dst = (INT64)(INT32)READ32(cpustate,ea);
+ CYCLES(cpustate,CYCLES_IMUL32_MEM_IMM_REG); /* TODO: Correct multiply timing */
+ }
+
+ src = (INT64)(INT32)FETCH32(cpustate);
+ result = src * dst;
+
+ STORE_REG32(modrm, (UINT32)result);
+
+ cpustate->CF = cpustate->OF = !(result == (INT64)(INT32)result);
+}
+
+static void I386OP(imul_r32_rm32_i8)(i386_state *cpustate) // Opcode 0x6b
+{
+ UINT8 modrm = FETCH(cpustate);
+ INT64 result;
+ INT64 src, dst;
+ if( modrm >= 0xc0 ) {
+ dst = (INT64)(INT32)LOAD_RM32(modrm);
+ CYCLES(cpustate,CYCLES_IMUL32_REG_IMM_REG); /* TODO: Correct multiply timing */
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ dst = (INT64)(INT32)READ32(cpustate,ea);
+ CYCLES(cpustate,CYCLES_IMUL32_MEM_IMM_REG); /* TODO: Correct multiply timing */
+ }
+
+ src = (INT64)(INT8)FETCH(cpustate);
+ result = src * dst;
+
+ STORE_REG32(modrm, (UINT32)result);
+
+ cpustate->CF = cpustate->OF = !(result == (INT64)(INT32)result);
+}
+
+static void I386OP(in_eax_i8)(i386_state *cpustate) // Opcode 0xe5
+{
+ UINT16 port = FETCH(cpustate);
+ UINT32 data = READPORT32(cpustate, port);
+ REG32(EAX) = data;
+ CYCLES(cpustate,CYCLES_IN_VAR);
+}
+
+static void I386OP(in_eax_dx)(i386_state *cpustate) // Opcode 0xed
+{
+ UINT16 port = REG16(DX);
+ UINT32 data = READPORT32(cpustate, port);
+ REG32(EAX) = data;
+ CYCLES(cpustate,CYCLES_IN);
+}
+
+static void I386OP(inc_eax)(i386_state *cpustate) // Opcode 0x40
+{
+ REG32(EAX) = INC32(cpustate, REG32(EAX) );
+ CYCLES(cpustate,CYCLES_INC_REG);
+}
+
+static void I386OP(inc_ecx)(i386_state *cpustate) // Opcode 0x41
+{
+ REG32(ECX) = INC32(cpustate, REG32(ECX) );
+ CYCLES(cpustate,CYCLES_INC_REG);
+}
+
+static void I386OP(inc_edx)(i386_state *cpustate) // Opcode 0x42
+{
+ REG32(EDX) = INC32(cpustate, REG32(EDX) );
+ CYCLES(cpustate,CYCLES_INC_REG);
+}
+
+static void I386OP(inc_ebx)(i386_state *cpustate) // Opcode 0x43
+{
+ REG32(EBX) = INC32(cpustate, REG32(EBX) );
+ CYCLES(cpustate,CYCLES_INC_REG);
+}
+
+static void I386OP(inc_esp)(i386_state *cpustate) // Opcode 0x44
+{
+ REG32(ESP) = INC32(cpustate, REG32(ESP) );
+ CYCLES(cpustate,CYCLES_INC_REG);
+}
+
+static void I386OP(inc_ebp)(i386_state *cpustate) // Opcode 0x45
+{
+ REG32(EBP) = INC32(cpustate, REG32(EBP) );
+ CYCLES(cpustate,CYCLES_INC_REG);
+}
+
+static void I386OP(inc_esi)(i386_state *cpustate) // Opcode 0x46
+{
+ REG32(ESI) = INC32(cpustate, REG32(ESI) );
+ CYCLES(cpustate,CYCLES_INC_REG);
+}
+
+static void I386OP(inc_edi)(i386_state *cpustate) // Opcode 0x47
+{
+ REG32(EDI) = INC32(cpustate, REG32(EDI) );
+ CYCLES(cpustate,CYCLES_INC_REG);
+}
+
+static void I386OP(iret32)(i386_state *cpustate) // Opcode 0xcf
+{
+ if( PROTECTED_MODE )
+ {
+ i386_protected_mode_iret(cpustate,1);
+ }
+ else
+ {
+ /* TODO: #SS(0) exception */
+ /* TODO: #GP(0) exception */
+ cpustate->eip = POP32(cpustate);
+ cpustate->sreg[CS].selector = POP32(cpustate) & 0xffff;
+ set_flags(cpustate, POP32(cpustate) );
+ i386_load_segment_descriptor(cpustate,CS);
+ CHANGE_PC(cpustate,cpustate->eip);
+ }
+ CYCLES(cpustate,CYCLES_IRET);
+}
+
+static void I386OP(ja_rel32)(i386_state *cpustate) // Opcode 0x0f 87
+{
+ INT32 disp = FETCH32(cpustate);
+ if( cpustate->CF == 0 && cpustate->ZF == 0 ) {
+ cpustate->eip += disp;
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH);
+ }
+}
+
+static void I386OP(jbe_rel32)(i386_state *cpustate) // Opcode 0x0f 86
+{
+ INT32 disp = FETCH32(cpustate);
+ if( cpustate->CF != 0 || cpustate->ZF != 0 ) {
+ cpustate->eip += disp;
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH);
+ }
+}
+
+static void I386OP(jc_rel32)(i386_state *cpustate) // Opcode 0x0f 82
+{
+ INT32 disp = FETCH32(cpustate);
+ if( cpustate->CF != 0 ) {
+ cpustate->eip += disp;
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH);
+ }
+}
+
+static void I386OP(jg_rel32)(i386_state *cpustate) // Opcode 0x0f 8f
+{
+ INT32 disp = FETCH32(cpustate);
+ if( cpustate->ZF == 0 && (cpustate->SF == cpustate->OF) ) {
+ cpustate->eip += disp;
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH);
+ }
+}
+
+static void I386OP(jge_rel32)(i386_state *cpustate) // Opcode 0x0f 8d
+{
+ INT32 disp = FETCH32(cpustate);
+ if( (cpustate->SF == cpustate->OF) ) {
+ cpustate->eip += disp;
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH);
+ }
+}
+
+static void I386OP(jl_rel32)(i386_state *cpustate) // Opcode 0x0f 8c
+{
+ INT32 disp = FETCH32(cpustate);
+ if( (cpustate->SF != cpustate->OF) ) {
+ cpustate->eip += disp;
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH);
+ }
+}
+
+static void I386OP(jle_rel32)(i386_state *cpustate) // Opcode 0x0f 8e
+{
+ INT32 disp = FETCH32(cpustate);
+ if( cpustate->ZF != 0 || (cpustate->SF != cpustate->OF) ) {
+ cpustate->eip += disp;
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH);
+ }
+}
+
+static void I386OP(jnc_rel32)(i386_state *cpustate) // Opcode 0x0f 83
+{
+ INT32 disp = FETCH32(cpustate);
+ if( cpustate->CF == 0 ) {
+ cpustate->eip += disp;
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH);
+ }
+}
+
+static void I386OP(jno_rel32)(i386_state *cpustate) // Opcode 0x0f 81
+{
+ INT32 disp = FETCH32(cpustate);
+ if( cpustate->OF == 0 ) {
+ cpustate->eip += disp;
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH);
+ }
+}
+
+static void I386OP(jnp_rel32)(i386_state *cpustate) // Opcode 0x0f 8b
+{
+ INT32 disp = FETCH32(cpustate);
+ if( cpustate->PF == 0 ) {
+ cpustate->eip += disp;
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH);
+ }
+}
+
+static void I386OP(jns_rel32)(i386_state *cpustate) // Opcode 0x0f 89
+{
+ INT32 disp = FETCH32(cpustate);
+ if( cpustate->SF == 0 ) {
+ cpustate->eip += disp;
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH);
+ }
+}
+
+static void I386OP(jnz_rel32)(i386_state *cpustate) // Opcode 0x0f 85
+{
+ INT32 disp = FETCH32(cpustate);
+ if( cpustate->ZF == 0 ) {
+ cpustate->eip += disp;
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH);
+ }
+}
+
+static void I386OP(jo_rel32)(i386_state *cpustate) // Opcode 0x0f 80
+{
+ INT32 disp = FETCH32(cpustate);
+ if( cpustate->OF != 0 ) {
+ cpustate->eip += disp;
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH);
+ }
+}
+
+static void I386OP(jp_rel32)(i386_state *cpustate) // Opcode 0x0f 8a
+{
+ INT32 disp = FETCH32(cpustate);
+ if( cpustate->PF != 0 ) {
+ cpustate->eip += disp;
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH);
+ }
+}
+
+static void I386OP(js_rel32)(i386_state *cpustate) // Opcode 0x0f 88
+{
+ INT32 disp = FETCH32(cpustate);
+ if( cpustate->SF != 0 ) {
+ cpustate->eip += disp;
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH);
+ }
+}
+
+static void I386OP(jz_rel32)(i386_state *cpustate) // Opcode 0x0f 84
+{
+ INT32 disp = FETCH32(cpustate);
+ if( cpustate->ZF != 0 ) {
+ cpustate->eip += disp;
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_FULL_DISP_NOBRANCH);
+ }
+}
+
+static void I386OP(jcxz32)(i386_state *cpustate) // Opcode 0xe3
+{
+ INT8 disp = FETCH(cpustate);
+ if( REG32(ECX) == 0 ) {
+ cpustate->eip += disp;
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_JCXZ); /* TODO: Timing = 9 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCXZ_NOBRANCH);
+ }
+}
+
+static void I386OP(jmp_rel32)(i386_state *cpustate) // Opcode 0xe9
+{
+ UINT32 disp = FETCH32(cpustate);
+ /* TODO: Segment limit */
+ cpustate->eip += disp;
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_JMP); /* TODO: Timing = 7 + m */
+}
+
+static void I386OP(jmp_abs32)(i386_state *cpustate) // Opcode 0xea
+{
+ UINT32 address = FETCH32(cpustate);
+ UINT16 segment = FETCH16(cpustate);
+
+ if( PROTECTED_MODE && !V8086_MODE)
+ {
+ i386_protected_mode_jump(cpustate,segment,address,0,1);
+ }
+ else
+ {
+ cpustate->eip = address;
+ cpustate->sreg[CS].selector = segment;
+ cpustate->performed_intersegment_jump = 1;
+ i386_load_segment_descriptor(cpustate,CS);
+ CHANGE_PC(cpustate,cpustate->eip);
+ }
+ CYCLES(cpustate,CYCLES_JMP_INTERSEG);
+}
+
+static void I386OP(lea32)(i386_state *cpustate) // Opcode 0x8d
+{
+ UINT8 modrm = FETCH(cpustate);
+ UINT32 ea = GetNonTranslatedEA(cpustate,modrm);
+ if (!cpustate->address_size)
+ {
+ ea &= 0xffff;
+ }
+ STORE_REG32(modrm, ea);
+ CYCLES(cpustate,CYCLES_LEA);
+}
+
+static void I386OP(enter32)(i386_state *cpustate) // Opcode 0xc8
+{
+ UINT16 framesize = FETCH16(cpustate);
+ UINT8 level = FETCH(cpustate) % 32;
+ UINT8 x;
+ UINT32 frameptr;
+ PUSH32(cpustate,REG32(EBP));
+ if(!STACK_32BIT)
+ frameptr = REG16(SP);
+ else
+ frameptr = REG32(ESP);
+
+ if(level > 0)
+ {
+ for(x=1;x<level-1;x++)
+ {
+ REG32(EBP) -= 4;
+ PUSH32(cpustate,READ32(cpustate,REG32(EBP)));
+ }
+ PUSH32(cpustate,frameptr);
+ }
+ REG32(EBP) = frameptr;
+ if(!STACK_32BIT)
+ REG16(SP) -= framesize;
+ else
+ REG32(ESP) -= framesize;
+ CYCLES(cpustate,CYCLES_ENTER);
+}
+
+static void I386OP(leave32)(i386_state *cpustate) // Opcode 0xc9
+{
+ if(!STACK_32BIT)
+ REG16(SP) = REG16(BP);
+ else
+ REG32(ESP) = REG32(EBP);
+ REG32(EBP) = POP32(cpustate);
+ CYCLES(cpustate,CYCLES_LEAVE);
+}
+
+static void I386OP(lodsd)(i386_state *cpustate) // Opcode 0xad
+{
+ UINT32 eas;
+ if( cpustate->segment_prefix ) {
+ eas = i386_translate(cpustate, cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI) );
+ } else {
+ eas = i386_translate(cpustate, DS, cpustate->address_size ? REG32(ESI) : REG16(SI) );
+ }
+ REG32(EAX) = READ32(cpustate,eas);
+ BUMP_SI(cpustate,4);
+ CYCLES(cpustate,CYCLES_LODS);
+}
+
+static void I386OP(loop32)(i386_state *cpustate) // Opcode 0xe2
+{
+ INT8 disp = FETCH(cpustate);
+ INT32 reg = (cpustate->address_size)?--REG32(ECX):--REG16(CX);
+ if( reg != 0 ) {
+ cpustate->eip += disp;
+ CHANGE_PC(cpustate,cpustate->eip);
+ }
+ CYCLES(cpustate,CYCLES_LOOP); /* TODO: Timing = 11 + m */
+}
+
+static void I386OP(loopne32)(i386_state *cpustate) // Opcode 0xe0
+{
+ INT8 disp = FETCH(cpustate);
+ INT32 reg = (cpustate->address_size)?--REG32(ECX):--REG16(CX);
+ if( reg != 0 && cpustate->ZF == 0 ) {
+ cpustate->eip += disp;
+ CHANGE_PC(cpustate,cpustate->eip);
+ }
+ CYCLES(cpustate,CYCLES_LOOPNZ); /* TODO: Timing = 11 + m */
+}
+
+static void I386OP(loopz32)(i386_state *cpustate) // Opcode 0xe1
+{
+ INT8 disp = FETCH(cpustate);
+ INT32 reg = (cpustate->address_size)?--REG32(ECX):--REG16(CX);
+ if( reg != 0 && cpustate->ZF != 0 ) {
+ cpustate->eip += disp;
+ CHANGE_PC(cpustate,cpustate->eip);
+ }
+ CYCLES(cpustate,CYCLES_LOOPZ); /* TODO: Timing = 11 + m */
+}
+
+static void I386OP(mov_rm32_r32)(i386_state *cpustate) // Opcode 0x89
+{
+ UINT32 src;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_REG32(modrm);
+ STORE_RM32(modrm, src);
+ CYCLES(cpustate,CYCLES_MOV_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = LOAD_REG32(modrm);
+ WRITE32(cpustate,ea, src);
+ CYCLES(cpustate,CYCLES_MOV_REG_MEM);
+ }
+}
+
+static void I386OP(mov_r32_rm32)(i386_state *cpustate) // Opcode 0x8b
+{
+ UINT32 src;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_RM32(modrm);
+ STORE_REG32(modrm, src);
+ CYCLES(cpustate,CYCLES_MOV_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = READ32(cpustate,ea);
+ STORE_REG32(modrm, src);
+ CYCLES(cpustate,CYCLES_MOV_MEM_REG);
+ }
+}
+
+static void I386OP(mov_rm32_i32)(i386_state *cpustate) // Opcode 0xc7
+{
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ UINT32 value = FETCH32(cpustate);
+ STORE_RM32(modrm, value);
+ CYCLES(cpustate,CYCLES_MOV_IMM_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT32 value = FETCH32(cpustate);
+ WRITE32(cpustate,ea, value);
+ CYCLES(cpustate,CYCLES_MOV_IMM_MEM);
+ }
+}
+
+static void I386OP(mov_eax_m32)(i386_state *cpustate) // Opcode 0xa1
+{
+ UINT32 offset, ea;
+ if( cpustate->address_size ) {
+ offset = FETCH32(cpustate);
+ } else {
+ offset = FETCH16(cpustate);
+ }
+ if( cpustate->segment_prefix ) {
+ ea = i386_translate(cpustate, cpustate->segment_override, offset );
+ } else {
+ ea = i386_translate(cpustate, DS, offset );
+ }
+ REG32(EAX) = READ32(cpustate,ea);
+ CYCLES(cpustate,CYCLES_MOV_MEM_ACC);
+}
+
+static void I386OP(mov_m32_eax)(i386_state *cpustate) // Opcode 0xa3
+{
+ UINT32 offset, ea;
+ if( cpustate->address_size ) {
+ offset = FETCH32(cpustate);
+ } else {
+ offset = FETCH16(cpustate);
+ }
+ if( cpustate->segment_prefix ) {
+ ea = i386_translate(cpustate, cpustate->segment_override, offset );
+ } else {
+ ea = i386_translate(cpustate, DS, offset );
+ }
+ WRITE32(cpustate, ea, REG32(EAX) );
+ CYCLES(cpustate,CYCLES_MOV_ACC_MEM);
+}
+
+static void I386OP(mov_eax_i32)(i386_state *cpustate) // Opcode 0xb8
+{
+ REG32(EAX) = FETCH32(cpustate);
+ CYCLES(cpustate,CYCLES_MOV_IMM_REG);
+}
+
+static void I386OP(mov_ecx_i32)(i386_state *cpustate) // Opcode 0xb9
+{
+ REG32(ECX) = FETCH32(cpustate);
+ CYCLES(cpustate,CYCLES_MOV_IMM_REG);
+}
+
+static void I386OP(mov_edx_i32)(i386_state *cpustate) // Opcode 0xba
+{
+ REG32(EDX) = FETCH32(cpustate);
+ CYCLES(cpustate,CYCLES_MOV_IMM_REG);
+}
+
+static void I386OP(mov_ebx_i32)(i386_state *cpustate) // Opcode 0xbb
+{
+ REG32(EBX) = FETCH32(cpustate);
+ CYCLES(cpustate,CYCLES_MOV_IMM_REG);
+}
+
+static void I386OP(mov_esp_i32)(i386_state *cpustate) // Opcode 0xbc
+{
+ REG32(ESP) = FETCH32(cpustate);
+ CYCLES(cpustate,CYCLES_MOV_IMM_REG);
+}
+
+static void I386OP(mov_ebp_i32)(i386_state *cpustate) // Opcode 0xbd
+{
+ REG32(EBP) = FETCH32(cpustate);
+ CYCLES(cpustate,CYCLES_MOV_IMM_REG);
+}
+
+static void I386OP(mov_esi_i32)(i386_state *cpustate) // Opcode 0xbe
+{
+ REG32(ESI) = FETCH32(cpustate);
+ CYCLES(cpustate,CYCLES_MOV_IMM_REG);
+}
+
+static void I386OP(mov_edi_i32)(i386_state *cpustate) // Opcode 0xbf
+{
+ REG32(EDI) = FETCH32(cpustate);
+ CYCLES(cpustate,CYCLES_MOV_IMM_REG);
+}
+
+static void I386OP(movsd)(i386_state *cpustate) // Opcode 0xa5
+{
+ UINT32 eas, ead, v;
+ if( cpustate->segment_prefix ) {
+ eas = i386_translate(cpustate, cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI) );
+ } else {
+ eas = i386_translate(cpustate, DS, cpustate->address_size ? REG32(ESI) : REG16(SI) );
+ }
+ ead = i386_translate(cpustate, ES, cpustate->address_size ? REG32(EDI) : REG16(DI) );
+ v = READ32(cpustate,eas);
+ WRITE32(cpustate,ead, v);
+ BUMP_SI(cpustate,4);
+ BUMP_DI(cpustate,4);
+ CYCLES(cpustate,CYCLES_MOVS);
+}
+
+static void I386OP(movsx_r32_rm8)(i386_state *cpustate) // Opcode 0x0f be
+{
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ INT32 src = (INT8)LOAD_RM8(modrm);
+ STORE_REG32(modrm, src);
+ CYCLES(cpustate,CYCLES_MOVSX_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ INT32 src = (INT8)READ8(cpustate,ea);
+ STORE_REG32(modrm, src);
+ CYCLES(cpustate,CYCLES_MOVSX_MEM_REG);
+ }
+}
+
+static void I386OP(movsx_r32_rm16)(i386_state *cpustate) // Opcode 0x0f bf
+{
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ INT32 src = (INT16)LOAD_RM16(modrm);
+ STORE_REG32(modrm, src);
+ CYCLES(cpustate,CYCLES_MOVSX_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ INT32 src = (INT16)READ16(cpustate,ea);
+ STORE_REG32(modrm, src);
+ CYCLES(cpustate,CYCLES_MOVSX_MEM_REG);
+ }
+}
+
+static void I386OP(movzx_r32_rm8)(i386_state *cpustate) // Opcode 0x0f b6
+{
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ UINT32 src = (UINT8)LOAD_RM8(modrm);
+ STORE_REG32(modrm, src);
+ CYCLES(cpustate,CYCLES_MOVZX_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT32 src = (UINT8)READ8(cpustate,ea);
+ STORE_REG32(modrm, src);
+ CYCLES(cpustate,CYCLES_MOVZX_MEM_REG);
+ }
+}
+
+static void I386OP(movzx_r32_rm16)(i386_state *cpustate) // Opcode 0x0f b7
+{
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ UINT32 src = (UINT16)LOAD_RM16(modrm);
+ STORE_REG32(modrm, src);
+ CYCLES(cpustate,CYCLES_MOVZX_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT32 src = (UINT16)READ16(cpustate,ea);
+ STORE_REG32(modrm, src);
+ CYCLES(cpustate,CYCLES_MOVZX_MEM_REG);
+ }
+}
+
+static void I386OP(or_rm32_r32)(i386_state *cpustate) // Opcode 0x09
+{
+ UINT32 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_REG32(modrm);
+ dst = LOAD_RM32(modrm);
+ dst = OR32(cpustate,dst, src);
+ STORE_RM32(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = LOAD_REG32(modrm);
+ dst = READ32(cpustate,ea);
+ dst = OR32(cpustate,dst, src);
+ WRITE32(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+}
+
+static void I386OP(or_r32_rm32)(i386_state *cpustate) // Opcode 0x0b
+{
+ UINT32 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_RM32(modrm);
+ dst = LOAD_REG32(modrm);
+ dst = OR32(cpustate,dst, src);
+ STORE_REG32(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = READ32(cpustate,ea);
+ dst = LOAD_REG32(modrm);
+ dst = OR32(cpustate,dst, src);
+ STORE_REG32(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_MEM_REG);
+ }
+}
+
+static void I386OP(or_eax_i32)(i386_state *cpustate) // Opcode 0x0d
+{
+ UINT32 src, dst;
+ src = FETCH32(cpustate);
+ dst = REG32(EAX);
+ dst = OR32(cpustate,dst, src);
+ REG32(EAX) = dst;
+ CYCLES(cpustate,CYCLES_ALU_IMM_ACC);
+}
+
+static void I386OP(out_eax_i8)(i386_state *cpustate) // Opcode 0xe7
+{
+ UINT16 port = FETCH(cpustate);
+ UINT32 data = REG32(EAX);
+ WRITEPORT32(cpustate, port, data);
+ CYCLES(cpustate,CYCLES_OUT_VAR);
+}
+
+static void I386OP(out_eax_dx)(i386_state *cpustate) // Opcode 0xef
+{
+ UINT16 port = REG16(DX);
+ UINT32 data = REG32(EAX);
+ WRITEPORT32(cpustate, port, data);
+ CYCLES(cpustate,CYCLES_OUT);
+}
+
+static void I386OP(pop_eax)(i386_state *cpustate) // Opcode 0x58
+{
+ REG32(EAX) = POP32(cpustate);
+ CYCLES(cpustate,CYCLES_POP_REG_SHORT);
+}
+
+static void I386OP(pop_ecx)(i386_state *cpustate) // Opcode 0x59
+{
+ REG32(ECX) = POP32(cpustate);
+ CYCLES(cpustate,CYCLES_POP_REG_SHORT);
+}
+
+static void I386OP(pop_edx)(i386_state *cpustate) // Opcode 0x5a
+{
+ REG32(EDX) = POP32(cpustate);
+ CYCLES(cpustate,CYCLES_POP_REG_SHORT);
+}
+
+static void I386OP(pop_ebx)(i386_state *cpustate) // Opcode 0x5b
+{
+ REG32(EBX) = POP32(cpustate);
+ CYCLES(cpustate,CYCLES_POP_REG_SHORT);
+}
+
+static void I386OP(pop_esp)(i386_state *cpustate) // Opcode 0x5c
+{
+ REG32(ESP) = POP32(cpustate);
+ CYCLES(cpustate,CYCLES_POP_REG_SHORT);
+}
+
+static void I386OP(pop_ebp)(i386_state *cpustate) // Opcode 0x5d
+{
+ REG32(EBP) = POP32(cpustate);
+ CYCLES(cpustate,CYCLES_POP_REG_SHORT);
+}
+
+static void I386OP(pop_esi)(i386_state *cpustate) // Opcode 0x5e
+{
+ REG32(ESI) = POP32(cpustate);
+ CYCLES(cpustate,CYCLES_POP_REG_SHORT);
+}
+
+static void I386OP(pop_edi)(i386_state *cpustate) // Opcode 0x5f
+{
+ REG32(EDI) = POP32(cpustate);
+ CYCLES(cpustate,CYCLES_POP_REG_SHORT);
+}
+
+static void I386OP(pop_ds32)(i386_state *cpustate) // Opcode 0x1f
+{
+ cpustate->sreg[DS].selector = POP32(cpustate);
+ if( PROTECTED_MODE ) {
+ i386_load_segment_descriptor(cpustate,DS);
+ } else {
+ i386_load_segment_descriptor(cpustate,DS);
+ }
+ CYCLES(cpustate,CYCLES_POP_SREG);
+}
+
+static void I386OP(pop_es32)(i386_state *cpustate) // Opcode 0x07
+{
+ cpustate->sreg[ES].selector = POP32(cpustate);
+ if( PROTECTED_MODE ) {
+ i386_load_segment_descriptor(cpustate,ES);
+ } else {
+ i386_load_segment_descriptor(cpustate,ES);
+ }
+ CYCLES(cpustate,CYCLES_POP_SREG);
+}
+
+static void I386OP(pop_fs32)(i386_state *cpustate) // Opcode 0x0f a1
+{
+ cpustate->sreg[FS].selector = POP32(cpustate);
+ if( PROTECTED_MODE ) {
+ i386_load_segment_descriptor(cpustate,FS);
+ } else {
+ i386_load_segment_descriptor(cpustate,FS);
+ }
+ CYCLES(cpustate,CYCLES_POP_SREG);
+}
+
+static void I386OP(pop_gs32)(i386_state *cpustate) // Opcode 0x0f a9
+{
+ cpustate->sreg[GS].selector = POP32(cpustate);
+ if( PROTECTED_MODE ) {
+ i386_load_segment_descriptor(cpustate,GS);
+ } else {
+ i386_load_segment_descriptor(cpustate,GS);
+ }
+ CYCLES(cpustate,CYCLES_POP_SREG);
+}
+
+static void I386OP(pop_ss32)(i386_state *cpustate) // Opcode 0x17
+{
+ if(cpustate->IF != 0) // if external interrupts are enabled
+ {
+ cpustate->IF = 0; // reset IF for the next instruction
+ cpustate->delayed_interrupt_enable = 1;
+ }
+
+ cpustate->sreg[SS].selector = POP32(cpustate);
+ if( PROTECTED_MODE ) {
+ i386_load_segment_descriptor(cpustate,SS);
+ } else {
+ i386_load_segment_descriptor(cpustate,SS);
+ }
+ CYCLES(cpustate,CYCLES_POP_SREG);
+}
+
+static void I386OP(pop_rm32)(i386_state *cpustate) // Opcode 0x8f
+{
+ UINT8 modrm = FETCH(cpustate);
+ UINT32 value = POP32(cpustate);
+
+ if( modrm >= 0xc0 ) {
+ STORE_RM32(modrm, value);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ WRITE32(cpustate,ea, value);
+ }
+ CYCLES(cpustate,CYCLES_POP_RM);
+}
+
+static void I386OP(popad)(i386_state *cpustate) // Opcode 0x61
+{
+ REG32(EDI) = POP32(cpustate);
+ REG32(ESI) = POP32(cpustate);
+ REG32(EBP) = POP32(cpustate);
+ REG32(ESP) += 4;
+ REG32(EBX) = POP32(cpustate);
+ REG32(EDX) = POP32(cpustate);
+ REG32(ECX) = POP32(cpustate);
+ REG32(EAX) = POP32(cpustate);
+ CYCLES(cpustate,CYCLES_POPA);
+}
+
+static void I386OP(popfd)(i386_state *cpustate) // Opcode 0x9d
+{
+ UINT32 value = POP32(cpustate);
+ set_flags(cpustate,value);
+ CYCLES(cpustate,CYCLES_POPF);
+}
+
+static void I386OP(push_eax)(i386_state *cpustate) // Opcode 0x50
+{
+ PUSH32(cpustate, REG32(EAX) );
+ CYCLES(cpustate,CYCLES_PUSH_REG_SHORT);
+}
+
+static void I386OP(push_ecx)(i386_state *cpustate) // Opcode 0x51
+{
+ PUSH32(cpustate, REG32(ECX) );
+ CYCLES(cpustate,CYCLES_PUSH_REG_SHORT);
+}
+
+static void I386OP(push_edx)(i386_state *cpustate) // Opcode 0x52
+{
+ PUSH32(cpustate, REG32(EDX) );
+ CYCLES(cpustate,CYCLES_PUSH_REG_SHORT);
+}
+
+static void I386OP(push_ebx)(i386_state *cpustate) // Opcode 0x53
+{
+ PUSH32(cpustate, REG32(EBX) );
+ CYCLES(cpustate,CYCLES_PUSH_REG_SHORT);
+}
+
+static void I386OP(push_esp)(i386_state *cpustate) // Opcode 0x54
+{
+ PUSH32(cpustate, REG32(ESP) );
+ CYCLES(cpustate,CYCLES_PUSH_REG_SHORT);
+}
+
+static void I386OP(push_ebp)(i386_state *cpustate) // Opcode 0x55
+{
+ PUSH32(cpustate, REG32(EBP) );
+ CYCLES(cpustate,CYCLES_PUSH_REG_SHORT);
+}
+
+static void I386OP(push_esi)(i386_state *cpustate) // Opcode 0x56
+{
+ PUSH32(cpustate, REG32(ESI) );
+ CYCLES(cpustate,CYCLES_PUSH_REG_SHORT);
+}
+
+static void I386OP(push_edi)(i386_state *cpustate) // Opcode 0x57
+{
+ PUSH32(cpustate, REG32(EDI) );
+ CYCLES(cpustate,CYCLES_PUSH_REG_SHORT);
+}
+
+static void I386OP(push_cs32)(i386_state *cpustate) // Opcode 0x0e
+{
+ PUSH32(cpustate, cpustate->sreg[CS].selector );
+ CYCLES(cpustate,CYCLES_PUSH_SREG);
+}
+
+static void I386OP(push_ds32)(i386_state *cpustate) // Opcode 0x1e
+{
+ PUSH32(cpustate, cpustate->sreg[DS].selector );
+ CYCLES(cpustate,CYCLES_PUSH_SREG);
+}
+
+static void I386OP(push_es32)(i386_state *cpustate) // Opcode 0x06
+{
+ PUSH32(cpustate, cpustate->sreg[ES].selector );
+ CYCLES(cpustate,CYCLES_PUSH_SREG);
+}
+
+static void I386OP(push_fs32)(i386_state *cpustate) // Opcode 0x0f a0
+{
+ PUSH32(cpustate, cpustate->sreg[FS].selector );
+ CYCLES(cpustate,CYCLES_PUSH_SREG);
+}
+
+static void I386OP(push_gs32)(i386_state *cpustate) // Opcode 0x0f a8
+{
+ PUSH32(cpustate, cpustate->sreg[GS].selector );
+ CYCLES(cpustate,CYCLES_PUSH_SREG);
+}
+
+static void I386OP(push_ss32)(i386_state *cpustate) // Opcode 0x16
+{
+ PUSH32(cpustate, cpustate->sreg[SS].selector );
+ CYCLES(cpustate,CYCLES_PUSH_SREG);
+}
+
+static void I386OP(push_i32)(i386_state *cpustate) // Opcode 0x68
+{
+ UINT32 value = FETCH32(cpustate);
+ PUSH32(cpustate,value);
+ CYCLES(cpustate,CYCLES_PUSH_IMM);
+}
+
+static void I386OP(pushad)(i386_state *cpustate) // Opcode 0x60
+{
+ UINT32 temp = REG32(ESP);
+ PUSH32(cpustate, REG32(EAX) );
+ PUSH32(cpustate, REG32(ECX) );
+ PUSH32(cpustate, REG32(EDX) );
+ PUSH32(cpustate, REG32(EBX) );
+ PUSH32(cpustate, temp );
+ PUSH32(cpustate, REG32(EBP) );
+ PUSH32(cpustate, REG32(ESI) );
+ PUSH32(cpustate, REG32(EDI) );
+ CYCLES(cpustate,CYCLES_PUSHA);
+}
+
+static void I386OP(pushfd)(i386_state *cpustate) // Opcode 0x9c
+{
+ PUSH32(cpustate, get_flags(cpustate) & 0x00fcffff );
+ CYCLES(cpustate,CYCLES_PUSHF);
+}
+
+static void I386OP(ret_near32_i16)(i386_state *cpustate) // Opcode 0xc2
+{
+ INT16 disp = FETCH16(cpustate);
+ cpustate->eip = POP32(cpustate);
+ REG32(ESP) += disp;
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_RET_IMM); /* TODO: Timing = 10 + m */
+}
+
+static void I386OP(ret_near32)(i386_state *cpustate) // Opcode 0xc3
+{
+ cpustate->eip = POP32(cpustate);
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES(cpustate,CYCLES_RET); /* TODO: Timing = 10 + m */
+}
+
+static void I386OP(sbb_rm32_r32)(i386_state *cpustate) // Opcode 0x19
+{
+ UINT32 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_REG32(modrm);
+ dst = LOAD_RM32(modrm);
+ dst = SBB32(cpustate, dst, src, cpustate->CF);
+ STORE_RM32(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = LOAD_REG32(modrm);
+ dst = READ32(cpustate,ea);
+ dst = SBB32(cpustate, dst, src, cpustate->CF);
+ WRITE32(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+}
+
+static void I386OP(sbb_r32_rm32)(i386_state *cpustate) // Opcode 0x1b
+{
+ UINT32 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_RM32(modrm);
+ dst = LOAD_REG32(modrm);
+ dst = SBB32(cpustate, dst, src, cpustate->CF);
+ STORE_REG32(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = READ32(cpustate,ea);
+ dst = LOAD_REG32(modrm);
+ dst = SBB32(cpustate, dst, src, cpustate->CF);
+ STORE_REG32(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_MEM_REG);
+ }
+}
+
+static void I386OP(sbb_eax_i32)(i386_state *cpustate) // Opcode 0x1d
+{
+ UINT32 src, dst;
+ src = FETCH32(cpustate);
+ dst = REG32(EAX);
+ dst = SBB32(cpustate, dst, src, cpustate->CF);
+ REG32(EAX) = dst;
+ CYCLES(cpustate,CYCLES_ALU_IMM_ACC);
+}
+
+static void I386OP(scasd)(i386_state *cpustate) // Opcode 0xaf
+{
+ UINT32 eas, src, dst;
+ eas = i386_translate(cpustate, ES, cpustate->address_size ? REG32(EDI) : REG16(DI) );
+ src = READ32(cpustate,eas);
+ dst = REG32(EAX);
+ SUB32(cpustate,dst, src);
+ BUMP_DI(cpustate,4);
+ CYCLES(cpustate,CYCLES_SCAS);
+}
+
+static void I386OP(shld32_i8)(i386_state *cpustate) // Opcode 0x0f a4
+{
+ /* TODO: Correct flags */
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ UINT32 dst = LOAD_RM32(modrm);
+ UINT32 upper = LOAD_REG32(modrm);
+ UINT8 shift = FETCH(cpustate);
+ if( shift > 31 || shift == 0 ) {
+
+ } else {
+ cpustate->CF = (dst & (1 << (32-shift))) ? 1 : 0;
+ dst = (dst << shift) | (upper >> (32-shift));
+ SetSZPF32(dst);
+ }
+ STORE_RM32(modrm, dst);
+ CYCLES(cpustate,CYCLES_SHLD_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT32 dst = READ32(cpustate,ea);
+ UINT32 upper = LOAD_REG32(modrm);
+ UINT8 shift = FETCH(cpustate);
+ if( shift > 31 || shift == 0 ) {
+
+ } else {
+ cpustate->CF = (dst & (1 << (32-shift))) ? 1 : 0;
+ dst = (dst << shift) | (upper >> (32-shift));
+ SetSZPF32(dst);
+ }
+ WRITE32(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_SHLD_MEM);
+ }
+}
+
+static void I386OP(shld32_cl)(i386_state *cpustate) // Opcode 0x0f a5
+{
+ /* TODO: Correct flags */
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ UINT32 dst = LOAD_RM32(modrm);
+ UINT32 upper = LOAD_REG32(modrm);
+ UINT8 shift = REG8(CL);
+ if( shift > 31 || shift == 0 ) {
+
+ } else {
+ cpustate->CF = (dst & (1 << (32-shift))) ? 1 : 0;
+ dst = (dst << shift) | (upper >> (32-shift));
+ SetSZPF32(dst);
+ }
+ STORE_RM32(modrm, dst);
+ CYCLES(cpustate,CYCLES_SHLD_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT32 dst = READ32(cpustate,ea);
+ UINT32 upper = LOAD_REG32(modrm);
+ UINT8 shift = REG8(CL);
+ if( shift > 31 || shift == 0 ) {
+
+ } else {
+ cpustate->CF = (dst & (1 << (32-shift))) ? 1 : 0;
+ dst = (dst << shift) | (upper >> (32-shift));
+ SetSZPF32(dst);
+ }
+ WRITE32(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_SHLD_MEM);
+ }
+}
+
+static void I386OP(shrd32_i8)(i386_state *cpustate) // Opcode 0x0f ac
+{
+ /* TODO: Correct flags */
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ UINT32 dst = LOAD_RM32(modrm);
+ UINT32 upper = LOAD_REG32(modrm);
+ UINT8 shift = FETCH(cpustate);
+ if( shift > 31 || shift == 0 ) {
+
+ } else {
+ cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0;
+ dst = (dst >> shift) | (upper << (32-shift));
+ SetSZPF32(dst);
+ }
+ STORE_RM32(modrm, dst);
+ CYCLES(cpustate,CYCLES_SHRD_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT32 dst = READ32(cpustate,ea);
+ UINT32 upper = LOAD_REG32(modrm);
+ UINT8 shift = FETCH(cpustate);
+ if( shift > 31 || shift == 0 ) {
+
+ } else {
+ cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0;
+ dst = (dst >> shift) | (upper << (32-shift));
+ SetSZPF32(dst);
+ }
+ WRITE32(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_SHRD_MEM);
+ }
+}
+
+static void I386OP(shrd32_cl)(i386_state *cpustate) // Opcode 0x0f ad
+{
+ /* TODO: Correct flags */
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ UINT32 dst = LOAD_RM32(modrm);
+ UINT32 upper = LOAD_REG32(modrm);
+ UINT8 shift = REG8(CL);
+ if( shift > 31 || shift == 0 ) {
+
+ } else {
+ cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0;
+ dst = (dst >> shift) | (upper << (32-shift));
+ SetSZPF32(dst);
+ }
+ STORE_RM32(modrm, dst);
+ CYCLES(cpustate,CYCLES_SHRD_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT32 dst = READ32(cpustate,ea);
+ UINT32 upper = LOAD_REG32(modrm);
+ UINT8 shift = REG8(CL);
+ if( shift > 31 || shift == 0 ) {
+
+ } else {
+ cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0;
+ dst = (dst >> shift) | (upper << (32-shift));
+ SetSZPF32(dst);
+ }
+ WRITE32(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_SHRD_MEM);
+ }
+}
+
+static void I386OP(stosd)(i386_state *cpustate) // Opcode 0xab
+{
+ UINT32 eas = i386_translate(cpustate, ES, cpustate->address_size ? REG32(EDI) : REG16(DI) );
+ WRITE32(cpustate,eas, REG32(EAX));
+ BUMP_DI(cpustate,4);
+ CYCLES(cpustate,CYCLES_STOS);
+}
+
+static void I386OP(sub_rm32_r32)(i386_state *cpustate) // Opcode 0x29
+{
+ UINT32 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_REG32(modrm);
+ dst = LOAD_RM32(modrm);
+ dst = SUB32(cpustate,dst, src);
+ STORE_RM32(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = LOAD_REG32(modrm);
+ dst = READ32(cpustate,ea);
+ dst = SUB32(cpustate,dst, src);
+ WRITE32(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+}
+
+static void I386OP(sub_r32_rm32)(i386_state *cpustate) // Opcode 0x2b
+{
+ UINT32 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_RM32(modrm);
+ dst = LOAD_REG32(modrm);
+ dst = SUB32(cpustate,dst, src);
+ STORE_REG32(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = READ32(cpustate,ea);
+ dst = LOAD_REG32(modrm);
+ dst = SUB32(cpustate,dst, src);
+ STORE_REG32(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_MEM_REG);
+ }
+}
+
+static void I386OP(sub_eax_i32)(i386_state *cpustate) // Opcode 0x2d
+{
+ UINT32 src, dst;
+ src = FETCH32(cpustate);
+ dst = REG32(EAX);
+ dst = SUB32(cpustate,dst, src);
+ REG32(EAX) = dst;
+ CYCLES(cpustate,CYCLES_ALU_IMM_ACC);
+}
+
+static void I386OP(test_eax_i32)(i386_state *cpustate) // Opcode 0xa9
+{
+ UINT32 src = FETCH32(cpustate);
+ UINT32 dst = REG32(EAX);
+ dst = src & dst;
+ SetSZPF32(dst);
+ cpustate->CF = 0;
+ cpustate->OF = 0;
+ CYCLES(cpustate,CYCLES_TEST_IMM_ACC);
+}
+
+static void I386OP(test_rm32_r32)(i386_state *cpustate) // Opcode 0x85
+{
+ UINT32 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_REG32(modrm);
+ dst = LOAD_RM32(modrm);
+ dst = src & dst;
+ SetSZPF32(dst);
+ cpustate->CF = 0;
+ cpustate->OF = 0;
+ CYCLES(cpustate,CYCLES_TEST_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = LOAD_REG32(modrm);
+ dst = READ32(cpustate,ea);
+ dst = src & dst;
+ SetSZPF32(dst);
+ cpustate->CF = 0;
+ cpustate->OF = 0;
+ CYCLES(cpustate,CYCLES_TEST_REG_MEM);
+ }
+}
+
+static void I386OP(xchg_eax_ecx)(i386_state *cpustate) // Opcode 0x91
+{
+ UINT32 temp;
+ temp = REG32(EAX);
+ REG32(EAX) = REG32(ECX);
+ REG32(ECX) = temp;
+ CYCLES(cpustate,CYCLES_XCHG_REG_REG);
+}
+
+static void I386OP(xchg_eax_edx)(i386_state *cpustate) // Opcode 0x92
+{
+ UINT32 temp;
+ temp = REG32(EAX);
+ REG32(EAX) = REG32(EDX);
+ REG32(EDX) = temp;
+ CYCLES(cpustate,CYCLES_XCHG_REG_REG);
+}
+
+static void I386OP(xchg_eax_ebx)(i386_state *cpustate) // Opcode 0x93
+{
+ UINT32 temp;
+ temp = REG32(EAX);
+ REG32(EAX) = REG32(EBX);
+ REG32(EBX) = temp;
+ CYCLES(cpustate,CYCLES_XCHG_REG_REG);
+}
+
+static void I386OP(xchg_eax_esp)(i386_state *cpustate) // Opcode 0x94
+{
+ UINT32 temp;
+ temp = REG32(EAX);
+ REG32(EAX) = REG32(ESP);
+ REG32(ESP) = temp;
+ CYCLES(cpustate,CYCLES_XCHG_REG_REG);
+}
+
+static void I386OP(xchg_eax_ebp)(i386_state *cpustate) // Opcode 0x95
+{
+ UINT32 temp;
+ temp = REG32(EAX);
+ REG32(EAX) = REG32(EBP);
+ REG32(EBP) = temp;
+ CYCLES(cpustate,CYCLES_XCHG_REG_REG);
+}
+
+static void I386OP(xchg_eax_esi)(i386_state *cpustate) // Opcode 0x96
+{
+ UINT32 temp;
+ temp = REG32(EAX);
+ REG32(EAX) = REG32(ESI);
+ REG32(ESI) = temp;
+ CYCLES(cpustate,CYCLES_XCHG_REG_REG);
+}
+
+static void I386OP(xchg_eax_edi)(i386_state *cpustate) // Opcode 0x97
+{
+ UINT32 temp;
+ temp = REG32(EAX);
+ REG32(EAX) = REG32(EDI);
+ REG32(EDI) = temp;
+ CYCLES(cpustate,CYCLES_XCHG_REG_REG);
+}
+
+static void I386OP(xchg_r32_rm32)(i386_state *cpustate) // Opcode 0x87
+{
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ UINT32 src = LOAD_RM32(modrm);
+ UINT32 dst = LOAD_REG32(modrm);
+ STORE_REG32(modrm, src);
+ STORE_RM32(modrm, dst);
+ CYCLES(cpustate,CYCLES_XCHG_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT32 src = READ32(cpustate,ea);
+ UINT32 dst = LOAD_REG32(modrm);
+ STORE_REG32(modrm, src);
+ WRITE32(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_XCHG_REG_MEM);
+ }
+}
+
+static void I386OP(xor_rm32_r32)(i386_state *cpustate) // Opcode 0x31
+{
+ UINT32 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_REG32(modrm);
+ dst = LOAD_RM32(modrm);
+ dst = XOR32(cpustate,dst, src);
+ STORE_RM32(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = LOAD_REG32(modrm);
+ dst = READ32(cpustate,ea);
+ dst = XOR32(cpustate,dst, src);
+ WRITE32(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+}
+
+static void I386OP(xor_r32_rm32)(i386_state *cpustate) // Opcode 0x33
+{
+ UINT32 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_RM32(modrm);
+ dst = LOAD_REG32(modrm);
+ dst = XOR32(cpustate,dst, src);
+ STORE_REG32(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = READ32(cpustate,ea);
+ dst = LOAD_REG32(modrm);
+ dst = XOR32(cpustate,dst, src);
+ STORE_REG32(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_MEM_REG);
+ }
+}
+
+static void I386OP(xor_eax_i32)(i386_state *cpustate) // Opcode 0x35
+{
+ UINT32 src, dst;
+ src = FETCH32(cpustate);
+ dst = REG32(EAX);
+ dst = XOR32(cpustate,dst, src);
+ REG32(EAX) = dst;
+ CYCLES(cpustate,CYCLES_ALU_IMM_ACC);
+}
+
+
+
+static void I386OP(group81_32)(i386_state *cpustate) // Opcode 0x81
+{
+ UINT32 ea;
+ UINT32 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+
+ switch( (modrm >> 3) & 0x7 )
+ {
+ case 0: // ADD Rm32, i32
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM32(modrm);
+ src = FETCH32(cpustate);
+ dst = ADD32(cpustate,dst, src);
+ STORE_RM32(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ dst = READ32(cpustate,ea);
+ src = FETCH32(cpustate);
+ dst = ADD32(cpustate,dst, src);
+ WRITE32(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+ break;
+ case 1: // OR Rm32, i32
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM32(modrm);
+ src = FETCH32(cpustate);
+ dst = OR32(cpustate,dst, src);
+ STORE_RM32(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ dst = READ32(cpustate,ea);
+ src = FETCH32(cpustate);
+ dst = OR32(cpustate,dst, src);
+ WRITE32(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+ break;
+ case 2: // ADC Rm32, i32
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM32(modrm);
+ src = FETCH32(cpustate);
+ dst = ADC32(cpustate, dst, src, cpustate->CF);
+ STORE_RM32(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ dst = READ32(cpustate,ea);
+ src = FETCH32(cpustate);
+ dst = ADC32(cpustate, dst, src, cpustate->CF);
+ WRITE32(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+ break;
+ case 3: // SBB Rm32, i32
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM32(modrm);
+ src = FETCH32(cpustate);
+ dst = SBB32(cpustate, dst, src, cpustate->CF);
+ STORE_RM32(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ dst = READ32(cpustate,ea);
+ src = FETCH32(cpustate);
+ dst = SBB32(cpustate, dst, src, cpustate->CF);
+ WRITE32(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+ break;
+ case 4: // AND Rm32, i32
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM32(modrm);
+ src = FETCH32(cpustate);
+ dst = AND32(cpustate,dst, src);
+ STORE_RM32(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ dst = READ32(cpustate,ea);
+ src = FETCH32(cpustate);
+ dst = AND32(cpustate,dst, src);
+ WRITE32(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+ break;
+ case 5: // SUB Rm32, i32
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM32(modrm);
+ src = FETCH32(cpustate);
+ dst = SUB32(cpustate,dst, src);
+ STORE_RM32(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ dst = READ32(cpustate,ea);
+ src = FETCH32(cpustate);
+ dst = SUB32(cpustate,dst, src);
+ WRITE32(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+ break;
+ case 6: // XOR Rm32, i32
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM32(modrm);
+ src = FETCH32(cpustate);
+ dst = XOR32(cpustate,dst, src);
+ STORE_RM32(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ dst = READ32(cpustate,ea);
+ src = FETCH32(cpustate);
+ dst = XOR32(cpustate,dst, src);
+ WRITE32(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+ break;
+ case 7: // CMP Rm32, i32
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM32(modrm);
+ src = FETCH32(cpustate);
+ SUB32(cpustate,dst, src);
+ CYCLES(cpustate,CYCLES_CMP_REG_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ dst = READ32(cpustate,ea);
+ src = FETCH32(cpustate);
+ SUB32(cpustate,dst, src);
+ CYCLES(cpustate,CYCLES_CMP_REG_MEM);
+ }
+ break;
+ }
+}
+
+static void I386OP(group83_32)(i386_state *cpustate) // Opcode 0x83
+{
+ UINT32 ea;
+ UINT32 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+
+ switch( (modrm >> 3) & 0x7 )
+ {
+ case 0: // ADD Rm32, i32
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM32(modrm);
+ src = (UINT32)(INT32)(INT8)FETCH(cpustate);
+ dst = ADD32(cpustate,dst, src);
+ STORE_RM32(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ dst = READ32(cpustate,ea);
+ src = (UINT32)(INT32)(INT8)FETCH(cpustate);
+ dst = ADD32(cpustate,dst, src);
+ WRITE32(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+ break;
+ case 1: // OR Rm32, i32
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM32(modrm);
+ src = (UINT32)(INT32)(INT8)FETCH(cpustate);
+ dst = OR32(cpustate,dst, src);
+ STORE_RM32(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ dst = READ32(cpustate,ea);
+ src = (UINT32)(INT32)(INT8)FETCH(cpustate);
+ dst = OR32(cpustate,dst, src);
+ WRITE32(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+ break;
+ case 2: // ADC Rm32, i32
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM32(modrm);
+ src = (UINT32)(INT32)(INT8)FETCH(cpustate);
+ dst = ADC32(cpustate, dst, src, cpustate->CF);
+ STORE_RM32(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ dst = READ32(cpustate,ea);
+ src = (UINT32)(INT32)(INT8)FETCH(cpustate);
+ dst = ADC32(cpustate, dst, src, cpustate->CF);
+ WRITE32(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+ break;
+ case 3: // SBB Rm32, i32
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM32(modrm);
+ src = ((UINT32)(INT32)(INT8)FETCH(cpustate));
+ dst = SBB32(cpustate, dst, src, cpustate->CF);
+ STORE_RM32(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ dst = READ32(cpustate,ea);
+ src = ((UINT32)(INT32)(INT8)FETCH(cpustate));
+ dst = SBB32(cpustate, dst, src, cpustate->CF);
+ WRITE32(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+ break;
+ case 4: // AND Rm32, i32
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM32(modrm);
+ src = (UINT32)(INT32)(INT8)FETCH(cpustate);
+ dst = AND32(cpustate,dst, src);
+ STORE_RM32(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ dst = READ32(cpustate,ea);
+ src = (UINT32)(INT32)(INT8)FETCH(cpustate);
+ dst = AND32(cpustate,dst, src);
+ WRITE32(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+ break;
+ case 5: // SUB Rm32, i32
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM32(modrm);
+ src = (UINT32)(INT32)(INT8)FETCH(cpustate);
+ dst = SUB32(cpustate,dst, src);
+ STORE_RM32(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ dst = READ32(cpustate,ea);
+ src = (UINT32)(INT32)(INT8)FETCH(cpustate);
+ dst = SUB32(cpustate,dst, src);
+ WRITE32(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+ break;
+ case 6: // XOR Rm32, i32
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM32(modrm);
+ src = (UINT32)(INT32)(INT8)FETCH(cpustate);
+ dst = XOR32(cpustate,dst, src);
+ STORE_RM32(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ dst = READ32(cpustate,ea);
+ src = (UINT32)(INT32)(INT8)FETCH(cpustate);
+ dst = XOR32(cpustate,dst, src);
+ WRITE32(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+ break;
+ case 7: // CMP Rm32, i32
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM32(modrm);
+ src = (UINT32)(INT32)(INT8)FETCH(cpustate);
+ SUB32(cpustate,dst, src);
+ CYCLES(cpustate,CYCLES_CMP_REG_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ dst = READ32(cpustate,ea);
+ src = (UINT32)(INT32)(INT8)FETCH(cpustate);
+ SUB32(cpustate,dst, src);
+ CYCLES(cpustate,CYCLES_CMP_REG_MEM);
+ }
+ break;
+ }
+}
+
+static void I386OP(groupC1_32)(i386_state *cpustate) // Opcode 0xc1
+{
+ UINT32 dst;
+ UINT8 modrm = FETCH(cpustate);
+ UINT8 shift;
+
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM32(modrm);
+ shift = FETCH(cpustate) & 0x1f;
+ dst = i386_shift_rotate32(cpustate, modrm, dst, shift);
+ STORE_RM32(modrm, dst);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ dst = READ32(cpustate,ea);
+ shift = FETCH(cpustate) & 0x1f;
+ dst = i386_shift_rotate32(cpustate, modrm, dst, shift);
+ WRITE32(cpustate,ea, dst);
+ }
+}
+
+static void I386OP(groupD1_32)(i386_state *cpustate) // Opcode 0xd1
+{
+ UINT32 dst;
+ UINT8 modrm = FETCH(cpustate);
+
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM32(modrm);
+ dst = i386_shift_rotate32(cpustate, modrm, dst, 1);
+ STORE_RM32(modrm, dst);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ dst = READ32(cpustate,ea);
+ dst = i386_shift_rotate32(cpustate, modrm, dst, 1);
+ WRITE32(cpustate,ea, dst);
+ }
+}
+
+static void I386OP(groupD3_32)(i386_state *cpustate) // Opcode 0xd3
+{
+ UINT32 dst;
+ UINT8 modrm = FETCH(cpustate);
+
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM32(modrm);
+ dst = i386_shift_rotate32(cpustate, modrm, dst, REG8(CL));
+ STORE_RM32(modrm, dst);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ dst = READ32(cpustate,ea);
+ dst = i386_shift_rotate32(cpustate, modrm, dst, REG8(CL));
+ WRITE32(cpustate,ea, dst);
+ }
+}
+
+static void I386OP(groupF7_32)(i386_state *cpustate) // Opcode 0xf7
+{
+ UINT8 modrm = FETCH(cpustate);
+
+ switch( (modrm >> 3) & 0x7 )
+ {
+ case 0: /* TEST Rm32, i32 */
+ if( modrm >= 0xc0 ) {
+ UINT32 dst = LOAD_RM32(modrm);
+ UINT32 src = FETCH32(cpustate);
+ dst &= src;
+ cpustate->CF = cpustate->OF = cpustate->AF = 0;
+ SetSZPF32(dst);
+ CYCLES(cpustate,CYCLES_TEST_IMM_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT32 dst = READ32(cpustate,ea);
+ UINT32 src = FETCH32(cpustate);
+ dst &= src;
+ cpustate->CF = cpustate->OF = cpustate->AF = 0;
+ SetSZPF32(dst);
+ CYCLES(cpustate,CYCLES_TEST_IMM_MEM);
+ }
+ break;
+ case 2: /* NOT Rm32 */
+ if( modrm >= 0xc0 ) {
+ UINT32 dst = LOAD_RM32(modrm);
+ dst = ~dst;
+ STORE_RM32(modrm, dst);
+ CYCLES(cpustate,CYCLES_NOT_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT32 dst = READ32(cpustate,ea);
+ dst = ~dst;
+ WRITE32(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_NOT_MEM);
+ }
+ break;
+ case 3: /* NEG Rm32 */
+ if( modrm >= 0xc0 ) {
+ UINT32 dst = LOAD_RM32(modrm);
+ dst = SUB32(cpustate, 0, dst );
+ STORE_RM32(modrm, dst);
+ CYCLES(cpustate,CYCLES_NEG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT32 dst = READ32(cpustate,ea);
+ dst = SUB32(cpustate, 0, dst );
+ WRITE32(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_NEG_MEM);
+ }
+ break;
+ case 4: /* MUL EAX, Rm32 */
+ {
+ UINT64 result;
+ UINT32 src, dst;
+ if( modrm >= 0xc0 ) {
+ src = LOAD_RM32(modrm);
+ CYCLES(cpustate,CYCLES_MUL32_ACC_REG); /* TODO: Correct multiply timing */
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = READ32(cpustate,ea);
+ CYCLES(cpustate,CYCLES_MUL32_ACC_MEM); /* TODO: Correct multiply timing */
+ }
+
+ dst = REG32(EAX);
+ result = (UINT64)src * (UINT64)dst;
+ REG32(EDX) = (UINT32)(result >> 32);
+ REG32(EAX) = (UINT32)result;
+
+ cpustate->CF = cpustate->OF = (REG32(EDX) != 0);
+ }
+ break;
+ case 5: /* IMUL EAX, Rm32 */
+ {
+ INT64 result;
+ INT64 src, dst;
+ if( modrm >= 0xc0 ) {
+ src = (INT64)(INT32)LOAD_RM32(modrm);
+ CYCLES(cpustate,CYCLES_IMUL32_ACC_REG); /* TODO: Correct multiply timing */
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = (INT64)(INT32)READ32(cpustate,ea);
+ CYCLES(cpustate,CYCLES_IMUL32_ACC_MEM); /* TODO: Correct multiply timing */
+ }
+
+ dst = (INT64)(INT32)REG32(EAX);
+ result = src * dst;
+
+ REG32(EDX) = (UINT32)(result >> 32);
+ REG32(EAX) = (UINT32)result;
+
+ cpustate->CF = cpustate->OF = !(result == (INT64)(INT32)result);
+ }
+ break;
+ case 6: /* DIV EAX, Rm32 */
+ {
+ UINT64 quotient, remainder, result;
+ UINT32 src;
+ if( modrm >= 0xc0 ) {
+ src = LOAD_RM32(modrm);
+ CYCLES(cpustate,CYCLES_DIV32_ACC_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = READ32(cpustate,ea);
+ CYCLES(cpustate,CYCLES_DIV32_ACC_MEM);
+ }
+
+ quotient = ((UINT64)(REG32(EDX)) << 32) | (UINT64)(REG32(EAX));
+ if( src ) {
+ remainder = quotient % (UINT64)src;
+ result = quotient / (UINT64)src;
+ if( result > 0xffffffff ) {
+ /* TODO: Divide error */
+ } else {
+ REG32(EDX) = (UINT32)remainder;
+ REG32(EAX) = (UINT32)result;
+ }
+ } else {
+ /* TODO: Divide by zero */
+ }
+ }
+ break;
+ case 7: /* IDIV EAX, Rm32 */
+ {
+ INT64 quotient, remainder, result;
+ UINT32 src;
+ if( modrm >= 0xc0 ) {
+ src = LOAD_RM32(modrm);
+ CYCLES(cpustate,CYCLES_IDIV32_ACC_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = READ32(cpustate,ea);
+ CYCLES(cpustate,CYCLES_IDIV32_ACC_MEM);
+ }
+
+ quotient = (((INT64)REG32(EDX)) << 32) | ((UINT64)REG32(EAX));
+ if( src ) {
+ remainder = quotient % (INT64)(INT32)src;
+ result = quotient / (INT64)(INT32)src;
+ if( result > 0xffffffff ) {
+ /* TODO: Divide error */
+ } else {
+ REG32(EDX) = (UINT32)remainder;
+ REG32(EAX) = (UINT32)result;
+ }
+ } else {
+ /* TODO: Divide by zero */
+ }
+ }
+ break;
+ }
+}
+
+static void I386OP(groupFF_32)(i386_state *cpustate) // Opcode 0xff
+{
+ UINT8 modrm = FETCH(cpustate);
+
+ switch( (modrm >> 3) & 0x7 )
+ {
+ case 0: /* INC Rm32 */
+ if( modrm >= 0xc0 ) {
+ UINT32 dst = LOAD_RM32(modrm);
+ dst = INC32(cpustate,dst);
+ STORE_RM32(modrm, dst);
+ CYCLES(cpustate,CYCLES_INC_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT32 dst = READ32(cpustate,ea);
+ dst = INC32(cpustate,dst);
+ WRITE32(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_INC_MEM);
+ }
+ break;
+ case 1: /* DEC Rm32 */
+ if( modrm >= 0xc0 ) {
+ UINT32 dst = LOAD_RM32(modrm);
+ dst = DEC32(cpustate,dst);
+ STORE_RM32(modrm, dst);
+ CYCLES(cpustate,CYCLES_DEC_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT32 dst = READ32(cpustate,ea);
+ dst = DEC32(cpustate,dst);
+ WRITE32(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_DEC_MEM);
+ }
+ break;
+ case 2: /* CALL Rm32 */
+ {
+ UINT32 address;
+ if( modrm >= 0xc0 ) {
+ address = LOAD_RM32(modrm);
+ CYCLES(cpustate,CYCLES_CALL_REG); /* TODO: Timing = 7 + m */
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ address = READ32(cpustate,ea);
+ CYCLES(cpustate,CYCLES_CALL_MEM); /* TODO: Timing = 10 + m */
+ }
+ PUSH32(cpustate, cpustate->eip );
+ cpustate->eip = address;
+ CHANGE_PC(cpustate,cpustate->eip);
+ }
+ break;
+ case 3: /* CALL FAR Rm32 */
+ {
+ UINT16 selector;
+ UINT32 address;
+
+ if( modrm >= 0xc0 )
+ {
+ fatalerror("i386: groupFF_32 /%d: NYI", (modrm >> 3) & 0x7);
+ }
+ else
+ {
+ UINT32 ea = GetEA(cpustate,modrm);
+ address = READ32(cpustate,ea + 0);
+ selector = READ16(cpustate,ea + 4);
+ CYCLES(cpustate,CYCLES_CALL_MEM_INTERSEG); /* TODO: Timing = 10 + m */
+ if(PROTECTED_MODE && !V8086_MODE)
+ {
+ i386_protected_mode_call(cpustate,selector,address,1,1);
+ }
+ else
+ {
+ PUSH32(cpustate, cpustate->sreg[CS].selector );
+ PUSH32(cpustate, cpustate->eip );
+ cpustate->sreg[CS].selector = selector;
+ cpustate->performed_intersegment_jump = 1;
+ i386_load_segment_descriptor(cpustate, CS );
+ cpustate->eip = address;
+ CHANGE_PC(cpustate,cpustate->eip);
+ }
+ }
+ }
+ break;
+ case 4: /* JMP Rm32 */
+ {
+ UINT32 address;
+ if( modrm >= 0xc0 ) {
+ address = LOAD_RM32(modrm);
+ CYCLES(cpustate,CYCLES_JMP_REG); /* TODO: Timing = 7 + m */
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ address = READ32(cpustate,ea);
+ CYCLES(cpustate,CYCLES_JMP_MEM); /* TODO: Timing = 10 + m */
+ }
+ cpustate->eip = address;
+ CHANGE_PC(cpustate,cpustate->eip);
+ }
+ break;
+ case 5: /* JMP FAR Rm32 */
+ {
+ UINT16 selector;
+ UINT32 address;
+
+ if( modrm >= 0xc0 )
+ {
+ fatalerror("i386: groupFF_32 /%d: NYI", (modrm >> 3) & 0x7);
+ }
+ else
+ {
+ UINT32 ea = GetEA(cpustate,modrm);
+ address = READ32(cpustate,ea + 0);
+ selector = READ16(cpustate,ea + 4);
+ CYCLES(cpustate,CYCLES_JMP_MEM_INTERSEG); /* TODO: Timing = 10 + m */
+ if(PROTECTED_MODE && !V8086_MODE)
+ {
+ i386_protected_mode_jump(cpustate,selector,address,1,1);
+ }
+ else
+ {
+ cpustate->sreg[CS].selector = selector;
+ cpustate->performed_intersegment_jump = 1;
+ i386_load_segment_descriptor(cpustate, CS );
+ cpustate->eip = address;
+ CHANGE_PC(cpustate,cpustate->eip);
+ }
+ }
+ }
+ break;
+ case 6: /* PUSH Rm32 */
+ {
+ UINT32 value;
+ if( modrm >= 0xc0 ) {
+ value = LOAD_RM32(modrm);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ value = READ32(cpustate,ea);
+ }
+ PUSH32(cpustate,value);
+ CYCLES(cpustate,CYCLES_PUSH_RM);
+ }
+ break;
+ default:
+ fatalerror("i386: groupFF_32 /%d unimplemented at %08X", (modrm >> 3) & 0x7, cpustate->pc-2);
+ break;
+ }
+}
+
+static void I386OP(group0F00_32)(i386_state *cpustate) // Opcode 0x0f 00
+{
+ UINT32 address, ea;
+ UINT8 modrm = FETCH(cpustate);
+ I386_SREG seg;
+ UINT8 result;
+
+ switch( (modrm >> 3) & 0x7 )
+ {
+ case 0: /* SLDT */
+ if ( PROTECTED_MODE && !V8086_MODE )
+ {
+ if( modrm >= 0xc0 ) {
+ address = LOAD_RM32(modrm);
+ STORE_RM32(address, cpustate->ldtr.segment);
+ CYCLES(cpustate,CYCLES_SLDT_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ WRITE32(cpustate, ea, cpustate->ldtr.segment);
+ CYCLES(cpustate,CYCLES_SLDT_MEM);
+ }
+ }
+ else
+ {
+ i386_trap(cpustate,6, 0, 0);
+ }
+ break;
+ case 1: /* STR */
+ if ( PROTECTED_MODE && !V8086_MODE )
+ {
+ if( modrm >= 0xc0 ) {
+ address = LOAD_RM32(modrm);
+ STORE_RM32(address, cpustate->task.segment);
+ CYCLES(cpustate,CYCLES_STR_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ WRITE32(cpustate, ea, cpustate->task.segment);
+ CYCLES(cpustate,CYCLES_STR_MEM);
+ }
+ }
+ else
+ {
+ i386_trap(cpustate,6, 0, 0);
+ }
+ break;
+ case 2: /* LLDT */
+ if ( PROTECTED_MODE && !V8086_MODE )
+ {
+ if( modrm >= 0xc0 ) {
+ address = LOAD_RM32(modrm);
+ cpustate->ldtr.segment = address;
+ CYCLES(cpustate,CYCLES_LLDT_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ cpustate->ldtr.segment = READ32(cpustate,ea);
+ CYCLES(cpustate,CYCLES_LLDT_MEM);
+ }
+ memset(&seg, 0, sizeof(seg));
+ seg.selector = cpustate->ldtr.segment;
+ i386_load_protected_mode_segment(cpustate,&seg);
+ cpustate->ldtr.limit = seg.limit;
+ cpustate->ldtr.base = seg.base;
+ cpustate->ldtr.flags = seg.flags;
+ }
+ else
+ {
+ i386_trap(cpustate,6, 0, 0);
+ }
+ break;
+
+ case 3: /* LTR */
+ if ( PROTECTED_MODE && !V8086_MODE )
+ {
+ if( modrm >= 0xc0 ) {
+ address = LOAD_RM32(modrm);
+ cpustate->task.segment = address;
+ CYCLES(cpustate,CYCLES_LTR_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ cpustate->task.segment = READ32(cpustate,ea);
+ CYCLES(cpustate,CYCLES_LTR_MEM);
+ }
+ memset(&seg, 0, sizeof(seg));
+ seg.selector = cpustate->task.segment;
+ i386_load_protected_mode_segment(cpustate,&seg);
+ cpustate->task.limit = seg.limit;
+ cpustate->task.base = seg.base;
+ cpustate->task.flags = seg.flags;
+ }
+ else
+ {
+ i386_trap(cpustate,6, 0, 0);
+ }
+ break;
+
+ case 4: /* VERR */
+ if ( PROTECTED_MODE && !V8086_MODE )
+ {
+ result = 1;
+ if( modrm >= 0xc0 ) {
+ address = LOAD_RM32(modrm);
+ CYCLES(cpustate,CYCLES_VERR_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ address = READ32(cpustate,ea);
+ CYCLES(cpustate,CYCLES_VERR_MEM);
+ }
+ memset(&seg, 0, sizeof(seg));
+ seg.selector = address;
+ i386_load_protected_mode_segment(cpustate,&seg);
+ // check if the segment is within the bounds of the GDT or LDT
+ if(seg.selector & 0x04)
+ { // LDT
+ if((seg.selector & 0xf8) > cpustate->ldtr.limit)
+ {
+ result = 0;
+ }
+ }
+ else
+ { // GDT
+ if((seg.selector & 0xf8) > cpustate->gdtr.limit)
+ {
+ result = 0;
+ }
+ }
+ // check if the segment is a code or data segment (not a special segment type, like a TSS, gate, LDT...)
+ if(!(seg.flags & 0x10))
+ result = 0;
+ // check that the segment is readable
+ if(seg.flags & 0x10) // is code or data segment
+ {
+ if(seg.flags & 0x08) // is code segment, so check if it's readable
+ {
+ if(!(seg.flags & 0x02))
+ {
+ result = 0;
+ }
+ else
+ { // check if conforming, these are always readable, regardless of privilege
+ if(!(seg.flags & 0x04))
+ {
+ // if not conforming, then we must check privilege levels (TODO: current privilege level check)
+ if(((seg.flags >> 5) & 0x03) < (address & 0x03))
+ result = 0;
+ }
+ }
+ }
+ }
+ // check that the descriptor privilege is greater or equal to the selector's privilege level and the current privilege (TODO)
+ SetZF(result);
+ }
+ else
+ {
+ i386_trap(cpustate,6, 0, 0);
+ logerror("i386: VERR: Exception - Running in real mode or virtual 8086 mode.\n");
+ }
+ break;
+
+ case 5: /* VERW */
+ if ( PROTECTED_MODE && !V8086_MODE )
+ {
+ result = 1;
+ if( modrm >= 0xc0 ) {
+ address = LOAD_RM16(modrm);
+ CYCLES(cpustate,CYCLES_VERW_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ address = READ16(cpustate,ea);
+ CYCLES(cpustate,CYCLES_VERW_MEM);
+ }
+ memset(&seg, 0, sizeof(seg));
+ seg.selector = address;
+ i386_load_protected_mode_segment(cpustate,&seg);
+ // check if the segment is within the bounds of the GDT or LDT
+ if(seg.selector & 0x04)
+ { // LDT
+ if((seg.selector & 0xf8) > cpustate->ldtr.limit)
+ {
+ result = 0;
+ }
+ }
+ else
+ { // GDT
+ if((seg.selector & 0xf8) > cpustate->gdtr.limit)
+ {
+ result = 0;
+ }
+ }
+ // check if the segment is a code or data segment (not a special segment type, like a TSS, gate, LDT...)
+ if(!(seg.flags & 0x10))
+ result = 0;
+ // check that the segment is writable
+ if(seg.flags & 0x10) // is code or data segment
+ {
+ if(seg.flags & 0x08) // is code segment (and thus, not writable)
+ {
+ result = 0;
+ }
+ else
+ { // is data segment
+ if(!(seg.flags & 0x02))
+ result = 0;
+ }
+ }
+ // check that the descriptor privilege is greater or equal to the selector's privilege level and the current privilege (TODO)
+ if(((seg.flags >> 5) & 0x03) < (address & 0x03))
+ result = 0;
+ SetZF(result);
+ }
+ else
+ {
+ i386_trap(cpustate,6, 0, 0);
+ logerror("i386: VERW: Exception - Running in real mode or virtual 8086 mode.\n");
+ }
+ break;
+
+ default:
+ fatalerror("i386: group0F00_32 /%d unimplemented", (modrm >> 3) & 0x7);
+ break;
+ }
+}
+
+static void I386OP(group0F01_32)(i386_state *cpustate) // Opcode 0x0f 01
+{
+ UINT8 modrm = FETCH(cpustate);
+ UINT32 address, ea;
+
+ switch( (modrm >> 3) & 0x7 )
+ {
+ case 0: /* SGDT */
+ {
+ if( modrm >= 0xc0 ) {
+ address = LOAD_RM32(modrm);
+ ea = i386_translate(cpustate, CS, address );
+ } else {
+ ea = GetEA(cpustate,modrm);
+ }
+ WRITE16(cpustate,ea, cpustate->gdtr.limit);
+ WRITE32(cpustate,ea + 2, cpustate->gdtr.base);
+ CYCLES(cpustate,CYCLES_SGDT);
+ break;
+ }
+ case 1: /* SIDT */
+ {
+ if (modrm >= 0xc0)
+ {
+ address = LOAD_RM32(modrm);
+ ea = i386_translate(cpustate, CS, address );
+ }
+ else
+ {
+ ea = GetEA(cpustate,modrm);
+ }
+ WRITE16(cpustate,ea, cpustate->idtr.limit);
+ WRITE32(cpustate,ea + 2, cpustate->idtr.base);
+ CYCLES(cpustate,CYCLES_SIDT);
+ break;
+ }
+ case 2: /* LGDT */
+ {
+ if( modrm >= 0xc0 ) {
+ address = LOAD_RM32(modrm);
+ ea = i386_translate(cpustate, CS, address );
+ } else {
+ ea = GetEA(cpustate,modrm);
+ }
+ cpustate->gdtr.limit = READ16(cpustate,ea);
+ cpustate->gdtr.base = READ32(cpustate,ea + 2);
+ CYCLES(cpustate,CYCLES_LGDT);
+ break;
+ }
+ case 3: /* LIDT */
+ {
+ if( modrm >= 0xc0 ) {
+ address = LOAD_RM32(modrm);
+ ea = i386_translate(cpustate, CS, address );
+ } else {
+ ea = GetEA(cpustate,modrm);
+ }
+ cpustate->idtr.limit = READ16(cpustate,ea);
+ cpustate->idtr.base = READ32(cpustate,ea + 2);
+ CYCLES(cpustate,CYCLES_LIDT);
+ break;
+ }
+ default:
+ fatalerror("i386: unimplemented opcode 0x0f 01 /%d at %08X", (modrm >> 3) & 0x7, cpustate->eip - 2);
+ break;
+ }
+}
+
+static void I386OP(group0FBA_32)(i386_state *cpustate) // Opcode 0x0f ba
+{
+ UINT8 modrm = FETCH(cpustate);
+
+ switch( (modrm >> 3) & 0x7 )
+ {
+ case 4: /* BT Rm32, i8 */
+ if( modrm >= 0xc0 ) {
+ UINT32 dst = LOAD_RM32(modrm);
+ UINT8 bit = FETCH(cpustate);
+
+ if( dst & (1 << bit) )
+ cpustate->CF = 1;
+ else
+ cpustate->CF = 0;
+
+ CYCLES(cpustate,CYCLES_BT_IMM_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT32 dst = READ32(cpustate,ea);
+ UINT8 bit = FETCH(cpustate);
+
+ if( dst & (1 << bit) )
+ cpustate->CF = 1;
+ else
+ cpustate->CF = 0;
+
+ CYCLES(cpustate,CYCLES_BT_IMM_MEM);
+ }
+ break;
+ case 5: /* BTS Rm32, i8 */
+ if( modrm >= 0xc0 ) {
+ UINT32 dst = LOAD_RM32(modrm);
+ UINT8 bit = FETCH(cpustate);
+
+ if( dst & (1 << bit) )
+ cpustate->CF = 1;
+ else
+ cpustate->CF = 0;
+ dst |= (1 << bit);
+
+ STORE_RM32(modrm, dst);
+ CYCLES(cpustate,CYCLES_BTS_IMM_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT32 dst = READ32(cpustate,ea);
+ UINT8 bit = FETCH(cpustate);
+
+ if( dst & (1 << bit) )
+ cpustate->CF = 1;
+ else
+ cpustate->CF = 0;
+ dst |= (1 << bit);
+
+ WRITE32(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_BTS_IMM_MEM);
+ }
+ break;
+ case 6: /* BTR Rm32, i8 */
+ if( modrm >= 0xc0 ) {
+ UINT32 dst = LOAD_RM32(modrm);
+ UINT8 bit = FETCH(cpustate);
+
+ if( dst & (1 << bit) )
+ cpustate->CF = 1;
+ else
+ cpustate->CF = 0;
+ dst &= ~(1 << bit);
+
+ STORE_RM32(modrm, dst);
+ CYCLES(cpustate,CYCLES_BTR_IMM_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT32 dst = READ32(cpustate,ea);
+ UINT8 bit = FETCH(cpustate);
+
+ if( dst & (1 << bit) )
+ cpustate->CF = 1;
+ else
+ cpustate->CF = 0;
+ dst &= ~(1 << bit);
+
+ WRITE32(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_BTR_IMM_MEM);
+ }
+ break;
+ case 7: /* BTC Rm32, i8 */
+ if( modrm >= 0xc0 ) {
+ UINT32 dst = LOAD_RM32(modrm);
+ UINT8 bit = FETCH(cpustate);
+
+ if( dst & (1 << bit) )
+ cpustate->CF = 1;
+ else
+ cpustate->CF = 0;
+ dst ^= (1 << bit);
+
+ STORE_RM32(modrm, dst);
+ CYCLES(cpustate,CYCLES_BTC_IMM_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT32 dst = READ32(cpustate,ea);
+ UINT8 bit = FETCH(cpustate);
+
+ if( dst & (1 << bit) )
+ cpustate->CF = 1;
+ else
+ cpustate->CF = 0;
+ dst ^= (1 << bit);
+
+ WRITE32(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_BTC_IMM_MEM);
+ }
+ break;
+ default:
+ fatalerror("i386: group0FBA_32 /%d unknown", (modrm >> 3) & 0x7);
+ break;
+ }
+}
+
+static void I386OP(lar_r32_rm32)(i386_state *cpustate) // Opcode 0x0f 0x02
+{
+ UINT8 modrm = FETCH(cpustate);
+ I386_SREG seg;
+ UINT8 type;
+
+ if(PROTECTED_MODE && !V8086_MODE)
+ {
+ memset(&seg,0,sizeof(seg));
+ if(modrm >= 0xc0)
+ {
+ seg.selector = LOAD_RM32(modrm);
+ CYCLES(cpustate,CYCLES_LAR_REG);
+ }
+ else
+ {
+ UINT32 ea = GetEA(cpustate,modrm);
+ seg.selector = READ32(cpustate,ea);
+ CYCLES(cpustate,CYCLES_LAR_MEM);
+ }
+ if(seg.selector == 0)
+ {
+ SetZF(0); // not a valid segment
+ }
+ else
+ {
+ i386_load_protected_mode_segment(cpustate,&seg);
+ if(!(seg.flags & 0x10)) // special segment
+ {
+ // check for invalid segment types
+ type = seg.flags & 0x000f;
+ if(type == 0x00 || type == 0x08 || type == 0x0a || type == 0x0d)
+ {
+ SetZF(0); // invalid segment type
+ }
+ else
+ {
+ // TODO: check current privilege level
+ STORE_REG32(modrm,(seg.flags << 8) & 0x00ffff00);
+ SetZF(1);
+ }
+ }
+ else
+ {
+ // TODO: check current privilege level
+ STORE_REG32(modrm,(seg.flags << 8) & 0x00ffff00);
+ SetZF(1);
+ }
+ }
+ }
+ else
+ {
+ // illegal opcode
+ i386_trap(cpustate,6,0, 0);
+ logerror("i386: LAR: Exception - running in real mode or virtual 8086 mode.\n");
+ }
+}
+
+static void I386OP(lsl_r32_rm32)(i386_state *cpustate) // Opcode 0x0f 0x03
+{
+ UINT8 modrm = FETCH(cpustate);
+ UINT32 limit;
+ I386_SREG seg;
+
+ if(PROTECTED_MODE)
+ {
+ memset(&seg, 0, sizeof(seg));
+ if(modrm >= 0xc0)
+ {
+ seg.selector = LOAD_RM32(modrm);
+ }
+ else
+ {
+ UINT32 ea = GetEA(cpustate,modrm);
+ seg.selector = READ32(cpustate,ea);
+ }
+ if(seg.selector == 0)
+ {
+ SetZF(0); // not a valid segment
+ }
+ else
+ {
+ // TODO: check segment type
+ i386_load_protected_mode_segment(cpustate,&seg);
+ limit = seg.limit;
+ STORE_REG32(modrm,limit);
+ SetZF(1);
+ }
+ }
+ else
+ i386_trap(cpustate,6, 0, 0);
+}
+
+static void I386OP(bound_r32_m32_m32)(i386_state *cpustate) // Opcode 0x62
+{
+ UINT8 modrm;
+ INT32 val, low, high;
+
+ modrm = FETCH(cpustate);
+
+ if (modrm >= 0xc0)
+ {
+ low = high = LOAD_RM32(modrm);
+ }
+ else
+ {
+ UINT32 ea = GetEA(cpustate,modrm);
+ low = READ32(cpustate,ea + 0);
+ high = READ32(cpustate,ea + 4);
+ }
+ val = LOAD_REG32(modrm);
+
+ if ((val < low) || (val > high))
+ {
+ CYCLES(cpustate,CYCLES_BOUND_OUT_RANGE);
+ i386_trap(cpustate,5, 0, 0);
+ }
+ else
+ {
+ CYCLES(cpustate,CYCLES_BOUND_IN_RANGE);
+ }
+}
+
+static void I386OP(retf32)(i386_state *cpustate) // Opcode 0xcb
+{
+ if(PROTECTED_MODE && !V8086_MODE)
+ {
+ i386_protected_mode_retf(cpustate,0,1);
+ }
+ else
+ {
+ cpustate->eip = POP32(cpustate);
+ cpustate->sreg[CS].selector = POP32(cpustate);
+ i386_load_segment_descriptor(cpustate, CS );
+ CHANGE_PC(cpustate,cpustate->eip);
+ }
+
+ CYCLES(cpustate,CYCLES_RET_INTERSEG);
+}
+
+static void I386OP(retf_i32)(i386_state *cpustate) // Opcode 0xca
+{
+ UINT16 count = FETCH16(cpustate);
+
+ if(PROTECTED_MODE && !V8086_MODE)
+ {
+ i386_protected_mode_retf(cpustate,count,1);
+ }
+ else
+ {
+ cpustate->eip = POP32(cpustate);
+ cpustate->sreg[CS].selector = POP32(cpustate);
+ i386_load_segment_descriptor(cpustate, CS );
+ CHANGE_PC(cpustate,cpustate->eip);
+ REG32(ESP) += count;
+ }
+
+ CYCLES(cpustate,CYCLES_RET_IMM_INTERSEG);
+}
+
+static void I386OP(xlat32)(i386_state *cpustate) // Opcode 0xd7
+{
+ UINT32 ea;
+ if( cpustate->segment_prefix ) {
+ ea = i386_translate(cpustate, cpustate->segment_override, REG32(EBX) + REG8(AL) );
+ } else {
+ ea = i386_translate(cpustate, DS, REG32(EBX) + REG8(AL) );
+ }
+ REG8(AL) = READ8(cpustate,ea);
+ CYCLES(cpustate,CYCLES_XLAT);
+}
+
+static void I386OP(load_far_pointer32)(i386_state *cpustate, int s)
+{
+ UINT8 modrm = FETCH(cpustate);
+
+ if( modrm >= 0xc0 ) {
+ fatalerror("i386: load_far_pointer32 NYI");
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ STORE_REG32(modrm, READ32(cpustate,ea + 0));
+ cpustate->sreg[s].selector = READ16(cpustate,ea + 4);
+ i386_load_segment_descriptor(cpustate, s );
+ }
+}
+
+static void I386OP(lds32)(i386_state *cpustate) // Opcode 0xc5
+{
+ I386OP(load_far_pointer32)(cpustate, DS);
+ CYCLES(cpustate,CYCLES_LDS);
+}
+
+static void I386OP(lss32)(i386_state *cpustate) // Opcode 0x0f 0xb2
+{
+ I386OP(load_far_pointer32)(cpustate, SS);
+ CYCLES(cpustate,CYCLES_LSS);
+}
+
+static void I386OP(les32)(i386_state *cpustate) // Opcode 0xc4
+{
+ I386OP(load_far_pointer32)(cpustate, ES);
+ CYCLES(cpustate,CYCLES_LES);
+}
+
+static void I386OP(lfs32)(i386_state *cpustate) // Opcode 0x0f 0xb4
+{
+ I386OP(load_far_pointer32)(cpustate, FS);
+ CYCLES(cpustate,CYCLES_LFS);
+}
+
+static void I386OP(lgs32)(i386_state *cpustate) // Opcode 0x0f 0xb5
+{
+ I386OP(load_far_pointer32)(cpustate, GS);
+ CYCLES(cpustate,CYCLES_LGS);
+}
diff --git a/trunk/src/emu/cpu/i386/i386ops.c b/trunk/src/emu/cpu/i386/i386ops.c
new file mode 100644
index 00000000000..e2b76d63ec1
--- /dev/null
+++ b/trunk/src/emu/cpu/i386/i386ops.c
@@ -0,0 +1,2400 @@
+static UINT8 I386OP(shift_rotate8)(i386_state *cpustate, UINT8 modrm, UINT32 value, UINT8 shift)
+{
+ UINT8 src = value;
+ UINT8 dst = value;
+
+ if( shift == 0 ) {
+ CYCLES_RM(cpustate,modrm, 3, 7);
+ } else if( shift == 1 ) {
+
+ switch( (modrm >> 3) & 0x7 )
+ {
+ case 0: /* ROL rm8, 1 */
+ cpustate->CF = (src & 0x80) ? 1 : 0;
+ dst = (src << 1) + cpustate->CF;
+ cpustate->OF = ((src ^ dst) & 0x80) ? 1 : 0;
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
+ break;
+ case 1: /* ROR rm8, 1 */
+ cpustate->CF = (src & 0x1) ? 1 : 0;
+ dst = (cpustate->CF << 7) | (src >> 1);
+ cpustate->OF = ((src ^ dst) & 0x80) ? 1 : 0;
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
+ break;
+ case 2: /* RCL rm8, 1 */
+ dst = (src << 1) + cpustate->CF;
+ cpustate->CF = (src & 0x80) ? 1 : 0;
+ cpustate->OF = ((src ^ dst) & 0x80) ? 1 : 0;
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
+ break;
+ case 3: /* RCR rm8, 1 */
+ dst = (cpustate->CF << 7) | (src >> 1);
+ cpustate->CF = src & 0x1;
+ cpustate->OF = ((src ^ dst) & 0x80) ? 1 : 0;
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
+ break;
+ case 4: /* SHL/SAL rm8, 1 */
+ case 6:
+ dst = src << 1;
+ cpustate->CF = (src & 0x80) ? 1 : 0;
+ cpustate->OF = (((cpustate->CF << 7) ^ dst) & 0x80) ? 1 : 0;
+ SetSZPF8(dst);
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
+ break;
+ case 5: /* SHR rm8, 1 */
+ dst = src >> 1;
+ cpustate->CF = src & 0x1;
+ cpustate->OF = (dst & 0x80) ? 1 : 0;
+ SetSZPF8(dst);
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
+ break;
+ case 7: /* SAR rm8, 1 */
+ dst = (INT8)(src) >> 1;
+ cpustate->CF = src & 0x1;
+ cpustate->OF = 0;
+ SetSZPF8(dst);
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
+ break;
+ }
+
+ } else {
+
+ switch( (modrm >> 3) & 0x7 )
+ {
+ case 0: /* ROL rm8, i8 */
+ dst = ((src & ((UINT8)0xff >> shift)) << shift) |
+ ((src & ((UINT8)0xff << (8-shift))) >> (8-shift));
+ cpustate->CF = (src >> (8-shift)) & 0x1;
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
+ break;
+ case 1: /* ROR rm8, i8 */
+ dst = ((src & ((UINT8)0xff << shift)) >> shift) |
+ ((src & ((UINT8)0xff >> (8-shift))) << (8-shift));
+ cpustate->CF = (src >> (shift-1)) & 0x1;
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
+ break;
+ case 2: /* RCL rm8, i8 */
+ dst = ((src & ((UINT8)0xff >> shift)) << shift) |
+ ((src & ((UINT8)0xff << (9-shift))) >> (9-shift)) |
+ (cpustate->CF << (shift-1));
+ cpustate->CF = (src >> (8-shift)) & 0x1;
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
+ break;
+ case 3: /* RCR rm8, i8 */
+ dst = ((src & ((UINT8)0xff << shift)) >> shift) |
+ ((src & ((UINT8)0xff >> (8-shift))) << (9-shift)) |
+ (cpustate->CF << (8-shift));
+ cpustate->CF = (src >> (shift-1)) & 0x1;
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
+ break;
+ case 4: /* SHL/SAL rm8, i8 */
+ case 6:
+ dst = src << shift;
+ cpustate->CF = (src & (1 << (8-shift))) ? 1 : 0;
+ SetSZPF8(dst);
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
+ break;
+ case 5: /* SHR rm8, i8 */
+ dst = src >> shift;
+ cpustate->CF = (src & (1 << (shift-1))) ? 1 : 0;
+ SetSZPF8(dst);
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
+ break;
+ case 7: /* SAR rm8, i8 */
+ dst = (INT8)src >> shift;
+ cpustate->CF = (src & (1 << (shift-1))) ? 1 : 0;
+ SetSZPF8(dst);
+ CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
+ break;
+ }
+ }
+
+ return dst;
+}
+
+
+
+static void I386OP(adc_rm8_r8)(i386_state *cpustate) // Opcode 0x10
+{
+ UINT8 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_REG8(modrm);
+ dst = LOAD_RM8(modrm);
+ dst = ADC8(cpustate, dst, src, cpustate->CF);
+ STORE_RM8(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = LOAD_REG8(modrm);
+ dst = READ8(cpustate,ea);
+ dst = ADC8(cpustate, dst, src, cpustate->CF);
+ WRITE8(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+}
+
+static void I386OP(adc_r8_rm8)(i386_state *cpustate) // Opcode 0x12
+{
+ UINT8 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_RM8(modrm);
+ dst = LOAD_REG8(modrm);
+ dst = ADC8(cpustate, dst, src, cpustate->CF);
+ STORE_REG8(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = READ8(cpustate,ea);
+ dst = LOAD_REG8(modrm);
+ dst = ADC8(cpustate, dst, src, cpustate->CF);
+ STORE_REG8(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_MEM_REG);
+ }
+}
+
+static void I386OP(adc_al_i8)(i386_state *cpustate) // Opcode 0x14
+{
+ UINT8 src, dst;
+ src = FETCH(cpustate);
+ dst = REG8(AL);
+ dst = ADC8(cpustate, dst, src, cpustate->CF);
+ REG8(AL) = dst;
+ CYCLES(cpustate,CYCLES_ALU_IMM_ACC);
+}
+
+static void I386OP(add_rm8_r8)(i386_state *cpustate) // Opcode 0x00
+{
+ UINT8 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_REG8(modrm);
+ dst = LOAD_RM8(modrm);
+ dst = ADD8(cpustate,dst, src);
+ STORE_RM8(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = LOAD_REG8(modrm);
+ dst = READ8(cpustate,ea);
+ dst = ADD8(cpustate,dst, src);
+ WRITE8(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+}
+
+static void I386OP(add_r8_rm8)(i386_state *cpustate) // Opcode 0x02
+{
+ UINT8 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_RM8(modrm);
+ dst = LOAD_REG8(modrm);
+ dst = ADD8(cpustate,dst, src);
+ STORE_REG8(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = READ8(cpustate,ea);
+ dst = LOAD_REG8(modrm);
+ dst = ADD8(cpustate,dst, src);
+ STORE_REG8(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_MEM_REG);
+ }
+}
+
+static void I386OP(add_al_i8)(i386_state *cpustate) // Opcode 0x04
+{
+ UINT8 src, dst;
+ src = FETCH(cpustate);
+ dst = REG8(AL);
+ dst = ADD8(cpustate,dst, src);
+ REG8(AL) = dst;
+ CYCLES(cpustate,CYCLES_ALU_IMM_ACC);
+}
+
+static void I386OP(and_rm8_r8)(i386_state *cpustate) // Opcode 0x20
+{
+ UINT8 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_REG8(modrm);
+ dst = LOAD_RM8(modrm);
+ dst = AND8(cpustate,dst, src);
+ STORE_RM8(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = LOAD_REG8(modrm);
+ dst = READ8(cpustate,ea);
+ dst = AND8(cpustate,dst, src);
+ WRITE8(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+}
+
+static void I386OP(and_r8_rm8)(i386_state *cpustate) // Opcode 0x22
+{
+ UINT8 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_RM8(modrm);
+ dst = LOAD_REG8(modrm);
+ dst = AND8(cpustate,dst, src);
+ STORE_REG8(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = READ8(cpustate,ea);
+ dst = LOAD_REG8(modrm);
+ dst = AND8(cpustate,dst, src);
+ STORE_REG8(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_MEM_REG);
+ }
+}
+
+static void I386OP(and_al_i8)(i386_state *cpustate) // Opcode 0x24
+{
+ UINT8 src, dst;
+ src = FETCH(cpustate);
+ dst = REG8(AL);
+ dst = AND8(cpustate,dst, src);
+ REG8(AL) = dst;
+ CYCLES(cpustate,CYCLES_ALU_IMM_ACC);
+}
+
+static void I386OP(clc)(i386_state *cpustate) // Opcode 0xf8
+{
+ cpustate->CF = 0;
+ CYCLES(cpustate,CYCLES_CLC);
+}
+
+static void I386OP(cld)(i386_state *cpustate) // Opcode 0xfc
+{
+ cpustate->DF = 0;
+ CYCLES(cpustate,CYCLES_CLD);
+}
+
+static void I386OP(cli)(i386_state *cpustate) // Opcode 0xfa
+{
+ cpustate->IF = 0;
+ CYCLES(cpustate,CYCLES_CLI);
+}
+
+static void I386OP(cmc)(i386_state *cpustate) // Opcode 0xf5
+{
+ cpustate->CF ^= 1;
+ CYCLES(cpustate,CYCLES_CMC);
+}
+
+static void I386OP(cmp_rm8_r8)(i386_state *cpustate) // Opcode 0x38
+{
+ UINT8 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_REG8(modrm);
+ dst = LOAD_RM8(modrm);
+ SUB8(cpustate,dst, src);
+ CYCLES(cpustate,CYCLES_CMP_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = LOAD_REG8(modrm);
+ dst = READ8(cpustate,ea);
+ SUB8(cpustate,dst, src);
+ CYCLES(cpustate,CYCLES_CMP_REG_MEM);
+ }
+}
+
+static void I386OP(cmp_r8_rm8)(i386_state *cpustate) // Opcode 0x3a
+{
+ UINT8 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_RM8(modrm);
+ dst = LOAD_REG8(modrm);
+ SUB8(cpustate,dst, src);
+ CYCLES(cpustate,CYCLES_CMP_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = READ8(cpustate,ea);
+ dst = LOAD_REG8(modrm);
+ SUB8(cpustate,dst, src);
+ CYCLES(cpustate,CYCLES_CMP_MEM_REG);
+ }
+}
+
+static void I386OP(cmp_al_i8)(i386_state *cpustate) // Opcode 0x3c
+{
+ UINT8 src, dst;
+ src = FETCH(cpustate);
+ dst = REG8(AL);
+ SUB8(cpustate,dst, src);
+ CYCLES(cpustate,CYCLES_CMP_IMM_ACC);
+}
+
+static void I386OP(cmpsb)(i386_state *cpustate) // Opcode 0xa6
+{
+ UINT32 eas, ead;
+ UINT8 src, dst;
+ if( cpustate->segment_prefix ) {
+ eas = i386_translate(cpustate, cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI) );
+ } else {
+ eas = i386_translate(cpustate, DS, cpustate->address_size ? REG32(ESI) : REG16(SI) );
+ }
+ ead = i386_translate(cpustate, ES, cpustate->address_size ? REG32(EDI) : REG16(DI) );
+ src = READ8(cpustate,eas);
+ dst = READ8(cpustate,ead);
+ SUB8(cpustate,dst, src);
+ BUMP_SI(cpustate,1);
+ BUMP_DI(cpustate,1);
+ CYCLES(cpustate,CYCLES_CMPS);
+}
+
+static void I386OP(in_al_i8)(i386_state *cpustate) // Opcode 0xe4
+{
+ UINT16 port = FETCH(cpustate);
+ UINT8 data = READPORT8(cpustate, port);
+ REG8(AL) = data;
+ CYCLES(cpustate,CYCLES_IN_VAR);
+}
+
+static void I386OP(in_al_dx)(i386_state *cpustate) // Opcode 0xec
+{
+ UINT16 port = REG16(DX);
+ UINT8 data = READPORT8(cpustate, port);
+ REG8(AL) = data;
+ CYCLES(cpustate,CYCLES_IN);
+}
+
+static void I386OP(ja_rel8)(i386_state *cpustate) // Opcode 0x77
+{
+ INT8 disp = FETCH(cpustate);
+ if( cpustate->CF == 0 && cpustate->ZF == 0 ) {
+ NEAR_BRANCH(cpustate,disp);
+ CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
+ }
+}
+
+static void I386OP(jbe_rel8)(i386_state *cpustate) // Opcode 0x76
+{
+ INT8 disp = FETCH(cpustate);
+ if( cpustate->CF != 0 || cpustate->ZF != 0 ) {
+ NEAR_BRANCH(cpustate,disp);
+ CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
+ }
+}
+
+static void I386OP(jc_rel8)(i386_state *cpustate) // Opcode 0x72
+{
+ INT8 disp = FETCH(cpustate);
+ if( cpustate->CF != 0 ) {
+ NEAR_BRANCH(cpustate,disp);
+ CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
+ }
+}
+
+static void I386OP(jg_rel8)(i386_state *cpustate) // Opcode 0x7f
+{
+ INT8 disp = FETCH(cpustate);
+ if( cpustate->ZF == 0 && (cpustate->SF == cpustate->OF) ) {
+ NEAR_BRANCH(cpustate,disp);
+ CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
+ }
+}
+
+static void I386OP(jge_rel8)(i386_state *cpustate) // Opcode 0x7d
+{
+ INT8 disp = FETCH(cpustate);
+ if( (cpustate->SF == cpustate->OF) ) {
+ NEAR_BRANCH(cpustate,disp);
+ CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
+ }
+}
+
+static void I386OP(jl_rel8)(i386_state *cpustate) // Opcode 0x7c
+{
+ INT8 disp = FETCH(cpustate);
+ if( (cpustate->SF != cpustate->OF) ) {
+ NEAR_BRANCH(cpustate,disp);
+ CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
+ }
+}
+
+static void I386OP(jle_rel8)(i386_state *cpustate) // Opcode 0x7e
+{
+ INT8 disp = FETCH(cpustate);
+ if( cpustate->ZF != 0 || (cpustate->SF != cpustate->OF) ) {
+ NEAR_BRANCH(cpustate,disp);
+ CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
+ }
+}
+
+static void I386OP(jnc_rel8)(i386_state *cpustate) // Opcode 0x73
+{
+ INT8 disp = FETCH(cpustate);
+ if( cpustate->CF == 0 ) {
+ NEAR_BRANCH(cpustate,disp);
+ CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
+ }
+}
+
+static void I386OP(jno_rel8)(i386_state *cpustate) // Opcode 0x71
+{
+ INT8 disp = FETCH(cpustate);
+ if( cpustate->OF == 0 ) {
+ NEAR_BRANCH(cpustate,disp);
+ CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
+ }
+}
+
+static void I386OP(jnp_rel8)(i386_state *cpustate) // Opcode 0x7b
+{
+ INT8 disp = FETCH(cpustate);
+ if( cpustate->PF == 0 ) {
+ NEAR_BRANCH(cpustate,disp);
+ CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
+ }
+}
+
+static void I386OP(jns_rel8)(i386_state *cpustate) // Opcode 0x79
+{
+ INT8 disp = FETCH(cpustate);
+ if( cpustate->SF == 0 ) {
+ NEAR_BRANCH(cpustate,disp);
+ CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
+ }
+}
+
+static void I386OP(jnz_rel8)(i386_state *cpustate) // Opcode 0x75
+{
+ INT8 disp = FETCH(cpustate);
+ if( cpustate->ZF == 0 ) {
+ NEAR_BRANCH(cpustate,disp);
+ CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
+ }
+}
+
+static void I386OP(jo_rel8)(i386_state *cpustate) // Opcode 0x70
+{
+ INT8 disp = FETCH(cpustate);
+ if( cpustate->OF != 0 ) {
+ NEAR_BRANCH(cpustate,disp);
+ CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
+ }
+}
+
+static void I386OP(jp_rel8)(i386_state *cpustate) // Opcode 0x7a
+{
+ INT8 disp = FETCH(cpustate);
+ if( cpustate->PF != 0 ) {
+ NEAR_BRANCH(cpustate,disp);
+ CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
+ }
+}
+
+static void I386OP(js_rel8)(i386_state *cpustate) // Opcode 0x78
+{
+ INT8 disp = FETCH(cpustate);
+ if( cpustate->SF != 0 ) {
+ NEAR_BRANCH(cpustate,disp);
+ CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
+ }
+}
+
+static void I386OP(jz_rel8)(i386_state *cpustate) // Opcode 0x74
+{
+ INT8 disp = FETCH(cpustate);
+ if( cpustate->ZF != 0 ) {
+ NEAR_BRANCH(cpustate,disp);
+ CYCLES(cpustate,CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */
+ } else {
+ CYCLES(cpustate,CYCLES_JCC_DISP8_NOBRANCH);
+ }
+}
+
+static void I386OP(jmp_rel8)(i386_state *cpustate) // Opcode 0xeb
+{
+ INT8 disp = FETCH(cpustate);
+ NEAR_BRANCH(cpustate,disp);
+ CYCLES(cpustate,CYCLES_JMP_SHORT); /* TODO: Timing = 7 + m */
+}
+
+static void I386OP(lahf)(i386_state *cpustate) // Opcode 0x9f
+{
+ REG8(AH) = get_flags(cpustate) & 0xd7;
+ CYCLES(cpustate,CYCLES_LAHF);
+}
+
+static void I386OP(lodsb)(i386_state *cpustate) // Opcode 0xac
+{
+ UINT32 eas;
+ if( cpustate->segment_prefix ) {
+ eas = i386_translate(cpustate, cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI) );
+ } else {
+ eas = i386_translate(cpustate, DS, cpustate->address_size ? REG32(ESI) : REG16(SI) );
+ }
+ REG8(AL) = READ8(cpustate,eas);
+ BUMP_SI(cpustate,1);
+ CYCLES(cpustate,CYCLES_LODS);
+}
+
+static void I386OP(mov_rm8_r8)(i386_state *cpustate) // Opcode 0x88
+{
+ UINT8 src;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_REG8(modrm);
+ STORE_RM8(modrm, src);
+ CYCLES(cpustate,CYCLES_MOV_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = LOAD_REG8(modrm);
+ WRITE8(cpustate,ea, src);
+ CYCLES(cpustate,CYCLES_MOV_REG_MEM);
+ }
+}
+
+static void I386OP(mov_r8_rm8)(i386_state *cpustate) // Opcode 0x8a
+{
+ UINT8 src;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_RM8(modrm);
+ STORE_REG8(modrm, src);
+ CYCLES(cpustate,CYCLES_MOV_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = READ8(cpustate,ea);
+ STORE_REG8(modrm, src);
+ CYCLES(cpustate,CYCLES_MOV_MEM_REG);
+ }
+}
+
+static void I386OP(mov_rm8_i8)(i386_state *cpustate) // Opcode 0xc6
+{
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ UINT8 value = FETCH(cpustate);
+ STORE_RM8(modrm, value);
+ CYCLES(cpustate,CYCLES_MOV_IMM_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT8 value = FETCH(cpustate);
+ WRITE8(cpustate,ea, value);
+ CYCLES(cpustate,CYCLES_MOV_IMM_MEM);
+ }
+}
+
+static void I386OP(mov_r32_cr)(i386_state *cpustate) // Opcode 0x0f 20
+{
+ UINT8 modrm = FETCH(cpustate);
+ UINT8 cr = (modrm >> 3) & 0x7;
+
+ STORE_RM32(modrm, cpustate->cr[cr]);
+ CYCLES(cpustate,CYCLES_MOV_CR_REG);
+}
+
+static void I386OP(mov_r32_dr)(i386_state *cpustate) // Opcode 0x0f 21
+{
+ UINT8 modrm = FETCH(cpustate);
+ UINT8 dr = (modrm >> 3) & 0x7;
+
+ STORE_RM32(modrm, cpustate->dr[dr]);
+ switch(dr)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ CYCLES(cpustate,CYCLES_MOV_REG_DR0_3);
+ break;
+ case 6:
+ case 7:
+ CYCLES(cpustate,CYCLES_MOV_REG_DR6_7);
+ break;
+ }
+}
+
+static void I386OP(mov_cr_r32)(i386_state *cpustate) // Opcode 0x0f 22
+{
+ UINT8 modrm = FETCH(cpustate);
+ UINT8 cr = (modrm >> 3) & 0x7;
+
+ cpustate->cr[cr] = LOAD_RM32(modrm);
+ switch(cr)
+ {
+ case 0: CYCLES(cpustate,CYCLES_MOV_REG_CR0); break;
+ case 2: CYCLES(cpustate,CYCLES_MOV_REG_CR2); break;
+ case 3: CYCLES(cpustate,CYCLES_MOV_REG_CR3); break;
+ case 4: CYCLES(cpustate,1); break; // TODO
+ default:
+ fatalerror("i386: mov_cr_r32 CR%d !", cr);
+ break;
+ }
+}
+
+static void I386OP(mov_dr_r32)(i386_state *cpustate) // Opcode 0x0f 23
+{
+ UINT8 modrm = FETCH(cpustate);
+ UINT8 dr = (modrm >> 3) & 0x7;
+
+ cpustate->dr[dr] = LOAD_RM32(modrm);
+ switch(dr)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ CYCLES(cpustate,CYCLES_MOV_DR0_3_REG);
+ break;
+ case 6:
+ case 7:
+ CYCLES(cpustate,CYCLES_MOV_DR6_7_REG);
+ break;
+ default:
+ fatalerror("i386: mov_dr_r32 DR%d !", dr);
+ break;
+ }
+}
+
+static void I386OP(mov_al_m8)(i386_state *cpustate) // Opcode 0xa0
+{
+ UINT32 offset, ea;
+ if( cpustate->address_size ) {
+ offset = FETCH32(cpustate);
+ } else {
+ offset = FETCH16(cpustate);
+ }
+ /* TODO: Not sure if this is correct... */
+ if( cpustate->segment_prefix ) {
+ ea = i386_translate(cpustate, cpustate->segment_override, offset );
+ } else {
+ ea = i386_translate(cpustate, DS, offset );
+ }
+ REG8(AL) = READ8(cpustate,ea);
+ CYCLES(cpustate,CYCLES_MOV_IMM_MEM);
+}
+
+static void I386OP(mov_m8_al)(i386_state *cpustate) // Opcode 0xa2
+{
+ UINT32 offset, ea;
+ if( cpustate->address_size ) {
+ offset = FETCH32(cpustate);
+ } else {
+ offset = FETCH16(cpustate);
+ }
+ /* TODO: Not sure if this is correct... */
+ if( cpustate->segment_prefix ) {
+ ea = i386_translate(cpustate, cpustate->segment_override, offset );
+ } else {
+ ea = i386_translate(cpustate, DS, offset );
+ }
+ WRITE8(cpustate, ea, REG8(AL) );
+ CYCLES(cpustate,CYCLES_MOV_MEM_ACC);
+}
+
+static void I386OP(mov_rm16_sreg)(i386_state *cpustate) // Opcode 0x8c
+{
+ UINT8 modrm = FETCH(cpustate);
+ int s = (modrm >> 3) & 0x7;
+
+ if( modrm >= 0xc0 ) {
+ STORE_RM16(modrm, cpustate->sreg[s].selector);
+ CYCLES(cpustate,CYCLES_MOV_SREG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ WRITE16(cpustate,ea, cpustate->sreg[s].selector);
+ CYCLES(cpustate,CYCLES_MOV_SREG_MEM);
+ }
+}
+
+static void I386OP(mov_sreg_rm16)(i386_state *cpustate) // Opcode 0x8e
+{
+ UINT16 selector;
+ UINT8 modrm = FETCH(cpustate);
+ int s = (modrm >> 3) & 0x7;
+
+ if( modrm >= 0xc0 ) {
+ selector = LOAD_RM16(modrm);
+ CYCLES(cpustate,CYCLES_MOV_REG_SREG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ selector = READ16(cpustate,ea);
+ CYCLES(cpustate,CYCLES_MOV_MEM_SREG);
+ }
+
+ if(s == SS)
+ {
+ if(cpustate->IF != 0) // if external interrupts are enabled
+ {
+ cpustate->IF = 0; // reset IF for the next instruction
+ cpustate->delayed_interrupt_enable = 1;
+ }
+ }
+
+ cpustate->sreg[s].selector = selector;
+ i386_load_segment_descriptor(cpustate, s );
+}
+
+static void I386OP(mov_al_i8)(i386_state *cpustate) // Opcode 0xb0
+{
+ REG8(AL) = FETCH(cpustate);
+ CYCLES(cpustate,CYCLES_MOV_IMM_REG);
+}
+
+static void I386OP(mov_cl_i8)(i386_state *cpustate) // Opcode 0xb1
+{
+ REG8(CL) = FETCH(cpustate);
+ CYCLES(cpustate,CYCLES_MOV_IMM_REG);
+}
+
+static void I386OP(mov_dl_i8)(i386_state *cpustate) // Opcode 0xb2
+{
+ REG8(DL) = FETCH(cpustate);
+ CYCLES(cpustate,CYCLES_MOV_IMM_REG);
+}
+
+static void I386OP(mov_bl_i8)(i386_state *cpustate) // Opcode 0xb3
+{
+ REG8(BL) = FETCH(cpustate);
+ CYCLES(cpustate,CYCLES_MOV_IMM_REG);
+}
+
+static void I386OP(mov_ah_i8)(i386_state *cpustate) // Opcode 0xb4
+{
+ REG8(AH) = FETCH(cpustate);
+ CYCLES(cpustate,CYCLES_MOV_IMM_REG);
+}
+
+static void I386OP(mov_ch_i8)(i386_state *cpustate) // Opcode 0xb5
+{
+ REG8(CH) = FETCH(cpustate);
+ CYCLES(cpustate,CYCLES_MOV_IMM_REG);
+}
+
+static void I386OP(mov_dh_i8)(i386_state *cpustate) // Opcode 0xb6
+{
+ REG8(DH) = FETCH(cpustate);
+ CYCLES(cpustate,CYCLES_MOV_IMM_REG);
+}
+
+static void I386OP(mov_bh_i8)(i386_state *cpustate) // Opcode 0xb7
+{
+ REG8(BH) = FETCH(cpustate);
+ CYCLES(cpustate,CYCLES_MOV_IMM_REG);
+}
+
+static void I386OP(movsb)(i386_state *cpustate) // Opcode 0xa4
+{
+ UINT32 eas, ead;
+ UINT8 v;
+ if( cpustate->segment_prefix ) {
+ eas = i386_translate(cpustate, cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI) );
+ } else {
+ eas = i386_translate(cpustate, DS, cpustate->address_size ? REG32(ESI) : REG16(SI) );
+ }
+ ead = i386_translate(cpustate, ES, cpustate->address_size ? REG32(EDI) : REG16(DI) );
+ v = READ8(cpustate,eas);
+ WRITE8(cpustate,ead, v);
+ BUMP_SI(cpustate,1);
+ BUMP_DI(cpustate,1);
+ CYCLES(cpustate,CYCLES_MOVS);
+}
+
+static void I386OP(or_rm8_r8)(i386_state *cpustate) // Opcode 0x08
+{
+ UINT8 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_REG8(modrm);
+ dst = LOAD_RM8(modrm);
+ dst = OR8(cpustate,dst, src);
+ STORE_RM8(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = LOAD_REG8(modrm);
+ dst = READ8(cpustate,ea);
+ dst = OR8(cpustate,dst, src);
+ WRITE8(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+}
+
+static void I386OP(or_r8_rm8)(i386_state *cpustate) // Opcode 0x0a
+{
+ UINT8 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_RM8(modrm);
+ dst = LOAD_REG8(modrm);
+ dst = OR8(cpustate,dst, src);
+ STORE_REG8(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = READ8(cpustate,ea);
+ dst = LOAD_REG8(modrm);
+ dst = OR8(cpustate,dst, src);
+ STORE_REG8(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_MEM_REG);
+ }
+}
+
+static void I386OP(or_al_i8)(i386_state *cpustate) // Opcode 0x0c
+{
+ UINT8 src, dst;
+ src = FETCH(cpustate);
+ dst = REG8(AL);
+ dst = OR8(cpustate,dst, src);
+ REG8(EAX) = dst;
+ CYCLES(cpustate,CYCLES_ALU_IMM_ACC);
+}
+
+static void I386OP(out_al_i8)(i386_state *cpustate) // Opcode 0xe6
+{
+ UINT16 port = FETCH(cpustate);
+ UINT8 data = REG8(AL);
+ WRITEPORT8(cpustate, port, data);
+ CYCLES(cpustate,CYCLES_OUT_VAR);
+}
+
+static void I386OP(out_al_dx)(i386_state *cpustate) // Opcode 0xee
+{
+ UINT16 port = REG16(DX);
+ UINT8 data = REG8(AL);
+ WRITEPORT8(cpustate, port, data);
+ CYCLES(cpustate,CYCLES_OUT);
+}
+
+
+static void I386OP(arpl)(i386_state *cpustate) // Opcode 0x63
+{
+ UINT16 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ UINT8 flag = 0;
+
+ if( modrm >= 0xc0 ) {
+ src = LOAD_REG16(modrm);
+ dst = LOAD_RM16(modrm);
+ if( (dst&0x3) < (src&0x3) ) {
+ dst = (dst&0xfffc) | (src&0x3);
+ flag = 1;
+ STORE_RM16(modrm, dst);
+ }
+ } else {
+ UINT32 ea = GetEA(cpustate, modrm);
+ src = LOAD_REG16(modrm);
+ dst = READ16(cpustate, ea);
+ if( (dst&0x3) < (src&0x3) ) {
+ dst = (dst&0xfffc) | (src&0x3);
+ flag = 1;
+ WRITE16(cpustate, ea, dst);
+ }
+ }
+ SetZF(flag);
+}
+
+static void I386OP(push_i8)(i386_state *cpustate) // Opcode 0x6a
+{
+ UINT8 value = FETCH(cpustate);
+ PUSH8(cpustate,value);
+ CYCLES(cpustate,CYCLES_PUSH_IMM);
+}
+
+static void I386OP(ins_generic)(i386_state *cpustate, int size)
+{
+ UINT32 ead;
+ UINT8 vb;
+ UINT16 vw;
+ UINT32 vd;
+
+ ead = i386_translate(cpustate, ES, cpustate->address_size ? REG32(EDI) : REG16(DI) );
+
+ switch(size) {
+ case 1:
+ vb = READPORT8(cpustate, REG16(DX));
+ WRITE8(cpustate,ead, vb);
+ break;
+ case 2:
+ vw = READPORT16(cpustate, REG16(DX));
+ WRITE16(cpustate,ead, vw);
+ break;
+ case 4:
+ vd = READPORT32(cpustate, REG16(DX));
+ WRITE32(cpustate,ead, vd);
+ break;
+ }
+
+ if(cpustate->address_size)
+ REG32(EDI) += ((cpustate->DF) ? -1 : 1) * size;
+ else
+ REG16(DI) += ((cpustate->DF) ? -1 : 1) * size;
+ CYCLES(cpustate,CYCLES_INS); // TODO: Confirm this value
+}
+
+static void I386OP(insb)(i386_state *cpustate) // Opcode 0x6c
+{
+ I386OP(ins_generic)(cpustate, 1);
+}
+
+static void I386OP(insw)(i386_state *cpustate) // Opcode 0x6d
+{
+ I386OP(ins_generic)(cpustate, 2);
+}
+
+static void I386OP(insd)(i386_state *cpustate) // Opcode 0x6d
+{
+ I386OP(ins_generic)(cpustate, 4);
+}
+
+static void I386OP(outs_generic)(i386_state *cpustate, int size)
+{
+ UINT32 eas;
+ UINT8 vb;
+ UINT16 vw;
+ UINT32 vd;
+
+ if( cpustate->segment_prefix ) {
+ eas = i386_translate(cpustate, cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI) );
+ } else {
+ eas = i386_translate(cpustate, DS, cpustate->address_size ? REG32(ESI) : REG16(SI) );
+ }
+
+ switch(size) {
+ case 1:
+ vb = READ8(cpustate,eas);
+ WRITEPORT8(cpustate, REG16(DX), vb);
+ break;
+ case 2:
+ vw = READ16(cpustate,eas);
+ WRITEPORT16(cpustate, REG16(DX), vw);
+ break;
+ case 4:
+ vd = READ32(cpustate,eas);
+ WRITEPORT32(cpustate, REG16(DX), vd);
+ break;
+ }
+
+ if(cpustate->address_size)
+ REG32(ESI) += ((cpustate->DF) ? -1 : 1) * size;
+ else
+ REG16(SI) += ((cpustate->DF) ? -1 : 1) * size;
+ CYCLES(cpustate,CYCLES_OUTS); // TODO: Confirm this value
+}
+
+static void I386OP(outsb)(i386_state *cpustate) // Opcode 0x6e
+{
+ I386OP(outs_generic)(cpustate, 1);
+}
+
+static void I386OP(outsw)(i386_state *cpustate) // Opcode 0x6f
+{
+ I386OP(outs_generic)(cpustate, 2);
+}
+
+static void I386OP(outsd)(i386_state *cpustate) // Opcode 0x6f
+{
+ I386OP(outs_generic)(cpustate, 4);
+}
+
+static void I386OP(repeat)(i386_state *cpustate, int invert_flag)
+{
+ UINT32 repeated_eip = cpustate->eip;
+ UINT32 repeated_pc = cpustate->pc;
+ UINT8 opcode; // = FETCH(cpustate);
+// UINT32 eas, ead;
+ UINT32 count;
+ INT32 cycle_base = 0, cycle_adjustment = 0;
+ UINT8 prefix_flag=1;
+ UINT8 *flag = NULL;
+
+
+ do {
+ repeated_eip = cpustate->eip;
+ repeated_pc = cpustate->pc;
+ opcode = FETCH(cpustate);
+ switch(opcode) {
+ case 0x26:
+ cpustate->segment_override=ES;
+ cpustate->segment_prefix=1;
+ break;
+ case 0x2e:
+ cpustate->segment_override=CS;
+ cpustate->segment_prefix=1;
+ break;
+ case 0x36:
+ cpustate->segment_override=SS;
+ cpustate->segment_prefix=1;
+ break;
+ case 0x3e:
+ cpustate->segment_override=DS;
+ cpustate->segment_prefix=1;
+ break;
+ case 0x64:
+ cpustate->segment_override=FS;
+ cpustate->segment_prefix=1;
+ break;
+ case 0x65:
+ cpustate->segment_override=GS;
+ cpustate->segment_prefix=1;
+ break;
+ case 0x66:
+ cpustate->operand_size ^= 1;
+ break;
+ case 0x67:
+ cpustate->address_size ^= 1;
+ break;
+ default:
+ prefix_flag=0;
+ }
+ } while (prefix_flag);
+
+
+ if( cpustate->segment_prefix ) {
+ // FIXME: the following does not work if both address override and segment override are used
+ i386_translate(cpustate, cpustate->segment_override, cpustate->sreg[cpustate->segment_prefix].d ? REG32(ESI) : REG16(SI) );
+ } else {
+ //eas =
+ i386_translate(cpustate, DS, cpustate->address_size ? REG32(ESI) : REG16(SI) );
+ }
+ i386_translate(cpustate, ES, cpustate->address_size ? REG32(EDI) : REG16(DI) );
+
+ switch(opcode)
+ {
+ case 0x6c:
+ case 0x6d:
+ /* INSB, INSW, INSD */
+ // TODO: cycle count
+ cycle_base = 8;
+ cycle_adjustment = -4;
+ flag = NULL;
+ break;
+
+ case 0x6e:
+ case 0x6f:
+ /* OUTSB, OUTSW, OUTSD */
+ // TODO: cycle count
+ cycle_base = 8;
+ cycle_adjustment = -4;
+ flag = NULL;
+ break;
+
+ case 0xa4:
+ case 0xa5:
+ /* MOVSB, MOVSW, MOVSD */
+ cycle_base = 8;
+ cycle_adjustment = -4;
+ flag = NULL;
+ break;
+
+ case 0xa6:
+ case 0xa7:
+ /* CMPSB, CMPSW, CMPSD */
+ cycle_base = 5;
+ cycle_adjustment = -1;
+ flag = &cpustate->ZF;
+ break;
+
+ case 0xac:
+ case 0xad:
+ /* LODSB, LODSW, LODSD */
+ cycle_base = 5;
+ cycle_adjustment = 1;
+ flag = NULL;
+ break;
+
+ case 0xaa:
+ case 0xab:
+ /* STOSB, STOSW, STOSD */
+ cycle_base = 5;
+ cycle_adjustment = 0;
+ flag = NULL;
+ break;
+
+ case 0xae:
+ case 0xaf:
+ /* SCASB, SCASW, SCASD */
+ cycle_base = 5;
+ cycle_adjustment = 0;
+ flag = &cpustate->ZF;
+ break;
+
+ default:
+ fatalerror("i386: Invalid REP/opcode %02X combination",opcode);
+ break;
+ }
+
+ if( cpustate->address_size ) {
+ if( REG32(ECX) == 0 )
+ return;
+ } else {
+ if( REG16(CX) == 0 )
+ return;
+ }
+
+ /* now actually perform the repeat */
+ CYCLES_NUM(cycle_base);
+ do
+ {
+ cpustate->eip = repeated_eip;
+ cpustate->pc = repeated_pc;
+ I386OP(decode_opcode)(cpustate);
+ CYCLES_NUM(cycle_adjustment);
+
+ if (cpustate->address_size)
+ count = --REG32(ECX);
+ else
+ count = --REG16(CX);
+ if (cpustate->cycles <= 0)
+ goto outofcycles;
+ }
+ while( count && (!flag || (invert_flag ? !*flag : *flag)) );
+ return;
+
+outofcycles:
+ /* if we run out of cycles to execute, and we are still in the repeat, we need
+ * to exit this instruction in such a way to go right back into it when we have
+ * time to execute cycles */
+ cpustate->eip = cpustate->prev_eip;
+ CHANGE_PC(cpustate,cpustate->eip);
+ CYCLES_NUM(-cycle_base);
+}
+
+static void I386OP(rep)(i386_state *cpustate) // Opcode 0xf3
+{
+ I386OP(repeat)(cpustate, 0);
+}
+
+static void I386OP(repne)(i386_state *cpustate) // Opcode 0xf2
+{
+ I386OP(repeat)(cpustate, 1);
+}
+
+static void I386OP(sahf)(i386_state *cpustate) // Opcode 0x9e
+{
+ set_flags(cpustate, (get_flags(cpustate) & 0xffffff00) | (REG8(AH) & 0xd7) );
+ CYCLES(cpustate,CYCLES_SAHF);
+}
+
+static void I386OP(sbb_rm8_r8)(i386_state *cpustate) // Opcode 0x18
+{
+ UINT8 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_REG8(modrm);
+ dst = LOAD_RM8(modrm);
+ dst = SBB8(cpustate, dst, src, cpustate->CF);
+ STORE_RM8(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = LOAD_REG8(modrm);
+ dst = READ8(cpustate,ea);
+ dst = SBB8(cpustate, dst, src, cpustate->CF);
+ WRITE8(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+}
+
+static void I386OP(sbb_r8_rm8)(i386_state *cpustate) // Opcode 0x1a
+{
+ UINT8 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_RM8(modrm);
+ dst = LOAD_REG8(modrm);
+ dst = SBB8(cpustate, dst, src, cpustate->CF);
+ STORE_REG8(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = READ8(cpustate,ea);
+ dst = LOAD_REG8(modrm);
+ dst = SBB8(cpustate, dst, src, cpustate->CF);
+ STORE_REG8(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_MEM_REG);
+ }
+}
+
+static void I386OP(sbb_al_i8)(i386_state *cpustate) // Opcode 0x1c
+{
+ UINT8 src, dst;
+ src = FETCH(cpustate);
+ dst = REG8(AL);
+ dst = SBB8(cpustate, dst, src, cpustate->CF);
+ REG8(EAX) = dst;
+ CYCLES(cpustate,CYCLES_ALU_IMM_ACC);
+}
+
+static void I386OP(scasb)(i386_state *cpustate) // Opcode 0xae
+{
+ UINT32 eas;
+ UINT8 src, dst;
+ eas = i386_translate(cpustate, ES, cpustate->address_size ? REG32(EDI) : REG16(DI) );
+ src = READ8(cpustate,eas);
+ dst = REG8(AL);
+ SUB8(cpustate,dst, src);
+ BUMP_DI(cpustate,1);
+ CYCLES(cpustate,CYCLES_SCAS);
+}
+
+static void I386OP(setalc)(i386_state *cpustate) // Opcode 0xd6 (undocumented)
+{
+ if( cpustate->CF ) {
+ REG8(AL) = 0xff;
+ } else {
+ REG8(AL) = 0;
+ }
+ CYCLES(cpustate,3);
+}
+
+static void I386OP(seta_rm8)(i386_state *cpustate) // Opcode 0x0f 97
+{
+ UINT8 modrm = FETCH(cpustate);
+ UINT8 value = 0;
+ if( cpustate->CF == 0 && cpustate->ZF == 0 ) {
+ value = 1;
+ }
+ if( modrm >= 0xc0 ) {
+ STORE_RM8(modrm, value);
+ CYCLES(cpustate,CYCLES_SETCC_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ WRITE8(cpustate,ea, value);
+ CYCLES(cpustate,CYCLES_SETCC_MEM);
+ }
+}
+
+static void I386OP(setbe_rm8)(i386_state *cpustate) // Opcode 0x0f 96
+{
+ UINT8 modrm = FETCH(cpustate);
+ UINT8 value = 0;
+ if( cpustate->CF != 0 || cpustate->ZF != 0 ) {
+ value = 1;
+ }
+ if( modrm >= 0xc0 ) {
+ STORE_RM8(modrm, value);
+ CYCLES(cpustate,CYCLES_SETCC_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ WRITE8(cpustate,ea, value);
+ CYCLES(cpustate,CYCLES_SETCC_MEM);
+ }
+}
+
+static void I386OP(setc_rm8)(i386_state *cpustate) // Opcode 0x0f 92
+{
+ UINT8 modrm = FETCH(cpustate);
+ UINT8 value = 0;
+ if( cpustate->CF != 0 ) {
+ value = 1;
+ }
+ if( modrm >= 0xc0 ) {
+ STORE_RM8(modrm, value);
+ CYCLES(cpustate,CYCLES_SETCC_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ WRITE8(cpustate,ea, value);
+ CYCLES(cpustate,CYCLES_SETCC_MEM);
+ }
+}
+
+static void I386OP(setg_rm8)(i386_state *cpustate) // Opcode 0x0f 9f
+{
+ UINT8 modrm = FETCH(cpustate);
+ UINT8 value = 0;
+ if( cpustate->ZF == 0 && (cpustate->SF == cpustate->OF) ) {
+ value = 1;
+ }
+ if( modrm >= 0xc0 ) {
+ STORE_RM8(modrm, value);
+ CYCLES(cpustate,CYCLES_SETCC_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ WRITE8(cpustate,ea, value);
+ CYCLES(cpustate,CYCLES_SETCC_MEM);
+ }
+}
+
+static void I386OP(setge_rm8)(i386_state *cpustate) // Opcode 0x0f 9d
+{
+ UINT8 modrm = FETCH(cpustate);
+ UINT8 value = 0;
+ if( (cpustate->SF == cpustate->OF) ) {
+ value = 1;
+ }
+ if( modrm >= 0xc0 ) {
+ STORE_RM8(modrm, value);
+ CYCLES(cpustate,CYCLES_SETCC_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ WRITE8(cpustate,ea, value);
+ CYCLES(cpustate,CYCLES_SETCC_MEM);
+ }
+}
+
+static void I386OP(setl_rm8)(i386_state *cpustate) // Opcode 0x0f 9c
+{
+ UINT8 modrm = FETCH(cpustate);
+ UINT8 value = 0;
+ if( cpustate->SF != cpustate->OF ) {
+ value = 1;
+ }
+ if( modrm >= 0xc0 ) {
+ STORE_RM8(modrm, value);
+ CYCLES(cpustate,CYCLES_SETCC_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ WRITE8(cpustate,ea, value);
+ CYCLES(cpustate,CYCLES_SETCC_MEM);
+ }
+}
+
+static void I386OP(setle_rm8)(i386_state *cpustate) // Opcode 0x0f 9e
+{
+ UINT8 modrm = FETCH(cpustate);
+ UINT8 value = 0;
+ if( cpustate->ZF != 0 || (cpustate->SF != cpustate->OF) ) {
+ value = 1;
+ }
+ if( modrm >= 0xc0 ) {
+ STORE_RM8(modrm, value);
+ CYCLES(cpustate,CYCLES_SETCC_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ WRITE8(cpustate,ea, value);
+ CYCLES(cpustate,CYCLES_SETCC_MEM);
+ }
+}
+
+static void I386OP(setnc_rm8)(i386_state *cpustate) // Opcode 0x0f 93
+{
+ UINT8 modrm = FETCH(cpustate);
+ UINT8 value = 0;
+ if( cpustate->CF == 0 ) {
+ value = 1;
+ }
+ if( modrm >= 0xc0 ) {
+ STORE_RM8(modrm, value);
+ CYCLES(cpustate,CYCLES_SETCC_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ WRITE8(cpustate,ea, value);
+ CYCLES(cpustate,CYCLES_SETCC_MEM);
+ }
+}
+
+static void I386OP(setno_rm8)(i386_state *cpustate) // Opcode 0x0f 91
+{
+ UINT8 modrm = FETCH(cpustate);
+ UINT8 value = 0;
+ if( cpustate->OF == 0 ) {
+ value = 1;
+ }
+ if( modrm >= 0xc0 ) {
+ STORE_RM8(modrm, value);
+ CYCLES(cpustate,CYCLES_SETCC_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ WRITE8(cpustate,ea, value);
+ CYCLES(cpustate,CYCLES_SETCC_MEM);
+ }
+}
+
+static void I386OP(setnp_rm8)(i386_state *cpustate) // Opcode 0x0f 9b
+{
+ UINT8 modrm = FETCH(cpustate);
+ UINT8 value = 0;
+ if( cpustate->PF == 0 ) {
+ value = 1;
+ }
+ if( modrm >= 0xc0 ) {
+ STORE_RM8(modrm, value);
+ CYCLES(cpustate,CYCLES_SETCC_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ WRITE8(cpustate,ea, value);
+ CYCLES(cpustate,CYCLES_SETCC_MEM);
+ }
+}
+
+static void I386OP(setns_rm8)(i386_state *cpustate) // Opcode 0x0f 99
+{
+ UINT8 modrm = FETCH(cpustate);
+ UINT8 value = 0;
+ if( cpustate->SF == 0 ) {
+ value = 1;
+ }
+ if( modrm >= 0xc0 ) {
+ STORE_RM8(modrm, value);
+ CYCLES(cpustate,CYCLES_SETCC_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ WRITE8(cpustate,ea, value);
+ CYCLES(cpustate,CYCLES_SETCC_MEM);
+ }
+}
+
+static void I386OP(setnz_rm8)(i386_state *cpustate) // Opcode 0x0f 95
+{
+ UINT8 modrm = FETCH(cpustate);
+ UINT8 value = 0;
+ if( cpustate->ZF == 0 ) {
+ value = 1;
+ }
+ if( modrm >= 0xc0 ) {
+ STORE_RM8(modrm, value);
+ CYCLES(cpustate,CYCLES_SETCC_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ WRITE8(cpustate,ea, value);
+ CYCLES(cpustate,CYCLES_SETCC_MEM);
+ }
+}
+
+static void I386OP(seto_rm8)(i386_state *cpustate) // Opcode 0x0f 90
+{
+ UINT8 modrm = FETCH(cpustate);
+ UINT8 value = 0;
+ if( cpustate->OF != 0 ) {
+ value = 1;
+ }
+ if( modrm >= 0xc0 ) {
+ STORE_RM8(modrm, value);
+ CYCLES(cpustate,CYCLES_SETCC_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ WRITE8(cpustate,ea, value);
+ CYCLES(cpustate,CYCLES_SETCC_MEM);
+ }
+}
+
+static void I386OP(setp_rm8)(i386_state *cpustate) // Opcode 0x0f 9a
+{
+ UINT8 modrm = FETCH(cpustate);
+ UINT8 value = 0;
+ if( cpustate->PF != 0 ) {
+ value = 1;
+ }
+ if( modrm >= 0xc0 ) {
+ STORE_RM8(modrm, value);
+ CYCLES(cpustate,CYCLES_SETCC_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ WRITE8(cpustate,ea, value);
+ CYCLES(cpustate,CYCLES_SETCC_MEM);
+ }
+}
+
+static void I386OP(sets_rm8)(i386_state *cpustate) // Opcode 0x0f 98
+{
+ UINT8 modrm = FETCH(cpustate);
+ UINT8 value = 0;
+ if( cpustate->SF != 0 ) {
+ value = 1;
+ }
+ if( modrm >= 0xc0 ) {
+ STORE_RM8(modrm, value);
+ CYCLES(cpustate,CYCLES_SETCC_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ WRITE8(cpustate,ea, value);
+ CYCLES(cpustate,CYCLES_SETCC_MEM);
+ }
+}
+
+static void I386OP(setz_rm8)(i386_state *cpustate) // Opcode 0x0f 94
+{
+ UINT8 modrm = FETCH(cpustate);
+ UINT8 value = 0;
+ if( cpustate->ZF != 0 ) {
+ value = 1;
+ }
+ if( modrm >= 0xc0 ) {
+ STORE_RM8(modrm, value);
+ CYCLES(cpustate,CYCLES_SETCC_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ WRITE8(cpustate,ea, value);
+ CYCLES(cpustate,CYCLES_SETCC_MEM);
+ }
+}
+
+static void I386OP(stc)(i386_state *cpustate) // Opcode 0xf9
+{
+ cpustate->CF = 1;
+ CYCLES(cpustate,CYCLES_STC);
+}
+
+static void I386OP(std)(i386_state *cpustate) // Opcode 0xfd
+{
+ cpustate->DF = 1;
+ CYCLES(cpustate,CYCLES_STD);
+}
+
+static void I386OP(sti)(i386_state *cpustate) // Opcode 0xfb
+{
+ cpustate->delayed_interrupt_enable = 1; // IF is set after the next instruction.
+ CYCLES(cpustate,CYCLES_STI);
+}
+
+static void I386OP(stosb)(i386_state *cpustate) // Opcode 0xaa
+{
+ UINT32 ead;
+ ead = i386_translate(cpustate, ES, cpustate->address_size ? REG32(EDI) : REG16(DI) );
+ WRITE8(cpustate,ead, REG8(AL));
+ BUMP_DI(cpustate,1);
+ CYCLES(cpustate,CYCLES_STOS);
+}
+
+static void I386OP(sub_rm8_r8)(i386_state *cpustate) // Opcode 0x28
+{
+ UINT8 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_REG8(modrm);
+ dst = LOAD_RM8(modrm);
+ dst = SUB8(cpustate,dst, src);
+ STORE_RM8(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = LOAD_REG8(modrm);
+ dst = READ8(cpustate,ea);
+ dst = SUB8(cpustate,dst, src);
+ WRITE8(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+}
+
+static void I386OP(sub_r8_rm8)(i386_state *cpustate) // Opcode 0x2a
+{
+ UINT8 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_RM8(modrm);
+ dst = LOAD_REG8(modrm);
+ dst = SUB8(cpustate,dst, src);
+ STORE_REG8(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = READ8(cpustate,ea);
+ dst = LOAD_REG8(modrm);
+ dst = SUB8(cpustate,dst, src);
+ STORE_REG8(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_MEM_REG);
+ }
+}
+
+static void I386OP(sub_al_i8)(i386_state *cpustate) // Opcode 0x2c
+{
+ UINT8 src, dst;
+ src = FETCH(cpustate);
+ dst = REG8(EAX);
+ dst = SUB8(cpustate,dst, src);
+ REG8(EAX) = dst;
+ CYCLES(cpustate,CYCLES_ALU_IMM_ACC);
+}
+
+static void I386OP(test_al_i8)(i386_state *cpustate) // Opcode 0xa8
+{
+ UINT8 src = FETCH(cpustate);
+ UINT8 dst = REG8(AL);
+ dst = src & dst;
+ SetSZPF8(dst);
+ cpustate->CF = 0;
+ cpustate->OF = 0;
+ CYCLES(cpustate,CYCLES_ALU_IMM_ACC);
+}
+
+static void I386OP(test_rm8_r8)(i386_state *cpustate) // Opcode 0x84
+{
+ UINT8 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_REG8(modrm);
+ dst = LOAD_RM8(modrm);
+ dst = src & dst;
+ SetSZPF8(dst);
+ cpustate->CF = 0;
+ cpustate->OF = 0;
+ CYCLES(cpustate,CYCLES_TEST_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = LOAD_REG8(modrm);
+ dst = READ8(cpustate,ea);
+ dst = src & dst;
+ SetSZPF8(dst);
+ cpustate->CF = 0;
+ cpustate->OF = 0;
+ CYCLES(cpustate,CYCLES_TEST_REG_MEM);
+ }
+}
+
+static void I386OP(xchg_r8_rm8)(i386_state *cpustate) // Opcode 0x86
+{
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ UINT8 src = LOAD_RM8(modrm);
+ UINT8 dst = LOAD_REG8(modrm);
+ STORE_REG8(modrm, src);
+ STORE_RM8(modrm, dst);
+ CYCLES(cpustate,CYCLES_XCHG_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT8 src = READ8(cpustate,ea);
+ UINT8 dst = LOAD_REG8(modrm);
+ STORE_REG8(modrm, src);
+ WRITE8(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_XCHG_REG_MEM);
+ }
+}
+
+static void I386OP(xor_rm8_r8)(i386_state *cpustate) // Opcode 0x30
+{
+ UINT8 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_REG8(modrm);
+ dst = LOAD_RM8(modrm);
+ dst = XOR8(cpustate,dst, src);
+ STORE_RM8(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = LOAD_REG8(modrm);
+ dst = READ8(cpustate,ea);
+ dst = XOR8(cpustate,dst, src);
+ WRITE8(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+}
+
+static void I386OP(xor_r8_rm8)(i386_state *cpustate) // Opcode 0x32
+{
+ UINT32 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ src = LOAD_RM8(modrm);
+ dst = LOAD_REG8(modrm);
+ dst = XOR8(cpustate,dst, src);
+ STORE_REG8(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = READ8(cpustate,ea);
+ dst = LOAD_REG8(modrm);
+ dst = XOR8(cpustate,dst, src);
+ STORE_REG8(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_MEM_REG);
+ }
+}
+
+static void I386OP(xor_al_i8)(i386_state *cpustate) // Opcode 0x34
+{
+ UINT8 src, dst;
+ src = FETCH(cpustate);
+ dst = REG8(AL);
+ dst = XOR8(cpustate,dst, src);
+ REG8(AL) = dst;
+ CYCLES(cpustate,CYCLES_ALU_IMM_ACC);
+}
+
+
+
+static void I386OP(group80_8)(i386_state *cpustate) // Opcode 0x80
+{
+ UINT32 ea;
+ UINT8 src, dst;
+ UINT8 modrm = FETCH(cpustate);
+
+ switch( (modrm >> 3) & 0x7 )
+ {
+ case 0: // ADD Rm8, i8
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM8(modrm);
+ src = FETCH(cpustate);
+ dst = ADD8(cpustate,dst, src);
+ STORE_RM8(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ dst = READ8(cpustate,ea);
+ src = FETCH(cpustate);
+ dst = ADD8(cpustate,dst, src);
+ WRITE8(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+ break;
+ case 1: // OR Rm8, i8
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM8(modrm);
+ src = FETCH(cpustate);
+ dst = OR8(cpustate,dst, src);
+ STORE_RM8(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ dst = READ8(cpustate,ea);
+ src = FETCH(cpustate);
+ dst = OR8(cpustate,dst, src);
+ WRITE8(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+ break;
+ case 2: // ADC Rm8, i8
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM8(modrm);
+ src = FETCH(cpustate);
+ dst = ADC8(cpustate, dst, src, cpustate->CF);
+ STORE_RM8(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ dst = READ8(cpustate,ea);
+ src = FETCH(cpustate);
+ dst = ADC8(cpustate, dst, src, cpustate->CF);
+ WRITE8(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+ break;
+ case 3: // SBB Rm8, i8
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM8(modrm);
+ src = FETCH(cpustate);
+ dst = SBB8(cpustate, dst, src, cpustate->CF);
+ STORE_RM8(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ dst = READ8(cpustate,ea);
+ src = FETCH(cpustate);
+ dst = SBB8(cpustate, dst, src, cpustate->CF);
+ WRITE8(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+ break;
+ case 4: // AND Rm8, i8
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM8(modrm);
+ src = FETCH(cpustate);
+ dst = AND8(cpustate,dst, src);
+ STORE_RM8(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ dst = READ8(cpustate,ea);
+ src = FETCH(cpustate);
+ dst = AND8(cpustate,dst, src);
+ WRITE8(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+ break;
+ case 5: // SUB Rm8, i8
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM8(modrm);
+ src = FETCH(cpustate);
+ dst = SUB8(cpustate,dst, src);
+ STORE_RM8(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ dst = READ8(cpustate,ea);
+ src = FETCH(cpustate);
+ dst = SUB8(cpustate,dst, src);
+ WRITE8(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+ break;
+ case 6: // XOR Rm8, i8
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM8(modrm);
+ src = FETCH(cpustate);
+ dst = XOR8(cpustate,dst, src);
+ STORE_RM8(modrm, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ dst = READ8(cpustate,ea);
+ src = FETCH(cpustate);
+ dst = XOR8(cpustate,dst, src);
+ WRITE8(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_ALU_REG_MEM);
+ }
+ break;
+ case 7: // CMP Rm8, i8
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM8(modrm);
+ src = FETCH(cpustate);
+ SUB8(cpustate,dst, src);
+ CYCLES(cpustate,CYCLES_CMP_REG_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ dst = READ8(cpustate,ea);
+ src = FETCH(cpustate);
+ SUB8(cpustate,dst, src);
+ CYCLES(cpustate,CYCLES_CMP_REG_MEM);
+ }
+ break;
+ }
+}
+
+static void I386OP(groupC0_8)(i386_state *cpustate) // Opcode 0xc0
+{
+ UINT8 dst;
+ UINT8 modrm = FETCH(cpustate);
+ UINT8 shift;
+
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM8(modrm);
+ shift = FETCH(cpustate) & 0x1f;
+ dst = i386_shift_rotate8(cpustate, modrm, dst, shift);
+ STORE_RM8(modrm, dst);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ dst = READ8(cpustate,ea);
+ shift = FETCH(cpustate) & 0x1f;
+ dst = i386_shift_rotate8(cpustate, modrm, dst, shift);
+ WRITE8(cpustate,ea, dst);
+ }
+}
+
+static void I386OP(groupD0_8)(i386_state *cpustate) // Opcode 0xd0
+{
+ UINT8 dst;
+ UINT8 modrm = FETCH(cpustate);
+
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM8(modrm);
+ dst = i386_shift_rotate8(cpustate, modrm, dst, 1);
+ STORE_RM8(modrm, dst);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ dst = READ8(cpustate,ea);
+ dst = i386_shift_rotate8(cpustate, modrm, dst, 1);
+ WRITE8(cpustate,ea, dst);
+ }
+}
+
+static void I386OP(groupD2_8)(i386_state *cpustate) // Opcode 0xd2
+{
+ UINT8 dst;
+ UINT8 modrm = FETCH(cpustate);
+
+ if( modrm >= 0xc0 ) {
+ dst = LOAD_RM8(modrm);
+ dst = i386_shift_rotate8(cpustate, modrm, dst, REG8(CL));
+ STORE_RM8(modrm, dst);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ dst = READ8(cpustate,ea);
+ dst = i386_shift_rotate8(cpustate, modrm, dst, REG8(CL));
+ WRITE8(cpustate,ea, dst);
+ }
+}
+
+static void I386OP(groupF6_8)(i386_state *cpustate) // Opcode 0xf6
+{
+ UINT8 modrm = FETCH(cpustate);
+
+ switch( (modrm >> 3) & 0x7 )
+ {
+ case 0: /* TEST Rm8, i8 */
+ if( modrm >= 0xc0 ) {
+ UINT8 dst = LOAD_RM8(modrm);
+ UINT8 src = FETCH(cpustate);
+ dst &= src;
+ cpustate->CF = cpustate->OF = cpustate->AF = 0;
+ SetSZPF8(dst);
+ CYCLES(cpustate,CYCLES_TEST_IMM_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT8 dst = READ8(cpustate,ea);
+ UINT8 src = FETCH(cpustate);
+ dst &= src;
+ cpustate->CF = cpustate->OF = cpustate->AF = 0;
+ SetSZPF8(dst);
+ CYCLES(cpustate,CYCLES_TEST_IMM_MEM);
+ }
+ break;
+ case 2: /* NOT Rm8 */
+ if( modrm >= 0xc0 ) {
+ UINT8 dst = LOAD_RM8(modrm);
+ dst = ~dst;
+ STORE_RM8(modrm, dst);
+ CYCLES(cpustate,CYCLES_NOT_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT8 dst = READ8(cpustate,ea);
+ dst = ~dst;
+ WRITE8(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_NOT_MEM);
+ }
+ break;
+ case 3: /* NEG Rm8 */
+ if( modrm >= 0xc0 ) {
+ UINT8 dst = LOAD_RM8(modrm);
+ dst = SUB8(cpustate, 0, dst );
+ STORE_RM8(modrm, dst);
+ CYCLES(cpustate,CYCLES_NEG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT8 dst = READ8(cpustate,ea);
+ dst = SUB8(cpustate, 0, dst );
+ WRITE8(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_NEG_MEM);
+ }
+ break;
+ case 4: /* MUL AL, Rm8 */
+ {
+ UINT16 result;
+ UINT8 src, dst;
+ if( modrm >= 0xc0 ) {
+ src = LOAD_RM8(modrm);
+ CYCLES(cpustate,CYCLES_MUL8_ACC_REG); /* TODO: Correct multiply timing */
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = READ8(cpustate,ea);
+ CYCLES(cpustate,CYCLES_MUL8_ACC_MEM); /* TODO: Correct multiply timing */
+ }
+
+ dst = REG8(AL);
+ result = (UINT16)src * (UINT16)dst;
+ REG16(AX) = (UINT16)result;
+
+ cpustate->CF = cpustate->OF = (REG16(AX) > 0xff);
+ }
+ break;
+ case 5: /* IMUL AL, Rm8 */
+ {
+ INT16 result;
+ INT16 src, dst;
+ if( modrm >= 0xc0 ) {
+ src = (INT16)(INT8)LOAD_RM8(modrm);
+ CYCLES(cpustate,CYCLES_IMUL8_ACC_REG); /* TODO: Correct multiply timing */
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = (INT16)(INT8)READ8(cpustate,ea);
+ CYCLES(cpustate,CYCLES_IMUL8_ACC_MEM); /* TODO: Correct multiply timing */
+ }
+
+ dst = (INT16)(INT8)REG8(AL);
+ result = src * dst;
+
+ REG16(AX) = (UINT16)result;
+
+ cpustate->CF = cpustate->OF = !(result == (INT16)(INT8)result);
+ }
+ break;
+ case 6: /* DIV AL, Rm8 */
+ {
+ UINT16 quotient, remainder, result;
+ UINT8 src;
+ if( modrm >= 0xc0 ) {
+ src = LOAD_RM8(modrm);
+ CYCLES(cpustate,CYCLES_DIV8_ACC_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = READ8(cpustate,ea);
+ CYCLES(cpustate,CYCLES_DIV8_ACC_MEM);
+ }
+
+ quotient = (UINT16)REG16(AX);
+ if( src ) {
+ remainder = quotient % (UINT16)src;
+ result = quotient / (UINT16)src;
+ if( result > 0xff ) {
+ /* TODO: Divide error */
+ } else {
+ REG8(AH) = (UINT8)remainder & 0xff;
+ REG8(AL) = (UINT8)result & 0xff;
+
+ // this flag is actually undefined, enable on non-cyrix
+ if (cpustate->cpuid_id0 != 0x69727943)
+ cpustate->CF = 1;
+ }
+ } else {
+ /* TODO: Divide by zero */
+ }
+ }
+ break;
+ case 7: /* IDIV AL, Rm8 */
+ {
+ INT16 quotient, remainder, result;
+ UINT8 src;
+ if( modrm >= 0xc0 ) {
+ src = LOAD_RM8(modrm);
+ CYCLES(cpustate,CYCLES_IDIV8_ACC_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ src = READ8(cpustate,ea);
+ CYCLES(cpustate,CYCLES_IDIV8_ACC_MEM);
+ }
+
+ quotient = (INT16)REG16(AX);
+ if( src ) {
+ remainder = quotient % (INT16)(INT8)src;
+ result = quotient / (INT16)(INT8)src;
+ if( result > 0xff ) {
+ /* TODO: Divide error */
+ } else {
+ REG8(AH) = (UINT8)remainder & 0xff;
+ REG8(AL) = (UINT8)result & 0xff;
+
+ // this flag is actually undefined, enable on non-cyrix
+ if (cpustate->cpuid_id0 != 0x69727943)
+ cpustate->CF = 1;
+ }
+ } else {
+ /* TODO: Divide by zero */
+ }
+ }
+ break;
+ }
+}
+
+static void I386OP(groupFE_8)(i386_state *cpustate) // Opcode 0xfe
+{
+ UINT8 modrm = FETCH(cpustate);
+
+ switch( (modrm >> 3) & 0x7 )
+ {
+ case 0: /* INC Rm8 */
+ if( modrm >= 0xc0 ) {
+ UINT8 dst = LOAD_RM8(modrm);
+ dst = INC8(cpustate,dst);
+ STORE_RM8(modrm, dst);
+ CYCLES(cpustate,CYCLES_INC_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT8 dst = READ8(cpustate,ea);
+ dst = INC8(cpustate,dst);
+ WRITE8(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_INC_MEM);
+ }
+ break;
+ case 1: /* DEC Rm8 */
+ if( modrm >= 0xc0 ) {
+ UINT8 dst = LOAD_RM8(modrm);
+ dst = DEC8(cpustate,dst);
+ STORE_RM8(modrm, dst);
+ CYCLES(cpustate,CYCLES_DEC_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT8 dst = READ8(cpustate,ea);
+ dst = DEC8(cpustate,dst);
+ WRITE8(cpustate,ea, dst);
+ CYCLES(cpustate,CYCLES_DEC_MEM);
+ }
+ break;
+ case 6: /* PUSH Rm8 */
+ {
+ UINT8 value;
+ if( modrm >= 0xc0 ) {
+ value = LOAD_RM8(modrm);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ value = READ8(cpustate,ea);
+ }
+ if( cpustate->operand_size ) {
+ PUSH32(cpustate,value);
+ } else {
+ PUSH16(cpustate,value);
+ }
+ CYCLES(cpustate,CYCLES_PUSH_RM);
+ }
+ break;
+ default:
+ fatalerror("i386: groupFE_8 /%d unimplemented", (modrm >> 3) & 0x7);
+ break;
+ }
+}
+
+
+
+static void I386OP(segment_CS)(i386_state *cpustate) // Opcode 0x2e
+{
+ cpustate->segment_prefix = 1;
+ cpustate->segment_override = CS;
+
+ I386OP(decode_opcode)(cpustate);
+}
+
+static void I386OP(segment_DS)(i386_state *cpustate) // Opcode 0x3e
+{
+ cpustate->segment_prefix = 1;
+ cpustate->segment_override = DS;
+ CYCLES(cpustate,0); // TODO: Specify cycle count
+ I386OP(decode_opcode)(cpustate);
+}
+
+static void I386OP(segment_ES)(i386_state *cpustate) // Opcode 0x26
+{
+ cpustate->segment_prefix = 1;
+ cpustate->segment_override = ES;
+ CYCLES(cpustate,0); // TODO: Specify cycle count
+ I386OP(decode_opcode)(cpustate);
+}
+
+static void I386OP(segment_FS)(i386_state *cpustate) // Opcode 0x64
+{
+ cpustate->segment_prefix = 1;
+ cpustate->segment_override = FS;
+ CYCLES(cpustate,1); // TODO: Specify cycle count
+ I386OP(decode_opcode)(cpustate);
+}
+
+static void I386OP(segment_GS)(i386_state *cpustate) // Opcode 0x65
+{
+ cpustate->segment_prefix = 1;
+ cpustate->segment_override = GS;
+ CYCLES(cpustate,1); // TODO: Specify cycle count
+ I386OP(decode_opcode)(cpustate);
+}
+
+static void I386OP(segment_SS)(i386_state *cpustate) // Opcode 0x36
+{
+ cpustate->segment_prefix = 1;
+ cpustate->segment_override = SS;
+ CYCLES(cpustate,0); // TODO: Specify cycle count
+ I386OP(decode_opcode)(cpustate);
+}
+
+static void I386OP(operand_size)(i386_state *cpustate) // Opcode 0x66
+{
+ cpustate->operand_size ^= 1;
+ I386OP(decode_opcode)(cpustate);
+}
+
+static void I386OP(address_size)(i386_state *cpustate) // Opcode 0x67
+{
+ cpustate->address_size ^= 1;
+ I386OP(decode_opcode)(cpustate);
+}
+
+static void I386OP(nop)(i386_state *cpustate) // Opcode 0x90
+{
+ CYCLES(cpustate,CYCLES_NOP);
+}
+
+static void I386OP(int3)(i386_state *cpustate) // Opcode 0xcc
+{
+ CYCLES(cpustate,CYCLES_INT3);
+ i386_trap(cpustate,3, 1, 0);
+}
+
+static void I386OP(int)(i386_state *cpustate) // Opcode 0xcd
+{
+ int interrupt = FETCH(cpustate);
+ CYCLES(cpustate,CYCLES_INT);
+ i386_trap(cpustate,interrupt, 1, 0);
+}
+
+static void I386OP(into)(i386_state *cpustate) // Opcode 0xce
+{
+ if( cpustate->OF ) {
+ i386_trap(cpustate,4, 1, 0);
+ CYCLES(cpustate,CYCLES_INTO_OF1);
+ }
+ else
+ {
+ CYCLES(cpustate,CYCLES_INTO_OF0);
+ }
+}
+
+static UINT32 i386_escape_ea; // hack around GCC 4.6 error because we need the side effects of GetEA()
+static void I386OP(escape)(i386_state *cpustate) // Opcodes 0xd8 - 0xdf
+{
+ UINT8 modrm = FETCH(cpustate);
+ if(modrm < 0xc0)
+ {
+ i386_escape_ea = GetEA(cpustate,modrm);
+ }
+ CYCLES(cpustate,3); // TODO: confirm this
+ (void) LOAD_RM8(modrm);
+}
+
+static void I386OP(hlt)(i386_state *cpustate) // Opcode 0xf4
+{
+ // TODO: We need to raise an exception in protected mode and when
+ // the current privilege level is not zero
+ cpustate->halted = 1;
+ CYCLES(cpustate,CYCLES_HLT);
+ if (cpustate->cycles > 0)
+ cpustate->cycles = 0;
+}
+
+static void I386OP(decimal_adjust)(i386_state *cpustate, int direction)
+{
+ UINT8 tmpAL = REG8(AL);
+ UINT8 tmpCF = cpustate->CF;
+
+ if (cpustate->AF || ((REG8(AL) & 0xf) > 9))
+ {
+ UINT16 t= (UINT16)REG8(AL) + (direction * 0x06);
+ REG8(AL) = (UINT8)t&0xff;
+ cpustate->AF = 1;
+ if (t & 0x100)
+ cpustate->CF = 1;
+ if (direction > 0)
+ tmpAL = REG8(AL);
+ }
+
+ if (tmpCF || (tmpAL > 0x99))
+ {
+ REG8(AL) += (direction * 0x60);
+ cpustate->CF = 1;
+ }
+
+ SetSZPF8(REG8(AL));
+}
+
+static void I386OP(daa)(i386_state *cpustate) // Opcode 0x27
+{
+ I386OP(decimal_adjust)(cpustate, +1);
+ CYCLES(cpustate,CYCLES_DAA);
+}
+
+static void I386OP(das)(i386_state *cpustate) // Opcode 0x2f
+{
+ I386OP(decimal_adjust)(cpustate, -1);
+ CYCLES(cpustate,CYCLES_DAS);
+}
+
+static void I386OP(aaa)(i386_state *cpustate) // Opcode 0x37
+{
+ if( ( (REG8(AL) & 0x0f) > 9) || (cpustate->AF != 0) ) {
+ REG16(AX) = REG16(AX) + 6;
+ REG8(AH) = REG8(AH) + 1;
+ cpustate->AF = 1;
+ cpustate->CF = 1;
+ } else {
+ cpustate->AF = 0;
+ cpustate->CF = 0;
+ }
+ REG8(AL) = REG8(AL) & 0x0f;
+ CYCLES(cpustate,CYCLES_AAA);
+}
+
+static void I386OP(aas)(i386_state *cpustate) // Opcode 0x3f
+{
+ if (cpustate->AF || ((REG8(AL) & 0xf) > 9))
+ {
+ REG16(AX) -= 6;
+ REG8(AH) -= 1;
+ cpustate->AF = 1;
+ cpustate->CF = 1;
+ }
+ else
+ {
+ cpustate->AF = 0;
+ cpustate->CF = 0;
+ }
+ REG8(AL) &= 0x0f;
+ CYCLES(cpustate,CYCLES_AAS);
+}
+
+static void I386OP(aad)(i386_state *cpustate) // Opcode 0xd5
+{
+ UINT8 tempAL = REG8(AL);
+ UINT8 tempAH = REG8(AH);
+ UINT8 i = FETCH(cpustate);
+
+ REG8(AL) = (tempAL + (tempAH * i)) & 0xff;
+ REG8(AH) = 0;
+ SetSZPF8( REG8(AL) );
+ CYCLES(cpustate,CYCLES_AAD);
+}
+
+static void I386OP(aam)(i386_state *cpustate) // Opcode 0xd4
+{
+ UINT8 tempAL = REG8(AL);
+ UINT8 i = FETCH(cpustate);
+
+ REG8(AH) = tempAL / i;
+ REG8(AL) = tempAL % i;
+ SetSZPF8( REG8(AL) );
+ CYCLES(cpustate,CYCLES_AAM);
+}
+
+static void I386OP(clts)(i386_state *cpustate) // Opcode 0x0f 0x06
+{
+ // Privileged instruction, CPL must be zero. Can be used in real or v86 mode.
+ if(PROTECTED_MODE && cpustate->CPL != 0)
+ FAULT(FAULT_GP,0)
+ cpustate->cr[0] &= ~0x08; /* clear TS bit */
+ CYCLES(cpustate,CYCLES_CLTS);
+}
+
+static void I386OP(wait)(i386_state *cpustate) // Opcode 0x9B
+{
+ // TODO
+}
+
+static void I386OP(lock)(i386_state *cpustate) // Opcode 0xf0
+{
+ CYCLES(cpustate,CYCLES_LOCK); // TODO: Determine correct cycle count
+ I386OP(decode_opcode)(cpustate);
+}
+
+static void I386OP(mov_r32_tr)(i386_state *cpustate) // Opcode 0x0f 24
+{
+ FETCH(cpustate);
+ CYCLES(cpustate,1); // TODO: correct cycle count
+}
+
+static void I386OP(mov_tr_r32)(i386_state *cpustate) // Opcode 0x0f 26
+{
+ FETCH(cpustate);
+ CYCLES(cpustate,1); // TODO: correct cycle count
+}
+
+static void I386OP(loadall)(i386_state *cpustate) // Opcode 0x0f 0x07 (0x0f 0x05 on 80286), undocumented
+{
+ popmessage("LOADALL instruction hit!");
+ CYCLES(cpustate,1); // TODO: correct cycle count
+}
+
+static void I386OP(unimplemented)(i386_state *cpustate)
+{
+ fatalerror("i386: Unimplemented opcode %02X at %08X", cpustate->opcode, cpustate->pc - 1 );
+}
+
+static void I386OP(invalid)(i386_state *cpustate)
+{
+ logerror("i386: Invalid opcode %02X at %08X\n", cpustate->opcode, cpustate->pc - 1);
+ i386_trap(cpustate, 6, 0, 0);
+}
diff --git a/trunk/src/emu/cpu/i386/i386ops.h b/trunk/src/emu/cpu/i386/i386ops.h
new file mode 100644
index 00000000000..a79759faa3b
--- /dev/null
+++ b/trunk/src/emu/cpu/i386/i386ops.h
@@ -0,0 +1,378 @@
+typedef struct {
+ UINT8 opcode;
+ UINT32 flags;
+ void (*handler16)(i386_state *cpustate);
+ void (*handler32)(i386_state *cpustate);
+} X86_OPCODE;
+
+#define OP_I386 0x1
+#define OP_FPU 0x2
+#define OP_I486 0x4
+#define OP_PENTIUM 0x8
+#define OP_MMX 0x10
+#define OP_PPRO 0x20
+#define OP_SSE 0x40
+#define OP_SSE2 0x80
+#define OP_SSE3 0x100
+#define OP_CYRIX 0x8000
+#define OP_2BYTE 0x80000000
+
+static const X86_OPCODE x86_opcode_table[] =
+{
+// Opcode Flags 16-bit handler 32-bit handler
+ { 0x00, OP_I386, I386OP(add_rm8_r8), I386OP(add_rm8_r8), },
+ { 0x01, OP_I386, I386OP(add_rm16_r16), I386OP(add_rm32_r32), },
+ { 0x02, OP_I386, I386OP(add_r8_rm8), I386OP(add_r8_rm8), },
+ { 0x03, OP_I386, I386OP(add_r16_rm16), I386OP(add_r32_rm32), },
+ { 0x04, OP_I386, I386OP(add_al_i8), I386OP(add_al_i8), },
+ { 0x05, OP_I386, I386OP(add_ax_i16), I386OP(add_eax_i32), },
+ { 0x06, OP_I386, I386OP(push_es16), I386OP(push_es32), },
+ { 0x07, OP_I386, I386OP(pop_es16), I386OP(pop_es32), },
+ { 0x08, OP_I386, I386OP(or_rm8_r8), I386OP(or_rm8_r8), },
+ { 0x09, OP_I386, I386OP(or_rm16_r16), I386OP(or_rm32_r32), },
+ { 0x0A, OP_I386, I386OP(or_r8_rm8), I386OP(or_r8_rm8), },
+ { 0x0B, OP_I386, I386OP(or_r16_rm16), I386OP(or_r32_rm32), },
+ { 0x0C, OP_I386, I386OP(or_al_i8), I386OP(or_al_i8), },
+ { 0x0D, OP_I386, I386OP(or_ax_i16), I386OP(or_eax_i32), },
+ { 0x0E, OP_I386, I386OP(push_cs16), I386OP(push_cs32), },
+ { 0x0F, OP_I386, I386OP(decode_two_byte), I386OP(decode_two_byte), },
+ { 0x10, OP_I386, I386OP(adc_rm8_r8), I386OP(adc_rm8_r8), },
+ { 0x11, OP_I386, I386OP(adc_rm16_r16), I386OP(adc_rm32_r32), },
+ { 0x12, OP_I386, I386OP(adc_r8_rm8), I386OP(adc_r8_rm8), },
+ { 0x13, OP_I386, I386OP(adc_r16_rm16), I386OP(adc_r32_rm32), },
+ { 0x14, OP_I386, I386OP(adc_al_i8), I386OP(adc_al_i8), },
+ { 0x15, OP_I386, I386OP(adc_ax_i16), I386OP(adc_eax_i32), },
+ { 0x16, OP_I386, I386OP(push_ss16), I386OP(push_ss32), },
+ { 0x17, OP_I386, I386OP(pop_ss16), I386OP(pop_ss32), },
+ { 0x18, OP_I386, I386OP(sbb_rm8_r8), I386OP(sbb_rm8_r8), },
+ { 0x19, OP_I386, I386OP(sbb_rm16_r16), I386OP(sbb_rm32_r32), },
+ { 0x1A, OP_I386, I386OP(sbb_r8_rm8), I386OP(sbb_r8_rm8), },
+ { 0x1B, OP_I386, I386OP(sbb_r16_rm16), I386OP(sbb_r32_rm32), },
+ { 0x1C, OP_I386, I386OP(sbb_al_i8), I386OP(sbb_al_i8), },
+ { 0x1D, OP_I386, I386OP(sbb_ax_i16), I386OP(sbb_eax_i32), },
+ { 0x1E, OP_I386, I386OP(push_ds16), I386OP(push_ds32), },
+ { 0x1F, OP_I386, I386OP(pop_ds16), I386OP(pop_ds32), },
+ { 0x20, OP_I386, I386OP(and_rm8_r8), I386OP(and_rm8_r8), },
+ { 0x21, OP_I386, I386OP(and_rm16_r16), I386OP(and_rm32_r32), },
+ { 0x22, OP_I386, I386OP(and_r8_rm8), I386OP(and_r8_rm8), },
+ { 0x23, OP_I386, I386OP(and_r16_rm16), I386OP(and_r32_rm32), },
+ { 0x24, OP_I386, I386OP(and_al_i8), I386OP(and_al_i8), },
+ { 0x25, OP_I386, I386OP(and_ax_i16), I386OP(and_eax_i32), },
+ { 0x26, OP_I386, I386OP(segment_ES), I386OP(segment_ES), },
+ { 0x27, OP_I386, I386OP(daa), I386OP(daa), },
+ { 0x28, OP_I386, I386OP(sub_rm8_r8), I386OP(sub_rm8_r8), },
+ { 0x29, OP_I386, I386OP(sub_rm16_r16), I386OP(sub_rm32_r32), },
+ { 0x2A, OP_I386, I386OP(sub_r8_rm8), I386OP(sub_r8_rm8), },
+ { 0x2B, OP_I386, I386OP(sub_r16_rm16), I386OP(sub_r32_rm32), },
+ { 0x2C, OP_I386, I386OP(sub_al_i8), I386OP(sub_al_i8), },
+ { 0x2D, OP_I386, I386OP(sub_ax_i16), I386OP(sub_eax_i32), },
+ { 0x2E, OP_I386, I386OP(segment_CS), I386OP(segment_CS), },
+ { 0x2F, OP_I386, I386OP(das), I386OP(das), },
+ { 0x30, OP_I386, I386OP(xor_rm8_r8), I386OP(xor_rm8_r8), },
+ { 0x31, OP_I386, I386OP(xor_rm16_r16), I386OP(xor_rm32_r32), },
+ { 0x32, OP_I386, I386OP(xor_r8_rm8), I386OP(xor_r8_rm8), },
+ { 0x33, OP_I386, I386OP(xor_r16_rm16), I386OP(xor_r32_rm32), },
+ { 0x34, OP_I386, I386OP(xor_al_i8), I386OP(xor_al_i8), },
+ { 0x35, OP_I386, I386OP(xor_ax_i16), I386OP(xor_eax_i32), },
+ { 0x36, OP_I386, I386OP(segment_SS), I386OP(segment_SS), },
+ { 0x37, OP_I386, I386OP(aaa), I386OP(aaa), },
+ { 0x38, OP_I386, I386OP(cmp_rm8_r8), I386OP(cmp_rm8_r8), },
+ { 0x39, OP_I386, I386OP(cmp_rm16_r16), I386OP(cmp_rm32_r32), },
+ { 0x3A, OP_I386, I386OP(cmp_r8_rm8), I386OP(cmp_r8_rm8), },
+ { 0x3B, OP_I386, I386OP(cmp_r16_rm16), I386OP(cmp_r32_rm32), },
+ { 0x3C, OP_I386, I386OP(cmp_al_i8), I386OP(cmp_al_i8), },
+ { 0x3D, OP_I386, I386OP(cmp_ax_i16), I386OP(cmp_eax_i32), },
+ { 0x3E, OP_I386, I386OP(segment_DS), I386OP(segment_DS), },
+ { 0x3F, OP_I386, I386OP(aas), I386OP(aas), },
+ { 0x40, OP_I386, I386OP(inc_ax), I386OP(inc_eax), },
+ { 0x41, OP_I386, I386OP(inc_cx), I386OP(inc_ecx), },
+ { 0x42, OP_I386, I386OP(inc_dx), I386OP(inc_edx), },
+ { 0x43, OP_I386, I386OP(inc_bx), I386OP(inc_ebx), },
+ { 0x44, OP_I386, I386OP(inc_sp), I386OP(inc_esp), },
+ { 0x45, OP_I386, I386OP(inc_bp), I386OP(inc_ebp), },
+ { 0x46, OP_I386, I386OP(inc_si), I386OP(inc_esi), },
+ { 0x47, OP_I386, I386OP(inc_di), I386OP(inc_edi), },
+ { 0x48, OP_I386, I386OP(dec_ax), I386OP(dec_eax), },
+ { 0x49, OP_I386, I386OP(dec_cx), I386OP(dec_ecx), },
+ { 0x4A, OP_I386, I386OP(dec_dx), I386OP(dec_edx), },
+ { 0x4B, OP_I386, I386OP(dec_bx), I386OP(dec_ebx), },
+ { 0x4C, OP_I386, I386OP(dec_sp), I386OP(dec_esp), },
+ { 0x4D, OP_I386, I386OP(dec_bp), I386OP(dec_ebp), },
+ { 0x4E, OP_I386, I386OP(dec_si), I386OP(dec_esi), },
+ { 0x4F, OP_I386, I386OP(dec_di), I386OP(dec_edi), },
+ { 0x50, OP_I386, I386OP(push_ax), I386OP(push_eax), },
+ { 0x51, OP_I386, I386OP(push_cx), I386OP(push_ecx), },
+ { 0x52, OP_I386, I386OP(push_dx), I386OP(push_edx), },
+ { 0x53, OP_I386, I386OP(push_bx), I386OP(push_ebx), },
+ { 0x54, OP_I386, I386OP(push_sp), I386OP(push_esp), },
+ { 0x55, OP_I386, I386OP(push_bp), I386OP(push_ebp), },
+ { 0x56, OP_I386, I386OP(push_si), I386OP(push_esi), },
+ { 0x57, OP_I386, I386OP(push_di), I386OP(push_edi), },
+ { 0x58, OP_I386, I386OP(pop_ax), I386OP(pop_eax), },
+ { 0x59, OP_I386, I386OP(pop_cx), I386OP(pop_ecx), },
+ { 0x5A, OP_I386, I386OP(pop_dx), I386OP(pop_edx), },
+ { 0x5B, OP_I386, I386OP(pop_bx), I386OP(pop_ebx), },
+ { 0x5C, OP_I386, I386OP(pop_sp), I386OP(pop_esp), },
+ { 0x5D, OP_I386, I386OP(pop_bp), I386OP(pop_ebp), },
+ { 0x5E, OP_I386, I386OP(pop_si), I386OP(pop_esi), },
+ { 0x5F, OP_I386, I386OP(pop_di), I386OP(pop_edi), },
+ { 0x60, OP_I386, I386OP(pusha), I386OP(pushad), },
+ { 0x61, OP_I386, I386OP(popa), I386OP(popad), },
+ { 0x62, OP_I386, I386OP(bound_r16_m16_m16), I386OP(bound_r32_m32_m32), },
+ { 0x63, OP_I386, I386OP(arpl), I386OP(arpl), },
+ { 0x64, OP_I386, I386OP(segment_FS), I386OP(segment_FS), },
+ { 0x65, OP_I386, I386OP(segment_GS), I386OP(segment_GS), },
+ { 0x66, OP_I386, I386OP(operand_size), I386OP(operand_size), },
+ { 0x67, OP_I386, I386OP(address_size), I386OP(address_size), },
+ { 0x68, OP_I386, I386OP(push_i16), I386OP(push_i32), },
+ { 0x69, OP_I386, I386OP(imul_r16_rm16_i16), I386OP(imul_r32_rm32_i32), },
+ { 0x6A, OP_I386, I386OP(push_i8), I386OP(push_i8), },
+ { 0x6B, OP_I386, I386OP(imul_r16_rm16_i8), I386OP(imul_r32_rm32_i8), },
+ { 0x6C, OP_I386, I386OP(insb), I386OP(insb), },
+ { 0x6D, OP_I386, I386OP(insw), I386OP(insd), },
+ { 0x6E, OP_I386, I386OP(outsb), I386OP(outsb), },
+ { 0x6F, OP_I386, I386OP(outsw), I386OP(outsd), },
+ { 0x70, OP_I386, I386OP(jo_rel8), I386OP(jo_rel8), },
+ { 0x71, OP_I386, I386OP(jno_rel8), I386OP(jno_rel8), },
+ { 0x72, OP_I386, I386OP(jc_rel8), I386OP(jc_rel8), },
+ { 0x73, OP_I386, I386OP(jnc_rel8), I386OP(jnc_rel8), },
+ { 0x74, OP_I386, I386OP(jz_rel8), I386OP(jz_rel8), },
+ { 0x75, OP_I386, I386OP(jnz_rel8), I386OP(jnz_rel8), },
+ { 0x76, OP_I386, I386OP(jbe_rel8), I386OP(jbe_rel8), },
+ { 0x77, OP_I386, I386OP(ja_rel8), I386OP(ja_rel8), },
+ { 0x78, OP_I386, I386OP(js_rel8), I386OP(js_rel8), },
+ { 0x79, OP_I386, I386OP(jns_rel8), I386OP(jns_rel8), },
+ { 0x7A, OP_I386, I386OP(jp_rel8), I386OP(jp_rel8), },
+ { 0x7B, OP_I386, I386OP(jnp_rel8), I386OP(jnp_rel8), },
+ { 0x7C, OP_I386, I386OP(jl_rel8), I386OP(jl_rel8), },
+ { 0x7D, OP_I386, I386OP(jge_rel8), I386OP(jge_rel8), },
+ { 0x7E, OP_I386, I386OP(jle_rel8), I386OP(jle_rel8), },
+ { 0x7F, OP_I386, I386OP(jg_rel8), I386OP(jg_rel8), },
+ { 0x80, OP_I386, I386OP(group80_8), I386OP(group80_8), },
+ { 0x81, OP_I386, I386OP(group81_16), I386OP(group81_32), },
+ { 0x82, OP_I386, I386OP(group80_8), I386OP(group80_8), },
+ { 0x83, OP_I386, I386OP(group83_16), I386OP(group83_32), },
+ { 0x84, OP_I386, I386OP(test_rm8_r8), I386OP(test_rm8_r8), },
+ { 0x85, OP_I386, I386OP(test_rm16_r16), I386OP(test_rm32_r32), },
+ { 0x86, OP_I386, I386OP(xchg_r8_rm8), I386OP(xchg_r8_rm8), },
+ { 0x87, OP_I386, I386OP(xchg_r16_rm16), I386OP(xchg_r32_rm32), },
+ { 0x88, OP_I386, I386OP(mov_rm8_r8), I386OP(mov_rm8_r8), },
+ { 0x89, OP_I386, I386OP(mov_rm16_r16), I386OP(mov_rm32_r32), },
+ { 0x8A, OP_I386, I386OP(mov_r8_rm8), I386OP(mov_r8_rm8), },
+ { 0x8B, OP_I386, I386OP(mov_r16_rm16), I386OP(mov_r32_rm32), },
+ { 0x8C, OP_I386, I386OP(mov_rm16_sreg), I386OP(mov_rm16_sreg), },
+ { 0x8D, OP_I386, I386OP(lea16), I386OP(lea32), },
+ { 0x8E, OP_I386, I386OP(mov_sreg_rm16), I386OP(mov_sreg_rm16), },
+ { 0x8F, OP_I386, I386OP(pop_rm16), I386OP(pop_rm32), },
+ { 0x90, OP_I386, I386OP(nop), I386OP(nop), },
+ { 0x91, OP_I386, I386OP(xchg_ax_cx), I386OP(xchg_eax_ecx), },
+ { 0x92, OP_I386, I386OP(xchg_ax_dx), I386OP(xchg_eax_edx), },
+ { 0x93, OP_I386, I386OP(xchg_ax_bx), I386OP(xchg_eax_ebx), },
+ { 0x94, OP_I386, I386OP(xchg_ax_sp), I386OP(xchg_eax_esp), },
+ { 0x95, OP_I386, I386OP(xchg_ax_bp), I386OP(xchg_eax_ebp), },
+ { 0x96, OP_I386, I386OP(xchg_ax_si), I386OP(xchg_eax_esi), },
+ { 0x97, OP_I386, I386OP(xchg_ax_di), I386OP(xchg_eax_edi), },
+ { 0x98, OP_I386, I386OP(cbw), I386OP(cwde), },
+ { 0x99, OP_I386, I386OP(cwd), I386OP(cdq), },
+ { 0x9A, OP_I386, I386OP(call_abs16), I386OP(call_abs32), },
+ { 0x9B, OP_I386, I386OP(wait), I386OP(wait), },
+ { 0x9C, OP_I386, I386OP(pushf), I386OP(pushfd), },
+ { 0x9D, OP_I386, I386OP(popf), I386OP(popfd), },
+ { 0x9E, OP_I386, I386OP(sahf), I386OP(sahf), },
+ { 0x9F, OP_I386, I386OP(lahf), I386OP(lahf), },
+ { 0xA0, OP_I386, I386OP(mov_al_m8), I386OP(mov_al_m8), },
+ { 0xA1, OP_I386, I386OP(mov_ax_m16), I386OP(mov_eax_m32), },
+ { 0xA2, OP_I386, I386OP(mov_m8_al), I386OP(mov_m8_al), },
+ { 0xA3, OP_I386, I386OP(mov_m16_ax), I386OP(mov_m32_eax), },
+ { 0xA4, OP_I386, I386OP(movsb), I386OP(movsb), },
+ { 0xA5, OP_I386, I386OP(movsw), I386OP(movsd), },
+ { 0xA6, OP_I386, I386OP(cmpsb), I386OP(cmpsb), },
+ { 0xA7, OP_I386, I386OP(cmpsw), I386OP(cmpsd), },
+ { 0xA8, OP_I386, I386OP(test_al_i8), I386OP(test_al_i8), },
+ { 0xA9, OP_I386, I386OP(test_ax_i16), I386OP(test_eax_i32), },
+ { 0xAA, OP_I386, I386OP(stosb), I386OP(stosb), },
+ { 0xAB, OP_I386, I386OP(stosw), I386OP(stosd), },
+ { 0xAC, OP_I386, I386OP(lodsb), I386OP(lodsb), },
+ { 0xAD, OP_I386, I386OP(lodsw), I386OP(lodsd), },
+ { 0xAE, OP_I386, I386OP(scasb), I386OP(scasb), },
+ { 0xAF, OP_I386, I386OP(scasw), I386OP(scasd), },
+ { 0xB0, OP_I386, I386OP(mov_al_i8), I386OP(mov_al_i8), },
+ { 0xB1, OP_I386, I386OP(mov_cl_i8), I386OP(mov_cl_i8), },
+ { 0xB2, OP_I386, I386OP(mov_dl_i8), I386OP(mov_dl_i8), },
+ { 0xB3, OP_I386, I386OP(mov_bl_i8), I386OP(mov_bl_i8), },
+ { 0xB4, OP_I386, I386OP(mov_ah_i8), I386OP(mov_ah_i8), },
+ { 0xB5, OP_I386, I386OP(mov_ch_i8), I386OP(mov_ch_i8), },
+ { 0xB6, OP_I386, I386OP(mov_dh_i8), I386OP(mov_dh_i8), },
+ { 0xB7, OP_I386, I386OP(mov_bh_i8), I386OP(mov_bh_i8), },
+ { 0xB8, OP_I386, I386OP(mov_ax_i16), I386OP(mov_eax_i32), },
+ { 0xB9, OP_I386, I386OP(mov_cx_i16), I386OP(mov_ecx_i32), },
+ { 0xBA, OP_I386, I386OP(mov_dx_i16), I386OP(mov_edx_i32), },
+ { 0xBB, OP_I386, I386OP(mov_bx_i16), I386OP(mov_ebx_i32), },
+ { 0xBC, OP_I386, I386OP(mov_sp_i16), I386OP(mov_esp_i32), },
+ { 0xBD, OP_I386, I386OP(mov_bp_i16), I386OP(mov_ebp_i32), },
+ { 0xBE, OP_I386, I386OP(mov_si_i16), I386OP(mov_esi_i32), },
+ { 0xBF, OP_I386, I386OP(mov_di_i16), I386OP(mov_edi_i32), },
+ { 0xC0, OP_I386, I386OP(groupC0_8), I386OP(groupC0_8), },
+ { 0xC1, OP_I386, I386OP(groupC1_16), I386OP(groupC1_32), },
+ { 0xC2, OP_I386, I386OP(ret_near16_i16), I386OP(ret_near32_i16), },
+ { 0xC3, OP_I386, I386OP(ret_near16), I386OP(ret_near32), },
+ { 0xC4, OP_I386, I386OP(les16), I386OP(les32), },
+ { 0xC5, OP_I386, I386OP(lds16), I386OP(lds32), },
+ { 0xC6, OP_I386, I386OP(mov_rm8_i8), I386OP(mov_rm8_i8), },
+ { 0xC7, OP_I386, I386OP(mov_rm16_i16), I386OP(mov_rm32_i32), },
+ { 0xC8, OP_I386, I386OP(enter16), I386OP(enter32), },
+ { 0xC9, OP_I386, I386OP(leave16), I386OP(leave32), },
+ { 0xCA, OP_I386, I386OP(retf_i16), I386OP(retf_i32), },
+ { 0xCB, OP_I386, I386OP(retf16), I386OP(retf32), },
+ { 0xCC, OP_I386, I386OP(int3), I386OP(int3), },
+ { 0xCD, OP_I386, I386OP(int), I386OP(int), },
+ { 0xCE, OP_I386, I386OP(into), I386OP(into), },
+ { 0xCF, OP_I386, I386OP(iret16), I386OP(iret32), },
+ { 0xD0, OP_I386, I386OP(groupD0_8), I386OP(groupD0_8), },
+ { 0xD1, OP_I386, I386OP(groupD1_16), I386OP(groupD1_32), },
+ { 0xD2, OP_I386, I386OP(groupD2_8), I386OP(groupD2_8), },
+ { 0xD3, OP_I386, I386OP(groupD3_16), I386OP(groupD3_32), },
+ { 0xD4, OP_I386, I386OP(aam), I386OP(aam), },
+ { 0xD5, OP_I386, I386OP(aad), I386OP(aad), },
+ { 0xD6, OP_I386, I386OP(setalc), I386OP(setalc), },
+ { 0xD7, OP_I386, I386OP(xlat16), I386OP(xlat32), },
+ { 0xD8, OP_I386, I386OP(escape), I386OP(escape), },
+ { 0xD9, OP_I386, I386OP(escape), I386OP(escape), },
+ { 0xDA, OP_I386, I386OP(escape), I386OP(escape), },
+ { 0xDB, OP_I386, I386OP(escape), I386OP(escape), },
+ { 0xDC, OP_I386, I386OP(escape), I386OP(escape), },
+ { 0xDD, OP_I386, I386OP(escape), I386OP(escape), },
+ { 0xDE, OP_I386, I386OP(escape), I386OP(escape), },
+ { 0xDF, OP_I386, I386OP(escape), I386OP(escape), },
+ { 0xD8, OP_FPU, I386OP(fpu_group_d8), I386OP(fpu_group_d8), },
+ { 0xD9, OP_FPU, I386OP(fpu_group_d9), I386OP(fpu_group_d9), },
+ { 0xDA, OP_FPU, I386OP(fpu_group_da), I386OP(fpu_group_da), },
+ { 0xDB, OP_FPU, I386OP(fpu_group_db), I386OP(fpu_group_db), },
+ { 0xDC, OP_FPU, I386OP(fpu_group_dc), I386OP(fpu_group_dc), },
+ { 0xDD, OP_FPU, I386OP(fpu_group_dd), I386OP(fpu_group_dd), },
+ { 0xDE, OP_FPU, I386OP(fpu_group_de), I386OP(fpu_group_de), },
+ { 0xDF, OP_FPU, I386OP(fpu_group_df), I386OP(fpu_group_df), },
+ { 0xE0, OP_I386, I386OP(loopne16), I386OP(loopne32), },
+ { 0xE1, OP_I386, I386OP(loopz16), I386OP(loopz32), },
+ { 0xE2, OP_I386, I386OP(loop16), I386OP(loop32), },
+ { 0xE3, OP_I386, I386OP(jcxz16), I386OP(jcxz32), },
+ { 0xE4, OP_I386, I386OP(in_al_i8), I386OP(in_al_i8), },
+ { 0xE5, OP_I386, I386OP(in_ax_i8), I386OP(in_eax_i8), },
+ { 0xE6, OP_I386, I386OP(out_al_i8), I386OP(out_al_i8), },
+ { 0xE7, OP_I386, I386OP(out_ax_i8), I386OP(out_eax_i8), },
+ { 0xE8, OP_I386, I386OP(call_rel16), I386OP(call_rel32), },
+ { 0xE9, OP_I386, I386OP(jmp_rel16), I386OP(jmp_rel32), },
+ { 0xEA, OP_I386, I386OP(jmp_abs16), I386OP(jmp_abs32), },
+ { 0xEB, OP_I386, I386OP(jmp_rel8), I386OP(jmp_rel8), },
+ { 0xEC, OP_I386, I386OP(in_al_dx), I386OP(in_al_dx), },
+ { 0xED, OP_I386, I386OP(in_ax_dx), I386OP(in_eax_dx), },
+ { 0xEE, OP_I386, I386OP(out_al_dx), I386OP(out_al_dx), },
+ { 0xEF, OP_I386, I386OP(out_ax_dx), I386OP(out_eax_dx), },
+ { 0xF0, OP_I386, I386OP(lock), I386OP(lock), },
+ { 0xF1, OP_I386, I386OP(invalid), I386OP(invalid), },
+ { 0xF2, OP_I386, I386OP(repne), I386OP(repne), },
+ { 0xF3, OP_I386, I386OP(rep), I386OP(rep), },
+ { 0xF4, OP_I386, I386OP(hlt), I386OP(hlt), },
+ { 0xF5, OP_I386, I386OP(cmc), I386OP(cmc), },
+ { 0xF6, OP_I386, I386OP(groupF6_8), I386OP(groupF6_8), },
+ { 0xF7, OP_I386, I386OP(groupF7_16), I386OP(groupF7_32), },
+ { 0xF8, OP_I386, I386OP(clc), I386OP(clc), },
+ { 0xF9, OP_I386, I386OP(stc), I386OP(stc), },
+ { 0xFA, OP_I386, I386OP(cli), I386OP(cli), },
+ { 0xFB, OP_I386, I386OP(sti), I386OP(sti), },
+ { 0xFC, OP_I386, I386OP(cld), I386OP(cld), },
+ { 0xFD, OP_I386, I386OP(std), I386OP(std), },
+ { 0xFE, OP_I386, I386OP(groupFE_8), I386OP(groupFE_8), },
+ { 0xFF, OP_I386, I386OP(groupFF_16), I386OP(groupFF_32), },
+ { 0x00, OP_2BYTE|OP_I386, I386OP(group0F00_16), I386OP(group0F00_32), },
+ { 0x01, OP_2BYTE|OP_I386, I386OP(group0F01_16), I386OP(group0F01_32), },
+ { 0x01, OP_2BYTE|OP_I486, I486OP(group0F01_16), I486OP(group0F01_32), },
+ { 0x02, OP_2BYTE|OP_I386, I386OP(lar_r16_rm16), I386OP(lar_r32_rm32), },
+ { 0x03, OP_2BYTE|OP_I386, I386OP(lsl_r16_rm16), I386OP(lsl_r32_rm32), },
+ { 0x06, OP_2BYTE|OP_I386, I386OP(clts), I386OP(clts), },
+ { 0x07, OP_2BYTE|OP_I386, I386OP(loadall), I386OP(loadall), },
+ { 0x08, OP_2BYTE|OP_I486, I486OP(invd), I486OP(invd), },
+ { 0x09, OP_2BYTE|OP_I486, I486OP(wbinvd), I486OP(wbinvd), },
+ { 0x0B, OP_2BYTE|OP_I386, I386OP(unimplemented), I386OP(unimplemented), },
+ { 0x20, OP_2BYTE|OP_I386, I386OP(mov_r32_cr), I386OP(mov_r32_cr), },
+ { 0x21, OP_2BYTE|OP_I386, I386OP(mov_r32_dr), I386OP(mov_r32_dr), },
+ { 0x22, OP_2BYTE|OP_I386, I386OP(mov_cr_r32), I386OP(mov_cr_r32), },
+ { 0x23, OP_2BYTE|OP_I386, I386OP(mov_dr_r32), I386OP(mov_dr_r32), },
+ { 0x24, OP_2BYTE|OP_I386, I386OP(mov_r32_tr), I386OP(mov_r32_tr), },
+ { 0x26, OP_2BYTE|OP_I386, I386OP(mov_tr_r32), I386OP(mov_tr_r32), },
+ { 0x30, OP_2BYTE|OP_PENTIUM, PENTIUMOP(wrmsr), PENTIUMOP(wrmsr), },
+ { 0x31, OP_2BYTE|OP_PENTIUM, PENTIUMOP(rdtsc), PENTIUMOP(rdtsc), },
+ { 0x32, OP_2BYTE|OP_PENTIUM, PENTIUMOP(rdmsr), PENTIUMOP(rdmsr), },
+ { 0x74, OP_2BYTE|OP_CYRIX, I386OP(cyrix_unknown), I386OP(cyrix_unknown), },
+ { 0x80, OP_2BYTE|OP_I386, I386OP(jo_rel16), I386OP(jo_rel32), },
+ { 0x81, OP_2BYTE|OP_I386, I386OP(jno_rel16), I386OP(jno_rel32), },
+ { 0x82, OP_2BYTE|OP_I386, I386OP(jc_rel16), I386OP(jc_rel32), },
+ { 0x83, OP_2BYTE|OP_I386, I386OP(jnc_rel16), I386OP(jnc_rel32), },
+ { 0x84, OP_2BYTE|OP_I386, I386OP(jz_rel16), I386OP(jz_rel32), },
+ { 0x85, OP_2BYTE|OP_I386, I386OP(jnz_rel16), I386OP(jnz_rel32), },
+ { 0x86, OP_2BYTE|OP_I386, I386OP(jbe_rel16), I386OP(jbe_rel32), },
+ { 0x87, OP_2BYTE|OP_I386, I386OP(ja_rel16), I386OP(ja_rel32), },
+ { 0x88, OP_2BYTE|OP_I386, I386OP(js_rel16), I386OP(js_rel32), },
+ { 0x89, OP_2BYTE|OP_I386, I386OP(jns_rel16), I386OP(jns_rel32), },
+ { 0x8A, OP_2BYTE|OP_I386, I386OP(jp_rel16), I386OP(jp_rel32), },
+ { 0x8B, OP_2BYTE|OP_I386, I386OP(jnp_rel16), I386OP(jnp_rel32), },
+ { 0x8C, OP_2BYTE|OP_I386, I386OP(jl_rel16), I386OP(jl_rel32), },
+ { 0x8D, OP_2BYTE|OP_I386, I386OP(jge_rel16), I386OP(jge_rel32), },
+ { 0x8E, OP_2BYTE|OP_I386, I386OP(jle_rel16), I386OP(jle_rel32), },
+ { 0x8F, OP_2BYTE|OP_I386, I386OP(jg_rel16), I386OP(jg_rel32), },
+ { 0x90, OP_2BYTE|OP_I386, I386OP(seto_rm8), I386OP(seto_rm8), },
+ { 0x91, OP_2BYTE|OP_I386, I386OP(setno_rm8), I386OP(setno_rm8), },
+ { 0x92, OP_2BYTE|OP_I386, I386OP(setc_rm8), I386OP(setc_rm8), },
+ { 0x93, OP_2BYTE|OP_I386, I386OP(setnc_rm8), I386OP(setnc_rm8), },
+ { 0x94, OP_2BYTE|OP_I386, I386OP(setz_rm8), I386OP(setz_rm8), },
+ { 0x95, OP_2BYTE|OP_I386, I386OP(setnz_rm8), I386OP(setnz_rm8), },
+ { 0x96, OP_2BYTE|OP_I386, I386OP(setbe_rm8), I386OP(setbe_rm8), },
+ { 0x97, OP_2BYTE|OP_I386, I386OP(seta_rm8), I386OP(seta_rm8), },
+ { 0x98, OP_2BYTE|OP_I386, I386OP(sets_rm8), I386OP(sets_rm8), },
+ { 0x99, OP_2BYTE|OP_I386, I386OP(setns_rm8), I386OP(setns_rm8), },
+ { 0x9A, OP_2BYTE|OP_I386, I386OP(setp_rm8), I386OP(setp_rm8), },
+ { 0x9B, OP_2BYTE|OP_I386, I386OP(setnp_rm8), I386OP(setnp_rm8), },
+ { 0x9C, OP_2BYTE|OP_I386, I386OP(setl_rm8), I386OP(setl_rm8), },
+ { 0x9D, OP_2BYTE|OP_I386, I386OP(setge_rm8), I386OP(setge_rm8), },
+ { 0x9E, OP_2BYTE|OP_I386, I386OP(setle_rm8), I386OP(setle_rm8), },
+ { 0x9F, OP_2BYTE|OP_I386, I386OP(setg_rm8), I386OP(setg_rm8), },
+ { 0xA0, OP_2BYTE|OP_I386, I386OP(push_fs16), I386OP(push_fs32), },
+ { 0xA1, OP_2BYTE|OP_I386, I386OP(pop_fs16), I386OP(pop_fs32), },
+ { 0xA2, OP_2BYTE|OP_I486, I486OP(cpuid), I486OP(cpuid), },
+ { 0xA3, OP_2BYTE|OP_I386, I386OP(bt_rm16_r16), I386OP(bt_rm32_r32), },
+ { 0xA4, OP_2BYTE|OP_I386, I386OP(shld16_i8), I386OP(shld32_i8), },
+ { 0xA5, OP_2BYTE|OP_I386, I386OP(shld16_cl), I386OP(shld32_cl), },
+ { 0xA8, OP_2BYTE|OP_I386, I386OP(push_gs16), I386OP(push_gs32), },
+ { 0xA9, OP_2BYTE|OP_I386, I386OP(pop_gs16), I386OP(pop_gs32), },
+ { 0xAA, OP_2BYTE|OP_I386, I386OP(unimplemented), I386OP(unimplemented), },
+ { 0xAB, OP_2BYTE|OP_I386, I386OP(bts_rm16_r16), I386OP(bts_rm32_r32), },
+ { 0xAC, OP_2BYTE|OP_I386, I386OP(shrd16_i8), I386OP(shrd32_i8), },
+ { 0xAD, OP_2BYTE|OP_I386, I386OP(shrd16_cl), I386OP(shrd32_cl), },
+ { 0xAE, OP_2BYTE|OP_I386, I386OP(invalid), I386OP(invalid), },
+ { 0xAF, OP_2BYTE|OP_I386, I386OP(imul_r16_rm16), I386OP(imul_r32_rm32), },
+ { 0xB0, OP_2BYTE|OP_I486, I486OP(cmpxchg_rm8_r8), I486OP(cmpxchg_rm8_r8), },
+ { 0xB1, OP_2BYTE|OP_I486, I486OP(cmpxchg_rm16_r16), I486OP(cmpxchg_rm32_r32), },
+ { 0xB2, OP_2BYTE|OP_I386, I386OP(lss16), I386OP(lss32), },
+ { 0xB3, OP_2BYTE|OP_I386, I386OP(btr_rm16_r16), I386OP(btr_rm32_r32), },
+ { 0xB4, OP_2BYTE|OP_I386, I386OP(lfs16), I386OP(lfs32), },
+ { 0xB5, OP_2BYTE|OP_I386, I386OP(lgs16), I386OP(lgs32), },
+ { 0xB6, OP_2BYTE|OP_I386, I386OP(movzx_r16_rm8), I386OP(movzx_r32_rm8), },
+ { 0xB7, OP_2BYTE|OP_I386, I386OP(invalid), I386OP(movzx_r32_rm16), },
+ { 0xBA, OP_2BYTE|OP_I386, I386OP(group0FBA_16), I386OP(group0FBA_32), },
+ { 0xBB, OP_2BYTE|OP_I386, I386OP(btc_rm16_r16), I386OP(btc_rm32_r32), },
+ { 0xBC, OP_2BYTE|OP_I386, I386OP(bsf_r16_rm16), I386OP(bsf_r32_rm32), },
+ { 0xBD, OP_2BYTE|OP_I386, I386OP(bsr_r16_rm16), I386OP(bsr_r32_rm32), },
+ { 0xBE, OP_2BYTE|OP_I386, I386OP(movsx_r16_rm8), I386OP(movsx_r32_rm8), },
+ { 0xBF, OP_2BYTE|OP_I386, I386OP(invalid), I386OP(movsx_r32_rm16), },
+ { 0xC0, OP_2BYTE|OP_I486, I486OP(xadd_rm8_r8), I486OP(xadd_rm8_r8), },
+ { 0xC1, OP_2BYTE|OP_I486, I486OP(xadd_rm16_r16), I486OP(xadd_rm32_r32), },
+ { 0xC7, OP_2BYTE|OP_PENTIUM, PENTIUMOP(cmpxchg8b_m64), PENTIUMOP(cmpxchg8b_m64), },
+ { 0xC8, OP_2BYTE|OP_I486, I486OP(bswap_eax), I486OP(bswap_eax), },
+ { 0xC9, OP_2BYTE|OP_I486, I486OP(bswap_ecx), I486OP(bswap_ecx), },
+ { 0xCA, OP_2BYTE|OP_I486, I486OP(bswap_edx), I486OP(bswap_edx), },
+ { 0xCB, OP_2BYTE|OP_I486, I486OP(bswap_ebx), I486OP(bswap_ebx), },
+ { 0xCC, OP_2BYTE|OP_I486, I486OP(bswap_esp), I486OP(bswap_esp), },
+ { 0xCD, OP_2BYTE|OP_I486, I486OP(bswap_ebp), I486OP(bswap_ebp), },
+ { 0xCE, OP_2BYTE|OP_I486, I486OP(bswap_esi), I486OP(bswap_esi), },
+ { 0xCF, OP_2BYTE|OP_I486, I486OP(bswap_edi), I486OP(bswap_edi), }
+};
diff --git a/trunk/src/emu/cpu/i386/i386priv.h b/trunk/src/emu/cpu/i386/i386priv.h
new file mode 100644
index 00000000000..5088dbda180
--- /dev/null
+++ b/trunk/src/emu/cpu/i386/i386priv.h
@@ -0,0 +1,993 @@
+#pragma once
+
+#ifndef __I386_H__
+#define __I386_H__
+
+#include "i386.h"
+
+#define I386OP(XX) i386_##XX
+#define I486OP(XX) i486_##XX
+#define PENTIUMOP(XX) pentium_##XX
+#define MMXOP(XX) mmx_##XX
+
+extern int i386_dasm_one(char *buffer, UINT32 pc, const UINT8 *oprom, int mode);
+
+typedef enum { ES, CS, SS, DS, FS, GS } SREGS;
+
+typedef enum
+{
+ AL = NATIVE_ENDIAN_VALUE_LE_BE(0,3),
+ AH = NATIVE_ENDIAN_VALUE_LE_BE(1,2),
+ CL = NATIVE_ENDIAN_VALUE_LE_BE(4,7),
+ CH = NATIVE_ENDIAN_VALUE_LE_BE(5,6),
+ DL = NATIVE_ENDIAN_VALUE_LE_BE(8,11),
+ DH = NATIVE_ENDIAN_VALUE_LE_BE(9,10),
+ BL = NATIVE_ENDIAN_VALUE_LE_BE(12,15),
+ BH = NATIVE_ENDIAN_VALUE_LE_BE(13,14)
+} BREGS;
+
+typedef enum
+{
+ AX = NATIVE_ENDIAN_VALUE_LE_BE(0,1),
+ CX = NATIVE_ENDIAN_VALUE_LE_BE(2,3),
+ DX = NATIVE_ENDIAN_VALUE_LE_BE(4,5),
+ BX = NATIVE_ENDIAN_VALUE_LE_BE(6,7),
+ SP = NATIVE_ENDIAN_VALUE_LE_BE(8,9),
+ BP = NATIVE_ENDIAN_VALUE_LE_BE(10,11),
+ SI = NATIVE_ENDIAN_VALUE_LE_BE(12,13),
+ DI = NATIVE_ENDIAN_VALUE_LE_BE(14,15)
+} WREGS;
+
+typedef enum { EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI } DREGS;
+
+enum
+{
+ I386_PC = 0,
+
+ /* 8-bit registers */
+ I386_AL,
+ I386_AH,
+ I386_BL,
+ I386_BH,
+ I386_CL,
+ I386_CH,
+ I386_DL,
+ I386_DH,
+
+ /* 16-bit registers */
+ I386_AX,
+ I386_BX,
+ I386_CX,
+ I386_DX,
+ I386_BP,
+ I386_SP,
+ I386_SI,
+ I386_DI,
+ I386_IP,
+
+ /* 32-bit registers */
+ I386_EAX,
+ I386_ECX,
+ I386_EDX,
+ I386_EBX,
+ I386_EBP,
+ I386_ESP,
+ I386_ESI,
+ I386_EDI,
+ I386_EIP,
+
+ /* segment registers */
+ I386_CS,
+ I386_CS_BASE,
+ I386_CS_LIMIT,
+ I386_CS_FLAGS,
+ I386_SS,
+ I386_SS_BASE,
+ I386_SS_LIMIT,
+ I386_SS_FLAGS,
+ I386_DS,
+ I386_DS_BASE,
+ I386_DS_LIMIT,
+ I386_DS_FLAGS,
+ I386_ES,
+ I386_ES_BASE,
+ I386_ES_LIMIT,
+ I386_ES_FLAGS,
+ I386_FS,
+ I386_FS_BASE,
+ I386_FS_LIMIT,
+ I386_FS_FLAGS,
+ I386_GS,
+ I386_GS_BASE,
+ I386_GS_LIMIT,
+ I386_GS_FLAGS,
+
+ /* other */
+ I386_EFLAGS,
+
+ I386_CR0,
+ I386_CR1,
+ I386_CR2,
+ I386_CR3,
+ I386_CR4,
+
+ I386_DR0,
+ I386_DR1,
+ I386_DR2,
+ I386_DR3,
+ I386_DR4,
+ I386_DR5,
+ I386_DR6,
+ I386_DR7,
+
+ I386_TR6,
+ I386_TR7,
+
+ I386_GDTR_BASE,
+ I386_GDTR_LIMIT,
+ I386_IDTR_BASE,
+ I386_IDTR_LIMIT,
+ I386_TR,
+ I386_TR_BASE,
+ I386_TR_LIMIT,
+ I386_TR_FLAGS,
+ I386_LDTR,
+ I386_LDTR_BASE,
+ I386_LDTR_LIMIT,
+ I386_LDTR_FLAGS,
+
+ I386_CPL,
+
+ X87_CTRL,
+ X87_STATUS,
+ X87_ST0,
+ X87_ST1,
+ X87_ST2,
+ X87_ST3,
+ X87_ST4,
+ X87_ST5,
+ X87_ST6,
+ X87_ST7,
+};
+
+/* Protected mode exceptions */
+#define FAULT_UD 6 // Invalid Opcode
+#define FAULT_NM 7 // Coprocessor not available
+#define FAULT_DF 8 // Double Fault
+#define FAULT_TS 10 // Invalid TSS
+#define FAULT_NP 11 // Segment or Gate not present
+#define FAULT_SS 12 // Stack fault
+#define FAULT_GP 13 // General Protection Fault
+#define FAULT_PF 14 // Page Fault
+#define FAULT_MF 16 // Match (Coprocessor) Fault
+
+typedef struct {
+ UINT16 selector;
+ UINT16 flags;
+ UINT32 base;
+ UINT32 limit;
+ int d; // Operand size
+} I386_SREG;
+
+typedef struct
+{
+ UINT16 segment;
+ UINT16 selector;
+ UINT32 offset;
+ UINT8 ar; // access rights
+ UINT8 dpl;
+ UINT8 dword_count;
+ UINT8 present;
+} I386_CALL_GATE;
+
+typedef struct {
+ UINT32 base;
+ UINT16 limit;
+} I386_SYS_TABLE;
+
+typedef struct {
+ UINT16 segment;
+ UINT16 flags;
+ UINT32 base;
+ UINT32 limit;
+} I386_SEG_DESC;
+
+typedef union {
+ UINT32 d[8];
+ UINT16 w[16];
+ UINT8 b[32];
+} I386_GPR;
+
+typedef union {
+ UINT64 i;
+ double f;
+} X87_REG;
+
+typedef struct _i386_state i386_state;
+struct _i386_state
+{
+ I386_GPR reg;
+ I386_SREG sreg[6];
+ UINT32 eip;
+ UINT32 pc;
+ UINT32 prev_eip;
+ UINT32 eflags;
+ UINT32 eflags_mask;
+ UINT8 CF;
+ UINT8 DF;
+ UINT8 SF;
+ UINT8 OF;
+ UINT8 ZF;
+ UINT8 PF;
+ UINT8 AF;
+ UINT8 IF;
+ UINT8 TF;
+ UINT8 IOP1;
+ UINT8 IOP2;
+ UINT8 NT;
+
+ UINT8 CPL; // current privilege level
+
+ UINT8 performed_intersegment_jump;
+ UINT8 delayed_interrupt_enable;
+
+ UINT32 cr[5]; // Control registers
+ UINT32 dr[8]; // Debug registers
+ UINT32 tr[8]; // Test registers
+
+ I386_SYS_TABLE gdtr; // Global Descriptor Table Register
+ I386_SYS_TABLE idtr; // Interrupt Descriptor Table Register
+ I386_SEG_DESC task; // Task register
+ I386_SEG_DESC ldtr; // Local Descriptor Table Register
+
+ int halted;
+
+ int operand_size;
+ int address_size;
+
+ int segment_prefix;
+ int segment_override;
+
+ int cycles;
+ int base_cycles;
+ UINT8 opcode;
+
+ UINT8 irq_state;
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ address_space *io;
+ UINT32 a20_mask;
+
+ int cpuid_max_input_value_eax;
+ UINT32 cpuid_id0, cpuid_id1, cpuid_id2;
+ UINT32 cpu_version;
+ UINT32 feature_flags;
+ UINT64 tsc;
+
+ // FPU
+ X87_REG fpu_reg[8];
+ UINT16 fpu_control_word;
+ UINT16 fpu_status_word;
+ UINT16 fpu_tag_word;
+ UINT64 fpu_data_ptr;
+ UINT64 fpu_inst_ptr;
+ UINT16 fpu_opcode;
+ int fpu_top;
+
+ void (*opcode_table1_16[256])(i386_state *cpustate);
+ void (*opcode_table1_32[256])(i386_state *cpustate);
+ void (*opcode_table2_16[256])(i386_state *cpustate);
+ void (*opcode_table2_32[256])(i386_state *cpustate);
+
+ UINT8 *cycle_table_pm;
+ UINT8 *cycle_table_rm;
+};
+
+INLINE i386_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == I386 ||
+ device->type() == I486 ||
+ device->type() == PENTIUM ||
+ device->type() == MEDIAGX);
+ return (i386_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+extern int i386_parity_table[256];
+
+#define PROTECTED_MODE (cpustate->cr[0] & 0x1)
+#define STACK_32BIT (cpustate->sreg[SS].d)
+#define V8086_MODE (cpustate->eflags & 0x00020000)
+#define NESTED_TASK (cpustate->eflags & 0x00004000)
+
+#define SetOF_Add32(r,s,d) (cpustate->OF = (((r) ^ (s)) & ((r) ^ (d)) & 0x80000000) ? 1: 0)
+#define SetOF_Add16(r,s,d) (cpustate->OF = (((r) ^ (s)) & ((r) ^ (d)) & 0x8000) ? 1 : 0)
+#define SetOF_Add8(r,s,d) (cpustate->OF = (((r) ^ (s)) & ((r) ^ (d)) & 0x80) ? 1 : 0)
+
+#define SetOF_Sub32(r,s,d) (cpustate->OF = (((d) ^ (s)) & ((d) ^ (r)) & 0x80000000) ? 1 : 0)
+#define SetOF_Sub16(r,s,d) (cpustate->OF = (((d) ^ (s)) & ((d) ^ (r)) & 0x8000) ? 1 : 0)
+#define SetOF_Sub8(r,s,d) (cpustate->OF = (((d) ^ (s)) & ((d) ^ (r)) & 0x80) ? 1 : 0)
+
+#define SetCF8(x) {cpustate->CF = ((x) & 0x100) ? 1 : 0; }
+#define SetCF16(x) {cpustate->CF = ((x) & 0x10000) ? 1 : 0; }
+#define SetCF32(x) {cpustate->CF = ((x) & (((UINT64)1) << 32)) ? 1 : 0; }
+
+#define SetSF(x) (cpustate->SF = (x))
+#define SetZF(x) (cpustate->ZF = (x))
+#define SetAF(x,y,z) (cpustate->AF = (((x) ^ ((y) ^ (z))) & 0x10) ? 1 : 0)
+#define SetPF(x) (cpustate->PF = i386_parity_table[(x) & 0xFF])
+
+#define SetSZPF8(x) {cpustate->ZF = ((UINT8)(x)==0); cpustate->SF = ((x)&0x80) ? 1 : 0; cpustate->PF = i386_parity_table[x & 0xFF]; }
+#define SetSZPF16(x) {cpustate->ZF = ((UINT16)(x)==0); cpustate->SF = ((x)&0x8000) ? 1 : 0; cpustate->PF = i386_parity_table[x & 0xFF]; }
+#define SetSZPF32(x) {cpustate->ZF = ((UINT32)(x)==0); cpustate->SF = ((x)&0x80000000) ? 1 : 0; cpustate->PF = i386_parity_table[x & 0xFF]; }
+
+/***********************************************************************************/
+
+typedef struct {
+ struct {
+ int b;
+ int w;
+ int d;
+ } reg;
+ struct {
+ int b;
+ int w;
+ int d;
+ } rm;
+} MODRM_TABLE;
+
+extern MODRM_TABLE i386_MODRM_table[256];
+
+#define REG8(x) (cpustate->reg.b[x])
+#define REG16(x) (cpustate->reg.w[x])
+#define REG32(x) (cpustate->reg.d[x])
+
+#define LOAD_REG8(x) (REG8(i386_MODRM_table[x].reg.b))
+#define LOAD_REG16(x) (REG16(i386_MODRM_table[x].reg.w))
+#define LOAD_REG32(x) (REG32(i386_MODRM_table[x].reg.d))
+#define LOAD_RM8(x) (REG8(i386_MODRM_table[x].rm.b))
+#define LOAD_RM16(x) (REG16(i386_MODRM_table[x].rm.w))
+#define LOAD_RM32(x) (REG32(i386_MODRM_table[x].rm.d))
+
+#define STORE_REG8(x, value) (REG8(i386_MODRM_table[x].reg.b) = value)
+#define STORE_REG16(x, value) (REG16(i386_MODRM_table[x].reg.w) = value)
+#define STORE_REG32(x, value) (REG32(i386_MODRM_table[x].reg.d) = value)
+#define STORE_RM8(x, value) (REG8(i386_MODRM_table[x].rm.b) = value)
+#define STORE_RM16(x, value) (REG16(i386_MODRM_table[x].rm.w) = value)
+#define STORE_RM32(x, value) (REG32(i386_MODRM_table[x].rm.d) = value)
+
+#define SWITCH_ENDIAN_32(x) (((((x) << 24) & (0xff << 24)) | (((x) << 8) & (0xff << 16)) | (((x) >> 8) & (0xff << 8)) | (((x) >> 24) & (0xff << 0))))
+
+/***********************************************************************************/
+
+INLINE UINT32 i386_translate(i386_state *cpustate, int segment, UINT32 ip)
+{
+ // TODO: segment limit
+ return cpustate->sreg[segment].base + ip;
+}
+
+INLINE int translate_address(i386_state *cpustate, UINT32 *address)
+{
+ UINT32 a = *address;
+ UINT32 pdbr = cpustate->cr[3] & 0xfffff000;
+ UINT32 directory = (a >> 22) & 0x3ff;
+ UINT32 table = (a >> 12) & 0x3ff;
+ UINT32 offset = a & 0xfff;
+ UINT32 page_entry;
+
+ // TODO: 4MB pages
+ UINT32 page_dir = cpustate->program->read_dword(pdbr + directory * 4);
+ if (!(cpustate->cr[4] & 0x10)) {
+ page_entry = cpustate->program->read_dword((page_dir & 0xfffff000) + (table * 4));
+ *address = (page_entry & 0xfffff000) | offset;
+ } else {
+ if (page_dir & 0x80)
+ *address = (page_dir & 0xffc00000) | (a & 0x003fffff);
+ else {
+ page_entry = cpustate->program->read_dword((page_dir & 0xfffff000) + (table * 4));
+ *address = (page_entry & 0xfffff000) | offset;
+ }
+ }
+ return 1;
+}
+
+INLINE void CHANGE_PC(i386_state *cpustate, UINT32 pc)
+{
+ UINT32 address;
+ cpustate->pc = i386_translate(cpustate, CS, pc );
+
+ address = cpustate->pc;
+
+ if (cpustate->cr[0] & 0x80000000) // page translation enabled
+ {
+ translate_address(cpustate,&address);
+ }
+}
+
+INLINE void NEAR_BRANCH(i386_state *cpustate, INT32 offs)
+{
+ UINT32 address;
+ /* TODO: limit */
+ cpustate->eip += offs;
+ cpustate->pc += offs;
+
+ address = cpustate->pc;
+
+ if (cpustate->cr[0] & 0x80000000) // page translation enabled
+ {
+ translate_address(cpustate,&address);
+ }
+}
+
+INLINE UINT8 FETCH(i386_state *cpustate)
+{
+ UINT8 value;
+ UINT32 address = cpustate->pc;
+
+ if (cpustate->cr[0] & 0x80000000) // page translation enabled
+ {
+ translate_address(cpustate,&address);
+ }
+
+ value = cpustate->direct->read_decrypted_byte(address & cpustate->a20_mask);
+ cpustate->eip++;
+ cpustate->pc++;
+ return value;
+}
+INLINE UINT16 FETCH16(i386_state *cpustate)
+{
+ UINT16 value;
+ UINT32 address = cpustate->pc;
+
+ if( address & 0x1 ) { /* Unaligned read */
+ value = (FETCH(cpustate) << 0) |
+ (FETCH(cpustate) << 8);
+ } else {
+ if (cpustate->cr[0] & 0x80000000) // page translation enabled
+ {
+ translate_address(cpustate,&address);
+ }
+ address &= cpustate->a20_mask;
+ value = cpustate->direct->read_decrypted_word(address);
+ cpustate->eip += 2;
+ cpustate->pc += 2;
+ }
+ return value;
+}
+INLINE UINT32 FETCH32(i386_state *cpustate)
+{
+ UINT32 value;
+ UINT32 address = cpustate->pc;
+
+ if( cpustate->pc & 0x3 ) { /* Unaligned read */
+ value = (FETCH(cpustate) << 0) |
+ (FETCH(cpustate) << 8) |
+ (FETCH(cpustate) << 16) |
+ (FETCH(cpustate) << 24);
+ } else {
+ if (cpustate->cr[0] & 0x80000000) // page translation enabled
+ {
+ translate_address(cpustate,&address);
+ }
+
+ address &= cpustate->a20_mask;
+ value = cpustate->direct->read_decrypted_dword(address);
+ cpustate->eip += 4;
+ cpustate->pc += 4;
+ }
+ return value;
+}
+
+INLINE UINT8 READ8(i386_state *cpustate,UINT32 ea)
+{
+ UINT32 address = ea;
+
+ if (cpustate->cr[0] & 0x80000000) // page translation enabled
+ {
+ translate_address(cpustate,&address);
+ }
+
+ address &= cpustate->a20_mask;
+ return cpustate->program->read_byte(address);
+}
+INLINE UINT16 READ16(i386_state *cpustate,UINT32 ea)
+{
+ UINT16 value;
+ UINT32 address = ea;
+
+ if( ea & 0x1 ) { /* Unaligned read */
+ value = (READ8( cpustate, address+0 ) << 0) |
+ (READ8( cpustate, address+1 ) << 8);
+ } else {
+ if (cpustate->cr[0] & 0x80000000) // page translation enabled
+ {
+ translate_address(cpustate,&address);
+ }
+
+ address &= cpustate->a20_mask;
+ value = cpustate->program->read_word( address );
+ }
+ return value;
+}
+INLINE UINT32 READ32(i386_state *cpustate,UINT32 ea)
+{
+ UINT32 value;
+ UINT32 address = ea;
+
+ if( ea & 0x3 ) { /* Unaligned read */
+ value = (READ8( cpustate, address+0 ) << 0) |
+ (READ8( cpustate, address+1 ) << 8) |
+ (READ8( cpustate, address+2 ) << 16) |
+ (READ8( cpustate, address+3 ) << 24);
+ } else {
+ if (cpustate->cr[0] & 0x80000000) // page translation enabled
+ {
+ translate_address(cpustate,&address);
+ }
+
+ address &= cpustate->a20_mask;
+ value = cpustate->program->read_dword( address );
+ }
+ return value;
+}
+
+INLINE UINT64 READ64(i386_state *cpustate,UINT32 ea)
+{
+ UINT64 value;
+ UINT32 address = ea;
+
+ if( ea & 0x7 ) { /* Unaligned read */
+ value = (((UINT64) READ8( cpustate, address+0 )) << 0) |
+ (((UINT64) READ8( cpustate, address+1 )) << 8) |
+ (((UINT64) READ8( cpustate, address+2 )) << 16) |
+ (((UINT64) READ8( cpustate, address+3 )) << 24) |
+ (((UINT64) READ8( cpustate, address+4 )) << 32) |
+ (((UINT64) READ8( cpustate, address+5 )) << 40) |
+ (((UINT64) READ8( cpustate, address+6 )) << 48) |
+ (((UINT64) READ8( cpustate, address+7 )) << 56);
+ } else {
+ if (cpustate->cr[0] & 0x80000000) // page translation enabled
+ {
+ translate_address(cpustate,&address);
+ }
+
+ address &= cpustate->a20_mask;
+ value = (((UINT64) cpustate->program->read_dword( address+0 )) << 0) |
+ (((UINT64) cpustate->program->read_dword( address+4 )) << 32);
+ }
+ return value;
+}
+
+INLINE void WRITE8(i386_state *cpustate,UINT32 ea, UINT8 value)
+{
+ UINT32 address = ea;
+
+ if (cpustate->cr[0] & 0x80000000) // page translation enabled
+ {
+ translate_address(cpustate,&address);
+ }
+
+ address &= cpustate->a20_mask;
+ cpustate->program->write_byte(address, value);
+}
+INLINE void WRITE16(i386_state *cpustate,UINT32 ea, UINT16 value)
+{
+ UINT32 address = ea;
+
+ if( ea & 0x1 ) { /* Unaligned write */
+ WRITE8( cpustate, address+0, value & 0xff );
+ WRITE8( cpustate, address+1, (value >> 8) & 0xff );
+ } else {
+ if (cpustate->cr[0] & 0x80000000) // page translation enabled
+ {
+ translate_address(cpustate,&address);
+ }
+
+ address &= cpustate->a20_mask;
+ cpustate->program->write_word(address, value);
+ }
+}
+INLINE void WRITE32(i386_state *cpustate,UINT32 ea, UINT32 value)
+{
+ UINT32 address = ea;
+
+ if( ea & 0x3 ) { /* Unaligned write */
+ WRITE8( cpustate, address+0, value & 0xff );
+ WRITE8( cpustate, address+1, (value >> 8) & 0xff );
+ WRITE8( cpustate, address+2, (value >> 16) & 0xff );
+ WRITE8( cpustate, address+3, (value >> 24) & 0xff );
+ } else {
+ if (cpustate->cr[0] & 0x80000000) // page translation enabled
+ {
+ translate_address(cpustate,&address);
+ }
+
+ ea &= cpustate->a20_mask;
+ cpustate->program->write_dword(address, value);
+ }
+}
+
+INLINE void WRITE64(i386_state *cpustate,UINT32 ea, UINT64 value)
+{
+ UINT32 address = ea;
+
+ if( ea & 0x7 ) { /* Unaligned write */
+ WRITE8( cpustate, address+0, value & 0xff );
+ WRITE8( cpustate, address+1, (value >> 8) & 0xff );
+ WRITE8( cpustate, address+2, (value >> 16) & 0xff );
+ WRITE8( cpustate, address+3, (value >> 24) & 0xff );
+ WRITE8( cpustate, address+4, (value >> 32) & 0xff );
+ WRITE8( cpustate, address+5, (value >> 40) & 0xff );
+ WRITE8( cpustate, address+6, (value >> 48) & 0xff );
+ WRITE8( cpustate, address+7, (value >> 56) & 0xff );
+ } else {
+ if (cpustate->cr[0] & 0x80000000) // page translation enabled
+ {
+ translate_address(cpustate,&address);
+ }
+
+ ea &= cpustate->a20_mask;
+ cpustate->program->write_dword(address+0, value & 0xffffffff);
+ cpustate->program->write_dword(address+4, (value >> 32) & 0xffffffff);
+ }
+}
+
+/***********************************************************************************/
+
+INLINE UINT8 OR8(i386_state *cpustate,UINT8 dst, UINT8 src)
+{
+ UINT8 res = dst | src;
+ cpustate->CF = cpustate->OF = 0;
+ SetSZPF8(res);
+ return res;
+}
+INLINE UINT16 OR16(i386_state *cpustate,UINT16 dst, UINT16 src)
+{
+ UINT16 res = dst | src;
+ cpustate->CF = cpustate->OF = 0;
+ SetSZPF16(res);
+ return res;
+}
+INLINE UINT32 OR32(i386_state *cpustate,UINT32 dst, UINT32 src)
+{
+ UINT32 res = dst | src;
+ cpustate->CF = cpustate->OF = 0;
+ SetSZPF32(res);
+ return res;
+}
+
+INLINE UINT8 AND8(i386_state *cpustate,UINT8 dst, UINT8 src)
+{
+ UINT8 res = dst & src;
+ cpustate->CF = cpustate->OF = 0;
+ SetSZPF8(res);
+ return res;
+}
+INLINE UINT16 AND16(i386_state *cpustate,UINT16 dst, UINT16 src)
+{
+ UINT16 res = dst & src;
+ cpustate->CF = cpustate->OF = 0;
+ SetSZPF16(res);
+ return res;
+}
+INLINE UINT32 AND32(i386_state *cpustate,UINT32 dst, UINT32 src)
+{
+ UINT32 res = dst & src;
+ cpustate->CF = cpustate->OF = 0;
+ SetSZPF32(res);
+ return res;
+}
+
+INLINE UINT8 XOR8(i386_state *cpustate,UINT8 dst, UINT8 src)
+{
+ UINT8 res = dst ^ src;
+ cpustate->CF = cpustate->OF = 0;
+ SetSZPF8(res);
+ return res;
+}
+INLINE UINT16 XOR16(i386_state *cpustate,UINT16 dst, UINT16 src)
+{
+ UINT16 res = dst ^ src;
+ cpustate->CF = cpustate->OF = 0;
+ SetSZPF16(res);
+ return res;
+}
+INLINE UINT32 XOR32(i386_state *cpustate,UINT32 dst, UINT32 src)
+{
+ UINT32 res = dst ^ src;
+ cpustate->CF = cpustate->OF = 0;
+ SetSZPF32(res);
+ return res;
+}
+
+#define SUB8(cpu, dst, src) SBB8(cpu, dst, src, 0)
+INLINE UINT8 SBB8(i386_state *cpustate,UINT8 dst, UINT8 src, UINT8 b)
+{
+ UINT16 res = (UINT16)dst - (UINT16)src - (UINT8)b;
+ SetCF8(res);
+ SetOF_Sub8(res,src,dst);
+ SetAF(res,src,dst);
+ SetSZPF8(res);
+ return (UINT8)res;
+}
+
+#define SUB16(cpu, dst, src) SBB16(cpu, dst, src, 0)
+INLINE UINT16 SBB16(i386_state *cpustate,UINT16 dst, UINT16 src, UINT16 b)
+{
+ UINT32 res = (UINT32)dst - (UINT32)src - (UINT32)b;
+ SetCF16(res);
+ SetOF_Sub16(res,src,dst);
+ SetAF(res,src,dst);
+ SetSZPF16(res);
+ return (UINT16)res;
+}
+
+#define SUB32(cpu, dst, src) SBB32(cpu, dst, src, 0)
+INLINE UINT32 SBB32(i386_state *cpustate,UINT32 dst, UINT32 src, UINT32 b)
+{
+ UINT64 res = (UINT64)dst - (UINT64)src - (UINT64) b;
+ SetCF32(res);
+ SetOF_Sub32(res,src,dst);
+ SetAF(res,src,dst);
+ SetSZPF32(res);
+ return (UINT32)res;
+}
+
+#define ADD8(cpu, dst, src) ADC8(cpu, dst, src, 0)
+INLINE UINT8 ADC8(i386_state *cpustate,UINT8 dst, UINT8 src, UINT8 c)
+{
+ UINT16 res = (UINT16)dst + (UINT16)src + (UINT16)c;
+ SetCF8(res);
+ SetOF_Add8(res,src,dst);
+ SetAF(res,src,dst);
+ SetSZPF8(res);
+ return (UINT8)res;
+}
+
+#define ADD16(cpu, dst, src) ADC16(cpu, dst, src, 0)
+INLINE UINT16 ADC16(i386_state *cpustate,UINT16 dst, UINT16 src, UINT8 c)
+{
+ UINT32 res = (UINT32)dst + (UINT32)src + (UINT32)c;
+ SetCF16(res);
+ SetOF_Add16(res,src,dst);
+ SetAF(res,src,dst);
+ SetSZPF16(res);
+ return (UINT16)res;
+}
+
+#define ADD32(cpu, dst, src) ADC32(cpu, dst, src, 0)
+INLINE UINT32 ADC32(i386_state *cpustate,UINT32 dst, UINT32 src, UINT32 c)
+{
+ UINT64 res = (UINT64)dst + (UINT64)src + (UINT64) c;
+ SetCF32(res);
+ SetOF_Add32(res,src,dst);
+ SetAF(res,src,dst);
+ SetSZPF32(res);
+ return (UINT32)res;
+}
+
+INLINE UINT8 INC8(i386_state *cpustate,UINT8 dst)
+{
+ UINT16 res = (UINT16)dst + 1;
+ SetOF_Add8(res,1,dst);
+ SetAF(res,1,dst);
+ SetSZPF8(res);
+ return (UINT8)res;
+}
+INLINE UINT16 INC16(i386_state *cpustate,UINT16 dst)
+{
+ UINT32 res = (UINT32)dst + 1;
+ SetOF_Add16(res,1,dst);
+ SetAF(res,1,dst);
+ SetSZPF16(res);
+ return (UINT16)res;
+}
+INLINE UINT32 INC32(i386_state *cpustate,UINT32 dst)
+{
+ UINT64 res = (UINT64)dst + 1;
+ SetOF_Add32(res,1,dst);
+ SetAF(res,1,dst);
+ SetSZPF32(res);
+ return (UINT32)res;
+}
+
+INLINE UINT8 DEC8(i386_state *cpustate,UINT8 dst)
+{
+ UINT16 res = (UINT16)dst - 1;
+ SetOF_Sub8(res,1,dst);
+ SetAF(res,1,dst);
+ SetSZPF8(res);
+ return (UINT8)res;
+}
+INLINE UINT16 DEC16(i386_state *cpustate,UINT16 dst)
+{
+ UINT32 res = (UINT32)dst - 1;
+ SetOF_Sub16(res,1,dst);
+ SetAF(res,1,dst);
+ SetSZPF16(res);
+ return (UINT16)res;
+}
+INLINE UINT32 DEC32(i386_state *cpustate,UINT32 dst)
+{
+ UINT64 res = (UINT64)dst - 1;
+ SetOF_Sub32(res,1,dst);
+ SetAF(res,1,dst);
+ SetSZPF32(res);
+ return (UINT32)res;
+}
+
+
+
+INLINE void PUSH16(i386_state *cpustate,UINT16 value)
+{
+ UINT32 ea;
+ if( STACK_32BIT ) {
+ REG32(ESP) -= 2;
+ ea = i386_translate(cpustate, SS, REG32(ESP) );
+ WRITE16(cpustate, ea, value );
+ } else {
+ REG16(SP) -= 2;
+ ea = i386_translate(cpustate, SS, REG16(SP) );
+ WRITE16(cpustate, ea, value );
+ }
+}
+INLINE void PUSH32(i386_state *cpustate,UINT32 value)
+{
+ UINT32 ea;
+ if( STACK_32BIT ) {
+ REG32(ESP) -= 4;
+ ea = i386_translate(cpustate, SS, REG32(ESP) );
+ WRITE32(cpustate, ea, value );
+ } else {
+ REG16(SP) -= 4;
+ ea = i386_translate(cpustate, SS, REG16(SP) );
+ WRITE32(cpustate, ea, value );
+ }
+}
+INLINE void PUSH8(i386_state *cpustate,UINT8 value)
+{
+ if( cpustate->operand_size ) {
+ PUSH32(cpustate,(INT32)(INT8)value);
+ } else {
+ PUSH16(cpustate,(INT16)(INT8)value);
+ }
+}
+
+INLINE UINT8 POP8(i386_state *cpustate)
+{
+ UINT8 value;
+ UINT32 ea;
+ if( STACK_32BIT ) {
+ REG32(ESP) += 1;
+ ea = i386_translate(cpustate, SS, REG32(ESP) - 1);
+ value = READ8(cpustate, ea );
+ } else {
+ REG16(SP) += 1;
+ ea = i386_translate(cpustate, SS, (REG16(SP) - 1) & 0xffff);
+ value = READ8(cpustate, ea );
+ }
+ return value;
+}
+INLINE UINT16 POP16(i386_state *cpustate)
+{
+ UINT16 value;
+ UINT32 ea;
+ if( STACK_32BIT ) {
+ REG32(ESP) += 2;
+ ea = i386_translate(cpustate, SS, REG32(ESP) - 2);
+ value = READ16(cpustate, ea );
+ } else {
+ REG16(SP) += 2;
+ ea = i386_translate(cpustate, SS, (REG16(SP) - 2) & 0xffff);
+ value = READ16(cpustate, ea );
+ }
+ return value;
+}
+INLINE UINT32 POP32(i386_state *cpustate)
+{
+ UINT32 value;
+ UINT32 ea;
+ if( STACK_32BIT ) {
+ REG32(ESP) += 4;
+ ea = i386_translate(cpustate, SS, REG32(ESP) - 4);
+ value = READ32(cpustate, ea );
+ } else {
+ REG16(SP) += 4;
+ ea = i386_translate(cpustate, SS, (REG16(SP) - 4) & 0xffff);
+ value = READ32(cpustate, ea );
+ }
+ return value;
+}
+
+INLINE void BUMP_SI(i386_state *cpustate,int adjustment)
+{
+ if ( cpustate->address_size )
+ REG32(ESI) += ((cpustate->DF) ? -adjustment : +adjustment);
+ else
+ REG16(SI) += ((cpustate->DF) ? -adjustment : +adjustment);
+}
+
+INLINE void BUMP_DI(i386_state *cpustate,int adjustment)
+{
+ if ( cpustate->address_size )
+ REG32(EDI) += ((cpustate->DF) ? -adjustment : +adjustment);
+ else
+ REG16(DI) += ((cpustate->DF) ? -adjustment : +adjustment);
+}
+
+
+
+/***********************************************************************************
+ I/O ACCESS
+***********************************************************************************/
+
+INLINE UINT8 READPORT8(i386_state *cpustate, offs_t port)
+{
+ return cpustate->io->read_byte(port);
+}
+
+INLINE void WRITEPORT8(i386_state *cpustate, offs_t port, UINT8 value)
+{
+ cpustate->io->write_byte(port, value);
+}
+
+INLINE UINT16 READPORT16(i386_state *cpustate, offs_t port)
+{
+ if (port & 1)
+ {
+ return READPORT8(cpustate, port) |
+ (READPORT8(cpustate, port + 1) << 8);
+ }
+ else
+ {
+ return cpustate->io->read_word(port);
+ }
+}
+
+INLINE void WRITEPORT16(i386_state *cpustate, offs_t port, UINT16 value)
+{
+ if (port & 1)
+ {
+ WRITEPORT8(cpustate, port, value & 0xff);
+ WRITEPORT8(cpustate, port + 1, (value >> 8) & 0xff);
+ }
+ else
+ {
+ cpustate->io->write_word(port, value);
+ }
+}
+
+INLINE UINT32 READPORT32(i386_state *cpustate, offs_t port)
+{
+ if (port & 3)
+ {
+ return READPORT8(cpustate, port) |
+ (READPORT8(cpustate, port + 1) << 8) |
+ (READPORT8(cpustate, port + 2) << 16) |
+ (READPORT8(cpustate, port + 3) << 24);
+ }
+ else
+ {
+ return cpustate->io->read_dword(port);
+ }
+}
+
+INLINE void WRITEPORT32(i386_state *cpustate, offs_t port, UINT32 value)
+{
+ if (port & 3)
+ {
+ WRITEPORT8(cpustate, port, value & 0xff);
+ WRITEPORT8(cpustate, port + 1, (value >> 8) & 0xff);
+ WRITEPORT8(cpustate, port + 2, (value >> 16) & 0xff);
+ WRITEPORT8(cpustate, port + 3, (value >> 24) & 0xff);
+ }
+ else
+ {
+ cpustate->io->write_dword(port, value);
+ }
+}
+
+
+#endif /* __I386_H__ */
diff --git a/trunk/src/emu/cpu/i386/i486ops.c b/trunk/src/emu/cpu/i386/i486ops.c
new file mode 100644
index 00000000000..daca98767b9
--- /dev/null
+++ b/trunk/src/emu/cpu/i386/i486ops.c
@@ -0,0 +1,424 @@
+// Intel 486+ specific opcodes
+
+static void I486OP(cpuid)(i386_state *cpustate) // Opcode 0x0F A2
+{
+ if (cpustate->cpuid_id0 == 0)
+ {
+ // this 486 doesn't support the CPUID instruction
+ logerror("CPUID not supported at %08x!\n", cpustate->eip);
+ i386_trap(cpustate, 6, 0, 0);
+ }
+ else
+ {
+ switch (REG32(EAX))
+ {
+ case 0:
+ {
+ REG32(EAX) = cpustate->cpuid_max_input_value_eax;
+ REG32(EBX) = cpustate->cpuid_id0;
+ REG32(ECX) = cpustate->cpuid_id2;
+ REG32(EDX) = cpustate->cpuid_id1;
+ CYCLES(cpustate,CYCLES_CPUID);
+ break;
+ }
+
+ case 1:
+ {
+ REG32(EAX) = cpustate->cpu_version;
+ REG32(EDX) = cpustate->feature_flags;
+ CYCLES(cpustate,CYCLES_CPUID_EAX1);
+ break;
+ }
+ }
+ }
+}
+
+static void I486OP(invd)(i386_state *cpustate) // Opcode 0x0f 08
+{
+ // Nothing to do ?
+ CYCLES(cpustate,CYCLES_INVD);
+}
+
+static void I486OP(wbinvd)(i386_state *cpustate) // Opcode 0x0f 09
+{
+ // Nothing to do ?
+}
+
+static void I486OP(cmpxchg_rm8_r8)(i386_state *cpustate) // Opcode 0x0f b0
+{
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ UINT8 dst = LOAD_RM8(modrm);
+ UINT8 src = LOAD_REG8(modrm);
+
+ if( REG8(AL) == dst ) {
+ STORE_RM8(modrm, src);
+ cpustate->ZF = 1;
+ CYCLES(cpustate,CYCLES_CMPXCHG_REG_REG_T);
+ } else {
+ REG8(AL) = dst;
+ cpustate->ZF = 0;
+ CYCLES(cpustate,CYCLES_CMPXCHG_REG_REG_F);
+ }
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT8 dst = READ8(cpustate,ea);
+ UINT8 src = LOAD_REG8(modrm);
+
+ if( REG8(AL) == dst ) {
+ WRITE8(cpustate,modrm, src);
+ cpustate->ZF = 1;
+ CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_T);
+ } else {
+ REG8(AL) = dst;
+ cpustate->ZF = 0;
+ CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_F);
+ }
+ }
+}
+
+static void I486OP(cmpxchg_rm16_r16)(i386_state *cpustate) // Opcode 0x0f b1
+{
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ UINT16 dst = LOAD_RM16(modrm);
+ UINT16 src = LOAD_REG16(modrm);
+
+ if( REG16(AX) == dst ) {
+ STORE_RM16(modrm, src);
+ cpustate->ZF = 1;
+ CYCLES(cpustate,CYCLES_CMPXCHG_REG_REG_T);
+ } else {
+ REG16(AX) = dst;
+ cpustate->ZF = 0;
+ CYCLES(cpustate,CYCLES_CMPXCHG_REG_REG_F);
+ }
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT16 dst = READ16(cpustate,ea);
+ UINT16 src = LOAD_REG16(modrm);
+
+ if( REG16(AX) == dst ) {
+ WRITE16(cpustate,modrm, src);
+ cpustate->ZF = 1;
+ CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_T);
+ } else {
+ REG16(AX) = dst;
+ cpustate->ZF = 0;
+ CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_F);
+ }
+ }
+}
+
+static void I486OP(cmpxchg_rm32_r32)(i386_state *cpustate) // Opcode 0x0f b1
+{
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ UINT32 dst = LOAD_RM32(modrm);
+ UINT32 src = LOAD_REG32(modrm);
+
+ if( REG32(EAX) == dst ) {
+ STORE_RM32(modrm, src);
+ cpustate->ZF = 1;
+ CYCLES(cpustate,CYCLES_CMPXCHG_REG_REG_T);
+ } else {
+ REG32(EAX) = dst;
+ cpustate->ZF = 0;
+ CYCLES(cpustate,CYCLES_CMPXCHG_REG_REG_F);
+ }
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT32 dst = READ32(cpustate,ea);
+ UINT32 src = LOAD_REG32(modrm);
+
+ if( REG32(EAX) == dst ) {
+ WRITE32(cpustate,ea, src);
+ cpustate->ZF = 1;
+ CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_T);
+ } else {
+ REG32(EAX) = dst;
+ cpustate->ZF = 0;
+ CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_F);
+ }
+ }
+}
+
+static void I486OP(xadd_rm8_r8)(i386_state *cpustate) // Opcode 0x0f c0
+{
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ UINT8 dst = LOAD_RM8(modrm);
+ UINT8 src = LOAD_REG8(modrm);
+ STORE_RM16(modrm, dst + src);
+ STORE_REG16(modrm, dst);
+ CYCLES(cpustate,CYCLES_XADD_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT8 dst = READ8(cpustate,ea);
+ UINT8 src = LOAD_REG8(modrm);
+ WRITE8(cpustate,ea, dst + src);
+ STORE_REG8(modrm, dst);
+ CYCLES(cpustate,CYCLES_XADD_REG_MEM);
+ }
+}
+
+static void I486OP(xadd_rm16_r16)(i386_state *cpustate) // Opcode 0x0f c1
+{
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ UINT16 dst = LOAD_RM16(modrm);
+ UINT16 src = LOAD_REG16(modrm);
+ STORE_RM16(modrm, dst + src);
+ STORE_REG16(modrm, dst);
+ CYCLES(cpustate,CYCLES_XADD_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT16 dst = READ16(cpustate,ea);
+ UINT16 src = LOAD_REG16(modrm);
+ WRITE16(cpustate,ea, dst + src);
+ STORE_REG16(modrm, dst);
+ CYCLES(cpustate,CYCLES_XADD_REG_MEM);
+ }
+}
+
+static void I486OP(xadd_rm32_r32)(i386_state *cpustate) // Opcode 0x0f c1
+{
+ UINT8 modrm = FETCH(cpustate);
+ if( modrm >= 0xc0 ) {
+ UINT32 dst = LOAD_RM32(modrm);
+ UINT32 src = LOAD_REG32(modrm);
+ STORE_RM32(modrm, dst + src);
+ STORE_REG32(modrm, dst);
+ CYCLES(cpustate,CYCLES_XADD_REG_REG);
+ } else {
+ UINT32 ea = GetEA(cpustate,modrm);
+ UINT32 dst = READ32(cpustate,ea);
+ UINT32 src = LOAD_REG32(modrm);
+ WRITE32(cpustate,ea, dst + src);
+ STORE_REG32(modrm, dst);
+ CYCLES(cpustate,CYCLES_XADD_REG_MEM);
+ }
+}
+
+static void I486OP(group0F01_16)(i386_state *cpustate) // Opcode 0x0f 01
+{
+ UINT8 modrm = FETCH(cpustate);
+ UINT16 address;
+ UINT32 ea;
+
+ switch( (modrm >> 3) & 0x7 )
+ {
+ case 0: /* SGDT */
+ {
+ if( modrm >= 0xc0 ) {
+ address = LOAD_RM16(modrm);
+ ea = i386_translate( cpustate, CS, address );
+ } else {
+ ea = GetEA(cpustate,modrm);
+ }
+ WRITE16(cpustate,ea, cpustate->gdtr.limit);
+ WRITE32(cpustate,ea + 2, cpustate->gdtr.base & 0xffffff);
+ CYCLES(cpustate,CYCLES_SGDT);
+ break;
+ }
+ case 1: /* SIDT */
+ {
+ if (modrm >= 0xc0)
+ {
+ address = LOAD_RM16(modrm);
+ ea = i386_translate( cpustate, CS, address );
+ }
+ else
+ {
+ ea = GetEA(cpustate,modrm);
+ }
+ WRITE16(cpustate,ea, cpustate->idtr.limit);
+ WRITE32(cpustate,ea + 2, cpustate->idtr.base & 0xffffff);
+ CYCLES(cpustate,CYCLES_SIDT);
+ break;
+ }
+ case 2: /* LGDT */
+ {
+ if( modrm >= 0xc0 ) {
+ address = LOAD_RM16(modrm);
+ ea = i386_translate( cpustate, CS, address );
+ } else {
+ ea = GetEA(cpustate,modrm);
+ }
+ cpustate->gdtr.limit = READ16(cpustate,ea);
+ cpustate->gdtr.base = READ32(cpustate,ea + 2) & 0xffffff;
+ CYCLES(cpustate,CYCLES_LGDT);
+ break;
+ }
+ case 3: /* LIDT */
+ {
+ if( modrm >= 0xc0 ) {
+ address = LOAD_RM16(modrm);
+ ea = i386_translate( cpustate, CS, address );
+ } else {
+ ea = GetEA(cpustate,modrm);
+ }
+ cpustate->idtr.limit = READ16(cpustate,ea);
+ cpustate->idtr.base = READ32(cpustate,ea + 2) & 0xffffff;
+ CYCLES(cpustate,CYCLES_LIDT);
+ break;
+ }
+ case 4: /* SMSW */
+ {
+ if( modrm >= 0xc0 ) {
+ STORE_RM16(modrm, cpustate->cr[0]);
+ CYCLES(cpustate,CYCLES_SMSW_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ WRITE16(cpustate,ea, cpustate->cr[0]);
+ CYCLES(cpustate,CYCLES_SMSW_MEM);
+ }
+ break;
+ }
+ case 6: /* LMSW */
+ {
+ // TODO: Check for protection fault
+ UINT8 b;
+ if( modrm >= 0xc0 ) {
+ b = LOAD_RM8(modrm);
+ CYCLES(cpustate,CYCLES_LMSW_REG);
+ } else {
+ ea = GetEA(cpustate,modrm);
+ CYCLES(cpustate,CYCLES_LMSW_MEM);
+ b = READ8(cpustate,ea);
+ }
+ cpustate->cr[0] &= ~0x03;
+ cpustate->cr[0] |= b & 0x03;
+ break;
+ }
+ case 7: /* INVLPG */
+ {
+ // Nothing to do ?
+ break;
+ }
+ default:
+ fatalerror("i486: unimplemented opcode 0x0f 01 /%d at %08X", (modrm >> 3) & 0x7, cpustate->eip - 2);
+ break;
+ }
+}
+
+static void I486OP(group0F01_32)(i386_state *cpustate) // Opcode 0x0f 01
+{
+ UINT8 modrm = FETCH(cpustate);
+ UINT32 address, ea;
+
+ switch( (modrm >> 3) & 0x7 )
+ {
+ case 0: /* SGDT */
+ {
+ if( modrm >= 0xc0 ) {
+ address = LOAD_RM32(modrm);
+ ea = i386_translate( cpustate, CS, address );
+ } else {
+ ea = GetEA(cpustate,modrm);
+ }
+ WRITE16(cpustate,ea, cpustate->gdtr.limit);
+ WRITE32(cpustate,ea + 2, cpustate->gdtr.base);
+ CYCLES(cpustate,CYCLES_SGDT);
+ break;
+ }
+ case 1: /* SIDT */
+ {
+ if (modrm >= 0xc0)
+ {
+ address = LOAD_RM32(modrm);
+ ea = i386_translate( cpustate, CS, address );
+ }
+ else
+ {
+ ea = GetEA(cpustate,modrm);
+ }
+ WRITE16(cpustate,ea, cpustate->idtr.limit);
+ WRITE32(cpustate,ea + 2, cpustate->idtr.base);
+ CYCLES(cpustate,CYCLES_SIDT);
+ break;
+ }
+ case 2: /* LGDT */
+ {
+ if( modrm >= 0xc0 ) {
+ address = LOAD_RM32(modrm);
+ ea = i386_translate( cpustate, CS, address );
+ } else {
+ ea = GetEA(cpustate,modrm);
+ }
+ cpustate->gdtr.limit = READ16(cpustate,ea);
+ cpustate->gdtr.base = READ32(cpustate,ea + 2);
+ CYCLES(cpustate,CYCLES_LGDT);
+ break;
+ }
+ case 3: /* LIDT */
+ {
+ if( modrm >= 0xc0 ) {
+ address = LOAD_RM32(modrm);
+ ea = i386_translate( cpustate, CS, address );
+ } else {
+ ea = GetEA(cpustate,modrm);
+ }
+ cpustate->idtr.limit = READ16(cpustate,ea);
+ cpustate->idtr.base = READ32(cpustate,ea + 2);
+ CYCLES(cpustate,CYCLES_LIDT);
+ break;
+ }
+ case 7: /* INVLPG */
+ {
+ // Nothing to do ?
+ break;
+ }
+ default:
+ fatalerror("i486: unimplemented opcode 0x0f 01 /%d at %08X", (modrm >> 3) & 0x7, cpustate->eip - 2);
+ break;
+ }
+}
+
+static void I486OP(bswap_eax)(i386_state *cpustate) // Opcode 0x0f 38
+{
+ REG32(EAX) = SWITCH_ENDIAN_32(REG32(EAX));
+ CYCLES(cpustate,1); // TODO
+}
+
+static void I486OP(bswap_ecx)(i386_state *cpustate) // Opcode 0x0f 39
+{
+ REG32(ECX) = SWITCH_ENDIAN_32(REG32(ECX));
+ CYCLES(cpustate,1); // TODO
+}
+
+static void I486OP(bswap_edx)(i386_state *cpustate) // Opcode 0x0f 3A
+{
+ REG32(EDX) = SWITCH_ENDIAN_32(REG32(EDX));
+ CYCLES(cpustate,1); // TODO
+}
+
+static void I486OP(bswap_ebx)(i386_state *cpustate) // Opcode 0x0f 3B
+{
+ REG32(EBX) = SWITCH_ENDIAN_32(REG32(EBX));
+ CYCLES(cpustate,1); // TODO
+}
+
+static void I486OP(bswap_esp)(i386_state *cpustate) // Opcode 0x0f 3C
+{
+ REG32(ESP) = SWITCH_ENDIAN_32(REG32(ESP));
+ CYCLES(cpustate,1); // TODO
+}
+
+static void I486OP(bswap_ebp)(i386_state *cpustate) // Opcode 0x0f 3D
+{
+ REG32(EBP) = SWITCH_ENDIAN_32(REG32(EBP));
+ CYCLES(cpustate,1); // TODO
+}
+
+static void I486OP(bswap_esi)(i386_state *cpustate) // Opcode 0x0f 3E
+{
+ REG32(ESI) = SWITCH_ENDIAN_32(REG32(ESI));
+ CYCLES(cpustate,1); // TODO
+}
+
+static void I486OP(bswap_edi)(i386_state *cpustate) // Opcode 0x0f 3F
+{
+ REG32(EDI) = SWITCH_ENDIAN_32(REG32(EDI));
+ CYCLES(cpustate,1); // TODO
+}
diff --git a/trunk/src/emu/cpu/i386/pentops.c b/trunk/src/emu/cpu/i386/pentops.c
new file mode 100644
index 00000000000..42931ca6ba4
--- /dev/null
+++ b/trunk/src/emu/cpu/i386/pentops.c
@@ -0,0 +1,53 @@
+// Pentium+ specific opcodes
+
+static void PENTIUMOP(rdmsr)(i386_state *cpustate) // Opcode 0x0f 32
+{
+ // TODO
+ CYCLES(cpustate,CYCLES_RDMSR);
+}
+
+static void PENTIUMOP(wrmsr)(i386_state *cpustate) // Opcode 0x0f 30
+{
+ // TODO
+ CYCLES(cpustate,1); // TODO: correct cycle count
+}
+
+static void PENTIUMOP(rdtsc)(i386_state *cpustate) // Opcode 0x0f 31
+{
+ UINT64 ts = cpustate->tsc + (cpustate->base_cycles - cpustate->cycles);
+ REG32(EAX) = (UINT32)(ts);
+ REG32(EDX) = (UINT32)(ts >> 32);
+
+ CYCLES(cpustate,CYCLES_RDTSC);
+}
+
+static void I386OP(cyrix_unknown)(i386_state *cpustate) // Opcode 0x0f 74
+{
+ CYCLES(cpustate,1);
+}
+
+static void PENTIUMOP(cmpxchg8b_m64)(i386_state *cpustate) // Opcode 0x0f c7
+{
+ UINT8 modm = FETCH(cpustate);
+ if( modm >= 0xc0 ) {
+ fatalerror("pentium: cmpxchg8b_m64 - invalid modm");
+ } else {
+ UINT32 ea = GetEA(cpustate,modm);
+ UINT64 value = READ64(cpustate,ea);
+ UINT64 edx_eax = (((UINT64) REG32(EDX)) << 32) | REG32(EAX);
+ UINT64 ecx_ebx = (((UINT64) REG32(ECX)) << 32) | REG32(EBX);
+
+ if( value == edx_eax ) {
+ WRITE64(cpustate,ea, ecx_ebx);
+ cpustate->ZF = 1;
+ CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_T);
+ } else {
+ REG32(EDX) = (UINT32) (value >> 32);
+ REG32(EAX) = (UINT32) (value >> 0);
+ cpustate->ZF = 0;
+ CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_F);
+ }
+ }
+}
+
+
diff --git a/trunk/src/emu/cpu/i386/x87ops.c b/trunk/src/emu/cpu/i386/x87ops.c
new file mode 100644
index 00000000000..0fd441abbaf
--- /dev/null
+++ b/trunk/src/emu/cpu/i386/x87ops.c
@@ -0,0 +1,391 @@
+// Intel x87 FPU opcodes
+
+#define ST(x) (cpustate->fpu_reg[(cpustate->fpu_top + (x)) & 7])
+#define FPU_INFINITY_DOUBLE U64(0x7ff0000000000000)
+#define FPU_INFINITY_SINGLE (0x7f800000)
+#define FPU_SIGN_BIT_DOUBLE U64(0x8000000000000000)
+#define FPU_SIGN_BIT_SINGLE (0x80000000)
+
+// FPU control word flags
+#define FPU_MASK_INVALID_OP 0x0001
+#define FPU_MASK_DENORMAL_OP 0x0002
+#define FPU_MASK_ZERO_DIVIDE 0x0004
+#define FPU_MASK_OVERFLOW 0x0008
+#define FPU_MASK_UNDERFLOW 0x0010
+#define FPU_MASK_PRECISION 0x0020
+
+// FPU status word flags
+#define FPU_BUSY 0x8000
+#define FPU_C3 0x4000
+#define FPU_STACK_TOP_MASK 0x3800
+#define FPU_C2 0x0400
+#define FPU_C1 0x0200
+#define FPU_C0 0x0100
+#define FPU_ERROR_SUMMARY 0x0080
+#define FPU_STACK_FAULT 0x0040
+#define FPU_EXCEPTION_PRECISION 0x0020
+#define FPU_EXCEPTION_UNDERFLOW 0x0010
+#define FPU_EXCEPTION_OVERFLOW 0x0008
+#define FPU_EXCEPTION_ZERO_DIVIDE 0x0004
+#define FPU_EXCEPTION_DENORMAL_OP 0x0002
+#define FPU_EXCEPTION_INVALID_OP 0x0001
+
+INLINE void FPU_PUSH(i386_state *cpustate, X87_REG value)
+{
+ cpustate->fpu_top--;
+ if (cpustate->fpu_top < 0)
+ {
+ cpustate->fpu_top = 7;
+ }
+
+ cpustate->fpu_reg[cpustate->fpu_top] = value;
+}
+
+INLINE X87_REG FPU_POP(i386_state *cpustate)
+{
+ X87_REG value = cpustate->fpu_reg[cpustate->fpu_top];
+
+ cpustate->fpu_tag_word |= 3 << (cpustate->fpu_top * 2); // set FPU register tag to 3 (empty)
+
+ cpustate->fpu_top++;
+ if (cpustate->fpu_top > 7)
+ {
+ cpustate->fpu_top = 0;
+ }
+
+ return value;
+}
+
+static void I386OP(fpu_group_d8)(i386_state *cpustate) // Opcode 0xd8
+{
+ UINT8 modrm = FETCH(cpustate);
+ if (modrm < 0xc0)
+ {
+ UINT32 ea = GetEA(cpustate,modrm);
+
+ switch ((modrm >> 3) & 0x7)
+ {
+ case 6: // FDIV
+ UINT32 src = READ32(cpustate,ea);
+ if(src == 0)
+ fatalerror("FPU: Unimplemented Divide-by-zero exception at %08X.\n", cpustate->pc-2);
+ ST(0).f = ST(0).f / src;
+ CYCLES(cpustate,1); // TODO
+ break;
+ }
+ }
+ else
+ {
+ fatalerror("I386: FPU Op D8 %02X at %08X", modrm, cpustate->pc-2);
+ }
+}
+
+static void I386OP(fpu_group_d9)(i386_state *cpustate) // Opcode 0xd9
+{
+ UINT8 modrm = FETCH(cpustate);
+
+ if (modrm < 0xc0)
+ {
+ UINT32 ea = GetEA(cpustate,modrm);
+
+ switch ((modrm >> 3) & 0x7)
+ {
+ case 5: // FLDCW
+ {
+ cpustate->fpu_control_word = READ16(cpustate,ea);
+ CYCLES(cpustate,1); // TODO
+ break;
+ }
+
+ case 6: // FSTENV
+ { // TODO: 32-bit operand size
+ WRITE16(cpustate,ea, cpustate->fpu_control_word);
+ WRITE16(cpustate,ea+2, cpustate->fpu_status_word);
+ WRITE16(cpustate,ea+4, cpustate->fpu_tag_word);
+ WRITE16(cpustate,ea+6, cpustate->fpu_inst_ptr & 0xffff);
+ WRITE16(cpustate,ea+8, (cpustate->fpu_opcode & 0x07ff) | ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4));
+ WRITE16(cpustate,ea+10, cpustate->fpu_data_ptr & 0xffff);
+ WRITE16(cpustate,ea+12, ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4));
+ CYCLES(cpustate,1); // TODO
+ break;
+ }
+
+ case 7: // FSTCW
+ {
+ WRITE16(cpustate,ea, cpustate->fpu_control_word);
+ CYCLES(cpustate,1); // TODO
+ break;
+ }
+
+ default:
+ fatalerror("I386: FPU Op D9 %02X at %08X", modrm, cpustate->pc-2);
+ }
+ }
+ else
+ {
+ switch (modrm & 0x3f)
+ {
+ // FLD
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+ {
+ X87_REG t = ST(modrm & 7);
+ FPU_PUSH(cpustate,t);
+ CYCLES(cpustate,1); // TODO
+ break;
+ }
+
+ case 0x20: // FCHS
+ {
+ ST(0).i ^= FPU_SIGN_BIT_DOUBLE;
+ CYCLES(cpustate,1); // TODO
+ break;
+ }
+
+ case 0x28: // FLD1
+ {
+ X87_REG t;
+ t.f = 1.0;
+ FPU_PUSH(cpustate,t);
+ CYCLES(cpustate,1); // TODO
+ break;
+ }
+
+ case 0x2e: // FLDZ
+ {
+ X87_REG t;
+ t.f = 0.0;
+ FPU_PUSH(cpustate,t);
+ CYCLES(cpustate,1); // TODO
+ break;
+ }
+ default:
+ fatalerror("I386: FPU Op D9 %02X at %08X", modrm, cpustate->pc-2);
+ }
+ }
+}
+
+static void I386OP(fpu_group_da)(i386_state *cpustate) // Opcode 0xda
+{
+ UINT8 modrm = FETCH(cpustate);
+ fatalerror("I386: FPU Op DA %02X at %08X", modrm, cpustate->pc-2);
+}
+
+static void I386OP(fpu_group_db)(i386_state *cpustate) // Opcode 0xdb
+{
+ UINT8 modrm = FETCH(cpustate);
+
+ if (modrm < 0xc0)
+ {
+ fatalerror("I386: FPU Op DB %02X at %08X", modrm, cpustate->pc-2);
+ }
+ else
+ {
+ switch (modrm & 0x3f)
+ {
+ case 0x22: // FCLEX
+ {
+ // clears exception flags and busy bit.
+ cpustate->fpu_status_word &= ~0x80ff;
+
+ CYCLES(cpustate,1); // TODO
+ break;
+ }
+ case 0x23: // FINIT
+ {
+ cpustate->fpu_control_word = 0x37f;
+ cpustate->fpu_status_word = 0;
+ cpustate->fpu_tag_word = 0xffff;
+ cpustate->fpu_data_ptr = 0;
+ cpustate->fpu_inst_ptr = 0;
+ cpustate->fpu_opcode = 0;
+
+ CYCLES(cpustate,1); // TODO
+ break;
+ }
+
+ case 0x24: // FSETPM (treated as nop on 387+)
+ {
+ CYCLES(cpustate,1);
+ break;
+ }
+
+ default:
+ fatalerror("I386: FPU Op DB %02X at %08X", modrm, cpustate->pc-2);
+ }
+ }
+}
+
+static void I386OP(fpu_group_dc)(i386_state *cpustate) // Opcode 0xdc
+{
+ UINT8 modrm = FETCH(cpustate);
+
+ if (modrm < 0xc0)
+ {
+ //UINT32 ea = GetEA(cpustate,modrm);
+
+ switch ((modrm >> 3) & 0x7)
+ {
+ default:
+ fatalerror("I386: FPU Op DC %02X at %08X", modrm, cpustate->pc-2);
+ }
+ }
+ else
+ {
+ switch (modrm & 0x3f)
+ {
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
+ {
+ // FDIVR
+ if ((ST(modrm & 7).i & U64(0x7fffffffffffffff)) == 0)
+ {
+ // set result as infinity if zero divide is masked
+ if (cpustate->fpu_control_word & FPU_MASK_ZERO_DIVIDE)
+ {
+ ST(modrm & 7).i |= FPU_INFINITY_DOUBLE;
+ }
+ }
+ else
+ {
+ ST(modrm & 7).f = ST(0).f / ST(modrm & 7).f;
+ }
+ CYCLES(cpustate,1); // TODO
+ break;
+ }
+
+ default:
+ fatalerror("I386: FPU Op DC %02X at %08X", modrm, cpustate->pc-2);
+ }
+ }
+}
+
+static void I386OP(fpu_group_dd)(i386_state *cpustate) // Opcode 0xdd
+{
+ UINT8 modrm = FETCH(cpustate);
+
+ if (modrm < 0xc0)
+ {
+ UINT32 ea = GetEA(cpustate,modrm);
+
+ switch ((modrm >> 3) & 0x7)
+ {
+ case 7: // FSTSW
+ {
+ WRITE16(cpustate,ea, (cpustate->fpu_status_word & ~FPU_STACK_TOP_MASK) | (cpustate->fpu_top << 10));
+ CYCLES(cpustate,1); // TODO
+ break;
+ }
+
+ default:
+ fatalerror("I386: FPU Op DD %02X at %08X", modrm, cpustate->pc-2);
+ }
+ }
+ else
+ {
+ switch (modrm & 0x3f)
+ {
+ default:
+ fatalerror("I386: FPU Op DD %02X at %08X", modrm, cpustate->pc-2);
+ }
+ }
+}
+
+static void I386OP(fpu_group_de)(i386_state *cpustate) // Opcode 0xde
+{
+ UINT8 modrm = FETCH(cpustate);
+
+ if (modrm < 0xc0)
+ {
+ // UINT32 ea = GetEA(cpustate,modrm);
+
+ switch ((modrm >> 3) & 0x7)
+ {
+ default:
+ fatalerror("I386: FPU Op DE %02X at %08X", modrm, cpustate->pc-2);
+ }
+ }
+ else
+ {
+ switch (modrm & 0x3f)
+ {
+ case 0x19: // FCOMPP
+ {
+ cpustate->fpu_status_word &= ~(FPU_C3 | FPU_C2 | FPU_C0);
+ if (ST(0).f > ST(1).f)
+ {
+ // C3 = 0, C2 = 0, C0 = 0
+ }
+ else if (ST(0).f < ST(1).f)
+ {
+ cpustate->fpu_status_word |= FPU_C0;
+ }
+ else if (ST(0).f == ST(1).f)
+ {
+ cpustate->fpu_status_word |= FPU_C3;
+ }
+ else
+ {
+ // unordered
+ cpustate->fpu_status_word |= (FPU_C3 | FPU_C2 | FPU_C0);
+ }
+ FPU_POP(cpustate);
+ FPU_POP(cpustate);
+ CYCLES(cpustate,1); // TODO
+ break;
+ }
+
+ // FDIVP
+ case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
+ {
+ if ((ST(0).i & U64(0x7fffffffffffffff)) == 0)
+ {
+ // set result as infinity if zero divide is masked
+ if (cpustate->fpu_control_word & FPU_MASK_ZERO_DIVIDE)
+ {
+ ST(modrm & 7).i |= FPU_INFINITY_DOUBLE;
+ }
+ }
+ else
+ {
+ ST(modrm & 7).f = ST(modrm & 7).f / ST(0).f;
+ }
+ FPU_POP(cpustate);
+ CYCLES(cpustate,1); // TODO
+ break;
+ }
+
+ default:
+ fatalerror("I386: FPU Op DE %02X at %08X", modrm, cpustate->pc-2);
+ }
+ }
+}
+
+static void I386OP(fpu_group_df)(i386_state *cpustate) // Opcode 0xdf
+{
+ UINT8 modrm = FETCH(cpustate);
+
+ if (modrm < 0xc0)
+ {
+ // UINT32 ea = GetEA(cpustate,modrm);
+
+ switch ((modrm >> 3) & 0x7)
+ {
+ default:
+ fatalerror("I386: FPU Op DF %02X at %08X", modrm, cpustate->pc-2);
+ }
+ }
+ else
+ {
+ switch (modrm & 0x3f)
+ {
+ case 0x20: // FSTSW AX
+ {
+ REG16(AX) = (cpustate->fpu_status_word & ~FPU_STACK_TOP_MASK) | (cpustate->fpu_top << 10);
+ CYCLES(cpustate,1); // TODO
+ break;
+ }
+
+ default:
+ fatalerror("I386: FPU Op DF %02X at %08X", modrm, cpustate->pc-2);
+ }
+ }
+}
diff --git a/trunk/src/emu/cpu/i4004/4004dasm.c b/trunk/src/emu/cpu/i4004/4004dasm.c
new file mode 100644
index 00000000000..bf94e274e92
--- /dev/null
+++ b/trunk/src/emu/cpu/i4004/4004dasm.c
@@ -0,0 +1,133 @@
+/*****************************************************************************
+ *
+ * 4004dasm.c
+ *
+ * Intel 4004 CPU Disassembly
+ *
+ * Initial version by Miodrag Milanovic
+ *
+ *****************************************************************************/
+
+#include "emu.h"
+
+#define OP(A) oprom[(A) - PC]
+#define ARG(A) opram[(A) - PC]
+
+CPU_DISASSEMBLE( i4004 )
+{
+ UINT32 flags = 0;
+ UINT8 op;
+ unsigned PC = pc;
+ UINT16 page = PC & 0x0f00;
+ switch (op = OP(pc++))
+ {
+ case 0x00: sprintf (buffer,"nop"); break;
+ case 0x11: sprintf (buffer,"jnt $%03x",page | ARG(pc)); pc++; break;
+ case 0x12: sprintf (buffer,"jc $%03x",page | ARG(pc)); pc++; break;
+ case 0x14: sprintf (buffer,"jz $%03x",page | ARG(pc)); pc++; break;
+ case 0x19: sprintf (buffer,"jt $%03x",page | ARG(pc)); pc++; break;
+ case 0x1a: sprintf (buffer,"jnc $%03x",page | ARG(pc)); pc++; break;
+ case 0x1c: sprintf (buffer,"jnz $%03x",page | ARG(pc)); pc++; break;
+ case 0x10: case 0x13: case 0x15: case 0x16:
+ case 0x17: case 0x18: case 0x1b: case 0x1d:
+ case 0x1e: case 0x1f:
+ sprintf (buffer,"jcn $%01x,$%03x",op & 0x0f,page | ARG(pc)); pc++; break;
+ case 0x20: case 0x22: case 0x24: case 0x26:
+ case 0x28: case 0x2a: case 0x2c: case 0x2e:
+ sprintf (buffer,"fim $%01x,$%02x",op & 0x0f,OP(pc)); pc++; break;
+ case 0x21: case 0x23: case 0x25: case 0x27:
+ case 0x29: case 0x2b: case 0x2d: case 0x2f:
+ sprintf (buffer,"src $%01x",(op & 0x0f)-1); break;
+ case 0x30: case 0x32: case 0x34: case 0x36:
+ case 0x38: case 0x3a: case 0x3c: case 0x3e:
+ sprintf (buffer,"fin $%01x",op & 0x0f); break;
+ case 0x31: case 0x33: case 0x35: case 0x37:
+ case 0x39: case 0x3b: case 0x3d: case 0x3f:
+ sprintf (buffer,"jin $%01x",(op & 0x0f)-1); break;
+ case 0x40: case 0x41: case 0x42: case 0x43:
+ case 0x44: case 0x45: case 0x46: case 0x47:
+ case 0x48: case 0x49: case 0x4a: case 0x4b:
+ case 0x4c: case 0x4d: case 0x4e: case 0x4f:
+ sprintf (buffer,"jun $%01x%02x",op & 0x0f,ARG(pc)); pc++; break;
+ case 0x50: case 0x51: case 0x52: case 0x53:
+ case 0x54: case 0x55: case 0x56: case 0x57:
+ case 0x58: case 0x59: case 0x5a: case 0x5b:
+ case 0x5c: case 0x5d: case 0x5e: case 0x5f:
+ sprintf (buffer,"jms $%01x%02x",op & 0x0f,ARG(pc)); pc++; break;
+ case 0x60: case 0x61: case 0x62: case 0x63:
+ case 0x64: case 0x65: case 0x66: case 0x67:
+ case 0x68: case 0x69: case 0x6a: case 0x6b:
+ case 0x6c: case 0x6d: case 0x6e: case 0x6f:
+ sprintf (buffer,"inc $%01x",op & 0x0f); break;
+ case 0x70: case 0x71: case 0x72: case 0x73:
+ case 0x74: case 0x75: case 0x76: case 0x77:
+ case 0x78: case 0x79: case 0x7a: case 0x7b:
+ case 0x7c: case 0x7d: case 0x7e: case 0x7f:
+ sprintf (buffer,"isz $%01x,%03x",op & 0x0f,page | ARG(pc)); pc++; break;
+ case 0x80: case 0x81: case 0x82: case 0x83:
+ case 0x84: case 0x85: case 0x86: case 0x87:
+ case 0x88: case 0x89: case 0x8a: case 0x8b:
+ case 0x8c: case 0x8d: case 0x8e: case 0x8f:
+ sprintf (buffer,"add $%01x",op & 0x0f); break;
+ case 0x90: case 0x91: case 0x92: case 0x93:
+ case 0x94: case 0x95: case 0x96: case 0x97:
+ case 0x98: case 0x99: case 0x9a: case 0x9b:
+ case 0x9c: case 0x9d: case 0x9e: case 0x9f:
+ sprintf (buffer,"sub $%01x",op & 0x0f); break;
+ case 0xa0: case 0xa1: case 0xa2: case 0xa3:
+ case 0xa4: case 0xa5: case 0xa6: case 0xa7:
+ case 0xa8: case 0xa9: case 0xaa: case 0xab:
+ case 0xac: case 0xad: case 0xae: case 0xaf:
+ sprintf (buffer,"ld $%01x",op & 0x0f); break;
+ case 0xb0: case 0xb1: case 0xb2: case 0xb3:
+ case 0xb4: case 0xb5: case 0xb6: case 0xb7:
+ case 0xb8: case 0xb9: case 0xba: case 0xbb:
+ case 0xbc: case 0xbd: case 0xbe: case 0xbf:
+ sprintf (buffer,"xch $%01x",op & 0x0f); break;
+ case 0xc0: case 0xc1: case 0xc2: case 0xc3:
+ case 0xc4: case 0xc5: case 0xc6: case 0xc7:
+ case 0xc8: case 0xc9: case 0xca: case 0xcb:
+ case 0xcc: case 0xcd: case 0xce: case 0xcf:
+ sprintf (buffer,"bbl $%01x",op & 0x0f); break;
+ case 0xd0: case 0xd1: case 0xd2: case 0xd3:
+ case 0xd4: case 0xd5: case 0xd6: case 0xd7:
+ case 0xd8: case 0xd9: case 0xda: case 0xdb:
+ case 0xdc: case 0xdd: case 0xde: case 0xdf:
+ sprintf (buffer,"ldm $%01x",op & 0x0f); break;
+
+ case 0xe0: sprintf (buffer,"wrm"); break;
+ case 0xe1: sprintf (buffer,"wmp"); break;
+ case 0xe2: sprintf (buffer,"wrr"); break;
+ case 0xe3: sprintf (buffer,"wpm"); break;
+ case 0xe4: sprintf (buffer,"wr0"); break;
+ case 0xe5: sprintf (buffer,"wr1"); break;
+ case 0xe6: sprintf (buffer,"wr2"); break;
+ case 0xe7: sprintf (buffer,"wr3"); break;
+ case 0xe8: sprintf (buffer,"sbm"); break;
+ case 0xe9: sprintf (buffer,"rdm"); break;
+ case 0xea: sprintf (buffer,"rdr"); break;
+ case 0xeb: sprintf (buffer,"adm"); break;
+ case 0xec: sprintf (buffer,"rd0"); break;
+ case 0xed: sprintf (buffer,"rd1"); break;
+ case 0xee: sprintf (buffer,"rd2"); break;
+ case 0xef: sprintf (buffer,"rd3"); break;
+
+ case 0xf0: sprintf (buffer,"clb"); break;
+ case 0xf1: sprintf (buffer,"clc"); break;
+ case 0xf2: sprintf (buffer,"iac"); break;
+ case 0xf3: sprintf (buffer,"cmc"); break;
+ case 0xf4: sprintf (buffer,"cma"); break;
+ case 0xf5: sprintf (buffer,"ral"); break;
+ case 0xf6: sprintf (buffer,"rar"); break;
+ case 0xf7: sprintf (buffer,"tcc"); break;
+ case 0xf8: sprintf (buffer,"dac"); break;
+ case 0xf9: sprintf (buffer,"tcs"); break;
+ case 0xfa: sprintf (buffer,"stc"); break;
+ case 0xfb: sprintf (buffer,"daa"); break;
+ case 0xfc: sprintf (buffer,"kbp"); break;
+ case 0xfd: sprintf (buffer,"dcl"); break;
+
+ default : sprintf (buffer,"illegal"); break;
+ }
+ return (pc - PC) | flags | DASMFLAG_SUPPORTED;
+}
diff --git a/trunk/src/emu/cpu/i4004/i4004.c b/trunk/src/emu/cpu/i4004/i4004.c
new file mode 100644
index 00000000000..b529ba1ba9e
--- /dev/null
+++ b/trunk/src/emu/cpu/i4004/i4004.c
@@ -0,0 +1,622 @@
+/*****************************************************************************
+ *
+ * i4004.c
+ *
+ * Intel 4004 CPU
+ *
+ * Initial version by Miodrag Milanovic
+ *
+ *****************************************************************************/
+#include "emu.h"
+#include "debugger.h"
+#include "i4004.h"
+
+#define VERBOSE 0
+
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+static const UINT8 kbp_table[] = { 0x00,0x01,0x02,0x0f,0x03,0x0f,0x0f,0x0f,0x04,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f };
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _i4004_state i4004_state;
+struct _i4004_state
+{
+ UINT8 A; // Accumulator
+ UINT8 R[8];
+ PAIR ADDR[4]; // Address registers
+ PAIR RAM;
+ UINT8 C; // Carry flag
+ UINT8 TEST; // Test PIN status
+ PAIR PC; // It is in fact one of ADDR regs
+ UINT8 flags; // used for I/O only
+
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ address_space *data;
+ address_space *io;
+ int icount;
+ int pc_pos; // PC possition in ADDR
+ int addr_mask;
+};
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+#define GET_PC (cpustate->ADDR[cpustate->pc_pos])
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+INLINE i4004_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == I4004);
+ return (i4004_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+INLINE UINT8 ROP(i4004_state *cpustate)
+{
+ UINT8 retVal = cpustate->direct->read_decrypted_byte(GET_PC.w.l);
+ GET_PC.w.l = (GET_PC.w.l + 1) & 0x0fff;
+ cpustate->PC = GET_PC;
+ return retVal;
+}
+
+INLINE UINT8 READ_ROM(i4004_state *cpustate)
+{
+ return cpustate->direct->read_decrypted_byte((GET_PC.w.l & 0x0f00) | cpustate->R[0]);
+}
+
+INLINE void WPM(i4004_state *cpustate)
+{
+ UINT8 t = (cpustate->program->read_byte(cpustate->RAM.d) << 4) | cpustate->A;
+ cpustate->program->write_byte((GET_PC.w.l & 0x0f00) | cpustate->RAM.d, t);
+}
+
+
+INLINE UINT8 ARG(i4004_state *cpustate)
+{
+ UINT8 retVal = cpustate->direct->read_raw_byte(GET_PC.w.l);
+ GET_PC.w.l = (GET_PC.w.l + 1) & 0x0fff;
+ cpustate->PC = GET_PC;
+ return retVal;
+}
+
+INLINE UINT8 RM(i4004_state *cpustate)
+{
+ return cpustate->data->read_byte(cpustate->RAM.d) & 0x0f;
+}
+
+INLINE UINT8 RMS(i4004_state *cpustate, UINT32 a)
+{
+ return cpustate->data->read_byte((cpustate->RAM.d & 0xff0) + a) >> 4;
+}
+
+INLINE void WM(i4004_state *cpustate, UINT8 v)
+{
+ UINT8 t = cpustate->data->read_byte(cpustate->RAM.d);
+ cpustate->data->write_byte(cpustate->RAM.d, (t & 0xf0) | v);
+}
+
+
+INLINE void WMP(i4004_state *cpustate, UINT8 v)
+{
+ cpustate->io->write_byte((cpustate->RAM.d >> 6) | 0x10, v & 0x0f);
+}
+
+INLINE void WMS(i4004_state *cpustate, UINT32 a, UINT8 v)
+{
+ UINT8 t = cpustate->data->read_byte((cpustate->RAM.d & 0xff0) + a);
+ cpustate->data->write_byte((cpustate->RAM.d & 0xff0) + a, (t & 0x0f) | (v<<4));
+}
+
+INLINE UINT8 RIO(i4004_state *cpustate)
+{
+ return cpustate->io->read_byte(cpustate->RAM.b.l >> 4) & 0x0f;
+}
+
+INLINE void WIO(i4004_state *cpustate, UINT8 v)
+{
+ cpustate->io->write_byte(cpustate->RAM.b.l >> 4, v & 0x0f);
+}
+
+INLINE UINT8 GET_REG(i4004_state *cpustate, UINT8 num)
+{
+ UINT8 r = cpustate->R[num>>1];
+ if (num & 1) {
+ return r & 0x0f;
+ } else {
+ return (r >> 4) & 0x0f;
+ }
+}
+
+INLINE void SET_REG(i4004_state *cpustate, UINT8 num, UINT8 val)
+{
+ if (num & 1) {
+ cpustate->R[num>>1] = (cpustate->R[num>>1] & 0xf0) + (val & 0x0f);
+ } else {
+ cpustate->R[num>>1] = (cpustate->R[num>>1] & 0x0f) + ((val & 0x0f) << 4);
+ }
+}
+
+INLINE void PUSH_STACK(i4004_state *cpustate)
+{
+ cpustate->pc_pos = (cpustate->pc_pos + 1) & cpustate->addr_mask;
+}
+
+INLINE void POP_STACK(i4004_state *cpustate)
+{
+ cpustate->ADDR[cpustate->pc_pos].d = 0;
+ cpustate->pc_pos = (cpustate->pc_pos - 1) & cpustate->addr_mask;
+}
+
+void i4004_set_test(device_t *device, UINT8 val)
+{
+ i4004_state *cpustate = get_safe_token(device);
+ cpustate->TEST = val;
+}
+
+static void execute_one(i4004_state *cpustate, int opcode)
+{
+ cpustate->icount -= 8;
+ switch (opcode)
+ {
+ case 0x00: /* NOP */
+ /* no op */
+ break;
+ case 0x10: case 0x11: case 0x12: case 0x13:
+ case 0x14: case 0x15: case 0x16: case 0x17:
+ case 0x18: case 0x19: case 0x1a: case 0x1b:
+ case 0x1c: case 0x1d: case 0x1e: case 0x1f: /* JCN */
+ {
+ UINT8 arg = ARG(cpustate);
+
+ UINT8 C1 = BIT(opcode,3);
+ UINT8 C2 = BIT(opcode,2);
+ UINT8 C3 = BIT(opcode,1);
+ UINT8 C4 = BIT(opcode,0);
+ UINT8 JUMP = (((cpustate->A == 0) ? 1 : 0) & C2) | ((cpustate->C) & C3) | ((cpustate->TEST ^ 1) & C4);
+ cpustate->icount -= 8;
+
+ if(((C1 ^ 1) & JUMP) | (C1 & (JUMP ^ 1))) {
+ GET_PC.w.l = (GET_PC.w.l & 0x0f00) | arg;
+ cpustate->PC = GET_PC;
+ }
+ }
+ break;
+ case 0x20: case 0x22: case 0x24: case 0x26:
+ case 0x28: case 0x2a: case 0x2c: case 0x2e: /* FIM */
+ cpustate->icount -= 8;
+ cpustate->R[(opcode & 0x0f)>>1] = ROP(cpustate);
+ break;
+ case 0x21: case 0x23: case 0x25: case 0x27:
+ case 0x29: case 0x2b: case 0x2d: case 0x2f: /* SRC */
+ cpustate->RAM.b.l = cpustate->R[(opcode & 0x0f)>>1];
+ break;
+ case 0x30: case 0x32: case 0x34: case 0x36:
+ case 0x38: case 0x3a: case 0x3c: case 0x3e: /* FIN */
+ cpustate->icount -= 8;
+ cpustate->R[(opcode & 0x0f)>>1] = READ_ROM(cpustate);
+ break;
+ case 0x31: case 0x33: case 0x35: case 0x37:
+ case 0x39: case 0x3b: case 0x3d: case 0x3f: /* JIN */
+ GET_PC.w.l = (GET_PC.w.l & 0x0f00) | cpustate->R[(opcode & 0x0f)>>1];
+ cpustate->PC = GET_PC;
+ break;
+ case 0x40: case 0x41: case 0x42: case 0x43:
+ case 0x44: case 0x45: case 0x46: case 0x47:
+ case 0x48: case 0x49: case 0x4a: case 0x4b:
+ case 0x4c: case 0x4d: case 0x4e: case 0x4f: /* JUN */
+ cpustate->icount -= 8;
+ GET_PC.w.l = ((opcode & 0x0f) << 8) | ARG(cpustate);
+ cpustate->PC = GET_PC;
+ break;
+ case 0x50: case 0x51: case 0x52: case 0x53:
+ case 0x54: case 0x55: case 0x56: case 0x57:
+ case 0x58: case 0x59: case 0x5a: case 0x5b:
+ case 0x5c: case 0x5d: case 0x5e: case 0x5f: /* JMS */
+ {
+ UINT16 newPC = ((opcode & 0x0f) << 8) | ARG(cpustate);
+ cpustate->icount -= 8;
+ PUSH_STACK(cpustate);
+ GET_PC.w.l = newPC;
+ cpustate->PC = GET_PC;
+ }
+ break;
+ case 0x60: case 0x61: case 0x62: case 0x63:
+ case 0x64: case 0x65: case 0x66: case 0x67:
+ case 0x68: case 0x69: case 0x6a: case 0x6b:
+ case 0x6c: case 0x6d: case 0x6e: case 0x6f: /* INC */
+ SET_REG(cpustate, opcode & 0x0f, GET_REG(cpustate, opcode & 0x0f) + 1);
+ break;
+ case 0x70: case 0x71: case 0x72: case 0x73:
+ case 0x74: case 0x75: case 0x76: case 0x77:
+ case 0x78: case 0x79: case 0x7a: case 0x7b:
+ case 0x7c: case 0x7d: case 0x7e: case 0x7f: /* ISZ */
+ {
+ UINT8 val = (GET_REG(cpustate, opcode & 0x0f) + 1) & 0xf;
+ UINT16 addr = ARG(cpustate);
+ cpustate->icount -= 8;
+ SET_REG(cpustate, opcode & 0x0f, val);
+ if (val!=0) {
+ GET_PC.w.l = (GET_PC.w.l & 0x0f00) | addr;
+ }
+ cpustate->PC = GET_PC;
+ }
+ break;
+ case 0x80: case 0x81: case 0x82: case 0x83:
+ case 0x84: case 0x85: case 0x86: case 0x87:
+ case 0x88: case 0x89: case 0x8a: case 0x8b:
+ case 0x8c: case 0x8d: case 0x8e: case 0x8f: /* ADD */
+ {
+ UINT8 acc = cpustate->A + GET_REG(cpustate, opcode & 0x0f) + cpustate->C;
+ cpustate->A = acc & 0x0f;
+ cpustate->C = (acc >> 4) & 1;
+ }
+ break;
+ case 0x90: case 0x91: case 0x92: case 0x93:
+ case 0x94: case 0x95: case 0x96: case 0x97:
+ case 0x98: case 0x99: case 0x9a: case 0x9b:
+ case 0x9c: case 0x9d: case 0x9e: case 0x9f: /* SUB */
+ {
+ UINT8 acc = cpustate->A + (GET_REG(cpustate, opcode & 0x0f) ^ 0x0f) + (cpustate->C ^ 1);
+ cpustate->A = acc & 0x0f;
+ cpustate->C = (acc >> 4) & 1;
+ }
+ break;
+ case 0xa0: case 0xa1: case 0xa2: case 0xa3:
+ case 0xa4: case 0xa5: case 0xa6: case 0xa7:
+ case 0xa8: case 0xa9: case 0xaa: case 0xab:
+ case 0xac: case 0xad: case 0xae: case 0xaf: /* LD */
+ cpustate->A = GET_REG(cpustate, opcode & 0x0f);
+ break;
+ case 0xb0: case 0xb1: case 0xb2: case 0xb3:
+ case 0xb4: case 0xb5: case 0xb6: case 0xb7:
+ case 0xb8: case 0xb9: case 0xba: case 0xbb:
+ case 0xbc: case 0xbd: case 0xbe: case 0xbf: /* XCH */
+ {
+ UINT8 temp = cpustate->A;
+ cpustate->A = GET_REG(cpustate, opcode & 0x0f);
+ SET_REG(cpustate, opcode & 0x0f, temp);
+ }
+ break;
+ case 0xc0: case 0xc1: case 0xc2: case 0xc3:
+ case 0xc4: case 0xc5: case 0xc6: case 0xc7:
+ case 0xc8: case 0xc9: case 0xca: case 0xcb:
+ case 0xcc: case 0xcd: case 0xce: case 0xcf: /* BBL */
+ POP_STACK(cpustate);
+ cpustate->A = opcode & 0x0f;
+ cpustate->PC = GET_PC;
+ break;
+ case 0xd0: case 0xd1: case 0xd2: case 0xd3:
+ case 0xd4: case 0xd5: case 0xd6: case 0xd7:
+ case 0xd8: case 0xd9: case 0xda: case 0xdb:
+ case 0xdc: case 0xdd: case 0xde: case 0xdf: /* LDM */
+ cpustate->A = opcode & 0x0f;
+ break;
+ case 0xe0: /* WRM */
+ WM(cpustate,cpustate->A);
+ break;
+ case 0xe1: /* WMP */
+ WMP(cpustate,cpustate->A);
+ break;
+ case 0xe2: /* WRR */
+ WIO(cpustate,cpustate->A);
+ break;
+ case 0xe3: /* WPM */
+ WPM(cpustate);
+ break;
+ case 0xe4: /* WR0 */
+ WMS(cpustate,0,cpustate->A);
+ break;
+ case 0xe5: /* WR1 */
+ WMS(cpustate,1,cpustate->A);
+ break;
+ case 0xe6: /* WR2 */
+ WMS(cpustate,2,cpustate->A);
+ break;
+ case 0xe7: /* WR3 */
+ WMS(cpustate,3,cpustate->A);
+ break;
+ case 0xe8: /* SBM */
+ cpustate->A = cpustate->A + (RM(cpustate) ^ 0x0f) + (cpustate->C ^ 1);
+ cpustate->C = cpustate->A >> 4;
+ cpustate->A &= 0x0f;
+ break;
+ case 0xe9: /* RDM */
+ cpustate->A = RM(cpustate);
+ break;
+ case 0xea: /* RDR */
+ cpustate->A = RIO(cpustate);
+ break;
+ case 0xeb: /* ADM */
+ cpustate->A += RM(cpustate) + cpustate->C;
+ cpustate->C = cpustate->A >> 4;
+ cpustate->A &= 0x0f;
+ break;
+ case 0xec: /* RD0 */
+ cpustate->A = RMS(cpustate,0);
+ break;
+ case 0xed: /* RD1 */
+ cpustate->A = RMS(cpustate,1);
+ break;
+ case 0xee: /* RD2 */
+ cpustate->A = RMS(cpustate,2);
+ break;
+ case 0xef: /* RD3 */
+ cpustate->A = RMS(cpustate,3);
+ break;
+
+ case 0xf0: /* CLB */
+ cpustate->A = 0;
+ cpustate->C = 0;
+ break;
+ case 0xf1: /* CLC */
+ cpustate->C = 0;
+ break;
+ case 0xf2: /* IAC */
+ cpustate->A += 1;
+ cpustate->C = cpustate->A >> 4;
+ cpustate->A &= 0x0f;
+ break;
+ case 0xf3: /* CMC */
+ cpustate->C ^= 1;
+ break;
+ case 0xf4: /* CMA */
+ cpustate->A ^= 0x0f;
+ break;
+ case 0xf5: /* RAL */
+ cpustate->A = (cpustate->A << 1) | cpustate->C;
+ cpustate->C = cpustate->A >> 4;
+ cpustate->A &= 0x0f;
+ break;
+ case 0xf6: /* RAR */
+ {
+ UINT8 c = cpustate->A & 1;
+ cpustate->A = (cpustate->A >> 1) | (cpustate->C << 3);
+ cpustate->C = c;
+ }
+ break;
+ case 0xf7: /* TCC */
+ cpustate->A = cpustate->C;
+ cpustate->C = 0;
+ break;
+ case 0xf8: /* DAC */
+ cpustate->A = cpustate->A + 0x0f;
+ cpustate->C = cpustate->A >> 4;
+ cpustate->A &= 0x0f;
+ break;
+ case 0xf9: /* TCS */
+ cpustate->A = cpustate->C ? 10 : 9;
+ cpustate->C = 0;
+ break;
+ case 0xfa: /* STC */
+ cpustate->C = 1;
+ break;
+ case 0xfb: /* DAA */
+ if (cpustate->C || (cpustate->A > 9)) {
+ cpustate->A += 6;
+ }
+ if (cpustate->A > 0x0f) {
+ // it is unaffected if it is in range
+ cpustate->C = 1;
+ }
+ cpustate->A &= 0x0f;
+ break;
+ case 0xfc: /* KBP */
+ cpustate->A = kbp_table[cpustate->A];
+ break;
+ case 0xfd: /* DCL */
+ cpustate->RAM.b.h = cpustate->A;
+ break;
+ }
+}
+
+
+/***************************************************************************
+ COMMON EXECUTION
+***************************************************************************/
+
+static CPU_EXECUTE( i4004 )
+{
+ i4004_state *cpustate = get_safe_token(device);
+
+ do
+ {
+ debugger_instruction_hook(device, GET_PC.d);
+ execute_one(cpustate, ROP(cpustate));
+
+ } while (cpustate->icount > 0);
+}
+
+/***************************************************************************
+ CORE INITIALIZATION
+***************************************************************************/
+
+static CPU_INIT( i4004 )
+{
+ i4004_state *cpustate = get_safe_token(device);
+
+ /* set up the state table */
+ {
+ device_state_interface *state;
+ device->interface(state);
+ state->state_add(I4004_PC, "PC", cpustate->PC.w.l).mask(0x0fff);
+ state->state_add(STATE_GENPC, "GENPC", cpustate->PC.w.l).mask(0x0fff).noshow();
+ state->state_add(STATE_GENFLAGS, "GENFLAGS", cpustate->flags).mask(0x0f).callimport().callexport().noshow().formatstr("%4s");
+ state->state_add(I4004_A, "A", cpustate->A).mask(0x0f);
+
+ astring tempstr;
+ for (int regnum = 0; regnum < 8; regnum++)
+ state->state_add(I4004_R01 + regnum, tempstr.format("R%X%X", regnum*2, regnum*2+1), cpustate->R[regnum]);
+
+ for (int addrnum = 0; addrnum < 4; addrnum++)
+ state->state_add(I4004_ADDR1 + addrnum, tempstr.format("ADDR%d", addrnum + 1), cpustate->ADDR[addrnum].w.l).mask(0xfff);
+
+ state->state_add(I4004_RAM, "RAM", cpustate->RAM.w.l).mask(0x0fff);
+ }
+
+ cpustate->device = device;
+
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+ cpustate->data = device->space(AS_DATA);
+ cpustate->io = device->space(AS_IO);
+
+ device->save_item(NAME(cpustate->PC));
+ device->save_item(NAME(cpustate->A));
+ device->save_item(NAME(cpustate->C));
+ device->save_item(NAME(cpustate->TEST));
+ device->save_item(NAME(cpustate->pc_pos));
+ device->save_item(NAME(cpustate->ADDR[0]));
+ device->save_item(NAME(cpustate->ADDR[1]));
+ device->save_item(NAME(cpustate->ADDR[2]));
+ device->save_item(NAME(cpustate->ADDR[3]));
+ device->save_item(NAME(cpustate->R[0]));
+ device->save_item(NAME(cpustate->R[1]));
+ device->save_item(NAME(cpustate->R[2]));
+ device->save_item(NAME(cpustate->R[3]));
+ device->save_item(NAME(cpustate->R[4]));
+ device->save_item(NAME(cpustate->R[5]));
+ device->save_item(NAME(cpustate->R[6]));
+ device->save_item(NAME(cpustate->R[7]));
+ device->save_item(NAME(cpustate->RAM));
+}
+
+
+
+/***************************************************************************
+ COMMON RESET
+***************************************************************************/
+
+static CPU_RESET( i4004 )
+{
+ i4004_state *cpustate = get_safe_token(device);
+
+ cpustate->addr_mask = 3;
+ cpustate->C = 0;
+ cpustate->pc_pos = 0;
+ cpustate->A = 0;
+ memset(cpustate->R,0,8);
+ memset(cpustate->ADDR,0,sizeof(cpustate->ADDR));
+ cpustate->RAM.d = 0;
+ cpustate->PC = GET_PC;
+
+}
+
+
+
+/***************************************************************************
+ COMMON STATE IMPORT/EXPORT
+***************************************************************************/
+
+static CPU_IMPORT_STATE( i4004 )
+{
+ i4004_state *cpustate = get_safe_token(device);
+
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ cpustate->C = (cpustate->flags >> 1) & 1;
+ cpustate->TEST = (cpustate->flags >> 0) & 1;
+ break;
+ }
+}
+
+static CPU_EXPORT_STATE( i4004 )
+{
+ i4004_state *cpustate = get_safe_token(device);
+
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ cpustate->flags = ((cpustate->A == 0) ? 0x04 : 0x00) |
+ (cpustate->C ? 0x02 : 0x00) |
+ (cpustate->TEST ? 0x01 : 0x00);
+ break;
+ }
+}
+
+static CPU_EXPORT_STRING( i4004 )
+{
+ i4004_state *cpustate = get_safe_token(device);
+
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ string.printf(".%c%c%c",
+ (cpustate->A==0) ? 'Z':'.',
+ cpustate->C ? 'C':'.',
+ cpustate->TEST ? 'T':'.');
+ break;
+ }
+}
+
+/***************************************************************************
+ COMMON SET INFO
+***************************************************************************/
+static CPU_SET_INFO( i4004 )
+{
+}
+
+/***************************************************************************
+ 4004 GET INFO
+***************************************************************************/
+
+CPU_GET_INFO( i4004 )
+{
+ i4004_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(i4004_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 0; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 2; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 8; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 16; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 12; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 12; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 8; break; // Only lower 4 bits used
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 6; break; // 4 I/O for each ROM chip and 4 OUT for each RAM
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break; // There could be 4 chips in 16 banks for RAM
+
+ /* --- the following bits of info are returned as pointers to functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(i4004); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(i4004); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(i4004); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(i4004); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(i4004); break;
+ case CPUINFO_FCT_IMPORT_STATE: info->import_state = CPU_IMPORT_STATE_NAME(i4004); break;
+ case CPUINFO_FCT_EXPORT_STATE: info->export_state = CPU_EXPORT_STATE_NAME(i4004); break;
+ case CPUINFO_FCT_EXPORT_STRING: info->export_string = CPU_EXPORT_STRING_NAME(i4004); break;
+
+ /* --- the following bits of info are returned as pointers --- */
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "4004"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Intel 4004"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Miodrag Milanovic"); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(I4004, i4004);
diff --git a/trunk/src/emu/cpu/i4004/i4004.h b/trunk/src/emu/cpu/i4004/i4004.h
new file mode 100644
index 00000000000..4adaf7f772c
--- /dev/null
+++ b/trunk/src/emu/cpu/i4004/i4004.h
@@ -0,0 +1,34 @@
+#ifndef __I4004_H__
+#define __I4004_H__
+
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+enum
+{
+ I4004_PC,
+ I4004_A,
+ I4004_R01, I4004_R23, I4004_R45, I4004_R67, I4004_R89, I4004_RAB, I4004_RCD, I4004_REF,
+ I4004_ADDR1,I4004_ADDR2,I4004_ADDR3,I4004_ADDR4,I4004_RAM,
+ I4004_GENPC = STATE_GENPC,
+ I4004_GENSP = STATE_GENSP,
+ I4004_GENPCBASE = STATE_GENPCBASE
+};
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+DECLARE_LEGACY_CPU_DEVICE(I4004, i4004);
+
+CPU_DISASSEMBLE( i4004 );
+
+void i4004_set_test(device_t *device, UINT8 val);
+#endif
diff --git a/trunk/src/emu/cpu/i8008/8008dasm.c b/trunk/src/emu/cpu/i8008/8008dasm.c
new file mode 100644
index 00000000000..221ac3c3230
--- /dev/null
+++ b/trunk/src/emu/cpu/i8008/8008dasm.c
@@ -0,0 +1,115 @@
+/*****************************************************************************
+ *
+ * 8008dasm.c
+ *
+ * Intel 8008 CPU Disassembly
+ *
+ * Initial version by Miodrag Milanovic
+ *
+ *****************************************************************************/
+
+#include "emu.h"
+
+#define OP(A) oprom[(A) - PC]
+#define ARG(A) opram[(A) - PC]
+
+static const char reg[] = { 'a', 'b', 'c', 'd', 'e', 'h', 'l', 'm' };
+static const char flag_names[] = { 'c', 'z', 's', 'p' };
+
+CPU_DISASSEMBLE( i8008 )
+{
+ UINT32 flags = 0;
+ unsigned PC = pc;
+ UINT8 op = OP(pc++);
+ switch (op >> 6)
+ {
+ case 0x03: // starting with 11
+ if (op==0xff) {
+ sprintf (buffer,"hlt");
+ } else {
+ sprintf (buffer,"l%c%c",reg[(op >> 3) & 7],reg[op & 7]);
+ }
+ break;
+ case 0x00: // starting with 00
+ switch(op & 7) {
+ case 0 : if(((op >> 3) & 7)==0) {
+ sprintf (buffer,"hlt");
+ } else {
+ if(((op >> 3) & 7)==7) {
+ sprintf (buffer,"illegal");
+ } else {
+ sprintf (buffer,"in%c",reg[(op >> 3) & 7]);
+ }
+ }
+ break;
+ case 1 : if(((op >> 3) & 7)==0) {
+ sprintf (buffer,"hlt");
+ } else {
+ if(((op >> 3) & 7)==7) {
+ sprintf (buffer,"illegal");
+ } else {
+ sprintf (buffer,"dc%c",reg[(op >> 3) & 7]);
+ }
+ }
+ break;
+ case 2 : {
+ switch((op >> 3) & 7) {
+ case 0 : sprintf (buffer,"rlc"); break;
+ case 1 : sprintf (buffer,"rrc"); break;
+ case 2 : sprintf (buffer,"ral"); break;
+ case 3 : sprintf (buffer,"rar"); break;
+ default : sprintf (buffer,"illegal"); break;
+ }
+ }
+ break;
+ case 3 : sprintf (buffer,"r%c%c",(BIT(op,5) ? 't' : 'f'),flag_names[(op>>3)&3]); break;
+ case 4 : {
+ switch((op >> 3) & 7) {
+ case 0 : sprintf (buffer,"adi %02x",ARG(pc)); pc++; break;
+ case 1 : sprintf (buffer,"aci %02x",ARG(pc)); pc++; break;
+ case 2 : sprintf (buffer,"sui %02x",ARG(pc)); pc++; break;
+ case 3 : sprintf (buffer,"sbi %02x",ARG(pc)); pc++; break;
+ case 4 : sprintf (buffer,"ndi %02x",ARG(pc)); pc++; break;
+ case 5 : sprintf (buffer,"xri %02x",ARG(pc)); pc++; break;
+ case 6 : sprintf (buffer,"ori %02x",ARG(pc)); pc++; break;
+ case 7 : sprintf (buffer,"cpi %02x",ARG(pc)); pc++; break;
+ }
+ }
+ break;
+ case 5 : sprintf (buffer,"rst %02x",(op>>3) & 7); break;
+ case 6 : sprintf (buffer,"l%ci %02x",reg[(op >> 3) & 7],ARG(pc)); pc++; break;
+ case 7 : sprintf (buffer,"ret"); break;
+ }
+ break;
+ case 0x01: // starting with 01
+ switch(op & 7) {
+ case 0 : sprintf (buffer,"j%c%c %02x%02x",(BIT(op,5)? 't' : 'f'),flag_names[(op>>3)&3], ARG(pc+1) & 0x3f,ARG(pc)); pc+=2; break;
+ case 2 : sprintf (buffer,"c%c%c %02x%02x",(BIT(op,5)? 't' : 'f'),flag_names[(op>>3)&3], ARG(pc+1) & 0x3f,ARG(pc)); pc+=2; break;
+ case 4 : sprintf (buffer,"jmp %02x%02x",ARG(pc+1) & 0x3f,ARG(pc)); pc+=2; break;
+ case 6 : sprintf (buffer,"cal %02x%02x",ARG(pc+1) & 0x3f,ARG(pc)); pc+=2; break;
+ case 1 :
+ case 3 :
+ case 5 :
+ case 7 : if (((op>>4)&3)==0) {
+ sprintf (buffer,"inp %02x",(op >> 1) & 0x07);
+ } else {
+ sprintf (buffer,"out %02x",(op >> 1) & 0x1f);
+ }
+ break;
+ }
+ break;
+ case 0x02: // starting with 10
+ switch((op >> 3) & 7) {
+ case 0 : sprintf (buffer,"ad%c",reg[op & 7]); break;
+ case 1 : sprintf (buffer,"ac%c",reg[op & 7]); break;
+ case 2 : sprintf (buffer,"su%c",reg[op & 7]); break;
+ case 3 : sprintf (buffer,"sb%c",reg[op & 7]); break;
+ case 4 : sprintf (buffer,"nd%c",reg[op & 7]); break;
+ case 5 : sprintf (buffer,"xr%c",reg[op & 7]); break;
+ case 6 : sprintf (buffer,"or%c",reg[op & 7]); break;
+ case 7 : sprintf (buffer,"cp%c",reg[op & 7]); break;
+ }
+ break;
+ }
+ return (pc - PC) | flags | DASMFLAG_SUPPORTED;
+}
diff --git a/trunk/src/emu/cpu/i8008/i8008.c b/trunk/src/emu/cpu/i8008/i8008.c
new file mode 100644
index 00000000000..bcc6b1672b6
--- /dev/null
+++ b/trunk/src/emu/cpu/i8008/i8008.c
@@ -0,0 +1,725 @@
+/*****************************************************************************
+ *
+ * i8008.c
+ *
+ * Intel 8008 CPU
+ *
+ * Initial version by Miodrag Milanovic
+ *
+ *****************************************************************************/
+#include "emu.h"
+#include "debugger.h"
+#include "i8008.h"
+
+#define VERBOSE 0
+
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+static UINT8 PARITY[256];
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _i8008_state i8008_state;
+struct _i8008_state
+{
+ UINT8 A,B,C,D,E,H,L;
+ PAIR PC; // It is in fact one of ADDR regs
+ PAIR ADDR[8]; // Address registers
+ UINT8 CF; // Carry flag
+ UINT8 ZF; // Zero flag
+ UINT8 SF; // Sign flag
+ UINT8 PF; // Parity flag
+ UINT8 HALT;
+ UINT8 flags; // temporary I/O only
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ address_space *io;
+ int icount;
+ int pc_pos; // PC possition in ADDR
+
+ device_irq_callback irq_callback;
+ UINT8 irq_state;
+};
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+#define REG_1 ((opcode >> 3) & 7)
+#define REG_2 (opcode & 7)
+#define GET_PC (cpustate->ADDR[cpustate->pc_pos])
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+INLINE i8008_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == I8008);
+ return (i8008_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+INLINE void PUSH_STACK(i8008_state *cpustate)
+{
+ cpustate->pc_pos = (cpustate->pc_pos + 1) & 7;
+}
+
+INLINE void POP_STACK(i8008_state *cpustate)
+{
+ cpustate->ADDR[cpustate->pc_pos].d = 0;
+ cpustate->pc_pos = (cpustate->pc_pos - 1) & 7;
+}
+
+INLINE UINT8 ROP(i8008_state *cpustate)
+{
+ UINT8 retVal = cpustate->direct->read_decrypted_byte(GET_PC.w.l);
+ GET_PC.w.l = (GET_PC.w.l + 1) & 0x3fff;
+ cpustate->PC = GET_PC;
+ return retVal;
+}
+
+INLINE UINT8 GET_REG(i8008_state *cpustate,UINT8 reg)
+{
+ UINT8 retVal;
+ switch(reg) {
+ case 0 : retVal = cpustate->A; break;
+ case 1 : retVal = cpustate->B; break;
+ case 2 : retVal = cpustate->C; break;
+ case 3 : retVal = cpustate->D; break;
+ case 4 : retVal = cpustate->E; break;
+ case 5 : retVal = cpustate->H; break;
+ case 6 : retVal = cpustate->L; break;
+ default: retVal = cpustate->program->read_byte((cpustate->H << 8) + cpustate->L); break;
+ }
+ return retVal;
+}
+
+INLINE void SET_REG(i8008_state *cpustate,UINT8 reg, UINT8 val)
+{
+ switch(reg) {
+ case 0 : cpustate->A = val; break;
+ case 1 : cpustate->B = val; break;
+ case 2 : cpustate->C = val; break;
+ case 3 : cpustate->D = val; break;
+ case 4 : cpustate->E = val; break;
+ case 5 : cpustate->H = val; break;
+ case 6 : cpustate->L = val; break;
+ default: cpustate->program->write_byte((cpustate->H << 8) + cpustate->L, val); break;
+ }
+}
+
+INLINE UINT8 ARG(i8008_state *cpustate)
+{
+ UINT8 retVal = cpustate->direct->read_raw_byte(GET_PC.w.l);
+ GET_PC.w.l = (GET_PC.w.l + 1) & 0x3fff;
+ cpustate->PC = GET_PC;
+ return retVal;
+}
+
+INLINE void UPDATE_FLAGS(i8008_state *cpustate,UINT8 val)
+{
+ cpustate->ZF = (val == 0) ? 1 : 0;
+ cpustate->SF = (val & 0x80) ? 1 : 0;
+ cpustate->PF = PARITY[val];
+}
+
+INLINE UINT8 DO_CONDITION(i8008_state *cpustate, UINT8 val)
+{
+ UINT8 v = (val >> 5) & 1;
+ UINT8 cond = 0;
+ switch((val>> 3) & 0x03) {
+ case 0 :
+ if (cpustate->CF==v) cond = 1;
+ break;
+ case 1 :
+ if (cpustate->ZF==v) cond = 1;
+ break;
+ case 2 :
+ if (cpustate->SF==v) cond = 1;
+ break;
+ case 3 :
+ if (cpustate->PF==v) cond = 1;
+ break;
+ }
+ return cond;
+}
+
+INLINE UINT16 GET_ADDR(i8008_state *cpustate)
+{
+ UINT8 lo = ARG(cpustate);
+ UINT8 hi = ARG(cpustate);
+ return ((hi & 0x3f) << 8) + lo;
+}
+
+INLINE void illegal(i8008_state *cpustate,UINT8 opcode)
+{
+#if VERBOSE
+ UINT16 pc = cpustate->PC.w.l;
+ LOG(("I8008 illegal instruction %04X $%02X\n", pc, opcode));
+#endif
+}
+
+static void execute_one(i8008_state *cpustate, int opcode)
+{
+ UINT16 tmp;
+
+ switch (opcode >> 6)
+ {
+ case 0x03: // starting with 11
+ if (opcode==0xff) {
+ // HLT
+ cpustate->icount -= 4;
+ GET_PC.w.l = GET_PC.w.l - 1;
+ cpustate->PC = GET_PC;
+ cpustate->HALT = 1;
+ } else {
+ // Lrr
+ cpustate->icount -= 5;
+ if (REG_1==7) cpustate->icount -= 2;
+ if (REG_2==7) cpustate->icount -= 3;
+ SET_REG(cpustate,REG_1, GET_REG(cpustate,REG_2));
+ }
+ break;
+ case 0x00: // starting with 00
+ switch(opcode & 7) {
+ case 0 : if(((opcode >> 3) & 7)==0) {
+ // HLT
+ cpustate->icount -= 4;
+ GET_PC.w.l = GET_PC.w.l - 1;
+ cpustate->PC = GET_PC;
+ cpustate->HALT = 1;
+ } else {
+ if(((opcode >> 3) & 7)==7) {
+ // ILLEGAL
+ cpustate->icount -= 5;
+ illegal(cpustate,opcode);
+ } else {
+ // INr
+ cpustate->icount -= 5;
+ tmp = GET_REG(cpustate,REG_1) + 1;
+ SET_REG(cpustate,REG_1, tmp & 0xff);
+ UPDATE_FLAGS(cpustate,tmp & 0xff);
+ }
+ }
+ break;
+ case 1 : if(((opcode >> 3) & 7)==0) {
+ // HLT
+ cpustate->icount -= 4;
+ GET_PC.w.l = GET_PC.w.l - 1;
+ cpustate->PC = GET_PC;
+ cpustate->HALT = 1;
+ } else {
+ if(((opcode >> 3) & 7)==7) {
+ // ILLEGAL
+ cpustate->icount -= 5;
+ illegal(cpustate,opcode);
+ } else {
+ // DCr
+ cpustate->icount -= 5;
+ tmp = GET_REG(cpustate,REG_1) - 1;
+ SET_REG(cpustate,REG_1, tmp & 0xff);
+ UPDATE_FLAGS(cpustate,tmp & 0xff);
+ }
+ }
+ break;
+ case 2 : {
+ // All instuction from this group have same timing
+ cpustate->icount -= 5;
+ switch((opcode >> 3) & 7) {
+ case 0 :
+ // RLC
+ tmp = cpustate->A;
+ cpustate->A = (cpustate->A << 1) | BIT(tmp,7);
+ cpustate->CF = BIT(tmp,7);
+ break;
+ case 1 :
+ // RRC
+ tmp = cpustate->A;
+ cpustate->A = (cpustate->A >> 1) | (BIT(tmp,0) ? 0x80 : 0x00);
+ cpustate->CF = BIT(tmp,0);
+ break;
+ case 2 :
+ // RAL
+ tmp = cpustate->A;
+ cpustate->A = (cpustate->A << 1) | cpustate->CF;
+ cpustate->CF = BIT(tmp,7);
+ break;
+ case 3 :
+ // RAR
+ tmp = cpustate->A;
+ cpustate->A = (cpustate->A >> 1) | (cpustate->CF ? 0x80 : 0x00);
+ cpustate->CF = BIT(tmp,0);
+ break;
+ default :
+ // ILLEGAL
+ illegal(cpustate,opcode);
+ break;
+ }
+ }
+ break;
+ case 3 :
+ // Rcc
+ {
+ cpustate->icount -= 3;
+ if (DO_CONDITION(cpustate,opcode)==1) {
+ cpustate->icount -= 2;
+ POP_STACK(cpustate);
+ cpustate->PC = GET_PC;
+ }
+ }
+ break;
+ case 4 : {
+ cpustate->icount -= 8;
+ switch((opcode >> 3) & 7) {
+ case 0 :
+ // ADI
+ tmp = GET_REG(cpustate,0) + ARG(cpustate);
+ SET_REG(cpustate,0,tmp & 0xff);
+ UPDATE_FLAGS(cpustate,tmp & 0xff);
+ cpustate->CF = (tmp >> 8) & 1;
+ break;
+ case 1 :
+ // ACI
+ tmp = GET_REG(cpustate,0) + ARG(cpustate) + cpustate->CF;
+ SET_REG(cpustate,0,tmp & 0xff);
+ UPDATE_FLAGS(cpustate,tmp & 0xff);
+ cpustate->CF = (tmp >> 8) & 1;
+ break;
+ case 2 :
+ // SUI
+ tmp = GET_REG(cpustate,0) - ARG(cpustate);
+ SET_REG(cpustate,0,tmp & 0xff);
+ UPDATE_FLAGS(cpustate,tmp & 0xff);
+ cpustate->CF = (tmp >> 8) & 1;
+ break;
+ case 3 :
+ // SBI
+ tmp = GET_REG(cpustate,0) - ARG(cpustate) - cpustate->CF;
+ SET_REG(cpustate,0,tmp & 0xff);
+ UPDATE_FLAGS(cpustate,tmp & 0xff);
+ cpustate->CF = (tmp >> 8) & 1;
+ break;
+ case 4 :
+ // NDI
+ tmp = GET_REG(cpustate,0) & ARG(cpustate);
+ SET_REG(cpustate,0,tmp & 0xff);
+ UPDATE_FLAGS(cpustate,tmp & 0xff);
+ cpustate->CF = 0;
+ break;
+ case 5 :
+ // XRI
+ tmp = GET_REG(cpustate,0) ^ ARG(cpustate);
+ SET_REG(cpustate,0,tmp & 0xff);
+ UPDATE_FLAGS(cpustate,tmp & 0xff);
+ cpustate->CF = 0;
+ break;
+ case 6 :
+ // ORI
+ tmp = GET_REG(cpustate,0) | ARG(cpustate);
+ SET_REG(cpustate,0,tmp & 0xff);
+ UPDATE_FLAGS(cpustate,tmp & 0xff);
+ cpustate->CF = 0;
+ break;
+ case 7 :
+ // CPI
+ tmp = GET_REG(cpustate,0) - ARG(cpustate);
+ UPDATE_FLAGS(cpustate,tmp & 0xff);
+ cpustate->CF = (tmp >> 8) & 1;
+ break;
+ }
+ }
+ break;
+ case 5 : // RST
+ cpustate->icount -= 5;
+ PUSH_STACK(cpustate);
+ GET_PC.w.l = opcode & 0x38;
+ cpustate->PC = GET_PC;
+ break;
+ case 6 : // LrI
+ cpustate->icount -= 8;
+ if (REG_1==7) cpustate->icount -= 1; // LMI
+ SET_REG(cpustate,REG_1, ARG(cpustate));
+ break;
+ case 7 : // RET
+ cpustate->icount -= 5;
+ POP_STACK(cpustate);
+ cpustate->PC = GET_PC;
+ break;
+ }
+ break;
+
+ case 0x01: // starting with 01
+ switch(opcode & 7) {
+ case 0 :
+ // Jcc
+ cpustate->icount -= 9;
+ tmp = GET_ADDR(cpustate);
+ if (DO_CONDITION(cpustate,opcode)==1) {
+ cpustate->icount -= 2;
+ GET_PC.w.l = tmp;
+ cpustate->PC = GET_PC;
+ }
+ break;
+ case 2 :
+ // Ccc
+ cpustate->icount -= 9;
+ tmp = GET_ADDR(cpustate);
+ if (DO_CONDITION(cpustate,opcode)==1) {
+ cpustate->icount -= 2;
+ PUSH_STACK(cpustate);
+ GET_PC.w.l = tmp;
+ cpustate->PC = GET_PC;
+ }
+ break;
+ case 4 :
+ // JMP
+ cpustate->icount -= 11;
+ GET_PC.w.l = GET_ADDR(cpustate);
+ cpustate->PC = GET_PC;
+ break;
+ case 6 :
+ // CAL
+ cpustate->icount -= 11;
+ tmp = GET_ADDR(cpustate);
+ PUSH_STACK(cpustate);
+ GET_PC.w.l = tmp;
+ cpustate->PC = GET_PC;
+ break;
+ default :
+ if (((opcode>>4)&3)==0) {
+ // INP
+ cpustate->icount -= 8;
+ cpustate->A = cpustate->io->read_byte((opcode >> 1) & 0x1f);
+ } else {
+ // OUT
+ cpustate->icount -= 6;
+ cpustate->io->write_byte((opcode >> 1) & 0x1f, cpustate->A);
+ }
+ break;
+ }
+ break;
+ case 0x02: // starting with 10
+ cpustate->icount -= 5;
+ if ((opcode & 7)==7) cpustate->icount -= 3; // operations with memory
+ switch((opcode >> 3) & 7) {
+ case 0 :
+ // ADx
+ tmp = GET_REG(cpustate,0) + GET_REG(cpustate,opcode & 7);
+ SET_REG(cpustate,0,tmp & 0xff);
+ UPDATE_FLAGS(cpustate,tmp & 0xff);
+ cpustate->CF = (tmp >> 8) & 1;
+ break;
+ case 1 :
+ // ACx
+ tmp = GET_REG(cpustate,0) + GET_REG(cpustate,opcode & 7) + cpustate->CF;
+ SET_REG(cpustate,0,tmp & 0xff);
+ UPDATE_FLAGS(cpustate,tmp & 0xff);
+ cpustate->CF = (tmp >> 8) & 1;
+ break;
+ case 2 :
+ // SUx
+ tmp = GET_REG(cpustate,0) - GET_REG(cpustate,opcode & 7);
+ SET_REG(cpustate,0,tmp & 0xff);
+ UPDATE_FLAGS(cpustate,tmp & 0xff);
+ cpustate->CF = (tmp >> 8) & 1;
+ break;
+ case 3 :
+ // SBx
+ tmp = GET_REG(cpustate,0) - GET_REG(cpustate,opcode & 7) - cpustate->CF;
+ SET_REG(cpustate,0,tmp & 0xff);
+ UPDATE_FLAGS(cpustate,tmp & 0xff);
+ cpustate->CF = (tmp >> 8) & 1;
+ break;
+ case 4 :
+ // NDx
+ tmp = GET_REG(cpustate,0) & GET_REG(cpustate,opcode & 7);
+ SET_REG(cpustate,0,tmp & 0xff);
+ UPDATE_FLAGS(cpustate,tmp & 0xff);
+ cpustate->CF = 0;
+ break;
+ case 5 :
+ // XRx
+ tmp = GET_REG(cpustate,0) ^ GET_REG(cpustate,opcode & 7);
+ SET_REG(cpustate,0,tmp & 0xff);
+ UPDATE_FLAGS(cpustate,tmp & 0xff);
+ cpustate->CF = 0;
+ break;
+ case 6 :
+ // ORx
+ tmp = GET_REG(cpustate,0) | GET_REG(cpustate,opcode & 7);
+ SET_REG(cpustate,0,tmp & 0xff);
+ UPDATE_FLAGS(cpustate,tmp & 0xff);
+ cpustate->CF = 0;
+ break;
+ case 7 :
+ // CPx
+ tmp = GET_REG(cpustate,0) - GET_REG(cpustate,opcode & 7);
+ UPDATE_FLAGS(cpustate,tmp & 0xff);
+ cpustate->CF = (tmp >> 8) & 1;
+ break;
+ }
+ break;
+ }
+}
+
+
+/***************************************************************************
+ COMMON EXECUTION
+***************************************************************************/
+static void take_interrupt(i8008_state *cpustate)
+{
+ if (cpustate->HALT) {
+ GET_PC.w.l = (GET_PC.w.l + 1) & 0x3fff;
+ cpustate->PC = GET_PC;
+ cpustate->HALT = 0;
+ }
+ // For now only support one byte operation to be executed
+ execute_one(cpustate,(*cpustate->irq_callback)(cpustate->device, 0));
+}
+
+static CPU_EXECUTE( i8008 )
+{
+ i8008_state *cpustate = get_safe_token(device);
+
+ do
+ {
+ if (cpustate->irq_state != CLEAR_LINE) {
+ take_interrupt(cpustate);
+ }
+ debugger_instruction_hook(device, cpustate->PC.d);
+ execute_one(cpustate, ROP(cpustate));
+
+ } while (cpustate->icount > 0);
+}
+
+/***************************************************************************
+ CORE INITIALIZATION
+***************************************************************************/
+static void init_tables (void)
+{
+ int i;
+ UINT8 p;
+ for (i = 0; i < 256; i++)
+ {
+ p = 0;
+ if (BIT(i,0)) p++;
+ if (BIT(i,1)) p++;
+ if (BIT(i,2)) p++;
+ if (BIT(i,3)) p++;
+ if (BIT(i,4)) p++;
+ if (BIT(i,5)) p++;
+ if (BIT(i,6)) p++;
+ if (BIT(i,7)) p++;
+ PARITY[i] = ((p&1) ? 0 : 1);
+ }
+}
+
+static CPU_INIT( i8008 )
+{
+ i8008_state *cpustate = get_safe_token(device);
+
+ /* set up the state table */
+ {
+ device_state_interface *state;
+ device->interface(state);
+ state->state_add(I8008_PC, "PC", cpustate->PC.w.l).mask(0x3fff);
+ state->state_add(STATE_GENPC, "GENPC", cpustate->PC.w.l).mask(0x3fff).noshow();
+ state->state_add(STATE_GENFLAGS, "GENFLAGS", cpustate->flags).mask(0x0f).callimport().callexport().noshow().formatstr("%4s");
+ state->state_add(I8008_A, "A", cpustate->A);
+ state->state_add(I8008_B, "B", cpustate->B);
+ state->state_add(I8008_C, "C", cpustate->C);
+ state->state_add(I8008_D, "D", cpustate->D);
+ state->state_add(I8008_E, "E", cpustate->E);
+ state->state_add(I8008_H, "H", cpustate->H);
+ state->state_add(I8008_L, "L", cpustate->L);
+
+ astring tempstr;
+ for (int addrnum = 0; addrnum < 8; addrnum++)
+ state->state_add(I8008_ADDR1 + addrnum, tempstr.format("ADDR%d", addrnum + 1), cpustate->ADDR[addrnum].w.l).mask(0xfff);
+ }
+
+ cpustate->device = device;
+
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+ cpustate->io = device->space(AS_IO);
+
+ cpustate->irq_callback = irqcallback;
+
+ init_tables();
+
+ device->save_item(NAME(cpustate->PC));
+ device->save_item(NAME(cpustate->A));
+ device->save_item(NAME(cpustate->B));
+ device->save_item(NAME(cpustate->C));
+ device->save_item(NAME(cpustate->D));
+ device->save_item(NAME(cpustate->E));
+ device->save_item(NAME(cpustate->H));
+ device->save_item(NAME(cpustate->L));
+ device->save_item(NAME(cpustate->CF));
+ device->save_item(NAME(cpustate->SF));
+ device->save_item(NAME(cpustate->ZF));
+ device->save_item(NAME(cpustate->PF));
+ device->save_item(NAME(cpustate->pc_pos));
+ device->save_item(NAME(cpustate->ADDR[0]));
+ device->save_item(NAME(cpustate->ADDR[1]));
+ device->save_item(NAME(cpustate->ADDR[2]));
+ device->save_item(NAME(cpustate->ADDR[3]));
+ device->save_item(NAME(cpustate->ADDR[4]));
+ device->save_item(NAME(cpustate->ADDR[5]));
+ device->save_item(NAME(cpustate->ADDR[6]));
+ device->save_item(NAME(cpustate->ADDR[7]));
+ device->save_item(NAME(cpustate->HALT));
+ device->save_item(NAME(cpustate->irq_state));
+}
+
+
+
+/***************************************************************************
+ COMMON RESET
+***************************************************************************/
+
+static CPU_RESET( i8008 )
+{
+ i8008_state *cpustate = get_safe_token(device);
+
+ cpustate->CF = cpustate->SF = cpustate->ZF = cpustate->PF = 0;
+ cpustate->A = cpustate->B = cpustate->C = cpustate->D = cpustate->E = cpustate->H = cpustate->L = 0;
+ cpustate->PC.d = 0;
+ cpustate->pc_pos = 0;
+ cpustate->HALT = 0;
+ cpustate->irq_state = CLEAR_LINE;
+ memset(cpustate->ADDR,0,sizeof(cpustate->ADDR));
+
+}
+
+/****************************************************************************
+ * Set IRQ line state
+ ****************************************************************************/
+static void set_irq_line(i8008_state *cpustate, int irqline, int state)
+{
+ cpustate->irq_state = state;
+}
+
+/***************************************************************************
+ COMMON STATE IMPORT/EXPORT
+***************************************************************************/
+
+static CPU_IMPORT_STATE( i8008 )
+{
+ i8008_state *cpustate = get_safe_token(device);
+
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ cpustate->CF = (cpustate->flags >> 3) & 1;
+ cpustate->ZF = (cpustate->flags >> 2) & 1;
+ cpustate->SF = (cpustate->flags >> 1) & 1;
+ cpustate->PF = (cpustate->flags >> 0) & 1;
+ break;
+ }
+}
+
+static CPU_EXPORT_STATE( i8008 )
+{
+ i8008_state *cpustate = get_safe_token(device);
+
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ cpustate->flags = (cpustate->CF ? 0x08 : 0x00) |
+ (cpustate->ZF ? 0x04 : 0x00) |
+ (cpustate->SF ? 0x02 : 0x00) |
+ (cpustate->PF ? 0x01 : 0x00);
+ break;
+ }
+}
+
+static CPU_EXPORT_STRING( i8008 )
+{
+ i8008_state *cpustate = get_safe_token(device);
+
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ string.printf("%c%c%c%c",
+ cpustate->CF ? 'C':'.',
+ cpustate->ZF ? 'Z':'.',
+ cpustate->SF ? 'S':'.',
+ cpustate->PF ? 'P':'.');
+ break;
+ }
+}
+
+/***************************************************************************
+ COMMON SET INFO
+***************************************************************************/
+static CPU_SET_INFO( i8008 )
+{
+ i8008_state *cpustate = get_safe_token(device);
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + 0: set_irq_line(cpustate, 0, info->i); break;
+ }
+}
+
+/***************************************************************************
+ 8008 GET INFO
+***************************************************************************/
+
+CPU_GET_INFO( i8008 )
+{
+ i8008_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(i8008_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 0; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 3; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 8; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 16; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 14; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ /* --- the following bits of info are returned as pointers to functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(i8008); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(i8008); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(i8008); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(i8008); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(i8008); break;
+ case CPUINFO_FCT_IMPORT_STATE: info->import_state = CPU_IMPORT_STATE_NAME(i8008); break;
+ case CPUINFO_FCT_EXPORT_STATE: info->export_state = CPU_EXPORT_STATE_NAME(i8008); break;
+ case CPUINFO_FCT_EXPORT_STRING: info->export_string = CPU_EXPORT_STRING_NAME(i8008); break;
+
+ /* --- the following bits of info are returned as pointers --- */
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "8008"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Intel 8008"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Miodrag Milanovic"); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(I8008, i8008);
diff --git a/trunk/src/emu/cpu/i8008/i8008.h b/trunk/src/emu/cpu/i8008/i8008.h
new file mode 100644
index 00000000000..5d15fdb6139
--- /dev/null
+++ b/trunk/src/emu/cpu/i8008/i8008.h
@@ -0,0 +1,31 @@
+#ifndef __I8008_H__
+#define __I8008_H__
+
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+enum
+{
+ I8008_PC,
+ I8008_A,I8008_B,I8008_C,I8008_D,I8008_E,I8008_H,I8008_L,
+ I8008_ADDR1,I8008_ADDR2,I8008_ADDR3,I8008_ADDR4,I8008_ADDR5,I8008_ADDR6,I8008_ADDR7,I8008_ADDR8,
+ I8008_GENPC = STATE_GENPC,
+ I8008_GENSP = STATE_GENSP,
+ I8008_GENPCBASE = STATE_GENPCBASE
+};
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+DECLARE_LEGACY_CPU_DEVICE(I8008, i8008);
+
+CPU_DISASSEMBLE( i8008 );
+#endif
diff --git a/trunk/src/emu/cpu/i8085/8085dasm.c b/trunk/src/emu/cpu/i8085/8085dasm.c
new file mode 100644
index 00000000000..5ce3d81dc58
--- /dev/null
+++ b/trunk/src/emu/cpu/i8085/8085dasm.c
@@ -0,0 +1,581 @@
+/*****************************************************************************
+ *
+ * 8085dasm.c
+ * Portable I8085A disassembler
+ *
+ * Copyright Juergen Buchmueller, all rights reserved.
+ * You can contact me at juergen@mame.net or pullmoll@stop1984.com
+ *
+ * - This source code is released as freeware for non-commercial purposes
+ * as part of the M.A.M.E. (Multiple Arcade Machine Emulator) project.
+ * The licensing terms of MAME apply to this piece of code for the MAME
+ * project and derviative works, as defined by the MAME license. You
+ * may opt to make modifications, improvements or derivative works under
+ * that same conditions, and the MAME project may opt to keep
+ * modifications, improvements or derivatives under their terms exclusively.
+ *
+ * - Alternatively you can choose to apply the terms of the "GPL" (see
+ * below) to this - and only this - piece of code or your derivative works.
+ * Note that in no case your choice can have any impact on any other
+ * source code of the MAME project, or binary, or executable, be it closely
+ * or losely related to this piece of code.
+ *
+ * - At your choice you are also free to remove either licensing terms from
+ * this file and continue to use it under only one of the two licenses. Do this
+ * if you think that licenses are not compatible (enough) for you, or if you
+ * consider either license 'too restrictive' or 'too free'.
+ *
+ * - GPL (GNU General Public License)
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *****************************************************************************/
+
+#include "emu.h"
+
+/* 8080/8085A mnemonics were more irritation than information
+ What would you guess "CP $3456" to mean? It's not compare,
+ but call if plus ... therefore: */
+//#define Z80_MNEMONICS
+
+#define OP(A) oprom[(A) - PC]
+#define ARG(A) opram[(A) - PC]
+#define ARGW(A) (opram[(A) - PC] | (opram[(A) + 1 - PC] << 8))
+
+CPU_DISASSEMBLE( i8085 )
+{
+ UINT32 flags = 0;
+ UINT8 op;
+ unsigned PC = pc;
+ switch (op = OP(pc++))
+ {
+#ifdef Z80_MNEMONICS
+ case 0x00: sprintf (buffer,"nop"); break;
+ case 0x01: sprintf (buffer,"ld bc,$%04x", ARGW(pc)); pc+=2; break;
+ case 0x02: sprintf (buffer,"ld (bc),a"); break;
+ case 0x03: sprintf (buffer,"inc bc"); break;
+ case 0x04: sprintf (buffer,"inc b"); break;
+ case 0x05: sprintf (buffer,"dec b"); break;
+ case 0x06: sprintf (buffer,"ld b,$%02x", ARG(pc)); pc++; break;
+ case 0x07: sprintf (buffer,"rlca"); break;
+ case 0x08: sprintf (buffer,"sub hl,bc (*)"); break;
+ case 0x09: sprintf (buffer,"add hl,bc"); break;
+ case 0x0a: sprintf (buffer,"ld a,(bc)"); break;
+ case 0x0b: sprintf (buffer,"dec bc"); break;
+ case 0x0c: sprintf (buffer,"inc c"); break;
+ case 0x0d: sprintf (buffer,"dec c"); break;
+ case 0x0e: sprintf (buffer,"ld c,$%02x", ARG(pc)); pc++; break;
+ case 0x0f: sprintf (buffer,"rrca"); break;
+ case 0x10: sprintf (buffer,"sra hl (*)"); break;
+ case 0x11: sprintf (buffer,"ld de,$%04x", ARGW(pc)); pc+=2; break;
+ case 0x12: sprintf (buffer,"ld (de),a"); break;
+ case 0x13: sprintf (buffer,"inc de"); break;
+ case 0x14: sprintf (buffer,"inc d"); break;
+ case 0x15: sprintf (buffer,"dec d"); break;
+ case 0x16: sprintf (buffer,"ld d,$%02x", ARG(pc)); pc++; break;
+ case 0x17: sprintf (buffer,"rla"); break;
+ case 0x18: sprintf (buffer,"rl de (*)"); break;
+ case 0x19: sprintf (buffer,"add hl,de"); break;
+ case 0x1a: sprintf (buffer,"ld a,(de)"); break;
+ case 0x1b: sprintf (buffer,"dec de"); break;
+ case 0x1c: sprintf (buffer,"inc e"); break;
+ case 0x1d: sprintf (buffer,"dec e"); break;
+ case 0x1e: sprintf (buffer,"ld e,$%02x", ARG(pc)); pc++; break;
+ case 0x1f: sprintf (buffer,"rra"); break;
+ case 0x20: sprintf (buffer,"rim"); break;
+ case 0x21: sprintf (buffer,"ld hl,$%04x", ARGW(pc)); pc+=2; break;
+ case 0x22: sprintf (buffer,"ld ($%04x),hl", ARGW(pc)); pc+=2;break;
+ case 0x23: sprintf (buffer,"inc hl"); break;
+ case 0x24: sprintf (buffer,"inc h"); break;
+ case 0x25: sprintf (buffer,"dec h"); break;
+ case 0x26: sprintf (buffer,"ld h,$%02x", ARG(pc)); pc++; break;
+ case 0x27: sprintf (buffer,"daa"); break;
+ case 0x28: sprintf (buffer,"ld de,hl+$%02x (*)",ARG(pc));pc++;break;
+ case 0x29: sprintf (buffer,"add hl,hl"); break;
+ case 0x2a: sprintf (buffer,"ld hl,($%04x)", ARGW(pc)); pc+=2;break;
+ case 0x2b: sprintf (buffer,"dec hl"); break;
+ case 0x2c: sprintf (buffer,"inc l"); break;
+ case 0x2d: sprintf (buffer,"dec l"); break;
+ case 0x2e: sprintf (buffer,"ld l,$%02x", ARG(pc)); pc++; break;
+ case 0x2f: sprintf (buffer,"cpl"); break;
+ case 0x30: sprintf (buffer,"sim"); break;
+ case 0x31: sprintf (buffer,"ld sp,$%04x", ARGW(pc)); pc+=2; break;
+ case 0x32: sprintf (buffer,"ld ($%04x),a", ARGW(pc)); pc+=2; break;
+ case 0x33: sprintf (buffer,"inc sp"); break;
+ case 0x34: sprintf (buffer,"inc (hl)"); break;
+ case 0x35: sprintf (buffer,"dec (hl)"); break;
+ case 0x36: sprintf (buffer,"ld (hl),$%02x", ARG(pc)); pc++; break;
+ case 0x37: sprintf (buffer,"scf"); break;
+ case 0x38: sprintf (buffer,"ld de,sp+$%02x (*)",ARG(pc));pc++;break;
+ case 0x39: sprintf (buffer,"add hl,sp"); break;
+ case 0x3a: sprintf (buffer,"ld a,($%04x)", ARGW(pc)); pc+=2; break;
+ case 0x3b: sprintf (buffer,"dec sp"); break;
+ case 0x3c: sprintf (buffer,"inc a"); break;
+ case 0x3d: sprintf (buffer,"dec a"); break;
+ case 0x3e: sprintf (buffer,"ld a,$%02x", ARG(pc)); pc++; break;
+ case 0x3f: sprintf (buffer,"ccf"); break;
+ case 0x40: sprintf (buffer,"ld b,b"); break;
+ case 0x41: sprintf (buffer,"ld b,c"); break;
+ case 0x42: sprintf (buffer,"ld b,d"); break;
+ case 0x43: sprintf (buffer,"ld b,e"); break;
+ case 0x44: sprintf (buffer,"ld b,h"); break;
+ case 0x45: sprintf (buffer,"ld b,l"); break;
+ case 0x46: sprintf (buffer,"ld b,(hl)"); break;
+ case 0x47: sprintf (buffer,"ld b,a"); break;
+ case 0x48: sprintf (buffer,"ld c,b"); break;
+ case 0x49: sprintf (buffer,"ld c,c"); break;
+ case 0x4a: sprintf (buffer,"ld c,d"); break;
+ case 0x4b: sprintf (buffer,"ld c,e"); break;
+ case 0x4c: sprintf (buffer,"ld c,h"); break;
+ case 0x4d: sprintf (buffer,"ld c,l"); break;
+ case 0x4e: sprintf (buffer,"ld c,(hl)"); break;
+ case 0x4f: sprintf (buffer,"ld c,a"); break;
+ case 0x50: sprintf (buffer,"ld d,b"); break;
+ case 0x51: sprintf (buffer,"ld d,c"); break;
+ case 0x52: sprintf (buffer,"ld d,d"); break;
+ case 0x53: sprintf (buffer,"ld d,e"); break;
+ case 0x54: sprintf (buffer,"ld d,h"); break;
+ case 0x55: sprintf (buffer,"ld d,l"); break;
+ case 0x56: sprintf (buffer,"ld d,(hl)"); break;
+ case 0x57: sprintf (buffer,"ld d,a"); break;
+ case 0x58: sprintf (buffer,"ld e,b"); break;
+ case 0x59: sprintf (buffer,"ld e,c"); break;
+ case 0x5a: sprintf (buffer,"ld e,d"); break;
+ case 0x5b: sprintf (buffer,"ld e,e"); break;
+ case 0x5c: sprintf (buffer,"ld e,h"); break;
+ case 0x5d: sprintf (buffer,"ld e,l"); break;
+ case 0x5e: sprintf (buffer,"ld e,(hl)"); break;
+ case 0x5f: sprintf (buffer,"ld e,a"); break;
+ case 0x60: sprintf (buffer,"ld h,b"); break;
+ case 0x61: sprintf (buffer,"ld h,c"); break;
+ case 0x62: sprintf (buffer,"ld h,d"); break;
+ case 0x63: sprintf (buffer,"ld h,e"); break;
+ case 0x64: sprintf (buffer,"ld h,h"); break;
+ case 0x65: sprintf (buffer,"ld h,l"); break;
+ case 0x66: sprintf (buffer,"ld h,(hl)"); break;
+ case 0x67: sprintf (buffer,"ld h,a"); break;
+ case 0x68: sprintf (buffer,"ld l,b"); break;
+ case 0x69: sprintf (buffer,"ld l,c"); break;
+ case 0x6a: sprintf (buffer,"ld l,d"); break;
+ case 0x6b: sprintf (buffer,"ld l,e"); break;
+ case 0x6c: sprintf (buffer,"ld l,h"); break;
+ case 0x6d: sprintf (buffer,"ld l,l"); break;
+ case 0x6e: sprintf (buffer,"ld l,(hl)"); break;
+ case 0x6f: sprintf (buffer,"ld l,a"); break;
+ case 0x70: sprintf (buffer,"ld (hl),b"); break;
+ case 0x71: sprintf (buffer,"ld (hl),c"); break;
+ case 0x72: sprintf (buffer,"ld (hl),d"); break;
+ case 0x73: sprintf (buffer,"ld (hl),e"); break;
+ case 0x74: sprintf (buffer,"ld (hl),h"); break;
+ case 0x75: sprintf (buffer,"ld (hl),l"); break;
+ case 0x76: sprintf (buffer,"halt"); break;
+ case 0x77: sprintf (buffer,"ld (hl),a"); break;
+ case 0x78: sprintf (buffer,"ld a,b"); break;
+ case 0x79: sprintf (buffer,"ld a,c"); break;
+ case 0x7a: sprintf (buffer,"ld a,d"); break;
+ case 0x7b: sprintf (buffer,"ld a,e"); break;
+ case 0x7c: sprintf (buffer,"ld a,h"); break;
+ case 0x7d: sprintf (buffer,"ld a,l"); break;
+ case 0x7e: sprintf (buffer,"ld a,(hl)"); break;
+ case 0x7f: sprintf (buffer,"ld a,a"); break;
+ case 0x80: sprintf (buffer,"add a,b"); break;
+ case 0x81: sprintf (buffer,"add a,c"); break;
+ case 0x82: sprintf (buffer,"add a,d"); break;
+ case 0x83: sprintf (buffer,"add a,e"); break;
+ case 0x84: sprintf (buffer,"add a,h"); break;
+ case 0x85: sprintf (buffer,"add a,l"); break;
+ case 0x86: sprintf (buffer,"add a,(hl)"); break;
+ case 0x87: sprintf (buffer,"add a,a"); break;
+ case 0x88: sprintf (buffer,"adc a,b"); break;
+ case 0x89: sprintf (buffer,"adc a,c"); break;
+ case 0x8a: sprintf (buffer,"adc a,d"); break;
+ case 0x8b: sprintf (buffer,"adc a,e"); break;
+ case 0x8c: sprintf (buffer,"adc a,h"); break;
+ case 0x8d: sprintf (buffer,"adc a,l"); break;
+ case 0x8e: sprintf (buffer,"adc a,(hl)"); break;
+ case 0x8f: sprintf (buffer,"adc a,a"); break;
+ case 0x90: sprintf (buffer,"sub b"); break;
+ case 0x91: sprintf (buffer,"sub c"); break;
+ case 0x92: sprintf (buffer,"sub d"); break;
+ case 0x93: sprintf (buffer,"sub e"); break;
+ case 0x94: sprintf (buffer,"sub h"); break;
+ case 0x95: sprintf (buffer,"sub l"); break;
+ case 0x96: sprintf (buffer,"sub (hl)"); break;
+ case 0x97: sprintf (buffer,"sub a"); break;
+ case 0x98: sprintf (buffer,"sbc a,b"); break;
+ case 0x99: sprintf (buffer,"sbc a,c"); break;
+ case 0x9a: sprintf (buffer,"sbc a,d"); break;
+ case 0x9b: sprintf (buffer,"sbc a,e"); break;
+ case 0x9c: sprintf (buffer,"sbc a,h"); break;
+ case 0x9d: sprintf (buffer,"sbc a,l"); break;
+ case 0x9e: sprintf (buffer,"sbc a,(hl)"); break;
+ case 0x9f: sprintf (buffer,"sbc a,a"); break;
+ case 0xa0: sprintf (buffer,"and b"); break;
+ case 0xa1: sprintf (buffer,"and c"); break;
+ case 0xa2: sprintf (buffer,"and d"); break;
+ case 0xa3: sprintf (buffer,"and e"); break;
+ case 0xa4: sprintf (buffer,"and h"); break;
+ case 0xa5: sprintf (buffer,"and l"); break;
+ case 0xa6: sprintf (buffer,"and (hl)"); break;
+ case 0xa7: sprintf (buffer,"and a"); break;
+ case 0xa8: sprintf (buffer,"xor b"); break;
+ case 0xa9: sprintf (buffer,"xor c"); break;
+ case 0xaa: sprintf (buffer,"xor d"); break;
+ case 0xab: sprintf (buffer,"xor e"); break;
+ case 0xac: sprintf (buffer,"xor h"); break;
+ case 0xad: sprintf (buffer,"xor l"); break;
+ case 0xae: sprintf (buffer,"xor (hl)"); break;
+ case 0xaf: sprintf (buffer,"xor a"); break;
+ case 0xb0: sprintf (buffer,"or b"); break;
+ case 0xb1: sprintf (buffer,"or c"); break;
+ case 0xb2: sprintf (buffer,"or d"); break;
+ case 0xb3: sprintf (buffer,"or e"); break;
+ case 0xb4: sprintf (buffer,"or h"); break;
+ case 0xb5: sprintf (buffer,"or l"); break;
+ case 0xb6: sprintf (buffer,"or (hl)"); break;
+ case 0xb7: sprintf (buffer,"or a"); break;
+ case 0xb8: sprintf (buffer,"cp b"); break;
+ case 0xb9: sprintf (buffer,"cp c"); break;
+ case 0xba: sprintf (buffer,"cp d"); break;
+ case 0xbb: sprintf (buffer,"cp e"); break;
+ case 0xbc: sprintf (buffer,"cp h"); break;
+ case 0xbd: sprintf (buffer,"cp l"); break;
+ case 0xbe: sprintf (buffer,"cp (hl)"); break;
+ case 0xbf: sprintf (buffer,"cp a"); break;
+ case 0xc0: sprintf (buffer,"ret nz"); flags = DASMFLAG_STEP_OUT; break;
+ case 0xc1: sprintf (buffer,"pop bc"); break;
+ case 0xc2: sprintf (buffer,"jp nz,$%04x", ARGW(pc)); pc+=2; break;
+ case 0xc3: sprintf (buffer,"jp $%04x", ARGW(pc)); pc+=2; break;
+ case 0xc4: sprintf (buffer,"call nz,$%04x", ARGW(pc)); pc+=2; flags = DASMFLAG_STEP_OVER; break;
+ case 0xc5: sprintf (buffer,"push bc"); break;
+ case 0xc6: sprintf (buffer,"add a,$%02x", ARG(pc)); pc++; break;
+ case 0xc7: sprintf (buffer,"rst $00"); flags = DASMFLAG_STEP_OVER; break;
+ case 0xc8: sprintf (buffer,"ret z"); flags = DASMFLAG_STEP_OUT; break;
+ case 0xc9: sprintf (buffer,"ret"); flags = DASMFLAG_STEP_OUT; break;
+ case 0xca: sprintf (buffer,"jp z,$%04x", ARGW(pc)); pc+=2; break;
+ case 0xcb: sprintf (buffer,"rst v,$40 (*)"); flags = DASMFLAG_STEP_OVER; break;
+ case 0xcc: sprintf (buffer,"call z,$%04x", ARGW(pc)); pc+=2; flags = DASMFLAG_STEP_OVER; break;
+ case 0xcd: sprintf (buffer,"call $%04x", ARGW(pc)); pc+=2; flags = DASMFLAG_STEP_OVER; break;
+ case 0xce: sprintf (buffer,"adc a,$%02x", ARG(pc)); pc++; break;
+ case 0xcf: sprintf (buffer,"rst $08"); flags = DASMFLAG_STEP_OVER; break;
+ case 0xd0: sprintf (buffer,"ret nc"); flags = DASMFLAG_STEP_OUT; break;
+ case 0xd1: sprintf (buffer,"pop de"); break;
+ case 0xd2: sprintf (buffer,"jp nc,$%04x", ARGW(pc)); pc+=2; break;
+ case 0xd3: sprintf (buffer,"out ($%02x),a", ARG(pc)); pc++; break;
+ case 0xd4: sprintf (buffer,"call nc,$%04x", ARGW(pc)); pc+=2; flags = DASMFLAG_STEP_OVER; break;
+ case 0xd5: sprintf (buffer,"push de"); break;
+ case 0xd6: sprintf (buffer,"sub $%02x", ARG(pc)); pc++; break;
+ case 0xd7: sprintf (buffer,"rst $10"); flags = DASMFLAG_STEP_OVER; break;
+ case 0xd8: sprintf (buffer,"ret c"); break;
+ case 0xd9: sprintf (buffer,"ld (de),hl (*)"); break;
+ case 0xda: sprintf (buffer,"jp c,$%04x", ARGW(pc)); pc+=2; break;
+ case 0xdb: sprintf (buffer,"in a,($%02x)", ARG(pc)); pc++; break;
+ case 0xdc: sprintf (buffer,"call c,$%04x", ARGW(pc)); pc+=2; flags = DASMFLAG_STEP_OVER; break;
+ case 0xdd: sprintf (buffer,"jp nx,$%04x (*)",ARGW(pc));pc+=2;break;
+ case 0xde: sprintf (buffer,"sub $%02x", ARG(pc)); pc++; break;
+ case 0xdf: sprintf (buffer,"rst $18"); flags = DASMFLAG_STEP_OVER; break;
+ case 0xe0: sprintf (buffer,"ret pe"); break;
+ case 0xe1: sprintf (buffer,"pop hl"); break;
+ case 0xe2: sprintf (buffer,"jp pe,$%04x", ARGW(pc)); pc+=2; break;
+ case 0xe3: sprintf (buffer,"ex (sp),hl"); break;
+ case 0xe4: sprintf (buffer,"call pe,$%04x", ARGW(pc)); pc+=2; flags = DASMFLAG_STEP_OVER; break;
+ case 0xe5: sprintf (buffer,"push hl"); break;
+ case 0xe6: sprintf (buffer,"and $%02x", ARG(pc)); pc++; break;
+ case 0xe7: sprintf (buffer,"rst $20"); flags = DASMFLAG_STEP_OVER; break;
+ case 0xe8: sprintf (buffer,"ret po"); break;
+ case 0xe9: sprintf (buffer,"jp (hl)"); break;
+ case 0xea: sprintf (buffer,"jp po,$%04x", ARGW(pc)); pc+=2; break;
+ case 0xeb: sprintf (buffer,"ex de,hl"); break;
+ case 0xec: sprintf (buffer,"call po,$%04x", ARGW(pc)); pc+=2; flags = DASMFLAG_STEP_OVER; break;
+ case 0xed: sprintf (buffer,"ld hl,(de) (*)"); break;
+ case 0xee: sprintf (buffer,"xor $%02x", ARG(pc)); pc++; break;
+ case 0xef: sprintf (buffer,"rst $28"); flags = DASMFLAG_STEP_OVER; break;
+ case 0xf0: sprintf (buffer,"ret p"); break;
+ case 0xf1: sprintf (buffer,"pop af"); break;
+ case 0xf2: sprintf (buffer,"jp p,$%04x", ARGW(pc)); pc+=2; break;
+ case 0xf3: sprintf (buffer,"di"); break;
+ case 0xf4: sprintf (buffer,"cp $%04x", ARGW(pc)); pc+=2; break;
+ case 0xf5: sprintf (buffer,"push af"); break;
+ case 0xf6: sprintf (buffer,"or $%02x", ARG(pc)); pc++; break;
+ case 0xf7: sprintf (buffer,"rst $30"); flags = DASMFLAG_STEP_OVER; break;
+ case 0xf8: sprintf (buffer,"ret m"); break;
+ case 0xf9: sprintf (buffer,"ld sp,hl"); break;
+ case 0xfa: sprintf (buffer,"jp m,$%04x", ARGW(pc)); pc+=2; break;
+ case 0xfb: sprintf (buffer,"ei"); break;
+ case 0xfc: sprintf (buffer,"call m,$%04x", ARGW(pc)); pc+=2; flags = DASMFLAG_STEP_OVER; break;
+ case 0xfd: sprintf (buffer,"jp x,$%04x (*)",ARGW(pc));pc+=2; break;
+ case 0xfe: sprintf (buffer,"cp $%02x", ARG(pc)); pc++; break;
+ case 0xff: sprintf (buffer,"rst $38"); flags = DASMFLAG_STEP_OVER; break;
+#else
+ case 0x00: sprintf (buffer,"nop"); break;
+ case 0x01: sprintf (buffer,"lxi b,$%04x", ARGW(pc)); pc+=2; break;
+ case 0x02: sprintf (buffer,"stax b"); break;
+ case 0x03: sprintf (buffer,"inx b"); break;
+ case 0x04: sprintf (buffer,"inr b"); break;
+ case 0x05: sprintf (buffer,"dcr b"); break;
+ case 0x06: sprintf (buffer,"mvi b,$%02x", ARG(pc)); pc++; break;
+ case 0x07: sprintf (buffer,"rlc"); break;
+ case 0x08: sprintf (buffer,"dsub (*)"); break;
+ case 0x09: sprintf (buffer,"dad b"); break;
+ case 0x0a: sprintf (buffer,"ldax b"); break;
+ case 0x0b: sprintf (buffer,"dcx b"); break;
+ case 0x0c: sprintf (buffer,"inr c"); break;
+ case 0x0d: sprintf (buffer,"dcr c"); break;
+ case 0x0e: sprintf (buffer,"mvi c,$%02x", ARG(pc)); pc++; break;
+ case 0x0f: sprintf (buffer,"rrc"); break;
+ case 0x10: sprintf (buffer,"asrh (*)"); break;
+ case 0x11: sprintf (buffer,"lxi d,$%04x", ARGW(pc)); pc+=2; break;
+ case 0x12: sprintf (buffer,"stax d"); break;
+ case 0x13: sprintf (buffer,"inx d"); break;
+ case 0x14: sprintf (buffer,"inr d"); break;
+ case 0x15: sprintf (buffer,"dcr d"); break;
+ case 0x16: sprintf (buffer,"mvi d,$%02x", ARG(pc)); pc++; break;
+ case 0x17: sprintf (buffer,"ral"); break;
+ case 0x18: sprintf (buffer,"rlde (*)"); break;
+ case 0x19: sprintf (buffer,"dad d"); break;
+ case 0x1a: sprintf (buffer,"ldax d"); break;
+ case 0x1b: sprintf (buffer,"dcx d"); break;
+ case 0x1c: sprintf (buffer,"inr e"); break;
+ case 0x1d: sprintf (buffer,"dcr e"); break;
+ case 0x1e: sprintf (buffer,"mvi e,$%02x", ARG(pc)); pc++; break;
+ case 0x1f: sprintf (buffer,"rar"); break;
+ case 0x20: sprintf (buffer,"rim"); break;
+ case 0x21: sprintf (buffer,"lxi h,$%04x", ARGW(pc)); pc+=2; break;
+ case 0x22: sprintf (buffer,"shld $%04x", ARGW(pc)); pc+=2; break;
+ case 0x23: sprintf (buffer,"inx h"); break;
+ case 0x24: sprintf (buffer,"inr h"); break;
+ case 0x25: sprintf (buffer,"dcr h"); break;
+ case 0x26: sprintf (buffer,"mvi h,$%02x", ARG(pc)); pc++; break;
+ case 0x27: sprintf (buffer,"daa"); break;
+ case 0x28: sprintf (buffer,"ldeh $%02x (*)", ARG(pc)); pc++; break;
+ case 0x29: sprintf (buffer,"dad h"); break;
+ case 0x2a: sprintf (buffer,"lhld $%04x", ARGW(pc)); pc+=2; break;
+ case 0x2b: sprintf (buffer,"dcx h"); break;
+ case 0x2c: sprintf (buffer,"inr l"); break;
+ case 0x2d: sprintf (buffer,"dcr l"); break;
+ case 0x2e: sprintf (buffer,"mvi l,$%02x", ARG(pc)); pc++; break;
+ case 0x2f: sprintf (buffer,"cma"); break;
+ case 0x30: sprintf (buffer,"sim"); break;
+ case 0x31: sprintf (buffer,"lxi sp,$%04x", ARGW(pc)); pc+=2; break;
+ case 0x32: sprintf (buffer,"stax $%04x", ARGW(pc)); pc+=2; break;
+ case 0x33: sprintf (buffer,"inx sp"); break;
+ case 0x34: sprintf (buffer,"inr m"); break;
+ case 0x35: sprintf (buffer,"dcr m"); break;
+ case 0x36: sprintf (buffer,"mvi m,$%02x", ARG(pc)); pc++; break;
+ case 0x37: sprintf (buffer,"stc"); break;
+ case 0x38: sprintf (buffer,"ldes $%02x", ARG(pc)); pc++; break;
+ case 0x39: sprintf (buffer,"dad sp"); break;
+ case 0x3a: sprintf (buffer,"ldax $%04x", ARGW(pc)); pc+=2; break;
+ case 0x3b: sprintf (buffer,"dcx sp"); break;
+ case 0x3c: sprintf (buffer,"inr a"); break;
+ case 0x3d: sprintf (buffer,"dcr a"); break;
+ case 0x3e: sprintf (buffer,"mvi a,$%02x", ARG(pc)); pc++; break;
+ case 0x3f: sprintf (buffer,"cmf"); break;
+ case 0x40: sprintf (buffer,"mov b,b"); break;
+ case 0x41: sprintf (buffer,"mov b,c"); break;
+ case 0x42: sprintf (buffer,"mov b,d"); break;
+ case 0x43: sprintf (buffer,"mov b,e"); break;
+ case 0x44: sprintf (buffer,"mov b,h"); break;
+ case 0x45: sprintf (buffer,"mov b,l"); break;
+ case 0x46: sprintf (buffer,"mov b,m"); break;
+ case 0x47: sprintf (buffer,"mov b,a"); break;
+ case 0x48: sprintf (buffer,"mov c,b"); break;
+ case 0x49: sprintf (buffer,"mov c,c"); break;
+ case 0x4a: sprintf (buffer,"mov c,d"); break;
+ case 0x4b: sprintf (buffer,"mov c,e"); break;
+ case 0x4c: sprintf (buffer,"mov c,h"); break;
+ case 0x4d: sprintf (buffer,"mov c,l"); break;
+ case 0x4e: sprintf (buffer,"mov c,m"); break;
+ case 0x4f: sprintf (buffer,"mov c,a"); break;
+ case 0x50: sprintf (buffer,"mov d,b"); break;
+ case 0x51: sprintf (buffer,"mov d,c"); break;
+ case 0x52: sprintf (buffer,"mov d,d"); break;
+ case 0x53: sprintf (buffer,"mov d,e"); break;
+ case 0x54: sprintf (buffer,"mov d,h"); break;
+ case 0x55: sprintf (buffer,"mov d,l"); break;
+ case 0x56: sprintf (buffer,"mov d,m"); break;
+ case 0x57: sprintf (buffer,"mov d,a"); break;
+ case 0x58: sprintf (buffer,"mov e,b"); break;
+ case 0x59: sprintf (buffer,"mov e,c"); break;
+ case 0x5a: sprintf (buffer,"mov e,d"); break;
+ case 0x5b: sprintf (buffer,"mov e,e"); break;
+ case 0x5c: sprintf (buffer,"mov e,h"); break;
+ case 0x5d: sprintf (buffer,"mov e,l"); break;
+ case 0x5e: sprintf (buffer,"mov e,m"); break;
+ case 0x5f: sprintf (buffer,"mov e,a"); break;
+ case 0x60: sprintf (buffer,"mov h,b"); break;
+ case 0x61: sprintf (buffer,"mov h,c"); break;
+ case 0x62: sprintf (buffer,"mov h,d"); break;
+ case 0x63: sprintf (buffer,"mov h,e"); break;
+ case 0x64: sprintf (buffer,"mov h,h"); break;
+ case 0x65: sprintf (buffer,"mov h,l"); break;
+ case 0x66: sprintf (buffer,"mov h,m"); break;
+ case 0x67: sprintf (buffer,"mov h,a"); break;
+ case 0x68: sprintf (buffer,"mov l,b"); break;
+ case 0x69: sprintf (buffer,"mov l,c"); break;
+ case 0x6a: sprintf (buffer,"mov l,d"); break;
+ case 0x6b: sprintf (buffer,"mov l,e"); break;
+ case 0x6c: sprintf (buffer,"mov l,h"); break;
+ case 0x6d: sprintf (buffer,"mov l,l"); break;
+ case 0x6e: sprintf (buffer,"mov l,m"); break;
+ case 0x6f: sprintf (buffer,"mov l,a"); break;
+ case 0x70: sprintf (buffer,"mov m,b"); break;
+ case 0x71: sprintf (buffer,"mov m,c"); break;
+ case 0x72: sprintf (buffer,"mov m,d"); break;
+ case 0x73: sprintf (buffer,"mov m,e"); break;
+ case 0x74: sprintf (buffer,"mov m,h"); break;
+ case 0x75: sprintf (buffer,"mov m,l"); break;
+ case 0x76: sprintf (buffer,"hlt"); break;
+ case 0x77: sprintf (buffer,"mov m,a"); break;
+ case 0x78: sprintf (buffer,"mov a,b"); break;
+ case 0x79: sprintf (buffer,"mov a,c"); break;
+ case 0x7a: sprintf (buffer,"mov a,d"); break;
+ case 0x7b: sprintf (buffer,"mov a,e"); break;
+ case 0x7c: sprintf (buffer,"mov a,h"); break;
+ case 0x7d: sprintf (buffer,"mov a,l"); break;
+ case 0x7e: sprintf (buffer,"mov a,m"); break;
+ case 0x7f: sprintf (buffer,"mov a,a"); break;
+ case 0x80: sprintf (buffer,"add b"); break;
+ case 0x81: sprintf (buffer,"add c"); break;
+ case 0x82: sprintf (buffer,"add d"); break;
+ case 0x83: sprintf (buffer,"add e"); break;
+ case 0x84: sprintf (buffer,"add h"); break;
+ case 0x85: sprintf (buffer,"add l"); break;
+ case 0x86: sprintf (buffer,"add m"); break;
+ case 0x87: sprintf (buffer,"add a"); break;
+ case 0x88: sprintf (buffer,"adc b"); break;
+ case 0x89: sprintf (buffer,"adc c"); break;
+ case 0x8a: sprintf (buffer,"adc d"); break;
+ case 0x8b: sprintf (buffer,"adc e"); break;
+ case 0x8c: sprintf (buffer,"adc h"); break;
+ case 0x8d: sprintf (buffer,"adc l"); break;
+ case 0x8e: sprintf (buffer,"adc m"); break;
+ case 0x8f: sprintf (buffer,"adc a"); break;
+ case 0x90: sprintf (buffer,"sub b"); break;
+ case 0x91: sprintf (buffer,"sub c"); break;
+ case 0x92: sprintf (buffer,"sub d"); break;
+ case 0x93: sprintf (buffer,"sub e"); break;
+ case 0x94: sprintf (buffer,"sub h"); break;
+ case 0x95: sprintf (buffer,"sub l"); break;
+ case 0x96: sprintf (buffer,"sub m"); break;
+ case 0x97: sprintf (buffer,"sub a"); break;
+ case 0x98: sprintf (buffer,"sbb b"); break;
+ case 0x99: sprintf (buffer,"sbb c"); break;
+ case 0x9a: sprintf (buffer,"sbb d"); break;
+ case 0x9b: sprintf (buffer,"sbb e"); break;
+ case 0x9c: sprintf (buffer,"sbb h"); break;
+ case 0x9d: sprintf (buffer,"sbb l"); break;
+ case 0x9e: sprintf (buffer,"sbb m"); break;
+ case 0x9f: sprintf (buffer,"sbb a"); break;
+ case 0xa0: sprintf (buffer,"ana b"); break;
+ case 0xa1: sprintf (buffer,"ana c"); break;
+ case 0xa2: sprintf (buffer,"ana d"); break;
+ case 0xa3: sprintf (buffer,"ana e"); break;
+ case 0xa4: sprintf (buffer,"ana h"); break;
+ case 0xa5: sprintf (buffer,"ana l"); break;
+ case 0xa6: sprintf (buffer,"ana m"); break;
+ case 0xa7: sprintf (buffer,"ana a"); break;
+ case 0xa8: sprintf (buffer,"xra b"); break;
+ case 0xa9: sprintf (buffer,"xra c"); break;
+ case 0xaa: sprintf (buffer,"xra d"); break;
+ case 0xab: sprintf (buffer,"xra e"); break;
+ case 0xac: sprintf (buffer,"xra h"); break;
+ case 0xad: sprintf (buffer,"xra l"); break;
+ case 0xae: sprintf (buffer,"xra m"); break;
+ case 0xaf: sprintf (buffer,"xra a"); break;
+ case 0xb0: sprintf (buffer,"ora b"); break;
+ case 0xb1: sprintf (buffer,"ora c"); break;
+ case 0xb2: sprintf (buffer,"ora d"); break;
+ case 0xb3: sprintf (buffer,"ora e"); break;
+ case 0xb4: sprintf (buffer,"ora h"); break;
+ case 0xb5: sprintf (buffer,"ora l"); break;
+ case 0xb6: sprintf (buffer,"ora m"); break;
+ case 0xb7: sprintf (buffer,"ora a"); break;
+ case 0xb8: sprintf (buffer,"cmp b"); break;
+ case 0xb9: sprintf (buffer,"cmp c"); break;
+ case 0xba: sprintf (buffer,"cmp d"); break;
+ case 0xbb: sprintf (buffer,"cmp e"); break;
+ case 0xbc: sprintf (buffer,"cmp h"); break;
+ case 0xbd: sprintf (buffer,"cmp l"); break;
+ case 0xbe: sprintf (buffer,"cmp m"); break;
+ case 0xbf: sprintf (buffer,"cmp a"); break;
+ case 0xc0: sprintf (buffer,"rnz"); flags = DASMFLAG_STEP_OUT; break;
+ case 0xc1: sprintf (buffer,"pop b"); break;
+ case 0xc2: sprintf (buffer,"jnz $%04x", ARGW(pc)); pc+=2; break;
+ case 0xc3: sprintf (buffer,"jmp $%04x", ARGW(pc)); pc+=2; break;
+ case 0xc4: sprintf (buffer,"cnz $%04x", ARGW(pc)); pc+=2; flags = DASMFLAG_STEP_OVER; break;
+ case 0xc5: sprintf (buffer,"push b"); break;
+ case 0xc6: sprintf (buffer,"adi $%02x", ARG(pc)); pc++; break;
+ case 0xc7: sprintf (buffer,"rst 0"); flags = DASMFLAG_STEP_OVER; break;
+ case 0xc8: sprintf (buffer,"rz"); flags = DASMFLAG_STEP_OUT; break;
+ case 0xc9: sprintf (buffer,"ret"); flags = DASMFLAG_STEP_OUT; break;
+ case 0xca: sprintf (buffer,"jz $%04x", ARGW(pc)); pc+=2; break;
+ case 0xcb: sprintf (buffer,"rstv 8 (*)"); flags = DASMFLAG_STEP_OVER; break;
+ case 0xcc: sprintf (buffer,"cz $%04x", ARGW(pc)); pc+=2; flags = DASMFLAG_STEP_OVER; break;
+ case 0xcd: sprintf (buffer,"call $%04x", ARGW(pc)); pc+=2; flags = DASMFLAG_STEP_OVER; break;
+ case 0xce: sprintf (buffer,"aci $%02x", ARG(pc)); pc++; break;
+ case 0xcf: sprintf (buffer,"rst 1"); flags = DASMFLAG_STEP_OVER; break;
+ case 0xd0: sprintf (buffer,"rnc"); flags = DASMFLAG_STEP_OUT; break;
+ case 0xd1: sprintf (buffer,"pop d"); break;
+ case 0xd2: sprintf (buffer,"jnc $%04x", ARGW(pc)); pc+=2; break;
+ case 0xd3: sprintf (buffer,"out $%02x", ARG(pc)); pc++; break;
+ case 0xd4: sprintf (buffer,"cnc $%04x", ARGW(pc)); pc+=2; flags = DASMFLAG_STEP_OVER; break;
+ case 0xd5: sprintf (buffer,"push d"); break;
+ case 0xd6: sprintf (buffer,"sui $%02x", ARG(pc)); pc++; break;
+ case 0xd7: sprintf (buffer,"rst 2"); flags = DASMFLAG_STEP_OVER; break;
+ case 0xd8: sprintf (buffer,"rc"); flags = DASMFLAG_STEP_OUT; break;
+ case 0xd9: sprintf (buffer,"shlx d (*)"); break;
+ case 0xda: sprintf (buffer,"jc $%04x", ARGW(pc)); pc+=2; break;
+ case 0xdb: sprintf (buffer,"in $%02x", ARG(pc)); pc++; break;
+ case 0xdc: sprintf (buffer,"cc $%04x", ARGW(pc)); pc+=2; flags = DASMFLAG_STEP_OVER; break;
+ case 0xdd: sprintf (buffer,"jnx $%04x (*)", ARGW(pc)); pc+=2; break;
+ case 0xde: sprintf (buffer,"sbi $%02x", ARG(pc)); pc++; break;
+ case 0xdf: sprintf (buffer,"rst 3"); flags = DASMFLAG_STEP_OVER; break;
+ case 0xe0: sprintf (buffer,"rpo"); flags = DASMFLAG_STEP_OUT; break;
+ case 0xe1: sprintf (buffer,"pop h"); break;
+ case 0xe2: sprintf (buffer,"jpo $%04x", ARGW(pc)); pc+=2; break;
+ case 0xe3: sprintf (buffer,"xthl"); break;
+ case 0xe4: sprintf (buffer,"cpo $%04x", ARGW(pc)); pc+=2; flags = DASMFLAG_STEP_OVER; break;
+ case 0xe5: sprintf (buffer,"push h"); break;
+ case 0xe6: sprintf (buffer,"ani $%02x", ARG(pc)); pc++; break;
+ case 0xe7: sprintf (buffer,"rst 4"); flags = DASMFLAG_STEP_OVER; break;
+ case 0xe8: sprintf (buffer,"rpe"); flags = DASMFLAG_STEP_OUT; break;
+ case 0xe9: sprintf (buffer,"pchl"); break;
+ case 0xea: sprintf (buffer,"jpe $%04x", ARGW(pc)); pc+=2; break;
+ case 0xeb: sprintf (buffer,"xchg"); break;
+ case 0xec: sprintf (buffer,"cpe $%04x", ARGW(pc)); pc+=2; flags = DASMFLAG_STEP_OVER; break;
+ case 0xed: sprintf (buffer,"lhlx d (*)"); break;
+ case 0xee: sprintf (buffer,"xri $%02x", ARG(pc)); pc++; break;
+ case 0xef: sprintf (buffer,"rst 5"); flags = DASMFLAG_STEP_OVER; break;
+ case 0xf0: sprintf (buffer,"rp"); flags = DASMFLAG_STEP_OUT; break;
+ case 0xf1: sprintf (buffer,"pop a"); break;
+ case 0xf2: sprintf (buffer,"jp $%04x", ARGW(pc)); pc+=2; break;
+ case 0xf3: sprintf (buffer,"di"); break;
+ case 0xf4: sprintf (buffer,"cp $%04x", ARGW(pc)); pc+=2; break;
+ case 0xf5: sprintf (buffer,"push a"); break;
+ case 0xf6: sprintf (buffer,"ori $%02x", ARG(pc)); pc++; break;
+ case 0xf7: sprintf (buffer,"rst 6"); flags = DASMFLAG_STEP_OVER; break;
+ case 0xf8: sprintf (buffer,"rm"); flags = DASMFLAG_STEP_OUT; break;
+ case 0xf9: sprintf (buffer,"sphl"); break;
+ case 0xfa: sprintf (buffer,"jm $%04x", ARGW(pc)); pc+=2; break;
+ case 0xfb: sprintf (buffer,"ei"); break;
+ case 0xfc: sprintf (buffer,"cm $%04x", ARGW(pc)); pc+=2; flags = DASMFLAG_STEP_OVER; break;
+ case 0xfd: sprintf (buffer,"jx $%04x (*)", ARGW(pc)); pc+=2; break;
+ case 0xfe: sprintf (buffer,"cpi $%02x", ARG(pc)); pc++; break;
+ case 0xff: sprintf (buffer,"rst 7"); flags = DASMFLAG_STEP_OVER; break;
+#endif
+ }
+ return (pc - PC) | flags | DASMFLAG_SUPPORTED;
+}
+
diff --git a/trunk/src/emu/cpu/i8085/i8085.c b/trunk/src/emu/cpu/i8085/i8085.c
new file mode 100644
index 00000000000..45ea628527d
--- /dev/null
+++ b/trunk/src/emu/cpu/i8085/i8085.c
@@ -0,0 +1,1298 @@
+/*****************************************************************************
+ *
+ * i8085.c
+ * Portable I8085A emulator V1.2
+ *
+ * Copyright Juergen Buchmueller, all rights reserved.
+ * Partially based on information out of Z80Em by Marcel De Kogel
+ *
+ * changes in V1.3
+ * - Added undocumented opcodes for the 8085A, based on a german
+ * book about microcomputers: "Mikrocomputertechnik mit dem
+ * Prozessor 8085A".
+ * - This book also suggest that INX/DCX should modify the X flag bit
+ * for a LSB to MSB carry and
+ * - that jumps take 10 T-states only when they're executed, 7 when
+ * they're skipped.
+ * Thanks for the info and a copy of the tables go to Timo Sachsenberg
+ * <timo.sachsenberg@student.uni-tuebingen.de>
+ * changes in V1.2
+ * - corrected cycle counts for these classes of opcodes
+ * Thanks go to Jim Battle <frustum@pacbell.bet>
+ *
+ * 808x Z80
+ * DEC A 5 4 \
+ * INC A 5 4 \
+ * LD A,B 5 4 >-- Z80 is faster
+ * JP (HL) 5 4 /
+ * CALL cc,nnnn: 11/17 10/17 /
+ *
+ * INC HL 5 6 \
+ * DEC HL 5 6 \
+ * LD SP,HL 5 6 \
+ * ADD HL,BC 10 11 \
+ * INC (HL) 10 11 >-- 8080 is faster
+ * DEC (HL) 10 11 /
+ * IN A,(#) 10 11 /
+ * OUT (#),A 10 11 /
+ * EX (SP),HL 18 19 /
+ *
+ * Copyright Juergen Buchmueller, all rights reserved.
+ * You can contact me at juergen@mame.net or pullmoll@stop1984.com
+ *
+ * - This source code is released as freeware for non-commercial purposes
+ * as part of the M.A.M.E. (Multiple Arcade Machine Emulator) project.
+ * The licensing terms of MAME apply to this piece of code for the MAME
+ * project and derviative works, as defined by the MAME license. You
+ * may opt to make modifications, improvements or derivative works under
+ * that same conditions, and the MAME project may opt to keep
+ * modifications, improvements or derivatives under their terms exclusively.
+ *
+ * - Alternatively you can choose to apply the terms of the "GPL" (see
+ * below) to this - and only this - piece of code or your derivative works.
+ * Note that in no case your choice can have any impact on any other
+ * source code of the MAME project, or binary, or executable, be it closely
+ * or losely related to this piece of code.
+ *
+ * - At your choice you are also free to remove either licensing terms from
+ * this file and continue to use it under only one of the two licenses. Do this
+ * if you think that licenses are not compatible (enough) for you, or if you
+ * consider either license 'too restrictive' or 'too free'.
+ *
+ * - GPL (GNU General Public License)
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Revisions:
+ *
+ * xx-xx-2002 Acho A. Tang
+ *
+ * - 8085 emulation was in fact never used. It's been treated as a plain 8080.
+ * - protected IRQ0 vector from being overwritten
+ * - modified interrupt handler to properly process 8085-specific IRQ's
+ * - corrected interrupt masking, RIM and SIM behaviors according to Intel's documentation
+ *
+ * 20-Jul-2002 Krzysztof Strzecha
+ *
+ * - SBB r instructions should affect parity flag.
+ * Fixed only for non x86 asm version (#define i8080_EXACT 1).
+ * There are probably more opcodes which should affect this flag, but don't.
+ * - JPO nnnn and JPE nnnn opcodes in disassembler were misplaced. Fixed.
+ * - Undocumented i8080 opcodes added:
+ * 08h, 10h, 18h, 20h, 28h, 30h, 38h - NOP
+ * 0CBh - JMP
+ * 0D9h - RET
+ * 0DDh, 0EDh, 0FDh - CALL
+ * Thanks for the info go to Anton V. Ignatichev.
+ *
+ * 08-Dec-2002 Krzysztof Strzecha
+ *
+ * - ADC r instructions should affect parity flag.
+ * Fixed only for non x86 asm version (#define i8080_EXACT 1).
+ * There are probably more opcodes which should affect this flag, but don't.
+ *
+ * 05-Sep-2003 Krzysztof Strzecha
+ *
+ * - INR r, DCR r, ADD r, SUB r, CMP r instructions should affect parity flag.
+ * Fixed only for non x86 asm version (#define i8080_EXACT 1).
+ *
+ * 23-Dec-2006 Tomasz Slanina
+ *
+ * - SIM fixed
+ *
+ * 28-Jan-2007 Zsolt Vasvari
+ *
+ * - Removed archaic i8080_EXACT flag.
+ *
+ * 08-June-2008 Miodrag Milanovic
+ *
+ * - Flag setting fix for some instructions and cycle count update
+ *
+ * August 2009, hap
+ *
+ * - removed DAA table
+ * - fixed accidental double memory reads due to macro overuse
+ * - fixed cycle deduction on unconditional CALL / RET
+ * - added cycle tables and cleaned up big switch source layout (1 tab = 4 spaces)
+ * - removed HLT cycle eating (earlier, HLT after EI could theoretically fail)
+ * - fixed parity flag on add/sub/cmp
+ * - renamed temp register XX to official name WZ
+ * - renamed flags from Z80 style S Z Y H X V N C to S Z X5 H X3 P V C, and
+ * fixed X5 / V flags where accidentally broken due to flag names confusion
+ *
+ * 21-Aug-2009, Curt Coder
+ *
+ * - added 8080A variant
+ * - refactored callbacks to use devcb
+ *
+ *****************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "i8085.h"
+#include "i8085cpu.h"
+
+#define VERBOSE 0
+
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+#define CPUTYPE_8080 0
+#define CPUTYPE_8085 1
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _i8085_state i8085_state;
+struct _i8085_state
+{
+ i8085_config config;
+
+ devcb_resolved_write8 out_status_func;
+ devcb_resolved_write_line out_inte_func;
+ devcb_resolved_read_line in_sid_func;
+ devcb_resolved_write_line out_sod_func;
+
+ int cputype; /* 0 8080, 1 8085A */
+ PAIR PC,SP,AF,BC,DE,HL,WZ;
+ UINT8 HALT;
+ UINT8 IM; /* interrupt mask (8085A only) */
+ UINT8 STATUS; /* status word */
+
+ UINT8 after_ei; /* post-EI processing; starts at 2, check for ints at 0 */
+ UINT8 nmi_state; /* raw NMI line state */
+ UINT8 irq_state[4]; /* raw IRQ line states */
+ UINT8 trap_pending; /* TRAP interrupt latched? */
+ UINT8 trap_im_copy; /* copy of IM register when TRAP was taken */
+ UINT8 sod_state; /* state of the SOD line */
+
+ UINT8 ietemp; /* import/export temp space */
+
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ address_space *io;
+ int icount;
+};
+
+
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+#define IS_8080(c) ((c)->cputype == CPUTYPE_8080)
+#define IS_8085(c) ((c)->cputype == CPUTYPE_8085)
+
+
+
+/***************************************************************************
+ STATIC TABLES
+***************************************************************************/
+
+/* cycles lookup */
+static const UINT8 lut_cycles_8080[256]={
+/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
+/* 0 */ 4, 10,7, 5, 5, 5, 7, 4, 4, 10,7, 5, 5, 5, 7, 4,
+/* 1 */ 4, 10,7, 5, 5, 5, 7, 4, 4, 10,7, 5, 5, 5, 7, 4,
+/* 2 */ 4, 10,16,5, 5, 5, 7, 4, 4, 10,16,5, 5, 5, 7, 4,
+/* 3 */ 4, 10,13,5, 10,10,10,4, 4, 10,13,5, 5, 5, 7, 4,
+/* 4 */ 5, 5, 5, 5, 5, 5, 7, 5, 5, 5, 5, 5, 5, 5, 7, 5,
+/* 5 */ 5, 5, 5, 5, 5, 5, 7, 5, 5, 5, 5, 5, 5, 5, 7, 5,
+/* 6 */ 5, 5, 5, 5, 5, 5, 7, 5, 5, 5, 5, 5, 5, 5, 7, 5,
+/* 7 */ 7, 7, 7, 7, 7, 7, 7, 7, 5, 5, 5, 5, 5, 5, 7, 5,
+/* 8 */ 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
+/* 9 */ 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
+/* A */ 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
+/* B */ 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
+/* C */ 5, 10,10,10,11,11,7, 11,5, 10,10,10,11,11,7, 11,
+/* D */ 5, 10,10,10,11,11,7, 11,5, 10,10,10,11,11,7, 11,
+/* E */ 5, 10,10,18,11,11,7, 11,5, 5, 10,5, 11,11,7, 11,
+/* F */ 5, 10,10,4, 11,11,7, 11,5, 5, 10,4, 11,11,7, 11 };
+static const UINT8 lut_cycles_8085[256]={
+/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
+/* 0 */ 4, 10,7, 6, 4, 4, 7, 4, 10,10,7, 6, 4, 4, 7, 4,
+/* 1 */ 7, 10,7, 6, 4, 4, 7, 4, 10,10,7, 6, 4, 4, 7, 4,
+/* 2 */ 7, 10,16,6, 4, 4, 7, 4, 10,10,16,6, 4, 4, 7, 4,
+/* 3 */ 7, 10,13,6, 10,10,10,4, 10,10,13,6, 4, 4, 7, 4,
+/* 4 */ 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
+/* 5 */ 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
+/* 6 */ 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
+/* 7 */ 7, 7, 7, 7, 7, 7, 5, 7, 4, 4, 4, 4, 4, 4, 7, 4,
+/* 8 */ 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
+/* 9 */ 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
+/* A */ 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
+/* B */ 4, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 4, 4, 7, 4,
+/* C */ 6, 10,10,10,11,12,7, 12,6, 10,10,12,11,11,7, 12,
+/* D */ 6, 10,10,10,11,12,7, 12,6, 10,10,10,11,10,7, 12,
+/* E */ 6, 10,10,16,11,12,7, 12,6, 6, 10,5, 11,10,7, 12,
+/* F */ 6, 10,10,4, 11,12,7, 12,6, 6, 10,4, 11,10,7, 12 };
+
+/* special cases (partially taken care of elsewhere):
+ base c taken? not taken?
+M_RET 8080 5 +6(11) -0 (conditional)
+M_RET 8085 6 +6(12) -0 (conditional)
+M_JMP 8080 10 +0 -0
+M_JMP 8085 10 +0 -3(7)
+M_CALL 8080 11 +6(17) -0
+M_CALL 8085 11 +7(18) -2(9)
+
+*/
+static UINT8 lut_cycles[256];
+
+/* flags lookup */
+static UINT8 ZS[256];
+static UINT8 ZSP[256];
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static void execute_one(i8085_state *cpustate, int opcode);
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+INLINE i8085_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == I8080 ||
+ device->type() == I8080A||
+ device->type() == I8085A);
+ return (i8085_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+INLINE void set_sod(i8085_state *cpustate, int state)
+{
+ if (state != 0 && cpustate->sod_state == 0)
+ {
+ cpustate->sod_state = 1;
+ cpustate->out_sod_func(cpustate->sod_state);
+ }
+ else if (state == 0 && cpustate->sod_state != 0)
+ {
+ cpustate->sod_state = 0;
+ cpustate->out_sod_func(cpustate->sod_state);
+ }
+}
+
+
+INLINE void set_inte(i8085_state *cpustate, int state)
+{
+ if (state != 0 && (cpustate->IM & IM_IE) == 0)
+ {
+ cpustate->IM |= IM_IE;
+ cpustate->out_inte_func(1);
+ }
+ else if (state == 0 && (cpustate->IM & IM_IE) != 0)
+ {
+ cpustate->IM &= ~IM_IE;
+ cpustate->out_inte_func(0);
+ }
+}
+
+
+INLINE void set_status(i8085_state *cpustate, UINT8 status)
+{
+ if (status != cpustate->STATUS)
+ cpustate->out_status_func(0, status);
+
+ cpustate->STATUS = status;
+}
+
+
+INLINE UINT8 get_rim_value(i8085_state *cpustate)
+{
+ UINT8 result = cpustate->IM;
+ int sid = cpustate->in_sid_func();
+
+ /* copy live RST5.5 and RST6.5 states */
+ result &= ~(IM_I65 | IM_I55);
+ if (cpustate->irq_state[I8085_RST65_LINE]) result |= IM_I65;
+ if (cpustate->irq_state[I8085_RST55_LINE]) result |= IM_I55;
+
+ /* fetch the SID bit if we have a callback */
+ result = (result & 0x7f) | (sid ? 0x80 : 0);
+
+ return result;
+}
+
+
+INLINE void break_halt_for_interrupt(i8085_state *cpustate)
+{
+ /* de-halt if necessary */
+ if (cpustate->HALT)
+ {
+ cpustate->PC.w.l++;
+ cpustate->HALT = 0;
+ set_status(cpustate, 0x26); /* int ack while halt */
+ }
+ else
+ set_status(cpustate, 0x23); /* int ack */
+}
+
+
+INLINE UINT8 ROP(i8085_state *cpustate)
+{
+ set_status(cpustate, 0xa2); // instruction fetch
+ return cpustate->direct->read_decrypted_byte(cpustate->PC.w.l++);
+}
+
+INLINE UINT8 ARG(i8085_state *cpustate)
+{
+ return cpustate->direct->read_raw_byte(cpustate->PC.w.l++);
+}
+
+INLINE UINT16 ARG16(i8085_state *cpustate)
+{
+ UINT16 w;
+ w = cpustate->direct->read_raw_byte(cpustate->PC.d);
+ cpustate->PC.w.l++;
+ w += cpustate->direct->read_raw_byte(cpustate->PC.d) << 8;
+ cpustate->PC.w.l++;
+ return w;
+}
+
+INLINE UINT8 RM(i8085_state *cpustate, UINT32 a)
+{
+ set_status(cpustate, 0x82); // memory read
+ return cpustate->program->read_byte(a);
+}
+
+INLINE void WM(i8085_state *cpustate, UINT32 a, UINT8 v)
+{
+ set_status(cpustate, 0x00); // memory write
+ cpustate->program->write_byte(a, v);
+}
+
+
+static void check_for_interrupts(i8085_state *cpustate)
+{
+ /* TRAP is the highest priority */
+ if (cpustate->trap_pending)
+ {
+ /* the first RIM after a TRAP reflects the original IE state; remember it here,
+ setting the high bit to indicate it is valid */
+ cpustate->trap_im_copy = cpustate->IM | 0x80;
+
+ /* reset the pending state */
+ cpustate->trap_pending = FALSE;
+
+ /* break out of HALT state and call the IRQ ack callback */
+ break_halt_for_interrupt(cpustate);
+ if (cpustate->irq_callback != NULL)
+ (*cpustate->irq_callback)(cpustate->device, INPUT_LINE_NMI);
+
+ /* push the PC and jump to $0024 */
+ M_PUSH(PC);
+ set_inte(cpustate, 0);
+ cpustate->PC.w.l = ADDR_TRAP;
+ cpustate->icount -= 11;
+ }
+
+ /* followed by RST7.5 */
+ else if ((cpustate->IM & IM_I75) && !(cpustate->IM & IM_M75) && (cpustate->IM & IM_IE))
+ {
+ /* reset the pending state (which is CPU-visible via the RIM instruction) */
+ cpustate->IM &= ~IM_I75;
+
+ /* break out of HALT state and call the IRQ ack callback */
+ break_halt_for_interrupt(cpustate);
+ if (cpustate->irq_callback != NULL)
+ (*cpustate->irq_callback)(cpustate->device, I8085_RST75_LINE);
+
+ /* push the PC and jump to $003C */
+ M_PUSH(PC);
+ set_inte(cpustate, 0);
+ cpustate->PC.w.l = ADDR_RST75;
+ cpustate->icount -= 11;
+ }
+
+ /* followed by RST6.5 */
+ else if (cpustate->irq_state[I8085_RST65_LINE] && !(cpustate->IM & IM_M65) && (cpustate->IM & IM_IE))
+ {
+ /* break out of HALT state and call the IRQ ack callback */
+ break_halt_for_interrupt(cpustate);
+ if (cpustate->irq_callback != NULL)
+ (*cpustate->irq_callback)(cpustate->device, I8085_RST65_LINE);
+
+ /* push the PC and jump to $0034 */
+ M_PUSH(PC);
+ set_inte(cpustate, 0);
+ cpustate->PC.w.l = ADDR_RST65;
+ cpustate->icount -= 11;
+ }
+
+ /* followed by RST5.5 */
+ else if (cpustate->irq_state[I8085_RST55_LINE] && !(cpustate->IM & IM_M55) && (cpustate->IM & IM_IE))
+ {
+ /* break out of HALT state and call the IRQ ack callback */
+ break_halt_for_interrupt(cpustate);
+ if (cpustate->irq_callback != NULL)
+ (*cpustate->irq_callback)(cpustate->device, I8085_RST55_LINE);
+
+ /* push the PC and jump to $002C */
+ M_PUSH(PC);
+ set_inte(cpustate, 0);
+ cpustate->PC.w.l = ADDR_RST55;
+ cpustate->icount -= 11;
+ }
+
+ /* followed by classic INTR */
+ else if (cpustate->irq_state[I8085_INTR_LINE] && (cpustate->IM & IM_IE))
+ {
+ UINT32 vector = 0;
+
+ /* break out of HALT state and call the IRQ ack callback */
+ break_halt_for_interrupt(cpustate);
+ if (cpustate->irq_callback != NULL)
+ vector = (*cpustate->irq_callback)(cpustate->device, I8085_INTR_LINE);
+
+ /* use the resulting vector as an opcode to execute */
+ set_inte(cpustate, 0);
+ switch (vector & 0xff0000)
+ {
+ case 0xcd0000: /* CALL nnnn */
+ cpustate->icount -= 7;
+ M_PUSH(PC);
+ case 0xc30000: /* JMP nnnn */
+ cpustate->icount -= 10;
+ cpustate->PC.d = vector & 0xffff;
+ break;
+
+ default:
+ LOG(("i8085 take int $%02x\n", vector));
+ execute_one(cpustate, vector & 0xff);
+ break;
+ }
+ }
+}
+
+
+static void execute_one(i8085_state *cpustate, int opcode)
+{
+ cpustate->icount -= lut_cycles[opcode];
+
+ switch (opcode)
+ {
+ case 0x00: break; /* NOP */
+ case 0x01: cpustate->BC.w.l = ARG16(cpustate); break; /* LXI B,nnnn */
+ case 0x02: WM(cpustate, cpustate->BC.d, cpustate->AF.b.h); break; /* STAX B */
+ case 0x03: cpustate->BC.w.l++; /* INX B */
+ if (IS_8085(cpustate)) { if (cpustate->BC.w.l == 0x0000) cpustate->AF.b.l |= X5F; else cpustate->AF.b.l &= ~X5F; }
+ break;
+ case 0x04: M_INR(cpustate->BC.b.h); break; /* INR B */
+ case 0x05: M_DCR(cpustate->BC.b.h); break; /* DCR B */
+ case 0x06: M_MVI(cpustate->BC.b.h); break; /* MVI B,nn */
+ case 0x07: M_RLC; break; /* RLC */
+
+ case 0x08: if (IS_8085(cpustate)) { M_DSUB(cpustate); } /* DSUB */
+ /* else { ; } */ /* NOP undocumented */
+ break;
+ case 0x09: M_DAD(BC); break; /* DAD B */
+ case 0x0a: cpustate->AF.b.h = RM(cpustate, cpustate->BC.d); break; /* LDAX B */
+ case 0x0b: cpustate->BC.w.l--; /* DCX B */
+ if (IS_8085(cpustate)) { if (cpustate->BC.w.l == 0xffff) cpustate->AF.b.l |= X5F; else cpustate->AF.b.l &= ~X5F; }
+ break;
+ case 0x0c: M_INR(cpustate->BC.b.l); break; /* INR C */
+ case 0x0d: M_DCR(cpustate->BC.b.l); break; /* DCR C */
+ case 0x0e: M_MVI(cpustate->BC.b.l); break; /* MVI C,nn */
+ case 0x0f: M_RRC; break; /* RRC */
+
+ case 0x10: if (IS_8085(cpustate)) { /* ASRH */
+ cpustate->AF.b.l = (cpustate->AF.b.l & ~CF) | (cpustate->HL.b.l & CF);
+ cpustate->HL.w.l = (cpustate->HL.w.l >> 1);
+ } /* else { ; } */ /* NOP undocumented */
+ break;
+ case 0x11: cpustate->DE.w.l = ARG16(cpustate); break; /* LXI D,nnnn */
+ case 0x12: WM(cpustate, cpustate->DE.d, cpustate->AF.b.h); break; /* STAX D */
+ case 0x13: cpustate->DE.w.l++; /* INX D */
+ if (IS_8085(cpustate)) { if (cpustate->DE.w.l == 0x0000) cpustate->AF.b.l |= X5F; else cpustate->AF.b.l &= ~X5F; }
+ break;
+ case 0x14: M_INR(cpustate->DE.b.h); break; /* INR D */
+ case 0x15: M_DCR(cpustate->DE.b.h); break; /* DCR D */
+ case 0x16: M_MVI(cpustate->DE.b.h); break; /* MVI D,nn */
+ case 0x17: M_RAL; break; /* RAL */
+
+ case 0x18: if (IS_8085(cpustate)) { /* RLDE */
+ cpustate->AF.b.l = (cpustate->AF.b.l & ~(CF | VF)) | (cpustate->DE.b.h >> 7);
+ cpustate->DE.w.l = (cpustate->DE.w.l << 1) | (cpustate->DE.w.l >> 15);
+ if (0 != (((cpustate->DE.w.l >> 15) ^ cpustate->AF.b.l) & CF)) cpustate->AF.b.l |= VF;
+ } /* else { ; } */ /* NOP undocumented */
+ break;
+ case 0x19: M_DAD(DE); break; /* DAD D */
+ case 0x1a: cpustate->AF.b.h = RM(cpustate, cpustate->DE.d); break; /* LDAX D */
+ case 0x1b: cpustate->DE.w.l--; /* DCX D */
+ if (IS_8085(cpustate)) { if (cpustate->DE.w.l == 0xffff) cpustate->AF.b.l |= X5F; else cpustate->AF.b.l &= ~X5F; }
+ break;
+ case 0x1c: M_INR(cpustate->DE.b.l); break; /* INR E */
+ case 0x1d: M_DCR(cpustate->DE.b.l); break; /* DCR E */
+ case 0x1e: M_MVI(cpustate->DE.b.l); break; /* MVI E,nn */
+ case 0x1f: M_RAR; break; /* RAR */
+
+ case 0x20: if (IS_8085(cpustate)) { /* RIM */
+ cpustate->AF.b.h = get_rim_value(cpustate);
+
+ /* if we have remembered state from taking a TRAP, fix up the IE flag here */
+ if (cpustate->trap_im_copy & 0x80) cpustate->AF.b.h = (cpustate->AF.b.h & ~IM_IE) | (cpustate->trap_im_copy & IM_IE);
+ cpustate->trap_im_copy = 0;
+ } /* else { ; } */ /* NOP undocumented */
+ break;
+ case 0x21: cpustate->HL.w.l = ARG16(cpustate); break; /* LXI H,nnnn */
+ case 0x22: cpustate->WZ.w.l = ARG16(cpustate); /* SHLD nnnn */
+ WM(cpustate, cpustate->WZ.d, cpustate->HL.b.l); cpustate->WZ.w.l++;
+ WM(cpustate, cpustate->WZ.d, cpustate->HL.b.h);
+ break;
+ case 0x23: cpustate->HL.w.l++; /* INX H */
+ if (IS_8085(cpustate)) { if (cpustate->HL.w.l == 0x0000) cpustate->AF.b.l |= X5F; else cpustate->AF.b.l &= ~X5F; }
+ break;
+ case 0x24: M_INR(cpustate->HL.b.h); break; /* INR H */
+ case 0x25: M_DCR(cpustate->HL.b.h); break; /* DCR H */
+ case 0x26: M_MVI(cpustate->HL.b.h); break; /* MVI H,nn */
+ case 0x27: cpustate->WZ.b.h = cpustate->AF.b.h; /* DAA */
+ if (cpustate->AF.b.l&VF) {
+ if ((cpustate->AF.b.l&HF) | ((cpustate->AF.b.h&0xf)>9)) cpustate->WZ.b.h-=6;
+ if ((cpustate->AF.b.l&CF) | (cpustate->AF.b.h>0x99)) cpustate->WZ.b.h-=0x60;
+ }
+ else {
+ if ((cpustate->AF.b.l&HF) | ((cpustate->AF.b.h&0xf)>9)) cpustate->WZ.b.h+=6;
+ if ((cpustate->AF.b.l&CF) | (cpustate->AF.b.h>0x99)) cpustate->WZ.b.h+=0x60;
+ }
+
+ cpustate->AF.b.l=(cpustate->AF.b.l&3) | (cpustate->AF.b.h&0x28) | (cpustate->AF.b.h>0x99) | ((cpustate->AF.b.h^cpustate->WZ.b.h)&0x10) | ZSP[cpustate->WZ.b.h];
+ cpustate->AF.b.h=cpustate->WZ.b.h;
+
+ if (IS_8080(cpustate)) cpustate->AF.b.l &= 0xd5; // Ignore not used flags
+ break;
+
+ case 0x28: if (IS_8085(cpustate)) { /* LDEH nn */
+ cpustate->WZ.d = ARG(cpustate);
+ cpustate->DE.d = (cpustate->HL.d + cpustate->WZ.d) & 0xffff;
+ } /* else { ; } */ /* NOP undocumented */
+ break;
+ case 0x29: M_DAD(HL); break; /* DAD H */
+ case 0x2a: cpustate->WZ.d = ARG16(cpustate); /* LHLD nnnn */
+ cpustate->HL.b.l = RM(cpustate, cpustate->WZ.d); cpustate->WZ.w.l++;
+ cpustate->HL.b.h = RM(cpustate, cpustate->WZ.d);
+ break;
+ case 0x2b: cpustate->HL.w.l--; /* DCX H */
+ if (IS_8085(cpustate)) { if (cpustate->HL.w.l == 0xffff) cpustate->AF.b.l |= X5F; else cpustate->AF.b.l &= ~X5F; }
+ break;
+ case 0x2c: M_INR(cpustate->HL.b.l); break; /* INR L */
+ case 0x2d: M_DCR(cpustate->HL.b.l); break; /* DCR L */
+ case 0x2e: M_MVI(cpustate->HL.b.l); break; /* MVI L,nn */
+ case 0x2f: cpustate->AF.b.h ^= 0xff; /* CMA */
+ if (IS_8085(cpustate)) cpustate->AF.b.l |= HF | VF;
+ break;
+
+ case 0x30: if (IS_8085(cpustate)) { /* SIM */
+ /* if bit 3 is set, bits 0-2 become the new masks */
+ if (cpustate->AF.b.h & 0x08) {
+ cpustate->IM &= ~(IM_M55 | IM_M65 | IM_M75 | IM_I55 | IM_I65);
+ cpustate->IM |= cpustate->AF.b.h & (IM_M55 | IM_M65 | IM_M75);
+
+ /* update live state based on the new masks */
+ if ((cpustate->IM & IM_M55) == 0 && cpustate->irq_state[I8085_RST55_LINE]) cpustate->IM |= IM_I55;
+ if ((cpustate->IM & IM_M65) == 0 && cpustate->irq_state[I8085_RST65_LINE]) cpustate->IM |= IM_I65;
+ }
+
+ /* bit if 4 is set, the 7.5 flip-flop is cleared */
+ if (cpustate->AF.b.h & 0x10) cpustate->IM &= ~IM_I75;
+
+ /* if bit 6 is set, then bit 7 is the new SOD state */
+ if (cpustate->AF.b.h & 0x40) set_sod(cpustate, cpustate->AF.b.h >> 7);
+
+ /* check for revealed interrupts */
+ check_for_interrupts(cpustate);
+ } /* else { ; } */ /* NOP undocumented */
+ break;
+ case 0x31: cpustate->SP.w.l = ARG16(cpustate); break; /* LXI SP,nnnn */
+ case 0x32: cpustate->WZ.d = ARG16(cpustate); /* STAX nnnn */
+ WM(cpustate, cpustate->WZ.d, cpustate->AF.b.h);
+ break;
+ case 0x33: cpustate->SP.w.l++; /* INX SP */
+ if (IS_8085(cpustate)) { if (cpustate->SP.w.l == 0x0000) cpustate->AF.b.l |= X5F; else cpustate->AF.b.l &= ~X5F; }
+ break;
+ case 0x34: cpustate->WZ.b.l = RM(cpustate, cpustate->HL.d); /* INR M */
+ M_INR(cpustate->WZ.b.l);
+ WM(cpustate, cpustate->HL.d, cpustate->WZ.b.l);
+ break;
+ case 0x35: cpustate->WZ.b.l = RM(cpustate, cpustate->HL.d); /* DCR M */
+ M_DCR(cpustate->WZ.b.l);
+ WM(cpustate, cpustate->HL.d, cpustate->WZ.b.l);
+ break;
+ case 0x36: cpustate->WZ.b.l = ARG(cpustate); /* MVI M,nn */
+ WM(cpustate, cpustate->HL.d, cpustate->WZ.b.l);
+ break;
+ case 0x37: cpustate->AF.b.l = (cpustate->AF.b.l & 0xfe) | CF; break; /* STC */
+
+ case 0x38: if (IS_8085(cpustate)) { /* LDES nn */
+ cpustate->WZ.d = ARG(cpustate);
+ cpustate->DE.d = (cpustate->SP.d + cpustate->WZ.d) & 0xffff;
+ } /* else { ; } */ /* NOP undocumented */
+ break;
+ case 0x39: M_DAD(SP); break; /* DAD SP */
+ case 0x3a: cpustate->WZ.d = ARG16(cpustate); /* LDAX nnnn */
+ cpustate->AF.b.h = RM(cpustate, cpustate->WZ.d);
+ break;
+ case 0x3b: cpustate->SP.w.l--; /* DCX SP */
+ if (IS_8085(cpustate)) { if (cpustate->SP.w.l == 0xffff) cpustate->AF.b.l |= X5F; else cpustate->AF.b.l &= ~X5F; }
+ break;
+ case 0x3c: M_INR(cpustate->AF.b.h); break; /* INR A */
+ case 0x3d: M_DCR(cpustate->AF.b.h); break; /* DCR A */
+ case 0x3e: M_MVI(cpustate->AF.b.h); break; /* MVI A,nn */
+ case 0x3f: cpustate->AF.b.l = (cpustate->AF.b.l & 0xfe) | (~cpustate->AF.b.l & CF); break; /* CMC */
+
+ case 0x40: break; /* MOV B,B */
+ case 0x41: cpustate->BC.b.h = cpustate->BC.b.l; break; /* MOV B,C */
+ case 0x42: cpustate->BC.b.h = cpustate->DE.b.h; break; /* MOV B,D */
+ case 0x43: cpustate->BC.b.h = cpustate->DE.b.l; break; /* MOV B,E */
+ case 0x44: cpustate->BC.b.h = cpustate->HL.b.h; break; /* MOV B,H */
+ case 0x45: cpustate->BC.b.h = cpustate->HL.b.l; break; /* MOV B,L */
+ case 0x46: cpustate->BC.b.h = RM(cpustate, cpustate->HL.d); break; /* MOV B,M */
+ case 0x47: cpustate->BC.b.h = cpustate->AF.b.h; break; /* MOV B,A */
+
+ case 0x48: cpustate->BC.b.l = cpustate->BC.b.h; break; /* MOV C,B */
+ case 0x49: break; /* MOV C,C */
+ case 0x4a: cpustate->BC.b.l = cpustate->DE.b.h; break; /* MOV C,D */
+ case 0x4b: cpustate->BC.b.l = cpustate->DE.b.l; break; /* MOV C,E */
+ case 0x4c: cpustate->BC.b.l = cpustate->HL.b.h; break; /* MOV C,H */
+ case 0x4d: cpustate->BC.b.l = cpustate->HL.b.l; break; /* MOV C,L */
+ case 0x4e: cpustate->BC.b.l = RM(cpustate, cpustate->HL.d); break; /* MOV C,M */
+ case 0x4f: cpustate->BC.b.l = cpustate->AF.b.h; break; /* MOV C,A */
+
+ case 0x50: cpustate->DE.b.h = cpustate->BC.b.h; break; /* MOV D,B */
+ case 0x51: cpustate->DE.b.h = cpustate->BC.b.l; break; /* MOV D,C */
+ case 0x52: break; /* MOV D,D */
+ case 0x53: cpustate->DE.b.h = cpustate->DE.b.l; break; /* MOV D,E */
+ case 0x54: cpustate->DE.b.h = cpustate->HL.b.h; break; /* MOV D,H */
+ case 0x55: cpustate->DE.b.h = cpustate->HL.b.l; break; /* MOV D,L */
+ case 0x56: cpustate->DE.b.h = RM(cpustate, cpustate->HL.d); break; /* MOV D,M */
+ case 0x57: cpustate->DE.b.h = cpustate->AF.b.h; break; /* MOV D,A */
+
+ case 0x58: cpustate->DE.b.l = cpustate->BC.b.h; break; /* MOV E,B */
+ case 0x59: cpustate->DE.b.l = cpustate->BC.b.l; break; /* MOV E,C */
+ case 0x5a: cpustate->DE.b.l = cpustate->DE.b.h; break; /* MOV E,D */
+ case 0x5b: break; /* MOV E,E */
+ case 0x5c: cpustate->DE.b.l = cpustate->HL.b.h; break; /* MOV E,H */
+ case 0x5d: cpustate->DE.b.l = cpustate->HL.b.l; break; /* MOV E,L */
+ case 0x5e: cpustate->DE.b.l = RM(cpustate, cpustate->HL.d); break; /* MOV E,M */
+ case 0x5f: cpustate->DE.b.l = cpustate->AF.b.h; break; /* MOV E,A */
+
+ case 0x60: cpustate->HL.b.h = cpustate->BC.b.h; break; /* MOV H,B */
+ case 0x61: cpustate->HL.b.h = cpustate->BC.b.l; break; /* MOV H,C */
+ case 0x62: cpustate->HL.b.h = cpustate->DE.b.h; break; /* MOV H,D */
+ case 0x63: cpustate->HL.b.h = cpustate->DE.b.l; break; /* MOV H,E */
+ case 0x64: break; /* MOV H,H */
+ case 0x65: cpustate->HL.b.h = cpustate->HL.b.l; break; /* MOV H,L */
+ case 0x66: cpustate->HL.b.h = RM(cpustate, cpustate->HL.d); break; /* MOV H,M */
+ case 0x67: cpustate->HL.b.h = cpustate->AF.b.h; break; /* MOV H,A */
+
+ case 0x68: cpustate->HL.b.l = cpustate->BC.b.h; break; /* MOV L,B */
+ case 0x69: cpustate->HL.b.l = cpustate->BC.b.l; break; /* MOV L,C */
+ case 0x6a: cpustate->HL.b.l = cpustate->DE.b.h; break; /* MOV L,D */
+ case 0x6b: cpustate->HL.b.l = cpustate->DE.b.l; break; /* MOV L,E */
+ case 0x6c: cpustate->HL.b.l = cpustate->HL.b.h; break; /* MOV L,H */
+ case 0x6d: break; /* MOV L,L */
+ case 0x6e: cpustate->HL.b.l = RM(cpustate, cpustate->HL.d); break; /* MOV L,M */
+ case 0x6f: cpustate->HL.b.l = cpustate->AF.b.h; break; /* MOV L,A */
+
+ case 0x70: WM(cpustate, cpustate->HL.d, cpustate->BC.b.h); break; /* MOV M,B */
+ case 0x71: WM(cpustate, cpustate->HL.d, cpustate->BC.b.l); break; /* MOV M,C */
+ case 0x72: WM(cpustate, cpustate->HL.d, cpustate->DE.b.h); break; /* MOV M,D */
+ case 0x73: WM(cpustate, cpustate->HL.d, cpustate->DE.b.l); break; /* MOV M,E */
+ case 0x74: WM(cpustate, cpustate->HL.d, cpustate->HL.b.h); break; /* MOV M,H */
+ case 0x75: WM(cpustate, cpustate->HL.d, cpustate->HL.b.l); break; /* MOV M,L */
+ case 0x76: cpustate->PC.w.l--; cpustate->HALT = 1; /* HLT */
+ set_status(cpustate, 0x8a); // halt acknowledge
+ break;
+ case 0x77: WM(cpustate, cpustate->HL.d, cpustate->AF.b.h); break; /* MOV M,A */
+
+ case 0x78: cpustate->AF.b.h = cpustate->BC.b.h; break; /* MOV A,B */
+ case 0x79: cpustate->AF.b.h = cpustate->BC.b.l; break; /* MOV A,C */
+ case 0x7a: cpustate->AF.b.h = cpustate->DE.b.h; break; /* MOV A,D */
+ case 0x7b: cpustate->AF.b.h = cpustate->DE.b.l; break; /* MOV A,E */
+ case 0x7c: cpustate->AF.b.h = cpustate->HL.b.h; break; /* MOV A,H */
+ case 0x7d: cpustate->AF.b.h = cpustate->HL.b.l; break; /* MOV A,L */
+ case 0x7e: cpustate->AF.b.h = RM(cpustate, cpustate->HL.d); break; /* MOV A,M */
+ case 0x7f: break; /* MOV A,A */
+
+ case 0x80: M_ADD(cpustate->BC.b.h); break; /* ADD B */
+ case 0x81: M_ADD(cpustate->BC.b.l); break; /* ADD C */
+ case 0x82: M_ADD(cpustate->DE.b.h); break; /* ADD D */
+ case 0x83: M_ADD(cpustate->DE.b.l); break; /* ADD E */
+ case 0x84: M_ADD(cpustate->HL.b.h); break; /* ADD H */
+ case 0x85: M_ADD(cpustate->HL.b.l); break; /* ADD L */
+ case 0x86: cpustate->WZ.b.l = RM(cpustate, cpustate->HL.d); M_ADD(cpustate->WZ.b.l); break; /* ADD M */
+ case 0x87: M_ADD(cpustate->AF.b.h); break; /* ADD A */
+
+ case 0x88: M_ADC(cpustate->BC.b.h); break; /* ADC B */
+ case 0x89: M_ADC(cpustate->BC.b.l); break; /* ADC C */
+ case 0x8a: M_ADC(cpustate->DE.b.h); break; /* ADC D */
+ case 0x8b: M_ADC(cpustate->DE.b.l); break; /* ADC E */
+ case 0x8c: M_ADC(cpustate->HL.b.h); break; /* ADC H */
+ case 0x8d: M_ADC(cpustate->HL.b.l); break; /* ADC L */
+ case 0x8e: cpustate->WZ.b.l = RM(cpustate, cpustate->HL.d); M_ADC(cpustate->WZ.b.l); break; /* ADC M */
+ case 0x8f: M_ADC(cpustate->AF.b.h); break; /* ADC A */
+
+ case 0x90: M_SUB(cpustate->BC.b.h); break; /* SUB B */
+ case 0x91: M_SUB(cpustate->BC.b.l); break; /* SUB C */
+ case 0x92: M_SUB(cpustate->DE.b.h); break; /* SUB D */
+ case 0x93: M_SUB(cpustate->DE.b.l); break; /* SUB E */
+ case 0x94: M_SUB(cpustate->HL.b.h); break; /* SUB H */
+ case 0x95: M_SUB(cpustate->HL.b.l); break; /* SUB L */
+ case 0x96: cpustate->WZ.b.l = RM(cpustate, cpustate->HL.d); M_SUB(cpustate->WZ.b.l); break; /* SUB M */
+ case 0x97: M_SUB(cpustate->AF.b.h); break; /* SUB A */
+
+ case 0x98: M_SBB(cpustate->BC.b.h); break; /* SBB B */
+ case 0x99: M_SBB(cpustate->BC.b.l); break; /* SBB C */
+ case 0x9a: M_SBB(cpustate->DE.b.h); break; /* SBB D */
+ case 0x9b: M_SBB(cpustate->DE.b.l); break; /* SBB E */
+ case 0x9c: M_SBB(cpustate->HL.b.h); break; /* SBB H */
+ case 0x9d: M_SBB(cpustate->HL.b.l); break; /* SBB L */
+ case 0x9e: cpustate->WZ.b.l = RM(cpustate, cpustate->HL.d); M_SBB(cpustate->WZ.b.l); break; /* SBB M */
+ case 0x9f: M_SBB(cpustate->AF.b.h); break; /* SBB A */
+
+ case 0xa0: M_ANA(cpustate->BC.b.h); break; /* ANA B */
+ case 0xa1: M_ANA(cpustate->BC.b.l); break; /* ANA C */
+ case 0xa2: M_ANA(cpustate->DE.b.h); break; /* ANA D */
+ case 0xa3: M_ANA(cpustate->DE.b.l); break; /* ANA E */
+ case 0xa4: M_ANA(cpustate->HL.b.h); break; /* ANA H */
+ case 0xa5: M_ANA(cpustate->HL.b.l); break; /* ANA L */
+ case 0xa6: cpustate->WZ.b.l = RM(cpustate, cpustate->HL.d); M_ANA(cpustate->WZ.b.l); break; /* ANA M */
+ case 0xa7: M_ANA(cpustate->AF.b.h); break; /* ANA A */
+
+ case 0xa8: M_XRA(cpustate->BC.b.h); break; /* XRA B */
+ case 0xa9: M_XRA(cpustate->BC.b.l); break; /* XRA C */
+ case 0xaa: M_XRA(cpustate->DE.b.h); break; /* XRA D */
+ case 0xab: M_XRA(cpustate->DE.b.l); break; /* XRA E */
+ case 0xac: M_XRA(cpustate->HL.b.h); break; /* XRA H */
+ case 0xad: M_XRA(cpustate->HL.b.l); break; /* XRA L */
+ case 0xae: cpustate->WZ.b.l = RM(cpustate, cpustate->HL.d); M_XRA(cpustate->WZ.b.l); break; /* XRA M */
+ case 0xaf: M_XRA(cpustate->AF.b.h); break; /* XRA A */
+
+ case 0xb0: M_ORA(cpustate->BC.b.h); break; /* ORA B */
+ case 0xb1: M_ORA(cpustate->BC.b.l); break; /* ORA C */
+ case 0xb2: M_ORA(cpustate->DE.b.h); break; /* ORA D */
+ case 0xb3: M_ORA(cpustate->DE.b.l); break; /* ORA E */
+ case 0xb4: M_ORA(cpustate->HL.b.h); break; /* ORA H */
+ case 0xb5: M_ORA(cpustate->HL.b.l); break; /* ORA L */
+ case 0xb6: cpustate->WZ.b.l = RM(cpustate, cpustate->HL.d); M_ORA(cpustate->WZ.b.l); break; /* ORA M */
+ case 0xb7: M_ORA(cpustate->AF.b.h); break; /* ORA A */
+
+ case 0xb8: M_CMP(cpustate->BC.b.h); break; /* CMP B */
+ case 0xb9: M_CMP(cpustate->BC.b.l); break; /* CMP C */
+ case 0xba: M_CMP(cpustate->DE.b.h); break; /* CMP D */
+ case 0xbb: M_CMP(cpustate->DE.b.l); break; /* CMP E */
+ case 0xbc: M_CMP(cpustate->HL.b.h); break; /* CMP H */
+ case 0xbd: M_CMP(cpustate->HL.b.l); break; /* CMP L */
+ case 0xbe: cpustate->WZ.b.l = RM(cpustate, cpustate->HL.d); M_CMP(cpustate->WZ.b.l); break; /* CMP M */
+ case 0xbf: M_CMP(cpustate->AF.b.h); break; /* CMP A */
+
+ case 0xc0: M_RET( !(cpustate->AF.b.l & ZF) ); break; /* RNZ */
+ case 0xc1: M_POP(BC); break; /* POP B */
+ case 0xc2: M_JMP( !(cpustate->AF.b.l & ZF) ); break; /* JNZ nnnn */
+ case 0xc3: M_JMP(1); break; /* JMP nnnn */
+ case 0xc4: M_CALL( !(cpustate->AF.b.l & ZF) ); break; /* CNZ nnnn */
+ case 0xc5: M_PUSH(BC); break; /* PUSH B */
+ case 0xc6: cpustate->WZ.b.l = ARG(cpustate); M_ADD(cpustate->WZ.b.l); break; /* ADI nn */
+ case 0xc7: M_RST(0); break; /* RST 0 */
+
+ case 0xc8: M_RET( cpustate->AF.b.l & ZF ); break; /* RZ */
+ case 0xc9: M_POP(PC); break; /* RET */
+ case 0xca: M_JMP( cpustate->AF.b.l & ZF ); break; /* JZ nnnn */
+ case 0xcb: if (IS_8085(cpustate)) { /* RST V */
+ if (cpustate->AF.b.l & VF) { M_RST(8); }
+ else cpustate->icount += 6; // RST not taken
+ } else { M_JMP(1); } /* JMP nnnn undocumented */
+ break;
+ case 0xcc: M_CALL( cpustate->AF.b.l & ZF ); break; /* CZ nnnn */
+ case 0xcd: M_CALL(1); break; /* CALL nnnn */
+ case 0xce: cpustate->WZ.b.l = ARG(cpustate); M_ADC(cpustate->WZ.b.l); break; /* ACI nn */
+ case 0xcf: M_RST(1); break; /* RST 1 */
+
+ case 0xd0: M_RET( !(cpustate->AF.b.l & CF) ); break; /* RNC */
+ case 0xd1: M_POP(DE); break; /* POP D */
+ case 0xd2: M_JMP( !(cpustate->AF.b.l & CF) ); break; /* JNC nnnn */
+ case 0xd3: M_OUT; break; /* OUT nn */
+ case 0xd4: M_CALL( !(cpustate->AF.b.l & CF) ); break; /* CNC nnnn */
+ case 0xd5: M_PUSH(DE); break; /* PUSH D */
+ case 0xd6: cpustate->WZ.b.l = ARG(cpustate); M_SUB(cpustate->WZ.b.l); break; /* SUI nn */
+ case 0xd7: M_RST(2); break; /* RST 2 */
+
+ case 0xd8: M_RET( cpustate->AF.b.l & CF ); break; /* RC */
+ case 0xd9: if (IS_8085(cpustate)) { /* SHLX */
+ cpustate->WZ.w.l = cpustate->DE.w.l;
+ WM(cpustate, cpustate->WZ.d, cpustate->HL.b.l); cpustate->WZ.w.l++;
+ WM(cpustate, cpustate->WZ.d, cpustate->HL.b.h);
+ } else { M_POP(PC); } /* RET undocumented */
+ break;
+ case 0xda: M_JMP( cpustate->AF.b.l & CF ); break; /* JC nnnn */
+ case 0xdb: M_IN; break; /* IN nn */
+ case 0xdc: M_CALL( cpustate->AF.b.l & CF ); break; /* CC nnnn */
+ case 0xdd: if (IS_8085(cpustate)) { M_JMP( !(cpustate->AF.b.l & X5F) ); } /* JNX nnnn */
+ else { M_CALL(1); } /* CALL nnnn undocumented */
+ break;
+ case 0xde: cpustate->WZ.b.l = ARG(cpustate); M_SBB(cpustate->WZ.b.l); break; /* SBI nn */
+ case 0xdf: M_RST(3); break; /* RST 3 */
+
+ case 0xe0: M_RET( !(cpustate->AF.b.l & PF) ); break; /* RPO */
+ case 0xe1: M_POP(HL); break; /* POP H */
+ case 0xe2: M_JMP( !(cpustate->AF.b.l & PF) ); break; /* JPO nnnn */
+ case 0xe3: M_POP(WZ); M_PUSH(HL); /* XTHL */
+ cpustate->HL.d = cpustate->WZ.d;
+ break;
+ case 0xe4: M_CALL( !(cpustate->AF.b.l & PF) ); break; /* CPO nnnn */
+ case 0xe5: M_PUSH(HL); break; /* PUSH H */
+ case 0xe6: cpustate->WZ.b.l = ARG(cpustate); M_ANA(cpustate->WZ.b.l); break; /* ANI nn */
+ case 0xe7: M_RST(4); break; /* RST 4 */
+
+ case 0xe8: M_RET( cpustate->AF.b.l & PF ); break; /* RPE */
+ case 0xe9: cpustate->PC.d = cpustate->HL.w.l; break; /* PCHL */
+ case 0xea: M_JMP( cpustate->AF.b.l & PF ); break; /* JPE nnnn */
+ case 0xeb: cpustate->WZ.d = cpustate->DE.d; /* XCHG */
+ cpustate->DE.d = cpustate->HL.d;
+ cpustate->HL.d = cpustate->WZ.d;
+ break;
+ case 0xec: M_CALL( cpustate->AF.b.l & PF ); break; /* CPE nnnn */
+ case 0xed: if (IS_8085(cpustate)) { /* LHLX */
+ cpustate->WZ.w.l = cpustate->DE.w.l;
+ cpustate->HL.b.l = RM(cpustate, cpustate->WZ.d); cpustate->WZ.w.l++;
+ cpustate->HL.b.h = RM(cpustate, cpustate->WZ.d);
+ } else { M_CALL(1); } /* CALL nnnn undocumented */
+ break;
+ case 0xee: cpustate->WZ.b.l = ARG(cpustate); M_XRA(cpustate->WZ.b.l); break; /* XRI nn */
+ case 0xef: M_RST(5); break; /* RST 5 */
+
+ case 0xf0: M_RET( !(cpustate->AF.b.l&SF) ); break; /* RP */
+ case 0xf1: M_POP(AF); break; /* POP A */
+ case 0xf2: M_JMP( !(cpustate->AF.b.l & SF) ); break; /* JP nnnn */
+ case 0xf3: set_inte(cpustate, 0); break; /* DI */
+ case 0xf4: M_CALL( !(cpustate->AF.b.l & SF) ); break; /* CP nnnn */
+ case 0xf5: M_PUSH(AF); break; /* PUSH A */
+ case 0xf6: cpustate->WZ.b.l = ARG(cpustate); M_ORA(cpustate->WZ.b.l); break; /* ORI nn */
+ case 0xf7: M_RST(6); break; /* RST 6 */
+
+ case 0xf8: M_RET( cpustate->AF.b.l & SF ); break; /* RM */
+ case 0xf9: cpustate->SP.d = cpustate->HL.d; break; /* SPHL */
+ case 0xfa: M_JMP( cpustate->AF.b.l & SF ); break; /* JM nnnn */
+ case 0xfb: set_inte(cpustate, 1); cpustate->after_ei = 2; break; /* EI */
+ case 0xfc: M_CALL( cpustate->AF.b.l & SF ); break; /* CM nnnn */
+ case 0xfd: if (IS_8085(cpustate)) { M_JMP( cpustate->AF.b.l & X5F ); } /* JX nnnn */
+ else { M_CALL(1); } /* CALL nnnn undocumented */
+ break;
+ case 0xfe: cpustate->WZ.b.l = ARG(cpustate); M_CMP(cpustate->WZ.b.l); break; /* CPI nn */
+ case 0xff: M_RST(7); break; /* RST 7 */
+ }
+}
+
+
+/***************************************************************************
+ COMMON EXECUTION
+***************************************************************************/
+
+static CPU_EXECUTE( i808x )
+{
+ i8085_state *cpustate = get_safe_token(device);
+
+ /* check for TRAPs before diving in (can't do others because of after_ei) */
+ if (cpustate->trap_pending || cpustate->after_ei == 0)
+ check_for_interrupts(cpustate);
+
+ do
+ {
+ debugger_instruction_hook(device, cpustate->PC.d);
+
+ /* the instruction after an EI does not take an interrupt, so
+ we cannot check immediately; handle post-EI behavior here */
+ if (cpustate->after_ei != 0 && --cpustate->after_ei == 0)
+ check_for_interrupts(cpustate);
+
+ /* here we go... */
+ execute_one(cpustate, ROP(cpustate));
+
+ } while (cpustate->icount > 0);
+}
+
+
+
+/***************************************************************************
+ CORE INITIALIZATION
+***************************************************************************/
+
+static void init_tables (int type)
+{
+ UINT8 zs;
+ int i, p;
+ for (i = 0; i < 256; i++)
+ {
+ /* cycles */
+ lut_cycles[i] = type?lut_cycles_8085[i]:lut_cycles_8080[i];
+
+ /* flags */
+ zs = 0;
+ if (i==0) zs |= ZF;
+ if (i&128) zs |= SF;
+ p = 0;
+ if (i&1) ++p;
+ if (i&2) ++p;
+ if (i&4) ++p;
+ if (i&8) ++p;
+ if (i&16) ++p;
+ if (i&32) ++p;
+ if (i&64) ++p;
+ if (i&128) ++p;
+ ZS[i] = zs;
+ ZSP[i] = zs | ((p&1) ? 0 : PF);
+ }
+}
+
+
+static void init_808x_common(legacy_cpu_device *device, device_irq_callback irqcallback, int type)
+{
+ i8085_state *cpustate = get_safe_token(device);
+
+ init_tables(type);
+
+ /* set up the state table */
+ {
+ device_state_interface *state;
+ device->interface(state);
+ state->state_add(I8085_PC, "PC", cpustate->PC.w.l);
+ state->state_add(STATE_GENPC, "GENPC", cpustate->PC.w.l).noshow();
+ state->state_add(I8085_SP, "SP", cpustate->SP.w.l);
+ state->state_add(STATE_GENSP, "GENSP", cpustate->SP.w.l).noshow();
+ state->state_add(STATE_GENFLAGS, "GENFLAGS", cpustate->AF.b.l).noshow().formatstr("%8s");
+ state->state_add(I8085_A, "A", cpustate->AF.b.h).noshow();
+ state->state_add(I8085_B, "B", cpustate->BC.b.h).noshow();
+ state->state_add(I8085_C, "C", cpustate->BC.b.l).noshow();
+ state->state_add(I8085_D, "D", cpustate->DE.b.h).noshow();
+ state->state_add(I8085_E, "E", cpustate->DE.b.l).noshow();
+ state->state_add(I8085_F, "F", cpustate->AF.b.l).noshow();
+ state->state_add(I8085_H, "H", cpustate->HL.b.h).noshow();
+ state->state_add(I8085_L, "L", cpustate->HL.b.l).noshow();
+ state->state_add(I8085_AF, "AF", cpustate->AF.w.l);
+ state->state_add(I8085_BC, "BC", cpustate->BC.w.l);
+ state->state_add(I8085_DE, "DE", cpustate->DE.w.l);
+ state->state_add(I8085_HL, "HL", cpustate->HL.w.l);
+ state->state_add(I8085_STATUS, "STATUS", cpustate->STATUS);
+ state->state_add(I8085_SOD, "SOD", cpustate->sod_state).mask(0x1);
+ state->state_add(I8085_SID, "SID", cpustate->ietemp).mask(0x1).callimport().callexport();
+ state->state_add(I8085_INTE, "INTE", cpustate->ietemp).mask(0x1).callimport().callexport();
+ }
+
+ if (device->static_config() != NULL)
+ cpustate->config = *(i8085_config *)device->static_config();
+ cpustate->cputype = type;
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+ cpustate->io = device->space(AS_IO);
+
+ /* resolve callbacks */
+ cpustate->out_status_func.resolve(cpustate->config.out_status_func, *device);
+ cpustate->out_inte_func.resolve(cpustate->config.out_inte_func, *device);
+ cpustate->in_sid_func.resolve(cpustate->config.in_sid_func, *device);
+ cpustate->out_sod_func.resolve(cpustate->config.out_sod_func, *device);
+
+ /* register for state saving */
+ device->save_item(NAME(cpustate->PC.w.l));
+ device->save_item(NAME(cpustate->SP.w.l));
+ device->save_item(NAME(cpustate->AF.w.l));
+ device->save_item(NAME(cpustate->BC.w.l));
+ device->save_item(NAME(cpustate->DE.w.l));
+ device->save_item(NAME(cpustate->HL.w.l));
+ device->save_item(NAME(cpustate->HALT));
+ device->save_item(NAME(cpustate->IM));
+ device->save_item(NAME(cpustate->STATUS));
+ device->save_item(NAME(cpustate->after_ei));
+ device->save_item(NAME(cpustate->nmi_state));
+ device->save_item(NAME(cpustate->irq_state));
+ device->save_item(NAME(cpustate->trap_pending));
+ device->save_item(NAME(cpustate->trap_im_copy));
+ device->save_item(NAME(cpustate->sod_state));
+}
+
+static CPU_INIT( i8080 )
+{
+ init_808x_common(device, irqcallback, CPUTYPE_8080);
+}
+
+static CPU_INIT( i8085 )
+{
+ init_808x_common(device, irqcallback, CPUTYPE_8085);
+}
+
+
+
+/***************************************************************************
+ COMMON RESET
+***************************************************************************/
+
+static CPU_RESET( i808x )
+{
+ i8085_state *cpustate = get_safe_token(device);
+
+ cpustate->PC.d = 0;
+ cpustate->HALT = 0;
+ cpustate->IM &= ~IM_I75;
+ cpustate->IM |= IM_M55 | IM_M65 | IM_M75;
+ cpustate->after_ei = FALSE;
+ cpustate->trap_pending = FALSE;
+ cpustate->trap_im_copy = 0;
+ set_inte(cpustate, 0);
+ set_sod(cpustate, 0);
+}
+
+
+
+/***************************************************************************
+ COMMON STATE IMPORT/EXPORT
+***************************************************************************/
+
+static CPU_IMPORT_STATE( i808x )
+{
+ i8085_state *cpustate = get_safe_token(device);
+
+ switch (entry.index())
+ {
+ case I8085_SID:
+ if (cpustate->ietemp)
+ cpustate->IM |= IM_SID;
+ else
+ cpustate->IM &= ~IM_SID;
+ break;
+
+ case I8085_INTE:
+ if (cpustate->ietemp)
+ cpustate->IM |= IM_IE;
+ else
+ cpustate->IM &= ~IM_IE;
+ break;
+
+ default:
+ fatalerror("CPU_IMPORT_STATE(i808x) called for unexpected value\n");
+ break;
+ }
+}
+
+
+static CPU_EXPORT_STATE( i808x )
+{
+ i8085_state *cpustate = get_safe_token(device);
+
+ switch (entry.index())
+ {
+ case I8085_SID:
+ {
+ int sid = cpustate->in_sid_func();
+
+ cpustate->ietemp = ((cpustate->IM & IM_SID) != 0);
+ cpustate->ietemp = (sid != 0);
+ }
+ break;
+
+ case I8085_INTE:
+ cpustate->ietemp = ((cpustate->IM & IM_IE) != 0);
+ break;
+
+ default:
+ fatalerror("CPU_EXPORT_STATE(i808x) called for unexpected value\n");
+ break;
+ }
+}
+
+static CPU_EXPORT_STRING( i808x )
+{
+ i8085_state *cpustate = get_safe_token(device);
+
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ string.printf("%c%c%c%c%c%c%c%c",
+ cpustate->AF.b.l & 0x80 ? 'S':'.',
+ cpustate->AF.b.l & 0x40 ? 'Z':'.',
+ cpustate->AF.b.l & 0x20 ? 'X':'.', // X5
+ cpustate->AF.b.l & 0x10 ? 'H':'.',
+ cpustate->AF.b.l & 0x08 ? '?':'.',
+ cpustate->AF.b.l & 0x04 ? 'P':'.',
+ cpustate->AF.b.l & 0x02 ? 'V':'.',
+ cpustate->AF.b.l & 0x01 ? 'C':'.');
+ break;
+ }
+}
+
+
+
+/***************************************************************************
+ COMMON SET INFO
+***************************************************************************/
+
+static void i808x_set_irq_line(i8085_state *cpustate, int irqline, int state)
+{
+ int newstate = (state != CLEAR_LINE);
+
+ /* NMI is edge-triggered */
+ if (irqline == INPUT_LINE_NMI)
+ {
+ if (!cpustate->nmi_state && newstate)
+ cpustate->trap_pending = TRUE;
+ cpustate->nmi_state = newstate;
+ }
+
+ /* RST7.5 is edge-triggered */
+ else if (irqline == I8085_RST75_LINE)
+ {
+ if (!cpustate->irq_state[I8085_RST75_LINE] && newstate)
+ cpustate->IM |= IM_I75;
+ cpustate->irq_state[I8085_RST75_LINE] = newstate;
+ }
+
+ /* remaining sources are level triggered */
+ else if (irqline < ARRAY_LENGTH(cpustate->irq_state))
+ cpustate->irq_state[irqline] = state;
+}
+
+
+static CPU_SET_INFO( i808x )
+{
+ i8085_state *cpustate = get_safe_token(device);
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + I8085_INTR_LINE:
+ case CPUINFO_INT_INPUT_STATE + I8085_RST55_LINE:
+ case CPUINFO_INT_INPUT_STATE + I8085_RST65_LINE:
+ case CPUINFO_INT_INPUT_STATE + I8085_RST75_LINE:
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI:
+ i808x_set_irq_line(cpustate, state - CPUINFO_INT_INPUT_STATE, info->i);
+ break;
+ }
+}
+
+
+
+/***************************************************************************
+ 8085/COMMON GET INFO
+***************************************************************************/
+
+CPU_GET_INFO( i8085 )
+{
+ i8085_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(i8085_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 4; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0xff; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 2; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 3; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 4; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 16; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ /* --- the following bits of info are returned as pointers to functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(i808x); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(i8085); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(i808x); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(i808x); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(i8085); break;
+ case CPUINFO_FCT_IMPORT_STATE: info->import_state = CPU_IMPORT_STATE_NAME(i808x); break;
+ case CPUINFO_FCT_EXPORT_STATE: info->export_state = CPU_EXPORT_STATE_NAME(i808x); break;
+ case CPUINFO_FCT_EXPORT_STRING: info->export_string = CPU_EXPORT_STRING_NAME(i808x); break;
+
+ /* --- the following bits of info are returned as pointers --- */
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "8085A"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "MCS-85"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.1"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Juergen Buchmueller, all rights reserved."); break;
+ break;
+ }
+}
+
+
+/***************************************************************************
+ 8080-SPECIFIC GET INFO
+***************************************************************************/
+
+CPU_GET_INFO( i8080 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 1; break;
+
+ /* --- the following bits of info are returned as pointers to functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(i8080); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "8080"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "MCS-80"); break;
+
+ default: CPU_GET_INFO_CALL(i8085); break;
+ }
+}
+
+
+/***************************************************************************
+ 8080A-SPECIFIC GET INFO
+***************************************************************************/
+
+CPU_GET_INFO( i8080a )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 1; break;
+
+ /* --- the following bits of info are returned as pointers to functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(i8080); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "8080A"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "MCS-80"); break;
+
+ default: CPU_GET_INFO_CALL(i8085); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(I8080, i8080);
+DEFINE_LEGACY_CPU_DEVICE(I8080A, i8080a);
+DEFINE_LEGACY_CPU_DEVICE(I8085A, i8085);
diff --git a/trunk/src/emu/cpu/i8085/i8085.h b/trunk/src/emu/cpu/i8085/i8085.h
new file mode 100644
index 00000000000..6c1dadc9448
--- /dev/null
+++ b/trunk/src/emu/cpu/i8085/i8085.h
@@ -0,0 +1,61 @@
+#ifndef __I8085_H__
+#define __I8085_H__
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+enum
+{
+ I8085_PC, I8085_SP, I8085_AF, I8085_BC, I8085_DE, I8085_HL,
+ I8085_A, I8085_B, I8085_C, I8085_D, I8085_E, I8085_F, I8085_H, I8085_L,
+ I8085_STATUS, I8085_SOD, I8085_SID, I8085_INTE,
+ I8085_HALT, I8085_IM,
+
+ I8085_GENPC = STATE_GENPC,
+ I8085_GENSP = STATE_GENSP,
+ I8085_GENPCBASE = STATE_GENPCBASE
+};
+
+#define I8085_INTR_LINE 0
+#define I8085_RST55_LINE 1
+#define I8085_RST65_LINE 2
+#define I8085_RST75_LINE 3
+
+#define I8085_STATUS_INTA 0x01
+#define I8085_STATUS_WO 0x02
+#define I8085_STATUS_STACK 0x04
+#define I8085_STATUS_HLTA 0x08
+#define I8085_STATUS_OUT 0x10
+#define I8085_STATUS_M1 0x20
+#define I8085_STATUS_INP 0x40
+#define I8085_STATUS_MEMR 0x80
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _i8085_config i8085_config;
+struct _i8085_config
+{
+ devcb_write8 out_status_func; /* STATUS changed callback */
+ devcb_write_line out_inte_func; /* INTE changed callback */
+ devcb_read_line in_sid_func; /* SID changed callback (8085A only) */
+ devcb_write_line out_sod_func; /* SOD changed callback (8085A only) */
+};
+#define I8085_CONFIG(name) const i8085_config (name) =
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+DECLARE_LEGACY_CPU_DEVICE(I8080, i8080);
+DECLARE_LEGACY_CPU_DEVICE(I8080A, i8080a);
+DECLARE_LEGACY_CPU_DEVICE(I8085A, i8085);
+
+CPU_DISASSEMBLE( i8085 );
+
+#define i8085_set_sid(cpu, sid) cpu_set_reg(cpu, I8085_SID, sid)
+
+#endif
diff --git a/trunk/src/emu/cpu/i8085/i8085cpu.h b/trunk/src/emu/cpu/i8085/i8085cpu.h
new file mode 100644
index 00000000000..a581924b578
--- /dev/null
+++ b/trunk/src/emu/cpu/i8085/i8085cpu.h
@@ -0,0 +1,188 @@
+/*******************************************************
+ *
+ * Portable (hopefully ;-) 8085A emulator
+ *
+ * Written by J. Buchmueller for use with MAME
+ *
+ * Partially based on Z80Em by Marcel De Kogel
+ *
+ * CPU related macros
+ *
+ *******************************************************/
+
+
+#define SF 0x80
+#define ZF 0x40
+#define X5F 0x20
+#define HF 0x10
+#define X3F 0x08
+#define PF 0x04
+#define VF 0x02
+#define CF 0x01
+
+#define IM_SID 0x80
+#define IM_I75 0x40
+#define IM_I65 0x20
+#define IM_I55 0x10
+#define IM_IE 0x08
+#define IM_M75 0x04
+#define IM_M65 0x02
+#define IM_M55 0x01
+
+#define ADDR_TRAP 0x0024
+#define ADDR_RST55 0x002c
+#define ADDR_RST65 0x0034
+#define ADDR_RST75 0x003c
+#define ADDR_INTR 0x0038
+
+
+#define M_MVI(R) R=ARG(cpustate)
+
+/* rotate */
+#define M_RLC { \
+ cpustate->AF.b.h = (cpustate->AF.b.h << 1) | (cpustate->AF.b.h >> 7); \
+ cpustate->AF.b.l = (cpustate->AF.b.l & 0xfe) | (cpustate->AF.b.h & CF); \
+}
+
+#define M_RRC { \
+ cpustate->AF.b.l = (cpustate->AF.b.l & 0xfe) | (cpustate->AF.b.h & CF); \
+ cpustate->AF.b.h = (cpustate->AF.b.h >> 1) | (cpustate->AF.b.h << 7); \
+}
+
+#define M_RAL { \
+ int c = cpustate->AF.b.l&CF; \
+ cpustate->AF.b.l = (cpustate->AF.b.l & 0xfe) | (cpustate->AF.b.h >> 7); \
+ cpustate->AF.b.h = (cpustate->AF.b.h << 1) | c; \
+}
+
+#define M_RAR { \
+ int c = (cpustate->AF.b.l&CF) << 7; \
+ cpustate->AF.b.l = (cpustate->AF.b.l & 0xfe) | (cpustate->AF.b.h & CF); \
+ cpustate->AF.b.h = (cpustate->AF.b.h >> 1) | c; \
+}
+
+/* logical */
+#define M_ORA(R) cpustate->AF.b.h|=R; cpustate->AF.b.l=ZSP[cpustate->AF.b.h]
+#define M_XRA(R) cpustate->AF.b.h^=R; cpustate->AF.b.l=ZSP[cpustate->AF.b.h]
+#define M_ANA(R) {UINT8 hc = ((cpustate->AF.b.h | R)<<1) & HF; cpustate->AF.b.h&=R; cpustate->AF.b.l=ZSP[cpustate->AF.b.h]; if(IS_8085(cpustate)) { cpustate->AF.b.l |= HF; } else {cpustate->AF.b.l |= hc; } }
+
+/* increase / decrease */
+#define M_INR(R) {UINT8 hc = ((R & 0x0f) == 0x0f) ? HF : 0; ++R; cpustate->AF.b.l= (cpustate->AF.b.l & CF ) | ZSP[R] | hc; }
+#define M_DCR(R) {UINT8 hc = ((R & 0x0f) == 0x00) ? HF : 0; --R; cpustate->AF.b.l= (cpustate->AF.b.l & CF ) | ZSP[R] | hc | VF; }
+
+/* arithmetic */
+#define M_ADD(R) { \
+ int q = cpustate->AF.b.h+R; \
+ cpustate->AF.b.l=ZSP[q&255]|((q>>8)&CF)|((cpustate->AF.b.h^q^R)&HF); \
+ cpustate->AF.b.h=q; \
+}
+
+#define M_ADC(R) { \
+ int q = cpustate->AF.b.h+R+(cpustate->AF.b.l&CF); \
+ cpustate->AF.b.l=ZSP[q&255]|((q>>8)&CF)|((cpustate->AF.b.h^q^R)&HF); \
+ cpustate->AF.b.h=q; \
+}
+
+#define M_SUB(R) { \
+ int q = cpustate->AF.b.h-R; \
+ cpustate->AF.b.l=ZSP[q&255]|((q>>8)&CF)|((cpustate->AF.b.h^q^R)&HF)|VF; \
+ cpustate->AF.b.h=q; \
+}
+
+#define M_SBB(R) { \
+ int q = cpustate->AF.b.h-R-(cpustate->AF.b.l&CF); \
+ cpustate->AF.b.l=ZSP[q&255]|((q>>8)&CF)|((cpustate->AF.b.h^q^R)&HF)|VF; \
+ cpustate->AF.b.h=q; \
+}
+
+#define M_CMP(R) { \
+ int q = cpustate->AF.b.h-R; \
+ cpustate->AF.b.l=ZSP[q&255]|((q>>8)&CF)|((cpustate->AF.b.h^q^R)&HF)|VF; \
+}
+
+#define M_DAD(R) { \
+ int q = cpustate->HL.d + cpustate->R.d; \
+ cpustate->AF.b.l = ( cpustate->AF.b.l & ~(HF+CF) ) | \
+ ( ((cpustate->HL.d^q^cpustate->R.d) >> 8) & HF ) | \
+ ( (q>>16) & CF ); \
+ cpustate->HL.w.l = q; \
+}
+
+#define M_DSUB(cpustate) { \
+ int q = cpustate->HL.b.l-cpustate->BC.b.l; \
+ cpustate->AF.b.l=ZS[q&255]|((q>>8)&CF)|VF| \
+ ((cpustate->HL.b.l^q^cpustate->BC.b.l)&HF)| \
+ (((cpustate->BC.b.l^cpustate->HL.b.l)&(cpustate->HL.b.l^q)&SF)>>5); \
+ cpustate->HL.b.l=q; \
+ q = cpustate->HL.b.h-cpustate->BC.b.h-(cpustate->AF.b.l&CF); \
+ cpustate->AF.b.l=ZS[q&255]|((q>>8)&CF)|VF| \
+ ((cpustate->HL.b.h^q^cpustate->BC.b.h)&HF)| \
+ (((cpustate->BC.b.h^cpustate->HL.b.h)&(cpustate->HL.b.h^q)&SF)>>5); \
+ if (cpustate->HL.b.l!=0) cpustate->AF.b.l&=~ZF; \
+}
+
+/* i/o */
+#define M_IN \
+ cpustate->STATUS = 0x42; \
+ cpustate->WZ.d=ARG(cpustate); \
+ cpustate->AF.b.h=cpustate->io->read_byte(cpustate->WZ.d);
+
+#define M_OUT \
+ cpustate->STATUS = 0x10; \
+ cpustate->WZ.d=ARG(cpustate); \
+ cpustate->io->write_byte(cpustate->WZ.d,cpustate->AF.b.h)
+
+/* stack */
+#define M_PUSH(R) { \
+ cpustate->STATUS = 0x04; \
+ cpustate->program->write_byte(--cpustate->SP.w.l, cpustate->R.b.h); \
+ cpustate->program->write_byte(--cpustate->SP.w.l, cpustate->R.b.l); \
+}
+
+#define M_POP(R) { \
+ cpustate->STATUS = 0x86; \
+ cpustate->R.b.l = cpustate->program->read_byte(cpustate->SP.w.l++); \
+ cpustate->R.b.h = cpustate->program->read_byte(cpustate->SP.w.l++); \
+}
+
+/* jumps */
+// On 8085 jump if condition is not satisfied is shorter
+#define M_JMP(cc) { \
+ if (cc) { \
+ cpustate->PC.w.l = ARG16(cpustate); \
+ } else { \
+ cpustate->PC.w.l += 2; \
+ cpustate->icount += (IS_8085(cpustate)) ? 3 : 0; \
+ } \
+}
+
+// On 8085 call if condition is not satisfied is 9 ticks
+#define M_CALL(cc) \
+{ \
+ if (cc) \
+ { \
+ UINT16 a = ARG16(cpustate); \
+ cpustate->icount -= (IS_8085(cpustate)) ? 7 : 6 ; \
+ M_PUSH(PC); \
+ cpustate->PC.d = a; \
+ } else { \
+ cpustate->PC.w.l += 2; \
+ cpustate->icount += (IS_8085(cpustate)) ? 2 : 0; \
+ } \
+}
+
+// conditional RET only
+#define M_RET(cc) \
+{ \
+ if (cc) \
+ { \
+ cpustate->icount -= 6; \
+ M_POP(PC); \
+ } \
+}
+
+#define M_RST(nn) { \
+ M_PUSH(PC); \
+ cpustate->PC.d = 8 * nn; \
+}
+
diff --git a/trunk/src/emu/cpu/i86/ea.h b/trunk/src/emu/cpu/i86/ea.h
new file mode 100644
index 00000000000..acfbf60f5ea
--- /dev/null
+++ b/trunk/src/emu/cpu/i86/ea.h
@@ -0,0 +1,55 @@
+static unsigned EA_000(i8086_state *cpustate) { cpustate->icount-=7; cpustate->eo=(WORD)(cpustate->regs.w[BX]+cpustate->regs.w[SI]); cpustate->ea_seg=DefaultSeg(DS); cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; }
+static unsigned EA_001(i8086_state *cpustate) { cpustate->icount-=8; cpustate->eo=(WORD)(cpustate->regs.w[BX]+cpustate->regs.w[DI]); cpustate->ea_seg=DefaultSeg(DS); cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; }
+static unsigned EA_002(i8086_state *cpustate) { cpustate->icount-=8; cpustate->eo=(WORD)(cpustate->regs.w[BP]+cpustate->regs.w[SI]); cpustate->ea_seg=DefaultSeg(SS); cpustate->ea=DefaultBase(SS)+cpustate->eo; return cpustate->ea; }
+static unsigned EA_003(i8086_state *cpustate) { cpustate->icount-=7; cpustate->eo=(WORD)(cpustate->regs.w[BP]+cpustate->regs.w[DI]); cpustate->ea_seg=DefaultSeg(SS); cpustate->ea=DefaultBase(SS)+cpustate->eo; return cpustate->ea; }
+static unsigned EA_004(i8086_state *cpustate) { cpustate->icount-=5; cpustate->eo=cpustate->regs.w[SI]; cpustate->ea_seg=DefaultSeg(DS); cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; }
+static unsigned EA_005(i8086_state *cpustate) { cpustate->icount-=5; cpustate->eo=cpustate->regs.w[DI]; cpustate->ea_seg=DefaultSeg(DS); cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; }
+static unsigned EA_006(i8086_state *cpustate) { cpustate->icount-=6; cpustate->eo=FETCHOP; cpustate->eo+=FETCHOP<<8; cpustate->ea_seg=DefaultSeg(DS); cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; }
+static unsigned EA_007(i8086_state *cpustate) { cpustate->icount-=5; cpustate->eo=cpustate->regs.w[BX]; cpustate->ea_seg=DefaultSeg(DS); cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; }
+
+static unsigned EA_100(i8086_state *cpustate) { cpustate->icount-=11; cpustate->eo=(WORD)(cpustate->regs.w[BX]+cpustate->regs.w[SI]+(INT8)FETCHOP); cpustate->ea_seg=DefaultSeg(DS); cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; }
+static unsigned EA_101(i8086_state *cpustate) { cpustate->icount-=12; cpustate->eo=(WORD)(cpustate->regs.w[BX]+cpustate->regs.w[DI]+(INT8)FETCHOP); cpustate->ea_seg=DefaultSeg(DS); cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; }
+static unsigned EA_102(i8086_state *cpustate) { cpustate->icount-=12; cpustate->eo=(WORD)(cpustate->regs.w[BP]+cpustate->regs.w[SI]+(INT8)FETCHOP); cpustate->ea_seg=DefaultSeg(SS); cpustate->ea=DefaultBase(SS)+cpustate->eo; return cpustate->ea; }
+static unsigned EA_103(i8086_state *cpustate) { cpustate->icount-=11; cpustate->eo=(WORD)(cpustate->regs.w[BP]+cpustate->regs.w[DI]+(INT8)FETCHOP); cpustate->ea_seg=DefaultSeg(SS); cpustate->ea=DefaultBase(SS)+cpustate->eo; return cpustate->ea; }
+static unsigned EA_104(i8086_state *cpustate) { cpustate->icount-=9; cpustate->eo=(WORD)(cpustate->regs.w[SI]+(INT8)FETCHOP); cpustate->ea_seg=DefaultSeg(DS); cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; }
+static unsigned EA_105(i8086_state *cpustate) { cpustate->icount-=9; cpustate->eo=(WORD)(cpustate->regs.w[DI]+(INT8)FETCHOP); cpustate->ea_seg=DefaultSeg(DS); cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; }
+static unsigned EA_106(i8086_state *cpustate) { cpustate->icount-=9; cpustate->eo=(WORD)(cpustate->regs.w[BP]+(INT8)FETCHOP); cpustate->ea_seg=DefaultSeg(SS); cpustate->ea=DefaultBase(SS)+cpustate->eo; return cpustate->ea; }
+static unsigned EA_107(i8086_state *cpustate) { cpustate->icount-=9; cpustate->eo=(WORD)(cpustate->regs.w[BX]+(INT8)FETCHOP); cpustate->ea_seg=DefaultSeg(DS); cpustate->ea=DefaultBase(DS)+cpustate->eo; return cpustate->ea; }
+
+static unsigned EA_200(i8086_state *cpustate) { cpustate->icount-=11; cpustate->eo=FETCHOP; cpustate->eo+=FETCHOP<<8; cpustate->eo+=cpustate->regs.w[BX]+cpustate->regs.w[SI]; cpustate->ea_seg=DefaultSeg(DS); cpustate->ea=DefaultBase(DS)+(WORD)cpustate->eo; return cpustate->ea; }
+static unsigned EA_201(i8086_state *cpustate) { cpustate->icount-=12; cpustate->eo=FETCHOP; cpustate->eo+=FETCHOP<<8; cpustate->eo+=cpustate->regs.w[BX]+cpustate->regs.w[DI]; cpustate->ea_seg=DefaultSeg(DS); cpustate->ea=DefaultBase(DS)+(WORD)cpustate->eo; return cpustate->ea; }
+static unsigned EA_202(i8086_state *cpustate) { cpustate->icount-=12; cpustate->eo=FETCHOP; cpustate->eo+=FETCHOP<<8; cpustate->eo+=cpustate->regs.w[BP]+cpustate->regs.w[SI]; cpustate->ea_seg=DefaultSeg(SS); cpustate->ea=DefaultBase(SS)+(WORD)cpustate->eo; return cpustate->ea; }
+static unsigned EA_203(i8086_state *cpustate) { cpustate->icount-=11; cpustate->eo=FETCHOP; cpustate->eo+=FETCHOP<<8; cpustate->eo+=cpustate->regs.w[BP]+cpustate->regs.w[DI]; cpustate->ea_seg=DefaultSeg(SS); cpustate->ea=DefaultBase(SS)+(WORD)cpustate->eo; return cpustate->ea; }
+static unsigned EA_204(i8086_state *cpustate) { cpustate->icount-=9; cpustate->eo=FETCHOP; cpustate->eo+=FETCHOP<<8; cpustate->eo+=cpustate->regs.w[SI]; cpustate->ea_seg=DefaultSeg(DS); cpustate->ea=DefaultBase(DS)+(WORD)cpustate->eo; return cpustate->ea; }
+static unsigned EA_205(i8086_state *cpustate) { cpustate->icount-=9; cpustate->eo=FETCHOP; cpustate->eo+=FETCHOP<<8; cpustate->eo+=cpustate->regs.w[DI]; cpustate->ea_seg=DefaultSeg(DS); cpustate->ea=DefaultBase(DS)+(WORD)cpustate->eo; return cpustate->ea; }
+static unsigned EA_206(i8086_state *cpustate) { cpustate->icount-=9; cpustate->eo=FETCHOP; cpustate->eo+=FETCHOP<<8; cpustate->eo+=cpustate->regs.w[BP]; cpustate->ea_seg=DefaultSeg(SS); cpustate->ea=DefaultBase(SS)+(WORD)cpustate->eo; return cpustate->ea; }
+static unsigned EA_207(i8086_state *cpustate) { cpustate->icount-=9; cpustate->eo=FETCHOP; cpustate->eo+=FETCHOP<<8; cpustate->eo+=cpustate->regs.w[BX]; cpustate->ea_seg=DefaultSeg(DS); cpustate->ea=DefaultBase(DS)+(WORD)cpustate->eo; return cpustate->ea; }
+
+static unsigned (*const GetEA[192])(i8086_state *cpustate)={
+ EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007,
+ EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007,
+ EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007,
+ EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007,
+ EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007,
+ EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007,
+ EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007,
+ EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007,
+
+ EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107,
+ EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107,
+ EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107,
+ EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107,
+ EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107,
+ EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107,
+ EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107,
+ EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107,
+
+ EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207,
+ EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207,
+ EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207,
+ EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207,
+ EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207,
+ EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207,
+ EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207,
+ EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207
+};
diff --git a/trunk/src/emu/cpu/i86/host.h b/trunk/src/emu/cpu/i86/host.h
new file mode 100644
index 00000000000..c31cd8b20c1
--- /dev/null
+++ b/trunk/src/emu/cpu/i86/host.h
@@ -0,0 +1,12 @@
+/*****************************************************************************/
+/* host dependent types */
+
+
+/*#define BIGCASE*/
+
+
+typedef UINT8 BOOLEAN;
+
+typedef UINT8 BYTE;
+typedef UINT16 WORD;
+typedef UINT32 DWORD;
diff --git a/trunk/src/emu/cpu/i86/i286.c b/trunk/src/emu/cpu/i86/i286.c
new file mode 100644
index 00000000000..76610820586
--- /dev/null
+++ b/trunk/src/emu/cpu/i86/i286.c
@@ -0,0 +1,540 @@
+/****************************************************************************
+* real mode i286 emulator v1.4 by Fabrice Frances *
+* (initial work based on David Hedley's pcemu) *
+****************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "host.h"
+
+
+#define VERBOSE 0
+#define LOG(x) do { if (VERBOSE) mame_printf_debug x; } while (0)
+
+/* All post-i286 CPUs have a 16MB address space */
+#define AMASK cpustate->amask
+
+
+#define INPUT_LINE_A20 1
+
+#include "i286.h"
+
+
+#include "i86time.c"
+
+/***************************************************************************/
+/* cpu state */
+/***************************************************************************/
+/* I86 registers */
+typedef union
+{ /* eight general registers */
+ UINT16 w[8]; /* viewed as 16 bits registers */
+ UINT8 b[16]; /* or as 8 bit registers */
+} i80286basicregs;
+
+typedef struct _i80286_state i80286_state;
+struct _i80286_state
+{
+ i80286basicregs regs;
+ offs_t fetch_xor;
+ UINT32 amask; /* address mask */
+ UINT32 pc;
+ UINT32 prevpc;
+ UINT16 flags;
+ UINT16 msw;
+ UINT32 base[4];
+ UINT16 sregs[4];
+ UINT16 limit[4];
+ UINT8 rights[4];
+ struct {
+ UINT32 base;
+ UINT16 limit;
+ } gdtr, idtr;
+ struct {
+ UINT16 sel;
+ UINT32 base;
+ UINT16 limit;
+ UINT8 rights;
+ } ldtr, tr;
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ address_space *io;
+ INT32 AuxVal, OverVal, SignVal, ZeroVal, CarryVal, DirVal; /* 0 or non-0 valued flags */
+ UINT8 ParityVal;
+ UINT8 TF, IF; /* 0 or 1 valued flags */
+ UINT8 int_vector;
+ INT8 nmi_state;
+ INT8 irq_state;
+ INT8 test_state;
+ UINT8 rep_in_progress;
+ INT32 extra_cycles; /* extra cycles for interrupts */
+
+ int halted; /* Is the CPU halted ? */
+ int trap_level;
+
+ int icount;
+ char seg_prefix;
+ UINT8 prefix_seg;
+ unsigned ea;
+ UINT16 eo; /* HJB 12/13/98 effective offset of the address (before segment is added) */
+ UINT8 ea_seg; /* effective segment of the address */
+};
+
+INLINE i80286_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == I80286);
+ return (i80286_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+#define INT_IRQ 0x01
+#define NMI_IRQ 0x02
+
+static UINT8 parity_table[256];
+
+static struct i80x86_timing timing;
+
+/***************************************************************************/
+
+#define I80286
+#include "i86priv.h"
+#define PREFIX(fname) i80286##fname
+#define PREFIX86(fname) i80286##fname
+#define PREFIX186(fname) i80286##fname
+#define PREFIX286(fname) i80286##fname
+#define i8086_state i80286_state
+
+#include "ea.h"
+#include "modrm286.h"
+#include "instr86.h"
+#include "instr186.h"
+#include "instr286.h"
+#include "table286.h"
+#include "instr86.c"
+#include "instr186.c"
+#include "instr286.c"
+
+static void i80286_urinit(void)
+{
+ unsigned int i,j,c;
+ static const BREGS reg_name[8]={ AL, CL, DL, BL, AH, CH, DH, BH };
+
+ for (i = 0;i < 256; i++)
+ {
+ for (j = i, c = 0; j > 0; j >>= 1)
+ if (j & 1) c++;
+
+ parity_table[i] = !(c & 1);
+ }
+
+ for (i = 0; i < 256; i++)
+ {
+ Mod_RM.reg.b[i] = reg_name[(i & 0x38) >> 3];
+ Mod_RM.reg.w[i] = (WREGS) ( (i & 0x38) >> 3) ;
+ }
+
+ for (i = 0xc0; i < 0x100; i++)
+ {
+ Mod_RM.RM.w[i] = (WREGS)( i & 7 );
+ Mod_RM.RM.b[i] = (BREGS)reg_name[i & 7];
+ }
+}
+
+static void i80286_set_a20_line(i80286_state *cpustate, int state)
+{
+ cpustate->amask = state ? 0x00ffffff : 0x000fffff;
+}
+
+static CPU_RESET( i80286 )
+{
+ i80286_state *cpustate = get_safe_token(device);
+
+ memset(&cpustate->regs, 0, sizeof(i80286basicregs));
+ cpustate->sregs[CS] = 0xf000;
+ cpustate->base[CS] = 0xff0000;
+ /* temporary, until I have the right reset vector working */
+ cpustate->base[CS] = cpustate->sregs[CS] << 4;
+ cpustate->pc = 0xffff0;
+ cpustate->limit[CS]=cpustate->limit[SS]=cpustate->limit[DS]=cpustate->limit[ES]=0xffff;
+ cpustate->sregs[DS]=cpustate->sregs[SS]=cpustate->sregs[ES]=0;
+ cpustate->base[DS]=cpustate->base[SS]=cpustate->base[ES]=0;
+ cpustate->rights[DS]=cpustate->rights[SS]=cpustate->rights[ES]=0x93;
+ cpustate->rights[CS]=0x9a;
+ cpustate->msw=0xfff0;
+ cpustate->flags=2;
+ ExpandFlags(cpustate->flags);
+ cpustate->idtr.base=0;cpustate->idtr.limit=0x3ff;
+ cpustate->gdtr.base=cpustate->ldtr.base=cpustate->tr.base=0;
+ cpustate->gdtr.limit=cpustate->ldtr.limit=cpustate->tr.limit=0;
+ cpustate->ldtr.rights=cpustate->tr.rights=0;
+ cpustate->ldtr.sel=cpustate->tr.sel=0;
+ cpustate->rep_in_progress = FALSE;
+ cpustate->seg_prefix = FALSE;
+
+ CHANGE_PC(cpustate->pc);
+
+ cpustate->halted = 0;
+}
+
+/****************************************************************************/
+
+/* ASG 971222 -- added these interface functions */
+
+static void set_irq_line(i80286_state *cpustate, int irqline, int state)
+{
+ if (state != CLEAR_LINE && cpustate->halted)
+ {
+ cpustate->halted = 0;
+ }
+ try
+ {
+ if (irqline == INPUT_LINE_NMI)
+ {
+ if (cpustate->nmi_state == state)
+ return;
+ cpustate->nmi_state = state;
+
+ /* on a rising edge, signal the NMI */
+ if (state != CLEAR_LINE)
+ i80286_interrupt_descriptor(cpustate, I8086_NMI_INT_VECTOR, 2, -1);
+ }
+ else
+ {
+ cpustate->irq_state = state;
+
+ /* if the IF is set, signal an interrupt */
+ if (state != CLEAR_LINE && cpustate->IF)
+ i80286_interrupt_descriptor(cpustate, (*cpustate->irq_callback)(cpustate->device, 0), 2, -1);
+
+ }
+ }
+ catch (UINT32 e)
+ {
+ i80286_trap2(cpustate, e);
+ }
+}
+
+static CPU_EXECUTE( i80286 )
+{
+ i80286_state *cpustate = get_safe_token(device);
+
+ if (cpustate->halted)
+ {
+ cpustate->icount = 0;
+ return;
+ }
+
+ /* copy over the cycle counts if they're not correct */
+ if (timing.id != 80286)
+ timing = i80286_cycles;
+
+ /* adjust for any interrupts that came in */
+ cpustate->icount -= cpustate->extra_cycles;
+ cpustate->extra_cycles = 0;
+
+ /* run until we're out */
+ while(cpustate->icount>0)
+ {
+ LOG(("[%04x:%04x]=%02x\tF:%04x\tAX=%04x\tBX=%04x\tCX=%04x\tDX=%04x %d%d%d%d%d%d%d%d%d\n",cpustate->sregs[CS],cpustate->pc - cpustate->base[CS],ReadByte(cpustate->pc),cpustate->flags,cpustate->regs.w[AX],cpustate->regs.w[BX],cpustate->regs.w[CX],cpustate->regs.w[DX], cpustate->AuxVal?1:0, cpustate->OverVal?1:0, cpustate->SignVal?1:0, cpustate->ZeroVal?1:0, cpustate->CarryVal?1:0, cpustate->ParityVal?1:0,cpustate->TF, cpustate->IF, cpustate->DirVal<0?1:0));
+ debugger_instruction_hook(device, cpustate->pc);
+
+ cpustate->seg_prefix=FALSE;
+ try
+ {
+ if (PM && ((cpustate->pc-cpustate->base[CS]) > cpustate->limit[CS]))
+ throw TRAP(GENERAL_PROTECTION_FAULT, cpustate->sregs[CS] & ~3);
+ cpustate->prevpc = cpustate->pc;
+
+ TABLE286 // call instruction
+ }
+ catch (UINT32 e)
+ {
+ i80286_trap2(cpustate,e);
+ }
+ }
+
+ /* adjust for any interrupts that came in */
+ cpustate->icount -= cpustate->extra_cycles;
+ cpustate->extra_cycles = 0;
+}
+
+extern int i386_dasm_one(char *buffer, UINT32 eip, const UINT8 *oprom, int mode);
+
+static CPU_DISASSEMBLE( i80286 )
+{
+ return i386_dasm_one(buffer, pc, oprom, 2);
+}
+
+static CPU_INIT( i80286 )
+{
+ i80286_state *cpustate = get_safe_token(device);
+
+ device->save_item(NAME(cpustate->regs.w));
+ device->save_item(NAME(cpustate->amask));
+ device->save_item(NAME(cpustate->pc));
+ device->save_item(NAME(cpustate->prevpc));
+ device->save_item(NAME(cpustate->msw));
+ device->save_item(NAME(cpustate->base));
+ device->save_item(NAME(cpustate->sregs));
+ device->save_item(NAME(cpustate->limit));
+ device->save_item(NAME(cpustate->rights));
+ device->save_item(NAME(cpustate->gdtr.base));
+ device->save_item(NAME(cpustate->gdtr.limit));
+ device->save_item(NAME(cpustate->idtr.base));
+ device->save_item(NAME(cpustate->idtr.limit));
+ device->save_item(NAME(cpustate->ldtr.sel));
+ device->save_item(NAME(cpustate->ldtr.base));
+ device->save_item(NAME(cpustate->ldtr.limit));
+ device->save_item(NAME(cpustate->ldtr.rights));
+ device->save_item(NAME(cpustate->tr.sel));
+ device->save_item(NAME(cpustate->tr.base));
+ device->save_item(NAME(cpustate->tr.limit));
+ device->save_item(NAME(cpustate->tr.rights));
+ device->save_item(NAME(cpustate->AuxVal));
+ device->save_item(NAME(cpustate->OverVal));
+ device->save_item(NAME(cpustate->SignVal));
+ device->save_item(NAME(cpustate->ZeroVal));
+ device->save_item(NAME(cpustate->CarryVal));
+ device->save_item(NAME(cpustate->DirVal));
+ device->save_item(NAME(cpustate->ParityVal));
+ device->save_item(NAME(cpustate->TF));
+ device->save_item(NAME(cpustate->IF));
+ device->save_item(NAME(cpustate->int_vector));
+ device->save_item(NAME(cpustate->nmi_state));
+ device->save_item(NAME(cpustate->irq_state));
+ device->save_item(NAME(cpustate->extra_cycles));
+ device->save_item(NAME(cpustate->rep_in_progress));
+
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->io = device->space(AS_IO);
+ cpustate->direct = &cpustate->program->direct();
+
+ /* If a reset parameter is given, take it as pointer to an address mask */
+ if( device->static_config() )
+ cpustate->amask = *(unsigned*)device->static_config();
+ else
+ cpustate->amask = 0x00ffff;
+
+ cpustate->fetch_xor = BYTE_XOR_LE(0);
+
+ i80286_urinit();
+}
+
+
+
+
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( i80286 )
+{
+ i80286_state *cpustate = get_safe_token(device);
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + 0: set_irq_line(cpustate, 0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: set_irq_line(cpustate, INPUT_LINE_NMI, info->i); break;
+
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_A20: i80286_set_a20_line(cpustate, info->i); break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + I80286_PC:
+ if (PM)
+ {
+ /* protected mode NYI */
+ }
+ else
+ {
+ if (info->i - cpustate->base[CS] >= 0x10000)
+ {
+ cpustate->base[CS] = info->i & 0xffff0;
+ cpustate->sregs[CS] = cpustate->base[CS] >> 4;
+ }
+ cpustate->pc = info->i;
+ }
+ break;
+
+ case CPUINFO_INT_REGISTER + I80286_IP: cpustate->pc = cpustate->base[CS] + info->i; break;
+ case CPUINFO_INT_SP:
+ if (PM)
+ {
+ /* protected mode NYI */
+ }
+ else
+ {
+ if (info->i - cpustate->base[SS] < 0x10000)
+ {
+ cpustate->regs.w[SP] = info->i - cpustate->base[SS];
+ }
+ else
+ {
+ cpustate->base[SS] = info->i & 0xffff0;
+ cpustate->sregs[SS] = cpustate->base[SS] >> 4;
+ cpustate->regs.w[SP] = info->i & 0x0000f;
+ }
+ }
+ break;
+
+ case CPUINFO_INT_REGISTER + I80286_SP: cpustate->regs.w[SP] = info->i; break;
+ case CPUINFO_INT_REGISTER + I80286_FLAGS: cpustate->flags = info->i; ExpandFlags(info->i); break;
+ case CPUINFO_INT_REGISTER + I80286_AX: cpustate->regs.w[AX] = info->i; break;
+ case CPUINFO_INT_REGISTER + I80286_CX: cpustate->regs.w[CX] = info->i; break;
+ case CPUINFO_INT_REGISTER + I80286_DX: cpustate->regs.w[DX] = info->i; break;
+ case CPUINFO_INT_REGISTER + I80286_BX: cpustate->regs.w[BX] = info->i; break;
+ case CPUINFO_INT_REGISTER + I80286_BP: cpustate->regs.w[BP] = info->i; break;
+ case CPUINFO_INT_REGISTER + I80286_SI: cpustate->regs.w[SI] = info->i; break;
+ case CPUINFO_INT_REGISTER + I80286_DI: cpustate->regs.w[DI] = info->i; break;
+ case CPUINFO_INT_REGISTER + I80286_ES: cpustate->sregs[ES] = info->i; cpustate->base[ES] = SegBase(ES); break;
+ case CPUINFO_INT_REGISTER + I80286_CS: cpustate->sregs[CS] = info->i; cpustate->base[CS] = SegBase(CS); break;
+ case CPUINFO_INT_REGISTER + I80286_SS: cpustate->sregs[SS] = info->i; cpustate->base[SS] = SegBase(SS); break;
+ case CPUINFO_INT_REGISTER + I80286_DS: cpustate->sregs[DS] = info->i; cpustate->base[DS] = SegBase(DS); break;
+ case CPUINFO_INT_REGISTER + I80286_VECTOR: cpustate->int_vector = info->i; break;
+ }
+}
+
+
+
+/****************************************************************************
+ * Generic get_info
+ ****************************************************************************/
+
+CPU_GET_INFO( i80286 )
+{
+ i80286_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(i80286_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 1; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0xff; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 10; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 50; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 24; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_INPUT_STATE + 0: info->i = cpustate->irq_state; break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: info->i = cpustate->nmi_state; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = cpustate->prevpc; break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + I80286_PC: info->i = cpustate->pc; break;
+ case CPUINFO_INT_REGISTER + I80286_IP: info->i = cpustate->pc - cpustate->base[CS]; break;
+ case CPUINFO_INT_SP: info->i = cpustate->base[SS] + cpustate->regs.w[SP]; break;
+ case CPUINFO_INT_REGISTER + I80286_SP: info->i = cpustate->regs.w[SP]; break;
+ case CPUINFO_INT_REGISTER + I80286_FLAGS: cpustate->flags = CompressFlags(); info->i = cpustate->flags; break;
+ case CPUINFO_INT_REGISTER + I80286_AX: info->i = cpustate->regs.w[AX]; break;
+ case CPUINFO_INT_REGISTER + I80286_CX: info->i = cpustate->regs.w[CX]; break;
+ case CPUINFO_INT_REGISTER + I80286_DX: info->i = cpustate->regs.w[DX]; break;
+ case CPUINFO_INT_REGISTER + I80286_BX: info->i = cpustate->regs.w[BX]; break;
+ case CPUINFO_INT_REGISTER + I80286_BP: info->i = cpustate->regs.w[BP]; break;
+ case CPUINFO_INT_REGISTER + I80286_SI: info->i = cpustate->regs.w[SI]; break;
+ case CPUINFO_INT_REGISTER + I80286_DI: info->i = cpustate->regs.w[DI]; break;
+ case CPUINFO_INT_REGISTER + I80286_ES: info->i = cpustate->sregs[ES]; break;
+ case CPUINFO_INT_REGISTER + I80286_CS: info->i = cpustate->sregs[CS]; break;
+ case CPUINFO_INT_REGISTER + I80286_SS: info->i = cpustate->sregs[SS]; break;
+ case CPUINFO_INT_REGISTER + I80286_DS: info->i = cpustate->sregs[DS]; break;
+ case CPUINFO_INT_REGISTER + I80286_VECTOR: info->i = cpustate->int_vector; break;
+ case CPUINFO_INT_REGISTER + I80286_MSW: info->i = cpustate->msw; break;
+ case CPUINFO_INT_REGISTER + I80286_GDTR_BASE: info->i = cpustate->gdtr.base; break;
+ case CPUINFO_INT_REGISTER + I80286_GDTR_LIMIT: info->i = cpustate->gdtr.limit; break;
+ case CPUINFO_INT_REGISTER + I80286_IDTR_BASE: info->i = cpustate->idtr.base; break;
+ case CPUINFO_INT_REGISTER + I80286_IDTR_LIMIT: info->i = cpustate->idtr.limit; break;
+ case CPUINFO_INT_REGISTER + I80286_LDTR_BASE: info->i = cpustate->ldtr.base; break;
+ case CPUINFO_INT_REGISTER + I80286_LDTR_LIMIT: info->i = cpustate->ldtr.limit; break;
+ case CPUINFO_INT_REGISTER + I80286_TR_BASE: info->i = cpustate->tr.base; break;
+ case CPUINFO_INT_REGISTER + I80286_TR_LIMIT: info->i = cpustate->tr.limit; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(i80286); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(i80286); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(i80286); break;
+ case CPUINFO_FCT_EXIT: info->exit = NULL; break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(i80286); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(i80286); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "80286"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Intel 80286"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.4"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Real mode i286 emulator v1.4 by Fabrice Frances\n(initial work cpustate->based on David Hedley's pcemu)"); break;
+
+ case CPUINFO_STR_FLAGS:
+ cpustate->flags = CompressFlags();
+ sprintf(info->s, "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c",
+ cpustate->flags & 0x8000 ? '0' : '.',
+ cpustate->flags & 0x4000 ? 'N' : '.',
+ cpustate->flags & 0x2000 ? 'I' : '.',
+ cpustate->flags & 0x1000 ? 'I' : '.',
+ cpustate->flags & 0x0800 ? 'O' : '.',
+ cpustate->flags & 0x0400 ? 'D' : '.',
+ cpustate->flags & 0x0200 ? 'I' : '.',
+ cpustate->flags & 0x0100 ? 'T' : '.',
+ cpustate->flags & 0x0080 ? 'S' : '.',
+ cpustate->flags & 0x0040 ? 'Z' : '.',
+ cpustate->flags & 0x0020 ? '0' : '.',
+ cpustate->flags & 0x0010 ? 'A' : '.',
+ cpustate->flags & 0x0008 ? '0' : '.',
+ cpustate->flags & 0x0004 ? 'P' : '.',
+ cpustate->flags & 0x0002 ? '1' : '.',
+ cpustate->flags & 0x0001 ? 'C' : '.');
+ break;
+
+ case CPUINFO_STR_REGISTER + I80286_PC: sprintf(info->s, "PC:%06X", cpustate->pc); break;
+ case CPUINFO_STR_REGISTER + I80286_IP: sprintf(info->s, "IP: %04X", cpustate->pc - cpustate->base[CS]); break;
+ case CPUINFO_STR_REGISTER + I80286_SP: sprintf(info->s, "SP: %04X", cpustate->regs.w[SP]); break;
+ case CPUINFO_STR_REGISTER + I80286_FLAGS: sprintf(info->s, "F:%04X", cpustate->flags); break;
+ case CPUINFO_STR_REGISTER + I80286_AX: sprintf(info->s, "AX:%04X", cpustate->regs.w[AX]); break;
+ case CPUINFO_STR_REGISTER + I80286_CX: sprintf(info->s, "CX:%04X", cpustate->regs.w[CX]); break;
+ case CPUINFO_STR_REGISTER + I80286_DX: sprintf(info->s, "DX:%04X", cpustate->regs.w[DX]); break;
+ case CPUINFO_STR_REGISTER + I80286_BX: sprintf(info->s, "BX:%04X", cpustate->regs.w[BX]); break;
+ case CPUINFO_STR_REGISTER + I80286_BP: sprintf(info->s, "BP:%04X", cpustate->regs.w[BP]); break;
+ case CPUINFO_STR_REGISTER + I80286_SI: sprintf(info->s, "SI: %04X", cpustate->regs.w[SI]); break;
+ case CPUINFO_STR_REGISTER + I80286_DI: sprintf(info->s, "DI: %04X", cpustate->regs.w[DI]); break;
+ case CPUINFO_STR_REGISTER + I80286_CS: sprintf(info->s, "CS: %04X %02X", cpustate->sregs[CS], cpustate->rights[CS]); break;
+ case CPUINFO_STR_REGISTER + I80286_CS_2: sprintf(info->s, "CSDESC: %06X %04X", cpustate->base[CS], cpustate->limit[CS]); break;
+ case CPUINFO_STR_REGISTER + I80286_SS: sprintf(info->s, "SS: %04X %02X", cpustate->sregs[SS], cpustate->rights[SS]); break;
+ case CPUINFO_STR_REGISTER + I80286_SS_2: sprintf(info->s, "SSDESC: %06X %04X", cpustate->base[SS], cpustate->limit[SS]); break;
+ case CPUINFO_STR_REGISTER + I80286_DS: sprintf(info->s, "DS: %04X %02X", cpustate->sregs[DS], cpustate->rights[DS]); break;
+ case CPUINFO_STR_REGISTER + I80286_DS_2: sprintf(info->s, "DSDESC: %06X %04X", cpustate->base[DS], cpustate->limit[DS]); break;
+ case CPUINFO_STR_REGISTER + I80286_ES: sprintf(info->s, "ES: %04X %02X", cpustate->sregs[ES], cpustate->rights[ES]); break;
+ case CPUINFO_STR_REGISTER + I80286_ES_2: sprintf(info->s, "ESDESC: %06X %04X", cpustate->base[ES], cpustate->limit[ES]); break;
+ case CPUINFO_STR_REGISTER + I80286_VECTOR: sprintf(info->s, "V:%02X", cpustate->int_vector); break;
+ case CPUINFO_STR_REGISTER + I80286_MSW: sprintf(info->s, "MSW:%04X", cpustate->msw); break;
+ case CPUINFO_STR_REGISTER + I80286_TR_BASE: sprintf(info->s, "TRBASE: %06X", cpustate->tr.base); break;
+ case CPUINFO_STR_REGISTER + I80286_TR_LIMIT: sprintf(info->s, "TRLIM: %04X", cpustate->tr.limit); break;
+ case CPUINFO_STR_REGISTER + I80286_GDTR_BASE: sprintf(info->s, "GDTRBASE: %06X", cpustate->gdtr.base); break;
+ case CPUINFO_STR_REGISTER + I80286_GDTR_LIMIT: sprintf(info->s, "GDTRLIM: %04X", cpustate->gdtr.limit); break;
+ case CPUINFO_STR_REGISTER + I80286_LDTR_BASE: sprintf(info->s, "LDTR: %04X %02X", cpustate->ldtr.sel, cpustate->ldtr.rights); break;
+ case CPUINFO_STR_REGISTER + I80286_LDTR_LIMIT: sprintf(info->s, "LDTRDESC: %06X %04X", cpustate->ldtr.base, cpustate->ldtr.limit); break;
+ case CPUINFO_STR_REGISTER + I80286_IDTR_BASE: sprintf(info->s, "IDTRBASE: %06X", cpustate->idtr.base); break;
+ case CPUINFO_STR_REGISTER + I80286_IDTR_LIMIT: sprintf(info->s, "IDTRLIM: %04X", cpustate->idtr.limit); break;
+ }
+}
+
+#undef I80286
+DEFINE_LEGACY_CPU_DEVICE(I80286, i80286);
diff --git a/trunk/src/emu/cpu/i86/i286.h b/trunk/src/emu/cpu/i86/i286.h
new file mode 100644
index 00000000000..d46cf46eb8b
--- /dev/null
+++ b/trunk/src/emu/cpu/i86/i286.h
@@ -0,0 +1,50 @@
+/* ASG 971222 -- rewrote this interface */
+#pragma once
+
+#ifndef __I286INTF_H__
+#define __I286INTF_H__
+
+#include "i86.h"
+
+enum
+{
+ I80286_PC=0,
+ I80286_IP,
+ I80286_AX,
+ I80286_CX,
+ I80286_DX,
+ I80286_BX,
+ I80286_SP,
+ I80286_BP,
+ I80286_SI,
+ I80286_DI,
+ I80286_FLAGS,
+ I80286_ES,
+ I80286_CS,
+ I80286_SS,
+ I80286_DS,
+ I80286_ES_2,
+ I80286_CS_2,
+ I80286_SS_2,
+ I80286_DS_2,
+ I80286_MSW,
+ I80286_GDTR_BASE,
+ I80286_IDTR_BASE,
+ I80286_LDTR_BASE,
+ I80286_TR_BASE,
+ I80286_GDTR_LIMIT,
+ I80286_IDTR_LIMIT,
+ I80286_LDTR_LIMIT,
+ I80286_TR_LIMIT,
+ I80286_VECTOR,
+ I80286_PENDING,
+ I80286_NMI_STATE,
+ I80286_IRQ_STATE
+};
+
+#define TRAP(fault, code) (UINT32)(((fault&0xffff)<<16)|(code&0xffff))
+
+/* Public functions */
+DECLARE_LEGACY_CPU_DEVICE(I80286, i80286);
+
+#endif /* __I286INTF_H__ */
diff --git a/trunk/src/emu/cpu/i86/i86.c b/trunk/src/emu/cpu/i86/i86.c
new file mode 100644
index 00000000000..341454b28d9
--- /dev/null
+++ b/trunk/src/emu/cpu/i86/i86.c
@@ -0,0 +1,698 @@
+/****************************************************************************
+* real mode i286 emulator v1.4 by Fabrice Frances *
+* (initial work based on David Hedley's pcemu) *
+****************************************************************************/
+/* 26.March 2000 PeT changed set_irq_line */
+
+#include "emu.h"
+#include "debugger.h"
+
+#include "host.h"
+#include "i86priv.h"
+#include "i86.h"
+
+extern int i386_dasm_one(char *buffer, UINT32 eip, const UINT8 *oprom, int mode);
+
+#define VERBOSE 0
+#define LOG(x) do { if (VERBOSE) mame_printf_debug x; } while (0)
+
+
+/* All pre-i286 CPUs have a 1MB address space */
+#define AMASK 0xfffff
+
+
+/* I86 registers */
+typedef union
+{ /* eight general registers */
+ UINT16 w[8]; /* viewed as 16 bits registers */
+ UINT8 b[16]; /* or as 8 bit registers */
+}
+i8086basicregs;
+
+typedef struct _i8086_state i8086_state;
+struct _i8086_state
+{
+ i8086basicregs regs;
+ offs_t fetch_xor;
+ UINT32 pc;
+ UINT32 prevpc;
+ UINT32 base[4];
+ UINT16 sregs[4];
+ UINT16 flags;
+ device_irq_callback irq_callback;
+ INT32 AuxVal, OverVal, SignVal, ZeroVal, CarryVal, DirVal; /* 0 or non-0 valued flags */
+ UINT8 ParityVal;
+ UINT8 TF, IF; /* 0 or 1 valued flags */
+ UINT8 MF; /* V30 mode flag */
+ UINT8 int_vector;
+ INT8 nmi_state;
+ INT8 irq_state;
+ INT8 test_state;
+ UINT8 rep_in_progress;
+ INT32 extra_cycles; /* extra cycles for interrupts */
+
+ int halted; /* Is the CPU halted ? */
+
+ UINT16 ip;
+ UINT32 sp;
+
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ address_space *io;
+ int icount;
+
+ char seg_prefix; /* prefix segment indicator */
+ UINT8 prefix_seg; /* The prefixed segment */
+ unsigned ea;
+ UINT16 eo; /* HJB 12/13/98 effective offset of the address (before segment is added) */
+ UINT8 ea_seg; /* effective segment of the address */
+
+ devcb_resolved_write_line out_tmrout0_func;
+ devcb_resolved_write_line out_tmrout1_func;
+};
+
+INLINE i8086_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == I8086 ||
+ device->type() == I8088 ||
+ device->type() == I80186 ||
+ device->type() == I80188);
+ return (i8086_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+
+#include "i86time.c"
+
+/***************************************************************************/
+/* cpu state */
+/***************************************************************************/
+
+
+static struct i80x86_timing timing;
+
+static UINT8 parity_table[256];
+
+/* The interrupt number of a pending external interrupt pending NMI is 2. */
+/* For INTR interrupts, the level is caught on the bus during an INTA cycle */
+
+#define PREFIX(name) i8086##name
+#define PREFIX86(name) i8086##name
+
+#define I8086
+#include "instr86.h"
+#include "ea.h"
+#include "modrm.h"
+#include "table86.h"
+
+#include "instr86.c"
+#undef I8086
+
+
+/***************************************************************************/
+static void i8086_state_register(device_t *device)
+{
+ i8086_state *cpustate = get_safe_token(device);
+ device->save_item(NAME(cpustate->regs.w));
+ device->save_item(NAME(cpustate->pc));
+ device->save_item(NAME(cpustate->prevpc));
+ device->save_item(NAME(cpustate->base));
+ device->save_item(NAME(cpustate->sregs));
+ device->save_item(NAME(cpustate->flags));
+ device->save_item(NAME(cpustate->AuxVal));
+ device->save_item(NAME(cpustate->OverVal));
+ device->save_item(NAME(cpustate->SignVal));
+ device->save_item(NAME(cpustate->ZeroVal));
+ device->save_item(NAME(cpustate->CarryVal));
+ device->save_item(NAME(cpustate->DirVal));
+ device->save_item(NAME(cpustate->ParityVal));
+ device->save_item(NAME(cpustate->TF));
+ device->save_item(NAME(cpustate->IF));
+ device->save_item(NAME(cpustate->MF));
+ device->save_item(NAME(cpustate->int_vector));
+ device->save_item(NAME(cpustate->nmi_state));
+ device->save_item(NAME(cpustate->irq_state));
+ device->save_item(NAME(cpustate->extra_cycles));
+ device->save_item(NAME(cpustate->halted));
+ device->save_item(NAME(cpustate->test_state)); /* PJB 03/05 */
+ device->save_item(NAME(cpustate->rep_in_progress)); /* PJB 03/05 */
+}
+
+static CPU_INIT( i8086 )
+{
+ i8086_state *cpustate = get_safe_token(device);
+ unsigned int i, j, c;
+ static const BREGS reg_name[8] = {AL, CL, DL, BL, AH, CH, DH, BH};
+ for (i = 0; i < 256; i++)
+ {
+ for (j = i, c = 0; j > 0; j >>= 1)
+ if (j & 1)
+ c++;
+
+ parity_table[i] = !(c & 1);
+ }
+
+ for (i = 0; i < 256; i++)
+ {
+ Mod_RM.reg.b[i] = reg_name[(i & 0x38) >> 3];
+ Mod_RM.reg.w[i] = (WREGS) ((i & 0x38) >> 3);
+ }
+
+ for (i = 0xc0; i < 0x100; i++)
+ {
+ Mod_RM.RM.w[i] = (WREGS) (i & 7);
+ Mod_RM.RM.b[i] = (BREGS) reg_name[i & 7];
+ }
+
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+ cpustate->io = device->space(AS_IO);
+
+ /* set up the state table */
+ {
+ device_state_interface *state;
+ device->interface(state);
+ state->state_add(STATE_GENPC, "GENPC", cpustate->pc).mask(0xfffff).formatstr("%9s").callimport();
+ state->state_add(I8086_IP, "IP", cpustate->ip).callimport().callexport();
+ state->state_add(I8086_FLAGS, "FLAGS", cpustate->flags).callimport().callexport().noshow();
+ state->state_add(STATE_GENFLAGS, "GENFLAGS", cpustate->flags).callimport().callexport().noshow().formatstr("%16s");
+ state->state_add(I8086_AX, "AX", cpustate->regs.w[AX]);
+ state->state_add(I8086_BX, "BX", cpustate->regs.w[BX]);
+ state->state_add(I8086_CX, "CX", cpustate->regs.w[CX]);
+ state->state_add(I8086_DX, "DX", cpustate->regs.w[DX]);
+ state->state_add(I8086_SI, "SI", cpustate->regs.w[SI]);
+ state->state_add(I8086_DI, "DI", cpustate->regs.w[DI]);
+ state->state_add(I8086_BP, "BP", cpustate->regs.w[BP]);
+ state->state_add(I8086_SP, "SP", cpustate->regs.w[SP]);
+ state->state_add(STATE_GENSP, "GENSP", cpustate->sp).mask(0xfffff).formatstr("%9s").callimport().callexport();
+ state->state_add(I8086_AL, "AL", cpustate->regs.b[AL]).noshow();
+ state->state_add(I8086_BL, "BL", cpustate->regs.b[BL]).noshow();
+ state->state_add(I8086_CL, "CL", cpustate->regs.b[CL]).noshow();
+ state->state_add(I8086_DL, "DL", cpustate->regs.b[DL]).noshow();
+ state->state_add(I8086_AH, "AH", cpustate->regs.b[AH]).noshow();
+ state->state_add(I8086_BH, "BH", cpustate->regs.b[BH]).noshow();
+ state->state_add(I8086_CH, "CH", cpustate->regs.b[CH]).noshow();
+ state->state_add(I8086_DH, "DH", cpustate->regs.b[DH]).noshow();
+ state->state_add(I8086_CS, "CS", cpustate->sregs[CS]).callimport();
+ state->state_add(I8086_DS, "DS", cpustate->sregs[DS]).callimport();
+ state->state_add(I8086_ES, "ES", cpustate->sregs[ES]).callimport();
+ state->state_add(I8086_SS, "SS", cpustate->sregs[SS]).callimport();
+ }
+
+ i8086_state_register(device);
+ cpustate->fetch_xor = BYTE_XOR_LE(0);
+}
+
+static CPU_INIT( i8088 )
+{
+ i8086_state *cpustate = get_safe_token(device);
+ CPU_INIT_CALL(i8086);
+ cpustate->fetch_xor = 0;
+}
+
+static CPU_INIT( i80186 )
+{
+ i8086_state *cpustate = get_safe_token(device);
+
+ CPU_INIT_CALL(i8086);
+
+ /* resolve callbacks */
+ i80186_interface *intf = (i80186_interface *) device->static_config();
+
+ if (intf != NULL)
+ {
+ cpustate->out_tmrout0_func.resolve(intf->out_tmrout0_func, *device);
+ cpustate->out_tmrout1_func.resolve(intf->out_tmrout1_func, *device);
+ }
+}
+
+static CPU_RESET( i8086 )
+{
+ i8086_state *cpustate = get_safe_token(device);
+ device_irq_callback save_irqcallback;
+
+ save_irqcallback = cpustate->irq_callback;
+ memset(cpustate, 0, sizeof(*cpustate));
+ cpustate->irq_callback = save_irqcallback;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+ cpustate->io = device->space(AS_IO);
+
+ cpustate->sregs[CS] = 0xffff;
+ cpustate->base[CS] = SegBase(CS);
+ cpustate->pc = 0xffff0 & AMASK;
+ ExpandFlags(cpustate->flags);
+
+ cpustate->halted = 0;
+}
+
+static CPU_EXIT( i8086 )
+{
+ /* nothing to do ? */
+}
+
+/* ASG 971222 -- added these interface functions */
+
+static void set_irq_line(i8086_state *cpustate, int irqline, int state)
+{
+ if (state != CLEAR_LINE && cpustate->halted)
+ {
+ cpustate->halted = 0;
+ }
+
+ if (irqline == INPUT_LINE_NMI)
+ {
+ if (cpustate->nmi_state == state)
+ return;
+ cpustate->nmi_state = state;
+
+ /* on a rising edge, signal the NMI */
+ if (state != CLEAR_LINE)
+ {
+ PREFIX(_interrupt)(cpustate, I8086_NMI_INT_VECTOR);
+ }
+ }
+ else
+ {
+ cpustate->irq_state = state;
+
+ /* if the IF is set, signal an interrupt */
+ if (state != CLEAR_LINE && cpustate->IF)
+ PREFIX(_interrupt)(cpustate, (UINT32)-1);
+ }
+}
+
+static void set_drq_line(i8086_state *cpustate, int irqline, int state)
+{
+ // TODO implement me
+}
+
+static void set_tmrin_line(i8086_state *cpustate, int irqline, int state)
+{
+ // TODO implement me
+}
+
+/* PJB 03/05 */
+static void set_test_line(i8086_state *cpustate, int state)
+{
+ cpustate->test_state = !state;
+}
+
+static CPU_EXECUTE( i8086 )
+{
+ i8086_state *cpustate = get_safe_token(device);
+
+
+ if (cpustate->halted)
+ {
+ cpustate->icount = 0;
+ return;
+ }
+
+ /* copy over the cycle counts if they're not correct */
+ if (timing.id != 8086)
+ timing = i8086_cycles;
+
+ /* adjust for any interrupts that came in */
+ cpustate->icount -= cpustate->extra_cycles;
+ cpustate->extra_cycles = 0;
+
+ /* run until we're out */
+ while (cpustate->icount > 0)
+ {
+ LOG(("[%04x:%04x]=%02x\tF:%04x\tAX=%04x\tBX=%04x\tCX=%04x\tDX=%04x %d%d%d%d%d%d%d%d%d\n",
+ cpustate->sregs[CS], cpustate->pc - cpustate->base[CS], ReadByte(cpustate->pc), cpustate->flags, cpustate->regs.w[AX], cpustate->regs.w[BX], cpustate->regs.w[CX], cpustate->regs.w[DX], cpustate->AuxVal ? 1 : 0, cpustate->OverVal ? 1 : 0,
+ cpustate->SignVal ? 1 : 0, cpustate->ZeroVal ? 1 : 0, cpustate->CarryVal ? 1 : 0, cpustate->ParityVal ? 1 : 0, cpustate->TF, cpustate->IF, cpustate->DirVal < 0 ? 1 : 0));
+ debugger_instruction_hook(device, cpustate->pc);
+
+ cpustate->seg_prefix = FALSE;
+ cpustate->prevpc = cpustate->pc;
+ TABLE86;
+ }
+
+ /* adjust for any interrupts that came in */
+ cpustate->icount -= cpustate->extra_cycles;
+ cpustate->extra_cycles = 0;
+}
+
+
+static CPU_DISASSEMBLE( i8086 )
+{
+ return i386_dasm_one(buffer, pc, oprom, 1);
+}
+
+
+
+#include "i86.h"
+
+#undef PREFIX
+#define PREFIX(name) i80186##name
+#define PREFIX186(name) i80186##name
+
+#define I80186
+#include "instr186.h"
+#include "table186.h"
+
+#include "instr86.c"
+#include "instr186.c"
+#undef I80186
+
+static CPU_EXECUTE( i80186 )
+{
+ i8086_state *cpustate = get_safe_token(device);
+
+ /* copy over the cycle counts if they're not correct */
+ if (timing.id != 80186)
+ timing = i80186_cycles;
+
+ /* adjust for any interrupts that came in */
+ cpustate->icount -= cpustate->extra_cycles;
+ cpustate->extra_cycles = 0;
+
+ /* run until we're out */
+ while (cpustate->icount > 0)
+ {
+ LOG(("[%04x:%04x]=%02x\tAX=%04x\tBX=%04x\tCX=%04x\tDX=%04x\n", cpustate->sregs[CS], cpustate->pc, ReadByte(cpustate->pc), cpustate->regs.w[AX],
+ cpustate->regs.w[BX], cpustate->regs.w[CX], cpustate->regs.w[DX]));
+ debugger_instruction_hook(device, cpustate->pc);
+
+ cpustate->seg_prefix = FALSE;
+ cpustate->prevpc = cpustate->pc;
+ TABLE186;
+ }
+
+ /* adjust for any interrupts that came in */
+ cpustate->icount -= cpustate->extra_cycles;
+ cpustate->extra_cycles = 0;
+}
+
+
+
+
+/**************************************************************************
+ * STATE IMPORT/EXPORT
+ **************************************************************************/
+
+static CPU_IMPORT_STATE( i8086 )
+{
+ i8086_state *cpustate = get_safe_token(device);
+
+ switch (entry.index())
+ {
+ case I8086_GENPC:
+ if (cpustate->pc - cpustate->base[CS] >= 0x10000)
+ {
+ cpustate->base[CS] = cpustate->pc & 0xffff0;
+ cpustate->sregs[CS] = cpustate->base[CS] >> 4;
+ }
+ break;
+
+ case I8086_IP:
+ cpustate->pc = cpustate->base[CS] + cpustate->ip;
+ break;
+
+ case I8086_GENSP:
+ if (cpustate->sp - cpustate->base[SS] >= 0x10000)
+ {
+ cpustate->base[SS] = cpustate->sp & 0xffff0;
+ cpustate->sregs[SS] = cpustate->base[SS] >> 4;
+ }
+ cpustate->regs.w[SP] = cpustate->sp - cpustate->base[SS];
+ break;
+
+ case I8086_FLAGS:
+ case STATE_GENFLAGS:
+ ExpandFlags(cpustate->flags);
+ break;
+
+ case I8086_ES:
+ cpustate->base[ES] = SegBase(ES);
+ break;
+
+ case I8086_CS:
+ cpustate->base[CS] = SegBase(CS);
+ break;
+
+ case I8086_SS:
+ cpustate->base[SS] = SegBase(SS);
+ break;
+
+ case I8086_DS:
+ cpustate->base[DS] = SegBase(DS);
+ break;
+
+ default:
+ fatalerror("CPU_IMPORT_STATE(i8086) called for unexpected value\n");
+ break;
+ }
+}
+
+
+static CPU_EXPORT_STATE( i8086 )
+{
+ i8086_state *cpustate = get_safe_token(device);
+
+ switch (entry.index())
+ {
+ case I8086_IP:
+ cpustate->ip = cpustate->pc - cpustate->base[CS];
+ break;
+
+ case I8086_FLAGS:
+ case STATE_GENFLAGS:
+ cpustate->flags = CompressFlags();
+ break;
+
+ case I8086_GENSP:
+ cpustate->sp = cpustate->base[SS] + cpustate->regs.w[SP];
+ break;
+
+ default:
+ fatalerror("CPU_EXPORT_STATE(i8086) called for unexpected value\n");
+ break;
+ }
+}
+
+
+static CPU_EXPORT_STRING( i8086 )
+{
+ i8086_state *cpustate = get_safe_token(device);
+
+ switch (entry.index())
+ {
+ case I8086_GENPC:
+ string.printf("%04X:%04X", cpustate->sregs[CS] & 0xffff, (cpustate->pc - cpustate->base[CS]) & 0xffff);
+ break;
+
+ case I8086_GENSP:
+ string.printf("%04X:%04X", cpustate->sregs[SS] & 0xffff, cpustate->regs.w[SP] & 0xffff);
+ break;
+
+ case STATE_GENFLAGS:
+ cpustate->flags = CompressFlags();
+ string.printf("%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c",
+ cpustate->flags & 0x8000 ? '1' : '.',
+ cpustate->flags & 0x4000 ? '1' : '.',
+ cpustate->flags & 0x2000 ? '1' : '.',
+ cpustate->flags & 0x1000 ? '1' : '.',
+ cpustate->flags & 0x0800 ? 'O' : '.',
+ cpustate->flags & 0x0400 ? 'D' : '.',
+ cpustate->flags & 0x0200 ? 'I' : '.',
+ cpustate->flags & 0x0100 ? 'T' : '.',
+ cpustate->flags & 0x0080 ? 'S' : '.',
+ cpustate->flags & 0x0040 ? 'Z' : '.',
+ cpustate->flags & 0x0020 ? '0' : '.',
+ cpustate->flags & 0x0010 ? 'A' : '.',
+ cpustate->flags & 0x0008 ? '0' : '.',
+ cpustate->flags & 0x0004 ? 'P' : '.',
+ cpustate->flags & 0x0002 ? '1' : '.',
+ cpustate->flags & 0x0001 ? 'C' : '.');
+ break;
+
+ default:
+ fatalerror("CPU_EXPORT_STRING(i8086) called for unexpected value\n");
+ break;
+ }
+}
+
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( i8086 )
+{
+ i8086_state *cpustate = get_safe_token(device);
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + 0: set_irq_line(cpustate, 0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: set_irq_line(cpustate, INPUT_LINE_NMI, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_TEST: set_test_line(cpustate, info->i); break; /* PJB 03/05 */
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+CPU_GET_INFO( i8086 )
+{
+ i8086_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(i8086_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 1; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0xff; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 8; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 50; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 20; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_INPUT_STATE + 0: info->i = cpustate->irq_state; break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: info->i = cpustate->nmi_state; break;
+
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_TEST: info->i = cpustate->test_state; break; /* PJB 03/05 */
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = cpustate->prevpc; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(i8086); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(i8086); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(i8086); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(i8086); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(i8086); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(i8086); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+ case CPUINFO_FCT_IMPORT_STATE: info->import_state = CPU_IMPORT_STATE_NAME(i8086); break;
+ case CPUINFO_FCT_EXPORT_STATE: info->export_state = CPU_EXPORT_STATE_NAME(i8086); break;
+ case CPUINFO_FCT_EXPORT_STRING: info->export_string = CPU_EXPORT_STRING_NAME(i8086);break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "8086"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Intel 80x86"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.4"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Real mode i286 emulator v1.4 by Fabrice Frances\n(initial work cpustate->based on David Hedley's pcemu)"); break;
+ }
+}
+
+
+/**************************************************************************
+ * CPU-specific get_info/set_info
+ **************************************************************************/
+
+CPU_GET_INFO( i8088 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 8; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(i8088); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "8088"); break;
+
+ default: CPU_GET_INFO_CALL(i8086); break;
+ }
+}
+
+
+/**************************************************************************
+ * CPU-specific get_info/set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( i80186 )
+{
+ i8086_state *cpustate = get_safe_token(device);
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_INT0: set_irq_line(cpustate, 0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_INT1: set_irq_line(cpustate, 1, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_INT2: set_irq_line(cpustate, 2, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_INT3: set_irq_line(cpustate, 3, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_DRQ0: set_drq_line(cpustate, 0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_DRQ1: set_drq_line(cpustate, 1, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_TMRIN0: set_tmrin_line(cpustate, 0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_TMRIN1: set_tmrin_line(cpustate, 1, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: set_irq_line(cpustate, INPUT_LINE_NMI, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_TEST: set_test_line(cpustate, info->i); break; /* PJB 03/05 */
+ }
+}
+
+CPU_GET_INFO( i80186 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 2; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(i80186); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(i80186); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(i80186); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "80186"); break;
+
+ default: CPU_GET_INFO_CALL(i8086); break;
+ }
+}
+
+
+/**************************************************************************
+ * CPU-specific get_info/set_info
+ **************************************************************************/
+
+CPU_GET_INFO( i80188 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 8; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(i8088); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(i80186);break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "80188"); break;
+
+ default: CPU_GET_INFO_CALL(i8086); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(I8086, i8086);
+DEFINE_LEGACY_CPU_DEVICE(I8088, i8088);
+DEFINE_LEGACY_CPU_DEVICE(I80186, i80186);
+DEFINE_LEGACY_CPU_DEVICE(I80188, i80188);
diff --git a/trunk/src/emu/cpu/i86/i86.h b/trunk/src/emu/cpu/i86/i86.h
new file mode 100644
index 00000000000..e8d1fd03738
--- /dev/null
+++ b/trunk/src/emu/cpu/i86/i86.h
@@ -0,0 +1,65 @@
+/* ASG 971222 -- rewrote this interface */
+#pragma once
+
+#ifndef __I86INTF_H__
+#define __I86INTF_H__
+
+
+#define INPUT_LINE_INT0 INPUT_LINE_IRQ0
+#define INPUT_LINE_INT1 INPUT_LINE_IRQ1
+#define INPUT_LINE_INT2 INPUT_LINE_IRQ2
+#define INPUT_LINE_INT3 INPUT_LINE_IRQ3
+#define INPUT_LINE_TEST 20 /* PJB 03/05 */
+#define INPUT_LINE_DRQ0 21
+#define INPUT_LINE_DRQ1 22
+#define INPUT_LINE_TMRIN0 23
+#define INPUT_LINE_TMRIN1 24
+
+
+typedef struct _i80186_interface i80186_interface;
+struct _i80186_interface
+{
+ devcb_write_line out_tmrout0_func;
+ devcb_write_line out_tmrout1_func;
+};
+#define I80186_INTERFACE(name) const i80186_interface (name) =
+
+
+enum
+{
+ I8086_IP,
+ I8086_AX,
+ I8086_CX,
+ I8086_DX,
+ I8086_BX,
+ I8086_SP,
+ I8086_BP,
+ I8086_SI,
+ I8086_DI,
+ I8086_AL,
+ I8086_CL,
+ I8086_DL,
+ I8086_BL,
+ I8086_AH,
+ I8086_CH,
+ I8086_DH,
+ I8086_BH,
+ I8086_FLAGS,
+ I8086_ES,
+ I8086_CS,
+ I8086_SS,
+ I8086_DS,
+ I8086_VECTOR,
+
+ I8086_GENPC = STATE_GENPC,
+ I8086_GENSP = STATE_GENSP,
+ I8086_GENPCBASE = STATE_GENPCBASE
+};
+
+/* Public functions */
+DECLARE_LEGACY_CPU_DEVICE(I8086, i8086);
+DECLARE_LEGACY_CPU_DEVICE(I8088, i8088);
+DECLARE_LEGACY_CPU_DEVICE(I80186, i80186);
+DECLARE_LEGACY_CPU_DEVICE(I80188, i80188);
+
+#endif /* __I86INTF_H__ */
diff --git a/trunk/src/emu/cpu/i86/i86.txt b/trunk/src/emu/cpu/i86/i86.txt
new file mode 100644
index 00000000000..ecf17e0e424
--- /dev/null
+++ b/trunk/src/emu/cpu/i86/i86.txt
@@ -0,0 +1,111 @@
+intel 8086 and compatibles
+--------------------------
+
+this info is here,
+to list and give some remarks on all 8086 compatible processors
+
+excellent info in Hamarsoft's 86BUGS list
+(also distributed in ralf browns interrupt list)
+
+8086/8088
+---------
+20 bit address bus, 16 bit data bus and registers
+many 8080 assembler sources should be compilable/reusable
+
+8086
+----
+6 bytes prefetch queue
+
+8088
+----
+8086 with 8 bit data bus,
+prefetch queue only 4 byte, and refilled when 1 byte empty
+
+early 8086/8088 revisions bug
+-----------------------------
+(copyright 1978 on package)
+mov sreg, doesnot disable until next operation is executed
+
+8086/8088
+---------
+"mov cs, " causes unconditional jump!
+
+80C86/80C88
+-----------
+"mov cs, " ignored
+
+80186/80188
+-----------
+integrated pic8259, pit8253, dma8253 (but not at standard pc addresses)
+additional instructions
+"mov cs, " ?
+shift count anded with 0x1f
+
+80188
+-----
+8bit data bus
+
+NEC series
+----------
+80186 instruction set, additional nec instructions
+although it is based on 80186 instruction set, some behaviours follow 8086
+8080 emulation mode
+"mov cs, " ignored
+shift count not anded (acts like 8086)
+
+NEC 70116 (V30)
+---------------
+8086 pin compatible
+
+NEC 70108 (V20)
+---------------
+8088 pinout
+
+NEC V30MX
+---------
+on die ems hardware
+24 bit address but for ems memory!?
+no 8080 emulation mode
+
+NEC V40
+-------
+pinout, integrated peripherals as 80186
+
+NEC V50
+-------
+pinout, integrated peripherals as 80188
+
+NEC V33?
+--------
+speed optimized V30?
+
+NEC V25/V35?
+------------
+
+NEC V25+/V35+?
+--------------
+
+NEC V60/V70
+-----------
+risc (misc/delux) like instruction set
+v30? emulation mode (without 8080 emulation mode)
+
+80286
+-----
+80186 with additional instructions
+24 bit address bus,
+protected mode
+
+80386 and later
+---------------
+not covered here
+
+8087/80287/80387/80387sx
+------------------------
+mathematical coprocessors
+
+weitek, iit variants
+
+in 80486 coprocessor integrated
+(except 80486sx and several clones)
+80487: 80486 with other pinout
diff --git a/trunk/src/emu/cpu/i86/i86priv.h b/trunk/src/emu/cpu/i86/i86priv.h
new file mode 100644
index 00000000000..0c51e3bc571
--- /dev/null
+++ b/trunk/src/emu/cpu/i86/i86priv.h
@@ -0,0 +1,168 @@
+/****************************************************************************/
+/* real mode i286 emulator by Fabrice Frances */
+/* (initial work based on David Hedley's pcemu) */
+/* */
+/****************************************************************************/
+#pragma once
+
+#ifndef __I86_H__
+#define __I86_H__
+
+#define I8086_NMI_INT_VECTOR 2
+
+typedef enum { ES, CS, SS, DS } SREGS;
+typedef enum { AX, CX, DX, BX, SP, BP, SI, DI } WREGS;
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE 1
+#endif
+
+
+typedef enum {
+ AL = NATIVE_ENDIAN_VALUE_LE_BE(0x0, 0x1),
+ AH = NATIVE_ENDIAN_VALUE_LE_BE(0x1, 0x0),
+ CL = NATIVE_ENDIAN_VALUE_LE_BE(0x2, 0x3),
+ CH = NATIVE_ENDIAN_VALUE_LE_BE(0x3, 0x2),
+ DL = NATIVE_ENDIAN_VALUE_LE_BE(0x4, 0x5),
+ DH = NATIVE_ENDIAN_VALUE_LE_BE(0x5, 0x4),
+ BL = NATIVE_ENDIAN_VALUE_LE_BE(0x6, 0x7),
+ BH = NATIVE_ENDIAN_VALUE_LE_BE(0x7, 0x6),
+ SPL = NATIVE_ENDIAN_VALUE_LE_BE(0x8, 0x9),
+ SPH = NATIVE_ENDIAN_VALUE_LE_BE(0x9, 0x8),
+ BPL = NATIVE_ENDIAN_VALUE_LE_BE(0xa, 0xb),
+ BPH = NATIVE_ENDIAN_VALUE_LE_BE(0xb, 0xa),
+ SIL = NATIVE_ENDIAN_VALUE_LE_BE(0xc, 0xd),
+ SIH = NATIVE_ENDIAN_VALUE_LE_BE(0xd, 0xc),
+ DIL = NATIVE_ENDIAN_VALUE_LE_BE(0xe, 0xf),
+ DIH = NATIVE_ENDIAN_VALUE_LE_BE(0xf, 0xe)
+} BREGS;
+
+/* parameter x = result, y = source 1, z = source 2 */
+
+#define SetTF(x) (cpustate->TF = (x))
+#define SetIF(x) (cpustate->IF = (x))
+#define SetDF(x) (cpustate->DirVal = (x) ? -1 : 1)
+
+#define SetOFW_Add(x,y,z) (cpustate->OverVal = ((x) ^ (y)) & ((x) ^ (z)) & 0x8000)
+#define SetOFB_Add(x,y,z) (cpustate->OverVal = ((x) ^ (y)) & ((x) ^ (z)) & 0x80)
+#define SetOFW_Sub(x,y,z) (cpustate->OverVal = ((z) ^ (y)) & ((z) ^ (x)) & 0x8000)
+#define SetOFB_Sub(x,y,z) (cpustate->OverVal = ((z) ^ (y)) & ((z) ^ (x)) & 0x80)
+
+#define SetCFB(x) (cpustate->CarryVal = (x) & 0x100)
+#define SetCFW(x) (cpustate->CarryVal = (x) & 0x10000)
+#define SetAF(x,y,z) (cpustate->AuxVal = ((x) ^ ((y) ^ (z))) & 0x10)
+#define SetSF(x) (cpustate->SignVal = (x))
+#define SetZF(x) (cpustate->ZeroVal = (x))
+#define SetPF(x) (cpustate->ParityVal = (x))
+
+#define SetSZPF_Byte(x) (cpustate->ParityVal = cpustate->SignVal = cpustate->ZeroVal = (INT8)(x))
+#define SetSZPF_Word(x) (cpustate->ParityVal = cpustate->SignVal = cpustate->ZeroVal = (INT16)(x))
+
+#define ADDB(dst,src) { unsigned res=dst+src; SetCFB(res); SetOFB_Add(res,src,dst); SetAF(res,src,dst); SetSZPF_Byte(res); dst=(BYTE)res; }
+#define ADDW(dst,src) { unsigned res=dst+src; SetCFW(res); SetOFW_Add(res,src,dst); SetAF(res,src,dst); SetSZPF_Word(res); dst=(WORD)res; }
+
+#define SUBB(dst,src) { unsigned res=dst-src; SetCFB(res); SetOFB_Sub(res,src,dst); SetAF(res,src,dst); SetSZPF_Byte(res); dst=(BYTE)res; }
+#define SUBW(dst,src) { unsigned res=dst-src; SetCFW(res); SetOFW_Sub(res,src,dst); SetAF(res,src,dst); SetSZPF_Word(res); dst=(WORD)res; }
+
+// don't modify CF in case fault occurs
+#define ADCB(dst,src,tmpcf) { unsigned res=dst+src; tmpcf = res & 0x100; SetOFB_Add(res,src,dst); SetAF(res,src,dst); SetSZPF_Byte(res); dst=(BYTE)res; }
+#define ADCW(dst,src,tmpcf) { unsigned res=dst+src; tmpcf = res & 0x10000; SetOFW_Add(res,src,dst); SetAF(res,src,dst); SetSZPF_Word(res); dst=(WORD)res; }
+
+#define SBBB(dst,src,tmpcf) { unsigned res=dst-src; tmpcf = res & 0x100; SetOFB_Sub(res,src,dst); SetAF(res,src,dst); SetSZPF_Byte(res); dst=(BYTE)res; }
+#define SBBW(dst,src,tmpcf) { unsigned res=dst-src; tmpcf = res & 0x10000; SetOFW_Sub(res,src,dst); SetAF(res,src,dst); SetSZPF_Word(res); dst=(WORD)res; }
+
+#define ORB(dst,src) dst |= src; cpustate->CarryVal = cpustate->OverVal = cpustate->AuxVal = 0; SetSZPF_Byte(dst)
+#define ORW(dst,src) dst |= src; cpustate->CarryVal = cpustate->OverVal = cpustate->AuxVal = 0; SetSZPF_Word(dst)
+
+#define ANDB(dst,src) dst &= src; cpustate->CarryVal = cpustate->OverVal = cpustate->AuxVal = 0; SetSZPF_Byte(dst)
+#define ANDW(dst,src) dst &= src; cpustate->CarryVal = cpustate->OverVal = cpustate->AuxVal = 0; SetSZPF_Word(dst)
+
+#define XORB(dst,src) dst ^= src; cpustate->CarryVal = cpustate->OverVal = cpustate->AuxVal = 0; SetSZPF_Byte(dst)
+#define XORW(dst,src) dst ^= src; cpustate->CarryVal = cpustate->OverVal = cpustate->AuxVal = 0; SetSZPF_Word(dst)
+
+#define CF (int)(cpustate->CarryVal != 0)
+#define SF (int)(cpustate->SignVal < 0)
+#define ZF (int)(cpustate->ZeroVal == 0)
+#define PF parity_table[cpustate->ParityVal&0xff]
+#define AF (int)(cpustate->AuxVal != 0)
+#define OF (int)(cpustate->OverVal != 0)
+#define DF (int)(cpustate->DirVal < 0)
+
+/************************************************************************/
+
+#define read_mem_byte(a) cpustate->program->read_byte(a)
+#define read_mem_word(a) cpustate->program->read_word_unaligned(a)
+#define write_mem_byte(a,d) cpustate->program->write_byte((a),(d))
+#define write_mem_word(a,d) cpustate->program->write_word_unaligned((a),(d))
+
+#define read_port_byte(a) cpustate->io->read_byte(a)
+#define read_port_word(a) cpustate->io->read_word_unaligned(a)
+#define write_port_byte(a,d) cpustate->io->write_byte((a),(d))
+#define write_port_word(a,d) cpustate->io->write_word_unaligned((a),(d))
+
+/************************************************************************/
+
+#define SegBase(Seg) (cpustate->sregs[Seg] << 4)
+
+#define DefaultSeg(Seg) ((cpustate->seg_prefix && (Seg == DS || Seg == SS)) ? cpustate->prefix_seg : Seg)
+#define DefaultBase(Seg) ((cpustate->seg_prefix && (Seg == DS || Seg == SS)) ? cpustate->base[cpustate->prefix_seg] : cpustate->base[Seg])
+
+#ifdef I80286
+#define GetMemB(Seg,Off) (read_mem_byte(GetMemAddr(cpustate,Seg,Off,1,I80286_READ)))
+#define GetMemW(Seg,Off) (read_mem_word(GetMemAddr(cpustate,Seg,Off,2,I80286_READ)))
+#define PutMemB(Seg,Off,x) write_mem_byte(GetMemAddr(cpustate,Seg,Off,1,I80286_WRITE), (x))
+#define PutMemW(Seg,Off,x) write_mem_word(GetMemAddr(cpustate,Seg,Off,2,I80286_WRITE), (x))
+#else
+#define GetMemB(Seg,Off) (read_mem_byte((DefaultBase(Seg) + (Off)) & AMASK))
+#define GetMemW(Seg,Off) (read_mem_word((DefaultBase(Seg) + (Off)) & AMASK))
+#define PutMemB(Seg,Off,x) write_mem_byte((DefaultBase(Seg) + (Off)) & AMASK, (x))
+#define PutMemW(Seg,Off,x) write_mem_word((DefaultBase(Seg) + (Off)) & AMASK, (x))
+#endif
+
+#define PEEKBYTE(ea) (read_mem_byte((ea) & AMASK))
+#define ReadByte(ea) (read_mem_byte((ea) & AMASK))
+#define ReadWord(ea) (read_mem_word((ea) & AMASK))
+#define WriteByte(ea,val) write_mem_byte((ea) & AMASK, val);
+#define WriteWord(ea,val) write_mem_word((ea) & AMASK, val);
+
+#define FETCH (cpustate->direct->read_raw_byte(cpustate->pc++, cpustate->fetch_xor))
+#define FETCHOP (cpustate->direct->read_decrypted_byte(cpustate->pc++, cpustate->fetch_xor))
+#define PEEKOP(addr) (cpustate->direct->read_decrypted_byte(addr, cpustate->fetch_xor))
+#define FETCHWORD(var) { var = cpustate->direct->read_raw_byte(cpustate->pc, cpustate->fetch_xor); var += (cpustate->direct->read_raw_byte(cpustate->pc + 1, cpustate->fetch_xor) << 8); cpustate->pc += 2; }
+#define CHANGE_PC(addr)
+#ifdef I80286
+#define PUSH(val) { if(PM) i80286_check_permission(cpustate, SS, cpustate->regs.w[SP]-2, I80286_WORD, I80286_WRITE); cpustate->regs.w[SP] -= 2; WriteWord(((cpustate->base[SS] + cpustate->regs.w[SP]) & AMASK), val); }
+#define POP(var) { if(PM) i80286_check_permission(cpustate, SS, cpustate->regs.w[SP], I80286_WORD, I80286_READ); cpustate->regs.w[SP] += 2; var = ReadWord(((cpustate->base[SS] + ((cpustate->regs.w[SP]-2) & 0xffff)) & AMASK)); }
+#else
+#define PUSH(val) { cpustate->regs.w[SP] -= 2; WriteWord(((cpustate->base[SS] + cpustate->regs.w[SP]) & AMASK), val); }
+#define POP(var) { cpustate->regs.w[SP] += 2; var = ReadWord(((cpustate->base[SS] + ((cpustate->regs.w[SP]-2) & 0xffff)) & AMASK)); }
+#endif
+/************************************************************************/
+#ifdef I80286
+#define IOPL ((cpustate->flags&0x3000)>>12)
+#define NT ((cpustate->flags&0x4000)>>14)
+#define xF (0)
+#else
+#define IOPL (3)
+#define NT (1)
+#define xF (1)
+#endif
+
+#define CompressFlags() (WORD)(CF | 2 |(PF << 2) | (AF << 4) | (ZF << 6) \
+ | (SF << 7) | (cpustate->TF << 8) | (cpustate->IF << 9) \
+ | (DF << 10) | (OF << 11) | (IOPL << 12) | (NT << 14) | (xF << 15))
+
+#define ExpandFlags(f) \
+{ \
+ cpustate->CarryVal = (f) & 1; \
+ cpustate->ParityVal = !((f) & 4); \
+ cpustate->AuxVal = (f) & 16; \
+ cpustate->ZeroVal = !((f) & 64); \
+ cpustate->SignVal = ((f) & 128) ? -1 : 0; \
+ cpustate->TF = ((f) & 256) >> 8; \
+ cpustate->IF = ((f) & 512) >> 9; \
+ cpustate->DirVal = ((f) & 1024) ? -1 : 1; \
+ cpustate->OverVal = (f) & 2048; \
+}
+#endif /* __I86_H__ */
diff --git a/trunk/src/emu/cpu/i86/i86time.c b/trunk/src/emu/cpu/i86/i86time.c
new file mode 100644
index 00000000000..88438668fd7
--- /dev/null
+++ b/trunk/src/emu/cpu/i86/i86time.c
@@ -0,0 +1,310 @@
+/****************************************************************************
+* real mode i286 emulator v1.4 by Fabrice Frances *
+* (initial work based on David Hedley's pcemu) *
+****************************************************************************/
+
+struct i80x86_timing
+{
+ int id;
+
+ UINT8 exception, iret; /* exception, IRET */
+ UINT8 int3, int_imm, into_nt, into_t; /* INTs */
+ UINT8 override; /* segment overrides */
+ UINT8 flag_ops, lahf, sahf; /* flag operations */
+ UINT8 aaa, aas, aam, aad; /* arithmetic adjusts */
+ UINT8 daa, das; /* decimal adjusts */
+ UINT8 cbw, cwd; /* sign extension */
+ UINT8 hlt, load_ptr, lea, nop, wait, xlat; /* misc */
+
+ UINT8 jmp_short, jmp_near, jmp_far; /* direct JMPs */
+ UINT8 jmp_r16, jmp_m16, jmp_m32; /* indirect JMPs */
+ UINT8 call_near, call_far; /* direct CALLs */
+ UINT8 call_r16, call_m16, call_m32; /* indirect CALLs */
+ UINT8 ret_near, ret_far, ret_near_imm, ret_far_imm; /* returns */
+ UINT8 jcc_nt, jcc_t, jcxz_nt, jcxz_t; /* conditional JMPs */
+ UINT8 loop_nt, loop_t, loope_nt, loope_t; /* loops */
+
+ UINT8 in_imm8, in_imm16, in_dx8, in_dx16; /* port reads */
+ UINT8 out_imm8, out_imm16, out_dx8, out_dx16; /* port writes */
+
+ UINT8 mov_rr8, mov_rm8, mov_mr8; /* move, 8-bit */
+ UINT8 mov_ri8, mov_mi8; /* move, 8-bit immediate */
+ UINT8 mov_rr16, mov_rm16, mov_mr16; /* move, 16-bit */
+ UINT8 mov_ri16, mov_mi16; /* move, 16-bit immediate */
+ UINT8 mov_am8, mov_am16, mov_ma8, mov_ma16; /* move, AL/AX memory */
+ UINT8 mov_sr, mov_sm, mov_rs, mov_ms; /* move, segment registers */
+ UINT8 xchg_rr8, xchg_rm8; /* exchange, 8-bit */
+ UINT8 xchg_rr16, xchg_rm16, xchg_ar16; /* exchange, 16-bit */
+
+ UINT8 push_r16, push_m16, push_seg, pushf; /* pushes */
+ UINT8 pop_r16, pop_m16, pop_seg, popf; /* pops */
+
+ UINT8 alu_rr8, alu_rm8, alu_mr8; /* ALU ops, 8-bit */
+ UINT8 alu_ri8, alu_mi8, alu_mi8_ro; /* ALU ops, 8-bit immediate */
+ UINT8 alu_rr16, alu_rm16, alu_mr16; /* ALU ops, 16-bit */
+ UINT8 alu_ri16, alu_mi16, alu_mi16_ro; /* ALU ops, 16-bit immediate */
+ UINT8 alu_r16i8, alu_m16i8, alu_m16i8_ro; /* ALU ops, 16-bit w/8-bit immediate */
+ UINT8 mul_r8, mul_r16, mul_m8, mul_m16; /* MUL */
+ UINT8 imul_r8, imul_r16, imul_m8, imul_m16; /* IMUL */
+ UINT8 div_r8, div_r16, div_m8, div_m16; /* DIV */
+ UINT8 idiv_r8, idiv_r16, idiv_m8, idiv_m16; /* IDIV */
+ UINT8 incdec_r8, incdec_r16, incdec_m8, incdec_m16; /* INC/DEC */
+ UINT8 negnot_r8, negnot_r16, negnot_m8, negnot_m16; /* NEG/NOT */
+
+ UINT8 rot_reg_1, rot_reg_base, rot_reg_bit; /* reg shift/rotate */
+ UINT8 rot_m8_1, rot_m8_base, rot_m8_bit; /* m8 shift/rotate */
+ UINT8 rot_m16_1, rot_m16_base, rot_m16_bit; /* m16 shift/rotate */
+
+ UINT8 cmps8, rep_cmps8_base, rep_cmps8_count; /* CMPS 8-bit */
+ UINT8 cmps16, rep_cmps16_base, rep_cmps16_count; /* CMPS 16-bit */
+ UINT8 scas8, rep_scas8_base, rep_scas8_count; /* SCAS 8-bit */
+ UINT8 scas16, rep_scas16_base, rep_scas16_count; /* SCAS 16-bit */
+ UINT8 lods8, rep_lods8_base, rep_lods8_count; /* LODS 8-bit */
+ UINT8 lods16, rep_lods16_base, rep_lods16_count; /* LODS 16-bit */
+ UINT8 stos8, rep_stos8_base, rep_stos8_count; /* STOS 8-bit */
+ UINT8 stos16, rep_stos16_base, rep_stos16_count; /* STOS 16-bit */
+ UINT8 movs8, rep_movs8_base, rep_movs8_count; /* MOVS 8-bit */
+ UINT8 movs16, rep_movs16_base, rep_movs16_count; /* MOVS 16-bit */
+
+ void * check1; /* marker to make sure we line up */
+
+ UINT8 ins8, rep_ins8_base, rep_ins8_count; /* (80186) INS 8-bit */
+ UINT8 ins16, rep_ins16_base, rep_ins16_count; /* (80186) INS 16-bit */
+ UINT8 outs8, rep_outs8_base, rep_outs8_count; /* (80186) OUTS 8-bit */
+ UINT8 outs16, rep_outs16_base, rep_outs16_count; /* (80186) OUTS 16-bit */
+ UINT8 push_imm, pusha, popa; /* (80186) PUSH immediate, PUSHA/POPA */
+ UINT8 imul_rri8, imul_rmi8; /* (80186) IMUL immediate 8-bit */
+ UINT8 imul_rri16, imul_rmi16; /* (80186) IMUL immediate 16-bit */
+ UINT8 enter0, enter1, enter_base, enter_count, leave; /* (80186) ENTER/LEAVE */
+ UINT8 bound; /* (80186) BOUND */
+
+ void * check2; /* marker to make sure we line up */
+};
+
+
+/* these come from the 8088 timings in OPCODE.LST, but with the
+ penalty for 16-bit memory accesses removed wherever possible */
+static const struct i80x86_timing i8086_cycles =
+{
+ 8086,
+
+ 51,32, /* exception, IRET */
+ 2, 0, 4, 2, /* INTs */
+ 2, /* segment overrides */
+ 2, 4, 4, /* flag operations */
+ 4, 4,83,60, /* arithmetic adjusts */
+ 4, 4, /* decimal adjusts */
+ 2, 5, /* sign extension */
+ 2,24, 2, 2, 3,11, /* misc */
+
+ 15,15,15, /* direct JMPs */
+ 11,18,24, /* indirect JMPs */
+ 19,28, /* direct CALLs */
+ 16,21,37, /* indirect CALLs */
+ 20,32,24,31, /* returns */
+ 4,16, 6,18, /* conditional JMPs */
+ 5,17, 6,18, /* loops */
+
+ 10,14, 8,12, /* port reads */
+ 10,14, 8,12, /* port writes */
+
+ 2, 8, 9, /* move, 8-bit */
+ 4,10, /* move, 8-bit immediate */
+ 2, 8, 9, /* move, 16-bit */
+ 4,10, /* move, 16-bit immediate */
+ 10,10,10,10, /* move, AL/AX memory */
+ 2, 8, 2, 9, /* move, segment registers */
+ 4,17, /* exchange, 8-bit */
+ 4,17, 3, /* exchange, 16-bit */
+
+ 15,24,14,14, /* pushes */
+ 12,25,12,12, /* pops */
+
+ 3, 9,16, /* ALU ops, 8-bit */
+ 4,17,10, /* ALU ops, 8-bit immediate */
+ 3, 9,16, /* ALU ops, 16-bit */
+ 4,17,10, /* ALU ops, 16-bit immediate */
+ 4,17,10, /* ALU ops, 16-bit w/8-bit immediate */
+ 70,118,76,128, /* MUL */
+ 80,128,86,138, /* IMUL */
+ 80,144,86,154, /* DIV */
+ 101,165,107,175,/* IDIV */
+ 3, 2,15,15, /* INC/DEC */
+ 3, 3,16,16, /* NEG/NOT */
+
+ 2, 8, 4, /* reg shift/rotate */
+ 15,20, 4, /* m8 shift/rotate */
+ 15,20, 4, /* m16 shift/rotate */
+
+ 22, 9,21, /* CMPS 8-bit */
+ 22, 9,21, /* CMPS 16-bit */
+ 15, 9,14, /* SCAS 8-bit */
+ 15, 9,14, /* SCAS 16-bit */
+ 12, 9,11, /* LODS 8-bit */
+ 12, 9,11, /* LODS 16-bit */
+ 11, 9,10, /* STOS 8-bit */
+ 11, 9,10, /* STOS 16-bit */
+ 18, 9,17, /* MOVS 8-bit */
+ 18, 9,17, /* MOVS 16-bit */
+
+ (void *)-1 /* marker to make sure we line up */
+};
+
+/* these come from the Intel 80186 datasheet */
+static const struct i80x86_timing i80186_cycles =
+{
+ 80186,
+
+ 45,28, /* exception, IRET */
+ 0, 2, 4, 3, /* INTs */
+ 2, /* segment overrides */
+ 2, 2, 3, /* flag operations */
+ 8, 7,19,15, /* arithmetic adjusts */
+ 4, 4, /* decimal adjusts */
+ 2, 4, /* sign extension */
+ 2,18, 6, 2, 6,11, /* misc */
+
+ 14,14,14, /* direct JMPs */
+ 11,17,26, /* indirect JMPs */
+ 15,23, /* direct CALLs */
+ 13,19,38, /* indirect CALLs */
+ 16,22,18,25, /* returns */
+ 4,13, 5,15, /* conditional JMPs */
+ 6,16, 6,16, /* loops */
+
+ 10,10, 8, 8, /* port reads */
+ 9, 9, 7, 7, /* port writes */
+
+ 2, 9,12, /* move, 8-bit */
+ 3,12, /* move, 8-bit immediate */
+ 2, 9,12, /* move, 16-bit */
+ 4,13, /* move, 16-bit immediate */
+ 8, 8, 9, 9, /* move, AL/AX memory */
+ 2,11, 2,11, /* move, segment registers */
+ 4,17, /* exchange, 8-bit */
+ 4,17, 3, /* exchange, 16-bit */
+
+ 10,16, 9, 9, /* pushes */
+ 10,20, 8, 8, /* pops */
+
+ 3,10,10, /* ALU ops, 8-bit */
+ 4,16,10, /* ALU ops, 8-bit immediate */
+ 3,10,10, /* ALU ops, 16-bit */
+ 4,16,10, /* ALU ops, 16-bit immediate */
+ 4,16,10, /* ALU ops, 16-bit w/8-bit immediate */
+ 26,35,32,41, /* MUL */
+ 25,34,31,40, /* IMUL */
+ 29,38,35,44, /* DIV */
+ 44,53,50,59, /* IDIV */
+ 3, 3,15,15, /* INC/DEC */
+ 3, 3,10,10, /* NEG/NOT */
+
+ 2, 5, 1, /* reg shift/rotate */
+ 15,17, 1, /* m8 shift/rotate */
+ 15,17, 1, /* m16 shift/rotate */
+
+ 22, 5,22, /* CMPS 8-bit */
+ 22, 5,22, /* CMPS 16-bit */
+ 15, 5,15, /* SCAS 8-bit */
+ 15, 5,15, /* SCAS 16-bit */
+ 12, 6,11, /* LODS 8-bit */
+ 12, 6,11, /* LODS 16-bit */
+ 10, 6, 9, /* STOS 8-bit */
+ 10, 6, 9, /* STOS 16-bit */
+ 14, 8, 8, /* MOVS 8-bit */
+ 14, 8, 8, /* MOVS 16-bit */
+
+ (void *)-1, /* marker to make sure we line up */
+
+ 14, 8, 8, /* (80186) INS 8-bit */
+ 14, 8, 8, /* (80186) INS 16-bit */
+ 14, 8, 8, /* (80186) OUTS 8-bit */
+ 14, 8, 8, /* (80186) OUTS 16-bit */
+ 14,68,83, /* (80186) PUSH immediate, PUSHA/POPA */
+ 22,29, /* (80186) IMUL immediate 8-bit */
+ 25,32, /* (80186) IMUL immediate 16-bit */
+ 15,25,4,16, 8, /* (80186) ENTER/LEAVE */
+ 33, /* (80186) BOUND */
+
+ (void *)-1 /* marker to make sure we line up */
+};
+
+/* these come from the 80286 timings in OPCODE.LST */
+/* many of these numbers are suspect */
+static const struct i80x86_timing i80286_cycles =
+{
+ 80286,
+
+ 23,17, /* exception, IRET */
+ 0, 2, 3, 1, /* INTs */
+ 2, /* segment overrides */
+ 2, 2, 2, /* flag operations */
+ 3, 3,16,14, /* arithmetic adjusts */
+ 3, 3, /* decimal adjusts */
+ 2, 2, /* sign extension */
+ 2, 7, 3, 3, 3, 5, /* misc */
+
+ 7, 7,11, /* direct JMPs */
+ 7,11,26, /* indirect JMPs */
+ 7,13, /* direct CALLs */
+ 7,11,29, /* indirect CALLs */
+ 11,15,11,15, /* returns */
+ 3, 7, 4, 8, /* conditional JMPs */
+ 4, 8, 4, 8, /* loops */
+
+ 5, 5, 5, 5, /* port reads */
+ 3, 3, 3, 3, /* port writes */
+
+ 2, 3, 3, /* move, 8-bit */
+ 2, 3, /* move, 8-bit immediate */
+ 2, 3, 3, /* move, 16-bit */
+ 2, 3, /* move, 16-bit immediate */
+ 5, 5, 3, 3, /* move, AL/AX memory */
+ 2, 5, 2, 3, /* move, segment registers */
+ 3, 5, /* exchange, 8-bit */
+ 3, 5, 3, /* exchange, 16-bit */
+
+ 5, 5, 3, 3, /* pushes */
+ 5, 5, 5, 5, /* pops */
+
+ 2, 7, 7, /* ALU ops, 8-bit */
+ 3, 7, 7, /* ALU ops, 8-bit immediate */
+ 2, 7, 7, /* ALU ops, 16-bit */
+ 3, 7, 7, /* ALU ops, 16-bit immediate */
+ 3, 7, 7, /* ALU ops, 16-bit w/8-bit immediate */
+ 13,21,16,24, /* MUL */
+ 13,21,16,24, /* IMUL */
+ 14,22,17,25, /* DIV */
+ 17,25,20,28, /* IDIV */
+ 2, 2, 7, 7, /* INC/DEC */
+ 2, 2, 7, 7, /* NEG/NOT */
+
+ 2, 5, 0, /* reg shift/rotate */
+ 7, 8, 1, /* m8 shift/rotate */
+ 7, 8, 1, /* m16 shift/rotate */
+
+ 13, 5,12, /* CMPS 8-bit */
+ 13, 5,12, /* CMPS 16-bit */
+ 9, 5, 8, /* SCAS 8-bit */
+ 9, 5, 8, /* SCAS 16-bit */
+ 5, 5, 4, /* LODS 8-bit */
+ 5, 5, 4, /* LODS 16-bit */
+ 4, 4, 3, /* STOS 8-bit */
+ 4, 4, 3, /* STOS 16-bit */
+ 5, 5, 4, /* MOVS 8-bit */
+ 5, 5, 4, /* MOVS 16-bit */
+
+ (void *)-1, /* marker to make sure we line up */
+
+ 5, 5, 4, /* (80186) INS 8-bit */
+ 5, 5, 4, /* (80186) INS 16-bit */
+ 5, 5, 4, /* (80186) OUTS 8-bit */
+ 5, 5, 4, /* (80186) OUTS 16-bit */
+ 3,17,19, /* (80186) PUSH immediate, PUSHA/POPA */
+ 21,24, /* (80186) IMUL immediate 8-bit */
+ 21,24, /* (80186) IMUL immediate 16-bit */
+ 11,15,12, 4, 5, /* (80186) ENTER/LEAVE */
+ 13, /* (80186) BOUND */
+
+ (void *)-1 /* marker to make sure we line up */
+};
diff --git a/trunk/src/emu/cpu/i86/instr186.c b/trunk/src/emu/cpu/i86/instr186.c
new file mode 100644
index 00000000000..3863dccd088
--- /dev/null
+++ b/trunk/src/emu/cpu/i86/instr186.c
@@ -0,0 +1,205 @@
+/****************************************************************************
+* real mode i286 emulator v1.4 by Fabrice Frances *
+* (initial work based on David Hedley's pcemu) *
+****************************************************************************/
+
+// file will be included in all cpu variants
+// function renaming will be added when necessary
+// timing value should move to separate array
+
+#undef ICOUNT
+
+#define ICOUNT cpustate->icount
+
+
+static void PREFIX186(_pusha)(i8086_state *cpustate) /* Opcode 0x60 */
+{
+ unsigned tmp=cpustate->regs.w[SP];
+
+#ifdef I80286
+ if(PM) i80286_check_permission(cpustate, SS, cpustate->regs.w[SP]-16, 16, I80286_WRITE);
+#endif
+ ICOUNT -= timing.pusha;
+ PUSH(cpustate->regs.w[AX]);
+ PUSH(cpustate->regs.w[CX]);
+ PUSH(cpustate->regs.w[DX]);
+ PUSH(cpustate->regs.w[BX]);
+ PUSH(tmp);
+ PUSH(cpustate->regs.w[BP]);
+ PUSH(cpustate->regs.w[SI]);
+ PUSH(cpustate->regs.w[DI]);
+}
+
+static unsigned i186_popa_tmp; // hack around GCC 4.6 error because we need the side effects of POP
+static void PREFIX186(_popa)(i8086_state *cpustate) /* Opcode 0x61 */
+{
+
+#ifdef I80286
+ if(PM) i80286_check_permission(cpustate, SS, cpustate->regs.w[SP], 16, I80286_READ);
+#endif
+ ICOUNT -= timing.popa;
+ POP(cpustate->regs.w[DI]);
+ POP(cpustate->regs.w[SI]);
+ POP(cpustate->regs.w[BP]);
+ POP(i186_popa_tmp);
+ POP(cpustate->regs.w[BX]);
+ POP(cpustate->regs.w[DX]);
+ POP(cpustate->regs.w[CX]);
+ POP(cpustate->regs.w[AX]);
+}
+
+static void PREFIX186(_bound)(i8086_state *cpustate) /* Opcode 0x62 */
+{
+ unsigned ModRM = FETCHOP;
+ int low = (INT16)GetRMWord(ModRM);
+ int high= (INT16)GetnextRMWord;
+ int tmp= (INT16)RegWord(ModRM);
+ if (tmp<low || tmp>high) {
+ cpustate->pc-= ( cpustate->seg_prefix ? 3 : 2 );
+ PREFIX86(_interrupt)(cpustate, 5);
+ }
+ ICOUNT -= timing.bound;
+}
+
+static void PREFIX186(_push_d16)(i8086_state *cpustate) /* Opcode 0x68 */
+{
+ unsigned tmp = FETCH;
+
+ ICOUNT -= timing.push_imm;
+ tmp += FETCH << 8;
+ PUSH(tmp);
+}
+
+static void PREFIX186(_imul_d16)(i8086_state *cpustate) /* Opcode 0x69 */
+{
+ DEF_r16w(dst,src);
+ unsigned src2=FETCH;
+ src2+=(FETCH<<8);
+
+ ICOUNT -= (ModRM >= 0xc0) ? timing.imul_rri16 : timing.imul_rmi16;
+
+ dst = (INT32)((INT16)src)*(INT32)((INT16)src2);
+ cpustate->CarryVal = cpustate->OverVal = (((INT32)dst) >> 15 != 0) && (((INT32)dst) >> 15 != -1);
+ RegWord(ModRM)=(WORD)dst;
+}
+
+
+static void PREFIX186(_push_d8)(i8086_state *cpustate) /* Opcode 0x6a */
+{
+ unsigned tmp = (WORD)((INT16)((INT8)FETCH));
+
+ ICOUNT -= timing.push_imm;
+ PUSH(tmp);
+}
+
+static void PREFIX186(_imul_d8)(i8086_state *cpustate) /* Opcode 0x6b */
+{
+ DEF_r16w(dst,src);
+ unsigned src2= (WORD)((INT16)((INT8)FETCH));
+
+ ICOUNT -= (ModRM >= 0xc0) ? timing.imul_rri8 : timing.imul_rmi8;
+
+ dst = (INT32)((INT16)src)*(INT32)((INT16)src2);
+ cpustate->CarryVal = cpustate->OverVal = (((INT32)dst) >> 15 != 0) && (((INT32)dst) >> 15 != -1);
+ RegWord(ModRM)=(WORD)dst;
+}
+
+static void PREFIX186(_insb)(i8086_state *cpustate) /* Opcode 0x6c */
+{
+#ifdef I80286
+ if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
+#endif
+ ICOUNT -= timing.ins8;
+ PutMemB(ES,cpustate->regs.w[DI],read_port_byte(cpustate->regs.w[DX]));
+ cpustate->regs.w[DI] += cpustate->DirVal;
+}
+
+static void PREFIX186(_insw)(i8086_state *cpustate) /* Opcode 0x6d */
+{
+#ifdef I80286
+ if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
+#endif
+ ICOUNT -= timing.ins16;
+ PutMemW(ES,cpustate->regs.w[DI],read_port_word(cpustate->regs.w[DX]));
+ cpustate->regs.w[DI] += 2 * cpustate->DirVal;
+}
+
+static void PREFIX186(_outsb)(i8086_state *cpustate) /* Opcode 0x6e */
+{
+#ifdef I80286
+ if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
+#endif
+ ICOUNT -= timing.outs8;
+ write_port_byte(cpustate->regs.w[DX],GetMemB(DS,cpustate->regs.w[SI]));
+ cpustate->regs.w[SI] += cpustate->DirVal; /* GOL 11/27/01 */
+}
+
+static void PREFIX186(_outsw)(i8086_state *cpustate) /* Opcode 0x6f */
+{
+#ifdef I80286
+ if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
+#endif
+ ICOUNT -= timing.outs16;
+ write_port_word(cpustate->regs.w[DX],GetMemW(DS,cpustate->regs.w[SI]));
+ cpustate->regs.w[SI] += 2 * cpustate->DirVal; /* GOL 11/27/01 */
+}
+
+static void PREFIX186(_rotshft_bd8)(i8086_state *cpustate) /* Opcode 0xc0 */
+{
+ unsigned ModRM = FETCH;
+ unsigned src = GetRMByte(ModRM);
+ unsigned count = FETCH;
+
+ PREFIX86(_rotate_shift_Byte)(cpustate,ModRM,count & 0x1f,src);
+}
+
+static void PREFIX186(_rotshft_wd8)(i8086_state *cpustate) /* Opcode 0xc1 */
+{
+ unsigned ModRM = FETCH;
+ unsigned src = GetRMWord(ModRM);
+ unsigned count = FETCH;
+
+ PREFIX86(_rotate_shift_Word)(cpustate,ModRM,count & 0x1f,src);
+}
+
+static void PREFIX186(_enter)(i8086_state *cpustate) /* Opcode 0xc8 */
+{
+ unsigned nb = FETCH;
+ unsigned i,level;
+ UINT16 fp;
+
+ nb += FETCH << 8;
+#ifdef I80286
+ level = FETCH & 0x1f;
+ if(PM) i80286_check_permission(cpustate, SS, cpustate->regs.w[SP]-2-(level*2), 2+(level*2), I80286_WRITE);
+#else
+ level = FETCH;
+#endif
+ ICOUNT -= (level == 0) ? timing.enter0 : (level == 1) ? timing.enter1 : timing.enter_base + level * timing.enter_count;
+ PUSH(cpustate->regs.w[BP]);
+ fp = cpustate->regs.w[SP];
+ for (i=1;i<level;i++)
+ PUSH(GetMemW(SS,cpustate->regs.w[BP]-i*2));
+ if (level) PUSH(fp);
+ cpustate->regs.w[BP] = fp;
+ cpustate->regs.w[SP] -= nb;
+}
+
+static void PREFIX186(_leave)(i8086_state *cpustate) /* Opcode 0xc9 */
+{
+ ICOUNT -= timing.leave;
+ cpustate->regs.w[SP]=cpustate->regs.w[BP];
+ POP(cpustate->regs.w[BP]);
+}
+
+static void PREFIX186(_rotshft_bcl)(i8086_state *cpustate) /* Opcode 0xd2 */
+{
+ unsigned ModRM = FETCHOP;
+ PREFIX86(_rotate_shift_Byte)(cpustate,ModRM,cpustate->regs.b[CL] & 0x1f,GetRMByte(ModRM));
+}
+
+static void PREFIX186(_rotshft_wcl)(i8086_state *cpustate) /* Opcode 0xd3 */
+{
+ unsigned ModRM = FETCHOP;
+ PREFIX86(_rotate_shift_Word)(cpustate,ModRM,cpustate->regs.b[CL] & 0x1f,GetRMWord(ModRM));
+}
diff --git a/trunk/src/emu/cpu/i86/instr186.h b/trunk/src/emu/cpu/i86/instr186.h
new file mode 100644
index 00000000000..f16b7e3fb01
--- /dev/null
+++ b/trunk/src/emu/cpu/i86/instr186.h
@@ -0,0 +1,36 @@
+/****************************************************************************
+* real mode i286 emulator v1.4 by Fabrice Frances *
+* (initial work based on David Hedley's pcemu) *
+****************************************************************************/
+
+// file will be included in all cpu variants
+// timing value should move to separate array
+
+static void PREFIX186(_pusha)(i8086_state *cpustate);
+static void PREFIX186(_popa)(i8086_state *cpustate);
+static void PREFIX186(_bound)(i8086_state *cpustate);
+static void PREFIX186(_push_d16)(i8086_state *cpustate);
+static void PREFIX186(_imul_d16)(i8086_state *cpustate);
+static void PREFIX186(_push_d8)(i8086_state *cpustate);
+static void PREFIX186(_imul_d8)(i8086_state *cpustate);
+static void PREFIX186(_rotshft_bd8)(i8086_state *cpustate);
+static void PREFIX186(_rotshft_wd8)(i8086_state *cpustate);
+static void PREFIX186(_enter)(i8086_state *cpustate);
+static void PREFIX186(_leave)(i8086_state *cpustate);
+static void PREFIX186(_insb)(i8086_state *cpustate);
+static void PREFIX186(_insw)(i8086_state *cpustate);
+static void PREFIX186(_outsb)(i8086_state *cpustate);
+static void PREFIX186(_outsw)(i8086_state *cpustate);
+
+/* changed instructions */
+static void PREFIX(_pop_ss)(i8086_state *cpustate);
+static void PREFIX(_es)(i8086_state *cpustate);
+static void PREFIX(_cs)(i8086_state *cpustate);
+static void PREFIX(_ss)(i8086_state *cpustate);
+static void PREFIX(_ds)(i8086_state *cpustate);
+static void PREFIX(_mov_sregw)(i8086_state *cpustate);
+static void PREFIX186(_repne)(i8086_state *cpustate);
+static void PREFIX186(_repe)(i8086_state *cpustate);
+static void PREFIX186(_sti)(i8086_state *cpustate);
+static void PREFIX186(_rotshft_bcl)(i8086_state *cpustate);
+static void PREFIX186(_rotshft_wcl)(i8086_state *cpustate);
diff --git a/trunk/src/emu/cpu/i86/instr286.c b/trunk/src/emu/cpu/i86/instr286.c
new file mode 100644
index 00000000000..ce841a0fa89
--- /dev/null
+++ b/trunk/src/emu/cpu/i86/instr286.c
@@ -0,0 +1,869 @@
+/* descriptor table format in memory
+ UINT16 limit
+ UINT24 addr
+ 0..3 type
+ system segment
+ 3 execute:
+ 0 data segment: readable,
+ 1: write
+ 2: expand down
+ 1 code segment
+ 1: readable
+ 2: conforming (can be used with higher privilege level)
+ 0: access (set when processor accesses segment)
+
+ 4 dt 0 system segment, 1 application segment (code, data)
+ 5,6 dpl descriptor privileg level
+ 7 p present 0 gives trap when accessed
+ UINT16 reserved (should be zero)
+*/
+#define LIMIT(desc) (desc[0]&0xffff)
+#define BASE(desc) ((desc[1]&0xffff)|((desc[2]&0xff)<<16))
+#define RIGHTS(desc) ((desc[2]>>8)&0xff)
+
+#define ACCESS(r) (r&1)
+#define SET_ACC(desc) (desc[2]|=0x100)
+#define RW(r) ((r>>1)&1)
+#define READ(r) ((r>>1)&1)
+#define CONF(r) ((r>>2)&1)
+#define EXPDOWN(r) ((r>>2)&1)
+#define CODE(r) ((r>>3)&1)
+#define SEGDESC(r) ((r>>4)&1)
+#define DPL(r) ((r>>5)&3)
+#define PRES(r) ((r>>7)&1)
+#define GATE(r) (r&31)
+#define GATESEL(desc) (desc[1])
+#define GATEOFF(desc) (desc[0])
+#define GATECNT(desc) (desc[2]&31)
+
+#define RPL(s) (s&3)
+#define IDX(s) (s&(~7))
+#define IDXTBL(s) (s&(~3))
+#define TBL(s) (s&4)
+
+#define TSSDESCIDLE 1
+#define LDTDESC 2
+#define TSSDESCBUSY 3
+#define CALLGATE 4
+#define TASKGATE 5
+#define INTGATE 6
+#define TRAPGATE 7
+
+#define TSS_BACK 0
+#define TSS_SP0 1
+#define TSS_SS0 2
+#define TSS_SP1 3
+#define TSS_SS1 4
+#define TSS_SP2 5
+#define TSS_SS2 6
+#define TSS_IP 7
+#define TSS_FLAG 8
+#define TSS_AX 9
+#define TSS_CX 10
+#define TSS_DX 11
+#define TSS_BX 12
+#define TSS_SP 13
+#define TSS_BP 14
+#define TSS_SI 15
+#define TSS_DI 16
+#define TSS_ES 17
+#define TSS_CS 18
+#define TSS_SS 19
+#define TSS_DS 20
+#define TSS_LDT 21
+
+#define PMAX(a,b) ((a<b)?b:a)
+
+#define IRET 0
+#define JMP 1
+#define CALL 2
+
+// when a cpu reset happens on a AT the bios checks for 9 in byte 0xf
+// of the nvram. if yes, after init, it sets the stack pointer to the value in 0040:0067
+// in the bios data segment then pops es and ds off that stack, does popa then a far ret.
+
+static void i80286_trap2(i80286_state *cpustate,UINT32 error)
+{
+ int error_code = error & 0xffff;
+ UINT16 number = error >> 16;
+ if(error_code == 0xffff) error_code = -1;
+ cpustate->pc = cpustate->prevpc;
+ try {
+ switch(number) {
+ case DIVIDE_BY_ZERO:
+ case INVALID_TSS:
+ case SEG_NOT_PRESENT:
+ case STACK_FAULT:
+ case GENERAL_PROTECTION_FAULT:
+ cpustate->trap_level++;
+ if(cpustate->trap_level == 2) throw TRAP(DOUBLE_FAULT,0);
+ if(cpustate->trap_level == 3) break;
+ i80286_interrupt_descriptor(cpustate,number,1,error_code);
+ break;
+ case DOUBLE_FAULT:
+ i80286_interrupt_descriptor(cpustate,number,1,0);
+ break;
+ default:
+ i80286_interrupt_descriptor(cpustate,number,1,-1);
+ }
+ } catch(UINT32 e) { i80286_trap2(cpustate, e); }
+ if(cpustate->trap_level == 3)
+ // this is supposed to triggered by support hardware
+ // create a shutdown output line that causes a reset
+ // NMI can wake processor without reset
+ device_set_input_line(cpustate->device, INPUT_LINE_RESET, PULSE_LINE);
+ cpustate->trap_level = 0;
+}
+
+static UINT32 i80286_selector_address(i80286_state *cpustate,UINT16 sel)
+{
+ UINT32 base;
+ UINT16 limit;
+ if(TBL(sel)) { base = cpustate->ldtr.base; limit = cpustate->ldtr.limit; }
+ else { base = cpustate->gdtr.base; limit = cpustate->gdtr.limit; }
+ return ((IDX(sel)>=limit)||!IDXTBL(sel)?-1:base+IDX(sel));
+}
+
+static int i80286_verify(i80286_state *cpustate, UINT16 selector, i80286_operation operation, UINT8 rights)
+{
+ if (!IDXTBL(selector)) return GENERAL_PROTECTION_FAULT;
+ if (!SEGDESC(rights)) return GENERAL_PROTECTION_FAULT;
+
+ switch(operation) {
+ case I80286_READ:
+ if (CODE(rights) && !READ(rights)) return GENERAL_PROTECTION_FAULT;
+ break;
+ case I80286_WRITE:
+ if (CODE(rights) || !RW(rights)) return GENERAL_PROTECTION_FAULT;
+ break;
+ case I80286_EXECUTE:
+ if (!CODE(rights)) return GENERAL_PROTECTION_FAULT;
+ break;
+ }
+ return 0;
+}
+
+static void i80286_pop_seg(i80286_state *cpustate, int reg)
+{
+ UINT16 sel;
+ if(PM) i80286_check_permission(cpustate, SS, cpustate->regs.w[SP], I80286_WORD, I80286_READ);
+ sel = ReadWord(cpustate->base[SS]+cpustate->regs.w[SP]);
+ i80286_data_descriptor(cpustate, reg, sel);
+ cpustate->regs.w[SP] += 2;
+}
+
+static void i80286_data_descriptor_full(i80286_state *cpustate, int reg, UINT16 selector, int cpl, UINT32 trap, UINT16 offset, int size)
+{
+ if (PM) {
+ UINT16 desc[3];
+ UINT8 r;
+ UINT32 addr;
+ /* selector format
+ 15..3 number/address in descriptor table
+ 2: 0 global, 1 local descriptor table
+ 1,0: requested privileg level
+ must be higher or same as current privileg level in code selector */
+ if ((reg != SS) && !IDXTBL(selector)) {
+ cpustate->sregs[reg]=0;
+ cpustate->limit[reg]=0;
+ cpustate->base[reg]=0;
+ cpustate->rights[reg]=0;
+ return;
+ }
+
+ if ((addr = i80286_selector_address(cpustate,selector)) == -1) throw trap;
+
+ desc[0] = ReadWord(addr);
+ desc[1] = ReadWord(addr+2);
+ desc[2] = ReadWord(addr+4);
+ r = RIGHTS(desc);
+ if (!SEGDESC(r)) throw trap;
+ if (reg == SS) {
+ if (!IDXTBL(selector)) throw trap;
+ if (DPL(r)!=cpl) throw trap;
+ if (RPL(selector)!=cpl) throw trap;
+ if (!RW(r) || CODE(r)) throw trap;
+ if (!PRES(r)) throw TRAP(STACK_FAULT,(IDXTBL(selector)+(trap&1)));
+ } else {
+ if ((DPL(r) < PMAX(cpl,RPL(selector))) && (!CODE(r) || (CODE(r) && !CONF(r)))) throw trap;
+ if (CODE(r) && !READ(r)) throw trap;
+ if (!PRES(r)) throw TRAP(SEG_NOT_PRESENT,(IDXTBL(selector)+(trap&1)));
+ }
+ if (offset+size) {
+ if ((CODE(r) || !EXPDOWN(r)) && ((offset+size-1) > LIMIT(desc))) throw (reg==SS)?TRAP(STACK_FAULT,(trap&1)):trap;
+ if (!CODE(r) && EXPDOWN(r) && ((offset <= LIMIT(desc)) || ((offset+size-1) > 0xffff))) throw (reg==SS)?TRAP(STACK_FAULT,(trap&1)):trap;
+ }
+
+ SET_ACC(desc);
+ WriteWord(addr+4, desc[2]);
+ cpustate->sregs[reg]=selector;
+ cpustate->limit[reg]=LIMIT(desc);
+ cpustate->base[reg]=BASE(desc);
+ cpustate->rights[reg]=RIGHTS(desc);
+ } else {
+ cpustate->sregs[reg]=selector;
+ cpustate->base[reg]=selector<<4;
+ }
+}
+
+static void i80286_data_descriptor(i80286_state *cpustate, int reg, UINT16 selector)
+{
+ i80286_data_descriptor_full(cpustate, reg, selector, CPL, TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(selector)), 0, 0);
+}
+
+static void i80286_switch_task(i80286_state *cpustate, UINT16 ntask, int type)
+{
+ UINT16 ndesc[3], desc[3], ntss[22], otss[22];
+ UINT8 r, lr;
+ UINT32 naddr, oaddr, ldtaddr;
+ int i;
+ logerror("This program uses TSSs, how rare. Please report this to the developers.\n");
+ if (TBL(ntask)) throw TRAP(INVALID_TSS,IDXTBL(ntask));
+ if ((naddr = i80286_selector_address(cpustate,ntask)) == -1) throw TRAP(INVALID_TSS,IDXTBL(ntask));
+ oaddr = i80286_selector_address(cpustate,cpustate->tr.sel);
+ ndesc[0] = ReadWord(naddr);
+ ndesc[1] = ReadWord(naddr+2);
+ ndesc[2] = ReadWord(naddr+4);
+ desc[2] = ReadWord(oaddr+4);
+ r = RIGHTS(ndesc);
+ if (SEGDESC(r) || ((GATE(r) & ~2) != TSSDESCIDLE)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(ntask));
+ if (!PRES(r)) throw TRAP(SEG_NOT_PRESENT, IDXTBL(ntask));
+ if (LIMIT(ndesc) < 43) throw TRAP(INVALID_TSS,IDXTBL(ntask));
+ for (i = 0; i < 44; i+=2) ntss[i/2] = ReadWord(BASE(ndesc)+i);
+
+ cpustate->flags = CompressFlags();
+ if (type == CALL) WriteWord(BASE(ndesc)+TSS_BACK*2, cpustate->tr.sel);
+ if (type == IRET) cpustate->flags &= ~0x4000;
+
+ otss[TSS_IP] = cpustate->pc-cpustate->base[CS];
+ otss[TSS_FLAG] = cpustate->flags;
+ otss[TSS_AX] = cpustate->regs.w[AX];
+ otss[TSS_CX] = cpustate->regs.w[CX];
+ otss[TSS_DX] = cpustate->regs.w[DX];
+ otss[TSS_BX] = cpustate->regs.w[BX];
+ otss[TSS_SP] = cpustate->regs.w[SP];
+ otss[TSS_BP] = cpustate->regs.w[BP];
+ otss[TSS_SI] = cpustate->regs.w[SI];
+ otss[TSS_DI] = cpustate->regs.w[DI];
+ otss[TSS_ES] = cpustate->sregs[ES];
+ otss[TSS_CS] = cpustate->sregs[CS];
+ otss[TSS_SS] = cpustate->sregs[SS];
+ otss[TSS_DS] = cpustate->sregs[DS];
+ otss[TSS_LDT] = cpustate->ldtr.sel;
+
+ for (i = 14; i < 44; i+=2) WriteWord(cpustate->tr.base+i, otss[i/2]);
+
+ // jmp does both
+ if (type != CALL) {
+ desc[2] &= ~0x200; // mark idle
+ WriteWord(oaddr+4, desc[2]);
+ }
+ if (type != IRET) {
+ ndesc[2] |= 0x200;
+ WriteWord(naddr+4, ndesc[2]);
+ }
+ cpustate->tr.sel=ntask;
+ cpustate->tr.limit=LIMIT(ndesc);
+ cpustate->tr.base=BASE(ndesc);
+ cpustate->tr.rights=RIGHTS(ndesc);
+
+ cpustate->flags = ntss[TSS_FLAG];
+ cpustate->regs.w[AX] = ntss[TSS_AX];
+ cpustate->regs.w[CX] = ntss[TSS_CX];
+ cpustate->regs.w[DX] = ntss[TSS_DX];
+ cpustate->regs.w[BX] = ntss[TSS_BX];
+ cpustate->regs.w[SP] = ntss[TSS_SP];
+ cpustate->regs.w[BP] = ntss[TSS_BP];
+ cpustate->regs.w[SI] = ntss[TSS_SI];
+ cpustate->regs.w[DI] = ntss[TSS_DI];
+
+ if (TBL(ntss[TSS_LDT])) throw TRAP(INVALID_TSS,IDXTBL(ntss[TSS_LDT]));
+ if (IDXTBL(ntss[TSS_LDT])) {
+ if ((ldtaddr = i80286_selector_address(cpustate,ntss[TSS_LDT])) == -1)
+ throw TRAP(INVALID_TSS,IDXTBL(ntss[TSS_LDT]));
+ desc[0] = ReadWord(ldtaddr);
+ desc[1] = ReadWord(ldtaddr+2);
+ desc[2] = ReadWord(ldtaddr+4);
+ lr = RIGHTS(desc);
+ if (SEGDESC(lr) || (GATE(lr) != LDTDESC)) throw TRAP(INVALID_TSS,IDXTBL(ntss[TSS_LDT]));
+ if (!PRES(lr)) throw TRAP(INVALID_TSS,IDXTBL(ntss[TSS_LDT]));
+ cpustate->ldtr.sel=ntss[TSS_LDT];
+ cpustate->ldtr.limit=LIMIT(desc);
+ cpustate->ldtr.base=BASE(desc);
+ cpustate->ldtr.rights=RIGHTS(desc);
+ } else {
+ cpustate->ldtr.sel=0;
+ cpustate->ldtr.limit=0;
+ cpustate->ldtr.base=0;
+ cpustate->ldtr.rights=0;
+ }
+
+ if (type == CALL) cpustate->flags |= 0x4000;
+ cpustate->msw |= 8;
+ i80286_data_descriptor_full(cpustate, SS, ntss[TSS_SS], RPL(ntss[TSS_CS]), TRAP(INVALID_TSS,IDXTBL(ntss[TSS_SS])), 0, 0);
+
+ cpustate->sregs[CS] = IDXTBL(cpustate->sregs[CS]) | RPL(ntss[TSS_CS]); // fixme
+ try {
+ i80286_code_descriptor(cpustate, ntss[TSS_CS], ntss[TSS_IP], 0);
+ } catch(UINT32 e) {
+ int error_code = e & 0xffff;
+ if(error_code == GENERAL_PROTECTION_FAULT) e = TRAP(INVALID_TSS,(e >> 16)); // #NP fault is correct
+ throw e;
+ }
+
+ i80286_data_descriptor_full(cpustate, ES, ntss[TSS_ES], RPL(ntss[TSS_CS]), TRAP(INVALID_TSS,IDXTBL(ntss[TSS_ES])), 0, 0);
+ i80286_data_descriptor_full(cpustate, DS, ntss[TSS_DS], RPL(ntss[TSS_CS]), TRAP(INVALID_TSS,IDXTBL(ntss[TSS_DS])), 0, 0);
+}
+
+static void i80286_code_descriptor(i80286_state *cpustate, UINT16 selector, UINT16 offset, int gate)
+{
+ if (PM) {
+ UINT16 desc[3];
+ UINT8 r;
+ UINT32 addr;
+ /* selector format
+ 15..3 number/address in descriptor table
+ 2: 0 global, 1 local descriptor table
+ 1,0: requested privileg level
+ must be higher or same as current privileg level in code selector */
+ if ((addr = i80286_selector_address(cpustate,selector)) == -1) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(selector));
+ desc[0] = ReadWord(addr);
+ desc[1] = ReadWord(addr+2);
+ desc[2] = ReadWord(addr+4);
+ r = RIGHTS(desc);
+
+ if (SEGDESC(r)) {
+ if (!CODE(r)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(selector));
+ if (CONF(r)) { if(DPL(r)>CPL) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(selector)); }
+ else if ((RPL(selector)>CPL) || (DPL(r)!=CPL)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(selector));
+
+ if (!PRES(r)) throw TRAP(SEG_NOT_PRESENT,IDXTBL(selector)); // this order is important
+ if (offset > LIMIT(desc)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
+ SET_ACC(desc);
+ WriteWord(addr+4, desc[2]);
+ cpustate->sregs[CS]=IDXTBL(selector) | CPL;
+ cpustate->limit[CS]=LIMIT(desc);
+ cpustate->base[CS]=BASE(desc);
+ cpustate->rights[CS]=RIGHTS(desc);
+ cpustate->pc=cpustate->base[CS]+offset;
+ } else { // systemdescriptor
+ UINT16 gatedesc[3]={0,0,0};
+ UINT16 gatesel = GATESEL(desc);
+ if (!gate) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(selector)); // tss cs must be segment
+ if (DPL(r) < PMAX(CPL,RPL(selector))) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(selector));
+ if (!PRES(r)) throw TRAP(SEG_NOT_PRESENT, IDXTBL(selector));
+
+ switch (GATE(r)) {
+ case CALLGATE:
+ if ((addr = i80286_selector_address(cpustate,gatesel)) == -1)
+ throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(gatesel));
+ gatedesc[0] = ReadWord(addr);
+ gatedesc[1] = ReadWord(addr+2);
+ gatedesc[2] = ReadWord(addr+4);
+ r = RIGHTS(gatedesc);
+ if (!CODE(r) || !SEGDESC(r)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(gatesel));
+ if (DPL(r)>CPL) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(gatesel));
+ if (!PRES(r)) throw TRAP(SEG_NOT_PRESENT,IDXTBL(gatesel));
+ if (GATEOFF(desc) > LIMIT(gatedesc)) throw TRAP(GENERAL_PROTECTION_FAULT,0);
+
+ if (!CONF(r)&&(DPL(r)<CPL)) { // inner call
+ UINT16 tss_ss, tss_sp, oldss, oldsp;
+ UINT32 oldstk;
+ int i;
+ if(gate == JMP) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(gatesel)); // can't jmp to inner
+ tss_ss = ReadWord(cpustate->tr.base+TSS_SS0*2+(DPL(r)*4));
+ tss_sp = ReadWord(cpustate->tr.base+TSS_SP0*2+(DPL(r)*4));
+
+ oldss = cpustate->sregs[SS];
+ oldsp = cpustate->regs.w[SP];
+ oldstk = cpustate->base[SS] + oldsp;
+ i80286_data_descriptor_full(cpustate, SS, tss_ss, DPL(r), TRAP(INVALID_TSS,IDXTBL(tss_ss)), tss_sp-8-(GATECNT(desc)*2), 8+(GATECNT(desc)*2));
+ cpustate->regs.w[SP] = tss_sp;
+ PUSH(oldss);
+ PUSH(oldsp);
+ for (i = GATECNT(desc)-1; i >= 0; i--)
+ PUSH(ReadWord(oldstk+(i*2)));
+ } else i80286_check_permission(cpustate, SS, cpustate->regs.w[SP]-4, 4, I80286_READ);
+ SET_ACC(gatedesc);
+ WriteWord(addr+4, gatedesc[2]);
+ cpustate->sregs[CS]=IDXTBL(gatesel) | DPL(r);
+ cpustate->limit[CS]=LIMIT(gatedesc);
+ cpustate->base[CS]=BASE(gatedesc);
+ cpustate->rights[CS]=RIGHTS(gatedesc);
+ cpustate->pc=(cpustate->base[CS]+GATEOFF(desc))&AMASK;
+ break;
+ case TASKGATE:
+ selector = gatesel;
+ if ((addr = i80286_selector_address(cpustate,selector)) == -1)
+ throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(selector));
+ desc[2] = ReadWord(addr+4);
+ r = RIGHTS(desc);
+ if (SEGDESC(r) || (GATE(r) != TSSDESCIDLE)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(selector));
+ case TSSDESCIDLE:
+ i80286_switch_task(cpustate, selector, gate);
+ i80286_load_flags(cpustate, cpustate->flags, CPL);
+ break;
+ default:
+ throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(selector));
+ }
+ }
+ } else {
+ cpustate->sregs[CS]=selector;
+ cpustate->base[CS]=selector<<4;
+ cpustate->rights[CS]=0x9a;
+ cpustate->limit[CS]=0xffff;
+ cpustate->pc=(cpustate->base[CS]+offset)&AMASK;
+ }
+}
+
+static void i80286_interrupt_descriptor(i80286_state *cpustate,UINT16 number, int hwint, int error)
+{
+ UINT16 desc[3], gatedesc[3]={0,0,0}, gatesel;
+ UINT8 r;
+ UINT32 addr;
+
+ if(!PM) return PREFIX86(_interrupt)(cpustate, number);
+
+ if ((number<<3)>=cpustate->idtr.limit)
+ throw TRAP(GENERAL_PROTECTION_FAULT,(number*8+2+(hwint&&1)));
+
+ desc[0] = ReadWord(cpustate->idtr.base+(number<<3));
+ desc[1] = ReadWord(cpustate->idtr.base+(number<<3)+2);
+ desc[2] = ReadWord(cpustate->idtr.base+(number<<3)+4);
+ r = RIGHTS(desc);
+ if (!hwint && (DPL(r)<CPL)) throw TRAP(GENERAL_PROTECTION_FAULT,(number*8+2+(hwint&&1)));
+ if (!PRES(r)) throw TRAP(SEG_NOT_PRESENT,(number*8+2+(hwint&&1)));
+ gatesel = GATESEL(desc);
+
+ switch (GATE(r)) {
+ case TASKGATE:
+ i80286_switch_task(cpustate, gatesel, CALL);
+ if((hwint == 1) && (error != -1)) PUSH(error);
+ i80286_load_flags(cpustate, cpustate->flags, CPL);
+ break;
+ case INTGATE:
+ case TRAPGATE:
+ if ((addr = i80286_selector_address(cpustate,gatesel)) == -1)
+ throw TRAP(GENERAL_PROTECTION_FAULT,(IDXTBL(gatesel)+(hwint&&1)));
+ gatedesc[0] = ReadWord(addr);
+ gatedesc[1] = ReadWord(addr+2);
+ gatedesc[2] = ReadWord(addr+4);
+ r = RIGHTS(gatedesc);
+ if (!CODE(r) || !SEGDESC(r)) throw TRAP(GENERAL_PROTECTION_FAULT,(IDXTBL(gatesel)+(hwint&&1)));
+ if (DPL(r)>CPL) throw TRAP(GENERAL_PROTECTION_FAULT,(IDXTBL(gatesel)+(hwint&&1)));
+ if (!PRES(r)) throw TRAP(SEG_NOT_PRESENT,(IDXTBL(gatesel)+(hwint&&1)));
+ if (GATEOFF(desc) > LIMIT(gatedesc)) throw TRAP(GENERAL_PROTECTION_FAULT,(int)(hwint&&1));
+
+ if (!CONF(r)&&(DPL(r)<CPL)) { // inner call
+ UINT16 tss_ss, tss_sp, oldss, oldsp;
+ tss_ss = ReadWord(cpustate->tr.base+TSS_SS0*2+(DPL(r)*4));
+ tss_sp = ReadWord(cpustate->tr.base+TSS_SP0*2+(DPL(r)*4));
+
+ oldss = cpustate->sregs[SS];
+ oldsp = cpustate->regs.w[SP];
+ i80286_data_descriptor_full(cpustate, SS, tss_ss, DPL(r), TRAP(INVALID_TSS,(IDXTBL(tss_ss)+(hwint&&1))), tss_sp-((error != -1)?12:10), (error != -1)?12:10);
+ cpustate->regs.w[SP] = tss_sp;
+ PUSH(oldss);
+ PUSH(oldsp);
+ } else i80286_check_permission(cpustate, SS, cpustate->regs.w[SP]-((error != -1)?8:6), (error != -1)?8:6, I80286_READ);
+ SET_ACC(gatedesc);
+ WriteWord(addr+4, gatedesc[2]);
+ PREFIX(_pushf(cpustate));
+ PUSH(cpustate->sregs[CS]);
+ PUSH(cpustate->pc-cpustate->base[CS]);
+ if((hwint == 1) && (error != -1)) PUSH(error);
+ cpustate->sregs[CS]=IDXTBL(gatesel) | DPL(r);
+ cpustate->limit[CS]=LIMIT(gatedesc);
+ cpustate->base[CS]=BASE(gatedesc);
+ cpustate->rights[CS]=RIGHTS(gatedesc);
+ cpustate->pc=(cpustate->base[CS]+GATEOFF(desc))&AMASK;
+ cpustate->TF = 0;
+ cpustate->flags &= ~0x4000;
+ if (GATE(RIGHTS(desc)) == INTGATE) cpustate->IF = 0;
+ CHANGE_PC(cpustate->pc);
+ break;
+ default:
+ throw TRAP(GENERAL_PROTECTION_FAULT,(number*8+2+(hwint&&1)));
+ }
+}
+
+static void PREFIX286(_0fpre)(i8086_state *cpustate)
+{
+ unsigned next = FETCHOP;
+ UINT16 ModRM, desc[3];
+ UINT16 tmp, msw, sel;
+ UINT8 r;
+ UINT32 addr;
+
+ switch (next) {
+ case 0:
+ if (!PM) throw TRAP(ILLEGAL_INSTRUCTION,-1);
+ ModRM=FETCHOP;
+ switch (ModRM&0x38) {
+ case 0: /* sldt */
+ PutRMWord(ModRM, cpustate->ldtr.sel);
+ break;
+ case 8: /* str */
+ PutRMWord(ModRM, cpustate->tr.sel);
+ break;
+ case 0x10: /* lldt */
+ if (CPL!=0) throw TRAP(GENERAL_PROTECTION_FAULT,0);
+ sel=GetRMWord(ModRM);
+ if (TBL(sel)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(sel));
+ if (IDXTBL(sel)) {
+ if (IDX(sel)>=cpustate->gdtr.limit) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(sel));
+ addr = cpustate->gdtr.base + IDX(sel);
+ desc[0] = ReadWord(addr);
+ desc[1] = ReadWord(addr+2);
+ desc[2] = ReadWord(addr+4);
+ r = RIGHTS(desc);
+ if (SEGDESC(r) || (GATE(r) != LDTDESC)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(sel));
+ if (!PRES(r)) throw TRAP(SEG_NOT_PRESENT,IDXTBL(sel));
+ } else {
+ desc[0] = 0;
+ desc[1] = 0;
+ desc[2] = 0;
+ }
+ cpustate->ldtr.sel=sel;
+ cpustate->ldtr.limit=LIMIT(desc);
+ cpustate->ldtr.base=BASE(desc);
+ cpustate->ldtr.rights=RIGHTS(desc);
+ break;
+ case 0x18: /* ltr */
+ if (CPL!=0) throw TRAP(GENERAL_PROTECTION_FAULT,0);
+ sel=GetRMWord(ModRM);
+ if ((addr = i80286_selector_address(cpustate,sel)) == -1) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(sel));
+ desc[0] = ReadWord(addr);
+ desc[1] = ReadWord(addr+2);
+ desc[2] = ReadWord(addr+4);
+ r = RIGHTS(desc);
+ if (SEGDESC(r) || (GATE(r) != TSSDESCIDLE)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(sel));
+ if (!PRES(r)) throw TRAP(SEG_NOT_PRESENT,IDXTBL(sel));
+ desc[2] |= 0x200; // mark busy
+ WriteWord(addr+4, desc[2]);
+ cpustate->tr.sel=sel;
+ cpustate->tr.limit=LIMIT(desc);
+ cpustate->tr.base=BASE(desc);
+ cpustate->tr.rights=RIGHTS(desc);
+ break;
+ case 0x20: /* verr */
+ tmp=GetRMWord(ModRM);
+ if ((addr = i80286_selector_address(cpustate,tmp)) == -1) cpustate->ZeroVal = 1;
+ else {
+ desc[2] = ReadWord(addr+4);
+ r = RIGHTS(desc);
+ cpustate->ZeroVal = i80286_verify(cpustate, tmp, I80286_READ, RIGHTS(desc));
+ cpustate->ZeroVal = cpustate->ZeroVal || (CODE(r) && CONF(r) ? 0 : (DPL(r)<PMAX(RPL(tmp),CPL)));
+ }
+ break;
+ case 0x28: /* verw */
+ tmp=GetRMWord(ModRM);
+ if ((addr = i80286_selector_address(cpustate,tmp)) == -1) cpustate->ZeroVal = 1;
+ else {
+ desc[2] = ReadWord(addr+4);
+ r = RIGHTS(desc);
+ cpustate->ZeroVal = i80286_verify(cpustate, tmp, I80286_WRITE, RIGHTS(desc));
+ cpustate->ZeroVal = cpustate->ZeroVal || (DPL(r)<PMAX(RPL(tmp),CPL));
+ }
+ break;
+ default:
+ throw TRAP(ILLEGAL_INSTRUCTION,-1);
+ break;
+ }
+ break;
+ case 1:
+ /* lgdt, lldt in protected mode privilege level 0 required else common protection
+ failure 0xd */
+ ModRM = FETCHOP;
+ switch (ModRM&0x38) {
+ case 0: /* sgdt */
+ PutRMWord(ModRM,cpustate->gdtr.limit);
+ PutRMWordOffset(2,cpustate->gdtr.base&0xffff);
+ PutRMWordOffset(4,0xff00|cpustate->gdtr.base>>16);
+ break;
+ case 8: /* sidt */
+ PutRMWord(ModRM,cpustate->idtr.limit);
+ PutRMWordOffset(2,cpustate->idtr.base&0xffff);
+ PutRMWordOffset(4,0xff00|cpustate->idtr.base>>16);
+ break;
+ case 0x10: /* lgdt */
+ if (PM&&(CPL!=0)) throw TRAP(GENERAL_PROTECTION_FAULT,0);
+ cpustate->gdtr.limit=GetRMWord(ModRM);
+ cpustate->gdtr.base=GetRMWordOffset(2)|(GetRMByteOffset(4)<<16);
+ break;
+ case 0x18: /* lidt */
+ if (PM&&(CPL!=0)) throw TRAP(GENERAL_PROTECTION_FAULT,0);
+ cpustate->idtr.limit=GetRMWord(ModRM);
+ cpustate->idtr.base=GetRMWordOffset(2)|(GetRMByteOffset(4)<<16);
+ break;
+ case 0x20: /* smsw */
+ PutRMWord(ModRM, cpustate->msw);
+ break;
+ case 0x30: /* lmsw */
+ if (PM&&(CPL!=0)) throw TRAP(GENERAL_PROTECTION_FAULT,0);
+ msw = GetRMWord(ModRM);
+ if (!PM&&(msw&1)) cpustate->sregs[CS] = IDX(cpustate->sregs[CS]); // cheat and set cpl to 0
+ cpustate->msw=(cpustate->msw&1)|msw;
+ break;
+ default:
+ throw TRAP(ILLEGAL_INSTRUCTION,-1);
+ break;
+ }
+ break;
+ case 2: /* LAR */
+ if (!PM) throw TRAP(ILLEGAL_INSTRUCTION,-1);
+ ModRM = FETCHOP;
+ tmp=GetRMWord(ModRM);
+ if ((addr = i80286_selector_address(cpustate,tmp)) == -1) cpustate->ZeroVal = 1;
+ else {
+ desc[2] = ReadWord(addr+4);
+ r = RIGHTS(desc);
+ if (DPL(r)>=PMAX(RPL(tmp),CPL)) {
+ cpustate->ZeroVal = 0;
+ // rights are expected to be in upper byte
+ RegWord(ModRM) = r << 8;
+ }
+ else
+ cpustate->ZeroVal = 1;
+ }
+ break;
+ case 3: /* LSL */
+ if (!PM) throw TRAP(ILLEGAL_INSTRUCTION,-1);
+ ModRM = FETCHOP;
+ tmp=GetRMWord(ModRM);
+ if ((addr = i80286_selector_address(cpustate,tmp)) == -1) cpustate->ZeroVal = 1;
+ else {
+ desc[2] = ReadWord(addr+4);
+ r = RIGHTS(desc);
+ if (!SEGDESC(r) && (GATE(r) >= CALLGATE)) cpustate->ZeroVal = 1; // not valid for gates
+ else if (DPL(r)>=PMAX(RPL(tmp),CPL)) {
+ cpustate->ZeroVal = 0;
+ RegWord(ModRM) = ReadWord(addr);
+ }
+ else
+ cpustate->ZeroVal = 1;
+ }
+ break;
+ case 5: /* loadall */
+ if (PM&&(CPL!=0)) throw TRAP(GENERAL_PROTECTION_FAULT,0);
+ cpustate->msw = (cpustate->msw&1)|ReadWord(0x806);
+ cpustate->tr.sel = ReadWord(0x816);
+ tmp = ReadWord(0x818);
+ ExpandFlags(tmp);
+ cpustate->flags = tmp;
+ cpustate->flags = CompressFlags();
+ cpustate->pc = ReadWord(0x81a);
+ cpustate->ldtr.sel = ReadWord(0x81c);
+ cpustate->sregs[DS] = ReadWord(0x81e);
+ cpustate->sregs[SS] = ReadWord(0x820);
+ cpustate->sregs[CS] = ReadWord(0x822);
+ cpustate->sregs[ES] = ReadWord(0x824);
+ cpustate->regs.w[DI] = ReadWord(0x826);
+ cpustate->regs.w[SI] = ReadWord(0x828);
+ cpustate->regs.w[BP] = ReadWord(0x82a);
+ cpustate->regs.w[SP] = ReadWord(0x82c);
+ cpustate->regs.w[BX] = ReadWord(0x82e);
+ cpustate->regs.w[DX] = ReadWord(0x830);
+ cpustate->regs.w[CX] = ReadWord(0x832);
+ cpustate->regs.w[AX] = ReadWord(0x834);
+// loadall uses base-rights-limit order
+#define LOADDESC(addr, sreg) { desc[1] = ReadWord(addr); desc[2] = ReadWord(addr+2); desc[0] = ReadWord(addr+4); \
+ cpustate->base[sreg] = BASE(desc); cpustate->rights[sreg] = RIGHTS(desc); \
+ cpustate->limit[sreg] = LIMIT(desc); }
+ LOADDESC(0x836, ES);
+ LOADDESC(0x83C, CS);
+ LOADDESC(0x842, SS);
+ LOADDESC(0x848, DS);
+#undef LOADDESC
+// void cast supresses warning
+#define LOADDESC(addr, reg, r) { desc[1] = ReadWord(addr); desc[2] = ReadWord(addr+2); desc[0] = ReadWord(addr+4); \
+ cpustate->reg.base = BASE(desc); (void)(r); cpustate->reg.limit = LIMIT(desc); }
+ LOADDESC(0x84e, gdtr, 1);
+ LOADDESC(0x854, ldtr, cpustate->ldtr.rights = RIGHTS(desc));
+ LOADDESC(0x85a, idtr, 1);
+ LOADDESC(0x860, tr, cpustate->tr.rights = RIGHTS(desc));
+#undef LOADDESC
+ cpustate->pc = (cpustate->pc + cpustate->base[CS]) & AMASK;
+ CHANGE_PC(cpustate->pc);
+ break;
+
+ case 6: /* clts */
+ if (PM&&(CPL!=0)) throw TRAP(GENERAL_PROTECTION_FAULT,0);
+ cpustate->msw&=~8;
+ break;
+ default:
+ throw TRAP(ILLEGAL_INSTRUCTION,-1);
+ break;
+ }
+}
+
+static void PREFIX286(_arpl)(i8086_state *cpustate) /* 0x63 */
+{
+ UINT16 ModRM, tmp, source;
+ if (!PM) throw TRAP(ILLEGAL_INSTRUCTION,-1);
+
+ ModRM=FETCHOP;
+ tmp=GetRMWord(ModRM);
+ source=RegWord(ModRM);
+
+ if (RPL(tmp)<RPL(source))
+ {
+ cpustate->ZeroVal = 0;
+ PutbackRMWord(ModRM, IDXTBL(tmp)|RPL(source));
+ }
+ else
+ cpustate->ZeroVal = 1;
+}
+
+static void i80286_load_flags(i8086_state *cpustate, UINT16 flags, int cpl)
+{
+ cpustate->flags = CompressFlags();
+ if(PM && cpl) {
+ UINT16 mask = 0x3000;
+ if(cpl>IOPL) mask |= 0x200;
+ flags &= ~mask;
+ flags |= (cpustate->flags & mask);
+ }
+ else if(!PM) (flags &= ~0xf000);
+ ExpandFlags(flags);
+ cpustate->flags = flags;
+
+ if (cpustate->TF) PREFIX(_trap)(cpustate);
+ /* if the IF is set, and an interrupt is pending, signal an interrupt */
+ if (cpustate->IF && cpustate->irq_state)
+ i80286_interrupt_descriptor(cpustate, (*cpustate->irq_callback)(cpustate->device, 0), 2, -1);
+}
+
+static void PREFIX286(_popf)(i8086_state *cpustate)
+{
+ UINT16 flags;
+ POP(flags);
+ ICOUNT -= timing.popf;
+ i80286_load_flags(cpustate, flags, CPL);
+}
+
+static UINT16 i80286_far_return(i8086_state *cpustate, int iret, int bytes)
+{
+ UINT16 sel, off, flags = 0;
+ int spaddr;
+
+ if (PM && NT && iret) {
+ i80286_switch_task(cpustate, ReadWord(cpustate->tr.base+TSS_BACK*2), IRET);
+ return cpustate->flags;
+ }
+
+ // must be restartable
+ if(PM) i80286_check_permission(cpustate, SS, cpustate->regs.w[SP], (iret?6:4), I80286_READ);
+ spaddr = (cpustate->base[SS] + cpustate->regs.w[SP]) & AMASK;
+ off = ReadWord(spaddr);
+ sel = ReadWord(spaddr+2);
+ if(iret) flags = ReadWord(spaddr+4);
+
+ if(PM) {
+ UINT16 desc[3], newsp, newss;
+ int addr, r;
+
+ if ((addr = i80286_selector_address(cpustate,sel)) == -1)
+ throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(sel));
+
+ if (RPL(sel)<CPL) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(sel));
+ desc[0] = ReadWord(addr);
+ desc[1] = ReadWord(addr+2);
+ desc[2] = ReadWord(addr+4);
+ r = RIGHTS(desc);
+
+ if (!CODE(r) || !SEGDESC(r)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(sel));
+ if (CONF(r)) { if(DPL(r)>RPL(sel)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(sel)); }
+ else if (DPL(r)!=RPL(sel)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(sel));
+
+ if (!PRES(r)) throw TRAP(SEG_NOT_PRESENT,IDXTBL(sel));
+ if (off > LIMIT(desc)) throw TRAP(GENERAL_PROTECTION_FAULT,0);
+ if (CPL<RPL(sel)) {
+ i80286_check_permission(cpustate, SS, cpustate->regs.w[SP]+(iret?6:4)+bytes, 4, I80286_READ);
+ newsp = ReadWord(spaddr+((iret?6:4)+bytes));
+ newss = ReadWord(spaddr+((iret?8:6)+bytes));
+ i80286_data_descriptor_full(cpustate, SS, newss, RPL(sel), TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(newss)), 0, 0);
+ cpustate->regs.w[SP] = newsp + bytes;
+ } else cpustate->regs.w[SP] += (iret?6:4) + bytes;
+ SET_ACC(desc);
+ WriteWord(addr+4, desc[2]);
+ cpustate->sregs[CS]=sel;
+ cpustate->limit[CS]=LIMIT(desc);
+ cpustate->base[CS]=BASE(desc);
+ cpustate->rights[CS]=RIGHTS(desc);
+ cpustate->pc=(cpustate->base[CS]+off)&AMASK;
+
+ // docs say check rpl but windows doesn't like it
+ r = cpustate->rights[DS];
+ if (i80286_verify(cpustate, cpustate->sregs[DS], I80286_READ, r) || (CODE(r) && CONF(r) ? 0 : (DPL(r) < CPL)))
+ i80286_data_descriptor(cpustate, DS, 0);
+ r = cpustate->rights[ES];
+ if (i80286_verify(cpustate, cpustate->sregs[ES], I80286_READ, r) || (CODE(r) && CONF(r) ? 0 : (DPL(r) < CPL)))
+ i80286_data_descriptor(cpustate, ES, 0);
+ } else {
+ cpustate->regs.w[SP] += (iret?6:4) + bytes;
+ cpustate->sregs[CS]=sel;
+ cpustate->base[CS]=sel<<4;
+ cpustate->rights[CS]=0x9a;
+ cpustate->limit[CS]=0xffff;
+ cpustate->pc=(cpustate->base[CS]+off)&AMASK;
+ }
+ CHANGE_PC(cpustate->pc);
+
+ return flags;
+}
+
+static void PREFIX286(_iret)(i8086_state *cpustate)
+{
+ int oldcpl = (PM)?CPL:0;
+ UINT16 flags = i80286_far_return(cpustate, 1, 0);
+ ICOUNT -= timing.iret;
+ i80286_load_flags(cpustate, flags, oldcpl);
+}
+
+static void PREFIX286(_retf_d16)(i8086_state *cpustate)
+{
+ unsigned count = FETCH;
+ count += FETCH << 8;
+ i80286_far_return(cpustate, 0, count);
+ ICOUNT -= timing.ret_far_imm;
+}
+
+static void PREFIX286(_retf)(i8086_state *cpustate)
+{
+ i80286_far_return(cpustate, 0, 0);
+ ICOUNT -= timing.ret_far;
+}
+
+static void PREFIX286(_escape)(i8086_state *cpustate) /* Opcodes 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde */
+{
+ if ((cpustate->msw&8) || (cpustate->msw&4)) throw TRAP(FPU_UNAVAILABLE,-1);
+ unsigned ModRM = FETCH;
+ ICOUNT -= timing.nop;
+ GetRMByte(ModRM);
+}
+
+static void PREFIX286(_escape_7)(i8086_state *cpustate) /* Opcode 0xdf */
+{
+ if ((cpustate->msw&8) || (cpustate->msw&4)) throw TRAP(FPU_UNAVAILABLE,-1);
+ unsigned ModRM = FETCH;
+ ICOUNT -= timing.nop;
+ GetRMByte(ModRM);
+ if (ModRM == 0xe0) cpustate->regs.w[AX] = 0xffff; // FPU not present
+}
+
+static void i80286_check_permission(i8086_state *cpustate, UINT8 check_seg, UINT32 offset, UINT16 size, i80286_operation operation)
+{
+ int trap = 0;
+ UINT8 rights;
+ if (PM) {
+ rights = cpustate->rights[check_seg];
+ trap = i80286_verify(cpustate, cpustate->sregs[check_seg], operation, rights);
+ if ((CODE(rights) || !EXPDOWN(rights)) && ((offset+size-1) > cpustate->limit[check_seg])) trap = GENERAL_PROTECTION_FAULT;
+ if (!CODE(rights) && EXPDOWN(rights) && ((offset <= cpustate->limit[check_seg]) || ((offset+size-1) > 0xffff))) trap = GENERAL_PROTECTION_FAULT;
+
+ if ((trap == GENERAL_PROTECTION_FAULT) && (check_seg == SS)) trap = STACK_FAULT;
+ if (trap) throw TRAP(trap, 0);
+ }
+}
+
diff --git a/trunk/src/emu/cpu/i86/instr286.h b/trunk/src/emu/cpu/i86/instr286.h
new file mode 100644
index 00000000000..eeb582b67e9
--- /dev/null
+++ b/trunk/src/emu/cpu/i86/instr286.h
@@ -0,0 +1,48 @@
+#define DIVIDE_BY_ZERO 0
+#define SINGLE_STEP 1
+#define NMI 2
+#define BREAK 3
+#define INTO_OVERFLOW 4
+#define BOUND_OVERRUN 5
+#define ILLEGAL_INSTRUCTION 6
+#define FPU_UNAVAILABLE 7
+#define DOUBLE_FAULT 8
+#define FPU_SEG_OVERRUN 9
+#define INVALID_TSS 10
+#define SEG_NOT_PRESENT 11
+#define STACK_FAULT 12
+#define GENERAL_PROTECTION_FAULT 13
+
+#define CPL (cpustate->sregs[CS]&3)
+#define PM (cpustate->msw&1)
+
+static void i80286_trap2(i80286_state *cpustate,UINT32 error);
+static void i80286_interrupt_descriptor(i80286_state *cpustate,UINT16 number, int trap, int error);
+static void i80286_code_descriptor(i80286_state *cpustate,UINT16 selector, UINT16 offset, int gate);
+static void i80286_data_descriptor(i80286_state *cpustate,int reg, UINT16 selector);
+static void PREFIX286(_0fpre)(i80286_state *cpustate);
+static void PREFIX286(_arpl)(i80286_state *cpustate);
+static void PREFIX286(_escape_7)(i8086_state *cpustate);
+static void i80286_pop_seg(i80286_state *cpustate,int reg);
+static void i80286_load_flags(i80286_state *cpustate, UINT16 flags, int cpl);
+
+enum i80286_size
+{
+ I80286_BYTE = 1,
+ I80286_WORD = 2
+};
+
+enum i80286_operation
+{
+ I80286_READ = 1,
+ I80286_WRITE,
+ I80286_EXECUTE
+};
+
+static void i80286_check_permission(i8086_state *cpustate, UINT8 check_seg, UINT32 offset, UINT16 size, i80286_operation operation);
+
+static inline UINT32 GetMemAddr(i80286_state *cpustate, UINT8 seg, UINT32 off, UINT16 size, i80286_operation op) {
+ seg = DefaultSeg(seg);
+ if(PM) i80286_check_permission(cpustate, seg, off, size, op);
+ return (cpustate->base[seg] + off) & AMASK;
+}
diff --git a/trunk/src/emu/cpu/i86/instr86.c b/trunk/src/emu/cpu/i86/instr86.c
new file mode 100644
index 00000000000..005683de848
--- /dev/null
+++ b/trunk/src/emu/cpu/i86/instr86.c
@@ -0,0 +1,3295 @@
+/****************************************************************************
+* real mode i286 emulator v1.4 by Fabrice Frances *
+* (initial work based on David Hedley's pcemu) *
+****************************************************************************/
+
+/*
+ * file will be included in all cpu variants
+ * put non i86 instructions in own files (i286, i386, nec)
+ * function renaming will be added when necessary
+ * timing value should move to separate array
+ */
+
+/*
+ PHS - 2010-12-29
+
+ Moved several instruction stubs so that they are compiled separately for
+ the 8086 and 80186. The instructions affected are :
+
+ _pop_ss, _es, _cs, _ss, _ds, _mov_sregw and _sti
+
+ This is because they call the next instruction directly as it cannot be
+ interrupted. If they are not compiled separately when executing on an
+ 80186, the wrong set of instructions are used (the 8086 set). This has
+ the serious effect of ignoring the next instruction, as invalid, *IF*
+ it is an 80186 specific instruction.
+
+*/
+
+#undef ICOUNT
+
+#define ICOUNT cpustate->icount
+
+
+#if !defined(I80186)
+static void PREFIX86(_interrupt)(i8086_state *cpustate, unsigned int_num)
+{
+ unsigned dest_seg, dest_off;
+ WORD ip = cpustate->pc - cpustate->base[CS];
+
+ if (int_num == -1)
+ int_num = (*cpustate->irq_callback)(cpustate->device, 0);
+
+#ifdef I80286
+ if (PM) {
+ i80286_interrupt_descriptor(cpustate, int_num, 0, 0);
+ } else {
+#endif
+ dest_off = ReadWord(int_num*4);
+ dest_seg = ReadWord(int_num*4+2);
+
+ PREFIX(_pushf(cpustate));
+ cpustate->TF = cpustate->IF = 0;
+ PUSH(cpustate->sregs[CS]);
+ PUSH(ip);
+ cpustate->sregs[CS] = (WORD)dest_seg;
+ cpustate->base[CS] = SegBase(CS);
+ cpustate->pc = (cpustate->base[CS] + dest_off) & AMASK;
+ CHANGE_PC(cpustate->pc);
+#ifdef I80286
+ }
+#endif
+ cpustate->extra_cycles += timing.exception;
+}
+
+static void PREFIX86(_trap)(i8086_state *cpustate)
+{
+ PREFIX(_instruction)[FETCHOP](cpustate);
+ PREFIX(_interrupt)(cpustate, 1);
+}
+#endif
+
+#ifndef I80186
+static void PREFIX86(_rotate_shift_Byte)(i8086_state *cpustate, unsigned ModRM, unsigned count, unsigned src)
+{
+// unsigned src = (unsigned)GetRMByte(ModRM);
+ unsigned dst=src;
+
+ if (count==0)
+ {
+ ICOUNT -= (ModRM >= 0xc0) ? timing.rot_reg_base : timing.rot_m8_base;
+ }
+ else if (count==1)
+ {
+ ICOUNT -= (ModRM >= 0xc0) ? timing.rot_reg_1 : timing.rot_m8_1;
+
+ switch (ModRM & 0x38)
+ {
+ case 0x00: /* ROL eb,1 */
+ cpustate->CarryVal = src & 0x80;
+ dst=(src<<1)+CF;
+ PutbackRMByte(ModRM,dst);
+ cpustate->OverVal = (src^dst)&0x80;
+ break;
+ case 0x08: /* ROR eb,1 */
+ cpustate->CarryVal = src & 0x01;
+ dst = ((CF<<8)+src) >> 1;
+ PutbackRMByte(ModRM,dst);
+ cpustate->OverVal = (src^dst)&0x80;
+ break;
+ case 0x10: /* RCL eb,1 */
+ dst=(src<<1)+CF;
+ PutbackRMByte(ModRM,dst);
+ SetCFB(dst);
+ cpustate->OverVal = (src^dst)&0x80;
+ break;
+ case 0x18: /* RCR eb,1 */
+ dst = ((CF<<8)+src) >> 1;
+ PutbackRMByte(ModRM,dst);
+ cpustate->CarryVal = src & 0x01;
+ cpustate->OverVal = (src^dst)&0x80;
+ break;
+ case 0x20: /* SHL eb,1 */
+ case 0x30:
+ dst = src << 1;
+ PutbackRMByte(ModRM,dst);
+ SetCFB(dst);
+ cpustate->OverVal = (src^dst)&0x80;
+ cpustate->AuxVal = 1;
+ SetSZPF_Byte(dst);
+ break;
+ case 0x28: /* SHR eb,1 */
+ dst = src >> 1;
+ PutbackRMByte(ModRM,dst);
+ cpustate->CarryVal = src & 0x01;
+ cpustate->OverVal = src & 0x80;
+ cpustate->AuxVal = 1;
+ SetSZPF_Byte(dst);
+ break;
+ case 0x38: /* SAR eb,1 */
+ dst = ((INT8)src) >> 1;
+ PutbackRMByte(ModRM,dst);
+ cpustate->CarryVal = src & 0x01;
+ cpustate->OverVal = 0;
+ cpustate->AuxVal = 1;
+ SetSZPF_Byte(dst);
+ break;
+ }
+ }
+ else
+ {
+ int tmpcf = CF;
+ ICOUNT -= (ModRM >= 0xc0) ? timing.rot_reg_base + timing.rot_reg_bit : timing.rot_m8_base + timing.rot_m8_bit;
+
+ switch (ModRM & 0x38)
+ {
+ case 0x00: /* ROL eb,count */
+ for (; count > 0; count--)
+ {
+ cpustate->CarryVal = dst & 0x80;
+ dst = (dst << 1) + CF;
+ }
+ PutbackRMByte(ModRM,(BYTE)dst);
+ break;
+ case 0x08: /* ROR eb,count */
+ for (; count > 0; count--)
+ {
+ cpustate->CarryVal = dst & 0x01;
+ dst = (dst >> 1) + (CF << 7);
+ }
+ PutbackRMByte(ModRM,(BYTE)dst);
+ break;
+ case 0x10: /* RCL eb,count */
+ for (; count > 0; count--)
+ {
+ dst = (dst << 1) + tmpcf;
+ tmpcf = (int)((dst & 0x100) != 0);
+ }
+ PutbackRMByte(ModRM,(BYTE)dst);
+ cpustate->CarryVal = tmpcf;
+ break;
+ case 0x18: /* RCR eb,count */
+ for (; count > 0; count--)
+ {
+ dst = (tmpcf<<8)+dst;
+ tmpcf = dst & 0x01;
+ dst >>= 1;
+ }
+ PutbackRMByte(ModRM,(BYTE)dst);
+ cpustate->CarryVal = tmpcf;
+ break;
+ case 0x20:
+ case 0x30: /* SHL eb,count */
+ for(int i=0;i<count;i++) dst<<= 1;
+ SetCFB(dst);
+ cpustate->AuxVal = 1;
+ SetSZPF_Byte(dst);
+ PutbackRMByte(ModRM,(BYTE)dst);
+ break;
+ case 0x28: /* SHR eb,count */
+ for(int i=0;i<count-1;i++) dst>>= 1;
+ cpustate->CarryVal = dst & 0x1;
+ dst >>= 1;
+ SetSZPF_Byte(dst);
+ cpustate->AuxVal = 1;
+ PutbackRMByte(ModRM,(BYTE)dst);
+ break;
+ case 0x38: /* SAR eb,count */
+ for(int i=0;i<count-1;i++) dst = ((INT8)dst) >> 1;
+ cpustate->CarryVal = dst & 0x1;
+ dst = ((INT8)((BYTE)dst)) >> 1;
+ SetSZPF_Byte(dst);
+ cpustate->AuxVal = 1;
+ PutbackRMByte(ModRM,(BYTE)dst);
+ break;
+ }
+ }
+}
+
+static void PREFIX86(_rotate_shift_Word)(i8086_state *cpustate, unsigned ModRM, unsigned count, unsigned src)
+{
+// unsigned src = GetRMWord(ModRM);
+ unsigned dst=src;
+
+ if (count==0)
+ {
+ ICOUNT -= (ModRM >= 0xc0) ? timing.rot_reg_base : timing.rot_m16_base;
+ }
+ else if (count==1)
+ {
+ ICOUNT -= (ModRM >= 0xc0) ? timing.rot_reg_1 : timing.rot_m16_1;
+
+ switch (ModRM & 0x38)
+ {
+#if 0
+ case 0x00: /* ROL ew,1 */
+ tmp2 = (tmp << 1) + CF;
+ SetCFW(tmp2);
+ cpustate->OverVal = !(!(tmp & 0x4000)) != CF;
+ PutbackRMWord(ModRM,tmp2);
+ break;
+ case 0x08: /* ROR ew,1 */
+ cpustate->CarryVal = tmp & 0x01;
+ tmp2 = (tmp >> 1) + ((unsigned)CF << 15);
+ cpustate->OverVal = !(!(tmp & 0x8000)) != CF;
+ PutbackRMWord(ModRM,tmp2);
+ break;
+ case 0x10: /* RCL ew,1 */
+ tmp2 = (tmp << 1) + CF;
+ SetCFW(tmp2);
+ cpustate->OverVal = (tmp ^ (tmp << 1)) & 0x8000;
+ PutbackRMWord(ModRM,tmp2);
+ break;
+ case 0x18: /* RCR ew,1 */
+ tmp2 = (tmp >> 1) + ((unsigned)CF << 15);
+ cpustate->OverVal = !(!(tmp & 0x8000)) != CF;
+ cpustate->CarryVal = tmp & 0x01;
+ PutbackRMWord(ModRM,tmp2);
+ break;
+ case 0x20: /* SHL ew,1 */
+ case 0x30:
+ tmp <<= 1;
+
+ SetCFW(tmp);
+ SetOFW_Add(tmp,tmp2,tmp2);
+ cpustate->AuxVal = 1;
+ SetSZPF_Word(tmp);
+
+ PutbackRMWord(ModRM,tmp);
+ break;
+ case 0x28: /* SHR ew,1 */
+ cpustate->CarryVal = tmp & 0x01;
+ cpustate->OverVal = tmp & 0x8000;
+
+ tmp2 = tmp >> 1;
+
+ SetSZPF_Word(tmp2);
+ cpustate->AuxVal = 1;
+ PutbackRMWord(ModRM,tmp2);
+ break;
+ case 0x38: /* SAR ew,1 */
+ cpustate->CarryVal = tmp & 0x01;
+ cpustate->OverVal = 0;
+
+ tmp2 = (tmp >> 1) | (tmp & 0x8000);
+
+ SetSZPF_Word(tmp2);
+ cpustate->AuxVal = 1;
+ PutbackRMWord(ModRM,tmp2);
+ break;
+#else
+ case 0x00: /* ROL ew,1 */
+ cpustate->CarryVal = src & 0x8000;
+ dst=(src<<1)+CF;
+ PutbackRMWord(ModRM,dst);
+ cpustate->OverVal = (src^dst)&0x8000;
+ break;
+ case 0x08: /* ROR ew,1 */
+ cpustate->CarryVal = src & 0x01;
+ dst = ((CF<<16)+src) >> 1;
+ PutbackRMWord(ModRM,dst);
+ cpustate->OverVal = (src^dst)&0x8000;
+ break;
+ case 0x10: /* RCL ew,1 */
+ dst=(src<<1)+CF;
+ PutbackRMWord(ModRM,dst);
+ SetCFW(dst);
+ cpustate->OverVal = (src^dst)&0x8000;
+ break;
+ case 0x18: /* RCR ew,1 */
+ dst = ((CF<<16)+src) >> 1;
+ PutbackRMWord(ModRM,dst);
+ cpustate->CarryVal = src & 0x01;
+ cpustate->OverVal = (src^dst)&0x8000;
+ break;
+ case 0x20: /* SHL ew,1 */
+ case 0x30:
+ dst = src << 1;
+ PutbackRMWord(ModRM,dst);
+ SetCFW(dst);
+ cpustate->OverVal = (src^dst)&0x8000;
+ cpustate->AuxVal = 1;
+ SetSZPF_Word(dst);
+ break;
+ case 0x28: /* SHR ew,1 */
+ dst = src >> 1;
+ PutbackRMWord(ModRM,dst);
+ cpustate->CarryVal = src & 0x01;
+ cpustate->OverVal = src & 0x8000;
+ cpustate->AuxVal = 1;
+ SetSZPF_Word(dst);
+ break;
+ case 0x38: /* SAR ew,1 */
+ dst = ((INT16)src) >> 1;
+ PutbackRMWord(ModRM,dst);
+ cpustate->CarryVal = src & 0x01;
+ cpustate->OverVal = 0;
+ cpustate->AuxVal = 1;
+ SetSZPF_Word(dst);
+ break;
+#endif
+ }
+ }
+ else
+ {
+ int tmpcf = CF;
+ ICOUNT -= (ModRM >= 0xc0) ? timing.rot_reg_base + timing.rot_reg_bit : timing.rot_m8_base + timing.rot_m16_bit;
+
+ switch (ModRM & 0x38)
+ {
+ case 0x00: /* ROL ew,count */
+ for (; count > 0; count--)
+ {
+ cpustate->CarryVal = dst & 0x8000;
+ dst = (dst << 1) + CF;
+ }
+ PutbackRMWord(ModRM,dst);
+ break;
+ case 0x08: /* ROR ew,count */
+ for (; count > 0; count--)
+ {
+ cpustate->CarryVal = dst & 0x01;
+ dst = (dst >> 1) + (CF << 15);
+ }
+ PutbackRMWord(ModRM,dst);
+ break;
+ case 0x10: /* RCL ew,count */
+ for (; count > 0; count--)
+ {
+ dst = (dst << 1) + tmpcf;
+ tmpcf = (int)((dst & 0x10000) != 0);
+ }
+ PutbackRMWord(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
+ break;
+ case 0x18: /* RCR ew,count */
+ for (; count > 0; count--)
+ {
+ dst = dst + (tmpcf << 16);
+ tmpcf = dst & 0x01;
+ dst >>= 1;
+ }
+ PutbackRMWord(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
+ break;
+ case 0x20:
+ case 0x30: /* SHL ew,count */
+ for(int i=0;i<count;i++) dst<<= 1;
+ SetCFW(dst);
+ cpustate->AuxVal = 1;
+ SetSZPF_Word(dst);
+ PutbackRMWord(ModRM,dst);
+ break;
+ case 0x28: /* SHR ew,count */
+ for(int i=0;i<count-1;i++) dst>>= 1;
+ cpustate->CarryVal = dst & 0x1;
+ dst >>= 1;
+ SetSZPF_Word(dst);
+ cpustate->AuxVal = 1;
+ PutbackRMWord(ModRM,dst);
+ break;
+ case 0x38: /* SAR ew,count */
+ for(int i=0;i<count-1;i++) dst = ((INT16)dst) >> 1;
+ cpustate->CarryVal = dst & 0x01;
+ dst = ((INT16)((WORD)dst)) >> 1;
+ SetSZPF_Word(dst);
+ cpustate->AuxVal = 1;
+ PutbackRMWord(ModRM,dst);
+ break;
+ }
+ }
+}
+#endif
+
+static void PREFIX(rep)(i8086_state *cpustate,int flagval)
+{
+ /* Handles rep- and repnz- prefixes. flagval is the value of ZF for the
+ loop to continue for CMPS and SCAS instructions. */
+
+ unsigned next = FETCHOP;
+
+ switch(next)
+ {
+ case 0x26: /* ES: */
+ cpustate->seg_prefix = TRUE;
+ cpustate->prefix_seg = ES;
+ if (!cpustate->rep_in_progress)
+ ICOUNT -= timing.override;
+ PREFIX(rep)(cpustate, flagval);
+ break;
+ case 0x2e: /* CS: */
+ cpustate->seg_prefix = TRUE;
+ cpustate->prefix_seg = CS;
+ if (!cpustate->rep_in_progress)
+ ICOUNT -= timing.override;
+ PREFIX(rep)(cpustate, flagval);
+ break;
+ case 0x36: /* SS: */
+ cpustate->seg_prefix = TRUE;
+ cpustate->prefix_seg = SS;
+ if (!cpustate->rep_in_progress)
+ ICOUNT -= timing.override;
+ PREFIX(rep)(cpustate, flagval);
+ break;
+ case 0x3e: /* DS: */
+ cpustate->seg_prefix = TRUE;
+ cpustate->prefix_seg = DS;
+ if (!cpustate->rep_in_progress)
+ ICOUNT -= timing.override;
+ PREFIX(rep)(cpustate, flagval);
+ break;
+#ifndef I8086
+ case 0x6c: /* REP INSB */
+#ifdef I80286
+ if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
+#endif
+ if (!cpustate->rep_in_progress)
+ ICOUNT -= timing.rep_ins8_base;
+ cpustate->rep_in_progress = FALSE;
+ while(cpustate->regs.w[CX])
+ {
+ if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
+ PutMemB(ES,cpustate->regs.w[DI],read_port_byte(cpustate->regs.w[DX]));
+ cpustate->regs.w[CX]--;
+ cpustate->regs.w[DI] += cpustate->DirVal;
+ ICOUNT -= timing.rep_ins8_count;
+ }
+ break;
+ case 0x6d: /* REP INSW */
+#ifdef I80286
+ if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
+#endif
+ if (!cpustate->rep_in_progress)
+ ICOUNT -= timing.rep_ins16_base;
+ cpustate->rep_in_progress = FALSE;
+ while(cpustate->regs.w[CX])
+ {
+ if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
+ PutMemW(ES,cpustate->regs.w[DI],read_port_word(cpustate->regs.w[DX]));
+ cpustate->regs.w[CX]--;
+ cpustate->regs.w[DI] += 2 * cpustate->DirVal;
+ ICOUNT -= timing.rep_ins16_count;
+ }
+ break;
+ case 0x6e: /* REP OUTSB */
+#ifdef I80286
+ if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
+#endif
+ if (!cpustate->rep_in_progress)
+ ICOUNT -= timing.rep_outs8_base;
+ cpustate->rep_in_progress = FALSE;
+ while(cpustate->regs.w[CX])
+ {
+ if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
+ write_port_byte(cpustate->regs.w[DX],GetMemB(DS,cpustate->regs.w[SI]));
+ cpustate->regs.w[CX]--;
+ cpustate->regs.w[SI] += cpustate->DirVal; /* GOL 11/27/01 */
+ ICOUNT -= timing.rep_outs8_count;
+ }
+ break;
+ case 0x6f: /* REP OUTSW */
+#ifdef I80286
+ if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
+#endif
+ if (!cpustate->rep_in_progress)
+ ICOUNT -= timing.rep_outs16_base;
+ cpustate->rep_in_progress = FALSE;
+ while(cpustate->regs.w[CX])
+ {
+ if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
+ write_port_word(cpustate->regs.w[DX],GetMemW(DS,cpustate->regs.w[SI]));
+ cpustate->regs.w[CX]--;
+ cpustate->regs.w[SI] += 2 * cpustate->DirVal; /* GOL 11/27/01 */
+ ICOUNT -= timing.rep_outs16_count;
+ }
+ break;
+#endif
+ case 0xa4: /* REP MOVSB */
+ if (!cpustate->rep_in_progress)
+ ICOUNT -= timing.rep_movs8_base;
+ cpustate->rep_in_progress = FALSE;
+ while(cpustate->regs.w[CX])
+ {
+ BYTE tmp;
+
+ if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
+ tmp = GetMemB(DS,cpustate->regs.w[SI]);
+ PutMemB(ES,cpustate->regs.w[DI], tmp);
+ cpustate->regs.w[CX]--;
+ cpustate->regs.w[DI] += cpustate->DirVal;
+ cpustate->regs.w[SI] += cpustate->DirVal;
+ ICOUNT -= timing.rep_movs8_count;
+ }
+ break;
+ case 0xa5: /* REP MOVSW */
+ if (!cpustate->rep_in_progress)
+ ICOUNT -= timing.rep_movs16_base;
+ cpustate->rep_in_progress = FALSE;
+ while(cpustate->regs.w[CX])
+ {
+ WORD tmp;
+
+ if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
+ tmp = GetMemW(DS,cpustate->regs.w[SI]);
+ PutMemW(ES,cpustate->regs.w[DI], tmp);
+ cpustate->regs.w[CX]--;
+ cpustate->regs.w[DI] += 2 * cpustate->DirVal;
+ cpustate->regs.w[SI] += 2 * cpustate->DirVal;
+ ICOUNT -= timing.rep_movs16_count;
+ }
+ break;
+ case 0xa6: /* REP(N)E CMPSB */
+ if (!cpustate->rep_in_progress)
+ ICOUNT -= timing.rep_cmps8_base;
+ cpustate->rep_in_progress = FALSE;
+ cpustate->ZeroVal = !flagval;
+ while(cpustate->regs.w[CX] && (ZF == flagval))
+ {
+ unsigned dst, src;
+
+ if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
+ dst = GetMemB(ES, cpustate->regs.w[DI]);
+ src = GetMemB(DS, cpustate->regs.w[SI]);
+ SUBB(src,dst); /* opposite of the usual convention */
+ cpustate->regs.w[CX]--;
+ cpustate->regs.w[DI] += cpustate->DirVal;
+ cpustate->regs.w[SI] += cpustate->DirVal;
+ ICOUNT -= timing.rep_cmps8_count;
+ }
+ break;
+ case 0xa7: /* REP(N)E CMPSW */
+ if (!cpustate->rep_in_progress)
+ ICOUNT -= timing.rep_cmps16_base;
+ cpustate->rep_in_progress = FALSE;
+ cpustate->ZeroVal = !flagval;
+ while(cpustate->regs.w[CX] && (ZF == flagval))
+ {
+ unsigned dst, src;
+
+ if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
+ dst = GetMemW(ES, cpustate->regs.w[DI]);
+ src = GetMemW(DS, cpustate->regs.w[SI]);
+ SUBW(src,dst); /* opposite of the usual convention */
+ cpustate->regs.w[CX]--;
+ cpustate->regs.w[DI] += 2 * cpustate->DirVal;
+ cpustate->regs.w[SI] += 2 * cpustate->DirVal;
+ ICOUNT -= timing.rep_cmps16_count;
+ }
+ break;
+ case 0xaa: /* REP STOSB */
+ if (!cpustate->rep_in_progress)
+ ICOUNT -= timing.rep_stos8_base;
+ cpustate->rep_in_progress = FALSE;
+ while(cpustate->regs.w[CX])
+ {
+ if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
+ PutMemB(ES,cpustate->regs.w[DI],cpustate->regs.b[AL]);
+ cpustate->regs.w[CX]--;
+ cpustate->regs.w[DI] += cpustate->DirVal;
+ ICOUNT -= timing.rep_stos8_count;
+ }
+ break;
+ case 0xab: /* REP STOSW */
+ if (!cpustate->rep_in_progress)
+ ICOUNT -= timing.rep_stos16_base;
+ cpustate->rep_in_progress = FALSE;
+ while(cpustate->regs.w[CX])
+ {
+ if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
+ PutMemW(ES,cpustate->regs.w[DI],cpustate->regs.w[AX]);
+ cpustate->regs.w[CX]--;
+ cpustate->regs.w[DI] += 2 * cpustate->DirVal;
+ ICOUNT -= timing.rep_stos16_count;
+ }
+ break;
+ case 0xac: /* REP LODSB */
+ if (!cpustate->rep_in_progress)
+ ICOUNT -= timing.rep_lods8_base;
+ cpustate->rep_in_progress = FALSE;
+ while(cpustate->regs.w[CX])
+ {
+ if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
+ cpustate->regs.b[AL] = GetMemB(DS,cpustate->regs.w[SI]);
+ cpustate->regs.w[CX]--;
+ cpustate->regs.w[SI] += cpustate->DirVal;
+ ICOUNT -= timing.rep_lods8_count;
+ }
+ break;
+ case 0xad: /* REP LODSW */
+ if (!cpustate->rep_in_progress)
+ ICOUNT -= timing.rep_lods16_base;
+ cpustate->rep_in_progress = FALSE;
+ while(cpustate->regs.w[CX])
+ {
+ if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
+ cpustate->regs.w[AX] = GetMemW(DS,cpustate->regs.w[SI]);
+ cpustate->regs.w[CX]--;
+ cpustate->regs.w[SI] += 2 * cpustate->DirVal;
+ ICOUNT -= timing.rep_lods16_count;
+ }
+ break;
+ case 0xae: /* REP(N)E SCASB */
+ if (!cpustate->rep_in_progress)
+ ICOUNT -= timing.rep_scas8_base;
+ cpustate->rep_in_progress = FALSE;
+ cpustate->ZeroVal = !flagval;
+ while(cpustate->regs.w[CX] && (ZF == flagval))
+ {
+ unsigned src, dst;
+
+ if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
+ src = GetMemB(ES, cpustate->regs.w[DI]);
+ dst = cpustate->regs.b[AL];
+ SUBB(dst,src);
+ cpustate->regs.w[CX]--;
+ cpustate->regs.w[DI] += cpustate->DirVal;
+ ICOUNT -= timing.rep_scas8_count;
+ }
+ break;
+ case 0xaf: /* REP(N)E SCASW */
+ if (!cpustate->rep_in_progress)
+ ICOUNT -= timing.rep_scas16_base;
+ cpustate->rep_in_progress = FALSE;
+ cpustate->ZeroVal = !flagval;
+ while(cpustate->regs.w[CX] && (ZF == flagval))
+ {
+ unsigned src, dst;
+
+ if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }
+ src = GetMemW(ES, cpustate->regs.w[DI]);
+ dst = cpustate->regs.w[AX];
+ SUBW(dst,src);
+ cpustate->regs.w[CX]--;
+ cpustate->regs.w[DI] += 2 * cpustate->DirVal;
+ ICOUNT -= timing.rep_scas16_count;
+ }
+ break;
+ default:
+ PREFIX(_instruction)[next](cpustate);
+ }
+}
+
+#ifndef I80186
+static void PREFIX86(_add_br8)(i8086_state *cpustate) /* Opcode 0x00 */
+{
+ DEF_br8(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
+ ADDB(dst,src);
+ PutbackRMByte(ModRM,dst);
+}
+
+static void PREFIX86(_add_wr16)(i8086_state *cpustate) /* Opcode 0x01 */
+{
+ DEF_wr16(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
+ ADDW(dst,src);
+ PutbackRMWord(ModRM,dst);
+}
+
+static void PREFIX86(_add_r8b)(i8086_state *cpustate) /* Opcode 0x02 */
+{
+ DEF_r8b(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
+ ADDB(dst,src);
+ RegByte(ModRM)=dst;
+}
+
+static void PREFIX86(_add_r16w)(i8086_state *cpustate) /* Opcode 0x03 */
+{
+ DEF_r16w(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
+ ADDW(dst,src);
+ RegWord(ModRM)=dst;
+}
+
+
+static void PREFIX86(_add_ald8)(i8086_state *cpustate) /* Opcode 0x04 */
+{
+ DEF_ald8(dst,src);
+ ICOUNT -= timing.alu_ri8;
+ ADDB(dst,src);
+ cpustate->regs.b[AL]=dst;
+}
+
+
+static void PREFIX86(_add_axd16)(i8086_state *cpustate) /* Opcode 0x05 */
+{
+ DEF_axd16(dst,src);
+ ICOUNT -= timing.alu_ri16;
+ ADDW(dst,src);
+ cpustate->regs.w[AX]=dst;
+}
+
+
+static void PREFIX86(_push_es)(i8086_state *cpustate) /* Opcode 0x06 */
+{
+ ICOUNT -= timing.push_seg;
+ PUSH(cpustate->sregs[ES]);
+}
+
+
+static void PREFIX86(_pop_es)(i8086_state *cpustate) /* Opcode 0x07 */
+{
+#ifdef I80286
+ i80286_pop_seg(cpustate,ES);
+#else
+ POP(cpustate->sregs[ES]);
+ cpustate->base[ES] = SegBase(ES);
+#endif
+ ICOUNT -= timing.pop_seg;
+}
+
+static void PREFIX86(_or_br8)(i8086_state *cpustate) /* Opcode 0x08 */
+{
+ DEF_br8(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
+ ORB(dst,src);
+ PutbackRMByte(ModRM,dst);
+}
+
+static void PREFIX86(_or_wr16)(i8086_state *cpustate) /* Opcode 0x09 */
+{
+ DEF_wr16(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
+ ORW(dst,src);
+ PutbackRMWord(ModRM,dst);
+}
+
+static void PREFIX86(_or_r8b)(i8086_state *cpustate) /* Opcode 0x0a */
+{
+ DEF_r8b(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
+ ORB(dst,src);
+ RegByte(ModRM)=dst;
+}
+
+static void PREFIX86(_or_r16w)(i8086_state *cpustate) /* Opcode 0x0b */
+{
+ DEF_r16w(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
+ ORW(dst,src);
+ RegWord(ModRM)=dst;
+}
+
+static void PREFIX86(_or_ald8)(i8086_state *cpustate) /* Opcode 0x0c */
+{
+ DEF_ald8(dst,src);
+ ICOUNT -= timing.alu_ri8;
+ ORB(dst,src);
+ cpustate->regs.b[AL]=dst;
+}
+
+static void PREFIX86(_or_axd16)(i8086_state *cpustate) /* Opcode 0x0d */
+{
+ DEF_axd16(dst,src);
+ ICOUNT -= timing.alu_ri16;
+ ORW(dst,src);
+ cpustate->regs.w[AX]=dst;
+}
+
+static void PREFIX86(_push_cs)(i8086_state *cpustate) /* Opcode 0x0e */
+{
+ ICOUNT -= timing.push_seg;
+ PUSH(cpustate->sregs[CS]);
+}
+
+#ifndef I80286
+static void PREFIX86(_pop_cs)(i8086_state *cpustate) /* Opcode 0x0f */
+{
+ int ip = cpustate->pc - cpustate->base[CS];
+ ICOUNT -= timing.push_seg;
+ POP(cpustate->sregs[CS]);
+ cpustate->base[CS] = SegBase(CS);
+ cpustate->pc = (ip + cpustate->base[CS]) & AMASK;
+ CHANGE_PC(cpustate->pc);
+}
+#endif
+
+static void PREFIX86(_adc_br8)(i8086_state *cpustate) /* Opcode 0x10 */
+{
+ int tmpcf;
+ DEF_br8(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
+ src+=CF;
+ ADCB(dst,src,tmpcf);
+ PutbackRMByte(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
+}
+
+static void PREFIX86(_adc_wr16)(i8086_state *cpustate) /* Opcode 0x11 */
+{
+ int tmpcf;
+ DEF_wr16(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
+ src+=CF;
+ ADCW(dst,src,tmpcf);
+ PutbackRMWord(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
+}
+
+static void PREFIX86(_adc_r8b)(i8086_state *cpustate) /* Opcode 0x12 */
+{
+ DEF_r8b(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
+ src+=CF;
+ ADDB(dst,src);
+ RegByte(ModRM)=dst;
+}
+
+static void PREFIX86(_adc_r16w)(i8086_state *cpustate) /* Opcode 0x13 */
+{
+ DEF_r16w(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
+ src+=CF;
+ ADDW(dst,src);
+ RegWord(ModRM)=dst;
+}
+
+static void PREFIX86(_adc_ald8)(i8086_state *cpustate) /* Opcode 0x14 */
+{
+ DEF_ald8(dst,src);
+ ICOUNT -= timing.alu_ri8;
+ src+=CF;
+ ADDB(dst,src);
+ cpustate->regs.b[AL] = dst;
+}
+
+static void PREFIX86(_adc_axd16)(i8086_state *cpustate) /* Opcode 0x15 */
+{
+ DEF_axd16(dst,src);
+ ICOUNT -= timing.alu_ri16;
+ src+=CF;
+ ADDW(dst,src);
+ cpustate->regs.w[AX]=dst;
+}
+
+static void PREFIX86(_push_ss)(i8086_state *cpustate) /* Opcode 0x16 */
+{
+ PUSH(cpustate->sregs[SS]);
+ ICOUNT -= timing.push_seg;
+}
+
+static void PREFIX86(_sbb_br8)(i8086_state *cpustate) /* Opcode 0x18 */
+{
+ int tmpcf;
+ DEF_br8(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
+ src+=CF;
+ SBBB(dst,src,tmpcf);
+ PutbackRMByte(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
+}
+
+static void PREFIX86(_sbb_wr16)(i8086_state *cpustate) /* Opcode 0x19 */
+{
+ int tmpcf;
+ DEF_wr16(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
+ src+=CF;
+ SBBW(dst,src,tmpcf);
+ PutbackRMWord(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
+}
+
+static void PREFIX86(_sbb_r8b)(i8086_state *cpustate) /* Opcode 0x1a */
+{
+ DEF_r8b(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
+ src+=CF;
+ SUBB(dst,src);
+ RegByte(ModRM)=dst;
+}
+
+static void PREFIX86(_sbb_r16w)(i8086_state *cpustate) /* Opcode 0x1b */
+{
+ DEF_r16w(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
+ src+=CF;
+ SUBW(dst,src);
+ RegWord(ModRM)= dst;
+}
+
+static void PREFIX86(_sbb_ald8)(i8086_state *cpustate) /* Opcode 0x1c */
+{
+ DEF_ald8(dst,src);
+ ICOUNT -= timing.alu_ri8;
+ src+=CF;
+ SUBB(dst,src);
+ cpustate->regs.b[AL] = dst;
+}
+
+static void PREFIX86(_sbb_axd16)(i8086_state *cpustate) /* Opcode 0x1d */
+{
+ DEF_axd16(dst,src);
+ ICOUNT -= timing.alu_ri16;
+ src+=CF;
+ SUBW(dst,src);
+ cpustate->regs.w[AX]=dst;
+}
+
+static void PREFIX86(_push_ds)(i8086_state *cpustate) /* Opcode 0x1e */
+{
+ PUSH(cpustate->sregs[DS]);
+ ICOUNT -= timing.push_seg;
+}
+
+static void PREFIX86(_pop_ds)(i8086_state *cpustate) /* Opcode 0x1f */
+{
+#ifdef I80286
+ i80286_pop_seg(cpustate,DS);
+#else
+ POP(cpustate->sregs[DS]);
+ cpustate->base[DS] = SegBase(DS);
+#endif
+ ICOUNT -= timing.push_seg;
+}
+
+static void PREFIX86(_and_br8)(i8086_state *cpustate) /* Opcode 0x20 */
+{
+ DEF_br8(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
+ ANDB(dst,src);
+ PutbackRMByte(ModRM,dst);
+}
+
+static void PREFIX86(_and_wr16)(i8086_state *cpustate) /* Opcode 0x21 */
+{
+ DEF_wr16(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
+ ANDW(dst,src);
+ PutbackRMWord(ModRM,dst);
+}
+
+static void PREFIX86(_and_r8b)(i8086_state *cpustate) /* Opcode 0x22 */
+{
+ DEF_r8b(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
+ ANDB(dst,src);
+ RegByte(ModRM)=dst;
+}
+
+static void PREFIX86(_and_r16w)(i8086_state *cpustate) /* Opcode 0x23 */
+{
+ DEF_r16w(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
+ ANDW(dst,src);
+ RegWord(ModRM)=dst;
+}
+
+static void PREFIX86(_and_ald8)(i8086_state *cpustate) /* Opcode 0x24 */
+{
+ DEF_ald8(dst,src);
+ ICOUNT -= timing.alu_ri8;
+ ANDB(dst,src);
+ cpustate->regs.b[AL] = dst;
+}
+
+static void PREFIX86(_and_axd16)(i8086_state *cpustate) /* Opcode 0x25 */
+{
+ DEF_axd16(dst,src);
+ ICOUNT -= timing.alu_ri16;
+ ANDW(dst,src);
+ cpustate->regs.w[AX]=dst;
+}
+
+static void PREFIX86(_daa)(i8086_state *cpustate) /* Opcode 0x27 */
+{
+ if (AF || ((cpustate->regs.b[AL] & 0xf) > 9))
+ {
+ int tmp;
+ cpustate->regs.b[AL] = tmp = cpustate->regs.b[AL] + 6;
+ cpustate->AuxVal = 1;
+ cpustate->CarryVal |= tmp & 0x100;
+ }
+
+ if (CF || (cpustate->regs.b[AL] > 0x9f))
+ {
+ cpustate->regs.b[AL] += 0x60;
+ cpustate->CarryVal = 1;
+ }
+
+ SetSZPF_Byte(cpustate->regs.b[AL]);
+ ICOUNT -= timing.daa;
+}
+
+static void PREFIX86(_sub_br8)(i8086_state *cpustate) /* Opcode 0x28 */
+{
+ DEF_br8(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
+ SUBB(dst,src);
+ PutbackRMByte(ModRM,dst);
+}
+
+static void PREFIX86(_sub_wr16)(i8086_state *cpustate) /* Opcode 0x29 */
+{
+ DEF_wr16(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
+ SUBW(dst,src);
+ PutbackRMWord(ModRM,dst);
+}
+
+static void PREFIX86(_sub_r8b)(i8086_state *cpustate) /* Opcode 0x2a */
+{
+ DEF_r8b(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
+ SUBB(dst,src);
+ RegByte(ModRM)=dst;
+}
+
+static void PREFIX86(_sub_r16w)(i8086_state *cpustate) /* Opcode 0x2b */
+{
+ DEF_r16w(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
+ SUBW(dst,src);
+ RegWord(ModRM)=dst;
+}
+
+static void PREFIX86(_sub_ald8)(i8086_state *cpustate) /* Opcode 0x2c */
+{
+ DEF_ald8(dst,src);
+ ICOUNT -= timing.alu_ri8;
+ SUBB(dst,src);
+ cpustate->regs.b[AL] = dst;
+}
+
+static void PREFIX86(_sub_axd16)(i8086_state *cpustate) /* Opcode 0x2d */
+{
+ DEF_axd16(dst,src);
+ ICOUNT -= timing.alu_ri16;
+ SUBW(dst,src);
+ cpustate->regs.w[AX]=dst;
+}
+
+static void PREFIX86(_das)(i8086_state *cpustate) /* Opcode 0x2f */
+{
+ UINT8 tmpAL=cpustate->regs.b[AL];
+ if (AF || ((cpustate->regs.b[AL] & 0xf) > 9))
+ {
+ int tmp;
+ cpustate->regs.b[AL] = tmp = cpustate->regs.b[AL] - 6;
+ cpustate->AuxVal = 1;
+ cpustate->CarryVal |= tmp & 0x100;
+ }
+
+ if (CF || (tmpAL > 0x9f))
+ {
+ cpustate->regs.b[AL] -= 0x60;
+ cpustate->CarryVal = 1;
+ }
+
+ SetSZPF_Byte(cpustate->regs.b[AL]);
+ ICOUNT -= timing.das;
+}
+
+static void PREFIX86(_xor_br8)(i8086_state *cpustate) /* Opcode 0x30 */
+{
+ DEF_br8(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
+ XORB(dst,src);
+ PutbackRMByte(ModRM,dst);
+}
+
+static void PREFIX86(_xor_wr16)(i8086_state *cpustate) /* Opcode 0x31 */
+{
+ DEF_wr16(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
+ XORW(dst,src);
+ PutbackRMWord(ModRM,dst);
+}
+
+static void PREFIX86(_xor_r8b)(i8086_state *cpustate) /* Opcode 0x32 */
+{
+ DEF_r8b(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
+ XORB(dst,src);
+ RegByte(ModRM)=dst;
+}
+
+static void PREFIX86(_xor_r16w)(i8086_state *cpustate) /* Opcode 0x33 */
+{
+ DEF_r16w(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
+ XORW(dst,src);
+ RegWord(ModRM)=dst;
+}
+
+static void PREFIX86(_xor_ald8)(i8086_state *cpustate) /* Opcode 0x34 */
+{
+ DEF_ald8(dst,src);
+ ICOUNT -= timing.alu_ri8;
+ XORB(dst,src);
+ cpustate->regs.b[AL] = dst;
+}
+
+static void PREFIX86(_xor_axd16)(i8086_state *cpustate) /* Opcode 0x35 */
+{
+ DEF_axd16(dst,src);
+ ICOUNT -= timing.alu_ri16;
+ XORW(dst,src);
+ cpustate->regs.w[AX]=dst;
+}
+
+static void PREFIX86(_aaa)(i8086_state *cpustate) /* Opcode 0x37 */
+{
+ UINT8 ALcarry=1;
+ if (cpustate->regs.b[AL]>0xf9) ALcarry=2;
+
+ if (AF || ((cpustate->regs.b[AL] & 0xf) > 9))
+ {
+ cpustate->regs.b[AL] += 6;
+ cpustate->regs.b[AH] += ALcarry;
+ cpustate->AuxVal = 1;
+ cpustate->CarryVal = 1;
+ }
+ else
+ {
+ cpustate->AuxVal = 0;
+ cpustate->CarryVal = 0;
+ }
+ cpustate->regs.b[AL] &= 0x0F;
+ ICOUNT -= timing.aaa;
+}
+
+static void PREFIX86(_cmp_br8)(i8086_state *cpustate) /* Opcode 0x38 */
+{
+ DEF_br8(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
+ SUBB(dst,src);
+}
+
+static void PREFIX86(_cmp_wr16)(i8086_state *cpustate) /* Opcode 0x39 */
+{
+ DEF_wr16(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
+ SUBW(dst,src);
+}
+
+static void PREFIX86(_cmp_r8b)(i8086_state *cpustate) /* Opcode 0x3a */
+{
+ DEF_r8b(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
+ SUBB(dst,src);
+}
+
+static void PREFIX86(_cmp_r16w)(i8086_state *cpustate) /* Opcode 0x3b */
+{
+ DEF_r16w(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
+ SUBW(dst,src);
+}
+
+static void PREFIX86(_cmp_ald8)(i8086_state *cpustate) /* Opcode 0x3c */
+{
+ DEF_ald8(dst,src);
+ ICOUNT -= timing.alu_ri8;
+ SUBB(dst,src);
+}
+
+static void PREFIX86(_cmp_axd16)(i8086_state *cpustate) /* Opcode 0x3d */
+{
+ DEF_axd16(dst,src);
+ ICOUNT -= timing.alu_ri16;
+ SUBW(dst,src);
+}
+
+static void PREFIX86(_aas)(i8086_state *cpustate) /* Opcode 0x3f */
+{
+// UINT8 ALcarry=1;
+// if (cpustate->regs.b[AL]>0xf9) ALcarry=2;
+
+ if (AF || ((cpustate->regs.b[AL] & 0xf) > 9))
+ {
+ cpustate->regs.b[AL] -= 6;
+ cpustate->regs.b[AH] -= 1;
+ cpustate->AuxVal = 1;
+ cpustate->CarryVal = 1;
+ }
+ else
+ {
+ cpustate->AuxVal = 0;
+ cpustate->CarryVal = 0;
+ }
+ cpustate->regs.b[AL] &= 0x0F;
+ ICOUNT -= timing.aas;
+}
+
+#define IncWordReg(Reg) \
+{ \
+ unsigned tmp = (unsigned)cpustate->regs.w[Reg]; \
+ unsigned tmp1 = tmp+1; \
+ SetOFW_Add(tmp1,tmp,1); \
+ SetAF(tmp1,tmp,1); \
+ SetSZPF_Word(tmp1); \
+ cpustate->regs.w[Reg]=tmp1; \
+ ICOUNT -= timing.incdec_r16; \
+}
+
+static void PREFIX86(_inc_ax)(i8086_state *cpustate) /* Opcode 0x40 */
+{
+ IncWordReg(AX);
+}
+
+static void PREFIX86(_inc_cx)(i8086_state *cpustate) /* Opcode 0x41 */
+{
+ IncWordReg(CX);
+}
+
+static void PREFIX86(_inc_dx)(i8086_state *cpustate) /* Opcode 0x42 */
+{
+ IncWordReg(DX);
+}
+
+static void PREFIX(_inc_bx)(i8086_state *cpustate) /* Opcode 0x43 */
+{
+ IncWordReg(BX);
+}
+
+static void PREFIX86(_inc_sp)(i8086_state *cpustate) /* Opcode 0x44 */
+{
+ IncWordReg(SP);
+}
+
+static void PREFIX86(_inc_bp)(i8086_state *cpustate) /* Opcode 0x45 */
+{
+ IncWordReg(BP);
+}
+
+static void PREFIX86(_inc_si)(i8086_state *cpustate) /* Opcode 0x46 */
+{
+ IncWordReg(SI);
+}
+
+static void PREFIX86(_inc_di)(i8086_state *cpustate) /* Opcode 0x47 */
+{
+ IncWordReg(DI);
+}
+
+#define DecWordReg(Reg) \
+{ \
+ unsigned tmp = (unsigned)cpustate->regs.w[Reg]; \
+ unsigned tmp1 = tmp-1; \
+ SetOFW_Sub(tmp1,1,tmp); \
+ SetAF(tmp1,tmp,1); \
+ SetSZPF_Word(tmp1); \
+ cpustate->regs.w[Reg]=tmp1; \
+ ICOUNT -= timing.incdec_r16; \
+}
+
+static void PREFIX86(_dec_ax)(i8086_state *cpustate) /* Opcode 0x48 */
+{
+ DecWordReg(AX);
+}
+
+static void PREFIX86(_dec_cx)(i8086_state *cpustate) /* Opcode 0x49 */
+{
+ DecWordReg(CX);
+}
+
+static void PREFIX86(_dec_dx)(i8086_state *cpustate) /* Opcode 0x4a */
+{
+ DecWordReg(DX);
+}
+
+static void PREFIX86(_dec_bx)(i8086_state *cpustate) /* Opcode 0x4b */
+{
+ DecWordReg(BX);
+}
+
+static void PREFIX86(_dec_sp)(i8086_state *cpustate) /* Opcode 0x4c */
+{
+ DecWordReg(SP);
+}
+
+static void PREFIX86(_dec_bp)(i8086_state *cpustate) /* Opcode 0x4d */
+{
+ DecWordReg(BP);
+}
+
+static void PREFIX86(_dec_si)(i8086_state *cpustate) /* Opcode 0x4e */
+{
+ DecWordReg(SI);
+}
+
+static void PREFIX86(_dec_di)(i8086_state *cpustate) /* Opcode 0x4f */
+{
+ DecWordReg(DI);
+}
+
+static void PREFIX86(_push_ax)(i8086_state *cpustate) /* Opcode 0x50 */
+{
+ ICOUNT -= timing.push_r16;
+ PUSH(cpustate->regs.w[AX]);
+}
+
+static void PREFIX86(_push_cx)(i8086_state *cpustate) /* Opcode 0x51 */
+{
+ ICOUNT -= timing.push_r16;
+ PUSH(cpustate->regs.w[CX]);
+}
+
+static void PREFIX86(_push_dx)(i8086_state *cpustate) /* Opcode 0x52 */
+{
+ ICOUNT -= timing.push_r16;
+ PUSH(cpustate->regs.w[DX]);
+}
+
+static void PREFIX86(_push_bx)(i8086_state *cpustate) /* Opcode 0x53 */
+{
+ ICOUNT -= timing.push_r16;
+ PUSH(cpustate->regs.w[BX]);
+}
+
+static void PREFIX86(_push_sp)(i8086_state *cpustate) /* Opcode 0x54 */
+{
+ ICOUNT -= timing.push_r16;
+#ifdef I80286
+ PUSH(cpustate->regs.w[SP]+2);
+#else
+ PUSH(cpustate->regs.w[SP]);
+#endif
+}
+
+static void PREFIX86(_push_bp)(i8086_state *cpustate) /* Opcode 0x55 */
+{
+ ICOUNT -= timing.push_r16;
+ PUSH(cpustate->regs.w[BP]);
+}
+
+
+static void PREFIX86(_push_si)(i8086_state *cpustate) /* Opcode 0x56 */
+{
+ ICOUNT -= timing.push_r16;
+ PUSH(cpustate->regs.w[SI]);
+}
+
+static void PREFIX86(_push_di)(i8086_state *cpustate) /* Opcode 0x57 */
+{
+ ICOUNT -= timing.push_r16;
+ PUSH(cpustate->regs.w[DI]);
+}
+
+static void PREFIX86(_pop_ax)(i8086_state *cpustate) /* Opcode 0x58 */
+{
+ ICOUNT -= timing.pop_r16;
+ POP(cpustate->regs.w[AX]);
+}
+
+static void PREFIX86(_pop_cx)(i8086_state *cpustate) /* Opcode 0x59 */
+{
+ ICOUNT -= timing.pop_r16;
+ POP(cpustate->regs.w[CX]);
+}
+
+static void PREFIX86(_pop_dx)(i8086_state *cpustate) /* Opcode 0x5a */
+{
+ ICOUNT -= timing.pop_r16;
+ POP(cpustate->regs.w[DX]);
+}
+
+static void PREFIX86(_pop_bx)(i8086_state *cpustate) /* Opcode 0x5b */
+{
+ ICOUNT -= timing.pop_r16;
+ POP(cpustate->regs.w[BX]);
+}
+
+static void PREFIX86(_pop_sp)(i8086_state *cpustate) /* Opcode 0x5c */
+{
+ ICOUNT -= timing.pop_r16;
+ POP(cpustate->regs.w[SP]);
+}
+
+static void PREFIX86(_pop_bp)(i8086_state *cpustate) /* Opcode 0x5d */
+{
+ ICOUNT -= timing.pop_r16;
+ POP(cpustate->regs.w[BP]);
+}
+
+static void PREFIX86(_pop_si)(i8086_state *cpustate) /* Opcode 0x5e */
+{
+ ICOUNT -= timing.pop_r16;
+ POP(cpustate->regs.w[SI]);
+}
+
+static void PREFIX86(_pop_di)(i8086_state *cpustate) /* Opcode 0x5f */
+{
+ ICOUNT -= timing.pop_r16;
+ POP(cpustate->regs.w[DI]);
+}
+
+static void PREFIX86(_jo)(i8086_state *cpustate) /* Opcode 0x70 */
+{
+ int tmp = (int)((INT8)FETCH);
+ if (OF)
+ {
+ cpustate->pc += tmp;
+ ICOUNT -= timing.jcc_t;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ } else ICOUNT -= timing.jcc_nt;
+}
+
+static void PREFIX86(_jno)(i8086_state *cpustate) /* Opcode 0x71 */
+{
+ int tmp = (int)((INT8)FETCH);
+ if (!OF) {
+ cpustate->pc += tmp;
+ ICOUNT -= timing.jcc_t;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ } else ICOUNT -= timing.jcc_nt;
+}
+
+static void PREFIX86(_jb)(i8086_state *cpustate) /* Opcode 0x72 */
+{
+ int tmp = (int)((INT8)FETCH);
+ if (CF) {
+ cpustate->pc += tmp;
+ ICOUNT -= timing.jcc_t;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ } else ICOUNT -= timing.jcc_nt;
+}
+
+static void PREFIX86(_jnb)(i8086_state *cpustate) /* Opcode 0x73 */
+{
+ int tmp = (int)((INT8)FETCH);
+ if (!CF) {
+ cpustate->pc += tmp;
+ ICOUNT -= timing.jcc_t;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ } else ICOUNT -= timing.jcc_nt;
+}
+
+static void PREFIX86(_jz)(i8086_state *cpustate) /* Opcode 0x74 */
+{
+ int tmp = (int)((INT8)FETCH);
+ if (ZF) {
+ cpustate->pc += tmp;
+ ICOUNT -= timing.jcc_t;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ } else ICOUNT -= timing.jcc_nt;
+}
+
+static void PREFIX86(_jnz)(i8086_state *cpustate) /* Opcode 0x75 */
+{
+ int tmp = (int)((INT8)FETCH);
+ if (!ZF) {
+ cpustate->pc += tmp;
+ ICOUNT -= timing.jcc_t;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ } else ICOUNT -= timing.jcc_nt;
+}
+
+static void PREFIX86(_jbe)(i8086_state *cpustate) /* Opcode 0x76 */
+{
+ int tmp = (int)((INT8)FETCH);
+ if (CF || ZF) {
+ cpustate->pc += tmp;
+ ICOUNT -= timing.jcc_t;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ } else ICOUNT -= timing.jcc_nt;
+}
+
+static void PREFIX86(_jnbe)(i8086_state *cpustate) /* Opcode 0x77 */
+{
+ int tmp = (int)((INT8)FETCH);
+ if (!(CF || ZF)) {
+ cpustate->pc += tmp;
+ ICOUNT -= timing.jcc_t;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ } else ICOUNT -= timing.jcc_nt;
+}
+
+static void PREFIX86(_js)(i8086_state *cpustate) /* Opcode 0x78 */
+{
+ int tmp = (int)((INT8)FETCH);
+ if (SF) {
+ cpustate->pc += tmp;
+ ICOUNT -= timing.jcc_t;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ } else ICOUNT -= timing.jcc_nt;
+}
+
+static void PREFIX86(_jns)(i8086_state *cpustate) /* Opcode 0x79 */
+{
+ int tmp = (int)((INT8)FETCH);
+ if (!SF) {
+ cpustate->pc += tmp;
+ ICOUNT -= timing.jcc_t;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ } else ICOUNT -= timing.jcc_nt;
+}
+
+static void PREFIX86(_jp)(i8086_state *cpustate) /* Opcode 0x7a */
+{
+ int tmp = (int)((INT8)FETCH);
+ if (PF) {
+ cpustate->pc += tmp;
+ ICOUNT -= timing.jcc_t;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ } else ICOUNT -= timing.jcc_nt;
+}
+
+static void PREFIX86(_jnp)(i8086_state *cpustate) /* Opcode 0x7b */
+{
+ int tmp = (int)((INT8)FETCH);
+ if (!PF) {
+ cpustate->pc += tmp;
+ ICOUNT -= timing.jcc_t;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ } else ICOUNT -= timing.jcc_nt;
+}
+
+static void PREFIX86(_jl)(i8086_state *cpustate) /* Opcode 0x7c */
+{
+ int tmp = (int)((INT8)FETCH);
+ if ((SF!=OF)&&!ZF) {
+ cpustate->pc += tmp;
+ ICOUNT -= timing.jcc_t;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ } else ICOUNT -= timing.jcc_nt;
+}
+
+static void PREFIX86(_jnl)(i8086_state *cpustate) /* Opcode 0x7d */
+{
+ int tmp = (int)((INT8)FETCH);
+ if (ZF||(SF==OF)) {
+ cpustate->pc += tmp;
+ ICOUNT -= timing.jcc_t;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ } else ICOUNT -= timing.jcc_nt;
+}
+
+static void PREFIX86(_jle)(i8086_state *cpustate) /* Opcode 0x7e */
+{
+ int tmp = (int)((INT8)FETCH);
+ if (ZF||(SF!=OF)) {
+ cpustate->pc += tmp;
+ ICOUNT -= timing.jcc_t;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ } else ICOUNT -= timing.jcc_nt;
+}
+
+static void PREFIX86(_jnle)(i8086_state *cpustate) /* Opcode 0x7f */
+{
+ int tmp = (int)((INT8)FETCH);
+ if ((SF==OF)&&!ZF) {
+ cpustate->pc += tmp;
+ ICOUNT -= timing.jcc_t;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ } else ICOUNT -= timing.jcc_nt;
+}
+
+static void PREFIX86(_80pre)(i8086_state *cpustate) /* Opcode 0x80 */
+{
+ unsigned ModRM = FETCHOP;
+ unsigned dst = GetRMByte(ModRM);
+ unsigned src = FETCH;
+ int tmpcf;
+
+ switch (ModRM & 0x38)
+ {
+ case 0x00: /* ADD eb,d8 */
+ ADDB(dst,src);
+ PutbackRMByte(ModRM,dst);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 0x08: /* OR eb,d8 */
+ ORB(dst,src);
+ PutbackRMByte(ModRM,dst);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 0x10: /* ADC eb,d8 */
+ src+=CF;
+ ADCB(dst,src,tmpcf);
+ PutbackRMByte(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 0x18: /* SBB eb,b8 */
+ src+=CF;
+ SBBB(dst,src,tmpcf);
+ PutbackRMByte(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 0x20: /* AND eb,d8 */
+ ANDB(dst,src);
+ PutbackRMByte(ModRM,dst);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 0x28: /* SUB eb,d8 */
+ SUBB(dst,src);
+ PutbackRMByte(ModRM,dst);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 0x30: /* XOR eb,d8 */
+ XORB(dst,src);
+ PutbackRMByte(ModRM,dst);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 0x38: /* CMP eb,d8 */
+ SUBB(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8_ro;
+ break;
+ }
+}
+
+
+static void PREFIX86(_81pre)(i8086_state *cpustate) /* Opcode 0x81 */
+{
+ unsigned ModRM = FETCH;
+ unsigned dst = GetRMWord(ModRM);
+ unsigned src = FETCH;
+ int tmpcf;
+ src+= (FETCH << 8);
+
+ switch (ModRM & 0x38)
+ {
+ case 0x00: /* ADD ew,d16 */
+ ADDW(dst,src);
+ PutbackRMWord(ModRM,dst);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
+ break;
+ case 0x08: /* OR ew,d16 */
+ ORW(dst,src);
+ PutbackRMWord(ModRM,dst);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
+ break;
+ case 0x10: /* ADC ew,d16 */
+ src+=CF;
+ ADCW(dst,src,tmpcf);
+ PutbackRMWord(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
+ break;
+ case 0x18: /* SBB ew,d16 */
+ src+=CF;
+ SBBW(dst,src,tmpcf);
+ PutbackRMWord(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
+ break;
+ case 0x20: /* AND ew,d16 */
+ ANDW(dst,src);
+ PutbackRMWord(ModRM,dst);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
+ break;
+ case 0x28: /* SUB ew,d16 */
+ SUBW(dst,src);
+ PutbackRMWord(ModRM,dst);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
+ break;
+ case 0x30: /* XOR ew,d16 */
+ XORW(dst,src);
+ PutbackRMWord(ModRM,dst);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
+ break;
+ case 0x38: /* CMP ew,d16 */
+ SUBW(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16_ro;
+ break;
+ }
+}
+
+static void PREFIX86(_82pre)(i8086_state *cpustate) /* Opcode 0x82 */
+{
+ unsigned ModRM = FETCH;
+ unsigned dst = GetRMByte(ModRM);
+ unsigned src = FETCH;
+ int tmpcf;
+
+ switch (ModRM & 0x38)
+ {
+ case 0x00: /* ADD eb,d8 */
+ ADDB(dst,src);
+ PutbackRMByte(ModRM,dst);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 0x08: /* OR eb,d8 */
+ ORB(dst,src);
+ PutbackRMByte(ModRM,dst);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 0x10: /* ADC eb,d8 */
+ src+=CF;
+ ADCB(dst,src,tmpcf);
+ PutbackRMByte(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 0x18: /* SBB eb,d8 */
+ src+=CF;
+ SBBB(dst,src,tmpcf);
+ PutbackRMByte(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 0x20: /* AND eb,d8 */
+ ANDB(dst,src);
+ PutbackRMByte(ModRM,dst);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 0x28: /* SUB eb,d8 */
+ SUBB(dst,src);
+ PutbackRMByte(ModRM,dst);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 0x30: /* XOR eb,d8 */
+ XORB(dst,src);
+ PutbackRMByte(ModRM,dst);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 0x38: /* CMP eb,d8 */
+ SUBB(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8_ro;
+ break;
+ }
+}
+
+static void PREFIX86(_83pre)(i8086_state *cpustate) /* Opcode 0x83 */
+{
+ unsigned ModRM = FETCH;
+ unsigned dst = GetRMWord(ModRM);
+ unsigned src = (WORD)((INT16)((INT8)FETCH));
+ int tmpcf;
+
+ switch (ModRM & 0x38)
+ {
+ case 0x00: /* ADD ew,d16 */
+ ADDW(dst,src);
+ PutbackRMWord(ModRM,dst);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
+ break;
+ case 0x08: /* OR ew,d16 */
+ ORW(dst,src);
+ PutbackRMWord(ModRM,dst);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
+ break;
+ case 0x10: /* ADC ew,d16 */
+ src+=CF;
+ ADCW(dst,src,tmpcf);
+ PutbackRMWord(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
+ break;
+ case 0x18: /* SBB ew,d16 */
+ src+=CF;
+ SBBW(dst,src,tmpcf);
+ PutbackRMWord(ModRM,dst);
+ cpustate->CarryVal = tmpcf;
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
+ break;
+ case 0x20: /* AND ew,d16 */
+ ANDW(dst,src);
+ PutbackRMWord(ModRM,dst);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
+ break;
+ case 0x28: /* SUB ew,d16 */
+ SUBW(dst,src);
+ PutbackRMWord(ModRM,dst);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
+ break;
+ case 0x30: /* XOR ew,d16 */
+ XORW(dst,src);
+ PutbackRMWord(ModRM,dst);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
+ break;
+ case 0x38: /* CMP ew,d16 */
+ SUBW(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8_ro;
+ break;
+ }
+}
+
+static void PREFIX86(_test_br8)(i8086_state *cpustate) /* Opcode 0x84 */
+{
+ DEF_br8(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
+ ANDB(dst,src);
+}
+
+static void PREFIX86(_test_wr16)(i8086_state *cpustate) /* Opcode 0x85 */
+{
+ DEF_wr16(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
+ ANDW(dst,src);
+}
+
+static void PREFIX86(_xchg_br8)(i8086_state *cpustate) /* Opcode 0x86 */
+{
+ DEF_br8(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.xchg_rr8 : timing.xchg_rm8;
+ PutbackRMByte(ModRM,src);
+ RegByte(ModRM)=dst;
+}
+
+static void PREFIX86(_xchg_wr16)(i8086_state *cpustate) /* Opcode 0x87 */
+{
+ DEF_wr16(dst,src);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.xchg_rr16 : timing.xchg_rm16;
+ PutbackRMWord(ModRM,src);
+ RegWord(ModRM)=dst;
+}
+
+static void PREFIX86(_mov_br8)(i8086_state *cpustate) /* Opcode 0x88 */
+{
+ unsigned ModRM = FETCH;
+ BYTE src = RegByte(ModRM);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.mov_rr8 : timing.mov_mr8;
+ PutRMByte(ModRM,src);
+}
+
+static void PREFIX86(_mov_wr16)(i8086_state *cpustate) /* Opcode 0x89 */
+{
+ unsigned ModRM = FETCH;
+ WORD src = RegWord(ModRM);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.mov_rr16 : timing.mov_mr16;
+ PutRMWord(ModRM,src);
+}
+
+static void PREFIX86(_mov_r8b)(i8086_state *cpustate) /* Opcode 0x8a */
+{
+ unsigned ModRM = FETCH;
+ BYTE src = GetRMByte(ModRM);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.mov_rr8 : timing.mov_rm8;
+ RegByte(ModRM)=src;
+}
+
+static void PREFIX86(_mov_r16w)(i8086_state *cpustate) /* Opcode 0x8b */
+{
+ unsigned ModRM = FETCH;
+ WORD src = GetRMWord(ModRM);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.mov_rr8 : timing.mov_rm16;
+ RegWord(ModRM)=src;
+}
+
+static void PREFIX86(_mov_wsreg)(i8086_state *cpustate) /* Opcode 0x8c */
+{
+ unsigned ModRM = FETCH;
+ ICOUNT -= (ModRM >= 0xc0) ? timing.mov_rs : timing.mov_ms;
+ if (ModRM & 0x20) { /* HJB 12/13/98 1xx is invalid */
+ cpustate->pc = cpustate->prevpc;
+ return PREFIX86(_invalid)(cpustate);
+ }
+
+ PutRMWord(ModRM,cpustate->sregs[(ModRM & 0x38) >> 3]);
+}
+
+static void PREFIX86(_lea)(i8086_state *cpustate) /* Opcode 0x8d */
+{
+ unsigned ModRM = FETCH;
+ ICOUNT -= timing.lea;
+ (void)(*GetEA[ModRM])(cpustate);
+ RegWord(ModRM)=cpustate->eo; /* HJB 12/13/98 effective offset (no segment part) */
+}
+
+static void PREFIX86(_popw)(i8086_state *cpustate) /* Opcode 0x8f */
+{
+ unsigned ModRM = FETCH;
+ WORD tmp;
+ tmp = ReadWord(cpustate->base[SS] + cpustate->regs.w[SP]);
+ ICOUNT -= (ModRM >= 0xc0) ? timing.pop_r16 : timing.pop_m16;
+ PutRMWord(ModRM,tmp);
+ cpustate->regs.w[SP] += 2;
+}
+
+
+#define XchgAXReg(Reg) \
+{ \
+ WORD tmp; \
+ tmp = cpustate->regs.w[Reg]; \
+ cpustate->regs.w[Reg] = cpustate->regs.w[AX]; \
+ cpustate->regs.w[AX] = tmp; \
+ ICOUNT -= timing.xchg_ar16; \
+}
+
+
+static void PREFIX86(_nop)(i8086_state *cpustate) /* Opcode 0x90 */
+{
+ /* this is XchgAXReg(AX); */
+ ICOUNT -= timing.nop;
+}
+
+static void PREFIX86(_xchg_axcx)(i8086_state *cpustate) /* Opcode 0x91 */
+{
+ XchgAXReg(CX);
+}
+
+static void PREFIX86(_xchg_axdx)(i8086_state *cpustate) /* Opcode 0x92 */
+{
+ XchgAXReg(DX);
+}
+
+static void PREFIX86(_xchg_axbx)(i8086_state *cpustate) /* Opcode 0x93 */
+{
+ XchgAXReg(BX);
+}
+
+static void PREFIX86(_xchg_axsp)(i8086_state *cpustate) /* Opcode 0x94 */
+{
+ XchgAXReg(SP);
+}
+
+static void PREFIX86(_xchg_axbp)(i8086_state *cpustate) /* Opcode 0x95 */
+{
+ XchgAXReg(BP);
+}
+
+static void PREFIX86(_xchg_axsi)(i8086_state *cpustate) /* Opcode 0x96 */
+{
+ XchgAXReg(SI);
+}
+
+static void PREFIX86(_xchg_axdi)(i8086_state *cpustate) /* Opcode 0x97 */
+{
+ XchgAXReg(DI);
+}
+
+static void PREFIX86(_cbw)(i8086_state *cpustate) /* Opcode 0x98 */
+{
+ ICOUNT -= timing.cbw;
+ cpustate->regs.b[AH] = (cpustate->regs.b[AL] & 0x80) ? 0xff : 0;
+}
+
+static void PREFIX86(_cwd)(i8086_state *cpustate) /* Opcode 0x99 */
+{
+ ICOUNT -= timing.cwd;
+ cpustate->regs.w[DX] = (cpustate->regs.b[AH] & 0x80) ? 0xffff : 0;
+}
+
+static void PREFIX86(_call_far)(i8086_state *cpustate)
+{
+ unsigned int tmp, tmp2;
+ WORD cs, ip;
+
+ tmp = FETCH;
+ tmp += FETCH << 8;
+
+ tmp2 = FETCH;
+ tmp2 += FETCH << 8;
+
+ ip = cpustate->pc - cpustate->base[CS];
+ cs = cpustate->sregs[CS];
+
+#ifdef I80286
+ i80286_code_descriptor(cpustate, tmp2, tmp, 2);
+#else
+ cpustate->sregs[CS] = (WORD)tmp2;
+ cpustate->base[CS] = SegBase(CS);
+ cpustate->pc = (cpustate->base[CS] + (WORD)tmp) & AMASK;
+#endif
+ PUSH(cs);
+ PUSH(ip);
+ ICOUNT -= timing.call_far;
+ CHANGE_PC(cpustate->pc);
+}
+
+static void PREFIX86(_wait)(i8086_state *cpustate) /* Opcode 0x9b */
+{
+#ifdef I80286
+ if ((cpustate->msw&0x0a) == 0x0a) throw TRAP(FPU_UNAVAILABLE,-1);
+#endif
+ if (cpustate->test_state)
+ {
+ ICOUNT = 0;
+ cpustate->pc--;
+ }
+ else
+ ICOUNT -= timing.wait;
+}
+
+static void PREFIX86(_pushf)(i8086_state *cpustate) /* Opcode 0x9c */
+{
+ unsigned tmp;
+ ICOUNT -= timing.pushf;
+
+ tmp = CompressFlags();
+#ifdef I80286
+ if(!PM) ( tmp &= ~0xf000 );
+#endif
+ PUSH( tmp );
+}
+
+#ifndef I80286
+static void PREFIX86(_popf)(i8086_state *cpustate) /* Opcode 0x9d */
+{
+ unsigned tmp;
+ POP(tmp);
+ ICOUNT -= timing.popf;
+
+ ExpandFlags(tmp);
+ cpustate->flags = tmp;
+ cpustate->flags = CompressFlags();
+
+ if (cpustate->TF) PREFIX(_trap)(cpustate);
+
+ /* if the IF is set, and an interrupt is pending, signal an interrupt */
+ if (cpustate->IF && cpustate->irq_state)
+ PREFIX(_interrupt)(cpustate, (UINT32)-1);
+}
+#endif
+
+static void PREFIX86(_sahf)(i8086_state *cpustate) /* Opcode 0x9e */
+{
+ unsigned tmp = (CompressFlags() & 0xff00) | (cpustate->regs.b[AH] & 0xd5);
+ ICOUNT -= timing.sahf;
+ ExpandFlags(tmp);
+}
+
+static void PREFIX86(_lahf)(i8086_state *cpustate) /* Opcode 0x9f */
+{
+ cpustate->regs.b[AH] = CompressFlags() & 0xff;
+ ICOUNT -= timing.lahf;
+}
+
+
+static void PREFIX86(_mov_aldisp)(i8086_state *cpustate) /* Opcode 0xa0 */
+{
+ unsigned addr;
+
+ addr = FETCH;
+ addr += FETCH << 8;
+
+ ICOUNT -= timing.mov_am8;
+ cpustate->regs.b[AL] = GetMemB(DS, addr);
+}
+
+static void PREFIX86(_mov_axdisp)(i8086_state *cpustate) /* Opcode 0xa1 */
+{
+ unsigned addr;
+
+ addr = FETCH;
+ addr += FETCH << 8;
+
+ ICOUNT -= timing.mov_am16;
+ cpustate->regs.w[AX] = GetMemW(DS, addr);
+}
+
+static void PREFIX86(_mov_dispal)(i8086_state *cpustate) /* Opcode 0xa2 */
+{
+ unsigned addr;
+
+ addr = FETCH;
+ addr += FETCH << 8;
+
+ ICOUNT -= timing.mov_ma8;
+ PutMemB(DS, addr, cpustate->regs.b[AL]);
+}
+
+static void PREFIX86(_mov_dispax)(i8086_state *cpustate) /* Opcode 0xa3 */
+{
+ unsigned addr;
+
+ addr = FETCH;
+ addr += FETCH << 8;
+
+ ICOUNT -= timing.mov_ma16;
+ PutMemW(DS, addr, cpustate->regs.w[AX]);
+}
+
+static void PREFIX86(_movsb)(i8086_state *cpustate) /* Opcode 0xa4 */
+{
+ BYTE tmp = GetMemB(DS,cpustate->regs.w[SI]);
+ PutMemB(ES,cpustate->regs.w[DI], tmp);
+ cpustate->regs.w[DI] += cpustate->DirVal;
+ cpustate->regs.w[SI] += cpustate->DirVal;
+ ICOUNT -= timing.movs8;
+}
+
+static void PREFIX86(_movsw)(i8086_state *cpustate) /* Opcode 0xa5 */
+{
+ WORD tmp = GetMemW(DS,cpustate->regs.w[SI]);
+ PutMemW(ES,cpustate->regs.w[DI], tmp);
+ cpustate->regs.w[DI] += 2 * cpustate->DirVal;
+ cpustate->regs.w[SI] += 2 * cpustate->DirVal;
+ ICOUNT -= timing.movs16;
+}
+
+static void PREFIX86(_cmpsb)(i8086_state *cpustate) /* Opcode 0xa6 */
+{
+ unsigned dst = GetMemB(ES, cpustate->regs.w[DI]);
+ unsigned src = GetMemB(DS, cpustate->regs.w[SI]);
+ SUBB(src,dst); /* opposite of the usual convention */
+ cpustate->regs.w[DI] += cpustate->DirVal;
+ cpustate->regs.w[SI] += cpustate->DirVal;
+ ICOUNT -= timing.cmps8;
+}
+
+static void PREFIX86(_cmpsw)(i8086_state *cpustate) /* Opcode 0xa7 */
+{
+ unsigned dst = GetMemW(ES, cpustate->regs.w[DI]);
+ unsigned src = GetMemW(DS, cpustate->regs.w[SI]);
+ SUBW(src,dst); /* opposite of the usual convention */
+ cpustate->regs.w[DI] += 2 * cpustate->DirVal;
+ cpustate->regs.w[SI] += 2 * cpustate->DirVal;
+ ICOUNT -= timing.cmps16;
+}
+
+static void PREFIX86(_test_ald8)(i8086_state *cpustate) /* Opcode 0xa8 */
+{
+ DEF_ald8(dst,src);
+ ICOUNT -= timing.alu_ri8;
+ ANDB(dst,src);
+}
+
+static void PREFIX86(_test_axd16)(i8086_state *cpustate) /* Opcode 0xa9 */
+{
+ DEF_axd16(dst,src);
+ ICOUNT -= timing.alu_ri16;
+ ANDW(dst,src);
+}
+
+static void PREFIX86(_stosb)(i8086_state *cpustate) /* Opcode 0xaa */
+{
+ PutMemB(ES,cpustate->regs.w[DI],cpustate->regs.b[AL]);
+ cpustate->regs.w[DI] += cpustate->DirVal;
+ ICOUNT -= timing.stos8;
+}
+
+static void PREFIX86(_stosw)(i8086_state *cpustate) /* Opcode 0xab */
+{
+ PutMemW(ES,cpustate->regs.w[DI],cpustate->regs.w[AX]);
+ cpustate->regs.w[DI] += 2 * cpustate->DirVal;
+ ICOUNT -= timing.stos16;
+}
+
+static void PREFIX86(_lodsb)(i8086_state *cpustate) /* Opcode 0xac */
+{
+ cpustate->regs.b[AL] = GetMemB(DS,cpustate->regs.w[SI]);
+ cpustate->regs.w[SI] += cpustate->DirVal;
+ ICOUNT -= timing.lods8;
+}
+
+static void PREFIX86(_lodsw)(i8086_state *cpustate) /* Opcode 0xad */
+{
+ cpustate->regs.w[AX] = GetMemW(DS,cpustate->regs.w[SI]);
+ cpustate->regs.w[SI] += 2 * cpustate->DirVal;
+ ICOUNT -= timing.lods16;
+}
+
+static void PREFIX86(_scasb)(i8086_state *cpustate) /* Opcode 0xae */
+{
+ unsigned src = GetMemB(ES, cpustate->regs.w[DI]);
+ unsigned dst = cpustate->regs.b[AL];
+ SUBB(dst,src);
+ cpustate->regs.w[DI] += cpustate->DirVal;
+ ICOUNT -= timing.scas8;
+}
+
+static void PREFIX86(_scasw)(i8086_state *cpustate) /* Opcode 0xaf */
+{
+ unsigned src = GetMemW(ES, cpustate->regs.w[DI]);
+ unsigned dst = cpustate->regs.w[AX];
+ SUBW(dst,src);
+ cpustate->regs.w[DI] += 2 * cpustate->DirVal;
+ ICOUNT -= timing.scas16;
+}
+
+static void PREFIX86(_mov_ald8)(i8086_state *cpustate) /* Opcode 0xb0 */
+{
+ cpustate->regs.b[AL] = FETCH;
+ ICOUNT -= timing.mov_ri8;
+}
+
+static void PREFIX86(_mov_cld8)(i8086_state *cpustate) /* Opcode 0xb1 */
+{
+ cpustate->regs.b[CL] = FETCH;
+ ICOUNT -= timing.mov_ri8;
+}
+
+static void PREFIX86(_mov_dld8)(i8086_state *cpustate) /* Opcode 0xb2 */
+{
+ cpustate->regs.b[DL] = FETCH;
+ ICOUNT -= timing.mov_ri8;
+}
+
+static void PREFIX86(_mov_bld8)(i8086_state *cpustate) /* Opcode 0xb3 */
+{
+ cpustate->regs.b[BL] = FETCH;
+ ICOUNT -= timing.mov_ri8;
+}
+
+static void PREFIX86(_mov_ahd8)(i8086_state *cpustate) /* Opcode 0xb4 */
+{
+ cpustate->regs.b[AH] = FETCH;
+ ICOUNT -= timing.mov_ri8;
+}
+
+static void PREFIX86(_mov_chd8)(i8086_state *cpustate) /* Opcode 0xb5 */
+{
+ cpustate->regs.b[CH] = FETCH;
+ ICOUNT -= timing.mov_ri8;
+}
+
+static void PREFIX86(_mov_dhd8)(i8086_state *cpustate) /* Opcode 0xb6 */
+{
+ cpustate->regs.b[DH] = FETCH;
+ ICOUNT -= timing.mov_ri8;
+}
+
+static void PREFIX86(_mov_bhd8)(i8086_state *cpustate) /* Opcode 0xb7 */
+{
+ cpustate->regs.b[BH] = FETCH;
+ ICOUNT -= timing.mov_ri8;
+}
+
+static void PREFIX86(_mov_axd16)(i8086_state *cpustate) /* Opcode 0xb8 */
+{
+ cpustate->regs.b[AL] = FETCH;
+ cpustate->regs.b[AH] = FETCH;
+ ICOUNT -= timing.mov_ri16;
+}
+
+static void PREFIX86(_mov_cxd16)(i8086_state *cpustate) /* Opcode 0xb9 */
+{
+ cpustate->regs.b[CL] = FETCH;
+ cpustate->regs.b[CH] = FETCH;
+ ICOUNT -= timing.mov_ri16;
+}
+
+static void PREFIX86(_mov_dxd16)(i8086_state *cpustate) /* Opcode 0xba */
+{
+ cpustate->regs.b[DL] = FETCH;
+ cpustate->regs.b[DH] = FETCH;
+ ICOUNT -= timing.mov_ri16;
+}
+
+static void PREFIX86(_mov_bxd16)(i8086_state *cpustate) /* Opcode 0xbb */
+{
+ cpustate->regs.b[BL] = FETCH;
+ cpustate->regs.b[BH] = FETCH;
+ ICOUNT -= timing.mov_ri16;
+}
+
+static void PREFIX86(_mov_spd16)(i8086_state *cpustate) /* Opcode 0xbc */
+{
+ cpustate->regs.b[SPL] = FETCH;
+ cpustate->regs.b[SPH] = FETCH;
+ ICOUNT -= timing.mov_ri16;
+}
+
+static void PREFIX86(_mov_bpd16)(i8086_state *cpustate) /* Opcode 0xbd */
+{
+ cpustate->regs.b[BPL] = FETCH;
+ cpustate->regs.b[BPH] = FETCH;
+ ICOUNT -= timing.mov_ri16;
+}
+
+static void PREFIX86(_mov_sid16)(i8086_state *cpustate) /* Opcode 0xbe */
+{
+ cpustate->regs.b[SIL] = FETCH;
+ cpustate->regs.b[SIH] = FETCH;
+ ICOUNT -= timing.mov_ri16;
+}
+
+static void PREFIX86(_mov_did16)(i8086_state *cpustate) /* Opcode 0xbf */
+{
+ cpustate->regs.b[DIL] = FETCH;
+ cpustate->regs.b[DIH] = FETCH;
+ ICOUNT -= timing.mov_ri16;
+}
+
+static void PREFIX86(_ret_d16)(i8086_state *cpustate) /* Opcode 0xc2 */
+{
+ unsigned count = FETCH;
+ count += FETCH << 8;
+ POP(cpustate->pc);
+ cpustate->pc = (cpustate->pc + cpustate->base[CS]) & AMASK;
+ cpustate->regs.w[SP]+=count;
+ ICOUNT -= timing.ret_near_imm;
+ CHANGE_PC(cpustate->pc);
+}
+
+static void PREFIX86(_ret)(i8086_state *cpustate) /* Opcode 0xc3 */
+{
+ POP(cpustate->pc);
+ cpustate->pc = (cpustate->pc + cpustate->base[CS]) & AMASK;
+ ICOUNT -= timing.ret_near;
+ CHANGE_PC(cpustate->pc);
+}
+
+static void PREFIX86(_les_dw)(i8086_state *cpustate) /* Opcode 0xc4 */
+{
+ unsigned ModRM = FETCH;
+ WORD tmp = GetRMWord(ModRM);
+
+#ifdef I80286
+ i80286_data_descriptor(cpustate,ES,GetnextRMWord);
+#else
+ cpustate->sregs[ES] = GetnextRMWord;
+ cpustate->base[ES] = SegBase(ES);
+#endif
+ RegWord(ModRM)= tmp;
+ ICOUNT -= timing.load_ptr;
+}
+
+static void PREFIX86(_lds_dw)(i8086_state *cpustate) /* Opcode 0xc5 */
+{
+ unsigned ModRM = FETCH;
+ WORD tmp = GetRMWord(ModRM);
+
+#ifdef I80286
+ i80286_data_descriptor(cpustate,DS,GetnextRMWord);
+#else
+ cpustate->sregs[DS] = GetnextRMWord;
+ cpustate->base[DS] = SegBase(DS);
+#endif
+ RegWord(ModRM)=tmp;
+ ICOUNT -= timing.load_ptr;
+}
+
+static void PREFIX86(_mov_bd8)(i8086_state *cpustate) /* Opcode 0xc6 */
+{
+ unsigned ModRM = FETCH;
+ ICOUNT -= (ModRM >= 0xc0) ? timing.mov_ri8 : timing.mov_mi8;
+ PutImmRMByte(ModRM);
+}
+
+static void PREFIX86(_mov_wd16)(i8086_state *cpustate) /* Opcode 0xc7 */
+{
+ unsigned ModRM = FETCH;
+ ICOUNT -= (ModRM >= 0xc0) ? timing.mov_ri16 : timing.mov_mi16;
+ PutImmRMWord(ModRM);
+}
+
+#ifndef I80286
+static void PREFIX86(_retf_d16)(i8086_state *cpustate) /* Opcode 0xca */
+{
+ unsigned count = FETCH;
+ count += FETCH << 8;
+
+ POP(cpustate->pc);
+ POP(cpustate->sregs[CS]);
+ cpustate->base[CS] = SegBase(CS);
+ cpustate->pc = (cpustate->pc + cpustate->base[CS]) & AMASK;
+ cpustate->regs.w[SP]+=count;
+ ICOUNT -= timing.ret_far_imm;
+ CHANGE_PC(cpustate->pc);
+}
+
+static void PREFIX86(_retf)(i8086_state *cpustate) /* Opcode 0xcb */
+{
+ POP(cpustate->pc);
+ POP(cpustate->sregs[CS]);
+ cpustate->base[CS] = SegBase(CS);
+ cpustate->pc = (cpustate->pc + cpustate->base[CS]) & AMASK;
+ ICOUNT -= timing.ret_far;
+ CHANGE_PC(cpustate->pc);
+}
+#endif
+
+static void PREFIX86(_int3)(i8086_state *cpustate) /* Opcode 0xcc */
+{
+ ICOUNT -= timing.int3;
+ PREFIX(_interrupt)(cpustate, 3);
+}
+
+static void PREFIX86(_int)(i8086_state *cpustate) /* Opcode 0xcd */
+{
+ unsigned int_num = FETCH;
+ ICOUNT -= timing.int_imm;
+ PREFIX(_interrupt)(cpustate, int_num);
+}
+
+static void PREFIX86(_into)(i8086_state *cpustate) /* Opcode 0xce */
+{
+ if (OF) {
+ ICOUNT -= timing.into_t;
+ PREFIX(_interrupt)(cpustate, 4);
+ } else ICOUNT -= timing.into_nt;
+}
+
+#ifndef I80286
+static void PREFIX86(_iret)(i8086_state *cpustate) /* Opcode 0xcf */
+{
+ ICOUNT -= timing.iret;
+ POP(cpustate->pc);
+ POP(cpustate->sregs[CS]);
+ cpustate->base[CS] = SegBase(CS);
+ cpustate->pc = (cpustate->pc + cpustate->base[CS]) & AMASK;
+ PREFIX(_popf)(cpustate);
+ CHANGE_PC(cpustate->pc);
+
+ /* if the IF is set, and an interrupt is pending, signal an interrupt */
+ if (cpustate->IF && cpustate->irq_state)
+ PREFIX(_interrupt)(cpustate, (UINT32)-1);
+}
+#endif
+
+static void PREFIX86(_rotshft_b)(i8086_state *cpustate) /* Opcode 0xd0 */
+{
+ unsigned ModRM = FETCHOP;
+ PREFIX(_rotate_shift_Byte)(cpustate,ModRM,1,GetRMByte(ModRM));
+}
+
+
+static void PREFIX86(_rotshft_w)(i8086_state *cpustate) /* Opcode 0xd1 */
+{
+ unsigned ModRM = FETCHOP;
+ PREFIX(_rotate_shift_Word)(cpustate,ModRM,1,GetRMWord(ModRM));
+}
+
+
+#ifdef I8086
+static void PREFIX86(_rotshft_bcl)(i8086_state *cpustate) /* Opcode 0xd2 */
+{
+ unsigned ModRM = FETCHOP;
+ PREFIX(_rotate_shift_Byte)(cpustate,ModRM,cpustate->regs.b[CL],GetRMByte(ModRM));
+}
+
+static void PREFIX86(_rotshft_wcl)(i8086_state *cpustate) /* Opcode 0xd3 */
+{
+ unsigned ModRM = FETCHOP;
+ PREFIX(_rotate_shift_Word)(cpustate,ModRM,cpustate->regs.b[CL],GetRMWord(ModRM));
+}
+#endif
+
+/* OB: Opcode works on NEC V-Series but not the Variants */
+/* one could specify any byte value as operand but the NECs */
+/* always substitute 0x0a. */
+static void PREFIX86(_aam)(i8086_state *cpustate) /* Opcode 0xd4 */
+{
+ unsigned mult = FETCH;
+
+ ICOUNT -= timing.aam;
+ if (mult == 0)
+ PREFIX(_interrupt)(cpustate, 0);
+ else
+ {
+ cpustate->regs.b[AH] = cpustate->regs.b[AL] / mult;
+ cpustate->regs.b[AL] %= mult;
+
+ SetSZPF_Word(cpustate->regs.w[AX]);
+ }
+}
+
+static void PREFIX86(_aad)(i8086_state *cpustate) /* Opcode 0xd5 */
+{
+ unsigned mult = FETCH;
+
+ ICOUNT -= timing.aad;
+
+ cpustate->regs.b[AL] = cpustate->regs.b[AH] * mult + cpustate->regs.b[AL];
+ cpustate->regs.b[AH] = 0;
+
+ SetZF(cpustate->regs.b[AL]);
+ SetPF(cpustate->regs.b[AL]);
+ cpustate->SignVal = 0;
+}
+
+
+static void PREFIX86(_xlat)(i8086_state *cpustate) /* Opcode 0xd7 */
+{
+ unsigned dest = cpustate->regs.w[BX]+cpustate->regs.b[AL];
+
+ ICOUNT -= timing.xlat;
+ cpustate->regs.b[AL] = GetMemB(DS, dest);
+}
+
+#ifndef I80286
+static void PREFIX86(_escape)(i8086_state *cpustate) /* Opcodes 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde and 0xdf */
+{
+ unsigned ModRM = FETCH;
+ ICOUNT -= timing.nop;
+ GetRMByte(ModRM);
+}
+#endif
+
+static void PREFIX86(_loopne)(i8086_state *cpustate) /* Opcode 0xe0 */
+{
+ int disp = (int)((INT8)FETCH);
+ unsigned tmp = cpustate->regs.w[CX]-1;
+
+ cpustate->regs.w[CX]=tmp;
+
+ if (!ZF && tmp) {
+ ICOUNT -= timing.loop_t;
+ cpustate->pc += disp;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ } else ICOUNT -= timing.loop_nt;
+}
+
+static void PREFIX86(_loope)(i8086_state *cpustate) /* Opcode 0xe1 */
+{
+ int disp = (int)((INT8)FETCH);
+ unsigned tmp = cpustate->regs.w[CX]-1;
+
+ cpustate->regs.w[CX]=tmp;
+
+ if (ZF && tmp) {
+ ICOUNT -= timing.loope_t;
+ cpustate->pc += disp;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ } else ICOUNT -= timing.loope_nt;
+}
+
+static void PREFIX86(_loop)(i8086_state *cpustate) /* Opcode 0xe2 */
+{
+ int disp = (int)((INT8)FETCH);
+ unsigned tmp = cpustate->regs.w[CX]-1;
+
+ cpustate->regs.w[CX]=tmp;
+
+ if (tmp) {
+ ICOUNT -= timing.loop_t;
+ cpustate->pc += disp;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ } else ICOUNT -= timing.loop_nt;
+}
+
+static void PREFIX86(_jcxz)(i8086_state *cpustate) /* Opcode 0xe3 */
+{
+ int disp = (int)((INT8)FETCH);
+
+ if (cpustate->regs.w[CX] == 0) {
+ ICOUNT -= timing.jcxz_t;
+ cpustate->pc += disp;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ } else
+ ICOUNT -= timing.jcxz_nt;
+}
+
+static void PREFIX86(_inal)(i8086_state *cpustate) /* Opcode 0xe4 */
+{
+ unsigned port;
+#ifdef I80286
+ if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
+#endif
+ port = FETCH;
+
+ ICOUNT -= timing.in_imm8;
+ cpustate->regs.b[AL] = read_port_byte(port);
+}
+
+static void PREFIX86(_inax)(i8086_state *cpustate) /* Opcode 0xe5 */
+{
+ unsigned port;
+#ifdef I80286
+ if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
+#endif
+ port = FETCH;
+
+ ICOUNT -= timing.in_imm16;
+ cpustate->regs.w[AX] = read_port_word(port);
+}
+
+static void PREFIX86(_outal)(i8086_state *cpustate) /* Opcode 0xe6 */
+{
+ unsigned port;
+#ifdef I80286
+ if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
+#endif
+ port = FETCH;
+
+ ICOUNT -= timing.out_imm8;
+ write_port_byte(port, cpustate->regs.b[AL]);
+}
+
+static void PREFIX86(_outax)(i8086_state *cpustate) /* Opcode 0xe7 */
+{
+ unsigned port;
+#ifdef I80286
+ if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
+#endif
+ port = FETCH;
+
+ ICOUNT -= timing.out_imm16;
+ write_port_word(port, cpustate->regs.w[AX]);
+}
+
+static void PREFIX86(_call_d16)(i8086_state *cpustate) /* Opcode 0xe8 */
+{
+ WORD ip, tmp;
+
+ FETCHWORD(tmp);
+ ip = cpustate->pc - cpustate->base[CS];
+ PUSH(ip);
+ ip += tmp;
+ cpustate->pc = (ip + cpustate->base[CS]) & AMASK;
+ ICOUNT -= timing.call_near;
+ CHANGE_PC(cpustate->pc);
+}
+
+static void PREFIX86(_jmp_d16)(i8086_state *cpustate) /* Opcode 0xe9 */
+{
+ WORD ip, tmp;
+
+ FETCHWORD(tmp);
+ ip = cpustate->pc - cpustate->base[CS] + tmp;
+ cpustate->pc = (ip + cpustate->base[CS]) & AMASK;
+ ICOUNT -= timing.jmp_near;
+ CHANGE_PC(cpustate->pc);
+}
+
+static void PREFIX86(_jmp_far)(i8086_state *cpustate) /* Opcode 0xea */
+{
+ unsigned tmp,tmp1;
+
+ tmp = FETCH;
+ tmp += FETCH << 8;
+
+ tmp1 = FETCH;
+ tmp1 += FETCH << 8;
+
+#ifdef I80286
+ i80286_code_descriptor(cpustate, tmp1,tmp, 1);
+#else
+ cpustate->sregs[CS] = (WORD)tmp1;
+ cpustate->base[CS] = SegBase(CS);
+ cpustate->pc = (cpustate->base[CS] + tmp) & AMASK;
+#endif
+ ICOUNT -= timing.jmp_far;
+ CHANGE_PC(cpustate->pc);
+}
+
+static void PREFIX86(_jmp_d8)(i8086_state *cpustate) /* Opcode 0xeb */
+{
+ int tmp = (int)((INT8)FETCH);
+ cpustate->pc += tmp;
+/* ASG - can probably assume this is safe
+ CHANGE_PC(cpustate->pc);*/
+ ICOUNT -= timing.jmp_short;
+}
+
+static void PREFIX86(_inaldx)(i8086_state *cpustate) /* Opcode 0xec */
+{
+#ifdef I80286
+ if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
+#endif
+ ICOUNT -= timing.in_dx8;
+ cpustate->regs.b[AL] = read_port_byte(cpustate->regs.w[DX]);
+}
+
+static void PREFIX86(_inaxdx)(i8086_state *cpustate) /* Opcode 0xed */
+{
+ unsigned port = cpustate->regs.w[DX];
+#ifdef I80286
+ if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
+#endif
+ ICOUNT -= timing.in_dx16;
+ cpustate->regs.w[AX] = read_port_word(port);
+}
+
+static void PREFIX86(_outdxal)(i8086_state *cpustate) /* Opcode 0xee */
+{
+#ifdef I80286
+ if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
+#endif
+ ICOUNT -= timing.out_dx8;
+ write_port_byte(cpustate->regs.w[DX], cpustate->regs.b[AL]);
+}
+
+static void PREFIX86(_outdxax)(i8086_state *cpustate) /* Opcode 0xef */
+{
+ unsigned port = cpustate->regs.w[DX];
+#ifdef I80286
+ if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);
+#endif
+ ICOUNT -= timing.out_dx16;
+ write_port_word(port, cpustate->regs.w[AX]);
+}
+
+/* I think thats not a V20 instruction...*/
+static void PREFIX86(_lock)(i8086_state *cpustate) /* Opcode 0xf0 */
+{
+#ifdef I80286
+ if(PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT,0);
+#endif
+ ICOUNT -= timing.nop;
+ PREFIX(_instruction)[FETCHOP](cpustate); /* un-interruptible */
+}
+#endif
+
+static void PREFIX(_pop_ss)(i8086_state *cpustate) /* Opcode 0x17 */
+{
+#ifdef I80286
+ i80286_pop_seg(cpustate, SS);
+#else
+ POP(cpustate->sregs[SS]);
+ cpustate->base[SS] = SegBase(SS);
+#endif
+ ICOUNT -= timing.pop_seg;
+ PREFIX(_instruction)[FETCHOP](cpustate); /* no interrupt before next instruction */
+}
+
+static void PREFIX(_es)(i8086_state *cpustate) /* Opcode 0x26 */
+{
+ cpustate->seg_prefix = TRUE;
+ cpustate->prefix_seg = ES;
+ ICOUNT -= timing.override;
+ PREFIX(_instruction)[FETCHOP](cpustate);
+}
+
+static void PREFIX(_cs)(i8086_state *cpustate) /* Opcode 0x2e */
+{
+ cpustate->seg_prefix = TRUE;
+ cpustate->prefix_seg = CS;
+ ICOUNT -= timing.override;
+ PREFIX(_instruction)[FETCHOP](cpustate);
+}
+
+static void PREFIX(_ss)(i8086_state *cpustate) /* Opcode 0x36 */
+{
+ cpustate->seg_prefix = TRUE;
+ cpustate->prefix_seg = SS;
+ ICOUNT -= timing.override;
+ PREFIX(_instruction)[FETCHOP](cpustate);
+}
+
+static void PREFIX(_ds)(i8086_state *cpustate) /* Opcode 0x3e */
+{
+ cpustate->seg_prefix = TRUE;
+ cpustate->prefix_seg = DS;
+ ICOUNT -= timing.override;
+ PREFIX(_instruction)[FETCHOP](cpustate);
+}
+
+static void PREFIX(_mov_sregw)(i8086_state *cpustate) /* Opcode 0x8e */
+{
+ unsigned ModRM = FETCH;
+ WORD src = GetRMWord(ModRM);
+
+ ICOUNT -= (ModRM >= 0xc0) ? timing.mov_sr : timing.mov_sm;
+#ifdef I80286
+ switch (ModRM & 0x38)
+ {
+ case 0x00: /* mov es,ew */
+ i80286_data_descriptor(cpustate,ES,src);
+ break;
+ case 0x18: /* mov ds,ew */
+ i80286_data_descriptor(cpustate,DS,src);
+ break;
+ case 0x10: /* mov ss,ew */
+ i80286_data_descriptor(cpustate,SS,src);
+ cpustate->seg_prefix = FALSE;
+ PREFIX(_instruction)[FETCHOP](cpustate);
+ break;
+ case 0x08: /* mov cs,ew */
+ PREFIX(_invalid)(cpustate);
+ break; /* doesn't do a jump far */
+ }
+#else
+ switch (ModRM & 0x38)
+ {
+ case 0x00: /* mov es,ew */
+ cpustate->sregs[ES] = src;
+ cpustate->base[ES] = SegBase(ES);
+ break;
+ case 0x18: /* mov ds,ew */
+ cpustate->sregs[DS] = src;
+ cpustate->base[DS] = SegBase(DS);
+ break;
+ case 0x10: /* mov ss,ew */
+ cpustate->sregs[SS] = src;
+ cpustate->base[SS] = SegBase(SS); /* no interrupt allowed before next instr */
+ cpustate->seg_prefix = FALSE;
+ PREFIX(_instruction)[FETCHOP](cpustate);
+ break;
+ case 0x08: /* mov cs,ew */
+#ifndef I80186
+ int ip = cpustate->pc - cpustate->base[CS];
+ cpustate->sregs[CS] = src;
+ cpustate->base[CS] = SegBase(CS);
+ cpustate->pc = (ip + cpustate->base[CS]) & AMASK;
+ CHANGE_PC(cpustate->pc);
+#endif
+ break;
+ }
+#endif
+}
+
+static void PREFIX(_repne)(i8086_state *cpustate) /* Opcode 0xf2 */
+{
+ PREFIX(rep)(cpustate, 0);
+}
+
+static void PREFIX(_repe)(i8086_state *cpustate) /* Opcode 0xf3 */
+{
+ PREFIX(rep)(cpustate, 1);
+}
+
+static void PREFIX(_sti)(i8086_state *cpustate) /* Opcode 0xfb */
+{
+#ifdef I80286
+ if(PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT,0);
+#endif
+ ICOUNT -= timing.flag_ops;
+ SetIF(1);
+ PREFIX(_instruction)[FETCHOP](cpustate); /* no interrupt before next instruction */
+
+ /* if an interrupt is pending, signal an interrupt */
+ if (cpustate->irq_state)
+#ifdef I80286
+ i80286_interrupt_descriptor(cpustate, (*cpustate->irq_callback)(cpustate->device, 0), 2, -1);
+#else
+ PREFIX86(_interrupt)(cpustate, (UINT32)-1);
+#endif
+}
+
+#ifndef I80186
+static void PREFIX86(_hlt)(i8086_state *cpustate) /* Opcode 0xf4 */
+{
+#ifdef I80286
+ if(PM && (CPL!=0)) throw TRAP(GENERAL_PROTECTION_FAULT,0);
+#endif
+ cpustate->halted=1;
+ ICOUNT = 0;
+}
+
+static void PREFIX86(_cmc)(i8086_state *cpustate) /* Opcode 0xf5 */
+{
+ ICOUNT -= timing.flag_ops;
+ cpustate->CarryVal = !CF;
+}
+
+static void PREFIX86(_f6pre)(i8086_state *cpustate)
+{
+ /* Opcode 0xf6 */
+ unsigned ModRM = FETCH;
+ unsigned tmp = (unsigned)GetRMByte(ModRM);
+ unsigned tmp2;
+
+
+ switch (ModRM & 0x38)
+ {
+ case 0x00: /* TEST Eb, data8 */
+ case 0x08: /* ??? */
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8_ro;
+ tmp &= FETCH;
+
+ cpustate->CarryVal = cpustate->OverVal = cpustate->AuxVal = 0;
+ SetSZPF_Byte(tmp);
+ break;
+
+ case 0x10: /* NOT Eb */
+ ICOUNT -= (ModRM >= 0xc0) ? timing.negnot_r8 : timing.negnot_m8;
+ PutbackRMByte(ModRM,~tmp);
+ break;
+
+ case 0x18: /* NEG Eb */
+ ICOUNT -= (ModRM >= 0xc0) ? timing.negnot_r8 : timing.negnot_m8;
+ tmp2=0;
+ SUBB(tmp2,tmp);
+ PutbackRMByte(ModRM,tmp2);
+ break;
+ case 0x20: /* MUL AL, Eb */
+ ICOUNT -= (ModRM >= 0xc0) ? timing.mul_r8 : timing.mul_m8;
+ {
+ UINT16 result;
+ tmp2 = cpustate->regs.b[AL];
+
+ SetSF((INT8)tmp2);
+ SetPF(tmp2);
+
+ result = (UINT16)tmp2*tmp;
+ cpustate->regs.w[AX]=(WORD)result;
+
+ SetZF(cpustate->regs.w[AX]);
+ cpustate->CarryVal = cpustate->OverVal = (cpustate->regs.b[AH] != 0);
+ }
+ break;
+ case 0x28: /* IMUL AL, Eb */
+ ICOUNT -= (ModRM >= 0xc0) ? timing.imul_r8 : timing.imul_m8;
+ {
+ INT16 result;
+
+ tmp2 = (unsigned)cpustate->regs.b[AL];
+
+ SetSF((INT8)tmp2);
+ SetPF(tmp2);
+
+ result = (INT16)((INT8)tmp2)*(INT16)((INT8)tmp);
+ cpustate->regs.w[AX]=(WORD)result;
+
+ SetZF(cpustate->regs.w[AX]);
+
+ cpustate->CarryVal = cpustate->OverVal = (result >> 7 != 0) && (result >> 7 != -1);
+ }
+ break;
+ case 0x30: /* DIV AL, Ew */
+ ICOUNT -= (ModRM >= 0xc0) ? timing.div_r8 : timing.div_m8;
+ {
+ UINT16 result;
+
+ result = cpustate->regs.w[AX];
+
+ if (tmp)
+ {
+ if ((result / tmp) > 0xff)
+ {
+ PREFIX(_interrupt)(cpustate, 0);
+ break;
+ }
+ else
+ {
+ cpustate->regs.b[AH] = result % tmp;
+ cpustate->regs.b[AL] = result / tmp;
+ }
+ }
+ else
+ {
+ PREFIX(_interrupt)(cpustate, 0);
+ break;
+ }
+ }
+ break;
+ case 0x38: /* IDIV AL, Ew */
+ ICOUNT -= (ModRM >= 0xc0) ? timing.idiv_r8 : timing.idiv_m8;
+ {
+
+ INT16 result;
+
+ result = cpustate->regs.w[AX];
+
+ if (tmp)
+ {
+ tmp2 = result % (INT16)((INT8)tmp);
+
+ if ((result /= (INT16)((INT8)tmp)) > 0xff)
+ {
+ PREFIX(_interrupt)(cpustate, 0);
+ break;
+ }
+ else
+ {
+ cpustate->regs.b[AL] = result;
+ cpustate->regs.b[AH] = tmp2;
+ }
+ }
+ else
+ {
+ PREFIX(_interrupt)(cpustate, 0);
+ break;
+ }
+ }
+ break;
+ }
+}
+
+
+static void PREFIX86(_f7pre)(i8086_state *cpustate)
+{
+ /* Opcode 0xf7 */
+ unsigned ModRM = FETCH;
+ unsigned tmp = GetRMWord(ModRM);
+ unsigned tmp2;
+
+
+ switch (ModRM & 0x38)
+ {
+ case 0x00: /* TEST Ew, data16 */
+ case 0x08: /* ??? */
+ ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16_ro;
+ tmp2 = FETCH;
+ tmp2 += FETCH << 8;
+
+ tmp &= tmp2;
+
+ cpustate->CarryVal = cpustate->OverVal = cpustate->AuxVal = 0;
+ SetSZPF_Word(tmp);
+ break;
+
+ case 0x10: /* NOT Ew */
+ ICOUNT -= (ModRM >= 0xc0) ? timing.negnot_r16 : timing.negnot_m16;
+ tmp = ~tmp;
+ PutbackRMWord(ModRM,tmp);
+ break;
+
+ case 0x18: /* NEG Ew */
+ ICOUNT -= (ModRM >= 0xc0) ? timing.negnot_r16 : timing.negnot_m16;
+ tmp2 = 0;
+ SUBW(tmp2,tmp);
+ PutbackRMWord(ModRM,tmp2);
+ break;
+ case 0x20: /* MUL AX, Ew */
+ ICOUNT -= (ModRM >= 0xc0) ? timing.mul_r16 : timing.mul_m16;
+ {
+ UINT32 result;
+ tmp2 = cpustate->regs.w[AX];
+
+ SetSF((INT16)tmp2);
+ SetPF(tmp2);
+
+ result = (UINT32)tmp2*tmp;
+ cpustate->regs.w[AX]=(WORD)result;
+ result >>= 16;
+ cpustate->regs.w[DX]=result;
+
+ SetZF(cpustate->regs.w[AX] | cpustate->regs.w[DX]);
+ cpustate->CarryVal = cpustate->OverVal = (cpustate->regs.w[DX] != 0);
+ }
+ break;
+
+ case 0x28: /* IMUL AX, Ew */
+ ICOUNT -= (ModRM >= 0xc0) ? timing.imul_r16 : timing.imul_m16;
+ {
+ INT32 result;
+
+ tmp2 = cpustate->regs.w[AX];
+
+ SetSF((INT16)tmp2);
+ SetPF(tmp2);
+
+ result = (INT32)((INT16)tmp2)*(INT32)((INT16)tmp);
+ cpustate->CarryVal = cpustate->OverVal = (result >> 15 != 0) && (result >> 15 != -1);
+
+ cpustate->regs.w[AX]=(WORD)result;
+ result = (WORD)(result >> 16);
+ cpustate->regs.w[DX]=result;
+
+ SetZF(cpustate->regs.w[AX] | cpustate->regs.w[DX]);
+ }
+ break;
+ case 0x30: /* DIV AX, Ew */
+ ICOUNT -= (ModRM >= 0xc0) ? timing.div_r16 : timing.div_m16;
+ {
+ UINT32 result;
+
+ result = (cpustate->regs.w[DX] << 16) + cpustate->regs.w[AX];
+
+ if (tmp)
+ {
+ tmp2 = result % tmp;
+ if ((result / tmp) > 0xffff)
+ {
+ PREFIX(_interrupt)(cpustate, 0);
+ break;
+ }
+ else
+ {
+ cpustate->regs.w[DX]=tmp2;
+ result /= tmp;
+ cpustate->regs.w[AX]=result;
+ }
+ }
+ else
+ {
+ PREFIX(_interrupt)(cpustate, 0);
+ break;
+ }
+ }
+ break;
+ case 0x38: /* IDIV AX, Ew */
+ ICOUNT -= (ModRM >= 0xc0) ? timing.idiv_r16 : timing.idiv_m16;
+ {
+ INT32 result;
+
+ result = (cpustate->regs.w[DX] << 16) + cpustate->regs.w[AX];
+
+ if (tmp)
+ {
+ tmp2 = result % (INT32)((INT16)tmp);
+ if ((result /= (INT32)((INT16)tmp)) > 0xffff)
+ {
+ PREFIX(_interrupt)(cpustate, 0);
+ break;
+ }
+ else
+ {
+ cpustate->regs.w[AX]=result;
+ cpustate->regs.w[DX]=tmp2;
+ }
+ }
+ else
+ {
+ PREFIX(_interrupt)(cpustate, 0);
+ break;
+ }
+ }
+ break;
+ }
+}
+
+
+static void PREFIX86(_clc)(i8086_state *cpustate) /* Opcode 0xf8 */
+{
+ ICOUNT -= timing.flag_ops;
+ cpustate->CarryVal = 0;
+}
+
+static void PREFIX86(_stc)(i8086_state *cpustate) /* Opcode 0xf9 */
+{
+ ICOUNT -= timing.flag_ops;
+ cpustate->CarryVal = 1;
+}
+
+static void PREFIX86(_cli)(i8086_state *cpustate) /* Opcode 0xfa */
+{
+#ifdef I80286
+ if(PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT,0);
+#endif
+ ICOUNT -= timing.flag_ops;
+ SetIF(0);
+}
+
+static void PREFIX86(_cld)(i8086_state *cpustate) /* Opcode 0xfc */
+{
+ ICOUNT -= timing.flag_ops;
+ SetDF(0);
+}
+
+static void PREFIX86(_std)(i8086_state *cpustate) /* Opcode 0xfd */
+{
+ ICOUNT -= timing.flag_ops;
+ SetDF(1);
+}
+
+static void PREFIX86(_fepre)(i8086_state *cpustate) /* Opcode 0xfe */
+{
+ unsigned ModRM = FETCH;
+ unsigned tmp = GetRMByte(ModRM);
+ unsigned tmp1;
+
+ ICOUNT -= (ModRM >= 0xc0) ? timing.incdec_r8 : timing.incdec_m8;
+ if ((ModRM & 0x38) == 0) /* INC eb */
+ {
+ tmp1 = tmp+1;
+ SetOFB_Add(tmp1,tmp,1);
+ }
+ else /* DEC eb */
+ {
+ tmp1 = tmp-1;
+ SetOFB_Sub(tmp1,1,tmp);
+ }
+
+ SetAF(tmp1,tmp,1);
+ SetSZPF_Byte(tmp1);
+
+ PutbackRMByte(ModRM,(BYTE)tmp1);
+}
+
+
+static void PREFIX86(_ffpre)(i8086_state *cpustate) /* Opcode 0xff */
+{
+ unsigned ModRM = FETCHOP;
+ unsigned tmp;
+ unsigned tmp1;
+ WORD ip;
+
+ switch(ModRM & 0x38)
+ {
+ case 0x00: /* INC ew */
+ ICOUNT -= (ModRM >= 0xc0) ? timing.incdec_r16 : timing.incdec_m16;
+ tmp = GetRMWord(ModRM);
+ tmp1 = tmp+1;
+
+ SetOFW_Add(tmp1,tmp,1);
+ SetAF(tmp1,tmp,1);
+ SetSZPF_Word(tmp1);
+
+ PutbackRMWord(ModRM,(WORD)tmp1);
+ break;
+
+ case 0x08: /* DEC ew */
+ ICOUNT -= (ModRM >= 0xc0) ? timing.incdec_r16 : timing.incdec_m16;
+ tmp = GetRMWord(ModRM);
+ tmp1 = tmp-1;
+
+ SetOFW_Sub(tmp1,1,tmp);
+ SetAF(tmp1,tmp,1);
+ SetSZPF_Word(tmp1);
+
+ PutbackRMWord(ModRM,(WORD)tmp1);
+ break;
+
+ case 0x10: /* CALL ew */
+ ICOUNT -= (ModRM >= 0xc0) ? timing.call_r16 : timing.call_m16;
+ tmp = GetRMWord(ModRM);
+ ip = cpustate->pc - cpustate->base[CS];
+ PUSH(ip);
+ cpustate->pc = (cpustate->base[CS] + (WORD)tmp) & AMASK;
+ CHANGE_PC(cpustate->pc);
+ break;
+
+ case 0x18: /* CALL FAR ea */
+ ICOUNT -= timing.call_m32;
+ tmp = cpustate->sregs[CS]; /* HJB 12/13/98 need to skip displacements of cpustate->ea */
+ tmp1 = GetRMWord(ModRM);
+ ip = cpustate->pc - cpustate->base[CS];
+#ifdef I80286
+ i80286_code_descriptor(cpustate, GetnextRMWord, tmp1, 2);
+#else
+ cpustate->sregs[CS] = GetnextRMWord;
+ cpustate->base[CS] = SegBase(CS);
+ cpustate->pc = (cpustate->base[CS] + tmp1) & AMASK;
+#endif
+ PUSH(tmp);
+ PUSH(ip);
+ CHANGE_PC(cpustate->pc);
+ break;
+
+ case 0x20: /* JMP ea */
+ ICOUNT -= (ModRM >= 0xc0) ? timing.jmp_r16 : timing.jmp_m16;
+ ip = GetRMWord(ModRM);
+ cpustate->pc = (cpustate->base[CS] + ip) & AMASK;
+ CHANGE_PC(cpustate->pc);
+ break;
+
+ case 0x28: /* JMP FAR ea */
+ ICOUNT -= timing.jmp_m32;
+
+#ifdef I80286
+ tmp = GetRMWord(ModRM);
+ i80286_code_descriptor(cpustate, GetnextRMWord, tmp, 1);
+#else
+ cpustate->pc = GetRMWord(ModRM);
+ cpustate->sregs[CS] = GetnextRMWord;
+ cpustate->base[CS] = SegBase(CS);
+ cpustate->pc = (cpustate->pc + cpustate->base[CS]) & AMASK;
+#endif
+ CHANGE_PC(cpustate->pc);
+ break;
+
+ case 0x30: /* PUSH ea */
+ ICOUNT -= (ModRM >= 0xc0) ? timing.push_r16 : timing.push_m16;
+ tmp = GetRMWord(ModRM);
+ PUSH(tmp);
+ break;
+ default:
+ tmp = GetRMWord(ModRM); // 286 doesn't matter but 8086?
+ return PREFIX(_invalid)(cpustate);
+ }
+}
+
+
+static void PREFIX86(_invalid)(i8086_state *cpustate)
+{
+#ifdef I80286
+ throw TRAP(ILLEGAL_INSTRUCTION,-1);
+#else
+ /* i8086/i8088 ignore an invalid opcode. */
+ /* i80186/i80188 probably also ignore an invalid opcode. */
+ logerror("illegal instruction %.2x at %.5x\n",PEEKBYTE(cpustate->pc-1), cpustate->pc);
+ ICOUNT -= 10;
+#endif
+}
+
+#ifndef I80286
+static void PREFIX86(_invalid_2b)(i8086_state *cpustate)
+{
+ unsigned ModRM = FETCH;
+ GetRMByte(ModRM);
+ logerror("illegal 2 byte instruction %.2x at %.5x\n",PEEKBYTE(cpustate->pc-2), cpustate->pc-2);
+ ICOUNT -= 10;
+}
+#endif
+#endif
+
diff --git a/trunk/src/emu/cpu/i86/instr86.h b/trunk/src/emu/cpu/i86/instr86.h
new file mode 100644
index 00000000000..5750d1738e9
--- /dev/null
+++ b/trunk/src/emu/cpu/i86/instr86.h
@@ -0,0 +1,250 @@
+#pragma once
+
+#ifndef __INSTR86_H__
+#define __INSTR86_H__
+
+/****************************************************************************
+* real mode i286 emulator v1.4 by Fabrice Frances *
+* (initial work based on David Hedley's pcemu) *
+****************************************************************************/
+
+// file will be included in all cpu variants
+// put non i86 instructions in own files (i286, i386, nec)
+// function renaming will be added when necessary
+// timing value should move to separate array
+
+static void PREFIX86(_add_br8)(i8086_state *cpustate);
+static void PREFIX86(_add_wr16)(i8086_state *cpustate);
+static void PREFIX86(_add_r8b)(i8086_state *cpustate);
+static void PREFIX86(_add_r16w)(i8086_state *cpustate);
+static void PREFIX86(_add_ald8)(i8086_state *cpustate);
+static void PREFIX86(_add_axd16)(i8086_state *cpustate);
+static void PREFIX86(_push_es)(i8086_state *cpustate);
+static void PREFIX86(_pop_es)(i8086_state *cpustate);
+static void PREFIX86(_or_br8)(i8086_state *cpustate);
+static void PREFIX86(_or_r8b)(i8086_state *cpustate);
+static void PREFIX86(_or_wr16)(i8086_state *cpustate);
+static void PREFIX86(_or_r16w)(i8086_state *cpustate);
+static void PREFIX86(_or_ald8)(i8086_state *cpustate);
+static void PREFIX86(_or_axd16)(i8086_state *cpustate);
+static void PREFIX86(_push_cs)(i8086_state *cpustate);
+#ifndef I80286
+static void PREFIX86(_pop_cs)(i8086_state *cpustate);
+#endif
+static void PREFIX86(_adc_br8)(i8086_state *cpustate);
+static void PREFIX86(_adc_wr16)(i8086_state *cpustate);
+static void PREFIX86(_adc_r8b)(i8086_state *cpustate);
+static void PREFIX86(_adc_r16w)(i8086_state *cpustate);
+static void PREFIX86(_adc_ald8)(i8086_state *cpustate);
+static void PREFIX86(_adc_axd16)(i8086_state *cpustate);
+static void PREFIX86(_push_ss)(i8086_state *cpustate);
+static void PREFIX86(_pop_ss)(i8086_state *cpustate);
+static void PREFIX86(_sbb_br8)(i8086_state *cpustate);
+static void PREFIX86(_sbb_wr16)(i8086_state *cpustate);
+static void PREFIX86(_sbb_r8b)(i8086_state *cpustate);
+static void PREFIX86(_sbb_r16w)(i8086_state *cpustate);
+static void PREFIX86(_sbb_ald8)(i8086_state *cpustate);
+static void PREFIX86(_sbb_axd16)(i8086_state *cpustate);
+static void PREFIX86(_push_ds)(i8086_state *cpustate);
+static void PREFIX86(_pop_ds)(i8086_state *cpustate);
+static void PREFIX86(_and_br8)(i8086_state *cpustate);
+static void PREFIX86(_and_r8b)(i8086_state *cpustate);
+static void PREFIX86(_and_wr16)(i8086_state *cpustate);
+static void PREFIX86(_and_r16w)(i8086_state *cpustate);
+static void PREFIX86(_and_ald8)(i8086_state *cpustate);
+static void PREFIX86(_and_axd16)(i8086_state *cpustate);
+static void PREFIX86(_es)(i8086_state *cpustate);
+static void PREFIX86(_daa)(i8086_state *cpustate);
+static void PREFIX86(_sub_br8)(i8086_state *cpustate);
+static void PREFIX86(_sub_wr16)(i8086_state *cpustate);
+static void PREFIX86(_sub_r8b)(i8086_state *cpustate);
+static void PREFIX86(_sub_r16w)(i8086_state *cpustate);
+static void PREFIX86(_sub_ald8)(i8086_state *cpustate);
+static void PREFIX86(_sub_axd16)(i8086_state *cpustate);
+static void PREFIX86(_cs)(i8086_state *cpustate);
+static void PREFIX86(_das)(i8086_state *cpustate);
+static void PREFIX86(_xor_br8)(i8086_state *cpustate);
+static void PREFIX86(_xor_r8b)(i8086_state *cpustate);
+static void PREFIX86(_xor_wr16)(i8086_state *cpustate);
+static void PREFIX86(_xor_r16w)(i8086_state *cpustate);
+static void PREFIX86(_xor_ald8)(i8086_state *cpustate);
+static void PREFIX86(_xor_axd16)(i8086_state *cpustate);
+static void PREFIX86(_ss)(i8086_state *cpustate);
+static void PREFIX86(_aaa)(i8086_state *cpustate);
+static void PREFIX86(_cmp_br8)(i8086_state *cpustate);
+static void PREFIX86(_cmp_wr16)(i8086_state *cpustate);
+static void PREFIX86(_cmp_r8b)(i8086_state *cpustate);
+static void PREFIX86(_cmp_r16w)(i8086_state *cpustate);
+static void PREFIX86(_cmp_ald8)(i8086_state *cpustate);
+static void PREFIX86(_cmp_axd16)(i8086_state *cpustate);
+static void PREFIX86(_ds)(i8086_state *cpustate);
+static void PREFIX86(_aas)(i8086_state *cpustate);
+static void PREFIX86(_inc_ax)(i8086_state *cpustate);
+static void PREFIX86(_inc_cx)(i8086_state *cpustate);
+static void PREFIX86(_inc_dx)(i8086_state *cpustate);
+static void PREFIX86(_inc_bx)(i8086_state *cpustate);
+static void PREFIX86(_inc_sp)(i8086_state *cpustate);
+static void PREFIX86(_inc_bp)(i8086_state *cpustate);
+static void PREFIX86(_inc_si)(i8086_state *cpustate);
+static void PREFIX86(_inc_di)(i8086_state *cpustate);
+static void PREFIX86(_dec_ax)(i8086_state *cpustate);
+static void PREFIX86(_dec_cx)(i8086_state *cpustate);
+static void PREFIX86(_dec_dx)(i8086_state *cpustate);
+static void PREFIX86(_dec_bx)(i8086_state *cpustate);
+static void PREFIX86(_dec_sp)(i8086_state *cpustate);
+static void PREFIX86(_dec_bp)(i8086_state *cpustate);
+static void PREFIX86(_dec_si)(i8086_state *cpustate);
+static void PREFIX86(_dec_di)(i8086_state *cpustate);
+static void PREFIX86(_push_ax)(i8086_state *cpustate);
+static void PREFIX86(_push_cx)(i8086_state *cpustate);
+static void PREFIX86(_push_dx)(i8086_state *cpustate);
+static void PREFIX86(_push_bx)(i8086_state *cpustate);
+static void PREFIX86(_push_sp)(i8086_state *cpustate);
+static void PREFIX86(_push_bp)(i8086_state *cpustate);
+static void PREFIX86(_push_si)(i8086_state *cpustate);
+static void PREFIX86(_push_di)(i8086_state *cpustate);
+static void PREFIX86(_pop_ax)(i8086_state *cpustate);
+static void PREFIX86(_pop_cx)(i8086_state *cpustate);
+static void PREFIX86(_pop_dx)(i8086_state *cpustate);
+static void PREFIX86(_pop_bx)(i8086_state *cpustate);
+static void PREFIX86(_pop_sp)(i8086_state *cpustate);
+static void PREFIX86(_pop_bp)(i8086_state *cpustate);
+static void PREFIX86(_pop_si)(i8086_state *cpustate);
+static void PREFIX86(_pop_di)(i8086_state *cpustate);
+static void PREFIX86(_jo)(i8086_state *cpustate);
+static void PREFIX86(_jno)(i8086_state *cpustate);
+static void PREFIX86(_jb)(i8086_state *cpustate);
+static void PREFIX86(_jnb)(i8086_state *cpustate);
+static void PREFIX86(_jz)(i8086_state *cpustate);
+static void PREFIX86(_jnz)(i8086_state *cpustate);
+static void PREFIX86(_jbe)(i8086_state *cpustate);
+static void PREFIX86(_jnbe)(i8086_state *cpustate);
+static void PREFIX86(_js)(i8086_state *cpustate);
+static void PREFIX86(_jns)(i8086_state *cpustate);
+static void PREFIX86(_jp)(i8086_state *cpustate);
+static void PREFIX86(_jnp)(i8086_state *cpustate);
+static void PREFIX86(_jl)(i8086_state *cpustate);
+static void PREFIX86(_jnl)(i8086_state *cpustate);
+static void PREFIX86(_jle)(i8086_state *cpustate);
+static void PREFIX86(_jnle)(i8086_state *cpustate);
+static void PREFIX86(_80pre)(i8086_state *cpustate);
+static void PREFIX86(_82pre)(i8086_state *cpustate);
+static void PREFIX86(_81pre)(i8086_state *cpustate);
+static void PREFIX86(_83pre)(i8086_state *cpustate);
+static void PREFIX86(_test_br8)(i8086_state *cpustate);
+static void PREFIX86(_test_wr16)(i8086_state *cpustate);
+static void PREFIX86(_xchg_br8)(i8086_state *cpustate);
+static void PREFIX86(_xchg_wr16)(i8086_state *cpustate);
+static void PREFIX86(_mov_br8)(i8086_state *cpustate);
+static void PREFIX86(_mov_r8b)(i8086_state *cpustate);
+static void PREFIX86(_mov_wr16)(i8086_state *cpustate);
+static void PREFIX86(_mov_r16w)(i8086_state *cpustate);
+static void PREFIX86(_mov_wsreg)(i8086_state *cpustate);
+static void PREFIX86(_lea)(i8086_state *cpustate);
+static void PREFIX86(_mov_sregw)(i8086_state *cpustate);
+static void PREFIX86(_invalid)(i8086_state *cpustate);
+#ifndef I80286
+static void PREFIX86(_invalid_2b)(i8086_state *cpustate);
+#endif
+static void PREFIX86(_popw)(i8086_state *cpustate);
+static void PREFIX86(_nop)(i8086_state *cpustate);
+static void PREFIX86(_xchg_axcx)(i8086_state *cpustate);
+static void PREFIX86(_xchg_axdx)(i8086_state *cpustate);
+static void PREFIX86(_xchg_axbx)(i8086_state *cpustate);
+static void PREFIX86(_xchg_axsp)(i8086_state *cpustate);
+static void PREFIX86(_xchg_axbp)(i8086_state *cpustate);
+static void PREFIX86(_xchg_axsi)(i8086_state *cpustate);
+static void PREFIX86(_xchg_axdi)(i8086_state *cpustate);
+static void PREFIX86(_cbw)(i8086_state *cpustate);
+static void PREFIX86(_cwd)(i8086_state *cpustate);
+static void PREFIX86(_call_far)(i8086_state *cpustate);
+static void PREFIX86(_pushf)(i8086_state *cpustate);
+static void PREFIX86(_popf)(i8086_state *cpustate);
+static void PREFIX86(_sahf)(i8086_state *cpustate);
+static void PREFIX86(_lahf)(i8086_state *cpustate);
+static void PREFIX86(_mov_aldisp)(i8086_state *cpustate);
+static void PREFIX86(_mov_axdisp)(i8086_state *cpustate);
+static void PREFIX86(_mov_dispal)(i8086_state *cpustate);
+static void PREFIX86(_mov_dispax)(i8086_state *cpustate);
+static void PREFIX86(_movsb)(i8086_state *cpustate);
+static void PREFIX86(_movsw)(i8086_state *cpustate);
+static void PREFIX86(_cmpsb)(i8086_state *cpustate);
+static void PREFIX86(_cmpsw)(i8086_state *cpustate);
+static void PREFIX86(_test_ald8)(i8086_state *cpustate);
+static void PREFIX86(_test_axd16)(i8086_state *cpustate);
+static void PREFIX86(_stosb)(i8086_state *cpustate);
+static void PREFIX86(_stosw)(i8086_state *cpustate);
+static void PREFIX86(_lodsb)(i8086_state *cpustate);
+static void PREFIX86(_lodsw)(i8086_state *cpustate);
+static void PREFIX86(_scasb)(i8086_state *cpustate);
+static void PREFIX86(_scasw)(i8086_state *cpustate);
+static void PREFIX86(_mov_ald8)(i8086_state *cpustate);
+static void PREFIX86(_mov_cld8)(i8086_state *cpustate);
+static void PREFIX86(_mov_dld8)(i8086_state *cpustate);
+static void PREFIX86(_mov_bld8)(i8086_state *cpustate);
+static void PREFIX86(_mov_ahd8)(i8086_state *cpustate);
+static void PREFIX86(_mov_chd8)(i8086_state *cpustate);
+static void PREFIX86(_mov_dhd8)(i8086_state *cpustate);
+static void PREFIX86(_mov_bhd8)(i8086_state *cpustate);
+static void PREFIX86(_mov_axd16)(i8086_state *cpustate);
+static void PREFIX86(_mov_cxd16)(i8086_state *cpustate);
+static void PREFIX86(_mov_dxd16)(i8086_state *cpustate);
+static void PREFIX86(_mov_bxd16)(i8086_state *cpustate);
+static void PREFIX86(_mov_spd16)(i8086_state *cpustate);
+static void PREFIX86(_mov_bpd16)(i8086_state *cpustate);
+static void PREFIX86(_mov_sid16)(i8086_state *cpustate);
+static void PREFIX86(_mov_did16)(i8086_state *cpustate);
+static void PREFIX86(_ret_d16)(i8086_state *cpustate);
+static void PREFIX86(_ret)(i8086_state *cpustate);
+static void PREFIX86(_les_dw)(i8086_state *cpustate);
+static void PREFIX86(_lds_dw)(i8086_state *cpustate);
+static void PREFIX86(_mov_bd8)(i8086_state *cpustate);
+static void PREFIX86(_mov_wd16)(i8086_state *cpustate);
+static void PREFIX86(_retf_d16)(i8086_state *cpustate);
+static void PREFIX86(_retf)(i8086_state *cpustate);
+static void PREFIX86(_int3)(i8086_state *cpustate);
+static void PREFIX86(_int)(i8086_state *cpustate);
+static void PREFIX86(_into)(i8086_state *cpustate);
+static void PREFIX86(_iret)(i8086_state *cpustate);
+static void PREFIX86(_rotshft_b)(i8086_state *cpustate);
+static void PREFIX86(_rotshft_w)(i8086_state *cpustate);
+static void PREFIX86(_rotshft_bcl)(i8086_state *cpustate);
+static void PREFIX86(_rotshft_wcl)(i8086_state *cpustate);
+static void PREFIX86(_aam)(i8086_state *cpustate);
+static void PREFIX86(_aad)(i8086_state *cpustate);
+static void PREFIX86(_xlat)(i8086_state *cpustate);
+static void PREFIX86(_escape)(i8086_state *cpustate);
+static void PREFIX86(_loopne)(i8086_state *cpustate);
+static void PREFIX86(_loope)(i8086_state *cpustate);
+static void PREFIX86(_loop)(i8086_state *cpustate);
+static void PREFIX86(_jcxz)(i8086_state *cpustate);
+static void PREFIX86(_inal)(i8086_state *cpustate);
+static void PREFIX86(_inax)(i8086_state *cpustate);
+static void PREFIX86(_outal)(i8086_state *cpustate);
+static void PREFIX86(_outax)(i8086_state *cpustate);
+static void PREFIX86(_call_d16)(i8086_state *cpustate);
+static void PREFIX86(_jmp_d16)(i8086_state *cpustate);
+static void PREFIX86(_jmp_far)(i8086_state *cpustate);
+static void PREFIX86(_jmp_d8)(i8086_state *cpustate);
+static void PREFIX86(_inaldx)(i8086_state *cpustate);
+static void PREFIX86(_inaxdx)(i8086_state *cpustate);
+static void PREFIX86(_outdxal)(i8086_state *cpustate);
+static void PREFIX86(_outdxax)(i8086_state *cpustate);
+static void PREFIX86(_lock)(i8086_state *cpustate);
+static void PREFIX86(_repne)(i8086_state *cpustate);
+static void PREFIX86(_repe)(i8086_state *cpustate);
+static void PREFIX86(_hlt)(i8086_state *cpustate);
+static void PREFIX86(_cmc)(i8086_state *cpustate);
+static void PREFIX86(_f6pre)(i8086_state *cpustate);
+static void PREFIX86(_f7pre)(i8086_state *cpustate);
+static void PREFIX86(_clc)(i8086_state *cpustate);
+static void PREFIX86(_stc)(i8086_state *cpustate);
+static void PREFIX86(_cli)(i8086_state *cpustate);
+static void PREFIX86(_sti)(i8086_state *cpustate);
+static void PREFIX86(_cld)(i8086_state *cpustate);
+static void PREFIX86(_std)(i8086_state *cpustate);
+static void PREFIX86(_fepre)(i8086_state *cpustate);
+static void PREFIX86(_ffpre)(i8086_state *cpustate);
+static void PREFIX86(_wait)(i8086_state *cpustate);
+
+#endif /* __INSTR86_H__ */
diff --git a/trunk/src/emu/cpu/i86/modrm.h b/trunk/src/emu/cpu/i86/modrm.h
new file mode 100644
index 00000000000..5919ebf230a
--- /dev/null
+++ b/trunk/src/emu/cpu/i86/modrm.h
@@ -0,0 +1,119 @@
+static struct
+{
+ struct
+ {
+ WREGS w[256];
+ BREGS b[256];
+ } reg;
+ struct
+ {
+ WREGS w[256];
+ BREGS b[256];
+ } RM;
+} Mod_RM;
+
+#define RegWord(ModRM) cpustate->regs.w[Mod_RM.reg.w[ModRM]]
+#define RegByte(ModRM) cpustate->regs.b[Mod_RM.reg.b[ModRM]]
+
+#define GetRMWord(ModRM) \
+ ((ModRM) >= 0xc0 ? cpustate->regs.w[Mod_RM.RM.w[ModRM]] : ( (*GetEA[ModRM])(cpustate), ReadWord( cpustate->ea ) ))
+
+#define PutbackRMWord(ModRM,val) \
+{ \
+ if (ModRM >= 0xc0) cpustate->regs.w[Mod_RM.RM.w[ModRM]]=val; \
+ else WriteWord(cpustate->ea,val); \
+}
+
+#define GetnextRMWord ReadWord(cpustate->ea+2)
+
+#define GetRMWordOffset(offs) \
+ ReadWord(cpustate->ea-cpustate->eo+(UINT16)(cpustate->eo+offs))
+
+#define GetRMByteOffset(offs) \
+ ReadByte(cpustate->ea-cpustate->eo+(UINT16)(cpustate->eo+offs))
+
+#define PutRMWord(ModRM,val) \
+{ \
+ if (ModRM >= 0xc0) \
+ cpustate->regs.w[Mod_RM.RM.w[ModRM]]=val; \
+ else { \
+ (*GetEA[ModRM])(cpustate); \
+ WriteWord( cpustate->ea ,val); \
+ } \
+}
+
+#define PutRMWordOffset(offs, val) \
+ WriteWord( cpustate->ea-cpustate->eo+(UINT16)(cpustate->eo+offs), val)
+
+#define PutRMByteOffset(offs, val) \
+ WriteByte( cpustate->ea-cpustate->eo+(UINT16)(cpustate->eo+offs), val)
+
+#define PutImmRMWord(ModRM) \
+{ \
+ WORD val; \
+ if (ModRM >= 0xc0) \
+ FETCHWORD(cpustate->regs.w[Mod_RM.RM.w[ModRM]]) \
+ else { \
+ (*GetEA[ModRM])(cpustate); \
+ FETCHWORD(val) \
+ WriteWord( cpustate->ea , val); \
+ } \
+}
+
+#define GetRMByte(ModRM) \
+ ((ModRM) >= 0xc0 ? cpustate->regs.b[Mod_RM.RM.b[ModRM]] : ReadByte( (*GetEA[ModRM])(cpustate) ))
+
+#define PutRMByte(ModRM,val) \
+{ \
+ if (ModRM >= 0xc0) \
+ cpustate->regs.b[Mod_RM.RM.b[ModRM]]=val; \
+ else \
+ WriteByte( (*GetEA[ModRM])(cpustate) ,val); \
+}
+
+#define PutImmRMByte(ModRM) \
+{ \
+ if (ModRM >= 0xc0) \
+ cpustate->regs.b[Mod_RM.RM.b[ModRM]]=FETCH; \
+ else { \
+ (*GetEA[ModRM])(cpustate); \
+ WriteByte( cpustate->ea , FETCH ); \
+ } \
+}
+
+#define PutbackRMByte(ModRM,val) \
+{ \
+ if (ModRM >= 0xc0) \
+ cpustate->regs.b[Mod_RM.RM.b[ModRM]]=val; \
+ else \
+ WriteByte(cpustate->ea,val); \
+}
+
+#define DEF_br8(dst,src) \
+ unsigned ModRM = FETCHOP; \
+ unsigned src = RegByte(ModRM); \
+ unsigned dst = GetRMByte(ModRM)
+
+#define DEF_wr16(dst,src) \
+ unsigned ModRM = FETCHOP; \
+ unsigned src = RegWord(ModRM); \
+ unsigned dst = GetRMWord(ModRM)
+
+#define DEF_r8b(dst,src) \
+ unsigned ModRM = FETCHOP; \
+ unsigned dst = RegByte(ModRM); \
+ unsigned src = GetRMByte(ModRM)
+
+#define DEF_r16w(dst,src) \
+ unsigned ModRM = FETCHOP; \
+ unsigned dst = RegWord(ModRM); \
+ unsigned src = GetRMWord(ModRM)
+
+#define DEF_ald8(dst,src) \
+ unsigned src = FETCHOP; \
+ unsigned dst = cpustate->regs.b[AL]
+
+#define DEF_axd16(dst,src) \
+ unsigned src = FETCHOP; \
+ unsigned dst = cpustate->regs.w[AX]; \
+ src += (FETCH << 8)
diff --git a/trunk/src/emu/cpu/i86/modrm286.h b/trunk/src/emu/cpu/i86/modrm286.h
new file mode 100644
index 00000000000..18c2495b7d8
--- /dev/null
+++ b/trunk/src/emu/cpu/i86/modrm286.h
@@ -0,0 +1,145 @@
+static struct
+{
+ struct
+ {
+ WREGS w[256];
+ BREGS b[256];
+ } reg;
+ struct
+ {
+ WREGS w[256];
+ BREGS b[256];
+ } RM;
+} Mod_RM;
+
+#define RegWord(ModRM) cpustate->regs.w[Mod_RM.reg.w[ModRM]]
+#define RegByte(ModRM) cpustate->regs.b[Mod_RM.reg.b[ModRM]]
+
+#define GetRMWord(ModRM) \
+ ((ModRM) >= 0xc0 ? cpustate->regs.w[Mod_RM.RM.w[ModRM]] : ( (*GetEA[ModRM])(cpustate), i80286_check_permission(cpustate, cpustate->ea_seg, cpustate->eo, I80286_WORD, I80286_READ), ReadWord( cpustate->ea ) ))
+
+#define PutbackRMWord(ModRM,val) \
+{ \
+ if (ModRM >= 0xc0) cpustate->regs.w[Mod_RM.RM.w[ModRM]]=val; \
+ else \
+ { \
+ i80286_check_permission(cpustate, cpustate->ea_seg, cpustate->eo, I80286_WORD, I80286_WRITE); \
+ WriteWord(cpustate->ea,val); \
+ } \
+}
+
+#define GetnextRMWord \
+ ( \
+ i80286_check_permission(cpustate, cpustate->ea_seg, cpustate->ea + 2 - cpustate->base[cpustate->ea_seg], I80286_WORD, I80286_READ), \
+ ReadWord(cpustate->ea+2) \
+ )
+
+#define GetRMWordOffset(offs) \
+ ( \
+ i80286_check_permission(cpustate, cpustate->ea_seg, (UINT16)(cpustate->eo+offs), I80286_WORD, I80286_READ), \
+ ReadWord(cpustate->ea-cpustate->eo+(UINT16)(cpustate->eo+offs)) \
+ )
+
+#define GetRMByteOffset(offs) \
+ ( \
+ i80286_check_permission(cpustate, cpustate->ea_seg, (UINT16)(cpustate->eo+offs), I80286_BYTE, I80286_READ), \
+ ReadByte(cpustate->ea-cpustate->eo+(UINT16)(cpustate->eo+offs)) \
+ )
+
+#define PutRMWord(ModRM,val) \
+{ \
+ if (ModRM >= 0xc0) \
+ cpustate->regs.w[Mod_RM.RM.w[ModRM]]=val; \
+ else { \
+ (*GetEA[ModRM])(cpustate); \
+ i80286_check_permission(cpustate, cpustate->ea_seg, cpustate->eo, I80286_WORD, I80286_WRITE); \
+ WriteWord( cpustate->ea ,val); \
+ } \
+}
+
+#define PutRMWordOffset(offs, val) \
+ i80286_check_permission(cpustate, cpustate->ea_seg, (UINT16)(cpustate->eo+offs), I80286_WORD, I80286_WRITE); \
+ WriteWord( cpustate->ea-cpustate->eo+(UINT16)(cpustate->eo+offs), val)
+
+#define PutRMByteOffset(offs, val) \
+ i80286_check_permission(cpustate, cpustate->ea_seg, (UINT16)(cpustate->eo+offs), I80286_BYTE, I80286_WRITE); \
+ WriteByte( cpustate->ea-cpustate->eo+(UINT16)(cpustate->eo+offs), val)
+
+#define PutImmRMWord(ModRM) \
+{ \
+ WORD val; \
+ if (ModRM >= 0xc0) \
+ FETCHWORD(cpustate->regs.w[Mod_RM.RM.w[ModRM]]) \
+ else { \
+ (*GetEA[ModRM])(cpustate); \
+ i80286_check_permission(cpustate, cpustate->ea_seg, cpustate->eo, I80286_WORD, I80286_WRITE); \
+ FETCHWORD(val) \
+ WriteWord( cpustate->ea , val); \
+ } \
+}
+
+#define GetRMByte(ModRM) \
+ ((ModRM) >= 0xc0 ? cpustate->regs.b[Mod_RM.RM.b[ModRM]] : ( (*GetEA[ModRM])(cpustate), i80286_check_permission(cpustate, cpustate->ea_seg, cpustate->eo, I80286_BYTE, I80286_READ), ReadByte( cpustate->ea )) )
+
+#define PutRMByte(ModRM,val) \
+{ \
+ if (ModRM >= 0xc0) \
+ cpustate->regs.b[Mod_RM.RM.b[ModRM]]=val; \
+ else \
+ { \
+ (*GetEA[ModRM])(cpustate); \
+ i80286_check_permission(cpustate, cpustate->ea_seg, cpustate->eo, I80286_BYTE, I80286_WRITE); \
+ WriteByte( cpustate->ea,val); \
+ } \
+}
+
+#define PutImmRMByte(ModRM) \
+{ \
+ if (ModRM >= 0xc0) \
+ cpustate->regs.b[Mod_RM.RM.b[ModRM]]=FETCH; \
+ else { \
+ (*GetEA[ModRM])(cpustate); \
+ i80286_check_permission(cpustate, cpustate->ea_seg, cpustate->eo, I80286_BYTE, I80286_WRITE); \
+ WriteByte( cpustate->ea , FETCH ); \
+ } \
+}
+
+#define PutbackRMByte(ModRM,val) \
+{ \
+ if (ModRM >= 0xc0) \
+ cpustate->regs.b[Mod_RM.RM.b[ModRM]]=val; \
+ else \
+ { \
+ i80286_check_permission(cpustate, cpustate->ea_seg, cpustate->eo, I80286_BYTE, I80286_WRITE); \
+ WriteByte(cpustate->ea,val); \
+ } \
+}
+
+#define DEF_br8(dst,src) \
+ unsigned ModRM = FETCHOP; \
+ unsigned src = RegByte(ModRM); \
+ unsigned dst = GetRMByte(ModRM)
+
+#define DEF_wr16(dst,src) \
+ unsigned ModRM = FETCHOP; \
+ unsigned src = RegWord(ModRM); \
+ unsigned dst = GetRMWord(ModRM)
+
+#define DEF_r8b(dst,src) \
+ unsigned ModRM = FETCHOP; \
+ unsigned dst = RegByte(ModRM); \
+ unsigned src = GetRMByte(ModRM)
+
+#define DEF_r16w(dst,src) \
+ unsigned ModRM = FETCHOP; \
+ unsigned dst = RegWord(ModRM); \
+ unsigned src = GetRMWord(ModRM)
+
+#define DEF_ald8(dst,src) \
+ unsigned src = FETCHOP; \
+ unsigned dst = cpustate->regs.b[AL]
+
+#define DEF_axd16(dst,src) \
+ unsigned src = FETCHOP; \
+ unsigned dst = cpustate->regs.w[AX]; \
+ src += (FETCH << 8)
diff --git a/trunk/src/emu/cpu/i86/table186.h b/trunk/src/emu/cpu/i86/table186.h
new file mode 100644
index 00000000000..e531d156380
--- /dev/null
+++ b/trunk/src/emu/cpu/i86/table186.h
@@ -0,0 +1,525 @@
+static void (*const PREFIX186(_instruction)[256])(i8086_state *cpustate) =
+{
+ PREFIX86(_add_br8), /* 0x00 */
+ PREFIX86(_add_wr16), /* 0x01 */
+ PREFIX86(_add_r8b), /* 0x02 */
+ PREFIX86(_add_r16w), /* 0x03 */
+ PREFIX86(_add_ald8), /* 0x04 */
+ PREFIX86(_add_axd16), /* 0x05 */
+ PREFIX86(_push_es), /* 0x06 */
+ PREFIX86(_pop_es), /* 0x07 */
+ PREFIX86(_or_br8), /* 0x08 */
+ PREFIX86(_or_wr16), /* 0x09 */
+ PREFIX86(_or_r8b), /* 0x0a */
+ PREFIX86(_or_r16w), /* 0x0b */
+ PREFIX86(_or_ald8), /* 0x0c */
+ PREFIX86(_or_axd16), /* 0x0d */
+ PREFIX86(_push_cs), /* 0x0e */
+ PREFIX86(_invalid),
+ PREFIX86(_adc_br8), /* 0x10 */
+ PREFIX86(_adc_wr16), /* 0x11 */
+ PREFIX86(_adc_r8b), /* 0x12 */
+ PREFIX86(_adc_r16w), /* 0x13 */
+ PREFIX86(_adc_ald8), /* 0x14 */
+ PREFIX86(_adc_axd16), /* 0x15 */
+ PREFIX86(_push_ss), /* 0x16 */
+ PREFIX186(_pop_ss), /* 0x17 */
+ PREFIX86(_sbb_br8), /* 0x18 */
+ PREFIX86(_sbb_wr16), /* 0x19 */
+ PREFIX86(_sbb_r8b), /* 0x1a */
+ PREFIX86(_sbb_r16w), /* 0x1b */
+ PREFIX86(_sbb_ald8), /* 0x1c */
+ PREFIX86(_sbb_axd16), /* 0x1d */
+ PREFIX86(_push_ds), /* 0x1e */
+ PREFIX86(_pop_ds), /* 0x1f */
+ PREFIX86(_and_br8), /* 0x20 */
+ PREFIX86(_and_wr16), /* 0x21 */
+ PREFIX86(_and_r8b), /* 0x22 */
+ PREFIX86(_and_r16w), /* 0x23 */
+ PREFIX86(_and_ald8), /* 0x24 */
+ PREFIX86(_and_axd16), /* 0x25 */
+ PREFIX186(_es), /* 0x26 */
+ PREFIX86(_daa), /* 0x27 */
+ PREFIX86(_sub_br8), /* 0x28 */
+ PREFIX86(_sub_wr16), /* 0x29 */
+ PREFIX86(_sub_r8b), /* 0x2a */
+ PREFIX86(_sub_r16w), /* 0x2b */
+ PREFIX86(_sub_ald8), /* 0x2c */
+ PREFIX86(_sub_axd16), /* 0x2d */
+ PREFIX186(_cs), /* 0x2e */
+ PREFIX86(_das), /* 0x2f */
+ PREFIX86(_xor_br8), /* 0x30 */
+ PREFIX86(_xor_wr16), /* 0x31 */
+ PREFIX86(_xor_r8b), /* 0x32 */
+ PREFIX86(_xor_r16w), /* 0x33 */
+ PREFIX86(_xor_ald8), /* 0x34 */
+ PREFIX86(_xor_axd16), /* 0x35 */
+ PREFIX186(_ss), /* 0x36 */
+ PREFIX86(_aaa), /* 0x37 */
+ PREFIX86(_cmp_br8), /* 0x38 */
+ PREFIX86(_cmp_wr16), /* 0x39 */
+ PREFIX86(_cmp_r8b), /* 0x3a */
+ PREFIX86(_cmp_r16w), /* 0x3b */
+ PREFIX86(_cmp_ald8), /* 0x3c */
+ PREFIX86(_cmp_axd16), /* 0x3d */
+ PREFIX186(_ds), /* 0x3e */
+ PREFIX86(_aas), /* 0x3f */
+ PREFIX86(_inc_ax), /* 0x40 */
+ PREFIX86(_inc_cx), /* 0x41 */
+ PREFIX86(_inc_dx), /* 0x42 */
+ PREFIX86(_inc_bx), /* 0x43 */
+ PREFIX86(_inc_sp), /* 0x44 */
+ PREFIX86(_inc_bp), /* 0x45 */
+ PREFIX86(_inc_si), /* 0x46 */
+ PREFIX86(_inc_di), /* 0x47 */
+ PREFIX86(_dec_ax), /* 0x48 */
+ PREFIX86(_dec_cx), /* 0x49 */
+ PREFIX86(_dec_dx), /* 0x4a */
+ PREFIX86(_dec_bx), /* 0x4b */
+ PREFIX86(_dec_sp), /* 0x4c */
+ PREFIX86(_dec_bp), /* 0x4d */
+ PREFIX86(_dec_si), /* 0x4e */
+ PREFIX86(_dec_di), /* 0x4f */
+ PREFIX86(_push_ax), /* 0x50 */
+ PREFIX86(_push_cx), /* 0x51 */
+ PREFIX86(_push_dx), /* 0x52 */
+ PREFIX86(_push_bx), /* 0x53 */
+ PREFIX86(_push_sp), /* 0x54 */
+ PREFIX86(_push_bp), /* 0x55 */
+ PREFIX86(_push_si), /* 0x56 */
+ PREFIX86(_push_di), /* 0x57 */
+ PREFIX86(_pop_ax), /* 0x58 */
+ PREFIX86(_pop_cx), /* 0x59 */
+ PREFIX86(_pop_dx), /* 0x5a */
+ PREFIX86(_pop_bx), /* 0x5b */
+ PREFIX86(_pop_sp), /* 0x5c */
+ PREFIX86(_pop_bp), /* 0x5d */
+ PREFIX86(_pop_si), /* 0x5e */
+ PREFIX86(_pop_di), /* 0x5f */
+ PREFIX186(_pusha), /* 0x60 */
+ PREFIX186(_popa), /* 0x61 */
+ PREFIX186(_bound), /* 0x62 */
+ PREFIX86(_invalid),
+ PREFIX86(_invalid),
+ PREFIX86(_invalid),
+ PREFIX86(_invalid),
+ PREFIX86(_invalid),
+ PREFIX186(_push_d16), /* 0x68 */
+ PREFIX186(_imul_d16), /* 0x69 */
+ PREFIX186(_push_d8), /* 0x6a */
+ PREFIX186(_imul_d8), /* 0x6b */
+ PREFIX186(_insb), /* 0x6c */
+ PREFIX186(_insw), /* 0x6d */
+ PREFIX186(_outsb), /* 0x6e */
+ PREFIX186(_outsw), /* 0x6f */
+ PREFIX86(_jo), /* 0x70 */
+ PREFIX86(_jno), /* 0x71 */
+ PREFIX86(_jb), /* 0x72 */
+ PREFIX86(_jnb), /* 0x73 */
+ PREFIX86(_jz), /* 0x74 */
+ PREFIX86(_jnz), /* 0x75 */
+ PREFIX86(_jbe), /* 0x76 */
+ PREFIX86(_jnbe), /* 0x77 */
+ PREFIX86(_js), /* 0x78 */
+ PREFIX86(_jns), /* 0x79 */
+ PREFIX86(_jp), /* 0x7a */
+ PREFIX86(_jnp), /* 0x7b */
+ PREFIX86(_jl), /* 0x7c */
+ PREFIX86(_jnl), /* 0x7d */
+ PREFIX86(_jle), /* 0x7e */
+ PREFIX86(_jnle), /* 0x7f */
+ PREFIX86(_80pre), /* 0x80 */
+ PREFIX86(_81pre), /* 0x81 */
+ PREFIX86(_82pre), /* 0x82 */
+ PREFIX86(_83pre), /* 0x83 */
+ PREFIX86(_test_br8), /* 0x84 */
+ PREFIX86(_test_wr16), /* 0x85 */
+ PREFIX86(_xchg_br8), /* 0x86 */
+ PREFIX86(_xchg_wr16), /* 0x87 */
+ PREFIX86(_mov_br8), /* 0x88 */
+ PREFIX86(_mov_wr16), /* 0x89 */
+ PREFIX86(_mov_r8b), /* 0x8a */
+ PREFIX86(_mov_r16w), /* 0x8b */
+ PREFIX86(_mov_wsreg), /* 0x8c */
+ PREFIX86(_lea), /* 0x8d */
+ PREFIX186(_mov_sregw), /* 0x8e */
+ PREFIX86(_popw), /* 0x8f */
+ PREFIX86(_nop), /* 0x90 */
+ PREFIX86(_xchg_axcx), /* 0x91 */
+ PREFIX86(_xchg_axdx), /* 0x92 */
+ PREFIX86(_xchg_axbx), /* 0x93 */
+ PREFIX86(_xchg_axsp), /* 0x94 */
+ PREFIX86(_xchg_axbp), /* 0x95 */
+ PREFIX86(_xchg_axsi), /* 0x97 */
+ PREFIX86(_xchg_axdi), /* 0x97 */
+ PREFIX86(_cbw), /* 0x98 */
+ PREFIX86(_cwd), /* 0x99 */
+ PREFIX86(_call_far), /* 0x9a */
+ PREFIX86(_wait), /* 0x9b */
+ PREFIX86(_pushf), /* 0x9c */
+ PREFIX86(_popf), /* 0x9d */
+ PREFIX86(_sahf), /* 0x9e */
+ PREFIX86(_lahf), /* 0x9f */
+ PREFIX86(_mov_aldisp), /* 0xa0 */
+ PREFIX86(_mov_axdisp), /* 0xa1 */
+ PREFIX86(_mov_dispal), /* 0xa2 */
+ PREFIX86(_mov_dispax), /* 0xa3 */
+ PREFIX86(_movsb), /* 0xa4 */
+ PREFIX86(_movsw), /* 0xa5 */
+ PREFIX86(_cmpsb), /* 0xa6 */
+ PREFIX86(_cmpsw), /* 0xa7 */
+ PREFIX86(_test_ald8), /* 0xa8 */
+ PREFIX86(_test_axd16), /* 0xa9 */
+ PREFIX86(_stosb), /* 0xaa */
+ PREFIX86(_stosw), /* 0xab */
+ PREFIX86(_lodsb), /* 0xac */
+ PREFIX86(_lodsw), /* 0xad */
+ PREFIX86(_scasb), /* 0xae */
+ PREFIX86(_scasw), /* 0xaf */
+ PREFIX86(_mov_ald8), /* 0xb0 */
+ PREFIX86(_mov_cld8), /* 0xb1 */
+ PREFIX86(_mov_dld8), /* 0xb2 */
+ PREFIX86(_mov_bld8), /* 0xb3 */
+ PREFIX86(_mov_ahd8), /* 0xb4 */
+ PREFIX86(_mov_chd8), /* 0xb5 */
+ PREFIX86(_mov_dhd8), /* 0xb6 */
+ PREFIX86(_mov_bhd8), /* 0xb7 */
+ PREFIX86(_mov_axd16), /* 0xb8 */
+ PREFIX86(_mov_cxd16), /* 0xb9 */
+ PREFIX86(_mov_dxd16), /* 0xba */
+ PREFIX86(_mov_bxd16), /* 0xbb */
+ PREFIX86(_mov_spd16), /* 0xbc */
+ PREFIX86(_mov_bpd16), /* 0xbd */
+ PREFIX86(_mov_sid16), /* 0xbe */
+ PREFIX86(_mov_did16), /* 0xbf */
+ PREFIX186(_rotshft_bd8), /* 0xc0 */
+ PREFIX186(_rotshft_wd8), /* 0xc1 */
+ PREFIX86(_ret_d16), /* 0xc2 */
+ PREFIX86(_ret), /* 0xc3 */
+ PREFIX86(_les_dw), /* 0xc4 */
+ PREFIX86(_lds_dw), /* 0xc5 */
+ PREFIX86(_mov_bd8), /* 0xc6 */
+ PREFIX86(_mov_wd16), /* 0xc7 */
+ PREFIX186(_enter), /* 0xc8 */
+ PREFIX186(_leave), /* 0xc9 */
+ PREFIX86(_retf_d16), /* 0xca */
+ PREFIX86(_retf), /* 0xcb */
+ PREFIX86(_int3), /* 0xcc */
+ PREFIX86(_int), /* 0xcd */
+ PREFIX86(_into), /* 0xce */
+ PREFIX86(_iret), /* 0xcf */
+ PREFIX86(_rotshft_b), /* 0xd0 */
+ PREFIX86(_rotshft_w), /* 0xd1 */
+ PREFIX186(_rotshft_bcl), /* 0xd2 */
+ PREFIX186(_rotshft_wcl), /* 0xd3 */
+ PREFIX86(_aam), /* 0xd4 */
+ PREFIX86(_aad), /* 0xd5 */
+ PREFIX86(_invalid),
+ PREFIX86(_xlat), /* 0xd7 */
+ PREFIX86(_escape), /* 0xd8 */
+ PREFIX86(_escape), /* 0xd9 */
+ PREFIX86(_escape), /* 0xda */
+ PREFIX86(_escape), /* 0xdb */
+ PREFIX86(_escape), /* 0xdc */
+ PREFIX86(_escape), /* 0xdd */
+ PREFIX86(_escape), /* 0xde */
+ PREFIX86(_escape), /* 0xdf */
+ PREFIX86(_loopne), /* 0xe0 */
+ PREFIX86(_loope), /* 0xe1 */
+ PREFIX86(_loop), /* 0xe2 */
+ PREFIX86(_jcxz), /* 0xe3 */
+ PREFIX86(_inal), /* 0xe4 */
+ PREFIX86(_inax), /* 0xe5 */
+ PREFIX86(_outal), /* 0xe6 */
+ PREFIX86(_outax), /* 0xe7 */
+ PREFIX86(_call_d16), /* 0xe8 */
+ PREFIX86(_jmp_d16), /* 0xe9 */
+ PREFIX86(_jmp_far), /* 0xea */
+ PREFIX86(_jmp_d8), /* 0xeb */
+ PREFIX86(_inaldx), /* 0xec */
+ PREFIX86(_inaxdx), /* 0xed */
+ PREFIX86(_outdxal), /* 0xee */
+ PREFIX86(_outdxax), /* 0xef */
+ PREFIX86(_lock), /* 0xf0 */
+ PREFIX86(_invalid), /* 0xf1 */
+ PREFIX186(_repne), /* 0xf2 */
+ PREFIX186(_repe), /* 0xf3 */
+ PREFIX86(_hlt), /* 0xf4 */
+ PREFIX86(_cmc), /* 0xf5 */
+ PREFIX86(_f6pre), /* 0xf6 */
+ PREFIX86(_f7pre), /* 0xf7 */
+ PREFIX86(_clc), /* 0xf8 */
+ PREFIX86(_stc), /* 0xf9 */
+ PREFIX86(_cli), /* 0xfa */
+ PREFIX186(_sti), /* 0xfb */
+ PREFIX86(_cld), /* 0xfc */
+ PREFIX86(_std), /* 0xfd */
+ PREFIX86(_fepre), /* 0xfe */
+ PREFIX86(_ffpre) /* 0xff */
+};
+
+#if defined(BIGCASE) && !defined(RS6000)
+ /* Some compilers cannot handle large case statements */
+#define TABLE186 \
+ switch(FETCHOP)\
+ {\
+ case 0x00: PREFIX86(_add_br8)(cpustate); break;\
+ case 0x01: PREFIX86(_add_wr16)(cpustate); break;\
+ case 0x02: PREFIX86(_add_r8b)(cpustate); break;\
+ case 0x03: PREFIX86(_add_r16w)(cpustate); break;\
+ case 0x04: PREFIX86(_add_ald8)(cpustate); break;\
+ case 0x05: PREFIX86(_add_axd16)(cpustate); break;\
+ case 0x06: PREFIX86(_push_es)(cpustate); break;\
+ case 0x07: PREFIX86(_pop_es)(cpustate); break;\
+ case 0x08: PREFIX86(_or_br8)(cpustate); break;\
+ case 0x09: PREFIX86(_or_wr16)(cpustate); break;\
+ case 0x0a: PREFIX86(_or_r8b)(cpustate); break;\
+ case 0x0b: PREFIX86(_or_r16w)(cpustate); break;\
+ case 0x0c: PREFIX86(_or_ald8)(cpustate); break;\
+ case 0x0d: PREFIX86(_or_axd16)(cpustate); break;\
+ case 0x0e: PREFIX86(_push_cs)(cpustate); break;\
+ case 0x0f: PREFIX86(_invalid)(cpustate); break;\
+ case 0x10: PREFIX86(_adc_br8)(cpustate); break;\
+ case 0x11: PREFIX86(_adc_wr16)(cpustate); break;\
+ case 0x12: PREFIX86(_adc_r8b)(cpustate); break;\
+ case 0x13: PREFIX86(_adc_r16w)(cpustate); break;\
+ case 0x14: PREFIX86(_adc_ald8)(cpustate); break;\
+ case 0x15: PREFIX86(_adc_axd16)(cpustate); break;\
+ case 0x16: PREFIX86(_push_ss)(cpustate); break;\
+ case 0x17: PREFIX86(_pop_ss)(cpustate); break;\
+ case 0x18: PREFIX86(_sbb_br8)(cpustate); break;\
+ case 0x19: PREFIX86(_sbb_wr16)(cpustate); break;\
+ case 0x1a: PREFIX86(_sbb_r8b)(cpustate); break;\
+ case 0x1b: PREFIX86(_sbb_r16w)(cpustate); break;\
+ case 0x1c: PREFIX86(_sbb_ald8)(cpustate); break;\
+ case 0x1d: PREFIX86(_sbb_axd16)(cpustate); break;\
+ case 0x1e: PREFIX86(_push_ds)(cpustate); break;\
+ case 0x1f: PREFIX86(_pop_ds)(cpustate); break;\
+ case 0x20: PREFIX86(_and_br8)(cpustate); break;\
+ case 0x21: PREFIX86(_and_wr16)(cpustate); break;\
+ case 0x22: PREFIX86(_and_r8b)(cpustate); break;\
+ case 0x23: PREFIX86(_and_r16w)(cpustate); break;\
+ case 0x24: PREFIX86(_and_ald8)(cpustate); break;\
+ case 0x25: PREFIX86(_and_axd16)(cpustate); break;\
+ case 0x26: PREFIX86(_es)(cpustate); break;\
+ case 0x27: PREFIX86(_daa)(cpustate); break;\
+ case 0x28: PREFIX86(_sub_br8)(cpustate); break;\
+ case 0x29: PREFIX86(_sub_wr16)(cpustate); break;\
+ case 0x2a: PREFIX86(_sub_r8b)(cpustate); break;\
+ case 0x2b: PREFIX86(_sub_r16w)(cpustate); break;\
+ case 0x2c: PREFIX86(_sub_ald8)(cpustate); break;\
+ case 0x2d: PREFIX86(_sub_axd16)(cpustate); break;\
+ case 0x2e: PREFIX86(_cs)(cpustate); break;\
+ case 0x2f: PREFIX86(_das)(cpustate); break;\
+ case 0x30: PREFIX86(_xor_br8)(cpustate); break;\
+ case 0x31: PREFIX86(_xor_wr16)(cpustate); break;\
+ case 0x32: PREFIX86(_xor_r8b)(cpustate); break;\
+ case 0x33: PREFIX86(_xor_r16w)(cpustate); break;\
+ case 0x34: PREFIX86(_xor_ald8)(cpustate); break;\
+ case 0x35: PREFIX86(_xor_axd16)(cpustate); break;\
+ case 0x36: PREFIX86(_ss)(cpustate); break;\
+ case 0x37: PREFIX86(_aaa)(cpustate); break;\
+ case 0x38: PREFIX86(_cmp_br8)(cpustate); break;\
+ case 0x39: PREFIX86(_cmp_wr16)(cpustate); break;\
+ case 0x3a: PREFIX86(_cmp_r8b)(cpustate); break;\
+ case 0x3b: PREFIX86(_cmp_r16w)(cpustate); break;\
+ case 0x3c: PREFIX86(_cmp_ald8)(cpustate); break;\
+ case 0x3d: PREFIX86(_cmp_axd16)(cpustate); break;\
+ case 0x3e: PREFIX86(_ds)(cpustate); break;\
+ case 0x3f: PREFIX86(_aas)(cpustate); break;\
+ case 0x40: PREFIX86(_inc_ax)(cpustate); break;\
+ case 0x41: PREFIX86(_inc_cx)(cpustate); break;\
+ case 0x42: PREFIX86(_inc_dx)(cpustate); break;\
+ case 0x43: PREFIX86(_inc_bx)(cpustate); break;\
+ case 0x44: PREFIX86(_inc_sp)(cpustate); break;\
+ case 0x45: PREFIX86(_inc_bp)(cpustate); break;\
+ case 0x46: PREFIX86(_inc_si)(cpustate); break;\
+ case 0x47: PREFIX86(_inc_di)(cpustate); break;\
+ case 0x48: PREFIX86(_dec_ax)(cpustate); break;\
+ case 0x49: PREFIX86(_dec_cx)(cpustate); break;\
+ case 0x4a: PREFIX86(_dec_dx)(cpustate); break;\
+ case 0x4b: PREFIX86(_dec_bx)(cpustate); break;\
+ case 0x4c: PREFIX86(_dec_sp)(cpustate); break;\
+ case 0x4d: PREFIX86(_dec_bp)(cpustate); break;\
+ case 0x4e: PREFIX86(_dec_si)(cpustate); break;\
+ case 0x4f: PREFIX86(_dec_di)(cpustate); break;\
+ case 0x50: PREFIX86(_push_ax)(cpustate); break;\
+ case 0x51: PREFIX86(_push_cx)(cpustate); break;\
+ case 0x52: PREFIX86(_push_dx)(cpustate); break;\
+ case 0x53: PREFIX86(_push_bx)(cpustate); break;\
+ case 0x54: PREFIX86(_push_sp)(cpustate); break;\
+ case 0x55: PREFIX86(_push_bp)(cpustate); break;\
+ case 0x56: PREFIX86(_push_si)(cpustate); break;\
+ case 0x57: PREFIX86(_push_di)(cpustate); break;\
+ case 0x58: PREFIX86(_pop_ax)(cpustate); break;\
+ case 0x59: PREFIX86(_pop_cx)(cpustate); break;\
+ case 0x5a: PREFIX86(_pop_dx)(cpustate); break;\
+ case 0x5b: PREFIX86(_pop_bx)(cpustate); break;\
+ case 0x5c: PREFIX86(_pop_sp)(cpustate); break;\
+ case 0x5d: PREFIX86(_pop_bp)(cpustate); break;\
+ case 0x5e: PREFIX86(_pop_si)(cpustate); break;\
+ case 0x5f: PREFIX86(_pop_di)(cpustate); break;\
+ case 0x60: PREFIX186(_pusha)(cpustate); break;\
+ case 0x61: PREFIX186(_popa)(cpustate); break;\
+ case 0x62: PREFIX186(_bound)(cpustate); break;\
+ case 0x63: PREFIX86(_invalid)(cpustate); break;\
+ case 0x64: PREFIX86(_invalid)(cpustate); break;\
+ case 0x65: PREFIX86(_invalid)(cpustate); break;\
+ case 0x66: PREFIX86(_invalid)(cpustate); break;\
+ case 0x67: PREFIX86(_invalid)(cpustate); break;\
+ case 0x68: PREFIX186(_push_d16)(cpustate); break;\
+ case 0x69: PREFIX186(_imul_d16)(cpustate); break;\
+ case 0x6a: PREFIX186(_push_d8)(cpustate); break;\
+ case 0x6b: PREFIX186(_imul_d8)(cpustate); break;\
+ case 0x6c: PREFIX186(_insb)(cpustate); break;\
+ case 0x6d: PREFIX186(_insw)(cpustate); break;\
+ case 0x6e: PREFIX186(_outsb)(cpustate); break;\
+ case 0x6f: PREFIX186(_outsw)(cpustate); break;\
+ case 0x70: PREFIX86(_jo)(cpustate); break;\
+ case 0x71: PREFIX86(_jno)(cpustate); break;\
+ case 0x72: PREFIX86(_jb)(cpustate); break;\
+ case 0x73: PREFIX86(_jnb)(cpustate); break;\
+ case 0x74: PREFIX86(_jz)(cpustate); break;\
+ case 0x75: PREFIX86(_jnz)(cpustate); break;\
+ case 0x76: PREFIX86(_jbe)(cpustate); break;\
+ case 0x77: PREFIX86(_jnbe)(cpustate); break;\
+ case 0x78: PREFIX86(_js)(cpustate); break;\
+ case 0x79: PREFIX86(_jns)(cpustate); break;\
+ case 0x7a: PREFIX86(_jp)(cpustate); break;\
+ case 0x7b: PREFIX86(_jnp)(cpustate); break;\
+ case 0x7c: PREFIX86(_jl)(cpustate); break;\
+ case 0x7d: PREFIX86(_jnl)(cpustate); break;\
+ case 0x7e: PREFIX86(_jle)(cpustate); break;\
+ case 0x7f: PREFIX86(_jnle)(cpustate); break;\
+ case 0x80: PREFIX86(_80pre)(cpustate); break;\
+ case 0x81: PREFIX86(_81pre)(cpustate); break;\
+ case 0x82: PREFIX86(_82pre)(cpustate); break;\
+ case 0x83: PREFIX86(_83pre)(cpustate); break;\
+ case 0x84: PREFIX86(_test_br8)(cpustate); break;\
+ case 0x85: PREFIX86(_test_wr16)(cpustate); break;\
+ case 0x86: PREFIX86(_xchg_br8)(cpustate); break;\
+ case 0x87: PREFIX86(_xchg_wr16)(cpustate); break;\
+ case 0x88: PREFIX86(_mov_br8)(cpustate); break;\
+ case 0x89: PREFIX86(_mov_wr16)(cpustate); break;\
+ case 0x8a: PREFIX86(_mov_r8b)(cpustate); break;\
+ case 0x8b: PREFIX86(_mov_r16w)(cpustate); break;\
+ case 0x8c: PREFIX86(_mov_wsreg)(cpustate); break;\
+ case 0x8d: PREFIX86(_lea)(cpustate); break;\
+ case 0x8e: PREFIX86(_mov_sregw)(cpustate); break;\
+ case 0x8f: PREFIX86(_popw)(cpustate); break;\
+ case 0x90: PREFIX86(_nop)(cpustate); break;\
+ case 0x91: PREFIX86(_xchg_axcx)(cpustate); break;\
+ case 0x92: PREFIX86(_xchg_axdx)(cpustate); break;\
+ case 0x93: PREFIX86(_xchg_axbx)(cpustate); break;\
+ case 0x94: PREFIX86(_xchg_axsp)(cpustate); break;\
+ case 0x95: PREFIX86(_xchg_axbp)(cpustate); break;\
+ case 0x96: PREFIX86(_xchg_axsi)(cpustate); break;\
+ case 0x97: PREFIX86(_xchg_axdi)(cpustate); break;\
+ case 0x98: PREFIX86(_cbw)(cpustate); break;\
+ case 0x99: PREFIX86(_cwd)(cpustate); break;\
+ case 0x9a: PREFIX86(_call_far)(cpustate); break;\
+ case 0x9b: PREFIX86(_wait)(cpustate); break;\
+ case 0x9c: PREFIX86(_pushf)(cpustate); break;\
+ case 0x9d: PREFIX86(_popf)(cpustate); break;\
+ case 0x9e: PREFIX86(_sahf)(cpustate); break;\
+ case 0x9f: PREFIX86(_lahf)(cpustate); break;\
+ case 0xa0: PREFIX86(_mov_aldisp)(cpustate); break;\
+ case 0xa1: PREFIX86(_mov_axdisp)(cpustate); break;\
+ case 0xa2: PREFIX86(_mov_dispal)(cpustate); break;\
+ case 0xa3: PREFIX86(_mov_dispax)(cpustate); break;\
+ case 0xa4: PREFIX86(_movsb)(cpustate); break;\
+ case 0xa5: PREFIX86(_movsw)(cpustate); break;\
+ case 0xa6: PREFIX86(_cmpsb)(cpustate); break;\
+ case 0xa7: PREFIX86(_cmpsw)(cpustate); break;\
+ case 0xa8: PREFIX86(_test_ald8)(cpustate); break;\
+ case 0xa9: PREFIX86(_test_axd16)(cpustate); break;\
+ case 0xaa: PREFIX86(_stosb)(cpustate); break;\
+ case 0xab: PREFIX86(_stosw)(cpustate); break;\
+ case 0xac: PREFIX86(_lodsb)(cpustate); break;\
+ case 0xad: PREFIX86(_lodsw)(cpustate); break;\
+ case 0xae: PREFIX86(_scasb)(cpustate); break;\
+ case 0xaf: PREFIX86(_scasw)(cpustate); break;\
+ case 0xb0: PREFIX86(_mov_ald8)(cpustate); break;\
+ case 0xb1: PREFIX86(_mov_cld8)(cpustate); break;\
+ case 0xb2: PREFIX86(_mov_dld8)(cpustate); break;\
+ case 0xb3: PREFIX86(_mov_bld8)(cpustate); break;\
+ case 0xb4: PREFIX86(_mov_ahd8)(cpustate); break;\
+ case 0xb5: PREFIX86(_mov_chd8)(cpustate); break;\
+ case 0xb6: PREFIX86(_mov_dhd8)(cpustate); break;\
+ case 0xb7: PREFIX86(_mov_bhd8)(cpustate); break;\
+ case 0xb8: PREFIX86(_mov_axd16)(cpustate); break;\
+ case 0xb9: PREFIX86(_mov_cxd16)(cpustate); break;\
+ case 0xba: PREFIX86(_mov_dxd16)(cpustate); break;\
+ case 0xbb: PREFIX86(_mov_bxd16)(cpustate); break;\
+ case 0xbc: PREFIX86(_mov_spd16)(cpustate); break;\
+ case 0xbd: PREFIX86(_mov_bpd16)(cpustate); break;\
+ case 0xbe: PREFIX86(_mov_sid16)(cpustate); break;\
+ case 0xbf: PREFIX86(_mov_did16)(cpustate); break;\
+ case 0xc0: PREFIX186(_rotshft_bd8)(cpustate); break;\
+ case 0xc1: PREFIX186(_rotshft_wd8)(cpustate); break;\
+ case 0xc2: PREFIX86(_ret_d16)(cpustate); break;\
+ case 0xc3: PREFIX86(_ret)(cpustate); break;\
+ case 0xc4: PREFIX86(_les_dw)(cpustate); break;\
+ case 0xc5: PREFIX86(_lds_dw)(cpustate); break;\
+ case 0xc6: PREFIX86(_mov_bd8)(cpustate); break;\
+ case 0xc7: PREFIX86(_mov_wd16)(cpustate); break;\
+ case 0xc8: PREFIX186(_enter)(cpustate); break;\
+ case 0xc9: PREFIX186(_leave)(cpustate); break;\
+ case 0xca: PREFIX86(_retf_d16)(cpustate); break;\
+ case 0xcb: PREFIX86(_retf)(cpustate); break;\
+ case 0xcc: PREFIX86(_int3)(cpustate); break;\
+ case 0xcd: PREFIX86(_int)(cpustate); break;\
+ case 0xce: PREFIX86(_into)(cpustate); break;\
+ case 0xcf: PREFIX86(_iret)(cpustate); break;\
+ case 0xd0: PREFIX86(_rotshft_b)(cpustate); break;\
+ case 0xd1: PREFIX86(_rotshft_w)(cpustate); break;\
+ case 0xd2: PREFIX186(_rotshft_bcl)(cpustate); break;\
+ case 0xd3: PREFIX186(_rotshft_wcl)(cpustate); break;\
+ case 0xd4: PREFIX86(_aam)(cpustate); break;\
+ case 0xd5: PREFIX86(_aad)(cpustate); break;\
+ case 0xd6: PREFIX86(_invalid)(cpustate); break;\
+ case 0xd7: PREFIX86(_xlat)(cpustate); break;\
+ case 0xd8: PREFIX86(_escape)(cpustate); break;\
+ case 0xd9: PREFIX86(_escape)(cpustate); break;\
+ case 0xda: PREFIX86(_escape)(cpustate); break;\
+ case 0xdb: PREFIX86(_escape)(cpustate); break;\
+ case 0xdc: PREFIX86(_escape)(cpustate); break;\
+ case 0xdd: PREFIX86(_escape)(cpustate); break;\
+ case 0xde: PREFIX86(_escape)(cpustate); break;\
+ case 0xdf: PREFIX86(_escape)(cpustate); break;\
+ case 0xe0: PREFIX86(_loopne)(cpustate); break;\
+ case 0xe1: PREFIX86(_loope)(cpustate); break;\
+ case 0xe2: PREFIX86(_loop)(cpustate); break;\
+ case 0xe3: PREFIX86(_jcxz)(cpustate); break;\
+ case 0xe4: PREFIX86(_inal)(cpustate); break;\
+ case 0xe5: PREFIX86(_inax)(cpustate); break;\
+ case 0xe6: PREFIX86(_outal)(cpustate); break;\
+ case 0xe7: PREFIX86(_outax)(cpustate); break;\
+ case 0xe8: PREFIX86(_call_d16)(cpustate); break;\
+ case 0xe9: PREFIX86(_jmp_d16)(cpustate); break;\
+ case 0xea: PREFIX86(_jmp_far)(cpustate); break;\
+ case 0xeb: PREFIX86(_jmp_d8)(cpustate); break;\
+ case 0xec: PREFIX86(_inaldx)(cpustate); break;\
+ case 0xed: PREFIX86(_inaxdx)(cpustate); break;\
+ case 0xee: PREFIX86(_outdxal)(cpustate); break;\
+ case 0xef: PREFIX86(_outdxax)(cpustate); break;\
+ case 0xf0: PREFIX86(_lock)(cpustate); break;\
+ case 0xf1: PREFIX86(_invalid)(cpustate); break;\
+ case 0xf2: PREFIX186(_repne)(cpustate); break;\
+ case 0xf3: PREFIX186(_repe)(cpustate); break;\
+ case 0xf4: PREFIX86(_hlt)(cpustate); break;\
+ case 0xf5: PREFIX86(_cmc)(cpustate); break;\
+ case 0xf6: PREFIX86(_f6pre)(cpustate); break;\
+ case 0xf7: PREFIX86(_f7pre)(cpustate); break;\
+ case 0xf8: PREFIX86(_clc)(cpustate); break;\
+ case 0xf9: PREFIX86(_stc)(cpustate); break;\
+ case 0xfa: PREFIX86(_cli)(cpustate); break;\
+ case 0xfb: PREFIX186(_sti)(cpustate); break;\
+ case 0xfc: PREFIX86(_cld)(cpustate); break;\
+ case 0xfd: PREFIX86(_std)(cpustate); break;\
+ case 0xfe: PREFIX86(_fepre)(cpustate); break;\
+ case 0xff: PREFIX86(_ffpre)(cpustate); break;\
+ };
+#else
+#define TABLE186 PREFIX186(_instruction)[FETCHOP](cpustate);
+#endif
diff --git a/trunk/src/emu/cpu/i86/table286.h b/trunk/src/emu/cpu/i86/table286.h
new file mode 100644
index 00000000000..0ac2afa7570
--- /dev/null
+++ b/trunk/src/emu/cpu/i86/table286.h
@@ -0,0 +1,530 @@
+/*
+ * special 286 protected mode instructions missing
+ * at the time the same like table186.h
+ */
+
+static void (*const PREFIX286(_instruction)[256])(i8086_state *cpustate) =
+{
+ PREFIX86(_add_br8), /* 0x00 */
+ PREFIX86(_add_wr16), /* 0x01 */
+ PREFIX86(_add_r8b), /* 0x02 */
+ PREFIX86(_add_r16w), /* 0x03 */
+ PREFIX86(_add_ald8), /* 0x04 */
+ PREFIX86(_add_axd16), /* 0x05 */
+ PREFIX86(_push_es), /* 0x06 */
+ PREFIX86(_pop_es), /* 0x07 */
+ PREFIX86(_or_br8), /* 0x08 */
+ PREFIX86(_or_wr16), /* 0x09 */
+ PREFIX86(_or_r8b), /* 0x0a */
+ PREFIX86(_or_r16w), /* 0x0b */
+ PREFIX86(_or_ald8), /* 0x0c */
+ PREFIX86(_or_axd16), /* 0x0d */
+ PREFIX86(_push_cs), /* 0x0e */
+ PREFIX286(_0fpre),
+ PREFIX86(_adc_br8), /* 0x10 */
+ PREFIX86(_adc_wr16), /* 0x11 */
+ PREFIX86(_adc_r8b), /* 0x12 */
+ PREFIX86(_adc_r16w), /* 0x13 */
+ PREFIX86(_adc_ald8), /* 0x14 */
+ PREFIX86(_adc_axd16), /* 0x15 */
+ PREFIX86(_push_ss), /* 0x16 */
+ PREFIX86(_pop_ss), /* 0x17 */
+ PREFIX86(_sbb_br8), /* 0x18 */
+ PREFIX86(_sbb_wr16), /* 0x19 */
+ PREFIX86(_sbb_r8b), /* 0x1a */
+ PREFIX86(_sbb_r16w), /* 0x1b */
+ PREFIX86(_sbb_ald8), /* 0x1c */
+ PREFIX86(_sbb_axd16), /* 0x1d */
+ PREFIX86(_push_ds), /* 0x1e */
+ PREFIX86(_pop_ds), /* 0x1f */
+ PREFIX86(_and_br8), /* 0x20 */
+ PREFIX86(_and_wr16), /* 0x21 */
+ PREFIX86(_and_r8b), /* 0x22 */
+ PREFIX86(_and_r16w), /* 0x23 */
+ PREFIX86(_and_ald8), /* 0x24 */
+ PREFIX86(_and_axd16), /* 0x25 */
+ PREFIX86(_es), /* 0x26 */
+ PREFIX86(_daa), /* 0x27 */
+ PREFIX86(_sub_br8), /* 0x28 */
+ PREFIX86(_sub_wr16), /* 0x29 */
+ PREFIX86(_sub_r8b), /* 0x2a */
+ PREFIX86(_sub_r16w), /* 0x2b */
+ PREFIX86(_sub_ald8), /* 0x2c */
+ PREFIX86(_sub_axd16), /* 0x2d */
+ PREFIX86(_cs), /* 0x2e */
+ PREFIX86(_das), /* 0x2f */
+ PREFIX86(_xor_br8), /* 0x30 */
+ PREFIX86(_xor_wr16), /* 0x31 */
+ PREFIX86(_xor_r8b), /* 0x32 */
+ PREFIX86(_xor_r16w), /* 0x33 */
+ PREFIX86(_xor_ald8), /* 0x34 */
+ PREFIX86(_xor_axd16), /* 0x35 */
+ PREFIX86(_ss), /* 0x36 */
+ PREFIX86(_aaa), /* 0x37 */
+ PREFIX86(_cmp_br8), /* 0x38 */
+ PREFIX86(_cmp_wr16), /* 0x39 */
+ PREFIX86(_cmp_r8b), /* 0x3a */
+ PREFIX86(_cmp_r16w), /* 0x3b */
+ PREFIX86(_cmp_ald8), /* 0x3c */
+ PREFIX86(_cmp_axd16), /* 0x3d */
+ PREFIX86(_ds), /* 0x3e */
+ PREFIX86(_aas), /* 0x3f */
+ PREFIX86(_inc_ax), /* 0x40 */
+ PREFIX86(_inc_cx), /* 0x41 */
+ PREFIX86(_inc_dx), /* 0x42 */
+ PREFIX86(_inc_bx), /* 0x43 */
+ PREFIX86(_inc_sp), /* 0x44 */
+ PREFIX86(_inc_bp), /* 0x45 */
+ PREFIX86(_inc_si), /* 0x46 */
+ PREFIX86(_inc_di), /* 0x47 */
+ PREFIX86(_dec_ax), /* 0x48 */
+ PREFIX86(_dec_cx), /* 0x49 */
+ PREFIX86(_dec_dx), /* 0x4a */
+ PREFIX86(_dec_bx), /* 0x4b */
+ PREFIX86(_dec_sp), /* 0x4c */
+ PREFIX86(_dec_bp), /* 0x4d */
+ PREFIX86(_dec_si), /* 0x4e */
+ PREFIX86(_dec_di), /* 0x4f */
+ PREFIX86(_push_ax), /* 0x50 */
+ PREFIX86(_push_cx), /* 0x51 */
+ PREFIX86(_push_dx), /* 0x52 */
+ PREFIX86(_push_bx), /* 0x53 */
+ PREFIX86(_push_sp), /* 0x54 */
+ PREFIX86(_push_bp), /* 0x55 */
+ PREFIX86(_push_si), /* 0x56 */
+ PREFIX86(_push_di), /* 0x57 */
+ PREFIX86(_pop_ax), /* 0x58 */
+ PREFIX86(_pop_cx), /* 0x59 */
+ PREFIX86(_pop_dx), /* 0x5a */
+ PREFIX86(_pop_bx), /* 0x5b */
+ PREFIX86(_pop_sp), /* 0x5c */
+ PREFIX86(_pop_bp), /* 0x5d */
+ PREFIX86(_pop_si), /* 0x5e */
+ PREFIX86(_pop_di), /* 0x5f */
+ PREFIX186(_pusha), /* 0x60 */
+ PREFIX186(_popa), /* 0x61 */
+ PREFIX186(_bound), /* 0x62 */
+ PREFIX286(_arpl), /* 0x63 */
+ PREFIX286(_invalid),
+ PREFIX286(_invalid),
+ PREFIX286(_invalid),
+ PREFIX286(_invalid),
+ PREFIX186(_push_d16), /* 0x68 */
+ PREFIX186(_imul_d16), /* 0x69 */
+ PREFIX186(_push_d8), /* 0x6a */
+ PREFIX186(_imul_d8), /* 0x6b */
+ PREFIX186(_insb), /* 0x6c */
+ PREFIX186(_insw), /* 0x6d */
+ PREFIX186(_outsb), /* 0x6e */
+ PREFIX186(_outsw), /* 0x6f */
+ PREFIX86(_jo), /* 0x70 */
+ PREFIX86(_jno), /* 0x71 */
+ PREFIX86(_jb), /* 0x72 */
+ PREFIX86(_jnb), /* 0x73 */
+ PREFIX86(_jz), /* 0x74 */
+ PREFIX86(_jnz), /* 0x75 */
+ PREFIX86(_jbe), /* 0x76 */
+ PREFIX86(_jnbe), /* 0x77 */
+ PREFIX86(_js), /* 0x78 */
+ PREFIX86(_jns), /* 0x79 */
+ PREFIX86(_jp), /* 0x7a */
+ PREFIX86(_jnp), /* 0x7b */
+ PREFIX86(_jl), /* 0x7c */
+ PREFIX86(_jnl), /* 0x7d */
+ PREFIX86(_jle), /* 0x7e */
+ PREFIX86(_jnle), /* 0x7f */
+ PREFIX86(_80pre), /* 0x80 */
+ PREFIX86(_81pre), /* 0x81 */
+ PREFIX86(_82pre), /* 0x82 */
+ PREFIX86(_83pre), /* 0x83 */
+ PREFIX86(_test_br8), /* 0x84 */
+ PREFIX86(_test_wr16), /* 0x85 */
+ PREFIX86(_xchg_br8), /* 0x86 */
+ PREFIX86(_xchg_wr16), /* 0x87 */
+ PREFIX86(_mov_br8), /* 0x88 */
+ PREFIX86(_mov_wr16), /* 0x89 */
+ PREFIX86(_mov_r8b), /* 0x8a */
+ PREFIX86(_mov_r16w), /* 0x8b */
+ PREFIX86(_mov_wsreg), /* 0x8c */
+ PREFIX86(_lea), /* 0x8d */
+ PREFIX86(_mov_sregw), /* 0x8e */
+ PREFIX86(_popw), /* 0x8f */
+ PREFIX86(_nop), /* 0x90 */
+ PREFIX86(_xchg_axcx), /* 0x91 */
+ PREFIX86(_xchg_axdx), /* 0x92 */
+ PREFIX86(_xchg_axbx), /* 0x93 */
+ PREFIX86(_xchg_axsp), /* 0x94 */
+ PREFIX86(_xchg_axbp), /* 0x95 */
+ PREFIX86(_xchg_axsi), /* 0x97 */
+ PREFIX86(_xchg_axdi), /* 0x97 */
+ PREFIX86(_cbw), /* 0x98 */
+ PREFIX86(_cwd), /* 0x99 */
+ PREFIX86(_call_far), /* 0x9a */
+ PREFIX86(_wait), /* 0x9b */
+ PREFIX86(_pushf), /* 0x9c */
+ PREFIX286(_popf), /* 0x9d */
+ PREFIX86(_sahf), /* 0x9e */
+ PREFIX86(_lahf), /* 0x9f */
+ PREFIX86(_mov_aldisp), /* 0xa0 */
+ PREFIX86(_mov_axdisp), /* 0xa1 */
+ PREFIX86(_mov_dispal), /* 0xa2 */
+ PREFIX86(_mov_dispax), /* 0xa3 */
+ PREFIX86(_movsb), /* 0xa4 */
+ PREFIX86(_movsw), /* 0xa5 */
+ PREFIX86(_cmpsb), /* 0xa6 */
+ PREFIX86(_cmpsw), /* 0xa7 */
+ PREFIX86(_test_ald8), /* 0xa8 */
+ PREFIX86(_test_axd16), /* 0xa9 */
+ PREFIX86(_stosb), /* 0xaa */
+ PREFIX86(_stosw), /* 0xab */
+ PREFIX86(_lodsb), /* 0xac */
+ PREFIX86(_lodsw), /* 0xad */
+ PREFIX86(_scasb), /* 0xae */
+ PREFIX86(_scasw), /* 0xaf */
+ PREFIX86(_mov_ald8), /* 0xb0 */
+ PREFIX86(_mov_cld8), /* 0xb1 */
+ PREFIX86(_mov_dld8), /* 0xb2 */
+ PREFIX86(_mov_bld8), /* 0xb3 */
+ PREFIX86(_mov_ahd8), /* 0xb4 */
+ PREFIX86(_mov_chd8), /* 0xb5 */
+ PREFIX86(_mov_dhd8), /* 0xb6 */
+ PREFIX86(_mov_bhd8), /* 0xb7 */
+ PREFIX86(_mov_axd16), /* 0xb8 */
+ PREFIX86(_mov_cxd16), /* 0xb9 */
+ PREFIX86(_mov_dxd16), /* 0xba */
+ PREFIX86(_mov_bxd16), /* 0xbb */
+ PREFIX86(_mov_spd16), /* 0xbc */
+ PREFIX86(_mov_bpd16), /* 0xbd */
+ PREFIX86(_mov_sid16), /* 0xbe */
+ PREFIX86(_mov_did16), /* 0xbf */
+ PREFIX186(_rotshft_bd8), /* 0xc0 */
+ PREFIX186(_rotshft_wd8), /* 0xc1 */
+ PREFIX86(_ret_d16), /* 0xc2 */
+ PREFIX86(_ret), /* 0xc3 */
+ PREFIX86(_les_dw), /* 0xc4 */
+ PREFIX86(_lds_dw), /* 0xc5 */
+ PREFIX86(_mov_bd8), /* 0xc6 */
+ PREFIX86(_mov_wd16), /* 0xc7 */
+ PREFIX186(_enter), /* 0xc8 */
+ PREFIX186(_leave), /* 0xc9 */
+ PREFIX286(_retf_d16), /* 0xca */
+ PREFIX286(_retf), /* 0xcb */
+ PREFIX86(_int3), /* 0xcc */
+ PREFIX86(_int), /* 0xcd */
+ PREFIX86(_into), /* 0xce */
+ PREFIX286(_iret), /* 0xcf */
+ PREFIX86(_rotshft_b), /* 0xd0 */
+ PREFIX86(_rotshft_w), /* 0xd1 */
+ PREFIX186(_rotshft_bcl), /* 0xd2 */
+ PREFIX186(_rotshft_wcl), /* 0xd3 */
+ PREFIX86(_aam), /* 0xd4 */
+ PREFIX86(_aad), /* 0xd5 */
+ PREFIX286(_invalid),
+ PREFIX86(_xlat), /* 0xd7 */
+ PREFIX286(_escape), /* 0xd8 */
+ PREFIX286(_escape), /* 0xd9 */
+ PREFIX286(_escape), /* 0xda */
+ PREFIX286(_escape), /* 0xdb */
+ PREFIX286(_escape), /* 0xdc */
+ PREFIX286(_escape), /* 0xdd */
+ PREFIX286(_escape), /* 0xde */
+ PREFIX286(_escape_7), /* 0xdf */
+ PREFIX86(_loopne), /* 0xe0 */
+ PREFIX86(_loope), /* 0xe1 */
+ PREFIX86(_loop), /* 0xe2 */
+ PREFIX86(_jcxz), /* 0xe3 */
+ PREFIX86(_inal), /* 0xe4 */
+ PREFIX86(_inax), /* 0xe5 */
+ PREFIX86(_outal), /* 0xe6 */
+ PREFIX86(_outax), /* 0xe7 */
+ PREFIX86(_call_d16), /* 0xe8 */
+ PREFIX86(_jmp_d16), /* 0xe9 */
+ PREFIX86(_jmp_far), /* 0xea */
+ PREFIX86(_jmp_d8), /* 0xeb */
+ PREFIX86(_inaldx), /* 0xec */
+ PREFIX86(_inaxdx), /* 0xed */
+ PREFIX86(_outdxal), /* 0xee */
+ PREFIX86(_outdxax), /* 0xef */
+ PREFIX86(_lock), /* 0xf0 */
+ PREFIX286(_invalid), /* 0xf1 */
+ PREFIX186(_repne), /* 0xf2 */
+ PREFIX186(_repe), /* 0xf3 */
+ PREFIX86(_hlt), /* 0xf4 */
+ PREFIX86(_cmc), /* 0xf5 */
+ PREFIX86(_f6pre), /* 0xf6 */
+ PREFIX86(_f7pre), /* 0xf7 */
+ PREFIX86(_clc), /* 0xf8 */
+ PREFIX86(_stc), /* 0xf9 */
+ PREFIX86(_cli), /* 0xfa */
+ PREFIX86(_sti), /* 0xfb */
+ PREFIX86(_cld), /* 0xfc */
+ PREFIX86(_std), /* 0xfd */
+ PREFIX86(_fepre), /* 0xfe */
+ PREFIX86(_ffpre) /* 0xff */
+};
+
+#if defined(BIGCASE) && !defined(RS6000)
+ /* Some compilers cannot handle large case statements */
+#define TABLE286 \
+ switch(FETCHOP)\
+ {\
+ case 0x00: PREFIX86(_add_br8)(cpustate); break;\
+ case 0x01: PREFIX86(_add_wr16)(cpustate); break;\
+ case 0x02: PREFIX86(_add_r8b)(cpustate); break;\
+ case 0x03: PREFIX86(_add_r16w)(cpustate); break;\
+ case 0x04: PREFIX86(_add_ald8)(cpustate); break;\
+ case 0x05: PREFIX86(_add_axd16)(cpustate); break;\
+ case 0x06: PREFIX86(_push_es)(cpustate); break;\
+ case 0x07: PREFIX86(_pop_es)(cpustate); break;\
+ case 0x08: PREFIX86(_or_br8)(cpustate); break;\
+ case 0x09: PREFIX86(_or_wr16)(cpustate); break;\
+ case 0x0a: PREFIX86(_or_r8b)(cpustate); break;\
+ case 0x0b: PREFIX86(_or_r16w)(cpustate); break;\
+ case 0x0c: PREFIX86(_or_ald8)(cpustate); break;\
+ case 0x0d: PREFIX86(_or_axd16)(cpustate); break;\
+ case 0x0e: PREFIX86(_push_cs)(cpustate); break;\
+ case 0x0f: PREFIX286(_0fpre)(cpustate); break;\
+ case 0x10: PREFIX86(_adc_br8)(cpustate); break;\
+ case 0x11: PREFIX86(_adc_wr16)(cpustate); break;\
+ case 0x12: PREFIX86(_adc_r8b)(cpustate); break;\
+ case 0x13: PREFIX86(_adc_r16w)(cpustate); break;\
+ case 0x14: PREFIX86(_adc_ald8)(cpustate); break;\
+ case 0x15: PREFIX86(_adc_axd16)(cpustate); break;\
+ case 0x16: PREFIX86(_push_ss)(cpustate); break;\
+ case 0x17: PREFIX86(_pop_ss)(cpustate); break;\
+ case 0x18: PREFIX86(_sbb_br8)(cpustate); break;\
+ case 0x19: PREFIX86(_sbb_wr16)(cpustate); break;\
+ case 0x1a: PREFIX86(_sbb_r8b)(cpustate); break;\
+ case 0x1b: PREFIX86(_sbb_r16w)(cpustate); break;\
+ case 0x1c: PREFIX86(_sbb_ald8)(cpustate); break;\
+ case 0x1d: PREFIX86(_sbb_axd16)(cpustate); break;\
+ case 0x1e: PREFIX86(_push_ds)(cpustate); break;\
+ case 0x1f: PREFIX86(_pop_ds)(cpustate); break;\
+ case 0x20: PREFIX86(_and_br8)(cpustate); break;\
+ case 0x21: PREFIX86(_and_wr16)(cpustate); break;\
+ case 0x22: PREFIX86(_and_r8b)(cpustate); break;\
+ case 0x23: PREFIX86(_and_r16w)(cpustate); break;\
+ case 0x24: PREFIX86(_and_ald8)(cpustate); break;\
+ case 0x25: PREFIX86(_and_axd16)(cpustate); break;\
+ case 0x26: PREFIX86(_es)(cpustate); break;\
+ case 0x27: PREFIX86(_daa)(cpustate); break;\
+ case 0x28: PREFIX86(_sub_br8)(cpustate); break;\
+ case 0x29: PREFIX86(_sub_wr16)(cpustate); break;\
+ case 0x2a: PREFIX86(_sub_r8b)(cpustate); break;\
+ case 0x2b: PREFIX86(_sub_r16w)(cpustate); break;\
+ case 0x2c: PREFIX86(_sub_ald8)(cpustate); break;\
+ case 0x2d: PREFIX86(_sub_axd16)(cpustate); break;\
+ case 0x2e: PREFIX86(_cs)(cpustate); break;\
+ case 0x2f: PREFIX86(_das)(cpustate); break;\
+ case 0x30: PREFIX86(_xor_br8)(cpustate); break;\
+ case 0x31: PREFIX86(_xor_wr16)(cpustate); break;\
+ case 0x32: PREFIX86(_xor_r8b)(cpustate); break;\
+ case 0x33: PREFIX86(_xor_r16w)(cpustate); break;\
+ case 0x34: PREFIX86(_xor_ald8)(cpustate); break;\
+ case 0x35: PREFIX86(_xor_axd16)(cpustate); break;\
+ case 0x36: PREFIX86(_ss)(cpustate); break;\
+ case 0x37: PREFIX86(_aaa)(cpustate); break;\
+ case 0x38: PREFIX86(_cmp_br8)(cpustate); break;\
+ case 0x39: PREFIX86(_cmp_wr16)(cpustate); break;\
+ case 0x3a: PREFIX86(_cmp_r8b)(cpustate); break;\
+ case 0x3b: PREFIX86(_cmp_r16w)(cpustate); break;\
+ case 0x3c: PREFIX86(_cmp_ald8)(cpustate); break;\
+ case 0x3d: PREFIX86(_cmp_axd16)(cpustate); break;\
+ case 0x3e: PREFIX86(_ds)(cpustate); break;\
+ case 0x3f: PREFIX86(_aas)(cpustate); break;\
+ case 0x40: PREFIX86(_inc_ax)(cpustate); break;\
+ case 0x41: PREFIX86(_inc_cx)(cpustate); break;\
+ case 0x42: PREFIX86(_inc_dx)(cpustate); break;\
+ case 0x43: PREFIX86(_inc_bx)(cpustate); break;\
+ case 0x44: PREFIX86(_inc_sp)(cpustate); break;\
+ case 0x45: PREFIX86(_inc_bp)(cpustate); break;\
+ case 0x46: PREFIX86(_inc_si)(cpustate); break;\
+ case 0x47: PREFIX86(_inc_di)(cpustate); break;\
+ case 0x48: PREFIX86(_dec_ax)(cpustate); break;\
+ case 0x49: PREFIX86(_dec_cx)(cpustate); break;\
+ case 0x4a: PREFIX86(_dec_dx)(cpustate); break;\
+ case 0x4b: PREFIX86(_dec_bx)(cpustate); break;\
+ case 0x4c: PREFIX86(_dec_sp)(cpustate); break;\
+ case 0x4d: PREFIX86(_dec_bp)(cpustate); break;\
+ case 0x4e: PREFIX86(_dec_si)(cpustate); break;\
+ case 0x4f: PREFIX86(_dec_di)(cpustate); break;\
+ case 0x50: PREFIX86(_push_ax)(cpustate); break;\
+ case 0x51: PREFIX86(_push_cx)(cpustate); break;\
+ case 0x52: PREFIX86(_push_dx)(cpustate); break;\
+ case 0x53: PREFIX86(_push_bx)(cpustate); break;\
+ case 0x54: PREFIX86(_push_sp)(cpustate); break;\
+ case 0x55: PREFIX86(_push_bp)(cpustate); break;\
+ case 0x56: PREFIX86(_push_si)(cpustate); break;\
+ case 0x57: PREFIX86(_push_di)(cpustate); break;\
+ case 0x58: PREFIX86(_pop_ax)(cpustate); break;\
+ case 0x59: PREFIX86(_pop_cx)(cpustate); break;\
+ case 0x5a: PREFIX86(_pop_dx)(cpustate); break;\
+ case 0x5b: PREFIX86(_pop_bx)(cpustate); break;\
+ case 0x5c: PREFIX86(_pop_sp)(cpustate); break;\
+ case 0x5d: PREFIX86(_pop_bp)(cpustate); break;\
+ case 0x5e: PREFIX86(_pop_si)(cpustate); break;\
+ case 0x5f: PREFIX86(_pop_di)(cpustate); break;\
+ case 0x60: PREFIX186(_pusha)(cpustate); break;\
+ case 0x61: PREFIX186(_popa)(cpustate); break;\
+ case 0x62: PREFIX186(_bound)(cpustate); break;\
+ case 0x63: PREFIX286(_arpl)(cpustate); break;\
+ case 0x64: PREFIX286(_invalid)(cpustate); break;\
+ case 0x65: PREFIX286(_invalid)(cpustate); break;\
+ case 0x66: PREFIX286(_invalid)(cpustate); break;\
+ case 0x67: PREFIX286(_invalid)(cpustate); break;\
+ case 0x68: PREFIX186(_push_d16)(cpustate); break;\
+ case 0x69: PREFIX186(_imul_d16)(cpustate); break;\
+ case 0x6a: PREFIX186(_push_d8)(cpustate); break;\
+ case 0x6b: PREFIX186(_imul_d8)(cpustate); break;\
+ case 0x6c: PREFIX186(_insb)(cpustate); break;\
+ case 0x6d: PREFIX186(_insw)(cpustate); break;\
+ case 0x6e: PREFIX186(_outsb)(cpustate); break;\
+ case 0x6f: PREFIX186(_outsw)(cpustate); break;\
+ case 0x70: PREFIX86(_jo)(cpustate); break;\
+ case 0x71: PREFIX86(_jno)(cpustate); break;\
+ case 0x72: PREFIX86(_jb)(cpustate); break;\
+ case 0x73: PREFIX86(_jnb)(cpustate); break;\
+ case 0x74: PREFIX86(_jz)(cpustate); break;\
+ case 0x75: PREFIX86(_jnz)(cpustate); break;\
+ case 0x76: PREFIX86(_jbe)(cpustate); break;\
+ case 0x77: PREFIX86(_jnbe)(cpustate); break;\
+ case 0x78: PREFIX86(_js)(cpustate); break;\
+ case 0x79: PREFIX86(_jns)(cpustate); break;\
+ case 0x7a: PREFIX86(_jp)(cpustate); break;\
+ case 0x7b: PREFIX86(_jnp)(cpustate); break;\
+ case 0x7c: PREFIX86(_jl)(cpustate); break;\
+ case 0x7d: PREFIX86(_jnl)(cpustate); break;\
+ case 0x7e: PREFIX86(_jle)(cpustate); break;\
+ case 0x7f: PREFIX86(_jnle)(cpustate); break;\
+ case 0x80: PREFIX86(_80pre)(cpustate); break;\
+ case 0x81: PREFIX86(_81pre)(cpustate); break;\
+ case 0x82: PREFIX86(_82pre)(cpustate); break;\
+ case 0x83: PREFIX86(_83pre)(cpustate); break;\
+ case 0x84: PREFIX86(_test_br8)(cpustate); break;\
+ case 0x85: PREFIX86(_test_wr16)(cpustate); break;\
+ case 0x86: PREFIX86(_xchg_br8)(cpustate); break;\
+ case 0x87: PREFIX86(_xchg_wr16)(cpustate); break;\
+ case 0x88: PREFIX86(_mov_br8)(cpustate); break;\
+ case 0x89: PREFIX86(_mov_wr16)(cpustate); break;\
+ case 0x8a: PREFIX86(_mov_r8b)(cpustate); break;\
+ case 0x8b: PREFIX86(_mov_r16w)(cpustate); break;\
+ case 0x8c: PREFIX86(_mov_wsreg)(cpustate); break;\
+ case 0x8d: PREFIX86(_lea)(cpustate); break;\
+ case 0x8e: PREFIX86(_mov_sregw)(cpustate); break;\
+ case 0x8f: PREFIX86(_popw)(cpustate); break;\
+ case 0x90: PREFIX86(_nop)(cpustate); break;\
+ case 0x91: PREFIX86(_xchg_axcx)(cpustate); break;\
+ case 0x92: PREFIX86(_xchg_axdx)(cpustate); break;\
+ case 0x93: PREFIX86(_xchg_axbx)(cpustate); break;\
+ case 0x94: PREFIX86(_xchg_axsp)(cpustate); break;\
+ case 0x95: PREFIX86(_xchg_axbp)(cpustate); break;\
+ case 0x96: PREFIX86(_xchg_axsi)(cpustate); break;\
+ case 0x97: PREFIX86(_xchg_axdi)(cpustate); break;\
+ case 0x98: PREFIX86(_cbw)(cpustate); break;\
+ case 0x99: PREFIX86(_cwd)(cpustate); break;\
+ case 0x9a: PREFIX86(_call_far)(cpustate); break;\
+ case 0x9b: PREFIX86(_wait)(cpustate); break;\
+ case 0x9c: PREFIX86(_pushf)(cpustate); break;\
+ case 0x9d: PREFIX286(_popf)(cpustate); break;\
+ case 0x9e: PREFIX86(_sahf)(cpustate); break;\
+ case 0x9f: PREFIX86(_lahf)(cpustate); break;\
+ case 0xa0: PREFIX86(_mov_aldisp)(cpustate); break;\
+ case 0xa1: PREFIX86(_mov_axdisp)(cpustate); break;\
+ case 0xa2: PREFIX86(_mov_dispal)(cpustate); break;\
+ case 0xa3: PREFIX86(_mov_dispax)(cpustate); break;\
+ case 0xa4: PREFIX86(_movsb)(cpustate); break;\
+ case 0xa5: PREFIX86(_movsw)(cpustate); break;\
+ case 0xa6: PREFIX86(_cmpsb)(cpustate); break;\
+ case 0xa7: PREFIX86(_cmpsw)(cpustate); break;\
+ case 0xa8: PREFIX86(_test_ald8)(cpustate); break;\
+ case 0xa9: PREFIX86(_test_axd16)(cpustate); break;\
+ case 0xaa: PREFIX86(_stosb)(cpustate); break;\
+ case 0xab: PREFIX86(_stosw)(cpustate); break;\
+ case 0xac: PREFIX86(_lodsb)(cpustate); break;\
+ case 0xad: PREFIX86(_lodsw)(cpustate); break;\
+ case 0xae: PREFIX86(_scasb)(cpustate); break;\
+ case 0xaf: PREFIX86(_scasw)(cpustate); break;\
+ case 0xb0: PREFIX86(_mov_ald8)(cpustate); break;\
+ case 0xb1: PREFIX86(_mov_cld8)(cpustate); break;\
+ case 0xb2: PREFIX86(_mov_dld8)(cpustate); break;\
+ case 0xb3: PREFIX86(_mov_bld8)(cpustate); break;\
+ case 0xb4: PREFIX86(_mov_ahd8)(cpustate); break;\
+ case 0xb5: PREFIX86(_mov_chd8)(cpustate); break;\
+ case 0xb6: PREFIX86(_mov_dhd8)(cpustate); break;\
+ case 0xb7: PREFIX86(_mov_bhd8)(cpustate); break;\
+ case 0xb8: PREFIX86(_mov_axd16)(cpustate); break;\
+ case 0xb9: PREFIX86(_mov_cxd16)(cpustate); break;\
+ case 0xba: PREFIX86(_mov_dxd16)(cpustate); break;\
+ case 0xbb: PREFIX86(_mov_bxd16)(cpustate); break;\
+ case 0xbc: PREFIX86(_mov_spd16)(cpustate); break;\
+ case 0xbd: PREFIX86(_mov_bpd16)(cpustate); break;\
+ case 0xbe: PREFIX86(_mov_sid16)(cpustate); break;\
+ case 0xbf: PREFIX86(_mov_did16)(cpustate); break;\
+ case 0xc0: PREFIX186(_rotshft_bd8)(cpustate); break;\
+ case 0xc1: PREFIX186(_rotshft_wd8)(cpustate); break;\
+ case 0xc2: PREFIX86(_ret_d16)(cpustate); break;\
+ case 0xc3: PREFIX86(_ret)(cpustate); break;\
+ case 0xc4: PREFIX86(_les_dw)(cpustate); break;\
+ case 0xc5: PREFIX86(_lds_dw)(cpustate); break;\
+ case 0xc6: PREFIX86(_mov_bd8)(cpustate); break;\
+ case 0xc7: PREFIX86(_mov_wd16)(cpustate); break;\
+ case 0xc8: PREFIX186(_enter)(cpustate); break;\
+ case 0xc9: PREFIX186(_leave)(cpustate); break;\
+ case 0xca: PREFIX286(_retf_d16)(cpustate); break;\
+ case 0xcb: PREFIX286(_retf)(cpustate); break;\
+ case 0xcc: PREFIX86(_int3)(cpustate); break;\
+ case 0xcd: PREFIX86(_int)(cpustate); break;\
+ case 0xce: PREFIX86(_into)(cpustate); break;\
+ case 0xcf: PREFIX286(_iret)(cpustate); break;\
+ case 0xd0: PREFIX86(_rotshft_b)(cpustate); break;\
+ case 0xd1: PREFIX86(_rotshft_w)(cpustate); break;\
+ case 0xd2: PREFIX186(_rotshft_bcl)(cpustate); break;\
+ case 0xd3: PREFIX186(_rotshft_wcl)(cpustate); break;\
+ case 0xd4: PREFIX86(_aam)(cpustate); break;\
+ case 0xd5: PREFIX86(_aad)(cpustate); break;\
+ case 0xd6: PREFIX286(_invalid)(cpustate); break;\
+ case 0xd7: PREFIX86(_xlat)(cpustate); break;\
+ case 0xd8: PREFIX286(_escape)(cpustate); break;\
+ case 0xd9: PREFIX286(_escape)(cpustate); break;\
+ case 0xda: PREFIX286(_escape)(cpustate); break;\
+ case 0xdb: PREFIX286(_escape)(cpustate); break;\
+ case 0xdc: PREFIX286(_escape)(cpustate); break;\
+ case 0xdd: PREFIX286(_escape)(cpustate); break;\
+ case 0xde: PREFIX286(_escape)(cpustate); break;\
+ case 0xdf: PREFIX286(_escape_7)(cpustate); break;\
+ case 0xe0: PREFIX86(_loopne)(cpustate); break;\
+ case 0xe1: PREFIX86(_loope)(cpustate); break;\
+ case 0xe2: PREFIX86(_loop)(cpustate); break;\
+ case 0xe3: PREFIX86(_jcxz)(cpustate); break;\
+ case 0xe4: PREFIX86(_inal)(cpustate); break;\
+ case 0xe5: PREFIX86(_inax)(cpustate); break;\
+ case 0xe6: PREFIX86(_outal)(cpustate); break;\
+ case 0xe7: PREFIX86(_outax)(cpustate); break;\
+ case 0xe8: PREFIX86(_call_d16)(cpustate); break;\
+ case 0xe9: PREFIX86(_jmp_d16)(cpustate); break;\
+ case 0xea: PREFIX86(_jmp_far)(cpustate); break;\
+ case 0xeb: PREFIX86(_jmp_d8)(cpustate); break;\
+ case 0xec: PREFIX86(_inaldx)(cpustate); break;\
+ case 0xed: PREFIX86(_inaxdx)(cpustate); break;\
+ case 0xee: PREFIX86(_outdxal)(cpustate); break;\
+ case 0xef: PREFIX86(_outdxax)(cpustate); break;\
+ case 0xf0: PREFIX86(_lock)(cpustate); break;\
+ case 0xf1: PREFIX286(_invalid)(cpustate); break;\
+ case 0xf2: PREFIX186(_repne)(cpustate); break;\
+ case 0xf3: PREFIX186(_repe)(cpustate); break;\
+ case 0xf4: PREFIX86(_hlt)(cpustate); break;\
+ case 0xf5: PREFIX86(_cmc)(cpustate); break;\
+ case 0xf6: PREFIX86(_f6pre)(cpustate); break;\
+ case 0xf7: PREFIX86(_f7pre)(cpustate); break;\
+ case 0xf8: PREFIX86(_clc)(cpustate); break;\
+ case 0xf9: PREFIX86(_stc)(cpustate); break;\
+ case 0xfa: PREFIX86(_cli)(cpustate); break;\
+ case 0xfb: PREFIX86(_sti)(cpustate); break;\
+ case 0xfc: PREFIX86(_cld)(cpustate); break;\
+ case 0xfd: PREFIX86(_std)(cpustate); break;\
+ case 0xfe: PREFIX86(_fepre)(cpustate); break;\
+ case 0xff: PREFIX86(_ffpre)(cpustate); break;\
+ };
+#else
+#define TABLE286 PREFIX286(_instruction)[FETCHOP](cpustate);
+#endif
diff --git a/trunk/src/emu/cpu/i86/table86.h b/trunk/src/emu/cpu/i86/table86.h
new file mode 100644
index 00000000000..b5b9be110a2
--- /dev/null
+++ b/trunk/src/emu/cpu/i86/table86.h
@@ -0,0 +1,525 @@
+static void (*const PREFIX86(_instruction)[256])(i8086_state *cpustate) =
+{
+ PREFIX86(_add_br8), /* 0x00 */
+ PREFIX86(_add_wr16), /* 0x01 */
+ PREFIX86(_add_r8b), /* 0x02 */
+ PREFIX86(_add_r16w), /* 0x03 */
+ PREFIX86(_add_ald8), /* 0x04 */
+ PREFIX86(_add_axd16), /* 0x05 */
+ PREFIX86(_push_es), /* 0x06 */
+ PREFIX86(_pop_es), /* 0x07 */
+ PREFIX86(_or_br8), /* 0x08 */
+ PREFIX86(_or_wr16), /* 0x09 */
+ PREFIX86(_or_r8b), /* 0x0a */
+ PREFIX86(_or_r16w), /* 0x0b */
+ PREFIX86(_or_ald8), /* 0x0c */
+ PREFIX86(_or_axd16), /* 0x0d */
+ PREFIX86(_push_cs), /* 0x0e */
+ PREFIX86(_pop_cs), /* 0x0f */
+ PREFIX86(_adc_br8), /* 0x10 */
+ PREFIX86(_adc_wr16), /* 0x11 */
+ PREFIX86(_adc_r8b), /* 0x12 */
+ PREFIX86(_adc_r16w), /* 0x13 */
+ PREFIX86(_adc_ald8), /* 0x14 */
+ PREFIX86(_adc_axd16), /* 0x15 */
+ PREFIX86(_push_ss), /* 0x16 */
+ PREFIX86(_pop_ss), /* 0x17 */
+ PREFIX86(_sbb_br8), /* 0x18 */
+ PREFIX86(_sbb_wr16), /* 0x19 */
+ PREFIX86(_sbb_r8b), /* 0x1a */
+ PREFIX86(_sbb_r16w), /* 0x1b */
+ PREFIX86(_sbb_ald8), /* 0x1c */
+ PREFIX86(_sbb_axd16), /* 0x1d */
+ PREFIX86(_push_ds), /* 0x1e */
+ PREFIX86(_pop_ds), /* 0x1f */
+ PREFIX86(_and_br8), /* 0x20 */
+ PREFIX86(_and_wr16), /* 0x21 */
+ PREFIX86(_and_r8b), /* 0x22 */
+ PREFIX86(_and_r16w), /* 0x23 */
+ PREFIX86(_and_ald8), /* 0x24 */
+ PREFIX86(_and_axd16), /* 0x25 */
+ PREFIX86(_es), /* 0x26 */
+ PREFIX86(_daa), /* 0x27 */
+ PREFIX86(_sub_br8), /* 0x28 */
+ PREFIX86(_sub_wr16), /* 0x29 */
+ PREFIX86(_sub_r8b), /* 0x2a */
+ PREFIX86(_sub_r16w), /* 0x2b */
+ PREFIX86(_sub_ald8), /* 0x2c */
+ PREFIX86(_sub_axd16), /* 0x2d */
+ PREFIX86(_cs), /* 0x2e */
+ PREFIX86(_das), /* 0x2f */
+ PREFIX86(_xor_br8), /* 0x30 */
+ PREFIX86(_xor_wr16), /* 0x31 */
+ PREFIX86(_xor_r8b), /* 0x32 */
+ PREFIX86(_xor_r16w), /* 0x33 */
+ PREFIX86(_xor_ald8), /* 0x34 */
+ PREFIX86(_xor_axd16), /* 0x35 */
+ PREFIX86(_ss), /* 0x36 */
+ PREFIX86(_aaa), /* 0x37 */
+ PREFIX86(_cmp_br8), /* 0x38 */
+ PREFIX86(_cmp_wr16), /* 0x39 */
+ PREFIX86(_cmp_r8b), /* 0x3a */
+ PREFIX86(_cmp_r16w), /* 0x3b */
+ PREFIX86(_cmp_ald8), /* 0x3c */
+ PREFIX86(_cmp_axd16), /* 0x3d */
+ PREFIX86(_ds), /* 0x3e */
+ PREFIX86(_aas), /* 0x3f */
+ PREFIX86(_inc_ax), /* 0x40 */
+ PREFIX86(_inc_cx), /* 0x41 */
+ PREFIX86(_inc_dx), /* 0x42 */
+ PREFIX86(_inc_bx), /* 0x43 */
+ PREFIX86(_inc_sp), /* 0x44 */
+ PREFIX86(_inc_bp), /* 0x45 */
+ PREFIX86(_inc_si), /* 0x46 */
+ PREFIX86(_inc_di), /* 0x47 */
+ PREFIX86(_dec_ax), /* 0x48 */
+ PREFIX86(_dec_cx), /* 0x49 */
+ PREFIX86(_dec_dx), /* 0x4a */
+ PREFIX86(_dec_bx), /* 0x4b */
+ PREFIX86(_dec_sp), /* 0x4c */
+ PREFIX86(_dec_bp), /* 0x4d */
+ PREFIX86(_dec_si), /* 0x4e */
+ PREFIX86(_dec_di), /* 0x4f */
+ PREFIX86(_push_ax), /* 0x50 */
+ PREFIX86(_push_cx), /* 0x51 */
+ PREFIX86(_push_dx), /* 0x52 */
+ PREFIX86(_push_bx), /* 0x53 */
+ PREFIX86(_push_sp), /* 0x54 */
+ PREFIX86(_push_bp), /* 0x55 */
+ PREFIX86(_push_si), /* 0x56 */
+ PREFIX86(_push_di), /* 0x57 */
+ PREFIX86(_pop_ax), /* 0x58 */
+ PREFIX86(_pop_cx), /* 0x59 */
+ PREFIX86(_pop_dx), /* 0x5a */
+ PREFIX86(_pop_bx), /* 0x5b */
+ PREFIX86(_pop_sp), /* 0x5c */
+ PREFIX86(_pop_bp), /* 0x5d */
+ PREFIX86(_pop_si), /* 0x5e */
+ PREFIX86(_pop_di), /* 0x5f */
+ PREFIX86(_invalid_2b), // PREFIX86(_pusha), /* 0x60 */
+ PREFIX86(_invalid_2b), // PREFIX86(_popa), /* 0x61 */
+ PREFIX86(_invalid_2b), // PREFIX86(_bound), /* 0x62 */
+ PREFIX86(_invalid_2b),
+ PREFIX86(_invalid_2b),
+ PREFIX86(_invalid_2b),
+ PREFIX86(_invalid_2b),
+ PREFIX86(_invalid_2b),
+ PREFIX86(_invalid_2b), //i_push_d16), /* 0x68 */
+ PREFIX86(_invalid_2b), //i_imul_d16), /* 0x69 */
+ PREFIX86(_invalid_2b), //i_push_d8), /* 0x6a */
+ PREFIX86(_invalid_2b), //i_imul_d8), /* 0x6b */
+ PREFIX86(_invalid_2b), //i_insb), /* 0x6c */
+ PREFIX86(_invalid_2b), //i_insw), /* 0x6d */
+ PREFIX86(_invalid_2b), //i_outsb), /* 0x6e */
+ PREFIX86(_invalid_2b), //i_outsw), /* 0x6f */
+ PREFIX86(_jo), /* 0x70 */
+ PREFIX86(_jno), /* 0x71 */
+ PREFIX86(_jb), /* 0x72 */
+ PREFIX86(_jnb), /* 0x73 */
+ PREFIX86(_jz), /* 0x74 */
+ PREFIX86(_jnz), /* 0x75 */
+ PREFIX86(_jbe), /* 0x76 */
+ PREFIX86(_jnbe), /* 0x77 */
+ PREFIX86(_js), /* 0x78 */
+ PREFIX86(_jns), /* 0x79 */
+ PREFIX86(_jp), /* 0x7a */
+ PREFIX86(_jnp), /* 0x7b */
+ PREFIX86(_jl), /* 0x7c */
+ PREFIX86(_jnl), /* 0x7d */
+ PREFIX86(_jle), /* 0x7e */
+ PREFIX86(_jnle), /* 0x7f */
+ PREFIX86(_80pre), /* 0x80 */
+ PREFIX86(_81pre), /* 0x81 */
+ PREFIX86(_82pre), /* 0x82 */
+ PREFIX86(_83pre), /* 0x83 */
+ PREFIX86(_test_br8), /* 0x84 */
+ PREFIX86(_test_wr16), /* 0x85 */
+ PREFIX86(_xchg_br8), /* 0x86 */
+ PREFIX86(_xchg_wr16), /* 0x87 */
+ PREFIX86(_mov_br8), /* 0x88 */
+ PREFIX86(_mov_wr16), /* 0x89 */
+ PREFIX86(_mov_r8b), /* 0x8a */
+ PREFIX86(_mov_r16w), /* 0x8b */
+ PREFIX86(_mov_wsreg), /* 0x8c */
+ PREFIX86(_lea), /* 0x8d */
+ PREFIX86(_mov_sregw), /* 0x8e */
+ PREFIX86(_popw), /* 0x8f */
+ PREFIX86(_nop), /* 0x90 */
+ PREFIX86(_xchg_axcx), /* 0x91 */
+ PREFIX86(_xchg_axdx), /* 0x92 */
+ PREFIX86(_xchg_axbx), /* 0x93 */
+ PREFIX86(_xchg_axsp), /* 0x94 */
+ PREFIX86(_xchg_axbp), /* 0x95 */
+ PREFIX86(_xchg_axsi), /* 0x97 */
+ PREFIX86(_xchg_axdi), /* 0x97 */
+ PREFIX86(_cbw), /* 0x98 */
+ PREFIX86(_cwd), /* 0x99 */
+ PREFIX86(_call_far), /* 0x9a */
+ PREFIX86(_wait), /* 0x9b */
+ PREFIX86(_pushf), /* 0x9c */
+ PREFIX86(_popf), /* 0x9d */
+ PREFIX86(_sahf), /* 0x9e */
+ PREFIX86(_lahf), /* 0x9f */
+ PREFIX86(_mov_aldisp), /* 0xa0 */
+ PREFIX86(_mov_axdisp), /* 0xa1 */
+ PREFIX86(_mov_dispal), /* 0xa2 */
+ PREFIX86(_mov_dispax), /* 0xa3 */
+ PREFIX86(_movsb), /* 0xa4 */
+ PREFIX86(_movsw), /* 0xa5 */
+ PREFIX86(_cmpsb), /* 0xa6 */
+ PREFIX86(_cmpsw), /* 0xa7 */
+ PREFIX86(_test_ald8), /* 0xa8 */
+ PREFIX86(_test_axd16), /* 0xa9 */
+ PREFIX86(_stosb), /* 0xaa */
+ PREFIX86(_stosw), /* 0xab */
+ PREFIX86(_lodsb), /* 0xac */
+ PREFIX86(_lodsw), /* 0xad */
+ PREFIX86(_scasb), /* 0xae */
+ PREFIX86(_scasw), /* 0xaf */
+ PREFIX86(_mov_ald8), /* 0xb0 */
+ PREFIX86(_mov_cld8), /* 0xb1 */
+ PREFIX86(_mov_dld8), /* 0xb2 */
+ PREFIX86(_mov_bld8), /* 0xb3 */
+ PREFIX86(_mov_ahd8), /* 0xb4 */
+ PREFIX86(_mov_chd8), /* 0xb5 */
+ PREFIX86(_mov_dhd8), /* 0xb6 */
+ PREFIX86(_mov_bhd8), /* 0xb7 */
+ PREFIX86(_mov_axd16), /* 0xb8 */
+ PREFIX86(_mov_cxd16), /* 0xb9 */
+ PREFIX86(_mov_dxd16), /* 0xba */
+ PREFIX86(_mov_bxd16), /* 0xbb */
+ PREFIX86(_mov_spd16), /* 0xbc */
+ PREFIX86(_mov_bpd16), /* 0xbd */
+ PREFIX86(_mov_sid16), /* 0xbe */
+ PREFIX86(_mov_did16), /* 0xbf */
+ PREFIX86(_invalid), // PREFIX86(_rotshft_bd8), /* 0xc0 */
+ PREFIX86(_invalid), // PREFIX86(_rotshft_wd8), /* 0xc1 */
+ PREFIX86(_ret_d16), /* 0xc2 */
+ PREFIX86(_ret), /* 0xc3 */
+ PREFIX86(_les_dw), /* 0xc4 */
+ PREFIX86(_lds_dw), /* 0xc5 */
+ PREFIX86(_mov_bd8), /* 0xc6 */
+ PREFIX86(_mov_wd16), /* 0xc7 */
+ PREFIX86(_invalid), //i_enter), /* 0xc8 */
+ PREFIX86(_invalid), //leave), /* 0xc9 */
+ PREFIX86(_retf_d16), /* 0xca */
+ PREFIX86(_retf), /* 0xcb */
+ PREFIX86(_int3), /* 0xcc */
+ PREFIX86(_int), /* 0xcd */
+ PREFIX86(_into), /* 0xce */
+ PREFIX86(_iret), /* 0xcf */
+ PREFIX86(_rotshft_b), /* 0xd0 */
+ PREFIX86(_rotshft_w), /* 0xd1 */
+ PREFIX86(_rotshft_bcl), /* 0xd2 */
+ PREFIX86(_rotshft_wcl), /* 0xd3 */
+ PREFIX86(_aam), /* 0xd4 */
+ PREFIX86(_aad), /* 0xd5 */
+ PREFIX86(_invalid),
+ PREFIX86(_xlat), /* 0xd7 */
+ PREFIX86(_escape), /* 0xd8 */
+ PREFIX86(_escape), /* 0xd9 */
+ PREFIX86(_escape), /* 0xda */
+ PREFIX86(_escape), /* 0xdb */
+ PREFIX86(_escape), /* 0xdc */
+ PREFIX86(_escape), /* 0xdd */
+ PREFIX86(_escape), /* 0xde */
+ PREFIX86(_escape), /* 0xdf */
+ PREFIX86(_loopne), /* 0xe0 */
+ PREFIX86(_loope), /* 0xe1 */
+ PREFIX86(_loop), /* 0xe2 */
+ PREFIX86(_jcxz), /* 0xe3 */
+ PREFIX86(_inal), /* 0xe4 */
+ PREFIX86(_inax), /* 0xe5 */
+ PREFIX86(_outal), /* 0xe6 */
+ PREFIX86(_outax), /* 0xe7 */
+ PREFIX86(_call_d16), /* 0xe8 */
+ PREFIX86(_jmp_d16), /* 0xe9 */
+ PREFIX86(_jmp_far), /* 0xea */
+ PREFIX86(_jmp_d8), /* 0xeb */
+ PREFIX86(_inaldx), /* 0xec */
+ PREFIX86(_inaxdx), /* 0xed */
+ PREFIX86(_outdxal), /* 0xee */
+ PREFIX86(_outdxax), /* 0xef */
+ PREFIX86(_lock), /* 0xf0 */
+ PREFIX86(_invalid), /* 0xf1 */
+ PREFIX86(_repne), /* 0xf2 */
+ PREFIX86(_repe), /* 0xf3 */
+ PREFIX86(_hlt), /* 0xf4 */
+ PREFIX86(_cmc), /* 0xf5 */
+ PREFIX86(_f6pre), /* 0xf6 */
+ PREFIX86(_f7pre), /* 0xf7 */
+ PREFIX86(_clc), /* 0xf8 */
+ PREFIX86(_stc), /* 0xf9 */
+ PREFIX86(_cli), /* 0xfa */
+ PREFIX86(_sti), /* 0xfb */
+ PREFIX86(_cld), /* 0xfc */
+ PREFIX86(_std), /* 0xfd */
+ PREFIX86(_fepre), /* 0xfe */
+ PREFIX86(_ffpre) /* 0xff */
+};
+
+#if defined(BIGCASE) && !defined(RS6000)
+ /* Some compilers cannot handle large case statements */
+#define TABLE86 \
+ switch(FETCHOP)\
+ {\
+ case 0x00: PREFIX86(_add_br8)(cpustate); break;\
+ case 0x01: PREFIX86(_add_wr16)(cpustate); break;\
+ case 0x02: PREFIX86(_add_r8b)(cpustate); break;\
+ case 0x03: PREFIX86(_add_r16w)(cpustate); break;\
+ case 0x04: PREFIX86(_add_ald8)(cpustate); break;\
+ case 0x05: PREFIX86(_add_axd16)(cpustate); break;\
+ case 0x06: PREFIX86(_push_es)(cpustate); break;\
+ case 0x07: PREFIX86(_pop_es)(cpustate); break;\
+ case 0x08: PREFIX86(_or_br8)(cpustate); break;\
+ case 0x09: PREFIX86(_or_wr16)(cpustate); break;\
+ case 0x0a: PREFIX86(_or_r8b)(cpustate); break;\
+ case 0x0b: PREFIX86(_or_r16w)(cpustate); break;\
+ case 0x0c: PREFIX86(_or_ald8)(cpustate); break;\
+ case 0x0d: PREFIX86(_or_axd16)(cpustate); break;\
+ case 0x0e: PREFIX86(_push_cs)(cpustate); break;\
+ case 0x0f: PREFIX86(_invalid)(cpustate); break;\
+ case 0x10: PREFIX86(_adc_br8)(cpustate); break;\
+ case 0x11: PREFIX86(_adc_wr16)(cpustate); break;\
+ case 0x12: PREFIX86(_adc_r8b)(cpustate); break;\
+ case 0x13: PREFIX86(_adc_r16w)(cpustate); break;\
+ case 0x14: PREFIX86(_adc_ald8)(cpustate); break;\
+ case 0x15: PREFIX86(_adc_axd16)(cpustate); break;\
+ case 0x16: PREFIX86(_push_ss)(cpustate); break;\
+ case 0x17: PREFIX86(_pop_ss)(cpustate); break;\
+ case 0x18: PREFIX86(_sbb_br8)(cpustate); break;\
+ case 0x19: PREFIX86(_sbb_wr16)(cpustate); break;\
+ case 0x1a: PREFIX86(_sbb_r8b)(cpustate); break;\
+ case 0x1b: PREFIX86(_sbb_r16w)(cpustate); break;\
+ case 0x1c: PREFIX86(_sbb_ald8)(cpustate); break;\
+ case 0x1d: PREFIX86(_sbb_axd16)(cpustate); break;\
+ case 0x1e: PREFIX86(_push_ds)(cpustate); break;\
+ case 0x1f: PREFIX86(_pop_ds)(cpustate); break;\
+ case 0x20: PREFIX86(_and_br8)(cpustate); break;\
+ case 0x21: PREFIX86(_and_wr16)(cpustate); break;\
+ case 0x22: PREFIX86(_and_r8b)(cpustate); break;\
+ case 0x23: PREFIX86(_and_r16w)(cpustate); break;\
+ case 0x24: PREFIX86(_and_ald8)(cpustate); break;\
+ case 0x25: PREFIX86(_and_axd16)(cpustate); break;\
+ case 0x26: PREFIX86(_es)(cpustate); break;\
+ case 0x27: PREFIX86(_daa)(cpustate); break;\
+ case 0x28: PREFIX86(_sub_br8)(cpustate); break;\
+ case 0x29: PREFIX86(_sub_wr16)(cpustate); break;\
+ case 0x2a: PREFIX86(_sub_r8b)(cpustate); break;\
+ case 0x2b: PREFIX86(_sub_r16w)(cpustate); break;\
+ case 0x2c: PREFIX86(_sub_ald8)(cpustate); break;\
+ case 0x2d: PREFIX86(_sub_axd16)(cpustate); break;\
+ case 0x2e: PREFIX86(_cs)(cpustate); break;\
+ case 0x2f: PREFIX86(_das)(cpustate); break;\
+ case 0x30: PREFIX86(_xor_br8)(cpustate); break;\
+ case 0x31: PREFIX86(_xor_wr16)(cpustate); break;\
+ case 0x32: PREFIX86(_xor_r8b)(cpustate); break;\
+ case 0x33: PREFIX86(_xor_r16w)(cpustate); break;\
+ case 0x34: PREFIX86(_xor_ald8)(cpustate); break;\
+ case 0x35: PREFIX86(_xor_axd16)(cpustate); break;\
+ case 0x36: PREFIX86(_ss)(cpustate); break;\
+ case 0x37: PREFIX86(_aaa)(cpustate); break;\
+ case 0x38: PREFIX86(_cmp_br8)(cpustate); break;\
+ case 0x39: PREFIX86(_cmp_wr16)(cpustate); break;\
+ case 0x3a: PREFIX86(_cmp_r8b)(cpustate); break;\
+ case 0x3b: PREFIX86(_cmp_r16w)(cpustate); break;\
+ case 0x3c: PREFIX86(_cmp_ald8)(cpustate); break;\
+ case 0x3d: PREFIX86(_cmp_axd16)(cpustate); break;\
+ case 0x3e: PREFIX86(_ds)(cpustate); break;\
+ case 0x3f: PREFIX86(_aas)(cpustate); break;\
+ case 0x40: PREFIX86(_inc_ax)(cpustate); break;\
+ case 0x41: PREFIX86(_inc_cx)(cpustate); break;\
+ case 0x42: PREFIX86(_inc_dx)(cpustate); break;\
+ case 0x43: PREFIX86(_inc_bx)(cpustate); break;\
+ case 0x44: PREFIX86(_inc_sp)(cpustate); break;\
+ case 0x45: PREFIX86(_inc_bp)(cpustate); break;\
+ case 0x46: PREFIX86(_inc_si)(cpustate); break;\
+ case 0x47: PREFIX86(_inc_di)(cpustate); break;\
+ case 0x48: PREFIX86(_dec_ax)(cpustate); break;\
+ case 0x49: PREFIX86(_dec_cx)(cpustate); break;\
+ case 0x4a: PREFIX86(_dec_dx)(cpustate); break;\
+ case 0x4b: PREFIX86(_dec_bx)(cpustate); break;\
+ case 0x4c: PREFIX86(_dec_sp)(cpustate); break;\
+ case 0x4d: PREFIX86(_dec_bp)(cpustate); break;\
+ case 0x4e: PREFIX86(_dec_si)(cpustate); break;\
+ case 0x4f: PREFIX86(_dec_di)(cpustate); break;\
+ case 0x50: PREFIX86(_push_ax)(cpustate); break;\
+ case 0x51: PREFIX86(_push_cx)(cpustate); break;\
+ case 0x52: PREFIX86(_push_dx)(cpustate); break;\
+ case 0x53: PREFIX86(_push_bx)(cpustate); break;\
+ case 0x54: PREFIX86(_push_sp)(cpustate); break;\
+ case 0x55: PREFIX86(_push_bp)(cpustate); break;\
+ case 0x56: PREFIX86(_push_si)(cpustate); break;\
+ case 0x57: PREFIX86(_push_di)(cpustate); break;\
+ case 0x58: PREFIX86(_pop_ax)(cpustate); break;\
+ case 0x59: PREFIX86(_pop_cx)(cpustate); break;\
+ case 0x5a: PREFIX86(_pop_dx)(cpustate); break;\
+ case 0x5b: PREFIX86(_pop_bx)(cpustate); break;\
+ case 0x5c: PREFIX86(_pop_sp)(cpustate); break;\
+ case 0x5d: PREFIX86(_pop_bp)(cpustate); break;\
+ case 0x5e: PREFIX86(_pop_si)(cpustate); break;\
+ case 0x5f: PREFIX86(_pop_di)(cpustate); break;\
+ case 0x60: PREFIX86(_invalid_2b)(cpustate); break;\
+ case 0x61: PREFIX86(_invalid_2b)(cpustate); break;\
+ case 0x62: PREFIX86(_invalid_2b)(cpustate); break;\
+ case 0x63: PREFIX86(_invalid_2b)(cpustate); break;\
+ case 0x64: PREFIX86(_invalid_2b)(cpustate); break;\
+ case 0x65: PREFIX86(_invalid_2b)(cpustate); break;\
+ case 0x66: PREFIX86(_invalid_2b)(cpustate); break;\
+ case 0x67: PREFIX86(_invalid_2b)(cpustate); break;\
+ case 0x68: PREFIX86(_invalid_2b)(cpustate); break;\
+ case 0x69: PREFIX86(_invalid_2b)(cpustate); break;\
+ case 0x6a: PREFIX86(_invalid_2b)(cpustate); break;\
+ case 0x6b: PREFIX86(_invalid_2b)(cpustate); break;\
+ case 0x6c: PREFIX86(_invalid_2b)(cpustate); break;\
+ case 0x6d: PREFIX86(_invalid_2b)(cpustate); break;\
+ case 0x6e: PREFIX86(_invalid_2b)(cpustate); break;\
+ case 0x6f: PREFIX86(_invalid_2b)(cpustate); break;\
+ case 0x70: PREFIX86(_jo)(cpustate); break;\
+ case 0x71: PREFIX86(_jno)(cpustate); break;\
+ case 0x72: PREFIX86(_jb)(cpustate); break;\
+ case 0x73: PREFIX86(_jnb)(cpustate); break;\
+ case 0x74: PREFIX86(_jz)(cpustate); break;\
+ case 0x75: PREFIX86(_jnz)(cpustate); break;\
+ case 0x76: PREFIX86(_jbe)(cpustate); break;\
+ case 0x77: PREFIX86(_jnbe)(cpustate); break;\
+ case 0x78: PREFIX86(_js)(cpustate); break;\
+ case 0x79: PREFIX86(_jns)(cpustate); break;\
+ case 0x7a: PREFIX86(_jp)(cpustate); break;\
+ case 0x7b: PREFIX86(_jnp)(cpustate); break;\
+ case 0x7c: PREFIX86(_jl)(cpustate); break;\
+ case 0x7d: PREFIX86(_jnl)(cpustate); break;\
+ case 0x7e: PREFIX86(_jle)(cpustate); break;\
+ case 0x7f: PREFIX86(_jnle)(cpustate); break;\
+ case 0x80: PREFIX86(_80pre)(cpustate); break;\
+ case 0x81: PREFIX86(_81pre)(cpustate); break;\
+ case 0x82: PREFIX86(_82pre)(cpustate); break;\
+ case 0x83: PREFIX86(_83pre)(cpustate); break;\
+ case 0x84: PREFIX86(_test_br8)(cpustate); break;\
+ case 0x85: PREFIX86(_test_wr16)(cpustate); break;\
+ case 0x86: PREFIX86(_xchg_br8)(cpustate); break;\
+ case 0x87: PREFIX86(_xchg_wr16)(cpustate); break;\
+ case 0x88: PREFIX86(_mov_br8)(cpustate); break;\
+ case 0x89: PREFIX86(_mov_wr16)(cpustate); break;\
+ case 0x8a: PREFIX86(_mov_r8b)(cpustate); break;\
+ case 0x8b: PREFIX86(_mov_r16w)(cpustate); break;\
+ case 0x8c: PREFIX86(_mov_wsreg)(cpustate); break;\
+ case 0x8d: PREFIX86(_lea)(cpustate); break;\
+ case 0x8e: PREFIX86(_mov_sregw)(cpustate); break;\
+ case 0x8f: PREFIX86(_popw)(cpustate); break;\
+ case 0x90: PREFIX86(_nop)(cpustate); break;\
+ case 0x91: PREFIX86(_xchg_axcx)(cpustate); break;\
+ case 0x92: PREFIX86(_xchg_axdx)(cpustate); break;\
+ case 0x93: PREFIX86(_xchg_axbx)(cpustate); break;\
+ case 0x94: PREFIX86(_xchg_axsp)(cpustate); break;\
+ case 0x95: PREFIX86(_xchg_axbp)(cpustate); break;\
+ case 0x96: PREFIX86(_xchg_axsi)(cpustate); break;\
+ case 0x97: PREFIX86(_xchg_axdi)(cpustate); break;\
+ case 0x98: PREFIX86(_cbw)(cpustate); break;\
+ case 0x99: PREFIX86(_cwd)(cpustate); break;\
+ case 0x9a: PREFIX86(_call_far)(cpustate); break;\
+ case 0x9b: PREFIX86(_wait)(cpustate); break;\
+ case 0x9c: PREFIX86(_pushf)(cpustate); break;\
+ case 0x9d: PREFIX86(_popf)(cpustate); break;\
+ case 0x9e: PREFIX86(_sahf)(cpustate); break;\
+ case 0x9f: PREFIX86(_lahf)(cpustate); break;\
+ case 0xa0: PREFIX86(_mov_aldisp)(cpustate); break;\
+ case 0xa1: PREFIX86(_mov_axdisp)(cpustate); break;\
+ case 0xa2: PREFIX86(_mov_dispal)(cpustate); break;\
+ case 0xa3: PREFIX86(_mov_dispax)(cpustate); break;\
+ case 0xa4: PREFIX86(_movsb)(cpustate); break;\
+ case 0xa5: PREFIX86(_movsw)(cpustate); break;\
+ case 0xa6: PREFIX86(_cmpsb)(cpustate); break;\
+ case 0xa7: PREFIX86(_cmpsw)(cpustate); break;\
+ case 0xa8: PREFIX86(_test_ald8)(cpustate); break;\
+ case 0xa9: PREFIX86(_test_axd16)(cpustate); break;\
+ case 0xaa: PREFIX86(_stosb)(cpustate); break;\
+ case 0xab: PREFIX86(_stosw)(cpustate); break;\
+ case 0xac: PREFIX86(_lodsb)(cpustate); break;\
+ case 0xad: PREFIX86(_lodsw)(cpustate); break;\
+ case 0xae: PREFIX86(_scasb)(cpustate); break;\
+ case 0xaf: PREFIX86(_scasw)(cpustate); break;\
+ case 0xb0: PREFIX86(_mov_ald8)(cpustate); break;\
+ case 0xb1: PREFIX86(_mov_cld8)(cpustate); break;\
+ case 0xb2: PREFIX86(_mov_dld8)(cpustate); break;\
+ case 0xb3: PREFIX86(_mov_bld8)(cpustate); break;\
+ case 0xb4: PREFIX86(_mov_ahd8)(cpustate); break;\
+ case 0xb5: PREFIX86(_mov_chd8)(cpustate); break;\
+ case 0xb6: PREFIX86(_mov_dhd8)(cpustate); break;\
+ case 0xb7: PREFIX86(_mov_bhd8)(cpustate); break;\
+ case 0xb8: PREFIX86(_mov_axd16)(cpustate); break;\
+ case 0xb9: PREFIX86(_mov_cxd16)(cpustate); break;\
+ case 0xba: PREFIX86(_mov_dxd16)(cpustate); break;\
+ case 0xbb: PREFIX86(_mov_bxd16)(cpustate); break;\
+ case 0xbc: PREFIX86(_mov_spd16)(cpustate); break;\
+ case 0xbd: PREFIX86(_mov_bpd16)(cpustate); break;\
+ case 0xbe: PREFIX86(_mov_sid16)(cpustate); break;\
+ case 0xbf: PREFIX86(_mov_did16)(cpustate); break;\
+ case 0xc0: PREFIX86(_invalid)(cpustate); break;\
+ case 0xc1: PREFIX86(_invalid)(cpustate); break;\
+ case 0xc2: PREFIX86(_ret_d16)(cpustate); break;\
+ case 0xc3: PREFIX86(_ret)(cpustate); break;\
+ case 0xc4: PREFIX86(_les_dw)(cpustate); break;\
+ case 0xc5: PREFIX86(_lds_dw)(cpustate); break;\
+ case 0xc6: PREFIX86(_mov_bd8)(cpustate); break;\
+ case 0xc7: PREFIX86(_mov_wd16)(cpustate); break;\
+ case 0xc8: PREFIX86(_invalid)(cpustate); break;\
+ case 0xc9: PREFIX86(_invalid)(cpustate); break;\
+ case 0xca: PREFIX86(_retf_d16)(cpustate); break;\
+ case 0xcb: PREFIX86(_retf)(cpustate); break;\
+ case 0xcc: PREFIX86(_int3)(cpustate); break;\
+ case 0xcd: PREFIX86(_int)(cpustate); break;\
+ case 0xce: PREFIX86(_into)(cpustate); break;\
+ case 0xcf: PREFIX86(_iret)(cpustate); break;\
+ case 0xd0: PREFIX86(_rotshft_b)(cpustate); break;\
+ case 0xd1: PREFIX86(_rotshft_w)(cpustate); break;\
+ case 0xd2: PREFIX86(_rotshft_bcl)(cpustate); break;\
+ case 0xd3: PREFIX86(_rotshft_wcl)(cpustate); break;\
+ case 0xd4: PREFIX86(_aam)(cpustate); break;\
+ case 0xd5: PREFIX86(_aad)(cpustate); break;\
+ case 0xd6: PREFIX86(_invalid)(cpustate); break;\
+ case 0xd7: PREFIX86(_xlat)(cpustate); break;\
+ case 0xd8: PREFIX86(_escape)(cpustate); break;\
+ case 0xd9: PREFIX86(_escape)(cpustate); break;\
+ case 0xda: PREFIX86(_escape)(cpustate); break;\
+ case 0xdb: PREFIX86(_escape)(cpustate); break;\
+ case 0xdc: PREFIX86(_escape)(cpustate); break;\
+ case 0xdd: PREFIX86(_escape)(cpustate); break;\
+ case 0xde: PREFIX86(_escape)(cpustate); break;\
+ case 0xdf: PREFIX86(_escape)(cpustate); break;\
+ case 0xe0: PREFIX86(_loopne)(cpustate); break;\
+ case 0xe1: PREFIX86(_loope)(cpustate); break;\
+ case 0xe2: PREFIX86(_loop)(cpustate); break;\
+ case 0xe3: PREFIX86(_jcxz)(cpustate); break;\
+ case 0xe4: PREFIX86(_inal)(cpustate); break;\
+ case 0xe5: PREFIX86(_inax)(cpustate); break;\
+ case 0xe6: PREFIX86(_outal)(cpustate); break;\
+ case 0xe7: PREFIX86(_outax)(cpustate); break;\
+ case 0xe8: PREFIX86(_call_d16)(cpustate); break;\
+ case 0xe9: PREFIX86(_jmp_d16)(cpustate); break;\
+ case 0xea: PREFIX86(_jmp_far)(cpustate); break;\
+ case 0xeb: PREFIX86(_jmp_d8)(cpustate); break;\
+ case 0xec: PREFIX86(_inaldx)(cpustate); break;\
+ case 0xed: PREFIX86(_inaxdx)(cpustate); break;\
+ case 0xee: PREFIX86(_outdxal)(cpustate); break;\
+ case 0xef: PREFIX86(_outdxax)(cpustate); break;\
+ case 0xf0: PREFIX86(_lock)(cpustate); break;\
+ case 0xf1: PREFIX86(_invalid)(cpustate); break;\
+ case 0xf2: PREFIX86(_repne)(cpustate); break;\
+ case 0xf3: PREFIX86(_repe)(cpustate); break;\
+ case 0xf4: PREFIX86(_hlt)(cpustate); break;\
+ case 0xf5: PREFIX86(_cmc)(cpustate); break;\
+ case 0xf6: PREFIX86(_f6pre)(cpustate); break;\
+ case 0xf7: PREFIX86(_f7pre)(cpustate); break;\
+ case 0xf8: PREFIX86(_clc)(cpustate); break;\
+ case 0xf9: PREFIX86(_stc)(cpustate); break;\
+ case 0xfa: PREFIX86(_cli)(cpustate); break;\
+ case 0xfb: PREFIX86(_sti)(cpustate); break;\
+ case 0xfc: PREFIX86(_cld)(cpustate); break;\
+ case 0xfd: PREFIX86(_std)(cpustate); break;\
+ case 0xfe: PREFIX86(_fepre)(cpustate); break;\
+ case 0xff: PREFIX86(_ffpre)(cpustate); break;\
+ };
+#else
+#define TABLE86 PREFIX86(_instruction)[FETCHOP](cpustate);
+#endif
diff --git a/trunk/src/emu/cpu/i860/i860.c b/trunk/src/emu/cpu/i860/i860.c
new file mode 100644
index 00000000000..85e9c85250b
--- /dev/null
+++ b/trunk/src/emu/cpu/i860/i860.c
@@ -0,0 +1,384 @@
+/***************************************************************************
+
+ i860.c
+
+ Interface file for the Intel i860 emulator.
+
+ Copyright (C) 1995-present Jason Eckhardt (jle@rice.edu)
+ Released for general non-commercial use under the MAME license
+ with the additional requirement that you are free to use and
+ redistribute this code in modified or unmodified form, provided
+ you list me in the credits.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+/*
+TODO: Separate out i860XR and i860XP (make different types, etc).
+ Hook IRQ lines into MAME core (they're custom functions atm).
+*/
+
+#include "emu.h"
+#include "debugger.h"
+#include "i860.h"
+
+/**************************************************************************
+ * Functions specified by GET_INFO
+ **************************************************************************/
+
+static CPU_INIT( i860 )
+{
+ i860_state_t *cpustate = get_safe_token(device);
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ reset_i860(cpustate);
+ i860_set_pin(device, DEC_PIN_BUS_HOLD, 0);
+ i860_set_pin(device, DEC_PIN_RESET, 0);
+ cpustate->single_stepping = 0;
+
+ device->save_item(NAME(cpustate->iregs));
+ device->save_item(NAME(cpustate->cregs));
+ device->save_item(NAME(cpustate->frg));
+ device->save_item(NAME(cpustate->pc));
+}
+
+static CPU_RESET( i860 )
+{
+ i860_state_t *cpustate = get_safe_token(device);
+ reset_i860(cpustate);
+}
+
+
+/***************************************************************************
+ * Disassembler hook
+ ***************************************************************************/
+
+static CPU_DISASSEMBLE( i860 )
+{
+ extern unsigned disasm_i860(char*, unsigned, UINT32);
+
+ /* Hard-coded little endian for now. */
+ return disasm_i860(buffer, pc, (oprom[0] << 0) |
+ (oprom[1] << 8) |
+ (oprom[2] << 16) |
+ (oprom[3] << 24));
+}
+
+
+/**************************************************************************
+ * The actual decode and execute code.
+ **************************************************************************/
+#include "i860dec.c"
+
+
+/**************************************************************************
+ * Generic set_info/get_info
+ **************************************************************************/
+
+#define CPU_SET_INFO_F(fnum) cpustate->frg[0+(4*fnum)] = (info->i & 0x000000ff); \
+ cpustate->frg[1+(4*fnum)] = (info->i & 0x0000ff00) >> 8; \
+ cpustate->frg[2+(4*fnum)] = (info->i & 0x00ff0000) >> 16; \
+ cpustate->frg[3+(4*fnum)] = (info->i & 0xff000000) >> 24;
+
+static CPU_SET_INFO( i860 )
+{
+ i860_state_t *cpustate = get_safe_token(device);
+
+ switch(state)
+ {
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + I860_PC: cpustate->pc = info->i & 0xffffffff; break;
+
+ case CPUINFO_INT_REGISTER + I860_FIR: cpustate->cregs[CR_FIR] = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + I860_PSR: cpustate->cregs[CR_PSR] = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + I860_DIRBASE: cpustate->cregs[CR_DIRBASE] = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + I860_DB: cpustate->cregs[CR_DB] = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + I860_FSR: cpustate->cregs[CR_FSR] = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + I860_EPSR: cpustate->cregs[CR_EPSR] = info->i & 0xffffffff; break;
+
+ case CPUINFO_INT_REGISTER + I860_R0: cpustate->iregs[0] = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + I860_R1: cpustate->iregs[1] = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + I860_R2: cpustate->iregs[2] = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + I860_R3: cpustate->iregs[3] = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + I860_R4: cpustate->iregs[4] = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + I860_R5: cpustate->iregs[5] = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + I860_R6: cpustate->iregs[6] = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + I860_R7: cpustate->iregs[7] = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + I860_R8: cpustate->iregs[8] = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + I860_R9: cpustate->iregs[9] = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + I860_R10: cpustate->iregs[10] = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + I860_R11: cpustate->iregs[11] = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + I860_R12: cpustate->iregs[12] = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + I860_R13: cpustate->iregs[13] = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + I860_R14: cpustate->iregs[14] = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + I860_R15: cpustate->iregs[15] = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + I860_R16: cpustate->iregs[16] = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + I860_R17: cpustate->iregs[17] = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + I860_R18: cpustate->iregs[18] = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + I860_R19: cpustate->iregs[19] = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + I860_R20: cpustate->iregs[20] = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + I860_R21: cpustate->iregs[21] = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + I860_R22: cpustate->iregs[22] = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + I860_R23: cpustate->iregs[23] = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + I860_R24: cpustate->iregs[24] = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + I860_R25: cpustate->iregs[25] = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + I860_R26: cpustate->iregs[26] = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + I860_R27: cpustate->iregs[27] = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + I860_R28: cpustate->iregs[28] = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + I860_R29: cpustate->iregs[29] = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + I860_R30: cpustate->iregs[30] = info->i & 0xffffffff; break;
+ case CPUINFO_INT_REGISTER + I860_R31: cpustate->iregs[31] = info->i & 0xffffffff; break;
+
+ case CPUINFO_INT_REGISTER + I860_F0: CPU_SET_INFO_F(0); break;
+ case CPUINFO_INT_REGISTER + I860_F1: CPU_SET_INFO_F(1); break;
+ case CPUINFO_INT_REGISTER + I860_F2: CPU_SET_INFO_F(2); break;
+ case CPUINFO_INT_REGISTER + I860_F3: CPU_SET_INFO_F(3); break;
+ case CPUINFO_INT_REGISTER + I860_F4: CPU_SET_INFO_F(4); break;
+ case CPUINFO_INT_REGISTER + I860_F5: CPU_SET_INFO_F(5); break;
+ case CPUINFO_INT_REGISTER + I860_F6: CPU_SET_INFO_F(6); break;
+ case CPUINFO_INT_REGISTER + I860_F7: CPU_SET_INFO_F(7); break;
+ case CPUINFO_INT_REGISTER + I860_F8: CPU_SET_INFO_F(8); break;
+ case CPUINFO_INT_REGISTER + I860_F9: CPU_SET_INFO_F(9); break;
+ case CPUINFO_INT_REGISTER + I860_F10: CPU_SET_INFO_F(10); break;
+ case CPUINFO_INT_REGISTER + I860_F11: CPU_SET_INFO_F(11); break;
+ case CPUINFO_INT_REGISTER + I860_F12: CPU_SET_INFO_F(12); break;
+ case CPUINFO_INT_REGISTER + I860_F13: CPU_SET_INFO_F(13); break;
+ case CPUINFO_INT_REGISTER + I860_F14: CPU_SET_INFO_F(14); break;
+ case CPUINFO_INT_REGISTER + I860_F15: CPU_SET_INFO_F(15); break;
+ case CPUINFO_INT_REGISTER + I860_F16: CPU_SET_INFO_F(16); break;
+ case CPUINFO_INT_REGISTER + I860_F17: CPU_SET_INFO_F(17); break;
+ case CPUINFO_INT_REGISTER + I860_F18: CPU_SET_INFO_F(18); break;
+ case CPUINFO_INT_REGISTER + I860_F19: CPU_SET_INFO_F(19); break;
+ case CPUINFO_INT_REGISTER + I860_F20: CPU_SET_INFO_F(20); break;
+ case CPUINFO_INT_REGISTER + I860_F21: CPU_SET_INFO_F(21); break;
+ case CPUINFO_INT_REGISTER + I860_F22: CPU_SET_INFO_F(22); break;
+ case CPUINFO_INT_REGISTER + I860_F23: CPU_SET_INFO_F(23); break;
+ case CPUINFO_INT_REGISTER + I860_F24: CPU_SET_INFO_F(24); break;
+ case CPUINFO_INT_REGISTER + I860_F25: CPU_SET_INFO_F(25); break;
+ case CPUINFO_INT_REGISTER + I860_F26: CPU_SET_INFO_F(26); break;
+ case CPUINFO_INT_REGISTER + I860_F27: CPU_SET_INFO_F(27); break;
+ case CPUINFO_INT_REGISTER + I860_F28: CPU_SET_INFO_F(28); break;
+ case CPUINFO_INT_REGISTER + I860_F29: CPU_SET_INFO_F(29); break;
+ case CPUINFO_INT_REGISTER + I860_F30: CPU_SET_INFO_F(30); break;
+ case CPUINFO_INT_REGISTER + I860_F31: CPU_SET_INFO_F(31); break;
+ }
+}
+
+#define CPU_GET_INFO_INT_F(fnum) (info->i = cpustate->frg[0+(4*fnum)] | \
+ cpustate->frg[1+(4*fnum)] << 8 | \
+ cpustate->frg[2+(4*fnum)] << 16 | \
+ cpustate->frg[3+(4*fnum)] << 24)
+
+#define CPU_GET_INFO_STR_F(fnum) (sprintf(info->s, "F%d : %08x", fnum, cpustate->frg[0+(4*fnum)] | \
+ cpustate->frg[1+(4*fnum)] << 8 | \
+ cpustate->frg[2+(4*fnum)] << 16 | \
+ cpustate->frg[3+(4*fnum)] << 24))
+
+CPU_GET_INFO( i860 )
+{
+ i860_state_t *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(i860_state_t); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 0; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0x00000000; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 8; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 64; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + I860_PC: info->i = cpustate->pc; break;
+ case CPUINFO_INT_PREVIOUSPC: info->i = cpustate->ppc; break;
+
+ case CPUINFO_INT_REGISTER + I860_FIR: info->i = cpustate->cregs[CR_FIR]; break;
+ case CPUINFO_INT_REGISTER + I860_PSR: info->i = cpustate->cregs[CR_PSR]; break;
+ case CPUINFO_INT_REGISTER + I860_DIRBASE: info->i = cpustate->cregs[CR_DIRBASE]; break;
+ case CPUINFO_INT_REGISTER + I860_DB: info->i = cpustate->cregs[CR_DB]; break;
+ case CPUINFO_INT_REGISTER + I860_FSR: info->i = cpustate->cregs[CR_FSR]; break;
+ case CPUINFO_INT_REGISTER + I860_EPSR: info->i = cpustate->cregs[CR_EPSR]; break;
+
+ case CPUINFO_INT_REGISTER + I860_R0: info->i = cpustate->iregs[0]; break;
+ case CPUINFO_INT_REGISTER + I860_R1: info->i = cpustate->iregs[1]; break;
+ case CPUINFO_INT_REGISTER + I860_R2: info->i = cpustate->iregs[2]; break;
+ case CPUINFO_INT_REGISTER + I860_R3: info->i = cpustate->iregs[3]; break;
+ case CPUINFO_INT_REGISTER + I860_R4: info->i = cpustate->iregs[4]; break;
+ case CPUINFO_INT_REGISTER + I860_R5: info->i = cpustate->iregs[5]; break;
+ case CPUINFO_INT_REGISTER + I860_R6: info->i = cpustate->iregs[6]; break;
+ case CPUINFO_INT_REGISTER + I860_R7: info->i = cpustate->iregs[7]; break;
+ case CPUINFO_INT_REGISTER + I860_R8: info->i = cpustate->iregs[8]; break;
+ case CPUINFO_INT_REGISTER + I860_R9: info->i = cpustate->iregs[9]; break;
+ case CPUINFO_INT_REGISTER + I860_R10: info->i = cpustate->iregs[10]; break;
+ case CPUINFO_INT_REGISTER + I860_R11: info->i = cpustate->iregs[11]; break;
+ case CPUINFO_INT_REGISTER + I860_R12: info->i = cpustate->iregs[12]; break;
+ case CPUINFO_INT_REGISTER + I860_R13: info->i = cpustate->iregs[13]; break;
+ case CPUINFO_INT_REGISTER + I860_R14: info->i = cpustate->iregs[14]; break;
+ case CPUINFO_INT_REGISTER + I860_R15: info->i = cpustate->iregs[15]; break;
+ case CPUINFO_INT_REGISTER + I860_R16: info->i = cpustate->iregs[16]; break;
+ case CPUINFO_INT_REGISTER + I860_R17: info->i = cpustate->iregs[17]; break;
+ case CPUINFO_INT_REGISTER + I860_R18: info->i = cpustate->iregs[18]; break;
+ case CPUINFO_INT_REGISTER + I860_R19: info->i = cpustate->iregs[19]; break;
+ case CPUINFO_INT_REGISTER + I860_R20: info->i = cpustate->iregs[20]; break;
+ case CPUINFO_INT_REGISTER + I860_R21: info->i = cpustate->iregs[21]; break;
+ case CPUINFO_INT_REGISTER + I860_R22: info->i = cpustate->iregs[22]; break;
+ case CPUINFO_INT_REGISTER + I860_R23: info->i = cpustate->iregs[23]; break;
+ case CPUINFO_INT_REGISTER + I860_R24: info->i = cpustate->iregs[24]; break;
+ case CPUINFO_INT_REGISTER + I860_R25: info->i = cpustate->iregs[25]; break;
+ case CPUINFO_INT_REGISTER + I860_R26: info->i = cpustate->iregs[26]; break;
+ case CPUINFO_INT_REGISTER + I860_R27: info->i = cpustate->iregs[27]; break;
+ case CPUINFO_INT_REGISTER + I860_R28: info->i = cpustate->iregs[28]; break;
+ case CPUINFO_INT_REGISTER + I860_R29: info->i = cpustate->iregs[29]; break;
+ case CPUINFO_INT_REGISTER + I860_R30: info->i = cpustate->iregs[30]; break;
+ case CPUINFO_INT_REGISTER + I860_R31: info->i = cpustate->iregs[31]; break;
+
+ case CPUINFO_INT_REGISTER + I860_F0: CPU_GET_INFO_INT_F(0); break;
+ case CPUINFO_INT_REGISTER + I860_F1: CPU_GET_INFO_INT_F(1); break;
+ case CPUINFO_INT_REGISTER + I860_F2: CPU_GET_INFO_INT_F(2); break;
+ case CPUINFO_INT_REGISTER + I860_F3: CPU_GET_INFO_INT_F(3); break;
+ case CPUINFO_INT_REGISTER + I860_F4: CPU_GET_INFO_INT_F(4); break;
+ case CPUINFO_INT_REGISTER + I860_F5: CPU_GET_INFO_INT_F(5); break;
+ case CPUINFO_INT_REGISTER + I860_F6: CPU_GET_INFO_INT_F(6); break;
+ case CPUINFO_INT_REGISTER + I860_F7: CPU_GET_INFO_INT_F(7); break;
+ case CPUINFO_INT_REGISTER + I860_F8: CPU_GET_INFO_INT_F(8); break;
+ case CPUINFO_INT_REGISTER + I860_F9: CPU_GET_INFO_INT_F(9); break;
+ case CPUINFO_INT_REGISTER + I860_F10: CPU_GET_INFO_INT_F(10); break;
+ case CPUINFO_INT_REGISTER + I860_F11: CPU_GET_INFO_INT_F(11); break;
+ case CPUINFO_INT_REGISTER + I860_F12: CPU_GET_INFO_INT_F(12); break;
+ case CPUINFO_INT_REGISTER + I860_F13: CPU_GET_INFO_INT_F(13); break;
+ case CPUINFO_INT_REGISTER + I860_F14: CPU_GET_INFO_INT_F(14); break;
+ case CPUINFO_INT_REGISTER + I860_F15: CPU_GET_INFO_INT_F(15); break;
+ case CPUINFO_INT_REGISTER + I860_F16: CPU_GET_INFO_INT_F(16); break;
+ case CPUINFO_INT_REGISTER + I860_F17: CPU_GET_INFO_INT_F(17); break;
+ case CPUINFO_INT_REGISTER + I860_F18: CPU_GET_INFO_INT_F(18); break;
+ case CPUINFO_INT_REGISTER + I860_F19: CPU_GET_INFO_INT_F(19); break;
+ case CPUINFO_INT_REGISTER + I860_F20: CPU_GET_INFO_INT_F(20); break;
+ case CPUINFO_INT_REGISTER + I860_F21: CPU_GET_INFO_INT_F(21); break;
+ case CPUINFO_INT_REGISTER + I860_F22: CPU_GET_INFO_INT_F(22); break;
+ case CPUINFO_INT_REGISTER + I860_F23: CPU_GET_INFO_INT_F(23); break;
+ case CPUINFO_INT_REGISTER + I860_F24: CPU_GET_INFO_INT_F(24); break;
+ case CPUINFO_INT_REGISTER + I860_F25: CPU_GET_INFO_INT_F(25); break;
+ case CPUINFO_INT_REGISTER + I860_F26: CPU_GET_INFO_INT_F(26); break;
+ case CPUINFO_INT_REGISTER + I860_F27: CPU_GET_INFO_INT_F(27); break;
+ case CPUINFO_INT_REGISTER + I860_F28: CPU_GET_INFO_INT_F(28); break;
+ case CPUINFO_INT_REGISTER + I860_F29: CPU_GET_INFO_INT_F(29); break;
+ case CPUINFO_INT_REGISTER + I860_F30: CPU_GET_INFO_INT_F(30); break;
+ case CPUINFO_INT_REGISTER + I860_F31: CPU_GET_INFO_INT_F(31); break;
+
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(i860); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(i860); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(i860); break;
+ case CPUINFO_FCT_EXIT: info->exit = NULL; break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(i860); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(i860); break;
+ case CPUINFO_FCT_DEBUG_INIT: info->debug_init = NULL; break;
+ case CPUINFO_FCT_TRANSLATE: info->translate = NULL; break;
+ case CPUINFO_FCT_READ: info->read = NULL; break;
+ case CPUINFO_FCT_WRITE: info->write = NULL; break;
+ case CPUINFO_FCT_READOP: info->readop = NULL; break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "i860XR"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Intel i860"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "0.1"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Jason Eckhardt"); break;
+
+ case CPUINFO_STR_FLAGS:
+ strcpy(info->s, ""); break;
+
+ case CPUINFO_STR_REGISTER + I860_PC: sprintf(info->s, "PC : %08x", cpustate->pc); break;
+ case CPUINFO_STR_REGISTER + I860_FIR: sprintf(info->s, "FIR : %08x", cpustate->cregs[CR_FIR]); break;
+ case CPUINFO_STR_REGISTER + I860_PSR: sprintf(info->s, "PSR : %08x", cpustate->cregs[CR_PSR]); break;
+ case CPUINFO_STR_REGISTER + I860_DIRBASE: sprintf(info->s, "DIRBASE : %08x", cpustate->cregs[CR_DIRBASE]);break;
+ case CPUINFO_STR_REGISTER + I860_DB: sprintf(info->s, "DB : %08x", cpustate->cregs[CR_DB]); break;
+ case CPUINFO_STR_REGISTER + I860_FSR: sprintf(info->s, "FSR : %08x", cpustate->cregs[CR_FSR]); break;
+ case CPUINFO_STR_REGISTER + I860_EPSR: sprintf(info->s, "EPSR : %08x", cpustate->cregs[CR_EPSR]); break;
+
+ case CPUINFO_STR_REGISTER + I860_R0: sprintf(info->s, "R0 : %08x", cpustate->iregs[0]); break;
+ case CPUINFO_STR_REGISTER + I860_R1: sprintf(info->s, "R1 : %08x", cpustate->iregs[1]); break;
+ case CPUINFO_STR_REGISTER + I860_R2: sprintf(info->s, "R2 : %08x", cpustate->iregs[2]); break;
+ case CPUINFO_STR_REGISTER + I860_R3: sprintf(info->s, "R3 : %08x", cpustate->iregs[3]); break;
+ case CPUINFO_STR_REGISTER + I860_R4: sprintf(info->s, "R4 : %08x", cpustate->iregs[4]); break;
+ case CPUINFO_STR_REGISTER + I860_R5: sprintf(info->s, "R5 : %08x", cpustate->iregs[5]); break;
+ case CPUINFO_STR_REGISTER + I860_R6: sprintf(info->s, "R6 : %08x", cpustate->iregs[6]); break;
+ case CPUINFO_STR_REGISTER + I860_R7: sprintf(info->s, "R7 : %08x", cpustate->iregs[7]); break;
+ case CPUINFO_STR_REGISTER + I860_R8: sprintf(info->s, "R8 : %08x", cpustate->iregs[8]); break;
+ case CPUINFO_STR_REGISTER + I860_R9: sprintf(info->s, "R9 : %08x", cpustate->iregs[9]); break;
+ case CPUINFO_STR_REGISTER + I860_R10: sprintf(info->s, "R10 : %08x", cpustate->iregs[10]); break;
+ case CPUINFO_STR_REGISTER + I860_R11: sprintf(info->s, "R11 : %08x", cpustate->iregs[11]); break;
+ case CPUINFO_STR_REGISTER + I860_R12: sprintf(info->s, "R12 : %08x", cpustate->iregs[12]); break;
+ case CPUINFO_STR_REGISTER + I860_R13: sprintf(info->s, "R13 : %08x", cpustate->iregs[13]); break;
+ case CPUINFO_STR_REGISTER + I860_R14: sprintf(info->s, "R14 : %08x", cpustate->iregs[14]); break;
+ case CPUINFO_STR_REGISTER + I860_R15: sprintf(info->s, "R15 : %08x", cpustate->iregs[15]); break;
+ case CPUINFO_STR_REGISTER + I860_R16: sprintf(info->s, "R16 : %08x", cpustate->iregs[16]); break;
+ case CPUINFO_STR_REGISTER + I860_R17: sprintf(info->s, "R17 : %08x", cpustate->iregs[17]); break;
+ case CPUINFO_STR_REGISTER + I860_R18: sprintf(info->s, "R18 : %08x", cpustate->iregs[18]); break;
+ case CPUINFO_STR_REGISTER + I860_R19: sprintf(info->s, "R19 : %08x", cpustate->iregs[19]); break;
+ case CPUINFO_STR_REGISTER + I860_R20: sprintf(info->s, "R20 : %08x", cpustate->iregs[20]); break;
+ case CPUINFO_STR_REGISTER + I860_R21: sprintf(info->s, "R21 : %08x", cpustate->iregs[21]); break;
+ case CPUINFO_STR_REGISTER + I860_R22: sprintf(info->s, "R22 : %08x", cpustate->iregs[22]); break;
+ case CPUINFO_STR_REGISTER + I860_R23: sprintf(info->s, "R23 : %08x", cpustate->iregs[23]); break;
+ case CPUINFO_STR_REGISTER + I860_R24: sprintf(info->s, "R24 : %08x", cpustate->iregs[24]); break;
+ case CPUINFO_STR_REGISTER + I860_R25: sprintf(info->s, "R25 : %08x", cpustate->iregs[25]); break;
+ case CPUINFO_STR_REGISTER + I860_R26: sprintf(info->s, "R26 : %08x", cpustate->iregs[26]); break;
+ case CPUINFO_STR_REGISTER + I860_R27: sprintf(info->s, "R27 : %08x", cpustate->iregs[27]); break;
+ case CPUINFO_STR_REGISTER + I860_R28: sprintf(info->s, "R28 : %08x", cpustate->iregs[28]); break;
+ case CPUINFO_STR_REGISTER + I860_R29: sprintf(info->s, "R29 : %08x", cpustate->iregs[29]); break;
+ case CPUINFO_STR_REGISTER + I860_R30: sprintf(info->s, "R30 : %08x", cpustate->iregs[30]); break;
+ case CPUINFO_STR_REGISTER + I860_R31: sprintf(info->s, "R31 : %08x", cpustate->iregs[31]); break;
+
+ case CPUINFO_STR_REGISTER + I860_F0: CPU_GET_INFO_STR_F(0); break;
+ case CPUINFO_STR_REGISTER + I860_F1: CPU_GET_INFO_STR_F(1); break;
+ case CPUINFO_STR_REGISTER + I860_F2: CPU_GET_INFO_STR_F(2); break;
+ case CPUINFO_STR_REGISTER + I860_F3: CPU_GET_INFO_STR_F(3); break;
+ case CPUINFO_STR_REGISTER + I860_F4: CPU_GET_INFO_STR_F(4); break;
+ case CPUINFO_STR_REGISTER + I860_F5: CPU_GET_INFO_STR_F(5); break;
+ case CPUINFO_STR_REGISTER + I860_F6: CPU_GET_INFO_STR_F(6); break;
+ case CPUINFO_STR_REGISTER + I860_F7: CPU_GET_INFO_STR_F(7); break;
+ case CPUINFO_STR_REGISTER + I860_F8: CPU_GET_INFO_STR_F(8); break;
+ case CPUINFO_STR_REGISTER + I860_F9: CPU_GET_INFO_STR_F(9); break;
+ case CPUINFO_STR_REGISTER + I860_F10: CPU_GET_INFO_STR_F(10); break;
+ case CPUINFO_STR_REGISTER + I860_F11: CPU_GET_INFO_STR_F(11); break;
+ case CPUINFO_STR_REGISTER + I860_F12: CPU_GET_INFO_STR_F(12); break;
+ case CPUINFO_STR_REGISTER + I860_F13: CPU_GET_INFO_STR_F(13); break;
+ case CPUINFO_STR_REGISTER + I860_F14: CPU_GET_INFO_STR_F(14); break;
+ case CPUINFO_STR_REGISTER + I860_F15: CPU_GET_INFO_STR_F(15); break;
+ case CPUINFO_STR_REGISTER + I860_F16: CPU_GET_INFO_STR_F(16); break;
+ case CPUINFO_STR_REGISTER + I860_F17: CPU_GET_INFO_STR_F(17); break;
+ case CPUINFO_STR_REGISTER + I860_F18: CPU_GET_INFO_STR_F(18); break;
+ case CPUINFO_STR_REGISTER + I860_F19: CPU_GET_INFO_STR_F(19); break;
+ case CPUINFO_STR_REGISTER + I860_F20: CPU_GET_INFO_STR_F(20); break;
+ case CPUINFO_STR_REGISTER + I860_F21: CPU_GET_INFO_STR_F(21); break;
+ case CPUINFO_STR_REGISTER + I860_F22: CPU_GET_INFO_STR_F(22); break;
+ case CPUINFO_STR_REGISTER + I860_F23: CPU_GET_INFO_STR_F(23); break;
+ case CPUINFO_STR_REGISTER + I860_F24: CPU_GET_INFO_STR_F(24); break;
+ case CPUINFO_STR_REGISTER + I860_F25: CPU_GET_INFO_STR_F(25); break;
+ case CPUINFO_STR_REGISTER + I860_F26: CPU_GET_INFO_STR_F(26); break;
+ case CPUINFO_STR_REGISTER + I860_F27: CPU_GET_INFO_STR_F(27); break;
+ case CPUINFO_STR_REGISTER + I860_F28: CPU_GET_INFO_STR_F(28); break;
+ case CPUINFO_STR_REGISTER + I860_F29: CPU_GET_INFO_STR_F(29); break;
+ case CPUINFO_STR_REGISTER + I860_F30: CPU_GET_INFO_STR_F(30); break;
+ case CPUINFO_STR_REGISTER + I860_F31: CPU_GET_INFO_STR_F(31); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(I860, i860);
diff --git a/trunk/src/emu/cpu/i860/i860.h b/trunk/src/emu/cpu/i860/i860.h
new file mode 100644
index 00000000000..8f3d4a8d74e
--- /dev/null
+++ b/trunk/src/emu/cpu/i860/i860.h
@@ -0,0 +1,223 @@
+/***************************************************************************
+
+ i860.h
+
+ Interface file for the Intel i860 emulator.
+
+ Copyright (C) 1995-present Jason Eckhardt (jle@rice.edu)
+ Released for general non-commercial use under the MAME license
+ with the additional requirement that you are free to use and
+ redistribute this code in modified or unmodified form, provided
+ you list me in the credits.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __I860_H__
+#define __I860_H__
+
+
+/***************************************************************************
+ REGISTER ENUMERATION
+***************************************************************************/
+
+enum
+{
+ I860_PC = 1,
+
+ I860_FIR,
+ I860_PSR,
+ I860_DIRBASE,
+ I860_DB,
+ I860_FSR,
+ I860_EPSR,
+
+ I860_R0, I860_R1, I860_R2, I860_R3, I860_R4, I860_R5, I860_R6, I860_R7, I860_R8, I860_R9,
+ I860_R10, I860_R11, I860_R12, I860_R13, I860_R14, I860_R15, I860_R16, I860_R17, I860_R18, I860_R19,
+ I860_R20, I860_R21, I860_R22, I860_R23, I860_R24, I860_R25, I860_R26, I860_R27, I860_R28, I860_R29,
+ I860_R30, I860_R31,
+
+ I860_F0, I860_F1, I860_F2, I860_F3, I860_F4, I860_F5, I860_F6, I860_F7, I860_F8, I860_F9,
+ I860_F10, I860_F11, I860_F12, I860_F13, I860_F14, I860_F15, I860_F16, I860_F17, I860_F18, I860_F19,
+ I860_F20, I860_F21, I860_F22, I860_F23, I860_F24, I860_F25, I860_F26, I860_F27, I860_F28, I860_F29,
+ I860_F30, I860_F31,
+
+};
+
+/* Needed for MAME */
+DECLARE_LEGACY_CPU_DEVICE(I860, i860);
+
+
+/***************************************************************************
+ STRUCTURES & TYPEDEFS
+***************************************************************************/
+
+/* i860 state. */
+typedef struct {
+ /* Integer registers (32 x 32-bits). */
+ UINT32 iregs[32];
+
+ /* Floating point registers (32 x 32-bits, 16 x 64 bits, or 8 x 128 bits).
+ When referenced as pairs or quads, the higher numbered registers
+ are the upper bits. E.g., double precision f0 is f1:f0. */
+ UINT8 frg[32 * 4];
+
+ /* Control registers (6 x 32-bits). */
+ UINT32 cregs[6];
+
+ /* Program counter (1 x 32-bits). Reset starts at pc=0xffffff00. */
+ UINT32 pc;
+
+ /* Special registers (4 x 64-bits). */
+ union
+ {
+ float s;
+ double d;
+ } KR, KI, T;
+ UINT64 merge;
+
+ /* The adder pipeline, always 3 stages. */
+ struct
+ {
+ /* The stage contents. */
+ union {
+ float s;
+ double d;
+ } val;
+
+ /* The stage status bits. */
+ struct {
+ /* Adder result precision (1 = dbl, 0 = sgl). */
+ char arp;
+ } stat;
+ } A[3];
+
+ /* The multiplier pipeline. 3 stages for single precision, 2 stages
+ for double precision, and confusing for mixed precision. */
+ struct {
+ /* The stage contents. */
+ union {
+ float s;
+ double d;
+ } val;
+
+ /* The stage status bits. */
+ struct {
+ /* Multiplier result precision (1 = dbl, 0 = sgl). */
+ char mrp;
+ } stat;
+ } M[3];
+
+ /* The load pipeline, always 3 stages. */
+ struct {
+ /* The stage contents. */
+ union {
+ float s;
+ double d;
+ } val;
+
+ /* The stage status bits. */
+ struct {
+ /* Load result precision (1 = dbl, 0 = sgl). */
+ char lrp;
+ } stat;
+ } L[3];
+
+ /* The graphics/integer pipeline, always 1 stage. */
+ struct {
+ /* The stage contents. */
+ union {
+ float s;
+ double d;
+ } val;
+
+ /* The stage status bits. */
+ struct {
+ /* Integer/graphics result precision (1 = dbl, 0 = sgl). */
+ char irp;
+ } stat;
+ } G;
+
+ /* Pins. */
+ int pin_bus_hold;
+ int pin_reset;
+
+ /*
+ * Other emulator state.
+ */
+ int exiting_readmem;
+ int exiting_ifetch;
+
+ /* Indicate a control-flow instruction, so we know the PC is updated. */
+ int pc_updated;
+
+ /* Indicate an instruction just generated a trap, so we know the PC
+ needs to go to the trap address. */
+ int pending_trap;
+
+ /* This is 1 if the next fir load gets the trap address, otherwise
+ it is 0 to get the ld.c address. This is set to 1 only when a
+ non-reset trap occurs. */
+ int fir_gets_trap_addr;
+
+ /* Single stepping flag for internal use. */
+ int single_stepping;
+
+ /*
+ * MAME-specific stuff.
+ */
+ legacy_cpu_device *device;
+ address_space *program;
+ UINT32 ppc;
+ int icount;
+
+} i860_state_t;
+
+INLINE i860_state_t *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == I860);
+ return (i860_state_t *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+
+/***************************************************************************
+ PUBLIC FUNCTIONS
+***************************************************************************/
+
+/* This is the external interface for asserting an external interrupt
+ to the i860. */
+extern void i860_gen_interrupt(i860_state_t*);
+
+/* This is the external interface for asserting/deasserting a pin on
+ the i860. */
+extern void i860_set_pin(device_t *, int, int);
+
+/* Hard or soft reset. */
+extern void reset_i860(i860_state_t*);
+
+/* i860 pins. */
+enum {
+ DEC_PIN_BUS_HOLD, /* Bus HOLD pin. */
+ DEC_PIN_RESET /* System reset pin. */
+};
+
+
+/* TODO: THESE WILL BE REPLACED BY MAME FUNCTIONS
+#define BYTE_REV32(t) \
+ do { \
+ (t) = ((UINT32)(t) >> 16) | ((UINT32)(t) << 16); \
+ (t) = (((UINT32)(t) >> 8) & 0x00ff00ff) | (((UINT32)(t) << 8) & 0xff00ff00); \
+ } while (0);
+
+#define BYTE_REV16(t) \
+ do { \
+ (t) = (((UINT16)(t) >> 8) & 0x00ff) | (((UINT16)(t) << 8) & 0xff00); \
+ } while (0);
+#endif
+*/
+
+#endif /* __I860_H__ */
+
diff --git a/trunk/src/emu/cpu/i860/i860dasm.c b/trunk/src/emu/cpu/i860/i860dasm.c
new file mode 100644
index 00000000000..3440236c822
--- /dev/null
+++ b/trunk/src/emu/cpu/i860/i860dasm.c
@@ -0,0 +1,377 @@
+#include "i860.h"
+
+/* Sub-group decoders */
+static void i860_dasm_core_dasm(const UINT32 op, char* buffer);
+static void i860_dasm_floating_point_dasm(const UINT32 op, char* buffer);
+static void i860_dasm_CTRL_dasm(const UINT32 op, char* buffer);
+
+/* REG-Format Opcodes*/
+static void i860_dasm_ldx(const UINT32 op, char* buffer);
+static void i860_dasm_stx(const UINT32 op, char* buffer);
+static void i860_dasm_ixfr(const UINT32 op, char* buffer);
+static void i860_dasm_fid_fst(const UINT32 op, char* buffer);
+static void i860_dasm_flush(const UINT32 op, char* buffer);
+static void i860_dasm_pstd(const UINT32 op, char* buffer);
+static void i860_dasm_ldc_sdc(const UINT32 op, char* buffer);
+static void i860_dasm_bri(const UINT32 op, char* buffer);
+static void i860_dasm_trap(const UINT32 op, char* buffer);
+static void i860_dasm_bte_btne(const UINT32 op, char* buffer);
+static void i860_dasm_pfidy(const UINT32 op, char* buffer);
+static void i860_dasm_addu_subu(const UINT32 op, char* buffer);
+static void i860_dasm_shl_shr(const UINT32 op, char* buffer);
+static void i860_dasm_shrd(const UINT32 op, char* buffer);
+static void i860_dasm_bla(const UINT32 op, char* buffer);
+static void i860_dasm_shra(const UINT32 op, char* buffer);
+static void i860_dasm_and_andh(const UINT32 op, char* buffer);
+static void i860_dasm_andnot_andnoth(const UINT32 op, char* buffer);
+static void i860_dasm_or_orh(const UINT32 op, char* buffer);
+static void i860_dasm_xor_xorh(const UINT32 op, char* buffer);
+
+/* CORE Escape Opcodes */
+static void i860_dasm_CORE_lock(const UINT32 op, char* buffer);
+static void i860_dasm_CORE_calli(const UINT32 op, char* buffer);
+static void i860_dasm_CORE_intovr(const UINT32 op, char* buffer);
+static void i860_dasm_CORE_unlock(const UINT32 op, char* buffer);
+
+/* CTRL-Format Opcodes */
+static void i860_dasm_CTRL_br(const UINT32 op, char* buffer);
+static void i860_dasm_CTRL_call(const UINT32 op, char* buffer);
+static void i860_dasm_CTRL_bc_bct(const UINT32 op, char* buffer);
+static void i860_dasm_CTRL_bnc_bnct(const UINT32 op, char* buffer);
+
+/* Floating-Point Instructions */
+
+
+CPU_DISASSEMBLE( i860 )
+{
+ char tempB[1024] = "";
+
+ /* Little Endian */
+ const UINT32 op = (oprom[3] << 24) | (oprom[2] << 16) | (oprom[1] << 8) | (oprom[0] << 0);
+ //const UINT32 op = (oprom[2] << 24) | (oprom[3] << 16) | (oprom[0] << 8) | (oprom[1] << 0); /* Mixed Endian */
+ //const UINT32 op = (oprom[0] << 24) | (oprom[1] << 16) | (oprom[2] << 8) | (oprom[3] << 0); /* Big Endian */
+ //const UINT32 op = (oprom[1] << 24) | (oprom[0] << 16) | (oprom[3] << 8) | (oprom[2] << 0); /* Mixed Endian */
+
+ /* The opcode is the top 6 bits */
+ UINT8 opcode = (op >> 26) & 0x3f;
+
+ /* DEBUG - print this out if you feel things are going a bit wonky */
+ // sprintf(buffer, "%08x : oo %02x", op, opcode);
+
+ /* Main decode */
+ switch (opcode)
+ {
+ case 0x00:
+ case 0x01:
+ case 0x04:
+ case 0x05: i860_dasm_ldx(op, tempB); break;
+
+ case 0x03:
+ case 0x07: i860_dasm_stx(op, tempB); break;
+
+ case 0x02: i860_dasm_ixfr(op, tempB); break;
+
+ case 0x06: sprintf(tempB, "(reserved)"); break;
+
+ case 0x08:
+ case 0x09:
+ case 0x0a:
+ case 0x0b: i860_dasm_fid_fst(op, tempB); break;
+
+ case 0x0d: i860_dasm_flush(op, tempB); break;
+
+ case 0x0f: i860_dasm_pstd(op, tempB); break;
+
+ case 0x0c:
+ case 0x0e: i860_dasm_ldc_sdc(op, tempB); break;
+
+ case 0x10: i860_dasm_bri(op, tempB); break;
+
+ case 0x11: i860_dasm_trap(op, tempB); break;
+
+ case 0x12: i860_dasm_floating_point_dasm(op, tempB); break; /* Floating point operation sub-group */
+
+ case 0x13: i860_dasm_core_dasm(op, tempB); break; /* Core operation sub-group */
+
+ case 0x14:
+ case 0x15:
+ case 0x16:
+ case 0x17: i860_dasm_bte_btne(op, tempB); break;
+
+ case 0x18:
+ case 0x19: i860_dasm_pfidy(op, tempB); break;
+
+ case 0x1a:
+ case 0x1b:
+ case 0x1c:
+ case 0x1d:
+ case 0x1e:
+ case 0x1f: i860_dasm_CTRL_dasm(op, tempB); break; /* CTRL operation sub-group */
+
+ case 0x20:
+ case 0x21:
+ case 0x22:
+ case 0x23:
+ case 0x24:
+ case 0x25:
+ case 0x26:
+ case 0x27: i860_dasm_addu_subu(op, tempB); break;
+
+ case 0x28:
+ case 0x29:
+ case 0x2a:
+ case 0x2b: i860_dasm_shl_shr(op, tempB); break;
+
+ case 0x2c: i860_dasm_shrd(op, tempB); break;
+
+ case 0x2d: i860_dasm_bla(op, tempB); break;
+
+ case 0x2e:
+ case 0x2f: i860_dasm_shra(op, tempB); break;
+
+ case 0x30:
+ case 0x31:
+ case 0x32:
+ case 0x33: i860_dasm_and_andh(op, tempB); break;
+
+ case 0x34:
+ case 0x35:
+ case 0x36:
+ case 0x37: i860_dasm_andnot_andnoth(op, tempB); break;
+
+ case 0x38:
+ case 0x39:
+ case 0x3a:
+ case 0x3b: i860_dasm_or_orh(op, tempB); break;
+
+ case 0x3c:
+ case 0x3d:
+ case 0x3e:
+ case 0x3f: i860_dasm_xor_xorh(op, tempB); break;
+
+ default: sprintf(tempB, "(reserved)"); break;
+ }
+
+ /* More Debug */
+ //strcat(buffer, " : ");
+ //strcat(buffer, tempB);
+ sprintf(buffer, "%s", tempB);
+
+ /* All opcodes are 32 bits */
+ return (4 | DASMFLAG_SUPPORTED);
+}
+
+
+// BIT HELPER
+// 31 27 23 19 15 11 7 3
+// 0000 0011 1111 1111 0000 0111 1110 0000
+
+
+/**********************/
+/* Sub-group decoders */
+/**********************/
+static void i860_dasm_core_dasm(const UINT32 op, char* buffer)
+{
+ //UINT8 src1 = (op >> 11) & 0x0000001f;
+
+ /* Reserved bits must be set to 0 */
+ if ( (op & 0x000007e0) || (op & 0x03ff0000) )
+ {
+ //logerror("[i860] Reserved CORE bits must be set to 0.");
+ printf("CORE baddie\n");
+ }
+
+ switch(op & 0x0000001f)
+ {
+ case 0x01: i860_dasm_CORE_lock(op, buffer); break;
+ case 0x02: i860_dasm_CORE_calli(op, buffer); break;
+ case 0x04: i860_dasm_CORE_intovr(op, buffer); break;
+ case 0x07: i860_dasm_CORE_unlock(op, buffer); break;
+
+ default: sprintf(buffer, "(reserved)"); break;
+ }
+}
+
+static void i860_dasm_floating_point_dasm(const UINT32 op, char* buffer)
+{
+ sprintf(buffer, "[[F-P unit]]");
+}
+
+static void i860_dasm_CTRL_dasm(const UINT32 op, char* buffer)
+{
+ UINT8 opc = (op >> 26) & 0x07;
+
+ switch(opc)
+ {
+ case 0x02: i860_dasm_CTRL_br(op, buffer); break;
+ case 0x03: i860_dasm_CTRL_call(op, buffer); break;
+ case 0x04: case 0x05: i860_dasm_CTRL_bc_bct(op, buffer); break;
+ case 0x06: case 0x07: i860_dasm_CTRL_bnc_bnct(op, buffer); break;
+
+ default: sprintf(buffer, "(reserved)"); break;
+ }
+}
+
+
+/*********************/
+/* REG-Format Opcodes*/
+/*********************/
+static void i860_dasm_ldx(const UINT32 op, char* buffer)
+{
+ sprintf(buffer, "ldx");
+}
+
+static void i860_dasm_stx(const UINT32 op, char* buffer)
+{
+ sprintf(buffer, "stx");
+}
+
+static void i860_dasm_ixfr(const UINT32 op, char* buffer)
+{
+// UINT16 val = op & 0x7ff;
+// UINT8 opc = (op >> 26) & 0x3f;
+// UINT8 src2 = (op >> 21) & 0x1f;
+// UINT8 dest = (op >> 16) & 0x1f;
+// UINT8 src1 = (op >> 11) & 0x1f;
+
+ sprintf(buffer, "ixfr");
+}
+
+static void i860_dasm_fid_fst(const UINT32 op, char* buffer)
+{
+ sprintf(buffer, "fst");
+}
+
+static void i860_dasm_flush(const UINT32 op, char* buffer)
+{
+ sprintf(buffer, "flush");
+}
+
+static void i860_dasm_pstd(const UINT32 op, char* buffer)
+{
+ sprintf(buffer, "pstd");
+}
+
+static void i860_dasm_ldc_sdc(const UINT32 op, char* buffer)
+{
+ sprintf(buffer, "ldc, sdc");
+}
+
+static void i860_dasm_bri(const UINT32 op, char* buffer)
+{
+ sprintf(buffer, "bri");
+}
+
+static void i860_dasm_trap(const UINT32 op, char* buffer)
+{
+ sprintf(buffer, "trap");
+}
+
+static void i860_dasm_bte_btne(const UINT32 op, char* buffer)
+{
+ sprintf(buffer, "bte, btne");
+}
+
+static void i860_dasm_pfidy(const UINT32 op, char* buffer)
+{
+ sprintf(buffer, "pfidy");
+}
+
+static void i860_dasm_addu_subu(const UINT32 op, char* buffer)
+{
+ sprintf(buffer, "addu, subu");
+}
+
+static void i860_dasm_shl_shr(const UINT32 op, char* buffer)
+{
+ sprintf(buffer, "shl, shr");
+}
+
+static void i860_dasm_shrd(const UINT32 op, char* buffer)
+{
+ sprintf(buffer, "shrd");
+}
+
+static void i860_dasm_bla(const UINT32 op, char* buffer)
+{
+ sprintf(buffer, "bla");
+}
+
+static void i860_dasm_shra(const UINT32 op, char* buffer)
+{
+ sprintf(buffer, "shra");
+}
+
+static void i860_dasm_and_andh(const UINT32 op, char* buffer)
+{
+ sprintf(buffer, "and, andh");
+}
+
+static void i860_dasm_andnot_andnoth(const UINT32 op, char* buffer)
+{
+ sprintf(buffer, "andnot, andnoth");
+}
+
+static void i860_dasm_or_orh(const UINT32 op, char* buffer)
+{
+ sprintf(buffer, "or, orh");
+}
+
+static void i860_dasm_xor_xorh(const UINT32 op, char* buffer)
+{
+ sprintf(buffer, "xor, xorh");
+}
+
+
+/***********************/
+/* CORE Escape Opcodes */
+/***********************/
+static void i860_dasm_CORE_lock(const UINT32 op, char* buffer)
+{
+ sprintf(buffer, "lock");
+}
+
+static void i860_dasm_CORE_calli(const UINT32 op, char* buffer)
+{
+ sprintf(buffer, "calli");
+}
+
+static void i860_dasm_CORE_intovr(const UINT32 op, char* buffer)
+{
+ sprintf(buffer, "intovr");
+}
+
+static void i860_dasm_CORE_unlock(const UINT32 op, char* buffer)
+{
+ sprintf(buffer, "unlock");
+}
+
+
+/***********************/
+/* CTRL-Format Opcodes */
+/***********************/
+static void i860_dasm_CTRL_br(const UINT32 op, char* buffer)
+{
+ sprintf(buffer, "br");
+}
+
+static void i860_dasm_CTRL_call(const UINT32 op, char* buffer)
+{
+ sprintf(buffer, "call");
+}
+
+static void i860_dasm_CTRL_bc_bct(const UINT32 op, char* buffer)
+{
+ sprintf(buffer, "bct");
+}
+
+static void i860_dasm_CTRL_bnc_bnct(const UINT32 op, char* buffer)
+{
+ sprintf(buffer, "bnct");
+}
+
+
+/*******************************/
+/* Floating-Point Instructions */
+/*******************************/
+
diff --git a/trunk/src/emu/cpu/i860/i860dec.c b/trunk/src/emu/cpu/i860/i860dec.c
new file mode 100644
index 00000000000..4277eecda8a
--- /dev/null
+++ b/trunk/src/emu/cpu/i860/i860dec.c
@@ -0,0 +1,4718 @@
+/***************************************************************************
+
+ i860dec.c
+
+ Execution engine for the Intel i860 emulator.
+
+ Copyright (C) 1995-present Jason Eckhardt (jle@rice.edu)
+ Released for general non-commercial use under the MAME license
+ with the additional requirement that you are free to use and
+ redistribute this code in modified or unmodified form, provided
+ you list me in the credits.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+/*
+ * References:
+ * `i860 Microprocessor Programmer's Reference Manual', Intel, 1990.
+ *
+ * This code was originally written by Jason Eckhardt as part of an
+ * emulator for some i860-based Unix workstations (early 1990's) such
+ * as the Stardent Vistra 800 series and the OkiStation/i860 7300 series.
+ * The code you are reading now is the i860 CPU portion only, which has
+ * been adapted to (and simplified for) MAME.
+ * MAME-specific notes:
+ * - i860XR emulation only (i860XP unnecessary for MAME).
+ * - No emulation of data and instruction caches (unnecessary for MAME version).
+ * - No emulation of DIM mode or CS8 mode (unnecessary for MAME version).
+ * - No BL/IL/locked sequences (unnecessary for MAME).
+ * - Emulate only the i860's LSB-first mode (BE = 0).
+ * Generic notes:
+ * - There is some amount of code duplication (e.g., see the
+ * various insn_* routines for the branches and FP routines) that
+ * could be eliminated.
+ * - The host's floating point types are used to emulate the i860's
+ * floating point. Should probably be made machine independent by
+ * using an IEEE FP emulation library. On the other hand, most machines
+ * today also use IEEE FP.
+ *
+ */
+#include "i860.h"
+#include <math.h>
+
+
+#undef HOST_MSB
+
+#undef TRACE_RDWR_MEM
+#undef TRACE_ADDR_TRANSLATION
+#undef TRACE_PAGE_FAULT
+#define TRACE_UNDEFINED_I860
+#undef TRACE_EXT_INT
+#define TRACE_UNALIGNED_MEM
+
+
+
+#define i860s i860_state_t
+
+
+/* Prototypes. */
+static void decode_exec (i860s *, UINT32, UINT32);
+static UINT32 get_address_translation (i860s *, UINT32, int, int);
+static UINT32 readmemi_emu (i860s *cpustate, UINT32, int);
+
+//static void debugger (i860s *cpustate);
+//static void disasm (i860s *cpustate, UINT32, int);
+//static void dump_state (i860s *cpustate);
+
+
+
+
+/* Defines for pending_trap. */
+enum {
+ TRAP_NORMAL = 0x01,
+ TRAP_IN_DELAY_SLOT = 0x02,
+ TRAP_WAS_EXTERNAL = 0x04
+};
+
+
+
+
+/* Get/set general register value -- watch for r0 on writes. */
+#define get_iregval(gr) (cpustate->iregs[(gr)])
+#define set_iregval(gr, val) (cpustate->iregs[(gr)] = ((gr) == 0 ? 0 : (val)))
+
+INLINE float get_fregval_s (i860s *cpustate, int fr)
+{
+ float f;
+ UINT32 x;
+ UINT8 *tp;
+ fr = 31 - fr;
+ tp = (UINT8 *)(&cpustate->frg[fr * 4]);
+ x = ((UINT32)tp[0] << 24) | ((UINT32)tp[1] << 16) |
+ ((UINT32)tp[2] << 8) | ((UINT32)tp[3]);
+ f = *(float *)(&x);
+ return f;
+}
+
+INLINE double get_fregval_d (i860s *cpustate, int fr)
+{
+ double d;
+ UINT64 x;
+ UINT8 *tp;
+ fr = 31 - (fr + 1);
+ tp = (UINT8 *)(&cpustate->frg[fr * 4]);
+ x = ((UINT64)tp[0] << 56) | ((UINT64)tp[1] << 48) |
+ ((UINT64)tp[2] << 40) | ((UINT64)tp[3] << 32) |
+ ((UINT64)tp[4] << 24) | ((UINT64)tp[5] << 16) |
+ ((UINT64)tp[6] << 8) | ((UINT64)tp[7]);
+ d = *(double *)(&x);
+ return d;
+}
+
+INLINE void set_fregval_s (i860s *cpustate, int fr, float s)
+{
+ UINT8 *f = (UINT8 *)&s;
+ UINT8 *tp;
+ int newfr = 31 - fr;
+ float jj = s;
+ tp = (UINT8 *)(&cpustate->frg[newfr * 4]);
+
+ f = (UINT8 *)(&jj);
+ if (fr == 0 || fr == 1)
+ {
+ tp[0] = 0; tp[1] = 0; tp[2] = 0; tp[3] = 0;
+ }
+ else
+ {
+#ifndef HOST_MSB
+ tp[0] = f[3]; tp[1] = f[2]; tp[2] = f[1]; tp[3] = f[0];
+#else
+ tp[0] = f[0]; tp[1] = f[1]; tp[2] = f[2]; tp[3] = f[3];
+#endif
+ }
+}
+
+INLINE void set_fregval_d (i860s *cpustate, int fr, double d)
+{
+ UINT8 *f = (UINT8 *)&d;
+ UINT8 *tp;
+ int newfr = 31 - (fr + 1);
+ double jj = d;
+ tp = (UINT8 *)(&cpustate->frg[newfr * 4]);
+
+ f = (UINT8 *)(&jj);
+
+ if (fr == 0)
+ {
+ tp[0] = 0; tp[1] = 0; tp[2] = 0; tp[3] = 0;
+ tp[4] = 0; tp[5] = 0; tp[6] = 0; tp[7] = 0;
+ }
+ else
+ {
+#ifndef HOST_MSB
+ tp[0] = f[7]; tp[1] = f[6]; tp[2] = f[5]; tp[3] = f[4];
+ tp[4] = f[3]; tp[5] = f[2]; tp[6] = f[1]; tp[7] = f[0];
+#else
+ tp[0] = f[0]; tp[1] = f[1]; tp[2] = f[2]; tp[3] = f[3];
+ tp[4] = f[4]; tp[5] = f[5]; tp[6] = f[6]; tp[7] = f[7];
+#endif
+ }
+}
+
+
+/* Macros for accessing register fields in instruction word. */
+#define get_isrc1(bits) (((bits) >> 11) & 0x1f)
+#define get_isrc2(bits) (((bits) >> 21) & 0x1f)
+#define get_idest(bits) (((bits) >> 16) & 0x1f)
+#define get_fsrc1(bits) (((bits) >> 11) & 0x1f)
+#define get_fsrc2(bits) (((bits) >> 21) & 0x1f)
+#define get_fdest(bits) (((bits) >> 16) & 0x1f)
+#define get_creg(bits) (((bits) >> 21) & 0x7)
+
+/* Macros for accessing immediate fields. */
+/* 16-bit immediate. */
+#define get_imm16(insn) ((insn) & 0xffff)
+
+/* Control register numbers. */
+enum {
+ CR_FIR = 0,
+ CR_PSR = 1,
+ CR_DIRBASE = 2,
+ CR_DB = 3,
+ CR_FSR = 4,
+ CR_EPSR = 5
+};
+
+/* A mask for all the trap bits of the PSR (FT, DAT, IAT, IN, IT, or
+ bits [12..8]). */
+#define PSR_ALL_TRAP_BITS_MASK 0x00001f00
+
+/* A mask for PSR bits which can only be changed from supervisor level. */
+#define PSR_SUPERVISOR_ONLY_MASK 0x0000fff3
+
+
+/* PSR: BR flag (PSR[0]): set/get. */
+#define GET_PSR_BR() ((cpustate->cregs[CR_PSR] >> 0) & 1)
+#define SET_PSR_BR(val) (cpustate->cregs[CR_PSR] = (cpustate->cregs[CR_PSR] & ~(1 << 0)) | (((val) & 1) << 0))
+
+/* PSR: BW flag (PSR[1]): set/get. */
+#define GET_PSR_BW() ((cpustate->cregs[CR_PSR] >> 1) & 1)
+#define SET_PSR_BW(val) (cpustate->cregs[CR_PSR] = (cpustate->cregs[CR_PSR] & ~(1 << 1)) | (((val) & 1) << 1))
+
+/* PSR: Shift count (PSR[21..17]): set/get. */
+#define GET_PSR_SC() ((cpustate->cregs[CR_PSR] >> 17) & 0x1f)
+#define SET_PSR_SC(val) (cpustate->cregs[CR_PSR] = (cpustate->cregs[CR_PSR] & ~0x003e0000) | (((val) & 0x1f) << 17))
+
+/* PSR: CC flag (PSR[2]): set/get. */
+#define GET_PSR_CC() ((cpustate->cregs[CR_PSR] >> 2) & 1)
+#define SET_PSR_CC(val) (cpustate->cregs[CR_PSR] = (cpustate->cregs[CR_PSR] & ~(1 << 2)) | (((val) & 1) << 2))
+
+/* PSR: IT flag (PSR[8]): set/get. */
+#define GET_PSR_IT() ((cpustate->cregs[CR_PSR] >> 8) & 1)
+#define SET_PSR_IT(val) (cpustate->cregs[CR_PSR] = (cpustate->cregs[CR_PSR] & ~(1 << 8)) | (((val) & 1) << 8))
+
+/* PSR: IN flag (PSR[9]): set/get. */
+#define GET_PSR_IN() ((cpustate->cregs[CR_PSR] >> 9) & 1)
+#define SET_PSR_IN(val) (cpustate->cregs[CR_PSR] = (cpustate->cregs[CR_PSR] & ~(1 << 9)) | (((val) & 1) << 9))
+
+/* PSR: IAT flag (PSR[10]): set/get. */
+#define GET_PSR_IAT() ((cpustate->cregs[CR_PSR] >> 10) & 1)
+#define SET_PSR_IAT(val) (cpustate->cregs[CR_PSR] = (cpustate->cregs[CR_PSR] & ~(1 << 10)) | (((val) & 1) << 10))
+
+/* PSR: DAT flag (PSR[11]): set/get. */
+#define GET_PSR_DAT() ((cpustate->cregs[CR_PSR] >> 11) & 1)
+#define SET_PSR_DAT(val) (cpustate->cregs[CR_PSR] = (cpustate->cregs[CR_PSR] & ~(1 << 11)) | (((val) & 1) << 11))
+
+/* PSR: FT flag (PSR[12]): set/get. */
+#define GET_PSR_FT() ((cpustate->cregs[CR_PSR] >> 12) & 1)
+#define SET_PSR_FT(val) (cpustate->cregs[CR_PSR] = (cpustate->cregs[CR_PSR] & ~(1 << 12)) | (((val) & 1) << 12))
+
+/* PSR: DS flag (PSR[13]): set/get. */
+#define GET_PSR_DS() ((cpustate->cregs[CR_PSR] >> 13) & 1)
+#define SET_PSR_DS(val) (cpustate->cregs[CR_PSR] = (cpustate->cregs[CR_PSR] & ~(1 << 13)) | (((val) & 1) << 13))
+
+/* PSR: DIM flag (PSR[14]): set/get. */
+#define GET_PSR_DIM() ((cpustate->cregs[CR_PSR] >> 14) & 1)
+#define SET_PSR_DIM(val) (cpustate->cregs[CR_PSR] = (cpustate->cregs[CR_PSR] & ~(1 << 14)) | (((val) & 1) << 14))
+
+/* PSR: LCC (PSR[3]): set/get. */
+#define GET_PSR_LCC() ((cpustate->cregs[CR_PSR] >> 3) & 1)
+#define SET_PSR_LCC(val) (cpustate->cregs[CR_PSR] = (cpustate->cregs[CR_PSR] & ~(1 << 3)) | (((val) & 1) << 3))
+
+/* PSR: IM (PSR[4]): set/get. */
+#define GET_PSR_IM() ((cpustate->cregs[CR_PSR] >> 4) & 1)
+#define SET_PSR_IM(val) (cpustate->cregs[CR_PSR] = (cpustate->cregs[CR_PSR] & ~(1 << 4)) | (((val) & 1) << 4))
+
+/* PSR: PIM (PSR[5]): set/get. */
+#define GET_PSR_PIM() ((cpustate->cregs[CR_PSR] >> 5) & 1)
+#define SET_PSR_PIM(val) (cpustate->cregs[CR_PSR] = (cpustate->cregs[CR_PSR] & ~(1 << 5)) | (((val) & 1) << 5))
+
+/* PSR: U (PSR[6]): set/get. */
+#define GET_PSR_U() ((cpustate->cregs[CR_PSR] >> 6) & 1)
+#define SET_PSR_U(val) (cpustate->cregs[CR_PSR] = (cpustate->cregs[CR_PSR] & ~(1 << 6)) | (((val) & 1) << 6))
+
+/* PSR: PU (PSR[7]): set/get. */
+#define GET_PSR_PU() ((cpustate->cregs[CR_PSR] >> 7) & 1)
+#define SET_PSR_PU(val) (cpustate->cregs[CR_PSR] = (cpustate->cregs[CR_PSR] & ~(1 << 7)) | (((val) & 1) << 7))
+
+/* PSR: Pixel size (PSR[23..22]): set/get. */
+#define GET_PSR_PS() ((cpustate->cregs[CR_PSR] >> 22) & 0x3)
+#define SET_PSR_PS(val) (cpustate->cregs[CR_PSR] = (cpustate->cregs[CR_PSR] & ~0x00c00000) | (((val) & 0x3) << 22))
+
+/* PSR: Pixel mask (PSR[31..24]): set/get. */
+#define GET_PSR_PM() ((cpustate->cregs[CR_PSR] >> 24) & 0xff)
+#define SET_PSR_PM(val) (cpustate->cregs[CR_PSR] = (cpustate->cregs[CR_PSR] & ~0xff000000) | (((val) & 0xff) << 24))
+
+/* EPSR: WP bit (EPSR[14]): set/get. */
+#define GET_EPSR_WP() ((cpustate->cregs[CR_EPSR] >> 14) & 1)
+#define SET_EPSR_WP(val) (cpustate->cregs[CR_EPSR] = (cpustate->cregs[CR_EPSR] & ~(1 << 14)) | (((val) & 1) << 14))
+
+/* EPSR: INT bit (EPSR[17]): set/get. */
+#define GET_EPSR_INT() ((cpustate->cregs[CR_EPSR] >> 17) & 1)
+#define SET_EPSR_INT(val) (cpustate->cregs[CR_EPSR] = (cpustate->cregs[CR_EPSR] & ~(1 << 17)) | (((val) & 1) << 17))
+
+
+/* EPSR: OF flag (EPSR[24]): set/get. */
+#define GET_EPSR_OF() ((cpustate->cregs[CR_EPSR] >> 24) & 1)
+#define SET_EPSR_OF(val) (cpustate->cregs[CR_EPSR] = (cpustate->cregs[CR_EPSR] & ~(1 << 24)) | (((val) & 1) << 24))
+
+/* EPSR: BE flag (EPSR[23]): set/get. */
+#define GET_EPSR_BE() ((cpustate->cregs[CR_EPSR] >> 23) & 1)
+#define SET_EPSR_BE(val) (cpustate->cregs[CR_EPSR] = (cpustate->cregs[CR_EPSR] & ~(1 << 23)) | (((val) & 1) << 23))
+
+/* DIRBASE: ATE bit (DIRBASE[0]): get. */
+#define GET_DIRBASE_ATE() (cpustate->cregs[CR_DIRBASE] & 1)
+
+/* DIRBASE: CS8 bit (DIRBASE[7]): get. */
+#define GET_DIRBASE_CS8() ((cpustate->cregs[CR_DIRBASE] >> 7) & 1)
+
+/* FSR: FTE bit (FSR[5]): set/get. */
+#define GET_FSR_FTE() ((cpustate->cregs[CR_FSR] >> 5) & 1)
+#define SET_FSR_FTE(val) (cpustate->cregs[CR_FSR] = (cpustate->cregs[CR_FSR] & ~(1 << 5)) | (((val) & 1) << 5))
+
+/* FSR: SE bit (FSR[8]): set/get. */
+#define GET_FSR_SE() ((cpustate->cregs[CR_FSR] >> 8) & 1)
+#define SET_FSR_SE(val) (cpustate->cregs[CR_FSR] = (cpustate->cregs[CR_FSR] & ~(1 << 8)) | (((val) & 1) << 8))
+
+
+/*
+static int has_delay_slot(UINT32 insn)
+{
+ int opc = (insn >> 26) & 0x3f;
+ if (opc == 0x10 || opc == 0x1a || opc == 0x1b || opc == 0x1d ||
+ opc == 0x1f || opc == 0x2d || (opc == 0x13 && (insn & 3) == 2))
+ return 1;
+ return 0;
+}
+*/
+
+/* This is the external interface for asserting/deasserting pins on
+ the i860. */
+void i860_set_pin (device_t *device, int pin, int val)
+{
+ i860s *cpustate = get_safe_token(device);
+ if (pin == DEC_PIN_BUS_HOLD)
+ cpustate->pin_bus_hold = val;
+ else if (pin == DEC_PIN_RESET)
+ cpustate->pin_reset = val;
+ else
+ assert (0);
+}
+
+
+/* This is the external interface for indicating an external interrupt
+ to the i860. */
+void i860_gen_interrupt (i860s *cpustate)
+{
+ /* If interrupts are enabled, then set PSR.IN and prepare for trap.
+ Otherwise, the external interrupt is ignored. We also set
+ bit EPSR.INT (which tracks the INT pin). */
+ if (GET_PSR_IM ())
+ {
+ SET_PSR_IN (1);
+ SET_EPSR_INT (1);
+ cpustate->pending_trap = TRAP_WAS_EXTERNAL;
+ }
+
+#ifdef TRACE_EXT_INT
+ fprintf (stderr, "i860_gen_interrupt: External interrupt received ");
+ if (GET_PSR_IM ())
+ fprintf (stderr, "[PSR.IN set, preparing to trap]\n");
+ else
+ fprintf (stderr, "[ignored (interrupts disabled)]\n");
+#endif
+}
+
+
+/* Fetch instructions from instruction cache.
+ Note: The instruction cache is not implemented for MAME version,
+ this just fetches and returns 1 instruction from memory. */
+static UINT32 ifetch (i860s *cpustate, UINT32 pc)
+{
+ UINT32 phys_pc = 0;
+ UINT32 w1 = 0;
+
+ /* If virtual mode, get translation. */
+ if (GET_DIRBASE_ATE ())
+ {
+ phys_pc = get_address_translation (cpustate, pc, 0 /* is_dataref */, 0 /* is_write */);
+ cpustate->exiting_ifetch = 0;
+ if (cpustate->pending_trap && (GET_PSR_DAT () || GET_PSR_IAT ()))
+ {
+ cpustate->exiting_ifetch = 1;
+ return 0xffeeffee;
+ }
+ }
+ else
+ phys_pc = pc;
+
+ /* Since i860 instructions are always stored LSB first (regardless of
+ the BE bit), we need to adjust the instruction below on MSB hosts. */
+ w1 = cpustate->program->read_dword(phys_pc);
+#ifdef HOST_MSB
+ BYTE_REV32 (w1);
+#endif /* HOST_MSB. */
+ return w1;
+}
+
+
+/* Given a virtual address, perform the i860 address translation and
+ return the corresponding physical address.
+ vaddr: virtual address
+ is_dataref: 1 = load/store, 0 = instruction fetch.
+ is_write: 1 = writing to vaddr, 0 = reading from vaddr
+ The last two arguments are only used to determine what types
+ of traps should be taken.
+
+ Page tables must always be in memory (not cached). So the routine
+ here only accesses memory. */
+static UINT32 get_address_translation (i860s *cpustate, UINT32 vaddr, int is_dataref, int is_write)
+{
+ UINT32 vdir = (vaddr >> 22) & 0x3ff;
+ UINT32 vpage = (vaddr >> 12) & 0x3ff;
+ UINT32 voffset = vaddr & 0xfff;
+ UINT32 dtb = (cpustate->cregs[CR_DIRBASE]) & 0xfffff000;
+ UINT32 pg_dir_entry_a = 0;
+ UINT32 pg_dir_entry = 0;
+ UINT32 pg_tbl_entry_a = 0;
+ UINT32 pg_tbl_entry = 0;
+ UINT32 pfa1 = 0;
+ UINT32 pfa2 = 0;
+ UINT32 ret = 0;
+ UINT32 ttpde = 0;
+ UINT32 ttpte = 0;
+
+ assert (GET_DIRBASE_ATE ());
+
+ /* Get page directory entry at DTB:DIR:00. */
+ pg_dir_entry_a = dtb | (vdir << 2);
+ pg_dir_entry = cpustate->program->read_dword(pg_dir_entry_a);
+#ifdef HOST_MSB
+ BYTE_REV32 (pg_dir_entry);
+#endif
+
+ /* Check for non-present PDE. */
+ if (!(pg_dir_entry & 1))
+ {
+ /* PDE is not present, generate DAT or IAT. */
+ if (is_dataref)
+ SET_PSR_DAT (1);
+ else
+ SET_PSR_IAT (1);
+ cpustate->pending_trap = 1;
+
+ /* Dummy return. */
+ return 0;
+ }
+
+ /* PDE Check for write protection violations. */
+ if (is_write && is_dataref
+ && !(pg_dir_entry & 2) /* W = 0. */
+ && (GET_PSR_U () || GET_EPSR_WP ())) /* PSR_U = 1 or EPSR_WP = 1. */
+ {
+ SET_PSR_DAT (1);
+ cpustate->pending_trap = 1;
+ /* Dummy return. */
+ return 0;
+ }
+
+ /* PDE Check for user-mode access to supervisor pages. */
+ if (GET_PSR_U ()
+ && !(pg_dir_entry & 4)) /* U = 0. */
+ {
+ if (is_dataref)
+ SET_PSR_DAT (1);
+ else
+ SET_PSR_IAT (1);
+ cpustate->pending_trap = 1;
+ /* Dummy return. */
+ return 0;
+ }
+
+ /* FIXME: How exactly to handle A check/update?. */
+
+ /* Get page table entry at PFA1:PAGE:00. */
+ pfa1 = pg_dir_entry & 0xfffff000;
+ pg_tbl_entry_a = pfa1 | (vpage << 2);
+ pg_tbl_entry = cpustate->program->read_dword(pg_tbl_entry_a);
+#ifdef HOST_MSB
+ BYTE_REV32 (pg_tbl_entry);
+#endif
+
+ /* Check for non-present PTE. */
+ if (!(pg_tbl_entry & 1))
+ {
+ /* PTE is not present, generate DAT or IAT. */
+ if (is_dataref)
+ SET_PSR_DAT (1);
+ else
+ SET_PSR_IAT (1);
+ cpustate->pending_trap = 1;
+
+ /* Dummy return. */
+ return 0;
+ }
+
+ /* PTE Check for write protection violations. */
+ if (is_write && is_dataref
+ && !(pg_tbl_entry & 2) /* W = 0. */
+ && (GET_PSR_U () || GET_EPSR_WP ())) /* PSR_U = 1 or EPSR_WP = 1. */
+ {
+ SET_PSR_DAT (1);
+ cpustate->pending_trap = 1;
+ /* Dummy return. */
+ return 0;
+ }
+
+ /* PTE Check for user-mode access to supervisor pages. */
+ if (GET_PSR_U ()
+ && !(pg_tbl_entry & 4)) /* U = 0. */
+ {
+ if (is_dataref)
+ SET_PSR_DAT (1);
+ else
+ SET_PSR_IAT (1);
+ cpustate->pending_trap = 1;
+ /* Dummy return. */
+ return 0;
+ }
+
+ /* Update A bit and check D bit. */
+ ttpde = pg_dir_entry | 0x20;
+ ttpte = pg_tbl_entry | 0x20;
+#ifdef HOST_MSB
+ BYTE_REV32 (ttpde);
+ BYTE_REV32 (ttpte);
+#endif
+ cpustate->program->write_dword(pg_dir_entry_a, ttpde);
+ cpustate->program->write_dword(pg_tbl_entry_a, ttpte);
+
+ if (is_write && is_dataref && (pg_tbl_entry & 0x40) == 0)
+ {
+ /* fprintf(stderr, "DAT trap on write without dirty bit v0x%08x/p0x%08x\n",
+ vaddr, (pg_tbl_entry & ~0xfff)|voffset); */
+ SET_PSR_DAT (1);
+ cpustate->pending_trap = 1;
+ /* Dummy return. */
+ return 0;
+ }
+
+ pfa2 = (pg_tbl_entry & 0xfffff000);
+ ret = pfa2 | voffset;
+
+#ifdef TRACE_ADDR_TRANSLATION
+ fprintf (stderr, "get_address_translation: virt(0x%08x) -> phys(0x%08x)\n",
+ vaddr, ret);
+#endif
+
+ return ret;
+}
+
+
+/* Read memory emulation.
+ addr = address to read.
+ size = size of read in bytes. */
+static UINT32 readmemi_emu (i860s *cpustate, UINT32 addr, int size)
+{
+#ifdef TRACE_RDWR_MEM
+ fprintf (stderr, "readmemi_emu: (ATE=%d) addr = 0x%08x, size = %d\n",
+ GET_DIRBASE_ATE (), addr, size);
+#endif
+
+ /* If virtual mode, do translation. */
+ if (GET_DIRBASE_ATE ())
+ {
+ UINT32 phys = get_address_translation (cpustate, addr, 1 /* is_dataref */, 0 /* is_write */);
+ if (cpustate->pending_trap && (GET_PSR_IAT () || GET_PSR_DAT ()))
+ {
+#ifdef TRACE_PAGE_FAULT
+ fprintf (stderr, "0x%08x: ## Page fault (readmemi_emu).\n",
+ cpustate->pc);
+#endif
+ cpustate->exiting_readmem = 1;
+ return 0;
+ }
+ addr = phys;
+ }
+
+ /* First check for match to db register (before read). */
+ if (((addr & ~(size - 1)) == cpustate->cregs[CR_DB]) && GET_PSR_BR ())
+ {
+ SET_PSR_DAT (1);
+ cpustate->pending_trap = 1;
+ return 0;
+ }
+
+ /* Now do the actual read. */
+ if (size == 1)
+ {
+ UINT32 ret = cpustate->program->read_byte(addr);
+ return ret & 0xff;
+ }
+ else if (size == 2)
+ {
+ UINT32 ret = cpustate->program->read_word(addr);
+#ifdef HOST_MSB
+ BYTE_REV16 (ret);
+#endif
+ return ret & 0xffff;
+ }
+ else if (size == 4)
+ {
+ UINT32 ret = cpustate->program->read_dword(addr);
+#ifdef HOST_MSB
+ BYTE_REV32 (ret);
+#endif
+ return ret;
+ }
+ else
+ assert (0);
+
+ return 0;
+}
+
+
+/* Write memory emulation.
+ addr = address to write.
+ size = size of write in bytes.
+ data = data to write. */
+static void writememi_emu (i860s *cpustate, UINT32 addr, int size, UINT32 data)
+{
+#ifdef TRACE_RDWR_MEM
+ fprintf (stderr, "writememi_emu: (ATE=%d) addr = 0x%08x, size = %d, data = 0x%08x\n",
+ GET_DIRBASE_ATE (), addr, size, data);
+#endif
+
+ /* If virtual mode, do translation. */
+ if (GET_DIRBASE_ATE ())
+ {
+ UINT32 phys = get_address_translation (cpustate, addr, 1 /* is_dataref */, 1 /* is_write */);
+ if (cpustate->pending_trap && (GET_PSR_IAT () || GET_PSR_DAT ()))
+ {
+#ifdef TRACE_PAGE_FAULT
+ fprintf (stderr, "0x%08x: ## Page fault (writememi_emu).\n",
+ cpustate->pc);
+#endif
+ cpustate->exiting_readmem = 2;
+ return;
+ }
+ addr = phys;
+ }
+
+ /* First check for match to db register (before write). */
+ if (((addr & ~(size - 1)) == cpustate->cregs[CR_DB]) && GET_PSR_BW ())
+ {
+ SET_PSR_DAT (1);
+ cpustate->pending_trap = 1;
+ return;
+ }
+
+ /* Now do the actual write. */
+ if (size == 1)
+ cpustate->program->write_byte(addr, data);
+ else if (size == 2)
+ {
+#ifdef HOST_MSB
+ BYTE_REV16 (data);
+#endif
+ cpustate->program->write_word(addr, data);
+ }
+ else if (size == 4)
+ {
+#ifdef HOST_MSB
+ BYTE_REV32 (data);
+#endif
+ cpustate->program->write_dword(addr, data);
+ }
+ else
+ assert (0);
+}
+
+
+/* Floating-point read mem routine.
+ addr = address to read.
+ size = size of read in bytes.
+ dest = memory to put read data. */
+static void fp_readmem_emu (i860s *cpustate, UINT32 addr, int size, UINT8 *dest)
+{
+#ifdef TRACE_RDWR_MEM
+ fprintf (stderr, "fp_readmem_emu: (ATE=%d) addr = 0x%08x, size = %d\n",
+ GET_DIRBASE_ATE (), addr, size);
+#endif
+
+ assert (size == 4 || size == 8 || size == 16);
+
+ /* If virtual mode, do translation. */
+ if (GET_DIRBASE_ATE ())
+ {
+ UINT32 phys = get_address_translation (cpustate, addr, 1 /* is_dataref */, 0 /* is_write */);
+ if (cpustate->pending_trap && (GET_PSR_IAT () || GET_PSR_DAT ()))
+ {
+#ifdef TRACE_PAGE_FAULT
+ fprintf (stderr, "0x%08x: ## Page fault (fp_readmem_emu).\n",
+ cpustate->pc);
+#endif
+ cpustate->exiting_readmem = 3;
+ return;
+ }
+ addr = phys;
+ }
+
+ /* First check for match to db register (before read). */
+ if (((addr & ~(size - 1)) == cpustate->cregs[CR_DB]) && GET_PSR_BR ())
+ {
+ SET_PSR_DAT (1);
+ cpustate->pending_trap = 1;
+ return;
+ }
+
+ if (size == 4)
+ {
+ dest[0] = cpustate->program->read_byte(addr+3);
+ dest[1] = cpustate->program->read_byte(addr+2);
+ dest[2] = cpustate->program->read_byte(addr+1);
+ dest[3] = cpustate->program->read_byte(addr+0);
+ }
+ else if (size == 8)
+ {
+ dest[0] = cpustate->program->read_byte(addr+7);
+ dest[1] = cpustate->program->read_byte(addr+6);
+ dest[2] = cpustate->program->read_byte(addr+5);
+ dest[3] = cpustate->program->read_byte(addr+4);
+ dest[4] = cpustate->program->read_byte(addr+3);
+ dest[5] = cpustate->program->read_byte(addr+2);
+ dest[6] = cpustate->program->read_byte(addr+1);
+ dest[7] = cpustate->program->read_byte(addr+0);
+ }
+ else if (size == 16)
+ {
+ int i;
+ for (i = 0; i < 16; i++)
+ {
+ dest[i] = cpustate->program->read_byte(addr+15-i);
+ }
+ }
+}
+
+
+/* Floating-point write mem routine.
+ addr = address to read.
+ size = size of read in bytes.
+ data = pointer to the data.
+ wmask = bit mask of bytes to write (only for pst.d). */
+static void fp_writemem_emu (i860s *cpustate, UINT32 addr, int size, UINT8 *data, UINT32 wmask)
+{
+#ifdef TRACE_RDWR_MEM
+ fprintf (stderr, "fp_writemem_emu: (ATE=%d) addr = 0x%08x, size = %d\n",
+ GET_DIRBASE_ATE (), addr, size);
+#endif
+
+ assert (size == 4 || size == 8 || size == 16);
+
+ /* If virtual mode, do translation. */
+ if (GET_DIRBASE_ATE ())
+ {
+ UINT32 phys = get_address_translation (cpustate, addr, 1 /* is_dataref */, 1 /* is_write */);
+ if (cpustate->pending_trap && GET_PSR_DAT ())
+ {
+#ifdef TRACE_PAGE_FAULT
+ fprintf (stderr, "0x%08x: ## Page fault (fp_writememi_emu).\n",
+ cpustate->pc);
+#endif
+ cpustate->exiting_readmem = 4;
+ return;
+ }
+ addr = phys;
+ }
+
+ /* First check for match to db register (before read). */
+ if (((addr & ~(size - 1)) == cpustate->cregs[CR_DB]) && GET_PSR_BW ())
+ {
+ SET_PSR_DAT (1);
+ cpustate->pending_trap = 1;
+ return;
+ }
+
+ if (size == 4)
+ {
+#if 1
+ cpustate->program->write_byte(addr+3, data[0]);
+ cpustate->program->write_byte(addr+2, data[1]);
+ cpustate->program->write_byte(addr+1, data[2]);
+ cpustate->program->write_byte(addr+0, data[3]);
+#else
+ UINT32 ddd = (data[3]) | (data[2] << 8) | (data[1] << 16) |(data[0] << 24);
+ cpustate->program->write_dword(addr+0, ddd);
+#endif
+ }
+ else if (size == 8)
+ {
+ /* Special: watch for wmask != 0xff, which means we're doing pst.d. */
+ if (wmask == 0xff)
+ {
+ cpustate->program->write_byte(addr+7, data[0]);
+ cpustate->program->write_byte(addr+6, data[1]);
+ cpustate->program->write_byte(addr+5, data[2]);
+ cpustate->program->write_byte(addr+4, data[3]);
+ cpustate->program->write_byte(addr+3, data[4]);
+ cpustate->program->write_byte(addr+2, data[5]);
+ cpustate->program->write_byte(addr+1, data[6]);
+ cpustate->program->write_byte(addr+0, data[7]);
+ }
+ else
+ {
+ if (wmask & 0x80) cpustate->program->write_byte(addr+7, data[0]);
+ if (wmask & 0x40) cpustate->program->write_byte(addr+6, data[1]);
+ if (wmask & 0x20) cpustate->program->write_byte(addr+5, data[2]);
+ if (wmask & 0x10) cpustate->program->write_byte(addr+4, data[3]);
+ if (wmask & 0x08) cpustate->program->write_byte(addr+3, data[4]);
+ if (wmask & 0x04) cpustate->program->write_byte(addr+2, data[5]);
+ if (wmask & 0x02) cpustate->program->write_byte(addr+1, data[6]);
+ if (wmask & 0x01) cpustate->program->write_byte(addr+0, data[7]);
+ }
+ }
+ else if (size == 16)
+ {
+ int i;
+ for (i = 0; i < 16; i++)
+ {
+ cpustate->program->write_byte(addr+15-i, data[i]);
+ }
+ }
+
+}
+
+
+#if 0
+/* Do a pipeline dump.
+ type: 0 (all), 1 (add), 2 (mul), 3 (load), 4 (graphics). */
+static void dump_pipe (i860s *cpustate, int type)
+{
+ int i = 0;
+
+ fprintf (stderr, "pipeline state:\n");
+ /* Dump the adder pipeline, if requested. */
+ if (type == 0 || type == 1)
+ {
+ fprintf (stderr, " A: ");
+ for (i = 0; i < 3; i++)
+ {
+ if (cpustate->A[i].stat.arp)
+ fprintf (stderr, "[%dd] 0x%016llx ", i + 1,
+ *(UINT64 *)(&cpustate->A[i].val.d));
+ else
+ fprintf (stderr, "[%ds] 0x%08x ", i + 1,
+ *(UINT32 *)(&cpustate->A[i].val.s));
+ }
+ fprintf (stderr, "\n");
+ }
+
+
+ /* Dump the multiplier pipeline, if requested. */
+ if (type == 0 || type == 2)
+ {
+ fprintf (stderr, " M: ");
+ for (i = 0; i < 3; i++)
+ {
+ if (cpustate->M[i].stat.mrp)
+ fprintf (stderr, "[%dd] 0x%016llx ", i + 1,
+ *(UINT64 *)(&cpustate->M[i].val.d));
+ else
+ fprintf (stderr, "[%ds] 0x%08x ", i + 1,
+ *(UINT32 *)(&cpustate->M[i].val.s));
+ }
+ fprintf (stderr, "\n");
+ }
+
+ /* Dump the load pipeline, if requested. */
+ if (type == 0 || type == 3)
+ {
+ fprintf (stderr, " L: ");
+ for (i = 0; i < 3; i++)
+ {
+ if (cpustate->L[i].stat.lrp)
+ fprintf (stderr, "[%dd] 0x%016llx ", i + 1,
+ *(UINT64 *)(&cpustate->L[i].val.d));
+ else
+ fprintf (stderr, "[%ds] 0x%08x ", i + 1,
+ *(UINT32 *)(&cpustate->L[i].val.s));
+ }
+ fprintf (stderr, "\n");
+ }
+
+ /* Dump the graphics pipeline, if requested. */
+ if (type == 0 || type == 4)
+ {
+ fprintf (stderr, " I: ");
+ if (cpustate->G.stat.irp)
+ fprintf (stderr, "[1d] 0x%016llx\n",
+ *(UINT64 *)(&cpustate->G.val.d));
+ else
+ fprintf (stderr, "[1s] 0x%08x\n",
+ *(UINT32 *)(&cpustate->G.val.s));
+ }
+}
+
+
+/* Do a register/state dump. */
+static void dump_state (i860s *cpustate)
+{
+ int rn;
+
+ /* GR's first, 4 per line. */
+ for (rn = 0; rn < 32; rn++)
+ {
+ if ((rn % 4) == 0)
+ fprintf (stderr, "\n");
+ fprintf (stderr, "%%r%-3d: 0x%08x ", rn, get_iregval (rn));
+ }
+ fprintf (stderr, "\n");
+
+ /* FR's (as 32-bits), 4 per line. */
+ for (rn = 0; rn < 32; rn++)
+ {
+ float ff = get_fregval_s (cpustate, rn);
+ if ((rn % 4) == 0)
+ fprintf (stderr, "\n");
+ fprintf (stderr, "%%f%-3d: 0x%08x ", rn, *(UINT32 *)&ff);
+ }
+ fprintf (stderr, "\n");
+
+ fprintf (stderr, " psr: CC = %d, LCC = %d, SC = %d, IM = %d, U = %d\n",
+ GET_PSR_CC (), GET_PSR_LCC (), GET_PSR_SC (), GET_PSR_IM (),
+ GET_PSR_U ());
+ fprintf (stderr, " IT/FT/IAT/DAT/IN = %d/%d/%d/%d/%d\n",
+ GET_PSR_IT (), GET_PSR_FT (), GET_PSR_IAT (),
+ GET_PSR_DAT (), GET_PSR_IN ());
+ fprintf (stderr, "epsr: INT = %d, OF = %d, BE = %d\n",
+ GET_EPSR_INT (), GET_EPSR_OF (), GET_EPSR_BE ());
+ fprintf (stderr, " fir: 0x%08x dirbase: 0x%08x fsr: 0x%08x\n",
+ cpustate->cregs[CR_FIR], cpustate->cregs[CR_DIRBASE],
+ cpustate->cregs[CR_FSR]);
+ fprintf (stderr, " pc: 0x%08x\n", cpustate->pc);
+}
+#endif
+
+/* Sign extend N-bit number. */
+INLINE INT32 sign_ext (UINT32 x, int n)
+{
+ INT32 t;
+ t = x >> (n - 1);
+ t = ((-t) << n) | x;
+ return t;
+}
+
+
+static void unrecog_opcode (UINT32 pc, UINT32 insn)
+{
+ fprintf (stderr, "0x%08x: 0x%08x (unrecognized opcode)\n", pc, insn);
+}
+
+
+/* Execute "ld.c csrc2,idest" instruction. */
+static void insn_ld_ctrl (i860s *cpustate, UINT32 insn)
+{
+ UINT32 csrc2 = get_creg (insn);
+ UINT32 idest = get_idest (insn);
+
+#ifdef TRACE_UNDEFINED_I860
+ if (csrc2 > 5)
+ {
+ /* Control register not between 0..5. Undefined i860XR behavior. */
+ fprintf (stderr, "WARNING: insn_ld_from_ctrl (pc=0x%08x): bad creg in ld.c (ignored)\n", cpustate->pc);
+ return;
+ }
+#endif
+
+ /* If this is a load of the fir, then there are two cases:
+ 1. First load of fir after a trap = usual value.
+ 2. Not first load of fir after a trap = address of the ld.c insn. */
+ if (csrc2 == CR_FIR)
+ {
+ if (cpustate->fir_gets_trap_addr)
+ set_iregval (idest, cpustate->cregs[csrc2]);
+ else
+ {
+ cpustate->cregs[csrc2] = cpustate->pc;
+ set_iregval (idest, cpustate->cregs[csrc2]);
+ }
+ cpustate->fir_gets_trap_addr = 0;
+ }
+ else
+ set_iregval (idest, cpustate->cregs[csrc2]);
+}
+
+
+/* Execute "st.c isrc1,csrc2" instruction. */
+static void insn_st_ctrl (i860s *cpustate, UINT32 insn)
+{
+ UINT32 csrc2 = get_creg (insn);
+ UINT32 isrc1 = get_isrc1 (insn);
+
+#ifdef TRACE_UNDEFINED_I860
+ if (csrc2 > 5)
+ {
+ /* Control register not between 0..5. Undefined i860XR behavior. */
+ fprintf (stderr, "WARNING: insn_st_to_ctrl (pc=0x%08x): bad creg in st.c (ignored)\n", cpustate->pc);
+ return;
+ }
+#endif
+
+ /* Look for ITI bit turned on (but it never actually is written --
+ it always appears to be 0). */
+ if (csrc2 == CR_DIRBASE && (get_iregval (isrc1) & 0x20))
+ {
+ /* NOTE: The actual icache and TLB flush are unimplemented for
+ the MAME version. */
+
+ /* Make sure ITI isn't actually written. */
+ set_iregval (isrc1, (get_iregval (isrc1) & ~0x20));
+ }
+
+ if (csrc2 == CR_DIRBASE && (get_iregval (isrc1) & 1)
+ && GET_DIRBASE_ATE () == 0)
+ {
+ fprintf (stderr, "0x%08x: ** ATE going high!\n", cpustate->pc);
+ }
+
+ /* Update the register -- unless it is fir which cannot be updated. */
+ if (csrc2 == CR_EPSR)
+ {
+ UINT32 enew = 0, tmp = 0;
+ /* Make sure unchangeable EPSR bits stay unchanged (DCS, stepping,
+ and type). Also, some bits are only writeable in supervisor
+ mode. */
+ if (GET_PSR_U ())
+ {
+ enew = get_iregval (isrc1) & ~(0x003e1fff | 0x00c06000);
+ tmp = cpustate->cregs[CR_EPSR] & (0x003e1fff | 0x00c06000);
+ }
+ else
+ {
+ enew = get_iregval (isrc1) & ~0x003e1fff;
+ tmp = cpustate->cregs[CR_EPSR] & 0x003e1fff;
+ }
+ cpustate->cregs[CR_EPSR] = enew | tmp;
+ }
+ else if (csrc2 == CR_PSR)
+ {
+ /* Some PSR bits are only writeable in supervisor mode. */
+ if (GET_PSR_U ())
+ {
+ UINT32 enew = get_iregval (isrc1) & ~PSR_SUPERVISOR_ONLY_MASK;
+ UINT32 tmp = cpustate->cregs[CR_PSR] & PSR_SUPERVISOR_ONLY_MASK;
+ cpustate->cregs[CR_PSR] = enew | tmp;
+ }
+ else
+ cpustate->cregs[CR_PSR] = get_iregval (isrc1);
+ }
+ else if (csrc2 == CR_FSR)
+ {
+ /* I believe that only 21..17, 8..5, and 3..0 should be updated. */
+ UINT32 enew = get_iregval (isrc1) & 0x003e01ef;
+ UINT32 tmp = cpustate->cregs[CR_FSR] & ~0x003e01ef;
+ cpustate->cregs[CR_FSR] = enew | tmp;
+ }
+ else if (csrc2 != CR_FIR)
+ cpustate->cregs[csrc2] = get_iregval (isrc1);
+}
+
+
+/* Execute "ld.{s,b,l} isrc1(isrc2),idest" or
+ "ld.{s,b,l} #const(isrc2),idest". */
+static void insn_ldx (i860s *cpustate, UINT32 insn)
+{
+ UINT32 isrc1 = get_isrc1 (insn);
+ INT32 immsrc1 = sign_ext (get_imm16 (insn), 16);
+ UINT32 isrc2 = get_isrc2 (insn);
+ UINT32 idest = get_idest (insn);
+ UINT32 eff = 0;
+ /* Operand size, in bytes. */
+ int sizes[4] = { 1, 1, 2, 4};
+ int size = 0;
+ int form_disp_reg = 0;
+
+ /* Bits 28 and 0 determine the operand size. */
+ size = sizes[((insn >> 27) & 2) | (insn & 1)];
+
+ /* Bit 26 determines the addressing mode (reg+reg or disp+reg). */
+ form_disp_reg = (insn & 0x04000000);
+
+ /* Get effective address depending on disp+reg or reg+reg form. */
+ if (form_disp_reg)
+ {
+ /* Chop off lower bits of displacement. */
+ immsrc1 &= ~(size - 1);
+ eff = (UINT32)(immsrc1 + (INT32)(get_iregval (isrc2)));
+ }
+ else
+ eff = get_iregval (isrc1) + get_iregval (isrc2);
+
+#ifdef TRACE_UNALIGNED_MEM
+ if (eff & (size - 1))
+ {
+ fprintf (stderr, "0x%08x: Unaligned access detected (0x%08x).\n",
+ cpustate->pc, eff);
+ SET_PSR_DAT (1);
+ cpustate->pending_trap = 1;
+ return;
+ }
+#endif
+
+ /* The i860 sign-extends 8- or 16-bit integer loads.
+
+ Below, the readmemi_emu() needs to happen outside of the
+ set_iregval macro (otherwise the readmem won't occur if r0
+ is the target register). */
+ if (size < 4)
+ {
+ UINT32 readval = sign_ext (readmemi_emu (cpustate, eff, size), size * 8);
+ /* Do not update register on page fault. */
+ if (cpustate->exiting_readmem)
+ {
+ return;
+ }
+ set_iregval (idest, readval);
+ }
+ else
+ {
+ UINT32 readval = readmemi_emu (cpustate, eff, size);
+ /* Do not update register on page fault. */
+ if (cpustate->exiting_readmem)
+ {
+ return;
+ }
+ set_iregval (idest, readval);
+ }
+}
+
+
+/* Execute "st.x isrc1ni,#const(isrc2)" instruction (there is no
+ (reg + reg form). Store uses the split immediate, not the normal
+ 16-bit immediate as in ld.x. */
+static void insn_stx (i860s *cpustate, UINT32 insn)
+{
+ INT32 immsrc = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16);
+ UINT32 isrc1 = get_isrc1 (insn);
+ UINT32 isrc2 = get_isrc2 (insn);
+ UINT32 eff = 0;
+ /* Operand size, in bytes. */
+ int sizes[4] = { 1, 1, 2, 4};
+ int size = 0;
+
+ /* Bits 28 and 0 determine the operand size. */
+ size = sizes[((insn >> 27) & 2) | (insn & 1)];
+
+ /* FIXME: Do any necessary traps. */
+
+ /* Get effective address. Chop off lower bits of displacement. */
+ immsrc &= ~(size - 1);
+ eff = (UINT32)(immsrc + (INT32)get_iregval (isrc2));
+
+ /* Write data (value of reg isrc1) to memory at eff. */
+ writememi_emu (cpustate, eff, size, get_iregval (isrc1));
+ if (cpustate->exiting_readmem)
+ return;
+}
+
+
+/* Execute "fst.y fdest,isrc1(isrc2)", "fst.y fdest,isrc1(isrc2)++",
+ "fst.y fdest,#const(isrc2)" or "fst.y fdest,#const(isrc2)++"
+ instruction. */
+static void insn_fsty (i860s *cpustate, UINT32 insn)
+{
+ UINT32 isrc1 = get_isrc1 (insn);
+ INT32 immsrc1 = sign_ext (get_imm16 (insn), 16);
+ UINT32 isrc2 = get_isrc2 (insn);
+ UINT32 fdest = get_fdest (insn);
+ UINT32 eff = 0;
+ /* Operand size, in bytes. */
+ int sizes[4] = { 8, 4, 16, 4};
+ int size = 0;
+ int form_disp_reg = 0;
+ int auto_inc = (insn & 1);
+
+ /* Bits 2 and 1 determine the operand size. */
+ size = sizes[((insn >> 1) & 3)];
+
+ /* Bit 26 determines the addressing mode (reg+reg or disp+reg). */
+ form_disp_reg = (insn & 0x04000000);
+
+ /* FIXME: Check for undefined behavior, non-even or non-quad
+ register operands for fst.d and fst.q respectively. */
+
+ /* Get effective address depending on disp+reg or reg+reg form. */
+ if (form_disp_reg)
+ {
+ /* Chop off lower bits of displacement. */
+ immsrc1 &= ~(size - 1);
+ eff = (UINT32)(immsrc1 + (INT32)(get_iregval (isrc2)));
+ }
+ else
+ eff = get_iregval (isrc1) + get_iregval (isrc2);
+
+#ifdef TRACE_UNALIGNED_MEM
+ if (eff & (size - 1))
+ {
+ fprintf (stderr, "0x%08x: Unaligned access detected (0x%08x).\n",
+ cpustate->pc, eff);
+ SET_PSR_DAT (1);
+ cpustate->pending_trap = 1;
+ return;
+ }
+#endif
+
+ /* Do (post) auto-increment. */
+ if (auto_inc)
+ {
+ set_iregval (isrc2, eff);
+#ifdef TRACE_UNDEFINED_I860
+ /* When auto-inc, isrc1 and isrc2 regs can't be the same. */
+ if (isrc1 == isrc2)
+ {
+ /* Undefined i860XR behavior. */
+ fprintf (stderr, "WARNING: insn_fsty (pc=0x%08x): isrc1 = isrc2 in fst with auto-inc (ignored)\n", cpustate->pc);
+ return;
+ }
+#endif
+ }
+
+ /* Write data (value of freg fdest) to memory at eff. */
+ if (size == 4)
+ fp_writemem_emu (cpustate, eff, size, (UINT8 *)(&cpustate->frg[4 * (31 - fdest)]), 0xff);
+ else if (size == 8)
+ fp_writemem_emu (cpustate, eff, size, (UINT8 *)(&cpustate->frg[4 * (31 - (fdest + 1))]), 0xff);
+ else
+ fp_writemem_emu (cpustate, eff, size, (UINT8 *)(&cpustate->frg[4 * (31 - (fdest + 3))]), 0xff);
+
+}
+
+
+/* Execute "fld.y isrc1(isrc2),fdest", "fld.y isrc1(isrc2)++,idest",
+ "fld.y #const(isrc2),fdest" or "fld.y #const(isrc2)++,idest".
+ Where y = {l,d,q}. Note, there is no pfld.q, though. */
+static void insn_fldy (i860s *cpustate, UINT32 insn)
+{
+ UINT32 isrc1 = get_isrc1 (insn);
+ INT32 immsrc1 = sign_ext (get_imm16 (insn), 16);
+ UINT32 isrc2 = get_isrc2 (insn);
+ UINT32 fdest = get_fdest (insn);
+ UINT32 eff = 0;
+ /* Operand size, in bytes. */
+ int sizes[4] = { 8, 4, 16, 4};
+ int size = 0;
+ int form_disp_reg = 0;
+ int auto_inc = (insn & 1);
+ int piped = (insn & 0x40000000);
+
+ /* Bits 2 and 1 determine the operand size. */
+ size = sizes[((insn >> 1) & 3)];
+
+ /* Bit 26 determines the addressing mode (reg+reg or disp+reg). */
+ form_disp_reg = (insn & 0x04000000);
+
+ /* There is no pipelined load quad. */
+ if (piped && size == 16)
+ {
+ unrecog_opcode (cpustate->pc, insn);
+ return;
+ }
+
+ /* FIXME: Check for undefined behavior, non-even or non-quad
+ register operands for fld.d and fld.q respectively. */
+
+ /* Get effective address depending on disp+reg or reg+reg form. */
+ if (form_disp_reg)
+ {
+ /* Chop off lower bits of displacement. */
+ immsrc1 &= ~(size - 1);
+ eff = (UINT32)(immsrc1 + (INT32)(get_iregval (isrc2)));
+ }
+ else
+ eff = get_iregval (isrc1) + get_iregval (isrc2);
+
+ /* Do (post) auto-increment. */
+ if (auto_inc)
+ {
+ set_iregval (isrc2, eff);
+#ifdef TRACE_UNDEFINED_I860
+ /* When auto-inc, isrc1 and isrc2 regs can't be the same. */
+ if (isrc1 == isrc2)
+ {
+ /* Undefined i860XR behavior. */
+ fprintf (stderr, "WARNING: insn_fldy (pc=0x%08x): isrc1 = isrc2 in fst with auto-inc (ignored)\n", cpustate->pc);
+ return;
+ }
+#endif
+ }
+
+#ifdef TRACE_UNALIGNED_MEM
+ if (eff & (size - 1))
+ {
+ fprintf (stderr, "0x%08x: Unaligned access detected (0x%08x).\n",
+ cpustate->pc, eff);
+ SET_PSR_DAT (1);
+ cpustate->pending_trap = 1;
+ return;
+ }
+#endif
+
+ /* Update the load pipe if necessary. */
+ /* FIXME: Copy result-status bits to fsr from last stage. */
+ if (!piped)
+ {
+ /* Scalar version writes the current result to fdest. */
+ /* Read data at 'eff' into freg 'fdest' (reads to f0 or f1 are
+ thrown away). */
+ if (fdest > 1)
+ {
+ if (size == 4)
+ fp_readmem_emu (cpustate, eff, size, (UINT8 *)&(cpustate->frg[4 * (31 - fdest)]));
+ else if (size == 8)
+ fp_readmem_emu (cpustate, eff, size, (UINT8 *)&(cpustate->frg[4 * (31 - (fdest + 1))]));
+ else if (size == 16)
+ fp_readmem_emu (cpustate, eff, size, (UINT8 *)&(cpustate->frg[4 * (31 - (fdest + 3))]));
+ }
+ }
+ else
+ {
+ /* Read the data into a temp space first. This way we can test
+ for any traps before updating the pipeline. The pipeline must
+ stay unaffected after a trap so that the instruction can be
+ properly restarted. */
+ UINT8 bebuf[8];
+ fp_readmem_emu (cpustate, eff, size, bebuf);
+ if (cpustate->pending_trap && cpustate->exiting_readmem)
+ goto ab_op;
+
+ /* Pipelined version writes fdest with the result from the last
+ stage of the pipeline, with precision specified by the LRP
+ bit of the stage's result-status bits. */
+#if 1 /* FIXME: WIP on FSR update. This may not be correct. */
+ /* Copy 3rd stage LRP to FSR. */
+ if (cpustate->L[1 /* 2 */].stat.lrp)
+ cpustate->cregs[CR_FSR] |= 0x04000000;
+ else
+ cpustate->cregs[CR_FSR] &= ~0x04000000;
+#endif
+ if (cpustate->L[2].stat.lrp) /* 3rd (last) stage. */
+ set_fregval_d (cpustate, fdest, cpustate->L[2].val.d);
+ else
+ set_fregval_s (cpustate, fdest, cpustate->L[2].val.s);
+
+ /* Now advance pipeline and write loaded data to first stage. */
+ cpustate->L[2] = cpustate->L[1];
+ cpustate->L[1] = cpustate->L[0];
+ if (size == 8)
+ {
+ UINT8 *t = (UINT8 *)&(cpustate->L[0].val.d);
+#ifndef HOST_MSB
+ t[7] = bebuf[0]; t[6] = bebuf[1]; t[5] = bebuf[2]; t[4] = bebuf[3];
+ t[3] = bebuf[4]; t[2] = bebuf[5]; t[1] = bebuf[6]; t[0] = bebuf[7];
+#else
+ t[0] = bebuf[0]; t[1] = bebuf[1]; t[2] = bebuf[2]; t[3] = bebuf[3];
+ t[4] = bebuf[4]; t[5] = bebuf[5]; t[6] = bebuf[6]; t[7] = bebuf[7];
+#endif
+ cpustate->L[0].stat.lrp = 1;
+ }
+ else
+ {
+ UINT8 *t = (UINT8 *)&(cpustate->L[0].val.s);
+#ifndef HOST_MSB
+ t[3] = bebuf[0]; t[2] = bebuf[1]; t[1] = bebuf[2]; t[0] = bebuf[3];
+#else
+ t[0] = bebuf[0]; t[1] = bebuf[1]; t[2] = bebuf[2]; t[3] = bebuf[3];
+#endif
+ cpustate->L[0].stat.lrp = 0;
+ }
+ }
+
+ ab_op:;
+}
+
+
+/* Execute "pst.d fdest,#const(isrc2)" or "fst.d fdest,#const(isrc2)++"
+ instruction. */
+static void insn_pstd (i860s *cpustate, UINT32 insn)
+{
+ INT32 immsrc1 = sign_ext (get_imm16 (insn), 16);
+ UINT32 isrc2 = get_isrc2 (insn);
+ UINT32 fdest = get_fdest (insn);
+ UINT32 eff = 0;
+ int auto_inc = (insn & 1);
+ UINT8 *bebuf = 0;
+ int pm = GET_PSR_PM ();
+ int i;
+ UINT32 wmask;
+ int orig_pm = pm;
+
+ /* Get the pixel size, where:
+ PS: 0 = 8 bits, 1 = 16 bits, 2 = 32-bits. */
+ int ps = GET_PSR_PS ();
+
+#ifdef TRACE_UNDEFINED_I860
+ if (!(ps == 0 || ps == 1 || ps == 2))
+ fprintf (stderr, "insn_pstd: Undefined i860XR behavior, invalid value %d for pixel size.\n", ps);
+#endif
+
+#ifdef TRACE_UNDEFINED_I860
+ /* Bits 2 and 1 determine the operand size, which must always be
+ zero (indicating a 64-bit operand). */
+ if (insn & 0x6)
+ {
+ /* Undefined i860XR behavior. */
+ fprintf (stderr, "WARNING: insn_pstd (pc=0x%08x): bad operand size specifier\n", cpustate->pc);
+ }
+#endif
+
+ /* FIXME: Check for undefined behavior, non-even register operands. */
+
+ /* Get effective address. Chop off lower bits of displacement. */
+ immsrc1 &= ~(8 - 1);
+ eff = (UINT32)(immsrc1 + (INT32)(get_iregval (isrc2)));
+
+#ifdef TRACE_UNALIGNED_MEM
+ if (eff & (8 - 1))
+ {
+ fprintf (stderr, "0x%08x: Unaligned access detected (0x%08x).\n",
+ cpustate->pc, eff);
+ SET_PSR_DAT (1);
+ cpustate->pending_trap = 1;
+ return;
+ }
+#endif
+
+ /* Do (post) auto-increment. */
+ if (auto_inc)
+ set_iregval (isrc2, eff);
+
+ /* Update the the pixel mask depending on the pixel size. Shift PM
+ right by 8/2^ps bits. */
+ if (ps == 0)
+ pm = (pm >> 8) & 0x00;
+ else if (ps == 1)
+ pm = (pm >> 4) & 0x0f;
+ else if (ps == 2)
+ pm = (pm >> 2) & 0x3f;
+ SET_PSR_PM (pm);
+
+ /* Write data (value of freg fdest) to memory at eff-- but only those
+ bytes that are enabled by the bits in PSR.PM. Bit 0 of PM selects
+ the pixel at the lowest address. */
+ wmask = 0;
+ for (i = 0; i < 8; )
+ {
+ if (ps == 0)
+ {
+ if (orig_pm & 0x80)
+ wmask |= 1 << (7-i);
+ i += 1;
+ }
+ else if (ps == 1)
+ {
+ if (orig_pm & 0x08)
+ wmask |= 0x3 << (6-i);
+ i += 2;
+ }
+ else if (ps == 2)
+ {
+ if (orig_pm & 0x02)
+ wmask |= 0xf << (4-i);
+ i += 4;
+ }
+ else
+ {
+ wmask = 0xff;
+ break;
+ }
+ orig_pm <<= 1;
+ }
+ bebuf = (UINT8 *)(&cpustate->frg[4 * (31 - (fdest + 1))]);
+ fp_writemem_emu (cpustate, eff, 8, bebuf, wmask);
+}
+
+
+/* Execute "ixfr isrc1ni,fdest" instruction. */
+static void insn_ixfr (i860s *cpustate, UINT32 insn)
+{
+ UINT32 isrc1 = get_isrc1 (insn);
+ UINT32 fdest = get_fdest (insn);
+ UINT32 iv = 0;
+
+ /* This is a bit-pattern transfer, not a conversion. */
+ iv = get_iregval (isrc1);
+ set_fregval_s (cpustate, fdest, *(float *)&iv);
+}
+
+
+/* Execute "addu isrc1,isrc2,idest". */
+static void insn_addu (i860s *cpustate, UINT32 insn)
+{
+ UINT32 src1val;
+ UINT32 isrc2 = get_isrc2 (insn);
+ UINT32 idest = get_idest (insn);
+ UINT32 tmp_dest_val = 0;
+ UINT64 tmp = 0;
+
+ src1val = get_iregval (get_isrc1 (insn));
+
+ /* We don't update the actual idest register now because below we
+ need to test the original src1 and src2 if either happens to
+ be the destination register. */
+ tmp_dest_val = src1val + get_iregval (isrc2);
+
+ /* Set OF and CC flags.
+ For unsigned:
+ OF = bit 31 carry
+ CC = bit 31 carry.
+ */
+ tmp = (UINT64)src1val + (UINT64)(get_iregval (isrc2));
+ if ((tmp >> 32) & 1)
+ {
+ SET_PSR_CC (1);
+ SET_EPSR_OF (1);
+ }
+ else
+ {
+ SET_PSR_CC (0);
+ SET_EPSR_OF (0);
+ }
+
+ /* Now update the destination register. */
+ set_iregval (idest, tmp_dest_val);
+}
+
+
+/* Execute "addu #const,isrc2,idest". */
+static void insn_addu_imm (i860s *cpustate, UINT32 insn)
+{
+ UINT32 src1val;
+ UINT32 isrc2 = get_isrc2 (insn);
+ UINT32 idest = get_idest (insn);
+ UINT32 tmp_dest_val = 0;
+ UINT64 tmp = 0;
+
+ src1val = sign_ext (get_imm16 (insn), 16);
+
+ /* We don't update the actual idest register now because below we
+ need to test the original src1 and src2 if either happens to
+ be the destination register. */
+ tmp_dest_val = src1val + get_iregval (isrc2);
+
+ /* Set OF and CC flags.
+ For unsigned:
+ OF = bit 31 carry
+ CC = bit 31 carry.
+ */
+ tmp = (UINT64)src1val + (UINT64)(get_iregval (isrc2));
+ if ((tmp >> 32) & 1)
+ {
+ SET_PSR_CC (1);
+ SET_EPSR_OF (1);
+ }
+ else
+ {
+ SET_PSR_CC (0);
+ SET_EPSR_OF (0);
+ }
+
+ /* Now update the destination register. */
+ set_iregval (idest, tmp_dest_val);
+}
+
+
+/* Execute "adds isrc1,isrc2,idest". */
+static void insn_adds (i860s *cpustate, UINT32 insn)
+{
+ UINT32 src1val;
+ UINT32 isrc2 = get_isrc2 (insn);
+ UINT32 idest = get_idest (insn);
+ UINT32 tmp_dest_val = 0;
+ int sa, sb, sres;
+
+ src1val = get_iregval (get_isrc1 (insn));
+
+ /* We don't update the actual idest register now because below we
+ need to test the original src1 and src2 if either happens to
+ be the destination register. */
+ tmp_dest_val = src1val + get_iregval (isrc2);
+
+ /* Set OF and CC flags.
+ For signed:
+ OF = standard signed overflow.
+ CC set if isrc2 < -isrc1
+ CC clear if isrc2 >= -isrc1
+ */
+ sa = src1val & 0x80000000;
+ sb = get_iregval (isrc2) & 0x80000000;
+ sres = tmp_dest_val & 0x80000000;
+ if (sa != sb && sa != sres)
+ SET_EPSR_OF (1);
+ else
+ SET_EPSR_OF (0);
+
+ if ((INT32)get_iregval (isrc2) < -(INT32)(src1val))
+ SET_PSR_CC (1);
+ else
+ SET_PSR_CC (0);
+
+ /* Now update the destination register. */
+ set_iregval (idest, tmp_dest_val);
+}
+
+
+/* Execute "adds #const,isrc2,idest". */
+static void insn_adds_imm (i860s *cpustate, UINT32 insn)
+{
+ UINT32 src1val;
+ UINT32 isrc2 = get_isrc2 (insn);
+ UINT32 idest = get_idest (insn);
+ UINT32 tmp_dest_val = 0;
+ int sa, sb, sres;
+
+ src1val = sign_ext (get_imm16 (insn), 16);
+
+ /* We don't update the actual idest register now because below we
+ need to test the original src1 and src2 if either happens to
+ be the destination register. */
+ tmp_dest_val = src1val + get_iregval (isrc2);
+
+ /* Set OF and CC flags.
+ For signed:
+ OF = standard signed overflow.
+ CC set if isrc2 < -isrc1
+ CC clear if isrc2 >= -isrc1
+ */
+ sa = src1val & 0x80000000;
+ sb = get_iregval (isrc2) & 0x80000000;
+ sres = tmp_dest_val & 0x80000000;
+ if (sa != sb && sa != sres)
+ SET_EPSR_OF (1);
+ else
+ SET_EPSR_OF (0);
+
+ if ((INT32)get_iregval (isrc2) < -(INT32)(src1val))
+ SET_PSR_CC (1);
+ else
+ SET_PSR_CC (0);
+
+ /* Now update the destination register. */
+ set_iregval (idest, tmp_dest_val);
+}
+
+
+/* Execute "subu isrc1,isrc2,idest". */
+static void insn_subu (i860s *cpustate, UINT32 insn)
+{
+ UINT32 src1val;
+ UINT32 isrc2 = get_isrc2 (insn);
+ UINT32 idest = get_idest (insn);
+ UINT32 tmp_dest_val = 0;
+
+ src1val = get_iregval (get_isrc1 (insn));
+
+ /* We don't update the actual idest register now because below we
+ need to test the original src1 and src2 if either happens to
+ be the destination register. */
+ tmp_dest_val = src1val - get_iregval (isrc2);
+
+ /* Set OF and CC flags.
+ For unsigned:
+ OF = NOT(bit 31 carry)
+ CC = bit 31 carry.
+ (i.e. CC set if isrc2 <= isrc1
+ CC clear if isrc2 > isrc1
+ */
+ if ((UINT32)get_iregval (isrc2) <= (UINT32)src1val)
+ {
+ SET_PSR_CC (1);
+ SET_EPSR_OF (0);
+ }
+ else
+ {
+ SET_PSR_CC (0);
+ SET_EPSR_OF (1);
+ }
+
+ /* Now update the destination register. */
+ set_iregval (idest, tmp_dest_val);
+}
+
+
+/* Execute "subu #const,isrc2,idest". */
+static void insn_subu_imm (i860s *cpustate, UINT32 insn)
+{
+ UINT32 src1val;
+ UINT32 isrc2 = get_isrc2 (insn);
+ UINT32 idest = get_idest (insn);
+ UINT32 tmp_dest_val = 0;
+
+ src1val = sign_ext (get_imm16 (insn), 16);
+
+ /* We don't update the actual idest register now because below we
+ need to test the original src1 and src2 if either happens to
+ be the destination register. */
+ tmp_dest_val = src1val - get_iregval (isrc2);
+
+ /* Set OF and CC flags.
+ For unsigned:
+ OF = NOT(bit 31 carry)
+ CC = bit 31 carry.
+ (i.e. CC set if isrc2 <= isrc1
+ CC clear if isrc2 > isrc1
+ */
+ if ((UINT32)get_iregval (isrc2) <= (UINT32)src1val)
+ {
+ SET_PSR_CC (1);
+ SET_EPSR_OF (0);
+ }
+ else
+ {
+ SET_PSR_CC (0);
+ SET_EPSR_OF (1);
+ }
+
+ /* Now update the destination register. */
+ set_iregval (idest, tmp_dest_val);
+}
+
+
+/* Execute "subs isrc1,isrc2,idest". */
+static void insn_subs (i860s *cpustate, UINT32 insn)
+{
+ UINT32 src1val;
+ UINT32 isrc2 = get_isrc2 (insn);
+ UINT32 idest = get_idest (insn);
+ UINT32 tmp_dest_val = 0;
+ int sa, sb, sres;
+
+ src1val = get_iregval (get_isrc1 (insn));
+
+ /* We don't update the actual idest register now because below we
+ need to test the original src1 and src2 if either happens to
+ be the destination register. */
+ tmp_dest_val = src1val - get_iregval (isrc2);
+
+ /* Set OF and CC flags.
+ For signed:
+ OF = standard signed overflow.
+ CC set if isrc2 > isrc1
+ CC clear if isrc2 <= isrc1
+ */
+ sa = src1val & 0x80000000;
+ sb = get_iregval (isrc2) & 0x80000000;
+ sres = tmp_dest_val & 0x80000000;
+ if (sa != sb && sa != sres)
+ SET_EPSR_OF (1);
+ else
+ SET_EPSR_OF (0);
+
+ if ((INT32)get_iregval (isrc2) > (INT32)(src1val))
+ SET_PSR_CC (1);
+ else
+ SET_PSR_CC (0);
+
+ /* Now update the destination register. */
+ set_iregval (idest, tmp_dest_val);
+}
+
+
+/* Execute "subs #const,isrc2,idest". */
+static void insn_subs_imm (i860s *cpustate, UINT32 insn)
+{
+ UINT32 src1val;
+ UINT32 isrc2 = get_isrc2 (insn);
+ UINT32 idest = get_idest (insn);
+ UINT32 tmp_dest_val = 0;
+ int sa, sb, sres;
+
+ src1val = sign_ext (get_imm16 (insn), 16);
+
+ /* We don't update the actual idest register now because below we
+ need to test the original src1 and src2 if either happens to
+ be the destination register. */
+ tmp_dest_val = src1val - get_iregval (isrc2);
+
+ /* Set OF and CC flags.
+ For signed:
+ OF = standard signed overflow.
+ CC set if isrc2 > isrc1
+ CC clear if isrc2 <= isrc1
+ */
+ sa = src1val & 0x80000000;
+ sb = get_iregval (isrc2) & 0x80000000;
+ sres = tmp_dest_val & 0x80000000;
+ if (sa != sb && sa != sres)
+ SET_EPSR_OF (1);
+ else
+ SET_EPSR_OF (0);
+
+ if ((INT32)get_iregval (isrc2) > (INT32)(src1val))
+ SET_PSR_CC (1);
+ else
+ SET_PSR_CC (0);
+
+ /* Now update the destination register. */
+ set_iregval (idest, tmp_dest_val);
+}
+
+
+/* Execute "shl isrc1,isrc2,idest". */
+static void insn_shl (i860s *cpustate, UINT32 insn)
+{
+ UINT32 src1val = 0;
+ UINT32 isrc2 = get_isrc2 (insn);
+ UINT32 idest = get_idest (insn);
+
+ src1val = get_iregval (get_isrc1 (insn));
+ set_iregval (idest, get_iregval (isrc2) << src1val);
+}
+
+
+/* Execute "shl #const,isrc2,idest". */
+static void insn_shl_imm (i860s *cpustate, UINT32 insn)
+{
+ UINT32 src1val = 0;
+ UINT32 isrc2 = get_isrc2 (insn);
+ UINT32 idest = get_idest (insn);
+
+ src1val = sign_ext (get_imm16 (insn), 16);
+ set_iregval (idest, get_iregval (isrc2) << src1val);
+}
+
+
+/* Execute "shr isrc1,isrc2,idest". */
+static void insn_shr (i860s *cpustate, UINT32 insn)
+{
+ UINT32 src1val = 0;
+ UINT32 isrc2 = get_isrc2 (insn);
+ UINT32 idest = get_idest (insn);
+
+ src1val = get_iregval (get_isrc1 (insn));
+
+ /* The iregs array is UINT32, so this is a logical shift. */
+ set_iregval (idest, get_iregval (isrc2) >> src1val);
+
+ /* shr also sets the SC in psr (shift count). */
+ SET_PSR_SC (src1val);
+}
+
+
+/* Execute "shr #const,isrc2,idest". */
+static void insn_shr_imm (i860s *cpustate, UINT32 insn)
+{
+ UINT32 src1val = 0;
+ UINT32 isrc2 = get_isrc2 (insn);
+ UINT32 idest = get_idest (insn);
+
+ src1val = sign_ext (get_imm16 (insn), 16);
+
+ /* The iregs array is UINT32, so this is a logical shift. */
+ set_iregval (idest, get_iregval (isrc2) >> src1val);
+
+ /* shr also sets the SC in psr (shift count). */
+ SET_PSR_SC (src1val);
+}
+
+
+/* Execute "shra isrc1,isrc2,idest". */
+static void insn_shra (i860s *cpustate, UINT32 insn)
+{
+ UINT32 src1val = 0;
+ UINT32 isrc2 = get_isrc2 (insn);
+ UINT32 idest = get_idest (insn);
+
+ src1val = get_iregval (get_isrc1 (insn));
+
+ /* The iregs array is UINT32, so cast isrc2 to get arithmetic shift. */
+ set_iregval (idest, (INT32)get_iregval (isrc2) >> src1val);
+}
+
+
+/* Execute "shra #const,isrc2,idest". */
+static void insn_shra_imm (i860s *cpustate, UINT32 insn)
+{
+ UINT32 src1val = 0;
+ UINT32 isrc2 = get_isrc2 (insn);
+ UINT32 idest = get_idest (insn);
+
+ src1val = sign_ext (get_imm16 (insn), 16);
+
+ /* The iregs array is UINT32, so cast isrc2 to get arithmetic shift. */
+ set_iregval (idest, (INT32)get_iregval (isrc2) >> src1val);
+}
+
+
+/* Execute "shrd isrc1ni,isrc2,idest" instruction. */
+static void insn_shrd (i860s *cpustate, UINT32 insn)
+{
+ UINT32 isrc1 = get_isrc1 (insn);
+ UINT32 isrc2 = get_isrc2 (insn);
+ UINT32 idest = get_idest (insn);
+ UINT32 sc = GET_PSR_SC ();
+ UINT32 tmp;
+
+ /* Do the operation:
+ idest = low_32(isrc1ni:isrc2 >> sc). */
+ if (sc == 0)
+ tmp = get_iregval (isrc2);
+ else
+ {
+ tmp = get_iregval (isrc1) << (32 - sc);
+ tmp |= (get_iregval (isrc2) >> sc);
+ }
+ set_iregval (idest, tmp);
+}
+
+
+/* Execute "and isrc1,isrc2,idest". */
+static void insn_and (i860s *cpustate, UINT32 insn)
+{
+ UINT32 isrc1 = get_isrc1 (insn);
+ UINT32 isrc2 = get_isrc2 (insn);
+ UINT32 idest = get_idest (insn);
+ UINT32 res = 0;
+
+ /* Do the operation. */
+ res = get_iregval (isrc1) & get_iregval (isrc2);
+
+ /* Set flags. */
+ if (res == 0)
+ SET_PSR_CC (1);
+ else
+ SET_PSR_CC (0);
+
+ set_iregval (idest, res);
+}
+
+
+/* Execute "and #const,isrc2,idest". */
+static void insn_and_imm (i860s *cpustate, UINT32 insn)
+{
+ UINT32 src1val = 0;
+ UINT32 isrc2 = get_isrc2 (insn);
+ UINT32 idest = get_idest (insn);
+ UINT32 res = 0;
+
+ /* Do the operation. */
+ src1val = get_imm16 (insn);
+ res = src1val & get_iregval (isrc2);
+
+ /* Set flags. */
+ if (res == 0)
+ SET_PSR_CC (1);
+ else
+ SET_PSR_CC (0);
+
+ set_iregval (idest, res);
+}
+
+
+/* Execute "andh #const,isrc2,idest". */
+static void insn_andh_imm (i860s *cpustate, UINT32 insn)
+{
+ UINT32 src1val = 0;
+ UINT32 isrc2 = get_isrc2 (insn);
+ UINT32 idest = get_idest (insn);
+ UINT32 res = 0;
+
+ /* Do the operation. */
+ src1val = get_imm16 (insn);
+ res = (src1val << 16) & get_iregval (isrc2);
+
+ /* Set flags. */
+ if (res == 0)
+ SET_PSR_CC (1);
+ else
+ SET_PSR_CC (0);
+
+ set_iregval (idest, res);
+}
+
+
+/* Execute "andnot isrc1,isrc2,idest". */
+static void insn_andnot (i860s *cpustate, UINT32 insn)
+{
+ UINT32 isrc1 = get_isrc1 (insn);
+ UINT32 isrc2 = get_isrc2 (insn);
+ UINT32 idest = get_idest (insn);
+ UINT32 res = 0;
+
+ /* Do the operation. */
+ res = (~get_iregval (isrc1)) & get_iregval (isrc2);
+
+ /* Set flags. */
+ if (res == 0)
+ SET_PSR_CC (1);
+ else
+ SET_PSR_CC (0);
+
+ set_iregval (idest, res);
+}
+
+
+/* Execute "andnot #const,isrc2,idest". */
+static void insn_andnot_imm (i860s *cpustate, UINT32 insn)
+{
+ UINT32 src1val = 0;
+ UINT32 isrc2 = get_isrc2 (insn);
+ UINT32 idest = get_idest (insn);
+ UINT32 res = 0;
+
+ /* Do the operation. */
+ src1val = get_imm16 (insn);
+ res = (~src1val) & get_iregval (isrc2);
+
+ /* Set flags. */
+ if (res == 0)
+ SET_PSR_CC (1);
+ else
+ SET_PSR_CC (0);
+
+ set_iregval (idest, res);
+}
+
+
+/* Execute "andnoth #const,isrc2,idest". */
+static void insn_andnoth_imm (i860s *cpustate, UINT32 insn)
+{
+ UINT32 src1val = 0;
+ UINT32 isrc2 = get_isrc2 (insn);
+ UINT32 idest = get_idest (insn);
+ UINT32 res = 0;
+
+ /* Do the operation. */
+ src1val = get_imm16 (insn);
+ res = (~(src1val << 16)) & get_iregval (isrc2);
+
+ /* Set flags. */
+ if (res == 0)
+ SET_PSR_CC (1);
+ else
+ SET_PSR_CC (0);
+
+ set_iregval (idest, res);
+}
+
+
+/* Execute "or isrc1,isrc2,idest". */
+static void insn_or (i860s *cpustate, UINT32 insn)
+{
+ UINT32 isrc1 = get_isrc1 (insn);
+ UINT32 isrc2 = get_isrc2 (insn);
+ UINT32 idest = get_idest (insn);
+ UINT32 res = 0;
+
+ /* Do the operation. */
+ res = get_iregval (isrc1) | get_iregval (isrc2);
+
+ /* Set flags. */
+ if (res == 0)
+ SET_PSR_CC (1);
+ else
+ SET_PSR_CC (0);
+
+ set_iregval (idest, res);
+}
+
+
+/* Execute "or #const,isrc2,idest". */
+static void insn_or_imm (i860s *cpustate, UINT32 insn)
+{
+ UINT32 src1val = 0;
+ UINT32 isrc2 = get_isrc2 (insn);
+ UINT32 idest = get_idest (insn);
+ UINT32 res = 0;
+
+ /* Do the operation. */
+ src1val = get_imm16 (insn);
+ res = src1val | get_iregval (isrc2);
+
+ /* Set flags. */
+ if (res == 0)
+ SET_PSR_CC (1);
+ else
+ SET_PSR_CC (0);
+
+ set_iregval (idest, res);
+}
+
+
+/* Execute "orh #const,isrc2,idest". */
+static void insn_orh_imm (i860s *cpustate, UINT32 insn)
+{
+ UINT32 src1val = 0;
+ UINT32 isrc2 = get_isrc2 (insn);
+ UINT32 idest = get_idest (insn);
+ UINT32 res = 0;
+
+ /* Do the operation. */
+ src1val = get_imm16 (insn);
+ res = (src1val << 16) | get_iregval (isrc2);
+
+ /* Set flags. */
+ if (res == 0)
+ SET_PSR_CC (1);
+ else
+ SET_PSR_CC (0);
+
+ set_iregval (idest, res);
+}
+
+
+/* Execute "xor isrc1,isrc2,idest". */
+static void insn_xor (i860s *cpustate, UINT32 insn)
+{
+ UINT32 isrc1 = get_isrc1 (insn);
+ UINT32 isrc2 = get_isrc2 (insn);
+ UINT32 idest = get_idest (insn);
+ UINT32 res = 0;
+
+ /* Do the operation. */
+ res = get_iregval (isrc1) ^ get_iregval (isrc2);
+
+ /* Set flags. */
+ if (res == 0)
+ SET_PSR_CC (1);
+ else
+ SET_PSR_CC (0);
+
+ set_iregval (idest, res);
+}
+
+
+/* Execute "xor #const,isrc2,idest". */
+static void insn_xor_imm (i860s *cpustate, UINT32 insn)
+{
+ UINT32 src1val = 0;
+ UINT32 isrc2 = get_isrc2 (insn);
+ UINT32 idest = get_idest (insn);
+ UINT32 res = 0;
+
+ /* Do the operation. */
+ src1val = get_imm16 (insn);
+ res = src1val ^ get_iregval (isrc2);
+
+ /* Set flags. */
+ if (res == 0)
+ SET_PSR_CC (1);
+ else
+ SET_PSR_CC (0);
+
+ set_iregval (idest, res);
+}
+
+
+/* Execute "xorh #const,isrc2,idest". */
+static void insn_xorh_imm (i860s *cpustate, UINT32 insn)
+{
+ UINT32 src1val = 0;
+ UINT32 isrc2 = get_isrc2 (insn);
+ UINT32 idest = get_idest (insn);
+ UINT32 res = 0;
+
+ /* Do the operation. */
+ src1val = get_imm16 (insn);
+ res = (src1val << 16) ^ get_iregval (isrc2);
+
+ /* Set flags. */
+ if (res == 0)
+ SET_PSR_CC (1);
+ else
+ SET_PSR_CC (0);
+
+ set_iregval (idest, res);
+}
+
+
+/* Execute "trap isrc1ni,isrc2,idest" instruction. */
+static void insn_trap (i860s *cpustate, UINT32 insn)
+{
+ SET_PSR_IT (1);
+ cpustate->pending_trap = 1;
+}
+
+
+/* Execute "intovr" instruction. */
+static void insn_intovr (i860s *cpustate, UINT32 insn)
+{
+ if (GET_EPSR_OF ())
+ {
+ SET_PSR_IT (1);
+ cpustate->pending_trap = 1;
+ }
+}
+
+
+/* Execute "bte isrc1,isrc2,sbroff". */
+static void insn_bte (i860s *cpustate, UINT32 insn)
+{
+ UINT32 src1val = 0;
+ UINT32 isrc2 = get_isrc2 (insn);
+ UINT32 target_addr = 0;
+ INT32 sbroff = 0;
+ int res = 0;
+
+ src1val = get_iregval (get_isrc1 (insn));
+
+ /* Compute the target address from the sbroff field. */
+ sbroff = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16);
+ target_addr = (INT32)cpustate->pc + 4 + (sbroff << 2);
+
+ /* Determine comparison result. */
+ res = (src1val == get_iregval (isrc2));
+
+ /* Branch routines always update the PC. */
+ if (res)
+ cpustate->pc = target_addr;
+ else
+ cpustate->pc += 4;
+
+ cpustate->pc_updated = 1;
+}
+
+
+/* Execute "bte #const5,isrc2,sbroff". */
+static void insn_bte_imm (i860s *cpustate, UINT32 insn)
+{
+ UINT32 src1val = 0;
+ UINT32 isrc2 = get_isrc2 (insn);
+ UINT32 target_addr = 0;
+ INT32 sbroff = 0;
+ int res = 0;
+
+ src1val = (insn >> 11) & 0x1f; /* 5-bit field, zero-extended. */
+
+ /* Compute the target address from the sbroff field. */
+ sbroff = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16);
+ target_addr = (INT32)cpustate->pc + 4 + (sbroff << 2);
+
+ /* Determine comparison result. */
+ res = (src1val == get_iregval (isrc2));
+
+ /* Branch routines always update the PC. */
+ if (res)
+ cpustate->pc = target_addr;
+ else
+ cpustate->pc += 4;
+
+ cpustate->pc_updated = 1;
+}
+
+
+/* Execute "btne isrc1,isrc2,sbroff". */
+static void insn_btne (i860s *cpustate, UINT32 insn)
+{
+ UINT32 src1val = 0;
+ UINT32 isrc2 = get_isrc2 (insn);
+ UINT32 target_addr = 0;
+ INT32 sbroff = 0;
+ int res = 0;
+
+ src1val = get_iregval (get_isrc1 (insn));
+
+ /* Compute the target address from the sbroff field. */
+ sbroff = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16);
+ target_addr = (INT32)cpustate->pc + 4 + (sbroff << 2);
+
+ /* Determine comparison result. */
+ res = (src1val != get_iregval (isrc2));
+
+ /* Branch routines always update the PC. */
+ if (res)
+ cpustate->pc = target_addr;
+ else
+ cpustate->pc += 4;
+
+ cpustate->pc_updated = 1;
+}
+
+
+/* Execute "btne #const5,isrc2,sbroff". */
+static void insn_btne_imm (i860s *cpustate, UINT32 insn)
+{
+ UINT32 src1val = 0;
+ UINT32 isrc2 = get_isrc2 (insn);
+ UINT32 target_addr = 0;
+ INT32 sbroff = 0;
+ int res = 0;
+
+ src1val = (insn >> 11) & 0x1f; /* 5-bit field, zero-extended. */
+
+ /* Compute the target address from the sbroff field. */
+ sbroff = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16);
+ target_addr = (INT32)cpustate->pc + 4 + (sbroff << 2);
+
+ /* Determine comparison result. */
+ res = (src1val != get_iregval (isrc2));
+
+ /* Branch routines always update the PC. */
+ if (res)
+ cpustate->pc = target_addr;
+ else
+ cpustate->pc += 4;
+
+ cpustate->pc_updated = 1;
+}
+
+
+/* Execute "bc lbroff" instruction. */
+static void insn_bc (i860s *cpustate, UINT32 insn)
+{
+ UINT32 target_addr = 0;
+ INT32 lbroff = 0;
+ int res = 0;
+
+ /* Compute the target address from the lbroff field. */
+ lbroff = sign_ext ((insn & 0x03ffffff), 26);
+ target_addr = (INT32)cpustate->pc + 4 + (lbroff << 2);
+
+ /* Determine comparison result. */
+ res = (GET_PSR_CC () == 1);
+
+ /* Branch routines always update the PC. */
+ if (res)
+ cpustate->pc = target_addr;
+ else
+ cpustate->pc += 4;
+
+ cpustate->pc_updated = 1;
+}
+
+
+/* Execute "bnc lbroff" instruction. */
+static void insn_bnc (i860s *cpustate, UINT32 insn)
+{
+ UINT32 target_addr = 0;
+ INT32 lbroff = 0;
+ int res = 0;
+
+ /* Compute the target address from the lbroff field. */
+ lbroff = sign_ext ((insn & 0x03ffffff), 26);
+ target_addr = (INT32)cpustate->pc + 4 + (lbroff << 2);
+
+ /* Determine comparison result. */
+ res = (GET_PSR_CC () == 0);
+
+ /* Branch routines always update the PC, since pc_updated is set
+ in the decode routine. */
+ if (res)
+ cpustate->pc = target_addr;
+ else
+ cpustate->pc += 4;
+
+ cpustate->pc_updated = 1;
+}
+
+
+/* Execute "bc.t lbroff" instruction. */
+static void insn_bct (i860s *cpustate, UINT32 insn)
+{
+ UINT32 target_addr = 0;
+ INT32 lbroff = 0;
+ int res = 0;
+ UINT32 orig_pc = cpustate->pc;
+
+ /* Compute the target address from the lbroff field. */
+ lbroff = sign_ext ((insn & 0x03ffffff), 26);
+ target_addr = (INT32)cpustate->pc + 4 + (lbroff << 2);
+
+ /* Determine comparison result. */
+ res = (GET_PSR_CC () == 1);
+
+ /* Careful. Unlike bla, the delay slot instruction is only executed
+ if the branch is taken. */
+ if (res)
+ {
+ /* Execute delay slot instruction. */
+ cpustate->pc += 4;
+ decode_exec (cpustate, ifetch (cpustate, orig_pc + 4), 0);
+ cpustate->pc = orig_pc;
+ if (cpustate->pending_trap)
+ {
+ cpustate->pending_trap |= TRAP_IN_DELAY_SLOT;
+ goto ab_op;
+ }
+ }
+
+ /* Since this branch is delayed, we must jump 2 instructions if
+ if isn't taken. */
+ if (res)
+ cpustate->pc = target_addr;
+ else
+ cpustate->pc += 8;
+
+ cpustate->pc_updated = 1;
+
+ ab_op:
+ ;
+}
+
+
+/* Execute "bnc.t lbroff" instruction. */
+static void insn_bnct (i860s *cpustate, UINT32 insn)
+{
+ UINT32 target_addr = 0;
+ INT32 lbroff = 0;
+ int res = 0;
+ UINT32 orig_pc = cpustate->pc;
+
+ /* Compute the target address from the lbroff field. */
+ lbroff = sign_ext ((insn & 0x03ffffff), 26);
+ target_addr = (INT32)cpustate->pc + 4 + (lbroff << 2);
+
+ /* Determine comparison result. */
+ res = (GET_PSR_CC () == 0);
+
+ /* Careful. Unlike bla, the delay slot instruction is only executed
+ if the branch is taken. */
+ if (res)
+ {
+ /* Execute delay slot instruction. */
+ cpustate->pc += 4;
+ decode_exec (cpustate, ifetch (cpustate, orig_pc + 4), 0);
+ cpustate->pc = orig_pc;
+ if (cpustate->pending_trap)
+ {
+ cpustate->pending_trap |= TRAP_IN_DELAY_SLOT;
+ goto ab_op;
+ }
+ }
+
+ /* Since this branch is delayed, we must jump 2 instructions if
+ if isn't taken. */
+ if (res)
+ cpustate->pc = target_addr;
+ else
+ cpustate->pc += 8;
+
+ cpustate->pc_updated = 1;
+
+ ab_op:
+ ;
+}
+
+
+/* Execute "call lbroff" instruction. */
+static void insn_call (i860s *cpustate, UINT32 insn)
+{
+ UINT32 target_addr = 0;
+ INT32 lbroff = 0;
+ UINT32 orig_pc = cpustate->pc;
+
+ /* Compute the target address from the lbroff field. */
+ lbroff = sign_ext ((insn & 0x03ffffff), 26);
+ target_addr = (INT32)cpustate->pc + 4 + (lbroff << 2);
+
+ /* Execute the delay slot instruction. */
+ cpustate->pc += 4;
+ decode_exec (cpustate, ifetch (cpustate, orig_pc + 4), 0);
+ cpustate->pc = orig_pc;
+ if (cpustate->pending_trap)
+ {
+ cpustate->pending_trap |= TRAP_IN_DELAY_SLOT;
+ goto ab_op;
+ }
+
+ /* Sets the return pointer (r1). */
+ set_iregval (1, orig_pc + 8);
+
+ /* New target. */
+ cpustate->pc = target_addr;
+ cpustate->pc_updated = 1;
+
+ ab_op:;
+}
+
+
+/* Execute "br lbroff". */
+static void insn_br (i860s *cpustate, UINT32 insn)
+{
+ UINT32 target_addr = 0;
+ INT32 lbroff = 0;
+ UINT32 orig_pc = cpustate->pc;
+
+ /* Compute the target address from the lbroff field. */
+ lbroff = sign_ext ((insn & 0x03ffffff), 26);
+ target_addr = (INT32)cpustate->pc + 4 + (lbroff << 2);
+
+ /* Execute the delay slot instruction. */
+ cpustate->pc += 4;
+ decode_exec (cpustate, ifetch (cpustate, orig_pc + 4), 0);
+ cpustate->pc = orig_pc;
+ if (cpustate->pending_trap)
+ {
+ cpustate->pending_trap |= TRAP_IN_DELAY_SLOT;
+ goto ab_op;
+ }
+
+ /* New target. */
+ cpustate->pc = target_addr;
+ cpustate->pc_updated = 1;
+
+ ab_op:;
+}
+
+
+/* Execute "bri isrc1ni" instruction.
+ Note: I didn't merge this code with calli because bri must do
+ a lot of flag manipulation if any trap bits are set. */
+static void insn_bri (i860s *cpustate, UINT32 insn)
+{
+ UINT32 isrc1 = get_isrc1 (insn);
+ UINT32 orig_pc = cpustate->pc;
+ UINT32 orig_psr = cpustate->cregs[CR_PSR];
+ UINT32 orig_src1_val = get_iregval (isrc1);
+
+#if 1 /* TURBO. */
+ cpustate->cregs[CR_PSR] &= ~PSR_ALL_TRAP_BITS_MASK;
+#endif
+
+ /* Execute the delay slot instruction. */
+ cpustate->pc += 4;
+ decode_exec (cpustate, ifetch (cpustate, orig_pc + 4), 0);
+ cpustate->pc = orig_pc;
+
+ /* Delay slot insn caused a trap, abort operation. */
+ if (cpustate->pending_trap)
+ {
+ cpustate->pending_trap |= TRAP_IN_DELAY_SLOT;
+ goto ab_op;
+ }
+
+ /* If any trap bits are set, we need to do the return from
+ trap work. Note, we must use the PSR value that existed
+ before the delay slot instruction was executed since the
+ delay slot instruction might itself cause a trap bit to
+ be set. */
+ if (orig_psr & PSR_ALL_TRAP_BITS_MASK)
+ {
+ /* Restore U and IM from their previous copies. */
+ SET_PSR_U (GET_PSR_PU ());
+ SET_PSR_IM (GET_PSR_PIM ());
+
+ cpustate->fir_gets_trap_addr = 0;
+ }
+
+ /* Update PC. */
+ cpustate->pc = orig_src1_val;
+
+ cpustate->pc_updated = 1;
+ ab_op:;
+}
+
+/* Execute "calli isrc1ni" instruction. */
+static void insn_calli (i860s *cpustate, UINT32 insn)
+{
+ UINT32 isrc1 = get_isrc1 (insn);
+ UINT32 orig_pc = cpustate->pc;
+ UINT32 orig_src1_val = get_iregval (isrc1);
+
+#ifdef TRACE_UNDEFINED_I860
+ /* Check for undefined behavior. */
+ if (isrc1 == 1)
+ {
+ /* Src1 must not be r1. */
+ fprintf (stderr, "WARNING: insn_calli (pc=0x%08x): isrc1 = r1 on a calli\n", cpustate->pc);
+ }
+#endif
+
+ /* Set return pointer before executing delay slot instruction. */
+ set_iregval (1, cpustate->pc + 8);
+
+ /* Execute the delay slot instruction. */
+ cpustate->pc += 4;
+ decode_exec (cpustate, ifetch (cpustate, orig_pc + 4), 0);
+ cpustate->pc = orig_pc;
+ if (cpustate->pending_trap)
+ {
+ set_iregval (1, orig_src1_val);
+ cpustate->pending_trap |= TRAP_IN_DELAY_SLOT;
+ goto ab_op;
+ }
+
+ /* Set new PC. */
+ cpustate->pc = orig_src1_val;
+ cpustate->pc_updated = 1;
+
+ ab_op:;
+}
+
+
+/* Execute "bla isrc1ni,isrc2,sbroff" instruction. */
+static void insn_bla (i860s *cpustate, UINT32 insn)
+{
+ UINT32 isrc1 = get_isrc1 (insn);
+ UINT32 isrc2 = get_isrc2 (insn);
+ UINT32 target_addr = 0;
+ INT32 sbroff = 0;
+ int lcc_tmp = 0;
+ UINT32 orig_pc = cpustate->pc;
+ UINT32 orig_isrc2val = get_iregval (isrc2);
+
+#ifdef TRACE_UNDEFINED_I860
+ /* Check for undefined behavior. */
+ if (isrc1 == isrc2)
+ {
+ /* Src1 and src2 the same is undefined i860XR behavior. */
+ fprintf (stderr, "WARNING: insn_bla (pc=0x%08x): isrc1 and isrc2 are the same (ignored)\n", cpustate->pc);
+ return;
+ }
+#endif
+
+ /* Compute the target address from the sbroff field. */
+ sbroff = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16);
+ target_addr = (INT32)cpustate->pc + 4 + (sbroff << 2);
+
+ /* Determine comparison result based on opcode. */
+ lcc_tmp = ((INT32)get_iregval (isrc2) >= -(INT32)get_iregval (isrc1));
+
+ set_iregval (isrc2, get_iregval (isrc1) + orig_isrc2val);
+
+ /* Execute the delay slot instruction. */
+ cpustate->pc += 4;
+ decode_exec (cpustate, ifetch (cpustate, orig_pc + 4), 0);
+ cpustate->pc = orig_pc;
+ if (cpustate->pending_trap)
+ {
+ cpustate->pending_trap |= TRAP_IN_DELAY_SLOT;
+ goto ab_op;
+ }
+
+ if (GET_PSR_LCC ())
+ cpustate->pc = target_addr;
+ else
+ {
+ /* Since this branch is delayed, we must jump 2 instructions if
+ if isn't taken. */
+ cpustate->pc += 8;
+ }
+ SET_PSR_LCC (lcc_tmp);
+
+ cpustate->pc_updated = 1;
+ ab_op:;
+}
+
+
+/* Execute "flush #const(isrc2)" or "flush #const(isrc2)++" instruction. */
+static void insn_flush (i860s *cpustate, UINT32 insn)
+{
+ UINT32 src1val = sign_ext (get_imm16 (insn), 16);
+ UINT32 isrc2 = get_isrc2 (insn);
+ int auto_inc = (insn & 1);
+ UINT32 eff = 0;
+
+ /* Technically, idest should be encoded as r0 because idest
+ is undefined after the instruction. We don't currently
+ check for this.
+
+ Flush D$ block at address #const+isrc2. Block is undefined
+ after. The effective address must be 16-byte aligned.
+
+ FIXME: Need to examine RB and RC and do this right.
+ */
+
+ /* Chop off lower bits of displacement to 16-byte alignment. */
+ src1val &= ~(16-1);
+ eff = src1val + get_iregval (isrc2);
+ if (auto_inc)
+ set_iregval (isrc2, eff);
+
+ /* In user mode, the flush is ignored. */
+ if (GET_PSR_U () == 0)
+ {
+ /* If line is dirty, write it to memory and invalidate.
+ NOTE: The actual dirty write is unimplemented in the MAME version
+ as we don't emulate the dcache. */
+ }
+}
+
+
+/* Execute "[p]fmul.{ss,sd,dd} fsrc1,fsrc2,fdest" instruction or
+ pfmul3.dd fsrc1,fsrc2,fdest.
+
+ The pfmul3.dd differs from pfmul.dd in that it treats the pipeline
+ as 3 stages, even though it is a double precision multiply. */
+static void insn_fmul (i860s *cpustate, UINT32 insn)
+{
+ UINT32 fsrc1 = get_fsrc1 (insn);
+ UINT32 fsrc2 = get_fsrc2 (insn);
+ UINT32 fdest = get_fdest (insn);
+ int src_prec = insn & 0x100; /* 1 = double, 0 = single. */
+ int res_prec = insn & 0x080; /* 1 = double, 0 = single. */
+ int piped = insn & 0x400; /* 1 = pipelined, 0 = scalar. */
+ double dbl_tmp_dest = 0.0;
+ float sgl_tmp_dest = 0.0;
+ double dbl_last_stage_contents = 0.0;
+ float sgl_last_stage_contents = 0.0;
+ int is_pfmul3 = insn & 0x4;
+ int num_stages = (src_prec && !is_pfmul3) ? 2 : 3;
+
+ /* Only .dd is valid for pfmul. */
+ if (is_pfmul3 && (insn & 0x180) != 0x180)
+ {
+ unrecog_opcode (cpustate->pc, insn);
+ return;
+ }
+
+ /* Check for invalid .ds combination. */
+ if ((insn & 0x180) == 0x100)
+ {
+ unrecog_opcode (cpustate->pc, insn);
+ return;
+ }
+
+ /* For pipelined version, retrieve the contents of the last stage
+ of the pipeline, whose precision is specified by the MRP bit
+ of the stage's result-status bits. Note for pfmul, the number
+ of stages is determined by the source precision of the current
+ operation. */
+ if (piped)
+ {
+ if (cpustate->M[num_stages - 1].stat.mrp)
+ dbl_last_stage_contents = cpustate->M[num_stages - 1].val.d;
+ else
+ sgl_last_stage_contents = cpustate->M[num_stages - 1].val.s;
+ }
+
+ /* Do the operation, being careful about source and result
+ precision. */
+ if (src_prec)
+ {
+ double v1 = get_fregval_d (cpustate, fsrc1);
+ double v2 = get_fregval_d (cpustate, fsrc2);
+
+ /* For pipelined mul, if fsrc2 is the same as fdest, then the last
+ stage is bypassed to fsrc2 (rather than using the value in fsrc2).
+ This bypass is not available for fsrc1, and is undefined behavior. */
+ if (0 && piped && fdest != 0 && fsrc1 == fdest)
+ v1 = dbl_last_stage_contents;
+ if (piped && fdest != 0 && fsrc2 == fdest)
+ v2 = dbl_last_stage_contents;
+
+ if (res_prec)
+ dbl_tmp_dest = v1 * v2;
+ else
+ sgl_tmp_dest = (float)(v1 * v2);
+ }
+ else
+ {
+ float v1 = get_fregval_s (cpustate, fsrc1);
+ float v2 = get_fregval_s (cpustate, fsrc2);
+
+ /* For pipelined mul, if fsrc2 is the same as fdest, then the last
+ stage is bypassed to fsrc2 (rather than using the value in fsrc2).
+ This bypass is not available for fsrc1, and is undefined behavior. */
+ if (0 && piped && fdest != 0 && fsrc1 == fdest)
+ v1 = sgl_last_stage_contents;
+ if (piped && fdest != 0 && fsrc2 == fdest)
+ v2 = sgl_last_stage_contents;
+
+ if (res_prec)
+ dbl_tmp_dest = (double)(v1 * v2);
+ else
+ sgl_tmp_dest = v1 * v2;
+ }
+
+ /* FIXME: Set result-status bits besides MRP. And copy to fsr from
+ last stage. */
+ /* FIXME: Scalar version flows through all stages. */
+ /* FIXME: Mixed precision (only weird for pfmul). */
+ if (!piped)
+ {
+ /* Scalar version writes the current calculation to the fdest
+ register, with precision specified by the R bit. */
+ if (res_prec)
+ set_fregval_d (cpustate, fdest, dbl_tmp_dest);
+ else
+ set_fregval_s (cpustate, fdest, sgl_tmp_dest);
+ }
+ else
+ {
+ /* Pipelined version writes fdest with the result from the last
+ stage of the pipeline. */
+#if 1 /* FIXME: WIP on FSR update. This may not be correct. */
+ /* Copy 3rd stage MRP to FSR. */
+ if (cpustate->M[num_stages - 2 /* 1 */].stat.mrp)
+ cpustate->cregs[CR_FSR] |= 0x10000000;
+ else
+ cpustate->cregs[CR_FSR] &= ~0x10000000;
+#endif
+
+ if (cpustate->M[num_stages - 1].stat.mrp)
+ set_fregval_d (cpustate, fdest, dbl_last_stage_contents);
+ else
+ set_fregval_s (cpustate, fdest, sgl_last_stage_contents);
+
+ /* Now advance pipeline and write current calculation to
+ first stage. */
+ if (num_stages == 3)
+ {
+ cpustate->M[2] = cpustate->M[1];
+ cpustate->M[1] = cpustate->M[0];
+ }
+ else
+ cpustate->M[1] = cpustate->M[0];
+
+ if (res_prec)
+ {
+ cpustate->M[0].val.d = dbl_tmp_dest;
+ cpustate->M[0].stat.mrp = 1;
+ }
+ else
+ {
+ cpustate->M[0].val.s = sgl_tmp_dest;
+ cpustate->M[0].stat.mrp = 0;
+ }
+ }
+}
+
+
+/* Execute "fmlow.dd fsrc1,fsrc2,fdest" instruction. */
+static void insn_fmlow (i860s *cpustate, UINT32 insn)
+{
+ UINT32 fsrc1 = get_fsrc1 (insn);
+ UINT32 fsrc2 = get_fsrc2 (insn);
+ UINT32 fdest = get_fdest (insn);
+
+ double v1 = get_fregval_d (cpustate, fsrc1);
+ double v2 = get_fregval_d (cpustate, fsrc2);
+ INT64 i1 = *(UINT64 *)&v1;
+ INT64 i2 = *(UINT64 *)&v2;
+ INT64 tmp = 0;
+
+ /* Only .dd is valid for fmlow. */
+ if ((insn & 0x180) != 0x180)
+ {
+ unrecog_opcode (cpustate->pc, insn);
+ return;
+ }
+
+ /* The lower 32-bits are obvious. What exactly goes in the upper
+ bits?
+ Technically, the upper-most 10 bits are undefined, but i'd like
+ to be undefined in the same way as the real i860 if possible. */
+
+ /* Keep lower 53 bits of multiply. */
+ tmp = i1 * i2;
+ tmp &= 0x001fffffffffffffULL;
+ tmp |= (i1 & 0x8000000000000000LL) ^ (i2 & 0x8000000000000000LL);
+ set_fregval_d (cpustate, fdest, *(double *)&tmp);
+}
+
+
+/* Execute [p]fadd.{ss,sd,dd} fsrc1,fsrc2,fdest (.ds disallowed above). */
+static void insn_fadd_sub (i860s *cpustate, UINT32 insn)
+{
+ UINT32 fsrc1 = get_fsrc1 (insn);
+ UINT32 fsrc2 = get_fsrc2 (insn);
+ UINT32 fdest = get_fdest (insn);
+ int src_prec = insn & 0x100; /* 1 = double, 0 = single. */
+ int res_prec = insn & 0x080; /* 1 = double, 0 = single. */
+ int piped = insn & 0x400; /* 1 = pipelined, 0 = scalar. */
+ int is_sub = insn & 1; /* 1 = sub, 0 = add. */
+ double dbl_tmp_dest = 0.0;
+ float sgl_tmp_dest = 0.0;
+ double dbl_last_stage_contents = 0.0;
+ float sgl_last_stage_contents = 0.0;
+
+ /* Check for invalid .ds combination. */
+ if ((insn & 0x180) == 0x100)
+ {
+ unrecog_opcode (cpustate->pc, insn);
+ return;
+ }
+
+ /* For pipelined version, retrieve the contents of the last stage
+ of the pipeline, whose precision is specified by the ARP bit
+ of the stage's result-status bits. There are always three stages
+ for pfadd/pfsub. */
+ if (piped)
+ {
+ if (cpustate->A[2].stat.arp)
+ dbl_last_stage_contents = cpustate->A[2].val.d;
+ else
+ sgl_last_stage_contents = cpustate->A[2].val.s;
+ }
+
+ /* Do the operation, being careful about source and result
+ precision. */
+ if (src_prec)
+ {
+ double v1 = get_fregval_d (cpustate, fsrc1);
+ double v2 = get_fregval_d (cpustate, fsrc2);
+
+ /* For pipelined add/sub, if fsrc1 is the same as fdest, then the last
+ stage is bypassed to fsrc1 (rather than using the value in fsrc1).
+ Likewise for fsrc2. */
+ if (piped && fdest != 0 && fsrc1 == fdest)
+ v1 = dbl_last_stage_contents;
+ if (piped && fdest != 0 && fsrc2 == fdest)
+ v2 = dbl_last_stage_contents;
+
+ if (res_prec)
+ dbl_tmp_dest = is_sub ? v1 - v2 : v1 + v2;
+ else
+ sgl_tmp_dest = is_sub ? (float)(v1 - v2) : (float)(v1 + v2);
+ }
+ else
+ {
+ float v1 = get_fregval_s (cpustate, fsrc1);
+ float v2 = get_fregval_s (cpustate, fsrc2);
+
+ /* For pipelined add/sub, if fsrc1 is the same as fdest, then the last
+ stage is bypassed to fsrc1 (rather than using the value in fsrc1).
+ Likewise for fsrc2. */
+ if (piped && fdest != 0 && fsrc1 == fdest)
+ v1 = sgl_last_stage_contents;
+ if (piped && fdest != 0 && fsrc2 == fdest)
+ v2 = sgl_last_stage_contents;
+
+ if (res_prec)
+ dbl_tmp_dest = is_sub ? (double)(v1 - v2) : (double)(v1 + v2);
+ else
+ sgl_tmp_dest = is_sub ? v1 - v2 : v1 + v2;
+ }
+
+ /* FIXME: Set result-status bits besides ARP. And copy to fsr from
+ last stage. */
+ /* FIXME: Scalar version flows through all stages. */
+ if (!piped)
+ {
+ /* Scalar version writes the current calculation to the fdest
+ register, with precision specified by the R bit. */
+ if (res_prec)
+ set_fregval_d (cpustate, fdest, dbl_tmp_dest);
+ else
+ set_fregval_s (cpustate, fdest, sgl_tmp_dest);
+ }
+ else
+ {
+ /* Pipelined version writes fdest with the result from the last
+ stage of the pipeline, with precision specified by the ARP
+ bit of the stage's result-status bits. */
+#if 1 /* FIXME: WIP on FSR update. This may not be correct. */
+ /* Copy 3rd stage ARP to FSR. */
+ if (cpustate->A[1 /* 2 */].stat.arp)
+ cpustate->cregs[CR_FSR] |= 0x20000000;
+ else
+ cpustate->cregs[CR_FSR] &= ~0x20000000;
+#endif
+ if (cpustate->A[2].stat.arp) /* 3rd (last) stage. */
+ set_fregval_d (cpustate, fdest, dbl_last_stage_contents);
+ else
+ set_fregval_s (cpustate, fdest, sgl_last_stage_contents);
+
+ /* Now advance pipeline and write current calculation to
+ first stage. */
+ cpustate->A[2] = cpustate->A[1];
+ cpustate->A[1] = cpustate->A[0];
+ if (res_prec)
+ {
+ cpustate->A[0].val.d = dbl_tmp_dest;
+ cpustate->A[0].stat.arp = 1;
+ }
+ else
+ {
+ cpustate->A[0].val.s = sgl_tmp_dest;
+ cpustate->A[0].stat.arp = 0;
+ }
+ }
+}
+
+
+/* Operand types for PFAM/PFMAM routine below. */
+enum {
+ OP_SRC1 = 0,
+ OP_SRC2 = 1,
+ OP_KI = 2,
+ OP_KR = 4,
+ OP_T = 8,
+ OP_MPIPE = 16,
+ OP_APIPE = 32,
+ FLAGM = 64 /* Indicates PFMAM uses M rather than A pipe result. */
+};
+
+/* A table to map DPC value to source operands.
+
+ The PFAM and PFMAM tables are nearly identical, and the only differences
+ are that every time PFAM uses the A pipe, PFMAM uses the M pipe instead.
+ So we only represent the PFAM table and use a special flag on any entry
+ where the PFMAM table would use the M pipe rather than the A pipe.
+ Also, entry 16 is not valid for PFMAM. */
+static const struct
+{
+ int M_unit_op1;
+ int M_unit_op2;
+ int A_unit_op1;
+ int A_unit_op2;
+ int T_loaded;
+ int K_loaded;
+} src_opers[] = {
+ /* 0000 */ { OP_KR, OP_SRC2, OP_SRC1, OP_MPIPE, 0, 0},
+ /* 0001 */ { OP_KR, OP_SRC2, OP_T, OP_MPIPE, 0, 1},
+ /* 0010 */ { OP_KR, OP_SRC2, OP_SRC1, OP_APIPE|FLAGM, 1, 0},
+ /* 0011 */ { OP_KR, OP_SRC2, OP_T, OP_APIPE|FLAGM, 1, 1},
+ /* 0100 */ { OP_KI, OP_SRC2, OP_SRC1, OP_MPIPE, 0, 0},
+ /* 0101 */ { OP_KI, OP_SRC2, OP_T, OP_MPIPE, 0, 1},
+ /* 0110 */ { OP_KI, OP_SRC2, OP_SRC1, OP_APIPE|FLAGM, 1, 0},
+ /* 0111 */ { OP_KI, OP_SRC2, OP_T, OP_APIPE|FLAGM, 1, 1},
+ /* 1000 */ { OP_KR, OP_APIPE|FLAGM, OP_SRC1, OP_SRC2, 1, 0},
+ /* 1001 */ { OP_SRC1, OP_SRC2, OP_APIPE|FLAGM, OP_MPIPE, 0, 0},
+ /* 1010 */ { OP_KR, OP_APIPE|FLAGM, OP_SRC1, OP_SRC2, 0, 0},
+ /* 1011 */ { OP_SRC1, OP_SRC2, OP_T, OP_APIPE|FLAGM, 1, 0},
+ /* 1100 */ { OP_KI, OP_APIPE|FLAGM, OP_SRC1, OP_SRC2, 1, 0},
+ /* 1101 */ { OP_SRC1, OP_SRC2, OP_T, OP_MPIPE, 0, 0},
+ /* 1110 */ { OP_KI, OP_APIPE|FLAGM, OP_SRC1, OP_SRC2, 0, 0},
+ /* 1111 */ { OP_SRC1, OP_SRC2, OP_T, OP_APIPE|FLAGM, 0, 0}
+};
+
+static float get_fval_from_optype_s (i860s *cpustate, UINT32 insn, int optype)
+{
+ float retval = 0.0;
+ UINT32 fsrc1 = get_fsrc1 (insn);
+ UINT32 fsrc2 = get_fsrc2 (insn);
+
+ optype &= ~FLAGM;
+ switch (optype)
+ {
+ case OP_SRC1:
+ retval = get_fregval_s (cpustate, fsrc1);
+ break;
+ case OP_SRC2:
+ retval = get_fregval_s (cpustate, fsrc2);
+ break;
+ case OP_KI:
+ retval = cpustate->KI.s;
+ break;
+ case OP_KR:
+ retval = cpustate->KR.s;
+ break;
+ case OP_T:
+ retval = cpustate->T.s;
+ break;
+ case OP_MPIPE:
+ /* Last stage is 3rd stage for single precision input. */
+ retval = cpustate->M[2].val.s;
+ break;
+ case OP_APIPE:
+ retval = cpustate->A[2].val.s;
+ break;
+ default:
+ assert (0);
+ }
+
+ return retval;
+}
+
+
+static double get_fval_from_optype_d (i860s *cpustate, UINT32 insn, int optype)
+{
+ double retval = 0.0;
+ UINT32 fsrc1 = get_fsrc1 (insn);
+ UINT32 fsrc2 = get_fsrc2 (insn);
+
+ optype &= ~FLAGM;
+ switch (optype)
+ {
+ case OP_SRC1:
+ retval = get_fregval_d (cpustate, fsrc1);
+ break;
+ case OP_SRC2:
+ retval = get_fregval_d (cpustate, fsrc2);
+ break;
+ case OP_KI:
+ retval = cpustate->KI.d;
+ break;
+ case OP_KR:
+ retval = cpustate->KR.d;
+ break;
+ case OP_T:
+ retval = cpustate->T.d;
+ break;
+ case OP_MPIPE:
+ /* Last stage is 2nd stage for double precision input. */
+ retval = cpustate->M[1].val.d;
+ break;
+ case OP_APIPE:
+ retval = cpustate->A[2].val.d;
+ break;
+ default:
+ assert (0);
+ }
+
+ return retval;
+}
+
+
+/* Execute pf[m]{a,s}m.{ss,sd,dd} fsrc1,fsrc2,fdest (FP dual ops).
+
+ Since these are always pipelined, the P bit is used to distinguish
+ family pfam (P=1) from family pfmam (P=0), and the lower 4 bits
+ of the extended opcode is the DPC.
+
+ Note also that the S and R bits are slightly different than normal
+ floating point operations. The S bit denotes the precision of the
+ multiplication source, while the R bit denotes the precision of
+ the addition source as well as precision of all results. */
+static void insn_dualop (i860s *cpustate, UINT32 insn)
+{
+ UINT32 fsrc1 = get_fsrc1 (insn);
+ UINT32 fsrc2 = get_fsrc2 (insn);
+ UINT32 fdest = get_fdest (insn);
+ int src_prec = insn & 0x100; /* 1 = double, 0 = single. */
+ int res_prec = insn & 0x080; /* 1 = double, 0 = single. */
+ int is_pfam = insn & 0x400; /* 1 = pfam, 0 = pfmam. */
+ int is_sub = insn & 0x10; /* 1 = pf[m]sm, 0 = pf[m]am. */
+ double dbl_tmp_dest_mul = 0.0;
+ float sgl_tmp_dest_mul = 0.0;
+ double dbl_tmp_dest_add = 0.0;
+ float sgl_tmp_dest_add = 0.0;
+ double dbl_last_Mstage_contents = 0.0;
+ float sgl_last_Mstage_contents = 0.0;
+ double dbl_last_Astage_contents = 0.0;
+ float sgl_last_Astage_contents = 0.0;
+ int num_mul_stages = src_prec ? 2 : 3;
+
+ int dpc = insn & 0xf;
+ int M_unit_op1 = src_opers[dpc].M_unit_op1;
+ int M_unit_op2 = src_opers[dpc].M_unit_op2;
+ int A_unit_op1 = src_opers[dpc].A_unit_op1;
+ int A_unit_op2 = src_opers[dpc].A_unit_op2;
+ int T_loaded = src_opers[dpc].T_loaded;
+ int K_loaded = src_opers[dpc].K_loaded;
+
+ /* Check for invalid .ds combination. */
+ if ((insn & 0x180) == 0x100)
+ {
+ unrecog_opcode (cpustate->pc, insn);
+ return;
+ }
+
+ if (is_pfam == 0)
+ {
+ /* Check for invalid DPC combination 16 for PFMAM. */
+ if (dpc == 16)
+ {
+ unrecog_opcode (cpustate->pc, insn);
+ return;
+ }
+
+ /* PFMAM table adjustments (M_unit_op1 is never a pipe stage,
+ so no adjustment made for it). */
+ M_unit_op2 = (M_unit_op2 & FLAGM) ? OP_MPIPE : M_unit_op2;
+ A_unit_op1 = (A_unit_op1 & FLAGM) ? OP_MPIPE : A_unit_op1;
+ A_unit_op2 = (A_unit_op2 & FLAGM) ? OP_MPIPE : A_unit_op2;
+ }
+
+ /* FIXME: Check for fsrc1/fdest overlap for some mul DPC combinations. */
+
+ /* Retrieve the contents of the last stage of the multiplier pipeline,
+ whose precision is specified by the MRP bit of the stage's result-
+ status bits. Note for multiply, the number of stages is determined
+ by the source precision of the current operation. */
+ if (cpustate->M[num_mul_stages - 1].stat.mrp)
+ dbl_last_Mstage_contents = cpustate->M[num_mul_stages - 1].val.d;
+ else
+ sgl_last_Mstage_contents = cpustate->M[num_mul_stages - 1].val.s;
+
+ /* Similarly, retrieve the last stage of the adder pipe. */
+ if (cpustate->A[2].stat.arp)
+ dbl_last_Astage_contents = cpustate->A[2].val.d;
+ else
+ sgl_last_Astage_contents = cpustate->A[2].val.s;
+
+ /* Do the mul operation, being careful about source and result
+ precision. */
+ if (src_prec)
+ {
+ double v1 = get_fval_from_optype_d (cpustate, insn, M_unit_op1);
+ double v2 = get_fval_from_optype_d (cpustate, insn, M_unit_op2);
+
+ /* For mul, if fsrc2 is the same as fdest, then the last stage
+ is bypassed to fsrc2 (rather than using the value in fsrc2).
+ This bypass is not available for fsrc1, and is undefined behavior. */
+ if (0 && M_unit_op1 == OP_SRC1 && fdest != 0 && fsrc1 == fdest)
+ v1 = is_pfam ? dbl_last_Astage_contents : dbl_last_Mstage_contents;
+ if (M_unit_op2 == OP_SRC2 && fdest != 0 && fsrc2 == fdest)
+ v2 = is_pfam ? dbl_last_Astage_contents : dbl_last_Mstage_contents;
+
+ if (res_prec)
+ dbl_tmp_dest_mul = v1 * v2;
+ else
+ sgl_tmp_dest_mul = (float)(v1 * v2);
+ }
+ else
+ {
+ float v1 = get_fval_from_optype_s (cpustate, insn, M_unit_op1);
+ float v2 = get_fval_from_optype_s (cpustate, insn, M_unit_op2);
+
+ /* For mul, if fsrc2 is the same as fdest, then the last stage
+ is bypassed to fsrc2 (rather than using the value in fsrc2).
+ This bypass is not available for fsrc1, and is undefined behavior. */
+ if (0 && M_unit_op1 == OP_SRC1 && fdest != 0 && fsrc1 == fdest)
+ v1 = is_pfam ? sgl_last_Astage_contents : sgl_last_Mstage_contents;
+ if (M_unit_op2 == OP_SRC2 && fdest != 0 && fsrc2 == fdest)
+ v2 = is_pfam ? sgl_last_Astage_contents : sgl_last_Mstage_contents;
+
+ if (res_prec)
+ dbl_tmp_dest_mul = (double)(v1 * v2);
+ else
+ sgl_tmp_dest_mul = v1 * v2;
+ }
+
+ /* Do the add operation, being careful about source and result
+ precision. Remember, the R bit indicates source and result precision
+ here. */
+ if (res_prec)
+ {
+ double v1 = get_fval_from_optype_d (cpustate, insn, A_unit_op1);
+ double v2 = get_fval_from_optype_d (cpustate, insn, A_unit_op2);
+
+ /* For add/sub, if fsrc1 is the same as fdest, then the last stage
+ is bypassed to fsrc1 (rather than using the value in fsrc1).
+ Likewise for fsrc2. */
+ if (A_unit_op1 == OP_SRC1 && fdest != 0 && fsrc1 == fdest)
+ v1 = is_pfam ? dbl_last_Astage_contents : dbl_last_Mstage_contents;
+ if (A_unit_op2 == OP_SRC2 && fdest != 0 && fsrc2 == fdest)
+ v2 = is_pfam ? dbl_last_Astage_contents : dbl_last_Mstage_contents;
+
+ if (res_prec)
+ dbl_tmp_dest_add = is_sub ? v1 - v2 : v1 + v2;
+ else
+ sgl_tmp_dest_add = is_sub ? (float)(v1 - v2) : (float)(v1 + v2);
+ }
+ else
+ {
+ float v1 = get_fval_from_optype_s (cpustate, insn, A_unit_op1);
+ float v2 = get_fval_from_optype_s (cpustate, insn, A_unit_op2);
+
+ /* For add/sub, if fsrc1 is the same as fdest, then the last stage
+ is bypassed to fsrc1 (rather than using the value in fsrc1).
+ Likewise for fsrc2. */
+ if (A_unit_op1 == OP_SRC1 && fdest != 0 && fsrc1 == fdest)
+ v1 = is_pfam ? sgl_last_Astage_contents : sgl_last_Mstage_contents;
+ if (A_unit_op2 == OP_SRC2 && fdest != 0 && fsrc2 == fdest)
+ v2 = is_pfam ? sgl_last_Astage_contents : sgl_last_Mstage_contents;
+
+ if (res_prec)
+ dbl_tmp_dest_add = is_sub ? (double)(v1 - v2) : (double)(v1 + v2);
+ else
+ sgl_tmp_dest_add = is_sub ? v1 - v2 : v1 + v2;
+ }
+
+ /* If necessary, load T. */
+ if (T_loaded)
+ {
+ /* T is loaded from the result of the last stage of the multiplier. */
+ if (cpustate->M[num_mul_stages - 1].stat.mrp)
+ cpustate->T.d = dbl_last_Mstage_contents;
+ else
+ cpustate->T.s = sgl_last_Mstage_contents;
+ }
+
+ /* If necessary, load KR or KI. */
+ if (K_loaded)
+ {
+ /* KI or KR is loaded from the first register input. */
+ if (M_unit_op1 == OP_KI)
+ {
+ if (src_prec)
+ cpustate->KI.d = get_fregval_d (cpustate, fsrc1);
+ else
+ cpustate->KI.s = get_fregval_s (cpustate, fsrc1);
+ }
+ else if (M_unit_op1 == OP_KR)
+ {
+ if (src_prec)
+ cpustate->KR.d = get_fregval_d (cpustate, fsrc1);
+ else
+ cpustate->KR.s = get_fregval_s (cpustate, fsrc1);
+ }
+ else
+ assert (0);
+ }
+
+ /* Now update fdest (either from adder pipe or multiplier pipe,
+ depending on whether the instruction is pfam or pfmam). */
+ if (is_pfam)
+ {
+ /* Update fdest with the result from the last stage of the
+ adder pipeline, with precision specified by the ARP
+ bit of the stage's result-status bits. */
+ if (cpustate->A[2].stat.arp)
+ set_fregval_d (cpustate, fdest, dbl_last_Astage_contents);
+ else
+ set_fregval_s (cpustate, fdest, sgl_last_Astage_contents);
+ }
+ else
+ {
+ /* Update fdest with the result from the last stage of the
+ multiplier pipeline, with precision specified by the MRP
+ bit of the stage's result-status bits. */
+ if (cpustate->M[num_mul_stages - 1].stat.mrp)
+ set_fregval_d (cpustate, fdest, dbl_last_Mstage_contents);
+ else
+ set_fregval_s (cpustate, fdest, sgl_last_Mstage_contents);
+ }
+
+ /* FIXME: Set result-status bits besides MRP. And copy to fsr from
+ last stage. */
+ /* FIXME: Mixed precision (only weird for pfmul). */
+#if 1 /* FIXME: WIP on FSR update. This may not be correct. */
+ /* Copy 3rd stage MRP to FSR. */
+ if (cpustate->M[num_mul_stages - 2 /* 1 */].stat.mrp)
+ cpustate->cregs[CR_FSR] |= 0x10000000;
+ else
+ cpustate->cregs[CR_FSR] &= ~0x10000000;
+#endif
+
+ /* Now advance multiplier pipeline and write current calculation to
+ first stage. */
+ if (num_mul_stages == 3)
+ {
+ cpustate->M[2] = cpustate->M[1];
+ cpustate->M[1] = cpustate->M[0];
+ }
+ else
+ cpustate->M[1] = cpustate->M[0];
+
+ if (res_prec)
+ {
+ cpustate->M[0].val.d = dbl_tmp_dest_mul;
+ cpustate->M[0].stat.mrp = 1;
+ }
+ else
+ {
+ cpustate->M[0].val.s = sgl_tmp_dest_mul;
+ cpustate->M[0].stat.mrp = 0;
+ }
+
+ /* FIXME: Set result-status bits besides ARP. And copy to fsr from
+ last stage. */
+#if 1 /* FIXME: WIP on FSR update. This may not be correct. */
+ /* Copy 3rd stage ARP to FSR. */
+ if (cpustate->A[1 /* 2 */].stat.arp)
+ cpustate->cregs[CR_FSR] |= 0x20000000;
+ else
+ cpustate->cregs[CR_FSR] &= ~0x20000000;
+#endif
+
+ /* Now advance adder pipeline and write current calculation to
+ first stage. */
+ cpustate->A[2] = cpustate->A[1];
+ cpustate->A[1] = cpustate->A[0];
+ if (res_prec)
+ {
+ cpustate->A[0].val.d = dbl_tmp_dest_add;
+ cpustate->A[0].stat.arp = 1;
+ }
+ else
+ {
+ cpustate->A[0].val.s = sgl_tmp_dest_add;
+ cpustate->A[0].stat.arp = 0;
+ }
+}
+
+
+/* Execute frcp.{ss,sd,dd} fsrc2,fdest (.ds disallowed above). */
+static void insn_frcp (i860s *cpustate, UINT32 insn)
+{
+ UINT32 fsrc2 = get_fsrc2 (insn);
+ UINT32 fdest = get_fdest (insn);
+ int src_prec = insn & 0x100; /* 1 = double, 0 = single. */
+ int res_prec = insn & 0x080; /* 1 = double, 0 = single. */
+
+ /* Do the operation, being careful about source and result
+ precision. */
+ if (src_prec)
+ {
+ double v = get_fregval_d (cpustate, fsrc2);
+ double res;
+ if (v == (double)0.0)
+ {
+ /* Generate source-exception trap if fsrc2 is 0. */
+ if (0 /* && GET_FSR_FTE () */)
+ {
+ SET_PSR_FT (1);
+ SET_FSR_SE (1);
+ cpustate->pending_trap = GET_FSR_FTE ();
+ }
+ /* Set fdest to INF or some other exceptional value here? */
+ }
+ else
+ {
+ /* Real i860 isn't a precise as a real divide, but this should
+ be okay. */
+ SET_FSR_SE (0);
+ *((UINT64 *)&v) &= 0xfffff00000000000ULL;
+ res = (double)1.0/v;
+ *((UINT64 *)&res) &= 0xfffff00000000000ULL;
+ if (res_prec)
+ set_fregval_d (cpustate, fdest, res);
+ else
+ set_fregval_s (cpustate, fdest, (float)res);
+ }
+ }
+ else
+ {
+ float v = get_fregval_s (cpustate, fsrc2);
+ float res;
+ if (v == 0.0)
+ {
+ /* Generate source-exception trap if fsrc2 is 0. */
+ if (0 /* GET_FSR_FTE () */)
+ {
+ SET_PSR_FT (1);
+ SET_FSR_SE (1);
+ cpustate->pending_trap = GET_FSR_FTE ();
+ }
+ /* Set fdest to INF or some other exceptional value here? */
+ }
+ else
+ {
+ /* Real i860 isn't a precise as a real divide, but this should
+ be okay. */
+ SET_FSR_SE (0);
+ *((UINT32 *)&v) &= 0xffff8000;
+ res = (float)1.0/v;
+ *((UINT32 *)&res) &= 0xffff8000;
+ if (res_prec)
+ set_fregval_d (cpustate, fdest, (double)res);
+ else
+ set_fregval_s (cpustate, fdest, res);
+ }
+ }
+}
+
+
+/* Execute frsqr.{ss,sd,dd} fsrc2,fdest (.ds disallowed above). */
+static void insn_frsqr (i860s *cpustate, UINT32 insn)
+{
+ UINT32 fsrc2 = get_fsrc2 (insn);
+ UINT32 fdest = get_fdest (insn);
+ int src_prec = insn & 0x100; /* 1 = double, 0 = single. */
+ int res_prec = insn & 0x080; /* 1 = double, 0 = single. */
+
+ /* Check for invalid .ds combination. */
+ if ((insn & 0x180) == 0x100)
+ {
+ unrecog_opcode (cpustate->pc, insn);
+ return;
+ }
+
+ /* Check for invalid .ds combination. */
+ if ((insn & 0x180) == 0x100)
+ {
+ unrecog_opcode (cpustate->pc, insn);
+ return;
+ }
+
+ /* Do the operation, being careful about source and result
+ precision. */
+ if (src_prec)
+ {
+ double v = get_fregval_d (cpustate, fsrc2);
+ double res;
+ if (v == 0.0 || v < 0.0)
+ {
+ /* Generate source-exception trap if fsrc2 is 0 or negative. */
+ if (0 /* GET_FSR_FTE () */)
+ {
+ SET_PSR_FT (1);
+ SET_FSR_SE (1);
+ cpustate->pending_trap = GET_FSR_FTE ();
+ }
+ /* Set fdest to INF or some other exceptional value here? */
+ }
+ else
+ {
+ SET_FSR_SE (0);
+ *((UINT64 *)&v) &= 0xfffff00000000000ULL;
+ res = (double)1.0/sqrt (v);
+ *((UINT64 *)&res) &= 0xfffff00000000000ULL;
+ if (res_prec)
+ set_fregval_d (cpustate, fdest, res);
+ else
+ set_fregval_s (cpustate, fdest, (float)res);
+ }
+ }
+ else
+ {
+ float v = get_fregval_s (cpustate, fsrc2);
+ float res;
+ if (v == 0.0 || v < 0.0)
+ {
+ /* Generate source-exception trap if fsrc2 is 0 or negative. */
+ if (0 /* GET_FSR_FTE () */)
+ {
+ SET_PSR_FT (1);
+ SET_FSR_SE (1);
+ cpustate->pending_trap = GET_FSR_FTE ();
+ }
+ /* Set fdest to INF or some other exceptional value here? */
+ }
+ else
+ {
+ SET_FSR_SE (0);
+ *((UINT32 *)&v) &= 0xffff8000;
+ res = (float)1.0/sqrt (v);
+ *((UINT32 *)&res) &= 0xffff8000;
+ if (res_prec)
+ set_fregval_d (cpustate, fdest, (double)res);
+ else
+ set_fregval_s (cpustate, fdest, res);
+ }
+ }
+}
+
+
+/* Execute fxfr fsrc1,idest. */
+static void insn_fxfr (i860s *cpustate, UINT32 insn)
+{
+ UINT32 fsrc1 = get_fsrc1 (insn);
+ UINT32 idest = get_idest (insn);
+ float fv = 0;
+
+ /* This is a bit-pattern transfer, not a conversion. */
+ fv = get_fregval_s (cpustate, fsrc1);
+ set_iregval (idest, *(UINT32 *)&fv);
+}
+
+
+/* Execute [p]ftrunc.{ss,sd,dd} fsrc1,idest. */
+/* FIXME: Is .ss really a valid combination? On the one hand,
+ the programmer's reference (1990) lists ftrunc.p where .p
+ is any of {ss,sd,dd}. On the other hand, a paragraph on the
+ same page states that [p]ftrunc must specify double-precision
+ results. Inconsistent.
+ Update: The vendor SVR4 assembler does not accept .ss combination,
+ so the latter sentence above appears to be the correct way. */
+static void insn_ftrunc (i860s *cpustate, UINT32 insn)
+{
+ UINT32 fsrc1 = get_fsrc1 (insn);
+ UINT32 fdest = get_fdest (insn);
+ int src_prec = insn & 0x100; /* 1 = double, 0 = single. */
+ int res_prec = insn & 0x080; /* 1 = double, 0 = single. */
+ int piped = insn & 0x400; /* 1 = pipelined, 0 = scalar. */
+
+ /* Check for invalid .ds or .ss combinations. */
+ if ((insn & 0x080) == 0)
+ {
+ unrecog_opcode (cpustate->pc, insn);
+ return;
+ }
+
+ /* Do the operation, being careful about source and result
+ precision. Operation: fdest = integer part of fsrc1 in
+ lower 32-bits. */
+ if (src_prec)
+ {
+ double v1 = get_fregval_d (cpustate, fsrc1);
+ INT32 iv = (INT32)v1;
+ /* We always write a single, since the lower 32-bits of fdest
+ get the result (and the even numbered reg is the lower). */
+ set_fregval_s (cpustate, fdest, *(float *)&iv);
+ }
+ else
+ {
+ float v1 = get_fregval_s (cpustate, fsrc1);
+ INT32 iv = (INT32)v1;
+ /* We always write a single, since the lower 32-bits of fdest
+ get the result (and the even numbered reg is the lower). */
+ set_fregval_s (cpustate, fdest, *(float *)&iv);
+ }
+
+ /* FIXME: Handle updating of pipestages for pftrunc. */
+ /* Includes looking at ARP (add result precision.) */
+ if (piped)
+ {
+ fprintf (stderr, "insn_ftrunc: FIXME: pipelined not functional yet.\n");
+ if (res_prec)
+ set_fregval_d (cpustate, fdest, 0.0);
+ else
+ set_fregval_s (cpustate, fdest, 0.0);
+ }
+}
+
+
+/* Execute [p]famov.{ss,sd,ds,dd} fsrc1,fdest. */
+static void insn_famov (i860s *cpustate, UINT32 insn)
+{
+ UINT32 fsrc1 = get_fsrc1 (insn);
+ UINT32 fdest = get_fdest (insn);
+ int src_prec = insn & 0x100; /* 1 = double, 0 = single. */
+ int res_prec = insn & 0x080; /* 1 = double, 0 = single. */
+ int piped = insn & 0x400; /* 1 = pipelined, 0 = scalar. */
+ double dbl_tmp_dest = 0.0;
+ double sgl_tmp_dest = 0.0;
+
+ /* Do the operation, being careful about source and result
+ precision. */
+ if (src_prec)
+ {
+ double v1 = get_fregval_d (cpustate, fsrc1);
+ if (res_prec)
+ dbl_tmp_dest = v1;
+ else
+ sgl_tmp_dest = (float)v1;
+ }
+ else
+ {
+ float v1 = get_fregval_s (cpustate, fsrc1);
+ if (res_prec)
+ dbl_tmp_dest = (double)v1;
+ else
+ sgl_tmp_dest = v1;
+ }
+
+ /* FIXME: Set result-status bits besides ARP. And copy to fsr from
+ last stage. */
+ /* FIXME: Scalar version flows through all stages. */
+ if (!piped)
+ {
+ /* Scalar version writes the current calculation to the fdest
+ register, with precision specified by the R bit. */
+ if (res_prec)
+ set_fregval_d (cpustate, fdest, dbl_tmp_dest);
+ else
+ set_fregval_s (cpustate, fdest, sgl_tmp_dest);
+ }
+ else
+ {
+ /* Pipelined version writes fdest with the result from the last
+ stage of the pipeline, with precision specified by the ARP
+ bit of the stage's result-status bits. */
+#if 1 /* FIXME: WIP on FSR update. This may not be correct. */
+ /* Copy 3rd stage ARP to FSR. */
+ if (cpustate->A[1 /* 2 */].stat.arp)
+ cpustate->cregs[CR_FSR] |= 0x20000000;
+ else
+ cpustate->cregs[CR_FSR] &= ~0x20000000;
+#endif
+ if (cpustate->A[2].stat.arp) /* 3rd (last) stage. */
+ set_fregval_d (cpustate, fdest, cpustate->A[2].val.d);
+ else
+ set_fregval_s (cpustate, fdest, cpustate->A[2].val.s);
+
+ /* Now advance pipeline and write current calculation to
+ first stage. */
+ cpustate->A[2] = cpustate->A[1];
+ cpustate->A[1] = cpustate->A[0];
+ if (res_prec)
+ {
+ cpustate->A[0].val.d = dbl_tmp_dest;
+ cpustate->A[0].stat.arp = 1;
+ }
+ else
+ {
+ cpustate->A[0].val.s = sgl_tmp_dest;
+ cpustate->A[0].stat.arp = 0;
+ }
+ }
+}
+
+
+/* Execute [p]fiadd/sub.{ss,dd} fsrc1,fsrc2,fdest. */
+static void insn_fiadd_sub (i860s *cpustate, UINT32 insn)
+{
+ UINT32 fsrc1 = get_fsrc1 (insn);
+ UINT32 fsrc2 = get_fsrc2 (insn);
+ UINT32 fdest = get_fdest (insn);
+ int src_prec = insn & 0x100; /* 1 = double, 0 = single. */
+ int res_prec = insn & 0x080; /* 1 = double, 0 = single. */
+ int piped = insn & 0x400; /* 1 = pipelined, 0 = scalar. */
+ int is_sub = insn & 0x4; /* 1 = sub, 0 = add. */
+ double dbl_tmp_dest = 0.0;
+ float sgl_tmp_dest = 0.0;
+
+ /* Check for invalid .ds and .sd combinations. */
+ if ((insn & 0x180) == 0x100
+ || (insn & 0x180) == 0x080)
+ {
+ unrecog_opcode (cpustate->pc, insn);
+ return;
+ }
+
+ /* Do the operation, being careful about source and result
+ precision. */
+ if (src_prec)
+ {
+ double v1 = get_fregval_d (cpustate, fsrc1);
+ double v2 = get_fregval_d (cpustate, fsrc2);
+ UINT64 iv1 = *(UINT64 *)&v1;
+ UINT64 iv2 = *(UINT64 *)&v2;
+ UINT64 r;
+ if (is_sub)
+ r = iv1 - iv2;
+ else
+ r = iv1 + iv2;
+ if (res_prec)
+ dbl_tmp_dest = *(double *)&r;
+ else
+ assert (0); /* .ds not allowed. */
+ }
+ else
+ {
+ float v1 = get_fregval_s (cpustate, fsrc1);
+ float v2 = get_fregval_s (cpustate, fsrc2);
+ UINT64 iv1 = (UINT64)(*(UINT32 *)&v1);
+ UINT64 iv2 = (UINT64)(*(UINT32 *)&v2);
+ UINT32 r;
+ if (is_sub)
+ r = (UINT32)(iv1 - iv2);
+ else
+ r = (UINT32)(iv1 + iv2);
+ if (res_prec)
+ assert (0); /* .sd not allowed. */
+ else
+ sgl_tmp_dest = *(float *)&r;
+ }
+
+ /* FIXME: Copy result-status bit IRP to fsr from last stage. */
+ /* FIXME: Scalar version flows through all stages. */
+ if (!piped)
+ {
+ /* Scalar version writes the current calculation to the fdest
+ register, with precision specified by the R bit. */
+ if (res_prec)
+ set_fregval_d (cpustate, fdest, dbl_tmp_dest);
+ else
+ set_fregval_s (cpustate, fdest, sgl_tmp_dest);
+ }
+ else
+ {
+ /* Pipelined version writes fdest with the result from the last
+ stage of the pipeline, with precision specified by the IRP
+ bit of the stage's result-status bits. */
+#if 1 /* FIXME: WIP on FSR update. This may not be correct. */
+ /* Copy stage IRP to FSR. */
+ if (res_prec)
+ cpustate->cregs[CR_FSR] |= 0x08000000;
+ else
+ cpustate->cregs[CR_FSR] &= ~0x08000000;
+#endif
+ if (cpustate->G.stat.irp) /* 1st (and last) stage. */
+ set_fregval_d (cpustate, fdest, cpustate->G.val.d);
+ else
+ set_fregval_s (cpustate, fdest, cpustate->G.val.s);
+
+ /* Now write current calculation to first and only stage. */
+ if (res_prec)
+ {
+ cpustate->G.val.d = dbl_tmp_dest;
+ cpustate->G.stat.irp = 1;
+ }
+ else
+ {
+ cpustate->G.val.s = sgl_tmp_dest;
+ cpustate->G.stat.irp = 0;
+ }
+ }
+}
+
+
+/* Execute pf{gt,le,eq}.{ss,dd} fsrc1,fsrc2,fdest.
+ Opcode pfgt has R bit cleared; pfle has R bit set. */
+static void insn_fcmp (i860s *cpustate, UINT32 insn)
+{
+ UINT32 fsrc1 = get_fsrc1 (insn);
+ UINT32 fsrc2 = get_fsrc2 (insn);
+ UINT32 fdest = get_fdest (insn);
+ int src_prec = insn & 0x100; /* 1 = double, 0 = single. */
+ double dbl_tmp_dest = 0.0;
+ double sgl_tmp_dest = 0.0;
+ /* int is_eq = insn & 1; */
+ int is_gt = ((insn & 0x81) == 0x00);
+ int is_le = ((insn & 0x81) == 0x80);
+
+ /* Do the operation. Source and result precision must be the same.
+ pfgt: CC set if fsrc1 > fsrc2, else cleared.
+ pfle: CC cleared if fsrc1 <= fsrc2, else set.
+ pfeq: CC set if fsrc1 = fsrc2, else cleared.
+
+ Note that the compares write an undefined (but non-exceptional)
+ result into the first stage of the adder pipeline. We'll model
+ this by just pushing in dbl_ or sgl_tmp_dest which equal 0.0. */
+ if (src_prec)
+ {
+ double v1 = get_fregval_d (cpustate, fsrc1);
+ double v2 = get_fregval_d (cpustate, fsrc2);
+ if (is_gt) /* gt. */
+ SET_PSR_CC (v1 > v2 ? 1 : 0);
+ else if (is_le) /* le. */
+ SET_PSR_CC (v1 <= v2 ? 0 : 1);
+ else /* eq. */
+ SET_PSR_CC (v1 == v2 ? 1 : 0);
+ }
+ else
+ {
+ float v1 = get_fregval_s (cpustate, fsrc1);
+ float v2 = get_fregval_s (cpustate, fsrc2);
+ if (is_gt) /* gt. */
+ SET_PSR_CC (v1 > v2 ? 1 : 0);
+ else if (is_le) /* le. */
+ SET_PSR_CC (v1 <= v2 ? 0 : 1);
+ else /* eq. */
+ SET_PSR_CC (v1 == v2 ? 1 : 0);
+ }
+
+ /* FIXME: Set result-status bits besides ARP. And copy to fsr from
+ last stage. */
+ /* These write fdest with the result from the last
+ stage of the pipeline, with precision specified by the ARP
+ bit of the stage's result-status bits. */
+#if 1 /* FIXME: WIP on FSR update. This may not be correct. */
+ /* Copy 3rd stage ARP to FSR. */
+ if (cpustate->A[1 /* 2 */].stat.arp)
+ cpustate->cregs[CR_FSR] |= 0x20000000;
+ else
+ cpustate->cregs[CR_FSR] &= ~0x20000000;
+#endif
+ if (cpustate->A[2].stat.arp) /* 3rd (last) stage. */
+ set_fregval_d (cpustate, fdest, cpustate->A[2].val.d);
+ else
+ set_fregval_s (cpustate, fdest, cpustate->A[2].val.s);
+
+ /* Now advance pipeline and write current calculation to
+ first stage. */
+ cpustate->A[2] = cpustate->A[1];
+ cpustate->A[1] = cpustate->A[0];
+ if (src_prec)
+ {
+ cpustate->A[0].val.d = dbl_tmp_dest;
+ cpustate->A[0].stat.arp = 1;
+ }
+ else
+ {
+ cpustate->A[0].val.s = sgl_tmp_dest;
+ cpustate->A[0].stat.arp = 0;
+ }
+}
+
+
+/* Execute [p]fzchk{l,s} fsrc1,fsrc2,fdest.
+ The fzchk instructions have S and R bits set. */
+static void insn_fzchk (i860s *cpustate, UINT32 insn)
+{
+ UINT32 fsrc1 = get_fsrc1 (insn);
+ UINT32 fsrc2 = get_fsrc2 (insn);
+ UINT32 fdest = get_fdest (insn);
+ int piped = insn & 0x400; /* 1 = pipelined, 0 = scalar. */
+ int is_fzchks = insn & 8; /* 1 = fzchks, 0 = fzchkl. */
+ double dbl_tmp_dest = 0.0;
+ int i;
+ double v1 = get_fregval_d (cpustate, fsrc1);
+ double v2 = get_fregval_d (cpustate, fsrc2);
+ UINT64 iv1 = *(UINT64 *)&v1;
+ UINT64 iv2 = *(UINT64 *)&v2;
+ UINT64 r = 0;
+ char pm = GET_PSR_PM ();
+
+ /* Check for S and R bits set. */
+ if ((insn & 0x180) != 0x180)
+ {
+ unrecog_opcode (cpustate->pc, insn);
+ return;
+ }
+
+ /* Do the operation. The fzchks version operates in parallel on
+ four 16-bit pixels, while the fzchkl operates on two 32-bit
+ pixels (pixels are unsigned ordinals in this context). */
+ if (is_fzchks)
+ {
+ pm = (pm >> 4) & 0x0f;
+ for (i = 3; i >= 0; i--)
+ {
+ UINT16 ps1 = (iv1 >> (i * 16)) & 0xffff;
+ UINT16 ps2 = (iv2 >> (i * 16)) & 0xffff;
+ if (ps2 <= ps1)
+ {
+ r |= ((UINT64)ps2 << (i * 16));
+ pm |= (1 << (7 - (3 - i)));
+ }
+ else
+ {
+ r |= ((UINT64)ps1 << (i * 16));
+ pm &= ~(1 << (7 - (3 - i)));
+ }
+ }
+ }
+ else
+ {
+ pm = (pm >> 2) & 0x3f;
+ for (i = 1; i >= 0; i--)
+ {
+ UINT32 ps1 = (iv1 >> (i * 32)) & 0xffffffff;
+ UINT32 ps2 = (iv2 >> (i * 32)) & 0xffffffff;
+ if (ps2 <= ps1)
+ {
+ r |= ((UINT64)ps2 << (i * 32));
+ pm |= (1 << (7 - (1 - i)));
+ }
+ else
+ {
+ r |= ((UINT64)ps1 << (i * 32));
+ pm &= ~(1 << (7 - (1 - i)));
+ }
+ }
+ }
+
+ dbl_tmp_dest = *(double *)&r;
+ SET_PSR_PM (pm);
+ cpustate->merge = 0;
+
+ /* FIXME: Copy result-status bit IRP to fsr from last stage. */
+ /* FIXME: Scalar version flows through all stages. */
+ if (!piped)
+ {
+ /* Scalar version writes the current calculation to the fdest
+ register, always with double precision. */
+ set_fregval_d (cpustate, fdest, dbl_tmp_dest);
+ }
+ else
+ {
+ /* Pipelined version writes fdest with the result from the last
+ stage of the pipeline, with precision specified by the IRP
+ bit of the stage's result-status bits. */
+ if (cpustate->G.stat.irp) /* 1st (and last) stage. */
+ set_fregval_d (cpustate, fdest, cpustate->G.val.d);
+ else
+ set_fregval_s (cpustate, fdest, cpustate->G.val.s);
+
+ /* Now write current calculation to first and only stage. */
+ cpustate->G.val.d = dbl_tmp_dest;
+ cpustate->G.stat.irp = 1;
+ }
+}
+
+
+/* Execute [p]form.dd fsrc1,fdest.
+ The form.dd instructions have S and R bits set. */
+static void insn_form (i860s *cpustate, UINT32 insn)
+{
+ UINT32 fsrc1 = get_fsrc1 (insn);
+ UINT32 fdest = get_fdest (insn);
+ int piped = insn & 0x400; /* 1 = pipelined, 0 = scalar. */
+ double dbl_tmp_dest = 0.0;
+ double v1 = get_fregval_d (cpustate, fsrc1);
+ UINT64 iv1 = *(UINT64 *)&v1;
+
+ /* Check for S and R bits set. */
+ if ((insn & 0x180) != 0x180)
+ {
+ unrecog_opcode (cpustate->pc, insn);
+ return;
+ }
+
+ iv1 |= cpustate->merge;
+ dbl_tmp_dest = *(double *)&iv1;
+ cpustate->merge = 0;
+
+ /* FIXME: Copy result-status bit IRP to fsr from last stage. */
+ /* FIXME: Scalar version flows through all stages. */
+ if (!piped)
+ {
+ /* Scalar version writes the current calculation to the fdest
+ register, always with double precision. */
+ set_fregval_d (cpustate, fdest, dbl_tmp_dest);
+ }
+ else
+ {
+ /* Pipelined version writes fdest with the result from the last
+ stage of the pipeline, with precision specified by the IRP
+ bit of the stage's result-status bits. */
+ if (cpustate->G.stat.irp) /* 1st (and last) stage. */
+ set_fregval_d (cpustate, fdest, cpustate->G.val.d);
+ else
+ set_fregval_s (cpustate, fdest, cpustate->G.val.s);
+
+ /* Now write current calculation to first and only stage. */
+ cpustate->G.val.d = dbl_tmp_dest;
+ cpustate->G.stat.irp = 1;
+ }
+}
+
+
+/* Execute [p]faddp fsrc1,fsrc2,fdest. */
+static void insn_faddp (i860s *cpustate, UINT32 insn)
+{
+ UINT32 fsrc1 = get_fsrc1 (insn);
+ UINT32 fsrc2 = get_fsrc2 (insn);
+ UINT32 fdest = get_fdest (insn);
+ int piped = insn & 0x400; /* 1 = pipelined, 0 = scalar. */
+ double dbl_tmp_dest = 0.0;
+ double v1 = get_fregval_d (cpustate, fsrc1);
+ double v2 = get_fregval_d (cpustate, fsrc2);
+ UINT64 iv1 = *(UINT64 *)&v1;
+ UINT64 iv2 = *(UINT64 *)&v2;
+ UINT64 r = 0;
+ int ps = GET_PSR_PS ();
+
+ r = iv1 + iv2;
+ dbl_tmp_dest = *(double *)&r;
+
+ /* Update the merge register depending on the pixel size.
+ PS: 0 = 8 bits, 1 = 16 bits, 2 = 32-bits. */
+ if (ps == 0)
+ {
+ cpustate->merge = ((cpustate->merge >> 8) & ~0xff00ff00ff00ff00ULL);
+ cpustate->merge |= (r & 0xff00ff00ff00ff00ULL);
+ }
+ else if (ps == 1)
+ {
+ cpustate->merge = ((cpustate->merge >> 6) & ~0xfc00fc00fc00fc00ULL);
+ cpustate->merge |= (r & 0xfc00fc00fc00fc00ULL);
+ }
+ else if (ps == 2)
+ {
+ cpustate->merge = ((cpustate->merge >> 8) & ~0xff000000ff000000ULL);
+ cpustate->merge |= (r & 0xff000000ff000000ULL);
+ }
+#ifdef TRACE_UNDEFINED_I860
+ else
+ fprintf (stderr, "insn_faddp: Undefined i860XR behavior, invalid value %d for pixel size.\n", ps);
+#endif
+
+ /* FIXME: Copy result-status bit IRP to fsr from last stage. */
+ /* FIXME: Scalar version flows through all stages. */
+ if (!piped)
+ {
+ /* Scalar version writes the current calculation to the fdest
+ register, always with double precision. */
+ set_fregval_d (cpustate, fdest, dbl_tmp_dest);
+ }
+ else
+ {
+ /* Pipelined version writes fdest with the result from the last
+ stage of the pipeline, with precision specified by the IRP
+ bit of the stage's result-status bits. */
+ if (cpustate->G.stat.irp) /* 1st (and last) stage. */
+ set_fregval_d (cpustate, fdest, cpustate->G.val.d);
+ else
+ set_fregval_s (cpustate, fdest, cpustate->G.val.s);
+
+ /* Now write current calculation to first and only stage. */
+ cpustate->G.val.d = dbl_tmp_dest;
+ cpustate->G.stat.irp = 1;
+ }
+}
+
+
+/* Execute [p]faddz fsrc1,fsrc2,fdest. */
+static void insn_faddz (i860s *cpustate, UINT32 insn)
+{
+ UINT32 fsrc1 = get_fsrc1 (insn);
+ UINT32 fsrc2 = get_fsrc2 (insn);
+ UINT32 fdest = get_fdest (insn);
+ int piped = insn & 0x400; /* 1 = pipelined, 0 = scalar. */
+ double dbl_tmp_dest = 0.0;
+ double v1 = get_fregval_d (cpustate, fsrc1);
+ double v2 = get_fregval_d (cpustate, fsrc2);
+ UINT64 iv1 = *(UINT64 *)&v1;
+ UINT64 iv2 = *(UINT64 *)&v2;
+ UINT64 r = 0;
+
+ r = iv1 + iv2;
+ dbl_tmp_dest = *(double *)&r;
+
+ /* Update the merge register depending on the pixel size. */
+ cpustate->merge = ((cpustate->merge >> 16) & ~0xffff0000ffff0000ULL);
+ cpustate->merge |= (r & 0xffff0000ffff0000ULL);
+
+ /* FIXME: Copy result-status bit IRP to fsr from last stage. */
+ /* FIXME: Scalar version flows through all stages. */
+ if (!piped)
+ {
+ /* Scalar version writes the current calculation to the fdest
+ register, always with double precision. */
+ set_fregval_d (cpustate, fdest, dbl_tmp_dest);
+ }
+ else
+ {
+ /* Pipelined version writes fdest with the result from the last
+ stage of the pipeline, with precision specified by the IRP
+ bit of the stage's result-status bits. */
+ if (cpustate->G.stat.irp) /* 1st (and last) stage. */
+ set_fregval_d (cpustate, fdest, cpustate->G.val.d);
+ else
+ set_fregval_s (cpustate, fdest, cpustate->G.val.s);
+
+ /* Now write current calculation to first and only stage. */
+ cpustate->G.val.d = dbl_tmp_dest;
+ cpustate->G.stat.irp = 1;
+ }
+}
+
+
+/* Flags for the decode table. */
+enum {
+ DEC_MORE = 1, /* More decoding necessary. */
+ DEC_DECODED = 2 /* Fully decoded, go. */
+};
+
+
+typedef struct {
+ /* Execute function for this opcode. */
+ void (*insn_exec)(i860s *, UINT32);
+
+ /* Flags for this opcode. */
+ char flags;
+} decode_tbl_t;
+
+
+/* First-level decode table (i.e., for the 6 primary opcode bits). */
+static const decode_tbl_t decode_tbl[64] = {
+ /* A slight bit of decoding for loads and stores is done in the
+ execution routines (operand size and addressing mode), which
+ is why their respective entries are identical. */
+ { insn_ldx, DEC_DECODED}, /* ld.b isrc1(isrc2),idest. */
+ { insn_ldx, DEC_DECODED}, /* ld.b #const(isrc2),idest. */
+ { insn_ixfr, DEC_DECODED}, /* ixfr isrc1ni,fdest. */
+ { insn_stx, DEC_DECODED}, /* st.b isrc1ni,#const(isrc2). */
+ { insn_ldx, DEC_DECODED}, /* ld.{s,l} isrc1(isrc2),idest. */
+ { insn_ldx, DEC_DECODED}, /* ld.{s,l} #const(isrc2),idest. */
+ { 0, 0},
+ { insn_stx, DEC_DECODED}, /* st.{s,l} isrc1ni,#const(isrc2),idest.*/
+ { insn_fldy, DEC_DECODED}, /* fld.{l,d,q} isrc1(isrc2)[++],fdest. */
+ { insn_fldy, DEC_DECODED}, /* fld.{l,d,q} #const(isrc2)[++],fdest. */
+ { insn_fsty, DEC_DECODED}, /* fst.{l,d,q} fdest,isrc1(isrc2)[++] */
+ { insn_fsty, DEC_DECODED}, /* fst.{l,d,q} fdest,#const(isrc2)[++] */
+ { insn_ld_ctrl, DEC_DECODED}, /* ld.c csrc2,idest. */
+ { insn_flush, DEC_DECODED}, /* flush #const(isrc2) (or autoinc). */
+ { insn_st_ctrl, DEC_DECODED}, /* st.c isrc1,csrc2. */
+ { insn_pstd, DEC_DECODED}, /* pst.d fdest,#const(isrc2)[++]. */
+ { insn_bri, DEC_DECODED}, /* bri isrc1ni. */
+ { insn_trap, DEC_DECODED}, /* trap isrc1ni,isrc2,idest. */
+ { 0, DEC_MORE}, /* FP ESCAPE FORMAT, more decode. */
+ { 0, DEC_MORE}, /* CORE ESCAPE FORMAT, more decode. */
+ { insn_btne, DEC_DECODED}, /* btne isrc1,isrc2,sbroff. */
+ { insn_btne_imm, DEC_DECODED}, /* btne #const,isrc2,sbroff. */
+ { insn_bte, DEC_DECODED}, /* bte isrc1,isrc2,sbroff. */
+ { insn_bte_imm, DEC_DECODED}, /* bte #const5,isrc2,idest. */
+ { insn_fldy, DEC_DECODED}, /* pfld.{l,d,q} isrc1(isrc2)[++],fdest.*/
+ { insn_fldy, DEC_DECODED}, /* pfld.{l,d,q} #const(isrc2)[++],fdest.*/
+ { insn_br, DEC_DECODED}, /* br lbroff. */
+ { insn_call, DEC_DECODED}, /* call lbroff . */
+ { insn_bc, DEC_DECODED}, /* bc lbroff. */
+ { insn_bct, DEC_DECODED}, /* bc.t lbroff. */
+ { insn_bnc, DEC_DECODED}, /* bnc lbroff. */
+ { insn_bnct, DEC_DECODED}, /* bnc.t lbroff. */
+ { insn_addu, DEC_DECODED}, /* addu isrc1,isrc2,idest. */
+ { insn_addu_imm, DEC_DECODED}, /* addu #const,isrc2,idest. */
+ { insn_subu, DEC_DECODED}, /* subu isrc1,isrc2,idest. */
+ { insn_subu_imm, DEC_DECODED}, /* subu #const,isrc2,idest. */
+ { insn_adds, DEC_DECODED}, /* adds isrc1,isrc2,idest. */
+ { insn_adds_imm, DEC_DECODED}, /* adds #const,isrc2,idest. */
+ { insn_subs, DEC_DECODED}, /* subs isrc1,isrc2,idest. */
+ { insn_subs_imm, DEC_DECODED}, /* subs #const,isrc2,idest. */
+ { insn_shl, DEC_DECODED}, /* shl isrc1,isrc2,idest. */
+ { insn_shl_imm, DEC_DECODED}, /* shl #const,isrc2,idest. */
+ { insn_shr, DEC_DECODED}, /* shr isrc1,isrc2,idest. */
+ { insn_shr_imm, DEC_DECODED}, /* shr #const,isrc2,idest. */
+ { insn_shrd, DEC_DECODED}, /* shrd isrc1ni,isrc2,idest. */
+ { insn_bla, DEC_DECODED}, /* bla isrc1ni,isrc2,sbroff. */
+ { insn_shra, DEC_DECODED}, /* shra isrc1,isrc2,idest. */
+ { insn_shra_imm, DEC_DECODED}, /* shra #const,isrc2,idest. */
+ { insn_and, DEC_DECODED}, /* and isrc1,isrc2,idest. */
+ { insn_and_imm, DEC_DECODED}, /* and #const,isrc2,idest. */
+ { 0, 0},
+ { insn_andh_imm, DEC_DECODED}, /* andh #const,isrc2,idest. */
+ { insn_andnot, DEC_DECODED}, /* andnot isrc1,isrc2,idest. */
+ { insn_andnot_imm, DEC_DECODED}, /* andnot #const,isrc2,idest. */
+ { 0, 0},
+ { insn_andnoth_imm, DEC_DECODED}, /* andnoth #const,isrc2,idest. */
+ { insn_or, DEC_DECODED}, /* or isrc1,isrc2,idest. */
+ { insn_or_imm, DEC_DECODED}, /* or #const,isrc2,idest. */
+ { 0, 0},
+ { insn_orh_imm, DEC_DECODED}, /* orh #const,isrc2,idest. */
+ { insn_xor, DEC_DECODED}, /* xor isrc1,isrc2,idest. */
+ { insn_xor_imm, DEC_DECODED}, /* xor #const,isrc2,idest. */
+ { 0, 0},
+ { insn_xorh_imm, DEC_DECODED}, /* xorh #const,isrc2,idest. */
+};
+
+
+/* Second-level decode table (i.e., for the 3 core escape opcode bits). */
+static const decode_tbl_t core_esc_decode_tbl[8] = {
+ { 0, 0},
+ { 0, 0}, /* lock (FIXME: unimplemented). */
+ { insn_calli, DEC_DECODED}, /* calli isrc1ni. */
+ { 0, 0},
+ { insn_intovr, DEC_DECODED}, /* intovr. */
+ { 0, 0},
+ { 0, 0},
+ { 0, 0}, /* unlock (FIXME: unimplemented). */
+};
+
+
+/* Second-level decode table (i.e., for the 7 FP extended opcode bits). */
+static const decode_tbl_t fp_decode_tbl[128] = {
+ /* Floating point instructions. The least significant 7 bits are
+ the (extended) opcode and bits 10:7 are P,D,S,R respectively
+ ([p]ipelined, [d]ual, [s]ource prec., [r]esult prec.).
+ For some operations, I defer decoding the P,S,R bits to the
+ emulation routine for them. */
+ { insn_dualop, DEC_DECODED}, /* 0x00 pf[m]am */
+ { insn_dualop, DEC_DECODED}, /* 0x01 pf[m]am */
+ { insn_dualop, DEC_DECODED}, /* 0x02 pf[m]am */
+ { insn_dualop, DEC_DECODED}, /* 0x03 pf[m]am */
+ { insn_dualop, DEC_DECODED}, /* 0x04 pf[m]am */
+ { insn_dualop, DEC_DECODED}, /* 0x05 pf[m]am */
+ { insn_dualop, DEC_DECODED}, /* 0x06 pf[m]am */
+ { insn_dualop, DEC_DECODED}, /* 0x07 pf[m]am */
+ { insn_dualop, DEC_DECODED}, /* 0x08 pf[m]am */
+ { insn_dualop, DEC_DECODED}, /* 0x09 pf[m]am */
+ { insn_dualop, DEC_DECODED}, /* 0x0A pf[m]am */
+ { insn_dualop, DEC_DECODED}, /* 0x0B pf[m]am */
+ { insn_dualop, DEC_DECODED}, /* 0x0C pf[m]am */
+ { insn_dualop, DEC_DECODED}, /* 0x0D pf[m]am */
+ { insn_dualop, DEC_DECODED}, /* 0x0E pf[m]am */
+ { insn_dualop, DEC_DECODED}, /* 0x0F pf[m]am */
+ { insn_dualop, DEC_DECODED}, /* 0x10 pf[m]sm */
+ { insn_dualop, DEC_DECODED}, /* 0x11 pf[m]sm */
+ { insn_dualop, DEC_DECODED}, /* 0x12 pf[m]sm */
+ { insn_dualop, DEC_DECODED}, /* 0x13 pf[m]sm */
+ { insn_dualop, DEC_DECODED}, /* 0x14 pf[m]sm */
+ { insn_dualop, DEC_DECODED}, /* 0x15 pf[m]sm */
+ { insn_dualop, DEC_DECODED}, /* 0x16 pf[m]sm */
+ { insn_dualop, DEC_DECODED}, /* 0x17 pf[m]sm */
+ { insn_dualop, DEC_DECODED}, /* 0x18 pf[m]sm */
+ { insn_dualop, DEC_DECODED}, /* 0x19 pf[m]sm */
+ { insn_dualop, DEC_DECODED}, /* 0x1A pf[m]sm */
+ { insn_dualop, DEC_DECODED}, /* 0x1B pf[m]sm */
+ { insn_dualop, DEC_DECODED}, /* 0x1C pf[m]sm */
+ { insn_dualop, DEC_DECODED}, /* 0x1D pf[m]sm */
+ { insn_dualop, DEC_DECODED}, /* 0x1E pf[m]sm */
+ { insn_dualop, DEC_DECODED}, /* 0x1F pf[m]sm */
+ { insn_fmul, DEC_DECODED}, /* 0x20 [p]fmul */
+ { insn_fmlow, DEC_DECODED}, /* 0x21 fmlow.dd */
+ { insn_frcp, DEC_DECODED}, /* 0x22 frcp.{ss,sd,dd} */
+ { insn_frsqr, DEC_DECODED}, /* 0x23 frsqr.{ss,sd,dd} */
+ { insn_fmul, DEC_DECODED}, /* 0x24 pfmul3.dd */
+ { 0, 0}, /* 0x25 */
+ { 0, 0}, /* 0x26 */
+ { 0, 0}, /* 0x27 */
+ { 0, 0}, /* 0x28 */
+ { 0, 0}, /* 0x29 */
+ { 0, 0}, /* 0x2A */
+ { 0, 0}, /* 0x2B */
+ { 0, 0}, /* 0x2C */
+ { 0, 0}, /* 0x2D */
+ { 0, 0}, /* 0x2E */
+ { 0, 0}, /* 0x2F */
+ { insn_fadd_sub, DEC_DECODED}, /* 0x30, [p]fadd.{ss,sd,dd} */
+ { insn_fadd_sub, DEC_DECODED}, /* 0x31, [p]fsub.{ss,sd,dd} */
+ { 0, 0}, /* 0x32, [p]fix.{ss,sd,dd} FIXME: nyi. */
+ { insn_famov, DEC_DECODED}, /* 0x33, [p]famov.{ss,sd,ds,dd} */
+ { insn_fcmp, DEC_DECODED}, /* 0x34, pf{gt,le}.{ss,dd} */
+ { insn_fcmp, DEC_DECODED}, /* 0x35, pfeq.{ss,dd} */
+ { 0, 0}, /* 0x36 */
+ { 0, 0}, /* 0x37 */
+ { 0, 0}, /* 0x38 */
+ { 0, 0}, /* 0x39 */
+ { insn_ftrunc, DEC_DECODED}, /* 0x3A, [p]ftrunc.{ss,sd,dd} */
+ { 0, 0}, /* 0x3B */
+ { 0, 0}, /* 0x3C */
+ { 0, 0}, /* 0x3D */
+ { 0, 0}, /* 0x3E */
+ { 0, 0}, /* 0x3F */
+ { insn_fxfr, DEC_DECODED}, /* 0x40, fxfr */
+ { 0, 0}, /* 0x41 */
+ { 0, 0}, /* 0x42 */
+ { 0, 0}, /* 0x43 */
+ { 0, 0}, /* 0x44 */
+ { 0, 0}, /* 0x45 */
+ { 0, 0}, /* 0x46 */
+ { 0, 0}, /* 0x47 */
+ { 0, 0}, /* 0x48 */
+ { insn_fiadd_sub, DEC_DECODED}, /* 0x49, [p]fiadd.{ss,dd} */
+ { 0, 0}, /* 0x4A */
+ { 0, 0}, /* 0x4B */
+ { 0, 0}, /* 0x4C */
+ { insn_fiadd_sub, DEC_DECODED}, /* 0x4D, [p]fisub.{ss,dd} */
+ { 0, 0}, /* 0x4E */
+ { 0, 0}, /* 0x4F */
+ { insn_faddp, DEC_DECODED}, /* 0x50, [p]faddp */
+ { insn_faddz, DEC_DECODED}, /* 0x51, [p]faddz */
+ { 0, 0}, /* 0x52 */
+ { 0, 0}, /* 0x53 */
+ { 0, 0}, /* 0x54 */
+ { 0, 0}, /* 0x55 */
+ { 0, 0}, /* 0x56 */
+ { insn_fzchk, DEC_DECODED}, /* 0x57, [p]fzchkl */
+ { 0, 0}, /* 0x58 */
+ { 0, 0}, /* 0x59 */
+ { insn_form, DEC_DECODED}, /* 0x5A, [p]form.dd */
+ { 0, 0}, /* 0x5B */
+ { 0, 0}, /* 0x5C */
+ { 0, 0}, /* 0x5D */
+ { 0, 0}, /* 0x5E */
+ { insn_fzchk, DEC_DECODED}, /* 0x5F, [p]fzchks */
+ { 0, 0}, /* 0x60 */
+ { 0, 0}, /* 0x61 */
+ { 0, 0}, /* 0x62 */
+ { 0, 0}, /* 0x63 */
+ { 0, 0}, /* 0x64 */
+ { 0, 0}, /* 0x65 */
+ { 0, 0}, /* 0x66 */
+ { 0, 0}, /* 0x67 */
+ { 0, 0}, /* 0x68 */
+ { 0, 0}, /* 0x69 */
+ { 0, 0}, /* 0x6A */
+ { 0, 0}, /* 0x6B */
+ { 0, 0}, /* 0x6C */
+ { 0, 0}, /* 0x6D */
+ { 0, 0}, /* 0x6E */
+ { 0, 0}, /* 0x6F */
+ { 0, 0}, /* 0x70 */
+ { 0, 0}, /* 0x71 */
+ { 0, 0}, /* 0x72 */
+ { 0, 0}, /* 0x73 */
+ { 0, 0}, /* 0x74 */
+ { 0, 0}, /* 0x75 */
+ { 0, 0}, /* 0x76 */
+ { 0, 0}, /* 0x77 */
+ { 0, 0}, /* 0x78 */
+ { 0, 0}, /* 0x79 */
+ { 0, 0}, /* 0x7A */
+ { 0, 0}, /* 0x7B */
+ { 0, 0}, /* 0x7C */
+ { 0, 0}, /* 0x7D */
+ { 0, 0}, /* 0x7E */
+ { 0, 0}, /* 0x7F */
+};
+
+
+/*
+ * Main decoder driver.
+ * insn = instruction at the current PC to execute.
+ * non_shadow = This insn is not in the shadow of a delayed branch).
+ */
+static void decode_exec (i860s *cpustate, UINT32 insn, UINT32 non_shadow)
+{
+ int upper_6bits = (insn >> 26) & 0x3f;
+ char flags = 0;
+ int unrecognized = 1;
+
+ if (cpustate->exiting_ifetch)
+ return;
+
+ if ((upper_6bits == 0x12 || upper_6bits == 0x2c) && insn & 0x0200)
+ logerror("D-bit seen.\n");
+ if (GET_EPSR_BE ())
+ logerror("BE-bit high.\n");
+ if (GET_DIRBASE_CS8 ())
+ logerror("CS8-bit high.\n");
+
+ flags = decode_tbl[upper_6bits].flags;
+ if (flags & DEC_DECODED)
+ {
+ decode_tbl[upper_6bits].insn_exec (cpustate, insn);
+ unrecognized = 0;
+ }
+ else if (flags & DEC_MORE)
+ {
+ if (upper_6bits == 0x12)
+ {
+ /* FP instruction format handled here. */
+ char fp_flags = fp_decode_tbl[insn & 0x7f].flags;
+ if (fp_flags & DEC_DECODED)
+ {
+ fp_decode_tbl[insn & 0x7f].insn_exec (cpustate, insn);
+ unrecognized = 0;
+ }
+ }
+ else if (upper_6bits == 0x13)
+ {
+ /* Core escape instruction format handled here. */
+ char esc_flags = core_esc_decode_tbl[insn & 0x3].flags;
+ if (esc_flags & DEC_DECODED)
+ {
+ core_esc_decode_tbl[insn & 0x3].insn_exec (cpustate, insn);
+ unrecognized = 0;
+ }
+ }
+ }
+
+ if (unrecognized)
+ unrecog_opcode (cpustate->pc, insn);
+
+ /* For now, just treat every instruction as taking the same number of
+ clocks-- a major oversimplification. */
+ cpustate->icount -= 9;
+}
+
+
+/* Set-up all the default power-on/reset values. */
+void reset_i860 (i860s *cpustate)
+{
+ int i;
+ /* On power-up/reset, i860 has values:
+ PC = 0xffffff00.
+ Integer registers: r0 = 0, others = undefined.
+ FP registers: f0:f1 = 0, others undefined.
+ psr: U = IM = BR = BW = 0; others = undefined.
+ epsr: IL = WP = PBM = BE = 0; processor type, stepping, and
+ DCS are proper and read-only; others = undefined.
+ db: undefined.
+ dirbase: DPS, BL, ATE = 0
+ fir, fsr, KR, KI, MERGE: undefined. (what about T?)
+
+ I$: flushed.
+ D$: undefined (all modified bits = 0).
+ TLB: flushed.
+
+ Note that any undefined values are set to 0x55aa55aa patterns to
+ try to detect defective i860 software. */
+
+ /* PC is at trap address after reset. */
+ cpustate->pc = 0xffffff00;
+
+ /* Set grs and frs to undefined/nonsense values, except r0. */
+ for (i = 0; i < 32; i++)
+ {
+ set_iregval (i, 0x55aa55aa);
+ set_fregval_s (cpustate, i, 0.0);
+ }
+ set_iregval (0, 0);
+ set_fregval_s (cpustate, 0, 0.0);
+ set_fregval_s (cpustate, 1, 0.0);
+
+ /* Set whole psr to 0. This sets the proper bits to 0 as specified
+ above, and zeroes the undefined bits. */
+ cpustate->cregs[CR_PSR] = 0;
+
+ /* Set most of the epsr bits to 0 (as specified above), leaving
+ undefined as zero as well. Then properly set processor type,
+ step, and DCS. Type = EPSR[7..0], step = EPSR[12..8],
+ DCS = EPSR[21..18] (2^[12+dcs] = cache size).
+ We'll pretend to be stepping D0, since it has the fewest bugs
+ (and I don't want to emulate the many defects in the earlier
+ steppings).
+ Proc type: 1 = XR, 2 = XP (XR has 8KB data cache -> DCS = 1).
+ Steppings (XR): 3,4,5,6,7 = (B2, C0, B3, C1, D0 respectively).
+ Steppings (XP): 0, 2, 3, 4 = (A0, B0, B1, B2) (any others?). */
+ cpustate->cregs[CR_EPSR] = 0x00040701;
+
+ /* Set DPS, BL, ATE = 0 and the undefined parts also to 0. */
+ cpustate->cregs[CR_DIRBASE] = 0x00000000;
+
+ /* Set fir, fsr, KR, KI, MERGE, T to undefined. */
+ cpustate->cregs[CR_FIR] = 0xaa55aa55;
+ cpustate->cregs[CR_FSR] = /* 0xaa55aa55; */ 0;
+ cpustate->KR.d = 0.0;
+ cpustate->KI.d = 0.0;
+ cpustate->T.d = 0.0;
+ cpustate->merge = 0xaa55aa55;
+
+ cpustate->fir_gets_trap_addr = 0;
+}
+
+
+
+
+/*=================================================================*/
+/* MAME execution hook for i860 emulator. */
+/*=================================================================*/
+
+#include "emu.h"
+
+static CPU_EXECUTE( i860 )
+{
+ i860_state_t *cpustate = get_safe_token(device);
+
+ /* Check if the data bus is held by another device, and bail if so.
+ Also check for reset. */
+ if (cpustate->pin_reset)
+ reset_i860 (cpustate);
+ if (cpustate->pin_bus_hold)
+ {
+ cpustate->icount = 0;
+ return;
+ }
+
+ cpustate->exiting_readmem = 0;
+ cpustate->exiting_ifetch = 0;
+
+ /* Decode and execute loop. */
+ while (cpustate->icount > 0)
+ {
+ UINT32 savepc = cpustate->pc;
+ cpustate->pc_updated = 0;
+ cpustate->pending_trap = 0;
+
+#if 1 /* Delete me soon, for debugging VC inter-processor synch. */
+ if (cpustate->pc == 0xfffc0370 ||
+ cpustate->pc == 0xfffc03a4)
+ {
+ fprintf(stderr, "(%s) 0x%08x: snag 0x20000000\n", cpustate->device->tag(), cpustate->pc);
+ cpustate->single_stepping = 0;
+ }
+ else if (cpustate->pc == 0xfffc0384 ||
+ cpustate->pc == 0xfffc03b8)
+ {
+ fprintf(stderr, "(%s) 0x%08x: passed 0x20000000\n", cpustate->device->tag(), cpustate->pc);
+ cpustate->single_stepping = 0;
+ }
+#endif
+
+ savepc = cpustate->pc;
+ debugger_instruction_hook(cpustate->device, cpustate->pc);
+ decode_exec (cpustate, ifetch (cpustate, cpustate->pc), 1);
+
+ cpustate->exiting_ifetch = 0;
+ cpustate->exiting_readmem = 0;
+
+ if (cpustate->pending_trap)
+ {
+ /* If we need to trap, change PC to trap address.
+ Also set supervisor mode, copy U and IM to their
+ previous versions, clear IM. */
+ if ((cpustate->pending_trap & TRAP_WAS_EXTERNAL) || (GET_EPSR_INT () && GET_PSR_IN ()))
+ {
+ if (!cpustate->pc_updated)
+ cpustate->cregs[CR_FIR] = savepc + 4;
+ else
+ cpustate->cregs[CR_FIR] = cpustate->pc;
+ }
+ else if (cpustate->pending_trap & TRAP_IN_DELAY_SLOT)
+ {
+ cpustate->cregs[CR_FIR] = savepc + 4;
+ }
+ else
+ cpustate->cregs[CR_FIR] = savepc;
+
+ cpustate->fir_gets_trap_addr = 1;
+ SET_PSR_PU (GET_PSR_U ());
+ SET_PSR_PIM (GET_PSR_IM ());
+ SET_PSR_U (0);
+ SET_PSR_IM (0);
+ SET_PSR_DIM (0);
+ SET_PSR_DS (0);
+ cpustate->pc = 0xffffff00;
+ cpustate->pending_trap = 0;
+ }
+ else if (!cpustate->pc_updated)
+ {
+ /* If the PC wasn't updated by a control flow instruction, just
+ bump to next sequential instruction. */
+ cpustate->pc += 4;
+ }
+
+ /*if (cpustate->single_stepping)
+ debugger (cpustate); */
+ }
+}
+/*=================================================================*/
+
+
+
+
+#if 0
+/*=================================================================*/
+/* Internal debugger-related stuff. */
+
+extern unsigned disasm_i860 (char *buf, unsigned int pc, unsigned int insn);
+
+
+/* Disassemble `len' instructions starting at `addr'. */
+static void disasm (i860s *cpustate, UINT32 addr, int len)
+{
+ UINT32 insn;
+ int j;
+ for (j = 0; j < len; j++)
+ {
+ char buf[256];
+ UINT32 phys_addr = addr;
+ if (GET_DIRBASE_ATE ())
+ phys_addr = get_address_translation (cpustate, addr, 1 /* is_dataref */, 0 /* is_write */);
+
+ /* Note that we print the incoming (possibly virtual) address as the
+ PC rather than the translated address. */
+ fprintf (stderr, " (%s) 0x%08x: ", cpustate->device->tag(), addr);
+ insn = cpustate->program->read_dword(phys_addr);
+#ifdef HOST_MSB
+ BYTE_REV32 (insn);
+#endif /* HOST_MSB. */
+ disasm_i860 (buf, addr, insn); fprintf (stderr, "%s", buf);
+ fprintf (stderr, "\n");
+ addr += 4;
+#if 1
+ if (cpustate->single_stepping == 1 && has_delay_slot (insn))
+ len += 1;
+#endif
+ }
+}
+
+
+/* Dump `len' bytes starting at `addr'. */
+static void dbg_db (i860s *cpustate, UINT32 addr, int len)
+{
+ UINT8 b[16];
+ int i;
+ /* This will always dump a multiple of 16 bytes, even if 'len' isn't. */
+ while (len > 0)
+ {
+ /* Note that we print the incoming (possibly virtual) address
+ rather than the translated address. */
+ fprintf (stderr, "0x%08x: ", addr);
+ for (i = 0; i < 16; i++)
+ {
+ UINT32 phys_addr = addr;
+ if (GET_DIRBASE_ATE ())
+ phys_addr = get_address_translation (cpustate, addr, 1 /* is_dataref */, 0 /* is_write */);
+
+ b[i] = cpustate->program->read_byte(phys_addr);
+ fprintf (stderr, "%02x ", b[i]);
+ addr++;
+ }
+ fprintf (stderr, "| ");
+ for (i = 0; i < 16; i++)
+ {
+ if (isprint (b[i]))
+ fprintf (stderr, "%c", b[i]);
+ else
+ fprintf (stderr, ".");
+ }
+ fprintf (stderr, "\n");
+ len -= 16;
+ }
+}
+
+
+/* A simple internal debugger. */
+void debugger (i860s *cpustate)
+{
+ char buf[256];
+ UINT32 curr_disasm = cpustate->pc;
+ UINT32 curr_dumpdb = 0;
+ int c = 0;
+
+ if (cpustate->single_stepping > 1 && cpustate->single_stepping != cpustate->pc)
+ return;
+
+ buf[0] = 0;
+
+ /* Always disassemble the upcoming instruction when single-stepping. */
+ if (cpustate->single_stepping)
+ {
+ disasm (cpustate, cpustate->pc, 1);
+ if (has_delay_slot (2))
+ disasm (cpustate, cpustate->pc + 4, 1);
+ }
+ else
+ fprintf (stderr, "\nEmulator: internal debugger started (? for help).\n");
+
+ fflush (stdin);
+
+ cpustate->single_stepping = 0;
+ while (!cpustate->single_stepping)
+ {
+ fprintf (stderr, "- ");
+#if 0 /* Doesn't work on MacOSX BSD flavor. */
+ fscanf (stdin, "%s", buf);
+#else
+ while (1)
+ {
+ char it = 0;
+ if (read(STDIN_FILENO, &it, 1) == 1)
+ {
+ if (it == '\n')
+ {
+ buf[c] = 0;
+ c = 0;
+ break;
+ }
+ buf[c++] = it;
+ }
+ }
+#endif
+ if (buf[0] == 'g')
+ {
+ if (buf[1] == '0')
+ sscanf (buf + 1, "%x", &cpustate->single_stepping);
+ else
+ break;
+ buf[1] = 0;
+ fprintf (stderr, "go until pc = 0x%08x.\n",
+ cpustate->single_stepping);
+ cpustate->single_stepping = 0; /* HACK */
+ }
+ else if (buf[0] == 'r')
+ dump_state (cpustate);
+ else if (buf[0] == 'u')
+ {
+ if (buf[1] == '0')
+ sscanf (buf + 1, "%x", &curr_disasm);
+ disasm (cpustate, curr_disasm, 10);
+ curr_disasm += 10 * 4;
+ buf[1] = 0;
+ }
+ else if (buf[0] == 'p')
+ {
+ if (buf[1] >= '0' && buf[1] <= '4')
+ dump_pipe (cpustate, buf[1] - 0x30);
+ buf[1] = 0;
+ }
+ else if (buf[0] == 's')
+ cpustate->single_stepping = 1;
+ else if (buf[0] == 'l')
+ ; //cpustate->pc = elf_load(buf + 1);
+ else if (buf[0] == 'd' && buf[1] == 'b')
+ {
+ if (buf[2] == '0')
+ sscanf (buf + 2, "%x", &curr_dumpdb);
+ dbg_db (cpustate, curr_dumpdb, 32);
+ curr_dumpdb += 32;
+ }
+ else if (buf[0] == 'x' && buf[1] == '0')
+ {
+ UINT32 v;
+ sscanf (buf + 1, "%x", &v);
+ if (GET_DIRBASE_ATE ())
+ fprintf (stderr, "vma 0x%08x ==> phys 0x%08x\n", v,
+ get_address_translation (cpustate, v, 1, 0));
+ else
+ fprintf (stderr, "not in virtual address mode.\n");
+ }
+ else if (buf[0] == 'B')
+ {
+ ;//cpustate->pc = elf_load("bins/bsd");
+ break;
+ }
+ else if (buf[0] == '?')
+ {
+ fprintf (stderr, " db: dump bytes (db[0xaddress])\n r: dump registers\n s: single-step\n g: go back to emulator (g[0xaddress])\n u: disassemble (u[0xaddress])\n p: dump pipelines (p{0-4} for all, add, mul, load, graphics)\n l: load an ELF binary (lpath)\n x: give virt->phys translation (x{0xaddress})\n");
+ }
+ else
+ fprintf (stderr, "Bad command '%s'.\n", buf);
+ }
+
+ /* Less noise when single-stepping. */
+ if (cpustate->single_stepping != 1)
+ fprintf (stderr, "Debugger done, continuing emulation.\n");
+}
+
+#endif
diff --git a/trunk/src/emu/cpu/i860/i860dis.c b/trunk/src/emu/cpu/i860/i860dis.c
new file mode 100644
index 00000000000..8fb32b7beb4
--- /dev/null
+++ b/trunk/src/emu/cpu/i860/i860dis.c
@@ -0,0 +1,696 @@
+/***************************************************************************
+
+ i860dis.c
+
+ Disassembler for the Intel i860 emulator.
+
+ Copyright (C) 1995-present Jason Eckhardt (jle@rice.edu)
+ Released for general non-commercial use under the MAME license
+ with the additional requirement that you are free to use and
+ redistribute this code in modified or unmodified form, provided
+ you list me in the credits.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "i860.h"
+
+/* Macros for accessing register fields in instruction word. */
+#define get_isrc1(bits) (((bits) >> 11) & 0x1f)
+#define get_isrc2(bits) (((bits) >> 21) & 0x1f)
+#define get_idest(bits) (((bits) >> 16) & 0x1f)
+#define get_fsrc1(bits) (((bits) >> 11) & 0x1f)
+#define get_fsrc2(bits) (((bits) >> 21) & 0x1f)
+#define get_fdest(bits) (((bits) >> 16) & 0x1f)
+#define get_creg(bits) (((bits) >> 21) & 0x7)
+
+/* Macros for accessing immediate fields. */
+/* 16-bit immediate. */
+#define get_imm16(insn) ((insn) & 0xffff)
+
+
+/* Control register names. */
+static const char *const cr2str[] =
+ {"fir", "psr", "dirbase", "db", "fsr", "epsr", "!", "!"};
+
+
+/* Sign extend N-bit number. */
+static INT32 sign_ext(UINT32 x, int n)
+{
+ INT32 t;
+ t = x >> (n - 1);
+ t = ((-t) << n) | x;
+ return t;
+}
+
+
+/* Basic integer 3-address register format:
+ * mnemonic %rs1,%rs2,%rd */
+static void int_12d(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
+{
+ /* Possibly prefix shrd with 'd.' */
+ if (((insn & 0xfc000000) == 0xb0000000) && (insn & 0x200))
+ sprintf(buf, "d.%s\t%%r%d,%%r%d,%%r%d", mnemonic,
+ get_isrc1 (insn), get_isrc2 (insn), get_idest (insn));
+ else
+ sprintf(buf, "%s\t%%r%d,%%r%d,%%r%d", mnemonic,
+ get_isrc1 (insn), get_isrc2 (insn), get_idest (insn));
+}
+
+
+/* Basic integer 3-address imm16 format:
+ * mnemonic #imm16,%rs2,%rd */
+static void int_i2d(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
+{
+ /* Sign extend the 16-bit immediate.
+ Print as hex for the bitwise operations. */
+ int upper_6bits = (insn >> 26) & 0x3f;
+ if (upper_6bits >= 0x30 && upper_6bits <= 0x3f)
+ sprintf(buf, "%s\t0x%04x,%%r%d,%%r%d", mnemonic,
+ (UINT32)(get_imm16 (insn)), get_isrc2 (insn), get_idest (insn));
+ else
+ sprintf(buf, "%s\t%d,%%r%d,%%r%d", mnemonic,
+ sign_ext(get_imm16 (insn), 16), get_isrc2 (insn), get_idest (insn));
+}
+
+
+/* Integer (mixed) 2-address isrc1ni,fdest. */
+static void int_1d(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
+{
+ sprintf(buf, "%s\t%%r%d,%%f%d", mnemonic, get_isrc1 (insn), get_fdest (insn));
+}
+
+
+/* Integer (mixed) 2-address csrc2,idest. */
+static void int_cd(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
+{
+ sprintf(buf, "%s\t%%%s,%%r%d", mnemonic, cr2str[get_creg (insn)], get_idest (insn));
+}
+
+
+/* Integer (mixed) 2-address isrc1,csrc2. */
+static void int_1c(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
+{
+ sprintf(buf, "%s\t%%r%d,%%%s", mnemonic, get_isrc1(insn), cr2str[get_creg (insn)]);
+}
+
+
+/* Integer 1-address register format:
+ * mnemonic %rs1 */
+static void int_1(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
+{
+ sprintf(buf, "%s\t%%r%d", mnemonic, get_isrc1 (insn));
+}
+
+
+/* Integer no-address register format:
+ * mnemonic */
+static void int_0(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
+{
+ sprintf(buf, "%s", mnemonic);
+}
+
+
+/* Basic floating-point 3-address register format:
+ * mnemonic %fs1,%fs2,%fd */
+static void flop_12d(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
+{
+ const char *const suffix[4] = { "ss", "sd", "ds", "dd" };
+ const char *prefix_d, *prefix_p;
+ prefix_p = (insn & 0x400) ? "p" : "";
+ prefix_d = (insn & 0x200) ? "d." : "";
+
+ /* Special case: pf[m]am and pf[m]sm families are always pipelined, so they
+ do not have a prefix. Also, for the pfmam and pfmsm families, replace
+ any 'a' in the mnemonic with 'm' and prepend an 'm'. */
+ if ((insn & 0x7f) < 0x20)
+ {
+ int is_pfam = insn & 0x400;
+ if (!is_pfam)
+ {
+ char newname[256];
+ char *op = mnemonic;
+ char *np = newname + 1;
+ newname[0] = 'm';
+ while (*op)
+ {
+ if (*op == 'a')
+ *np = 'm';
+ else
+ *np = *op;
+ np++;
+ op++;
+ }
+ *np = 0;
+ mnemonic = newname;
+ }
+ prefix_p = "";
+ }
+
+ /* Special case: pfgt/pfle-- R-bit distinguishes the two. */
+ if ((insn & 0x7f) == 0x34)
+ {
+ const char *const mn[2] = { "fgt.", "fle." };
+ int r = (insn & 0x080) >> 7;
+ int s = (insn & 0x100) ? 3 : 0;
+ sprintf(buf, "%s%s%s%s\t%%f%d,%%f%d,%%f%d", prefix_d, prefix_p, mn[r],
+ suffix[s], get_fsrc1 (insn), get_fsrc2 (insn), get_fdest (insn));
+ }
+ else
+ {
+ int s = (insn & 0x180) >> 7;
+ sprintf(buf, "%s%s%s%s\t%%f%d,%%f%d,%%f%d", prefix_d, prefix_p, mnemonic,
+ suffix[s], get_fsrc1 (insn), get_fsrc2 (insn), get_fdest (insn));
+ }
+}
+
+
+/* Floating-point 2-address register format:
+ * mnemonic %fs1,%fd */
+static void flop_1d(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
+{
+ const char *const suffix[4] = { "ss", "sd", "ds", "dd" };
+ const char *prefix_d, *prefix_p;
+ int s = (insn & 0x180) >> 7;
+ prefix_p = (insn & 0x400) ? "p" : "";
+ prefix_d = (insn & 0x200) ? "d." : "";
+ sprintf(buf, "%s%s%s%s\t%%f%d,%%f%d", prefix_d, prefix_p, mnemonic,
+ suffix[s], get_fsrc1 (insn), get_fdest (insn));
+}
+
+
+/* Floating-point 2-address register format:
+ * mnemonic %fs2,%fd */
+static void flop_2d(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
+{
+ const char *const suffix[4] = { "ss", "sd", "ds", "dd" };
+ const char *prefix_d;
+ int s = (insn & 0x180) >> 7;
+ prefix_d = (insn & 0x200) ? "d." : "";
+ sprintf(buf, "%s%s%s\t%%f%d,%%f%d", prefix_d, mnemonic, suffix[s],
+ get_fsrc2 (insn), get_fdest (insn));
+}
+
+
+/* Floating-point (mixed) 2-address register format:
+ * fxfr fsrc1,idest. */
+static void flop_fxfr(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
+{
+ const char *prefix_d = (insn & 0x200) ? "d." : "";
+ sprintf(buf, "%s%s\t%%f%d,%%r%d", prefix_d, mnemonic, get_fsrc1 (insn),
+ get_idest (insn));
+}
+
+
+/* Branch with reg,reg,sbroff format:
+ * mnemonic %rs1,%rs2,sbroff */
+static void int_12S(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
+{
+ INT32 sbroff = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16);
+ INT32 rel = (INT32)pc + (sbroff << 2) + 4;
+
+ sprintf(buf, "%s\t%%r%d,%%r%d,0x%08x", mnemonic, get_isrc1 (insn),
+ get_isrc2 (insn), (UINT32)rel);
+}
+
+
+/* Branch with #const5,reg,sbroff format:
+ * mnemonic #const5,%rs2,sbroff */
+static void int_i2S(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
+{
+ INT32 sbroff = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16);
+ INT32 rel = (INT32)pc + (sbroff << 2) + 4;
+
+ sprintf(buf, "%s\t%d,%%r%d,0x%08x", mnemonic, ((insn >> 11) & 0x1f),
+ get_isrc2 (insn), (UINT32)rel);
+}
+
+
+/* Branch with lbroff format:
+ * mnemonic lbroff */
+static void int_L(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
+{
+ INT32 lbroff = sign_ext ((insn & 0x03ffffff), 26);
+ INT32 rel = (INT32)pc + (lbroff << 2) + 4;
+
+ sprintf(buf, "%s\t0x%08x", mnemonic, (UINT32)rel);
+}
+
+
+/* Integer load.
+ * ld.{b,s,l} isrc1(isrc2),idest
+ * ld.{b,s,l} #const(isrc2),idest */
+static void int_ldx(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
+{
+ /* Operand size, in bytes. */
+ int sizes[4] = { 1, 1, 2, 4 };
+ const char *const suffix[4] = { "b", "b", "s", "l" };
+ UINT32 idx = 0;
+
+ /* Bits 28 and 0 determine the operand size. */
+ idx = ((insn >> 27) & 2) | (insn & 1);
+
+ /* Bit 26 determines the addressing mode (reg+reg or disp+reg). */
+ if (insn & 0x04000000)
+ {
+ /* Chop off lower bits of displacement. */
+ INT32 immsrc1 = sign_ext (get_imm16 (insn), 16);
+ int size = sizes[idx];
+ immsrc1 &= ~(size - 1);
+ sprintf(buf, "%s%s\t%d(%%r%d),%%r%d", mnemonic, suffix[idx],
+ immsrc1, get_isrc2 (insn), get_idest (insn));
+ }
+ else
+ sprintf(buf, "%s%s\t%%r%d(%%r%d),%%r%d", mnemonic, suffix[idx],
+ get_isrc1 (insn), get_isrc2 (insn), get_idest (insn));
+}
+
+
+/* Integer store: st.b isrc1ni,#const(isrc2) */
+static void int_stx(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
+{
+ /* Operand size, in bytes. */
+ int sizes[4] = { 1, 1, 2, 4 };
+ const char *const suffix[4] = { "b", "b", "s", "l" };
+ int idx = 0;
+ int size;
+ INT32 immsrc = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16);
+
+ /* Bits 28 and 0 determine the operand size. */
+ idx = ((insn >> 27) & 2) | (insn & 1);
+
+ /* Chop off lower bits of displacement. */
+ size = sizes[idx];
+ immsrc &= ~(size - 1);
+ sprintf(buf, "%s%s\t%%r%d,%d(%%r%d)", mnemonic, suffix[idx],
+ get_isrc1 (insn), immsrc, get_isrc2 (insn));
+}
+
+
+/* Disassemble:
+ * "[p]fld.y isrc1(isrc2),fdest", "[p]fld.y isrc1(isrc2)++,idest",
+ * "[p]fld.y #const(isrc2),fdest" or "[p]fld.y #const(isrc2)++,idest".
+ * "fst.y fdest,isrc1(isrc2)", "fst.y fdest,isrc1(isrc2)++",
+ * "fst.y fdest,#const(isrc2)" or "fst.y fdest,#const(isrc2)++"
+ * Where y = {l,d,q}. Note, there is no pfld.q, though. */
+static void int_fldst(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
+{
+ INT32 immsrc1 = sign_ext (get_imm16 (insn), 16);
+ /* Operand size, in bytes. */
+ int sizes[4] = { 8, 4, 16, 4 };
+ const char *const suffix[4] = { "d", "l", "q", "l" };
+ int idx = 0;
+ int size = 0;
+ int auto_inc = (insn & 1);
+ const char *const auto_suff[2] = { "", "++" };
+ int piped = (insn & 0x40000000) >> 29;
+ const char *const piped_suff[2] = { "", "p" };
+ int upper_6bits = (insn >> 26) & 0x3f;
+ int is_load = (upper_6bits == 8 || upper_6bits == 9 || upper_6bits == 24
+ || upper_6bits == 25);
+
+ /* Bits 2 and 1 determine the operand size. */
+ idx = ((insn >> 1) & 3);
+ size = sizes[idx];
+
+ /* There is no pipelined load quad on XR. */
+ if (piped && size == 16)
+ {
+ sprintf (buf, ".long\t%#08x; *", insn);
+ return;
+ }
+
+ /* There is only a 64-bit pixel store. */
+ if ((upper_6bits == 15) && size != 8)
+ {
+ sprintf (buf, ".long\t%#08x", insn);
+ return;
+ }
+
+ /* Bit 26 determines the addressing mode (reg+reg or disp+reg). */
+ if (insn & 0x04000000)
+ {
+ /* Chop off lower bits of displacement. */
+ immsrc1 &= ~(size - 1);
+ if (is_load)
+ sprintf(buf, "%s%s%s\t%d(%%r%d)%s,%%f%d", piped_suff[piped], mnemonic,
+ suffix[idx], immsrc1, get_isrc2 (insn), auto_suff[auto_inc],
+ get_fdest (insn));
+ else
+ sprintf(buf, "%s%s\t%%f%d,%d(%%r%d)%s", mnemonic, suffix[idx],
+ get_fdest (insn), immsrc1, get_isrc2 (insn), auto_suff[auto_inc]);
+ }
+ else
+ {
+ if (is_load)
+ sprintf(buf, "%s%s%s\t%%r%d(%%r%d)%s,%%f%d", piped_suff[piped],
+ mnemonic, suffix[idx], get_isrc1 (insn), get_isrc2 (insn),
+ auto_suff[auto_inc], get_fdest (insn));
+ else
+ sprintf(buf, "%s%s\t%%f%d,%%r%d(%%r%d)%s", mnemonic, suffix[idx],
+ get_fdest (insn), get_isrc1 (insn), get_isrc2 (insn),
+ auto_suff[auto_inc]);
+ }
+}
+
+
+/* flush #const(isrc2)[++]. */
+static void int_flush(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
+{
+ const char *const auto_suff[2] = { "", "++" };
+ INT32 immsrc = sign_ext (get_imm16 (insn), 16);
+ immsrc &= ~(16-1);
+ sprintf(buf, "%s\t%d(%%r%d)%s", mnemonic, immsrc, get_isrc2 (insn),
+ auto_suff[(insn & 1)]);
+}
+
+
+/* Flags for the decode table. */
+enum
+{
+ DEC_MORE = 1, /* More decoding necessary. */
+ DEC_DECODED = 2 /* Fully decoded, go. */
+};
+
+
+typedef struct
+{
+ /* Disassembly function for this opcode.
+ Call with buffer, mnemonic, pc, insn. */
+ void (*insn_dis)(char *, char *, UINT32, UINT32);
+
+ /* Flags for this opcode. */
+ char flags;
+
+ /* Mnemonic of this opcode (sometimes partial when more decode is
+ done in disassembly routines-- e.g., loads and stores). */
+ const char *mnemonic;
+} decode_tbl_t;
+
+
+/* First-level decode table (i.e., for the 6 primary opcode bits). */
+static const decode_tbl_t decode_tbl[64] =
+{
+ /* A slight bit of decoding for loads and stores is done in the
+ execution routines (operand size and addressing mode), which
+ is why their respective entries are identical. */
+ { int_ldx, DEC_DECODED, "ld." }, /* ld.b isrc1(isrc2),idest. */
+ { int_ldx, DEC_DECODED, "ld." }, /* ld.b #const(isrc2),idest. */
+ { int_1d, DEC_DECODED, "ixfr" }, /* ixfr isrc1ni,fdest. */
+ { int_stx, DEC_DECODED, "st." }, /* st.b isrc1ni,#const(isrc2). */
+ { int_ldx, DEC_DECODED, "ld." }, /* ld.{s,l} isrc1(isrc2),idest. */
+ { int_ldx, DEC_DECODED, "ld." }, /* ld.{s,l} #const(isrc2),idest. */
+ { 0, 0 , 0 },
+ { int_stx, DEC_DECODED, "st." }, /* st.{s,l} isrc1ni,#const(isrc2),idest.*/
+ { int_fldst, DEC_DECODED, "fld." }, /* fld.{l,d,q} isrc1(isrc2)[++],fdest. */
+ { int_fldst, DEC_DECODED, "fld." }, /* fld.{l,d,q} #const(isrc2)[++],fdest. */
+ { int_fldst, DEC_DECODED, "fst." }, /* fst.{l,d,q} fdest,isrc1(isrc2)[++] */
+ { int_fldst, DEC_DECODED, "fst." }, /* fst.{l,d,q} fdest,#const(isrc2)[++] */
+ { int_cd, DEC_DECODED, "ld.c" }, /* ld.c csrc2,idest. */
+ { int_flush, DEC_DECODED, "flush" }, /* flush #const(isrc2) (or autoinc). */
+ { int_1c, DEC_DECODED, "st.c" }, /* st.c isrc1,csrc2. */
+ { int_fldst, DEC_DECODED, "pstd." }, /* pst.d fdest,#const(isrc2)[++]. */
+ { int_1, DEC_DECODED, "bri" }, /* bri isrc1ni. */
+ { int_12d, DEC_DECODED, "trap" }, /* trap isrc1ni,isrc2,idest. */
+ { 0, DEC_MORE, 0 }, /* FP ESCAPE FORMAT, more decode. */
+ { 0, DEC_MORE, 0 }, /* CORE ESCAPE FORMAT, more decode. */
+ { int_12S, DEC_DECODED, "btne" }, /* btne isrc1,isrc2,sbroff. */
+ { int_i2S, DEC_DECODED, "btne" }, /* btne #const,isrc2,sbroff. */
+ { int_12S, DEC_DECODED, "bte" }, /* bte isrc1,isrc2,sbroff. */
+ { int_i2S, DEC_DECODED, "bte" }, /* bte #const5,isrc2,idest. */
+ { int_fldst, DEC_DECODED, "pfld." }, /* pfld.{l,d,q} isrc1(isrc2)[++],fdest. */
+ { int_fldst, DEC_DECODED, "pfld." }, /* pfld.{l,d,q} #const(isrc2)[++],fdest.*/
+ { int_L, DEC_DECODED, "br" }, /* br lbroff. */
+ { int_L, DEC_DECODED, "call" }, /* call lbroff . */
+ { int_L, DEC_DECODED, "bc" }, /* bc lbroff. */
+ { int_L, DEC_DECODED, "bc.t" }, /* bc.t lbroff. */
+ { int_L, DEC_DECODED, "bnc" }, /* bnc lbroff. */
+ { int_L, DEC_DECODED, "bnc.t" }, /* bnc.t lbroff. */
+ { int_12d, DEC_DECODED, "addu" }, /* addu isrc1,isrc2,idest. */
+ { int_i2d, DEC_DECODED, "addu" }, /* addu #const,isrc2,idest. */
+ { int_12d, DEC_DECODED, "subu" }, /* subu isrc1,isrc2,idest. */
+ { int_i2d, DEC_DECODED, "subu" }, /* subu #const,isrc2,idest. */
+ { int_12d, DEC_DECODED, "adds" }, /* adds isrc1,isrc2,idest. */
+ { int_i2d, DEC_DECODED, "adds" }, /* adds #const,isrc2,idest. */
+ { int_12d, DEC_DECODED, "subs" }, /* subs isrc1,isrc2,idest. */
+ { int_i2d, DEC_DECODED, "subs" }, /* subs #const,isrc2,idest. */
+ { int_12d, DEC_DECODED, "shl" }, /* shl isrc1,isrc2,idest. */
+ { int_i2d, DEC_DECODED, "shl" }, /* shl #const,isrc2,idest. */
+ { int_12d, DEC_DECODED, "shr" }, /* shr isrc1,isrc2,idest. */
+ { int_i2d, DEC_DECODED, "shr" }, /* shr #const,isrc2,idest. */
+ { int_12d, DEC_DECODED, "shrd" }, /* shrd isrc1ni,isrc2,idest. */
+ { int_12S, DEC_DECODED, "bla" }, /* bla isrc1ni,isrc2,sbroff. */
+ { int_12d, DEC_DECODED, "shra" }, /* shra isrc1,isrc2,idest. */
+ { int_i2d, DEC_DECODED, "shra" }, /* shra #const,isrc2,idest. */
+ { int_12d, DEC_DECODED, "and" }, /* and isrc1,isrc2,idest. */
+ { int_i2d, DEC_DECODED, "and" }, /* and #const,isrc2,idest. */
+ { 0, 0 , 0 },
+ { int_i2d, DEC_DECODED, "andh" }, /* andh #const,isrc2,idest. */
+ { int_12d, DEC_DECODED, "andnot" }, /* andnot isrc1,isrc2,idest. */
+ { int_i2d, DEC_DECODED, "andnot" }, /* andnot #const,isrc2,idest. */
+ { 0, 0 , 0 },
+ { int_i2d, DEC_DECODED, "andnoth" }, /* andnoth #const,isrc2,idest.*/
+ { int_12d, DEC_DECODED, "or" }, /* or isrc1,isrc2,idest. */
+ { int_i2d, DEC_DECODED, "or" }, /* or #const,isrc2,idest. */
+ { 0, 0 , 0 },
+ { int_i2d, DEC_DECODED, "orh" }, /* orh #const,isrc2,idest. */
+ { int_12d, DEC_DECODED, "xor" }, /* xor isrc1,isrc2,idest. */
+ { int_i2d, DEC_DECODED, "xor" }, /* xor #const,isrc2,idest. */
+ { 0, 0 , 0 },
+ { int_i2d, DEC_DECODED, "xorh" }, /* xorh #const,isrc2,idest. */
+};
+
+
+/* Second-level decode table (i.e., for the 3 core escape opcode bits). */
+static const decode_tbl_t core_esc_decode_tbl[8] =
+{
+ { 0, 0 , 0 },
+ { int_0, DEC_DECODED, "lock" }, /* lock. */
+ { int_1, DEC_DECODED, "calli" }, /* calli isrc1ni. */
+ { 0, 0 , 0 },
+ { int_0, DEC_DECODED, "intovr" }, /* intovr. */
+ { 0, 0 , 0 },
+ { 0, 0 , 0 },
+ { int_0, DEC_DECODED, "unlock" }, /* unlock. */
+};
+
+
+/* Second-level decode table (i.e., for the 7 FP extended opcode bits). */
+static const decode_tbl_t fp_decode_tbl[128] =
+{
+ /* Floating point instructions. The least significant 7 bits are
+ the (extended) opcode and bits 10:7 are P,D,S,R respectively
+ ([p]ipelined, [d]ual, [s]ource prec., [r]esult prec.).
+ For some operations, I defer decoding the P,S,R bits to the
+ emulation routine for them. */
+ { flop_12d, DEC_DECODED, "r2p1." }, /* 0x00 pf[m]am */
+ { flop_12d, DEC_DECODED, "r2pt." }, /* 0x01 pf[m]am */
+ { flop_12d, DEC_DECODED, "r2ap1." }, /* 0x02 pf[m]am */
+ { flop_12d, DEC_DECODED, "r2apt." }, /* 0x03 pf[m]am */
+ { flop_12d, DEC_DECODED, "i2p1." }, /* 0x04 pf[m]am */
+ { flop_12d, DEC_DECODED, "i2pt." }, /* 0x05 pf[m]am */
+ { flop_12d, DEC_DECODED, "i2ap1." }, /* 0x06 pf[m]am */
+ { flop_12d, DEC_DECODED, "i2apt." }, /* 0x07 pf[m]am */
+ { flop_12d, DEC_DECODED, "rat1p2." }, /* 0x08 pf[m]am */
+ { flop_12d, DEC_DECODED, "m12apm." }, /* 0x09 pf[m]am */
+ { flop_12d, DEC_DECODED, "ra1p2." }, /* 0x0A pf[m]am */
+ { flop_12d, DEC_DECODED, "m12ttpa." }, /* 0x0B pf[m]am */
+ { flop_12d, DEC_DECODED, "iat1p2." }, /* 0x0C pf[m]am */
+ { flop_12d, DEC_DECODED, "m12tpm." }, /* 0x0D pf[m]am */
+ { flop_12d, DEC_DECODED, "ia1p2." }, /* 0x0E pf[m]am */
+ { flop_12d, DEC_DECODED, "m12tpa." }, /* 0x0F pf[m]am */
+ { flop_12d, DEC_DECODED, "r2s1." }, /* 0x10 pf[m]sm */
+ { flop_12d, DEC_DECODED, "r2st." }, /* 0x11 pf[m]sm */
+ { flop_12d, DEC_DECODED, "r2as1." }, /* 0x12 pf[m]sm */
+ { flop_12d, DEC_DECODED, "r2ast." }, /* 0x13 pf[m]sm */
+ { flop_12d, DEC_DECODED, "i2s1." }, /* 0x14 pf[m]sm */
+ { flop_12d, DEC_DECODED, "i2st." }, /* 0x15 pf[m]sm */
+ { flop_12d, DEC_DECODED, "i2as1." }, /* 0x16 pf[m]sm */
+ { flop_12d, DEC_DECODED, "i2ast." }, /* 0x17 pf[m]sm */
+ { flop_12d, DEC_DECODED, "rat1s2." }, /* 0x18 pf[m]sm */
+ { flop_12d, DEC_DECODED, "m12asm." }, /* 0x19 pf[m]sm */
+ { flop_12d, DEC_DECODED, "ra1s2." }, /* 0x1A pf[m]sm */
+ { flop_12d, DEC_DECODED, "m12ttsa." }, /* 0x1B pf[m]sm */
+ { flop_12d, DEC_DECODED, "iat1s2." }, /* 0x1C pf[m]sm */
+ { flop_12d, DEC_DECODED, "m12tsm." }, /* 0x1D pf[m]sm */
+ { flop_12d, DEC_DECODED, "ia1s2." }, /* 0x1E pf[m]sm */
+ { flop_12d, DEC_DECODED, "m12tsa." }, /* 0x1F pf[m]sm */
+ { flop_12d, DEC_DECODED, "fmul." }, /* 0x20 [p]fmul */
+ { flop_12d, DEC_DECODED, "fmlow." }, /* 0x21 fmlow.dd */
+ { flop_2d, DEC_DECODED, "frcp." }, /* 0x22 frcp.{ss,sd,dd} */
+ { flop_2d, DEC_DECODED, "frsqr." }, /* 0x23 frsqr.{ss,sd,dd} */
+ { flop_12d, DEC_DECODED, "pfmul3.dd" }, /* 0x24 pfmul3.dd */
+ { 0, 0 , 0 }, /* 0x25 */
+ { 0, 0 , 0 }, /* 0x26 */
+ { 0, 0 , 0 }, /* 0x27 */
+ { 0, 0 , 0 }, /* 0x28 */
+ { 0, 0 , 0 }, /* 0x29 */
+ { 0, 0 , 0 }, /* 0x2A */
+ { 0, 0 , 0 }, /* 0x2B */
+ { 0, 0 , 0 }, /* 0x2C */
+ { 0, 0 , 0 }, /* 0x2D */
+ { 0, 0 , 0 }, /* 0x2E */
+ { 0, 0 , 0 }, /* 0x2F */
+ { flop_12d, DEC_DECODED, "fadd." }, /* 0x30, [p]fadd.{ss,sd,dd} */
+ { flop_12d, DEC_DECODED, "fsub." }, /* 0x31, [p]fsub.{ss,sd,dd} */
+ { flop_1d, DEC_DECODED, "fix." }, /* 0x32, [p]fix.{ss,sd,dd} */
+ { flop_1d, DEC_DECODED, "famov." }, /* 0x33, [p]famov.{ss,sd,ds,dd} */
+ { flop_12d, DEC_DECODED, "f{gt,le}" }, /* 0x34, pf{gt,le}.{ss,dd} */
+ { flop_12d, DEC_DECODED, "feq." }, /* 0x35, pfeq.{ss,dd} */
+ { 0, 0 , 0 }, /* 0x36 */
+ { 0, 0 , 0 }, /* 0x37 */
+ { 0, 0 , 0 }, /* 0x38 */
+ { 0, 0 , 0 }, /* 0x39 */
+ { flop_1d, DEC_DECODED, "ftrunc." }, /* 0x3A, [p]ftrunc.{ss,sd,dd} */
+ { 0, 0 , 0 }, /* 0x3B */
+ { 0, 0 , 0 }, /* 0x3C */
+ { 0, 0 , 0 }, /* 0x3D */
+ { 0, 0 , 0 }, /* 0x3E */
+ { 0, 0 , 0 }, /* 0x3F */
+ { flop_fxfr, DEC_DECODED, "fxfr" }, /* 0x40, fxfr fsrc1,idest. */
+ { 0, 0 , 0 }, /* 0x41 */
+ { 0, 0 , 0 }, /* 0x42 */
+ { 0, 0 , 0 }, /* 0x43 */
+ { 0, 0 , 0 }, /* 0x44 */
+ { 0, 0 , 0 }, /* 0x45 */
+ { 0, 0 , 0 }, /* 0x46 */
+ { 0, 0 , 0 }, /* 0x47 */
+ { 0, 0 , 0 }, /* 0x48 */
+ { flop_12d, DEC_DECODED, "fiadd." }, /* 0x49, [p]fiadd.{ss,dd} */
+ { 0, 0 , 0 }, /* 0x4A */
+ { 0, 0 , 0 }, /* 0x4B */
+ { 0, 0 , 0 }, /* 0x4C */
+ { flop_12d, DEC_DECODED, "fisub." }, /* 0x4D, [p]fisub.{ss,dd} */
+ { 0, 0 , 0 }, /* 0x4E */
+ { 0, 0 , 0 }, /* 0x4F */
+ { flop_12d, DEC_DECODED, "faddp" }, /* 0x50, [p]faddp */
+ { flop_12d, DEC_DECODED, "faddz" }, /* 0x51, [p]faddz */
+ { 0, 0 , 0 }, /* 0x52 */
+ { 0, 0 , 0 }, /* 0x53 */
+ { 0, 0 , 0 }, /* 0x54 */
+ { 0, 0 , 0 }, /* 0x55 */
+ { 0, 0 , 0 }, /* 0x56 */
+ { flop_12d, DEC_DECODED, "fzchkl" }, /* 0x57, [p]fzchkl */
+ { 0, 0 , 0 }, /* 0x58 */
+ { 0, 0 , 0 }, /* 0x59 */
+ { flop_1d, DEC_DECODED, "form" }, /* 0x5A, [p]form.dd */
+ { 0, 0 , 0 }, /* 0x5B */
+ { 0, 0 , 0 }, /* 0x5C */
+ { 0, 0 , 0 }, /* 0x5D */
+ { 0, 0 , 0 }, /* 0x5E */
+ { flop_12d, DEC_DECODED, "fzchks" }, /* 0x5F, [p]fzchks */
+ { 0, 0 , 0 }, /* 0x60 */
+ { 0, 0 , 0 }, /* 0x61 */
+ { 0, 0 , 0 }, /* 0x62 */
+ { 0, 0 , 0 }, /* 0x63 */
+ { 0, 0 , 0 }, /* 0x64 */
+ { 0, 0 , 0 }, /* 0x65 */
+ { 0, 0 , 0 }, /* 0x66 */
+ { 0, 0 , 0 }, /* 0x67 */
+ { 0, 0 , 0 }, /* 0x68 */
+ { 0, 0 , 0 }, /* 0x69 */
+ { 0, 0 , 0 }, /* 0x6A */
+ { 0, 0 , 0 }, /* 0x6B */
+ { 0, 0 , 0 }, /* 0x6C */
+ { 0, 0 , 0 }, /* 0x6D */
+ { 0, 0 , 0 }, /* 0x6E */
+ { 0, 0 , 0 }, /* 0x6F */
+ { 0, 0 , 0 }, /* 0x70 */
+ { 0, 0 , 0 }, /* 0x71 */
+ { 0, 0 , 0 }, /* 0x72 */
+ { 0, 0 , 0 }, /* 0x73 */
+ { 0, 0 , 0 }, /* 0x74 */
+ { 0, 0 , 0 }, /* 0x75 */
+ { 0, 0 , 0 }, /* 0x76 */
+ { 0, 0 , 0 }, /* 0x77 */
+ { 0, 0 , 0 }, /* 0x78 */
+ { 0, 0 , 0 }, /* 0x79 */
+ { 0, 0 , 0 }, /* 0x7A */
+ { 0, 0 , 0 }, /* 0x7B */
+ { 0, 0 , 0 }, /* 0x7C */
+ { 0, 0 , 0 }, /* 0x7D */
+ { 0, 0 , 0 }, /* 0x7E */
+ { 0, 0 , 0 }, /* 0x7F */
+};
+
+
+/* Replaces tabs with spaces. */
+static void i860_dasm_tab_replacer(char* buf, int tab_size)
+{
+ int i = 0;
+ int tab_count = 0;
+ char tab_buf[1024];
+ memset(tab_buf, 0, 1024);
+
+ while (i != strlen(buf))
+ {
+ if (buf[i] != '\t')
+ {
+ tab_buf[tab_count] = buf[i];
+ tab_count++;
+ }
+ else
+ {
+ while (tab_count % tab_size != 0)
+ {
+ strcat(tab_buf, " ");
+ tab_count++;
+ }
+ }
+ i++;
+ }
+
+ tab_buf[tab_count] = 0x00;
+ strcpy(buf, tab_buf);
+}
+
+
+/* Entry point for disassembler. */
+unsigned disasm_i860(char *buf, unsigned pc, UINT32 insn)
+{
+ int unrecognized_op = 1;
+ int upper_6bits = (insn >> 26) & 0x3f;
+ char flags = decode_tbl[upper_6bits].flags;
+ if (flags & DEC_DECODED)
+ {
+ const char *s = decode_tbl[upper_6bits].mnemonic;
+ decode_tbl[upper_6bits].insn_dis (buf, (char *)s, pc, insn);
+ unrecognized_op = 0;
+ }
+ else if (flags & DEC_MORE)
+ {
+ if (upper_6bits == 0x12)
+ {
+ /* FP instruction format handled here. */
+ char fp_flags = fp_decode_tbl[insn & 0x7f].flags;
+ const char *s = fp_decode_tbl[insn & 0x7f].mnemonic;
+ if (fp_flags & DEC_DECODED)
+ {
+ fp_decode_tbl[insn & 0x7f].insn_dis (buf, (char *)s, pc, insn);
+ unrecognized_op = 0;
+ }
+ }
+ else if (upper_6bits == 0x13)
+ {
+ /* Core escape instruction format handled here. */
+ char esc_flags = core_esc_decode_tbl[insn & 0x3].flags;
+ const char *s = core_esc_decode_tbl[insn & 0x3].mnemonic;
+ if (esc_flags & DEC_DECODED)
+ {
+ core_esc_decode_tbl[insn & 0x3].insn_dis (buf, (char *)s, pc, insn);
+ unrecognized_op = 0;
+ }
+ }
+ }
+
+ if (unrecognized_op)
+ sprintf (buf, ".long\t%#08x", insn);
+
+ /* Replace tabs with spaces */
+ i860_dasm_tab_replacer(buf, 10);
+
+ /* Return number of bytes disassembled. */
+ /* MAME dasm flags haven't been added yet */
+ return (4);
+}
diff --git a/trunk/src/emu/cpu/i960/i960.c b/trunk/src/emu/cpu/i960/i960.c
new file mode 100644
index 00000000000..632c9f5c8e9
--- /dev/null
+++ b/trunk/src/emu/cpu/i960/i960.c
@@ -0,0 +1,2232 @@
+#include "emu.h"
+#include "debugger.h"
+#include "i960.h"
+
+CPU_DISASSEMBLE( i960 );
+
+#ifdef _MSC_VER
+/* logb prototype is different for MS Visual C */
+#include <float.h>
+#define logb _logb
+#endif
+
+
+// Warning, IP = Instruction Pointer, called PC outside of Intel
+// PC = Process Control
+
+enum { RCACHE_SIZE = 4 };
+
+typedef struct _i960_state_t i960_state_t;
+struct _i960_state_t {
+ UINT32 r[0x20];
+ UINT32 rcache[RCACHE_SIZE][0x10];
+ UINT32 rcache_frame_addr[RCACHE_SIZE];
+ // rcache_pos = how deep in the stack we are. 0-(RCACHE_SIZE-1) means in-cache.
+ // RCACHE_SIZE or greater means out of cache, must save to memory.
+ INT32 rcache_pos;
+
+ double fp[4];
+
+ UINT32 SAT, PRCB, PC, AC;
+ UINT32 IP, PIP, ICR;
+ int bursting;
+
+ int immediate_irq, immediate_vector, immediate_pri;
+
+ device_irq_callback irq_cb;
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+
+ int icount;
+};
+
+INLINE i960_state_t *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == I960);
+ return (i960_state_t *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+static void do_call(i960_state_t *i960, UINT32 adr, int type, UINT32 stack);
+
+INLINE UINT32 i960_read_dword_unaligned(i960_state_t *i960, UINT32 address)
+{
+ if (address & 3)
+ return i960->program->read_byte(address) | i960->program->read_byte(address+1)<<8 | i960->program->read_byte(address+2)<<16 | i960->program->read_byte(address+3)<<24;
+ else
+ return i960->program->read_dword(address);
+}
+
+INLINE UINT16 i960_read_word_unaligned(i960_state_t *i960, UINT32 address)
+{
+ if (address & 1)
+ return i960->program->read_byte(address) | i960->program->read_byte(address+1)<<8;
+ else
+ return i960->program->read_word(address);
+}
+
+INLINE void i960_write_dword_unaligned(i960_state_t *i960, UINT32 address, UINT32 data)
+{
+ if (address & 3)
+ {
+ i960->program->write_byte(address, data & 0xff);
+ i960->program->write_byte(address+1, (data>>8)&0xff);
+ i960->program->write_byte(address+2, (data>>16)&0xff);
+ i960->program->write_byte(address+3, (data>>24)&0xff);
+ }
+ else
+ {
+ i960->program->write_dword(address, data);
+ }
+}
+
+INLINE void i960_write_word_unaligned(i960_state_t *i960, UINT32 address, UINT16 data)
+{
+ if (address & 1)
+ {
+ i960->program->write_byte(address, data & 0xff);
+ i960->program->write_byte(address+1, (data>>8)&0xff);
+ }
+ else
+ {
+ i960->program->write_word(address, data);
+ }
+}
+
+INLINE void send_iac(i960_state_t *i960, UINT32 adr)
+{
+ UINT32 iac[4];
+ iac[0] = i960->program->read_dword(adr);
+ iac[1] = i960->program->read_dword(adr+4);
+ iac[2] = i960->program->read_dword(adr+8);
+ iac[3] = i960->program->read_dword(adr+12);
+
+ switch(iac[0]>>24) {
+ case 0x93: // reinit
+ i960->SAT = iac[1];
+ i960->PRCB = iac[2];
+ i960->IP = iac[3];
+ break;
+ default:
+ fatalerror("I960: %x: IAC %08x %08x %08x %08x", i960->PIP, iac[0], iac[1], iac[2], iac[3]);
+ break;
+ }
+}
+
+INLINE UINT32 get_ea(i960_state_t *i960, UINT32 opcode)
+{
+ int abase = (opcode >> 14) & 0x1f;
+ if(!(opcode & 0x00001000)) { // MEMA
+ UINT32 offset = opcode & 0x1fff;
+ if(!(opcode & 0x2000))
+ return offset;
+ else
+ return i960->r[abase]+offset;
+ } else { // MEMB
+ int index = opcode & 0x1f;
+ int scale = (opcode >> 7) & 0x7;
+ int mode = (opcode >> 10) & 0xf;
+ UINT32 ret;
+
+ switch(mode) {
+ case 0x4:
+ return i960->r[abase];
+
+ case 0x7:
+ return i960->r[abase] + (i960->r[index] << scale);
+
+ case 0xc:
+ ret = i960->direct->read_decrypted_dword(i960->IP);
+ i960->IP += 4;
+ return ret;
+
+ case 0xd:
+ ret = i960->direct->read_decrypted_dword(i960->IP) + i960->r[abase];
+ i960->IP += 4;
+ return ret;
+
+ case 0xe:
+ ret = i960->direct->read_decrypted_dword(i960->IP) + (i960->r[index] << scale);
+ i960->IP += 4;
+ return ret;
+
+ case 0xf:
+ ret = i960->direct->read_decrypted_dword(i960->IP) + i960->r[abase] + (i960->r[index] << scale);
+ i960->IP += 4;
+ return ret;
+
+ default:
+ fatalerror("I960: %x: unhandled MEMB mode %x", i960->PIP, mode);
+ return 0;
+ }
+ }
+}
+
+INLINE UINT32 get_1_ri(i960_state_t *i960, UINT32 opcode)
+{
+ if(!(opcode & 0x00000800))
+ return i960->r[opcode & 0x1f];
+ else
+ return opcode & 0x1f;
+}
+
+INLINE UINT32 get_2_ri(i960_state_t *i960, UINT32 opcode)
+{
+ if(!(opcode & 0x00001000))
+ return i960->r[(opcode>>14) & 0x1f];
+ else
+ return (opcode>>14) & 0x1f;
+}
+
+INLINE UINT64 get_2_ri64(i960_state_t *i960, UINT32 opcode)
+{
+ if(!(opcode & 0x00001000))
+ return i960->r[(opcode>>14) & 0x1f] | ((UINT64)i960->r[((opcode>>14) & 0x1f)+1]<<32);
+ else
+ return (opcode>>14) & 0x1f;
+}
+
+INLINE void set_ri(i960_state_t *i960, UINT32 opcode, UINT32 val)
+{
+ if(!(opcode & 0x00002000))
+ i960->r[(opcode>>19) & 0x1f] = val;
+ else {
+ fatalerror("I960: %x: set_ri on literal?", i960->PIP);
+ }
+}
+
+INLINE void set_ri2(i960_state_t *i960, UINT32 opcode, UINT32 val, UINT32 val2)
+{
+ if(!(opcode & 0x00002000))
+ {
+ i960->r[(opcode>>19) & 0x1f] = val;
+ i960->r[((opcode>>19) & 0x1f)+1] = val2;
+ }
+ else {
+ fatalerror("I960: %x: set_ri2 on literal?", i960->PIP);
+ }
+}
+
+INLINE void set_ri64(i960_state_t *i960, UINT32 opcode, UINT64 val)
+{
+ if(!(opcode & 0x00002000)) {
+ i960->r[(opcode>>19) & 0x1f] = val;
+ i960->r[((opcode>>19) & 0x1f)+1] = val >> 32;
+ } else
+ fatalerror("I960: %x: set_ri64 on literal?", i960->PIP);
+}
+
+INLINE double get_1_rif(i960_state_t *i960, UINT32 opcode)
+{
+ if(!(opcode & 0x00000800))
+ return u2f(i960->r[opcode & 0x1f]);
+ else {
+ int idx = opcode & 0x1f;
+ if(idx < 4)
+ return i960->fp[idx];
+ if(idx == 0x16)
+ return 1.0;
+ return 0.0;
+ }
+}
+
+INLINE double get_2_rif(i960_state_t *i960, UINT32 opcode)
+{
+ if(!(opcode & 0x00001000))
+ return u2f(i960->r[(opcode>>14) & 0x1f]);
+ else {
+ int idx = (opcode>>14) & 0x1f;
+ if(idx < 4)
+ return i960->fp[idx];
+ if(idx == 0x16)
+ return 1.0;
+ return 0.0;
+ }
+}
+
+INLINE void set_rif(i960_state_t *i960, UINT32 opcode, double val)
+{
+ if(!(opcode & 0x00002000))
+ i960->r[(opcode>>19) & 0x1f] = f2u(val);
+ else if(!(opcode & 0x00e00000))
+ i960->fp[(opcode>>19) & 3] = val;
+ else
+ fatalerror("I960: %x: set_rif on literal?", i960->PIP);
+}
+
+INLINE double get_1_rifl(i960_state_t *i960, UINT32 opcode)
+{
+ if(!(opcode & 0x00000800)) {
+ UINT64 v = i960->r[opcode & 0x1e];
+ v |= ((UINT64)(i960->r[(opcode & 0x1e)+1]))<<32;
+ return u2d(v);
+ } else {
+ int idx = opcode & 0x1f;
+ if(idx < 4)
+ return i960->fp[idx];
+ if(idx == 0x16)
+ return 1.0;
+ return 0.0;
+ }
+}
+
+INLINE double get_2_rifl(i960_state_t *i960, UINT32 opcode)
+{
+ if(!(opcode & 0x00001000)) {
+ UINT64 v = i960->r[(opcode >> 14) & 0x1e];
+ v |= ((UINT64)(i960->r[((opcode>>14) & 0x1e)+1]))<<32;
+ return u2d(v);
+ } else {
+ int idx = (opcode>>14) & 0x1f;
+ if(idx < 4)
+ return i960->fp[idx];
+ if(idx == 0x16)
+ return 1.0;
+ return 0.0;
+ }
+}
+
+INLINE void set_rifl(i960_state_t *i960, UINT32 opcode, double val)
+{
+ if(!(opcode & 0x00002000)) {
+ UINT64 v = d2u(val);
+ i960->r[(opcode>>19) & 0x1e] = v;
+ i960->r[((opcode>>19) & 0x1e)+1] = v>>32;
+ } else if(!(opcode & 0x00e00000))
+ i960->fp[(opcode>>19) & 3] = val;
+ else
+ fatalerror("I960: %x: set_rifl on literal?", i960->PIP);
+}
+
+INLINE UINT32 get_1_ci(i960_state_t *i960, UINT32 opcode)
+{
+ if(!(opcode & 0x00002000))
+ return i960->r[(opcode >> 19) & 0x1f];
+ else
+ return (opcode >> 19) & 0x1f;
+}
+
+INLINE UINT32 get_2_ci(i960_state_t *i960, UINT32 opcode)
+{
+ return i960->r[(opcode >> 14) & 0x1f];
+}
+
+INLINE UINT32 get_disp(i960_state_t *i960, UINT32 opcode)
+{
+ UINT32 disp;
+ disp = opcode & 0xffffff;
+ if(disp & 0x00800000)
+ disp |= 0xff000000;
+ return disp-4;
+}
+
+INLINE UINT32 get_disp_s(i960_state_t *i960, UINT32 opcode)
+{
+ UINT32 disp;
+ disp = opcode & 0x1fff;
+ if(disp & 0x00001000)
+ disp |= 0xffffe000;
+ return disp-4;
+}
+
+INLINE void cmp_s(i960_state_t *i960, INT32 v1, INT32 v2)
+{
+ i960->AC &= ~7;
+ if(v1<v2)
+ i960->AC |= 4;
+ else if(v1 == v2)
+ i960->AC |= 2;
+ else
+ i960->AC |= 1;
+}
+
+INLINE void cmp_u(i960_state_t *i960, UINT32 v1, UINT32 v2)
+{
+ i960->AC &= ~7;
+ if(v1<v2)
+ i960->AC |= 4;
+ else if(v1 == v2)
+ i960->AC |= 2;
+ else
+ i960->AC |= 1;
+}
+
+INLINE void concmp_s(i960_state_t *i960, INT32 v1, INT32 v2)
+{
+ i960->AC &= ~7;
+ if(v1 <= v2)
+ i960->AC |= 2;
+ else
+ i960->AC |= 1;
+}
+
+INLINE void concmp_u(i960_state_t *i960, UINT32 v1, UINT32 v2)
+{
+ i960->AC &= ~7;
+ if(v1 <= v2)
+ i960->AC |= 2;
+ else
+ i960->AC |= 1;
+}
+
+INLINE void cmp_d(i960_state_t *i960, double v1, double v2)
+{
+ i960->AC &= ~7;
+ if(v1<v2)
+ i960->AC |= 4;
+ else if(v1 == v2)
+ i960->AC |= 2;
+ else if(v1 > v2)
+ i960->AC |= 1;
+}
+
+INLINE void bxx(i960_state_t *i960, UINT32 opcode, int mask)
+{
+ if(i960->AC & mask) {
+ i960->IP += get_disp(i960, opcode);
+ }
+}
+
+INLINE void bxx_s(i960_state_t *i960, UINT32 opcode, int mask)
+{
+ if(i960->AC & mask) {
+ i960->IP += get_disp_s(i960, opcode);
+ }
+}
+
+INLINE void test(i960_state_t *i960, UINT32 opcode, int mask)
+{
+ if(i960->AC & mask)
+ i960->r[(opcode>>19) & 0x1f] = 1;
+ else
+ i960->r[(opcode>>19) & 0x1f] = 0;
+}
+
+INLINE const char *i960_get_strflags(i960_state_t *i960)
+{
+ static const char *const conditions[8] =
+ {
+ "no", "g", "e", "ge", "l", "ne", "le", "o"
+ };
+
+ return (conditions[i960->AC & 7]);
+}
+
+// interrupt dispatch
+static void take_interrupt(i960_state_t *i960, int vector, int lvl)
+{
+ int int_tab = i960->program->read_dword(i960->PRCB+20); // interrupt table
+ int int_SP = i960->program->read_dword(i960->PRCB+24); // interrupt stack
+ int SP;
+ UINT32 IRQV;
+
+ IRQV = i960->program->read_dword(int_tab + 36 + (vector-8)*4);
+
+ // start the process
+ if(!(i960->PC & 0x2000)) // if this is a nested interrupt, don't re-get int_SP
+ {
+ SP = int_SP;
+ }
+ else
+ {
+ SP = i960->r[I960_SP];
+ }
+
+ SP = (SP + 63) & ~63;
+ SP += 128; // emulate ElSemi's core, this fixes the crash in sonic the fighters
+
+ do_call(i960, IRQV, 7, SP);
+
+ // save the processor state
+ i960->program->write_dword(i960->r[I960_FP]-16, i960->PC);
+ i960->program->write_dword(i960->r[I960_FP]-12, i960->AC);
+ // store the vector
+ i960->program->write_dword(i960->r[I960_FP]-8, vector-8);
+
+ i960->PC &= ~0x1f00; // clear priority, state, trace-fault pending, and trace enable
+ i960->PC |= (lvl<<16); // set CPU level to current IRQ level
+ i960->PC |= 0x2002; // set supervisor mode & interrupt flag
+}
+
+static void check_irqs(i960_state_t *i960)
+{
+ int int_tab = i960->program->read_dword(i960->PRCB+20); // interrupt table
+ int cpu_pri = (i960->PC>>16)&0x1f;
+ int pending_pri;
+ int lvl, irq, take = -1;
+ int vword;
+ static const UINT32 lvlmask[4] = { 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 };
+
+ pending_pri = i960->program->read_dword(int_tab); // read pending priorities
+
+ if ((i960->immediate_irq) && ((cpu_pri < i960->immediate_pri) || (i960->immediate_pri == 31)))
+ {
+ take_interrupt(i960, i960->immediate_vector, i960->immediate_pri);
+ i960->immediate_irq = 0;
+ }
+ else
+ {
+ for(lvl = 31; lvl >= 0; lvl--) {
+ if((pending_pri & (1 << lvl)) && ((cpu_pri < lvl) || (lvl == 31))) {
+ int word, wordl, wordh;
+
+ // figure out which word contains this level's priorities
+ word = ((lvl / 4) * 4) + 4; // (lvl/4) = word address, *4 for byte address, +4 to skip pending priorities
+ wordl = (lvl % 4) * 8;
+ wordh = (wordl + 8) - 1;
+
+ vword = i960->program->read_dword(int_tab + word);
+
+ // take the first vector we find for this level
+ for (irq = wordh; irq >= wordl; irq--) {
+ if(vword & (1 << irq)) {
+ // clear pending bit
+ vword &= ~(1 << irq);
+ i960->program->write_dword(int_tab + word, vword);
+ take = irq;
+ break;
+ }
+ }
+
+ // if no vectors were found at our level, it's an error
+ if(take == -1) {
+ logerror("i960: ERROR! no vector found for pending level %d\n", lvl);
+
+ // try to recover...
+ pending_pri &= ~(1 << lvl);
+ i960->program->write_dword(int_tab, pending_pri);
+ return;
+ }
+
+ // if no vectors are waiting for this level, clear the level bit
+ if(!(vword & lvlmask[lvl % 4])) {
+ pending_pri &= ~(1 << lvl);
+ i960->program->write_dword(int_tab, pending_pri);
+ }
+
+ take += ((lvl/4) * 32);
+
+ take_interrupt(i960, take, lvl);
+ return;
+ }
+ }
+ }
+}
+
+static void do_call(i960_state_t *i960, UINT32 adr, int type, UINT32 stack)
+{
+ int i;
+ UINT32 FP;
+
+ // call and callx take 9 cycles base
+ i960->icount -= 9;
+
+ // set the new RIP
+ i960->r[I960_RIP] = i960->IP;
+// mame_printf_debug("CALL (type %d): FP %x, %x => %x, stack %x, rcache_pos %d\n", type, i960->r[I960_FP], i960->r[I960_RIP], adr, stack, i960->rcache_pos);
+
+ // are we out of cache entries?
+ if (i960->rcache_pos >= RCACHE_SIZE) {
+ // flush the current register set to the current frame
+ FP = i960->r[I960_FP] & ~0x3f;
+ for (i = 0; i < 16; i++) {
+ i960->program->write_dword(FP + (i*4), i960->r[i]);
+ }
+ }
+ else // a cache entry is available, use it
+ {
+ memcpy(&i960->rcache[i960->rcache_pos][0], i960->r, 0x10 * sizeof(UINT32));
+ i960->rcache_frame_addr[i960->rcache_pos] = i960->r[I960_FP] & ~0x3f;
+ }
+ i960->rcache_pos++;
+
+ i960->IP = adr;
+ i960->r[I960_PFP] = i960->r[I960_FP] & ~7;
+ i960->r[I960_PFP] |= type;
+
+ if(type == 7) { // interrupts need special handling
+ // set the stack to the passed-in value to properly handle nested interrupts
+ // (can't set it externally or the original program's SP will be lost)
+ i960->r[I960_SP] = stack;
+ }
+
+ i960->r[I960_FP] = (i960->r[I960_SP] + 63) & ~63;
+ i960->r[I960_SP] = i960->r[I960_FP] + 64;
+}
+
+static void do_ret_0(i960_state_t *i960)
+{
+// int type = i960->r[I960_PFP] & 7;
+
+ i960->r[I960_FP] = i960->r[I960_PFP] & ~0x3f;
+
+ i960->rcache_pos--;
+
+ // normal situation: if we're still above rcache size, we're not in cache.
+ // abnormal situation (after the app does a FLUSHREG): rcache_pos will be 0
+ // coming in, but we must still treat it as a not-in-cache situation.
+ if ((i960->rcache_pos >= RCACHE_SIZE) || (i960->rcache_pos < 0))
+ {
+ int i;
+ for(i=0; i<0x10; i++)
+ i960->r[i] = i960->program->read_dword(i960->r[I960_FP]+4*i);
+
+ if (i960->rcache_pos < 0)
+ {
+ i960->rcache_pos = 0;
+ }
+ }
+ else
+ {
+ memcpy(i960->r, i960->rcache[i960->rcache_pos], 0x10*sizeof(UINT32));
+ }
+
+// mame_printf_debug("RET (type %d): FP %x, %x => %x, rcache_pos %d\n", type, i960->r[I960_FP], i960->IP, i960->r[I960_RIP], i960->rcache_pos);
+ i960->IP = i960->r[I960_RIP];
+}
+
+static void do_ret(i960_state_t *i960)
+{
+ UINT32 x, y;
+ i960->icount -= 7;
+ switch(i960->r[I960_PFP] & 7) {
+ case 0:
+ do_ret_0(i960);
+ break;
+
+ case 7:
+ x = i960->program->read_dword(i960->r[I960_FP]-16);
+ y = i960->program->read_dword(i960->r[I960_FP]-12);
+ do_ret_0(i960);
+ i960->AC = y;
+ // #### test supervisor
+ i960->PC = x;
+
+ // check for another IRQ now that we're back
+ check_irqs(i960);
+ break;
+
+ default:
+ fatalerror("I960: %x: Unsupported return mode %d", i960->PIP, i960->r[I960_PFP] & 7);
+ }
+}
+
+INLINE void execute_op(i960_state_t *i960, UINT32 opcode)
+{
+ UINT32 t1, t2;
+ double t1f, t2f;
+
+ switch(opcode >> 24) {
+ case 0x08: // b
+ i960->icount--;
+ i960->IP += get_disp(i960, opcode);
+ break;
+
+ case 0x09: // call
+ do_call(i960, i960->IP+get_disp(i960, opcode), 0, i960->r[I960_SP]);
+ break;
+
+ case 0x0a: // ret
+ do_ret(i960);
+ break;
+
+ case 0x0b: // bal
+ i960->icount -= 5;
+ i960->r[0x1e] = i960->IP;
+ i960->IP += get_disp(i960, opcode);
+ break;
+
+ case 0x10: // bno
+ i960->icount--;
+ if(!(i960->AC & 7)) {
+ i960->IP += get_disp(i960, opcode);
+ }
+ break;
+
+ case 0x11: // bg
+ i960->icount--;
+ bxx(i960, opcode, 1);
+ break;
+
+ case 0x12: // be
+ i960->icount--;
+ bxx(i960, opcode, 2);
+ break;
+
+ case 0x13: // bge
+ i960->icount--;
+ bxx(i960, opcode, 3);
+ break;
+
+ case 0x14: // bl
+ i960->icount--;
+ bxx(i960, opcode, 4);
+ break;
+
+ case 0x15: // bne
+ i960->icount--;
+ bxx(i960, opcode, 5);
+ break;
+
+ case 0x16: // ble
+ i960->icount--;
+ bxx(i960, opcode, 6);
+ break;
+
+ case 0x17: // bo
+ i960->icount--;
+ bxx(i960, opcode, 7);
+ break;
+
+ case 0x20: // testno
+ i960->icount--;
+ if(!(i960->AC & 7))
+ i960->r[(opcode>>19) & 0x1f] = 1;
+ else
+ i960->r[(opcode>>19) & 0x1f] = 0;
+ break;
+
+ case 0x21: // testg
+ i960->icount--;
+ test(i960, opcode, 1);
+ break;
+
+ case 0x22: // teste
+ i960->icount--;
+ test(i960, opcode, 2);
+ break;
+
+ case 0x23: // testge
+ i960->icount--;
+ test(i960, opcode, 3);
+ break;
+
+ case 0x24: // testl
+ i960->icount--;
+ test(i960, opcode, 4);
+ break;
+
+ case 0x25: // testne
+ i960->icount--;
+ test(i960, opcode, 5);
+ break;
+
+ case 0x26: // testle
+ i960->icount--;
+ test(i960, opcode, 6);
+ break;
+
+ case 0x27: // testo
+ i960->icount--;
+ test(i960, opcode, 7);
+ break;
+
+ case 0x30: // bbc
+ i960->icount -= 4;
+ t1 = get_1_ci(i960, opcode) & 0x1f;
+ t2 = get_2_ci(i960, opcode);
+ if(!(t2 & (1<<t1))) {
+ i960->AC = (i960->AC & ~7) | 2;
+ i960->IP += get_disp_s(i960, opcode);
+ } else
+ i960->AC &= ~7;
+ break;
+
+ case 0x31: // cmp0bg
+ i960->icount -= 4;
+ t1 = get_1_ci(i960, opcode);
+ t2 = get_2_ci(i960, opcode);
+ cmp_u(i960, t1, t2);
+ bxx_s(i960, opcode, 1);
+ break;
+
+ case 0x32: // cmpobe
+ i960->icount -= 4;
+ t1 = get_1_ci(i960, opcode);
+ t2 = get_2_ci(i960, opcode);
+ cmp_u(i960, t1, t2);
+ bxx_s(i960, opcode, 2);
+ break;
+
+ case 0x33: // cmpobge
+ i960->icount -= 4;
+ t1 = get_1_ci(i960, opcode);
+ t2 = get_2_ci(i960, opcode);
+ cmp_u(i960, t1, t2);
+ bxx_s(i960, opcode, 3);
+ break;
+
+ case 0x34: // cmpobl
+ i960->icount -= 4;
+ t1 = get_1_ci(i960, opcode);
+ t2 = get_2_ci(i960, opcode);
+ cmp_u(i960, t1, t2);
+ bxx_s(i960, opcode, 4);
+ break;
+
+ case 0x35: // cmpobne
+ i960->icount -= 4;
+ t1 = get_1_ci(i960, opcode);
+ t2 = get_2_ci(i960, opcode);
+ cmp_u(i960, t1, t2);
+ bxx_s(i960, opcode, 5);
+ break;
+
+ case 0x36: // cmpoble
+ i960->icount -= 4;
+ t1 = get_1_ci(i960, opcode);
+ t2 = get_2_ci(i960, opcode);
+ cmp_u(i960, t1, t2);
+ bxx_s(i960, opcode, 6);
+ break;
+
+ case 0x37: // bbs
+ i960->icount -= 4;
+ t1 = get_1_ci(i960, opcode) & 0x1f;
+ t2 = get_2_ci(i960, opcode);
+ if(t2 & (1<<t1)) {
+ i960->AC = (i960->AC & ~7) | 2;
+ i960->IP += get_disp_s(i960, opcode);
+ } else
+ i960->AC &= ~7;
+ break;
+
+ case 0x39: // cmpibg
+ i960->icount -= 4;
+ t1 = get_1_ci(i960, opcode);
+ t2 = get_2_ci(i960, opcode);
+ cmp_s(i960, t1, t2);
+ bxx_s(i960, opcode, 1);
+ break;
+
+ case 0x3a: // cmpibe
+ i960->icount -= 4;
+ t1 = get_1_ci(i960, opcode);
+ t2 = get_2_ci(i960, opcode);
+ cmp_s(i960, t1, t2);
+ bxx_s(i960, opcode, 2);
+ break;
+
+ case 0x3b: // cmpibge
+ i960->icount -= 4;
+ t1 = get_1_ci(i960, opcode);
+ t2 = get_2_ci(i960, opcode);
+ cmp_s(i960, t1, t2);
+ bxx_s(i960, opcode, 3);
+ break;
+
+ case 0x3c: // cmpibl
+ i960->icount -= 4;
+ t1 = get_1_ci(i960, opcode);
+ t2 = get_2_ci(i960, opcode);
+ cmp_s(i960, t1, t2);
+ bxx_s(i960, opcode, 4);
+ break;
+
+ case 0x3d: // cmpibne
+ i960->icount -= 4;
+ t1 = get_1_ci(i960, opcode);
+ t2 = get_2_ci(i960, opcode);
+ cmp_s(i960, t1, t2);
+ bxx_s(i960, opcode, 5);
+ break;
+
+ case 0x3e: // cmpible
+ i960->icount -= 4;
+ t1 = get_1_ci(i960, opcode);
+ t2 = get_2_ci(i960, opcode);
+ cmp_s(i960, t1, t2);
+ bxx_s(i960, opcode, 6);
+ break;
+
+ case 0x58:
+ switch((opcode >> 7) & 0xf) {
+ case 0x0: // notbit
+ i960->icount -= 2;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ set_ri(i960, opcode, t2 ^ (1<<(t1 & 31)));
+ break;
+
+ case 0x1: // and
+ i960->icount--;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ set_ri(i960, opcode, t2 & t1);
+ break;
+
+ case 0x2: // andnot
+ i960->icount--;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ set_ri(i960, opcode, t2 & ~t1);
+ break;
+
+ case 0x3: // setbit
+ i960->icount -= 2;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ set_ri(i960, opcode, t2 | (1<<(t1 & 31)));
+ break;
+
+ case 0x4: // notand
+ i960->icount--;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ set_ri(i960, opcode, (~t2) & t1);
+ break;
+
+ case 0x6: // xor
+ i960->icount--;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ set_ri(i960, opcode, t2 ^ t1);
+ break;
+
+ case 0x7: // or
+ i960->icount--;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ set_ri(i960, opcode, t2 | t1);
+ break;
+
+ case 0x8: // nor
+ i960->icount--;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ set_ri(i960, opcode, ((~t2) & (~t1)));
+ break;
+
+ case 0x9: // xnor
+ i960->icount--;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ set_ri(i960, opcode, ~(t2 ^ t1));
+ break;
+
+ case 0xa: // not
+ i960->icount--;
+ t1 = get_1_ri(i960, opcode);
+ set_ri(i960, opcode, ~t1);
+ break;
+
+ case 0xb: // ornot
+ i960->icount--;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ set_ri(i960, opcode, t2 | ~t1);
+ break;
+
+ case 0xc: // clrbit
+ i960->icount -= 2;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ set_ri(i960, opcode, t2 & ~(1<<(t1 & 31)));
+ break;
+
+ case 0xd: // notor
+ i960->icount--;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ set_ri(i960, opcode, (~t2) | t1);
+ break;
+
+ case 0xe: // nand
+ i960->icount -= 2;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ set_ri(i960, opcode, ~t2 | ~t1);
+ break;
+
+ case 0xf: // alterbit
+ i960->icount -= 2;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ if(i960->AC & 2)
+ set_ri(i960, opcode, t2 | (1<<(t1 & 31)));
+ else
+ set_ri(i960, opcode, t2 & ~(1<<(t1 & 31)));
+ break;
+
+ default:
+ fatalerror("I960: %x: Unhandled 58.%x", i960->PIP, (opcode >> 7) & 0xf);
+ }
+ break;
+
+ case 0x59:
+ switch((opcode >> 7) & 0xf) {
+ case 0x0: // addo
+ i960->icount--;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ set_ri(i960, opcode, t2+t1);
+ break;
+
+ case 0x1: // addi
+ // #### overflow
+ i960->icount--;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ set_ri(i960, opcode, t2+t1);
+ break;
+
+ case 0x2: // subo
+ i960->icount--;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ set_ri(i960, opcode, t2-t1);
+ break;
+
+ case 0x3: // subi
+ // #### overflow
+ i960->icount--;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ set_ri(i960, opcode, t2-t1);
+ break;
+
+ case 0x8: // shro
+ i960->icount--;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ set_ri(i960, opcode, t2>>t1);
+ break;
+
+ case 0xa: // shrdi
+ i960->icount--;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ if(((INT32)t2) < 0) {
+ if(t2 & ((1<<t1)-1))
+ set_ri(i960, opcode, (((INT32)t2)>>t1)+1);
+ else
+ set_ri(i960, opcode, ((INT32)t2)>>t1);
+ } else
+ set_ri(i960, opcode, t2>>t1);
+ break;
+
+ case 0xb: // shri
+ i960->icount--;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ set_ri(i960, opcode, ((INT32)t2)>>t1);
+ break;
+
+ case 0xc: // shlo
+ i960->icount--;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ set_ri(i960, opcode, t2<<t1);
+ break;
+
+ case 0xd: // rotate
+ i960->icount--;
+ t1 = get_1_ri(i960, opcode) & 0x1f;
+ t2 = get_2_ri(i960, opcode);
+ set_ri(i960, opcode, (t2<<t1)|(t2>>(32-t1)));
+ break;
+
+ case 0xe: // shli
+ // missing overflow
+ i960->icount--;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ set_ri(i960, opcode, t2<<t1);
+ break;
+
+ default:
+ fatalerror("I960: %x: Unhandled 59.%x", i960->PIP, (opcode >> 7) & 0xf);
+ }
+ break;
+
+ case 0x5a:
+ switch((opcode >> 7) & 0xf) {
+ case 0x0: // cmpo
+ i960->icount--;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ cmp_u(i960, t1, t2);
+ break;
+
+ case 0x1: // cmpi
+ i960->icount--;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ cmp_s(i960, t1, t2);
+ break;
+
+ case 0x2: // concmpo
+ i960->icount--;
+ if(!(i960->AC & 0x4)) {
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ concmp_u(i960, t1, t2);
+ }
+ break;
+
+ case 0x3: // concmpi
+ i960->icount--;
+ if(!(i960->AC & 0x4)) {
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ concmp_s(i960, t1, t2);
+ }
+ break;
+
+ case 0x4: // cmpinco
+ i960->icount -= 2;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ cmp_u(i960, t1, t2);
+ set_ri(i960, opcode, t2+1);
+ break;
+
+ case 0x5: // cmpinci
+ i960->icount -= 2;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ cmp_s(i960, t1, t2);
+ set_ri(i960, opcode, t2+1);
+ break;
+
+ case 0x6: // cmpdeco
+ i960->icount -= 2;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ cmp_u(i960, t1, t2);
+ set_ri(i960, opcode, t2-1);
+ break;
+
+ case 0x7: // cmpdeci
+ i960->icount -= 2;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ cmp_s(i960, t1, t2);
+ set_ri(i960, opcode, t2-1);
+ break;
+
+ case 0xe: // chkbit
+ i960->icount -= 2;
+ t1 = get_1_ri(i960, opcode) & 0x1f;
+ t2 = get_2_ri(i960, opcode);
+ if(t2 & (1<<t1))
+ i960->AC = (i960->AC & ~7) | 2;
+ else
+ i960->AC &= ~7;
+ break;
+
+ default:
+ fatalerror("I960: %x: Unhandled 5a.%x", i960->PIP, (opcode >> 7) & 0xf);
+ }
+ break;
+
+ case 0x5b:
+ switch((opcode >> 7) & 0xf) {
+ case 0x0: // addc
+ {
+ UINT64 res;
+
+ i960->icount -= 2;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ res = t2+(t1+((i960->AC>>1)&1));
+ set_ri(i960, opcode, res&0xffffffff);
+
+ i960->AC &= ~0x3; // clear C and V
+ // set carry
+ i960->AC |= ((res) & (((UINT64)1) << 32)) ? 0x2 : 0;
+ // set overflow
+ i960->AC |= (((res) ^ (t1)) & ((res) ^ (t2)) & 0x80000000) ? 1: 0;
+ }
+ break;
+
+ case 0x2: // subc
+ {
+ UINT64 res;
+
+ i960->icount -= 2;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ res = t2-(t1+((i960->AC>>1)&1));
+ set_ri(i960, opcode, res&0xffffffff);
+
+ i960->AC &= ~0x3; // clear C and V
+ // set carry
+ i960->AC |= ((res) & (((UINT64)1) << 32)) ? 0x2 : 0;
+ // set overflow
+ i960->AC |= (((t2) ^ (t1)) & ((t2) ^ (res)) & 0x80000000) ? 1 : 0;
+ }
+ break;
+
+ default:
+ fatalerror("I960: %x: Unhandled 5b.%x", i960->PIP, (opcode >> 7) & 0xf);
+ }
+ break;
+
+ case 0x5c:
+ switch((opcode >> 7) & 0xf) {
+ case 0xc: // mov
+ i960->icount -= 2;
+ t1 = get_1_ri(i960, opcode);
+ set_ri(i960, opcode, t1);
+ break;
+
+ default:
+ fatalerror("I960: %x: Unhandled 5c.%x", i960->PIP, (opcode >> 7) & 0xf);
+ }
+ break;
+
+ case 0x5d:
+ switch((opcode >> 7) & 0xf) {
+ case 0xc: // movl
+ i960->icount -= 2;
+ t2 = (opcode>>19) & 0x1e;
+ if(opcode & 0x00000800) { // litteral
+ t1 = opcode & 0x1f;
+ i960->r[t2] = i960->r[t2+1] = t1;
+ } else
+ memcpy(i960->r+t2, i960->r+(opcode & 0x1f), 2*sizeof(UINT32));
+ break;
+
+ default:
+ fatalerror("I960: %x: Unhandled 5d.%x", i960->PIP, (opcode >> 7) & 0xf);
+ }
+ break;
+
+ case 0x5e:
+ switch((opcode >> 7) & 0xf) {
+ case 0xc: // movt
+ i960->icount -= 3;
+ t2 = (opcode>>19) & 0x1c;
+ if(opcode & 0x00000800) { // litteral
+ t1 = opcode & 0x1f;
+ i960->r[t2] = i960->r[t2+1] = i960->r[t2+2]= t1;
+ } else
+ memcpy(i960->r+t2, i960->r+(opcode & 0x1f), 3*sizeof(UINT32));
+ break;
+
+ default:
+ fatalerror("I960: %x: Unhandled 5e.%x", i960->PIP, (opcode >> 7) & 0xf);
+ }
+ break;
+
+ case 0x5f:
+ switch((opcode >> 7) & 0xf) {
+ case 0xc: // movq
+ i960->icount -= 4;
+ t2 = (opcode>>19) & 0x1c;
+ if(opcode & 0x00000800) { // litteral
+ t1 = opcode & 0x1f;
+ i960->r[t2] = i960->r[t2+1] = i960->r[t2+2] = i960->r[t2+3] = t1;
+ } else
+ memcpy(i960->r+t2, i960->r+(opcode & 0x1f), 4*sizeof(UINT32));
+ break;
+
+ default:
+ fatalerror("I960: %x: Unhandled 5f.%x", i960->PIP, (opcode >> 7) & 0xf);
+ }
+ break;
+
+ case 0x60:
+ switch((opcode >> 7) & 0xf) {
+ case 0x0: // synmov
+ i960->icount -= 6;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ // interrupt control register
+ if(t1 == 0xff000004)
+ i960->ICR = i960->program->read_dword(t2);
+ else
+ i960->program->write_dword(t1, i960->program->read_dword(t2));
+ i960->AC = (i960->AC & ~7) | 2;
+ break;
+
+ case 0x2: // synmovq
+ i960->icount -= 12;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ if(t1 == 0xff000010)
+ send_iac(i960, t2);
+ else {
+ i960->program->write_dword(t1, i960->program->read_dword(t2));
+ i960->program->write_dword(t1+4, i960->program->read_dword(t2+4));
+ i960->program->write_dword(t1+8, i960->program->read_dword(t2+8));
+ i960->program->write_dword(t1+12, i960->program->read_dword(t2+12));
+ }
+ i960->AC = (i960->AC & ~7) | 2;
+ break;
+
+ default:
+ fatalerror("I960: %x: Unhandled 60.%x", i960->PIP, (opcode >> 7) & 0xf);
+ }
+ break;
+
+ case 0x64:
+ switch((opcode >> 7) & 0xf) {
+ case 0x0: // spanbit
+ {
+ UINT32 res = 0xffffffff;
+ int i;
+
+ i960->icount -= 10;
+
+ t1 = get_1_ri(i960, opcode);
+ i960->AC &= ~7;
+
+ for (i = 31; i >= 0; i--)
+ {
+ if (!(t1 & (1<<i)))
+ {
+ i960->AC |= 2;
+ res = i;
+ break;
+ }
+ }
+
+ set_ri(i960, opcode, res);
+ }
+ break;
+
+ case 0x1: // scanbit
+ {
+ UINT32 res = 0xffffffff;
+ int i;
+
+ i960->icount -= 10;
+
+ t1 = get_1_ri(i960, opcode);
+ i960->AC &= ~7;
+
+ for (i = 31; i >= 0; i--)
+ {
+ if (t1 & (1<<i))
+ {
+ i960->AC |= 2;
+ res = i;
+ break;
+ }
+ }
+
+ set_ri(i960, opcode, res);
+ }
+ break;
+
+ case 0x5: // modac
+ i960->icount -= 10;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ set_ri(i960, opcode, i960->AC);
+ i960->AC = (i960->AC & ~t1) | (t2 & t1);
+ break;
+
+ default:
+ fatalerror("I960: %x: Unhandled 64.%x", i960->PIP, (opcode >> 7) & 0xf);
+ }
+ break;
+
+ case 0x65:
+ switch((opcode >> 7) & 0xf) {
+ case 0x5: // modpc
+ i960->icount -= 10;
+ t1 = i960->PC;
+ t2 = get_2_ri(i960, opcode);
+ i960->PC = (i960->PC & ~t2) | (i960->r[(opcode>>19) & 0x1f] & t2);
+ set_ri(i960, opcode, t1);
+ break;
+
+ default:
+ fatalerror("I960: %x: Unhandled 65.%x", i960->PIP, (opcode >> 7) & 0xf);
+ }
+ break;
+
+ case 0x66:
+ switch((opcode >> 7) & 0xf) {
+ case 0xd: // flushreg
+ if (i960->rcache_pos > 4)
+ {
+ i960->rcache_pos = 4;
+ }
+ for(t1=0; t1 < i960->rcache_pos; t1++)
+ {
+ int i;
+
+ for (i = 0; i < 0x10; i++)
+ {
+ i960->program->write_dword(i960->rcache_frame_addr[t1] + (i * sizeof(UINT32)), i960->rcache[t1][i]);
+ }
+ }
+ i960->rcache_pos = 0;
+ break;
+
+ default:
+ fatalerror("I960: %x: Unhandled 66.%x", i960->PIP, (opcode >> 7) & 0xf);
+ }
+ break;
+
+ case 0x67:
+ switch((opcode >> 7) & 0xf) {
+ case 0x0: // emul
+ i960->icount -= 37;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+
+ set_ri64(i960, opcode, (INT64)t1 * (INT64)t2);
+ break;
+
+ case 0x1: // ediv
+ i960->icount -= 37;
+ {
+ UINT64 src1, src2;
+
+ src1 = get_1_ri(i960, opcode);
+ src2 = get_2_ri64(i960, opcode);
+
+ set_ri2(i960, opcode, src2 % src1, src2 / src1);
+ }
+ break;
+
+ case 0x4: // cvtir
+ i960->icount -= 30;
+ t1 = get_1_ri(i960, opcode);
+ set_rif(i960, opcode, (double)(INT32)t1);
+ break;
+
+ case 0x6: // scalerl
+ i960->icount -= 30;
+ t1 = get_1_ri(i960, opcode);
+ t2f = get_2_rifl(i960, opcode);
+ set_rifl(i960, opcode, t2f * pow(2.0, (double)(INT32)t1));
+ break;
+
+ case 0x7: // scaler
+ i960->icount -= 30;
+ t1 = get_1_ri(i960, opcode);
+ t2f = get_2_rif(i960, opcode);
+ set_rif(i960, opcode, t2f * pow(2.0, (double)(INT32)t1));
+ break;
+
+ default:
+ fatalerror("I960: %x: Unhandled 67.%x", i960->PIP, (opcode >> 7) & 0xf);
+ }
+ break;
+
+ case 0x68:
+ switch((opcode >> 7) & 0xf) {
+ case 0x0: // atanr
+ i960->icount -= 267;
+ t1f = get_1_rif(i960, opcode);
+ t2f = get_2_rif(i960, opcode);
+ set_rif(i960, opcode, atan2(t2f, t1f));
+ break;
+
+ case 0x1: // logepr
+ i960->icount -= 400;
+ t1f = get_1_rif(i960, opcode);
+ t2f = get_2_rif(i960, opcode);
+ set_rif(i960, opcode, t2f*log(t1f+1.0)/log(2.0));
+ break;
+
+ case 0x3: // remr
+ i960->icount -= 67; // (67 to 75878 depending on opcodes!!!)
+ t1f = get_1_rif(i960, opcode);
+ t2f = get_2_rif(i960, opcode);
+ set_rif(i960, opcode, fmod(t2f, t1f));
+ break;
+
+ case 0x5: // cmpr
+ i960->icount -= 10;
+ t1f = get_1_rif(i960, opcode);
+ t2f = get_2_rif(i960, opcode);
+ cmp_d(i960, t1f, t2f);
+ break;
+
+ case 0x8: // sqrtr
+ i960->icount -= 104;
+ t1f = get_1_rif(i960, opcode);
+ set_rif(i960, opcode, sqrt(t1f));
+ break;
+
+ case 0xa: // logbnr
+ i960->icount -= 37;
+ t1f = get_1_rif(i960, opcode);
+ set_rif(i960, opcode, logb(t1f));
+ break;
+
+ case 0xb: // roundr
+ {
+ INT32 st1 = get_1_rif(i960, opcode);
+ i960->icount -= 69;
+ set_rif(i960, opcode, (double)st1);
+ }
+ break;
+
+ case 0xc: // sinr
+ i960->icount -= 406;
+ t1f = get_1_rif(i960, opcode);
+ set_rif(i960, opcode, sin(t1f));
+ break;
+
+ case 0xd: // cosr
+ i960->icount -= 406;
+ t1f = get_1_rif(i960, opcode);
+ set_rif(i960, opcode, sin(t1f));
+ break;
+
+ case 0xe: // tanr
+ i960->icount -= 293;
+ t1f = get_1_rif(i960, opcode);
+ set_rif(i960, opcode, tan(t1f));
+ break;
+
+ default:
+ fatalerror("I960: %x: Unhandled 68.%x", i960->PIP, (opcode >> 7) & 0xf);
+ }
+ break;
+
+ case 0x69:
+ switch((opcode >> 7) & 0xf) {
+ case 0x0: // atanrl
+ i960->icount -= 350;
+ t1f = get_1_rifl(i960, opcode);
+ t2f = get_2_rifl(i960, opcode);
+ set_rifl(i960, opcode, atan2(t2f, t1f));
+ break;
+
+ case 0x2: // logrl
+ i960->icount -= 438;
+ t1f = get_1_rifl(i960, opcode);
+ set_rifl(i960, opcode, log(t1f));
+ break;
+
+ case 0x5: // cmprl
+ i960->icount -= 12;
+ t1f = get_1_rifl(i960, opcode);
+ t2f = get_2_rifl(i960, opcode);
+ cmp_d(i960, t1f, t2f);
+ break;
+
+ case 0x8: // sqrtrl
+ i960->icount -= 104;
+ t1f = get_1_rifl(i960, opcode);
+ set_rifl(i960, opcode, sqrt(t1f));
+ break;
+
+ case 0x9: // exprl
+ i960->icount -= 334;
+ t1f = get_1_rifl(i960, opcode);
+ set_rifl(i960, opcode, pow(2.0, t1f)-1.0);
+ break;
+
+ case 0xa: // logbnrl
+ i960->icount -= 37;
+ t1f = get_1_rifl(i960, opcode);
+ set_rifl(i960, opcode, logb(t1f));
+ break;
+
+ case 0xb: // roundrl
+ {
+ INT32 st1 = get_1_rifl(i960, opcode);
+ i960->icount -= 70;
+ set_rifl(i960, opcode, (double)st1);
+ }
+ break;
+
+ case 0xc: // sinrl
+ i960->icount -= 441;
+ t1f = get_1_rifl(i960, opcode);
+ set_rifl(i960, opcode, sin(t1f));
+ break;
+
+ case 0xd: // cosrl
+ i960->icount -= 441;
+ t1f = get_1_rifl(i960, opcode);
+ set_rifl(i960, opcode, cos(t1f));
+ break;
+
+ case 0xe: // tanrl
+ i960->icount -= 323;
+ t1f = get_1_rifl(i960, opcode);
+ set_rifl(i960, opcode, tan(t1f));
+ break;
+
+ default:
+ fatalerror("I960: %x: Unhandled 69.%x", i960->PIP, (opcode >> 7) & 0xf);
+ }
+ break;
+
+ case 0x6c:
+ switch((opcode >> 7) & 0xf) {
+ case 0x0: // cvtri
+ i960->icount -= 33;
+ t1f = get_1_rif(i960, opcode);
+ // apply rounding mode
+ // we do this a little indirectly to avoid some odd GCC warnings
+ t2f = 0.0;
+ switch((i960->AC>>30)&3)
+ {
+ case 0: t2f = floor(t1f+0.5); break;
+ case 1: t2f = floor(t1f); break;
+ case 2: t2f = ceil(t1f); break;
+ case 3: t2f = t1f; break;
+ }
+ set_ri(i960, opcode, (INT32)t2f);
+ break;
+
+ case 0x2: // cvtzri
+ i960->icount -= 43;
+ t1f = get_1_rif(i960, opcode);
+ set_ri(i960, opcode, (INT32)t1f);
+ break;
+
+ case 0x3: // cvtzril
+ i960->icount -= 44;
+ t1f = get_1_rif(i960, opcode);
+ set_ri64(i960, opcode, (INT64)t1f);
+ break;
+
+ case 0x9: // movr
+ i960->icount -= 5;
+ t1f = get_1_rif(i960, opcode);
+ set_rif(i960, opcode, t1f);
+ break;
+
+ default:
+ fatalerror("I960: %x: Unhandled 6c.%x", i960->PIP, (opcode >> 7) & 0xf);
+ }
+ break;
+
+ case 0x6d:
+ switch((opcode >> 7) & 0xf) {
+ case 0x9: // movrl
+ i960->icount -= 6;
+ t1f = get_1_rifl(i960, opcode);
+ set_rifl(i960, opcode, t1f);
+ break;
+
+ default:
+ fatalerror("I960: %x: Unhandled 6d.%x", i960->PIP, (opcode >> 7) & 0xf);
+ }
+ break;
+
+ case 0x6e:
+ switch((opcode >> 7) & 0xf) {
+ case 0x1: // movre
+ {
+ UINT32 *src=0, *dst=0;
+
+ i960->icount -= 8;
+
+ if(!(opcode & 0x00000800)) {
+ src = (UINT32 *)&i960->r[opcode & 0x1e];
+ } else {
+ int idx = opcode & 0x1f;
+ if(idx < 4)
+ src = (UINT32 *)&i960->fp[idx];
+ }
+
+ if(!(opcode & 0x00002000)) {
+ dst = (UINT32 *)&i960->r[(opcode>>19) & 0x1e];
+ } else if(!(opcode & 0x00e00000))
+ dst = (UINT32 *)&i960->fp[(opcode>>19) & 3];
+
+ dst[0] = src[0];
+ dst[1] = src[1];
+ dst[2] = src[2]&0xffff;
+ }
+ break;
+ case 0x2: // cpysre
+ i960->icount -= 8;
+ t1f = get_1_rifl(i960, opcode);
+ t2f = get_2_rifl(i960, opcode);
+
+ if (t2f >= 0.0)
+ set_rifl(i960, opcode, fabs(t1f));
+ else
+ set_rifl(i960, opcode, -fabs(t1f));
+ break;
+ default:
+ fatalerror("I960: %x: Unhandled 6e.%x", i960->PIP, (opcode >> 7) & 0xf);
+ }
+ break;
+
+ case 0x70:
+ switch((opcode >> 7) & 0xf) {
+ case 0x1: // mulo
+ i960->icount -= 18;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ set_ri(i960, opcode, t2*t1);
+ break;
+
+ case 0x8: // remo
+ i960->icount -= 37;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ set_ri(i960, opcode, t2%t1);
+ break;
+
+ case 0xb: // divo
+ i960->icount -= 37;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ if (t1 == 0) // HACK!
+ set_ri(i960, opcode, 0);
+ else
+ set_ri(i960, opcode, t2/t1);
+ break;
+
+ default:
+ fatalerror("I960: %x: Unhandled 70.%x", i960->PIP, (opcode >> 7) & 0xf);
+ }
+ break;
+
+ case 0x74:
+ switch((opcode >> 7) & 0xf) {
+ case 0x1: // muli
+ i960->icount -= 18;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ set_ri(i960, opcode, ((INT32)t2)*((INT32)t1));
+ break;
+
+ case 0x8: // remi
+ i960->icount -= 37;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ set_ri(i960, opcode, ((INT32)t2)%((INT32)t1));
+ break;
+
+ case 0x9:{// modi
+ INT32 src1, src2, dst;
+ i960->icount -= 37;
+ src1 = (INT32)get_1_ri(i960, opcode);
+ src2 = (INT32)get_2_ri(i960, opcode);
+ dst = src2 - ((src2/src1)*src1);
+ if(((src2*src1) < 0) && (dst != 0))
+ dst += src1;
+ set_ri(i960, opcode, dst);
+ break;
+ }
+
+ case 0xb: // divi
+ i960->icount -= 37;
+ t1 = get_1_ri(i960, opcode);
+ t2 = get_2_ri(i960, opcode);
+ set_ri(i960, opcode, ((INT32)t2)/((INT32)t1));
+ break;
+
+ default:
+ fatalerror("I960: %x: Unhandled 74.%x", i960->PIP, (opcode >> 7) & 0xf);
+ }
+ break;
+
+ case 0x78:
+ switch((opcode >> 7) & 0xf) {
+ case 0xb: // divr
+ i960->icount -= 35;
+ t1f = get_1_rif(i960, opcode);
+ t2f = get_2_rif(i960, opcode);
+ set_rif(i960, opcode, t2f/t1f);
+ break;
+
+ case 0xc: // mulr
+ i960->icount -= 18;
+ t1f = get_1_rif(i960, opcode);
+ t2f = get_2_rif(i960, opcode);
+ set_rif(i960, opcode, t2f*t1f);
+ break;
+
+ case 0xd: // subr
+ i960->icount -= 10;
+ t1f = get_1_rif(i960, opcode);
+ t2f = get_2_rif(i960, opcode);
+ set_rif(i960, opcode, t2f-t1f);
+ break;
+
+ case 0xf: // addr
+ i960->icount -= 10;
+ t1f = get_1_rif(i960, opcode);
+ t2f = get_2_rif(i960, opcode);
+ set_rif(i960, opcode, t2f+t1f);
+ break;
+
+ default:
+ fatalerror("I960: %x: Unhandled 78.%x", i960->PIP, (opcode >> 7) & 0xf);
+ }
+ break;
+
+ case 0x79:
+ switch((opcode >> 7) & 0xf) {
+ case 0xb: // divrl
+ i960->icount -= 77;
+ t1f = get_1_rifl(i960, opcode);
+ t2f = get_2_rifl(i960, opcode);
+ set_rifl(i960, opcode, t2f/t1f);
+ break;
+
+ case 0xc: // mulrl
+ i960->icount -= 36;
+ t1f = get_1_rifl(i960, opcode);
+ t2f = get_2_rifl(i960, opcode);
+ set_rifl(i960, opcode, t2f*t1f);
+ break;
+
+ case 0xd: // subrl
+ i960->icount -= 13;
+ t1f = get_1_rifl(i960, opcode);
+ t2f = get_2_rifl(i960, opcode);
+ set_rifl(i960, opcode, t2f-t1f);
+ break;
+
+ case 0xf: // addrl
+ i960->icount -= 13;
+ t1f = get_1_rifl(i960, opcode);
+ t2f = get_2_rifl(i960, opcode);
+ set_rifl(i960, opcode, t2f+t1f);
+ break;
+
+ default:
+ fatalerror("I960: %x: Unhandled 79.%x", i960->PIP, (opcode >> 7) & 0xf);
+ }
+ break;
+
+ case 0x80: // ldob
+ i960->icount -= 4;
+ i960->r[(opcode>>19)&0x1f] = i960->program->read_byte(get_ea(i960, opcode));
+ break;
+
+ case 0x82: // stob
+ i960->icount -= 2;
+ i960->program->write_byte(get_ea(i960, opcode), i960->r[(opcode>>19)&0x1f]);
+ break;
+
+ case 0x84: // bx
+ i960->icount -= 3;
+ i960->IP = get_ea(i960, opcode);
+ break;
+
+ case 0x85: // balx
+ i960->icount -= 5;
+ t1 = get_ea(i960, opcode);
+ i960->r[(opcode>>19)&0x1f] = i960->IP;
+ i960->IP = t1;
+ break;
+
+ case 0x86: // callx
+ t1 = get_ea(i960, opcode);
+ do_call(i960, t1, 0, i960->r[I960_SP]);
+ break;
+
+ case 0x88: // ldos
+ i960->icount -= 4;
+ i960->r[(opcode>>19)&0x1f] = i960_read_word_unaligned(i960, get_ea(i960, opcode));
+ break;
+
+ case 0x8a: // stos
+ i960->icount -= 2;
+ i960_write_word_unaligned(i960, get_ea(i960, opcode), i960->r[(opcode>>19)&0x1f]);
+ break;
+
+ case 0x8c: // lda
+ i960->icount--;
+ i960->r[(opcode>>19)&0x1f] = get_ea(i960, opcode);
+ break;
+
+ case 0x90: // ld
+ i960->icount -= 4;
+ i960->r[(opcode>>19)&0x1f] = i960_read_dword_unaligned(i960, get_ea(i960, opcode));
+ break;
+
+ case 0x92: // st
+ i960->icount -= 2;
+ i960_write_dword_unaligned(i960, get_ea(i960, opcode), i960->r[(opcode>>19)&0x1f]);
+ break;
+
+ case 0x98:{// ldl
+ int i;
+ i960->icount -= 5;
+ t1 = get_ea(i960, opcode);
+ t2 = (opcode>>19)&0x1e;
+ i960->bursting = 1;
+ for(i=0; i<2; i++) {
+ i960->r[t2+i] = i960_read_dword_unaligned(i960, t1);
+ if(i960->bursting)
+ t1 += 4;
+ }
+ break;
+ }
+
+ case 0x9a:{// stl
+ int i;
+ i960->icount -= 3;
+ t1 = get_ea(i960, opcode);
+ t2 = (opcode>>19)&0x1e;
+ i960->bursting = 1;
+ for(i=0; i<2; i++) {
+ i960_write_dword_unaligned(i960, t1, i960->r[t2+i]);
+ if(i960->bursting)
+ t1 += 4;
+ }
+ break;
+ }
+
+ case 0xa0:{// ldt
+ int i;
+ i960->icount -= 6;
+ t1 = get_ea(i960, opcode);
+ t2 = (opcode>>19)&0x1c;
+ i960->bursting = 1;
+ for(i=0; i<3; i++) {
+ i960->r[t2+i] = i960_read_dword_unaligned(i960, t1);
+ if(i960->bursting)
+ t1 += 4;
+ }
+ break;
+ }
+
+ case 0xa2:{// stt
+ int i;
+ i960->icount -= 4;
+ t1 = get_ea(i960, opcode);
+ t2 = (opcode>>19)&0x1c;
+ i960->bursting = 1;
+ for(i=0; i<3; i++) {
+ i960_write_dword_unaligned(i960, t1, i960->r[t2+i]);
+ if(i960->bursting)
+ t1 += 4;
+ }
+ break;
+ }
+
+ case 0xb0:{// ldq
+ int i;
+ i960->icount -= 7;
+ t1 = get_ea(i960, opcode);
+ t2 = (opcode>>19)&0x1c;
+ i960->bursting = 1;
+ for(i=0; i<4; i++) {
+ i960->r[t2+i] = i960_read_dword_unaligned(i960, t1);
+ if(i960->bursting)
+ t1 += 4;
+ }
+ break;
+ }
+
+ case 0xb2:{// stq
+ int i;
+ i960->icount -= 5;
+ t1 = get_ea(i960, opcode);
+ t2 = (opcode>>19)&0x1c;
+ i960->bursting = 1;
+ for(i=0; i<4; i++) {
+ i960_write_dword_unaligned(i960, t1, i960->r[t2+i]);
+ if(i960->bursting)
+ t1 += 4;
+ }
+ break;
+ }
+
+ case 0xc0: // ldib
+ i960->icount -= 4;
+ i960->r[(opcode>>19)&0x1f] = (INT8)i960->program->read_byte(get_ea(i960, opcode));
+ break;
+
+ case 0xc2: // stib
+ i960->icount -= 2;
+ i960->program->write_byte(get_ea(i960, opcode), i960->r[(opcode>>19)&0x1f]);
+ break;
+
+ case 0xc8: // ldis
+ i960->icount -= 4;
+ i960->r[(opcode>>19)&0x1f] = (INT16)i960_read_word_unaligned(i960, get_ea(i960, opcode));
+ break;
+
+ case 0xca: // stis
+ i960->icount -= 2;
+ i960_write_word_unaligned(i960, get_ea(i960, opcode), i960->r[(opcode>>19)&0x1f]);
+ break;
+
+ default:
+ fatalerror("I960: %x: Unhandled %02x", i960->PIP, opcode >> 24);
+ }
+
+}
+
+static CPU_EXECUTE( i960 )
+{
+ i960_state_t *i960 = get_safe_token(device);
+ UINT32 opcode;
+
+ check_irqs(i960);
+ while(i960->icount > 0) {
+ i960->PIP = i960->IP;
+ debugger_instruction_hook(device, i960->IP);
+
+ i960->bursting = 0;
+
+ opcode = i960->direct->read_decrypted_dword(i960->IP);
+ i960->IP += 4;
+
+ execute_op(i960, opcode);
+ }
+}
+
+static void set_irq_line(i960_state_t *i960, int irqline, int state)
+{
+ int int_tab = i960->program->read_dword(i960->PRCB+20); // interrupt table
+ int cpu_pri = (i960->PC>>16)&0x1f;
+ int vector =0;
+ int priority;
+ UINT32 pend, word, wordofs;
+
+ // We support the 4 external IRQ lines in "normal" mode only.
+ // The i960's interrupt support is a bit more complete than that,
+ // but Namco and Sega both went for the cheapest solution.
+
+ switch (irqline)
+ {
+ case I960_IRQ0:
+ vector = i960->ICR & 0xff;
+ break;
+
+ case I960_IRQ1:
+ vector = (i960->ICR>>8)&0xff;
+ break;
+
+ case I960_IRQ2:
+ vector = (i960->ICR>>16)&0xff;
+ break;
+
+ case I960_IRQ3:
+ vector = (i960->ICR>>24)&0xff;
+ break;
+ }
+
+ if(!vector)
+ {
+ logerror("i960: interrupt line %d in IAC mode, unsupported!\n", irqline);
+ return;
+ }
+
+
+ priority = vector / 8;
+
+ if(state) {
+ // check if we can take this "right now"
+ if (((cpu_pri < priority) || (priority == 31)) && (i960->immediate_irq == 0))
+ {
+ i960->immediate_irq = 1;
+ i960->immediate_vector = vector;
+ i960->immediate_pri = priority;
+ }
+ else
+ {
+ // store the interrupt in the "pending" table
+ pend = i960->program->read_dword(int_tab);
+ pend |= (1 << priority);
+ i960->program->write_dword(int_tab, pend);
+
+ // now bitfield-ize the vector
+ word = ((vector / 32) * 4) + 4;
+ wordofs = vector % 32;
+ pend = i960->program->read_dword(int_tab + word);
+ pend |= (1 << wordofs);
+ i960->program->write_dword(int_tab + word, pend);
+ }
+
+ // and ack it to the core now that it's queued
+ (*i960->irq_cb)(i960->device, irqline);
+ }
+}
+
+static CPU_SET_INFO( i960 )
+{
+ i960_state_t *i960 = get_safe_token(device);
+
+ if(state >= CPUINFO_INT_REGISTER+I960_R0 && state <= CPUINFO_INT_REGISTER + I960_G15) {
+ i960->r[state - (CPUINFO_INT_REGISTER + I960_R0)] = info->i;
+ return;
+ }
+
+ switch(state) {
+ // Interfacing
+ case CPUINFO_INT_REGISTER + I960_IP: i960->IP = info->i; break;
+ case CPUINFO_INT_INPUT_STATE + I960_IRQ0: set_irq_line(i960, I960_IRQ0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + I960_IRQ1: set_irq_line(i960, I960_IRQ1, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + I960_IRQ2: set_irq_line(i960, I960_IRQ2, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + I960_IRQ3: set_irq_line(i960, I960_IRQ3, info->i); break;
+
+ default:
+ fatalerror("i960_set_info %x", state);
+ }
+}
+
+static CPU_INIT( i960 )
+{
+ i960_state_t *i960 = get_safe_token(device);
+
+ i960->irq_cb = irqcallback;
+ i960->device = device;
+ i960->program = device->space(AS_PROGRAM);
+ i960->direct = &i960->program->direct();
+
+ device->save_item(NAME(i960->PIP));
+ device->save_item(NAME(i960->SAT));
+ device->save_item(NAME(i960->PRCB));
+ device->save_item(NAME(i960->PC));
+ device->save_item(NAME(i960->AC));
+ device->save_item(NAME(i960->ICR));
+ device->save_item(NAME(i960->r));
+ device->save_item(NAME(i960->fp));
+ device->save_item(NAME(i960->rcache));
+ device->save_item(NAME(i960->rcache_frame_addr));
+}
+
+static CPU_RESET( i960 )
+{
+ i960_state_t *i960 = get_safe_token(device);
+
+ i960->SAT = i960->program->read_dword(0);
+ i960->PRCB = i960->program->read_dword(4);
+ i960->IP = i960->program->read_dword(12);
+ i960->PC = 0x001f2002;
+ i960->AC = 0;
+ i960->ICR = 0xff000000;
+ i960->bursting = 0;
+ i960->immediate_irq = 0;
+
+ memset(i960->r, 0, sizeof(i960->r));
+ memset(i960->rcache, 0, sizeof(i960->rcache));
+
+ i960->r[I960_FP] = i960->program->read_dword(i960->PRCB+24);
+ i960->r[I960_SP] = i960->r[I960_FP] + 64;
+ i960->rcache_pos = 0;
+}
+
+CPU_GET_INFO( i960 )
+{
+ i960_state_t *i960 = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ if(state >= CPUINFO_INT_REGISTER+I960_R0 && state <= CPUINFO_INT_REGISTER + I960_G15) {
+ info->i = i960->r[state - (CPUINFO_INT_REGISTER + I960_R0)];
+ return;
+ }
+
+ switch(state) {
+ // Interface functions and variables
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(i960); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(i960); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(i960); break;
+ case CPUINFO_FCT_EXIT: info->exit = 0; break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(i960); break;
+ case CPUINFO_FCT_BURN: info->burn = 0; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(i960); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &i960->icount; break;
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(i960_state_t); break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 8; break;
+
+ // Bus sizes
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case CPUINFO_INT_LOGADDR_WIDTH_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case CPUINFO_INT_LOGADDR_WIDTH_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+ case CPUINFO_INT_LOGADDR_WIDTH_IO: info->i = 0; break;
+
+ // Internal maps
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map32 = NULL;break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map32 = NULL;break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_IO: info->internal_map32 = NULL;break;
+
+ // CPU misc parameters
+ case DEVINFO_STR_NAME: strcpy(info->s, "i960KB"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case CPUINFO_STR_FLAGS: strcpy(info->s, i960_get_strflags(i960)); break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 4; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = -1; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+
+ // CPU main state
+ case CPUINFO_INT_PC: info->i = i960->IP; break;
+ case CPUINFO_INT_SP: info->i = i960->r[I960_SP]; break;
+ case CPUINFO_INT_PREVIOUSPC: info->i = i960->PIP; break;
+
+ case CPUINFO_INT_REGISTER + I960_SAT: info->i = i960->SAT; break;
+ case CPUINFO_INT_REGISTER + I960_PRCB: info->i = i960->PRCB; break;
+ case CPUINFO_INT_REGISTER + I960_PC: info->i = i960->PC; break;
+ case CPUINFO_INT_REGISTER + I960_AC: info->i = i960->AC; break;
+ case CPUINFO_INT_REGISTER + I960_IP: info->i = i960->IP; break;
+ case CPUINFO_INT_REGISTER + I960_PIP: info->i = i960->PIP; break;
+
+ // CPU debug stuff
+ case CPUINFO_STR_REGISTER + I960_SAT: sprintf(info->s, "sat :%08x", i960->SAT); break;
+ case CPUINFO_STR_REGISTER + I960_PRCB: sprintf(info->s, "prcb :%08x", i960->PRCB); break;
+ case CPUINFO_STR_REGISTER + I960_PC: sprintf(info->s, "pc :%08x", i960->PC); break;
+ case CPUINFO_STR_REGISTER + I960_AC: sprintf(info->s, "ac :%08x", i960->AC); break;
+ case CPUINFO_STR_REGISTER + I960_IP: sprintf(info->s, "ip :%08x", i960->IP); break;
+ case CPUINFO_STR_REGISTER + I960_PIP: sprintf(info->s, "pip :%08x", i960->PIP); break;
+
+ case CPUINFO_STR_REGISTER + I960_R0: sprintf(info->s, "pfp :%08x", i960->r[ 0]); break;
+ case CPUINFO_STR_REGISTER + I960_R1: sprintf(info->s, "sp :%08x", i960->r[ 1]); break;
+ case CPUINFO_STR_REGISTER + I960_R2: sprintf(info->s, "rip :%08x", i960->r[ 2]); break;
+ case CPUINFO_STR_REGISTER + I960_R3: sprintf(info->s, "r3 :%08x", i960->r[ 3]); break;
+ case CPUINFO_STR_REGISTER + I960_R4: sprintf(info->s, "r4 :%08x", i960->r[ 4]); break;
+ case CPUINFO_STR_REGISTER + I960_R5: sprintf(info->s, "r5 :%08x", i960->r[ 5]); break;
+ case CPUINFO_STR_REGISTER + I960_R6: sprintf(info->s, "r6 :%08x", i960->r[ 6]); break;
+ case CPUINFO_STR_REGISTER + I960_R7: sprintf(info->s, "r7 :%08x", i960->r[ 7]); break;
+ case CPUINFO_STR_REGISTER + I960_R8: sprintf(info->s, "r8 :%08x", i960->r[ 8]); break;
+ case CPUINFO_STR_REGISTER + I960_R9: sprintf(info->s, "r9 :%08x", i960->r[ 9]); break;
+ case CPUINFO_STR_REGISTER + I960_R10: sprintf(info->s, "r10 :%08x", i960->r[10]); break;
+ case CPUINFO_STR_REGISTER + I960_R11: sprintf(info->s, "r11 :%08x", i960->r[11]); break;
+ case CPUINFO_STR_REGISTER + I960_R12: sprintf(info->s, "r12 :%08x", i960->r[12]); break;
+ case CPUINFO_STR_REGISTER + I960_R13: sprintf(info->s, "r13 :%08x", i960->r[13]); break;
+ case CPUINFO_STR_REGISTER + I960_R14: sprintf(info->s, "r14 :%08x", i960->r[14]); break;
+ case CPUINFO_STR_REGISTER + I960_R15: sprintf(info->s, "r15 :%08x", i960->r[15]); break;
+
+ case CPUINFO_STR_REGISTER + I960_G0: sprintf(info->s, "g0 :%08x", i960->r[16]); break;
+ case CPUINFO_STR_REGISTER + I960_G1: sprintf(info->s, "g1 :%08x", i960->r[17]); break;
+ case CPUINFO_STR_REGISTER + I960_G2: sprintf(info->s, "g2 :%08x", i960->r[18]); break;
+ case CPUINFO_STR_REGISTER + I960_G3: sprintf(info->s, "g3 :%08x", i960->r[19]); break;
+ case CPUINFO_STR_REGISTER + I960_G4: sprintf(info->s, "g4 :%08x", i960->r[20]); break;
+ case CPUINFO_STR_REGISTER + I960_G5: sprintf(info->s, "g5 :%08x", i960->r[21]); break;
+ case CPUINFO_STR_REGISTER + I960_G6: sprintf(info->s, "g6 :%08x", i960->r[22]); break;
+ case CPUINFO_STR_REGISTER + I960_G7: sprintf(info->s, "g7 :%08x", i960->r[23]); break;
+ case CPUINFO_STR_REGISTER + I960_G8: sprintf(info->s, "g8 :%08x", i960->r[24]); break;
+ case CPUINFO_STR_REGISTER + I960_G9: sprintf(info->s, "g9 :%08x", i960->r[25]); break;
+ case CPUINFO_STR_REGISTER + I960_G10: sprintf(info->s, "g10 :%08x", i960->r[26]); break;
+ case CPUINFO_STR_REGISTER + I960_G11: sprintf(info->s, "g11 :%08x", i960->r[27]); break;
+ case CPUINFO_STR_REGISTER + I960_G12: sprintf(info->s, "g12 :%08x", i960->r[28]); break;
+ case CPUINFO_STR_REGISTER + I960_G13: sprintf(info->s, "g13 :%08x", i960->r[29]); break;
+ case CPUINFO_STR_REGISTER + I960_G14: sprintf(info->s, "g14 :%08x", i960->r[30]); break;
+ case CPUINFO_STR_REGISTER + I960_G15: sprintf(info->s, "fp :%08x", i960->r[31]); break;
+
+// default:
+// fatalerror("i960_get_info %x ", state);
+ }
+}
+
+// call from any read/write handler for a memory area that can't be bursted
+// on the real hardware (e.g. Model 2's interrupt control registers)
+void i960_noburst(device_t *device)
+{
+ i960_state_t *i960 = get_safe_token(device);
+ i960->bursting = 0;
+}
+
+void i960_stall(device_t *device)
+{
+ i960_state_t *i960 = get_safe_token(device);
+ i960->IP = i960->PIP;
+}
+
+DEFINE_LEGACY_CPU_DEVICE(I960, i960);
diff --git a/trunk/src/emu/cpu/i960/i960.h b/trunk/src/emu/cpu/i960/i960.h
new file mode 100644
index 00000000000..3b06f5bf437
--- /dev/null
+++ b/trunk/src/emu/cpu/i960/i960.h
@@ -0,0 +1,68 @@
+#pragma once
+
+#ifndef __I960_H__
+#define __I960_H__
+
+
+enum
+{
+ I960_PFP = 0,
+ I960_SP = 1,
+ I960_RIP = 2,
+ I960_FP = 31,
+
+ I960_R0 = 0,
+ I960_R1 = 1,
+ I960_R2 = 2,
+ I960_R3 = 3,
+ I960_R4 = 4,
+ I960_R5 = 5,
+ I960_R6 = 6,
+ I960_R7 = 7,
+ I960_R8 = 8,
+ I960_R9 = 9,
+ I960_R10 = 10,
+ I960_R11 = 11,
+ I960_R12 = 12,
+ I960_R13 = 13,
+ I960_R14 = 14,
+ I960_R15 = 15,
+ I960_G0 = 16,
+ I960_G1 = 17,
+ I960_G2 = 18,
+ I960_G3 = 19,
+ I960_G4 = 20,
+ I960_G5 = 21,
+ I960_G6 = 22,
+ I960_G7 = 23,
+ I960_G8 = 24,
+ I960_G9 = 25,
+ I960_G10 = 26,
+ I960_G11 = 27,
+ I960_G12 = 28,
+ I960_G13 = 29,
+ I960_G14 = 30,
+ I960_G15 = 31,
+
+ I960_SAT = 32,
+ I960_PRCB = 33,
+ I960_PC = 34,
+ I960_AC = 35,
+ I960_IP = 36,
+ I960_PIP = 37
+};
+
+enum
+{
+ I960_IRQ0 = 0,
+ I960_IRQ1 = 1,
+ I960_IRQ2 = 2,
+ I960_IRQ3 = 3
+};
+
+DECLARE_LEGACY_CPU_DEVICE(I960, i960);
+
+void i960_noburst(device_t *device);
+void i960_stall(device_t *device);
+
+#endif /* __I960_H__ */
diff --git a/trunk/src/emu/cpu/i960/i960dis.c b/trunk/src/emu/cpu/i960/i960dis.c
new file mode 100644
index 00000000000..b27b0fdc6ff
--- /dev/null
+++ b/trunk/src/emu/cpu/i960/i960dis.c
@@ -0,0 +1,305 @@
+/*
+ Intel i960 disassembler
+
+ By Farfetch'd and R. Belmont
+*/
+
+#include "emu.h"
+#include "i960.h"
+#include "i960dis.h"
+
+typedef struct
+{
+ const char *mnem;
+ unsigned short type;
+} mnemonic_t;
+
+
+static const mnemonic_t mnemonic[256] = {
+ { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, // 00
+ { "b", 8 }, { "call", 8 }, { "ret", 9 }, { "bal", 8 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 },
+
+ { "bno", 8 }, { "bg", 8 }, { "be", 8 }, { "bge", 8 }, { "bl", 8 }, { "bne", 8 }, { "ble", 8 }, { "bo", 8 }, // 10
+ { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 },
+
+ { "testno", 10 }, { "testg", 10 }, { "teste", 10 }, { "testge", 10 }, { "testl", 10 }, { "testne", 10 }, { "testle", 10 }, { "testo", 10 }, // 20
+ { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 },
+
+ { "bbc", 6 }, { "cmpobg", 7 }, { "cmpobe", 7 }, { "cmpobge", 7 }, { "cmpobl", 7 }, { "cmpobne", 7 }, { "cmpoble", 7 }, { "bbs", 6 }, // 30
+ { "cmpibno", 7 }, { "cmpibg", 7 }, { "cmpibe", 7 }, { "cmpibge", 7 }, { "cmpibl", 7 }, { "cmpibne", 7 }, { "cmpible", 7 }, { "cmpibo", 7 },
+
+ { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, // 40
+ { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 },
+
+ { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, // 50
+ { "58", 3 }, { "59", 3 }, { "5A", 3 }, { "5B", 3 }, { "5C", 2 }, { "5D", 3 }, { "?", 0 }, { "5F", 3 },
+
+ { "synmov", 1 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "64", 3 }, { "65", 3 }, { "calls", 0 }, { "67", 3 }, // 60
+ { "68", 3 }, { "69", 3 }, { "?", 0 }, { "?", 0 }, { "6C", 3 }, { "6D", 3 }, { "6E", 3 }, { "?", 0 },
+
+ { "70", 3 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "74", 3 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, // 70
+ { "78", 3 }, { "79", 3 }, { "7A", 3 }, { "7B", 3 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 },
+
+ { "ldob", 1 }, { "?", 0 }, { "stob", 1 }, { "?", 0 }, { "bx", 1 }, { "balx", 1 }, { "callx", 1 }, { "?", 0 }, // 80
+ { "ldos", 1 }, { "?", 0 }, { "stos", 1 }, { "?", 0 }, { "lda", 1 }, { "?", 0 }, { "?", 0 }, { "?", 0 },
+
+ { "ld", 1 }, { "?", 0 }, { "st", 1 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, // 90
+ { "ldl", 1 }, { "?", 0 }, { "stl", 1 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 },
+
+ { "ldt", 1 }, { "?", 0 }, { "stt", 1 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, // a0
+ { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 },
+
+ { "ldq", 1 }, { "?", 0 }, { "stq", 1 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, // b0
+ { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 },
+
+ { "ldib", 1 }, { "?", 0 }, { "stib", 1 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, // c0
+ { "ldis", 1 }, { "?", 0 }, { "stis", 1 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 },
+
+ { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, // d0
+ { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 },
+
+ { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, // e0
+ { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 },
+
+ { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, // f0
+ { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }
+};
+
+static const mnemonic_t mnem_reg[100] =
+{
+ { "notbit", 0x580 }, { "and", 0x581 }, { "andnot", 0x582 }, { "setbit", 0x583 }, { "notand",0x584 },
+ { "xor", 0x586 }, { "or", 0x587 }, { "nor", 0x588 }, { "xnor",0x589 }, { "not",0x58a },
+ { "clrbit", 0x58c },
+ { "addo", 0x590 }, { "addi",0x591 }, { "subo",0x592 }, { "subi",0x593 }, { "cmpob",0x594 }, { "shro",0x598 }, { "shrdi",0x59a }, { "shri",0x59b }, { "shlo",0x59c }, { "rotate",0x59d }, { "shli",0x59e },
+ { "cmpo",0x5a0 }, { "cmpi",0x5a1 }, { "concmpo",0x5a2 }, { "concmpi",0x5a3 }, { "cmpinco",0x5a4 }, { "cmpinci",0x5a5 }, { "cmpdeco",0x5a6 }, { "cmpdeci",0x5a7 }, { "scanbyte",0x5ac }, { "bswap",0x5ad }, { "chkbit",0x5ae },
+ { "addc",0x5b0 }, { "subc",0x5b2 },
+ { "mov", 0x5cc },
+ { "movl",0x5dc },
+ { "movq",0x5fc },
+ { "scanbit", 0x641 }, { "daddc", 0x642 }, { "dsubc", 0x643 }, { "dmovt", 0x644 }, { "modac",0x645 },
+ { "modify",0x650 }, { "extract",0x651 }, { "modtc",0x654 }, { "modpc",0x655 },
+ { "emul",0x670 }, { "ediv",0x671 },
+ { "atanr",0x680 }, { "logepr", 0x681 }, { "logr", 0x682 }, { "remr", 0x683 }, { "cmpor", 0x684 }, { "cmpr", 0x685 }, { "sqrtr", 0x688 },
+ { "expr", 0x689 }, { "logbnr", 0x68a }, { "roundr", 0x68b }, { "sinr", 0x68c }, { "cosr", 0x68d }, { "tanr", 0x68e }, { "classr", 0x68f },
+ { "atanrl",0x690 }, { "logeprl", 0x691 }, { "logrl", 0x692 }, { "remrl", 0x693 }, { "cmporl", 0x694 }, { "cmprl", 0x695 }, { "sqrtrl", 0x698 },
+ { "exprl", 0x699 }, { "logbnrl", 0x69a }, { "roundrl", 0x69b }, { "sinrl", 0x69c }, { "cosrl", 0x69d }, { "tanrl", 0x69e }, { "classrl", 0x69f },
+ { "cvtri", 0x6c0 }, { "cvtril", 0x6c1 }, { "cvtzri", 0x6c2 }, { "cvtzril", 0x6c3 }, { "movr", 0x6c9 },
+ { "movrl", 0x6d9 },
+ { "movre", 0x6e1 }, { "cpysre", 0x6e2 }, { "cpyrsre", 0x6e3 },
+ { "mulo", 0x701 }, { "remo",0x708 }, { "divo",0x70b },
+ { "muli",0x741 }, { "remi",0x748 }, { "modi",0x749 }, { "divi",0x74b },
+ { "ending_code",0 }
+};
+
+static const char *const constnames[32] =
+{
+ "0x0", "0x1", "0x2", "0x3", "0x4", "0x5", "0x6", "0x7", "0x8", "0x9", "0xa", "0xb", "0xc", "0xd", "0xe", "0xf",
+ "0x10", "0x11", "0x12", "0x13", "0x14", "0x15", "0x16", "0x17", "0x18", "0x19", "0x1a", "0x1b", "0x1c", "0x1d", "0x1e", "0x1f"
+};
+
+static const char *const regnames[32] =
+{
+ "pfp","sp","rip","r3", "r4","r5","r6","r7", "r8","r9","r10","r11", "r12","r13","r14","r15",
+ "g0","g1","g2","g3", "g4","g5","g6","g7", "g8","g9","g10","g11", "g12","g13","g14","fp",
+};
+
+#define REG_DST regnames[dst]
+#define REG_ABASE regnames[abase]
+#define REG_REG2 regnames[reg2]
+#define REG_COBR_SRC1 ((iCode & 0x2000) ? constnames[COBRSRC1] : regnames[COBRSRC1])
+#define REG_COBR_SRC2 regnames[COBRSRC2]
+#define NEM mnemonic[op].mnem
+
+// REG format
+#define SRC1 (iCode & 0x1f)
+#define S1 ((iCode >> 5) & 0x1)
+#define S2 ((iCode >> 6) & 0x1)
+#define OP2 ((iCode >> 7) & 0xf)
+#define M1 ((iCode >> 11) & 0x1)
+#define M2 ((iCode >> 12) & 0x1)
+#define M3 ((iCode >> 13) & 0x1)
+#define SRC2 ((iCode >> 14) & 0x1f)
+#define DST ((iCode >> 19) & 0x1f)
+#define OP ((iCode >> 24) & 0xff)
+
+// COBR format
+#define COBRSRC1 ((iCode >> 19) & 0x1f)
+#define COBRSRC2 ((iCode >> 14) & 0x1f)
+
+static char *dis_decode_reg(unsigned long iCode, char* tmpStr,unsigned char cnt)
+{
+ char src1[10];
+ char src2[10];
+ char dst[10];
+
+ if (S1) src1[0] = 0;
+ else
+ {
+ if(M1) sprintf(src1,"0x%lx",SRC1);
+ else sprintf(src1,"%s",regnames[SRC1]);
+ }
+ if (S2) sprintf(src2,"reserved");
+ else
+ {
+ if(M2) sprintf(src2,"0x%lx,",SRC2);
+ else sprintf(src2,"%s,",regnames[SRC2]);
+ }
+ if(M3) dst[0] = 0;
+ else sprintf(dst,"%s,",regnames[DST]);
+ if (cnt == 1)
+ sprintf(tmpStr,"%s%s",dst,src1);
+ else
+ sprintf(tmpStr,"%s%s%s",dst,src2,src1);
+ return tmpStr;
+}
+
+#define READ32(dis,offs) ((dis)->oprom[(offs) + 0] | ((dis)->oprom[(offs) + 1] << 8) | ((dis)->oprom[(offs) + 2] << 16) | ((dis)->oprom[(offs) + 3] << 24))
+
+static char *i960_disassemble(disassemble_t *diss)
+{
+ unsigned char op,op2;
+ unsigned char /*mode,*/ modeh, model;
+ unsigned char dst,abase,reg2;
+ unsigned short opc;
+ unsigned long iCode;
+ char tmpStr[256];
+ long i;
+
+ iCode = READ32(diss,0);
+ op = (unsigned char) (iCode >> 24);
+ op2 = (unsigned char) (iCode >> 7)&0xf;
+
+ model = (unsigned char) (iCode >> 10) &0x3;
+ modeh = (unsigned char) (iCode >> 12) &0x3;
+ //mode = (unsigned char) (iCode >> 10) &0x7;
+ dst = (unsigned char) (iCode >> 19) &0x1f;
+ abase = (unsigned char) (iCode>>14)&0x1f;
+ reg2 = (unsigned char) (iCode)&0x1f;
+
+ sprintf(diss->buffer,"???");
+ diss->IPinc = 4;
+ diss->disflags = 0;
+
+ if (op == 0x09 || op == 0x0b || op == 0x66 || op == 0x85 || op == 0x86)
+ diss->disflags = DASMFLAG_STEP_OVER;
+ else if (op == 0x0a)
+ diss->disflags = DASMFLAG_STEP_OUT;
+
+ switch(mnemonic[op].type)
+ {
+ case 0: // not yet implemented
+ sprintf(diss->buffer,"%s %02x:%01x %08lx %1x %1x",mnemonic[op].mnem,op,op2,iCode, modeh, model);
+ break;
+ case 1: // memory access
+ switch(modeh)
+ {
+ case 0:
+ sprintf(diss->buffer, "%-8s%s,0x%lx",NEM,REG_DST, iCode&0xfff);
+ break;
+ case 1:
+ switch (model)
+ {
+ case 0:
+ sprintf(diss->buffer, "%-8s%s,(%s)",NEM,REG_DST, REG_ABASE);
+ break;
+ case 3:
+ sprintf(diss->buffer, "%-8s%s,(%s)[%s*%ld]",NEM,REG_DST, REG_ABASE,REG_REG2,(iCode>>7)&0x7);
+ break;
+ default:
+ sprintf(diss->buffer,"%s %02x:%01x %08lx %1x %1x",mnemonic[op].mnem,op,op2,iCode, modeh, model);
+ break;
+ }
+ break;
+ case 2:
+ sprintf(diss->buffer, "%-8s%s,0x%lx(%s)",NEM,REG_DST, iCode&0xfff,REG_ABASE);
+ break;
+ case 3:
+ switch (model)
+ {
+ case 0:
+ sprintf(diss->buffer, "%-8s%s,0x%x",NEM,REG_DST, READ32(diss,4));
+ diss->IPinc = 8;
+ break;
+ case 1:
+ sprintf(diss->buffer, "%-8s%s,0x%x(%s)",NEM,REG_DST, READ32(diss,4),REG_ABASE);
+ diss->IPinc = 8;
+ break;
+ case 2:
+ sprintf(diss->buffer, "%-8s%s,0x%x[%s*%ld]",NEM,REG_DST, READ32(diss,4),REG_REG2,(iCode>>7)&0x7);
+ diss->IPinc = 8;
+ break;
+ case 3:
+ sprintf(diss->buffer, "%-8s%s,0x%x(%s)[%s*%ld]",NEM,REG_DST, READ32(diss,4),REG_ABASE,REG_REG2,(iCode>>7)&0x7);
+ diss->IPinc = 8;
+ break;
+ default:
+ sprintf(diss->buffer,"%s %02x:%01x %08lx %1x %1x",mnemonic[op].mnem,op,op2,iCode, modeh, model);
+ break;
+ }
+ break;
+ default:
+ sprintf(diss->buffer,"%s %02x:%01x %08lx %1x %1x",mnemonic[op].mnem,op,op2,iCode, modeh, model);
+ break;
+ }
+ break;
+ case 2:
+ i = 0;
+ opc = op<<4|op2;
+
+ while(mnem_reg[i].type != 0)
+ {
+ if (mnem_reg[i].type == opc) break;
+ i++;
+ }
+
+ if (mnem_reg[i].type == opc) sprintf(diss->buffer, "%-8s%s", mnem_reg[i].mnem,dis_decode_reg(iCode,tmpStr,1));
+ else sprintf(diss->buffer,"%s %02x:%01x %08lx %1x %1x",mnemonic[op].mnem,op,op2,iCode, modeh, model);
+ break;
+ case 3:
+ i = 0;
+ opc = op<<4|op2;
+
+ while(mnem_reg[i].type != 0)
+ {
+ if (mnem_reg[i].type == opc) break;
+ i++;
+ }
+
+ if (mnem_reg[i].type == opc) sprintf(diss->buffer, "%-8s%s", mnem_reg[i].mnem,dis_decode_reg(iCode,tmpStr,0));
+ else sprintf(diss->buffer,"%s %02x:%01x %08lx %1x %1x",mnemonic[op].mnem,op,op2,iCode, modeh, model);
+ break;
+
+ case 6: // bitpos and branch type
+ sprintf(diss->buffer, "%-8s%ld,%s,0x%lx",NEM, COBRSRC1, REG_COBR_SRC2,((((long)iCode&0x00fffffc)<<19)>>19) + (diss->IP));
+ break;
+ case 7: // compare and branch type
+ sprintf(diss->buffer, "%-8s%s,%s,0x%lx",NEM,REG_COBR_SRC1,REG_COBR_SRC2,((((long)iCode&0x00fffffc)<<19)>>19) + (diss->IP));
+ break;
+ case 8: // target type
+ sprintf(diss->buffer, "%-8s%08lx",NEM,((((long)iCode&0x00fffffc)<<8)>>8) + (diss->IP));
+ break;
+ case 9: // no operands
+ sprintf(diss->buffer, "%s",NEM);
+ break;
+ case 10: // TEST type: register only
+ sprintf(diss->buffer, "%s %s", NEM, REG_DST);
+ break;
+ }
+ return diss->buffer;
+}
+
+
+
+CPU_DISASSEMBLE( i960 )
+{
+ disassemble_t dis;
+
+ dis.IP = pc;
+ dis.buffer = buffer;
+ dis.oprom = oprom;
+
+ i960_disassemble(&dis);
+
+ return dis.IPinc | dis.disflags | DASMFLAG_SUPPORTED;
+}
+
diff --git a/trunk/src/emu/cpu/i960/i960dis.h b/trunk/src/emu/cpu/i960/i960dis.h
new file mode 100644
index 00000000000..2c18dd1c64a
--- /dev/null
+++ b/trunk/src/emu/cpu/i960/i960dis.h
@@ -0,0 +1,14 @@
+#ifndef __I960DIS_H__
+#define __I960DIS_H__
+
+typedef struct _disassemble_t disassemble_t;
+struct _disassemble_t
+{
+ char *buffer; // output buffer
+ unsigned long IP;
+ unsigned long IPinc;
+ const UINT8 *oprom;
+ UINT32 disflags;
+};
+
+#endif /* __I960DIS_H__ */
diff --git a/trunk/src/emu/cpu/jaguar/jagdasm.c b/trunk/src/emu/cpu/jaguar/jagdasm.c
new file mode 100644
index 00000000000..cc0a8f678b0
--- /dev/null
+++ b/trunk/src/emu/cpu/jaguar/jagdasm.c
@@ -0,0 +1,197 @@
+/***************************************************************************
+
+ jagdasm.c
+ Disassembler for the portable Jaguar DSP emulator.
+ Written by Aaron Giles
+
+***************************************************************************/
+
+#include "emu.h"
+#include "jaguar.h"
+
+
+/***************************************************************************
+ MEMORY ACCESSORS
+***************************************************************************/
+
+#define ROPCODE(offs) ((oprom[offs] << 8) | oprom[(offs) + 1])
+
+
+/***************************************************************************
+ STATIC VARIABLES
+***************************************************************************/
+
+static const UINT8 convert_zero[32] =
+{ 32,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 };
+
+static const char *const condition[32] =
+{
+ "",
+ "nz,",
+ "z,",
+ "???,",
+ "nc,",
+ "nc nz,",
+ "nc z,",
+ "???,",
+ "c,",
+ "c nz,",
+ "c z,",
+ "???,",
+ "???,",
+ "???,",
+ "???,",
+ "???,",
+
+ "???,",
+ "???,",
+ "???,",
+ "???,",
+ "nn,",
+ "nn nz,",
+ "nn z,",
+ "???,",
+ "n,",
+ "n nz,",
+ "n z,",
+ "???,",
+ "???,",
+ "???,",
+ "???,",
+ "never,"
+};
+
+
+
+/***************************************************************************
+ CODE CODE
+***************************************************************************/
+
+INLINE char *signed_16bit(INT16 val)
+{
+ static char temp[10];
+ if (val < 0)
+ sprintf(temp, "-$%x", -val);
+ else
+ sprintf(temp, "$%x", val);
+ return temp;
+}
+
+static unsigned dasmjag(int variant, char *buffer, unsigned pc, const UINT8 *oprom)
+{
+ UINT32 flags = 0;
+ int op = ROPCODE(0);
+ int reg1 = (op >> 5) & 31;
+ int reg2 = op & 31;
+ int size = 2;
+
+ pc += 2;
+ switch (op >> 10)
+ {
+ case 0: sprintf(buffer, "add r%d,r%d", reg1, reg2); break;
+ case 1: sprintf(buffer, "addc r%d,r%d", reg1, reg2); break;
+ case 2: sprintf(buffer, "addq $%x,r%d", convert_zero[reg1], reg2); break;
+ case 3: sprintf(buffer, "addqt $%x,r%d", convert_zero[reg1], reg2); break;
+ case 4: sprintf(buffer, "sub r%d,r%d", reg1, reg2); break;
+ case 5: sprintf(buffer, "subc r%d,r%d", reg1, reg2); break;
+ case 6: sprintf(buffer, "subq $%x,r%d", convert_zero[reg1], reg2); break;
+ case 7: sprintf(buffer, "subqt $%x,r%d", convert_zero[reg1], reg2); break;
+ case 8: sprintf(buffer, "neg r%d", reg2); break;
+ case 9: sprintf(buffer, "and r%d,r%d", reg1, reg2); break;
+ case 10: sprintf(buffer, "or r%d,r%d", reg1, reg2); break;
+ case 11: sprintf(buffer, "xor r%d,r%d", reg1, reg2); break;
+ case 12: sprintf(buffer, "not r%d", reg2); break;
+ case 13: sprintf(buffer, "btst $%x,r%d", reg1, reg2); break;
+ case 14: sprintf(buffer, "bset $%x,r%d", reg1, reg2); break;
+ case 15: sprintf(buffer, "bclr $%x,r%d", reg1, reg2); break;
+ case 16: sprintf(buffer, "mult r%d,r%d", reg1, reg2); break;
+ case 17: sprintf(buffer, "imult r%d,r%d", reg1, reg2); break;
+ case 18: sprintf(buffer, "imultn r%d,r%d", reg1, reg2); break;
+ case 19: sprintf(buffer, "resmac r%d", reg2); break;
+ case 20: sprintf(buffer, "imacn r%d,r%d", reg1, reg2); break;
+ case 21: sprintf(buffer, "div r%d,r%d", reg1, reg2); break;
+ case 22: sprintf(buffer, "abs r%d", reg2); break;
+ case 23: sprintf(buffer, "sh r%d,r%d", reg1, reg2); break;
+ case 24: sprintf(buffer, "shlq $%x,r%d", 32 - convert_zero[reg1], reg2); break;
+ case 25: sprintf(buffer, "shrq $%x,r%d", convert_zero[reg1], reg2); break;
+ case 26: sprintf(buffer, "sha r%d,r%d", reg1, reg2); break;
+ case 27: sprintf(buffer, "sharq $%x,r%d", convert_zero[reg1], reg2); break;
+ case 28: sprintf(buffer, "ror r%d,r%d", reg1, reg2); break;
+ case 29: sprintf(buffer, "rorq $%x,r%d", convert_zero[reg1], reg2); break;
+ case 30: sprintf(buffer, "cmp r%d,r%d", reg1, reg2); break;
+ case 31: sprintf(buffer, "cmpq %s,r%d", signed_16bit((INT16)(reg1 << 11) >> 11), reg2);break;
+ case 32: if (variant == JAGUAR_VARIANT_GPU)
+ sprintf(buffer, "sat8 r%d", reg2);
+ else
+ sprintf(buffer, "subqmod $%x,r%d", convert_zero[reg1], reg2);
+ break;
+ case 33: if (variant == JAGUAR_VARIANT_GPU)
+ sprintf(buffer, "sat16 r%d", reg2);
+ else
+ sprintf(buffer, "sat16s r%d", reg2);
+ break;
+ case 34: sprintf(buffer, "move r%d,r%d", reg1, reg2); break;
+ case 35: sprintf(buffer, "moveq %d,r%d", reg1, reg2); break;
+ case 36: sprintf(buffer, "moveta r%d,r%d", reg1, reg2); break;
+ case 37: sprintf(buffer, "movefa r%d,r%d", reg1, reg2); break;
+ case 38: sprintf(buffer, "movei $%x,r%d", ROPCODE(2) | (ROPCODE(4)<<16), reg2); size = 6; break;
+ case 39: sprintf(buffer, "loadb (r%d),r%d", reg1, reg2); break;
+ case 40: sprintf(buffer, "loadw (r%d),r%d", reg1, reg2); break;
+ case 41: sprintf(buffer, "load (r%d),r%d", reg1, reg2); break;
+ case 42: if (variant == JAGUAR_VARIANT_GPU)
+ sprintf(buffer, "loadp (r%d),r%d", reg1, reg2);
+ else
+ sprintf(buffer, "sat32s r%d", reg2);
+ break;
+ case 43: sprintf(buffer, "load (r14+$%x),r%d", convert_zero[reg1]*4, reg2);break;
+ case 44: sprintf(buffer, "load (r15+$%x),r%d", convert_zero[reg1]*4, reg2);break;
+ case 45: sprintf(buffer, "storeb r%d,(r%d)", reg2, reg1); break;
+ case 46: sprintf(buffer, "storew r%d,(r%d)", reg2, reg1); break;
+ case 47: sprintf(buffer, "store r%d,(r%d)", reg2, reg1); break;
+ case 48: if (variant == JAGUAR_VARIANT_GPU)
+ sprintf(buffer, "storep r%d,(r%d)", reg2, reg1);
+ else
+ sprintf(buffer, "mirror r%d", reg2);
+ break;
+ case 49: sprintf(buffer, "store r%d,(r14+$%x)", reg2, convert_zero[reg1]*4);break;
+ case 50: sprintf(buffer, "store r%d,(r15+$%x)", reg2, convert_zero[reg1]*4);break;
+ case 51: sprintf(buffer, "move pc,r%d", reg2); break;
+ case 52: sprintf(buffer, "jump %s(r%d)", condition[reg2], reg1); break;
+ case 53: sprintf(buffer, "jr %s%08X", condition[reg2], pc + ((INT8)(reg1 << 3) >> 2)); break;
+ case 54: sprintf(buffer, "mmult r%d,r%d", reg1, reg2); break;
+ case 55: sprintf(buffer, "mtoi r%d,r%d", reg1, reg2); break;
+ case 56: sprintf(buffer, "normi r%d,r%d", reg1, reg2); break;
+ case 57: sprintf(buffer, "nop"); break;
+ case 58: sprintf(buffer, "load (r14+r%d),r%d", reg1, reg2); break;
+ case 59: sprintf(buffer, "load (r15+r%d),r%d", reg1, reg2); break;
+ case 60: sprintf(buffer, "store r%d,(r14+r%d)", reg2, reg1); break;
+ case 61: sprintf(buffer, "store r%d,(r15+r%d)", reg2, reg1); break;
+ case 62: if (variant == JAGUAR_VARIANT_GPU)
+ sprintf(buffer, "sat24 r%d", reg2);
+ else
+ sprintf(buffer, "illegal");
+ break;
+ case 63: if (variant == JAGUAR_VARIANT_GPU)
+ sprintf(buffer, reg1 ?
+ "unpack r%d" :
+ "pack r%d", reg2);
+ else
+ sprintf(buffer, "addqmod $%x,r%d", convert_zero[reg1], reg2);
+ break;
+ }
+ return size | flags | DASMFLAG_SUPPORTED;
+}
+
+
+CPU_DISASSEMBLE( jaguargpu )
+{
+ return dasmjag(JAGUAR_VARIANT_GPU, buffer, pc, oprom);
+}
+
+CPU_DISASSEMBLE( jaguardsp )
+{
+ return dasmjag(JAGUAR_VARIANT_DSP, buffer, pc, oprom);
+}
+
+
+
diff --git a/trunk/src/emu/cpu/jaguar/jaguar.c b/trunk/src/emu/cpu/jaguar/jaguar.c
new file mode 100644
index 00000000000..0b35c291e62
--- /dev/null
+++ b/trunk/src/emu/cpu/jaguar/jaguar.c
@@ -0,0 +1,1666 @@
+/***************************************************************************
+
+ jaguar.c
+ Core implementation for the portable Jaguar DSP emulator.
+ Written by Aaron Giles
+
+***************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "jaguar.h"
+
+CPU_DISASSEMBLE( jaguargpu );
+CPU_DISASSEMBLE( jaguardsp );
+
+#define LOG_GPU_IO 0
+#define LOG_DSP_IO 0
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define ZFLAG 0x00001
+#define CFLAG 0x00002
+#define NFLAG 0x00004
+#define IFLAG 0x00008
+#define EINT0FLAG 0x00010
+#define EINT1FLAG 0x00020
+#define EINT2FLAG 0x00040
+#define EINT3FLAG 0x00080
+#define EINT4FLAG 0x00100
+#define EINT04FLAGS (EINT0FLAG | EINT1FLAG | EINT2FLAG | EINT3FLAG | EINT4FLAG)
+#define CINT0FLAG 0x00200
+#define CINT1FLAG 0x00400
+#define CINT2FLAG 0x00800
+#define CINT3FLAG 0x01000
+#define CINT4FLAG 0x02000
+#define CINT04FLAGS (CINT0FLAG | CINT1FLAG | CINT2FLAG | CINT3FLAG | CINT4FLAG)
+#define RPAGEFLAG 0x04000
+#define DMAFLAG 0x08000
+#define EINT5FLAG 0x10000 /* DSP only */
+#define CINT5FLAG 0x20000 /* DSP only */
+
+#define CLR_Z(J) ((J)->FLAGS &= ~ZFLAG)
+#define CLR_ZN(J) ((J)->FLAGS &= ~(ZFLAG | NFLAG))
+#define CLR_ZNC(J) ((J)->FLAGS &= ~(CFLAG | ZFLAG | NFLAG))
+#define SET_Z(J,r) ((J)->FLAGS |= ((r) == 0))
+#define SET_C_ADD(J,a,b) ((J)->FLAGS |= ((UINT32)(b) > (UINT32)(~(a))) << 1)
+#define SET_C_SUB(J,a,b) ((J)->FLAGS |= ((UINT32)(b) > (UINT32)(a)) << 1)
+#define SET_N(J,r) ((J)->FLAGS |= (((UINT32)(r) >> 29) & 4))
+#define SET_ZN(J,r) SET_N(J,r); SET_Z(J,r)
+#define SET_ZNC_ADD(J,a,b,r) SET_N(J,r); SET_Z(J,r); SET_C_ADD(J,a,b)
+#define SET_ZNC_SUB(J,a,b,r) SET_N(J,r); SET_Z(J,r); SET_C_SUB(J,a,b)
+
+
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+#define PC ctrl[G_PC]
+#define FLAGS ctrl[G_FLAGS]
+
+#define CONDITION(x) condition_table[(x) + ((jaguar->FLAGS & 7) << 5)]
+
+#define READBYTE(J,a) (J)->program->read_byte(a)
+#define READWORD(J,a) (J)->program->read_word(a)
+#define READLONG(J,a) (J)->program->read_dword(a)
+
+#define WRITEBYTE(J,a,v) (J)->program->write_byte(a, v)
+#define WRITEWORD(J,a,v) (J)->program->write_word(a, v)
+#define WRITELONG(J,a,v) (J)->program->write_dword(a, v)
+
+
+
+/***************************************************************************
+ STRUCTURES & TYPEDEFS
+***************************************************************************/
+
+/* Jaguar Registers */
+typedef struct _jaguar_state jaguar_state;
+struct _jaguar_state
+{
+ /* core registers */
+ UINT32 r[32];
+ UINT32 a[32];
+ UINT32 * b0;
+ UINT32 * b1;
+
+ /* control registers */
+ UINT32 ctrl[G_CTRLMAX];
+ UINT32 ppc;
+ UINT64 accum;
+
+ /* internal stuff */
+ int isdsp;
+ int icount;
+ int bankswitch_icount;
+ void (*const *table)(jaguar_state *jaguar, UINT16 op);
+ device_irq_callback irq_callback;
+ jaguar_int_func cpu_interrupt;
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+};
+
+
+
+/***************************************************************************
+ PRIVATE GLOBAL VARIABLES
+***************************************************************************/
+
+static UINT32 table_refcount;
+static UINT16 * mirror_table;
+static UINT8 * condition_table;
+
+static const UINT32 convert_zero[32] =
+{ 32,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 };
+
+
+
+/***************************************************************************
+ FUNCTION TABLES
+***************************************************************************/
+
+static void abs_rn(jaguar_state *jaguar, UINT16 op);
+static void add_rn_rn(jaguar_state *jaguar, UINT16 op);
+static void addc_rn_rn(jaguar_state *jaguar, UINT16 op);
+static void addq_n_rn(jaguar_state *jaguar, UINT16 op);
+static void addqmod_n_rn(jaguar_state *jaguar, UINT16 op); /* DSP only */
+static void addqt_n_rn(jaguar_state *jaguar, UINT16 op);
+static void and_rn_rn(jaguar_state *jaguar, UINT16 op);
+static void bclr_n_rn(jaguar_state *jaguar, UINT16 op);
+static void bset_n_rn(jaguar_state *jaguar, UINT16 op);
+static void btst_n_rn(jaguar_state *jaguar, UINT16 op);
+static void cmp_rn_rn(jaguar_state *jaguar, UINT16 op);
+static void cmpq_n_rn(jaguar_state *jaguar, UINT16 op);
+static void div_rn_rn(jaguar_state *jaguar, UINT16 op);
+static void illegal(jaguar_state *jaguar, UINT16 op);
+static void imacn_rn_rn(jaguar_state *jaguar, UINT16 op);
+static void imult_rn_rn(jaguar_state *jaguar, UINT16 op);
+static void imultn_rn_rn(jaguar_state *jaguar, UINT16 op);
+static void jr_cc_n(jaguar_state *jaguar, UINT16 op);
+static void jump_cc_rn(jaguar_state *jaguar, UINT16 op);
+static void load_rn_rn(jaguar_state *jaguar, UINT16 op);
+static void load_r14n_rn(jaguar_state *jaguar, UINT16 op);
+static void load_r15n_rn(jaguar_state *jaguar, UINT16 op);
+static void load_r14rn_rn(jaguar_state *jaguar, UINT16 op);
+static void load_r15rn_rn(jaguar_state *jaguar, UINT16 op);
+static void loadb_rn_rn(jaguar_state *jaguar, UINT16 op);
+static void loadw_rn_rn(jaguar_state *jaguar, UINT16 op);
+static void loadp_rn_rn(jaguar_state *jaguar, UINT16 op); /* GPU only */
+static void mirror_rn(jaguar_state *jaguar, UINT16 op); /* DSP only */
+static void mmult_rn_rn(jaguar_state *jaguar, UINT16 op);
+static void move_rn_rn(jaguar_state *jaguar, UINT16 op);
+static void move_pc_rn(jaguar_state *jaguar, UINT16 op);
+static void movefa_rn_rn(jaguar_state *jaguar, UINT16 op);
+static void movei_n_rn(jaguar_state *jaguar, UINT16 op);
+static void moveq_n_rn(jaguar_state *jaguar, UINT16 op);
+static void moveta_rn_rn(jaguar_state *jaguar, UINT16 op);
+static void mtoi_rn_rn(jaguar_state *jaguar, UINT16 op);
+static void mult_rn_rn(jaguar_state *jaguar, UINT16 op);
+static void neg_rn(jaguar_state *jaguar, UINT16 op);
+static void nop(jaguar_state *jaguar, UINT16 op);
+static void normi_rn_rn(jaguar_state *jaguar, UINT16 op);
+static void not_rn(jaguar_state *jaguar, UINT16 op);
+static void or_rn_rn(jaguar_state *jaguar, UINT16 op);
+static void pack_rn(jaguar_state *jaguar, UINT16 op); /* GPU only */
+static void resmac_rn(jaguar_state *jaguar, UINT16 op);
+static void ror_rn_rn(jaguar_state *jaguar, UINT16 op);
+static void rorq_n_rn(jaguar_state *jaguar, UINT16 op);
+static void sat8_rn(jaguar_state *jaguar, UINT16 op); /* GPU only */
+static void sat16_rn(jaguar_state *jaguar, UINT16 op); /* GPU only */
+static void sat16s_rn(jaguar_state *jaguar, UINT16 op); /* DSP only */
+static void sat24_rn(jaguar_state *jaguar, UINT16 op); /* GPU only */
+static void sat32s_rn(jaguar_state *jaguar, UINT16 op); /* DSP only */
+static void sh_rn_rn(jaguar_state *jaguar, UINT16 op);
+static void sha_rn_rn(jaguar_state *jaguar, UINT16 op);
+static void sharq_n_rn(jaguar_state *jaguar, UINT16 op);
+static void shlq_n_rn(jaguar_state *jaguar, UINT16 op);
+static void shrq_n_rn(jaguar_state *jaguar, UINT16 op);
+static void store_rn_rn(jaguar_state *jaguar, UINT16 op);
+static void store_rn_r14n(jaguar_state *jaguar, UINT16 op);
+static void store_rn_r15n(jaguar_state *jaguar, UINT16 op);
+static void store_rn_r14rn(jaguar_state *jaguar, UINT16 op);
+static void store_rn_r15rn(jaguar_state *jaguar, UINT16 op);
+static void storeb_rn_rn(jaguar_state *jaguar, UINT16 op);
+static void storew_rn_rn(jaguar_state *jaguar, UINT16 op);
+static void storep_rn_rn(jaguar_state *jaguar, UINT16 op); /* GPU only */
+static void sub_rn_rn(jaguar_state *jaguar, UINT16 op);
+static void subc_rn_rn(jaguar_state *jaguar, UINT16 op);
+static void subq_n_rn(jaguar_state *jaguar, UINT16 op);
+static void subqmod_n_rn(jaguar_state *jaguar, UINT16 op); /* DSP only */
+static void subqt_n_rn(jaguar_state *jaguar, UINT16 op);
+static void xor_rn_rn(jaguar_state *jaguar, UINT16 op);
+
+static void (*const gpu_op_table[64])(jaguar_state *jaguar, UINT16 op) =
+{
+ /* 00-03 */ add_rn_rn, addc_rn_rn, addq_n_rn, addqt_n_rn,
+ /* 04-07 */ sub_rn_rn, subc_rn_rn, subq_n_rn, subqt_n_rn,
+ /* 08-11 */ neg_rn, and_rn_rn, or_rn_rn, xor_rn_rn,
+ /* 12-15 */ not_rn, btst_n_rn, bset_n_rn, bclr_n_rn,
+ /* 16-19 */ mult_rn_rn, imult_rn_rn, imultn_rn_rn, resmac_rn,
+ /* 20-23 */ imacn_rn_rn, div_rn_rn, abs_rn, sh_rn_rn,
+ /* 24-27 */ shlq_n_rn, shrq_n_rn, sha_rn_rn, sharq_n_rn,
+ /* 28-31 */ ror_rn_rn, rorq_n_rn, cmp_rn_rn, cmpq_n_rn,
+ /* 32-35 */ sat8_rn, sat16_rn, move_rn_rn, moveq_n_rn,
+ /* 36-39 */ moveta_rn_rn, movefa_rn_rn, movei_n_rn, loadb_rn_rn,
+ /* 40-43 */ loadw_rn_rn, load_rn_rn, loadp_rn_rn, load_r14n_rn,
+ /* 44-47 */ load_r15n_rn, storeb_rn_rn, storew_rn_rn, store_rn_rn,
+ /* 48-51 */ storep_rn_rn, store_rn_r14n, store_rn_r15n, move_pc_rn,
+ /* 52-55 */ jump_cc_rn, jr_cc_n, mmult_rn_rn, mtoi_rn_rn,
+ /* 56-59 */ normi_rn_rn, nop, load_r14rn_rn, load_r15rn_rn,
+ /* 60-63 */ store_rn_r14rn, store_rn_r15rn, sat24_rn, pack_rn
+};
+
+static void (*const dsp_op_table[64])(jaguar_state *jaguar, UINT16 op) =
+{
+ /* 00-03 */ add_rn_rn, addc_rn_rn, addq_n_rn, addqt_n_rn,
+ /* 04-07 */ sub_rn_rn, subc_rn_rn, subq_n_rn, subqt_n_rn,
+ /* 08-11 */ neg_rn, and_rn_rn, or_rn_rn, xor_rn_rn,
+ /* 12-15 */ not_rn, btst_n_rn, bset_n_rn, bclr_n_rn,
+ /* 16-19 */ mult_rn_rn, imult_rn_rn, imultn_rn_rn, resmac_rn,
+ /* 20-23 */ imacn_rn_rn, div_rn_rn, abs_rn, sh_rn_rn,
+ /* 24-27 */ shlq_n_rn, shrq_n_rn, sha_rn_rn, sharq_n_rn,
+ /* 28-31 */ ror_rn_rn, rorq_n_rn, cmp_rn_rn, cmpq_n_rn,
+ /* 32-35 */ subqmod_n_rn, sat16s_rn, move_rn_rn, moveq_n_rn,
+ /* 36-39 */ moveta_rn_rn, movefa_rn_rn, movei_n_rn, loadb_rn_rn,
+ /* 40-43 */ loadw_rn_rn, load_rn_rn, sat32s_rn, load_r14n_rn,
+ /* 44-47 */ load_r15n_rn, storeb_rn_rn, storew_rn_rn, store_rn_rn,
+ /* 48-51 */ mirror_rn, store_rn_r14n, store_rn_r15n, move_pc_rn,
+ /* 52-55 */ jump_cc_rn, jr_cc_n, mmult_rn_rn, mtoi_rn_rn,
+ /* 56-59 */ normi_rn_rn, nop, load_r14rn_rn, load_r15rn_rn,
+ /* 60-63 */ store_rn_r14rn, store_rn_r15rn, illegal, addqmod_n_rn
+};
+
+
+
+/***************************************************************************
+ MEMORY ACCESSORS
+***************************************************************************/
+
+#define ROPCODE(J,pc) ((J)->direct->read_decrypted_word(pc, WORD_XOR_BE(0)))
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+INLINE jaguar_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == JAGUARGPU ||
+ device->type() == JAGUARDSP);
+ return (jaguar_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+INLINE void update_register_banks(jaguar_state *jaguar)
+{
+ UINT32 temp;
+ int i, bank;
+
+ /* pick the bank */
+ bank = jaguar->FLAGS & RPAGEFLAG;
+ if (jaguar->FLAGS & IFLAG) bank = 0;
+
+ /* do we need to swap? */
+ if ((bank == 0 && jaguar->b0 != jaguar->r) || (bank != 0 && jaguar->b1 != jaguar->r))
+ {
+ /* remember the icount of the instruction after we swap */
+ jaguar->bankswitch_icount = jaguar->icount - 1;
+
+ /* exchange the contents */
+ for (i = 0; i < 32; i++)
+ temp = jaguar->r[i], jaguar->r[i] = jaguar->a[i], jaguar->a[i] = temp;
+
+ /* swap the bank pointers */
+ if (bank == 0)
+ {
+ jaguar->b0 = jaguar->r;
+ jaguar->b1 = jaguar->a;
+ }
+ else
+ {
+ jaguar->b0 = jaguar->a;
+ jaguar->b1 = jaguar->r;
+ }
+ }
+}
+
+
+
+/***************************************************************************
+ IRQ HANDLING
+***************************************************************************/
+
+static void check_irqs(jaguar_state *jaguar)
+{
+ int bits, mask, which = 0;
+
+ /* if the IMASK is set, bail */
+ if (jaguar->FLAGS & IFLAG)
+ return;
+
+ /* get the active interrupt bits */
+ bits = (jaguar->ctrl[G_CTRL] >> 6) & 0x1f;
+ bits |= (jaguar->ctrl[G_CTRL] >> 10) & 0x20;
+
+ /* get the interrupt mask */
+ mask = (jaguar->FLAGS >> 4) & 0x1f;
+ mask |= (jaguar->FLAGS >> 11) & 0x20;
+
+ /* bail if nothing is available */
+ bits &= mask;
+ if (bits == 0)
+ return;
+
+ /* determine which interrupt */
+ if (bits & 0x01) which = 0;
+ if (bits & 0x02) which = 1;
+ if (bits & 0x04) which = 2;
+ if (bits & 0x08) which = 3;
+ if (bits & 0x10) which = 4;
+ if (bits & 0x20) which = 5;
+
+ /* set the interrupt flag */
+ jaguar->FLAGS |= IFLAG;
+ update_register_banks(jaguar);
+
+ /* push the PC-2 on the stack */
+ jaguar->r[31] -= 4;
+ WRITELONG(jaguar, jaguar->r[31], jaguar->PC - 2);
+
+ /* dispatch */
+ jaguar->PC = (jaguar->isdsp) ? 0xf1b000 : 0xf03000;
+ jaguar->PC += which * 0x10;
+}
+
+
+static void set_irq_line(jaguar_state *jaguar, int irqline, int state)
+{
+ int mask = (irqline < 5) ? (0x40 << irqline) : 0x10000;
+ jaguar->ctrl[G_CTRL] &= ~mask;
+ if (state != CLEAR_LINE)
+ {
+ jaguar->ctrl[G_CTRL] |= mask;
+ check_irqs(jaguar);
+ }
+}
+
+
+
+/***************************************************************************
+ INITIALIZATION AND SHUTDOWN
+***************************************************************************/
+
+static void init_tables(void)
+{
+ int i, j;
+
+ /* if we're not the first, skip */
+ if (table_refcount++ != 0)
+ {
+ assert(mirror_table != NULL);
+ assert(condition_table != NULL);
+ return;
+ }
+
+ /* fill in the mirror table */
+ mirror_table = global_alloc_array(UINT16, 65536);
+ for (i = 0; i < 65536; i++)
+ mirror_table[i] = ((i >> 15) & 0x0001) | ((i >> 13) & 0x0002) |
+ ((i >> 11) & 0x0004) | ((i >> 9) & 0x0008) |
+ ((i >> 7) & 0x0010) | ((i >> 5) & 0x0020) |
+ ((i >> 3) & 0x0040) | ((i >> 1) & 0x0080) |
+ ((i << 1) & 0x0100) | ((i << 3) & 0x0200) |
+ ((i << 5) & 0x0400) | ((i << 7) & 0x0800) |
+ ((i << 9) & 0x1000) | ((i << 11) & 0x2000) |
+ ((i << 13) & 0x4000) | ((i << 15) & 0x8000);
+
+ /* fill in the condition table */
+ condition_table = global_alloc_array(UINT8, 32 * 8);
+ for (i = 0; i < 8; i++)
+ for (j = 0; j < 32; j++)
+ {
+ int result = 1;
+ if (j & 1)
+ if (i & ZFLAG) result = 0;
+ if (j & 2)
+ if (!(i & ZFLAG)) result = 0;
+ if (j & 4)
+ if (i & (CFLAG << (j >> 4))) result = 0;
+ if (j & 8)
+ if (!(i & (CFLAG << (j >> 4)))) result = 0;
+ condition_table[i * 32 + j] = result;
+ }
+}
+
+
+static void jaguar_postload(jaguar_state *jaguar)
+{
+ update_register_banks(jaguar);
+ check_irqs(jaguar);
+}
+
+
+static void init_common(int isdsp, legacy_cpu_device *device, device_irq_callback irqcallback)
+{
+ const jaguar_cpu_config *configdata = (const jaguar_cpu_config *)device->static_config();
+ jaguar_state *jaguar = get_safe_token(device);
+
+ init_tables();
+
+ jaguar->table = isdsp ? dsp_op_table : gpu_op_table;
+ jaguar->isdsp = isdsp;
+
+ jaguar->irq_callback = irqcallback;
+ jaguar->device = device;
+ jaguar->program = device->space(AS_PROGRAM);
+ jaguar->direct = &jaguar->program->direct();
+ if (configdata != NULL)
+ jaguar->cpu_interrupt = configdata->cpu_int_callback;
+
+ device->save_item(NAME(jaguar->r));
+ device->save_item(NAME(jaguar->a));
+ device->save_item(NAME(jaguar->ctrl));
+ device->save_item(NAME(jaguar->ppc));
+ device->machine().save().register_postload(save_prepost_delegate(FUNC(jaguar_postload), jaguar));
+}
+
+
+static CPU_INIT( jaguargpu )
+{
+ init_common(FALSE, device, irqcallback);
+}
+
+
+static CPU_INIT( jaguardsp )
+{
+ init_common(TRUE, device, irqcallback);
+}
+
+
+static CPU_RESET( jaguar )
+{
+ jaguar_state *jaguar = get_safe_token(device);
+
+ jaguar->b0 = jaguar->r;
+ jaguar->b1 = jaguar->a;
+}
+
+
+static CPU_EXIT( jaguar )
+{
+ if (--table_refcount != 0)
+ return;
+
+ if (mirror_table != NULL)
+ global_free(mirror_table);
+ mirror_table = NULL;
+
+ if (condition_table != NULL)
+ global_free(condition_table);
+ condition_table = NULL;
+}
+
+
+
+/***************************************************************************
+ CORE EXECUTION LOOP
+***************************************************************************/
+
+static CPU_EXECUTE( jaguargpu )
+{
+ jaguar_state *jaguar = get_safe_token(device);
+
+ /* if we're halted, we shouldn't be here */
+ if (!(jaguar->ctrl[G_CTRL] & 1))
+ {
+ //device_set_input_line(device, INPUT_LINE_HALT, ASSERT_LINE);
+ jaguar->icount = 0;
+ return;
+ }
+
+ /* check for IRQs */
+ check_irqs(jaguar);
+
+ /* count cycles and interrupt cycles */
+ jaguar->bankswitch_icount = -1000;
+
+ /* core execution loop */
+ do
+ {
+ UINT32 op;
+
+ /* debugging */
+ //if (jaguar->PC < 0xf03000 || jaguar->PC > 0xf04000) { fatalerror("GPU: jaguar->PC = %06X (ppc = %06X)", jaguar->PC, jaguar->ppc); }
+ jaguar->ppc = jaguar->PC;
+ debugger_instruction_hook(device, jaguar->PC);
+
+ /* instruction fetch */
+ op = ROPCODE(jaguar, jaguar->PC);
+ jaguar->PC += 2;
+
+ /* parse the instruction */
+ (*gpu_op_table[op >> 10])(jaguar, op);
+ jaguar->icount--;
+
+ } while (jaguar->icount > 0 || jaguar->icount == jaguar->bankswitch_icount);
+}
+
+static CPU_EXECUTE( jaguardsp )
+{
+ jaguar_state *jaguar = get_safe_token(device);
+
+ /* if we're halted, we shouldn't be here */
+ if (!(jaguar->ctrl[G_CTRL] & 1))
+ {
+ //device_set_input_line(device, INPUT_LINE_HALT, ASSERT_LINE);
+ jaguar->icount = 0;
+ return;
+ }
+
+ /* check for IRQs */
+ check_irqs(jaguar);
+
+ /* count cycles and interrupt cycles */
+ jaguar->bankswitch_icount = -1000;
+
+ /* core execution loop */
+ do
+ {
+ UINT32 op;
+
+ /* debugging */
+ //if (jaguar->PC < 0xf1b000 || jaguar->PC > 0xf1d000) { fatalerror(stderr, "DSP: jaguar->PC = %06X", jaguar->PC); }
+ jaguar->ppc = jaguar->PC;
+ debugger_instruction_hook(device, jaguar->PC);
+
+ /* instruction fetch */
+ op = ROPCODE(jaguar, jaguar->PC);
+ jaguar->PC += 2;
+
+ /* parse the instruction */
+ (*dsp_op_table[op >> 10])(jaguar, op);
+ jaguar->icount--;
+
+ } while (jaguar->icount > 0 || jaguar->icount == jaguar->bankswitch_icount);
+}
+
+
+
+/***************************************************************************
+ OPCODES
+***************************************************************************/
+
+void abs_rn(jaguar_state *jaguar, UINT16 op)
+{
+ int dreg = op & 31;
+ UINT32 res = jaguar->r[dreg];
+ CLR_ZNC(jaguar);
+ if (res & 0x80000000)
+ {
+ jaguar->r[dreg] = res = -res;
+ jaguar->FLAGS |= CFLAG;
+ }
+ SET_Z(jaguar, res);
+}
+
+void add_rn_rn(jaguar_state *jaguar, UINT16 op)
+{
+ int dreg = op & 31;
+ UINT32 r1 = jaguar->r[(op >> 5) & 31];
+ UINT32 r2 = jaguar->r[dreg];
+ UINT32 res = r2 + r1;
+ jaguar->r[dreg] = res;
+ CLR_ZNC(jaguar); SET_ZNC_ADD(jaguar, r2, r1, res);
+}
+
+void addc_rn_rn(jaguar_state *jaguar, UINT16 op)
+{
+ int dreg = op & 31;
+ UINT32 r1 = jaguar->r[(op >> 5) & 31];
+ UINT32 r2 = jaguar->r[dreg];
+ UINT32 res = r2 + r1 + ((jaguar->FLAGS >> 1) & 1);
+ jaguar->r[dreg] = res;
+ CLR_ZNC(jaguar); SET_ZNC_ADD(jaguar, r2, r1, res);
+}
+
+void addq_n_rn(jaguar_state *jaguar, UINT16 op)
+{
+ int dreg = op & 31;
+ UINT32 r1 = convert_zero[(op >> 5) & 31];
+ UINT32 r2 = jaguar->r[dreg];
+ UINT32 res = r2 + r1;
+ jaguar->r[dreg] = res;
+ CLR_ZNC(jaguar); SET_ZNC_ADD(jaguar, r2, r1, res);
+}
+
+void addqmod_n_rn(jaguar_state *jaguar, UINT16 op) /* DSP only */
+{
+ int dreg = op & 31;
+ UINT32 r1 = convert_zero[(op >> 5) & 31];
+ UINT32 r2 = jaguar->r[dreg];
+ UINT32 res = r2 + r1;
+ res = (res & ~jaguar->ctrl[D_MOD]) | (r2 & ~jaguar->ctrl[D_MOD]);
+ jaguar->r[dreg] = res;
+ CLR_ZNC(jaguar); SET_ZNC_ADD(jaguar, r2, r1, res);
+}
+
+void addqt_n_rn(jaguar_state *jaguar, UINT16 op)
+{
+ int dreg = op & 31;
+ UINT32 r1 = convert_zero[(op >> 5) & 31];
+ UINT32 r2 = jaguar->r[dreg];
+ UINT32 res = r2 + r1;
+ jaguar->r[dreg] = res;
+}
+
+void and_rn_rn(jaguar_state *jaguar, UINT16 op)
+{
+ int dreg = op & 31;
+ UINT32 r1 = jaguar->r[(op >> 5) & 31];
+ UINT32 r2 = jaguar->r[dreg];
+ UINT32 res = r2 & r1;
+ jaguar->r[dreg] = res;
+ CLR_ZN(jaguar); SET_ZN(jaguar, res);
+}
+
+void bclr_n_rn(jaguar_state *jaguar, UINT16 op)
+{
+ int dreg = op & 31;
+ UINT32 r1 = (op >> 5) & 31;
+ UINT32 r2 = jaguar->r[dreg];
+ UINT32 res = r2 & ~(1 << r1);
+ jaguar->r[dreg] = res;
+ CLR_ZN(jaguar); SET_ZN(jaguar, res);
+}
+
+void bset_n_rn(jaguar_state *jaguar, UINT16 op)
+{
+ int dreg = op & 31;
+ UINT32 r1 = (op >> 5) & 31;
+ UINT32 r2 = jaguar->r[dreg];
+ UINT32 res = r2 | (1 << r1);
+ jaguar->r[dreg] = res;
+ CLR_ZN(jaguar); SET_ZN(jaguar, res);
+}
+
+void btst_n_rn(jaguar_state *jaguar, UINT16 op)
+{
+ UINT32 r1 = (op >> 5) & 31;
+ UINT32 r2 = jaguar->r[op & 31];
+ CLR_Z(jaguar); jaguar->FLAGS |= (~r2 >> r1) & 1;
+}
+
+void cmp_rn_rn(jaguar_state *jaguar, UINT16 op)
+{
+ UINT32 r1 = jaguar->r[(op >> 5) & 31];
+ UINT32 r2 = jaguar->r[op & 31];
+ UINT32 res = r2 - r1;
+ CLR_ZNC(jaguar); SET_ZNC_SUB(jaguar, r2, r1, res);
+}
+
+void cmpq_n_rn(jaguar_state *jaguar, UINT16 op)
+{
+ UINT32 r1 = (INT8)(op >> 2) >> 3;
+ UINT32 r2 = jaguar->r[op & 31];
+ UINT32 res = r2 - r1;
+ CLR_ZNC(jaguar); SET_ZNC_SUB(jaguar, r2, r1, res);
+}
+
+void div_rn_rn(jaguar_state *jaguar, UINT16 op)
+{
+ int dreg = op & 31;
+ UINT32 r1 = jaguar->r[(op >> 5) & 31];
+ UINT32 r2 = jaguar->r[dreg];
+ if (r1)
+ {
+ if (jaguar->ctrl[D_DIVCTRL] & 1)
+ {
+ jaguar->r[dreg] = ((UINT64)r2 << 16) / r1;
+ jaguar->ctrl[D_REMAINDER] = ((UINT64)r2 << 16) % r1;
+ }
+ else
+ {
+ jaguar->r[dreg] = r2 / r1;
+ jaguar->ctrl[D_REMAINDER] = r2 % r1;
+ }
+ }
+ else
+ jaguar->r[dreg] = 0xffffffff;
+}
+
+void illegal(jaguar_state *jaguar, UINT16 op)
+{
+}
+
+void imacn_rn_rn(jaguar_state *jaguar, UINT16 op)
+{
+ UINT32 r1 = jaguar->r[(op >> 5) & 31];
+ UINT32 r2 = jaguar->r[op & 31];
+ jaguar->accum += (INT64)((INT16)r1 * (INT16)r2);
+ logerror("Unexpected IMACN instruction!\n");
+}
+
+void imult_rn_rn(jaguar_state *jaguar, UINT16 op)
+{
+ int dreg = op & 31;
+ UINT32 r1 = jaguar->r[(op >> 5) & 31];
+ UINT32 r2 = jaguar->r[dreg];
+ UINT32 res = (INT16)r1 * (INT16)r2;
+ jaguar->r[dreg] = res;
+ CLR_ZN(jaguar); SET_ZN(jaguar, res);
+}
+
+void imultn_rn_rn(jaguar_state *jaguar, UINT16 op)
+{
+ int dreg = op & 31;
+ UINT32 r1 = jaguar->r[(op >> 5) & 31];
+ UINT32 r2 = jaguar->r[dreg];
+ UINT32 res = (INT16)r1 * (INT16)r2;
+ jaguar->accum = (INT32)res;
+ CLR_ZN(jaguar); SET_ZN(jaguar, res);
+
+ op = ROPCODE(jaguar, jaguar->PC);
+ while ((op >> 10) == 20)
+ {
+ r1 = jaguar->r[(op >> 5) & 31];
+ r2 = jaguar->r[op & 31];
+ jaguar->accum += (INT64)((INT16)r1 * (INT16)r2);
+ jaguar->PC += 2;
+ op = ROPCODE(jaguar, jaguar->PC);
+ }
+ if ((op >> 10) == 19)
+ {
+ jaguar->PC += 2;
+ jaguar->r[op & 31] = (UINT32)jaguar->accum;
+ }
+}
+
+void jr_cc_n(jaguar_state *jaguar, UINT16 op)
+{
+ if (CONDITION(op & 31))
+ {
+ INT32 r1 = (INT8)((op >> 2) & 0xf8) >> 2;
+ UINT32 newpc = jaguar->PC + r1;
+ debugger_instruction_hook(jaguar->device, jaguar->PC);
+ op = ROPCODE(jaguar, jaguar->PC);
+ jaguar->PC = newpc;
+ (*jaguar->table[op >> 10])(jaguar, op);
+
+ jaguar->icount -= 3; /* 3 wait states guaranteed */
+ }
+}
+
+void jump_cc_rn(jaguar_state *jaguar, UINT16 op)
+{
+ if (CONDITION(op & 31))
+ {
+ UINT8 reg = (op >> 5) & 31;
+
+ /* special kludge for risky code in the cojag DSP interrupt handlers */
+ UINT32 newpc = (jaguar->icount == jaguar->bankswitch_icount) ? jaguar->a[reg] : jaguar->r[reg];
+ debugger_instruction_hook(jaguar->device, jaguar->PC);
+ op = ROPCODE(jaguar, jaguar->PC);
+ jaguar->PC = newpc;
+ (*jaguar->table[op >> 10])(jaguar, op);
+
+ jaguar->icount -= 3; /* 3 wait states guaranteed */
+ }
+}
+
+void load_rn_rn(jaguar_state *jaguar, UINT16 op)
+{
+ UINT32 r1 = jaguar->r[(op >> 5) & 31];
+ jaguar->r[op & 31] = READLONG(jaguar, r1);
+}
+
+void load_r14n_rn(jaguar_state *jaguar, UINT16 op)
+{
+ UINT32 r1 = convert_zero[(op >> 5) & 31];
+ jaguar->r[op & 31] = READLONG(jaguar, jaguar->r[14] + 4 * r1);
+}
+
+void load_r15n_rn(jaguar_state *jaguar, UINT16 op)
+{
+ UINT32 r1 = convert_zero[(op >> 5) & 31];
+ jaguar->r[op & 31] = READLONG(jaguar, jaguar->r[15] + 4 * r1);
+}
+
+void load_r14rn_rn(jaguar_state *jaguar, UINT16 op)
+{
+ UINT32 r1 = jaguar->r[(op >> 5) & 31];
+ jaguar->r[op & 31] = READLONG(jaguar, jaguar->r[14] + r1);
+}
+
+void load_r15rn_rn(jaguar_state *jaguar, UINT16 op)
+{
+ UINT32 r1 = jaguar->r[(op >> 5) & 31];
+ jaguar->r[op & 31] = READLONG(jaguar, jaguar->r[15] + r1);
+}
+
+void loadb_rn_rn(jaguar_state *jaguar, UINT16 op)
+{
+ UINT32 r1 = jaguar->r[(op >> 5) & 31];
+ jaguar->r[op & 31] = READBYTE(jaguar, r1);
+}
+
+void loadw_rn_rn(jaguar_state *jaguar, UINT16 op)
+{
+ UINT32 r1 = jaguar->r[(op >> 5) & 31];
+ jaguar->r[op & 31] = READWORD(jaguar, r1);
+}
+
+void loadp_rn_rn(jaguar_state *jaguar, UINT16 op) /* GPU only */
+{
+ UINT32 r1 = jaguar->r[(op >> 5) & 31];
+ jaguar->ctrl[G_HIDATA] = READWORD(jaguar, r1);
+ jaguar->r[op & 31] = READWORD(jaguar, r1+4);
+}
+
+void mirror_rn(jaguar_state *jaguar, UINT16 op) /* DSP only */
+{
+ int dreg = op & 31;
+ UINT32 r1 = jaguar->r[dreg];
+ UINT32 res = (mirror_table[r1 & 0xffff] << 16) | mirror_table[r1 >> 16];
+ jaguar->r[dreg] = res;
+ CLR_ZN(jaguar); SET_ZN(jaguar, res);
+}
+
+void mmult_rn_rn(jaguar_state *jaguar, UINT16 op)
+{
+ int count = jaguar->ctrl[G_MTXC] & 15, i;
+ int sreg = (op >> 5) & 31;
+ int dreg = op & 31;
+ UINT32 addr = jaguar->ctrl[G_MTXA];
+ INT64 accum = 0;
+ UINT32 res;
+
+ if (!(jaguar->ctrl[G_MTXC] & 0x10))
+ {
+ for (i = 0; i < count; i++)
+ {
+ accum += (INT16)(jaguar->b1[sreg + i/2] >> (16 * ((i & 1) ^ 1))) * (INT16)READWORD(jaguar, addr);
+ addr += 2;
+ }
+ }
+ else
+ {
+ for (i = 0; i < count; i++)
+ {
+ accum += (INT16)(jaguar->b1[sreg + i/2] >> (16 * ((i & 1) ^ 1))) * (INT16)READWORD(jaguar, addr);
+ addr += 2 * count;
+ }
+ }
+ jaguar->r[dreg] = res = (UINT32)accum;
+ CLR_ZN(jaguar); SET_ZN(jaguar, res);
+}
+
+void move_rn_rn(jaguar_state *jaguar, UINT16 op)
+{
+ jaguar->r[op & 31] = jaguar->r[(op >> 5) & 31];
+}
+
+void move_pc_rn(jaguar_state *jaguar, UINT16 op)
+{
+ jaguar->r[op & 31] = jaguar->ppc;
+}
+
+void movefa_rn_rn(jaguar_state *jaguar, UINT16 op)
+{
+ jaguar->r[op & 31] = jaguar->a[(op >> 5) & 31];
+}
+
+void movei_n_rn(jaguar_state *jaguar, UINT16 op)
+{
+ UINT32 res = ROPCODE(jaguar, jaguar->PC) | (ROPCODE(jaguar, jaguar->PC + 2) << 16);
+ jaguar->PC += 4;
+ jaguar->r[op & 31] = res;
+}
+
+void moveq_n_rn(jaguar_state *jaguar, UINT16 op)
+{
+ jaguar->r[op & 31] = (op >> 5) & 31;
+}
+
+void moveta_rn_rn(jaguar_state *jaguar, UINT16 op)
+{
+ jaguar->a[op & 31] = jaguar->r[(op >> 5) & 31];
+}
+
+void mtoi_rn_rn(jaguar_state *jaguar, UINT16 op)
+{
+ UINT32 r1 = jaguar->r[(op >> 5) & 31];
+ jaguar->r[op & 31] = (((INT32)r1 >> 8) & 0xff800000) | (r1 & 0x007fffff);
+}
+
+void mult_rn_rn(jaguar_state *jaguar, UINT16 op)
+{
+ int dreg = op & 31;
+ UINT32 r1 = jaguar->r[(op >> 5) & 31];
+ UINT32 r2 = jaguar->r[dreg];
+ UINT32 res = (UINT16)r1 * (UINT16)r2;
+ jaguar->r[dreg] = res;
+ CLR_ZN(jaguar); SET_ZN(jaguar, res);
+}
+
+void neg_rn(jaguar_state *jaguar, UINT16 op)
+{
+ int dreg = op & 31;
+ UINT32 r2 = jaguar->r[dreg];
+ UINT32 res = -r2;
+ jaguar->r[dreg] = res;
+ CLR_ZNC(jaguar); SET_ZNC_SUB(jaguar, 0, r2, res);
+}
+
+void nop(jaguar_state *jaguar, UINT16 op)
+{
+}
+
+void normi_rn_rn(jaguar_state *jaguar, UINT16 op)
+{
+ UINT32 r1 = jaguar->r[(op >> 5) & 31];
+ UINT32 res = 0;
+ if (r1 != 0)
+ {
+ while ((r1 & 0xffc00000) == 0)
+ {
+ r1 <<= 1;
+ res--;
+ }
+ while ((r1 & 0xff800000) != 0)
+ {
+ r1 >>= 1;
+ res++;
+ }
+ }
+ jaguar->r[op & 31] = res;
+ CLR_ZN(jaguar); SET_ZN(jaguar, res);
+}
+
+void not_rn(jaguar_state *jaguar, UINT16 op)
+{
+ int dreg = op & 31;
+ UINT32 res = ~jaguar->r[dreg];
+ jaguar->r[dreg] = res;
+ CLR_ZN(jaguar); SET_ZN(jaguar, res);
+}
+
+void or_rn_rn(jaguar_state *jaguar, UINT16 op)
+{
+ int dreg = op & 31;
+ UINT32 r1 = jaguar->r[(op >> 5) & 31];
+ UINT32 r2 = jaguar->r[dreg];
+ UINT32 res = r1 | r2;
+ jaguar->r[dreg] = res;
+ CLR_ZN(jaguar); SET_ZN(jaguar, res);
+}
+
+void pack_rn(jaguar_state *jaguar, UINT16 op) /* GPU only */
+{
+ int dreg = op & 31;
+ UINT32 r1 = jaguar->r[(op >> 5) & 31];
+ UINT32 r2 = jaguar->r[dreg];
+ UINT32 res;
+ if (r1 == 0) /* PACK */
+ res = ((r2 >> 10) & 0xf000) | ((r2 >> 5) & 0x0f00) | (r2 & 0xff);
+ else /* UNPACK */
+ res = ((r2 & 0xf000) << 10) | ((r2 & 0x0f00) << 5) | (r2 & 0xff);
+ jaguar->r[dreg] = res;
+ CLR_ZN(jaguar); SET_ZN(jaguar, res);
+}
+
+void resmac_rn(jaguar_state *jaguar, UINT16 op)
+{
+ jaguar->r[op & 31] = (UINT32)jaguar->accum;
+}
+
+void ror_rn_rn(jaguar_state *jaguar, UINT16 op)
+{
+ int dreg = op & 31;
+ UINT32 r1 = jaguar->r[(op >> 5) & 31] & 31;
+ UINT32 r2 = jaguar->r[dreg];
+ UINT32 res = (r2 >> r1) | (r2 << (32 - r1));
+ jaguar->r[dreg] = res;
+ CLR_ZNC(jaguar); SET_ZN(jaguar, res); jaguar->FLAGS |= (r2 >> 30) & 2;
+}
+
+void rorq_n_rn(jaguar_state *jaguar, UINT16 op)
+{
+ int dreg = op & 31;
+ UINT32 r1 = convert_zero[(op >> 5) & 31];
+ UINT32 r2 = jaguar->r[dreg];
+ UINT32 res = (r2 >> r1) | (r2 << (32 - r1));
+ jaguar->r[dreg] = res;
+ CLR_ZNC(jaguar); SET_ZN(jaguar, res); jaguar->FLAGS |= (r2 >> 30) & 2;
+}
+
+void sat8_rn(jaguar_state *jaguar, UINT16 op) /* GPU only */
+{
+ int dreg = op & 31;
+ INT32 r2 = jaguar->r[dreg];
+ UINT32 res = (r2 < 0) ? 0 : (r2 > 255) ? 255 : r2;
+ jaguar->r[dreg] = res;
+ CLR_ZN(jaguar); SET_ZN(jaguar, res);
+}
+
+void sat16_rn(jaguar_state *jaguar, UINT16 op) /* GPU only */
+{
+ int dreg = op & 31;
+ INT32 r2 = jaguar->r[dreg];
+ UINT32 res = (r2 < 0) ? 0 : (r2 > 65535) ? 65535 : r2;
+ jaguar->r[dreg] = res;
+ CLR_ZN(jaguar); SET_ZN(jaguar, res);
+}
+
+void sat16s_rn(jaguar_state *jaguar, UINT16 op) /* DSP only */
+{
+ int dreg = op & 31;
+ INT32 r2 = jaguar->r[dreg];
+ UINT32 res = (r2 < -32768) ? -32768 : (r2 > 32767) ? 32767 : r2;
+ jaguar->r[dreg] = res;
+ CLR_ZN(jaguar); SET_ZN(jaguar, res);
+}
+
+void sat24_rn(jaguar_state *jaguar, UINT16 op) /* GPU only */
+{
+ int dreg = op & 31;
+ INT32 r2 = jaguar->r[dreg];
+ UINT32 res = (r2 < 0) ? 0 : (r2 > 16777215) ? 16777215 : r2;
+ jaguar->r[dreg] = res;
+ CLR_ZN(jaguar); SET_ZN(jaguar, res);
+}
+
+void sat32s_rn(jaguar_state *jaguar, UINT16 op) /* DSP only */
+{
+ int dreg = op & 31;
+ INT32 r2 = (UINT32)jaguar->r[dreg];
+ INT32 temp = jaguar->accum >> 32;
+ UINT32 res = (temp < -1) ? (INT32)0x80000000 : (temp > 0) ? (INT32)0x7fffffff : r2;
+ jaguar->r[dreg] = res;
+ CLR_ZN(jaguar); SET_ZN(jaguar, res);
+}
+
+void sh_rn_rn(jaguar_state *jaguar, UINT16 op)
+{
+ int dreg = op & 31;
+ INT32 r1 = (INT32)jaguar->r[(op >> 5) & 31];
+ UINT32 r2 = jaguar->r[dreg];
+ UINT32 res;
+
+ CLR_ZNC(jaguar);
+ if (r1 < 0)
+ {
+ res = (r1 <= -32) ? 0 : (r2 << -r1);
+ jaguar->FLAGS |= (r2 >> 30) & 2;
+ }
+ else
+ {
+ res = (r1 >= 32) ? 0 : (r2 >> r1);
+ jaguar->FLAGS |= (r2 << 1) & 2;
+ }
+ jaguar->r[dreg] = res;
+ SET_ZN(jaguar, res);
+}
+
+void sha_rn_rn(jaguar_state *jaguar, UINT16 op)
+{
+ int dreg = op & 31;
+ INT32 r1 = (INT32)jaguar->r[(op >> 5) & 31];
+ UINT32 r2 = jaguar->r[dreg];
+ UINT32 res;
+
+ CLR_ZNC(jaguar);
+ if (r1 < 0)
+ {
+ res = (r1 <= -32) ? 0 : (r2 << -r1);
+ jaguar->FLAGS |= (r2 >> 30) & 2;
+ }
+ else
+ {
+ res = (r1 >= 32) ? ((INT32)r2 >> 31) : ((INT32)r2 >> r1);
+ jaguar->FLAGS |= (r2 << 1) & 2;
+ }
+ jaguar->r[dreg] = res;
+ SET_ZN(jaguar, res);
+}
+
+void sharq_n_rn(jaguar_state *jaguar, UINT16 op)
+{
+ int dreg = op & 31;
+ INT32 r1 = convert_zero[(op >> 5) & 31];
+ UINT32 r2 = jaguar->r[dreg];
+ UINT32 res = (INT32)r2 >> r1;
+ jaguar->r[dreg] = res;
+ CLR_ZNC(jaguar); SET_ZN(jaguar, res); jaguar->FLAGS |= (r2 << 1) & 2;
+}
+
+void shlq_n_rn(jaguar_state *jaguar, UINT16 op)
+{
+ int dreg = op & 31;
+ INT32 r1 = convert_zero[(op >> 5) & 31];
+ UINT32 r2 = jaguar->r[dreg];
+ UINT32 res = r2 << (32 - r1);
+ jaguar->r[dreg] = res;
+ CLR_ZNC(jaguar); SET_ZN(jaguar, res); jaguar->FLAGS |= (r2 >> 30) & 2;
+}
+
+void shrq_n_rn(jaguar_state *jaguar, UINT16 op)
+{
+ int dreg = op & 31;
+ INT32 r1 = convert_zero[(op >> 5) & 31];
+ UINT32 r2 = jaguar->r[dreg];
+ UINT32 res = r2 >> r1;
+ jaguar->r[dreg] = res;
+ CLR_ZNC(jaguar); SET_ZN(jaguar, res); jaguar->FLAGS |= (r2 << 1) & 2;
+}
+
+void store_rn_rn(jaguar_state *jaguar, UINT16 op)
+{
+ UINT32 r1 = jaguar->r[(op >> 5) & 31];
+ WRITELONG(jaguar, r1, jaguar->r[op & 31]);
+}
+
+void store_rn_r14n(jaguar_state *jaguar, UINT16 op)
+{
+ UINT32 r1 = convert_zero[(op >> 5) & 31];
+ WRITELONG(jaguar, jaguar->r[14] + r1 * 4, jaguar->r[op & 31]);
+}
+
+void store_rn_r15n(jaguar_state *jaguar, UINT16 op)
+{
+ UINT32 r1 = convert_zero[(op >> 5) & 31];
+ WRITELONG(jaguar, jaguar->r[15] + r1 * 4, jaguar->r[op & 31]);
+}
+
+void store_rn_r14rn(jaguar_state *jaguar, UINT16 op)
+{
+ UINT32 r1 = jaguar->r[(op >> 5) & 31];
+ WRITELONG(jaguar, jaguar->r[14] + r1, jaguar->r[op & 31]);
+}
+
+void store_rn_r15rn(jaguar_state *jaguar, UINT16 op)
+{
+ UINT32 r1 = jaguar->r[(op >> 5) & 31];
+ WRITELONG(jaguar, jaguar->r[15] + r1, jaguar->r[op & 31]);
+}
+
+void storeb_rn_rn(jaguar_state *jaguar, UINT16 op)
+{
+ UINT32 r1 = jaguar->r[(op >> 5) & 31];
+ WRITEBYTE(jaguar, r1, jaguar->r[op & 31]);
+}
+
+void storew_rn_rn(jaguar_state *jaguar, UINT16 op)
+{
+ UINT32 r1 = jaguar->r[(op >> 5) & 31];
+ WRITEWORD(jaguar, r1, jaguar->r[op & 31]);
+}
+
+void storep_rn_rn(jaguar_state *jaguar, UINT16 op) /* GPU only */
+{
+ UINT32 r1 = jaguar->r[(op >> 5) & 31];
+ WRITELONG(jaguar, r1, jaguar->ctrl[G_HIDATA]);
+ WRITELONG(jaguar, r1+4, jaguar->r[op & 31]);
+}
+
+void sub_rn_rn(jaguar_state *jaguar, UINT16 op)
+{
+ int dreg = op & 31;
+ UINT32 r1 = jaguar->r[(op >> 5) & 31];
+ UINT32 r2 = jaguar->r[dreg];
+ UINT32 res = r2 - r1;
+ jaguar->r[dreg] = res;
+ CLR_ZNC(jaguar); SET_ZNC_SUB(jaguar, r2, r1, res);
+}
+
+void subc_rn_rn(jaguar_state *jaguar, UINT16 op)
+{
+ int dreg = op & 31;
+ UINT32 r1 = jaguar->r[(op >> 5) & 31];
+ UINT32 r2 = jaguar->r[dreg];
+ UINT32 res = r2 - r1 - ((jaguar->FLAGS >> 1) & 1);
+ jaguar->r[dreg] = res;
+ CLR_ZNC(jaguar); SET_ZNC_SUB(jaguar, r2, r1, res);
+}
+
+void subq_n_rn(jaguar_state *jaguar, UINT16 op)
+{
+ int dreg = op & 31;
+ UINT32 r1 = convert_zero[(op >> 5) & 31];
+ UINT32 r2 = jaguar->r[dreg];
+ UINT32 res = r2 - r1;
+ jaguar->r[dreg] = res;
+ CLR_ZNC(jaguar); SET_ZNC_SUB(jaguar, r2, r1, res);
+}
+
+void subqmod_n_rn(jaguar_state *jaguar, UINT16 op) /* DSP only */
+{
+ int dreg = op & 31;
+ UINT32 r1 = convert_zero[(op >> 5) & 31];
+ UINT32 r2 = jaguar->r[dreg];
+ UINT32 res = r2 - r1;
+ res = (res & ~jaguar->ctrl[D_MOD]) | (r2 & ~jaguar->ctrl[D_MOD]);
+ jaguar->r[dreg] = res;
+ CLR_ZNC(jaguar); SET_ZNC_SUB(jaguar, r2, r1, res);
+}
+
+void subqt_n_rn(jaguar_state *jaguar, UINT16 op)
+{
+ int dreg = op & 31;
+ UINT32 r1 = convert_zero[(op >> 5) & 31];
+ UINT32 r2 = jaguar->r[dreg];
+ UINT32 res = r2 - r1;
+ jaguar->r[dreg] = res;
+}
+
+void xor_rn_rn(jaguar_state *jaguar, UINT16 op)
+{
+ int dreg = op & 31;
+ UINT32 r1 = jaguar->r[(op >> 5) & 31];
+ UINT32 r2 = jaguar->r[dreg];
+ UINT32 res = r1 ^ r2;
+ jaguar->r[dreg] = res;
+ CLR_ZN(jaguar); SET_ZN(jaguar, res);
+}
+
+
+
+/***************************************************************************
+ I/O HANDLING
+***************************************************************************/
+
+UINT32 jaguargpu_ctrl_r(device_t *device, offs_t offset)
+{
+ jaguar_state *jaguar = get_safe_token(device);
+
+ if (LOG_GPU_IO) logerror("GPU read register @ F021%02X\n", offset * 4);
+
+ return jaguar->ctrl[offset];
+}
+
+
+void jaguargpu_ctrl_w(device_t *device, offs_t offset, UINT32 data, UINT32 mem_mask)
+{
+ jaguar_state *jaguar = get_safe_token(device);
+ UINT32 oldval, newval;
+
+ if (LOG_GPU_IO && offset != G_HIDATA)
+ logerror("GPU write register @ F021%02X = %08X\n", offset * 4, data);
+
+ /* remember the old and set the new */
+ oldval = jaguar->ctrl[offset];
+ newval = oldval;
+ COMBINE_DATA(&newval);
+
+ /* handle the various registers */
+ switch (offset)
+ {
+ case G_FLAGS:
+
+ /* combine the data properly */
+ jaguar->ctrl[offset] = newval & (ZFLAG | CFLAG | NFLAG | EINT04FLAGS | RPAGEFLAG);
+ if (newval & IFLAG)
+ jaguar->ctrl[offset] |= oldval & IFLAG;
+
+ /* clear interrupts */
+ jaguar->ctrl[G_CTRL] &= ~((newval & CINT04FLAGS) >> 3);
+
+ /* determine which register bank should be active */
+ update_register_banks(jaguar);
+
+ /* update IRQs */
+ check_irqs(jaguar);
+ break;
+
+ case G_MTXC:
+ case G_MTXA:
+ jaguar->ctrl[offset] = newval;
+ break;
+
+ case G_END:
+ jaguar->ctrl[offset] = newval;
+ if ((newval & 7) != 7)
+ logerror("GPU to set to little-endian!\n");
+ break;
+
+ case G_PC:
+ jaguar->PC = newval & 0xffffff;
+ break;
+
+ case G_CTRL:
+ jaguar->ctrl[offset] = newval;
+ if ((oldval ^ newval) & 0x01)
+ {
+ device_set_input_line(device, INPUT_LINE_HALT, (newval & 1) ? CLEAR_LINE : ASSERT_LINE);
+ device_yield(device);
+ }
+ if (newval & 0x02)
+ {
+ if (jaguar->cpu_interrupt != NULL)
+ (*jaguar->cpu_interrupt)(device);
+ jaguar->ctrl[offset] &= ~0x02;
+ }
+ if (newval & 0x04)
+ {
+ jaguar->ctrl[G_CTRL] |= 1 << 6;
+ jaguar->ctrl[offset] &= ~0x04;
+ check_irqs(jaguar);
+ }
+ if (newval & 0x18)
+ {
+ logerror("GPU single stepping was enabled!\n");
+ }
+ break;
+
+ case G_HIDATA:
+ case G_DIVCTRL:
+ jaguar->ctrl[offset] = newval;
+ break;
+ }
+}
+
+
+
+/***************************************************************************
+ I/O HANDLING
+***************************************************************************/
+
+UINT32 jaguardsp_ctrl_r(device_t *device, offs_t offset)
+{
+ jaguar_state *jaguar = get_safe_token(device);
+
+ if (LOG_DSP_IO && offset != D_FLAGS)
+ logerror("DSP read register @ F1A1%02X\n", offset * 4);
+
+ /* switch to the target context */
+ return jaguar->ctrl[offset];
+}
+
+
+void jaguardsp_ctrl_w(device_t *device, offs_t offset, UINT32 data, UINT32 mem_mask)
+{
+ jaguar_state *jaguar = get_safe_token(device);
+ UINT32 oldval, newval;
+
+ if (LOG_DSP_IO && offset != D_FLAGS)
+ logerror("DSP write register @ F1A1%02X = %08X\n", offset * 4, data);
+
+ /* remember the old and set the new */
+ oldval = jaguar->ctrl[offset];
+ newval = oldval;
+ COMBINE_DATA(&newval);
+
+ /* handle the various registers */
+ switch (offset)
+ {
+ case D_FLAGS:
+
+ /* combine the data properly */
+ jaguar->ctrl[offset] = newval & (ZFLAG | CFLAG | NFLAG | EINT04FLAGS | EINT5FLAG | RPAGEFLAG);
+ if (newval & IFLAG)
+ jaguar->ctrl[offset] |= oldval & IFLAG;
+
+ /* clear interrupts */
+ jaguar->ctrl[D_CTRL] &= ~((newval & CINT04FLAGS) >> 3);
+ jaguar->ctrl[D_CTRL] &= ~((newval & CINT5FLAG) >> 1);
+
+ /* determine which register bank should be active */
+ update_register_banks(jaguar);
+
+ /* update IRQs */
+ check_irqs(jaguar);
+ break;
+
+ case D_MTXC:
+ case D_MTXA:
+ jaguar->ctrl[offset] = newval;
+ break;
+
+ case D_END:
+ jaguar->ctrl[offset] = newval;
+ if ((newval & 7) != 7)
+ logerror("DSP to set to little-endian!\n");
+ break;
+
+ case D_PC:
+ jaguar->PC = newval & 0xffffff;
+ break;
+
+ case D_CTRL:
+ jaguar->ctrl[offset] = newval;
+ if ((oldval ^ newval) & 0x01)
+ {
+ device_set_input_line(device, INPUT_LINE_HALT, (newval & 1) ? CLEAR_LINE : ASSERT_LINE);
+ device_yield(device);
+ }
+ if (newval & 0x02)
+ {
+ if (jaguar->cpu_interrupt != NULL)
+ (*jaguar->cpu_interrupt)(device);
+ jaguar->ctrl[offset] &= ~0x02;
+ }
+ if (newval & 0x04)
+ {
+ jaguar->ctrl[D_CTRL] |= 1 << 6;
+ jaguar->ctrl[offset] &= ~0x04;
+ check_irqs(jaguar);
+ }
+ if (newval & 0x18)
+ {
+ logerror("DSP single stepping was enabled!\n");
+ }
+ break;
+
+ case D_MOD:
+ case D_DIVCTRL:
+ jaguar->ctrl[offset] = newval;
+ break;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( jaguargpu )
+{
+ jaguar_state *jaguar = get_safe_token(device);
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + JAGUAR_IRQ0: set_irq_line(jaguar, JAGUAR_IRQ0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + JAGUAR_IRQ1: set_irq_line(jaguar, JAGUAR_IRQ1, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + JAGUAR_IRQ2: set_irq_line(jaguar, JAGUAR_IRQ2, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + JAGUAR_IRQ3: set_irq_line(jaguar, JAGUAR_IRQ3, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + JAGUAR_IRQ4: set_irq_line(jaguar, JAGUAR_IRQ4, info->i); break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + JAGUAR_PC: jaguar->PC = info->i; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_FLAGS: jaguar->FLAGS = info->i; break;
+
+ case CPUINFO_INT_REGISTER + JAGUAR_R0: jaguar->r[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R1: jaguar->r[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R2: jaguar->r[2] = info->i; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R3: jaguar->r[3] = info->i; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R4: jaguar->r[4] = info->i; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R5: jaguar->r[5] = info->i; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R6: jaguar->r[6] = info->i; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R7: jaguar->r[7] = info->i; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R8: jaguar->r[8] = info->i; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R9: jaguar->r[9] = info->i; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R10: jaguar->r[10] = info->i; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R11: jaguar->r[11] = info->i; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R12: jaguar->r[12] = info->i; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R13: jaguar->r[13] = info->i; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R14: jaguar->r[14] = info->i; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R15: jaguar->r[15] = info->i; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R16: jaguar->r[16] = info->i; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R17: jaguar->r[17] = info->i; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R18: jaguar->r[18] = info->i; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R19: jaguar->r[19] = info->i; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R20: jaguar->r[20] = info->i; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R21: jaguar->r[21] = info->i; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R22: jaguar->r[22] = info->i; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R23: jaguar->r[23] = info->i; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R24: jaguar->r[24] = info->i; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R25: jaguar->r[25] = info->i; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R26: jaguar->r[26] = info->i; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R27: jaguar->r[27] = info->i; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R28: jaguar->r[28] = info->i; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R29: jaguar->r[29] = info->i; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R30: jaguar->r[30] = info->i; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R31: jaguar->r[31] = info->i; break;
+ case CPUINFO_INT_SP: jaguar->b0[31] = info->i; break;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+CPU_GET_INFO( jaguargpu )
+{
+ jaguar_state *jaguar = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(jaguar_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 5; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 2; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 6; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 1; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 24; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+
+ case CPUINFO_INT_INPUT_STATE + JAGUAR_IRQ0: info->i = (jaguar->ctrl[G_CTRL] & 0x40) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + JAGUAR_IRQ1: info->i = (jaguar->ctrl[G_CTRL] & 0x80) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + JAGUAR_IRQ2: info->i = (jaguar->ctrl[G_CTRL] & 0x100) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + JAGUAR_IRQ3: info->i = (jaguar->ctrl[G_CTRL] & 0x200) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + JAGUAR_IRQ4: info->i = (jaguar->ctrl[G_CTRL] & 0x400) ? ASSERT_LINE : CLEAR_LINE; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = jaguar->ppc; break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + JAGUAR_PC: info->i = jaguar->PC; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_FLAGS: info->i = jaguar->FLAGS; break;
+
+ case CPUINFO_INT_REGISTER + JAGUAR_R0: info->i = jaguar->r[0]; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R1: info->i = jaguar->r[1]; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R2: info->i = jaguar->r[2]; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R3: info->i = jaguar->r[3]; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R4: info->i = jaguar->r[4]; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R5: info->i = jaguar->r[5]; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R6: info->i = jaguar->r[6]; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R7: info->i = jaguar->r[7]; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R8: info->i = jaguar->r[8]; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R9: info->i = jaguar->r[9]; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R10: info->i = jaguar->r[10]; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R11: info->i = jaguar->r[11]; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R12: info->i = jaguar->r[12]; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R13: info->i = jaguar->r[13]; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R14: info->i = jaguar->r[14]; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R15: info->i = jaguar->r[15]; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R16: info->i = jaguar->r[16]; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R17: info->i = jaguar->r[17]; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R18: info->i = jaguar->r[18]; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R19: info->i = jaguar->r[19]; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R20: info->i = jaguar->r[20]; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R21: info->i = jaguar->r[21]; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R22: info->i = jaguar->r[22]; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R23: info->i = jaguar->r[23]; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R24: info->i = jaguar->r[24]; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R25: info->i = jaguar->r[25]; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R26: info->i = jaguar->r[26]; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R27: info->i = jaguar->r[27]; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R28: info->i = jaguar->r[28]; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R29: info->i = jaguar->r[29]; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R30: info->i = jaguar->r[30]; break;
+ case CPUINFO_INT_REGISTER + JAGUAR_R31: info->i = jaguar->r[31]; break;
+ case CPUINFO_INT_SP: info->i = jaguar->b0[31]; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(jaguargpu); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(jaguargpu); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(jaguar); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(jaguar); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(jaguargpu); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(jaguargpu);break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &jaguar->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "Jaguar GPU"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Atari Jaguar"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Aaron Giles"); break;
+
+ case CPUINFO_STR_FLAGS: sprintf(info->s, "%c%c%c%c%c%c%c%c%c%c%c",
+ jaguar->FLAGS & 0x8000 ? 'D':'.',
+ jaguar->FLAGS & 0x4000 ? 'A':'.',
+ jaguar->FLAGS & 0x0100 ? '4':'.',
+ jaguar->FLAGS & 0x0080 ? '3':'.',
+ jaguar->FLAGS & 0x0040 ? '2':'.',
+ jaguar->FLAGS & 0x0020 ? '1':'.',
+ jaguar->FLAGS & 0x0010 ? '0':'.',
+ jaguar->FLAGS & 0x0008 ? 'I':'.',
+ jaguar->FLAGS & 0x0004 ? 'N':'.',
+ jaguar->FLAGS & 0x0002 ? 'C':'.',
+ jaguar->FLAGS & 0x0001 ? 'Z':'.'); break;
+
+ case CPUINFO_STR_REGISTER + JAGUAR_PC: sprintf(info->s, "PC: %08X", jaguar->PC); break;
+ case CPUINFO_STR_REGISTER + JAGUAR_FLAGS: sprintf(info->s, "FLAGS: %08X", jaguar->FLAGS); break;
+ case CPUINFO_STR_REGISTER + JAGUAR_R0: sprintf(info->s, "R0: %08X", jaguar->r[0]); break;
+ case CPUINFO_STR_REGISTER + JAGUAR_R1: sprintf(info->s, "R1: %08X", jaguar->r[1]); break;
+ case CPUINFO_STR_REGISTER + JAGUAR_R2: sprintf(info->s, "R2: %08X", jaguar->r[2]); break;
+ case CPUINFO_STR_REGISTER + JAGUAR_R3: sprintf(info->s, "R3: %08X", jaguar->r[3]); break;
+ case CPUINFO_STR_REGISTER + JAGUAR_R4: sprintf(info->s, "R4: %08X", jaguar->r[4]); break;
+ case CPUINFO_STR_REGISTER + JAGUAR_R5: sprintf(info->s, "R5: %08X", jaguar->r[5]); break;
+ case CPUINFO_STR_REGISTER + JAGUAR_R6: sprintf(info->s, "R6: %08X", jaguar->r[6]); break;
+ case CPUINFO_STR_REGISTER + JAGUAR_R7: sprintf(info->s, "R7: %08X", jaguar->r[7]); break;
+ case CPUINFO_STR_REGISTER + JAGUAR_R8: sprintf(info->s, "R8: %08X", jaguar->r[8]); break;
+ case CPUINFO_STR_REGISTER + JAGUAR_R9: sprintf(info->s, "R9: %08X", jaguar->r[9]); break;
+ case CPUINFO_STR_REGISTER + JAGUAR_R10: sprintf(info->s, "R10:%08X", jaguar->r[10]); break;
+ case CPUINFO_STR_REGISTER + JAGUAR_R11: sprintf(info->s, "R11:%08X", jaguar->r[11]); break;
+ case CPUINFO_STR_REGISTER + JAGUAR_R12: sprintf(info->s, "R12:%08X", jaguar->r[12]); break;
+ case CPUINFO_STR_REGISTER + JAGUAR_R13: sprintf(info->s, "R13:%08X", jaguar->r[13]); break;
+ case CPUINFO_STR_REGISTER + JAGUAR_R14: sprintf(info->s, "R14:%08X", jaguar->r[14]); break;
+ case CPUINFO_STR_REGISTER + JAGUAR_R15: sprintf(info->s, "R15:%08X", jaguar->r[15]); break;
+ case CPUINFO_STR_REGISTER + JAGUAR_R16: sprintf(info->s, "R16:%08X", jaguar->r[16]); break;
+ case CPUINFO_STR_REGISTER + JAGUAR_R17: sprintf(info->s, "R17:%08X", jaguar->r[17]); break;
+ case CPUINFO_STR_REGISTER + JAGUAR_R18: sprintf(info->s, "R18:%08X", jaguar->r[18]); break;
+ case CPUINFO_STR_REGISTER + JAGUAR_R19: sprintf(info->s, "R19:%08X", jaguar->r[19]); break;
+ case CPUINFO_STR_REGISTER + JAGUAR_R20: sprintf(info->s, "R20:%08X", jaguar->r[20]); break;
+ case CPUINFO_STR_REGISTER + JAGUAR_R21: sprintf(info->s, "R21:%08X", jaguar->r[21]); break;
+ case CPUINFO_STR_REGISTER + JAGUAR_R22: sprintf(info->s, "R22:%08X", jaguar->r[22]); break;
+ case CPUINFO_STR_REGISTER + JAGUAR_R23: sprintf(info->s, "R23:%08X", jaguar->r[23]); break;
+ case CPUINFO_STR_REGISTER + JAGUAR_R24: sprintf(info->s, "R24:%08X", jaguar->r[24]); break;
+ case CPUINFO_STR_REGISTER + JAGUAR_R25: sprintf(info->s, "R25:%08X", jaguar->r[25]); break;
+ case CPUINFO_STR_REGISTER + JAGUAR_R26: sprintf(info->s, "R26:%08X", jaguar->r[26]); break;
+ case CPUINFO_STR_REGISTER + JAGUAR_R27: sprintf(info->s, "R27:%08X", jaguar->r[27]); break;
+ case CPUINFO_STR_REGISTER + JAGUAR_R28: sprintf(info->s, "R28:%08X", jaguar->r[28]); break;
+ case CPUINFO_STR_REGISTER + JAGUAR_R29: sprintf(info->s, "R29:%08X", jaguar->r[29]); break;
+ case CPUINFO_STR_REGISTER + JAGUAR_R30: sprintf(info->s, "R30:%08X", jaguar->r[30]); break;
+ case CPUINFO_STR_REGISTER + JAGUAR_R31: sprintf(info->s, "R31:%08X", jaguar->r[31]); break;
+ }
+}
+
+
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( jaguardsp )
+{
+ jaguar_state *jaguar = get_safe_token(device);
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + JAGUAR_IRQ5: set_irq_line(jaguar, JAGUAR_IRQ5, info->i); break;
+
+ /* --- the following bits of info are set as pointers to data or functions --- */
+
+ default: CPU_SET_INFO_CALL(jaguargpu); break;
+ }
+}
+
+CPU_GET_INFO( jaguardsp )
+{
+ jaguar_state *jaguar = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_LINES: info->i = 6; break;
+ case CPUINFO_INT_INPUT_STATE + JAGUAR_IRQ5: info->i = (jaguar->ctrl[G_CTRL] & 0x10000) ? ASSERT_LINE : CLEAR_LINE; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(jaguardsp); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(jaguardsp); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(jaguardsp); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(jaguardsp);break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "Jaguar DSP"); break;
+
+ default: CPU_GET_INFO_CALL(jaguargpu); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(JAGUARGPU, jaguargpu);
+DEFINE_LEGACY_CPU_DEVICE(JAGUARDSP, jaguardsp);
diff --git a/trunk/src/emu/cpu/jaguar/jaguar.h b/trunk/src/emu/cpu/jaguar/jaguar.h
new file mode 100644
index 00000000000..a29da2384d4
--- /dev/null
+++ b/trunk/src/emu/cpu/jaguar/jaguar.h
@@ -0,0 +1,111 @@
+/***************************************************************************
+
+ jaguar.h
+ Interface file for the portable Jaguar DSP emulator.
+ Written by Aaron Giles
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __JAGUAR_H__
+#define __JAGUAR_H__
+
+
+
+/***************************************************************************
+ GLOBAL CONSTANTS
+***************************************************************************/
+
+#define JAGUAR_VARIANT_GPU 0
+#define JAGUAR_VARIANT_DSP 1
+
+
+
+/***************************************************************************
+ REGISTER ENUMERATION
+***************************************************************************/
+
+enum
+{
+ JAGUAR_PC=1,JAGUAR_FLAGS,
+ JAGUAR_R0,JAGUAR_R1,JAGUAR_R2,JAGUAR_R3,JAGUAR_R4,JAGUAR_R5,JAGUAR_R6,JAGUAR_R7,
+ JAGUAR_R8,JAGUAR_R9,JAGUAR_R10,JAGUAR_R11,JAGUAR_R12,JAGUAR_R13,JAGUAR_R14,JAGUAR_R15,
+ JAGUAR_R16,JAGUAR_R17,JAGUAR_R18,JAGUAR_R19,JAGUAR_R20,JAGUAR_R21,JAGUAR_R22,JAGUAR_R23,
+ JAGUAR_R24,JAGUAR_R25,JAGUAR_R26,JAGUAR_R27,JAGUAR_R28,JAGUAR_R29,JAGUAR_R30,JAGUAR_R31
+};
+
+enum
+{
+ G_FLAGS = 0,
+ G_MTXC,
+ G_MTXA,
+ G_END,
+ G_PC,
+ G_CTRL,
+ G_HIDATA,
+ G_DIVCTRL,
+ G_DUMMY,
+ G_REMAINDER,
+ G_CTRLMAX
+};
+
+enum
+{
+ D_FLAGS = 0,
+ D_MTXC,
+ D_MTXA,
+ D_END,
+ D_PC,
+ D_CTRL,
+ D_MOD,
+ D_DIVCTRL,
+ D_MACHI,
+ D_REMAINDER,
+ D_CTRLMAX
+};
+
+
+
+/***************************************************************************
+ CONFIGURATION STRUCTURE
+***************************************************************************/
+
+typedef void (*jaguar_int_func)(device_t *device);
+
+
+typedef struct _jaguar_cpu_config jaguar_cpu_config;
+struct _jaguar_cpu_config
+{
+ jaguar_int_func cpu_int_callback;
+};
+
+
+
+/***************************************************************************
+ INTERRUPT CONSTANTS
+***************************************************************************/
+
+#define JAGUAR_IRQ0 0 /* IRQ0 */
+#define JAGUAR_IRQ1 1 /* IRQ1 */
+#define JAGUAR_IRQ2 2 /* IRQ2 */
+#define JAGUAR_IRQ3 3 /* IRQ3 */
+#define JAGUAR_IRQ4 4 /* IRQ4 */
+#define JAGUAR_IRQ5 5 /* IRQ5 */
+
+
+
+/***************************************************************************
+ PUBLIC FUNCTIONS
+***************************************************************************/
+
+DECLARE_LEGACY_CPU_DEVICE(JAGUARGPU, jaguargpu);
+extern void jaguargpu_ctrl_w(device_t *device, offs_t offset, UINT32 data, UINT32 mem_mask);
+extern UINT32 jaguargpu_ctrl_r(device_t *device, offs_t offset);
+
+DECLARE_LEGACY_CPU_DEVICE(JAGUARDSP, jaguardsp);
+extern void jaguardsp_ctrl_w(device_t *device, offs_t offset, UINT32 data, UINT32 mem_mask);
+extern UINT32 jaguardsp_ctrl_r(device_t *device, offs_t offset);
+
+
+#endif /* __JAGUAR_H__ */
diff --git a/trunk/src/emu/cpu/konami/knmidasm.c b/trunk/src/emu/cpu/konami/knmidasm.c
new file mode 100644
index 00000000000..a3def422110
--- /dev/null
+++ b/trunk/src/emu/cpu/konami/knmidasm.c
@@ -0,0 +1,1875 @@
+#include "emu.h"
+#include "debugger.h"
+#include "konami.h"
+
+#ifndef TRUE
+#define TRUE -1
+#define FALSE 0
+#endif
+
+/*
+
+0x08 leax indexed
+0x09 leay indexed (not confirmed)
+0x0a leau indexed
+0x0b leas indexed (not confirmed)
+
+0x0c pushs xx
+0x0d pushu xx (not confirmed)
+0x0e pulls xx
+0x0f pulls xx (not confirmed)
+
+0x10 lda xx
+0x11 ldb xx
+0x12 lda indexed
+0x13 ldb indexed
+
+0x14 adda xx
+0x15 addb xx (not confirmed)
+0x16 adda indexed (not confirmed)
+0x17 addb indexed
+
+0x18 adca xx
+0x19 adcb xx (not confirmed)
+0x1a adca indexed (not confirmed)
+0x1b adcb indexed (not confirmed)
+
+0x1c suba xx
+0x1d subb xx
+0x1e suba indexed
+0x1f subb indexed
+
+0x20 sbca xx
+0x21 sbcb xx
+0x22 sbca indexed
+0x23 sbcb indexed
+
+0x24 anda xx
+0x25 andb xx
+0x26 anda indexed
+0x27 andb indexed
+
+0x28 bita xx
+0x29 bitb xx
+0x2a bita indexed
+0x2b bitb indexed
+
+0x2c eora xx
+0x2d eorb xx
+0x2e eora indexed
+0x2f eorb indexed
+
+0x30 ora xx
+0x31 orb xx
+0x32 ora indexed
+0x33 orb indexed
+
+0x34 cmpa xx
+0x35 cmpb xx
+0x36 cmpa indexed
+0x37 cmpb indexed
+
+CUSTOM OPCODE: Set Address lines 16-23
+--------------------------------------
+0x38 setlines xx
+0x39 setlines indexed
+
+The eight bits taken as parameter set address lines 16 to 23.
+
+
+0x3a sta indexed
+0x3b stb indexed
+0x3c andcc
+0x3d orcc
+
+0x3e exg xx
+0x3f tfr xx
+
+0x40 ldd xx xx
+0x41 ldd indexed
+0x42 ldx xx xx
+0x43 ldx indexed
+0x44 ldy xx xx
+0x45 ldy indexed (not confirmed)
+0x46 ldu xx xx
+0x47 ldu indexed
+0x48 lds xx xx
+0x49 lds indexed (not confirmed)
+
+0x4a cmpd xx xx
+0x4b cmpd indexed
+0x4c cmpx xx xx
+0x4d cmpx indexed
+0x4e cmpy xx xx (not confirmed)
+0x4f cmpy indexed (not confirmed)
+0x50 cmpu xx xx (not confirmed)
+0x51 cmpu indexed (not confirmed)
+0x52 cmps xx xx (not confirmed)
+0x53 cmps indexed (not confirmed)
+
+0x54 addd xx xx
+0x55 addd indexed (not confirmed)
+0x56 subd xx xx
+0x57 subd indexed (not confirmed)
+
+0x58 std indexed
+0x59 stx indexed
+0x5a sty indexed
+0x5b stu indexed
+0x5c sts indexed (not confirmed)
+
+
+BRANCH OPCODE TABLE :
+---------------------
+
+Opcode M6809 Konami
+BRA 20 60
+BRN 21 70
+BHI 22 61
+BLS 23 71
+BCC 24 62
+BCS 25 72
+BNE 26 63
+BEQ 27 73
+BVC 28 64
+BVS 29 74
+BPL 2a 65
+BMI 2b 75
+BGE 2c 66
+BLT 2d 76
+BGT 2e 67
+BLE 2f 77
+
+Long versions of the branchs are the number + 8.
+
+0x80 clra
+0x81 clrb
+0x82 clr indexed
+
+0x83 coma
+0x84 comb
+0x85 com indexed
+
+0x86 nega (not confirmed)
+0x87 negb (not confirmed)
+0x88 neg indexed (not confirmed)
+
+0x89 inca
+0x8a incb (not confirmed)
+0x8b inc indexed
+
+0x8c deca
+0x8d decb
+0x8e dec indexed
+
+0x8f rts
+
+0x90 tsta (not confirmed)
+0x91 tstb (not confirmed)
+0x92 tst indexed (not confirmed)
+
+0x93 lsra
+0x94 lsrb
+0x95 lsr indexed
+
+0x96 rora
+0x97 rorb
+0x98 ror indexed
+
+0x99 asra
+0x9a asrb
+0x9b asr indexed
+
+0x9c asla
+0x9d aslb
+0x9e asl indexed
+
+0x9f rti
+
+0xa0 rola
+0xa1 rolb
+0xa2 rol indexed
+
+0xa3 lsrw indexed ( not confirmed )
+0xa4 rorw indexed ( not confirmed )
+0xa5 asrw indexed ( not confirmed )
+0xa6 aslw indexed ( not confirmed )
+0xa7 rolw indexed ( not confirmed )
+
+0xa8 jmp indexed
+0xa9 jsr indexed
+0xaa bsr xx
+0xab lbsr xx xx
+0xac decb,jnz xx
+0xad decx,jnz xx
+0xae nop
+
+0xb0 abx
+0xb1 daa
+0xb2 sex
+
+0xb3 mul
+
+0xb4 lmul x:y = x * y
+
+0xb5 divx x = ( x / b ), b = ( x % b )
+
+CUSTOM OPCODE: BlockMove (y,x,u):
+---------------------------------
+0xb6 bmove y,x,u
+
+y = pointer to source address
+x = pointer to destination address
+u = bytes to move
+
+One byte is copied at a time and x and y get incremented for each access.
+
+CUSTOM OPCODE: Move (y,x,u):
+---------------------------------
+0xb7 move y,x,u
+
+y = pointer to source address
+x = pointer to destination address
+u = counter
+
+Copy ONE byte, increment x and y, decrement u.
+
+0xb8 lsrd xx
+0xb9 lsrd indexed
+0xba rord xx ( not confirmed )
+0xbb rord indexed ( not confirmed )
+0xbc asrd xx ( not confirmed )
+0xbd asrd indexed ( not confirmed )
+0xbe asld xx
+0xbf asld indexed ( not confirmed )
+0xc0 rold xx ( not confirmed )
+0xc1 rold indexed ( not confirmed )
+
+0xc2 clrd
+0xc3 clrw indexed ( clears an entire word ) ( not confirmed )
+
+0xc4 negd (not confirmed )
+0xc5 negw indexed
+
+0xc6 incd (not confirmed )
+0xc7 incw indexed
+
+0xc8 decd (not confirmed )
+0xc9 decw indexed
+
+0xca tstd
+0xcb tstw indexed
+
+0xcc absa
+0xcd absb
+0xce absd
+
+CUSTOM OPCODE: BlockSet (a,x,u):
+---------------------------------
+0xcf bset a,x,u
+
+a = source data
+x = pointer to destination address
+u = bytes to move
+
+One byte is copied at a time and x get incremented for each access.
+
+CUSTOM OPCODE: BlockSet (d,x,u): (not confirmed)
+--------------------------------
+0xd0 bset d,x,u
+
+d = source data
+x = pointer to destination address
+u = bytes to move/2
+
+Two bytes are copied at a time and x get incremented twice for each access.
+
+*/
+
+static unsigned byte_count;
+static unsigned local_pc;
+static unsigned flags;
+
+static const unsigned char *opram_ptr;
+
+static unsigned char get_next_byte( void ) {
+ return opram_ptr[byte_count++];
+}
+
+/* Table for indexed operations */
+static const char index_reg[8][3] = {
+ "?", /* 0 - extended mode */
+ "?", /* 1 */
+ "x", /* 2 */
+ "y", /* 3 */
+ "?", /* 4 - direct page */
+ "u", /* 5 */
+ "s", /* 6 */
+ "pc" /* 7 - pc */
+};
+
+/* Table for tfr/exg operations */
+static const char tfrexg_reg[8][3] = {
+ "a", /* 0 */
+ "b", /* 1 */
+ "x", /* 2 */
+ "y", /* 3 */
+ "s", /* 4 */
+ "u", /* 5 */
+ "?", /* 6 */
+ "?", /* 7 */
+};
+
+/* Table for stack S operations */
+static const char stack_reg_s[8][3] = {
+ "cc",
+ "a",
+ "b",
+ "dp",
+ "x",
+ "y",
+ "u",
+ "pc"
+};
+
+/* Table for stack U operations */
+static const char stack_reg_u[8][3] = {
+ "cc",
+ "a",
+ "b",
+ "dp",
+ "x",
+ "y",
+ "s",
+ "pc"
+};
+
+static void calc_indexed( unsigned char mode, char *buf ) {
+ char buf2[30];
+ int idx, type;
+
+ idx = ( mode >> 4 ) & 7;
+ type = mode & 0x0f;
+
+ /* special modes */
+ if ( mode & 0x80 ) {
+ if ( type & 8 ) { /* indirect */
+ switch ( type & 7 ) {
+ case 0x00: /* register a */
+ sprintf( buf2, "[a,%s]", index_reg[idx] );
+ break;
+
+ case 0x01: /* register b */
+ sprintf( buf2, "[b,%s]", index_reg[idx] );
+ break;
+
+ case 0x04: /* direct - mode */
+ sprintf( buf2, "[$%02x]", get_next_byte() );
+ break;
+
+ case 0x07: /* register d */
+ sprintf( buf2, "[d,%s]", index_reg[idx] );
+ break;
+
+ default:
+ sprintf( buf2, "[?,%s]", index_reg[idx] );
+ break;
+ }
+ } else {
+ switch ( type & 7 ) {
+ case 0x00: /* register a */
+ sprintf( buf2, "a,%s", index_reg[idx] );
+ break;
+
+ case 0x01: /* register b */
+ sprintf( buf2, "b,%s", index_reg[idx] );
+ break;
+
+ case 0x04: /* direct - mode */
+ sprintf( buf2, "$%02x", get_next_byte() );
+ break;
+
+ case 0x07: /* register d */
+ sprintf( buf2, "d,%s", index_reg[idx] );
+ break;
+
+ default:
+ sprintf( buf2, "????,%s", index_reg[idx] );
+ break;
+ }
+ }
+ } else {
+ if ( type & 8 ) { /* indirect */
+ switch ( type & 7 ) {
+ case 0: /* auto increment */
+ sprintf( buf2, "[,%s+]", index_reg[idx] );
+ break;
+
+ case 1: /* auto increment double */
+ sprintf( buf2, "[,%s++]", index_reg[idx] );
+ break;
+
+ case 2: /* auto decrement */
+ sprintf( buf2, "[,-%s]", index_reg[idx] );
+ break;
+
+ case 3: /* auto decrement double */
+ sprintf( buf2, "[,--%s]", index_reg[idx] );
+ break;
+
+ case 4: /* post byte offset */
+ {
+ int val = get_next_byte();
+
+ if ( val & 0x80 )
+ sprintf( buf2, "[#$-%02x,%s]", 0x100 - val, index_reg[idx] );
+ else
+ sprintf( buf2, "[#$%02x,%s]", val, index_reg[idx] );
+ }
+ break;
+
+ case 5: /* post word offset */
+ {
+ int val = get_next_byte() << 8;
+
+ val |= get_next_byte();
+
+ if ( val & 0x8000 )
+ sprintf( buf2, "[#$-%04x,%s]", 0x10000 - val, index_reg[idx] );
+ else
+ sprintf( buf2, "[#$%04x,%s]", val, index_reg[idx] );
+ }
+ break;
+
+ case 6: /* simple */
+ sprintf( buf2, "[,%s]", index_reg[idx] );
+ break;
+
+ case 7: /* extended */
+ {
+ int val = get_next_byte() << 8;
+
+ val |= get_next_byte();
+
+ sprintf( buf2, "[$%04x]", val );
+ }
+ break;
+ }
+ } else {
+ switch ( type & 7 ) {
+ case 0: /* auto increment */
+ sprintf( buf2, ",%s+", index_reg[idx] );
+ break;
+
+ case 1: /* auto increment double */
+ sprintf( buf2, ",%s++", index_reg[idx] );
+ break;
+
+ case 2: /* auto decrement */
+ sprintf( buf2, ",-%s", index_reg[idx] );
+ break;
+
+ case 3: /* auto decrement double */
+ sprintf( buf2, ",--%s", index_reg[idx] );
+ break;
+
+ case 4: /* post byte offset */
+ {
+ int val = get_next_byte();
+
+ if ( val & 0x80 )
+ sprintf( buf2, "#$-%02x,%s", 0x100 - val , index_reg[idx] );
+ else
+ sprintf( buf2, "#$%02x,%s", val, index_reg[idx] );
+ }
+ break;
+
+ case 5: /* post word offset */
+ {
+ int val = get_next_byte() << 8;
+
+ val |= get_next_byte();
+
+ if ( val & 0x8000 )
+ sprintf( buf2, "#$-%04x,%s", 0x10000 - val, index_reg[idx] );
+ else
+ sprintf( buf2, "#$%04x,%s", val, index_reg[idx] );
+ }
+ break;
+
+ case 6: /* simple */
+ sprintf( buf2, ",%s", index_reg[idx] );
+ break;
+
+ case 7: /* extended */
+ {
+ int val = get_next_byte() << 8;
+
+ val |= get_next_byte();
+
+ sprintf( buf2, "$%04x", val );
+ }
+ break;
+
+ }
+ }
+ }
+
+ strcat( buf, buf2 );
+}
+
+static void do_relative( char *buf ) {
+ char buf2[30];
+ signed char offs = ( signed char )get_next_byte();
+
+ sprintf( buf2, "$%04x (%d)", local_pc + byte_count + offs, (int)offs );
+
+ strcat( buf, buf2 );
+}
+
+static void do_relative_word( char *buf ) {
+ char buf2[30];
+ signed short offs;
+ int val = get_next_byte() << 8;
+
+ val |= get_next_byte();
+
+ offs = ( signed short )val;
+
+ sprintf( buf2, "$%04x (%d)", local_pc + byte_count + offs, (int)offs );
+
+ strcat( buf, buf2 );
+}
+
+static void do_addressing( char *buf ) {
+ unsigned char mode = get_next_byte();
+
+ calc_indexed( mode, buf );
+}
+
+/*********************************************************************************
+
+ Opcodes
+
+*********************************************************************************/
+
+static void illegal( char *buf ) {
+ sprintf( buf, "illegal/unknown " );
+
+}
+
+static void leax( char *buf ) {
+ sprintf( buf, "leax " );
+ do_addressing( buf );
+}
+
+static void leay( char *buf ) {
+ sprintf( buf, "leay " );
+ do_addressing( buf );
+}
+
+static void leau( char *buf ) {
+ sprintf( buf, "leau " );
+ do_addressing( buf );
+}
+
+static void leas( char *buf ) {
+ sprintf( buf, "leas " );
+ do_addressing( buf );
+}
+
+static void lda( char *buf ) {
+ sprintf( buf, "lda #$%02x", get_next_byte() );
+}
+
+static void ldb( char *buf ) {
+ sprintf( buf, "ldb #$%02x", get_next_byte() );
+}
+
+static void lda2( char *buf ) {
+ sprintf( buf, "lda " );
+ do_addressing( buf );
+}
+
+static void ldb2( char *buf ) {
+ sprintf( buf, "ldb " );
+ do_addressing( buf );
+}
+
+static void adda( char *buf ) {
+ sprintf( buf, "adda #$%02x", get_next_byte() );
+}
+
+static void addb( char *buf ) {
+ sprintf( buf, "addb #$%02x", get_next_byte() );
+}
+
+static void adda2( char *buf ) {
+ sprintf( buf, "adda " );
+ do_addressing( buf );
+}
+
+static void addb2( char *buf ) {
+ sprintf( buf, "addb " );
+ do_addressing( buf );
+}
+
+static void suba( char *buf ) {
+ sprintf( buf, "suba #$%02x", get_next_byte() );
+}
+
+static void subb( char *buf ) {
+ sprintf( buf, "subb #$%02x", get_next_byte() );
+}
+
+static void suba2( char *buf ) {
+ sprintf( buf, "suba " );
+ do_addressing( buf );
+}
+
+static void subb2( char *buf ) {
+ sprintf( buf, "subb " );
+ do_addressing( buf );
+}
+
+static void sbca( char *buf ) {
+ sprintf( buf, "sbca #$%02x", get_next_byte() );
+}
+
+static void sbcb( char *buf ) {
+ sprintf( buf, "sbcb #$%02x", get_next_byte() );
+}
+
+static void sbca2( char *buf ) {
+ sprintf( buf, "sbca " );
+ do_addressing( buf );
+}
+
+static void sbcb2( char *buf ) {
+ sprintf( buf, "sbcb " );
+ do_addressing( buf );
+}
+
+static void adca( char *buf ) {
+ sprintf( buf, "adca #$%02x", get_next_byte() );
+}
+
+static void adca2( char *buf ) {
+ sprintf( buf, "adca " );
+ do_addressing( buf );
+}
+
+static void adcb2( char *buf ) {
+ sprintf( buf, "adcb " );
+ do_addressing( buf );
+}
+
+static void adcb( char *buf ) {
+ sprintf( buf, "adcb #$%02x", get_next_byte() );
+}
+
+static void anda( char *buf ) {
+ sprintf( buf, "anda #$%02x", get_next_byte() );
+}
+
+static void andb( char *buf ) {
+ sprintf( buf, "andb #$%02x", get_next_byte() );
+}
+
+static void anda2( char *buf ) {
+ sprintf( buf, "anda " );
+ do_addressing( buf );
+}
+
+static void andb2( char *buf ) {
+ sprintf( buf, "andb " );
+ do_addressing( buf );
+}
+
+static void bita( char *buf ) {
+ sprintf( buf, "bita #$%02x", get_next_byte() );
+}
+
+static void bitb( char *buf ) {
+ sprintf( buf, "bitb #$%02x", get_next_byte() );
+}
+
+static void bita2( char *buf ) {
+ sprintf( buf, "bita " );
+ do_addressing( buf );
+}
+
+static void bitb2( char *buf ) {
+ sprintf( buf, "bitb " );
+ do_addressing( buf );
+}
+
+static void eora( char *buf ) {
+ sprintf( buf, "eora #$%02x", get_next_byte() );
+}
+
+static void eorb( char *buf ) {
+ sprintf( buf, "eorb #$%02x", get_next_byte() );
+}
+
+static void eora2( char *buf ) {
+ sprintf( buf, "eora " );
+ do_addressing( buf );
+}
+
+static void eorb2( char *buf ) {
+ sprintf( buf, "eorb " );
+ do_addressing( buf );
+}
+
+static void ora( char *buf ) {
+ sprintf( buf, "ora #$%02x", get_next_byte() );
+}
+
+static void orb( char *buf ) {
+ sprintf( buf, "orb #$%02x", get_next_byte() );
+}
+
+static void ora2( char *buf ) {
+ sprintf( buf, "ora " );
+ do_addressing( buf );
+}
+
+static void orb2( char *buf ) {
+ sprintf( buf, "orb " );
+ do_addressing( buf );
+}
+
+static void cmpa( char *buf ) {
+ sprintf( buf, "cmpa #$%02x", get_next_byte() );
+}
+
+static void cmpb( char *buf ) {
+ sprintf( buf, "cmpb #$%02x", get_next_byte() );
+}
+
+static void cmpa2( char *buf ) {
+ sprintf( buf, "cmpa " );
+ do_addressing( buf );
+}
+
+static void cmpb2( char *buf ) {
+ sprintf( buf, "cmpb " );
+ do_addressing( buf );
+}
+
+static void setlines( char *buf ) {
+ sprintf( buf, "setlines #$%02x", get_next_byte() );
+}
+
+static void setlines2( char *buf ) {
+ sprintf( buf, "setlines " );
+ do_addressing( buf );
+}
+
+static void sta2( char *buf ) {
+ sprintf( buf, "sta " );
+ do_addressing( buf );
+}
+
+static void stb2( char *buf ) {
+ sprintf( buf, "stb " );
+ do_addressing( buf );
+}
+
+static void ldd( char *buf ) {
+ int val = get_next_byte() << 8;
+
+ val |= get_next_byte();
+
+ sprintf( buf, "ldd #$%04x", val );
+}
+
+static void ldd2( char *buf ) {
+ sprintf( buf, "ldd " );
+ do_addressing( buf );
+}
+
+static void ldx( char *buf ) {
+ int val = get_next_byte() << 8;
+
+ val |= get_next_byte();
+
+ sprintf( buf, "ldx #$%04x", val );
+}
+
+static void ldx2( char *buf ) {
+ sprintf( buf, "ldx " );
+ do_addressing( buf );
+}
+
+static void ldy( char *buf ) {
+ int val = get_next_byte() << 8;
+
+ val |= get_next_byte();
+
+ sprintf( buf, "ldy #$%04x", val );
+}
+
+static void ldy2( char *buf ) {
+ sprintf( buf, "ldy " );
+ do_addressing( buf );
+}
+
+static void ldu( char *buf ) {
+ int val = get_next_byte() << 8;
+
+ val |= get_next_byte();
+
+ sprintf( buf, "ldu #$%04x", val );
+}
+
+static void ldu2( char *buf ) {
+ sprintf( buf, "ldu " );
+ do_addressing( buf );
+}
+
+static void lds( char *buf ) {
+ int val = get_next_byte() << 8;
+
+ val |= get_next_byte();
+
+ sprintf( buf, "lds #$%04x", val );
+}
+
+static void lds2( char *buf ) {
+ sprintf( buf, "lds " );
+ do_addressing( buf );
+}
+
+static void cmpd( char *buf ) {
+ int val = get_next_byte() << 8;
+
+ val |= get_next_byte();
+
+ sprintf( buf, "cmpd #$%04x", val );
+}
+
+static void cmpd2( char *buf ) {
+ sprintf( buf, "cmpd " );
+ do_addressing( buf );
+}
+
+static void cmpx( char *buf ) {
+ int val = get_next_byte() << 8;
+
+ val |= get_next_byte();
+
+ sprintf( buf, "cmpx #$%04x", val );
+}
+
+static void cmpx2( char *buf ) {
+ sprintf( buf, "cmpx " );
+ do_addressing( buf );
+}
+
+static void cmpy( char *buf ) {
+ int val = get_next_byte() << 8;
+
+ val |= get_next_byte();
+
+ sprintf( buf, "cmpy #$%04x", val );
+}
+
+static void cmpy2( char *buf ) {
+ sprintf( buf, "cmpy " );
+ do_addressing( buf );
+}
+
+static void cmpu( char *buf ) {
+ int val = get_next_byte() << 8;
+
+ val |= get_next_byte();
+
+ sprintf( buf, "cmpu #$%04x", val );
+}
+
+static void cmpu2( char *buf ) {
+ sprintf( buf, "cmpu " );
+ do_addressing( buf );
+}
+
+static void cmps( char *buf ) {
+ int val = get_next_byte() << 8;
+
+ val |= get_next_byte();
+
+ sprintf( buf, "cmps #$%04x", val );
+}
+
+static void cmps2( char *buf ) {
+ sprintf( buf, "cmps " );
+ do_addressing( buf );
+}
+
+static void addd2( char *buf ) {
+ sprintf( buf, "addd " );
+ do_addressing( buf );
+}
+
+static void subd2( char *buf ) {
+ sprintf( buf, "subd " );
+ do_addressing( buf );
+}
+
+static void std2( char *buf ) {
+ sprintf( buf, "std " );
+ do_addressing( buf );
+}
+
+static void stx2( char *buf ) {
+ sprintf( buf, "stx " );
+ do_addressing( buf );
+}
+
+static void sty2( char *buf ) {
+ sprintf( buf, "sty " );
+ do_addressing( buf );
+}
+
+static void stu2( char *buf ) {
+ sprintf( buf, "stu " );
+ do_addressing( buf );
+}
+
+static void sts2( char *buf ) {
+ sprintf( buf, "sts " );
+ do_addressing( buf );
+}
+
+static void bra( char *buf ) {
+ sprintf( buf, "bra " );
+ do_relative( buf );
+}
+
+static void lbra( char *buf ) {
+ sprintf( buf, "lbra " );
+ do_relative_word( buf );
+}
+
+static void brn( char *buf ) {
+ sprintf( buf, "brn " );
+ do_relative( buf );
+}
+
+static void lbrn( char *buf ) {
+ sprintf( buf, "lbrn " );
+ do_relative_word( buf );
+}
+
+static void bhi( char *buf ) {
+ sprintf( buf, "bhi " );
+ do_relative( buf );
+}
+
+static void lbhi( char *buf ) {
+ sprintf( buf, "lbhi " );
+ do_relative_word( buf );
+}
+
+static void bls( char *buf ) {
+ sprintf( buf, "bls " );
+ do_relative( buf );
+}
+
+static void lbls( char *buf ) {
+ sprintf( buf, "lbls " );
+ do_relative_word( buf );
+}
+
+static void bcc( char *buf ) {
+ sprintf( buf, "bcc " );
+ do_relative( buf );
+}
+
+static void lbcc( char *buf ) {
+ sprintf( buf, "lbcc " );
+ do_relative_word( buf );
+}
+
+static void bcs( char *buf ) {
+ sprintf( buf, "bcs " );
+ do_relative( buf );
+}
+
+static void lbcs( char *buf ) {
+ sprintf( buf, "lbcs " );
+ do_relative_word( buf );
+}
+
+static void bne( char *buf ) {
+ sprintf( buf, "bne " );
+ do_relative( buf );
+}
+
+static void lbne( char *buf ) {
+ sprintf( buf, "lbne " );
+ do_relative_word( buf );
+}
+
+static void beq( char *buf ) {
+ sprintf( buf, "beq " );
+ do_relative( buf );
+}
+
+static void lbeq( char *buf ) {
+ sprintf( buf, "lbeq " );
+ do_relative_word( buf );
+}
+
+static void bvc( char *buf ) {
+ sprintf( buf, "bvc " );
+ do_relative( buf );
+}
+
+static void lbvc( char *buf ) {
+ sprintf( buf, "lbvc " );
+ do_relative_word( buf );
+}
+
+static void bvs( char *buf ) {
+ sprintf( buf, "bvs " );
+ do_relative( buf );
+}
+
+static void lbvs( char *buf ) {
+ sprintf( buf, "lbvs " );
+ do_relative_word( buf );
+}
+
+static void bpl( char *buf ) {
+ sprintf( buf, "bpl " );
+ do_relative( buf );
+}
+
+static void lbpl( char *buf ) {
+ sprintf( buf, "lbpl " );
+ do_relative_word( buf );
+}
+
+static void bmi( char *buf ) {
+ sprintf( buf, "bmi " );
+ do_relative( buf );
+}
+
+static void lbmi( char *buf ) {
+ sprintf( buf, "lbmi " );
+ do_relative_word( buf );
+}
+
+static void bge( char *buf ) {
+ sprintf( buf, "bge " );
+ do_relative( buf );
+}
+
+static void lbge( char *buf ) {
+ sprintf( buf, "lbge " );
+ do_relative_word( buf );
+}
+
+static void blt( char *buf ) {
+ sprintf( buf, "blt " );
+ do_relative( buf );
+}
+
+static void lblt( char *buf ) {
+ sprintf( buf, "lblt " );
+ do_relative_word( buf );
+}
+
+static void bgt( char *buf ) {
+ sprintf( buf, "bgt " );
+ do_relative( buf );
+}
+
+static void lbgt( char *buf ) {
+ sprintf( buf, "lbgt " );
+ do_relative_word( buf );
+}
+
+static void ble( char *buf ) {
+ sprintf( buf, "ble " );
+ do_relative( buf );
+}
+
+static void lble( char *buf ) {
+ sprintf( buf, "lble " );
+ do_relative_word( buf );
+}
+
+static void clra( char *buf ) {
+ sprintf( buf, "clra" );
+}
+
+static void clrb( char *buf ) {
+ sprintf( buf, "clrb" );
+}
+
+static void clrd( char *buf ) {
+ sprintf( buf, "clrd" );
+}
+
+static void clrw( char *buf ) {
+ sprintf( buf, "clrw " );
+ do_addressing( buf );
+}
+
+static void negd( char *buf ) {
+ sprintf( buf, "negd" );
+}
+
+static void negw( char *buf ) {
+ sprintf( buf, "negw" );
+ do_addressing( buf );
+}
+
+static void incd( char *buf ) {
+ sprintf( buf, "incd" );
+}
+
+static void incw( char *buf ) {
+ sprintf( buf, "incw " );
+ do_addressing( buf );
+}
+
+static void decd( char *buf ) {
+ sprintf( buf, "decd" );
+}
+
+static void decw( char *buf ) {
+ sprintf( buf, "decw " );
+ do_addressing( buf );
+}
+
+static void tstd( char *buf ) {
+ sprintf( buf, "tstd " );
+}
+
+static void tstw( char *buf ) {
+ sprintf( buf, "tstw " );
+ do_addressing( buf );
+}
+
+static void clr2( char *buf ) {
+ sprintf( buf, "clr " );
+ do_addressing( buf );
+}
+
+static void coma( char *buf ) {
+ sprintf( buf, "coma" );
+}
+
+static void comb( char *buf ) {
+ sprintf( buf, "comb" );
+}
+
+static void com2( char *buf ) {
+ sprintf( buf, "com " );
+ do_addressing( buf );
+}
+
+static void nega( char *buf ) {
+ sprintf( buf, "nega" );
+}
+
+static void negb( char *buf ) {
+ sprintf( buf, "negb" );
+}
+
+static void neg2( char *buf ) {
+ sprintf( buf, "neg " );
+ do_addressing( buf );
+}
+
+static void inca( char *buf ) {
+ sprintf( buf, "inca" );
+}
+
+static void incb( char *buf ) {
+ sprintf( buf, "incb" );
+}
+
+static void inc2( char *buf ) {
+ sprintf( buf, "inc " );
+ do_addressing( buf );
+}
+
+static void deca( char *buf ) {
+ sprintf( buf, "deca" );
+}
+
+static void decb( char *buf ) {
+ sprintf( buf, "decb" );
+}
+
+static void dec2( char *buf ) {
+ sprintf( buf, "dec " );
+ do_addressing( buf );
+}
+
+static void rts( char *buf ) {
+ sprintf( buf, "rts" );
+ flags = DASMFLAG_STEP_OUT;
+}
+
+static void asla( char *buf ) {
+ sprintf( buf, "asla" );
+}
+
+static void aslb( char *buf ) {
+ sprintf( buf, "aslb" );
+}
+
+static void asl2( char *buf ) {
+ sprintf( buf, "asl " );
+ do_addressing( buf );
+}
+
+static void rora( char *buf ) {
+ sprintf( buf, "rora" );
+}
+
+static void rorb( char *buf ) {
+ sprintf( buf, "rorb" );
+}
+
+static void ror2( char *buf ) {
+ sprintf( buf, "ror " );
+ do_addressing( buf );
+}
+
+static void rti( char *buf ) {
+ sprintf( buf, "rti" );
+ flags = DASMFLAG_STEP_OUT;
+}
+
+static void jsr2( char *buf ) {
+ sprintf( buf, "jsr " );
+ do_addressing( buf );
+ flags = DASMFLAG_STEP_OVER;
+}
+
+static void jmp2( char *buf ) {
+ sprintf( buf, "jmp " );
+ do_addressing( buf );
+}
+
+static void bsr( char *buf ) {
+ sprintf( buf, "bsr " );
+ do_relative( buf );
+ flags = DASMFLAG_STEP_OVER;
+}
+
+static void lbsr( char *buf ) {
+ sprintf( buf, "lbsr " );
+ do_relative_word( buf );
+ flags = DASMFLAG_STEP_OVER;
+}
+
+static void decbjnz( char *buf ) {
+ sprintf( buf, "decb,jnz " );
+ do_relative( buf );
+ flags = DASMFLAG_STEP_OVER;
+}
+
+static void decxjnz( char *buf ) {
+ sprintf( buf, "decx,jnz " );
+ do_relative( buf );
+ flags = DASMFLAG_STEP_OVER;
+}
+
+static void addd( char *buf ) {
+ int val = get_next_byte() << 8;
+
+ val |= get_next_byte();
+
+ sprintf( buf, "addd #$%04x", val );
+}
+
+static void subd( char *buf ) {
+ int val = get_next_byte() << 8;
+
+ val |= get_next_byte();
+
+ sprintf( buf, "subd #$%04x", val );
+}
+
+static void tsta( char *buf ) {
+ sprintf( buf, "tsta" );
+}
+
+static void tstb( char *buf ) {
+ sprintf( buf, "tstb" );
+}
+
+static void tst2( char *buf ) {
+ sprintf( buf, "tst " );
+ do_addressing( buf );
+}
+
+static void lsra( char *buf ) {
+ sprintf( buf, "lsra" );
+}
+
+static void lsrb( char *buf ) {
+ sprintf( buf, "lsrb" );
+}
+
+static void lsr2( char *buf ) {
+ sprintf( buf, "lsr " );
+ do_addressing( buf );
+}
+
+static void asra( char *buf ) {
+ sprintf( buf, "asra" );
+}
+
+static void asrb( char *buf ) {
+ sprintf( buf, "asrb" );
+}
+
+static void asr2( char *buf ) {
+ sprintf( buf, "asr " );
+ do_addressing( buf );
+}
+
+static void abx( char *buf ) {
+ sprintf( buf, "abx" );
+}
+
+static void sex( char *buf ) {
+ sprintf( buf, "sex" );
+}
+
+static void daa( char *buf ) {
+ sprintf( buf, "daa" );
+}
+
+static void mul( char *buf ) {
+ sprintf( buf, "mul" );
+}
+
+static void lmul( char *buf ) {
+ sprintf( buf, "lmul" );
+}
+
+static void divx( char *buf ) {
+ sprintf( buf, "div x,b" );
+}
+
+static void andcc( char *buf ) {
+ sprintf( buf, "andcc #$%02x", get_next_byte() );
+}
+
+static void orcc( char *buf ) {
+ sprintf( buf, "orcc #$%02x", get_next_byte() );
+}
+
+static void pushs( char *buf ) {
+ int mask = get_next_byte(), i;
+
+ sprintf( buf, "pushs " );
+
+ for ( i = 0; i < 8; i++ ) {
+ if ( ( mask >> i ) & 1 ) {
+ strcat( buf, stack_reg_s[i] );
+ mask &= ~( 1 << i );
+ if ( mask )
+ strcat( buf, "," );
+ else
+ return;
+ }
+ }
+}
+
+static void pushu( char *buf ) {
+ int mask = get_next_byte(), i;
+
+ sprintf( buf, "pushu " );
+
+ for ( i = 0; i < 8; i++ ) {
+ if ( ( mask >> i ) & 1 ) {
+ strcat( buf, stack_reg_u[i] );
+ mask &= ~( 1 << i );
+ if ( mask )
+ strcat( buf, "," );
+ else
+ return;
+ }
+ }
+}
+
+static void pulls( char *buf ) {
+ int mask = get_next_byte(), i;
+
+ sprintf( buf, "pulls " );
+
+ for ( i = 0; i < 8; i++ ) {
+ if ( ( mask >> i ) & 1 ) {
+ strcat( buf, stack_reg_s[i] );
+ if (i == 7)
+ flags = DASMFLAG_STEP_OUT;
+ mask &= ~( 1 << i );
+ if ( mask )
+ strcat( buf, "," );
+ else
+ return;
+ }
+ }
+}
+
+static void pullu( char *buf ) {
+ int mask = get_next_byte(), i;
+
+ sprintf( buf, "pullu " );
+
+ for ( i = 0; i < 8; i++ ) {
+ if ( ( mask >> i ) & 1 ) {
+ strcat( buf, stack_reg_s[i] );
+ mask &= ~( 1 << i );
+ if ( mask )
+ strcat( buf, "," );
+ else
+ return;
+ }
+ }
+}
+
+static void rola( char *buf ) {
+ sprintf( buf, "rola" );
+}
+
+static void rolb( char *buf ) {
+ sprintf( buf, "rolb" );
+}
+
+static void rol2( char *buf ) {
+ sprintf( buf, "rol " );
+ do_addressing( buf );
+}
+
+static void bmove( char *buf ) {
+ sprintf( buf, "bmove y,x,u" );
+}
+
+static void move( char *buf ) {
+ sprintf( buf, "move y,x,u" );
+}
+
+static void bset( char *buf ) {
+ sprintf( buf, "bset a,x,u" );
+}
+
+static void bset2( char *buf ) {
+ sprintf( buf, "bset d,x,u" );
+}
+
+static void nop( char *buf ) {
+ sprintf( buf, "nop" );
+}
+
+static void tfr( char *buf ) {
+ int mask = get_next_byte();
+
+ sprintf( buf, "tfr " );
+
+ strcat( buf, tfrexg_reg[ mask & 0x07 ] );
+ strcat( buf, "," );
+ strcat( buf, tfrexg_reg[ ( mask >> 4 ) & 0x07 ] );
+}
+
+static void exg( char *buf ) {
+ int mask = get_next_byte();
+
+ sprintf( buf, "exg " );
+
+ strcat( buf, tfrexg_reg[ mask & 0x07 ] );
+ strcat( buf, "," );
+ strcat( buf, tfrexg_reg[ ( mask >> 4 ) & 0x07 ] );
+}
+
+static void lsrd( char *buf ) {
+ sprintf( buf, "lsrd #$%02x", get_next_byte() );
+}
+
+static void lsrd2( char *buf ) {
+ sprintf( buf, "lsrd " );
+ do_addressing( buf );
+}
+
+static void rord( char *buf ) {
+ sprintf( buf, "rord #$%02x", get_next_byte() );
+}
+
+static void rord2( char *buf ) {
+ sprintf( buf, "rord " );
+ do_addressing( buf );
+}
+
+static void asrd( char *buf ) {
+ sprintf( buf, "asrd #$%02x", get_next_byte() );
+}
+
+static void asrd2( char *buf ) {
+ sprintf( buf, "asrd " );
+ do_addressing( buf );
+}
+
+static void asld( char *buf ) {
+ sprintf( buf, "asld #$%02x", get_next_byte() );
+}
+
+static void asld2( char *buf ) {
+ sprintf( buf, "asld " );
+ do_addressing( buf );
+}
+
+static void rold( char *buf ) {
+ sprintf( buf, "rold #$%02x", get_next_byte() );
+}
+
+static void rold2( char *buf ) {
+ sprintf( buf, "rold " );
+ do_addressing( buf );
+}
+
+static void lsrw( char *buf ) {
+ sprintf( buf, "lsrw " );
+ do_addressing( buf );
+}
+
+static void rorw( char *buf ) {
+ sprintf( buf, "lsrw " );
+ do_addressing( buf );
+}
+
+static void asrw( char *buf ) {
+ sprintf( buf, "asrw " );
+ do_addressing( buf );
+}
+
+static void aslw( char *buf ) {
+ sprintf( buf, "aslw " );
+ do_addressing( buf );
+}
+
+static void rolw( char *buf ) {
+ sprintf( buf, "rolw " );
+ do_addressing( buf );
+}
+
+static void absa( char *buf ) {
+ sprintf( buf, "absa" );
+}
+
+static void absb( char *buf ) {
+ sprintf( buf, "absb" );
+}
+
+static void absd( char *buf ) {
+ sprintf( buf, "absd" );
+}
+
+/*********************************************************************************
+
+ Opcode Table
+
+*********************************************************************************/
+
+typedef struct {
+ void (*decode)( char *buf );
+ int confirmed;
+} konami_opcode_def;
+
+static const konami_opcode_def op_table[256] = {
+ /* 00 */ { illegal, 0 },
+ /* 01 */ { illegal, 0 },
+ /* 02 */ { illegal, 0 },
+ /* 03 */ { illegal, 0 },
+ /* 04 */ { illegal, 0 },
+ /* 05 */ { illegal, 0 },
+ /* 06 */ { illegal, 0 },
+ /* 07 */ { illegal, 0 },
+ /* 08 */ { leax, 1 },
+ /* 09 */ { leay, 1 },
+ /* 0a */ { leau, 1 },
+ /* 0b */ { leas, 0 },
+ /* 0c */ { pushs, 1 },
+ /* 0d */ { pushu, 0 },
+ /* 0e */ { pulls, 1 },
+ /* 0f */ { pullu, 0 },
+
+ /* 10 */ { lda, 1 },
+ /* 11 */ { ldb, 1 },
+ /* 12 */ { lda2, 1 },
+ /* 13 */ { ldb2, 1 },
+ /* 14 */ { adda, 1 },
+ /* 15 */ { addb, 1 },
+ /* 16 */ { adda2, 1 },
+ /* 17 */ { addb2, 1 },
+ /* 18 */ { adca, 1 },
+ /* 19 */ { adcb, 1 },
+ /* 1a */ { adca2, 1 },
+ /* 1b */ { adcb2, 1 },
+ /* 1c */ { suba, 1 },
+ /* 1d */ { subb, 1 },
+ /* 1e */ { suba2, 1 },
+ /* 1f */ { subb2, 1 },
+
+ /* 20 */ { sbca, 0 },
+ /* 21 */ { sbcb, 0 },
+ /* 22 */ { sbca2, 0 },
+ /* 23 */ { sbcb2, 0 },
+ /* 24 */ { anda, 1 },
+ /* 25 */ { andb, 1 },
+ /* 26 */ { anda2, 1 },
+ /* 27 */ { andb2, 1 },
+ /* 28 */ { bita, 0 },
+ /* 29 */ { bitb, 0 },
+ /* 2a */ { bita2, 0 },
+ /* 2b */ { bitb2, 0 },
+ /* 2c */ { eora, 0 },
+ /* 2d */ { eorb, 0 },
+ /* 2e */ { eora2, 0 },
+ /* 2f */ { eorb2, 0 },
+
+ /* 30 */ { ora, 1 },
+ /* 31 */ { orb, 1 },
+ /* 32 */ { ora2, 1 },
+ /* 33 */ { orb2, 1 },
+ /* 34 */ { cmpa, 1 },
+ /* 35 */ { cmpb, 1 },
+ /* 36 */ { cmpa2, 1 },
+ /* 37 */ { cmpb2, 1 },
+ /* 38 */ { setlines, 0 },
+ /* 39 */ { setlines2, 0 },
+ /* 3a */ { sta2, 1 },
+ /* 3b */ { stb2, 1 },
+ /* 3c */ { andcc, 1 },
+ /* 3d */ { orcc, 0 },
+ /* 3e */ { exg, 0 },
+ /* 3f */ { tfr, 0 },
+
+ /* 40 */ { ldd, 1 },
+ /* 41 */ { ldd2, 1 },
+ /* 42 */ { ldx, 1 },
+ /* 43 */ { ldx2, 1 },
+ /* 44 */ { ldy, 1 },
+ /* 45 */ { ldy2, 1 },
+ /* 46 */ { ldu, 1 },
+ /* 47 */ { ldu2, 1 },
+ /* 48 */ { lds, 1 },
+ /* 49 */ { lds2, 1 },
+ /* 4a */ { cmpd, 1 },
+ /* 4b */ { cmpd2, 1 },
+ /* 4c */ { cmpx, 1 },
+ /* 4d */ { cmpx2, 1 },
+ /* 4e */ { cmpy, 1 },
+ /* 4f */ { cmpy2, 1 },
+
+ /* 50 */ { cmpu, 1 },
+ /* 51 */ { cmpu2, 1 },
+ /* 52 */ { cmps, 1 },
+ /* 53 */ { cmps2, 1 },
+ /* 54 */ { addd, 0 },
+ /* 55 */ { addd2, 0 },
+ /* 56 */ { subd, 1 },
+ /* 57 */ { subd2, 0 },
+ /* 58 */ { std2, 1 },
+ /* 59 */ { stx2, 1 },
+ /* 5a */ { sty2, 1 },
+ /* 5b */ { stu2, 1 },
+ /* 5c */ { sts2, 1 },
+ /* 5d */ { illegal, 0 },
+ /* 5e */ { illegal, 0 },
+ /* 5f */ { illegal, 0 },
+
+ /* 60 */ { bra, 1 },
+ /* 61 */ { bhi, 1 },
+ /* 62 */ { bcc, 1 },
+ /* 63 */ { bne, 1 },
+ /* 64 */ { bvc, 1 },
+ /* 65 */ { bpl, 1 },
+ /* 66 */ { bge, 1 },
+ /* 67 */ { bgt, 1 },
+ /* 68 */ { lbra, 1 },
+ /* 69 */ { lbhi, 1 },
+ /* 6a */ { lbcc, 1 },
+ /* 6b */ { lbne, 1 },
+ /* 6c */ { lbvc, 1 },
+ /* 6d */ { lbpl, 1 },
+ /* 6e */ { lbge, 1 },
+ /* 6f */ { lbgt, 1 },
+
+ /* 70 */ { brn, 1 },
+ /* 71 */ { bls, 1 },
+ /* 72 */ { bcs, 1 },
+ /* 73 */ { beq, 1 },
+ /* 74 */ { bvs, 1 },
+ /* 75 */ { bmi, 1 },
+ /* 76 */ { blt, 1 },
+ /* 77 */ { ble, 1 },
+ /* 78 */ { lbrn, 1 },
+ /* 79 */ { lbls, 1 },
+ /* 7a */ { lbcs, 1 },
+ /* 7b */ { lbeq, 1 },
+ /* 7c */ { lbvs, 1 },
+ /* 7d */ { lbmi, 1 },
+ /* 7e */ { lblt, 1 },
+ /* 7f */ { lble, 1 },
+
+ /* 80 */ { clra, 1 },
+ /* 81 */ { clrb, 1 },
+ /* 82 */ { clr2, 1 },
+ /* 83 */ { coma, 1 },
+ /* 84 */ { comb, 0 },
+ /* 85 */ { com2, 0 },
+ /* 86 */ { nega, 0 },
+ /* 87 */ { negb, 0 },
+ /* 88 */ { neg2, 0 },
+ /* 89 */ { inca, 1 },
+ /* 8a */ { incb, 1 },
+ /* 8b */ { inc2, 1 },
+ /* 8c */ { deca, 1 },
+ /* 8d */ { decb, 1 },
+ /* 8e */ { dec2, 1 },
+ /* 8f */ { rts, 1 },
+
+ /* 90 */ { tsta, 0 },
+ /* 91 */ { tstb, 0 },
+ /* 92 */ { tst2, 0 },
+ /* 93 */ { lsra, 1 },
+ /* 94 */ { lsrb, 1 },
+ /* 95 */ { lsr2, 0 },
+ /* 96 */ { rora, 0 },
+ /* 97 */ { rorb, 0 },
+ /* 98 */ { ror2, 0 },
+ /* 99 */ { asra, 0 },
+ /* 9a */ { asrb, 0 },
+ /* 9b */ { asr2, 0 },
+ /* 9c */ { asla, 1 },
+ /* 9d */ { aslb, 1 },
+ /* 9e */ { asl2, 0 },
+ /* 9f */ { rti, 1 },
+
+ /* a0 */ { rola, 1 },
+ /* a1 */ { rolb, 0 },
+ /* a2 */ { rol2, 0 },
+ /* a3 */ { lsrw, 0 },
+ /* a4 */ { rorw, 0 },
+ /* a5 */ { asrw, 0 },
+ /* a6 */ { aslw, 0 },
+ /* a7 */ { rolw, 0 },
+ /* a8 */ { jmp2, 1 },
+ /* a9 */ { jsr2, 1 },
+ /* aa */ { bsr, 1 },
+ /* ab */ { lbsr, 1 },
+ /* ac */ { decbjnz, 0 },
+ /* ad */ { decxjnz, 0 },
+ /* ae */ { nop, 0 },
+ /* af */ { illegal, 0 },
+
+ /* b0 */ { abx, 0 },
+ /* b1 */ { daa, 0 },
+ /* b2 */ { sex, 0 },
+ /* b3 */ { mul, 1 },
+ /* b4 */ { lmul, 0 },
+ /* b5 */ { divx, 0 },
+ /* b6 */ { bmove, 1 },
+ /* b7 */ { move, 0 },
+ /* b8 */ { lsrd, 0 },
+ /* b9 */ { lsrd2, 0 },
+ /* ba */ { rord, 0 },
+ /* bb */ { rord2, 0 },
+ /* bc */ { asrd, 0 },
+ /* bd */ { asrd2, 0 },
+ /* be */ { asld, 0 },
+ /* bf */ { asld2, 0 },
+
+ /* c0 */ { rold, 0 },
+ /* c1 */ { rold2, 0 },
+ /* c2 */ { clrd, 1 },
+ /* c3 */ { clrw, 0 },
+ /* c4 */ { negd, 0 },
+ /* c5 */ { negw, 0 },
+ /* c6 */ { incd, 0 },
+ /* c7 */ { incw, 0 },
+ /* c8 */ { decd, 0 },
+ /* c9 */ { decw, 0 },
+ /* ca */ { tstd, 0 },
+ /* cb */ { tstw, 0 },
+ /* cc */ { absa, 0 },
+ /* cd */ { absb, 0 },
+ /* ce */ { absd, 0 },
+ /* cf */ { bset, 0 },
+
+ /* d0 */ { bset2, 0 },
+ /* d1 */ { illegal, 0 },
+ /* d2 */ { illegal, 0 },
+ /* d3 */ { illegal, 0 },
+ /* d4 */ { illegal, 0 },
+ /* d5 */ { illegal, 0 },
+ /* d6 */ { illegal, 0 },
+ /* d7 */ { illegal, 0 },
+ /* d8 */ { illegal, 0 },
+ /* d9 */ { illegal, 0 },
+ /* da */ { illegal, 0 },
+ /* db */ { illegal, 0 },
+ /* dc */ { illegal, 0 },
+ /* dd */ { illegal, 0 },
+ /* de */ { illegal, 0 },
+ /* df */ { illegal, 0 },
+
+ /* e0 */ { illegal, 0 },
+ /* e1 */ { illegal, 0 },
+ /* e2 */ { illegal, 0 },
+ /* e3 */ { illegal, 0 },
+ /* e4 */ { illegal, 0 },
+ /* e5 */ { illegal, 0 },
+ /* e6 */ { illegal, 0 },
+ /* e7 */ { illegal, 0 },
+ /* e8 */ { illegal, 0 },
+ /* e9 */ { illegal, 0 },
+ /* ea */ { illegal, 0 },
+ /* eb */ { illegal, 0 },
+ /* ec */ { illegal, 0 },
+ /* ed */ { illegal, 0 },
+ /* ee */ { illegal, 0 },
+ /* ef */ { illegal, 0 },
+
+ /* f0 */ { illegal, 0 },
+ /* f1 */ { illegal, 0 },
+ /* f2 */ { illegal, 0 },
+ /* f3 */ { illegal, 0 },
+ /* f4 */ { illegal, 0 },
+ /* f5 */ { illegal, 0 },
+ /* f6 */ { illegal, 0 },
+ /* f7 */ { illegal, 0 },
+ /* f8 */ { illegal, 0 },
+ /* f9 */ { illegal, 0 },
+ /* fa */ { illegal, 0 },
+ /* fb */ { illegal, 0 },
+ /* fc */ { illegal, 0 },
+ /* fd */ { illegal, 0 },
+ /* fe */ { illegal, 0 },
+ /* ff */ { illegal, 0 }
+};
+
+CPU_DISASSEMBLE( konami )
+{
+ buffer[0] = '\0';
+
+ local_pc = pc;
+ byte_count = 1;
+ opram_ptr = opram;
+ flags = 0;
+
+ (op_table[*oprom].decode)( buffer );
+
+ return byte_count | flags | DASMFLAG_SUPPORTED;
+}
diff --git a/trunk/src/emu/cpu/konami/konami.c b/trunk/src/emu/cpu/konami/konami.c
new file mode 100644
index 00000000000..3fe57dd150d
--- /dev/null
+++ b/trunk/src/emu/cpu/konami/konami.c
@@ -0,0 +1,632 @@
+/*** konami: Portable Konami cpu emulator ******************************************
+
+ Copyright Nicola Salmoria and the MAME Team
+
+ Based on M6809 cpu core copyright John Butler
+
+ References:
+
+ 6809 Simulator V09, By L.C. Benschop, Eidnhoven The Netherlands.
+
+ m6809: Portable 6809 emulator, DS (6809 code in MAME, derived from
+ the 6809 Simulator V09)
+
+ 6809 Microcomputer Programming & Interfacing with Experiments"
+ by Andrew C. Staugaard, Jr.; Howard W. Sams & Co., Inc.
+
+ System dependencies: UINT16 must be 16 bit unsigned int
+ UINT8 must be 8 bit unsigned int
+ UINT32 must be more than 16 bits
+ arrays up to 65536 bytes must be supported
+ machine must be twos complement
+
+ History:
+991022 HJB:
+ Tried to improve speed: Using bit7 of cycles1 as flag for multi
+ byte opcodes is gone, those opcodes now instead go through opcode2().
+ Inlined fetch_effective_address() into that function as well.
+ Got rid of the slow/fast flags for stack (S and U) memory accesses.
+ Minor changes to use 32 bit values as arguments to memory functions
+ and added defines for that purpose (e.g. X = 16bit XD = 32bit).
+
+990720 EHC:
+ Created this file
+
+*****************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "konami.h"
+
+#define VERBOSE 0
+
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+/* Konami Registers */
+typedef struct _konami_state konami_state;
+struct _konami_state
+{
+ PAIR pc; /* Program counter */
+ PAIR ppc; /* Previous program counter */
+ PAIR d; /* Accumulator a and b */
+ PAIR dp; /* Direct Page register (page in MSB) */
+ PAIR u, s; /* Stack pointers */
+ PAIR x, y; /* Index registers */
+ PAIR ea;
+ UINT8 cc;
+ UINT8 ireg;
+ UINT8 irq_state[2];
+ device_irq_callback irq_callback;
+ UINT8 int_state; /* SYNC and CWAI flags */
+ UINT8 nmi_state;
+ UINT8 nmi_pending;
+ int icount;
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ konami_set_lines_func setlines_callback;
+};
+
+INLINE konami_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == KONAMI);
+ return (konami_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+/* flag bits in the cc register */
+#define CC_C 0x01 /* Carry */
+#define CC_V 0x02 /* Overflow */
+#define CC_Z 0x04 /* Zero */
+#define CC_N 0x08 /* Negative */
+#define CC_II 0x10 /* Inhibit IRQ */
+#define CC_H 0x20 /* Half (auxiliary) carry */
+#define CC_IF 0x40 /* Inhibit FIRQ */
+#define CC_E 0x80 /* entire state pushed */
+
+/* Konami registers */
+#define pPPC cpustate->ppc
+#define pPC cpustate->pc
+#define pU cpustate->u
+#define pS cpustate->s
+#define pX cpustate->x
+#define pY cpustate->y
+#define pD cpustate->d
+
+#define PPC cpustate->ppc.w.l
+#define PC cpustate->pc.w.l
+#define PCD cpustate->pc.d
+#define U cpustate->u.w.l
+#define UD cpustate->u.d
+#define S cpustate->s.w.l
+#define SD cpustate->s.d
+#define X cpustate->x.w.l
+#define XD cpustate->x.d
+#define Y cpustate->y.w.l
+#define YD cpustate->y.d
+#define D cpustate->d.w.l
+#define A cpustate->d.b.h
+#define B cpustate->d.b.l
+#define DP cpustate->dp.b.h
+#define DPD cpustate->dp.d
+#define CC cpustate->cc
+
+#define EAB cpustate->ea.b.l
+#define EA cpustate->ea.w.l
+#define EAD cpustate->ea.d
+
+#define KONAMI_CWAI 8 /* set when CWAI is waiting for an interrupt */
+#define KONAMI_SYNC 16 /* set when SYNC is waiting for an interrupt */
+#define KONAMI_LDS 32 /* set when LDS occurred at least once */
+
+#define RM(cs,Addr) (cs)->program->read_byte(Addr)
+#define WM(cs,Addr,Value) (cs)->program->write_byte(Addr,Value)
+#define ROP(cs,Addr) (cs)->direct->read_decrypted_byte(Addr)
+#define ROP_ARG(cs,Addr) (cs)->direct->read_raw_byte(Addr)
+
+#define SIGNED(a) (UINT16)(INT16)(INT8)(a)
+
+/* macros to access memory */
+#define IMMBYTE(cs,b) { b = ROP_ARG(cs,PCD); PC++; }
+#define IMMWORD(cs,w) { w.d = (ROP_ARG(cs,PCD)<<8) | ROP_ARG(cs,PCD+1); PC += 2; }
+
+#define PUSHBYTE(cs,b) --S; WM(cs,SD,b)
+#define PUSHWORD(cs,w) --S; WM(cs,SD,w.b.l); --S; WM(cs,SD,w.b.h)
+#define PULLBYTE(cs,b) b=RM(cs,SD); S++
+#define PULLWORD(cs,w) w=RM(cs,SD)<<8; S++; w|=RM(cs,SD); S++
+
+#define PSHUBYTE(cs,b) --U; WM(cs,UD,b);
+#define PSHUWORD(cs,w) --U; WM(cs,UD,w.b.l); --U; WM(cs,UD,w.b.h)
+#define PULUBYTE(cs,b) b=RM(cs,UD); U++
+#define PULUWORD(cs,w) w=RM(cs,UD)<<8; U++; w|=RM(cs,UD); U++
+
+#define CLR_HNZVC CC&=~(CC_H|CC_N|CC_Z|CC_V|CC_C)
+#define CLR_NZV CC&=~(CC_N|CC_Z|CC_V)
+#define CLR_NZ CC&=~(CC_N|CC_Z)
+#define CLR_HNZC CC&=~(CC_H|CC_N|CC_Z|CC_C)
+#define CLR_NZVC CC&=~(CC_N|CC_Z|CC_V|CC_C)
+#define CLR_Z CC&=~(CC_Z)
+#define CLR_NZC CC&=~(CC_N|CC_Z|CC_C)
+#define CLR_ZC CC&=~(CC_Z|CC_C)
+
+/* macros for CC -- CC bits affected should be reset before calling */
+#define SET_Z(a) if(!a)SEZ
+#define SET_Z8(a) SET_Z((UINT8)a)
+#define SET_Z16(a) SET_Z((UINT16)a)
+#define SET_N8(a) CC|=((a&0x80)>>4)
+#define SET_N16(a) CC|=((a&0x8000)>>12)
+#define SET_H(a,b,r) CC|=(((a^b^r)&0x10)<<1)
+#define SET_C8(a) CC|=((a&0x100)>>8)
+#define SET_C16(a) CC|=((a&0x10000)>>16)
+#define SET_V8(a,b,r) CC|=(((a^b^r^(r>>1))&0x80)>>6)
+#define SET_V16(a,b,r) CC|=(((a^b^r^(r>>1))&0x8000)>>14)
+
+static const UINT8 flags8i[256]= /* increment */
+{
+CC_Z,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+CC_N|CC_V,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N
+};
+static const UINT8 flags8d[256]= /* decrement */
+{
+CC_Z,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,CC_V,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N
+};
+#define SET_FLAGS8I(a) {CC|=flags8i[(a)&0xff];}
+#define SET_FLAGS8D(a) {CC|=flags8d[(a)&0xff];}
+
+/* combos */
+#define SET_NZ8(a) {SET_N8(a);SET_Z(a);}
+#define SET_NZ16(a) {SET_N16(a);SET_Z(a);}
+#define SET_FLAGS8(a,b,r) {SET_N8(r);SET_Z8(r);SET_V8(a,b,r);SET_C8(r);}
+#define SET_FLAGS16(a,b,r) {SET_N16(r);SET_Z16(r);SET_V16(a,b,r);SET_C16(r);}
+
+/* macros for addressing modes (postbytes have their own code) */
+#define DIRECT(cs) EAD = DPD; IMMBYTE(cs,EAB)
+#define IMM8(cs) EAD = PCD; PC++
+#define IMM16(cs) EAD = PCD; PC+=2
+#define EXTENDED(cs) IMMWORD(cs,(cs)->ea)
+
+/* macros to set status flags */
+#if defined(SEC)
+#undef SEC
+#endif
+#define SEC CC|=CC_C
+#define CLC CC&=~CC_C
+#define SEZ CC|=CC_Z
+#define CLZ CC&=~CC_Z
+#define SEN CC|=CC_N
+#define CLN CC&=~CC_N
+#define SEV CC|=CC_V
+#define CLV CC&=~CC_V
+#define SEH CC|=CC_H
+#define CLH CC&=~CC_H
+
+/* macros for convenience */
+#define DIRBYTE(cs,b) DIRECT(cs); b=RM(cs,EAD)
+#define DIRWORD(cs,w) DIRECT(cs); w.d=RM16(cs,EAD)
+#define EXTBYTE(cs,b) EXTENDED(cs); b=RM(cs,EAD)
+#define EXTWORD(cs,w) EXTENDED(cs); w.d=RM16(cs,EAD)
+
+/* macros for branch instructions */
+#define BRANCH(cs,f) { \
+ UINT8 t; \
+ IMMBYTE(cs,t); \
+ if( f ) \
+ { \
+ PC += SIGNED(t); \
+ } \
+}
+
+#define LBRANCH(cs,f) { \
+ PAIR t; \
+ IMMWORD(cs,t); \
+ if( f ) \
+ { \
+ cpustate->icount -= 1; \
+ PC += t.w.l; \
+ } \
+}
+
+#define NXORV ((CC&CC_N)^((CC&CC_V)<<2))
+
+/* macros for setting/getting registers in TFR/EXG instructions */
+#define GETREG(val,reg) \
+ switch(reg) { \
+ case 0: val = A; break; \
+ case 1: val = B; break; \
+ case 2: val = X; break; \
+ case 3: val = Y; break; \
+ case 4: val = S; break; /* ? */ \
+ case 5: val = U; break; \
+ default: val = 0xff; logerror("Unknown TFR/EXG idx at PC:%04x\n", PC ); break; \
+ }
+
+#define SETREG(val,reg) \
+ switch(reg) { \
+ case 0: A = val; break; \
+ case 1: B = val; break; \
+ case 2: X = val; break; \
+ case 3: Y = val; break; \
+ case 4: S = val; break; /* ? */ \
+ case 5: U = val; break; \
+ default: logerror("Unknown TFR/EXG idx at PC:%04x\n", PC ); break; \
+ }
+
+/* opcode timings */
+static const UINT8 cycles1[] =
+{
+ /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
+ /*0*/ 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 4, 5, 5, 5, 5,
+ /*1*/ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ /*2*/ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ /*3*/ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 7, 6,
+ /*4*/ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 3, 3, 4, 4,
+ /*5*/ 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 1, 1, 1,
+ /*6*/ 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 5, 5, 5, 5, 5, 5,
+ /*7*/ 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 5, 5, 5, 5, 5, 5,
+ /*8*/ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5,
+ /*9*/ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6,
+ /*A*/ 2, 2, 2, 4, 4, 4, 4, 4, 2, 2, 2, 2, 3, 3, 2, 1,
+ /*B*/ 3, 2, 2,11,22,11, 2, 4, 3, 3, 3, 3, 3, 3, 3, 3,
+ /*C*/ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 3, 2,
+ /*D*/ 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ /*E*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ /*F*/ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+};
+
+INLINE UINT32 RM16( konami_state *cpustate, UINT32 Addr )
+{
+ UINT32 result = RM(cpustate, Addr) << 8;
+ return result | RM(cpustate, (Addr+1)&0xffff);
+}
+
+INLINE void WM16( konami_state *cpustate, UINT32 Addr, PAIR *p )
+{
+ WM(cpustate, Addr, p->b.h );
+ WM(cpustate, (Addr+1)&0xffff, p->b.l );
+}
+
+
+static void check_irq_lines(konami_state *cpustate)
+{
+ if (cpustate->nmi_pending && (cpustate->int_state & KONAMI_LDS))
+ {
+ cpustate->nmi_pending = FALSE;
+
+ /* state already saved by CWAI? */
+ if (cpustate->int_state & KONAMI_CWAI)
+ {
+ cpustate->int_state &= ~KONAMI_CWAI;
+ cpustate->icount -= 7;
+ }
+ else
+ {
+ CC |= CC_E; /* save entire state */
+ PUSHWORD(cpustate, pPC);
+ PUSHWORD(cpustate, pU);
+ PUSHWORD(cpustate, pY);
+ PUSHWORD(cpustate, pX);
+ PUSHBYTE(cpustate, DP);
+ PUSHBYTE(cpustate, B);
+ PUSHBYTE(cpustate, A);
+ PUSHBYTE(cpustate, CC);
+ cpustate->icount -= 19;
+ }
+ CC |= CC_IF | CC_II; /* inhibit FIRQ and IRQ */
+ PCD = RM16(cpustate, 0xfffc);
+ (void)(*cpustate->irq_callback)(cpustate->device, INPUT_LINE_NMI);
+ }
+
+ else if (cpustate->irq_state[KONAMI_FIRQ_LINE] !=CLEAR_LINE && !(CC & CC_IF))
+ {
+ /* fast IRQ */
+ /* state already saved by CWAI? */
+ if (cpustate->int_state & KONAMI_CWAI)
+ {
+ cpustate->int_state &= ~KONAMI_CWAI; /* clear CWAI */
+ cpustate->icount -= 7;
+ }
+ else
+ {
+ CC &= ~CC_E; /* save 'short' state */
+ PUSHWORD(cpustate, pPC);
+ PUSHBYTE(cpustate, CC);
+ cpustate->icount -= 10;
+ }
+ CC |= CC_IF | CC_II; /* inhibit FIRQ and IRQ */
+ PCD = RM16(cpustate, 0xfff6);
+ (void)(*cpustate->irq_callback)(cpustate->device, KONAMI_FIRQ_LINE);
+ }
+
+ else if (cpustate->irq_state[KONAMI_IRQ_LINE] != CLEAR_LINE && !(CC & CC_II))
+ {
+ /* standard IRQ */
+ /* state already saved by CWAI? */
+ if (cpustate->int_state & KONAMI_CWAI)
+ {
+ cpustate->int_state &= ~KONAMI_CWAI; /* clear CWAI flag */
+ cpustate->icount -= 7;
+ }
+ else
+ {
+ CC |= CC_E; /* save entire state */
+ PUSHWORD(cpustate, pPC);
+ PUSHWORD(cpustate, pU);
+ PUSHWORD(cpustate, pY);
+ PUSHWORD(cpustate, pX);
+ PUSHBYTE(cpustate, DP);
+ PUSHBYTE(cpustate, B);
+ PUSHBYTE(cpustate, A);
+ PUSHBYTE(cpustate, CC);
+ cpustate->icount -= 19;
+ }
+ CC |= CC_II; /* inhibit IRQ */
+ PCD = RM16(cpustate, 0xfff8);
+ (void)(*cpustate->irq_callback)(cpustate->device, KONAMI_IRQ_LINE);
+ }
+}
+
+
+/****************************************************************************/
+/* Reset registers to their initial values */
+/****************************************************************************/
+static CPU_INIT( konami )
+{
+ konami_state *cpustate = get_safe_token(device);
+
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+
+ device->save_item(NAME(PC));
+ device->save_item(NAME(U));
+ device->save_item(NAME(S));
+ device->save_item(NAME(X));
+ device->save_item(NAME(Y));
+ device->save_item(NAME(D));
+ device->save_item(NAME(DP));
+ device->save_item(NAME(CC));
+ device->save_item(NAME(cpustate->int_state));
+ device->save_item(NAME(cpustate->nmi_state));
+ device->save_item(NAME(cpustate->nmi_pending));
+ device->save_item(NAME(cpustate->irq_state[0]));
+ device->save_item(NAME(cpustate->irq_state[1]));
+}
+
+static CPU_RESET( konami )
+{
+ konami_state *cpustate = get_safe_token(device);
+
+ cpustate->int_state = 0;
+ cpustate->nmi_state = CLEAR_LINE;
+ cpustate->nmi_pending = FALSE;
+ cpustate->irq_state[0] = CLEAR_LINE;
+ cpustate->irq_state[1] = CLEAR_LINE;
+
+ DPD = 0; /* Reset direct page register */
+
+ CC |= CC_II; /* IRQ disabled */
+ CC |= CC_IF; /* FIRQ disabled */
+
+ PCD = RM16(cpustate, 0xfffe);
+}
+
+static CPU_EXIT( konami )
+{
+}
+
+/* Generate interrupts */
+/****************************************************************************
+ * Set IRQ line state
+ ****************************************************************************/
+static void set_irq_line(konami_state *cpustate, int irqline, int state)
+{
+ if (state != CLEAR_LINE)
+ cpustate->int_state &= ~KONAMI_SYNC;
+
+ if (irqline == INPUT_LINE_NMI)
+ {
+ if (cpustate->nmi_state == CLEAR_LINE && state != CLEAR_LINE)
+ cpustate->nmi_pending = TRUE;
+ cpustate->nmi_state = state;
+ }
+ else if (irqline < ARRAY_LENGTH(cpustate->irq_state))
+ cpustate->irq_state[irqline] = state;
+}
+
+/* includes the static function prototypes and the master opcode table */
+#include "konamtbl.c"
+
+/* includes the actual opcode implementations */
+#include "konamops.c"
+
+/* execute instructions on this CPU until icount expires */
+static CPU_EXECUTE( konami )
+{
+ konami_state *cpustate = get_safe_token(device);
+
+ check_irq_lines(cpustate);
+
+ if( cpustate->int_state & (KONAMI_CWAI | KONAMI_SYNC) )
+ {
+ cpustate->icount = 0;
+ }
+ else
+ {
+ do
+ {
+ UINT8 ireg;
+
+ pPPC = pPC;
+
+ debugger_instruction_hook(device, PCD);
+
+ cpustate->ireg = ireg = ROP(cpustate, PCD);
+ PC++;
+
+ (*konami_main[ireg])(cpustate);
+
+ cpustate->icount -= cycles1[ireg];
+
+ } while( cpustate->icount > 0 );
+ }
+}
+
+
+void konami_configure_set_lines(device_t *device, konami_set_lines_func func)
+{
+ konami_state *cpustate = get_safe_token(device);
+ cpustate->setlines_callback = func;
+}
+
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( konami )
+{
+ konami_state *cpustate = get_safe_token(device);
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + KONAMI_IRQ_LINE: set_irq_line(cpustate, KONAMI_IRQ_LINE, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + KONAMI_FIRQ_LINE:set_irq_line(cpustate, KONAMI_FIRQ_LINE, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: set_irq_line(cpustate, INPUT_LINE_NMI, info->i); break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + KONAMI_PC: PC = info->i; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + KONAMI_S: S = info->i; break;
+ case CPUINFO_INT_REGISTER + KONAMI_CC: CC = info->i; break;
+ case CPUINFO_INT_REGISTER + KONAMI_U: U = info->i; break;
+ case CPUINFO_INT_REGISTER + KONAMI_A: A = info->i; break;
+ case CPUINFO_INT_REGISTER + KONAMI_B: B = info->i; break;
+ case CPUINFO_INT_REGISTER + KONAMI_X: X = info->i; break;
+ case CPUINFO_INT_REGISTER + KONAMI_Y: Y = info->i; break;
+ case CPUINFO_INT_REGISTER + KONAMI_DP: DP = info->i; break;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+CPU_GET_INFO( konami )
+{
+ konami_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(konami_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 2; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 13; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_INPUT_STATE + KONAMI_IRQ_LINE: info->i = cpustate->irq_state[KONAMI_IRQ_LINE]; break;
+ case CPUINFO_INT_INPUT_STATE + KONAMI_FIRQ_LINE:info->i = cpustate->irq_state[KONAMI_FIRQ_LINE]; break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: info->i = cpustate->nmi_state; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = PPC; break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + KONAMI_PC: info->i = PC; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + KONAMI_S: info->i = S; break;
+ case CPUINFO_INT_REGISTER + KONAMI_CC: info->i = CC; break;
+ case CPUINFO_INT_REGISTER + KONAMI_U: info->i = U; break;
+ case CPUINFO_INT_REGISTER + KONAMI_A: info->i = A; break;
+ case CPUINFO_INT_REGISTER + KONAMI_B: info->i = B; break;
+ case CPUINFO_INT_REGISTER + KONAMI_X: info->i = X; break;
+ case CPUINFO_INT_REGISTER + KONAMI_Y: info->i = Y; break;
+ case CPUINFO_INT_REGISTER + KONAMI_DP: info->i = DP; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(konami); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(konami); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(konami); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(konami); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(konami); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(konami);break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "KONAMI"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "KONAMI 5000x"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Nicola Salmoria and the MAME Team"); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c%c%c%c%c%c%c",
+ cpustate->cc & 0x80 ? 'E':'.',
+ cpustate->cc & 0x40 ? 'F':'.',
+ cpustate->cc & 0x20 ? 'H':'.',
+ cpustate->cc & 0x10 ? 'I':'.',
+ cpustate->cc & 0x08 ? 'N':'.',
+ cpustate->cc & 0x04 ? 'Z':'.',
+ cpustate->cc & 0x02 ? 'V':'.',
+ cpustate->cc & 0x01 ? 'C':'.');
+ break;
+
+ case CPUINFO_STR_REGISTER + KONAMI_PC: sprintf(info->s, "PC:%04X", cpustate->pc.w.l); break;
+ case CPUINFO_STR_REGISTER + KONAMI_S: sprintf(info->s, "S:%04X", cpustate->s.w.l); break;
+ case CPUINFO_STR_REGISTER + KONAMI_CC: sprintf(info->s, "CC:%02X", cpustate->cc); break;
+ case CPUINFO_STR_REGISTER + KONAMI_U: sprintf(info->s, "U:%04X", cpustate->u.w.l); break;
+ case CPUINFO_STR_REGISTER + KONAMI_A: sprintf(info->s, "A:%02X", cpustate->d.b.h); break;
+ case CPUINFO_STR_REGISTER + KONAMI_B: sprintf(info->s, "B:%02X", cpustate->d.b.l); break;
+ case CPUINFO_STR_REGISTER + KONAMI_X: sprintf(info->s, "X:%04X", cpustate->x.w.l); break;
+ case CPUINFO_STR_REGISTER + KONAMI_Y: sprintf(info->s, "Y:%04X", cpustate->y.w.l); break;
+ case CPUINFO_STR_REGISTER + KONAMI_DP: sprintf(info->s, "DP:%02X", cpustate->dp.b.h); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(KONAMI, konami);
diff --git a/trunk/src/emu/cpu/konami/konami.h b/trunk/src/emu/cpu/konami/konami.h
new file mode 100644
index 00000000000..cb49648d4da
--- /dev/null
+++ b/trunk/src/emu/cpu/konami/konami.h
@@ -0,0 +1,30 @@
+/*** konami: Portable Konami cpu emulator ******************************************/
+
+#pragma once
+
+#ifndef __KONAMI_H__
+#define __KONAMI_H__
+
+
+typedef void (*konami_set_lines_func)(device_t *device, int lines);
+
+enum
+{
+ KONAMI_PC=1, KONAMI_S, KONAMI_CC ,KONAMI_A, KONAMI_B, KONAMI_U, KONAMI_X, KONAMI_Y,
+ KONAMI_DP
+};
+
+#define KONAMI_SETLINES_CALLBACK(name) void name(device_t *device, int lines)
+
+#define KONAMI_IRQ_LINE 0 /* IRQ line number */
+#define KONAMI_FIRQ_LINE 1 /* FIRQ line number */
+
+/* PUBLIC FUNCTIONS */
+DECLARE_LEGACY_CPU_DEVICE(KONAMI, konami);
+
+CPU_DISASSEMBLE( konami );
+
+void konami_configure_set_lines(device_t *device, konami_set_lines_func func);
+
+
+#endif /* __KONAMI_H__ */
diff --git a/trunk/src/emu/cpu/konami/konamops.c b/trunk/src/emu/cpu/konami/konamops.c
new file mode 100644
index 00000000000..1049e18e28e
--- /dev/null
+++ b/trunk/src/emu/cpu/konami/konamops.c
@@ -0,0 +1,4339 @@
+/*
+
+HNZVC
+
+? = undefined
+* = affected
+- = unaffected
+0 = cleared
+1 = set
+# = CCr directly affected by instruction
+@ = special - carry set if bit 7 is set
+
+*/
+
+#ifdef NEW
+static void illegal( konami_state *cpustate )
+#else
+INLINE void illegal( konami_state *cpustate )
+#endif
+{
+ logerror("KONAMI: illegal opcode at %04x\n",PC);
+}
+
+/* $00 NEG direct ?**** */
+INLINE void neg_di( konami_state *cpustate )
+{
+ UINT16 r,t;
+ DIRBYTE(cpustate, t);
+ r = -t;
+ CLR_NZVC;
+ SET_FLAGS8(0,t,r);
+ WM(cpustate, EAD,r);
+}
+
+/* $01 ILLEGAL */
+
+/* $02 ILLEGAL */
+
+/* $03 COM direct -**01 */
+INLINE void com_di( konami_state *cpustate )
+{
+ UINT8 t;
+ DIRBYTE(cpustate, t);
+ t = ~t;
+ CLR_NZV;
+ SET_NZ8(t);
+ SEC;
+ WM(cpustate, EAD,t);
+}
+
+/* $04 LSR direct -0*-* */
+INLINE void lsr_di( konami_state *cpustate )
+{
+ UINT8 t;
+ DIRBYTE(cpustate, t);
+ CLR_NZC;
+ CC |= (t & CC_C);
+ t >>= 1;
+ SET_Z8(t);
+ WM(cpustate, EAD,t);
+}
+
+/* $05 ILLEGAL */
+
+/* $06 ROR direct -**-* */
+INLINE void ror_di( konami_state *cpustate )
+{
+ UINT8 t,r;
+ DIRBYTE(cpustate, t);
+ r= (CC & CC_C) << 7;
+ CLR_NZC;
+ CC |= (t & CC_C);
+ r |= t>>1;
+ SET_NZ8(r);
+ WM(cpustate, EAD,r);
+}
+
+/* $07 ASR direct ?**-* */
+INLINE void asr_di( konami_state *cpustate )
+{
+ UINT8 t;
+ DIRBYTE(cpustate, t);
+ CLR_NZC;
+ CC |= (t & CC_C);
+ t = (t & 0x80) | (t >> 1);
+ SET_NZ8(t);
+ WM(cpustate, EAD,t);
+}
+
+/* $08 ASL direct ?**** */
+INLINE void asl_di( konami_state *cpustate )
+{
+ UINT16 t,r;
+ DIRBYTE(cpustate, t);
+ r = t << 1;
+ CLR_NZVC;
+ SET_FLAGS8(t,t,r);
+ WM(cpustate, EAD,r);
+}
+
+/* $09 ROL direct -**** */
+INLINE void rol_di( konami_state *cpustate )
+{
+ UINT16 t,r;
+ DIRBYTE(cpustate, t);
+ r = (CC & CC_C) | (t << 1);
+ CLR_NZVC;
+ SET_FLAGS8(t,t,r);
+ WM(cpustate, EAD,r);
+}
+
+/* $0A DEC direct -***- */
+INLINE void dec_di( konami_state *cpustate )
+{
+ UINT8 t;
+ DIRBYTE(cpustate, t);
+ --t;
+ CLR_NZV;
+ SET_FLAGS8D(t);
+ WM(cpustate, EAD,t);
+}
+
+/* $0B ILLEGAL */
+
+/* $OC INC direct -***- */
+INLINE void inc_di( konami_state *cpustate )
+{
+ UINT8 t;
+ DIRBYTE(cpustate, t);
+ ++t;
+ CLR_NZV;
+ SET_FLAGS8I(t);
+ WM(cpustate, EAD,t);
+}
+
+/* $OD TST direct -**0- */
+INLINE void tst_di( konami_state *cpustate )
+{
+ UINT8 t;
+ DIRBYTE(cpustate, t);
+ CLR_NZV;
+ SET_NZ8(t);
+}
+
+/* $0E JMP direct ----- */
+INLINE void jmp_di( konami_state *cpustate )
+{
+ DIRECT(cpustate);
+ PCD=EAD;
+}
+
+/* $0F CLR direct -0100 */
+INLINE void clr_di( konami_state *cpustate )
+{
+ DIRECT(cpustate);
+ WM(cpustate, EAD,0);
+ CLR_NZVC;
+ SEZ;
+}
+
+/* $10 FLAG */
+
+/* $11 FLAG */
+
+/* $12 NOP inherent ----- */
+INLINE void nop( konami_state *cpustate )
+{
+ ;
+}
+
+/* $13 SYNC inherent ----- */
+INLINE void sync( konami_state *cpustate )
+{
+ /* SYNC stops processing instructions until an interrupt request happens. */
+ /* This doesn't require the corresponding interrupt to be enabled: if it */
+ /* is disabled, execution continues with the next instruction. */
+ cpustate->int_state |= KONAMI_SYNC;
+ check_irq_lines(cpustate);
+ /* if KONAMI_SYNC has not been cleared by check_irq_lines,
+ * stop execution until the interrupt lines change. */
+ if( (cpustate->int_state & KONAMI_SYNC) && cpustate->icount > 0 )
+ cpustate->icount = 0;
+}
+
+/* $14 ILLEGAL */
+
+/* $15 ILLEGAL */
+
+/* $16 LBRA relative ----- */
+INLINE void lbra( konami_state *cpustate )
+{
+ IMMWORD(cpustate, cpustate->ea);
+ PC += EA;
+}
+
+/* $17 LBSR relative ----- */
+INLINE void lbsr( konami_state *cpustate )
+{
+ IMMWORD(cpustate, cpustate->ea);
+ PUSHWORD(cpustate, pPC);
+ PC += EA;
+}
+
+/* $18 ILLEGAL */
+
+#if 1
+/* $19 DAA inherent (A) -**0* */
+INLINE void daa( konami_state *cpustate )
+{
+ UINT8 msn, lsn;
+ UINT16 t, cf = 0;
+ msn = A & 0xf0; lsn = A & 0x0f;
+ if( lsn>0x09 || CC & CC_H) cf |= 0x06;
+ if( msn>0x80 && lsn>0x09 ) cf |= 0x60;
+ if( msn>0x90 || CC & CC_C) cf |= 0x60;
+ t = cf + A;
+ CLR_NZV; /* keep carry from previous operation */
+ SET_NZ8((UINT8)t); SET_C8(t);
+ A = t;
+}
+#else
+/* $19 DAA inherent (A) -**0* */
+INLINE void daa( konami_state *cpustate )
+{
+ UINT16 t;
+ t = A;
+ if (CC & CC_H) t+=0x06;
+ if ((t&0x0f)>9) t+=0x06; /* ASG -- this code is broken! $66+$99=$FF -> DAA should = $65, we get $05! */
+ if (CC & CC_C) t+=0x60;
+ if ((t&0xf0)>0x90) t+=0x60;
+ if (t&0x100) SEC;
+ A = t;
+}
+#endif
+
+/* $1A ORCC immediate ##### */
+INLINE void orcc( konami_state *cpustate )
+{
+ UINT8 t;
+ IMMBYTE(cpustate, t);
+ CC |= t;
+ check_irq_lines(cpustate);
+}
+
+/* $1B ILLEGAL */
+
+/* $1C ANDCC immediate ##### */
+INLINE void andcc( konami_state *cpustate )
+{
+ UINT8 t;
+ IMMBYTE(cpustate, t);
+ CC &= t;
+ check_irq_lines(cpustate);
+}
+
+/* $1D SEX inherent -**0- */
+INLINE void sex( konami_state *cpustate )
+{
+ UINT16 t;
+ t = SIGNED(B);
+ D = t;
+// CLR_NZV; NS 20020905: applying the same fix that was applied to 6809 and 6309
+ CLR_NZ;
+ SET_NZ16(t);
+}
+
+/* $1E EXG inherent ----- */
+INLINE void exg( konami_state *cpustate )
+{
+ UINT16 t1 = 0, t2 = 0;
+ UINT8 tb;
+
+ IMMBYTE(cpustate, tb);
+
+ GETREG( t1, tb >> 4 );
+ GETREG( t2, tb & 0x0f );
+
+ SETREG( t2, tb >> 4 );
+ SETREG( t1, tb & 0x0f );
+}
+
+/* $1F TFR inherent ----- */
+INLINE void tfr( konami_state *cpustate )
+{
+ UINT8 tb;
+ UINT16 t = 0;
+
+ IMMBYTE(cpustate, tb);
+
+ GETREG( t, tb & 0x0f );
+ SETREG( t, ( tb >> 4 ) & 0x07 );
+}
+
+/* $20 BRA relative ----- */
+INLINE void bra( konami_state *cpustate )
+{
+ UINT8 t;
+ IMMBYTE(cpustate, t);
+ PC += SIGNED(t);
+}
+
+/* $21 BRN relative ----- */
+static UINT8 konami_brn_t; // hack around GCC 4.6 error because we need the side effects of IMMBYTE
+INLINE void brn( konami_state *cpustate )
+{
+ IMMBYTE(cpustate, konami_brn_t);
+}
+
+/* $1021 LBRN relative ----- */
+INLINE void lbrn( konami_state *cpustate )
+{
+ IMMWORD(cpustate, cpustate->ea);
+}
+
+/* $22 BHI relative ----- */
+INLINE void bhi( konami_state *cpustate )
+{
+ BRANCH(cpustate, !(CC & (CC_Z|CC_C)) );
+}
+
+/* $1022 LBHI relative ----- */
+INLINE void lbhi( konami_state *cpustate )
+{
+ LBRANCH(cpustate, !(CC & (CC_Z|CC_C)) );
+}
+
+/* $23 BLS relative ----- */
+INLINE void bls( konami_state *cpustate )
+{
+ BRANCH(cpustate, (CC & (CC_Z|CC_C)) );
+}
+
+/* $1023 LBLS relative ----- */
+INLINE void lbls( konami_state *cpustate )
+{
+ LBRANCH(cpustate, (CC&(CC_Z|CC_C)) );
+}
+
+/* $24 BCC relative ----- */
+INLINE void bcc( konami_state *cpustate )
+{
+ BRANCH(cpustate, !(CC&CC_C) );
+}
+
+/* $1024 LBCC relative ----- */
+INLINE void lbcc( konami_state *cpustate )
+{
+ LBRANCH(cpustate, !(CC&CC_C) );
+}
+
+/* $25 BCS relative ----- */
+INLINE void bcs( konami_state *cpustate )
+{
+ BRANCH(cpustate, (CC&CC_C) );
+}
+
+/* $1025 LBCS relative ----- */
+INLINE void lbcs( konami_state *cpustate )
+{
+ LBRANCH(cpustate, (CC&CC_C) );
+}
+
+/* $26 BNE relative ----- */
+INLINE void bne( konami_state *cpustate )
+{
+ BRANCH(cpustate, !(CC&CC_Z) );
+}
+
+/* $1026 LBNE relative ----- */
+INLINE void lbne( konami_state *cpustate )
+{
+ LBRANCH(cpustate, !(CC&CC_Z) );
+}
+
+/* $27 BEQ relative ----- */
+INLINE void beq( konami_state *cpustate )
+{
+ BRANCH(cpustate, (CC&CC_Z) );
+}
+
+/* $1027 LBEQ relative ----- */
+INLINE void lbeq( konami_state *cpustate )
+{
+ LBRANCH(cpustate, (CC&CC_Z) );
+}
+
+/* $28 BVC relative ----- */
+INLINE void bvc( konami_state *cpustate )
+{
+ BRANCH(cpustate, !(CC&CC_V) );
+}
+
+/* $1028 LBVC relative ----- */
+INLINE void lbvc( konami_state *cpustate )
+{
+ LBRANCH(cpustate, !(CC&CC_V) );
+}
+
+/* $29 BVS relative ----- */
+INLINE void bvs( konami_state *cpustate )
+{
+ BRANCH(cpustate, (CC&CC_V) );
+}
+
+/* $1029 LBVS relative ----- */
+INLINE void lbvs( konami_state *cpustate )
+{
+ LBRANCH(cpustate, (CC&CC_V) );
+}
+
+/* $2A BPL relative ----- */
+INLINE void bpl( konami_state *cpustate )
+{
+ BRANCH(cpustate, !(CC&CC_N) );
+}
+
+/* $102A LBPL relative ----- */
+INLINE void lbpl( konami_state *cpustate )
+{
+ LBRANCH(cpustate, !(CC&CC_N) );
+}
+
+/* $2B BMI relative ----- */
+INLINE void bmi( konami_state *cpustate )
+{
+ BRANCH(cpustate, (CC&CC_N) );
+}
+
+/* $102B LBMI relative ----- */
+INLINE void lbmi( konami_state *cpustate )
+{
+ LBRANCH(cpustate, (CC&CC_N) );
+}
+
+/* $2C BGE relative ----- */
+INLINE void bge( konami_state *cpustate )
+{
+ BRANCH(cpustate, !NXORV );
+}
+
+/* $102C LBGE relative ----- */
+INLINE void lbge( konami_state *cpustate )
+{
+ LBRANCH(cpustate, !NXORV );
+}
+
+/* $2D BLT relative ----- */
+INLINE void blt( konami_state *cpustate )
+{
+ BRANCH(cpustate, NXORV );
+}
+
+/* $102D LBLT relative ----- */
+INLINE void lblt( konami_state *cpustate )
+{
+ LBRANCH(cpustate, NXORV );
+}
+
+/* $2E BGT relative ----- */
+INLINE void bgt( konami_state *cpustate )
+{
+ BRANCH(cpustate, !(NXORV || (CC&CC_Z)) );
+}
+
+/* $102E LBGT relative ----- */
+INLINE void lbgt( konami_state *cpustate )
+{
+ LBRANCH(cpustate, !(NXORV || (CC&CC_Z)) );
+}
+
+/* $2F BLE relative ----- */
+INLINE void ble( konami_state *cpustate )
+{
+ BRANCH(cpustate, (NXORV || (CC&CC_Z)) );
+}
+
+/* $102F LBLE relative ----- */
+INLINE void lble( konami_state *cpustate )
+{
+ LBRANCH(cpustate, (NXORV || (CC&CC_Z)) );
+}
+
+/* $30 LEAX indexed --*-- */
+INLINE void leax( konami_state *cpustate )
+{
+ X = EA;
+ CLR_Z;
+ SET_Z(X);
+}
+
+/* $31 LEAY indexed --*-- */
+INLINE void leay( konami_state *cpustate )
+{
+ Y = EA;
+ CLR_Z;
+ SET_Z(Y);
+}
+
+/* $32 LEAS indexed ----- */
+INLINE void leas( konami_state *cpustate )
+{
+ S = EA;
+ cpustate->int_state |= KONAMI_LDS;
+}
+
+/* $33 LEAU indexed ----- */
+INLINE void leau( konami_state *cpustate )
+{
+ U = EA;
+}
+
+/* $34 PSHS inherent ----- */
+INLINE void pshs( konami_state *cpustate )
+{
+ UINT8 t;
+ IMMBYTE(cpustate, t);
+ if( t&0x80 ) { PUSHWORD(cpustate, pPC); cpustate->icount -= 2; }
+ if( t&0x40 ) { PUSHWORD(cpustate, pU); cpustate->icount -= 2; }
+ if( t&0x20 ) { PUSHWORD(cpustate, pY); cpustate->icount -= 2; }
+ if( t&0x10 ) { PUSHWORD(cpustate, pX); cpustate->icount -= 2; }
+ if( t&0x08 ) { PUSHBYTE(cpustate, DP); cpustate->icount -= 1; }
+ if( t&0x04 ) { PUSHBYTE(cpustate, B); cpustate->icount -= 1; }
+ if( t&0x02 ) { PUSHBYTE(cpustate, A); cpustate->icount -= 1; }
+ if( t&0x01 ) { PUSHBYTE(cpustate, CC); cpustate->icount -= 1; }
+}
+
+/* 35 PULS inherent ----- */
+INLINE void puls( konami_state *cpustate )
+{
+ UINT8 t;
+ IMMBYTE(cpustate, t);
+ if( t&0x01 ) { PULLBYTE(cpustate, CC); cpustate->icount -= 1; }
+ if( t&0x02 ) { PULLBYTE(cpustate, A); cpustate->icount -= 1; }
+ if( t&0x04 ) { PULLBYTE(cpustate, B); cpustate->icount -= 1; }
+ if( t&0x08 ) { PULLBYTE(cpustate, DP); cpustate->icount -= 1; }
+ if( t&0x10 ) { PULLWORD(cpustate, XD); cpustate->icount -= 2; }
+ if( t&0x20 ) { PULLWORD(cpustate, YD); cpustate->icount -= 2; }
+ if( t&0x40 ) { PULLWORD(cpustate, UD); cpustate->icount -= 2; }
+ if( t&0x80 ) { PULLWORD(cpustate, PCD); cpustate->icount -= 2; }
+
+ /* check after all PULLs */
+ if( t&0x01 ) { check_irq_lines(cpustate); }
+}
+
+/* $36 PSHU inherent ----- */
+INLINE void pshu( konami_state *cpustate )
+{
+ UINT8 t;
+ IMMBYTE(cpustate, t);
+ if( t&0x80 ) { PSHUWORD(cpustate, pPC); cpustate->icount -= 2; }
+ if( t&0x40 ) { PSHUWORD(cpustate, pS); cpustate->icount -= 2; }
+ if( t&0x20 ) { PSHUWORD(cpustate, pY); cpustate->icount -= 2; }
+ if( t&0x10 ) { PSHUWORD(cpustate, pX); cpustate->icount -= 2; }
+ if( t&0x08 ) { PSHUBYTE(cpustate, DP); cpustate->icount -= 1; }
+ if( t&0x04 ) { PSHUBYTE(cpustate, B); cpustate->icount -= 1; }
+ if( t&0x02 ) { PSHUBYTE(cpustate, A); cpustate->icount -= 1; }
+ if( t&0x01 ) { PSHUBYTE(cpustate, CC); cpustate->icount -= 1; }
+}
+
+/* 37 PULU inherent ----- */
+INLINE void pulu( konami_state *cpustate )
+{
+ UINT8 t;
+ IMMBYTE(cpustate, t);
+ if( t&0x01 ) { PULUBYTE(cpustate, CC); cpustate->icount -= 1; }
+ if( t&0x02 ) { PULUBYTE(cpustate, A); cpustate->icount -= 1; }
+ if( t&0x04 ) { PULUBYTE(cpustate, B); cpustate->icount -= 1; }
+ if( t&0x08 ) { PULUBYTE(cpustate, DP); cpustate->icount -= 1; }
+ if( t&0x10 ) { PULUWORD(cpustate, XD); cpustate->icount -= 2; }
+ if( t&0x20 ) { PULUWORD(cpustate, YD); cpustate->icount -= 2; }
+ if( t&0x40 ) { PULUWORD(cpustate, SD); cpustate->icount -= 2; }
+ if( t&0x80 ) { PULUWORD(cpustate, PCD); cpustate->icount -= 2; }
+
+ /* check after all PULLs */
+ if( t&0x01 ) { check_irq_lines(cpustate); }
+}
+
+/* $38 ILLEGAL */
+
+/* $39 RTS inherent ----- */
+INLINE void rts( konami_state *cpustate )
+{
+ PULLWORD(cpustate, PCD);
+}
+
+/* $3A ABX inherent ----- */
+INLINE void abx( konami_state *cpustate )
+{
+ X += B;
+}
+
+/* $3B RTI inherent ##### */
+INLINE void rti( konami_state *cpustate )
+{
+ PULLBYTE(cpustate, CC);
+ if( CC & CC_E ) /* entire state saved? */
+ {
+ cpustate->icount -= 9;
+ PULLBYTE(cpustate, A);
+ PULLBYTE(cpustate, B);
+ PULLBYTE(cpustate, DP);
+ PULLWORD(cpustate, XD);
+ PULLWORD(cpustate, YD);
+ PULLWORD(cpustate, UD);
+ }
+ PULLWORD(cpustate, PCD);
+ check_irq_lines(cpustate);
+}
+
+/* $3C CWAI inherent ----1 */
+INLINE void cwai( konami_state *cpustate )
+{
+ UINT8 t;
+ IMMBYTE(cpustate, t);
+ CC &= t;
+ /*
+ * CWAI stacks the entire machine state on the hardware stack,
+ * then waits for an interrupt; when the interrupt is taken
+ * later, the state is *not* saved again after CWAI.
+ */
+ CC |= CC_E; /* HJB 990225: save entire state */
+ PUSHWORD(cpustate, pPC);
+ PUSHWORD(cpustate, pU);
+ PUSHWORD(cpustate, pY);
+ PUSHWORD(cpustate, pX);
+ PUSHBYTE(cpustate, DP);
+ PUSHBYTE(cpustate, B);
+ PUSHBYTE(cpustate, A);
+ PUSHBYTE(cpustate, CC);
+ cpustate->int_state |= KONAMI_CWAI;
+ check_irq_lines(cpustate);
+ if( (cpustate->int_state & KONAMI_CWAI) && cpustate->icount > 0 )
+ cpustate->icount = 0;
+}
+
+/* $3D MUL inherent --*-@ */
+INLINE void mul( konami_state *cpustate )
+{
+ UINT16 t;
+ t = A * B;
+ CLR_ZC; SET_Z16(t); if(t&0x80) SEC;
+ D = t;
+}
+
+/* $3E ILLEGAL */
+
+/* $3F SWI (SWI2 SWI3) absolute indirect ----- */
+INLINE void swi( konami_state *cpustate )
+{
+ CC |= CC_E; /* HJB 980225: save entire state */
+ PUSHWORD(cpustate, pPC);
+ PUSHWORD(cpustate, pU);
+ PUSHWORD(cpustate, pY);
+ PUSHWORD(cpustate, pX);
+ PUSHBYTE(cpustate, DP);
+ PUSHBYTE(cpustate, B);
+ PUSHBYTE(cpustate, A);
+ PUSHBYTE(cpustate, CC);
+ CC |= CC_IF | CC_II; /* inhibit FIRQ and IRQ */
+ PCD=RM16(cpustate, 0xfffa);
+}
+
+/* $103F SWI2 absolute indirect ----- */
+INLINE void swi2( konami_state *cpustate )
+{
+ CC |= CC_E; /* HJB 980225: save entire state */
+ PUSHWORD(cpustate, pPC);
+ PUSHWORD(cpustate, pU);
+ PUSHWORD(cpustate, pY);
+ PUSHWORD(cpustate, pX);
+ PUSHBYTE(cpustate, DP);
+ PUSHBYTE(cpustate, B);
+ PUSHBYTE(cpustate, A);
+ PUSHBYTE(cpustate, CC);
+ PCD=RM16(cpustate, 0xfff4);
+}
+
+/* $113F SWI3 absolute indirect ----- */
+INLINE void swi3( konami_state *cpustate )
+{
+ CC |= CC_E; /* HJB 980225: save entire state */
+ PUSHWORD(cpustate, pPC);
+ PUSHWORD(cpustate, pU);
+ PUSHWORD(cpustate, pY);
+ PUSHWORD(cpustate, pX);
+ PUSHBYTE(cpustate, DP);
+ PUSHBYTE(cpustate, B);
+ PUSHBYTE(cpustate, A);
+ PUSHBYTE(cpustate, CC);
+ PCD=RM16(cpustate, 0xfff2);
+}
+
+/* $40 NEGA inherent ?**** */
+INLINE void nega( konami_state *cpustate )
+{
+ UINT16 r;
+ r = -A;
+ CLR_NZVC;
+ SET_FLAGS8(0,A,r);
+ A = r;
+}
+
+/* $41 ILLEGAL */
+
+/* $42 ILLEGAL */
+
+/* $43 COMA inherent -**01 */
+INLINE void coma( konami_state *cpustate )
+{
+ A = ~A;
+ CLR_NZV;
+ SET_NZ8(A);
+ SEC;
+}
+
+/* $44 LSRA inherent -0*-* */
+INLINE void lsra( konami_state *cpustate )
+{
+ CLR_NZC;
+ CC |= (A & CC_C);
+ A >>= 1;
+ SET_Z8(A);
+}
+
+/* $45 ILLEGAL */
+
+/* $46 RORA inherent -**-* */
+INLINE void rora( konami_state *cpustate )
+{
+ UINT8 r;
+ r = (CC & CC_C) << 7;
+ CLR_NZC;
+ CC |= (A & CC_C);
+ r |= A >> 1;
+ SET_NZ8(r);
+ A = r;
+}
+
+/* $47 ASRA inherent ?**-* */
+INLINE void asra( konami_state *cpustate )
+{
+ CLR_NZC;
+ CC |= (A & CC_C);
+ A = (A & 0x80) | (A >> 1);
+ SET_NZ8(A);
+}
+
+/* $48 ASLA inherent ?**** */
+INLINE void asla( konami_state *cpustate )
+{
+ UINT16 r;
+ r = A << 1;
+ CLR_NZVC;
+ SET_FLAGS8(A,A,r);
+ A = r;
+}
+
+/* $49 ROLA inherent -**** */
+INLINE void rola( konami_state *cpustate )
+{
+ UINT16 t,r;
+ t = A;
+ r = (CC & CC_C) | (t<<1);
+ CLR_NZVC; SET_FLAGS8(t,t,r);
+ A = r;
+}
+
+/* $4A DECA inherent -***- */
+INLINE void deca( konami_state *cpustate )
+{
+ --A;
+ CLR_NZV;
+ SET_FLAGS8D(A);
+}
+
+/* $4B ILLEGAL */
+
+/* $4C INCA inherent -***- */
+INLINE void inca( konami_state *cpustate )
+{
+ ++A;
+ CLR_NZV;
+ SET_FLAGS8I(A);
+}
+
+/* $4D TSTA inherent -**0- */
+INLINE void tsta( konami_state *cpustate )
+{
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $4E ILLEGAL */
+
+/* $4F CLRA inherent -0100 */
+INLINE void clra( konami_state *cpustate )
+{
+ A = 0;
+ CLR_NZVC; SEZ;
+}
+
+/* $50 NEGB inherent ?**** */
+INLINE void negb( konami_state *cpustate )
+{
+ UINT16 r;
+ r = -B;
+ CLR_NZVC;
+ SET_FLAGS8(0,B,r);
+ B = r;
+}
+
+/* $51 ILLEGAL */
+
+/* $52 ILLEGAL */
+
+/* $53 COMB inherent -**01 */
+INLINE void comb( konami_state *cpustate )
+{
+ B = ~B;
+ CLR_NZV;
+ SET_NZ8(B);
+ SEC;
+}
+
+/* $54 LSRB inherent -0*-* */
+INLINE void lsrb( konami_state *cpustate )
+{
+ CLR_NZC;
+ CC |= (B & CC_C);
+ B >>= 1;
+ SET_Z8(B);
+}
+
+/* $55 ILLEGAL */
+
+/* $56 RORB inherent -**-* */
+INLINE void rorb( konami_state *cpustate )
+{
+ UINT8 r;
+ r = (CC & CC_C) << 7;
+ CLR_NZC;
+ CC |= (B & CC_C);
+ r |= B >> 1;
+ SET_NZ8(r);
+ B = r;
+}
+
+/* $57 ASRB inherent ?**-* */
+INLINE void asrb( konami_state *cpustate )
+{
+ CLR_NZC;
+ CC |= (B & CC_C);
+ B= (B & 0x80) | (B >> 1);
+ SET_NZ8(B);
+}
+
+/* $58 ASLB inherent ?**** */
+INLINE void aslb( konami_state *cpustate )
+{
+ UINT16 r;
+ r = B << 1;
+ CLR_NZVC;
+ SET_FLAGS8(B,B,r);
+ B = r;
+}
+
+/* $59 ROLB inherent -**** */
+INLINE void rolb( konami_state *cpustate )
+{
+ UINT16 t,r;
+ t = B;
+ r = CC & CC_C;
+ r |= t << 1;
+ CLR_NZVC;
+ SET_FLAGS8(t,t,r);
+ B = r;
+}
+
+/* $5A DECB inherent -***- */
+INLINE void decb( konami_state *cpustate )
+{
+ --B;
+ CLR_NZV;
+ SET_FLAGS8D(B);
+}
+
+/* $5B ILLEGAL */
+
+/* $5C INCB inherent -***- */
+INLINE void incb( konami_state *cpustate )
+{
+ ++B;
+ CLR_NZV;
+ SET_FLAGS8I(B);
+}
+
+/* $5D TSTB inherent -**0- */
+INLINE void tstb( konami_state *cpustate )
+{
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $5E ILLEGAL */
+
+/* $5F CLRB inherent -0100 */
+INLINE void clrb( konami_state *cpustate )
+{
+ B = 0;
+ CLR_NZVC; SEZ;
+}
+
+/* $60 NEG indexed ?**** */
+INLINE void neg_ix( konami_state *cpustate )
+{
+ UINT16 r,t;
+ t = RM(cpustate, EAD);
+ r = -t;
+ CLR_NZVC;
+ SET_FLAGS8(0,t,r);
+ WM(cpustate, EAD,r);
+}
+
+/* $61 ILLEGAL */
+
+/* $62 ILLEGAL */
+
+/* $63 COM indexed -**01 */
+INLINE void com_ix( konami_state *cpustate )
+{
+ UINT8 t;
+ t = ~RM(cpustate, EAD);
+ CLR_NZV;
+ SET_NZ8(t);
+ SEC;
+ WM(cpustate, EAD,t);
+}
+
+/* $64 LSR indexed -0*-* */
+INLINE void lsr_ix( konami_state *cpustate )
+{
+ UINT8 t;
+ t = RM(cpustate, EAD);
+ CLR_NZC;
+ CC |= (t & CC_C);
+ t>>=1; SET_Z8(t);
+ WM(cpustate, EAD,t);
+}
+
+/* $65 ILLEGAL */
+
+/* $66 ROR indexed -**-* */
+INLINE void ror_ix( konami_state *cpustate )
+{
+ UINT8 t,r;
+ t = RM(cpustate, EAD);
+ r = (CC & CC_C) << 7;
+ CLR_NZC;
+ CC |= (t & CC_C);
+ r |= t>>1; SET_NZ8(r);
+ WM(cpustate, EAD,r);
+}
+
+/* $67 ASR indexed ?**-* */
+INLINE void asr_ix( konami_state *cpustate )
+{
+ UINT8 t;
+ t = RM(cpustate, EAD);
+ CLR_NZC;
+ CC |= (t & CC_C);
+ t=(t&0x80)|(t>>1);
+ SET_NZ8(t);
+ WM(cpustate, EAD,t);
+}
+
+/* $68 ASL indexed ?**** */
+INLINE void asl_ix( konami_state *cpustate )
+{
+ UINT16 t,r;
+ t = RM(cpustate, EAD);
+ r = t << 1;
+ CLR_NZVC;
+ SET_FLAGS8(t,t,r);
+ WM(cpustate, EAD,r);
+}
+
+/* $69 ROL indexed -**** */
+INLINE void rol_ix( konami_state *cpustate )
+{
+ UINT16 t,r;
+ t = RM(cpustate, EAD);
+ r = CC & CC_C;
+ r |= t << 1;
+ CLR_NZVC;
+ SET_FLAGS8(t,t,r);
+ WM(cpustate, EAD,r);
+}
+
+/* $6A DEC indexed -***- */
+INLINE void dec_ix( konami_state *cpustate )
+{
+ UINT8 t;
+ t = RM(cpustate, EAD) - 1;
+ CLR_NZV; SET_FLAGS8D(t);
+ WM(cpustate, EAD,t);
+}
+
+/* $6B ILLEGAL */
+
+/* $6C INC indexed -***- */
+INLINE void inc_ix( konami_state *cpustate )
+{
+ UINT8 t;
+ t = RM(cpustate, EAD) + 1;
+ CLR_NZV; SET_FLAGS8I(t);
+ WM(cpustate, EAD,t);
+}
+
+/* $6D TST indexed -**0- */
+INLINE void tst_ix( konami_state *cpustate )
+{
+ UINT8 t;
+ t = RM(cpustate, EAD);
+ CLR_NZV;
+ SET_NZ8(t);
+}
+
+/* $6E JMP indexed ----- */
+INLINE void jmp_ix( konami_state *cpustate )
+{
+ PCD=EAD;
+}
+
+/* $6F CLR indexed -0100 */
+INLINE void clr_ix( konami_state *cpustate )
+{
+ WM(cpustate, EAD,0);
+ CLR_NZVC; SEZ;
+}
+
+/* $70 NEG extended ?**** */
+INLINE void neg_ex( konami_state *cpustate )
+{
+ UINT16 r,t;
+ EXTBYTE(cpustate, t); r=-t;
+ CLR_NZVC; SET_FLAGS8(0,t,r);
+ WM(cpustate, EAD,r);
+}
+
+/* $71 ILLEGAL */
+
+/* $72 ILLEGAL */
+
+/* $73 COM extended -**01 */
+INLINE void com_ex( konami_state *cpustate )
+{
+ UINT8 t;
+ EXTBYTE(cpustate, t); t = ~t;
+ CLR_NZV; SET_NZ8(t); SEC;
+ WM(cpustate, EAD,t);
+}
+
+/* $74 LSR extended -0*-* */
+INLINE void lsr_ex( konami_state *cpustate )
+{
+ UINT8 t;
+ EXTBYTE(cpustate, t); CLR_NZC; CC |= (t & CC_C);
+ t>>=1; SET_Z8(t);
+ WM(cpustate, EAD,t);
+}
+
+/* $75 ILLEGAL */
+
+/* $76 ROR extended -**-* */
+INLINE void ror_ex( konami_state *cpustate )
+{
+ UINT8 t,r;
+ EXTBYTE(cpustate, t); r=(CC & CC_C) << 7;
+ CLR_NZC; CC |= (t & CC_C);
+ r |= t>>1; SET_NZ8(r);
+ WM(cpustate, EAD,r);
+}
+
+/* $77 ASR extended ?**-* */
+INLINE void asr_ex( konami_state *cpustate )
+{
+ UINT8 t;
+ EXTBYTE(cpustate, t); CLR_NZC; CC |= (t & CC_C);
+ t=(t&0x80)|(t>>1);
+ SET_NZ8(t);
+ WM(cpustate, EAD,t);
+}
+
+/* $78 ASL extended ?**** */
+INLINE void asl_ex( konami_state *cpustate )
+{
+ UINT16 t,r;
+ EXTBYTE(cpustate, t); r=t<<1;
+ CLR_NZVC; SET_FLAGS8(t,t,r);
+ WM(cpustate, EAD,r);
+}
+
+/* $79 ROL extended -**** */
+INLINE void rol_ex( konami_state *cpustate )
+{
+ UINT16 t,r;
+ EXTBYTE(cpustate, t); r = (CC & CC_C) | (t << 1);
+ CLR_NZVC; SET_FLAGS8(t,t,r);
+ WM(cpustate, EAD,r);
+}
+
+/* $7A DEC extended -***- */
+INLINE void dec_ex( konami_state *cpustate )
+{
+ UINT8 t;
+ EXTBYTE(cpustate, t); --t;
+ CLR_NZV; SET_FLAGS8D(t);
+ WM(cpustate, EAD,t);
+}
+
+/* $7B ILLEGAL */
+
+/* $7C INC extended -***- */
+INLINE void inc_ex( konami_state *cpustate )
+{
+ UINT8 t;
+ EXTBYTE(cpustate, t); ++t;
+ CLR_NZV; SET_FLAGS8I(t);
+ WM(cpustate, EAD,t);
+}
+
+/* $7D TST extended -**0- */
+INLINE void tst_ex( konami_state *cpustate )
+{
+ UINT8 t;
+ EXTBYTE(cpustate, t); CLR_NZV; SET_NZ8(t);
+}
+
+/* $7E JMP extended ----- */
+INLINE void jmp_ex( konami_state *cpustate )
+{
+ EXTENDED(cpustate);
+ PCD=EAD;
+}
+
+/* $7F CLR extended -0100 */
+INLINE void clr_ex( konami_state *cpustate )
+{
+ EXTENDED(cpustate);
+ WM(cpustate, EAD,0);
+ CLR_NZVC; SEZ;
+}
+
+/* $80 SUBA immediate ?**** */
+INLINE void suba_im( konami_state *cpustate )
+{
+ UINT16 t,r;
+ IMMBYTE(cpustate, t);
+ r = A - t;
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $81 CMPA immediate ?**** */
+INLINE void cmpa_im( konami_state *cpustate )
+{
+ UINT16 t,r;
+ IMMBYTE(cpustate, t);
+ r = A - t;
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+}
+
+/* $82 SBCA immediate ?**** */
+INLINE void sbca_im( konami_state *cpustate )
+{
+ UINT16 t,r;
+ IMMBYTE(cpustate, t);
+ r = A - t - (CC & CC_C);
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $83 SUBD (CMPD CMPU) immediate -**** */
+INLINE void subd_im( konami_state *cpustate )
+{
+ UINT32 r,d;
+ PAIR b;
+ IMMWORD(cpustate, b);
+ d = D;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ D = r;
+}
+
+/* $1083 CMPD immediate -**** */
+INLINE void cmpd_im( konami_state *cpustate )
+{
+ UINT32 r,d;
+ PAIR b;
+ IMMWORD(cpustate, b);
+ d = D;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $1183 CMPU immediate -**** */
+INLINE void cmpu_im( konami_state *cpustate )
+{
+ UINT32 r, d;
+ PAIR b;
+ IMMWORD(cpustate, b);
+ d = U;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $84 ANDA immediate -**0- */
+INLINE void anda_im( konami_state *cpustate )
+{
+ UINT8 t;
+ IMMBYTE(cpustate, t);
+ A &= t;
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $85 BITA immediate -**0- */
+INLINE void bita_im( konami_state *cpustate )
+{
+ UINT8 t,r;
+ IMMBYTE(cpustate, t);
+ r = A & t;
+ CLR_NZV;
+ SET_NZ8(r);
+}
+
+/* $86 LDA immediate -**0- */
+INLINE void lda_im( konami_state *cpustate )
+{
+ IMMBYTE(cpustate, A);
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* is this a legal instruction? */
+/* $87 STA immediate -**0- */
+INLINE void sta_im( konami_state *cpustate )
+{
+ CLR_NZV;
+ SET_NZ8(A);
+ IMM8(cpustate);
+ WM(cpustate, EAD,A);
+}
+
+/* $88 EORA immediate -**0- */
+INLINE void eora_im( konami_state *cpustate )
+{
+ UINT8 t;
+ IMMBYTE(cpustate, t);
+ A ^= t;
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $89 ADCA immediate ***** */
+INLINE void adca_im( konami_state *cpustate )
+{
+ UINT16 t,r;
+ IMMBYTE(cpustate, t);
+ r = A + t + (CC & CC_C);
+ CLR_HNZVC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $8A ORA immediate -**0- */
+INLINE void ora_im( konami_state *cpustate )
+{
+ UINT8 t;
+ IMMBYTE(cpustate, t);
+ A |= t;
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $8B ADDA immediate ***** */
+INLINE void adda_im( konami_state *cpustate )
+{
+ UINT16 t,r;
+ IMMBYTE(cpustate, t);
+ r = A + t;
+ CLR_HNZVC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $8C CMPX (CMPY CMPS) immediate -**** */
+INLINE void cmpx_im( konami_state *cpustate )
+{
+ UINT32 r,d;
+ PAIR b;
+ IMMWORD(cpustate, b);
+ d = X;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $108C CMPY immediate -**** */
+INLINE void cmpy_im( konami_state *cpustate )
+{
+ UINT32 r,d;
+ PAIR b;
+ IMMWORD(cpustate, b);
+ d = Y;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $118C CMPS immediate -**** */
+INLINE void cmps_im( konami_state *cpustate )
+{
+ UINT32 r,d;
+ PAIR b;
+ IMMWORD(cpustate, b);
+ d = S;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $8D BSR ----- */
+INLINE void bsr( konami_state *cpustate )
+{
+ UINT8 t;
+ IMMBYTE(cpustate, t);
+ PUSHWORD(cpustate, pPC);
+ PC += SIGNED(t);
+}
+
+/* $8E LDX (LDY) immediate -**0- */
+INLINE void ldx_im( konami_state *cpustate )
+{
+ IMMWORD(cpustate, pX);
+ CLR_NZV;
+ SET_NZ16(X);
+}
+
+/* $108E LDY immediate -**0- */
+INLINE void ldy_im( konami_state *cpustate )
+{
+ IMMWORD(cpustate, pY);
+ CLR_NZV;
+ SET_NZ16(Y);
+}
+
+/* is this a legal instruction? */
+/* $8F STX (STY) immediate -**0- */
+INLINE void stx_im( konami_state *cpustate )
+{
+ CLR_NZV;
+ SET_NZ16(X);
+ IMM16(cpustate);
+ WM16(cpustate, EAD,&pX);
+}
+
+/* is this a legal instruction? */
+/* $108F STY immediate -**0- */
+INLINE void sty_im( konami_state *cpustate )
+{
+ CLR_NZV;
+ SET_NZ16(Y);
+ IMM16(cpustate);
+ WM16(cpustate, EAD,&pY);
+}
+
+/* $90 SUBA direct ?**** */
+INLINE void suba_di( konami_state *cpustate )
+{
+ UINT16 t,r;
+ DIRBYTE(cpustate, t);
+ r = A - t;
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $91 CMPA direct ?**** */
+INLINE void cmpa_di( konami_state *cpustate )
+{
+ UINT16 t,r;
+ DIRBYTE(cpustate, t);
+ r = A - t;
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+}
+
+/* $92 SBCA direct ?**** */
+INLINE void sbca_di( konami_state *cpustate )
+{
+ UINT16 t,r;
+ DIRBYTE(cpustate, t);
+ r = A - t - (CC & CC_C);
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $93 SUBD (CMPD CMPU) direct -**** */
+INLINE void subd_di( konami_state *cpustate )
+{
+ UINT32 r,d;
+ PAIR b;
+ DIRWORD(cpustate, b);
+ d = D;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ D = r;
+}
+
+/* $1093 CMPD direct -**** */
+INLINE void cmpd_di( konami_state *cpustate )
+{
+ UINT32 r,d;
+ PAIR b;
+ DIRWORD(cpustate, b);
+ d = D;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $1193 CMPU direct -**** */
+INLINE void cmpu_di( konami_state *cpustate )
+{
+ UINT32 r,d;
+ PAIR b;
+ DIRWORD(cpustate, b);
+ d = U;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(U,b.d,r);
+}
+
+/* $94 ANDA direct -**0- */
+INLINE void anda_di( konami_state *cpustate )
+{
+ UINT8 t;
+ DIRBYTE(cpustate, t);
+ A &= t;
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $95 BITA direct -**0- */
+INLINE void bita_di( konami_state *cpustate )
+{
+ UINT8 t,r;
+ DIRBYTE(cpustate, t);
+ r = A & t;
+ CLR_NZV;
+ SET_NZ8(r);
+}
+
+/* $96 LDA direct -**0- */
+INLINE void lda_di( konami_state *cpustate )
+{
+ DIRBYTE(cpustate, A);
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $97 STA direct -**0- */
+INLINE void sta_di( konami_state *cpustate )
+{
+ CLR_NZV;
+ SET_NZ8(A);
+ DIRECT(cpustate);
+ WM(cpustate, EAD,A);
+}
+
+/* $98 EORA direct -**0- */
+INLINE void eora_di( konami_state *cpustate )
+{
+ UINT8 t;
+ DIRBYTE(cpustate, t);
+ A ^= t;
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $99 ADCA direct ***** */
+INLINE void adca_di( konami_state *cpustate )
+{
+ UINT16 t,r;
+ DIRBYTE(cpustate, t);
+ r = A + t + (CC & CC_C);
+ CLR_HNZVC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $9A ORA direct -**0- */
+INLINE void ora_di( konami_state *cpustate )
+{
+ UINT8 t;
+ DIRBYTE(cpustate, t);
+ A |= t;
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $9B ADDA direct ***** */
+INLINE void adda_di( konami_state *cpustate )
+{
+ UINT16 t,r;
+ DIRBYTE(cpustate, t);
+ r = A + t;
+ CLR_HNZVC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $9C CMPX (CMPY CMPS) direct -**** */
+INLINE void cmpx_di( konami_state *cpustate )
+{
+ UINT32 r,d;
+ PAIR b;
+ DIRWORD(cpustate, b);
+ d = X;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $109C CMPY direct -**** */
+INLINE void cmpy_di( konami_state *cpustate )
+{
+ UINT32 r,d;
+ PAIR b;
+ DIRWORD(cpustate, b);
+ d = Y;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $119C CMPS direct -**** */
+INLINE void cmps_di( konami_state *cpustate )
+{
+ UINT32 r,d;
+ PAIR b;
+ DIRWORD(cpustate, b);
+ d = S;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $9D JSR direct ----- */
+INLINE void jsr_di( konami_state *cpustate )
+{
+ DIRECT(cpustate);
+ PUSHWORD(cpustate, pPC);
+ PCD=EAD;
+}
+
+/* $9E LDX (LDY) direct -**0- */
+INLINE void ldx_di( konami_state *cpustate )
+{
+ DIRWORD(cpustate, pX);
+ CLR_NZV;
+ SET_NZ16(X);
+}
+
+/* $109E LDY direct -**0- */
+INLINE void ldy_di( konami_state *cpustate )
+{
+ DIRWORD(cpustate, pY);
+ CLR_NZV;
+ SET_NZ16(Y);
+}
+
+/* $9F STX (STY) direct -**0- */
+INLINE void stx_di( konami_state *cpustate )
+{
+ CLR_NZV;
+ SET_NZ16(X);
+ DIRECT(cpustate);
+ WM16(cpustate, EAD,&pX);
+}
+
+/* $109F STY direct -**0- */
+INLINE void sty_di( konami_state *cpustate )
+{
+ CLR_NZV;
+ SET_NZ16(Y);
+ DIRECT(cpustate);
+ WM16(cpustate, EAD,&pY);
+}
+
+/* $a0 SUBA indexed ?**** */
+INLINE void suba_ix( konami_state *cpustate )
+{
+ UINT16 t,r;
+ t = RM(cpustate, EAD);
+ r = A - t;
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $a1 CMPA indexed ?**** */
+INLINE void cmpa_ix( konami_state *cpustate )
+{
+ UINT16 t,r;
+ t = RM(cpustate, EAD);
+ r = A - t;
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+}
+
+/* $a2 SBCA indexed ?**** */
+INLINE void sbca_ix( konami_state *cpustate )
+{
+ UINT16 t,r;
+ t = RM(cpustate, EAD);
+ r = A - t - (CC & CC_C);
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $a3 SUBD (CMPD CMPU) indexed -**** */
+INLINE void subd_ix( konami_state *cpustate )
+{
+ UINT32 r,d;
+ PAIR b;
+ b.d=RM16(cpustate, EAD);
+ d = D;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ D = r;
+}
+
+/* $10a3 CMPD indexed -**** */
+INLINE void cmpd_ix( konami_state *cpustate )
+{
+ UINT32 r,d;
+ PAIR b;
+ b.d=RM16(cpustate, EAD);
+ d = D;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $11a3 CMPU indexed -**** */
+INLINE void cmpu_ix( konami_state *cpustate )
+{
+ UINT32 r;
+ PAIR b;
+ b.d=RM16(cpustate, EAD);
+ r = U - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(U,b.d,r);
+}
+
+/* $a4 ANDA indexed -**0- */
+INLINE void anda_ix( konami_state *cpustate )
+{
+ A &= RM(cpustate, EAD);
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $a5 BITA indexed -**0- */
+INLINE void bita_ix( konami_state *cpustate )
+{
+ UINT8 r;
+ r = A & RM(cpustate, EAD);
+ CLR_NZV;
+ SET_NZ8(r);
+}
+
+/* $a6 LDA indexed -**0- */
+INLINE void lda_ix( konami_state *cpustate )
+{
+ A = RM(cpustate, EAD);
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $a7 STA indexed -**0- */
+INLINE void sta_ix( konami_state *cpustate )
+{
+ CLR_NZV;
+ SET_NZ8(A);
+ WM(cpustate, EAD,A);
+}
+
+/* $a8 EORA indexed -**0- */
+INLINE void eora_ix( konami_state *cpustate )
+{
+ A ^= RM(cpustate, EAD);
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $a9 ADCA indexed ***** */
+INLINE void adca_ix( konami_state *cpustate )
+{
+ UINT16 t,r;
+ t = RM(cpustate, EAD);
+ r = A + t + (CC & CC_C);
+ CLR_HNZVC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $aA ORA indexed -**0- */
+INLINE void ora_ix( konami_state *cpustate )
+{
+ A |= RM(cpustate, EAD);
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $aB ADDA indexed ***** */
+INLINE void adda_ix( konami_state *cpustate )
+{
+ UINT16 t,r;
+ t = RM(cpustate, EAD);
+ r = A + t;
+ CLR_HNZVC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $aC CMPX (CMPY CMPS) indexed -**** */
+INLINE void cmpx_ix( konami_state *cpustate )
+{
+ UINT32 r,d;
+ PAIR b;
+ b.d=RM16(cpustate, EAD);
+ d = X;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $10aC CMPY indexed -**** */
+INLINE void cmpy_ix( konami_state *cpustate )
+{
+ UINT32 r,d;
+ PAIR b;
+ b.d=RM16(cpustate, EAD);
+ d = Y;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $11aC CMPS indexed -**** */
+INLINE void cmps_ix( konami_state *cpustate )
+{
+ UINT32 r,d;
+ PAIR b;
+ b.d=RM16(cpustate, EAD);
+ d = S;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $aD JSR indexed ----- */
+INLINE void jsr_ix( konami_state *cpustate )
+{
+ PUSHWORD(cpustate, pPC);
+ PCD=EAD;
+}
+
+/* $aE LDX (LDY) indexed -**0- */
+INLINE void ldx_ix( konami_state *cpustate )
+{
+ X=RM16(cpustate, EAD);
+ CLR_NZV;
+ SET_NZ16(X);
+}
+
+/* $10aE LDY indexed -**0- */
+INLINE void ldy_ix( konami_state *cpustate )
+{
+ Y=RM16(cpustate, EAD);
+ CLR_NZV;
+ SET_NZ16(Y);
+}
+
+/* $aF STX (STY) indexed -**0- */
+INLINE void stx_ix( konami_state *cpustate )
+{
+ CLR_NZV;
+ SET_NZ16(X);
+ WM16(cpustate, EAD,&pX);
+}
+
+/* $10aF STY indexed -**0- */
+INLINE void sty_ix( konami_state *cpustate )
+{
+ CLR_NZV;
+ SET_NZ16(Y);
+ WM16(cpustate, EAD,&pY);
+}
+
+/* $b0 SUBA extended ?**** */
+INLINE void suba_ex( konami_state *cpustate )
+{
+ UINT16 t,r;
+ EXTBYTE(cpustate, t);
+ r = A - t;
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $b1 CMPA extended ?**** */
+INLINE void cmpa_ex( konami_state *cpustate )
+{
+ UINT16 t,r;
+ EXTBYTE(cpustate, t);
+ r = A - t;
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+}
+
+/* $b2 SBCA extended ?**** */
+INLINE void sbca_ex( konami_state *cpustate )
+{
+ UINT16 t,r;
+ EXTBYTE(cpustate, t);
+ r = A - t - (CC & CC_C);
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $b3 SUBD (CMPD CMPU) extended -**** */
+INLINE void subd_ex( konami_state *cpustate )
+{
+ UINT32 r,d;
+ PAIR b;
+ EXTWORD(cpustate, b);
+ d = D;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ D = r;
+}
+
+/* $10b3 CMPD extended -**** */
+INLINE void cmpd_ex( konami_state *cpustate )
+{
+ UINT32 r,d;
+ PAIR b;
+ EXTWORD(cpustate, b);
+ d = D;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $11b3 CMPU extended -**** */
+INLINE void cmpu_ex( konami_state *cpustate )
+{
+ UINT32 r,d;
+ PAIR b;
+ EXTWORD(cpustate, b);
+ d = U;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $b4 ANDA extended -**0- */
+INLINE void anda_ex( konami_state *cpustate )
+{
+ UINT8 t;
+ EXTBYTE(cpustate, t);
+ A &= t;
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $b5 BITA extended -**0- */
+INLINE void bita_ex( konami_state *cpustate )
+{
+ UINT8 t,r;
+ EXTBYTE(cpustate, t);
+ r = A & t;
+ CLR_NZV; SET_NZ8(r);
+}
+
+/* $b6 LDA extended -**0- */
+INLINE void lda_ex( konami_state *cpustate )
+{
+ EXTBYTE(cpustate, A);
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $b7 STA extended -**0- */
+INLINE void sta_ex( konami_state *cpustate )
+{
+ CLR_NZV;
+ SET_NZ8(A);
+ EXTENDED(cpustate);
+ WM(cpustate, EAD,A);
+}
+
+/* $b8 EORA extended -**0- */
+INLINE void eora_ex( konami_state *cpustate )
+{
+ UINT8 t;
+ EXTBYTE(cpustate, t);
+ A ^= t;
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $b9 ADCA extended ***** */
+INLINE void adca_ex( konami_state *cpustate )
+{
+ UINT16 t,r;
+ EXTBYTE(cpustate, t);
+ r = A + t + (CC & CC_C);
+ CLR_HNZVC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $bA ORA extended -**0- */
+INLINE void ora_ex( konami_state *cpustate )
+{
+ UINT8 t;
+ EXTBYTE(cpustate, t);
+ A |= t;
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $bB ADDA extended ***** */
+INLINE void adda_ex( konami_state *cpustate )
+{
+ UINT16 t,r;
+ EXTBYTE(cpustate, t);
+ r = A + t;
+ CLR_HNZVC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $bC CMPX (CMPY CMPS) extended -**** */
+INLINE void cmpx_ex( konami_state *cpustate )
+{
+ UINT32 r,d;
+ PAIR b;
+ EXTWORD(cpustate, b);
+ d = X;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $10bC CMPY extended -**** */
+INLINE void cmpy_ex( konami_state *cpustate )
+{
+ UINT32 r,d;
+ PAIR b;
+ EXTWORD(cpustate, b);
+ d = Y;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $11bC CMPS extended -**** */
+INLINE void cmps_ex( konami_state *cpustate )
+{
+ UINT32 r,d;
+ PAIR b;
+ EXTWORD(cpustate, b);
+ d = S;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $bD JSR extended ----- */
+INLINE void jsr_ex( konami_state *cpustate )
+{
+ EXTENDED(cpustate);
+ PUSHWORD(cpustate, pPC);
+ PCD=EAD;
+}
+
+/* $bE LDX (LDY) extended -**0- */
+INLINE void ldx_ex( konami_state *cpustate )
+{
+ EXTWORD(cpustate, pX);
+ CLR_NZV;
+ SET_NZ16(X);
+}
+
+/* $10bE LDY extended -**0- */
+INLINE void ldy_ex( konami_state *cpustate )
+{
+ EXTWORD(cpustate, pY);
+ CLR_NZV;
+ SET_NZ16(Y);
+}
+
+/* $bF STX (STY) extended -**0- */
+INLINE void stx_ex( konami_state *cpustate )
+{
+ CLR_NZV;
+ SET_NZ16(X);
+ EXTENDED(cpustate);
+ WM16(cpustate, EAD,&pX);
+}
+
+/* $10bF STY extended -**0- */
+INLINE void sty_ex( konami_state *cpustate )
+{
+ CLR_NZV;
+ SET_NZ16(Y);
+ EXTENDED(cpustate);
+ WM16(cpustate, EAD,&pY);
+}
+
+/* $c0 SUBB immediate ?**** */
+INLINE void subb_im( konami_state *cpustate )
+{
+ UINT16 t,r;
+ IMMBYTE(cpustate, t);
+ r = B - t;
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+ B = r;
+}
+
+/* $c1 CMPB immediate ?**** */
+INLINE void cmpb_im( konami_state *cpustate )
+{
+ UINT16 t,r;
+ IMMBYTE(cpustate, t);
+ r = B - t;
+ CLR_NZVC; SET_FLAGS8(B,t,r);
+}
+
+/* $c2 SBCB immediate ?**** */
+INLINE void sbcb_im( konami_state *cpustate )
+{
+ UINT16 t,r;
+ IMMBYTE(cpustate, t);
+ r = B - t - (CC & CC_C);
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+ B = r;
+}
+
+/* $c3 ADDD immediate -**** */
+INLINE void addd_im( konami_state *cpustate )
+{
+ UINT32 r,d;
+ PAIR b;
+ IMMWORD(cpustate, b);
+ d = D;
+ r = d + b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ D = r;
+}
+
+/* $c4 ANDB immediate -**0- */
+INLINE void andb_im( konami_state *cpustate )
+{
+ UINT8 t;
+ IMMBYTE(cpustate, t);
+ B &= t;
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $c5 BITB immediate -**0- */
+INLINE void bitb_im( konami_state *cpustate )
+{
+ UINT8 t,r;
+ IMMBYTE(cpustate, t);
+ r = B & t;
+ CLR_NZV;
+ SET_NZ8(r);
+}
+
+/* $c6 LDB immediate -**0- */
+INLINE void ldb_im( konami_state *cpustate )
+{
+ IMMBYTE(cpustate, B);
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* is this a legal instruction? */
+/* $c7 STB immediate -**0- */
+INLINE void stb_im( konami_state *cpustate )
+{
+ CLR_NZV;
+ SET_NZ8(B);
+ IMM8(cpustate);
+ WM(cpustate, EAD,B);
+}
+
+/* $c8 EORB immediate -**0- */
+INLINE void eorb_im( konami_state *cpustate )
+{
+ UINT8 t;
+ IMMBYTE(cpustate, t);
+ B ^= t;
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $c9 ADCB immediate ***** */
+INLINE void adcb_im( konami_state *cpustate )
+{
+ UINT16 t,r;
+ IMMBYTE(cpustate, t);
+ r = B + t + (CC & CC_C);
+ CLR_HNZVC;
+ SET_FLAGS8(B,t,r);
+ SET_H(B,t,r);
+ B = r;
+}
+
+/* $cA ORB immediate -**0- */
+INLINE void orb_im( konami_state *cpustate )
+{
+ UINT8 t;
+ IMMBYTE(cpustate, t);
+ B |= t;
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $cB ADDB immediate ***** */
+INLINE void addb_im( konami_state *cpustate )
+{
+ UINT16 t,r;
+ IMMBYTE(cpustate, t);
+ r = B + t;
+ CLR_HNZVC;
+ SET_FLAGS8(B,t,r);
+ SET_H(B,t,r);
+ B = r;
+}
+
+/* $cC LDD immediate -**0- */
+INLINE void ldd_im( konami_state *cpustate )
+{
+ IMMWORD(cpustate, pD);
+ CLR_NZV;
+ SET_NZ16(D);
+}
+
+/* is this a legal instruction? */
+/* $cD STD immediate -**0- */
+INLINE void std_im( konami_state *cpustate )
+{
+ CLR_NZV;
+ SET_NZ16(D);
+ IMM16(cpustate);
+ WM16(cpustate, EAD,&pD);
+}
+
+/* $cE LDU (LDS) immediate -**0- */
+INLINE void ldu_im( konami_state *cpustate )
+{
+ IMMWORD(cpustate, pU);
+ CLR_NZV;
+ SET_NZ16(U);
+}
+
+/* $10cE LDS immediate -**0- */
+INLINE void lds_im( konami_state *cpustate )
+{
+ IMMWORD(cpustate, pS);
+ CLR_NZV;
+ SET_NZ16(S);
+ cpustate->int_state |= KONAMI_LDS;
+}
+
+/* is this a legal instruction? */
+/* $cF STU (STS) immediate -**0- */
+INLINE void stu_im( konami_state *cpustate )
+{
+ CLR_NZV;
+ SET_NZ16(U);
+ IMM16(cpustate);
+ WM16(cpustate, EAD,&pU);
+}
+
+/* is this a legal instruction? */
+/* $10cF STS immediate -**0- */
+INLINE void sts_im( konami_state *cpustate )
+{
+ CLR_NZV;
+ SET_NZ16(S);
+ IMM16(cpustate);
+ WM16(cpustate, EAD,&pS);
+}
+
+/* $d0 SUBB direct ?**** */
+INLINE void subb_di( konami_state *cpustate )
+{
+ UINT16 t,r;
+ DIRBYTE(cpustate, t);
+ r = B - t;
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+ B = r;
+}
+
+/* $d1 CMPB direct ?**** */
+INLINE void cmpb_di( konami_state *cpustate )
+{
+ UINT16 t,r;
+ DIRBYTE(cpustate, t);
+ r = B - t;
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+}
+
+/* $d2 SBCB direct ?**** */
+INLINE void sbcb_di( konami_state *cpustate )
+{
+ UINT16 t,r;
+ DIRBYTE(cpustate, t);
+ r = B - t - (CC & CC_C);
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+ B = r;
+}
+
+/* $d3 ADDD direct -**** */
+INLINE void addd_di( konami_state *cpustate )
+{
+ UINT32 r,d;
+ PAIR b;
+ DIRWORD(cpustate, b);
+ d = D;
+ r = d + b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ D = r;
+}
+
+/* $d4 ANDB direct -**0- */
+INLINE void andb_di( konami_state *cpustate )
+{
+ UINT8 t;
+ DIRBYTE(cpustate, t);
+ B &= t;
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $d5 BITB direct -**0- */
+INLINE void bitb_di( konami_state *cpustate )
+{
+ UINT8 t,r;
+ DIRBYTE(cpustate, t);
+ r = B & t;
+ CLR_NZV;
+ SET_NZ8(r);
+}
+
+/* $d6 LDB direct -**0- */
+INLINE void ldb_di( konami_state *cpustate )
+{
+ DIRBYTE(cpustate, B);
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $d7 STB direct -**0- */
+INLINE void stb_di( konami_state *cpustate )
+{
+ CLR_NZV;
+ SET_NZ8(B);
+ DIRECT(cpustate);
+ WM(cpustate, EAD,B);
+}
+
+/* $d8 EORB direct -**0- */
+INLINE void eorb_di( konami_state *cpustate )
+{
+ UINT8 t;
+ DIRBYTE(cpustate, t);
+ B ^= t;
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $d9 ADCB direct ***** */
+INLINE void adcb_di( konami_state *cpustate )
+{
+ UINT16 t,r;
+ DIRBYTE(cpustate, t);
+ r = B + t + (CC & CC_C);
+ CLR_HNZVC;
+ SET_FLAGS8(B,t,r);
+ SET_H(B,t,r);
+ B = r;
+}
+
+/* $dA ORB direct -**0- */
+INLINE void orb_di( konami_state *cpustate )
+{
+ UINT8 t;
+ DIRBYTE(cpustate, t);
+ B |= t;
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $dB ADDB direct ***** */
+INLINE void addb_di( konami_state *cpustate )
+{
+ UINT16 t,r;
+ DIRBYTE(cpustate, t);
+ r = B + t;
+ CLR_HNZVC;
+ SET_FLAGS8(B,t,r);
+ SET_H(B,t,r);
+ B = r;
+}
+
+/* $dC LDD direct -**0- */
+INLINE void ldd_di( konami_state *cpustate )
+{
+ DIRWORD(cpustate, pD);
+ CLR_NZV;
+ SET_NZ16(D);
+}
+
+/* $dD STD direct -**0- */
+INLINE void std_di( konami_state *cpustate )
+{
+ CLR_NZV;
+ SET_NZ16(D);
+ DIRECT(cpustate);
+ WM16(cpustate, EAD,&pD);
+}
+
+/* $dE LDU (LDS) direct -**0- */
+INLINE void ldu_di( konami_state *cpustate )
+{
+ DIRWORD(cpustate, pU);
+ CLR_NZV;
+ SET_NZ16(U);
+}
+
+/* $10dE LDS direct -**0- */
+INLINE void lds_di( konami_state *cpustate )
+{
+ DIRWORD(cpustate, pS);
+ CLR_NZV;
+ SET_NZ16(S);
+ cpustate->int_state |= KONAMI_LDS;
+}
+
+/* $dF STU (STS) direct -**0- */
+INLINE void stu_di( konami_state *cpustate )
+{
+ CLR_NZV;
+ SET_NZ16(U);
+ DIRECT(cpustate);
+ WM16(cpustate, EAD,&pU);
+}
+
+/* $10dF STS direct -**0- */
+INLINE void sts_di( konami_state *cpustate )
+{
+ CLR_NZV;
+ SET_NZ16(S);
+ DIRECT(cpustate);
+ WM16(cpustate, EAD,&pS);
+}
+
+/* $e0 SUBB indexed ?**** */
+INLINE void subb_ix( konami_state *cpustate )
+{
+ UINT16 t,r;
+ t = RM(cpustate, EAD);
+ r = B - t;
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+ B = r;
+}
+
+/* $e1 CMPB indexed ?**** */
+INLINE void cmpb_ix( konami_state *cpustate )
+{
+ UINT16 t,r;
+ t = RM(cpustate, EAD);
+ r = B - t;
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+}
+
+/* $e2 SBCB indexed ?**** */
+INLINE void sbcb_ix( konami_state *cpustate )
+{
+ UINT16 t,r;
+ t = RM(cpustate, EAD);
+ r = B - t - (CC & CC_C);
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+ B = r;
+}
+
+/* $e3 ADDD indexed -**** */
+INLINE void addd_ix( konami_state *cpustate )
+{
+ UINT32 r,d;
+ PAIR b;
+ b.d=RM16(cpustate, EAD);
+ d = D;
+ r = d + b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ D = r;
+}
+
+/* $e4 ANDB indexed -**0- */
+INLINE void andb_ix( konami_state *cpustate )
+{
+ B &= RM(cpustate, EAD);
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $e5 BITB indexed -**0- */
+INLINE void bitb_ix( konami_state *cpustate )
+{
+ UINT8 r;
+ r = B & RM(cpustate, EAD);
+ CLR_NZV;
+ SET_NZ8(r);
+}
+
+/* $e6 LDB indexed -**0- */
+INLINE void ldb_ix( konami_state *cpustate )
+{
+ B = RM(cpustate, EAD);
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $e7 STB indexed -**0- */
+INLINE void stb_ix( konami_state *cpustate )
+{
+ CLR_NZV;
+ SET_NZ8(B);
+ WM(cpustate, EAD,B);
+}
+
+/* $e8 EORB indexed -**0- */
+INLINE void eorb_ix( konami_state *cpustate )
+{
+ B ^= RM(cpustate, EAD);
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $e9 ADCB indexed ***** */
+INLINE void adcb_ix( konami_state *cpustate )
+{
+ UINT16 t,r;
+ t = RM(cpustate, EAD);
+ r = B + t + (CC & CC_C);
+ CLR_HNZVC;
+ SET_FLAGS8(B,t,r);
+ SET_H(B,t,r);
+ B = r;
+}
+
+/* $eA ORB indexed -**0- */
+INLINE void orb_ix( konami_state *cpustate )
+{
+ B |= RM(cpustate, EAD);
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $eb ADDB indexed ***** */
+INLINE void addb_ix( konami_state *cpustate )
+{
+ UINT16 t,r;
+ t = RM(cpustate, EAD);
+ r = B + t;
+ CLR_HNZVC;
+ SET_FLAGS8(B,t,r);
+ SET_H(B,t,r);
+ B = r;
+}
+
+/* $ec LDD indexed -**0- */
+INLINE void ldd_ix( konami_state *cpustate )
+{
+ D=RM16(cpustate, EAD);
+ CLR_NZV; SET_NZ16(D);
+}
+
+/* $eD STD indexed -**0- */
+INLINE void std_ix( konami_state *cpustate )
+{
+ CLR_NZV;
+ SET_NZ16(D);
+ WM16(cpustate, EAD,&pD);
+}
+
+/* $eE LDU (LDS) indexed -**0- */
+INLINE void ldu_ix( konami_state *cpustate )
+{
+ U=RM16(cpustate, EAD);
+ CLR_NZV;
+ SET_NZ16(U);
+}
+
+/* $10eE LDS indexed -**0- */
+INLINE void lds_ix( konami_state *cpustate )
+{
+ S=RM16(cpustate, EAD);
+ CLR_NZV;
+ SET_NZ16(S);
+ cpustate->int_state |= KONAMI_LDS;
+}
+
+/* $eF STU (STS) indexed -**0- */
+INLINE void stu_ix( konami_state *cpustate )
+{
+ CLR_NZV;
+ SET_NZ16(U);
+ WM16(cpustate, EAD,&pU);
+}
+
+/* $10eF STS indexed -**0- */
+INLINE void sts_ix( konami_state *cpustate )
+{
+ CLR_NZV;
+ SET_NZ16(S);
+ WM16(cpustate, EAD,&pS);
+}
+
+/* $f0 SUBB extended ?**** */
+INLINE void subb_ex( konami_state *cpustate )
+{
+ UINT16 t,r;
+ EXTBYTE(cpustate, t);
+ r = B - t;
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+ B = r;
+}
+
+/* $f1 CMPB extended ?**** */
+INLINE void cmpb_ex( konami_state *cpustate )
+{
+ UINT16 t,r;
+ EXTBYTE(cpustate, t);
+ r = B - t;
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+}
+
+/* $f2 SBCB extended ?**** */
+INLINE void sbcb_ex( konami_state *cpustate )
+{
+ UINT16 t,r;
+ EXTBYTE(cpustate, t);
+ r = B - t - (CC & CC_C);
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+ B = r;
+}
+
+/* $f3 ADDD extended -**** */
+INLINE void addd_ex( konami_state *cpustate )
+{
+ UINT32 r,d;
+ PAIR b;
+ EXTWORD(cpustate, b);
+ d = D;
+ r = d + b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ D = r;
+}
+
+/* $f4 ANDB extended -**0- */
+INLINE void andb_ex( konami_state *cpustate )
+{
+ UINT8 t;
+ EXTBYTE(cpustate, t);
+ B &= t;
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $f5 BITB extended -**0- */
+INLINE void bitb_ex( konami_state *cpustate )
+{
+ UINT8 t,r;
+ EXTBYTE(cpustate, t);
+ r = B & t;
+ CLR_NZV;
+ SET_NZ8(r);
+}
+
+/* $f6 LDB extended -**0- */
+INLINE void ldb_ex( konami_state *cpustate )
+{
+ EXTBYTE(cpustate, B);
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $f7 STB extended -**0- */
+INLINE void stb_ex( konami_state *cpustate )
+{
+ CLR_NZV;
+ SET_NZ8(B);
+ EXTENDED(cpustate);
+ WM(cpustate, EAD,B);
+}
+
+/* $f8 EORB extended -**0- */
+INLINE void eorb_ex( konami_state *cpustate )
+{
+ UINT8 t;
+ EXTBYTE(cpustate, t);
+ B ^= t;
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $f9 ADCB extended ***** */
+INLINE void adcb_ex( konami_state *cpustate )
+{
+ UINT16 t,r;
+ EXTBYTE(cpustate, t);
+ r = B + t + (CC & CC_C);
+ CLR_HNZVC;
+ SET_FLAGS8(B,t,r);
+ SET_H(B,t,r);
+ B = r;
+}
+
+/* $fA ORB extended -**0- */
+INLINE void orb_ex( konami_state *cpustate )
+{
+ UINT8 t;
+ EXTBYTE(cpustate, t);
+ B |= t;
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $fB ADDB extended ***** */
+INLINE void addb_ex( konami_state *cpustate )
+{
+ UINT16 t,r;
+ EXTBYTE(cpustate, t);
+ r = B + t;
+ CLR_HNZVC;
+ SET_FLAGS8(B,t,r);
+ SET_H(B,t,r);
+ B = r;
+}
+
+/* $fC LDD extended -**0- */
+INLINE void ldd_ex( konami_state *cpustate )
+{
+ EXTWORD(cpustate, pD);
+ CLR_NZV;
+ SET_NZ16(D);
+}
+
+/* $fD STD extended -**0- */
+INLINE void std_ex( konami_state *cpustate )
+{
+ CLR_NZV;
+ SET_NZ16(D);
+ EXTENDED(cpustate);
+ WM16(cpustate, EAD,&pD);
+}
+
+/* $fE LDU (LDS) extended -**0- */
+INLINE void ldu_ex( konami_state *cpustate )
+{
+ EXTWORD(cpustate, pU);
+ CLR_NZV;
+ SET_NZ16(U);
+}
+
+/* $10fE LDS extended -**0- */
+INLINE void lds_ex( konami_state *cpustate )
+{
+ EXTWORD(cpustate, pS);
+ CLR_NZV;
+ SET_NZ16(S);
+ cpustate->int_state |= KONAMI_LDS;
+}
+
+/* $fF STU (STS) extended -**0- */
+INLINE void stu_ex( konami_state *cpustate )
+{
+ CLR_NZV;
+ SET_NZ16(U);
+ EXTENDED(cpustate);
+ WM16(cpustate, EAD,&pU);
+}
+
+/* $10fF STS extended -**0- */
+INLINE void sts_ex( konami_state *cpustate )
+{
+ CLR_NZV;
+ SET_NZ16(S);
+ EXTENDED(cpustate);
+ WM16(cpustate, EAD,&pS);
+}
+
+INLINE void setline_im( konami_state *cpustate )
+{
+ UINT8 t;
+ IMMBYTE(cpustate, t);
+
+ if ( cpustate->setlines_callback )
+ (*cpustate->setlines_callback)( cpustate->device, t );
+}
+
+INLINE void setline_ix( konami_state *cpustate )
+{
+ UINT8 t;
+ t = RM(cpustate, EA);
+
+ if ( cpustate->setlines_callback )
+ (*cpustate->setlines_callback)( cpustate->device, t );
+}
+
+INLINE void setline_di( konami_state *cpustate )
+{
+ UINT8 t;
+ DIRBYTE(cpustate, t);
+
+ if ( cpustate->setlines_callback )
+ (*cpustate->setlines_callback)( cpustate->device, t );
+}
+
+INLINE void setline_ex( konami_state *cpustate )
+{
+ UINT8 t;
+ EXTBYTE(cpustate, t);
+
+ if ( cpustate->setlines_callback )
+ (*cpustate->setlines_callback)( cpustate->device, t );
+}
+
+INLINE void bmove( konami_state *cpustate )
+{
+ UINT8 t;
+
+ while( U != 0 ) {
+ t = RM(cpustate, Y);
+ WM(cpustate, X,t);
+ Y++;
+ X++;
+ U--;
+ cpustate->icount -= 2;
+ }
+}
+
+INLINE void move( konami_state *cpustate )
+{
+ UINT8 t;
+
+ t = RM(cpustate, Y);
+ WM(cpustate, X,t);
+ Y++;
+ X++;
+ U--;
+}
+
+/* CLRD inherent -0100 */
+INLINE void clrd( konami_state *cpustate )
+{
+ D = 0;
+ CLR_NZVC; SEZ;
+}
+
+/* CLRW indexed -0100 */
+INLINE void clrw_ix( konami_state *cpustate )
+{
+ PAIR t;
+ t.d = 0;
+ WM16(cpustate, EAD,&t);
+ CLR_NZVC; SEZ;
+}
+
+/* CLRW direct -0100 */
+INLINE void clrw_di( konami_state *cpustate )
+{
+ PAIR t;
+ t.d = 0;
+ DIRECT(cpustate);
+ WM16(cpustate, EAD,&t);
+ CLR_NZVC;
+ SEZ;
+}
+
+/* CLRW extended -0100 */
+INLINE void clrw_ex( konami_state *cpustate )
+{
+ PAIR t;
+ t.d = 0;
+ EXTENDED(cpustate);
+ WM16(cpustate, EAD,&t);
+ CLR_NZVC; SEZ;
+}
+
+/* LSRD immediate -0*-* */
+INLINE void lsrd( konami_state *cpustate )
+{
+ UINT8 t;
+
+ IMMBYTE(cpustate, t );
+
+ while ( t-- ) {
+ CLR_NZC;
+ CC |= (D & CC_C);
+ D >>= 1;
+ SET_Z16(D);
+ }
+}
+
+/* RORD immediate -**-* */
+INLINE void rord( konami_state *cpustate )
+{
+ UINT16 r;
+ UINT8 t;
+
+ IMMBYTE(cpustate, t);
+
+ while ( t-- ) {
+ r = (CC & CC_C) << 15;
+ CLR_NZC;
+ CC |= (D & CC_C);
+ r |= D >> 1;
+ SET_NZ16(r);
+ D = r;
+ }
+}
+
+/* ASRD immediate ?**-* */
+INLINE void asrd( konami_state *cpustate )
+{
+ UINT8 t;
+
+ IMMBYTE(cpustate, t);
+
+ while ( t-- ) {
+ CLR_NZC;
+ CC |= (D & CC_C);
+ D = (D & 0x8000) | (D >> 1);
+ SET_NZ16(D);
+ }
+}
+
+/* ASLD immediate ?**** */
+INLINE void asld( konami_state *cpustate )
+{
+ UINT32 r;
+ UINT8 t;
+
+ IMMBYTE(cpustate, t );
+
+ while ( t-- ) {
+ r = D << 1;
+ CLR_NZVC;
+ SET_FLAGS16(D,D,r);
+ D = r;
+ }
+}
+
+/* ROLD immediate -**-* */
+INLINE void rold( konami_state *cpustate )
+{
+ UINT16 r;
+ UINT8 t;
+
+ IMMBYTE(cpustate, t);
+
+ while ( t-- ) {
+ CLR_NZC;
+ if ( D & 0x8000 ) SEC;
+ r = CC & CC_C;
+ r |= D << 1;
+ SET_NZ16(r);
+ D = r;
+ }
+}
+
+/* DECB,JNZ relative ----- */
+INLINE void decbjnz( konami_state *cpustate )
+{
+ --B;
+ CLR_NZV;
+ SET_FLAGS8D(B);
+ BRANCH(cpustate, !(CC&CC_Z) );
+}
+
+/* DECX,JNZ relative ----- */
+INLINE void decxjnz( konami_state *cpustate )
+{
+ --X;
+ CLR_NZV;
+ SET_NZ16(X); /* should affect V as well? */
+ BRANCH(cpustate, !(CC&CC_Z) );
+}
+
+INLINE void bset( konami_state *cpustate )
+{
+ UINT8 t;
+
+ while( U != 0 ) {
+ t = A;
+ WM(cpustate, XD,t);
+ X++;
+ U--;
+ cpustate->icount -= 2;
+ }
+}
+
+INLINE void bset2( konami_state *cpustate )
+{
+ while( U != 0 ) {
+ WM16(cpustate, XD,&pD);
+ X += 2;
+ U--;
+ cpustate->icount -= 3;
+ }
+}
+
+/* LMUL inherent --*-@ */
+INLINE void lmul( konami_state *cpustate )
+{
+ UINT32 t;
+ t = X * Y;
+ X = (t >> 16);
+ Y = (t & 0xffff);
+ CLR_ZC; SET_Z(t); if( t & 0x8000 ) SEC;
+}
+
+/* DIVX inherent --*-@ */
+INLINE void divx( konami_state *cpustate )
+{
+ UINT16 t;
+ UINT8 r;
+ if ( B != 0 )
+ {
+ t = X / B;
+ r = X % B;
+ }
+ else
+ {
+ /* ?? */
+ t = 0;
+ r = 0;
+ }
+ CLR_ZC; SET_Z16(t); if ( t & 0x80 ) SEC;
+ X = t;
+ B = r;
+}
+
+/* INCD inherent -***- */
+INLINE void incd( konami_state *cpustate )
+{
+ UINT32 r;
+ r = D + 1;
+ CLR_NZV;
+ SET_FLAGS16(D,D,r);
+ D = r;
+}
+
+/* INCW direct -***- */
+INLINE void incw_di( konami_state *cpustate )
+{
+ PAIR t,r;
+ DIRWORD(cpustate, t);
+ r = t;
+ ++r.d;
+ CLR_NZV;
+ SET_FLAGS16(t.d, t.d, r.d);
+ WM16(cpustate, EAD,&r);
+}
+
+/* INCW indexed -***- */
+INLINE void incw_ix( konami_state *cpustate )
+{
+ PAIR t,r;
+ t.d=RM16(cpustate, EAD);
+ r = t;
+ ++r.d;
+ CLR_NZV;
+ SET_FLAGS16(t.d, t.d, r.d);
+ WM16(cpustate, EAD,&r);
+}
+
+/* INCW extended -***- */
+INLINE void incw_ex( konami_state *cpustate )
+{
+ PAIR t, r;
+ EXTWORD(cpustate, t);
+ r = t;
+ ++r.d;
+ CLR_NZV; SET_FLAGS16(t.d,t.d,r.d);
+ WM16(cpustate, EAD,&r);
+}
+
+/* DECD inherent -***- */
+INLINE void decd( konami_state *cpustate )
+{
+ UINT32 r;
+ r = D - 1;
+ CLR_NZV;
+ SET_FLAGS16(D,D,r);
+ D = r;
+}
+
+/* DECW direct -***- */
+INLINE void decw_di( konami_state *cpustate )
+{
+ PAIR t,r;
+ DIRWORD(cpustate, t);
+ r = t;
+ --r.d;
+ CLR_NZV;
+ SET_FLAGS16(t.d, t.d, r.d);
+ WM16(cpustate, EAD,&r);
+}
+
+/* DECW indexed -***- */
+INLINE void decw_ix( konami_state *cpustate )
+{
+ PAIR t, r;
+ t.d=RM16(cpustate, EAD);
+ r = t;
+ --r.d;
+ CLR_NZV; SET_FLAGS16(t.d, t.d, r.d);
+ WM16(cpustate, EAD,&r);
+}
+
+/* DECW extended -***- */
+INLINE void decw_ex( konami_state *cpustate )
+{
+ PAIR t, r;
+ EXTWORD(cpustate, t);
+ r = t;
+ --r.d;
+ CLR_NZV; SET_FLAGS16(t.d,t.d,r.d);
+ WM16(cpustate, EAD,&r);
+}
+
+/* TSTD inherent -**0- */
+INLINE void tstd( konami_state *cpustate )
+{
+ CLR_NZV;
+ SET_NZ16(D);
+}
+
+/* TSTW direct -**0- */
+INLINE void tstw_di( konami_state *cpustate )
+{
+ PAIR t;
+ CLR_NZV;
+ DIRWORD(cpustate, t);
+ SET_NZ16(t.d);
+}
+
+/* TSTW indexed -**0- */
+INLINE void tstw_ix( konami_state *cpustate )
+{
+ PAIR t;
+ CLR_NZV;
+ t.d=RM16(cpustate, EAD);
+ SET_NZ16(t.d);
+}
+
+/* TSTW extended -**0- */
+INLINE void tstw_ex( konami_state *cpustate )
+{
+ PAIR t;
+ CLR_NZV;
+ EXTWORD(cpustate, t);
+ SET_NZ16(t.d);
+}
+
+/* LSRW direct -0*-* */
+INLINE void lsrw_di( konami_state *cpustate )
+{
+ PAIR t;
+ DIRWORD(cpustate, t);
+ CLR_NZC;
+ CC |= (t.d & CC_C);
+ t.d >>= 1;
+ SET_Z16(t.d);
+ WM16(cpustate, EAD,&t);
+}
+
+/* LSRW indexed -0*-* */
+INLINE void lsrw_ix( konami_state *cpustate )
+{
+ PAIR t;
+ t.d=RM16(cpustate, EAD);
+ CLR_NZC;
+ CC |= (t.d & CC_C);
+ t.d >>= 1;
+ SET_Z16(t.d);
+ WM16(cpustate, EAD,&t);
+}
+
+/* LSRW extended -0*-* */
+INLINE void lsrw_ex( konami_state *cpustate )
+{
+ PAIR t;
+ EXTWORD(cpustate, t);
+ CLR_NZC;
+ CC |= (t.d & CC_C);
+ t.d >>= 1;
+ SET_Z16(t.d);
+ WM16(cpustate, EAD,&t);
+}
+
+/* RORW direct -**-* */
+INLINE void rorw_di( konami_state *cpustate )
+{
+ PAIR t,r;
+ DIRWORD(cpustate, t);
+ r.d = (CC & CC_C) << 15;
+ CLR_NZC;
+ CC |= (t.d & CC_C);
+ r.d |= t.d>>1;
+ SET_NZ16(r.d);
+ WM16(cpustate, EAD,&r);
+}
+
+/* RORW indexed -**-* */
+INLINE void rorw_ix( konami_state *cpustate )
+{
+ PAIR t,r;
+ t.d=RM16(cpustate, EAD);
+ r.d = (CC & CC_C) << 15;
+ CLR_NZC;
+ CC |= (t.d & CC_C);
+ r.d |= t.d>>1;
+ SET_NZ16(r.d);
+ WM16(cpustate, EAD,&r);
+}
+
+/* RORW extended -**-* */
+INLINE void rorw_ex( konami_state *cpustate )
+{
+ PAIR t,r;
+ EXTWORD(cpustate, t);
+ r.d = (CC & CC_C) << 15;
+ CLR_NZC;
+ CC |= (t.d & CC_C);
+ r.d |= t.d>>1;
+ SET_NZ16(r.d);
+ WM16(cpustate, EAD,&r);
+}
+
+/* ASRW direct ?**-* */
+INLINE void asrw_di( konami_state *cpustate )
+{
+ PAIR t;
+ DIRWORD(cpustate, t);
+ CLR_NZC;
+ CC |= (t.d & CC_C);
+ t.d = (t.d & 0x8000) | (t.d >> 1);
+ SET_NZ16(t.d);
+ WM16(cpustate, EAD,&t);
+}
+
+/* ASRW indexed ?**-* */
+INLINE void asrw_ix( konami_state *cpustate )
+{
+ PAIR t;
+ t.d=RM16(cpustate, EAD);
+ CLR_NZC;
+ CC |= (t.d & CC_C);
+ t.d = (t.d & 0x8000) | (t.d >> 1);
+ SET_NZ16(t.d);
+ WM16(cpustate, EAD,&t);
+}
+
+/* ASRW extended ?**-* */
+INLINE void asrw_ex( konami_state *cpustate )
+{
+ PAIR t;
+ EXTWORD(cpustate, t);
+ CLR_NZC;
+ CC |= (t.d & CC_C);
+ t.d = (t.d & 0x8000) | (t.d >> 1);
+ SET_NZ16(t.d);
+ WM16(cpustate, EAD,&t);
+}
+
+/* ASLW direct ?**** */
+INLINE void aslw_di( konami_state *cpustate )
+{
+ PAIR t,r;
+ DIRWORD(cpustate, t);
+ r.d = t.d << 1;
+ CLR_NZVC;
+ SET_FLAGS16(t.d,t.d,r.d);
+ WM16(cpustate, EAD,&r);
+}
+
+/* ASLW indexed ?**** */
+INLINE void aslw_ix( konami_state *cpustate )
+{
+ PAIR t,r;
+ t.d=RM16(cpustate, EAD);
+ r.d = t.d << 1;
+ CLR_NZVC;
+ SET_FLAGS16(t.d,t.d,r.d);
+ WM16(cpustate, EAD,&r);
+}
+
+/* ASLW extended ?**** */
+INLINE void aslw_ex( konami_state *cpustate )
+{
+ PAIR t,r;
+ EXTWORD(cpustate, t);
+ r.d = t.d << 1;
+ CLR_NZVC;
+ SET_FLAGS16(t.d,t.d,r.d);
+ WM16(cpustate, EAD,&r);
+}
+
+/* ROLW direct -**** */
+INLINE void rolw_di( konami_state *cpustate )
+{
+ PAIR t,r;
+ DIRWORD(cpustate, t);
+ r.d = (CC & CC_C) | (t.d << 1);
+ CLR_NZVC;
+ SET_FLAGS16(t.d,t.d,r.d);
+ WM16(cpustate, EAD,&r);
+}
+
+/* ROLW indexed -**** */
+INLINE void rolw_ix( konami_state *cpustate )
+{
+ PAIR t,r;
+ t.d=RM16(cpustate, EAD);
+ r.d = (CC & CC_C) | (t.d << 1);
+ CLR_NZVC;
+ SET_FLAGS16(t.d,t.d,r.d);
+ WM16(cpustate, EAD,&r);
+}
+
+/* ROLW extended -**** */
+INLINE void rolw_ex( konami_state *cpustate )
+{
+ PAIR t,r;
+ EXTWORD(cpustate, t);
+ r.d = (CC & CC_C) | (t.d << 1);
+ CLR_NZVC;
+ SET_FLAGS16(t.d,t.d,r.d);
+ WM16(cpustate, EAD,&r);
+}
+
+/* NEGD inherent ?**** */
+INLINE void negd( konami_state *cpustate )
+{
+ UINT32 r;
+ r = -D;
+ CLR_NZVC;
+ SET_FLAGS16(0,D,r);
+ D = r;
+}
+
+/* NEGW direct ?**** */
+INLINE void negw_di( konami_state *cpustate )
+{
+ PAIR r,t;
+ DIRWORD(cpustate, t);
+ r.d = -t.d;
+ CLR_NZVC;
+ SET_FLAGS16(0,t.d,r.d);
+ WM16(cpustate, EAD,&r);
+}
+
+/* NEGW indexed ?**** */
+INLINE void negw_ix( konami_state *cpustate )
+{
+ PAIR r,t;
+ t.d=RM16(cpustate, EAD);
+ r.d = -t.d;
+ CLR_NZVC;
+ SET_FLAGS16(0,t.d,r.d);
+ WM16(cpustate, EAD,&r);
+}
+
+/* NEGW extended ?**** */
+INLINE void negw_ex( konami_state *cpustate )
+{
+ PAIR r,t;
+ EXTWORD(cpustate, t);
+ r.d = -t.d;
+ CLR_NZVC;
+ SET_FLAGS16(0,t.d,r.d);
+ WM16(cpustate, EAD,&r);
+}
+
+/* ABSA inherent ?**** */
+INLINE void absa( konami_state *cpustate )
+{
+ UINT16 r;
+ if (A & 0x80)
+ r = -A;
+ else
+ r = A;
+ CLR_NZVC;
+ SET_FLAGS8(0,A,r);
+ A = r;
+}
+
+/* ABSB inherent ?**** */
+INLINE void absb( konami_state *cpustate )
+{
+ UINT16 r;
+ if (B & 0x80)
+ r = -B;
+ else
+ r = B;
+ CLR_NZVC;
+ SET_FLAGS8(0,B,r);
+ B = r;
+}
+
+/* ABSD inherent ?**** */
+INLINE void absd( konami_state *cpustate )
+{
+ UINT32 r;
+ if (D & 0x8000)
+ r = -D;
+ else
+ r = D;
+ CLR_NZVC;
+ SET_FLAGS16(0,D,r);
+ D = r;
+}
+
+/* LSRD direct -0*-* */
+INLINE void lsrd_di( konami_state *cpustate )
+{
+ UINT8 t;
+
+ DIRBYTE(cpustate, t );
+
+ while ( t-- ) {
+ CLR_NZC;
+ CC |= (D & CC_C);
+ D >>= 1;
+ SET_Z16(D);
+ }
+}
+
+/* RORD direct -**-* */
+INLINE void rord_di( konami_state *cpustate )
+{
+ UINT16 r;
+ UINT8 t;
+
+ DIRBYTE(cpustate, t);
+
+ while ( t-- ) {
+ r = (CC & CC_C) << 15;
+ CLR_NZC;
+ CC |= (D & CC_C);
+ r |= D >> 1;
+ SET_NZ16(r);
+ D = r;
+ }
+}
+
+/* ASRD direct ?**-* */
+INLINE void asrd_di( konami_state *cpustate )
+{
+ UINT8 t;
+
+ DIRBYTE(cpustate, t);
+
+ while ( t-- ) {
+ CLR_NZC;
+ CC |= (D & CC_C);
+ D = (D & 0x8000) | (D >> 1);
+ SET_NZ16(D);
+ }
+}
+
+/* ASLD direct ?**** */
+INLINE void asld_di( konami_state *cpustate )
+{
+ UINT32 r;
+ UINT8 t;
+
+ DIRBYTE(cpustate, t );
+
+ while ( t-- ) {
+ r = D << 1;
+ CLR_NZVC;
+ SET_FLAGS16(D,D,r);
+ D = r;
+ }
+}
+
+/* ROLD direct -**-* */
+INLINE void rold_di( konami_state *cpustate )
+{
+ UINT16 r;
+ UINT8 t;
+
+ DIRBYTE(cpustate, t);
+
+ while ( t-- ) {
+ CLR_NZC;
+ if ( D & 0x8000 ) SEC;
+ r = CC & CC_C;
+ r |= D << 1;
+ SET_NZ16(r);
+ D = r;
+ }
+}
+
+/* LSRD indexed -0*-* */
+INLINE void lsrd_ix( konami_state *cpustate )
+{
+ UINT8 t;
+
+ t=RM(cpustate, EA);
+
+ while ( t-- ) {
+ CLR_NZC;
+ CC |= (D & CC_C);
+ D >>= 1;
+ SET_Z16(D);
+ }
+}
+
+/* RORD indexed -**-* */
+INLINE void rord_ix( konami_state *cpustate )
+{
+ UINT16 r;
+ UINT8 t;
+
+ t=RM(cpustate, EA);
+
+ while ( t-- ) {
+ r = (CC & CC_C) << 15;
+ CLR_NZC;
+ CC |= (D & CC_C);
+ r |= D >> 1;
+ SET_NZ16(r);
+ D = r;
+ }
+}
+
+/* ASRD indexed ?**-* */
+INLINE void asrd_ix( konami_state *cpustate )
+{
+ UINT8 t;
+
+ t=RM(cpustate, EA);
+
+ while ( t-- ) {
+ CLR_NZC;
+ CC |= (D & CC_C);
+ D = (D & 0x8000) | (D >> 1);
+ SET_NZ16(D);
+ }
+}
+
+/* ASLD indexed ?**** */
+INLINE void asld_ix( konami_state *cpustate )
+{
+ UINT32 r;
+ UINT8 t;
+
+ t=RM(cpustate, EA);
+
+ while ( t-- ) {
+ r = D << 1;
+ CLR_NZVC;
+ SET_FLAGS16(D,D,r);
+ D = r;
+ }
+}
+
+/* ROLD indexed -**-* */
+INLINE void rold_ix( konami_state *cpustate )
+{
+ UINT16 r;
+ UINT8 t;
+
+ t=RM(cpustate, EA);
+
+ while ( t-- ) {
+ CLR_NZC;
+ if ( D & 0x8000 ) SEC;
+ r = CC & CC_C;
+ r |= D << 1;
+ SET_NZ16(r);
+ D = r;
+ }
+}
+
+/* LSRD extended -0*-* */
+INLINE void lsrd_ex( konami_state *cpustate )
+{
+ UINT8 t;
+
+ EXTBYTE(cpustate, t);
+
+ while ( t-- ) {
+ CLR_NZC;
+ CC |= (D & CC_C);
+ D >>= 1;
+ SET_Z16(D);
+ }
+}
+
+/* RORD extended -**-* */
+INLINE void rord_ex( konami_state *cpustate )
+{
+ UINT16 r;
+ UINT8 t;
+
+ EXTBYTE(cpustate, t);
+
+ while ( t-- ) {
+ r = (CC & CC_C) << 15;
+ CLR_NZC;
+ CC |= (D & CC_C);
+ r |= D >> 1;
+ SET_NZ16(r);
+ D = r;
+ }
+}
+
+/* ASRD extended ?**-* */
+INLINE void asrd_ex( konami_state *cpustate )
+{
+ UINT8 t;
+
+ EXTBYTE(cpustate, t);
+
+ while ( t-- ) {
+ CLR_NZC;
+ CC |= (D & CC_C);
+ D = (D & 0x8000) | (D >> 1);
+ SET_NZ16(D);
+ }
+}
+
+/* ASLD extended ?**** */
+INLINE void asld_ex( konami_state *cpustate )
+{
+ UINT32 r;
+ UINT8 t;
+
+ EXTBYTE(cpustate, t);
+
+ while ( t-- ) {
+ r = D << 1;
+ CLR_NZVC;
+ SET_FLAGS16(D,D,r);
+ D = r;
+ }
+}
+
+/* ROLD extended -**-* */
+INLINE void rold_ex( konami_state *cpustate )
+{
+ UINT16 r;
+ UINT8 t;
+
+ EXTBYTE(cpustate, t);
+
+ while ( t-- ) {
+ CLR_NZC;
+ if ( D & 0x8000 ) SEC;
+ r = CC & CC_C;
+ r |= D << 1;
+ SET_NZ16(r);
+ D = r;
+ }
+}
+
+INLINE void opcode2( konami_state *cpustate )
+{
+ UINT8 ireg2 = ROP_ARG(cpustate, PCD);
+ PC++;
+
+ switch ( ireg2 ) {
+// case 0x00: EA=0; break; /* auto increment */
+// case 0x01: EA=0; break; /* double auto increment */
+// case 0x02: EA=0; break; /* auto decrement */
+// case 0x03: EA=0; break; /* double auto decrement */
+// case 0x04: EA=0; break; /* postbyte offs */
+// case 0x05: EA=0; break; /* postword offs */
+// case 0x06: EA=0; break; /* normal */
+ case 0x07:
+ EAD=0;
+ (*konami_extended[cpustate->ireg])(cpustate);
+ cpustate->icount -= 2;
+ return;
+// case 0x08: EA=0; break; /* indirect - auto increment */
+// case 0x09: EA=0; break; /* indirect - double auto increment */
+// case 0x0a: EA=0; break; /* indirect - auto decrement */
+// case 0x0b: EA=0; break; /* indirect - double auto decrement */
+// case 0x0c: EA=0; break; /* indirect - postbyte offs */
+// case 0x0d: EA=0; break; /* indirect - postword offs */
+// case 0x0e: EA=0; break; /* indirect - normal */
+ case 0x0f: /* indirect - extended */
+ IMMWORD(cpustate, cpustate->ea);
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=4;
+ break;
+// case 0x10: EA=0; break; /* auto increment */
+// case 0x11: EA=0; break; /* double auto increment */
+// case 0x12: EA=0; break; /* auto decrement */
+// case 0x13: EA=0; break; /* double auto decrement */
+// case 0x14: EA=0; break; /* postbyte offs */
+// case 0x15: EA=0; break; /* postword offs */
+// case 0x16: EA=0; break; /* normal */
+// case 0x17: EA=0; break; /* extended */
+// case 0x18: EA=0; break; /* indirect - auto increment */
+// case 0x19: EA=0; break; /* indirect - double auto increment */
+// case 0x1a: EA=0; break; /* indirect - auto decrement */
+// case 0x1b: EA=0; break; /* indirect - double auto decrement */
+// case 0x1c: EA=0; break; /* indirect - postbyte offs */
+// case 0x1d: EA=0; break; /* indirect - postword offs */
+// case 0x1e: EA=0; break; /* indirect - normal */
+// case 0x1f: EA=0; break; /* indirect - extended */
+
+/* base X */
+ case 0x20: /* auto increment */
+ EA=X;
+ X++;
+ cpustate->icount-=2;
+ break;
+ case 0x21: /* double auto increment */
+ EA=X;
+ X+=2;
+ cpustate->icount-=3;
+ break;
+ case 0x22: /* auto decrement */
+ X--;
+ EA=X;
+ cpustate->icount-=2;
+ break;
+ case 0x23: /* double auto decrement */
+ X-=2;
+ EA=X;
+ cpustate->icount-=3;
+ break;
+ case 0x24: /* postbyte offs */
+ IMMBYTE(cpustate, EA);
+ EA=X+SIGNED(EA);
+ cpustate->icount-=2;
+ break;
+ case 0x25: /* postword offs */
+ IMMWORD(cpustate, cpustate->ea);
+ EA+=X;
+ cpustate->icount-=4;
+ break;
+ case 0x26: /* normal */
+ EA=X;
+ break;
+// case 0x27: EA=0; break; /* extended */
+ case 0x28: /* indirect - auto increment */
+ EA=X;
+ X++;
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=5;
+ break;
+ case 0x29: /* indirect - double auto increment */
+ EA=X;
+ X+=2;
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=6;
+ break;
+ case 0x2a: /* indirect - auto decrement */
+ X--;
+ EA=X;
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=5;
+ break;
+ case 0x2b: /* indirect - double auto decrement */
+ X-=2;
+ EA=X;
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=6;
+ break;
+ case 0x2c: /* indirect - postbyte offs */
+ IMMBYTE(cpustate, EA);
+ EA=X+SIGNED(EA);
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=4;
+ break;
+ case 0x2d: /* indirect - postword offs */
+ IMMWORD(cpustate, cpustate->ea);
+ EA+=X;
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=7;
+ break;
+ case 0x2e: /* indirect - normal */
+ EA=X;
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=3;
+ break;
+// case 0x2f: EA=0; break; /* indirect - extended */
+
+/* base Y */
+ case 0x30: /* auto increment */
+ EA=Y;
+ Y++;
+ cpustate->icount-=2;
+ break;
+ case 0x31: /* double auto increment */
+ EA=Y;
+ Y+=2;
+ cpustate->icount-=3;
+ break;
+ case 0x32: /* auto decrement */
+ Y--;
+ EA=Y;
+ cpustate->icount-=2;
+ break;
+ case 0x33: /* double auto decrement */
+ Y-=2;
+ EA=Y;
+ cpustate->icount-=3;
+ break;
+ case 0x34: /* postbyte offs */
+ IMMBYTE(cpustate, EA);
+ EA=Y+SIGNED(EA);
+ cpustate->icount-=2;
+ break;
+ case 0x35: /* postword offs */
+ IMMWORD(cpustate, cpustate->ea);
+ EA+=Y;
+ cpustate->icount-=4;
+ break;
+ case 0x36: /* normal */
+ EA=Y;
+ break;
+// case 0x37: EA=0; break; /* extended */
+ case 0x38: /* indirect - auto increment */
+ EA=Y;
+ Y++;
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=5;
+ break;
+ case 0x39: /* indirect - double auto increment */
+ EA=Y;
+ Y+=2;
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=6;
+ break;
+ case 0x3a: /* indirect - auto decrement */
+ Y--;
+ EA=Y;
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=5;
+ break;
+ case 0x3b: /* indirect - double auto decrement */
+ Y-=2;
+ EA=Y;
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=6;
+ break;
+ case 0x3c: /* indirect - postbyte offs */
+ IMMBYTE(cpustate, EA);
+ EA=Y+SIGNED(EA);
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=4;
+ break;
+ case 0x3d: /* indirect - postword offs */
+ IMMWORD(cpustate, cpustate->ea);
+ EA+=Y;
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=7;
+ break;
+ case 0x3e: /* indirect - normal */
+ EA=Y;
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=3;
+ break;
+// case 0x3f: EA=0; break; /* indirect - extended */
+
+// case 0x40: EA=0; break; /* auto increment */
+// case 0x41: EA=0; break; /* double auto increment */
+// case 0x42: EA=0; break; /* auto decrement */
+// case 0x43: EA=0; break; /* double auto decrement */
+// case 0x44: EA=0; break; /* postbyte offs */
+// case 0x45: EA=0; break; /* postword offs */
+// case 0x46: EA=0; break; /* normal */
+// case 0x47: EA=0; break; /* extended */
+// case 0x48: EA=0; break; /* indirect - auto increment */
+// case 0x49: EA=0; break; /* indirect - double auto increment */
+// case 0x4a: EA=0; break; /* indirect - auto decrement */
+// case 0x4b: EA=0; break; /* indirect - double auto decrement */
+// case 0x4c: EA=0; break; /* indirect - postbyte offs */
+// case 0x4d: EA=0; break; /* indirect - postword offs */
+// case 0x4e: EA=0; break; /* indirect - normal */
+// case 0x4f: EA=0; break; /* indirect - extended */
+
+/* base U */
+ case 0x50: /* auto increment */
+ EA=U;
+ U++;
+ cpustate->icount-=2;
+ break;
+ case 0x51: /* double auto increment */
+ EA=U;
+ U+=2;
+ cpustate->icount-=3;
+ break;
+ case 0x52: /* auto decrement */
+ U--;
+ EA=U;
+ cpustate->icount-=2;
+ break;
+ case 0x53: /* double auto decrement */
+ U-=2;
+ EA=U;
+ cpustate->icount-=3;
+ break;
+ case 0x54: /* postbyte offs */
+ IMMBYTE(cpustate, EA);
+ EA=U+SIGNED(EA);
+ cpustate->icount-=2;
+ break;
+ case 0x55: /* postword offs */
+ IMMWORD(cpustate, cpustate->ea);
+ EA+=U;
+ cpustate->icount-=4;
+ break;
+ case 0x56: /* normal */
+ EA=U;
+ break;
+// case 0x57: EA=0; break; /* extended */
+ case 0x58: /* indirect - auto increment */
+ EA=U;
+ U++;
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=5;
+ break;
+ case 0x59: /* indirect - double auto increment */
+ EA=U;
+ U+=2;
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=6;
+ break;
+ case 0x5a: /* indirect - auto decrement */
+ U--;
+ EA=U;
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=5;
+ break;
+ case 0x5b: /* indirect - double auto decrement */
+ U-=2;
+ EA=U;
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=6;
+ break;
+ case 0x5c: /* indirect - postbyte offs */
+ IMMBYTE(cpustate, EA);
+ EA=U+SIGNED(EA);
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=4;
+ break;
+ case 0x5d: /* indirect - postword offs */
+ IMMWORD(cpustate, cpustate->ea);
+ EA+=U;
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=7;
+ break;
+ case 0x5e: /* indirect - normal */
+ EA=U;
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=3;
+ break;
+// case 0x5f: EA=0; break; /* indirect - extended */
+
+/* base S */
+ case 0x60: /* auto increment */
+ EAD=SD;
+ S++;
+ cpustate->icount-=2;
+ break;
+ case 0x61: /* double auto increment */
+ EAD=SD;
+ S+=2;
+ cpustate->icount-=3;
+ break;
+ case 0x62: /* auto decrement */
+ S--;
+ EAD=SD;
+ cpustate->icount-=2;
+ break;
+ case 0x63: /* double auto decrement */
+ S-=2;
+ EAD=SD;
+ cpustate->icount-=3;
+ break;
+ case 0x64: /* postbyte offs */
+ IMMBYTE(cpustate, EA);
+ EA=S+SIGNED(EA);
+ cpustate->icount-=2;
+ break;
+ case 0x65: /* postword offs */
+ IMMWORD(cpustate, cpustate->ea);
+ EA+=S;
+ cpustate->icount-=4;
+ break;
+ case 0x66: /* normal */
+ EAD=SD;
+ break;
+// case 0x67: EA=0; break; /* extended */
+ case 0x68: /* indirect - auto increment */
+ EAD=SD;
+ S++;
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=5;
+ break;
+ case 0x69: /* indirect - double auto increment */
+ EAD=SD;
+ S+=2;
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=6;
+ break;
+ case 0x6a: /* indirect - auto decrement */
+ S--;
+ EAD=SD;
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=5;
+ break;
+ case 0x6b: /* indirect - double auto decrement */
+ S-=2;
+ EAD=SD;
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=6;
+ break;
+ case 0x6c: /* indirect - postbyte offs */
+ IMMBYTE(cpustate, EA);
+ EA=S+SIGNED(EA);
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=4;
+ break;
+ case 0x6d: /* indirect - postword offs */
+ IMMWORD(cpustate, cpustate->ea);
+ EA+=S;
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=7;
+ break;
+ case 0x6e: /* indirect - normal */
+ EAD=SD;
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=3;
+ break;
+// case 0x6f: EA=0; break; /* indirect - extended */
+
+/* base PC */
+ case 0x70: /* auto increment */
+ EAD=PCD;
+ PC++;
+ cpustate->icount-=2;
+ break;
+ case 0x71: /* double auto increment */
+ EAD=PCD;
+ PC+=2;
+ cpustate->icount-=3;
+ break;
+ case 0x72: /* auto decrement */
+ PC--;
+ EAD=PCD;
+ cpustate->icount-=2;
+ break;
+ case 0x73: /* double auto decrement */
+ PC-=2;
+ EAD=PCD;
+ cpustate->icount-=3;
+ break;
+ case 0x74: /* postbyte offs */
+ IMMBYTE(cpustate, EA);
+ EA=PC-1+SIGNED(EA);
+ cpustate->icount-=2;
+ break;
+ case 0x75: /* postword offs */
+ IMMWORD(cpustate, cpustate->ea);
+ EA+=PC-2;
+ cpustate->icount-=4;
+ break;
+ case 0x76: /* normal */
+ EAD=PCD;
+ break;
+// case 0x77: EA=0; break; /* extended */
+ case 0x78: /* indirect - auto increment */
+ EAD=PCD;
+ PC++;
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=5;
+ break;
+ case 0x79: /* indirect - double auto increment */
+ EAD=PCD;
+ PC+=2;
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=6;
+ break;
+ case 0x7a: /* indirect - auto decrement */
+ PC--;
+ EAD=PCD;
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=5;
+ break;
+ case 0x7b: /* indirect - double auto decrement */
+ PC-=2;
+ EAD=PCD;
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=6;
+ break;
+ case 0x7c: /* indirect - postbyte offs */
+ IMMBYTE(cpustate, EA);
+ EA=PC-1+SIGNED(EA);
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=4;
+ break;
+ case 0x7d: /* indirect - postword offs */
+ IMMWORD(cpustate, cpustate->ea);
+ EA+=PC-2;
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=7;
+ break;
+ case 0x7e: /* indirect - normal */
+ EAD=PCD;
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=3;
+ break;
+// case 0x7f: EA=0; break; /* indirect - extended */
+
+// case 0x80: EA=0; break; /* register a */
+// case 0x81: EA=0; break; /* register b */
+// case 0x82: EA=0; break; /* ???? */
+// case 0x83: EA=0; break; /* ???? */
+// case 0x84: EA=0; break; /* ???? */
+// case 0x85: EA=0; break; /* ???? */
+// case 0x86: EA=0; break; /* ???? */
+// case 0x87: EA=0; break; /* register d */
+// case 0x88: EA=0; break; /* indirect - register a */
+// case 0x89: EA=0; break; /* indirect - register b */
+// case 0x8a: EA=0; break; /* indirect - ???? */
+// case 0x8b: EA=0; break; /* indirect - ???? */
+// case 0x8c: EA=0; break; /* indirect - ???? */
+// case 0x8d: EA=0; break; /* indirect - ???? */
+// case 0x8e: EA=0; break; /* indirect - register d */
+// case 0x8f: EA=0; break; /* indirect - ???? */
+// case 0x90: EA=0; break; /* register a */
+// case 0x91: EA=0; break; /* register b */
+// case 0x92: EA=0; break; /* ???? */
+// case 0x93: EA=0; break; /* ???? */
+// case 0x94: EA=0; break; /* ???? */
+// case 0x95: EA=0; break; /* ???? */
+// case 0x96: EA=0; break; /* ???? */
+// case 0x97: EA=0; break; /* register d */
+// case 0x98: EA=0; break; /* indirect - register a */
+// case 0x99: EA=0; break; /* indirect - register b */
+// case 0x9a: EA=0; break; /* indirect - ???? */
+// case 0x9b: EA=0; break; /* indirect - ???? */
+// case 0x9c: EA=0; break; /* indirect - ???? */
+// case 0x9d: EA=0; break; /* indirect - ???? */
+// case 0x9e: EA=0; break; /* indirect - register d */
+// case 0x9f: EA=0; break; /* indirect - ???? */
+ case 0xa0: /* register a */
+ EA=X+SIGNED(A);
+ cpustate->icount-=1;
+ break;
+ case 0xa1: /* register b */
+ EA=X+SIGNED(B);
+ cpustate->icount-=1;
+ break;
+// case 0xa2: EA=0; break; /* ???? */
+// case 0xa3: EA=0; break; /* ???? */
+// case 0xa4: EA=0; break; /* ???? */
+// case 0xa5: EA=0; break; /* ???? */
+// case 0xa6: EA=0; break; /* ???? */
+ case 0xa7: /* register d */
+ EA=X+D;
+ cpustate->icount-=4;
+ break;
+ case 0xa8: /* indirect - register a */
+ EA=X+SIGNED(A);
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=4;
+ break;
+ case 0xa9: /* indirect - register b */
+ EA=X+SIGNED(B);
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=4;
+ break;
+// case 0xaa: EA=0; break; /* indirect - ???? */
+// case 0xab: EA=0; break; /* indirect - ???? */
+// case 0xac: EA=0; break; /* indirect - ???? */
+// case 0xad: EA=0; break; /* indirect - ???? */
+// case 0xae: EA=0; break; /* indirect - ???? */
+ case 0xaf: /* indirect - register d */
+ EA=X+D;
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=7;
+ break;
+ case 0xb0: /* register a */
+ EA=Y+SIGNED(A);
+ cpustate->icount-=1;
+ break;
+ case 0xb1: /* register b */
+ EA=Y+SIGNED(B);
+ cpustate->icount-=1;
+ break;
+// case 0xb2: EA=0; break; /* ???? */
+// case 0xb3: EA=0; break; /* ???? */
+// case 0xb4: EA=0; break; /* ???? */
+// case 0xb5: EA=0; break; /* ???? */
+// case 0xb6: EA=0; break; /* ???? */
+ case 0xb7: /* register d */
+ EA=Y+D;
+ cpustate->icount-=4;
+ break;
+ case 0xb8: /* indirect - register a */
+ EA=Y+SIGNED(A);
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=4;
+ break;
+ case 0xb9: /* indirect - register b */
+ EA=Y+SIGNED(B);
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=4;
+ break;
+// case 0xba: EA=0; break; /* indirect - ???? */
+// case 0xbb: EA=0; break; /* indirect - ???? */
+// case 0xbc: EA=0; break; /* indirect - ???? */
+// case 0xbd: EA=0; break; /* indirect - ???? */
+// case 0xbe: EA=0; break; /* indirect - ???? */
+ case 0xbf: /* indirect - register d */
+ EA=Y+D;
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=7;
+ break;
+// case 0xc0: EA=0; break; /* register a */
+// case 0xc1: EA=0; break; /* register b */
+// case 0xc2: EA=0; break; /* ???? */
+// case 0xc3: EA=0; break; /* ???? */
+ case 0xc4:
+ EAD=0;
+ (*konami_direct[cpustate->ireg])(cpustate);
+ cpustate->icount -= 1;
+ return;
+// case 0xc5: EA=0; break; /* ???? */
+// case 0xc6: EA=0; break; /* ???? */
+// case 0xc7: EA=0; break; /* register d */
+// case 0xc8: EA=0; break; /* indirect - register a */
+// case 0xc9: EA=0; break; /* indirect - register b */
+// case 0xca: EA=0; break; /* indirect - ???? */
+// case 0xcb: EA=0; break; /* indirect - ???? */
+ case 0xcc: /* indirect - direct */
+ DIRWORD(cpustate, cpustate->ea);
+ cpustate->icount-=4;
+ break;
+// case 0xcd: EA=0; break; /* indirect - ???? */
+// case 0xce: EA=0; break; /* indirect - register d */
+// case 0xcf: EA=0; break; /* indirect - ???? */
+ case 0xd0: /* register a */
+ EA=U+SIGNED(A);
+ cpustate->icount-=1;
+ break;
+ case 0xd1: /* register b */
+ EA=U+SIGNED(B);
+ cpustate->icount-=1;
+ break;
+// case 0xd2: EA=0; break; /* ???? */
+// case 0xd3: EA=0; break; /* ???? */
+// case 0xd4: EA=0; break; /* ???? */
+// case 0xd5: EA=0; break; /* ???? */
+// case 0xd6: EA=0; break; /* ???? */
+ case 0xd7: /* register d */
+ EA=U+D;
+ cpustate->icount-=4;
+ break;
+ case 0xd8: /* indirect - register a */
+ EA=U+SIGNED(A);
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=4;
+ break;
+ case 0xd9: /* indirect - register b */
+ EA=U+SIGNED(B);
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=4;
+ break;
+// case 0xda: EA=0; break; /* indirect - ???? */
+// case 0xdb: EA=0; break; /* indirect - ???? */
+// case 0xdc: EA=0; break; /* indirect - ???? */
+// case 0xdd: EA=0; break; /* indirect - ???? */
+// case 0xde: EA=0; break; /* indirect - ???? */
+ case 0xdf: /* indirect - register d */
+ EA=U+D;
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=7;
+ break;
+ case 0xe0: /* register a */
+ EA=S+SIGNED(A);
+ cpustate->icount-=1;
+ break;
+ case 0xe1: /* register b */
+ EA=S+SIGNED(B);
+ cpustate->icount-=1;
+ break;
+// case 0xe2: EA=0; break; /* ???? */
+// case 0xe3: EA=0; break; /* ???? */
+// case 0xe4: EA=0; break; /* ???? */
+// case 0xe5: EA=0; break; /* ???? */
+// case 0xe6: EA=0; break; /* ???? */
+ case 0xe7: /* register d */
+ EA=S+D;
+ cpustate->icount-=4;
+ break;
+ case 0xe8: /* indirect - register a */
+ EA=S+SIGNED(A);
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=4;
+ break;
+ case 0xe9: /* indirect - register b */
+ EA=S+SIGNED(B);
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=4;
+ break;
+// case 0xea: EA=0; break; /* indirect - ???? */
+// case 0xeb: EA=0; break; /* indirect - ???? */
+// case 0xec: EA=0; break; /* indirect - ???? */
+// case 0xed: EA=0; break; /* indirect - ???? */
+// case 0xee: EA=0; break; /* indirect - ???? */
+ case 0xef: /* indirect - register d */
+ EA=S+D;
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=7;
+ break;
+ case 0xf0: /* register a */
+ EA=PC+SIGNED(A);
+ cpustate->icount-=1;
+ break;
+ case 0xf1: /* register b */
+ EA=PC+SIGNED(B);
+ cpustate->icount-=1;
+ break;
+// case 0xf2: EA=0; break; /* ???? */
+// case 0xf3: EA=0; break; /* ???? */
+// case 0xf4: EA=0; break; /* ???? */
+// case 0xf5: EA=0; break; /* ???? */
+// case 0xf6: EA=0; break; /* ???? */
+ case 0xf7: /* register d */
+ EA=PC+D;
+ cpustate->icount-=4;
+ break;
+ case 0xf8: /* indirect - register a */
+ EA=PC+SIGNED(A);
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=4;
+ break;
+ case 0xf9: /* indirect - register b */
+ EA=PC+SIGNED(B);
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=4;
+ break;
+// case 0xfa: EA=0; break; /* indirect - ???? */
+// case 0xfb: EA=0; break; /* indirect - ???? */
+// case 0xfc: EA=0; break; /* indirect - ???? */
+// case 0xfd: EA=0; break; /* indirect - ???? */
+// case 0xfe: EA=0; break; /* indirect - ???? */
+ case 0xff: /* indirect - register d */
+ EA=PC+D;
+ EA=RM16(cpustate, EAD);
+ cpustate->icount-=7;
+ break;
+ default:
+ logerror("KONAMI: Unknown/Invalid postbyte at PC = %04x\n", PC -1 );
+ EAD = 0;
+ }
+ (*konami_indexed[cpustate->ireg])(cpustate);
+}
diff --git a/trunk/src/emu/cpu/konami/konamtbl.c b/trunk/src/emu/cpu/konami/konamtbl.c
new file mode 100644
index 00000000000..4f2d0388263
--- /dev/null
+++ b/trunk/src/emu/cpu/konami/konamtbl.c
@@ -0,0 +1,491 @@
+INLINE void abx(konami_state *cpustate);
+INLINE void adca_di(konami_state *cpustate);
+INLINE void adca_ex(konami_state *cpustate);
+INLINE void adca_im(konami_state *cpustate);
+INLINE void adca_ix(konami_state *cpustate);
+INLINE void adcb_di(konami_state *cpustate);
+INLINE void adcb_ex(konami_state *cpustate);
+INLINE void adcb_im(konami_state *cpustate);
+INLINE void adcb_ix(konami_state *cpustate);
+INLINE void adda_di(konami_state *cpustate);
+INLINE void adda_ex(konami_state *cpustate);
+INLINE void adda_im(konami_state *cpustate);
+INLINE void adda_ix(konami_state *cpustate);
+INLINE void addb_di(konami_state *cpustate);
+INLINE void addb_ex(konami_state *cpustate);
+INLINE void addb_im(konami_state *cpustate);
+INLINE void addb_ix(konami_state *cpustate);
+INLINE void addd_di(konami_state *cpustate);
+INLINE void addd_ex(konami_state *cpustate);
+INLINE void addd_im(konami_state *cpustate);
+INLINE void addd_ix(konami_state *cpustate);
+INLINE void anda_di(konami_state *cpustate);
+INLINE void anda_ex(konami_state *cpustate);
+INLINE void anda_im(konami_state *cpustate);
+INLINE void anda_ix(konami_state *cpustate);
+INLINE void andb_di(konami_state *cpustate);
+INLINE void andb_ex(konami_state *cpustate);
+INLINE void andb_im(konami_state *cpustate);
+INLINE void andb_ix(konami_state *cpustate);
+INLINE void andcc(konami_state *cpustate);
+INLINE void asl_di(konami_state *cpustate);
+INLINE void asl_ex(konami_state *cpustate);
+INLINE void asl_ix(konami_state *cpustate);
+INLINE void asla(konami_state *cpustate);
+INLINE void aslb(konami_state *cpustate);
+INLINE void asr_di(konami_state *cpustate);
+INLINE void asr_ex(konami_state *cpustate);
+INLINE void asr_ix(konami_state *cpustate);
+INLINE void asra(konami_state *cpustate);
+INLINE void asrb(konami_state *cpustate);
+INLINE void bcc(konami_state *cpustate);
+INLINE void bcs(konami_state *cpustate);
+INLINE void beq(konami_state *cpustate);
+INLINE void bge(konami_state *cpustate);
+INLINE void bgt(konami_state *cpustate);
+INLINE void bhi(konami_state *cpustate);
+INLINE void bita_di(konami_state *cpustate);
+INLINE void bita_ex(konami_state *cpustate);
+INLINE void bita_im(konami_state *cpustate);
+INLINE void bita_ix(konami_state *cpustate);
+INLINE void bitb_di(konami_state *cpustate);
+INLINE void bitb_ex(konami_state *cpustate);
+INLINE void bitb_im(konami_state *cpustate);
+INLINE void bitb_ix(konami_state *cpustate);
+INLINE void ble(konami_state *cpustate);
+INLINE void bls(konami_state *cpustate);
+INLINE void blt(konami_state *cpustate);
+INLINE void bmi(konami_state *cpustate);
+INLINE void bne(konami_state *cpustate);
+INLINE void bpl(konami_state *cpustate);
+INLINE void bra(konami_state *cpustate);
+INLINE void brn(konami_state *cpustate);
+INLINE void bsr(konami_state *cpustate);
+INLINE void bvc(konami_state *cpustate);
+INLINE void bvs(konami_state *cpustate);
+INLINE void clr_di(konami_state *cpustate);
+INLINE void clr_ex(konami_state *cpustate);
+INLINE void clr_ix(konami_state *cpustate);
+INLINE void clra(konami_state *cpustate);
+INLINE void clrb(konami_state *cpustate);
+INLINE void cmpa_di(konami_state *cpustate);
+INLINE void cmpa_ex(konami_state *cpustate);
+INLINE void cmpa_im(konami_state *cpustate);
+INLINE void cmpa_ix(konami_state *cpustate);
+INLINE void cmpb_di(konami_state *cpustate);
+INLINE void cmpb_ex(konami_state *cpustate);
+INLINE void cmpb_im(konami_state *cpustate);
+INLINE void cmpb_ix(konami_state *cpustate);
+INLINE void cmpd_di(konami_state *cpustate);
+INLINE void cmpd_ex(konami_state *cpustate);
+INLINE void cmpd_im(konami_state *cpustate);
+INLINE void cmpd_ix(konami_state *cpustate);
+INLINE void cmps_di(konami_state *cpustate);
+INLINE void cmps_ex(konami_state *cpustate);
+INLINE void cmps_im(konami_state *cpustate);
+INLINE void cmps_ix(konami_state *cpustate);
+INLINE void cmpu_di(konami_state *cpustate);
+INLINE void cmpu_ex(konami_state *cpustate);
+INLINE void cmpu_im(konami_state *cpustate);
+INLINE void cmpu_ix(konami_state *cpustate);
+INLINE void cmpx_di(konami_state *cpustate);
+INLINE void cmpx_ex(konami_state *cpustate);
+INLINE void cmpx_im(konami_state *cpustate);
+INLINE void cmpx_ix(konami_state *cpustate);
+INLINE void cmpy_di(konami_state *cpustate);
+INLINE void cmpy_ex(konami_state *cpustate);
+INLINE void cmpy_im(konami_state *cpustate);
+INLINE void cmpy_ix(konami_state *cpustate);
+INLINE void com_di(konami_state *cpustate);
+INLINE void com_ex(konami_state *cpustate);
+INLINE void com_ix(konami_state *cpustate);
+INLINE void coma(konami_state *cpustate);
+INLINE void comb(konami_state *cpustate);
+INLINE void cwai(konami_state *cpustate);
+INLINE void daa(konami_state *cpustate);
+INLINE void dec_di(konami_state *cpustate);
+INLINE void dec_ex(konami_state *cpustate);
+INLINE void dec_ix(konami_state *cpustate);
+INLINE void deca(konami_state *cpustate);
+INLINE void decb(konami_state *cpustate);
+INLINE void eora_di(konami_state *cpustate);
+INLINE void eora_ex(konami_state *cpustate);
+INLINE void eora_im(konami_state *cpustate);
+INLINE void eora_ix(konami_state *cpustate);
+INLINE void eorb_di(konami_state *cpustate);
+INLINE void eorb_ex(konami_state *cpustate);
+INLINE void eorb_im(konami_state *cpustate);
+INLINE void eorb_ix(konami_state *cpustate);
+INLINE void exg(konami_state *cpustate);
+INLINE void illegal(konami_state *cpustate);
+INLINE void inc_di(konami_state *cpustate);
+INLINE void inc_ex(konami_state *cpustate);
+INLINE void inc_ix(konami_state *cpustate);
+INLINE void inca(konami_state *cpustate);
+INLINE void incb(konami_state *cpustate);
+INLINE void jmp_di(konami_state *cpustate);
+INLINE void jmp_ex(konami_state *cpustate);
+INLINE void jmp_ix(konami_state *cpustate);
+INLINE void jsr_di(konami_state *cpustate);
+INLINE void jsr_ex(konami_state *cpustate);
+INLINE void jsr_ix(konami_state *cpustate);
+INLINE void lbcc(konami_state *cpustate);
+INLINE void lbcs(konami_state *cpustate);
+INLINE void lbeq(konami_state *cpustate);
+INLINE void lbge(konami_state *cpustate);
+INLINE void lbgt(konami_state *cpustate);
+INLINE void lbhi(konami_state *cpustate);
+INLINE void lble(konami_state *cpustate);
+INLINE void lbls(konami_state *cpustate);
+INLINE void lblt(konami_state *cpustate);
+INLINE void lbmi(konami_state *cpustate);
+INLINE void lbne(konami_state *cpustate);
+INLINE void lbpl(konami_state *cpustate);
+INLINE void lbra(konami_state *cpustate);
+INLINE void lbrn(konami_state *cpustate);
+INLINE void lbsr(konami_state *cpustate);
+INLINE void lbvc(konami_state *cpustate);
+INLINE void lbvs(konami_state *cpustate);
+INLINE void lda_di(konami_state *cpustate);
+INLINE void lda_ex(konami_state *cpustate);
+INLINE void lda_im(konami_state *cpustate);
+INLINE void lda_ix(konami_state *cpustate);
+INLINE void ldb_di(konami_state *cpustate);
+INLINE void ldb_ex(konami_state *cpustate);
+INLINE void ldb_im(konami_state *cpustate);
+INLINE void ldb_ix(konami_state *cpustate);
+INLINE void ldd_di(konami_state *cpustate);
+INLINE void ldd_ex(konami_state *cpustate);
+INLINE void ldd_im(konami_state *cpustate);
+INLINE void ldd_ix(konami_state *cpustate);
+INLINE void lds_di(konami_state *cpustate);
+INLINE void lds_ex(konami_state *cpustate);
+INLINE void lds_im(konami_state *cpustate);
+INLINE void lds_ix(konami_state *cpustate);
+INLINE void ldu_di(konami_state *cpustate);
+INLINE void ldu_ex(konami_state *cpustate);
+INLINE void ldu_im(konami_state *cpustate);
+INLINE void ldu_ix(konami_state *cpustate);
+INLINE void ldx_di(konami_state *cpustate);
+INLINE void ldx_ex(konami_state *cpustate);
+INLINE void ldx_im(konami_state *cpustate);
+INLINE void ldx_ix(konami_state *cpustate);
+INLINE void ldy_di(konami_state *cpustate);
+INLINE void ldy_ex(konami_state *cpustate);
+INLINE void ldy_im(konami_state *cpustate);
+INLINE void ldy_ix(konami_state *cpustate);
+INLINE void leas(konami_state *cpustate);
+INLINE void leau(konami_state *cpustate);
+INLINE void leax(konami_state *cpustate);
+INLINE void leay(konami_state *cpustate);
+INLINE void lsr_di(konami_state *cpustate);
+INLINE void lsr_ex(konami_state *cpustate);
+INLINE void lsr_ix(konami_state *cpustate);
+INLINE void lsra(konami_state *cpustate);
+INLINE void lsrb(konami_state *cpustate);
+INLINE void mul(konami_state *cpustate);
+INLINE void neg_di(konami_state *cpustate);
+INLINE void neg_ex(konami_state *cpustate);
+INLINE void neg_ix(konami_state *cpustate);
+INLINE void nega(konami_state *cpustate);
+INLINE void negb(konami_state *cpustate);
+INLINE void nop(konami_state *cpustate);
+INLINE void ora_di(konami_state *cpustate);
+INLINE void ora_ex(konami_state *cpustate);
+INLINE void ora_im(konami_state *cpustate);
+INLINE void ora_ix(konami_state *cpustate);
+INLINE void orb_di(konami_state *cpustate);
+INLINE void orb_ex(konami_state *cpustate);
+INLINE void orb_im(konami_state *cpustate);
+INLINE void orb_ix(konami_state *cpustate);
+INLINE void orcc(konami_state *cpustate);
+INLINE void pshs(konami_state *cpustate);
+INLINE void pshu(konami_state *cpustate);
+INLINE void puls(konami_state *cpustate);
+INLINE void pulu(konami_state *cpustate);
+INLINE void rol_di(konami_state *cpustate);
+INLINE void rol_ex(konami_state *cpustate);
+INLINE void rol_ix(konami_state *cpustate);
+INLINE void rola(konami_state *cpustate);
+INLINE void rolb(konami_state *cpustate);
+INLINE void ror_di(konami_state *cpustate);
+INLINE void ror_ex(konami_state *cpustate);
+INLINE void ror_ix(konami_state *cpustate);
+INLINE void rora(konami_state *cpustate);
+INLINE void rorb(konami_state *cpustate);
+INLINE void rti(konami_state *cpustate);
+INLINE void rts(konami_state *cpustate);
+INLINE void sbca_di(konami_state *cpustate);
+INLINE void sbca_ex(konami_state *cpustate);
+INLINE void sbca_im(konami_state *cpustate);
+INLINE void sbca_ix(konami_state *cpustate);
+INLINE void sbcb_di(konami_state *cpustate);
+INLINE void sbcb_ex(konami_state *cpustate);
+INLINE void sbcb_im(konami_state *cpustate);
+INLINE void sbcb_ix(konami_state *cpustate);
+INLINE void sex(konami_state *cpustate);
+INLINE void sta_di(konami_state *cpustate);
+INLINE void sta_ex(konami_state *cpustate);
+INLINE void sta_im(konami_state *cpustate);
+INLINE void sta_ix(konami_state *cpustate);
+INLINE void stb_di(konami_state *cpustate);
+INLINE void stb_ex(konami_state *cpustate);
+INLINE void stb_im(konami_state *cpustate);
+INLINE void stb_ix(konami_state *cpustate);
+INLINE void std_di(konami_state *cpustate);
+INLINE void std_ex(konami_state *cpustate);
+INLINE void std_im(konami_state *cpustate);
+INLINE void std_ix(konami_state *cpustate);
+INLINE void sts_di(konami_state *cpustate);
+INLINE void sts_ex(konami_state *cpustate);
+INLINE void sts_im(konami_state *cpustate);
+INLINE void sts_ix(konami_state *cpustate);
+INLINE void stu_di(konami_state *cpustate);
+INLINE void stu_ex(konami_state *cpustate);
+INLINE void stu_im(konami_state *cpustate);
+INLINE void stu_ix(konami_state *cpustate);
+INLINE void stx_di(konami_state *cpustate);
+INLINE void stx_ex(konami_state *cpustate);
+INLINE void stx_im(konami_state *cpustate);
+INLINE void stx_ix(konami_state *cpustate);
+INLINE void sty_di(konami_state *cpustate);
+INLINE void sty_ex(konami_state *cpustate);
+INLINE void sty_im(konami_state *cpustate);
+INLINE void sty_ix(konami_state *cpustate);
+INLINE void suba_di(konami_state *cpustate);
+INLINE void suba_ex(konami_state *cpustate);
+INLINE void suba_im(konami_state *cpustate);
+INLINE void suba_ix(konami_state *cpustate);
+INLINE void subb_di(konami_state *cpustate);
+INLINE void subb_ex(konami_state *cpustate);
+INLINE void subb_im(konami_state *cpustate);
+INLINE void subb_ix(konami_state *cpustate);
+INLINE void subd_di(konami_state *cpustate);
+INLINE void subd_ex(konami_state *cpustate);
+INLINE void subd_im(konami_state *cpustate);
+INLINE void subd_ix(konami_state *cpustate);
+INLINE void swi(konami_state *cpustate);
+INLINE void swi2(konami_state *cpustate);
+INLINE void swi3(konami_state *cpustate);
+INLINE void sync(konami_state *cpustate);
+INLINE void tfr(konami_state *cpustate);
+INLINE void tst_di(konami_state *cpustate);
+INLINE void tst_ex(konami_state *cpustate);
+INLINE void tst_ix(konami_state *cpustate);
+INLINE void tsta(konami_state *cpustate);
+INLINE void tstb(konami_state *cpustate);
+
+INLINE void clrd(konami_state *cpustate); /* 6309 */
+INLINE void clrw_ix(konami_state *cpustate); /* 6309 ? */
+INLINE void clrw_di(konami_state *cpustate); /* 6309 ? */
+INLINE void clrw_ex(konami_state *cpustate); /* 6309 ? */
+INLINE void negd(konami_state *cpustate);
+INLINE void negw_ix(konami_state *cpustate); /* 6309 ? */
+INLINE void negw_di(konami_state *cpustate); /* 6309 ? */
+INLINE void negw_ex(konami_state *cpustate); /* 6309 ? */
+INLINE void lsrd(konami_state *cpustate); /* 6309 */
+INLINE void lsrd_di(konami_state *cpustate); /* 6309 */
+INLINE void lsrd_ix(konami_state *cpustate); /* 6309 */
+INLINE void lsrd_ex(konami_state *cpustate); /* 6309 */
+INLINE void rord(konami_state *cpustate); /* 6309 ? */
+INLINE void rord_di(konami_state *cpustate); /* 6309 */
+INLINE void rord_ix(konami_state *cpustate); /* 6309 */
+INLINE void rord_ex(konami_state *cpustate); /* 6309 */
+INLINE void asrd(konami_state *cpustate); /* 6309 ? */
+INLINE void asrd_di(konami_state *cpustate); /* 6309 */
+INLINE void asrd_ix(konami_state *cpustate); /* 6309 */
+INLINE void asrd_ex(konami_state *cpustate); /* 6309 */
+INLINE void asld(konami_state *cpustate); /* 6309 */
+INLINE void asld_di(konami_state *cpustate); /* 6309 */
+INLINE void asld_ix(konami_state *cpustate); /* 6309 */
+INLINE void asld_ex(konami_state *cpustate); /* 6309 */
+INLINE void rold(konami_state *cpustate); /* 6309 ? */
+INLINE void rold_di(konami_state *cpustate); /* 6309 */
+INLINE void rold_ix(konami_state *cpustate); /* 6309 */
+INLINE void rold_ex(konami_state *cpustate); /* 6309 */
+INLINE void tstd(konami_state *cpustate);
+INLINE void tstw_di(konami_state *cpustate);
+INLINE void tstw_ix(konami_state *cpustate);
+INLINE void tstw_ex(konami_state *cpustate);
+
+/* Custom opcodes */
+INLINE void setline_im(konami_state *cpustate);
+INLINE void setline_ix(konami_state *cpustate);
+INLINE void setline_di(konami_state *cpustate);
+INLINE void setline_ex(konami_state *cpustate);
+INLINE void bmove(konami_state *cpustate);
+INLINE void move(konami_state *cpustate);
+INLINE void decbjnz(konami_state *cpustate);
+INLINE void decxjnz(konami_state *cpustate);
+INLINE void bset(konami_state *cpustate);
+INLINE void bset2(konami_state *cpustate);
+INLINE void lmul(konami_state *cpustate);
+INLINE void divx(konami_state *cpustate);
+INLINE void incd(konami_state *cpustate);
+INLINE void incw_di(konami_state *cpustate);
+INLINE void incw_ix(konami_state *cpustate);
+INLINE void incw_ex(konami_state *cpustate);
+INLINE void decd(konami_state *cpustate);
+INLINE void decw_di(konami_state *cpustate);
+INLINE void decw_ix(konami_state *cpustate);
+INLINE void decw_ex(konami_state *cpustate);
+INLINE void lsrw_di(konami_state *cpustate);
+INLINE void lsrw_ix(konami_state *cpustate);
+INLINE void lsrw_ex(konami_state *cpustate);
+INLINE void rorw_di(konami_state *cpustate);
+INLINE void rorw_ix(konami_state *cpustate);
+INLINE void rorw_ex(konami_state *cpustate);
+INLINE void asrw_di(konami_state *cpustate);
+INLINE void asrw_ix(konami_state *cpustate);
+INLINE void asrw_ex(konami_state *cpustate);
+INLINE void aslw_di(konami_state *cpustate);
+INLINE void aslw_ix(konami_state *cpustate);
+INLINE void aslw_ex(konami_state *cpustate);
+INLINE void rolw_di(konami_state *cpustate);
+INLINE void rolw_ix(konami_state *cpustate);
+INLINE void rolw_ex(konami_state *cpustate);
+INLINE void absa(konami_state *cpustate);
+INLINE void absb(konami_state *cpustate);
+INLINE void absd(konami_state *cpustate);
+
+INLINE void opcode2(konami_state *cpustate);
+
+static void (*const konami_main[0x100])(konami_state *cpustate) = {
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* 00 */
+ opcode2,opcode2,opcode2,opcode2,pshs ,pshu ,puls ,pulu ,
+ lda_im ,ldb_im ,opcode2,opcode2,adda_im,addb_im,opcode2,opcode2, /* 10 */
+ adca_im,adcb_im,opcode2,opcode2,suba_im,subb_im,opcode2,opcode2,
+ sbca_im,sbcb_im,opcode2,opcode2,anda_im,andb_im,opcode2,opcode2, /* 20 */
+ bita_im,bitb_im,opcode2,opcode2,eora_im,eorb_im,opcode2,opcode2,
+ ora_im ,orb_im ,opcode2,opcode2,cmpa_im,cmpb_im,opcode2,opcode2, /* 30 */
+ setline_im,opcode2,opcode2,opcode2,andcc,orcc ,exg ,tfr ,
+ ldd_im ,opcode2,ldx_im ,opcode2,ldy_im ,opcode2,ldu_im ,opcode2, /* 40 */
+ lds_im ,opcode2,cmpd_im,opcode2,cmpx_im,opcode2,cmpy_im,opcode2,
+ cmpu_im,opcode2,cmps_im,opcode2,addd_im,opcode2,subd_im,opcode2, /* 50 */
+ opcode2,opcode2,opcode2,opcode2,opcode2,illegal,illegal,illegal,
+ bra ,bhi ,bcc ,bne ,bvc ,bpl ,bge ,bgt , /* 60 */
+ lbra ,lbhi ,lbcc ,lbne ,lbvc ,lbpl ,lbge ,lbgt ,
+ brn ,bls ,bcs ,beq ,bvs ,bmi ,blt ,ble , /* 70 */
+ lbrn ,lbls ,lbcs ,lbeq ,lbvs ,lbmi ,lblt ,lble ,
+ clra ,clrb ,opcode2,coma ,comb ,opcode2,nega ,negb , /* 80 */
+ opcode2,inca ,incb ,opcode2,deca ,decb ,opcode2,rts ,
+ tsta ,tstb ,opcode2,lsra ,lsrb ,opcode2,rora ,rorb , /* 90 */
+ opcode2,asra ,asrb ,opcode2,asla ,aslb ,opcode2,rti ,
+ rola ,rolb ,opcode2,opcode2,opcode2,opcode2,opcode2,opcode2, /* a0 */
+ opcode2,opcode2,bsr ,lbsr ,decbjnz,decxjnz,nop ,illegal,
+ abx ,daa ,sex ,mul ,lmul ,divx ,bmove ,move , /* b0 */
+ lsrd ,opcode2,rord ,opcode2,asrd ,opcode2,asld ,opcode2,
+ rold ,opcode2,clrd ,opcode2,negd ,opcode2,incd ,opcode2, /* c0 */
+ decd ,opcode2,tstd ,opcode2,absa ,absb ,absd ,bset ,
+ bset2 ,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* d0 */
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal,
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* e0 */
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal,
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* f0 */
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal
+};
+
+static void (*const konami_indexed[0x100])(konami_state *cpustate) = {
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* 00 */
+ leax ,leay ,leau ,leas ,illegal,illegal,illegal,illegal,
+ illegal,illegal,lda_ix ,ldb_ix ,illegal,illegal,adda_ix,addb_ix, /* 10 */
+ illegal,illegal,adca_ix,adcb_ix,illegal,illegal,suba_ix,subb_ix,
+ illegal,illegal,sbca_ix,sbcb_ix,illegal,illegal,anda_ix,andb_ix, /* 20 */
+ illegal,illegal,bita_ix,bitb_ix,illegal,illegal,eora_ix,eorb_ix,
+ illegal,illegal,ora_ix ,orb_ix ,illegal,illegal,cmpa_ix,cmpb_ix, /* 30 */
+ illegal,setline_ix,sta_ix,stb_ix,illegal,illegal,illegal,illegal,
+ illegal,ldd_ix ,illegal,ldx_ix ,illegal,ldy_ix ,illegal,ldu_ix , /* 40 */
+ illegal,lds_ix ,illegal,cmpd_ix,illegal,cmpx_ix,illegal,cmpy_ix,
+ illegal,cmpu_ix,illegal,cmps_ix,illegal,addd_ix,illegal,subd_ix, /* 50 */
+ std_ix ,stx_ix ,sty_ix ,stu_ix ,sts_ix ,illegal,illegal,illegal,
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* 60 */
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal,
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* 70 */
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal,
+ illegal,illegal,clr_ix ,illegal,illegal,com_ix ,illegal,illegal, /* 80 */
+ neg_ix ,illegal,illegal,inc_ix ,illegal,illegal,dec_ix ,illegal,
+ illegal,illegal,tst_ix ,illegal,illegal,lsr_ix ,illegal,illegal, /* 90 */
+ ror_ix ,illegal,illegal,asr_ix ,illegal,illegal,asl_ix ,illegal,
+ illegal,illegal,rol_ix ,lsrw_ix,rorw_ix,asrw_ix,aslw_ix,rolw_ix, /* a0 */
+ jmp_ix ,jsr_ix ,illegal,illegal,illegal,illegal,illegal,illegal,
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* b0 */
+ illegal,lsrd_ix,illegal,rord_ix,illegal,asrd_ix,illegal,asld_ix,
+ illegal,rold_ix,illegal,clrw_ix,illegal,negw_ix,illegal,incw_ix, /* c0 */
+ illegal,decw_ix,illegal,tstw_ix,illegal,illegal,illegal,illegal,
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* d0 */
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal,
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* e0 */
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal,
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* f0 */
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal
+};
+
+static void (*const konami_direct[0x100])(konami_state *cpustate) = {
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* 00 */
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal,
+ illegal,illegal,lda_di ,ldb_di ,illegal,illegal,adda_di,addb_di, /* 10 */
+ illegal,illegal,adca_di,adcb_di,illegal,illegal,suba_di,subb_di,
+ illegal,illegal,sbca_di,sbcb_di,illegal,illegal,anda_di,andb_di, /* 20 */
+ illegal,illegal,bita_di,bitb_di,illegal,illegal,eora_di,eorb_di,
+ illegal,illegal,ora_di ,orb_di ,illegal,illegal,cmpa_di,cmpb_di, /* 30 */
+ illegal,setline_di,sta_di,stb_di,illegal,illegal,illegal,illegal,
+ illegal,ldd_di ,illegal,ldx_di ,illegal,ldy_di ,illegal,ldu_di , /* 40 */
+ illegal,lds_di ,illegal,cmpd_di,illegal,cmpx_di,illegal,cmpy_di,
+ illegal,cmpu_di,illegal,cmps_di,illegal,addd_di,illegal,subd_di, /* 50 */
+ std_di ,stx_di ,sty_di ,stu_di ,sts_di ,illegal,illegal,illegal,
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* 60 */
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal,
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* 70 */
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal,
+ illegal,illegal,clr_di ,illegal,illegal,com_di ,illegal,illegal, /* 80 */
+ neg_di ,illegal,illegal,inc_di ,illegal,illegal,dec_di ,illegal,
+ illegal,illegal,tst_di ,illegal,illegal,lsr_di ,illegal,illegal, /* 90 */
+ ror_di ,illegal,illegal,asr_di ,illegal,illegal,asl_di ,illegal,
+ illegal,illegal,rol_di ,lsrw_di,rorw_di,asrw_di,aslw_di,rolw_di, /* a0 */
+ jmp_di ,jsr_di ,illegal,illegal,illegal,illegal,illegal,illegal,
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* b0 */
+ illegal,lsrd_di,illegal,rord_di,illegal,asrd_di,illegal,asld_di,
+ illegal,rold_di,illegal,clrw_di,illegal,negw_di,illegal,incw_di, /* c0 */
+ illegal,decw_di,illegal,tstw_di,illegal,illegal,illegal,illegal,
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* d0 */
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal,
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* e0 */
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal,
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* f0 */
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal
+};
+
+static void (*const konami_extended[0x100])(konami_state *cpustate) = {
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* 00 */
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal,
+ illegal,illegal,lda_ex ,ldb_ex ,illegal,illegal,adda_ex,addb_ex, /* 10 */
+ illegal,illegal,adca_ex,adcb_ex,illegal,illegal,suba_ex,subb_ex,
+ illegal,illegal,sbca_ex,sbcb_ex,illegal,illegal,anda_ex,andb_ex, /* 20 */
+ illegal,illegal,bita_ex,bitb_ex,illegal,illegal,eora_ex,eorb_ex,
+ illegal,illegal,ora_ex ,orb_ex ,illegal,illegal,cmpa_ex,cmpb_ex, /* 30 */
+ illegal,setline_ex,sta_ex,stb_ex,illegal,illegal,illegal,illegal,
+ illegal,ldd_ex ,illegal,ldx_ex ,illegal,ldy_ex ,illegal,ldu_ex , /* 40 */
+ illegal,lds_ex ,illegal,cmpd_ex,illegal,cmpx_ex,illegal,cmpy_ex,
+ illegal,cmpu_ex,illegal,cmps_ex,illegal,addd_ex,illegal,subd_ex, /* 50 */
+ std_ex ,stx_ex ,sty_ex ,stu_ex ,sts_ex ,illegal,illegal,illegal,
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* 60 */
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal,
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* 70 */
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal,
+ illegal,illegal,clr_ex ,illegal,illegal,com_ex ,illegal,illegal, /* 80 */
+ neg_ex ,illegal,illegal,inc_ex ,illegal,illegal,dec_ex ,illegal,
+ illegal,illegal,tst_ex ,illegal,illegal,lsr_ex ,illegal,illegal, /* 90 */
+ ror_ex ,illegal,illegal,asr_ex ,illegal,illegal,asl_ex ,illegal,
+ illegal,illegal,rol_ex ,lsrw_ex,rorw_ex,asrw_ex,aslw_ex,rolw_ex, /* a0 */
+ jmp_ex ,jsr_ex ,illegal,illegal,illegal,illegal,illegal,illegal,
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* b0 */
+ illegal,lsrd_ex,illegal,rord_ex,illegal,asrd_ex,illegal,asld_ex,
+ illegal,rold_ex,illegal,clrw_ex,illegal,negw_ex,illegal,incw_ex, /* c0 */
+ illegal,decw_ex,illegal,tstw_ex,illegal,illegal,illegal,illegal,
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* d0 */
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal,
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* e0 */
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal,
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal, /* f0 */
+ illegal,illegal,illegal,illegal,illegal,illegal,illegal,illegal
+};
diff --git a/trunk/src/emu/cpu/lh5801/5801dasm.c b/trunk/src/emu/cpu/lh5801/5801dasm.c
new file mode 100644
index 00000000000..840205042fd
--- /dev/null
+++ b/trunk/src/emu/cpu/lh5801/5801dasm.c
@@ -0,0 +1,736 @@
+/*****************************************************************************
+ *
+ * disasm.c
+ * portable lh5801 emulator interface
+ *
+ * Copyright Peter Trauner, all rights reserved.
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * peter.trauner@jk.uni-linz.ac.at
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ *****************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+
+#include "lh5801.h"
+
+typedef enum
+{
+ Imp,
+ Reg,
+ Vec, // imm byte (vector at 0xffxx)
+ Vej,
+ Imm,
+ RegImm,
+ Imm16,
+ RegImm16,
+ ME0,
+ ME0Imm,
+ Abs,
+ AbsImm,
+ ME1,
+ ME1Imm,
+ ME1Abs,
+ ME1AbsImm,
+ RelP,
+ RelM
+} Adr;
+
+typedef enum
+{
+ RegNone,
+ A,
+ XL, XH, X,
+ YL, YH, Y,
+ UL, UH, U,
+ P, S
+} Regs;
+
+static const char *const RegNames[]= {
+ 0, "A", "XL", "XH", "X", "YL", "YH", "Y", "UL", "UH", "U", "P", "S"
+};
+
+#if defined(SEC)
+#undef SEC
+#endif
+
+typedef enum
+{
+ ILL, ILL2, PREFD, NOP,
+
+ LDA, STA, LDI, LDX, STX,
+ LDE, SDE, LIN, SIN,
+ TIN, // (x++)->(y++)
+ ADC, ADI, ADR, SBC, SBI,
+ DCA, DCS, // bcd add and sub
+ CPA, CPI, CIN, // A compared with (x++)
+ AND, ANI, ORA, ORI, EOR, EAI, BIT, BII,
+ INC, DEC,
+ DRL, DRR, // digit rotates
+ ROL, ROR,
+ SHL, SHR,
+ AEX, // A nibble swap
+
+ BCR, BCS, BHR, BHS, BZR, BZS, BVR, BVS,
+ BCH, LOP, // loop with ul
+ JMP, SJP, RTN, RTI, HLT,
+ VCR, VCS, VHR, VHS, VVS, VZR, VZS,
+ VMJ, VEJ,
+ PSH, POP, ATT, TTA,
+ REC, SEC, RIE, SIE,
+
+ AM0, AM1, // load timer reg
+ ITA, // reads input port
+ ATP, // akku send to data bus
+ CDV, // clears internal divider
+ OFF, // clears bf flip flop
+ RDP, SDP,// reset display flip flop
+ RPU, SPU,// flip flop pu off
+ RPV, SPV,// flip flop pv off
+} Ins;
+
+static const char *const InsNames[]={
+ "ILL", "ILL", 0, "NOP",
+ "LDA", "STA", "LDI", "LDX", "STX",
+ "LDE", "SDE", "LIN", "SIN",
+ "TIN",
+ "ADC", "ADI", "ADR", "SBC", "SBI",
+ "DCA", "DCS",
+ "CPA", "CPI", "CIN",
+ "AND", "ANI", "ORA", "ORI", "EOR", "EAI", "BIT", "BII",
+ "INC", "DEC",
+ "DRL", "DRR",
+ "ROL", "ROR",
+ "SHL", "SHR",
+ "AEX",
+ "BCR", "BCS", "BHR", "BHS", "BZR", "BZS", "BVR", "BVS",
+ "BCH", "LOP",
+ "JMP", "SJP", "RTN", "RTI", "HLT",
+ "VCR", "VCS", "VHR", "VHS", "VVS", "VZR", "VZS",
+ "VMJ", "VEJ",
+ "PSH", "POP", "ATT", "TTA",
+ "REC", "SEC", "RIE", "SIE",
+
+ "AM0", "AM1",
+ "ITA",
+ "ATP",
+ "CDV",
+ "OFF",
+ "RDP", "SDP",
+ "RPU", "SPU",
+ "RPV", "SPV",
+};
+
+typedef struct { Ins ins; Adr adr; Regs reg; } Entry;
+
+static const Entry table[0x100]={
+ { SBC, Reg, XL }, // 0
+ { SBC, ME0, X },
+ { ADC, Reg, XL },
+ { ADC, ME0, X },
+ { LDA, Reg, XL },
+ { LDA, ME0, X },
+ { CPA, Reg, XL },
+ { CPA, ME0, X },
+ { STA, Reg, XH },
+ { AND, ME0, X },
+ { STA, Reg, XL },
+ { ORA, ME0, X },
+ { DCS, ME0, X },
+ { EOR, ME0, X },
+ { STA, ME0, X },
+ { BIT, ME0, X },
+ { SBC, Reg, YL }, // 0x10
+ { SBC, ME0, Y },
+ { ADC, Reg, YL },
+ { ADC, ME0, Y },
+ { LDA, Reg, YL },
+ { LDA, ME0, Y },
+ { CPA, Reg, YL },
+ { CPA, ME0, Y },
+ { STA, Reg, YH },
+ { AND, ME0, Y },
+ { STA, Reg, YL },
+ { ORA, ME0, Y },
+ { DCS, ME0, Y },
+ { EOR, ME0, Y },
+ { STA, ME0, Y },
+ { BIT, ME0, Y },
+ { SBC, Reg, UL }, // 0x20
+ { SBC, ME0, U },
+ { ADC, Reg, UL },
+ { ADC, ME0, U },
+ { LDA, Reg, UL },
+ { LDA, ME0, U },
+ { CPA, Reg, UL },
+ { CPA, ME0, U },
+ { STA, Reg, UH },
+ { AND, ME0, U },
+ { STA, Reg, UL },
+ { ORA, ME0, U },
+ { DCS, ME0, U },
+ { EOR, ME0, U },
+ { STA, ME0, U },
+ { BIT, ME0, U },
+ { ILL }, // 0x30
+ { ILL },
+ { ILL },
+ { ILL },
+ { ILL },
+ { ILL },
+ { ILL },
+ { ILL },
+ { NOP, Imp },
+ { ILL },
+ { ILL },
+ { ILL },
+ { ILL },
+ { ILL },
+ { ILL },
+ { ILL },
+ { INC, Reg, XL }, //0x40
+ { SIN, Reg, X },
+ { DEC, Reg, XL },
+ { SDE, Reg, X },
+ { INC, Reg, X },
+ { LIN, Reg, X },
+ { DEC, Reg, X },
+ { LDE, Reg, X },
+ { LDI, RegImm, XH },
+ { ANI, ME0Imm, X },
+ { LDI, RegImm, XL },
+ { ORI, ME0Imm, X },
+ { CPI, RegImm, XH },
+ { BII, ME0Imm, X },
+ { CPI, RegImm, XL },
+ { ADI, ME0Imm, X },
+ { INC, Reg, YL }, //0x50
+ { SIN, Reg, Y },
+ { DEC, Reg, YL },
+ { SDE, Reg, Y },
+ { INC, Reg, Y },
+ { LIN, Reg, Y },
+ { DEC, Reg, Y },
+ { LDE, Reg, Y },
+ { LDI, RegImm, YH },
+ { ANI, ME0Imm, Y },
+ { LDI, RegImm, YL },
+ { ORI, ME0Imm, Y },
+ { CPI, RegImm, YH },
+ { BII, ME0Imm, Y },
+ { CPI, RegImm, YL },
+ { ADI, ME0Imm, Y },
+ { INC, Reg, UL }, //0x60
+ { SIN, Reg, U },
+ { DEC, Reg, UL },
+ { SDE, Reg, U },
+ { INC, Reg, U },
+ { LIN, Reg, U },
+ { DEC, Reg, U },
+ { LDE, Reg, U },
+ { LDI, RegImm, UH },
+ { ANI, ME0Imm, U },
+ { LDI, RegImm, UL },
+ { ORI, ME0Imm, U },
+ { CPI, RegImm, UH },
+ { BII, ME0Imm, U },
+ { CPI, RegImm, UL },
+ { ADI, ME0Imm, U },
+ { ILL }, // 0X70
+ { ILL },
+ { ILL },
+ { ILL },
+ { ILL },
+ { ILL },
+ { ILL },
+ { ILL },
+ { ILL },
+ { ILL },
+ { ILL },
+ { ILL },
+ { ILL },
+ { ILL },
+ { ILL },
+ { ILL },
+ { SBC, Reg, XH }, // 0x80
+ { BCR, RelP },
+ { ADC, Reg, XH },
+ { BCS, RelP },
+ { LDA, Reg, XH },
+ { BHR, RelP },
+ { CPA, Reg, XH },
+ { BHS, RelP },
+ { LOP, RelM },
+ { BZR, RelP },
+ { RTI, Imp },
+ { BZS, RelP },
+ { DCA, ME0, X },
+ { BVR, RelP },
+ { BCH, RelP },
+ { BVS, RelP },
+ { SBC, Reg, YH }, // 0x90
+ { BCR, RelM },
+ { ADC, Reg, YH },
+ { BCS, RelM },
+ { LDA, Reg, YH },
+ { BHR, RelM },
+ { CPA, Reg, YH },
+ { BHS, RelM },
+ { ILL },
+ { BZR, RelM },
+ { RTN, Imp },
+ { BZS, RelM },
+ { DCA, ME0, Y },
+ { BVR, RelM },
+ { BCH, RelM },
+ { BVS, RelM },
+ { SBC, Reg, UH }, // 0xa0
+ { SBC, Abs },
+ { ADC, Reg, UH },
+ { ADC, Abs },
+ { LDA, Reg, UH },
+ { LDA, Abs },
+ { CPA, Reg, UH },
+ { CPA, Abs },
+ { SPV, Imp },
+ { AND, Abs },
+ { LDI, RegImm16, S },
+ { ORA, Abs },
+ { DCA, ME0, U },
+ { EOR, Abs },
+ { STA, Abs },
+ { BIT, Abs },
+ { ILL }, //0xb0
+ { SBI },
+ { ILL },
+ { ADI, RegImm, A },
+ { ILL },
+ { LDI, RegImm, A },
+ { ILL },
+ { CPI, RegImm, A },
+ { RPV, Imp },
+ { ANI, RegImm, A },
+ { JMP, Imm16 },
+ { ORI, RegImm, A },
+ { ILL },
+ { EAI, Imm },
+ { SJP, Imm16 },
+ { BII, RegImm, A },
+ { VEJ, Vej }, // 0xc0
+ { VCR, Vec },
+ { VEJ, Vej },
+ { VCS, Vec },
+ { VEJ, Vej },
+ { VHR, Vec },
+ { VEJ, Vej },
+ { VHS, Vec },
+ { VEJ, Vej },
+ { VZR, Vec },
+ { VEJ, Vej },
+ { VZS, Vec },
+ { VEJ, Vej },
+ { VMJ, Vec },
+ { VEJ, Vej },
+ { VVS, Vec },
+ { VEJ, Vej }, // 0xd0
+ { ROR, Imp },
+ { VEJ, Vej },
+ { DRR, Imp },
+ { VEJ, Vej },
+ { SHR, Imp },
+ { VEJ, Vej },
+ { DRL, Imp },
+ { VEJ, Vej },
+ { SHL, Imp },
+ { VEJ, Vej },
+ { ROL, Imp },
+ { VEJ, Vej },
+ { INC, Reg, A },
+ { VEJ, Vej },
+ { DEC, Reg, A },
+ { VEJ, Vej }, //0xe0
+ { SPU, Imp },
+ { VEJ, Vej },
+ { RPU, Imp },
+ { VEJ, Vej },
+ { ILL },
+ { VEJ, Vej },
+ { ILL },
+ { VEJ, Vej },
+ { ANI, AbsImm },
+ { VEJ, Vej },
+ { ORI, AbsImm },
+ { VEJ, Vej },
+ { BII, AbsImm },
+ { VEJ, Vej },
+ { ADI, AbsImm },
+ { VEJ, Vej }, //0xf0
+ { AEX, Imp },
+ { VEJ, Vej },
+ { ILL },
+ { VEJ, Vej },
+ { TIN, Imp },
+ { VEJ, Vej },
+ { CIN, Imp },
+ { ILL },
+ { REC, Imp },
+ { ILL },
+ { SEC, Imp },
+ { ILL },
+ { PREFD },
+ { ILL },
+ { ILL }
+};
+static const Entry table_fd[0x100]={
+ { ILL2 }, // 0x00
+ { SBC, ME1, X },
+ { ILL2 },
+ { ADC, ME1, X },
+ { ILL2 },
+ { LDA, ME1, X },
+ { ILL2 },
+ { CPA, ME1, X },
+ { LDX, Reg, X },
+ { AND, ME1, X },
+ { POP, Reg, X },
+ { ORA, ME1, X },
+ { DCS, ME1, X },
+ { EOR, ME1, X },
+ { STA, ME1, X },
+ { BIT, ME1, X },
+ { ILL2 }, // 0x10
+ { SBC, ME1, Y },
+ { ILL2 },
+ { ADC, ME1, Y },
+ { ILL2 },
+ { LDA, ME1, Y },
+ { ILL2 },
+ { CPA, ME1, Y },
+ { LDX, Reg, Y },
+ { AND, ME1, Y },
+ { POP, Reg, Y },
+ { ORA, ME1, Y },
+ { DCS, ME1, Y },
+ { EOR, ME1, Y },
+ { STA, ME1, Y },
+ { BIT, ME1, Y },
+ { ILL2 }, // 0x20
+ { SBC, ME1, U },
+ { ILL2 },
+ { ADC, ME1, U },
+ { ILL2 },
+ { LDA, ME1, U },
+ { ILL2 },
+ { CPA, ME1, U },
+ { LDX, Reg, U },
+ { AND, ME1, U },
+ { POP, Reg, U },
+ { ORA, ME1, U },
+ { DCS, ME1, U },
+ { EOR, ME1, U },
+ { STA, ME1, U },
+ { BIT, ME1, U },
+ { ILL2 }, // 0x30
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { INC, Reg, XH }, // 0x40
+ { ILL2 },
+ { DEC, Reg, XH }, //46 in other part of manual
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { LDX, Reg, S },
+ { ANI, ME1Imm, X },
+ { STX, Reg, X },
+ { ORI, ME1Imm, X },
+ { OFF, Imp },
+ { BII, ME1Imm, X },
+ { STX, Reg, S },
+ { ADI, ME1Imm, X },
+ { INC, Reg, YH }, // 0x50
+ { ILL2 },
+ { DEC, Reg, YH }, // 56 in other part of manual
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { LDX, Reg, P },
+ { ANI, ME1Imm, Y },
+ { STX, Reg, Y },
+ { ORI, ME1Imm, Y },
+ { ILL2 },
+ { BII, ME1Imm, Y },
+ { STX, Reg, P },
+ { ADI, ME1Imm, Y },
+ { INC, Reg, UH }, // 0x60
+ { ILL2 },
+ { DEC, Reg, UH }, // 66 in other part of manual
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ANI, ME1Imm, U },
+ { STX, Reg, U },
+ { ORI, ME1Imm, U },
+ { ILL2 },
+ { BII, ME1Imm, U },
+ { ILL },
+ { ADI, ME1Imm, U },
+ { ILL2 }, // 0x70
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 }, // 0x80
+ { SIE, Imp },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { PSH, Reg, X },
+ { ILL2 },
+ { POP, Reg, A },
+ { ILL2 },
+ { DCA, ME1, X },
+ { ILL2 },
+ { CDV, Imp },
+ { ILL2 },
+ { ILL2 }, // 0x90
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { PSH, Reg, Y },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { DCA, ME1, Y },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 }, // 0xa0
+ { SBC, ME1Abs },
+ { ILL2 },
+ { ADC, ME1Abs },
+ { ILL2 },
+ { LDA, ME1Abs },
+ { ILL2 },
+ { CPA, ME1Abs },
+ { PSH, Reg, U },
+ { AND, ME1Abs },
+ { TTA, Imp },
+ { ORA, ME1Abs },
+ { DCA, ME1, U },
+ { EOR, ME1Abs },
+ { STA, ME1Abs },
+ { BIT, ME1Abs },
+ { ILL2 }, // 0xb0
+ { HLT, Imp },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ITA, Imp },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { RIE, Imp },
+ { ILL2 },
+ { RDP, Imp }, // 0xc0
+ { SDP, Imp },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { PSH, Reg, A },
+ { ILL2 },
+ { ADR, Reg, X },
+ { ILL2 },
+ { ATP, Imp },
+ { ILL2 },
+ { AM0, Imp },
+ { ILL2 },
+ { ILL2 }, // 0xd0
+ { ILL2 },
+ { ILL2 },
+ { DRR, ME1, X },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { DRL, ME1, X },
+ { ILL2 },
+ { ILL2 },
+ { ADR, Reg, Y },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { AM1, Imp },
+ { ILL2 },
+ { ILL2 }, // 0xe0
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ANI, ME1AbsImm },
+ { ADR, Reg, U },
+ { ORI, ME1AbsImm },
+ { ATT, Imp },
+ { BII, ME1AbsImm },
+ { ILL2 },
+ { ADI, ME1AbsImm },
+ { ILL2 }, // 0xf0
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 },
+ { ILL2 }
+};
+
+CPU_DISASSEMBLE( lh5801 )
+{
+ int pos = 0;
+ int oper;
+ UINT16 absolut;
+ const Entry *entry;
+ int temp;
+
+ oper=oprom[pos++];
+ entry=table+oper;
+
+ if (table[oper].ins==PREFD) {
+ oper=oprom[pos++];
+ entry=table_fd+oper;
+ }
+ switch (entry->ins) {
+ case ILL:
+ sprintf(buffer,"%s %.2x", InsNames[entry->ins], oper);break;
+ case ILL2:
+ sprintf(buffer,"%s fd%.2x", InsNames[entry->ins], oper);break;
+ default:
+ switch(entry->adr) {
+ case Imp:
+ sprintf(buffer,"%s", InsNames[entry->ins]);break;
+ case Reg:
+ sprintf(buffer,"%s %s", InsNames[entry->ins],RegNames[entry->reg]);break;
+ case RegImm:
+ sprintf(buffer,"%s %s,%.2x", InsNames[entry->ins],
+ RegNames[entry->reg], oprom[pos++]);
+ break;
+ case RegImm16:
+ absolut=oprom[pos++]<<8;
+ absolut|=oprom[pos++];
+ sprintf(buffer,"%s %s,%.4x", InsNames[entry->ins],RegNames[entry->reg],absolut );
+ break;
+ case Vec:
+ sprintf(buffer,"%s (ff%.2x)", InsNames[entry->ins],oprom[pos++]);break;
+ case Vej:
+ sprintf(buffer,"%s (ff%.2x)", InsNames[entry->ins], oper);break;
+ case Imm:
+ sprintf(buffer,"%s %.2x", InsNames[entry->ins],oprom[pos++]);break;
+ case Imm16:
+ absolut=oprom[pos++]<<8;
+ absolut|=oprom[pos++];
+ sprintf(buffer,"%s %.4x", InsNames[entry->ins],absolut );break;
+ case RelP:
+ temp=oprom[pos++];
+ sprintf(buffer,"%s %.4x", InsNames[entry->ins],pc+pos+temp );break;
+ case RelM:
+ temp=oprom[pos++];
+ sprintf(buffer,"%s %.4x", InsNames[entry->ins],pc+pos-temp );break;
+ case Abs:
+ absolut=oprom[pos++]<<8;
+ absolut|=oprom[pos++];
+ sprintf(buffer,"%s (%.4x)", InsNames[entry->ins],absolut );break;
+ case ME1Abs:
+ absolut=oprom[pos++]<<8;
+ absolut|=oprom[pos++];
+ sprintf(buffer,"%s #(%.4x)", InsNames[entry->ins],absolut );break;
+ case AbsImm:
+ absolut=oprom[pos++]<<8;
+ absolut|=oprom[pos++];
+ sprintf(buffer,"%s (%.4x),%.2x", InsNames[entry->ins],absolut,
+ oprom[pos++]);break;
+ case ME1AbsImm:
+ absolut=oprom[pos++]<<8;
+ absolut|=oprom[pos++];
+ sprintf(buffer,"%s #(%.4x),%.2x", InsNames[entry->ins],absolut,
+ oprom[pos++]);break;
+ case ME0:
+ sprintf(buffer,"%s (%s)", InsNames[entry->ins],RegNames[entry->reg] );break;
+ case ME0Imm:
+ sprintf(buffer,"%s (%s),%.2x", InsNames[entry->ins],RegNames[entry->reg],oprom[pos++] );
+ break;
+ case ME1:
+ sprintf(buffer,"%s #(%s)", InsNames[entry->ins],RegNames[entry->reg] );break;
+ case ME1Imm:
+ sprintf(buffer,"%s #(%s),%.2x", InsNames[entry->ins],RegNames[entry->reg],oprom[pos++] );
+ break;
+ }
+ }
+
+ return pos;
+}
diff --git a/trunk/src/emu/cpu/lh5801/5801tbl.c b/trunk/src/emu/cpu/lh5801/5801tbl.c
new file mode 100644
index 00000000000..3ebaa96691f
--- /dev/null
+++ b/trunk/src/emu/cpu/lh5801/5801tbl.c
@@ -0,0 +1,692 @@
+/* assumed
+ res=left+right+c
+ sbc is like adc with inverted carry and right side
+ (decrement, compare the same)
+ (like in the m6502 processors)
+*/
+INLINE UINT8 lh5801_add_generic(lh5801_state *cpustate, int left, int right, int carry)
+{
+ int res=left+right+carry;
+ int v,c;
+
+ cpustate->t&=~(H|V|Z|C);
+
+ if (!(res&0xff)) cpustate->t|=Z;
+ c=res&0x100;
+ if (c) cpustate->t|=C;
+ if (((left&0xf)+(right&0xf)+carry)&0x10) cpustate->t|=H;
+ v=((left&0x7f)+(right&0x7f)+carry)&0x80;
+ if ( (c&&!v)||(!c&&v) ) cpustate->t|=V;
+
+ return res;
+}
+
+INLINE UINT16 lh5801_readop_word(lh5801_state *cpustate)
+{
+ UINT16 r;
+ r=cpustate->direct->read_decrypted_byte(P++)<<8;
+ r|=cpustate->direct->read_decrypted_byte(P++);
+ return r;
+}
+
+
+INLINE void lh5801_adc(lh5801_state *cpustate, UINT8 data)
+{
+ cpustate->a=lh5801_add_generic(cpustate,cpustate->a,data,cpustate->t&C);
+}
+
+INLINE void lh5801_add_mem(lh5801_state *cpustate, address_space *space, int addr, UINT8 data)
+{
+ int v=lh5801_add_generic(cpustate, space->read_byte(addr),data,0);
+ space->write_byte(addr,v);
+}
+
+INLINE void lh5801_adr(lh5801_state *cpustate, PAIR *reg)
+{
+ reg->b.l=lh5801_add_generic(cpustate,reg->b.l,cpustate->a,0);
+ if (cpustate->t&C) {
+ reg->b.h++;
+ }
+}
+
+INLINE void lh5801_sbc(lh5801_state *cpustate, UINT8 data)
+{
+ cpustate->a=lh5801_add_generic(cpustate,cpustate->a,data^0xff,cpustate->t&C);
+}
+
+INLINE void lh5801_cpa(lh5801_state *cpustate, UINT8 a, UINT8 b)
+{
+ lh5801_add_generic(cpustate,a, b^0xff, 1);
+}
+
+INLINE UINT8 lh5801_decimaladd_generic(lh5801_state *cpustate, int left, int right, int carry)
+{
+ int res=lh5801_add_generic(cpustate, left, right, carry);
+ UINT8 da;
+
+ //DA values taken from official documentation
+ if (!(cpustate->t&C) && !(cpustate->t&H))
+ da = 0x9a;
+ else if (!(cpustate->t&C) && (cpustate->t&H))
+ da = 0xa0;
+ else if ((cpustate->t&C) && !(cpustate->t&H))
+ da = 0xfa;
+ else //if ((cpustate->t&C) && (cpustate->t&H))
+ da = 0x00;
+
+ return res + da;
+}
+
+INLINE void lh5801_dca(lh5801_state *cpustate, UINT8 data)
+{
+ cpustate->a += 0x66; //taken from official documentation
+ cpustate->a=lh5801_decimaladd_generic(cpustate, cpustate->a, data, cpustate->t&C);
+}
+
+INLINE void lh5801_dcs(lh5801_state *cpustate, UINT8 data)
+{
+ cpustate->a=lh5801_decimaladd_generic(cpustate, cpustate->a, data^0xff, cpustate->t&C);
+}
+
+INLINE void lh5801_and(lh5801_state *cpustate, UINT8 data)
+{
+ cpustate->a&=data;
+ cpustate->t&=~Z;
+ if (!cpustate->a) cpustate->t|=Z;
+}
+
+INLINE void lh5801_and_mem(lh5801_state *cpustate, address_space *space, int addr, UINT8 data)
+{
+ data&=space->read_byte(addr);
+ cpustate->t&=~Z;
+ if (!data) cpustate->t|=Z;
+ space->write_byte(addr,data);
+}
+
+INLINE void lh5801_bit(lh5801_state *cpustate, UINT8 a, UINT8 b)
+{
+ cpustate->t&=~Z;
+ if (!(a&b)) cpustate->t|=Z;
+}
+
+INLINE void lh5801_eor(lh5801_state *cpustate, UINT8 data)
+{
+ cpustate->a^=data;
+ cpustate->t&=~Z;
+ if (!cpustate->a) cpustate->t|=Z;
+}
+
+INLINE void lh5801_ora(lh5801_state *cpustate, UINT8 data)
+{
+ cpustate->a|=data;
+ cpustate->t&=~Z;
+ if (!cpustate->a) cpustate->t|=Z;
+}
+
+INLINE void lh5801_ora_mem(lh5801_state *cpustate, address_space *space, int addr, UINT8 data)
+{
+ data|=space->read_byte(addr);
+ cpustate->t&=~Z;
+ if (!data) cpustate->t|=Z;
+ space->write_byte(addr,data);
+}
+
+INLINE void lh5801_lda(lh5801_state *cpustate, UINT8 data)
+{
+ cpustate->a=data;
+ cpustate->t&=~Z;
+ if (!cpustate->a) cpustate->t|=Z;
+}
+
+INLINE void lh5801_lde(lh5801_state *cpustate, PAIR *reg)
+{
+ // or z flag depends on reg
+ cpustate->a=cpustate->program->read_byte(reg->w.l--);
+ cpustate->t&=~Z;
+ if (!cpustate->a) cpustate->t|=Z;
+}
+
+INLINE void lh5801_sde(lh5801_state *cpustate, PAIR *reg)
+{
+ cpustate->program->write_byte(reg->w.l--, cpustate->a);
+}
+
+INLINE void lh5801_lin(lh5801_state *cpustate, PAIR *reg)
+{
+ // or z flag depends on reg
+ cpustate->a=cpustate->program->read_byte(reg->w.l++);
+ cpustate->t&=~Z;
+ if (!cpustate->a) cpustate->t|=Z;
+}
+
+INLINE void lh5801_sin(lh5801_state *cpustate, PAIR *reg)
+{
+ cpustate->program->write_byte(reg->w.l++, cpustate->a);
+}
+
+INLINE void lh5801_dec(lh5801_state *cpustate, UINT8 *adr)
+{
+ *adr=lh5801_add_generic(cpustate,*adr,0xff,0);
+}
+
+INLINE void lh5801_inc(lh5801_state *cpustate, UINT8 *adr)
+{
+ *adr=lh5801_add_generic(cpustate,*adr,1,0);
+}
+
+INLINE void lh5801_pop(lh5801_state *cpustate)
+{
+ cpustate->a=cpustate->program->read_byte(++S);
+ cpustate->t&=~Z;
+ if (!cpustate->a) cpustate->t|=Z;
+}
+
+INLINE void lh5801_pop_word(lh5801_state *cpustate, PAIR *reg)
+{
+ reg->b.h=cpustate->program->read_byte(++S);
+ reg->b.l=cpustate->program->read_byte(++S);
+ // z flag?
+}
+
+INLINE void lh5801_rtn(lh5801_state *cpustate)
+{
+ P=cpustate->program->read_byte(++S)<<8;
+ P|=cpustate->program->read_byte(++S);
+}
+
+INLINE void lh5801_rti(lh5801_state *cpustate)
+{
+ P=cpustate->program->read_byte(++S)<<8;
+ P|=cpustate->program->read_byte(++S);
+ cpustate->t=cpustate->program->read_byte(++S);
+}
+
+INLINE void lh5801_push(lh5801_state *cpustate, UINT8 data)
+{
+ cpustate->program->write_byte(S--, data);
+}
+
+INLINE void lh5801_push_word(lh5801_state *cpustate, UINT16 data)
+{
+ cpustate->program->write_byte(S--, data&0xff);
+ cpustate->program->write_byte(S--, data>>8);
+}
+
+INLINE void lh5801_jmp(lh5801_state *cpustate, UINT16 adr)
+{
+ P=adr;
+}
+
+INLINE void lh5801_branch_plus(lh5801_state *cpustate, int doit)
+{
+ UINT8 t=cpustate->direct->read_decrypted_byte(P++);
+ if (doit) {
+ cpustate->icount-=3;
+ P+=t;
+ }
+}
+
+INLINE void lh5801_branch_minus(lh5801_state *cpustate, int doit)
+{
+ UINT8 t=cpustate->direct->read_decrypted_byte(P++);
+ if (doit) {
+ cpustate->icount-=3;
+ P-=t;
+ }
+}
+
+INLINE void lh5801_lop(lh5801_state *cpustate)
+{
+ UINT8 t=cpustate->direct->read_decrypted_byte(P++);
+ cpustate->icount-=8;
+ if (UL--) {
+ cpustate->icount-=3;
+ P-=t;
+ }
+}
+
+INLINE void lh5801_sjp(lh5801_state *cpustate)
+{
+ UINT16 n=lh5801_readop_word(cpustate);
+ lh5801_push_word(cpustate,P);
+ P=n;
+}
+
+INLINE void lh5801_vector(lh5801_state *cpustate, int doit, int nr)
+{
+ if (doit) {
+ lh5801_push_word(cpustate,P);
+ P=cpustate->program->read_byte(0xff00+nr)<<8;
+ P|=cpustate->program->read_byte(0xff00+nr+1);
+ cpustate->icount-=21-8;
+ }
+ cpustate->t&=~Z; // after the jump!?
+}
+
+INLINE void lh5801_aex(lh5801_state *cpustate)
+{
+ UINT8 t=cpustate->a;
+ cpustate->a=(t<<4)|(t>>4);
+ // flags?
+}
+
+INLINE void lh5801_drl(lh5801_state *cpustate, address_space *space, int adr)
+{
+ UINT16 t=cpustate->a|(space->read_byte(adr)<<8);
+
+ cpustate->a=t>>8;
+ space->write_byte(adr,t>>4);
+}
+
+INLINE void lh5801_drr(lh5801_state *cpustate, address_space *space, int adr)
+{
+ UINT16 t=space->read_byte(adr)|(cpustate->a<<8);
+
+ cpustate->a=t;
+ space->write_byte(adr,t>>4);
+}
+
+INLINE void lh5801_rol(lh5801_state *cpustate)
+{
+ // maybe use of the adder
+ int n = cpustate->a;
+ cpustate->a = (n<<1) | (cpustate->t&C);
+ // flags cvhz
+ cpustate->t&=~(H|V|Z|C);
+ if (n&0x80) cpustate->t|=C;
+ if (!cpustate->a) cpustate->t|=Z;
+ if (cpustate->a & 0x10) cpustate->t|=H;
+ if ((BIT(n,6) && !BIT(n,7)) || (!BIT(n,6) && BIT(n,7))) cpustate->t|=V;
+}
+
+INLINE void lh5801_ror(lh5801_state *cpustate)
+{
+ int n = cpustate->a;
+ cpustate->a=(n | ((cpustate->t&C)<<8))>>1;
+ // flags cvhz
+ cpustate->t&=~(H|V|Z|C);
+ if (n&0x01) cpustate->t|=C;
+ if (!cpustate->a) cpustate->t|=Z;
+ if (cpustate->a & 0x08) cpustate->t|=H;
+ if ((BIT(n,0) && BIT(cpustate->a,1)) || (BIT(cpustate->a,0) && BIT(n,1))) cpustate->t|=V;
+}
+
+INLINE void lh5801_shl(lh5801_state *cpustate)
+{
+ int n = cpustate->a;
+ cpustate->a<<=1;
+ // flags cvhz
+ cpustate->t&=~(H|V|Z|C);
+ if (n&0x80) cpustate->t|=C;
+ if (!cpustate->a) cpustate->t|=Z;
+ if (cpustate->a & 0x10) cpustate->t|=H;
+ if ((BIT(n,6) && !BIT(n,7)) || (!BIT(n,6) && BIT(n,7))) cpustate->t|=V;
+}
+
+INLINE void lh5801_shr(lh5801_state *cpustate)
+{
+ int n = cpustate->a;
+ cpustate->a>>=1;
+ // flags cvhz
+ cpustate->t&=~(H|V|Z|C);
+ if (n & 0x01) cpustate->t|=C;
+ if (!cpustate->a) cpustate->t|=Z;
+ if (cpustate->a & 0x08) cpustate->t|=H;
+ if ((BIT(n,0) && BIT(cpustate->a,1)) || (BIT(cpustate->a,0) && BIT(n,1))) cpustate->t|=V;
+}
+
+INLINE void lh5801_am(lh5801_state *cpustate, int value)
+{
+ cpustate->tm=value;
+ // jfkas?jfkl?jkd?
+}
+
+INLINE void lh5801_ita(lh5801_state *cpustate)
+{
+ if (cpustate->config&&cpustate->config->in) {
+ cpustate->a=cpustate->config->in(cpustate->device);
+ } else {
+ cpustate->a=0;
+ }
+ cpustate->t&=~Z;
+ if (!cpustate->a) cpustate->t|=Z;
+}
+
+static void lh5801_instruction_fd(lh5801_state *cpustate)
+{
+ int oper;
+ int adr;
+
+ oper=cpustate->direct->read_decrypted_byte(P++);
+ switch (oper) {
+ case 0x01: lh5801_sbc(cpustate,cpustate->io->read_byte(X)); cpustate->icount-=11;break;
+ case 0x03: lh5801_adc(cpustate,cpustate->io->read_byte(X)); cpustate->icount-=11;break;
+ case 0x05: lh5801_lda(cpustate,cpustate->io->read_byte(X)); cpustate->icount-=10;break;
+ case 0x07: lh5801_cpa(cpustate,cpustate->a, cpustate->io->read_byte(X)); cpustate->icount-=11;break;
+ case 0x08: X=X;cpustate->icount-=11;break; //!!!
+ case 0x09: lh5801_and(cpustate,cpustate->io->read_byte(X)); cpustate->icount-=11;break;
+ case 0x0a: lh5801_pop_word(cpustate,&cpustate->x); cpustate->icount-=15;break;
+ case 0x0b: lh5801_ora(cpustate,cpustate->io->read_byte(X)); cpustate->icount-=11;break;
+ case 0x0c: lh5801_dcs(cpustate,cpustate->io->read_byte(X)); cpustate->icount-=17; break;
+ case 0x0d: lh5801_eor(cpustate,cpustate->io->read_byte(X)); cpustate->icount-=11;break;
+ case 0x0e: cpustate->io->write_byte(X,cpustate->a); cpustate->icount-=10;break;
+ case 0x0f: lh5801_bit(cpustate,cpustate->io->read_byte(X),cpustate->a); cpustate->icount-=11;break;
+ case 0x11: lh5801_sbc(cpustate,cpustate->io->read_byte(Y)); cpustate->icount-=11;break;
+ case 0x13: lh5801_adc(cpustate,cpustate->io->read_byte(Y)); cpustate->icount-=11;break;
+ case 0x15: lh5801_lda(cpustate,cpustate->io->read_byte(Y)); cpustate->icount-=10;break;
+ case 0x17: lh5801_cpa(cpustate,cpustate->a, cpustate->io->read_byte(Y)); cpustate->icount-=11;break;
+ case 0x18: X=Y;cpustate->icount-=11;break;
+ case 0x19: lh5801_and(cpustate,cpustate->io->read_byte(Y)); cpustate->icount-=11;break;
+ case 0x1a: lh5801_pop_word(cpustate,&cpustate->y); cpustate->icount-=15;break;
+ case 0x1b: lh5801_ora(cpustate,cpustate->io->read_byte(Y)); cpustate->icount-=11;break;
+ case 0x1c: lh5801_dcs(cpustate,cpustate->io->read_byte(Y)); cpustate->icount-=17; break;
+ case 0x1d: lh5801_eor(cpustate,cpustate->io->read_byte(Y)); cpustate->icount-=11;break;
+ case 0x1e: cpustate->io->write_byte(Y,cpustate->a); cpustate->icount-=10;break;
+ case 0x1f: lh5801_bit(cpustate,cpustate->io->read_byte(Y),cpustate->a); cpustate->icount-=11;break;
+ case 0x21: lh5801_sbc(cpustate,cpustate->io->read_byte(U)); cpustate->icount-=11;break;
+ case 0x23: lh5801_adc(cpustate,cpustate->io->read_byte(U)); cpustate->icount-=11;break;
+ case 0x25: lh5801_lda(cpustate,cpustate->io->read_byte(U)); cpustate->icount-=10;break;
+ case 0x27: lh5801_cpa(cpustate,cpustate->a, cpustate->io->read_byte(U)); cpustate->icount-=11;break;
+ case 0x28: X=U;cpustate->icount-=11;break;
+ case 0x29: lh5801_and(cpustate,cpustate->io->read_byte(U)); cpustate->icount-=11;break;
+ case 0x2a: lh5801_pop_word(cpustate,&cpustate->u); cpustate->icount-=15;break;
+ case 0x2b: lh5801_ora(cpustate,cpustate->io->read_byte(U)); cpustate->icount-=11;break;
+ case 0x2c: lh5801_dcs(cpustate,cpustate->io->read_byte(U)); cpustate->icount-=17; break;
+ case 0x2d: lh5801_eor(cpustate,cpustate->io->read_byte(U)); cpustate->icount-=11;break;
+ case 0x2e: cpustate->io->write_byte(U,cpustate->a); cpustate->icount-=10;break;
+ case 0x2f: lh5801_bit(cpustate,cpustate->io->read_byte(U),cpustate->a); cpustate->icount-=11;break;
+ case 0x40: lh5801_inc(cpustate,&XH);cpustate->icount-=9;break;
+ case 0x42: lh5801_dec(cpustate,&XH);cpustate->icount-=9;break;
+ case 0x48: X=S;cpustate->icount-=11;break;
+ case 0x49: lh5801_and_mem(cpustate, cpustate->io, X, cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=17;break;
+ case 0x4a: X=X;cpustate->icount-=11;break; //!!!
+ case 0x4b: lh5801_ora_mem(cpustate, cpustate->io, X, cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=17;break;
+ case 0x4c: cpustate->bf=0;/*off !*/ cpustate->icount-=8;break;
+ case 0x4d: lh5801_bit(cpustate,cpustate->io->read_byte(X), cpustate->direct->read_decrypted_byte(P++));cpustate->icount-=14;break;
+ case 0x4e: S=X;cpustate->icount-=11;break;
+ case 0x4f: lh5801_add_mem(cpustate, cpustate->io, X, cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=17;break;
+ case 0x50: lh5801_inc(cpustate,&YH);cpustate->icount-=9;break;
+ case 0x52: lh5801_dec(cpustate,&YH);cpustate->icount-=9;break;
+ case 0x58: X=P;cpustate->icount-=11;break;
+ case 0x59: lh5801_and_mem(cpustate, cpustate->io, Y, cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=17;break;
+ case 0x5a: Y=X;cpustate->icount-=11;break;
+ case 0x5b: lh5801_ora_mem(cpustate, cpustate->io, Y, cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=17;break;
+ case 0x5d: lh5801_bit(cpustate,cpustate->io->read_byte(Y), cpustate->direct->read_decrypted_byte(P++));cpustate->icount-=14;break;
+ case 0x5e: lh5801_jmp(cpustate,X);cpustate->icount-=11;break; // P=X
+ case 0x5f: lh5801_add_mem(cpustate, cpustate->io, Y, cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=17;break;
+ case 0x60: lh5801_inc(cpustate,&UH);cpustate->icount-=9;break;
+ case 0x62: lh5801_dec(cpustate,&UH);cpustate->icount-=9;break;
+ case 0x69: lh5801_and_mem(cpustate, cpustate->io, U, cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=17;break;
+ case 0x6a: U=X;cpustate->icount-=11;break;
+ case 0x6b: lh5801_ora_mem(cpustate, cpustate->io, U, cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=17;break;
+ case 0x6d: lh5801_bit(cpustate,cpustate->io->read_byte(X), cpustate->direct->read_decrypted_byte(P++));cpustate->icount-=14;break;
+ case 0x6f: lh5801_add_mem(cpustate, cpustate->io, U, cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=17;break;
+ case 0x81: cpustate->t|=IE; /*sie !*/cpustate->icount-=8;break;
+ case 0x88: lh5801_push_word(cpustate,X); cpustate->icount-=14;break;
+ case 0x8a: lh5801_pop(cpustate); cpustate->icount-=12; break;
+ case 0x8c: lh5801_dca(cpustate,cpustate->io->read_byte(X)); cpustate->icount-=19; break;
+ case 0x8e: /*cdv clears internal devider*/cpustate->icount-=8;break;
+ case 0x98: lh5801_push_word(cpustate,Y); cpustate->icount-=14;break;
+ case 0x9c: lh5801_dca(cpustate,cpustate->io->read_byte(Y)); cpustate->icount-=19; break;
+ case 0xa1: lh5801_sbc(cpustate,cpustate->io->read_byte(lh5801_readop_word(cpustate))); cpustate->icount-=17;break;
+ case 0xa3: lh5801_adc(cpustate,cpustate->io->read_byte(lh5801_readop_word(cpustate))); cpustate->icount-=17;break;
+ case 0xa5: lh5801_lda(cpustate,cpustate->io->read_byte(lh5801_readop_word(cpustate))); cpustate->icount-=16;break;
+ case 0xa7: lh5801_cpa(cpustate,cpustate->a, cpustate->io->read_byte(lh5801_readop_word(cpustate))); cpustate->icount-=17;break;
+ case 0xa8: lh5801_push_word(cpustate,U); cpustate->icount-=14;break;
+ case 0xa9: lh5801_and(cpustate,cpustate->io->read_byte(lh5801_readop_word(cpustate))); cpustate->icount-=17;break;
+ case 0xaa: lh5801_lda(cpustate,cpustate->t); cpustate->icount-=9;break;
+ case 0xab: lh5801_ora(cpustate,cpustate->io->read_byte(lh5801_readop_word(cpustate))); cpustate->icount-=17;break;
+ case 0xac: lh5801_dca(cpustate,cpustate->io->read_byte(U)); cpustate->icount-=19; break;
+ case 0xad: lh5801_eor(cpustate,cpustate->io->read_byte(lh5801_readop_word(cpustate))); cpustate->icount-=17;break;
+ case 0xae: cpustate->io->write_byte(lh5801_readop_word(cpustate),cpustate->a); cpustate->icount-=16;break;
+ case 0xaf: lh5801_bit(cpustate,cpustate->io->read_byte(lh5801_readop_word(cpustate)),cpustate->a); cpustate->icount-=17;break;
+ case 0xb1: /*hlt*/cpustate->icount-=8;break;
+ case 0xba: lh5801_ita(cpustate);cpustate->icount-=9;break;
+ case 0xbe: cpustate->t&=~IE; /*rie !*/cpustate->icount-=8;break;
+ case 0xc0: cpustate->dp=0; /*rdp !*/cpustate->icount-=8;break;
+ case 0xc1: cpustate->dp=1; /*sdp !*/cpustate->icount-=8;break;
+ case 0xc8: lh5801_push(cpustate,cpustate->a); cpustate->icount-=11;break;
+ case 0xca: lh5801_adr(cpustate,&cpustate->x);cpustate->icount-=11;break;
+ case 0xcc: /*atp sends a to data bus*/cpustate->icount-=9;break;
+ case 0xce: lh5801_am(cpustate,cpustate->a); cpustate->icount-=9; break;
+ case 0xd3: lh5801_drr(cpustate, cpustate->io, X); cpustate->icount-=16; break;
+ case 0xd7: lh5801_drl(cpustate, cpustate->io, X); cpustate->icount-=16; break;
+ case 0xda: lh5801_adr(cpustate,&cpustate->y);cpustate->icount-=11;break;
+ case 0xde: lh5801_am(cpustate,cpustate->a|0x100); cpustate->icount-=9; break;
+ case 0xea: lh5801_adr(cpustate,&cpustate->u);cpustate->icount-=11;break;
+ case 0xe9:
+ adr=lh5801_readop_word(cpustate);
+ lh5801_and_mem(cpustate, cpustate->io, adr, cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=23;
+ break;
+ case 0xeb:
+ adr=lh5801_readop_word(cpustate);
+ lh5801_ora_mem(cpustate, cpustate->io, adr, cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=23;
+ break;
+ case 0xec: cpustate->t=cpustate->a; cpustate->icount-=9;break;
+ case 0xed:
+ adr=lh5801_readop_word(cpustate);
+ lh5801_bit(cpustate,cpustate->io->read_byte(adr), cpustate->direct->read_decrypted_byte(P++));
+ cpustate->icount-=20;break;
+ case 0xef:
+ adr=lh5801_readop_word(cpustate);
+ lh5801_add_mem(cpustate, cpustate->io, adr, cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=23;
+ break;
+
+ default:
+ logerror("lh5801 illegal opcode at %.4x fd%.2x\n",P-2, oper);
+ }
+}
+
+static void lh5801_instruction(lh5801_state *cpustate)
+{
+ int oper;
+ int adr;
+
+ oper=cpustate->direct->read_decrypted_byte(P++);
+ switch (oper) {
+ case 0x00: lh5801_sbc(cpustate,XL); cpustate->icount-=6;break;
+ case 0x01: lh5801_sbc(cpustate,cpustate->program->read_byte(X)); cpustate->icount-=7;break;
+ case 0x02: lh5801_adc(cpustate,XL); cpustate->icount-=6;break;
+ case 0x03: lh5801_adc(cpustate,cpustate->program->read_byte(X)); cpustate->icount-=7;break;
+ case 0x04: lh5801_lda(cpustate,XL); cpustate->icount-=5;break;
+ case 0x05: lh5801_lda(cpustate,cpustate->program->read_byte(X)); cpustate->icount-=6;break;
+ case 0x06: lh5801_cpa(cpustate,cpustate->a, XL); cpustate->icount-=6;break;
+ case 0x07: lh5801_cpa(cpustate,cpustate->a, cpustate->program->read_byte(X)); cpustate->icount-=7;break;
+ case 0x08: XH=cpustate->a; cpustate->icount-=5; break;
+ case 0x09: lh5801_and(cpustate,cpustate->program->read_byte(X)); cpustate->icount-=7;break;
+ case 0x0a: XL=cpustate->a; cpustate->icount-=5; break;
+ case 0x0b: lh5801_ora(cpustate,cpustate->program->read_byte(X)); cpustate->icount-=7;break;
+ case 0x0c: lh5801_dcs(cpustate,cpustate->program->read_byte(X)); cpustate->icount-=13; break;
+ case 0x0d: lh5801_eor(cpustate,cpustate->program->read_byte(X)); cpustate->icount-=7;break;
+ case 0x0e: cpustate->program->write_byte(X,cpustate->a); cpustate->icount-=6;break;
+ case 0x0f: lh5801_bit(cpustate,cpustate->program->read_byte(X),cpustate->a); cpustate->icount-=7;break;
+ case 0x10: lh5801_sbc(cpustate,YL); cpustate->icount-=6;break;
+ case 0x11: lh5801_sbc(cpustate,cpustate->program->read_byte(Y)); cpustate->icount-=7;break;
+ case 0x12: lh5801_adc(cpustate,YL); cpustate->icount-=6;break;
+ case 0x13: lh5801_adc(cpustate,cpustate->program->read_byte(Y)); cpustate->icount-=7;break;
+ case 0x14: lh5801_lda(cpustate,YL); cpustate->icount-=5;break;
+ case 0x15: lh5801_lda(cpustate,cpustate->program->read_byte(Y)); cpustate->icount-=6;break;
+ case 0x16: lh5801_cpa(cpustate,cpustate->a, YL); cpustate->icount-=6;break;
+ case 0x17: lh5801_cpa(cpustate,cpustate->a, cpustate->program->read_byte(Y)); cpustate->icount-=7;break;
+ case 0x18: YH=cpustate->a; cpustate->icount-=5; break;
+ case 0x19: lh5801_and(cpustate,cpustate->program->read_byte(Y)); cpustate->icount-=7;break;
+ case 0x1a: YL=cpustate->a; cpustate->icount-=5; break;
+ case 0x1b: lh5801_ora(cpustate,cpustate->program->read_byte(Y)); cpustate->icount-=7;break;
+ case 0x1c: lh5801_dcs(cpustate,cpustate->program->read_byte(Y)); cpustate->icount-=13; break;
+ case 0x1d: lh5801_eor(cpustate,cpustate->program->read_byte(Y)); cpustate->icount-=7;break;
+ case 0x1e: cpustate->program->write_byte(Y,cpustate->a); cpustate->icount-=6;break;
+ case 0x1f: lh5801_bit(cpustate,cpustate->program->read_byte(Y),cpustate->a); cpustate->icount-=7;break;
+ case 0x20: lh5801_sbc(cpustate,UL); cpustate->icount-=6;break;
+ case 0x21: lh5801_sbc(cpustate,cpustate->program->read_byte(U)); cpustate->icount-=7;break;
+ case 0x22: lh5801_adc(cpustate,UL); cpustate->icount-=6;break;
+ case 0x23: lh5801_adc(cpustate,cpustate->program->read_byte(U)); cpustate->icount-=7;break;
+ case 0x24: lh5801_lda(cpustate,UL); cpustate->icount-=5;break;
+ case 0x25: lh5801_lda(cpustate,cpustate->program->read_byte(U)); cpustate->icount-=6;break;
+ case 0x26: lh5801_cpa(cpustate,cpustate->a, UL); cpustate->icount-=6;break;
+ case 0x27: lh5801_cpa(cpustate,cpustate->a, cpustate->program->read_byte(U)); cpustate->icount-=7;break;
+ case 0x28: UH=cpustate->a; cpustate->icount-=5; break;
+ case 0x29: lh5801_and(cpustate,cpustate->program->read_byte(U)); cpustate->icount-=7;break;
+ case 0x2a: UL=cpustate->a; cpustate->icount-=5; break;
+ case 0x2b: lh5801_ora(cpustate,cpustate->program->read_byte(U)); cpustate->icount-=7;break;
+ case 0x2c: lh5801_dcs(cpustate,cpustate->program->read_byte(U)); cpustate->icount-=13; break;
+ case 0x2d: lh5801_eor(cpustate,cpustate->program->read_byte(U)); cpustate->icount-=7;break;
+ case 0x2e: cpustate->program->write_byte(U,cpustate->a); cpustate->icount-=6;break;
+ case 0x2f: lh5801_bit(cpustate,cpustate->program->read_byte(U),cpustate->a); cpustate->icount-=7;break;
+ case 0x38: /*nop*/cpustate->icount-=5;break;
+ case 0x40: lh5801_inc(cpustate,&XL);cpustate->icount-=5;break;
+ case 0x41: lh5801_sin(cpustate,&cpustate->x); cpustate->icount-=6;break;
+ case 0x42: lh5801_dec(cpustate,&XL);cpustate->icount-=5;break;
+ case 0x43: lh5801_sde(cpustate,&cpustate->x); cpustate->icount-=6;break;
+ case 0x44: X++;cpustate->icount-=5;break;
+ case 0x45: lh5801_lin(cpustate,&cpustate->x);cpustate->icount-=6;break;
+ case 0x46: X--;cpustate->icount-=5;break;
+ case 0x47: lh5801_lde(cpustate,&cpustate->x);cpustate->icount-=6;break;
+ case 0x48: XH=cpustate->direct->read_decrypted_byte(P++);cpustate->icount-=6;break;
+ case 0x49: lh5801_and_mem(cpustate, cpustate->program, X, cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=13;break;
+ case 0x4a: XL=cpustate->direct->read_decrypted_byte(P++);cpustate->icount-=6;break;
+ case 0x4b: lh5801_ora_mem(cpustate, cpustate->program, X, cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=13;break;
+ case 0x4c: lh5801_cpa(cpustate,XH, cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=7;break;
+ case 0x4d: lh5801_bit(cpustate,cpustate->program->read_byte(X), cpustate->direct->read_decrypted_byte(P++));cpustate->icount-=10;break;
+ case 0x4e: lh5801_cpa(cpustate,XL, cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=7;break;
+ case 0x4f: lh5801_add_mem(cpustate, cpustate->program, X, cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=13;break;
+ case 0x50: lh5801_inc(cpustate,&YL);cpustate->icount-=5;break;
+ case 0x51: lh5801_sin(cpustate,&cpustate->y); cpustate->icount-=6;break;
+ case 0x52: lh5801_dec(cpustate,&YL);cpustate->icount-=5;break;
+ case 0x53: lh5801_sde(cpustate,&cpustate->y); cpustate->icount-=6;break;
+ case 0x54: Y++;cpustate->icount-=5;break;
+ case 0x55: lh5801_lin(cpustate,&cpustate->y);cpustate->icount-=6;break;
+ case 0x56: Y--;cpustate->icount-=5;break;
+ case 0x57: lh5801_lde(cpustate,&cpustate->y);cpustate->icount-=6;break;
+ case 0x58: YH=cpustate->direct->read_decrypted_byte(P++);cpustate->icount-=6;break;
+ case 0x59: lh5801_and_mem(cpustate, cpustate->program, Y, cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=13;break;
+ case 0x5a: YL=cpustate->direct->read_decrypted_byte(P++);cpustate->icount-=6;break;
+ case 0x5b: lh5801_ora_mem(cpustate, cpustate->program, Y, cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=13;break;
+ case 0x5c: lh5801_cpa(cpustate,YH, cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=7;break;
+ case 0x5d: lh5801_bit(cpustate,cpustate->program->read_byte(Y), cpustate->direct->read_decrypted_byte(P++));cpustate->icount-=10;break;
+ case 0x5e: lh5801_cpa(cpustate,YL, cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=7;break;
+ case 0x5f: lh5801_add_mem(cpustate, cpustate->program, Y, cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=13;break;
+ case 0x60: lh5801_inc(cpustate,&UL);cpustate->icount-=5;break;
+ case 0x61: lh5801_sin(cpustate,&cpustate->u); cpustate->icount-=6;break;
+ case 0x62: lh5801_dec(cpustate,&UL);cpustate->icount-=5;break;
+ case 0x63: lh5801_sde(cpustate,&cpustate->u); cpustate->icount-=6;break;
+ case 0x64: U++;cpustate->icount-=5;break;
+ case 0x65: lh5801_lin(cpustate,&cpustate->u);cpustate->icount-=6;break;
+ case 0x66: U--;cpustate->icount-=5;break;
+ case 0x67: lh5801_lde(cpustate,&cpustate->u);cpustate->icount-=6;break;
+ case 0x68: UH=cpustate->direct->read_decrypted_byte(P++);cpustate->icount-=6;break;
+ case 0x69: lh5801_and_mem(cpustate, cpustate->program, U, cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=13;break;
+ case 0x6a: UL=cpustate->direct->read_decrypted_byte(P++);cpustate->icount-=6;break;
+ case 0x6b: lh5801_ora_mem(cpustate, cpustate->program, U, cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=13;break;
+ case 0x6c: lh5801_cpa(cpustate,UH, cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=7;break;
+ case 0x6d: lh5801_bit(cpustate,cpustate->program->read_byte(U), cpustate->direct->read_decrypted_byte(P++));cpustate->icount-=10;break;
+ case 0x6e: lh5801_cpa(cpustate,UL, cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=7;break;
+ case 0x6f: lh5801_add_mem(cpustate, cpustate->program, U, cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=13;break;
+ case 0x80: lh5801_sbc(cpustate,XH); cpustate->icount-=6;break;
+ case 0x81: lh5801_branch_plus(cpustate,!(cpustate->t&C)); cpustate->icount-=8; break;
+ case 0x82: lh5801_adc(cpustate,XH); cpustate->icount-=6;break;
+ case 0x83: lh5801_branch_plus(cpustate,cpustate->t&C); cpustate->icount-=8; break;
+ case 0x84: lh5801_lda(cpustate,XH); cpustate->icount-=5;break;
+ case 0x85: lh5801_branch_plus(cpustate,!(cpustate->t&H)); cpustate->icount-=8; break;
+ case 0x86: lh5801_cpa(cpustate,cpustate->a, XH); cpustate->icount-=6;break;
+ case 0x87: lh5801_branch_plus(cpustate,cpustate->t&H); cpustate->icount-=8; break;
+ case 0x88: lh5801_lop(cpustate); break;
+ case 0x89: lh5801_branch_plus(cpustate,!(cpustate->t&Z)); cpustate->icount-=8; break;
+ case 0x8a: lh5801_rti(cpustate); cpustate->icount-=14; break;
+ case 0x8b: lh5801_branch_plus(cpustate,cpustate->t&Z); cpustate->icount-=8; break;
+ case 0x8c: lh5801_dca(cpustate,cpustate->program->read_byte(X)); cpustate->icount-=15; break;
+ case 0x8d: lh5801_branch_plus(cpustate,!(cpustate->t&V)); cpustate->icount-=8; break;
+ case 0x8e: lh5801_branch_plus(cpustate,1); cpustate->icount-=5; break;
+ case 0x8f: lh5801_branch_plus(cpustate,cpustate->t&V); cpustate->icount-=8; break;
+ case 0x90: lh5801_sbc(cpustate,YH); cpustate->icount-=6;break;
+ case 0x91: lh5801_branch_minus(cpustate,!(cpustate->t&C)); cpustate->icount-=8; break;
+ case 0x92: lh5801_adc(cpustate,YH); cpustate->icount-=6;break;
+ case 0x93: lh5801_branch_minus(cpustate,cpustate->t&C); cpustate->icount-=8; break;
+ case 0x94: lh5801_lda(cpustate,YH); cpustate->icount-=5;break;
+ case 0x95: lh5801_branch_minus(cpustate,!(cpustate->t&H)); cpustate->icount-=8; break;
+ case 0x96: lh5801_cpa(cpustate,cpustate->a, YH); cpustate->icount-=6;break;
+ case 0x97: lh5801_branch_minus(cpustate,cpustate->t&H); cpustate->icount-=8; break;
+ case 0x99: lh5801_branch_minus(cpustate,!(cpustate->t&Z)); cpustate->icount-=8; break;
+ case 0x9a: lh5801_rtn(cpustate); cpustate->icount-=11; break;
+ case 0x9b: lh5801_branch_minus(cpustate,cpustate->t&Z); cpustate->icount-=8; break;
+ case 0x9c: lh5801_dca(cpustate,cpustate->program->read_byte(Y)); cpustate->icount-=15; break;
+ case 0x9d: lh5801_branch_minus(cpustate,!(cpustate->t&V)); cpustate->icount-=8; break;
+ case 0x9e: lh5801_branch_minus(cpustate,1); cpustate->icount-=6; break;
+ case 0x9f: lh5801_branch_minus(cpustate,cpustate->t&V); cpustate->icount-=8; break;
+ case 0xa0: lh5801_sbc(cpustate,UH); cpustate->icount-=6;break;
+ case 0xa2: lh5801_adc(cpustate,UH); cpustate->icount-=6;break;
+ case 0xa1: lh5801_sbc(cpustate,cpustate->program->read_byte(lh5801_readop_word(cpustate))); cpustate->icount-=13;break;
+ case 0xa3: lh5801_adc(cpustate,cpustate->program->read_byte(lh5801_readop_word(cpustate))); cpustate->icount-=13;break;
+ case 0xa4: lh5801_lda(cpustate,UH); cpustate->icount-=5;break;
+ case 0xa5: lh5801_lda(cpustate,cpustate->program->read_byte(lh5801_readop_word(cpustate))); cpustate->icount-=12;break;
+ case 0xa6: lh5801_cpa(cpustate,cpustate->a, UH); cpustate->icount-=6;break;
+ case 0xa7: lh5801_cpa(cpustate,cpustate->a, cpustate->program->read_byte(lh5801_readop_word(cpustate))); cpustate->icount-=13;break;
+ case 0xa8: cpustate->pv=1;/*spv!*/ cpustate->icount-=4; break;
+ case 0xa9: lh5801_and(cpustate,cpustate->program->read_byte(lh5801_readop_word(cpustate))); cpustate->icount-=13;break;
+ case 0xaa: S=lh5801_readop_word(cpustate);cpustate->icount-=6;break;
+ case 0xab: lh5801_ora(cpustate,cpustate->program->read_byte(lh5801_readop_word(cpustate))); cpustate->icount-=13;break;
+ case 0xac: lh5801_dca(cpustate,cpustate->program->read_byte(U)); cpustate->icount-=15; break;
+ case 0xad: lh5801_eor(cpustate,cpustate->program->read_byte(lh5801_readop_word(cpustate))); cpustate->icount-=13;break;
+ case 0xae: cpustate->program->write_byte(lh5801_readop_word(cpustate),cpustate->a); cpustate->icount-=12;break;
+ case 0xaf: lh5801_bit(cpustate,cpustate->program->read_byte(lh5801_readop_word(cpustate)),cpustate->a); cpustate->icount-=13;break;
+ case 0xb1: lh5801_sbc(cpustate,cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=7;break;
+ case 0xb3: lh5801_adc(cpustate,cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=7;break;
+ case 0xb5: lh5801_lda(cpustate,cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=6;break;
+ case 0xb7: lh5801_cpa(cpustate,cpustate->a, cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=7;break;
+ case 0xb8: cpustate->pv=0;/*rpv!*/ cpustate->icount-=4; break;
+ case 0xb9: lh5801_and(cpustate,cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=7;break;
+ case 0xba: lh5801_jmp(cpustate,lh5801_readop_word(cpustate)); cpustate->icount-=12;break;
+ case 0xbb: lh5801_ora(cpustate,cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=7;break;
+ case 0xbd: lh5801_eor(cpustate,cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=7;break;
+ case 0xbe: lh5801_sjp(cpustate); cpustate->icount-=19; break;
+ case 0xbf: lh5801_bit(cpustate,cpustate->a, cpustate->direct->read_decrypted_byte(P++));cpustate->icount-=7;break;
+ case 0xc1: lh5801_vector(cpustate,!(cpustate->t&C), cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=8;break;
+ case 0xc3: lh5801_vector(cpustate,cpustate->t&C, cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=8;break;
+ case 0xc5: lh5801_vector(cpustate,!(cpustate->t&H), cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=8;break;
+ case 0xc7: lh5801_vector(cpustate,cpustate->t&H, cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=8;break;
+ case 0xc9: lh5801_vector(cpustate,!(cpustate->t&Z), cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=8;break;
+ case 0xcb: lh5801_vector(cpustate,cpustate->t&Z, cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=8;break;
+ case 0xcd: lh5801_vector(cpustate,1, cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=7;break;
+ case 0xcf: lh5801_vector(cpustate,cpustate->t&V, cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=8;break;
+ case 0xd1: lh5801_ror(cpustate); cpustate->icount-=6; break;
+ case 0xd3: lh5801_drr(cpustate, cpustate->program, X); cpustate->icount-=12; break;
+ case 0xd5: lh5801_shr(cpustate); cpustate->icount-=6; break;
+ case 0xd7: lh5801_drl(cpustate, cpustate->program, X); cpustate->icount-=12; break;
+ case 0xd9: lh5801_shl(cpustate); cpustate->icount-=6; break;
+ case 0xdb: lh5801_rol(cpustate); cpustate->icount-=6; break;
+ case 0xdd: lh5801_inc(cpustate,&cpustate->a);cpustate->icount-=5;break;
+ case 0xdf: lh5801_dec(cpustate,&cpustate->a);cpustate->icount-=5;break;
+ case 0xe1: cpustate->pu=1;/*spu!*/ cpustate->icount-=4; break;
+ case 0xe3: cpustate->pu=0;/*rpu!*/ cpustate->icount-=4; break;
+ case 0xe9:
+ adr=lh5801_readop_word(cpustate);lh5801_and_mem(cpustate, cpustate->program, adr, cpustate->direct->read_decrypted_byte(P++));
+ cpustate->icount-=19;break;
+ case 0xeb:
+ adr=lh5801_readop_word(cpustate);lh5801_ora_mem(cpustate, cpustate->program, adr, cpustate->direct->read_decrypted_byte(P++));
+ cpustate->icount-=19;break;
+ case 0xed:
+ adr=lh5801_readop_word(cpustate);lh5801_bit(cpustate,cpustate->program->read_byte(adr), cpustate->direct->read_decrypted_byte(P++));
+ cpustate->icount-=16;break;
+ case 0xef:
+ adr=lh5801_readop_word(cpustate);
+ lh5801_add_mem(cpustate, cpustate->program, adr, cpustate->direct->read_decrypted_byte(P++)); cpustate->icount-=19;
+ break;
+ case 0xf1: lh5801_aex(cpustate); cpustate->icount-=6; break;
+ case 0xf5: cpustate->program->write_byte(Y++, cpustate->program->read_byte(X++)); cpustate->icount-=7; break; //tin
+ case 0xf7: lh5801_cpa(cpustate,cpustate->a, cpustate->program->read_byte(X++));cpustate->icount-=7; break; //cin
+ case 0xf9: cpustate->t&=~C;cpustate->icount-=4;break;
+ case 0xfb: cpustate->t|=C;cpustate->icount-=4;break;
+ case 0xfd: lh5801_instruction_fd(cpustate);break;
+ case 0xc0: case 0xc2: case 0xc4: case 0xc6:
+ case 0xc8: case 0xca: case 0xcc: case 0xce:
+ case 0xd0: case 0xd2: case 0xd4: case 0xd6:
+ case 0xd8: case 0xda: case 0xdc: case 0xde:
+ case 0xe0: case 0xe2: case 0xe4: case 0xe6:
+ case 0xe8: case 0xea: case 0xec: case 0xee:
+ case 0xf0: case 0xf2: case 0xf4: case 0xf6:
+ lh5801_vector(cpustate,1, oper);cpustate->icount-=4;break;
+ default:
+ logerror("lh5801 illegal opcode at %.4x %.2x\n",P-1, oper);
+ }
+
+}
+
diff --git a/trunk/src/emu/cpu/lh5801/lh5801.c b/trunk/src/emu/cpu/lh5801/lh5801.c
new file mode 100644
index 00000000000..854e276f90a
--- /dev/null
+++ b/trunk/src/emu/cpu/lh5801/lh5801.c
@@ -0,0 +1,348 @@
+/*****************************************************************************
+ *
+ * Copyright Peter Trauner, all rights reserved.
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * peter.trauner@jk.uni-linz.ac.at
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ *
+ * 02/2011 (Sandro Ronco)
+ * - Added IO_SPACE and updated all access in ME1 memory for use it.
+ * - Implemented interrupts.
+ * - Fixed the flags in the ROL/ROR/SHL/SHR opcodes.
+ * - Fixed decimal add/sub opcodes.
+ *
+ * based on info found on an artikel for the tandy trs80 pc2
+ * and on "PC1500 Technical reference manual"
+ *
+ *****************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+
+#include "lh5801.h"
+
+#define VERBOSE 0
+
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+enum
+{
+ LH5801_T=1,
+ LH5801_P,
+ LH5801_S,
+ LH5801_U,
+ LH5801_X,
+ LH5801_Y,
+ LH5801_A,
+
+ LH5801_TM,
+ LH5801_IN,
+ LH5801_BF,
+ LH5801_PU,
+ LH5801_PV,
+ LH5801_DP,
+ LH5801_IRQ_STATE
+};
+
+typedef struct _lh5801_state lh5801_state;
+struct _lh5801_state
+{
+ const lh5801_cpu_core *config;
+ legacy_cpu_device *device;
+ address_space *program; //ME0
+ address_space *io; //ME1
+ direct_read_data *direct;
+
+ PAIR s, p, u, x, y;
+ int tm; //9 bit
+
+ UINT8 t, a;
+
+ int bf, dp, pu, pv;
+
+ UINT16 oldpc;
+
+ int irq_state;
+
+ UINT8 ir_flipflop[3]; //interrupt request flipflop: IR0, IR1, IR2
+ int lines_status[2]; //MI and NMI lines status
+
+ int idle;
+ int icount;
+};
+
+INLINE lh5801_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == LH5801);
+ return (lh5801_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+#define P cpustate->p.w.l
+#define S cpustate->s.w.l
+#define U cpustate->u.w.l
+#define UL cpustate->u.b.l
+#define UH cpustate->u.b.h
+#define X cpustate->x.w.l
+#define XL cpustate->x.b.l
+#define XH cpustate->x.b.h
+#define Y cpustate->y.w.l
+#define YL cpustate->y.b.l
+#define YH cpustate->y.b.h
+
+#define C 0x01
+#define IE 0x02
+#define Z 0x04
+#define V 0x08
+#define H 0x10
+
+/***************************************************************
+ * include the opcode macros, functions and tables
+ ***************************************************************/
+#include "5801tbl.c"
+
+static CPU_INIT( lh5801 )
+{
+ lh5801_state *cpustate = get_safe_token(device);
+
+ memset(cpustate, 0, sizeof(*cpustate));
+ cpustate->config = (const lh5801_cpu_core *) device->static_config();
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->io = device->space(AS_IO);
+ cpustate->direct = &cpustate->program->direct();
+}
+
+static CPU_RESET( lh5801 )
+{
+ lh5801_state *cpustate = get_safe_token(device);
+
+ P = (cpustate->program->read_byte(0xfffe)<<8) | cpustate->program->read_byte(0xffff);
+
+ cpustate->idle=0;
+
+ memset(cpustate->ir_flipflop, 0, sizeof(cpustate->ir_flipflop));
+ memset(cpustate->lines_status, 0, sizeof(cpustate->lines_status));
+}
+
+
+static void check_irq(device_t *device)
+{
+ lh5801_state *cpustate = get_safe_token(device);
+
+ if (cpustate->ir_flipflop[0])
+ {
+ //NMI interrupt
+ cpustate->ir_flipflop[0] = 0;
+ lh5801_push(cpustate,cpustate->t);
+ cpustate->t&=~IE;
+ lh5801_push_word(cpustate,P);
+ P = (cpustate->program->read_byte(0xfffc)<<8) | cpustate->program->read_byte(0xfffd);
+ }
+ else if (cpustate->ir_flipflop[1] && (cpustate->t & IE))
+ {
+ //counter interrupt (counter not yet implemented)
+ cpustate->ir_flipflop[1] = 0;
+ lh5801_push(cpustate,cpustate->t);
+ cpustate->t&=~IE;
+ lh5801_push_word(cpustate,P);
+ P = (cpustate->program->read_byte(0xfffa)<<8) | cpustate->program->read_byte(0xfffb);
+ }
+ else if (cpustate->ir_flipflop[2] && (cpustate->t & IE))
+ {
+ //MI interrupt
+ cpustate->ir_flipflop[2] = 0;
+ lh5801_push(cpustate, cpustate->t);
+ cpustate->t&=~IE;
+ lh5801_push_word(cpustate, P);
+ P = (cpustate->program->read_byte(0xfff8)<<8) | cpustate->program->read_byte(0xfff9);
+ }
+}
+
+
+static CPU_EXECUTE( lh5801 )
+{
+ lh5801_state *cpustate = get_safe_token(device);
+
+ do
+ {
+ check_irq(device);
+
+ if (cpustate->idle)
+ cpustate->icount = 0;
+ else
+ {
+ cpustate->oldpc = P;
+
+ debugger_instruction_hook(device, P);
+ lh5801_instruction(cpustate);
+ }
+
+ } while (cpustate->icount > 0);
+}
+
+static void set_irq_line(lh5801_state *cpustate, int irqline, int state)
+{
+ switch( irqline)
+ {
+ case LH5801_LINE_MI:
+ if (cpustate->lines_status[0] == CLEAR_LINE && state == ASSERT_LINE)
+ {
+ cpustate->idle = 0;
+ cpustate->ir_flipflop[2] = 1;
+ }
+
+ cpustate->lines_status[0] = state;
+ break;
+ case INPUT_LINE_NMI:
+ if (cpustate->lines_status[1] == CLEAR_LINE && state == ASSERT_LINE)
+ {
+ cpustate->idle = 0;
+ cpustate->ir_flipflop[0] = 1;
+ }
+
+ cpustate->lines_status[1] = state;
+ break;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( lh5801 )
+{
+ lh5801_state *cpustate = get_safe_token(device);
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + LH5801_LINE_MI: set_irq_line(cpustate, LH5801_LINE_MI, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: set_irq_line(cpustate, INPUT_LINE_NMI, info->i); break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + LH5801_P: P = info->i; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + LH5801_S: S = info->i; break;
+ case CPUINFO_INT_REGISTER + LH5801_U: U = info->i; break;
+ case CPUINFO_INT_REGISTER + LH5801_X: X = info->i; break;
+ case CPUINFO_INT_REGISTER + LH5801_Y: Y = info->i; break;
+ case CPUINFO_INT_REGISTER + LH5801_T: cpustate->t = info->i; break;
+ case CPUINFO_INT_REGISTER + LH5801_TM: cpustate->tm = info->i; break;
+ case CPUINFO_INT_REGISTER + LH5801_BF: cpustate->bf = info->i; break;
+ case CPUINFO_INT_REGISTER + LH5801_PV: cpustate->pv = info->i; break;
+ case CPUINFO_INT_REGISTER + LH5801_PU: cpustate->pu = info->i; break;
+ case CPUINFO_INT_REGISTER + LH5801_DP: cpustate->dp = info->i; break;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+CPU_GET_INFO( lh5801 )
+{
+ lh5801_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(lh5801_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 2; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 5; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 2; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 19; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_INPUT_STATE: info->i = cpustate->irq_state; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = cpustate->oldpc; break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + LH5801_P: info->i = P; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + LH5801_S: info->i = S; break;
+ case CPUINFO_INT_REGISTER + LH5801_U: info->i = U; break;
+ case CPUINFO_INT_REGISTER + LH5801_X: info->i = X; break;
+ case CPUINFO_INT_REGISTER + LH5801_Y: info->i = Y; break;
+ case CPUINFO_INT_REGISTER + LH5801_T: info->i = cpustate->t; break;
+ case CPUINFO_INT_REGISTER + LH5801_TM: info->i = cpustate->tm; break;
+ case CPUINFO_INT_REGISTER + LH5801_IN: info->i = cpustate->config->in(device); break;
+ case CPUINFO_INT_REGISTER + LH5801_BF: info->i = cpustate->bf; break;
+ case CPUINFO_INT_REGISTER + LH5801_PV: info->i = cpustate->pv; break;
+ case CPUINFO_INT_REGISTER + LH5801_PU: info->i = cpustate->pu; break;
+ case CPUINFO_INT_REGISTER + LH5801_DP: info->i = cpustate->dp; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(lh5801); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(lh5801); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(lh5801); break;
+ case CPUINFO_FCT_EXIT: info->exit = NULL; break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(lh5801); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(lh5801); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "LH5801"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "LH5801"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0alpha"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Peter Trauner, all rights reserved."); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%s%s%s%s%s%s%s%s",
+ cpustate->t&0x80?"1":"0",
+ cpustate->t&0x40?"1":"0",
+ cpustate->t&0x20?"1":"0",
+ cpustate->t&0x10?"H":".",
+ cpustate->t&8?"V":".",
+ cpustate->t&4?"Z":".",
+ cpustate->t&2?"I":".",
+ cpustate->t&1?"C":".");
+ break;
+
+ case CPUINFO_STR_REGISTER + LH5801_P: sprintf(info->s, "P:%04X", cpustate->p.w.l); break;
+ case CPUINFO_STR_REGISTER + LH5801_S: sprintf(info->s, "S:%04X", cpustate->s.w.l); break;
+ case CPUINFO_STR_REGISTER + LH5801_U: sprintf(info->s, "U:%04X", cpustate->u.w.l); break;
+ case CPUINFO_STR_REGISTER + LH5801_X: sprintf(info->s, "X:%04X", cpustate->x.w.l); break;
+ case CPUINFO_STR_REGISTER + LH5801_Y: sprintf(info->s, "Y:%04X", cpustate->y.w.l); break;
+ case CPUINFO_STR_REGISTER + LH5801_T: sprintf(info->s, "T:%02X", cpustate->t); break;
+ case CPUINFO_STR_REGISTER + LH5801_A: sprintf(info->s, "A:%02X", cpustate->a); break;
+ case CPUINFO_STR_REGISTER + LH5801_TM: sprintf(info->s, "TM:%03X", cpustate->tm); break;
+ case CPUINFO_STR_REGISTER + LH5801_IN: sprintf(info->s, "IN:%02X", cpustate->config->in(device)); break;
+ case CPUINFO_STR_REGISTER + LH5801_PV: sprintf(info->s, "PV:%04X", cpustate->pv); break;
+ case CPUINFO_STR_REGISTER + LH5801_PU: sprintf(info->s, "PU:%04X", cpustate->pu); break;
+ case CPUINFO_STR_REGISTER + LH5801_BF: sprintf(info->s, "BF:%04X", cpustate->bf); break;
+ case CPUINFO_STR_REGISTER + LH5801_DP: sprintf(info->s, "DP:%04X", cpustate->dp); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(LH5801, lh5801);
diff --git a/trunk/src/emu/cpu/lh5801/lh5801.h b/trunk/src/emu/cpu/lh5801/lh5801.h
new file mode 100644
index 00000000000..78bc01a68c5
--- /dev/null
+++ b/trunk/src/emu/cpu/lh5801/lh5801.h
@@ -0,0 +1,85 @@
+/*****************************************************************************
+ *
+ * cpustate->h
+ * portable lh5801 emulator interface
+ *
+ * Copyright Peter Trauner, all rights reserved.
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * peter.trauner@jk.uni-linz.ac.at
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ *****************************************************************************/
+#pragma once
+
+#ifndef __LH5801_H__
+#define __LH5801_H__
+
+/*
+lh5801
+
+little endian
+
+ph, pl p
+sh, sl s
+
+xh, xl x
+yh, yl y
+uh, ul u
+
+a A
+
+0 0 0 H V Z IE C
+
+TM 9bit polynominal?
+
+pu pv disp flipflops
+
+bf flipflop (break key connected)
+
+ me0, me1 chip select for 2 64kb memory blocks
+
+in0-in7 input pins
+
+ mi maskable interrupt input (fff8/9)
+ timer fffa/b
+ nmi non .. (fffc/d)
+ reset fffe/f
+e ?
+
+
+
+lh5811 chip
+pa 8bit io
+pb 8bit io
+pc 8bit
+*/
+
+
+
+typedef UINT8 (*lh5801_in_func)(device_t *device);
+
+typedef struct _lh5801_cpu_core lh5801_cpu_core;
+struct _lh5801_cpu_core
+{
+ lh5801_in_func in;
+};
+
+// input lines
+enum
+{
+ LH5801_LINE_MI, //maskable interrupt
+};
+
+DECLARE_LEGACY_CPU_DEVICE(LH5801, lh5801);
+extern CPU_DISASSEMBLE( lh5801 );
+
+#endif /* __LH5801_H__ */
diff --git a/trunk/src/emu/cpu/lr35902/lr35902.c b/trunk/src/emu/cpu/lr35902/lr35902.c
new file mode 100644
index 00000000000..13b40d46782
--- /dev/null
+++ b/trunk/src/emu/cpu/lr35902/lr35902.c
@@ -0,0 +1,495 @@
+/*************************************************************/
+/** **/
+/** lr35902.c **/
+/** **/
+/** This file contains implementation for the GameBoy CPU. **/
+/** See lr35902.h for the relevant definitions. Please, note**/
+/** that this code can not be used to emulate a generic Z80 **/
+/** because the GameBoy version of it differs from Z80 in **/
+/** many ways. **/
+/** **/
+/** Orginal cpu code (PlayBoy) Carsten Sorensen 1998 **/
+/** MESS modifications Hans de Goede 1998 **/
+/** Adapted to new cpuintrf Juergen Buchmueller 2000 **/
+/** Adapted to new cpuintrf Anthony Kruize 2002 **/
+/** Changed reset function to **/
+/** reset all registers instead **/
+/** of just AF. Wilbert Pol 2004 **/
+/** **/
+/** 1.1: **/
+/** Removed dependency on the mess gameboy driver **/
+/** **/
+/** 1.2: **/
+/** Fixed cycle count for taking an interrupt **/
+/** Fixed cycle count for BIT X,(HL) instructions **/
+/** Fixed flags in RRCA instruction **/
+/** Fixed DAA instruction **/
+/** Fixed flags in ADD SP,n8 instruction **/
+/** Fixed flags in LD HL,SP+n8 instruction **/
+/** **/
+/** 1.3: **/
+/** Improved triggering of the HALT bug **/
+/** Added 4 cycle penalty when leaving HALT state for **/
+/** newer versions of the cpu core **/
+/** **/
+/** 1.4: **/
+/** Split fetch and execute cycles. **/
+/** **/
+/*************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "lr35902.h"
+
+#define FLAG_Z 0x80
+#define FLAG_N 0x40
+#define FLAG_H 0x20
+#define FLAG_C 0x10
+
+#define CYCLES_PASSED(X) cpustate->w.icount -= ((X) / (cpustate->w.gb_speed)); \
+ if ( cpustate->w.timer_expired_func ) { \
+ cpustate->w.timer_expired_func( cpustate->w.device, X ); \
+ }
+
+typedef struct {
+ UINT16 AF;
+ UINT16 BC;
+ UINT16 DE;
+ UINT16 HL;
+
+ UINT16 SP;
+ UINT16 PC;
+ /* Interrupt related */
+ UINT8 IE;
+ UINT8 IF;
+ int irq_state;
+ int ei_delay;
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ address_space *program;
+ int icount;
+ /* Timer stuff */
+ lr35902_timer_fired_func timer_expired_func;
+ /* Fetch & execute related */
+ int execution_state;
+ UINT8 op;
+ /* Others */
+ int gb_speed;
+ int gb_speed_change_pending;
+ int enable;
+ int doHALTbug;
+ UINT8 features;
+ const lr35902_cpu_core *config;
+} lr35902_16BitRegs;
+
+#ifdef LSB_FIRST
+typedef struct {
+ UINT8 F;
+ UINT8 A;
+ UINT8 C;
+ UINT8 B;
+ UINT8 E;
+ UINT8 D;
+ UINT8 L;
+ UINT8 H;
+} lr35902_8BitRegs;
+#else
+typedef struct {
+ UINT8 A;
+ UINT8 F;
+ UINT8 B;
+ UINT8 C;
+ UINT8 D;
+ UINT8 E;
+ UINT8 H;
+ UINT8 L;
+} lr35902_8BitRegs;
+#endif
+
+
+typedef union _lr35902_state lr35902_state;
+union _lr35902_state {
+ lr35902_16BitRegs w;
+ lr35902_8BitRegs b;
+};
+
+INLINE lr35902_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == LR35902);
+ return (lr35902_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+typedef int (*OpcodeEmulator) (lr35902_state *cpustate);
+
+#define IME 0x01
+#define HALTED 0x02
+
+/****************************************************************************/
+/* Memory functions */
+/****************************************************************************/
+
+#define mem_ReadByte(cs,A) ((UINT8)(cs)->w.program->read_byte(A))
+#define mem_WriteByte(cs,A,V) ((cs)->w.program->write_byte(A,V))
+
+INLINE UINT16 mem_ReadWord (lr35902_state *cpustate, UINT32 address)
+{
+ UINT16 value = (UINT16) mem_ReadByte (cpustate, (address + 1) & 0xffff) << 8;
+ value |= mem_ReadByte (cpustate, address);
+ return value;
+}
+
+INLINE void mem_WriteWord (lr35902_state *cpustate, UINT32 address, UINT16 value)
+{
+ mem_WriteByte (cpustate, address, value & 0xFF);
+ mem_WriteByte (cpustate, (address + 1) & 0xffff, value >> 8);
+}
+
+static const int Cycles[256] =
+{
+ 4,12, 8, 8, 4, 4, 8, 4,20, 8, 8, 8, 4, 4, 8, 4,
+ 4,12, 8, 8, 4, 4, 8, 4,12, 8, 8, 8, 4, 4, 8, 4,
+ 8,12, 8, 8, 4, 4, 8, 4, 8, 8, 8, 8, 4, 4, 8, 4,
+ 8,12, 8, 8,12,12,12, 4, 8, 8, 8, 8, 4, 4, 8, 4,
+ 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
+ 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
+ 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
+ 8, 8, 8, 8, 8, 8, 4, 8, 4, 4, 4, 4, 4, 4, 8, 4,
+ 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
+ 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
+ 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
+ 4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4, 4, 4, 4, 8, 4,
+ 8,12,12,16,12,16, 8,16, 8,16,12, 0,12,24, 8,16,
+ 8,12,12, 4,12,16, 8,16, 8,16,12, 4,12, 4, 8,16,
+ 12,12, 8, 4, 4,16, 8,16,16, 4,16, 4, 4, 4, 8,16,
+ 12,12, 8, 4, 4,16, 8,16,12, 8,16, 4, 4, 4, 8,16
+};
+
+static const int CyclesCB[256] =
+{
+ 8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,
+ 8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,
+ 8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,
+ 8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,
+ 8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8,
+ 8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8,
+ 8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8,
+ 8, 8, 8, 8, 8, 8,12, 8, 8, 8, 8, 8, 8, 8,12, 8,
+ 8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,
+ 8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,
+ 8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,
+ 8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,
+ 8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,
+ 8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,
+ 8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8,
+ 8, 8, 8, 8, 8, 8,16, 8, 8, 8, 8, 8, 8, 8,16, 8
+};
+
+static CPU_INIT( lr35902 )
+{
+ lr35902_state *cpustate = get_safe_token(device);
+
+ cpustate->w.config = (const lr35902_cpu_core *) device->static_config();
+ cpustate->w.irq_callback = irqcallback;
+ cpustate->w.device = device;
+ cpustate->w.program = device->space(AS_PROGRAM);
+}
+
+/*** Reset lr353902 registers: ******************************/
+/*** This function can be used to reset the register ***/
+/*** file before starting execution with lr35902_execute(cpustate)***/
+/*** It sets the registers to their initial values. ***/
+/************************************************************/
+static CPU_RESET( lr35902 )
+{
+ lr35902_state *cpustate = get_safe_token(device);
+
+ cpustate->w.AF = 0x0000;
+ cpustate->w.BC = 0x0000;
+ cpustate->w.DE = 0x0000;
+ cpustate->w.HL = 0x0000;
+ cpustate->w.SP = 0x0000;
+ cpustate->w.PC = 0x0000;
+ cpustate->w.timer_expired_func = NULL;
+ cpustate->w.features = LR35902_FEATURE_HALT_BUG;
+ if (cpustate->w.config)
+ {
+ if ( cpustate->w.config->regs ) {
+ cpustate->w.AF = cpustate->w.config->regs[0];
+ cpustate->w.BC = cpustate->w.config->regs[1];
+ cpustate->w.DE = cpustate->w.config->regs[2];
+ cpustate->w.HL = cpustate->w.config->regs[3];
+ cpustate->w.SP = cpustate->w.config->regs[4];
+ cpustate->w.PC = cpustate->w.config->regs[5];
+ }
+ cpustate->w.timer_expired_func = cpustate->w.config->timer_expired_func;
+ cpustate->w.features = cpustate->w.config->features;
+ }
+ cpustate->w.enable = 0;
+ cpustate->w.IE = 0;
+ cpustate->w.IF = 0;
+
+ cpustate->w.execution_state = 0;
+ cpustate->w.doHALTbug = 0;
+ cpustate->w.ei_delay = 0;
+ cpustate->w.gb_speed_change_pending = 0;
+ cpustate->w.gb_speed = 1;
+}
+
+INLINE void lr35902_ProcessInterrupts (lr35902_state *cpustate)
+{
+ UINT8 irq = cpustate->w.IE & cpustate->w.IF;
+
+ /* Interrupts should be taken after the first instruction after an EI instruction */
+ if (cpustate->w.ei_delay) {
+ cpustate->w.ei_delay = 0;
+ return;
+ }
+
+ /*
+ logerror("Attempting to process LR35902 Interrupt IRQ $%02X\n", irq);
+ logerror("Attempting to process LR35902 Interrupt IE $%02X\n", cpustate->w.IE);
+ logerror("Attempting to process LR35902 Interrupt IF $%02X\n", cpustate->w.IF);
+ */
+ if (irq)
+ {
+ int irqline = 0;
+ /*
+ logerror("LR35902 Interrupt IRQ $%02X\n", irq);
+ */
+
+ for( ; irqline < 5; irqline++ )
+ {
+ if( irq & (1<<irqline) )
+ {
+ if (cpustate->w.enable & HALTED)
+ {
+ cpustate->w.enable &= ~HALTED;
+ cpustate->w.PC++;
+ if ( cpustate->w.features & LR35902_FEATURE_HALT_BUG ) {
+ if ( ! ( cpustate->w.enable & IME ) ) {
+ /* Old cpu core (dmg/mgb/sgb) */
+ cpustate->w.doHALTbug = 1;
+ }
+ } else {
+ /* New cpu core (cgb/agb/ags) */
+ /* Adjust for internal syncing with video core */
+ /* This feature needs more investigation */
+ if ( irqline < 2 ) {
+ CYCLES_PASSED( 4 );
+ }
+ }
+ }
+ if ( cpustate->w.enable & IME ) {
+ if ( cpustate->w.irq_callback )
+ (*cpustate->w.irq_callback)(cpustate->w.device, irqline);
+ cpustate->w.enable &= ~IME;
+ cpustate->w.IF &= ~(1 << irqline);
+ CYCLES_PASSED( 20 );
+ cpustate->w.SP -= 2;
+ mem_WriteWord (cpustate, cpustate->w.SP, cpustate->w.PC);
+ cpustate->w.PC = 0x40 + irqline * 8;
+ /*logerror("LR35902 Interrupt PC $%04X\n", cpustate->w.PC );*/
+ return;
+ }
+ }
+ }
+ }
+}
+
+/************************************************************/
+/*** Execute lr35902 code for cycles cycles, return nr of ***/
+/*** cycles actually executed. ***/
+/************************************************************/
+static CPU_EXECUTE( lr35902 )
+{
+ lr35902_state *cpustate = get_safe_token(device);
+
+ do
+ {
+ if ( cpustate->w.execution_state ) {
+ UINT8 x;
+ /* Execute instruction */
+ switch( cpustate->w.op ) {
+#include "opc_main.h"
+ }
+ } else {
+ /* Fetch and count cycles */
+ lr35902_ProcessInterrupts (cpustate);
+ debugger_instruction_hook(device, cpustate->w.PC);
+ if ( cpustate->w.enable & HALTED ) {
+ CYCLES_PASSED( Cycles[0x76] );
+ cpustate->w.execution_state = 1;
+ } else {
+ cpustate->w.op = mem_ReadByte (cpustate, cpustate->w.PC++);
+ if ( cpustate->w.doHALTbug ) {
+ cpustate->w.PC--;
+ cpustate->w.doHALTbug = 0;
+ }
+ CYCLES_PASSED( Cycles[cpustate->w.op] );
+ }
+ }
+ cpustate->w.execution_state ^= 1;
+ } while (cpustate->w.icount > 0);
+}
+
+static CPU_BURN( lr35902 )
+{
+ lr35902_state *cpustate = get_safe_token(device);
+
+ if( cycles > 0 )
+ {
+ /* NOP takes 4 cycles per instruction */
+ int n = (cycles + 3) / 4;
+ cpustate->w.icount -= 4 * n;
+ }
+}
+
+static void lr35902_set_irq_line (lr35902_state *cpustate, int irqline, int state)
+{
+ /*logerror("setting irq line 0x%02x state 0x%08x\n", irqline, state);*/
+ //if( cpustate->w.irq_state == state )
+ // return;
+
+ cpustate->w.irq_state = state;
+ if( state == ASSERT_LINE )
+ {
+
+ cpustate->w.IF |= (0x01 << irqline);
+ /*logerror("LR35902 assert irq line %d ($%02X)\n", irqline, cpustate->w.IF);*/
+
+ }
+ else
+ {
+
+ cpustate->w.IF &= ~(0x01 << irqline);
+ /*logerror("LR35902 clear irq line %d ($%02X)\n", irqline, cpustate->w.IF);*/
+
+ }
+}
+
+#ifdef UNUSED_FUNCTION
+static void lr35902_clear_pending_interrupts (lr35902_state *cpustate)
+{
+ cpustate->w.IF = 0;
+}
+#endif
+
+static CPU_SET_INFO( lr35902 )
+{
+ lr35902_state *cpustate = get_safe_token(device);
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + 0:
+ case CPUINFO_INT_INPUT_STATE + 1:
+ case CPUINFO_INT_INPUT_STATE + 2:
+ case CPUINFO_INT_INPUT_STATE + 3:
+ case CPUINFO_INT_INPUT_STATE + 4: lr35902_set_irq_line(cpustate, state-CPUINFO_INT_INPUT_STATE, info->i); break;
+
+ case CPUINFO_INT_SP: cpustate->w.SP = info->i; break;
+ case CPUINFO_INT_PC: cpustate->w.PC = info->i; break;
+
+ case CPUINFO_INT_REGISTER + LR35902_PC: cpustate->w.PC = info->i; break;
+ case CPUINFO_INT_REGISTER + LR35902_SP: cpustate->w.SP = info->i; break;
+ case CPUINFO_INT_REGISTER + LR35902_AF: cpustate->w.AF = info->i; break;
+ case CPUINFO_INT_REGISTER + LR35902_BC: cpustate->w.BC = info->i; break;
+ case CPUINFO_INT_REGISTER + LR35902_DE: cpustate->w.DE = info->i; break;
+ case CPUINFO_INT_REGISTER + LR35902_HL: cpustate->w.HL = info->i; break;
+ case CPUINFO_INT_REGISTER + LR35902_IE: cpustate->w.IE = info->i; break;
+ case CPUINFO_INT_REGISTER + LR35902_IF: cpustate->w.IF = info->i; break;
+ case CPUINFO_INT_REGISTER + LR35902_SPEED: cpustate->w.gb_speed_change_pending = info->i & 0x01; break;
+ }
+}
+
+CPU_GET_INFO( lr35902 )
+{
+ lr35902_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(lr35902_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 5; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0xff; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; /* right? */ break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 16; /* right? */ break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_SP: info->i = cpustate->w.SP; break;
+ case CPUINFO_INT_PC: info->i = cpustate->w.PC; break;
+ case CPUINFO_INT_PREVIOUSPC: info->i = 0; /* TODO??? */ break;
+
+ case CPUINFO_INT_INPUT_STATE + 0:
+ case CPUINFO_INT_INPUT_STATE + 1:
+ case CPUINFO_INT_INPUT_STATE + 2:
+ case CPUINFO_INT_INPUT_STATE + 3:
+ case CPUINFO_INT_INPUT_STATE + 4: info->i = cpustate->w.IF & (1 << (state-CPUINFO_INT_INPUT_STATE)); break;
+
+ case CPUINFO_INT_REGISTER + LR35902_PC: info->i = cpustate->w.PC; break;
+ case CPUINFO_INT_REGISTER + LR35902_SP: info->i = cpustate->w.SP; break;
+ case CPUINFO_INT_REGISTER + LR35902_AF: info->i = cpustate->w.AF; break;
+ case CPUINFO_INT_REGISTER + LR35902_BC: info->i = cpustate->w.BC; break;
+ case CPUINFO_INT_REGISTER + LR35902_DE: info->i = cpustate->w.DE; break;
+ case CPUINFO_INT_REGISTER + LR35902_HL: info->i = cpustate->w.HL; break;
+ case CPUINFO_INT_REGISTER + LR35902_IE: info->i = cpustate->w.IE; break;
+ case CPUINFO_INT_REGISTER + LR35902_IF: info->i = cpustate->w.IF; break;
+ case CPUINFO_INT_REGISTER + LR35902_SPEED: info->i = 0x7E | ( ( cpustate->w.gb_speed - 1 ) << 7 ) | cpustate->w.gb_speed_change_pending; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(lr35902); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(lr35902); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(lr35902); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(lr35902); break;
+ case CPUINFO_FCT_BURN: info->burn = CPU_BURN_NAME(lr35902); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(lr35902); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->w.icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "LR35902"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Sharp LR35902"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.4"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright The MESS Team."); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c%c%c%c%c%c%c",
+ cpustate->b.F & 0x80 ? 'Z':'.',
+ cpustate->b.F & 0x40 ? 'N':'.',
+ cpustate->b.F & 0x20 ? 'H':'.',
+ cpustate->b.F & 0x10 ? 'C':'.',
+ cpustate->b.F & 0x08 ? '3':'.',
+ cpustate->b.F & 0x04 ? '2':'.',
+ cpustate->b.F & 0x02 ? '1':'.',
+ cpustate->b.F & 0x01 ? '0':'.');
+ break;
+
+ case CPUINFO_STR_REGISTER + LR35902_PC: sprintf(info->s, "PC:%04X", cpustate->w.PC); break;
+ case CPUINFO_STR_REGISTER + LR35902_SP: sprintf(info->s, "SP:%04X", cpustate->w.SP); break;
+ case CPUINFO_STR_REGISTER + LR35902_AF: sprintf(info->s, "AF:%04X", cpustate->w.AF); break;
+ case CPUINFO_STR_REGISTER + LR35902_BC: sprintf(info->s, "BC:%04X", cpustate->w.BC); break;
+ case CPUINFO_STR_REGISTER + LR35902_DE: sprintf(info->s, "DE:%04X", cpustate->w.DE); break;
+ case CPUINFO_STR_REGISTER + LR35902_HL: sprintf(info->s, "HL:%04X", cpustate->w.HL); break;
+ case CPUINFO_STR_REGISTER + LR35902_IRQ_STATE: sprintf(info->s, "IRQ:%X", cpustate->w.enable & IME ); break;
+ case CPUINFO_STR_REGISTER + LR35902_IE: sprintf(info->s, "IE:%02X", cpustate->w.IE); break;
+ case CPUINFO_STR_REGISTER + LR35902_IF: sprintf(info->s, "IF:%02X", cpustate->w.IF); break;
+ case CPUINFO_STR_REGISTER + LR35902_SPEED: sprintf(info->s, "SPD:%02x", 0x7E | ( ( cpustate->w.gb_speed - 1 ) << 7 ) | cpustate->w.gb_speed_change_pending ); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(LR35902, lr35902);
diff --git a/trunk/src/emu/cpu/lr35902/lr35902.h b/trunk/src/emu/cpu/lr35902/lr35902.h
new file mode 100644
index 00000000000..54f5717de9a
--- /dev/null
+++ b/trunk/src/emu/cpu/lr35902/lr35902.h
@@ -0,0 +1,36 @@
+#pragma once
+
+#ifndef __LR35902_H__
+#define __LR35902_H__
+
+
+typedef void (*lr35902_timer_fired_func)(device_t *device, int cycles);
+
+typedef struct _lr35902_cpu_core lr35902_cpu_core;
+struct _lr35902_cpu_core
+{
+ const UINT16 *regs;
+ UINT8 features;
+ lr35902_timer_fired_func timer_expired_func;
+};
+
+enum
+{
+ LR35902_PC=1, LR35902_SP, LR35902_AF, LR35902_BC, LR35902_DE, LR35902_HL,
+ LR35902_IRQ_STATE,
+ /* Pseudo registers to keep track of the interrupt statuses */
+ LR35902_IE, LR35902_IF,
+ /* Pseudo register to change and check the cpu operating speed */
+ LR35902_SPEED,
+};
+
+#define LR35902_FEATURE_HALT_BUG 0x01
+
+/****************************************************************************/
+/* Return register contents */
+/****************************************************************************/
+DECLARE_LEGACY_CPU_DEVICE(LR35902, lr35902);
+
+extern CPU_DISASSEMBLE( lr35902 );
+
+#endif /* __LR35902_H__ */
diff --git a/trunk/src/emu/cpu/lr35902/lr35902d.c b/trunk/src/emu/cpu/lr35902/lr35902d.c
new file mode 100644
index 00000000000..aa1bfccd4e8
--- /dev/null
+++ b/trunk/src/emu/cpu/lr35902/lr35902d.c
@@ -0,0 +1,289 @@
+/*****************************************************************************
+ *
+ * lr35902d.c
+ * Portable Sharp LR35902 disassembler
+ *
+ * Copyright The MESS Team.
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * pullmoll@t-online.de
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ *****************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "lr35902.h"
+
+enum e_mnemonics
+{
+ zADC, zADD, zAND, zBIT, zCALL, zCCF, zCP,
+ zCPL, zDAA, zDB, zDEC, zDI, zEI, zHLT,
+ zIN, zINC, zJP, zJR, zLD, zNOP, zOR,
+ zPOP, zPUSH, zRES, zRET, zRETI, zRL, zRLA,
+ zRLC, zRLCA, zRR, zRRA, zRRC, zRRCA, zRST,
+ zSBC, zSCF, zSET, zSLA, zSLL, zSRA, zSRL,
+ zSTOP, zSUB, zXOR, zSWAP
+};
+
+static const char *const s_mnemonic[] =
+{
+ "adc", "add", "and", "bit", "call","ccf", "cp",
+ "cpl", "daa", "db", "dec", "di", "ei", "halt",
+ "in", "inc", "jp", "jr", "ld", "nop", "or",
+ "pop", "push","res", "ret", "reti","rl", "rla",
+ "rlc", "rlca","rr", "rra", "rrc", "rrca","rst",
+ "sbc", "scf", "set", "sla", "sll", "sra", "srl",
+ "stop","sub", "xor", "swap"
+};
+
+#define _OVER DASMFLAG_STEP_OVER
+#define _OUT DASMFLAG_STEP_OUT
+
+static const UINT32 s_flags[] = {
+ 0 ,0 ,0 ,0 ,_OVER,0 ,0 ,
+ 0 ,0 ,0 ,0 ,0 ,0 ,_OVER,
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+ 0 ,0 ,0 ,_OUT ,_OUT ,0 ,0 ,
+ 0 ,0 ,0 ,0 ,0 ,0 ,_OVER,
+ 0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+ _OVER,0 ,0 ,0
+};
+
+typedef struct
+{
+ UINT8 mnemonic;
+ const char *arguments;
+} lr35902dasm;
+
+static const lr35902dasm mnemonic_cb[256] = {
+ {zRLC,"b"}, {zRLC,"c"}, {zRLC,"d"}, {zRLC,"e"},
+ {zRLC,"h"}, {zRLC,"l"}, {zRLC,"(hl)"}, {zRLC,"a"},
+ {zRRC,"b"}, {zRRC,"c"}, {zRRC,"d"}, {zRRC,"e"},
+ {zRRC,"h"}, {zRRC,"l"}, {zRRC,"(hl)"}, {zRRC,"a"},
+ {zRL,"b"}, {zRL,"c"}, {zRL,"d"}, {zRL,"e"},
+ {zRL,"h"}, {zRL,"l"}, {zRL,"(hl)"}, {zRL,"a"},
+ {zRR,"b"}, {zRR,"c"}, {zRR,"d"}, {zRR,"e"},
+ {zRR,"h"}, {zRR,"l"}, {zRR,"(hl)"}, {zRR,"a"},
+ {zSLA,"b"}, {zSLA,"c"}, {zSLA,"d"}, {zSLA,"e"},
+ {zSLA,"h"}, {zSLA,"l"}, {zSLA,"(hl)"}, {zSLA,"a"},
+ {zSRA,"b"}, {zSRA,"c"}, {zSRA,"d"}, {zSRA,"e"},
+ {zSRA,"h"}, {zSRA,"l"}, {zSRA,"(hl)"}, {zSRA,"a"},
+ {zSWAP,"b"}, {zSWAP,"c"}, {zSWAP,"d"}, {zSWAP,"e"},
+ {zSWAP,"h"}, {zSWAP,"l"}, {zSWAP,"(hl)"}, {zSWAP,"a"},
+ {zSRL,"b"}, {zSRL,"c"}, {zSRL,"d"}, {zSRL,"e"},
+ {zSRL,"h"}, {zSRL,"l"}, {zSRL,"(hl)"}, {zSRL,"a"},
+ {zBIT,"0,b"}, {zBIT,"0,c"}, {zBIT,"0,d"}, {zBIT,"0,e"},
+ {zBIT,"0,h"}, {zBIT,"0,l"}, {zBIT,"0,(hl)"},{zBIT,"0,a"},
+ {zBIT,"1,b"}, {zBIT,"1,c"}, {zBIT,"1,d"}, {zBIT,"1,e"},
+ {zBIT,"1,h"}, {zBIT,"1,l"}, {zBIT,"1,(hl)"},{zBIT,"1,a"},
+ {zBIT,"2,b"}, {zBIT,"2,c"}, {zBIT,"2,d"}, {zBIT,"2,e"},
+ {zBIT,"2,h"}, {zBIT,"2,l"}, {zBIT,"2,(hl)"},{zBIT,"2,a"},
+ {zBIT,"3,b"}, {zBIT,"3,c"}, {zBIT,"3,d"}, {zBIT,"3,e"},
+ {zBIT,"3,h"}, {zBIT,"3,l"}, {zBIT,"3,(hl)"},{zBIT,"3,a"},
+ {zBIT,"4,b"}, {zBIT,"4,c"}, {zBIT,"4,d"}, {zBIT,"4,e"},
+ {zBIT,"4,h"}, {zBIT,"4,l"}, {zBIT,"4,(hl)"},{zBIT,"4,a"},
+ {zBIT,"5,b"}, {zBIT,"5,c"}, {zBIT,"5,d"}, {zBIT,"5,e"},
+ {zBIT,"5,h"}, {zBIT,"5,l"}, {zBIT,"5,(hl)"},{zBIT,"5,a"},
+ {zBIT,"6,b"}, {zBIT,"6,c"}, {zBIT,"6,d"}, {zBIT,"6,e"},
+ {zBIT,"6,h"}, {zBIT,"6,l"}, {zBIT,"6,(hl)"},{zBIT,"6,a"},
+ {zBIT,"7,b"}, {zBIT,"7,c"}, {zBIT,"7,d"}, {zBIT,"7,e"},
+ {zBIT,"7,h"}, {zBIT,"7,l"}, {zBIT,"7,(hl)"},{zBIT,"7,a"},
+ {zRES,"0,b"}, {zRES,"0,c"}, {zRES,"0,d"}, {zRES,"0,e"},
+ {zRES,"0,h"}, {zRES,"0,l"}, {zRES,"0,(hl)"},{zRES,"0,a"},
+ {zRES,"1,b"}, {zRES,"1,c"}, {zRES,"1,d"}, {zRES,"1,e"},
+ {zRES,"1,h"}, {zRES,"1,l"}, {zRES,"1,(hl)"},{zRES,"1,a"},
+ {zRES,"2,b"}, {zRES,"2,c"}, {zRES,"2,d"}, {zRES,"2,e"},
+ {zRES,"2,h"}, {zRES,"2,l"}, {zRES,"2,(hl)"},{zRES,"2,a"},
+ {zRES,"3,b"}, {zRES,"3,c"}, {zRES,"3,d"}, {zRES,"3,e"},
+ {zRES,"3,h"}, {zRES,"3,l"}, {zRES,"3,(hl)"},{zRES,"3,a"},
+ {zRES,"4,b"}, {zRES,"4,c"}, {zRES,"4,d"}, {zRES,"4,e"},
+ {zRES,"4,h"}, {zRES,"4,l"}, {zRES,"4,(hl)"},{zRES,"4,a"},
+ {zRES,"5,b"}, {zRES,"5,c"}, {zRES,"5,d"}, {zRES,"5,e"},
+ {zRES,"5,h"}, {zRES,"5,l"}, {zRES,"5,(hl)"},{zRES,"5,a"},
+ {zRES,"6,b"}, {zRES,"6,c"}, {zRES,"6,d"}, {zRES,"6,e"},
+ {zRES,"6,h"}, {zRES,"6,l"}, {zRES,"6,(hl)"},{zRES,"6,a"},
+ {zRES,"7,b"}, {zRES,"7,c"}, {zRES,"7,d"}, {zRES,"7,e"},
+ {zRES,"7,h"}, {zRES,"7,l"}, {zRES,"7,(hl)"},{zRES,"7,a"},
+ {zSET,"0,b"}, {zSET,"0,c"}, {zSET,"0,d"}, {zSET,"0,e"},
+ {zSET,"0,h"}, {zSET,"0,l"}, {zSET,"0,(hl)"},{zSET,"0,a"},
+ {zSET,"1,b"}, {zSET,"1,c"}, {zSET,"1,d"}, {zSET,"1,e"},
+ {zSET,"1,h"}, {zSET,"1,l"}, {zSET,"1,(hl)"},{zSET,"1,a"},
+ {zSET,"2,b"}, {zSET,"2,c"}, {zSET,"2,d"}, {zSET,"2,e"},
+ {zSET,"2,h"}, {zSET,"2,l"}, {zSET,"2,(hl)"},{zSET,"2,a"},
+ {zSET,"3,b"}, {zSET,"3,c"}, {zSET,"3,d"}, {zSET,"3,e"},
+ {zSET,"3,h"}, {zSET,"3,l"}, {zSET,"3,(hl)"},{zSET,"3,a"},
+ {zSET,"4,b"}, {zSET,"4,c"}, {zSET,"4,d"}, {zSET,"4,e"},
+ {zSET,"4,h"}, {zSET,"4,l"}, {zSET,"4,(hl)"},{zSET,"4,a"},
+ {zSET,"5,b"}, {zSET,"5,c"}, {zSET,"5,d"}, {zSET,"5,e"},
+ {zSET,"5,h"}, {zSET,"5,l"}, {zSET,"5,(hl)"},{zSET,"5,a"},
+ {zSET,"6,b"}, {zSET,"6,c"}, {zSET,"6,d"}, {zSET,"6,e"},
+ {zSET,"6,h"}, {zSET,"6,l"}, {zSET,"6,(hl)"},{zSET,"6,a"},
+ {zSET,"7,b"}, {zSET,"7,c"}, {zSET,"7,d"}, {zSET,"7,e"},
+ {zSET,"7,h"}, {zSET,"7,l"}, {zSET,"7,(hl)"},{zSET,"7,a"}
+};
+
+static const lr35902dasm mnemonic_main[256]= {
+ {zNOP,0}, {zLD,"bc,N"}, {zLD,"(bc),a"}, {zINC,"bc"},
+ {zINC,"b"}, {zDEC,"b"}, {zLD,"b,B"}, {zRLCA,0},
+ {zLD,"(W),sp"}, {zADD,"hl,bc"}, {zLD,"a,(bc)"}, {zDEC,"bc"},
+ {zINC,"c"}, {zDEC,"c"}, {zLD,"c,B"}, {zRRCA,0},
+ {zSTOP,0}, {zLD,"de,N"}, {zLD,"(de),a"}, {zINC,"de"},
+ {zINC,"d"}, {zDEC,"d"}, {zLD,"d,B"}, {zRLA,0},
+ {zJR,"O"}, {zADD,"hl,de"}, {zLD,"a,(de)"}, {zDEC,"de"},
+ {zINC,"e"}, {zDEC,"e"}, {zLD,"e,B"}, {zRRA,0},
+ {zJR,"nz,O"}, {zLD,"hl,N"}, {zLD,"(hl+),a"},{zINC,"hl"},
+ {zINC,"h"}, {zDEC,"h"}, {zLD,"h,B"}, {zDAA,0},
+ {zJR,"z,O"}, {zADD,"hl,hl"}, {zLD,"a,(hl+)"},{zDEC,"hl"},
+ {zINC,"l"}, {zDEC,"l"}, {zLD,"l,B"}, {zCPL,0},
+ {zJR,"nc,O"}, {zLD,"sp,N"}, {zLD,"(hl-),a"},{zINC,"sp"},
+ {zINC,"(hl)"}, {zDEC,"(hl)"}, {zLD,"(hl),B"}, {zSCF,0},
+ {zJR,"c,O"}, {zADD,"hl,sp"}, {zLD,"a,(hl-)"},{zDEC,"sp"},
+ {zINC,"a"}, {zDEC,"a"}, {zLD,"a,B"}, {zCCF,0},
+ {zLD,"b,b"}, {zLD,"b,c"}, {zLD,"b,d"}, {zLD,"b,e"},
+ {zLD,"b,h"}, {zLD,"b,l"}, {zLD,"b,(hl)"}, {zLD,"b,a"},
+ {zLD,"c,b"}, {zLD,"c,c"}, {zLD,"c,d"}, {zLD,"c,e"},
+ {zLD,"c,h"}, {zLD,"c,l"}, {zLD,"c,(hl)"}, {zLD,"c,a"},
+ {zLD,"d,b"}, {zLD,"d,c"}, {zLD,"d,d"}, {zLD,"d,e"},
+ {zLD,"d,h"}, {zLD,"d,l"}, {zLD,"d,(hl)"}, {zLD,"d,a"},
+ {zLD,"e,b"}, {zLD,"e,c"}, {zLD,"e,d"}, {zLD,"e,e"},
+ {zLD,"e,h"}, {zLD,"e,l"}, {zLD,"e,(hl)"}, {zLD,"e,a"},
+ {zLD,"h,b"}, {zLD,"h,c"}, {zLD,"h,d"}, {zLD,"h,e"},
+ {zLD,"h,h"}, {zLD,"h,l"}, {zLD,"h,(hl)"}, {zLD,"h,a"},
+ {zLD,"l,b"}, {zLD,"l,c"}, {zLD,"l,d"}, {zLD,"l,e"},
+ {zLD,"l,h"}, {zLD,"l,l"}, {zLD,"l,(hl)"}, {zLD,"l,a"},
+ {zLD,"(hl),b"}, {zLD,"(hl),c"}, {zLD,"(hl),d"}, {zLD,"(hl),e"},
+ {zLD,"(hl),h"}, {zLD,"(hl),l"}, {zHLT,0}, {zLD,"(hl),a"},
+ {zLD,"a,b"}, {zLD,"a,c"}, {zLD,"a,d"}, {zLD,"a,e"},
+ {zLD,"a,h"}, {zLD,"a,l"}, {zLD,"a,(hl)"}, {zLD,"a,a"},
+ {zADD,"a,b"}, {zADD,"a,c"}, {zADD,"a,d"}, {zADD,"a,e"},
+ {zADD,"a,h"}, {zADD,"a,l"}, {zADD,"a,(hl)"},{zADD,"a,a"},
+ {zADC,"a,b"}, {zADC,"a,c"}, {zADC,"a,d"}, {zADC,"a,e"},
+ {zADC,"a,h"}, {zADC,"a,l"}, {zADC,"a,(hl)"},{zADC,"a,a"},
+ {zSUB,"b"}, {zSUB,"c"}, {zSUB,"d"}, {zSUB,"e"},
+ {zSUB,"h"}, {zSUB,"l"}, {zSUB,"(hl)"}, {zSUB,"a"},
+ {zSBC,"a,b"}, {zSBC,"a,c"}, {zSBC,"a,d"}, {zSBC,"a,e"},
+ {zSBC,"a,h"}, {zSBC,"a,l"}, {zSBC,"a,(hl)"},{zSBC,"a,a"},
+ {zAND,"b"}, {zAND,"c"}, {zAND,"d"}, {zAND,"e"},
+ {zAND,"h"}, {zAND,"l"}, {zAND,"(hl)"}, {zAND,"a"},
+ {zXOR,"b"}, {zXOR,"c"}, {zXOR,"d"}, {zXOR,"e"},
+ {zXOR,"h"}, {zXOR,"l"}, {zXOR,"(hl)"}, {zXOR,"a"},
+ {zOR,"b"}, {zOR,"c"}, {zOR,"d"}, {zOR,"e"},
+ {zOR,"h"}, {zOR,"l"}, {zOR,"(hl)"}, {zOR,"a"},
+ {zCP,"b"}, {zCP,"c"}, {zCP,"d"}, {zCP,"e"},
+ {zCP,"h"}, {zCP,"l"}, {zCP,"(hl)"}, {zCP,"a"},
+ {zRET,"nz"}, {zPOP,"bc"}, {zJP,"nz,A"}, {zJP,"A"},
+ {zCALL,"nz,A"}, {zPUSH,"bc"}, {zADD,"a,B"}, {zRST,"V"},
+ {zRET,"z"}, {zRET,0}, {zJP,"z,A"}, {zDB,"cb"},
+ {zCALL,"z,A"}, {zCALL,"A"}, {zADC,"a,B"}, {zRST,"V"},
+ {zRET,"nc"}, {zPOP,"de"}, {zJP,"nc,A"}, {zDB,"d3"},
+ {zCALL,"nc,A"}, {zPUSH,"de"}, {zSUB,"B"}, {zRST,"V"},
+ {zRET,"c"}, {zRETI,0}, {zJP,"c,A"}, {zDB,"db"},
+ {zCALL,"c,A"}, {zDB,"dd"}, {zSBC,"a,B"}, {zRST,"V"},
+ {zLD,"(F),a"}, {zPOP,"hl"}, {zLD,"(C),a"}, {zDB,"e3"},
+ {zDB,"e4"}, {zPUSH,"hl"}, {zAND,"B"}, {zRST,"V"},
+ {zADD,"SP,B"}, {zJP,"(hl)"}, {zLD,"(W),a"}, {zDB,"eb"},
+ {zDB,"ec"}, {zDB,"ed"}, {zXOR,"B"}, {zRST,"V"},
+ {zLD,"a,(F)"}, {zPOP,"af"}, {zLD,"a,(C)"}, {zDI,0},
+ {zDB,"f4"}, {zPUSH,"af"}, {zOR,"B"}, {zRST,"V"},
+ {zLD,"hl,sp+B"},{zLD,"sp,hl"}, {zLD,"a,(W)"}, {zEI,0},
+ {zDB,"fc"}, {zDB,"fd"}, {zCP,"B"}, {zRST,"V"}
+};
+
+/****************************************************************************
+ * Disassemble opcode at PC and return number of bytes it takes
+ ****************************************************************************/
+
+CPU_DISASSEMBLE( lr35902 )
+{
+ const lr35902dasm *d;
+ const char /* *symbol,*/ *src;
+ char *dst;
+ INT8 offset = 0;
+ UINT8 op, op1;
+ UINT16 ea = 0;
+ int pos = 0;
+
+ dst = buffer;
+ //symbol = NULL;
+
+ op = oprom[pos++];
+ op1 = 0; /* keep GCC happy */
+
+ if( op == 0xcb ) {
+ op = oprom[pos++];
+ d = &mnemonic_cb[op];
+ } else {
+ d = &mnemonic_main[op];
+ }
+
+ if( d->arguments ) {
+ dst += sprintf(dst, "%-4s ", s_mnemonic[d->mnemonic]);
+ src = d->arguments;
+ while( *src ) {
+ switch( *src ) {
+ case '?': /* illegal opcode */
+ dst += sprintf( dst, "$%02X,$%02X", op, op1);
+ break;
+ case 'A':
+ ea = opram[pos] + ( opram[pos+1] << 8);
+ pos += 2;
+ dst += sprintf( dst, "$%04X", ea );
+ break;
+ case 'B': /* Byte op arg */
+ ea = opram[pos++];
+ dst += sprintf( dst, "$%02X", ea );
+ break;
+ case '(': /* Memory byte at (...) */
+ *dst++ = *src;
+ if( !strncmp( src, "(bc)", 4) ) {
+ } else if( !strncmp( src, "(de)", 4) ) {
+ } else if( !strncmp( src, "(hl)", 4) ) {
+ } else if( !strncmp( src, "(sp)", 4) ) {
+ } else if( !strncmp( src, "(F)", 3) ) {
+ ea = 0xFF00 + opram[pos++];
+ dst += sprintf( dst, "$%02X", ea );
+ src++;
+ } else if( !strncmp( src, "(C)", 3) ) {
+ dst += sprintf( dst, "$FF00+c" );
+ src++;
+ }
+ break;
+ case 'N': /* Immediate 16 bit */
+ ea = opram[pos] + ( opram[pos+1] << 8 );
+ pos += 2;
+ dst += sprintf( dst, "$%04X", ea );
+ break;
+ case 'O': /* Offset relative to PC */
+ offset = (INT8) opram[pos++];
+ dst += sprintf( dst, "$%04X", pc + offset + 2 );
+ break;
+ case 'V': /* Restart vector */
+ ea = op & 0x38;
+ dst += sprintf( dst, "$%02X", ea );
+ break;
+ case 'W': /* Memory address word */
+ ea = opram[pos] + ( opram[pos+1] << 8 );
+ pos += 2;
+ dst += sprintf( dst, "$%04X", ea );
+ break;
+ default:
+ *dst++ = *src;
+ }
+ src++;
+ }
+ *dst = '\0';
+ } else {
+ dst += sprintf(dst, "%s", s_mnemonic[d->mnemonic]);
+ }
+
+ return pos | s_flags[d->mnemonic] | DASMFLAG_SUPPORTED;
+}
diff --git a/trunk/src/emu/cpu/lr35902/opc_cb.h b/trunk/src/emu/cpu/lr35902/opc_cb.h
new file mode 100644
index 00000000000..080aeb5478b
--- /dev/null
+++ b/trunk/src/emu/cpu/lr35902/opc_cb.h
@@ -0,0 +1,1440 @@
+#define RLC_8BIT(x) \
+{ \
+ register UINT8 f; \
+ (x)=(UINT8)(((x)<<1)|((x)>>7)); \
+ if( (x)&1 ) \
+ f=FLAG_C; \
+ else \
+ f=0; \
+ if( (x)==0 ) \
+ f|=FLAG_Z; \
+ cpustate->b.F=f; \
+}
+
+#define RL_8BIT(x) \
+{ \
+ register UINT8 r; \
+ r=((x)&0x80)?FLAG_C:0; \
+ (x)=(UINT8)(((x)<<1)|((cpustate->b.F&FLAG_C)?1:0)); \
+ if( (x)==0 ) \
+ r|=FLAG_Z; \
+ cpustate->b.F=r; \
+}
+
+#define RRC_8BIT(x) \
+{ \
+ register UINT8 f; \
+ (x)=(UINT8)(((x)>>1)|((x)<<7)); \
+ if( (x)&0x80 ) \
+ f=FLAG_C; \
+ else \
+ f=0; \
+ if( (x)==0 ) \
+ f|=FLAG_Z; \
+ cpustate->b.F=f; \
+}
+
+#define RR_8BIT(x) \
+{ \
+ register UINT8 r; \
+ r=((x)&1)?FLAG_C:0; \
+ (x)=(UINT8)(((x)>>1)|((cpustate->b.F&FLAG_C)?0x80:0)); \
+ if( (x)==0 ) \
+ r|=FLAG_Z; \
+ cpustate->b.F=r; \
+}
+
+#define SLA_8BIT(x) \
+{ \
+ register UINT8 f; \
+ if( (x)&0x80 ) \
+ f=FLAG_C; \
+ else \
+ f=0; \
+ (x)<<=1; \
+ if( (x)==0 ) \
+ f|=FLAG_Z; \
+ cpustate->b.F=f; \
+}
+
+#define SRA_8BIT(x) \
+{ \
+ register UINT8 f; \
+ if( (x)&1 ) \
+ f=FLAG_C; \
+ else \
+ f=0; \
+ (x)=(UINT8)(((char)(x))>>1); \
+ if( (x)==0 ) \
+ f|=FLAG_Z; \
+ cpustate->b.F=f; \
+}
+
+#define SWAP_8BIT(x) \
+ (x)=(UINT8)(((x)>>4)|((x)<<4)); \
+ if( (x)==0 ) \
+ cpustate->b.F=FLAG_Z; \
+ else \
+ cpustate->b.F=0;
+
+
+#define SRL_8BIT(x) \
+{ \
+ register UINT8 f; \
+ if( (x)&1 ) \
+ f=FLAG_C; \
+ else \
+ f=0; \
+ (x)>>=1; \
+ if( (x)==0 ) \
+ f|=FLAG_Z; \
+ cpustate->b.F=f; \
+}
+
+#define BIT_8BIT(n,x) \
+ if( (x)&(1<<(n)) ) \
+ cpustate->b.F=(UINT8)(FLAG_H|(cpustate->b.F&FLAG_C)); \
+ else \
+ cpustate->b.F=(UINT8)(FLAG_Z|FLAG_H|(cpustate->b.F&FLAG_C));
+
+#define RES_8BIT(n,x) (x)&=~(1<<(n));
+
+#define SET_8BIT(n,x) (x)|=(1<<(n));
+
+
+case 0x00:
+ /* RLC B */
+
+ RLC_8BIT (cpustate->b.B)
+ break;
+case 0x01:
+ /* RLC C */
+
+ RLC_8BIT (cpustate->b.C)
+ break;
+case 0x02:
+ /* RLC D */
+
+ RLC_8BIT (cpustate->b.D)
+ break;
+case 0x03:
+ /* RLC E */
+
+ RLC_8BIT (cpustate->b.E)
+ break;
+case 0x04:
+ /* RLC H */
+
+ RLC_8BIT (cpustate->b.H)
+ break;
+case 0x05:
+ /* RLC L */
+
+ RLC_8BIT (cpustate->b.L)
+ break;
+case 0x06:
+ /* RLC (HL) */
+
+ x = mem_ReadByte (cpustate, cpustate->w.HL);
+ RLC_8BIT (x)
+ mem_WriteByte (cpustate, cpustate->w.HL, x);
+ break;
+case 0x07:
+ /* RLC A */
+
+ RLC_8BIT (cpustate->b.A)
+ break;
+case 0x08:
+ /* RRC B */
+
+ RRC_8BIT (cpustate->b.B)
+ break;
+case 0x09:
+ /* RRC C */
+
+ RRC_8BIT (cpustate->b.C)
+ break;
+case 0x0A:
+ /* RRC D */
+
+ RRC_8BIT (cpustate->b.D)
+ break;
+case 0x0B:
+ /* RRC E */
+
+ RRC_8BIT (cpustate->b.E)
+ break;
+case 0x0C:
+ /* RRC H */
+
+ RRC_8BIT (cpustate->b.H)
+ break;
+case 0x0D:
+ /* RRC L */
+
+ RRC_8BIT (cpustate->b.L)
+ break;
+case 0x0E:
+ /* RRC (HL) */
+
+ x = mem_ReadByte (cpustate, cpustate->w.HL);
+ RRC_8BIT (x)
+ mem_WriteByte (cpustate, cpustate->w.HL, x);
+ break;
+case 0x0F:
+ /* RRC A */
+
+ RRC_8BIT (cpustate->b.A)
+ break;
+case 0x10:
+ /* RL B */
+
+ RL_8BIT (cpustate->b.B)
+ break;
+case 0x11:
+ /* RL C */
+
+ RL_8BIT (cpustate->b.C)
+ break;
+case 0x12:
+ /* RL D */
+
+ RL_8BIT (cpustate->b.D)
+ break;
+case 0x13:
+ /* RL E */
+
+ RL_8BIT (cpustate->b.E)
+ break;
+case 0x14:
+ /* RL H */
+
+ RL_8BIT (cpustate->b.H)
+ break;
+case 0x15:
+ /* RL L */
+
+ RL_8BIT (cpustate->b.L)
+ break;
+case 0x16:
+ /* RL (HL) */
+
+ x = mem_ReadByte (cpustate, cpustate->w.HL);
+ RL_8BIT (x)
+ mem_WriteByte (cpustate, cpustate->w.HL, x);
+ break;
+case 0x17:
+ /* RL A */
+
+ RL_8BIT (cpustate->b.A)
+ break;
+case 0x18:
+ /* RR B */
+
+ RR_8BIT (cpustate->b.B)
+ break;
+case 0x19:
+ /* RR C */
+
+ RR_8BIT (cpustate->b.C)
+ break;
+case 0x1A:
+ /* RR D */
+
+ RR_8BIT (cpustate->b.D)
+ break;
+case 0x1B:
+ /* RR E */
+
+ RR_8BIT (cpustate->b.E)
+ break;
+case 0x1C:
+ /* RR H */
+
+ RR_8BIT (cpustate->b.H)
+ break;
+case 0x1D:
+ /* RR L */
+
+ RR_8BIT (cpustate->b.L)
+ break;
+case 0x1E:
+ /* RR (HL) */
+
+ x = mem_ReadByte (cpustate, cpustate->w.HL);
+ RR_8BIT (x)
+ mem_WriteByte (cpustate, cpustate->w.HL, x);
+ break;
+case 0x1F:
+ /* RR A */
+
+ RR_8BIT (cpustate->b.A)
+ break;
+case 0x20:
+ /* SLA B */
+
+ SLA_8BIT (cpustate->b.B)
+ break;
+case 0x21:
+ /* SLA C */
+
+ SLA_8BIT (cpustate->b.C)
+ break;
+case 0x22:
+ /* SLA D */
+
+ SLA_8BIT (cpustate->b.D)
+ break;
+case 0x23:
+ /* SLA E */
+
+ SLA_8BIT (cpustate->b.E)
+ break;
+case 0x24:
+ /* SLA H */
+
+ SLA_8BIT (cpustate->b.H)
+ break;
+case 0x25:
+ /* SLA L */
+
+ SLA_8BIT (cpustate->b.L)
+ break;
+case 0x26:
+ /* SLA (HL) */
+
+ x = mem_ReadByte (cpustate, cpustate->w.HL);
+ SLA_8BIT (x)
+ mem_WriteByte (cpustate, cpustate->w.HL, x);
+ break;
+case 0x27:
+ /* SLA A */
+
+ SLA_8BIT (cpustate->b.A)
+ break;
+case 0x28:
+ /* SRA B */
+
+ SRA_8BIT (cpustate->b.B)
+ break;
+case 0x29:
+ /* SRA C */
+
+ SRA_8BIT (cpustate->b.C)
+ break;
+case 0x2A:
+ /* SRA D */
+
+ SRA_8BIT (cpustate->b.D)
+ break;
+case 0x2B:
+ /* SRA E */
+
+ SRA_8BIT (cpustate->b.E)
+ break;
+case 0x2C:
+ /* SRA H */
+
+ SRA_8BIT (cpustate->b.H)
+ break;
+case 0x2D:
+ /* SRA L */
+
+ SRA_8BIT (cpustate->b.L)
+ break;
+case 0x2E:
+ /* SRA (HL) */
+
+ x = mem_ReadByte (cpustate, cpustate->w.HL);
+ SRA_8BIT (x)
+ mem_WriteByte (cpustate, cpustate->w.HL, x);
+ break;
+case 0x2F:
+ /* SRA A */
+
+ SRA_8BIT (cpustate->b.A)
+ break;
+case 0x30:
+ /* SWAP B */
+
+ SWAP_8BIT (cpustate->b.B)
+ break;
+case 0x31:
+ /* SWAP C */
+
+ SWAP_8BIT (cpustate->b.C)
+ break;
+case 0x32:
+ /* SWAP D */
+
+ SWAP_8BIT (cpustate->b.D)
+ break;
+case 0x33:
+ /* SWAP E */
+
+ SWAP_8BIT (cpustate->b.E)
+ break;
+case 0x34:
+ /* SWAP H */
+
+ SWAP_8BIT (cpustate->b.H)
+ break;
+case 0x35:
+ /* SWAP L */
+
+ SWAP_8BIT (cpustate->b.L)
+ break;
+case 0x36:
+ /* SWAP (HL) */
+
+ x = mem_ReadByte (cpustate, cpustate->w.HL);
+ SWAP_8BIT (x)
+ mem_WriteByte (cpustate, cpustate->w.HL, x);
+ break;
+case 0x37:
+ /* SWAP A */
+
+ SWAP_8BIT (cpustate->b.A)
+ break;
+case 0x38:
+ /* SRL B */
+
+ SRL_8BIT (cpustate->b.B)
+ break;
+case 0x39:
+ /* SRL C */
+
+ SRL_8BIT (cpustate->b.C)
+ break;
+case 0x3A:
+ /* SRL D */
+
+ SRL_8BIT (cpustate->b.D)
+ break;
+case 0x3B:
+ /* SRL E */
+
+ SRL_8BIT (cpustate->b.E)
+ break;
+case 0x3C:
+ /* SRL H */
+
+ SRL_8BIT (cpustate->b.H)
+ break;
+case 0x3D:
+ /* SRL L */
+
+ SRL_8BIT (cpustate->b.L)
+ break;
+case 0x3E:
+ /* SRL (HL) */
+
+ x = mem_ReadByte (cpustate, cpustate->w.HL);
+ SRL_8BIT (x)
+ mem_WriteByte (cpustate, cpustate->w.HL, x);
+ break;
+case 0x3F:
+ /* SRL A */
+
+ SRL_8BIT (cpustate->b.A)
+ break;
+case 0x40:
+ /* BIT 0,B */
+
+ BIT_8BIT (0, cpustate->b.B)
+ break;
+case 0x41:
+ /* BIT 0,C */
+
+ BIT_8BIT (0, cpustate->b.C)
+ break;
+case 0x42:
+ /* BIT 0,D */
+
+ BIT_8BIT (0, cpustate->b.D)
+ break;
+case 0x43:
+ /* BIT 0,E */
+
+ BIT_8BIT (0, cpustate->b.E)
+ break;
+case 0x44:
+ /* BIT 0,H */
+
+ BIT_8BIT (0, cpustate->b.H)
+ break;
+case 0x45:
+ /* BIT 0,L */
+
+ BIT_8BIT (0, cpustate->b.L)
+ break;
+case 0x46:
+ /* BIT 0,(HL) */
+
+ x = mem_ReadByte (cpustate, cpustate->w.HL);
+ BIT_8BIT (0, x)
+ break;
+case 0x47:
+ /* BIT 0,A */
+
+ BIT_8BIT (0, cpustate->b.A)
+ break;
+case 0x48:
+ /* BIT 1,B */
+
+ BIT_8BIT (1, cpustate->b.B)
+ break;
+case 0x49:
+ /* BIT 1,C */
+
+ BIT_8BIT (1, cpustate->b.C)
+ break;
+case 0x4A:
+ /* BIT 1,D */
+
+ BIT_8BIT (1, cpustate->b.D)
+ break;
+case 0x4B:
+ /* BIT 1,E */
+
+ BIT_8BIT (1, cpustate->b.E)
+ break;
+case 0x4C:
+ /* BIT 1,H */
+
+ BIT_8BIT (1, cpustate->b.H)
+ break;
+case 0x4D:
+ /* BIT 1,L */
+
+ BIT_8BIT (1, cpustate->b.L)
+ break;
+case 0x4E:
+ /* BIT 1,(HL) */
+
+ x = mem_ReadByte (cpustate, cpustate->w.HL);
+ BIT_8BIT (1, x)
+ break;
+case 0x4F:
+ /* BIT 1,A */
+
+ BIT_8BIT (1, cpustate->b.A)
+ break;
+case 0x50:
+ /* BIT 2,B */
+
+ BIT_8BIT (2, cpustate->b.B)
+ break;
+case 0x51:
+ /* BIT 2,C */
+
+ BIT_8BIT (2, cpustate->b.C)
+ break;
+case 0x52:
+ /* BIT 2,D */
+
+ BIT_8BIT (2, cpustate->b.D)
+ break;
+case 0x53:
+ /* BIT 2,E */
+
+ BIT_8BIT (2, cpustate->b.E)
+ break;
+case 0x54:
+ /* BIT 2,H */
+
+ BIT_8BIT (2, cpustate->b.H)
+ break;
+case 0x55:
+ /* BIT 2,L */
+
+ BIT_8BIT (2, cpustate->b.L)
+ break;
+case 0x56:
+ /* BIT 2,(HL) */
+
+ x = mem_ReadByte (cpustate, cpustate->w.HL);
+ BIT_8BIT (2, x)
+ break;
+case 0x57:
+ /* BIT 2,A */
+
+ BIT_8BIT (2, cpustate->b.A)
+ break;
+case 0x58:
+ /* BIT 3,B */
+
+ BIT_8BIT (3, cpustate->b.B)
+ break;
+case 0x59:
+ /* BIT 3,C */
+
+ BIT_8BIT (3, cpustate->b.C)
+ break;
+case 0x5A:
+ /* BIT 3,D */
+
+ BIT_8BIT (3, cpustate->b.D)
+ break;
+case 0x5B:
+ /* BIT 3,E */
+
+ BIT_8BIT (3, cpustate->b.E)
+ break;
+case 0x5C:
+ /* BIT 3,H */
+
+ BIT_8BIT (3, cpustate->b.H)
+ break;
+case 0x5D:
+ /* BIT 3,L */
+
+ BIT_8BIT (3, cpustate->b.L)
+ break;
+case 0x5E:
+ /* BIT 3,(HL) */
+
+ x = mem_ReadByte (cpustate, cpustate->w.HL);
+ BIT_8BIT (3, x)
+ break;
+case 0x5F:
+ /* BIT 3,A */
+
+ BIT_8BIT (3, cpustate->b.A)
+ break;
+case 0x60:
+ /* BIT 4,B */
+
+ BIT_8BIT (4, cpustate->b.B)
+ break;
+case 0x61:
+ /* BIT 4,C */
+
+ BIT_8BIT (4, cpustate->b.C)
+ break;
+case 0x62:
+ /* BIT 4,D */
+
+ BIT_8BIT (4, cpustate->b.D)
+ break;
+case 0x63:
+ /* BIT 4,E */
+
+ BIT_8BIT (4, cpustate->b.E)
+ break;
+case 0x64:
+ /* BIT 4,H */
+
+ BIT_8BIT (4, cpustate->b.H)
+ break;
+case 0x65:
+ /* BIT 4,L */
+
+ BIT_8BIT (4, cpustate->b.L)
+ break;
+case 0x66:
+ /* BIT 4,(HL) */
+
+ x = mem_ReadByte (cpustate, cpustate->w.HL);
+ BIT_8BIT (4, x)
+ break;
+case 0x67:
+ /* BIT 4,A */
+
+ BIT_8BIT (4, cpustate->b.A)
+ break;
+case 0x68:
+ /* BIT 5,B */
+
+ BIT_8BIT (5, cpustate->b.B)
+ break;
+case 0x69:
+ /* BIT 5,C */
+
+ BIT_8BIT (5, cpustate->b.C)
+ break;
+case 0x6A:
+ /* BIT 5,D */
+
+ BIT_8BIT (5, cpustate->b.D)
+ break;
+case 0x6B:
+ /* BIT 5,E */
+
+ BIT_8BIT (5, cpustate->b.E)
+ break;
+case 0x6C:
+ /* BIT 5,H */
+
+ BIT_8BIT (5, cpustate->b.H)
+ break;
+case 0x6D:
+ /* BIT 5,L */
+
+ BIT_8BIT (5, cpustate->b.L)
+ break;
+case 0x6E:
+ /* BIT 5,(HL) */
+
+ x = mem_ReadByte (cpustate, cpustate->w.HL);
+ BIT_8BIT (5, x)
+ break;
+case 0x6F:
+ /* BIT 5,A */
+
+ BIT_8BIT (5, cpustate->b.A)
+ break;
+case 0x70:
+ /* BIT 6,B */
+
+ BIT_8BIT (6, cpustate->b.B)
+ break;
+case 0x71:
+ /* BIT 6,C */
+
+ BIT_8BIT (6, cpustate->b.C)
+ break;
+case 0x72:
+ /* BIT 6,D */
+
+ BIT_8BIT (6, cpustate->b.D)
+ break;
+case 0x73:
+ /* BIT 6,E */
+
+ BIT_8BIT (6, cpustate->b.E)
+ break;
+case 0x74:
+ /* BIT 6,H */
+
+ BIT_8BIT (6, cpustate->b.H)
+ break;
+case 0x75:
+ /* BIT 6,L */
+
+ BIT_8BIT (6, cpustate->b.L)
+ break;
+case 0x76:
+ /* BIT 6,(HL) */
+
+ x = mem_ReadByte (cpustate, cpustate->w.HL);
+ BIT_8BIT (6, x)
+ break;
+case 0x77:
+ /* BIT 6,A */
+
+ BIT_8BIT (6, cpustate->b.A)
+ break;
+case 0x78:
+ /* BIT 7,B */
+
+ BIT_8BIT (7, cpustate->b.B)
+ break;
+case 0x79:
+ /* BIT 7,C */
+
+ BIT_8BIT (7, cpustate->b.C)
+ break;
+case 0x7A:
+ /* BIT 7,D */
+
+ BIT_8BIT (7, cpustate->b.D)
+ break;
+case 0x7B:
+ /* BIT 7,E */
+
+ BIT_8BIT (7, cpustate->b.E)
+ break;
+case 0x7C:
+ /* BIT 7,H */
+
+ BIT_8BIT (7, cpustate->b.H)
+ break;
+case 0x7D:
+ /* BIT 7,L */
+
+ BIT_8BIT (7, cpustate->b.L)
+ break;
+case 0x7E:
+ /* BIT 7,(HL) */
+
+ x = mem_ReadByte (cpustate, cpustate->w.HL);
+ BIT_8BIT (7, x)
+ break;
+case 0x7F:
+ /* BIT 7,A */
+
+ BIT_8BIT (7, cpustate->b.A)
+ break;
+case 0x80:
+ /* RES 0,B */
+
+ RES_8BIT (0, cpustate->b.B)
+ break;
+case 0x81:
+ /* RES 0,C */
+
+ RES_8BIT (0, cpustate->b.C)
+ break;
+case 0x82:
+ /* RES 0,D */
+
+ RES_8BIT (0, cpustate->b.D)
+ break;
+case 0x83:
+ /* RES 0,E */
+
+ RES_8BIT (0, cpustate->b.E)
+ break;
+case 0x84:
+ /* RES 0,H */
+
+ RES_8BIT (0, cpustate->b.H)
+ break;
+case 0x85:
+ /* RES 0,L */
+
+ RES_8BIT (0, cpustate->b.L)
+ break;
+case 0x86:
+ /* RES 0,(HL) */
+
+ x = mem_ReadByte (cpustate, cpustate->w.HL);
+ RES_8BIT (0, x)
+ mem_WriteByte (cpustate, cpustate->w.HL, x);
+ break;
+case 0x87:
+ /* RES 0,A */
+
+ RES_8BIT (0, cpustate->b.A)
+ break;
+case 0x88:
+ /* RES 1,B */
+
+ RES_8BIT (1, cpustate->b.B)
+ break;
+case 0x89:
+ /* RES 1,C */
+
+ RES_8BIT (1, cpustate->b.C)
+ break;
+case 0x8A:
+ /* RES 1,D */
+
+ RES_8BIT (1, cpustate->b.D)
+ break;
+case 0x8B:
+ /* RES 1,E */
+
+ RES_8BIT (1, cpustate->b.E)
+ break;
+case 0x8C:
+ /* RES 1,H */
+
+ RES_8BIT (1, cpustate->b.H)
+ break;
+case 0x8D:
+ /* RES 1,L */
+
+ RES_8BIT (1, cpustate->b.L)
+ break;
+case 0x8E:
+ /* RES 1,(HL) */
+
+ x = mem_ReadByte (cpustate, cpustate->w.HL);
+ RES_8BIT (1, x)
+ mem_WriteByte (cpustate, cpustate->w.HL, x);
+ break;
+case 0x8F:
+ /* RES 1,A */
+
+ RES_8BIT (1, cpustate->b.A)
+ break;
+case 0x90:
+ /* RES 2,B */
+
+ RES_8BIT (2, cpustate->b.B)
+ break;
+case 0x91:
+ /* RES 2,C */
+
+ RES_8BIT (2, cpustate->b.C)
+ break;
+case 0x92:
+ /* RES 2,D */
+
+ RES_8BIT (2, cpustate->b.D)
+ break;
+case 0x93:
+ /* RES 2,E */
+
+ RES_8BIT (2, cpustate->b.E)
+ break;
+case 0x94:
+ /* RES 2,H */
+
+ RES_8BIT (2, cpustate->b.H)
+ break;
+case 0x95:
+ /* RES 2,L */
+
+ RES_8BIT (2, cpustate->b.L)
+ break;
+case 0x96:
+ /* RES 2,(HL) */
+
+ x = mem_ReadByte (cpustate, cpustate->w.HL);
+ RES_8BIT (2, x)
+ mem_WriteByte (cpustate, cpustate->w.HL, x);
+ break;
+case 0x97:
+ /* RES 2,A */
+
+ RES_8BIT (2, cpustate->b.A)
+ break;
+case 0x98:
+ /* RES 3,B */
+
+ RES_8BIT (3, cpustate->b.B)
+ break;
+case 0x99:
+ /* RES 3,C */
+
+ RES_8BIT (3, cpustate->b.C)
+ break;
+case 0x9A:
+ /* RES 3,D */
+
+ RES_8BIT (3, cpustate->b.D)
+ break;
+case 0x9B:
+ /* RES 3,E */
+
+ RES_8BIT (3, cpustate->b.E)
+ break;
+case 0x9C:
+ /* RES 3,H */
+
+ RES_8BIT (3, cpustate->b.H)
+ break;
+case 0x9D:
+ /* RES 3,L */
+
+ RES_8BIT (3, cpustate->b.L)
+ break;
+case 0x9E:
+ /* RES 3,(HL) */
+
+ x = mem_ReadByte (cpustate, cpustate->w.HL);
+ RES_8BIT (3, x)
+ mem_WriteByte (cpustate, cpustate->w.HL, x);
+ break;
+case 0x9F:
+ /* RES 3,A */
+
+ RES_8BIT (3, cpustate->b.A)
+ break;
+case 0xA0:
+ /* RES 4,B */
+
+ RES_8BIT (4, cpustate->b.B)
+ break;
+case 0xA1:
+ /* RES 4,C */
+
+ RES_8BIT (4, cpustate->b.C)
+ break;
+case 0xA2:
+ /* RES 4,D */
+
+ RES_8BIT (4, cpustate->b.D)
+ break;
+case 0xA3:
+ /* RES 4,E */
+
+ RES_8BIT (4, cpustate->b.E)
+ break;
+case 0xA4:
+ /* RES 4,H */
+
+ RES_8BIT (4, cpustate->b.H)
+ break;
+case 0xA5:
+ /* RES 4,L */
+
+ RES_8BIT (4, cpustate->b.L)
+ break;
+case 0xA6:
+ /* RES 4,(HL) */
+
+ x = mem_ReadByte (cpustate, cpustate->w.HL);
+ RES_8BIT (4, x)
+ mem_WriteByte (cpustate, cpustate->w.HL, x);
+ break;
+case 0xA7:
+ /* RES 4,A */
+
+ RES_8BIT (4, cpustate->b.A)
+ break;
+case 0xA8:
+ /* RES 5,B */
+
+ RES_8BIT (5, cpustate->b.B)
+ break;
+case 0xA9:
+ /* RES 5,C */
+
+ RES_8BIT (5, cpustate->b.C)
+ break;
+case 0xAA:
+ /* RES 5,D */
+
+ RES_8BIT (5, cpustate->b.D)
+ break;
+case 0xAB:
+ /* RES 5,E */
+
+ RES_8BIT (5, cpustate->b.E)
+ break;
+case 0xAC:
+ /* RES 5,H */
+
+ RES_8BIT (5, cpustate->b.H)
+ break;
+case 0xAD:
+ /* RES 5,L */
+
+ RES_8BIT (5, cpustate->b.L)
+ break;
+case 0xAE:
+ /* RES 5,(HL) */
+
+ x = mem_ReadByte (cpustate, cpustate->w.HL);
+ RES_8BIT (5, x)
+ mem_WriteByte (cpustate, cpustate->w.HL, x);
+ break;
+case 0xAF:
+ /* RES 5,A */
+
+ RES_8BIT (5, cpustate->b.A)
+ break;
+case 0xB0:
+ /* RES 6,B */
+
+ RES_8BIT (6, cpustate->b.B)
+ break;
+case 0xB1:
+ /* RES 6,C */
+
+ RES_8BIT (6, cpustate->b.C)
+ break;
+case 0xB2:
+ /* RES 6,D */
+
+ RES_8BIT (6, cpustate->b.D)
+ break;
+case 0xB3:
+ /* RES 6,E */
+
+ RES_8BIT (6, cpustate->b.E)
+ break;
+case 0xB4:
+ /* RES 6,H */
+
+ RES_8BIT (6, cpustate->b.H)
+ break;
+case 0xB5:
+ /* RES 6,L */
+
+ RES_8BIT (6, cpustate->b.L)
+ break;
+case 0xB6:
+ /* RES 6,(HL) */
+
+ x = mem_ReadByte (cpustate, cpustate->w.HL);
+ RES_8BIT (6, x)
+ mem_WriteByte (cpustate, cpustate->w.HL, x);
+ break;
+case 0xB7:
+ /* RES 6,A */
+
+ RES_8BIT (6, cpustate->b.A)
+ break;
+case 0xB8:
+ /* RES 7,B */
+
+ RES_8BIT (7, cpustate->b.B)
+ break;
+case 0xB9:
+ /* RES 7,C */
+
+ RES_8BIT (7, cpustate->b.C)
+ break;
+case 0xBA:
+ /* RES 7,D */
+
+ RES_8BIT (7, cpustate->b.D)
+ break;
+case 0xBB:
+ /* RES 7,E */
+
+ RES_8BIT (7, cpustate->b.E)
+ break;
+case 0xBC:
+ /* RES 7,H */
+
+ RES_8BIT (7, cpustate->b.H)
+ break;
+case 0xBD:
+ /* RES 7,L */
+
+ RES_8BIT (7, cpustate->b.L)
+ break;
+case 0xBE:
+ /* RES 7,(HL) */
+
+ x = mem_ReadByte (cpustate, cpustate->w.HL);
+ RES_8BIT (7, x)
+ mem_WriteByte (cpustate, cpustate->w.HL, x);
+ break;
+case 0xBF:
+ /* RES 7,A */
+
+ RES_8BIT (7, cpustate->b.A)
+ break;
+case 0xC0:
+ /* SET 0,B */
+
+ SET_8BIT (0, cpustate->b.B)
+ break;
+case 0xC1:
+ /* SET 0,C */
+
+ SET_8BIT (0, cpustate->b.C)
+ break;
+case 0xC2:
+ /* SET 0,D */
+
+ SET_8BIT (0, cpustate->b.D)
+ break;
+case 0xC3:
+ /* SET 0,E */
+
+ SET_8BIT (0, cpustate->b.E)
+ break;
+case 0xC4:
+ /* SET 0,H */
+
+ SET_8BIT (0, cpustate->b.H)
+ break;
+case 0xC5:
+ /* SET 0,L */
+
+ SET_8BIT (0, cpustate->b.L)
+ break;
+case 0xC6:
+ /* SET 0,(HL) */
+
+ x = mem_ReadByte (cpustate, cpustate->w.HL);
+ SET_8BIT (0, x)
+ mem_WriteByte (cpustate, cpustate->w.HL, x);
+ break;
+case 0xC7:
+ /* SET 0,A */
+
+ SET_8BIT (0, cpustate->b.A)
+ break;
+case 0xC8:
+ /* SET 1,B */
+
+ SET_8BIT (1, cpustate->b.B)
+ break;
+case 0xC9:
+ /* SET 1,C */
+
+ SET_8BIT (1, cpustate->b.C)
+ break;
+case 0xCA:
+ /* SET 1,D */
+
+ SET_8BIT (1, cpustate->b.D)
+ break;
+case 0xCB:
+ /* SET 1,E */
+
+ SET_8BIT (1, cpustate->b.E)
+ break;
+case 0xCC:
+ /* SET 1,H */
+
+ SET_8BIT (1, cpustate->b.H)
+ break;
+case 0xCD:
+ /* SET 1,L */
+
+ SET_8BIT (1, cpustate->b.L)
+ break;
+case 0xCE:
+ /* SET 1,(HL) */
+
+ x = mem_ReadByte (cpustate, cpustate->w.HL);
+ SET_8BIT (1, x)
+ mem_WriteByte (cpustate, cpustate->w.HL, x);
+ break;
+case 0xCF:
+ /* SET 1,A */
+
+ SET_8BIT (1, cpustate->b.A)
+ break;
+case 0xD0:
+ /* SET 2,B */
+
+ SET_8BIT (2, cpustate->b.B)
+ break;
+case 0xD1:
+ /* SET 2,C */
+
+ SET_8BIT (2, cpustate->b.C)
+ break;
+case 0xD2:
+ /* SET 2,D */
+
+ SET_8BIT (2, cpustate->b.D)
+ break;
+case 0xD3:
+ /* SET 2,E */
+
+ SET_8BIT (2, cpustate->b.E)
+ break;
+case 0xD4:
+ /* SET 2,H */
+
+ SET_8BIT (2, cpustate->b.H)
+ break;
+case 0xD5:
+ /* SET 2,L */
+
+ SET_8BIT (2, cpustate->b.L)
+ break;
+case 0xD6:
+ /* SET 2,(HL) */
+
+ x = mem_ReadByte (cpustate, cpustate->w.HL);
+ SET_8BIT (2, x)
+ mem_WriteByte (cpustate, cpustate->w.HL, x);
+ break;
+case 0xD7:
+ /* SET 2,A */
+
+ SET_8BIT (2, cpustate->b.A)
+ break;
+case 0xD8:
+ /* SET 3,B */
+
+ SET_8BIT (3, cpustate->b.B)
+ break;
+case 0xD9:
+ /* SET 3,C */
+
+ SET_8BIT (3, cpustate->b.C)
+ break;
+case 0xDA:
+ /* SET 3,D */
+
+ SET_8BIT (3, cpustate->b.D)
+ break;
+case 0xDB:
+ /* SET 3,E */
+
+ SET_8BIT (3, cpustate->b.E)
+ break;
+case 0xDC:
+ /* SET 3,H */
+
+ SET_8BIT (3, cpustate->b.H)
+ break;
+case 0xDD:
+ /* SET 3,L */
+
+ SET_8BIT (3, cpustate->b.L)
+ break;
+case 0xDE:
+ /* SET 3,(HL) */
+
+ x = mem_ReadByte (cpustate, cpustate->w.HL);
+ SET_8BIT (3, x)
+ mem_WriteByte (cpustate, cpustate->w.HL, x);
+ break;
+case 0xDF:
+ /* SET 3,A */
+
+ SET_8BIT (3, cpustate->b.A)
+ break;
+case 0xE0:
+ /* SET 4,B */
+
+ SET_8BIT (4, cpustate->b.B)
+ break;
+case 0xE1:
+ /* SET 4,C */
+
+ SET_8BIT (4, cpustate->b.C)
+ break;
+case 0xE2:
+ /* SET 4,D */
+
+ SET_8BIT (4, cpustate->b.D)
+ break;
+case 0xE3:
+ /* SET 4,E */
+
+ SET_8BIT (4, cpustate->b.E)
+ break;
+case 0xE4:
+ /* SET 4,H */
+
+ SET_8BIT (4, cpustate->b.H)
+ break;
+case 0xE5:
+ /* SET 4,L */
+
+ SET_8BIT (4, cpustate->b.L)
+ break;
+case 0xE6:
+ /* SET 4,(HL) */
+
+ x = mem_ReadByte (cpustate, cpustate->w.HL);
+ SET_8BIT (4, x)
+ mem_WriteByte (cpustate, cpustate->w.HL, x);
+ break;
+case 0xE7:
+ /* SET 4,A */
+
+ SET_8BIT (4, cpustate->b.A)
+ break;
+case 0xE8:
+ /* SET 5,B */
+
+ SET_8BIT (5, cpustate->b.B)
+ break;
+case 0xE9:
+ /* SET 5,C */
+
+ SET_8BIT (5, cpustate->b.C)
+ break;
+case 0xEA:
+ /* SET 5,D */
+
+ SET_8BIT (5, cpustate->b.D)
+ break;
+case 0xEB:
+ /* SET 5,E */
+
+ SET_8BIT (5, cpustate->b.E)
+ break;
+case 0xEC:
+ /* SET 5,H */
+
+ SET_8BIT (5, cpustate->b.H)
+ break;
+case 0xED:
+ /* SET 5,L */
+
+ SET_8BIT (5, cpustate->b.L)
+ break;
+case 0xEE:
+ /* SET 5,(HL) */
+
+ x = mem_ReadByte (cpustate, cpustate->w.HL);
+ SET_8BIT (5, x)
+ mem_WriteByte (cpustate, cpustate->w.HL, x);
+ break;
+case 0xEF:
+ /* SET 5,A */
+
+ SET_8BIT (5, cpustate->b.A)
+ break;
+case 0xF0:
+ /* SET 6,B */
+
+ SET_8BIT (6, cpustate->b.B)
+ break;
+case 0xF1:
+ /* SET 6,C */
+
+ SET_8BIT (6, cpustate->b.C)
+ break;
+case 0xF2:
+ /* SET 6,D */
+
+ SET_8BIT (6, cpustate->b.D)
+ break;
+case 0xF3:
+ /* SET 6,E */
+
+ SET_8BIT (6, cpustate->b.E)
+ break;
+case 0xF4:
+ /* SET 6,H */
+
+ SET_8BIT (6, cpustate->b.H)
+ break;
+case 0xF5:
+ /* SET 6,L */
+
+ SET_8BIT (6, cpustate->b.L)
+ break;
+case 0xF6:
+ /* SET 6,(HL) */
+
+ x = mem_ReadByte (cpustate, cpustate->w.HL);
+ SET_8BIT (6, x)
+ mem_WriteByte (cpustate, cpustate->w.HL, x);
+ break;
+case 0xF7:
+ /* SET 6,A */
+
+ SET_8BIT (6, cpustate->b.A)
+ break;
+case 0xF8:
+ /* SET 7,B */
+
+ SET_8BIT (7, cpustate->b.B)
+ break;
+case 0xF9:
+ /* SET 7,C */
+
+ SET_8BIT (7, cpustate->b.C)
+ break;
+case 0xFA:
+ /* SET 7,D */
+
+ SET_8BIT (7, cpustate->b.D)
+ break;
+case 0xFB:
+ /* SET 7,E */
+
+ SET_8BIT (7, cpustate->b.E)
+ break;
+case 0xFC:
+ /* SET 7,H */
+
+ SET_8BIT (7, cpustate->b.H)
+ break;
+case 0xFD:
+ /* SET 7,L */
+
+ SET_8BIT (7, cpustate->b.L)
+ break;
+case 0xFE:
+ /* SET 7,(HL) */
+
+ x = mem_ReadByte (cpustate, cpustate->w.HL);
+ SET_8BIT (7, x)
+ mem_WriteByte (cpustate, cpustate->w.HL, x);
+ break;
+case 0xFF:
+ /* SET 7,A */
+
+ SET_8BIT (7, cpustate->b.A)
+ break;
diff --git a/trunk/src/emu/cpu/lr35902/opc_main.h b/trunk/src/emu/cpu/lr35902/opc_main.h
new file mode 100644
index 00000000000..6c47af1e3e8
--- /dev/null
+++ b/trunk/src/emu/cpu/lr35902/opc_main.h
@@ -0,0 +1,1551 @@
+#define INC_8BIT(x) \
+{ \
+ register UINT8 r,f; \
+ x++; \
+ r=(x); \
+ f=(UINT8)(cpustate->b.F&FLAG_C); \
+ if( r==0 ) f|=FLAG_Z; \
+ if( (r&0xF)==0 ) f|=FLAG_H; \
+ cpustate->b.F=f; \
+}
+
+#define DEC_8BIT(x) \
+{ \
+ register UINT8 r,f; \
+ x--; \
+ r=(x); \
+ f=(UINT8)((cpustate->b.F&FLAG_C)|FLAG_N); \
+ if( r==0 ) f|=FLAG_Z; \
+ if( (r&0xF)==0xF ) f|=FLAG_H; \
+ cpustate->b.F=f; \
+}
+
+#define ADD_HL_RR(x) \
+{ \
+ register UINT32 r1,r2; \
+ register UINT8 f; \
+ r1=cpustate->w.HL+(x); \
+ r2=(cpustate->w.HL&0xFFF)+((x)&0xFFF); \
+ f=(UINT8)(cpustate->b.F&FLAG_Z); \
+ if( r1>0xFFFF ) f|=FLAG_C; \
+ if( r2>0x0FFF ) f|=FLAG_H; \
+ cpustate->w.HL=(UINT16)r1; \
+ cpustate->b.F=f; \
+}
+
+#define ADD_A_X(x) \
+{ \
+ register UINT16 r1,r2; \
+ register UINT8 f; \
+ r1=(UINT16)((cpustate->b.A&0xF)+((x)&0xF)); \
+ r2=(UINT16)(cpustate->b.A+(x)); \
+ cpustate->b.A=(UINT8)r2; \
+ if( ((UINT8)r2)==0 ) f=FLAG_Z; \
+ else f=0; \
+ if( r2>0xFF ) f|=FLAG_C; \
+ if( r1>0xF ) f|=FLAG_H; \
+ cpustate->b.F=f; \
+}
+
+#define SUB_A_X(x) \
+{ \
+ register UINT16 r1,r2; \
+ register UINT8 f; \
+ r1=(UINT16)((cpustate->b.A&0xF)-((x)&0xF)); \
+ r2=(UINT16)(cpustate->b.A-(x)); \
+ cpustate->b.A=(UINT8)r2; \
+ if( ((UINT8)r2)==0 ) f=FLAG_N|FLAG_Z; \
+ else f=FLAG_N; \
+ if( r2>0xFF ) f|=FLAG_C; \
+ if( r1>0xF ) f|=FLAG_H; \
+ cpustate->b.F=f; \
+}
+
+/*
+ #define CP_A_X(x) \
+ { \
+ register UINT16 r; \
+ register UINT8 f; \
+ r=(UINT16)(cpustate->b.A-(x)); \
+ if( ((UINT8)r)==0 ) \
+ f=FLAG_N|FLAG_Z; \
+ else \
+ f=FLAG_N; \
+ f|=(UINT8)((r>>8)&FLAG_C); \
+ if( (r^cpustate->b.A^(x))&0x10 ) \
+ f|=FLAG_H; \
+ cpustate->b.F=f; \
+ }
+ */
+
+#define CP_A_X(x) \
+{ \
+ register UINT16 r1,r2; \
+ register UINT8 f; \
+ r1=(UINT16)((cpustate->b.A&0xF)-((x)&0xF)); \
+ r2=(UINT16)(cpustate->b.A-(x)); \
+ if( ((UINT8)r2)==0 ) f=FLAG_N|FLAG_Z; \
+ else f=FLAG_N; \
+ if( r2>0xFF ) f|=FLAG_C; \
+ if( r1>0xF ) f|=FLAG_H; \
+ cpustate->b.F=f; \
+}
+
+#define SBC_A_X(x) \
+{ \
+ register UINT16 r1,r2; \
+ register UINT8 f; \
+ r1=(UINT16)((cpustate->b.A&0xF)-((x)&0xF)-((cpustate->b.F&FLAG_C)?1:0)); \
+ r2=(UINT16)(cpustate->b.A-(x)-((cpustate->b.F&FLAG_C)?1:0)); \
+ cpustate->b.A=(UINT8)r2; \
+ if( ((UINT8)r2)==0 ) f=FLAG_N|FLAG_Z; \
+ else f=FLAG_N; \
+ if( r2>0xFF ) f|=FLAG_C; \
+ if( r1>0xF ) f|=FLAG_H; \
+ cpustate->b.F=f; \
+}
+
+#define ADC_A_X(x) \
+{ \
+ register UINT16 r1,r2; \
+ register UINT8 f; \
+ r1=(UINT16)((cpustate->b.A&0xF)+((x)&0xF)+((cpustate->b.F&FLAG_C)?1:0)); \
+ r2=(UINT16)(cpustate->b.A+(x)+((cpustate->b.F&FLAG_C)?1:0)); \
+ if( (cpustate->b.A=(UINT8)r2)==0 ) f=FLAG_Z; \
+ else f=0; \
+ if( r2>0xFF ) f|=FLAG_C; \
+ if( r1>0xF ) f|=FLAG_H; \
+ cpustate->b.F=f; \
+}
+
+#define AND_A_X(x) \
+ if( (cpustate->b.A&=(x))==0 ) \
+ cpustate->b.F=FLAG_H|FLAG_Z; \
+ else \
+ cpustate->b.F=FLAG_H;
+
+#define XOR_A_X(x) \
+ if( (cpustate->b.A^=(x))==0 ) \
+ cpustate->b.F=FLAG_Z; \
+ else \
+ cpustate->b.F=0;
+
+#define OR_A_X(x) \
+ if( (cpustate->b.A|=(x))==0 ) \
+ cpustate->b.F=FLAG_Z; \
+ else \
+ cpustate->b.F=0;
+
+
+case 0x00: /* NOP */
+ break;
+case 0x01: /* LD BC,n16 */
+ cpustate->w.BC = mem_ReadWord (cpustate, cpustate->w.PC);
+ cpustate->w.PC += 2;
+ break;
+case 0x02: /* LD (BC),A */
+ mem_WriteByte (cpustate, cpustate->w.BC, cpustate->b.A);
+ break;
+case 0x03: /* INC BC */
+
+#if 0 /* FIXME ?? do we want to support this? (bug emulation) */
+ if (cpustate->b.B == 0xFE)
+ {
+ trash_sprites (state);
+ }
+#endif
+ cpustate->w.BC += 1;
+ break;
+case 0x04: /* INC B */
+
+ INC_8BIT (cpustate->b.B)
+ break;
+case 0x05: /* DEC B */
+
+ DEC_8BIT (cpustate->b.B)
+ break;
+case 0x06: /* LD B,n8 */
+
+ cpustate->b.B = mem_ReadByte (cpustate, cpustate->w.PC++);
+ break;
+case 0x07: /* RLCA */
+
+ cpustate->b.A = (UINT8) ((cpustate->b.A << 1) | (cpustate->b.A >> 7));
+ if (cpustate->b.A & 1)
+ {
+ cpustate->b.F = FLAG_C;
+ }
+ else
+ {
+ cpustate->b.F = 0;
+ }
+ break;
+case 0x08: /* LD (n16),SP */
+
+ mem_WriteWord (cpustate, mem_ReadWord (cpustate, cpustate->w.PC), cpustate->w.SP);
+ cpustate->w.PC += 2;
+ break;
+case 0x09: /* ADD HL,BC */
+
+ ADD_HL_RR (cpustate->w.BC)
+ break;
+case 0x0A: /* LD A,(BC) */
+
+ cpustate->b.A = mem_ReadByte (cpustate, cpustate->w.BC);
+ break;
+case 0x0B: /* DEC BC */
+
+#if 0 /* FIXME ?? do we want to support this? (bug emulation) */
+ if (cpustate->b.B == 0xFE)
+ {
+ trash_sprites (state);
+ }
+#endif
+
+ cpustate->w.BC -= 1;
+ break;
+case 0x0C: /* INC C */
+
+ INC_8BIT (cpustate->b.C)
+ break;
+case 0x0D: /* DEC C */
+
+ DEC_8BIT (cpustate->b.C)
+ break;
+case 0x0E: /* LD C,n8 */
+
+ cpustate->b.C = mem_ReadByte (cpustate, cpustate->w.PC++);
+ break;
+case 0x0F: /* RRCA */
+
+ cpustate->b.A = (UINT8) ((cpustate->b.A >> 1) | (cpustate->b.A << 7));
+ cpustate->b.F = 0;
+ if (cpustate->b.A & 0x80)
+ {
+ cpustate->b.F |= FLAG_C;
+ }
+ break;
+case 0x10: /* STOP */
+ if ( cpustate->w.gb_speed_change_pending ) {
+ cpustate->w.gb_speed = ( cpustate->w.gb_speed == 1 ) ? 2 : 1;
+ }
+ cpustate->w.gb_speed_change_pending = 0;
+ break;
+case 0x11: /* LD DE,n16 */
+
+ cpustate->w.DE = mem_ReadWord (cpustate, cpustate->w.PC);
+ cpustate->w.PC += 2;
+ break;
+case 0x12: /* LD (DE),A */
+ mem_WriteByte (cpustate, cpustate->w.DE, cpustate->b.A);
+ break;
+case 0x13: /* INC DE */
+
+#if 0 /* FIXME ?? do we want to support this? (bug emulation) */
+ if (cpustate->b.D == 0xFE)
+ {
+ trash_sprites (state);
+ }
+#endif
+
+ cpustate->w.DE += 1;
+ break;
+case 0x14: /* INC D */
+
+ INC_8BIT (cpustate->b.D)
+ break;
+case 0x15: /* DEC D */
+
+ DEC_8BIT (cpustate->b.D)
+ break;
+case 0x16: /* LD D,n8 */
+
+ cpustate->b.D = mem_ReadByte (cpustate, cpustate->w.PC++);
+ break;
+case 0x17: /* RLA */
+
+ x = (cpustate->b.A & 0x80) ? FLAG_C : 0;
+
+ cpustate->b.A = (UINT8) ((cpustate->b.A << 1) | ((cpustate->b.F & FLAG_C) ? 1 : 0));
+ cpustate->b.F = x;
+ break;
+case 0x18: /* JR n8 */
+ {
+ INT8 offset;
+
+ offset = mem_ReadByte (cpustate, cpustate->w.PC++);
+ cpustate->w.PC += offset;
+ }
+ break;
+case 0x19: /* ADD HL,DE */
+
+ ADD_HL_RR (cpustate->w.DE)
+ break;
+case 0x1A: /* LD A,(DE) */
+
+ cpustate->b.A = mem_ReadByte (cpustate, cpustate->w.DE);
+ break;
+case 0x1B: /* DEC DE */
+
+#if 0 /* FIXME ?? do we want to support this? (bug emulation) */
+ if (cpustate->b.D == 0xFE)
+ {
+ trash_sprites (state);
+ }
+#endif
+
+ cpustate->w.DE -= 1;
+ break;
+case 0x1C: /* INC E */
+
+ INC_8BIT (cpustate->b.E)
+ break;
+case 0x1D: /* DEC E */
+
+ DEC_8BIT (cpustate->b.E)
+ break;
+case 0x1E: /* LD E,n8 */
+
+ cpustate->b.E = mem_ReadByte (cpustate, cpustate->w.PC++);
+ break;
+case 0x1F: /* RRA */
+
+ x = (cpustate->b.A & 1) ? FLAG_C : 0;
+
+ cpustate->b.A = (UINT8) ((cpustate->b.A >> 1) | ((cpustate->b.F & FLAG_C) ? 0x80 : 0));
+ cpustate->b.F = x;
+ break;
+case 0x20: /* JR NZ,n8 */
+
+ if (cpustate->b.F & FLAG_Z)
+ {
+ cpustate->w.PC++;
+ }
+ else
+ {
+ INT8 offset;
+
+ offset = mem_ReadByte (cpustate, cpustate->w.PC++);
+ cpustate->w.PC += offset;
+ CYCLES_PASSED( 4 );
+ }
+ break;
+case 0x21: /* LD HL,n16 */
+
+ cpustate->w.HL = mem_ReadWord (cpustate, cpustate->w.PC);
+ cpustate->w.PC += 2;
+ break;
+case 0x22: /* LD (HL+),A */
+
+#if 0 /* FIXME ?? do we want to support this? (bug emulation) */
+ if (cpustate->b.H == 0xFE)
+ {
+ trash_sprites (state);
+ }
+#endif
+
+ mem_WriteByte (cpustate, cpustate->w.HL, cpustate->b.A);
+ cpustate->w.HL += 1;
+ break;
+case 0x23: /* INC HL */
+
+#if 0 /* FIXME ?? do we want to support this? (bug emulation) */
+ if (cpustate->b.H == 0xFE)
+ {
+ trash_sprites (state);
+ }
+#endif
+
+ cpustate->w.HL += 1;
+ break;
+case 0x24: /* INC H */
+
+ INC_8BIT (cpustate->b.H);
+ break;
+case 0x25: /* DEC H */
+
+ DEC_8BIT (cpustate->b.H);
+ break;
+case 0x26: /* LD H,n8 */
+
+ cpustate->b.H = mem_ReadByte (cpustate, cpustate->w.PC++);
+ break;
+case 0x27: /* DAA */
+ {
+ int tmp = cpustate->b.A;
+
+ if ( ! ( cpustate->b.F & FLAG_N ) ) {
+ if ( ( cpustate->b.F & FLAG_H ) || ( tmp & 0x0F ) > 9 )
+ tmp += 6;
+ if ( ( cpustate->b.F & FLAG_C ) || tmp > 0x9F )
+ tmp += 0x60;
+ } else {
+ if ( cpustate->b.F & FLAG_H ) {
+ tmp -= 6;
+ if ( ! ( cpustate->b.F & FLAG_C ) )
+ tmp &= 0xFF;
+ }
+ if ( cpustate->b.F & FLAG_C )
+ tmp -= 0x60;
+ }
+ cpustate->b.F &= ~ ( FLAG_H | FLAG_Z );
+ if ( tmp & 0x100 )
+ cpustate->b.F |= FLAG_C;
+ cpustate->b.A = tmp & 0xFF;
+ if ( ! cpustate->b.A )
+ cpustate->b.F |= FLAG_Z;
+ }
+ break;
+case 0x28: /* JR Z,n8 */
+
+ if (cpustate->b.F & FLAG_Z)
+ {
+ INT8 offset;
+
+ offset = mem_ReadByte (cpustate, cpustate->w.PC++);
+ cpustate->w.PC += offset;
+
+ CYCLES_PASSED( 4 );
+ }
+ else
+ {
+ cpustate->w.PC += 1;
+ }
+ break;
+case 0x29: /* ADD HL,HL */
+
+ ADD_HL_RR (cpustate->w.HL)
+ break;
+case 0x2A: /* LD A,(HL+) */
+#if 0 /* FIXME ?? do we want to support this? (bug emulation) */
+ if (cpustate->b.H == 0xFE)
+ {
+ trash_sprites (state);
+ }
+#endif
+
+ cpustate->b.A = mem_ReadByte (cpustate, cpustate->w.HL);
+ cpustate->w.HL += 1;
+ break;
+case 0x2B: /* DEC HL */
+
+#if 0 /* FIXME ?? do we want to support this? (bug emulation) */
+ if (cpustate->b.H == 0xFE)
+ {
+ trash_sprites (state);
+ }
+#endif
+
+ cpustate->w.HL -= 1;
+ break;
+case 0x2C: /* INC L */
+
+ INC_8BIT (cpustate->b.L);
+ break;
+case 0x2D: /* DEC L */
+
+ DEC_8BIT (cpustate->b.L);
+ break;
+case 0x2E: /* LD L,n8 */
+
+ cpustate->b.L = mem_ReadByte (cpustate, cpustate->w.PC++);
+ break;
+case 0x2F: /* CPL */
+
+ cpustate->b.A = ~cpustate->b.A;
+ cpustate->b.F |= FLAG_N | FLAG_H;
+ break;
+case 0x30: /* JR NC,n8 */
+
+ if (cpustate->b.F & FLAG_C)
+ {
+ cpustate->w.PC += 1;
+ }
+ else
+ {
+ INT8 offset;
+
+ offset = mem_ReadByte (cpustate, cpustate->w.PC++);
+ cpustate->w.PC += offset;
+ CYCLES_PASSED( 4 );
+ }
+ break;
+case 0x31: /* LD SP,n16 */
+
+ cpustate->w.SP = mem_ReadWord (cpustate, cpustate->w.PC);
+ cpustate->w.PC += 2;
+ break;
+case 0x32: /* LD (HL-),A */
+
+#if 0 /* FIXME ?? do we want to support this? (bug emulation) */
+ if (cpustate->b.H == 0xFE)
+ {
+ trash_sprites (state);
+ }
+#endif
+
+ mem_WriteByte (cpustate, cpustate->w.HL, cpustate->b.A);
+ cpustate->w.HL -= 1;
+ break;
+case 0x33: /* INC SP */
+
+ cpustate->w.SP += 1;
+ break;
+case 0x34: /* INC (HL) */
+
+ {
+ register UINT8 r, f;
+
+ f = (UINT8) (cpustate->b.F & FLAG_C);
+ r = (UINT8) (mem_ReadByte (cpustate, cpustate->w.HL) + 1);
+ mem_WriteByte (cpustate, cpustate->w.HL, r);
+
+ if (r == 0)
+ f |= FLAG_Z;
+
+ if ((r & 0xF) == 0)
+ f |= FLAG_H;
+
+ cpustate->b.F = f;
+ }
+ break;
+case 0x35: /* DEC (HL) */
+
+ {
+ register UINT8 r, f;
+
+ f = (UINT8) ((cpustate->b.F & FLAG_C) | FLAG_N);
+ r = (UINT8) (mem_ReadByte (cpustate, cpustate->w.HL) - 1);
+ mem_WriteByte (cpustate, cpustate->w.HL, r);
+
+ if (r == 0)
+ f |= FLAG_Z;
+
+ if ((r & 0xF) == 0xF)
+ f |= FLAG_H;
+
+ cpustate->b.F = f;
+ }
+ break;
+case 0x36: /* LD (HL),n8 */
+ /* FIXED / broken ? */
+ mem_WriteByte (cpustate, cpustate->w.HL, mem_ReadByte (cpustate, cpustate->w.PC++));
+ break;
+case 0x37: /* SCF */
+
+ cpustate->b.F = (UINT8) ((cpustate->b.F & FLAG_Z) | FLAG_C);
+ break;
+case 0x38: /* JR C,n8 */
+
+ if (cpustate->b.F & FLAG_C)
+ {
+ INT8 offset;
+
+ offset = mem_ReadByte (cpustate, cpustate->w.PC++);
+ cpustate->w.PC += offset;
+
+ CYCLES_PASSED( 4 );
+ }
+ else
+ {
+ cpustate->w.PC += 1;
+ }
+ break;
+case 0x39: /* ADD HL,SP */
+ ADD_HL_RR (cpustate->w.SP)
+ break;
+case 0x3A: /* LD A,(HL-) */
+#if 0 /* FIXME ?? do we want to support this? (bug emulation) */
+ if (cpustate->b.H == 0xFE)
+ {
+ trash_sprites (state);
+ }
+#endif
+
+ cpustate->b.A = mem_ReadByte (cpustate, cpustate->w.HL);
+ cpustate->w.HL -= 1;
+ break;
+case 0x3B: /* DEC SP */
+
+ cpustate->w.SP -= 1;
+ break;
+case 0x3C: /* INC A */
+
+ INC_8BIT (cpustate->b.A);
+ break;
+case 0x3D: /* DEC A */
+
+ DEC_8BIT (cpustate->b.A);
+ break;
+case 0x3E: /* LD A,n8 */
+
+ cpustate->b.A = mem_ReadByte (cpustate, cpustate->w.PC++);
+ break;
+case 0x3F: /* CCF */
+
+ cpustate->b.F = (UINT8) ((cpustate->b.F & FLAG_Z) | ((cpustate->b.F & FLAG_C) ? 0 : FLAG_C));
+ break;
+case 0x40: /* LD B,B */
+ break;
+case 0x41: /* LD B,C */
+
+ cpustate->b.B = cpustate->b.C;
+ break;
+case 0x42: /* LD B,D */
+
+ cpustate->b.B = cpustate->b.D;
+ break;
+case 0x43: /* LD B,E */
+
+ cpustate->b.B = cpustate->b.E;
+ break;
+case 0x44: /* LD B,H */
+
+ cpustate->b.B = cpustate->b.H;
+ break;
+case 0x45: /* LD B,L */
+
+ cpustate->b.B = cpustate->b.L;
+ break;
+case 0x46: /* LD B,(HL) */
+
+ cpustate->b.B = mem_ReadByte (cpustate, cpustate->w.HL);
+ break;
+case 0x47: /* LD B,A */
+
+ cpustate->b.B = cpustate->b.A;
+ break;
+case 0x48: /* LD C,B */
+
+ cpustate->b.C = cpustate->b.B;
+ break;
+case 0x49: /* LD C,C */
+ break;
+case 0x4A: /* LD C,D */
+
+ cpustate->b.C = cpustate->b.D;
+ break;
+case 0x4B: /* LD C,E */
+
+ cpustate->b.C = cpustate->b.E;
+ break;
+case 0x4C: /* LD C,H */
+
+ cpustate->b.C = cpustate->b.H;
+ break;
+case 0x4D: /* LD C,L */
+
+ cpustate->b.C = cpustate->b.L;
+ break;
+case 0x4E: /* LD C,(HL) */
+
+ cpustate->b.C = mem_ReadByte (cpustate, cpustate->w.HL);
+ break;
+case 0x4F: /* LD C,A */
+
+ cpustate->b.C = cpustate->b.A;
+ break;
+case 0x50: /* LD D,B */
+
+ cpustate->b.D = cpustate->b.B;
+ break;
+case 0x51: /* LD D,C */
+
+ cpustate->b.D = cpustate->b.C;
+ break;
+case 0x52: /* LD D,D */
+ break;
+case 0x53: /* LD D,E */
+
+ cpustate->b.D = cpustate->b.E;
+ break;
+case 0x54: /* LD D,H */
+
+ cpustate->b.D = cpustate->b.H;
+ break;
+case 0x55: /* LD D,L */
+
+ cpustate->b.D = cpustate->b.L;
+ break;
+case 0x56: /* LD D,(HL) */
+
+ cpustate->b.D = mem_ReadByte (cpustate, cpustate->w.HL);
+ break;
+case 0x57: /* LD D,A */
+
+ cpustate->b.D = cpustate->b.A;
+ break;
+case 0x58: /* LD E,B */
+
+ cpustate->b.E = cpustate->b.B;
+ break;
+case 0x59: /* LD E,C */
+
+ cpustate->b.E = cpustate->b.C;
+ break;
+case 0x5A: /* LD E,D */
+
+ cpustate->b.E = cpustate->b.D;
+ break;
+case 0x5B: /* LD E,E */
+ break;
+case 0x5C: /* LD E,H */
+
+ cpustate->b.E = cpustate->b.H;
+ break;
+case 0x5D: /* LD E,L */
+
+ cpustate->b.E = cpustate->b.L;
+ break;
+case 0x5E: /* LD E,(HL) */
+
+ cpustate->b.E = mem_ReadByte (cpustate, cpustate->w.HL);
+ break;
+case 0x5F: /* LD E,A */
+
+ cpustate->b.E = cpustate->b.A;
+ break;
+case 0x60: /* LD H,B */
+
+ cpustate->b.H = cpustate->b.B;
+ break;
+case 0x61: /* LD H,C */
+
+ cpustate->b.H = cpustate->b.C;
+ break;
+case 0x62: /* LD H,D */
+
+ cpustate->b.H = cpustate->b.D;
+ break;
+case 0x63: /* LD H,E */
+
+ cpustate->b.H = cpustate->b.E;
+ break;
+case 0x64: /* LD H,H */
+ break;
+case 0x65: /* LD H,L */
+
+ cpustate->b.H = cpustate->b.L;
+ break;
+case 0x66: /* LD H,(HL) */
+
+ cpustate->b.H = mem_ReadByte (cpustate, cpustate->w.HL);
+ break;
+case 0x67: /* LD H,A */
+
+ cpustate->b.H = cpustate->b.A;
+ break;
+case 0x68: /* LD L,B */
+
+ cpustate->b.L = cpustate->b.B;
+ break;
+case 0x69: /* LD L,C */
+
+ cpustate->b.L = cpustate->b.C;
+ break;
+case 0x6A: /* LD L,D */
+ cpustate->b.L = cpustate->b.D;
+ break;
+case 0x6B: /* LD L,E */
+
+ cpustate->b.L = cpustate->b.E;
+ break;
+case 0x6C: /* LD L,H */
+
+ cpustate->b.L = cpustate->b.H;
+ break;
+case 0x6D: /* LD L,L */
+ break;
+case 0x6E: /* LD L,(HL) */
+
+ cpustate->b.L = mem_ReadByte (cpustate, cpustate->w.HL);
+ break;
+case 0x6F: /* LD L,A */
+
+ cpustate->b.L = cpustate->b.A;
+ break;
+case 0x70: /* LD (HL),B */
+
+ mem_WriteByte (cpustate, cpustate->w.HL, cpustate->b.B);
+ break;
+case 0x71: /* LD (HL),C */
+
+ mem_WriteByte (cpustate, cpustate->w.HL, cpustate->b.C);
+ break;
+case 0x72: /* LD (HL),D */
+
+ mem_WriteByte (cpustate, cpustate->w.HL, cpustate->b.D);
+ break;
+case 0x73: /* LD (HL),E */
+
+ mem_WriteByte (cpustate, cpustate->w.HL, cpustate->b.E);
+ break;
+case 0x74: /* LD (HL),H */
+
+ mem_WriteByte (cpustate, cpustate->w.HL, cpustate->b.H);
+ break;
+case 0x75: /* LD (HL),L */
+
+ mem_WriteByte (cpustate, cpustate->w.HL, cpustate->b.L);
+ break;
+case 0x76: /* HALT */
+ cpustate->w.enable |= HALTED;
+ cpustate->w.PC--;
+ break;
+case 0x77: /* LD (HL),A */
+
+ mem_WriteByte (cpustate, cpustate->w.HL, cpustate->b.A);
+ break;
+case 0x78: /* LD A,B */
+
+ cpustate->b.A = cpustate->b.B;
+ break;
+case 0x79: /* LD A,C */
+
+ cpustate->b.A = cpustate->b.C;
+ break;
+case 0x7A: /* LD A,D */
+
+ cpustate->b.A = cpustate->b.D;
+ break;
+case 0x7B: /* LD A,E */
+
+ cpustate->b.A = cpustate->b.E;
+ break;
+case 0x7C: /* LD A,H */
+
+ cpustate->b.A = cpustate->b.H;
+ break;
+case 0x7D: /* LD A,L */
+
+ cpustate->b.A = cpustate->b.L;
+ break;
+case 0x7E: /* LD A,(HL) */
+
+ cpustate->b.A = mem_ReadByte (cpustate, cpustate->w.HL);
+ break;
+case 0x7F: /* LD A,A */
+ break;
+case 0x80: /* ADD A,B */
+
+ ADD_A_X (cpustate->b.B)
+ break;
+case 0x81: /* ADD A,C */
+
+ ADD_A_X (cpustate->b.C)
+ break;
+case 0x82: /* ADD A,D */
+
+ ADD_A_X (cpustate->b.D)
+ break;
+case 0x83: /* ADD A,E */
+
+ ADD_A_X (cpustate->b.E)
+ break;
+case 0x84: /* ADD A,H */
+
+ ADD_A_X (cpustate->b.H)
+ break;
+case 0x85: /* ADD A,L */
+
+ ADD_A_X (cpustate->b.L)
+ break;
+case 0x86: /* ADD A,(HL) */
+
+ x = mem_ReadByte (cpustate, cpustate->w.HL);
+
+ ADD_A_X (x)
+ break;
+case 0x87: /* ADD A,A */
+
+ ADD_A_X (cpustate->b.A)
+ break;
+case 0x88: /* ADC A,B */
+
+ ADC_A_X (cpustate->b.B)
+ break;
+case 0x89: /* ADC A,C */
+
+ ADC_A_X (cpustate->b.C)
+ break;
+case 0x8A: /* ADC A,D */
+
+ ADC_A_X (cpustate->b.D)
+ break;
+case 0x8B: /* ADC A,E */
+
+ ADC_A_X (cpustate->b.E)
+ break;
+case 0x8C: /* ADC A,H */
+
+ ADC_A_X (cpustate->b.H)
+ break;
+case 0x8D: /* ADC A,L */
+
+ ADC_A_X (cpustate->b.L)
+ break;
+case 0x8E: /* ADC A,(HL) */
+
+ x = mem_ReadByte (cpustate, cpustate->w.HL);
+
+ ADC_A_X (x)
+ break;
+case 0x8F: /* ADC A,A */
+
+ ADC_A_X (cpustate->b.A)
+ break;
+case 0x90: /* SUB A,B */
+
+ SUB_A_X (cpustate->b.B)
+ break;
+case 0x91: /* SUB A,C */
+
+ SUB_A_X (cpustate->b.C)
+ break;
+case 0x92: /* SUB A,D */
+
+ SUB_A_X (cpustate->b.D)
+ break;
+case 0x93: /* SUB A,E */
+
+ SUB_A_X (cpustate->b.E)
+ break;
+case 0x94: /* SUB A,H */
+
+ SUB_A_X (cpustate->b.H)
+ break;
+case 0x95: /* SUB A,L */
+
+ SUB_A_X (cpustate->b.L)
+ break;
+case 0x96: /* SUB A,(HL) */
+
+
+ x = mem_ReadByte (cpustate, cpustate->w.HL);
+
+ SUB_A_X (x)
+ break;
+case 0x97: /* SUB A,A */
+
+ SUB_A_X (cpustate->b.A)
+ break;
+case 0x98: /* SBC A,B */
+
+ SBC_A_X (cpustate->b.B)
+ break;
+case 0x99: /* SBC A,C */
+
+ SBC_A_X (cpustate->b.C)
+ break;
+case 0x9A: /* SBC A,D */
+
+ SBC_A_X (cpustate->b.D)
+ break;
+case 0x9B: /* SBC A,E */
+
+ SBC_A_X (cpustate->b.E)
+ break;
+case 0x9C: /* SBC A,H */
+
+ SBC_A_X (cpustate->b.H)
+ break;
+case 0x9D: /* SBC A,L */
+
+ SBC_A_X (cpustate->b.L)
+ break;
+case 0x9E: /* SBC A,(HL) */
+
+ x = mem_ReadByte (cpustate, cpustate->w.HL);
+
+ SBC_A_X (x)
+ break;
+case 0x9F: /* SBC A,A */
+
+ SBC_A_X (cpustate->b.A)
+ break;
+case 0xA0: /* AND A,B */
+
+ AND_A_X (cpustate->b.B)
+ break;
+case 0xA1: /* AND A,C */
+
+ AND_A_X (cpustate->b.C)
+ break;
+case 0xA2: /* AND A,D */
+
+ AND_A_X (cpustate->b.D)
+ break;
+case 0xA3: /* AND A,E */
+
+ AND_A_X (cpustate->b.E)
+ break;
+case 0xA4: /* AND A,H */
+
+ AND_A_X (cpustate->b.H)
+ break;
+case 0xA5: /* AND A,L */
+
+ AND_A_X (cpustate->b.L)
+ break;
+case 0xA6: /* AND A,(HL) */
+
+ x = mem_ReadByte (cpustate, cpustate->w.HL);
+
+ AND_A_X (x)
+ break;
+case 0xA7: /* AND A,A */
+
+ cpustate->b.F = (cpustate->b.A == 0) ? (FLAG_H | FLAG_Z) : FLAG_H;
+ break;
+case 0xA8: /* XOR A,B */
+
+ XOR_A_X (cpustate->b.B)
+ break;
+case 0xA9: /* XOR A,C */
+
+ XOR_A_X (cpustate->b.C)
+ break;
+case 0xAA: /* XOR A,D */
+
+ XOR_A_X (cpustate->b.D)
+ break;
+case 0xAB: /* XOR A,E */
+
+ XOR_A_X (cpustate->b.E)
+ break;
+case 0xAC: /* XOR A,H */
+
+ XOR_A_X (cpustate->b.H)
+ break;
+case 0xAD: /* XOR A,L */
+
+ XOR_A_X (cpustate->b.L)
+ break;
+case 0xAE: /* XOR A,(HL) */
+
+ x = mem_ReadByte (cpustate, cpustate->w.HL);
+
+ XOR_A_X (x)
+ break;
+case 0xAF: /* XOR A,A */
+
+ XOR_A_X (cpustate->b.A)
+ break;
+case 0xB0: /* OR A,B */
+
+ OR_A_X (cpustate->b.B)
+ break;
+case 0xB1: /* OR A,C */
+
+ OR_A_X (cpustate->b.C)
+ break;
+case 0xB2: /* OR A,D */
+
+ OR_A_X (cpustate->b.D)
+ break;
+case 0xB3: /* OR A,E */
+
+ OR_A_X (cpustate->b.E)
+ break;
+case 0xB4: /* OR A,H */
+
+ OR_A_X (cpustate->b.H)
+ break;
+case 0xB5: /* OR A,L */
+
+ OR_A_X (cpustate->b.L)
+ break;
+case 0xB6: /* OR A,(HL) */
+
+ x = mem_ReadByte (cpustate, cpustate->w.HL);
+
+ OR_A_X (x)
+ break;
+case 0xB7: /* OR A,A */
+
+ OR_A_X (cpustate->b.A)
+ break;
+case 0xB8: /* CP A,B */
+
+ CP_A_X (cpustate->b.B)
+ break;
+case 0xB9: /* CP A,C */
+
+ CP_A_X (cpustate->b.C)
+ break;
+case 0xBA: /* CP A,D */
+
+ CP_A_X (cpustate->b.D)
+ break;
+case 0xBB: /* CP A,E */
+
+ CP_A_X (cpustate->b.E)
+ break;
+case 0xBC: /* CP A,H */
+
+ CP_A_X (cpustate->b.H)
+ break;
+case 0xBD: /* CP A,L */
+
+ CP_A_X (cpustate->b.L)
+ break;
+case 0xBE: /* CP A,(HL) */
+
+ x = mem_ReadByte (cpustate, cpustate->w.HL);
+
+ CP_A_X (x)
+ break;
+case 0xBF: /* CP A,A */
+
+ CP_A_X (cpustate->b.A)
+ break;
+case 0xC0: /* RET NZ */
+
+ if (!(cpustate->b.F & FLAG_Z))
+ {
+ cpustate->w.PC = mem_ReadWord (cpustate, cpustate->w.SP);
+ cpustate->w.SP += 2;
+ CYCLES_PASSED( 12 );
+ }
+ break;
+case 0xC1: /* POP BC */
+
+ cpustate->w.BC = mem_ReadWord (cpustate, cpustate->w.SP);
+ cpustate->w.SP += 2;
+ break;
+case 0xC2: /* JP NZ,n16 */
+
+ if (cpustate->b.F & FLAG_Z)
+ {
+ cpustate->w.PC += 2;
+ }
+ else
+ {
+ cpustate->w.PC = mem_ReadWord (cpustate, cpustate->w.PC);
+ CYCLES_PASSED( 4 );
+ }
+ break;
+case 0xC3: /* JP n16 */
+
+ cpustate->w.PC = mem_ReadWord (cpustate, cpustate->w.PC);
+ break;
+case 0xC4: /* CALL NZ,n16 */
+
+ if (cpustate->b.F & FLAG_Z)
+ {
+ cpustate->w.PC += 2;
+ }
+ else
+ {
+ register UINT16 PC;
+ PC = mem_ReadWord (cpustate, cpustate->w.PC);
+ cpustate->w.PC += 2;
+
+ cpustate->w.SP -= 2;
+ mem_WriteWord (cpustate, cpustate->w.SP, cpustate->w.PC);
+ cpustate->w.PC = PC;
+ CYCLES_PASSED( 12 );
+ }
+ break;
+case 0xC5: /* PUSH BC */
+
+ cpustate->w.SP -= 2;
+ mem_WriteWord (cpustate, cpustate->w.SP, cpustate->w.BC);
+ break;
+case 0xC6: /* ADD A,n8 */
+
+ x = mem_ReadByte (cpustate, cpustate->w.PC++);
+ ADD_A_X (x)
+ break;
+case 0xC7: /* RST 0 */
+
+ {
+ register UINT16 PC;
+ PC = cpustate->w.PC;
+ cpustate->w.PC = 0;
+
+ cpustate->w.SP -= 2;
+ mem_WriteWord (cpustate, cpustate->w.SP, PC);
+ }
+ break;
+case 0xC8: /* RET Z */
+
+ if (cpustate->b.F & FLAG_Z)
+ {
+ cpustate->w.PC = mem_ReadWord (cpustate, cpustate->w.SP);
+ cpustate->w.SP += 2;
+ CYCLES_PASSED( 12 );
+ }
+ break;
+case 0xC9: /* RET */
+
+ cpustate->w.PC = mem_ReadWord (cpustate, cpustate->w.SP);
+ cpustate->w.SP += 2;
+ break;
+case 0xCA: /* JP Z,n16 */
+
+ if (cpustate->b.F & FLAG_Z)
+ {
+ cpustate->w.PC = mem_ReadWord (cpustate, cpustate->w.PC);
+ CYCLES_PASSED( 4 );
+ }
+ else
+ {
+ cpustate->w.PC += 2;
+ }
+ break;
+case 0xCB: /* PREFIX! */
+ x = mem_ReadByte (cpustate, cpustate->w.PC++);
+ CYCLES_PASSED( CyclesCB[x] );
+ switch (x)
+ {
+ #include "opc_cb.h"
+ }
+ break;
+case 0xCC: /* CALL Z,n16 */
+
+ if (cpustate->b.F & FLAG_Z)
+ {
+ register UINT16 PC;
+ PC = mem_ReadWord (cpustate, cpustate->w.PC);
+ cpustate->w.PC += 2;
+
+ cpustate->w.SP -= 2;
+ mem_WriteWord (cpustate, cpustate->w.SP, cpustate->w.PC);
+ cpustate->w.PC = PC;
+ CYCLES_PASSED( 12 );
+ }
+ else
+ {
+ cpustate->w.PC += 2;
+ }
+ break;
+case 0xCD: /* CALL n16 */
+ {
+ register UINT16 PC;
+ PC = mem_ReadWord (cpustate, cpustate->w.PC);
+ cpustate->w.PC += 2;
+
+ cpustate->w.SP -= 2;
+ mem_WriteWord (cpustate, cpustate->w.SP, cpustate->w.PC);
+ cpustate->w.PC = PC;
+ }
+ break;
+case 0xCE: /* ADC A,n8 */
+
+ x = mem_ReadByte (cpustate, cpustate->w.PC++);
+ ADC_A_X (x)
+ break;
+case 0xCF: /* RST 8 */
+
+ cpustate->w.SP -= 2;
+ mem_WriteWord (cpustate, cpustate->w.SP, cpustate->w.PC);
+ cpustate->w.PC = 8;
+ break;
+case 0xD0: /* RET NC */
+
+ if (!(cpustate->b.F & FLAG_C))
+ {
+ cpustate->w.PC = mem_ReadWord (cpustate, cpustate->w.SP);
+ cpustate->w.SP += 2;
+ CYCLES_PASSED( 12 );
+ }
+ break;
+case 0xD1: /* POP DE */
+
+ cpustate->w.DE = mem_ReadWord (cpustate, cpustate->w.SP);
+ cpustate->w.SP += 2;
+ break;
+case 0xD2: /* JP NC,n16 */
+
+ if (cpustate->b.F & FLAG_C)
+ {
+ cpustate->w.PC += 2;
+ }
+ else
+ {
+ cpustate->w.PC = mem_ReadWord (cpustate, cpustate->w.PC);
+ CYCLES_PASSED( 4 );
+ }
+ break;
+case 0xD3: /* EH? */
+ break;
+case 0xD4: /* CALL NC,n16 */
+
+ if (cpustate->b.F & FLAG_C)
+ {
+ cpustate->w.PC += 2;
+ }
+ else
+ {
+ register UINT16 PC;
+ PC = mem_ReadWord (cpustate, cpustate->w.PC);
+ cpustate->w.PC += 2;
+
+ cpustate->w.SP -= 2;
+ mem_WriteWord (cpustate, cpustate->w.SP, cpustate->w.PC);
+ cpustate->w.PC = PC;
+ CYCLES_PASSED( 12 );
+ }
+ break;
+case 0xD5: /* PUSH DE */
+
+ cpustate->w.SP -= 2;
+ mem_WriteWord (cpustate, cpustate->w.SP, cpustate->w.DE);
+ break;
+case 0xD6: /* SUB A,n8 */
+
+ x = mem_ReadByte (cpustate, cpustate->w.PC++);
+ SUB_A_X (x)
+ break;
+case 0xD7: /* RST $10 */
+
+ cpustate->w.SP -= 2;
+ mem_WriteWord (cpustate, cpustate->w.SP, cpustate->w.PC);
+ cpustate->w.PC = 0x10;
+ break;
+case 0xD8: /* RET C */
+
+ if (cpustate->b.F & FLAG_C)
+ {
+ cpustate->w.PC = mem_ReadWord (cpustate, cpustate->w.SP);
+ cpustate->w.SP += 2;
+ CYCLES_PASSED( 12 );
+ }
+ break;
+case 0xD9: /* RETI */
+
+ cpustate->w.PC = mem_ReadWord (cpustate, cpustate->w.SP);
+ cpustate->w.SP += 2;
+ cpustate->w.enable |= IME;
+ break;
+case 0xDA: /* JP C,n16 */
+
+ if (cpustate->b.F & FLAG_C)
+ {
+ cpustate->w.PC = mem_ReadWord (cpustate, cpustate->w.PC);
+ CYCLES_PASSED( 4 );
+ }
+ else
+ {
+ cpustate->w.PC += 2;
+ }
+ break;
+case 0xDB: /* EH? */
+ break;
+case 0xDC: /* CALL C,n16 */
+
+ if (cpustate->b.F & FLAG_C)
+ {
+ register UINT16 PC;
+ PC = mem_ReadWord (cpustate, cpustate->w.PC);
+ cpustate->w.PC += 2;
+
+ cpustate->w.SP -= 2;
+ mem_WriteWord (cpustate, cpustate->w.SP, cpustate->w.PC);
+ cpustate->w.PC = PC;
+ CYCLES_PASSED( 12 );
+ }
+ else
+ {
+ cpustate->w.PC += 2;
+ }
+ break;
+case 0xDD: /* EH? */
+ break;
+case 0xDE: /* SBC A,n8 */
+
+ x = mem_ReadByte (cpustate, cpustate->w.PC++);
+ SBC_A_X (x)
+ break;
+case 0xDF: /* RST $18 */
+
+ cpustate->w.SP -= 2;
+ mem_WriteWord (cpustate, cpustate->w.SP, cpustate->w.PC);
+ cpustate->w.PC = 0x18;
+ break;
+case 0xE0: /* LD ($FF00+n8),A */
+ mem_WriteByte (cpustate, mem_ReadByte (cpustate, cpustate->w.PC++) + 0xFF00, cpustate->b.A);
+ break;
+case 0xE1: /* POP HL */
+
+ cpustate->w.HL = mem_ReadWord (cpustate, cpustate->w.SP);
+ cpustate->w.SP += 2;
+ break;
+case 0xE2: /* LD ($FF00+C),A */
+
+ mem_WriteByte (cpustate, (UINT16) (0xFF00 + cpustate->b.C), cpustate->b.A);
+ break;
+case 0xE3: /* EH? */
+ break;
+case 0xE4: /* EH? */
+ break;
+case 0xE5: /* PUSH HL */
+
+ cpustate->w.SP -= 2;
+ mem_WriteWord (cpustate, cpustate->w.SP, cpustate->w.HL);
+ break;
+case 0xE6: /* AND A,n8 */
+
+ x = mem_ReadByte (cpustate, cpustate->w.PC++);
+ AND_A_X (x)
+ break;
+case 0xE7: /* RST $20 */
+
+ cpustate->w.SP -= 2;
+ mem_WriteWord (cpustate, cpustate->w.SP, cpustate->w.PC);
+ cpustate->w.PC = 0x20;
+ break;
+case 0xE8: /* ADD SP,n8 */
+/*
+ * Z - Reset.
+ * N - Reset.
+ * H - Set or reset according to operation.
+ * C - Set or reset according to operation.
+ */
+
+ {
+ register INT32 n;
+
+ n = (INT32) ((INT8) mem_ReadByte (cpustate, cpustate->w.PC++));
+
+ if ( ( cpustate->w.SP & 0xFF ) + (UINT8)(n & 0xFF) > 0xFF )
+ {
+ cpustate->b.F = FLAG_C;
+ }
+ else
+ {
+ cpustate->b.F = 0;
+ }
+
+ if ( ( cpustate->w.SP & 0x0F ) + ( n & 0x0F ) > 0x0F )
+ {
+ cpustate->b.F |= FLAG_H;
+ }
+
+ cpustate->w.SP = (UINT16) ( cpustate->w.SP + n );
+ }
+ break;
+case 0xE9: /* JP (HL) */
+
+ cpustate->w.PC = cpustate->w.HL;
+ break;
+case 0xEA: /* LD (n16),A */
+
+ mem_WriteByte (cpustate, mem_ReadWord (cpustate, cpustate->w.PC), cpustate->b.A);
+ cpustate->w.PC += 2;
+ break;
+case 0xEB: /* EH? */
+ break;
+case 0xEC: /* EH? */
+ break;
+case 0xED: /* EH? */
+ break;
+case 0xEE: /* XOR A,n8 */
+
+ x = mem_ReadByte (cpustate, cpustate->w.PC++);
+ XOR_A_X (x)
+ break;
+case 0xEF: /* RST $28 */
+
+ cpustate->w.SP -= 2;
+ mem_WriteWord (cpustate, cpustate->w.SP, cpustate->w.PC);
+ cpustate->w.PC = 0x28;
+ break;
+case 0xF0: /* LD A,($FF00+n8) */
+
+ cpustate->b.A = mem_ReadByte (cpustate, 0xFF00 + mem_ReadByte (cpustate, cpustate->w.PC++));
+ break;
+case 0xF1: /* POP AF */
+
+ cpustate->w.AF = (UINT16) (mem_ReadWord (cpustate, cpustate->w.SP) & 0xFFF0);
+ cpustate->w.SP += 2;
+ break;
+case 0xF2: /* LD A,($FF00+C) */
+
+ cpustate->b.A = mem_ReadByte (cpustate, (UINT16) (0xFF00 + cpustate->b.C));
+ break;
+case 0xF3: /* DI */
+ cpustate->w.ei_delay = 0;
+ cpustate->w.enable &= ~IME;
+ break;
+case 0xF4: /* EH? */
+ break;
+case 0xF5: /* PUSH AF */
+
+ cpustate->w.SP -= 2;
+ mem_WriteWord (cpustate, cpustate->w.SP, (UINT16) (cpustate->w.AF & 0xFFF0));
+ break;
+case 0xF6: /* OR A,n8 */
+
+ x = mem_ReadByte (cpustate, cpustate->w.PC++);
+ OR_A_X (x)
+ break;
+case 0xF7: /* RST $30 */
+
+ cpustate->w.SP -= 2;
+ mem_WriteWord (cpustate, cpustate->w.SP, cpustate->w.PC);
+ cpustate->w.PC = 0x30;
+ break;
+case 0xF8: /* LD HL,SP+n8 */
+/*
+ * n = one UINT8 signed immediate value.
+ * Flags affected:
+ * Z - Reset.
+ * N - Reset.
+ * H - Set or reset according to operation.
+ * C - Set or reset according to operation.
+ *
+ */
+
+ {
+ register INT32 n;
+
+ n = (INT32) ((INT8) mem_ReadByte (cpustate, cpustate->w.PC++));
+
+ if ( ( cpustate->w.SP & 0xFF ) + (UINT8)(n & 0xFF) > 0xFF )
+ {
+ cpustate->b.F = FLAG_C;
+ }
+ else
+ {
+ cpustate->b.F = 0;
+ }
+
+ if ( ( cpustate->w.SP & 0x0F ) + ( n & 0x0F ) > 0x0F )
+ {
+ cpustate->b.F |= FLAG_H;
+ }
+
+ cpustate->w.HL = (UINT16) ( cpustate->w.SP + n );
+ }
+ break;
+case 0xF9: /* LD SP,HL */
+
+ cpustate->w.SP = cpustate->w.HL;
+ break;
+case 0xFA: /* LD A,(n16) */
+
+ cpustate->b.A = mem_ReadByte (cpustate, mem_ReadWord (cpustate, cpustate->w.PC));
+ cpustate->w.PC += 2;
+ break;
+case 0xFB: /* EI */
+
+ cpustate->w.enable |= IME;
+ cpustate->w.ei_delay = 1;
+ break;
+case 0xFC: /* EH? */
+ break;
+case 0xFD: /* EH? */
+ break;
+case 0xFE: /* CP A,n8 */
+
+ x = mem_ReadByte (cpustate, cpustate->w.PC++);
+ CP_A_X (x)
+ break;
+case 0xFF: /* RST $38 */
+
+ cpustate->w.SP -= 2;
+ mem_WriteWord (cpustate, cpustate->w.SP, cpustate->w.PC);
+ cpustate->w.PC = 0x38;
+ break;
diff --git a/trunk/src/emu/cpu/m37710/m37710.c b/trunk/src/emu/cpu/m37710/m37710.c
new file mode 100644
index 00000000000..add2eabaf14
--- /dev/null
+++ b/trunk/src/emu/cpu/m37710/m37710.c
@@ -0,0 +1,1130 @@
+/*
+ Mitsubishi M37702/37710 CPU Emulator
+
+ The 7700 series is based on the WDC 65C816 core, with the following
+ notable changes:
+
+ - Second accumulator called "B" (on the 65816, "A" and "B" were the
+ two 8-bit halves of the 16-bit "C" accumulator).
+ - 6502 emulation mode and XCE instruction are not present.
+ - No NMI line. BRK and the watchdog interrupt are non-maskable, but there
+ is no provision for the traditional 6502/65816 NMI line.
+ - 3-bit interrupt priority levels like the 68000. Interrupts in general
+ are very different from the 65816.
+ - New single-instruction immediate-to-memory move instructions (LDM)
+ replaces STZ.
+ - CLM and SEM (clear and set "M" status bit) replace CLD/SED. Decimal
+ mode is still available via REP/SEP instructions.
+ - INC and DEC (0x1A and 0x3A) switch places for no particular reason.
+ - The microcode bug that caused MVN/NVP to take 2 extra cycles per byte
+ on the 65816 seems to have been fixed.
+ - The WDM (0x42) and BIT immediate (0x89) instructions are now prefixes.
+ 0x42 when used before an instruction involving the A accumulator makes
+ it use the B accumulator instead. 0x89 adds multiply and divide
+ opcodes, which the real 65816 doesn't have.
+ - The 65C816 preserves the upper 8 bits of A when in 8-bit M mode, but
+ not the upper 8 bits of X or Y when in 8-bit X. The 7700 preserves
+ the top bits of all registers in all modes (code in the C74 BIOS
+ starting at d881 requires this!).
+
+ The various 7700 series models differ primarily by their on board
+ peripherals. The 7750 and later models do include some additional
+ instructions, vs. the 770x/1x/2x, notably signed multiply/divide and
+ sign extension opcodes.
+
+ Peripherals common across the 7700 series include: programmable timers,
+ digital I/O ports, and analog to digital converters.
+
+ Reference: 7700 Family Software User's Manual (instruction set)
+ 7702/7703 Family User's Manual (on-board peripherals)
+ 7720 Family User's Manual
+
+ Emulator by R. Belmont.
+ Based on G65816 Emulator by Karl Stenrud.
+
+ History:
+ - v1.0 RB First version, basic operation OK, timers not complete
+ - v1.1 RB Data bus is 16-bit, dozens of bugfixes to IRQs, opcodes,
+ and opcode mapping. New opcodes added, internal timers added.
+ - v1.2 RB Fixed execution outside of bank 0, fixed LDM outside of bank 0,
+ fixed so top 8 bits of X & Y are preserved while in 8-bit mode,
+ added save state support.
+*/
+
+#include "emu.h"
+#include "debugger.h"
+#include "m37710.h"
+#include "m37710cm.h"
+
+#define M37710_DEBUG (0) // enables verbose logging for peripherals, etc.
+
+static void m37710_set_irq_line(m37710i_cpu_struct *cpustate, int line, int state);
+
+/* interrupt control mapping */
+
+extern const int m37710_irq_levels[M37710_LINE_MAX];
+const int m37710_irq_levels[M37710_LINE_MAX] =
+{
+ // maskable
+ 0x70, // ADC
+ 0x73, // UART 1 XMIT
+ 0x74, // UART 1 RECV
+ 0x71, // UART 0 XMIT
+ 0x72, // UART 0 RECV
+ 0x7c, // Timer B2
+ 0x7b, // Timer B1
+ 0x7a, // Timer B0
+ 0x79, // Timer A4
+ 0x78, // Timer A3
+ 0x77, // Timer A2
+ 0x76, // Timer A1
+ 0x75, // Timer A0
+ 0x7f, // IRQ 2
+ 0x7e, // IRQ 1
+ 0x7d, // IRQ 0
+
+ // non-maskable
+ 0, // watchdog
+ 0, // debugger control
+ 0, // BRK
+ 0, // divide by zero
+ 0, // reset
+};
+
+static const int m37710_irq_vectors[M37710_LINE_MAX] =
+{
+ // maskable C74
+ 0xffd6, // A-D converter c68b
+ 0xffd8, // UART1 transmit c68e
+ 0xffda, // UART1 receive c691
+ 0xffdc, // UART0 transmit c694
+ 0xffde, // UART0 receive c697
+ 0xffe0, // Timer B2 c69a
+ 0xffe2, // Timer B1 c69d
+ 0xffe4, // Timer B0 c6a0
+ 0xffe6, // Timer A4 c6a3
+ 0xffe8, // Timer A3 c6a6
+ 0xffea, // Timer A2 c6a9
+ 0xffec, // Timer A1 c6ac
+ 0xffee, // Timer A0 c6af
+ 0xfff0, // external INT2 pin c6b2
+ 0xfff2, // external INT1 pin c6b5
+ 0xfff4, // external INT0 pin c6b8
+
+ // non-maskable
+ 0xfff6, // watchdog timer
+ 0xfff8, // debugger control (not used in shipping ICs?)
+ 0xfffa, // BRK
+ 0xfffc, // divide by zero
+ 0xfffe, // RESET
+};
+
+// M37710 internal peripherals
+
+#if M37710_DEBUG
+static const char *const m37710_rnames[128] =
+{
+ "",
+ "",
+ "Port P0 reg",
+ "Port P1 reg",
+ "Port P0 dir reg",
+ "Port P1 dir reg",
+ "Port P2 reg",
+ "Port P3 reg",
+ "Port P2 dir reg",
+ "Port P3 dir reg",
+ "Port P4 reg",
+ "Port P5 reg",
+ "Port P4 dir reg",
+ "Port P5 dir reg",
+ "Port P6 reg",
+ "Port P7 reg",
+ "Port P6 dir reg", // 16
+ "Port P7 dir reg",
+ "Port P8 reg",
+ "",
+ "Port P8 dir reg",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "A/D control reg",
+ "A/D sweep pin select",
+ "A/D 0", // 32 (0x20)
+ "",
+ "A/D 1",
+ "",
+ "A/D 2",
+ "",
+ "A/D 3",
+ "",
+ "A/D 4",
+ "",
+ "A/D 5",
+ "",
+ "A/D 6",
+ "",
+ "A/D 7",
+ "",
+ "UART0 transmit/recv mode", // 48 (0x30)
+ "UART0 baud rate", // 0x31
+ "UART0 transmit buf L", // 0x32
+ "UART0 transmit buf H", // 0x33
+ "UART0 transmit/recv ctrl 0", // 0x34
+ "UART0 transmit/recv ctrl 1", // 0x35
+ "UART0 recv buf L", // 0x36
+ "UART0 recv buf H", // 0x37
+ "UART1 transmit/recv mode", // 0x38
+ "UART1 baud rate",
+ "UART1 transmit buf L",
+ "UART1 transmit buf H",
+ "UART1 transmit/recv ctrl 0",
+ "UART1 transmit/recv ctrl 1",
+ "UART1 recv buf L",
+ "UART1 recv buf H",
+ "Count start",
+ "",
+ "One-shot start",
+ "",
+ "Up-down register",
+ "",
+ "Timer A0 L",
+ "Timer A0 H",
+ "Timer A1 L",
+ "Timer A1 H",
+ "Timer A2 L",
+ "Timer A2 H",
+ "Timer A3 L",
+ "Timer A3 H",
+ "Timer A4 L",
+ "Timer A4 H",
+ "Timer B0 L",
+ "Timer B0 H",
+ "Timer B1 L",
+ "Timer B1 H",
+ "Timer B2 L",
+ "Timer B2 H",
+ "Timer A0 mode",
+ "Timer A1 mode",
+ "Timer A2 mode",
+ "Timer A3 mode",
+ "Timer A4 mode",
+ "Timer B0 mode",
+ "Timer B1 mode",
+ "Timer B2 mode",
+ "Processor mode",
+ "",
+ "Watchdog reset",
+ "Watchdog frequency",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "A/D IRQ ctrl",
+ "UART0 xmit IRQ ctrl",
+ "UART0 recv IRQ ctrl",
+ "UART1 xmit IRQ ctrl",
+ "UART1 recv IRQ ctrl",
+ "Timer A0 IRQ ctrl",
+ "Timer A1 IRQ ctrl",
+ "Timer A2 IRQ ctrl",
+ "Timer A3 IRQ ctrl",
+ "Timer A4 IRQ ctrl",
+ "Timer B0 IRQ ctrl",
+ "Timer B1 IRQ ctrl",
+ "Timer B2 IRQ ctrl",
+ "INT0 IRQ ctrl",
+ "INT1 IRQ ctrl",
+ "INT2 IRQ ctrl",
+};
+
+static const char *const m37710_tnames[8] =
+{
+ "A0", "A1", "A2", "A3", "A4", "B0", "B1", "B2"
+};
+#endif
+
+static TIMER_CALLBACK( m37710_timer_cb )
+{
+ m37710i_cpu_struct *cpustate = (m37710i_cpu_struct *)ptr;
+ int which = param;
+ int curirq = M37710_LINE_TIMERA0 - which;
+
+ cpustate->timers[which]->adjust(cpustate->reload[which], param);
+
+ cpustate->m37710_regs[m37710_irq_levels[curirq]] |= 0x04;
+ m37710_set_irq_line(cpustate, curirq, PULSE_LINE);
+ device_triggerint(cpustate->device);
+}
+
+static void m37710_external_tick(m37710i_cpu_struct *cpustate, int timer, int state)
+{
+ // we only care if the state is "on"
+ if (!state)
+ {
+ return;
+ }
+
+ // check if enabled
+ if (cpustate->m37710_regs[0x40] & (1<<timer))
+ {
+ if ((cpustate->m37710_regs[0x56+timer] & 0x3) == 1)
+ {
+ if (cpustate->m37710_regs[0x46+(timer*2)] == 0xff)
+ {
+ cpustate->m37710_regs[0x46+(timer*2)] = 0;
+ cpustate->m37710_regs[0x46+(timer*2)+1]++;
+ }
+ else
+ {
+ cpustate->m37710_regs[0x46+(timer*2)]++;
+ }
+ }
+ else
+ {
+ logerror("M37710: external tick for timer %d, not in event counter mode!\n", timer);
+ }
+ }
+}
+
+static void m37710_recalc_timer(m37710i_cpu_struct *cpustate, int timer)
+{
+ int tval;
+ static const int tcr[8] = { 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d };
+ attotime time;
+ static const int tscales[4] = { 2, 16, 64, 512 };
+
+ // check if enabled
+ if (cpustate->m37710_regs[0x40] & (1<<timer))
+ {
+ #if M37710_DEBUG
+ mame_printf_debug("Timer %d (%s) is enabled\n", timer, m37710_tnames[timer]);
+ #endif
+
+ // set the timer's value
+ tval = cpustate->m37710_regs[0x46+(timer*2)] | (cpustate->m37710_regs[0x47+(timer*2)]<<8);
+
+ // check timer's mode
+ // modes are slightly different between timer groups A and B
+ if (timer < 5)
+ {
+ switch (cpustate->m37710_regs[0x56+timer] & 0x3)
+ {
+ case 0: // timer mode
+ time = attotime::from_hz(cpustate->device->unscaled_clock()) * tscales[cpustate->m37710_regs[tcr[timer]]>>6];
+ time *= tval + 1;
+
+ #if M37710_DEBUG
+ mame_printf_debug("Timer %d in timer mode, %f Hz\n", timer, 1.0 / time.as_double());
+ #endif
+
+ cpustate->timers[timer]->adjust(time, timer);
+ cpustate->reload[timer] = time;
+ break;
+
+ case 1: // event counter mode
+ #if M37710_DEBUG
+ mame_printf_debug("Timer %d in event counter mode\n", timer);
+ #endif
+ break;
+
+ case 2: // one-shot pulse mode
+ #if M37710_DEBUG
+ mame_printf_debug("Timer %d in one-shot mode\n", timer);
+ #endif
+ break;
+
+ case 3: // PWM mode
+ #if M37710_DEBUG
+ mame_printf_debug("Timer %d in PWM mode\n", timer);
+ #endif
+ break;
+ }
+ }
+ else
+ {
+ switch (cpustate->m37710_regs[0x56+timer] & 0x3)
+ {
+ case 0: // timer mode
+ time = attotime::from_hz(cpustate->device->unscaled_clock()) * tscales[cpustate->m37710_regs[tcr[timer]]>>6];
+ time *= tval + 1;
+
+ #if M37710_DEBUG
+ mame_printf_debug("Timer %d in timer mode, %f Hz\n", timer, 1.0 / time.as_double());
+ #endif
+
+ cpustate->timers[timer]->adjust(time, timer);
+ cpustate->reload[timer] = time;
+ break;
+
+ case 1: // event counter mode
+ #if M37710_DEBUG
+ mame_printf_debug("Timer %d in event counter mode\n", timer);
+ #endif
+ break;
+
+ case 2: // pulse period/pulse width measurement mode
+ #if M37710_DEBUG
+ mame_printf_debug("Timer %d in pulse period/width measurement mode\n", timer);
+ #endif
+ break;
+
+ case 3:
+ #if M37710_DEBUG
+ mame_printf_debug("Timer %d in unknown mode!\n", timer);
+ #endif
+ break;
+ }
+ }
+ }
+}
+
+static UINT8 m37710_internal_r(m37710i_cpu_struct *cpustate, int offset)
+{
+ #if M37710_DEBUG
+ if (offset > 1)
+ logerror("m37710_internal_r from %02x: %s (PC=%x)\n", (int)offset, m37710_rnames[(int)offset], REG_PB<<16 | REG_PC);
+ #endif
+
+ switch (offset)
+ {
+ case 2: // p0
+ return cpustate->io->read_byte(M37710_PORT0);
+ case 3: // p1
+ return cpustate->io->read_byte(M37710_PORT1);
+ case 6: // p2
+ return cpustate->io->read_byte(M37710_PORT2);
+ case 7: // p3
+ return cpustate->io->read_byte(M37710_PORT3);
+ case 0xa: // p4
+ return cpustate->io->read_byte(M37710_PORT4);
+ case 0xb: // p5
+ return cpustate->io->read_byte(M37710_PORT5);
+ case 0xe: // p6
+ return cpustate->io->read_byte(M37710_PORT6);
+ case 0xf: // p7
+ return cpustate->io->read_byte(M37710_PORT7);
+ case 0x12: // p8
+ return cpustate->io->read_byte(M37710_PORT8);
+
+ case 0x20:
+ return cpustate->io->read_byte(M37710_ADC0_L);
+ case 0x21:
+ return cpustate->io->read_byte(M37710_ADC0_H);
+ case 0x22:
+ return cpustate->io->read_byte(M37710_ADC1_L);
+ case 0x23:
+ return cpustate->io->read_byte(M37710_ADC1_H);
+ case 0x24:
+ return cpustate->io->read_byte(M37710_ADC2_L);
+ case 0x25:
+ return cpustate->io->read_byte(M37710_ADC2_H);
+ case 0x26:
+ return cpustate->io->read_byte(M37710_ADC3_L);
+ case 0x27:
+ return cpustate->io->read_byte(M37710_ADC3_H);
+ case 0x28:
+ return cpustate->io->read_byte(M37710_ADC4_L);
+ case 0x29:
+ return cpustate->io->read_byte(M37710_ADC4_H);
+ case 0x2a:
+ return cpustate->io->read_byte(M37710_ADC5_L);
+ case 0x2b:
+ return cpustate->io->read_byte(M37710_ADC5_H);
+ case 0x2c:
+ return cpustate->io->read_byte(M37710_ADC6_L);
+ case 0x2d:
+ return cpustate->io->read_byte(M37710_ADC6_H);
+ case 0x2e:
+ return cpustate->io->read_byte(M37710_ADC7_L);
+ case 0x2f:
+ return cpustate->io->read_byte(M37710_ADC7_H);
+ case 0x35:
+ return 0xff; // UART control
+
+ case 0x70: // A/D IRQ control
+ return cpustate->m37710_regs[offset] | 8;
+ }
+
+ return cpustate->m37710_regs[offset];
+}
+
+static void m37710_internal_w(m37710i_cpu_struct *cpustate, int offset, UINT8 data)
+{
+ int i;
+
+ switch(offset)
+ {
+ case 2: // p0
+ cpustate->io->write_byte(M37710_PORT0, data);
+ return;
+ case 3: // p1
+ cpustate->io->write_byte(M37710_PORT1, data);
+ return;
+ case 6: // p2
+ cpustate->io->write_byte(M37710_PORT2, data);
+ return;
+ case 7: // p3
+ cpustate->io->write_byte(M37710_PORT3, data);
+ return;
+ case 0xa: // p4
+ cpustate->io->write_byte(M37710_PORT4, data);
+ return;
+ case 0xb: // p5
+ cpustate->io->write_byte(M37710_PORT5, data);
+ return;
+ case 0xe: // p6
+ cpustate->io->write_byte(M37710_PORT6, data);
+ return;
+ case 0xf: // p7
+ cpustate->io->write_byte(M37710_PORT7, data);
+ return;
+ case 0x12: // p8
+ cpustate->io->write_byte(M37710_PORT8, data);
+ return;
+
+ case 0x40: // count start
+ for (i = 0; i < 8; i++)
+ {
+ if ((data & (1<<i)) && !(cpustate->m37710_regs[offset] & (1<<i)))
+ {
+ cpustate->m37710_regs[offset] |= (1<<i);
+ m37710_recalc_timer(cpustate, i);
+ }
+ }
+
+ cpustate->m37710_regs[offset] = data;
+
+ return;
+
+ case 0x60: // watchdog reset
+ return;
+ }
+
+ cpustate->m37710_regs[offset] = data;
+
+ #if M37710_DEBUG
+ if (offset >= 0x1e && offset <= 0x40)
+ logerror("m37710_internal_w %x to %02x: %s = %x\n", data, (int)offset, m37710_rnames[(int)offset], cpustate->m37710_regs[offset]);
+ #endif
+}
+
+static READ16_HANDLER( m37710_internal_word_r )
+{
+ m37710i_cpu_struct *cpustate = get_safe_token(&space->device());
+
+ if (mem_mask == 0xffff)
+ {
+ return (m37710_internal_r(cpustate, offset*2) | m37710_internal_r(cpustate, (offset*2)+1)<<8);
+ }
+ else if (mem_mask == 0xff00)
+ {
+ return m37710_internal_r(cpustate, (offset*2)+1)<<8;
+ }
+ else if (mem_mask == 0x00ff)
+ {
+ return m37710_internal_r(cpustate, (offset*2));
+ }
+
+ return 0;
+}
+
+static WRITE16_HANDLER( m37710_internal_word_w )
+{
+ m37710i_cpu_struct *cpustate = get_safe_token(&space->device());
+
+ if (mem_mask == 0xffff)
+ {
+ m37710_internal_w(cpustate, (offset*2), data & 0xff);
+ m37710_internal_w(cpustate, (offset*2)+1, data>>8);
+ }
+ else if (mem_mask == 0xff00)
+ {
+ m37710_internal_w(cpustate, (offset*2)+1, data>>8);
+ }
+ else if (mem_mask == 0x00ff)
+ {
+ m37710_internal_w(cpustate, (offset*2), data & 0xff);
+ }
+}
+
+extern void (*const m37710i_opcodes_M0X0[])(m37710i_cpu_struct *cpustate);
+extern void (*const m37710i_opcodes42_M0X0[])(m37710i_cpu_struct *cpustate);
+extern void (*const m37710i_opcodes89_M0X0[])(m37710i_cpu_struct *cpustate);
+extern uint m37710i_get_reg_M0X0(m37710i_cpu_struct *cpustate, int regnum);
+extern void m37710i_set_reg_M0X0(m37710i_cpu_struct *cpustate, int regnum, uint val);
+extern void m37710i_set_line_M0X0(m37710i_cpu_struct *cpustate, int line, int state);
+extern int m37710i_execute_M0X0(m37710i_cpu_struct *cpustate, int cycles);
+
+extern void (*const m37710i_opcodes_M0X1[])(m37710i_cpu_struct *cpustate);
+extern void (*const m37710i_opcodes42_M0X1[])(m37710i_cpu_struct *cpustate);
+extern void (*const m37710i_opcodes89_M0X1[])(m37710i_cpu_struct *cpustate);
+extern uint m37710i_get_reg_M0X1(m37710i_cpu_struct *cpustate, int regnum);
+extern void m37710i_set_reg_M0X1(m37710i_cpu_struct *cpustate, int regnum, uint val);
+extern void m37710i_set_line_M0X1(m37710i_cpu_struct *cpustate, int line, int state);
+extern int m37710i_execute_M0X1(m37710i_cpu_struct *cpustate, int cycles);
+
+extern void (*const m37710i_opcodes_M1X0[])(m37710i_cpu_struct *cpustate);
+extern void (*const m37710i_opcodes42_M1X0[])(m37710i_cpu_struct *cpustate);
+extern void (*const m37710i_opcodes89_M1X0[])(m37710i_cpu_struct *cpustate);
+extern uint m37710i_get_reg_M1X0(m37710i_cpu_struct *cpustate, int regnum);
+extern void m37710i_set_reg_M1X0(m37710i_cpu_struct *cpustate, int regnum, uint val);
+extern void m37710i_set_line_M1X0(m37710i_cpu_struct *cpustate, int line, int state);
+extern int m37710i_execute_M1X0(m37710i_cpu_struct *cpustate, int cycles);
+
+extern void (*const m37710i_opcodes_M1X1[])(m37710i_cpu_struct *cpustate);
+extern void (*const m37710i_opcodes42_M1X1[])(m37710i_cpu_struct *cpustate);
+extern void (*const m37710i_opcodes89_M1X1[])(m37710i_cpu_struct *cpustate);
+extern uint m37710i_get_reg_M1X1(m37710i_cpu_struct *cpustate, int regnum);
+extern void m37710i_set_reg_M1X1(m37710i_cpu_struct *cpustate, int regnum, uint val);
+extern void m37710i_set_line_M1X1(m37710i_cpu_struct *cpustate, int line, int state);
+extern int m37710i_execute_M1X1(m37710i_cpu_struct *cpustate, int cycles);
+
+void (*const *const m37710i_opcodes[4])(m37710i_cpu_struct *cpustate) =
+{
+ m37710i_opcodes_M0X0,
+ m37710i_opcodes_M0X1,
+ m37710i_opcodes_M1X0,
+ m37710i_opcodes_M1X1,
+};
+
+void (*const *const m37710i_opcodes2[4])(m37710i_cpu_struct *cpustate) =
+{
+ m37710i_opcodes42_M0X0,
+ m37710i_opcodes42_M0X1,
+ m37710i_opcodes42_M1X0,
+ m37710i_opcodes42_M1X1,
+};
+
+void (*const *const m37710i_opcodes3[4])(m37710i_cpu_struct *cpustate) =
+{
+ m37710i_opcodes89_M0X0,
+ m37710i_opcodes89_M0X1,
+ m37710i_opcodes89_M1X0,
+ m37710i_opcodes89_M1X1,
+};
+
+uint (*const m37710i_get_reg[4])(m37710i_cpu_struct *cpustate, int regnum) =
+{
+ m37710i_get_reg_M0X0,
+ m37710i_get_reg_M0X1,
+ m37710i_get_reg_M1X0,
+ m37710i_get_reg_M1X1,
+};
+
+void (*const m37710i_set_reg[4])(m37710i_cpu_struct *cpustate, int regnum, uint val) =
+{
+ m37710i_set_reg_M0X0,
+ m37710i_set_reg_M0X1,
+ m37710i_set_reg_M1X0,
+ m37710i_set_reg_M1X1,
+};
+
+void (*const m37710i_set_line[4])(m37710i_cpu_struct *cpustate, int line, int state) =
+{
+ m37710i_set_line_M0X0,
+ m37710i_set_line_M0X1,
+ m37710i_set_line_M1X0,
+ m37710i_set_line_M1X1,
+};
+
+int (*const m37710i_execute[4])(m37710i_cpu_struct *cpustate, int cycles) =
+{
+ m37710i_execute_M0X0,
+ m37710i_execute_M0X1,
+ m37710i_execute_M1X0,
+ m37710i_execute_M1X1,
+};
+
+/* internal functions */
+
+INLINE void m37710i_push_8(m37710i_cpu_struct *cpustate, uint value)
+{
+ m37710_write_8(REG_S, value);
+ REG_S = MAKE_UINT_16(REG_S-1);
+}
+
+INLINE void m37710i_push_16(m37710i_cpu_struct *cpustate, uint value)
+{
+ m37710i_push_8(cpustate, value>>8);
+ m37710i_push_8(cpustate, value&0xff);
+}
+
+INLINE uint m37710i_get_reg_p(m37710i_cpu_struct *cpustate)
+{
+ return (FLAG_N&0x80) |
+ ((FLAG_V>>1)&0x40) |
+ FLAG_M |
+ FLAG_X |
+ FLAG_D |
+ FLAG_I |
+ ((!FLAG_Z)<<1) |
+ ((FLAG_C>>8)&1);
+}
+
+void m37710i_update_irqs(m37710i_cpu_struct *cpustate)
+{
+ int curirq, pending = LINE_IRQ;
+ int wantedIRQ, curpri;
+
+ if (FLAG_I)
+ {
+ return;
+ }
+
+ curpri = -1;
+ wantedIRQ = -1;
+
+ for (curirq = M37710_LINE_MAX - 1; curirq >= 0; curirq--)
+ {
+ if ((pending & (1 << curirq)))
+ {
+ // this IRQ is set
+ if (m37710_irq_levels[curirq])
+ {
+// logerror("line %d set, level %x curpri %x IPL %x\n", curirq, cpustate->m37710_regs[m37710_irq_levels[curirq]] & 7, curpri, cpustate->ipl);
+ // it's maskable, check if the level works
+ if ((cpustate->m37710_regs[m37710_irq_levels[curirq]] & 7) > curpri)
+ {
+ // also make sure it's acceptable for the current CPU level
+ if ((cpustate->m37710_regs[m37710_irq_levels[curirq]] & 7) > cpustate->ipl)
+ {
+ // mark us as the best candidate
+ wantedIRQ = curirq;
+ curpri = cpustate->m37710_regs[m37710_irq_levels[curirq]] & 7;
+ }
+ }
+ }
+ else
+ {
+ // non-maskable
+ wantedIRQ = curirq;
+ curirq = -1;
+ break; // no more processing, NMIs always win
+ }
+ }
+ }
+
+ if (wantedIRQ != -1)
+ {
+ if (INT_ACK) INT_ACK(cpustate->device, wantedIRQ);
+
+ // make sure we're running to service the interrupt
+ CPU_STOPPED &= ~STOP_LEVEL_WAI;
+
+ // indicate we're servicing it now
+ if (m37710_irq_levels[wantedIRQ])
+ {
+ cpustate->m37710_regs[m37710_irq_levels[wantedIRQ]] &= ~8;
+ }
+
+ // auto-clear if it's an internal line
+ if (wantedIRQ <= 12)
+ {
+ m37710_set_irq_line(cpustate, wantedIRQ, CLEAR_LINE);
+ }
+
+ // let's do it...
+ // push PB, then PC, then status
+ CLK(8);
+// mame_printf_debug("taking IRQ %d: PC = %06x, SP = %04x, IPL %d\n", wantedIRQ, REG_PB | REG_PC, REG_S, cpustate->ipl);
+ m37710i_push_8(cpustate, REG_PB>>16);
+ m37710i_push_16(cpustate, REG_PC);
+ m37710i_push_8(cpustate, cpustate->ipl);
+ m37710i_push_8(cpustate, m37710i_get_reg_p(cpustate));
+
+ // set I to 1, set IPL to the interrupt we're taking
+ FLAG_I = IFLAG_SET;
+ cpustate->ipl = curpri;
+ // then PB=0, PC=(vector)
+ REG_PB = 0;
+ REG_PC = m37710_read_8(m37710_irq_vectors[wantedIRQ]) |
+ m37710_read_8(m37710_irq_vectors[wantedIRQ]+1)<<8;
+// logerror("IRQ @ %06x\n", REG_PB | REG_PC);
+ m37710i_jumping(REG_PB | REG_PC);
+ }
+}
+
+/* external functions */
+
+static CPU_RESET( m37710 )
+{
+ m37710i_cpu_struct *cpustate = get_safe_token(device);
+
+ /* Start the CPU */
+ CPU_STOPPED = 0;
+
+ /* 37710 boots in full native mode */
+ REG_D = 0;
+ REG_PB = 0;
+ REG_DB = 0;
+ REG_S = (REG_S & 0xff) | 0x100;
+ REG_X &= 0xff;
+ REG_Y &= 0xff;
+ if(!FLAG_M)
+ {
+ REG_B = REG_A & 0xff00;
+ REG_A &= 0xff;
+ }
+ FLAG_M = MFLAG_CLEAR;
+ FLAG_X = XFLAG_CLEAR;
+
+ /* Clear D and set I */
+ FLAG_D = DFLAG_CLEAR;
+ FLAG_I = IFLAG_SET;
+
+ /* Clear all pending interrupts (should we really do this?) */
+ LINE_IRQ = 0;
+ IRQ_DELAY = 0;
+
+ /* Set the function tables to emulation mode */
+ m37710i_set_execution_mode(cpustate, EXECUTION_MODE_M0X0);
+
+ FLAG_Z = ZFLAG_CLEAR;
+ REG_S = 0x1ff;
+
+ /* Fetch the reset vector */
+ REG_PC = m37710_read_8(0xfffe) | (m37710_read_8(0xffff)<<8);
+ m37710i_jumping(REG_PB | REG_PC);
+}
+
+/* Exit and clean up */
+static CPU_EXIT( m37710 )
+{
+ /* nothing to do yet */
+}
+
+/* Execute some instructions */
+static CPU_EXECUTE( m37710 )
+{
+ m37710i_cpu_struct *m37710 = get_safe_token(device);
+
+ m37710i_update_irqs(m37710);
+
+ int clocks = m37710->ICount;
+ m37710->ICount = clocks - m37710->execute(m37710, m37710->ICount);
+}
+
+
+/* Set the Program Counter */
+static void m37710_set_pc(m37710i_cpu_struct *cpustate, unsigned val)
+{
+ REG_PC = MAKE_UINT_16(val);
+ m37710_jumping(REG_PB | REG_PC);
+}
+
+/* Get the current Stack Pointer */
+static unsigned m37710_get_sp(m37710i_cpu_struct *cpustate)
+{
+ return REG_S;
+}
+
+/* Set the Stack Pointer */
+static void m37710_set_sp(m37710i_cpu_struct *cpustate, unsigned val)
+{
+ REG_S = MAKE_UINT_16(val);
+}
+
+/* Get a register */
+static unsigned m37710_get_reg(m37710i_cpu_struct *cpustate, int regnum)
+{
+ return FTABLE_GET_REG(cpustate, regnum);
+}
+
+/* Set a register */
+static void m37710_set_reg(m37710i_cpu_struct *cpustate, int regnum, unsigned value)
+{
+ FTABLE_SET_REG(cpustate, regnum, value);
+}
+
+/* Set an interrupt line */
+static void m37710_set_irq_line(m37710i_cpu_struct *cpustate, int line, int state)
+{
+ FTABLE_SET_LINE(cpustate, line, state);
+}
+
+/* Set the callback that is called when servicing an interrupt */
+#ifdef UNUSED_FUNCTION
+void m37710_set_irq_callback(device_irq_callback callback)
+{
+ INT_ACK = callback;
+}
+#endif
+
+/* Disassemble an instruction */
+#include "m7700ds.h"
+
+static CPU_DISASSEMBLE( m37710 )
+{
+ m37710i_cpu_struct *cpustate = get_safe_token(device);
+
+ return m7700_disassemble(buffer, (pc&0xffff), pc>>16, oprom, FLAG_M, FLAG_X);
+}
+
+static void m37710_restore_state(m37710i_cpu_struct *cpustate)
+{
+ // restore proper function pointers
+ m37710i_set_execution_mode(cpustate, (FLAG_M>>4) | (FLAG_X>>4));
+
+ // make sure the memory system can keep up
+ m37710i_jumping(REG_PB | REG_PC);
+}
+
+static CPU_INIT( m37710 )
+{
+ m37710i_cpu_struct *cpustate = get_safe_token(device);
+ int i;
+
+ memset(cpustate, 0, sizeof(*cpustate));
+
+ INT_ACK = irqcallback;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->io = device->space(AS_IO);
+
+ cpustate->ICount = 0;
+
+ cpustate->source = 0;
+ cpustate->destination = 0;
+
+ for (i = 0; i < 8; i++)
+ cpustate->timers[i] = device->machine().scheduler().timer_alloc(FUNC(m37710_timer_cb), cpustate);
+
+ device->save_item(NAME(cpustate->a));
+ device->save_item(NAME(cpustate->b));
+ device->save_item(NAME(cpustate->ba));
+ device->save_item(NAME(cpustate->bb));
+ device->save_item(NAME(cpustate->x));
+ device->save_item(NAME(cpustate->y));
+ device->save_item(NAME(cpustate->s));
+ device->save_item(NAME(cpustate->pc));
+ device->save_item(NAME(cpustate->ppc));
+ device->save_item(NAME(cpustate->pb));
+ device->save_item(NAME(cpustate->db));
+ device->save_item(NAME(cpustate->d));
+ device->save_item(NAME(cpustate->flag_e));
+ device->save_item(NAME(cpustate->flag_m));
+ device->save_item(NAME(cpustate->flag_x));
+ device->save_item(NAME(cpustate->flag_n));
+ device->save_item(NAME(cpustate->flag_v));
+ device->save_item(NAME(cpustate->flag_d));
+ device->save_item(NAME(cpustate->flag_i));
+ device->save_item(NAME(cpustate->flag_z));
+ device->save_item(NAME(cpustate->flag_c));
+ device->save_item(NAME(cpustate->line_irq));
+ device->save_item(NAME(cpustate->ipl));
+ device->save_item(NAME(cpustate->ir));
+ device->save_item(NAME(cpustate->im));
+ device->save_item(NAME(cpustate->im2));
+ device->save_item(NAME(cpustate->im3));
+ device->save_item(NAME(cpustate->im4));
+ device->save_item(NAME(cpustate->irq_delay));
+ device->save_item(NAME(cpustate->irq_level));
+ device->save_item(NAME(cpustate->stopped));
+ device->save_item(NAME(cpustate->m37710_regs));
+ device->save_item(NAME(cpustate->reload[0]));
+ device->save_item(NAME(cpustate->reload[1]));
+ device->save_item(NAME(cpustate->reload[2]));
+ device->save_item(NAME(cpustate->reload[3]));
+ device->save_item(NAME(cpustate->reload[4]));
+ device->save_item(NAME(cpustate->reload[5]));
+ device->save_item(NAME(cpustate->reload[6]));
+ device->save_item(NAME(cpustate->reload[7]));
+
+ device->machine().save().register_postload(save_prepost_delegate(FUNC(m37710_restore_state), cpustate));
+}
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( m37710 )
+{
+ m37710i_cpu_struct *cpustate = get_safe_token(device);
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + M37710_LINE_ADC: m37710_set_irq_line(cpustate, M37710_LINE_ADC, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + M37710_LINE_IRQ0: m37710_set_irq_line(cpustate, M37710_LINE_IRQ0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + M37710_LINE_IRQ1: m37710_set_irq_line(cpustate, M37710_LINE_IRQ1, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + M37710_LINE_IRQ2: m37710_set_irq_line(cpustate, M37710_LINE_IRQ2, info->i); break;
+
+ case CPUINFO_INT_INPUT_STATE + M37710_LINE_TIMERA0TICK: m37710_external_tick(cpustate, state - CPUINFO_INT_INPUT_STATE - M37710_LINE_TIMERA0TICK, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + M37710_LINE_TIMERA1TICK: m37710_external_tick(cpustate, state - CPUINFO_INT_INPUT_STATE - M37710_LINE_TIMERA0TICK, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + M37710_LINE_TIMERA2TICK: m37710_external_tick(cpustate, state - CPUINFO_INT_INPUT_STATE - M37710_LINE_TIMERA0TICK, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + M37710_LINE_TIMERA3TICK: m37710_external_tick(cpustate, state - CPUINFO_INT_INPUT_STATE - M37710_LINE_TIMERA0TICK, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + M37710_LINE_TIMERA4TICK: m37710_external_tick(cpustate, state - CPUINFO_INT_INPUT_STATE - M37710_LINE_TIMERA0TICK, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + M37710_LINE_TIMERB0TICK: m37710_external_tick(cpustate, state - CPUINFO_INT_INPUT_STATE - M37710_LINE_TIMERA0TICK, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + M37710_LINE_TIMERB1TICK: m37710_external_tick(cpustate, state - CPUINFO_INT_INPUT_STATE - M37710_LINE_TIMERA0TICK, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + M37710_LINE_TIMERB2TICK: m37710_external_tick(cpustate, state - CPUINFO_INT_INPUT_STATE - M37710_LINE_TIMERA0TICK, info->i); break;
+
+ case CPUINFO_INT_PC: REG_PB = info->i & 0xff0000; m37710_set_pc(cpustate, info->i & 0xffff); break;
+ case CPUINFO_INT_SP: m37710_set_sp(cpustate, info->i); break;
+
+ case CPUINFO_INT_REGISTER + M37710_PC: m37710_set_reg(cpustate, M37710_PC, info->i); break;
+ case CPUINFO_INT_REGISTER + M37710_S: m37710_set_reg(cpustate, M37710_S, info->i); break;
+ case CPUINFO_INT_REGISTER + M37710_P: m37710_set_reg(cpustate, M37710_P, info->i&0xff); cpustate->ipl = (info->i>>8)&0xff; break;
+ case CPUINFO_INT_REGISTER + M37710_A: m37710_set_reg(cpustate, M37710_A, info->i); break;
+ case CPUINFO_INT_REGISTER + M37710_X: m37710_set_reg(cpustate, M37710_X, info->i); break;
+ case CPUINFO_INT_REGISTER + M37710_Y: m37710_set_reg(cpustate, M37710_Y, info->i); break;
+ case CPUINFO_INT_REGISTER + M37710_PB: m37710_set_reg(cpustate, M37710_PB, info->i); break;
+ case CPUINFO_INT_REGISTER + M37710_DB: m37710_set_reg(cpustate, M37710_DB, info->i); break;
+ case CPUINFO_INT_REGISTER + M37710_D: m37710_set_reg(cpustate, M37710_D, info->i); break;
+ case CPUINFO_INT_REGISTER + M37710_E: m37710_set_reg(cpustate, M37710_E, info->i); break;
+ case CPUINFO_INT_REGISTER + M37710_NMI_STATE: m37710_set_reg(cpustate, M37710_NMI_STATE, info->i); break;
+ case CPUINFO_INT_REGISTER + M37710_IRQ_STATE: m37710_set_reg(cpustate, M37710_IRQ_STATE, info->i); break;
+ }
+}
+
+// On-board RAM and peripherals
+static ADDRESS_MAP_START( m37710_internal_map, AS_PROGRAM, 16 )
+ AM_RANGE(0x000000, 0x00007f) AM_READWRITE(m37710_internal_word_r, m37710_internal_word_w)
+ AM_RANGE(0x000080, 0x00027f) AM_RAM
+ADDRESS_MAP_END
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+CPU_GET_INFO( m37710 )
+{
+ m37710i_cpu_struct *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(m37710i_cpu_struct); break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 6; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 20; /* rough guess */ break;
+ case CPUINFO_INT_INPUT_LINES: info->i = M37710_LINE_MAX; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 24; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_INPUT_STATE + M37710_LINE_IRQ0: info->i = 0; break;
+ case CPUINFO_INT_INPUT_STATE + M37710_LINE_IRQ1: info->i = 0; break;
+ case CPUINFO_INT_INPUT_STATE + M37710_LINE_IRQ2: info->i = 0; break;
+ case CPUINFO_INT_INPUT_STATE + M37710_LINE_RESET: info->i = 0; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = REG_PPC; break;
+ case CPUINFO_INT_PC: info->i = (REG_PB | REG_PC); break;
+ case CPUINFO_INT_SP: info->i = m37710_get_sp(cpustate); break;
+
+ case CPUINFO_INT_REGISTER + M37710_PC: info->i = m37710_get_reg(cpustate, M37710_PC); break;
+ case CPUINFO_INT_REGISTER + M37710_S: info->i = m37710_get_reg(cpustate, M37710_S); break;
+ case CPUINFO_INT_REGISTER + M37710_P: info->i = m37710_get_reg(cpustate, M37710_P) | (cpustate->ipl<<8); break;
+ case CPUINFO_INT_REGISTER + M37710_A: info->i = m37710_get_reg(cpustate, M37710_A); break;
+ case CPUINFO_INT_REGISTER + M37710_B: info->i = m37710_get_reg(cpustate, M37710_B); break;
+ case CPUINFO_INT_REGISTER + M37710_X: info->i = m37710_get_reg(cpustate, M37710_X); break;
+ case CPUINFO_INT_REGISTER + M37710_Y: info->i = m37710_get_reg(cpustate, M37710_Y); break;
+ case CPUINFO_INT_REGISTER + M37710_PB: info->i = m37710_get_reg(cpustate, M37710_PB); break;
+ case CPUINFO_INT_REGISTER + M37710_DB: info->i = m37710_get_reg(cpustate, M37710_DB); break;
+ case CPUINFO_INT_REGISTER + M37710_D: info->i = m37710_get_reg(cpustate, M37710_D); break;
+ case CPUINFO_INT_REGISTER + M37710_E: info->i = m37710_get_reg(cpustate, M37710_E); break;
+ case CPUINFO_INT_REGISTER + M37710_NMI_STATE: info->i = m37710_get_reg(cpustate, M37710_NMI_STATE); break;
+ case CPUINFO_INT_REGISTER + M37710_IRQ_STATE: info->i = m37710_get_reg(cpustate, M37710_IRQ_STATE); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(m37710); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(m37710); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(m37710); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(m37710); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(m37710); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(m37710); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->ICount; break;
+
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map16 = ADDRESS_MAP_NAME(m37710_internal_map); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map16 = NULL; break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_IO: info->internal_map8 = NULL; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "M37710"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "M7700"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.2"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright R. Belmont, based on G65816 by Karl Stenerud"); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c%c%c%c%c%c%c",
+ cpustate->flag_n & NFLAG_SET ? 'N':'.',
+ cpustate->flag_v & VFLAG_SET ? 'V':'.',
+ cpustate->flag_m & MFLAG_SET ? 'M':'.',
+ cpustate->flag_x & XFLAG_SET ? 'X':'.',
+ cpustate->flag_d & DFLAG_SET ? 'D':'.',
+ cpustate->flag_i & IFLAG_SET ? 'I':'.',
+ cpustate->flag_z == 0 ? 'Z':'.',
+ cpustate->flag_c & CFLAG_SET ? 'C':'.');
+ break;
+
+ case CPUINFO_STR_REGISTER + M37710_PC: sprintf(info->s, "PC:%04X", cpustate->pc); break;
+ case CPUINFO_STR_REGISTER + M37710_PB: sprintf(info->s, "PB:%02X", cpustate->pb>>16); break;
+ case CPUINFO_STR_REGISTER + M37710_DB: sprintf(info->s, "DB:%02X", cpustate->db>>16); break;
+ case CPUINFO_STR_REGISTER + M37710_D: sprintf(info->s, "D:%04X", cpustate->d); break;
+ case CPUINFO_STR_REGISTER + M37710_S: sprintf(info->s, "S:%04X", cpustate->s); break;
+ case CPUINFO_STR_REGISTER + M37710_P: sprintf(info->s, "P:%04X",
+ (cpustate->flag_n&0x80) |
+ ((cpustate->flag_v>>1)&0x40) |
+ cpustate->flag_m |
+ cpustate->flag_x |
+ cpustate->flag_d |
+ cpustate->flag_i |
+ ((!cpustate->flag_z)<<1) |
+ ((cpustate->flag_c>>8)&1) | (cpustate->ipl<<8)); break;
+ case CPUINFO_STR_REGISTER + M37710_E: sprintf(info->s, "E:%d", cpustate->flag_e); break;
+ case CPUINFO_STR_REGISTER + M37710_A: sprintf(info->s, "A:%04X", cpustate->a | cpustate->b); break;
+ case CPUINFO_STR_REGISTER + M37710_B: sprintf(info->s, "B:%04X", cpustate->ba | cpustate->bb); break;
+ case CPUINFO_STR_REGISTER + M37710_X: sprintf(info->s, "X:%04X", cpustate->x); break;
+ case CPUINFO_STR_REGISTER + M37710_Y: sprintf(info->s, "Y:%04X", cpustate->y); break;
+ case CPUINFO_STR_REGISTER + M37710_IRQ_STATE: sprintf(info->s, "IRQ:%X", cpustate->line_irq); break;
+ }
+}
+
+// 37702 is identical except with an internal ROM, so just change the name
+CPU_GET_INFO( m37702 )
+{
+ if (state == DEVINFO_STR_NAME)
+ {
+ strcpy(info->s, "M37702");
+ return;
+ }
+
+ CPU_GET_INFO_CALL(m37710);
+}
+
+DEFINE_LEGACY_CPU_DEVICE(M37710, m37710);
+DEFINE_LEGACY_CPU_DEVICE(M37702, m37702);
+
+/* ======================================================================== */
+/* ============================== END OF FILE ============================= */
+/* ======================================================================== */
diff --git a/trunk/src/emu/cpu/m37710/m37710.h b/trunk/src/emu/cpu/m37710/m37710.h
new file mode 100644
index 00000000000..a9a159d77cb
--- /dev/null
+++ b/trunk/src/emu/cpu/m37710/m37710.h
@@ -0,0 +1,95 @@
+#pragma once
+
+#ifndef __M37710_H__
+#define __M37710_H__
+
+/* ======================================================================== */
+/* =============================== COPYRIGHT ============================== */
+/* ======================================================================== */
+/*
+
+M37710 CPU Emulator v0.1
+
+*/
+
+/* ======================================================================== */
+/* =============================== DEFINES ================================ */
+/* ======================================================================== */
+/*
+ Input lines - used with cpunum_set_input_line() and the like.
+ WARNING: these are in the same order as the vector table for simplicity.
+ Do not alter this order!
+*/
+
+enum
+{
+ // these interrupts are maskable
+ M37710_LINE_ADC = 0,
+ M37710_LINE_UART1XMIT,
+ M37710_LINE_UART1RECV,
+ M37710_LINE_UART0XMIT,
+ M37710_LINE_UART0RECV,
+ M37710_LINE_TIMERB2,
+ M37710_LINE_TIMERB1,
+ M37710_LINE_TIMERB0,
+ M37710_LINE_TIMERA4,
+ M37710_LINE_TIMERA3,
+ M37710_LINE_TIMERA2,
+ M37710_LINE_TIMERA1,
+ M37710_LINE_TIMERA0,
+ M37710_LINE_IRQ2,
+ M37710_LINE_IRQ1,
+ M37710_LINE_IRQ0,
+ // these interrupts are non-maskable
+ M37710_LINE_WATCHDOG,
+ M37710_LINE_DEBUG,
+ M37710_LINE_BRK,
+ M37710_LINE_ZERODIV,
+ M37710_LINE_RESET,
+
+ // these are not interrupts, they're signals external hardware can send
+ M37710_LINE_TIMERA0TICK,
+ M37710_LINE_TIMERA1TICK,
+ M37710_LINE_TIMERA2TICK,
+ M37710_LINE_TIMERA3TICK,
+ M37710_LINE_TIMERA4TICK,
+ M37710_LINE_TIMERB0TICK,
+ M37710_LINE_TIMERB1TICK,
+ M37710_LINE_TIMERB2TICK,
+
+ M37710_LINE_MAX
+};
+
+/* Registers - used by m37710_set_reg() and m37710_get_reg() */
+enum
+{
+ M37710_PC=1, M37710_S, M37710_P, M37710_A, M37710_B, M37710_X, M37710_Y,
+ M37710_PB, M37710_DB, M37710_D, M37710_E,
+ M37710_NMI_STATE, M37710_IRQ_STATE
+};
+
+
+/* I/O ports */
+enum
+{
+ M37710_PORT0 = 0,
+ M37710_PORT1, M37710_PORT2, M37710_PORT3, M37710_PORT4,
+ M37710_PORT5, M37710_PORT6, M37710_PORT7, M37710_PORT8,
+
+ M37710_ADC0_L = 0x10, M37710_ADC0_H,
+ M37710_ADC1_L, M37710_ADC1_H, M37710_ADC2_L, M37710_ADC2_H, M37710_ADC3_L, M37710_ADC3_H,
+ M37710_ADC4_L, M37710_ADC4_H, M37710_ADC5_L, M37710_ADC5_H, M37710_ADC6_L, M37710_ADC6_H,
+ M37710_ADC7_L, M37710_ADC7_H,
+
+ M37710_SER0_REC = 0x20,
+ M37710_SER0_XMIT, M37710_SER1_REC, M37710_SER1_XMIT
+};
+
+DECLARE_LEGACY_CPU_DEVICE(M37710, m37710);
+DECLARE_LEGACY_CPU_DEVICE(M37702, m37702);
+
+/* ======================================================================== */
+/* ============================== END OF FILE ============================= */
+/* ======================================================================== */
+
+#endif /* __M37710_H__ */
diff --git a/trunk/src/emu/cpu/m37710/m37710cm.h b/trunk/src/emu/cpu/m37710/m37710cm.h
new file mode 100644
index 00000000000..7c2f18dc01e
--- /dev/null
+++ b/trunk/src/emu/cpu/m37710/m37710cm.h
@@ -0,0 +1,336 @@
+#pragma once
+
+#ifndef __M37710CM_H__
+#define __M37710CM_H__
+
+#define m37710i_branching(A)
+#define m37710i_jumping(A)
+
+
+/* ======================================================================== */
+/* ================================ INCLUDES ============================== */
+/* ======================================================================== */
+
+#include <limits.h>
+#include "m37710.h"
+
+
+/* ======================================================================== */
+/* ================================= MAME ================================= */
+/* ======================================================================== */
+
+#undef M37710_CALL_DEBUGGER
+
+#define M37710_CALL_DEBUGGER(x) debugger_instruction_hook(cpustate->device, x)
+#define m37710_read_8(addr) cpustate->program->read_byte(addr)
+#define m37710_write_8(addr,data) cpustate->program->write_byte(addr,data)
+#define m37710_read_8_immediate(A) cpustate->program->read_byte(A)
+#define m37710_read_16(addr) cpustate->program->read_word(addr)
+#define m37710_write_16(addr,data) cpustate->program->write_word(addr,data)
+#define m37710_jumping(A)
+#define m37710_branching(A)
+
+
+/* ======================================================================== */
+/* ================================ GENERAL =============================== */
+/* ======================================================================== */
+
+/* This should be set to the default size of your processor (min 16 bit) */
+#undef uint
+#define uint unsigned int
+
+#undef uint8
+#define uint8 unsigned char
+
+#undef int8
+
+/* Allow for architectures that don't have 8-bit sizes */
+#if UCHAR_MAX == 0xff
+#define int8 char
+#define MAKE_INT_8(A) (int8)((A)&0xff)
+#else
+#define int8 int
+INLINE int MAKE_INT_8(int A) {return (A & 0x80) ? A | ~0xff : A & 0xff;}
+#endif /* UCHAR_MAX == 0xff */
+
+#define MAKE_UINT_8(A) ((A)&0xff)
+#define MAKE_UINT_16(A) ((A)&0xffff)
+#define MAKE_UINT_24(A) ((A)&0xffffff)
+
+/* Bits */
+#define BIT_0 0x01
+#define BIT_1 0x02
+#define BIT_2 0x04
+#define BIT_3 0x08
+#define BIT_4 0x10
+#define BIT_5 0x20
+#define BIT_6 0x40
+#define BIT_7 0x80
+
+/* ======================================================================== */
+/* ================================== CPU ================================= */
+/* ======================================================================== */
+
+/* CPU Structure */
+typedef struct _m37710i_cpu_struct m37710i_cpu_struct;
+struct _m37710i_cpu_struct
+{
+ uint a; /* Accumulator */
+ uint b; /* holds high byte of accumulator */
+ uint ba; /* Secondary Accumulator */
+ uint bb; /* holds high byte of secondary accumulator */
+ uint x; /* Index Register X */
+ uint y; /* Index Register Y */
+ uint s; /* Stack Pointer */
+ uint pc; /* Program Counter */
+ uint ppc; /* Previous Program Counter */
+ uint pb; /* Program Bank (shifted left 16) */
+ uint db; /* Data Bank (shifted left 16) */
+ uint d; /* Direct Register */
+ uint flag_e; /* Emulation Mode Flag */
+ uint flag_m; /* Memory/Accumulator Select Flag */
+ uint flag_x; /* Index Select Flag */
+ uint flag_n; /* Negative Flag */
+ uint flag_v; /* Overflow Flag */
+ uint flag_d; /* Decimal Mode Flag */
+ uint flag_i; /* Interrupt Mask Flag */
+ uint flag_z; /* Zero Flag (inverted) */
+ uint flag_c; /* Carry Flag */
+ uint line_irq; /* Bitmask of pending IRQs */
+ uint ipl; /* Interrupt priority level (top of PSW) */
+ uint ir; /* Instruction Register */
+ uint im; /* Immediate load value */
+ uint im2; /* Immediate load target */
+ uint im3; /* Immediate load target */
+ uint im4; /* Immediate load target */
+ uint irq_delay; /* delay 1 instruction before checking irq */
+ uint irq_level; /* irq level */
+ int ICount; /* cycle count */
+ uint source; /* temp register */
+ uint destination; /* temp register */
+ device_irq_callback int_ack;
+ legacy_cpu_device *device;
+ address_space *program;
+ address_space *io;
+ uint stopped; /* Sets how the CPU is stopped */
+ void (*const *opcodes)(m37710i_cpu_struct *cpustate); /* opcodes with no prefix */
+ void (*const *opcodes42)(m37710i_cpu_struct *cpustate); /* opcodes with 0x42 prefix */
+ void (*const *opcodes89)(m37710i_cpu_struct *cpustate); /* opcodes with 0x89 prefix */
+ uint (*get_reg)(m37710i_cpu_struct *cpustate, int regnum);
+ void (*set_reg)(m37710i_cpu_struct *cpustate, int regnum, uint val);
+ void (*set_line)(m37710i_cpu_struct *cpustate, int line, int state);
+ int (*execute)(m37710i_cpu_struct *cpustate, int cycles);
+
+ // on-board peripheral stuff
+ UINT8 m37710_regs[128];
+ attotime reload[8];
+ emu_timer *timers[8];
+};
+
+INLINE m37710i_cpu_struct *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == M37710 ||
+ device->type() == M37702);
+ return (m37710i_cpu_struct *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+extern uint m37710i_adc_tbl[];
+extern uint m37710i_sbc_tbl[];
+
+extern void (*const *const m37710i_opcodes[])(m37710i_cpu_struct *cpustate);
+extern void (*const *const m37710i_opcodes2[])(m37710i_cpu_struct *cpustate);
+extern void (*const *const m37710i_opcodes3[])(m37710i_cpu_struct *cpustate);
+extern uint (*const m37710i_get_reg[])(m37710i_cpu_struct *cpustate,int regnum);
+extern void (*const m37710i_set_reg[])(m37710i_cpu_struct *cpustate,int regnum, uint val);
+extern void (*const m37710i_set_line[])(m37710i_cpu_struct *cpustate,int line, int state);
+extern int (*const m37710i_execute[])(m37710i_cpu_struct *cpustate, int cycles);
+
+#define REG_A cpustate->a /* Accumulator */
+#define REG_B cpustate->b /* Accumulator hi byte */
+#define REG_BA cpustate->ba /* Secondary Accumulator */
+#define REG_BB cpustate->bb /* Secondary Accumulator hi byte */
+#define REG_X cpustate->x /* Index X Register */
+#define REG_Y cpustate->y /* Index Y Register */
+#define REG_S cpustate->s /* Stack Pointer */
+#define REG_PC cpustate->pc /* Program Counter */
+#define REG_PPC cpustate->ppc /* Previous Program Counter */
+#define REG_PB cpustate->pb /* Program Bank */
+#define REG_DB cpustate->db /* Data Bank */
+#define REG_D cpustate->d /* Direct Register */
+#define FLAG_M cpustate->flag_m /* Memory/Accumulator Select Flag */
+#define FLAG_X cpustate->flag_x /* Index Select Flag */
+#define FLAG_N cpustate->flag_n /* Negative Flag */
+#define FLAG_V cpustate->flag_v /* Overflow Flag */
+#define FLAG_D cpustate->flag_d /* Decimal Mode Flag */
+#define FLAG_I cpustate->flag_i /* Interrupt Mask Flag */
+#define FLAG_Z cpustate->flag_z /* Zero Flag (inverted) */
+#define FLAG_C cpustate->flag_c /* Carry Flag */
+#define LINE_IRQ cpustate->line_irq /* Status of the IRQ line */
+#define REG_IR cpustate->ir /* Instruction Register */
+#define REG_IM cpustate->im /* Immediate load value */
+#define REG_IM2 cpustate->im2 /* Immediate load target */
+#define REG_IM3 cpustate->im3 /* Immediate load target */
+#define REG_IM4 cpustate->im4 /* Immediate load target */
+#define INT_ACK cpustate->int_ack /* Interrupt Acknowledge function pointer */
+#define CLOCKS cpustate->ICount /* Clock cycles remaining */
+#define IRQ_DELAY cpustate->irq_delay /* Delay 1 instruction before checking IRQ */
+#define CPU_STOPPED cpustate->stopped /* Stopped status of the CPU */
+
+#define FTABLE_GET_REG cpustate->get_reg
+#define FTABLE_SET_REG cpustate->set_reg
+#define FTABLE_SET_LINE cpustate->set_line
+
+#define SRC cpustate->source /* Source Operand */
+#define DST cpustate->destination /* Destination Operand */
+
+#define STOP_LEVEL_WAI 1
+#define STOP_LEVEL_STOP 2
+
+#define EXECUTION_MODE_M0X0 0
+#define EXECUTION_MODE_M0X1 1
+#define EXECUTION_MODE_M1X0 2
+#define EXECUTION_MODE_M1X1 3
+
+INLINE void m37710i_set_execution_mode(m37710i_cpu_struct *cpustate, uint mode)
+{
+ cpustate->opcodes = m37710i_opcodes[mode];
+ cpustate->opcodes42 = m37710i_opcodes2[mode];
+ cpustate->opcodes89 = m37710i_opcodes3[mode];
+ FTABLE_GET_REG = m37710i_get_reg[mode];
+ FTABLE_SET_REG = m37710i_set_reg[mode];
+ FTABLE_SET_LINE = m37710i_set_line[mode];
+ cpustate->execute = m37710i_execute[mode];
+}
+
+/* ======================================================================== */
+/* ================================= CLOCK ================================ */
+/* ======================================================================== */
+
+#define CLK_OP 1
+#define CLK_R8 1
+#define CLK_R16 2
+#define CLK_R24 3
+#define CLK_W8 1
+#define CLK_W16 2
+#define CLK_W24 3
+#define CLK_RMW8 3
+#define CLK_RMW16 5
+
+#define CLK_IMPLIED 1
+#define CLK_IMPLIED 1
+#define CLK_RELATIVE_8 1
+#define CLK_RELATIVE_16 2
+#define CLK_IMM 0
+#define CLK_AI 4
+#define CLK_AXI 4
+#define CLK_A 2
+#define CLK_AL 3
+#define CLK_ALX 3
+#define CLK_AX 2
+#define CLK_AY 2
+#define CLK_D 1
+#define CLK_DI 3
+#define CLK_DIY 3
+#define CLK_DLI 4
+#define CLK_DLIY 4
+#define CLK_DX 2
+#define CLK_DXI 4
+#define CLK_DY 2
+#define CLK_S 2
+#define CLK_SIY 5
+
+/* AX and AY addressing modes take 1 extra cycle when writing */
+#define CLK_W_IMM 0
+#define CLK_W_AI 4
+#define CLK_W_AXI 4
+#define CLK_W_A 2
+#define CLK_W_AL 3
+#define CLK_W_ALX 3
+#define CLK_W_AX 3
+#define CLK_W_AY 3
+#define CLK_W_D 1
+#define CLK_W_DI 3
+#define CLK_W_DIY 3
+#define CLK_W_DLI 4
+#define CLK_W_DLIY 4
+#define CLK_W_DX 2
+#define CLK_W_DXI 4
+#define CLK_W_DY 2
+#define CLK_W_S 2
+#define CLK_W_SIY 5
+
+#define CLK(A) CLOCKS -= (A)
+#define USE_ALL_CLKS() CLOCKS = 0
+
+
+/* ======================================================================== */
+/* ============================ STATUS REGISTER =========================== */
+/* ======================================================================== */
+
+/* Flag positions in Processor Status Register */
+/* common */
+#define FLAGPOS_N BIT_7 /* Negative */
+#define FLAGPOS_V BIT_6 /* Overflow */
+#define FLAGPOS_D BIT_3 /* Decimal Mode */
+#define FLAGPOS_I BIT_2 /* Interrupt Mask */
+#define FLAGPOS_Z BIT_1 /* Zero */
+#define FLAGPOS_C BIT_0 /* Carry */
+/* emulation */
+#define FLAGPOS_R BIT_5 /* Reserved */
+#define FLAGPOS_B BIT_4 /* BRK Instruction */
+/* native */
+#define FLAGPOS_M BIT_5 /* Mem/Reg Select */
+#define FLAGPOS_X BIT_4 /* Index Select */
+
+#define EFLAG_SET 1
+#define EFLAG_CLEAR 0
+#define MFLAG_SET FLAGPOS_M
+#define MFLAG_CLEAR 0
+#define XFLAG_SET FLAGPOS_X
+#define XFLAG_CLEAR 0
+#define NFLAG_SET 0x80
+#define NFLAG_CLEAR 0
+#define VFLAG_SET 0x80
+#define VFLAG_CLEAR 0
+#define DFLAG_SET FLAGPOS_D
+#define DFLAG_CLEAR 0
+#define IFLAG_SET FLAGPOS_I
+#define IFLAG_CLEAR 0
+#define BFLAG_SET FLAGPOS_B
+#define BFLAG_CLEAR 0
+#define ZFLAG_SET 0
+#define ZFLAG_CLEAR 1
+#define CFLAG_SET 0x100
+#define CFLAG_CLEAR 0
+
+/* Codition code tests */
+#define COND_CC() (!(FLAG_C&0x100)) /* Carry Clear */
+#define COND_CS() (FLAG_C&0x100) /* Carry Set */
+#define COND_EQ() (!FLAG_Z) /* Equal */
+#define COND_NE() FLAG_Z /* Not Equal */
+#define COND_MI() (FLAG_N&0x80) /* Minus */
+#define COND_PL() (!(FLAG_N&0x80)) /* Plus */
+#define COND_VC() (!(FLAG_V&0x80)) /* Overflow Clear */
+#define COND_VS() (FLAG_V&0x80) /* Overflow Set */
+
+/* Set Overflow flag in math operations */
+#define VFLAG_ADD_8(S, D, R) ((S^R) & (D^R))
+#define VFLAG_ADD_16(S, D, R) (((S^R) & (D^R))>>8)
+#define VFLAG_SUB_8(S, D, R) ((S^D) & (R^D))
+#define VFLAG_SUB_16(S, D, R) (((S^D) & (R^D))>>8)
+
+#define CFLAG_8(A) (A)
+#define CFLAG_16(A) ((A)>>8)
+#define NFLAG_8(A) (A)
+#define NFLAG_16(A) ((A)>>8)
+
+#define CFLAG_AS_1() ((FLAG_C>>8)&1)
+
+/* update IRQ state (internal use only) */
+void m37710i_update_irqs(m37710i_cpu_struct *cpustate);
+
+/* ======================================================================== */
+/* ================================== CPU ================================= */
+/* ======================================================================== */
+#endif /* __M37710CM_H__ */
diff --git a/trunk/src/emu/cpu/m37710/m37710o0.c b/trunk/src/emu/cpu/m37710/m37710o0.c
new file mode 100644
index 00000000000..7ba636a03c0
--- /dev/null
+++ b/trunk/src/emu/cpu/m37710/m37710o0.c
@@ -0,0 +1,5 @@
+#include "emu.h"
+#include "debugger.h"
+#include "m37710cm.h"
+#define EXECUTION_MODE EXECUTION_MODE_M0X0
+#include "m37710op.h"
diff --git a/trunk/src/emu/cpu/m37710/m37710o1.c b/trunk/src/emu/cpu/m37710/m37710o1.c
new file mode 100644
index 00000000000..3c1c0bfe6f7
--- /dev/null
+++ b/trunk/src/emu/cpu/m37710/m37710o1.c
@@ -0,0 +1,5 @@
+#include "emu.h"
+#include "debugger.h"
+#include "m37710cm.h"
+#define EXECUTION_MODE EXECUTION_MODE_M0X1
+#include "m37710op.h"
diff --git a/trunk/src/emu/cpu/m37710/m37710o2.c b/trunk/src/emu/cpu/m37710/m37710o2.c
new file mode 100644
index 00000000000..7c9c558568a
--- /dev/null
+++ b/trunk/src/emu/cpu/m37710/m37710o2.c
@@ -0,0 +1,5 @@
+#include "emu.h"
+#include "debugger.h"
+#include "m37710cm.h"
+#define EXECUTION_MODE EXECUTION_MODE_M1X0
+#include "m37710op.h"
diff --git a/trunk/src/emu/cpu/m37710/m37710o3.c b/trunk/src/emu/cpu/m37710/m37710o3.c
new file mode 100644
index 00000000000..cd513fc1bb2
--- /dev/null
+++ b/trunk/src/emu/cpu/m37710/m37710o3.c
@@ -0,0 +1,5 @@
+#include "emu.h"
+#include "debugger.h"
+#include "m37710cm.h"
+#define EXECUTION_MODE EXECUTION_MODE_M1X1
+#include "m37710op.h"
diff --git a/trunk/src/emu/cpu/m37710/m37710op.h b/trunk/src/emu/cpu/m37710/m37710op.h
new file mode 100644
index 00000000000..1ae9cbc0b56
--- /dev/null
+++ b/trunk/src/emu/cpu/m37710/m37710op.h
@@ -0,0 +1,2959 @@
+/* ======================================================================== */
+/* ============================= CONFIGURATION ============================ */
+/* ======================================================================== */
+
+#undef FLAG_SET_M
+#undef FLAG_SET_X
+
+#if EXECUTION_MODE == EXECUTION_MODE_M0X0
+#define FLAG_SET_M 0
+#define FLAG_SET_X 0
+#elif EXECUTION_MODE == EXECUTION_MODE_M0X1
+#define FLAG_SET_M 0
+#define FLAG_SET_X 1
+#elif EXECUTION_MODE == EXECUTION_MODE_M1X0
+#define FLAG_SET_M 1
+#define FLAG_SET_X 0
+#elif EXECUTION_MODE == EXECUTION_MODE_M1X1
+#define FLAG_SET_M 1
+#define FLAG_SET_X 1
+#endif
+
+/* ======================================================================== */
+/* ================================= MEMORY =============================== */
+/* ======================================================================== */
+
+#define ADDRESS_37710(A) ((A)&0xffffff)
+
+INLINE uint m37710i_read_8_normal(m37710i_cpu_struct *cpustate, uint address)
+{
+ address = ADDRESS_37710(address);
+ return m37710_read_8(address);
+}
+
+INLINE uint m37710i_read_8_immediate(m37710i_cpu_struct *cpustate, uint address)
+{
+ address = ADDRESS_37710(address);
+ return m37710_read_8_immediate(address);
+}
+
+INLINE uint m37710i_read_8_direct(m37710i_cpu_struct *cpustate, uint address)
+{
+ address = ADDRESS_37710(address);
+ return m37710_read_8(address);
+}
+
+INLINE void m37710i_write_8_normal(m37710i_cpu_struct *cpustate, uint address, uint value)
+{
+ address = ADDRESS_37710(address);
+ m37710_write_8(address, MAKE_UINT_8(value));
+}
+
+INLINE void m37710i_write_8_direct(m37710i_cpu_struct *cpustate, uint address, uint value)
+{
+ address = ADDRESS_37710(address);
+ m37710_write_8(address, MAKE_UINT_8(value));
+}
+
+INLINE uint m37710i_read_16_normal(m37710i_cpu_struct *cpustate, uint address)
+{
+ address = ADDRESS_37710(address);
+ if (address & 1)
+ return m37710i_read_8_normal(cpustate, address) | m37710i_read_8_normal(cpustate, address+1)<<8;
+ else
+ return m37710_read_16(address);
+}
+
+INLINE uint m37710i_read_16_immediate(m37710i_cpu_struct *cpustate, uint address)
+{
+ address = ADDRESS_37710(address);
+ if (address & 1)
+ return m37710_read_8_immediate(address) | m37710_read_8_immediate(address+1)<<8;
+ else
+ return m37710_read_16(address);
+}
+
+INLINE uint m37710i_read_16_direct(m37710i_cpu_struct *cpustate, uint address)
+{
+ address = ADDRESS_37710(address);
+ if (address & 1)
+ return m37710_read_8(address) | m37710_read_8((address)+1)<<8;
+ else
+ return m37710_read_16(address);
+}
+
+INLINE void m37710i_write_16_normal(m37710i_cpu_struct *cpustate, uint address, uint value)
+{
+ address = ADDRESS_37710(address);
+ if (address & 1)
+ {
+ m37710_write_8(address, value);
+ m37710_write_8(address+1, value>>8);
+ }
+ else
+ m37710_write_16(address, value);
+}
+
+INLINE void m37710i_write_16_direct(m37710i_cpu_struct *cpustate, uint address, uint value)
+{
+ address = ADDRESS_37710(address);
+ if (address & 1)
+ {
+ m37710_write_8(address, value);
+ m37710_write_8(address+1, value>>8);
+ }
+ else
+ m37710_write_16(address, value);
+}
+
+INLINE uint m37710i_read_24_normal(m37710i_cpu_struct *cpustate, uint address)
+{
+ return m37710i_read_16_normal(cpustate, address) |
+ (m37710i_read_8_normal(cpustate, address+2)<<16);
+}
+
+INLINE uint m37710i_read_24_immediate(m37710i_cpu_struct *cpustate, uint address)
+{
+ return m37710i_read_16_immediate(cpustate, address) |
+ (m37710i_read_8_immediate(cpustate, address+2)<<16);
+}
+
+INLINE uint m37710i_read_24_direct(m37710i_cpu_struct *cpustate, uint address)
+{
+ return m37710i_read_16_direct(cpustate, address) |
+ (m37710i_read_8_direct(cpustate, address+2)<<16);
+}
+
+
+
+/* ======================================================================== */
+/* ================================= STACK ================================ */
+/* ======================================================================== */
+
+INLINE void m37710i_push_8(m37710i_cpu_struct *cpustate, uint value)
+{
+ m37710i_write_8_normal(cpustate, REG_S, value);
+ REG_S = MAKE_UINT_16(REG_S-1);
+}
+
+INLINE uint m37710i_pull_8(m37710i_cpu_struct *cpustate)
+{
+ REG_S = MAKE_UINT_16(REG_S+1);
+ return m37710i_read_8_normal(cpustate, REG_S);
+}
+
+INLINE void m37710i_push_16(m37710i_cpu_struct *cpustate, uint value)
+{
+ m37710i_push_8(cpustate, value>>8);
+ m37710i_push_8(cpustate, value&0xff);
+}
+
+INLINE uint m37710i_pull_16(m37710i_cpu_struct *cpustate)
+{
+ uint res = m37710i_pull_8(cpustate);
+ return res | (m37710i_pull_8(cpustate) << 8);
+}
+
+INLINE void m37710i_push_24(m37710i_cpu_struct *cpustate, uint value)
+{
+ m37710i_push_8(cpustate, value>>16);
+ m37710i_push_8(cpustate, (value>>8)&0xff);
+ m37710i_push_8(cpustate, value&0xff);
+}
+
+INLINE uint m37710i_pull_24(m37710i_cpu_struct *cpustate)
+{
+ uint res = m37710i_pull_8(cpustate);
+ res |= m37710i_pull_8(cpustate) << 8;
+ return res | (m37710i_pull_8(cpustate) << 16);
+}
+
+
+/* ======================================================================== */
+/* ============================ PROGRAM COUNTER =========================== */
+/* ======================================================================== */
+
+INLINE void m37710i_jump_16(m37710i_cpu_struct *cpustate, uint address)
+{
+ REG_PC = MAKE_UINT_16(address);
+ m37710i_jumping(REG_PC);
+}
+
+INLINE void m37710i_jump_24(m37710i_cpu_struct *cpustate, uint address)
+{
+ REG_PB = address&0xff0000;
+ REG_PC = MAKE_UINT_16(address);
+ m37710i_jumping(REG_PC);
+}
+
+INLINE void m37710i_branch_8(m37710i_cpu_struct *cpustate, uint offset)
+{
+ REG_PC = MAKE_UINT_16(REG_PC + MAKE_INT_8(offset));
+ m37710i_branching(REG_PC);
+}
+
+INLINE void m37710i_branch_16(m37710i_cpu_struct *cpustate, uint offset)
+{
+ REG_PC = MAKE_UINT_16(REG_PC + offset);
+ m37710i_branching(REG_PC);
+}
+
+
+/* ======================================================================== */
+/* ============================ STATUS REGISTER =========================== */
+/* ======================================================================== */
+
+/* note: difference from 65816. when switching to 8-bit X/Y, X and Y are *not* truncated
+ to 8 bits! */
+
+INLINE void m37710i_set_flag_mx(m37710i_cpu_struct *cpustate, uint value)
+{
+#if FLAG_SET_M
+ if(!(value & FLAGPOS_M))
+ {
+ REG_A |= REG_B;
+ REG_B = 0;
+ REG_BA |= REG_BB;
+ REG_BB = 0;
+ FLAG_M = MFLAG_CLEAR;
+ }
+#else
+ if(value & FLAGPOS_M)
+ {
+ REG_B = REG_A & 0xff00;
+ REG_A = MAKE_UINT_8(REG_A);
+ REG_BB = REG_BA & 0xff00;
+ REG_BA = MAKE_UINT_8(REG_BA);
+ FLAG_M = MFLAG_SET;
+ }
+#endif
+#if FLAG_SET_X
+ if(!(value & FLAGPOS_X))
+ {
+ FLAG_X = XFLAG_CLEAR;
+ }
+#else
+ if(value & FLAGPOS_X)
+ {
+ FLAG_X = XFLAG_SET;
+ }
+#endif
+ m37710i_set_execution_mode(cpustate, (FLAG_M>>4) | (FLAG_X>>4));
+}
+
+
+INLINE void m37710i_set_flag_i(m37710i_cpu_struct *cpustate, uint value)
+{
+ value &= FLAGPOS_I;
+ if(!FLAG_I || value)
+ {
+ FLAG_I = value;
+ return;
+ }
+ FLAG_I = value;
+}
+
+
+
+
+/* Get the Processor Status Register */
+INLINE uint m37710i_get_reg_p(m37710i_cpu_struct *cpustate)
+{
+ return (FLAG_N&0x80) |
+ ((FLAG_V>>1)&0x40) |
+ FLAG_M |
+ FLAG_X |
+ FLAG_D |
+ FLAG_I |
+ ((!FLAG_Z)<<1) |
+ ((FLAG_C>>8)&1);
+}
+
+INLINE void m37710i_set_reg_p(m37710i_cpu_struct *cpustate, uint value)
+{
+ FLAG_N = value;
+ FLAG_V = value << 1;
+ FLAG_D = value & FLAGPOS_D;
+ FLAG_Z = !(value & FLAGPOS_Z);
+ FLAG_C = value << 8;
+ m37710i_set_flag_mx(cpustate, value);
+ m37710i_set_flag_i(cpustate, value);
+}
+
+INLINE void m37710i_set_reg_ipl(m37710i_cpu_struct *cpustate, uint value)
+{
+ cpustate->ipl = value & 7;
+}
+
+/* ======================================================================== */
+/* =============================== INTERRUPTS ============================= */
+/* ======================================================================== */
+
+INLINE void m37710i_interrupt_hardware(m37710i_cpu_struct *cpustate, uint vector)
+{
+ CLK(8);
+ m37710i_push_8(cpustate, REG_PB>>16);
+ m37710i_push_16(cpustate, REG_PC);
+ m37710i_push_8(cpustate, m37710i_get_reg_p(cpustate));
+ FLAG_D = DFLAG_CLEAR;
+ m37710i_set_flag_i(cpustate, IFLAG_SET);
+ REG_PB = 0;
+ m37710i_jump_16(cpustate, m37710i_read_16_normal(cpustate, vector));
+ if(INT_ACK) INT_ACK(cpustate->device, 0);
+}
+
+INLINE void m37710i_interrupt_software(m37710i_cpu_struct *cpustate, uint vector)
+{
+ CLK(8);
+ m37710i_push_8(cpustate, REG_PB>>16);
+ m37710i_push_16(cpustate, REG_PC);
+ m37710i_push_8(cpustate, m37710i_get_reg_p(cpustate));
+ FLAG_D = DFLAG_CLEAR;
+ m37710i_set_flag_i(cpustate, IFLAG_SET);
+ REG_PB = 0;
+ m37710i_jump_16(cpustate, m37710i_read_16_normal(cpustate, vector));
+}
+
+/* ======================================================================== */
+/* ========================== EFFECTIVE ADDRESSES ========================= */
+/* ======================================================================== */
+
+/* Effective-address based memory access macros */
+#define read_8_NORM(A) m37710i_read_8_normal(cpustate, A)
+#define read_8_IMM(A) m37710i_read_8_immediate(cpustate, A)
+#define read_8_D(A) m37710i_read_8_direct(cpustate, A)
+#define read_8_A(A) m37710i_read_8_normal(cpustate, A)
+#define read_8_AL(A) m37710i_read_8_normal(cpustate, A)
+#define read_8_DX(A) m37710i_read_8_direct(cpustate, A)
+#define read_8_DY(A) m37710i_read_8_direct(cpustate, A)
+#define read_8_AX(A) m37710i_read_8_normal(cpustate, A)
+#define read_8_ALX(A) m37710i_read_8_normal(cpustate, A)
+#define read_8_AY(A) m37710i_read_8_normal(cpustate, A)
+#define read_8_DI(A) m37710i_read_8_normal(cpustate, A)
+#define read_8_DLI(A) m37710i_read_8_normal(cpustate, A)
+#define read_8_AI(A) m37710i_read_8_normal(cpustate, A)
+#define read_8_ALI(A) m37710i_read_8_normal(cpustate, A)
+#define read_8_DXI(A) m37710i_read_8_normal(cpustate, A)
+#define read_8_DIY(A) m37710i_read_8_normal(cpustate, A)
+#define read_8_DLIY(A) m37710i_read_8_normal(cpustate, A)
+#define read_8_AXI(A) m37710i_read_8_normal(cpustate, A)
+#define read_8_S(A) m37710i_read_8_normal(cpustate, A)
+#define read_8_SIY(A) m37710i_read_8_normal(cpustate, A)
+
+#define read_16_NORM(A) m37710i_read_16_normal(cpustate, A)
+#define read_16_IMM(A) m37710i_read_16_immediate(cpustate, A)
+#define read_16_D(A) m37710i_read_16_direct(cpustate, A)
+#define read_16_A(A) m37710i_read_16_normal(cpustate, A)
+#define read_16_AL(A) m37710i_read_16_normal(cpustate, A)
+#define read_16_DX(A) m37710i_read_16_direct(cpustate, A)
+#define read_16_DY(A) m37710i_read_16_direct(cpustate, A)
+#define read_16_AX(A) m37710i_read_16_normal(cpustate, A)
+#define read_16_ALX(A) m37710i_read_16_normal(cpustate, A)
+#define read_16_AY(A) m37710i_read_16_normal(cpustate, A)
+#define read_16_DI(A) m37710i_read_16_normal(cpustate, A)
+#define read_16_DLI(A) m37710i_read_16_normal(cpustate, A)
+#define read_16_AI(A) m37710i_read_16_normal(cpustate, A)
+#define read_16_ALI(A) m37710i_read_16_normal(cpustate, A)
+#define read_16_DXI(A) m37710i_read_16_normal(cpustate, A)
+#define read_16_DIY(A) m37710i_read_16_normal(cpustate, A)
+#define read_16_DLIY(A) m37710i_read_16_normal(cpustate, A)
+#define read_16_AXI(A) m37710i_read_16_normal(cpustate, A)
+#define read_16_S(A) m37710i_read_16_normal(cpustate, A)
+#define read_16_SIY(A) m37710i_read_16_normal(cpustate, A)
+
+#define read_24_NORM(A) m37710i_read_24_normal(cpustate, A)
+#define read_24_IMM(A) m37710i_read_24_immediate(cpustate, A)
+#define read_24_D(A) m37710i_read_24_direct(cpustate, A)
+#define read_24_A(A) m37710i_read_24_normal(cpustate, A)
+#define read_24_AL(A) m37710i_read_24_normal(cpustate, A)
+#define read_24_DX(A) m37710i_read_24_direct(cpustate, A)
+#define read_24_DY(A) m37710i_read_24_direct(cpustate, A)
+#define read_24_AX(A) m37710i_read_24_normal(cpustate, A)
+#define read_24_ALX(A) m37710i_read_24_normal(cpustate, A)
+#define read_24_AY(A) m37710i_read_24_normal(cpustate, A)
+#define read_24_DI(A) m37710i_read_24_normal(cpustate, A)
+#define read_24_DLI(A) m37710i_read_24_normal(cpustate, A)
+#define read_24_AI(A) m37710i_read_24_normal(cpustate, A)
+#define read_24_ALI(A) m37710i_read_24_normal(cpustate, A)
+#define read_24_DXI(A) m37710i_read_24_normal(cpustate, A)
+#define read_24_DIY(A) m37710i_read_24_normal(cpustate, A)
+#define read_24_DLIY(A) m37710i_read_24_normal(cpustate, A)
+#define read_24_AXI(A) m37710i_read_24_normal(cpustate, A)
+#define read_24_S(A) m37710i_read_24_normal(cpustate, A)
+#define read_24_SIY(A) m37710i_read_24_normal(cpustate, A)
+
+#define write_8_NORM(A, V) m37710i_write_8_normal(cpustate, A, V)
+#define write_8_D(A, V) m37710i_write_8_direct(cpustate, A, V)
+#define write_8_A(A, V) m37710i_write_8_normal(cpustate, A, V)
+#define write_8_AL(A, V) m37710i_write_8_normal(cpustate, A, V)
+#define write_8_DX(A, V) m37710i_write_8_direct(cpustate, A, V)
+#define write_8_DY(A, V) m37710i_write_8_direct(cpustate, A, V)
+#define write_8_AX(A, V) m37710i_write_8_normal(cpustate, A, V)
+#define write_8_ALX(A, V) m37710i_write_8_normal(cpustate, A, V)
+#define write_8_AY(A, V) m37710i_write_8_normal(cpustate, A, V)
+#define write_8_DI(A, V) m37710i_write_8_normal(cpustate, A, V)
+#define write_8_DLI(A, V) m37710i_write_8_normal(cpustate, A, V)
+#define write_8_AI(A, V) m37710i_write_8_normal(cpustate, A, V)
+#define write_8_ALI(A, V) m37710i_write_8_normal(cpustate, A, V)
+#define write_8_DXI(A, V) m37710i_write_8_normal(cpustate, A, V)
+#define write_8_DIY(A, V) m37710i_write_8_normal(cpustate, A, V)
+#define write_8_DLIY(A, V) m37710i_write_8_normal(cpustate, A, V)
+#define write_8_AXI(A, V) m37710i_write_8_normal(cpustate, A, V)
+#define write_8_S(A, V) m37710i_write_8_normal(cpustate, A, V)
+#define write_8_SIY(A, V) m37710i_write_8_normal(cpustate, A, V)
+
+#define write_16_NORM(A, V) m37710i_write_16_normal(cpustate, A, V)
+#define write_16_D(A, V) m37710i_write_16_direct(cpustate, A, V)
+#define write_16_A(A, V) m37710i_write_16_normal(cpustate, A, V)
+#define write_16_AL(A, V) m37710i_write_16_normal(cpustate, A, V)
+#define write_16_DX(A, V) m37710i_write_16_direct(cpustate, A, V)
+#define write_16_DY(A, V) m37710i_write_16_direct(cpustate, A, V)
+#define write_16_AX(A, V) m37710i_write_16_normal(cpustate, A, V)
+#define write_16_ALX(A, V) m37710i_write_16_normal(cpustate, A, V)
+#define write_16_AY(A, V) m37710i_write_16_normal(cpustate, A, V)
+#define write_16_DI(A, V) m37710i_write_16_normal(cpustate, A, V)
+#define write_16_DLI(A, V) m37710i_write_16_normal(cpustate, A, V)
+#define write_16_AI(A, V) m37710i_write_16_normal(cpustate, A, V)
+#define write_16_ALI(A, V) m37710i_write_16_normal(cpustate, A, V)
+#define write_16_DXI(A, V) m37710i_write_16_normal(cpustate, A, V)
+#define write_16_DIY(A, V) m37710i_write_16_normal(cpustate, A, V)
+#define write_16_DLIY(A, V) m37710i_write_16_normal(cpustate, A, V)
+#define write_16_AXI(A, V) m37710i_write_16_normal(cpustate, A, V)
+#define write_16_S(A, V) m37710i_write_16_normal(cpustate, A, V)
+#define write_16_SIY(A, V) m37710i_write_16_normal(cpustate, A, V)
+
+
+#define OPER_8_IMM(cpustate) read_8_IMM(EA_IMM8(cpustate))
+#define OPER_8_D(cpustate) read_8_D(EA_D(cpustate))
+#define OPER_8_A(cpustate) read_8_A(EA_A(cpustate))
+#define OPER_8_AL(cpustate) read_8_AL(EA_AL(cpustate))
+#define OPER_8_DX(cpustate) read_8_DX(EA_DX(cpustate))
+#define OPER_8_DY(cpustate) read_8_DY(EA_DY(cpustate))
+#define OPER_8_AX(cpustate) read_8_AX(EA_AX(cpustate))
+#define OPER_8_ALX(cpustate) read_8_ALX(EA_ALX(cpustate))
+#define OPER_8_AY(cpustate) read_8_AY(EA_AY(cpustate))
+#define OPER_8_DI(cpustate) read_8_DI(EA_DI(cpustate))
+#define OPER_8_DLI(cpustate) read_8_DLI(EA_DLI(cpustate))
+#define OPER_8_AI(cpustate) read_8_AI(EA_AI(cpustate))
+#define OPER_8_ALI(cpustate) read_8_ALI(EA_ALI(cpustate))
+#define OPER_8_DXI(cpustate) read_8_DXI(EA_DXI(cpustate))
+#define OPER_8_DIY(cpustate) read_8_DIY(EA_DIY(cpustate))
+#define OPER_8_DLIY(cpustate) read_8_DLIY(EA_DLIY(cpustate))
+#define OPER_8_AXI(cpustate) read_8_AXI(EA_AXI(cpustate))
+#define OPER_8_S(cpustate) read_8_S(EA_S(cpustate))
+#define OPER_8_SIY(cpustate) read_8_SIY(EA_SIY(cpustate))
+
+#define OPER_16_IMM(cpustate) read_16_IMM(EA_IMM16(cpustate))
+#define OPER_16_D(cpustate) read_16_D(EA_D(cpustate))
+#define OPER_16_A(cpustate) read_16_A(EA_A(cpustate))
+#define OPER_16_AL(cpustate) read_16_AL(EA_AL(cpustate))
+#define OPER_16_DX(cpustate) read_16_DX(EA_DX(cpustate))
+#define OPER_16_DY(cpustate) read_16_DY(EA_DY(cpustate))
+#define OPER_16_AX(cpustate) read_16_AX(EA_AX(cpustate))
+#define OPER_16_ALX(cpustate) read_16_ALX(EA_ALX(cpustate))
+#define OPER_16_AY(cpustate) read_16_AY(EA_AY(cpustate))
+#define OPER_16_DI(cpustate) read_16_DI(EA_DI(cpustate))
+#define OPER_16_DLI(cpustate) read_16_DLI(EA_DLI(cpustate))
+#define OPER_16_AI(cpustate) read_16_AI(EA_AI(cpustate))
+#define OPER_16_ALI(cpustate) read_16_ALI(EA_ALI(cpustate))
+#define OPER_16_DXI(cpustate) read_16_DXI(EA_DXI(cpustate))
+#define OPER_16_DIY(cpustate) read_16_DIY(EA_DIY(cpustate))
+#define OPER_16_DLIY(cpustate) read_16_DLIY(EA_DLIY(cpustate))
+#define OPER_16_AXI(cpustate) read_16_AXI(EA_AXI(cpustate))
+#define OPER_16_S(cpustate) read_16_S(EA_S(cpustate))
+#define OPER_16_SIY(cpustate) read_16_SIY(EA_SIY(cpustate))
+
+#define OPER_24_IMM(cpustate) read_24_IMM(EA_IMM24(cpustate))
+#define OPER_24_D(cpustate) read_24_D(EA_D(cpustate))
+#define OPER_24_A(cpustate) read_24_A(EA_A(cpustate))
+#define OPER_24_AL(cpustate) read_24_AL(EA_AL(cpustate))
+#define OPER_24_DX(cpustate) read_24_DX(EA_DX(cpustate))
+#define OPER_24_DY(cpustate) read_24_DY(EA_DY(cpustate))
+#define OPER_24_AX(cpustate) read_24_AX(EA_AX(cpustate))
+#define OPER_24_ALX(cpustate) read_24_ALX(EA_ALX(cpustate))
+#define OPER_24_AY(cpustate) read_24_AY(EA_AY(cpustate))
+#define OPER_24_DI(cpustate) read_24_DI(EA_DI(cpustate))
+#define OPER_24_DLI(cpustate) read_24_DLI(EA_DLI(cpustate))
+#define OPER_24_AI(cpustate) read_24_AI(EA_AI(cpustate))
+#define OPER_24_ALI(cpustate) read_24_ALI(EA_ALI())
+#define OPER_24_DXI(cpustate) read_24_DXI(EA_DXI(cpustate))
+#define OPER_24_DIY(cpustate) read_24_DIY(EA_DIY(cpustate))
+#define OPER_24_DLIY(cpustate) read_24_DLIY(EA_DLIY(cpustate))
+#define OPER_24_AXI(cpustate) read_24_AXI(EA_AXI(cpustate))
+#define OPER_24_S(cpustate) read_24_S(EA_S(cpustate))
+#define OPER_24_SIY(cpustate) read_24_SIY(EA_SIY(cpustate))
+
+INLINE uint EA_IMM8(m37710i_cpu_struct *cpustate) {REG_PC += 1; return REG_PB | MAKE_UINT_16(REG_PC-1);}
+INLINE uint EA_IMM16(m37710i_cpu_struct *cpustate) {REG_PC += 2; return REG_PB | MAKE_UINT_16(REG_PC-2);}
+INLINE uint EA_IMM24(m37710i_cpu_struct *cpustate) {REG_PC += 3; return REG_PB | MAKE_UINT_16(REG_PC-3);}
+INLINE uint EA_D(m37710i_cpu_struct *cpustate) {if(MAKE_UINT_8(REG_D)) CLK(1); return MAKE_UINT_16(REG_D + OPER_8_IMM(cpustate));}
+INLINE uint EA_A(m37710i_cpu_struct *cpustate) {return REG_DB | OPER_16_IMM(cpustate);}
+INLINE uint EA_AL(m37710i_cpu_struct *cpustate) {return OPER_24_IMM(cpustate);}
+INLINE uint EA_DX(m37710i_cpu_struct *cpustate) {return MAKE_UINT_16(REG_D + OPER_8_IMM(cpustate) + REG_X);}
+INLINE uint EA_DY(m37710i_cpu_struct *cpustate) {return MAKE_UINT_16(REG_D + OPER_8_IMM(cpustate) + REG_Y);}
+INLINE uint EA_AX(m37710i_cpu_struct *cpustate) {uint tmp = EA_A(cpustate); if((tmp^(tmp+REG_X))&0xff00) CLK(1); return tmp + REG_X;}
+INLINE uint EA_ALX(m37710i_cpu_struct *cpustate) {return EA_AL(cpustate) + REG_X;}
+INLINE uint EA_AY(m37710i_cpu_struct *cpustate) {uint tmp = EA_A(cpustate); if((tmp^(tmp+REG_X))&0xff00) CLK(1); return tmp + REG_Y;}
+INLINE uint EA_DI(m37710i_cpu_struct *cpustate) {return REG_DB | OPER_16_D(cpustate);}
+INLINE uint EA_DLI(m37710i_cpu_struct *cpustate) {return OPER_24_D(cpustate);}
+INLINE uint EA_AI(m37710i_cpu_struct *cpustate) {return read_16_A(OPER_16_IMM(cpustate));}
+INLINE uint EA_ALI(m37710i_cpu_struct *cpustate) {return OPER_24_A(cpustate);}
+INLINE uint EA_DXI(m37710i_cpu_struct *cpustate) {return REG_DB | OPER_16_DX(cpustate);}
+INLINE uint EA_DIY(m37710i_cpu_struct *cpustate) {uint tmp = REG_DB | OPER_16_D(cpustate); if((tmp^(tmp+REG_X))&0xff00) CLK(1); return tmp + REG_Y;}
+INLINE uint EA_DLIY(m37710i_cpu_struct *cpustate) {return OPER_24_D(cpustate) + REG_Y;}
+INLINE uint EA_AXI(m37710i_cpu_struct *cpustate) {return read_16_AXI(MAKE_UINT_16(OPER_16_IMM(cpustate) + REG_X));}
+INLINE uint EA_S(m37710i_cpu_struct *cpustate) {return MAKE_UINT_16(REG_S + OPER_8_IMM(cpustate));}
+INLINE uint EA_SIY(m37710i_cpu_struct *cpustate) {return MAKE_UINT_16(read_16_SIY(REG_S + OPER_8_IMM(cpustate)) + REG_Y) | REG_DB;}
+
+
+/* ======================================================================== */
+/* =========================== OPERATION MACROS =========================== */
+/* ======================================================================== */
+
+/* M37710 Push all */
+#undef OP_PSH
+
+#if FLAG_SET_M
+#if FLAG_SET_X
+#define OP_PSH(MODE) \
+ SRC = OPER_8_##MODE(cpustate); \
+ if (SRC&0x1) \
+ m37710i_push_8(cpustate, REG_A); \
+ if (SRC&0x2) \
+ m37710i_push_8(cpustate, REG_BA); \
+ if (SRC&0x4) \
+ m37710i_push_8(cpustate, REG_X); \
+ if (SRC&0x8) \
+ m37710i_push_8(cpustate, REG_Y); \
+ if (SRC&0x10) \
+ m37710i_push_16(cpustate, REG_D); \
+ if (SRC&0x20) \
+ m37710i_push_8(cpustate, REG_DB>>16); \
+ if (SRC&0x40) \
+ m37710i_push_8(cpustate, REG_PB>>16); \
+ if (SRC&0x80) \
+ m37710i_push_8(cpustate, m37710i_get_reg_p(cpustate));
+#else // FLAG_SET_X
+#define OP_PSH(MODE) \
+ SRC = OPER_8_##MODE(cpustate); \
+ if (SRC&0x1) \
+ m37710i_push_8(cpustate, REG_A); \
+ if (SRC&0x2) \
+ m37710i_push_8(cpustate, REG_BA); \
+ if (SRC&0x4) \
+ m37710i_push_16(cpustate, REG_X); \
+ if (SRC&0x8) \
+ m37710i_push_16(cpustate, REG_Y); \
+ if (SRC&0x10) \
+ m37710i_push_16(cpustate, REG_D); \
+ if (SRC&0x20) \
+ m37710i_push_8(cpustate, REG_DB>>16); \
+ if (SRC&0x40) \
+ m37710i_push_8(cpustate, REG_PB>>16); \
+ if (SRC&0x80) \
+ m37710i_push_8(cpustate, m37710i_get_reg_p(cpustate));
+#endif // FLAG_SET_X
+#else // FLAG_SET_M
+#if FLAG_SET_X
+#define OP_PSH(MODE) \
+ SRC = OPER_8_##MODE(cpustate); \
+ if (SRC&0x1) \
+ m37710i_push_16(cpustate, REG_A); \
+ if (SRC&0x2) \
+ m37710i_push_16(cpustate, REG_BA); \
+ if (SRC&0x4) \
+ m37710i_push_8(cpustate, REG_X); \
+ if (SRC&0x8) \
+ m37710i_push_8(cpustate, REG_Y); \
+ if (SRC&0x10) \
+ m37710i_push_16(cpustate, REG_D); \
+ if (SRC&0x20) \
+ m37710i_push_8(cpustate, REG_DB>>16); \
+ if (SRC&0x40) \
+ m37710i_push_8(cpustate, REG_PB>>16); \
+ if (SRC&0x80) \
+ m37710i_push_8(cpustate, m37710i_get_reg_p(cpustate));
+#else // FLAG_SET_X
+#define OP_PSH(MODE) \
+ SRC = OPER_8_##MODE(cpustate); \
+ if (SRC&0x1) \
+ m37710i_push_16(cpustate, REG_A); \
+ if (SRC&0x2) \
+ m37710i_push_16(cpustate, REG_BA); \
+ if (SRC&0x4) \
+ m37710i_push_16(cpustate, REG_X); \
+ if (SRC&0x8) \
+ m37710i_push_16(cpustate, REG_Y); \
+ if (SRC&0x10) \
+ m37710i_push_16(cpustate, REG_D); \
+ if (SRC&0x20) \
+ m37710i_push_8(cpustate, REG_DB>>16); \
+ if (SRC&0x40) \
+ m37710i_push_8(cpustate, REG_PB>>16); \
+ if (SRC&0x80) \
+ m37710i_push_8(cpustate, m37710i_get_reg_p(cpustate));
+#endif // FLAG_SET_X
+#endif // FLAG_SET_M
+
+/* M37710 Pull all */
+#undef OP_PUL
+#if FLAG_SET_M
+#if FLAG_SET_X
+#define OP_PUL(MODE) \
+ SRC = OPER_8_##MODE(cpustate); \
+ if (SRC&0x80) \
+ m37710i_set_reg_p(cpustate, m37710i_pull_8(cpustate)); \
+ if (SRC&0x40) \
+ REG_PB = m37710i_pull_8(cpustate) << 16; \
+ if (SRC&0x20) \
+ REG_DB = m37710i_pull_8(cpustate) << 16; \
+ if (SRC&0x10) \
+ REG_D = m37710i_pull_16(cpustate); \
+ if (SRC&0x8) \
+ REG_Y = m37710i_pull_8(cpustate); \
+ if (SRC&0x4) \
+ REG_X = m37710i_pull_8(cpustate); \
+ if (SRC&0x2) \
+ REG_BA = m37710i_pull_8(cpustate); \
+ if (SRC&0x1) \
+ REG_A = m37710i_pull_8(cpustate);
+#else
+#define OP_PUL(MODE) \
+ SRC = OPER_8_##MODE(cpustate); \
+ if (SRC&0x80) \
+ m37710i_set_reg_p(cpustate, m37710i_pull_8(cpustate)); \
+ if (SRC&0x40) \
+ REG_PB = m37710i_pull_8(cpustate) << 16; \
+ if (SRC&0x20) \
+ REG_DB = m37710i_pull_8(cpustate) << 16; \
+ if (SRC&0x10) \
+ REG_D = m37710i_pull_16(cpustate); \
+ if (SRC&0x8) \
+ REG_Y = m37710i_pull_16(cpustate); \
+ if (SRC&0x4) \
+ REG_X = m37710i_pull_16(cpustate); \
+ if (SRC&0x2) \
+ REG_BA = m37710i_pull_8(cpustate); \
+ if (SRC&0x1) \
+ REG_A = m37710i_pull_8(cpustate);
+#endif
+#else
+#if FLAG_SET_X
+#define OP_PUL(MODE) \
+ SRC = OPER_8_##MODE(cpustate); \
+ if (SRC&0x80) \
+ m37710i_set_reg_p(cpustate, m37710i_pull_8(cpustate)); \
+ if (SRC&0x40) \
+ REG_PB = m37710i_pull_8(cpustate) << 16; \
+ if (SRC&0x20) \
+ REG_DB = m37710i_pull_8(cpustate) << 16; \
+ if (SRC&0x10) \
+ REG_D = m37710i_pull_16(cpustate); \
+ if (SRC&0x8) \
+ REG_Y = m37710i_pull_8(cpustate); \
+ if (SRC&0x4) \
+ REG_X = m37710i_pull_8(cpustate); \
+ if (SRC&0x2) \
+ REG_BA = m37710i_pull_16(cpustate); \
+ if (SRC&0x1) \
+ REG_A = m37710i_pull_16(cpustate);
+#else
+#define OP_PUL(MODE) \
+ SRC = OPER_8_##MODE(cpustate); \
+ if (SRC&0x80) \
+ m37710i_set_reg_p(cpustate, m37710i_pull_8(cpustate)); \
+ if (SRC&0x40) \
+ REG_PB = m37710i_pull_8(cpustate) << 16; \
+ if (SRC&0x20) \
+ REG_DB = m37710i_pull_8(cpustate) << 16; \
+ if (SRC&0x10) \
+ REG_D = m37710i_pull_16(cpustate); \
+ if (SRC&0x8) \
+ REG_Y = m37710i_pull_16(cpustate); \
+ if (SRC&0x4) \
+ REG_X = m37710i_pull_16(cpustate); \
+ if (SRC&0x2) \
+ REG_BA = m37710i_pull_16(cpustate); \
+ if (SRC&0x1) \
+ REG_A = m37710i_pull_16(cpustate);
+#endif
+#endif
+
+/* M37710 Multiply */
+#undef OP_MPY
+#if FLAG_SET_M
+#define OP_MPY(MODE) \
+ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \
+ SRC = OPER_8_##MODE(cpustate); \
+ { int temp = SRC * REG_A; REG_A = temp & 0xff; REG_BA = (temp>>8)&0xff; FLAG_Z = temp; FLAG_N = (temp & 0x8000) ? 1 : 0; FLAG_C = 0; }
+#else
+#define OP_MPY(MODE) \
+ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \
+ SRC = OPER_16_##MODE(cpustate); \
+ { int temp = SRC * REG_A; REG_A = temp & 0xffff; REG_BA = (temp>>16)&0xffff; FLAG_Z = temp; FLAG_N = (temp & 0x80000000) ? 1 : 0; FLAG_C = 0; }
+#endif
+
+/* M37710 Divide */
+#undef OP_DIV
+#if FLAG_SET_M
+#define OP_DIV(MODE) \
+ CLK(CLK_OP + CLK_R8 + CLK_##MODE + 25); \
+ SRC = (REG_BA&0xff)<<8 | (REG_A & 0xff); \
+ DST = OPER_8_##MODE(cpustate); \
+ if (DST != 0) { REG_A = SRC / DST; REG_BA = SRC % DST; SRC /= DST; } \
+ FLAG_N = (SRC & 0x80) ? 1 : 0; \
+ FLAG_Z = MAKE_UINT_8(SRC); \
+ if (DST != 0) { FLAG_V = 0; FLAG_C = 0; }
+#else
+#define OP_DIV(MODE) \
+ CLK(CLK_OP + CLK_R16 + CLK_##MODE + 25); \
+ SRC = (REG_BA<<16) | REG_A; \
+ DST = OPER_16_##MODE(cpustate); \
+ if (DST != 0) { REG_A = SRC / DST; REG_BA = SRC % DST; SRC /= DST; } \
+ FLAG_N = (SRC & 0x8000) ? 1 : 0; \
+ FLAG_Z = SRC; \
+ if (DST != 0) { FLAG_V = 0; FLAG_C = 0; }
+#endif
+
+/* M37710 Add With Carry */
+#undef OP_ADC
+#if FLAG_SET_M
+#define OP_ADC(MODE) \
+ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \
+ SRC = OPER_8_##MODE(cpustate); \
+ FLAG_C = REG_A + SRC + CFLAG_AS_1(); \
+ if(FLAG_D) \
+ { \
+ if((FLAG_C & 0xf) > 9) \
+ FLAG_C+=6; \
+ if((FLAG_C & 0xf0) > 0x90) \
+ FLAG_C+=0x60; \
+ } \
+ FLAG_V = VFLAG_ADD_8(SRC, REG_A, FLAG_C); \
+ FLAG_N = FLAG_Z = REG_A = MAKE_UINT_8(FLAG_C)
+#else
+#define OP_ADC(MODE) \
+ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \
+ SRC = OPER_16_##MODE(cpustate); \
+ if(!FLAG_D) \
+ { \
+ FLAG_C = REG_A + SRC + CFLAG_AS_1(); \
+ FLAG_V = VFLAG_ADD_16(SRC, REG_A, FLAG_C); \
+ FLAG_Z = REG_A = MAKE_UINT_16(FLAG_C); \
+ FLAG_N = NFLAG_16(REG_A); \
+ FLAG_C = CFLAG_16(FLAG_C); \
+ BREAKOUT; \
+ } \
+ FLAG_C = MAKE_UINT_8(REG_A) + MAKE_UINT_8(SRC) + CFLAG_AS_1(); \
+ if((FLAG_C & 0xf) > 9) \
+ FLAG_C+=6; \
+ if((FLAG_C & 0xf0) > 0x90) \
+ FLAG_C+=0x60; \
+ FLAG_Z = MAKE_UINT_8(FLAG_C); \
+ \
+ FLAG_C = MAKE_UINT_8(REG_A>>8) + MAKE_UINT_8(SRC>>8) + CFLAG_AS_1(); \
+ if((FLAG_C & 0xf) > 9) \
+ FLAG_C+=6; \
+ if((FLAG_C & 0xf0) > 0x90) \
+ FLAG_C+=0x60; \
+ FLAG_Z |= MAKE_UINT_8(FLAG_C) << 8; \
+ FLAG_N = NFLAG_16(FLAG_Z); \
+ FLAG_V = VFLAG_ADD_16(SRC, REG_A, FLAG_C); \
+ REG_A = FLAG_Z
+#endif
+
+/* M37710 Add With Carry - B accumulator*/
+#undef OP_ADCB
+#if FLAG_SET_M
+#define OP_ADCB(MODE) \
+ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \
+ SRC = OPER_8_##MODE(cpustate); \
+ FLAG_C = REG_BA + SRC + CFLAG_AS_1(); \
+ if(FLAG_D) \
+ { \
+ if((FLAG_C & 0xf) > 9) \
+ FLAG_C+=6; \
+ if((FLAG_C & 0xf0) > 0x90) \
+ FLAG_C+=0x60; \
+ } \
+ FLAG_V = VFLAG_ADD_8(SRC, REG_BA, FLAG_C); \
+ FLAG_N = FLAG_Z = REG_BA = MAKE_UINT_8(FLAG_C)
+#else
+#define OP_ADCB(MODE) \
+ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \
+ SRC = OPER_16_##MODE(cpustate); \
+ if(!FLAG_D) \
+ { \
+ FLAG_C = REG_BA + SRC + CFLAG_AS_1(); \
+ FLAG_V = VFLAG_ADD_16(SRC, REG_BA, FLAG_C); \
+ FLAG_Z = REG_BA = MAKE_UINT_16(FLAG_C); \
+ FLAG_N = NFLAG_16(REG_BA); \
+ FLAG_C = CFLAG_16(FLAG_C); \
+ BREAKOUT; \
+ } \
+ FLAG_C = MAKE_UINT_8(REG_BA) + MAKE_UINT_8(SRC) + CFLAG_AS_1(); \
+ if((FLAG_C & 0xf) > 9) \
+ FLAG_C+=6; \
+ if((FLAG_C & 0xf0) > 0x90) \
+ FLAG_C+=0x60; \
+ FLAG_Z = MAKE_UINT_8(FLAG_C); \
+ \
+ FLAG_C = MAKE_UINT_8(REG_BA>>8) + MAKE_UINT_8(SRC>>8) + CFLAG_AS_1(); \
+ if((FLAG_C & 0xf) > 9) \
+ FLAG_C+=6; \
+ if((FLAG_C & 0xf0) > 0x90) \
+ FLAG_C+=0x60; \
+ FLAG_Z |= MAKE_UINT_8(FLAG_C) << 8; \
+ FLAG_N = NFLAG_16(FLAG_Z); \
+ FLAG_V = VFLAG_ADD_16(SRC, REG_BA, FLAG_C); \
+ REG_BA = FLAG_Z
+#endif
+
+/* M37710 Logical AND with accumulator */
+#undef OP_AND
+#if FLAG_SET_M
+#define OP_AND(MODE) \
+ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \
+ FLAG_N = FLAG_Z = REG_A &= OPER_8_##MODE(cpustate)
+#else
+#define OP_AND(MODE) \
+ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \
+ FLAG_Z = REG_A &= OPER_16_##MODE(cpustate); \
+ FLAG_N = NFLAG_16(REG_A)
+#endif
+
+/* M37710 Logical AND with B accumulator */
+#undef OP_ANDB
+#if FLAG_SET_M
+#define OP_ANDB(MODE) \
+ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \
+ FLAG_N = FLAG_Z = REG_BA &= OPER_8_##MODE(cpustate)
+#else
+#define OP_ANDB(MODE) \
+ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \
+ FLAG_Z = REG_BA &= OPER_16_##MODE(cpustate); \
+ FLAG_N = NFLAG_16(REG_BA)
+#endif
+
+/* M37710 Arithmetic Shift Left accumulator */
+#undef OP_ASL
+#if FLAG_SET_M
+#define OP_ASL() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_C = REG_A << 1; \
+ FLAG_N = FLAG_Z = REG_A = MAKE_UINT_8(FLAG_C)
+#else
+#define OP_ASL() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_C = REG_A << 1; \
+ FLAG_Z = REG_A = MAKE_UINT_16(FLAG_C); \
+ FLAG_N = NFLAG_16(FLAG_C); \
+ FLAG_C = CFLAG_16(FLAG_C)
+#endif
+
+/* M37710 Arithmetic Shift Left B accumulator */
+#undef OP_BSL
+#if FLAG_SET_M
+#define OP_BSL() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_C = REG_BA << 1; \
+ FLAG_N = FLAG_Z = REG_BA = MAKE_UINT_8(FLAG_C)
+#else
+#define OP_BSL() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_C = REG_BA << 1; \
+ FLAG_Z = REG_BA = MAKE_UINT_16(FLAG_C); \
+ FLAG_N = NFLAG_16(FLAG_C); \
+ FLAG_C = CFLAG_16(FLAG_C)
+#endif
+
+/* M37710 Arithmetic Shift Left operand */
+#undef OP_ASLM
+#if FLAG_SET_M
+#define OP_ASLM(MODE) \
+ CLK(CLK_OP + CLK_RMW8 + CLK_W_##MODE); \
+ DST = EA_##MODE(cpustate); \
+ FLAG_C = read_8_##MODE(DST) << 1; \
+ FLAG_N = FLAG_Z = MAKE_UINT_8(FLAG_C); \
+ write_8_##MODE(DST, FLAG_Z)
+#else
+#define OP_ASLM(MODE) \
+ CLK(CLK_OP + CLK_RMW16 + CLK_W_##MODE); \
+ DST = EA_##MODE(cpustate); \
+ FLAG_C = read_16_##MODE(DST) << 1; \
+ FLAG_Z = MAKE_UINT_16(FLAG_C); \
+ FLAG_N = NFLAG_16(FLAG_C); \
+ FLAG_C = CFLAG_16(FLAG_C); \
+ write_16_##MODE(DST, FLAG_Z)
+#endif
+
+/* M37710 Branch on Condition Code */
+#undef OP_BCC
+#define OP_BCC(COND) \
+ DST = OPER_8_IMM(cpustate); \
+ if(COND) \
+ { \
+ CLK(CLK_OP + CLK_RELATIVE_8 + 1); \
+ m37710i_branch_8(cpustate, DST); \
+ BREAKOUT; \
+ } \
+ CLK(CLK_OP + CLK_RELATIVE_8); \
+
+/* M37710 Set flags according to bits */
+#undef OP_BIT
+#if FLAG_SET_M
+#define OP_BIT(MODE) \
+ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \
+ FLAG_N = OPER_8_##MODE(cpustate); \
+ FLAG_Z = FLAG_N & REG_A; \
+ FLAG_V = FLAG_N << 1
+#else
+#define OP_BIT(MODE) \
+ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \
+ FLAG_N = OPER_16_##MODE(cpustate); \
+ FLAG_Z = FLAG_N & REG_A; \
+ FLAG_N = NFLAG_16(FLAG_N); \
+ FLAG_V = FLAG_N << 1
+#endif
+
+/* M37710 Set flags according to bits (immediate addressing mode) */
+#undef OP_BITI
+#if FLAG_SET_M
+#define OP_BITI() \
+ CLK(CLK_OP + CLK_R8 + CLK_IMM); \
+ FLAG_Z = REG_A & OPER_8_IMM(cpustate)
+#else
+#define OP_BITI() \
+ CLK(CLK_OP + CLK_R16 + CLK_IMM); \
+ FLAG_Z = REG_A & OPER_16_IMM(cpustate)
+#endif
+
+/* M37710 Cause a Break interrupt */
+#undef OP_BRK
+#define OP_BRK() \
+ REG_PC++; \
+ logerror("fatalerror M37710: BRK at PC=%06x", REG_PB|REG_PC); \
+ m37710i_interrupt_software(cpustate, 0xfffa)
+
+/* M37710 Branch Always */
+#undef OP_BRA
+#define OP_BRA() \
+ CLK(CLK_OP + CLK_IMPLIED + CLK_RELATIVE_8); \
+ m37710i_branch_8(cpustate, OPER_8_IMM(cpustate))
+
+/* M37710 Branch Always Long */
+#undef OP_BRL
+#define OP_BRL() \
+ CLK(CLK_OP + CLK_IMPLIED + CLK_RELATIVE_16); \
+ m37710i_branch_16(cpustate, OPER_16_IMM(cpustate))
+
+/* M37710 Clear Carry flag */
+#undef OP_CLC
+#define OP_CLC() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_C = CFLAG_CLEAR
+
+/* M37710 Clear Decimal flag */
+#undef OP_CLD
+#define OP_CLD() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_D = DFLAG_CLEAR
+
+/* M37710 Clear Interrupt Mask flag */
+#undef OP_CLI
+#define OP_CLI() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ m37710i_set_flag_i(cpustate, IFLAG_CLEAR)
+
+/* M37710 Clear oVerflow flag */
+#undef OP_CLV
+#define OP_CLV() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_V = VFLAG_CLEAR
+
+/* M37710 Compare operand to accumulator */
+/* Unusual behavior: C flag is inverted */
+#undef OP_CMP
+#if FLAG_SET_M
+#define OP_CMP(MODE) \
+ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \
+ FLAG_C = REG_A - OPER_8_##MODE(cpustate); \
+ FLAG_N = FLAG_Z = MAKE_UINT_8(FLAG_C); \
+ FLAG_C ^= CFLAG_SET
+#else
+#define OP_CMP(MODE) \
+ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \
+ FLAG_C = REG_A - OPER_16_##MODE(cpustate); \
+ FLAG_Z = MAKE_UINT_16(FLAG_C); \
+ FLAG_N = NFLAG_16(FLAG_C); \
+ FLAG_C = ~CFLAG_16(FLAG_C)
+#endif
+
+/* M37710 Compare operand to B accumulator */
+/* Unusual behavior: C flag is inverted */
+#undef OP_CMPB
+#if FLAG_SET_M
+#define OP_CMPB(MODE) \
+ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \
+ FLAG_C = REG_BA - OPER_8_##MODE(cpustate); \
+ FLAG_N = FLAG_Z = MAKE_UINT_8(FLAG_C); \
+ FLAG_C ^= CFLAG_SET
+#else
+#define OP_CMPB(MODE) \
+ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \
+ FLAG_C = REG_BA - OPER_16_##MODE(cpustate); \
+ FLAG_Z = MAKE_UINT_16(FLAG_C); \
+ FLAG_N = NFLAG_16(FLAG_C); \
+ FLAG_C = ~CFLAG_16(FLAG_C)
+#endif
+
+/* M37710 Compare operand to index register */
+/* Unusual behavior: C flag is inverted */
+#undef OP_CMPX
+#if FLAG_SET_X
+#define OP_CMPX(REG, MODE) \
+ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \
+ FLAG_C = REG - OPER_8_##MODE(cpustate); \
+ FLAG_N = FLAG_Z = MAKE_UINT_8(FLAG_C); \
+ FLAG_C ^= CFLAG_SET
+#else
+#define OP_CMPX(REG, MODE) \
+ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \
+ FLAG_C = REG - OPER_16_##MODE(cpustate); \
+ FLAG_Z = MAKE_UINT_16(FLAG_C); \
+ FLAG_N = NFLAG_16(FLAG_C); \
+ FLAG_C = ~CFLAG_16(FLAG_C)
+#endif
+
+/* M37710 Coprocessor operation */
+#undef OP_COP
+#define OP_COP() \
+ REG_PC++; \
+ m37710i_interrupt_software(cpustate, VECTOR_COP)
+
+/* M37710 Decrement accumulator */
+#undef OP_DEC
+#if FLAG_SET_M
+#define OP_DEC() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_N = FLAG_Z = REG_A = MAKE_UINT_8(REG_A - 1)
+#else
+#define OP_DEC() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REG_A = MAKE_UINT_16(REG_A - 1); \
+ FLAG_N = NFLAG_16(REG_A)
+#endif
+
+/* M37710 Decrement B accumulator */
+#undef OP_DECB
+#if FLAG_SET_M
+#define OP_DECB() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_N = FLAG_Z = REG_BA = MAKE_UINT_8(REG_BA - 1)
+#else
+#define OP_DECB() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REG_BA = MAKE_UINT_16(REG_BA - 1); \
+ FLAG_N = NFLAG_16(REG_BA)
+#endif
+
+/* M37710 Decrement operand */
+#undef OP_DECM
+#if FLAG_SET_M
+#define OP_DECM(MODE) \
+ CLK(CLK_OP + CLK_RMW8 + CLK_W_##MODE); \
+ DST = EA_##MODE(cpustate); \
+ FLAG_N = FLAG_Z = MAKE_UINT_8(read_8_##MODE(DST) - 1); \
+ write_8_##MODE(DST, FLAG_Z)
+#else
+#define OP_DECM(MODE) \
+ CLK(CLK_OP + CLK_RMW16 + CLK_W_##MODE); \
+ DST = EA_##MODE(cpustate); \
+ FLAG_Z = MAKE_UINT_16(read_16_##MODE(DST) - 1); \
+ FLAG_N = NFLAG_16(FLAG_Z); \
+ write_16_##MODE(DST, FLAG_Z)
+#endif
+
+/* M37710 Decrement index register */
+#undef OP_DECX
+#if FLAG_SET_X
+#define OP_DECX(REG) \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_N = FLAG_Z = REG = MAKE_UINT_8(REG - 1)
+#else
+#define OP_DECX(REG) \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REG = MAKE_UINT_16(REG - 1); \
+ FLAG_N = NFLAG_16(REG)
+#endif
+
+/* M37710 Exclusive Or operand to accumulator */
+#undef OP_EOR
+#if FLAG_SET_M
+#define OP_EOR(MODE) \
+ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \
+ FLAG_N = FLAG_Z = REG_A ^= OPER_8_##MODE(cpustate)
+#else
+#define OP_EOR(MODE) \
+ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \
+ FLAG_Z = REG_A ^= OPER_16_##MODE(cpustate); \
+ FLAG_N = NFLAG_16(REG_A)
+#endif
+
+/* M37710 Exclusive Or operand to accumulator B */
+#undef OP_EORB
+#if FLAG_SET_M
+#define OP_EORB(MODE) \
+ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \
+ FLAG_N = FLAG_Z = REG_BA ^= OPER_8_##MODE(cpustate)
+#else
+#define OP_EORB(MODE) \
+ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \
+ FLAG_Z = REG_BA ^= OPER_16_##MODE(cpustate); \
+ FLAG_N = NFLAG_16(REG_BA)
+#endif
+
+/* M37710 Increment accumulator */
+#undef OP_INC
+#if FLAG_SET_M
+#define OP_INC() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_N = FLAG_Z = REG_A = MAKE_UINT_8(REG_A + 1)
+#else
+#define OP_INC() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REG_A = MAKE_UINT_16(REG_A + 1); \
+ FLAG_N = NFLAG_16(REG_A)
+#endif
+
+/* M37710 Increment B accumulator */
+#undef OP_INCB
+#if FLAG_SET_M
+#define OP_INCB() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_N = FLAG_Z = REG_BA = MAKE_UINT_8(REG_BA + 1)
+#else
+#define OP_INCB() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REG_BA = MAKE_UINT_16(REG_BA + 1); \
+ FLAG_N = NFLAG_16(REG_BA)
+#endif
+
+/* M37710 Increment operand */
+#undef OP_INCM
+#if FLAG_SET_M
+#define OP_INCM(MODE) \
+ CLK(CLK_OP + CLK_RMW8 + CLK_W_##MODE); \
+ DST = EA_##MODE(cpustate); \
+ FLAG_N = FLAG_Z = MAKE_UINT_8(read_8_##MODE(DST) + 1); \
+ write_8_##MODE(DST, FLAG_Z)
+#else
+#define OP_INCM(MODE) \
+ CLK(CLK_OP + CLK_RMW16 + CLK_W_##MODE); \
+ DST = EA_##MODE(cpustate); \
+ FLAG_Z = MAKE_UINT_16(read_16_##MODE(DST) + 1); \
+ FLAG_N = NFLAG_16(FLAG_Z); \
+ write_16_##MODE(DST, FLAG_Z)
+#endif
+
+/* M37710 Increment index register */
+#undef OP_INCX
+#if FLAG_SET_X
+#define OP_INCX(REG) \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_N = FLAG_Z = REG = MAKE_UINT_8(REG + 1)
+#else
+#define OP_INCX(REG) \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REG = MAKE_UINT_16(REG + 1); \
+ FLAG_N = NFLAG_16(REG)
+#endif
+
+/* M37710 Jump Long */
+#undef OP_JMLAI
+#define OP_JMLAI() \
+ CLK(CLK_OP + CLK_AI + 1); \
+ m37710i_jump_24(cpustate, read_24_A(OPER_16_IMM(cpustate)))
+
+/* M37710 Jump */
+#undef OP_JMP
+#define OP_JMP(MODE) \
+ CLK(CLK_OP + CLK_##MODE); \
+ m37710i_jump_16(cpustate, EA_##MODE(cpustate))
+
+/* M37710 Jump absolute indexed indirect */
+#undef OP_JMPAXI
+#define OP_JMPAXI() \
+ CLK(CLK_OP + CLK_AXI); \
+ m37710i_jump_16(cpustate, read_16_AXI(REG_PB | (MAKE_UINT_16(OPER_16_IMM(cpustate) + REG_X))))
+
+/* M37710 Jump absolute long */
+#undef OP_JMPAL
+#define OP_JMPAL() \
+ CLK(CLK_OP + CLK_AL); \
+ m37710i_jump_24(cpustate, EA_AL(cpustate))
+
+/* M37710 Jump to Subroutine Long */
+#undef OP_JSL
+#define OP_JSL(MODE) \
+ CLK(CLK_OP + CLK_W24 + CLK_##MODE + 1); \
+ DST = EA_##MODE(cpustate); \
+ m37710i_push_8(cpustate, REG_PB>>16); \
+ m37710i_push_16(cpustate, REG_PC); \
+ m37710i_jump_24(cpustate, DST)
+
+/* M37710 Jump to Subroutine */
+#undef OP_JSR
+#define OP_JSR(MODE) \
+ CLK(CLK_OP + CLK_W16 + CLK_##MODE); \
+ DST = EA_##MODE(cpustate); \
+ m37710i_push_16(cpustate, REG_PC); \
+ m37710i_jump_16(cpustate, DST)
+
+/* M37710 Jump to Subroutine */
+#undef OP_JSRAXI
+#define OP_JSRAXI() \
+ CLK(CLK_OP + CLK_W16 + CLK_AXI); \
+ DST = read_16_AXI(REG_PB | (MAKE_UINT_16(OPER_16_IMM(cpustate) + REG_X))); \
+ m37710i_push_16(cpustate, REG_PC); \
+ m37710i_jump_16(cpustate, DST)
+
+/* M37710 Load accumulator with operand */
+#undef OP_LDA
+#if FLAG_SET_M
+#define OP_LDA(MODE) \
+ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \
+ FLAG_N = FLAG_Z = REG_A = OPER_8_##MODE(cpustate)
+#else
+#define OP_LDA(MODE) \
+ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \
+ FLAG_Z = REG_A = OPER_16_##MODE(cpustate); \
+ FLAG_N = NFLAG_16(REG_A)
+#endif
+
+/* M37710 Load B accumulator with operand */
+#undef OP_LDB
+#if FLAG_SET_M
+#define OP_LDB(MODE) \
+ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \
+ FLAG_N = FLAG_Z = REG_BA = OPER_8_##MODE(cpustate)
+#else
+#define OP_LDB(MODE) \
+ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \
+ FLAG_Z = REG_BA = OPER_16_##MODE(cpustate); \
+ FLAG_N = NFLAG_16(REG_BA)
+#endif
+
+/* M37710 Load memory with operand */
+#undef OP_LDM
+#if FLAG_SET_M
+#define OP_LDM(MODE) \
+ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \
+ REG_IM2 = EA_##MODE(cpustate); \
+ REG_IM = read_8_NORM(REG_PB|REG_PC); \
+ REG_PC++; \
+ write_8_##MODE(REG_IM2, REG_IM)
+#else
+#define OP_LDM(MODE) \
+ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \
+ REG_IM2 = EA_##MODE(cpustate); \
+ REG_IM = read_16_NORM(REG_PB|REG_PC); \
+ REG_PC+=2; \
+ write_16_##MODE(REG_IM2, REG_IM)
+#endif
+
+/* M37710 Branch if bits set */
+#undef OP_BBS
+#if FLAG_SET_M
+#define OP_BBS(MODE) \
+ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \
+ REG_IM2 = read_8_NORM(EA_##MODE(cpustate)); \
+ REG_IM = read_8_NORM(REG_PC); \
+ REG_PC++; \
+ DST = OPER_8_IMM(cpustate); \
+ if ((REG_IM2 & REG_IM) == REG_IM) \
+ { \
+ CLK(CLK_OP + CLK_RELATIVE_8 + 1); \
+ m37710i_branch_8(cpustate, DST); \
+ BREAKOUT; \
+ }
+#else
+#define OP_BBS(MODE) \
+ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \
+ REG_IM2 = read_16_NORM(EA_##MODE(cpustate)); \
+ REG_IM = read_16_NORM(REG_PC); \
+ REG_PC++; \
+ REG_PC++; \
+ DST = OPER_8_IMM(cpustate); \
+ if ((REG_IM2 & REG_IM) == REG_IM) \
+ { \
+ CLK(CLK_OP + CLK_RELATIVE_8 + 1); \
+ m37710i_branch_8(cpustate, DST); \
+ BREAKOUT; \
+ }
+#endif
+
+/* M37710 Branch if bits clear */
+#undef OP_BBC
+#if FLAG_SET_M
+#define OP_BBC(MODE) \
+ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \
+ REG_IM2 = read_8_NORM(EA_##MODE(cpustate)); \
+ REG_IM = read_8_NORM(REG_PC); \
+ REG_PC++; \
+ DST = OPER_8_IMM(cpustate); \
+ if ((REG_IM2 & REG_IM) == 0) \
+ { \
+ CLK(CLK_OP + CLK_RELATIVE_8 + 1); \
+ m37710i_branch_8(cpustate, DST); \
+ BREAKOUT; \
+ }
+#else
+#define OP_BBC(MODE) \
+ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \
+ REG_IM2 = read_16_NORM(EA_##MODE(cpustate)); \
+ REG_IM = read_16_NORM(REG_PC); \
+ REG_PC++; \
+ REG_PC++; \
+ DST = OPER_8_IMM(cpustate); \
+ if ((REG_IM2 & REG_IM) == 0) \
+ { \
+ CLK(CLK_OP + CLK_RELATIVE_8 + 1); \
+ m37710i_branch_8(cpustate, DST); \
+ BREAKOUT; \
+ }
+#endif
+
+/* M37710 Swap accumulators */
+#undef OP_XAB
+#if FLAG_SET_M
+#define OP_XAB() \
+ CLK(6); \
+ DST = REG_A; \
+ FLAG_N = FLAG_Z = REG_A = REG_BA; \
+ REG_BA = DST;
+#else
+#define OP_XAB() \
+ CLK(6); \
+ DST = REG_A; \
+ FLAG_Z = REG_A = REG_BA; \
+ FLAG_N = NFLAG_16(REG_A); \
+ REG_BA = DST;
+#endif
+
+/* M37710 Load index register with operand */
+#undef OP_LDX
+#if FLAG_SET_X
+#define OP_LDX(REG, MODE) \
+ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \
+ FLAG_N = FLAG_Z = REG = OPER_8_##MODE(cpustate)
+#else
+#define OP_LDX(REG, MODE) \
+ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \
+ FLAG_Z = REG = OPER_16_##MODE(cpustate); \
+ FLAG_N = NFLAG_16(REG)
+#endif
+
+/* M37710 Logical Shift Right accumulator */
+#undef OP_LSR
+#if FLAG_SET_M
+#define OP_LSR() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_N = 0; \
+ FLAG_C = REG_A << 8; \
+ FLAG_Z = REG_A >>= 1
+#else
+#define OP_LSR() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_N = 0; \
+ FLAG_C = REG_A << 8; \
+ FLAG_Z = REG_A >>= 1
+#endif
+
+/* M37710 Logical Shift Right B accumulator */
+#undef OP_LSRB
+#if FLAG_SET_M
+#define OP_LSRB() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_N = 0; \
+ FLAG_C = REG_BA << 8; \
+ FLAG_Z = REG_BA >>= 1
+#else
+#define OP_LSRB() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_N = 0; \
+ FLAG_C = REG_BA << 8; \
+ FLAG_Z = REG_BA >>= 1
+#endif
+
+/* M37710 Logical Shift Right operand */
+#undef OP_LSRM
+#if FLAG_SET_M
+#define OP_LSRM(MODE) \
+ CLK(CLK_OP + CLK_RMW8 + CLK_W_##MODE); \
+ DST = EA_##MODE(cpustate); \
+ FLAG_N = 0; \
+ FLAG_Z = read_8_##MODE(DST); \
+ FLAG_C = FLAG_Z << 8; \
+ FLAG_Z >>= 1; \
+ write_8_##MODE(DST, FLAG_Z)
+#else
+#define OP_LSRM(MODE) \
+ CLK(CLK_OP + CLK_RMW16 + CLK_W_##MODE); \
+ DST = EA_##MODE(cpustate); \
+ FLAG_N = 0; \
+ FLAG_Z = read_16_##MODE(DST); \
+ FLAG_C = FLAG_Z << 8; \
+ FLAG_Z >>= 1; \
+ write_16_##MODE(DST, FLAG_Z)
+#endif
+
+/* M37710 Move Block Negative */
+#undef OP_MVN
+#if FLAG_SET_X
+#define OP_MVN() \
+ DST = OPER_8_IMM(cpustate)<<16; \
+ SRC = OPER_8_IMM(cpustate)<<16; \
+ REG_DB = DST; \
+ REG_A |= REG_B; \
+ CLK(7); \
+ if (REG_A > 0) \
+ { \
+ write_8_NORM(DST | REG_Y, read_8_NORM(SRC | REG_X)); \
+ REG_X = MAKE_UINT_8(REG_X+1); \
+ REG_Y = MAKE_UINT_8(REG_Y+1); \
+ REG_A--; \
+ if ((REG_A&0xffff) != 0) \
+ {\
+ REG_PC -= 3; \
+ }\
+ else \
+ { \
+ if (FLAG_M) \
+ { \
+ REG_A = 0xff; \
+ REG_B = 0xff00; \
+ } \
+ else \
+ { \
+ REG_A = 0xffff; \
+ } \
+ } \
+ }
+#else
+#define OP_MVN() \
+ DST = OPER_8_IMM(cpustate)<<16; \
+ SRC = OPER_8_IMM(cpustate)<<16; \
+ REG_DB = DST; \
+ REG_A |= REG_B; \
+ CLK(7); \
+ if (REG_A > 0) \
+ { \
+ write_8_NORM(DST | REG_Y, read_8_NORM(SRC | REG_X)); \
+ REG_X = MAKE_UINT_16(REG_X+1); \
+ REG_Y = MAKE_UINT_16(REG_Y+1); \
+ REG_A--; \
+ if ((REG_A&0xffff) != 0) \
+ {\
+ REG_PC -= 3; \
+ }\
+ else \
+ { \
+ if (FLAG_M) \
+ { \
+ REG_A = 0xff; \
+ REG_B = 0xff00; \
+ } \
+ else \
+ { \
+ REG_A = 0xffff; \
+ } \
+ } \
+ }
+#endif
+
+/* M37710 Move Block Positive */
+#undef OP_MVP
+#if FLAG_SET_X
+#define OP_MVP() \
+ DST = OPER_8_IMM(cpustate)<<16; \
+ SRC = OPER_8_IMM(cpustate)<<16; \
+ REG_DB = DST; \
+ REG_A |= REG_B; \
+ CLK(7); \
+ if (REG_A > 0) \
+ { \
+ write_8_NORM(DST | REG_Y, read_8_NORM(SRC | REG_X)); \
+ REG_X = MAKE_UINT_8(REG_X-1); \
+ REG_Y = MAKE_UINT_8(REG_Y-1); \
+ REG_A--; \
+ if ((REG_A&0xffff) != 0) \
+ {\
+ REG_PC -= 3; \
+ }\
+ else \
+ { \
+ if (FLAG_M) \
+ { \
+ REG_A = 0xff; \
+ REG_B = 0xff00; \
+ } \
+ else \
+ { \
+ REG_A = 0xffff; \
+ } \
+ } \
+ }
+#else
+#define OP_MVP() \
+ DST = OPER_8_IMM(cpustate)<<16; \
+ SRC = OPER_8_IMM(cpustate)<<16; \
+ REG_DB = DST; \
+ REG_A |= REG_B; \
+ CLK(7); \
+ if (REG_A > 0) \
+ { \
+ write_8_NORM(DST | REG_Y, read_8_NORM(SRC | REG_X)); \
+ REG_X = MAKE_UINT_16(REG_X-1); \
+ REG_Y = MAKE_UINT_16(REG_Y-1); \
+ REG_A--; \
+ if ((REG_A&0xffff) != 0) \
+ {\
+ REG_PC -= 3; \
+ }\
+ else \
+ { \
+ if (FLAG_M) \
+ { \
+ REG_A = 0xff; \
+ REG_B = 0xff00; \
+ } \
+ else \
+ { \
+ REG_A = 0xffff; \
+ } \
+ } \
+ }
+#endif
+
+/* M37710 No Operation */
+#undef OP_NOP
+#define OP_NOP() \
+ CLK(CLK_OP + CLK_IMPLIED)
+
+/* M37710 Logical OR operand to accumulator */
+#undef OP_ORA
+#if FLAG_SET_M
+#define OP_ORA(MODE) \
+ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \
+ FLAG_N = FLAG_Z = REG_A |= OPER_8_ ## MODE(cpustate)
+#else
+#define OP_ORA(MODE) \
+ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \
+ FLAG_Z = REG_A |= OPER_16_##MODE(cpustate); \
+ FLAG_N = NFLAG_16(REG_A)
+#endif
+
+/* M37710 Logical OR operand to B accumulator */
+#undef OP_ORB
+#if FLAG_SET_M
+#define OP_ORB(MODE) \
+ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \
+ FLAG_N = FLAG_Z = REG_BA |= OPER_8_ ## MODE(cpustate)
+#else
+#define OP_ORB(MODE) \
+ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \
+ FLAG_Z = REG_BA |= OPER_16_##MODE(cpustate); \
+ FLAG_N = NFLAG_16(REG_BA)
+#endif
+
+/* M37710 Push Effective Address */
+#undef OP_PEA
+#define OP_PEA() \
+ CLK(CLK_OP + CLK_R16 + CLK_W16); \
+ m37710i_push_16(cpustate, OPER_16_IMM(cpustate))
+
+/* M37710 Push Effective Indirect Address */
+#undef OP_PEI
+#define OP_PEI() \
+ CLK(CLK_OP + CLK_R16 + CLK_W16 + CLK_D); \
+ m37710i_push_16(cpustate, EA_DI(cpustate))
+
+/* M37710 Push Effective PC-Relative Address */
+#undef OP_PER
+#define OP_PER() \
+ CLK(CLK_OP + CLK_R16 + CLK_W16 + 1); \
+ SRC = OPER_16_IMM(cpustate); \
+ m37710i_push_16(cpustate, REG_PC + SRC)
+
+/* M37710 Push accumulator to the stack */
+#undef OP_PHA
+#if FLAG_SET_M
+#define OP_PHA() \
+ CLK(CLK_OP + CLK_W8 + 1); \
+ m37710i_push_8(cpustate, REG_A)
+#else
+#define OP_PHA() \
+ CLK(CLK_OP + CLK_W16 + 1); \
+ m37710i_push_16(cpustate, REG_A)
+#endif
+
+/* M37710 Push B accumulator to the stack */
+#undef OP_PHAB
+#if FLAG_SET_M
+#define OP_PHAB() \
+ CLK(CLK_OP + CLK_W8 + 1); \
+ m37710i_push_8(cpustate, REG_BA)
+#else
+#define OP_PHAB() \
+ CLK(CLK_OP + CLK_W16 + 1); \
+ m37710i_push_16(cpustate, REG_BA)
+#endif
+
+/* M37710 Push index register to the stack */
+#undef OP_PHX
+#if FLAG_SET_X
+#define OP_PHX(REG) \
+ CLK(CLK_OP + CLK_W8 + 1); \
+ m37710i_push_8(cpustate, REG)
+#else
+#define OP_PHX(REG) \
+ CLK(CLK_OP + CLK_W16 + 1); \
+ m37710i_push_16(cpustate, REG)
+#endif
+
+/* M37710 Push data bank register */
+#undef OP_PHT
+#define OP_PHT() \
+ CLK(CLK_OP + CLK_W8 + 1); \
+ m37710i_push_8(cpustate, REG_DB>>16)
+
+/* M37710 Push direct register */
+#undef OP_PHD
+#define OP_PHD() \
+ CLK(CLK_OP + CLK_W16 + 1); \
+ m37710i_push_16(cpustate, REG_D)
+
+/* M37710 Push program bank register */
+#undef OP_PHK
+#define OP_PHK() \
+ CLK(CLK_OP + CLK_W8 + 1); \
+ m37710i_push_8(cpustate, REG_PB>>16)
+
+/* M37710 Push the Processor Status Register to the stack */
+#undef OP_PHP
+#define OP_PHP() \
+ CLK(CLK_OP + CLK_W8 + 1); \
+ m37710i_push_8(cpustate, cpustate->ipl); \
+ m37710i_push_8(cpustate, m37710i_get_reg_p(cpustate))
+
+/* M37710 Pull accumulator from the stack */
+#undef OP_PLA
+#if FLAG_SET_M
+#define OP_PLA() \
+ CLK(CLK_OP + CLK_R8 + 2); \
+ FLAG_N = FLAG_Z = REG_A = m37710i_pull_8(cpustate)
+#else
+#define OP_PLA() \
+ CLK(CLK_OP + CLK_R16 + 2); \
+ FLAG_Z = REG_A = m37710i_pull_16(cpustate); \
+ FLAG_N = NFLAG_16(FLAG_Z)
+#endif
+
+/* M37710 Pull B accumulator from the stack */
+#undef OP_PLAB
+#if FLAG_SET_M
+#define OP_PLAB() \
+ CLK(CLK_OP + CLK_R8 + 2); \
+ FLAG_N = FLAG_Z = REG_BA = m37710i_pull_8(cpustate)
+#else
+#define OP_PLAB() \
+ CLK(CLK_OP + CLK_R16 + 2); \
+ FLAG_Z = REG_BA = m37710i_pull_16(cpustate); \
+ FLAG_N = NFLAG_16(FLAG_Z)
+#endif
+
+/* M37710 Pull index register from the stack */
+#undef OP_PLX
+#if FLAG_SET_X
+#define OP_PLX(REG) \
+ CLK(CLK_OP + CLK_R8 + 2); \
+ FLAG_N = FLAG_Z = REG = m37710i_pull_8(cpustate)
+#else
+#define OP_PLX(REG) \
+ CLK(CLK_OP + CLK_R16 + 2); \
+ FLAG_Z = REG = m37710i_pull_16(cpustate); \
+ FLAG_N = NFLAG_16(FLAG_Z)
+#endif
+
+/* M37710 Pull data bank register */
+#undef OP_PLT
+#define OP_PLT() \
+ CLK(CLK_OP + CLK_R8 + 2); \
+ FLAG_N = FLAG_Z = m37710i_pull_8(cpustate); \
+ REG_DB = FLAG_Z << 16
+
+/* M37710 Pull direct register */
+#undef OP_PLD
+#define OP_PLD() \
+ CLK(CLK_OP + CLK_R16 + 2); \
+ FLAG_Z = REG_D = m37710i_pull_16(cpustate); \
+ FLAG_N = NFLAG_16(FLAG_Z)
+
+/* M37710 Pull the Processor Status Register from the stack */
+#undef OP_PLP
+#define OP_PLP() \
+ CLK(CLK_OP + CLK_R8 + 2); \
+ m37710i_set_reg_p(cpustate, m37710i_pull_8(cpustate)); \
+ m37710i_set_reg_ipl(cpustate, m37710i_pull_8(cpustate))
+
+/* M37710 Reset Program status word */
+#undef OP_REP
+#define OP_REP() \
+ CLK(CLK_OP + CLK_R8 + 1); \
+ m37710i_set_reg_p(cpustate, m37710i_get_reg_p(cpustate) & ~OPER_8_IMM(cpustate))
+
+/* M37710 Clear "M" status bit */
+#undef OP_CLM
+#define OP_CLM() \
+ CLK(CLK_OP + CLK_R8 + 1); \
+ m37710i_set_reg_p(cpustate, m37710i_get_reg_p(cpustate) & ~FLAGPOS_M)
+
+/* M37710 Rotate Left the accumulator */
+#undef OP_ROL
+#if FLAG_SET_M
+#define OP_ROL() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_C = (REG_A<<1) | CFLAG_AS_1(); \
+ FLAG_N = FLAG_Z = REG_A = MAKE_UINT_8(FLAG_C)
+#else
+#define OP_ROL() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_C = (REG_A<<1) | CFLAG_AS_1(); \
+ FLAG_Z = REG_A = MAKE_UINT_16(FLAG_C); \
+ FLAG_N = NFLAG_16(FLAG_C); \
+ FLAG_C = CFLAG_16(FLAG_C)
+#endif
+
+/* M37710 Rotate Left the B accumulator */
+#undef OP_ROLB
+#if FLAG_SET_M
+#define OP_ROLB() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_C = (REG_BA<<1) | CFLAG_AS_1(); \
+ FLAG_N = FLAG_Z = REG_BA = MAKE_UINT_8(FLAG_C)
+#else
+#define OP_ROLB() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_C = (REG_BA<<1) | CFLAG_AS_1(); \
+ FLAG_Z = REG_BA = MAKE_UINT_16(FLAG_C); \
+ FLAG_N = NFLAG_16(FLAG_C); \
+ FLAG_C = CFLAG_16(FLAG_C)
+#endif
+
+/* M37710 Rotate Left the accumulator by a specified amount */
+#undef OP_RLA
+#if FLAG_SET_M
+#define OP_RLA(MODE) \
+ { int cnt = OPER_8_##MODE(cpustate); int tmp; while (cnt > 0) { CLK(6); tmp = REG_A; REG_A=(REG_A<<1)&0xff; REG_A |= (tmp>>7); cnt--; } }
+#else
+#define OP_RLA(MODE) \
+ { int cnt = OPER_16_##MODE(cpustate); int tmp; while (cnt > 0) { CLK(6); tmp = REG_A; REG_A=(REG_A<<1)&0xffff; REG_A |= (tmp>>15); cnt--; } }
+#endif
+
+/* M37710 Rotate Left an operand */
+#undef OP_ROLM
+#if FLAG_SET_M
+#define OP_ROLM(MODE) \
+ CLK(CLK_OP + CLK_RMW8 + CLK_W_##MODE); \
+ DST = EA_##MODE(cpustate); \
+ FLAG_C = (read_8_##MODE(DST)<<1) | CFLAG_AS_1(); \
+ FLAG_N = FLAG_Z = MAKE_UINT_8(FLAG_C); \
+ write_8_##MODE(DST, FLAG_Z)
+#else
+#define OP_ROLM(MODE) \
+ CLK(CLK_OP + CLK_RMW16 + CLK_W_##MODE); \
+ DST = EA_##MODE(cpustate); \
+ FLAG_C = (read_16_##MODE(DST)<<1) | CFLAG_AS_1(); \
+ FLAG_Z = MAKE_UINT_16(FLAG_C); \
+ FLAG_N = NFLAG_16(FLAG_C); \
+ FLAG_C = CFLAG_16(FLAG_C); \
+ write_16_##MODE(DST, FLAG_Z)
+#endif
+
+/* M37710 Rotate Right the accumulator */
+#undef OP_ROR
+#if FLAG_SET_M
+#define OP_ROR() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ REG_A |= FLAG_C & 0x100; \
+ FLAG_C = REG_A << 8; \
+ FLAG_N = FLAG_Z = REG_A >>= 1
+#else
+#define OP_ROR() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ REG_A |= (FLAG_C<<8) & 0x10000; \
+ FLAG_C = REG_A << 8; \
+ FLAG_Z = REG_A >>= 1; \
+ FLAG_N = NFLAG_16(REG_A)
+#endif
+
+/* M37710 Rotate Right the B accumulator */
+#undef OP_RORB
+#if FLAG_SET_M
+#define OP_RORB() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ REG_BA |= FLAG_C & 0x100; \
+ FLAG_C = REG_BA << 8; \
+ FLAG_N = FLAG_Z = REG_BA >>= 1
+#else
+#define OP_RORB() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ REG_BA |= (FLAG_C<<8) & 0x10000; \
+ FLAG_C = REG_BA << 8; \
+ FLAG_Z = REG_BA >>= 1; \
+ FLAG_N = NFLAG_16(REG_BA)
+#endif
+
+/* M37710 Rotate Right an operand */
+#undef OP_RORM
+#if FLAG_SET_M
+#define OP_RORM(MODE) \
+ CLK(CLK_OP + CLK_RMW8 + CLK_W_##MODE); \
+ DST = EA_##MODE(cpustate); \
+ FLAG_Z = read_8_##MODE(DST) | (FLAG_C & 0x100); \
+ FLAG_C = FLAG_Z << 8; \
+ FLAG_N = FLAG_Z >>= 1; \
+ write_8_##MODE(DST, FLAG_Z)
+#else
+#define OP_RORM(MODE) \
+ CLK(CLK_OP + CLK_RMW16 + CLK_W_##MODE); \
+ DST = EA_##MODE(cpustate); \
+ FLAG_Z = read_16_##MODE(DST) | ((FLAG_C<<8) & 0x10000); \
+ FLAG_C = FLAG_Z << 8; \
+ FLAG_Z >>= 1; \
+ FLAG_N = NFLAG_16(FLAG_Z); \
+ write_16_##MODE(DST, FLAG_Z)
+#endif
+
+/* M37710 Return from Interrupt */
+#undef OP_RTI
+#define OP_RTI() \
+ CLK(8); \
+ m37710i_set_reg_p(cpustate, m37710i_pull_8(cpustate)); \
+ m37710i_set_reg_ipl(cpustate, m37710i_pull_8(cpustate)); \
+ m37710i_jump_16(cpustate, m37710i_pull_16(cpustate)); \
+ REG_PB = m37710i_pull_8(cpustate) << 16; \
+ m37710i_jumping(REG_PB | REG_PC)
+
+/* M37710 Return from Subroutine Long */
+#undef OP_RTL
+#define OP_RTL() \
+ CLK(6); \
+ m37710i_jump_24(cpustate, m37710i_pull_24(cpustate))
+
+/* M37710 Return from Subroutine */
+#undef OP_RTS
+#define OP_RTS() \
+ CLK(6); \
+ DST = m37710i_pull_16(cpustate); \
+ m37710i_jump_16(cpustate, DST)
+
+/* M37710 Subtract with Carry */
+/* Unusual behavior: C flag is inverted */
+#undef OP_SBC
+#if FLAG_SET_M
+#define OP_SBC(MODE) \
+ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \
+ SRC = OPER_8_##MODE(cpustate); \
+ FLAG_C = ~FLAG_C; \
+ if(!FLAG_D) \
+ { \
+ FLAG_C = REG_A - SRC - CFLAG_AS_1(); \
+ FLAG_V = VFLAG_SUB_8(SRC, REG_A, FLAG_C); \
+ FLAG_N = FLAG_Z = REG_A = MAKE_UINT_8(FLAG_C); \
+ FLAG_C = ~FLAG_C; \
+ BREAKOUT; \
+ } \
+ DST = CFLAG_AS_1(); \
+ FLAG_C = REG_A - SRC - DST; \
+ FLAG_V = VFLAG_SUB_8(SRC, REG_A, FLAG_C); \
+ if((FLAG_C & 0xf) > 9) \
+ FLAG_C-=6; \
+ if((FLAG_C & 0xf0) > 0x90) \
+ FLAG_C-=0x60; \
+ FLAG_N = FLAG_Z = REG_A = MAKE_UINT_8(FLAG_C); \
+ FLAG_C = ~FLAG_C
+#else
+#define OP_SBC(MODE) \
+ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \
+ SRC = OPER_16_##MODE(cpustate); \
+ FLAG_C = ~FLAG_C; \
+ if(!FLAG_D) \
+ { \
+ FLAG_C = REG_A - SRC - CFLAG_AS_1(); \
+ FLAG_V = VFLAG_SUB_16(SRC, REG_A, FLAG_C); \
+ FLAG_Z = REG_A = MAKE_UINT_16(FLAG_C); \
+ FLAG_N = NFLAG_16(REG_A); \
+ FLAG_C = ~CFLAG_16(FLAG_C); \
+ BREAKOUT; \
+ } \
+ DST = CFLAG_AS_1(); \
+ FLAG_C = MAKE_UINT_8(REG_A) - MAKE_UINT_8(SRC) - DST; \
+ if((FLAG_C & 0xf) > 9) \
+ FLAG_C-=6; \
+ if((FLAG_C & 0xf0) > 0x90) \
+ FLAG_C-=0x60; \
+ FLAG_Z = MAKE_UINT_8(FLAG_C); \
+ DST = CFLAG_AS_1(); \
+ FLAG_C = MAKE_UINT_8(REG_A>>8) - MAKE_UINT_8(SRC>>8) - DST; \
+ if((FLAG_C & 0xf) > 9) \
+ FLAG_C-=6; \
+ if((FLAG_C & 0xf0) > 0x90) \
+ FLAG_C-=0x60; \
+ FLAG_Z |= MAKE_UINT_8(FLAG_C) << 8; \
+ FLAG_N = NFLAG_16(FLAG_Z); \
+ FLAG_V = VFLAG_SUB_16(SRC, REG_A, FLAG_Z); \
+ REG_A = FLAG_Z; \
+ FLAG_C = ~FLAG_C
+#endif
+
+/* M37710 Subtract with Carry - B accumulator */
+/* Unusual behavior: C flag is inverted */
+#undef OP_SBCB
+#if FLAG_SET_M
+#define OP_SBCB(MODE) \
+ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \
+ SRC = OPER_8_##MODE(cpustate); \
+ FLAG_C = ~FLAG_C; \
+ if(!FLAG_D) \
+ { \
+ FLAG_C = REG_BA - SRC - CFLAG_AS_1(); \
+ FLAG_V = VFLAG_SUB_8(SRC, REG_BA, FLAG_C); \
+ FLAG_N = FLAG_Z = REG_BA = MAKE_UINT_8(FLAG_C); \
+ FLAG_C = ~FLAG_C; \
+ BREAKOUT; \
+ } \
+ DST = CFLAG_AS_1(); \
+ FLAG_C = REG_BA - SRC - DST; \
+ FLAG_V = VFLAG_SUB_8(SRC, REG_BA, FLAG_C); \
+ if((FLAG_C & 0xf) > 9) \
+ FLAG_C-=6; \
+ if((FLAG_C & 0xf0) > 0x90) \
+ FLAG_C-=0x60; \
+ FLAG_N = FLAG_Z = REG_BA = MAKE_UINT_8(FLAG_C); \
+ FLAG_C = ~FLAG_C
+#else
+#define OP_SBCB(MODE) \
+ CLK(CLK_OP + CLK_R16 + CLK_##MODE); \
+ SRC = OPER_16_##MODE(cpustate); \
+ FLAG_C = ~FLAG_C; \
+ if(!FLAG_D) \
+ { \
+ FLAG_C = REG_BA - SRC - CFLAG_AS_1(); \
+ FLAG_V = VFLAG_SUB_16(SRC, REG_BA, FLAG_C); \
+ FLAG_Z = REG_BA = MAKE_UINT_16(FLAG_C); \
+ FLAG_N = NFLAG_16(REG_BA); \
+ FLAG_C = ~CFLAG_16(FLAG_C); \
+ BREAKOUT; \
+ } \
+ DST = CFLAG_AS_1(); \
+ FLAG_C = MAKE_UINT_8(REG_BA) - MAKE_UINT_8(SRC) - DST; \
+ if((FLAG_C & 0xf) > 9) \
+ FLAG_C-=6; \
+ if((FLAG_C & 0xf0) > 0x90) \
+ FLAG_C-=0x60; \
+ FLAG_Z = MAKE_UINT_8(FLAG_C); \
+ DST = CFLAG_AS_1(); \
+ FLAG_C = MAKE_UINT_8(REG_A>>8) - MAKE_UINT_8(SRC>>8) - DST; \
+ if((FLAG_C & 0xf) > 9) \
+ FLAG_C-=6; \
+ if((FLAG_C & 0xf0) > 0x90) \
+ FLAG_C-=0x60; \
+ FLAG_Z |= MAKE_UINT_8(FLAG_C) << 8; \
+ FLAG_N = NFLAG_16(FLAG_Z); \
+ FLAG_V = VFLAG_SUB_16(SRC, REG_BA, FLAG_Z); \
+ REG_BA = FLAG_Z; \
+ FLAG_C = ~FLAG_C
+#endif
+
+/* M37710 Set Carry flag */
+#undef OP_SEC
+#define OP_SEC() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_C = CFLAG_SET
+
+/* M37710 Set Decimal flag */
+#undef OP_SED
+#define OP_SED() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_D = DFLAG_SET
+
+/* M37710 Set Interrupt Mask flag */
+#undef OP_SEI
+#define OP_SEI() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ m37710i_set_flag_i(cpustate, IFLAG_SET)
+
+/* M37710 Set Program status word */
+#undef OP_SEP
+#define OP_SEP() \
+ CLK(CLK_OP + CLK_R8 + 1); \
+ m37710i_set_reg_p(cpustate, m37710i_get_reg_p(cpustate) | OPER_8_IMM(cpustate))
+
+/* M37710 Set "M" status bit */
+#undef OP_SEM
+#define OP_SEM() \
+ CLK(CLK_OP + CLK_R8 + 1); \
+ m37710i_set_reg_p(cpustate, m37710i_get_reg_p(cpustate) | FLAGPOS_M)
+
+/* M37710 Store accumulator to memory */
+#undef OP_STA
+#if FLAG_SET_M
+#define OP_STA(MODE) \
+ CLK(CLK_OP + CLK_W8 + CLK_W_##MODE); \
+ write_8_##MODE(EA_##MODE(cpustate), REG_A)
+#else
+#define OP_STA(MODE) \
+ CLK(CLK_OP + CLK_W16 + CLK_W_##MODE); \
+ write_16_##MODE(EA_##MODE(cpustate), REG_A)
+#endif
+
+/* M37710 Store B accumulator to memory */
+#undef OP_STB
+#if FLAG_SET_M
+#define OP_STB(MODE) \
+ CLK(CLK_OP + CLK_W8 + CLK_W_##MODE); \
+ write_8_##MODE(EA_##MODE(cpustate), REG_BA)
+#else
+#define OP_STB(MODE) \
+ CLK(CLK_OP + CLK_W16 + CLK_W_##MODE); \
+ write_16_##MODE(EA_##MODE(cpustate), REG_BA)
+#endif
+
+/* M37710 Store index register to memory */
+#undef OP_STX
+#if FLAG_SET_X
+#define OP_STX(REG, MODE) \
+ CLK(CLK_OP + CLK_W8 + CLK_W_##MODE); \
+ write_8_##MODE(EA_##MODE(cpustate), REG)
+#else
+#define OP_STX(REG, MODE) \
+ CLK(CLK_OP + CLK_W16 + CLK_W_##MODE); \
+ write_16_##MODE(EA_##MODE(cpustate), REG)
+#endif
+
+/* M37710 Store zero to memory */
+#undef OP_STZ
+#if FLAG_SET_M
+#define OP_STZ(MODE) \
+ CLK(CLK_OP + CLK_W8 + CLK_W_##MODE); \
+ write_8_##MODE(EA_##MODE(cpustate), 0)
+#else
+#define OP_STZ(MODE) \
+ CLK(CLK_OP + CLK_W16 + CLK_W_##MODE); \
+ write_16_##MODE(EA_##MODE(cpustate), 0)
+#endif
+
+/* M37710 Stop the clock */
+#undef OP_STP
+#define OP_STP() \
+ USE_ALL_CLKS(); \
+ CPU_STOPPED |= STOP_LEVEL_STOP
+
+/* M37710 Transfer accumulator to index */
+#undef OP_TAX
+#if FLAG_SET_M
+#if FLAG_SET_X
+#define OP_TAX(REG) \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REG = REG_A; \
+ FLAG_N = NFLAG_8(FLAG_Z)
+#else /* FLAG_SET_X */
+#define OP_TAX(REG) \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REG = REG_B | REG_A; \
+ FLAG_N = NFLAG_16(FLAG_Z)
+#endif /* FLAG_SET_X */
+#else /* FLAG_SET_M */
+#if FLAG_SET_X
+#define OP_TAX(REG) \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REG = MAKE_UINT_8(REG_A); \
+ FLAG_N = NFLAG_8(FLAG_Z)
+#else /* FLAG_SET_X */
+#define OP_TAX(REG) \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REG = REG_A; \
+ FLAG_N = NFLAG_16(FLAG_Z)
+#endif /* FLAG_SET_X */
+#endif /* FLAG_SET_M */
+
+
+/* M37710 Transfer accumulator B to index */
+#undef OP_TBX
+#if FLAG_SET_M
+#if FLAG_SET_X
+#define OP_TBX(REG) \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REG = REG_BA; \
+ FLAG_N = NFLAG_8(FLAG_Z)
+#else /* FLAG_SET_X */
+#define OP_TBX(REG) \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REG = REG_BB | REG_BA; \
+ FLAG_N = NFLAG_16(FLAG_Z)
+#endif /* FLAG_SET_X */
+#else /* FLAG_SET_M */
+#if FLAG_SET_X
+#define OP_TBX(REG) \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REG = MAKE_UINT_8(REG_BA); \
+ FLAG_N = NFLAG_8(FLAG_Z)
+#else /* FLAG_SET_X */
+#define OP_TBX(REG) \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REG = REG_BA; \
+ FLAG_N = NFLAG_16(FLAG_Z)
+#endif /* FLAG_SET_X */
+#endif /* FLAG_SET_M */
+
+/* M37710 Transfer index to accumulator */
+#undef OP_TXA
+#if FLAG_SET_M
+#define OP_TXA(REG) \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REG_A = MAKE_UINT_8(REG); \
+ FLAG_N = NFLAG_8(FLAG_Z)
+#else
+#define OP_TXA(REG) \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REG_A = REG; \
+ FLAG_N = NFLAG_16(FLAG_Z)
+#endif
+
+/* M37710 Transfer index to accumulator */
+#undef OP_TXB
+#if FLAG_SET_M
+#define OP_TXB(REG) \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REG_BA = MAKE_UINT_8(REG); \
+ FLAG_N = NFLAG_8(FLAG_Z)
+#else
+#define OP_TXB(REG) \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REG_BA = REG; \
+ FLAG_N = NFLAG_16(FLAG_Z)
+#endif
+
+/* M37710 Transfer C to direct register */
+#undef OP_TCD
+#if FLAG_SET_M
+#define OP_TCD() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REG_D = REG_A | REG_B; \
+ FLAG_N = NFLAG_16(FLAG_Z)
+#else
+#define OP_TCD() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REG_D = REG_A; \
+ FLAG_N = NFLAG_16(FLAG_Z)
+#endif
+
+/* M37710 Transfer direct register to C */
+#undef OP_TDC
+#if FLAG_SET_M
+#define OP_TDC() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REG_D; \
+ FLAG_N = NFLAG_16(FLAG_Z); \
+ REG_A = MAKE_UINT_8(REG_D); \
+ REG_B = REG_D & 0xff00
+#else
+#define OP_TDC() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REG_A = REG_D; \
+ FLAG_N = NFLAG_16(FLAG_Z)
+#endif
+
+/* M37710 Transfer C to stack pointer */
+#undef OP_TCS
+#define OP_TCS() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ REG_S = REG_A | REG_B
+
+/* M37710 Transfer stack pointer to C */
+#undef OP_TSC
+#if FLAG_SET_M
+#define OP_TSC() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REG_S; \
+ FLAG_N = NFLAG_16(FLAG_Z); \
+ REG_A = MAKE_UINT_8(REG_S); \
+ REG_B = REG_S & 0xff00
+#else
+#define OP_TSC() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REG_A = REG_S; \
+ FLAG_N = NFLAG_16(FLAG_Z)
+#endif
+
+/* M37710 Transfer stack pointer to X */
+#undef OP_TSX
+#if FLAG_SET_X
+#define OP_TSX() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REG_X = MAKE_UINT_8(REG_S); \
+ FLAG_N = NFLAG_8(FLAG_Z)
+#else
+#define OP_TSX() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REG_X = REG_S; \
+ FLAG_N = NFLAG_16(FLAG_Z)
+#endif
+
+/* M37710 Transfer X to stack pointer */
+#undef OP_TXS
+#define OP_TXS() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ REG_S = REG_X
+
+/* M37710 Transfer X to Y */
+#undef OP_TXY
+#if FLAG_SET_X
+#define OP_TXY() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REG_Y = REG_X; \
+ FLAG_N = NFLAG_8(FLAG_Z)
+#else
+#define OP_TXY() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REG_Y = REG_X; \
+ FLAG_N = NFLAG_16(FLAG_Z)
+#endif
+
+/* M37710 Transfer Y to X */
+#undef OP_TYX
+#if FLAG_SET_X
+#define OP_TYX() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REG_X = REG_Y; \
+ FLAG_N = NFLAG_8(FLAG_Z)
+#else
+#define OP_TYX() \
+ CLK(CLK_OP + CLK_IMPLIED); \
+ FLAG_Z = REG_X = REG_Y; \
+ FLAG_N = NFLAG_16(FLAG_Z)
+#endif
+
+/* M37710 clear bit */
+#undef OP_CLB
+#if FLAG_SET_M
+#define OP_CLB(MODE) \
+ CLK(CLK_OP + CLK_RMW8 + CLK_W_##MODE); \
+ DST = EA_##MODE(cpustate); \
+ REG_IM = read_8_##MODE(DST); \
+ REG_IM2 = read_8_NORM(REG_PB | REG_PC); \
+ REG_PC++; \
+ write_8_##MODE(DST, REG_IM & ~REG_IM2);
+#else
+#define OP_CLB(MODE) \
+ CLK(CLK_OP + CLK_RMW16 + CLK_W_##MODE); \
+ DST = EA_##MODE(cpustate); \
+ REG_IM = read_16_##MODE(DST); \
+ REG_IM2 = read_16_NORM(REG_PB | REG_PC); \
+ REG_PC+=2; \
+ write_16_##MODE(DST, REG_IM & ~REG_IM2);
+#endif
+
+/* M37710 set bit */
+#undef OP_SEB
+#if FLAG_SET_M
+#define OP_SEB(MODE) \
+ CLK(CLK_OP + CLK_RMW8 + CLK_W_##MODE); \
+ DST = EA_##MODE(cpustate); \
+ REG_IM = read_8_##MODE(DST); \
+ REG_IM2 = read_8_NORM(REG_PB | REG_PC); \
+ REG_PC++; \
+ write_8_##MODE(DST, REG_IM | REG_IM2);
+#else
+#define OP_SEB(MODE) \
+ CLK(CLK_OP + CLK_RMW16 + CLK_W_##MODE); \
+ DST = EA_##MODE(cpustate); \
+ REG_IM = read_16_##MODE(DST); \
+ REG_IM2 = read_16_NORM(REG_PB | REG_PC); \
+ REG_PC+=2; \
+ write_16_##MODE(DST, REG_IM | REG_IM2);
+#endif
+
+/* M37710 Wait for interrupt */
+#undef OP_WAI
+#define OP_WAI() \
+ USE_ALL_CLKS(); \
+ CPU_STOPPED |= STOP_LEVEL_WAI
+
+/* M37710 prefix for B accumulator (0x42) */
+/* There is a 2 cycle penalty for all instructions using this prefix */
+#undef OP_PFB
+#define OP_PFB() \
+ CLK(2); \
+ REG_IR = read_8_IMM(REG_PB | REG_PC); \
+ REG_PC++; \
+ cpustate->opcodes42[REG_IR](cpustate);
+
+
+/* M37710 prefix for multiply / divide instructions (0x89) */
+#undef OP_PFXM
+#define OP_PFXM() \
+ REG_IR = read_8_IMM(REG_PB | REG_PC); \
+ REG_PC++; \
+ cpustate->opcodes89[REG_IR](cpustate);
+
+
+/* M37710 unimplemented opcode */
+#undef OP_UNIMP
+#define OP_UNIMP() \
+ logerror("fatalerror: M37710: UNIMPLEMENTED OPCODE! K=%x PC=%x", REG_PB, REG_PPC);
+
+/* M37710 load data bank register */
+#undef OP_LDTAAA
+#define OP_LDT(MODE) \
+ CLK(CLK_OP + CLK_R8 + CLK_##MODE); \
+ REG_DB = OPER_8_##MODE(cpustate)<<16;
+
+/* ======================================================================== */
+/* ======================== OPCODE & FUNCTION TABLES ====================== */
+/* ======================================================================== */
+
+#undef OP
+#undef O
+#undef TABLE_OPCODES
+#undef TABLE_FUNCTION
+
+#if !FLAG_SET_M && !FLAG_SET_X
+#define OP(CODE, OPERATION) static void m37710i_ ## CODE ## _M0X0(m37710i_cpu_struct *cpustate) {OPERATION;}
+#define O(CODE) m37710i_ ## CODE ## _M0X0
+#define TABLE_OPCODES void (*const m37710i_opcodes_M0X0[256])(m37710i_cpu_struct *cpustate)
+#define TABLE_OPCODES2 void (*const m37710i_opcodes42_M0X0[256])(m37710i_cpu_struct *cpustate)
+#define TABLE_OPCODES3 void (*const m37710i_opcodes89_M0X0[256])(m37710i_cpu_struct *cpustate)
+#define TABLE_FUNCTION(RTYPE, NAME, ARGS) RTYPE m37710i_ ## NAME ## _M0X0 ARGS
+
+#elif !FLAG_SET_M && FLAG_SET_X
+
+#define OP(CODE, OPERATION) static void m37710i_ ## CODE ## _M0X1(m37710i_cpu_struct *cpustate) {OPERATION;}
+#define O(CODE) m37710i_ ## CODE ## _M0X1
+#define TABLE_OPCODES void (*const m37710i_opcodes_M0X1[256])(m37710i_cpu_struct *cpustate)
+#define TABLE_OPCODES2 void (*const m37710i_opcodes42_M0X1[256])(m37710i_cpu_struct *cpustate)
+#define TABLE_OPCODES3 void (*const m37710i_opcodes89_M0X1[256])(m37710i_cpu_struct *cpustate)
+#define TABLE_FUNCTION(RTYPE, NAME, ARGS) RTYPE m37710i_ ## NAME ## _M0X1 ARGS
+
+#elif FLAG_SET_M && !FLAG_SET_X
+
+#define OP(CODE, OPERATION) static void m37710i_ ## CODE ## _M1X0(m37710i_cpu_struct *cpustate) {OPERATION;}
+#define O(CODE) m37710i_ ## CODE ## _M1X0
+#define TABLE_OPCODES void (*const m37710i_opcodes_M1X0[256])(m37710i_cpu_struct *cpustate)
+#define TABLE_OPCODES2 void (*const m37710i_opcodes42_M1X0[256])(m37710i_cpu_struct *cpustate)
+#define TABLE_OPCODES3 void (*const m37710i_opcodes89_M1X0[256])(m37710i_cpu_struct *cpustate)
+#define TABLE_FUNCTION(RTYPE, NAME, ARGS) RTYPE m37710i_ ## NAME ## _M1X0 ARGS
+
+#elif FLAG_SET_M && FLAG_SET_X
+
+#define OP(CODE, OPERATION) static void m37710i_ ## CODE ## _M1X1(m37710i_cpu_struct *cpustate) {OPERATION;}
+#define O(CODE) m37710i_ ## CODE ## _M1X1
+#define TABLE_OPCODES void (*const m37710i_opcodes_M1X1[256])(m37710i_cpu_struct *cpustate)
+#define TABLE_OPCODES2 void (*const m37710i_opcodes42_M1X1[256])(m37710i_cpu_struct *cpustate)
+#define TABLE_OPCODES3 void (*const m37710i_opcodes89_M1X1[256])(m37710i_cpu_struct *cpustate)
+#define TABLE_FUNCTION(RTYPE, NAME, ARGS) RTYPE m37710i_ ## NAME ## _M1X1 ARGS
+
+#endif
+
+#define BREAKOUT return
+
+/* OP FUNCTION Comment */
+OP(00, OP_BRK ( ) ) /* BRK */
+OP(01, OP_ORA ( DXI ) ) /* ORA dxi */
+OP(02, OP_NOP ( ) ) /* unused */
+OP(03, OP_ORA ( S ) ) /* ORA s (G) */
+OP(04, OP_SEB ( D ) ) /* SEB d (C) */
+OP(05, OP_ORA ( D ) ) /* ORA d */
+OP(06, OP_ASLM ( D ) ) /* ASL d */
+OP(07, OP_ORA ( DLI ) ) /* ORA dli (G) */
+OP(08, OP_PHP ( ) ) /* PHP */
+OP(09, OP_ORA ( IMM ) ) /* ORA imm */
+OP(0a, OP_ASL ( ) ) /* ASL acc */
+OP(0b, OP_PHD ( ) ) /* PHD (G) */
+OP(0c, OP_SEB ( A ) ) /* SEB a (C) */
+OP(0d, OP_ORA ( A ) ) /* ORA a */
+OP(0e, OP_ASLM ( A ) ) /* ASL a */
+OP(0f, OP_ORA ( AL ) ) /* ORA al (G) */
+OP(10, OP_BCC ( COND_PL() ) ) /* BPL */
+OP(11, OP_ORA ( DIY ) ) /* ORA diy */
+OP(12, OP_ORA ( DI ) ) /* ORA di (C) */
+OP(13, OP_ORA ( SIY ) ) /* ORA siy (G) */
+OP(14, OP_CLB ( D ) ) /* CLB d (C) */
+OP(15, OP_ORA ( DX ) ) /* ORA dx */
+OP(16, OP_ASLM ( DX ) ) /* ASL dx */
+OP(17, OP_ORA ( DLIY ) ) /* ORA dliy(C) */
+OP(18, OP_CLC ( ) ) /* CLC */
+OP(19, OP_ORA ( AY ) ) /* ORA ay */
+OP(1a, OP_DEC ( ) ) /* DEA (C) */
+OP(1b, OP_TCS ( ) ) /* TCS (G) */
+OP(1c, OP_CLB ( A ) ) /* CLB a (C) */
+OP(1d, OP_ORA ( AX ) ) /* ORA ax */
+OP(1e, OP_ASLM ( AX ) ) /* ASL ax */
+OP(1f, OP_ORA ( ALX ) ) /* ORA alx (G) */
+OP(20, OP_JSR ( A ) ) /* JSR a */
+OP(21, OP_AND ( DXI ) ) /* AND dxi */
+OP(22, OP_JSL ( AL ) ) /* JSL al (G) */
+OP(23, OP_AND ( S ) ) /* AND s (G) */
+OP(24, OP_BBS ( D ) ) /* BBS d */
+OP(25, OP_AND ( D ) ) /* AND d */
+OP(26, OP_ROLM ( D ) ) /* ROL d */
+OP(27, OP_AND ( DLI ) ) /* AND dli (G) */
+OP(28, OP_PLP ( ) ) /* PLP */
+OP(29, OP_AND ( IMM ) ) /* AND imm */
+OP(2a, OP_ROL ( ) ) /* ROL acc */
+OP(2b, OP_PLD ( ) ) /* PLD (G) */
+OP(2c, OP_BBS ( A ) ) /* BBS a */
+OP(2d, OP_AND ( A ) ) /* AND a */
+OP(2e, OP_ROLM ( A ) ) /* ROL a */
+OP(2f, OP_AND ( AL ) ) /* AND al (G) */
+OP(30, OP_BCC ( COND_MI() ) ) /* BMI */
+OP(31, OP_AND ( DIY ) ) /* AND diy */
+OP(32, OP_AND ( DI ) ) /* AND di (C) */
+OP(33, OP_AND ( SIY ) ) /* AND siy */
+OP(34, OP_BBC ( D ) ) /* BBC d */
+OP(35, OP_AND ( DX ) ) /* AND dx */
+OP(36, OP_ROLM ( DX ) ) /* ROL dx */
+OP(37, OP_AND ( DLIY ) ) /* AND dliy(G) */
+OP(38, OP_SEC ( ) ) /* SEC */
+OP(39, OP_AND ( AY ) ) /* AND ay */
+OP(3a, OP_INC ( ) ) /* INA (C) */
+OP(3b, OP_TSC ( ) ) /* TSC (G) */
+OP(3c, OP_BBC ( A ) ) /* BBC a */
+OP(3d, OP_AND ( AX ) ) /* AND ax */
+OP(3e, OP_ROLM ( AX ) ) /* ROL ax */
+OP(3f, OP_AND ( ALX ) ) /* AND alx (G) */
+OP(40, OP_RTI ( ) ) /* RTI */
+OP(41, OP_EOR ( DXI ) ) /* EOR dxi */
+OP(42, OP_PFB ( ) ) /* prefix for "B" accumulator */
+OP(43, OP_EOR ( S ) ) /* EOR s (G) */
+OP(44, OP_MVP ( ) ) /* MVP (G) */
+OP(45, OP_EOR ( D ) ) /* EOR d */
+OP(46, OP_LSRM ( D ) ) /* LSR d */
+OP(47, OP_EOR ( DLI ) ) /* EOR dli (G) */
+OP(48, OP_PHA ( ) ) /* PHA */
+OP(49, OP_EOR ( IMM ) ) /* EOR imm */
+OP(4a, OP_LSR ( ) ) /* LSR acc */
+OP(4b, OP_PHK ( ) ) /* PHK (G) */
+OP(4c, OP_JMP ( A ) ) /* JMP a */
+OP(4d, OP_EOR ( A ) ) /* EOR a */
+OP(4e, OP_LSRM ( A ) ) /* LSR a */
+OP(4f, OP_EOR ( AL ) ) /* EOR al (G) */
+OP(50, OP_BCC ( COND_VC() ) ) /* BVC */
+OP(51, OP_EOR ( DIY ) ) /* EOR diy */
+OP(52, OP_EOR ( DI ) ) /* EOR di (C) */
+OP(53, OP_EOR ( SIY ) ) /* EOR siy (G) */
+OP(54, OP_MVN ( ) ) /* MVN (G) */
+OP(55, OP_EOR ( DX ) ) /* EOR dx */
+OP(56, OP_LSRM ( DX ) ) /* LSR dx */
+OP(57, OP_EOR ( DLIY ) ) /* EOR dliy(G) */
+OP(58, OP_CLI ( ) ) /* CLI */
+OP(59, OP_EOR ( AY ) ) /* EOR ay */
+OP(5a, OP_PHX ( REG_Y ) ) /* PHY (C) */
+OP(5b, OP_TCD ( ) ) /* TCD (G) */
+OP(5c, OP_JMPAL( ) ) /* JMP al (G) */
+OP(5d, OP_EOR ( AX ) ) /* EOR ax */
+OP(5e, OP_LSRM ( AX ) ) /* LSR ax */
+OP(5f, OP_EOR ( ALX ) ) /* EOR alx (G) */
+OP(60, OP_RTS ( ) ) /* RTS */
+OP(61, OP_ADC ( DXI ) ) /* ADC dxi */
+OP(62, OP_PER ( ) ) /* PER (G) */
+OP(63, OP_ADC ( S ) ) /* ADC s (G) */
+OP(64, OP_LDM ( D ) ) /* LDM d (C) */
+OP(65, OP_ADC ( D ) ) /* ADC d */
+OP(66, OP_RORM ( D ) ) /* ROR d */
+OP(67, OP_ADC ( DLI ) ) /* ADC dli (G) */
+OP(68, OP_PLA ( ) ) /* PLA */
+OP(69, OP_ADC ( IMM ) ) /* ADC imm */
+OP(6a, OP_ROR ( ) ) /* ROR acc */
+OP(6b, OP_RTL ( ) ) /* RTL (G) */
+OP(6c, OP_JMP ( AI ) ) /* JMP ai */
+OP(6d, OP_ADC ( A ) ) /* ADC a */
+OP(6e, OP_RORM ( A ) ) /* ROR a */
+OP(6f, OP_ADC ( AL ) ) /* ADC al (G) */
+OP(70, OP_BCC ( COND_VS() ) ) /* BVS */
+OP(71, OP_ADC ( DIY ) ) /* ADC diy */
+OP(72, OP_ADC ( DI ) ) /* ADC di (G) */
+OP(73, OP_ADC ( SIY ) ) /* ADC siy (G) */
+OP(74, OP_LDM ( DX ) ) /* LDM dx (C) */
+OP(75, OP_ADC ( DX ) ) /* ADC dx */
+OP(76, OP_RORM ( DX ) ) /* ROR dx */
+OP(77, OP_ADC ( DLIY ) ) /* ADC dliy(G) */
+OP(78, OP_SEI ( ) ) /* SEI */
+OP(79, OP_ADC ( AY ) ) /* ADC ay */
+OP(7a, OP_PLX ( REG_Y ) ) /* PLY (C) */
+OP(7b, OP_TDC ( ) ) /* TDC (G) */
+OP(7c, OP_JMPAXI( ) ) /* JMP axi (C) */
+OP(7d, OP_ADC ( AX ) ) /* ADC ax */
+OP(7e, OP_RORM ( AX ) ) /* ROR ax */
+OP(7f, OP_ADC ( ALX ) ) /* ADC alx (G) */
+OP(80, OP_BRA ( ) ) /* BRA (C) */
+OP(81, OP_STA ( DXI ) ) /* STA dxi */
+OP(82, OP_BRL ( ) ) /* BRL (G) */
+OP(83, OP_STA ( S ) ) /* STA s (G) */
+OP(84, OP_STX ( REG_Y, D ) ) /* STY d */
+OP(85, OP_STA ( D ) ) /* STA d */
+OP(86, OP_STX ( REG_X, D ) ) /* STX d */
+OP(87, OP_STA ( DLI ) ) /* STA dli (G) */
+OP(88, OP_DECX ( REG_Y ) ) /* DEY */
+OP(89, OP_PFXM ( ) ) /* prefix for mul/div insns */
+OP(8a, OP_TXA ( REG_X ) ) /* TXA */
+OP(8b, OP_PHT ( ) ) /* PHT (G) */
+OP(8c, OP_STX ( REG_Y, A ) ) /* STY a */
+OP(8d, OP_STA ( A ) ) /* STA a */
+OP(8e, OP_STX ( REG_X, A ) ) /* STX a */
+OP(8f, OP_STA ( AL ) ) /* STA al (G) */
+OP(90, OP_BCC ( COND_CC() ) ) /* BCC */
+OP(91, OP_STA ( DIY ) ) /* STA diy */
+OP(92, OP_STA ( DI ) ) /* STA di (C) */
+OP(93, OP_STA ( SIY ) ) /* STA siy (G) */
+OP(94, OP_STX ( REG_Y, DX ) ) /* STY dx */
+OP(95, OP_STA ( DX ) ) /* STA dx */
+OP(96, OP_STX ( REG_X, DY ) ) /* STX dy */
+OP(97, OP_STA ( DLIY ) ) /* STA dliy(G) */
+OP(98, OP_TXA ( REG_Y ) ) /* TYA */
+OP(99, OP_STA ( AY ) ) /* STA ay */
+OP(9a, OP_TXS ( ) ) /* TXS */
+OP(9b, OP_TXY ( ) ) /* TXY (G) */
+OP(9c, OP_LDM ( A ) ) /* LDM a (C) */
+OP(9d, OP_STA ( AX ) ) /* STA ax */
+OP(9e, OP_LDM ( AX ) ) /* LDM ax (C) */
+OP(9f, OP_STA ( ALX ) ) /* STA alx (G) */
+OP(a0, OP_LDX ( REG_Y, IMM ) ) /* LDY imm */
+OP(a1, OP_LDA ( DXI ) ) /* LDA dxi */
+OP(a2, OP_LDX ( REG_X, IMM ) ) /* LDX imm */
+OP(a3, OP_LDA ( S ) ) /* LDA s (G) */
+OP(a4, OP_LDX ( REG_Y, D ) ) /* LDY d */
+OP(a5, OP_LDA ( D ) ) /* LDA d */
+OP(a6, OP_LDX ( REG_X, D ) ) /* LDX d */
+OP(a7, OP_LDA ( DLI ) ) /* LDA dli (G) */
+OP(a8, OP_TAX ( REG_Y ) ) /* TAY */
+OP(a9, OP_LDA ( IMM ) ) /* LDA imm */
+OP(aa, OP_TAX ( REG_X ) ) /* TAX */
+OP(ab, OP_PLT ( ) ) /* PLT (G) */
+OP(ac, OP_LDX ( REG_Y, A ) ) /* LDY a */
+OP(ad, OP_LDA ( A ) ) /* LDA a */
+OP(ae, OP_LDX ( REG_X, A ) ) /* LDX a */
+OP(af, OP_LDA ( AL ) ) /* LDA al (G) */
+OP(b0, OP_BCC ( COND_CS() ) ) /* BCS */
+OP(b1, OP_LDA ( DIY ) ) /* LDA diy */
+OP(b2, OP_LDA ( DI ) ) /* LDA di (C) */
+OP(b3, OP_LDA ( SIY ) ) /* LDA siy (G) */
+OP(b4, OP_LDX ( REG_Y, DX ) ) /* LDY dx */
+OP(b5, OP_LDA ( DX ) ) /* LDA dx */
+OP(b6, OP_LDX ( REG_X, DY ) ) /* LDX dy */
+OP(b7, OP_LDA ( DLIY ) ) /* LDA dliy(G) */
+OP(b8, OP_CLV ( ) ) /* CLV */
+OP(b9, OP_LDA ( AY ) ) /* LDA ay */
+OP(ba, OP_TSX ( ) ) /* TSX */
+OP(bb, OP_TYX ( ) ) /* TYX (G) */
+OP(bc, OP_LDX ( REG_Y, AX ) ) /* LDY ax */
+OP(bd, OP_LDA ( AX ) ) /* LDA ax */
+OP(be, OP_LDX ( REG_X, AY ) ) /* LDX ay */
+OP(bf, OP_LDA ( ALX ) ) /* LDA alx (G) */
+OP(c0, OP_CMPX ( REG_Y, IMM ) ) /* CPY imm */
+OP(c1, OP_CMP ( DXI ) ) /* CMP dxi */
+OP(c2, OP_REP ( ) ) /* REP (G) */
+OP(c3, OP_CMP ( S ) ) /* CMP s (G) */
+OP(c4, OP_CMPX ( REG_Y, D ) ) /* CPY d */
+OP(c5, OP_CMP ( D ) ) /* CMP d */
+OP(c6, OP_DECM ( D ) ) /* DEC d */
+OP(c7, OP_CMP ( DLI ) ) /* CMP dli (G) */
+OP(c8, OP_INCX ( REG_Y ) ) /* INY */
+OP(c9, OP_CMP ( IMM ) ) /* CMP imm */
+OP(ca, OP_DECX ( REG_X ) ) /* DEX */
+OP(cb, OP_WAI ( ) ) /* WAI (G) */
+OP(cc, OP_CMPX ( REG_Y, A ) ) /* CPY a */
+OP(cd, OP_CMP ( A ) ) /* CMP a */
+OP(ce, OP_DECM ( A ) ) /* DEC a */
+OP(cf, OP_CMP ( AL ) ) /* CMP al (G) */
+OP(d0, OP_BCC ( COND_NE() ) ) /* BNE */
+OP(d1, OP_CMP ( DIY ) ) /* CMP diy */
+OP(d2, OP_CMP ( DI ) ) /* CMP di (C) */
+OP(d3, OP_CMP ( SIY ) ) /* CMP siy (G) */
+OP(d4, OP_PEI ( ) ) /* PEI (G) */
+OP(d5, OP_CMP ( DX ) ) /* CMP dx */
+OP(d6, OP_DECM ( DX ) ) /* DEC dx */
+OP(d7, OP_CMP ( DLIY ) ) /* CMP dliy(G) */
+OP(d8, OP_CLM ( ) ) /* CLM */
+OP(d9, OP_CMP ( AY ) ) /* CMP ay */
+OP(da, OP_PHX ( REG_X ) ) /* PHX (C) */
+OP(db, OP_STP ( ) ) /* STP (G) */
+OP(dc, OP_JMLAI( ) ) /* JML ai (G) */
+OP(dd, OP_CMP ( AX ) ) /* CMP ax */
+OP(de, OP_DECM ( AX ) ) /* DEC ax */
+OP(df, OP_CMP ( ALX ) ) /* CMP alx (G) */
+OP(e0, OP_CMPX ( REG_X, IMM ) ) /* CPX imm */
+OP(e1, OP_SBC ( DXI ) ) /* SBC dxi */
+OP(e2, OP_SEP ( ) ) /* SEP imm (G) */
+OP(e3, OP_SBC ( S ) ) /* SBC s (G) */
+OP(e4, OP_CMPX ( REG_X, D ) ) /* CPX d */
+OP(e5, OP_SBC ( D ) ) /* SBC d */
+OP(e6, OP_INCM ( D ) ) /* INC d */
+OP(e7, OP_SBC ( DLI ) ) /* SBC dli (G) */
+OP(e8, OP_INCX ( REG_X ) ) /* INX */
+OP(e9, OP_SBC ( IMM ) ) /* SBC imm */
+OP(ea, OP_NOP ( ) ) /* NOP */
+OP(eb, OP_PSH ( IMM ) ) /* PSH imm */
+OP(ec, OP_CMPX ( REG_X, A ) ) /* CPX a */
+OP(ed, OP_SBC ( A ) ) /* SBC a */
+OP(ee, OP_INCM ( A ) ) /* INC a */
+OP(ef, OP_SBC ( AL ) ) /* SBC al (G) */
+OP(f0, OP_BCC ( COND_EQ() ) ) /* BEQ */
+OP(f1, OP_SBC ( DIY ) ) /* SBC diy */
+OP(f2, OP_SBC ( DI ) ) /* SBC di (C) */
+OP(f3, OP_SBC ( SIY ) ) /* SBC siy (G) */
+OP(f4, OP_PEA ( ) ) /* PEA (G) */
+OP(f5, OP_SBC ( DX ) ) /* SBC dx */
+OP(f6, OP_INCM ( DX ) ) /* INC dx */
+OP(f7, OP_SBC ( DLIY ) ) /* SBC dliy(G) */
+OP(f8, OP_SEM ( ) ) /* SEM */
+OP(f9, OP_SBC ( AY ) ) /* SBC ay */
+OP(fa, OP_PLX ( REG_X ) ) /* PLX (C) */
+OP(fb, OP_PUL ( IMM ) ) /* PUL imm */
+OP(fc, OP_JSRAXI( ) ) /* JSR axi (G) */
+OP(fd, OP_SBC ( AX ) ) /* SBC ax */
+OP(fe, OP_INCM ( AX ) ) /* INC ax */
+OP(ff, OP_SBC ( ALX ) ) /* SBC alx (G) */
+OP(101, OP_ORB ( DXI ) ) /* ORB dxi */
+OP(103, OP_ORB ( S ) ) /* ORB s (G) */
+OP(105, OP_ORB ( D ) ) /* ORB d */
+OP(107, OP_ORB ( DLI ) ) /* ORB dli (G) */
+OP(109, OP_ORB ( IMM ) ) /* ORB imm */
+OP(10a, OP_BSL ( ) ) /* BSL acc */
+OP(10d, OP_ORB ( A ) ) /* ORB a */
+OP(10f, OP_ORB ( AL ) ) /* ORB al (G) */
+OP(111, OP_ORB ( DIY ) ) /* ORB diy */
+OP(112, OP_ORB ( DI ) ) /* ORB di (C) */
+OP(113, OP_ORB ( SIY ) ) /* ORB siy (G) */
+OP(115, OP_ORB ( DX ) ) /* ORB dx */
+OP(117, OP_ORB ( DLIY ) ) /* ORB dliy(C) */
+OP(119, OP_ORB ( AY ) ) /* ORB ay */
+OP(11a, OP_DECB ( ) ) /* DEB (C) */
+OP(11d, OP_ORB ( AX ) ) /* ORB ax */
+OP(11f, OP_ORB ( ALX ) ) /* ORB alx (G) */
+OP(129, OP_ANDB ( IMM ) ) /* ANDB imm */
+OP(12a, OP_ROLB ( ) ) /* ROL Bacc */
+OP(13a, OP_INCB ( ) ) /* INB (C) */
+OP(148, OP_PHAB ( ) ) /* PHB */
+OP(149, OP_EORB ( IMM ) ) /* EORB imm */
+OP(14a, OP_LSRB ( ) ) /* LSRB acc */
+OP(161, OP_ADCB ( DXI ) ) /* ADCB dxi */
+OP(163, OP_ADCB ( S ) ) /* ADCB s (G) */
+OP(165, OP_ADCB ( D ) ) /* ADCB d */
+OP(167, OP_ADCB ( DLI ) ) /* ADCB dli (G) */
+OP(168, OP_PLAB ( ) ) /* PLB */
+OP(169, OP_ADCB ( IMM ) ) /* ADCB imm */
+OP(16a, OP_RORB ( ) ) /* ROR Bacc */
+OP(16d, OP_ADCB ( A ) ) /* ADCB a */
+OP(16f, OP_ADCB ( AL ) ) /* ADCB al (G) */
+OP(171, OP_ADCB ( DIY ) ) /* ADCB diy */
+OP(172, OP_ADCB ( DI ) ) /* ADCB di (G) */
+OP(173, OP_ADCB ( SIY ) ) /* ADCB siy (G) */
+OP(175, OP_ADCB ( DX ) ) /* ADCB dx */
+OP(177, OP_ADCB ( DLIY ) ) /* ADCB dliy(G) */
+OP(179, OP_ADCB ( AY ) ) /* ADCB ay */
+OP(17d, OP_ADCB ( AX ) ) /* ADCB ax */
+OP(17f, OP_ADCB ( ALX ) ) /* ADCB alx (G) */
+OP(181, OP_STB ( DXI ) ) /* STB dxi */
+OP(183, OP_STB ( S ) ) /* STB s (G) */
+OP(185, OP_STB ( D ) ) /* STB d */
+OP(187, OP_STB ( DLI ) ) /* STB dli (G) */
+OP(18a, OP_TXB ( REG_X ) ) /* TXB */
+OP(18d, OP_STB ( A ) ) /* STB a */
+OP(18f, OP_STB ( AL ) ) /* STB al (G) */
+OP(191, OP_STB ( DIY ) ) /* STB diy */
+OP(192, OP_STB ( DI ) ) /* STB di (C) */
+OP(193, OP_STB ( SIY ) ) /* STB siy (G) */
+OP(195, OP_STB ( DX ) ) /* STB dx */
+OP(197, OP_STB ( DLIY ) ) /* STB dliy(G) */
+OP(198, OP_TXB ( REG_Y ) ) /* TYB */
+OP(199, OP_STB ( AY ) ) /* STB ay */
+OP(19d, OP_STB ( AX ) ) /* STB ax */
+OP(19f, OP_STB ( ALX ) ) /* STB alx (G) */
+OP(1a1, OP_LDB ( DXI ) ) /* LDB dxi */
+OP(1a5, OP_LDB ( D ) ) /* LDB d */
+OP(1a8, OP_TBX ( REG_Y ) ) /* TBY */
+OP(1a9, OP_LDB ( IMM ) ) /* LDB imm */
+OP(1aa, OP_TBX ( REG_X ) ) /* TBX */
+OP(1ad, OP_LDB ( A ) ) /* LDB a */
+OP(1b2, OP_LDB ( DI ) ) /* LDB di (C) */
+OP(1b5, OP_LDB ( DX ) ) /* LDB dx */
+OP(1b9, OP_LDB ( AY ) ) /* LDB ay */
+OP(1bd, OP_LDB ( AX ) ) /* LDB ax */
+OP(1c1, OP_CMPB ( DXI ) ) /* CMPB dxi */
+OP(1c3, OP_CMPB ( S ) ) /* CMPB s (G) */
+OP(1c5, OP_CMPB ( D ) ) /* CMPB d */
+OP(1c7, OP_CMPB ( DLI ) ) /* CMPB dli (G) */
+OP(1c9, OP_CMPB ( IMM ) ) /* CMPB imm */
+OP(1cd, OP_CMPB ( A ) ) /* CMPB a */
+OP(1cf, OP_CMPB ( AL ) ) /* CMPB al (G) */
+OP(1d1, OP_CMPB ( DIY ) ) /* CMPB diy */
+OP(1d2, OP_CMPB ( DI ) ) /* CMPB di (C) */
+OP(1d3, OP_CMPB ( SIY ) ) /* CMPB siy (G) */
+OP(1d5, OP_CMPB ( DX ) ) /* CMPB dx */
+OP(1d7, OP_CMPB ( DLIY ) ) /* CMPB dliy(G) */
+OP(1d9, OP_CMPB ( AY ) ) /* CMPB ay */
+OP(1dd, OP_CMPB ( AX ) ) /* CMPB ax */
+OP(1df, OP_CMPB ( ALX ) ) /* CMPB alx (G) */
+OP(1e9, OP_SBCB ( IMM ) ) /* SBCB imm */
+OP(1f5, OP_SBCB ( DX ) ) /* SBCB dx */
+OP(200, OP_UNIMP ( ) ) /* unimplemented */
+OP(203, OP_MPY ( S ) ) /* MPY s */
+OP(205, OP_MPY ( D ) ) /* MPY d */
+OP(209, OP_MPY ( IMM ) ) /* MPY imm */
+OP(215, OP_MPY ( DX ) ) /* MPY dx */
+OP(219, OP_MPY ( AY ) ) /* MPY ay */
+OP(225, OP_DIV ( D ) ) /* DIV d */
+OP(228, OP_XAB ( ) ) /* XAB */
+OP(235, OP_DIV ( DX ) ) /* DIV dx */
+OP(249, OP_RLA ( IMM ) ) /* RLA imm */
+OP(2c2, OP_LDT ( IMM ) ) /* LDT imm */
+
+extern TABLE_OPCODES;
+TABLE_OPCODES =
+{
+ O(00),O(01),O(02),O(03),O(04),O(05),O(06),O(07),
+ O(08),O(09),O(0a),O(0b),O(0c),O(0d),O(0e),O(0f),
+ O(10),O(11),O(12),O(13),O(14),O(15),O(16),O(17),
+ O(18),O(19),O(1a),O(1b),O(1c),O(1d),O(1e),O(1f),
+ O(20),O(21),O(22),O(23),O(24),O(25),O(26),O(27),
+ O(28),O(29),O(2a),O(2b),O(2c),O(2d),O(2e),O(2f),
+ O(30),O(31),O(32),O(33),O(34),O(35),O(36),O(37),
+ O(38),O(39),O(3a),O(3b),O(3c),O(3d),O(3e),O(3f),
+ O(40),O(41),O(42),O(43),O(44),O(45),O(46),O(47),
+ O(48),O(49),O(4a),O(4b),O(4c),O(4d),O(4e),O(4f),
+ O(50),O(51),O(52),O(53),O(54),O(55),O(56),O(57),
+ O(58),O(59),O(5a),O(5b),O(5c),O(5d),O(5e),O(5f),
+ O(60),O(61),O(62),O(63),O(64),O(65),O(66),O(67),
+ O(68),O(69),O(6a),O(6b),O(6c),O(6d),O(6e),O(6f),
+ O(70),O(71),O(72),O(73),O(74),O(75),O(76),O(77),
+ O(78),O(79),O(7a),O(7b),O(7c),O(7d),O(7e),O(7f),
+ O(80),O(81),O(82),O(83),O(84),O(85),O(86),O(87),
+ O(88),O(89),O(8a),O(8b),O(8c),O(8d),O(8e),O(8f),
+ O(90),O(91),O(92),O(93),O(94),O(95),O(96),O(97),
+ O(98),O(99),O(9a),O(9b),O(9c),O(9d),O(9e),O(9f),
+ O(a0),O(a1),O(a2),O(a3),O(a4),O(a5),O(a6),O(a7),
+ O(a8),O(a9),O(aa),O(ab),O(ac),O(ad),O(ae),O(af),
+ O(b0),O(b1),O(b2),O(b3),O(b4),O(b5),O(b6),O(b7),
+ O(b8),O(b9),O(ba),O(bb),O(bc),O(bd),O(be),O(bf),
+ O(c0),O(c1),O(c2),O(c3),O(c4),O(c5),O(c6),O(c7),
+ O(c8),O(c9),O(ca),O(cb),O(cc),O(cd),O(ce),O(cf),
+ O(d0),O(d1),O(d2),O(d3),O(d4),O(d5),O(d6),O(d7),
+ O(d8),O(d9),O(da),O(db),O(dc),O(dd),O(de),O(df),
+ O(e0),O(e1),O(e2),O(e3),O(e4),O(e5),O(e6),O(e7),
+ O(e8),O(e9),O(ea),O(eb),O(ec),O(ed),O(ee),O(ef),
+ O(f0),O(f1),O(f2),O(f3),O(f4),O(f5),O(f6),O(f7),
+ O(f8),O(f9),O(fa),O(fb),O(fc),O(fd),O(fe),O(ff)
+};
+
+extern TABLE_OPCODES2;
+TABLE_OPCODES2 =
+{
+ O(200),O(101),O(200),O(103),O(200),O(105),O(200),O(107),
+ O(200),O(109),O(10a),O(200),O(200),O(10d),O(200),O(10f),
+ O(200),O(111),O(112),O(113),O(200),O(115),O(200),O(117), // 10
+ O(200),O(119),O(11a),O(200),O(200),O(11d),O(200),O(11f),
+ O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200), // 20
+ O(200),O(129),O(12a),O(200),O(200),O(200),O(200),O(200),
+ O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200), // 30
+ O(200),O(200),O(13a),O(200),O(200),O(200),O(200),O(200),
+ O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200), // 40
+ O(148),O(149),O(14a),O(200),O(200),O(200),O(200),O(200),
+ O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200), // 50
+ O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200),
+ O(200),O(161),O(200),O(163),O(200),O(165),O(200),O(167), // 60
+ O(168),O(169),O(16a),O(200),O(200),O(16d),O(200),O(16f),
+ O(200),O(171),O(172),O(173),O(200),O(175),O(200),O(177), // 70
+ O(200),O(179),O(200),O(200),O(200),O(17d),O(200),O(17f),
+ O(200),O(181),O(200),O(183),O(200),O(185),O(200),O(187), // 80
+ O(200),O(200),O(18a),O(200),O(200),O(18d),O(200),O(18f),
+ O(200),O(191),O(192),O(193),O(200),O(195),O(200),O(197), // 90
+ O(198),O(199),O(200),O(200),O(200),O(19d),O(200),O(19f),
+ O(200),O(1a1),O(200),O(200),O(200),O(1a5),O(200),O(200), // a0
+ O(1a8),O(1a9),O(1aa),O(200),O(200),O(1ad),O(200),O(200),
+ O(200),O(200),O(1b2),O(200),O(200),O(1b5),O(200),O(200), // b0
+ O(200),O(1b9),O(200),O(200),O(200),O(1bd),O(200),O(200),
+ O(200),O(1c1),O(200),O(1c3),O(200),O(1c5),O(200),O(1c7), // c0
+ O(200),O(1c9),O(200),O(200),O(200),O(1cd),O(200),O(1cf),
+ O(200),O(1d1),O(1d2),O(1d3),O(200),O(1d5),O(200),O(1d7), // d0
+ O(200),O(1d9),O(200),O(200),O(200),O(1dd),O(200),O(1df),
+ O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200), // e0
+ O(200),O(1e9),O(200),O(200),O(200),O(200),O(200),O(200),
+ O(200),O(200),O(200),O(200),O(200),O(1f5),O(200),O(200), // f0
+ O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200)
+};
+
+extern TABLE_OPCODES3;
+TABLE_OPCODES3 =
+{
+ O(200),O(200),O(200),O(203),O(200),O(205),O(200),O(200),
+ O(200),O(209),O(200),O(200),O(200),O(200),O(200),O(200),
+ O(200),O(200),O(200),O(200),O(200),O(215),O(200),O(200), // 10
+ O(200),O(219),O(200),O(200),O(200),O(200),O(200),O(200),
+ O(200),O(200),O(200),O(200),O(200),O(225),O(200),O(200), // 20
+ O(228),O(200),O(200),O(200),O(200),O(200),O(200),O(200),
+ O(200),O(200),O(200),O(200),O(200),O(235),O(200),O(200), // 30
+ O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200),
+ O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200), // 40
+ O(200),O(249),O(200),O(200),O(200),O(200),O(200),O(200),
+ O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200), // 50
+ O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200),
+ O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200), // 60
+ O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200),
+ O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200), // 70
+ O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200),
+ O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200), // 80
+ O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200),
+ O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200), // 90
+ O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200),
+ O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200), // a0
+ O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200),
+ O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200), // b0
+ O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200),
+ O(200),O(200),O(2c2),O(200),O(200),O(200),O(200),O(200), // c0
+ O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200),
+ O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200), // d0
+ O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200),
+ O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200), // e0
+ O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200),
+ O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200), // f0
+ O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200)
+};
+
+extern const int m37710_irq_levels[M37710_LINE_MAX];
+
+/* Assert or clear a line on the CPU */
+TABLE_FUNCTION(void, set_line, (m37710i_cpu_struct *cpustate, int line, int state))
+{
+ switch(line)
+ {
+ // maskable interrupts
+ case M37710_LINE_ADC:
+ case M37710_LINE_UART1XMIT:
+ case M37710_LINE_UART1RECV:
+ case M37710_LINE_UART0XMIT:
+ case M37710_LINE_UART0RECV:
+ case M37710_LINE_TIMERB2:
+ case M37710_LINE_TIMERB1:
+ case M37710_LINE_TIMERB0:
+ case M37710_LINE_TIMERA4:
+ case M37710_LINE_TIMERA3:
+ case M37710_LINE_TIMERA2:
+ case M37710_LINE_TIMERA1:
+ case M37710_LINE_TIMERA0:
+ case M37710_LINE_IRQ2:
+ case M37710_LINE_IRQ1:
+ case M37710_LINE_IRQ0:
+ switch(state)
+ {
+ case CLEAR_LINE:
+ LINE_IRQ &= ~(1 << line);
+ if (m37710_irq_levels[line])
+ {
+ cpustate->m37710_regs[m37710_irq_levels[line]] |= 8;
+ }
+ return;
+ case ASSERT_LINE:
+ case PULSE_LINE:
+ case HOLD_LINE:
+ LINE_IRQ |= (1 << line);
+ if (m37710_irq_levels[line])
+ {
+ cpustate->m37710_regs[m37710_irq_levels[line]] &= ~8;
+ }
+ break;
+ }
+
+ // if I flag is set, trip the WAI mechanism only (may not be totally accurate)
+ if(FLAG_I)
+ {
+ if(CPU_STOPPED & STOP_LEVEL_WAI)
+ CPU_STOPPED &= ~STOP_LEVEL_WAI;
+ return;
+ }
+ return;
+ }
+}
+
+
+
+/* Get a register from the CPU core */
+TABLE_FUNCTION(uint, get_reg, (m37710i_cpu_struct *cpustate, int regnum))
+{
+ switch(regnum)
+ {
+ case M37710_A: return REG_B | REG_A;
+ case M37710_B: return REG_BB | REG_BA;
+ case M37710_X: return REG_X;
+ case M37710_Y: return REG_Y;
+ case M37710_S: return REG_S;
+ case M37710_PC: return REG_PC;
+ case M37710_PB: return REG_PB >> 16;
+ case M37710_DB: return REG_DB >> 16;
+ case M37710_D: return REG_D;
+ case M37710_P: return m37710i_get_reg_p(cpustate);
+ case M37710_IRQ_STATE: return LINE_IRQ;
+ case STATE_GENPCBASE: return REG_PPC;
+ }
+ return 0;
+}
+
+TABLE_FUNCTION(void, set_reg, (m37710i_cpu_struct *cpustate, int regnum, uint val))
+{
+ switch(regnum)
+ {
+ case M37710_PC: REG_PC = MAKE_UINT_16(val); break;
+ case M37710_S: REG_S = MAKE_UINT_16(val); break;
+ case M37710_P: m37710i_set_reg_p(cpustate, val); break;
+#if FLAG_SET_M
+ case M37710_A: REG_A = MAKE_UINT_8(val); REG_B = val&0xff00; break;
+ case M37710_B: REG_BA = MAKE_UINT_8(val); REG_BB = val&0xff00; break;
+#else
+ case M37710_A: REG_A = MAKE_UINT_16(val); break;
+ case M37710_B: REG_BA = MAKE_UINT_16(val); break;
+#endif
+#if FLAG_SET_X
+ case M37710_X: REG_X = MAKE_UINT_8(val); break;
+ case M37710_Y: REG_Y = MAKE_UINT_8(val); break;
+#else
+ case M37710_X: REG_X = MAKE_UINT_16(val); break;
+ case M37710_Y: REG_Y = MAKE_UINT_16(val); break;
+#endif
+ case M37710_IRQ_STATE: FTABLE_SET_LINE(cpustate, M37710_LINE_IRQ0, val == 0 ? CLEAR_LINE : ASSERT_LINE); break;
+ }
+}
+
+TABLE_FUNCTION(int, execute, (m37710i_cpu_struct *cpustate, int clocks))
+{
+ if(!CPU_STOPPED)
+ {
+ CLOCKS = clocks;
+ do
+ {
+ REG_PPC = REG_PC;
+ M37710_CALL_DEBUGGER(REG_PC);
+ REG_PC++;
+ REG_IR = read_8_IMM(REG_PB | REG_PPC);
+ cpustate->opcodes[REG_IR](cpustate);
+ } while(CLOCKS > 0);
+ return clocks - CLOCKS;
+ }
+ return clocks;
+}
+
+
+/* ======================================================================== */
+/* ================================== EOF ================================= */
+/* ======================================================================== */
diff --git a/trunk/src/emu/cpu/m37710/m7700ds.c b/trunk/src/emu/cpu/m37710/m7700ds.c
new file mode 100644
index 00000000000..a76b45ef1c2
--- /dev/null
+++ b/trunk/src/emu/cpu/m37710/m7700ds.c
@@ -0,0 +1,616 @@
+/*
+
+Mitsubishi 7700 Series CPU disassembler v1.1
+
+By R. Belmont
+Based on G65C816 CPU Emulator by Karl Stenerud
+
+*/
+
+#include "emu.h"
+#include "m7700ds.h"
+
+#ifdef SEC
+#undef SEC
+#endif
+
+#define ADDRESS_24BIT(A) ((A)&0xffffff)
+
+typedef struct
+{
+ unsigned char name;
+ unsigned char flag;
+ unsigned char ea;
+} opcode_struct;
+
+enum
+{
+ IMP , ACC , RELB, RELW, IMM , A , AI , AL , ALX , AX , AXI ,
+ AY , D , DI , DIY , DLI , DLIY, DX , DXI , DY , S , SIY ,
+ SIG /*, MVN , MVP , PEA , PEI , PER */, LDM4, LDM5, LDM4X, LDM5X,
+ BBCD, BBCA, ACCB
+};
+
+enum
+{
+ I, /* ignore */
+ M, /* check m bit */
+ X /* check x bit */
+};
+
+enum
+{
+ ADC , AND , ASL , BCC , BCS , BEQ , BIT , BMI , BNE , BPL , BRA ,
+ BRK , BRL , BVC , BVS , CLC , CLD , CLI , CLV , CMP , COP , CPX ,
+ CPY , DEA , DEC , DEX , DEY , EOR , INA , INC , INX , INY , JML ,
+ JMP , JSL , JSR , LDA , LDX , LDY , LSR , MVN , MVP , NOP , ORA ,
+ PEA , PEI , PER , PHA , PHT , PHD , PHK , PHP , PHX , PHY , PLA ,
+ PLB , PLD , PLP , PLX , PLY , CLP , ROL , ROR , RTI , RTL , RTS ,
+ SBC , SEC , SED , SEI , SEP , STA , STP , STX , STY , STZ , TAX ,
+ TAY , TCS , TCD , TDC , TRB , TSB , TSC , TSX , TXA , TXS , TXY ,
+ TYA , TYX , WAI , WDM , XBA , XCE , MPY , DIV , MPYS, DIVS, RLA ,
+ EXTS, EXTZ , LDT , LDM , UNK , SEB , SEM , CLM , STB , LDB , ADCB ,
+ SBCB, EORB , TBX , CMPB, INB , DEB , TXB , TYB , LSRB, ORB , CLB ,
+ BBC, BBS, TBY, ANDB, PUL , PSH , PLAB, XAB , PHB
+};
+
+static const char *const g_opnames[] =
+{
+ "ADC", "AND", "ASL", "BCC", "BCS", "BEQ", "BIT", "BMI", "BNE", "BPL", "BRA",
+ "BRK", "BRL", "BVC", "BVS", "CLC", "CLD", "CLI", "CLV", "CMP", "COP", "CPX",
+ "CPY", "DEA", "DEC", "DEX", "DEY", "EOR", "INA", "INC", "INX", "INY", "JML",
+ "JMP", "JSL", "JSR", "LDA", "LDX", "LDY", "LSR", "MVN", "MVP", "NOP", "ORA",
+ "PEA", "PEI", "PER", "PHA", "PHT", "PHD", "PHK", "PHP", "PHX", "PHY", "PLA",
+ "PLT", "PLD", "PLP", "PLX", "PLY", "CLP", "ROL", "ROR", "RTI", "RTL", "RTS",
+ "SBC", "SEC", "SED", "SEI", "SEP", "STA", "STP", "STX", "STY", "STZ", "TAX",
+ "TAY", "TCS", "TCD", "TDC", "TRB", "TSB", "TSC", "TSX", "TXA", "TXS", "TXY",
+ "TYA", "TYX", "WAI", "WDM", "XBA", "XCE", "MPY", "DIV", "MPYS", "DIVS", "RLA",
+ "EXTS","EXTZ","LDT", "LDM", "UNK", "SEB", "SEM", "CLM", "STB", "LDB", "ADCB",
+ "SBCB","EORB","TBX", "CMPB","INB", "DEB", "TXB", "TYB", "LSRB", "ORB", "CLB",
+ "BBC", "BBS", "TBY", "ANDB","PUL", "PSH", "PLB", "XAB", "PHB",
+};
+
+static const opcode_struct g_opcodes[256] =
+{
+ {BRK, I, SIG }, {ORA, M, DXI }, {UNK, I, SIG }, {ORA, M, S },
+ {SEB, M, LDM4 }, {ORA, M, D }, {ASL, M, D }, {ORA, M, DLI },
+ {PHP, I, IMP }, {ORA, M, IMM }, {ASL, M, ACC }, {PHD, I, IMP },
+ {SEB, M, LDM5 }, {ORA, M, A }, {ASL, M, A }, {ORA, M, AL },
+// 0x10
+ {BPL, I, RELB}, {ORA, M, DIY }, {ORA, M, DI }, {ORA, M, SIY },
+ {CLB, M, LDM4}, {ORA, M, DX }, {ASL, M, DX }, {ORA, M, DLIY},
+ {CLC, I, IMP }, {ORA, M, AY }, {DEA, I, IMP }, {TCS, I, IMP },
+ {CLB, M, LDM5}, {ORA, M, AX }, {ASL, M, AX }, {ORA, M, ALX },
+// 0x20
+ {JSR, I, A }, {AND, M, DXI }, {JSL, I, AL }, {AND, M, S },
+ {BBS, M, BBCD}, {AND, M, D }, {ROL, M, D }, {AND, M, DLI },
+ {PLP, I, IMP }, {AND, M, IMM }, {ROL, M, ACC }, {PLD, I, IMP },
+ {BBS, M, BBCA}, {AND, M, A }, {ROL, M, A }, {AND, M, AL },
+// 0x30
+ {BMI, I, RELB}, {AND, M, DIY }, {AND, M, DI }, {AND, M, SIY },
+ {BBC, M, BBCD}, {AND, M, DX }, {ROL, M, DX }, {AND, M, DLIY},
+ {SEC, I, IMP }, {AND, M, AY }, {INA, I, IMP }, {TSC, I, IMP },
+ {BBC, M, BBCA}, {AND, M, AX }, {ROL, M, AX }, {AND, M, ALX },
+// 0x40
+ {RTI, I, IMP }, {EOR, M, DXI }, {WDM, I, IMP }, {EOR, M, S },
+ {MVP, I, MVP }, {EOR, M, D }, {LSR, M, D }, {EOR, M, DLI },
+ {PHA, I, IMP }, {EOR, M, IMM }, {LSR, M, ACC }, {PHK, I, IMP },
+ {JMP, I, A }, {EOR, M, A }, {LSR, M, A }, {EOR, M, AL },
+// 0x50
+ {BVC, I, RELB}, {EOR, M, DIY }, {EOR, M, DI }, {EOR, M, SIY },
+ {MVN, I, MVN }, {EOR, M, DX }, {LSR, M, DX }, {EOR, M, DLIY},
+ {CLI, I, IMP }, {EOR, M, AY }, {PHY, I, IMP }, {TCD, I, IMP },
+ {JMP, I, AL }, {EOR, M, AX }, {LSR, M, AX }, {EOR, M, ALX },
+// 0x60
+ {RTS, I, IMP }, {ADC, M, DXI }, {PER, I, PER }, {ADC, M, S },
+ {LDM, M, LDM4 }, {ADC, M, D }, {ROR, M, D }, {ADC, M, DLI },
+ {PLA, I, IMP }, {ADC, M, IMM }, {ROR, M, ACC }, {RTL, I, IMP },
+ {JMP, I, AI }, {ADC, M, A }, {ROR, M, A }, {ADC, M, AL },
+// 0x70
+ {BVS, I, RELB}, {ADC, M, DIY }, {ADC, M, DI }, {ADC, M, SIY },
+ {LDM, M, LDM4X }, {ADC, M, DX }, {ROR, M, DX }, {ADC, M, DLIY},
+ {SEI, I, IMP }, {ADC, M, AY }, {PLY, I, IMP }, {TDC, I, IMP },
+ {JMP, I, AXI }, {ADC, M, AX }, {ROR, M, AX }, {ADC, M, ALX },
+// 0x80
+ {BRA, I, RELB}, {STA, M, DXI }, {BRL, I, RELW}, {STA, M, S },
+ {STY, X, D }, {STA, M, D }, {STX, X, D }, {STA, M, DLI },
+ {DEY, I, IMP }, {BIT, M, IMM }, {TXA, I, IMP }, {PHT, I, IMP },
+ {STY, X, A }, {STA, M, A }, {STX, X, A }, {STA, M, AL },
+// 0x90
+ {BCC, I, RELB}, {STA, M, DIY }, {STA, M, DI }, {STA, M, SIY },
+ {STY, X, DX }, {STA, M, DX }, {STX, X, DY }, {STA, M, DLIY},
+ {TYA, I, IMP }, {STA, M, AY }, {TXS, I, IMP }, {TXY, I, IMP },
+ {LDM, M, LDM5 }, {STA, M, AX }, {LDM, M, LDM5X }, {STA, M, ALX },
+// 0xA0
+ {LDY, X, IMM }, {LDA, M, DXI }, {LDX, X, IMM }, {LDA, M, S },
+ {LDY, X, D }, {LDA, M, D }, {LDX, X, D }, {LDA, M, DLI },
+ {TAY, I, IMP }, {LDA, M, IMM }, {TAX, I, IMP }, {PLB, I, IMP },
+ {LDY, X, A }, {LDA, M, A }, {LDX, X, A }, {LDA, M, AL },
+// 0xB0
+ {BCS, I, RELB}, {LDA, M, DIY }, {LDA, M, DI }, {LDA, M, SIY },
+ {LDY, X, DX }, {LDA, M, DX }, {LDX, X, DY }, {LDA, M, DLIY},
+ {CLV, I, IMP }, {LDA, M, AY }, {TSX, I, IMP }, {TYX, I, IMP },
+ {LDY, X, AX }, {LDA, M, AX }, {LDX, X, AY }, {LDA, M, ALX },
+// 0xC0
+ {CPY, X, IMM }, {CMP, M, DXI }, {CLP, I, IMM }, {CMP, M, S },
+ {CPY, X, D }, {CMP, M, D }, {DEC, M, D }, {CMP, M, DLI },
+ {INY, I, IMP }, {CMP, M, IMM }, {DEX, I, IMP }, {WAI, I, IMP },
+ {CPY, X, A }, {CMP, M, A }, {DEC, M, A }, {CMP, M, AL },
+// 0xD0
+ {BNE, I, RELB}, {CMP, M, DIY }, {CMP, M, DI }, {CMP, M, SIY },
+ {PEI, I, PEI }, {CMP, M, DX }, {DEC, M, DX }, {CMP, M, DLIY},
+ {CLM, I, IMP }, {CMP, M, AY }, {PHX, I, IMP }, {STP, I, IMP },
+ {JML, I, AI }, {CMP, M, AX }, {DEC, M, AX }, {CMP, M, ALX },
+// 0xE0
+ {CPX, X, IMM }, {SBC, M, DXI }, {SEP, I, IMM }, {SBC, M, S },
+ {CPX, X, D }, {SBC, M, D }, {INC, M, D }, {SBC, M, DLI },
+ {INX, M, IMP }, {SBC, M, IMM }, {NOP, I, IMP }, {PSH, I, IMM },
+ {CPX, X, A }, {SBC, M, A }, {INC, M, A }, {SBC, M, AL },
+// 0xF0
+ {BEQ, I, RELB}, {SBC, M, DIY }, {SBC, M, DI }, {SBC, M, SIY },
+ {PEA, I, PEA }, {SBC, M, DX }, {INC, M, DX }, {SBC, M, DLIY},
+ {SEM, I, IMP }, {SBC, M, AY }, {PLX, I, IMP }, {PUL, I, IMM },
+ {JSR, I, AXI }, {SBC, M, AX }, {INC, M, AX }, {SBC, M, ALX }
+};
+
+static const opcode_struct g_opcodes_prefix42[256] =
+{
+ {BRK, I, SIG }, {ORB, M, DXI }, {COP, I, SIG }, {ORB, M, S },
+ {TSB, M, D }, {ORB, M, D }, {ASL, M, D }, {ORB, M, DLI },
+ {PHP, I, IMP }, {ORB, M, IMM }, {ASL, M, ACCB }, {PHD, I, IMP },
+ {TSB, M, A }, {ORB, M, A }, {ASL, M, A }, {ORB, M, AL },
+// 0x10
+ {BPL, I, RELB}, {ORB, M, DIY }, {ORB, M, DI }, {ORB, M, SIY },
+ {TRB, M, D }, {ORB, M, DX }, {ASL, M, DX }, {ORB, M, DLIY},
+ {CLC, I, IMP }, {ORB, M, AY }, {DEB, I, IMP }, {TCS, I, IMP },
+ {TRB, M, A }, {ORB, M, AX }, {ASL, M, AX }, {ORB, M, ALX },
+// 0x20
+ {JSR, I, A }, {ANDB, M, DXI }, {JSL, I, AL }, {ANDB, M, S },
+ {BIT, M, D }, {ANDB, M, D }, {ROL, M, D }, {ANDB, M, DLI },
+ {PLP, I, IMP }, {ANDB, M, IMM }, {ROL, M, ACCB }, {PLD, I, IMP },
+ {BIT, M, A }, {ANDB, M, A }, {ROL, M, A }, {ANDB, M, AL },
+// 0x30
+ {BMI, I, RELB}, {AND, M, DIY }, {AND, M, DI }, {AND, M, SIY },
+ {BIT, M, DX }, {AND, M, DX }, {ROL, M, DX }, {AND, M, DLIY},
+ {SEC, I, IMP }, {AND, M, AY }, {INB, I, IMP }, {TSC, I, IMP },
+ {BIT, M, AX }, {AND, M, AX }, {ROL, M, AX }, {AND, M, ALX },
+// 0x40
+ {RTI, I, IMP }, {EORB, M, DXI }, {WDM, I, IMP }, {EORB, M, S },
+ {MVP, I, MVP }, {EORB, M, D }, {LSRB, M, D }, {EORB, M, DLI },
+ {PHB, I, IMP }, {EORB, M, IMM }, {LSRB, M, ACC }, {PHK, I, IMP },
+ {JMP, I, A }, {EORB, M, A }, {LSRB, M, A }, {EORB, M, AL },
+// 0x50
+ {BVC, I, RELB}, {EORB, M, DIY }, {EORB, M, DI }, {EORB, M, SIY },
+ {MVN, I, MVN }, {EORB, M, DX }, {LSRB, M, DX }, {EORB, M, DLIY},
+ {CLI, I, IMP }, {EORB, M, AY }, {PHY, I, IMP }, {TCD, I, IMP },
+ {JMP, I, AL }, {EORB, M, AX }, {LSRB, M, AX }, {EORB, M, ALX },
+// 0x60
+ {RTS, I, IMP }, {ADCB, M, DXI }, {PER, I, PER }, {ADCB, M, S },
+ {STZ, M, D }, {ADCB, M, D }, {ROR, M, D }, {ADCB, M, DLI },
+ {PLAB,I, IMP }, {ADCB, M, IMM }, {ROR, M, ACC }, {RTL, I, IMP },
+ {JMP, I, AI }, {ADCB, M, A }, {ROR, M, A }, {ADCB, M, AL },
+// 0x70
+ {BVS, I, RELB}, {ADCB, M, DIY }, {ADCB, M, DI }, {ADCB, M, SIY },
+ {STZ, M, DX }, {ADCB, M, DX }, {ROR, M, DX }, {ADCB, M, DLIY},
+ {SEI, I, IMP }, {ADCB, M, AY }, {PLY, I, IMP }, {TDC, I, IMP },
+ {JMP, I, AXI }, {ADCB, M, AX }, {ROR, M, AX }, {ADCB, M, ALX },
+// 0x80
+ {BRA, I, RELB}, {STB, M, DXI }, {BRL, I, RELW}, {STB, M, S },
+ {STY, X, D }, {STB, M, D }, {STX, X, D }, {STB, M, DLI },
+ {DEY, I, IMP }, {BIT, M, IMM }, {TXB, I, IMP }, {PHB, I, IMP },
+ {STY, X, A }, {STB, M, A }, {STX, X, A }, {STB, M, AL },
+// 0x90
+ {BCC, I, RELB}, {STB, M, DIY }, {STB, M, DI }, {STB, M, SIY },
+ {STY, X, DX }, {STB, M, DX }, {STX, X, DY }, {STB, M, DLIY},
+ {TYB, I, IMP }, {STB, M, AY }, {TXS, I, IMP }, {TXY, I, IMP },
+ {STZ, M, A }, {STB, M, AX }, {STZ, M, AX }, {STB, M, ALX },
+// 0xA0
+ {LDY, X, IMM }, {LDB, M, DXI }, {LDX, X, IMM }, {LDB, M, S },
+ {LDY, X, D }, {LDB, M, D }, {LDX, X, D }, {LDB, M, DLI },
+ {TBY, I, IMP }, {LDB, M, IMM }, {TBX, I, IMP }, {PLB, I, IMP },
+ {LDY, X, A }, {LDB, M, A }, {LDX, X, A }, {LDB, M, AL },
+// 0xB0
+ {BCS, I, RELB}, {LDB, M, DIY }, {LDB, M, DI }, {LDB, M, SIY },
+ {LDY, X, DX }, {LDB, M, DX }, {LDX, X, DY }, {LDB, M, DLIY},
+ {CLV, I, IMP }, {LDB, M, AY }, {TSX, I, IMP }, {TYX, I, IMP },
+ {LDY, X, AX }, {LDB, M, AX }, {LDX, X, AY }, {LDB, M, ALX },
+// 0xC0
+ {CPY, X, IMM }, {CMPB, M, DXI }, {CLP, I, IMM }, {CMPB, M, S },
+ {CPY, X, D }, {CMPB, M, D }, {DEC, M, D }, {CMPB, M, DLI },
+ {INY, I, IMP }, {CMPB, M, IMM }, {DEX, I, IMP }, {WAI, I, IMP },
+ {CPY, X, A }, {CMPB, M, A }, {DEC, M, A }, {CMPB, M, AL },
+// 0xD0
+ {BNE, I, RELB}, {CMPB, M, DIY }, {CMPB, M, DI }, {CMPB, M, SIY },
+ {PEI, I, PEI }, {CMPB, M, DX }, {DEC, M, DX }, {CMPB, M, DLIY},
+ {CLD, I, IMP }, {CMPB, M, AY }, {PHX, I, IMP }, {STP, I, IMP },
+ {JML, I, AI }, {CMPB, M, AX }, {DEC, M, AX }, {CMPB, M, ALX },
+// 0xE0
+ {CPX, X, IMM }, {SBCB, M, DXI }, {SEP, I, IMM }, {SBCB, M, S },
+ {CPX, X, D }, {SBCB, M, D }, {INC, M, D }, {SBCB, M, DLI },
+ {INX, M, IMP }, {SBCB, M, IMM }, {NOP, I, IMP }, {XBA, I, IMP },
+ {CPX, X, A }, {SBCB, M, A }, {INC, M, A }, {SBCB, M, AL },
+// 0xF0
+ {BEQ, I, RELB}, {SBCB, M, DIY }, {SBCB, M, DI }, {SBCB, M, SIY },
+ {PEA, I, PEA }, {SBCB, M, DX }, {INC, M, DX }, {SBCB, M, DLIY},
+ {SED, I, IMP }, {SBCB, M, AY }, {PLX, I, IMP }, {XCE, I, IMP },
+ {JSR, I, AXI }, {SBCB, M, AX }, {INC, M, AX }, {SBCB, M, ALX }
+};
+
+static const opcode_struct g_opcodes_prefix89[256] =
+{
+ {BRK, I, SIG }, {MPY, M, DXI }, {COP, I, SIG }, {MPY, M, S },
+ {TSB, M, D }, {MPY, M, D }, {ASL, M, D }, {MPY, M, DLI },
+ {PHP, I, IMP }, {MPY, M, IMM }, {ASL, M, ACC }, {PHD, I, IMP },
+ {TSB, M, A }, {MPY, M, A }, {ASL, M, A }, {MPY, M, AL },
+// 0x10
+ {BPL, I, RELB}, {ORA, M, DIY }, {ORA, M, DI }, {ORA, M, SIY },
+ {TRB, M, D }, {MPY, M, DX }, {ASL, M, DX }, {ORA, M, DLIY},
+ {CLC, I, IMP }, {MPY, M, AY }, {INA, I, IMP }, {TCS, I, IMP },
+ {TRB, M, A }, {ORA, M, AX }, {ASL, M, AX }, {ORA, M, ALX },
+// 0x20
+ {JSR, I, A }, {AND, M, DXI }, {JSL, I, AL }, {AND, M, S },
+ {BIT, M, D }, {AND, M, D }, {ROL, M, D }, {AND, M, DLI },
+ {XAB, I, IMP }, {AND, M, IMM }, {ROL, M, ACC }, {PLD, I, IMP },
+ {BIT, M, A }, {AND, M, A }, {ROL, M, A }, {AND, M, AL },
+// 0x30
+ {BMI, I, RELB}, {AND, M, DIY }, {AND, M, DI }, {AND, M, SIY },
+ {BIT, M, DX }, {AND, M, DX }, {ROL, M, DX }, {AND, M, DLIY},
+ {SEC, I, IMP }, {AND, M, AY }, {DEA, I, IMP }, {TSC, I, IMP },
+ {BIT, M, AX }, {AND, M, AX }, {ROL, M, AX }, {AND, M, ALX },
+// 0x40
+ {RTI, I, IMP }, {EOR, M, DXI }, {WDM, I, IMP }, {EOR, M, S },
+ {MVP, I, MVP }, {EOR, M, D }, {LSR, M, D }, {EOR, M, DLI },
+ {PHA, I, IMP }, {RLA, M, IMM }, {LSR, M, ACC }, {PHK, I, IMP },
+ {JMP, I, A }, {EOR, M, A }, {LSR, M, A }, {EOR, M, AL },
+// 0x50
+ {BVC, I, RELB}, {EOR, M, DIY }, {EOR, M, DI }, {EOR, M, SIY },
+ {MVN, I, MVN }, {EOR, M, DX }, {LSR, M, DX }, {EOR, M, DLIY},
+ {CLI, I, IMP }, {EOR, M, AY }, {PHY, I, IMP }, {TCD, I, IMP },
+ {JMP, I, AL }, {EOR, M, AX }, {LSR, M, AX }, {EOR, M, ALX },
+// 0x60
+ {RTS, I, IMP }, {ADC, M, DXI }, {PER, I, PER }, {ADC, M, S },
+ {STZ, M, D }, {ADC, M, D }, {ROR, M, D }, {ADC, M, DLI },
+ {PLA, I, IMP }, {ADC, M, IMM }, {ROR, M, ACC }, {RTL, I, IMP },
+ {JMP, I, AI }, {ADC, M, A }, {ROR, M, A }, {ADC, M, AL },
+// 0x70
+ {BVS, I, RELB}, {ADC, M, DIY }, {ADC, M, DI }, {ADC, M, SIY },
+ {STZ, M, DX }, {ADC, M, DX }, {ROR, M, DX }, {ADC, M, DLIY},
+ {SEI, I, IMP }, {ADC, M, AY }, {PLY, I, IMP }, {TDC, I, IMP },
+ {JMP, I, AXI }, {ADC, M, AX }, {ROR, M, AX }, {ADC, M, ALX },
+// 0x80
+ {BRA, I, RELB}, {STA, M, DXI }, {BRL, I, RELW}, {STA, M, S },
+ {STY, X, D }, {STA, M, D }, {STX, X, D }, {STA, M, DLI },
+ {DEY, I, IMP }, {BIT, M, IMM }, {TXA, I, IMP }, {PHB, I, IMP },
+ {STY, X, A }, {STA, M, A }, {STX, X, A }, {STA, M, AL },
+// 0x90
+ {BCC, I, RELB}, {STA, M, DIY }, {STA, M, DI }, {STA, M, SIY },
+ {STY, X, DX }, {STA, M, DX }, {STX, X, DY }, {STA, M, DLIY},
+ {TYA, I, IMP }, {STA, M, AY }, {TXS, I, IMP }, {TXY, I, IMP },
+ {STZ, M, A }, {STA, M, AX }, {STZ, M, AX }, {STA, M, ALX },
+// 0xA0
+ {LDY, X, IMM }, {LDA, M, DXI }, {LDX, X, IMM }, {LDA, M, S },
+ {LDY, X, D }, {LDA, M, D }, {LDX, X, D }, {LDA, M, DLI },
+ {TAY, I, IMP }, {LDA, M, IMM }, {TAX, I, IMP }, {PLB, I, IMP },
+ {LDY, X, A }, {LDA, M, A }, {LDX, X, A }, {LDA, M, AL },
+// 0xB0
+ {BCS, I, RELB}, {LDA, M, DIY }, {LDA, M, DI }, {LDA, M, SIY },
+ {LDY, X, DX }, {LDA, M, DX }, {LDX, X, DY }, {LDA, M, DLIY},
+ {CLV, I, IMP }, {LDA, M, AY }, {TSX, I, IMP }, {TYX, I, IMP },
+ {LDY, X, AX }, {LDA, M, AX }, {LDX, X, AY }, {LDA, M, ALX },
+// 0xC0
+ {CPY, X, IMM }, {CMP, M, DXI }, {LDT, I, IMM }, {CMP, M, S },
+ {CPY, X, D }, {CMP, M, D }, {DEC, M, D }, {CMP, M, DLI },
+ {INY, I, IMP }, {CMP, M, IMM }, {DEX, I, IMP }, {WAI, I, IMP },
+ {CPY, X, A }, {CMP, M, A }, {DEC, M, A }, {CMP, M, AL },
+// 0xD0
+ {BNE, I, RELB}, {CMP, M, DIY }, {CMP, M, DI }, {CMP, M, SIY },
+ {PEI, I, PEI }, {CMP, M, DX }, {DEC, M, DX }, {CMP, M, DLIY},
+ {CLD, I, IMP }, {CMP, M, AY }, {PHX, I, IMP }, {STP, I, IMP },
+ {JML, I, AI }, {CMP, M, AX }, {DEC, M, AX }, {CMP, M, ALX },
+// 0xE0
+ {CPX, X, IMM }, {SBC, M, DXI }, {SEP, I, IMM }, {SBC, M, S },
+ {CPX, X, D }, {SBC, M, D }, {INC, M, D }, {SBC, M, DLI },
+ {INX, M, IMP }, {SBC, M, IMM }, {NOP, I, IMP }, {XBA, I, IMP },
+ {CPX, X, A }, {SBC, M, A }, {INC, M, A }, {SBC, M, AL },
+// 0xF0
+ {BEQ, I, RELB}, {SBC, M, DIY }, {SBC, M, DI }, {SBC, M, SIY },
+ {PEA, I, PEA }, {SBC, M, DX }, {INC, M, DX }, {SBC, M, DLIY},
+ {SEM, I, IMP }, {SBC, M, AY }, {PLX, I, IMP }, {XCE, I, IMP },
+ {JSR, I, AXI }, {SBC, M, AX }, {INC, M, AX }, {SBC, M, ALX }
+};
+
+INLINE unsigned int read_8(const UINT8 *oprom, unsigned int offset)
+{
+ return oprom[offset];
+}
+
+INLINE unsigned int read_16(const UINT8 *oprom, unsigned int offset)
+{
+ unsigned int val = read_8(oprom, offset);
+ return val | (read_8(oprom, offset+1)<<8);
+}
+
+INLINE unsigned int read_24(const UINT8 *oprom, unsigned int offset)
+{
+ unsigned int val = read_8(oprom, offset);
+ val |= (read_8(oprom, offset+1)<<8);
+ return val | (read_8(oprom, offset+2)<<16);
+}
+
+INLINE char* int_8_str(unsigned int val)
+{
+ static char str[20];
+
+ val &= 0xff;
+
+ if(val & 0x80)
+ sprintf(str, "-$%x", (0-val) & 0x7f);
+ else
+ sprintf(str, "$%x", val & 0x7f);
+
+ return str;
+}
+
+INLINE char* int_16_str(unsigned int val)
+{
+ static char str[20];
+
+ val &= 0xffff;
+
+ if(val & 0x8000)
+ sprintf(str, "-$%x", (0-val) & 0x7fff);
+ else
+ sprintf(str, "$%x", val & 0x7fff);
+
+ return str;
+}
+
+
+int m7700_disassemble(char* buff, unsigned int pc, unsigned int pb, const UINT8 *oprom, int m_flag, int x_flag)
+{
+ unsigned int instruction;
+ const opcode_struct *opcode;
+ char* ptr;
+ int var;
+ signed char varS;
+ int length = 1;
+ unsigned int address;
+ //unsigned int start;
+ UINT32 flags = 0;
+
+ pb <<= 16;
+ address = pc | pb;
+ //start = address;
+
+ instruction = read_8(oprom,0);
+
+ // check for prefixes
+ switch (instruction)
+ {
+ case 0x42:
+ address++;
+ length++;
+ oprom++;
+ instruction = read_8(oprom,0);
+ opcode = g_opcodes_prefix42 + instruction;
+ break;
+
+ case 0x89:
+ address++;
+ length++;
+ oprom++;
+ instruction = read_8(oprom,0);
+ opcode = g_opcodes_prefix89 + instruction;
+ break;
+
+ default:
+ opcode = g_opcodes + instruction;
+ break;
+ }
+
+ if (opcode->name == JSR)
+ flags = DASMFLAG_STEP_OVER;
+ else if (opcode->name == RTS || opcode->name == RTI)
+ flags = DASMFLAG_STEP_OUT;
+
+ sprintf(buff, "%s", g_opnames[opcode->name]);
+ ptr = buff + strlen(buff);
+
+ switch(opcode->ea)
+ {
+ case IMP :
+ break;
+ case ACC :
+ sprintf(ptr, " A");
+ break;
+ case ACCB :
+ sprintf(ptr, " B");
+ break;
+ case RELB:
+ varS = read_8(oprom,1);
+ length++;
+ sprintf(ptr, " %06x (%s)", pb | ((pc + length + varS)&0xffff), int_8_str(varS));
+ break;
+ case RELW:
+ case PER :
+ var = read_16(oprom,1);
+ length += 2;
+ sprintf(ptr, " %06x (%s)", pb | ((pc + length + var)&0xffff), int_16_str(var));
+ break;
+ case IMM :
+ if((opcode->flag == M && !m_flag) || (opcode->flag == X && !x_flag))
+ {
+ sprintf(ptr, " #$%04x", read_16(oprom,1));
+ length += 2;
+ }
+ else
+ {
+ sprintf(ptr, " #$%02x", read_8(oprom,1));
+ length++;
+ }
+ break;
+ case BBCD:
+ if((opcode->flag == M && !m_flag) || (opcode->flag == X && !x_flag))
+ {
+ varS = read_8(oprom,4);
+ length += 4;
+ sprintf(ptr, " #$%04x, $%02x, %06x (%s)", read_16(oprom,2), read_8(oprom,1), pb | ((pc + length + varS)&0xffff), int_8_str(varS));
+ }
+ else
+ {
+ varS = read_8(oprom,3);
+ length += 3;
+ sprintf(ptr, " #$%02x, $%02x, %06x (%s)", read_8(oprom,2), read_8(oprom,1), pb | ((pc + length + varS)&0xffff), int_8_str(varS));
+ }
+ break;
+ case BBCA:
+ if((opcode->flag == M && !m_flag) || (opcode->flag == X && !x_flag))
+ {
+ length += 5;
+ varS = read_8(oprom,5);
+ sprintf(ptr, " #$%04x, $%04x, %06x (%s)", read_16(oprom,3), read_16(oprom,1), pb | ((pc + length + varS)&0xffff), int_8_str(varS));
+ }
+ else
+ {
+ length += 4;
+ varS = read_8(oprom,4);
+ sprintf(ptr, " #$%02x, $%04x, %06x (%s)", read_8(oprom,3), read_16(oprom,1), pb | ((pc + length + varS)&0xffff), int_8_str(varS));
+ }
+ break;
+ case LDM4:
+ if((opcode->flag == M && !m_flag) || (opcode->flag == X && !x_flag))
+ {
+ sprintf(ptr, " #$%04x, $%02x", read_16(oprom,2), read_8(oprom,1));
+ length += 3;
+ }
+ else
+ {
+ sprintf(ptr, " #$%02x, $%02x", read_8(oprom,2), read_8(oprom,1));
+ length += 2;
+ }
+ break;
+ case LDM5:
+ if((opcode->flag == M && !m_flag) || (opcode->flag == X && !x_flag))
+ {
+ sprintf(ptr, " #$%04x, $%04x", read_16(oprom,3), read_16(oprom,1));
+ length += 4;
+ }
+ else
+ {
+ sprintf(ptr, " #$%02x, $%04x", read_8(oprom,3), read_16(oprom,1));
+ length += 3;
+ }
+ break;
+ case LDM4X:
+ if((opcode->flag == M && !m_flag) || (opcode->flag == X && !x_flag))
+ {
+ sprintf(ptr, " #$%04x, $%02x, X", read_16(oprom,2), read_8(oprom,1));
+ length += 3;
+ }
+ else
+ {
+ sprintf(ptr, " #$%02x, $%02x, X", read_8(oprom,2), read_8(oprom,1));
+ length += 2;
+ }
+ break;
+ case LDM5X:
+ if((opcode->flag == M && !m_flag) || (opcode->flag == X && !x_flag))
+ {
+ sprintf(ptr, " #$%04x, $%04x, X", read_16(oprom,3), read_16(oprom,1));
+ length += 4;
+ }
+ else
+ {
+ sprintf(ptr, " #$%02x, $%04x, X", read_8(oprom,3), read_16(oprom,1));
+ length += 3;
+ }
+ break;
+ case A :
+ case PEA :
+ sprintf(ptr, " $%04x", read_16(oprom,1));
+ length += 2;
+ break;
+ case AI :
+ sprintf(ptr, " ($%04x)", read_16(oprom,1));
+ length += 2;
+ break;
+ case AL :
+ sprintf(ptr, " $%06x", read_24(oprom,1));
+ length += 3;
+ break;
+ case ALX :
+ sprintf(ptr, " $%06x,X", read_24(oprom,1));
+ length += 3;
+ break;
+ case AX :
+ sprintf(ptr, " $%04x,X", read_16(oprom,1));
+ length += 2;
+ break;
+ case AXI :
+ sprintf(ptr, " ($%04x,X)", read_16(oprom,1));
+ length += 2;
+ break;
+ case AY :
+ sprintf(ptr, " $%04x,Y", read_16(oprom,1));
+ length += 2;
+ break;
+ case D :
+ sprintf(ptr, " $%02x", read_8(oprom,1));
+ length++;
+ break;
+ case DI :
+ case PEI :
+ sprintf(ptr, " ($%02x)", read_8(oprom,1));
+ length++;
+ break;
+ case DIY :
+ sprintf(ptr, " ($%02x),Y", read_8(oprom,1));
+ length++;
+ break;
+ case DLI :
+ sprintf(ptr, " [$%02x]", read_8(oprom,1));
+ length++;
+ break;
+ case DLIY:
+ sprintf(ptr, " [$%02x],Y", read_8(oprom,1));
+ length++;
+ break;
+ case DX :
+ sprintf(ptr, " $%02x,X", read_8(oprom,1));
+ length++;
+ break;
+ case DXI :
+ sprintf(ptr, " ($%02x,X)", read_8(oprom,1));
+ length++;
+ break;
+ case DY :
+ sprintf(ptr, " $%02x,Y", read_8(oprom,1));
+ length++;
+ break;
+ case S :
+ sprintf(ptr, " %s,S", int_8_str(read_8(oprom,1)));
+ length++;
+ break;
+ case SIY :
+ sprintf(ptr, " (%s,S),Y", int_8_str(read_8(oprom,1)));
+ length++;
+ break;
+ case SIG :
+ sprintf(ptr, " #$%02x", read_8(oprom,1));
+ length++;
+ break;
+ case MVN :
+ case MVP :
+ sprintf(ptr, " $%02x, $%02x", read_8(oprom,2), read_8(oprom,1));
+ length += 2;
+ break;
+ }
+
+ return length | flags | DASMFLAG_SUPPORTED;
+}
+
+CPU_DISASSEMBLE( m37710_generic )
+{
+ return m7700_disassemble(buffer, (pc&0xffff), pc>>16, oprom, 0, 0);
+}
+
diff --git a/trunk/src/emu/cpu/m37710/m7700ds.h b/trunk/src/emu/cpu/m37710/m7700ds.h
new file mode 100644
index 00000000000..4df93f0c5ae
--- /dev/null
+++ b/trunk/src/emu/cpu/m37710/m7700ds.h
@@ -0,0 +1,21 @@
+#pragma once
+
+#ifndef __M7700DS_H__
+#define __M7700DS_H__
+
+/*
+
+Mitsubishi 7700 CPU Emulator v0.10
+By R. Belmont
+
+Based on:
+G65C816 CPU Emulator V0.92
+
+Copyright Karl Stenerud
+All rights reserved.
+
+*/
+
+int m7700_disassemble(char* buff, unsigned int pc, unsigned int pb, const UINT8 *oprom, int m_flag, int x_flag);
+
+#endif /* __M7700DS_H__ */
diff --git a/trunk/src/emu/cpu/m6502/6502dasm.c b/trunk/src/emu/cpu/m6502/6502dasm.c
new file mode 100644
index 00000000000..f8343f40715
--- /dev/null
+++ b/trunk/src/emu/cpu/m6502/6502dasm.c
@@ -0,0 +1,767 @@
+/*****************************************************************************
+ *
+ * 6502dasm.c
+ * 6502/65c02/6510 disassembler
+ *
+ * Copyright Juergen Buchmueller, all rights reserved.
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * pullmoll@t-online.de
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ *****************************************************************************/
+/* 2. February 2000 PeT added support for 65sc02 subtype */
+/* 2. February 2000 PeT added support for 65ce02 variant */
+/* 3. February 2000 PeT bbr bbs displayment */
+/* 4. February 2000 PeT ply inw dew */
+/* 4. February 2000 PeT fixed relative word operand */
+/* 9. May 2000 PeT added m4510 */
+/* 18.April 2008 Roberto Fresca fixed bbr, bbs, rmb & smb displayment,
+ showing the correct bit to operate */
+
+#include "emu.h"
+#include "debugger.h"
+#include "m6502.h"
+#include "m65ce02.h"
+#include "m6509.h"
+#include "m4510.h"
+
+enum addr_mode {
+ non, /* no additional arguments */
+ imp, /* implicit */
+ acc, /* accumulator */
+ imm, /* immediate */
+ iw2, /* immediate word (65ce02) */
+ iw3, /* augment (65ce02) */
+ adr, /* absolute address (jmp,jsr) */
+ aba, /* absolute */
+ zpg, /* zero page */
+ zpx, /* zero page + X */
+ zpy, /* zero page + Y */
+ zpi, /* zero page indirect (65c02) */
+ zpb, /* zero page and branch (65c02 bbr,bbs) */
+ abx, /* absolute + X */
+ aby, /* absolute + Y */
+ rel, /* relative */
+ rw2, /* relative word (65cs02, 65ce02) */
+ idx, /* zero page pre indexed */
+ idy, /* zero page post indexed */
+ idz, /* zero page post indexed (65ce02) */
+ isy, /* zero page pre indexed sp and post indexed y (65ce02) */
+ ind, /* indirect (jmp) */
+ iax /* indirect + X (65c02 jmp) */
+};
+
+enum opcodes {
+ adc, and_,asl, bcc, bcs, beq, bit, bmi,
+ bne, bpl, m6502_brk, bvc, bvs, clc, cld, cli,
+ clv, cmp, cpx, cpy, dec, dex, dey, eor,
+ inc, inx, iny, jmp, jsr, lda, ldx, ldy,
+ lsr, nop, ora, pha, php, pla, plp, rol,
+ ror, rti, rts, sbc, sec, sed, sei, sta,
+ stx, sty, tax, tay, tsx, txa, txs, tya,
+ ill,
+/* 65c02 (only) mnemonics */
+ bbr, bbs, bra, rmb, smb, stz, trb, tsb,
+/* 65sc02 (only) mnemonics */
+ bsr,
+/* 6510 + 65c02 mnemonics */
+ anc, asr, ast, arr, asx, axa, dcp, dea,
+ dop, ina, isb, lax, phx, phy, plx, ply,
+ rla, rra, sax, slo, sre, sah, say, ssh,
+ sxh, syh, top, oal, kil,
+/* 65ce02 mnemonics */
+ cle, see, rtn, aug,
+ tab, tba, taz, tza, tys, tsy,
+ ldz, stz2/* real register store */,
+ dez, inz, cpz, phz, plz,
+ neg, asr2/* arithmetic shift right */,
+ asw, row, dew, inw, phw,
+/* 4510 mnemonics */
+ map,
+
+/* Deco CPU16 mnemonics */
+ vbl, u13, u8F, uAB, u87, u0B, uA3, u4B,
+ u3F, uBB, u23
+};
+
+
+static const char *const token[]=
+{
+ "adc", "and", "asl", "bcc", "bcs", "beq", "bit", "bmi",
+ "bne", "bpl", "m6502_brk", "bvc", "bvs", "clc", "cld", "cli",
+ "clv", "cmp", "cpx", "cpy", "dec", "dex", "dey", "eor",
+ "inc", "inx", "iny", "jmp", "jsr", "lda", "ldx", "ldy",
+ "lsr", "nop", "ora", "pha", "php", "pla", "plp", "rol",
+ "ror", "rti", "rts", "sbc", "sec", "sed", "sei", "sta",
+ "stx", "sty", "tax", "tay", "tsx", "txa", "txs", "tya",
+ "ill",
+/* 65c02 mnemonics */
+ "bbr", "bbs", "bra", "rmb", "smb", "stz", "trb", "tsb",
+/* 65sc02 mnemonics */
+ "bsr",
+/* 6510 mnemonics */
+ "anc", "asr", "ast", "arr", "asx", "axa", "dcp", "dea",
+ "dop", "ina", "isb", "lax", "phx", "phy", "plx", "ply",
+ "rla", "rra", "sax", "slo", "sre", "sah", "say", "ssh",
+ "sxh", "syh", "top", "oal", "kil",
+/* 65ce02 mnemonics */
+ "cle", "see", "rtn", "aug",
+ "tab", "tba", "taz", "tza", "tys", "tsy",
+ "ldz", "stz",
+ "dez", "inz", "cpz", "phz", "plz",
+ "neg", "asr",
+ "asw", "row", "dew", "inw", "phw",
+/* 4510 mnemonics */
+ "map",
+
+/* Deco CPU16 mnemonics */
+ "VBL", "u13", "u8F", "uAB", "u87", "u0B", "uA3", "u4B",
+ "u3F", "uBB", "u23"
+};
+
+struct op6502_info
+{
+ UINT8 opc;
+ UINT8 arg;
+};
+
+static const struct op6502_info op6502[256] = {
+ {m6502_brk,imm},{ora,idx},{kil,non},{slo,idx},/* 00 */
+ {nop,zpg},{ora,zpg},{asl,zpg},{slo,zpg},
+ {php,imp},{ora,imm},{asl,acc},{anc,imm},
+ {nop,aba},{ora,aba},{asl,aba},{slo,aba},
+ {bpl,rel},{ora,idy},{kil,non},{slo,idy},/* 10 */
+ {nop,zpx},{ora,zpx},{asl,zpx},{slo,zpx},
+ {clc,imp},{ora,aby},{nop,imp},{slo,aby},
+ {nop,abx},{ora,abx},{asl,abx},{slo,abx},
+ {jsr,adr},{and_,idx},{kil,non},{rla,idx},/* 20 */
+ {bit,zpg},{and_,zpg},{rol,zpg},{rla,zpg},
+ {plp,imp},{and_,imm},{rol,acc},{anc,imm},
+ {bit,aba},{and_,aba},{rol,aba},{rla,aba},
+ {bmi,rel},{and_,idy},{kil,non},{rla,idy},/* 30 */
+ {nop,zpx},{and_,zpx},{rol,zpx},{rla,zpx},
+ {sec,imp},{and_,aby},{nop,imp},{rla,aby},
+ {nop,abx},{and_,abx},{rol,abx},{rla,abx},
+ {rti,imp},{eor,idx},{kil,non},{sre,idx},/* 40 */
+ {nop,zpg},{eor,zpg},{lsr,zpg},{sre,zpg},
+ {pha,imp},{eor,imm},{lsr,acc},{asr,imm},
+ {jmp,adr},{eor,aba},{lsr,aba},{sre,aba},
+ {bvc,rel},{eor,idy},{kil,non},{sre,idy},/* 50 */
+ {nop,zpx},{eor,zpx},{lsr,zpx},{sre,zpx},
+ {cli,imp},{eor,aby},{nop,imp},{sre,aby},
+ {nop,abx},{eor,abx},{lsr,abx},{sre,abx},
+ {rts,imp},{adc,idx},{kil,non},{rra,idx},/* 60 */
+ {nop,zpg},{adc,zpg},{ror,zpg},{rra,zpg},
+ {pla,imp},{adc,imm},{ror,acc},{arr,imm},
+ {jmp,ind},{adc,aba},{ror,aba},{rra,aba},
+ {bvs,rel},{adc,idy},{kil,non},{rra,idy},/* 70 */
+ {nop,zpx},{adc,zpx},{ror,zpx},{rra,zpx},
+ {sei,imp},{adc,aby},{nop,imp},{rra,aby},
+ {nop,abx},{adc,abx},{ror,abx},{rra,abx},
+ {nop,imm},{sta,idx},{nop,imm},{sax,idx},/* 80 */
+ {sty,zpg},{sta,zpg},{stx,zpg},{sax,zpg},
+ {dey,imp},{nop,imm},{txa,imp},{axa,imm},
+ {sty,aba},{sta,aba},{stx,aba},{sax,aba},
+ {bcc,rel},{sta,idy},{kil,non},{say,idy},/* 90 */
+ {sty,zpx},{sta,zpx},{stx,zpy},{sax,zpy},
+ {tya,imp},{sta,aby},{txs,imp},{ssh,aby},
+ {syh,abx},{sta,abx},{sxh,aby},{sah,aby},
+ {ldy,imm},{lda,idx},{ldx,imm},{lax,idx},/* a0 */
+ {ldy,zpg},{lda,zpg},{ldx,zpg},{lax,zpg},
+ {tay,imp},{lda,imm},{tax,imp},{oal,imm},
+ {ldy,aba},{lda,aba},{ldx,aba},{lax,aba},
+ {bcs,rel},{lda,idy},{kil,non},{lax,idy},/* b0 */
+ {ldy,zpx},{lda,zpx},{ldx,zpy},{lax,zpy},
+ {clv,imp},{lda,aby},{tsx,imp},{ast,aby},
+ {ldy,abx},{lda,abx},{ldx,aby},{lax,aby},
+ {cpy,imm},{cmp,idx},{nop,imm},{dcp,idx},/* c0 */
+ {cpy,zpg},{cmp,zpg},{dec,zpg},{dcp,zpg},
+ {iny,imp},{cmp,imm},{dex,imp},{asx,imm},
+ {cpy,aba},{cmp,aba},{dec,aba},{dcp,aba},
+ {bne,rel},{cmp,idy},{kil,non},{dcp,idy},/* d0 */
+ {nop,zpx},{cmp,zpx},{dec,zpx},{dcp,zpx},
+ {cld,imp},{cmp,aby},{nop,imp},{dcp,aby},
+ {nop,abx},{cmp,abx},{dec,abx},{dcp,abx},
+ {cpx,imm},{sbc,idx},{nop,imm},{isb,idx},/* e0 */
+ {cpx,zpg},{sbc,zpg},{inc,zpg},{isb,zpg},
+ {inx,imp},{sbc,imm},{nop,imp},{sbc,imm},
+ {cpx,aba},{sbc,aba},{inc,aba},{isb,aba},
+ {beq,rel},{sbc,idy},{kil,non},{isb,idy},/* f0 */
+ {nop,zpx},{sbc,zpx},{inc,zpx},{isb,zpx},
+ {sed,imp},{sbc,aby},{nop,imp},{isb,aby},
+ {nop,abx},{sbc,abx},{inc,abx},{isb,abx}
+};
+
+static const struct op6502_info op65c02[256] = {
+ {m6502_brk,imm},{ora,idx},{ill,non},{ill,non},/* 00 */
+ {tsb,zpg},{ora,zpg},{asl,zpg},{rmb,zpg},
+ {php,imp},{ora,imm},{asl,acc},{ill,non},
+ {tsb,aba},{ora,aba},{asl,aba},{bbr,zpb},
+ {bpl,rel},{ora,idy},{ora,zpi},{ill,non},/* 10 */
+ {trb,zpg},{ora,zpx},{asl,zpx},{rmb,zpg},
+ {clc,imp},{ora,aby},{ina,imp},{ill,non},
+ {trb,aba},{ora,abx},{asl,abx},{bbr,zpb},
+ {jsr,adr},{and_,idx},{ill,non},{ill,non},/* 20 */
+ {bit,zpg},{and_,zpg},{rol,zpg},{rmb,zpg},
+ {plp,imp},{and_,imm},{rol,acc},{ill,non},
+ {bit,aba},{and_,aba},{rol,aba},{bbr,zpb},
+ {bmi,rel},{and_,idy},{and_,zpi},{ill,non},/* 30 */
+ {bit,zpx},{and_,zpx},{rol,zpx},{rmb,zpg},
+ {sec,imp},{and_,aby},{dea,imp},{ill,non},
+ {bit,abx},{and_,abx},{rol,abx},{bbr,zpb},
+ {rti,imp},{eor,idx},{ill,non},{ill,non},/* 40 */
+ {ill,non},{eor,zpg},{lsr,zpg},{rmb,zpg},
+ {pha,imp},{eor,imm},{lsr,acc},{ill,non},
+ {jmp,adr},{eor,aba},{lsr,aba},{bbr,zpb},
+ {bvc,rel},{eor,idy},{eor,zpi},{ill,non},/* 50 */
+ {ill,non},{eor,zpx},{lsr,zpx},{rmb,zpg},
+ {cli,imp},{eor,aby},{phy,imp},{ill,non},
+ {ill,non},{eor,abx},{lsr,abx},{bbr,zpb},
+ {rts,imp},{adc,idx},{ill,non},{ill,non},/* 60 */
+ {stz,zpg},{adc,zpg},{ror,zpg},{rmb,zpg},
+ {pla,imp},{adc,imm},{ror,acc},{ill,non},
+ {jmp,ind},{adc,aba},{ror,aba},{bbr,zpb},
+ {bvs,rel},{adc,idy},{adc,zpi},{ill,non},/* 70 */
+ {stz,zpx},{adc,zpx},{ror,zpx},{rmb,zpg},
+ {sei,imp},{adc,aby},{ply,imp},{ill,non},
+ {jmp,iax},{adc,abx},{ror,abx},{bbr,zpb},
+ {bra,rel},{sta,idx},{ill,non},{ill,non},/* 80 */
+ {sty,zpg},{sta,zpg},{stx,zpg},{smb,zpg},
+ {dey,imp},{bit,imm},{txa,imp},{ill,non},
+ {sty,aba},{sta,aba},{stx,aba},{bbs,zpb},
+ {bcc,rel},{sta,idy},{sta,zpi},{ill,non},/* 90 */
+ {sty,zpx},{sta,zpx},{stx,zpy},{smb,zpg},
+ {tya,imp},{sta,aby},{txs,imp},{ill,non},
+ {stz,aba},{sta,abx},{stz,abx},{bbs,zpb},
+ {ldy,imm},{lda,idx},{ldx,imm},{ill,non},/* a0 */
+ {ldy,zpg},{lda,zpg},{ldx,zpg},{smb,zpg},
+ {tay,imp},{lda,imm},{tax,imp},{ill,non},
+ {ldy,aba},{lda,aba},{ldx,aba},{bbs,zpb},
+ {bcs,rel},{lda,idy},{lda,zpi},{ill,non},/* b0 */
+ {ldy,zpx},{lda,zpx},{ldx,zpy},{smb,zpg},
+ {clv,imp},{lda,aby},{tsx,imp},{ill,non},
+ {ldy,abx},{lda,abx},{ldx,aby},{bbs,zpb},
+ {cpy,imm},{cmp,idx},{ill,non},{ill,non},/* c0 */
+ {cpy,zpg},{cmp,zpg},{dec,zpg},{smb,zpg},
+ {iny,imp},{cmp,imm},{dex,imp},{ill,non},
+ {cpy,aba},{cmp,aba},{dec,aba},{bbs,zpb},
+ {bne,rel},{cmp,idy},{cmp,zpi},{ill,non},/* d0 */
+ {ill,non},{cmp,zpx},{dec,zpx},{smb,zpg},
+ {cld,imp},{cmp,aby},{phx,imp},{ill,non},
+ {ill,non},{cmp,abx},{dec,abx},{bbs,zpb},
+ {cpx,imm},{sbc,idx},{ill,non},{ill,non},/* e0 */
+ {cpx,zpg},{sbc,zpg},{inc,zpg},{smb,zpg},
+ {inx,imp},{sbc,imm},{nop,imp},{ill,non},
+ {cpx,aba},{sbc,aba},{inc,aba},{bbs,zpb},
+ {beq,rel},{sbc,idy},{sbc,zpi},{ill,non},/* f0 */
+ {ill,non},{sbc,zpx},{inc,zpx},{smb,zpg},
+ {sed,imp},{sbc,aby},{plx,imp},{ill,non},
+ {ill,non},{sbc,abx},{inc,abx},{bbs,zpb}
+};
+
+/* only bsr additional to 65c02 yet */
+static const struct op6502_info op65sc02[256] = {
+ {m6502_brk,imm},{ora,idx},{ill,non},{ill,non},/* 00 */
+ {tsb,zpg},{ora,zpg},{asl,zpg},{rmb,zpg},
+ {php,imp},{ora,imm},{asl,acc},{ill,non},
+ {tsb,aba},{ora,aba},{asl,aba},{bbr,zpb},
+ {bpl,rel},{ora,idy},{ora,zpi},{ill,non},/* 10 */
+ {trb,zpg},{ora,zpx},{asl,zpx},{rmb,zpg},
+ {clc,imp},{ora,aby},{ina,imp},{ill,non},
+ {trb,aba},{ora,abx},{asl,abx},{bbr,zpb},
+ {jsr,adr},{and_,idx},{ill,non},{ill,non},/* 20 */
+ {bit,zpg},{and_,zpg},{rol,zpg},{rmb,zpg},
+ {plp,imp},{and_,imm},{rol,acc},{ill,non},
+ {bit,aba},{and_,aba},{rol,aba},{bbr,zpb},
+ {bmi,rel},{and_,idy},{and_,zpi},{ill,non},/* 30 */
+ {bit,zpx},{and_,zpx},{rol,zpx},{rmb,zpg},
+ {sec,imp},{and_,aby},{dea,imp},{ill,non},
+ {bit,abx},{and_,abx},{rol,abx},{bbr,zpb},
+ {rti,imp},{eor,idx},{ill,non},{ill,non},/* 40 */
+ {ill,non},{eor,zpg},{lsr,zpg},{rmb,zpg},
+ {pha,imp},{eor,imm},{lsr,acc},{ill,non},
+ {jmp,adr},{eor,aba},{lsr,aba},{bbr,zpb},
+ {bvc,rel},{eor,idy},{eor,zpi},{ill,non},/* 50 */
+ {ill,non},{eor,zpx},{lsr,zpx},{rmb,zpg},
+ {cli,imp},{eor,aby},{phy,imp},{ill,non},
+ {ill,non},{eor,abx},{lsr,abx},{bbr,zpb},
+ {rts,imp},{adc,idx},{ill,non},{bsr,rw2},/* 60 */
+ {stz,zpg},{adc,zpg},{ror,zpg},{rmb,zpg},
+ {pla,imp},{adc,imm},{ror,acc},{ill,non},
+ {jmp,ind},{adc,aba},{ror,aba},{bbr,zpb},
+ {bvs,rel},{adc,idy},{adc,zpi},{ill,non},/* 70 */
+ {stz,zpx},{adc,zpx},{ror,zpx},{rmb,zpg},
+ {sei,imp},{adc,aby},{ply,imp},{ill,non},
+ {jmp,iax},{adc,abx},{ror,abx},{bbr,zpb},
+ {bra,rel},{sta,idx},{ill,non},{ill,non},/* 80 */
+ {sty,zpg},{sta,zpg},{stx,zpg},{smb,zpg},
+ {dey,imp},{bit,imm},{txa,imp},{ill,non},
+ {sty,aba},{sta,aba},{stx,aba},{bbs,zpb},
+ {bcc,rel},{sta,idy},{sta,zpi},{ill,non},/* 90 */
+ {sty,zpx},{sta,zpx},{stx,zpy},{smb,zpg},
+ {tya,imp},{sta,aby},{txs,imp},{ill,non},
+ {stz,aba},{sta,abx},{stz,abx},{bbs,zpb},
+ {ldy,imm},{lda,idx},{ldx,imm},{ill,non},/* a0 */
+ {ldy,zpg},{lda,zpg},{ldx,zpg},{smb,zpg},
+ {tay,imp},{lda,imm},{tax,imp},{ill,non},
+ {ldy,aba},{lda,aba},{ldx,aba},{bbs,zpb},
+ {bcs,rel},{lda,idy},{lda,zpi},{ill,non},/* b0 */
+ {ldy,zpx},{lda,zpx},{ldx,zpy},{smb,zpg},
+ {clv,imp},{lda,aby},{tsx,imp},{ill,non},
+ {ldy,abx},{lda,abx},{ldx,aby},{bbs,zpb},
+ {cpy,imm},{cmp,idx},{ill,non},{ill,non},/* c0 */
+ {cpy,zpg},{cmp,zpg},{dec,zpg},{smb,zpg},
+ {iny,imp},{cmp,imm},{dex,imp},{ill,non},
+ {cpy,aba},{cmp,aba},{dec,aba},{bbs,zpb},
+ {bne,rel},{cmp,idy},{cmp,zpi},{ill,non},/* d0 */
+ {ill,non},{cmp,zpx},{dec,zpx},{smb,zpg},
+ {cld,imp},{cmp,aby},{phx,imp},{ill,non},
+ {ill,non},{cmp,abx},{dec,abx},{bbs,zpb},
+ {cpx,imm},{sbc,idx},{ill,non},{ill,non},/* e0 */
+ {cpx,zpg},{sbc,zpg},{inc,zpg},{smb,zpg},
+ {inx,imp},{sbc,imm},{nop,imp},{ill,non},
+ {cpx,aba},{sbc,aba},{inc,aba},{bbs,zpb},
+ {beq,rel},{sbc,idy},{sbc,zpi},{ill,non},/* f0 */
+ {ill,non},{sbc,zpx},{inc,zpx},{smb,zpg},
+ {sed,imp},{sbc,aby},{plx,imp},{ill,non},
+ {ill,non},{sbc,abx},{inc,abx},{bbs,zpb}
+};
+
+static const struct op6502_info op65ce02[256] = {
+ {m6502_brk,imm},{ora,idx},{cle,imp},{see,imp},/* 00 */
+ {tsb,zpg},{ora,zpg},{asl,zpg},{rmb,zpg},
+ {php,imp},{ora,imm},{asl,acc},{tsy,imp},
+ {tsb,aba},{ora,aba},{asl,aba},{bbr,zpb},
+ {bpl,rel},{ora,idy},{ora,idz},{bpl,rw2},/* 10 */
+ {trb,zpg},{ora,zpx},{asl,zpx},{rmb,zpg},
+ {clc,imp},{ora,aby},{ina,imp},{inz,imp},
+ {trb,aba},{ora,abx},{asl,abx},{bbr,zpb},
+ {jsr,adr},{and_,idx},{jsr,ind},{jsr,iax},/* 20 */
+ {bit,zpg},{and_,zpg},{rol,zpg},{rmb,zpg},
+ {plp,imp},{and_,imm},{rol,acc},{tys,imp},
+ {bit,aba},{and_,aba},{rol,aba},{bbr,zpb},
+ {bmi,rel},{and_,idz},{and_,zpi},{bmi,rw2},/* 30 */
+ {bit,zpx},{and_,zpx},{rol,zpx},{rmb,zpg},
+ {sec,imp},{and_,aby},{dea,imp},{dez,imp},
+ {bit,abx},{and_,abx},{rol,abx},{bbr,zpb},
+ {rti,imp},{eor,idx},{neg,imp},{asr2,imp},/* 40 */
+ {asr2,zpg},{eor,zpg},{lsr,zpg},{rmb,zpg},
+ {pha,imp},{eor,imm},{lsr,acc},{taz,imp},
+ {jmp,adr},{eor,aba},{lsr,aba},{bbr,zpb},
+ {bvc,rel},{eor,idy},{eor,idz},{bvc,rw2},/* 50 */
+ {asr2,zpx},{eor,zpx},{lsr,zpx},{rmb,zpg},
+ {cli,imp},{eor,aby},{phy,imp},{tab,imp},
+ {aug,iw3},{eor,abx},{lsr,abx},{bbr,zpb},
+ {rts,imp},{adc,idx},{rtn,imm},{bsr,rw2},/* 60 */
+ {stz2,zpg},{adc,zpg},{ror,zpg},{rmb,zpg},
+ {pla,imp},{adc,imm},{ror,acc},{tza,imp},
+ {jmp,ind},{adc,aba},{ror,aba},{bbr,zpb},
+ {bvs,rel},{adc,idy},{adc,zpi},{bvs,rw2},/* 70 */
+ {stz2,zpx},{adc,zpx},{ror,zpx},{rmb,zpg},
+ {sei,imp},{adc,aby},{ply,imp},{tba,imp},
+ {jmp,iax},{adc,abx},{ror,abx},{bbr,zpb},
+ {bra,rel},{sta,idx},{sta,isy},{bra,rw2},/* 80 */
+ {sty,zpg},{sta,zpg},{stx,zpg},{smb,zpg},
+ {dey,imp},{bit,imm},{txa,imp},{sty,abx},
+ {sty,aba},{sta,aba},{stx,aba},{bbs,zpb},
+ {bcc,rel},{sta,idy},{sta,inz},{bcc,rw2},/* 90 */
+ {sty,zpx},{sta,zpx},{stx,zpy},{smb,zpg},
+ {tya,imp},{sta,aby},{txs,imp},{stx,aby},
+ {stz2,aba},{sta,abx},{stz2,abx},{bbs,zpb},
+ {ldy,imm},{lda,idx},{ldx,imm},{ldz,imm},/* a0 */
+ {ldy,zpg},{lda,zpg},{ldx,zpg},{smb,zpg},
+ {tay,imp},{lda,imm},{tax,imp},{ldz,aba},
+ {ldy,aba},{lda,aba},{ldx,aba},{bbs,zpb},
+ {bcs,rel},{lda,idy},{lda,inz},{bcs,rw2},/* b0 */
+ {ldy,zpx},{lda,zpx},{ldx,zpy},{smb,zpg},
+ {clv,imp},{lda,aby},{tsx,imp},{ldz,abx},
+ {ldy,abx},{lda,abx},{ldx,aby},{bbs,zpb},
+ {cpy,imm},{cmp,idx},{cpz,imm},{dew,zpg},/* c0 */
+ {cpy,zpg},{cmp,zpg},{dec,zpg},{smb,zpg},
+ {iny,imp},{cmp,imm},{dex,imp},{asw,aba},
+ {cpy,aba},{cmp,aba},{dec,aba},{bbs,zpb},
+ {bne,rel},{cmp,idy},{cmp,idz},{bne,rw2},/* d0 */
+ {cpz,zpg},{cmp,zpx},{dec,zpx},{smb,zpg},
+ {cld,imp},{cmp,aby},{phx,imp},{phz,imp},
+ {cpz,aba},{cmp,abx},{dec,abx},{bbs,zpb},
+ {cpx,imm},{sbc,idx},{lda,isy},{inw,zpg},/* e0 */
+ {cpx,zpg},{sbc,zpg},{inc,zpg},{smb,zpg},
+ {inx,imp},{sbc,imm},{nop,imp},{row,aba},
+ {cpx,aba},{sbc,aba},{inc,aba},{bbs,zpb},
+ {beq,rel},{sbc,idy},{sbc,idz},{beq,rw2},/* f0 */
+ {phw,iw2},{sbc,zpx},{inc,zpx},{smb,zpg},
+ {sed,imp},{sbc,aby},{plx,imp},{plz,imp},
+ {phw,aba},{sbc,abx},{inc,abx},{bbs,zpb}
+};
+
+// only map instead of aug and 20 bit memory management
+static const struct op6502_info op4510[256] = {
+ {m6502_brk,imm},{ora,idx},{cle,imp},{see,imp},/* 00 */
+ {tsb,zpg},{ora,zpg},{asl,zpg},{rmb,zpg},
+ {php,imp},{ora,imm},{asl,acc},{tsy,imp},
+ {tsb,aba},{ora,aba},{asl,aba},{bbr,zpb},
+ {bpl,rel},{ora,idy},{ora,idz},{bpl,rw2},/* 10 */
+ {trb,zpg},{ora,zpx},{asl,zpx},{rmb,zpg},
+ {clc,imp},{ora,aby},{ina,imp},{inz,imp},
+ {trb,aba},{ora,abx},{asl,abx},{bbr,zpb},
+ {jsr,adr},{and_,idx},{jsr,ind},{jsr,iax},/* 20 */
+ {bit,zpg},{and_,zpg},{rol,zpg},{rmb,zpg},
+ {plp,imp},{and_,imm},{rol,acc},{tys,imp},
+ {bit,aba},{and_,aba},{rol,aba},{bbr,zpb},
+ {bmi,rel},{and_,idz},{and_,zpi},{bmi,rw2},/* 30 */
+ {bit,zpx},{and_,zpx},{rol,zpx},{rmb,zpg},
+ {sec,imp},{and_,aby},{dea,imp},{dez,imp},
+ {bit,abx},{and_,abx},{rol,abx},{bbr,zpb},
+ {rti,imp},{eor,idx},{neg,imp},{asr2,imp},/* 40 */
+ {asr2,zpg},{eor,zpg},{lsr,zpg},{rmb,zpg},
+ {pha,imp},{eor,imm},{lsr,acc},{taz,imp},
+ {jmp,adr},{eor,aba},{lsr,aba},{bbr,zpb},
+ {bvc,rel},{eor,idy},{eor,idz},{bvc,rw2},/* 50 */
+ {asr2,zpx},{eor,zpx},{lsr,zpx},{rmb,zpg},
+ {cli,imp},{eor,aby},{phy,imp},{tab,imp},
+ {map,imp},{eor,abx},{lsr,abx},{bbr,zpb},
+ {rts,imp},{adc,idx},{rtn,imm},{bsr,rw2},/* 60 */
+ {stz2,zpg},{adc,zpg},{ror,zpg},{rmb,zpg},
+ {pla,imp},{adc,imm},{ror,acc},{tza,imp},
+ {jmp,ind},{adc,aba},{ror,aba},{bbr,zpb},
+ {bvs,rel},{adc,idy},{adc,zpi},{bvs,rw2},/* 70 */
+ {stz2,zpx},{adc,zpx},{ror,zpx},{rmb,zpg},
+ {sei,imp},{adc,aby},{ply,imp},{tba,imp},
+ {jmp,iax},{adc,abx},{ror,abx},{bbr,zpb},
+ {bra,rel},{sta,idx},{sta,isy},{bra,rw2},/* 80 */
+ {sty,zpg},{sta,zpg},{stx,zpg},{smb,zpg},
+ {dey,imp},{bit,imm},{txa,imp},{sty,abx},
+ {sty,aba},{sta,aba},{stx,aba},{bbs,zpb},
+ {bcc,rel},{sta,idy},{sta,inz},{bcc,rw2},/* 90 */
+ {sty,zpx},{sta,zpx},{stx,zpy},{smb,zpg},
+ {tya,imp},{sta,aby},{txs,imp},{stx,aby},
+ {stz2,aba},{sta,abx},{stz2,abx},{bbs,zpb},
+ {ldy,imm},{lda,idx},{ldx,imm},{ldz,imm},/* a0 */
+ {ldy,zpg},{lda,zpg},{ldx,zpg},{smb,zpg},
+ {tay,imp},{lda,imm},{tax,imp},{ldz,aba},
+ {ldy,aba},{lda,aba},{ldx,aba},{bbs,zpb},
+ {bcs,rel},{lda,idy},{lda,inz},{bcs,rw2},/* b0 */
+ {ldy,zpx},{lda,zpx},{ldx,zpy},{smb,zpg},
+ {clv,imp},{lda,aby},{tsx,imp},{ldz,abx},
+ {ldy,abx},{lda,abx},{ldx,aby},{bbs,zpb},
+ {cpy,imm},{cmp,idx},{cpz,imm},{dew,zpg},/* c0 */
+ {cpy,zpg},{cmp,zpg},{dec,zpg},{smb,zpg},
+ {iny,imp},{cmp,imm},{dex,imp},{asw,aba},
+ {cpy,aba},{cmp,aba},{dec,aba},{bbs,zpb},
+ {bne,rel},{cmp,idy},{cmp,idz},{bne,rw2},/* d0 */
+ {cpz,zpg},{cmp,zpx},{dec,zpx},{smb,zpg},
+ {cld,imp},{cmp,aby},{phx,imp},{phz,imp},
+ {cpz,aba},{cmp,abx},{dec,abx},{bbs,zpb},
+ {cpx,imm},{sbc,idx},{lda,isy},{inw,zpg},/* e0 */
+ {cpx,zpg},{sbc,zpg},{inc,zpg},{smb,zpg},
+ {inx,imp},{sbc,imm},{nop,imp},{row,aba},
+ {cpx,aba},{sbc,aba},{inc,aba},{bbs,zpb},
+ {beq,rel},{sbc,idy},{sbc,idz},{beq,rw2},/* f0 */
+ {phw,iw2},{sbc,zpx},{inc,zpx},{smb,zpg},
+ {sed,imp},{sbc,aby},{plx,imp},{plz,imp},
+ {phw,aba},{sbc,abx},{inc,abx},{bbs,zpb}
+};
+
+static const struct op6502_info opdeco16[256] =
+{
+ {m6502_brk,imp},{ora,idx},{ill,non},{ill,non},/* 00 */
+ {ill,non},{ora,zpg},{asl,zpg},{ill,non},
+ {php,imp},{ora,imm},{asl,acc},{u0B,zpg},
+ {ill,non},{ora,aba},{asl,aba},{ill,non},
+ {bpl,rel},{ora,idy},{ill,non},{u13,zpg},/* 10 */
+ {ill,non},{ora,zpx},{asl,zpx},{ill,non},
+ {clc,imp},{ora,aby},{ill,non},{ill,non},
+ {ill,non},{ora,abx},{asl,abx},{ill,non},
+ {jsr,adr},{and_,idx},{ill,non},{u23,zpg},/* 20 */
+ {bit,zpg},{and_,zpg},{rol,zpg},{ill,non},
+ {plp,imp},{and_,imm},{rol,acc},{ill,non},
+ {bit,aba},{and_,aba},{rol,aba},{ill,non},
+ {bmi,rel},{and_,idy},{ill,non},{ill,non},/* 30 */
+ {ill,non},{and_,zpx},{rol,zpx},{ill,non},
+ {sec,imp},{and_,aby},{ill,non},{ill,non},
+ {ill,non},{and_,abx},{rol,abx},{u3F,zpg},
+ {rti,imp},{eor,idx},{ill,non},{ill,non},/* 40 */
+ {ill,non},{eor,zpg},{lsr,zpg},{ill,non},
+ {pha,imp},{eor,imm},{lsr,acc},{u4B,zpg},
+ {jmp,adr},{eor,aba},{lsr,aba},{ill,non},
+ {bvc,rel},{eor,idy},{ill,non},{ill,non},/* 50 */
+ {ill,non},{eor,zpx},{lsr,zpx},{ill,non},
+ {cli,imp},{eor,aby},{ill,non},{ill,non},
+ {ill,non},{eor,abx},{lsr,abx},{ill,non},
+ {rts,imp},{adc,idx},{ill,non},{ill,non},/* 60 */
+ {ill,non},{adc,zpg},{ror,zpg},{vbl,zpg}, // MISH
+ {pla,imp},{adc,imm},{ror,acc},{ill,non},
+ {jmp,ind},{adc,aba},{ror,aba},{ill,non},
+ {bvs,rel},{adc,idy},{ill,non},{ill,non},/* 70 */
+ {ill,non},{adc,zpx},{ror,zpx},{ill,non},
+ {sei,imp},{adc,aby},{ill,non},{ill,non},
+ {ill,non},{adc,abx},{ror,abx},{ill,non},
+ {ill,non},{sta,idx},{ill,non},{ill,non},/* 80 */
+ {sty,zpg},{sta,zpg},{stx,zpg},{u87,zpg},
+ {dey,imp},{ill,non},{txa,imp},{ill,non},
+ {sty,aba},{sta,aba},{stx,aba},{u8F,zpg},
+ {bcc,rel},{sta,idy},{ill,non},{ill,non},/* 90 */
+ {sty,zpx},{sta,zpx},{stx,zpy},{ill,non},
+ {tya,imp},{sta,aby},{txs,imp},{ill,non},
+ {ill,non},{sta,abx},{ill,non},{ill,non},
+ {ldy,imm},{lda,idx},{ldx,imm},{uA3,zpg},/* a0 */
+ {ldy,zpg},{lda,zpg},{ldx,zpg},{ill,non},
+ {tay,imp},{lda,imm},{tax,imp},{uAB,zpg},
+ {ldy,aba},{lda,aba},{ldx,aba},{ill,non},
+ {bcs,rel},{lda,idy},{ill,non},{ill,non},/* b0 */
+ {ldy,zpx},{lda,zpx},{ldx,zpy},{ill,non},
+ {clv,imp},{lda,aby},{tsx,imp},{uBB,zpg},
+ {ldy,abx},{lda,abx},{ldx,aby},{ill,non},
+ {cpy,imm},{cmp,idx},{ill,non},{ill,non},/* c0 */
+ {cpy,zpg},{cmp,zpg},{dec,zpg},{ill,non},
+ {iny,imp},{cmp,imm},{dex,imp},{ill,non},
+ {cpy,aba},{cmp,aba},{dec,aba},{ill,non},
+ {bne,rel},{cmp,idy},{ill,non},{ill,non},/* d0 */
+ {ill,non},{cmp,zpx},{dec,zpx},{ill,non},
+ {cld,imp},{cmp,aby},{ill,non},{ill,non},
+ {ill,non},{cmp,abx},{dec,abx},{ill,non},
+ {cpx,imm},{sbc,idx},{ill,non},{ill,non},/* e0 */
+ {cpx,zpg},{sbc,zpg},{inc,zpg},{ill,non},
+ {inx,imp},{sbc,imm},{nop,imp},{ill,non},
+ {cpx,aba},{sbc,aba},{inc,aba},{ill,non},
+ {beq,rel},{sbc,idy},{ill,non},{ill,non},/* f0 */
+ {ill,non},{sbc,zpx},{inc,zpx},{ill,non},
+ {sed,imp},{sbc,aby},{ill,non},{ill,non},
+ {ill,non},{sbc,abx},{inc,abx},{ill,non}
+};
+
+/*****************************************************************************
+ * Disassemble a single opcode starting at pc
+ *****************************************************************************/
+static unsigned internal_m6502_dasm(const struct op6502_info *opinfo, char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram)
+{
+ char *dst = buffer;
+ INT8 offset;
+ INT16 offset16;
+ unsigned PC = pc;
+ UINT16 addr;
+ UINT8 op, opc, arg, value;
+ UINT32 flags;
+ int pos = 0;
+
+ op = oprom[pos++];
+ pc++;
+
+ opc = opinfo[op].opc;
+ arg = opinfo[op].arg;
+
+ /* determine dasmflags */
+ switch(opc)
+ {
+ case jsr:
+ case bsr:
+ flags = DASMFLAG_SUPPORTED | DASMFLAG_STEP_OVER;
+ break;
+
+ case rts:
+ case rti:
+ case rtn:
+ flags = DASMFLAG_SUPPORTED | DASMFLAG_STEP_OUT;
+ break;
+
+ default:
+ flags = DASMFLAG_SUPPORTED;
+ break;
+ }
+
+ dst += sprintf(dst, "%-5s", token[opc]);
+ if( opc == bbr || opc == bbs || opc == rmb || opc == smb )
+ dst += sprintf(dst, "%d,", (op >> 4) & 7);
+
+ switch(arg)
+ {
+ case imp:
+ break;
+
+ case acc:
+ dst += sprintf(dst,"a");
+ break;
+
+ case rel:
+ offset = (INT8) opram[pos++];
+ pc++;
+ dst += sprintf(dst, "$%04X", (pc + offset) & 0xFFFF);
+ break;
+
+ case rw2:
+ offset16 = (opram[pos] | (opram[pos+1] << 8)) -1;
+ pos += 2;
+ pc += 2;
+ dst += sprintf(dst, "$%04X", (pc + offset16) & 0xFFFF);
+ break;
+
+ case imm:
+ value = opram[pos++];
+ pc++;
+ dst += sprintf(dst,"#$%02X", value);
+ break;
+
+ case zpg:
+ addr = opram[pos++];
+ pc++;
+ dst += sprintf(dst,"$%02X", addr);
+ break;
+
+ case zpx:
+ addr = opram[pos++];
+ pc++;
+ dst += sprintf(dst,"$%02X,x", addr);
+ break;
+
+ case zpy:
+ addr = opram[pos++];
+ pc++;
+ dst += sprintf(dst,"$%02X,y", addr);
+ break;
+
+ case idx:
+ addr = opram[pos++];
+ pc++;
+ dst += sprintf(dst,"($%02X,x)", addr);
+ break;
+
+ case idy:
+ addr = opram[pos++];
+ pc++;
+ dst += sprintf(dst,"($%02X),y", addr);
+ break;
+
+ case zpi:
+ addr = opram[pos++];
+ pc++;
+ dst += sprintf(dst,"($%02X)", addr);
+ break;
+
+ case zpb:
+ addr = opram[pos++];
+ pc++;
+ dst += sprintf(dst,"$%02X", addr);
+ offset = (INT8) opram[pos++];
+ pc++;
+ dst += sprintf(dst,",$%04X", pc + offset);
+ break;
+
+ case adr:
+ addr = (opram[pos] | (opram[pos+1] << 8));
+ pos += 2;
+ pc += 2;
+ dst += sprintf(dst, "$%04X", addr);
+ break;
+
+ case aba:
+ addr = (opram[pos] | (opram[pos+1] << 8));
+ pos += 2;
+ pc += 2;
+ dst += sprintf(dst, "$%04X", addr);
+ break;
+
+ case abx:
+ addr = (opram[pos] | (opram[pos+1] << 8));
+ pos += 2;
+ pc += 2;
+ dst += sprintf(dst,"$%04X,x", addr);
+ break;
+
+ case aby:
+ addr = (opram[pos] | (opram[pos+1] << 8));
+ pos += 2;
+ pc += 2;
+ dst += sprintf(dst,"$%04X,y", addr);
+ break;
+
+ case ind:
+ addr = (opram[pos] | (opram[pos+1] << 8));
+ pos += 2;
+ pc += 2;
+ dst += sprintf(dst,"($%04X)", addr);
+ break;
+
+ case iax:
+ addr = (opram[pos] | (opram[pos+1] << 8));
+ pos += 2;
+ pc += 2;
+ dst += sprintf(dst,"($%04X),X", addr);
+ break;
+
+ case iw2:
+ addr = (opram[pos] | (opram[pos+1] << 8));
+ pos += 2;
+ pc += 2;
+ dst += sprintf(dst,"#%04X", addr);
+ break;
+
+ case iw3:
+ addr = (opram[pos] | (opram[pos+1] << 8) | (opram[pos+2] << 16));
+ pos += 3;
+ pc += 3;
+ dst += sprintf(dst,"#%06x", addr);
+ break;
+
+ case idz:
+ addr = (INT8) opram[pos++];
+ pc++;
+ dst += sprintf(dst,"($%02X),z", addr);
+ break;
+
+ case isy:
+ op = opram[pos++];
+ pc++;
+ addr = op;
+ dst += sprintf(dst,"(s,$%02X),y", addr);
+ break;
+
+ default:
+ dst += sprintf(dst,"$%02X", op);
+ break;
+ }
+ return (pc - PC) | flags;
+}
+
+CPU_DISASSEMBLE( m6502 )
+{
+ return internal_m6502_dasm(op6502, buffer, pc, oprom, opram);
+}
+
+CPU_DISASSEMBLE( m65sc02 )
+{
+ return internal_m6502_dasm(op65sc02, buffer, pc, oprom, opram);
+}
+
+CPU_DISASSEMBLE( m65c02 )
+{
+ return internal_m6502_dasm(op65c02, buffer, pc, oprom, opram);
+}
+
+CPU_DISASSEMBLE( m65ce02 )
+{
+ return internal_m6502_dasm(op65ce02, buffer, pc, oprom, opram);
+}
+
+CPU_DISASSEMBLE( m6510 )
+{
+ return internal_m6502_dasm(op6502, buffer, pc, oprom, opram);
+}
+
+CPU_DISASSEMBLE( deco16 )
+{
+ return internal_m6502_dasm(opdeco16, buffer, pc, oprom, opram);
+}
+
+CPU_DISASSEMBLE( m4510 )
+{
+ return internal_m6502_dasm(op4510, buffer, pc, oprom, opram);
+}
diff --git a/trunk/src/emu/cpu/m6502/ill02.h b/trunk/src/emu/cpu/m6502/ill02.h
new file mode 100644
index 00000000000..0a69bbaf818
--- /dev/null
+++ b/trunk/src/emu/cpu/m6502/ill02.h
@@ -0,0 +1,337 @@
+#pragma once
+
+#ifndef __ILL02_H__
+#define __ILL02_H__
+
+/*****************************************************************************
+ *
+ * ill02.h
+ * Addressing mode and opcode macros for the NMOS 6502 illegal opcodes
+ *
+ * Copyright Juergen Buchmueller, all rights reserved.
+ * 65sc02 core Copyright Peter Trauner, all rights reserved.
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * pullmoll@t-online.de
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ *****************************************************************************/
+
+/* test with the excellent C64 Emulator test suite
+ ? at www.funet.fi/pub/cbm/documents/chipdata/tsuit215.zip
+ good reference in the vice emulator (source) distribution doc/64doc.txt
+
+ $ab=OAL like in 6502-NMOS.extra.opcodes, vice so in vice (lxa)
+*/
+
+/***************************************************************
+ ***************************************************************
+ * Macros to emulate the 6510 opcodes
+ ***************************************************************
+ ***************************************************************/
+
+/* 6510 ********************************************************
+ * ANC logical and, set carry from bit of A
+ ***************************************************************/
+#define ANC \
+ P &= ~F_C; \
+ A = (UINT8)(A & tmp); \
+ if (A & 0x80) \
+ P |= F_C; \
+ SET_NZ(A)
+
+/* 6510 ********************************************************
+ * ASR logical and, logical shift right
+ ***************************************************************/
+#define ASR \
+ tmp &= A; \
+ LSR
+
+/* 6510 ********************************************************
+ * AST and stack; transfer to accumulator and index X
+ * logical and stack (LSB) with data, transfer result to S
+ * transfer result to accumulator and index X also
+ ***************************************************************/
+#define AST \
+ S &= tmp; \
+ A = X = S; \
+ SET_NZ(A)
+
+/* 6510 ********************************************************
+ * ARR logical and, rotate right
+ ***************************************************************/
+#define ARR \
+ if( P & F_D ) \
+ { \
+ int lo, hi, t; \
+ tmp &= A; \
+ t = tmp; \
+ hi = tmp &0xf0; \
+ lo = tmp &0x0f; \
+ if( P & F_C ) \
+ { \
+ tmp = (tmp >> 1) | 0x80; \
+ P |= F_N; \
+ } \
+ else \
+ { \
+ tmp >>= 1; \
+ P &= ~F_N; \
+ } \
+ if( tmp ) \
+ P &= ~F_Z; \
+ else \
+ P |= F_Z; \
+ if( (t^tmp) & 0x40 ) \
+ P|=F_V; \
+ else \
+ P &= ~F_V; \
+ if( lo + (lo & 0x01) > 0x05 ) \
+ tmp = (tmp & 0xf0) | ((tmp+6) & 0xf); \
+ if( hi + (hi & 0x10) > 0x50 ) \
+ { \
+ P |= F_C; \
+ tmp = (tmp+0x60) & 0xff; \
+ } \
+ else \
+ P &= ~F_C; \
+ } \
+ else \
+ { \
+ tmp &= A; \
+ ROR; \
+ P &=~(F_V|F_C); \
+ if( tmp & 0x40 ) \
+ P|=F_C; \
+ if( (tmp & 0x60) == 0x20 || (tmp & 0x60) == 0x40 ) \
+ P|=F_V; \
+ }
+
+/* 6510 ********************************************************
+ * ASX logical and X w/ A, subtract data from X
+ ***************************************************************/
+#define ASX \
+ P &= ~F_C; \
+ X &= A; \
+ if (X >= tmp) \
+ P |= F_C; \
+ X = (UINT8)(X - tmp); \
+ SET_NZ(X)
+
+/* 6510 ********************************************************
+ * AXA transfer index X to accumulator, logical and
+ * depends on the data of the dma device (videochip) fetched
+ * between opcode read and operand read
+ ***************************************************************/
+#define AXA \
+ A = (UINT8)( (A|0xee)& X & tmp); \
+ SET_NZ(A)
+
+/* 6510 ********************************************************
+ * DCP decrement data and compare
+ ***************************************************************/
+#define DCP \
+ tmp = (UINT8)(tmp-1); \
+ P &= ~F_C; \
+ if (A >= tmp) \
+ P |= F_C; \
+ SET_NZ((UINT8)(A - tmp))
+
+/* 6502 ********************************************************
+ * DOP double no operation
+ ***************************************************************/
+#define DOP \
+ RDOPARG()
+
+/* 6510 ********************************************************
+ * ISB increment and subtract with carry
+ ***************************************************************/
+#define ISB \
+ tmp = (UINT8)(tmp+1); \
+ SBC
+
+/* 6510 ********************************************************
+ * LAX load accumulator and index X
+ ***************************************************************/
+#define LAX \
+ A = X = (UINT8)tmp; \
+ SET_NZ(A)
+
+/* 6510 ********************************************************
+ * OAL load accumulator and index X
+ ***************************************************************/
+#define OAL \
+ A = X = (UINT8)((A|0xee)&tmp); \
+ SET_NZ(A)
+
+/* 6510 ********************************************************
+ * RLA rotate left and logical and accumulator
+ * new C <- [7][6][5][4][3][2][1][0] <- C
+ ***************************************************************/
+#define RLA \
+ tmp = (tmp << 1) | (P & F_C); \
+ P = (P & ~F_C) | ((tmp >> 8) & F_C); \
+ tmp = (UINT8)tmp; \
+ A &= tmp; \
+ SET_NZ(A)
+
+/* 6510 ********************************************************
+ * RRA rotate right and add with carry
+ * C -> [7][6][5][4][3][2][1][0] -> C
+ ***************************************************************/
+#define RRA \
+ tmp |= (P & F_C) << 8; \
+ P = (P & ~F_C) | (tmp & F_C); \
+ tmp = (UINT8)(tmp >> 1); \
+ ADC
+
+/* 6510 ********************************************************
+ * SAX logical and accumulator with index X and store
+ ***************************************************************/
+#define SAX \
+ tmp = A & X
+
+/* 6510 ********************************************************
+ * SLO shift left and logical or
+ ***************************************************************/
+#define SLO \
+ P = (P & ~F_C) | ((tmp >> 7) & F_C); \
+ tmp = (UINT8)(tmp << 1); \
+ A |= tmp; \
+ SET_NZ(A)
+
+/* 6510 ********************************************************
+ * SRE logical shift right and logical exclusive or
+ * 0 -> [7][6][5][4][3][2][1][0] -> C
+ ***************************************************************/
+#define SRE \
+ P = (P & ~F_C) | (tmp & F_C); \
+ tmp = (UINT8)tmp >> 1; \
+ A ^= tmp; \
+ SET_NZ(A)
+
+/* 6510 ********************************************************
+ * SAH store accumulator and index X and high + 1
+ * result = accumulator and index X and memory [PC+1] + 1
+ ***************************************************************/
+#define SAH tmp = A & X & (EAH+1)
+
+/* 6510 ********************************************************
+ * SSH store stack high
+ * logical and accumulator with index X, transfer result to S
+ * logical and result with memory [PC+1] + 1
+ ***************************************************************/
+#define SSH \
+ S = A & X; \
+ tmp = S & (EAH+1)
+#if 0
+#define SSH \
+ tmp = S = A & X; \
+ tmp &= (UINT8)(cpustate->direct->read_raw_byte((PCW + 1) & 0xffff) + 1)
+#endif
+
+/* 6510 ********************************************************
+ * SXH store index X high
+ * logical and index X with memory[PC+1] and store the result
+ ***************************************************************/
+#define SXH tmp = X & (EAH+1)
+
+/* 6510 ********************************************************
+ * SYH store index Y and (high + 1)
+ * logical and index Y with memory[PC+1] + 1 and store the result
+ ***************************************************************/
+#define SYH tmp = Y & (EAH+1)
+
+/* 6510 ********************************************************
+ * TOP triple no operation
+ ***************************************************************/
+#define TOP \
+ PCW+=2
+
+/* 6510 ********************************************************
+ * KIL Illegal opcode
+ * processor halted: no hardware interrupt will help,
+ * only reset
+ ***************************************************************/
+#define KIL \
+ PCW--; \
+ logerror("M6510 KILL opcode %04x: %02x\n", \
+ PCW, cpustate->direct->read_decrypted_byte(PCW))
+
+/* N2A03 *******************************************************
+ * ARR logical and, rotate right - no decimal mode
+ ***************************************************************/
+#define ARR_NES \
+ { \
+ tmp &= A; \
+ ROR; \
+ P &=~(F_V|F_C); \
+ if( tmp & 0x40 ) \
+ P|=F_C; \
+ if( (tmp & 0x60) == 0x20 || (tmp & 0x60) == 0x40 ) \
+ P|=F_V; \
+ }
+
+/* N2A03 *******************************************************
+ * ISB increment and subtract with carry
+ ***************************************************************/
+#define ISB_NES \
+ tmp = (UINT8)(tmp+1); \
+ SBC_NES
+
+/* N2A03 *******************************************************
+ * RRA rotate right and add with carry
+ * C -> [7][6][5][4][3][2][1][0] -> C
+ ***************************************************************/
+#define RRA_NES \
+ tmp |= (P & F_C) << 8; \
+ P = (P & ~F_C) | (tmp & F_C); \
+ tmp = (UINT8)(tmp >> 1); \
+ ADC_NES
+
+/* N2A03 *******************************************************
+ * OAL load accumulator and index X
+ ***************************************************************/
+#define OAL_NES \
+ A = X = (UINT8)((A|0xff)&tmp); \
+ SET_NZ(A)
+
+/* N2A03 *******************************************************
+ * SXH store index X high
+ * logical and index X with memory[PC+1] and store the result
+ *
+ * This instruction writes to an odd address when crossing
+ * a page boundary. The one known test case can be explained
+ * with a shift of Y. More testing will be needed to determine
+ * if this is correct.
+ *
+ ***************************************************************/
+#define SXH_NES \
+ if ( Y && Y > EAL ) \
+ EAH |= ( Y << 1 ); \
+ tmp = X & (EAH+1)
+
+/* N2A03 *******************************************************
+ * SYH store index Y and (high + 1)
+ * logical and index Y with memory[PC+1] + 1 and store the result
+ *
+ * This instruction writs to an odd address when crossing a
+ * a page boundary. The one known test case can be explained
+ * with a shoft of X. More testing will be needed to determine
+ * if this is correct.
+ *
+ ***************************************************************/
+#define SYH_NES \
+ if ( X && X > EAL ) \
+ EAH |= ( X << 1 ); \
+ tmp = Y & (EAH+1)
+
+#endif /* __ILL02_H__ */
diff --git a/trunk/src/emu/cpu/m6502/m4510.c b/trunk/src/emu/cpu/m6502/m4510.c
new file mode 100644
index 00000000000..c59207d260e
--- /dev/null
+++ b/trunk/src/emu/cpu/m6502/m4510.c
@@ -0,0 +1,557 @@
+/*****************************************************************************
+ *
+ * m4510.c
+ * Portable 4510 emulator V1.0beta1
+ *
+ * Copyright Peter Trauner, all rights reserved
+ * documentation preliminary databook
+ * documentation by michael steil mist@c64.org
+ * available at ftp://ftp.funet.fi/pub/cbm/c65
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * pullmoll@t-online.de
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ *****************************************************************************/
+
+/*
+ c65 memory management
+ (reset)
+ c64 ff
+ c65 20 (interface)
+
+a (c65 mode)
+ a:00 x:e3 y:00 z:b3
+ c65 64 (interface)
+ c64 ff
+
+b (c65 dosmode?)
+ c65 65 (interface, full colorram)
+ a:00 x:11 y:80 z:31
+ c64 ff
+
+c (?)
+ c64 07
+ a:00 x:00 y:00 z:00
+
+ a c65 mode
+
+ diskcontroller accesses
+
+
+ monitor
+ c64 ff
+ a:a0 x:82 y:00 z:83
+
+ c64 mode
+ c65 0
+ c65 2f:0 !
+ c64 ff
+ a:00 x:00 y:00 z:00
+
+internal 8 mb to 64k switching (jmp routine in rom)
+( seams to be incomplete, in chapter 1 1megabyte memory mapper )
+ a x y z
+g 0 00 e0 00 f0
+g 10000 00 e1 00 f1
+g 20000 00 e2 00 f2
+g 30000 00 e3 00 f3
+g 40000 00 e4 00 f4
+g 50000 00 e5 00 f5
+g 60000 00 e6 00 f6
+.
+.
+g f0000 00 ef 00 ff
+the same for 100000 .. 700000
+g 800000 00 e3 00 b3
+
+thesis:
+a: ?0?0 0000
+ ? ? only in monitor mode set
+x: xxxx address bits a19 .. a16 for memory accesses with a15 0 ?
+ 0000 c64 mode
+ 0001 dosmode
+ 1110 c65 mode, plain ram access
+ (0000-1fff contains the switching code, so not switchable!?)
+ 1000 monitor
+ 1 map 6000-7fff
+ 1 map 4000-5fff
+ 1 map 2000-3fff
+ 1 map 0000-1fff
+y: ?000 0000
+ ? only in dos mode set
+z: xxxx address bits a19 .. a16 for memory accesses with a15 1 ?
+ 0000 c64 mode
+ 0011 dosmode
+ 1000 monitor
+ 1011 c65 mode
+ 1111 plain ram access
+ 1 map e000-ffff
+ 1 map c000-dfff
+ 1 map a000-bfff
+ 1 map 8000-9fff
+ */
+
+#include "emu.h"
+#include "debugger.h"
+#include "m6502.h"
+#include "m4510.h"
+
+#include "minc4510.h"
+#include "opsce02.h"
+#include "ops4510.h"
+
+#define M6502_NMI_VEC 0xfffa
+#define M6502_RST_VEC 0xfffc
+#define M6502_IRQ_VEC 0xfffe
+#define M4510_RST_VEC M6502_RST_VEC
+#define M4510_IRQ_VEC M6502_IRQ_VEC
+#define M4510_NMI_VEC M6502_NMI_VEC
+
+#define VERBOSE 0
+
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+typedef struct _m4510_Regs m4510_Regs;
+struct _m4510_Regs {
+ void (*const *insn)(m4510_Regs *); /* pointer to the function pointer table */
+ PAIR ppc; /* previous program counter */
+ PAIR pc; /* program counter */
+ PAIR sp; /* stack pointer (always 100 - 1FF) */
+ PAIR zp; /* zero page address */
+ /* contains B register zp.b.h */
+ PAIR ea; /* effective address */
+ UINT8 a; /* Accumulator */
+ UINT8 x; /* X index register */
+ UINT8 y; /* Y index register */
+ UINT8 z; /* Z index register */
+ UINT8 p; /* Processor status */
+ UINT8 interrupt_inhibit; /* Some instructions, like MAP, inhibit interrupt */
+ UINT8 pending_irq; /* nonzero if an IRQ is pending */
+ UINT8 after_cli; /* pending IRQ and last insn cleared I */
+ UINT8 nmi_state;
+ UINT8 irq_state;
+ UINT16 low, high;
+ UINT32 mem[8];
+
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ address_space *space;
+ direct_read_data *direct;
+ int icount;
+
+ read8_space_func rdmem_id; /* readmem callback for indexed instructions */
+ write8_space_func wrmem_id; /* writemem callback for indexed instructions */
+
+ UINT8 ddr;
+ UINT8 port;
+
+ devcb_resolved_read8 in_port_func;
+ devcb_resolved_write8 out_port_func;
+};
+
+INLINE m4510_Regs *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == M4510);
+ return (m4510_Regs *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+/***************************************************************
+ * include the opcode macros, functions and tables
+ ***************************************************************/
+
+INLINE int m4510_cpu_readop(m4510_Regs *cpustate)
+{
+ register UINT16 t=cpustate->pc.w.l++;
+ return cpustate->direct->read_decrypted_byte(M4510_MEM(t));
+}
+
+INLINE int m4510_cpu_readop_arg(m4510_Regs *cpustate)
+{
+ register UINT16 t=cpustate->pc.w.l++;
+ return cpustate->direct->read_raw_byte(M4510_MEM(t));
+}
+
+#define M4510
+#include "t65ce02.c"
+
+static UINT8 default_rdmem_id(address_space *space, offs_t address)
+{
+ m4510_Regs *cpustate = get_safe_token(&space->device());
+ return space->read_byte(M4510_MEM(address));
+}
+static void default_wrmem_id(address_space *space, offs_t address, UINT8 data)
+{
+ m4510_Regs *cpustate = get_safe_token(&space->device());
+ space->write_byte(M4510_MEM(address), data);
+}
+
+static CPU_INIT( m4510 )
+{
+ m4510_Regs *cpustate = get_safe_token(device);
+ const m6502_interface *intf = (const m6502_interface *)device->static_config();
+
+ cpustate->interrupt_inhibit = 0;
+ cpustate->rdmem_id = default_rdmem_id;
+ cpustate->wrmem_id = default_wrmem_id;
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+ cpustate->space = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->space->direct();
+
+ if ( intf )
+ {
+ if ( intf->read_indexed_func )
+ cpustate->rdmem_id = intf->read_indexed_func;
+
+ if ( intf->write_indexed_func )
+ cpustate->wrmem_id = intf->write_indexed_func;
+
+ cpustate->in_port_func.resolve(intf->in_port_func, *device);
+ cpustate->out_port_func.resolve(intf->out_port_func, *device);
+ }
+ else
+ {
+ devcb_write8 nullcb = DEVCB_NULL;
+ cpustate->out_port_func.resolve(nullcb, *device);
+ }
+}
+
+static CPU_RESET( m4510 )
+{
+ m4510_Regs *cpustate = get_safe_token(device);
+
+ cpustate->insn = insn4510;
+
+ /* wipe out the rest of the m65ce02 structure */
+ /* read the reset vector into PC */
+ /* reset z index and b bank */
+ PCL = RDMEM(M4510_RST_VEC);
+ PCH = RDMEM(M4510_RST_VEC+1);
+
+ /* after reset in 6502 compatibility mode */
+ cpustate->sp.d = 0x01ff; /* high byte descriped in databook */
+ cpustate->z = 0;
+ B = 0;
+ cpustate->p = F_E|F_B|F_I|F_Z; /* set E, I and Z flags */
+ cpustate->interrupt_inhibit = 0;
+ cpustate->pending_irq = 0; /* nonzero if an IRQ is pending */
+ cpustate->after_cli = 0; /* pending IRQ and last insn cleared I */
+ cpustate->irq_callback = NULL;
+
+ /* don't know */
+ cpustate->high=0x8200;
+ cpustate->mem[7]=0x20000;
+
+ cpustate->port = 0xff;
+ cpustate->ddr = 0x00;
+}
+
+static CPU_EXIT( m4510 )
+{
+ /* nothing to do yet */
+}
+
+INLINE void m4510_take_irq(m4510_Regs *cpustate)
+{
+ if(( !(P & F_I) ) && (cpustate->interrupt_inhibit == 0))
+ {
+ EAD = M4510_IRQ_VEC;
+ cpustate->icount -= 7;
+ PUSH(PCH);
+ PUSH(PCL);
+ PUSH(P & ~F_B);
+ P = (P & ~F_D) | F_I; /* knock out D and set I flag */
+ PCL = RDMEM(EAD);
+ PCH = RDMEM(EAD+1);
+ LOG(("M4510 '%s' takes IRQ ($%04x)\n", cpustate->device->tag(), PCD));
+ /* call back the cpuintrf to let it clear the line */
+ if (cpustate->irq_callback) (*cpustate->irq_callback)(cpustate->device, 0);
+ }
+ cpustate->pending_irq = 0;
+}
+
+static CPU_EXECUTE( m4510 )
+{
+ m4510_Regs *cpustate = get_safe_token(device);
+
+ do
+ {
+ UINT8 op;
+ PPC = PCD;
+
+ debugger_instruction_hook(device, PCD);
+
+ /* if an irq is pending, take it now */
+ if( cpustate->pending_irq )
+ m4510_take_irq(cpustate);
+
+ op = RDOP();
+ (*insn4510[op])(cpustate);
+
+ /* check if the I flag was just reset (interrupts enabled) */
+ if( cpustate->after_cli )
+ {
+ LOG(("M4510 '%s' after_cli was >0", cpustate->device->tag()));
+ cpustate->after_cli = 0;
+ if (cpustate->irq_state != CLEAR_LINE)
+ {
+ LOG((": irq line is asserted: set pending IRQ\n"));
+ cpustate->pending_irq = 1;
+ }
+ else
+ {
+ LOG((": irq line is clear\n"));
+ }
+ }
+ else
+ if( cpustate->pending_irq )
+ m4510_take_irq(cpustate);
+
+ } while (cpustate->icount > 0);
+}
+
+static void m4510_set_irq_line(m4510_Regs *cpustate, int irqline, int state)
+{
+ if (irqline == INPUT_LINE_NMI)
+ {
+ if (cpustate->nmi_state == state) return;
+ cpustate->nmi_state = state;
+ if( state != CLEAR_LINE )
+ {
+ LOG(("M4510 '%s' set_nmi_line(ASSERT)\n", cpustate->device->tag()));
+ EAD = M4510_NMI_VEC;
+ cpustate->icount -= 7;
+ PUSH(PCH);
+ PUSH(PCL);
+ PUSH(P & ~F_B);
+ P = (P & ~F_D) | F_I; /* knock out D and set I flag */
+ PCL = RDMEM(EAD);
+ PCH = RDMEM(EAD+1);
+ LOG(("M4510 '%s' takes NMI ($%04x)\n", cpustate->device->tag(), PCD));
+ }
+ }
+ else
+ {
+ cpustate->irq_state = state;
+ if( state != CLEAR_LINE )
+ {
+ LOG(("M4510 '%s' set_irq_line(ASSERT)\n", cpustate->device->tag()));
+ cpustate->pending_irq = 1;
+ }
+ }
+}
+
+UINT8 m4510_get_port(legacy_cpu_device *device)
+{
+ m4510_Regs *cpustate = get_safe_token(device);
+ return (cpustate->port & cpustate->ddr) | (cpustate->ddr ^ 0xff);
+}
+static READ8_HANDLER( m4510_read_0000 )
+{
+ UINT8 result = 0x00;
+ m4510_Regs *cpustate = get_safe_token(&space->device());
+
+ switch(offset)
+ {
+ case 0x0000: /* DDR */
+ result = cpustate->ddr;
+ break;
+ case 0x0001: /* Data Port */
+ result = cpustate->in_port_func(0);
+ result = (cpustate->ddr & cpustate->port) | (~cpustate->ddr & result);
+ break;
+ }
+ return result;
+}
+
+static WRITE8_HANDLER( m4510_write_0000 )
+{
+ m4510_Regs *cpustate = get_safe_token(&space->device());
+
+ switch(offset)
+ {
+ case 0x0000: /* DDR */
+ cpustate->ddr = data;
+ break;
+ case 0x0001: /* Data Port */
+ cpustate->port = data;
+ break;
+ }
+
+ cpustate->out_port_func(0, m4510_get_port(downcast<legacy_cpu_device *>(&space->device())));
+}
+
+static ADDRESS_MAP_START(m4510_mem, AS_PROGRAM, 8)
+ AM_RANGE(0x0000, 0x0001) AM_READWRITE(m4510_read_0000, m4510_write_0000)
+ADDRESS_MAP_END
+
+static CPU_TRANSLATE( m4510 )
+{
+ m4510_Regs *cpustate = get_safe_token(device);
+
+ if (space == AS_PROGRAM)
+ *address = M4510_MEM(*address);
+ return TRUE;
+}
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( m4510 )
+{
+ m4510_Regs *cpustate = get_safe_token(device);
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + M4510_IRQ_LINE: m4510_set_irq_line(cpustate, M4510_IRQ_LINE, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: m4510_set_irq_line(cpustate, INPUT_LINE_NMI, info->i); break;
+
+ case CPUINFO_INT_PC: PCW = info->i; break;
+ case CPUINFO_INT_REGISTER + M4510_PC: cpustate->pc.w.l = info->i; break;
+ case CPUINFO_INT_SP: SPL = info->i; break;
+ case CPUINFO_INT_REGISTER + M4510_S: cpustate->sp.b.l = info->i; break;
+ case CPUINFO_INT_REGISTER + M4510_P: cpustate->p = info->i; break;
+ case CPUINFO_INT_REGISTER + M4510_A: cpustate->a = info->i; break;
+ case CPUINFO_INT_REGISTER + M4510_X: cpustate->x = info->i; break;
+ case CPUINFO_INT_REGISTER + M4510_Y: cpustate->y = info->i; break;
+ case CPUINFO_INT_REGISTER + M4510_Z: cpustate->z = info->i; break;
+ case CPUINFO_INT_REGISTER + M4510_B: cpustate->zp.b.h = info->i; break;
+ case CPUINFO_INT_REGISTER + M4510_MEM_LOW: cpustate->low = info->i; break;
+ case CPUINFO_INT_REGISTER + M4510_MEM_HIGH: cpustate->high = info->i; break;
+ case CPUINFO_INT_REGISTER + M4510_EA: cpustate->ea.w.l = info->i; break;
+ case CPUINFO_INT_REGISTER + M4510_ZP: cpustate->zp.w.l = info->i; break;
+ case CPUINFO_INT_REGISTER + M4510_MEM0: cpustate->mem[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + M4510_MEM1: cpustate->mem[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + M4510_MEM2: cpustate->mem[2] = info->i; break;
+ case CPUINFO_INT_REGISTER + M4510_MEM3: cpustate->mem[3] = info->i; break;
+ case CPUINFO_INT_REGISTER + M4510_MEM4: cpustate->mem[4] = info->i; break;
+ case CPUINFO_INT_REGISTER + M4510_MEM5: cpustate->mem[5] = info->i; break;
+ case CPUINFO_INT_REGISTER + M4510_MEM6: cpustate->mem[6] = info->i; break;
+ case CPUINFO_INT_REGISTER + M4510_MEM7: cpustate->mem[7] = info->i; break;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+CPU_GET_INFO( m4510 )
+{
+ m4510_Regs *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(m4510_Regs); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 2; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 3; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 10; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 20; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case CPUINFO_INT_LOGADDR_WIDTH_PROGRAM: info->i = 16; break;
+ case CPUINFO_INT_PAGE_SHIFT_PROGRAM: info->i = 13; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_INPUT_STATE + M4510_IRQ_LINE: info->i = cpustate->irq_state; break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: info->i = cpustate->nmi_state; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = cpustate->ppc.w.l; break;
+
+ case CPUINFO_INT_PC: info->i = PCD; break;
+ case CPUINFO_INT_REGISTER + M4510_PC: info->i = cpustate->pc.w.l; break;
+ case CPUINFO_INT_SP: info->i = SPL; break;
+ case CPUINFO_INT_REGISTER + M4510_S: info->i = cpustate->sp.b.l; break;
+ case CPUINFO_INT_REGISTER + M4510_P: info->i = cpustate->p; break;
+ case CPUINFO_INT_REGISTER + M4510_A: info->i = cpustate->a; break;
+ case CPUINFO_INT_REGISTER + M4510_X: info->i = cpustate->x; break;
+ case CPUINFO_INT_REGISTER + M4510_Y: info->i = cpustate->y; break;
+ case CPUINFO_INT_REGISTER + M4510_Z: info->i = cpustate->z; break;
+ case CPUINFO_INT_REGISTER + M4510_B: info->i = cpustate->zp.b.h; break;
+ case CPUINFO_INT_REGISTER + M4510_MEM_LOW: info->i = cpustate->low; break;
+ case CPUINFO_INT_REGISTER + M4510_MEM_HIGH: info->i = cpustate->high; break;
+ case CPUINFO_INT_REGISTER + M4510_EA: info->i = cpustate->ea.w.l; break;
+ case CPUINFO_INT_REGISTER + M4510_ZP: info->i = cpustate->zp.w.l; break;
+ case CPUINFO_INT_REGISTER + M4510_MEM0: info->i = cpustate->mem[0]; break;
+ case CPUINFO_INT_REGISTER + M4510_MEM1: info->i = cpustate->mem[1]; break;
+ case CPUINFO_INT_REGISTER + M4510_MEM2: info->i = cpustate->mem[2]; break;
+ case CPUINFO_INT_REGISTER + M4510_MEM3: info->i = cpustate->mem[3]; break;
+ case CPUINFO_INT_REGISTER + M4510_MEM4: info->i = cpustate->mem[4]; break;
+ case CPUINFO_INT_REGISTER + M4510_MEM5: info->i = cpustate->mem[5]; break;
+ case CPUINFO_INT_REGISTER + M4510_MEM6: info->i = cpustate->mem[6]; break;
+ case CPUINFO_INT_REGISTER + M4510_MEM7: info->i = cpustate->mem[7]; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(m4510); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(m4510); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(m4510); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(m4510); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(m4510); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(m4510); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME(m4510_mem); break;
+ case CPUINFO_FCT_TRANSLATE: info->translate = CPU_TRANSLATE_NAME(m4510); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "M4510"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "CBM Semiconductor Group CSG 65CE02"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0beta"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Juergen Buchmueller\nCopyright Peter Trauner\nall rights reserved."); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c%c%c%c%c%c%c",
+ cpustate->p & 0x80 ? 'N':'.',
+ cpustate->p & 0x40 ? 'V':'.',
+ cpustate->p & 0x20 ? 'R':'.',
+ cpustate->p & 0x10 ? 'B':'.',
+ cpustate->p & 0x08 ? 'D':'.',
+ cpustate->p & 0x04 ? 'I':'.',
+ cpustate->p & 0x02 ? 'Z':'.',
+ cpustate->p & 0x01 ? 'C':'.');
+ break;
+
+ case CPUINFO_STR_REGISTER + M4510_PC: sprintf(info->s, "PC:%04X", cpustate->pc.w.l); break;
+ case CPUINFO_STR_REGISTER + M4510_S: sprintf(info->s, "S:%02X", cpustate->sp.b.l); break;
+ case CPUINFO_STR_REGISTER + M4510_P: sprintf(info->s, "P:%02X", cpustate->p); break;
+ case CPUINFO_STR_REGISTER + M4510_A: sprintf(info->s, "A:%02X", cpustate->a); break;
+ case CPUINFO_STR_REGISTER + M4510_X: sprintf(info->s, "X:%02X", cpustate->x); break;
+ case CPUINFO_STR_REGISTER + M4510_Y: sprintf(info->s, "Y:%02X", cpustate->y); break;
+ case CPUINFO_STR_REGISTER + M4510_Z: sprintf(info->s, "Z:%02X", cpustate->z); break;
+ case CPUINFO_STR_REGISTER + M4510_B: sprintf(info->s, "B:%02X", cpustate->zp.b.h); break;
+ case CPUINFO_STR_REGISTER + M4510_MEM_LOW: sprintf(info->s, "M0:%01X", cpustate->low); break;
+ case CPUINFO_STR_REGISTER + M4510_MEM_HIGH: sprintf(info->s, "M1:%01X", cpustate->high); break;
+ case CPUINFO_STR_REGISTER + M4510_EA: sprintf(info->s, "EA:%04X", cpustate->ea.w.l); break;
+ case CPUINFO_STR_REGISTER + M4510_ZP: sprintf(info->s, "ZP:%03X", cpustate->zp.w.l); break;
+ }
+}
+
+#undef M4510
+DEFINE_LEGACY_CPU_DEVICE(M4510, m4510);
diff --git a/trunk/src/emu/cpu/m6502/m4510.h b/trunk/src/emu/cpu/m6502/m4510.h
new file mode 100644
index 00000000000..e896a9bf5b3
--- /dev/null
+++ b/trunk/src/emu/cpu/m6502/m4510.h
@@ -0,0 +1,49 @@
+/*****************************************************************************
+ *
+ * m4510.c
+ * Portable 4510 emulator V1.0beta
+ *
+ * Copyright Peter Trauner, all rights reserved.
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * pullmoll@t-online.de
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ *****************************************************************************/
+
+#pragma once
+
+#ifndef __M4510_H__
+#define __M4510_H__
+
+#include "m6502.h"
+
+
+enum
+{
+ M4510_PC=1, M4510_S, M4510_P, M4510_A, M4510_X, M4510_Y,
+ M4510_Z, M4510_B, M4510_EA, M4510_ZP,
+ M4510_NMI_STATE, M4510_IRQ_STATE,
+ M4510_MEM_LOW,M4510_MEM_HIGH,
+ M4510_MEM0, M4510_MEM1, M4510_MEM2, M4510_MEM3,
+ M4510_MEM4, M4510_MEM5, M4510_MEM6, M4510_MEM7
+};
+
+#define M4510_IRQ_LINE M6502_IRQ_LINE
+
+DECLARE_LEGACY_CPU_DEVICE(M4510, m4510);
+
+
+extern CPU_DISASSEMBLE( m4510 );
+
+UINT8 m4510_get_port(legacy_cpu_device *device);
+
+#endif /* __M4510_H__ */
diff --git a/trunk/src/emu/cpu/m6502/m6502.c b/trunk/src/emu/cpu/m6502/m6502.c
new file mode 100644
index 00000000000..3029959fc7e
--- /dev/null
+++ b/trunk/src/emu/cpu/m6502/m6502.c
@@ -0,0 +1,996 @@
+/*****************************************************************************
+ *
+ * m6502.c
+ * Portable 6502/65c02/65sc02/6510/n2a03 emulator V1.2
+ *
+ * Copyright Juergen Buchmueller, all rights reserved.
+ * 65sc02 core Copyright Peter Trauner.
+ * Deco16 portions Copyright Bryan McPhail.
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * pullmoll@t-online.de
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ *****************************************************************************/
+/* 2.February 2000 PeT added 65sc02 subtype */
+/* 10.March 2000 PeT added 6502 set overflow input line */
+/* 13.September 2000 PeT N2A03 jmp indirect */
+
+#include "emu.h"
+#include "debugger.h"
+#include "m6502.h"
+#include "ops02.h"
+#include "ill02.h"
+
+
+#define M6502_NMI_VEC 0xfffa
+#define M6502_RST_VEC 0xfffc
+#define M6502_IRQ_VEC 0xfffe
+
+#define DECO16_RST_VEC 0xfff0
+#define DECO16_IRQ_VEC 0xfff2
+#define DECO16_NMI_VEC 0xfff4
+
+#define VERBOSE 0
+
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+
+
+/****************************************************************************
+ * The 6502 registers.
+ ****************************************************************************/
+typedef struct _m6502_Regs m6502_Regs;
+struct _m6502_Regs
+{
+ UINT8 subtype; /* currently selected cpu sub type */
+ void (*const *insn)(m6502_Regs *); /* pointer to the function pointer table */
+ PAIR ppc; /* previous program counter */
+ PAIR pc; /* program counter */
+ PAIR sp; /* stack pointer (always 100 - 1FF) */
+ PAIR zp; /* zero page address */
+ PAIR ea; /* effective address */
+ UINT8 a; /* Accumulator */
+ UINT8 x; /* X index register */
+ UINT8 y; /* Y index register */
+ UINT8 p; /* Processor status */
+ UINT8 pending_irq; /* nonzero if an IRQ is pending */
+ UINT8 after_cli; /* pending IRQ and last insn cleared I */
+ UINT8 nmi_state;
+ UINT8 irq_state;
+ UINT8 so_state;
+
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ address_space *space;
+ direct_read_data *direct;
+ address_space *io;
+ int int_occured;
+ int icount;
+
+ read8_space_func rdmem_id; /* readmem callback for indexed instructions */
+ write8_space_func wrmem_id; /* writemem callback for indexed instructions */
+
+ UINT8 ddr;
+ UINT8 port;
+
+ devcb_resolved_read8 in_port_func;
+ devcb_resolved_write8 out_port_func;
+};
+
+INLINE m6502_Regs *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == M6502 ||
+ device->type() == M6504 ||
+ device->type() == M6510 ||
+ device->type() == M6510T ||
+ device->type() == M7501 ||
+ device->type() == M8502 ||
+ device->type() == N2A03 ||
+ device->type() == M65C02 ||
+ device->type() == M65SC02 ||
+ device->type() == DECO16);
+ return (m6502_Regs *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+static UINT8 default_rdmem_id(address_space *space, offs_t offset) { return space->read_byte(offset); }
+static void default_wdmem_id(address_space *space, offs_t offset, UINT8 data) { space->write_byte(offset, data); }
+
+/***************************************************************
+ * include the opcode macros, functions and tables
+ ***************************************************************/
+#include "t6502.c"
+
+#include "t6510.c"
+
+#include "opsn2a03.h"
+
+#include "tn2a03.c"
+
+#include "opsc02.h"
+
+#include "t65c02.c"
+
+#include "t65sc02.c"
+
+#include "tdeco16.c"
+
+/*****************************************************************************
+ *
+ * 6502 CPU interface functions
+ *
+ *****************************************************************************/
+
+static void m6502_common_init(legacy_cpu_device *device, device_irq_callback irqcallback, UINT8 subtype, void (*const *insn)(m6502_Regs *cpustate), const char *type)
+{
+ m6502_Regs *cpustate = get_safe_token(device);
+ const m6502_interface *intf = (const m6502_interface *)device->static_config();
+
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+ cpustate->space = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->space->direct();
+ cpustate->subtype = subtype;
+ cpustate->insn = insn;
+ cpustate->rdmem_id = default_rdmem_id;
+ cpustate->wrmem_id = default_wdmem_id;
+
+ if ( intf )
+ {
+ if ( intf->read_indexed_func )
+ cpustate->rdmem_id = intf->read_indexed_func;
+
+ if ( intf->write_indexed_func )
+ cpustate->wrmem_id = intf->write_indexed_func;
+
+ cpustate->in_port_func.resolve(intf->in_port_func, *device);
+ cpustate->out_port_func.resolve(intf->out_port_func, *device);
+ }
+ else
+ {
+ devcb_write8 nullcb = DEVCB_NULL;
+ cpustate->out_port_func.resolve(nullcb, *device);
+ }
+
+ device->save_item(NAME(cpustate->pc.w.l));
+ device->save_item(NAME(cpustate->sp.w.l));
+ device->save_item(NAME(cpustate->p));
+ device->save_item(NAME(cpustate->a));
+ device->save_item(NAME(cpustate->x));
+ device->save_item(NAME(cpustate->y));
+ device->save_item(NAME(cpustate->pending_irq));
+ device->save_item(NAME(cpustate->after_cli));
+ device->save_item(NAME(cpustate->nmi_state));
+ device->save_item(NAME(cpustate->irq_state));
+ device->save_item(NAME(cpustate->so_state));
+
+ if (subtype == SUBTYPE_6510)
+ {
+ device->save_item(NAME(cpustate->port));
+ device->save_item(NAME(cpustate->ddr));
+ }
+}
+
+static CPU_INIT( m6502 )
+{
+ m6502_common_init(device, irqcallback, SUBTYPE_6502, insn6502, "m6502");
+}
+
+static CPU_RESET( m6502 )
+{
+ m6502_Regs *cpustate = get_safe_token(device);
+ /* wipe out the rest of the m6502 structure */
+ /* read the reset vector into PC */
+ PCL = RDMEM(M6502_RST_VEC);
+ PCH = RDMEM(M6502_RST_VEC+1);
+
+ cpustate->sp.d = 0x01ff; /* stack pointer starts at page 1 offset FF */
+ cpustate->p = F_T|F_I|F_Z|F_B|(P&F_D); /* set T, I and Z flags */
+ cpustate->pending_irq = 0; /* nonzero if an IRQ is pending */
+ cpustate->after_cli = 0; /* pending IRQ and last insn cleared I */
+ cpustate->irq_state = 0;
+ cpustate->nmi_state = 0;
+}
+
+static CPU_EXIT( m6502 )
+{
+ /* nothing to do yet */
+}
+
+INLINE void m6502_take_irq(m6502_Regs *cpustate)
+{
+ if( !(P & F_I) )
+ {
+ EAD = M6502_IRQ_VEC;
+ cpustate->icount -= 2;
+ PUSH(PCH);
+ PUSH(PCL);
+ PUSH(P & ~F_B);
+ P |= F_I; /* set I flag */
+ PCL = RDMEM(EAD);
+ PCH = RDMEM(EAD+1);
+ LOG(("M6502 '%s' takes IRQ ($%04x)\n", cpustate->device->tag(), PCD));
+ /* call back the cpuintrf to let it clear the line */
+ if (cpustate->irq_callback) (*cpustate->irq_callback)(cpustate->device, 0);
+ }
+ cpustate->pending_irq = 0;
+}
+
+static CPU_EXECUTE( m6502 )
+{
+ m6502_Regs *cpustate = get_safe_token(device);
+
+ do
+ {
+ UINT8 op;
+ PPC = PCD;
+
+ debugger_instruction_hook(device, PCD);
+
+ /* if an irq is pending, take it now */
+ if( cpustate->pending_irq )
+ m6502_take_irq(cpustate);
+
+ op = RDOP();
+ (*cpustate->insn[op])(cpustate);
+
+ /* check if the I flag was just reset (interrupts enabled) */
+ if( cpustate->after_cli )
+ {
+ LOG(("M6502 '%s' after_cli was >0", cpustate->device->tag()));
+ cpustate->after_cli = 0;
+ if (cpustate->irq_state != CLEAR_LINE)
+ {
+ LOG((": irq line is asserted: set pending IRQ\n"));
+ cpustate->pending_irq = 1;
+ }
+ else
+ {
+ LOG((": irq line is clear\n"));
+ }
+ }
+ else {
+ if ( cpustate->pending_irq == 2 ) {
+ if ( cpustate->int_occured - cpustate->icount > 1 ) {
+ cpustate->pending_irq = 1;
+ }
+ }
+ if( cpustate->pending_irq == 1 )
+ m6502_take_irq(cpustate);
+ if ( cpustate->pending_irq == 2 ) {
+ cpustate->pending_irq = 1;
+ }
+ }
+
+ } while (cpustate->icount > 0);
+}
+
+static void m6502_set_irq_line(m6502_Regs *cpustate, int irqline, int state)
+{
+ if (irqline == INPUT_LINE_NMI)
+ {
+ if (cpustate->nmi_state == state) return;
+ cpustate->nmi_state = state;
+ if( state != CLEAR_LINE )
+ {
+ LOG(( "M6502 '%s' set_nmi_line(ASSERT)\n", cpustate->device->tag()));
+ EAD = M6502_NMI_VEC;
+ cpustate->icount -= 2;
+ PUSH(PCH);
+ PUSH(PCL);
+ PUSH(P & ~F_B);
+ P |= F_I; /* set I flag */
+ PCL = RDMEM(EAD);
+ PCH = RDMEM(EAD+1);
+ LOG(("M6502 '%s' takes NMI ($%04x)\n", cpustate->device->tag(), PCD));
+ }
+ }
+ else
+ {
+ if( irqline == M6502_SET_OVERFLOW )
+ {
+ if( cpustate->so_state && !state )
+ {
+ LOG(( "M6502 '%s' set overflow\n", cpustate->device->tag()));
+ P|=F_V;
+ }
+ cpustate->so_state=state;
+ return;
+ }
+ cpustate->irq_state = state;
+ if( state != CLEAR_LINE )
+ {
+ LOG(( "M6502 '%s' set_irq_line(ASSERT)\n", cpustate->device->tag()));
+ cpustate->pending_irq = 1;
+// cpustate->pending_irq = 2;
+ cpustate->int_occured = cpustate->icount;
+ }
+ }
+}
+
+
+
+/****************************************************************************
+ * 2A03 section
+ ****************************************************************************/
+
+static CPU_INIT( n2a03 )
+{
+ m6502_common_init(device, irqcallback, SUBTYPE_2A03, insn2a03, "n2a03");
+}
+
+/* The N2A03 is integrally tied to its PSG (they're on the same die).
+ Bit 7 of address $4011 (the PSG's DPCM control register), when set,
+ causes an IRQ to be generated. This function allows the IRQ to be called
+ from the PSG core when such an occasion arises. */
+void n2a03_irq(device_t *device)
+{
+ m6502_Regs *cpustate = get_safe_token(device);
+
+ m6502_take_irq(cpustate);
+}
+
+
+/****************************************************************************
+ * 6510 section
+ ****************************************************************************/
+
+static CPU_INIT( m6510 )
+{
+ m6502_common_init(device, irqcallback, SUBTYPE_6510, insn6510, "m6510");
+}
+
+static CPU_RESET( m6510 )
+{
+ m6502_Regs *cpustate = get_safe_token(device);
+
+ CPU_RESET_CALL(m6502);
+ cpustate->port = 0xff;
+ cpustate->ddr = 0x00;
+}
+
+UINT8 m6510_get_port(legacy_cpu_device *device)
+{
+ m6502_Regs *cpustate = get_safe_token(device);
+ return (cpustate->port & cpustate->ddr) | (cpustate->ddr ^ 0xff);
+}
+
+static READ8_HANDLER( m6510_read_0000 )
+{
+ m6502_Regs *cpustate = get_safe_token(&space->device());
+ UINT8 result = 0x00;
+
+ switch(offset)
+ {
+ case 0x0000: /* DDR */
+ result = cpustate->ddr;
+ break;
+ case 0x0001: /* Data Port */
+ result = cpustate->in_port_func(cpustate->ddr);
+ result = (cpustate->ddr & cpustate->port) | (~cpustate->ddr & result);
+ break;
+ }
+ return result;
+}
+
+static WRITE8_HANDLER( m6510_write_0000 )
+{
+ m6502_Regs *cpustate = get_safe_token(&space->device());
+
+ switch(offset)
+ {
+ case 0x0000: /* DDR */
+ cpustate->ddr = data;
+ break;
+ case 0x0001: /* Data Port */
+ cpustate->port = data;
+ break;
+ }
+
+ cpustate->out_port_func(cpustate->ddr, cpustate->port & cpustate->ddr);
+}
+
+static ADDRESS_MAP_START(m6510_mem, AS_PROGRAM, 8)
+ AM_RANGE(0x0000, 0x0001) AM_READWRITE(m6510_read_0000, m6510_write_0000)
+ADDRESS_MAP_END
+
+
+
+/****************************************************************************
+ * 65C02 section
+ ****************************************************************************/
+
+static CPU_INIT( m65c02 )
+{
+ m6502_common_init(device, irqcallback, SUBTYPE_65C02, insn65c02, "m65c02");
+}
+
+static CPU_RESET( m65c02 )
+{
+ m6502_Regs *cpustate = get_safe_token(device);
+
+ CPU_RESET_CALL(m6502);
+ P &=~F_D;
+}
+
+INLINE void m65c02_take_irq(m6502_Regs *cpustate)
+{
+ if( !(P & F_I) )
+ {
+ EAD = M6502_IRQ_VEC;
+ cpustate->icount -= 2;
+ PUSH(PCH);
+ PUSH(PCL);
+ PUSH(P & ~F_B);
+ P = (P & ~F_D) | F_I; /* knock out D and set I flag */
+ PCL = RDMEM(EAD);
+ PCH = RDMEM(EAD+1);
+ LOG(("M65c02 '%s' takes IRQ ($%04x)\n", cpustate->device->tag(), PCD));
+ /* call back the cpuintrf to let it clear the line */
+ if (cpustate->irq_callback) (*cpustate->irq_callback)(cpustate->device, 0);
+ }
+ cpustate->pending_irq = 0;
+}
+
+static CPU_EXECUTE( m65c02 )
+{
+ m6502_Regs *cpustate = get_safe_token(device);
+
+ do
+ {
+ UINT8 op;
+ PPC = PCD;
+
+ debugger_instruction_hook(device, PCD);
+
+ op = RDOP();
+ (*cpustate->insn[op])(cpustate);
+
+ /* if an irq is pending, take it now */
+ if( cpustate->pending_irq )
+ m65c02_take_irq(cpustate);
+
+
+ /* check if the I flag was just reset (interrupts enabled) */
+ if( cpustate->after_cli )
+ {
+ LOG(("M6502 '%s' after_cli was >0", cpustate->device->tag()));
+ cpustate->after_cli = 0;
+ if (cpustate->irq_state != CLEAR_LINE)
+ {
+ LOG((": irq line is asserted: set pending IRQ\n"));
+ cpustate->pending_irq = 1;
+ }
+ else
+ {
+ LOG((": irq line is clear\n"));
+ }
+ }
+ else
+ if( cpustate->pending_irq )
+ m65c02_take_irq(cpustate);
+
+ } while (cpustate->icount > 0);
+}
+
+static void m65c02_set_irq_line(m6502_Regs *cpustate, int irqline, int state)
+{
+ if (irqline == INPUT_LINE_NMI)
+ {
+ if (cpustate->nmi_state == state) return;
+ cpustate->nmi_state = state;
+ if( state != CLEAR_LINE )
+ {
+ LOG(( "M6502 '%s' set_nmi_line(ASSERT)\n", cpustate->device->tag()));
+ EAD = M6502_NMI_VEC;
+ cpustate->icount -= 2;
+ PUSH(PCH);
+ PUSH(PCL);
+ PUSH(P & ~F_B);
+ P = (P & ~F_D) | F_I; /* knock out D and set I flag */
+ PCL = RDMEM(EAD);
+ PCH = RDMEM(EAD+1);
+ LOG(("M6502 '%s' takes NMI ($%04x)\n", cpustate->device->tag(), PCD));
+ }
+ }
+ else
+ m6502_set_irq_line(cpustate, irqline,state);
+}
+
+/****************************************************************************
+ * 65SC02 section
+ ****************************************************************************/
+static CPU_INIT( m65sc02 )
+{
+ m6502_common_init(device, irqcallback, SUBTYPE_65SC02, insn65sc02, "m65sc02");
+}
+
+/****************************************************************************
+ * DECO16 section
+ ****************************************************************************/
+
+static CPU_INIT( deco16 )
+{
+ m6502_Regs *cpustate = get_safe_token(device);
+ m6502_common_init(device, irqcallback, SUBTYPE_DECO16, insndeco16, "deco16");
+ cpustate->io = device->space(AS_IO);
+}
+
+
+static CPU_RESET( deco16 )
+{
+ m6502_Regs *cpustate = get_safe_token(device);
+
+ CPU_RESET_CALL(m6502);
+ cpustate->subtype = SUBTYPE_DECO16;
+ cpustate->insn = insndeco16;
+
+ PCL = RDMEM(DECO16_RST_VEC+1);
+ PCH = RDMEM(DECO16_RST_VEC);
+
+ cpustate->sp.d = 0x01ff; /* stack pointer starts at page 1 offset FF */
+ cpustate->p = F_T|F_I|F_Z|F_B|(P&F_D); /* set T, I and Z flags */
+ cpustate->pending_irq = 0; /* nonzero if an IRQ is pending */
+ cpustate->after_cli = 0; /* pending IRQ and last insn cleared I */
+}
+
+INLINE void deco16_take_irq(m6502_Regs *cpustate)
+{
+ if( !(P & F_I) )
+ {
+ EAD = DECO16_IRQ_VEC;
+ cpustate->icount -= 2;
+ PUSH(PCH);
+ PUSH(PCL);
+ PUSH(P & ~F_B);
+ P |= F_I; /* set I flag */
+ PCL = RDMEM(EAD+1);
+ PCH = RDMEM(EAD);
+ LOG(("M6502 '%s' takes IRQ ($%04x)\n", cpustate->device->tag(), PCD));
+ /* call back the cpuintrf to let it clear the line */
+ if (cpustate->irq_callback) (*cpustate->irq_callback)(cpustate->device, 0);
+ }
+ cpustate->pending_irq = 0;
+}
+
+static void deco16_set_irq_line(m6502_Regs *cpustate, int irqline, int state)
+{
+ if (irqline == INPUT_LINE_NMI)
+ {
+ if (cpustate->nmi_state == state) return;
+ cpustate->nmi_state = state;
+ if( state != CLEAR_LINE )
+ {
+ LOG(( "M6502 '%s' set_nmi_line(ASSERT)\n", cpustate->device->tag()));
+ EAD = DECO16_NMI_VEC;
+ cpustate->icount -= 7;
+ PUSH(PCH);
+ PUSH(PCL);
+ PUSH(P & ~F_B);
+ P |= F_I; /* set I flag */
+ PCL = RDMEM(EAD+1);
+ PCH = RDMEM(EAD);
+ LOG(("M6502 '%s' takes NMI ($%04x)\n", cpustate->device->tag(), PCD));
+ }
+ }
+ else
+ {
+ if( irqline == M6502_SET_OVERFLOW )
+ {
+ if( cpustate->so_state && !state )
+ {
+ LOG(( "M6502 '%s' set overflow\n", cpustate->device->tag()));
+ P|=F_V;
+ }
+ cpustate->so_state=state;
+ return;
+ }
+ cpustate->irq_state = state;
+ if( state != CLEAR_LINE )
+ {
+ LOG(( "M6502 '%s' set_irq_line(ASSERT)\n", cpustate->device->tag()));
+ cpustate->pending_irq = 1;
+ }
+ }
+}
+
+static CPU_EXECUTE( deco16 )
+{
+ m6502_Regs *cpustate = get_safe_token(device);
+
+ do
+ {
+ UINT8 op;
+ PPC = PCD;
+
+ debugger_instruction_hook(device, PCD);
+
+ op = RDOP();
+ (*cpustate->insn[op])(cpustate);
+
+ /* if an irq is pending, take it now */
+ if( cpustate->pending_irq )
+ deco16_take_irq(cpustate);
+
+
+ /* check if the I flag was just reset (interrupts enabled) */
+ if( cpustate->after_cli )
+ {
+ LOG(("M6502 %s after_cli was >0", cpustate->device->tag()));
+ cpustate->after_cli = 0;
+ if (cpustate->irq_state != CLEAR_LINE)
+ {
+ LOG((": irq line is asserted: set pending IRQ\n"));
+ cpustate->pending_irq = 1;
+ }
+ else
+ {
+ LOG((": irq line is clear\n"));
+ }
+ }
+ else
+ if( cpustate->pending_irq )
+ deco16_take_irq(cpustate);
+
+ } while (cpustate->icount > 0);
+}
+
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( m6502 )
+{
+ m6502_Regs *cpustate = get_safe_token(device);
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + M6502_IRQ_LINE: m6502_set_irq_line(cpustate, M6502_IRQ_LINE, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + M6502_SET_OVERFLOW: m6502_set_irq_line(cpustate, M6502_SET_OVERFLOW, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: m6502_set_irq_line(cpustate, INPUT_LINE_NMI, info->i); break;
+
+ case CPUINFO_INT_PC: PCW = info->i; break;
+ case CPUINFO_INT_REGISTER + M6502_PC: cpustate->pc.w.l = info->i; break;
+ case CPUINFO_INT_SP: S = info->i; break;
+ case CPUINFO_INT_REGISTER + M6502_S: cpustate->sp.b.l = info->i; break;
+ case CPUINFO_INT_REGISTER + M6502_P: cpustate->p = info->i; break;
+ case CPUINFO_INT_REGISTER + M6502_A: cpustate->a = info->i; break;
+ case CPUINFO_INT_REGISTER + M6502_X: cpustate->x = info->i; break;
+ case CPUINFO_INT_REGISTER + M6502_Y: cpustate->y = info->i; break;
+ case CPUINFO_INT_REGISTER + M6502_EA: cpustate->ea.w.l = info->i; break;
+ case CPUINFO_INT_REGISTER + M6502_ZP: cpustate->zp.w.l = info->i; break;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+CPU_GET_INFO( m6502 )
+{
+ m6502_Regs *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(m6502_Regs); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 2; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 10; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_INPUT_STATE + M6502_IRQ_LINE: info->i = cpustate->irq_state; break;
+ case CPUINFO_INT_INPUT_STATE + M6502_SET_OVERFLOW: info->i = cpustate->so_state; break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: info->i = cpustate->nmi_state; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = cpustate->ppc.w.l; break;
+
+ case CPUINFO_INT_PC: info->i = PCD; break;
+ case CPUINFO_INT_REGISTER + M6502_PC: info->i = cpustate->pc.w.l; break;
+ case CPUINFO_INT_SP: info->i = S; break;
+ case CPUINFO_INT_REGISTER + M6502_S: info->i = cpustate->sp.b.l; break;
+ case CPUINFO_INT_REGISTER + M6502_P: info->i = cpustate->p; break;
+ case CPUINFO_INT_REGISTER + M6502_A: info->i = cpustate->a; break;
+ case CPUINFO_INT_REGISTER + M6502_X: info->i = cpustate->x; break;
+ case CPUINFO_INT_REGISTER + M6502_Y: info->i = cpustate->y; break;
+ case CPUINFO_INT_REGISTER + M6502_EA: info->i = cpustate->ea.w.l; break;
+ case CPUINFO_INT_REGISTER + M6502_ZP: info->i = cpustate->zp.w.l; break;
+ case CPUINFO_INT_REGISTER + M6502_SUBTYPE: info->i = cpustate->subtype; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(m6502); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(m6502); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(m6502); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(m6502); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(m6502); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(m6502); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "M6502"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Mostek 6502"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.2"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Juergen Buchmueller, all rights reserved."); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c%c%c%c%c%c%c",
+ cpustate->p & 0x80 ? 'N':'.',
+ cpustate->p & 0x40 ? 'V':'.',
+ cpustate->p & 0x20 ? 'R':'.',
+ cpustate->p & 0x10 ? 'B':'.',
+ cpustate->p & 0x08 ? 'D':'.',
+ cpustate->p & 0x04 ? 'I':'.',
+ cpustate->p & 0x02 ? 'Z':'.',
+ cpustate->p & 0x01 ? 'C':'.');
+ break;
+
+ case CPUINFO_STR_REGISTER + M6502_PC: sprintf(info->s, "PC:%04X", cpustate->pc.w.l); break;
+ case CPUINFO_STR_REGISTER + M6502_S: sprintf(info->s, "S:%02X", cpustate->sp.b.l); break;
+ case CPUINFO_STR_REGISTER + M6502_P: sprintf(info->s, "P:%02X", cpustate->p); break;
+ case CPUINFO_STR_REGISTER + M6502_A: sprintf(info->s, "A:%02X", cpustate->a); break;
+ case CPUINFO_STR_REGISTER + M6502_X: sprintf(info->s, "X:%02X", cpustate->x); break;
+ case CPUINFO_STR_REGISTER + M6502_Y: sprintf(info->s, "Y:%02X", cpustate->y); break;
+ case CPUINFO_STR_REGISTER + M6502_EA: sprintf(info->s, "EA:%04X", cpustate->ea.w.l); break;
+ case CPUINFO_STR_REGISTER + M6502_ZP: sprintf(info->s, "ZP:%03X", cpustate->zp.w.l); break;
+ }
+}
+
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+
+CPU_GET_INFO( m6504 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "M6504"); break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 13; break;
+
+ default: CPU_GET_INFO_CALL(m6502); break;
+ }
+}
+
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+
+CPU_GET_INFO( n2a03 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(n2a03); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "N2A03"); break;
+
+ default: CPU_GET_INFO_CALL(m6502); break;
+ }
+}
+
+
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( m6510 )
+{
+ switch (state)
+ {
+ default: CPU_SET_INFO_CALL(m6502); break;
+ }
+}
+
+CPU_GET_INFO( m6510 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(m6510); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(m6510); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(m6510); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(m6510); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME(m6510_mem); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "M6510"); break;
+
+ default: CPU_GET_INFO_CALL(m6502); break;
+ }
+}
+
+
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+
+CPU_GET_INFO( m6510t )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "M6510T"); break;
+
+ default: CPU_GET_INFO_CALL(m6510); break;
+ }
+}
+
+
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+
+CPU_GET_INFO( m7501 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "M7501"); break;
+
+ default: CPU_GET_INFO_CALL(m6510); break;
+ }
+}
+
+
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+
+CPU_GET_INFO( m8502 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "M8502"); break;
+
+ default: CPU_GET_INFO_CALL(m6510); break;
+ }
+}
+
+
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( m65c02 )
+{
+ m6502_Regs *cpustate = get_safe_token(device);
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: m65c02_set_irq_line(cpustate, INPUT_LINE_NMI, info->i); break;
+
+ default: CPU_SET_INFO_CALL(m6502); break;
+ }
+}
+
+CPU_GET_INFO( m65c02 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(m65c02); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(m65c02); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(m65c02); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(m65c02); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(m65c02); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "M65C02"); break;
+
+ default: CPU_GET_INFO_CALL(m6502); break;
+ }
+}
+
+
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+
+CPU_GET_INFO( m65sc02 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(m65sc02); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(m65sc02); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "M65SC02"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Metal Oxid Semiconductor MOS 6502"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0beta"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Juergen Buchmueller\nCopyright Peter Trauner\nall rights reserved."); break;
+
+ default: CPU_GET_INFO_CALL(m65c02); break;
+ }
+}
+
+
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( deco16 )
+{
+ m6502_Regs *cpustate = get_safe_token(device);
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + M6502_IRQ_LINE: deco16_set_irq_line(cpustate, M6502_IRQ_LINE, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + M6502_SET_OVERFLOW: deco16_set_irq_line(cpustate, M6502_SET_OVERFLOW, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: deco16_set_irq_line(cpustate, INPUT_LINE_NMI, info->i); break;
+
+ default: CPU_SET_INFO_CALL(m6502); break;
+ }
+}
+
+CPU_GET_INFO( deco16 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 8; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(deco16); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(deco16); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(deco16); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(deco16); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(deco16); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "DECO CPU16"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "DECO"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "0.1"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Juergen Buchmueller\nCopyright Bryan McPhail\nall rights reserved."); break;
+
+ default: CPU_GET_INFO_CALL(m6502); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(M6502, m6502);
+DEFINE_LEGACY_CPU_DEVICE(M6504, m6504);
+DEFINE_LEGACY_CPU_DEVICE(M6510, m6510);
+DEFINE_LEGACY_CPU_DEVICE(M6510T, m6510t);
+DEFINE_LEGACY_CPU_DEVICE(M7501, m7501);
+DEFINE_LEGACY_CPU_DEVICE(M8502, m8502);
+DEFINE_LEGACY_CPU_DEVICE(N2A03, n2a03);
+DEFINE_LEGACY_CPU_DEVICE(M65C02, m65c02);
+DEFINE_LEGACY_CPU_DEVICE(M65SC02, m65sc02);
+DEFINE_LEGACY_CPU_DEVICE(DECO16, deco16);
diff --git a/trunk/src/emu/cpu/m6502/m6502.h b/trunk/src/emu/cpu/m6502/m6502.h
new file mode 100644
index 00000000000..c9ebf634dc7
--- /dev/null
+++ b/trunk/src/emu/cpu/m6502/m6502.h
@@ -0,0 +1,226 @@
+/*****************************************************************************
+ *
+ * m6502.h
+ * Portable 6502/65c02/65sc02/6510/n2a03 emulator interface
+ *
+ * Copyright Juergen Buchmueller, all rights reserved.
+ * 65sc02 core Copyright Peter Trauner.
+ * Deco16 portions Copyright Bryan McPhail.
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * pullmoll@t-online.de
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ *****************************************************************************/
+/* 2.February 2000 PeT added 65sc02 subtype */
+
+#pragma once
+
+#ifndef __M6502_H__
+#define __M6502_H__
+
+
+/* set to 1 to test cur_mrhard/cur_wmhard to avoid calls */
+#define FAST_MEMORY 0
+
+#define SUBTYPE_6502 0
+#define SUBTYPE_65C02 1
+#define SUBTYPE_6510 2
+#define SUBTYPE_2A03 3
+#define SUBTYPE_65SC02 4
+#define SUBTYPE_DECO16 5
+
+enum
+{
+ M6502_PC=1, M6502_S, M6502_P, M6502_A, M6502_X, M6502_Y,
+ M6502_EA, M6502_ZP,
+ M6502_SUBTYPE
+};
+
+#define M6502_IRQ_LINE 0
+/* use device_set_input_line(cpudevice, M6502_SET_OVERFLOW, level)
+ to change level of the so input line
+ positiv edge sets overflow flag */
+#define M6502_SET_OVERFLOW 1
+
+
+/* Optional interface to set callbacks */
+typedef struct _m6502_interface m6502_interface;
+struct _m6502_interface
+{
+ read8_space_func read_indexed_func;
+ write8_space_func write_indexed_func;
+ devcb_read8 in_port_func;
+ devcb_write8 out_port_func;
+};
+
+DECLARE_LEGACY_CPU_DEVICE(M6502, m6502);
+DECLARE_LEGACY_CPU_DEVICE(M6504, m6504);
+extern CPU_DISASSEMBLE( m6502 );
+
+/****************************************************************************
+ * The 6510
+ ****************************************************************************/
+#define M6510_A M6502_A
+#define M6510_X M6502_X
+#define M6510_Y M6502_Y
+#define M6510_S M6502_S
+#define M6510_PC M6502_PC
+#define M6510_P M6502_P
+#define M6510_EA M6502_EA
+#define M6510_ZP M6502_ZP
+#define M6510_NMI_STATE M6502_NMI_STATE
+#define M6510_IRQ_STATE M6502_IRQ_STATE
+
+#define M6510_IRQ_LINE M6502_IRQ_LINE
+
+DECLARE_LEGACY_CPU_DEVICE(M6510, m6510);
+
+extern CPU_DISASSEMBLE( m6510 );
+
+UINT8 m6510_get_port(legacy_cpu_device *device);
+
+#define M6510T_A M6502_A
+#define M6510T_X M6502_X
+#define M6510T_Y M6502_Y
+#define M6510T_S M6502_S
+#define M6510T_PC M6502_PC
+#define M6510T_P M6502_P
+#define M6510T_EA M6502_EA
+#define M6510T_ZP M6502_ZP
+#define M6510T_NMI_STATE M6502_NMI_STATE
+#define M6510T_IRQ_STATE M6502_IRQ_STATE
+
+#define M6510T_IRQ_LINE M6502_IRQ_LINE
+
+DECLARE_LEGACY_CPU_DEVICE(M6510T, m6510t);
+
+
+#define M7501_A M6502_A
+#define M7501_X M6502_X
+#define M7501_Y M6502_Y
+#define M7501_S M6502_S
+#define M7501_PC M6502_PC
+#define M7501_P M6502_P
+#define M7501_EA M6502_EA
+#define M7501_ZP M6502_ZP
+#define M7501_NMI_STATE M6502_NMI_STATE
+#define M7501_IRQ_STATE M6502_IRQ_STATE
+
+#define M7501_IRQ_LINE M6502_IRQ_LINE
+
+DECLARE_LEGACY_CPU_DEVICE(M7501, m7501);
+
+#define M8502_A M6502_A
+#define M8502_X M6502_X
+#define M8502_Y M6502_Y
+#define M8502_S M6502_S
+#define M8502_PC M6502_PC
+#define M8502_P M6502_P
+#define M8502_EA M6502_EA
+#define M8502_ZP M6502_ZP
+#define M8502_NMI_STATE M6502_NMI_STATE
+#define M8502_IRQ_STATE M6502_IRQ_STATE
+
+#define M8502_IRQ_LINE M6502_IRQ_LINE
+
+DECLARE_LEGACY_CPU_DEVICE(M8502, m8502);
+
+
+/****************************************************************************
+ * The 2A03 (NES 6502 without decimal mode ADC/SBC)
+ ****************************************************************************/
+#define N2A03_A M6502_A
+#define N2A03_X M6502_X
+#define N2A03_Y M6502_Y
+#define N2A03_S M6502_S
+#define N2A03_PC M6502_PC
+#define N2A03_P M6502_P
+#define N2A03_EA M6502_EA
+#define N2A03_ZP M6502_ZP
+#define N2A03_NMI_STATE M6502_NMI_STATE
+#define N2A03_IRQ_STATE M6502_IRQ_STATE
+
+#define N2A03_IRQ_LINE M6502_IRQ_LINE
+
+DECLARE_LEGACY_CPU_DEVICE(N2A03, n2a03);
+
+#define N2A03_DEFAULTCLOCK (21477272.724 / 12)
+
+/* The N2A03 is integrally tied to its PSG (they're on the same die).
+ Bit 7 of address $4011 (the PSG's DPCM control register), when set,
+ causes an IRQ to be generated. This function allows the IRQ to be called
+ from the PSG core when such an occasion arises. */
+extern void n2a03_irq(device_t *device);
+
+
+/****************************************************************************
+ * The 65C02
+ ****************************************************************************/
+#define M65C02_A M6502_A
+#define M65C02_X M6502_X
+#define M65C02_Y M6502_Y
+#define M65C02_S M6502_S
+#define M65C02_PC M6502_PC
+#define M65C02_P M6502_P
+#define M65C02_EA M6502_EA
+#define M65C02_ZP M6502_ZP
+#define M65C02_NMI_STATE M6502_NMI_STATE
+#define M65C02_IRQ_STATE M6502_IRQ_STATE
+
+#define M65C02_IRQ_LINE M6502_IRQ_LINE
+
+DECLARE_LEGACY_CPU_DEVICE(M65C02, m65c02);
+
+extern CPU_DISASSEMBLE( m65c02 );
+
+
+/****************************************************************************
+ * The 65SC02
+ ****************************************************************************/
+#define M65SC02_A M6502_A
+#define M65SC02_X M6502_X
+#define M65SC02_Y M6502_Y
+#define M65SC02_S M6502_S
+#define M65SC02_PC M6502_PC
+#define M65SC02_P M6502_P
+#define M65SC02_EA M6502_EA
+#define M65SC02_ZP M6502_ZP
+#define M65SC02_NMI_STATE M6502_NMI_STATE
+#define M65SC02_IRQ_STATE M6502_IRQ_STATE
+
+#define M65SC02_IRQ_LINE M6502_IRQ_LINE
+
+DECLARE_LEGACY_CPU_DEVICE(M65SC02, m65sc02);
+
+extern CPU_DISASSEMBLE( m65sc02 );
+
+/****************************************************************************
+ * The DECO CPU16
+ ****************************************************************************/
+#define DECO16_A M6502_A
+#define DECO16_X M6502_X
+#define DECO16_Y M6502_Y
+#define DECO16_S M6502_S
+#define DECO16_PC M6502_PC
+#define DECO16_P M6502_P
+#define DECO16_EA M6502_EA
+#define DECO16_ZP M6502_ZP
+#define DECO16_NMI_STATE M6502_NMI_STATE
+#define DECO16_IRQ_STATE M6502_IRQ_STATE
+
+#define DECO16_IRQ_LINE M6502_IRQ_LINE
+
+DECLARE_LEGACY_CPU_DEVICE(DECO16, deco16);
+
+extern CPU_DISASSEMBLE( deco16 );
+
+#endif /* __M6502_H__ */
diff --git a/trunk/src/emu/cpu/m6502/m6502.txt b/trunk/src/emu/cpu/m6502/m6502.txt
new file mode 100644
index 00000000000..d92af7ec146
--- /dev/null
+++ b/trunk/src/emu/cpu/m6502/m6502.txt
@@ -0,0 +1,163 @@
+mos metal oxid semiconductor
+bought by cbm
+
+license to produce chips
+ rockwell
+
+transistor, logic gate designs:
+NMOS (M65xx)
+CMOS (M65Cxx)
+HMOS (M75xx) hyper? MOS, used in early c16/plus4 series
+H2MOS (M85xx) hyper2 MOS, used in C128, later c16/plus4, late C64
+?SCMOS (M65SCxx) Super? CMOS
+?CE (M65CExx, M45xx) CMOS Enhanced?, used in not released C65
+
+HMOS, H2MOS CPUs have the same core as the NMOS series
+
+6500 / 6501
+mask programable microcontroller
+32 io ports (2 interruptable)
+timer
+64 byte ram
+8 kbyte rom
+
+6502 (used in many designs)
+b-flag always 1! (only pushed as 0 when break executed!)
+memory changing opcodes accesses memory: read, write data, write modified data
+
+6504
+only 12 address pins a11..a0
+
+6508
+8 io pins (p0 bis p7)
+
+6509
+1 megabyte memory management
+(lda,sta (zeropage),y modified, uses 2nd address extension register)
+
+6510/8500 (used in some designs)
+6 io pins (p0 bis p5)
+
+6510T/8503? (used in commodore C1551 floppy)
+8 io pins
+integrated clock generation?
+
+7501/8501 (c16, c116, c232, c264, plus4, c364)
+7 io pins (no p5)
+no nmi
+
+8502 (c128)
+7 io pins (no p7)
+
+the above series is opcode compatible (including illegal opcodes)
+
+
+n2a03 (some arcades, NES)
+-------------------------
+(nintendo variant)
+NMOS based!
+illegal opcodes
+$6c jump indirect low byte overrun problem as in 6502
+no decimal mode
+integrated sound hardware
+
+
+65c02 (used in some designs)
+----------------------------
+fixed jmp ind opcode
+memory changing opcodes accesses memory: read, read, write
+no illegal opcodes from the above series
+so not full compatible to 6502 series
+b flag always 1 as in NMOS Series is not known?
+additional commands
+
+several other CMOS variants
+
+
+65sc02 (where used?)
+--------------------
+65c02 compatible
+additional commands
+
+atari lynx bastian schicks bll
+integrated m65sc02 cpu core
+no bbr bbs instructions, else m65c02 compatible
+
+watara supervision
+integrated m65c02 cpu core (or m65sc02 or m65ce02?)
+
+
+gte65816 (nintendo snes)
+------------------------
+65802 upgrade cpu (c64 and c128 upgrade cpu)
+16 bit wide registers
+24 bit address space
+65c02? compatible mode
+additional commands
+
+
+spc700
+------
+(snes sound processor)
+same register layout?
+same addressing modes?
+heavily modified opcodes
+YA could be combined for 16 bit operations?
+
+
+huc6280 (nec pcengine)
+----------------------
+65sc02 compatible?
+8 memory registers
+(highest 3 bits select memory register, these build a22..a13)
+(so 2 Megabyte address room!)
+additional commands?
+several additional integrated features
+
+
+65ce02 (c65 prototype)
+----------------------
+(scan of documentation available, also use
+c65 m4510 documentation)
+(cpu core to be used in asics)
+65sc02 compatible
+z register
+(65c02 zeropage indexed addressing is now (zeropage),z)
+b bank register, highbyte of all zerozape addressing
+register for stack high byte
+additional command (some from the 65816)
+
+
+m4510 (Commodore C65 CPU)
+-------------------------
+(scan of documentation (in c65 documentation) available)
+65ce02 compatible
+integrated 20 bit memory management (map)
+(aug opcode changed to map opcode)
+2 cia6526 integrated
+1 uart integrated
+
+
+mitsubishi 740 series
+---------------------
+(data book in electronic form available)
+(M507xx, M509xx, M374xx, M38xxx, M375xx)
+NMOS based
+additional operation mode
+(arithmetic instruction not performing on akku (a=a operation addressing mode)
+but on zeropage ([x]=[x] operation addressing mode))
+additional instructions LDM, MUL, DIV, TST, COM, RRF, CLT, SET, WIT, STP, CLP
+BRK 1 byte only?
+BRA CMOS compatible
+BBC, BBR different opcode as CMOS, and also akku addressing
+different TRB, TSB
+no CMOS STZ, JMP ind,x
+STP not in all variants
+MUL, DIV not in all variants
+
+
+Set Overflow Pin
+----------------
+in 6502 and pin compatibles (65C02 65SC02 65SC802 65CE02), M6509
+no SO pin 6510/7501/8500/8501/8502/65sc816
+6510T ?
diff --git a/trunk/src/emu/cpu/m6502/m6509.c b/trunk/src/emu/cpu/m6502/m6509.c
new file mode 100644
index 00000000000..995a935096f
--- /dev/null
+++ b/trunk/src/emu/cpu/m6502/m6509.c
@@ -0,0 +1,418 @@
+/*****************************************************************************
+ *
+ * m6509.c
+ * Portable 6509 emulator V1.0beta1
+ *
+ * Copyright Peter Trauner, all rights reserved.
+ * documentation by vice emulator team
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * pullmoll@t-online.de
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ *****************************************************************************/
+/*
+ 2000 March 10 PeT added SO input line
+
+The basic difference is the amount of RAM these machines have been supplied with. The B128 and the CBM *10
+models had 128k RAM, the others 256k. This implies some banking scheme, as the 6502 can only address 64k. And
+indeed those machines use a 6509, that can address 1 MByte of RAM. It has 2 registers at addresses 0 and 1. The
+indirect bank register at address 1 determines the bank (0-15) where the opcodes LDA (zp),Y and STA (zp),Y
+take the data from. The exec bank register at address 0 determines the bank where all other read and write
+addresses take place.
+
+ vice writes to bank register only with zeropage operand
+ 0, 1 are bank register in all banks
+
+ lda (zp),y
+ sta (zp),y
+
+*/
+
+#include "emu.h"
+#include "debugger.h"
+#include "m6509.h"
+
+#include "ops02.h"
+#include "ill02.h"
+#include "ops09.h"
+
+#define M6502_NMI_VEC 0xfffa
+#define M6502_RST_VEC 0xfffc
+#define M6502_IRQ_VEC 0xfffe
+#define M6509_RST_VEC M6502_RST_VEC
+#define M6509_IRQ_VEC M6502_IRQ_VEC
+#define M6509_NMI_VEC M6502_NMI_VEC
+
+#define VERBOSE 0
+
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+typedef struct _m6509_Regs m6509_Regs;
+struct _m6509_Regs {
+ UINT8 subtype; /* currently selected cpu sub type */
+ void (*const *insn)(m6509_Regs *); /* pointer to the function pointer table */
+ PAIR ppc; /* previous program counter */
+ /* pc.w.h contains the current page pc_bank.w.h for better speed */
+ PAIR pc; /* program counter */
+ PAIR sp; /* stack pointer (always 100 - 1FF) */
+ PAIR zp; /* zero page address */
+ PAIR ea; /* effective address */
+ UINT8 a; /* Accumulator */
+ UINT8 x; /* X index register */
+ UINT8 y; /* Y index register */
+ PAIR pc_bank; /* 4 bits, addressed over address 0 */
+ PAIR ind_bank; /* 4 bits, addressed over address 1 */
+ UINT8 p; /* Processor status */
+ UINT8 pending_irq; /* nonzero if an IRQ is pending */
+ UINT8 after_cli; /* pending IRQ and last insn cleared I */
+ UINT8 nmi_state;
+ UINT8 irq_state;
+ UINT8 so_state;
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ address_space *space;
+ direct_read_data *direct;
+
+ int icount;
+
+ read8_space_func rdmem_id; /* readmem callback for indexed instructions */
+ write8_space_func wrmem_id; /* writemem callback for indexed instructions */
+};
+
+INLINE m6509_Regs *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == M6509);
+ return (m6509_Regs *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+/***************************************************************
+ * include the opcode macros, functions and tables
+ ***************************************************************/
+
+#include "t6509.c"
+
+static READ8_HANDLER( m6509_read_00000 )
+{
+ m6509_Regs *cpustate = get_safe_token(&space->device());
+
+ return cpustate->pc_bank.b.h2;
+}
+
+static READ8_HANDLER( m6509_read_00001 )
+{
+ m6509_Regs *cpustate = get_safe_token(&space->device());
+
+ return cpustate->ind_bank.b.h2;
+}
+
+static WRITE8_HANDLER( m6509_write_00000 )
+{
+ m6509_Regs *cpustate = get_safe_token(&space->device());
+
+ cpustate->pc_bank.b.h2=data&0xf;
+ cpustate->pc.w.h=cpustate->pc_bank.w.h;
+}
+
+static WRITE8_HANDLER( m6509_write_00001 )
+{
+ m6509_Regs *cpustate = get_safe_token(&space->device());
+
+ cpustate->ind_bank.b.h2=data&0xf;
+}
+
+static ADDRESS_MAP_START(m6509_mem, AS_PROGRAM, 8)
+ AM_RANGE(0x00000, 0x00000) AM_MIRROR(0xF0000) AM_READWRITE(m6509_read_00000, m6509_write_00000)
+ AM_RANGE(0x00001, 0x00001) AM_MIRROR(0xF0000) AM_READWRITE(m6509_read_00001, m6509_write_00001)
+ADDRESS_MAP_END
+
+static UINT8 default_rdmem_id(address_space *space, offs_t address) { return space->read_byte(address); }
+static void default_wdmem_id(address_space *space, offs_t address, UINT8 data) { space->write_byte(address, data); }
+
+static CPU_INIT( m6509 )
+{
+ m6509_Regs *cpustate = get_safe_token(device);
+ const m6502_interface *intf = (const m6502_interface *)device->static_config();
+
+ cpustate->rdmem_id = default_rdmem_id;
+ cpustate->wrmem_id = default_wdmem_id;
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+ cpustate->space = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->space->direct();
+
+ if ( intf )
+ {
+ if ( intf->read_indexed_func )
+ cpustate->rdmem_id = intf->read_indexed_func;
+
+ if ( intf->write_indexed_func )
+ cpustate->wrmem_id = intf->write_indexed_func;
+ }
+}
+
+static CPU_RESET( m6509 )
+{
+ m6509_Regs *cpustate = get_safe_token(device);
+
+ cpustate->insn = insn6509;
+
+ cpustate->pc_bank.d=cpustate->ind_bank.d=0;
+ cpustate->pc_bank.b.h2=cpustate->ind_bank.b.h2=0xf; /* cbm500 needs this */
+ cpustate->pc.w.h=cpustate->pc_bank.w.h;
+ /* wipe out the rest of the m6509 structure */
+ /* read the reset vector into PC */
+ PCL = RDMEM(M6509_RST_VEC|PB);
+ PCH = RDMEM((M6509_RST_VEC+1)|PB);
+
+ cpustate->sp.d = 0x01ff;
+ cpustate->p = F_T|F_B|F_I|F_Z|(P&F_D); /* set T, I and Z flags */
+ cpustate->pending_irq = 0; /* nonzero if an IRQ is pending */
+ cpustate->after_cli = 0; /* pending IRQ and last insn cleared I */
+ cpustate->irq_callback = NULL;
+}
+
+static CPU_EXIT( m6509 )
+{
+ /* nothing to do yet */
+}
+
+INLINE void m6509_take_irq( m6509_Regs *cpustate)
+{
+
+ if( !(P & F_I) )
+ {
+ EAD = M6509_IRQ_VEC;
+ EAWH = PBWH;
+ cpustate->icount -= 2;
+ PUSH(PCH);
+ PUSH(PCL);
+ PUSH(P & ~F_B);
+ P |= F_I; /* knock out D and set I flag */
+ PCL = RDMEM(EAD);
+ PCH = RDMEM(EAD+1);
+ LOG(("M6509 '%s' takes IRQ ($%04x)\n", cpustate->device->tag(), PCD));
+ /* call back the cpuintrf to let it clear the line */
+ if (cpustate->irq_callback) (*cpustate->irq_callback)(cpustate->device, 0);
+ }
+ cpustate->pending_irq = 0;
+}
+
+static CPU_EXECUTE( m6509 )
+{
+ m6509_Regs *cpustate = get_safe_token(device);
+
+ do
+ {
+ UINT8 op;
+ PPC = PCD;
+
+ debugger_instruction_hook(device, PCD);
+
+ /* if an irq is pending, take it now */
+ if( cpustate->pending_irq )
+ m6509_take_irq(cpustate);
+
+ op = RDOP();
+ (*cpustate->insn[op])(cpustate);
+
+ /* check if the I flag was just reset (interrupts enabled) */
+ if( cpustate->after_cli )
+ {
+ LOG(("M6509 '%s' after_cli was >0", cpustate->device->tag()));
+ cpustate->after_cli = 0;
+ if (cpustate->irq_state != CLEAR_LINE)
+ {
+ LOG((": irq line is asserted: set pending IRQ\n"));
+ cpustate->pending_irq = 1;
+ }
+ else
+ {
+ LOG((": irq line is clear\n"));
+ }
+ }
+ else
+ if( cpustate->pending_irq )
+ m6509_take_irq(cpustate);
+
+ } while (cpustate->icount > 0);
+}
+
+static void m6509_set_irq_line(m6509_Regs *cpustate, int irqline, int state)
+{
+ if (irqline == INPUT_LINE_NMI)
+ {
+ if (cpustate->nmi_state == state) return;
+ cpustate->nmi_state = state;
+ if( state != CLEAR_LINE )
+ {
+ LOG(( "M6509 '%s' set_nmi_line(ASSERT)\n", cpustate->device->tag()));
+ EAD = M6509_NMI_VEC;
+ EAWH = PBWH;
+ cpustate->icount -= 2;
+ PUSH(PCH);
+ PUSH(PCL);
+ PUSH(P & ~F_B);
+ P |= F_I; /* knock out D and set I flag */
+ PCL = RDMEM(EAD);
+ PCH = RDMEM(EAD+1);
+ LOG(("M6509 '%s' takes NMI ($%04x)\n", cpustate->device->tag(), PCD));
+ }
+ }
+ else
+ {
+ if( irqline == M6509_SET_OVERFLOW )
+ {
+ if( cpustate->so_state && !state )
+ {
+ LOG(( "M6509 '%s' set overflow\n", cpustate->device->tag()));
+ P|=F_V;
+ }
+ cpustate->so_state=state;
+ return;
+ }
+ cpustate->irq_state = state;
+ if( state != CLEAR_LINE )
+ {
+ LOG(( "M6509 '%s' set_irq_line(ASSERT)\n", cpustate->device->tag()));
+ cpustate->pending_irq = 1;
+ }
+ }
+}
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( m6509 )
+{
+ m6509_Regs *cpustate = get_safe_token(device);
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + M6509_IRQ_LINE: m6509_set_irq_line(cpustate, M6509_IRQ_LINE, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + M6509_SET_OVERFLOW:m6509_set_irq_line(cpustate, M6509_SET_OVERFLOW, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: m6509_set_irq_line(cpustate, INPUT_LINE_NMI, info->i); break;
+
+ case CPUINFO_INT_PC: PCW = info->i; break;
+ case CPUINFO_INT_REGISTER + M6509_PC: cpustate->pc.w.l = info->i; break;
+ case CPUINFO_INT_SP: S = info->i; break;
+ case CPUINFO_INT_REGISTER + M6509_S: cpustate->sp.b.l = info->i; break;
+ case CPUINFO_INT_REGISTER + M6509_P: cpustate->p = info->i; break;
+ case CPUINFO_INT_REGISTER + M6509_A: cpustate->a = info->i; break;
+ case CPUINFO_INT_REGISTER + M6509_X: cpustate->x = info->i; break;
+ case CPUINFO_INT_REGISTER + M6509_Y: cpustate->y = info->i; break;
+ case CPUINFO_INT_REGISTER + M6509_PC_BANK: cpustate->pc_bank.b.h2 = info->i; break;
+ case CPUINFO_INT_REGISTER + M6509_IND_BANK: cpustate->ind_bank.b.h2 = info->i; break;
+ case CPUINFO_INT_REGISTER + M6509_EA: cpustate->ea.w.l = info->i; break;
+ case CPUINFO_INT_REGISTER + M6509_ZP: cpustate->zp.w.l = info->i; break;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+CPU_GET_INFO( m6509 )
+{
+ m6509_Regs *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(m6509_Regs); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 2; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 3; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 10; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 20; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_INPUT_STATE + M6509_IRQ_LINE: info->i = cpustate->irq_state; break;
+ case CPUINFO_INT_INPUT_STATE + M6509_SET_OVERFLOW:info->i = cpustate->so_state; break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: info->i = cpustate->nmi_state; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = cpustate->ppc.w.l; break;
+
+ case CPUINFO_INT_PC: info->i = PCD; break;
+ case CPUINFO_INT_REGISTER + M6509_PC: info->i = cpustate->pc.w.l; break;
+ case CPUINFO_INT_SP: info->i = S; break;
+ case CPUINFO_INT_REGISTER + M6509_S: info->i = cpustate->sp.b.l; break;
+ case CPUINFO_INT_REGISTER + M6509_P: info->i = cpustate->p; break;
+ case CPUINFO_INT_REGISTER + M6509_A: info->i = cpustate->a; break;
+ case CPUINFO_INT_REGISTER + M6509_X: info->i = cpustate->x; break;
+ case CPUINFO_INT_REGISTER + M6509_Y: info->i = cpustate->y; break;
+ case CPUINFO_INT_REGISTER + M6509_PC_BANK: info->i = cpustate->pc_bank.b.h2; break;
+ case CPUINFO_INT_REGISTER + M6509_IND_BANK: info->i = cpustate->ind_bank.b.h2; break;
+ case CPUINFO_INT_REGISTER + M6509_EA: info->i = cpustate->ea.w.l; break;
+ case CPUINFO_INT_REGISTER + M6509_ZP: info->i = cpustate->zp.w.l; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(m6509); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(m6509); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(m6509); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(m6509); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(m6509); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(m6502); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME(m6509_mem); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "M6509"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "MOS Technology 6509"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0beta"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Juergen Buchmueller\nCopyright Peter Trauner\nall rights reserved."); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c%c%c%c%c%c%c",
+ cpustate->p & 0x80 ? 'N':'.',
+ cpustate->p & 0x40 ? 'V':'.',
+ cpustate->p & 0x20 ? 'R':'.',
+ cpustate->p & 0x10 ? 'B':'.',
+ cpustate->p & 0x08 ? 'D':'.',
+ cpustate->p & 0x04 ? 'I':'.',
+ cpustate->p & 0x02 ? 'Z':'.',
+ cpustate->p & 0x01 ? 'C':'.');
+ break;
+
+ case CPUINFO_STR_REGISTER + M6509_PC: sprintf(info->s, "PC:%04X", cpustate->pc.w.l); break;
+ case CPUINFO_STR_REGISTER + M6509_S: sprintf(info->s, "S:%02X", cpustate->sp.b.l); break;
+ case CPUINFO_STR_REGISTER + M6509_P: sprintf(info->s, "P:%02X", cpustate->p); break;
+ case CPUINFO_STR_REGISTER + M6509_A: sprintf(info->s, "A:%02X", cpustate->a); break;
+ case CPUINFO_STR_REGISTER + M6509_X: sprintf(info->s, "X:%02X", cpustate->x); break;
+ case CPUINFO_STR_REGISTER + M6509_Y: sprintf(info->s, "Y:%02X", cpustate->y); break;
+ case CPUINFO_STR_REGISTER + M6509_PC_BANK: sprintf(info->s, "M0:%01X", cpustate->pc_bank.b.h2); break;
+ case CPUINFO_STR_REGISTER + M6509_IND_BANK: sprintf(info->s, "M1:%01X", cpustate->ind_bank.b.h2); break;
+ case CPUINFO_STR_REGISTER + M6509_EA: sprintf(info->s, "EA:%04X", cpustate->ea.w.l); break;
+ case CPUINFO_STR_REGISTER + M6509_ZP: sprintf(info->s, "ZP:%03X", cpustate->zp.w.l); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(M6509, m6509);
diff --git a/trunk/src/emu/cpu/m6502/m6509.h b/trunk/src/emu/cpu/m6502/m6509.h
new file mode 100644
index 00000000000..0f3fe1daa48
--- /dev/null
+++ b/trunk/src/emu/cpu/m6502/m6509.h
@@ -0,0 +1,44 @@
+/*****************************************************************************
+ *
+ * m6509.h
+ * Portable 6509 emulator V1.0beta
+ *
+ * Copyright Peter Trauner, all rights reserved.
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * pullmoll@t-online.de
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ *****************************************************************************/
+
+#pragma once
+
+#ifndef __M6509_H__
+#define _M6509_H
+
+#include "m6502.h"
+
+enum
+{
+ M6509_PC=1, M6509_S, M6509_P, M6509_A, M6509_X, M6509_Y,
+ M6509_EA, M6509_ZP, M6509_NMI_STATE, M6509_IRQ_STATE, M6509_SO_STATE,
+ M6509_PC_BANK, M6509_IND_BANK
+};
+
+#define M6509_IRQ_LINE M6502_IRQ_LINE
+/* use device_set_input_line(cpudevice, M6509_SET_OVERFLOW, level)
+ to change level of the so input line
+ positiv edge sets overflow flag */
+#define M6509_SET_OVERFLOW 3
+
+DECLARE_LEGACY_CPU_DEVICE(M6509, m6509);
+
+#endif /* __M6509_H__ */
diff --git a/trunk/src/emu/cpu/m6502/m65ce02.c b/trunk/src/emu/cpu/m6502/m65ce02.c
new file mode 100644
index 00000000000..a79fbc7fd9d
--- /dev/null
+++ b/trunk/src/emu/cpu/m6502/m65ce02.c
@@ -0,0 +1,365 @@
+/*****************************************************************************
+ *
+ * m65ce02.c
+ * Portable 65ce02 emulator V1.0beta3
+ *
+ * Copyright Peter Trauner, all rights reserved
+ * documentation preliminary databook
+ * documentation by michael steil mist@c64.org
+ * available at ftp://ftp.funet.fi/pub/cbm/c65
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * pullmoll@t-online.de
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ *****************************************************************************/
+/* 4. February 2000 PeT fixed relative word operand */
+/* 4. February 2000 PeT jsr (absolut) jsr (absolut,x) inw dew */
+/* 17.February 2000 PeT phw */
+/* 16.March 2000 PeT fixed some instructions accordingly to databook */
+/* 7. May 2000 PeT splittet into m65ce02 and m4510 */
+
+/*
+
+* neg is now simple 2er komplement negation with set of N and Z
+
+* phw push low order byte, push high order byte!
+
+* tys txs not interruptable, not implemented
+
+*/
+
+#include "emu.h"
+#include "debugger.h"
+#include "m65ce02.h"
+
+#include "mincce02.h"
+#include "opsce02.h"
+
+#define M6502_NMI_VEC 0xfffa
+#define M6502_RST_VEC 0xfffc
+#define M6502_IRQ_VEC 0xfffe
+#define M65CE02_RST_VEC M6502_RST_VEC
+#define M65CE02_IRQ_VEC M6502_IRQ_VEC
+#define M65CE02_NMI_VEC M6502_NMI_VEC
+
+#define VERBOSE 0
+
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+typedef struct _m65ce02_Regs m65ce02_Regs;
+struct _m65ce02_Regs {
+ void (*const *insn)(m65ce02_Regs *); /* pointer to the function pointer table */
+ PAIR ppc; /* previous program counter */
+ PAIR pc; /* program counter */
+ PAIR sp; /* stack pointer (always 100 - 1FF) */
+ PAIR zp; /* zero page address */
+ /* contains B register zp.b.h */
+ PAIR ea; /* effective address */
+ UINT8 a; /* Accumulator */
+ UINT8 x; /* X index register */
+ UINT8 y; /* Y index register */
+ UINT8 z; /* Z index register */
+ UINT8 p; /* Processor status */
+ UINT8 pending_irq; /* nonzero if an IRQ is pending */
+ UINT8 after_cli; /* pending IRQ and last insn cleared I */
+ UINT8 nmi_state;
+ UINT8 irq_state;
+ int icount;
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ address_space *space;
+ direct_read_data *direct;
+ read8_space_func rdmem_id; /* readmem callback for indexed instructions */
+ write8_space_func wrmem_id; /* writemem callback for indexed instructions */
+};
+
+INLINE m65ce02_Regs *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == M65CE02);
+ return (m65ce02_Regs *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+/***************************************************************
+ * include the opcode macros, functions and tables
+ ***************************************************************/
+
+#include "t65ce02.c"
+
+static UINT8 default_rdmem_id(address_space *space, offs_t address) { return space->read_byte(address); }
+static void default_wdmem_id(address_space *space, offs_t address, UINT8 data) { space->write_byte(address, data); }
+
+static CPU_INIT( m65ce02 )
+{
+ m65ce02_Regs *cpustate = get_safe_token(device);
+ const m6502_interface *intf = (const m6502_interface *)device->static_config();
+
+ cpustate->rdmem_id = default_rdmem_id;
+ cpustate->wrmem_id = default_wdmem_id;
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+ cpustate->space = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->space->direct();
+
+ if ( intf )
+ {
+ if ( intf->read_indexed_func )
+ cpustate->rdmem_id = intf->read_indexed_func;
+
+ if ( intf->write_indexed_func )
+ cpustate->wrmem_id = intf->write_indexed_func;
+ }
+}
+
+static CPU_RESET( m65ce02 )
+{
+ m65ce02_Regs *cpustate = get_safe_token(device);
+
+ cpustate->insn = insn65ce02;
+
+ /* wipe out the rest of the m65ce02 structure */
+ /* read the reset vector into PC */
+ /* reset z index and b bank */
+ PCL = RDMEM(M65CE02_RST_VEC);
+ PCH = RDMEM(M65CE02_RST_VEC+1);
+
+ /* after reset in 6502 compatibility mode */
+ cpustate->sp.d = 0x01ff; /* high byte descriped in databook */
+ cpustate->z = 0;
+ B = 0;
+ cpustate->p = F_E|F_B|F_I|F_Z; /* set E, I and Z flags */
+ cpustate->pending_irq = 0; /* nonzero if an IRQ is pending */
+ cpustate->after_cli = 0; /* pending IRQ and last insn cleared I */
+ cpustate->irq_callback = NULL;
+}
+
+static CPU_EXIT( m65ce02 )
+{
+ /* nothing to do yet */
+}
+
+INLINE void m65ce02_take_irq(m65ce02_Regs *cpustate)
+{
+ if( !(P & F_I) )
+ {
+ EAD = M65CE02_IRQ_VEC;
+ cpustate->icount -= 7;
+ PUSH(PCH);
+ PUSH(PCL);
+ PUSH(P & ~F_B);
+ P = (P & ~F_D) | F_I; /* knock out D and set I flag */
+ PCL = RDMEM(EAD);
+ PCH = RDMEM(EAD+1);
+ LOG(("M65ce02 '%s' takes IRQ ($%04x)\n", cpustate->device->tag(), PCD));
+ /* call back the cpuintrf to let it clear the line */
+ if (cpustate->irq_callback) (*cpustate->irq_callback)(cpustate->device, 0);
+ }
+ cpustate->pending_irq = 0;
+}
+
+static CPU_EXECUTE( m65ce02 )
+{
+ m65ce02_Regs *cpustate = get_safe_token(device);
+
+ do
+ {
+ UINT8 op;
+ PPC = PCD;
+
+ debugger_instruction_hook(device, PCD);
+
+ /* if an irq is pending, take it now */
+ if( cpustate->pending_irq )
+ m65ce02_take_irq(cpustate);
+
+ op = RDOP();
+ (*insn65ce02[op])(cpustate);
+
+ /* check if the I flag was just reset (interrupts enabled) */
+ if( cpustate->after_cli )
+ {
+ LOG(("M65ce02 '%s' after_cli was >0", cpustate->device->tag()));
+ cpustate->after_cli = 0;
+ if (cpustate->irq_state != CLEAR_LINE)
+ {
+ LOG((": irq line is asserted: set pending IRQ\n"));
+ cpustate->pending_irq = 1;
+ }
+ else
+ {
+ LOG((": irq line is clear\n"));
+ }
+ }
+ else
+ if( cpustate->pending_irq )
+ m65ce02_take_irq(cpustate);
+
+ } while (cpustate->icount > 0);
+}
+
+static void m65ce02_set_irq_line(m65ce02_Regs *cpustate, int irqline, int state)
+{
+ if (irqline == INPUT_LINE_NMI)
+ {
+ if (cpustate->nmi_state == state) return;
+ cpustate->nmi_state = state;
+ if( state != CLEAR_LINE )
+ {
+ LOG(("M65ce02 '%s' set_nmi_line(ASSERT)\n", cpustate->device->tag()));
+ EAD = M65CE02_NMI_VEC;
+ cpustate->icount -= 7;
+ PUSH(PCH);
+ PUSH(PCL);
+ PUSH(P & ~F_B);
+ P = (P & ~F_D) | F_I; /* knock out D and set I flag */
+ PCL = RDMEM(EAD);
+ PCH = RDMEM(EAD+1);
+ LOG(("M65ce02 '%s' takes NMI ($%04x)\n", cpustate->device->tag(), PCD));
+ }
+ }
+ else
+ {
+ cpustate->irq_state = state;
+ if( state != CLEAR_LINE )
+ {
+ LOG(("M65ce02 '%s' set_irq_line(ASSERT)\n", cpustate->device->tag()));
+ cpustate->pending_irq = 1;
+ }
+ }
+}
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( m65ce02 )
+{
+ m65ce02_Regs *cpustate = get_safe_token(device);
+
+ switch( state )
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + M65CE02_IRQ_STATE: m65ce02_set_irq_line( cpustate, M65CE02_IRQ_LINE, info->i ); break;
+ case CPUINFO_INT_INPUT_STATE + M65CE02_NMI_STATE: m65ce02_set_irq_line( cpustate, INPUT_LINE_NMI, info->i ); break;
+
+ case CPUINFO_INT_PC: PCW = info->i; break;
+ case CPUINFO_INT_REGISTER + M65CE02_PC: cpustate->pc.w.l = info->i; break;
+ case CPUINFO_INT_SP: cpustate->sp.b.l = info->i; break;
+ case CPUINFO_INT_REGISTER + M65CE02_S: cpustate->sp.w.l = info->i; break;
+ case CPUINFO_INT_REGISTER + M65CE02_P: cpustate->p = info->i; break;
+ case CPUINFO_INT_REGISTER + M65CE02_A: cpustate->a = info->i; break;
+ case CPUINFO_INT_REGISTER + M65CE02_X: cpustate->x = info->i; break;
+ case CPUINFO_INT_REGISTER + M65CE02_Y: cpustate->y = info->i; break;
+ case CPUINFO_INT_REGISTER + M65CE02_Z: cpustate->z = info->i; break;
+ case CPUINFO_INT_REGISTER + M65CE02_B: cpustate->zp.b.h = info->i; break;
+ case CPUINFO_INT_REGISTER + M65CE02_EA: cpustate->ea.w.l = info->i; break;
+ case CPUINFO_INT_REGISTER + M65CE02_ZP: cpustate->zp.b.l = info->i; break;
+ }
+}
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+CPU_GET_INFO( m65ce02 )
+{
+ m65ce02_Regs *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch( state )
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(m65ce02_Regs); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 2; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 3; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 10; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 20; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case CPUINFO_INT_LOGADDR_WIDTH_PROGRAM: info->i = 16; break;
+ case CPUINFO_INT_PAGE_SHIFT_PROGRAM: info->i = 13; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_INPUT_STATE+M65CE02_NMI_STATE: info->i = cpustate->nmi_state; break;
+ case CPUINFO_INT_INPUT_STATE+M65CE02_IRQ_STATE: info->i = cpustate->irq_state; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = cpustate->ppc.w.l; break;
+
+ case CPUINFO_INT_PC: info->i = PCD; break;
+ case CPUINFO_INT_REGISTER+M65CE02_PC: info->i = cpustate->pc.w.l; break;
+ case CPUINFO_INT_SP: info->i = cpustate->sp.b.l; break;
+ case CPUINFO_INT_REGISTER+M65CE02_S: info->i = cpustate->sp.w.l; break;
+ case CPUINFO_INT_REGISTER+M65CE02_P: info->i = cpustate->p; break;
+ case CPUINFO_INT_REGISTER+M65CE02_A: info->i = cpustate->a; break;
+ case CPUINFO_INT_REGISTER+M65CE02_X: info->i = cpustate->x; break;
+ case CPUINFO_INT_REGISTER+M65CE02_Y: info->i = cpustate->y; break;
+ case CPUINFO_INT_REGISTER+M65CE02_Z: info->i = cpustate->z; break;
+ case CPUINFO_INT_REGISTER+M65CE02_B: info->i = cpustate->zp.b.h; break;
+ case CPUINFO_INT_REGISTER+M65CE02_EA: info->i = cpustate->ea.w.l; break;
+ case CPUINFO_INT_REGISTER+M65CE02_ZP: info->i = cpustate->zp.w.l; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(m65ce02); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(m65ce02); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(m65ce02); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(m65ce02); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(m65ce02); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(m65ce02); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "M65CE02"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s,"CBM Semiconductor Group CSG 65CE02"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s,"1.0beta"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s,__FILE__);
+ case DEVINFO_STR_CREDITS:
+ strcpy(info->s, "Copyright Juergen Buchmueller\n"
+ "Copyright Peter Trauner\n"
+ "all rights reserved."); break;
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c%c%c%c%c%c%c",
+ cpustate->p & 0x80 ? 'N':'.',
+ cpustate->p & 0x40 ? 'V':'.',
+ cpustate->p & 0x20 ? 'E':'.',
+ cpustate->p & 0x10 ? 'B':'.',
+ cpustate->p & 0x08 ? 'D':'.',
+ cpustate->p & 0x04 ? 'I':'.',
+ cpustate->p & 0x02 ? 'Z':'.',
+ cpustate->p & 0x01 ? 'C':'.');
+ break;
+
+ case CPUINFO_STR_REGISTER + M65CE02_PC: sprintf(info->s, "PC:%04X", cpustate->pc.w.l); break;
+ case CPUINFO_STR_REGISTER + M65CE02_S: sprintf(info->s, "S:%02X", cpustate->sp.b.l); break;
+ case CPUINFO_STR_REGISTER + M65CE02_P: sprintf(info->s, "P:%02X", cpustate->p); break;
+ case CPUINFO_STR_REGISTER + M65CE02_A: sprintf(info->s, "A:%02X", cpustate->a); break;
+ case CPUINFO_STR_REGISTER + M65CE02_X: sprintf(info->s, "X:%02X", cpustate->x); break;
+ case CPUINFO_STR_REGISTER + M65CE02_Y: sprintf(info->s, "Y:%02X", cpustate->y); break;
+ case CPUINFO_STR_REGISTER + M65CE02_Z: sprintf(info->s, "Z:%02X", cpustate->z); break;
+ case CPUINFO_STR_REGISTER + M65CE02_B: sprintf(info->s, "B:%02X", cpustate->zp.b.h); break;
+ case CPUINFO_STR_REGISTER + M65CE02_EA: sprintf(info->s, "EA:%04X", cpustate->ea.w.l); break;
+ case CPUINFO_STR_REGISTER + M65CE02_ZP: sprintf(info->s, "ZP:%03X", cpustate->zp.w.l); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(M65CE02, m65ce02);
diff --git a/trunk/src/emu/cpu/m6502/m65ce02.h b/trunk/src/emu/cpu/m6502/m65ce02.h
new file mode 100644
index 00000000000..2a556f560ff
--- /dev/null
+++ b/trunk/src/emu/cpu/m6502/m65ce02.h
@@ -0,0 +1,42 @@
+/*****************************************************************************
+ *
+ * m65ce02.c
+ * Portable 65ce02 emulator V1.0beta
+ *
+ * Copyright Peter Trauner, all rights reserved.
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * pullmoll@t-online.de
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ *****************************************************************************/
+
+#pragma once
+
+#ifndef __M65CE02_H__
+#define __M65CE02_H__
+
+#include "m6502.h"
+
+enum
+{
+ M65CE02_PC=1, M65CE02_S, M65CE02_P, M65CE02_A, M65CE02_X, M65CE02_Y,
+ M65CE02_Z, M65CE02_B, M65CE02_EA, M65CE02_ZP,
+ M65CE02_NMI_STATE, M65CE02_IRQ_STATE
+};
+
+#define M65CE02_IRQ_LINE M6502_IRQ_LINE
+
+DECLARE_LEGACY_CPU_DEVICE(M65CE02, m65ce02);
+
+extern CPU_DISASSEMBLE( m65ce02 );
+
+#endif /* __M65CE02_H__ */
diff --git a/trunk/src/emu/cpu/m6502/minc4510.h b/trunk/src/emu/cpu/m6502/minc4510.h
new file mode 100644
index 00000000000..26b06fba9c9
--- /dev/null
+++ b/trunk/src/emu/cpu/m6502/minc4510.h
@@ -0,0 +1,70 @@
+/*****************************************************************************
+ *
+ * minc4510.h
+ * Base macros for 4510 CPU files
+ *
+ *****************************************************************************/
+
+
+/* 4510 flags */
+#define F_C 0x01
+#define F_Z 0x02
+#define F_I 0x04
+#define F_D 0x08
+#define F_B 0x10
+#define F_E 0x20
+#define F_V 0x40
+#define F_N 0x80
+
+/* some shortcuts for improved readability */
+#define A cpustate->a
+#define X cpustate->x
+#define Y cpustate->y
+#define P cpustate->p
+#define Z cpustate->z
+#define B cpustate->zp.b.h
+#define SW cpustate->sp.w.l
+#define SPL cpustate->sp.b.l
+#define SPH cpustate->sp.b.h
+#define SPD cpustate->sp.d
+
+#define NZ cpustate->nz
+
+#define EAL cpustate->ea.b.l
+#define EAH cpustate->ea.b.h
+#define EAW cpustate->ea.w.l
+#define EAD cpustate->ea.d
+
+#define ZPL cpustate->zp.b.l
+#define ZPH cpustate->zp.b.h
+#define ZPW cpustate->zp.w.l
+#define ZPD cpustate->zp.d
+
+#define PCL cpustate->pc.b.l
+#define PCH cpustate->pc.b.h
+#define PCW cpustate->pc.w.l
+#define PCD cpustate->pc.d
+
+#define PPC cpustate->ppc.d
+
+#define IRQ_STATE cpustate->irq_state
+#define AFTER_CLI cpustate->after_cli
+
+#define M4510_MEM(addr) (cpustate->mem[(addr)>>13]+(addr))
+
+#define PEEK_OP() cpustate->direct->read_decrypted_byte(M4510_MEM(PCW))
+
+#define RDMEM(addr) cpustate->space->read_byte(M4510_MEM(addr)); cpustate->icount -= 1
+#define WRMEM(addr,data) cpustate->space->write_byte(M4510_MEM(addr),data); cpustate->icount -= 1
+
+/***************************************************************
+ * RDOP read an opcode
+ ***************************************************************/
+#undef RDOP
+#define RDOP() m4510_cpu_readop(cpustate); cpustate->icount -= 1
+
+/***************************************************************
+ * RDOPARG read an opcode argument
+ ***************************************************************/
+#undef RDOPARG
+#define RDOPARG() m4510_cpu_readop_arg(cpustate); cpustate->icount -= 1
diff --git a/trunk/src/emu/cpu/m6502/mincce02.h b/trunk/src/emu/cpu/m6502/mincce02.h
new file mode 100644
index 00000000000..fca4d51044f
--- /dev/null
+++ b/trunk/src/emu/cpu/m6502/mincce02.h
@@ -0,0 +1,69 @@
+/*****************************************************************************
+ *
+ * mincce02.h
+ * Base macros for 65ce02 CPU files
+ *
+ *****************************************************************************/
+
+
+/* 65ce02 flags */
+#define F_C 0x01
+#define F_Z 0x02
+#define F_I 0x04
+#define F_D 0x08
+#define F_B 0x10
+#define F_E 0x20
+#define F_V 0x40
+#define F_N 0x80
+
+/* some shortcuts for improved readability */
+#define A cpustate->a
+#define X cpustate->x
+#define Y cpustate->y
+#define P cpustate->p
+#define Z cpustate->z
+#define B cpustate->zp.b.h
+#define SW cpustate->sp.w.l
+#define SPL cpustate->sp.b.l
+#define SPH cpustate->sp.b.h
+#define SPD cpustate->sp.d
+
+#define NZ cpustate->nz
+
+#define EAL cpustate->ea.b.l
+#define EAH cpustate->ea.b.h
+#define EAW cpustate->ea.w.l
+#define EAD cpustate->ea.d
+
+#define ZPL cpustate->zp.b.l
+#define ZPH cpustate->zp.b.h
+#define ZPW cpustate->zp.w.l
+#define ZPD cpustate->zp.d
+
+#define PCL cpustate->pc.b.l
+#define PCH cpustate->pc.b.h
+#define PCW cpustate->pc.w.l
+#define PCD cpustate->pc.d
+
+#define PPC cpustate->ppc.d
+
+#define RDMEM_ID(a) cpustate->rdmem_id(cpustate->space, a)
+#define WRMEM_ID(a,d) cpustate->wrmem_id(cpustate->space, a, d)
+
+#define IRQ_STATE cpustate->irq_state
+#define AFTER_CLI cpustate->after_cli
+
+/***************************************************************
+ * RDOP read an opcode
+ ***************************************************************/
+#define RDOP() cpustate->direct->read_decrypted_byte(PCW++); cpustate->icount -= 1
+
+/***************************************************************
+ * RDOPARG read an opcode argument
+ ***************************************************************/
+#define RDOPARG() cpustate->direct->read_raw_byte(PCW++); cpustate->icount -= 1
+
+#define PEEK_OP() cpustate->direct->read_decrypted_byte(PCW)
+
+#define RDMEM(addr) cpustate->space->read_byte(addr); cpustate->icount -= 1
+#define WRMEM(addr,data) cpustate->space->write_byte(addr,data); cpustate->icount -= 1
diff --git a/trunk/src/emu/cpu/m6502/ops02.h b/trunk/src/emu/cpu/m6502/ops02.h
new file mode 100644
index 00000000000..3b41514bc37
--- /dev/null
+++ b/trunk/src/emu/cpu/m6502/ops02.h
@@ -0,0 +1,808 @@
+/*****************************************************************************
+ *
+ * ops02.h
+ * Addressing mode and opcode macros for 6502,65c02,65sc02,6510,n2a03 CPUs
+ *
+ * Copyright Juergen Buchmueller, all rights reserved.
+ * 65sc02 core Copyright Peter Trauner, all rights reserved.
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * pullmoll@t-online.de
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ *****************************************************************************/
+
+
+/* 6502 flags */
+#define F_C 0x01
+#define F_Z 0x02
+#define F_I 0x04
+#define F_D 0x08
+#define F_B 0x10
+#define F_T 0x20
+#define F_V 0x40
+#define F_N 0x80
+
+/* some shortcuts for improved readability */
+#define A cpustate->a
+#define X cpustate->x
+#define Y cpustate->y
+#define P cpustate->p
+#define S cpustate->sp.b.l
+#define SPD cpustate->sp.d
+
+#define NZ cpustate->nz
+
+#define SET_NZ(n) \
+ if ((n) == 0) P = (P & ~F_N) | F_Z; else P = (P & ~(F_N | F_Z)) | ((n) & F_N)
+
+#define SET_Z(n) \
+ if ((n) == 0) P |= F_Z; else P &= ~F_Z
+
+#define EAL cpustate->ea.b.l
+#define EAH cpustate->ea.b.h
+#define EAW cpustate->ea.w.l
+#define EAD cpustate->ea.d
+
+#define ZPL cpustate->zp.b.l
+#define ZPH cpustate->zp.b.h
+#define ZPW cpustate->zp.w.l
+#define ZPD cpustate->zp.d
+
+#define PCL cpustate->pc.b.l
+#define PCH cpustate->pc.b.h
+#define PCW cpustate->pc.w.l
+#define PCD cpustate->pc.d
+
+#define PPC cpustate->ppc.d
+
+#define RDMEM_ID(a) cpustate->rdmem_id(cpustate->space,a)
+#define WRMEM_ID(a,d) cpustate->wrmem_id(cpustate->space,a,d)
+
+/***************************************************************
+ * RDOP read an opcode
+ ***************************************************************/
+#define RDOP() cpustate->direct->read_decrypted_byte(PCW++); cpustate->icount -= 1
+#define PEEKOP() cpustate->direct->read_decrypted_byte(PCW)
+
+/***************************************************************
+ * RDOPARG read an opcode argument
+ ***************************************************************/
+#define RDOPARG() cpustate->direct->read_raw_byte(PCW++); cpustate->icount -= 1
+
+/***************************************************************
+ * RDMEM read memory
+ ***************************************************************/
+#define RDMEM(addr) cpustate->space->read_byte(addr); cpustate->icount -= 1
+
+/***************************************************************
+ * WRMEM write memory
+ ***************************************************************/
+#define WRMEM(addr,data) cpustate->space->write_byte(addr,data); cpustate->icount -= 1
+
+/***************************************************************
+ * BRA branch relative
+ * extra cycle if page boundary is crossed
+ ***************************************************************/
+#define BRA(cond) \
+ { \
+ INT8 tmp2 = RDOPARG(); \
+ if (cond) \
+ { \
+ RDMEM(PCW); \
+ EAW = PCW + (signed char)tmp2; \
+ if ( EAH != PCH ) { \
+ RDMEM( (PCH << 8 ) | EAL) ; \
+ } \
+ PCD = EAD; \
+ } \
+ }
+
+/***************************************************************
+ *
+ * Helper macros to build the effective address
+ *
+ ***************************************************************/
+
+/***************************************************************
+ * EA = zero page address
+ ***************************************************************/
+#define EA_ZPG \
+ ZPL = RDOPARG(); \
+ EAD = ZPD
+
+/***************************************************************
+ * EA = zero page address + X
+ ***************************************************************/
+#define EA_ZPX \
+ ZPL = RDOPARG(); \
+ RDMEM(ZPD); \
+ ZPL = X + ZPL; \
+ EAD = ZPD
+
+/***************************************************************
+ * EA = zero page address + Y
+ ***************************************************************/
+#define EA_ZPY \
+ ZPL = RDOPARG(); \
+ RDMEM(ZPD); \
+ ZPL = Y + ZPL; \
+ EAD = ZPD
+
+/***************************************************************
+ * EA = absolute address
+ ***************************************************************/
+#define EA_ABS \
+ EAL = RDOPARG(); \
+ EAH = RDOPARG()
+
+/***************************************************************
+ * EA = absolute address + X
+ * one additional read if page boundary is crossed
+ ***************************************************************/
+#define EA_ABX_P \
+ EA_ABS; \
+ if ( EAL + X > 0xff ) { \
+ RDMEM( ( EAH << 8 ) | ( ( EAL + X ) & 0xff ) ); \
+ } \
+ EAW += X;
+
+/***************************************************************
+ * EA = absolute address + X
+ ***************************************************************/
+#define EA_ABX_NP \
+ EA_ABS; \
+ RDMEM( ( EAH << 8 ) | ( ( EAL + X ) & 0xff ) ); \
+ EAW += X
+
+/***************************************************************
+ * EA = absolute address + Y
+ * one additional read if page boundary is crossed
+ ***************************************************************/
+#define EA_ABY_P \
+ EA_ABS; \
+ if ( EAL + Y > 0xff ) { \
+ RDMEM( ( EAH << 8 ) | ( ( EAL + Y ) & 0xff ) ); \
+ } \
+ EAW += Y;
+
+/***************************************************************
+ * EA = absolute address + Y
+ ***************************************************************/
+#define EA_ABY_NP \
+ EA_ABS; \
+ RDMEM( ( EAH << 8 ) | ( ( EAL + Y ) & 0xff ) ); \
+ EAW += Y
+
+/***************************************************************
+ * EA = zero page + X indirect (pre indexed)
+ ***************************************************************/
+#define EA_IDX \
+ ZPL = RDOPARG(); \
+ RDMEM(ZPD); \
+ ZPL = ZPL + X; \
+ EAL = RDMEM(ZPD); \
+ ZPL++; \
+ EAH = RDMEM(ZPD)
+
+/***************************************************************
+ * EA = zero page indirect + Y (post indexed)
+ * subtract 1 cycle if page boundary is crossed
+ ***************************************************************/
+#define EA_IDY_P \
+ ZPL = RDOPARG(); \
+ EAL = RDMEM(ZPD); \
+ ZPL++; \
+ EAH = RDMEM(ZPD); \
+ if (EAL + Y > 0xff) { \
+ RDMEM( ( EAH << 8 ) | ( ( EAL + Y ) & 0xff ) ); \
+ } \
+ EAW += Y;
+
+/***************************************************************
+ * EA = zero page indirect + Y
+ ***************************************************************/
+#define EA_IDY_NP \
+ ZPL = RDOPARG(); \
+ EAL = RDMEM(ZPD); \
+ ZPL++; \
+ EAH = RDMEM(ZPD); \
+ RDMEM( ( EAH << 8 ) | ( ( EAL + Y ) & 0xff ) ); \
+ EAW += Y
+
+/***************************************************************
+ * EA = zero page indirect (65c02 pre indexed w/o X)
+ ***************************************************************/
+#define EA_ZPI \
+ ZPL = RDOPARG(); \
+ EAL = RDMEM(ZPD); \
+ ZPL++; \
+ EAH = RDMEM(ZPD)
+
+/***************************************************************
+ * EA = indirect (only used by JMP)
+ ***************************************************************/
+#define EA_IND \
+ EA_ABS; \
+ tmp = RDMEM(EAD); \
+ EAL++; /* booby trap: stay in same page! ;-) */ \
+ EAH = RDMEM(EAD); \
+ EAL = tmp
+
+
+/* read a value into tmp */
+/* Base number of cycles taken for each mode (including reading of opcode):
+ RD_IMM 2
+ RD_DUM 2
+ RD_ACC 0
+ RD_ZPG/WR_ZPG 3
+ RD_ZPX/WR_ZPX 4
+ RD_ZPY/WR_ZPY 4
+ RD_ABS/WR_ABS 4
+ RD_ABX_P 4/5
+ RD_ABX_NP/WR_ABX_NP 5
+ RD_ABY_P 4/5
+ RD_ABY_NP/WR_ABY_NP 5
+ RD_IDX/WR_IDX 6
+ RD_IDY_P 5/6
+ RD_IDY_NP/WR_IDY_NP 6
+ RD_ZPI/WR_ZPI 5
+ */
+#define RD_IMM tmp = RDOPARG()
+#define RD_IMM_DISCARD RDOPARG()
+#define RD_DUM RDMEM(PCW)
+#define RD_ACC tmp = A
+#define RD_ZPG EA_ZPG; tmp = RDMEM(EAD)
+#define RD_ZPG_DISCARD EA_ZPG; RDMEM(EAD)
+#define RD_ZPX EA_ZPX; tmp = RDMEM(EAD)
+#define RD_ZPX_DISCARD EA_ZPX; RDMEM(EAD)
+#define RD_ZPY EA_ZPY; tmp = RDMEM(EAD)
+#define RD_ABS EA_ABS; tmp = RDMEM(EAD)
+#define RD_ABS_DISCARD EA_ABS; RDMEM(EAD)
+#define RD_ABX_P EA_ABX_P; tmp = RDMEM(EAD)
+#define RD_ABX_P_DISCARD EA_ABX_P; RDMEM(EAD);
+#define RD_ABX_NP EA_ABX_NP; tmp = RDMEM(EAD)
+#define RD_ABY_P EA_ABY_P; tmp = RDMEM(EAD)
+#define RD_ABY_NP EA_ABY_NP; tmp = RDMEM(EAD)
+#define RD_IDX EA_IDX; tmp = RDMEM_ID(EAD); cpustate->icount -= 1
+#define RD_IDY_P EA_IDY_P; tmp = RDMEM_ID(EAD); cpustate->icount -= 1
+#define RD_IDY_NP EA_IDY_NP; tmp = RDMEM_ID(EAD); cpustate->icount -= 1
+#define RD_ZPI EA_ZPI; tmp = RDMEM(EAD)
+
+/* write a value from tmp */
+#define WR_ZPG EA_ZPG; WRMEM(EAD, tmp)
+#define WR_ZPX EA_ZPX; WRMEM(EAD, tmp)
+#define WR_ZPY EA_ZPY; WRMEM(EAD, tmp)
+#define WR_ABS EA_ABS; WRMEM(EAD, tmp)
+#define WR_ABX_NP EA_ABX_NP; WRMEM(EAD, tmp)
+#define WR_ABY_NP EA_ABY_NP; WRMEM(EAD, tmp)
+#define WR_IDX EA_IDX; WRMEM_ID(EAD, tmp); cpustate->icount -= 1
+#define WR_IDY_NP EA_IDY_NP; WRMEM_ID(EAD, tmp); cpustate->icount -= 1
+#define WR_ZPI EA_ZPI; WRMEM(EAD, tmp)
+
+/* dummy read from the last EA */
+#define RD_EA RDMEM(EAD)
+
+/* write back a value from tmp to the last EA */
+#define WB_ACC A = (UINT8)tmp;
+#define WB_EA WRMEM(EAD, tmp)
+
+/***************************************************************
+ ***************************************************************
+ * Macros to emulate the plain 6502 opcodes
+ ***************************************************************
+ ***************************************************************/
+
+/***************************************************************
+ * push a register onto the stack
+ ***************************************************************/
+#define PUSH(Rg) WRMEM(SPD, Rg); S--
+
+/***************************************************************
+ * pull a register from the stack
+ ***************************************************************/
+#define PULL(Rg) S++; Rg = RDMEM(SPD)
+
+/* 6502 ********************************************************
+ * ADC Add with carry
+ ***************************************************************/
+#define ADC \
+ if (P & F_D) { \
+ int c = (P & F_C); \
+ int lo = (A & 0x0f) + (tmp & 0x0f) + c; \
+ int hi = (A & 0xf0) + (tmp & 0xf0); \
+ P &= ~(F_V | F_C|F_N|F_Z); \
+ if (!((lo+hi)&0xff)) P|=F_Z; \
+ if (lo > 0x09) { \
+ hi += 0x10; \
+ lo += 0x06; \
+ } \
+ if (hi&0x80) P|=F_N; \
+ if (~(A^tmp) & (A^hi) & F_N) \
+ P |= F_V; \
+ if (hi > 0x90) \
+ hi += 0x60; \
+ if (hi & 0xff00) \
+ P |= F_C; \
+ A = (lo & 0x0f) + (hi & 0xf0); \
+ } else { \
+ int c = (P & F_C); \
+ int sum = A + tmp + c; \
+ P &= ~(F_V | F_C); \
+ if (~(A^tmp) & (A^sum) & F_N) \
+ P |= F_V; \
+ if (sum & 0xff00) \
+ P |= F_C; \
+ A = (UINT8) sum; \
+ SET_NZ(A); \
+ }
+
+/* 6502 ********************************************************
+ * AND Logical and
+ ***************************************************************/
+#define AND \
+ A = (UINT8)(A & tmp); \
+ SET_NZ(A)
+
+/* 6502 ********************************************************
+ * ASL Arithmetic shift left
+ ***************************************************************/
+#define ASL \
+ P = (P & ~F_C) | ((tmp >> 7) & F_C); \
+ tmp = (UINT8)(tmp << 1); \
+ SET_NZ(tmp)
+
+/* 6502 ********************************************************
+ * BCC Branch if carry clear
+ ***************************************************************/
+#define BCC BRA(!(P & F_C))
+
+/* 6502 ********************************************************
+ * BCS Branch if carry set
+ ***************************************************************/
+#define BCS BRA(P & F_C)
+
+/* 6502 ********************************************************
+ * BEQ Branch if equal
+ ***************************************************************/
+#define BEQ BRA(P & F_Z)
+
+/* 6502 ********************************************************
+ * BIT Bit test
+ ***************************************************************/
+#undef BIT
+#define BIT \
+ P &= ~(F_N|F_V|F_Z); \
+ P |= tmp & (F_N|F_V); \
+ if ((tmp & A) == 0) \
+ P |= F_Z
+
+/* 6502 ********************************************************
+ * BMI Branch if minus
+ ***************************************************************/
+#define BMI BRA(P & F_N)
+
+/* 6502 ********************************************************
+ * BNE Branch if not equal
+ ***************************************************************/
+#define BNE BRA(!(P & F_Z))
+
+/* 6502 ********************************************************
+ * BPL Branch if plus
+ ***************************************************************/
+#define BPL BRA(!(P & F_N))
+
+/* 6502 ********************************************************
+ * BRK Break
+ * increment PC, push PC hi, PC lo, flags (with B bit set),
+ * set I flag, jump via IRQ vector
+ ***************************************************************/
+#define BRK \
+ RDOPARG(); \
+ PUSH(PCH); \
+ PUSH(PCL); \
+ PUSH(P | F_B); \
+ P = (P | F_I); \
+ PCL = RDMEM(M6502_IRQ_VEC); \
+ PCH = RDMEM(M6502_IRQ_VEC+1)
+
+/* 6502 ********************************************************
+ * BVC Branch if overflow clear
+ ***************************************************************/
+#define BVC BRA(!(P & F_V))
+
+/* 6502 ********************************************************
+ * BVS Branch if overflow set
+ ***************************************************************/
+#define BVS BRA(P & F_V)
+
+/* 6502 ********************************************************
+ * CLC Clear carry flag
+ ***************************************************************/
+#define CLC \
+ P &= ~F_C
+
+/* 6502 ********************************************************
+ * CLD Clear decimal flag
+ ***************************************************************/
+#define CLD \
+ P &= ~F_D
+
+/* 6502 ********************************************************
+ * CLI Clear interrupt flag
+ ***************************************************************/
+#define CLI \
+ if ((cpustate->irq_state != CLEAR_LINE) && (P & F_I)) { \
+ /* kludge for now until IRQ rewrite: ignore if RTI follows */ \
+ if (PEEKOP() != 0x40) \
+ cpustate->after_cli = 1; \
+ } \
+ P &= ~F_I
+
+/* 6502 ********************************************************
+ * CLV Clear overflow flag
+ ***************************************************************/
+#define CLV \
+ P &= ~F_V
+
+/* 6502 ********************************************************
+ * CMP Compare accumulator
+ ***************************************************************/
+#define CMP \
+ P &= ~F_C; \
+ if (A >= tmp) \
+ P |= F_C; \
+ SET_NZ((UINT8)(A - tmp))
+
+/* 6502 ********************************************************
+ * CPX Compare index X
+ ***************************************************************/
+#define CPX \
+ P &= ~F_C; \
+ if (X >= tmp) \
+ P |= F_C; \
+ SET_NZ((UINT8)(X - tmp))
+
+/* 6502 ********************************************************
+ * CPY Compare index Y
+ ***************************************************************/
+#define CPY \
+ P &= ~F_C; \
+ if (Y >= tmp) \
+ P |= F_C; \
+ SET_NZ((UINT8)(Y - tmp))
+
+/* 6502 ********************************************************
+ * DEC Decrement memory
+ ***************************************************************/
+#define DEC \
+ tmp = (UINT8)(tmp-1); \
+ SET_NZ(tmp)
+
+/* 6502 ********************************************************
+ * DEX Decrement index X
+ ***************************************************************/
+#define DEX \
+ X = (UINT8)(X-1); \
+ SET_NZ(X)
+
+/* 6502 ********************************************************
+ * DEY Decrement index Y
+ ***************************************************************/
+#define DEY \
+ Y = (UINT8)(Y-1); \
+ SET_NZ(Y)
+
+/* 6502 ********************************************************
+ * EOR Logical exclusive or
+ ***************************************************************/
+#define EOR \
+ A = (UINT8)(A ^ tmp); \
+ SET_NZ(A)
+
+/* 6502 ********************************************************
+ * ILL Illegal opcode
+ ***************************************************************/
+#define ILL \
+ logerror("M6502 illegal opcode %04x: %02x\n",(PCW-1)&0xffff, cpustate->direct->read_decrypted_byte((PCW-1)&0xffff))
+
+/* 6502 ********************************************************
+ * INC Increment memory
+ ***************************************************************/
+#define INC \
+ tmp = (UINT8)(tmp+1); \
+ SET_NZ(tmp)
+
+/* 6502 ********************************************************
+ * INX Increment index X
+ ***************************************************************/
+#define INX \
+ X = (UINT8)(X+1); \
+ SET_NZ(X)
+
+/* 6502 ********************************************************
+ * INY Increment index Y
+ ***************************************************************/
+#define INY \
+ Y = (UINT8)(Y+1); \
+ SET_NZ(Y)
+
+/* 6502 ********************************************************
+ * JMP Jump to address
+ * set PC to the effective address
+ ***************************************************************/
+#define JMP \
+ if( EAD == PPC && !cpustate->pending_irq && !cpustate->after_cli ) \
+ if( cpustate->icount > 0 ) cpustate->icount = 0; \
+ PCD = EAD
+
+/* 6502 ********************************************************
+ * JSR Jump to subroutine
+ * decrement PC (sic!) push PC hi, push PC lo and set
+ * PC to the effective address
+ ***************************************************************/
+#define JSR \
+ EAL = RDOPARG(); \
+ RDMEM(SPD); \
+ PUSH(PCH); \
+ PUSH(PCL); \
+ EAH = RDOPARG(); \
+ PCD = EAD
+
+/* 6502 ********************************************************
+ * LDA Load accumulator
+ ***************************************************************/
+#define LDA \
+ A = (UINT8)tmp; \
+ SET_NZ(A)
+
+/* 6502 ********************************************************
+ * LDX Load index X
+ ***************************************************************/
+#define LDX \
+ X = (UINT8)tmp; \
+ SET_NZ(X)
+
+/* 6502 ********************************************************
+ * LDY Load index Y
+ ***************************************************************/
+#define LDY \
+ Y = (UINT8)tmp; \
+ SET_NZ(Y)
+
+/* 6502 ********************************************************
+ * LSR Logic shift right
+ * 0 -> [7][6][5][4][3][2][1][0] -> C
+ ***************************************************************/
+#define LSR \
+ P = (P & ~F_C) | (tmp & F_C); \
+ tmp = (UINT8)tmp >> 1; \
+ SET_NZ(tmp)
+
+/* 6502 ********************************************************
+ * NOP No operation
+ ***************************************************************/
+#define NOP
+
+/* 6502 ********************************************************
+ * ORA Logical inclusive or
+ ***************************************************************/
+#define ORA \
+ A = (UINT8)(A | tmp); \
+ SET_NZ(A)
+
+/* 6502 ********************************************************
+ * PHA Push accumulator
+ ***************************************************************/
+#define PHA \
+ PUSH(A)
+
+/* 6502 ********************************************************
+ * PHP Push processor status (flags)
+ ***************************************************************/
+#define PHP \
+ PUSH(P)
+
+/* 6502 ********************************************************
+ * PLA Pull accumulator
+ ***************************************************************/
+#define PLA \
+ RDMEM(SPD); \
+ PULL(A); \
+ SET_NZ(A)
+
+
+/* 6502 ********************************************************
+ * PLP Pull processor status (flags)
+ ***************************************************************/
+#define PLP \
+ RDMEM(SPD); \
+ if ( P & F_I ) { \
+ PULL(P); \
+ if ((cpustate->irq_state != CLEAR_LINE) && !(P & F_I)) { \
+ LOG(("M6502 '%s' PLP sets after_cli\n",cpustate->device->tag())); \
+ cpustate->after_cli = 1; \
+ } \
+ } else { \
+ PULL(P); \
+ } \
+ P |= (F_T|F_B);
+
+/* 6502 ********************************************************
+ * ROL Rotate left
+ * new C <- [7][6][5][4][3][2][1][0] <- C
+ ***************************************************************/
+#define ROL \
+ tmp = (tmp << 1) | (P & F_C); \
+ P = (P & ~F_C) | ((tmp >> 8) & F_C); \
+ tmp = (UINT8)tmp; \
+ SET_NZ(tmp)
+
+/* 6502 ********************************************************
+ * ROR Rotate right
+ * C -> [7][6][5][4][3][2][1][0] -> new C
+ ***************************************************************/
+#define ROR \
+ tmp |= (P & F_C) << 8; \
+ P = (P & ~F_C) | (tmp & F_C); \
+ tmp = (UINT8)(tmp >> 1); \
+ SET_NZ(tmp)
+
+/* 6502 ********************************************************
+ * RTI Return from interrupt
+ * pull flags, pull PC lo, pull PC hi and increment PC
+ * PCW++;
+ ***************************************************************/
+#define RTI \
+ RDOPARG(); \
+ RDMEM(SPD); \
+ PULL(P); \
+ PULL(PCL); \
+ PULL(PCH); \
+ P |= F_T | F_B; \
+ if( (cpustate->irq_state != CLEAR_LINE) && !(P & F_I) ) \
+ { \
+ LOG(("M6502 '%s' RTI sets after_cli\n",cpustate->device->tag())); \
+ cpustate->after_cli = 1; \
+ }
+
+/* 6502 ********************************************************
+ * RTS Return from subroutine
+ * pull PC lo, PC hi and increment PC
+ ***************************************************************/
+#define RTS \
+ RDOPARG(); \
+ RDMEM(SPD); \
+ PULL(PCL); \
+ PULL(PCH); \
+ RDMEM(PCW); PCW++
+
+/* 6502 ********************************************************
+ * SBC Subtract with carry
+ ***************************************************************/
+#define SBC \
+ if (P & F_D) \
+ { \
+ int c = (P & F_C) ^ F_C; \
+ int sum = A - tmp - c; \
+ int lo = (A & 0x0f) - (tmp & 0x0f) - c; \
+ int hi = (A & 0xf0) - (tmp & 0xf0); \
+ if (lo & 0x10) \
+ { \
+ lo -= 6; \
+ hi--; \
+ } \
+ P &= ~(F_V | F_C|F_Z|F_N); \
+ if( (A^tmp) & (A^sum) & F_N ) \
+ P |= F_V; \
+ if( hi & 0x0100 ) \
+ hi -= 0x60; \
+ if( (sum & 0xff00) == 0 ) \
+ P |= F_C; \
+ if( !((A-tmp-c) & 0xff) ) \
+ P |= F_Z; \
+ if( (A-tmp-c) & 0x80 ) \
+ P |= F_N; \
+ A = (lo & 0x0f) | (hi & 0xf0); \
+ } \
+ else \
+ { \
+ int c = (P & F_C) ^ F_C; \
+ int sum = A - tmp - c; \
+ P &= ~(F_V | F_C); \
+ if( (A^tmp) & (A^sum) & F_N ) \
+ P |= F_V; \
+ if( (sum & 0xff00) == 0 ) \
+ P |= F_C; \
+ A = (UINT8) sum; \
+ SET_NZ(A); \
+ }
+
+/* 6502 ********************************************************
+ * SEC Set carry flag
+ ***************************************************************/
+#if defined(SEC)
+#undef SEC
+#endif
+#define SEC \
+ P |= F_C
+
+/* 6502 ********************************************************
+ * SED Set decimal flag
+ ***************************************************************/
+#define SED \
+ P |= F_D
+
+/* 6502 ********************************************************
+ * SEI Set interrupt flag
+ ***************************************************************/
+#define SEI \
+ P |= F_I
+
+/* 6502 ********************************************************
+ * STA Store accumulator
+ ***************************************************************/
+#define STA \
+ tmp = A
+
+/* 6502 ********************************************************
+ * STX Store index X
+ ***************************************************************/
+#define STX \
+ tmp = X
+
+/* 6502 ********************************************************
+ * STY Store index Y
+ ***************************************************************/
+#define STY \
+ tmp = Y
+
+/* 6502 ********************************************************
+ * TAX Transfer accumulator to index X
+ ***************************************************************/
+#define TAX \
+ X = A; \
+ SET_NZ(X)
+
+/* 6502 ********************************************************
+ * TAY Transfer accumulator to index Y
+ ***************************************************************/
+#define TAY \
+ Y = A; \
+ SET_NZ(Y)
+
+/* 6502 ********************************************************
+ * TSX Transfer stack LSB to index X
+ ***************************************************************/
+#define TSX \
+ X = S; \
+ SET_NZ(X)
+
+/* 6502 ********************************************************
+ * TXA Transfer index X to accumulator
+ ***************************************************************/
+#define TXA \
+ A = X; \
+ SET_NZ(A)
+
+/* 6502 ********************************************************
+ * TXS Transfer index X to stack LSB
+ * no flags changed (sic!)
+ ***************************************************************/
+#define TXS \
+ S = X
+
+/* 6502 ********************************************************
+ * TYA Transfer index Y to accumulator
+ ***************************************************************/
+#define TYA \
+ A = Y; \
+ SET_NZ(A)
diff --git a/trunk/src/emu/cpu/m6502/ops09.h b/trunk/src/emu/cpu/m6502/ops09.h
new file mode 100644
index 00000000000..16d375f435a
--- /dev/null
+++ b/trunk/src/emu/cpu/m6502/ops09.h
@@ -0,0 +1,206 @@
+/*****************************************************************************
+ *
+ * ops09.h
+ *
+ * Copyright Peter Trauner, all rights reserved.
+ * documentation by michael steil mist@c64.org
+ * available at ftp://ftp.funet.fi/pub/cbm/c65
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * pullmoll@t-online.de
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ *****************************************************************************/
+
+#define ZPWH cpustate->zp.w.h
+
+#define EAWH cpustate->ea.w.h
+
+#define PBWH cpustate->pc_bank.w.h
+#define PB cpustate->pc_bank.d
+
+#define IBWH cpustate->ind_bank.w.h
+#define IB cpustate->ind_bank.d
+
+/***************************************************************
+ * RDOP read an opcode
+ ***************************************************************/
+#undef RDOP
+#define RDOP() cpustate->direct->read_decrypted_byte((PCW++)|PB); cpustate->icount -= 1
+
+/***************************************************************
+ * RDOPARG read an opcode argument
+ ***************************************************************/
+#undef RDOPARG
+#define RDOPARG() cpustate->direct->read_raw_byte((PCW++)|PB); cpustate->icount -= 1
+
+/***************************************************************
+ * RDMEM read memory
+ ***************************************************************/
+#undef RDMEM
+#define RDMEM(addr) cpustate->space->read_byte(addr); cpustate->icount -= 1
+
+/***************************************************************
+ * WRMEM write memory
+ ***************************************************************/
+#undef WRMEM
+#define WRMEM(addr,data) cpustate->space->write_byte(addr,data); cpustate->icount -= 1
+
+/***************************************************************
+ * push a register onto the stack
+ ***************************************************************/
+#undef PUSH
+#define PUSH(Rg) WRMEM(SPD|PB, Rg); S--
+
+/***************************************************************
+ * pull a register from the stack
+ ***************************************************************/
+#undef PULL
+#define PULL(Rg) S++; Rg = RDMEM(SPD|PB)
+
+
+/***************************************************************
+ * EA = zero page address
+ ***************************************************************/
+#undef EA_ZPG
+#define EA_ZPG \
+ ZPL = RDOPARG(); \
+ ZPWH = PBWH; \
+ EAD = ZPD
+
+/***************************************************************
+ * EA = zero page address + X
+ ***************************************************************/
+#undef EA_ZPX
+#define EA_ZPX \
+ ZPL = X + RDOPARG(); \
+ ZPWH = PBWH; \
+ EAD = ZPD
+
+/***************************************************************
+ * EA = zero page address + Y
+ ***************************************************************/
+#undef EA_ZPY
+#define EA_ZPY \
+ ZPL = Y + RDOPARG(); \
+ ZPWH = PBWH; \
+ EAD = ZPD
+
+/***************************************************************
+ * EA = absolute address
+ ***************************************************************/
+#undef EA_ABS
+#define EA_ABS \
+ EAL = RDOPARG(); \
+ EAH = RDOPARG(); \
+ EAWH = PBWH
+
+/***************************************************************
+ * EA = zero page + X indirect (pre indexed)
+ ***************************************************************/
+#undef EA_IDX
+#define EA_IDX \
+ ZPL = X + RDOPARG(); \
+ ZPWH=PBWH; \
+ EAL = RDMEM(ZPD); \
+ ZPL++; \
+ EAH = RDMEM(ZPD); \
+ EAWH = PBWH
+
+/***************************************************************
+ * EA = zero page indirect + Y (post indexed)
+ * subtract 1 cycle if page boundary is crossed
+ ***************************************************************/
+#undef EA_IDY
+#define EA_IDY \
+ ZPL = RDOPARG(); \
+ ZPWH = PBWH; \
+ EAL = RDMEM(ZPD); \
+ ZPL++; \
+ EAH = RDMEM(ZPD); \
+ EAWH = PBWH; \
+ if (EAL + Y > 0xff) \
+ cpustate->icount--; \
+ EAW += Y
+
+
+/***************************************************************
+ * EA = zero page indirect + Y (post indexed)
+ * subtract 1 cycle if page boundary is crossed
+ ***************************************************************/
+#define EA_IDY_6509 \
+ ZPL = RDOPARG(); \
+ ZPWH = PBWH; \
+ EAL = RDMEM(ZPD); \
+ ZPL++; \
+ EAH = RDMEM(ZPD); \
+ EAWH = IBWH; \
+ if (EAL + Y > 0xff) \
+ cpustate->icount--; \
+ EAW += Y
+
+/***************************************************************
+ * EA = indirect (only used by JMP)
+ ***************************************************************/
+#undef EA_IND
+#define EA_IND \
+ EA_ABS; \
+ tmp = RDMEM(EAD); \
+ EAL++; /* booby trap: stay in same page! ;-) */ \
+ EAH = RDMEM(EAD); \
+ EAL = tmp;
+/* EAWH = PBWH */
+
+#define RD_IDY_6509 EA_IDY_6509; tmp = RDMEM(EAD)
+#define WR_IDY_6509 EA_IDY_6509; WRMEM(EAD, tmp)
+
+/***************************************************************
+ * BRA branch relative
+ * extra cycle if page boundary is crossed
+ ***************************************************************/
+#undef BRA
+#define BRA(cond) \
+ if (cond) \
+ { \
+ tmp = RDOPARG(); \
+ EAW = PCW + (signed char)tmp; \
+ cpustate->icount -= (PCH == EAH) ? 1 : 2; \
+ PCD = EAD|PB; \
+ } \
+ else \
+ { \
+ PCW++; \
+ cpustate->icount -= 1; \
+ }
+
+/* 6502 ********************************************************
+ * JSR Jump to subroutine
+ * decrement PC (sic!) push PC hi, push PC lo and set
+ * PC to the effective address
+ ***************************************************************/
+#undef JSR
+#define JSR \
+ EAL = RDOPARG(); \
+ PUSH(PCH); \
+ PUSH(PCL); \
+ EAH = RDOPARG(); \
+ EAWH = PBWH; \
+ PCD = EAD
+
+/* 6510 ********************************************************
+ * KIL Illegal opcode
+ * processor haltet, no hardware interrupt will help
+ * only reset
+ ***************************************************************/
+#undef KIL
+#define KIL \
+ PCW--; \
+ logerror("M6509 KILL opcode %05x: %02x\n", PCD, cpustate->direct->read_decrypted_byte(PCD))
diff --git a/trunk/src/emu/cpu/m6502/ops4510.h b/trunk/src/emu/cpu/m6502/ops4510.h
new file mode 100644
index 00000000000..a8ebd215a7c
--- /dev/null
+++ b/trunk/src/emu/cpu/m6502/ops4510.h
@@ -0,0 +1,61 @@
+/*****************************************************************************
+ *
+ * ops4510.h
+ * Addressing mode and opcode macros for 4510 CPU
+ *
+ * Copyright Peter Trauner, all rights reserved.
+ * documentation preliminary databook
+ * documentation by michael steil mist@c64.org
+ * available at ftp://ftp.funet.fi/pub/cbm/c65
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * pullmoll@t-online.de
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ *****************************************************************************/
+
+
+/* 65ce02 ********************************************************
+ * TXS Transfer index X to stack LSB
+ * no flags changed (sic!)
+ * txs tys not interruptable
+ ***************************************************************/
+#undef TXS
+#define TXS \
+ SPL = X; \
+ if (PEEK_OP() == 0x2b /*TYS*/ ) { \
+ UINT8 op = RDOP(); \
+ (*cpustate->insn[op])(cpustate); \
+ }
+
+#undef NOP
+#define NOP \
+ cpustate->interrupt_inhibit = 0;
+
+/* c65 docu says transfer of axyz to the mapper register
+ so no readback!? */
+#define MAP \
+ cpustate->interrupt_inhibit = 1; \
+ cpustate->low=cpustate->a|(cpustate->x<<8); \
+ cpustate->high=cpustate->y|(cpustate->z<<8); \
+ cpustate->mem[0]=(cpustate->low&0x1000) ? (cpustate->low&0xfff)<<8:0; \
+ cpustate->mem[1]=(cpustate->low&0x2000) ? (cpustate->low&0xfff)<<8:0; \
+ cpustate->mem[2]=(cpustate->low&0x4000) ? (cpustate->low&0xfff)<<8:0; \
+ cpustate->mem[3]=(cpustate->low&0x8000) ? (cpustate->low&0xfff)<<8:0; \
+ cpustate->mem[4]=(cpustate->high&0x1000) ? (cpustate->high&0xfff)<<8:0; \
+ cpustate->mem[5]=(cpustate->high&0x2000) ? (cpustate->high&0xfff)<<8:0; \
+ cpustate->mem[6]=(cpustate->high&0x4000) ? (cpustate->high&0xfff)<<8:0; \
+ cpustate->mem[7]=(cpustate->high&0x8000) ? (cpustate->high&0xfff)<<8:0; \
+ cpustate->icount -= 3; \
+ { \
+ UINT8 op = RDOP(); \
+ (*cpustate->insn[op])(cpustate); \
+ }
diff --git a/trunk/src/emu/cpu/m6502/opsc02.h b/trunk/src/emu/cpu/m6502/opsc02.h
new file mode 100644
index 00000000000..affd6dfd72a
--- /dev/null
+++ b/trunk/src/emu/cpu/m6502/opsc02.h
@@ -0,0 +1,359 @@
+/*****************************************************************************
+ *
+ * m6502ops.h
+ * Addressing mode and opcode macros for 6502,65c02,65sc02,6510,n2a03 CPUs
+ *
+ * Copyright Juergen Buchmueller, all rights reserved.
+ * 65sc02 core Copyright Peter Trauner, all rights reserved.
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * pullmoll@t-online.de
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ *****************************************************************************/
+
+
+/***************************************************************
+ ***************************************************************
+ * Macros to emulate the 65C02 opcodes
+ ***************************************************************
+ ***************************************************************/
+
+/* 65C02 *******************************************************
+ * EA = absolute address + X
+ * one additional read if page boundary is crossed
+ ***************************************************************/
+#define EA_ABX_C02_P \
+ EA_ABS; \
+ if ( EAL + X > 0xff ) { \
+ RDMEM( PCW - 1 ); \
+ } \
+ EAW += X;
+
+/* 65C02 *******************************************************
+ * EA = absolute address + X
+ ***************************************************************/
+#define EA_ABX_C02_NP \
+ EA_ABS; \
+ RDMEM( PCW - 1 ); \
+ EAW += X;
+
+/***************************************************************
+ * EA = absolute address + Y
+ * one additional read if page boundary is crossed
+ ***************************************************************/
+#define EA_ABY_C02_P \
+ EA_ABS; \
+ if ( EAL + Y > 0xff ) { \
+ RDMEM( PCW - 1 ); \
+ } \
+ EAW += Y;
+
+/* 65C02 *******************************************************
+ * EA = absolute address + Y
+ ***************************************************************/
+#define EA_ABY_C02_NP \
+ EA_ABS; \
+ RDMEM( PCW - 1 ); \
+ EAW += Y
+
+/* 65C02 *******************************************************
+ * EA = zero page indirect + Y (post indexed)
+ * subtract 1 cycle if page boundary is crossed
+ ***************************************************************/
+#define EA_IDY_C02_P \
+ ZPL = RDOPARG(); \
+ EAL = RDMEM(ZPD); \
+ ZPL++; \
+ EAH = RDMEM(ZPD); \
+ if (EAL + Y > 0xff) { \
+ RDMEM( PCW - 1 ); \
+ } \
+ EAW += Y;
+
+/* 65C02 *******************************************************
+ * EA = zero page indirect + Y
+ ***************************************************************/
+#define EA_IDY_C02_NP \
+ ZPL = RDOPARG(); \
+ EAL = RDMEM(ZPD); \
+ ZPL++; \
+ EAH = RDMEM(ZPD); \
+ RDMEM( PCW - 1 ); \
+ EAW += Y
+
+/* 65C02 *******************************************************
+ * EA = indirect (only used by JMP)
+ * correct overflow handling
+ ***************************************************************/
+#define EA_IND_C02 \
+ EA_ABS; \
+ tmp = RDMEM(EAD); \
+ RDMEM(PCW-1); \
+ EAD++; \
+ EAH = RDMEM(EAD); \
+ EAL = tmp
+
+/* 65C02 *******************************************************
+ * EA = indirect plus x (only used by 65c02 JMP)
+ ***************************************************************/
+#define EA_IAX \
+ EA_ABS; \
+ RDMEM( PCW - 1 ); \
+ if (EAL + X > 0xff) { \
+ RDMEM( PCW - 1 ); \
+ } \
+ EAW += X; \
+ tmp = RDMEM(EAD); \
+ EAD++; \
+ EAH = RDMEM(EAD); \
+ EAL = tmp
+
+/* read a value into tmp */
+/* Base number of cycles taken for each mode (including reading of opcode):
+ RD_ABX_C02_P 4/5
+ RD_ABX_C02_NP/WR_ABX_C02_NP 5
+ RD_ABY_C02_P 4/5
+ RD_IDY_C02_P 5/6
+ WR_IDY_C02_NP 6
+ */
+#define RD_ABX_C02_P EA_ABX_C02_P; tmp = RDMEM(EAD)
+#define RD_ABX_C02_NP EA_ABX_C02_NP; tmp = RDMEM(EAD)
+#define RD_ABX_C02_NP_DISCARD EA_ABX_C02_NP; RDMEM(EAD)
+#define RD_ABY_C02_P EA_ABY_C02_P; tmp = RDMEM(EAD)
+#define RD_IDY_C02_P EA_IDY_C02_P; tmp = RDMEM_ID(EAD); cpustate->icount -= 1
+
+#define WR_ABX_C02_NP EA_ABX_C02_NP; WRMEM(EAD, tmp)
+#define WR_ABY_C02_NP EA_ABY_C02_NP; WRMEM(EAD, tmp)
+#define WR_IDY_C02_NP EA_IDY_C02_NP; WRMEM_ID(EAD, tmp); cpustate->icount -= 1
+
+
+/* 65C02********************************************************
+ * BRA branch relative
+ * extra cycle if page boundary is crossed
+ ***************************************************************/
+#define BRA_C02(cond) \
+ tmp = RDOPARG(); \
+ if (cond) \
+ { \
+ RDMEM(PCW); \
+ EAW = PCW + (signed char)tmp; \
+ if ( EAH != PCH ) { \
+ RDMEM( PCW - 1 ); \
+ } \
+ PCD = EAD; \
+ }
+
+/* 65C02 ********************************************************
+ * ADC Add with carry
+ * different setting of flags in decimal mode
+ ***************************************************************/
+#define ADC_C02 \
+ if (P & F_D) \
+ { \
+ int c = (P & F_C); \
+ int lo = (A & 0x0f) + (tmp & 0x0f) + c; \
+ int hi = (A & 0xf0) + (tmp & 0xf0); \
+ P &= ~(F_V | F_C); \
+ if( lo > 0x09 ) \
+ { \
+ hi += 0x10; \
+ lo += 0x06; \
+ } \
+ if( ~(A^tmp) & (A^hi) & F_N ) \
+ P |= F_V; \
+ if( hi > 0x90 ) \
+ hi += 0x60; \
+ if( hi & 0xff00 ) \
+ P |= F_C; \
+ A = (lo & 0x0f) + (hi & 0xf0); \
+ RDMEM( PCW - 1 ); \
+ } \
+ else \
+ { \
+ int c = (P & F_C); \
+ int sum = A + tmp + c; \
+ P &= ~(F_V | F_C); \
+ if( ~(A^tmp) & (A^sum) & F_N ) \
+ P |= F_V; \
+ if( sum & 0xff00 ) \
+ P |= F_C; \
+ A = (UINT8) sum; \
+ } \
+ SET_NZ(A)
+
+/* 65C02 ********************************************************
+ * SBC Subtract with carry
+ * different setting of flags in decimal mode
+ ***************************************************************/
+#define SBC_C02 \
+ if (P & F_D) \
+ { \
+ int c = (P & F_C) ^ F_C; \
+ int sum = A - tmp - c; \
+ int lo = (A & 0x0f) - (tmp & 0x0f) - c; \
+ int hi = (A & 0xf0) - (tmp & 0xf0); \
+ P &= ~(F_V | F_C); \
+ if( (A^tmp) & (A^sum) & F_N ) \
+ P |= F_V; \
+ if( lo & 0xf0 ) \
+ lo -= 6; \
+ if( lo & 0x80 ) \
+ hi -= 0x10; \
+ if( hi & 0x0f00 ) \
+ hi -= 0x60; \
+ if( (sum & 0xff00) == 0 ) \
+ P |= F_C; \
+ A = (lo & 0x0f) + (hi & 0xf0); \
+ RDMEM( PCW - 1 ); \
+ } \
+ else \
+ { \
+ int c = (P & F_C) ^ F_C; \
+ int sum = A - tmp - c; \
+ P &= ~(F_V | F_C); \
+ if( (A^tmp) & (A^sum) & F_N ) \
+ P |= F_V; \
+ if( (sum & 0xff00) == 0 ) \
+ P |= F_C; \
+ A = (UINT8) sum; \
+ } \
+ SET_NZ(A)
+
+/* 65C02 *******************************************************
+ * BBR Branch if bit is reset
+ ***************************************************************/
+#define BBR(bit) \
+ BRA(!(tmp & (1<<bit)))
+
+/* 65C02 *******************************************************
+ * BBS Branch if bit is set
+ ***************************************************************/
+#define BBS(bit) \
+ BRA(tmp & (1<<bit))
+
+/* 65c02 ********************************************************
+ * BRK Break
+ * increment PC, push PC hi, PC lo, flags (with B bit set),
+ * set I flag, reset D flag and jump via IRQ vector
+ ***************************************************************/
+#define BRK_C02 \
+ RDOPARG(); \
+ PUSH(PCH); \
+ PUSH(PCL); \
+ PUSH(P | F_B); \
+ P = (P | F_I) & ~F_D; \
+ PCL = RDMEM(M6502_IRQ_VEC); \
+ PCH = RDMEM(M6502_IRQ_VEC+1);
+
+
+/* 65C02 *******************************************************
+ * DEA Decrement accumulator
+ ***************************************************************/
+#define DEA \
+ A = (UINT8)(A - 1); \
+ SET_NZ(A)
+
+/* 65C02 *******************************************************
+ * INA Increment accumulator
+ ***************************************************************/
+#define INA \
+ A = (UINT8)(A + 1); \
+ SET_NZ(A)
+
+/* 65C02 *******************************************************
+ * PHX Push index X
+ ***************************************************************/
+#define PHX \
+ PUSH(X)
+
+/* 65C02 *******************************************************
+ * PHY Push index Y
+ ***************************************************************/
+#define PHY \
+ PUSH(Y)
+
+/* 65C02 *******************************************************
+ * PLX Pull index X
+ ***************************************************************/
+#define PLX \
+ RDMEM(SPD); \
+ PULL(X); \
+ SET_NZ(X)
+
+/* 65C02 *******************************************************
+ * PLY Pull index Y
+ ***************************************************************/
+#define PLY \
+ RDMEM(SPD); \
+ PULL(Y); \
+ SET_NZ(Y)
+
+/* 65C02 *******************************************************
+ * RMB Reset memory bit
+ ***************************************************************/
+#define RMB(bit) \
+ tmp &= ~(1<<bit)
+
+/* 65C02 *******************************************************
+ * SMB Set memory bit
+ ***************************************************************/
+#define SMB(bit) \
+ tmp |= (1<<bit)
+
+/* 65C02 *******************************************************
+ * STZ Store zero
+ ***************************************************************/
+#define STZ \
+ tmp = 0
+
+/* 65C02 *******************************************************
+ * TRB Test and reset bits
+ ***************************************************************/
+#define TRB \
+ SET_Z(tmp&A); \
+ tmp &= ~A
+
+/* 65C02 *******************************************************
+ * TSB Test and set bits
+ ***************************************************************/
+#define TSB \
+ SET_Z(tmp&A); \
+ tmp |= A
+
+/* 6502 ********************************************************
+ * BIT Bit test Immediate, only Z affected
+ ***************************************************************/
+#undef BIT_IMM_C02
+#define BIT_IMM_C02 \
+ P &= ~(F_Z); \
+ if ((tmp & A) == 0) \
+ P |= F_Z
+
+
+/***************************************************************
+ ***************************************************************
+ * Macros to emulate the 65sc02 opcodes
+ ***************************************************************
+ ***************************************************************/
+
+
+/* 65sc02 ********************************************************
+ * BSR Branch to subroutine
+ ***************************************************************/
+#define BSR \
+ EAL = RDOPARG(); \
+ RDMEM(SPD); \
+ PUSH(PCH); \
+ PUSH(PCL); \
+ EAH = RDOPARG(); \
+ EAW = PCW + (INT16)(EAW-1); \
+ PCD = EAD;
diff --git a/trunk/src/emu/cpu/m6502/opsce02.h b/trunk/src/emu/cpu/m6502/opsce02.h
new file mode 100644
index 00000000000..64549135932
--- /dev/null
+++ b/trunk/src/emu/cpu/m6502/opsce02.h
@@ -0,0 +1,989 @@
+/*****************************************************************************
+ *
+ * opsce02.h
+ * Addressing mode and opcode macros for 65ce02 CPU
+ *
+ * Copyright Peter Trauner, all rights reserved.
+ * documentation preliminary databook
+ * documentation by michael steil mist@c64.org
+ * available at ftp://ftp.funet.fi/pub/cbm/c65
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * pullmoll@t-online.de
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ *****************************************************************************/
+
+
+#define SET_NZ(n) if ((n) == 0) P = (P & ~F_N) | F_Z; else P = (P & ~(F_N | F_Z)) | ((n) & F_N)
+#define SET_Z(n) if ((n) == 0) P |= F_Z; else P &= ~F_Z
+
+#define RDMEM_WORD(addr, pair) pair.b.l=RDMEM( addr ); pair.b.h=RDMEM( (addr+1) & 0xffff )
+#define WRMEM_WORD(addr,pair) WRMEM(addr,pair.b.l); WRMEM((addr+1)&0xffff,pair.b.h)
+
+#define SET_NZ_WORD(n) \
+ if( n.w.l == 0 ) \
+ P = (P & ~F_N) | F_Z; \
+ else \
+ P = (P & ~(F_N | F_Z)) | ((n.b.h) & F_N)
+
+/***************************************************************
+ * EA = absolute address
+ ***************************************************************/
+#define EA_ABS \
+ EAL = RDOPARG(); \
+ EAH = RDOPARG()
+
+/***************************************************************
+ * EA = absolute address + X
+ ***************************************************************/
+#define EA_ABX \
+ EA_ABS; \
+ EAW += X
+
+/***************************************************************
+ * EA = absolute address + Y
+ * one additional read if page boundary is crossed
+ ***************************************************************/
+#define EA_ABY \
+ EA_ABS; \
+ EAW += Y;
+
+/***************************************************************
+ * EA = zero page address
+ ***************************************************************/
+#define EA_ZPG \
+ ZPL = RDOPARG(); \
+ EAD = ZPD
+
+/***************************************************************
+ * EA = zero page address + X
+ ***************************************************************/
+#define EA_ZPX \
+ ZPL = RDOPARG(); \
+ ZPL = X + ZPL; \
+ EAD = ZPD
+
+/***************************************************************
+ * EA = zero page address + Y
+ ***************************************************************/
+#define EA_ZPY \
+ ZPL = RDOPARG(); \
+ ZPL = Y + ZPL; \
+ EAD = ZPD
+
+/***************************************************************
+ * EA = zero page + X indirect (pre indexed)
+ ***************************************************************/
+#define EA_IDX \
+ ZPL = RDOPARG(); \
+ ZPL = ZPL + X; \
+ EAL = RDMEM(ZPD); \
+ ZPL++; \
+ EAH = RDMEM(ZPD)
+
+/***************************************************************
+ * EA = zero page indirect + Y (post indexed)
+ ***************************************************************/
+#define EA_IDY \
+ ZPL = RDOPARG(); \
+ EAL = RDMEM(ZPD); \
+ ZPL++; \
+ EAH = RDMEM(ZPD); \
+ EAW += Y
+
+/***************************************************************
+ * EA = zero page indirect + Z (post indexed)
+ * ???? subtract 1 cycle if page boundary is crossed
+ ***************************************************************/
+#define EA_IDZ \
+ ZPL = RDOPARG(); \
+ EAL = RDMEM(ZPD); \
+ ZPL++; \
+ EAH = RDMEM(ZPD); \
+ EAW += Z
+
+/***************************************************************
+ * EA = zero page indexed stack, indirect + Y (post indexed)
+ ***************************************************************/
+#define EA_INSY \
+ { \
+ PAIR pair={{0}}; \
+ pair.b.l = SPL+RDOPARG(); \
+ pair.b.h = SPH; \
+ EAL = RDMEM(pair.d); \
+ if( P & F_E ) \
+ pair.b.l++; \
+ else \
+ pair.w.l++; \
+ EAH = RDMEM(pair.d); \
+ /* RDMEM(PCW-1); */ \
+ EAW += Y; \
+ }
+
+/***************************************************************
+ * EA = indirect (only used by JMP)
+ ***************************************************************/
+#define EA_IND \
+ EA_ABS; \
+ tmp = RDMEM(EAD); \
+ EAL++; \
+ EAH = RDMEM(EAD); \
+ EAL = tmp
+
+/* 65ce02 ******************************************************
+ * EA = indirect plus x (only used by 65c02 JMP)
+ ***************************************************************/
+#define EA_IAX \
+ EA_ABS; \
+ EAW += X; \
+ tmp = RDMEM(EAD); \
+ EAL++; \
+ EAH = RDMEM(EAD); \
+ EAL = tmp
+
+/* read a value into tmp */
+/* Base number of cycles taken for each mode (including reading of opcode):
+ RD_ACC/WR_ACC 0
+ RD_IMM 2
+ RD_DUM 2
+ RD_ABS/WR_ABS 4
+ RD_ABS_WORD/WR_ABS_WORD 5
+ RD_ABX/WR_ABX 4
+ RD_ABY/WR_ABY 4
+ RD_IDX/WR_IDX 5
+ RD_IDY/WR_IDY 5
+ RD_IDZ 5
+ RD_INSY/WR_INSY 6
+ RD_ZPG/WR_ZPG 3
+ RD_ZPG_WORD 4
+ RD_ZPX/WR_ZPX 3
+ RD_ZPY/WR_ZPY 3
+ */
+#define RD_ACC tmp = A
+#define RD_IMM tmp = RDOPARG()
+#define RD_IMM_WORD tmp.b.l = RDOPARG(); tmp.b.h=RDOPARG()
+#define RD_DUM RDMEM(PCW-1)
+#define RD_ABS EA_ABS; tmp = RDMEM(EAD)
+#define RD_ABS_WORD EA_ABS; RDMEM_WORD(EAD, tmp)
+#define RD_ABX EA_ABX; tmp = RDMEM(EAD)
+#define RD_ABY EA_ABY; tmp = RDMEM(EAD)
+#define RD_IDX EA_IDX; tmp = RDMEM(EAD)
+#define RD_IDY EA_IDY; tmp = RDMEM(EAD)
+#define RD_IDZ EA_IDZ; tmp = RDMEM(EAD)
+#define RD_IDZ_DISCARD EA_IDZ; RDMEM(EAD)
+#define RD_INSY EA_INSY; tmp = RDMEM(EAD)
+#define RD_INSY_DISCARD EA_INSY; RDMEM(EAD)
+#define RD_ZPG EA_ZPG; tmp = RDMEM(EAD)
+#define RD_ZPG_WORD EA_ZPG; RDMEM_WORD(EAD, tmp)
+#define RD_ZPX EA_ZPX; tmp = RDMEM(EAD)
+#define RD_ZPY EA_ZPY; tmp = RDMEM(EAD)
+
+/* write a value from tmp */
+#define WR_ACC A = (UINT8)tmp
+#define WR_ABS EA_ABS; WRMEM(EAD, tmp)
+#define WR_ABS_WORD EA_ABS; WRMEM_WORD(EAD, tmp)
+#define WR_ABX EA_ABX; WRMEM(EAD, tmp)
+#define WR_ABY EA_ABY; WRMEM(EAD, tmp)
+#define WR_IDX EA_IDX; WRMEM(EAD, tmp)
+#define WR_IDY EA_IDY; WRMEM(EAD, tmp)
+#define WR_INSY EA_INSY; WRMEM(EAD, tmp)
+#define WR_ZPG EA_ZPG; WRMEM(EAD, tmp)
+#define WR_ZPX EA_ZPX; WRMEM(EAD, tmp)
+#define WR_ZPY EA_ZPY; WRMEM(EAD, tmp)
+
+#define WB_EA WRMEM(EAD, tmp)
+#define WB_EA_WORD WRMEM_WORD(EAD, tmp)
+
+/***************************************************************
+ * push a register onto the stack
+ ***************************************************************/
+#define PUSH(Rg) WRMEM(SPD, Rg); if (P&F_E) { SPL--; } else { SW--; }
+
+/***************************************************************
+ * pull a register from the stack
+ ***************************************************************/
+#define PULL(Rg) if (P&F_E) { SPL++; } else { SW++; } Rg = RDMEM(SPD)
+
+/* the order in which the args are pushed is correct! */
+#define PUSH_WORD(pair) PUSH(pair.b.l);PUSH(pair.b.h)
+
+/* 65ce02 *******************************************************
+ * ADC Add with carry
+ * correct setting of flags in decimal mode
+ ***************************************************************/
+#define ADC \
+ if (P & F_D) { \
+ int c = (P & F_C); \
+ int lo = (A & 0x0f) + (tmp & 0x0f) + c; \
+ int hi = (A & 0xf0) + (tmp & 0xf0); \
+ P &= ~(F_V | F_C); \
+ if( lo > 0x09 ) { \
+ hi += 0x10; \
+ lo += 0x06; \
+ } \
+ if( ~(A^tmp) & (A^hi) & F_N ) \
+ P |= F_V; \
+ if( hi > 0x90 ) \
+ hi += 0x60; \
+ if( hi & 0xff00 ) \
+ P |= F_C; \
+ A = (lo & 0x0f) + (hi & 0xf0); \
+ } else { \
+ int c = (P & F_C); \
+ int sum = A + tmp + c; \
+ P &= ~(F_V | F_C); \
+ if( ~(A^tmp) & (A^sum) & F_N ) \
+ P |= F_V; \
+ if( sum & 0xff00 ) \
+ P |= F_C; \
+ A = (UINT8) sum; \
+ } \
+ SET_NZ(A)
+
+/* 65ce02 ******************************************************
+ * AND Logical and
+ ***************************************************************/
+#define AND \
+ A = (UINT8)(A & tmp); \
+ SET_NZ(A)
+
+/* 65ce02 ******************************************************
+ * ASL Arithmetic shift left
+ ***************************************************************/
+#define ASL \
+ P = (P & ~F_C) | ((tmp >> 7) & F_C); \
+ tmp = (UINT8)(tmp << 1); \
+ SET_NZ(tmp)
+
+/* 65ce02 ******************************************************
+ * ASR arithmetic (signed) shift right
+ * [7] -> [7][6][5][4][3][2][1][0] -> C
+ ***************************************************************/
+#define ASR_65CE02 \
+ P = (P & ~F_C) | (tmp & F_C); \
+ tmp = (signed char)tmp >> 1; \
+ SET_NZ(tmp)
+
+/* 65ce02 ******************************************************
+ * ASW arithmetic shift left word
+ * [c] <- [15]..[6][5][4][3][2][1][0]
+ ***************************************************************/
+/* not sure about how 16 bit memory modifying is executed */
+#define ASW \
+ tmp.w.l = tmp.w.l << 1; \
+ P = (P & ~F_C) | (tmp.b.h2 & F_C); \
+ SET_NZ_WORD(tmp);
+
+
+/* 65ce02 ******************************************************
+ * augment
+ ***************************************************************/
+#define AUG \
+ t1=RDOPARG(); \
+ t2=RDOPARG(); \
+ t3=RDOPARG(); \
+ logerror("m65ce02 at pc:%.4x reserved op aug %.2x %.2x %.2x\n", cpu_get_pc(cpustate->device),t1,t2,t3);
+
+/* 65ce02 ******************************************************
+ * BBR Branch if bit is reset
+ ***************************************************************/
+#define BBR(bit) \
+ BRA(!(tmp & (1<<bit)))
+
+/* 65ce02 ******************************************************
+ * BBS Branch if bit is set
+ ***************************************************************/
+#define BBS(bit) \
+ BRA(tmp & (1<<bit))
+
+/* 65ce02 ******************************************************
+ * BIT Bit test
+ ***************************************************************/
+#undef BIT
+#define BIT \
+ P &= ~(F_N|F_V|F_Z); \
+ P |= tmp & (F_N|F_V); \
+ if ((tmp & A) == 0) \
+ P |= F_Z
+
+/***************************************************************
+ * BRA branch relative
+ ***************************************************************/
+#define BRA(cond) \
+ if (cond) \
+ { \
+ tmp = RDOPARG(); \
+ EAW = PCW + (signed char)tmp; \
+ PCD = EAD; \
+ } \
+ else \
+ { \
+ PCW += 1; \
+ }
+
+/***************************************************************
+ * BRA branch relative
+ ***************************************************************/
+#define BRA_WORD(cond) \
+ if (cond) \
+ { \
+ EAL = RDOPARG(); \
+ EAH = RDOPARG(); \
+ EAW = PCW + (short)(EAW-1); \
+ PCD = EAD; \
+ } \
+ else \
+ { \
+ PCW += 2; \
+ }
+/* 65ce02 ******************************************************
+ * BRK Break
+ * increment PC, push PC hi, PC lo, flags (with B bit set),
+ * set I flag, jump via IRQ vector
+ ***************************************************************/
+#define BRK \
+ RDOPARG(); \
+ PUSH(PCH); \
+ PUSH(PCL); \
+ PUSH(P | F_B); \
+ P = (P | F_I); \
+ PCL = RDMEM(M6502_IRQ_VEC); \
+ PCH = RDMEM(M6502_IRQ_VEC+1);
+
+/* 65ce02 ********************************************************
+ * BSR Branch to subroutine
+ ***************************************************************/
+#define BSR \
+ EAL = RDOPARG(); \
+ PUSH(PCH); \
+ PUSH(PCL); \
+ EAH = RDOPARG(); \
+ EAW = PCW + (INT16)(EAW-1); \
+ PCD = EAD;
+
+/* 65ce02 ******************************************************
+ * CLC Clear carry flag
+ ***************************************************************/
+#define CLC \
+ P &= ~F_C
+
+/* 65ce02 ******************************************************
+ * CLD Clear decimal flag
+ ***************************************************************/
+#define CLD \
+ P &= ~F_D
+
+/* 65ce02 ******************************************************
+ * cle clear disable extended stack flag
+ ***************************************************************/
+#define CLE \
+ P|=F_E
+
+/* 65ce02 ******************************************************
+ * CLI Clear interrupt flag
+ ***************************************************************/
+#define CLI \
+ if ((IRQ_STATE != CLEAR_LINE) && (P & F_I)) { \
+ AFTER_CLI = 1; \
+ } \
+ P &= ~F_I
+
+/* 65ce02 ******************************************************
+ * CLV Clear overflow flag
+ ***************************************************************/
+#define CLV \
+ P &= ~F_V
+
+/* 65ce02 ******************************************************
+ * CMP Compare accumulator
+ ***************************************************************/
+#define CMP \
+ P &= ~F_C; \
+ if (A >= tmp) \
+ P |= F_C; \
+ SET_NZ((UINT8)(A - tmp))
+
+/* 65ce02 ******************************************************
+ * CPX Compare index X
+ ***************************************************************/
+#define CPX \
+ P &= ~F_C; \
+ if (X >= tmp) \
+ P |= F_C; \
+ SET_NZ((UINT8)(X - tmp))
+
+/* 65ce02 ******************************************************
+ * CPY Compare index Y
+ ***************************************************************/
+#define CPY \
+ P &= ~F_C; \
+ if (Y >= tmp) \
+ P |= F_C; \
+ SET_NZ((UINT8)(Y - tmp))
+
+/* 65ce02 ******************************************************
+ * CPZ Compare index Z
+ ***************************************************************/
+#define CPZ \
+ P &= ~F_C; \
+ if (Z >= tmp) \
+ P |= F_C; \
+ SET_NZ((UINT8)(Z - tmp))
+
+/* 65ce02 ******************************************************
+ * DEA Decrement accumulator
+ ***************************************************************/
+#define DEA \
+ A = (UINT8)(A - 1); \
+ SET_NZ(A)
+
+/* 65ce02 ******************************************************
+ * DEC Decrement memory
+ ***************************************************************/
+#define DEC \
+ tmp = (UINT8)(tmp-1); \
+ SET_NZ(tmp)
+
+/* 65ce02 ******************************************************
+ * DEW Decrement memory word
+ ***************************************************************/
+#define DEW \
+ tmp.w.l -= 1; \
+ SET_NZ_WORD(tmp)
+
+/* 65ce02 ******************************************************
+ * DEX Decrement index X
+ ***************************************************************/
+#define DEX \
+ X = (UINT8)(X-1); \
+ SET_NZ(X)
+
+/* 65ce02 ******************************************************
+ * DEY Decrement index Y
+ ***************************************************************/
+#define DEY \
+ Y = (UINT8)(Y-1); \
+ SET_NZ(Y)
+
+/* 65ce02 ******************************************************
+ * DEZ Decrement index Z
+ ***************************************************************/
+#define DEZ \
+ Z = (UINT8)(Z-1); \
+ SET_NZ(Z)
+
+/* 65ce02 ******************************************************
+ * EOR Logical exclusive or
+ ***************************************************************/
+#define EOR \
+ A = (UINT8)(A ^ tmp); \
+ SET_NZ(A)
+
+/* 65ce02 ******************************************************
+ * INA Increment accumulator
+ ***************************************************************/
+#define INA \
+ A = (UINT8)(A + 1); \
+ SET_NZ(A)
+
+/* 65ce02 ******************************************************
+ * INC Increment memory
+ ***************************************************************/
+#define INC \
+ tmp = (UINT8)(tmp+1); \
+ SET_NZ(tmp)
+
+/* 65ce02 ******************************************************
+ * INW Increment memory word
+ ***************************************************************/
+#define INW \
+ tmp.w.l += 1; \
+ SET_NZ_WORD(tmp)
+
+/* 65ce02 ******************************************************
+ * INX Increment index X
+ ***************************************************************/
+#define INX \
+ X = (UINT8)(X+1); \
+ SET_NZ(X)
+
+/* 65ce02 ******************************************************
+ * INY Increment index Y
+ ***************************************************************/
+#define INY \
+ Y = (UINT8)(Y+1); \
+ SET_NZ(Y)
+
+/* 65ce02 ******************************************************
+ * INZ Increment index Z
+ ***************************************************************/
+#define INZ \
+ Z = (UINT8)(Z+1); \
+ SET_NZ(Z)
+
+/* 65ce02 ******************************************************
+ * JMP Jump to address
+ * set PC to the effective address
+ ***************************************************************/
+#define JMP \
+ PCD = EAD;
+
+/* 65ce02 ******************************************************
+ * JSR Jump to subroutine
+ * decrement PC (sic!) push PC hi, push PC lo and set
+ * PC to the effective address
+ ***************************************************************/
+#define JSR \
+ EAL = RDOPARG(); \
+ PUSH(PCH); \
+ PUSH(PCL); \
+ EAH = RDOPARG(); \
+ PCD = EAD;
+
+/* 65ce02 ******************************************************
+ * JSR Jump to subroutine
+ * decrement PC (sic!) push PC hi, push PC lo and set
+ * PC to the effective address
+ ***************************************************************/
+#define JSR_IND \
+ EAL = RDOPARG(); \
+ PUSH(PCH); \
+ PUSH(PCL); \
+ EAH = RDOPARG(); \
+ PCL = RDMEM(EAD); \
+ PCH = RDMEM(EAD+1);
+
+/* 65ce02 ******************************************************
+ * JSR Jump to subroutine
+ * decrement PC (sic!) push PC hi, push PC lo and set
+ * PC to the effective address
+ ***************************************************************/
+#define JSR_INDX \
+ EAL = RDOPARG()+X; \
+ PUSH(PCH); \
+ PUSH(PCL); \
+ EAH = RDOPARG(); \
+ PCL = RDMEM(EAD); \
+ PCH = RDMEM(EAD+1);
+
+/* 65ce02 ******************************************************
+ * LDA Load accumulator
+ ***************************************************************/
+#define LDA \
+ A = (UINT8)tmp; \
+ SET_NZ(A)
+
+/* 65ce02 ******************************************************
+ * LDX Load index X
+ ***************************************************************/
+#define LDX \
+ X = (UINT8)tmp; \
+ SET_NZ(X)
+
+/* 65ce02 ******************************************************
+ * LDY Load index Y
+ ***************************************************************/
+#define LDY \
+ Y = (UINT8)tmp; \
+ SET_NZ(Y)
+
+/* 65ce02 ******************************************************
+ * LDZ Load index Z
+ ***************************************************************/
+#define LDZ \
+ Z = (UINT8)tmp; \
+ SET_NZ(Z)
+
+/* 65ce02 ******************************************************
+ * LSR Logic shift right
+ * 0 -> [7][6][5][4][3][2][1][0] -> C
+ ***************************************************************/
+#define LSR \
+ P = (P & ~F_C) | (tmp & F_C); \
+ tmp = (UINT8)tmp >> 1; \
+ SET_NZ(tmp)
+
+/* 65ce02 ******************************************************
+ * NEG accu
+ * twos complement
+ ***************************************************************/
+#define NEG \
+ A= (A^0xff)+1; \
+ SET_NZ(A)
+
+/* 65ce02 ******************************************************
+ * NOP No operation
+ ***************************************************************/
+#define NOP
+
+/* 65ce02 ******************************************************
+ * ORA Logical inclusive or
+ ***************************************************************/
+#define ORA \
+ A = (UINT8)(A | tmp); \
+ SET_NZ(A)
+
+/* 65ce02 ******************************************************
+ * PHA Push accumulator
+ ***************************************************************/
+#define PHA \
+ PUSH(A)
+
+/* 65ce02 ******************************************************
+ * PHP Push processor status (flags)
+ ***************************************************************/
+#define PHP \
+ PUSH(P)
+
+/* 65ce02 ******************************************************
+ * PHX Push index X
+ ***************************************************************/
+#define PHX \
+ PUSH(X)
+
+/* 65ce02 ******************************************************
+ * PHY Push index Y
+ ***************************************************************/
+#define PHY \
+ PUSH(Y)
+
+/* 65ce02 ******************************************************
+ * PHZ Push index z
+ ***************************************************************/
+#define PHZ \
+ PUSH(Z)
+
+/* 65ce02 ******************************************************
+ * PLA Pull accumulator
+ ***************************************************************/
+#define PLA \
+ PULL(A); \
+ SET_NZ(A)
+
+/* 65ce02 ******************************************************
+ * PLP Pull processor status (flags)
+ ***************************************************************/
+#define PLP \
+ if ( P & F_I ) { \
+ UINT8 temp; \
+ PULL(temp); \
+ P=(P&F_E)|F_B|(temp&~F_E); \
+ if( IRQ_STATE != CLEAR_LINE && !(P & F_I) ) { \
+ LOG(("M65ce02 '%s' PLP sets after_cli\n", cpustate->device->tag())); \
+ AFTER_CLI = 1; \
+ } \
+ } else { \
+ UINT8 temp; \
+ PULL(temp); \
+ P=(P&F_E)|F_B|(temp&~F_E); \
+ }
+
+/* 65ce02 ******************************************************
+ * PLX Pull index X
+ ***************************************************************/
+#define PLX \
+ PULL(X); \
+ SET_NZ(X)
+
+/* 65ce02 ******************************************************
+ * PLY Pull index Y
+ ***************************************************************/
+#define PLY \
+ PULL(Y); \
+ SET_NZ(Y)
+
+/* 65ce02 ******************************************************
+ * PLZ Pull index Z
+ ***************************************************************/
+#define PLZ \
+ PULL(Z); \
+ SET_NZ(Z)
+
+/* 65ce02 ******************************************************
+ * RMB Reset memory bit
+ ***************************************************************/
+#define RMB(bit) \
+ tmp &= ~(1<<bit)
+
+/* 65ce02 ******************************************************
+ * ROL Rotate left
+ * new C <- [7][6][5][4][3][2][1][0] <- C
+ ***************************************************************/
+#define ROL \
+ tmp = (tmp << 1) | (P & F_C); \
+ P = (P & ~F_C) | ((tmp >> 8) & F_C); \
+ tmp = (UINT8)tmp; \
+ SET_NZ(tmp)
+
+/* 65ce02 ******************************************************
+ * ROR Rotate right
+ * C -> [7][6][5][4][3][2][1][0] -> new C
+ ***************************************************************/
+#define ROR \
+ tmp |= (P & F_C) << 8; \
+ P = (P & ~F_C) | (tmp & F_C); \
+ tmp = (UINT8)(tmp >> 1); \
+ SET_NZ(tmp)
+
+/* 65ce02 ******************************************************
+ * ROW rotate left word
+ * [c] <- [15]..[6][5][4][3][2][1][0] <- C
+ ***************************************************************/
+/* not sure about how 16 bit memory modifying is executed */
+#define ROW \
+ tmp.d =(tmp.d << 1); \
+ tmp.w.l |= (P & F_C); \
+ P = (P & ~F_C) | (tmp.w.l & F_C); \
+ SET_NZ_WORD(tmp);
+
+
+/* 65ce02 ********************************************************
+ * RTI Return from interrupt
+ * pull flags, pull PC lo, pull PC hi
+ ***************************************************************/
+#define RTI \
+ RDMEM(SPD); \
+ PULL(tmp); \
+ P = (P&F_E)|F_B|(tmp&~F_E); \
+ PULL(PCL); \
+ PULL(PCH); \
+ if( IRQ_STATE != CLEAR_LINE && !(P & F_I) ) \
+ { \
+ LOG(("M65ce02 '%s' RTI sets after_cli\n", cpustate->device->tag())); \
+ AFTER_CLI = 1; \
+ }
+
+/* 65ce02 ******************************************************
+ * RTS Return from subroutine
+ * pull PC lo, PC hi and increment PC
+ ***************************************************************/
+#define RTS \
+ PULL(PCL); \
+ PULL(PCH); \
+ RDMEM(PCW); PCW++;
+
+/* 65ce02 ******************************************************
+ * RTS imm
+ * Is the stack adjustment done before or after the return actions?
+ * Exact order of the read instructions unknown
+ ***************************************************************/
+#define RTN \
+ if (P&F_E) { \
+ SPL+=tmp; \
+ } else { \
+ SW+=tmp; \
+ } \
+ RDMEM(PCW-1); \
+ RDMEM(PCW-1); \
+ RDMEM(SPD); \
+ P = (P&F_E)|F_B|(tmp&~F_E); \
+ PULL(PCL); \
+ PULL(PCH); \
+ if( IRQ_STATE != CLEAR_LINE && !(P & F_I) ) { \
+ LOG(("M65ce02 '%s' RTI sets after_cli\n", cpustate->device->tag())); \
+ AFTER_CLI = 1; \
+ }
+
+
+/* 65ce02 *******************************************************
+ * SBC Subtract with carry
+ * correct setting of flags in decimal mode
+ ***************************************************************/
+#define SBC \
+ if (P & F_D) { \
+ int c = (P & F_C) ^ F_C; \
+ int sum = A - tmp - c; \
+ int lo = (A & 0x0f) - (tmp & 0x0f) - c; \
+ int hi = (A & 0xf0) - (tmp & 0xf0); \
+ P &= ~(F_V | F_C); \
+ if( (A^tmp) & (A^sum) & F_N ) \
+ P |= F_V; \
+ if( lo & 0xf0 ) \
+ lo -= 6; \
+ if( lo & 0x80 ) \
+ hi -= 0x10; \
+ if( hi & 0x0f00 ) \
+ hi -= 0x60; \
+ if( (sum & 0xff00) == 0 ) \
+ P |= F_C; \
+ A = (lo & 0x0f) + (hi & 0xf0); \
+ } else { \
+ int c = (P & F_C) ^ F_C; \
+ int sum = A - tmp - c; \
+ P &= ~(F_V | F_C); \
+ if( (A^tmp) & (A^sum) & F_N ) \
+ P |= F_V; \
+ if( (sum & 0xff00) == 0 ) \
+ P |= F_C; \
+ A = (UINT8) sum; \
+ } \
+ SET_NZ(A)
+
+/* 65ce02 ******************************************************
+ * SEC Set carry flag
+ ***************************************************************/
+#if defined(SEC)
+#undef SEC
+#endif
+#define SEC \
+ P |= F_C
+
+/* 65ce02 ******************************************************
+ * SED Set decimal flag
+ ***************************************************************/
+#define SED \
+ P |= F_D
+
+/* 65ce02 ******************************************************
+ * see set disable extended stack flag
+ ***************************************************************/
+#define SEE \
+ P&=~F_E
+
+/* 65ce02 ******************************************************
+ * SEI Set interrupt flag
+ ***************************************************************/
+#define SEI \
+ P |= F_I
+
+/* 65ce02 ******************************************************
+ * SMB Set memory bit
+ ***************************************************************/
+#define SMB(bit) \
+ tmp |= (1<<bit)
+
+/* 65ce02 ******************************************************
+ * STA Store accumulator
+ ***************************************************************/
+#define STA \
+ tmp = A
+
+/* 65ce02 ******************************************************
+ * STX Store index X
+ ***************************************************************/
+#define STX \
+ tmp = X
+
+/* 65ce02 ******************************************************
+ * STY Store index Y
+ ***************************************************************/
+#define STY \
+ tmp = Y
+
+/* 65ce02 ******************************************************
+ * STZ Store index Z
+ ***************************************************************/
+#define STZ_65CE02 \
+ tmp = Z
+
+/* 65ce02 ******************************************************
+ * TAB Transfer accumulator to Direct Page
+ ***************************************************************/
+#define TAB \
+ B = A; \
+ SET_NZ(B)
+
+/* 65ce02 ******************************************************
+ * TAX Transfer accumulator to index X
+ ***************************************************************/
+#define TAX \
+ X = A; \
+ SET_NZ(X)
+
+/* 65ce02 ******************************************************
+ * TAY Transfer accumulator to index Y
+ ***************************************************************/
+#define TAY \
+ Y = A; \
+ SET_NZ(Y)
+
+/* 65ce02 ******************************************************
+ * TAZ Transfer accumulator to index z
+ ***************************************************************/
+#define TAZ \
+ Z = A; \
+ SET_NZ(Z)
+
+/* 65ce02 ******************************************************
+ * TBA Transfer direct page to accumulator
+ ***************************************************************/
+#define TBA \
+ A = B; \
+ SET_NZ(A)
+
+/* 65ce02 ******************************************************
+ * TRB Test and reset bits
+ ***************************************************************/
+#define TRB \
+ SET_Z(tmp&A); \
+ tmp &= ~A
+
+/* 65ce02 ******************************************************
+ * TSB Test and set bits
+ ***************************************************************/
+#define TSB \
+ SET_Z(tmp&A); \
+ tmp |= A
+
+/* 65ce02 ******************************************************
+ * TSX Transfer stack LSB to index X
+ ***************************************************************/
+#define TSX \
+ X = SPL; \
+ SET_NZ(X)
+
+/* 65ce02 ******************************************************
+ * TSY Transfer stack pointer to index y
+ ***************************************************************/
+#define TSY \
+ Y = SPH; \
+ SET_NZ(Y)
+
+/* 65ce02 ******************************************************
+ * TXA Transfer index X to accumulator
+ ***************************************************************/
+#define TXA \
+ A = X; \
+ SET_NZ(A)
+
+/* 65ce02 ********************************************************
+ * TXS Transfer index X to stack LSB
+ * no flags changed (sic!)
+ * txs tys not interruptable
+ ***************************************************************/
+#define TXS \
+ SPL = X; \
+ if (PEEK_OP() == 0x2b /*TYS*/ ) { \
+ UINT8 op = RDOP(); \
+ (*cpustate->insn[op])(cpustate); \
+ }
+
+
+/* 65ce02 ******************************************************
+ * TYA Transfer index Y to accumulator
+ ***************************************************************/
+#define TYA \
+ A = Y; \
+ SET_NZ(A)
+
+/* 65ce02 ******************************************************
+ * TYS Transfer index y to stack pointer
+ ***************************************************************/
+#define TYS \
+ SPH = Y;
+
+/* 65ce02 ******************************************************
+ * TZA Transfer index z to accumulator
+ ***************************************************************/
+#define TZA \
+ A = Z; \
+ SET_NZ(A)
diff --git a/trunk/src/emu/cpu/m6502/opsn2a03.h b/trunk/src/emu/cpu/m6502/opsn2a03.h
new file mode 100644
index 00000000000..8632168fe32
--- /dev/null
+++ b/trunk/src/emu/cpu/m6502/opsn2a03.h
@@ -0,0 +1,38 @@
+/***************************************************************
+ ***************************************************************
+ * Macros to emulate the N2A03 opcodes
+ ***************************************************************
+ ***************************************************************/
+
+
+/* N2A03 *******************************************************
+ * ADC Add with carry - no decimal mode
+ ***************************************************************/
+#define ADC_NES \
+ { \
+ int c = (P & F_C); \
+ int sum = A + tmp + c; \
+ P &= ~(F_V | F_C); \
+ if( ~(A^tmp) & (A^sum) & F_N ) \
+ P |= F_V; \
+ if( sum & 0xff00 ) \
+ P |= F_C; \
+ A = (UINT8) sum; \
+ } \
+ SET_NZ(A)
+
+/* N2A03 *******************************************************
+ * SBC Subtract with carry - no decimal mode
+ ***************************************************************/
+#define SBC_NES \
+ { \
+ int c = (P & F_C) ^ F_C; \
+ int sum = A - tmp - c; \
+ P &= ~(F_V | F_C); \
+ if( (A^tmp) & (A^sum) & F_N ) \
+ P |= F_V; \
+ if( (sum & 0xff00) == 0 ) \
+ P |= F_C; \
+ A = (UINT8) sum; \
+ } \
+ SET_NZ(A)
diff --git a/trunk/src/emu/cpu/m6502/t6502.c b/trunk/src/emu/cpu/m6502/t6502.c
new file mode 100644
index 00000000000..0bd06e6754d
--- /dev/null
+++ b/trunk/src/emu/cpu/m6502/t6502.c
@@ -0,0 +1,360 @@
+/*****************************************************************************
+ *
+ * tbl6502.c
+ * 6502 opcode functions and function pointer table
+ *
+ * Copyright Juergen Buchmueller, all rights reserved.
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * pullmoll@t-online.de
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ * 2003-05-26 Fixed PHP, PLP, PHA, PLA cycle counts. [SJ]
+ * 2004-04-30 Fixed STX (abs) cycle count. [SJ]
+ *
+ *****************************************************************************/
+
+#undef OP
+#define OP(nn) INLINE void m6502_##nn(m6502_Regs *cpustate)
+
+/*****************************************************************************
+ *****************************************************************************
+ *
+ * plain vanilla 6502 opcodes
+ *
+ *****************************************************************************
+ * op temp cycles rdmem opc wrmem ********************/
+
+OP(00) { BRK; } /* 7 BRK */
+OP(20) { JSR; } /* 6 JSR */
+OP(40) { RTI; } /* 6 RTI */
+OP(60) { RTS; } /* 6 RTS */
+OP(80) { RDOPARG(); NOP; } /* 2 NOP IMM */
+OP(a0) { int tmp; RD_IMM; LDY; } /* 2 LDY IMM */
+OP(c0) { int tmp; RD_IMM; CPY; } /* 2 CPY IMM */
+OP(e0) { int tmp; RD_IMM; CPX; } /* 2 CPX IMM */
+
+OP(10) { BPL; } /* 2-4 BPL REL */
+OP(30) { BMI; } /* 2-4 BMI REL */
+OP(50) { BVC; } /* 2-4 BVC REL */
+OP(70) { BVS; } /* 2-4 BVS REL */
+OP(90) { BCC; } /* 2-4 BCC REL */
+OP(b0) { BCS; } /* 2-4 BCS REL */
+OP(d0) { BNE; } /* 2-4 BNE REL */
+OP(f0) { BEQ; } /* 2-4 BEQ REL */
+
+OP(01) { int tmp; RD_IDX; ORA; } /* 6 ORA IDX */
+OP(21) { int tmp; RD_IDX; AND; } /* 6 AND IDX */
+OP(41) { int tmp; RD_IDX; EOR; } /* 6 EOR IDX */
+OP(61) { int tmp; RD_IDX; ADC; } /* 6 ADC IDX */
+OP(81) { int tmp; STA; WR_IDX; } /* 6 STA IDX */
+OP(a1) { int tmp; RD_IDX; LDA; } /* 6 LDA IDX */
+OP(c1) { int tmp; RD_IDX; CMP; } /* 6 CMP IDX */
+OP(e1) { int tmp; RD_IDX; SBC; } /* 6 SBC IDX */
+
+OP(11) { int tmp; RD_IDY_P; ORA; } /* 5 ORA IDY page penalty */
+OP(31) { int tmp; RD_IDY_P; AND; } /* 5 AND IDY page penalty */
+OP(51) { int tmp; RD_IDY_P; EOR; } /* 5 EOR IDY page penalty */
+OP(71) { int tmp; RD_IDY_P; ADC; } /* 5 ADC IDY page penalty */
+OP(91) { int tmp; STA; WR_IDY_NP; } /* 6 STA IDY */
+OP(b1) { int tmp; RD_IDY_P; LDA; } /* 5 LDA IDY page penalty */
+OP(d1) { int tmp; RD_IDY_P; CMP; } /* 5 CMP IDY page penalty */
+OP(f1) { int tmp; RD_IDY_P; SBC; } /* 5 SBC IDY page penalty */
+
+OP(02) { KIL; } /* 1 KIL */
+OP(22) { KIL; } /* 1 KIL */
+OP(42) { KIL; } /* 1 KIL */
+OP(62) { KIL; } /* 1 KIL */
+OP(82) { RDOPARG(); NOP; } /* 2 NOP IMM */
+OP(a2) { int tmp; RD_IMM; LDX; } /* 2 LDX IMM */
+OP(c2) { RDOPARG(); NOP; } /* 2 NOP IMM */
+OP(e2) { RDOPARG(); NOP; } /* 2 NOP IMM */
+
+OP(12) { KIL; } /* 1 KIL */
+OP(32) { KIL; } /* 1 KIL */
+OP(52) { KIL; } /* 1 KIL */
+OP(72) { KIL; } /* 1 KIL */
+OP(92) { KIL; } /* 1 KIL */
+OP(b2) { KIL; } /* 1 KIL */
+OP(d2) { KIL; } /* 1 KIL */
+OP(f2) { KIL; } /* 1 KIL */
+
+OP(03) { int tmp; RD_IDX; WB_EA; SLO; WB_EA; } /* 7 SLO IDX */
+OP(23) { int tmp; RD_IDX; WB_EA; RLA; WB_EA; } /* 7 RLA IDX */
+OP(43) { int tmp; RD_IDX; WB_EA; SRE; WB_EA; } /* 7 SRE IDX */
+OP(63) { int tmp; RD_IDX; WB_EA; RRA; WB_EA; } /* 7 RRA IDX */
+OP(83) { int tmp; SAX; WR_IDX; } /* 6 SAX IDX */
+OP(a3) { int tmp; RD_IDX; LAX; } /* 6 LAX IDX */
+OP(c3) { int tmp; RD_IDX; WB_EA; DCP; WB_EA; } /* 7 DCP IDX */
+OP(e3) { int tmp; RD_IDX; WB_EA; ISB; WB_EA; } /* 7 ISB IDX */
+
+OP(13) { int tmp; RD_IDY_NP; WB_EA; SLO; WB_EA; } /* 7 SLO IDY */
+OP(33) { int tmp; RD_IDY_NP; WB_EA; RLA; WB_EA; } /* 7 RLA IDY */
+OP(53) { int tmp; RD_IDY_NP; WB_EA; SRE; WB_EA; } /* 7 SRE IDY */
+OP(73) { int tmp; RD_IDY_NP; WB_EA; RRA; WB_EA; } /* 7 RRA IDY */
+OP(93) { int tmp; EA_IDY_NP; SAH; WB_EA; } /* 5 SAH IDY */
+OP(b3) { int tmp; RD_IDY_P; LAX; } /* 5 LAX IDY page penalty */
+OP(d3) { int tmp; RD_IDY_NP; WB_EA; DCP; WB_EA; } /* 7 DCP IDY */
+OP(f3) { int tmp; RD_IDY_NP; WB_EA; ISB; WB_EA; } /* 7 ISB IDY */
+
+OP(04) { RD_ZPG_DISCARD; NOP; } /* 3 NOP ZPG */
+OP(24) { int tmp; RD_ZPG; BIT; } /* 3 BIT ZPG */
+OP(44) { RD_ZPG_DISCARD; NOP; } /* 3 NOP ZPG */
+OP(64) { RD_ZPG_DISCARD; NOP; } /* 3 NOP ZPG */
+OP(84) { int tmp; STY; WR_ZPG; } /* 3 STY ZPG */
+OP(a4) { int tmp; RD_ZPG; LDY; } /* 3 LDY ZPG */
+OP(c4) { int tmp; RD_ZPG; CPY; } /* 3 CPY ZPG */
+OP(e4) { int tmp; RD_ZPG; CPX; } /* 3 CPX ZPG */
+
+OP(14) { RD_ZPX_DISCARD; NOP; } /* 4 NOP ZPX */
+OP(34) { RD_ZPX_DISCARD; NOP; } /* 4 NOP ZPX */
+OP(54) { RD_ZPX_DISCARD; NOP; } /* 4 NOP ZPX */
+OP(74) { RD_ZPX_DISCARD; NOP; } /* 4 NOP ZPX */
+OP(94) { int tmp; STY; WR_ZPX; } /* 4 STY ZPX */
+OP(b4) { int tmp; RD_ZPX; LDY; } /* 4 LDY ZPX */
+OP(d4) { RD_ZPX_DISCARD; NOP; } /* 4 NOP ZPX */
+OP(f4) { RD_ZPX_DISCARD; NOP; } /* 4 NOP ZPX */
+
+OP(05) { int tmp; RD_ZPG; ORA; } /* 3 ORA ZPG */
+OP(25) { int tmp; RD_ZPG; AND; } /* 3 AND ZPG */
+OP(45) { int tmp; RD_ZPG; EOR; } /* 3 EOR ZPG */
+OP(65) { int tmp; RD_ZPG; ADC; } /* 3 ADC ZPG */
+OP(85) { int tmp; STA; WR_ZPG; } /* 3 STA ZPG */
+OP(a5) { int tmp; RD_ZPG; LDA; } /* 3 LDA ZPG */
+OP(c5) { int tmp; RD_ZPG; CMP; } /* 3 CMP ZPG */
+OP(e5) { int tmp; RD_ZPG; SBC; } /* 3 SBC ZPG */
+
+OP(15) { int tmp; RD_ZPX; ORA; } /* 4 ORA ZPX */
+OP(35) { int tmp; RD_ZPX; AND; } /* 4 AND ZPX */
+OP(55) { int tmp; RD_ZPX; EOR; } /* 4 EOR ZPX */
+OP(75) { int tmp; RD_ZPX; ADC; } /* 4 ADC ZPX */
+OP(95) { int tmp; STA; WR_ZPX; } /* 4 STA ZPX */
+OP(b5) { int tmp; RD_ZPX; LDA; } /* 4 LDA ZPX */
+OP(d5) { int tmp; RD_ZPX; CMP; } /* 4 CMP ZPX */
+OP(f5) { int tmp; RD_ZPX; SBC; } /* 4 SBC ZPX */
+
+OP(06) { int tmp; RD_ZPG; WB_EA; ASL; WB_EA; } /* 5 ASL ZPG */
+OP(26) { int tmp; RD_ZPG; WB_EA; ROL; WB_EA; } /* 5 ROL ZPG */
+OP(46) { int tmp; RD_ZPG; WB_EA; LSR; WB_EA; } /* 5 LSR ZPG */
+OP(66) { int tmp; RD_ZPG; WB_EA; ROR; WB_EA; } /* 5 ROR ZPG */
+OP(86) { int tmp; STX; WR_ZPG; } /* 3 STX ZPG */
+OP(a6) { int tmp; RD_ZPG; LDX; } /* 3 LDX ZPG */
+OP(c6) { int tmp; RD_ZPG; WB_EA; DEC; WB_EA; } /* 5 DEC ZPG */
+OP(e6) { int tmp; RD_ZPG; WB_EA; INC; WB_EA; } /* 5 INC ZPG */
+
+OP(16) { int tmp; RD_ZPX; WB_EA; ASL; WB_EA; } /* 6 ASL ZPX */
+OP(36) { int tmp; RD_ZPX; WB_EA; ROL; WB_EA; } /* 6 ROL ZPX */
+OP(56) { int tmp; RD_ZPX; WB_EA; LSR; WB_EA; } /* 6 LSR ZPX */
+OP(76) { int tmp; RD_ZPX; WB_EA; ROR; WB_EA; } /* 6 ROR ZPX */
+OP(96) { int tmp; STX; WR_ZPY; } /* 4 STX ZPY */
+OP(b6) { int tmp; RD_ZPY; LDX; } /* 4 LDX ZPY */
+OP(d6) { int tmp; RD_ZPX; WB_EA; DEC; WB_EA; } /* 6 DEC ZPX */
+OP(f6) { int tmp; RD_ZPX; WB_EA; INC; WB_EA; } /* 6 INC ZPX */
+
+OP(07) { int tmp; RD_ZPG; WB_EA; SLO; WB_EA; } /* 5 SLO ZPG */
+OP(27) { int tmp; RD_ZPG; WB_EA; RLA; WB_EA; } /* 5 RLA ZPG */
+OP(47) { int tmp; RD_ZPG; WB_EA; SRE; WB_EA; } /* 5 SRE ZPG */
+OP(67) { int tmp; RD_ZPG; WB_EA; RRA; WB_EA; } /* 5 RRA ZPG */
+OP(87) { int tmp; SAX; WR_ZPG; } /* 3 SAX ZPG */
+OP(a7) { int tmp; RD_ZPG; LAX; } /* 3 LAX ZPG */
+OP(c7) { int tmp; RD_ZPG; WB_EA; DCP; WB_EA; } /* 5 DCP ZPG */
+OP(e7) { int tmp; RD_ZPG; WB_EA; ISB; WB_EA; } /* 5 ISB ZPG */
+
+OP(17) { int tmp; RD_ZPX; WB_EA; SLO; WB_EA; } /* 6 SLO ZPX */
+OP(37) { int tmp; RD_ZPX; WB_EA; RLA; WB_EA; } /* 6 RLA ZPX */
+OP(57) { int tmp; RD_ZPX; WB_EA; SRE; WB_EA; } /* 6 SRE ZPX */
+OP(77) { int tmp; RD_ZPX; WB_EA; RRA; WB_EA; } /* 6 RRA ZPX */
+OP(97) { int tmp; SAX; WR_ZPY; } /* 4 SAX ZPY */
+OP(b7) { int tmp; RD_ZPY; LAX; } /* 4 LAX ZPY */
+OP(d7) { int tmp; RD_ZPX; WB_EA; DCP; WB_EA; } /* 6 DCP ZPX */
+OP(f7) { int tmp; RD_ZPX; WB_EA; ISB; WB_EA; } /* 6 ISB ZPX */
+
+OP(08) { RD_DUM; PHP; } /* 3 PHP */
+OP(28) { RD_DUM; PLP; } /* 4 PLP */
+OP(48) { RD_DUM; PHA; } /* 3 PHA */
+OP(68) { RD_DUM; PLA; } /* 4 PLA */
+OP(88) { RD_DUM; DEY; } /* 2 DEY */
+OP(a8) { RD_DUM; TAY; } /* 2 TAY */
+OP(c8) { RD_DUM; INY; } /* 2 INY */
+OP(e8) { RD_DUM; INX; } /* 2 INX */
+
+OP(18) { RD_DUM; CLC; } /* 2 CLC */
+OP(38) { RD_DUM; SEC; } /* 2 SEC */
+OP(58) { RD_DUM; CLI; } /* 2 CLI */
+OP(78) { RD_DUM; SEI; } /* 2 SEI */
+OP(98) { RD_DUM; TYA; } /* 2 TYA */
+OP(b8) { RD_DUM; CLV; } /* 2 CLV */
+OP(d8) { RD_DUM; CLD; } /* 2 CLD */
+OP(f8) { RD_DUM; SED; } /* 2 SED */
+
+OP(09) { int tmp; RD_IMM; ORA; } /* 2 ORA IMM */
+OP(29) { int tmp; RD_IMM; AND; } /* 2 AND IMM */
+OP(49) { int tmp; RD_IMM; EOR; } /* 2 EOR IMM */
+OP(69) { int tmp; RD_IMM; ADC; } /* 2 ADC IMM */
+OP(89) { RD_IMM_DISCARD; NOP; } /* 2 NOP IMM */
+OP(a9) { int tmp; RD_IMM; LDA; } /* 2 LDA IMM */
+OP(c9) { int tmp; RD_IMM; CMP; } /* 2 CMP IMM */
+OP(e9) { int tmp; RD_IMM; SBC; } /* 2 SBC IMM */
+
+OP(19) { int tmp; RD_ABY_P; ORA; } /* 4 ORA ABY page penalty */
+OP(39) { int tmp; RD_ABY_P; AND; } /* 4 AND ABY page penalty */
+OP(59) { int tmp; RD_ABY_P; EOR; } /* 4 EOR ABY page penalty */
+OP(79) { int tmp; RD_ABY_P; ADC; } /* 4 ADC ABY page penalty */
+OP(99) { int tmp; STA; WR_ABY_NP; } /* 5 STA ABY */
+OP(b9) { int tmp; RD_ABY_P; LDA; } /* 4 LDA ABY page penalty */
+OP(d9) { int tmp; RD_ABY_P; CMP; } /* 4 CMP ABY page penalty */
+OP(f9) { int tmp; RD_ABY_P; SBC; } /* 4 SBC ABY page penalty */
+
+OP(0a) { int tmp; RD_DUM; RD_ACC; ASL; WB_ACC; } /* 2 ASL A */
+OP(2a) { int tmp; RD_DUM; RD_ACC; ROL; WB_ACC; } /* 2 ROL A */
+OP(4a) { int tmp; RD_DUM; RD_ACC; LSR; WB_ACC; } /* 2 LSR A */
+OP(6a) { int tmp; RD_DUM; RD_ACC; ROR; WB_ACC; } /* 2 ROR A */
+OP(8a) { RD_DUM; TXA; } /* 2 TXA */
+OP(aa) { RD_DUM; TAX; } /* 2 TAX */
+OP(ca) { RD_DUM; DEX; } /* 2 DEX */
+OP(ea) { RD_DUM; NOP; } /* 2 NOP */
+
+OP(1a) { RD_DUM; NOP; } /* 2 NOP */
+OP(3a) { RD_DUM; NOP; } /* 2 NOP */
+OP(5a) { RD_DUM; NOP; } /* 2 NOP */
+OP(7a) { RD_DUM; NOP; } /* 2 NOP */
+OP(9a) { RD_DUM; TXS; } /* 2 TXS */
+OP(ba) { RD_DUM; TSX; } /* 2 TSX */
+OP(da) { RD_DUM; NOP; } /* 2 NOP */
+OP(fa) { RD_DUM; NOP; } /* 2 NOP */
+
+OP(0b) { int tmp; RD_IMM; ANC; } /* 2 ANC IMM */
+OP(2b) { int tmp; RD_IMM; ANC; } /* 2 ANC IMM */
+OP(4b) { int tmp; RD_IMM; ASR; WB_ACC; } /* 2 ASR IMM */
+OP(6b) { int tmp; RD_IMM; ARR; WB_ACC; } /* 2 ARR IMM */
+OP(8b) { int tmp; RD_IMM; AXA; } /* 2 AXA IMM */
+OP(ab) { int tmp; RD_IMM; OAL; } /* 2 OAL IMM */
+OP(cb) { int tmp; RD_IMM; ASX; } /* 2 ASX IMM */
+OP(eb) { int tmp; RD_IMM; SBC; } /* 2 SBC IMM */
+
+OP(1b) { int tmp; RD_ABY_NP; WB_EA; SLO; WB_EA; } /* 7 SLO ABY */
+OP(3b) { int tmp; RD_ABY_NP; WB_EA; RLA; WB_EA; } /* 7 RLA ABY */
+OP(5b) { int tmp; RD_ABY_NP; WB_EA; SRE; WB_EA; } /* 7 SRE ABY */
+OP(7b) { int tmp; RD_ABY_NP; WB_EA; RRA; WB_EA; } /* 7 RRA ABY */
+OP(9b) { int tmp; EA_ABY_NP; SSH; WB_EA; } /* 5 SSH ABY */
+OP(bb) { int tmp; RD_ABY_P; AST; } /* 4 AST ABY page penalty */
+OP(db) { int tmp; RD_ABY_NP; WB_EA; DCP; WB_EA; } /* 7 DCP ABY */
+OP(fb) { int tmp; RD_ABY_NP; WB_EA; ISB; WB_EA; } /* 7 ISB ABY */
+
+OP(0c) { RD_ABS_DISCARD; NOP; } /* 4 NOP ABS */
+OP(2c) { int tmp; RD_ABS; BIT; } /* 4 BIT ABS */
+OP(4c) { EA_ABS; JMP; } /* 3 JMP ABS */
+OP(6c) { int tmp; EA_IND; JMP; } /* 5 JMP IND */
+OP(8c) { int tmp; STY; WR_ABS; } /* 4 STY ABS */
+OP(ac) { int tmp; RD_ABS; LDY; } /* 4 LDY ABS */
+OP(cc) { int tmp; RD_ABS; CPY; } /* 4 CPY ABS */
+OP(ec) { int tmp; RD_ABS; CPX; } /* 4 CPX ABS */
+
+OP(1c) { RD_ABX_P_DISCARD; NOP; } /* 4 NOP ABX page penalty */
+OP(3c) { RD_ABX_P_DISCARD; NOP; } /* 4 NOP ABX page penalty */
+OP(5c) { RD_ABX_P_DISCARD; NOP; } /* 4 NOP ABX page penalty */
+OP(7c) { RD_ABX_P_DISCARD; NOP; } /* 4 NOP ABX page penalty */
+OP(9c) { int tmp; EA_ABX_NP; SYH; WB_EA; } /* 5 SYH ABX */
+OP(bc) { int tmp; RD_ABX_P; LDY; } /* 4 LDY ABX page penalty */
+OP(dc) { RD_ABX_P_DISCARD; NOP; } /* 4 NOP ABX page penalty */
+OP(fc) { RD_ABX_P_DISCARD; NOP; } /* 4 NOP ABX page penalty */
+
+OP(0d) { int tmp; RD_ABS; ORA; } /* 4 ORA ABS */
+OP(2d) { int tmp; RD_ABS; AND; } /* 4 AND ABS */
+OP(4d) { int tmp; RD_ABS; EOR; } /* 4 EOR ABS */
+OP(6d) { int tmp; RD_ABS; ADC; } /* 4 ADC ABS */
+OP(8d) { int tmp; STA; WR_ABS; } /* 4 STA ABS */
+OP(ad) { int tmp; RD_ABS; LDA; } /* 4 LDA ABS */
+OP(cd) { int tmp; RD_ABS; CMP; } /* 4 CMP ABS */
+OP(ed) { int tmp; RD_ABS; SBC; } /* 4 SBC ABS */
+
+OP(1d) { int tmp; RD_ABX_P; ORA; } /* 4 ORA ABX page penalty */
+OP(3d) { int tmp; RD_ABX_P; AND; } /* 4 AND ABX page penalty */
+OP(5d) { int tmp; RD_ABX_P; EOR; } /* 4 EOR ABX page penalty */
+OP(7d) { int tmp; RD_ABX_P; ADC; } /* 4 ADC ABX page penalty */
+OP(9d) { int tmp; STA; WR_ABX_NP; } /* 5 STA ABX */
+OP(bd) { int tmp; RD_ABX_P; LDA; } /* 4 LDA ABX page penalty */
+OP(dd) { int tmp; RD_ABX_P; CMP; } /* 4 CMP ABX page penalty */
+OP(fd) { int tmp; RD_ABX_P; SBC; } /* 4 SBC ABX page penalty */
+
+OP(0e) { int tmp; RD_ABS; WB_EA; ASL; WB_EA; } /* 6 ASL ABS */
+OP(2e) { int tmp; RD_ABS; WB_EA; ROL; WB_EA; } /* 6 ROL ABS */
+OP(4e) { int tmp; RD_ABS; WB_EA; LSR; WB_EA; } /* 6 LSR ABS */
+OP(6e) { int tmp; RD_ABS; WB_EA; ROR; WB_EA; } /* 6 ROR ABS */
+OP(8e) { int tmp; STX; WR_ABS; } /* 4 STX ABS */
+OP(ae) { int tmp; RD_ABS; LDX; } /* 4 LDX ABS */
+OP(ce) { int tmp; RD_ABS; WB_EA; DEC; WB_EA; } /* 6 DEC ABS */
+OP(ee) { int tmp; RD_ABS; WB_EA; INC; WB_EA; } /* 6 INC ABS */
+
+OP(1e) { int tmp; RD_ABX_NP; WB_EA; ASL; WB_EA; } /* 7 ASL ABX */
+OP(3e) { int tmp; RD_ABX_NP; WB_EA; ROL; WB_EA; } /* 7 ROL ABX */
+OP(5e) { int tmp; RD_ABX_NP; WB_EA; LSR; WB_EA; } /* 7 LSR ABX */
+OP(7e) { int tmp; RD_ABX_NP; WB_EA; ROR; WB_EA; } /* 7 ROR ABX */
+OP(9e) { int tmp; EA_ABY_NP; SXH; WB_EA; } /* 5 SXH ABY */
+OP(be) { int tmp; RD_ABY_P; LDX; } /* 4 LDX ABY page penalty */
+OP(de) { int tmp; RD_ABX_NP; WB_EA; DEC; WB_EA; } /* 7 DEC ABX */
+OP(fe) { int tmp; RD_ABX_NP; WB_EA; INC; WB_EA; } /* 7 INC ABX */
+
+OP(0f) { int tmp; RD_ABS; WB_EA; SLO; WB_EA; } /* 6 SLO ABS */
+OP(2f) { int tmp; RD_ABS; WB_EA; RLA; WB_EA; } /* 6 RLA ABS */
+OP(4f) { int tmp; RD_ABS; WB_EA; SRE; WB_EA; } /* 6 SRE ABS */
+OP(6f) { int tmp; RD_ABS; WB_EA; RRA; WB_EA; } /* 6 RRA ABS */
+OP(8f) { int tmp; SAX; WR_ABS; } /* 4 SAX ABS */
+OP(af) { int tmp; RD_ABS; LAX; } /* 4 LAX ABS */
+OP(cf) { int tmp; RD_ABS; WB_EA; DCP; WB_EA; } /* 6 DCP ABS */
+OP(ef) { int tmp; RD_ABS; WB_EA; ISB; WB_EA; } /* 6 ISB ABS */
+
+OP(1f) { int tmp; RD_ABX_NP; WB_EA; SLO; WB_EA; } /* 7 SLO ABX */
+OP(3f) { int tmp; RD_ABX_NP; WB_EA; RLA; WB_EA; } /* 7 RLA ABX */
+OP(5f) { int tmp; RD_ABX_NP; WB_EA; SRE; WB_EA; } /* 7 SRE ABX */
+OP(7f) { int tmp; RD_ABX_NP; WB_EA; RRA; WB_EA; } /* 7 RRA ABX */
+OP(9f) { int tmp; EA_ABY_NP; SAH; WB_EA; } /* 5 SAH ABY */
+OP(bf) { int tmp; RD_ABY_P; LAX; } /* 4 LAX ABY page penalty */
+OP(df) { int tmp; RD_ABX_NP; WB_EA; DCP; WB_EA; } /* 7 DCP ABX */
+OP(ff) { int tmp; RD_ABX_NP; WB_EA; ISB; WB_EA; } /* 7 ISB ABX */
+
+/* and here's the array of function pointers */
+
+static void (*const insn6502[0x100])(m6502_Regs *cpustate) = {
+ m6502_00,m6502_01,m6502_02,m6502_03,m6502_04,m6502_05,m6502_06,m6502_07,
+ m6502_08,m6502_09,m6502_0a,m6502_0b,m6502_0c,m6502_0d,m6502_0e,m6502_0f,
+ m6502_10,m6502_11,m6502_12,m6502_13,m6502_14,m6502_15,m6502_16,m6502_17,
+ m6502_18,m6502_19,m6502_1a,m6502_1b,m6502_1c,m6502_1d,m6502_1e,m6502_1f,
+ m6502_20,m6502_21,m6502_22,m6502_23,m6502_24,m6502_25,m6502_26,m6502_27,
+ m6502_28,m6502_29,m6502_2a,m6502_2b,m6502_2c,m6502_2d,m6502_2e,m6502_2f,
+ m6502_30,m6502_31,m6502_32,m6502_33,m6502_34,m6502_35,m6502_36,m6502_37,
+ m6502_38,m6502_39,m6502_3a,m6502_3b,m6502_3c,m6502_3d,m6502_3e,m6502_3f,
+ m6502_40,m6502_41,m6502_42,m6502_43,m6502_44,m6502_45,m6502_46,m6502_47,
+ m6502_48,m6502_49,m6502_4a,m6502_4b,m6502_4c,m6502_4d,m6502_4e,m6502_4f,
+ m6502_50,m6502_51,m6502_52,m6502_53,m6502_54,m6502_55,m6502_56,m6502_57,
+ m6502_58,m6502_59,m6502_5a,m6502_5b,m6502_5c,m6502_5d,m6502_5e,m6502_5f,
+ m6502_60,m6502_61,m6502_62,m6502_63,m6502_64,m6502_65,m6502_66,m6502_67,
+ m6502_68,m6502_69,m6502_6a,m6502_6b,m6502_6c,m6502_6d,m6502_6e,m6502_6f,
+ m6502_70,m6502_71,m6502_72,m6502_73,m6502_74,m6502_75,m6502_76,m6502_77,
+ m6502_78,m6502_79,m6502_7a,m6502_7b,m6502_7c,m6502_7d,m6502_7e,m6502_7f,
+ m6502_80,m6502_81,m6502_82,m6502_83,m6502_84,m6502_85,m6502_86,m6502_87,
+ m6502_88,m6502_89,m6502_8a,m6502_8b,m6502_8c,m6502_8d,m6502_8e,m6502_8f,
+ m6502_90,m6502_91,m6502_92,m6502_93,m6502_94,m6502_95,m6502_96,m6502_97,
+ m6502_98,m6502_99,m6502_9a,m6502_9b,m6502_9c,m6502_9d,m6502_9e,m6502_9f,
+ m6502_a0,m6502_a1,m6502_a2,m6502_a3,m6502_a4,m6502_a5,m6502_a6,m6502_a7,
+ m6502_a8,m6502_a9,m6502_aa,m6502_ab,m6502_ac,m6502_ad,m6502_ae,m6502_af,
+ m6502_b0,m6502_b1,m6502_b2,m6502_b3,m6502_b4,m6502_b5,m6502_b6,m6502_b7,
+ m6502_b8,m6502_b9,m6502_ba,m6502_bb,m6502_bc,m6502_bd,m6502_be,m6502_bf,
+ m6502_c0,m6502_c1,m6502_c2,m6502_c3,m6502_c4,m6502_c5,m6502_c6,m6502_c7,
+ m6502_c8,m6502_c9,m6502_ca,m6502_cb,m6502_cc,m6502_cd,m6502_ce,m6502_cf,
+ m6502_d0,m6502_d1,m6502_d2,m6502_d3,m6502_d4,m6502_d5,m6502_d6,m6502_d7,
+ m6502_d8,m6502_d9,m6502_da,m6502_db,m6502_dc,m6502_dd,m6502_de,m6502_df,
+ m6502_e0,m6502_e1,m6502_e2,m6502_e3,m6502_e4,m6502_e5,m6502_e6,m6502_e7,
+ m6502_e8,m6502_e9,m6502_ea,m6502_eb,m6502_ec,m6502_ed,m6502_ee,m6502_ef,
+ m6502_f0,m6502_f1,m6502_f2,m6502_f3,m6502_f4,m6502_f5,m6502_f6,m6502_f7,
+ m6502_f8,m6502_f9,m6502_fa,m6502_fb,m6502_fc,m6502_fd,m6502_fe,m6502_ff
+};
+
diff --git a/trunk/src/emu/cpu/m6502/t6509.c b/trunk/src/emu/cpu/m6502/t6509.c
new file mode 100644
index 00000000000..9803a7f325a
--- /dev/null
+++ b/trunk/src/emu/cpu/m6502/t6509.c
@@ -0,0 +1,352 @@
+/*****************************************************************************
+ *
+ * tbl6509.c
+ * 6509 opcode functions and function pointer table
+ *
+ * Copyright Peter Trauner, all rights reserved.
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * pullmoll@t-online.de
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ * - Opcode information based on an Intel 386 '6510.asm' core
+ * written by R.F. van Ee (1993)
+ * - Cycle counts are guesswork :-)
+ *
+ *****************************************************************************/
+
+#undef OP
+#define OP(nn) INLINE void m6509_##nn(m6509_Regs *cpustate)
+
+OP(00) { BRK; } /* 7 BRK */
+OP(20) { JSR; } /* 6 JSR */
+OP(40) { RTI; } /* 6 RTI */
+OP(60) { RTS; } /* 6 RTS */
+OP(80) { RD_IMM_DISCARD; NOP; } /* 2 NOP IMM */
+OP(a0) { int tmp; RD_IMM; LDY; } /* 2 LDY IMM */
+OP(c0) { int tmp; RD_IMM; CPY; } /* 2 CPY IMM */
+OP(e0) { int tmp; RD_IMM; CPX; } /* 2 CPX IMM */
+
+OP(10) { int tmp; BPL; } /* 2-4 BPL REL */
+OP(30) { int tmp; BMI; } /* 2-4 BMI REL */
+OP(50) { int tmp; BVC; } /* 2-4 BVC REL */
+OP(70) { int tmp; BVS; } /* 2-4 BVS REL */
+OP(90) { int tmp; BCC; } /* 2-4 BCC REL */
+OP(b0) { int tmp; BCS; } /* 2-4 BCS REL */
+OP(d0) { int tmp; BNE; } /* 2-4 BNE REL */
+OP(f0) { int tmp; BEQ; } /* 2-4 BEQ REL */
+
+OP(01) { int tmp; RD_IDX; ORA; } /* 6 ORA IDX */
+OP(21) { int tmp; RD_IDX; AND; } /* 6 AND IDX */
+OP(41) { int tmp; RD_IDX; EOR; } /* 6 EOR IDX */
+OP(61) { int tmp; RD_IDX; ADC; } /* 6 ADC IDX */
+OP(81) { int tmp; STA; WR_IDX; } /* 6 STA IDX */
+OP(a1) { int tmp; RD_IDX; LDA; } /* 6 LDA IDX */
+OP(c1) { int tmp; RD_IDX; CMP; } /* 6 CMP IDX */
+OP(e1) { int tmp; RD_IDX; SBC; } /* 6 SBC IDX */
+
+OP(11) { int tmp; RD_IDY_P; ORA; } /* 5 ORA IDY page penalty */
+OP(31) { int tmp; RD_IDY_P; AND; } /* 5 AND IDY page penalty */
+OP(51) { int tmp; RD_IDY_P; EOR; } /* 5 EOR IDY page penalty */
+OP(71) { int tmp; RD_IDY_P; ADC; } /* 5 ADC IDY page penalty */
+OP(91) { int tmp; STA; WR_IDY_6509; } /* 6 STA IDY */
+OP(b1) { int tmp; RD_IDY_6509; LDA; } /* 5 LDA IDY page penalty */
+OP(d1) { int tmp; RD_IDY_P; CMP; } /* 5 CMP IDY page penalty */
+OP(f1) { int tmp; RD_IDY_P; SBC; } /* 5 SBC IDY page penalty */
+
+OP(02) { KIL; } /* 1 KIL */
+OP(22) { KIL; } /* 1 KIL */
+OP(42) { KIL; } /* 1 KIL */
+OP(62) { KIL; } /* 1 KIL */
+OP(82) { RD_IMM_DISCARD; NOP; } /* 2 NOP IMM */
+OP(a2) { int tmp; RD_IMM; LDX; } /* 2 LDX IMM */
+OP(c2) { RD_IMM_DISCARD; NOP; } /* 2 NOP IMM */
+OP(e2) { RD_IMM_DISCARD; NOP; } /* 2 NOP IMM */
+
+OP(12) { KIL; } /* 1 KIL */
+OP(32) { KIL; } /* 1 KIL */
+OP(52) { KIL; } /* 1 KIL */
+OP(72) { KIL; } /* 1 KIL */
+OP(92) { KIL; } /* 1 KIL */
+OP(b2) { KIL; } /* 1 KIL */
+OP(d2) { KIL; } /* 1 KIL */
+OP(f2) { KIL; } /* 1 KIL */
+
+OP(03) { int tmp; RD_IDX; WB_EA; SLO; WB_EA; } /* 7 SLO IDX */
+OP(23) { int tmp; RD_IDX; WB_EA; RLA; WB_EA; } /* 7 RLA IDX */
+OP(43) { int tmp; RD_IDX; WB_EA; SRE; WB_EA; } /* 7 SRE IDX */
+OP(63) { int tmp; RD_IDX; WB_EA; RRA; WB_EA; } /* 7 RRA IDX */
+OP(83) { int tmp; SAX; WR_IDX; } /* 6 SAX IDX */
+OP(a3) { int tmp; RD_IDX; LAX; } /* 6 LAX IDX */
+OP(c3) { int tmp; RD_IDX; WB_EA; DCP; WB_EA; } /* 7 DCP IDX */
+OP(e3) { int tmp; RD_IDX; WB_EA; ISB; WB_EA; } /* 7 ISB IDX */
+
+OP(13) { int tmp; RD_IDY_NP; WB_EA; SLO; WB_EA; } /* 7 SLO IDY */
+OP(33) { int tmp; RD_IDY_NP; WB_EA; RLA; WB_EA; } /* 7 RLA IDY */
+OP(53) { int tmp; RD_IDY_NP; WB_EA; SRE; WB_EA; } /* 7 SRE IDY */
+OP(73) { int tmp; RD_IDY_NP; WB_EA; RRA; WB_EA; } /* 7 RRA IDY */
+OP(93) { int tmp; EA_IDY_NP; SAH; WB_EA; } /* 5 SAH IDY */
+OP(b3) { int tmp; RD_IDY_P; LAX; } /* 5 LAX IDY page penalty */
+OP(d3) { int tmp; RD_IDY_NP; WB_EA; DCP; WB_EA; } /* 7 DCP IDY */
+OP(f3) { int tmp; RD_IDY_NP; WB_EA; ISB; WB_EA; } /* 7 ISB IDY */
+
+OP(04) { RD_ZPG_DISCARD; NOP; } /* 3 NOP ZPG */
+OP(24) { int tmp; RD_ZPG; BIT; } /* 3 BIT ZPG */
+OP(44) { RD_ZPG_DISCARD; NOP; } /* 3 NOP ZPG */
+OP(64) { RD_ZPG_DISCARD; NOP; } /* 3 NOP ZPG */
+OP(84) { int tmp; STY; WR_ZPG; } /* 3 STY ZPG */
+OP(a4) { int tmp; RD_ZPG; LDY; } /* 3 LDY ZPG */
+OP(c4) { int tmp; RD_ZPG; CPY; } /* 3 CPY ZPG */
+OP(e4) { int tmp; RD_ZPG; CPX; } /* 3 CPX ZPG */
+
+OP(14) { RD_ZPX_DISCARD; NOP; } /* 4 NOP ZPX */
+OP(34) { RD_ZPX_DISCARD; NOP; } /* 4 NOP ZPX */
+OP(54) { RD_ZPX_DISCARD; NOP; } /* 4 NOP ZPX */
+OP(74) { RD_ZPX_DISCARD; NOP; } /* 4 NOP ZPX */
+OP(94) { int tmp; STY; WR_ZPX; } /* 4 STY ZPX */
+OP(b4) { int tmp; RD_ZPX; LDY; } /* 4 LDY ZPX */
+OP(d4) { RD_ZPX_DISCARD; NOP; } /* 4 NOP ZPX */
+OP(f4) { RD_ZPX_DISCARD; NOP; } /* 4 NOP ZPX */
+
+OP(05) { int tmp; RD_ZPG; ORA; } /* 3 ORA ZPG */
+OP(25) { int tmp; RD_ZPG; AND; } /* 3 AND ZPG */
+OP(45) { int tmp; RD_ZPG; EOR; } /* 3 EOR ZPG */
+OP(65) { int tmp; RD_ZPG; ADC; } /* 3 ADC ZPG */
+OP(85) { int tmp; STA; WR_ZPG; } /* 3 STA ZPG */
+OP(a5) { int tmp; RD_ZPG; LDA; } /* 3 LDA ZPG */
+OP(c5) { int tmp; RD_ZPG; CMP; } /* 3 CMP ZPG */
+OP(e5) { int tmp; RD_ZPG; SBC; } /* 3 SBC ZPG */
+
+OP(15) { int tmp; RD_ZPX; ORA; } /* 4 ORA ZPX */
+OP(35) { int tmp; RD_ZPX; AND; } /* 4 AND ZPX */
+OP(55) { int tmp; RD_ZPX; EOR; } /* 4 EOR ZPX */
+OP(75) { int tmp; RD_ZPX; ADC; } /* 4 ADC ZPX */
+OP(95) { int tmp; STA; WR_ZPX; } /* 4 STA ZPX */
+OP(b5) { int tmp; RD_ZPX; LDA; } /* 4 LDA ZPX */
+OP(d5) { int tmp; RD_ZPX; CMP; } /* 4 CMP ZPX */
+OP(f5) { int tmp; RD_ZPX; SBC; } /* 4 SBC ZPX */
+
+OP(06) { int tmp; RD_ZPG; WB_EA; ASL; WB_EA; } /* 5 ASL ZPG */
+OP(26) { int tmp; RD_ZPG; WB_EA; ROL; WB_EA; } /* 5 ROL ZPG */
+OP(46) { int tmp; RD_ZPG; WB_EA; LSR; WB_EA; } /* 5 LSR ZPG */
+OP(66) { int tmp; RD_ZPG; WB_EA; ROR; WB_EA; } /* 5 ROR ZPG */
+OP(86) { int tmp; STX; WR_ZPG; } /* 3 STX ZPG */
+OP(a6) { int tmp; RD_ZPG; LDX; } /* 3 LDX ZPG */
+OP(c6) { int tmp; RD_ZPG; WB_EA; DEC; WB_EA; } /* 5 DEC ZPG */
+OP(e6) { int tmp; RD_ZPG; WB_EA; INC; WB_EA; } /* 5 INC ZPG */
+
+OP(16) { int tmp; RD_ZPX; WB_EA; ASL; WB_EA; } /* 6 ASL ZPX */
+OP(36) { int tmp; RD_ZPX; WB_EA; ROL; WB_EA; } /* 6 ROL ZPX */
+OP(56) { int tmp; RD_ZPX; WB_EA; LSR; WB_EA; } /* 6 LSR ZPX */
+OP(76) { int tmp; RD_ZPX; WB_EA; ROR; WB_EA; } /* 6 ROR ZPX */
+OP(96) { int tmp; STX; WR_ZPY; } /* 4 STX ZPY */
+OP(b6) { int tmp; RD_ZPY; LDX; } /* 4 LDX ZPY */
+OP(d6) { int tmp; RD_ZPX; WB_EA; DEC; WB_EA; } /* 6 DEC ZPX */
+OP(f6) { int tmp; RD_ZPX; WB_EA; INC; WB_EA; } /* 6 INC ZPX */
+
+OP(07) { int tmp; RD_ZPG; WB_EA; SLO; WB_EA; } /* 5 SLO ZPG */
+OP(27) { int tmp; RD_ZPG; WB_EA; RLA; WB_EA; } /* 5 RLA ZPG */
+OP(47) { int tmp; RD_ZPG; WB_EA; SRE; WB_EA; } /* 5 SRE ZPG */
+OP(67) { int tmp; RD_ZPG; WB_EA; RRA; WB_EA; } /* 5 RRA ZPG */
+OP(87) { int tmp; SAX; WR_ZPG; } /* 3 SAX ZPG */
+OP(a7) { int tmp; RD_ZPG; LAX; } /* 3 LAX ZPG */
+OP(c7) { int tmp; RD_ZPG; WB_EA; DCP; WB_EA; } /* 5 DCP ZPG */
+OP(e7) { int tmp; RD_ZPG; WB_EA; ISB; WB_EA; } /* 5 ISB ZPG */
+
+OP(17) { int tmp; RD_ZPX; WB_EA; SLO; WB_EA; } /* 6 SLO ZPX */
+OP(37) { int tmp; RD_ZPX; WB_EA; RLA; WB_EA; } /* 6 RLA ZPX */
+OP(57) { int tmp; RD_ZPX; WB_EA; SRE; WB_EA; } /* 6 SRE ZPX */
+OP(77) { int tmp; RD_ZPX; WB_EA; RRA; WB_EA; } /* 6 RRA ZPX */
+OP(97) { int tmp; SAX; WR_ZPY; } /* 4 SAX ZPY */
+OP(b7) { int tmp; RD_ZPY; LAX; } /* 4 LAX ZPY */
+OP(d7) { int tmp; RD_ZPX; WB_EA; DCP; WB_EA; } /* 6 DCP ZPX */
+OP(f7) { int tmp; RD_ZPX; WB_EA; ISB; WB_EA; } /* 6 ISB ZPX */
+
+OP(08) { RD_DUM; PHP; } /* 3 PHP */
+OP(28) { RD_DUM; PLP; } /* 4 PLP */
+OP(48) { RD_DUM; PHA; } /* 3 PHA */
+OP(68) { RD_DUM; PLA; } /* 4 PLA */
+OP(88) { RD_DUM; DEY; } /* 2 DEY */
+OP(a8) { RD_DUM; TAY; } /* 2 TAY */
+OP(c8) { RD_DUM; INY; } /* 2 INY */
+OP(e8) { RD_DUM; INX; } /* 2 INX */
+
+OP(18) { RD_DUM; CLC; } /* 2 CLC */
+OP(38) { RD_DUM; SEC; } /* 2 SEC */
+OP(58) { RD_DUM; CLI; } /* 2 CLI */
+OP(78) { RD_DUM; SEI; } /* 2 SEI */
+OP(98) { RD_DUM; TYA; } /* 2 TYA */
+OP(b8) { RD_DUM; CLV; } /* 2 CLV */
+OP(d8) { RD_DUM; CLD; } /* 2 CLD */
+OP(f8) { RD_DUM; SED; } /* 2 SED */
+
+OP(09) { int tmp; RD_IMM; ORA; } /* 2 ORA IMM */
+OP(29) { int tmp; RD_IMM; AND; } /* 2 AND IMM */
+OP(49) { int tmp; RD_IMM; EOR; } /* 2 EOR IMM */
+OP(69) { int tmp; RD_IMM; ADC; } /* 2 ADC IMM */
+OP(89) { RD_IMM_DISCARD; NOP; } /* 2 NOP IMM */
+OP(a9) { int tmp; RD_IMM; LDA; } /* 2 LDA IMM */
+OP(c9) { int tmp; RD_IMM; CMP; } /* 2 CMP IMM */
+OP(e9) { int tmp; RD_IMM; SBC; } /* 2 SBC IMM */
+
+OP(19) { int tmp; RD_ABY_P; ORA; } /* 4 ORA ABY page penalty */
+OP(39) { int tmp; RD_ABY_P; AND; } /* 4 AND ABY page penalty */
+OP(59) { int tmp; RD_ABY_P; EOR; } /* 4 EOR ABY page penalty */
+OP(79) { int tmp; RD_ABY_P; ADC; } /* 4 ADC ABY page penalty */
+OP(99) { int tmp; STA; WR_ABY_NP; } /* 5 STA ABY */
+OP(b9) { int tmp; RD_ABY_P; LDA; } /* 4 LDA ABY page penalty */
+OP(d9) { int tmp; RD_ABY_P; CMP; } /* 4 CMP ABY page penalty */
+OP(f9) { int tmp; RD_ABY_P; SBC; } /* 4 SBC ABY page penalty */
+
+OP(0a) { int tmp; RD_DUM; RD_ACC; ASL; WB_ACC; } /* 2 ASL A */
+OP(2a) { int tmp; RD_DUM; RD_ACC; ROL; WB_ACC; } /* 2 ROL A */
+OP(4a) { int tmp; RD_DUM; RD_ACC; LSR; WB_ACC; } /* 2 LSR A */
+OP(6a) { int tmp; RD_DUM; RD_ACC; ROR; WB_ACC; } /* 2 ROR A */
+OP(8a) { RD_DUM; TXA; } /* 2 TXA */
+OP(aa) { RD_DUM; TAX; } /* 2 TAX */
+OP(ca) { RD_DUM; DEX; } /* 2 DEX */
+OP(ea) { RD_DUM; NOP; } /* 2 NOP */
+
+OP(1a) { RD_DUM; NOP; } /* 2 NOP */
+OP(3a) { RD_DUM; NOP; } /* 2 NOP */
+OP(5a) { RD_DUM; NOP; } /* 2 NOP */
+OP(7a) { RD_DUM; NOP; } /* 2 NOP */
+OP(9a) { RD_DUM; TXS; } /* 2 TXS */
+OP(ba) { RD_DUM; TSX; } /* 2 TSX */
+OP(da) { RD_DUM; NOP; } /* 2 NOP */
+OP(fa) { RD_DUM; NOP; } /* 2 NOP */
+
+OP(0b) { int tmp; RD_IMM; ANC; } /* 2 ANC IMM */
+OP(2b) { int tmp; RD_IMM; ANC; } /* 2 ANC IMM */
+OP(4b) { int tmp; RD_IMM; ASR; WB_ACC; } /* 2 ASR IMM */
+OP(6b) { int tmp; RD_IMM; ARR; WB_ACC; } /* 2 ARR IMM */
+OP(8b) { int tmp; RD_IMM; AXA; } /* 2 AXA IMM */
+OP(ab) { int tmp; RD_IMM; OAL; } /* 2 OAL IMM */
+OP(cb) { int tmp; RD_IMM; ASX; } /* 2 ASX IMM */
+OP(eb) { int tmp; RD_IMM; SBC; } /* 2 SBC IMM */
+
+OP(1b) { int tmp; RD_ABY_NP; WB_EA; SLO; WB_EA; } /* 7 SLO ABY */
+OP(3b) { int tmp; RD_ABY_NP; WB_EA; RLA; WB_EA; } /* 7 RLA ABY */
+OP(5b) { int tmp; RD_ABY_NP; WB_EA; SRE; WB_EA; } /* 7 SRE ABY */
+OP(7b) { int tmp; RD_ABY_NP; WB_EA; RRA; WB_EA; } /* 7 RRA ABY */
+OP(9b) { int tmp; EA_ABY_NP; SSH; WB_EA; } /* 5 SSH ABY */
+OP(bb) { int tmp; RD_ABY_P; AST; } /* 4 AST ABY page penalty */
+OP(db) { int tmp; RD_ABY_NP; WB_EA; DCP; WB_EA; } /* 7 DCP ABY */
+OP(fb) { int tmp; RD_ABY_NP; WB_EA; ISB; WB_EA; } /* 7 ISB ABY */
+
+OP(0c) { RD_ABS_DISCARD; NOP; } /* 4 NOP ABS */
+OP(2c) { int tmp; RD_ABS; BIT; } /* 4 BIT ABS */
+OP(4c) { EA_ABS; JMP; } /* 3 JMP ABS */
+OP(6c) { int tmp; EA_IND; JMP; } /* 5 JMP IND */
+OP(8c) { int tmp; STY; WR_ABS; } /* 4 STY ABS */
+OP(ac) { int tmp; RD_ABS; LDY; } /* 4 LDY ABS */
+OP(cc) { int tmp; RD_ABS; CPY; } /* 4 CPY ABS */
+OP(ec) { int tmp; RD_ABS; CPX; } /* 4 CPX ABS */
+
+OP(1c) { RD_ABX_P_DISCARD; NOP; } /* 4 NOP ABX page penalty */
+OP(3c) { RD_ABX_P_DISCARD; NOP; } /* 4 NOP ABX page penalty */
+OP(5c) { RD_ABX_P_DISCARD; NOP; } /* 4 NOP ABX page penalty */
+OP(7c) { RD_ABX_P_DISCARD; NOP; } /* 4 NOP ABX page penalty */
+OP(9c) { int tmp; EA_ABX_NP; SYH; WB_EA; } /* 5 SYH ABX */
+OP(bc) { int tmp; RD_ABX_P; LDY; } /* 4 LDY ABX page penalty */
+OP(dc) { RD_ABX_P_DISCARD; NOP; } /* 4 NOP ABX page penalty */
+OP(fc) { RD_ABX_P_DISCARD; NOP; } /* 4 NOP ABX page penalty */
+
+OP(0d) { int tmp; RD_ABS; ORA; } /* 4 ORA ABS */
+OP(2d) { int tmp; RD_ABS; AND; } /* 4 AND ABS */
+OP(4d) { int tmp; RD_ABS; EOR; } /* 4 EOR ABS */
+OP(6d) { int tmp; RD_ABS; ADC; } /* 4 ADC ABS */
+OP(8d) { int tmp; STA; WR_ABS; } /* 4 STA ABS */
+OP(ad) { int tmp; RD_ABS; LDA; } /* 4 LDA ABS */
+OP(cd) { int tmp; RD_ABS; CMP; } /* 4 CMP ABS */
+OP(ed) { int tmp; RD_ABS; SBC; } /* 4 SBC ABS */
+
+OP(1d) { int tmp; RD_ABX_P; ORA; } /* 4 ORA ABX page penalty */
+OP(3d) { int tmp; RD_ABX_P; AND; } /* 4 AND ABX page penalty */
+OP(5d) { int tmp; RD_ABX_P; EOR; } /* 4 EOR ABX page penalty */
+OP(7d) { int tmp; RD_ABX_P; ADC; } /* 4 ADC ABX page penalty */
+OP(9d) { int tmp; STA; WR_ABX_NP; } /* 5 STA ABX */
+OP(bd) { int tmp; RD_ABX_P; LDA; } /* 4 LDA ABX page penalty */
+OP(dd) { int tmp; RD_ABX_P; CMP; } /* 4 CMP ABX page penalty */
+OP(fd) { int tmp; RD_ABX_P; SBC; } /* 4 SBC ABX page penalty */
+
+OP(0e) { int tmp; RD_ABS; WB_EA; ASL; WB_EA; } /* 6 ASL ABS */
+OP(2e) { int tmp; RD_ABS; WB_EA; ROL; WB_EA; } /* 6 ROL ABS */
+OP(4e) { int tmp; RD_ABS; WB_EA; LSR; WB_EA; } /* 6 LSR ABS */
+OP(6e) { int tmp; RD_ABS; WB_EA; ROR; WB_EA; } /* 6 ROR ABS */
+OP(8e) { int tmp; STX; WR_ABS; } /* 4 STX ABS */
+OP(ae) { int tmp; RD_ABS; LDX; } /* 4 LDX ABS */
+OP(ce) { int tmp; RD_ABS; WB_EA; DEC; WB_EA; } /* 6 DEC ABS */
+OP(ee) { int tmp; RD_ABS; WB_EA; INC; WB_EA; } /* 6 INC ABS */
+
+OP(1e) { int tmp; RD_ABX_NP; WB_EA; ASL; WB_EA; } /* 7 ASL ABX */
+OP(3e) { int tmp; RD_ABX_NP; WB_EA; ROL; WB_EA; } /* 7 ROL ABX */
+OP(5e) { int tmp; RD_ABX_NP; WB_EA; LSR; WB_EA; } /* 7 LSR ABX */
+OP(7e) { int tmp; RD_ABX_NP; WB_EA; ROR; WB_EA; } /* 7 ROR ABX */
+OP(9e) { int tmp; EA_ABY_NP; SXH; WB_EA; } /* 5 SXH ABY */
+OP(be) { int tmp; RD_ABY_P; LDX; } /* 4 LDX ABY page penalty */
+OP(de) { int tmp; RD_ABX_NP; WB_EA; DEC; WB_EA; } /* 7 DEC ABX */
+OP(fe) { int tmp; RD_ABX_NP; WB_EA; INC; WB_EA; } /* 7 INC ABX */
+
+OP(0f) { int tmp; RD_ABS; WB_EA; SLO; WB_EA; } /* 6 SLO ABS */
+OP(2f) { int tmp; RD_ABS; WB_EA; RLA; WB_EA; } /* 6 RLA ABS */
+OP(4f) { int tmp; RD_ABS; WB_EA; SRE; WB_EA; } /* 6 SRE ABS */
+OP(6f) { int tmp; RD_ABS; WB_EA; RRA; WB_EA; } /* 6 RRA ABS */
+OP(8f) { int tmp; SAX; WR_ABS; } /* 4 SAX ABS */
+OP(af) { int tmp; RD_ABS; LAX; } /* 4 LAX ABS */
+OP(cf) { int tmp; RD_ABS; WB_EA; DCP; WB_EA; } /* 6 DCP ABS */
+OP(ef) { int tmp; RD_ABS; WB_EA; ISB; WB_EA; } /* 6 ISB ABS */
+
+OP(1f) { int tmp; RD_ABX_NP; WB_EA; SLO; WB_EA; } /* 7 SLO ABX */
+OP(3f) { int tmp; RD_ABX_NP; WB_EA; RLA; WB_EA; } /* 7 RLA ABX */
+OP(5f) { int tmp; RD_ABX_NP; WB_EA; SRE; WB_EA; } /* 7 SRE ABX */
+OP(7f) { int tmp; RD_ABX_NP; WB_EA; RRA; WB_EA; } /* 7 RRA ABX */
+OP(9f) { int tmp; EA_ABY_NP; SAH; WB_EA; } /* 5 SAH ABY */
+OP(bf) { int tmp; RD_ABY_P; LAX; } /* 4 LAX ABY page penalty */
+OP(df) { int tmp; RD_ABX_NP; WB_EA; DCP; WB_EA; } /* 7 DCP ABX */
+OP(ff) { int tmp; RD_ABX_NP; WB_EA; ISB; WB_EA; } /* 7 ISB ABX */
+
+static void (*const insn6509[0x100])(m6509_Regs *) = {
+ m6509_00,m6509_01,m6509_02,m6509_03,m6509_04,m6509_05,m6509_06,m6509_07,
+ m6509_08,m6509_09,m6509_0a,m6509_0b,m6509_0c,m6509_0d,m6509_0e,m6509_0f,
+ m6509_10,m6509_11,m6509_12,m6509_13,m6509_14,m6509_15,m6509_16,m6509_17,
+ m6509_18,m6509_19,m6509_1a,m6509_1b,m6509_1c,m6509_1d,m6509_1e,m6509_1f,
+ m6509_20,m6509_21,m6509_22,m6509_23,m6509_24,m6509_25,m6509_26,m6509_27,
+ m6509_28,m6509_29,m6509_2a,m6509_2b,m6509_2c,m6509_2d,m6509_2e,m6509_2f,
+ m6509_30,m6509_31,m6509_32,m6509_33,m6509_34,m6509_35,m6509_36,m6509_37,
+ m6509_38,m6509_39,m6509_3a,m6509_3b,m6509_3c,m6509_3d,m6509_3e,m6509_3f,
+ m6509_40,m6509_41,m6509_42,m6509_43,m6509_44,m6509_45,m6509_46,m6509_47,
+ m6509_48,m6509_49,m6509_4a,m6509_4b,m6509_4c,m6509_4d,m6509_4e,m6509_4f,
+ m6509_50,m6509_51,m6509_52,m6509_53,m6509_54,m6509_55,m6509_56,m6509_57,
+ m6509_58,m6509_59,m6509_5a,m6509_5b,m6509_5c,m6509_5d,m6509_5e,m6509_5f,
+ m6509_60,m6509_61,m6509_62,m6509_63,m6509_64,m6509_65,m6509_66,m6509_67,
+ m6509_68,m6509_69,m6509_6a,m6509_6b,m6509_6c,m6509_6d,m6509_6e,m6509_6f,
+ m6509_70,m6509_71,m6509_72,m6509_73,m6509_74,m6509_75,m6509_76,m6509_77,
+ m6509_78,m6509_79,m6509_7a,m6509_7b,m6509_7c,m6509_7d,m6509_7e,m6509_7f,
+ m6509_80,m6509_81,m6509_82,m6509_83,m6509_84,m6509_85,m6509_86,m6509_87,
+ m6509_88,m6509_89,m6509_8a,m6509_8b,m6509_8c,m6509_8d,m6509_8e,m6509_8f,
+ m6509_90,m6509_91,m6509_92,m6509_93,m6509_94,m6509_95,m6509_96,m6509_97,
+ m6509_98,m6509_99,m6509_9a,m6509_9b,m6509_9c,m6509_9d,m6509_9e,m6509_9f,
+ m6509_a0,m6509_a1,m6509_a2,m6509_a3,m6509_a4,m6509_a5,m6509_a6,m6509_a7,
+ m6509_a8,m6509_a9,m6509_aa,m6509_ab,m6509_ac,m6509_ad,m6509_ae,m6509_af,
+ m6509_b0,m6509_b1,m6509_b2,m6509_b3,m6509_b4,m6509_b5,m6509_b6,m6509_b7,
+ m6509_b8,m6509_b9,m6509_ba,m6509_bb,m6509_bc,m6509_bd,m6509_be,m6509_bf,
+ m6509_c0,m6509_c1,m6509_c2,m6509_c3,m6509_c4,m6509_c5,m6509_c6,m6509_c7,
+ m6509_c8,m6509_c9,m6509_ca,m6509_cb,m6509_cc,m6509_cd,m6509_ce,m6509_cf,
+ m6509_d0,m6509_d1,m6509_d2,m6509_d3,m6509_d4,m6509_d5,m6509_d6,m6509_d7,
+ m6509_d8,m6509_d9,m6509_da,m6509_db,m6509_dc,m6509_dd,m6509_de,m6509_df,
+ m6509_e0,m6509_e1,m6509_e2,m6509_e3,m6509_e4,m6509_e5,m6509_e6,m6509_e7,
+ m6509_e8,m6509_e9,m6509_ea,m6509_eb,m6509_ec,m6509_ed,m6509_ee,m6509_ef,
+ m6509_f0,m6509_f1,m6509_f2,m6509_f3,m6509_f4,m6509_f5,m6509_f6,m6509_f7,
+ m6509_f8,m6509_f9,m6509_fa,m6509_fb,m6509_fc,m6509_fd,m6509_fe,m6509_ff
+};
+
+
diff --git a/trunk/src/emu/cpu/m6502/t6510.c b/trunk/src/emu/cpu/m6502/t6510.c
new file mode 100644
index 00000000000..59e473046fb
--- /dev/null
+++ b/trunk/src/emu/cpu/m6502/t6510.c
@@ -0,0 +1,27 @@
+/*****************************************************************************
+ *
+ * tbl6510.c
+ * 6510 opcode functions and function pointer table
+ *
+ * Copyright Juergen Buchmueller, all rights reserved.
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * pullmoll@t-online.de
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ * - Opcode information based on an Intel 386 '6510.asm' core
+ * written by R.F. van Ee (1993)
+ * - Cycle counts are guesswork :-)
+ *
+ *****************************************************************************/
+
+#define insn6510 insn6502
+
diff --git a/trunk/src/emu/cpu/m6502/t65c02.c b/trunk/src/emu/cpu/m6502/t65c02.c
new file mode 100644
index 00000000000..679c5c0f23e
--- /dev/null
+++ b/trunk/src/emu/cpu/m6502/t65c02.c
@@ -0,0 +1,410 @@
+/*****************************************************************************
+ *
+ * tbl65c02.c
+ * 65c02 opcode functions and function pointer table
+ *
+ * Copyright Juergen Buchmueller, all rights reserved.
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * pullmoll@t-online.de
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ * Not sure about the timing of all the extra (undocumented) NOP instructions.
+ * Core may need to be split up into two 65c02 core. Not all versions supported
+ * the bit operation RMB/SMB/etc.
+ *
+ *****************************************************************************/
+
+#undef OP
+#define OP(nn) INLINE void m65c02_##nn(m6502_Regs *cpustate)
+
+/*****************************************************************************
+ *****************************************************************************
+ *
+ * Implementations for 65C02 opcodes
+ *
+ * There are a few slight differences between Rockwell and WDC 65C02 CPUs.
+ * The absolute indexed addressing mode RMW instructions take 6 cycles on
+ * WDC 65C02 CPU but 7 cycles on a regular 6502 and a Rockwell 65C02 CPU.
+ * TODO: Implement STP and WAI for wdc65c02.
+ *
+ *****************************************************************************
+ * op temp cycles rdmem opc wrmem ********************/
+OP(00) { BRK_C02; } /* 7 BRK */
+OP(20) { JSR; } /* 6 JSR */
+OP(40) { RTI; } /* 6 RTI */
+OP(60) { RTS; } /* 6 RTS */
+OP(80) { int tmp; BRA_C02( 1 ); } /* 3-4 BRA REL */
+OP(a0) { int tmp; RD_IMM; LDY; } /* 2 LDY IMM */
+OP(c0) { int tmp; RD_IMM; CPY; } /* 2 CPY IMM */
+OP(e0) { int tmp; RD_IMM; CPX; } /* 2 CPX IMM */
+
+OP(10) { int tmp; BRA_C02( ! ( P & F_N ) ); } /* 2-4 BPL REL */
+OP(30) { int tmp; BRA_C02( ( P & F_N ) ); } /* 2-4 BMI REL */
+OP(50) { int tmp; BRA_C02( ! ( P & F_V ) ); } /* 2-4 BVC REL */
+OP(70) { int tmp; BRA_C02( ( P & F_V ) ); } /* 2-4 BVS REL */
+OP(90) { int tmp; BRA_C02( ! ( P & F_C ) ); } /* 2-4 BCC REL */
+OP(b0) { int tmp; BRA_C02( ( P & F_C ) ); } /* 2-4 BCS REL */
+OP(d0) { int tmp; BRA_C02( ! ( P & F_Z ) ); } /* 2-4 BNE REL */
+OP(f0) { int tmp; BRA_C02( ( P & F_Z ) ); } /* 2-4 BEQ REL */
+
+OP(01) { int tmp; RD_IDX; ORA; } /* 6 ORA IDX */
+OP(21) { int tmp; RD_IDX; AND; } /* 6 AND IDX */
+OP(41) { int tmp; RD_IDX; EOR; } /* 6 EOR IDX */
+OP(61) { int tmp; RD_IDX; ADC_C02; } /* 6/7 ADC IDX */
+OP(81) { int tmp; STA; WR_IDX; } /* 6 STA IDX */
+OP(a1) { int tmp; RD_IDX; LDA; } /* 6 LDA IDX */
+OP(c1) { int tmp; RD_IDX; CMP; } /* 6 CMP IDX */
+OP(e1) { int tmp; RD_IDX; SBC_C02; } /* 6/7 SBC IDX */
+
+OP(11) { int tmp; RD_IDY_C02_P; ORA; } /* 5 ORA IDY page penalty */
+OP(31) { int tmp; RD_IDY_C02_P; AND; } /* 5 AND IDY page penalty */
+OP(51) { int tmp; RD_IDY_C02_P; EOR; } /* 5 EOR IDY page penalty */
+OP(71) { int tmp; RD_IDY_C02_P; ADC_C02; } /* 5/6 ADC IDY page penalty */
+OP(91) { int tmp; STA; WR_IDY_C02_NP; } /* 6 STA IDY */
+OP(b1) { int tmp; RD_IDY_C02_P; LDA; } /* 5 LDA IDY page penalty */
+OP(d1) { int tmp; RD_IDY_C02_P; CMP; } /* 5 CMP IDY page penalty */
+OP(f1) { int tmp; RD_IDY_C02_P; SBC_C02; } /* 5/6 SBC IDY page penalty */
+
+OP(02) { RD_IMM_DISCARD; NOP; } /* 2 NOP not sure for rockwell */
+OP(22) { RD_IMM_DISCARD; NOP; } /* 2 NOP not sure for rockwell */
+OP(42) { RD_IMM_DISCARD; NOP; } /* 2 NOP not sure for rockwell */
+OP(62) { RD_IMM_DISCARD; NOP; } /* 2 NOP not sure for rockwell */
+OP(82) { RD_IMM_DISCARD; NOP; } /* 2 NOP not sure for rockwell */
+OP(a2) { int tmp; RD_IMM; LDX; } /* 2 LDX IMM */
+OP(c2) { RD_IMM_DISCARD; NOP; } /* 2 NOP not sure for rockwell */
+OP(e2) { RD_IMM_DISCARD; NOP; } /* 2 NOP not sure for rockwell */
+
+OP(12) { int tmp; RD_ZPI; ORA; } /* 5 ORA ZPI */
+OP(32) { int tmp; RD_ZPI; AND; } /* 5 AND ZPI */
+OP(52) { int tmp; RD_ZPI; EOR; } /* 5 EOR ZPI */
+OP(72) { int tmp; RD_ZPI; ADC_C02; } /* 5/6 ADC ZPI */
+OP(92) { int tmp; STA; WR_ZPI; } /* 5 STA ZPI */
+OP(b2) { int tmp; RD_ZPI; LDA; } /* 5 LDA ZPI */
+OP(d2) { int tmp; RD_ZPI; CMP; } /* 5 CMP ZPI */
+OP(f2) { int tmp; RD_ZPI; SBC_C02; } /* 5/6 SBC ZPI */
+
+OP(03) { NOP; } /* 1 NOP not sure for rockwell */
+OP(23) { NOP; } /* 1 NOP not sure for rockwell */
+OP(43) { NOP; } /* 1 NOP not sure for rockwell */
+OP(63) { NOP; } /* 1 NOP not sure for rockwell */
+OP(83) { NOP; } /* 1 NOP not sure for rockwell */
+OP(a3) { NOP; } /* 1 NOP not sure for rockwell */
+OP(c3) { NOP; } /* 1 NOP not sure for rockwell */
+OP(e3) { NOP; } /* 1 NOP not sure for rockwell */
+
+OP(13) { NOP; } /* 1 NOP not sure for rockwell */
+OP(33) { NOP; } /* 1 NOP not sure for rockwell */
+OP(53) { NOP; } /* 1 NOP not sure for rockwell */
+OP(73) { NOP; } /* 1 NOP not sure for rockwell */
+OP(93) { NOP; } /* 1 NOP not sure for rockwell */
+OP(b3) { NOP; } /* 1 NOP not sure for rockwell */
+OP(d3) { NOP; } /* 1 NOP not sure for rockwell */
+OP(f3) { NOP; } /* 1 NOP not sure for rockwell */
+
+OP(04) { int tmp; RD_ZPG; RD_EA; TSB; WB_EA; } /* 5 TSB ZPG */
+OP(24) { int tmp; RD_ZPG; BIT; } /* 3 BIT ZPG */
+OP(44) { RD_ZPG_DISCARD; NOP; } /* 3 NOP not sure for rockwell */
+OP(64) { int tmp; STZ; WR_ZPG; } /* 3 STZ ZPG */
+OP(84) { int tmp; STY; WR_ZPG; } /* 3 STY ZPG */
+OP(a4) { int tmp; RD_ZPG; LDY; } /* 3 LDY ZPG */
+OP(c4) { int tmp; RD_ZPG; CPY; } /* 3 CPY ZPG */
+OP(e4) { int tmp; RD_ZPG; CPX; } /* 3 CPX ZPG */
+
+OP(14) { int tmp; RD_ZPG; RD_EA; TRB; WB_EA; } /* 5 TRB ZPG */
+OP(34) { int tmp; RD_ZPX; BIT; } /* 4 BIT ZPX */
+OP(54) { RD_ZPX_DISCARD; NOP; } /* 4 NOP not sure for rockwell */
+OP(74) { int tmp; STZ; WR_ZPX; } /* 4 STZ ZPX */
+OP(94) { int tmp; STY; WR_ZPX; } /* 4 STY ZPX */
+OP(b4) { int tmp; RD_ZPX; LDY; } /* 4 LDY ZPX */
+OP(d4) { RD_ZPX_DISCARD; NOP; } /* 4 NOP not sure for rockwell */
+OP(f4) { RD_ZPX_DISCARD; NOP; } /* 4 NOP not sure for rockwell */
+
+OP(05) { int tmp; RD_ZPG; ORA; } /* 3 ORA ZPG */
+OP(25) { int tmp; RD_ZPG; AND; } /* 3 AND ZPG */
+OP(45) { int tmp; RD_ZPG; EOR; } /* 3 EOR ZPG */
+OP(65) { int tmp; RD_ZPG; ADC_C02; } /* 3/4 ADC ZPG */
+OP(85) { int tmp; STA; WR_ZPG; } /* 3 STA ZPG */
+OP(a5) { int tmp; RD_ZPG; LDA; } /* 3 LDA ZPG */
+OP(c5) { int tmp; RD_ZPG; CMP; } /* 3 CMP ZPG */
+OP(e5) { int tmp; RD_ZPG; SBC_C02; } /* 3/4 SBC ZPG */
+
+OP(15) { int tmp; RD_ZPX; ORA; } /* 4 ORA ZPX */
+OP(35) { int tmp; RD_ZPX; AND; } /* 4 AND ZPX */
+OP(55) { int tmp; RD_ZPX; EOR; } /* 4 EOR ZPX */
+OP(75) { int tmp; RD_ZPX; ADC_C02; } /* 4/5 ADC ZPX */
+OP(95) { int tmp; STA; WR_ZPX; } /* 4 STA ZPX */
+OP(b5) { int tmp; RD_ZPX; LDA; } /* 4 LDA ZPX */
+OP(d5) { int tmp; RD_ZPX; CMP; } /* 4 CMP ZPX */
+OP(f5) { int tmp; RD_ZPX; SBC_C02; } /* 4/5 SBC ZPX */
+
+OP(06) { int tmp; RD_ZPG, RD_EA; ASL; WB_EA; } /* 5 ASL ZPG */
+OP(26) { int tmp; RD_ZPG; RD_EA; ROL; WB_EA; } /* 5 ROL ZPG */
+OP(46) { int tmp; RD_ZPG; RD_EA; LSR; WB_EA; } /* 5 LSR ZPG */
+OP(66) { int tmp; RD_ZPG; RD_EA; ROR; WB_EA; } /* 5 ROR ZPG */
+OP(86) { int tmp; STX; WR_ZPG; } /* 3 STX ZPG */
+OP(a6) { int tmp; RD_ZPG; LDX; } /* 3 LDX ZPG */
+OP(c6) { int tmp; RD_ZPG; RD_EA; DEC; WB_EA; } /* 5 DEC ZPG */
+OP(e6) { int tmp; RD_ZPG; RD_EA; INC; WB_EA; } /* 5 INC ZPG */
+
+OP(16) { int tmp; RD_ZPX; RD_EA; ASL; WB_EA; } /* 6 ASL ZPX */
+OP(36) { int tmp; RD_ZPX; RD_EA; ROL; WB_EA; } /* 6 ROL ZPX */
+OP(56) { int tmp; RD_ZPX; RD_EA; LSR; WB_EA; } /* 6 LSR ZPX */
+OP(76) { int tmp; RD_ZPX; RD_EA; ROR; WB_EA; } /* 6 ROR ZPX */
+OP(96) { int tmp; STX; WR_ZPY; } /* 4 STX ZPY */
+OP(b6) { int tmp; RD_ZPY; LDX; } /* 4 LDX ZPY */
+OP(d6) { int tmp; RD_ZPX; RD_EA; DEC; WB_EA; } /* 6 DEC ZPX */
+OP(f6) { int tmp; RD_ZPX; RD_EA; INC; WB_EA; } /* 6 INC ZPX */
+
+OP(07) { int tmp; RD_ZPG; RD_EA; RMB(0);WB_EA; } /* 5 RMB0 ZPG */
+OP(27) { int tmp; RD_ZPG; RD_EA; RMB(2);WB_EA; } /* 5 RMB2 ZPG */
+OP(47) { int tmp; RD_ZPG; RD_EA; RMB(4);WB_EA; } /* 5 RMB4 ZPG */
+OP(67) { int tmp; RD_ZPG; RD_EA; RMB(6);WB_EA; } /* 5 RMB6 ZPG */
+OP(87) { int tmp; RD_ZPG; RD_EA; SMB(0);WB_EA; } /* 5 SMB0 ZPG */
+OP(a7) { int tmp; RD_ZPG; RD_EA; SMB(2);WB_EA; } /* 5 SMB2 ZPG */
+OP(c7) { int tmp; RD_ZPG; RD_EA; SMB(4);WB_EA; } /* 5 SMB4 ZPG */
+OP(e7) { int tmp; RD_ZPG; RD_EA; SMB(6);WB_EA; } /* 5 SMB6 ZPG */
+
+OP(17) { int tmp; RD_ZPG; RD_EA; RMB(1);WB_EA; } /* 5 RMB1 ZPG */
+OP(37) { int tmp; RD_ZPG; RD_EA; RMB(3);WB_EA; } /* 5 RMB3 ZPG */
+OP(57) { int tmp; RD_ZPG; RD_EA; RMB(5);WB_EA; } /* 5 RMB5 ZPG */
+OP(77) { int tmp; RD_ZPG; RD_EA; RMB(7);WB_EA; } /* 5 RMB7 ZPG */
+OP(97) { int tmp; RD_ZPG; RD_EA; SMB(1);WB_EA; } /* 5 SMB1 ZPG */
+OP(b7) { int tmp; RD_ZPG; RD_EA; SMB(3);WB_EA; } /* 5 SMB3 ZPG */
+OP(d7) { int tmp; RD_ZPG; RD_EA; SMB(5);WB_EA; } /* 5 SMB5 ZPG */
+OP(f7) { int tmp; RD_ZPG; RD_EA; SMB(7);WB_EA; } /* 5 SMB7 ZPG */
+
+OP(08) { RD_DUM; PHP; } /* 3 PHP */
+OP(28) { RD_DUM; PLP; } /* 4 PLP */
+OP(48) { RD_DUM; PHA; } /* 3 PHA */
+OP(68) { RD_DUM; PLA; } /* 4 PLA */
+OP(88) { RD_DUM; DEY; } /* 2 DEY */
+OP(a8) { RD_DUM; TAY; } /* 2 TAY */
+OP(c8) { RD_DUM; INY; } /* 2 INY */
+OP(e8) { RD_DUM; INX; } /* 2 INX */
+
+OP(18) { RD_DUM; CLC; } /* 2 CLC */
+OP(38) { RD_DUM; SEC; } /* 2 SEC */
+OP(58) { RD_DUM; CLI; } /* 2 CLI */
+OP(78) { RD_DUM; SEI; } /* 2 SEI */
+OP(98) { RD_DUM; TYA; } /* 2 TYA */
+OP(b8) { RD_DUM; CLV; } /* 2 CLV */
+OP(d8) { RD_DUM; CLD; } /* 2 CLD */
+OP(f8) { RD_DUM; SED; } /* 2 SED */
+
+OP(09) { int tmp; RD_IMM; ORA; } /* 2 ORA IMM */
+OP(29) { int tmp; RD_IMM; AND; } /* 2 AND IMM */
+OP(49) { int tmp; RD_IMM; EOR; } /* 2 EOR IMM */
+OP(69) { int tmp; RD_IMM; ADC_C02; } /* 2/3 ADC IMM */
+OP(89) { int tmp; RD_IMM; BIT_IMM_C02; } /* 2 BIT IMM */
+OP(a9) { int tmp; RD_IMM; LDA; } /* 2 LDA IMM */
+OP(c9) { int tmp; RD_IMM; CMP; } /* 2 CMP IMM */
+OP(e9) { int tmp; RD_IMM; SBC_C02; } /* 2/3 SBC IMM */
+
+OP(19) { int tmp; RD_ABY_C02_P; ORA; } /* 4 ORA ABY page penalty */
+OP(39) { int tmp; RD_ABY_C02_P; AND; } /* 4 AND ABY page penalty */
+OP(59) { int tmp; RD_ABY_C02_P; EOR; } /* 4 EOR ABY page penalty */
+OP(79) { int tmp; RD_ABY_C02_P; ADC_C02; } /* 4/5 ADC ABY page penalty */
+OP(99) { int tmp; STA; WR_ABY_C02_NP; } /* 5 STA ABY */
+OP(b9) { int tmp; RD_ABY_C02_P; LDA; } /* 4 LDA ABY page penalty */
+OP(d9) { int tmp; RD_ABY_C02_P; CMP; } /* 4 CMP ABY page penalty */
+OP(f9) { int tmp; RD_ABY_C02_P; SBC_C02; } /* 4/5 SBC ABY page penalty */
+
+OP(0a) { int tmp; RD_DUM; RD_ACC; ASL; WB_ACC; } /* 2 ASL A */
+OP(2a) { int tmp; RD_DUM; RD_ACC; ROL; WB_ACC; } /* 2 ROL A */
+OP(4a) { int tmp; RD_DUM; RD_ACC; LSR; WB_ACC; } /* 2 LSR A */
+OP(6a) { int tmp; RD_DUM; RD_ACC; ROR; WB_ACC; } /* 2 ROR A */
+OP(8a) { RD_DUM; TXA; } /* 2 TXA */
+OP(aa) { RD_DUM; TAX; } /* 2 TAX */
+OP(ca) { RD_DUM; DEX; } /* 2 DEX */
+OP(ea) { RD_DUM; NOP; } /* 2 NOP */
+
+OP(1a) { RD_DUM;INA; } /* 2 INA */
+OP(3a) { RD_DUM;DEA; } /* 2 DEA */
+OP(5a) { RD_DUM;PHY; } /* 3 PHY */
+OP(7a) { RD_DUM;PLY; } /* 4 PLY */
+OP(9a) { RD_DUM; TXS; } /* 2 TXS */
+OP(ba) { RD_DUM; TSX; } /* 2 TSX */
+OP(da) { RD_DUM;PHX; } /* 3 PHX */
+OP(fa) { RD_DUM;PLX; } /* 4 PLX */
+
+OP(0b) { NOP; } /* 1 NOP not sure for rockwell */
+OP(2b) { NOP; } /* 1 NOP not sure for rockwell */
+OP(4b) { NOP; } /* 1 NOP not sure for rockwell */
+OP(6b) { NOP; } /* 1 NOP not sure for rockwell */
+OP(8b) { NOP; } /* 1 NOP not sure for rockwell */
+OP(ab) { NOP; } /* 1 NOP not sure for rockwell */
+OP(cb) { NOP; } /* 1 NOP not sure for rockwell */
+OP(eb) { NOP; } /* 1 NOP not sure for rockwell */
+
+OP(1b) { NOP; } /* 1 NOP not sure for rockwell */
+OP(3b) { NOP; } /* 1 NOP not sure for rockwell */
+OP(5b) { NOP; } /* 1 NOP not sure for rockwell */
+OP(7b) { NOP; } /* 1 NOP not sure for rockwell */
+OP(9b) { NOP; } /* 1 NOP not sure for rockwell */
+OP(bb) { NOP; } /* 1 NOP not sure for rockwell */
+OP(db) { NOP; } /* 1 NOP not sure for rockwell */
+OP(fb) { NOP; } /* 1 NOP not sure for rockwell */
+
+OP(0c) { int tmp; RD_ABS; RD_EA; TSB; WB_EA; } /* 6 TSB ABS */
+OP(2c) { int tmp; RD_ABS; BIT; } /* 4 BIT ABS */
+OP(4c) { EA_ABS; JMP; } /* 3 JMP ABS */
+OP(6c) { int tmp; EA_IND_C02; JMP; } /* 6 JMP IND */
+OP(8c) { int tmp; STY; WR_ABS; } /* 4 STY ABS */
+OP(ac) { int tmp; RD_ABS; LDY; } /* 4 LDY ABS */
+OP(cc) { int tmp; RD_ABS; CPY; } /* 4 CPY ABS */
+OP(ec) { int tmp; RD_ABS; CPX; } /* 4 CPX ABS */
+
+OP(1c) { int tmp; RD_ABS; RD_EA; TRB; WB_EA; } /* 6 TRB ABS */
+OP(3c) { int tmp; RD_ABX_C02_P; BIT; } /* 4 BIT ABX page penalty */
+OP(5c) { RD_ABX_C02_NP_DISCARD; RD_DUM; RD_DUM; RD_DUM; RD_DUM; } /* 8 NOP ABX not sure for rockwell. Page penalty not sure */
+OP(7c) { int tmp; EA_IAX; JMP; } /* 6 JMP IAX page penalty */
+OP(9c) { int tmp; STZ; WR_ABS; } /* 4 STZ ABS */
+OP(bc) { int tmp; RD_ABX_C02_P; LDY; } /* 4 LDY ABX page penalty */
+OP(dc) { RD_ABX_C02_NP_DISCARD; NOP; } /* 4 NOP ABX not sure for rockwell. Page penalty not sure */
+OP(fc) { RD_ABX_C02_NP_DISCARD; NOP; } /* 4 NOP ABX not sure for rockwell. Page penalty not sure */
+
+OP(0d) { int tmp; RD_ABS; ORA; } /* 4 ORA ABS */
+OP(2d) { int tmp; RD_ABS; AND; } /* 4 AND ABS */
+OP(4d) { int tmp; RD_ABS; EOR; } /* 4 EOR ABS */
+OP(6d) { int tmp; RD_ABS; ADC_C02; } /* 4/5 ADC ABS */
+OP(8d) { int tmp; STA; WR_ABS; } /* 4 STA ABS */
+OP(ad) { int tmp; RD_ABS; LDA; } /* 4 LDA ABS */
+OP(cd) { int tmp; RD_ABS; CMP; } /* 4 CMP ABS */
+OP(ed) { int tmp; RD_ABS; SBC_C02; } /* 4/5 SBC ABS */
+
+OP(1d) { int tmp; RD_ABX_C02_P; ORA; } /* 4 ORA ABX page penalty */
+OP(3d) { int tmp; RD_ABX_C02_P; AND; } /* 4 AND ABX page penalty */
+OP(5d) { int tmp; RD_ABX_C02_P; EOR; } /* 4 EOR ABX page penalty */
+OP(7d) { int tmp; RD_ABX_C02_P; ADC_C02; } /* 4/5 ADC ABX page penalty */
+OP(9d) { int tmp; STA; WR_ABX_C02_NP; } /* 5 STA ABX */
+OP(bd) { int tmp; RD_ABX_C02_P; LDA; } /* 4 LDA ABX page penalty */
+OP(dd) { int tmp; RD_ABX_C02_P; CMP; } /* 4 CMP ABX page penalty */
+OP(fd) { int tmp; RD_ABX_C02_P; SBC_C02; } /* 4/5 SBC ABX page penalty */
+
+OP(0e) { int tmp; RD_ABS; RD_EA; ASL; WB_EA; } /* 6 ASL ABS */
+OP(2e) { int tmp; RD_ABS; RD_EA; ROL; WB_EA; } /* 6 ROL ABS */
+OP(4e) { int tmp; RD_ABS; RD_EA; LSR; WB_EA; } /* 6 LSR ABS */
+OP(6e) { int tmp; RD_ABS; RD_EA; ROR; WB_EA; } /* 6 ROR ABS */
+OP(8e) { int tmp; STX; WR_ABS; } /* 4 STX ABS */
+OP(ae) { int tmp; RD_ABS; LDX; } /* 4 LDX ABS */
+OP(ce) { int tmp; RD_ABS; RD_EA; DEC; WB_EA; } /* 6 DEC ABS */
+OP(ee) { int tmp; RD_ABS; RD_EA; INC; WB_EA; } /* 6 INC ABS */
+
+OP(1e) { int tmp; RD_ABX_C02_NP; RD_EA; ASL; WB_EA; } /* 7 ASL ABX */
+OP(3e) { int tmp; RD_ABX_C02_NP; RD_EA; ROL; WB_EA; } /* 7 ROL ABX */
+OP(5e) { int tmp; RD_ABX_C02_NP; RD_EA; LSR; WB_EA; } /* 7 LSR ABX */
+OP(7e) { int tmp; RD_ABX_C02_NP; RD_EA; ROR; WB_EA; } /* 7 ROR ABX */
+OP(9e) { int tmp; STZ; WR_ABX_C02_NP; } /* 5 STZ ABX */
+OP(be) { int tmp; RD_ABY_C02_P; LDX; } /* 4 LDX ABY page penalty */
+OP(de) { int tmp; RD_ABX_C02_NP; RD_EA; DEC; WB_EA; } /* 7 DEC ABX */
+OP(fe) { int tmp; RD_ABX_C02_NP; RD_EA; INC; WB_EA; } /* 7 INC ABX */
+
+OP(0f) { int tmp; RD_ZPG; BBR(0); } /* 5-7 BBR0 ZPG */
+OP(2f) { int tmp; RD_ZPG; BBR(2); } /* 5-7 BBR2 ZPG */
+OP(4f) { int tmp; RD_ZPG; BBR(4); } /* 5-7 BBR4 ZPG */
+OP(6f) { int tmp; RD_ZPG; BBR(6); } /* 5-7 BBR6 ZPG */
+OP(8f) { int tmp; RD_ZPG; BBS(0); } /* 5-7 BBS0 ZPG */
+OP(af) { int tmp; RD_ZPG; BBS(2); } /* 5-7 BBS2 ZPG */
+OP(cf) { int tmp; RD_ZPG; BBS(4); } /* 5-7 BBS4 ZPG */
+OP(ef) { int tmp; RD_ZPG; BBS(6); } /* 5-7 BBS6 ZPG */
+
+OP(1f) { int tmp; RD_ZPG; BBR(1); } /* 5-7 BBR1 ZPG */
+OP(3f) { int tmp; RD_ZPG; BBR(3); } /* 5-7 BBR3 ZPG */
+OP(5f) { int tmp; RD_ZPG; BBR(5); } /* 5-7 BBR5 ZPG */
+OP(7f) { int tmp; RD_ZPG; BBR(7); } /* 5-7 BBR7 ZPG */
+OP(9f) { int tmp; RD_ZPG; BBS(1); } /* 5-7 BBS1 ZPG */
+OP(bf) { int tmp; RD_ZPG; BBS(3); } /* 5-7 BBS3 ZPG */
+OP(df) { int tmp; RD_ZPG; BBS(5); } /* 5-7 BBS5 ZPG */
+OP(ff) { int tmp; RD_ZPG; BBS(7); } /* 5-7 BBS7 ZPG */
+
+static void (*const insn65c02[0x100])(m6502_Regs *cpustate) = {
+ m65c02_00,m65c02_01,m65c02_02,m65c02_03,m65c02_04,m65c02_05,m65c02_06,m65c02_07,
+ m65c02_08,m65c02_09,m65c02_0a,m65c02_0b,m65c02_0c,m65c02_0d,m65c02_0e,m65c02_0f,
+ m65c02_10,m65c02_11,m65c02_12,m65c02_13,m65c02_14,m65c02_15,m65c02_16,m65c02_17,
+ m65c02_18,m65c02_19,m65c02_1a,m65c02_1b,m65c02_1c,m65c02_1d,m65c02_1e,m65c02_1f,
+ m65c02_20,m65c02_21,m65c02_22,m65c02_23,m65c02_24,m65c02_25,m65c02_26,m65c02_27,
+ m65c02_28,m65c02_29,m65c02_2a,m65c02_2b,m65c02_2c,m65c02_2d,m65c02_2e,m65c02_2f,
+ m65c02_30,m65c02_31,m65c02_32,m65c02_33,m65c02_34,m65c02_35,m65c02_36,m65c02_37,
+ m65c02_38,m65c02_39,m65c02_3a,m65c02_3b,m65c02_3c,m65c02_3d,m65c02_3e,m65c02_3f,
+ m65c02_40,m65c02_41,m65c02_42,m65c02_43,m65c02_44,m65c02_45,m65c02_46,m65c02_47,
+ m65c02_48,m65c02_49,m65c02_4a,m65c02_4b,m65c02_4c,m65c02_4d,m65c02_4e,m65c02_4f,
+ m65c02_50,m65c02_51,m65c02_52,m65c02_53,m65c02_54,m65c02_55,m65c02_56,m65c02_57,
+ m65c02_58,m65c02_59,m65c02_5a,m65c02_5b,m65c02_5c,m65c02_5d,m65c02_5e,m65c02_5f,
+ m65c02_60,m65c02_61,m65c02_62,m65c02_63,m65c02_64,m65c02_65,m65c02_66,m65c02_67,
+ m65c02_68,m65c02_69,m65c02_6a,m65c02_6b,m65c02_6c,m65c02_6d,m65c02_6e,m65c02_6f,
+ m65c02_70,m65c02_71,m65c02_72,m65c02_73,m65c02_74,m65c02_75,m65c02_76,m65c02_77,
+ m65c02_78,m65c02_79,m65c02_7a,m65c02_7b,m65c02_7c,m65c02_7d,m65c02_7e,m65c02_7f,
+ m65c02_80,m65c02_81,m65c02_82,m65c02_83,m65c02_84,m65c02_85,m65c02_86,m65c02_87,
+ m65c02_88,m65c02_89,m65c02_8a,m65c02_8b,m65c02_8c,m65c02_8d,m65c02_8e,m65c02_8f,
+ m65c02_90,m65c02_91,m65c02_92,m65c02_93,m65c02_94,m65c02_95,m65c02_96,m65c02_97,
+ m65c02_98,m65c02_99,m65c02_9a,m65c02_9b,m65c02_9c,m65c02_9d,m65c02_9e,m65c02_9f,
+ m65c02_a0,m65c02_a1,m65c02_a2,m65c02_a3,m65c02_a4,m65c02_a5,m65c02_a6,m65c02_a7,
+ m65c02_a8,m65c02_a9,m65c02_aa,m65c02_ab,m65c02_ac,m65c02_ad,m65c02_ae,m65c02_af,
+ m65c02_b0,m65c02_b1,m65c02_b2,m65c02_b3,m65c02_b4,m65c02_b5,m65c02_b6,m65c02_b7,
+ m65c02_b8,m65c02_b9,m65c02_ba,m65c02_bb,m65c02_bc,m65c02_bd,m65c02_be,m65c02_bf,
+ m65c02_c0,m65c02_c1,m65c02_c2,m65c02_c3,m65c02_c4,m65c02_c5,m65c02_c6,m65c02_c7,
+ m65c02_c8,m65c02_c9,m65c02_ca,m65c02_cb,m65c02_cc,m65c02_cd,m65c02_ce,m65c02_cf,
+ m65c02_d0,m65c02_d1,m65c02_d2,m65c02_d3,m65c02_d4,m65c02_d5,m65c02_d6,m65c02_d7,
+ m65c02_d8,m65c02_d9,m65c02_da,m65c02_db,m65c02_dc,m65c02_dd,m65c02_de,m65c02_df,
+ m65c02_e0,m65c02_e1,m65c02_e2,m65c02_e3,m65c02_e4,m65c02_e5,m65c02_e6,m65c02_e7,
+ m65c02_e8,m65c02_e9,m65c02_ea,m65c02_eb,m65c02_ec,m65c02_ed,m65c02_ee,m65c02_ef,
+ m65c02_f0,m65c02_f1,m65c02_f2,m65c02_f3,m65c02_f4,m65c02_f5,m65c02_f6,m65c02_f7,
+ m65c02_f8,m65c02_f9,m65c02_fa,m65c02_fb,m65c02_fc,m65c02_fd,m65c02_fe,m65c02_ff
+};
+
+#ifdef WDC65C02
+OP(cb_wdc) { RD_DUM; RD_DUM; } /* 3 WAI, TODO: Implement HALT mode */
+OP(db_wdc) { RD_DUM; RD_DUM; } /* 3 STP, TODO: Implement STP mode */
+OP(1e_wdc) { int tmp; RD_ABX_P; RD_EA; ASL; WB_EA; } /* 6 ASL ABX page penalty */
+OP(3e_wdc) { int tmp; RD_ABX_P; RD_EA; ROL; WB_EA; } /* 6 ROL ABX page penalty */
+OP(5e_wdc) { int tmp; RD_ABX_P; RD_EA; LSR; WB_EA; } /* 6 LSR ABX page penalty */
+OP(7e_wdc) { int tmp; RD_ABX_P; RD_EA; ROR; WB_EA; } /* 6 ROR ABX page penalty */
+OP(de_wdc) { int tmp; RD_ABX_P; RD_EA; DEC; WB_EA; } /* 6 DEC ABX page penalty */
+OP(fe_wdc) { int tmp; RD_ABX_P; RD_EA; INC; WB_EA; } /* 6 INC ABX page penalty */
+
+static void (*const insnwdc65c02[0x100])(m6502_Regs *cpustate) = {
+ m65c02_00,m65c02_01,m65c02_02,m65c02_03,m65c02_04,m65c02_05,m65c02_06,m65c02_07,
+ m65c02_08,m65c02_09,m65c02_0a,m65c02_0b,m65c02_0c,m65c02_0d,m65c02_0e,m65c02_0f,
+ m65c02_10,m65c02_11,m65c02_12,m65c02_13,m65c02_14,m65c02_15,m65c02_16,m65c02_17,
+ m65c02_18,m65c02_19,m65c02_1a,m65c02_1b,m65c02_1c,m65c02_1d,m65c02_1e_wdc,m65c02_1f,
+ m65c02_20,m65c02_21,m65c02_22,m65c02_23,m65c02_24,m65c02_25,m65c02_26,m65c02_27,
+ m65c02_28,m65c02_29,m65c02_2a,m65c02_2b,m65c02_2c,m65c02_2d,m65c02_2e,m65c02_2f,
+ m65c02_30,m65c02_31,m65c02_32,m65c02_33,m65c02_34,m65c02_35,m65c02_36,m65c02_37,
+ m65c02_38,m65c02_39,m65c02_3a,m65c02_3b,m65c02_3c,m65c02_3d,m65c02_3e_wdc,m65c02_3f,
+ m65c02_40,m65c02_41,m65c02_42,m65c02_43,m65c02_44,m65c02_45,m65c02_46,m65c02_47,
+ m65c02_48,m65c02_49,m65c02_4a,m65c02_4b,m65c02_4c,m65c02_4d,m65c02_4e,m65c02_4f,
+ m65c02_50,m65c02_51,m65c02_52,m65c02_53,m65c02_54,m65c02_55,m65c02_56,m65c02_57,
+ m65c02_58,m65c02_59,m65c02_5a,m65c02_5b,m65c02_5c,m65c02_5d,m65c02_5e_wdc,m65c02_5f,
+ m65c02_60,m65c02_61,m65c02_62,m65c02_63,m65c02_64,m65c02_65,m65c02_66,m65c02_67,
+ m65c02_68,m65c02_69,m65c02_6a,m65c02_6b,m65c02_6c,m65c02_6d,m65c02_6e,m65c02_6f,
+ m65c02_70,m65c02_71,m65c02_72,m65c02_73,m65c02_74,m65c02_75,m65c02_76,m65c02_77,
+ m65c02_78,m65c02_79,m65c02_7a,m65c02_7b,m65c02_7c,m65c02_7d,m65c02_7e_wdc,m65c02_7f,
+ m65c02_80,m65c02_81,m65c02_82,m65c02_83,m65c02_84,m65c02_85,m65c02_86,m65c02_87,
+ m65c02_88,m65c02_89,m65c02_8a,m65c02_8b,m65c02_8c,m65c02_8d,m65c02_8e,m65c02_8f,
+ m65c02_90,m65c02_91,m65c02_92,m65c02_93,m65c02_94,m65c02_95,m65c02_96,m65c02_97,
+ m65c02_98,m65c02_99,m65c02_9a,m65c02_9b,m65c02_9c,m65c02_9d,m65c02_9e,m65c02_9f,
+ m65c02_a0,m65c02_a1,m65c02_a2,m65c02_a3,m65c02_a4,m65c02_a5,m65c02_a6,m65c02_a7,
+ m65c02_a8,m65c02_a9,m65c02_aa,m65c02_ab,m65c02_ac,m65c02_ad,m65c02_ae,m65c02_af,
+ m65c02_b0,m65c02_b1,m65c02_b2,m65c02_b3,m65c02_b4,m65c02_b5,m65c02_b6,m65c02_b7,
+ m65c02_b8,m65c02_b9,m65c02_ba,m65c02_bb,m65c02_bc,m65c02_bd,m65c02_be,m65c02_bf,
+ m65c02_c0,m65c02_c1,m65c02_c2,m65c02_c3,m65c02_c4,m65c02_c5,m65c02_c6,m65c02_c7,
+ m65c02_c8,m65c02_c9,m65c02_ca,m65c02_cb_wdc,m65c02_cc,m65c02_cd,m65c02_ce,m65c02_cf,
+ m65c02_d0,m65c02_d1,m65c02_d2,m65c02_d3,m65c02_d4,m65c02_d5,m65c02_d6,m65c02_d7,
+ m65c02_d8,m65c02_d9,m65c02_da,m65c02_db_wdc,m65c02_dc,m65c02_dd,m65c02_de_wdc,m65c02_df,
+ m65c02_e0,m65c02_e1,m65c02_e2,m65c02_e3,m65c02_e4,m65c02_e5,m65c02_e6,m65c02_e7,
+ m65c02_e8,m65c02_e9,m65c02_ea,m65c02_eb,m65c02_ec,m65c02_ed,m65c02_ee,m65c02_ef,
+ m65c02_f0,m65c02_f1,m65c02_f2,m65c02_f3,m65c02_f4,m65c02_f5,m65c02_f6,m65c02_f7,
+ m65c02_f8,m65c02_f9,m65c02_fa,m65c02_fb,m65c02_fc,m65c02_fd,m65c02_fe_wdc,m65c02_ff
+};
+#endif
+
+
diff --git a/trunk/src/emu/cpu/m6502/t65ce02.c b/trunk/src/emu/cpu/m6502/t65ce02.c
new file mode 100644
index 00000000000..20f7f749182
--- /dev/null
+++ b/trunk/src/emu/cpu/m6502/t65ce02.c
@@ -0,0 +1,399 @@
+/*****************************************************************************
+ *
+ * t65ce02.c
+ * 65ce02 opcode functions and function pointer table
+ *
+ * Copyright Peter Trauner, all rights reserved.
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * pullmoll@t-online.de
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ *****************************************************************************/
+
+#undef OP
+#ifdef M4510
+#define OP(nn) INLINE void m4510_##nn(m4510_Regs *cpustate)
+#else
+#define OP(nn) INLINE void m65ce02_##nn(m65ce02_Regs *cpustate)
+#endif
+
+/*****************************************************************************
+ *****************************************************************************
+ *
+ * overrides for 65CE02 opcodes
+ *
+ *****************************************************************************
+ * op temp cycles rdmem opc wrmem ********************/
+OP(00) { BRK; } /* 7 BRK */
+OP(20) { JSR; } /* 5 JSR */
+OP(40) { int tmp; RTI; } /* 5 RTI */
+OP(60) { RTS; } /* 4 RTS */
+OP(80) { int tmp; BRA(1); } /* 2 BRA */
+OP(a0) { int tmp; RD_IMM; LDY; } /* 2 LDY IMM */
+OP(c0) { int tmp; RD_IMM; CPY; } /* 2 CPY IMM */
+OP(e0) { int tmp; RD_IMM; CPX; } /* 2 CPX IMM */
+
+OP(10) { int tmp; BRA( ! ( P & F_N ) ); } /* 2 BPL REL */
+OP(30) { int tmp; BRA( ( P & F_N ) ); } /* 2 BMI REL */
+OP(50) { int tmp; BRA( ! ( P & F_V ) ); } /* 2 BVC REL */
+OP(70) { int tmp; BRA( ( P & F_V ) ); } /* 2 BVS REL */
+OP(90) { int tmp; BRA( ! ( P & F_C ) ); } /* 2 BCC REL */
+OP(b0) { int tmp; BRA( ( P & F_C ) ); } /* 2 BCS REL */
+OP(d0) { int tmp; BRA( ! ( P & F_Z ) ); } /* 2 BNE REL */
+OP(f0) { int tmp; BRA( ( P & F_Z ) ); } /* 2 BEQ REL */
+
+OP(01) { int tmp; RD_IDX; ORA; } /* 5 ORA IDX */
+OP(21) { int tmp; RD_IDX; AND; } /* 5 AND IDX */
+OP(41) { int tmp; RD_IDX; EOR; } /* 5 EOR IDX */
+OP(61) { int tmp; RD_IDX; ADC; } /* 5 ADC IDX */
+OP(81) { int tmp; STA; WR_IDX; } /* 5 STA IDX */
+OP(a1) { int tmp; RD_IDX; LDA; } /* 5 LDA IDX */
+OP(c1) { int tmp; RD_IDX; CMP; } /* 5 CMP IDX */
+OP(e1) { int tmp; RD_IDX; SBC; } /* 5 SBC IDX */
+
+OP(11) { int tmp; RD_IDY; ORA; } /* 5 ORA IDY */
+OP(31) { int tmp; RD_IDY; AND; } /* 5 AND IDY */
+OP(51) { int tmp; RD_IDY; EOR; } /* 5 EOR IDY */
+OP(71) { int tmp; RD_IDY; ADC; } /* 5 ADC IDY */
+OP(91) { int tmp; STA; WR_IDY; } /* 5 STA IDY */
+OP(b1) { int tmp; RD_IDY; LDA; } /* 5 LDA IDY */
+OP(d1) { int tmp; RD_IDY; CMP; } /* 5 CMP IDY */
+OP(f1) { int tmp; RD_IDY; SBC; } /* 5 SBC IDY */
+
+OP(02) { RD_DUM; CLE; } /* 2 CLE */
+OP(22) { JSR_IND; } /* 7 JSR IND */
+OP(42) { RD_DUM; NEG; } /* 2 NEG */
+OP(62) { int tmp; RD_IMM; RTN; } /* 7 RTN IMM */
+OP(82) { RD_INSY_DISCARD; } /* 6 STA INSY */
+OP(a2) { int tmp; RD_IMM; LDX; } /* 2 LDX IMM */
+OP(c2) { int tmp; RD_IMM; CPZ; } /* 2 CPZ IMM */
+OP(e2) { int tmp; RD_INSY; LDA; } /* 6 LDA INSY */
+
+OP(12) { int tmp; RD_IDZ; ORA; } /* 5 ORA IDZ */
+OP(32) { int tmp; RD_IDZ; AND; } /* 5 AND IDZ */
+OP(52) { int tmp; RD_IDZ; EOR; } /* 5 EOR IDZ */
+OP(72) { int tmp; RD_IDZ; ADC; } /* 5 ADC IDZ */
+OP(92) { RD_IDZ_DISCARD; } /* 5 STA IDZ */
+OP(b2) { int tmp; RD_IDZ; LDA; } /* 5 LDA IDZ */
+OP(d2) { int tmp; RD_IDZ; CMP; } /* 5 CMP IDZ */
+OP(f2) { int tmp; RD_IDZ; SBC; } /* 5 SBC IDZ */
+
+OP(03) { RD_DUM; SEE; } /* 2 SEE */
+OP(23) { JSR_INDX; } /* 7 JSR INDX */
+OP(43) { int tmp; RD_DUM; RD_ACC; ASR_65CE02; WR_ACC; } /* 2 ASR A */
+OP(63) { BSR; } /* 5 BSR */
+OP(83) { BRA_WORD(1); } /* 3 BRA REL WORD */
+OP(a3) { int tmp; RD_IMM; LDZ; } /* 2 LDZ IMM */
+OP(c3) { PAIR tmp; RD_ZPG_WORD; DEW; WB_EA_WORD; } /* 6 DEW ABS */
+OP(e3) { PAIR tmp; RD_ZPG_WORD; INW; WB_EA_WORD; } /* 6 INW ABS */
+
+OP(13) { BRA_WORD( ! ( P & F_N ) ); } /* 3 BPL REL WORD */
+OP(33) { BRA_WORD( ( P & F_N ) ); } /* 3 BMI REL WORD */
+OP(53) { BRA_WORD( ! ( P & F_V ) ); } /* 3 BVC REL WORD */
+OP(73) { BRA_WORD( ( P & F_V ) ); } /* 3 BVS REL WORD */
+OP(93) { BRA_WORD( ! ( P & F_C ) ); } /* 3 BCC REL WORD */
+OP(b3) { BRA_WORD( ( P & F_C ) ); } /* 3 BCS REL WORD */
+OP(d3) { BRA_WORD( ! ( P & F_Z ) ); } /* 3 BNE REL WORD */
+OP(f3) { BRA_WORD( ( P & F_Z ) ); } /* 3 BEQ REL WORD */
+
+OP(04) { int tmp; RD_ZPG; TSB; WB_EA; } /* 4 TSB ZPG */
+OP(24) { int tmp; RD_ZPG; RD_DUM; BIT; } /* 4 BIT ZPG */
+OP(44) { int tmp; RD_ZPG; ASR_65CE02; WB_EA; } /* 4 ASR ZPG */
+OP(64) { int tmp; STZ_65CE02; WR_ZPG; } /* 3 STZ ZPG */
+OP(84) { int tmp; STY; WR_ZPG; } /* 3 STY ZPG */
+OP(a4) { int tmp; RD_ZPG; LDY; } /* 3 LDY ZPG */
+OP(c4) { int tmp; RD_ZPG; CPY; } /* 3 CPY ZPG */
+OP(e4) { int tmp; RD_ZPG; CPX; } /* 3 CPX ZPG */
+
+OP(14) { int tmp; RD_ZPG; TRB; WB_EA; } /* 4 TRB ZPG */
+OP(34) { int tmp; RD_ZPX; RD_DUM; BIT; } /* 4 BIT ZPX */
+OP(54) { int tmp; RD_ZPX; ASR_65CE02; WB_EA; } /* 4 ASR ZPX */
+OP(74) { int tmp; STZ_65CE02; WR_ZPX; } /* 3 STZ ZPX */
+OP(94) { int tmp; STY; WR_ZPX; } /* 3 STY ZPX */
+OP(b4) { int tmp; RD_ZPX; LDY; } /* 3 LDY ZPX */
+OP(d4) { int tmp; RD_ZPG; CPZ; } /* 3 CPZ ZPG */
+OP(f4) { PAIR tmp; RD_IMM_WORD; PUSH_WORD(tmp); } /* 5 PHW imm16 */
+
+OP(05) { int tmp; RD_ZPG; ORA; } /* 3 ORA ZPG */
+OP(25) { int tmp; RD_ZPG; AND; } /* 3 AND ZPG */
+OP(45) { int tmp; RD_ZPG; EOR; } /* 3 EOR ZPG */
+OP(65) { int tmp; RD_ZPG; ADC; } /* 3 ADC ZPG */
+OP(85) { int tmp; STA; WR_ZPG; } /* 3 STA ZPG */
+OP(a5) { int tmp; RD_ZPG; LDA; } /* 3 LDA ZPG */
+OP(c5) { int tmp; RD_ZPG; CMP; } /* 3 CMP ZPG */
+OP(e5) { int tmp; RD_ZPG; SBC; } /* 3 SBC ZPG */
+
+OP(15) { int tmp; RD_ZPX; ORA; } /* 3 ORA ZPX */
+OP(35) { int tmp; RD_ZPX; AND; } /* 3 AND ZPX */
+OP(55) { int tmp; RD_ZPX; EOR; } /* 3 EOR ZPX */
+OP(75) { int tmp; RD_ZPX; ADC; } /* 3 ADC ZPX */
+OP(95) { int tmp; STA; WR_ZPX; } /* 3 STA ZPX */
+OP(b5) { int tmp; RD_ZPX; LDA; } /* 3 LDA ZPX */
+OP(d5) { int tmp; RD_ZPX; CMP; } /* 3 CMP ZPX */
+OP(f5) { int tmp; RD_ZPX; SBC; } /* 3 SBC ZPX */
+
+OP(06) { int tmp; RD_ZPG; ASL; WB_EA; } /* 4 ASL ZPG */
+OP(26) { int tmp; RD_ZPG; ROL; WB_EA; } /* 4 ROL ZPG */
+OP(46) { int tmp; RD_ZPG; LSR; WB_EA; } /* 4 LSR ZPG */
+OP(66) { int tmp; RD_ZPG; ROR; WB_EA; } /* 4 ROR ZPG */
+OP(86) { int tmp; STX; WR_ZPG; } /* 3 STX ZPG */
+OP(a6) { int tmp; RD_ZPG; LDX; } /* 3 LDX ZPG */
+OP(c6) { int tmp; RD_ZPG; DEC; WB_EA; } /* 4 DEC ZPG */
+OP(e6) { int tmp; RD_ZPG; INC; WB_EA; } /* 4 INC ZPG */
+
+OP(16) { int tmp; RD_ZPX; ASL; WB_EA; } /* 4 ASL ZPX */
+OP(36) { int tmp; RD_ZPX; ROL; WB_EA; } /* 4 ROL ZPX */
+OP(56) { int tmp; RD_ZPX; LSR; WB_EA; } /* 4 LSR ZPX */
+OP(76) { int tmp; RD_ZPX; ROR; WB_EA; } /* 4 ROR ZPX */
+OP(96) { int tmp; STX; WR_ZPY; } /* 3 STX ZPY */
+OP(b6) { int tmp; RD_ZPY; LDX; } /* 3 LDX ZPY */
+OP(d6) { int tmp; RD_ZPX; DEC; WB_EA; } /* 4 DEC ZPX */
+OP(f6) { int tmp; RD_ZPX; INC; WB_EA; } /* 4 INC ZPX */
+
+OP(07) { int tmp; RD_ZPG; RMB(0); WB_EA; } /* 4 RMB0 ZPG */
+OP(27) { int tmp; RD_ZPG; RMB(2); WB_EA; } /* 4 RMB2 ZPG */
+OP(47) { int tmp; RD_ZPG; RMB(4); WB_EA; } /* 4 RMB4 ZPG */
+OP(67) { int tmp; RD_ZPG; RMB(6); WB_EA; } /* 4 RMB6 ZPG */
+OP(87) { int tmp; RD_ZPG; SMB(0); WB_EA; } /* 4 SMB0 ZPG */
+OP(a7) { int tmp; RD_ZPG; SMB(2); WB_EA; } /* 4 SMB2 ZPG */
+OP(c7) { int tmp; RD_ZPG; SMB(4); WB_EA; } /* 4 SMB4 ZPG */
+OP(e7) { int tmp; RD_ZPG; SMB(6); WB_EA; } /* 4 SMB6 ZPG */
+
+OP(17) { int tmp; RD_ZPG; RMB(1); WB_EA; } /* 4 RMB1 ZPG */
+OP(37) { int tmp; RD_ZPG; RMB(3); WB_EA; } /* 4 RMB3 ZPG */
+OP(57) { int tmp; RD_ZPG; RMB(5); WB_EA; } /* 4 RMB5 ZPG */
+OP(77) { int tmp; RD_ZPG; RMB(7); WB_EA; } /* 4 RMB7 ZPG */
+OP(97) { int tmp; RD_ZPG; SMB(1); WB_EA; } /* 4 SMB1 ZPG */
+OP(b7) { int tmp; RD_ZPG; SMB(3); WB_EA; } /* 4 SMB3 ZPG */
+OP(d7) { int tmp; RD_ZPG; SMB(5); WB_EA; } /* 4 SMB5 ZPG */
+OP(f7) { int tmp; RD_ZPG; SMB(7); WB_EA; } /* 4 SMB7 ZPG */
+
+OP(08) { RD_DUM; PHP; } /* 3 PHP */
+OP(28) { RD_DUM; PLP; } /* 3 PLP */
+OP(48) { RD_DUM; PHA; } /* 3 PHA */
+OP(68) { RD_DUM; PLA; } /* 3 PLA */
+OP(88) { DEY; } /* 1 DEY */
+OP(a8) { TAY; } /* 1 TAY */
+OP(c8) { INY; } /* 1 INY */
+OP(e8) { INX; } /* 1 INX */
+
+OP(18) { CLC; } /* 1 CLC */
+OP(38) { SEC; } /* 1 SEC */
+OP(58) { CLI; } /* 1 CLI */
+OP(78) { RD_DUM; SEI; } /* 2 SEI */
+OP(98) { TYA; } /* 1 TYA */
+OP(b8) { CLV; } /* 1 CLV */
+OP(d8) { CLD; } /* 1 CLD */
+OP(f8) { SED; } /* 1 SED */
+
+OP(09) { int tmp; RD_IMM; ORA; } /* 2 ORA IMM */
+OP(29) { int tmp; RD_IMM; AND; } /* 2 AND IMM */
+OP(49) { int tmp; RD_IMM; EOR; } /* 2 EOR IMM */
+OP(69) { int tmp; RD_IMM; ADC; } /* 2 ADC IMM */
+OP(89) { int tmp; RD_IMM; BIT; } /* 2 BIT IMM */
+OP(a9) { int tmp; RD_IMM; LDA; } /* 2 LDA IMM */
+OP(c9) { int tmp; RD_IMM; CMP; } /* 2 CMP IMM */
+OP(e9) { int tmp; RD_IMM; SBC; } /* 2 SBC IMM */
+
+OP(19) { int tmp; RD_ABY; ORA; } /* 4 ORA ABY */
+OP(39) { int tmp; RD_ABY; AND; } /* 4 AND ABY */
+OP(59) { int tmp; RD_ABY; EOR; } /* 4 EOR ABY */
+OP(79) { int tmp; RD_ABY; ADC; } /* 4 ADC ABY */
+OP(99) { int tmp; STA; WR_ABY; } /* 4 STA ABY */
+OP(b9) { int tmp; RD_ABY; LDA; } /* 4 LDA ABY */
+OP(d9) { int tmp; RD_ABY; CMP; } /* 4 CMP ABY */
+OP(f9) { int tmp; RD_ABY; SBC; } /* 4 SBC ABY */
+
+OP(0a) { int tmp; RD_ACC; ASL; WR_ACC; } /* 1 ASL A */
+OP(2a) { int tmp; RD_ACC; ROL; WR_ACC; } /* 1 ROL A */
+OP(4a) { int tmp; RD_ACC; LSR; WR_ACC; } /* 1 LSR A */
+OP(6a) { int tmp; RD_ACC; ROR; WR_ACC; } /* 1 ROR A */
+OP(8a) { TXA; } /* 1 TXA */
+OP(aa) { TAX; } /* 1 TAX */
+OP(ca) { DEX; } /* 1 DEX */
+OP(ea) { NOP; } /* 1 NOP */
+
+OP(1a) { INA; } /* 1 INA */
+OP(3a) { DEA; } /* 1 DEA */
+OP(5a) { RD_DUM; PHY; } /* 3 PHY */
+OP(7a) { RD_DUM; PLY; } /* 3 PLY */
+OP(9a) { TXS; } /* 1 TXS */
+OP(ba) { TSX; } /* 1 TSX */
+OP(da) { RD_DUM; PHX; } /* 3 PHX */
+OP(fa) { RD_DUM; PLX; } /* 3 PLX */
+
+OP(0b) { TSY; } /* 1 TSY */
+OP(2b) { TYS; } /* 1 TYS */
+OP(4b) { TAZ; } /* 1 TAZ */
+OP(6b) { TZA; } /* 1 TZA */
+OP(8b) { int tmp; STY; WR_ABX; } /* 4 STY ABX */
+OP(ab) { int tmp; RD_ABS; LDZ; } /* 4 LDZ ABS */
+OP(cb) { PAIR tmp; tmp.d = 0; RD_ABS_WORD; ASW; WB_EA_WORD; } /* 7 ASW ABS */
+OP(eb) { PAIR tmp; RD_ABS_WORD; ROW; WB_EA_WORD; } /* 6/7? roW ABS */
+
+OP(1b) { INZ; } /* 1 INZ */
+OP(3b) { DEZ; } /* 1 DEZ */
+OP(5b) { TAB; } /* 1 TAB */
+OP(7b) { TBA; } /* 1 TBA */
+OP(9b) { int tmp; STX; WR_ABY; } /* 4 STX ABY */
+OP(bb) { int tmp; RD_ABX; LDZ; } /* 4 LDZ ABX */
+OP(db) { RD_DUM; PHZ; } /* 3 PHZ */
+OP(fb) { RD_DUM; PLZ; } /* 3 PLZ */
+
+OP(0c) { int tmp; RD_ABS; TSB; WB_EA; } /* 5 TSB ABS */
+OP(2c) { int tmp; RD_ABS; RD_DUM; BIT; } /* 5 BIT ABS */
+OP(4c) { EA_ABS; JMP; } /* 3 JMP ABS */
+OP(6c) { int tmp; EA_IND; JMP; } /* 5 JMP IND */
+OP(8c) { int tmp; STY; WR_ABS; } /* 4 STY ABS */
+OP(ac) { int tmp; RD_ABS; LDY; } /* 4 LDY ABS */
+OP(cc) { int tmp; RD_ABS; CPY; } /* 4 CPY ABS */
+OP(ec) { int tmp; RD_ABS; CPX; } /* 4 CPX ABS */
+
+OP(1c) { int tmp; RD_ABS; TRB; WB_EA; } /* 5 TRB ABS */
+OP(3c) { int tmp; RD_ABX; RD_DUM; BIT; } /* 5 BIT ABX */
+#ifdef M4510
+OP(5c) { MAP; } /* 4? MAP */
+#else
+OP(5c) { int t1,t2,t3; AUG; } /* 4 AUGMENT/no operation */
+#endif
+OP(7c) { int tmp; EA_IAX; JMP; } /* 5 JMP IAX */
+OP(9c) { int tmp; STZ_65CE02; WR_ABS; } /* 4 STZ ABS */
+OP(bc) { int tmp; RD_ABX; LDY; } /* 4 LDY ABX */
+OP(dc) { int tmp; RD_ABS; CPZ; } /* 4 CPZ ABS */
+OP(fc) { PAIR tmp; RD_ABS_WORD; PUSH_WORD(tmp); } /* 7 PHW ab */
+
+OP(0d) { int tmp; RD_ABS; ORA; } /* 4 ORA ABS */
+OP(2d) { int tmp; RD_ABS; AND; } /* 4 AND ABS */
+OP(4d) { int tmp; RD_ABS; EOR; } /* 4 EOR ABS */
+OP(6d) { int tmp; RD_ABS; ADC; } /* 4 ADC ABS */
+OP(8d) { int tmp; STA; WR_ABS; } /* 4 STA ABS */
+OP(ad) { int tmp; RD_ABS; LDA; } /* 4 LDA ABS */
+OP(cd) { int tmp; RD_ABS; CMP; } /* 4 CMP ABS */
+OP(ed) { int tmp; RD_ABS; SBC; } /* 4 SBC ABS */
+
+OP(1d) { int tmp; RD_ABX; ORA; } /* 4 ORA ABX */
+OP(3d) { int tmp; RD_ABX; AND; } /* 4 AND ABX */
+OP(5d) { int tmp; RD_ABX; EOR; } /* 4 EOR ABX */
+OP(7d) { int tmp; RD_ABX; ADC; } /* 4 ADC ABX */
+OP(9d) { int tmp; STA; WR_ABX; } /* 4 STA ABX */
+OP(bd) { int tmp; RD_ABX; LDA; } /* 4 LDA ABX */
+OP(dd) { int tmp; RD_ABX; CMP; } /* 4 CMP ABX */
+OP(fd) { int tmp; RD_ABX; SBC; } /* 4 SBC ABX */
+
+OP(0e) { int tmp; RD_ABS; ASL; WB_EA; } /* 5 ASL ABS */
+OP(2e) { int tmp; RD_ABS; ROL; WB_EA; } /* 5 ROL ABS */
+OP(4e) { int tmp; RD_ABS; LSR; WB_EA; } /* 5 LSR ABS */
+OP(6e) { int tmp; RD_ABS; ROR; WB_EA; } /* 5 ROR ABS */
+OP(8e) { int tmp; STX; WR_ABS; } /* 4 STX ABS */
+OP(ae) { int tmp; RD_ABS; LDX; } /* 4 LDX ABS */
+OP(ce) { int tmp; RD_ABS; DEC; WB_EA; } /* 5 DEC ABS */
+OP(ee) { int tmp; RD_ABS; INC; WB_EA; } /* 5 INC ABS */
+
+OP(1e) { int tmp; RD_ABX; ASL; WB_EA; } /* 5 ASL ABX */
+OP(3e) { int tmp; RD_ABX; ROL; WB_EA; } /* 5 ROL ABX */
+OP(5e) { int tmp; RD_ABX; LSR; WB_EA; } /* 5 LSR ABX */
+OP(7e) { int tmp; RD_ABX; ROR; WB_EA; } /* 5 ROR ABX */
+OP(9e) { int tmp; STZ_65CE02; WR_ABX; } /* 4 STZ ABX */
+OP(be) { int tmp; RD_ABY; LDX; } /* 4 LDX ABY */
+OP(de) { int tmp; RD_ABX; DEC; WB_EA; } /* 5 DEC ABX */
+OP(fe) { int tmp; RD_ABX; INC; WB_EA; } /* 5 INC ABX */
+
+OP(0f) { int tmp; RD_ZPG; BBR(0); } /* 4 BBR0 ZPG */
+OP(2f) { int tmp; RD_ZPG; BBR(2); } /* 4 BBR2 ZPG */
+OP(4f) { int tmp; RD_ZPG; BBR(4); } /* 4 BBR4 ZPG */
+OP(6f) { int tmp; RD_ZPG; BBR(6); } /* 4 BBR6 ZPG */
+OP(8f) { int tmp; RD_ZPG; BBS(0); } /* 4 BBS0 ZPG */
+OP(af) { int tmp; RD_ZPG; BBS(2); } /* 4 BBS2 ZPG */
+OP(cf) { int tmp; RD_ZPG; BBS(4); } /* 4 BBS4 ZPG */
+OP(ef) { int tmp; RD_ZPG; BBS(6); } /* 4 BBS6 ZPG */
+
+OP(1f) { int tmp; RD_ZPG; BBR(1); } /* 4 BBR1 ZPG */
+OP(3f) { int tmp; RD_ZPG; BBR(3); } /* 4 BBR3 ZPG */
+OP(5f) { int tmp; RD_ZPG; BBR(5); } /* 4 BBR5 ZPG */
+OP(7f) { int tmp; RD_ZPG; BBR(7); } /* 4 BBR7 ZPG */
+OP(9f) { int tmp; RD_ZPG; BBS(1); } /* 4 BBS1 ZPG */
+OP(bf) { int tmp; RD_ZPG; BBS(3); } /* 4 BBS3 ZPG */
+OP(df) { int tmp; RD_ZPG; BBS(5); } /* 4 BBS5 ZPG */
+OP(ff) { int tmp; RD_ZPG; BBS(7); } /* 4 BBS7 ZPG */
+
+#ifdef M4510
+static void (*const insn4510[0x100])(m4510_Regs *) = {
+ m4510_00,m4510_01,m4510_02,m4510_03,m4510_04,m4510_05,m4510_06,m4510_07,
+ m4510_08,m4510_09,m4510_0a,m4510_0b,m4510_0c,m4510_0d,m4510_0e,m4510_0f,
+ m4510_10,m4510_11,m4510_12,m4510_13,m4510_14,m4510_15,m4510_16,m4510_17,
+ m4510_18,m4510_19,m4510_1a,m4510_1b,m4510_1c,m4510_1d,m4510_1e,m4510_1f,
+ m4510_20,m4510_21,m4510_22,m4510_23,m4510_24,m4510_25,m4510_26,m4510_27,
+ m4510_28,m4510_29,m4510_2a,m4510_2b,m4510_2c,m4510_2d,m4510_2e,m4510_2f,
+ m4510_30,m4510_31,m4510_32,m4510_33,m4510_34,m4510_35,m4510_36,m4510_37,
+ m4510_38,m4510_39,m4510_3a,m4510_3b,m4510_3c,m4510_3d,m4510_3e,m4510_3f,
+ m4510_40,m4510_41,m4510_42,m4510_43,m4510_44,m4510_45,m4510_46,m4510_47,
+ m4510_48,m4510_49,m4510_4a,m4510_4b,m4510_4c,m4510_4d,m4510_4e,m4510_4f,
+ m4510_50,m4510_51,m4510_52,m4510_53,m4510_54,m4510_55,m4510_56,m4510_57,
+ m4510_58,m4510_59,m4510_5a,m4510_5b,m4510_5c,m4510_5d,m4510_5e,m4510_5f,
+ m4510_60,m4510_61,m4510_62,m4510_63,m4510_64,m4510_65,m4510_66,m4510_67,
+ m4510_68,m4510_69,m4510_6a,m4510_6b,m4510_6c,m4510_6d,m4510_6e,m4510_6f,
+ m4510_70,m4510_71,m4510_72,m4510_73,m4510_74,m4510_75,m4510_76,m4510_77,
+ m4510_78,m4510_79,m4510_7a,m4510_7b,m4510_7c,m4510_7d,m4510_7e,m4510_7f,
+ m4510_80,m4510_81,m4510_82,m4510_83,m4510_84,m4510_85,m4510_86,m4510_87,
+ m4510_88,m4510_89,m4510_8a,m4510_8b,m4510_8c,m4510_8d,m4510_8e,m4510_8f,
+ m4510_90,m4510_91,m4510_92,m4510_93,m4510_94,m4510_95,m4510_96,m4510_97,
+ m4510_98,m4510_99,m4510_9a,m4510_9b,m4510_9c,m4510_9d,m4510_9e,m4510_9f,
+ m4510_a0,m4510_a1,m4510_a2,m4510_a3,m4510_a4,m4510_a5,m4510_a6,m4510_a7,
+ m4510_a8,m4510_a9,m4510_aa,m4510_ab,m4510_ac,m4510_ad,m4510_ae,m4510_af,
+ m4510_b0,m4510_b1,m4510_b2,m4510_b3,m4510_b4,m4510_b5,m4510_b6,m4510_b7,
+ m4510_b8,m4510_b9,m4510_ba,m4510_bb,m4510_bc,m4510_bd,m4510_be,m4510_bf,
+ m4510_c0,m4510_c1,m4510_c2,m4510_c3,m4510_c4,m4510_c5,m4510_c6,m4510_c7,
+ m4510_c8,m4510_c9,m4510_ca,m4510_cb,m4510_cc,m4510_cd,m4510_ce,m4510_cf,
+ m4510_d0,m4510_d1,m4510_d2,m4510_d3,m4510_d4,m4510_d5,m4510_d6,m4510_d7,
+ m4510_d8,m4510_d9,m4510_da,m4510_db,m4510_dc,m4510_dd,m4510_de,m4510_df,
+ m4510_e0,m4510_e1,m4510_e2,m4510_e3,m4510_e4,m4510_e5,m4510_e6,m4510_e7,
+ m4510_e8,m4510_e9,m4510_ea,m4510_eb,m4510_ec,m4510_ed,m4510_ee,m4510_ef,
+ m4510_f0,m4510_f1,m4510_f2,m4510_f3,m4510_f4,m4510_f5,m4510_f6,m4510_f7,
+ m4510_f8,m4510_f9,m4510_fa,m4510_fb,m4510_fc,m4510_fd,m4510_fe,m4510_ff
+};
+#else
+static void (*const insn65ce02[0x100])(m65ce02_Regs *) = {
+ m65ce02_00,m65ce02_01,m65ce02_02,m65ce02_03,m65ce02_04,m65ce02_05,m65ce02_06,m65ce02_07,
+ m65ce02_08,m65ce02_09,m65ce02_0a,m65ce02_0b,m65ce02_0c,m65ce02_0d,m65ce02_0e,m65ce02_0f,
+ m65ce02_10,m65ce02_11,m65ce02_12,m65ce02_13,m65ce02_14,m65ce02_15,m65ce02_16,m65ce02_17,
+ m65ce02_18,m65ce02_19,m65ce02_1a,m65ce02_1b,m65ce02_1c,m65ce02_1d,m65ce02_1e,m65ce02_1f,
+ m65ce02_20,m65ce02_21,m65ce02_22,m65ce02_23,m65ce02_24,m65ce02_25,m65ce02_26,m65ce02_27,
+ m65ce02_28,m65ce02_29,m65ce02_2a,m65ce02_2b,m65ce02_2c,m65ce02_2d,m65ce02_2e,m65ce02_2f,
+ m65ce02_30,m65ce02_31,m65ce02_32,m65ce02_33,m65ce02_34,m65ce02_35,m65ce02_36,m65ce02_37,
+ m65ce02_38,m65ce02_39,m65ce02_3a,m65ce02_3b,m65ce02_3c,m65ce02_3d,m65ce02_3e,m65ce02_3f,
+ m65ce02_40,m65ce02_41,m65ce02_42,m65ce02_43,m65ce02_44,m65ce02_45,m65ce02_46,m65ce02_47,
+ m65ce02_48,m65ce02_49,m65ce02_4a,m65ce02_4b,m65ce02_4c,m65ce02_4d,m65ce02_4e,m65ce02_4f,
+ m65ce02_50,m65ce02_51,m65ce02_52,m65ce02_53,m65ce02_54,m65ce02_55,m65ce02_56,m65ce02_57,
+ m65ce02_58,m65ce02_59,m65ce02_5a,m65ce02_5b,m65ce02_5c,m65ce02_5d,m65ce02_5e,m65ce02_5f,
+ m65ce02_60,m65ce02_61,m65ce02_62,m65ce02_63,m65ce02_64,m65ce02_65,m65ce02_66,m65ce02_67,
+ m65ce02_68,m65ce02_69,m65ce02_6a,m65ce02_6b,m65ce02_6c,m65ce02_6d,m65ce02_6e,m65ce02_6f,
+ m65ce02_70,m65ce02_71,m65ce02_72,m65ce02_73,m65ce02_74,m65ce02_75,m65ce02_76,m65ce02_77,
+ m65ce02_78,m65ce02_79,m65ce02_7a,m65ce02_7b,m65ce02_7c,m65ce02_7d,m65ce02_7e,m65ce02_7f,
+ m65ce02_80,m65ce02_81,m65ce02_82,m65ce02_83,m65ce02_84,m65ce02_85,m65ce02_86,m65ce02_87,
+ m65ce02_88,m65ce02_89,m65ce02_8a,m65ce02_8b,m65ce02_8c,m65ce02_8d,m65ce02_8e,m65ce02_8f,
+ m65ce02_90,m65ce02_91,m65ce02_92,m65ce02_93,m65ce02_94,m65ce02_95,m65ce02_96,m65ce02_97,
+ m65ce02_98,m65ce02_99,m65ce02_9a,m65ce02_9b,m65ce02_9c,m65ce02_9d,m65ce02_9e,m65ce02_9f,
+ m65ce02_a0,m65ce02_a1,m65ce02_a2,m65ce02_a3,m65ce02_a4,m65ce02_a5,m65ce02_a6,m65ce02_a7,
+ m65ce02_a8,m65ce02_a9,m65ce02_aa,m65ce02_ab,m65ce02_ac,m65ce02_ad,m65ce02_ae,m65ce02_af,
+ m65ce02_b0,m65ce02_b1,m65ce02_b2,m65ce02_b3,m65ce02_b4,m65ce02_b5,m65ce02_b6,m65ce02_b7,
+ m65ce02_b8,m65ce02_b9,m65ce02_ba,m65ce02_bb,m65ce02_bc,m65ce02_bd,m65ce02_be,m65ce02_bf,
+ m65ce02_c0,m65ce02_c1,m65ce02_c2,m65ce02_c3,m65ce02_c4,m65ce02_c5,m65ce02_c6,m65ce02_c7,
+ m65ce02_c8,m65ce02_c9,m65ce02_ca,m65ce02_cb,m65ce02_cc,m65ce02_cd,m65ce02_ce,m65ce02_cf,
+ m65ce02_d0,m65ce02_d1,m65ce02_d2,m65ce02_d3,m65ce02_d4,m65ce02_d5,m65ce02_d6,m65ce02_d7,
+ m65ce02_d8,m65ce02_d9,m65ce02_da,m65ce02_db,m65ce02_dc,m65ce02_dd,m65ce02_de,m65ce02_df,
+ m65ce02_e0,m65ce02_e1,m65ce02_e2,m65ce02_e3,m65ce02_e4,m65ce02_e5,m65ce02_e6,m65ce02_e7,
+ m65ce02_e8,m65ce02_e9,m65ce02_ea,m65ce02_eb,m65ce02_ec,m65ce02_ed,m65ce02_ee,m65ce02_ef,
+ m65ce02_f0,m65ce02_f1,m65ce02_f2,m65ce02_f3,m65ce02_f4,m65ce02_f5,m65ce02_f6,m65ce02_f7,
+ m65ce02_f8,m65ce02_f9,m65ce02_fa,m65ce02_fb,m65ce02_fc,m65ce02_fd,m65ce02_fe,m65ce02_ff
+};
+#endif
+
diff --git a/trunk/src/emu/cpu/m6502/t65sc02.c b/trunk/src/emu/cpu/m6502/t65sc02.c
new file mode 100644
index 00000000000..5796cd38514
--- /dev/null
+++ b/trunk/src/emu/cpu/m6502/t65sc02.c
@@ -0,0 +1,80 @@
+/*****************************************************************************
+ *
+ * tbl65sc02.c
+ * 65sc02 opcode functions and function pointer table
+ *
+ * Copyright Peter Trauner, all rights reserved.
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * pullmoll@t-online.de
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ *****************************************************************************/
+/* 4. February 2000 PeT fixed relative word operand */
+
+/* opcode already in 65c02
+ although docu says they were introduced with this cpu
+
+ bbr
+ bbs
+ rmb
+ smb
+ trb
+ tsb
+*/
+
+#undef OP
+#define OP(nn) INLINE void m65sc02_##nn(m6502_Regs *cpustate)
+
+/*****************************************************************************
+ *****************************************************************************
+ *
+ * overrides for 65SC02 opcodes
+ *
+ *****************************************************************************
+ * op temp cycles rdmem opc wrmem ********************/
+OP(63) { BSR; } /* 5? BSR */
+
+static void (*const insn65sc02[0x100])(m6502_Regs *cpustate) = {
+ m65c02_00,m65c02_01,m65c02_02,m65c02_03,m65c02_04,m65c02_05,m65c02_06,m65c02_07,
+ m65c02_08,m65c02_09,m65c02_0a,m65c02_0b,m65c02_0c,m65c02_0d,m65c02_0e,m65c02_0f,
+ m65c02_10,m65c02_11,m65c02_12,m65c02_13,m65c02_14,m65c02_15,m65c02_16,m65c02_17,
+ m65c02_18,m65c02_19,m65c02_1a,m65c02_1b,m65c02_1c,m65c02_1d,m65c02_1e,m65c02_1f,
+ m65c02_20,m65c02_21,m65c02_22,m65c02_23,m65c02_24,m65c02_25,m65c02_26,m65c02_27,
+ m65c02_28,m65c02_29,m65c02_2a,m65c02_2b,m65c02_2c,m65c02_2d,m65c02_2e,m65c02_2f,
+ m65c02_30,m65c02_31,m65c02_32,m65c02_33,m65c02_34,m65c02_35,m65c02_36,m65c02_37,
+ m65c02_38,m65c02_39,m65c02_3a,m65c02_3b,m65c02_3c,m65c02_3d,m65c02_3e,m65c02_3f,
+ m65c02_40,m65c02_41,m65c02_42,m65c02_43,m65c02_44,m65c02_45,m65c02_46,m65c02_47,
+ m65c02_48,m65c02_49,m65c02_4a,m65c02_4b,m65c02_4c,m65c02_4d,m65c02_4e,m65c02_4f,
+ m65c02_50,m65c02_51,m65c02_52,m65c02_53,m65c02_54,m65c02_55,m65c02_56,m65c02_57,
+ m65c02_58,m65c02_59,m65c02_5a,m65c02_5b,m65c02_5c,m65c02_5d,m65c02_5e,m65c02_5f,
+ m65c02_60,m65c02_61,m65c02_62,m65c02_63,m65c02_64,m65c02_65,m65c02_66,m65c02_67,
+ m65c02_68,m65c02_69,m65c02_6a,m65c02_6b,m65c02_6c,m65c02_6d,m65c02_6e,m65c02_6f,
+ m65c02_70,m65c02_71,m65c02_72,m65c02_73,m65c02_74,m65c02_75,m65c02_76,m65c02_77,
+ m65c02_78,m65c02_79,m65c02_7a,m65c02_7b,m65c02_7c,m65c02_7d,m65c02_7e,m65c02_7f,
+ m65c02_80,m65c02_81,m65c02_82,m65c02_83,m65c02_84,m65c02_85,m65c02_86,m65c02_87,
+ m65c02_88,m65c02_89,m65c02_8a,m65c02_8b,m65c02_8c,m65c02_8d,m65c02_8e,m65c02_8f,
+ m65c02_90,m65c02_91,m65c02_92,m65c02_93,m65c02_94,m65c02_95,m65c02_96,m65c02_97,
+ m65c02_98,m65c02_99,m65c02_9a,m65c02_9b,m65c02_9c,m65c02_9d,m65c02_9e,m65c02_9f,
+ m65c02_a0,m65c02_a1,m65c02_a2,m65c02_a3,m65c02_a4,m65c02_a5,m65c02_a6,m65c02_a7,
+ m65c02_a8,m65c02_a9,m65c02_aa,m65c02_ab,m65c02_ac,m65c02_ad,m65c02_ae,m65c02_af,
+ m65c02_b0,m65c02_b1,m65c02_b2,m65c02_b3,m65c02_b4,m65c02_b5,m65c02_b6,m65c02_b7,
+ m65c02_b8,m65c02_b9,m65c02_ba,m65c02_bb,m65c02_bc,m65c02_bd,m65c02_be,m65c02_bf,
+ m65c02_c0,m65c02_c1,m65c02_c2,m65c02_c3,m65c02_c4,m65c02_c5,m65c02_c6,m65c02_c7,
+ m65c02_c8,m65c02_c9,m65c02_ca,m65c02_cb,m65c02_cc,m65c02_cd,m65c02_ce,m65c02_cf,
+ m65c02_d0,m65c02_d1,m65c02_d2,m65c02_d3,m65c02_d4,m65c02_d5,m65c02_d6,m65c02_d7,
+ m65c02_d8,m65c02_d9,m65c02_da,m65c02_db,m65c02_dc,m65c02_dd,m65c02_de,m65c02_df,
+ m65c02_e0,m65c02_e1,m65c02_e2,m65c02_e3,m65c02_e4,m65c02_e5,m65c02_e6,m65c02_e7,
+ m65c02_e8,m65c02_e9,m65c02_ea,m65c02_eb,m65c02_ec,m65c02_ed,m65c02_ee,m65c02_ef,
+ m65c02_f0,m65c02_f1,m65c02_f2,m65c02_f3,m65c02_f4,m65c02_f5,m65c02_f6,m65c02_f7,
+ m65c02_f8,m65c02_f9,m65c02_fa,m65c02_fb,m65c02_fc,m65c02_fd,m65c02_fe,m65c02_ff
+};
+
diff --git a/trunk/src/emu/cpu/m6502/tdeco16.c b/trunk/src/emu/cpu/m6502/tdeco16.c
new file mode 100644
index 00000000000..f84b7489141
--- /dev/null
+++ b/trunk/src/emu/cpu/m6502/tdeco16.c
@@ -0,0 +1,428 @@
+/*****************************************************************************
+ * Deco CPU16 instructions - still very work in progress!
+ *
+ *****************************************************************************/
+
+#define DECO16_VERBOSE 0
+
+#undef OP
+#define OP(nn) INLINE void deco16_##nn(m6502_Regs *cpustate)
+
+#define DECO16_BRK \
+ logerror("%04x: BRK\n",PCW); \
+ RDOPARG(); \
+ PUSH(PCH); \
+ PUSH(PCL); \
+ PUSH(P | F_B); \
+ P = (P | F_I); \
+ PCL = RDMEM(DECO16_IRQ_VEC+1); \
+ PCH = RDMEM(DECO16_IRQ_VEC);
+
+
+/*****************************************************************************
+ *****************************************************************************
+ *
+ * overrides for 6502 opcodes
+ *
+ *****************************************************************************
+ * op temp cycles rdmem opc wrmem ********************/
+OP(00) { DECO16_BRK; } /* 7 BRK */
+#define deco16_20 m6502_20 /* 6 JSR ABS */
+#define deco16_40 m6502_40 /* 6 RTI */
+#define deco16_60 m6502_60 /* 6 RTS */
+OP(80) { RD_DUM; ILL; } /* 2 ILL */
+#define deco16_a0 m6502_a0 /* 2 LDY IMM */
+#define deco16_c0 m6502_c0 /* 2 CPY IMM */
+#define deco16_e0 m6502_e0 /* 2 CPX IMM */
+
+#define deco16_10 m6502_10 /* 2 BPL */
+#define deco16_30 m6502_30 /* 2 BMI */
+#define deco16_50 m6502_50 /* 2 BVC */
+#define deco16_70 m6502_70 /* 2 BVS */
+#define deco16_90 m6502_90 /* 2 BCC */
+#define deco16_b0 m6502_b0 /* 2 BCS */
+#define deco16_d0 m6502_d0 /* 2 BNE */
+#define deco16_f0 m6502_f0 /* 2 BEQ */
+
+#define deco16_01 m6502_01 /* 6 ORA IDX */
+#define deco16_21 m6502_21 /* 6 AND IDX */
+#define deco16_41 m6502_41 /* 6 EOR IDX */
+#define deco16_61 m6502_61 /* 6 ADC IDX */
+#define deco16_81 m6502_81 /* 6 STA IDX */
+#define deco16_a1 m6502_a1 /* 6 LDA IDX */
+#define deco16_c1 m6502_c1 /* 6 CMP IDX */
+#define deco16_e1 m6502_e1 /* 6 SBC IDX */
+
+#define deco16_11 m6502_11 /* 5 ORA IDY; */
+#define deco16_31 m6502_31 /* 5 AND IDY; */
+#define deco16_51 m6502_51 /* 5 EOR IDY; */
+#define deco16_71 m6502_71 /* 5 ADC IDY; */
+#define deco16_91 m6502_91 /* 6 STA IDY; */
+#define deco16_b1 m6502_b1 /* 5 LDA IDY; */
+#define deco16_d1 m6502_d1 /* 5 CMP IDY; */
+#define deco16_f1 m6502_f1 /* 5 SBC IDY; */
+
+OP(02) { RD_DUM; ILL; } /* 2 ILL */
+OP(22) { RD_DUM; ILL; } /* 2 ILL */
+OP(42) { RD_DUM; ILL; } /* 2 ILL */
+OP(62) { RD_DUM; ILL; } /* 2 ILL */
+OP(82) { RD_DUM; ILL; } /* 2 ILL */
+#define deco16_a2 m6502_a2 /* 2 LDX IMM */
+OP(c2) { RD_DUM; ILL; } /* 2 ILL */
+OP(e2) { RD_DUM; ILL; } /* 2 ILL */
+
+OP(12) { RD_DUM; ILL; } /* 2 ILL / 3 ora zpi ?? */
+OP(32) { RD_DUM; ILL; } /* 2 ILL / 3 and zpi ?? */
+OP(52) { RD_DUM; ILL; } /* 2 ILL / 3 eor zpi ?? */
+OP(72) { RD_DUM; ILL; } /* 2 ILL / 3 adc zpi ?? */
+OP(92) { RD_DUM; ILL; } /* 2 ILL / 3 sta zpi ?? */
+OP(b2) { RD_DUM; ILL; } /* 2 ILL / 3 lda zpi ?? */
+OP(d2) { RD_DUM; ILL; } /* 2 ILL / 3 cmp zpi ?? */
+OP(f2) { RD_DUM; ILL; } /* 2 ILL / 3 sbc zpi ?? */
+
+OP(03) { RD_DUM; ILL; } /* 2 ILL */
+OP(23) {
+ int tmp;
+
+ cpustate->icount -= 1;
+ RD_IMM;
+
+ if (DECO16_VERBOSE)
+ logerror("%04x: OP23 %02x\n",PCW,tmp);
+}
+OP(43) { RD_DUM; ILL; } /* 2 ILL */
+OP(63) {
+ int tmp;
+
+ cpustate->icount -= 1;
+ RD_IMM;
+
+ if (DECO16_VERBOSE)
+ logerror("%04x: OP63 %02x\n",PCW,tmp);
+}
+OP(83) { RD_DUM; ILL; } /* 2 ILL */
+OP(a3) {
+ int tmp;
+
+ cpustate->icount -= 1;
+ RD_IMM;
+
+ if (DECO16_VERBOSE)
+ logerror("%04x: OPA3 %02x\n",PCW,tmp);
+}
+OP(c3) { RD_DUM; ILL; } /* 2 ILL */
+OP(e3) { RD_DUM; ILL; } /* 2 ILL */
+
+OP(13) { int tmp; cpustate->icount -= 1; RD_IMM;
+
+ if (DECO16_VERBOSE)
+ logerror("%04x: OP13 %02x\n",PCW,tmp);
+
+//bank select control?
+
+ } /* */
+OP(33) { RD_DUM; ILL; } /* 2 ILL */
+OP(53) { RD_DUM; ILL; } /* 2 ILL */
+OP(73) { RD_DUM; ILL; } /* 2 ILL */
+OP(93) { RD_DUM; ILL; } /* 2 ILL */
+OP(b3) { RD_DUM; ILL; } /* 2 ILL */
+OP(d3) { RD_DUM; ILL; } /* 2 ILL */
+OP(f3) { RD_DUM; ILL; } /* 2 ILL */
+
+OP(04) { RD_DUM; ILL; } /* 2 ILL / 3 tsb zpg ?? */
+#define deco16_24 m6502_24 /* 3 BIT ZPG */
+OP(44) { RD_DUM; ILL; } /* 2 ILL */
+OP(64) { RD_DUM; ILL; } /* 2 ILL / 3 stz zpg ?? */
+#define deco16_84 m6502_84 /* 3 STY ZPG */
+#define deco16_a4 m6502_a4 /* 3 LDY ZPG */
+#define deco16_c4 m6502_c4 /* 3 CPY ZPG */
+#define deco16_e4 m6502_e4 /* 3 CPX ZPG */
+
+OP(14) { RD_DUM; ILL; } /* 2 ILL / 3 trb zpg ?? */
+OP(34) { RD_DUM; ILL; } /* 2 ILL / 4 bit zpx ?? */
+OP(54) { RD_DUM; ILL; } /* 2 ILL */
+OP(74) { RD_DUM; ILL; } /* 2 ILL / 4 stz zpx ?? */
+#define deco16_94 m6502_94 /* 4 sty zpx */
+#define deco16_b4 m6502_b4 /* 4 ldy zpx */
+OP(d4) { RD_DUM; ILL; } /* 2 ILL */
+OP(f4) { RD_DUM; ILL; } /* 2 ILL */
+
+#define deco16_05 m6502_05 /* 3 ORA ZPG */
+#define deco16_25 m6502_25 /* 3 AND ZPG */
+#define deco16_45 m6502_45 /* 3 EOR ZPG */
+#define deco16_65 m6502_65 /* 3 ADC ZPG */
+#define deco16_85 m6502_85 /* 3 STA ZPG */
+#define deco16_a5 m6502_a5 /* 3 LDA ZPG */
+#define deco16_c5 m6502_c5 /* 3 CMP ZPG */
+#define deco16_e5 m6502_e5 /* 3 SBC ZPG */
+
+#define deco16_15 m6502_15 /* 4 ORA ZPX */
+#define deco16_35 m6502_35 /* 4 AND ZPX */
+#define deco16_55 m6502_55 /* 4 EOR ZPX */
+#define deco16_75 m6502_75 /* 4 ADC ZPX */
+#define deco16_95 m6502_95 /* 4 STA ZPX */
+#define deco16_b5 m6502_b5 /* 4 LDA ZPX */
+#define deco16_d5 m6502_d5 /* 4 CMP ZPX */
+#define deco16_f5 m6502_f5 /* 4 SBC ZPX */
+
+#define deco16_06 m6502_06 /* 5 ASL ZPG */
+#define deco16_26 m6502_26 /* 5 ROL ZPG */
+#define deco16_46 m6502_46 /* 5 LSR ZPG */
+#define deco16_66 m6502_66 /* 5 ROR ZPG */
+#define deco16_86 m6502_86 /* 3 STX ZPG */
+#define deco16_a6 m6502_a6 /* 3 LDX ZPG */
+#define deco16_c6 m6502_c6 /* 5 DEC ZPG */
+#define deco16_e6 m6502_e6 /* 5 INC ZPG */
+
+#define deco16_16 m6502_16 /* 6 ASL ZPX */
+#define deco16_36 m6502_36 /* 6 ROL ZPX */
+#define deco16_56 m6502_56 /* 6 LSR ZPX */
+#define deco16_76 m6502_76 /* 6 ROR ZPX */
+#define deco16_96 m6502_96 /* 4 STX ZPY */
+#define deco16_b6 m6502_b6 /* 4 LDX ZPY */
+#define deco16_d6 m6502_d6 /* 6 DEC ZPX */
+#define deco16_f6 m6502_f6 /* 6 INC ZPX */
+
+OP(07) { RD_DUM; ILL; } /* 2 ILL / 5 RMB0 ZPG ?? */
+OP(27) { RD_DUM; ILL; } /* 2 ILL / 5 RMB2 ZPG ?? */
+OP(47) { RD_DUM; ILL; } /* 2 ILL / 5 RMB4 ZPG ?? */
+OP(67) {
+ RD_IMM_DISCARD;
+ cpustate->a=cpustate->io->read_byte(0);
+
+// logerror("%04x: VBL (0x67)\n",PCW);
+
+// really - wait for status?
+
+} /* */
+OP(87) { int tmp; cpustate->icount -= 1; RD_IMM;
+ logerror("%04x: OP87 %02x\n",PCW,tmp);
+
+} /* */
+OP(a7) { RD_DUM; ILL; } /* 2 ILL / 5 SMB2 ZPG ?? */
+OP(c7) { RD_DUM; ILL; } /* 2 ILL / 5 SMB4 ZPG ?? */
+OP(e7) { RD_DUM; ILL; } /* 2 ILL / 5 SMB6 ZPG ?? */
+
+OP(17) { RD_DUM; ILL; } /* 2 ILL / 5 RMB1 ZPG ?? */
+OP(37) { RD_DUM; ILL; } /* 2 ILL / 5 RMB3 ZPG ?? */
+OP(57) { RD_DUM; ILL; } /* 2 ILL / 5 RMB5 ZPG ?? */
+OP(77) { RD_DUM; ILL; } /* 2 ILL / 5 RMB7 ZPG ?? */
+OP(97) { RD_DUM; ILL; } /* 2 ILL / 5 SMB1 ZPG ?? */
+OP(b7) { RD_DUM; ILL; } /* 2 ILL / 5 SMB3 ZPG ?? */
+OP(d7) { RD_DUM; ILL; } /* 2 ILL / 5 SMB5 ZPG ?? */
+OP(f7) { RD_DUM; ILL; } /* 2 ILL / 5 SMB7 ZPG ?? */
+
+#define deco16_08 m6502_08 /* 3 PHP */
+#define deco16_28 m6502_28 /* 4 PLP */
+#define deco16_48 m6502_48 /* 3 PHA */
+#define deco16_68 m6502_68 /* 4 PLA */
+#define deco16_88 m6502_88 /* 2 DEY */
+#define deco16_a8 m6502_a8 /* 2 TAY */
+#define deco16_c8 m6502_c8 /* 2 INY */
+#define deco16_e8 m6502_e8 /* 2 INX */
+
+#define deco16_18 m6502_18 /* 2 CLC */
+#define deco16_38 m6502_38 /* 2 SEC */
+#define deco16_58 m6502_58 /* 2 CLI */
+#define deco16_78 m6502_78 /* 2 SEI */
+#define deco16_98 m6502_98 /* 2 TYA */
+#define deco16_b8 m6502_b8 /* 2 CLV */
+#define deco16_d8 m6502_d8 /* 2 CLD */
+#define deco16_f8 m6502_f8 /* 2 SED */
+
+#define deco16_09 m6502_09 /* 2 ORA IMM */
+#define deco16_29 m6502_29 /* 2 AND IMM */
+#define deco16_49 m6502_49 /* 2 EOR IMM */
+#define deco16_69 m6502_69 /* 2 ADC IMM */
+#define deco16_89 m65c02_89 /* 2 BIT IMM */
+#define deco16_a9 m6502_a9 /* 2 LDA IMM */
+#define deco16_c9 m6502_c9 /* 2 CMP IMM */
+#define deco16_e9 m6502_e9 /* 2 SBC IMM */
+
+#define deco16_19 m6502_19 /* 4 ORA ABY */
+#define deco16_39 m6502_39 /* 4 AND ABY */
+#define deco16_59 m6502_59 /* 4 EOR ABY */
+#define deco16_79 m6502_79 /* 4 ADC ABY */
+#define deco16_99 m6502_99 /* 5 STA ABY */
+#define deco16_b9 m6502_b9 /* 4 LDA ABY */
+#define deco16_d9 m6502_d9 /* 4 CMP ABY */
+#define deco16_f9 m6502_f9 /* 4 SBC ABY */
+
+#define deco16_0a m6502_0a /* 2 ASL */
+#define deco16_2a m6502_2a /* 2 ROL */
+#define deco16_4a m6502_4a /* 2 LSR */
+#define deco16_6a m6502_6a /* 2 ROR */
+#define deco16_8a m6502_8a /* 2 TXA */
+#define deco16_aa m6502_aa /* 2 TAX */
+#define deco16_ca m6502_ca /* 2 DEX */
+#define deco16_ea m6502_ea /* 2 NOP */
+
+#define deco16_1a m65c02_1a /* 2 INA */
+#define deco16_3a m65c02_3a /* 2 DEA */
+#define deco16_5a m65c02_5a /* 3 PHY */
+#define deco16_7a m65c02_7a /* 4 PLY */
+#define deco16_9a m6502_9a /* 2 TXS */
+#define deco16_ba m6502_ba /* 2 TSX */
+#define deco16_da m65c02_da /* 3 PHX */
+#define deco16_fa m65c02_fa /* 4 PLX */
+
+OP(0b) { int tmp; cpustate->icount -= 1; RD_IMM;
+ logerror("%04x: OP0B %02x\n",PCW,tmp);
+
+ }
+OP(2b) { RD_DUM; ILL; } /* 2 ILL */
+OP(4b) { cpustate->icount -= 1; RD_IMM_DISCARD;
+ //logerror("%04x: OP4B %02x\n",PCW,tmp);
+ /* TODO: Maybe it's just read I/O 0 and do a logic AND with bit 1? */
+ cpustate->a=cpustate->io->read_byte(1);
+
+//tilt??
+
+//VBL on expr-raider
+//VBL on boomrang (bit 2)
+
+ }
+OP(6b) { RD_DUM; ILL; } /* 2 ILL */
+OP(8b) { RD_DUM; ILL; } /* 2 ILL */
+OP(ab) { RD_DUM; ILL; } /* 2 ILL */
+OP(cb) { RD_DUM; ILL; } /* 2 ILL */
+OP(eb) { RD_DUM; ILL; } /* 2 ILL */
+
+OP(1b) { RD_DUM; ILL; } /* 2 ILL */
+OP(3b) { RD_DUM; ILL; } /* 2 ILL */
+OP(5b) { RD_DUM; ILL; } /* 2 ILL */
+OP(7b) { RD_DUM; ILL; } /* 2 ILL */
+OP(9b) { RD_DUM; ILL; } /* 2 ILL */
+OP(bb) {
+ int tmp;
+
+ cpustate->icount -= 1;
+ RD_IMM;
+
+ if (DECO16_VERBOSE)
+ logerror("%04x: OPBB %02x\n",PCW,tmp);
+}
+OP(db) { RD_DUM; ILL; } /* 2 ILL */
+OP(fb) { RD_DUM; ILL; } /* 2 ILL */
+
+#define deco16_0c m65c02_0c /* 4 TSB ABS */
+#define deco16_2c m6502_2c /* 4 BIT ABS */
+#define deco16_4c m6502_4c /* 3 JMP ABS */
+#define deco16_6c m65c02_6c /* 5 JMP IND */
+#define deco16_8c m6502_8c /* 4 STY ABS */
+#define deco16_ac m6502_ac /* 4 LDY ABS */
+#define deco16_cc m6502_cc /* 4 CPY ABS */
+#define deco16_ec m6502_ec /* 4 CPX ABS */
+
+#define deco16_1c m65c02_1c /* 4 TRB ABS */
+#define deco16_3c m65c02_3c /* 4 BIT ABX */
+OP(5c) { RD_DUM; ILL; } /* 2 ILL */
+#define deco16_7c m65c02_7c /* 6 JMP IAX */
+#define deco16_9c m65c02_9c /* 4 STZ ABS */
+#define deco16_bc m65c02_bc /* 4 LDY ABX */
+OP(dc) { RD_DUM; ILL; } /* 2 ILL */
+OP(fc) { RD_DUM; ILL; } /* 2 ILL */
+
+#define deco16_0d m6502_0d /* 4 ORA ABS */
+#define deco16_2d m6502_2d /* 4 AND ABS */
+#define deco16_4d m6502_4d /* 4 EOR ABS */
+#define deco16_6d m6502_6d /* 4 ADC ABS */
+#define deco16_8d m6502_8d /* 4 STA ABS */
+#define deco16_ad m6502_ad /* 4 LDA ABS */
+#define deco16_cd m6502_cd /* 4 CMP ABS */
+#define deco16_ed m6502_ed /* 4 SBC ABS */
+
+#define deco16_1d m6502_1d /* 4 ORA ABX */
+#define deco16_3d m6502_3d /* 4 AND ABX */
+#define deco16_5d m6502_5d /* 4 EOR ABX */
+#define deco16_7d m6502_7d /* 4 ADC ABX */
+#define deco16_9d m6502_9d /* 5 STA ABX */
+#define deco16_bd m6502_bd /* 4 LDA ABX */
+#define deco16_dd m6502_dd /* 4 CMP ABX */
+#define deco16_fd m6502_fd /* 4 SBC ABX */
+
+#define deco16_0e m6502_0e /* 6 ASL ABS */
+#define deco16_2e m6502_2e /* 6 ROL ABS */
+#define deco16_4e m6502_4e /* 6 LSR ABS */
+#define deco16_6e m6502_6e /* 6 ROR ABS */
+#define deco16_8e m6502_8e /* 4 STX ABS */
+#define deco16_ae m6502_ae /* 4 LDX ABS */
+#define deco16_ce m6502_ce /* 6 DEC ABS */
+#define deco16_ee m6502_ee /* 6 INC ABS */
+
+#define deco16_1e m6502_1e /* 7 ASL ABX */
+#define deco16_3e m6502_3e /* 7 ROL ABX */
+#define deco16_5e m6502_5e /* 7 LSR ABX */
+#define deco16_7e m6502_7e /* 7 ROR ABX */
+#define deco16_9e m65c02_9e /* 5 STZ ABX */
+#define deco16_be m6502_be /* 4 LDX ABY */
+#define deco16_de m6502_de /* 7 DEC ABX */
+#define deco16_fe m6502_fe /* 7 INC ABX */
+
+OP(0f) { RD_DUM; ILL; } /* 2 ILL / 5 BBR0 ZPG ?? */
+OP(2f) { RD_DUM; ILL; } /* 2 ILL / 5 BBR2 ZPG ?? */
+OP(4f) { RD_DUM; ILL; } /* 2 ILL / 5 BBR4 ZPG ?? */
+OP(6f) { RD_DUM; ILL; } /* 2 ILL / 5 BBR6 ZPG ?? */
+OP(8f) { int tmp; cpustate->icount -= 1; RD_IMM;
+ if (DECO16_VERBOSE)
+ logerror("%04x: BANK (8F) %02x\n",PCW,tmp);
+
+ cpustate->io->write_byte(0,tmp);
+
+ //swap bank in/out
+} /* */
+OP(af) { RD_DUM; ILL; } /* 2 ILL / 5 BBS2 ZPG ?? */
+OP(cf) { RD_DUM; ILL; } /* 2 ILL / 5 BBS4 ZPG ?? */
+OP(ef) { RD_DUM; ILL; } /* 2 ILL / 5 BBS6 ZPG ?? */
+
+OP(1f) { RD_DUM; ILL; } /* 2 ILL / 5 BBR1 ZPG ?? */
+OP(3f) {
+ int tmp;
+
+ cpustate->icount -= 1;
+ RD_IMM;
+
+ if (DECO16_VERBOSE)
+ logerror("%04x: OP3F %02x\n",PCW,tmp);
+}
+OP(5f) { RD_DUM; ILL; } /* 2 ILL / 5 BBR5 ZPG ?? */
+OP(7f) { RD_DUM; ILL; } /* 2 ILL / 5 BBR7 ZPG ?? */
+OP(9f) { RD_DUM; ILL; } /* 2 ILL / 5 BBS1 ZPG ?? */
+OP(bf) { RD_DUM; ILL; } /* 2 ILL / 5 BBS3 ZPG ?? */
+OP(df) { RD_DUM; ILL; } /* 2 ILL / 5 BBS5 ZPG ?? */
+OP(ff) { RD_DUM; ILL; } /* 2 ILL / 5 BBS7 ZPG ?? */
+
+static void (*const insndeco16[0x100])(m6502_Regs *cpustate) = {
+ deco16_00,deco16_01,deco16_02,deco16_03,deco16_04,deco16_05,deco16_06,deco16_07,
+ deco16_08,deco16_09,deco16_0a,deco16_0b,deco16_0c,deco16_0d,deco16_0e,deco16_0f,
+ deco16_10,deco16_11,deco16_12,deco16_13,deco16_14,deco16_15,deco16_16,deco16_17,
+ deco16_18,deco16_19,deco16_1a,deco16_1b,deco16_1c,deco16_1d,deco16_1e,deco16_1f,
+ deco16_20,deco16_21,deco16_22,deco16_23,deco16_24,deco16_25,deco16_26,deco16_27,
+ deco16_28,deco16_29,deco16_2a,deco16_2b,deco16_2c,deco16_2d,deco16_2e,deco16_2f,
+ deco16_30,deco16_31,deco16_32,deco16_33,deco16_34,deco16_35,deco16_36,deco16_37,
+ deco16_38,deco16_39,deco16_3a,deco16_3b,deco16_3c,deco16_3d,deco16_3e,deco16_3f,
+ deco16_40,deco16_41,deco16_42,deco16_43,deco16_44,deco16_45,deco16_46,deco16_47,
+ deco16_48,deco16_49,deco16_4a,deco16_4b,deco16_4c,deco16_4d,deco16_4e,deco16_4f,
+ deco16_50,deco16_51,deco16_52,deco16_53,deco16_54,deco16_55,deco16_56,deco16_57,
+ deco16_58,deco16_59,deco16_5a,deco16_5b,deco16_5c,deco16_5d,deco16_5e,deco16_5f,
+ deco16_60,deco16_61,deco16_62,deco16_63,deco16_64,deco16_65,deco16_66,deco16_67,
+ deco16_68,deco16_69,deco16_6a,deco16_6b,deco16_6c,deco16_6d,deco16_6e,deco16_6f,
+ deco16_70,deco16_71,deco16_72,deco16_73,deco16_74,deco16_75,deco16_76,deco16_77,
+ deco16_78,deco16_79,deco16_7a,deco16_7b,deco16_7c,deco16_7d,deco16_7e,deco16_7f,
+ deco16_80,deco16_81,deco16_82,deco16_83,deco16_84,deco16_85,deco16_86,deco16_87,
+ deco16_88,deco16_89,deco16_8a,deco16_8b,deco16_8c,deco16_8d,deco16_8e,deco16_8f,
+ deco16_90,deco16_91,deco16_92,deco16_93,deco16_94,deco16_95,deco16_96,deco16_97,
+ deco16_98,deco16_99,deco16_9a,deco16_9b,deco16_9c,deco16_9d,deco16_9e,deco16_9f,
+ deco16_a0,deco16_a1,deco16_a2,deco16_a3,deco16_a4,deco16_a5,deco16_a6,deco16_a7,
+ deco16_a8,deco16_a9,deco16_aa,deco16_ab,deco16_ac,deco16_ad,deco16_ae,deco16_af,
+ deco16_b0,deco16_b1,deco16_b2,deco16_b3,deco16_b4,deco16_b5,deco16_b6,deco16_b7,
+ deco16_b8,deco16_b9,deco16_ba,deco16_bb,deco16_bc,deco16_bd,deco16_be,deco16_bf,
+ deco16_c0,deco16_c1,deco16_c2,deco16_c3,deco16_c4,deco16_c5,deco16_c6,deco16_c7,
+ deco16_c8,deco16_c9,deco16_ca,deco16_cb,deco16_cc,deco16_cd,deco16_ce,deco16_cf,
+ deco16_d0,deco16_d1,deco16_d2,deco16_d3,deco16_d4,deco16_d5,deco16_d6,deco16_d7,
+ deco16_d8,deco16_d9,deco16_da,deco16_db,deco16_dc,deco16_dd,deco16_de,deco16_df,
+ deco16_e0,deco16_e1,deco16_e2,deco16_e3,deco16_e4,deco16_e5,deco16_e6,deco16_e7,
+ deco16_e8,deco16_e9,deco16_ea,deco16_eb,deco16_ec,deco16_ed,deco16_ee,deco16_ef,
+ deco16_f0,deco16_f1,deco16_f2,deco16_f3,deco16_f4,deco16_f5,deco16_f6,deco16_f7,
+ deco16_f8,deco16_f9,deco16_fa,deco16_fb,deco16_fc,deco16_fd,deco16_fe,deco16_ff
+};
diff --git a/trunk/src/emu/cpu/m6502/tn2a03.c b/trunk/src/emu/cpu/m6502/tn2a03.c
new file mode 100644
index 00000000000..34d6f1d52ae
--- /dev/null
+++ b/trunk/src/emu/cpu/m6502/tn2a03.c
@@ -0,0 +1,114 @@
+/*****************************************************************************
+ *
+ * tbl2a03.c
+ * 2a03 opcode functions and function pointer table
+ *
+ * The 2a03 is a 6502 CPU that does not support the decimal mode
+ * of the ADC and SBC instructions, so all opcodes except ADC/SBC
+ * are simply mapped to the m6502 ones.
+ *
+ * Copyright Juergen Buchmueller, all rights reserved.
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * pullmoll@t-online.de
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ *****************************************************************************/
+
+/*
+ based on the nmos 6502
+
+ b flag handling might be changed,
+ although only nmos series b-flag handling is quite sure
+*/
+
+
+#undef OP
+#define OP(nn) INLINE void n2a03_##nn(m6502_Regs *cpustate)
+
+/*****************************************************************************
+ *****************************************************************************
+ *
+ * overrides for 2a03 opcodes
+ *
+ *****************************************************************************
+ ********** insn temp cycles rdmem opc wrmem **********/
+OP(61) { int tmp; RD_IDX; ADC_NES; } /* 6 ADC IDX */
+OP(e1) { int tmp; RD_IDX; SBC_NES; } /* 6 SBC IDX */
+OP(71) { int tmp; RD_IDY_P; ADC_NES; } /* 5 ADC IDY page penalty */
+OP(f1) { int tmp; RD_IDY_P; SBC_NES; } /* 5 SBC IDY page penalty */
+OP(63) { int tmp; RD_IDX; WB_EA; RRA_NES; WB_EA; } /* 7 RRA IDX */
+OP(73) { int tmp; RD_IDY_NP; WB_EA; RRA_NES; WB_EA; } /* 7 RRA IDY */
+OP(e3) { int tmp; RD_IDX; WB_EA; ISB_NES; WB_EA; } /* 7 ISB IDX */
+OP(f3) { int tmp; RD_IDY_NP; WB_EA; ISB_NES; WB_EA; } /* 7 ISB IDY */
+OP(65) { int tmp; RD_ZPG; ADC_NES; } /* 3 ADC ZPG */
+OP(e5) { int tmp; RD_ZPG; SBC_NES; } /* 3 SBC ZPG */
+OP(75) { int tmp; RD_ZPX; ADC_NES; } /* 4 ADC ZPX */
+OP(f5) { int tmp; RD_ZPX; SBC_NES; } /* 4 SBC ZPX */
+OP(67) { int tmp; RD_ZPG; WB_EA; RRA_NES; WB_EA; } /* 5 RRA ZPG */
+OP(77) { int tmp; RD_ZPX; WB_EA; RRA_NES; WB_EA; } /* 6 RRA ZPX */
+OP(e7) { int tmp; RD_ZPG; WB_EA; ISB_NES; WB_EA; } /* 5 ISB ZPG */
+OP(f7) { int tmp; RD_ZPX; WB_EA; ISB_NES; WB_EA; } /* 6 ISB ZPX */
+OP(69) { int tmp; RD_IMM; ADC_NES; } /* 2 ADC IMM */
+OP(e9) { int tmp; RD_IMM; SBC_NES; } /* 2 SBC IMM */
+OP(79) { int tmp; RD_ABY_P; ADC_NES; } /* 4 ADC ABY page penalty */
+OP(f9) { int tmp; RD_ABY_P; SBC_NES; } /* 4 SBC ABY page penalty */
+OP(6b) { int tmp; RD_IMM; ARR_NES; WB_ACC; } /* 2 ARR IMM */
+OP(7b) { int tmp; RD_ABY_NP; WB_EA; RRA_NES; WB_EA; } /* 7 RRA ABY */
+OP(ab) { int tmp; RD_IMM; OAL_NES; } /* 2 OAL IMM */
+OP(eb) { int tmp; RD_IMM; SBC_NES; } /* 2 SBC IMM */
+OP(fb) { int tmp; RD_ABY_NP; WB_EA; ISB_NES; WB_EA; } /* 7 ISB ABY */
+OP(9c) { int tmp; EA_ABX_NP; SYH_NES; WB_EA; } /* 5 SYH ABX */
+OP(6d) { int tmp; RD_ABS; ADC_NES; } /* 4 ADC ABS */
+OP(ed) { int tmp; RD_ABS; SBC_NES; } /* 4 SBC ABS */
+OP(7d) { int tmp; RD_ABX_P; ADC_NES; } /* 4 ADC ABX page penalty */
+OP(fd) { int tmp; RD_ABX_P; SBC_NES; } /* 4 SBC ABX page penalty */
+OP(9e) { int tmp; EA_ABY_NP; SXH_NES; WB_EA; } /* 5 SXH ABY */
+OP(6f) { int tmp; RD_ABS; WB_EA; RRA_NES; WB_EA; } /* 6 RRA ABS */
+OP(7f) { int tmp; RD_ABX_NP; WB_EA; RRA_NES; WB_EA; } /* 7 RRA ABX */
+OP(ef) { int tmp; RD_ABS; WB_EA; ISB_NES; WB_EA; } /* 6 ISB ABS */
+OP(ff) { int tmp; RD_ABX_NP; WB_EA; ISB_NES; WB_EA; } /* 7 ISB ABX */
+
+
+static void (*const insn2a03[0x100])(m6502_Regs *cpustate) = {
+ m6502_00,m6502_01,m6502_02,m6502_03,m6502_04,m6502_05,m6502_06,m6502_07,
+ m6502_08,m6502_09,m6502_0a,m6502_0b,m6502_0c,m6502_0d,m6502_0e,m6502_0f,
+ m6502_10,m6502_11,m6502_12,m6502_13,m6502_14,m6502_15,m6502_16,m6502_17,
+ m6502_18,m6502_19,m6502_1a,m6502_1b,m6502_1c,m6502_1d,m6502_1e,m6502_1f,
+ m6502_20,m6502_21,m6502_22,m6502_23,m6502_24,m6502_25,m6502_26,m6502_27,
+ m6502_28,m6502_29,m6502_2a,m6502_2b,m6502_2c,m6502_2d,m6502_2e,m6502_2f,
+ m6502_30,m6502_31,m6502_32,m6502_33,m6502_34,m6502_35,m6502_36,m6502_37,
+ m6502_38,m6502_39,m6502_3a,m6502_3b,m6502_3c,m6502_3d,m6502_3e,m6502_3f,
+ m6502_40,m6502_41,m6502_42,m6502_43,m6502_44,m6502_45,m6502_46,m6502_47,
+ m6502_48,m6502_49,m6502_4a,m6502_4b,m6502_4c,m6502_4d,m6502_4e,m6502_4f,
+ m6502_50,m6502_51,m6502_52,m6502_53,m6502_54,m6502_55,m6502_56,m6502_57,
+ m6502_58,m6502_59,m6502_5a,m6502_5b,m6502_5c,m6502_5d,m6502_5e,m6502_5f,
+ m6502_60,n2a03_61,m6502_62,n2a03_63,m6502_64,n2a03_65,m6502_66,n2a03_67,
+ m6502_68,n2a03_69,m6502_6a,n2a03_6b,m6502_6c,n2a03_6d,m6502_6e,n2a03_6f,
+ m6502_70,n2a03_71,m6502_72,n2a03_73,m6502_74,n2a03_75,m6502_76,n2a03_77,
+ m6502_78,n2a03_79,m6502_7a,n2a03_7b,m6502_7c,n2a03_7d,m6502_7e,n2a03_7f,
+ m6502_80,m6502_81,m6502_82,m6502_83,m6502_84,m6502_85,m6502_86,m6502_87,
+ m6502_88,m6502_89,m6502_8a,m6502_8b,m6502_8c,m6502_8d,m6502_8e,m6502_8f,
+ m6502_90,m6502_91,m6502_92,m6502_93,m6502_94,m6502_95,m6502_96,m6502_97,
+ m6502_98,m6502_99,m6502_9a,m6502_9b,n2a03_9c,m6502_9d,n2a03_9e,m6502_9f,
+ m6502_a0,m6502_a1,m6502_a2,m6502_a3,m6502_a4,m6502_a5,m6502_a6,m6502_a7,
+ m6502_a8,m6502_a9,m6502_aa,n2a03_ab,m6502_ac,m6502_ad,m6502_ae,m6502_af,
+ m6502_b0,m6502_b1,m6502_b2,m6502_b3,m6502_b4,m6502_b5,m6502_b6,m6502_b7,
+ m6502_b8,m6502_b9,m6502_ba,m6502_bb,m6502_bc,m6502_bd,m6502_be,m6502_bf,
+ m6502_c0,m6502_c1,m6502_c2,m6502_c3,m6502_c4,m6502_c5,m6502_c6,m6502_c7,
+ m6502_c8,m6502_c9,m6502_ca,m6502_cb,m6502_cc,m6502_cd,m6502_ce,m6502_cf,
+ m6502_d0,m6502_d1,m6502_d2,m6502_d3,m6502_d4,m6502_d5,m6502_d6,m6502_d7,
+ m6502_d8,m6502_d9,m6502_da,m6502_db,m6502_dc,m6502_dd,m6502_de,m6502_df,
+ m6502_e0,n2a03_e1,m6502_e2,n2a03_e3,m6502_e4,n2a03_e5,m6502_e6,n2a03_e7,
+ m6502_e8,n2a03_e9,m6502_ea,n2a03_eb,m6502_ec,n2a03_ed,m6502_ee,n2a03_ef,
+ m6502_f0,n2a03_f1,m6502_f2,n2a03_f3,m6502_f4,n2a03_f5,m6502_f6,n2a03_f7,
+ m6502_f8,n2a03_f9,m6502_fa,n2a03_fb,m6502_fc,n2a03_fd,m6502_fe,n2a03_ff
+};
diff --git a/trunk/src/emu/cpu/m6800/6800dasm.c b/trunk/src/emu/cpu/m6800/6800dasm.c
new file mode 100644
index 00000000000..712de231159
--- /dev/null
+++ b/trunk/src/emu/cpu/m6800/6800dasm.c
@@ -0,0 +1,280 @@
+/*
+ * A quick-hack 6803/6808 disassembler
+ *
+ * Note: this is not the good and proper way to disassemble anything, but it works
+ *
+ * I'm afraid to put my name on it, but I feel obligated:
+ * This code written by Aaron Giles (agiles@sirius.com) for the MAME project
+ *
+ * History:
+ * 990314 HJB
+ * The disassembler knows about valid opcodes for M6800/1/2/3/8 and HD63701.
+ * 990302 HJB
+ * Changed the string array into a table of opcode names (or tokens) and
+ * argument types. This second try should give somewhat better results.
+ * Named the undocumented HD63701YO opcodes $12 and $13 'asx1' and 'asx2',
+ * since 'add contents of stack to x register' is what they do.
+ *
+ */
+
+#include "emu.h"
+#include "debugger.h"
+#include "m6800.h"
+
+enum addr_mode {
+ inh, /* inherent */
+ rel, /* relative */
+ imb, /* immediate (byte) */
+ imw, /* immediate (word) */
+ dir, /* direct address */
+ imd, /* HD63701YO: immediate, direct address */
+ ext, /* extended address */
+ idx, /* x + byte offset */
+ imx, /* HD63701YO: immediate, x + byte offset */
+ sx1 /* HD63701YO: undocumented opcodes: byte from (s+1) */
+};
+
+enum op_names {
+ aba=0, abx, adca, adcb, adda, addb, addd, aim,
+ anda, andb, asl, asla, aslb, asld, asr, asra,
+ asrb, bcc, bcs, beq, bge, bgt, bhi, bita,
+ bitb, ble, bls, blt, bmi, bne, bpl, bra,
+ brn, bsr, bvc, bvs, cba, clc, cli, clr,
+ clra, clrb, clv, cmpa, cmpb, cmpx, com, coma,
+ comb, daa, dec, deca, decb, des, dex, eim,
+ eora, eorb, ill, inc, inca, incb, ins, inx,
+ jmp, jsr, lda, ldb, ldd, lds, ldx, lsr,
+ lsra, lsrb, lsrd, mul, neg, nega, negb, nop,
+ oim, ora, orb, psha, pshb, pshx, pula, pulb,
+ pulx, rol, rola, rolb, ror, rora, rorb, rti,
+ rts, sba, sbca, sbcb, sec, sev, sta, stb,
+ _std, sei, sts, stx, suba, subb, subd, swi,
+ wai, tab, tap, tba, tim, tpa, tst, tsta,
+ tstb, tsx, txs, asx1, asx2, xgdx, addx, adcx
+};
+
+static const char *const op_name_str[] = {
+ "aba", "abx", "adca", "adcb", "adda", "addb", "addd", "aim",
+ "anda", "andb", "asl", "asla", "aslb", "asld", "asr", "asra",
+ "asrb", "bcc", "bcs", "beq", "bge", "bgt", "bhi", "bita",
+ "bitb", "ble", "bls", "blt", "bmi", "bne", "bpl", "bra",
+ "brn", "bsr", "bvc", "bvs", "cba", "clc", "cli", "clr",
+ "clra", "clrb", "clv", "cmpa", "cmpb", "cmpx", "com", "coma",
+ "comb", "daa", "dec", "deca", "decb", "des", "dex", "eim",
+ "eora", "eorb", "illegal","inc", "inca", "incb", "ins", "inx",
+ "jmp", "jsr", "lda", "ldb", "ldd", "lds", "ldx", "lsr",
+ "lsra", "lsrb", "lsrd", "mul", "neg", "nega", "negb", "nop",
+ "oim", "ora", "orb", "psha", "pshb", "pshx", "pula", "pulb",
+ "pulx", "rol", "rola", "rolb", "ror", "rora", "rorb", "rti",
+ "rts", "sba", "sbca", "sbcb", "sec", "sev", "sta", "stb",
+ "std", "sei", "sts", "stx", "suba", "subb", "subd", "swi",
+ "wai", "tab", "tap", "tba", "tim", "tpa", "tst", "tsta",
+ "tstb", "tsx", "txs", "asx1", "asx2", "xgdx", "addx", "adcx"
+};
+
+/*
+ * This table defines the opcodes:
+ * byte meaning
+ * 0 token (menmonic)
+ * 1 addressing mode
+ * 2 invalid opcode for 1:6800/6802/6808, 2:6801/6803, 4:HD63701
+ */
+
+static const UINT8 table[0x102][3] = {
+ {ill, inh,7},{nop, inh,0},{ill, inh,7},{ill, inh,7},/* 00 */
+ {lsrd,inh,1},{asld,inh,1},{tap, inh,0},{tpa, inh,0},
+ {inx, inh,0},{dex, inh,0},{clv, inh,0},{sev, inh,0},
+ {clc, inh,0},{sec, inh,0},{cli, inh,0},{sei, inh,0},
+ {sba, inh,0},{cba, inh,0},{asx1,sx1,0},{asx2,sx1,0},/* 10 */
+ {ill, inh,7},{ill, inh,7},{tab, inh,0},{tba, inh,0},
+ {xgdx,inh,3},{daa, inh,0},{ill, inh,7},{aba, inh,0},
+ {ill, inh,7},{ill, inh,7},{ill, inh,7},{ill, inh,7},
+ {bra, rel,0},{brn, rel,0},{bhi, rel,0},{bls, rel,0},/* 20 */
+ {bcc, rel,0},{bcs, rel,0},{bne, rel,0},{beq, rel,0},
+ {bvc, rel,0},{bvs, rel,0},{bpl, rel,0},{bmi, rel,0},
+ {bge, rel,0},{blt, rel,0},{bgt, rel,0},{ble, rel,0},
+ {tsx, inh,0},{ins, inh,0},{pula,inh,0},{pulb,inh,0},/* 30 */
+ {des, inh,0},{txs, inh,0},{psha,inh,0},{pshb,inh,0},
+ {pulx,inh,1},{rts, inh,0},{abx, inh,1},{rti, inh,0},
+ {pshx,inh,1},{mul, inh,1},{wai, inh,0},{swi, inh,0},
+ {nega,inh,0},{ill, inh,7},{ill, inh,7},{coma,inh,0},/* 40 */
+ {lsra,inh,0},{ill, inh,7},{rora,inh,0},{asra,inh,0},
+ {asla,inh,0},{rola,inh,0},{deca,inh,0},{ill, inh,7},
+ {inca,inh,0},{tsta,inh,0},{ill, inh,7},{clra,inh,0},
+ {negb,inh,0},{ill, inh,7},{ill, inh,7},{comb,inh,0},/* 50 */
+ {lsrb,inh,0},{ill, inh,7},{rorb,inh,0},{asrb,inh,0},
+ {aslb,inh,0},{rolb,inh,0},{decb,inh,0},{ill, inh,7},
+ {incb,inh,0},{tstb,inh,0},{ill, inh,7},{clrb,inh,0},
+ {neg, idx,0},{aim, imx,3},{oim, imx,3},{com, idx,0},/* 60 */
+ {lsr, idx,0},{eim, imx,3},{ror, idx,0},{asr, idx,0},
+ {asl, idx,0},{rol, idx,0},{dec, idx,0},{tim, imx,3},
+ {inc, idx,0},{tst, idx,0},{jmp, idx,0},{clr, idx,0},
+ {neg, ext,0},{aim, imd,3},{oim, imd,3},{com, ext,0},/* 70 */
+ {lsr, ext,0},{eim, imd,3},{ror, ext,0},{asr, ext,0},
+ {asl, ext,0},{rol, ext,0},{dec, ext,0},{tim, imd,3},
+ {inc, ext,0},{tst, ext,0},{jmp, ext,0},{clr, ext,0},
+ {suba,imb,0},{cmpa,imb,0},{sbca,imb,0},{subd,imw,1},/* 80 */
+ {anda,imb,0},{bita,imb,0},{lda, imb,0},{sta, imb,0},
+ {eora,imb,0},{adca,imb,0},{ora, imb,0},{adda,imb,0},
+ {cmpx,imw,0},{bsr, rel,0},{lds, imw,0},{sts, imw,0},
+ {suba,dir,0},{cmpa,dir,0},{sbca,dir,0},{subd,dir,1},/* 90 */
+ {anda,dir,0},{bita,dir,0},{lda, dir,0},{sta, dir,0},
+ {eora,dir,0},{adca,dir,0},{ora, dir,0},{adda,dir,0},
+ {cmpx,dir,0},{jsr, dir,0},{lds, dir,0},{sts, dir,0},
+ {suba,idx,0},{cmpa,idx,0},{sbca,idx,0},{subd,idx,1},/* a0 */
+ {anda,idx,0},{bita,idx,0},{lda, idx,0},{sta, idx,0},
+ {eora,idx,0},{adca,idx,0},{ora, idx,0},{adda,idx,0},
+ {cmpx,idx,0},{jsr, idx,0},{lds, idx,0},{sts, idx,0},
+ {suba,ext,0},{cmpa,ext,0},{sbca,ext,0},{subd,ext,1},/* b0 */
+ {anda,ext,0},{bita,ext,0},{lda, ext,0},{sta, ext,0},
+ {eora,ext,0},{adca,ext,0},{ora, ext,0},{adda,ext,0},
+ {cmpx,ext,0},{jsr, ext,0},{lds, ext,0},{sts, ext,0},
+ {subb,imb,0},{cmpb,imb,0},{sbcb,imb,0},{addd,imw,1},/* c0 */
+ {andb,imb,0},{bitb,imb,0},{ldb, imb,0},{stb, imb,0},
+ {eorb,imb,0},{adcb,imb,0},{orb, imb,0},{addb,imb,0},
+ {ldd, imw,1},{_std,imw,1},{ldx, imw,0},{stx, imw,0},
+ {subb,dir,0},{cmpb,dir,0},{sbcb,dir,0},{addd,dir,1},/* d0 */
+ {andb,dir,0},{bitb,dir,0},{ldb, dir,0},{stb, dir,0},
+ {eorb,dir,0},{adcb,dir,0},{orb, dir,0},{addb,dir,0},
+ {ldd, dir,1},{_std,dir,1},{ldx, dir,0},{stx, dir,0},
+ {subb,idx,0},{cmpb,idx,0},{sbcb,idx,0},{addd,idx,1},/* e0 */
+ {andb,idx,0},{bitb,idx,0},{ldb, idx,0},{stb, idx,0},
+ {eorb,idx,0},{adcb,idx,0},{orb, idx,0},{addb,idx,0},
+ {ldd, idx,1},{_std,idx,1},{ldx, idx,0},{stx, idx,0},
+ {subb,ext,0},{cmpb,ext,0},{sbcb,ext,0},{addd,ext,1},/* f0 */
+ {andb,ext,0},{bitb,ext,0},{ldb, ext,0},{stb, ext,0},
+ {eorb,ext,0},{adcb,ext,0},{orb, ext,0},{addb,ext,0},
+ {ldd, ext,1},{_std,ext,1},{ldx, ext,0},{stx, ext,0},
+
+ /* extra instruction $fc for NSC-8105 */
+ {addx,ext,0},
+ /* extra instruction $ec for NSC-8105 */
+ {adcx,imb,0}
+};
+
+/* some macros to keep things short */
+#define OP oprom[0]
+#define ARG1 opram[1]
+#define ARG2 opram[2]
+#define ARGW (opram[1]<<8) + opram[2]
+
+static unsigned Dasm680x (int subtype, char *buf, unsigned pc, const UINT8 *oprom, const UINT8 *opram)
+{
+ UINT32 flags = 0;
+ int invalid_mask;
+ int code = OP;
+ UINT8 opcode, args, invalid;
+
+ switch( subtype )
+ {
+ case 6800: case 6802: case 6808: case 8105:
+ invalid_mask = 1;
+ break;
+ case 6801: case 6803:
+ invalid_mask = 2;
+ break;
+ default:
+ invalid_mask = 4;
+ }
+
+ /* NSC-8105 is a special case */
+ if (subtype == 8105)
+ {
+ /* swap bits */
+ code = (code & 0x3c) | ((code & 0x41) << 1) | ((code & 0x82) >> 1);
+
+ /* and check for extra instruction */
+ if (code == 0xfc) code = 0x0100;
+ if (code == 0xec) code = 0x0101;
+ }
+
+ opcode = table[code][0];
+ args = table[code][1];
+ invalid = table[code][2];
+
+ if (opcode == bsr || opcode == jsr)
+ flags = DASMFLAG_STEP_OVER;
+ else if (opcode == rti || opcode == rts)
+ flags = DASMFLAG_STEP_OUT;
+
+ if ( invalid & invalid_mask ) /* invalid for this cpu type ? */
+ {
+ strcpy(buf, "illegal");
+ return 1 | flags | DASMFLAG_SUPPORTED;
+ }
+
+ buf += sprintf(buf, "%-5s", op_name_str[opcode]);
+
+ switch( args )
+ {
+ case rel: /* relative */
+ sprintf (buf, "$%04X", pc + (INT8)ARG1 + 2);
+ return 2 | flags | DASMFLAG_SUPPORTED;
+ case imb: /* immediate (byte) */
+ sprintf (buf, "#$%02X", ARG1);
+ return 2 | flags | DASMFLAG_SUPPORTED;
+ case imw: /* immediate (word) */
+ sprintf (buf, "#$%04X", ARGW);
+ return 3 | flags | DASMFLAG_SUPPORTED;
+ case idx: /* indexed + byte offset */
+ sprintf (buf, "(x+$%02X)", ARG1 );
+ return 2 | flags | DASMFLAG_SUPPORTED;
+ case imx: /* immediate, indexed + byte offset */
+ sprintf (buf, "#$%02X,(x+$%02x)", ARG1, ARG2 );
+ return 3 | flags | DASMFLAG_SUPPORTED;
+ case dir: /* direct address */
+ sprintf (buf, "$%02X", ARG1 );
+ return 2 | flags | DASMFLAG_SUPPORTED;
+ case imd: /* immediate, direct address */
+ sprintf (buf, "#$%02X,$%02X", ARG1, ARG2);
+ return 3 | flags | DASMFLAG_SUPPORTED;
+ case ext: /* extended address */
+ sprintf (buf, "$%04X", ARGW);
+ return 3 | flags | DASMFLAG_SUPPORTED;
+ case sx1: /* byte from address (s + 1) */
+ sprintf (buf, "(s+1)");
+ return 1 | flags | DASMFLAG_SUPPORTED;
+ default:
+ return 1 | flags | DASMFLAG_SUPPORTED;
+ }
+}
+
+CPU_DISASSEMBLE( m6800 )
+{
+ return Dasm680x(6800,buffer,pc,oprom,opram);
+}
+
+CPU_DISASSEMBLE( m6801 )
+{
+ return Dasm680x(6801,buffer,pc,oprom,opram);
+}
+
+CPU_DISASSEMBLE( m6802 )
+{
+ return Dasm680x(6802,buffer,pc,oprom,opram);
+}
+
+CPU_DISASSEMBLE( m6803 )
+{
+ return Dasm680x(6803,buffer,pc,oprom,opram);
+}
+
+CPU_DISASSEMBLE( m6808 )
+{
+ return Dasm680x(6808,buffer,pc,oprom,opram);
+}
+
+CPU_DISASSEMBLE( hd6301 )
+{
+ return Dasm680x(6301,buffer,pc,oprom,opram);
+}
+
+CPU_DISASSEMBLE( hd63701 )
+{
+ return Dasm680x(63701,buffer,pc,oprom,opram);
+}
+
+CPU_DISASSEMBLE( nsc8105 )
+{
+ return Dasm680x(8105,buffer,pc,oprom,opram);
+}
diff --git a/trunk/src/emu/cpu/m6800/6800ops.c b/trunk/src/emu/cpu/m6800/6800ops.c
new file mode 100644
index 00000000000..97aab2f8dba
--- /dev/null
+++ b/trunk/src/emu/cpu/m6800/6800ops.c
@@ -0,0 +1,2284 @@
+
+/*
+
+HNZVC
+
+? = undefined
+* = affected
+- = unaffected
+0 = cleared
+1 = set
+# = ccr directly affected by instruction
+@ = special - carry set if bit 7 is set
+
+*/
+
+#define OP_HANDLER(_name) INLINE void _name (m6800_state *cpustate)
+
+//OP_HANDLER( illegal )
+OP_HANDLER( illegal )
+{
+ logerror("m6800: illegal opcode: address %04X, op %02X\n",PC-1,(int) M_RDOP_ARG(PC-1)&0xFF);
+}
+
+/* HD63701 only */
+//OP_HANDLER( trap )
+OP_HANDLER( trap )
+{
+ logerror("m6800: illegal opcode: address %04X, op %02X\n",PC-1,(int) M_RDOP_ARG(PC-1)&0xFF);
+ TAKE_TRAP;
+}
+
+/* $00 ILLEGAL */
+
+/* $01 NOP */
+OP_HANDLER( nop )
+{
+}
+
+/* $02 ILLEGAL */
+
+/* $03 ILLEGAL */
+
+/* $04 LSRD inherent -0*-* */
+OP_HANDLER( lsrd )
+{
+ UINT16 t;
+ CLR_NZC; t = D; CC|=(t&0x0001);
+ t>>=1; SET_Z16(t); D=t;
+}
+
+/* $05 ASLD inherent ?**** */
+OP_HANDLER( asld )
+{
+ int r;
+ UINT16 t;
+ t = D; r=t<<1;
+ CLR_NZVC; SET_FLAGS16(t,t,r);
+ D=r;
+}
+
+/* $06 TAP inherent ##### */
+OP_HANDLER( tap )
+{
+ CC=A;
+ ONE_MORE_INSN();
+ CHECK_IRQ_LINES(cpustate); /* HJB 990417 */
+}
+
+/* $07 TPA inherent ----- */
+OP_HANDLER( tpa )
+{
+ A=CC;
+}
+
+/* $08 INX inherent --*-- */
+OP_HANDLER( inx )
+{
+ ++X;
+ CLR_Z; SET_Z16(X);
+}
+
+/* $09 DEX inherent --*-- */
+OP_HANDLER( dex )
+{
+ --X;
+ CLR_Z; SET_Z16(X);
+}
+
+/* $0a CLV */
+OP_HANDLER( clv )
+{
+ CLV;
+}
+
+/* $0b SEV */
+OP_HANDLER( sev )
+{
+ SEV;
+}
+
+/* $0c CLC */
+OP_HANDLER( clc )
+{
+ CLC;
+}
+
+/* $0d SEC */
+OP_HANDLER( sec )
+{
+ SEC;
+}
+
+/* $0e CLI */
+OP_HANDLER( cli )
+{
+ CLI;
+ ONE_MORE_INSN();
+ CHECK_IRQ_LINES(cpustate); /* HJB 990417 */
+}
+
+/* $0f SEI */
+OP_HANDLER( sei )
+{
+ SEI;
+ ONE_MORE_INSN();
+ CHECK_IRQ_LINES(cpustate); /* HJB 990417 */
+}
+
+/* $10 SBA inherent -**** */
+OP_HANDLER( sba )
+{
+ UINT16 t;
+ t=A-B;
+ CLR_NZVC; SET_FLAGS8(A,B,t);
+ A=t;
+}
+
+/* $11 CBA inherent -**** */
+OP_HANDLER( cba )
+{
+ UINT16 t;
+ t=A-B;
+ CLR_NZVC; SET_FLAGS8(A,B,t);
+}
+
+/* $12 ILLEGAL */
+OP_HANDLER( undoc1 )
+{
+ X += RM( S + 1 );
+}
+
+/* $13 ILLEGAL */
+OP_HANDLER( undoc2 )
+{
+ X += RM( S + 1 );
+}
+
+
+/* $14 ILLEGAL */
+
+/* $15 ILLEGAL */
+
+/* $16 TAB inherent -**0- */
+OP_HANDLER( tab )
+{
+ B=A;
+ CLR_NZV; SET_NZ8(B);
+}
+
+/* $17 TBA inherent -**0- */
+OP_HANDLER( tba )
+{
+ A=B;
+ CLR_NZV; SET_NZ8(A);
+}
+
+/* $18 XGDX inherent ----- */ /* HD63701YO only */
+OP_HANDLER( xgdx )
+{
+ UINT16 t = X;
+ X = D;
+ D=t;
+}
+
+/* $19 DAA inherent (A) -**0* */
+OP_HANDLER( daa )
+{
+ UINT8 msn, lsn;
+ UINT16 t, cf = 0;
+ msn=A & 0xf0; lsn=A & 0x0f;
+ if( lsn>0x09 || CC&0x20 ) cf |= 0x06;
+ if( msn>0x80 && lsn>0x09 ) cf |= 0x60;
+ if( msn>0x90 || CC&0x01 ) cf |= 0x60;
+ t = cf + A;
+ CLR_NZV; /* keep carry from previous operation */
+ SET_NZ8((UINT8)t); SET_C8(t);
+ A = t;
+}
+
+/* $1a ILLEGAL */
+
+/* $1a SLP */ /* HD63701YO only */
+OP_HANDLER( slp )
+{
+ /* wait for next IRQ (same as waiting of wai) */
+ cpustate->wai_state |= M6800_SLP;
+ EAT_CYCLES;
+}
+
+/* $1b ABA inherent ***** */
+OP_HANDLER( aba )
+{
+ UINT16 t;
+ t=A+B;
+ CLR_HNZVC; SET_FLAGS8(A,B,t); SET_H(A,B,t);
+ A=t;
+}
+
+/* $1c ILLEGAL */
+
+/* $1d ILLEGAL */
+
+/* $1e ILLEGAL */
+
+/* $1f ILLEGAL */
+
+/* $20 BRA relative ----- */
+OP_HANDLER( bra )
+{
+ UINT8 t;
+ IMMBYTE(t);
+ PC+=SIGNED(t);
+}
+
+/* $21 BRN relative ----- */
+static UINT8 m6800_brn_t; // hack around GCC 4.6 error because we need the side effects of IMMBYTE
+OP_HANDLER( brn )
+{
+ IMMBYTE(m6800_brn_t);
+}
+
+/* $22 BHI relative ----- */
+OP_HANDLER( bhi )
+{
+ UINT8 t;
+ BRANCH(!(CC&0x05));
+}
+
+/* $23 BLS relative ----- */
+OP_HANDLER( bls )
+{
+ UINT8 t;
+ BRANCH(CC&0x05);
+}
+
+/* $24 BCC relative ----- */
+OP_HANDLER( bcc )
+{
+ UINT8 t;
+ BRANCH(!(CC&0x01));
+}
+
+/* $25 BCS relative ----- */
+OP_HANDLER( bcs )
+{
+ UINT8 t;
+ BRANCH(CC&0x01);
+}
+
+/* $26 BNE relative ----- */
+OP_HANDLER( bne )
+{
+ UINT8 t;
+ BRANCH(!(CC&0x04));
+}
+
+/* $27 BEQ relative ----- */
+OP_HANDLER( beq )
+{
+ UINT8 t;
+ BRANCH(CC&0x04);
+}
+
+/* $28 BVC relative ----- */
+OP_HANDLER( bvc )
+{
+ UINT8 t;
+ BRANCH(!(CC&0x02));
+}
+
+/* $29 BVS relative ----- */
+OP_HANDLER( bvs )
+{
+ UINT8 t;
+ BRANCH(CC&0x02);
+}
+
+/* $2a BPL relative ----- */
+OP_HANDLER( bpl )
+{
+ UINT8 t;
+ BRANCH(!(CC&0x08));
+}
+
+/* $2b BMI relative ----- */
+OP_HANDLER( bmi )
+{
+ UINT8 t;
+ BRANCH(CC&0x08);
+}
+
+/* $2c BGE relative ----- */
+OP_HANDLER( bge )
+{
+ UINT8 t;
+ BRANCH(!NXORV);
+}
+
+/* $2d BLT relative ----- */
+OP_HANDLER( blt )
+{
+ UINT8 t;
+ BRANCH(NXORV);
+}
+
+/* $2e BGT relative ----- */
+OP_HANDLER( bgt )
+{
+ UINT8 t;
+ BRANCH(!(NXORV||CC&0x04));
+}
+
+/* $2f BLE relative ----- */
+OP_HANDLER( ble )
+{
+ UINT8 t;
+ BRANCH(NXORV||CC&0x04);
+}
+
+/* $30 TSX inherent ----- */
+OP_HANDLER( tsx )
+{
+ X = ( S + 1 );
+}
+
+/* $31 INS inherent ----- */
+OP_HANDLER( ins )
+{
+ ++S;
+}
+
+/* $32 PULA inherent ----- */
+OP_HANDLER( pula )
+{
+ PULLBYTE(cpustate->d.b.h);
+}
+
+/* $33 PULB inherent ----- */
+OP_HANDLER( pulb )
+{
+ PULLBYTE(cpustate->d.b.l);
+}
+
+/* $34 DES inherent ----- */
+OP_HANDLER( des )
+{
+ --S;
+}
+
+/* $35 TXS inherent ----- */
+OP_HANDLER( txs )
+{
+ S = ( X - 1 );
+}
+
+/* $36 PSHA inherent ----- */
+OP_HANDLER( psha )
+{
+ PUSHBYTE(cpustate->d.b.h);
+}
+
+/* $37 PSHB inherent ----- */
+OP_HANDLER( pshb )
+{
+ PUSHBYTE(cpustate->d.b.l);
+}
+
+/* $38 PULX inherent ----- */
+OP_HANDLER( pulx )
+{
+ PULLWORD(pX);
+}
+
+/* $39 RTS inherent ----- */
+OP_HANDLER( rts )
+{
+ PULLWORD(pPC);
+}
+
+/* $3a ABX inherent ----- */
+OP_HANDLER( abx )
+{
+ X += B;
+}
+
+/* $3b RTI inherent ##### */
+OP_HANDLER( rti )
+{
+ PULLBYTE(CC);
+ PULLBYTE(B);
+ PULLBYTE(A);
+ PULLWORD(pX);
+ PULLWORD(pPC);
+ CHECK_IRQ_LINES(cpustate); /* HJB 990417 */
+}
+
+/* $3c PSHX inherent ----- */
+OP_HANDLER( pshx )
+{
+ PUSHWORD(pX);
+}
+
+/* $3d MUL inherent --*-@ */
+OP_HANDLER( mul )
+{
+ UINT16 t;
+ t=A*B;
+ CLR_C;
+ if(t&0x80) SEC;
+ D=t;
+}
+
+/* $3e WAI inherent ----- */
+OP_HANDLER( wai )
+{
+ /*
+ * WAI stacks the entire machine state on the
+ * hardware stack, then waits for an interrupt.
+ */
+ cpustate->wai_state |= M6800_WAI;
+ PUSHWORD(pPC);
+ PUSHWORD(pX);
+ PUSHBYTE(A);
+ PUSHBYTE(B);
+ PUSHBYTE(CC);
+ CHECK_IRQ_LINES(cpustate);
+ if (cpustate->wai_state & M6800_WAI) EAT_CYCLES;
+}
+
+/* $3f SWI absolute indirect ----- */
+OP_HANDLER( swi )
+{
+ PUSHWORD(pPC);
+ PUSHWORD(pX);
+ PUSHBYTE(A);
+ PUSHBYTE(B);
+ PUSHBYTE(CC);
+ SEI;
+ PCD = RM16(cpustate, 0xfffa);
+}
+
+/* $40 NEGA inherent ?**** */
+OP_HANDLER( nega )
+{
+ UINT16 r;
+ r=-A;
+ CLR_NZVC; SET_FLAGS8(0,A,r);
+ A=r;
+}
+
+/* $41 ILLEGAL */
+
+/* $42 ILLEGAL */
+
+/* $43 COMA inherent -**01 */
+OP_HANDLER( coma )
+{
+ A = ~A;
+ CLR_NZV; SET_NZ8(A); SEC;
+}
+
+/* $44 LSRA inherent -0*-* */
+OP_HANDLER( lsra )
+{
+ CLR_NZC; CC|=(A&0x01);
+ A>>=1; SET_Z8(A);
+}
+
+/* $45 ILLEGAL */
+
+/* $46 RORA inherent -**-* */
+OP_HANDLER( rora )
+{
+ UINT8 r;
+ r=(CC&0x01)<<7;
+ CLR_NZC; CC|=(A&0x01);
+ r |= A>>1; SET_NZ8(r);
+ A=r;
+}
+
+/* $47 ASRA inherent ?**-* */
+OP_HANDLER( asra )
+{
+ CLR_NZC; CC|=(A&0x01);
+ A>>=1; A|=((A&0x40)<<1);
+ SET_NZ8(A);
+}
+
+/* $48 ASLA inherent ?**** */
+OP_HANDLER( asla )
+{
+ UINT16 r;
+ r=A<<1;
+ CLR_NZVC; SET_FLAGS8(A,A,r);
+ A=r;
+}
+
+/* $49 ROLA inherent -**** */
+OP_HANDLER( rola )
+{
+ UINT16 t,r;
+ t = A; r = CC&0x01; r |= t<<1;
+ CLR_NZVC; SET_FLAGS8(t,t,r);
+ A=r;
+}
+
+/* $4a DECA inherent -***- */
+OP_HANDLER( deca )
+{
+ --A;
+ CLR_NZV; SET_FLAGS8D(A);
+}
+
+/* $4b ILLEGAL */
+
+/* $4c INCA inherent -***- */
+OP_HANDLER( inca )
+{
+ ++A;
+ CLR_NZV; SET_FLAGS8I(A);
+}
+
+/* $4d TSTA inherent -**0- */
+OP_HANDLER( tsta )
+{
+ CLR_NZVC; SET_NZ8(A);
+}
+
+/* $4e ILLEGAL */
+
+/* $4f CLRA inherent -0100 */
+OP_HANDLER( clra )
+{
+ A=0;
+ CLR_NZVC; SEZ;
+}
+
+/* $50 NEGB inherent ?**** */
+OP_HANDLER( negb )
+{
+ UINT16 r;
+ r=-B;
+ CLR_NZVC; SET_FLAGS8(0,B,r);
+ B=r;
+}
+
+/* $51 ILLEGAL */
+
+/* $52 ILLEGAL */
+
+/* $53 COMB inherent -**01 */
+OP_HANDLER( comb )
+{
+ B = ~B;
+ CLR_NZV; SET_NZ8(B); SEC;
+}
+
+/* $54 LSRB inherent -0*-* */
+OP_HANDLER( lsrb )
+{
+ CLR_NZC; CC|=(B&0x01);
+ B>>=1; SET_Z8(B);
+}
+
+/* $55 ILLEGAL */
+
+/* $56 RORB inherent -**-* */
+OP_HANDLER( rorb )
+{
+ UINT8 r;
+ r=(CC&0x01)<<7;
+ CLR_NZC; CC|=(B&0x01);
+ r |= B>>1; SET_NZ8(r);
+ B=r;
+}
+
+/* $57 ASRB inherent ?**-* */
+OP_HANDLER( asrb )
+{
+ CLR_NZC; CC|=(B&0x01);
+ B>>=1; B|=((B&0x40)<<1);
+ SET_NZ8(B);
+}
+
+/* $58 ASLB inherent ?**** */
+OP_HANDLER( aslb )
+{
+ UINT16 r;
+ r=B<<1;
+ CLR_NZVC; SET_FLAGS8(B,B,r);
+ B=r;
+}
+
+/* $59 ROLB inherent -**** */
+OP_HANDLER( rolb )
+{
+ UINT16 t,r;
+ t = B; r = CC&0x01; r |= t<<1;
+ CLR_NZVC; SET_FLAGS8(t,t,r);
+ B=r;
+}
+
+/* $5a DECB inherent -***- */
+OP_HANDLER( decb )
+{
+ --B;
+ CLR_NZV; SET_FLAGS8D(B);
+}
+
+/* $5b ILLEGAL */
+
+/* $5c INCB inherent -***- */
+OP_HANDLER( incb )
+{
+ ++B;
+ CLR_NZV; SET_FLAGS8I(B);
+}
+
+/* $5d TSTB inherent -**0- */
+OP_HANDLER( tstb )
+{
+ CLR_NZVC; SET_NZ8(B);
+}
+
+/* $5e ILLEGAL */
+
+/* $5f CLRB inherent -0100 */
+OP_HANDLER( clrb )
+{
+ B=0;
+ CLR_NZVC; SEZ;
+}
+
+/* $60 NEG indexed ?**** */
+OP_HANDLER( neg_ix )
+{
+ UINT16 r,t;
+ IDXBYTE(t); r=-t;
+ CLR_NZVC; SET_FLAGS8(0,t,r);
+ WM(EAD,r);
+}
+
+/* $61 AIM --**0- */ /* HD63701YO only */
+OP_HANDLER( aim_ix )
+{
+ UINT8 t, r;
+ IMMBYTE(t);
+ IDXBYTE(r);
+ r &= t;
+ CLR_NZV; SET_NZ8(r);
+ WM(EAD,r);
+}
+
+/* $62 OIM --**0- */ /* HD63701YO only */
+OP_HANDLER( oim_ix )
+{
+ UINT8 t, r;
+ IMMBYTE(t);
+ IDXBYTE(r);
+ r |= t;
+ CLR_NZV; SET_NZ8(r);
+ WM(EAD,r);
+}
+
+/* $63 COM indexed -**01 */
+OP_HANDLER( com_ix )
+{
+ UINT8 t;
+ IDXBYTE(t); t = ~t;
+ CLR_NZV; SET_NZ8(t); SEC;
+ WM(EAD,t);
+}
+
+/* $64 LSR indexed -0*-* */
+OP_HANDLER( lsr_ix )
+{
+ UINT8 t;
+ IDXBYTE(t); CLR_NZC; CC|=(t&0x01);
+ t>>=1; SET_Z8(t);
+ WM(EAD,t);
+}
+
+/* $65 EIM --**0- */ /* HD63701YO only */
+OP_HANDLER( eim_ix )
+{
+ UINT8 t, r;
+ IMMBYTE(t);
+ IDXBYTE(r);
+ r ^= t;
+ CLR_NZV; SET_NZ8(r);
+ WM(EAD,r);
+}
+
+/* $66 ROR indexed -**-* */
+OP_HANDLER( ror_ix )
+{
+ UINT8 t,r;
+ IDXBYTE(t); r=(CC&0x01)<<7;
+ CLR_NZC; CC|=(t&0x01);
+ r |= t>>1; SET_NZ8(r);
+ WM(EAD,r);
+}
+
+/* $67 ASR indexed ?**-* */
+OP_HANDLER( asr_ix )
+{
+ UINT8 t;
+ IDXBYTE(t); CLR_NZC; CC|=(t&0x01);
+ t>>=1; t|=((t&0x40)<<1);
+ SET_NZ8(t);
+ WM(EAD,t);
+}
+
+/* $68 ASL indexed ?**** */
+OP_HANDLER( asl_ix )
+{
+ UINT16 t,r;
+ IDXBYTE(t); r=t<<1;
+ CLR_NZVC; SET_FLAGS8(t,t,r);
+ WM(EAD,r);
+}
+
+/* $69 ROL indexed -**** */
+OP_HANDLER( rol_ix )
+{
+ UINT16 t,r;
+ IDXBYTE(t); r = CC&0x01; r |= t<<1;
+ CLR_NZVC; SET_FLAGS8(t,t,r);
+ WM(EAD,r);
+}
+
+/* $6a DEC indexed -***- */
+OP_HANDLER( dec_ix )
+{
+ UINT8 t;
+ IDXBYTE(t); --t;
+ CLR_NZV; SET_FLAGS8D(t);
+ WM(EAD,t);
+}
+
+/* $6b TIM --**0- */ /* HD63701YO only */
+OP_HANDLER( tim_ix )
+{
+ UINT8 t, r;
+ IMMBYTE(t);
+ IDXBYTE(r);
+ r &= t;
+ CLR_NZV; SET_NZ8(r);
+}
+
+/* $6c INC indexed -***- */
+OP_HANDLER( inc_ix )
+{
+ UINT8 t;
+ IDXBYTE(t); ++t;
+ CLR_NZV; SET_FLAGS8I(t);
+ WM(EAD,t);
+}
+
+/* $6d TST indexed -**0- */
+OP_HANDLER( tst_ix )
+{
+ UINT8 t;
+ IDXBYTE(t); CLR_NZVC; SET_NZ8(t);
+}
+
+/* $6e JMP indexed ----- */
+OP_HANDLER( jmp_ix )
+{
+ INDEXED; PC=EA;
+}
+
+/* $6f CLR indexed -0100 */
+OP_HANDLER( clr_ix )
+{
+ INDEXED; WM(EAD,0);
+ CLR_NZVC; SEZ;
+}
+
+/* $70 NEG extended ?**** */
+OP_HANDLER( neg_ex )
+{
+ UINT16 r,t;
+ EXTBYTE(t); r=-t;
+ CLR_NZVC; SET_FLAGS8(0,t,r);
+ WM(EAD,r);
+}
+
+/* $71 AIM --**0- */ /* HD63701YO only */
+OP_HANDLER( aim_di )
+{
+ UINT8 t, r;
+ IMMBYTE(t);
+ DIRBYTE(r);
+ r &= t;
+ CLR_NZV; SET_NZ8(r);
+ WM(EAD,r);
+}
+
+/* $72 OIM --**0- */ /* HD63701YO only */
+OP_HANDLER( oim_di )
+{
+ UINT8 t, r;
+ IMMBYTE(t);
+ DIRBYTE(r);
+ r |= t;
+ CLR_NZV; SET_NZ8(r);
+ WM(EAD,r);
+}
+
+/* $73 COM extended -**01 */
+OP_HANDLER( com_ex )
+{
+ UINT8 t;
+ EXTBYTE(t); t = ~t;
+ CLR_NZV; SET_NZ8(t); SEC;
+ WM(EAD,t);
+}
+
+/* $74 LSR extended -0*-* */
+OP_HANDLER( lsr_ex )
+{
+ UINT8 t;
+ EXTBYTE(t);
+ CLR_NZC;
+ CC|=(t&0x01);
+ t>>=1;
+ SET_Z8(t);
+ WM(EAD,t);
+}
+
+/* $75 EIM --**0- */ /* HD63701YO only */
+OP_HANDLER( eim_di )
+{
+ UINT8 t, r;
+ IMMBYTE(t);
+ DIRBYTE(r);
+ r ^= t;
+ CLR_NZV; SET_NZ8(r);
+ WM(EAD,r);
+}
+
+/* $76 ROR extended -**-* */
+OP_HANDLER( ror_ex )
+{
+ UINT8 t,r;
+ EXTBYTE(t); r=(CC&0x01)<<7;
+ CLR_NZC; CC|=(t&0x01);
+ r |= t>>1; SET_NZ8(r);
+ WM(EAD,r);
+}
+
+/* $77 ASR extended ?**-* */
+OP_HANDLER( asr_ex )
+{
+ UINT8 t;
+ EXTBYTE(t); CLR_NZC; CC|=(t&0x01);
+ t>>=1; t|=((t&0x40)<<1);
+ SET_NZ8(t);
+ WM(EAD,t);
+}
+
+/* $78 ASL extended ?**** */
+OP_HANDLER( asl_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t); r=t<<1;
+ CLR_NZVC; SET_FLAGS8(t,t,r);
+ WM(EAD,r);
+}
+
+/* $79 ROL extended -**** */
+OP_HANDLER( rol_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t); r = CC&0x01; r |= t<<1;
+ CLR_NZVC; SET_FLAGS8(t,t,r);
+ WM(EAD,r);
+}
+
+/* $7a DEC extended -***- */
+OP_HANDLER( dec_ex )
+{
+ UINT8 t;
+ EXTBYTE(t); --t;
+ CLR_NZV; SET_FLAGS8D(t);
+ WM(EAD,t);
+}
+
+/* $7b TIM --**0- */ /* HD63701YO only */
+OP_HANDLER( tim_di )
+{
+ UINT8 t, r;
+ IMMBYTE(t);
+ DIRBYTE(r);
+ r &= t;
+ CLR_NZV; SET_NZ8(r);
+}
+
+/* $7c INC extended -***- */
+OP_HANDLER( inc_ex )
+{
+ UINT8 t;
+ EXTBYTE(t); ++t;
+ CLR_NZV; SET_FLAGS8I(t);
+ WM(EAD,t);
+}
+
+/* $7d TST extended -**0- */
+OP_HANDLER( tst_ex )
+{
+ UINT8 t;
+ EXTBYTE(t); CLR_NZVC; SET_NZ8(t);
+}
+
+/* $7e JMP extended ----- */
+OP_HANDLER( jmp_ex )
+{
+ EXTENDED; PC=EA;
+}
+
+/* $7f CLR extended -0100 */
+OP_HANDLER( clr_ex )
+{
+ EXTENDED; WM(EAD,0);
+ CLR_NZVC; SEZ;
+}
+
+/* $80 SUBA immediate ?**** */
+OP_HANDLER( suba_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t); r = A-t;
+ CLR_NZVC; SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $81 CMPA immediate ?**** */
+OP_HANDLER( cmpa_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t); r = A-t;
+ CLR_NZVC; SET_FLAGS8(A,t,r);
+}
+
+/* $82 SBCA immediate ?**** */
+OP_HANDLER( sbca_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t); r = A-t-(CC&0x01);
+ CLR_NZVC; SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $83 SUBD immediate -**** */
+OP_HANDLER( subd_im )
+{
+ UINT32 r,d;
+ PAIR b;
+ IMMWORD(b);
+ d = D;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ D = r;
+}
+
+/* $84 ANDA immediate -**0- */
+OP_HANDLER( anda_im )
+{
+ UINT8 t;
+ IMMBYTE(t); A &= t;
+ CLR_NZV; SET_NZ8(A);
+}
+
+/* $85 BITA immediate -**0- */
+OP_HANDLER( bita_im )
+{
+ UINT8 t,r;
+ IMMBYTE(t); r = A&t;
+ CLR_NZV; SET_NZ8(r);
+}
+
+/* $86 LDA immediate -**0- */
+OP_HANDLER( lda_im )
+{
+ IMMBYTE(A);
+ CLR_NZV; SET_NZ8(A);
+}
+
+/* is this a legal instruction? */
+/* $87 STA immediate -**0- */
+OP_HANDLER( sta_im )
+{
+ CLR_NZV; SET_NZ8(A);
+ IMM8; WM(EAD,A);
+}
+
+/* $88 EORA immediate -**0- */
+OP_HANDLER( eora_im )
+{
+ UINT8 t;
+ IMMBYTE(t); A ^= t;
+ CLR_NZV; SET_NZ8(A);
+}
+
+/* $89 ADCA immediate ***** */
+OP_HANDLER( adca_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t); r = A+t+(CC&0x01);
+ CLR_HNZVC; SET_FLAGS8(A,t,r); SET_H(A,t,r);
+ A = r;
+}
+
+/* $8a ORA immediate -**0- */
+OP_HANDLER( ora_im )
+{
+ UINT8 t;
+ IMMBYTE(t); A |= t;
+ CLR_NZV; SET_NZ8(A);
+}
+
+/* $8b ADDA immediate ***** */
+OP_HANDLER( adda_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t); r = A+t;
+ CLR_HNZVC; SET_FLAGS8(A,t,r); SET_H(A,t,r);
+ A = r;
+}
+
+/* $8c CMPX immediate -***- */
+OP_HANDLER( cmpx_im )
+{
+ UINT32 r,d;
+ PAIR b;
+ IMMWORD(b);
+ d = X;
+ r = d - b.d;
+ CLR_NZV;
+ SET_NZ16(r); SET_V16(d,b.d,r);
+}
+
+/* $8c CPX immediate -**** (6803) */
+OP_HANDLER( cpx_im )
+{
+ UINT32 r,d;
+ PAIR b;
+ IMMWORD(b);
+ d = X;
+ r = d - b.d;
+ CLR_NZVC; SET_FLAGS16(d,b.d,r);
+}
+
+
+/* $8d BSR ----- */
+OP_HANDLER( bsr )
+{
+ UINT8 t;
+ IMMBYTE(t);
+ PUSHWORD(pPC);
+ PC += SIGNED(t);
+}
+
+/* $8e LDS immediate -**0- */
+OP_HANDLER( lds_im )
+{
+ IMMWORD(cpustate->s);
+ CLR_NZV;
+ SET_NZ16(S);
+}
+
+/* $8f STS immediate -**0- */
+OP_HANDLER( sts_im )
+{
+ CLR_NZV;
+ SET_NZ16(S);
+ IMM16;
+ WM16(cpustate, EAD,&cpustate->s);
+}
+
+/* $90 SUBA direct ?**** */
+OP_HANDLER( suba_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t); r = A-t;
+ CLR_NZVC; SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $91 CMPA direct ?**** */
+OP_HANDLER( cmpa_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t); r = A-t;
+ CLR_NZVC; SET_FLAGS8(A,t,r);
+}
+
+/* $92 SBCA direct ?**** */
+OP_HANDLER( sbca_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t); r = A-t-(CC&0x01);
+ CLR_NZVC; SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $93 SUBD direct -**** */
+OP_HANDLER( subd_di )
+{
+ UINT32 r,d;
+ PAIR b;
+ DIRWORD(b);
+ d = D;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ D=r;
+}
+
+/* $94 ANDA direct -**0- */
+OP_HANDLER( anda_di )
+{
+ UINT8 t;
+ DIRBYTE(t); A &= t;
+ CLR_NZV; SET_NZ8(A);
+}
+
+/* $95 BITA direct -**0- */
+OP_HANDLER( bita_di )
+{
+ UINT8 t,r;
+ DIRBYTE(t); r = A&t;
+ CLR_NZV; SET_NZ8(r);
+}
+
+/* $96 LDA direct -**0- */
+OP_HANDLER( lda_di )
+{
+ DIRBYTE(A);
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $97 STA direct -**0- */
+OP_HANDLER( sta_di )
+{
+ CLR_NZV;
+ SET_NZ8(A);
+ DIRECT;
+ WM(EAD,A);
+}
+
+/* $98 EORA direct -**0- */
+OP_HANDLER( eora_di )
+{
+ UINT8 t;
+ DIRBYTE(t);
+ A ^= t;
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $99 ADCA direct ***** */
+OP_HANDLER( adca_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = A+t+(CC&0x01);
+ CLR_HNZVC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $9a ORA direct -**0- */
+OP_HANDLER( ora_di )
+{
+ UINT8 t;
+ DIRBYTE(t);
+ A |= t;
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $9b ADDA direct ***** */
+OP_HANDLER( adda_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = A + t;
+ CLR_HNZVC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $9c CMPX direct -***- */
+OP_HANDLER( cmpx_di )
+{
+ UINT32 r,d;
+ PAIR b;
+ DIRWORD(b);
+ d = X;
+ r = d - b.d;
+ CLR_NZV;
+ SET_NZ16(r);
+ SET_V16(d,b.d,r);
+}
+
+/* $9c CPX direct -**** (6803) */
+OP_HANDLER( cpx_di )
+{
+ UINT32 r,d;
+ PAIR b;
+ DIRWORD(b);
+ d = X;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $9d JSR direct ----- */
+OP_HANDLER( jsr_di )
+{
+ DIRECT;
+ PUSHWORD(pPC);
+ PC = EA;
+}
+
+/* $9e LDS direct -**0- */
+OP_HANDLER( lds_di )
+{
+ DIRWORD(cpustate->s);
+ CLR_NZV;
+ SET_NZ16(S);
+}
+
+/* $9f STS direct -**0- */
+OP_HANDLER( sts_di )
+{
+ CLR_NZV;
+ SET_NZ16(S);
+ DIRECT;
+ WM16(cpustate, EAD,&cpustate->s);
+}
+
+/* $a0 SUBA indexed ?**** */
+OP_HANDLER( suba_ix )
+{
+ UINT16 t,r;
+ IDXBYTE(t);
+ r = A - t;
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $a1 CMPA indexed ?**** */
+OP_HANDLER( cmpa_ix )
+{
+ UINT16 t,r;
+ IDXBYTE(t);
+ r = A - t;
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+}
+
+/* $a2 SBCA indexed ?**** */
+OP_HANDLER( sbca_ix )
+{
+ UINT16 t,r;
+ IDXBYTE(t);
+ r = A - t - (CC&0x01);
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $a3 SUBD indexed -**** */
+OP_HANDLER( subd_ix )
+{
+ UINT32 r,d;
+ PAIR b;
+ IDXWORD(b);
+ d = D;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ D = r;
+}
+
+/* $a4 ANDA indexed -**0- */
+OP_HANDLER( anda_ix )
+{
+ UINT8 t;
+ IDXBYTE(t); A &= t;
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $a5 BITA indexed -**0- */
+OP_HANDLER( bita_ix )
+{
+ UINT8 t,r;
+ IDXBYTE(t); r = A&t;
+ CLR_NZV;
+ SET_NZ8(r);
+}
+
+/* $a6 LDA indexed -**0- */
+OP_HANDLER( lda_ix )
+{
+ IDXBYTE(A);
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $a7 STA indexed -**0- */
+OP_HANDLER( sta_ix )
+{
+ CLR_NZV;
+ SET_NZ8(A);
+ INDEXED;
+ WM(EAD,A);
+}
+
+/* $a8 EORA indexed -**0- */
+OP_HANDLER( eora_ix )
+{
+ UINT8 t;
+ IDXBYTE(t);
+ A ^= t;
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $a9 ADCA indexed ***** */
+OP_HANDLER( adca_ix )
+{
+ UINT16 t,r;
+ IDXBYTE(t);
+ r = A + t + (CC&0x01);
+ CLR_HNZVC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $aa ORA indexed -**0- */
+OP_HANDLER( ora_ix )
+{
+ UINT8 t;
+ IDXBYTE(t);
+ A |= t;
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $ab ADDA indexed ***** */
+OP_HANDLER( adda_ix )
+{
+ UINT16 t,r;
+ IDXBYTE(t);
+ r = A+t;
+ CLR_HNZVC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $ac CMPX indexed -***- */
+OP_HANDLER( cmpx_ix )
+{
+ UINT32 r,d;
+ PAIR b;
+ IDXWORD(b);
+ d = X;
+ r = d - b.d;
+ CLR_NZV;
+ SET_NZ16(r);
+ SET_V16(d,b.d,r);
+}
+
+/* $ac CPX indexed -**** (6803)*/
+OP_HANDLER( cpx_ix )
+{
+ UINT32 r,d;
+ PAIR b;
+ IDXWORD(b);
+ d = X;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $ad JSR indexed ----- */
+OP_HANDLER( jsr_ix )
+{
+ INDEXED;
+ PUSHWORD(pPC);
+ PC = EA;
+}
+
+/* $ae LDS indexed -**0- */
+OP_HANDLER( lds_ix )
+{
+ IDXWORD(cpustate->s);
+ CLR_NZV;
+ SET_NZ16(S);
+}
+
+/* $af STS indexed -**0- */
+OP_HANDLER( sts_ix )
+{
+ CLR_NZV;
+ SET_NZ16(S);
+ INDEXED;
+ WM16(cpustate, EAD,&cpustate->s);
+}
+
+/* $b0 SUBA extended ?**** */
+OP_HANDLER( suba_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = A - t;
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $b1 CMPA extended ?**** */
+OP_HANDLER( cmpa_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = A-t;
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+}
+
+/* $b2 SBCA extended ?**** */
+OP_HANDLER( sbca_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = A-t-(CC&0x01);
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $b3 SUBD extended -**** */
+OP_HANDLER( subd_ex )
+{
+ UINT32 r,d;
+ PAIR b;
+ EXTWORD(b);
+ d = D;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ D=r;
+}
+
+/* $b4 ANDA extended -**0- */
+OP_HANDLER( anda_ex )
+{
+ UINT8 t;
+ EXTBYTE(t);
+ A &= t;
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $b5 BITA extended -**0- */
+OP_HANDLER( bita_ex )
+{
+ UINT8 t,r;
+ EXTBYTE(t);
+ r = A&t;
+ CLR_NZV;
+ SET_NZ8(r);
+}
+
+/* $b6 LDA extended -**0- */
+OP_HANDLER( lda_ex )
+{
+ EXTBYTE(A);
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $b7 STA extended -**0- */
+OP_HANDLER( sta_ex )
+{
+ CLR_NZV;
+ SET_NZ8(A);
+ EXTENDED;
+ WM(EAD,A);
+}
+
+/* $b8 EORA extended -**0- */
+OP_HANDLER( eora_ex )
+{
+ UINT8 t;
+ EXTBYTE(t);
+ A ^= t;
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $b9 ADCA extended ***** */
+OP_HANDLER( adca_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = A+t+(CC&0x01);
+ CLR_HNZVC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $ba ORA extended -**0- */
+OP_HANDLER( ora_ex )
+{
+ UINT8 t;
+ EXTBYTE(t);
+ A |= t;
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $bb ADDA extended ***** */
+OP_HANDLER( adda_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = A+t;
+ CLR_HNZVC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $bc CMPX extended -***- */
+OP_HANDLER( cmpx_ex )
+{
+ UINT32 r,d;
+ PAIR b;
+ EXTWORD(b);
+ d = X;
+ r = d - b.d;
+ CLR_NZV;
+ SET_NZ16(r);
+ SET_V16(d,b.d,r);
+}
+
+/* $bc CPX extended -**** (6803) */
+OP_HANDLER( cpx_ex )
+{
+ UINT32 r,d;
+ PAIR b;
+ EXTWORD(b);
+ d = X;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $bd JSR extended ----- */
+OP_HANDLER( jsr_ex )
+{
+ EXTENDED;
+ PUSHWORD(pPC);
+ PC = EA;
+}
+
+/* $be LDS extended -**0- */
+OP_HANDLER( lds_ex )
+{
+ EXTWORD(cpustate->s);
+ CLR_NZV;
+ SET_NZ16(S);
+}
+
+/* $bf STS extended -**0- */
+OP_HANDLER( sts_ex )
+{
+ CLR_NZV;
+ SET_NZ16(S);
+ EXTENDED;
+ WM16(cpustate, EAD,&cpustate->s);
+}
+
+/* $c0 SUBB immediate ?**** */
+OP_HANDLER( subb_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t);
+ r = B-t;
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+ B = r;
+}
+
+/* $c1 CMPB immediate ?**** */
+OP_HANDLER( cmpb_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t);
+ r = B-t;
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+}
+
+/* $c2 SBCB immediate ?**** */
+OP_HANDLER( sbcb_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t);
+ r = B-t-(CC&0x01);
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+ B = r;
+}
+
+/* $c3 ADDD immediate -**** */
+OP_HANDLER( addd_im )
+{
+ UINT32 r,d;
+ PAIR b;
+ IMMWORD(b);
+ d = D;
+ r = d + b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ D = r;
+}
+
+/* $c4 ANDB immediate -**0- */
+OP_HANDLER( andb_im )
+{
+ UINT8 t;
+ IMMBYTE(t);
+ B &= t;
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $c5 BITB immediate -**0- */
+OP_HANDLER( bitb_im )
+{
+ UINT8 t,r;
+ IMMBYTE(t);
+ r = B&t;
+ CLR_NZV;
+ SET_NZ8(r);
+}
+
+/* $c6 LDB immediate -**0- */
+OP_HANDLER( ldb_im )
+{
+ IMMBYTE(B);
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* is this a legal instruction? */
+/* $c7 STB immediate -**0- */
+OP_HANDLER( stb_im )
+{
+ CLR_NZV;
+ SET_NZ8(B);
+ IMM8;
+ WM(EAD,B);
+}
+
+/* $c8 EORB immediate -**0- */
+OP_HANDLER( eorb_im )
+{
+ UINT8 t;
+ IMMBYTE(t);
+ B ^= t;
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $c9 ADCB immediate ***** */
+OP_HANDLER( adcb_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t);
+ r = B+t+(CC&0x01);
+ CLR_HNZVC;
+ SET_FLAGS8(B,t,r);
+ SET_H(B,t,r);
+ B = r;
+}
+
+/* $ca ORB immediate -**0- */
+OP_HANDLER( orb_im )
+{
+ UINT8 t;
+ IMMBYTE(t);
+ B |= t;
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $cb ADDB immediate ***** */
+OP_HANDLER( addb_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t);
+ r = B+t;
+ CLR_HNZVC;
+ SET_FLAGS8(B,t,r);
+ SET_H(B,t,r);
+ B = r;
+}
+
+/* $CC LDD immediate -**0- */
+OP_HANDLER( ldd_im )
+{
+ IMMWORD(cpustate->d);
+ CLR_NZV;
+ SET_NZ16(D);
+}
+
+/* is this a legal instruction? */
+/* $cd STD immediate -**0- */
+OP_HANDLER( std_im )
+{
+ IMM16;
+ CLR_NZV;
+ SET_NZ16(D);
+ WM16(cpustate, EAD,&cpustate->d);
+}
+
+/* $ce LDX immediate -**0- */
+OP_HANDLER( ldx_im )
+{
+ IMMWORD(cpustate->x);
+ CLR_NZV;
+ SET_NZ16(X);
+}
+
+/* $cf STX immediate -**0- */
+OP_HANDLER( stx_im )
+{
+ CLR_NZV;
+ SET_NZ16(X);
+ IMM16;
+ WM16(cpustate, EAD,&cpustate->x);
+}
+
+/* $d0 SUBB direct ?**** */
+OP_HANDLER( subb_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = B-t;
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+ B = r;
+}
+
+/* $d1 CMPB direct ?**** */
+OP_HANDLER( cmpb_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = B-t;
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+}
+
+/* $d2 SBCB direct ?**** */
+OP_HANDLER( sbcb_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = B-t-(CC&0x01);
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+ B = r;
+}
+
+/* $d3 ADDD direct -**** */
+OP_HANDLER( addd_di )
+{
+ UINT32 r,d;
+ PAIR b;
+ DIRWORD(b);
+ d = D;
+ r = d + b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ D = r;
+}
+
+/* $d4 ANDB direct -**0- */
+OP_HANDLER( andb_di )
+{
+ UINT8 t;
+ DIRBYTE(t);
+ B &= t;
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $d5 BITB direct -**0- */
+OP_HANDLER( bitb_di )
+{
+ UINT8 t,r;
+ DIRBYTE(t);
+ r = B&t;
+ CLR_NZV;
+ SET_NZ8(r);
+}
+
+/* $d6 LDB direct -**0- */
+OP_HANDLER( ldb_di )
+{
+ DIRBYTE(B);
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $d7 STB direct -**0- */
+OP_HANDLER( stb_di )
+{
+ CLR_NZV;
+ SET_NZ8(B);
+ DIRECT;
+ WM(EAD,B);
+}
+
+/* $d8 EORB direct -**0- */
+OP_HANDLER( eorb_di )
+{
+ UINT8 t;
+ DIRBYTE(t);
+ B ^= t;
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $d9 ADCB direct ***** */
+OP_HANDLER( adcb_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = B+t+(CC&0x01);
+ CLR_HNZVC;
+ SET_FLAGS8(B,t,r);
+ SET_H(B,t,r);
+ B = r;
+}
+
+/* $da ORB direct -**0- */
+OP_HANDLER( orb_di )
+{
+ UINT8 t;
+ DIRBYTE(t);
+ B |= t;
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $db ADDB direct ***** */
+OP_HANDLER( addb_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = B+t;
+ CLR_HNZVC;
+ SET_FLAGS8(B,t,r);
+ SET_H(B,t,r);
+ B = r;
+}
+
+/* $dc LDD direct -**0- */
+OP_HANDLER( ldd_di )
+{
+ DIRWORD(cpustate->d);
+ CLR_NZV;
+ SET_NZ16(D);
+}
+
+/* $dd STD direct -**0- */
+OP_HANDLER( std_di )
+{
+ DIRECT;
+ CLR_NZV;
+ SET_NZ16(D);
+ WM16(cpustate, EAD,&cpustate->d);
+}
+
+/* $de LDX direct -**0- */
+OP_HANDLER( ldx_di )
+{
+ DIRWORD(cpustate->x);
+ CLR_NZV;
+ SET_NZ16(X);
+}
+
+/* $dF STX direct -**0- */
+OP_HANDLER( stx_di )
+{
+ CLR_NZV;
+ SET_NZ16(X);
+ DIRECT;
+ WM16(cpustate, EAD,&cpustate->x);
+}
+
+/* $e0 SUBB indexed ?**** */
+OP_HANDLER( subb_ix )
+{
+ UINT16 t,r;
+ IDXBYTE(t);
+ r = B-t;
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+ B = r;
+}
+
+/* $e1 CMPB indexed ?**** */
+OP_HANDLER( cmpb_ix )
+{
+ UINT16 t,r;
+ IDXBYTE(t);
+ r = B-t;
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+}
+
+/* $e2 SBCB indexed ?**** */
+OP_HANDLER( sbcb_ix )
+{
+ UINT16 t,r;
+ IDXBYTE(t);
+ r = B-t-(CC&0x01);
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+ B = r;
+}
+
+/* $e3 ADDD indexed -**** */
+OP_HANDLER( addd_ix )
+{
+ UINT32 r,d;
+ PAIR b;
+ IDXWORD(b);
+ d = D;
+ r = d + b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ D = r;
+}
+
+/* $e4 ANDB indexed -**0- */
+OP_HANDLER( andb_ix )
+{
+ UINT8 t;
+ IDXBYTE(t);
+ B &= t;
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $e5 BITB indexed -**0- */
+OP_HANDLER( bitb_ix )
+{
+ UINT8 t,r;
+ IDXBYTE(t);
+ r = B&t;
+ CLR_NZV;
+ SET_NZ8(r);
+}
+
+/* $e6 LDB indexed -**0- */
+OP_HANDLER( ldb_ix )
+{
+ IDXBYTE(B);
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $e7 STB indexed -**0- */
+OP_HANDLER( stb_ix )
+{
+ CLR_NZV;
+ SET_NZ8(B);
+ INDEXED;
+ WM(EAD,B);
+}
+
+/* $e8 EORB indexed -**0- */
+OP_HANDLER( eorb_ix )
+{
+ UINT8 t;
+ IDXBYTE(t);
+ B ^= t;
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $e9 ADCB indexed ***** */
+OP_HANDLER( adcb_ix )
+{
+ UINT16 t,r;
+ IDXBYTE(t);
+ r = B+t+(CC&0x01);
+ CLR_HNZVC;
+ SET_FLAGS8(B,t,r);
+ SET_H(B,t,r);
+ B = r;
+}
+
+/* $ea ORB indexed -**0- */
+OP_HANDLER( orb_ix )
+{
+ UINT8 t;
+ IDXBYTE(t);
+ B |= t;
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $eb ADDB indexed ***** */
+OP_HANDLER( addb_ix )
+{
+ UINT16 t,r;
+ IDXBYTE(t);
+ r = B+t;
+ CLR_HNZVC;
+ SET_FLAGS8(B,t,r);
+ SET_H(B,t,r);
+ B = r;
+}
+
+/* $ec LDD indexed -**0- */
+OP_HANDLER( ldd_ix )
+{
+ IDXWORD(cpustate->d);
+ CLR_NZV;
+ SET_NZ16(D);
+}
+
+/* $ec ADCX immediate -**** NSC8105 only. Flags are a guess - copied from addb_im() */
+OP_HANDLER( adcx_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t);
+ r = X+t+(CC&0x01);
+ CLR_HNZVC;
+ SET_FLAGS8(X,t,r);
+ SET_H(X,t,r);
+ X = r;
+}
+
+/* $ed STD indexed -**0- */
+OP_HANDLER( std_ix )
+{
+ INDEXED;
+ CLR_NZV;
+ SET_NZ16(D);
+ WM16(cpustate, EAD,&cpustate->d);
+}
+
+/* $ee LDX indexed -**0- */
+OP_HANDLER( ldx_ix )
+{
+ IDXWORD(cpustate->x);
+ CLR_NZV;
+ SET_NZ16(X);
+}
+
+/* $ef STX indexed -**0- */
+OP_HANDLER( stx_ix )
+{
+ CLR_NZV;
+ SET_NZ16(X);
+ INDEXED;
+ WM16(cpustate, EAD,&cpustate->x);
+}
+
+/* $f0 SUBB extended ?**** */
+OP_HANDLER( subb_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = B-t;
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+ B = r;
+}
+
+/* $f1 CMPB extended ?**** */
+OP_HANDLER( cmpb_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = B-t;
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+}
+
+/* $f2 SBCB extended ?**** */
+OP_HANDLER( sbcb_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = B-t-(CC&0x01);
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+ B = r;
+}
+
+/* $f3 ADDD extended -**** */
+OP_HANDLER( addd_ex )
+{
+ UINT32 r,d;
+ PAIR b;
+ EXTWORD(b);
+ d = D;
+ r = d + b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ D = r;
+}
+
+/* $f4 ANDB extended -**0- */
+OP_HANDLER( andb_ex )
+{
+ UINT8 t;
+ EXTBYTE(t);
+ B &= t;
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $f5 BITB extended -**0- */
+OP_HANDLER( bitb_ex )
+{
+ UINT8 t,r;
+ EXTBYTE(t);
+ r = B & t;
+ CLR_NZV;
+ SET_NZ8(r);
+}
+
+/* $f6 LDB extended -**0- */
+OP_HANDLER( ldb_ex )
+{
+ EXTBYTE(B);
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $f7 STB extended -**0- */
+OP_HANDLER( stb_ex )
+{
+ CLR_NZV;
+ SET_NZ8(B);
+ EXTENDED;
+ WM(EAD,B);
+}
+
+/* $f8 EORB extended -**0- */
+OP_HANDLER( eorb_ex )
+{
+ UINT8 t;
+ EXTBYTE(t);
+ B ^= t;
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $f9 ADCB extended ***** */
+OP_HANDLER( adcb_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = B+t+(CC&0x01);
+ CLR_HNZVC;
+ SET_FLAGS8(B,t,r);
+ SET_H(B,t,r);
+ B = r;
+}
+
+/* $fa ORB extended -**0- */
+OP_HANDLER( orb_ex )
+{
+ UINT8 t;
+ EXTBYTE(t);
+ B |= t;
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $fb ADDB extended ***** */
+OP_HANDLER( addb_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = B+t;
+ CLR_HNZVC;
+ SET_FLAGS8(B,t,r);
+ SET_H(B,t,r);
+ B = r;
+}
+
+/* $fc LDD extended -**0- */
+OP_HANDLER( ldd_ex )
+{
+ EXTWORD(cpustate->d);
+ CLR_NZV;
+ SET_NZ16(D);
+}
+
+/* $fc ADDX extended -**** NSC8105 only. Flags are a guess */
+OP_HANDLER( addx_ex )
+{
+ UINT32 r,d;
+ PAIR b;
+ EXTWORD(b);
+ d = X;
+ r = d + b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ X = r;
+}
+
+/* $fd STD extended -**0- */
+OP_HANDLER( std_ex )
+{
+ EXTENDED;
+ CLR_NZV;
+ SET_NZ16(D);
+ WM16(cpustate, EAD,&cpustate->d);
+}
+
+/* $fe LDX extended -**0- */
+OP_HANDLER( ldx_ex )
+{
+ EXTWORD(cpustate->x);
+ CLR_NZV;
+ SET_NZ16(X);
+}
+
+/* $ff STX extended -**0- */
+OP_HANDLER( stx_ex )
+{
+ CLR_NZV;
+ SET_NZ16(X);
+ EXTENDED;
+ WM16(cpustate, EAD,&cpustate->x);
+}
diff --git a/trunk/src/emu/cpu/m6800/6800tbl.c b/trunk/src/emu/cpu/m6800/6800tbl.c
new file mode 100644
index 00000000000..eae581b0671
--- /dev/null
+++ b/trunk/src/emu/cpu/m6800/6800tbl.c
@@ -0,0 +1,386 @@
+INLINE void aba(m6800_state *cpustate);
+INLINE void abx(m6800_state *cpustate);
+INLINE void adca_di(m6800_state *cpustate);
+INLINE void adca_ex(m6800_state *cpustate);
+INLINE void adca_im(m6800_state *cpustate);
+INLINE void adca_ix(m6800_state *cpustate);
+INLINE void adcb_di(m6800_state *cpustate);
+INLINE void adcb_ex(m6800_state *cpustate);
+INLINE void adcb_im(m6800_state *cpustate);
+INLINE void adcb_ix(m6800_state *cpustate);
+INLINE void adcx_im(m6800_state *cpustate);
+INLINE void adda_di(m6800_state *cpustate);
+INLINE void adda_ex(m6800_state *cpustate);
+INLINE void adda_im(m6800_state *cpustate);
+INLINE void adda_ix(m6800_state *cpustate);
+INLINE void addb_di(m6800_state *cpustate);
+INLINE void addb_ex(m6800_state *cpustate);
+INLINE void addb_im(m6800_state *cpustate);
+INLINE void addb_ix(m6800_state *cpustate);
+INLINE void addd_di(m6800_state *cpustate);
+INLINE void addd_ex(m6800_state *cpustate);
+INLINE void addx_ex(m6800_state *cpustate);
+INLINE void addd_im(m6800_state *cpustate);
+INLINE void addd_ix(m6800_state *cpustate);
+INLINE void aim_di(m6800_state *cpustate);
+INLINE void aim_ix(m6800_state *cpustate);
+INLINE void anda_di(m6800_state *cpustate);
+INLINE void anda_ex(m6800_state *cpustate);
+INLINE void anda_im(m6800_state *cpustate);
+INLINE void anda_ix(m6800_state *cpustate);
+INLINE void andb_di(m6800_state *cpustate);
+INLINE void andb_ex(m6800_state *cpustate);
+INLINE void andb_im(m6800_state *cpustate);
+INLINE void andb_ix(m6800_state *cpustate);
+INLINE void asl_ex(m6800_state *cpustate);
+INLINE void asl_ix(m6800_state *cpustate);
+INLINE void asla(m6800_state *cpustate);
+INLINE void aslb(m6800_state *cpustate);
+INLINE void asld(m6800_state *cpustate);
+INLINE void asr_ex(m6800_state *cpustate);
+INLINE void asr_ix(m6800_state *cpustate);
+INLINE void asra(m6800_state *cpustate);
+INLINE void asrb(m6800_state *cpustate);
+INLINE void bcc(m6800_state *cpustate);
+INLINE void bcs(m6800_state *cpustate);
+INLINE void beq(m6800_state *cpustate);
+INLINE void bge(m6800_state *cpustate);
+INLINE void bgt(m6800_state *cpustate);
+INLINE void bhi(m6800_state *cpustate);
+INLINE void bita_di(m6800_state *cpustate);
+INLINE void bita_ex(m6800_state *cpustate);
+INLINE void bita_im(m6800_state *cpustate);
+INLINE void bita_ix(m6800_state *cpustate);
+INLINE void bitb_di(m6800_state *cpustate);
+INLINE void bitb_ex(m6800_state *cpustate);
+INLINE void bitb_im(m6800_state *cpustate);
+INLINE void bitb_ix(m6800_state *cpustate);
+INLINE void ble(m6800_state *cpustate);
+INLINE void bls(m6800_state *cpustate);
+INLINE void blt(m6800_state *cpustate);
+INLINE void bmi(m6800_state *cpustate);
+INLINE void bne(m6800_state *cpustate);
+INLINE void bpl(m6800_state *cpustate);
+INLINE void bra(m6800_state *cpustate);
+INLINE void brn(m6800_state *cpustate);
+INLINE void bsr(m6800_state *cpustate);
+INLINE void bvc(m6800_state *cpustate);
+INLINE void bvs(m6800_state *cpustate);
+INLINE void cba(m6800_state *cpustate);
+INLINE void clc(m6800_state *cpustate);
+INLINE void cli(m6800_state *cpustate);
+INLINE void clr_ex(m6800_state *cpustate);
+INLINE void clr_ix(m6800_state *cpustate);
+INLINE void clra(m6800_state *cpustate);
+INLINE void clrb(m6800_state *cpustate);
+INLINE void clv(m6800_state *cpustate);
+INLINE void cmpa_di(m6800_state *cpustate);
+INLINE void cmpa_ex(m6800_state *cpustate);
+INLINE void cmpa_im(m6800_state *cpustate);
+INLINE void cmpa_ix(m6800_state *cpustate);
+INLINE void cmpb_di(m6800_state *cpustate);
+INLINE void cmpb_ex(m6800_state *cpustate);
+INLINE void cmpb_im(m6800_state *cpustate);
+INLINE void cmpb_ix(m6800_state *cpustate);
+INLINE void cmpx_di(m6800_state *cpustate);
+INLINE void cmpx_ex(m6800_state *cpustate);
+INLINE void cmpx_im(m6800_state *cpustate);
+INLINE void cmpx_ix(m6800_state *cpustate);
+INLINE void com_ex(m6800_state *cpustate);
+INLINE void com_ix(m6800_state *cpustate);
+INLINE void coma(m6800_state *cpustate);
+INLINE void comb(m6800_state *cpustate);
+INLINE void daa(m6800_state *cpustate);
+INLINE void dec_ex(m6800_state *cpustate);
+INLINE void dec_ix(m6800_state *cpustate);
+INLINE void deca(m6800_state *cpustate);
+INLINE void decb(m6800_state *cpustate);
+INLINE void des(m6800_state *cpustate);
+INLINE void dex(m6800_state *cpustate);
+INLINE void eim_di(m6800_state *cpustate);
+INLINE void eim_ix(m6800_state *cpustate);
+INLINE void eora_di(m6800_state *cpustate);
+INLINE void eora_ex(m6800_state *cpustate);
+INLINE void eora_im(m6800_state *cpustate);
+INLINE void eora_ix(m6800_state *cpustate);
+INLINE void eorb_di(m6800_state *cpustate);
+INLINE void eorb_ex(m6800_state *cpustate);
+INLINE void eorb_im(m6800_state *cpustate);
+INLINE void eorb_ix(m6800_state *cpustate);
+INLINE void illegal(m6800_state *cpustate);
+INLINE void inc_ex(m6800_state *cpustate);
+INLINE void inc_ix(m6800_state *cpustate);
+INLINE void inca(m6800_state *cpustate);
+INLINE void incb(m6800_state *cpustate);
+INLINE void ins(m6800_state *cpustate);
+INLINE void inx(m6800_state *cpustate);
+INLINE void jmp_ex(m6800_state *cpustate);
+INLINE void jmp_ix(m6800_state *cpustate);
+INLINE void jsr_di(m6800_state *cpustate);
+INLINE void jsr_ex(m6800_state *cpustate);
+INLINE void jsr_ix(m6800_state *cpustate);
+INLINE void lda_di(m6800_state *cpustate);
+INLINE void lda_ex(m6800_state *cpustate);
+INLINE void lda_im(m6800_state *cpustate);
+INLINE void lda_ix(m6800_state *cpustate);
+INLINE void ldb_di(m6800_state *cpustate);
+INLINE void ldb_ex(m6800_state *cpustate);
+INLINE void ldb_im(m6800_state *cpustate);
+INLINE void ldb_ix(m6800_state *cpustate);
+INLINE void ldd_di(m6800_state *cpustate);
+INLINE void ldd_ex(m6800_state *cpustate);
+INLINE void ldd_im(m6800_state *cpustate);
+INLINE void ldd_ix(m6800_state *cpustate);
+INLINE void lds_di(m6800_state *cpustate);
+INLINE void lds_ex(m6800_state *cpustate);
+INLINE void lds_im(m6800_state *cpustate);
+INLINE void lds_ix(m6800_state *cpustate);
+INLINE void ldx_di(m6800_state *cpustate);
+INLINE void ldx_ex(m6800_state *cpustate);
+INLINE void ldx_im(m6800_state *cpustate);
+INLINE void ldx_ix(m6800_state *cpustate);
+INLINE void lsr_ex(m6800_state *cpustate);
+INLINE void lsr_ix(m6800_state *cpustate);
+INLINE void lsra(m6800_state *cpustate);
+INLINE void lsrb(m6800_state *cpustate);
+INLINE void lsrd(m6800_state *cpustate);
+INLINE void mul(m6800_state *cpustate);
+INLINE void neg_ex(m6800_state *cpustate);
+INLINE void neg_ix(m6800_state *cpustate);
+INLINE void nega(m6800_state *cpustate);
+INLINE void negb(m6800_state *cpustate);
+INLINE void nop(m6800_state *cpustate);
+INLINE void oim_di(m6800_state *cpustate);
+INLINE void oim_ix(m6800_state *cpustate);
+INLINE void ora_di(m6800_state *cpustate);
+INLINE void ora_ex(m6800_state *cpustate);
+INLINE void ora_im(m6800_state *cpustate);
+INLINE void ora_ix(m6800_state *cpustate);
+INLINE void orb_di(m6800_state *cpustate);
+INLINE void orb_ex(m6800_state *cpustate);
+INLINE void orb_im(m6800_state *cpustate);
+INLINE void orb_ix(m6800_state *cpustate);
+INLINE void psha(m6800_state *cpustate);
+INLINE void pshb(m6800_state *cpustate);
+INLINE void pshx(m6800_state *cpustate);
+INLINE void pula(m6800_state *cpustate);
+INLINE void pulb(m6800_state *cpustate);
+INLINE void pulx(m6800_state *cpustate);
+INLINE void rol_ex(m6800_state *cpustate);
+INLINE void rol_ix(m6800_state *cpustate);
+INLINE void rola(m6800_state *cpustate);
+INLINE void rolb(m6800_state *cpustate);
+INLINE void ror_ex(m6800_state *cpustate);
+INLINE void ror_ix(m6800_state *cpustate);
+INLINE void rora(m6800_state *cpustate);
+INLINE void rorb(m6800_state *cpustate);
+INLINE void rti(m6800_state *cpustate);
+INLINE void rts(m6800_state *cpustate);
+INLINE void sba(m6800_state *cpustate);
+INLINE void sbca_di(m6800_state *cpustate);
+INLINE void sbca_ex(m6800_state *cpustate);
+INLINE void sbca_im(m6800_state *cpustate);
+INLINE void sbca_ix(m6800_state *cpustate);
+INLINE void sbcb_di(m6800_state *cpustate);
+INLINE void sbcb_ex(m6800_state *cpustate);
+INLINE void sbcb_im(m6800_state *cpustate);
+INLINE void sbcb_ix(m6800_state *cpustate);
+INLINE void sec(m6800_state *cpustate);
+INLINE void sei(m6800_state *cpustate);
+INLINE void sev(m6800_state *cpustate);
+INLINE void slp(m6800_state *cpustate);
+INLINE void sta_di(m6800_state *cpustate);
+INLINE void sta_ex(m6800_state *cpustate);
+INLINE void sta_im(m6800_state *cpustate);
+INLINE void sta_ix(m6800_state *cpustate);
+INLINE void stb_di(m6800_state *cpustate);
+INLINE void stb_ex(m6800_state *cpustate);
+INLINE void stb_im(m6800_state *cpustate);
+INLINE void stb_ix(m6800_state *cpustate);
+INLINE void std_di(m6800_state *cpustate);
+INLINE void std_ex(m6800_state *cpustate);
+INLINE void std_im(m6800_state *cpustate);
+INLINE void std_ix(m6800_state *cpustate);
+INLINE void sts_di(m6800_state *cpustate);
+INLINE void sts_ex(m6800_state *cpustate);
+INLINE void sts_im(m6800_state *cpustate);
+INLINE void sts_ix(m6800_state *cpustate);
+INLINE void stx_di(m6800_state *cpustate);
+INLINE void stx_ex(m6800_state *cpustate);
+INLINE void stx_im(m6800_state *cpustate);
+INLINE void stx_ix(m6800_state *cpustate);
+INLINE void suba_di(m6800_state *cpustate);
+INLINE void suba_ex(m6800_state *cpustate);
+INLINE void suba_im(m6800_state *cpustate);
+INLINE void suba_ix(m6800_state *cpustate);
+INLINE void subb_di(m6800_state *cpustate);
+INLINE void subb_ex(m6800_state *cpustate);
+INLINE void subb_im(m6800_state *cpustate);
+INLINE void subb_ix(m6800_state *cpustate);
+INLINE void subd_di(m6800_state *cpustate);
+INLINE void subd_ex(m6800_state *cpustate);
+INLINE void subd_im(m6800_state *cpustate);
+INLINE void subd_ix(m6800_state *cpustate);
+INLINE void swi(m6800_state *cpustate);
+INLINE void tab(m6800_state *cpustate);
+INLINE void tap(m6800_state *cpustate);
+INLINE void tba(m6800_state *cpustate);
+INLINE void tim_di(m6800_state *cpustate);
+INLINE void tim_ix(m6800_state *cpustate);
+INLINE void tpa(m6800_state *cpustate);
+INLINE void tst_ex(m6800_state *cpustate);
+INLINE void tst_ix(m6800_state *cpustate);
+INLINE void tsta(m6800_state *cpustate);
+INLINE void tstb(m6800_state *cpustate);
+INLINE void tsx(m6800_state *cpustate);
+INLINE void txs(m6800_state *cpustate);
+INLINE void undoc1(m6800_state *cpustate);
+INLINE void undoc2(m6800_state *cpustate);
+INLINE void wai(m6800_state *cpustate);
+INLINE void xgdx(m6800_state *cpustate);
+
+INLINE void cpx_di(m6800_state *cpustate);
+INLINE void cpx_ex(m6800_state *cpustate);
+INLINE void cpx_im(m6800_state *cpustate);
+INLINE void cpx_ix(m6800_state *cpustate);
+INLINE void trap(m6800_state *cpustate);
+
+static void (*const m6800_insn[0x100])(m6800_state *cpustate) = {
+illegal,nop, illegal,illegal,illegal,illegal,tap, tpa,
+inx, dex, clv, sev, clc, sec, cli, sei,
+sba, cba, illegal,illegal,illegal,illegal,tab, tba,
+illegal,daa, illegal,aba, illegal,illegal,illegal,illegal,
+bra, brn, bhi, bls, bcc, bcs, bne, beq,
+bvc, bvs, bpl, bmi, bge, blt, bgt, ble,
+tsx, ins, pula, pulb, des, txs, psha, pshb,
+illegal,rts, illegal,rti, illegal,illegal,wai, swi,
+nega, illegal,illegal,coma, lsra, illegal,rora, asra,
+asla, rola, deca, illegal,inca, tsta, illegal,clra,
+negb, illegal,illegal,comb, lsrb, illegal,rorb, asrb,
+aslb, rolb, decb, illegal,incb, tstb, illegal,clrb,
+neg_ix, illegal,illegal,com_ix, lsr_ix, illegal,ror_ix, asr_ix,
+asl_ix, rol_ix, dec_ix, illegal,inc_ix, tst_ix, jmp_ix, clr_ix,
+neg_ex, illegal,illegal,com_ex, lsr_ex, illegal,ror_ex, asr_ex,
+asl_ex, rol_ex, dec_ex, illegal,inc_ex, tst_ex, jmp_ex, clr_ex,
+suba_im,cmpa_im,sbca_im,illegal,anda_im,bita_im,lda_im, sta_im,
+eora_im,adca_im,ora_im, adda_im,cmpx_im,bsr, lds_im, sts_im,
+suba_di,cmpa_di,sbca_di,illegal,anda_di,bita_di,lda_di, sta_di,
+eora_di,adca_di,ora_di, adda_di,cmpx_di,jsr_di, lds_di, sts_di,
+suba_ix,cmpa_ix,sbca_ix,illegal,anda_ix,bita_ix,lda_ix, sta_ix,
+eora_ix,adca_ix,ora_ix, adda_ix,cmpx_ix,jsr_ix, lds_ix, sts_ix,
+suba_ex,cmpa_ex,sbca_ex,illegal,anda_ex,bita_ex,lda_ex, sta_ex,
+eora_ex,adca_ex,ora_ex, adda_ex,cmpx_ex,jsr_ex, lds_ex, sts_ex,
+subb_im,cmpb_im,sbcb_im,illegal,andb_im,bitb_im,ldb_im, stb_im,
+eorb_im,adcb_im,orb_im, addb_im,illegal,illegal,ldx_im, stx_im,
+subb_di,cmpb_di,sbcb_di,illegal,andb_di,bitb_di,ldb_di, stb_di,
+eorb_di,adcb_di,orb_di, addb_di,illegal,illegal,ldx_di, stx_di,
+subb_ix,cmpb_ix,sbcb_ix,illegal,andb_ix,bitb_ix,ldb_ix, stb_ix,
+eorb_ix,adcb_ix,orb_ix, addb_ix,illegal,illegal,ldx_ix, stx_ix,
+subb_ex,cmpb_ex,sbcb_ex,illegal,andb_ex,bitb_ex,ldb_ex, stb_ex,
+eorb_ex,adcb_ex,orb_ex, addb_ex,illegal,illegal,ldx_ex, stx_ex
+};
+
+static void (*const m6803_insn[0x100])(m6800_state *cpustate) = {
+illegal,nop, illegal,illegal,lsrd, asld, tap, tpa,
+inx, dex, clv, sev, clc, sec, cli, sei,
+sba, cba, illegal,illegal,illegal,illegal,tab, tba,
+illegal,daa, illegal,aba, illegal,illegal,illegal,illegal,
+bra, brn, bhi, bls, bcc, bcs, bne, beq,
+bvc, bvs, bpl, bmi, bge, blt, bgt, ble,
+tsx, ins, pula, pulb, des, txs, psha, pshb,
+pulx, rts, abx, rti, pshx, mul, wai, swi,
+nega, illegal,illegal,coma, lsra, illegal,rora, asra,
+asla, rola, deca, illegal,inca, tsta, illegal,clra,
+negb, illegal,illegal,comb, lsrb, illegal,rorb, asrb,
+aslb, rolb, decb, illegal,incb, tstb, illegal,clrb,
+neg_ix, illegal,illegal,com_ix, lsr_ix, illegal,ror_ix, asr_ix,
+asl_ix, rol_ix, dec_ix, illegal,inc_ix, tst_ix, jmp_ix, clr_ix,
+neg_ex, illegal,illegal,com_ex, lsr_ex, illegal,ror_ex, asr_ex,
+asl_ex, rol_ex, dec_ex, illegal,inc_ex, tst_ex, jmp_ex, clr_ex,
+suba_im,cmpa_im,sbca_im,subd_im,anda_im,bita_im,lda_im, sta_im,
+eora_im,adca_im,ora_im, adda_im,cpx_im ,bsr, lds_im, sts_im,
+suba_di,cmpa_di,sbca_di,subd_di,anda_di,bita_di,lda_di, sta_di,
+eora_di,adca_di,ora_di, adda_di,cpx_di ,jsr_di, lds_di, sts_di,
+suba_ix,cmpa_ix,sbca_ix,subd_ix,anda_ix,bita_ix,lda_ix, sta_ix,
+eora_ix,adca_ix,ora_ix, adda_ix,cpx_ix ,jsr_ix, lds_ix, sts_ix,
+suba_ex,cmpa_ex,sbca_ex,subd_ex,anda_ex,bita_ex,lda_ex, sta_ex,
+eora_ex,adca_ex,ora_ex, adda_ex,cpx_ex ,jsr_ex, lds_ex, sts_ex,
+subb_im,cmpb_im,sbcb_im,addd_im,andb_im,bitb_im,ldb_im, stb_im,
+eorb_im,adcb_im,orb_im, addb_im,ldd_im, std_im, ldx_im, stx_im,
+subb_di,cmpb_di,sbcb_di,addd_di,andb_di,bitb_di,ldb_di, stb_di,
+eorb_di,adcb_di,orb_di, addb_di,ldd_di, std_di, ldx_di, stx_di,
+subb_ix,cmpb_ix,sbcb_ix,addd_ix,andb_ix,bitb_ix,ldb_ix, stb_ix,
+eorb_ix,adcb_ix,orb_ix, addb_ix,ldd_ix, std_ix, ldx_ix, stx_ix,
+subb_ex,cmpb_ex,sbcb_ex,addd_ex,andb_ex,bitb_ex,ldb_ex, stb_ex,
+eorb_ex,adcb_ex,orb_ex, addb_ex,ldd_ex, std_ex, ldx_ex, stx_ex
+};
+
+static void (*const hd63701_insn[0x100])(m6800_state *cpustate) = {
+trap, nop, trap, trap, lsrd, asld, tap, tpa,
+inx, dex, clv, sev, clc, sec, cli, sei,
+sba, cba, undoc1, undoc2, trap, trap, tab, tba,
+xgdx, daa, slp, aba, trap, trap, trap, trap,
+bra, brn, bhi, bls, bcc, bcs, bne, beq,
+bvc, bvs, bpl, bmi, bge, blt, bgt, ble,
+tsx, ins, pula, pulb, des, txs, psha, pshb,
+pulx, rts, abx, rti, pshx, mul, wai, swi,
+nega, trap, trap, coma, lsra, trap, rora, asra,
+asla, rola, deca, trap, inca, tsta, trap, clra,
+negb, trap, trap, comb, lsrb, trap, rorb, asrb,
+aslb, rolb, decb, trap, incb, tstb, trap, clrb,
+neg_ix, aim_ix, oim_ix, com_ix, lsr_ix, eim_ix, ror_ix, asr_ix,
+asl_ix, rol_ix, dec_ix, tim_ix, inc_ix, tst_ix, jmp_ix, clr_ix,
+neg_ex, aim_di, oim_di, com_ex, lsr_ex, eim_di, ror_ex, asr_ex,
+asl_ex, rol_ex, dec_ex, tim_di, inc_ex, tst_ex, jmp_ex, clr_ex,
+suba_im,cmpa_im,sbca_im,subd_im,anda_im,bita_im,lda_im, sta_im,
+eora_im,adca_im,ora_im, adda_im,cpx_im ,bsr, lds_im, sts_im,
+suba_di,cmpa_di,sbca_di,subd_di,anda_di,bita_di,lda_di, sta_di,
+eora_di,adca_di,ora_di, adda_di,cpx_di ,jsr_di, lds_di, sts_di,
+suba_ix,cmpa_ix,sbca_ix,subd_ix,anda_ix,bita_ix,lda_ix, sta_ix,
+eora_ix,adca_ix,ora_ix, adda_ix,cpx_ix ,jsr_ix, lds_ix, sts_ix,
+suba_ex,cmpa_ex,sbca_ex,subd_ex,anda_ex,bita_ex,lda_ex, sta_ex,
+eora_ex,adca_ex,ora_ex, adda_ex,cpx_ex ,jsr_ex, lds_ex, sts_ex,
+subb_im,cmpb_im,sbcb_im,addd_im,andb_im,bitb_im,ldb_im, stb_im,
+eorb_im,adcb_im,orb_im, addb_im,ldd_im, std_im, ldx_im, stx_im,
+subb_di,cmpb_di,sbcb_di,addd_di,andb_di,bitb_di,ldb_di, stb_di,
+eorb_di,adcb_di,orb_di, addb_di,ldd_di, std_di, ldx_di, stx_di,
+subb_ix,cmpb_ix,sbcb_ix,addd_ix,andb_ix,bitb_ix,ldb_ix, stb_ix,
+eorb_ix,adcb_ix,orb_ix, addb_ix,ldd_ix, std_ix, ldx_ix, stx_ix,
+subb_ex,cmpb_ex,sbcb_ex,addd_ex,andb_ex,bitb_ex,ldb_ex, stb_ex,
+eorb_ex,adcb_ex,orb_ex, addb_ex,ldd_ex, std_ex, ldx_ex, stx_ex
+};
+
+static void (*const nsc8105_insn[0x100])(m6800_state *cpustate) = {
+illegal,illegal,nop, illegal,illegal,tap, illegal,tpa,
+inx, clv, dex, sev, clc, cli, sec, sei,
+sba, illegal,cba, illegal,illegal,tab, illegal,tba,
+illegal,illegal,daa, aba, illegal,illegal,illegal,illegal,
+bra, bhi, brn, bls, bcc, bne, bcs, beq,
+bvc, bpl, bvs, bmi, bge, bgt, blt, ble,
+tsx, pula, ins, pulb, des, psha, txs, pshb,
+illegal,illegal,rts, rti, illegal,wai, illegal,swi,
+suba_im,sbca_im,cmpa_im,illegal,anda_im,lda_im, bita_im,sta_im,
+eora_im,ora_im, adca_im,adda_im,cmpx_im,lds_im, bsr, sts_im,
+suba_di,sbca_di,cmpa_di,illegal,anda_di,lda_di, bita_di,sta_di,
+eora_di,ora_di, adca_di,adda_di,cmpx_di,lds_di, jsr_di, sts_di,
+suba_ix,sbca_ix,cmpa_ix,illegal,anda_ix,lda_ix, bita_ix,sta_ix,
+eora_ix,ora_ix, adca_ix,adda_ix,cmpx_ix,lds_ix, jsr_ix, sts_ix,
+suba_ex,sbca_ex,cmpa_ex,illegal,anda_ex,lda_ex, bita_ex,sta_ex,
+eora_ex,ora_ex, adca_ex,adda_ex,cmpx_ex,lds_ex, jsr_ex, sts_ex,
+nega, illegal,illegal,coma, lsra, rora, illegal,asra,
+asla, deca, rola, illegal,inca, illegal,tsta, clra,
+negb, illegal,illegal,comb, lsrb, rorb, illegal,asrb,
+aslb, decb, rolb, illegal,incb, illegal,tstb, clrb,
+neg_ix, illegal,illegal,com_ix, lsr_ix, ror_ix, illegal,asr_ix,
+asl_ix, dec_ix, rol_ix, illegal,inc_ix, jmp_ix, tst_ix, clr_ix,
+neg_ex, illegal,illegal,com_ex, lsr_ex, ror_ex, illegal,asr_ex,
+asl_ex, dec_ex, rol_ex, illegal,inc_ex, jmp_ex, tst_ex, clr_ex,
+subb_im,sbcb_im,cmpb_im,illegal,andb_im,ldb_im, bitb_im,stb_im,
+eorb_im,orb_im, adcb_im,addb_im,illegal,ldx_im, illegal,stx_im,
+subb_di,sbcb_di,cmpb_di,illegal,andb_di,ldb_di, bitb_di,stb_di,
+eorb_di,orb_di, adcb_di,addb_di,illegal,ldx_di, illegal,stx_di,
+subb_ix,sbcb_ix,cmpb_ix,illegal,andb_ix,ldb_ix, bitb_ix,stb_ix,
+eorb_ix,orb_ix, adcb_ix,addb_ix,adcx_im,ldx_ix, illegal,stx_ix,
+subb_ex,sbcb_ex,cmpb_ex,illegal,andb_ex,ldb_ex, bitb_ex,stb_ex,
+eorb_ex,orb_ex, adcb_ex,addb_ex,addx_ex,ldx_ex, illegal,stx_ex
+};
diff --git a/trunk/src/emu/cpu/m6800/m6800.c b/trunk/src/emu/cpu/m6800/m6800.c
new file mode 100644
index 00000000000..9963e7399e5
--- /dev/null
+++ b/trunk/src/emu/cpu/m6800/m6800.c
@@ -0,0 +1,2130 @@
+/*** m6800: Portable 6800 class emulator *************************************
+
+ m68xx.c
+
+ References:
+
+ 6809 Simulator V09, By L.C. Benschop, Eidnhoven The Netherlands.
+
+ m6809: Portable 6809 emulator, DS (6809 code in MAME, derived from
+ the 6809 Simulator V09)
+
+ 6809 Microcomputer Programming & Interfacing with Experiments"
+ by Andrew C. Staugaard, Jr.; Howard W. Sams & Co., Inc.
+
+ System dependencies: UINT16 must be 16 bit unsigned int
+ UINT8 must be 8 bit unsigned int
+ UINT32 must be more than 16 bits
+ arrays up to 65536 bytes must be supported
+ machine must be twos complement
+
+History
+991031 ZV
+ Added NSC-8105 support
+
+990319 HJB
+ Fixed wrong LSB/MSB order for push/pull word.
+ Subtract .extra_cycles at the beginning/end of the exectuion loops.
+
+990316 HJB
+ Renamed to 6800, since that's the basic CPU.
+ Added different cycle count tables for M6800/2/8, M6801/3 and m68xx.
+
+990314 HJB
+ Also added the M6800 subtype.
+
+990311 HJB
+ Added _info functions. Now uses static m6808_Regs struct instead
+ of single statics. Changed the 16 bit registers to use the generic
+ PAIR union. Registers defined using macros. Split the core into
+ four execution loops for M6802, M6803, M6808 and HD63701.
+ TST, TSTA and TSTB opcodes reset carry flag.
+TODO:
+ Verify invalid opcodes for the different CPU types.
+ Add proper credits to _info functions.
+ Integrate m6808_Flags into the registers (multiple m6808 type CPUs?)
+
+990301 HJB
+ Modified the interrupt handling. No more pending interrupt checks.
+ WAI opcode saves state, when an interrupt is taken (IRQ or OCI),
+ the state is only saved if not already done by WAI.
+
+*****************************************************************************/
+
+/*
+
+ Chip RAM NVRAM ROM SCI r15-f ports
+ -----------------------------------------------------------------
+ MC6800 - - - no no 4
+ MC6802 128 32 - no no 4
+ MC6802NS 128 - - no no 4
+ MC6808 - - - no no 4
+
+ MC6801 128 64 2K yes no 4
+ MC68701 128 64 - yes no 4
+ MC6803 128 64 - yes no 4
+
+ MC6801U4 192 32 4K yes yes 4
+ MC6803U4 192 32 - yes yes 4
+
+ HD6801 128 64 2K yes no 4
+ HD6301V 128 - 4K yes no 4
+ HD63701V 192 - 4K yes no 4
+ HD6303R 128 - - yes no 4
+
+ HD6301X 192 - 4K yes yes 6
+ HD6301Y 256 - 16K yes yes 6
+ HD6303X 192 - - yes yes 6
+ HD6303Y 256 - - yes yes 6
+
+ NSC8105
+ MS2010-A
+
+*/
+
+#include "emu.h"
+#include "debugger.h"
+#include "m6800.h"
+
+#define VERBOSE 0
+
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+#if 0
+/* CPU subtypes, needed for extra insn after TAP/CLI/SEI */
+enum
+{
+ SUBTYPE_M6800,
+ SUBTYPE_M6801,
+ SUBTYPE_M6802,
+ SUBTYPE_M6803,
+ SUBTYPE_M6808,
+ SUBTYPE_HD6301,
+ SUBTYPE_HD63701,
+ SUBTYPE_NSC8105
+};
+#endif
+
+/* 6800 Registers */
+typedef struct _m6800_state m6800_state;
+struct _m6800_state
+{
+// int subtype; /* CPU subtype */
+ PAIR ppc; /* Previous program counter */
+ PAIR pc; /* Program counter */
+ PAIR s; /* Stack pointer */
+ PAIR x; /* Index register */
+ PAIR d; /* Accumulators */
+ UINT8 cc; /* Condition codes */
+ UINT8 wai_state; /* WAI opcode state ,(or sleep opcode state) */
+ UINT8 nmi_state; /* NMI line state */
+ UINT8 nmi_pending; /* NMI pending */
+ UINT8 irq_state[3]; /* IRQ line state [IRQ1,TIN,SC1] */
+ UINT8 ic_eddge; /* InputCapture eddge , b.0=fall,b.1=raise */
+ int sc1_state;
+
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+
+ /* Memory spaces */
+ address_space *program;
+ direct_read_data *direct;
+ address_space *data;
+ address_space *io;
+
+ void (* const * insn)(m6800_state *); /* instruction table */
+ const UINT8 *cycles; /* clock cycle of instruction table */
+ /* internal registers */
+ UINT8 port1_ddr;
+ UINT8 port2_ddr;
+ UINT8 port3_ddr;
+ UINT8 port4_ddr;
+ UINT8 port1_data;
+ UINT8 port2_data;
+ UINT8 port3_data;
+ UINT8 port4_data;
+ UINT8 p3csr; // Port 3 Control/Status Register
+ UINT8 tcsr; /* Timer Control and Status Register */
+ UINT8 pending_tcsr; /* pending IRQ flag for clear IRQflag process */
+ UINT8 irq2; /* IRQ2 flags */
+ UINT8 ram_ctrl;
+ PAIR counter; /* free running counter */
+ PAIR output_compare; /* output compare */
+ UINT16 input_capture; /* input capture */
+ int p3csr_is3_flag_read;
+ int port3_latched;
+
+ int clock;
+ UINT8 trcsr, rmcr, rdr, tdr, rsr, tsr;
+ int rxbits, txbits, txstate, trcsr_read_tdre, trcsr_read_orfe, trcsr_read_rdrf, tx;
+ int port2_written;
+
+ int icount;
+ int latch09;
+
+ PAIR timer_over;
+ emu_timer *sci_timer;
+ PAIR ea; /* effective address */
+
+ devcb_resolved_write_line out_sc2_func;
+};
+
+INLINE m6800_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == M6800 ||
+ device->type() == M6801 ||
+ device->type() == M6802 ||
+ device->type() == M6803 ||
+ device->type() == M6808 ||
+ device->type() == HD6301 ||
+ device->type() == HD63701 ||
+ device->type() == NSC8105);
+ return (m6800_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+#if 0
+static void hd63701_trap_pc(m6800_state *cpustate);
+#endif
+
+#define pPPC cpustate->ppc
+#define pPC cpustate->pc
+#define pS cpustate->s
+#define pX cpustate->x
+#define pD cpustate->d
+
+#define PC cpustate->pc.w.l
+#define PCD cpustate->pc.d
+#define S cpustate->s.w.l
+#define SD cpustate->s.d
+#define X cpustate->x.w.l
+#define D cpustate->d.w.l
+#define A cpustate->d.b.h
+#define B cpustate->d.b.l
+#define CC cpustate->cc
+
+#define CT cpustate->counter.w.l
+#define CTH cpustate->counter.w.h
+#define CTD cpustate->counter.d
+#define OC cpustate->output_compare.w.l
+#define OCH cpustate->output_compare.w.h
+#define OCD cpustate->output_compare.d
+#define TOH cpustate->timer_over.w.l
+#define TOD cpustate->timer_over.d
+
+#define EAD cpustate->ea.d
+#define EA cpustate->ea.w.l
+
+/* point of next timer event */
+static UINT32 timer_next;
+
+/* memory interface */
+
+/****************************************************************************/
+/* Read a byte from given memory location */
+/****************************************************************************/
+#define RM(Addr) ((unsigned)cpustate->program->read_byte(Addr))
+
+/****************************************************************************/
+/* Write a byte to given memory location */
+/****************************************************************************/
+#define WM(Addr,Value) (cpustate->program->write_byte(Addr,Value))
+
+/****************************************************************************/
+/* M6800_RDOP() is identical to M6800_RDMEM() except it is used for reading */
+/* opcodes. In case of system with memory mapped I/O, this function can be */
+/* used to greatly speed up emulation */
+/****************************************************************************/
+#define M_RDOP(Addr) ((unsigned)cpustate->direct->read_decrypted_byte(Addr))
+
+/****************************************************************************/
+/* M6800_RDOP_ARG() is identical to M6800_RDOP() but it's used for reading */
+/* opcode arguments. This difference can be used to support systems that */
+/* use different encoding mechanisms for opcodes and opcode arguments */
+/****************************************************************************/
+#define M_RDOP_ARG(Addr) ((unsigned)cpustate->direct->read_raw_byte(Addr))
+
+/* macros to access memory */
+#define IMMBYTE(b) b = M_RDOP_ARG(PCD); PC++
+#define IMMWORD(w) w.d = (M_RDOP_ARG(PCD)<<8) | M_RDOP_ARG((PCD+1)&0xffff); PC+=2
+
+#define PUSHBYTE(b) WM(SD,b); --S
+#define PUSHWORD(w) WM(SD,w.b.l); --S; WM(SD,w.b.h); --S
+#define PULLBYTE(b) S++; b = RM(SD)
+#define PULLWORD(w) S++; w.d = RM(SD)<<8; S++; w.d |= RM(SD)
+
+#define MODIFIED_tcsr { \
+ cpustate->irq2 = (cpustate->tcsr&(cpustate->tcsr<<3))&(TCSR_ICF|TCSR_OCF|TCSR_TOF); \
+}
+
+#define SET_TIMER_EVENT { \
+ timer_next = (OCD - CTD < TOD - CTD) ? OCD : TOD; \
+}
+
+/* cleanup high-word of counters */
+#define CLEANUP_COUNTERS() { \
+ OCH -= CTH; \
+ TOH -= CTH; \
+ CTH = 0; \
+ SET_TIMER_EVENT; \
+}
+
+/* when change freerunningcounter or outputcapture */
+#define MODIFIED_counters { \
+ OCH = (OC >= CT) ? CTH : CTH+1; \
+ SET_TIMER_EVENT; \
+}
+
+// I/O registers
+
+enum
+{
+ IO_P1DDR = 0,
+ IO_P2DDR,
+ IO_P1DATA,
+ IO_P2DATA,
+ IO_P3DDR,
+ IO_P4DDR,
+ IO_P3DATA,
+ IO_P4DATA,
+ IO_TCSR,
+ IO_CH,
+ IO_CL,
+ IO_OCRH,
+ IO_OCRL,
+ IO_ICRH,
+ IO_ICRL,
+ IO_P3CSR,
+ IO_RMCR,
+ IO_TRCSR,
+ IO_RDR,
+ IO_TDR,
+ IO_RCR,
+ IO_CAAH,
+ IO_CAAL,
+ IO_TCR1,
+ IO_TCR2,
+ IO_TSR,
+ IO_OCR2H,
+ IO_OCR2L,
+ IO_OCR3H,
+ IO_OCR3L,
+ IO_ICR2H,
+ IO_ICR2L
+};
+
+// serial I/O
+
+#define M6800_RMCR_SS_MASK 0x03 // Speed Select
+#define M6800_RMCR_SS_4096 0x03 // E / 4096
+#define M6800_RMCR_SS_1024 0x02 // E / 1024
+#define M6800_RMCR_SS_128 0x01 // E / 128
+#define M6800_RMCR_SS_16 0x00 // E / 16
+#define M6800_RMCR_CC_MASK 0x0c // Clock Control/Format Select
+
+#define M6800_TRCSR_RDRF 0x80 // Receive Data Register Full
+#define M6800_TRCSR_ORFE 0x40 // Over Run Framing Error
+#define M6800_TRCSR_TDRE 0x20 // Transmit Data Register Empty
+#define M6800_TRCSR_RIE 0x10 // Receive Interrupt Enable
+#define M6800_TRCSR_RE 0x08 // Receive Enable
+#define M6800_TRCSR_TIE 0x04 // Transmit Interrupt Enable
+#define M6800_TRCSR_TE 0x02 // Transmit Enable
+#define M6800_TRCSR_WU 0x01 // Wake Up
+
+#define M6800_PORT2_IO4 0x10
+#define M6800_PORT2_IO3 0x08
+
+#define M6801_P3CSR_LE 0x08
+#define M6801_P3CSR_OSS 0x10
+#define M6801_P3CSR_IS3_ENABLE 0x40
+#define M6801_P3CSR_IS3_FLAG 0x80
+
+static const int M6800_RMCR_SS[] = { 16, 128, 1024, 4096 };
+
+#define M6800_SERIAL_START 0
+#define M6800_SERIAL_STOP 9
+
+enum
+{
+ M6800_TX_STATE_INIT = 0,
+ M6800_TX_STATE_READY
+};
+
+/* take interrupt */
+#define TAKE_ICI enter_interrupt(cpustate, "M6800 '%s' take ICI\n",0xfff6)
+#define TAKE_OCI enter_interrupt(cpustate, "M6800 '%s' take OCI\n",0xfff4)
+#define TAKE_TOI enter_interrupt(cpustate, "M6800 '%s' take TOI\n",0xfff2)
+#define TAKE_SCI enter_interrupt(cpustate, "M6800 '%s' take SCI\n",0xfff0)
+#define TAKE_TRAP enter_interrupt(cpustate, "M6800 '%s' take TRAP\n",0xffee)
+
+/* operate one instruction for */
+#define ONE_MORE_INSN() { \
+ UINT8 ireg; \
+ pPPC = pPC; \
+ debugger_instruction_hook(cpustate->device, PCD); \
+ ireg=M_RDOP(PCD); \
+ PC++; \
+ (*cpustate->insn[ireg])(cpustate); \
+ increment_counter(cpustate, cpustate->cycles[ireg]); \
+}
+
+/* CC masks HI NZVC
+ 7654 3210 */
+#define CLR_HNZVC CC&=0xd0
+#define CLR_NZV CC&=0xf1
+#define CLR_HNZC CC&=0xd2
+#define CLR_NZVC CC&=0xf0
+#define CLR_Z CC&=0xfb
+#define CLR_NZC CC&=0xf2
+#define CLR_ZC CC&=0xfa
+#define CLR_C CC&=0xfe
+
+/* macros for CC -- CC bits affected should be reset before calling */
+#define SET_Z(a) if(!(a))SEZ
+#define SET_Z8(a) SET_Z((UINT8)(a))
+#define SET_Z16(a) SET_Z((UINT16)(a))
+#define SET_N8(a) CC|=(((a)&0x80)>>4)
+#define SET_N16(a) CC|=(((a)&0x8000)>>12)
+#define SET_H(a,b,r) CC|=((((a)^(b)^(r))&0x10)<<1)
+#define SET_C8(a) CC|=(((a)&0x100)>>8)
+#define SET_C16(a) CC|=(((a)&0x10000)>>16)
+#define SET_V8(a,b,r) CC|=((((a)^(b)^(r)^((r)>>1))&0x80)>>6)
+#define SET_V16(a,b,r) CC|=((((a)^(b)^(r)^((r)>>1))&0x8000)>>14)
+
+static const UINT8 flags8i[256]= /* increment */
+{
+0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x0a,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08
+};
+static const UINT8 flags8d[256]= /* decrement */
+{
+0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,
+0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08
+};
+#define SET_FLAGS8I(a) {CC|=flags8i[(a)&0xff];}
+#define SET_FLAGS8D(a) {CC|=flags8d[(a)&0xff];}
+
+/* combos */
+#define SET_NZ8(a) {SET_N8(a);SET_Z8(a);}
+#define SET_NZ16(a) {SET_N16(a);SET_Z16(a);}
+#define SET_FLAGS8(a,b,r) {SET_N8(r);SET_Z8(r);SET_V8(a,b,r);SET_C8(r);}
+#define SET_FLAGS16(a,b,r) {SET_N16(r);SET_Z16(r);SET_V16(a,b,r);SET_C16(r);}
+
+/* for treating an UINT8 as a signed INT16 */
+#define SIGNED(b) ((INT16)(b&0x80?b|0xff00:b))
+
+/* Macros for addressing modes */
+#define DIRECT IMMBYTE(EAD)
+#define IMM8 EA=PC++
+#define IMM16 {EA=PC;PC+=2;}
+#define EXTENDED IMMWORD(cpustate->ea)
+#define INDEXED {EA=X+(UINT8)M_RDOP_ARG(PCD);PC++;}
+
+/* macros to set status flags */
+#if defined(SEC)
+#undef SEC
+#endif
+#define SEC CC|=0x01
+#define CLC CC&=0xfe
+#define SEZ CC|=0x04
+#define CLZ CC&=0xfb
+#define SEN CC|=0x08
+#define CLN CC&=0xf7
+#define SEV CC|=0x02
+#define CLV CC&=0xfd
+#define SEH CC|=0x20
+#define CLH CC&=0xdf
+#define SEI CC|=0x10
+#define CLI CC&=~0x10
+
+/* mnemonicos for the Timer Control and Status Register bits */
+#define TCSR_OLVL 0x01
+#define TCSR_IEDG 0x02
+#define TCSR_ETOI 0x04
+#define TCSR_EOCI 0x08
+#define TCSR_EICI 0x10
+#define TCSR_TOF 0x20
+#define TCSR_OCF 0x40
+#define TCSR_ICF 0x80
+
+/* macros for convenience */
+#define DIRBYTE(b) {DIRECT;b=RM(EAD);}
+#define DIRWORD(w) {DIRECT;w.d=RM16(cpustate, EAD);}
+#define EXTBYTE(b) {EXTENDED;b=RM(EAD);}
+#define EXTWORD(w) {EXTENDED;w.d=RM16(cpustate, EAD);}
+
+#define IDXBYTE(b) {INDEXED;b=RM(EAD);}
+#define IDXWORD(w) {INDEXED;w.d=RM16(cpustate, EAD);}
+
+/* Macros for branch instructions */
+#define BRANCH(f) {IMMBYTE(t);if(f){PC+=SIGNED(t);}}
+#define NXORV ((CC&0x08)^((CC&0x02)<<2))
+
+#define M6800_WAI 8 /* set when WAI is waiting for an interrupt */
+#define M6800_SLP 0x10 /* HD63701 only */
+
+/* Note: don't use 0 cycles here for invalid opcodes so that we don't */
+/* hang in an infinite loop if we hit one */
+#define XX 5 // invalid opcode unknown cc
+static const UINT8 cycles_6800[] =
+{
+ /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
+ /*0*/ XX, 2,XX,XX,XX,XX, 2, 2, 4, 4, 2, 2, 2, 2, 2, 2,
+ /*1*/ 2, 2,XX,XX,XX,XX, 2, 2,XX, 2,XX, 2,XX,XX,XX,XX,
+ /*2*/ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ /*3*/ 4, 4, 4, 4, 4, 4, 4, 4,XX, 5,XX,10,XX,XX, 9,12,
+ /*4*/ 2,XX,XX, 2, 2,XX, 2, 2, 2, 2, 2,XX, 2, 2,XX, 2,
+ /*5*/ 2,XX,XX, 2, 2,XX, 2, 2, 2, 2, 2,XX, 2, 2,XX, 2,
+ /*6*/ 7,XX,XX, 7, 7,XX, 7, 7, 7, 7, 7,XX, 7, 7, 4, 7,
+ /*7*/ 6,XX,XX, 6, 6,XX, 6, 6, 6, 6, 6,XX, 6, 6, 3, 6,
+ /*8*/ 2, 2, 2,XX, 2, 2, 2, 3, 2, 2, 2, 2, 3, 8, 3, 4,
+ /*9*/ 3, 3, 3,XX, 3, 3, 3, 4, 3, 3, 3, 3, 4, 6, 4, 5,
+ /*A*/ 5, 5, 5,XX, 5, 5, 5, 6, 5, 5, 5, 5, 6, 8, 6, 7,
+ /*B*/ 4, 4, 4,XX, 4, 4, 4, 5, 4, 4, 4, 4, 5, 9, 5, 6,
+ /*C*/ 2, 2, 2,XX, 2, 2, 2, 3, 2, 2, 2, 2,XX,XX, 3, 4,
+ /*D*/ 3, 3, 3,XX, 3, 3, 3, 4, 3, 3, 3, 3,XX,XX, 4, 5,
+ /*E*/ 5, 5, 5,XX, 5, 5, 5, 6, 5, 5, 5, 5,XX,XX, 6, 7,
+ /*F*/ 4, 4, 4,XX, 4, 4, 4, 5, 4, 4, 4, 4,XX,XX, 5, 6
+};
+
+static const UINT8 cycles_6803[] =
+{
+ /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
+ /*0*/ XX, 2,XX,XX, 3, 3, 2, 2, 3, 3, 2, 2, 2, 2, 2, 2,
+ /*1*/ 2, 2,XX,XX,XX,XX, 2, 2,XX, 2,XX, 2,XX,XX,XX,XX,
+ /*2*/ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ /*3*/ 3, 3, 4, 4, 3, 3, 3, 3, 5, 5, 3,10, 4,10, 9,12,
+ /*4*/ 2,XX,XX, 2, 2,XX, 2, 2, 2, 2, 2,XX, 2, 2,XX, 2,
+ /*5*/ 2,XX,XX, 2, 2,XX, 2, 2, 2, 2, 2,XX, 2, 2,XX, 2,
+ /*6*/ 6,XX,XX, 6, 6,XX, 6, 6, 6, 6, 6,XX, 6, 6, 3, 6,
+ /*7*/ 6,XX,XX, 6, 6,XX, 6, 6, 6, 6, 6,XX, 6, 6, 3, 6,
+ /*8*/ 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 2, 4, 6, 3, 3,
+ /*9*/ 3, 3, 3, 5, 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 4, 4,
+ /*A*/ 4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 5, 5,
+ /*B*/ 4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 5, 5,
+ /*C*/ 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 2, 3,XX, 3, 3,
+ /*D*/ 3, 3, 3, 5, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4,
+ /*E*/ 4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5,
+ /*F*/ 4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5
+};
+
+static const UINT8 cycles_63701[] =
+{
+ /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
+ /*0*/ XX, 1,XX,XX, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ /*1*/ 1, 1,XX,XX,XX,XX, 1, 1, 2, 2, 4, 1,XX,XX,XX,XX,
+ /*2*/ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ /*3*/ 1, 1, 3, 3, 1, 1, 4, 4, 4, 5, 1,10, 5, 7, 9,12,
+ /*4*/ 1,XX,XX, 1, 1,XX, 1, 1, 1, 1, 1,XX, 1, 1,XX, 1,
+ /*5*/ 1,XX,XX, 1, 1,XX, 1, 1, 1, 1, 1,XX, 1, 1,XX, 1,
+ /*6*/ 6, 7, 7, 6, 6, 7, 6, 6, 6, 6, 6, 5, 6, 4, 3, 5,
+ /*7*/ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 4, 6, 4, 3, 5,
+ /*8*/ 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 3, 5, 3, 3,
+ /*9*/ 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 4, 5, 4, 4,
+ /*A*/ 4, 4, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5,
+ /*B*/ 4, 4, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 5, 6, 5, 5,
+ /*C*/ 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 3,XX, 3, 3,
+ /*D*/ 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4,
+ /*E*/ 4, 4, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5,
+ /*F*/ 4, 4, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5
+};
+
+static const UINT8 cycles_nsc8105[] =
+{
+ /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
+ /*0*/ XX,XX, 2,XX,XX, 2,XX, 2, 4, 2, 4, 2, 2, 2, 2, 2,
+ /*1*/ 2,XX, 2,XX,XX, 2,XX, 2,XX,XX, 2, 2,XX,XX,XX,XX,
+ /*2*/ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ /*3*/ 4, 4, 4, 4, 4, 4, 4, 4,XX,XX, 5,10,XX, 9,XX,12,
+ /*4*/ 2, 2, 2,XX, 2, 2, 2, 3, 2, 2, 2, 2, 3, 3, 8, 4,
+ /*5*/ 3, 3, 3,XX, 3, 3, 3, 4, 3, 3, 3, 3, 4, 4, 6, 5,
+ /*6*/ 5, 5, 5,XX, 5, 5, 5, 6, 5, 5, 5, 5, 6, 6, 8, 7,
+ /*7*/ 4, 4, 4,XX, 4, 4, 4, 5, 4, 4, 4, 4, 5, 5, 9, 6,
+ /*8*/ 2,XX,XX, 2, 2, 2,XX, 2, 2, 2, 2,XX, 2,XX, 2, 2,
+ /*9*/ 2,XX,XX, 2, 2, 2,XX, 2, 2, 2, 2,XX, 2,XX, 2, 2,
+ /*A*/ 7,XX,XX, 7, 7, 7,XX, 7, 7, 7, 7,XX, 7, 4, 7, 7,
+ /*B*/ 6,XX,XX, 6, 6, 6,XX, 6, 6, 6, 6,XX, 6, 3, 6, 6,
+ /*C*/ 2, 2, 2,XX, 2, 2, 2, 3, 2, 2, 2, 2,XX, 3,XX, 4,
+ /*D*/ 3, 3, 3,XX, 3, 3, 3, 4, 3, 3, 3, 3,XX, 4,XX, 5,
+ /*E*/ 5, 5, 5,XX, 5, 5, 5, 6, 5, 5, 5, 5, 5, 6,XX, 7,
+ /*F*/ 4, 4, 4,XX, 4, 4, 4, 5, 4, 4, 4, 4, 4, 5,XX, 6
+};
+#undef XX // /invalid opcode unknown cc
+
+#define EAT_CYCLES \
+{ \
+ int cycles_to_eat; \
+ \
+ cycles_to_eat = timer_next - CTD; \
+ if( cycles_to_eat > cpustate->icount) cycles_to_eat = cpustate->icount; \
+ if (cycles_to_eat > 0) \
+ { \
+ increment_counter(cpustate, cycles_to_eat); \
+ } \
+}
+
+INLINE UINT32 RM16(m6800_state *cpustate, UINT32 Addr )
+{
+ UINT32 result = RM(Addr) << 8;
+ return result | RM((Addr+1)&0xffff);
+}
+
+INLINE void WM16(m6800_state *cpustate, UINT32 Addr, PAIR *p )
+{
+ WM( Addr, p->b.h );
+ WM( (Addr+1)&0xffff, p->b.l );
+}
+
+/* IRQ enter */
+static void enter_interrupt(m6800_state *cpustate, const char *message,UINT16 irq_vector)
+{
+ LOG((message, cpustate->device->tag()));
+ if( cpustate->wai_state & (M6800_WAI|M6800_SLP) )
+ {
+ if( cpustate->wai_state & M6800_WAI )
+ cpustate->icount -= 4;
+ cpustate->wai_state &= ~(M6800_WAI|M6800_SLP);
+ }
+ else
+ {
+ PUSHWORD(pPC);
+ PUSHWORD(pX);
+ PUSHBYTE(A);
+ PUSHBYTE(B);
+ PUSHBYTE(CC);
+ cpustate->icount -= 12;
+ }
+ SEI;
+ PCD = RM16(cpustate, irq_vector );
+}
+
+
+
+static void m6800_check_irq2(m6800_state *cpustate)
+{
+ if ((cpustate->tcsr & (TCSR_EICI|TCSR_ICF)) == (TCSR_EICI|TCSR_ICF))
+ {
+ TAKE_ICI;
+ if( cpustate->irq_callback )
+ (void)(*cpustate->irq_callback)(cpustate->device, M6801_TIN_LINE);
+ }
+ else if ((cpustate->tcsr & (TCSR_EOCI|TCSR_OCF)) == (TCSR_EOCI|TCSR_OCF))
+ {
+ TAKE_OCI;
+ }
+ else if ((cpustate->tcsr & (TCSR_ETOI|TCSR_TOF)) == (TCSR_ETOI|TCSR_TOF))
+ {
+ TAKE_TOI;
+ }
+ else if (((cpustate->trcsr & (M6800_TRCSR_RIE|M6800_TRCSR_RDRF)) == (M6800_TRCSR_RIE|M6800_TRCSR_RDRF)) ||
+ ((cpustate->trcsr & (M6800_TRCSR_RIE|M6800_TRCSR_ORFE)) == (M6800_TRCSR_RIE|M6800_TRCSR_ORFE)) ||
+ ((cpustate->trcsr & (M6800_TRCSR_TIE|M6800_TRCSR_TDRE)) == (M6800_TRCSR_TIE|M6800_TRCSR_TDRE)))
+ {
+ //logerror("M6800 '%s' SCI interrupt\n", cpustate->device->tag());
+ TAKE_SCI;
+ }
+}
+
+
+/* check the IRQ lines for pending interrupts */
+INLINE void CHECK_IRQ_LINES(m6800_state *cpustate)
+{
+ // TODO: IS3 interrupt
+
+ if (cpustate->nmi_pending)
+ {
+ if(cpustate->wai_state & M6800_SLP)
+ cpustate->wai_state &= ~M6800_SLP;
+
+ cpustate->nmi_pending = FALSE;
+ enter_interrupt(cpustate, "M6800 '%s' take NMI\n",0xfffc);
+ }
+ else
+ {
+ if( cpustate->irq_state[M6800_IRQ_LINE] != CLEAR_LINE )
+ { /* standard IRQ */
+ if(cpustate->wai_state & M6800_SLP)
+ cpustate->wai_state &= ~M6800_SLP;
+
+ if( !(CC & 0x10) )
+ {
+ enter_interrupt(cpustate, "M6800 '%s' take IRQ1\n",0xfff8);
+ if( cpustate->irq_callback )
+ (void)(*cpustate->irq_callback)(cpustate->device, M6800_IRQ_LINE);
+ }
+ }
+ else
+ if( !(CC & 0x10) )
+ m6800_check_irq2(cpustate);
+ }
+}
+
+/* check OCI or TOI */
+static void check_timer_event(m6800_state *cpustate)
+{
+ /* OCI */
+ if( CTD >= OCD)
+ {
+ OCH++; // next IRQ point
+ cpustate->tcsr |= TCSR_OCF;
+ cpustate->pending_tcsr |= TCSR_OCF;
+ MODIFIED_tcsr;
+ if((cpustate->tcsr & TCSR_EOCI) && cpustate->wai_state & M6800_SLP)
+ cpustate->wai_state &= ~M6800_SLP;
+ if ( !(CC & 0x10) && (cpustate->tcsr & TCSR_EOCI))
+ TAKE_OCI;
+ }
+ /* TOI */
+ if( CTD >= TOD)
+ {
+ TOH++; // next IRQ point
+#if 0
+ CLEANUP_COUNTERS();
+#endif
+ cpustate->tcsr |= TCSR_TOF;
+ cpustate->pending_tcsr |= TCSR_TOF;
+ MODIFIED_tcsr;
+ if((cpustate->tcsr & TCSR_ETOI) && cpustate->wai_state & M6800_SLP)
+ cpustate->wai_state &= ~M6800_SLP;
+ if ( !(CC & 0x10) && (cpustate->tcsr & TCSR_ETOI))
+ TAKE_TOI;
+ }
+ /* set next event */
+ SET_TIMER_EVENT;
+}
+
+INLINE void increment_counter(m6800_state *cpustate, int amount)
+{
+ cpustate->icount -= amount;
+ CTD += amount;
+ if( CTD >= timer_next)
+ check_timer_event(cpustate);
+}
+
+INLINE void set_rmcr(m6800_state *cpustate, UINT8 data)
+{
+ if (cpustate->rmcr == data) return;
+
+ cpustate->rmcr = data;
+
+ switch ((cpustate->rmcr & M6800_RMCR_CC_MASK) >> 2)
+ {
+ case 0:
+ case 3: // not implemented
+ cpustate->sci_timer->enable(false);
+ break;
+
+ case 1:
+ case 2:
+ {
+ int divisor = M6800_RMCR_SS[cpustate->rmcr & M6800_RMCR_SS_MASK];
+
+ cpustate->sci_timer->adjust(attotime::from_hz(cpustate->clock / divisor), 0, attotime::from_hz(cpustate->clock / divisor));
+ }
+ break;
+ }
+}
+
+INLINE void write_port2(m6800_state *cpustate)
+{
+ if (!cpustate->port2_written) return;
+
+ UINT8 data = cpustate->port2_data;
+ UINT8 ddr = cpustate->port2_ddr & 0x1f;
+
+ if ((ddr != 0x1f) && ddr)
+ {
+ data = (cpustate->port2_data & ddr) | (ddr ^ 0xff);
+ }
+
+ if (cpustate->trcsr & M6800_TRCSR_TE)
+ {
+ data = (data & 0xef) | (cpustate->tx << 4);
+ }
+
+ data &= 0x1f;
+
+ cpustate->io->write_byte(M6801_PORT2, data);
+}
+
+/* include the opcode prototypes and function pointer tables */
+#include "6800tbl.c"
+
+/* include the opcode functions */
+#include "6800ops.c"
+
+static int m6800_rx(m6800_state *cpustate)
+{
+ return (cpustate->io->read_byte(M6801_PORT2) & M6800_PORT2_IO3) >> 3;
+}
+
+static void serial_transmit(m6800_state *cpustate)
+{
+ //logerror("M6800 '%s' Tx Tick\n", cpustate->device->tag());
+
+ if (cpustate->trcsr & M6800_TRCSR_TE)
+ {
+ // force Port 2 bit 4 as output
+ cpustate->port2_ddr |= M6800_PORT2_IO4;
+
+ switch (cpustate->txstate)
+ {
+ case M6800_TX_STATE_INIT:
+ cpustate->tx = 1;
+ cpustate->txbits++;
+
+ if (cpustate->txbits == 10)
+ {
+ cpustate->txstate = M6800_TX_STATE_READY;
+ cpustate->txbits = M6800_SERIAL_START;
+ }
+ break;
+
+ case M6800_TX_STATE_READY:
+ switch (cpustate->txbits)
+ {
+ case M6800_SERIAL_START:
+ if (cpustate->trcsr & M6800_TRCSR_TDRE)
+ {
+ // transmit buffer is empty, send consecutive '1's
+ cpustate->tx = 1;
+ }
+ else
+ {
+ // transmit buffer is full, send data
+
+ // load TDR to shift register
+ cpustate->tsr = cpustate->tdr;
+
+ // transmit buffer is empty, set TDRE flag
+ cpustate->trcsr |= M6800_TRCSR_TDRE;
+
+ // send start bit '0'
+ cpustate->tx = 0;
+
+ cpustate->txbits++;
+
+ //logerror("M6800 '%s' Transmit START Data %02x\n", cpustate->device->tag(), cpustate->tsr);
+ }
+ break;
+
+ case M6800_SERIAL_STOP:
+ // send stop bit '1'
+ cpustate->tx = 1;
+
+ CHECK_IRQ_LINES(cpustate);
+
+ cpustate->txbits = M6800_SERIAL_START;
+
+ //logerror("M6800 '%s' Transmit STOP\n", cpustate->device->tag());
+ break;
+
+ default:
+ // send data bit '0' or '1'
+ cpustate->tx = cpustate->tsr & 0x01;
+
+ // shift transmit register
+ cpustate->tsr >>= 1;
+
+ //logerror("M6800 '%s' Transmit Bit %u: %u\n", cpustate->device->tag(), cpustate->txbits, cpustate->tx);
+
+ cpustate->txbits++;
+ break;
+ }
+ break;
+ }
+
+ cpustate->port2_written = 1;
+ write_port2(cpustate);
+ }
+}
+
+static void serial_receive(m6800_state *cpustate)
+{
+ //logerror("M6800 '%s' Rx Tick TRCSR %02x bits %u check %02x\n", cpustate->device->tag(), cpustate->trcsr, cpustate->rxbits, cpustate->trcsr & M6800_TRCSR_RE);
+
+ if (cpustate->trcsr & M6800_TRCSR_RE)
+ {
+ if (cpustate->trcsr & M6800_TRCSR_WU)
+ {
+ // wait for 10 bits of '1'
+ if (m6800_rx(cpustate) == 1)
+ {
+ cpustate->rxbits++;
+
+ //logerror("M6800 '%s' Received WAKE UP bit %u\n", cpustate->device->tag(), cpustate->rxbits);
+
+ if (cpustate->rxbits == 10)
+ {
+ //logerror("M6800 '%s' Receiver Wake Up\n", cpustate->device->tag());
+
+ cpustate->trcsr &= ~M6800_TRCSR_WU;
+ cpustate->rxbits = M6800_SERIAL_START;
+ }
+ }
+ else
+ {
+ //logerror("M6800 '%s' Receiver Wake Up interrupted\n", cpustate->device->tag());
+
+ cpustate->rxbits = M6800_SERIAL_START;
+ }
+ }
+ else
+ {
+ // receive data
+ switch (cpustate->rxbits)
+ {
+ case M6800_SERIAL_START:
+ if (m6800_rx(cpustate) == 0)
+ {
+ // start bit found
+ cpustate->rxbits++;
+
+ //logerror("M6800 '%s' Received START bit\n", cpustate->device->tag());
+ }
+ break;
+
+ case M6800_SERIAL_STOP:
+ if (m6800_rx(cpustate) == 1)
+ {
+ //logerror("M6800 '%s' Received STOP bit\n", cpustate->device->tag());
+
+ if (cpustate->trcsr & M6800_TRCSR_RDRF)
+ {
+ // overrun error
+ cpustate->trcsr |= M6800_TRCSR_ORFE;
+
+ //logerror("M6800 '%s' Receive Overrun Error\n", cpustate->device->tag());
+
+ CHECK_IRQ_LINES(cpustate);
+ }
+ else
+ {
+ if (!(cpustate->trcsr & M6800_TRCSR_ORFE))
+ {
+ // transfer data into receive register
+ cpustate->rdr = cpustate->rsr;
+
+ //logerror("M6800 '%s' Receive Data Register: %02x\n", cpustate->device->tag(), cpustate->rdr);
+
+ // set RDRF flag
+ cpustate->trcsr |= M6800_TRCSR_RDRF;
+
+ CHECK_IRQ_LINES(cpustate);
+ }
+ }
+ }
+ else
+ {
+ // framing error
+ if (!(cpustate->trcsr & M6800_TRCSR_ORFE))
+ {
+ // transfer unframed data into receive register
+ cpustate->rdr = cpustate->rsr;
+ }
+
+ cpustate->trcsr |= M6800_TRCSR_ORFE;
+ cpustate->trcsr &= ~M6800_TRCSR_RDRF;
+
+ //logerror("M6800 '%s' Receive Framing Error\n", cpustate->device->tag());
+
+ CHECK_IRQ_LINES(cpustate);
+ }
+
+ cpustate->rxbits = M6800_SERIAL_START;
+ break;
+
+ default:
+ // shift receive register
+ cpustate->rsr >>= 1;
+
+ // receive bit into register
+ cpustate->rsr |= (m6800_rx(cpustate) << 7);
+
+ //logerror("M6800 '%s' Received DATA bit %u: %u\n", cpustate->device->tag(), cpustate->rxbits, BIT(cpustate->rsr, 7));
+
+ cpustate->rxbits++;
+ break;
+ }
+ }
+ }
+}
+
+static TIMER_CALLBACK( sci_tick )
+{
+ m6800_state *cpustate = (m6800_state *)ptr;
+
+ serial_transmit(cpustate);
+ serial_receive(cpustate);
+}
+
+/****************************************************************************
+ * Reset registers to their initial values
+ ****************************************************************************/
+static void state_register(m6800_state *cpustate, const char *type)
+{
+ cpustate->device->save_item(NAME(cpustate->ppc.w.l));
+ cpustate->device->save_item(NAME(cpustate->pc.w.l));
+ cpustate->device->save_item(NAME(cpustate->s.w.l));
+ cpustate->device->save_item(NAME(cpustate->x.w.l));
+ cpustate->device->save_item(NAME(cpustate->d.w.l));
+ cpustate->device->save_item(NAME(cpustate->cc));
+ cpustate->device->save_item(NAME(cpustate->wai_state));
+ cpustate->device->save_item(NAME(cpustate->nmi_state));
+ cpustate->device->save_item(NAME(cpustate->nmi_pending));
+ cpustate->device->save_item(NAME(cpustate->irq_state));
+ cpustate->device->save_item(NAME(cpustate->ic_eddge));
+
+ cpustate->device->save_item(NAME(cpustate->port1_ddr));
+ cpustate->device->save_item(NAME(cpustate->port2_ddr));
+ cpustate->device->save_item(NAME(cpustate->port3_ddr));
+ cpustate->device->save_item(NAME(cpustate->port4_ddr));
+ cpustate->device->save_item(NAME(cpustate->port1_data));
+ cpustate->device->save_item(NAME(cpustate->port2_data));
+ cpustate->device->save_item(NAME(cpustate->port3_data));
+ cpustate->device->save_item(NAME(cpustate->port4_data));
+ cpustate->device->save_item(NAME(cpustate->port2_written));
+ cpustate->device->save_item(NAME(cpustate->port3_latched));
+ cpustate->device->save_item(NAME(cpustate->p3csr));
+ cpustate->device->save_item(NAME(cpustate->p3csr_is3_flag_read));
+ cpustate->device->save_item(NAME(cpustate->tcsr));
+ cpustate->device->save_item(NAME(cpustate->pending_tcsr));
+ cpustate->device->save_item(NAME(cpustate->irq2));
+ cpustate->device->save_item(NAME(cpustate->ram_ctrl));
+
+ cpustate->device->save_item(NAME(cpustate->counter.d));
+ cpustate->device->save_item(NAME(cpustate->output_compare.d));
+ cpustate->device->save_item(NAME(cpustate->input_capture));
+ cpustate->device->save_item(NAME(cpustate->timer_over.d));
+
+ cpustate->device->save_item(NAME(cpustate->clock));
+ cpustate->device->save_item(NAME(cpustate->trcsr));
+ cpustate->device->save_item(NAME(cpustate->rmcr));
+ cpustate->device->save_item(NAME(cpustate->rdr));
+ cpustate->device->save_item(NAME(cpustate->tdr));
+ cpustate->device->save_item(NAME(cpustate->rsr));
+ cpustate->device->save_item(NAME(cpustate->tsr));
+ cpustate->device->save_item(NAME(cpustate->rxbits));
+ cpustate->device->save_item(NAME(cpustate->txbits));
+ cpustate->device->save_item(NAME(cpustate->txstate));
+ cpustate->device->save_item(NAME(cpustate->trcsr_read_tdre));
+ cpustate->device->save_item(NAME(cpustate->trcsr_read_orfe));
+ cpustate->device->save_item(NAME(cpustate->trcsr_read_rdrf));
+ cpustate->device->save_item(NAME(cpustate->tx));
+}
+
+static CPU_INIT( m6800 )
+{
+ m6800_state *cpustate = get_safe_token(device);
+
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+ cpustate->data = device->space(AS_DATA);
+ cpustate->io = device->space(AS_IO);
+
+ // cpustate->subtype = SUBTYPE_M6800;
+ cpustate->insn = m6800_insn;
+ cpustate->cycles = cycles_6800;
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+ state_register(cpustate, "m6800");
+}
+
+static CPU_RESET( m6800 )
+{
+ m6800_state *cpustate = get_safe_token(device);
+
+ cpustate->cc = 0xc0;
+ SEI; /* IRQ disabled */
+ PCD = RM16(cpustate, 0xfffe );
+
+ cpustate->wai_state = 0;
+ cpustate->nmi_state = 0;
+ cpustate->nmi_pending = 0;
+ cpustate->sc1_state = 0;
+ cpustate->irq_state[M6800_IRQ_LINE] = 0;
+ cpustate->irq_state[M6801_TIN_LINE] = 0;
+ cpustate->ic_eddge = 0;
+
+ cpustate->port1_ddr = 0x00;
+ cpustate->port2_ddr = 0x00;
+ cpustate->port3_ddr = 0x00;
+ cpustate->p3csr = 0x00;
+ cpustate->p3csr_is3_flag_read = 0;
+ cpustate->port2_written = 0;
+ cpustate->port3_latched = 0;
+ /* TODO: on reset port 2 should be read to determine the operating mode (bits 0-2) */
+ cpustate->tcsr = 0x00;
+ cpustate->pending_tcsr = 0x00;
+ cpustate->irq2 = 0;
+ CTD = 0x0000;
+ OCD = 0xffff;
+ TOD = 0xffff;
+ cpustate->ram_ctrl |= 0x40;
+
+ cpustate->trcsr = M6800_TRCSR_TDRE;
+
+ cpustate->txstate = M6800_TX_STATE_INIT;
+ cpustate->txbits = cpustate->rxbits = 0;
+ cpustate->tx = 1;
+ cpustate->trcsr_read_tdre = 0;
+ cpustate->trcsr_read_orfe = 0;
+ cpustate->trcsr_read_rdrf = 0;
+
+ set_rmcr(cpustate, 0);
+}
+
+/****************************************************************************
+ * Shut down CPU emulation
+ ****************************************************************************/
+static CPU_EXIT( m6800 )
+{
+ /* nothing to do */
+}
+
+
+static void set_irq_line(m6800_state *cpustate, int irqline, int state)
+{
+ switch (irqline)
+ {
+ case INPUT_LINE_NMI:
+ if (!cpustate->nmi_state && state != CLEAR_LINE)
+ cpustate->nmi_pending = TRUE;
+ cpustate->nmi_state = state;
+ break;
+
+ case M6801_SC1_LINE:
+ if (!cpustate->port3_latched && (cpustate->p3csr & M6801_P3CSR_LE))
+ {
+ if (!cpustate->sc1_state && state)
+ {
+ // latch input data to port 3
+ cpustate->port3_data = (cpustate->io->read_byte(M6801_PORT3) & (cpustate->port3_ddr ^ 0xff)) | (cpustate->port3_data & cpustate->port3_ddr);
+ cpustate->port3_latched = 1;
+ //logerror("M6801 '%s' Latched Port 3 Data: %02x\n", cpustate->device->tag(), cpustate->port3_data);
+
+ // set IS3 flag bit
+ cpustate->p3csr |= M6801_P3CSR_IS3_FLAG;
+ }
+ }
+ cpustate->sc1_state = state;
+ break;
+
+ default:
+ LOG(("M6800 '%s' set_irq_line %d,%d\n", cpustate->device->tag(), irqline, state));
+ cpustate->irq_state[irqline] = state;
+
+ if (irqline == M6801_TIN_LINE && state != cpustate->irq_state[irqline])
+ {
+ //eddge = (state == CLEAR_LINE ) ? 2 : 0;
+ if( ((cpustate->tcsr&TCSR_IEDG) ^ (state==CLEAR_LINE ? TCSR_IEDG : 0))==0 )
+ return;
+ /* active edge in */
+ cpustate->tcsr |= TCSR_ICF;
+ cpustate->pending_tcsr |= TCSR_ICF;
+ cpustate->input_capture = CT;
+ MODIFIED_tcsr;
+ }
+ }
+}
+
+/****************************************************************************
+ * Execute cycles CPU cycles. Return number of cycles really executed
+ ****************************************************************************/
+static CPU_EXECUTE( m6800 )
+{
+ m6800_state *cpustate = get_safe_token(device);
+ UINT8 ireg;
+
+ CHECK_IRQ_LINES(cpustate); /* HJB 990417 */
+
+ CLEANUP_COUNTERS();
+
+ do
+ {
+ if( cpustate->wai_state & (M6800_WAI|M6800_SLP) )
+ {
+ EAT_CYCLES;
+ }
+ else
+ {
+ pPPC = pPC;
+ debugger_instruction_hook(device, PCD);
+ ireg=M_RDOP(PCD);
+ PC++;
+ (*cpustate->insn[ireg])(cpustate);
+ increment_counter(cpustate, cpustate->cycles[ireg]);
+ }
+ } while( cpustate->icount>0 );
+}
+
+/****************************************************************************
+ * M6801 almost (fully?) equal to the M6803
+ ****************************************************************************/
+static CPU_INIT( m6801 )
+{
+ m6800_state *cpustate = get_safe_token(device);
+// cpustate->subtype = SUBTYPE_M6801;
+ cpustate->insn = m6803_insn;
+ cpustate->cycles = cycles_6803;
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+ cpustate->data = device->space(AS_DATA);
+ cpustate->io = device->space(AS_IO);
+
+ cpustate->clock = device->clock() / 4;
+ cpustate->sci_timer = device->machine().scheduler().timer_alloc(FUNC(sci_tick), cpustate);
+
+ state_register(cpustate, "m6801");
+
+ if (device->static_config() != NULL)
+ {
+ m6801_interface *intf = (m6801_interface *) device->static_config();
+
+ cpustate->out_sc2_func.resolve(intf->out_sc2_func, *device);
+ }
+ else
+ {
+ devcb_write_line nullcb = DEVCB_NULL;
+ cpustate->out_sc2_func.resolve(nullcb, *device);
+ }
+}
+
+/****************************************************************************
+ * M6802 almost (fully?) equal to the M6800
+ ****************************************************************************/
+static CPU_INIT( m6802 )
+{
+ m6800_state *cpustate = get_safe_token(device);
+ // cpustate->subtype = SUBTYPE_M6802;
+ cpustate->insn = m6800_insn;
+ cpustate->cycles = cycles_6800;
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+ cpustate->data = device->space(AS_DATA);
+ cpustate->io = device->space(AS_IO);
+
+ state_register(cpustate, "m6802");
+}
+
+/****************************************************************************
+ * M6803 almost (fully?) equal to the M6801
+ ****************************************************************************/
+static CPU_INIT( m6803 )
+{
+ m6800_state *cpustate = get_safe_token(device);
+ // cpustate->subtype = SUBTYPE_M6803;
+ cpustate->insn = m6803_insn;
+ cpustate->cycles = cycles_6803;
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+ cpustate->data = device->space(AS_DATA);
+ cpustate->io = device->space(AS_IO);
+
+ cpustate->clock = device->clock() / 4;
+ cpustate->sci_timer = device->machine().scheduler().timer_alloc(FUNC(sci_tick), cpustate);
+
+ state_register(cpustate, "m6803");
+
+ if (device->static_config() != NULL)
+ {
+ m6801_interface *intf = (m6801_interface *) device->static_config();
+
+ cpustate->out_sc2_func.resolve(intf->out_sc2_func, *device);
+ }
+ else
+ {
+ devcb_write_line nullcb = DEVCB_NULL;
+ cpustate->out_sc2_func.resolve(nullcb, *device);
+ }
+}
+
+static ADDRESS_MAP_START(m6803_mem, AS_PROGRAM, 8)
+ AM_RANGE(0x0000, 0x001f) AM_READWRITE(m6801_io_r, m6801_io_w)
+ AM_RANGE(0x0020, 0x007f) AM_NOP /* unused */
+ AM_RANGE(0x0080, 0x00ff) AM_RAM /* 6803 internal RAM */
+ADDRESS_MAP_END
+
+
+/****************************************************************************
+ * M6808 almost (fully?) equal to the M6800
+ ****************************************************************************/
+static CPU_INIT( m6808 )
+{
+ m6800_state *cpustate = get_safe_token(device);
+ // cpustate->subtype = SUBTYPE_M6808;
+ cpustate->insn = m6800_insn;
+ cpustate->cycles = cycles_6800;
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+ cpustate->data = device->space(AS_DATA);
+ cpustate->io = device->space(AS_IO);
+
+ state_register(cpustate, "m6808");
+}
+
+/****************************************************************************
+ * HD6301 similiar to the M6800
+ ****************************************************************************/
+
+static CPU_INIT( hd6301 )
+{
+ m6800_state *cpustate = get_safe_token(device);
+ // cpustate->subtype = SUBTYPE_HD6301;
+ cpustate->insn = hd63701_insn;
+ cpustate->cycles = cycles_63701;
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+ cpustate->data = device->space(AS_DATA);
+ cpustate->io = device->space(AS_IO);
+
+ cpustate->clock = device->clock() / 4;
+ cpustate->sci_timer = device->machine().scheduler().timer_alloc(FUNC(sci_tick), cpustate);
+
+ state_register(cpustate, "hd6301");
+}
+
+/****************************************************************************
+ * HD63701 similiar to the HD6301
+ ****************************************************************************/
+
+static CPU_INIT( hd63701 )
+{
+ m6800_state *cpustate = get_safe_token(device);
+ // cpustate->subtype = SUBTYPE_HD63701;
+ cpustate->insn = hd63701_insn;
+ cpustate->cycles = cycles_63701;
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+ cpustate->data = device->space(AS_DATA);
+ cpustate->io = device->space(AS_IO);
+
+ cpustate->clock = device->clock() / 4;
+ cpustate->sci_timer = device->machine().scheduler().timer_alloc(FUNC(sci_tick), cpustate);
+
+ state_register(cpustate, "hd63701");
+}
+
+/*
+ if change_pc(cpustate) direccted these areas ,Call hd63701_trap_pc(cpustate).
+ 'mode' is selected by the sense of p2.0,p2.1,and p2.3 at reset timming.
+ mode 0,1,2,4,6 : $0000-$001f
+ mode 5 : $0000-$001f,$0200-$efff
+ mode 7 : $0000-$001f,$0100-$efff
+*/
+#if 0
+static void hd63701_trap_pc(m6800_state *cpustate)
+{
+ TAKE_TRAP;
+}
+#endif
+
+/****************************************************************************
+ * NSC-8105 similiar to the M6800, but the opcodes are scrambled and there
+ * is at least one new opcode ($fc)
+ ****************************************************************************/
+static CPU_INIT( nsc8105 )
+{
+ m6800_state *cpustate = get_safe_token(device);
+ // cpustate->subtype = SUBTYPE_NSC8105;
+ cpustate->device = device;
+
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+ cpustate->data = device->space(AS_DATA);
+ cpustate->io = device->space(AS_IO);
+
+ cpustate->insn = nsc8105_insn;
+ cpustate->cycles = cycles_nsc8105;
+ state_register(cpustate, "nsc8105");
+}
+
+INLINE void set_os3(m6800_state *cpustate, int state)
+{
+ //logerror("M6801 '%s' OS3: %u\n", cpustate->device->tag(), state);
+
+ cpustate->out_sc2_func(state);
+}
+
+READ8_HANDLER( m6801_io_r )
+{
+ m6800_state *cpustate = get_safe_token(&space->device());
+
+ UINT8 data = 0;
+
+ switch (offset)
+ {
+ case IO_P1DDR:
+ data = cpustate->port1_ddr;
+ break;
+
+ case IO_P2DDR:
+ data = cpustate->port2_ddr;
+ break;
+
+ case IO_P1DATA:
+ if(cpustate->port1_ddr == 0xff)
+ data = cpustate->port1_data;
+ else
+ data = (cpustate->io->read_byte(M6801_PORT1) & (cpustate->port1_ddr ^ 0xff))
+ | (cpustate->port1_data & cpustate->port1_ddr);
+ break;
+
+ case IO_P2DATA:
+ if(cpustate->port2_ddr == 0xff)
+ data = cpustate->port2_data;
+ else
+ data = (cpustate->io->read_byte(M6801_PORT2) & (cpustate->port2_ddr ^ 0xff))
+ | (cpustate->port2_data & cpustate->port2_ddr);
+ break;
+
+ case IO_P3DDR:
+ logerror("M6801 '%s' Port 3 DDR is a write-only register\n", space->device().tag());
+ break;
+
+ case IO_P4DDR:
+ data = cpustate->port4_ddr;
+ break;
+
+ case IO_P3DATA:
+ if (!space->debugger_access())
+ {
+ if (cpustate->p3csr_is3_flag_read)
+ {
+ //logerror("M6801 '%s' Cleared IS3\n", space->device().tag());
+ cpustate->p3csr &= ~M6801_P3CSR_IS3_FLAG;
+ cpustate->p3csr_is3_flag_read = 0;
+ }
+
+ if (!(cpustate->p3csr & M6801_P3CSR_OSS))
+ {
+ set_os3(cpustate, ASSERT_LINE);
+ }
+ }
+
+ if ((cpustate->p3csr & M6801_P3CSR_LE) || (cpustate->port3_ddr == 0xff))
+ data = cpustate->port3_data;
+ else
+ data = (cpustate->io->read_byte(M6801_PORT3) & (cpustate->port3_ddr ^ 0xff))
+ | (cpustate->port3_data & cpustate->port3_ddr);
+
+ if (!space->debugger_access())
+ {
+ cpustate->port3_latched = 0;
+
+ if (!(cpustate->p3csr & M6801_P3CSR_OSS))
+ {
+ set_os3(cpustate, CLEAR_LINE);
+ }
+ }
+ break;
+
+ case IO_P4DATA:
+ if(cpustate->port4_ddr == 0xff)
+ data = cpustate->port4_data;
+ else
+ data = (cpustate->io->read_byte(M6801_PORT4) & (cpustate->port4_ddr ^ 0xff))
+ | (cpustate->port4_data & cpustate->port4_ddr);
+ break;
+
+ case IO_TCSR:
+ cpustate->pending_tcsr = 0;
+ data = cpustate->tcsr;
+ break;
+
+ case IO_CH:
+ if(!(cpustate->pending_tcsr&TCSR_TOF) && !space->debugger_access())
+ {
+ cpustate->tcsr &= ~TCSR_TOF;
+ MODIFIED_tcsr;
+ }
+ data = cpustate->counter.b.h;
+ break;
+
+ case IO_CL:
+ data = cpustate->counter.b.l;
+
+ case IO_OCRH:
+ if(!(cpustate->pending_tcsr&TCSR_OCF) && !space->debugger_access())
+ {
+ cpustate->tcsr &= ~TCSR_OCF;
+ MODIFIED_tcsr;
+ }
+ data = cpustate->output_compare.b.h;
+ break;
+
+ case IO_OCRL:
+ if(!(cpustate->pending_tcsr&TCSR_OCF) && !space->debugger_access())
+ {
+ cpustate->tcsr &= ~TCSR_OCF;
+ MODIFIED_tcsr;
+ }
+ data = cpustate->output_compare.b.l;
+ break;
+
+ case IO_ICRH:
+ if(!(cpustate->pending_tcsr&TCSR_ICF) && !space->debugger_access())
+ {
+ cpustate->tcsr &= ~TCSR_ICF;
+ MODIFIED_tcsr;
+ }
+ data = (cpustate->input_capture >> 0) & 0xff;
+ break;
+
+ case IO_ICRL:
+ data = (cpustate->input_capture >> 8) & 0xff;
+ break;
+
+ case IO_P3CSR:
+ if ((cpustate->p3csr & M6801_P3CSR_IS3_FLAG) && !space->debugger_access())
+ {
+ cpustate->p3csr_is3_flag_read = 1;
+ }
+
+ data = cpustate->p3csr;
+ break;
+
+ case IO_RMCR:
+ data = cpustate->rmcr;
+ break;
+
+ case IO_TRCSR:
+ if (!space->debugger_access())
+ {
+ if (cpustate->trcsr & M6800_TRCSR_TDRE)
+ {
+ cpustate->trcsr_read_tdre = 1;
+ }
+
+ if (cpustate->trcsr & M6800_TRCSR_ORFE)
+ {
+ cpustate->trcsr_read_orfe = 1;
+ }
+
+ if (cpustate->trcsr & M6800_TRCSR_RDRF)
+ {
+ cpustate->trcsr_read_rdrf = 1;
+ }
+ }
+
+ data = cpustate->trcsr;
+ break;
+
+ case IO_RDR:
+ if (!space->debugger_access())
+ {
+ if (cpustate->trcsr_read_orfe)
+ {
+ //logerror("M6801 '%s' Cleared ORFE\n", space->device().tag());
+ cpustate->trcsr_read_orfe = 0;
+ cpustate->trcsr &= ~M6800_TRCSR_ORFE;
+ }
+
+ if (cpustate->trcsr_read_rdrf)
+ {
+ //logerror("M6801 '%s' Cleared RDRF\n", space->device().tag());
+ cpustate->trcsr_read_rdrf = 0;
+ cpustate->trcsr &= ~M6800_TRCSR_RDRF;
+ }
+ }
+
+ data = cpustate->rdr;
+ break;
+
+ case IO_TDR:
+ data = cpustate->tdr;
+ break;
+
+ case IO_RCR:
+ data = cpustate->ram_ctrl;
+ break;
+
+ case IO_CAAH:
+ case IO_CAAL:
+ case IO_TCR1:
+ case IO_TCR2:
+ case IO_TSR:
+ case IO_OCR2H:
+ case IO_OCR2L:
+ case IO_OCR3H:
+ case IO_OCR3L:
+ case IO_ICR2H:
+ case IO_ICR2L:
+ default:
+ logerror("M6801 '%s' PC %04x: warning - read from reserved internal register %02x\n",space->device().tag(),cpu_get_pc(&space->device()),offset);
+ }
+
+ return data;
+}
+
+WRITE8_HANDLER( m6801_io_w )
+{
+ m6800_state *cpustate = get_safe_token(&space->device());
+
+ switch (offset)
+ {
+ case IO_P1DDR:
+ //logerror("M6801 '%s' Port 1 Data Direction Register: %02x\n", space->device().tag(), data);
+
+ if (cpustate->port1_ddr != data)
+ {
+ cpustate->port1_ddr = data;
+ if(cpustate->port1_ddr == 0xff)
+ cpustate->io->write_byte(M6801_PORT1,cpustate->port1_data);
+ else
+ cpustate->io->write_byte(M6801_PORT1,(cpustate->port1_data & cpustate->port1_ddr) | (cpustate->port1_ddr ^ 0xff));
+ }
+ break;
+
+ case IO_P2DDR:
+ //logerror("M6801 '%s' Port 2 Data Direction Register: %02x\n", space->device().tag(), data);
+
+ if (cpustate->port2_ddr != data)
+ {
+ cpustate->port2_ddr = data;
+ write_port2(cpustate);
+
+ if (cpustate->port2_ddr & 2)
+ logerror("CPU '%s' PC %04x: warning - port 2 bit 1 set as output (OLVL) - not supported\n",space->device().tag(),cpu_get_pc(&space->device()));
+ }
+ break;
+
+ case IO_P1DATA:
+ //logerror("M6801 '%s' Port 1 Data Register: %02x\n", space->device().tag(), data);
+
+ cpustate->port1_data = data;
+ if(cpustate->port1_ddr == 0xff)
+ cpustate->io->write_byte(M6801_PORT1,cpustate->port1_data);
+ else
+ cpustate->io->write_byte(M6801_PORT1,(cpustate->port1_data & cpustate->port1_ddr) | (cpustate->port1_ddr ^ 0xff));
+ break;
+
+ case IO_P2DATA:
+ //logerror("M6801 '%s' Port 2 Data Register: %02x\n", space->device().tag(), data);
+
+ cpustate->port2_data = data;
+ cpustate->port2_written = 1;
+ write_port2(cpustate);
+ break;
+
+ case IO_P3DDR:
+ //logerror("M6801 '%s' Port 3 Data Direction Register: %02x\n", space->device().tag(), data);
+
+ if (cpustate->port3_ddr != data)
+ {
+ cpustate->port3_ddr = data;
+ if(cpustate->port3_ddr == 0xff)
+ cpustate->io->write_byte(M6801_PORT3,cpustate->port3_data);
+ else
+ cpustate->io->write_byte(M6801_PORT3,(cpustate->port3_data & cpustate->port3_ddr) | (cpustate->port3_ddr ^ 0xff));
+ }
+ break;
+
+ case IO_P4DDR:
+ //logerror("M6801 '%s' Port 4 Data Direction Register: %02x\n", space->device().tag(), data);
+
+ if (cpustate->port4_ddr != data)
+ {
+ cpustate->port4_ddr = data;
+ if(cpustate->port4_ddr == 0xff)
+ cpustate->io->write_byte(M6801_PORT4,cpustate->port4_data);
+ else
+ cpustate->io->write_byte(M6801_PORT4,(cpustate->port4_data & cpustate->port4_ddr) | (cpustate->port4_ddr ^ 0xff));
+ }
+ break;
+
+ case IO_P3DATA:
+ //logerror("M6801 '%s' Port 3 Data Register: %02x\n", space->device().tag(), data);
+
+ if (cpustate->p3csr_is3_flag_read)
+ {
+ //logerror("M6801 '%s' Cleared IS3\n", space->device().tag());
+ cpustate->p3csr &= ~M6801_P3CSR_IS3_FLAG;
+ cpustate->p3csr_is3_flag_read = 0;
+ }
+
+ if (cpustate->p3csr & M6801_P3CSR_OSS)
+ {
+ set_os3(cpustate, ASSERT_LINE);
+ }
+
+ cpustate->port3_data = data;
+ if(cpustate->port3_ddr == 0xff)
+ cpustate->io->write_byte(M6801_PORT3,cpustate->port3_data);
+ else
+ cpustate->io->write_byte(M6801_PORT3,(cpustate->port3_data & cpustate->port3_ddr) | (cpustate->port3_ddr ^ 0xff));
+
+ if (cpustate->p3csr & M6801_P3CSR_OSS)
+ {
+ set_os3(cpustate, CLEAR_LINE);
+ }
+ break;
+
+ case IO_P4DATA:
+ //logerror("M6801 '%s' Port 4 Data Register: %02x\n", space->device().tag(), data);
+
+ cpustate->port4_data = data;
+ if(cpustate->port4_ddr == 0xff)
+ cpustate->io->write_byte(M6801_PORT4,cpustate->port4_data);
+ else
+ cpustate->io->write_byte(M6801_PORT4,(cpustate->port4_data & cpustate->port4_ddr) | (cpustate->port4_ddr ^ 0xff));
+ break;
+
+ case IO_TCSR:
+ //logerror("M6801 '%s' Timer Control and Status Register: %02x\n", space->device().tag(), data);
+
+ cpustate->tcsr = data;
+ cpustate->pending_tcsr &= cpustate->tcsr;
+ MODIFIED_tcsr;
+ if( !(CC & 0x10) )
+ m6800_check_irq2(cpustate);
+ break;
+
+ case IO_CH:
+ //logerror("M6801 '%s' Counter High Register: %02x\n", space->device().tag(), data);
+
+ cpustate->latch09 = data & 0xff; /* 6301 only */
+ CT = 0xfff8;
+ TOH = CTH;
+ MODIFIED_counters;
+ break;
+
+ case IO_CL: /* 6301 only */
+ //logerror("M6801 '%s' Counter Low Register: %02x\n", space->device().tag(), data);
+
+ CT = (cpustate->latch09 << 8) | (data & 0xff);
+ TOH = CTH;
+ MODIFIED_counters;
+ break;
+
+ case IO_OCRH:
+ //logerror("M6801 '%s' Output Compare High Register: %02x\n", space->device().tag(), data);
+
+ if( cpustate->output_compare.b.h != data)
+ {
+ cpustate->output_compare.b.h = data;
+ MODIFIED_counters;
+ }
+ break;
+
+ case IO_OCRL:
+ //logerror("M6801 '%s' Output Compare Low Register: %02x\n", space->device().tag(), data);
+
+ if( cpustate->output_compare.b.l != data)
+ {
+ cpustate->output_compare.b.l = data;
+ MODIFIED_counters;
+ }
+ break;
+
+ case IO_ICRH:
+ case IO_ICRL:
+ case IO_RDR:
+ //logerror("CPU '%s' PC %04x: warning - write %02x to read only internal register %02x\n",space->device().tag(),cpu_get_pc(&space->device()),data,offset);
+ break;
+
+ case IO_P3CSR:
+ //logerror("M6801 '%s' Port 3 Control and Status Register: %02x\n", space->device().tag(), data);
+
+ cpustate->p3csr = data;
+ break;
+
+ case IO_RMCR:
+ //logerror("M6801 '%s' Rate and Mode Control Register: %02x\n", space->device().tag(), data);
+
+ set_rmcr(cpustate, data);
+ break;
+
+ case IO_TRCSR:
+ //logerror("M6801 '%s' Transmit/Receive Control and Status Register: %02x\n", space->device().tag(), data);
+
+ if ((data & M6800_TRCSR_TE) && !(cpustate->trcsr & M6800_TRCSR_TE))
+ {
+ cpustate->txstate = M6800_TX_STATE_INIT;
+ cpustate->txbits = 0;
+ cpustate->tx = 1;
+ }
+
+ if ((data & M6800_TRCSR_RE) && !(cpustate->trcsr & M6800_TRCSR_RE))
+ {
+ cpustate->rxbits = 0;
+ }
+
+ cpustate->trcsr = (cpustate->trcsr & 0xe0) | (data & 0x1f);
+ break;
+
+ case IO_TDR:
+ //logerror("M6800 '%s' Transmit Data Register: %02x\n", space->device().tag(), data);
+
+ if (cpustate->trcsr_read_tdre)
+ {
+ cpustate->trcsr_read_tdre = 0;
+ cpustate->trcsr &= ~M6800_TRCSR_TDRE;
+ }
+ cpustate->tdr = data;
+ break;
+
+ case IO_RCR:
+ //logerror("M6801 '%s' RAM Control Register: %02x\n", space->device().tag(), data);
+
+ cpustate->ram_ctrl = data;
+ break;
+
+ case IO_CAAH:
+ case IO_CAAL:
+ case IO_TCR1:
+ case IO_TCR2:
+ case IO_TSR:
+ case IO_OCR2H:
+ case IO_OCR2L:
+ case IO_OCR3H:
+ case IO_OCR3L:
+ case IO_ICR2H:
+ case IO_ICR2L:
+ default:
+ logerror("M6801 '%s' PC %04x: warning - write %02x to reserved internal register %02x\n",space->device().tag(),cpu_get_pc(&space->device()),data,offset);
+ break;
+ }
+}
+
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( m6800 )
+{
+ m6800_state *cpustate = get_safe_token(device);
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + M6800_IRQ_LINE: set_irq_line(cpustate, M6800_IRQ_LINE, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + M6801_TIN_LINE: set_irq_line(cpustate, M6801_TIN_LINE, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + M6801_SC1_LINE: set_irq_line(cpustate, M6801_SC1_LINE, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: set_irq_line(cpustate, INPUT_LINE_NMI, info->i); break;
+
+ case CPUINFO_INT_PC: PC = info->i; break;
+ case CPUINFO_INT_REGISTER + M6800_PC: cpustate->pc.w.l = info->i; break;
+ case CPUINFO_INT_SP: S = info->i; break;
+ case CPUINFO_INT_REGISTER + M6800_S: cpustate->s.w.l = info->i; break;
+ case CPUINFO_INT_REGISTER + M6800_CC: cpustate->cc = info->i; break;
+ case CPUINFO_INT_REGISTER + M6800_A: cpustate->d.b.h = info->i; break;
+ case CPUINFO_INT_REGISTER + M6800_B: cpustate->d.b.l = info->i; break;
+ case CPUINFO_INT_REGISTER + M6800_X: cpustate->x.w.l = info->i; break;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+CPU_GET_INFO( m6800 )
+{
+ m6800_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(m6800_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 2; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 12; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 9; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_INPUT_STATE + M6800_IRQ_LINE: info->i = cpustate->irq_state[M6800_IRQ_LINE]; break;
+ case CPUINFO_INT_INPUT_STATE + M6801_TIN_LINE: info->i = cpustate->irq_state[M6801_TIN_LINE]; break;
+ case CPUINFO_INT_INPUT_STATE + M6801_SC1_LINE: info->i = cpustate->irq_state[M6801_SC1_LINE]; break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: info->i = cpustate->nmi_state; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = cpustate->ppc.w.l; break;
+
+ case CPUINFO_INT_PC: info->i = PC; break;
+ case CPUINFO_INT_REGISTER + M6800_PC: info->i = cpustate->pc.w.l; break;
+ case CPUINFO_INT_SP: info->i = S; break;
+ case CPUINFO_INT_REGISTER + M6800_S: info->i = cpustate->s.w.l; break;
+ case CPUINFO_INT_REGISTER + M6800_CC: info->i = cpustate->cc; break;
+ case CPUINFO_INT_REGISTER + M6800_A: info->i = cpustate->d.b.h; break;
+ case CPUINFO_INT_REGISTER + M6800_B: info->i = cpustate->d.b.l; break;
+ case CPUINFO_INT_REGISTER + M6800_X: info->i = cpustate->x.w.l; break;
+ case CPUINFO_INT_REGISTER + M6800_WAI_STATE: info->i = cpustate->wai_state; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(m6800); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(m6800); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(m6800); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(m6800); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(m6800); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(m6800); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "M6800"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Motorola 6800"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.1"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "The MAME team."); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c%c%c%c%c%c%c",
+ cpustate->cc & 0x80 ? '?':'.',
+ cpustate->cc & 0x40 ? '?':'.',
+ cpustate->cc & 0x20 ? 'H':'.',
+ cpustate->cc & 0x10 ? 'I':'.',
+ cpustate->cc & 0x08 ? 'N':'.',
+ cpustate->cc & 0x04 ? 'Z':'.',
+ cpustate->cc & 0x02 ? 'V':'.',
+ cpustate->cc & 0x01 ? 'C':'.');
+ break;
+
+ case CPUINFO_STR_REGISTER + M6800_A: sprintf(info->s, "A:%02X", cpustate->d.b.h); break;
+ case CPUINFO_STR_REGISTER + M6800_B: sprintf(info->s, "B:%02X", cpustate->d.b.l); break;
+ case CPUINFO_STR_REGISTER + M6800_PC: sprintf(info->s, "PC:%04X", cpustate->pc.w.l); break;
+ case CPUINFO_STR_REGISTER + M6800_S: sprintf(info->s, "S:%04X", cpustate->s.w.l); break;
+ case CPUINFO_STR_REGISTER + M6800_X: sprintf(info->s, "X:%04X", cpustate->x.w.l); break;
+ case CPUINFO_STR_REGISTER + M6800_CC: sprintf(info->s, "CC:%02X", cpustate->cc); break;
+ case CPUINFO_STR_REGISTER + M6800_WAI_STATE: sprintf(info->s, "WAI:%X", cpustate->wai_state); break;
+ }
+}
+
+
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+
+CPU_GET_INFO( m6801 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 4; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 9; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(m6801); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(m6801); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "M6801"); break;
+
+ default: CPU_GET_INFO_CALL(m6800); break;
+ }
+}
+
+
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+
+CPU_GET_INFO( m6802 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 4; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(m6802); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(m6802); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "M6802"); break;
+
+ default: CPU_GET_INFO_CALL(m6800); break;
+ }
+}
+
+
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+
+CPU_GET_INFO( m6803 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 4; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 9; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(m6803); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(m6803); break;
+
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME(m6803_mem); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "M6803"); break;
+
+ default: CPU_GET_INFO_CALL(m6800); break;
+ }
+}
+
+
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+
+CPU_GET_INFO( m6808 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 4; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(m6808); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(m6808); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "M6808"); break;
+
+ default: CPU_GET_INFO_CALL(m6800); break;
+ }
+}
+
+
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+
+CPU_GET_INFO( hd6301 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 4; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 9; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(hd6301); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(hd6301); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "HD6301"); break;
+
+ default: CPU_GET_INFO_CALL(m6800); break;
+ }
+}
+
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+
+CPU_GET_INFO( hd63701 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 4; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 9; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(hd63701); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(hd63701); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "HD63701"); break;
+
+ default: CPU_GET_INFO_CALL(m6800); break;
+ }
+}
+
+
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+
+CPU_GET_INFO( nsc8105 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 4; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(nsc8105); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(nsc8105); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "NSC8105"); break;
+
+ default: CPU_GET_INFO_CALL(m6800); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(M6800, m6800);
+DEFINE_LEGACY_CPU_DEVICE(M6801, m6801);
+DEFINE_LEGACY_CPU_DEVICE(M6802, m6802);
+DEFINE_LEGACY_CPU_DEVICE(M6803, m6803);
+DEFINE_LEGACY_CPU_DEVICE(M6808, m6808);
+DEFINE_LEGACY_CPU_DEVICE(HD6301, hd6301);
+DEFINE_LEGACY_CPU_DEVICE(HD63701, hd63701);
+DEFINE_LEGACY_CPU_DEVICE(NSC8105, nsc8105);
diff --git a/trunk/src/emu/cpu/m6800/m6800.h b/trunk/src/emu/cpu/m6800/m6800.h
new file mode 100644
index 00000000000..7cdce37592d
--- /dev/null
+++ b/trunk/src/emu/cpu/m6800/m6800.h
@@ -0,0 +1,76 @@
+/*** m6800: Portable 6800 class emulator *************************************/
+
+#pragma once
+
+#ifndef __M6800_H__
+#define __M6800_H__
+
+
+typedef struct _m6801_interface m6801_interface;
+struct _m6801_interface
+{
+ devcb_write_line out_sc2_func;
+};
+#define M6801_INTERFACE(name) const m6801_interface (name) =
+
+
+enum
+{
+ M6800_PC=1, M6800_S, M6800_A, M6800_B, M6800_X, M6800_CC,
+ M6800_WAI_STATE
+};
+
+enum
+{
+ M6800_IRQ_LINE = 0, /* IRQ line number */
+ M6801_TIN_LINE, /* P20/Tin Input Capture line (eddge sense) */
+ /* Active eddge is selecrable by internal reg. */
+ /* raise eddge : CLEAR_LINE -> ASSERT_LINE */
+ /* fall eddge : ASSERT_LINE -> CLEAR_LINE */
+ /* it is usuali to use PULSE_LINE state */
+ M6801_SC1_LINE
+};
+
+enum
+{
+ M6801_MODE_0 = 0,
+ M6801_MODE_1,
+ M6801_MODE_2,
+ M6801_MODE_3,
+ M6801_MODE_4,
+ M6801_MODE_5,
+ M6801_MODE_6,
+ M6801_MODE_7
+};
+
+enum
+{
+ M6801_PORT1 = 0x100,
+ M6801_PORT2,
+ M6801_PORT3,
+ M6801_PORT4
+};
+
+DECLARE_LEGACY_CPU_DEVICE(M6800, m6800);
+DECLARE_LEGACY_CPU_DEVICE(M6801, m6801);
+DECLARE_LEGACY_CPU_DEVICE(M6802, m6802);
+DECLARE_LEGACY_CPU_DEVICE(M6803, m6803);
+DECLARE_LEGACY_CPU_DEVICE(M6808, m6808);
+DECLARE_LEGACY_CPU_DEVICE(HD6301, hd6301);
+DECLARE_LEGACY_CPU_DEVICE(HD63701, hd63701);
+DECLARE_LEGACY_CPU_DEVICE(NSC8105, nsc8105);
+
+READ8_HANDLER( m6801_io_r );
+WRITE8_HANDLER( m6801_io_w );
+
+CPU_DISASSEMBLE( m6800 );
+CPU_DISASSEMBLE( m6801 );
+CPU_DISASSEMBLE( m6802 );
+CPU_DISASSEMBLE( m6803 );
+CPU_DISASSEMBLE( m6808 );
+CPU_DISASSEMBLE( hd6301 );
+CPU_DISASSEMBLE( hd63701 );
+CPU_DISASSEMBLE( nsc8105 );
+
+#endif /* __M6800_H__ */
+
diff --git a/trunk/src/emu/cpu/m68000/m68000.h b/trunk/src/emu/cpu/m68000/m68000.h
new file mode 100644
index 00000000000..2e38254b834
--- /dev/null
+++ b/trunk/src/emu/cpu/m68000/m68000.h
@@ -0,0 +1,120 @@
+#pragma once
+
+#ifndef __M68000_H__
+#define __M68000_H__
+
+
+/* There are 7 levels of interrupt to the 68K.
+ * A transition from < 7 to 7 will cause a non-maskable interrupt (NMI).
+ */
+#define M68K_IRQ_NONE 0
+#define M68K_IRQ_1 1
+#define M68K_IRQ_2 2
+#define M68K_IRQ_3 3
+#define M68K_IRQ_4 4
+#define M68K_IRQ_5 5
+#define M68K_IRQ_6 6
+#define M68K_IRQ_7 7
+
+// special input lines
+#define M68K_LINE_BUSERROR 16
+
+/* CPU types for use in m68k_set_cpu_type() */
+enum
+{
+ M68K_CPU_TYPE_INVALID,
+ M68K_CPU_TYPE_68000,
+ M68K_CPU_TYPE_68008,
+ M68K_CPU_TYPE_68010,
+ M68K_CPU_TYPE_68EC020,
+ M68K_CPU_TYPE_68020,
+ M68K_CPU_TYPE_68EC030,
+ M68K_CPU_TYPE_68030,
+ M68K_CPU_TYPE_68EC040,
+ M68K_CPU_TYPE_68LC040,
+ M68K_CPU_TYPE_68040,
+ M68K_CPU_TYPE_SCC68070
+};
+
+// function codes
+enum
+{
+ M68K_FC_USER_DATA = 1,
+ M68K_FC_USER_PROGRAM = 2,
+ M68K_FC_SUPERVISOR_DATA = 5,
+ M68K_FC_SUPERVISOR_PROGRAM = 6,
+ M68K_FC_INTERRUPT = 7
+};
+
+/* HMMU enable types for use with m68k_set_hmmu_enable() */
+#define M68K_HMMU_DISABLE 0 /* no translation */
+#define M68K_HMMU_ENABLE_II 1 /* Mac II style fixed translation */
+#define M68K_HMMU_ENABLE_LC 2 /* Mac LC style fixed translation */
+
+/* Special interrupt acknowledge values.
+ * Use these as special returns from the interrupt acknowledge callback
+ * (specified later in this header).
+ */
+
+/* Causes an interrupt autovector (0x18 + interrupt level) to be taken.
+ * This happens in a real 68K if VPA or AVEC is asserted during an interrupt
+ * acknowledge cycle instead of DTACK.
+ */
+#define M68K_INT_ACK_AUTOVECTOR 0xffffffff
+
+/* Causes the spurious interrupt vector (0x18) to be taken
+ * This happens in a real 68K if BERR is asserted during the interrupt
+ * acknowledge cycle (i.e. no devices responded to the acknowledge).
+ */
+#define M68K_INT_ACK_SPURIOUS 0xfffffffe
+
+enum
+{
+ /* NOTE: M68K_SP fetches the current SP, be it USP, ISP, or MSP */
+ M68K_PC, M68K_SP, M68K_ISP, M68K_USP, M68K_MSP, M68K_SR, M68K_VBR,
+ M68K_SFC, M68K_DFC, M68K_CACR, M68K_CAAR, M68K_PREF_ADDR, M68K_PREF_DATA,
+ M68K_D0, M68K_D1, M68K_D2, M68K_D3, M68K_D4, M68K_D5, M68K_D6, M68K_D7,
+ M68K_A0, M68K_A1, M68K_A2, M68K_A3, M68K_A4, M68K_A5, M68K_A6, M68K_A7,
+ M68K_FP0, M68K_FP1, M68K_FP2, M68K_FP3, M68K_FP4, M68K_FP5, M68K_FP6, M68K_FP7,
+ M68K_FPSR, M68K_FPCR,
+
+ M68K_GENPC = STATE_GENPC,
+ M68K_GENSP = STATE_GENSP,
+ M68K_GENPCBASE = STATE_GENPCBASE
+};
+
+typedef void (*m68k_bkpt_ack_func)(device_t *device, UINT32 data);
+typedef void (*m68k_reset_func)(device_t *device);
+typedef void (*m68k_cmpild_func)(device_t *device, UINT32 data, UINT8 reg);
+typedef void (*m68k_rte_func)(device_t *device);
+typedef int (*m68k_tas_func)(device_t *device);
+
+
+DECLARE_LEGACY_CPU_DEVICE(M68000, m68000);
+DECLARE_LEGACY_CPU_DEVICE(M68008, m68008);
+DECLARE_LEGACY_CPU_DEVICE(M68010, m68010);
+DECLARE_LEGACY_CPU_DEVICE(M68EC020, m68ec020);
+DECLARE_LEGACY_CPU_DEVICE(M68020, m68020);
+DECLARE_LEGACY_CPU_DEVICE(M68020PMMU, m68020pmmu);
+DECLARE_LEGACY_CPU_DEVICE(M68020HMMU, m68020hmmu);
+DECLARE_LEGACY_CPU_DEVICE(M68EC030, m68ec030);
+DECLARE_LEGACY_CPU_DEVICE(M68030, m68030);
+DECLARE_LEGACY_CPU_DEVICE(M68EC040, m68ec040);
+DECLARE_LEGACY_CPU_DEVICE(M68LC040, m68lc040);
+DECLARE_LEGACY_CPU_DEVICE(M68040, m68040);
+DECLARE_LEGACY_CPU_DEVICE(SCC68070, scc68070);
+
+
+void m68k_set_encrypted_opcode_range(device_t *device, offs_t start, offs_t end);
+
+void m68k_set_hmmu_enable(device_t *device, int enable);
+
+unsigned int m68k_disassemble_raw(char* str_buff, unsigned int pc, const unsigned char* opdata, const unsigned char* argdata, unsigned int cpu_type);
+
+void m68k_set_reset_callback(device_t *device, m68k_reset_func callback);
+void m68k_set_cmpild_callback(device_t *device, m68k_cmpild_func callback);
+void m68k_set_rte_callback(device_t *device, m68k_rte_func callback);
+void m68k_set_tas_callback(device_t *device, m68k_tas_func callback);
+UINT16 m68k_get_fc(device_t *device);
+
+#endif /* __M68000_H__ */
diff --git a/trunk/src/emu/cpu/m68000/m68k_in.c b/trunk/src/emu/cpu/m68000/m68k_in.c
new file mode 100644
index 00000000000..ec74f6037de
--- /dev/null
+++ b/trunk/src/emu/cpu/m68000/m68k_in.c
@@ -0,0 +1,10231 @@
+/*
+must fix:
+ callm
+ chk
+*/
+/* ======================================================================== */
+/* ========================= LICENSING & COPYRIGHT ======================== */
+/* ======================================================================== */
+/*
+ * MUSASHI
+ * Version 3.32
+ *
+ * A portable Motorola M680x0 processor emulation engine.
+ * Copyright Karl Stenerud. All rights reserved.
+ *
+ * This code may be freely used for non-commercial purposes as long as this
+ * copyright notice remains unaltered in the source code and any binary files
+ * containing this code in compiled form.
+ *
+ * All other licensing terms must be negotiated with the author
+ * (Karl Stenerud).
+ *
+ * The latest version of this code can be obtained at:
+ * http://kstenerud.cjb.net
+ */
+
+/* Special thanks to Bart Trzynadlowski for his insight into the
+ * undocumented features of this chip:
+ *
+ * http://dynarec.com/~bart/files/68knotes.txt
+ */
+
+
+/* Input file for m68kmake
+ * -----------------------
+ *
+ * All sections begin with 80 X's in a row followed by an end-of-line
+ * sequence.
+ * After this, m68kmake will expect to find one of the following section
+ * identifiers:
+ * M68KMAKE_PROTOTYPE_HEADER - header for opcode handler prototypes
+ * M68KMAKE_PROTOTYPE_FOOTER - footer for opcode handler prototypes
+ * M68KMAKE_TABLE_HEADER - header for opcode handler jumptable
+ * M68KMAKE_TABLE_FOOTER - footer for opcode handler jumptable
+ * M68KMAKE_TABLE_BODY - the table itself
+ * M68KMAKE_OPCODE_HANDLER_HEADER - header for opcode handler implementation
+ * M68KMAKE_OPCODE_HANDLER_FOOTER - footer for opcode handler implementation
+ * M68KMAKE_OPCODE_HANDLER_BODY - body section for opcode handler implementation
+ *
+ * NOTE: M68KMAKE_OPCODE_HANDLER_BODY must be last in the file and
+ * M68KMAKE_TABLE_BODY must be second last in the file.
+ *
+ * The M68KMAKE_OPHANDLER_BODY section contains the opcode handler
+ * primitives themselves. Each opcode handler begins with:
+ * M68KMAKE_OP(A, B, C, D)
+ *
+ * where A is the opcode handler name, B is the size of the operation,
+ * C denotes any special processing mode, and D denotes a specific
+ * addressing mode.
+ * For C and D where nothing is specified, use "."
+ *
+ * Example:
+ * M68KMAKE_OP(abcd, 8, rr, .) abcd, size 8, register to register, default EA
+ * M68KMAKE_OP(abcd, 8, mm, ax7) abcd, size 8, memory to memory, register X is A7
+ * M68KMAKE_OP(tst, 16, ., pcix) tst, size 16, PCIX addressing
+ *
+ * All opcode handler primitives end with a closing curly brace "}" at column 1
+ *
+ * NOTE: Do not place a M68KMAKE_OP() directive inside the opcode handler,
+ * and do not put a closing curly brace at column 1 unless it is
+ * marking the end of the handler!
+ *
+ * Inside the handler, m68kmake will recognize M68KMAKE_GET_OPER_xx_xx,
+ * M68KMAKE_GET_EA_xx_xx, and M68KMAKE_CC directives, and create multiple
+ * opcode handlers to handle variations in the opcode handler.
+ * Note: M68KMAKE_CC will only be interpreted in condition code opcodes.
+ * As well, M68KMAKE_GET_EA_xx_xx and M68KMAKE_GET_OPER_xx_xx will only
+ * be interpreted on instructions where the corresponding table entry
+ * specifies multiple effective addressing modes.
+ * Example:
+ * clr 32 . . 0100001010...... A+-DXWL... U U U 12 6 4
+ *
+ * This table entry says that the clr.l opcde has 7 variations (A+-DXWL).
+ * It is run in user or supervisor mode for all CPUs, and uses 12 cycles for
+ * 68000, 6 cycles for 68010, and 4 cycles for 68020.
+ */
+
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+M68KMAKE_PROTOTYPE_HEADER
+
+#ifndef M68KOPS__HEADER
+#define M68KOPS__HEADER
+
+/* ======================================================================== */
+/* ============================ OPCODE HANDLERS =========================== */
+/* ======================================================================== */
+
+
+
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+M68KMAKE_PROTOTYPE_FOOTER
+
+
+/* Build the opcode handler table */
+void m68ki_build_opcode_table(void);
+
+extern void (*m68ki_instruction_jump_table[][0x10000])(m68ki_cpu_core *m68k); /* opcode handler jump table */
+extern unsigned char m68ki_cycles[][0x10000];
+
+
+/* ======================================================================== */
+/* ============================== END OF FILE ============================= */
+/* ======================================================================== */
+
+#endif /* M68KOPS__HEADER */
+
+
+
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+M68KMAKE_TABLE_HEADER
+
+/* ======================================================================== */
+/* ========================= OPCODE TABLE BUILDER ========================= */
+/* ======================================================================== */
+
+#include "m68kops.h"
+
+#define NUM_CPU_TYPES 5
+
+void (*m68ki_instruction_jump_table[NUM_CPU_TYPES][0x10000])(m68ki_cpu_core *m68k); /* opcode handler jump table */
+unsigned char m68ki_cycles[NUM_CPU_TYPES][0x10000]; /* Cycles used by CPU type */
+
+/* This is used to generate the opcode handler jump table */
+typedef struct
+{
+ void (*opcode_handler)(m68ki_cpu_core *m68k); /* handler function */
+ unsigned int mask; /* mask on opcode */
+ unsigned int match; /* what to match after masking */
+ unsigned char cycles[NUM_CPU_TYPES]; /* cycles each cpu type takes */
+} opcode_handler_struct;
+
+
+/* Opcode handler table */
+static const opcode_handler_struct m68k_opcode_handler_table[] =
+{
+/* function mask match 000 010 020 040 */
+
+
+
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+M68KMAKE_TABLE_FOOTER
+
+ {0, 0, 0, {0, 0, 0, 0, 0}}
+};
+
+
+/* Build the opcode handler jump table */
+
+static void m68ki_set_one(unsigned short opcode, const opcode_handler_struct *s)
+{
+ for(int i=0; i<NUM_CPU_TYPES; i++)
+ if(s->cycles[i] != 0xff) {
+ m68ki_cycles[i][opcode] = s->cycles[i];
+ m68ki_instruction_jump_table[i][opcode] = s->opcode_handler;
+ }
+}
+
+void m68ki_build_opcode_table(void)
+{
+ const opcode_handler_struct *ostruct;
+ int i;
+ int j;
+ int k;
+
+ for(i = 0; i < 0x10000; i++)
+ {
+ /* default to illegal */
+ for(k=0;k<NUM_CPU_TYPES;k++)
+ {
+ m68ki_instruction_jump_table[k][i] = m68k_op_illegal;
+ m68ki_cycles[k][i] = 0;
+ }
+ }
+
+ ostruct = m68k_opcode_handler_table;
+ while(ostruct->mask != 0xff00)
+ {
+ for(i = 0;i < 0x10000;i++)
+ {
+ if((i & ostruct->mask) == ostruct->match)
+ m68ki_set_one(i, ostruct);
+ }
+ ostruct++;
+ }
+ while(ostruct->mask == 0xff00)
+ {
+ for(i = 0;i <= 0xff;i++)
+ m68ki_set_one(ostruct->match | i, ostruct);
+ ostruct++;
+ }
+ while(ostruct->mask == 0xf1f8)
+ {
+ for(i = 0;i < 8;i++)
+ {
+ for(j = 0;j < 8;j++)
+ m68ki_set_one(ostruct->match | (i << 9) | j, ostruct);
+ }
+ ostruct++;
+ }
+ while(ostruct->mask == 0xfff0)
+ {
+ for(i = 0;i <= 0x0f;i++)
+ m68ki_set_one(ostruct->match | i, ostruct);
+ ostruct++;
+ }
+ while(ostruct->mask == 0xf1ff)
+ {
+ for(i = 0;i <= 0x07;i++)
+ m68ki_set_one(ostruct->match | (i << 9), ostruct);
+ ostruct++;
+ }
+ while(ostruct->mask == 0xfff8)
+ {
+ for(i = 0;i <= 0x07;i++)
+ m68ki_set_one(ostruct->match | i, ostruct);
+ ostruct++;
+ }
+ while(ostruct->mask == 0xffff)
+ {
+ m68ki_set_one(ostruct->match, ostruct);
+ ostruct++;
+ }
+}
+
+
+/* ======================================================================== */
+/* ============================== END OF FILE ============================= */
+/* ======================================================================== */
+
+
+
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+M68KMAKE_OPCODE_HANDLER_HEADER
+
+#include "emu.h"
+#include "m68kcpu.h"
+extern void m68040_fpu_op0(m68ki_cpu_core *m68k);
+extern void m68040_fpu_op1(m68ki_cpu_core *m68k);
+extern void m68881_mmu_ops(m68ki_cpu_core *m68k);
+
+/* ======================================================================== */
+/* ========================= INSTRUCTION HANDLERS ========================= */
+/* ======================================================================== */
+
+
+
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+M68KMAKE_OPCODE_HANDLER_FOOTER
+
+/* ======================================================================== */
+/* ============================== END OF FILE ============================= */
+/* ======================================================================== */
+
+
+
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+M68KMAKE_TABLE_BODY
+/*
+The following table is arranged as follows:
+
+name: Opcode mnemonic
+
+size: Operation size
+
+spec proc: Special processing mode:
+ .: normal
+ s: static operand
+ r: register operand
+ rr: register to register
+ mm: memory to memory
+ er: effective address to register
+ re: register to effective address
+ dd: data register to data register
+ da: data register to address register
+ aa: address register to address register
+ cr: control register to register
+ rc: register to control register
+ toc: to condition code register
+ tos: to status register
+ tou: to user stack pointer
+ frc: from condition code register
+ frs: from status register
+ fru: from user stack pointer
+ * for move.x, the special processing mode is a specific
+ destination effective addressing mode.
+
+spec ea: Specific effective addressing mode:
+ .: normal
+ i: immediate
+ d: data register
+ a: address register
+ ai: address register indirect
+ pi: address register indirect with postincrement
+ pd: address register indirect with predecrement
+ di: address register indirect with displacement
+ ix: address register indirect with index
+ aw: absolute word address
+ al: absolute long address
+ pcdi: program counter relative with displacement
+ pcix: program counter relative with index
+ a7: register specified in instruction is A7
+ ax7: register field X of instruction is A7
+ ay7: register field Y of instruction is A7
+ axy7: register fields X and Y of instruction are A7
+
+bit pattern: Pattern to recognize this opcode. "." means don't care.
+
+allowed ea: List of allowed addressing modes:
+ .: not present
+ A: address register indirect
+ +: ARI (address register indirect) with postincrement
+ -: ARI with predecrement
+ D: ARI with displacement
+ X: ARI with index
+ W: absolute word address
+ L: absolute long address
+ d: program counter indirect with displacement
+ x: program counter indirect with index
+ I: immediate
+mode: CPU operating mode for each cpu type. U = user or supervisor,
+ S = supervisor only, "." = opcode not present.
+
+cpu cycles: Base number of cycles required to execute this opcode on the
+ specified CPU type.
+ Use "." if CPU does not have this opcode.
+*/
+
+
+ spec spec allowed ea mode cpu cycles
+name size proc ea bit pattern A+-DXWLdxI 0 1 2 3 4 000 010 020 030 040 comments
+====== ==== ==== ==== ================ ========== = = = = = === === === === === =============
+M68KMAKE_TABLE_START
+1010 0 . . 1010............ .......... U U U U U 4 4 4 4 4
+1111 0 . . 1111............ .......... U U U U U 4 4 4 4 4
+040fpu0 32 . . 11110010........ .......... . . . U U . . . 0 0
+040fpu1 32 . . 11110011........ .......... . . . U U . . . 0 0
+abcd 8 rr . 1100...100000... .......... U U U U U 6 6 4 4 4
+abcd 8 mm ax7 1100111100001... .......... U U U U U 18 18 16 16 16
+abcd 8 mm ay7 1100...100001111 .......... U U U U U 18 18 16 16 16
+abcd 8 mm axy7 1100111100001111 .......... U U U U U 18 18 16 16 16
+abcd 8 mm . 1100...100001... .......... U U U U U 18 18 16 16 16
+add 8 er d 1101...000000... .......... U U U U U 4 4 2 2 2
+add 8 er . 1101...000...... A+-DXWLdxI U U U U U 4 4 2 2 2
+add 16 er d 1101...001000... .......... U U U U U 4 4 2 2 2
+add 16 er a 1101...001001... .......... U U U U U 4 4 2 2 2
+add 16 er . 1101...001...... A+-DXWLdxI U U U U U 4 4 2 2 2
+add 32 er d 1101...010000... .......... U U U U U 6 6 2 2 2
+add 32 er a 1101...010001... .......... U U U U U 6 6 2 2 2
+add 32 er . 1101...010...... A+-DXWLdxI U U U U U 6 6 2 2 2
+add 8 re . 1101...100...... A+-DXWL... U U U U U 8 8 4 4 4
+add 16 re . 1101...101...... A+-DXWL... U U U U U 8 8 4 4 4
+add 32 re . 1101...110...... A+-DXWL... U U U U U 12 12 4 4 4
+adda 16 . d 1101...011000... .......... U U U U U 8 8 2 2 2
+adda 16 . a 1101...011001... .......... U U U U U 8 8 2 2 2
+adda 16 . . 1101...011...... A+-DXWLdxI U U U U U 8 8 2 2 2
+adda 32 . d 1101...111000... .......... U U U U U 6 6 2 2 2
+adda 32 . a 1101...111001... .......... U U U U U 6 6 2 2 2
+adda 32 . . 1101...111...... A+-DXWLdxI U U U U U 6 6 2 2 2
+addi 8 . d 0000011000000... .......... U U U U U 8 8 2 2 2
+addi 8 . . 0000011000...... A+-DXWL... U U U U U 12 12 4 4 4
+addi 16 . d 0000011001000... .......... U U U U U 8 8 2 2 2
+addi 16 . . 0000011001...... A+-DXWL... U U U U U 12 12 4 4 4
+addi 32 . d 0000011010000... .......... U U U U U 16 14 2 2 2
+addi 32 . . 0000011010...... A+-DXWL... U U U U U 20 20 4 4 4
+addq 8 . d 0101...000000... .......... U U U U U 4 4 2 2 2
+addq 8 . . 0101...000...... A+-DXWL... U U U U U 8 8 4 4 4
+addq 16 . d 0101...001000... .......... U U U U U 4 4 2 2 2
+addq 16 . a 0101...001001... .......... U U U U U 4 4 2 2 2
+addq 16 . . 0101...001...... A+-DXWL... U U U U U 8 8 4 4 4
+addq 32 . d 0101...010000... .......... U U U U U 8 8 2 2 2
+addq 32 . a 0101...010001... .......... U U U U U 8 8 2 2 2
+addq 32 . . 0101...010...... A+-DXWL... U U U U U 12 12 4 4 4
+addx 8 rr . 1101...100000... .......... U U U U U 4 4 2 2 2
+addx 16 rr . 1101...101000... .......... U U U U U 4 4 2 2 2
+addx 32 rr . 1101...110000... .......... U U U U U 8 6 2 2 2
+addx 8 mm ax7 1101111100001... .......... U U U U U 18 18 12 12 12
+addx 8 mm ay7 1101...100001111 .......... U U U U U 18 18 12 12 12
+addx 8 mm axy7 1101111100001111 .......... U U U U U 18 18 12 12 12
+addx 8 mm . 1101...100001... .......... U U U U U 18 18 12 12 12
+addx 16 mm . 1101...101001... .......... U U U U U 18 18 12 12 12
+addx 32 mm . 1101...110001... .......... U U U U U 30 30 12 12 12
+and 8 er d 1100...000000... .......... U U U U U 4 4 2 2 2
+and 8 er . 1100...000...... A+-DXWLdxI U U U U U 4 4 2 2 2
+and 16 er d 1100...001000... .......... U U U U U 4 4 2 2 2
+and 16 er . 1100...001...... A+-DXWLdxI U U U U U 4 4 2 2 2
+and 32 er d 1100...010000... .......... U U U U U 6 6 2 2 2
+and 32 er . 1100...010...... A+-DXWLdxI U U U U U 6 6 2 2 2
+and 8 re . 1100...100...... A+-DXWL... U U U U U 8 8 4 4 4
+and 16 re . 1100...101...... A+-DXWL... U U U U U 8 8 4 4 4
+and 32 re . 1100...110...... A+-DXWL... U U U U U 12 12 4 4 4
+andi 16 toc . 0000001000111100 .......... U U U U U 20 16 12 12 12
+andi 16 tos . 0000001001111100 .......... S S S S S 20 16 12 12 12
+andi 8 . d 0000001000000... .......... U U U U U 8 8 2 2 2
+andi 8 . . 0000001000...... A+-DXWL... U U U U U 12 12 4 4 4
+andi 16 . d 0000001001000... .......... U U U U U 8 8 2 2 2
+andi 16 . . 0000001001...... A+-DXWL... U U U U U 12 12 4 4 4
+andi 32 . d 0000001010000... .......... U U U U U 14 14 2 2 2
+andi 32 . . 0000001010...... A+-DXWL... U U U U U 20 20 4 4 4
+asr 8 s . 1110...000000... .......... U U U U U 6 6 6 6 6
+asr 16 s . 1110...001000... .......... U U U U U 6 6 6 6 6
+asr 32 s . 1110...010000... .......... U U U U U 8 8 6 6 6
+asr 8 r . 1110...000100... .......... U U U U U 6 6 6 6 6
+asr 16 r . 1110...001100... .......... U U U U U 6 6 6 6 6
+asr 32 r . 1110...010100... .......... U U U U U 8 8 6 6 6
+asr 16 . . 1110000011...... A+-DXWL... U U U U U 8 8 5 5 5
+asl 8 s . 1110...100000... .......... U U U U U 6 6 8 8 8
+asl 16 s . 1110...101000... .......... U U U U U 6 6 8 8 8
+asl 32 s . 1110...110000... .......... U U U U U 8 8 8 8 8
+asl 8 r . 1110...100100... .......... U U U U U 6 6 8 8 8
+asl 16 r . 1110...101100... .......... U U U U U 6 6 8 8 8
+asl 32 r . 1110...110100... .......... U U U U U 8 8 8 8 8
+asl 16 . . 1110000111...... A+-DXWL... U U U U U 8 8 6 6 6
+bcc 8 . . 0110............ .......... U U U U U 10 10 6 6 6
+bcc 16 . . 0110....00000000 .......... U U U U U 10 10 6 6 6
+bcc 32 . . 0110....11111111 .......... U U U U U 10 10 6 6 6
+bchg 8 r . 0000...101...... A+-DXWL... U U U U U 8 8 4 4 4
+bchg 32 r d 0000...101000... .......... U U U U U 8 8 4 4 4
+bchg 8 s . 0000100001...... A+-DXWL... U U U U U 12 12 4 4 4
+bchg 32 s d 0000100001000... .......... U U U U U 12 12 4 4 4
+bclr 8 r . 0000...110...... A+-DXWL... U U U U U 8 10 4 4 4
+bclr 32 r d 0000...110000... .......... U U U U U 10 10 4 4 4
+bclr 8 s . 0000100010...... A+-DXWL... U U U U U 12 12 4 4 4
+bclr 32 s d 0000100010000... .......... U U U U U 14 14 4 4 4
+bfchg 32 . d 1110101011000... .......... . . U U U . . 12 12 12 timing not quite correct
+bfchg 32 . . 1110101011...... A..DXWL... . . U U U . . 20 20 20
+bfclr 32 . d 1110110011000... .......... . . U U U . . 12 12 12
+bfclr 32 . . 1110110011...... A..DXWL... . . U U U . . 20 20 20
+bfexts 32 . d 1110101111000... .......... . . U U U . . 8 8 8
+bfexts 32 . . 1110101111...... A..DXWLdx. . . U U U . . 15 15 15
+bfextu 32 . d 1110100111000... .......... . . U U U . . 8 8 8
+bfextu 32 . . 1110100111...... A..DXWLdx. . . U U U . . 15 15 15
+bfffo 32 . d 1110110111000... .......... . . U U U . . 18 18 18
+bfffo 32 . . 1110110111...... A..DXWLdx. . . U U U . . 28 28 28
+bfins 32 . d 1110111111000... .......... . . U U U . . 10 10 10
+bfins 32 . . 1110111111...... A..DXWL... . . U U U . . 17 17 17
+bfset 32 . d 1110111011000... .......... . . U U U . . 12 12 12
+bfset 32 . . 1110111011...... A..DXWL... . . U U U . . 20 20 20
+bftst 32 . d 1110100011000... .......... . . U U U . . 6 6 6
+bftst 32 . . 1110100011...... A..DXWLdx. . . U U U . . 13 13 13
+bkpt 0 . . 0100100001001... .......... . U U U U . 10 10 10 10
+bra 8 . . 01100000........ .......... U U U U U 10 10 10 10 10
+bra 16 . . 0110000000000000 .......... U U U U U 10 10 10 10 10
+bra 32 . . 0110000011111111 .......... U U U U U 10 10 10 10 10
+bset 32 r d 0000...111000... .......... U U U U U 8 8 4 4 4
+bset 8 r . 0000...111...... A+-DXWL... U U U U U 8 8 4 4 4
+bset 8 s . 0000100011...... A+-DXWL... U U U U U 12 12 4 4 4
+bset 32 s d 0000100011000... .......... U U U U U 12 12 4 4 4
+bsr 8 . . 01100001........ .......... U U U U U 18 18 7 7 7
+bsr 16 . . 0110000100000000 .......... U U U U U 18 18 7 7 7
+bsr 32 . . 0110000111111111 .......... U U U U U 18 18 7 7 7
+btst 8 r . 0000...100...... A+-DXWLdxI U U U U U 4 4 4 4 4
+btst 32 r d 0000...100000... .......... U U U U U 6 6 4 4 4
+btst 8 s . 0000100000...... A+-DXWLdx. U U U U U 8 8 4 4 4
+btst 32 s d 0000100000000... .......... U U U U U 10 10 4 4 4
+callm 32 . . 0000011011...... A..DXWLdx. . . U U U . . 60 60 60 not properly emulated
+cas 8 . . 0000101011...... A+-DXWL... . . U U U . . 12 12 12
+cas 16 . . 0000110011...... A+-DXWL... . . U U U . . 12 12 12
+cas 32 . . 0000111011...... A+-DXWL... . . U U U . . 12 12 12
+cas2 16 . . 0000110011111100 .......... . . U U U . . 12 12 12
+cas2 32 . . 0000111011111100 .......... . . U U U . . 12 12 12
+chk 16 . d 0100...110000... .......... U U U U U 10 8 8 8 8
+chk 16 . . 0100...110...... A+-DXWLdxI U U U U U 10 8 8 8 8
+chk 32 . d 0100...100000... .......... . . U U U . . 8 8 8
+chk 32 . . 0100...100...... A+-DXWLdxI . . U U U . . 8 8 8
+chk2cmp2 8 . pcdi 0000000011111010 .......... . . U U U . . 23 23 23
+chk2cmp2 8 . pcix 0000000011111011 .......... . . U U U . . 23 23 23
+chk2cmp2 8 . . 0000000011...... A..DXWL... . . U U U . . 18 18 18
+chk2cmp2 16 . pcdi 0000001011111010 .......... . . U U U . . 23 23 23
+chk2cmp2 16 . pcix 0000001011111011 .......... . . U U U . . 23 23 23
+chk2cmp2 16 . . 0000001011...... A..DXWL... . . U U U . . 18 18 18
+chk2cmp2 32 . pcdi 0000010011111010 .......... . . U U U . . 23 23 23
+chk2cmp2 32 . pcix 0000010011111011 .......... . . U U U . . 23 23 23
+chk2cmp2 32 . . 0000010011...... A..DXWL... . . U U U . . 18 18 18
+clr 8 . d 0100001000000... .......... U U U U U 4 4 2 2 2
+clr 8 . . 0100001000...... A+-DXWL... U U U U U 8 4 4 4 4
+clr 16 . d 0100001001000... .......... U U U U U 4 4 2 2 2
+clr 16 . . 0100001001...... A+-DXWL... U U U U U 8 4 4 4 4
+clr 32 . d 0100001010000... .......... U U U U U 6 6 2 2 2
+clr 32 . . 0100001010...... A+-DXWL... U U U U U 12 6 4 4 4
+cmp 8 . d 1011...000000... .......... U U U U U 4 4 2 2 2
+cmp 8 . . 1011...000...... A+-DXWLdxI U U U U U 4 4 2 2 2
+cmp 16 . d 1011...001000... .......... U U U U U 4 4 2 2 2
+cmp 16 . a 1011...001001... .......... U U U U U 4 4 2 2 2
+cmp 16 . . 1011...001...... A+-DXWLdxI U U U U U 4 4 2 2 2
+cmp 32 . d 1011...010000... .......... U U U U U 6 6 2 2 2
+cmp 32 . a 1011...010001... .......... U U U U U 6 6 2 2 2
+cmp 32 . . 1011...010...... A+-DXWLdxI U U U U U 6 6 2 2 2
+cmpa 16 . d 1011...011000... .......... U U U U U 6 6 4 4 4
+cmpa 16 . a 1011...011001... .......... U U U U U 6 6 4 4 4
+cmpa 16 . . 1011...011...... A+-DXWLdxI U U U U U 6 6 4 4 4
+cmpa 32 . d 1011...111000... .......... U U U U U 6 6 4 4 4
+cmpa 32 . a 1011...111001... .......... U U U U U 6 6 4 4 4
+cmpa 32 . . 1011...111...... A+-DXWLdxI U U U U U 6 6 4 4 4
+cmpi 8 . d 0000110000000... .......... U U U U U 8 8 2 2 2
+cmpi 8 . . 0000110000...... A+-DXWL... U U U U U 8 8 2 2 2
+cmpi 8 . pcdi 0000110000111010 .......... . . U U U . . 7 7 7
+cmpi 8 . pcix 0000110000111011 .......... . . U U U . . 9 9 9
+cmpi 16 . d 0000110001000... .......... U U U U U 8 8 2 2 2
+cmpi 16 . . 0000110001...... A+-DXWL... U U U U U 8 8 2 2 2
+cmpi 16 . pcdi 0000110001111010 .......... . . U U U . . 7 7 7
+cmpi 16 . pcix 0000110001111011 .......... . . U U U . . 9 9 9
+cmpi 32 . d 0000110010000... .......... U U U U U 14 12 2 2 2
+cmpi 32 . . 0000110010...... A+-DXWL... U U U U U 12 12 2 2 2
+cmpi 32 . pcdi 0000110010111010 .......... . . U U U . . 7 7 7
+cmpi 32 . pcix 0000110010111011 .......... . . U U U . . 9 9 9
+cmpm 8 . ax7 1011111100001... .......... U U U U U 12 12 9 9 9
+cmpm 8 . ay7 1011...100001111 .......... U U U U U 12 12 9 9 9
+cmpm 8 . axy7 1011111100001111 .......... U U U U U 12 12 9 9 9
+cmpm 8 . . 1011...100001... .......... U U U U U 12 12 9 9 9
+cmpm 16 . . 1011...101001... .......... U U U U U 12 12 9 9 9
+cmpm 32 . . 1011...110001... .......... U U U U U 20 20 9 9 9
+cpbcc 32 . . 1111...01....... .......... . . U U U . . 4 4 4 unemulated
+cpdbcc 32 . . 1111...001001... .......... . . U U U . . 4 4 4 unemulated
+cpgen 32 . . 1111...000...... .......... . . U U U . . 4 4 4 unemulated
+cpscc 32 . . 1111...001...... .......... . . U U U . . 4 4 4 unemulated
+cptrapcc 32 . . 1111...001111... .......... . . U U U . . 4 4 4 unemulated
+dbt 16 . . 0101000011001... .......... U U U U U 12 12 6 6 6
+dbf 16 . . 0101000111001... .......... U U U U U 12 12 6 6 6
+dbcc 16 . . 0101....11001... .......... U U U U U 12 12 6 6 6
+divs 16 . d 1000...111000... .......... U U U U U 158 122 56 56 56
+divs 16 . . 1000...111...... A+-DXWLdxI U U U U U 158 122 56 56 56
+divu 16 . d 1000...011000... .......... U U U U U 140 108 44 44 44
+divu 16 . . 1000...011...... A+-DXWLdxI U U U U U 140 108 44 44 44
+divl 32 . d 0100110001000... .......... . . U U U . . 84 84 84
+divl 32 . . 0100110001...... A+-DXWLdxI . . U U U . . 84 84 84
+eor 8 . d 1011...100000... .......... U U U U U 4 4 2 2 2
+eor 8 . . 1011...100...... A+-DXWL... U U U U U 8 8 4 4 4
+eor 16 . d 1011...101000... .......... U U U U U 4 4 2 2 2
+eor 16 . . 1011...101...... A+-DXWL... U U U U U 8 8 4 4 4
+eor 32 . d 1011...110000... .......... U U U U U 8 6 2 2 2
+eor 32 . . 1011...110...... A+-DXWL... U U U U U 12 12 4 4 4
+eori 16 toc . 0000101000111100 .......... U U U U U 20 16 12 12 12
+eori 16 tos . 0000101001111100 .......... S S S S S 20 16 12 12 12
+eori 8 . d 0000101000000... .......... U U U U U 8 8 2 2 2
+eori 8 . . 0000101000...... A+-DXWL... U U U U U 12 12 4 4 4
+eori 16 . d 0000101001000... .......... U U U U U 8 8 2 2 2
+eori 16 . . 0000101001...... A+-DXWL... U U U U U 12 12 4 4 4
+eori 32 . d 0000101010000... .......... U U U U U 16 14 2 2 2
+eori 32 . . 0000101010...... A+-DXWL... U U U U U 20 20 4 4 4
+exg 32 dd . 1100...101000... .......... U U U U U 6 6 2 2 2
+exg 32 aa . 1100...101001... .......... U U U U U 6 6 2 2 2
+exg 32 da . 1100...110001... .......... U U U U U 6 6 2 2 2
+ext 16 . . 0100100010000... .......... U U U U U 4 4 4 4 4
+ext 32 . . 0100100011000... .......... U U U U U 4 4 4 4 4
+extb 32 . . 0100100111000... .......... . . U U U . . 4 4 4
+illegal 0 . . 0100101011111100 .......... U U U U U 4 4 4 4 4
+jmp 32 . . 0100111011...... A..DXWLdx. U U U U U 4 4 0 0 0
+jsr 32 . . 0100111010...... A..DXWLdx. U U U U U 12 12 0 0 0
+lea 32 . . 0100...111...... A..DXWLdx. U U U U U 0 0 2 2 2
+link 16 . a7 0100111001010111 .......... U U U U U 16 16 5 5 5
+link 16 . . 0100111001010... .......... U U U U U 16 16 5 5 5
+link 32 . a7 0100100000001111 .......... . . U U U . . 6 6 6
+link 32 . . 0100100000001... .......... . . U U U . . 6 6 6
+lsr 8 s . 1110...000001... .......... U U U U U 6 6 4 4 4
+lsr 16 s . 1110...001001... .......... U U U U U 6 6 4 4 4
+lsr 32 s . 1110...010001... .......... U U U U U 8 8 4 4 4
+lsr 8 r . 1110...000101... .......... U U U U U 6 6 6 6 6
+lsr 16 r . 1110...001101... .......... U U U U U 6 6 6 6 6
+lsr 32 r . 1110...010101... .......... U U U U U 8 8 6 6 6
+lsr 16 . . 1110001011...... A+-DXWL... U U U U U 8 8 5 5 5
+lsl 8 s . 1110...100001... .......... U U U U U 6 6 4 4 4
+lsl 16 s . 1110...101001... .......... U U U U U 6 6 4 4 4
+lsl 32 s . 1110...110001... .......... U U U U U 8 8 4 4 4
+lsl 8 r . 1110...100101... .......... U U U U U 6 6 6 6 6
+lsl 16 r . 1110...101101... .......... U U U U U 6 6 6 6 6
+lsl 32 r . 1110...110101... .......... U U U U U 8 8 6 6 6
+lsl 16 . . 1110001111...... A+-DXWL... U U U U U 8 8 5 5 5
+move 8 d d 0001...000000... .......... U U U U U 4 4 2 2 2
+move 8 d . 0001...000...... A+-DXWLdxI U U U U U 4 4 2 2 2
+move 8 ai d 0001...010000... .......... U U U U U 8 8 4 4 4
+move 8 ai . 0001...010...... A+-DXWLdxI U U U U U 8 8 4 4 4
+move 8 pi d 0001...011000... .......... U U U U U 8 8 4 4 4
+move 8 pi . 0001...011...... A+-DXWLdxI U U U U U 8 8 4 4 4
+move 8 pi7 d 0001111011000... .......... U U U U U 8 8 4 4 4
+move 8 pi7 . 0001111011...... A+-DXWLdxI U U U U U 8 8 4 4 4
+move 8 pd d 0001...100000... .......... U U U U U 8 8 5 5 5
+move 8 pd . 0001...100...... A+-DXWLdxI U U U U U 8 8 5 5 5
+move 8 pd7 d 0001111100000... .......... U U U U U 8 8 5 5 5
+move 8 pd7 . 0001111100...... A+-DXWLdxI U U U U U 8 8 5 5 5
+move 8 di d 0001...101000... .......... U U U U U 12 12 5 5 5
+move 8 di . 0001...101...... A+-DXWLdxI U U U U U 12 12 5 5 5
+move 8 ix d 0001...110000... .......... U U U U U 14 14 7 7 7
+move 8 ix . 0001...110...... A+-DXWLdxI U U U U U 14 14 7 7 7
+move 8 aw d 0001000111000... .......... U U U U U 12 12 4 4 4
+move 8 aw . 0001000111...... A+-DXWLdxI U U U U U 12 12 4 4 4
+move 8 al d 0001001111000... .......... U U U U U 16 16 6 6 6
+move 8 al . 0001001111...... A+-DXWLdxI U U U U U 16 16 6 6 6
+move 16 d d 0011...000000... .......... U U U U U 4 4 2 2 2
+move 16 d a 0011...000001... .......... U U U U U 4 4 2 2 2
+move 16 d . 0011...000...... A+-DXWLdxI U U U U U 4 4 2 2 2
+move 16 ai d 0011...010000... .......... U U U U U 8 8 4 4 4
+move 16 ai a 0011...010001... .......... U U U U U 8 8 4 4 4
+move 16 ai . 0011...010...... A+-DXWLdxI U U U U U 8 8 4 4 4
+move 16 pi d 0011...011000... .......... U U U U U 8 8 4 4 4
+move 16 pi a 0011...011001... .......... U U U U U 8 8 4 4 4
+move 16 pi . 0011...011...... A+-DXWLdxI U U U U U 8 8 4 4 4
+move 16 pd d 0011...100000... .......... U U U U U 8 8 5 5 5
+move 16 pd a 0011...100001... .......... U U U U U 8 8 5 5 5
+move 16 pd . 0011...100...... A+-DXWLdxI U U U U U 8 8 5 5 5
+move 16 di d 0011...101000... .......... U U U U U 12 12 5 5 5
+move 16 di a 0011...101001... .......... U U U U U 12 12 5 5 5
+move 16 di . 0011...101...... A+-DXWLdxI U U U U U 12 12 5 5 5
+move 16 ix d 0011...110000... .......... U U U U U 14 14 7 7 7
+move 16 ix a 0011...110001... .......... U U U U U 14 14 7 7 7
+move 16 ix . 0011...110...... A+-DXWLdxI U U U U U 14 14 7 7 7
+move 16 aw d 0011000111000... .......... U U U U U 12 12 4 4 4
+move 16 aw a 0011000111001... .......... U U U U U 12 12 4 4 4
+move 16 aw . 0011000111...... A+-DXWLdxI U U U U U 12 12 4 4 4
+move 16 al d 0011001111000... .......... U U U U U 16 16 6 6 6
+move 16 al a 0011001111001... .......... U U U U U 16 16 6 6 6
+move 16 al . 0011001111...... A+-DXWLdxI U U U U U 16 16 6 6 6
+move 32 d d 0010...000000... .......... U U U U U 4 4 2 2 2
+move 32 d a 0010...000001... .......... U U U U U 4 4 2 2 2
+move 32 d . 0010...000...... A+-DXWLdxI U U U U U 4 4 2 2 2
+move 32 ai d 0010...010000... .......... U U U U U 12 12 4 4 4
+move 32 ai a 0010...010001... .......... U U U U U 12 12 4 4 4
+move 32 ai . 0010...010...... A+-DXWLdxI U U U U U 12 12 4 4 4
+move 32 pi d 0010...011000... .......... U U U U U 12 12 4 4 4
+move 32 pi a 0010...011001... .......... U U U U U 12 12 4 4 4
+move 32 pi . 0010...011...... A+-DXWLdxI U U U U U 12 12 4 4 4
+move 32 pd d 0010...100000... .......... U U U U U 12 14 5 5 5
+move 32 pd a 0010...100001... .......... U U U U U 12 14 5 5 5
+move 32 pd . 0010...100...... A+-DXWLdxI U U U U U 12 14 5 5 5
+move 32 di d 0010...101000... .......... U U U U U 16 16 5 5 5
+move 32 di a 0010...101001... .......... U U U U U 16 16 5 5 5
+move 32 di . 0010...101...... A+-DXWLdxI U U U U U 16 16 5 5 5
+move 32 ix d 0010...110000... .......... U U U U U 18 18 7 7 7
+move 32 ix a 0010...110001... .......... U U U U U 18 18 7 7 7
+move 32 ix . 0010...110...... A+-DXWLdxI U U U U U 18 18 7 7 7
+move 32 aw d 0010000111000... .......... U U U U U 16 16 4 4 4
+move 32 aw a 0010000111001... .......... U U U U U 16 16 4 4 4
+move 32 aw . 0010000111...... A+-DXWLdxI U U U U U 16 16 4 4 4
+move 32 al d 0010001111000... .......... U U U U U 20 20 6 6 6
+move 32 al a 0010001111001... .......... U U U U U 20 20 6 6 6
+move 32 al . 0010001111...... A+-DXWLdxI U U U U U 20 20 6 6 6
+movea 16 . d 0011...001000... .......... U U U U U 4 4 2 2 2
+movea 16 . a 0011...001001... .......... U U U U U 4 4 2 2 2
+movea 16 . . 0011...001...... A+-DXWLdxI U U U U U 4 4 2 2 2
+movea 32 . d 0010...001000... .......... U U U U U 4 4 2 2 2
+movea 32 . a 0010...001001... .......... U U U U U 4 4 2 2 2
+movea 32 . . 0010...001...... A+-DXWLdxI U U U U U 4 4 2 2 2
+move 16 frc d 0100001011000... .......... . U U U U . 4 4 4 4
+move 16 frc . 0100001011...... A+-DXWL... . U U U U . 8 4 4 4
+move 16 toc d 0100010011000... .......... U U U U U 12 12 4 4 4
+move 16 toc . 0100010011...... A+-DXWLdxI U U U U U 12 12 4 4 4
+move 16 frs d 0100000011000... .......... U S S S S 6 4 8 8 8 U only for 000
+move 16 frs . 0100000011...... A+-DXWL... U S S S S 8 8 8 8 8 U only for 000
+move 16 tos d 0100011011000... .......... S S S S S 12 12 8 8 8
+move 16 tos . 0100011011...... A+-DXWLdxI S S S S S 12 12 8 8 8
+move 32 fru . 0100111001101... .......... S S S S S 4 6 2 2 2
+move 32 tou . 0100111001100... .......... S S S S S 4 6 2 2 2
+movec 32 cr . 0100111001111010 .......... . S S S S . 12 6 6 6
+movec 32 rc . 0100111001111011 .......... . S S S S . 10 12 12 12
+movem 16 re pd 0100100010100... .......... U U U U U 8 8 4 4 4
+movem 16 re . 0100100010...... A..DXWL... U U U U U 8 8 4 4 4
+movem 32 re pd 0100100011100... .......... U U U U U 8 8 4 4 4
+movem 32 re . 0100100011...... A..DXWL... U U U U U 8 8 4 4 4
+movem 16 er pi 0100110010011... .......... U U U U U 12 12 8 8 8
+movem 16 er pcdi 0100110010111010 .......... U U U U U 16 16 9 9 9
+movem 16 er pcix 0100110010111011 .......... U U U U U 18 18 11 11 11
+movem 16 er . 0100110010...... A..DXWL... U U U U U 12 12 8 8 8
+movem 32 er pi 0100110011011... .......... U U U U U 12 12 8 8 8
+movem 32 er pcdi 0100110011111010 .......... U U U U U 16 16 9 9 9
+movem 32 er pcix 0100110011111011 .......... U U U U U 18 18 11 11 11
+movem 32 er . 0100110011...... A..DXWL... U U U U U 12 12 8 8 8
+movep 16 er . 0000...100001... .......... U U U U U 16 16 12 12 12
+movep 32 er . 0000...101001... .......... U U U U U 24 24 18 18 18
+movep 16 re . 0000...110001... .......... U U U U U 16 16 11 11 11
+movep 32 re . 0000...111001... .......... U U U U U 24 24 17 17 17
+moveq 32 . . 0111...0........ .......... U U U U U 4 4 2 2 2
+moves 8 . . 0000111000...... A+-DXWL... . S S S S . 14 5 5 5
+moves 16 . . 0000111001...... A+-DXWL... . S S S S . 14 5 5 5
+moves 32 . . 0000111010...... A+-DXWL... . S S S S . 16 5 5 5
+move16 32 . . 1111011000100... .......... . . . . U . . . . 4 TODO: correct timing
+muls 16 . d 1100...111000... .......... U U U U U 54 32 27 27 27
+muls 16 . . 1100...111...... A+-DXWLdxI U U U U U 54 32 27 27 27
+mulu 16 . d 1100...011000... .......... U U U U U 54 30 27 27 27
+mulu 16 . . 1100...011...... A+-DXWLdxI U U U U U 54 30 27 27 27
+mull 32 . d 0100110000000... .......... . . U U U . . 43 43 43
+mull 32 . . 0100110000...... A+-DXWLdxI . . U U U . . 43 43 43
+nbcd 8 . d 0100100000000... .......... U U U U U 6 6 6 6 6
+nbcd 8 . . 0100100000...... A+-DXWL... U U U U U 8 8 6 6 6
+neg 8 . d 0100010000000... .......... U U U U U 4 4 2 2 2
+neg 8 . . 0100010000...... A+-DXWL... U U U U U 8 8 4 4 4
+neg 16 . d 0100010001000... .......... U U U U U 4 4 2 2 2
+neg 16 . . 0100010001...... A+-DXWL... U U U U U 8 8 4 4 4
+neg 32 . d 0100010010000... .......... U U U U U 6 6 2 2 2
+neg 32 . . 0100010010...... A+-DXWL... U U U U U 12 12 4 4 4
+negx 8 . d 0100000000000... .......... U U U U U 4 4 2 2 2
+negx 8 . . 0100000000...... A+-DXWL... U U U U U 8 8 4 4 4
+negx 16 . d 0100000001000... .......... U U U U U 4 4 2 2 2
+negx 16 . . 0100000001...... A+-DXWL... U U U U U 8 8 4 4 4
+negx 32 . d 0100000010000... .......... U U U U U 6 6 2 2 2
+negx 32 . . 0100000010...... A+-DXWL... U U U U U 12 12 4 4 4
+nop 0 . . 0100111001110001 .......... U U U U U 4 4 2 2 2
+not 8 . d 0100011000000... .......... U U U U U 4 4 2 2 2
+not 8 . . 0100011000...... A+-DXWL... U U U U U 8 8 4 4 4
+not 16 . d 0100011001000... .......... U U U U U 4 4 2 2 2
+not 16 . . 0100011001...... A+-DXWL... U U U U U 8 8 4 4 4
+not 32 . d 0100011010000... .......... U U U U U 6 6 2 2 2
+not 32 . . 0100011010...... A+-DXWL... U U U U U 12 12 4 4 4
+or 8 er d 1000...000000... .......... U U U U U 4 4 2 2 2
+or 8 er . 1000...000...... A+-DXWLdxI U U U U U 4 4 2 2 2
+or 16 er d 1000...001000... .......... U U U U U 4 4 2 2 2
+or 16 er . 1000...001...... A+-DXWLdxI U U U U U 4 4 2 2 2
+or 32 er d 1000...010000... .......... U U U U U 6 6 2 2 2
+or 32 er . 1000...010...... A+-DXWLdxI U U U U U 6 6 2 2 2
+or 8 re . 1000...100...... A+-DXWL... U U U U U 8 8 4 4 4
+or 16 re . 1000...101...... A+-DXWL... U U U U U 8 8 4 4 4
+or 32 re . 1000...110...... A+-DXWL... U U U U U 12 12 4 4 4
+ori 16 toc . 0000000000111100 .......... U U U U U 20 16 12 12 12
+ori 16 tos . 0000000001111100 .......... S S S S S 20 16 12 12 12
+ori 8 . d 0000000000000... .......... U U U U U 8 8 2 2 2
+ori 8 . . 0000000000...... A+-DXWL... U U U U U 12 12 4 4 4
+ori 16 . d 0000000001000... .......... U U U U U 8 8 2 2 2
+ori 16 . . 0000000001...... A+-DXWL... U U U U U 12 12 4 4 4
+ori 32 . d 0000000010000... .......... U U U U U 16 14 2 2 2
+ori 32 . . 0000000010...... A+-DXWL... U U U U U 20 20 4 4 4
+pack 16 rr . 1000...101000... .......... . . U U U . . 6 6 6
+pack 16 mm ax7 1000111101001... .......... . . U U U . . 13 13 13
+pack 16 mm ay7 1000...101001111 .......... . . U U U . . 13 13 13
+pack 16 mm axy7 1000111101001111 .......... . . U U U . . 13 13 13
+pack 16 mm . 1000...101001... .......... . . U U U . . 13 13 13
+pea 32 . . 0100100001...... A..DXWLdx. U U U U U 6 6 5 5 5
+pflush 32 . . 1111010100011000 .......... . . . . S . . . . 4 TODO: correct timing
+pmmu 32 . . 1111000......... .......... . . S S S . . 8 8 8
+reset 0 . . 0100111001110000 .......... S S S S S 0 0 0 0 0
+ror 8 s . 1110...000011... .......... U U U U U 6 6 8 8 8
+ror 16 s . 1110...001011... .......... U U U U U 6 6 8 8 8
+ror 32 s . 1110...010011... .......... U U U U U 8 8 8 8 8
+ror 8 r . 1110...000111... .......... U U U U U 6 6 8 8 8
+ror 16 r . 1110...001111... .......... U U U U U 6 6 8 8 8
+ror 32 r . 1110...010111... .......... U U U U U 8 8 8 8 8
+ror 16 . . 1110011011...... A+-DXWL... U U U U U 8 8 7 7 7
+rol 8 s . 1110...100011... .......... U U U U U 6 6 8 8 8
+rol 16 s . 1110...101011... .......... U U U U U 6 6 8 8 8
+rol 32 s . 1110...110011... .......... U U U U U 8 8 8 8 8
+rol 8 r . 1110...100111... .......... U U U U U 6 6 8 8 8
+rol 16 r . 1110...101111... .......... U U U U U 6 6 8 8 8
+rol 32 r . 1110...110111... .......... U U U U U 8 8 8 8 8
+rol 16 . . 1110011111...... A+-DXWL... U U U U U 8 8 7 7 7
+roxr 8 s . 1110...000010... .......... U U U U U 6 6 12 12 12
+roxr 16 s . 1110...001010... .......... U U U U U 6 6 12 12 12
+roxr 32 s . 1110...010010... .......... U U U U U 8 8 12 12 12
+roxr 8 r . 1110...000110... .......... U U U U U 6 6 12 12 12
+roxr 16 r . 1110...001110... .......... U U U U U 6 6 12 12 12
+roxr 32 r . 1110...010110... .......... U U U U U 8 8 12 12 12
+roxr 16 . . 1110010011...... A+-DXWL... U U U U U 8 8 5 5 5
+roxl 8 s . 1110...100010... .......... U U U U U 6 6 12 12 12
+roxl 16 s . 1110...101010... .......... U U U U U 6 6 12 12 12
+roxl 32 s . 1110...110010... .......... U U U U U 8 8 12 12 12
+roxl 8 r . 1110...100110... .......... U U U U U 6 6 12 12 12
+roxl 16 r . 1110...101110... .......... U U U U U 6 6 12 12 12
+roxl 32 r . 1110...110110... .......... U U U U U 8 8 12 12 12
+roxl 16 . . 1110010111...... A+-DXWL... U U U U U 8 8 5 5 5
+rtd 32 . . 0100111001110100 .......... . U U U U . 16 10 10 10
+rte 32 . . 0100111001110011 .......... S S S S S 20 24 20 20 20 bus fault not emulated
+rtm 32 . . 000001101100.... .......... . . U U U . . 19 19 19 not properly emulated
+rtr 32 . . 0100111001110111 .......... U U U U U 20 20 14 14 14
+rts 32 . . 0100111001110101 .......... U U U U U 16 16 10 10 10
+sbcd 8 rr . 1000...100000... .......... U U U U U 6 6 4 4 4
+sbcd 8 mm ax7 1000111100001... .......... U U U U U 18 18 16 16 16
+sbcd 8 mm ay7 1000...100001111 .......... U U U U U 18 18 16 16 16
+sbcd 8 mm axy7 1000111100001111 .......... U U U U U 18 18 16 16 16
+sbcd 8 mm . 1000...100001... .......... U U U U U 18 18 16 16 16
+st 8 . d 0101000011000... .......... U U U U U 6 4 4 4 4
+st 8 . . 0101000011...... A+-DXWL... U U U U U 8 8 6 6 6
+sf 8 . d 0101000111000... .......... U U U U U 4 4 4 4 4
+sf 8 . . 0101000111...... A+-DXWL... U U U U U 8 8 6 6 6
+scc 8 . d 0101....11000... .......... U U U U U 4 4 4 4 4
+scc 8 . . 0101....11...... A+-DXWL... U U U U U 8 8 6 6 6
+stop 0 . . 0100111001110010 .......... S S S S S 4 4 8 8 8
+sub 8 er d 1001...000000... .......... U U U U U 4 4 2 2 2
+sub 8 er . 1001...000...... A+-DXWLdxI U U U U U 4 4 2 2 2
+sub 16 er d 1001...001000... .......... U U U U U 4 4 2 2 2
+sub 16 er a 1001...001001... .......... U U U U U 4 4 2 2 2
+sub 16 er . 1001...001...... A+-DXWLdxI U U U U U 4 4 2 2 2
+sub 32 er d 1001...010000... .......... U U U U U 6 6 2 2 2
+sub 32 er a 1001...010001... .......... U U U U U 6 6 2 2 2
+sub 32 er . 1001...010...... A+-DXWLdxI U U U U U 6 6 2 2 2
+sub 8 re . 1001...100...... A+-DXWL... U U U U U 8 8 4 4 4
+sub 16 re . 1001...101...... A+-DXWL... U U U U U 8 8 4 4 4
+sub 32 re . 1001...110...... A+-DXWL... U U U U U 12 12 4 4 4
+suba 16 . d 1001...011000... .......... U U U U U 8 8 2 2 2
+suba 16 . a 1001...011001... .......... U U U U U 8 8 2 2 2
+suba 16 . . 1001...011...... A+-DXWLdxI U U U U U 8 8 2 2 2
+suba 32 . d 1001...111000... .......... U U U U U 6 6 2 2 2
+suba 32 . a 1001...111001... .......... U U U U U 6 6 2 2 2
+suba 32 . . 1001...111...... A+-DXWLdxI U U U U U 6 6 2 2 2
+subi 8 . d 0000010000000... .......... U U U U U 8 8 2 2 2
+subi 8 . . 0000010000...... A+-DXWL... U U U U U 12 12 4 4 4
+subi 16 . d 0000010001000... .......... U U U U U 8 8 2 2 2
+subi 16 . . 0000010001...... A+-DXWL... U U U U U 12 12 4 4 4
+subi 32 . d 0000010010000... .......... U U U U U 16 14 2 2 2
+subi 32 . . 0000010010...... A+-DXWL... U U U U U 20 20 4 4 4
+subq 8 . d 0101...100000... .......... U U U U U 4 4 2 2 2
+subq 8 . . 0101...100...... A+-DXWL... U U U U U 8 8 4 4 4
+subq 16 . d 0101...101000... .......... U U U U U 4 4 2 2 2
+subq 16 . a 0101...101001... .......... U U U U U 8 4 2 2 2
+subq 16 . . 0101...101...... A+-DXWL... U U U U U 8 8 4 4 4
+subq 32 . d 0101...110000... .......... U U U U U 8 8 2 2 2
+subq 32 . a 0101...110001... .......... U U U U U 8 8 2 2 2
+subq 32 . . 0101...110...... A+-DXWL... U U U U U 12 12 4 4 4
+subx 8 rr . 1001...100000... .......... U U U U U 4 4 2 2 2
+subx 16 rr . 1001...101000... .......... U U U U U 4 4 2 2 2
+subx 32 rr . 1001...110000... .......... U U U U U 8 6 2 2 2
+subx 8 mm ax7 1001111100001... .......... U U U U U 18 18 12 12 12
+subx 8 mm ay7 1001...100001111 .......... U U U U U 18 18 12 12 12
+subx 8 mm axy7 1001111100001111 .......... U U U U U 18 18 12 12 12
+subx 8 mm . 1001...100001... .......... U U U U U 18 18 12 12 12
+subx 16 mm . 1001...101001... .......... U U U U U 18 18 12 12 12
+subx 32 mm . 1001...110001... .......... U U U U U 30 30 12 12 12
+swap 32 . . 0100100001000... .......... U U U U U 4 4 4 4 4
+tas 8 . d 0100101011000... .......... U U U U U 4 4 4 4 4
+tas 8 . . 0100101011...... A+-DXWL... U U U U U 14 14 12 12 12
+trap 0 . . 010011100100.... .......... U U U U U 4 4 4 4 4
+trapt 0 . . 0101000011111100 .......... . . U U U . . 4 4 4
+trapt 16 . . 0101000011111010 .......... . . U U U . . 6 6 6
+trapt 32 . . 0101000011111011 .......... . . U U U . . 8 8 8
+trapf 0 . . 0101000111111100 .......... . . U U U . . 4 4 4
+trapf 16 . . 0101000111111010 .......... . . U U U . . 6 6 6
+trapf 32 . . 0101000111111011 .......... . . U U U . . 8 8 8
+trapcc 0 . . 0101....11111100 .......... . . U U U . . 4 4 4
+trapcc 16 . . 0101....11111010 .......... . . U U U . . 6 6 6
+trapcc 32 . . 0101....11111011 .......... . . U U U . . 8 8 8
+trapv 0 . . 0100111001110110 .......... U U U U U 4 4 4 4 4
+tst 8 . d 0100101000000... .......... U U U U U 4 4 2 2 2
+tst 8 . . 0100101000...... A+-DXWL... U U U U U 4 4 2 2 2
+tst 8 . pcdi 0100101000111010 .......... . . U U U . . 7 7 7
+tst 8 . pcix 0100101000111011 .......... . . U U U . . 9 9 9
+tst 8 . i 0100101000111100 .......... . . U U U . . 6 6 6
+tst 16 . d 0100101001000... .......... U U U U U 4 4 2 2 2
+tst 16 . a 0100101001001... .......... . . U U U . . 2 2 2
+tst 16 . . 0100101001...... A+-DXWL... U U U U U 4 4 2 2 2
+tst 16 . pcdi 0100101001111010 .......... . . U U U . . 7 7 7
+tst 16 . pcix 0100101001111011 .......... . . U U U . . 9 9 9
+tst 16 . i 0100101001111100 .......... . . U U U . . 6 6 6
+tst 32 . d 0100101010000... .......... U U U U U 4 4 2 2 2
+tst 32 . a 0100101010001... .......... . . U U U . . 2 2 2
+tst 32 . . 0100101010...... A+-DXWL... U U U U U 4 4 2 2 2
+tst 32 . pcdi 0100101010111010 .......... . . U U U . . 7 7 7
+tst 32 . pcix 0100101010111011 .......... . . U U U . . 9 9 9
+tst 32 . i 0100101010111100 .......... . . U U U . . 6 6 6
+unlk 32 . a7 0100111001011111 .......... U U U U U 12 12 6 6 6
+unlk 32 . . 0100111001011... .......... U U U U U 12 12 6 6 6
+unpk 16 rr . 1000...110000... .......... . . U U U . . 8 8 8
+unpk 16 mm ax7 1000111110001... .......... . . U U U . . 13 13 13
+unpk 16 mm ay7 1000...110001111 .......... . . U U U . . 13 13 13
+unpk 16 mm axy7 1000111110001111 .......... . . U U U . . 13 13 13
+unpk 16 mm . 1000...110001... .......... . . U U U . . 13 13 13
+
+
+
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+M68KMAKE_OPCODE_HANDLER_BODY
+
+M68KMAKE_OP(1010, 0, ., .)
+{
+ m68ki_exception_1010(m68k);
+}
+
+
+M68KMAKE_OP(1111, 0, ., .)
+{
+ m68ki_exception_1111(m68k);
+}
+
+
+M68KMAKE_OP(040fpu0, 32, ., .)
+{
+ if(m68k->has_fpu)
+ {
+ m68040_fpu_op0(m68k);
+ return;
+ }
+ m68ki_exception_1111(m68k);
+}
+
+
+M68KMAKE_OP(040fpu1, 32, ., .)
+{
+ if(m68k->has_fpu)
+ {
+ m68040_fpu_op1(m68k);
+ return;
+ }
+ m68ki_exception_1111(m68k);
+}
+
+
+
+M68KMAKE_OP(abcd, 8, rr, .)
+{
+ UINT32* r_dst = &DX;
+ UINT32 src = DY;
+ UINT32 dst = *r_dst;
+ UINT32 res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(m68k);
+
+ m68k->v_flag = ~res; /* Undefined V behavior */
+
+ if(res > 9)
+ res += 6;
+ res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst);
+ m68k->x_flag = m68k->c_flag = (res > 0x99) << 8;
+ if(m68k->c_flag)
+ res -= 0xa0;
+
+ m68k->v_flag &= res; /* Undefined V behavior part II */
+ m68k->n_flag = NFLAG_8(res); /* Undefined N behavior */
+
+ res = MASK_OUT_ABOVE_8(res);
+ m68k->not_z_flag |= res;
+
+ *r_dst = MASK_OUT_BELOW_8(*r_dst) | res;
+}
+
+
+M68KMAKE_OP(abcd, 8, mm, ax7)
+{
+ UINT32 src = OPER_AY_PD_8(m68k);
+ UINT32 ea = EA_A7_PD_8(m68k);
+ UINT32 dst = m68ki_read_8(m68k, ea);
+ UINT32 res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(m68k);
+
+ m68k->v_flag = ~res; /* Undefined V behavior */
+
+ if(res > 9)
+ res += 6;
+ res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst);
+ m68k->x_flag = m68k->c_flag = (res > 0x99) << 8;
+ if(m68k->c_flag)
+ res -= 0xa0;
+
+ m68k->v_flag &= res; /* Undefined V behavior part II */
+ m68k->n_flag = NFLAG_8(res); /* Undefined N behavior */
+
+ res = MASK_OUT_ABOVE_8(res);
+ m68k->not_z_flag |= res;
+
+ m68ki_write_8(m68k, ea, res);
+}
+
+
+M68KMAKE_OP(abcd, 8, mm, ay7)
+{
+ UINT32 src = OPER_A7_PD_8(m68k);
+ UINT32 ea = EA_AX_PD_8(m68k);
+ UINT32 dst = m68ki_read_8(m68k, ea);
+ UINT32 res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(m68k);
+
+ m68k->v_flag = ~res; /* Undefined V behavior */
+
+ if(res > 9)
+ res += 6;
+ res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst);
+ m68k->x_flag = m68k->c_flag = (res > 0x99) << 8;
+ if(m68k->c_flag)
+ res -= 0xa0;
+
+ m68k->v_flag &= res; /* Undefined V behavior part II */
+ m68k->n_flag = NFLAG_8(res); /* Undefined N behavior */
+
+ res = MASK_OUT_ABOVE_8(res);
+ m68k->not_z_flag |= res;
+
+ m68ki_write_8(m68k, ea, res);
+}
+
+
+M68KMAKE_OP(abcd, 8, mm, axy7)
+{
+ UINT32 src = OPER_A7_PD_8(m68k);
+ UINT32 ea = EA_A7_PD_8(m68k);
+ UINT32 dst = m68ki_read_8(m68k, ea);
+ UINT32 res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(m68k);
+
+ m68k->v_flag = ~res; /* Undefined V behavior */
+
+ if(res > 9)
+ res += 6;
+ res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst);
+ m68k->x_flag = m68k->c_flag = (res > 0x99) << 8;
+ if(m68k->c_flag)
+ res -= 0xa0;
+
+ m68k->v_flag &= res; /* Undefined V behavior part II */
+ m68k->n_flag = NFLAG_8(res); /* Undefined N behavior */
+
+ res = MASK_OUT_ABOVE_8(res);
+ m68k->not_z_flag |= res;
+
+ m68ki_write_8(m68k, ea, res);
+}
+
+
+M68KMAKE_OP(abcd, 8, mm, .)
+{
+ UINT32 src = OPER_AY_PD_8(m68k);
+ UINT32 ea = EA_AX_PD_8(m68k);
+ UINT32 dst = m68ki_read_8(m68k, ea);
+ UINT32 res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(m68k);
+
+ m68k->v_flag = ~res; /* Undefined V behavior */
+
+ if(res > 9)
+ res += 6;
+ res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst);
+ m68k->x_flag = m68k->c_flag = (res > 0x99) << 8;
+ if(m68k->c_flag)
+ res -= 0xa0;
+
+ m68k->v_flag &= res; /* Undefined V behavior part II */
+ m68k->n_flag = NFLAG_8(res); /* Undefined N behavior */
+
+ res = MASK_OUT_ABOVE_8(res);
+ m68k->not_z_flag |= res;
+
+ m68ki_write_8(m68k, ea, res);
+}
+
+
+M68KMAKE_OP(add, 8, er, d)
+{
+ UINT32* r_dst = &DX;
+ UINT32 src = MASK_OUT_ABOVE_8(DY);
+ UINT32 dst = MASK_OUT_ABOVE_8(*r_dst);
+ UINT32 res = src + dst;
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->v_flag = VFLAG_ADD_8(src, dst, res);
+ m68k->x_flag = m68k->c_flag = CFLAG_8(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_8(res);
+
+ *r_dst = MASK_OUT_BELOW_8(*r_dst) | m68k->not_z_flag;
+}
+
+
+M68KMAKE_OP(add, 8, er, .)
+{
+ UINT32* r_dst = &DX;
+ UINT32 src = M68KMAKE_GET_OPER_AY_8;
+ UINT32 dst = MASK_OUT_ABOVE_8(*r_dst);
+ UINT32 res = src + dst;
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->v_flag = VFLAG_ADD_8(src, dst, res);
+ m68k->x_flag = m68k->c_flag = CFLAG_8(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_8(res);
+
+ *r_dst = MASK_OUT_BELOW_8(*r_dst) | m68k->not_z_flag;
+}
+
+
+M68KMAKE_OP(add, 16, er, d)
+{
+ UINT32* r_dst = &DX;
+ UINT32 src = MASK_OUT_ABOVE_16(DY);
+ UINT32 dst = MASK_OUT_ABOVE_16(*r_dst);
+ UINT32 res = src + dst;
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->v_flag = VFLAG_ADD_16(src, dst, res);
+ m68k->x_flag = m68k->c_flag = CFLAG_16(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_16(res);
+
+ *r_dst = MASK_OUT_BELOW_16(*r_dst) | m68k->not_z_flag;
+}
+
+
+M68KMAKE_OP(add, 16, er, a)
+{
+ UINT32* r_dst = &DX;
+ UINT32 src = MASK_OUT_ABOVE_16(AY);
+ UINT32 dst = MASK_OUT_ABOVE_16(*r_dst);
+ UINT32 res = src + dst;
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->v_flag = VFLAG_ADD_16(src, dst, res);
+ m68k->x_flag = m68k->c_flag = CFLAG_16(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_16(res);
+
+ *r_dst = MASK_OUT_BELOW_16(*r_dst) | m68k->not_z_flag;
+}
+
+
+M68KMAKE_OP(add, 16, er, .)
+{
+ UINT32* r_dst = &DX;
+ UINT32 src = M68KMAKE_GET_OPER_AY_16;
+ UINT32 dst = MASK_OUT_ABOVE_16(*r_dst);
+ UINT32 res = src + dst;
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->v_flag = VFLAG_ADD_16(src, dst, res);
+ m68k->x_flag = m68k->c_flag = CFLAG_16(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_16(res);
+
+ *r_dst = MASK_OUT_BELOW_16(*r_dst) | m68k->not_z_flag;
+}
+
+
+M68KMAKE_OP(add, 32, er, d)
+{
+ UINT32* r_dst = &DX;
+ UINT32 src = DY;
+ UINT32 dst = *r_dst;
+ UINT32 res = src + dst;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->v_flag = VFLAG_ADD_32(src, dst, res);
+ m68k->x_flag = m68k->c_flag = CFLAG_ADD_32(src, dst, res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res);
+
+ *r_dst = m68k->not_z_flag;
+}
+
+
+M68KMAKE_OP(add, 32, er, a)
+{
+ UINT32* r_dst = &DX;
+ UINT32 src = AY;
+ UINT32 dst = *r_dst;
+ UINT32 res = src + dst;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->v_flag = VFLAG_ADD_32(src, dst, res);
+ m68k->x_flag = m68k->c_flag = CFLAG_ADD_32(src, dst, res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res);
+
+ *r_dst = m68k->not_z_flag;
+}
+
+
+M68KMAKE_OP(add, 32, er, .)
+{
+ UINT32* r_dst = &DX;
+ UINT32 src = M68KMAKE_GET_OPER_AY_32;
+ UINT32 dst = *r_dst;
+ UINT32 res = src + dst;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->v_flag = VFLAG_ADD_32(src, dst, res);
+ m68k->x_flag = m68k->c_flag = CFLAG_ADD_32(src, dst, res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res);
+
+ *r_dst = m68k->not_z_flag;
+}
+
+
+M68KMAKE_OP(add, 8, re, .)
+{
+ UINT32 ea = M68KMAKE_GET_EA_AY_8;
+ UINT32 src = MASK_OUT_ABOVE_8(DX);
+ UINT32 dst = m68ki_read_8(m68k, ea);
+ UINT32 res = src + dst;
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->v_flag = VFLAG_ADD_8(src, dst, res);
+ m68k->x_flag = m68k->c_flag = CFLAG_8(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_8(res);
+
+ m68ki_write_8(m68k, ea, m68k->not_z_flag);
+}
+
+
+M68KMAKE_OP(add, 16, re, .)
+{
+ UINT32 ea = M68KMAKE_GET_EA_AY_16;
+ UINT32 src = MASK_OUT_ABOVE_16(DX);
+ UINT32 dst = m68ki_read_16(m68k, ea);
+ UINT32 res = src + dst;
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->v_flag = VFLAG_ADD_16(src, dst, res);
+ m68k->x_flag = m68k->c_flag = CFLAG_16(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_16(res);
+
+ m68ki_write_16(m68k, ea, m68k->not_z_flag);
+}
+
+
+M68KMAKE_OP(add, 32, re, .)
+{
+ UINT32 ea = M68KMAKE_GET_EA_AY_32;
+ UINT32 src = DX;
+ UINT32 dst = m68ki_read_32(m68k, ea);
+ UINT32 res = src + dst;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->v_flag = VFLAG_ADD_32(src, dst, res);
+ m68k->x_flag = m68k->c_flag = CFLAG_ADD_32(src, dst, res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res);
+
+ m68ki_write_32(m68k, ea, m68k->not_z_flag);
+}
+
+
+M68KMAKE_OP(adda, 16, ., d)
+{
+ UINT32* r_dst = &AX;
+
+ *r_dst = MASK_OUT_ABOVE_32(*r_dst + MAKE_INT_16(DY));
+}
+
+
+M68KMAKE_OP(adda, 16, ., a)
+{
+ UINT32* r_dst = &AX;
+
+ *r_dst = MASK_OUT_ABOVE_32(*r_dst + MAKE_INT_16(AY));
+}
+
+
+M68KMAKE_OP(adda, 16, ., .)
+{
+ UINT32* r_dst = &AX;
+ UINT32 src = MAKE_INT_16(M68KMAKE_GET_OPER_AY_16);
+
+ *r_dst = MASK_OUT_ABOVE_32(*r_dst + src);
+}
+
+
+M68KMAKE_OP(adda, 32, ., d)
+{
+ UINT32* r_dst = &AX;
+
+ *r_dst = MASK_OUT_ABOVE_32(*r_dst + DY);
+}
+
+
+M68KMAKE_OP(adda, 32, ., a)
+{
+ UINT32* r_dst = &AX;
+
+ *r_dst = MASK_OUT_ABOVE_32(*r_dst + AY);
+}
+
+
+M68KMAKE_OP(adda, 32, ., .)
+{
+ UINT32* r_dst = &AX;
+ UINT32 src = M68KMAKE_GET_OPER_AY_32;
+
+ *r_dst = MASK_OUT_ABOVE_32(*r_dst + src);
+}
+
+
+M68KMAKE_OP(addi, 8, ., d)
+{
+ UINT32* r_dst = &DY;
+ UINT32 src = OPER_I_8(m68k);
+ UINT32 dst = MASK_OUT_ABOVE_8(*r_dst);
+ UINT32 res = src + dst;
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->v_flag = VFLAG_ADD_8(src, dst, res);
+ m68k->x_flag = m68k->c_flag = CFLAG_8(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_8(res);
+
+ *r_dst = MASK_OUT_BELOW_8(*r_dst) | m68k->not_z_flag;
+}
+
+
+M68KMAKE_OP(addi, 8, ., .)
+{
+ UINT32 src = OPER_I_8(m68k);
+ UINT32 ea = M68KMAKE_GET_EA_AY_8;
+ UINT32 dst = m68ki_read_8(m68k, ea);
+ UINT32 res = src + dst;
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->v_flag = VFLAG_ADD_8(src, dst, res);
+ m68k->x_flag = m68k->c_flag = CFLAG_8(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_8(res);
+
+ m68ki_write_8(m68k, ea, m68k->not_z_flag);
+}
+
+
+M68KMAKE_OP(addi, 16, ., d)
+{
+ UINT32* r_dst = &DY;
+ UINT32 src = OPER_I_16(m68k);
+ UINT32 dst = MASK_OUT_ABOVE_16(*r_dst);
+ UINT32 res = src + dst;
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->v_flag = VFLAG_ADD_16(src, dst, res);
+ m68k->x_flag = m68k->c_flag = CFLAG_16(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_16(res);
+
+ *r_dst = MASK_OUT_BELOW_16(*r_dst) | m68k->not_z_flag;
+}
+
+
+M68KMAKE_OP(addi, 16, ., .)
+{
+ UINT32 src = OPER_I_16(m68k);
+ UINT32 ea = M68KMAKE_GET_EA_AY_16;
+ UINT32 dst = m68ki_read_16(m68k, ea);
+ UINT32 res = src + dst;
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->v_flag = VFLAG_ADD_16(src, dst, res);
+ m68k->x_flag = m68k->c_flag = CFLAG_16(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_16(res);
+
+ m68ki_write_16(m68k, ea, m68k->not_z_flag);
+}
+
+
+M68KMAKE_OP(addi, 32, ., d)
+{
+ UINT32* r_dst = &DY;
+ UINT32 src = OPER_I_32(m68k);
+ UINT32 dst = *r_dst;
+ UINT32 res = src + dst;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->v_flag = VFLAG_ADD_32(src, dst, res);
+ m68k->x_flag = m68k->c_flag = CFLAG_ADD_32(src, dst, res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res);
+
+ *r_dst = m68k->not_z_flag;
+}
+
+
+M68KMAKE_OP(addi, 32, ., .)
+{
+ UINT32 src = OPER_I_32(m68k);
+ UINT32 ea = M68KMAKE_GET_EA_AY_32;
+ UINT32 dst = m68ki_read_32(m68k, ea);
+ UINT32 res = src + dst;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->v_flag = VFLAG_ADD_32(src, dst, res);
+ m68k->x_flag = m68k->c_flag = CFLAG_ADD_32(src, dst, res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res);
+
+ m68ki_write_32(m68k, ea, m68k->not_z_flag);
+}
+
+
+M68KMAKE_OP(addq, 8, ., d)
+{
+ UINT32* r_dst = &DY;
+ UINT32 src = (((m68k->ir >> 9) - 1) & 7) + 1;
+ UINT32 dst = MASK_OUT_ABOVE_8(*r_dst);
+ UINT32 res = src + dst;
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->v_flag = VFLAG_ADD_8(src, dst, res);
+ m68k->x_flag = m68k->c_flag = CFLAG_8(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_8(res);
+
+ *r_dst = MASK_OUT_BELOW_8(*r_dst) | m68k->not_z_flag;
+}
+
+
+M68KMAKE_OP(addq, 8, ., .)
+{
+ UINT32 src = (((m68k->ir >> 9) - 1) & 7) + 1;
+ UINT32 ea = M68KMAKE_GET_EA_AY_8;
+ UINT32 dst = m68ki_read_8(m68k, ea);
+ UINT32 res = src + dst;
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->v_flag = VFLAG_ADD_8(src, dst, res);
+ m68k->x_flag = m68k->c_flag = CFLAG_8(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_8(res);
+
+ m68ki_write_8(m68k, ea, m68k->not_z_flag);
+}
+
+
+M68KMAKE_OP(addq, 16, ., d)
+{
+ UINT32* r_dst = &DY;
+ UINT32 src = (((m68k->ir >> 9) - 1) & 7) + 1;
+ UINT32 dst = MASK_OUT_ABOVE_16(*r_dst);
+ UINT32 res = src + dst;
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->v_flag = VFLAG_ADD_16(src, dst, res);
+ m68k->x_flag = m68k->c_flag = CFLAG_16(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_16(res);
+
+ *r_dst = MASK_OUT_BELOW_16(*r_dst) | m68k->not_z_flag;
+}
+
+
+M68KMAKE_OP(addq, 16, ., a)
+{
+ UINT32* r_dst = &AY;
+
+ *r_dst = MASK_OUT_ABOVE_32(*r_dst + (((m68k->ir >> 9) - 1) & 7) + 1);
+}
+
+
+M68KMAKE_OP(addq, 16, ., .)
+{
+ UINT32 src = (((m68k->ir >> 9) - 1) & 7) + 1;
+ UINT32 ea = M68KMAKE_GET_EA_AY_16;
+ UINT32 dst = m68ki_read_16(m68k, ea);
+ UINT32 res = src + dst;
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->v_flag = VFLAG_ADD_16(src, dst, res);
+ m68k->x_flag = m68k->c_flag = CFLAG_16(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_16(res);
+
+ m68ki_write_16(m68k, ea, m68k->not_z_flag);
+}
+
+
+M68KMAKE_OP(addq, 32, ., d)
+{
+ UINT32* r_dst = &DY;
+ UINT32 src = (((m68k->ir >> 9) - 1) & 7) + 1;
+ UINT32 dst = *r_dst;
+ UINT32 res = src + dst;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->v_flag = VFLAG_ADD_32(src, dst, res);
+ m68k->x_flag = m68k->c_flag = CFLAG_ADD_32(src, dst, res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res);
+
+ *r_dst = m68k->not_z_flag;
+}
+
+
+M68KMAKE_OP(addq, 32, ., a)
+{
+ UINT32* r_dst = &AY;
+
+ *r_dst = MASK_OUT_ABOVE_32(*r_dst + (((m68k->ir >> 9) - 1) & 7) + 1);
+}
+
+
+M68KMAKE_OP(addq, 32, ., .)
+{
+ UINT32 src = (((m68k->ir >> 9) - 1) & 7) + 1;
+ UINT32 ea = M68KMAKE_GET_EA_AY_32;
+ UINT32 dst = m68ki_read_32(m68k, ea);
+ UINT32 res = src + dst;
+
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->v_flag = VFLAG_ADD_32(src, dst, res);
+ m68k->x_flag = m68k->c_flag = CFLAG_ADD_32(src, dst, res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res);
+
+ m68ki_write_32(m68k, ea, m68k->not_z_flag);
+}
+
+
+M68KMAKE_OP(addx, 8, rr, .)
+{
+ UINT32* r_dst = &DX;
+ UINT32 src = MASK_OUT_ABOVE_8(DY);
+ UINT32 dst = MASK_OUT_ABOVE_8(*r_dst);
+ UINT32 res = src + dst + XFLAG_AS_1(m68k);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->v_flag = VFLAG_ADD_8(src, dst, res);
+ m68k->x_flag = m68k->c_flag = CFLAG_8(res);
+
+ res = MASK_OUT_ABOVE_8(res);
+ m68k->not_z_flag |= res;
+
+ *r_dst = MASK_OUT_BELOW_8(*r_dst) | res;
+}
+
+
+M68KMAKE_OP(addx, 16, rr, .)
+{
+ UINT32* r_dst = &DX;
+ UINT32 src = MASK_OUT_ABOVE_16(DY);
+ UINT32 dst = MASK_OUT_ABOVE_16(*r_dst);
+ UINT32 res = src + dst + XFLAG_AS_1(m68k);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->v_flag = VFLAG_ADD_16(src, dst, res);
+ m68k->x_flag = m68k->c_flag = CFLAG_16(res);
+
+ res = MASK_OUT_ABOVE_16(res);
+ m68k->not_z_flag |= res;
+
+ *r_dst = MASK_OUT_BELOW_16(*r_dst) | res;
+}
+
+
+M68KMAKE_OP(addx, 32, rr, .)
+{
+ UINT32* r_dst = &DX;
+ UINT32 src = DY;
+ UINT32 dst = *r_dst;
+ UINT32 res = src + dst + XFLAG_AS_1(m68k);
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->v_flag = VFLAG_ADD_32(src, dst, res);
+ m68k->x_flag = m68k->c_flag = CFLAG_ADD_32(src, dst, res);
+
+ res = MASK_OUT_ABOVE_32(res);
+ m68k->not_z_flag |= res;
+
+ *r_dst = res;
+}
+
+
+M68KMAKE_OP(addx, 8, mm, ax7)
+{
+ UINT32 src = OPER_AY_PD_8(m68k);
+ UINT32 ea = EA_A7_PD_8(m68k);
+ UINT32 dst = m68ki_read_8(m68k, ea);
+ UINT32 res = src + dst + XFLAG_AS_1(m68k);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->v_flag = VFLAG_ADD_8(src, dst, res);
+ m68k->x_flag = m68k->c_flag = CFLAG_8(res);
+
+ res = MASK_OUT_ABOVE_8(res);
+ m68k->not_z_flag |= res;
+
+ m68ki_write_8(m68k, ea, res);
+}
+
+
+M68KMAKE_OP(addx, 8, mm, ay7)
+{
+ UINT32 src = OPER_A7_PD_8(m68k);
+ UINT32 ea = EA_AX_PD_8(m68k);
+ UINT32 dst = m68ki_read_8(m68k, ea);
+ UINT32 res = src + dst + XFLAG_AS_1(m68k);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->v_flag = VFLAG_ADD_8(src, dst, res);
+ m68k->x_flag = m68k->c_flag = CFLAG_8(res);
+
+ res = MASK_OUT_ABOVE_8(res);
+ m68k->not_z_flag |= res;
+
+ m68ki_write_8(m68k, ea, res);
+}
+
+
+M68KMAKE_OP(addx, 8, mm, axy7)
+{
+ UINT32 src = OPER_A7_PD_8(m68k);
+ UINT32 ea = EA_A7_PD_8(m68k);
+ UINT32 dst = m68ki_read_8(m68k, ea);
+ UINT32 res = src + dst + XFLAG_AS_1(m68k);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->v_flag = VFLAG_ADD_8(src, dst, res);
+ m68k->x_flag = m68k->c_flag = CFLAG_8(res);
+
+ res = MASK_OUT_ABOVE_8(res);
+ m68k->not_z_flag |= res;
+
+ m68ki_write_8(m68k, ea, res);
+}
+
+
+M68KMAKE_OP(addx, 8, mm, .)
+{
+ UINT32 src = OPER_AY_PD_8(m68k);
+ UINT32 ea = EA_AX_PD_8(m68k);
+ UINT32 dst = m68ki_read_8(m68k, ea);
+ UINT32 res = src + dst + XFLAG_AS_1(m68k);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->v_flag = VFLAG_ADD_8(src, dst, res);
+ m68k->x_flag = m68k->c_flag = CFLAG_8(res);
+
+ res = MASK_OUT_ABOVE_8(res);
+ m68k->not_z_flag |= res;
+
+ m68ki_write_8(m68k, ea, res);
+}
+
+
+M68KMAKE_OP(addx, 16, mm, .)
+{
+ UINT32 src = OPER_AY_PD_16(m68k);
+ UINT32 ea = EA_AX_PD_16(m68k);
+ UINT32 dst = m68ki_read_16(m68k, ea);
+ UINT32 res = src + dst + XFLAG_AS_1(m68k);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->v_flag = VFLAG_ADD_16(src, dst, res);
+ m68k->x_flag = m68k->c_flag = CFLAG_16(res);
+
+ res = MASK_OUT_ABOVE_16(res);
+ m68k->not_z_flag |= res;
+
+ m68ki_write_16(m68k, ea, res);
+}
+
+
+M68KMAKE_OP(addx, 32, mm, .)
+{
+ UINT32 src = OPER_AY_PD_32(m68k);
+ UINT32 ea = EA_AX_PD_32(m68k);
+ UINT32 dst = m68ki_read_32(m68k, ea);
+ UINT32 res = src + dst + XFLAG_AS_1(m68k);
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->v_flag = VFLAG_ADD_32(src, dst, res);
+ m68k->x_flag = m68k->c_flag = CFLAG_ADD_32(src, dst, res);
+
+ res = MASK_OUT_ABOVE_32(res);
+ m68k->not_z_flag |= res;
+
+ m68ki_write_32(m68k, ea, res);
+}
+
+
+M68KMAKE_OP(and, 8, er, d)
+{
+ m68k->not_z_flag = MASK_OUT_ABOVE_8(DX &= (DY | 0xffffff00));
+
+ m68k->n_flag = NFLAG_8(m68k->not_z_flag);
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(and, 8, er, .)
+{
+ m68k->not_z_flag = MASK_OUT_ABOVE_8(DX &= (M68KMAKE_GET_OPER_AY_8 | 0xffffff00));
+
+ m68k->n_flag = NFLAG_8(m68k->not_z_flag);
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(and, 16, er, d)
+{
+ m68k->not_z_flag = MASK_OUT_ABOVE_16(DX &= (DY | 0xffff0000));
+
+ m68k->n_flag = NFLAG_16(m68k->not_z_flag);
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(and, 16, er, .)
+{
+ m68k->not_z_flag = MASK_OUT_ABOVE_16(DX &= (M68KMAKE_GET_OPER_AY_16 | 0xffff0000));
+
+ m68k->n_flag = NFLAG_16(m68k->not_z_flag);
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(and, 32, er, d)
+{
+ m68k->not_z_flag = DX &= DY;
+
+ m68k->n_flag = NFLAG_32(m68k->not_z_flag);
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(and, 32, er, .)
+{
+ m68k->not_z_flag = DX &= M68KMAKE_GET_OPER_AY_32;
+
+ m68k->n_flag = NFLAG_32(m68k->not_z_flag);
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(and, 8, re, .)
+{
+ UINT32 ea = M68KMAKE_GET_EA_AY_8;
+ UINT32 res = DX & m68ki_read_8(m68k, ea);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->not_z_flag = MASK_OUT_ABOVE_8(res);
+
+ m68ki_write_8(m68k, ea, m68k->not_z_flag);
+}
+
+
+M68KMAKE_OP(and, 16, re, .)
+{
+ UINT32 ea = M68KMAKE_GET_EA_AY_16;
+ UINT32 res = DX & m68ki_read_16(m68k, ea);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->not_z_flag = MASK_OUT_ABOVE_16(res);
+
+ m68ki_write_16(m68k, ea, m68k->not_z_flag);
+}
+
+
+M68KMAKE_OP(and, 32, re, .)
+{
+ UINT32 ea = M68KMAKE_GET_EA_AY_32;
+ UINT32 res = DX & m68ki_read_32(m68k, ea);
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+
+ m68ki_write_32(m68k, ea, res);
+}
+
+
+M68KMAKE_OP(andi, 8, ., d)
+{
+ m68k->not_z_flag = MASK_OUT_ABOVE_8(DY &= (OPER_I_8(m68k) | 0xffffff00));
+
+ m68k->n_flag = NFLAG_8(m68k->not_z_flag);
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(andi, 8, ., .)
+{
+ UINT32 src = OPER_I_8(m68k);
+ UINT32 ea = M68KMAKE_GET_EA_AY_8;
+ UINT32 res = src & m68ki_read_8(m68k, ea);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+
+ m68ki_write_8(m68k, ea, res);
+}
+
+
+M68KMAKE_OP(andi, 16, ., d)
+{
+ m68k->not_z_flag = MASK_OUT_ABOVE_16(DY &= (OPER_I_16(m68k) | 0xffff0000));
+
+ m68k->n_flag = NFLAG_16(m68k->not_z_flag);
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(andi, 16, ., .)
+{
+ UINT32 src = OPER_I_16(m68k);
+ UINT32 ea = M68KMAKE_GET_EA_AY_16;
+ UINT32 res = src & m68ki_read_16(m68k, ea);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+
+ m68ki_write_16(m68k, ea, res);
+}
+
+
+M68KMAKE_OP(andi, 32, ., d)
+{
+ m68k->not_z_flag = DY &= (OPER_I_32(m68k));
+
+ m68k->n_flag = NFLAG_32(m68k->not_z_flag);
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(andi, 32, ., .)
+{
+ UINT32 src = OPER_I_32(m68k);
+ UINT32 ea = M68KMAKE_GET_EA_AY_32;
+ UINT32 res = src & m68ki_read_32(m68k, ea);
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+
+ m68ki_write_32(m68k, ea, res);
+}
+
+
+M68KMAKE_OP(andi, 16, toc, .)
+{
+ m68ki_set_ccr(m68k, m68ki_get_ccr(m68k) & OPER_I_16(m68k));
+}
+
+
+M68KMAKE_OP(andi, 16, tos, .)
+{
+ if(m68k->s_flag)
+ {
+ UINT32 src = OPER_I_16(m68k);
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+ m68ki_set_sr(m68k, m68ki_get_sr(m68k) & src);
+ return;
+ }
+ m68ki_exception_privilege_violation(m68k);
+}
+
+
+M68KMAKE_OP(asr, 8, s, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 shift = (((m68k->ir >> 9) - 1) & 7) + 1;
+ UINT32 src = MASK_OUT_ABOVE_8(*r_dst);
+ UINT32 res = src >> shift;
+
+ if(shift != 0)
+ m68k->remaining_cycles -= shift<<m68k->cyc_shift;
+
+ if(GET_MSB_8(src))
+ res |= m68ki_shift_8_table[shift];
+
+ *r_dst = MASK_OUT_BELOW_8(*r_dst) | res;
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->x_flag = m68k->c_flag = src << (9-shift);
+}
+
+
+M68KMAKE_OP(asr, 16, s, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 shift = (((m68k->ir >> 9) - 1) & 7) + 1;
+ UINT32 src = MASK_OUT_ABOVE_16(*r_dst);
+ UINT32 res = src >> shift;
+
+ if(shift != 0)
+ m68k->remaining_cycles -= shift<<m68k->cyc_shift;
+
+ if(GET_MSB_16(src))
+ res |= m68ki_shift_16_table[shift];
+
+ *r_dst = MASK_OUT_BELOW_16(*r_dst) | res;
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->x_flag = m68k->c_flag = src << (9-shift);
+}
+
+
+M68KMAKE_OP(asr, 32, s, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 shift = (((m68k->ir >> 9) - 1) & 7) + 1;
+ UINT32 src = *r_dst;
+ UINT32 res = src >> shift;
+
+ if(shift != 0)
+ m68k->remaining_cycles -= shift<<m68k->cyc_shift;
+
+ if(GET_MSB_32(src))
+ res |= m68ki_shift_32_table[shift];
+
+ *r_dst = res;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->x_flag = m68k->c_flag = src << (9-shift);
+}
+
+
+M68KMAKE_OP(asr, 8, r, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 shift = DX & 0x3f;
+ UINT32 src = MASK_OUT_ABOVE_8(*r_dst);
+ UINT32 res = src >> shift;
+
+ if(shift != 0)
+ {
+ m68k->remaining_cycles -= shift<<m68k->cyc_shift;
+
+ if(shift < 8)
+ {
+ if(GET_MSB_8(src))
+ res |= m68ki_shift_8_table[shift];
+
+ *r_dst = MASK_OUT_BELOW_8(*r_dst) | res;
+
+ m68k->x_flag = m68k->c_flag = src << (9-shift);
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ return;
+ }
+
+ if(GET_MSB_8(src))
+ {
+ *r_dst |= 0xff;
+ m68k->c_flag = CFLAG_SET;
+ m68k->x_flag = XFLAG_SET;
+ m68k->n_flag = NFLAG_SET;
+ m68k->not_z_flag = ZFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+ return;
+ }
+
+ *r_dst &= 0xffffff00;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->x_flag = XFLAG_CLEAR;
+ m68k->n_flag = NFLAG_CLEAR;
+ m68k->not_z_flag = ZFLAG_SET;
+ m68k->v_flag = VFLAG_CLEAR;
+ return;
+ }
+
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->n_flag = NFLAG_8(src);
+ m68k->not_z_flag = src;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(asr, 16, r, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 shift = DX & 0x3f;
+ UINT32 src = MASK_OUT_ABOVE_16(*r_dst);
+ UINT32 res = src >> shift;
+
+ if(shift != 0)
+ {
+ m68k->remaining_cycles -= shift<<m68k->cyc_shift;
+
+ if(shift < 16)
+ {
+ if(GET_MSB_16(src))
+ res |= m68ki_shift_16_table[shift];
+
+ *r_dst = MASK_OUT_BELOW_16(*r_dst) | res;
+
+ m68k->c_flag = m68k->x_flag = (src >> (shift - 1))<<8;
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ return;
+ }
+
+ if(GET_MSB_16(src))
+ {
+ *r_dst |= 0xffff;
+ m68k->c_flag = CFLAG_SET;
+ m68k->x_flag = XFLAG_SET;
+ m68k->n_flag = NFLAG_SET;
+ m68k->not_z_flag = ZFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+ return;
+ }
+
+ *r_dst &= 0xffff0000;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->x_flag = XFLAG_CLEAR;
+ m68k->n_flag = NFLAG_CLEAR;
+ m68k->not_z_flag = ZFLAG_SET;
+ m68k->v_flag = VFLAG_CLEAR;
+ return;
+ }
+
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->n_flag = NFLAG_16(src);
+ m68k->not_z_flag = src;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(asr, 32, r, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 shift = DX & 0x3f;
+ UINT32 src = *r_dst;
+ UINT32 res = src >> shift;
+
+ if(shift != 0)
+ {
+ m68k->remaining_cycles -= shift<<m68k->cyc_shift;
+
+ if(shift < 32)
+ {
+ if(GET_MSB_32(src))
+ res |= m68ki_shift_32_table[shift];
+
+ *r_dst = res;
+
+ m68k->c_flag = m68k->x_flag = (src >> (shift - 1))<<8;
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ return;
+ }
+
+ if(GET_MSB_32(src))
+ {
+ *r_dst = 0xffffffff;
+ m68k->c_flag = CFLAG_SET;
+ m68k->x_flag = XFLAG_SET;
+ m68k->n_flag = NFLAG_SET;
+ m68k->not_z_flag = ZFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+ return;
+ }
+
+ *r_dst = 0;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->x_flag = XFLAG_CLEAR;
+ m68k->n_flag = NFLAG_CLEAR;
+ m68k->not_z_flag = ZFLAG_SET;
+ m68k->v_flag = VFLAG_CLEAR;
+ return;
+ }
+
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->n_flag = NFLAG_32(src);
+ m68k->not_z_flag = src;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(asr, 16, ., .)
+{
+ UINT32 ea = M68KMAKE_GET_EA_AY_16;
+ UINT32 src = m68ki_read_16(m68k, ea);
+ UINT32 res = src >> 1;
+
+ if(GET_MSB_16(src))
+ res |= 0x8000;
+
+ m68ki_write_16(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = m68k->x_flag = src << 8;
+}
+
+
+M68KMAKE_OP(asl, 8, s, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 shift = (((m68k->ir >> 9) - 1) & 7) + 1;
+ UINT32 src = MASK_OUT_ABOVE_8(*r_dst);
+ UINT32 res = MASK_OUT_ABOVE_8(src << shift);
+
+ if(shift != 0)
+ m68k->remaining_cycles -= shift<<m68k->cyc_shift;
+
+ *r_dst = MASK_OUT_BELOW_8(*r_dst) | res;
+
+ m68k->x_flag = m68k->c_flag = src << shift;
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ src &= m68ki_shift_8_table[shift + 1];
+ m68k->v_flag = (!(src == 0 || (src == m68ki_shift_8_table[shift + 1] && shift < 8)))<<7;
+}
+
+
+M68KMAKE_OP(asl, 16, s, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 shift = (((m68k->ir >> 9) - 1) & 7) + 1;
+ UINT32 src = MASK_OUT_ABOVE_16(*r_dst);
+ UINT32 res = MASK_OUT_ABOVE_16(src << shift);
+
+ if(shift != 0)
+ m68k->remaining_cycles -= shift<<m68k->cyc_shift;
+
+ *r_dst = MASK_OUT_BELOW_16(*r_dst) | res;
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->x_flag = m68k->c_flag = src >> (8-shift);
+ src &= m68ki_shift_16_table[shift + 1];
+ m68k->v_flag = (!(src == 0 || src == m68ki_shift_16_table[shift + 1]))<<7;
+}
+
+
+M68KMAKE_OP(asl, 32, s, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 shift = (((m68k->ir >> 9) - 1) & 7) + 1;
+ UINT32 src = *r_dst;
+ UINT32 res = MASK_OUT_ABOVE_32(src << shift);
+
+ if(shift != 0)
+ m68k->remaining_cycles -= shift<<m68k->cyc_shift;
+
+ *r_dst = res;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->x_flag = m68k->c_flag = src >> (24-shift);
+ src &= m68ki_shift_32_table[shift + 1];
+ m68k->v_flag = (!(src == 0 || src == m68ki_shift_32_table[shift + 1]))<<7;
+}
+
+
+M68KMAKE_OP(asl, 8, r, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 shift = DX & 0x3f;
+ UINT32 src = MASK_OUT_ABOVE_8(*r_dst);
+ UINT32 res = MASK_OUT_ABOVE_8(src << shift);
+
+ if(shift != 0)
+ {
+ m68k->remaining_cycles -= shift<<m68k->cyc_shift;
+
+ if(shift < 8)
+ {
+ *r_dst = MASK_OUT_BELOW_8(*r_dst) | res;
+ m68k->x_flag = m68k->c_flag = src << shift;
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ src &= m68ki_shift_8_table[shift + 1];
+ m68k->v_flag = (!(src == 0 || src == m68ki_shift_8_table[shift + 1]))<<7;
+ return;
+ }
+
+ *r_dst &= 0xffffff00;
+ m68k->x_flag = m68k->c_flag = ((shift == 8 ? src & 1 : 0))<<8;
+ m68k->n_flag = NFLAG_CLEAR;
+ m68k->not_z_flag = ZFLAG_SET;
+ m68k->v_flag = (!(src == 0))<<7;
+ return;
+ }
+
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->n_flag = NFLAG_8(src);
+ m68k->not_z_flag = src;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(asl, 16, r, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 shift = DX & 0x3f;
+ UINT32 src = MASK_OUT_ABOVE_16(*r_dst);
+ UINT32 res = MASK_OUT_ABOVE_16(src << shift);
+
+ if(shift != 0)
+ {
+ m68k->remaining_cycles -= shift<<m68k->cyc_shift;
+
+ if(shift < 16)
+ {
+ *r_dst = MASK_OUT_BELOW_16(*r_dst) | res;
+ m68k->x_flag = m68k->c_flag = (src << shift) >> 8;
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ src &= m68ki_shift_16_table[shift + 1];
+ m68k->v_flag = (!(src == 0 || src == m68ki_shift_16_table[shift + 1]))<<7;
+ return;
+ }
+
+ *r_dst &= 0xffff0000;
+ m68k->x_flag = m68k->c_flag = ((shift == 16 ? src & 1 : 0))<<8;
+ m68k->n_flag = NFLAG_CLEAR;
+ m68k->not_z_flag = ZFLAG_SET;
+ m68k->v_flag = (!(src == 0))<<7;
+ return;
+ }
+
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->n_flag = NFLAG_16(src);
+ m68k->not_z_flag = src;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(asl, 32, r, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 shift = DX & 0x3f;
+ UINT32 src = *r_dst;
+ UINT32 res = MASK_OUT_ABOVE_32(src << shift);
+
+ if(shift != 0)
+ {
+ m68k->remaining_cycles -= shift<<m68k->cyc_shift;
+
+ if(shift < 32)
+ {
+ *r_dst = res;
+ m68k->x_flag = m68k->c_flag = (src >> (32 - shift)) << 8;
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ src &= m68ki_shift_32_table[shift + 1];
+ m68k->v_flag = (!(src == 0 || src == m68ki_shift_32_table[shift + 1]))<<7;
+ return;
+ }
+
+ *r_dst = 0;
+ m68k->x_flag = m68k->c_flag = ((shift == 32 ? src & 1 : 0))<<8;
+ m68k->n_flag = NFLAG_CLEAR;
+ m68k->not_z_flag = ZFLAG_SET;
+ m68k->v_flag = (!(src == 0))<<7;
+ return;
+ }
+
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->n_flag = NFLAG_32(src);
+ m68k->not_z_flag = src;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(asl, 16, ., .)
+{
+ UINT32 ea = M68KMAKE_GET_EA_AY_16;
+ UINT32 src = m68ki_read_16(m68k, ea);
+ UINT32 res = MASK_OUT_ABOVE_16(src << 1);
+
+ m68ki_write_16(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->x_flag = m68k->c_flag = src >> 7;
+ src &= 0xc000;
+ m68k->v_flag = (!(src == 0 || src == 0xc000))<<7;
+}
+
+
+M68KMAKE_OP(bcc, 8, ., .)
+{
+ if(M68KMAKE_CC)
+ {
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+ m68ki_branch_8(m68k, MASK_OUT_ABOVE_8(m68k->ir));
+ return;
+ }
+ m68k->remaining_cycles -= m68k->cyc_bcc_notake_b;
+}
+
+
+M68KMAKE_OP(bcc, 16, ., .)
+{
+ if(M68KMAKE_CC)
+ {
+ UINT32 offset = OPER_I_16(m68k);
+ REG_PC -= 2;
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+ m68ki_branch_16(m68k, offset);
+ return;
+ }
+ REG_PC += 2;
+ m68k->remaining_cycles -= m68k->cyc_bcc_notake_w;
+}
+
+
+M68KMAKE_OP(bcc, 32, ., .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ if(M68KMAKE_CC)
+ {
+ UINT32 offset = OPER_I_32(m68k);
+ REG_PC -= 4;
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+ m68ki_branch_32(m68k, offset);
+ return;
+ }
+ REG_PC += 4;
+ return;
+ }
+ else
+ {
+ if(M68KMAKE_CC)
+ {
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+ m68ki_branch_8(m68k, MASK_OUT_ABOVE_8(m68k->ir));
+ return;
+ }
+ m68k->remaining_cycles -= m68k->cyc_bcc_notake_b;
+ }
+}
+
+
+M68KMAKE_OP(bchg, 32, r, d)
+{
+ UINT32* r_dst = &DY;
+ UINT32 mask = 1 << (DX & 0x1f);
+
+ m68k->not_z_flag = *r_dst & mask;
+ *r_dst ^= mask;
+}
+
+
+M68KMAKE_OP(bchg, 8, r, .)
+{
+ UINT32 ea = M68KMAKE_GET_EA_AY_8;
+ UINT32 src = m68ki_read_8(m68k, ea);
+ UINT32 mask = 1 << (DX & 7);
+
+ m68k->not_z_flag = src & mask;
+ m68ki_write_8(m68k, ea, src ^ mask);
+}
+
+
+M68KMAKE_OP(bchg, 32, s, d)
+{
+ UINT32* r_dst = &DY;
+ UINT32 mask = 1 << (OPER_I_8(m68k) & 0x1f);
+
+ m68k->not_z_flag = *r_dst & mask;
+ *r_dst ^= mask;
+}
+
+
+M68KMAKE_OP(bchg, 8, s, .)
+{
+ UINT32 mask = 1 << (OPER_I_8(m68k) & 7);
+ UINT32 ea = M68KMAKE_GET_EA_AY_8;
+ UINT32 src = m68ki_read_8(m68k, ea);
+
+ m68k->not_z_flag = src & mask;
+ m68ki_write_8(m68k, ea, src ^ mask);
+}
+
+
+M68KMAKE_OP(bclr, 32, r, d)
+{
+ UINT32* r_dst = &DY;
+ UINT32 mask = 1 << (DX & 0x1f);
+
+ m68k->not_z_flag = *r_dst & mask;
+ *r_dst &= ~mask;
+}
+
+
+M68KMAKE_OP(bclr, 8, r, .)
+{
+ UINT32 ea = M68KMAKE_GET_EA_AY_8;
+ UINT32 src = m68ki_read_8(m68k, ea);
+ UINT32 mask = 1 << (DX & 7);
+
+ m68k->not_z_flag = src & mask;
+ m68ki_write_8(m68k, ea, src & ~mask);
+}
+
+
+M68KMAKE_OP(bclr, 32, s, d)
+{
+ UINT32* r_dst = &DY;
+ UINT32 mask = 1 << (OPER_I_8(m68k) & 0x1f);
+
+ m68k->not_z_flag = *r_dst & mask;
+ *r_dst &= ~mask;
+}
+
+
+M68KMAKE_OP(bclr, 8, s, .)
+{
+ UINT32 mask = 1 << (OPER_I_8(m68k) & 7);
+ UINT32 ea = M68KMAKE_GET_EA_AY_8;
+ UINT32 src = m68ki_read_8(m68k, ea);
+
+ m68k->not_z_flag = src & mask;
+ m68ki_write_8(m68k, ea, src & ~mask);
+}
+
+
+M68KMAKE_OP(bfchg, 32, ., d)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 word2 = OPER_I_16(m68k);
+ UINT32 offset = (word2>>6)&31;
+ UINT32 width = word2;
+ UINT32* data = &DY;
+ UINT64 mask;
+
+
+ if(BIT_B(word2))
+ offset = REG_D[offset&7];
+ if(BIT_5(word2))
+ width = REG_D[width&7];
+
+ offset &= 31;
+ width = ((width-1) & 31) + 1;
+
+ mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width));
+ mask = ROR_32(mask, offset);
+
+ m68k->n_flag = NFLAG_32(*data<<offset);
+ m68k->not_z_flag = *data & mask;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+
+ *data ^= mask;
+
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(bfchg, 32, ., .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 word2 = OPER_I_16(m68k);
+ INT32 offset = (word2>>6)&31;
+ UINT32 width = word2;
+ UINT32 mask_base;
+ UINT32 data_long;
+ UINT32 mask_long;
+ UINT32 data_byte = 0;
+ UINT32 mask_byte = 0;
+ UINT32 ea = M68KMAKE_GET_EA_AY_8;
+
+
+ if(BIT_B(word2))
+ offset = MAKE_INT_32(REG_D[offset&7]);
+ if(BIT_5(word2))
+ width = REG_D[width&7];
+
+ /* Offset is signed so we have to use ugly math =( */
+ ea += offset / 8;
+ offset %= 8;
+ if(offset < 0)
+ {
+ offset += 8;
+ ea--;
+ }
+ width = ((width-1) & 31) + 1;
+
+ mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width));
+ mask_long = mask_base >> offset;
+
+ data_long = m68ki_read_32(m68k, ea);
+ m68k->n_flag = NFLAG_32(data_long << offset);
+ m68k->not_z_flag = data_long & mask_long;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+
+ m68ki_write_32(m68k, ea, data_long ^ mask_long);
+
+ if((width + offset) > 32)
+ {
+ mask_byte = MASK_OUT_ABOVE_8(mask_base);
+ data_byte = m68ki_read_8(m68k, ea+4);
+ m68k->not_z_flag |= (data_byte & mask_byte);
+ m68ki_write_8(m68k, ea+4, data_byte ^ mask_byte);
+ }
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(bfclr, 32, ., d)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 word2 = OPER_I_16(m68k);
+ UINT32 offset = (word2>>6)&31;
+ UINT32 width = word2;
+ UINT32* data = &DY;
+ UINT64 mask;
+
+
+ if(BIT_B(word2))
+ offset = REG_D[offset&7];
+ if(BIT_5(word2))
+ width = REG_D[width&7];
+
+
+ offset &= 31;
+ width = ((width-1) & 31) + 1;
+
+
+ mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width));
+ mask = ROR_32(mask, offset);
+
+ m68k->n_flag = NFLAG_32(*data<<offset);
+ m68k->not_z_flag = *data & mask;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+
+ *data &= ~mask;
+
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(bfclr, 32, ., .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 word2 = OPER_I_16(m68k);
+ INT32 offset = (word2>>6)&31;
+ UINT32 width = word2;
+ UINT32 mask_base;
+ UINT32 data_long;
+ UINT32 mask_long;
+ UINT32 data_byte = 0;
+ UINT32 mask_byte = 0;
+ UINT32 ea = M68KMAKE_GET_EA_AY_8;
+
+
+ if(BIT_B(word2))
+ offset = MAKE_INT_32(REG_D[offset&7]);
+ if(BIT_5(word2))
+ width = REG_D[width&7];
+
+ /* Offset is signed so we have to use ugly math =( */
+ ea += offset / 8;
+ offset %= 8;
+ if(offset < 0)
+ {
+ offset += 8;
+ ea--;
+ }
+ width = ((width-1) & 31) + 1;
+
+ mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width));
+ mask_long = mask_base >> offset;
+
+ data_long = m68ki_read_32(m68k, ea);
+ m68k->n_flag = NFLAG_32(data_long << offset);
+ m68k->not_z_flag = data_long & mask_long;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+
+ m68ki_write_32(m68k, ea, data_long & ~mask_long);
+
+ if((width + offset) > 32)
+ {
+ mask_byte = MASK_OUT_ABOVE_8(mask_base);
+ data_byte = m68ki_read_8(m68k, ea+4);
+ m68k->not_z_flag |= (data_byte & mask_byte);
+ m68ki_write_8(m68k, ea+4, data_byte & ~mask_byte);
+ }
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(bfexts, 32, ., d)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 word2 = OPER_I_16(m68k);
+ UINT32 offset = (word2>>6)&31;
+ UINT32 width = word2;
+ UINT64 data = DY;
+
+
+ if(BIT_B(word2))
+ offset = REG_D[offset&7];
+ if(BIT_5(word2))
+ width = REG_D[width&7];
+
+ offset &= 31;
+ width = ((width-1) & 31) + 1;
+
+ data = ROL_32(data, offset);
+ m68k->n_flag = NFLAG_32(data);
+ data = MAKE_INT_32(data) >> (32 - width);
+
+ m68k->not_z_flag = data;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+
+ REG_D[(word2>>12)&7] = data;
+
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(bfexts, 32, ., .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 word2 = OPER_I_16(m68k);
+ INT32 offset = (word2>>6)&31;
+ UINT32 width = word2;
+ UINT32 data;
+ UINT32 ea = M68KMAKE_GET_EA_AY_8;
+
+
+ if(BIT_B(word2))
+ offset = MAKE_INT_32(REG_D[offset&7]);
+ if(BIT_5(word2))
+ width = REG_D[width&7];
+
+ if(BIT_B(word2))
+ {
+ /* Offset is signed so we have to use ugly math =( */
+ ea += offset / 8;
+ offset %= 8;
+ if(offset < 0)
+ {
+ offset += 8;
+ ea--;
+ }
+ }
+ width = ((width-1) & 31) + 1;
+
+ data = (offset+width) < 16 ? (m68ki_read_16(m68k, ea) << 16) : m68ki_read_32(m68k, ea);
+
+ data = MASK_OUT_ABOVE_32(data<<offset);
+
+ if((offset+width) > 32)
+ data |= (m68ki_read_8(m68k, ea+4) << offset) >> 8;
+
+ m68k->n_flag = NFLAG_32(data);
+ data = MAKE_INT_32(data) >> (32 - width);
+
+ m68k->not_z_flag = data;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+
+ REG_D[(word2 >> 12) & 7] = data;
+
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(bfextu, 32, ., d)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 word2 = OPER_I_16(m68k);
+ UINT32 offset = (word2>>6)&31;
+ UINT32 width = word2;
+ UINT64 data = DY;
+
+
+ if(BIT_B(word2))
+ offset = REG_D[offset&7];
+ if(BIT_5(word2))
+ width = REG_D[width&7];
+
+ offset &= 31;
+ width = ((width-1) & 31) + 1;
+
+ data = ROL_32(data, offset);
+ m68k->n_flag = NFLAG_32(data);
+ data >>= 32 - width;
+
+ m68k->not_z_flag = data;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+
+ REG_D[(word2>>12)&7] = data;
+
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(bfextu, 32, ., .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 word2 = OPER_I_16(m68k);
+ INT32 offset = (word2>>6)&31;
+ UINT32 width = word2;
+ UINT32 data;
+ UINT32 ea = M68KMAKE_GET_EA_AY_8;
+
+
+ if(BIT_B(word2))
+ offset = MAKE_INT_32(REG_D[offset&7]);
+ if(BIT_5(word2))
+ width = REG_D[width&7];
+
+ if(BIT_B(word2))
+ {
+ /* Offset is signed so we have to use ugly math =( */
+ ea += offset / 8;
+ offset %= 8;
+ if(offset < 0)
+ {
+ offset += 8;
+ ea--;
+ }
+ }
+ width = ((width-1) & 31) + 1;
+
+ data = (offset+width) < 16 ? (m68ki_read_16(m68k, ea) << 16) : m68ki_read_32(m68k, ea);
+ data = MASK_OUT_ABOVE_32(data<<offset);
+
+ if((offset+width) > 32)
+ data |= (m68ki_read_8(m68k, ea+4) << offset) >> 8;
+
+ m68k->n_flag = NFLAG_32(data);
+ data >>= (32 - width);
+
+ m68k->not_z_flag = data;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+
+ REG_D[(word2 >> 12) & 7] = data;
+
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(bfffo, 32, ., d)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 word2 = OPER_I_16(m68k);
+ UINT32 offset = (word2>>6)&31;
+ UINT32 width = word2;
+ UINT64 data = DY;
+ UINT32 bit;
+
+
+ if(BIT_B(word2))
+ offset = REG_D[offset&7];
+ if(BIT_5(word2))
+ width = REG_D[width&7];
+
+ offset &= 31;
+ width = ((width-1) & 31) + 1;
+
+ data = ROL_32(data, offset);
+ m68k->n_flag = NFLAG_32(data);
+ data >>= 32 - width;
+
+ m68k->not_z_flag = data;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+
+ for(bit = 1<<(width-1);bit && !(data & bit);bit>>= 1)
+ offset++;
+
+ REG_D[(word2>>12)&7] = offset;
+
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(bfffo, 32, ., .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 word2 = OPER_I_16(m68k);
+ INT32 offset = (word2>>6)&31;
+ INT32 local_offset;
+ UINT32 width = word2;
+ UINT32 data;
+ UINT32 bit;
+ UINT32 ea = M68KMAKE_GET_EA_AY_8;
+
+
+ if(BIT_B(word2))
+ offset = MAKE_INT_32(REG_D[offset&7]);
+ if(BIT_5(word2))
+ width = REG_D[width&7];
+
+ /* Offset is signed so we have to use ugly math =( */
+ ea += offset / 8;
+ local_offset = offset % 8;
+ if(local_offset < 0)
+ {
+ local_offset += 8;
+ ea--;
+ }
+ width = ((width-1) & 31) + 1;
+
+ data = (offset+width) < 16 ? (m68ki_read_16(m68k, ea) << 16) : m68ki_read_32(m68k, ea);
+ data = MASK_OUT_ABOVE_32(data<<local_offset);
+
+ if((local_offset+width) > 32)
+ data |= (m68ki_read_8(m68k, ea+4) << local_offset) >> 8;
+
+ m68k->n_flag = NFLAG_32(data);
+ data >>= (32 - width);
+
+ m68k->not_z_flag = data;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+
+ for(bit = 1<<(width-1);bit && !(data & bit);bit>>= 1)
+ offset++;
+
+ REG_D[(word2>>12)&7] = offset;
+
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(bfins, 32, ., d)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 word2 = OPER_I_16(m68k);
+ UINT32 offset = (word2>>6)&31;
+ UINT32 width = word2;
+ UINT32* data = &DY;
+ UINT64 mask;
+ UINT64 insert = REG_D[(word2>>12)&7];
+
+
+ if(BIT_B(word2))
+ offset = REG_D[offset&7];
+ if(BIT_5(word2))
+ width = REG_D[width&7];
+
+
+ offset &= 31;
+ width = ((width-1) & 31) + 1;
+
+
+ mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width));
+ mask = ROR_32(mask, offset);
+
+ insert = MASK_OUT_ABOVE_32(insert << (32 - width));
+ m68k->n_flag = NFLAG_32(insert);
+ m68k->not_z_flag = insert;
+ insert = ROR_32(insert, offset);
+
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+
+ *data &= ~mask;
+ *data |= insert;
+
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(bfins, 32, ., .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 word2 = OPER_I_16(m68k);
+ INT32 offset = (word2>>6)&31;
+ UINT32 width = word2;
+ UINT32 insert_base = REG_D[(word2>>12)&7];
+ UINT32 insert_long;
+ UINT32 insert_byte;
+ UINT32 mask_base;
+ UINT32 data_long;
+ UINT32 mask_long;
+ UINT32 data_byte = 0;
+ UINT32 mask_byte = 0;
+ UINT32 ea = M68KMAKE_GET_EA_AY_8;
+
+
+ if(BIT_B(word2))
+ offset = MAKE_INT_32(REG_D[offset&7]);
+ if(BIT_5(word2))
+ width = REG_D[width&7];
+
+ if(BIT_B(word2))
+ {
+ /* Offset is signed so we have to use ugly math =( */
+ ea += offset / 8;
+ offset %= 8;
+ if(offset < 0)
+ {
+ offset += 8;
+ ea--;
+ }
+ }
+ width = ((width-1) & 31) + 1;
+
+ mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width));
+ mask_long = mask_base >> offset;
+
+ insert_base = MASK_OUT_ABOVE_32(insert_base << (32 - width));
+ m68k->n_flag = NFLAG_32(insert_base);
+ m68k->not_z_flag = insert_base;
+ insert_long = insert_base >> offset;
+
+ data_long = (offset+width) < 16 ? (m68ki_read_16(m68k, ea) << 16) : m68ki_read_32(m68k, ea);
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+
+ if((width + offset) < 16)
+ {
+ m68ki_write_16(m68k, ea, ((data_long & ~mask_long) | insert_long) >> 16);
+ }
+ else
+ {
+ m68ki_write_32(m68k, ea, (data_long & ~mask_long) | insert_long);
+ }
+
+ if((width + offset) > 32)
+ {
+ mask_byte = MASK_OUT_ABOVE_8(mask_base);
+ insert_byte = MASK_OUT_ABOVE_8(insert_base);
+ data_byte = m68ki_read_8(m68k, ea+4);
+ m68k->not_z_flag |= (data_byte & mask_byte);
+ m68ki_write_8(m68k, ea+4, (data_byte & ~mask_byte) | insert_byte);
+ }
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(bfset, 32, ., d)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 word2 = OPER_I_16(m68k);
+ UINT32 offset = (word2>>6)&31;
+ UINT32 width = word2;
+ UINT32* data = &DY;
+ UINT64 mask;
+
+
+ if(BIT_B(word2))
+ offset = REG_D[offset&7];
+ if(BIT_5(word2))
+ width = REG_D[width&7];
+
+
+ offset &= 31;
+ width = ((width-1) & 31) + 1;
+
+
+ mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width));
+ mask = ROR_32(mask, offset);
+
+ m68k->n_flag = NFLAG_32(*data<<offset);
+ m68k->not_z_flag = *data & mask;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+
+ *data |= mask;
+
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(bfset, 32, ., .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 word2 = OPER_I_16(m68k);
+ INT32 offset = (word2>>6)&31;
+ UINT32 width = word2;
+ UINT32 mask_base;
+ UINT32 data_long;
+ UINT32 mask_long;
+ UINT32 data_byte = 0;
+ UINT32 mask_byte = 0;
+ UINT32 ea = M68KMAKE_GET_EA_AY_8;
+
+
+ if(BIT_B(word2))
+ offset = MAKE_INT_32(REG_D[offset&7]);
+ if(BIT_5(word2))
+ width = REG_D[width&7];
+
+ /* Offset is signed so we have to use ugly math =( */
+ ea += offset / 8;
+ offset %= 8;
+ if(offset < 0)
+ {
+ offset += 8;
+ ea--;
+ }
+ width = ((width-1) & 31) + 1;
+
+
+ mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width));
+ mask_long = mask_base >> offset;
+
+ data_long = m68ki_read_32(m68k, ea);
+ m68k->n_flag = NFLAG_32(data_long << offset);
+ m68k->not_z_flag = data_long & mask_long;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+
+ m68ki_write_32(m68k, ea, data_long | mask_long);
+
+ if((width + offset) > 32)
+ {
+ mask_byte = MASK_OUT_ABOVE_8(mask_base);
+ data_byte = m68ki_read_8(m68k, ea+4);
+ m68k->not_z_flag |= (data_byte & mask_byte);
+ m68ki_write_8(m68k, ea+4, data_byte | mask_byte);
+ }
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(bftst, 32, ., d)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 word2 = OPER_I_16(m68k);
+ UINT32 offset = (word2>>6)&31;
+ UINT32 width = word2;
+ UINT32* data = &DY;
+ UINT64 mask;
+
+
+ if(BIT_B(word2))
+ offset = REG_D[offset&7];
+ if(BIT_5(word2))
+ width = REG_D[width&7];
+
+
+ offset &= 31;
+ width = ((width-1) & 31) + 1;
+
+
+ mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width));
+ mask = ROR_32(mask, offset);
+
+ m68k->n_flag = NFLAG_32(*data<<offset);
+ m68k->not_z_flag = *data & mask;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(bftst, 32, ., .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 word2 = OPER_I_16(m68k);
+ INT32 offset = (word2>>6)&31;
+ UINT32 width = word2;
+ UINT32 mask_base;
+ UINT32 data_long;
+ UINT32 mask_long;
+ UINT32 data_byte = 0;
+ UINT32 mask_byte = 0;
+ UINT32 ea = M68KMAKE_GET_EA_AY_8;
+
+ if(BIT_B(word2))
+ offset = MAKE_INT_32(REG_D[offset&7]);
+ if(BIT_5(word2))
+ width = REG_D[width&7];
+
+ /* Offset is signed so we have to use ugly math =( */
+ ea += offset / 8;
+ offset %= 8;
+ if(offset < 0)
+ {
+ offset += 8;
+ ea--;
+ }
+ width = ((width-1) & 31) + 1;
+
+
+ mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width));
+ mask_long = mask_base >> offset;
+
+ data_long = m68ki_read_32(m68k, ea);
+ m68k->n_flag = ((data_long & (0x80000000 >> offset))<<offset)>>24;
+ m68k->not_z_flag = data_long & mask_long;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+
+ if((width + offset) > 32)
+ {
+ mask_byte = MASK_OUT_ABOVE_8(mask_base);
+ data_byte = m68ki_read_8(m68k, ea+4);
+ m68k->not_z_flag |= (data_byte & mask_byte);
+ }
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(bkpt, 0, ., .)
+{
+ if(CPU_TYPE_IS_010_PLUS(m68k->cpu_type))
+ {
+ if (m68k->bkpt_ack_callback != NULL)
+ (*m68k->bkpt_ack_callback)(m68k->device, CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type) ? m68k->ir & 7 : 0);
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(bra, 8, ., .)
+{
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+ m68ki_branch_8(m68k, MASK_OUT_ABOVE_8(m68k->ir));
+ if(REG_PC == REG_PPC && m68k->remaining_cycles > 0)
+ m68k->remaining_cycles = 0;
+}
+
+
+M68KMAKE_OP(bra, 16, ., .)
+{
+ UINT32 offset = OPER_I_16(m68k);
+ REG_PC -= 2;
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+ m68ki_branch_16(m68k, offset);
+ if(REG_PC == REG_PPC && m68k->remaining_cycles > 0)
+ m68k->remaining_cycles = 0;
+}
+
+
+M68KMAKE_OP(bra, 32, ., .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 offset = OPER_I_32(m68k);
+ REG_PC -= 4;
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+ m68ki_branch_32(m68k, offset);
+ if(REG_PC == REG_PPC && m68k->remaining_cycles > 0)
+ m68k->remaining_cycles = 0;
+ return;
+ }
+ else
+ {
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+ m68ki_branch_8(m68k, MASK_OUT_ABOVE_8(m68k->ir));
+ if(REG_PC == REG_PPC && m68k->remaining_cycles > 0)
+ m68k->remaining_cycles = 0;
+ }
+}
+
+
+M68KMAKE_OP(bset, 32, r, d)
+{
+ UINT32* r_dst = &DY;
+ UINT32 mask = 1 << (DX & 0x1f);
+
+ m68k->not_z_flag = *r_dst & mask;
+ *r_dst |= mask;
+}
+
+
+M68KMAKE_OP(bset, 8, r, .)
+{
+ UINT32 ea = M68KMAKE_GET_EA_AY_8;
+ UINT32 src = m68ki_read_8(m68k, ea);
+ UINT32 mask = 1 << (DX & 7);
+
+ m68k->not_z_flag = src & mask;
+ m68ki_write_8(m68k, ea, src | mask);
+}
+
+
+M68KMAKE_OP(bset, 32, s, d)
+{
+ UINT32* r_dst = &DY;
+ UINT32 mask = 1 << (OPER_I_8(m68k) & 0x1f);
+
+ m68k->not_z_flag = *r_dst & mask;
+ *r_dst |= mask;
+}
+
+
+M68KMAKE_OP(bset, 8, s, .)
+{
+ UINT32 mask = 1 << (OPER_I_8(m68k) & 7);
+ UINT32 ea = M68KMAKE_GET_EA_AY_8;
+ UINT32 src = m68ki_read_8(m68k, ea);
+
+ m68k->not_z_flag = src & mask;
+ m68ki_write_8(m68k, ea, src | mask);
+}
+
+
+M68KMAKE_OP(bsr, 8, ., .)
+{
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+ m68ki_push_32(m68k, REG_PC);
+ m68ki_branch_8(m68k, MASK_OUT_ABOVE_8(m68k->ir));
+}
+
+
+M68KMAKE_OP(bsr, 16, ., .)
+{
+ UINT32 offset = OPER_I_16(m68k);
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+ m68ki_push_32(m68k, REG_PC);
+ REG_PC -= 2;
+ m68ki_branch_16(m68k, offset);
+}
+
+
+M68KMAKE_OP(bsr, 32, ., .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 offset = OPER_I_32(m68k);
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+ m68ki_push_32(m68k, REG_PC);
+ REG_PC -= 4;
+ m68ki_branch_32(m68k, offset);
+ return;
+ }
+ else
+ {
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+ m68ki_push_32(m68k, REG_PC);
+ m68ki_branch_8(m68k, MASK_OUT_ABOVE_8(m68k->ir));
+ }
+}
+
+
+M68KMAKE_OP(btst, 32, r, d)
+{
+ m68k->not_z_flag = DY & (1 << (DX & 0x1f));
+}
+
+
+M68KMAKE_OP(btst, 8, r, .)
+{
+ m68k->not_z_flag = M68KMAKE_GET_OPER_AY_8 & (1 << (DX & 7));
+}
+
+
+M68KMAKE_OP(btst, 32, s, d)
+{
+ m68k->not_z_flag = DY & (1 << (OPER_I_8(m68k) & 0x1f));
+}
+
+
+M68KMAKE_OP(btst, 8, s, .)
+{
+ UINT32 bit = OPER_I_8(m68k) & 7;
+
+ m68k->not_z_flag = M68KMAKE_GET_OPER_AY_8 & (1 << bit);
+}
+
+
+M68KMAKE_OP(callm, 32, ., .)
+{
+ /* note: watch out for pcrelative modes */
+ if(CPU_TYPE_IS_020_VARIANT(m68k->cpu_type))
+ {
+ UINT32 ea = M68KMAKE_GET_EA_AY_32;
+
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+ REG_PC += 2;
+(void)ea; /* just to avoid an 'unused variable' warning */
+ logerror("%s at %08x: called unimplemented instruction %04x (callm)\n",
+ m68k->device->tag(), REG_PC - 2, m68k->ir);
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(cas, 8, ., .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 word2 = OPER_I_16(m68k);
+ UINT32 ea = M68KMAKE_GET_EA_AY_8;
+ UINT32 dest = m68ki_read_8(m68k, ea);
+ UINT32* compare = &REG_D[word2 & 7];
+ UINT32 res = dest - MASK_OUT_ABOVE_8(*compare);
+
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_8(res);
+ m68k->v_flag = VFLAG_SUB_8(*compare, dest, res);
+ m68k->c_flag = CFLAG_8(res);
+
+ if(COND_NE(m68k))
+ *compare = MASK_OUT_BELOW_8(*compare) | dest;
+ else
+ {
+ m68k->remaining_cycles -= 3;
+ m68ki_write_8(m68k, ea, MASK_OUT_ABOVE_8(REG_D[(word2 >> 6) & 7]));
+ }
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(cas, 16, ., .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 word2 = OPER_I_16(m68k);
+ UINT32 ea = M68KMAKE_GET_EA_AY_16;
+ UINT32 dest = m68ki_read_16(m68k, ea);
+ UINT32* compare = &REG_D[word2 & 7];
+ UINT32 res = dest - MASK_OUT_ABOVE_16(*compare);
+
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_16(res);
+ m68k->v_flag = VFLAG_SUB_16(*compare, dest, res);
+ m68k->c_flag = CFLAG_16(res);
+
+ if(COND_NE(m68k))
+ *compare = MASK_OUT_BELOW_16(*compare) | dest;
+ else
+ {
+ m68k->remaining_cycles -= 3;
+ m68ki_write_16(m68k, ea, MASK_OUT_ABOVE_16(REG_D[(word2 >> 6) & 7]));
+ }
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(cas, 32, ., .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 word2 = OPER_I_16(m68k);
+ UINT32 ea = M68KMAKE_GET_EA_AY_32;
+ UINT32 dest = m68ki_read_32(m68k, ea);
+ UINT32* compare = &REG_D[word2 & 7];
+ UINT32 res = dest - *compare;
+
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res);
+ m68k->v_flag = VFLAG_SUB_32(*compare, dest, res);
+ m68k->c_flag = CFLAG_SUB_32(*compare, dest, res);
+
+ if(COND_NE(m68k))
+ *compare = dest;
+ else
+ {
+ m68k->remaining_cycles -= 3;
+ m68ki_write_32(m68k, ea, REG_D[(word2 >> 6) & 7]);
+ }
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(cas2, 16, ., .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 word2 = OPER_I_32(m68k);
+ UINT32* compare1 = &REG_D[(word2 >> 16) & 7];
+ UINT32 ea1 = REG_DA[(word2 >> 28) & 15];
+ UINT32 dest1 = m68ki_read_16(m68k, ea1);
+ UINT32 res1 = dest1 - MASK_OUT_ABOVE_16(*compare1);
+ UINT32* compare2 = &REG_D[word2 & 7];
+ UINT32 ea2 = REG_DA[(word2 >> 12) & 15];
+ UINT32 dest2 = m68ki_read_16(m68k, ea2);
+ UINT32 res2;
+
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+ m68k->n_flag = NFLAG_16(res1);
+ m68k->not_z_flag = MASK_OUT_ABOVE_16(res1);
+ m68k->v_flag = VFLAG_SUB_16(*compare1, dest1, res1);
+ m68k->c_flag = CFLAG_16(res1);
+
+ if(COND_EQ(m68k))
+ {
+ res2 = dest2 - MASK_OUT_ABOVE_16(*compare2);
+
+ m68k->n_flag = NFLAG_16(res2);
+ m68k->not_z_flag = MASK_OUT_ABOVE_16(res2);
+ m68k->v_flag = VFLAG_SUB_16(*compare2, dest2, res2);
+ m68k->c_flag = CFLAG_16(res2);
+
+ if(COND_EQ(m68k))
+ {
+ m68k->remaining_cycles -= 3;
+ m68ki_write_16(m68k, ea1, REG_D[(word2 >> 22) & 7]);
+ m68ki_write_16(m68k, ea2, REG_D[(word2 >> 6) & 7]);
+ return;
+ }
+ }
+ *compare1 = BIT_1F(word2) ? MAKE_INT_16(dest1) : MASK_OUT_BELOW_16(*compare1) | dest1;
+ *compare2 = BIT_F(word2) ? MAKE_INT_16(dest2) : MASK_OUT_BELOW_16(*compare2) | dest2;
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(cas2, 32, ., .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 word2 = OPER_I_32(m68k);
+ UINT32* compare1 = &REG_D[(word2 >> 16) & 7];
+ UINT32 ea1 = REG_DA[(word2 >> 28) & 15];
+ UINT32 dest1 = m68ki_read_32(m68k, ea1);
+ UINT32 res1 = dest1 - *compare1;
+ UINT32* compare2 = &REG_D[word2 & 7];
+ UINT32 ea2 = REG_DA[(word2 >> 12) & 15];
+ UINT32 dest2 = m68ki_read_32(m68k, ea2);
+ UINT32 res2;
+
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+ m68k->n_flag = NFLAG_32(res1);
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res1);
+ m68k->v_flag = VFLAG_SUB_32(*compare1, dest1, res1);
+ m68k->c_flag = CFLAG_SUB_32(*compare1, dest1, res1);
+
+ if(COND_EQ(m68k))
+ {
+ res2 = dest2 - *compare2;
+
+ m68k->n_flag = NFLAG_32(res2);
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res2);
+ m68k->v_flag = VFLAG_SUB_32(*compare2, dest2, res2);
+ m68k->c_flag = CFLAG_SUB_32(*compare2, dest2, res2);
+
+ if(COND_EQ(m68k))
+ {
+ m68k->remaining_cycles -= 3;
+ m68ki_write_32(m68k, ea1, REG_D[(word2 >> 22) & 7]);
+ m68ki_write_32(m68k, ea2, REG_D[(word2 >> 6) & 7]);
+ return;
+ }
+ }
+ *compare1 = dest1;
+ *compare2 = dest2;
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(chk, 16, ., d)
+{
+ INT32 src = MAKE_INT_16(DX);
+ INT32 bound = MAKE_INT_16(DY);
+
+ m68k->not_z_flag = ZFLAG_16(src); /* Undocumented */
+ m68k->v_flag = VFLAG_CLEAR; /* Undocumented */
+ m68k->c_flag = CFLAG_CLEAR; /* Undocumented */
+
+ if(src >= 0 && src <= bound)
+ {
+ return;
+ }
+ m68k->n_flag = (src < 0)<<7;
+ m68ki_exception_trap(m68k, EXCEPTION_CHK);
+}
+
+
+M68KMAKE_OP(chk, 16, ., .)
+{
+ INT32 src = MAKE_INT_16(DX);
+ INT32 bound = MAKE_INT_16(M68KMAKE_GET_OPER_AY_16);
+
+ m68k->not_z_flag = ZFLAG_16(src); /* Undocumented */
+ m68k->v_flag = VFLAG_CLEAR; /* Undocumented */
+ m68k->c_flag = CFLAG_CLEAR; /* Undocumented */
+
+ if(src >= 0 && src <= bound)
+ {
+ return;
+ }
+ m68k->n_flag = (src < 0)<<7;
+ m68ki_exception_trap(m68k, EXCEPTION_CHK);
+}
+
+
+M68KMAKE_OP(chk, 32, ., d)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ INT32 src = MAKE_INT_32(DX);
+ INT32 bound = MAKE_INT_32(DY);
+
+ m68k->not_z_flag = ZFLAG_32(src); /* Undocumented */
+ m68k->v_flag = VFLAG_CLEAR; /* Undocumented */
+ m68k->c_flag = CFLAG_CLEAR; /* Undocumented */
+
+ if(src >= 0 && src <= bound)
+ {
+ return;
+ }
+ m68k->n_flag = (src < 0)<<7;
+ m68ki_exception_trap(m68k, EXCEPTION_CHK);
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(chk, 32, ., .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ INT32 src = MAKE_INT_32(DX);
+ INT32 bound = MAKE_INT_32(M68KMAKE_GET_OPER_AY_32);
+
+ m68k->not_z_flag = ZFLAG_32(src); /* Undocumented */
+ m68k->v_flag = VFLAG_CLEAR; /* Undocumented */
+ m68k->c_flag = CFLAG_CLEAR; /* Undocumented */
+
+ if(src >= 0 && src <= bound)
+ {
+ return;
+ }
+ m68k->n_flag = (src < 0)<<7;
+ m68ki_exception_trap(m68k, EXCEPTION_CHK);
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(chk2cmp2, 8, ., pcdi)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 word2 = OPER_I_16(m68k);
+ UINT32 compare = REG_DA[(word2 >> 12) & 15]&0xff;
+ UINT32 ea = EA_PCDI_8(m68k);
+ UINT32 lower_bound = m68ki_read_pcrel_8(m68k, ea);
+ UINT32 upper_bound = m68ki_read_pcrel_8(m68k, ea + 1);
+
+ if(!BIT_F(word2))
+ m68k->c_flag = MAKE_INT_8(compare) - MAKE_INT_8(lower_bound);
+ else
+ m68k->c_flag = compare - lower_bound;
+ m68k->not_z_flag = !((upper_bound==compare) | (lower_bound==compare));
+ if(COND_CS(m68k))
+ {
+ if(BIT_B(word2))
+ m68ki_exception_trap(m68k, EXCEPTION_CHK);
+ return;
+ }
+
+ m68k->c_flag = upper_bound - compare;
+ if(COND_CS(m68k) && BIT_B(word2))
+ m68ki_exception_trap(m68k, EXCEPTION_CHK);
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(chk2cmp2, 8, ., pcix)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 word2 = OPER_I_16(m68k);
+ UINT32 compare = REG_DA[(word2 >> 12) & 15]&0xff;
+ UINT32 ea = EA_PCIX_8(m68k);
+ UINT32 lower_bound = m68ki_read_pcrel_8(m68k, ea);
+ UINT32 upper_bound = m68ki_read_pcrel_8(m68k, ea + 1);
+
+ if(!BIT_F(word2))
+ m68k->c_flag = MAKE_INT_8(compare) - MAKE_INT_8(lower_bound);
+ else
+ m68k->c_flag = compare - lower_bound;
+ m68k->not_z_flag = !((upper_bound==compare) | (lower_bound==compare));
+ if(COND_CS(m68k))
+ {
+ if(BIT_B(word2))
+ m68ki_exception_trap(m68k, EXCEPTION_CHK);
+ return;
+ }
+
+ m68k->c_flag = upper_bound - compare;
+ if(COND_CS(m68k) && BIT_B(word2))
+ m68ki_exception_trap(m68k, EXCEPTION_CHK);
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(chk2cmp2, 8, ., .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 word2 = OPER_I_16(m68k);
+ UINT32 compare = REG_DA[(word2 >> 12) & 15]&0xff;
+ UINT32 ea = M68KMAKE_GET_EA_AY_8;
+ UINT32 lower_bound = m68ki_read_8(m68k, ea);
+ UINT32 upper_bound = m68ki_read_8(m68k, ea + 1);
+
+ if(!BIT_F(word2))
+ m68k->c_flag = MAKE_INT_8(compare) - MAKE_INT_8(lower_bound);
+ else
+ m68k->c_flag = compare - lower_bound;
+ m68k->not_z_flag = !((upper_bound==compare) | (lower_bound==compare));
+ if(COND_CS(m68k))
+ {
+ if(BIT_B(word2))
+ m68ki_exception_trap(m68k, EXCEPTION_CHK);
+ return;
+ }
+
+ m68k->c_flag = upper_bound - compare;
+ if(COND_CS(m68k) && BIT_B(word2))
+ m68ki_exception_trap(m68k, EXCEPTION_CHK);
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(chk2cmp2, 16, ., pcdi)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 word2 = OPER_I_16(m68k);
+ UINT32 compare = REG_DA[(word2 >> 12) & 15]&0xffff;
+ UINT32 ea = EA_PCDI_16(m68k);
+ UINT32 lower_bound = m68ki_read_pcrel_16(m68k, ea);
+ UINT32 upper_bound = m68ki_read_pcrel_16(m68k, ea + 2);
+
+ if(!BIT_F(word2))
+ m68k->c_flag = MAKE_INT_16(compare) - MAKE_INT_16(lower_bound);
+ else
+ m68k->c_flag = compare - lower_bound;
+ m68k->not_z_flag = !((upper_bound==compare) | (lower_bound==compare));
+ m68k->c_flag = CFLAG_16(m68k->c_flag);
+ if(COND_CS(m68k))
+ {
+ if(BIT_B(word2))
+ m68ki_exception_trap(m68k, EXCEPTION_CHK);
+ return;
+ }
+
+ if(!BIT_F(word2))
+ m68k->c_flag = MAKE_INT_16(upper_bound) - MAKE_INT_16(compare);
+ else
+ m68k->c_flag = upper_bound - compare;
+ m68k->c_flag = CFLAG_16(m68k->c_flag);
+ if(COND_CS(m68k) && BIT_B(word2))
+ m68ki_exception_trap(m68k, EXCEPTION_CHK);
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(chk2cmp2, 16, ., pcix)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 word2 = OPER_I_16(m68k);
+ UINT32 compare = REG_DA[(word2 >> 12) & 15]&0xffff;
+ UINT32 ea = EA_PCIX_16(m68k);
+ UINT32 lower_bound = m68ki_read_pcrel_16(m68k, ea);
+ UINT32 upper_bound = m68ki_read_pcrel_16(m68k, ea + 2);
+
+ if(!BIT_F(word2))
+ m68k->c_flag = MAKE_INT_16(compare) - MAKE_INT_16(lower_bound);
+ else
+ m68k->c_flag = compare - lower_bound;
+ m68k->not_z_flag = !((upper_bound==compare) | (lower_bound==compare));
+ m68k->c_flag = CFLAG_16(m68k->c_flag);
+ if(COND_CS(m68k))
+ {
+ if(BIT_B(word2))
+ m68ki_exception_trap(m68k, EXCEPTION_CHK);
+ return;
+ }
+
+ if(!BIT_F(word2))
+ m68k->c_flag = MAKE_INT_16(upper_bound) - MAKE_INT_16(compare);
+ else
+ m68k->c_flag = upper_bound - compare;
+ m68k->c_flag = CFLAG_16(m68k->c_flag);
+ if(COND_CS(m68k) && BIT_B(word2))
+ m68ki_exception_trap(m68k, EXCEPTION_CHK);
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(chk2cmp2, 16, ., .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 word2 = OPER_I_16(m68k);
+ UINT32 compare = REG_DA[(word2 >> 12) & 15]&0xffff;
+ UINT32 ea = M68KMAKE_GET_EA_AY_16;
+ UINT32 lower_bound = m68ki_read_16(m68k, ea);
+ UINT32 upper_bound = m68ki_read_16(m68k, ea + 2);
+
+ if(!BIT_F(word2))
+ m68k->c_flag = MAKE_INT_16(compare) - MAKE_INT_16(lower_bound);
+ else
+ m68k->c_flag = compare - lower_bound;
+
+ m68k->not_z_flag = !((upper_bound==compare) | (lower_bound==compare));
+ m68k->c_flag = CFLAG_16(m68k->c_flag);
+ if(COND_CS(m68k))
+ {
+ if(BIT_B(word2))
+ m68ki_exception_trap(m68k, EXCEPTION_CHK);
+ return;
+ }
+ if(!BIT_F(word2))
+ m68k->c_flag = MAKE_INT_16(upper_bound) - MAKE_INT_16(compare);
+ else
+ m68k->c_flag = upper_bound - compare;
+
+ m68k->c_flag = CFLAG_16(m68k->c_flag);
+ if(COND_CS(m68k) && BIT_B(word2))
+ m68ki_exception_trap(m68k, EXCEPTION_CHK);
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(chk2cmp2, 32, ., pcdi)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 word2 = OPER_I_16(m68k);
+ UINT32 compare = REG_DA[(word2 >> 12) & 15];
+ UINT32 ea = EA_PCDI_32(m68k);
+ UINT32 lower_bound = m68ki_read_pcrel_32(m68k, ea);
+ UINT32 upper_bound = m68ki_read_pcrel_32(m68k, ea + 4);
+
+ m68k->c_flag = compare - lower_bound;
+ m68k->not_z_flag = !((upper_bound==compare) | (lower_bound==compare));
+ m68k->c_flag = CFLAG_SUB_32(lower_bound, compare, m68k->c_flag);
+ if(COND_CS(m68k))
+ {
+ if(BIT_B(word2))
+ m68ki_exception_trap(m68k, EXCEPTION_CHK);
+ return;
+ }
+
+ m68k->c_flag = upper_bound - compare;
+ m68k->c_flag = CFLAG_SUB_32(compare, upper_bound, m68k->c_flag);
+ if(COND_CS(m68k) && BIT_B(word2))
+ m68ki_exception_trap(m68k, EXCEPTION_CHK);
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(chk2cmp2, 32, ., pcix)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 word2 = OPER_I_16(m68k);
+ UINT32 compare = REG_DA[(word2 >> 12) & 15];
+ UINT32 ea = EA_PCIX_32(m68k);
+ UINT32 lower_bound = m68ki_read_pcrel_32(m68k, ea);
+ UINT32 upper_bound = m68ki_read_pcrel_32(m68k, ea + 4);
+
+ m68k->c_flag = compare - lower_bound;
+ m68k->not_z_flag = !((upper_bound==compare) | (lower_bound==compare));
+ m68k->c_flag = CFLAG_SUB_32(lower_bound, compare, m68k->c_flag);
+ if(COND_CS(m68k))
+ {
+ if(BIT_B(word2))
+ m68ki_exception_trap(m68k, EXCEPTION_CHK);
+ return;
+ }
+
+ m68k->c_flag = upper_bound - compare;
+ m68k->c_flag = CFLAG_SUB_32(compare, upper_bound, m68k->c_flag);
+ if(COND_CS(m68k) && BIT_B(word2))
+ m68ki_exception_trap(m68k, EXCEPTION_CHK);
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(chk2cmp2, 32, ., .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 word2 = OPER_I_16(m68k);
+ UINT32 compare = REG_DA[(word2 >> 12) & 15];
+ UINT32 ea = M68KMAKE_GET_EA_AY_32;
+ UINT32 lower_bound = m68ki_read_32(m68k, ea);
+ UINT32 upper_bound = m68ki_read_32(m68k, ea + 4);
+
+ m68k->c_flag = compare - lower_bound;
+ m68k->not_z_flag = !((upper_bound==compare) | (lower_bound==compare));
+ m68k->c_flag = CFLAG_SUB_32(lower_bound, compare, m68k->c_flag);
+ if(COND_CS(m68k))
+ {
+ if(BIT_B(word2))
+ m68ki_exception_trap(m68k, EXCEPTION_CHK);
+ return;
+ }
+
+ m68k->c_flag = upper_bound - compare;
+ m68k->c_flag = CFLAG_SUB_32(compare, upper_bound, m68k->c_flag);
+ if(COND_CS(m68k) && BIT_B(word2))
+ m68ki_exception_trap(m68k, EXCEPTION_CHK);
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(clr, 8, ., d)
+{
+ DY &= 0xffffff00;
+
+ m68k->n_flag = NFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->not_z_flag = ZFLAG_SET;
+}
+
+
+M68KMAKE_OP(clr, 8, ., .)
+{
+ m68ki_write_8(m68k, M68KMAKE_GET_EA_AY_8, 0);
+
+ m68k->n_flag = NFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->not_z_flag = ZFLAG_SET;
+}
+
+
+M68KMAKE_OP(clr, 16, ., d)
+{
+ DY &= 0xffff0000;
+
+ m68k->n_flag = NFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->not_z_flag = ZFLAG_SET;
+}
+
+
+M68KMAKE_OP(clr, 16, ., .)
+{
+ m68ki_write_16(m68k, M68KMAKE_GET_EA_AY_16, 0);
+
+ m68k->n_flag = NFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->not_z_flag = ZFLAG_SET;
+}
+
+
+M68KMAKE_OP(clr, 32, ., d)
+{
+ DY = 0;
+
+ m68k->n_flag = NFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->not_z_flag = ZFLAG_SET;
+}
+
+
+M68KMAKE_OP(clr, 32, ., .)
+{
+ m68ki_write_32(m68k, M68KMAKE_GET_EA_AY_32, 0);
+
+ m68k->n_flag = NFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->not_z_flag = ZFLAG_SET;
+}
+
+
+M68KMAKE_OP(cmp, 8, ., d)
+{
+ UINT32 src = MASK_OUT_ABOVE_8(DY);
+ UINT32 dst = MASK_OUT_ABOVE_8(DX);
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_8(res);
+ m68k->v_flag = VFLAG_SUB_8(src, dst, res);
+ m68k->c_flag = CFLAG_8(res);
+}
+
+
+M68KMAKE_OP(cmp, 8, ., .)
+{
+ UINT32 src = M68KMAKE_GET_OPER_AY_8;
+ UINT32 dst = MASK_OUT_ABOVE_8(DX);
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_8(res);
+ m68k->v_flag = VFLAG_SUB_8(src, dst, res);
+ m68k->c_flag = CFLAG_8(res);
+}
+
+
+M68KMAKE_OP(cmp, 16, ., d)
+{
+ UINT32 src = MASK_OUT_ABOVE_16(DY);
+ UINT32 dst = MASK_OUT_ABOVE_16(DX);
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_16(res);
+ m68k->v_flag = VFLAG_SUB_16(src, dst, res);
+ m68k->c_flag = CFLAG_16(res);
+}
+
+
+M68KMAKE_OP(cmp, 16, ., a)
+{
+ UINT32 src = MASK_OUT_ABOVE_16(AY);
+ UINT32 dst = MASK_OUT_ABOVE_16(DX);
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_16(res);
+ m68k->v_flag = VFLAG_SUB_16(src, dst, res);
+ m68k->c_flag = CFLAG_16(res);
+}
+
+
+M68KMAKE_OP(cmp, 16, ., .)
+{
+ UINT32 src = M68KMAKE_GET_OPER_AY_16;
+ UINT32 dst = MASK_OUT_ABOVE_16(DX);
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_16(res);
+ m68k->v_flag = VFLAG_SUB_16(src, dst, res);
+ m68k->c_flag = CFLAG_16(res);
+}
+
+
+M68KMAKE_OP(cmp, 32, ., d)
+{
+ UINT32 src = DY;
+ UINT32 dst = DX;
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res);
+ m68k->v_flag = VFLAG_SUB_32(src, dst, res);
+ m68k->c_flag = CFLAG_SUB_32(src, dst, res);
+}
+
+
+M68KMAKE_OP(cmp, 32, ., a)
+{
+ UINT32 src = AY;
+ UINT32 dst = DX;
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res);
+ m68k->v_flag = VFLAG_SUB_32(src, dst, res);
+ m68k->c_flag = CFLAG_SUB_32(src, dst, res);
+}
+
+
+M68KMAKE_OP(cmp, 32, ., .)
+{
+ UINT32 src = M68KMAKE_GET_OPER_AY_32;
+ UINT32 dst = DX;
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res);
+ m68k->v_flag = VFLAG_SUB_32(src, dst, res);
+ m68k->c_flag = CFLAG_SUB_32(src, dst, res);
+}
+
+
+M68KMAKE_OP(cmpa, 16, ., d)
+{
+ UINT32 src = MAKE_INT_16(DY);
+ UINT32 dst = AX;
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res);
+ m68k->v_flag = VFLAG_SUB_32(src, dst, res);
+ m68k->c_flag = CFLAG_SUB_32(src, dst, res);
+}
+
+
+M68KMAKE_OP(cmpa, 16, ., a)
+{
+ UINT32 src = MAKE_INT_16(AY);
+ UINT32 dst = AX;
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res);
+ m68k->v_flag = VFLAG_SUB_32(src, dst, res);
+ m68k->c_flag = CFLAG_SUB_32(src, dst, res);
+}
+
+
+M68KMAKE_OP(cmpa, 16, ., .)
+{
+ UINT32 src = MAKE_INT_16(M68KMAKE_GET_OPER_AY_16);
+ UINT32 dst = AX;
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res);
+ m68k->v_flag = VFLAG_SUB_32(src, dst, res);
+ m68k->c_flag = CFLAG_SUB_32(src, dst, res);
+}
+
+
+M68KMAKE_OP(cmpa, 32, ., d)
+{
+ UINT32 src = DY;
+ UINT32 dst = AX;
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res);
+ m68k->v_flag = VFLAG_SUB_32(src, dst, res);
+ m68k->c_flag = CFLAG_SUB_32(src, dst, res);
+}
+
+
+M68KMAKE_OP(cmpa, 32, ., a)
+{
+ UINT32 src = AY;
+ UINT32 dst = AX;
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res);
+ m68k->v_flag = VFLAG_SUB_32(src, dst, res);
+ m68k->c_flag = CFLAG_SUB_32(src, dst, res);
+}
+
+
+M68KMAKE_OP(cmpa, 32, ., .)
+{
+ UINT32 src = M68KMAKE_GET_OPER_AY_32;
+ UINT32 dst = AX;
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res);
+ m68k->v_flag = VFLAG_SUB_32(src, dst, res);
+ m68k->c_flag = CFLAG_SUB_32(src, dst, res);
+}
+
+
+M68KMAKE_OP(cmpi, 8, ., d)
+{
+ UINT32 src = OPER_I_8(m68k);
+ UINT32 dst = MASK_OUT_ABOVE_8(DY);
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_8(res);
+ m68k->v_flag = VFLAG_SUB_8(src, dst, res);
+ m68k->c_flag = CFLAG_8(res);
+}
+
+
+M68KMAKE_OP(cmpi, 8, ., .)
+{
+ UINT32 src = OPER_I_8(m68k);
+ UINT32 dst = M68KMAKE_GET_OPER_AY_8;
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_8(res);
+ m68k->v_flag = VFLAG_SUB_8(src, dst, res);
+ m68k->c_flag = CFLAG_8(res);
+}
+
+
+M68KMAKE_OP(cmpi, 8, ., pcdi)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 src = OPER_I_8(m68k);
+ UINT32 dst = OPER_PCDI_8(m68k);
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_8(res);
+ m68k->v_flag = VFLAG_SUB_8(src, dst, res);
+ m68k->c_flag = CFLAG_8(res);
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(cmpi, 8, ., pcix)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 src = OPER_I_8(m68k);
+ UINT32 dst = OPER_PCIX_8(m68k);
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_8(res);
+ m68k->v_flag = VFLAG_SUB_8(src, dst, res);
+ m68k->c_flag = CFLAG_8(res);
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(cmpi, 16, ., d)
+{
+ UINT32 src = OPER_I_16(m68k);
+ UINT32 dst = MASK_OUT_ABOVE_16(DY);
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_16(res);
+ m68k->v_flag = VFLAG_SUB_16(src, dst, res);
+ m68k->c_flag = CFLAG_16(res);
+}
+
+
+M68KMAKE_OP(cmpi, 16, ., .)
+{
+ UINT32 src = OPER_I_16(m68k);
+ UINT32 dst = M68KMAKE_GET_OPER_AY_16;
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_16(res);
+ m68k->v_flag = VFLAG_SUB_16(src, dst, res);
+ m68k->c_flag = CFLAG_16(res);
+}
+
+
+M68KMAKE_OP(cmpi, 16, ., pcdi)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 src = OPER_I_16(m68k);
+ UINT32 dst = OPER_PCDI_16(m68k);
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_16(res);
+ m68k->v_flag = VFLAG_SUB_16(src, dst, res);
+ m68k->c_flag = CFLAG_16(res);
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(cmpi, 16, ., pcix)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 src = OPER_I_16(m68k);
+ UINT32 dst = OPER_PCIX_16(m68k);
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_16(res);
+ m68k->v_flag = VFLAG_SUB_16(src, dst, res);
+ m68k->c_flag = CFLAG_16(res);
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(cmpi, 32, ., d)
+{
+ UINT32 src = OPER_I_32(m68k);
+ UINT32 dst = DY;
+ UINT32 res = dst - src;
+
+ if (m68k->cmpild_instr_callback != NULL)
+ (*m68k->cmpild_instr_callback)(m68k->device, src, m68k->ir & 7);
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res);
+ m68k->v_flag = VFLAG_SUB_32(src, dst, res);
+ m68k->c_flag = CFLAG_SUB_32(src, dst, res);
+}
+
+
+M68KMAKE_OP(cmpi, 32, ., .)
+{
+ UINT32 src = OPER_I_32(m68k);
+ UINT32 dst = M68KMAKE_GET_OPER_AY_32;
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res);
+ m68k->v_flag = VFLAG_SUB_32(src, dst, res);
+ m68k->c_flag = CFLAG_SUB_32(src, dst, res);
+}
+
+
+M68KMAKE_OP(cmpi, 32, ., pcdi)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 src = OPER_I_32(m68k);
+ UINT32 dst = OPER_PCDI_32(m68k);
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res);
+ m68k->v_flag = VFLAG_SUB_32(src, dst, res);
+ m68k->c_flag = CFLAG_SUB_32(src, dst, res);
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(cmpi, 32, ., pcix)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 src = OPER_I_32(m68k);
+ UINT32 dst = OPER_PCIX_32(m68k);
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res);
+ m68k->v_flag = VFLAG_SUB_32(src, dst, res);
+ m68k->c_flag = CFLAG_SUB_32(src, dst, res);
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(cmpm, 8, ., ax7)
+{
+ UINT32 src = OPER_AY_PI_8(m68k);
+ UINT32 dst = OPER_A7_PI_8(m68k);
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_8(res);
+ m68k->v_flag = VFLAG_SUB_8(src, dst, res);
+ m68k->c_flag = CFLAG_8(res);
+}
+
+
+M68KMAKE_OP(cmpm, 8, ., ay7)
+{
+ UINT32 src = OPER_A7_PI_8(m68k);
+ UINT32 dst = OPER_AX_PI_8(m68k);
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_8(res);
+ m68k->v_flag = VFLAG_SUB_8(src, dst, res);
+ m68k->c_flag = CFLAG_8(res);
+}
+
+
+M68KMAKE_OP(cmpm, 8, ., axy7)
+{
+ UINT32 src = OPER_A7_PI_8(m68k);
+ UINT32 dst = OPER_A7_PI_8(m68k);
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_8(res);
+ m68k->v_flag = VFLAG_SUB_8(src, dst, res);
+ m68k->c_flag = CFLAG_8(res);
+}
+
+
+M68KMAKE_OP(cmpm, 8, ., .)
+{
+ UINT32 src = OPER_AY_PI_8(m68k);
+ UINT32 dst = OPER_AX_PI_8(m68k);
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_8(res);
+ m68k->v_flag = VFLAG_SUB_8(src, dst, res);
+ m68k->c_flag = CFLAG_8(res);
+}
+
+
+M68KMAKE_OP(cmpm, 16, ., .)
+{
+ UINT32 src = OPER_AY_PI_16(m68k);
+ UINT32 dst = OPER_AX_PI_16(m68k);
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_16(res);
+ m68k->v_flag = VFLAG_SUB_16(src, dst, res);
+ m68k->c_flag = CFLAG_16(res);
+}
+
+
+M68KMAKE_OP(cmpm, 32, ., .)
+{
+ UINT32 src = OPER_AY_PI_32(m68k);
+ UINT32 dst = OPER_AX_PI_32(m68k);
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res);
+ m68k->v_flag = VFLAG_SUB_32(src, dst, res);
+ m68k->c_flag = CFLAG_SUB_32(src, dst, res);
+}
+
+
+M68KMAKE_OP(cpbcc, 32, ., .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ logerror("%s at %08x: called unimplemented instruction %04x (cpbcc)\n",
+ m68k->device->tag(), REG_PC - 2, m68k->ir);
+ return;
+ }
+ m68ki_exception_1111(m68k);
+}
+
+
+M68KMAKE_OP(cpdbcc, 32, ., .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ logerror("%s at %08x: called unimplemented instruction %04x (cpdbcc)\n",
+ m68k->device->tag(), REG_PC - 2, m68k->ir);
+ return;
+ }
+ m68ki_exception_1111(m68k);
+}
+
+
+M68KMAKE_OP(cpgen, 32, ., .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ logerror("%s at %08x: called unimplemented instruction %04x (cpgen)\n",
+ m68k->device->tag(), REG_PC - 2, m68k->ir);
+ return;
+ }
+ m68ki_exception_1111(m68k);
+}
+
+
+M68KMAKE_OP(cpscc, 32, ., .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ logerror("%s at %08x: called unimplemented instruction %04x (cpscc)\n",
+ m68k->device->tag(), REG_PC - 2, m68k->ir);
+ return;
+ }
+ m68ki_exception_1111(m68k);
+}
+
+
+M68KMAKE_OP(cptrapcc, 32, ., .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ logerror("%s at %08x: called unimplemented instruction %04x (cptrapcc)\n",
+ m68k->device->tag(), REG_PC - 2, m68k->ir);
+ return;
+ }
+ m68ki_exception_1111(m68k);
+}
+
+
+M68KMAKE_OP(dbt, 16, ., .)
+{
+ REG_PC += 2;
+}
+
+
+M68KMAKE_OP(dbf, 16, ., .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 res = MASK_OUT_ABOVE_16(*r_dst - 1);
+
+ *r_dst = MASK_OUT_BELOW_16(*r_dst) | res;
+ if(res != 0xffff)
+ {
+ UINT32 offset = OPER_I_16(m68k);
+ REG_PC -= 2;
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+ m68ki_branch_16(m68k, offset);
+ m68k->remaining_cycles -= m68k->cyc_dbcc_f_noexp;
+ return;
+ }
+ REG_PC += 2;
+ m68k->remaining_cycles -= m68k->cyc_dbcc_f_exp;
+}
+
+
+M68KMAKE_OP(dbcc, 16, ., .)
+{
+ if(M68KMAKE_NOT_CC)
+ {
+ UINT32* r_dst = &DY;
+ UINT32 res = MASK_OUT_ABOVE_16(*r_dst - 1);
+
+ *r_dst = MASK_OUT_BELOW_16(*r_dst) | res;
+ if(res != 0xffff)
+ {
+ UINT32 offset = OPER_I_16(m68k);
+ REG_PC -= 2;
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+ m68ki_branch_16(m68k, offset);
+ m68k->remaining_cycles -= m68k->cyc_dbcc_f_noexp;
+ return;
+ }
+ REG_PC += 2;
+ m68k->remaining_cycles -= m68k->cyc_dbcc_f_exp;
+ return;
+ }
+ REG_PC += 2;
+}
+
+
+M68KMAKE_OP(divs, 16, ., d)
+{
+ UINT32* r_dst = &DX;
+ INT32 src = MAKE_INT_16(DY);
+ INT32 quotient;
+ INT32 remainder;
+
+ if(src != 0)
+ {
+ if((UINT32)*r_dst == 0x80000000 && src == -1)
+ {
+ m68k->not_z_flag = 0;
+ m68k->n_flag = NFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+ *r_dst = 0;
+ return;
+ }
+
+ quotient = MAKE_INT_32(*r_dst) / src;
+ remainder = MAKE_INT_32(*r_dst) % src;
+
+ if(quotient == MAKE_INT_16(quotient))
+ {
+ m68k->not_z_flag = quotient;
+ m68k->n_flag = NFLAG_16(quotient);
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+ *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16));
+ return;
+ }
+ m68k->v_flag = VFLAG_SET;
+ return;
+ }
+ m68ki_exception_trap(m68k, EXCEPTION_ZERO_DIVIDE);
+}
+
+
+M68KMAKE_OP(divs, 16, ., .)
+{
+ UINT32* r_dst = &DX;
+ INT32 src = MAKE_INT_16(M68KMAKE_GET_OPER_AY_16);
+ INT32 quotient;
+ INT32 remainder;
+
+ if(src != 0)
+ {
+ if((UINT32)*r_dst == 0x80000000 && src == -1)
+ {
+ m68k->not_z_flag = 0;
+ m68k->n_flag = NFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+ *r_dst = 0;
+ return;
+ }
+
+ quotient = MAKE_INT_32(*r_dst) / src;
+ remainder = MAKE_INT_32(*r_dst) % src;
+
+ if(quotient == MAKE_INT_16(quotient))
+ {
+ m68k->not_z_flag = quotient;
+ m68k->n_flag = NFLAG_16(quotient);
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+ *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16));
+ return;
+ }
+ m68k->v_flag = VFLAG_SET;
+ return;
+ }
+ m68ki_exception_trap(m68k, EXCEPTION_ZERO_DIVIDE);
+}
+
+
+M68KMAKE_OP(divu, 16, ., d)
+{
+ UINT32* r_dst = &DX;
+ UINT32 src = MASK_OUT_ABOVE_16(DY);
+
+ if(src != 0)
+ {
+ UINT32 quotient = *r_dst / src;
+ UINT32 remainder = *r_dst % src;
+
+ if(quotient < 0x10000)
+ {
+ m68k->not_z_flag = quotient;
+ m68k->n_flag = NFLAG_16(quotient);
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+ *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16));
+ return;
+ }
+ m68k->v_flag = VFLAG_SET;
+ return;
+ }
+ m68ki_exception_trap(m68k, EXCEPTION_ZERO_DIVIDE);
+}
+
+
+M68KMAKE_OP(divu, 16, ., .)
+{
+ UINT32* r_dst = &DX;
+ UINT32 src = M68KMAKE_GET_OPER_AY_16;
+
+ if(src != 0)
+ {
+ UINT32 quotient = *r_dst / src;
+ UINT32 remainder = *r_dst % src;
+
+ if(quotient < 0x10000)
+ {
+ m68k->not_z_flag = quotient;
+ m68k->n_flag = NFLAG_16(quotient);
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+ *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16));
+ return;
+ }
+ m68k->v_flag = VFLAG_SET;
+ return;
+ }
+ m68ki_exception_trap(m68k, EXCEPTION_ZERO_DIVIDE);
+}
+
+
+M68KMAKE_OP(divl, 32, ., d)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 word2 = OPER_I_16(m68k);
+ UINT64 divisor = DY;
+ UINT64 dividend = 0;
+ UINT64 quotient = 0;
+ UINT64 remainder = 0;
+
+ if(divisor != 0)
+ {
+ if(BIT_A(word2)) /* 64 bit */
+ {
+ dividend = REG_D[word2 & 7];
+ dividend <<= 32;
+ dividend |= REG_D[(word2 >> 12) & 7];
+
+ if(BIT_B(word2)) /* signed */
+ {
+ quotient = (UINT64)((INT64)dividend / (INT64)((INT32)divisor));
+ remainder = (UINT64)((INT64)dividend % (INT64)((INT32)divisor));
+ if((INT64)quotient != (INT64)((INT32)quotient))
+ {
+ m68k->v_flag = VFLAG_SET;
+ return;
+ }
+ }
+ else /* unsigned */
+ {
+ quotient = dividend / divisor;
+ if(quotient > 0xffffffff)
+ {
+ m68k->v_flag = VFLAG_SET;
+ return;
+ }
+ remainder = dividend % divisor;
+ }
+ }
+ else /* 32 bit */
+ {
+ dividend = REG_D[(word2 >> 12) & 7];
+ if(BIT_B(word2)) /* signed */
+ {
+ quotient = (UINT64)((INT64)((INT32)dividend) / (INT64)((INT32)divisor));
+ remainder = (UINT64)((INT64)((INT32)dividend) % (INT64)((INT32)divisor));
+ }
+ else /* unsigned */
+ {
+ quotient = dividend / divisor;
+ remainder = dividend % divisor;
+ }
+ }
+
+ REG_D[word2 & 7] = remainder;
+ REG_D[(word2 >> 12) & 7] = quotient;
+
+ m68k->n_flag = NFLAG_32(quotient);
+ m68k->not_z_flag = quotient;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+ return;
+ }
+ m68ki_exception_trap(m68k, EXCEPTION_ZERO_DIVIDE);
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(divl, 32, ., .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 word2 = OPER_I_16(m68k);
+ UINT64 divisor = M68KMAKE_GET_OPER_AY_32;
+ UINT64 dividend = 0;
+ UINT64 quotient = 0;
+ UINT64 remainder = 0;
+
+ if(divisor != 0)
+ {
+ if(BIT_A(word2)) /* 64 bit */
+ {
+ dividend = REG_D[word2 & 7];
+ dividend <<= 32;
+ dividend |= REG_D[(word2 >> 12) & 7];
+
+ if(BIT_B(word2)) /* signed */
+ {
+ quotient = (UINT64)((INT64)dividend / (INT64)((INT32)divisor));
+ remainder = (UINT64)((INT64)dividend % (INT64)((INT32)divisor));
+ if((INT64)quotient != (INT64)((INT32)quotient))
+ {
+ m68k->v_flag = VFLAG_SET;
+ return;
+ }
+ }
+ else /* unsigned */
+ {
+ quotient = dividend / divisor;
+ if(quotient > 0xffffffff)
+ {
+ m68k->v_flag = VFLAG_SET;
+ return;
+ }
+ remainder = dividend % divisor;
+ }
+ }
+ else /* 32 bit */
+ {
+ dividend = REG_D[(word2 >> 12) & 7];
+ if(BIT_B(word2)) /* signed */
+ {
+ quotient = (UINT64)((INT64)((INT32)dividend) / (INT64)((INT32)divisor));
+ remainder = (UINT64)((INT64)((INT32)dividend) % (INT64)((INT32)divisor));
+ }
+ else /* unsigned */
+ {
+ quotient = dividend / divisor;
+ remainder = dividend % divisor;
+ }
+ }
+
+ REG_D[word2 & 7] = remainder;
+ REG_D[(word2 >> 12) & 7] = quotient;
+
+ m68k->n_flag = NFLAG_32(quotient);
+ m68k->not_z_flag = quotient;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+ return;
+ }
+ m68ki_exception_trap(m68k, EXCEPTION_ZERO_DIVIDE);
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(eor, 8, ., d)
+{
+ UINT32 res = MASK_OUT_ABOVE_8(DY ^= MASK_OUT_ABOVE_8(DX));
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(eor, 8, ., .)
+{
+ UINT32 ea = M68KMAKE_GET_EA_AY_8;
+ UINT32 res = MASK_OUT_ABOVE_8(DX ^ m68ki_read_8(m68k, ea));
+
+ m68ki_write_8(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(eor, 16, ., d)
+{
+ UINT32 res = MASK_OUT_ABOVE_16(DY ^= MASK_OUT_ABOVE_16(DX));
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(eor, 16, ., .)
+{
+ UINT32 ea = M68KMAKE_GET_EA_AY_16;
+ UINT32 res = MASK_OUT_ABOVE_16(DX ^ m68ki_read_16(m68k, ea));
+
+ m68ki_write_16(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(eor, 32, ., d)
+{
+ UINT32 res = DY ^= DX;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(eor, 32, ., .)
+{
+ UINT32 ea = M68KMAKE_GET_EA_AY_32;
+ UINT32 res = DX ^ m68ki_read_32(m68k, ea);
+
+ m68ki_write_32(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(eori, 8, ., d)
+{
+ UINT32 res = MASK_OUT_ABOVE_8(DY ^= OPER_I_8(m68k));
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(eori, 8, ., .)
+{
+ UINT32 src = OPER_I_8(m68k);
+ UINT32 ea = M68KMAKE_GET_EA_AY_8;
+ UINT32 res = src ^ m68ki_read_8(m68k, ea);
+
+ m68ki_write_8(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(eori, 16, ., d)
+{
+ UINT32 res = MASK_OUT_ABOVE_16(DY ^= OPER_I_16(m68k));
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(eori, 16, ., .)
+{
+ UINT32 src = OPER_I_16(m68k);
+ UINT32 ea = M68KMAKE_GET_EA_AY_16;
+ UINT32 res = src ^ m68ki_read_16(m68k, ea);
+
+ m68ki_write_16(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(eori, 32, ., d)
+{
+ UINT32 res = DY ^= OPER_I_32(m68k);
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(eori, 32, ., .)
+{
+ UINT32 src = OPER_I_32(m68k);
+ UINT32 ea = M68KMAKE_GET_EA_AY_32;
+ UINT32 res = src ^ m68ki_read_32(m68k, ea);
+
+ m68ki_write_32(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(eori, 16, toc, .)
+{
+ m68ki_set_ccr(m68k, m68ki_get_ccr(m68k) ^ OPER_I_16(m68k));
+}
+
+
+M68KMAKE_OP(eori, 16, tos, .)
+{
+ if(m68k->s_flag)
+ {
+ UINT32 src = OPER_I_16(m68k);
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+ m68ki_set_sr(m68k, m68ki_get_sr(m68k) ^ src);
+ return;
+ }
+ m68ki_exception_privilege_violation(m68k);
+}
+
+
+M68KMAKE_OP(exg, 32, dd, .)
+{
+ UINT32* reg_a = &DX;
+ UINT32* reg_b = &DY;
+ UINT32 tmp = *reg_a;
+ *reg_a = *reg_b;
+ *reg_b = tmp;
+}
+
+
+M68KMAKE_OP(exg, 32, aa, .)
+{
+ UINT32* reg_a = &AX;
+ UINT32* reg_b = &AY;
+ UINT32 tmp = *reg_a;
+ *reg_a = *reg_b;
+ *reg_b = tmp;
+}
+
+
+M68KMAKE_OP(exg, 32, da, .)
+{
+ UINT32* reg_a = &DX;
+ UINT32* reg_b = &AY;
+ UINT32 tmp = *reg_a;
+ *reg_a = *reg_b;
+ *reg_b = tmp;
+}
+
+
+M68KMAKE_OP(ext, 16, ., .)
+{
+ UINT32* r_dst = &DY;
+
+ *r_dst = MASK_OUT_BELOW_16(*r_dst) | MASK_OUT_ABOVE_8(*r_dst) | (GET_MSB_8(*r_dst) ? 0xff00 : 0);
+
+ m68k->n_flag = NFLAG_16(*r_dst);
+ m68k->not_z_flag = MASK_OUT_ABOVE_16(*r_dst);
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(ext, 32, ., .)
+{
+ UINT32* r_dst = &DY;
+
+ *r_dst = MASK_OUT_ABOVE_16(*r_dst) | (GET_MSB_16(*r_dst) ? 0xffff0000 : 0);
+
+ m68k->n_flag = NFLAG_32(*r_dst);
+ m68k->not_z_flag = *r_dst;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(extb, 32, ., .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32* r_dst = &DY;
+
+ *r_dst = MASK_OUT_ABOVE_8(*r_dst) | (GET_MSB_8(*r_dst) ? 0xffffff00 : 0);
+
+ m68k->n_flag = NFLAG_32(*r_dst);
+ m68k->not_z_flag = *r_dst;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(illegal, 0, ., .)
+{
+ m68ki_exception_illegal(m68k);
+}
+
+M68KMAKE_OP(jmp, 32, ., .)
+{
+ m68ki_jump(m68k, M68KMAKE_GET_EA_AY_32);
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+ if(REG_PC == REG_PPC && m68k->remaining_cycles > 0)
+ m68k->remaining_cycles = 0;
+}
+
+
+M68KMAKE_OP(jsr, 32, ., .)
+{
+ UINT32 ea = M68KMAKE_GET_EA_AY_32;
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+ m68ki_push_32(m68k, REG_PC);
+ m68ki_jump(m68k, ea);
+}
+
+
+M68KMAKE_OP(lea, 32, ., .)
+{
+ AX = M68KMAKE_GET_EA_AY_32;
+}
+
+
+M68KMAKE_OP(link, 16, ., a7)
+{
+ REG_A[7] -= 4;
+ m68ki_write_32(m68k, REG_A[7], REG_A[7]);
+ REG_A[7] = MASK_OUT_ABOVE_32(REG_A[7] + MAKE_INT_16(OPER_I_16(m68k)));
+}
+
+
+M68KMAKE_OP(link, 16, ., .)
+{
+ UINT32* r_dst = &AY;
+
+ m68ki_push_32(m68k, *r_dst);
+ *r_dst = REG_A[7];
+ REG_A[7] = MASK_OUT_ABOVE_32(REG_A[7] + MAKE_INT_16(OPER_I_16(m68k)));
+}
+
+
+M68KMAKE_OP(link, 32, ., a7)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ REG_A[7] -= 4;
+ m68ki_write_32(m68k, REG_A[7], REG_A[7]);
+ REG_A[7] = MASK_OUT_ABOVE_32(REG_A[7] + OPER_I_32(m68k));
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(link, 32, ., .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32* r_dst = &AY;
+
+ m68ki_push_32(m68k, *r_dst);
+ *r_dst = REG_A[7];
+ REG_A[7] = MASK_OUT_ABOVE_32(REG_A[7] + OPER_I_32(m68k));
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(lsr, 8, s, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 shift = (((m68k->ir >> 9) - 1) & 7) + 1;
+ UINT32 src = MASK_OUT_ABOVE_8(*r_dst);
+ UINT32 res = src >> shift;
+
+ if(shift != 0)
+ m68k->remaining_cycles -= shift<<m68k->cyc_shift;
+
+ *r_dst = MASK_OUT_BELOW_8(*r_dst) | res;
+
+ m68k->n_flag = NFLAG_CLEAR;
+ m68k->not_z_flag = res;
+ m68k->x_flag = m68k->c_flag = src << (9-shift);
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(lsr, 16, s, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 shift = (((m68k->ir >> 9) - 1) & 7) + 1;
+ UINT32 src = MASK_OUT_ABOVE_16(*r_dst);
+ UINT32 res = src >> shift;
+
+ if(shift != 0)
+ m68k->remaining_cycles -= shift<<m68k->cyc_shift;
+
+ *r_dst = MASK_OUT_BELOW_16(*r_dst) | res;
+
+ m68k->n_flag = NFLAG_CLEAR;
+ m68k->not_z_flag = res;
+ m68k->x_flag = m68k->c_flag = src << (9-shift);
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(lsr, 32, s, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 shift = (((m68k->ir >> 9) - 1) & 7) + 1;
+ UINT32 src = *r_dst;
+ UINT32 res = src >> shift;
+
+ if(shift != 0)
+ m68k->remaining_cycles -= shift<<m68k->cyc_shift;
+
+ *r_dst = res;
+
+ m68k->n_flag = NFLAG_CLEAR;
+ m68k->not_z_flag = res;
+ m68k->x_flag = m68k->c_flag = src << (9-shift);
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(lsr, 8, r, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 shift = DX & 0x3f;
+ UINT32 src = MASK_OUT_ABOVE_8(*r_dst);
+ UINT32 res = src >> shift;
+
+ if(shift != 0)
+ {
+ m68k->remaining_cycles -= shift<<m68k->cyc_shift;
+
+ if(shift <= 8)
+ {
+ *r_dst = MASK_OUT_BELOW_8(*r_dst) | res;
+ m68k->x_flag = m68k->c_flag = src << (9-shift);
+ m68k->n_flag = NFLAG_CLEAR;
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ return;
+ }
+
+ *r_dst &= 0xffffff00;
+ m68k->x_flag = XFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->n_flag = NFLAG_CLEAR;
+ m68k->not_z_flag = ZFLAG_SET;
+ m68k->v_flag = VFLAG_CLEAR;
+ return;
+ }
+
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->n_flag = NFLAG_8(src);
+ m68k->not_z_flag = src;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(lsr, 16, r, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 shift = DX & 0x3f;
+ UINT32 src = MASK_OUT_ABOVE_16(*r_dst);
+ UINT32 res = src >> shift;
+
+ if(shift != 0)
+ {
+ m68k->remaining_cycles -= shift<<m68k->cyc_shift;
+
+ if(shift <= 16)
+ {
+ *r_dst = MASK_OUT_BELOW_16(*r_dst) | res;
+ m68k->c_flag = m68k->x_flag = (src >> (shift - 1))<<8;
+ m68k->n_flag = NFLAG_CLEAR;
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ return;
+ }
+
+ *r_dst &= 0xffff0000;
+ m68k->x_flag = XFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->n_flag = NFLAG_CLEAR;
+ m68k->not_z_flag = ZFLAG_SET;
+ m68k->v_flag = VFLAG_CLEAR;
+ return;
+ }
+
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->n_flag = NFLAG_16(src);
+ m68k->not_z_flag = src;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(lsr, 32, r, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 shift = DX & 0x3f;
+ UINT32 src = *r_dst;
+ UINT32 res = src >> shift;
+
+ if(shift != 0)
+ {
+ m68k->remaining_cycles -= shift<<m68k->cyc_shift;
+
+ if(shift < 32)
+ {
+ *r_dst = res;
+ m68k->c_flag = m68k->x_flag = (src >> (shift - 1))<<8;
+ m68k->n_flag = NFLAG_CLEAR;
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ return;
+ }
+
+ *r_dst = 0;
+ m68k->x_flag = m68k->c_flag = (shift == 32 ? GET_MSB_32(src)>>23 : 0);
+ m68k->n_flag = NFLAG_CLEAR;
+ m68k->not_z_flag = ZFLAG_SET;
+ m68k->v_flag = VFLAG_CLEAR;
+ return;
+ }
+
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->n_flag = NFLAG_32(src);
+ m68k->not_z_flag = src;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(lsr, 16, ., .)
+{
+ UINT32 ea = M68KMAKE_GET_EA_AY_16;
+ UINT32 src = m68ki_read_16(m68k, ea);
+ UINT32 res = src >> 1;
+
+ m68ki_write_16(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_CLEAR;
+ m68k->not_z_flag = res;
+ m68k->c_flag = m68k->x_flag = src << 8;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(lsl, 8, s, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 shift = (((m68k->ir >> 9) - 1) & 7) + 1;
+ UINT32 src = MASK_OUT_ABOVE_8(*r_dst);
+ UINT32 res = MASK_OUT_ABOVE_8(src << shift);
+
+ if(shift != 0)
+ m68k->remaining_cycles -= shift<<m68k->cyc_shift;
+
+ *r_dst = MASK_OUT_BELOW_8(*r_dst) | res;
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->x_flag = m68k->c_flag = src << shift;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(lsl, 16, s, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 shift = (((m68k->ir >> 9) - 1) & 7) + 1;
+ UINT32 src = MASK_OUT_ABOVE_16(*r_dst);
+ UINT32 res = MASK_OUT_ABOVE_16(src << shift);
+
+ if(shift != 0)
+ m68k->remaining_cycles -= shift<<m68k->cyc_shift;
+
+ *r_dst = MASK_OUT_BELOW_16(*r_dst) | res;
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->x_flag = m68k->c_flag = src >> (8-shift);
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(lsl, 32, s, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 shift = (((m68k->ir >> 9) - 1) & 7) + 1;
+ UINT32 src = *r_dst;
+ UINT32 res = MASK_OUT_ABOVE_32(src << shift);
+
+ if(shift != 0)
+ m68k->remaining_cycles -= shift<<m68k->cyc_shift;
+
+ *r_dst = res;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->x_flag = m68k->c_flag = src >> (24-shift);
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(lsl, 8, r, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 shift = DX & 0x3f;
+ UINT32 src = MASK_OUT_ABOVE_8(*r_dst);
+ UINT32 res = MASK_OUT_ABOVE_8(src << shift);
+
+ if(shift != 0)
+ {
+ m68k->remaining_cycles -= shift<<m68k->cyc_shift;
+
+ if(shift <= 8)
+ {
+ *r_dst = MASK_OUT_BELOW_8(*r_dst) | res;
+ m68k->x_flag = m68k->c_flag = src << shift;
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ return;
+ }
+
+ *r_dst &= 0xffffff00;
+ m68k->x_flag = XFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->n_flag = NFLAG_CLEAR;
+ m68k->not_z_flag = ZFLAG_SET;
+ m68k->v_flag = VFLAG_CLEAR;
+ return;
+ }
+
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->n_flag = NFLAG_8(src);
+ m68k->not_z_flag = src;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(lsl, 16, r, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 shift = DX & 0x3f;
+ UINT32 src = MASK_OUT_ABOVE_16(*r_dst);
+ UINT32 res = MASK_OUT_ABOVE_16(src << shift);
+
+ if(shift != 0)
+ {
+ m68k->remaining_cycles -= shift<<m68k->cyc_shift;
+
+ if(shift <= 16)
+ {
+ *r_dst = MASK_OUT_BELOW_16(*r_dst) | res;
+ m68k->x_flag = m68k->c_flag = (src << shift) >> 8;
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ return;
+ }
+
+ *r_dst &= 0xffff0000;
+ m68k->x_flag = XFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->n_flag = NFLAG_CLEAR;
+ m68k->not_z_flag = ZFLAG_SET;
+ m68k->v_flag = VFLAG_CLEAR;
+ return;
+ }
+
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->n_flag = NFLAG_16(src);
+ m68k->not_z_flag = src;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(lsl, 32, r, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 shift = DX & 0x3f;
+ UINT32 src = *r_dst;
+ UINT32 res = MASK_OUT_ABOVE_32(src << shift);
+
+ if(shift != 0)
+ {
+ m68k->remaining_cycles -= shift<<m68k->cyc_shift;
+
+ if(shift < 32)
+ {
+ *r_dst = res;
+ m68k->x_flag = m68k->c_flag = (src >> (32 - shift)) << 8;
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ return;
+ }
+
+ *r_dst = 0;
+ m68k->x_flag = m68k->c_flag = ((shift == 32 ? src & 1 : 0))<<8;
+ m68k->n_flag = NFLAG_CLEAR;
+ m68k->not_z_flag = ZFLAG_SET;
+ m68k->v_flag = VFLAG_CLEAR;
+ return;
+ }
+
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->n_flag = NFLAG_32(src);
+ m68k->not_z_flag = src;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(lsl, 16, ., .)
+{
+ UINT32 ea = M68KMAKE_GET_EA_AY_16;
+ UINT32 src = m68ki_read_16(m68k, ea);
+ UINT32 res = MASK_OUT_ABOVE_16(src << 1);
+
+ m68ki_write_16(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->x_flag = m68k->c_flag = src >> 7;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 8, d, d)
+{
+ UINT32 res = MASK_OUT_ABOVE_8(DY);
+ UINT32* r_dst = &DX;
+
+ *r_dst = MASK_OUT_BELOW_8(*r_dst) | res;
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 8, d, .)
+{
+ UINT32 res = M68KMAKE_GET_OPER_AY_8;
+ UINT32* r_dst = &DX;
+
+ *r_dst = MASK_OUT_BELOW_8(*r_dst) | res;
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 8, ai, d)
+{
+ UINT32 res = MASK_OUT_ABOVE_8(DY);
+ UINT32 ea = EA_AX_AI_8(m68k);
+
+ m68ki_write_8(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 8, ai, .)
+{
+ UINT32 res = M68KMAKE_GET_OPER_AY_8;
+ UINT32 ea = EA_AX_AI_8(m68k);
+
+ m68ki_write_8(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 8, pi7, d)
+{
+ UINT32 res = MASK_OUT_ABOVE_8(DY);
+ UINT32 ea = EA_A7_PI_8(m68k);
+
+ m68ki_write_8(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 8, pi, d)
+{
+ UINT32 res = MASK_OUT_ABOVE_8(DY);
+ UINT32 ea = EA_AX_PI_8(m68k);
+
+ m68ki_write_8(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 8, pi7, .)
+{
+ UINT32 res = M68KMAKE_GET_OPER_AY_8;
+ UINT32 ea = EA_A7_PI_8(m68k);
+
+ m68ki_write_8(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 8, pi, .)
+{
+ UINT32 res = M68KMAKE_GET_OPER_AY_8;
+ UINT32 ea = EA_AX_PI_8(m68k);
+
+ m68ki_write_8(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 8, pd7, d)
+{
+ UINT32 res = MASK_OUT_ABOVE_8(DY);
+ UINT32 ea = EA_A7_PD_8(m68k);
+
+ m68ki_write_8(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 8, pd, d)
+{
+ UINT32 res = MASK_OUT_ABOVE_8(DY);
+ UINT32 ea = EA_AX_PD_8(m68k);
+
+ m68ki_write_8(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 8, pd7, .)
+{
+ UINT32 res = M68KMAKE_GET_OPER_AY_8;
+ UINT32 ea = EA_A7_PD_8(m68k);
+
+ m68ki_write_8(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 8, pd, .)
+{
+ UINT32 res = M68KMAKE_GET_OPER_AY_8;
+ UINT32 ea = EA_AX_PD_8(m68k);
+
+ m68ki_write_8(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 8, di, d)
+{
+ UINT32 res = MASK_OUT_ABOVE_8(DY);
+ UINT32 ea = EA_AX_DI_8(m68k);
+
+ m68ki_write_8(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 8, di, .)
+{
+ UINT32 res = M68KMAKE_GET_OPER_AY_8;
+ UINT32 ea = EA_AX_DI_8(m68k);
+
+ m68ki_write_8(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 8, ix, d)
+{
+ UINT32 res = MASK_OUT_ABOVE_8(DY);
+ UINT32 ea = EA_AX_IX_8(m68k);
+
+ m68ki_write_8(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 8, ix, .)
+{
+ UINT32 res = M68KMAKE_GET_OPER_AY_8;
+ UINT32 ea = EA_AX_IX_8(m68k);
+
+ m68ki_write_8(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 8, aw, d)
+{
+ UINT32 res = MASK_OUT_ABOVE_8(DY);
+ UINT32 ea = EA_AW_8(m68k);
+
+ m68ki_write_8(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 8, aw, .)
+{
+ UINT32 res = M68KMAKE_GET_OPER_AY_8;
+ UINT32 ea = EA_AW_8(m68k);
+
+ m68ki_write_8(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 8, al, d)
+{
+ UINT32 res = MASK_OUT_ABOVE_8(DY);
+ UINT32 ea = EA_AL_8(m68k);
+
+ m68ki_write_8(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 8, al, .)
+{
+ UINT32 res = M68KMAKE_GET_OPER_AY_8;
+ UINT32 ea = EA_AL_8(m68k);
+
+ m68ki_write_8(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 16, d, d)
+{
+ UINT32 res = MASK_OUT_ABOVE_16(DY);
+ UINT32* r_dst = &DX;
+
+ *r_dst = MASK_OUT_BELOW_16(*r_dst) | res;
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 16, d, a)
+{
+ UINT32 res = MASK_OUT_ABOVE_16(AY);
+ UINT32* r_dst = &DX;
+
+ *r_dst = MASK_OUT_BELOW_16(*r_dst) | res;
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 16, d, .)
+{
+ UINT32 res = M68KMAKE_GET_OPER_AY_16;
+ UINT32* r_dst = &DX;
+
+ *r_dst = MASK_OUT_BELOW_16(*r_dst) | res;
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 16, ai, d)
+{
+ UINT32 res = MASK_OUT_ABOVE_16(DY);
+ UINT32 ea = EA_AX_AI_16(m68k);
+
+ m68ki_write_16(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 16, ai, a)
+{
+ UINT32 res = MASK_OUT_ABOVE_16(AY);
+ UINT32 ea = EA_AX_AI_16(m68k);
+
+ m68ki_write_16(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 16, ai, .)
+{
+ UINT32 res = M68KMAKE_GET_OPER_AY_16;
+ UINT32 ea = EA_AX_AI_16(m68k);
+
+ m68ki_write_16(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 16, pi, d)
+{
+ UINT32 res = MASK_OUT_ABOVE_16(DY);
+ UINT32 ea = EA_AX_PI_16(m68k);
+
+ m68ki_write_16(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 16, pi, a)
+{
+ UINT32 res = MASK_OUT_ABOVE_16(AY);
+ UINT32 ea = EA_AX_PI_16(m68k);
+
+ m68ki_write_16(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 16, pi, .)
+{
+ UINT32 res = M68KMAKE_GET_OPER_AY_16;
+ UINT32 ea = EA_AX_PI_16(m68k);
+
+ m68ki_write_16(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 16, pd, d)
+{
+ UINT32 res = MASK_OUT_ABOVE_16(DY);
+ UINT32 ea = EA_AX_PD_16(m68k);
+
+ m68ki_write_16(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 16, pd, a)
+{
+ UINT32 res = MASK_OUT_ABOVE_16(AY);
+ UINT32 ea = EA_AX_PD_16(m68k);
+
+ m68ki_write_16(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 16, pd, .)
+{
+ UINT32 res = M68KMAKE_GET_OPER_AY_16;
+ UINT32 ea = EA_AX_PD_16(m68k);
+
+ m68ki_write_16(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 16, di, d)
+{
+ UINT32 res = MASK_OUT_ABOVE_16(DY);
+ UINT32 ea = EA_AX_DI_16(m68k);
+
+ m68ki_write_16(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 16, di, a)
+{
+ UINT32 res = MASK_OUT_ABOVE_16(AY);
+ UINT32 ea = EA_AX_DI_16(m68k);
+
+ m68ki_write_16(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 16, di, .)
+{
+ UINT32 res = M68KMAKE_GET_OPER_AY_16;
+ UINT32 ea = EA_AX_DI_16(m68k);
+
+ m68ki_write_16(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 16, ix, d)
+{
+ UINT32 res = MASK_OUT_ABOVE_16(DY);
+ UINT32 ea = EA_AX_IX_16(m68k);
+
+ m68ki_write_16(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 16, ix, a)
+{
+ UINT32 res = MASK_OUT_ABOVE_16(AY);
+ UINT32 ea = EA_AX_IX_16(m68k);
+
+ m68ki_write_16(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 16, ix, .)
+{
+ UINT32 res = M68KMAKE_GET_OPER_AY_16;
+ UINT32 ea = EA_AX_IX_16(m68k);
+
+ m68ki_write_16(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 16, aw, d)
+{
+ UINT32 res = MASK_OUT_ABOVE_16(DY);
+ UINT32 ea = EA_AW_16(m68k);
+
+ m68ki_write_16(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 16, aw, a)
+{
+ UINT32 res = MASK_OUT_ABOVE_16(AY);
+ UINT32 ea = EA_AW_16(m68k);
+
+ m68ki_write_16(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 16, aw, .)
+{
+ UINT32 res = M68KMAKE_GET_OPER_AY_16;
+ UINT32 ea = EA_AW_16(m68k);
+
+ m68ki_write_16(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 16, al, d)
+{
+ UINT32 res = MASK_OUT_ABOVE_16(DY);
+ UINT32 ea = EA_AL_16(m68k);
+
+ m68ki_write_16(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 16, al, a)
+{
+ UINT32 res = MASK_OUT_ABOVE_16(AY);
+ UINT32 ea = EA_AL_16(m68k);
+
+ m68ki_write_16(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 16, al, .)
+{
+ UINT32 res = M68KMAKE_GET_OPER_AY_16;
+ UINT32 ea = EA_AL_16(m68k);
+
+ m68ki_write_16(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 32, d, d)
+{
+ UINT32 res = DY;
+ UINT32* r_dst = &DX;
+
+ *r_dst = res;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 32, d, a)
+{
+ UINT32 res = AY;
+ UINT32* r_dst = &DX;
+
+ *r_dst = res;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 32, d, .)
+{
+ UINT32 res = M68KMAKE_GET_OPER_AY_32;
+ UINT32* r_dst = &DX;
+
+ *r_dst = res;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 32, ai, d)
+{
+ UINT32 res = DY;
+ UINT32 ea = EA_AX_AI_32(m68k);
+
+ m68ki_write_32(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 32, ai, a)
+{
+ UINT32 res = AY;
+ UINT32 ea = EA_AX_AI_32(m68k);
+
+ m68ki_write_32(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 32, ai, .)
+{
+ UINT32 res = M68KMAKE_GET_OPER_AY_32;
+ UINT32 ea = EA_AX_AI_32(m68k);
+
+ m68ki_write_32(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 32, pi, d)
+{
+ UINT32 res = DY;
+ UINT32 ea = EA_AX_PI_32(m68k);
+
+ m68ki_write_32(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 32, pi, a)
+{
+ UINT32 res = AY;
+ UINT32 ea = EA_AX_PI_32(m68k);
+
+ m68ki_write_32(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 32, pi, .)
+{
+ UINT32 res = M68KMAKE_GET_OPER_AY_32;
+ UINT32 ea = EA_AX_PI_32(m68k);
+
+ m68ki_write_32(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 32, pd, d)
+{
+ UINT32 res = DY;
+ UINT32 ea = EA_AX_PD_32(m68k);
+
+ m68ki_write_16(m68k, ea+2, res & 0xFFFF );
+ m68ki_write_16(m68k, ea, (res >> 16) & 0xFFFF );
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 32, pd, a)
+{
+ UINT32 res = AY;
+ UINT32 ea = EA_AX_PD_32(m68k);
+
+ m68ki_write_16(m68k, ea+2, res & 0xFFFF );
+ m68ki_write_16(m68k, ea, (res >> 16) & 0xFFFF );
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 32, pd, .)
+{
+ UINT32 res = M68KMAKE_GET_OPER_AY_32;
+ UINT32 ea = EA_AX_PD_32(m68k);
+
+ m68ki_write_16(m68k, ea+2, res & 0xFFFF );
+ m68ki_write_16(m68k, ea, (res >> 16) & 0xFFFF );
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 32, di, d)
+{
+ UINT32 res = DY;
+ UINT32 ea = EA_AX_DI_32(m68k);
+
+ m68ki_write_32(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 32, di, a)
+{
+ UINT32 res = AY;
+ UINT32 ea = EA_AX_DI_32(m68k);
+
+ m68ki_write_32(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 32, di, .)
+{
+ UINT32 res = M68KMAKE_GET_OPER_AY_32;
+ UINT32 ea = EA_AX_DI_32(m68k);
+
+ m68ki_write_32(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 32, ix, d)
+{
+ UINT32 res = DY;
+ UINT32 ea = EA_AX_IX_32(m68k);
+
+ m68ki_write_32(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 32, ix, a)
+{
+ UINT32 res = AY;
+ UINT32 ea = EA_AX_IX_32(m68k);
+
+ m68ki_write_32(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 32, ix, .)
+{
+ UINT32 res = M68KMAKE_GET_OPER_AY_32;
+ UINT32 ea = EA_AX_IX_32(m68k);
+
+ m68ki_write_32(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 32, aw, d)
+{
+ UINT32 res = DY;
+ UINT32 ea = EA_AW_32(m68k);
+
+ m68ki_write_32(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 32, aw, a)
+{
+ UINT32 res = AY;
+ UINT32 ea = EA_AW_32(m68k);
+
+ m68ki_write_32(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 32, aw, .)
+{
+ UINT32 res = M68KMAKE_GET_OPER_AY_32;
+ UINT32 ea = EA_AW_32(m68k);
+
+ m68ki_write_32(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 32, al, d)
+{
+ UINT32 res = DY;
+ UINT32 ea = EA_AL_32(m68k);
+
+ m68ki_write_32(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 32, al, a)
+{
+ UINT32 res = AY;
+ UINT32 ea = EA_AL_32(m68k);
+
+ m68ki_write_32(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move, 32, al, .)
+{
+ UINT32 res = M68KMAKE_GET_OPER_AY_32;
+ UINT32 ea = EA_AL_32(m68k);
+
+ m68ki_write_32(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(movea, 16, ., d)
+{
+ AX = MAKE_INT_16(DY);
+}
+
+
+M68KMAKE_OP(movea, 16, ., a)
+{
+ AX = MAKE_INT_16(AY);
+}
+
+
+M68KMAKE_OP(movea, 16, ., .)
+{
+ AX = MAKE_INT_16(M68KMAKE_GET_OPER_AY_16);
+}
+
+
+M68KMAKE_OP(movea, 32, ., d)
+{
+ AX = DY;
+}
+
+
+M68KMAKE_OP(movea, 32, ., a)
+{
+ AX = AY;
+}
+
+
+M68KMAKE_OP(movea, 32, ., .)
+{
+ AX = M68KMAKE_GET_OPER_AY_32;
+}
+
+
+M68KMAKE_OP(move, 16, frc, d)
+{
+ if(CPU_TYPE_IS_010_PLUS(m68k->cpu_type))
+ {
+ DY = MASK_OUT_BELOW_16(DY) | m68ki_get_ccr(m68k);
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(move, 16, frc, .)
+{
+ if(CPU_TYPE_IS_010_PLUS(m68k->cpu_type))
+ {
+ m68ki_write_16(m68k, M68KMAKE_GET_EA_AY_16, m68ki_get_ccr(m68k));
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(move, 16, toc, d)
+{
+ m68ki_set_ccr(m68k, DY);
+}
+
+
+M68KMAKE_OP(move, 16, toc, .)
+{
+ m68ki_set_ccr(m68k, M68KMAKE_GET_OPER_AY_16);
+}
+
+
+M68KMAKE_OP(move, 16, frs, d)
+{
+ if(CPU_TYPE_IS_000(m68k->cpu_type) || m68k->s_flag) /* NS990408 */
+ {
+ DY = MASK_OUT_BELOW_16(DY) | m68ki_get_sr(m68k);
+ return;
+ }
+ m68ki_exception_privilege_violation(m68k);
+}
+
+
+M68KMAKE_OP(move, 16, frs, .)
+{
+ if(CPU_TYPE_IS_000(m68k->cpu_type) || m68k->s_flag) /* NS990408 */
+ {
+ UINT32 ea = M68KMAKE_GET_EA_AY_16;
+ m68ki_write_16(m68k, ea, m68ki_get_sr(m68k));
+ return;
+ }
+ m68ki_exception_privilege_violation(m68k);
+}
+
+
+M68KMAKE_OP(move, 16, tos, d)
+{
+ if(m68k->s_flag)
+ {
+ m68ki_set_sr(m68k, DY);
+ return;
+ }
+ m68ki_exception_privilege_violation(m68k);
+}
+
+
+M68KMAKE_OP(move, 16, tos, .)
+{
+ if(m68k->s_flag)
+ {
+ UINT32 new_sr = M68KMAKE_GET_OPER_AY_16;
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+ m68ki_set_sr(m68k, new_sr);
+ return;
+ }
+ m68ki_exception_privilege_violation(m68k);
+}
+
+
+M68KMAKE_OP(move, 32, fru, .)
+{
+ if(m68k->s_flag)
+ {
+ AY = REG_USP;
+ return;
+ }
+ m68ki_exception_privilege_violation(m68k);
+}
+
+
+M68KMAKE_OP(move, 32, tou, .)
+{
+ if(m68k->s_flag)
+ {
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+ REG_USP = AY;
+ return;
+ }
+ m68ki_exception_privilege_violation(m68k);
+}
+
+
+M68KMAKE_OP(movec, 32, cr, .)
+{
+ if(CPU_TYPE_IS_010_PLUS(m68k->cpu_type))
+ {
+ if(m68k->s_flag)
+ {
+ UINT32 word2 = OPER_I_16(m68k);
+
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+ switch (word2 & 0xfff)
+ {
+ case 0x000: /* SFC */
+ REG_DA[(word2 >> 12) & 15] = m68k->sfc;
+ return;
+ case 0x001: /* DFC */
+ REG_DA[(word2 >> 12) & 15] = m68k->dfc;
+ return;
+ case 0x002: /* CACR */
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ REG_DA[(word2 >> 12) & 15] = m68k->cacr;
+ return;
+ }
+ return;
+ case 0x800: /* USP */
+ REG_DA[(word2 >> 12) & 15] = REG_USP;
+ return;
+ case 0x801: /* VBR */
+ REG_DA[(word2 >> 12) & 15] = m68k->vbr;
+ return;
+ case 0x802: /* CAAR */
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ REG_DA[(word2 >> 12) & 15] = m68k->caar;
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+ break;
+ case 0x803: /* MSP */
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ REG_DA[(word2 >> 12) & 15] = m68k->m_flag ? REG_SP : REG_MSP;
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+ return;
+ case 0x804: /* ISP */
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ REG_DA[(word2 >> 12) & 15] = m68k->m_flag ? REG_ISP : REG_SP;
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+ return;
+ case 0x003: /* TC */
+ if(CPU_TYPE_IS_040_PLUS(m68k->cpu_type))
+ {
+ /* TODO */
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+ return;
+ case 0x004: /* ITT0 */
+ if(CPU_TYPE_IS_040_PLUS(m68k->cpu_type))
+ {
+ /* TODO */
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+ return;
+ case 0x005: /* ITT1 */
+ if(CPU_TYPE_IS_040_PLUS(m68k->cpu_type))
+ {
+ /* TODO */
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+ return;
+ case 0x006: /* DTT0 */
+ if(CPU_TYPE_IS_040_PLUS(m68k->cpu_type))
+ {
+ /* TODO */
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+ return;
+ case 0x007: /* DTT1 */
+ if(CPU_TYPE_IS_040_PLUS(m68k->cpu_type))
+ {
+ /* TODO */
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+ return;
+ case 0x805: /* MMUSR */
+ if(CPU_TYPE_IS_040_PLUS(m68k->cpu_type))
+ {
+ /* TODO */
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+ return;
+ case 0x806: /* URP */
+ if(CPU_TYPE_IS_040_PLUS(m68k->cpu_type))
+ {
+ /* TODO */
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+ return;
+ case 0x807: /* SRP */
+ if(CPU_TYPE_IS_040_PLUS(m68k->cpu_type))
+ {
+ /* TODO */
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+ return;
+ default:
+ m68ki_exception_illegal(m68k);
+ return;
+ }
+ }
+ m68ki_exception_privilege_violation(m68k);
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(movec, 32, rc, .)
+{
+ if(CPU_TYPE_IS_010_PLUS(m68k->cpu_type))
+ {
+ if(m68k->s_flag)
+ {
+ UINT32 word2 = OPER_I_16(m68k);
+
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+ switch (word2 & 0xfff)
+ {
+ case 0x000: /* SFC */
+ m68k->sfc = REG_DA[(word2 >> 12) & 15] & 7;
+ return;
+ case 0x001: /* DFC */
+ m68k->dfc = REG_DA[(word2 >> 12) & 15] & 7;
+ return;
+ case 0x002: /* CACR */
+ /* Only EC020 and later have CACR */
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ /* 68030 can write all bits except 5-7, 040 can write all */
+ if (CPU_TYPE_IS_040_PLUS(m68k->cpu_type))
+ {
+ m68k->cacr = REG_DA[(word2 >> 12) & 15];
+ }
+ else if (CPU_TYPE_IS_030_PLUS(m68k->cpu_type))
+ {
+ m68k->cacr = REG_DA[(word2 >> 12) & 15] & 0xff1f;
+ }
+ else
+ {
+ m68k->cacr = REG_DA[(word2 >> 12) & 15] & 0x0f;
+ }
+
+// logerror("movec to cacr=%04x\n", m68k->cacr);
+ if (m68k->cacr & (M68K_CACR_CI | M68K_CACR_CEI))
+ {
+ m68ki_ic_clear(m68k);
+ }
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+ return;
+ case 0x800: /* USP */
+ REG_USP = REG_DA[(word2 >> 12) & 15];
+ return;
+ case 0x801: /* VBR */
+ m68k->vbr = REG_DA[(word2 >> 12) & 15];
+ return;
+ case 0x802: /* CAAR */
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ m68k->caar = REG_DA[(word2 >> 12) & 15];
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+ return;
+ case 0x803: /* MSP */
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ /* we are in supervisor mode so just check for M flag */
+ if(!m68k->m_flag)
+ {
+ REG_MSP = REG_DA[(word2 >> 12) & 15];
+ return;
+ }
+ REG_SP = REG_DA[(word2 >> 12) & 15];
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+ return;
+ case 0x804: /* ISP */
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ if(!m68k->m_flag)
+ {
+ REG_SP = REG_DA[(word2 >> 12) & 15];
+ return;
+ }
+ REG_ISP = REG_DA[(word2 >> 12) & 15];
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+ return;
+ case 0x003: /* TC */
+ if (CPU_TYPE_IS_040_PLUS(m68k->cpu_type))
+ {
+ /* TODO */
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+ return;
+ case 0x004: /* ITT0 */
+ if (CPU_TYPE_IS_040_PLUS(m68k->cpu_type))
+ {
+ /* TODO */
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+ return;
+ case 0x005: /* ITT1 */
+ if (CPU_TYPE_IS_040_PLUS(m68k->cpu_type))
+ {
+ /* TODO */
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+ return;
+ case 0x006: /* DTT0 */
+ if (CPU_TYPE_IS_040_PLUS(m68k->cpu_type))
+ {
+ /* TODO */
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+ return;
+ case 0x007: /* DTT1 */
+ if (CPU_TYPE_IS_040_PLUS(m68k->cpu_type))
+ {
+ /* TODO */
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+ return;
+ case 0x805: /* MMUSR */
+ if (CPU_TYPE_IS_040_PLUS(m68k->cpu_type))
+ {
+ /* TODO */
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+ return;
+ case 0x806: /* URP */
+ if (CPU_TYPE_IS_040_PLUS(m68k->cpu_type))
+ {
+ /* TODO */
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+ return;
+ case 0x807: /* SRP */
+ if (CPU_TYPE_IS_040_PLUS(m68k->cpu_type))
+ {
+ /* TODO */
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+ return;
+ default:
+ m68ki_exception_illegal(m68k);
+ return;
+ }
+ }
+ m68ki_exception_privilege_violation(m68k);
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(movem, 16, re, pd)
+{
+ UINT32 i = 0;
+ UINT32 register_list = OPER_I_16(m68k);
+ UINT32 ea = AY;
+ UINT32 count = 0;
+
+ for(; i < 16; i++)
+ if(register_list & (1 << i))
+ {
+ ea -= 2;
+ m68ki_write_16(m68k, ea, MASK_OUT_ABOVE_16(REG_DA[15-i]));
+ count++;
+ }
+ AY = ea;
+
+ m68k->remaining_cycles -= count<<m68k->cyc_movem_w;
+}
+
+
+M68KMAKE_OP(movem, 16, re, .)
+{
+ UINT32 i = 0;
+ UINT32 register_list = OPER_I_16(m68k);
+ UINT32 ea = M68KMAKE_GET_EA_AY_16;
+ UINT32 count = 0;
+
+ for(; i < 16; i++)
+ if(register_list & (1 << i))
+ {
+ m68ki_write_16(m68k, ea, MASK_OUT_ABOVE_16(REG_DA[i]));
+ ea += 2;
+ count++;
+ }
+
+ m68k->remaining_cycles -= count<<m68k->cyc_movem_w;
+}
+
+
+M68KMAKE_OP(movem, 32, re, pd)
+{
+ UINT32 i = 0;
+ UINT32 register_list = OPER_I_16(m68k);
+ UINT32 ea = AY;
+ UINT32 count = 0;
+
+ for(; i < 16; i++)
+ if(register_list & (1 << i))
+ {
+ ea -= 4;
+ m68ki_write_16(m68k, ea+2, REG_DA[15-i] & 0xFFFF );
+ m68ki_write_16(m68k, ea, (REG_DA[15-i] >> 16) & 0xFFFF );
+ count++;
+ }
+ AY = ea;
+
+ m68k->remaining_cycles -= count<<m68k->cyc_movem_l;
+}
+
+
+M68KMAKE_OP(movem, 32, re, .)
+{
+ UINT32 i = 0;
+ UINT32 register_list = OPER_I_16(m68k);
+ UINT32 ea = M68KMAKE_GET_EA_AY_32;
+ UINT32 count = 0;
+
+ for(; i < 16; i++)
+ if(register_list & (1 << i))
+ {
+ m68ki_write_32(m68k, ea, REG_DA[i]);
+ ea += 4;
+ count++;
+ }
+
+ m68k->remaining_cycles -= count<<m68k->cyc_movem_l;
+}
+
+
+M68KMAKE_OP(movem, 16, er, pi)
+{
+ UINT32 i = 0;
+ UINT32 register_list = OPER_I_16(m68k);
+ UINT32 ea = AY;
+ UINT32 count = 0;
+
+ for(; i < 16; i++)
+ if(register_list & (1 << i))
+ {
+ REG_DA[i] = MAKE_INT_16(MASK_OUT_ABOVE_16(m68ki_read_16(m68k, ea)));
+ ea += 2;
+ count++;
+ }
+ AY = ea;
+
+ m68k->remaining_cycles -= count<<m68k->cyc_movem_w;
+}
+
+
+M68KMAKE_OP(movem, 16, er, pcdi)
+{
+ UINT32 i = 0;
+ UINT32 register_list = OPER_I_16(m68k);
+ UINT32 ea = EA_PCDI_16(m68k);
+ UINT32 count = 0;
+
+ for(; i < 16; i++)
+ if(register_list & (1 << i))
+ {
+ REG_DA[i] = MAKE_INT_16(MASK_OUT_ABOVE_16(m68ki_read_pcrel_16(m68k, ea)));
+ ea += 2;
+ count++;
+ }
+
+ m68k->remaining_cycles -= count<<m68k->cyc_movem_w;
+}
+
+
+M68KMAKE_OP(movem, 16, er, pcix)
+{
+ UINT32 i = 0;
+ UINT32 register_list = OPER_I_16(m68k);
+ UINT32 ea = EA_PCIX_16(m68k);
+ UINT32 count = 0;
+
+ for(; i < 16; i++)
+ if(register_list & (1 << i))
+ {
+ REG_DA[i] = MAKE_INT_16(MASK_OUT_ABOVE_16(m68ki_read_pcrel_16(m68k, ea)));
+ ea += 2;
+ count++;
+ }
+
+ m68k->remaining_cycles -= count<<m68k->cyc_movem_w;
+}
+
+
+M68KMAKE_OP(movem, 16, er, .)
+{
+ UINT32 i = 0;
+ UINT32 register_list = OPER_I_16(m68k);
+ UINT32 ea = M68KMAKE_GET_EA_AY_16;
+ UINT32 count = 0;
+
+ for(; i < 16; i++)
+ if(register_list & (1 << i))
+ {
+ REG_DA[i] = MAKE_INT_16(MASK_OUT_ABOVE_16(m68ki_read_16(m68k, ea)));
+ ea += 2;
+ count++;
+ }
+
+ m68k->remaining_cycles -= count<<m68k->cyc_movem_w;
+}
+
+
+M68KMAKE_OP(movem, 32, er, pi)
+{
+ UINT32 i = 0;
+ UINT32 register_list = OPER_I_16(m68k);
+ UINT32 ea = AY;
+ UINT32 count = 0;
+
+ for(; i < 16; i++)
+ if(register_list & (1 << i))
+ {
+ REG_DA[i] = m68ki_read_32(m68k, ea);
+ ea += 4;
+ count++;
+ }
+ AY = ea;
+
+ m68k->remaining_cycles -= count<<m68k->cyc_movem_l;
+}
+
+
+M68KMAKE_OP(movem, 32, er, pcdi)
+{
+ UINT32 i = 0;
+ UINT32 register_list = OPER_I_16(m68k);
+ UINT32 ea = EA_PCDI_32(m68k);
+ UINT32 count = 0;
+
+ for(; i < 16; i++)
+ if(register_list & (1 << i))
+ {
+ REG_DA[i] = m68ki_read_pcrel_32(m68k, ea);
+ ea += 4;
+ count++;
+ }
+
+ m68k->remaining_cycles -= count<<m68k->cyc_movem_l;
+}
+
+
+M68KMAKE_OP(movem, 32, er, pcix)
+{
+ UINT32 i = 0;
+ UINT32 register_list = OPER_I_16(m68k);
+ UINT32 ea = EA_PCIX_32(m68k);
+ UINT32 count = 0;
+
+ for(; i < 16; i++)
+ if(register_list & (1 << i))
+ {
+ REG_DA[i] = m68ki_read_pcrel_32(m68k, ea);
+ ea += 4;
+ count++;
+ }
+
+ m68k->remaining_cycles -= count<<m68k->cyc_movem_l;
+}
+
+
+M68KMAKE_OP(movem, 32, er, .)
+{
+ UINT32 i = 0;
+ UINT32 register_list = OPER_I_16(m68k);
+ UINT32 ea = M68KMAKE_GET_EA_AY_32;
+ UINT32 count = 0;
+
+ for(; i < 16; i++)
+ if(register_list & (1 << i))
+ {
+ REG_DA[i] = m68ki_read_32(m68k, ea);
+ ea += 4;
+ count++;
+ }
+
+ m68k->remaining_cycles -= count<<m68k->cyc_movem_l;
+}
+
+
+M68KMAKE_OP(movep, 16, re, .)
+{
+ UINT32 ea = EA_AY_DI_16(m68k);
+ UINT32 src = DX;
+
+ m68ki_write_8(m68k, ea, MASK_OUT_ABOVE_8(src >> 8));
+ m68ki_write_8(m68k, ea += 2, MASK_OUT_ABOVE_8(src));
+}
+
+
+M68KMAKE_OP(movep, 32, re, .)
+{
+ UINT32 ea = EA_AY_DI_32(m68k);
+ UINT32 src = DX;
+
+ m68ki_write_8(m68k, ea, MASK_OUT_ABOVE_8(src >> 24));
+ m68ki_write_8(m68k, ea += 2, MASK_OUT_ABOVE_8(src >> 16));
+ m68ki_write_8(m68k, ea += 2, MASK_OUT_ABOVE_8(src >> 8));
+ m68ki_write_8(m68k, ea += 2, MASK_OUT_ABOVE_8(src));
+}
+
+
+M68KMAKE_OP(movep, 16, er, .)
+{
+ UINT32 ea = EA_AY_DI_16(m68k);
+ UINT32* r_dst = &DX;
+
+ *r_dst = MASK_OUT_BELOW_16(*r_dst) | ((m68ki_read_8(m68k, ea) << 8) + m68ki_read_8(m68k, ea + 2));
+}
+
+
+M68KMAKE_OP(movep, 32, er, .)
+{
+ UINT32 ea = EA_AY_DI_32(m68k);
+
+ DX = (m68ki_read_8(m68k, ea) << 24) + (m68ki_read_8(m68k, ea + 2) << 16)
+ + (m68ki_read_8(m68k, ea + 4) << 8) + m68ki_read_8(m68k, ea + 6);
+}
+
+
+M68KMAKE_OP(moves, 8, ., .)
+{
+ if(CPU_TYPE_IS_010_PLUS(m68k->cpu_type))
+ {
+ if(m68k->s_flag)
+ {
+ UINT32 word2 = OPER_I_16(m68k);
+ UINT32 ea = M68KMAKE_GET_EA_AY_8;
+
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+ if(BIT_B(word2)) /* Register to memory */
+ {
+ m68ki_write_8_fc(m68k, ea, m68k->dfc, MASK_OUT_ABOVE_8(REG_DA[(word2 >> 12) & 15]));
+ return;
+ }
+ if(BIT_F(word2)) /* Memory to address register */
+ {
+ REG_A[(word2 >> 12) & 7] = MAKE_INT_8(m68ki_read_8_fc(m68k, ea, m68k->sfc));
+ if(CPU_TYPE_IS_020_VARIANT(m68k->cpu_type))
+ m68k->remaining_cycles -= 2;
+ return;
+ }
+ /* Memory to data register */
+ REG_D[(word2 >> 12) & 7] = MASK_OUT_BELOW_8(REG_D[(word2 >> 12) & 7]) | m68ki_read_8_fc(m68k, ea, m68k->sfc);
+ if(CPU_TYPE_IS_020_VARIANT(m68k->cpu_type))
+ m68k->remaining_cycles -= 2;
+ return;
+ }
+ m68ki_exception_privilege_violation(m68k);
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(moves, 16, ., .)
+{
+ if(CPU_TYPE_IS_010_PLUS(m68k->cpu_type))
+ {
+ if(m68k->s_flag)
+ {
+ UINT32 word2 = OPER_I_16(m68k);
+ UINT32 ea = M68KMAKE_GET_EA_AY_16;
+
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+ if(BIT_B(word2)) /* Register to memory */
+ {
+ m68ki_write_16_fc(m68k, ea, m68k->dfc, MASK_OUT_ABOVE_16(REG_DA[(word2 >> 12) & 15]));
+ return;
+ }
+ if(BIT_F(word2)) /* Memory to address register */
+ {
+ REG_A[(word2 >> 12) & 7] = MAKE_INT_16(m68ki_read_16_fc(m68k, ea, m68k->sfc));
+ if(CPU_TYPE_IS_020_VARIANT(m68k->cpu_type))
+ m68k->remaining_cycles -= 2;
+ return;
+ }
+ /* Memory to data register */
+ REG_D[(word2 >> 12) & 7] = MASK_OUT_BELOW_16(REG_D[(word2 >> 12) & 7]) | m68ki_read_16_fc(m68k, ea, m68k->sfc);
+ if(CPU_TYPE_IS_020_VARIANT(m68k->cpu_type))
+ m68k->remaining_cycles -= 2;
+ return;
+ }
+ m68ki_exception_privilege_violation(m68k);
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(moves, 32, ., .)
+{
+ if(CPU_TYPE_IS_010_PLUS(m68k->cpu_type))
+ {
+ if(m68k->s_flag)
+ {
+ UINT32 word2 = OPER_I_16(m68k);
+ UINT32 ea = M68KMAKE_GET_EA_AY_32;
+
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+ if(BIT_B(word2)) /* Register to memory */
+ {
+ m68ki_write_32_fc(m68k, ea, m68k->dfc, REG_DA[(word2 >> 12) & 15]);
+ if(CPU_TYPE_IS_020_VARIANT(m68k->cpu_type))
+ m68k->remaining_cycles -= 2;
+ return;
+ }
+ /* Memory to register */
+ REG_DA[(word2 >> 12) & 15] = m68ki_read_32_fc(m68k, ea, m68k->sfc);
+ if(CPU_TYPE_IS_020_VARIANT(m68k->cpu_type))
+ m68k->remaining_cycles -= 2;
+ return;
+ }
+ m68ki_exception_privilege_violation(m68k);
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(moveq, 32, ., .)
+{
+ UINT32 res = DX = MAKE_INT_8(MASK_OUT_ABOVE_8(m68k->ir));
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(move16, 32, ., .)
+{
+ UINT16 w2 = OPER_I_16(m68k);
+ int ax = m68k->ir & 7;
+ int ay = (w2 >> 12) & 7;
+ m68ki_write_32(m68k, REG_A[ay], m68ki_read_32(m68k, REG_A[ax]));
+ m68ki_write_32(m68k, REG_A[ay]+4, m68ki_read_32(m68k, REG_A[ax]+4));
+ m68ki_write_32(m68k, REG_A[ay]+8, m68ki_read_32(m68k, REG_A[ax]+8));
+ m68ki_write_32(m68k, REG_A[ay]+12, m68ki_read_32(m68k, REG_A[ax]+12));
+
+ REG_A[ax] += 16;
+ REG_A[ay] += 16;
+}
+
+
+M68KMAKE_OP(muls, 16, ., d)
+{
+ UINT32* r_dst = &DX;
+ UINT32 res = MASK_OUT_ABOVE_32(MAKE_INT_16(DY) * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst)));
+
+ *r_dst = res;
+
+ m68k->not_z_flag = res;
+ m68k->n_flag = NFLAG_32(res);
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(muls, 16, ., .)
+{
+ UINT32* r_dst = &DX;
+ UINT32 res = MASK_OUT_ABOVE_32(MAKE_INT_16(M68KMAKE_GET_OPER_AY_16) * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst)));
+
+ *r_dst = res;
+
+ m68k->not_z_flag = res;
+ m68k->n_flag = NFLAG_32(res);
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(mulu, 16, ., d)
+{
+ UINT32* r_dst = &DX;
+ UINT32 res = MASK_OUT_ABOVE_16(DY) * MASK_OUT_ABOVE_16(*r_dst);
+
+ *r_dst = res;
+
+ m68k->not_z_flag = res;
+ m68k->n_flag = NFLAG_32(res);
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(mulu, 16, ., .)
+{
+ UINT32* r_dst = &DX;
+ UINT32 res = M68KMAKE_GET_OPER_AY_16 * MASK_OUT_ABOVE_16(*r_dst);
+
+ *r_dst = res;
+
+ m68k->not_z_flag = res;
+ m68k->n_flag = NFLAG_32(res);
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(mull, 32, ., d)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 word2 = OPER_I_16(m68k);
+ UINT64 src = DY;
+ UINT64 dst = REG_D[(word2 >> 12) & 7];
+ UINT64 res;
+
+ m68k->c_flag = CFLAG_CLEAR;
+
+ if(BIT_B(word2)) /* signed */
+ {
+ res = (INT64)((INT32)src) * (INT64)((INT32)dst);
+ if(!BIT_A(word2))
+ {
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res);
+ m68k->n_flag = NFLAG_32(res);
+ m68k->v_flag = ((INT64)res != (INT32)res)<<7;
+ REG_D[(word2 >> 12) & 7] = m68k->not_z_flag;
+ return;
+ }
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res) | (res>>32);
+ m68k->n_flag = NFLAG_64(res);
+ m68k->v_flag = VFLAG_CLEAR;
+ REG_D[word2 & 7] = (res >> 32);
+ REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res);
+ return;
+ }
+
+ res = src * dst;
+ if(!BIT_A(word2))
+ {
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res);
+ m68k->n_flag = NFLAG_32(res);
+ m68k->v_flag = (res > 0xffffffff)<<7;
+ REG_D[(word2 >> 12) & 7] = m68k->not_z_flag;
+ return;
+ }
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res) | (res>>32);
+ m68k->n_flag = NFLAG_64(res);
+ m68k->v_flag = VFLAG_CLEAR;
+ REG_D[word2 & 7] = (res >> 32);
+ REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res);
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(mull, 32, ., .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 word2 = OPER_I_16(m68k);
+ UINT64 src = M68KMAKE_GET_OPER_AY_32;
+ UINT64 dst = REG_D[(word2 >> 12) & 7];
+ UINT64 res;
+
+ m68k->c_flag = CFLAG_CLEAR;
+
+ if(BIT_B(word2)) /* signed */
+ {
+ res = (INT64)((INT32)src) * (INT64)((INT32)dst);
+ if(!BIT_A(word2))
+ {
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res);
+ m68k->n_flag = NFLAG_32(res);
+ m68k->v_flag = ((INT64)res != (INT32)res)<<7;
+ REG_D[(word2 >> 12) & 7] = m68k->not_z_flag;
+ return;
+ }
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res) | (res>>32);
+ m68k->n_flag = NFLAG_64(res);
+ m68k->v_flag = VFLAG_CLEAR;
+ REG_D[word2 & 7] = (res >> 32);
+ REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res);
+ return;
+ }
+
+ res = src * dst;
+ if(!BIT_A(word2))
+ {
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res);
+ m68k->n_flag = NFLAG_32(res);
+ m68k->v_flag = (res > 0xffffffff)<<7;
+ REG_D[(word2 >> 12) & 7] = m68k->not_z_flag;
+ return;
+ }
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res) | (res>>32);
+ m68k->n_flag = NFLAG_64(res);
+ m68k->v_flag = VFLAG_CLEAR;
+ REG_D[word2 & 7] = (res >> 32);
+ REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res);
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(nbcd, 8, ., d)
+{
+ UINT32* r_dst = &DY;
+ UINT32 dst = *r_dst;
+ UINT32 res = MASK_OUT_ABOVE_8(0x9a - dst - XFLAG_AS_1(m68k));
+
+ if(res != 0x9a)
+ {
+ m68k->v_flag = ~res; /* Undefined V behavior */
+
+ if((res & 0x0f) == 0xa)
+ res = (res & 0xf0) + 0x10;
+
+ res = MASK_OUT_ABOVE_8(res);
+
+ m68k->v_flag &= res; /* Undefined V behavior part II */
+
+ *r_dst = MASK_OUT_BELOW_8(*r_dst) | res;
+
+ m68k->not_z_flag |= res;
+ m68k->c_flag = CFLAG_SET;
+ m68k->x_flag = XFLAG_SET;
+ }
+ else
+ {
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->x_flag = XFLAG_CLEAR;
+ }
+ m68k->n_flag = NFLAG_8(res); /* Undefined N behavior */
+}
+
+
+M68KMAKE_OP(nbcd, 8, ., .)
+{
+ UINT32 ea = M68KMAKE_GET_EA_AY_8;
+ UINT32 dst = m68ki_read_8(m68k, ea);
+ UINT32 res = MASK_OUT_ABOVE_8(0x9a - dst - XFLAG_AS_1(m68k));
+
+ if(res != 0x9a)
+ {
+ m68k->v_flag = ~res; /* Undefined V behavior */
+
+ if((res & 0x0f) == 0xa)
+ res = (res & 0xf0) + 0x10;
+
+ res = MASK_OUT_ABOVE_8(res);
+
+ m68k->v_flag &= res; /* Undefined V behavior part II */
+
+ m68ki_write_8(m68k, ea, MASK_OUT_ABOVE_8(res));
+
+ m68k->not_z_flag |= res;
+ m68k->c_flag = CFLAG_SET;
+ m68k->x_flag = XFLAG_SET;
+ }
+ else
+ {
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->x_flag = XFLAG_CLEAR;
+ }
+ m68k->n_flag = NFLAG_8(res); /* Undefined N behavior */
+}
+
+
+M68KMAKE_OP(neg, 8, ., d)
+{
+ UINT32* r_dst = &DY;
+ UINT32 res = 0 - MASK_OUT_ABOVE_8(*r_dst);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->c_flag = m68k->x_flag = CFLAG_8(res);
+ m68k->v_flag = *r_dst & res;
+ m68k->not_z_flag = MASK_OUT_ABOVE_8(res);
+
+ *r_dst = MASK_OUT_BELOW_8(*r_dst) | m68k->not_z_flag;
+}
+
+
+M68KMAKE_OP(neg, 8, ., .)
+{
+ UINT32 ea = M68KMAKE_GET_EA_AY_8;
+ UINT32 src = m68ki_read_8(m68k, ea);
+ UINT32 res = 0 - src;
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->c_flag = m68k->x_flag = CFLAG_8(res);
+ m68k->v_flag = src & res;
+ m68k->not_z_flag = MASK_OUT_ABOVE_8(res);
+
+ m68ki_write_8(m68k, ea, m68k->not_z_flag);
+}
+
+
+M68KMAKE_OP(neg, 16, ., d)
+{
+ UINT32* r_dst = &DY;
+ UINT32 res = 0 - MASK_OUT_ABOVE_16(*r_dst);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->c_flag = m68k->x_flag = CFLAG_16(res);
+ m68k->v_flag = (*r_dst & res)>>8;
+ m68k->not_z_flag = MASK_OUT_ABOVE_16(res);
+
+ *r_dst = MASK_OUT_BELOW_16(*r_dst) | m68k->not_z_flag;
+}
+
+
+M68KMAKE_OP(neg, 16, ., .)
+{
+ UINT32 ea = M68KMAKE_GET_EA_AY_16;
+ UINT32 src = m68ki_read_16(m68k, ea);
+ UINT32 res = 0 - src;
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->c_flag = m68k->x_flag = CFLAG_16(res);
+ m68k->v_flag = (src & res)>>8;
+ m68k->not_z_flag = MASK_OUT_ABOVE_16(res);
+
+ m68ki_write_16(m68k, ea, m68k->not_z_flag);
+}
+
+
+M68KMAKE_OP(neg, 32, ., d)
+{
+ UINT32* r_dst = &DY;
+ UINT32 res = 0 - *r_dst;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->c_flag = m68k->x_flag = CFLAG_SUB_32(*r_dst, 0, res);
+ m68k->v_flag = (*r_dst & res)>>24;
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res);
+
+ *r_dst = m68k->not_z_flag;
+}
+
+
+M68KMAKE_OP(neg, 32, ., .)
+{
+ UINT32 ea = M68KMAKE_GET_EA_AY_32;
+ UINT32 src = m68ki_read_32(m68k, ea);
+ UINT32 res = 0 - src;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->c_flag = m68k->x_flag = CFLAG_SUB_32(src, 0, res);
+ m68k->v_flag = (src & res)>>24;
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res);
+
+ m68ki_write_32(m68k, ea, m68k->not_z_flag);
+}
+
+
+M68KMAKE_OP(negx, 8, ., d)
+{
+ UINT32* r_dst = &DY;
+ UINT32 res = 0 - MASK_OUT_ABOVE_8(*r_dst) - XFLAG_AS_1(m68k);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->x_flag = m68k->c_flag = CFLAG_8(res);
+ m68k->v_flag = *r_dst & res;
+
+ res = MASK_OUT_ABOVE_8(res);
+ m68k->not_z_flag |= res;
+
+ *r_dst = MASK_OUT_BELOW_8(*r_dst) | res;
+}
+
+
+M68KMAKE_OP(negx, 8, ., .)
+{
+ UINT32 ea = M68KMAKE_GET_EA_AY_8;
+ UINT32 src = m68ki_read_8(m68k, ea);
+ UINT32 res = 0 - src - XFLAG_AS_1(m68k);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->x_flag = m68k->c_flag = CFLAG_8(res);
+ m68k->v_flag = src & res;
+
+ res = MASK_OUT_ABOVE_8(res);
+ m68k->not_z_flag |= res;
+
+ m68ki_write_8(m68k, ea, res);
+}
+
+
+M68KMAKE_OP(negx, 16, ., d)
+{
+ UINT32* r_dst = &DY;
+ UINT32 res = 0 - MASK_OUT_ABOVE_16(*r_dst) - XFLAG_AS_1(m68k);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->x_flag = m68k->c_flag = CFLAG_16(res);
+ m68k->v_flag = (*r_dst & res)>>8;
+
+ res = MASK_OUT_ABOVE_16(res);
+ m68k->not_z_flag |= res;
+
+ *r_dst = MASK_OUT_BELOW_16(*r_dst) | res;
+}
+
+
+M68KMAKE_OP(negx, 16, ., .)
+{
+ UINT32 ea = M68KMAKE_GET_EA_AY_16;
+ UINT32 src = m68ki_read_16(m68k, ea);
+ UINT32 res = 0 - MASK_OUT_ABOVE_16(src) - XFLAG_AS_1(m68k);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->x_flag = m68k->c_flag = CFLAG_16(res);
+ m68k->v_flag = (src & res)>>8;
+
+ res = MASK_OUT_ABOVE_16(res);
+ m68k->not_z_flag |= res;
+
+ m68ki_write_16(m68k, ea, res);
+}
+
+
+M68KMAKE_OP(negx, 32, ., d)
+{
+ UINT32* r_dst = &DY;
+ UINT32 res = 0 - MASK_OUT_ABOVE_32(*r_dst) - XFLAG_AS_1(m68k);
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->x_flag = m68k->c_flag = CFLAG_SUB_32(*r_dst, 0, res);
+ m68k->v_flag = (*r_dst & res)>>24;
+
+ res = MASK_OUT_ABOVE_32(res);
+ m68k->not_z_flag |= res;
+
+ *r_dst = res;
+}
+
+
+M68KMAKE_OP(negx, 32, ., .)
+{
+ UINT32 ea = M68KMAKE_GET_EA_AY_32;
+ UINT32 src = m68ki_read_32(m68k, ea);
+ UINT32 res = 0 - MASK_OUT_ABOVE_32(src) - XFLAG_AS_1(m68k);
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->x_flag = m68k->c_flag = CFLAG_SUB_32(src, 0, res);
+ m68k->v_flag = (src & res)>>24;
+
+ res = MASK_OUT_ABOVE_32(res);
+ m68k->not_z_flag |= res;
+
+ m68ki_write_32(m68k, ea, res);
+}
+
+
+M68KMAKE_OP(nop, 0, ., .)
+{
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+}
+
+
+M68KMAKE_OP(not, 8, ., d)
+{
+ UINT32* r_dst = &DY;
+ UINT32 res = MASK_OUT_ABOVE_8(~*r_dst);
+
+ *r_dst = MASK_OUT_BELOW_8(*r_dst) | res;
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(not, 8, ., .)
+{
+ UINT32 ea = M68KMAKE_GET_EA_AY_8;
+ UINT32 res = MASK_OUT_ABOVE_8(~m68ki_read_8(m68k, ea));
+
+ m68ki_write_8(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(not, 16, ., d)
+{
+ UINT32* r_dst = &DY;
+ UINT32 res = MASK_OUT_ABOVE_16(~*r_dst);
+
+ *r_dst = MASK_OUT_BELOW_16(*r_dst) | res;
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(not, 16, ., .)
+{
+ UINT32 ea = M68KMAKE_GET_EA_AY_16;
+ UINT32 res = MASK_OUT_ABOVE_16(~m68ki_read_16(m68k, ea));
+
+ m68ki_write_16(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(not, 32, ., d)
+{
+ UINT32* r_dst = &DY;
+ UINT32 res = *r_dst = MASK_OUT_ABOVE_32(~*r_dst);
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(not, 32, ., .)
+{
+ UINT32 ea = M68KMAKE_GET_EA_AY_32;
+ UINT32 res = MASK_OUT_ABOVE_32(~m68ki_read_32(m68k, ea));
+
+ m68ki_write_32(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(or, 8, er, d)
+{
+ UINT32 res = MASK_OUT_ABOVE_8((DX |= MASK_OUT_ABOVE_8(DY)));
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(or, 8, er, .)
+{
+ UINT32 res = MASK_OUT_ABOVE_8((DX |= M68KMAKE_GET_OPER_AY_8));
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(or, 16, er, d)
+{
+ UINT32 res = MASK_OUT_ABOVE_16((DX |= MASK_OUT_ABOVE_16(DY)));
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(or, 16, er, .)
+{
+ UINT32 res = MASK_OUT_ABOVE_16((DX |= M68KMAKE_GET_OPER_AY_16));
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(or, 32, er, d)
+{
+ UINT32 res = DX |= DY;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(or, 32, er, .)
+{
+ UINT32 res = DX |= M68KMAKE_GET_OPER_AY_32;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(or, 8, re, .)
+{
+ UINT32 ea = M68KMAKE_GET_EA_AY_8;
+ UINT32 res = MASK_OUT_ABOVE_8(DX | m68ki_read_8(m68k, ea));
+
+ m68ki_write_8(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(or, 16, re, .)
+{
+ UINT32 ea = M68KMAKE_GET_EA_AY_16;
+ UINT32 res = MASK_OUT_ABOVE_16(DX | m68ki_read_16(m68k, ea));
+
+ m68ki_write_16(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(or, 32, re, .)
+{
+ UINT32 ea = M68KMAKE_GET_EA_AY_32;
+ UINT32 res = DX | m68ki_read_32(m68k, ea);
+
+ m68ki_write_32(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(ori, 8, ., d)
+{
+ UINT32 res = MASK_OUT_ABOVE_8((DY |= OPER_I_8(m68k)));
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(ori, 8, ., .)
+{
+ UINT32 src = OPER_I_8(m68k);
+ UINT32 ea = M68KMAKE_GET_EA_AY_8;
+ UINT32 res = MASK_OUT_ABOVE_8(src | m68ki_read_8(m68k, ea));
+
+ m68ki_write_8(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(ori, 16, ., d)
+{
+ UINT32 res = MASK_OUT_ABOVE_16(DY |= OPER_I_16(m68k));
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(ori, 16, ., .)
+{
+ UINT32 src = OPER_I_16(m68k);
+ UINT32 ea = M68KMAKE_GET_EA_AY_16;
+ UINT32 res = MASK_OUT_ABOVE_16(src | m68ki_read_16(m68k, ea));
+
+ m68ki_write_16(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(ori, 32, ., d)
+{
+ UINT32 res = DY |= OPER_I_32(m68k);
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(ori, 32, ., .)
+{
+ UINT32 src = OPER_I_32(m68k);
+ UINT32 ea = M68KMAKE_GET_EA_AY_32;
+ UINT32 res = src | m68ki_read_32(m68k, ea);
+
+ m68ki_write_32(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(ori, 16, toc, .)
+{
+ m68ki_set_ccr(m68k, m68ki_get_ccr(m68k) | OPER_I_16(m68k));
+}
+
+
+M68KMAKE_OP(ori, 16, tos, .)
+{
+ if(m68k->s_flag)
+ {
+ UINT32 src = OPER_I_16(m68k);
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+ m68ki_set_sr(m68k, m68ki_get_sr(m68k) | src);
+ return;
+ }
+ m68ki_exception_privilege_violation(m68k);
+}
+
+
+M68KMAKE_OP(pack, 16, rr, .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ /* Note: DX and DY are reversed in Motorola's docs */
+ UINT32 src = DY + OPER_I_16(m68k);
+ UINT32* r_dst = &DX;
+
+ *r_dst = MASK_OUT_BELOW_8(*r_dst) | ((src >> 4) & 0x00f0) | (src & 0x000f);
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(pack, 16, mm, ax7)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ /* Note: AX and AY are reversed in Motorola's docs */
+ UINT32 ea_src = EA_AY_PD_8(m68k);
+ UINT32 src = m68ki_read_8(m68k, ea_src);
+ ea_src = EA_AY_PD_8(m68k);
+ src = ((src << 8) | m68ki_read_8(m68k, ea_src)) + OPER_I_16(m68k);
+
+ m68ki_write_8(m68k, EA_A7_PD_8(m68k), ((src >> 4) & 0x00f0) | (src & 0x000f));
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(pack, 16, mm, ay7)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ /* Note: AX and AY are reversed in Motorola's docs */
+ UINT32 ea_src = EA_A7_PD_8(m68k);
+ UINT32 src = m68ki_read_8(m68k, ea_src);
+ ea_src = EA_A7_PD_8(m68k);
+ src = ((src << 8) | m68ki_read_8(m68k, ea_src)) + OPER_I_16(m68k);
+
+ m68ki_write_8(m68k, EA_AX_PD_8(m68k), ((src >> 4) & 0x00f0) | (src & 0x000f));
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(pack, 16, mm, axy7)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 ea_src = EA_A7_PD_8(m68k);
+ UINT32 src = m68ki_read_8(m68k, ea_src);
+ ea_src = EA_A7_PD_8(m68k);
+ src = ((src << 8) | m68ki_read_8(m68k, ea_src)) + OPER_I_16(m68k);
+
+ m68ki_write_8(m68k, EA_A7_PD_8(m68k), ((src >> 4) & 0x00f0) | (src & 0x000f));
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(pack, 16, mm, .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ /* Note: AX and AY are reversed in Motorola's docs */
+ UINT32 ea_src = EA_AY_PD_8(m68k);
+ UINT32 src = m68ki_read_8(m68k, ea_src);
+ ea_src = EA_AY_PD_8(m68k);
+ src = ((src << 8) | m68ki_read_8(m68k, ea_src)) + OPER_I_16(m68k);
+
+ m68ki_write_8(m68k, EA_AX_PD_8(m68k), ((src >> 4) & 0x00f0) | (src & 0x000f));
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(pea, 32, ., .)
+{
+ UINT32 ea = M68KMAKE_GET_EA_AY_32;
+
+ m68ki_push_32(m68k, ea);
+}
+
+M68KMAKE_OP(pflush, 32, ., .)
+{
+ if ((CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type)) && (m68k->has_pmmu))
+ {
+ logerror("68040: unhandled PFLUSH\n");
+ return;
+ }
+ m68ki_exception_1111(m68k);
+}
+
+M68KMAKE_OP(pmmu, 32, ., .)
+{
+ if ((CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type)) && (m68k->has_pmmu))
+ {
+ m68881_mmu_ops(m68k);
+ }
+ else
+ {
+ m68ki_exception_1111(m68k);
+ }
+}
+
+M68KMAKE_OP(reset, 0, ., .)
+{
+ if(m68k->s_flag)
+ {
+ if (m68k->reset_instr_callback != NULL)
+ (*m68k->reset_instr_callback)(m68k->device);
+ m68k->remaining_cycles -= m68k->cyc_reset;
+ return;
+ }
+ m68ki_exception_privilege_violation(m68k);
+}
+
+
+M68KMAKE_OP(ror, 8, s, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 orig_shift = (((m68k->ir >> 9) - 1) & 7) + 1;
+ UINT32 shift = orig_shift & 7;
+ UINT32 src = MASK_OUT_ABOVE_8(*r_dst);
+ UINT32 res = ROR_8(src, shift);
+
+ if(orig_shift != 0)
+ m68k->remaining_cycles -= orig_shift<<m68k->cyc_shift;
+
+ *r_dst = MASK_OUT_BELOW_8(*r_dst) | res;
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = src << (9-orig_shift);
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(ror, 16, s, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 shift = (((m68k->ir >> 9) - 1) & 7) + 1;
+ UINT32 src = MASK_OUT_ABOVE_16(*r_dst);
+ UINT32 res = ROR_16(src, shift);
+
+ if(shift != 0)
+ m68k->remaining_cycles -= shift<<m68k->cyc_shift;
+
+ *r_dst = MASK_OUT_BELOW_16(*r_dst) | res;
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = src << (9-shift);
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(ror, 32, s, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 shift = (((m68k->ir >> 9) - 1) & 7) + 1;
+ UINT64 src = *r_dst;
+ UINT32 res = ROR_32(src, shift);
+
+ if(shift != 0)
+ m68k->remaining_cycles -= shift<<m68k->cyc_shift;
+
+ *r_dst = res;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = src << (9-shift);
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(ror, 8, r, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 orig_shift = DX & 0x3f;
+ UINT32 shift = orig_shift & 7;
+ UINT32 src = MASK_OUT_ABOVE_8(*r_dst);
+ UINT32 res = ROR_8(src, shift);
+
+ if(orig_shift != 0)
+ {
+ m68k->remaining_cycles -= orig_shift<<m68k->cyc_shift;
+
+ *r_dst = MASK_OUT_BELOW_8(*r_dst) | res;
+ m68k->c_flag = src << (8-((shift-1)&7));
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ return;
+ }
+
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->n_flag = NFLAG_8(src);
+ m68k->not_z_flag = src;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(ror, 16, r, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 orig_shift = DX & 0x3f;
+ UINT32 shift = orig_shift & 15;
+ UINT32 src = MASK_OUT_ABOVE_16(*r_dst);
+ UINT32 res = ROR_16(src, shift);
+
+ if(orig_shift != 0)
+ {
+ m68k->remaining_cycles -= orig_shift<<m68k->cyc_shift;
+
+ *r_dst = MASK_OUT_BELOW_16(*r_dst) | res;
+ m68k->c_flag = (src >> ((shift - 1) & 15)) << 8;
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ return;
+ }
+
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->n_flag = NFLAG_16(src);
+ m68k->not_z_flag = src;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(ror, 32, r, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 orig_shift = DX & 0x3f;
+ UINT32 shift = orig_shift & 31;
+ UINT64 src = *r_dst;
+ UINT32 res = ROR_32(src, shift);
+
+ if(orig_shift != 0)
+ {
+ m68k->remaining_cycles -= orig_shift<<m68k->cyc_shift;
+
+ *r_dst = res;
+ m68k->c_flag = (src >> ((shift - 1) & 31)) << 8;
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ return;
+ }
+
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->n_flag = NFLAG_32(src);
+ m68k->not_z_flag = src;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(ror, 16, ., .)
+{
+ UINT32 ea = M68KMAKE_GET_EA_AY_16;
+ UINT32 src = m68ki_read_16(m68k, ea);
+ UINT32 res = ROR_16(src, 1);
+
+ m68ki_write_16(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = src << 8;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(rol, 8, s, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 orig_shift = (((m68k->ir >> 9) - 1) & 7) + 1;
+ UINT32 shift = orig_shift & 7;
+ UINT32 src = MASK_OUT_ABOVE_8(*r_dst);
+ UINT32 res = ROL_8(src, shift);
+
+ if(orig_shift != 0)
+ m68k->remaining_cycles -= orig_shift<<m68k->cyc_shift;
+
+ *r_dst = MASK_OUT_BELOW_8(*r_dst) | res;
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = src << orig_shift;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(rol, 16, s, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 shift = (((m68k->ir >> 9) - 1) & 7) + 1;
+ UINT32 src = MASK_OUT_ABOVE_16(*r_dst);
+ UINT32 res = ROL_16(src, shift);
+
+ if(shift != 0)
+ m68k->remaining_cycles -= shift<<m68k->cyc_shift;
+
+ *r_dst = MASK_OUT_BELOW_16(*r_dst) | res;
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = src >> (8-shift);
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(rol, 32, s, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 shift = (((m68k->ir >> 9) - 1) & 7) + 1;
+ UINT64 src = *r_dst;
+ UINT32 res = ROL_32(src, shift);
+
+ if(shift != 0)
+ m68k->remaining_cycles -= shift<<m68k->cyc_shift;
+
+ *r_dst = res;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = src >> (24-shift);
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(rol, 8, r, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 orig_shift = DX & 0x3f;
+ UINT32 shift = orig_shift & 7;
+ UINT32 src = MASK_OUT_ABOVE_8(*r_dst);
+ UINT32 res = ROL_8(src, shift);
+
+ if(orig_shift != 0)
+ {
+ m68k->remaining_cycles -= orig_shift<<m68k->cyc_shift;
+
+ if(shift != 0)
+ {
+ *r_dst = MASK_OUT_BELOW_8(*r_dst) | res;
+ m68k->c_flag = src << shift;
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ return;
+ }
+ m68k->c_flag = (src & 1)<<8;
+ m68k->n_flag = NFLAG_8(src);
+ m68k->not_z_flag = src;
+ m68k->v_flag = VFLAG_CLEAR;
+ return;
+ }
+
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->n_flag = NFLAG_8(src);
+ m68k->not_z_flag = src;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(rol, 16, r, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 orig_shift = DX & 0x3f;
+ UINT32 shift = orig_shift & 15;
+ UINT32 src = MASK_OUT_ABOVE_16(*r_dst);
+ UINT32 res = MASK_OUT_ABOVE_16(ROL_16(src, shift));
+
+ if(orig_shift != 0)
+ {
+ m68k->remaining_cycles -= orig_shift<<m68k->cyc_shift;
+
+ if(shift != 0)
+ {
+ *r_dst = MASK_OUT_BELOW_16(*r_dst) | res;
+ m68k->c_flag = (src << shift) >> 8;
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ return;
+ }
+ m68k->c_flag = (src & 1)<<8;
+ m68k->n_flag = NFLAG_16(src);
+ m68k->not_z_flag = src;
+ m68k->v_flag = VFLAG_CLEAR;
+ return;
+ }
+
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->n_flag = NFLAG_16(src);
+ m68k->not_z_flag = src;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(rol, 32, r, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 orig_shift = DX & 0x3f;
+ UINT32 shift = orig_shift & 31;
+ UINT64 src = *r_dst;
+ UINT32 res = ROL_32(src, shift);
+
+ if(orig_shift != 0)
+ {
+ m68k->remaining_cycles -= orig_shift<<m68k->cyc_shift;
+
+ *r_dst = res;
+
+ m68k->c_flag = (src >> ((32 - shift) & 0x1f)) << 8;
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ return;
+ }
+
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->n_flag = NFLAG_32(src);
+ m68k->not_z_flag = src;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(rol, 16, ., .)
+{
+ UINT32 ea = M68KMAKE_GET_EA_AY_16;
+ UINT32 src = m68ki_read_16(m68k, ea);
+ UINT32 res = MASK_OUT_ABOVE_16(ROL_16(src, 1));
+
+ m68ki_write_16(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->c_flag = src >> 7;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(roxr, 8, s, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 shift = (((m68k->ir >> 9) - 1) & 7) + 1;
+ UINT32 src = MASK_OUT_ABOVE_8(*r_dst);
+ UINT32 res = ROR_9(src | (XFLAG_AS_1(m68k) << 8), shift);
+
+ if(shift != 0)
+ m68k->remaining_cycles -= shift<<m68k->cyc_shift;
+
+ m68k->c_flag = m68k->x_flag = res;
+ res = MASK_OUT_ABOVE_8(res);
+
+ *r_dst = MASK_OUT_BELOW_8(*r_dst) | res;
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(roxr, 16, s, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 shift = (((m68k->ir >> 9) - 1) & 7) + 1;
+ UINT32 src = MASK_OUT_ABOVE_16(*r_dst);
+ UINT32 res = ROR_17(src | (XFLAG_AS_1(m68k) << 16), shift);
+
+ if(shift != 0)
+ m68k->remaining_cycles -= shift<<m68k->cyc_shift;
+
+ m68k->c_flag = m68k->x_flag = res >> 8;
+ res = MASK_OUT_ABOVE_16(res);
+
+ *r_dst = MASK_OUT_BELOW_16(*r_dst) | res;
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(roxr, 32, s, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 shift = (((m68k->ir >> 9) - 1) & 7) + 1;
+ UINT64 src = *r_dst;
+ UINT64 res = src | (((UINT64)XFLAG_AS_1(m68k)) << 32);
+
+ if(shift != 0)
+ m68k->remaining_cycles -= shift<<m68k->cyc_shift;
+
+ res = ROR_33_64(res, shift);
+
+ m68k->c_flag = m68k->x_flag = res >> 24;
+ res = MASK_OUT_ABOVE_32(res);
+
+ *r_dst = res;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(roxr, 8, r, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 orig_shift = DX & 0x3f;
+
+ if(orig_shift != 0)
+ {
+ UINT32 shift = orig_shift % 9;
+ UINT32 src = MASK_OUT_ABOVE_8(*r_dst);
+ UINT32 res = ROR_9(src | (XFLAG_AS_1(m68k) << 8), shift);
+
+ m68k->remaining_cycles -= orig_shift<<m68k->cyc_shift;
+
+ m68k->c_flag = m68k->x_flag = res;
+ res = MASK_OUT_ABOVE_8(res);
+
+ *r_dst = MASK_OUT_BELOW_8(*r_dst) | res;
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ return;
+ }
+
+ m68k->c_flag = m68k->x_flag;
+ m68k->n_flag = NFLAG_8(*r_dst);
+ m68k->not_z_flag = MASK_OUT_ABOVE_8(*r_dst);
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(roxr, 16, r, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 orig_shift = DX & 0x3f;
+
+ if(orig_shift != 0)
+ {
+ UINT32 shift = orig_shift % 17;
+ UINT32 src = MASK_OUT_ABOVE_16(*r_dst);
+ UINT32 res = ROR_17(src | (XFLAG_AS_1(m68k) << 16), shift);
+
+ m68k->remaining_cycles -= orig_shift<<m68k->cyc_shift;
+
+ m68k->c_flag = m68k->x_flag = res >> 8;
+ res = MASK_OUT_ABOVE_16(res);
+
+ *r_dst = MASK_OUT_BELOW_16(*r_dst) | res;
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ return;
+ }
+
+ m68k->c_flag = m68k->x_flag;
+ m68k->n_flag = NFLAG_16(*r_dst);
+ m68k->not_z_flag = MASK_OUT_ABOVE_16(*r_dst);
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(roxr, 32, r, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 orig_shift = DX & 0x3f;
+
+ if(orig_shift != 0)
+ {
+ UINT32 shift = orig_shift % 33;
+ UINT64 src = *r_dst;
+ UINT64 res = src | (((UINT64)XFLAG_AS_1(m68k)) << 32);
+
+ res = ROR_33_64(res, shift);
+
+ m68k->remaining_cycles -= orig_shift<<m68k->cyc_shift;
+
+ m68k->c_flag = m68k->x_flag = res >> 24;
+ res = MASK_OUT_ABOVE_32(res);
+
+ *r_dst = res;
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ return;
+ }
+
+ m68k->c_flag = m68k->x_flag;
+ m68k->n_flag = NFLAG_32(*r_dst);
+ m68k->not_z_flag = *r_dst;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(roxr, 16, ., .)
+{
+ UINT32 ea = M68KMAKE_GET_EA_AY_16;
+ UINT32 src = m68ki_read_16(m68k, ea);
+ UINT32 res = ROR_17(src | (XFLAG_AS_1(m68k) << 16), 1);
+
+ m68k->c_flag = m68k->x_flag = res >> 8;
+ res = MASK_OUT_ABOVE_16(res);
+
+ m68ki_write_16(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(roxl, 8, s, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 shift = (((m68k->ir >> 9) - 1) & 7) + 1;
+ UINT32 src = MASK_OUT_ABOVE_8(*r_dst);
+ UINT32 res = ROL_9(src | (XFLAG_AS_1(m68k) << 8), shift);
+
+ if(shift != 0)
+ m68k->remaining_cycles -= shift<<m68k->cyc_shift;
+
+ m68k->c_flag = m68k->x_flag = res;
+ res = MASK_OUT_ABOVE_8(res);
+
+ *r_dst = MASK_OUT_BELOW_8(*r_dst) | res;
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(roxl, 16, s, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 shift = (((m68k->ir >> 9) - 1) & 7) + 1;
+ UINT32 src = MASK_OUT_ABOVE_16(*r_dst);
+ UINT32 res = ROL_17(src | (XFLAG_AS_1(m68k) << 16), shift);
+
+ if(shift != 0)
+ m68k->remaining_cycles -= shift<<m68k->cyc_shift;
+
+ m68k->c_flag = m68k->x_flag = res >> 8;
+ res = MASK_OUT_ABOVE_16(res);
+
+ *r_dst = MASK_OUT_BELOW_16(*r_dst) | res;
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(roxl, 32, s, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 shift = (((m68k->ir >> 9) - 1) & 7) + 1;
+ UINT64 src = *r_dst;
+ UINT64 res = src | (((UINT64)XFLAG_AS_1(m68k)) << 32);
+
+ if(shift != 0)
+ m68k->remaining_cycles -= shift<<m68k->cyc_shift;
+
+ res = ROL_33_64(res, shift);
+
+ m68k->c_flag = m68k->x_flag = res >> 24;
+ res = MASK_OUT_ABOVE_32(res);
+
+ *r_dst = res;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(roxl, 8, r, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 orig_shift = DX & 0x3f;
+
+
+ if(orig_shift != 0)
+ {
+ UINT32 shift = orig_shift % 9;
+ UINT32 src = MASK_OUT_ABOVE_8(*r_dst);
+ UINT32 res = ROL_9(src | (XFLAG_AS_1(m68k) << 8), shift);
+
+ m68k->remaining_cycles -= orig_shift<<m68k->cyc_shift;
+
+ m68k->c_flag = m68k->x_flag = res;
+ res = MASK_OUT_ABOVE_8(res);
+
+ *r_dst = MASK_OUT_BELOW_8(*r_dst) | res;
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ return;
+ }
+
+ m68k->c_flag = m68k->x_flag;
+ m68k->n_flag = NFLAG_8(*r_dst);
+ m68k->not_z_flag = MASK_OUT_ABOVE_8(*r_dst);
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(roxl, 16, r, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 orig_shift = DX & 0x3f;
+
+ if(orig_shift != 0)
+ {
+ UINT32 shift = orig_shift % 17;
+ UINT32 src = MASK_OUT_ABOVE_16(*r_dst);
+ UINT32 res = ROL_17(src | (XFLAG_AS_1(m68k) << 16), shift);
+
+ m68k->remaining_cycles -= orig_shift<<m68k->cyc_shift;
+
+ m68k->c_flag = m68k->x_flag = res >> 8;
+ res = MASK_OUT_ABOVE_16(res);
+
+ *r_dst = MASK_OUT_BELOW_16(*r_dst) | res;
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ return;
+ }
+
+ m68k->c_flag = m68k->x_flag;
+ m68k->n_flag = NFLAG_16(*r_dst);
+ m68k->not_z_flag = MASK_OUT_ABOVE_16(*r_dst);
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(roxl, 32, r, .)
+{
+ UINT32* r_dst = &DY;
+ UINT32 orig_shift = DX & 0x3f;
+
+ if(orig_shift != 0)
+ {
+ UINT32 shift = orig_shift % 33;
+ UINT64 src = *r_dst;
+ UINT64 res = src | (((UINT64)XFLAG_AS_1(m68k)) << 32);
+
+ res = ROL_33_64(res, shift);
+
+ m68k->remaining_cycles -= orig_shift<<m68k->cyc_shift;
+
+ m68k->c_flag = m68k->x_flag = res >> 24;
+ res = MASK_OUT_ABOVE_32(res);
+
+ *r_dst = res;
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ return;
+ }
+
+ m68k->c_flag = m68k->x_flag;
+ m68k->n_flag = NFLAG_32(*r_dst);
+ m68k->not_z_flag = *r_dst;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(roxl, 16, ., .)
+{
+ UINT32 ea = M68KMAKE_GET_EA_AY_16;
+ UINT32 src = m68ki_read_16(m68k, ea);
+ UINT32 res = ROL_17(src | (XFLAG_AS_1(m68k) << 16), 1);
+
+ m68k->c_flag = m68k->x_flag = res >> 8;
+ res = MASK_OUT_ABOVE_16(res);
+
+ m68ki_write_16(m68k, ea, res);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(rtd, 32, ., .)
+{
+ if(CPU_TYPE_IS_010_PLUS(m68k->cpu_type))
+ {
+ UINT32 new_pc = m68ki_pull_32(m68k);
+
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+ REG_A[7] = MASK_OUT_ABOVE_32(REG_A[7] + MAKE_INT_16(OPER_I_16(m68k)));
+ m68ki_jump(m68k, new_pc);
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(rte, 32, ., .)
+{
+ if(m68k->s_flag)
+ {
+ UINT32 new_sr;
+ UINT32 new_pc;
+ UINT32 format_word;
+
+ if (m68k->rte_instr_callback != NULL)
+ (*m68k->rte_instr_callback)(m68k->device);
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+
+ if(CPU_TYPE_IS_000(m68k->cpu_type))
+ {
+ new_sr = m68ki_pull_16(m68k);
+ new_pc = m68ki_pull_32(m68k);
+ m68ki_jump(m68k, new_pc);
+ m68ki_set_sr(m68k, new_sr);
+
+ m68k->instr_mode = INSTRUCTION_YES;
+ m68k->run_mode = RUN_MODE_NORMAL;
+
+ return;
+ }
+
+ if(CPU_TYPE_IS_010(m68k->cpu_type))
+ {
+ format_word = m68ki_read_16(m68k, REG_A[7]+6) >> 12;
+ if(format_word == 0)
+ {
+ new_sr = m68ki_pull_16(m68k);
+ new_pc = m68ki_pull_32(m68k);
+ m68ki_fake_pull_16(m68k); /* format word */
+ m68ki_jump(m68k, new_pc);
+ m68ki_set_sr(m68k, new_sr);
+ m68k->instr_mode = INSTRUCTION_YES;
+ m68k->run_mode = RUN_MODE_NORMAL;
+ return;
+ }
+ m68k->instr_mode = INSTRUCTION_YES;
+ m68k->run_mode = RUN_MODE_NORMAL;
+ /* Not handling bus fault (9) */
+ m68ki_exception_format_error(m68k);
+ return;
+ }
+
+ /* Otherwise it's 020 */
+rte_loop:
+ format_word = m68ki_read_16(m68k, REG_A[7]+6) >> 12;
+ switch(format_word)
+ {
+ case 0: /* Normal */
+ new_sr = m68ki_pull_16(m68k);
+ new_pc = m68ki_pull_32(m68k);
+ m68ki_fake_pull_16(m68k); /* format word */
+ m68ki_jump(m68k, new_pc);
+ m68ki_set_sr(m68k, new_sr);
+ m68k->instr_mode = INSTRUCTION_YES;
+ m68k->run_mode = RUN_MODE_NORMAL;
+ return;
+ case 1: /* Throwaway */
+ new_sr = m68ki_pull_16(m68k);
+ m68ki_fake_pull_32(m68k); /* program counter */
+ m68ki_fake_pull_16(m68k); /* format word */
+ m68ki_set_sr_noint(m68k, new_sr);
+ goto rte_loop;
+ case 2: /* Trap */
+ new_sr = m68ki_pull_16(m68k);
+ new_pc = m68ki_pull_32(m68k);
+ m68ki_fake_pull_16(m68k); /* format word */
+ m68ki_fake_pull_32(m68k); /* address */
+ m68ki_jump(m68k, new_pc);
+ m68ki_set_sr(m68k, new_sr);
+ m68k->instr_mode = INSTRUCTION_YES;
+ m68k->run_mode = RUN_MODE_NORMAL;
+ return;
+ case 0x0a: /* Bus Error at instruction boundary */
+ new_sr = m68ki_pull_16(m68k);
+ new_pc = m68ki_pull_32(m68k);
+ m68ki_fake_pull_16(m68k); /* $06: format word */
+ m68ki_fake_pull_16(m68k); /* $08: internal register */
+ m68ki_fake_pull_16(m68k); /* $0a: special status word */
+ m68ki_fake_pull_16(m68k); /* $0c: instruction pipe stage c */
+ m68ki_fake_pull_16(m68k); /* $0e: instruction pipe stage b */
+ m68ki_fake_pull_32(m68k); /* $10: data fault address */
+ m68ki_fake_pull_32(m68k); /* $14: internal registers */
+ m68ki_fake_pull_32(m68k); /* $18: data output buffer */
+ m68ki_fake_pull_32(m68k); /* $1c: internal registers */
+
+ m68ki_jump(m68k, new_pc);
+ m68ki_set_sr(m68k, new_sr);
+ m68k->instr_mode = INSTRUCTION_YES;
+ m68k->run_mode = RUN_MODE_NORMAL;
+ return;
+ case 0x0b: /* Bus Error - Instruction Execution in Progress */
+ new_sr = m68ki_pull_16(m68k);
+ new_pc = m68ki_pull_32(m68k);
+ m68ki_fake_pull_16(m68k); /* $06: format word */
+ m68ki_fake_pull_16(m68k); /* $08: internal register */
+ m68ki_fake_pull_16(m68k); /* $0a: special status word */
+ m68ki_fake_pull_16(m68k); /* $0c: instruction pipe stage c */
+ m68ki_fake_pull_16(m68k); /* $0e: instruction pipe stage b */
+ m68ki_fake_pull_32(m68k); /* $10: data fault address */
+ m68ki_fake_pull_32(m68k); /* $14: internal registers */
+ m68ki_fake_pull_32(m68k); /* $18: data output buffer */
+ m68ki_fake_pull_32(m68k); /* $1c: internal registers */
+ m68ki_fake_pull_32(m68k); /* $20: */
+ m68ki_fake_pull_32(m68k); /* $24: stage B address */
+ m68ki_fake_pull_32(m68k); /* $28: */
+ m68ki_fake_pull_32(m68k); /* $2c: data input buffer */
+ m68ki_fake_pull_32(m68k); /* $30: */
+ m68ki_fake_pull_16(m68k); /* $34: */
+ m68ki_fake_pull_16(m68k); /* $36: version #, internal information */
+ m68ki_fake_pull_32(m68k); /* $38: */
+ m68ki_fake_pull_32(m68k); /* $3c: */
+ m68ki_fake_pull_32(m68k); /* $40: */
+ m68ki_fake_pull_32(m68k); /* $44: */
+ m68ki_fake_pull_32(m68k); /* $48: */
+ m68ki_fake_pull_32(m68k); /* $4c: */
+ m68ki_fake_pull_32(m68k); /* $50: */
+ m68ki_fake_pull_32(m68k); /* $54: */
+ m68ki_fake_pull_32(m68k); /* $58: */
+
+ m68ki_jump(m68k, new_pc);
+ m68ki_set_sr(m68k, new_sr);
+ m68k->instr_mode = INSTRUCTION_YES;
+ m68k->run_mode = RUN_MODE_NORMAL;
+ return;
+ }
+ /* Not handling long or short bus fault */
+ m68k->instr_mode = INSTRUCTION_YES;
+ m68k->run_mode = RUN_MODE_NORMAL;
+ m68ki_exception_format_error(m68k);
+ return;
+ }
+ m68ki_exception_privilege_violation(m68k);
+}
+
+
+M68KMAKE_OP(rtm, 32, ., .)
+{
+ if(CPU_TYPE_IS_020_VARIANT(m68k->cpu_type))
+ {
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+ logerror("%s at %08x: called unimplemented instruction %04x (rtm)\n",
+ m68k->device->tag(), REG_PC - 2, m68k->ir);
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(rtr, 32, ., .)
+{
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+ m68ki_set_ccr(m68k, m68ki_pull_16(m68k));
+ m68ki_jump(m68k, m68ki_pull_32(m68k));
+}
+
+
+M68KMAKE_OP(rts, 32, ., .)
+{
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+ m68ki_jump(m68k, m68ki_pull_32(m68k));
+}
+
+
+M68KMAKE_OP(sbcd, 8, rr, .)
+{
+ UINT32* r_dst = &DX;
+ UINT32 src = DY;
+ UINT32 dst = *r_dst;
+ UINT32 res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(m68k);
+
+// m68k->v_flag = ~res; /* Undefined V behavior */
+ m68k->v_flag = VFLAG_CLEAR; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to assume cleared. */
+
+ if(res > 9)
+ res -= 6;
+ res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src);
+ if(res > 0x99)
+ {
+ res += 0xa0;
+ m68k->x_flag = m68k->c_flag = CFLAG_SET;
+ m68k->n_flag = NFLAG_SET; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to follow carry. */
+ }
+ else
+ m68k->n_flag = m68k->x_flag = m68k->c_flag = 0;
+
+ res = MASK_OUT_ABOVE_8(res);
+
+// m68k->v_flag &= res; /* Undefined V behavior part II */
+// m68k->n_flag = NFLAG_8(res); /* Undefined N behavior */
+ m68k->not_z_flag |= res;
+
+ *r_dst = MASK_OUT_BELOW_8(*r_dst) | res;
+}
+
+
+M68KMAKE_OP(sbcd, 8, mm, ax7)
+{
+ UINT32 src = OPER_AY_PD_8(m68k);
+ UINT32 ea = EA_A7_PD_8(m68k);
+ UINT32 dst = m68ki_read_8(m68k, ea);
+ UINT32 res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(m68k);
+
+// m68k->v_flag = ~res; /* Undefined V behavior */
+ m68k->v_flag = VFLAG_CLEAR; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to return zero. */
+
+ if(res > 9)
+ res -= 6;
+ res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src);
+ if(res > 0x99)
+ {
+ res += 0xa0;
+ m68k->x_flag = m68k->c_flag = CFLAG_SET;
+ m68k->n_flag = NFLAG_SET; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to follow carry. */
+ }
+ else
+ m68k->n_flag = m68k->x_flag = m68k->c_flag = 0;
+
+ res = MASK_OUT_ABOVE_8(res);
+
+// m68k->v_flag &= res; /* Undefined V behavior part II */
+// m68k->n_flag = NFLAG_8(res); /* Undefined N behavior */
+ m68k->not_z_flag |= res;
+
+ m68ki_write_8(m68k, ea, res);
+}
+
+
+M68KMAKE_OP(sbcd, 8, mm, ay7)
+{
+ UINT32 src = OPER_A7_PD_8(m68k);
+ UINT32 ea = EA_AX_PD_8(m68k);
+ UINT32 dst = m68ki_read_8(m68k, ea);
+ UINT32 res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(m68k);
+
+// m68k->v_flag = ~res; /* Undefined V behavior */
+ m68k->v_flag = VFLAG_CLEAR; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to return zero. */
+
+ if(res > 9)
+ res -= 6;
+ res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src);
+ if(res > 0x99)
+ {
+ res += 0xa0;
+ m68k->x_flag = m68k->c_flag = CFLAG_SET;
+ m68k->n_flag = NFLAG_SET; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to follow carry. */
+ }
+ else
+ m68k->n_flag = m68k->x_flag = m68k->c_flag = 0;
+
+ res = MASK_OUT_ABOVE_8(res);
+
+// m68k->v_flag &= res; /* Undefined V behavior part II */
+// m68k->n_flag = NFLAG_8(res); /* Undefined N behavior */
+ m68k->not_z_flag |= res;
+
+ m68ki_write_8(m68k, ea, res);
+}
+
+
+M68KMAKE_OP(sbcd, 8, mm, axy7)
+{
+ UINT32 src = OPER_A7_PD_8(m68k);
+ UINT32 ea = EA_A7_PD_8(m68k);
+ UINT32 dst = m68ki_read_8(m68k, ea);
+ UINT32 res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(m68k);
+
+// m68k->v_flag = ~res; /* Undefined V behavior */
+ m68k->v_flag = VFLAG_CLEAR; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to return zero. */
+
+ if(res > 9)
+ res -= 6;
+ res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src);
+ if(res > 0x99)
+ {
+ res += 0xa0;
+ m68k->x_flag = m68k->c_flag = CFLAG_SET;
+ m68k->n_flag = NFLAG_SET; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to follow carry. */
+ }
+ else
+ m68k->n_flag = m68k->x_flag = m68k->c_flag = 0;
+
+ res = MASK_OUT_ABOVE_8(res);
+
+// m68k->v_flag &= res; /* Undefined V behavior part II */
+// m68k->n_flag = NFLAG_8(res); /* Undefined N behavior */
+ m68k->not_z_flag |= res;
+
+ m68ki_write_8(m68k, ea, res);
+}
+
+
+M68KMAKE_OP(sbcd, 8, mm, .)
+{
+ UINT32 src = OPER_AY_PD_8(m68k);
+ UINT32 ea = EA_AX_PD_8(m68k);
+ UINT32 dst = m68ki_read_8(m68k, ea);
+ UINT32 res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(m68k);
+
+// m68k->v_flag = ~res; /* Undefined V behavior */
+ m68k->v_flag = VFLAG_CLEAR; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to return zero. */
+
+ if(res > 9)
+ res -= 6;
+ res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src);
+ if(res > 0x99)
+ {
+ res += 0xa0;
+ m68k->x_flag = m68k->c_flag = CFLAG_SET;
+ m68k->n_flag = NFLAG_SET; /* Undefined in Motorola's M68000PM/AD rev.1 and safer to follow carry. */
+ }
+ else
+ m68k->n_flag = m68k->x_flag = m68k->c_flag = 0;
+
+ res = MASK_OUT_ABOVE_8(res);
+
+// m68k->v_flag &= res; /* Undefined V behavior part II */
+// m68k->n_flag = NFLAG_8(res); /* Undefined N behavior */
+ m68k->not_z_flag |= res;
+
+ m68ki_write_8(m68k, ea, res);
+}
+
+
+M68KMAKE_OP(st, 8, ., d)
+{
+ DY |= 0xff;
+}
+
+
+M68KMAKE_OP(st, 8, ., .)
+{
+ m68ki_write_8(m68k, M68KMAKE_GET_EA_AY_8, 0xff);
+}
+
+
+M68KMAKE_OP(sf, 8, ., d)
+{
+ DY &= 0xffffff00;
+}
+
+
+M68KMAKE_OP(sf, 8, ., .)
+{
+ m68ki_write_8(m68k, M68KMAKE_GET_EA_AY_8, 0);
+}
+
+
+M68KMAKE_OP(scc, 8, ., d)
+{
+ if(M68KMAKE_CC)
+ {
+ DY |= 0xff;
+ m68k->remaining_cycles -= m68k->cyc_scc_r_true;
+ return;
+ }
+ DY &= 0xffffff00;
+}
+
+
+M68KMAKE_OP(scc, 8, ., .)
+{
+ m68ki_write_8(m68k, M68KMAKE_GET_EA_AY_8, M68KMAKE_CC ? 0xff : 0);
+}
+
+
+M68KMAKE_OP(stop, 0, ., .)
+{
+ if(m68k->s_flag)
+ {
+ UINT32 new_sr = OPER_I_16(m68k);
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+ m68k->stopped |= STOP_LEVEL_STOP;
+ m68ki_set_sr(m68k, new_sr);
+ m68k->remaining_cycles = 0;
+ return;
+ }
+ m68ki_exception_privilege_violation(m68k);
+}
+
+
+M68KMAKE_OP(sub, 8, er, d)
+{
+ UINT32* r_dst = &DX;
+ UINT32 src = MASK_OUT_ABOVE_8(DY);
+ UINT32 dst = MASK_OUT_ABOVE_8(*r_dst);
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->x_flag = m68k->c_flag = CFLAG_8(res);
+ m68k->v_flag = VFLAG_SUB_8(src, dst, res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_8(res);
+
+ *r_dst = MASK_OUT_BELOW_8(*r_dst) | m68k->not_z_flag;
+}
+
+
+M68KMAKE_OP(sub, 8, er, .)
+{
+ UINT32* r_dst = &DX;
+ UINT32 src = M68KMAKE_GET_OPER_AY_8;
+ UINT32 dst = MASK_OUT_ABOVE_8(*r_dst);
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->x_flag = m68k->c_flag = CFLAG_8(res);
+ m68k->v_flag = VFLAG_SUB_8(src, dst, res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_8(res);
+
+ *r_dst = MASK_OUT_BELOW_8(*r_dst) | m68k->not_z_flag;
+}
+
+
+M68KMAKE_OP(sub, 16, er, d)
+{
+ UINT32* r_dst = &DX;
+ UINT32 src = MASK_OUT_ABOVE_16(DY);
+ UINT32 dst = MASK_OUT_ABOVE_16(*r_dst);
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->x_flag = m68k->c_flag = CFLAG_16(res);
+ m68k->v_flag = VFLAG_SUB_16(src, dst, res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_16(res);
+
+ *r_dst = MASK_OUT_BELOW_16(*r_dst) | m68k->not_z_flag;
+}
+
+
+M68KMAKE_OP(sub, 16, er, a)
+{
+ UINT32* r_dst = &DX;
+ UINT32 src = MASK_OUT_ABOVE_16(AY);
+ UINT32 dst = MASK_OUT_ABOVE_16(*r_dst);
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->x_flag = m68k->c_flag = CFLAG_16(res);
+ m68k->v_flag = VFLAG_SUB_16(src, dst, res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_16(res);
+
+ *r_dst = MASK_OUT_BELOW_16(*r_dst) | m68k->not_z_flag;
+}
+
+
+M68KMAKE_OP(sub, 16, er, .)
+{
+ UINT32* r_dst = &DX;
+ UINT32 src = M68KMAKE_GET_OPER_AY_16;
+ UINT32 dst = MASK_OUT_ABOVE_16(*r_dst);
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->x_flag = m68k->c_flag = CFLAG_16(res);
+ m68k->v_flag = VFLAG_SUB_16(src, dst, res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_16(res);
+
+ *r_dst = MASK_OUT_BELOW_16(*r_dst) | m68k->not_z_flag;
+}
+
+
+M68KMAKE_OP(sub, 32, er, d)
+{
+ UINT32* r_dst = &DX;
+ UINT32 src = DY;
+ UINT32 dst = *r_dst;
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->x_flag = m68k->c_flag = CFLAG_SUB_32(src, dst, res);
+ m68k->v_flag = VFLAG_SUB_32(src, dst, res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res);
+
+ *r_dst = m68k->not_z_flag;
+}
+
+
+M68KMAKE_OP(sub, 32, er, a)
+{
+ UINT32* r_dst = &DX;
+ UINT32 src = AY;
+ UINT32 dst = *r_dst;
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->x_flag = m68k->c_flag = CFLAG_SUB_32(src, dst, res);
+ m68k->v_flag = VFLAG_SUB_32(src, dst, res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res);
+
+ *r_dst = m68k->not_z_flag;
+}
+
+
+M68KMAKE_OP(sub, 32, er, .)
+{
+ UINT32* r_dst = &DX;
+ UINT32 src = M68KMAKE_GET_OPER_AY_32;
+ UINT32 dst = *r_dst;
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->x_flag = m68k->c_flag = CFLAG_SUB_32(src, dst, res);
+ m68k->v_flag = VFLAG_SUB_32(src, dst, res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res);
+
+ *r_dst = m68k->not_z_flag;
+}
+
+
+M68KMAKE_OP(sub, 8, re, .)
+{
+ UINT32 ea = M68KMAKE_GET_EA_AY_8;
+ UINT32 src = MASK_OUT_ABOVE_8(DX);
+ UINT32 dst = m68ki_read_8(m68k, ea);
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_8(res);
+ m68k->x_flag = m68k->c_flag = CFLAG_8(res);
+ m68k->v_flag = VFLAG_SUB_8(src, dst, res);
+
+ m68ki_write_8(m68k, ea, m68k->not_z_flag);
+}
+
+
+M68KMAKE_OP(sub, 16, re, .)
+{
+ UINT32 ea = M68KMAKE_GET_EA_AY_16;
+ UINT32 src = MASK_OUT_ABOVE_16(DX);
+ UINT32 dst = m68ki_read_16(m68k, ea);
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_16(res);
+ m68k->x_flag = m68k->c_flag = CFLAG_16(res);
+ m68k->v_flag = VFLAG_SUB_16(src, dst, res);
+
+ m68ki_write_16(m68k, ea, m68k->not_z_flag);
+}
+
+
+M68KMAKE_OP(sub, 32, re, .)
+{
+ UINT32 ea = M68KMAKE_GET_EA_AY_32;
+ UINT32 src = DX;
+ UINT32 dst = m68ki_read_32(m68k, ea);
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res);
+ m68k->x_flag = m68k->c_flag = CFLAG_SUB_32(src, dst, res);
+ m68k->v_flag = VFLAG_SUB_32(src, dst, res);
+
+ m68ki_write_32(m68k, ea, m68k->not_z_flag);
+}
+
+
+M68KMAKE_OP(suba, 16, ., d)
+{
+ UINT32* r_dst = &AX;
+
+ *r_dst = MASK_OUT_ABOVE_32(*r_dst - MAKE_INT_16(DY));
+}
+
+
+M68KMAKE_OP(suba, 16, ., a)
+{
+ UINT32* r_dst = &AX;
+
+ *r_dst = MASK_OUT_ABOVE_32(*r_dst - MAKE_INT_16(AY));
+}
+
+
+M68KMAKE_OP(suba, 16, ., .)
+{
+ UINT32* r_dst = &AX;
+ UINT32 src = MAKE_INT_16(M68KMAKE_GET_OPER_AY_16);
+
+ *r_dst = MASK_OUT_ABOVE_32(*r_dst - src);
+}
+
+
+M68KMAKE_OP(suba, 32, ., d)
+{
+ UINT32* r_dst = &AX;
+
+ *r_dst = MASK_OUT_ABOVE_32(*r_dst - DY);
+}
+
+
+M68KMAKE_OP(suba, 32, ., a)
+{
+ UINT32* r_dst = &AX;
+
+ *r_dst = MASK_OUT_ABOVE_32(*r_dst - AY);
+}
+
+
+M68KMAKE_OP(suba, 32, ., .)
+{
+ UINT32* r_dst = &AX;
+ UINT32 src = M68KMAKE_GET_OPER_AY_32;
+
+ *r_dst = MASK_OUT_ABOVE_32(*r_dst - src);
+}
+
+
+M68KMAKE_OP(subi, 8, ., d)
+{
+ UINT32* r_dst = &DY;
+ UINT32 src = OPER_I_8(m68k);
+ UINT32 dst = MASK_OUT_ABOVE_8(*r_dst);
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_8(res);
+ m68k->x_flag = m68k->c_flag = CFLAG_8(res);
+ m68k->v_flag = VFLAG_SUB_8(src, dst, res);
+
+ *r_dst = MASK_OUT_BELOW_8(*r_dst) | m68k->not_z_flag;
+}
+
+
+M68KMAKE_OP(subi, 8, ., .)
+{
+ UINT32 src = OPER_I_8(m68k);
+ UINT32 ea = M68KMAKE_GET_EA_AY_8;
+ UINT32 dst = m68ki_read_8(m68k, ea);
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_8(res);
+ m68k->x_flag = m68k->c_flag = CFLAG_8(res);
+ m68k->v_flag = VFLAG_SUB_8(src, dst, res);
+
+ m68ki_write_8(m68k, ea, m68k->not_z_flag);
+}
+
+
+M68KMAKE_OP(subi, 16, ., d)
+{
+ UINT32* r_dst = &DY;
+ UINT32 src = OPER_I_16(m68k);
+ UINT32 dst = MASK_OUT_ABOVE_16(*r_dst);
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_16(res);
+ m68k->x_flag = m68k->c_flag = CFLAG_16(res);
+ m68k->v_flag = VFLAG_SUB_16(src, dst, res);
+
+ *r_dst = MASK_OUT_BELOW_16(*r_dst) | m68k->not_z_flag;
+}
+
+
+M68KMAKE_OP(subi, 16, ., .)
+{
+ UINT32 src = OPER_I_16(m68k);
+ UINT32 ea = M68KMAKE_GET_EA_AY_16;
+ UINT32 dst = m68ki_read_16(m68k, ea);
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_16(res);
+ m68k->x_flag = m68k->c_flag = CFLAG_16(res);
+ m68k->v_flag = VFLAG_SUB_16(src, dst, res);
+
+ m68ki_write_16(m68k, ea, m68k->not_z_flag);
+}
+
+
+M68KMAKE_OP(subi, 32, ., d)
+{
+ UINT32* r_dst = &DY;
+ UINT32 src = OPER_I_32(m68k);
+ UINT32 dst = *r_dst;
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res);
+ m68k->x_flag = m68k->c_flag = CFLAG_SUB_32(src, dst, res);
+ m68k->v_flag = VFLAG_SUB_32(src, dst, res);
+
+ *r_dst = m68k->not_z_flag;
+}
+
+
+M68KMAKE_OP(subi, 32, ., .)
+{
+ UINT32 src = OPER_I_32(m68k);
+ UINT32 ea = M68KMAKE_GET_EA_AY_32;
+ UINT32 dst = m68ki_read_32(m68k, ea);
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res);
+ m68k->x_flag = m68k->c_flag = CFLAG_SUB_32(src, dst, res);
+ m68k->v_flag = VFLAG_SUB_32(src, dst, res);
+
+ m68ki_write_32(m68k, ea, m68k->not_z_flag);
+}
+
+
+M68KMAKE_OP(subq, 8, ., d)
+{
+ UINT32* r_dst = &DY;
+ UINT32 src = (((m68k->ir >> 9) - 1) & 7) + 1;
+ UINT32 dst = MASK_OUT_ABOVE_8(*r_dst);
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_8(res);
+ m68k->x_flag = m68k->c_flag = CFLAG_8(res);
+ m68k->v_flag = VFLAG_SUB_8(src, dst, res);
+
+ *r_dst = MASK_OUT_BELOW_8(*r_dst) | m68k->not_z_flag;
+}
+
+
+M68KMAKE_OP(subq, 8, ., .)
+{
+ UINT32 src = (((m68k->ir >> 9) - 1) & 7) + 1;
+ UINT32 ea = M68KMAKE_GET_EA_AY_8;
+ UINT32 dst = m68ki_read_8(m68k, ea);
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_8(res);
+ m68k->x_flag = m68k->c_flag = CFLAG_8(res);
+ m68k->v_flag = VFLAG_SUB_8(src, dst, res);
+
+ m68ki_write_8(m68k, ea, m68k->not_z_flag);
+}
+
+
+M68KMAKE_OP(subq, 16, ., d)
+{
+ UINT32* r_dst = &DY;
+ UINT32 src = (((m68k->ir >> 9) - 1) & 7) + 1;
+ UINT32 dst = MASK_OUT_ABOVE_16(*r_dst);
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_16(res);
+ m68k->x_flag = m68k->c_flag = CFLAG_16(res);
+ m68k->v_flag = VFLAG_SUB_16(src, dst, res);
+
+ *r_dst = MASK_OUT_BELOW_16(*r_dst) | m68k->not_z_flag;
+}
+
+
+M68KMAKE_OP(subq, 16, ., a)
+{
+ UINT32* r_dst = &AY;
+
+ *r_dst = MASK_OUT_ABOVE_32(*r_dst - ((((m68k->ir >> 9) - 1) & 7) + 1));
+}
+
+
+M68KMAKE_OP(subq, 16, ., .)
+{
+ UINT32 src = (((m68k->ir >> 9) - 1) & 7) + 1;
+ UINT32 ea = M68KMAKE_GET_EA_AY_16;
+ UINT32 dst = m68ki_read_16(m68k, ea);
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_16(res);
+ m68k->x_flag = m68k->c_flag = CFLAG_16(res);
+ m68k->v_flag = VFLAG_SUB_16(src, dst, res);
+
+ m68ki_write_16(m68k, ea, m68k->not_z_flag);
+}
+
+
+M68KMAKE_OP(subq, 32, ., d)
+{
+ UINT32* r_dst = &DY;
+ UINT32 src = (((m68k->ir >> 9) - 1) & 7) + 1;
+ UINT32 dst = *r_dst;
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res);
+ m68k->x_flag = m68k->c_flag = CFLAG_SUB_32(src, dst, res);
+ m68k->v_flag = VFLAG_SUB_32(src, dst, res);
+
+ *r_dst = m68k->not_z_flag;
+}
+
+
+M68KMAKE_OP(subq, 32, ., a)
+{
+ UINT32* r_dst = &AY;
+
+ *r_dst = MASK_OUT_ABOVE_32(*r_dst - ((((m68k->ir >> 9) - 1) & 7) + 1));
+}
+
+
+M68KMAKE_OP(subq, 32, ., .)
+{
+ UINT32 src = (((m68k->ir >> 9) - 1) & 7) + 1;
+ UINT32 ea = M68KMAKE_GET_EA_AY_32;
+ UINT32 dst = m68ki_read_32(m68k, ea);
+ UINT32 res = dst - src;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(res);
+ m68k->x_flag = m68k->c_flag = CFLAG_SUB_32(src, dst, res);
+ m68k->v_flag = VFLAG_SUB_32(src, dst, res);
+
+ m68ki_write_32(m68k, ea, m68k->not_z_flag);
+}
+
+
+M68KMAKE_OP(subx, 8, rr, .)
+{
+ UINT32* r_dst = &DX;
+ UINT32 src = MASK_OUT_ABOVE_8(DY);
+ UINT32 dst = MASK_OUT_ABOVE_8(*r_dst);
+ UINT32 res = dst - src - XFLAG_AS_1(m68k);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->x_flag = m68k->c_flag = CFLAG_8(res);
+ m68k->v_flag = VFLAG_SUB_8(src, dst, res);
+
+ res = MASK_OUT_ABOVE_8(res);
+ m68k->not_z_flag |= res;
+
+ *r_dst = MASK_OUT_BELOW_8(*r_dst) | res;
+}
+
+
+M68KMAKE_OP(subx, 16, rr, .)
+{
+ UINT32* r_dst = &DX;
+ UINT32 src = MASK_OUT_ABOVE_16(DY);
+ UINT32 dst = MASK_OUT_ABOVE_16(*r_dst);
+ UINT32 res = dst - src - XFLAG_AS_1(m68k);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->x_flag = m68k->c_flag = CFLAG_16(res);
+ m68k->v_flag = VFLAG_SUB_16(src, dst, res);
+
+ res = MASK_OUT_ABOVE_16(res);
+ m68k->not_z_flag |= res;
+
+ *r_dst = MASK_OUT_BELOW_16(*r_dst) | res;
+}
+
+
+M68KMAKE_OP(subx, 32, rr, .)
+{
+ UINT32* r_dst = &DX;
+ UINT32 src = DY;
+ UINT32 dst = *r_dst;
+ UINT32 res = dst - src - XFLAG_AS_1(m68k);
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->x_flag = m68k->c_flag = CFLAG_SUB_32(src, dst, res);
+ m68k->v_flag = VFLAG_SUB_32(src, dst, res);
+
+ res = MASK_OUT_ABOVE_32(res);
+ m68k->not_z_flag |= res;
+
+ *r_dst = res;
+}
+
+
+M68KMAKE_OP(subx, 8, mm, ax7)
+{
+ UINT32 src = OPER_AY_PD_8(m68k);
+ UINT32 ea = EA_A7_PD_8(m68k);
+ UINT32 dst = m68ki_read_8(m68k, ea);
+ UINT32 res = dst - src - XFLAG_AS_1(m68k);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->x_flag = m68k->c_flag = CFLAG_8(res);
+ m68k->v_flag = VFLAG_SUB_8(src, dst, res);
+
+ res = MASK_OUT_ABOVE_8(res);
+ m68k->not_z_flag |= res;
+
+ m68ki_write_8(m68k, ea, res);
+}
+
+
+M68KMAKE_OP(subx, 8, mm, ay7)
+{
+ UINT32 src = OPER_A7_PD_8(m68k);
+ UINT32 ea = EA_AX_PD_8(m68k);
+ UINT32 dst = m68ki_read_8(m68k, ea);
+ UINT32 res = dst - src - XFLAG_AS_1(m68k);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->x_flag = m68k->c_flag = CFLAG_8(res);
+ m68k->v_flag = VFLAG_SUB_8(src, dst, res);
+
+ res = MASK_OUT_ABOVE_8(res);
+ m68k->not_z_flag |= res;
+
+ m68ki_write_8(m68k, ea, res);
+}
+
+
+M68KMAKE_OP(subx, 8, mm, axy7)
+{
+ UINT32 src = OPER_A7_PD_8(m68k);
+ UINT32 ea = EA_A7_PD_8(m68k);
+ UINT32 dst = m68ki_read_8(m68k, ea);
+ UINT32 res = dst - src - XFLAG_AS_1(m68k);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->x_flag = m68k->c_flag = CFLAG_8(res);
+ m68k->v_flag = VFLAG_SUB_8(src, dst, res);
+
+ res = MASK_OUT_ABOVE_8(res);
+ m68k->not_z_flag |= res;
+
+ m68ki_write_8(m68k, ea, res);
+}
+
+
+M68KMAKE_OP(subx, 8, mm, .)
+{
+ UINT32 src = OPER_AY_PD_8(m68k);
+ UINT32 ea = EA_AX_PD_8(m68k);
+ UINT32 dst = m68ki_read_8(m68k, ea);
+ UINT32 res = dst - src - XFLAG_AS_1(m68k);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->x_flag = m68k->c_flag = CFLAG_8(res);
+ m68k->v_flag = VFLAG_SUB_8(src, dst, res);
+
+ res = MASK_OUT_ABOVE_8(res);
+ m68k->not_z_flag |= res;
+
+ m68ki_write_8(m68k, ea, res);
+}
+
+
+M68KMAKE_OP(subx, 16, mm, .)
+{
+ UINT32 src = OPER_AY_PD_16(m68k);
+ UINT32 ea = EA_AX_PD_16(m68k);
+ UINT32 dst = m68ki_read_16(m68k, ea);
+ UINT32 res = dst - src - XFLAG_AS_1(m68k);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->x_flag = m68k->c_flag = CFLAG_16(res);
+ m68k->v_flag = VFLAG_SUB_16(src, dst, res);
+
+ res = MASK_OUT_ABOVE_16(res);
+ m68k->not_z_flag |= res;
+
+ m68ki_write_16(m68k, ea, res);
+}
+
+
+M68KMAKE_OP(subx, 32, mm, .)
+{
+ UINT32 src = OPER_AY_PD_32(m68k);
+ UINT32 ea = EA_AX_PD_32(m68k);
+ UINT32 dst = m68ki_read_32(m68k, ea);
+ UINT32 res = dst - src - XFLAG_AS_1(m68k);
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->x_flag = m68k->c_flag = CFLAG_SUB_32(src, dst, res);
+ m68k->v_flag = VFLAG_SUB_32(src, dst, res);
+
+ res = MASK_OUT_ABOVE_32(res);
+ m68k->not_z_flag |= res;
+
+ m68ki_write_32(m68k, ea, res);
+}
+
+
+M68KMAKE_OP(swap, 32, ., .)
+{
+ UINT32* r_dst = &DY;
+
+ m68k->not_z_flag = MASK_OUT_ABOVE_32(*r_dst<<16);
+ *r_dst = (*r_dst>>16) | m68k->not_z_flag;
+
+ m68k->not_z_flag = *r_dst;
+ m68k->n_flag = NFLAG_32(*r_dst);
+ m68k->c_flag = CFLAG_CLEAR;
+ m68k->v_flag = VFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(tas, 8, ., d)
+{
+ UINT32* r_dst = &DY;
+
+ m68k->not_z_flag = MASK_OUT_ABOVE_8(*r_dst);
+ m68k->n_flag = NFLAG_8(*r_dst);
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+ *r_dst |= 0x80;
+}
+
+
+M68KMAKE_OP(tas, 8, ., .)
+{
+ UINT32 ea = M68KMAKE_GET_EA_AY_8;
+ UINT32 dst = m68ki_read_8(m68k, ea);
+ UINT32 allow_writeback = TRUE;
+
+ m68k->not_z_flag = dst;
+ m68k->n_flag = NFLAG_8(dst);
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+
+ /* The Genesis/Megadrive games Gargoyles and Ex-Mutants need the TAS writeback
+ disabled in order to function properly. Some Amiga software may also rely
+ on this, but only when accessing specific addresses so additional functionality
+ will be needed. */
+ if (m68k->tas_instr_callback != NULL)
+ allow_writeback = (*m68k->tas_instr_callback)(m68k->device);
+
+ if (allow_writeback)
+ m68ki_write_8(m68k, ea, dst | 0x80);
+}
+
+
+M68KMAKE_OP(trap, 0, ., .)
+{
+ /* Trap#n stacks exception frame type 0 */
+ m68ki_exception_trapN(m68k, EXCEPTION_TRAP_BASE + (m68k->ir & 0xf)); /* HJB 990403 */
+}
+
+
+M68KMAKE_OP(trapt, 0, ., .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ m68ki_exception_trap(m68k, EXCEPTION_TRAPV); /* HJB 990403 */
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(trapt, 16, ., .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ m68ki_exception_trap(m68k, EXCEPTION_TRAPV); /* HJB 990403 */
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(trapt, 32, ., .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ m68ki_exception_trap(m68k, EXCEPTION_TRAPV); /* HJB 990403 */
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(trapf, 0, ., .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(trapf, 16, ., .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ REG_PC += 2;
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(trapf, 32, ., .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ REG_PC += 4;
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(trapcc, 0, ., .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ if(M68KMAKE_CC)
+ m68ki_exception_trap(m68k, EXCEPTION_TRAPV); /* HJB 990403 */
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(trapcc, 16, ., .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ if(M68KMAKE_CC)
+ {
+ m68ki_exception_trap(m68k, EXCEPTION_TRAPV); /* HJB 990403 */
+ return;
+ }
+ REG_PC += 2;
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(trapcc, 32, ., .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ if(M68KMAKE_CC)
+ {
+ m68ki_exception_trap(m68k, EXCEPTION_TRAPV); /* HJB 990403 */
+ return;
+ }
+ REG_PC += 4;
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(trapv, 0, ., .)
+{
+ if(COND_VC(m68k))
+ {
+ return;
+ }
+ m68ki_exception_trap(m68k, EXCEPTION_TRAPV); /* HJB 990403 */
+}
+
+
+M68KMAKE_OP(tst, 8, ., d)
+{
+ UINT32 res = MASK_OUT_ABOVE_8(DY);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(tst, 8, ., .)
+{
+ UINT32 res = M68KMAKE_GET_OPER_AY_8;
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(tst, 8, ., pcdi)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 res = OPER_PCDI_8(m68k);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(tst, 8, ., pcix)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 res = OPER_PCIX_8(m68k);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(tst, 8, ., i)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 res = OPER_I_8(m68k);
+
+ m68k->n_flag = NFLAG_8(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(tst, 16, ., d)
+{
+ UINT32 res = MASK_OUT_ABOVE_16(DY);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(tst, 16, ., a)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 res = MAKE_INT_16(AY);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(tst, 16, ., .)
+{
+ UINT32 res = M68KMAKE_GET_OPER_AY_16;
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(tst, 16, ., pcdi)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 res = OPER_PCDI_16(m68k);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(tst, 16, ., pcix)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 res = OPER_PCIX_16(m68k);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(tst, 16, ., i)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 res = OPER_I_16(m68k);
+
+ m68k->n_flag = NFLAG_16(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(tst, 32, ., d)
+{
+ UINT32 res = DY;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(tst, 32, ., a)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 res = AY;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(tst, 32, ., .)
+{
+ UINT32 res = M68KMAKE_GET_OPER_AY_32;
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+}
+
+
+M68KMAKE_OP(tst, 32, ., pcdi)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 res = OPER_PCDI_32(m68k);
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(tst, 32, ., pcix)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 res = OPER_PCIX_32(m68k);
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(tst, 32, ., i)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 res = OPER_I_32(m68k);
+
+ m68k->n_flag = NFLAG_32(res);
+ m68k->not_z_flag = res;
+ m68k->v_flag = VFLAG_CLEAR;
+ m68k->c_flag = CFLAG_CLEAR;
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(unlk, 32, ., a7)
+{
+ REG_A[7] = m68ki_read_32(m68k, REG_A[7]);
+}
+
+
+M68KMAKE_OP(unlk, 32, ., .)
+{
+ UINT32* r_dst = &AY;
+
+ REG_A[7] = *r_dst;
+ *r_dst = m68ki_pull_32(m68k);
+}
+
+
+M68KMAKE_OP(unpk, 16, rr, .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ /* Note: DX and DY are reversed in Motorola's docs */
+ UINT32 src = DY;
+ UINT32* r_dst = &DX;
+
+ *r_dst = MASK_OUT_BELOW_16(*r_dst) | (((((src << 4) & 0x0f00) | (src & 0x000f)) + OPER_I_16(m68k)) & 0xffff);
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(unpk, 16, mm, ax7)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ /* Note: AX and AY are reversed in Motorola's docs */
+ UINT32 src = OPER_AY_PD_8(m68k);
+ UINT32 ea_dst;
+
+ src = (((src << 4) & 0x0f00) | (src & 0x000f)) + OPER_I_16(m68k);
+ ea_dst = EA_A7_PD_8(m68k);
+ m68ki_write_8(m68k, ea_dst, (src >> 8) & 0xff);
+ ea_dst = EA_A7_PD_8(m68k);
+ m68ki_write_8(m68k, ea_dst, src & 0xff);
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(unpk, 16, mm, ay7)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ /* Note: AX and AY are reversed in Motorola's docs */
+ UINT32 src = OPER_A7_PD_8(m68k);
+ UINT32 ea_dst;
+
+ src = (((src << 4) & 0x0f00) | (src & 0x000f)) + OPER_I_16(m68k);
+ ea_dst = EA_AX_PD_8(m68k);
+ m68ki_write_8(m68k, ea_dst, (src >> 8) & 0xff);
+ ea_dst = EA_AX_PD_8(m68k);
+ m68ki_write_8(m68k, ea_dst, src & 0xff);
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(unpk, 16, mm, axy7)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ UINT32 src = OPER_A7_PD_8(m68k);
+ UINT32 ea_dst;
+
+ src = (((src << 4) & 0x0f00) | (src & 0x000f)) + OPER_I_16(m68k);
+ ea_dst = EA_A7_PD_8(m68k);
+ m68ki_write_8(m68k, ea_dst, (src >> 8) & 0xff);
+ ea_dst = EA_A7_PD_8(m68k);
+ m68ki_write_8(m68k, ea_dst, src & 0xff);
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+M68KMAKE_OP(unpk, 16, mm, .)
+{
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ /* Note: AX and AY are reversed in Motorola's docs */
+ UINT32 src = OPER_AY_PD_8(m68k);
+ UINT32 ea_dst;
+
+ src = (((src << 4) & 0x0f00) | (src & 0x000f)) + OPER_I_16(m68k);
+ ea_dst = EA_AX_PD_8(m68k);
+ m68ki_write_8(m68k, ea_dst, (src >> 8) & 0xff);
+ ea_dst = EA_AX_PD_8(m68k);
+ m68ki_write_8(m68k, ea_dst, src & 0xff);
+ return;
+ }
+ m68ki_exception_illegal(m68k);
+}
+
+
+
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+M68KMAKE_END
diff --git a/trunk/src/emu/cpu/m68000/m68kcpu.c b/trunk/src/emu/cpu/m68000/m68kcpu.c
new file mode 100644
index 00000000000..4d21789dda7
--- /dev/null
+++ b/trunk/src/emu/cpu/m68000/m68kcpu.c
@@ -0,0 +1,2248 @@
+/* ======================================================================== */
+/* ========================= LICENSING & COPYRIGHT ======================== */
+/* ======================================================================== */
+
+#if 0
+static const char copyright_notice[] =
+"MUSASHI\n"
+"Version 4.70 (2010-11-06)\n"
+"A portable Motorola M680x0 processor emulation engine.\n"
+"Copyright Karl Stenerud. All rights reserved.\n"
+"\n"
+"This code may be freely used for non-commercial purpooses as long as this\n"
+"copyright notice remains unaltered in the source code and any binary files\n"
+"containing this code in compiled form.\n"
+"\n"
+"All other licensing terms must be negotiated with the author\n"
+"(Karl Stenerud).\n"
+"\n"
+"The latest version of this code can be obtained at:\n"
+"http://kstenerud.cjb.net or http://mamedev.org\n"
+;
+#endif
+
+
+/* ======================================================================== */
+/* ================================= NOTES ================================ */
+/* ======================================================================== */
+
+
+
+/* ======================================================================== */
+/* ================================ INCLUDES ============================== */
+/* ======================================================================== */
+
+#include "emu.h"
+#include "debugger.h"
+#include <setjmp.h>
+#include "m68kcpu.h"
+#include "m68kops.h"
+#include "m68kfpu.c"
+
+#include "m68kmmu.h"
+
+extern void m68040_fpu_op0(m68ki_cpu_core *m68k);
+extern void m68040_fpu_op1(m68ki_cpu_core *m68k);
+extern void m68881_mmu_ops(m68ki_cpu_core *m68k);
+
+/* ======================================================================== */
+/* ================================= DATA ================================= */
+/* ======================================================================== */
+
+/* Used by shift & rotate instructions */
+const UINT8 m68ki_shift_8_table[65] =
+{
+ 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff
+};
+const UINT16 m68ki_shift_16_table[65] =
+{
+ 0x0000, 0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00,
+ 0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc, 0xfffe, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff
+};
+const UINT32 m68ki_shift_32_table[65] =
+{
+ 0x00000000, 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, 0xf8000000,
+ 0xfc000000, 0xfe000000, 0xff000000, 0xff800000, 0xffc00000, 0xffe00000,
+ 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000, 0xffff8000,
+ 0xffffc000, 0xffffe000, 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
+ 0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, 0xfffffff8,
+ 0xfffffffc, 0xfffffffe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
+};
+
+
+/* Number of clock cycles to use for exception processing.
+ * I used 4 for any vectors that are undocumented for processing times.
+ */
+const UINT8 m68ki_exception_cycle_table[5][256] =
+{
+ { /* 000 */
+ 40, /* 0: Reset - Initial Stack Pointer */
+ 4, /* 1: Reset - Initial Program Counter */
+ 50, /* 2: Bus Error (unemulated) */
+ 50, /* 3: Address Error (unemulated) */
+ 34, /* 4: Illegal Instruction */
+ 38, /* 5: Divide by Zero */
+ 40, /* 6: CHK */
+ 34, /* 7: TRAPV */
+ 34, /* 8: Privilege Violation */
+ 34, /* 9: Trace */
+ 4, /* 10: 1010 */
+ 4, /* 11: 1111 */
+ 4, /* 12: RESERVED */
+ 4, /* 13: Coprocessor Protocol Violation (unemulated) */
+ 4, /* 14: Format Error */
+ 44, /* 15: Uninitialized Interrupt */
+ 4, /* 16: RESERVED */
+ 4, /* 17: RESERVED */
+ 4, /* 18: RESERVED */
+ 4, /* 19: RESERVED */
+ 4, /* 20: RESERVED */
+ 4, /* 21: RESERVED */
+ 4, /* 22: RESERVED */
+ 4, /* 23: RESERVED */
+ 44, /* 24: Spurious Interrupt */
+ 44, /* 25: Level 1 Interrupt Autovector */
+ 44, /* 26: Level 2 Interrupt Autovector */
+ 44, /* 27: Level 3 Interrupt Autovector */
+ 44, /* 28: Level 4 Interrupt Autovector */
+ 44, /* 29: Level 5 Interrupt Autovector */
+ 44, /* 30: Level 6 Interrupt Autovector */
+ 44, /* 31: Level 7 Interrupt Autovector */
+ 34, /* 32: TRAP #0 */
+ 34, /* 33: TRAP #1 */
+ 34, /* 34: TRAP #2 */
+ 34, /* 35: TRAP #3 */
+ 34, /* 36: TRAP #4 */
+ 34, /* 37: TRAP #5 */
+ 34, /* 38: TRAP #6 */
+ 34, /* 39: TRAP #7 */
+ 34, /* 40: TRAP #8 */
+ 34, /* 41: TRAP #9 */
+ 34, /* 42: TRAP #10 */
+ 34, /* 43: TRAP #11 */
+ 34, /* 44: TRAP #12 */
+ 34, /* 45: TRAP #13 */
+ 34, /* 46: TRAP #14 */
+ 34, /* 47: TRAP #15 */
+ 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
+ 4, /* 49: FP Inexact Result (unemulated) */
+ 4, /* 50: FP Divide by Zero (unemulated) */
+ 4, /* 51: FP Underflow (unemulated) */
+ 4, /* 52: FP Operand Error (unemulated) */
+ 4, /* 53: FP Overflow (unemulated) */
+ 4, /* 54: FP Signaling NAN (unemulated) */
+ 4, /* 55: FP Unimplemented Data Type (unemulated) */
+ 4, /* 56: MMU Configuration Error (unemulated) */
+ 4, /* 57: MMU Illegal Operation Error (unemulated) */
+ 4, /* 58: MMU Access Level Violation Error (unemulated) */
+ 4, /* 59: RESERVED */
+ 4, /* 60: RESERVED */
+ 4, /* 61: RESERVED */
+ 4, /* 62: RESERVED */
+ 4, /* 63: RESERVED */
+ /* 64-255: User Defined */
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
+ },
+ { /* 010 */
+ 40, /* 0: Reset - Initial Stack Pointer */
+ 4, /* 1: Reset - Initial Program Counter */
+ 126, /* 2: Bus Error (unemulated) */
+ 126, /* 3: Address Error (unemulated) */
+ 38, /* 4: Illegal Instruction */
+ 44, /* 5: Divide by Zero */
+ 44, /* 6: CHK */
+ 34, /* 7: TRAPV */
+ 38, /* 8: Privilege Violation */
+ 38, /* 9: Trace */
+ 4, /* 10: 1010 */
+ 4, /* 11: 1111 */
+ 4, /* 12: RESERVED */
+ 4, /* 13: Coprocessor Protocol Violation (unemulated) */
+ 4, /* 14: Format Error */
+ 44, /* 15: Uninitialized Interrupt */
+ 4, /* 16: RESERVED */
+ 4, /* 17: RESERVED */
+ 4, /* 18: RESERVED */
+ 4, /* 19: RESERVED */
+ 4, /* 20: RESERVED */
+ 4, /* 21: RESERVED */
+ 4, /* 22: RESERVED */
+ 4, /* 23: RESERVED */
+ 46, /* 24: Spurious Interrupt */
+ 46, /* 25: Level 1 Interrupt Autovector */
+ 46, /* 26: Level 2 Interrupt Autovector */
+ 46, /* 27: Level 3 Interrupt Autovector */
+ 46, /* 28: Level 4 Interrupt Autovector */
+ 46, /* 29: Level 5 Interrupt Autovector */
+ 46, /* 30: Level 6 Interrupt Autovector */
+ 46, /* 31: Level 7 Interrupt Autovector */
+ 38, /* 32: TRAP #0 */
+ 38, /* 33: TRAP #1 */
+ 38, /* 34: TRAP #2 */
+ 38, /* 35: TRAP #3 */
+ 38, /* 36: TRAP #4 */
+ 38, /* 37: TRAP #5 */
+ 38, /* 38: TRAP #6 */
+ 38, /* 39: TRAP #7 */
+ 38, /* 40: TRAP #8 */
+ 38, /* 41: TRAP #9 */
+ 38, /* 42: TRAP #10 */
+ 38, /* 43: TRAP #11 */
+ 38, /* 44: TRAP #12 */
+ 38, /* 45: TRAP #13 */
+ 38, /* 46: TRAP #14 */
+ 38, /* 47: TRAP #15 */
+ 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
+ 4, /* 49: FP Inexact Result (unemulated) */
+ 4, /* 50: FP Divide by Zero (unemulated) */
+ 4, /* 51: FP Underflow (unemulated) */
+ 4, /* 52: FP Operand Error (unemulated) */
+ 4, /* 53: FP Overflow (unemulated) */
+ 4, /* 54: FP Signaling NAN (unemulated) */
+ 4, /* 55: FP Unimplemented Data Type (unemulated) */
+ 4, /* 56: MMU Configuration Error (unemulated) */
+ 4, /* 57: MMU Illegal Operation Error (unemulated) */
+ 4, /* 58: MMU Access Level Violation Error (unemulated) */
+ 4, /* 59: RESERVED */
+ 4, /* 60: RESERVED */
+ 4, /* 61: RESERVED */
+ 4, /* 62: RESERVED */
+ 4, /* 63: RESERVED */
+ /* 64-255: User Defined */
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
+ },
+ { /* 020 */
+ 4, /* 0: Reset - Initial Stack Pointer */
+ 4, /* 1: Reset - Initial Program Counter */
+ 50, /* 2: Bus Error (unemulated) */
+ 50, /* 3: Address Error (unemulated) */
+ 20, /* 4: Illegal Instruction */
+ 38, /* 5: Divide by Zero */
+ 40, /* 6: CHK */
+ 20, /* 7: TRAPV */
+ 34, /* 8: Privilege Violation */
+ 25, /* 9: Trace */
+ 20, /* 10: 1010 */
+ 20, /* 11: 1111 */
+ 4, /* 12: RESERVED */
+ 4, /* 13: Coprocessor Protocol Violation (unemulated) */
+ 4, /* 14: Format Error */
+ 30, /* 15: Uninitialized Interrupt */
+ 4, /* 16: RESERVED */
+ 4, /* 17: RESERVED */
+ 4, /* 18: RESERVED */
+ 4, /* 19: RESERVED */
+ 4, /* 20: RESERVED */
+ 4, /* 21: RESERVED */
+ 4, /* 22: RESERVED */
+ 4, /* 23: RESERVED */
+ 30, /* 24: Spurious Interrupt */
+ 30, /* 25: Level 1 Interrupt Autovector */
+ 30, /* 26: Level 2 Interrupt Autovector */
+ 30, /* 27: Level 3 Interrupt Autovector */
+ 30, /* 28: Level 4 Interrupt Autovector */
+ 30, /* 29: Level 5 Interrupt Autovector */
+ 30, /* 30: Level 6 Interrupt Autovector */
+ 30, /* 31: Level 7 Interrupt Autovector */
+ 20, /* 32: TRAP #0 */
+ 20, /* 33: TRAP #1 */
+ 20, /* 34: TRAP #2 */
+ 20, /* 35: TRAP #3 */
+ 20, /* 36: TRAP #4 */
+ 20, /* 37: TRAP #5 */
+ 20, /* 38: TRAP #6 */
+ 20, /* 39: TRAP #7 */
+ 20, /* 40: TRAP #8 */
+ 20, /* 41: TRAP #9 */
+ 20, /* 42: TRAP #10 */
+ 20, /* 43: TRAP #11 */
+ 20, /* 44: TRAP #12 */
+ 20, /* 45: TRAP #13 */
+ 20, /* 46: TRAP #14 */
+ 20, /* 47: TRAP #15 */
+ 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
+ 4, /* 49: FP Inexact Result (unemulated) */
+ 4, /* 50: FP Divide by Zero (unemulated) */
+ 4, /* 51: FP Underflow (unemulated) */
+ 4, /* 52: FP Operand Error (unemulated) */
+ 4, /* 53: FP Overflow (unemulated) */
+ 4, /* 54: FP Signaling NAN (unemulated) */
+ 4, /* 55: FP Unimplemented Data Type (unemulated) */
+ 4, /* 56: MMU Configuration Error (unemulated) */
+ 4, /* 57: MMU Illegal Operation Error (unemulated) */
+ 4, /* 58: MMU Access Level Violation Error (unemulated) */
+ 4, /* 59: RESERVED */
+ 4, /* 60: RESERVED */
+ 4, /* 61: RESERVED */
+ 4, /* 62: RESERVED */
+ 4, /* 63: RESERVED */
+ /* 64-255: User Defined */
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
+ },
+ { /* 030 - not correct */
+ 4, /* 0: Reset - Initial Stack Pointer */
+ 4, /* 1: Reset - Initial Program Counter */
+ 50, /* 2: Bus Error (unemulated) */
+ 50, /* 3: Address Error (unemulated) */
+ 20, /* 4: Illegal Instruction */
+ 38, /* 5: Divide by Zero */
+ 40, /* 6: CHK */
+ 20, /* 7: TRAPV */
+ 34, /* 8: Privilege Violation */
+ 25, /* 9: Trace */
+ 20, /* 10: 1010 */
+ 20, /* 11: 1111 */
+ 4, /* 12: RESERVED */
+ 4, /* 13: Coprocessor Protocol Violation (unemulated) */
+ 4, /* 14: Format Error */
+ 30, /* 15: Uninitialized Interrupt */
+ 4, /* 16: RESERVED */
+ 4, /* 17: RESERVED */
+ 4, /* 18: RESERVED */
+ 4, /* 19: RESERVED */
+ 4, /* 20: RESERVED */
+ 4, /* 21: RESERVED */
+ 4, /* 22: RESERVED */
+ 4, /* 23: RESERVED */
+ 30, /* 24: Spurious Interrupt */
+ 30, /* 25: Level 1 Interrupt Autovector */
+ 30, /* 26: Level 2 Interrupt Autovector */
+ 30, /* 27: Level 3 Interrupt Autovector */
+ 30, /* 28: Level 4 Interrupt Autovector */
+ 30, /* 29: Level 5 Interrupt Autovector */
+ 30, /* 30: Level 6 Interrupt Autovector */
+ 30, /* 31: Level 7 Interrupt Autovector */
+ 20, /* 32: TRAP #0 */
+ 20, /* 33: TRAP #1 */
+ 20, /* 34: TRAP #2 */
+ 20, /* 35: TRAP #3 */
+ 20, /* 36: TRAP #4 */
+ 20, /* 37: TRAP #5 */
+ 20, /* 38: TRAP #6 */
+ 20, /* 39: TRAP #7 */
+ 20, /* 40: TRAP #8 */
+ 20, /* 41: TRAP #9 */
+ 20, /* 42: TRAP #10 */
+ 20, /* 43: TRAP #11 */
+ 20, /* 44: TRAP #12 */
+ 20, /* 45: TRAP #13 */
+ 20, /* 46: TRAP #14 */
+ 20, /* 47: TRAP #15 */
+ 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
+ 4, /* 49: FP Inexact Result (unemulated) */
+ 4, /* 50: FP Divide by Zero (unemulated) */
+ 4, /* 51: FP Underflow (unemulated) */
+ 4, /* 52: FP Operand Error (unemulated) */
+ 4, /* 53: FP Overflow (unemulated) */
+ 4, /* 54: FP Signaling NAN (unemulated) */
+ 4, /* 55: FP Unimplemented Data Type (unemulated) */
+ 4, /* 56: MMU Configuration Error (unemulated) */
+ 4, /* 57: MMU Illegal Operation Error (unemulated) */
+ 4, /* 58: MMU Access Level Violation Error (unemulated) */
+ 4, /* 59: RESERVED */
+ 4, /* 60: RESERVED */
+ 4, /* 61: RESERVED */
+ 4, /* 62: RESERVED */
+ 4, /* 63: RESERVED */
+ /* 64-255: User Defined */
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
+ },
+ { /* 040 */ // TODO: these values are not correct
+ 4, /* 0: Reset - Initial Stack Pointer */
+ 4, /* 1: Reset - Initial Program Counter */
+ 50, /* 2: Bus Error (unemulated) */
+ 50, /* 3: Address Error (unemulated) */
+ 20, /* 4: Illegal Instruction */
+ 38, /* 5: Divide by Zero */
+ 40, /* 6: CHK */
+ 20, /* 7: TRAPV */
+ 34, /* 8: Privilege Violation */
+ 25, /* 9: Trace */
+ 20, /* 10: 1010 */
+ 20, /* 11: 1111 */
+ 4, /* 12: RESERVED */
+ 4, /* 13: Coprocessor Protocol Violation (unemulated) */
+ 4, /* 14: Format Error */
+ 30, /* 15: Uninitialized Interrupt */
+ 4, /* 16: RESERVED */
+ 4, /* 17: RESERVED */
+ 4, /* 18: RESERVED */
+ 4, /* 19: RESERVED */
+ 4, /* 20: RESERVED */
+ 4, /* 21: RESERVED */
+ 4, /* 22: RESERVED */
+ 4, /* 23: RESERVED */
+ 30, /* 24: Spurious Interrupt */
+ 30, /* 25: Level 1 Interrupt Autovector */
+ 30, /* 26: Level 2 Interrupt Autovector */
+ 30, /* 27: Level 3 Interrupt Autovector */
+ 30, /* 28: Level 4 Interrupt Autovector */
+ 30, /* 29: Level 5 Interrupt Autovector */
+ 30, /* 30: Level 6 Interrupt Autovector */
+ 30, /* 31: Level 7 Interrupt Autovector */
+ 20, /* 32: TRAP #0 */
+ 20, /* 33: TRAP #1 */
+ 20, /* 34: TRAP #2 */
+ 20, /* 35: TRAP #3 */
+ 20, /* 36: TRAP #4 */
+ 20, /* 37: TRAP #5 */
+ 20, /* 38: TRAP #6 */
+ 20, /* 39: TRAP #7 */
+ 20, /* 40: TRAP #8 */
+ 20, /* 41: TRAP #9 */
+ 20, /* 42: TRAP #10 */
+ 20, /* 43: TRAP #11 */
+ 20, /* 44: TRAP #12 */
+ 20, /* 45: TRAP #13 */
+ 20, /* 46: TRAP #14 */
+ 20, /* 47: TRAP #15 */
+ 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
+ 4, /* 49: FP Inexact Result (unemulated) */
+ 4, /* 50: FP Divide by Zero (unemulated) */
+ 4, /* 51: FP Underflow (unemulated) */
+ 4, /* 52: FP Operand Error (unemulated) */
+ 4, /* 53: FP Overflow (unemulated) */
+ 4, /* 54: FP Signaling NAN (unemulated) */
+ 4, /* 55: FP Unimplemented Data Type (unemulated) */
+ 4, /* 56: MMU Configuration Error (unemulated) */
+ 4, /* 57: MMU Illegal Operation Error (unemulated) */
+ 4, /* 58: MMU Access Level Violation Error (unemulated) */
+ 4, /* 59: RESERVED */
+ 4, /* 60: RESERVED */
+ 4, /* 61: RESERVED */
+ 4, /* 62: RESERVED */
+ 4, /* 63: RESERVED */
+ /* 64-255: User Defined */
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
+ }
+};
+
+const UINT8 m68ki_ea_idx_cycle_table[64] =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, /* ..01.000 no memory indirect, base NULL */
+ 5, /* ..01..01 memory indirect, base NULL, outer NULL */
+ 7, /* ..01..10 memory indirect, base NULL, outer 16 */
+ 7, /* ..01..11 memory indirect, base NULL, outer 32 */
+ 0, 5, 7, 7, 0, 5, 7, 7, 0, 5, 7, 7,
+ 2, /* ..10.000 no memory indirect, base 16 */
+ 7, /* ..10..01 memory indirect, base 16, outer NULL */
+ 9, /* ..10..10 memory indirect, base 16, outer 16 */
+ 9, /* ..10..11 memory indirect, base 16, outer 32 */
+ 0, 7, 9, 9, 0, 7, 9, 9, 0, 7, 9, 9,
+ 6, /* ..11.000 no memory indirect, base 32 */
+ 11, /* ..11..01 memory indirect, base 32, outer NULL */
+ 13, /* ..11..10 memory indirect, base 32, outer 16 */
+ 13, /* ..11..11 memory indirect, base 32, outer 32 */
+ 0, 11, 13, 13, 0, 11, 13, 13, 0, 11, 13, 13
+};
+
+
+
+/***************************************************************************
+ CPU STATE DESCRIPTION
+***************************************************************************/
+
+#define MASK_ALL (CPU_TYPE_000 | CPU_TYPE_008 | CPU_TYPE_010 | CPU_TYPE_EC020 | CPU_TYPE_020 | CPU_TYPE_EC030 | CPU_TYPE_030 | CPU_TYPE_EC040 | CPU_TYPE_040)
+#define MASK_24BIT_SPACE (CPU_TYPE_000 | CPU_TYPE_008 | CPU_TYPE_010 | CPU_TYPE_EC020)
+#define MASK_32BIT_SPACE (CPU_TYPE_020 | CPU_TYPE_EC030 | CPU_TYPE_030 | CPU_TYPE_EC040 | CPU_TYPE_040)
+#define MASK_010_OR_LATER (CPU_TYPE_010 | CPU_TYPE_EC020 | CPU_TYPE_020 | CPU_TYPE_030 | CPU_TYPE_EC030 | CPU_TYPE_040 | CPU_TYPE_EC040)
+#define MASK_020_OR_LATER (CPU_TYPE_EC020 | CPU_TYPE_020 | CPU_TYPE_EC030 | CPU_TYPE_030 | CPU_TYPE_EC040 | CPU_TYPE_040)
+#define MASK_030_OR_LATER (CPU_TYPE_030 | CPU_TYPE_EC030 | CPU_TYPE_040 | CPU_TYPE_EC040)
+#define MASK_040_OR_LATER (CPU_TYPE_040 | CPU_TYPE_EC040)
+
+
+INLINE m68ki_cpu_core *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == M68000 ||
+ device->type() == M68008 ||
+ device->type() == M68010 ||
+ device->type() == M68EC020 ||
+ device->type() == M68020 ||
+ device->type() == M68020HMMU ||
+ device->type() == M68020PMMU ||
+ device->type() == M68EC030 ||
+ device->type() == M68030 ||
+ device->type() == M68EC040 ||
+ device->type() == M68040 ||
+ device->type() == SCC68070);
+ return (m68ki_cpu_core *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+/* ======================================================================== */
+/* ================================= API ================================== */
+/* ======================================================================== */
+
+static void set_irq_line(m68ki_cpu_core *m68k, int irqline, int state)
+{
+ UINT32 old_level = m68k->int_level;
+ UINT32 vstate = m68k->virq_state;
+ UINT32 blevel;
+
+ if(state == ASSERT_LINE)
+ vstate |= 1 << irqline;
+ else
+ vstate &= ~(1 << irqline);
+ m68k->virq_state = vstate;
+
+ for(blevel = 7; blevel > 0; blevel--)
+ if(vstate & (1 << blevel))
+ break;
+
+ m68k->int_level = blevel << 8;
+
+ /* A transition from < 7 to 7 always interrupts (NMI) */
+ /* Note: Level 7 can also level trigger like a normal IRQ */
+ if(old_level != 0x0700 && m68k->int_level == 0x0700)
+ m68k->nmi_pending = TRUE;
+}
+
+static void m68k_presave(m68ki_cpu_core *m68k)
+{
+ m68k->save_sr = m68ki_get_sr(m68k);
+ m68k->save_stopped = (m68k->stopped & STOP_LEVEL_STOP) != 0;
+ m68k->save_halted = (m68k->stopped & STOP_LEVEL_HALT) != 0;
+}
+
+static void m68k_postload(m68ki_cpu_core *m68k)
+{
+ m68ki_set_sr_noint_nosp(m68k, m68k->save_sr);
+ m68k->stopped = m68k->save_stopped ? STOP_LEVEL_STOP : 0
+ | m68k->save_halted ? STOP_LEVEL_HALT : 0;
+ m68ki_jump(m68k, REG_PC);
+}
+
+static void m68k_cause_bus_error(m68ki_cpu_core *m68k)
+{
+ UINT32 sr;
+
+ sr = m68ki_init_exception(m68k);
+
+ m68k->run_mode = RUN_MODE_BERR_AERR_RESET;
+
+ if (!CPU_TYPE_IS_020_PLUS(m68k->cpu_type))
+ {
+ /* Note: This is implemented for 68000 only! */
+ m68ki_stack_frame_buserr(m68k, sr);
+ }
+ else if (m68k->mmu_tmp_buserror_address == REG_PPC)
+ {
+ m68ki_stack_frame_1010(m68k, sr, EXCEPTION_BUS_ERROR, REG_PPC, m68k->mmu_tmp_buserror_address);
+ }
+ else
+ {
+ m68ki_stack_frame_1011(m68k, sr, EXCEPTION_BUS_ERROR, REG_PPC, m68k->mmu_tmp_buserror_address);
+ }
+
+ m68ki_jump_vector(m68k, EXCEPTION_BUS_ERROR);
+}
+
+/* translate logical to physical addresses */
+static CPU_TRANSLATE( m68k )
+{
+ m68ki_cpu_core *m68k = get_safe_token(device);
+
+ /* only applies to the program address space and only does something if the MMU's enabled */
+ if (m68k)
+ {
+ if ((space == AS_PROGRAM) && (m68k->pmmu_enabled))
+ {
+ // FIXME: mmu_tmp_sr will be overwritten in pmmu_translate_addr_with_fc
+ UINT16 mmu_tmp_sr = m68k->mmu_tmp_sr;
+// UINT32 va=*address;
+
+ *address = pmmu_translate_addr_with_fc(m68k, *address, 4, 1);
+
+ if ((m68k->mmu_tmp_sr & M68K_MMU_SR_INVALID) != 0) {
+// logerror("cpu_translate_m68k failed with mmu_sr=%04x va=%08x pa=%08x\n",m68k->mmu_tmp_sr,va ,*address);
+ *address = 0;
+ }
+
+ m68k->mmu_tmp_sr= mmu_tmp_sr;
+ }
+ }
+ return TRUE;
+}
+
+/* translate logical to physical addresses for Apple HMMU */
+static CPU_TRANSLATE( m68khmmu )
+{
+ m68ki_cpu_core *m68k = get_safe_token(device);
+
+ /* only applies to the program address space and only does something if the MMU's enabled */
+ if (m68k)
+ {
+ if ((space == AS_PROGRAM) && (m68k->hmmu_enabled))
+ {
+ *address = hmmu_translate_addr(m68k, *address);
+ }
+ }
+ return TRUE;
+}
+
+/* Execute some instructions until we use up cycles clock cycles */
+static CPU_EXECUTE( m68k )
+{
+ m68ki_cpu_core *m68k = get_safe_token(device);
+
+ m68k->initial_cycles = m68k->remaining_cycles;
+
+ /* eat up any reset cycles */
+ if (m68k->reset_cycles) {
+ int rc = m68k->reset_cycles;
+ m68k->reset_cycles = 0;
+ m68k->remaining_cycles -= rc;
+
+ if (m68k->remaining_cycles <= 0) return;
+ }
+
+ /* See if interrupts came in */
+ m68ki_check_interrupts(m68k);
+
+ /* Make sure we're not stopped */
+ if(!m68k->stopped)
+ {
+ /* Return point if we had an address error */
+ m68ki_set_address_error_trap(m68k); /* auto-disable (see m68kcpu.h) */
+
+ /* Main loop. Keep going until we run out of clock cycles */
+ do
+ {
+ /* Set tracing accodring to T1. (T0 is done inside instruction) */
+ m68ki_trace_t1(); /* auto-disable (see m68kcpu.h) */
+
+ /* Call external hook to peek at CPU */
+ debugger_instruction_hook(device, REG_PC);
+
+ /* call external instruction hook (independent of debug mode) */
+ if (m68k->instruction_hook != NULL)
+ m68k->instruction_hook(device, REG_PC);
+
+ /* Record previous program counter */
+ REG_PPC = REG_PC;
+
+ if (!m68k->pmmu_enabled)
+ {
+ /* Read an instruction and call its handler */
+ m68k->ir = m68ki_read_imm_16(m68k);
+ m68k->jump_table[m68k->ir](m68k);
+ m68k->remaining_cycles -= m68k->cyc_instruction[m68k->ir];
+ }
+ else
+ {
+ // save CPU address registers values at start of instruction
+ int i;
+ UINT32 tmp_dar[16];
+
+ for (i = 15; i >= 0; i--)
+ {
+ tmp_dar[i] = REG_DA[i];
+ }
+
+ m68k->mmu_tmp_buserror_occurred = 0;
+
+ /* Read an instruction and call its handler */
+ m68k->ir = m68ki_read_imm_16(m68k);
+
+ if (!m68k->mmu_tmp_buserror_occurred)
+ {
+ m68k->jump_table[m68k->ir](m68k);
+ m68k->remaining_cycles -= m68k->cyc_instruction[m68k->ir];
+ }
+
+ if (m68k->mmu_tmp_buserror_occurred)
+ {
+ UINT32 sr;
+
+ m68k->mmu_tmp_buserror_occurred = 0;
+
+ // restore cpu address registers to value at start of instruction
+ for (i = 15; i >= 0; i--)
+ {
+ if (REG_DA[i] != tmp_dar[i])
+ {
+// logerror("PMMU: pc=%08x sp=%08x bus error: fixed %s[%d]: %08x -> %08x\n",
+// REG_PPC, REG_A[7], i < 8 ? "D" : "A", i & 7, REG_DA[i], tmp_dar[i]);
+ REG_DA[i] = tmp_dar[i];
+ }
+ }
+
+ sr = m68ki_init_exception(m68k);
+
+ m68k->run_mode = RUN_MODE_BERR_AERR_RESET;
+
+ if (!CPU_TYPE_IS_020_PLUS(m68k->cpu_type))
+ {
+ /* Note: This is implemented for 68000 only! */
+ m68ki_stack_frame_buserr(m68k, sr);
+ }
+ else if (m68k->mmu_tmp_buserror_address == REG_PPC)
+ {
+ m68ki_stack_frame_1010(m68k, sr, EXCEPTION_BUS_ERROR, REG_PPC, m68k->mmu_tmp_buserror_address);
+ }
+ else
+ {
+ m68ki_stack_frame_1011(m68k, sr, EXCEPTION_BUS_ERROR, REG_PPC, m68k->mmu_tmp_buserror_address);
+ }
+
+ m68ki_jump_vector(m68k, EXCEPTION_BUS_ERROR);
+
+ // TODO:
+ /* Use up some clock cycles and undo the instruction's cycles */
+ // m68k->remaining_cycles -= m68k->cyc_exception[EXCEPTION_BUS_ERROR] - m68k->cyc_instruction[m68k->ir];
+ }
+ }
+
+ /* Trace m68k_exception, if necessary */
+ m68ki_exception_if_trace(); /* auto-disable (see m68kcpu.h) */
+ } while (m68k->remaining_cycles > 0);
+
+ /* set previous PC to current PC for the next entry into the loop */
+ REG_PPC = REG_PC;
+ }
+ else if (m68k->remaining_cycles > 0)
+ m68k->remaining_cycles = 0;
+}
+
+static CPU_INIT( m68k )
+{
+ static UINT32 emulation_initialized = 0;
+ m68ki_cpu_core *m68k = get_safe_token(device);
+
+ m68k->device = device;
+ m68k->program = device->space(AS_PROGRAM);
+ m68k->int_ack_callback = irqcallback;
+
+ /* disable all MMUs */
+ m68k->has_pmmu = 0;
+ m68k->has_hmmu = 0;
+ m68k->pmmu_enabled = 0;
+ m68k->hmmu_enabled = 0;
+
+ /* The first call to this function initializes the opcode handler jump table */
+ if(!emulation_initialized)
+ {
+ m68ki_build_opcode_table();
+ emulation_initialized = 1;
+ }
+
+ /* Note, D covers A because the dar array is common, REG_A=REG_D+8 */
+ device->save_item(NAME(REG_D));
+ device->save_item(NAME(REG_PPC));
+ device->save_item(NAME(REG_PC));
+ device->save_item(NAME(REG_USP));
+ device->save_item(NAME(REG_ISP));
+ device->save_item(NAME(REG_MSP));
+ device->save_item(NAME(m68k->vbr));
+ device->save_item(NAME(m68k->sfc));
+ device->save_item(NAME(m68k->dfc));
+ device->save_item(NAME(m68k->cacr));
+ device->save_item(NAME(m68k->caar));
+ device->save_item(NAME(m68k->save_sr));
+ device->save_item(NAME(m68k->int_level));
+ device->save_item(NAME(m68k->save_stopped));
+ device->save_item(NAME(m68k->save_halted));
+ device->save_item(NAME(m68k->pref_addr));
+ device->save_item(NAME(m68k->pref_data));
+ device->machine().save().register_presave(save_prepost_delegate(FUNC(m68k_presave), m68k));
+ device->machine().save().register_postload(save_prepost_delegate(FUNC(m68k_postload), m68k));
+}
+
+/* Pulse the RESET line on the CPU */
+static CPU_RESET( m68k )
+{
+ m68ki_cpu_core *m68k = get_safe_token(device);
+
+ /* Disable the PMMU/HMMU on reset, if any */
+ m68k->pmmu_enabled = 0;
+ m68k->hmmu_enabled = 0;
+
+ m68k->mmu_tc = 0;
+ m68k->mmu_tt0 = 0;
+ m68k->mmu_tt1 = 0;
+
+ /* Clear all stop levels and eat up all remaining cycles */
+ m68k->stopped = 0;
+ if (m68k->remaining_cycles > 0)
+ m68k->remaining_cycles = 0;
+
+ m68k->run_mode = RUN_MODE_BERR_AERR_RESET;
+
+ /* Turn off tracing */
+ m68k->t1_flag = m68k->t0_flag = 0;
+ m68ki_clear_trace();
+ /* Interrupt mask to level 7 */
+ m68k->int_mask = 0x0700;
+ m68k->int_level = 0;
+ m68k->virq_state = 0;
+ /* Reset VBR */
+ m68k->vbr = 0;
+ /* Go to supervisor mode */
+ m68ki_set_sm_flag(m68k, SFLAG_SET | MFLAG_CLEAR);
+
+ /* Invalidate the prefetch queue */
+ /* Set to arbitrary number since our first fetch is from 0 */
+ m68k->pref_addr = 0x1000;
+
+ /* Read the initial stack pointer and program counter */
+ m68ki_jump(m68k, 0);
+ REG_SP = m68ki_read_imm_32(m68k);
+ REG_PC = m68ki_read_imm_32(m68k);
+ m68ki_jump(m68k, REG_PC);
+
+ m68k->run_mode = RUN_MODE_NORMAL;
+
+ m68k->reset_cycles = m68k->cyc_exception[EXCEPTION_RESET];
+
+ /* flush the MMU's cache */
+ pmmu_atc_flush(m68k);
+
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ // clear instruction cache
+ m68ki_ic_clear(m68k);
+ }
+
+ // disable instruction hook
+ m68k->instruction_hook = NULL;
+}
+
+static CPU_DISASSEMBLE( m68k )
+{
+ m68ki_cpu_core *m68k = get_safe_token(device);
+ return m68k_disassemble_raw(buffer, pc, oprom, opram, m68k->dasm_type);
+}
+
+
+
+/**************************************************************************
+ * STATE IMPORT/EXPORT
+ **************************************************************************/
+
+static CPU_IMPORT_STATE( m68k )
+{
+ m68ki_cpu_core *m68k = get_safe_token(device);
+
+ switch (entry.index())
+ {
+ case M68K_SR:
+ case STATE_GENFLAGS:
+ m68ki_set_sr(m68k, m68k->iotemp);
+ break;
+
+ case M68K_ISP:
+ if (m68k->s_flag && !m68k->m_flag)
+ REG_SP = m68k->iotemp;
+ else
+ REG_ISP = m68k->iotemp;
+ break;
+
+ case M68K_USP:
+ if (!m68k->s_flag)
+ REG_SP = m68k->iotemp;
+ else
+ REG_USP = m68k->iotemp;
+ break;
+
+ case M68K_MSP:
+ if (m68k->s_flag && m68k->m_flag)
+ REG_SP = m68k->iotemp;
+ else
+ REG_MSP = m68k->iotemp;
+ break;
+
+ default:
+ fatalerror("CPU_IMPORT_STATE(m68k) called for unexpected value\n");
+ break;
+ }
+}
+
+
+static CPU_EXPORT_STATE( m68k )
+{
+ m68ki_cpu_core *m68k = get_safe_token(device);
+
+ switch (entry.index())
+ {
+ case M68K_SR:
+ case STATE_GENFLAGS:
+ m68k->iotemp = m68ki_get_sr(m68k);
+ break;
+
+ case M68K_ISP:
+ m68k->iotemp = (m68k->s_flag && !m68k->m_flag) ? REG_SP : REG_ISP;
+ break;
+
+ case M68K_USP:
+ m68k->iotemp = (!m68k->s_flag) ? REG_SP : REG_USP;
+ break;
+
+ case M68K_MSP:
+ m68k->iotemp = (m68k->s_flag && m68k->m_flag) ? REG_SP : REG_MSP;
+ break;
+
+ case M68K_FP0:
+ case M68K_FP1:
+ case M68K_FP2:
+ case M68K_FP3:
+ case M68K_FP4:
+ case M68K_FP5:
+ case M68K_FP6:
+ case M68K_FP7:
+ break;
+
+ default:
+ fatalerror("CPU_EXPORT_STATE(m68k) called for unexpected value\n");
+ break;
+ }
+}
+
+static CPU_SET_INFO( m68k )
+{
+ m68ki_cpu_core *m68k = get_safe_token(device);
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + 0:
+ case CPUINFO_INT_INPUT_STATE + 1:
+ case CPUINFO_INT_INPUT_STATE + 2:
+ case CPUINFO_INT_INPUT_STATE + 3:
+ case CPUINFO_INT_INPUT_STATE + 4:
+ case CPUINFO_INT_INPUT_STATE + 5:
+ case CPUINFO_INT_INPUT_STATE + 6:
+ case CPUINFO_INT_INPUT_STATE + 7:
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI:
+ set_irq_line(m68k, state - CPUINFO_INT_INPUT_STATE, info->i);
+ break;
+
+ case CPUINFO_INT_INPUT_STATE + M68K_LINE_BUSERROR:
+ if (info->i == ASSERT_LINE)
+ {
+ m68k_cause_bus_error(m68k);
+ }
+ break;
+ }
+}
+
+static CPU_EXPORT_STRING( m68k )
+{
+ m68ki_cpu_core *m68k = get_safe_token(device);
+ UINT16 sr;
+
+ switch (entry.index())
+ {
+ case M68K_FP0:
+ string.printf("%f", fx80_to_double(REG_FP[0]));
+ break;
+
+ case M68K_FP1:
+ string.printf("%f", fx80_to_double(REG_FP[1]));
+ break;
+
+ case M68K_FP2:
+ string.printf("%f", fx80_to_double(REG_FP[2]));
+ break;
+
+ case M68K_FP3:
+ string.printf("%f", fx80_to_double(REG_FP[3]));
+ break;
+
+ case M68K_FP4:
+ string.printf("%f", fx80_to_double(REG_FP[4]));
+ break;
+
+ case M68K_FP5:
+ string.printf("%f", fx80_to_double(REG_FP[5]));
+ break;
+
+ case M68K_FP6:
+ string.printf("%f", fx80_to_double(REG_FP[6]));
+ break;
+
+ case M68K_FP7:
+ string.printf("%f", fx80_to_double(REG_FP[7]));
+ break;
+
+ case STATE_GENFLAGS:
+ sr = m68ki_get_sr(m68k);
+ string.printf("%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c",
+ sr & 0x8000 ? 'T':'.',
+ sr & 0x4000 ? 't':'.',
+ sr & 0x2000 ? 'S':'.',
+ sr & 0x1000 ? 'M':'.',
+ sr & 0x0800 ? '?':'.',
+ sr & 0x0400 ? 'I':'.',
+ sr & 0x0200 ? 'I':'.',
+ sr & 0x0100 ? 'I':'.',
+ sr & 0x0080 ? '?':'.',
+ sr & 0x0040 ? '?':'.',
+ sr & 0x0020 ? '?':'.',
+ sr & 0x0010 ? 'X':'.',
+ sr & 0x0008 ? 'N':'.',
+ sr & 0x0004 ? 'Z':'.',
+ sr & 0x0002 ? 'V':'.',
+ sr & 0x0001 ? 'C':'.');
+ break;
+ }
+}
+
+static CPU_GET_INFO( m68k )
+{
+ m68ki_cpu_core *m68k = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(m68ki_cpu_core); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 8; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = -1; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 2; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 10; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 4; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 158; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 24; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+
+ case CPUINFO_INT_INPUT_STATE + 0: info->i = 0; /* there is no level 0 */ break;
+ case CPUINFO_INT_INPUT_STATE + 1: info->i = (m68k->virq_state >> 1) & 1; break;
+ case CPUINFO_INT_INPUT_STATE + 2: info->i = (m68k->virq_state >> 2) & 1; break;
+ case CPUINFO_INT_INPUT_STATE + 3: info->i = (m68k->virq_state >> 3) & 1; break;
+ case CPUINFO_INT_INPUT_STATE + 4: info->i = (m68k->virq_state >> 4) & 1; break;
+ case CPUINFO_INT_INPUT_STATE + 5: info->i = (m68k->virq_state >> 5) & 1; break;
+ case CPUINFO_INT_INPUT_STATE + 6: info->i = (m68k->virq_state >> 6) & 1; break;
+ case CPUINFO_INT_INPUT_STATE + 7: info->i = (m68k->virq_state >> 7) & 1; break;
+
+ /* --- the following bits of info are returned as pointers to functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(m68k); break;
+ case CPUINFO_FCT_INIT: /* set per-core */ break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(m68k); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(m68k); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(m68k); break;
+ case CPUINFO_FCT_IMPORT_STATE: info->import_state = CPU_IMPORT_STATE_NAME(m68k); break;
+ case CPUINFO_FCT_EXPORT_STATE: info->export_state = CPU_EXPORT_STATE_NAME(m68k); break;
+ case CPUINFO_FCT_EXPORT_STRING: info->export_string = CPU_EXPORT_STRING_NAME(m68k); break;
+ case CPUINFO_FCT_TRANSLATE: info->translate = CPU_TRANSLATE_NAME(m68k); break;
+
+ /* --- the following bits of info are returned as pointers --- */
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &m68k->remaining_cycles; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: /* set per-core */ break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Motorola 68K"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "4.60"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Karl Stenerud. All rights reserved. (2.1 fixes HJB, FPU+MMU by RB+HO)"); break;
+ }
+}
+
+
+/* global access */
+
+void m68k_set_encrypted_opcode_range(device_t *device, offs_t start, offs_t end)
+{
+ m68ki_cpu_core *m68k = get_safe_token(device);
+ m68k->encrypted_start = start;
+ m68k->encrypted_end = end;
+}
+
+void m68k_set_hmmu_enable(device_t *device, int enable)
+{
+ m68ki_cpu_core *m68k = get_safe_token(device);
+
+ m68k->hmmu_enabled = enable;
+}
+
+/****************************************************************************
+ * 8-bit data memory interface
+ ****************************************************************************/
+
+UINT16 m68k_memory_interface::m68008_read_immediate_16(offs_t address)
+{
+ return (m_direct->read_decrypted_byte(address) << 8) | (m_direct->read_decrypted_byte(address + 1));
+}
+
+void m68k_memory_interface::init8(address_space &space)
+{
+ m_space = &space;
+ m_direct = &space.direct();
+ m_cpustate = get_safe_token(&space.device());
+ opcode_xor = 0;
+
+ readimm16 = m68k_readimm16_delegate(FUNC(m68k_memory_interface::m68008_read_immediate_16), this);
+ read8 = m68k_read8_delegate(FUNC(address_space::read_byte), &space);
+ read16 = m68k_read16_delegate(FUNC(address_space::read_word), &space);
+ read32 = m68k_read32_delegate(FUNC(address_space::read_dword), &space);
+ write8 = m68k_write8_delegate(FUNC(address_space::write_byte), &space);
+ write16 = m68k_write16_delegate(FUNC(address_space::write_word), &space);
+ write32 = m68k_write32_delegate(FUNC(address_space::write_dword), &space);
+}
+
+/****************************************************************************
+ * 16-bit data memory interface
+ ****************************************************************************/
+
+UINT16 m68k_memory_interface::read_immediate_16(offs_t address)
+{
+ return m_direct->read_decrypted_word((address), opcode_xor);
+}
+
+UINT16 m68k_memory_interface::simple_read_immediate_16(offs_t address)
+{
+ return m_direct->read_decrypted_word(address);
+}
+
+void m68k_memory_interface::init16(address_space &space)
+{
+ m_space = &space;
+ m_direct = &space.direct();
+ m_cpustate = get_safe_token(&space.device());
+ opcode_xor = 0;
+
+ readimm16 = m68k_readimm16_delegate(FUNC(m68k_memory_interface::simple_read_immediate_16), this);
+ read8 = m68k_read8_delegate(FUNC(address_space::read_byte), &space);
+ read16 = m68k_read16_delegate(FUNC(address_space::read_word), &space);
+ read32 = m68k_read32_delegate(FUNC(address_space::read_dword), &space);
+ write8 = m68k_write8_delegate(FUNC(address_space::write_byte), &space);
+ write16 = m68k_write16_delegate(FUNC(address_space::write_word), &space);
+ write32 = m68k_write32_delegate(FUNC(address_space::write_dword), &space);
+}
+
+/****************************************************************************
+ * 32-bit data memory interface
+ ****************************************************************************/
+
+/* interface for 32-bit data bus (68EC020, 68020) */
+void m68k_memory_interface::init32(address_space &space)
+{
+ m_space = &space;
+ m_direct = &space.direct();
+ m_cpustate = get_safe_token(&space.device());
+ opcode_xor = WORD_XOR_BE(0);
+
+ readimm16 = m68k_readimm16_delegate(FUNC(m68k_memory_interface::read_immediate_16), this);
+ read8 = m68k_read8_delegate(FUNC(address_space::read_byte), &space);
+ read16 = m68k_read16_delegate(FUNC(address_space::read_word_unaligned), &space);
+ read32 = m68k_read32_delegate(FUNC(address_space::read_dword_unaligned), &space);
+ write8 = m68k_write8_delegate(FUNC(address_space::write_byte), &space);
+ write16 = m68k_write16_delegate(FUNC(address_space::write_word_unaligned), &space);
+ write32 = m68k_write32_delegate(FUNC(address_space::write_dword_unaligned), &space);
+}
+
+/* interface for 32-bit data bus with PMMU (68EC020, 68020) */
+UINT8 m68k_memory_interface::read_byte_32_mmu(offs_t address)
+{
+ if (m_cpustate->pmmu_enabled)
+ {
+ address = pmmu_translate_addr(m_cpustate, address);
+ if (m_cpustate->mmu_tmp_buserror_occurred) {
+ return ~0;
+ }
+ }
+
+ return m_space->read_byte(address);
+}
+
+void m68k_memory_interface::write_byte_32_mmu(offs_t address, UINT8 data)
+{
+ if (m_cpustate->pmmu_enabled)
+ {
+ address = pmmu_translate_addr(m_cpustate, address);
+ if (m_cpustate->mmu_tmp_buserror_occurred) {
+ return;
+ }
+ }
+
+ m_space->write_byte(address, data);
+}
+
+UINT16 m68k_memory_interface::read_immediate_16_mmu(offs_t address)
+{
+ if (m_cpustate->pmmu_enabled)
+ {
+ address = pmmu_translate_addr(m_cpustate, address);
+ if (m_cpustate->mmu_tmp_buserror_occurred) {
+ return ~0;
+ }
+ }
+
+ return m_direct->read_decrypted_word((address), m_cpustate->memory.opcode_xor);
+}
+
+/* potentially misaligned 16-bit reads with a 32-bit data bus (and 24-bit address bus) */
+UINT16 m68k_memory_interface::readword_d32_mmu(offs_t address)
+{
+ UINT16 result;
+
+ if (m_cpustate->pmmu_enabled)
+ {
+ UINT32 address0 = pmmu_translate_addr(m_cpustate, address);
+ if (m_cpustate->mmu_tmp_buserror_occurred) {
+ return ~0;
+ } else if (!(address & 1)) {
+ return m_space->read_word(address0);
+ } else {
+ UINT32 address1 = pmmu_translate_addr(m_cpustate, address + 1);
+ if (m_cpustate->mmu_tmp_buserror_occurred) {
+ return ~0;
+ } else {
+ result = m_space->read_byte(address0) << 8;
+ return result | m_space->read_byte(address1);
+ }
+ }
+ }
+
+ if (!(address & 1))
+ return m_space->read_word(address);
+ result = m_space->read_byte(address) << 8;
+ return result | m_space->read_byte(address + 1);
+}
+
+/* potentially misaligned 16-bit writes with a 32-bit data bus (and 24-bit address bus) */
+void m68k_memory_interface::writeword_d32_mmu(offs_t address, UINT16 data)
+{
+ if (m_cpustate->pmmu_enabled)
+ {
+ UINT32 address0 = pmmu_translate_addr(m_cpustate, address);
+ if (m_cpustate->mmu_tmp_buserror_occurred) {
+ return;
+ } else if (!(address & 1)) {
+ m_space->write_word(address0, data);
+ return;
+ } else {
+ UINT32 address1 = pmmu_translate_addr(m_cpustate, address + 1);
+ if (m_cpustate->mmu_tmp_buserror_occurred) {
+ return;
+ } else {
+ m_space->write_byte(address0, data >> 8);
+ m_space->write_byte(address1, data);
+ return;
+ }
+ }
+ }
+
+ if (!(address & 1))
+ {
+ m_space->write_word(address, data);
+ return;
+ }
+ m_space->write_byte(address, data >> 8);
+ m_space->write_byte(address + 1, data);
+}
+
+/* potentially misaligned 32-bit reads with a 32-bit data bus (and 24-bit address bus) */
+UINT32 m68k_memory_interface::readlong_d32_mmu(offs_t address)
+{
+ UINT32 result;
+
+ if (m_cpustate->pmmu_enabled)
+ {
+ UINT32 address0 = pmmu_translate_addr(m_cpustate, address);
+ if (m_cpustate->mmu_tmp_buserror_occurred) {
+ return ~0;
+ } else if ((address +3) & 0xfc) {
+ // not at page boundary; use default code
+ address = address0;
+ } else if (!(address & 3)) { // 0
+ return m_space->read_dword(address0);
+ } else {
+ UINT32 address2 = pmmu_translate_addr(m_cpustate, address+2);
+ if (m_cpustate->mmu_tmp_buserror_occurred) {
+ return ~0;
+ } else if (!(address & 1)) { // 2
+ result = m_space->read_word(address0) << 16;
+ return result | m_space->read_word(address2);
+ } else {
+ UINT32 address1 = pmmu_translate_addr(m_cpustate, address+1);
+ UINT32 address3 = pmmu_translate_addr(m_cpustate, address+3);
+ if (m_cpustate->mmu_tmp_buserror_occurred) {
+ return ~0;
+ } else {
+ result = m_space->read_byte(address0) << 24;
+ result |= m_space->read_word(address1) << 8;
+ return result | m_space->read_byte(address3);
+ }
+ }
+ }
+ }
+
+ if (!(address & 3))
+ return m_space->read_dword(address);
+ else if (!(address & 1))
+ {
+ result = m_space->read_word(address) << 16;
+ return result | m_space->read_word(address + 2);
+ }
+ result = m_space->read_byte(address) << 24;
+ result |= m_space->read_word(address + 1) << 8;
+ return result | m_space->read_byte(address + 3);
+}
+
+/* potentially misaligned 32-bit writes with a 32-bit data bus (and 24-bit address bus) */
+void m68k_memory_interface::writelong_d32_mmu(offs_t address, UINT32 data)
+{
+ if (m_cpustate->pmmu_enabled)
+ {
+ UINT32 address0 = pmmu_translate_addr(m_cpustate, address);
+ if (m_cpustate->mmu_tmp_buserror_occurred) {
+ return;
+ } else if ((address +3) & 0xfc) {
+ // not at page boundary; use default code
+ address = address0;
+ } else if (!(address & 3)) { // 0
+ m_space->write_dword(address0, data);
+ return;
+ } else {
+ UINT32 address2 = pmmu_translate_addr(m_cpustate, address+2);
+ if (m_cpustate->mmu_tmp_buserror_occurred) {
+ return;
+ } else if (!(address & 1)) { // 2
+ m_space->write_word(address0, data >> 16);
+ m_space->write_word(address2, data);
+ return;
+ } else {
+ UINT32 address1 = pmmu_translate_addr(m_cpustate, address+1);
+ UINT32 address3 = pmmu_translate_addr(m_cpustate, address+3);
+ if (m_cpustate->mmu_tmp_buserror_occurred) {
+ return;
+ } else {
+ m_space->write_byte(address0, data >> 24);
+ m_space->write_word(address1, data >> 8);
+ m_space->write_byte(address3, data);
+ return;
+ }
+ }
+ }
+ }
+
+ if (!(address & 3))
+ {
+ m_space->write_dword(address, data);
+ return;
+ }
+ else if (!(address & 1))
+ {
+ m_space->write_word(address, data >> 16);
+ m_space->write_word(address + 2, data);
+ return;
+ }
+ m_space->write_byte(address, data >> 24);
+ m_space->write_word(address + 1, data >> 8);
+ m_space->write_byte(address + 3, data);
+}
+
+void m68k_memory_interface::init32mmu(address_space &space)
+{
+ m_space = &space;
+ m_direct = &space.direct();
+ m_cpustate = get_safe_token(&space.device());
+ opcode_xor = WORD_XOR_BE(0);
+
+ readimm16 = m68k_readimm16_delegate(FUNC(m68k_memory_interface::read_immediate_16_mmu), this);
+ read8 = m68k_read8_delegate(FUNC(m68k_memory_interface::read_byte_32_mmu), this);
+ read16 = m68k_read16_delegate(FUNC(m68k_memory_interface::readword_d32_mmu), this);
+ read32 = m68k_read32_delegate(FUNC(m68k_memory_interface::readlong_d32_mmu), this);
+ write8 = m68k_write8_delegate(FUNC(m68k_memory_interface::write_byte_32_mmu), this);
+ write16 = m68k_write16_delegate(FUNC(m68k_memory_interface::writeword_d32_mmu), this);
+ write32 = m68k_write32_delegate(FUNC(m68k_memory_interface::writelong_d32_mmu), this);
+}
+
+
+/* interface for 32-bit data bus with PMMU (68EC020, 68020) */
+UINT8 m68k_memory_interface::read_byte_32_hmmu(offs_t address)
+{
+ if (m_cpustate->hmmu_enabled)
+ {
+ address = hmmu_translate_addr(m_cpustate, address);
+ }
+
+ return m_space->read_byte(address);
+}
+
+void m68k_memory_interface::write_byte_32_hmmu(offs_t address, UINT8 data)
+{
+ if (m_cpustate->hmmu_enabled)
+ {
+ address = hmmu_translate_addr(m_cpustate, address);
+ }
+
+ m_space->write_byte(address, data);
+}
+
+UINT16 m68k_memory_interface::read_immediate_16_hmmu(offs_t address)
+{
+ if (m_cpustate->hmmu_enabled)
+ {
+ address = hmmu_translate_addr(m_cpustate, address);
+ }
+
+ return m_direct->read_decrypted_word((address), m_cpustate->memory.opcode_xor);
+}
+
+/* potentially misaligned 16-bit reads with a 32-bit data bus (and 24-bit address bus) */
+UINT16 m68k_memory_interface::readword_d32_hmmu(offs_t address)
+{
+ UINT16 result;
+
+ if (m_cpustate->hmmu_enabled)
+ {
+ address = hmmu_translate_addr(m_cpustate, address);
+ }
+
+ if (!(address & 1))
+ return m_space->read_word(address);
+ result = m_space->read_byte(address) << 8;
+ return result | m_space->read_byte(address + 1);
+}
+
+/* potentially misaligned 16-bit writes with a 32-bit data bus (and 24-bit address bus) */
+void m68k_memory_interface::writeword_d32_hmmu(offs_t address, UINT16 data)
+{
+ if (m_cpustate->hmmu_enabled)
+ {
+ address = hmmu_translate_addr(m_cpustate, address);
+ }
+
+ if (!(address & 1))
+ {
+ m_space->write_word(address, data);
+ return;
+ }
+ m_space->write_byte(address, data >> 8);
+ m_space->write_byte(address + 1, data);
+}
+
+/* potentially misaligned 32-bit reads with a 32-bit data bus (and 24-bit address bus) */
+UINT32 m68k_memory_interface::readlong_d32_hmmu(offs_t address)
+{
+ UINT32 result;
+
+ if (m_cpustate->hmmu_enabled)
+ {
+ address = hmmu_translate_addr(m_cpustate, address);
+ }
+
+ if (!(address & 3))
+ return m_space->read_dword(address);
+ else if (!(address & 1))
+ {
+ result = m_space->read_word(address) << 16;
+ return result | m_space->read_word(address + 2);
+ }
+ result = m_space->read_byte(address) << 24;
+ result |= m_space->read_word(address + 1) << 8;
+ return result | m_space->read_byte(address + 3);
+}
+
+/* potentially misaligned 32-bit writes with a 32-bit data bus (and 24-bit address bus) */
+void m68k_memory_interface::writelong_d32_hmmu(offs_t address, UINT32 data)
+{
+ if (m_cpustate->hmmu_enabled)
+ {
+ address = hmmu_translate_addr(m_cpustate, address);
+ }
+
+ if (!(address & 3))
+ {
+ m_space->write_dword(address, data);
+ return;
+ }
+ else if (!(address & 1))
+ {
+ m_space->write_word(address, data >> 16);
+ m_space->write_word(address + 2, data);
+ return;
+ }
+ m_space->write_byte(address, data >> 24);
+ m_space->write_word(address + 1, data >> 8);
+ m_space->write_byte(address + 3, data);
+}
+
+void m68k_memory_interface::init32hmmu(address_space &space)
+{
+ m_space = &space;
+ m_direct = &space.direct();
+ m_cpustate = get_safe_token(&space.device());
+ opcode_xor = WORD_XOR_BE(0);
+
+ readimm16 = m68k_readimm16_delegate(FUNC(m68k_memory_interface::read_immediate_16_hmmu), this);
+ read8 = m68k_read8_delegate(FUNC(m68k_memory_interface::read_byte_32_hmmu), this);
+ read16 = m68k_read16_delegate(FUNC(m68k_memory_interface::readword_d32_hmmu), this);
+ read32 = m68k_read32_delegate(FUNC(m68k_memory_interface::readlong_d32_hmmu), this);
+ write8 = m68k_write8_delegate(FUNC(m68k_memory_interface::write_byte_32_hmmu), this);
+ write16 = m68k_write16_delegate(FUNC(m68k_memory_interface::writeword_d32_hmmu), this);
+ write32 = m68k_write32_delegate(FUNC(m68k_memory_interface::writelong_d32_hmmu), this);
+}
+
+void m68k_set_reset_callback(device_t *device, m68k_reset_func callback)
+{
+ m68ki_cpu_core *m68k = get_safe_token(device);
+ m68k->reset_instr_callback = callback;
+}
+
+void m68k_set_cmpild_callback(device_t *device, m68k_cmpild_func callback)
+{
+ m68ki_cpu_core *m68k = get_safe_token(device);
+ m68k->cmpild_instr_callback = callback;
+}
+
+void m68k_set_rte_callback(device_t *device, m68k_rte_func callback)
+{
+ m68ki_cpu_core *m68k = get_safe_token(device);
+ m68k->rte_instr_callback = callback;
+}
+
+void m68k_set_tas_callback(device_t *device, m68k_tas_func callback)
+{
+ m68ki_cpu_core *m68k = get_safe_token(device);
+ m68k->tas_instr_callback = callback;
+}
+
+UINT16 m68k_get_fc(device_t *device)
+{
+ m68ki_cpu_core *m68k = get_safe_token(device);
+ return m68k->mmu_tmp_fc;
+}
+
+
+/****************************************************************************
+ * State definition
+ ****************************************************************************/
+
+static void define_state(device_t *device)
+{
+ m68ki_cpu_core *m68k = get_safe_token(device);
+ UINT32 addrmask = (m68k->cpu_type & MASK_24BIT_SPACE) ? 0xffffff : 0xffffffff;
+
+ device_state_interface *state;
+ device->interface(state);
+ state->state_add(M68K_PC, "PC", m68k->pc).mask(addrmask);
+ state->state_add(STATE_GENPC, "GENPC", m68k->pc).mask(addrmask).noshow();
+ state->state_add(STATE_GENPCBASE, "GENPCBASE", m68k->ppc).mask(addrmask).noshow();
+ state->state_add(M68K_SP, "SP", m68k->dar[15]);
+ state->state_add(STATE_GENSP, "GENSP", m68k->dar[15]).noshow();
+ state->state_add(STATE_GENFLAGS, "GENFLAGS", m68k->iotemp).noshow().callimport().callexport().formatstr("%16s");
+ state->state_add(M68K_ISP, "ISP", m68k->iotemp).callimport().callexport();
+ state->state_add(M68K_USP, "USP", m68k->iotemp).callimport().callexport();
+ if (m68k->cpu_type & MASK_020_OR_LATER)
+ state->state_add(M68K_MSP, "MSP", m68k->iotemp).callimport().callexport();
+ state->state_add(M68K_ISP, "ISP", m68k->iotemp).callimport().callexport();
+
+ astring tempstr;
+ for (int regnum = 0; regnum < 8; regnum++)
+ state->state_add(M68K_D0 + regnum, tempstr.format("D%d", regnum), m68k->dar[regnum]);
+ for (int regnum = 0; regnum < 8; regnum++)
+ state->state_add(M68K_A0 + regnum, tempstr.format("A%d", regnum), m68k->dar[8 + regnum]);
+
+ state->state_add(M68K_PREF_ADDR, "PREF_ADDR", m68k->pref_addr).mask(addrmask);
+ state->state_add(M68K_PREF_DATA, "PREF_DATA", m68k->pref_data);
+
+ if (m68k->cpu_type & MASK_010_OR_LATER)
+ {
+ state->state_add(M68K_SFC, "SFC", m68k->sfc).mask(0x7);
+ state->state_add(M68K_DFC, "DFC", m68k->dfc).mask(0x7);
+ state->state_add(M68K_VBR, "VBR", m68k->vbr);
+ }
+
+ if (m68k->cpu_type & MASK_020_OR_LATER)
+ {
+ state->state_add(M68K_CACR, "CACR", m68k->cacr);
+ state->state_add(M68K_CAAR, "CAAR", m68k->caar);
+ }
+
+ if (m68k->cpu_type & MASK_030_OR_LATER)
+ {
+ for (int regnum = 0; regnum < 8; regnum++)
+ state->state_add(M68K_FP0 + regnum, tempstr.format("FP%d", regnum), m68k->iotemp).callimport().callexport().formatstr("%10s");
+ state->state_add(M68K_FPSR, "FPSR", m68k->fpsr);
+ state->state_add(M68K_FPCR, "FPCR", m68k->fpcr);
+ }
+}
+
+
+/****************************************************************************
+ * 68000 section
+ ****************************************************************************/
+
+static CPU_INIT( m68000 )
+{
+ m68ki_cpu_core *m68k = get_safe_token(device);
+
+ CPU_INIT_CALL(m68k);
+
+ m68k->cpu_type = CPU_TYPE_000;
+ m68k->dasm_type = M68K_CPU_TYPE_68000;
+// hack alert: we use placement new to ensure we are properly initialized
+// because we live in the device state which is allocated as bytes
+// remove me when we have a real C++ device
+ new(&m68k->memory) m68k_memory_interface;
+ m68k->memory.init16(*m68k->program);
+ m68k->sr_mask = 0xa71f; /* T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */
+ m68k->jump_table = m68ki_instruction_jump_table[0];
+ m68k->cyc_instruction = m68ki_cycles[0];
+ m68k->cyc_exception = m68ki_exception_cycle_table[0];
+ m68k->cyc_bcc_notake_b = -2;
+ m68k->cyc_bcc_notake_w = 2;
+ m68k->cyc_dbcc_f_noexp = -2;
+ m68k->cyc_dbcc_f_exp = 2;
+ m68k->cyc_scc_r_true = 2;
+ m68k->cyc_movem_w = 2;
+ m68k->cyc_movem_l = 3;
+ m68k->cyc_shift = 1;
+ m68k->cyc_reset = 132;
+ m68k->has_pmmu = 0;
+ m68k->has_hmmu = 0;
+ m68k->has_fpu = 0;
+
+ define_state(device);
+}
+
+CPU_GET_INFO( m68000 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(m68000); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "68000"); break;
+
+ default: CPU_GET_INFO_CALL(m68k); break;
+ }
+}
+
+
+/****************************************************************************
+ * M68008 section
+ ****************************************************************************/
+
+static CPU_INIT( m68008 )
+{
+ m68ki_cpu_core *m68k = get_safe_token(device);
+
+ CPU_INIT_CALL(m68k);
+
+ m68k->cpu_type = CPU_TYPE_008;
+ m68k->dasm_type = M68K_CPU_TYPE_68008;
+// hack alert: we use placement new to ensure we are properly initialized
+// because we live in the device state which is allocated as bytes
+// remove me when we have a real C++ device
+ new(&m68k->memory) m68k_memory_interface;
+ m68k->memory.init8(*m68k->program);
+ m68k->sr_mask = 0xa71f; /* T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */
+ m68k->jump_table = m68ki_instruction_jump_table[0];
+ m68k->cyc_instruction = m68ki_cycles[0];
+ m68k->cyc_exception = m68ki_exception_cycle_table[0];
+ m68k->cyc_bcc_notake_b = -2;
+ m68k->cyc_bcc_notake_w = 2;
+ m68k->cyc_dbcc_f_noexp = -2;
+ m68k->cyc_dbcc_f_exp = 2;
+ m68k->cyc_scc_r_true = 2;
+ m68k->cyc_movem_w = 2;
+ m68k->cyc_movem_l = 3;
+ m68k->cyc_shift = 1;
+ m68k->cyc_reset = 132;
+ m68k->has_pmmu = 0;
+ m68k->has_fpu = 0;
+
+ define_state(device);
+}
+
+CPU_GET_INFO( m68008 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 22; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(m68008); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "68008"); break;
+
+ default: CPU_GET_INFO_CALL(m68k); break;
+ }
+}
+
+
+/****************************************************************************
+ * M68010 section
+ ****************************************************************************/
+
+static CPU_INIT( m68010 )
+{
+ m68ki_cpu_core *m68k = get_safe_token(device);
+
+ CPU_INIT_CALL(m68k);
+
+ m68k->cpu_type = CPU_TYPE_010;
+ m68k->dasm_type = M68K_CPU_TYPE_68010;
+// hack alert: we use placement new to ensure we are properly initialized
+// because we live in the device state which is allocated as bytes
+// remove me when we have a real C++ device
+ new(&m68k->memory) m68k_memory_interface;
+ m68k->memory.init16(*m68k->program);
+ m68k->sr_mask = 0xa71f; /* T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */
+ m68k->jump_table = m68ki_instruction_jump_table[1];
+ m68k->cyc_instruction = m68ki_cycles[1];
+ m68k->cyc_exception = m68ki_exception_cycle_table[1];
+ m68k->cyc_bcc_notake_b = -4;
+ m68k->cyc_bcc_notake_w = 0;
+ m68k->cyc_dbcc_f_noexp = 0;
+ m68k->cyc_dbcc_f_exp = 6;
+ m68k->cyc_scc_r_true = 0;
+ m68k->cyc_movem_w = 2;
+ m68k->cyc_movem_l = 3;
+ m68k->cyc_shift = 1;
+ m68k->cyc_reset = 130;
+ m68k->has_pmmu = 0;
+ m68k->has_fpu = 0;
+
+ define_state(device);
+}
+
+CPU_GET_INFO( m68010 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(m68010); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "68010"); break;
+
+ default: CPU_GET_INFO_CALL(m68k); break;
+ }
+}
+
+
+/****************************************************************************
+ * M68020 section
+ ****************************************************************************/
+
+static CPU_INIT( m68020 )
+{
+ m68ki_cpu_core *m68k = get_safe_token(device);
+
+ CPU_INIT_CALL(m68k);
+
+ m68k->cpu_type = CPU_TYPE_020;
+ m68k->dasm_type = M68K_CPU_TYPE_68020;
+// hack alert: we use placement new to ensure we are properly initialized
+// because we live in the device state which is allocated as bytes
+// remove me when we have a real C++ device
+ new(&m68k->memory) m68k_memory_interface;
+ m68k->memory.init32(*m68k->program);
+ m68k->sr_mask = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
+ m68k->jump_table = m68ki_instruction_jump_table[2];
+ m68k->cyc_instruction = m68ki_cycles[2];
+ m68k->cyc_exception = m68ki_exception_cycle_table[2];
+ m68k->cyc_bcc_notake_b = -2;
+ m68k->cyc_bcc_notake_w = 0;
+ m68k->cyc_dbcc_f_noexp = 0;
+ m68k->cyc_dbcc_f_exp = 4;
+ m68k->cyc_scc_r_true = 0;
+ m68k->cyc_movem_w = 2;
+ m68k->cyc_movem_l = 2;
+ m68k->cyc_shift = 0;
+ m68k->cyc_reset = 518;
+
+ define_state(device);
+}
+
+CPU_GET_INFO( m68020 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 20; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 2; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 158; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(m68020); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "68020"); break;
+
+ default: CPU_GET_INFO_CALL(m68k); break;
+ }
+}
+
+// 68020 with 68851 PMMU
+static CPU_INIT( m68020pmmu )
+{
+ m68ki_cpu_core *m68k = get_safe_token(device);
+
+ CPU_INIT_CALL(m68020);
+
+ m68k->has_pmmu = 1;
+ m68k->has_fpu = 1;
+
+// hack alert: we use placement new to ensure we are properly initialized
+// because we live in the device state which is allocated as bytes
+// remove me when we have a real C++ device
+ new(&m68k->memory) m68k_memory_interface;
+ m68k->memory.init32mmu(*m68k->program);
+}
+
+CPU_GET_INFO( m68020pmmu )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(m68020pmmu); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "68020, 68851"); break;
+
+ default: CPU_GET_INFO_CALL(m68020); break;
+ }
+}
+
+// 68020 with Apple HMMU & 68881 FPU
+static CPU_INIT( m68020hmmu )
+{
+ m68ki_cpu_core *m68k = get_safe_token(device);
+
+ CPU_INIT_CALL(m68020);
+
+ m68k->has_hmmu = 1;
+ m68k->has_fpu = 1;
+// hack alert: we use placement new to ensure we are properly initialized
+// because we live in the device state which is allocated as bytes
+// remove me when we have a real C++ device
+ new(&m68k->memory) m68k_memory_interface;
+ m68k->memory.init32hmmu(*m68k->program);
+}
+
+CPU_GET_INFO( m68020hmmu )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(m68020hmmu); break;
+ case CPUINFO_FCT_TRANSLATE: info->translate = CPU_TRANSLATE_NAME(m68khmmu); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "68020, Apple HMMU"); break;
+
+ default: CPU_GET_INFO_CALL(m68020); break;
+ }
+}
+
+/****************************************************************************
+ * M680EC20 section
+ ****************************************************************************/
+
+static CPU_INIT( m68ec020 )
+{
+ m68ki_cpu_core *m68k = get_safe_token(device);
+
+ CPU_INIT_CALL(m68k);
+
+ m68k->cpu_type = CPU_TYPE_EC020;
+ m68k->dasm_type = M68K_CPU_TYPE_68EC020;
+// hack alert: we use placement new to ensure we are properly initialized
+// because we live in the device state which is allocated as bytes
+// remove me when we have a real C++ device
+ new(&m68k->memory) m68k_memory_interface;
+ m68k->memory.init32(*m68k->program);
+ m68k->sr_mask = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
+ m68k->jump_table = m68ki_instruction_jump_table[2];
+ m68k->cyc_instruction = m68ki_cycles[2];
+ m68k->cyc_exception = m68ki_exception_cycle_table[2];
+ m68k->cyc_bcc_notake_b = -2;
+ m68k->cyc_bcc_notake_w = 0;
+ m68k->cyc_dbcc_f_noexp = 0;
+ m68k->cyc_dbcc_f_exp = 4;
+ m68k->cyc_scc_r_true = 0;
+ m68k->cyc_movem_w = 2;
+ m68k->cyc_movem_l = 2;
+ m68k->cyc_shift = 0;
+ m68k->cyc_reset = 518;
+ m68k->has_pmmu = 0;
+ m68k->has_fpu = 0;
+
+ define_state(device);
+}
+
+CPU_GET_INFO( m68ec020 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 24; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(m68ec020); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "68EC020"); break;
+
+ default: CPU_GET_INFO_CALL(m68020); break;
+ }
+}
+
+/****************************************************************************
+ * M68030 section
+ ****************************************************************************/
+
+static CPU_INIT( m68030 )
+{
+ m68ki_cpu_core *m68k = get_safe_token(device);
+
+ CPU_INIT_CALL(m68k);
+
+ m68k->cpu_type = CPU_TYPE_030;
+ m68k->dasm_type = M68K_CPU_TYPE_68030;
+// hack alert: we use placement new to ensure we are properly initialized
+// because we live in the device state which is allocated as bytes
+// remove me when we have a real C++ device
+ new(&m68k->memory) m68k_memory_interface;
+ m68k->memory.init32mmu(*m68k->program);
+ m68k->sr_mask = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
+ m68k->jump_table = m68ki_instruction_jump_table[3];
+ m68k->cyc_instruction = m68ki_cycles[3];
+ m68k->cyc_exception = m68ki_exception_cycle_table[3];
+ m68k->cyc_bcc_notake_b = -2;
+ m68k->cyc_bcc_notake_w = 0;
+ m68k->cyc_dbcc_f_noexp = 0;
+ m68k->cyc_dbcc_f_exp = 4;
+ m68k->cyc_scc_r_true = 0;
+ m68k->cyc_movem_w = 2;
+ m68k->cyc_movem_l = 2;
+ m68k->cyc_shift = 0;
+ m68k->cyc_reset = 518;
+ m68k->has_pmmu = 1;
+ m68k->has_fpu = 1;
+
+ define_state(device);
+}
+
+CPU_GET_INFO( m68030 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 20; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 2; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 158; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(m68030); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "68030"); break;
+
+ default: CPU_GET_INFO_CALL(m68k); break;
+ }
+}
+
+
+/****************************************************************************
+ * M680EC30 section
+ ****************************************************************************/
+
+static CPU_INIT( m68ec030 )
+{
+ m68ki_cpu_core *m68k = get_safe_token(device);
+
+ CPU_INIT_CALL(m68k);
+
+ m68k->cpu_type = CPU_TYPE_EC030;
+ m68k->dasm_type = M68K_CPU_TYPE_68EC030;
+// hack alert: we use placement new to ensure we are properly initialized
+// because we live in the device state which is allocated as bytes
+// remove me when we have a real C++ device
+ new(&m68k->memory) m68k_memory_interface;
+ m68k->memory.init32(*m68k->program);
+ m68k->sr_mask = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
+ m68k->jump_table = m68ki_instruction_jump_table[3];
+ m68k->cyc_instruction = m68ki_cycles[3];
+ m68k->cyc_exception = m68ki_exception_cycle_table[3];
+ m68k->cyc_bcc_notake_b = -2;
+ m68k->cyc_bcc_notake_w = 0;
+ m68k->cyc_dbcc_f_noexp = 0;
+ m68k->cyc_dbcc_f_exp = 4;
+ m68k->cyc_scc_r_true = 0;
+ m68k->cyc_movem_w = 2;
+ m68k->cyc_movem_l = 2;
+ m68k->cyc_shift = 0;
+ m68k->cyc_reset = 518;
+ m68k->has_pmmu = 0; /* EC030 lacks the PMMU and is effectively a die-shrink 68020 */
+ m68k->has_fpu = 1;
+
+ define_state(device);
+}
+
+CPU_GET_INFO( m68ec030 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(m68ec030); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "68EC030"); break;
+
+ default: CPU_GET_INFO_CALL(m68030); break;
+ }
+}
+
+/****************************************************************************
+ * M68040 section
+ ****************************************************************************/
+
+static CPU_INIT( m68040 )
+{
+ m68ki_cpu_core *m68k = get_safe_token(device);
+
+ CPU_INIT_CALL(m68k);
+
+ m68k->cpu_type = CPU_TYPE_040;
+ m68k->dasm_type = M68K_CPU_TYPE_68040;
+// hack alert: we use placement new to ensure we are properly initialized
+// because we live in the device state which is allocated as bytes
+// remove me when we have a real C++ device
+ new(&m68k->memory) m68k_memory_interface;
+ m68k->memory.init32mmu(*m68k->program);
+ m68k->sr_mask = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
+ m68k->jump_table = m68ki_instruction_jump_table[4];
+ m68k->cyc_instruction = m68ki_cycles[4];
+ m68k->cyc_exception = m68ki_exception_cycle_table[4];
+ m68k->cyc_bcc_notake_b = -2;
+ m68k->cyc_bcc_notake_w = 0;
+ m68k->cyc_dbcc_f_noexp = 0;
+ m68k->cyc_dbcc_f_exp = 4;
+ m68k->cyc_scc_r_true = 0;
+ m68k->cyc_movem_w = 2;
+ m68k->cyc_movem_l = 2;
+ m68k->cyc_shift = 0;
+ m68k->cyc_reset = 518;
+ m68k->has_pmmu = 1;
+ m68k->has_fpu = 1;
+
+ define_state(device);
+}
+
+CPU_GET_INFO( m68040 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 20; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 2; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 158; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(m68040); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "68040"); break;
+
+ default: CPU_GET_INFO_CALL(m68k); break;
+ }
+}
+
+/****************************************************************************
+ * M68EC040 section
+ ****************************************************************************/
+
+static CPU_INIT( m68ec040 )
+{
+ m68ki_cpu_core *m68k = get_safe_token(device);
+
+ CPU_INIT_CALL(m68k);
+
+ m68k->cpu_type = CPU_TYPE_EC040;
+ m68k->dasm_type = M68K_CPU_TYPE_68EC040;
+// hack alert: we use placement new to ensure we are properly initialized
+// because we live in the device state which is allocated as bytes
+// remove me when we have a real C++ device
+ new(&m68k->memory) m68k_memory_interface;
+ m68k->memory.init32(*m68k->program);
+ m68k->sr_mask = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
+ m68k->jump_table = m68ki_instruction_jump_table[4];
+ m68k->cyc_instruction = m68ki_cycles[4];
+ m68k->cyc_exception = m68ki_exception_cycle_table[4];
+ m68k->cyc_bcc_notake_b = -2;
+ m68k->cyc_bcc_notake_w = 0;
+ m68k->cyc_dbcc_f_noexp = 0;
+ m68k->cyc_dbcc_f_exp = 4;
+ m68k->cyc_scc_r_true = 0;
+ m68k->cyc_movem_w = 2;
+ m68k->cyc_movem_l = 2;
+ m68k->cyc_shift = 0;
+ m68k->cyc_reset = 518;
+ m68k->has_pmmu = 0;
+ m68k->has_fpu = 0;
+
+ define_state(device);
+}
+
+CPU_GET_INFO( m68ec040 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(m68ec040); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "68EC040"); break;
+
+ default: CPU_GET_INFO_CALL(m68040); break;
+ }
+}
+
+/****************************************************************************
+ * M68LC040 section
+ ****************************************************************************/
+
+static CPU_INIT( m68lc040 )
+{
+ m68ki_cpu_core *m68k = get_safe_token(device);
+
+ CPU_INIT_CALL(m68k);
+
+ m68k->cpu_type = CPU_TYPE_LC040;
+ m68k->dasm_type = M68K_CPU_TYPE_68LC040;
+// hack alert: we use placement new to ensure we are properly initialized
+// because we live in the device state which is allocated as bytes
+// remove me when we have a real C++ device
+ new(&m68k->memory) m68k_memory_interface;
+ m68k->memory.init32mmu(*m68k->program);
+ m68k->sr_mask = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
+ m68k->jump_table = m68ki_instruction_jump_table[4];
+ m68k->cyc_instruction = m68ki_cycles[4];
+ m68k->cyc_exception = m68ki_exception_cycle_table[4];
+ m68k->cyc_bcc_notake_b = -2;
+ m68k->cyc_bcc_notake_w = 0;
+ m68k->cyc_dbcc_f_noexp = 0;
+ m68k->cyc_dbcc_f_exp = 4;
+ m68k->cyc_scc_r_true = 0;
+ m68k->cyc_movem_w = 2;
+ m68k->cyc_movem_l = 2;
+ m68k->cyc_shift = 0;
+ m68k->cyc_reset = 518;
+ m68k->has_pmmu = 1;
+ m68k->has_fpu = 0;
+
+ define_state(device);
+}
+
+CPU_GET_INFO( m68lc040 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(m68lc040); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "68LC040"); break;
+
+ default: CPU_GET_INFO_CALL(m68040); break;
+ }
+}
+
+/****************************************************************************
+ * SCC-68070 section
+ ****************************************************************************/
+
+static CPU_INIT( scc68070 )
+{
+ m68ki_cpu_core *m68k = get_safe_token(device);
+
+ CPU_INIT_CALL(m68010);
+
+ m68k->cpu_type = CPU_TYPE_SCC070;
+}
+
+CPU_GET_INFO( scc68070 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(scc68070); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "SCC68070"); break;
+
+ default: CPU_GET_INFO_CALL(m68k); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(M68000, m68000);
+DEFINE_LEGACY_CPU_DEVICE(M68008, m68008);
+DEFINE_LEGACY_CPU_DEVICE(M68010, m68010);
+DEFINE_LEGACY_CPU_DEVICE(M68EC020, m68ec020);
+DEFINE_LEGACY_CPU_DEVICE(M68020, m68020);
+DEFINE_LEGACY_CPU_DEVICE(M68020PMMU, m68020pmmu);
+DEFINE_LEGACY_CPU_DEVICE(M68020HMMU, m68020hmmu);
+DEFINE_LEGACY_CPU_DEVICE(M68EC030, m68ec030);
+DEFINE_LEGACY_CPU_DEVICE(M68030, m68030);
+DEFINE_LEGACY_CPU_DEVICE(M68EC040, m68ec040);
+DEFINE_LEGACY_CPU_DEVICE(M68LC040, m68lc040);
+DEFINE_LEGACY_CPU_DEVICE(M68040, m68040);
+DEFINE_LEGACY_CPU_DEVICE(SCC68070, scc68070);
+
diff --git a/trunk/src/emu/cpu/m68000/m68kcpu.h b/trunk/src/emu/cpu/m68000/m68kcpu.h
new file mode 100644
index 00000000000..9311cfa2f52
--- /dev/null
+++ b/trunk/src/emu/cpu/m68000/m68kcpu.h
@@ -0,0 +1,1923 @@
+/* ======================================================================== */
+/* ========================= LICENSING & COPYRIGHT ======================== */
+/* ======================================================================== */
+/*
+ * MUSASHI
+ * Version 4.50
+ *
+ * A portable Motorola M680x0 processor emulation engine.
+ * Copyright Karl Stenerud. All rights reserved.
+ *
+ * This code may be freely used for non-commercial purposes as long as this
+ * copyright notice remains unaltered in the source code and any binary files
+ * containing this code in compiled form.
+ *
+ * All other licensing terms must be negotiated with the author
+ * (Karl Stenerud).
+ *
+ * The latest version of this code can be obtained at:
+ * http://kstenerud.cjb.net
+ */
+
+
+#pragma once
+
+#ifndef __M68KCPU_H__
+#define __M68KCPU_H__
+
+typedef struct _m68ki_cpu_core m68ki_cpu_core;
+
+
+#include "m68000.h"
+#include "../../../lib/softfloat/milieu.h"
+#include "../../../lib/softfloat/softfloat.h"
+
+#include <limits.h>
+#include <setjmp.h>
+
+/* ======================================================================== */
+/* ==================== ARCHITECTURE-DEPENDANT DEFINES ==================== */
+/* ======================================================================== */
+
+/* Check for > 32bit sizes */
+#define MAKE_INT_8(A) (INT8)(A)
+#define MAKE_INT_16(A) (INT16)(A)
+#define MAKE_INT_32(A) (INT32)(A)
+
+
+/* ======================================================================== */
+/* ============================ GENERAL DEFINES =========================== */
+/* ======================================================================== */
+
+/* Exception Vectors handled by emulation */
+#define EXCEPTION_RESET 0
+#define EXCEPTION_BUS_ERROR 2 /* This one is not emulated! */
+#define EXCEPTION_ADDRESS_ERROR 3 /* This one is partially emulated (doesn't stack a proper frame yet) */
+#define EXCEPTION_ILLEGAL_INSTRUCTION 4
+#define EXCEPTION_ZERO_DIVIDE 5
+#define EXCEPTION_CHK 6
+#define EXCEPTION_TRAPV 7
+#define EXCEPTION_PRIVILEGE_VIOLATION 8
+#define EXCEPTION_TRACE 9
+#define EXCEPTION_1010 10
+#define EXCEPTION_1111 11
+#define EXCEPTION_FORMAT_ERROR 14
+#define EXCEPTION_UNINITIALIZED_INTERRUPT 15
+#define EXCEPTION_SPURIOUS_INTERRUPT 24
+#define EXCEPTION_INTERRUPT_AUTOVECTOR 24
+#define EXCEPTION_TRAP_BASE 32
+
+/* Function codes set by CPU during data/address bus activity */
+#define FUNCTION_CODE_USER_DATA 1
+#define FUNCTION_CODE_USER_PROGRAM 2
+#define FUNCTION_CODE_SUPERVISOR_DATA 5
+#define FUNCTION_CODE_SUPERVISOR_PROGRAM 6
+#define FUNCTION_CODE_CPU_SPACE 7
+
+/* CPU types for deciding what to emulate */
+#define CPU_TYPE_000 (0x00000001)
+#define CPU_TYPE_008 (0x00000002)
+#define CPU_TYPE_010 (0x00000004)
+#define CPU_TYPE_EC020 (0x00000008)
+#define CPU_TYPE_020 (0x00000010)
+#define CPU_TYPE_EC030 (0x00000020)
+#define CPU_TYPE_030 (0x00000040)
+#define CPU_TYPE_EC040 (0x00000080)
+#define CPU_TYPE_LC040 (0x00000100)
+#define CPU_TYPE_040 (0x00000200)
+#define CPU_TYPE_SCC070 (0x00000400)
+
+/* Different ways to stop the CPU */
+#define STOP_LEVEL_STOP 1
+#define STOP_LEVEL_HALT 2
+
+/* Used for 68000 address error processing */
+#define INSTRUCTION_YES 0
+#define INSTRUCTION_NO 0x08
+#define MODE_READ 0x10
+#define MODE_WRITE 0
+
+#define RUN_MODE_NORMAL 0
+#define RUN_MODE_BERR_AERR_RESET 1
+
+/* MMU constants */
+#define MMU_ATC_ENTRIES (22) // 68851 has 64, 030 has 22
+
+/* instruction cache constants */
+#define M68K_IC_SIZE 128
+
+#define M68K_CACR_IBE 0x10 // Instruction Burst Enable
+#define M68K_CACR_CI 0x08 // Clear Instruction Cache
+#define M68K_CACR_CEI 0x04 // Clear Entry in Instruction Cache
+#define M68K_CACR_FI 0x02 // Freeze Instruction Cache
+#define M68K_CACR_EI 0x01 // Enable Instruction Cache
+
+/* ======================================================================== */
+/* ================================ MACROS ================================ */
+/* ======================================================================== */
+
+
+/* ---------------------------- General Macros ---------------------------- */
+
+/* Bit Isolation Macros */
+#define BIT_0(A) ((A) & 0x00000001)
+#define BIT_1(A) ((A) & 0x00000002)
+#define BIT_2(A) ((A) & 0x00000004)
+#define BIT_3(A) ((A) & 0x00000008)
+#define BIT_4(A) ((A) & 0x00000010)
+#define BIT_5(A) ((A) & 0x00000020)
+#define BIT_6(A) ((A) & 0x00000040)
+#define BIT_7(A) ((A) & 0x00000080)
+#define BIT_8(A) ((A) & 0x00000100)
+#define BIT_9(A) ((A) & 0x00000200)
+#define BIT_A(A) ((A) & 0x00000400)
+#define BIT_B(A) ((A) & 0x00000800)
+#define BIT_C(A) ((A) & 0x00001000)
+#define BIT_D(A) ((A) & 0x00002000)
+#define BIT_E(A) ((A) & 0x00004000)
+#define BIT_F(A) ((A) & 0x00008000)
+#define BIT_10(A) ((A) & 0x00010000)
+#define BIT_11(A) ((A) & 0x00020000)
+#define BIT_12(A) ((A) & 0x00040000)
+#define BIT_13(A) ((A) & 0x00080000)
+#define BIT_14(A) ((A) & 0x00100000)
+#define BIT_15(A) ((A) & 0x00200000)
+#define BIT_16(A) ((A) & 0x00400000)
+#define BIT_17(A) ((A) & 0x00800000)
+#define BIT_18(A) ((A) & 0x01000000)
+#define BIT_19(A) ((A) & 0x02000000)
+#define BIT_1A(A) ((A) & 0x04000000)
+#define BIT_1B(A) ((A) & 0x08000000)
+#define BIT_1C(A) ((A) & 0x10000000)
+#define BIT_1D(A) ((A) & 0x20000000)
+#define BIT_1E(A) ((A) & 0x40000000)
+#define BIT_1F(A) ((A) & 0x80000000)
+
+/* Get the most significant bit for specific sizes */
+#define GET_MSB_8(A) ((A) & 0x80)
+#define GET_MSB_9(A) ((A) & 0x100)
+#define GET_MSB_16(A) ((A) & 0x8000)
+#define GET_MSB_17(A) ((A) & 0x10000)
+#define GET_MSB_32(A) ((A) & 0x80000000)
+#define GET_MSB_33(A) ((A) & U64(0x100000000))
+
+/* Isolate nibbles */
+#define LOW_NIBBLE(A) ((A) & 0x0f)
+#define HIGH_NIBBLE(A) ((A) & 0xf0)
+
+/* These are used to isolate 8, 16, and 32 bit sizes */
+#define MASK_OUT_ABOVE_2(A) ((A) & 3)
+#define MASK_OUT_ABOVE_8(A) ((A) & 0xff)
+#define MASK_OUT_ABOVE_16(A) ((A) & 0xffff)
+#define MASK_OUT_BELOW_2(A) ((A) & ~3)
+#define MASK_OUT_BELOW_8(A) ((A) & ~0xff)
+#define MASK_OUT_BELOW_16(A) ((A) & ~0xffff)
+
+/* No need to mask if we are 32 bit */
+#define MASK_OUT_ABOVE_32(A) ((A) & U64(0xffffffff))
+#define MASK_OUT_BELOW_32(A) ((A) & ~U64(0xffffffff))
+
+/* Shift & Rotate Macros. */
+#define LSL(A, C) ((A) << (C))
+#define LSR(A, C) ((A) >> (C))
+
+/* We have to do this because the morons at ANSI decided that shifts
+* by >= data size are undefined.
+*/
+#define LSR_32(A, C) ((C) < 32 ? (A) >> (C) : 0)
+#define LSL_32(A, C) ((C) < 32 ? (A) << (C) : 0)
+
+#define LSL_32_64(A, C) ((A) << (C))
+#define LSR_32_64(A, C) ((A) >> (C))
+#define ROL_33_64(A, C) (LSL_32_64(A, C) | LSR_32_64(A, 33-(C)))
+#define ROR_33_64(A, C) (LSR_32_64(A, C) | LSL_32_64(A, 33-(C)))
+
+#define ROL_8(A, C) MASK_OUT_ABOVE_8(LSL(A, C) | LSR(A, 8-(C)))
+#define ROL_9(A, C) (LSL(A, C) | LSR(A, 9-(C)))
+#define ROL_16(A, C) MASK_OUT_ABOVE_16(LSL(A, C) | LSR(A, 16-(C)))
+#define ROL_17(A, C) (LSL(A, C) | LSR(A, 17-(C)))
+#define ROL_32(A, C) MASK_OUT_ABOVE_32(LSL_32(A, C) | LSR_32(A, 32-(C)))
+#define ROL_33(A, C) (LSL_32(A, C) | LSR_32(A, 33-(C)))
+
+#define ROR_8(A, C) MASK_OUT_ABOVE_8(LSR(A, C) | LSL(A, 8-(C)))
+#define ROR_9(A, C) (LSR(A, C) | LSL(A, 9-(C)))
+#define ROR_16(A, C) MASK_OUT_ABOVE_16(LSR(A, C) | LSL(A, 16-(C)))
+#define ROR_17(A, C) (LSR(A, C) | LSL(A, 17-(C)))
+#define ROR_32(A, C) MASK_OUT_ABOVE_32(LSR_32(A, C) | LSL_32(A, 32-(C)))
+#define ROR_33(A, C) (LSR_32(A, C) | LSL_32(A, 33-(C)))
+
+
+
+/* ------------------------------ CPU Access ------------------------------ */
+
+/* Access the CPU registers */
+#define REG_DA m68k->dar /* easy access to data and address regs */
+#define REG_D m68k->dar
+#define REG_A (m68k->dar+8)
+#define REG_PPC m68k->ppc
+#define REG_PC m68k->pc
+#define REG_SP_BASE m68k->sp
+#define REG_USP m68k->sp[0]
+#define REG_ISP m68k->sp[4]
+#define REG_MSP m68k->sp[6]
+#define REG_SP m68k->dar[15]
+
+#define REG_FP m68k->fpr
+#define REG_FPCR m68k->fpcr
+#define REG_FPSR m68k->fpsr
+#define REG_FPIAR m68k->fpiar
+
+
+/* ----------------------------- Configuration ---------------------------- */
+
+/* These defines are dependant on the configuration defines in m68kconf.h */
+
+/* Disable certain comparisons if we're not using all CPU types */
+#define CPU_TYPE_IS_040_PLUS(A) ((A) & (CPU_TYPE_040 | CPU_TYPE_EC040))
+#define CPU_TYPE_IS_040_LESS(A) 1
+
+#define CPU_TYPE_IS_030_PLUS(A) ((A) & (CPU_TYPE_030 | CPU_TYPE_EC030 | CPU_TYPE_040 | CPU_TYPE_EC040))
+#define CPU_TYPE_IS_030_LESS(A) 1
+
+#define CPU_TYPE_IS_020_PLUS(A) ((A) & (CPU_TYPE_020 | CPU_TYPE_030 | CPU_TYPE_EC030 | CPU_TYPE_040 | CPU_TYPE_EC040))
+#define CPU_TYPE_IS_020_LESS(A) 1
+
+#define CPU_TYPE_IS_020_VARIANT(A) ((A) & (CPU_TYPE_EC020 | CPU_TYPE_020))
+
+#define CPU_TYPE_IS_EC020_PLUS(A) ((A) & (CPU_TYPE_EC020 | CPU_TYPE_020 | CPU_TYPE_030 | CPU_TYPE_EC030 | CPU_TYPE_040 | CPU_TYPE_EC040))
+#define CPU_TYPE_IS_EC020_LESS(A) ((A) & (CPU_TYPE_000 | CPU_TYPE_008 | CPU_TYPE_010 | CPU_TYPE_EC020))
+
+#define CPU_TYPE_IS_010(A) ((A) == CPU_TYPE_010)
+#define CPU_TYPE_IS_010_PLUS(A) ((A) & (CPU_TYPE_010 | CPU_TYPE_EC020 | CPU_TYPE_020 | CPU_TYPE_EC030 | CPU_TYPE_030 | CPU_TYPE_040 | CPU_TYPE_EC040))
+#define CPU_TYPE_IS_010_LESS(A) ((A) & (CPU_TYPE_000 | CPU_TYPE_008 | CPU_TYPE_010))
+
+#define CPU_TYPE_IS_000(A) ((A) == CPU_TYPE_000 || (A) == CPU_TYPE_008)
+
+
+/* Configuration switches (see m68kconf.h for explanation) */
+#define M68K_EMULATE_TRACE 0
+
+/* Enable or disable trace emulation */
+#if M68K_EMULATE_TRACE
+ /* Initiates trace checking before each instruction (t1) */
+ #define m68ki_trace_t1() m68ki_tracing = m68k->t1_flag
+ /* adds t0 to trace checking if we encounter change of flow */
+ #define m68ki_trace_t0() m68ki_tracing |= m68k->t0_flag
+ /* Clear all tracing */
+ #define m68ki_clear_trace() m68ki_tracing = 0
+ /* Cause a trace exception if we are tracing */
+ #define m68ki_exception_if_trace() if(m68ki_tracing) m68ki_exception_trace(m68k)
+#else
+ #define m68ki_trace_t1()
+ #define m68ki_trace_t0()
+ #define m68ki_clear_trace()
+ #define m68ki_exception_if_trace()
+#endif /* M68K_EMULATE_TRACE */
+
+
+
+/* Address error */
+/* sigjmp() on Mac OS X and *BSD in general saves signal contexts and is super-slow, use sigsetjmp() to tell it not to */
+#ifdef _BSD_SETJMP_H
+#define m68ki_set_address_error_trap(m68k) \
+ if(sigsetjmp(m68k->aerr_trap, 0) != 0) \
+ { \
+ m68ki_exception_address_error(m68k); \
+ if(m68k->stopped) \
+ { \
+ if (m68k->remaining_cycles > 0) \
+ m68k->remaining_cycles = 0; \
+ return; \
+ } \
+ }
+
+#define m68ki_check_address_error(m68k, ADDR, WRITE_MODE, FC) \
+ if((ADDR)&1) \
+ { \
+ m68k->aerr_address = ADDR; \
+ m68k->aerr_write_mode = WRITE_MODE; \
+ m68k->aerr_fc = FC; \
+ siglongjmp(m68k->aerr_trap, 1); \
+ }
+#else
+#define m68ki_set_address_error_trap(m68k) \
+ if(setjmp(m68k->aerr_trap) != 0) \
+ { \
+ m68ki_exception_address_error(m68k); \
+ if(m68k->stopped) \
+ { \
+ if (m68k->remaining_cycles > 0) \
+ m68k->remaining_cycles = 0; \
+ return; \
+ } \
+ }
+
+#define m68ki_check_address_error(m68k, ADDR, WRITE_MODE, FC) \
+ if((ADDR)&1) \
+ { \
+ m68k->aerr_address = ADDR; \
+ m68k->aerr_write_mode = WRITE_MODE; \
+ m68k->aerr_fc = FC; \
+ longjmp(m68k->aerr_trap, 1); \
+ }
+#endif
+
+
+/* -------------------------- EA / Operand Access ------------------------- */
+
+/*
+ * The general instruction format follows this pattern:
+ * .... XXX. .... .YYY
+ * where XXX is register X and YYY is register Y
+ */
+/* Data Register Isolation */
+#define DX (REG_D[(m68k->ir >> 9) & 7])
+#define DY (REG_D[m68k->ir & 7])
+/* Address Register Isolation */
+#define AX (REG_A[(m68k->ir >> 9) & 7])
+#define AY (REG_A[m68k->ir & 7])
+
+
+/* Effective Address Calculations */
+#define EA_AY_AI_8(m68k) AY /* address register indirect */
+#define EA_AY_AI_16(m68k) EA_AY_AI_8(m68k)
+#define EA_AY_AI_32(m68k) EA_AY_AI_8(m68k)
+#define EA_AY_PI_8(m68k) (AY++) /* postincrement (size = byte) */
+#define EA_AY_PI_16(m68k) ((AY+=2)-2) /* postincrement (size = word) */
+#define EA_AY_PI_32(m68k) ((AY+=4)-4) /* postincrement (size = long) */
+#define EA_AY_PD_8(m68k) (--AY) /* predecrement (size = byte) */
+#define EA_AY_PD_16(m68k) (AY-=2) /* predecrement (size = word) */
+#define EA_AY_PD_32(m68k) (AY-=4) /* predecrement (size = long) */
+#define EA_AY_DI_8(m68k) (AY+MAKE_INT_16(m68ki_read_imm_16(m68k))) /* displacement */
+#define EA_AY_DI_16(m68k) EA_AY_DI_8(m68k)
+#define EA_AY_DI_32(m68k) EA_AY_DI_8(m68k)
+#define EA_AY_IX_8(m68k) m68ki_get_ea_ix(m68k, AY) /* indirect + index */
+#define EA_AY_IX_16(m68k) EA_AY_IX_8(m68k)
+#define EA_AY_IX_32(m68k) EA_AY_IX_8(m68k)
+
+#define EA_AX_AI_8(m68k) AX
+#define EA_AX_AI_16(m68k) EA_AX_AI_8(m68k)
+#define EA_AX_AI_32(m68k) EA_AX_AI_8(m68k)
+#define EA_AX_PI_8(m68k) (AX++)
+#define EA_AX_PI_16(m68k) ((AX+=2)-2)
+#define EA_AX_PI_32(m68k) ((AX+=4)-4)
+#define EA_AX_PD_8(m68k) (--AX)
+#define EA_AX_PD_16(m68k) (AX-=2)
+#define EA_AX_PD_32(m68k) (AX-=4)
+#define EA_AX_DI_8(m68k) (AX+MAKE_INT_16(m68ki_read_imm_16(m68k)))
+#define EA_AX_DI_16(m68k) EA_AX_DI_8(m68k)
+#define EA_AX_DI_32(m68k) EA_AX_DI_8(m68k)
+#define EA_AX_IX_8(m68k) m68ki_get_ea_ix(m68k, AX)
+#define EA_AX_IX_16(m68k) EA_AX_IX_8(m68k)
+#define EA_AX_IX_32(m68k) EA_AX_IX_8(m68k)
+
+#define EA_A7_PI_8(m68k) ((REG_A[7]+=2)-2)
+#define EA_A7_PD_8(m68k) (REG_A[7]-=2)
+
+#define EA_AW_8(m68k) MAKE_INT_16(m68ki_read_imm_16(m68k)) /* absolute word */
+#define EA_AW_16(m68k) EA_AW_8(m68k)
+#define EA_AW_32(m68k) EA_AW_8(m68k)
+#define EA_AL_8(m68k) m68ki_read_imm_32(m68k) /* absolute long */
+#define EA_AL_16(m68k) EA_AL_8(m68k)
+#define EA_AL_32(m68k) EA_AL_8(m68k)
+#define EA_PCDI_8(m68k) m68ki_get_ea_pcdi(m68k) /* pc indirect + displacement */
+#define EA_PCDI_16(m68k) EA_PCDI_8(m68k)
+#define EA_PCDI_32(m68k) EA_PCDI_8(m68k)
+#define EA_PCIX_8(m68k) m68ki_get_ea_pcix(m68k) /* pc indirect + index */
+#define EA_PCIX_16(m68k) EA_PCIX_8(m68k)
+#define EA_PCIX_32(m68k) EA_PCIX_8(m68k)
+
+
+#define OPER_I_8(m68k) m68ki_read_imm_8(m68k)
+#define OPER_I_16(m68k) m68ki_read_imm_16(m68k)
+#define OPER_I_32(m68k) m68ki_read_imm_32(m68k)
+
+
+
+/* --------------------------- Status Register ---------------------------- */
+
+/* Flag Calculation Macros */
+#define CFLAG_8(A) (A)
+#define CFLAG_16(A) ((A)>>8)
+
+#define CFLAG_ADD_32(S, D, R) (((S & D) | (~R & (S | D)))>>23)
+#define CFLAG_SUB_32(S, D, R) (((S & R) | (~D & (S | R)))>>23)
+
+#define VFLAG_ADD_8(S, D, R) ((S^R) & (D^R))
+#define VFLAG_ADD_16(S, D, R) (((S^R) & (D^R))>>8)
+#define VFLAG_ADD_32(S, D, R) (((S^R) & (D^R))>>24)
+
+#define VFLAG_SUB_8(S, D, R) ((S^D) & (R^D))
+#define VFLAG_SUB_16(S, D, R) (((S^D) & (R^D))>>8)
+#define VFLAG_SUB_32(S, D, R) (((S^D) & (R^D))>>24)
+
+#define NFLAG_8(A) (A)
+#define NFLAG_16(A) ((A)>>8)
+#define NFLAG_32(A) ((A)>>24)
+#define NFLAG_64(A) ((A)>>56)
+
+#define ZFLAG_8(A) MASK_OUT_ABOVE_8(A)
+#define ZFLAG_16(A) MASK_OUT_ABOVE_16(A)
+#define ZFLAG_32(A) MASK_OUT_ABOVE_32(A)
+
+
+/* Flag values */
+#define NFLAG_SET 0x80
+#define NFLAG_CLEAR 0
+#define CFLAG_SET 0x100
+#define CFLAG_CLEAR 0
+#define XFLAG_SET 0x100
+#define XFLAG_CLEAR 0
+#define VFLAG_SET 0x80
+#define VFLAG_CLEAR 0
+#define ZFLAG_SET 0
+#define ZFLAG_CLEAR 0xffffffff
+
+#define SFLAG_SET 4
+#define SFLAG_CLEAR 0
+#define MFLAG_SET 2
+#define MFLAG_CLEAR 0
+
+/* Turn flag values into 1 or 0 */
+#define XFLAG_AS_1(M) (((M)->x_flag>>8)&1)
+#define NFLAG_AS_1(M) (((M)->n_flag>>7)&1)
+#define VFLAG_AS_1(M) (((M)->v_flag>>7)&1)
+#define ZFLAG_AS_1(M) (!(M)->not_z_flag)
+#define CFLAG_AS_1(M) (((M)->c_flag>>8)&1)
+
+
+/* Conditions */
+#define COND_CS(M) ((M)->c_flag&0x100)
+#define COND_CC(M) (!COND_CS(M))
+#define COND_VS(M) ((M)->v_flag&0x80)
+#define COND_VC(M) (!COND_VS(M))
+#define COND_NE(M) (M)->not_z_flag
+#define COND_EQ(M) (!COND_NE(M))
+#define COND_MI(M) ((M)->n_flag&0x80)
+#define COND_PL(M) (!COND_MI(M))
+#define COND_LT(M) (((M)->n_flag^(M)->v_flag)&0x80)
+#define COND_GE(M) (!COND_LT(M))
+#define COND_HI(M) (COND_CC(M) && COND_NE(M))
+#define COND_LS(M) (COND_CS(M) || COND_EQ(M))
+#define COND_GT(M) (COND_GE(M) && COND_NE(M))
+#define COND_LE(M) (COND_LT(M) || COND_EQ(M))
+
+/* Reversed conditions */
+#define COND_NOT_CS(M) COND_CC(M)
+#define COND_NOT_CC(M) COND_CS(M)
+#define COND_NOT_VS(M) COND_VC(M)
+#define COND_NOT_VC(M) COND_VS(M)
+#define COND_NOT_NE(M) COND_EQ(M)
+#define COND_NOT_EQ(M) COND_NE(M)
+#define COND_NOT_MI(M) COND_PL(M)
+#define COND_NOT_PL(M) COND_MI(M)
+#define COND_NOT_LT(M) COND_GE(M)
+#define COND_NOT_GE(M) COND_LT(M)
+#define COND_NOT_HI(M) COND_LS(M)
+#define COND_NOT_LS(M) COND_HI(M)
+#define COND_NOT_GT(M) COND_LE(M)
+#define COND_NOT_LE(M) COND_GT(M)
+
+/* Not real conditions, but here for convenience */
+#define COND_XS(M) ((M)->x_flag&0x100)
+#define COND_XC(M) (!COND_XS)
+
+
+/* Get the condition code register */
+#define m68ki_get_ccr(M) ((COND_XS(M) >> 4) | \
+ (COND_MI(M) >> 4) | \
+ (COND_EQ(M) << 2) | \
+ (COND_VS(M) >> 6) | \
+ (COND_CS(M) >> 8))
+
+/* Get the status register */
+#define m68ki_get_sr(M) ((M)->t1_flag | \
+ (M)->t0_flag | \
+ ((M)->s_flag << 11) | \
+ ((M)->m_flag << 11) | \
+ (M)->int_mask | \
+ m68ki_get_ccr(M))
+
+
+
+/* ----------------------------- Read / Write ----------------------------- */
+
+/* Read from the current address space */
+#define m68ki_read_8(M, A) m68ki_read_8_fc (M, A, m68k->s_flag | FUNCTION_CODE_USER_DATA)
+#define m68ki_read_16(M, A) m68ki_read_16_fc(M, A, m68k->s_flag | FUNCTION_CODE_USER_DATA)
+#define m68ki_read_32(M, A) m68ki_read_32_fc(M, A, m68k->s_flag | FUNCTION_CODE_USER_DATA)
+
+/* Write to the current data space */
+#define m68ki_write_8(M, A, V) m68ki_write_8_fc (M, A, m68k->s_flag | FUNCTION_CODE_USER_DATA, V)
+#define m68ki_write_16(M, A, V) m68ki_write_16_fc(M, A, m68k->s_flag | FUNCTION_CODE_USER_DATA, V)
+#define m68ki_write_32(M, A, V) m68ki_write_32_fc(M, A, m68k->s_flag | FUNCTION_CODE_USER_DATA, V)
+#define m68ki_write_32_pd(M, A, V) m68ki_write_32_pd_fc(M, A, m68k->s_flag | FUNCTION_CODE_USER_DATA, V)
+
+/* map read immediate 8 to read immediate 16 */
+#define m68ki_read_imm_8(M) MASK_OUT_ABOVE_8(m68ki_read_imm_16(M))
+
+/* Map PC-relative reads */
+#define m68ki_read_pcrel_8(M, A) m68k_read_pcrelative_8(M, A)
+#define m68ki_read_pcrel_16(M, A) m68k_read_pcrelative_16(M, A)
+#define m68ki_read_pcrel_32(M, A) m68k_read_pcrelative_32(M, A)
+
+/* Read from the program space */
+#define m68ki_read_program_8(M, A) m68ki_read_8_fc(M, A, m68k->s_flag | FUNCTION_CODE_USER_PROGRAM)
+#define m68ki_read_program_16(M, A) m68ki_read_16_fc(M, A, m68k->s_flag | FUNCTION_CODE_USER_PROGRAM)
+#define m68ki_read_program_32(M, A) m68ki_read_32_fc(M, A, m68k->s_flag | FUNCTION_CODE_USER_PROGRAM)
+
+/* Read from the data space */
+#define m68ki_read_data_8(M, A) m68ki_read_8_fc(M, A, m68k->s_flag | FUNCTION_CODE_USER_DATA)
+#define m68ki_read_data_16(M, A) m68ki_read_16_fc(M, A, m68k->s_flag | FUNCTION_CODE_USER_DATA)
+#define m68ki_read_data_32(M, A) m68ki_read_32_fc(M, A, m68k->s_flag | FUNCTION_CODE_USER_DATA)
+
+
+
+/* ======================================================================== */
+/* =============================== PROTOTYPES ============================= */
+/* ======================================================================== */
+
+typedef union _fp_reg fp_reg;
+union _fp_reg
+{
+ UINT64 i;
+ double f;
+};
+
+/* Redirect memory calls */
+
+typedef delegate<UINT8 (offs_t)> m68k_read8_delegate;
+typedef delegate<UINT16 (offs_t)> m68k_readimm16_delegate;
+typedef delegate<UINT16 (offs_t)> m68k_read16_delegate;
+typedef delegate<UINT32 (offs_t)> m68k_read32_delegate;
+typedef delegate<void (offs_t, UINT8)> m68k_write8_delegate;
+typedef delegate<void (offs_t, UINT16)> m68k_write16_delegate;
+typedef delegate<void (offs_t, UINT32)> m68k_write32_delegate;
+
+class m68k_memory_interface
+{
+public:
+ void init8(address_space &space);
+ void init16(address_space &space);
+ void init32(address_space &space);
+ void init32mmu(address_space &space);
+ void init32hmmu(address_space &space);
+
+ offs_t opcode_xor; // Address Calculation
+ m68k_readimm16_delegate readimm16; // Immediate read 16 bit
+ m68k_read8_delegate read8;
+ m68k_read16_delegate read16;
+ m68k_read32_delegate read32;
+ m68k_write8_delegate write8;
+ m68k_write16_delegate write16;
+ m68k_write32_delegate write32;
+
+private:
+ UINT16 m68008_read_immediate_16(offs_t address);
+ UINT16 read_immediate_16(offs_t address);
+ UINT16 simple_read_immediate_16(offs_t address);
+
+ UINT8 read_byte_32_mmu(offs_t address);
+ void write_byte_32_mmu(offs_t address, UINT8 data);
+ UINT16 read_immediate_16_mmu(offs_t address);
+ UINT16 readword_d32_mmu(offs_t address);
+ void writeword_d32_mmu(offs_t address, UINT16 data);
+ UINT32 readlong_d32_mmu(offs_t address);
+ void writelong_d32_mmu(offs_t address, UINT32 data);
+
+ UINT8 read_byte_32_hmmu(offs_t address);
+ void write_byte_32_hmmu(offs_t address, UINT8 data);
+ UINT16 read_immediate_16_hmmu(offs_t address);
+ UINT16 readword_d32_hmmu(offs_t address);
+ void writeword_d32_hmmu(offs_t address, UINT16 data);
+ UINT32 readlong_d32_hmmu(offs_t address);
+ void writelong_d32_hmmu(offs_t address, UINT32 data);
+
+ address_space *m_space;
+ direct_read_data *m_direct;
+ m68ki_cpu_core *m_cpustate;
+};
+
+struct _m68ki_cpu_core
+{
+ UINT32 cpu_type; /* CPU Type: 68000, 68008, 68010, 68EC020, 68020, 68EC030, 68030, 68EC040, or 68040 */
+ UINT32 dasm_type; /* disassembly type */
+ UINT32 dar[16]; /* Data and Address Registers */
+ UINT32 ppc; /* Previous program counter */
+ UINT32 pc; /* Program Counter */
+ UINT32 sp[7]; /* User, Interrupt, and Master Stack Pointers */
+ UINT32 vbr; /* Vector Base Register (m68010+) */
+ UINT32 sfc; /* Source Function Code Register (m68010+) */
+ UINT32 dfc; /* Destination Function Code Register (m68010+) */
+ UINT32 cacr; /* Cache Control Register (m68020, unemulated) */
+ UINT32 caar; /* Cache Address Register (m68020, unemulated) */
+ UINT32 ir; /* Instruction Register */
+ floatx80 fpr[8]; /* FPU Data Register (m68030/040) */
+ UINT32 fpiar; /* FPU Instruction Address Register (m68040) */
+ UINT32 fpsr; /* FPU Status Register (m68040) */
+ UINT32 fpcr; /* FPU Control Register (m68040) */
+ UINT32 t1_flag; /* Trace 1 */
+ UINT32 t0_flag; /* Trace 0 */
+ UINT32 s_flag; /* Supervisor */
+ UINT32 m_flag; /* Master/Interrupt state */
+ UINT32 x_flag; /* Extend */
+ UINT32 n_flag; /* Negative */
+ UINT32 not_z_flag; /* Zero, inverted for speedups */
+ UINT32 v_flag; /* Overflow */
+ UINT32 c_flag; /* Carry */
+ UINT32 int_mask; /* I0-I2 */
+ UINT32 int_level; /* State of interrupt pins IPL0-IPL2 -- ASG: changed from ints_pending */
+ UINT32 stopped; /* Stopped state */
+ UINT32 pref_addr; /* Last prefetch address */
+ UINT32 pref_data; /* Data in the prefetch queue */
+ UINT32 sr_mask; /* Implemented status register bits */
+ UINT32 instr_mode; /* Stores whether we are in instruction mode or group 0/1 exception mode */
+ UINT32 run_mode; /* Stores whether we are processing a reset, bus error, address error, or something else */
+ int has_pmmu; /* Indicates if a PMMU available (yes on 030, 040, no on EC030) */
+ int has_hmmu; /* Indicates if an Apple HMMU is available in place of the 68851 (020 only) */
+ int pmmu_enabled; /* Indicates if the PMMU is enabled */
+ int hmmu_enabled; /* Indicates if the HMMU is enabled */
+ int has_fpu; /* Indicates if a FPU is available (yes on 030, 040, may be on 020) */
+ int fpu_just_reset; /* Indicates the FPU was just reset */
+
+ /* Clocks required for instructions / exceptions */
+ UINT32 cyc_bcc_notake_b;
+ UINT32 cyc_bcc_notake_w;
+ UINT32 cyc_dbcc_f_noexp;
+ UINT32 cyc_dbcc_f_exp;
+ UINT32 cyc_scc_r_true;
+ UINT32 cyc_movem_w;
+ UINT32 cyc_movem_l;
+ UINT32 cyc_shift;
+ UINT32 cyc_reset;
+
+ int initial_cycles;
+ int remaining_cycles; /* Number of clocks remaining */
+ int reset_cycles;
+ UINT32 tracing;
+
+#ifdef _BSD_SETJMP_H
+ sigjmp_buf aerr_trap;
+#else
+ jmp_buf aerr_trap;
+#endif
+ UINT32 aerr_address;
+ UINT32 aerr_write_mode;
+ UINT32 aerr_fc;
+
+ /* Virtual IRQ lines state */
+ UINT32 virq_state;
+ UINT32 nmi_pending;
+
+ void (**jump_table)(m68ki_cpu_core *m68k);
+ const UINT8* cyc_instruction;
+ const UINT8* cyc_exception;
+
+ /* Callbacks to host */
+ device_irq_callback int_ack_callback; /* Interrupt Acknowledge */
+ m68k_bkpt_ack_func bkpt_ack_callback; /* Breakpoint Acknowledge */
+ m68k_reset_func reset_instr_callback; /* Called when a RESET instruction is encountered */
+ m68k_cmpild_func cmpild_instr_callback; /* Called when a CMPI.L #v, Dn instruction is encountered */
+ m68k_rte_func rte_instr_callback; /* Called when a RTE instruction is encountered */
+ m68k_tas_func tas_instr_callback; /* Called when a TAS instruction is encountered, allows / disallows writeback */
+
+ legacy_cpu_device *device;
+ address_space *program;
+ m68k_memory_interface memory;
+ offs_t encrypted_start;
+ offs_t encrypted_end;
+
+ UINT32 iotemp;
+
+ /* save state data */
+ UINT16 save_sr;
+ UINT8 save_stopped;
+ UINT8 save_halted;
+
+ /* PMMU registers */
+ UINT32 mmu_crp_aptr, mmu_crp_limit;
+ UINT32 mmu_srp_aptr, mmu_srp_limit;
+ UINT32 mmu_tc;
+ UINT16 mmu_sr;
+ UINT32 mmu_atc_tag[MMU_ATC_ENTRIES], mmu_atc_data[MMU_ATC_ENTRIES];
+ UINT32 mmu_atc_rr;
+ UINT32 mmu_tt0, mmu_tt1;
+
+ UINT16 mmu_tmp_sr; /* temporary hack: status code for ptest and to handle write protection */
+ UINT16 mmu_tmp_fc; /* temporary hack: function code for the mmu (moves) */
+ UINT16 mmu_tmp_rw; /* temporary hack: read/write (1/0) for the mmu */
+ UINT32 mmu_tmp_buserror_address; /* temporary hack: (first) bus error address */
+ UINT16 mmu_tmp_buserror_occurred; /* temporary hack: flag that bus error has occurred from mmu */
+
+ UINT32 ic_address[M68K_IC_SIZE]; /* instruction cache address data */
+ UINT16 ic_data[M68K_IC_SIZE]; /* instruction cache content data */
+
+ /* external instruction hook (does not depend on debug mode) */
+ typedef int (*instruction_hook_t)(device_t *device, offs_t curpc);
+ instruction_hook_t instruction_hook;
+};
+
+
+extern const UINT8 m68ki_shift_8_table[];
+extern const UINT16 m68ki_shift_16_table[];
+extern const UINT32 m68ki_shift_32_table[];
+extern const UINT8 m68ki_exception_cycle_table[][256];
+extern const UINT8 m68ki_ea_idx_cycle_table[];
+
+/* Read data immediately after the program counter */
+INLINE UINT32 m68ki_read_imm_16(m68ki_cpu_core *m68k);
+INLINE UINT32 m68ki_read_imm_32(m68ki_cpu_core *m68k);
+
+/* Read data with specific function code */
+INLINE UINT32 m68ki_read_8_fc (m68ki_cpu_core *m68k, UINT32 address, UINT32 fc);
+INLINE UINT32 m68ki_read_16_fc (m68ki_cpu_core *m68k, UINT32 address, UINT32 fc);
+INLINE UINT32 m68ki_read_32_fc (m68ki_cpu_core *m68k, UINT32 address, UINT32 fc);
+
+/* Write data with specific function code */
+INLINE void m68ki_write_8_fc (m68ki_cpu_core *m68k, UINT32 address, UINT32 fc, UINT32 value);
+INLINE void m68ki_write_16_fc(m68ki_cpu_core *m68k, UINT32 address, UINT32 fc, UINT32 value);
+INLINE void m68ki_write_32_fc(m68ki_cpu_core *m68k, UINT32 address, UINT32 fc, UINT32 value);
+INLINE void m68ki_write_32_pd_fc(m68ki_cpu_core *m68k, UINT32 address, UINT32 fc, UINT32 value);
+
+/* Indexed and PC-relative ea fetching */
+INLINE UINT32 m68ki_get_ea_pcdi(m68ki_cpu_core *m68k);
+INLINE UINT32 m68ki_get_ea_pcix(m68ki_cpu_core *m68k);
+INLINE UINT32 m68ki_get_ea_ix(m68ki_cpu_core *m68k, UINT32 An);
+
+/* Operand fetching */
+INLINE UINT32 OPER_AY_AI_8(m68ki_cpu_core *m68k);
+INLINE UINT32 OPER_AY_AI_16(m68ki_cpu_core *m68k);
+INLINE UINT32 OPER_AY_AI_32(m68ki_cpu_core *m68k);
+INLINE UINT32 OPER_AY_PI_8(m68ki_cpu_core *m68k);
+INLINE UINT32 OPER_AY_PI_16(m68ki_cpu_core *m68k);
+INLINE UINT32 OPER_AY_PI_32(m68ki_cpu_core *m68k);
+INLINE UINT32 OPER_AY_PD_8(m68ki_cpu_core *m68k);
+INLINE UINT32 OPER_AY_PD_16(m68ki_cpu_core *m68k);
+INLINE UINT32 OPER_AY_PD_32(m68ki_cpu_core *m68k);
+INLINE UINT32 OPER_AY_DI_8(m68ki_cpu_core *m68k);
+INLINE UINT32 OPER_AY_DI_16(m68ki_cpu_core *m68k);
+INLINE UINT32 OPER_AY_DI_32(m68ki_cpu_core *m68k);
+INLINE UINT32 OPER_AY_IX_8(m68ki_cpu_core *m68k);
+INLINE UINT32 OPER_AY_IX_16(m68ki_cpu_core *m68k);
+INLINE UINT32 OPER_AY_IX_32(m68ki_cpu_core *m68k);
+
+INLINE UINT32 OPER_AX_AI_8(m68ki_cpu_core *m68k);
+INLINE UINT32 OPER_AX_AI_16(m68ki_cpu_core *m68k);
+INLINE UINT32 OPER_AX_AI_32(m68ki_cpu_core *m68k);
+INLINE UINT32 OPER_AX_PI_8(m68ki_cpu_core *m68k);
+INLINE UINT32 OPER_AX_PI_16(m68ki_cpu_core *m68k);
+INLINE UINT32 OPER_AX_PI_32(m68ki_cpu_core *m68k);
+INLINE UINT32 OPER_AX_PD_8(m68ki_cpu_core *m68k);
+INLINE UINT32 OPER_AX_PD_16(m68ki_cpu_core *m68k);
+INLINE UINT32 OPER_AX_PD_32(m68ki_cpu_core *m68k);
+INLINE UINT32 OPER_AX_DI_8(m68ki_cpu_core *m68k);
+INLINE UINT32 OPER_AX_DI_16(m68ki_cpu_core *m68k);
+INLINE UINT32 OPER_AX_DI_32(m68ki_cpu_core *m68k);
+INLINE UINT32 OPER_AX_IX_8(m68ki_cpu_core *m68k);
+INLINE UINT32 OPER_AX_IX_16(m68ki_cpu_core *m68k);
+INLINE UINT32 OPER_AX_IX_32(m68ki_cpu_core *m68k);
+
+INLINE UINT32 OPER_A7_PI_8(m68ki_cpu_core *m68k);
+INLINE UINT32 OPER_A7_PD_8(m68ki_cpu_core *m68k);
+
+INLINE UINT32 OPER_AW_8(m68ki_cpu_core *m68k);
+INLINE UINT32 OPER_AW_16(m68ki_cpu_core *m68k);
+INLINE UINT32 OPER_AW_32(m68ki_cpu_core *m68k);
+INLINE UINT32 OPER_AL_8(m68ki_cpu_core *m68k);
+INLINE UINT32 OPER_AL_16(m68ki_cpu_core *m68k);
+INLINE UINT32 OPER_AL_32(m68ki_cpu_core *m68k);
+INLINE UINT32 OPER_PCDI_8(m68ki_cpu_core *m68k);
+INLINE UINT32 OPER_PCDI_16(m68ki_cpu_core *m68k);
+INLINE UINT32 OPER_PCDI_32(m68ki_cpu_core *m68k);
+INLINE UINT32 OPER_PCIX_8(m68ki_cpu_core *m68k);
+INLINE UINT32 OPER_PCIX_16(m68ki_cpu_core *m68k);
+INLINE UINT32 OPER_PCIX_32(m68ki_cpu_core *m68k);
+
+/* Stack operations */
+INLINE void m68ki_push_16(m68ki_cpu_core *m68k, UINT32 value);
+INLINE void m68ki_push_32(m68ki_cpu_core *m68k, UINT32 value);
+INLINE UINT32 m68ki_pull_16(m68ki_cpu_core *m68k);
+INLINE UINT32 m68ki_pull_32(m68ki_cpu_core *m68k);
+
+/* Program flow operations */
+INLINE void m68ki_jump(m68ki_cpu_core *m68k, UINT32 new_pc);
+INLINE void m68ki_jump_vector(m68ki_cpu_core *m68k, UINT32 vector);
+INLINE void m68ki_branch_8(m68ki_cpu_core *m68k, UINT32 offset);
+INLINE void m68ki_branch_16(m68ki_cpu_core *m68k, UINT32 offset);
+INLINE void m68ki_branch_32(m68ki_cpu_core *m68k, UINT32 offset);
+
+/* Status register operations. */
+INLINE void m68ki_set_s_flag(m68ki_cpu_core *m68k, UINT32 value); /* Only bit 2 of value should be set (i.e. 4 or 0) */
+INLINE void m68ki_set_sm_flag(m68ki_cpu_core *m68k, UINT32 value); /* only bits 1 and 2 of value should be set */
+INLINE void m68ki_set_ccr(m68ki_cpu_core *m68k, UINT32 value); /* set the condition code register */
+INLINE void m68ki_set_sr(m68ki_cpu_core *m68k, UINT32 value); /* set the status register */
+INLINE void m68ki_set_sr_noint(m68ki_cpu_core *m68k, UINT32 value); /* set the status register */
+
+/* Exception processing */
+INLINE UINT32 m68ki_init_exception(m68ki_cpu_core *m68k); /* Initial exception processing */
+
+INLINE void m68ki_stack_frame_3word(m68ki_cpu_core *m68k, UINT32 pc, UINT32 sr); /* Stack various frame types */
+INLINE void m68ki_stack_frame_buserr(m68ki_cpu_core *m68k, UINT32 sr);
+
+INLINE void m68ki_stack_frame_0000(m68ki_cpu_core *m68k, UINT32 pc, UINT32 sr, UINT32 vector);
+INLINE void m68ki_stack_frame_0001(m68ki_cpu_core *m68k, UINT32 pc, UINT32 sr, UINT32 vector);
+INLINE void m68ki_stack_frame_0010(m68ki_cpu_core *m68k, UINT32 sr, UINT32 vector);
+INLINE void m68ki_stack_frame_1000(m68ki_cpu_core *m68k, UINT32 pc, UINT32 sr, UINT32 vector);
+INLINE void m68ki_stack_frame_1010(m68ki_cpu_core *m68k, UINT32 sr, UINT32 vector, UINT32 pc, UINT32 fault_address);
+INLINE void m68ki_stack_frame_1011(m68ki_cpu_core *m68k, UINT32 sr, UINT32 vector, UINT32 pc, UINT32 fault_address);
+
+INLINE void m68ki_exception_trap(m68ki_cpu_core *m68k, UINT32 vector);
+INLINE void m68ki_exception_trapN(m68ki_cpu_core *m68k, UINT32 vector);
+INLINE void m68ki_exception_trace(m68ki_cpu_core *m68k);
+INLINE void m68ki_exception_privilege_violation(m68ki_cpu_core *m68k);
+INLINE void m68ki_exception_1010(m68ki_cpu_core *m68k);
+INLINE void m68ki_exception_1111(m68ki_cpu_core *m68k);
+INLINE void m68ki_exception_illegal(m68ki_cpu_core *m68k);
+INLINE void m68ki_exception_format_error(m68ki_cpu_core *m68k);
+INLINE void m68ki_exception_address_error(m68ki_cpu_core *m68k);
+INLINE void m68ki_exception_interrupt(m68ki_cpu_core *m68k, UINT32 int_level);
+INLINE void m68ki_check_interrupts(m68ki_cpu_core *m68k); /* ASG: check for interrupts */
+
+/* quick disassembly (used for logging) */
+char* m68ki_disassemble_quick(unsigned int pc, unsigned int cpu_type);
+
+
+/* ======================================================================== */
+/* =========================== UTILITY FUNCTIONS ========================== */
+/* ======================================================================== */
+
+
+INLINE unsigned int m68k_read_immediate_32(m68ki_cpu_core *m68k, unsigned int address)
+{
+ return (m68k->memory.readimm16(address) << 16) | m68k->memory.readimm16(address + 2);
+}
+
+INLINE unsigned int m68k_read_pcrelative_8(m68ki_cpu_core *m68k, unsigned int address)
+{
+ if (address >= m68k->encrypted_start && address < m68k->encrypted_end)
+ return ((m68k->memory.readimm16(address&~1)>>(8*(1-(address & 1))))&0xff);
+
+ return m68k->memory.read8(address);
+}
+
+INLINE unsigned int m68k_read_pcrelative_16(m68ki_cpu_core *m68k, unsigned int address)
+{
+ if (address >= m68k->encrypted_start && address < m68k->encrypted_end)
+ return m68k->memory.readimm16(address);
+
+ return m68k->memory.read16(address);
+}
+
+INLINE unsigned int m68k_read_pcrelative_32(m68ki_cpu_core *m68k, unsigned int address)
+{
+ if (address >= m68k->encrypted_start && address < m68k->encrypted_end)
+ return m68k_read_immediate_32(m68k, address);
+
+ return m68k->memory.read32(address);
+}
+
+
+/* Special call to simulate undocumented 68k behavior when move.l with a
+ * predecrement destination mode is executed.
+ * A real 68k first writes the high word to [address+2], and then writes the
+ * low word to [address].
+ */
+INLINE void m68kx_write_memory_32_pd(m68ki_cpu_core *m68k, unsigned int address, unsigned int value)
+{
+ m68k->memory.write16(address+2, value>>16);
+ m68k->memory.write16(address, value&0xffff);
+}
+
+
+/* ---------------------------- Read Immediate ---------------------------- */
+
+// clear the instruction cache
+INLINE void m68ki_ic_clear(m68ki_cpu_core *m68k)
+{
+ int i;
+ for (i=0; i< M68K_IC_SIZE; i++) {
+ m68k->ic_address[i] = ~0;
+ }
+}
+
+// read immediate word using the instruction cache
+
+INLINE UINT32 m68ki_ic_readimm16(m68ki_cpu_core *m68k, UINT32 address)
+{
+/* if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type) && (m68k->cacr & M68K_CACR_EI))
+ {
+ UINT32 ic_offset = (address >> 1) % M68K_IC_SIZE;
+ if (m68k->ic_address[ic_offset] == address)
+ {
+ return m68k->ic_data[ic_offset];
+ }
+ else
+ {
+ UINT32 data = m68k->memory.readimm16(address);
+ if (!m68k->mmu_tmp_buserror_occurred)
+ {
+ m68k->ic_data[ic_offset] = data;
+ m68k->ic_address[ic_offset] = address;
+ }
+ return data;
+ }
+ }
+ else*/
+ {
+ return m68k->memory.readimm16(address);
+ }
+
+ // this can't happen, but Apple GCC insists
+// return 0;
+}
+
+/* Handles all immediate reads, does address error check, function code setting,
+ * and prefetching if they are enabled in m68kconf.h
+ */
+INLINE UINT32 m68ki_read_imm_16(m68ki_cpu_core *m68k)
+{
+ UINT32 result;
+
+ m68k->mmu_tmp_fc = m68k->s_flag | FUNCTION_CODE_USER_PROGRAM;
+ m68k->mmu_tmp_rw = 1;
+
+ m68ki_check_address_error(m68k, REG_PC, MODE_READ, m68k->s_flag | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */
+
+ if(REG_PC != m68k->pref_addr)
+ {
+ m68k->pref_data = m68ki_ic_readimm16(m68k, REG_PC);
+ m68k->pref_addr = m68k->mmu_tmp_buserror_occurred ? ~0 : REG_PC;
+ }
+ result = MASK_OUT_ABOVE_16(m68k->pref_data);
+ REG_PC += 2;
+ if (!m68k->mmu_tmp_buserror_occurred) {
+ // prefetch only if no bus error occurred in opcode fetch
+ m68k->pref_data = m68ki_ic_readimm16(m68k, REG_PC);
+ m68k->pref_addr = m68k->mmu_tmp_buserror_occurred ? ~0 : REG_PC;
+ // ignore bus error on prefetch
+ m68k->mmu_tmp_buserror_occurred = 0;
+ }
+
+ return result;
+}
+
+INLINE UINT32 m68ki_read_imm_32(m68ki_cpu_core *m68k)
+{
+ UINT32 temp_val;
+
+ m68k->mmu_tmp_fc = m68k->s_flag | FUNCTION_CODE_USER_PROGRAM;
+ m68k->mmu_tmp_rw = 1;
+
+ m68ki_check_address_error(m68k, REG_PC, MODE_READ, m68k->s_flag | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */
+
+ if(REG_PC != m68k->pref_addr)
+ {
+ m68k->pref_addr = REG_PC;
+ m68k->pref_data = m68ki_ic_readimm16(m68k, m68k->pref_addr);
+ }
+ temp_val = MASK_OUT_ABOVE_16(m68k->pref_data);
+ REG_PC += 2;
+ m68k->pref_addr = REG_PC;
+ m68k->pref_data = m68ki_ic_readimm16(m68k, m68k->pref_addr);
+
+ temp_val = MASK_OUT_ABOVE_32((temp_val << 16) | MASK_OUT_ABOVE_16(m68k->pref_data));
+ REG_PC += 2;
+ m68k->pref_data = m68ki_ic_readimm16(m68k, REG_PC);
+ m68k->pref_addr = m68k->mmu_tmp_buserror_occurred ? ~0 : REG_PC;
+
+ return temp_val;
+}
+
+
+
+/* ------------------------- Top level read/write ------------------------- */
+
+/* Handles all memory accesses (except for immediate reads if they are
+ * configured to use separate functions in m68kconf.h).
+ * All memory accesses must go through these top level functions.
+ * These functions will also check for address error and set the function
+ * code if they are enabled in m68kconf.h.
+ */
+INLINE UINT32 m68ki_read_8_fc(m68ki_cpu_core *m68k, UINT32 address, UINT32 fc)
+{
+ m68k->mmu_tmp_fc = fc;
+ m68k->mmu_tmp_rw = 1;
+ return m68k->memory.read8(address);
+}
+INLINE UINT32 m68ki_read_16_fc(m68ki_cpu_core *m68k, UINT32 address, UINT32 fc)
+{
+ if (CPU_TYPE_IS_010_LESS(m68k->cpu_type))
+ {
+ m68ki_check_address_error(m68k, address, MODE_READ, fc);
+ }
+ m68k->mmu_tmp_fc = fc;
+ m68k->mmu_tmp_rw = 1;
+ return m68k->memory.read16(address);
+}
+INLINE UINT32 m68ki_read_32_fc(m68ki_cpu_core *m68k, UINT32 address, UINT32 fc)
+{
+ if (CPU_TYPE_IS_010_LESS(m68k->cpu_type))
+ {
+ m68ki_check_address_error(m68k, address, MODE_READ, fc);
+ }
+ m68k->mmu_tmp_fc = fc;
+ m68k->mmu_tmp_rw = 1;
+ return m68k->memory.read32(address);
+}
+
+INLINE void m68ki_write_8_fc(m68ki_cpu_core *m68k, UINT32 address, UINT32 fc, UINT32 value)
+{
+ m68k->mmu_tmp_fc = fc;
+ m68k->mmu_tmp_rw = 0;
+ m68k->memory.write8(address, value);
+}
+INLINE void m68ki_write_16_fc(m68ki_cpu_core *m68k, UINT32 address, UINT32 fc, UINT32 value)
+{
+ if (CPU_TYPE_IS_010_LESS(m68k->cpu_type))
+ {
+ m68ki_check_address_error(m68k, address, MODE_WRITE, fc);
+ }
+ m68k->mmu_tmp_fc = fc;
+ m68k->mmu_tmp_rw = 0;
+ m68k->memory.write16(address, value);
+}
+INLINE void m68ki_write_32_fc(m68ki_cpu_core *m68k, UINT32 address, UINT32 fc, UINT32 value)
+{
+ if (CPU_TYPE_IS_010_LESS(m68k->cpu_type))
+ {
+ m68ki_check_address_error(m68k, address, MODE_WRITE, fc);
+ }
+ m68k->mmu_tmp_fc = fc;
+ m68k->mmu_tmp_rw = 0;
+ m68k->memory.write32(address, value);
+}
+
+/* Special call to simulate undocumented 68k behavior when move.l with a
+ * predecrement destination mode is executed.
+ * A real 68k first writes the high word to [address+2], and then writes the
+ * low word to [address].
+ */
+INLINE void m68ki_write_32_pd_fc(m68ki_cpu_core *m68k, UINT32 address, UINT32 fc, UINT32 value)
+{
+ if (CPU_TYPE_IS_010_LESS(m68k->cpu_type))
+ {
+ m68ki_check_address_error(m68k, address, MODE_WRITE, fc);
+ }
+ m68k->mmu_tmp_fc = fc;
+ m68k->mmu_tmp_rw = 0;
+ m68k->memory.write16(address+2, value>>16);
+ m68k->memory.write16(address, value&0xffff);
+}
+
+
+/* --------------------- Effective Address Calculation -------------------- */
+
+/* The program counter relative addressing modes cause operands to be
+ * retrieved from program space, not data space.
+ */
+INLINE UINT32 m68ki_get_ea_pcdi(m68ki_cpu_core *m68k)
+{
+ UINT32 old_pc = REG_PC;
+ return old_pc + MAKE_INT_16(m68ki_read_imm_16(m68k));
+}
+
+
+INLINE UINT32 m68ki_get_ea_pcix(m68ki_cpu_core *m68k)
+{
+ return m68ki_get_ea_ix(m68k, REG_PC);
+}
+
+/* Indexed addressing modes are encoded as follows:
+ *
+ * Base instruction format:
+ * F E D C B A 9 8 7 6 | 5 4 3 | 2 1 0
+ * x x x x x x x x x x | 1 1 0 | BASE REGISTER (An)
+ *
+ * Base instruction format for destination EA in move instructions:
+ * F E D C | B A 9 | 8 7 6 | 5 4 3 2 1 0
+ * x x x x | BASE REG | 1 1 0 | X X X X X X (An)
+ *
+ * Brief extension format:
+ * F | E D C | B | A 9 | 8 | 7 6 5 4 3 2 1 0
+ * D/A | REGISTER | W/L | SCALE | 0 | DISPLACEMENT
+ *
+ * Full extension format:
+ * F E D C B A 9 8 7 6 5 4 3 2 1 0
+ * D/A | REGISTER | W/L | SCALE | 1 | BS | IS | BD SIZE | 0 | I/IS
+ * BASE DISPLACEMENT (0, 16, 32 bit) (bd)
+ * OUTER DISPLACEMENT (0, 16, 32 bit) (od)
+ *
+ * D/A: 0 = Dn, 1 = An (Xn)
+ * W/L: 0 = W (sign extend), 1 = L (.SIZE)
+ * SCALE: 00=1, 01=2, 10=4, 11=8 (*SCALE)
+ * BS: 0=add base reg, 1=suppress base reg (An suppressed)
+ * IS: 0=add index, 1=suppress index (Xn suppressed)
+ * BD SIZE: 00=reserved, 01=NULL, 10=Word, 11=Long (size of bd)
+ *
+ * IS I/IS Operation
+ * 0 000 No Memory Indirect
+ * 0 001 indir prex with null outer
+ * 0 010 indir prex with word outer
+ * 0 011 indir prex with long outer
+ * 0 100 reserved
+ * 0 101 indir postx with null outer
+ * 0 110 indir postx with word outer
+ * 0 111 indir postx with long outer
+ * 1 000 no memory indirect
+ * 1 001 mem indir with null outer
+ * 1 010 mem indir with word outer
+ * 1 011 mem indir with long outer
+ * 1 100-111 reserved
+ */
+INLINE UINT32 m68ki_get_ea_ix(m68ki_cpu_core *m68k, UINT32 An)
+{
+ /* An = base register */
+ UINT32 extension = m68ki_read_imm_16(m68k);
+ UINT32 Xn = 0; /* Index register */
+ UINT32 bd = 0; /* Base Displacement */
+ UINT32 od = 0; /* Outer Displacement */
+
+ if(CPU_TYPE_IS_010_LESS(m68k->cpu_type))
+ {
+ /* Calculate index */
+ Xn = REG_DA[extension>>12]; /* Xn */
+ if(!BIT_B(extension)) /* W/L */
+ Xn = MAKE_INT_16(Xn);
+
+ /* Add base register and displacement and return */
+ return An + Xn + MAKE_INT_8(extension);
+ }
+
+ /* Brief extension format */
+ if(!BIT_8(extension))
+ {
+ /* Calculate index */
+ Xn = REG_DA[extension>>12]; /* Xn */
+ if(!BIT_B(extension)) /* W/L */
+ Xn = MAKE_INT_16(Xn);
+ /* Add scale if proper CPU type */
+ if(CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ Xn <<= (extension>>9) & 3; /* SCALE */
+
+ /* Add base register and displacement and return */
+ return An + Xn + MAKE_INT_8(extension);
+ }
+
+ /* Full extension format */
+
+ m68k->remaining_cycles -= m68ki_ea_idx_cycle_table[extension&0x3f];
+
+ /* Check if base register is present */
+ if(BIT_7(extension)) /* BS */
+ An = 0; /* An */
+
+ /* Check if index is present */
+ if(!BIT_6(extension)) /* IS */
+ {
+ Xn = REG_DA[extension>>12]; /* Xn */
+ if(!BIT_B(extension)) /* W/L */
+ Xn = MAKE_INT_16(Xn);
+ Xn <<= (extension>>9) & 3; /* SCALE */
+ }
+
+ /* Check if base displacement is present */
+ if(BIT_5(extension)) /* BD SIZE */
+ bd = BIT_4(extension) ? m68ki_read_imm_32(m68k) : MAKE_INT_16(m68ki_read_imm_16(m68k));
+
+ /* If no indirect action, we are done */
+ if(!(extension&7)) /* No Memory Indirect */
+ return An + bd + Xn;
+
+ /* Check if outer displacement is present */
+ if(BIT_1(extension)) /* I/IS: od */
+ od = BIT_0(extension) ? m68ki_read_imm_32(m68k) : MAKE_INT_16(m68ki_read_imm_16(m68k));
+
+ /* Postindex */
+ if(BIT_2(extension)) /* I/IS: 0 = preindex, 1 = postindex */
+ return m68ki_read_32(m68k, An + bd) + Xn + od;
+
+ /* Preindex */
+ return m68ki_read_32(m68k, An + bd + Xn) + od;
+}
+
+
+/* Fetch operands */
+INLINE UINT32 OPER_AY_AI_8(m68ki_cpu_core *m68k) {UINT32 ea = EA_AY_AI_8(m68k); return m68ki_read_8(m68k, ea); }
+INLINE UINT32 OPER_AY_AI_16(m68ki_cpu_core *m68k) {UINT32 ea = EA_AY_AI_16(m68k); return m68ki_read_16(m68k, ea);}
+INLINE UINT32 OPER_AY_AI_32(m68ki_cpu_core *m68k) {UINT32 ea = EA_AY_AI_32(m68k); return m68ki_read_32(m68k, ea);}
+INLINE UINT32 OPER_AY_PI_8(m68ki_cpu_core *m68k) {UINT32 ea = EA_AY_PI_8(m68k); return m68ki_read_8(m68k, ea); }
+INLINE UINT32 OPER_AY_PI_16(m68ki_cpu_core *m68k) {UINT32 ea = EA_AY_PI_16(m68k); return m68ki_read_16(m68k, ea);}
+INLINE UINT32 OPER_AY_PI_32(m68ki_cpu_core *m68k) {UINT32 ea = EA_AY_PI_32(m68k); return m68ki_read_32(m68k, ea);}
+INLINE UINT32 OPER_AY_PD_8(m68ki_cpu_core *m68k) {UINT32 ea = EA_AY_PD_8(m68k); return m68ki_read_8(m68k, ea); }
+INLINE UINT32 OPER_AY_PD_16(m68ki_cpu_core *m68k) {UINT32 ea = EA_AY_PD_16(m68k); return m68ki_read_16(m68k, ea);}
+INLINE UINT32 OPER_AY_PD_32(m68ki_cpu_core *m68k) {UINT32 ea = EA_AY_PD_32(m68k); return m68ki_read_32(m68k, ea);}
+INLINE UINT32 OPER_AY_DI_8(m68ki_cpu_core *m68k) {UINT32 ea = EA_AY_DI_8(m68k); return m68ki_read_8(m68k, ea); }
+INLINE UINT32 OPER_AY_DI_16(m68ki_cpu_core *m68k) {UINT32 ea = EA_AY_DI_16(m68k); return m68ki_read_16(m68k, ea);}
+INLINE UINT32 OPER_AY_DI_32(m68ki_cpu_core *m68k) {UINT32 ea = EA_AY_DI_32(m68k); return m68ki_read_32(m68k, ea);}
+INLINE UINT32 OPER_AY_IX_8(m68ki_cpu_core *m68k) {UINT32 ea = EA_AY_IX_8(m68k); return m68ki_read_8(m68k, ea); }
+INLINE UINT32 OPER_AY_IX_16(m68ki_cpu_core *m68k) {UINT32 ea = EA_AY_IX_16(m68k); return m68ki_read_16(m68k, ea);}
+INLINE UINT32 OPER_AY_IX_32(m68ki_cpu_core *m68k) {UINT32 ea = EA_AY_IX_32(m68k); return m68ki_read_32(m68k, ea);}
+
+INLINE UINT32 OPER_AX_AI_8(m68ki_cpu_core *m68k) {UINT32 ea = EA_AX_AI_8(m68k); return m68ki_read_8(m68k, ea); }
+INLINE UINT32 OPER_AX_AI_16(m68ki_cpu_core *m68k) {UINT32 ea = EA_AX_AI_16(m68k); return m68ki_read_16(m68k, ea);}
+INLINE UINT32 OPER_AX_AI_32(m68ki_cpu_core *m68k) {UINT32 ea = EA_AX_AI_32(m68k); return m68ki_read_32(m68k, ea);}
+INLINE UINT32 OPER_AX_PI_8(m68ki_cpu_core *m68k) {UINT32 ea = EA_AX_PI_8(m68k); return m68ki_read_8(m68k, ea); }
+INLINE UINT32 OPER_AX_PI_16(m68ki_cpu_core *m68k) {UINT32 ea = EA_AX_PI_16(m68k); return m68ki_read_16(m68k, ea);}
+INLINE UINT32 OPER_AX_PI_32(m68ki_cpu_core *m68k) {UINT32 ea = EA_AX_PI_32(m68k); return m68ki_read_32(m68k, ea);}
+INLINE UINT32 OPER_AX_PD_8(m68ki_cpu_core *m68k) {UINT32 ea = EA_AX_PD_8(m68k); return m68ki_read_8(m68k, ea); }
+INLINE UINT32 OPER_AX_PD_16(m68ki_cpu_core *m68k) {UINT32 ea = EA_AX_PD_16(m68k); return m68ki_read_16(m68k, ea);}
+INLINE UINT32 OPER_AX_PD_32(m68ki_cpu_core *m68k) {UINT32 ea = EA_AX_PD_32(m68k); return m68ki_read_32(m68k, ea);}
+INLINE UINT32 OPER_AX_DI_8(m68ki_cpu_core *m68k) {UINT32 ea = EA_AX_DI_8(m68k); return m68ki_read_8(m68k, ea); }
+INLINE UINT32 OPER_AX_DI_16(m68ki_cpu_core *m68k) {UINT32 ea = EA_AX_DI_16(m68k); return m68ki_read_16(m68k, ea);}
+INLINE UINT32 OPER_AX_DI_32(m68ki_cpu_core *m68k) {UINT32 ea = EA_AX_DI_32(m68k); return m68ki_read_32(m68k, ea);}
+INLINE UINT32 OPER_AX_IX_8(m68ki_cpu_core *m68k) {UINT32 ea = EA_AX_IX_8(m68k); return m68ki_read_8(m68k, ea); }
+INLINE UINT32 OPER_AX_IX_16(m68ki_cpu_core *m68k) {UINT32 ea = EA_AX_IX_16(m68k); return m68ki_read_16(m68k, ea);}
+INLINE UINT32 OPER_AX_IX_32(m68ki_cpu_core *m68k) {UINT32 ea = EA_AX_IX_32(m68k); return m68ki_read_32(m68k, ea);}
+
+INLINE UINT32 OPER_A7_PI_8(m68ki_cpu_core *m68k) {UINT32 ea = EA_A7_PI_8(m68k); return m68ki_read_8(m68k, ea); }
+INLINE UINT32 OPER_A7_PD_8(m68ki_cpu_core *m68k) {UINT32 ea = EA_A7_PD_8(m68k); return m68ki_read_8(m68k, ea); }
+
+INLINE UINT32 OPER_AW_8(m68ki_cpu_core *m68k) {UINT32 ea = EA_AW_8(m68k); return m68ki_read_8(m68k, ea); }
+INLINE UINT32 OPER_AW_16(m68ki_cpu_core *m68k) {UINT32 ea = EA_AW_16(m68k); return m68ki_read_16(m68k, ea);}
+INLINE UINT32 OPER_AW_32(m68ki_cpu_core *m68k) {UINT32 ea = EA_AW_32(m68k); return m68ki_read_32(m68k, ea);}
+INLINE UINT32 OPER_AL_8(m68ki_cpu_core *m68k) {UINT32 ea = EA_AL_8(m68k); return m68ki_read_8(m68k, ea); }
+INLINE UINT32 OPER_AL_16(m68ki_cpu_core *m68k) {UINT32 ea = EA_AL_16(m68k); return m68ki_read_16(m68k, ea);}
+INLINE UINT32 OPER_AL_32(m68ki_cpu_core *m68k) {UINT32 ea = EA_AL_32(m68k); return m68ki_read_32(m68k, ea);}
+INLINE UINT32 OPER_PCDI_8(m68ki_cpu_core *m68k) {UINT32 ea = EA_PCDI_8(m68k); return m68ki_read_pcrel_8(m68k, ea); }
+INLINE UINT32 OPER_PCDI_16(m68ki_cpu_core *m68k) {UINT32 ea = EA_PCDI_16(m68k); return m68ki_read_pcrel_16(m68k, ea);}
+INLINE UINT32 OPER_PCDI_32(m68ki_cpu_core *m68k) {UINT32 ea = EA_PCDI_32(m68k); return m68ki_read_pcrel_32(m68k, ea);}
+INLINE UINT32 OPER_PCIX_8(m68ki_cpu_core *m68k) {UINT32 ea = EA_PCIX_8(m68k); return m68ki_read_pcrel_8(m68k, ea); }
+INLINE UINT32 OPER_PCIX_16(m68ki_cpu_core *m68k) {UINT32 ea = EA_PCIX_16(m68k); return m68ki_read_pcrel_16(m68k, ea);}
+INLINE UINT32 OPER_PCIX_32(m68ki_cpu_core *m68k) {UINT32 ea = EA_PCIX_32(m68k); return m68ki_read_pcrel_32(m68k, ea);}
+
+
+
+/* ---------------------------- Stack Functions --------------------------- */
+
+/* Push/pull data from the stack */
+INLINE void m68ki_push_16(m68ki_cpu_core *m68k, UINT32 value)
+{
+ REG_SP = MASK_OUT_ABOVE_32(REG_SP - 2);
+ m68ki_write_16(m68k, REG_SP, value);
+}
+
+INLINE void m68ki_push_32(m68ki_cpu_core *m68k, UINT32 value)
+{
+ REG_SP = MASK_OUT_ABOVE_32(REG_SP - 4);
+ m68ki_write_32(m68k, REG_SP, value);
+}
+
+INLINE UINT32 m68ki_pull_16(m68ki_cpu_core *m68k)
+{
+ REG_SP = MASK_OUT_ABOVE_32(REG_SP + 2);
+ return m68ki_read_16(m68k, REG_SP-2);
+}
+
+INLINE UINT32 m68ki_pull_32(m68ki_cpu_core *m68k)
+{
+ REG_SP = MASK_OUT_ABOVE_32(REG_SP + 4);
+ return m68ki_read_32(m68k, REG_SP-4);
+}
+
+
+/* Increment/decrement the stack as if doing a push/pull but
+ * don't do any memory access.
+ */
+INLINE void m68ki_fake_push_16(m68ki_cpu_core *m68k)
+{
+ REG_SP = MASK_OUT_ABOVE_32(REG_SP - 2);
+}
+
+INLINE void m68ki_fake_push_32(m68ki_cpu_core *m68k)
+{
+ REG_SP = MASK_OUT_ABOVE_32(REG_SP - 4);
+}
+
+INLINE void m68ki_fake_pull_16(m68ki_cpu_core *m68k)
+{
+ REG_SP = MASK_OUT_ABOVE_32(REG_SP + 2);
+}
+
+INLINE void m68ki_fake_pull_32(m68ki_cpu_core *m68k)
+{
+ REG_SP = MASK_OUT_ABOVE_32(REG_SP + 4);
+}
+
+
+/* ----------------------------- Program Flow ----------------------------- */
+
+/* Jump to a new program location or vector.
+ * These functions will also call the pc_changed callback if it was enabled
+ * in m68kconf.h.
+ */
+INLINE void m68ki_jump(m68ki_cpu_core *m68k, UINT32 new_pc)
+{
+ REG_PC = new_pc;
+}
+
+INLINE void m68ki_jump_vector(m68ki_cpu_core *m68k, UINT32 vector)
+{
+ REG_PC = (vector<<2) + m68k->vbr;
+ REG_PC = m68ki_read_data_32(m68k, REG_PC);
+}
+
+
+/* Branch to a new memory location.
+ * The 32-bit branch will call pc_changed if it was enabled in m68kconf.h.
+ * So far I've found no problems with not calling pc_changed for 8 or 16
+ * bit branches.
+ */
+INLINE void m68ki_branch_8(m68ki_cpu_core *m68k, UINT32 offset)
+{
+ REG_PC += MAKE_INT_8(offset);
+}
+
+INLINE void m68ki_branch_16(m68ki_cpu_core *m68k, UINT32 offset)
+{
+ REG_PC += MAKE_INT_16(offset);
+}
+
+INLINE void m68ki_branch_32(m68ki_cpu_core *m68k, UINT32 offset)
+{
+ REG_PC += offset;
+}
+
+
+
+/* ---------------------------- Status Register --------------------------- */
+
+/* Set the S flag and change the active stack pointer.
+ * Note that value MUST be 4 or 0.
+ */
+INLINE void m68ki_set_s_flag(m68ki_cpu_core *m68k, UINT32 value)
+{
+ /* Backup the old stack pointer */
+ REG_SP_BASE[m68k->s_flag | ((m68k->s_flag>>1) & m68k->m_flag)] = REG_SP;
+ /* Set the S flag */
+ m68k->s_flag = value;
+ /* Set the new stack pointer */
+ REG_SP = REG_SP_BASE[m68k->s_flag | ((m68k->s_flag>>1) & m68k->m_flag)];
+}
+
+/* Set the S and M flags and change the active stack pointer.
+ * Note that value MUST be 0, 2, 4, or 6 (bit2 = S, bit1 = M).
+ */
+INLINE void m68ki_set_sm_flag(m68ki_cpu_core *m68k, UINT32 value)
+{
+ /* Backup the old stack pointer */
+ REG_SP_BASE[m68k->s_flag | ((m68k->s_flag>>1) & m68k->m_flag)] = REG_SP;
+ /* Set the S and M flags */
+ m68k->s_flag = value & SFLAG_SET;
+ m68k->m_flag = value & MFLAG_SET;
+ /* Set the new stack pointer */
+ REG_SP = REG_SP_BASE[m68k->s_flag | ((m68k->s_flag>>1) & m68k->m_flag)];
+}
+
+/* Set the S and M flags. Don't touch the stack pointer. */
+INLINE void m68ki_set_sm_flag_nosp(m68ki_cpu_core *m68k, UINT32 value)
+{
+ /* Set the S and M flags */
+ m68k->s_flag = value & SFLAG_SET;
+ m68k->m_flag = value & MFLAG_SET;
+}
+
+
+/* Set the condition code register */
+INLINE void m68ki_set_ccr(m68ki_cpu_core *m68k, UINT32 value)
+{
+ m68k->x_flag = BIT_4(value) << 4;
+ m68k->n_flag = BIT_3(value) << 4;
+ m68k->not_z_flag = !BIT_2(value);
+ m68k->v_flag = BIT_1(value) << 6;
+ m68k->c_flag = BIT_0(value) << 8;
+}
+
+/* Set the status register but don't check for interrupts */
+INLINE void m68ki_set_sr_noint(m68ki_cpu_core *m68k, UINT32 value)
+{
+ /* Mask out the "unimplemented" bits */
+ value &= m68k->sr_mask;
+
+ /* Now set the status register */
+ m68k->t1_flag = BIT_F(value);
+ m68k->t0_flag = BIT_E(value);
+ m68k->int_mask = value & 0x0700;
+ m68ki_set_ccr(m68k, value);
+ m68ki_set_sm_flag(m68k, (value >> 11) & 6);
+}
+
+/* Set the status register but don't check for interrupts nor
+ * change the stack pointer
+ */
+INLINE void m68ki_set_sr_noint_nosp(m68ki_cpu_core *m68k, UINT32 value)
+{
+ /* Mask out the "unimplemented" bits */
+ value &= m68k->sr_mask;
+
+ /* Now set the status register */
+ m68k->t1_flag = BIT_F(value);
+ m68k->t0_flag = BIT_E(value);
+ m68k->int_mask = value & 0x0700;
+ m68ki_set_ccr(m68k, value);
+ m68ki_set_sm_flag_nosp(m68k, (value >> 11) & 6);
+}
+
+/* Set the status register and check for interrupts */
+INLINE void m68ki_set_sr(m68ki_cpu_core *m68k, UINT32 value)
+{
+ m68ki_set_sr_noint(m68k, value);
+ m68ki_check_interrupts(m68k);
+}
+
+
+/* ------------------------- Exception Processing ------------------------- */
+
+/* Initiate exception processing */
+INLINE UINT32 m68ki_init_exception(m68ki_cpu_core *m68k)
+{
+ /* Save the old status register */
+ UINT32 sr = m68ki_get_sr(m68k);
+
+ /* Turn off trace flag, clear pending traces */
+ m68k->t1_flag = m68k->t0_flag = 0;
+ m68ki_clear_trace();
+ /* Enter supervisor mode */
+ m68ki_set_s_flag(m68k, SFLAG_SET);
+
+ return sr;
+}
+
+/* 3 word stack frame (68000 only) */
+INLINE void m68ki_stack_frame_3word(m68ki_cpu_core *m68k, UINT32 pc, UINT32 sr)
+{
+ m68ki_push_32(m68k, pc);
+ m68ki_push_16(m68k, sr);
+}
+
+/* Format 0 stack frame.
+ * This is the standard stack frame for 68010+.
+ */
+INLINE void m68ki_stack_frame_0000(m68ki_cpu_core *m68k, UINT32 pc, UINT32 sr, UINT32 vector)
+{
+ /* Stack a 3-word frame if we are 68000 */
+ if(m68k->cpu_type == CPU_TYPE_000 || m68k->cpu_type == CPU_TYPE_008)
+ {
+ m68ki_stack_frame_3word(m68k, pc, sr);
+ return;
+ }
+ m68ki_push_16(m68k, vector<<2);
+ m68ki_push_32(m68k, pc);
+ m68ki_push_16(m68k, sr);
+}
+
+/* Format 1 stack frame (68020).
+ * For 68020, this is the 4 word throwaway frame.
+ */
+INLINE void m68ki_stack_frame_0001(m68ki_cpu_core *m68k, UINT32 pc, UINT32 sr, UINT32 vector)
+{
+ m68ki_push_16(m68k, 0x1000 | (vector<<2));
+ m68ki_push_32(m68k, pc);
+ m68ki_push_16(m68k, sr);
+}
+
+/* Format 2 stack frame.
+ * This is used only by 68020 for trap exceptions.
+ */
+INLINE void m68ki_stack_frame_0010(m68ki_cpu_core *m68k, UINT32 sr, UINT32 vector)
+{
+ m68ki_push_32(m68k, REG_PPC);
+ m68ki_push_16(m68k, 0x2000 | (vector<<2));
+ m68ki_push_32(m68k, REG_PC);
+ m68ki_push_16(m68k, sr);
+}
+
+
+/* Bus error stack frame (68000 only).
+ */
+INLINE void m68ki_stack_frame_buserr(m68ki_cpu_core *m68k, UINT32 sr)
+{
+ m68ki_push_32(m68k, REG_PC);
+ m68ki_push_16(m68k, sr);
+ m68ki_push_16(m68k, m68k->ir);
+ m68ki_push_32(m68k, m68k->aerr_address); /* access address */
+ /* 0 0 0 0 0 0 0 0 0 0 0 R/W I/N FC
+ * R/W 0 = write, 1 = read
+ * I/N 0 = instruction, 1 = not
+ * FC 3-bit function code
+ */
+ m68ki_push_16(m68k, m68k->aerr_write_mode | m68k->instr_mode | m68k->aerr_fc);
+}
+
+/* Format 8 stack frame (68010).
+ * 68010 only. This is the 29 word bus/address error frame.
+ */
+void m68ki_stack_frame_1000(m68ki_cpu_core *m68k, UINT32 pc, UINT32 sr, UINT32 vector)
+{
+ /* VERSION
+ * NUMBER
+ * INTERNAL INFORMATION, 16 WORDS
+ */
+ m68ki_fake_push_32(m68k);
+ m68ki_fake_push_32(m68k);
+ m68ki_fake_push_32(m68k);
+ m68ki_fake_push_32(m68k);
+ m68ki_fake_push_32(m68k);
+ m68ki_fake_push_32(m68k);
+ m68ki_fake_push_32(m68k);
+ m68ki_fake_push_32(m68k);
+
+ /* INSTRUCTION INPUT BUFFER */
+ m68ki_push_16(m68k, 0);
+
+ /* UNUSED, RESERVED (not written) */
+ m68ki_fake_push_16(m68k);
+
+ /* DATA INPUT BUFFER */
+ m68ki_push_16(m68k, 0);
+
+ /* UNUSED, RESERVED (not written) */
+ m68ki_fake_push_16(m68k);
+
+ /* DATA OUTPUT BUFFER */
+ m68ki_push_16(m68k, 0);
+
+ /* UNUSED, RESERVED (not written) */
+ m68ki_fake_push_16(m68k);
+
+ /* FAULT ADDRESS */
+ m68ki_push_32(m68k, 0);
+
+ /* SPECIAL STATUS WORD */
+ m68ki_push_16(m68k, 0);
+
+ /* 1000, VECTOR OFFSET */
+ m68ki_push_16(m68k, 0x8000 | (vector<<2));
+
+ /* PROGRAM COUNTER */
+ m68ki_push_32(m68k, pc);
+
+ /* STATUS REGISTER */
+ m68ki_push_16(m68k, sr);
+}
+
+/* Format A stack frame (short bus fault).
+ * This is used only by 68020 for bus fault and address error
+ * if the error happens at an instruction boundary.
+ * PC stacked is address of next instruction.
+ */
+void m68ki_stack_frame_1010(m68ki_cpu_core *m68k, UINT32 sr, UINT32 vector, UINT32 pc, UINT32 fault_address)
+{
+ int orig_rw = m68k->mmu_tmp_rw; // this gets splatted by the following pushes, so save it now
+
+ /* INTERNAL REGISTER */
+ m68ki_push_16(m68k, 0);
+
+ /* INTERNAL REGISTER */
+ m68ki_push_16(m68k, 0);
+
+ /* DATA OUTPUT BUFFER (2 words) */
+ m68ki_push_32(m68k, 0);
+
+ /* INTERNAL REGISTER */
+ m68ki_push_16(m68k, 0);
+
+ /* INTERNAL REGISTER */
+ m68ki_push_16(m68k, 0);
+
+ /* DATA CYCLE FAULT ADDRESS (2 words) */
+ m68ki_push_32(m68k, fault_address);
+
+ /* INSTRUCTION PIPE STAGE B */
+ m68ki_push_16(m68k, 0);
+
+ /* INSTRUCTION PIPE STAGE C */
+ m68ki_push_16(m68k, 0);
+
+ /* SPECIAL STATUS REGISTER */
+ // set bit for: Rerun Faulted bus Cycle, or run pending prefetch
+ // set FC
+ m68ki_push_16(m68k, 0x0100 | m68k->mmu_tmp_fc | orig_rw<<6);
+
+ /* INTERNAL REGISTER */
+ m68ki_push_16(m68k, 0);
+
+ /* 1010, VECTOR OFFSET */
+ m68ki_push_16(m68k, 0xa000 | (vector<<2));
+
+ /* PROGRAM COUNTER */
+ m68ki_push_32(m68k, pc);
+
+ /* STATUS REGISTER */
+ m68ki_push_16(m68k, sr);
+}
+
+/* Format B stack frame (long bus fault).
+ * This is used only by 68020 for bus fault and address error
+ * if the error happens during instruction execution.
+ * PC stacked is address of instruction in progress.
+ */
+void m68ki_stack_frame_1011(m68ki_cpu_core *m68k, UINT32 sr, UINT32 vector, UINT32 pc, UINT32 fault_address)
+{
+ int orig_rw = m68k->mmu_tmp_rw; // this gets splatted by the following pushes, so save it now
+
+ /* INTERNAL REGISTERS (18 words) */
+ m68ki_push_32(m68k, 0);
+ m68ki_push_32(m68k, 0);
+ m68ki_push_32(m68k, 0);
+ m68ki_push_32(m68k, 0);
+ m68ki_push_32(m68k, 0);
+ m68ki_push_32(m68k, 0);
+ m68ki_push_32(m68k, 0);
+ m68ki_push_32(m68k, 0);
+ m68ki_push_32(m68k, 0);
+
+ /* VERSION# (4 bits), INTERNAL INFORMATION */
+ m68ki_push_16(m68k, 0);
+
+ /* INTERNAL REGISTERS (3 words) */
+ m68ki_push_32(m68k, 0);
+ m68ki_push_16(m68k, 0);
+
+ /* DATA INTPUT BUFFER (2 words) */
+ m68ki_push_32(m68k, 0);
+
+ /* INTERNAL REGISTERS (2 words) */
+ m68ki_push_32(m68k, 0);
+
+ /* STAGE B ADDRESS (2 words) */
+ m68ki_push_32(m68k, 0);
+
+ /* INTERNAL REGISTER (4 words) */
+ m68ki_push_32(m68k, 0);
+ m68ki_push_32(m68k, 0);
+
+ /* DATA OUTPUT BUFFER (2 words) */
+ m68ki_push_32(m68k, 0);
+
+ /* INTERNAL REGISTER */
+ m68ki_push_16(m68k, 0);
+
+ /* INTERNAL REGISTER */
+ m68ki_push_16(m68k, 0);
+
+ /* DATA CYCLE FAULT ADDRESS (2 words) */
+ m68ki_push_32(m68k, fault_address);
+
+ /* INSTRUCTION PIPE STAGE B */
+ m68ki_push_16(m68k, 0);
+
+ /* INSTRUCTION PIPE STAGE C */
+ m68ki_push_16(m68k, 0);
+
+ /* SPECIAL STATUS REGISTER */
+ m68ki_push_16(m68k, 0x0100 | m68k->mmu_tmp_fc | orig_rw<<6);
+
+ /* INTERNAL REGISTER */
+ m68ki_push_16(m68k, 0);
+
+ /* 1011, VECTOR OFFSET */
+ m68ki_push_16(m68k, 0xb000 | (vector<<2));
+
+ /* PROGRAM COUNTER */
+ m68ki_push_32(m68k, pc);
+
+ /* STATUS REGISTER */
+ m68ki_push_16(m68k, sr);
+}
+
+
+/* Used for Group 2 exceptions.
+ * These stack a type 2 frame on the 020.
+ */
+INLINE void m68ki_exception_trap(m68ki_cpu_core *m68k, UINT32 vector)
+{
+ UINT32 sr = m68ki_init_exception(m68k);
+
+ if(CPU_TYPE_IS_010_LESS(m68k->cpu_type))
+ m68ki_stack_frame_0000(m68k, REG_PC, sr, vector);
+ else
+ m68ki_stack_frame_0010(m68k, sr, vector);
+
+ m68ki_jump_vector(m68k, vector);
+
+ /* Use up some clock cycles */
+ m68k->remaining_cycles -= m68k->cyc_exception[vector];
+}
+
+/* Trap#n stacks a 0 frame but behaves like group2 otherwise */
+INLINE void m68ki_exception_trapN(m68ki_cpu_core *m68k, UINT32 vector)
+{
+ UINT32 sr = m68ki_init_exception(m68k);
+ m68ki_stack_frame_0000(m68k, REG_PC, sr, vector);
+ m68ki_jump_vector(m68k, vector);
+
+ /* Use up some clock cycles */
+ m68k->remaining_cycles -= m68k->cyc_exception[vector];
+}
+
+/* Exception for trace mode */
+INLINE void m68ki_exception_trace(m68ki_cpu_core *m68k)
+{
+ UINT32 sr = m68ki_init_exception(m68k);
+
+ if(CPU_TYPE_IS_010_LESS(m68k->cpu_type))
+ {
+ if(CPU_TYPE_IS_000(m68k->cpu_type))
+ {
+ m68k->instr_mode = INSTRUCTION_NO;
+ }
+ m68ki_stack_frame_0000(m68k, REG_PC, sr, EXCEPTION_TRACE);
+ }
+ else
+ m68ki_stack_frame_0010(m68k, sr, EXCEPTION_TRACE);
+
+ m68ki_jump_vector(m68k, EXCEPTION_TRACE);
+
+ /* Trace nullifies a STOP instruction */
+ m68k->stopped &= ~STOP_LEVEL_STOP;
+
+ /* Use up some clock cycles */
+ m68k->remaining_cycles -= m68k->cyc_exception[EXCEPTION_TRACE];
+}
+
+/* Exception for privilege violation */
+INLINE void m68ki_exception_privilege_violation(m68ki_cpu_core *m68k)
+{
+ UINT32 sr = m68ki_init_exception(m68k);
+
+ if(CPU_TYPE_IS_000(m68k->cpu_type))
+ {
+ m68k->instr_mode = INSTRUCTION_NO;
+ }
+
+ m68ki_stack_frame_0000(m68k, REG_PPC, sr, EXCEPTION_PRIVILEGE_VIOLATION);
+ m68ki_jump_vector(m68k, EXCEPTION_PRIVILEGE_VIOLATION);
+
+ /* Use up some clock cycles and undo the instruction's cycles */
+ m68k->remaining_cycles -= m68k->cyc_exception[EXCEPTION_PRIVILEGE_VIOLATION] - m68k->cyc_instruction[m68k->ir];
+}
+
+/* Exception for A-Line instructions */
+INLINE void m68ki_exception_1010(m68ki_cpu_core *m68k)
+{
+ UINT32 sr;
+
+ sr = m68ki_init_exception(m68k);
+ m68ki_stack_frame_0000(m68k, REG_PPC, sr, EXCEPTION_1010);
+ m68ki_jump_vector(m68k, EXCEPTION_1010);
+
+ /* Use up some clock cycles and undo the instruction's cycles */
+ m68k->remaining_cycles -= m68k->cyc_exception[EXCEPTION_1010] - m68k->cyc_instruction[m68k->ir];
+}
+
+/* Exception for F-Line instructions */
+INLINE void m68ki_exception_1111(m68ki_cpu_core *m68k)
+{
+ UINT32 sr;
+
+ sr = m68ki_init_exception(m68k);
+ m68ki_stack_frame_0000(m68k, REG_PPC, sr, EXCEPTION_1111);
+ m68ki_jump_vector(m68k, EXCEPTION_1111);
+
+ /* Use up some clock cycles and undo the instruction's cycles */
+ m68k->remaining_cycles -= m68k->cyc_exception[EXCEPTION_1111] - m68k->cyc_instruction[m68k->ir];
+}
+
+/* Exception for illegal instructions */
+INLINE void m68ki_exception_illegal(m68ki_cpu_core *m68k)
+{
+ UINT32 sr;
+
+ sr = m68ki_init_exception(m68k);
+
+ if(CPU_TYPE_IS_000(m68k->cpu_type))
+ {
+ m68k->instr_mode = INSTRUCTION_NO;
+ }
+
+ m68ki_stack_frame_0000(m68k, REG_PPC, sr, EXCEPTION_ILLEGAL_INSTRUCTION);
+ m68ki_jump_vector(m68k, EXCEPTION_ILLEGAL_INSTRUCTION);
+
+ /* Use up some clock cycles and undo the instruction's cycles */
+ m68k->remaining_cycles -= m68k->cyc_exception[EXCEPTION_ILLEGAL_INSTRUCTION] - m68k->cyc_instruction[m68k->ir];
+}
+
+/* Exception for format errror in RTE */
+INLINE void m68ki_exception_format_error(m68ki_cpu_core *m68k)
+{
+ UINT32 sr = m68ki_init_exception(m68k);
+ m68ki_stack_frame_0000(m68k, REG_PC, sr, EXCEPTION_FORMAT_ERROR);
+ m68ki_jump_vector(m68k, EXCEPTION_FORMAT_ERROR);
+
+ /* Use up some clock cycles and undo the instruction's cycles */
+ m68k->remaining_cycles -= m68k->cyc_exception[EXCEPTION_FORMAT_ERROR] - m68k->cyc_instruction[m68k->ir];
+}
+
+/* Exception for address error */
+INLINE void m68ki_exception_address_error(m68ki_cpu_core *m68k)
+{
+ UINT32 sr = m68ki_init_exception(m68k);
+
+ /* If we were processing a bus error, address error, or reset,
+ * this is a catastrophic failure.
+ * Halt the CPU
+ */
+ if(m68k->run_mode == RUN_MODE_BERR_AERR_RESET)
+ {
+ m68k->memory.read8(0x00ffff01);
+ m68k->stopped = STOP_LEVEL_HALT;
+ return;
+ }
+ m68k->run_mode = RUN_MODE_BERR_AERR_RESET;
+
+ /* Note: This is implemented for 68000 only! */
+ m68ki_stack_frame_buserr(m68k, sr);
+
+ m68ki_jump_vector(m68k, EXCEPTION_ADDRESS_ERROR);
+
+ /* Use up some clock cycles and undo the instruction's cycles */
+ m68k->remaining_cycles -= m68k->cyc_exception[EXCEPTION_ADDRESS_ERROR] - m68k->cyc_instruction[m68k->ir];
+}
+
+
+/* Service an interrupt request and start exception processing */
+void m68ki_exception_interrupt(m68ki_cpu_core *m68k, UINT32 int_level)
+{
+ UINT32 vector;
+ UINT32 sr;
+ UINT32 new_pc;
+
+ if(CPU_TYPE_IS_000(m68k->cpu_type))
+ {
+ m68k->instr_mode = INSTRUCTION_NO;
+ }
+
+ /* Turn off the stopped state */
+ m68k->stopped &= ~STOP_LEVEL_STOP;
+
+ /* If we are halted, don't do anything */
+ if(m68k->stopped)
+ return;
+
+ /* Acknowledge the interrupt */
+ vector = (*m68k->int_ack_callback)(m68k->device, int_level);
+
+ /* Get the interrupt vector */
+ if(vector == M68K_INT_ACK_AUTOVECTOR)
+ /* Use the autovectors. This is the most commonly used implementation */
+ vector = EXCEPTION_INTERRUPT_AUTOVECTOR+int_level;
+ else if(vector == M68K_INT_ACK_SPURIOUS)
+ /* Called if no devices respond to the interrupt acknowledge */
+ vector = EXCEPTION_SPURIOUS_INTERRUPT;
+ else if(vector > 255)
+ return;
+
+ /* Start exception processing */
+ sr = m68ki_init_exception(m68k);
+
+ /* Set the interrupt mask to the level of the one being serviced */
+ m68k->int_mask = int_level<<8;
+
+ /* Get the new PC */
+ new_pc = m68ki_read_data_32(m68k, (vector<<2) + m68k->vbr);
+
+ /* If vector is uninitialized, call the uninitialized interrupt vector */
+ if(new_pc == 0)
+ new_pc = m68ki_read_data_32(m68k, (EXCEPTION_UNINITIALIZED_INTERRUPT<<2) + m68k->vbr);
+
+ /* Generate a stack frame */
+ m68ki_stack_frame_0000(m68k, REG_PC, sr, vector);
+ if(m68k->m_flag && CPU_TYPE_IS_EC020_PLUS(m68k->cpu_type))
+ {
+ /* Create throwaway frame */
+ m68ki_set_sm_flag(m68k, m68k->s_flag); /* clear M */
+ sr |= 0x2000; /* Same as SR in master stack frame except S is forced high */
+ m68ki_stack_frame_0001(m68k, REG_PC, sr, vector);
+ }
+
+ m68ki_jump(m68k, new_pc);
+
+ /* Defer cycle counting until later */
+ m68k->remaining_cycles -= m68k->cyc_exception[vector];
+}
+
+
+/* ASG: Check for interrupts */
+INLINE void m68ki_check_interrupts(m68ki_cpu_core *m68k)
+{
+ if(m68k->nmi_pending)
+ {
+ m68k->nmi_pending = FALSE;
+ m68ki_exception_interrupt(m68k, 7);
+ }
+ else if(m68k->int_level > m68k->int_mask)
+ m68ki_exception_interrupt(m68k, m68k->int_level>>8);
+}
+
+
+
+/* ======================================================================== */
+/* ============================== END OF FILE ============================= */
+/* ======================================================================== */
+
+#endif /* __M68KCPU_H__ */
diff --git a/trunk/src/emu/cpu/m68000/m68kdasm.c b/trunk/src/emu/cpu/m68000/m68kdasm.c
new file mode 100644
index 00000000000..2628847c849
--- /dev/null
+++ b/trunk/src/emu/cpu/m68000/m68kdasm.c
@@ -0,0 +1,4031 @@
+/* ======================================================================== */
+/* ========================= LICENSING & COPYRIGHT ======================== */
+/* ======================================================================== */
+/*
+ * MUSASHI
+ * Version 3.32
+ *
+ * A portable Motorola M680x0 processor emulation engine.
+ * Copyright Karl Stenerud. All rights reserved.
+ *
+ * This code may be freely used for non-commercial purposes as long as this
+ * copyright notice remains unaltered in the source code and any binary files
+ * containing this code in compiled form.
+ *
+ * All other licensing terms must be negotiated with the author
+ * (Karl Stenerud).
+ *
+ * The latest version of this code can be obtained at:
+ * http://kstenerud.cjb.net
+ */
+
+
+
+/* ======================================================================== */
+/* ================================ INCLUDES ============================== */
+/* ======================================================================== */
+
+#define m68ki_cpu_core void
+#include "emu.h"
+#include "m68000.h"
+
+#ifndef DECL_SPEC
+#define DECL_SPEC
+#endif
+
+/* ======================================================================== */
+/* ============================ GENERAL DEFINES =========================== */
+/* ======================================================================== */
+
+/* unsigned int and int must be at least 32 bits wide */
+#undef UINT32
+#define UINT32 unsigned int
+
+/* Bit Isolation Functions */
+#define BIT_0(A) ((A) & 0x00000001)
+#define BIT_1(A) ((A) & 0x00000002)
+#define BIT_2(A) ((A) & 0x00000004)
+#define BIT_3(A) ((A) & 0x00000008)
+#define BIT_4(A) ((A) & 0x00000010)
+#define BIT_5(A) ((A) & 0x00000020)
+#define BIT_6(A) ((A) & 0x00000040)
+#define BIT_7(A) ((A) & 0x00000080)
+#define BIT_8(A) ((A) & 0x00000100)
+#define BIT_9(A) ((A) & 0x00000200)
+#define BIT_A(A) ((A) & 0x00000400)
+#define BIT_B(A) ((A) & 0x00000800)
+#define BIT_C(A) ((A) & 0x00001000)
+#define BIT_D(A) ((A) & 0x00002000)
+#define BIT_E(A) ((A) & 0x00004000)
+#define BIT_F(A) ((A) & 0x00008000)
+#define BIT_10(A) ((A) & 0x00010000)
+#define BIT_11(A) ((A) & 0x00020000)
+#define BIT_12(A) ((A) & 0x00040000)
+#define BIT_13(A) ((A) & 0x00080000)
+#define BIT_14(A) ((A) & 0x00100000)
+#define BIT_15(A) ((A) & 0x00200000)
+#define BIT_16(A) ((A) & 0x00400000)
+#define BIT_17(A) ((A) & 0x00800000)
+#define BIT_18(A) ((A) & 0x01000000)
+#define BIT_19(A) ((A) & 0x02000000)
+#define BIT_1A(A) ((A) & 0x04000000)
+#define BIT_1B(A) ((A) & 0x08000000)
+#define BIT_1C(A) ((A) & 0x10000000)
+#define BIT_1D(A) ((A) & 0x20000000)
+#define BIT_1E(A) ((A) & 0x40000000)
+#define BIT_1F(A) ((A) & 0x80000000)
+
+/* These are the CPU types understood by this disassembler */
+#define TYPE_68000 1
+#define TYPE_68008 2
+#define TYPE_68010 4
+#define TYPE_68020 8
+#define TYPE_68030 16
+#define TYPE_68040 32
+
+#define M68000_ONLY (TYPE_68000 | TYPE_68008)
+
+#define M68010_ONLY TYPE_68010
+#define M68010_LESS (TYPE_68000 | TYPE_68008 | TYPE_68010)
+#define M68010_PLUS (TYPE_68010 | TYPE_68020 | TYPE_68030 | TYPE_68040)
+
+#define M68020_ONLY TYPE_68020
+#define M68020_LESS (TYPE_68010 | TYPE_68020)
+#define M68020_PLUS (TYPE_68020 | TYPE_68030 | TYPE_68040)
+
+#define M68030_ONLY TYPE_68030
+#define M68030_LESS (TYPE_68010 | TYPE_68020 | TYPE_68030)
+#define M68030_PLUS (TYPE_68030 | TYPE_68040)
+
+#define M68040_PLUS TYPE_68040
+
+
+/* Extension word formats */
+#define EXT_8BIT_DISPLACEMENT(A) ((A)&0xff)
+#define EXT_FULL(A) BIT_8(A)
+#define EXT_EFFECTIVE_ZERO(A) (((A)&0xe4) == 0xc4 || ((A)&0xe2) == 0xc0)
+#define EXT_BASE_REGISTER_PRESENT(A) (!BIT_7(A))
+#define EXT_INDEX_REGISTER_PRESENT(A) (!BIT_6(A))
+#define EXT_INDEX_REGISTER(A) (((A)>>12)&7)
+#define EXT_INDEX_PRE_POST(A) (EXT_INDEX_PRESENT(A) && (A)&3)
+#define EXT_INDEX_PRE(A) (EXT_INDEX_PRESENT(A) && ((A)&7) < 4 && ((A)&7) != 0)
+#define EXT_INDEX_POST(A) (EXT_INDEX_PRESENT(A) && ((A)&7) > 4)
+#define EXT_INDEX_SCALE(A) (((A)>>9)&3)
+#define EXT_INDEX_LONG(A) BIT_B(A)
+#define EXT_INDEX_AR(A) BIT_F(A)
+#define EXT_BASE_DISPLACEMENT_PRESENT(A) (((A)&0x30) > 0x10)
+#define EXT_BASE_DISPLACEMENT_WORD(A) (((A)&0x30) == 0x20)
+#define EXT_BASE_DISPLACEMENT_LONG(A) (((A)&0x30) == 0x30)
+#define EXT_OUTER_DISPLACEMENT_PRESENT(A) (((A)&3) > 1 && ((A)&0x47) < 0x44)
+#define EXT_OUTER_DISPLACEMENT_WORD(A) (((A)&3) == 2 && ((A)&0x47) < 0x44)
+#define EXT_OUTER_DISPLACEMENT_LONG(A) (((A)&3) == 3 && ((A)&0x47) < 0x44)
+
+
+/* Opcode flags */
+#define SET_OPCODE_FLAGS(x) g_opcode_type = x;
+#define COMBINE_OPCODE_FLAGS(x) ((x) | g_opcode_type | DASMFLAG_SUPPORTED)
+
+
+/* ======================================================================== */
+/* =============================== PROTOTYPES ============================= */
+/* ======================================================================== */
+
+/* Read data at the PC and increment PC */
+UINT32 read_imm_8(void);
+UINT32 read_imm_16(void);
+UINT32 read_imm_32(void);
+
+/* Read data at the PC but don't imcrement the PC */
+UINT32 peek_imm_8(void);
+UINT32 peek_imm_16(void);
+UINT32 peek_imm_32(void);
+
+/* make signed integers 100% portably */
+static int make_int_8(int value);
+static int make_int_16(int value);
+static int make_int_32(int value);
+
+/* make a string of a hex value */
+static char* make_signed_hex_str_8(UINT32 val);
+static char* make_signed_hex_str_16(UINT32 val);
+static char* make_signed_hex_str_32(UINT32 val);
+
+/* make string of ea mode */
+static char* get_ea_mode_str(UINT32 instruction, UINT32 size);
+
+char* get_ea_mode_str_8(UINT32 instruction);
+char* get_ea_mode_str_16(UINT32 instruction);
+char* get_ea_mode_str_32(UINT32 instruction);
+
+/* make string of immediate value */
+static char* get_imm_str_s(UINT32 size);
+static char* get_imm_str_u(UINT32 size);
+
+char* get_imm_str_s8(void);
+char* get_imm_str_s16(void);
+char* get_imm_str_s32(void);
+
+/* Stuff to build the opcode handler jump table */
+static void build_opcode_table(void);
+static int valid_ea(UINT32 opcode, UINT32 mask);
+static int DECL_SPEC compare_nof_true_bits(const void *aptr, const void *bptr);
+
+/* used to build opcode handler jump table */
+typedef struct
+{
+ void (*opcode_handler)(void); /* handler function */
+ UINT32 mask; /* mask on opcode */
+ UINT32 match; /* what to match after masking */
+ UINT32 ea_mask; /* what ea modes are allowed */
+} opcode_struct;
+
+
+
+/* ======================================================================== */
+/* ================================= DATA ================================= */
+/* ======================================================================== */
+
+/* Opcode handler jump table */
+static void (*g_instruction_table[0x10000])(void);
+/* Flag if disassembler initialized */
+static int g_initialized = 0;
+
+static char g_dasm_str[100]; /* string to hold disassembly */
+static char g_helper_str[100]; /* string to hold helpful info */
+static UINT32 g_cpu_pc; /* program counter */
+static UINT32 g_cpu_ir; /* instruction register */
+static UINT32 g_cpu_type;
+static UINT32 g_opcode_type;
+static const unsigned char* g_rawop;
+static UINT32 g_rawbasepc;
+
+/* used by ops like asr, ror, addq, etc */
+static const UINT32 g_3bit_qdata_table[8] = {8, 1, 2, 3, 4, 5, 6, 7};
+
+static const UINT32 g_5bit_data_table[32] =
+{
+ 32, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
+};
+
+static const char *const g_cc[16] =
+{"t", "f", "hi", "ls", "cc", "cs", "ne", "eq", "vc", "vs", "pl", "mi", "ge", "lt", "gt", "le"};
+
+static const char *const g_cpcc[64] =
+{/* 000 001 010 011 100 101 110 111 */
+ "f", "eq", "ogt", "oge", "olt", "ole", "ogl", "or", /* 000 */
+ "un", "ueq", "ugt", "uge", "ult", "ule", "ne", "t", /* 001 */
+ "sf", "seq", "gt", "ge", "lt", "le", "gl" "gle", /* 010 */
+ "ngle", "ngl", "nle", "nlt", "nge", "ngt", "sne", "st", /* 011 */
+ "?", "?", "?", "?", "?", "?", "?", "?", /* 100 */
+ "?", "?", "?", "?", "?", "?", "?", "?", /* 101 */
+ "?", "?", "?", "?", "?", "?", "?", "?", /* 110 */
+ "?", "?", "?", "?", "?", "?", "?", "?" /* 111 */
+};
+
+static const char *const g_mmuregs[8] =
+{
+ "tc", "drp", "srp", "crp", "cal", "val", "sccr", "acr"
+};
+
+static const char *const g_mmucond[16] =
+{
+ "bs", "bc", "ls", "lc", "ss", "sc", "as", "ac",
+ "ws", "wc", "is", "ic", "gs", "gc", "cs", "cc"
+};
+
+/* ======================================================================== */
+/* =========================== UTILITY FUNCTIONS ========================== */
+/* ======================================================================== */
+
+#define LIMIT_CPU_TYPES(ALLOWED_CPU_TYPES) \
+ if(!(g_cpu_type & ALLOWED_CPU_TYPES)) \
+ { \
+ if((g_cpu_ir & 0xf000) == 0xf000) \
+ d68000_1111(); \
+ else d68000_illegal(); \
+ return; \
+ }
+
+static UINT32 dasm_read_imm_8(UINT32 advance)
+{
+ UINT32 result;
+ result = g_rawop[g_cpu_pc + 1 - g_rawbasepc];
+ g_cpu_pc += advance;
+ return result;
+}
+
+static UINT32 dasm_read_imm_16(UINT32 advance)
+{
+ UINT32 result;
+ result = (g_rawop[g_cpu_pc + 0 - g_rawbasepc] << 8) |
+ g_rawop[g_cpu_pc + 1 - g_rawbasepc];
+ g_cpu_pc += advance;
+ return result;
+}
+
+static UINT32 dasm_read_imm_32(UINT32 advance)
+{
+ UINT32 result;
+ result = (g_rawop[g_cpu_pc + 0 - g_rawbasepc] << 24) |
+ (g_rawop[g_cpu_pc + 1 - g_rawbasepc] << 16) |
+ (g_rawop[g_cpu_pc + 2 - g_rawbasepc] << 8) |
+ g_rawop[g_cpu_pc + 3 - g_rawbasepc];
+ g_cpu_pc += advance;
+ return result;
+}
+
+#define read_imm_8() dasm_read_imm_8(2)
+#define read_imm_16() dasm_read_imm_16(2)
+#define read_imm_32() dasm_read_imm_32(4)
+
+#define peek_imm_8() dasm_read_imm_8(0)
+#define peek_imm_16() dasm_read_imm_16(0)
+#define peek_imm_32() dasm_read_imm_32(0)
+
+/* Fake a split interface */
+#define get_ea_mode_str_8(instruction) get_ea_mode_str(instruction, 0)
+#define get_ea_mode_str_16(instruction) get_ea_mode_str(instruction, 1)
+#define get_ea_mode_str_32(instruction) get_ea_mode_str(instruction, 2)
+
+#define get_imm_str_s8() get_imm_str_s(0)
+#define get_imm_str_s16() get_imm_str_s(1)
+#define get_imm_str_s32() get_imm_str_s(2)
+
+#define get_imm_str_u8() get_imm_str_u(0)
+#define get_imm_str_u16() get_imm_str_u(1)
+#define get_imm_str_u32() get_imm_str_u(2)
+
+static int sext_7bit_int(int value)
+{
+ return (value & 0x40) ? (value | 0xffffff80) : (value & 0x7f);
+}
+
+
+/* 100% portable signed int generators */
+static int make_int_8(int value)
+{
+ return (value & 0x80) ? value | ~0xff : value & 0xff;
+}
+
+static int make_int_16(int value)
+{
+ return (value & 0x8000) ? value | ~0xffff : value & 0xffff;
+}
+
+static int make_int_32(int value)
+{
+ return (value & 0x80000000) ? value | ~0xffffffff : value & 0xffffffff;
+}
+
+/* Get string representation of hex values */
+static char* make_signed_hex_str_8(UINT32 val)
+{
+ static char str[20];
+
+ val &= 0xff;
+
+ if(val == 0x80)
+ sprintf(str, "-$80");
+ else if(val & 0x80)
+ sprintf(str, "-$%x", (0-val) & 0x7f);
+ else
+ sprintf(str, "$%x", val & 0x7f);
+
+ return str;
+}
+
+static char* make_signed_hex_str_16(UINT32 val)
+{
+ static char str[20];
+
+ val &= 0xffff;
+
+ if(val == 0x8000)
+ sprintf(str, "-$8000");
+ else if(val & 0x8000)
+ sprintf(str, "-$%x", (0-val) & 0x7fff);
+ else
+ sprintf(str, "$%x", val & 0x7fff);
+
+ return str;
+}
+
+static char* make_signed_hex_str_32(UINT32 val)
+{
+ static char str[20];
+
+ val &= 0xffffffff;
+
+ if(val == 0x80000000)
+ sprintf(str, "-$80000000");
+ else if(val & 0x80000000)
+ sprintf(str, "-$%x", (0-val) & 0x7fffffff);
+ else
+ sprintf(str, "$%x", val & 0x7fffffff);
+
+ return str;
+}
+
+
+/* make string of immediate value */
+static char* get_imm_str_s(UINT32 size)
+{
+ static char str[15];
+ if(size == 0)
+ sprintf(str, "#%s", make_signed_hex_str_8(read_imm_8()));
+ else if(size == 1)
+ sprintf(str, "#%s", make_signed_hex_str_16(read_imm_16()));
+ else
+ sprintf(str, "#%s", make_signed_hex_str_32(read_imm_32()));
+ return str;
+}
+
+static char* get_imm_str_u(UINT32 size)
+{
+ static char str[15];
+ if(size == 0)
+ sprintf(str, "#$%x", read_imm_8() & 0xff);
+ else if(size == 1)
+ sprintf(str, "#$%x", read_imm_16() & 0xffff);
+ else
+ sprintf(str, "#$%x", read_imm_32() & 0xffffffff);
+ return str;
+}
+
+/* Make string of effective address mode */
+static char* get_ea_mode_str(UINT32 instruction, UINT32 size)
+{
+ static char b1[64];
+ static char b2[64];
+ static char* mode = b2;
+ UINT32 extension;
+ UINT32 base;
+ UINT32 outer;
+ char base_reg[4];
+ char index_reg[8];
+ UINT32 preindex;
+ UINT32 postindex;
+ UINT32 comma = 0;
+ UINT32 temp_value;
+ char invalid_mode = 0;
+
+ /* Switch buffers so we don't clobber on a double-call to this function */
+ mode = mode == b1 ? b2 : b1;
+
+ switch(instruction & 0x3f)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+ /* data register direct */
+ sprintf(mode, "D%d", instruction&7);
+ break;
+ case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ /* address register direct */
+ sprintf(mode, "A%d", instruction&7);
+ break;
+ case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
+ /* address register indirect */
+ sprintf(mode, "(A%d)", instruction&7);
+ break;
+ case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ /* address register indirect with postincrement */
+ sprintf(mode, "(A%d)+", instruction&7);
+ break;
+ case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
+ /* address register indirect with predecrement */
+ sprintf(mode, "-(A%d)", instruction&7);
+ break;
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ /* address register indirect with displacement*/
+ sprintf(mode, "(%s,A%d)", make_signed_hex_str_16(read_imm_16()), instruction&7);
+ break;
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
+ /* address register indirect with index */
+ extension = read_imm_16();
+
+ if((g_cpu_type & M68010_LESS) && EXT_INDEX_SCALE(extension))
+ {
+ invalid_mode = 1;
+ break;
+ }
+
+ if(EXT_FULL(extension))
+ {
+ if(g_cpu_type & M68010_LESS)
+ {
+ invalid_mode = 1;
+ break;
+ }
+
+ if(EXT_EFFECTIVE_ZERO(extension))
+ {
+ strcpy(mode, "0");
+ break;
+ }
+
+ base = EXT_BASE_DISPLACEMENT_PRESENT(extension) ? (EXT_BASE_DISPLACEMENT_LONG(extension) ? read_imm_32() : read_imm_16()) : 0;
+ outer = EXT_OUTER_DISPLACEMENT_PRESENT(extension) ? (EXT_OUTER_DISPLACEMENT_LONG(extension) ? read_imm_32() : read_imm_16()) : 0;
+ if(EXT_BASE_REGISTER_PRESENT(extension))
+ sprintf(base_reg, "A%d", instruction&7);
+ else
+ *base_reg = 0;
+ if(EXT_INDEX_REGISTER_PRESENT(extension))
+ {
+ sprintf(index_reg, "%c%d.%c", EXT_INDEX_AR(extension) ? 'A' : 'D', EXT_INDEX_REGISTER(extension), EXT_INDEX_LONG(extension) ? 'l' : 'w');
+ if(EXT_INDEX_SCALE(extension))
+ sprintf(index_reg+strlen(index_reg), "*%d", 1 << EXT_INDEX_SCALE(extension));
+ }
+ else
+ *index_reg = 0;
+ preindex = (extension&7) > 0 && (extension&7) < 4;
+ postindex = (extension&7) > 4;
+
+ strcpy(mode, "(");
+ if(preindex || postindex)
+ strcat(mode, "[");
+ if(base)
+ {
+ if (EXT_BASE_DISPLACEMENT_LONG(extension))
+ {
+ strcat(mode, make_signed_hex_str_32(base));
+ }
+ else
+ {
+ strcat(mode, make_signed_hex_str_16(base));
+ }
+ comma = 1;
+ }
+ if(*base_reg)
+ {
+ if(comma)
+ strcat(mode, ",");
+ strcat(mode, base_reg);
+ comma = 1;
+ }
+ if(postindex)
+ {
+ strcat(mode, "]");
+ comma = 1;
+ }
+ if(*index_reg)
+ {
+ if(comma)
+ strcat(mode, ",");
+ strcat(mode, index_reg);
+ comma = 1;
+ }
+ if(preindex)
+ {
+ strcat(mode, "]");
+ comma = 1;
+ }
+ if(outer)
+ {
+ if(comma)
+ strcat(mode, ",");
+ strcat(mode, make_signed_hex_str_16(outer));
+ }
+ strcat(mode, ")");
+ break;
+ }
+
+ if(EXT_8BIT_DISPLACEMENT(extension) == 0)
+ sprintf(mode, "(A%d,%c%d.%c", instruction&7, EXT_INDEX_AR(extension) ? 'A' : 'D', EXT_INDEX_REGISTER(extension), EXT_INDEX_LONG(extension) ? 'l' : 'w');
+ else
+ sprintf(mode, "(%s,A%d,%c%d.%c", make_signed_hex_str_8(extension), instruction&7, EXT_INDEX_AR(extension) ? 'A' : 'D', EXT_INDEX_REGISTER(extension), EXT_INDEX_LONG(extension) ? 'l' : 'w');
+ if(EXT_INDEX_SCALE(extension))
+ sprintf(mode+strlen(mode), "*%d", 1 << EXT_INDEX_SCALE(extension));
+ strcat(mode, ")");
+ break;
+ case 0x38:
+ /* absolute short address */
+ sprintf(mode, "$%x.w", read_imm_16());
+ break;
+ case 0x39:
+ /* absolute long address */
+ sprintf(mode, "$%x.l", read_imm_32());
+ break;
+ case 0x3a:
+ /* program counter with displacement */
+ temp_value = read_imm_16();
+ sprintf(mode, "(%s,PC)", make_signed_hex_str_16(temp_value));
+ sprintf(g_helper_str, "; ($%x)", (make_int_16(temp_value) + g_cpu_pc-2) & 0xffffffff);
+ break;
+ case 0x3b:
+ /* program counter with index */
+ extension = read_imm_16();
+
+ if((g_cpu_type & M68010_LESS) && EXT_INDEX_SCALE(extension))
+ {
+ invalid_mode = 1;
+ break;
+ }
+
+ if(EXT_FULL(extension))
+ {
+ if(g_cpu_type & M68010_LESS)
+ {
+ invalid_mode = 1;
+ break;
+ }
+
+ if(EXT_EFFECTIVE_ZERO(extension))
+ {
+ strcpy(mode, "0");
+ break;
+ }
+ base = EXT_BASE_DISPLACEMENT_PRESENT(extension) ? (EXT_BASE_DISPLACEMENT_LONG(extension) ? read_imm_32() : read_imm_16()) : 0;
+ outer = EXT_OUTER_DISPLACEMENT_PRESENT(extension) ? (EXT_OUTER_DISPLACEMENT_LONG(extension) ? read_imm_32() : read_imm_16()) : 0;
+ if(EXT_BASE_REGISTER_PRESENT(extension))
+ strcpy(base_reg, "PC");
+ else
+ *base_reg = 0;
+ if(EXT_INDEX_REGISTER_PRESENT(extension))
+ {
+ sprintf(index_reg, "%c%d.%c", EXT_INDEX_AR(extension) ? 'A' : 'D', EXT_INDEX_REGISTER(extension), EXT_INDEX_LONG(extension) ? 'l' : 'w');
+ if(EXT_INDEX_SCALE(extension))
+ sprintf(index_reg+strlen(index_reg), "*%d", 1 << EXT_INDEX_SCALE(extension));
+ }
+ else
+ *index_reg = 0;
+ preindex = (extension&7) > 0 && (extension&7) < 4;
+ postindex = (extension&7) > 4;
+
+ strcpy(mode, "(");
+ if(preindex || postindex)
+ strcat(mode, "[");
+ if(base)
+ {
+ strcat(mode, make_signed_hex_str_16(base));
+ comma = 1;
+ }
+ if(*base_reg)
+ {
+ if(comma)
+ strcat(mode, ",");
+ strcat(mode, base_reg);
+ comma = 1;
+ }
+ if(postindex)
+ {
+ strcat(mode, "]");
+ comma = 1;
+ }
+ if(*index_reg)
+ {
+ if(comma)
+ strcat(mode, ",");
+ strcat(mode, index_reg);
+ comma = 1;
+ }
+ if(preindex)
+ {
+ strcat(mode, "]");
+ comma = 1;
+ }
+ if(outer)
+ {
+ if(comma)
+ strcat(mode, ",");
+ strcat(mode, make_signed_hex_str_16(outer));
+ }
+ strcat(mode, ")");
+ break;
+ }
+
+ if(EXT_8BIT_DISPLACEMENT(extension) == 0)
+ sprintf(mode, "(PC,%c%d.%c", EXT_INDEX_AR(extension) ? 'A' : 'D', EXT_INDEX_REGISTER(extension), EXT_INDEX_LONG(extension) ? 'l' : 'w');
+ else
+ sprintf(mode, "(%s,PC,%c%d.%c", make_signed_hex_str_8(extension), EXT_INDEX_AR(extension) ? 'A' : 'D', EXT_INDEX_REGISTER(extension), EXT_INDEX_LONG(extension) ? 'l' : 'w');
+ if(EXT_INDEX_SCALE(extension))
+ sprintf(mode+strlen(mode), "*%d", 1 << EXT_INDEX_SCALE(extension));
+ strcat(mode, ")");
+ break;
+ case 0x3c:
+ /* Immediate */
+ sprintf(mode, "%s", get_imm_str_u(size));
+ break;
+ default:
+ invalid_mode = 1;
+ }
+
+ if(invalid_mode)
+ sprintf(mode, "INVALID %x", instruction & 0x3f);
+
+ return mode;
+}
+
+
+
+/* ======================================================================== */
+/* ========================= INSTRUCTION HANDLERS ========================= */
+/* ======================================================================== */
+/* Instruction handler function names follow this convention:
+ *
+ * d68000_NAME_EXTENSIONS(void)
+ * where NAME is the name of the opcode it handles and EXTENSIONS are any
+ * extensions for special instances of that opcode.
+ *
+ * Examples:
+ * d68000_add_er_8(): add opcode, from effective address to register,
+ * size = byte
+ *
+ * d68000_asr_s_8(): arithmetic shift right, static count, size = byte
+ *
+ *
+ * Common extensions:
+ * 8 : size = byte
+ * 16 : size = word
+ * 32 : size = long
+ * rr : register to register
+ * mm : memory to memory
+ * r : register
+ * s : static
+ * er : effective address -> register
+ * re : register -> effective address
+ * ea : using effective address mode of operation
+ * d : data register direct
+ * a : address register direct
+ * ai : address register indirect
+ * pi : address register indirect with postincrement
+ * pd : address register indirect with predecrement
+ * di : address register indirect with displacement
+ * ix : address register indirect with index
+ * aw : absolute word
+ * al : absolute long
+ */
+
+static void d68000_illegal(void)
+{
+ sprintf(g_dasm_str, "dc.w $%04x; ILLEGAL", g_cpu_ir);
+}
+
+static void d68000_1010(void)
+{
+ sprintf(g_dasm_str, "dc.w $%04x; opcode 1010", g_cpu_ir);
+}
+
+
+static void d68000_1111(void)
+{
+ sprintf(g_dasm_str, "dc.w $%04x; opcode 1111", g_cpu_ir);
+}
+
+
+static void d68000_abcd_rr(void)
+{
+ sprintf(g_dasm_str, "abcd D%d, D%d", g_cpu_ir&7, (g_cpu_ir>>9)&7);
+}
+
+
+static void d68000_abcd_mm(void)
+{
+ sprintf(g_dasm_str, "abcd -(A%d), -(A%d)", g_cpu_ir&7, (g_cpu_ir>>9)&7);
+}
+
+static void d68000_add_er_8(void)
+{
+ sprintf(g_dasm_str, "add.b %s, D%d", get_ea_mode_str_8(g_cpu_ir), (g_cpu_ir>>9)&7);
+}
+
+
+static void d68000_add_er_16(void)
+{
+ sprintf(g_dasm_str, "add.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7);
+}
+
+static void d68000_add_er_32(void)
+{
+ sprintf(g_dasm_str, "add.l %s, D%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7);
+}
+
+static void d68000_add_re_8(void)
+{
+ sprintf(g_dasm_str, "add.b D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir));
+}
+
+static void d68000_add_re_16(void)
+{
+ sprintf(g_dasm_str, "add.w D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_16(g_cpu_ir));
+}
+
+static void d68000_add_re_32(void)
+{
+ sprintf(g_dasm_str, "add.l D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_32(g_cpu_ir));
+}
+
+static void d68000_adda_16(void)
+{
+ sprintf(g_dasm_str, "adda.w %s, A%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7);
+}
+
+static void d68000_adda_32(void)
+{
+ sprintf(g_dasm_str, "adda.l %s, A%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7);
+}
+
+static void d68000_addi_8(void)
+{
+ char* str = get_imm_str_s8();
+ sprintf(g_dasm_str, "addi.b %s, %s", str, get_ea_mode_str_8(g_cpu_ir));
+}
+
+static void d68000_addi_16(void)
+{
+ char* str = get_imm_str_s16();
+ sprintf(g_dasm_str, "addi.w %s, %s", str, get_ea_mode_str_16(g_cpu_ir));
+}
+
+static void d68000_addi_32(void)
+{
+ char* str = get_imm_str_s32();
+ sprintf(g_dasm_str, "addi.l %s, %s", str, get_ea_mode_str_32(g_cpu_ir));
+}
+
+static void d68000_addq_8(void)
+{
+ sprintf(g_dasm_str, "addq.b #%d, %s", g_3bit_qdata_table[(g_cpu_ir>>9)&7], get_ea_mode_str_8(g_cpu_ir));
+}
+
+static void d68000_addq_16(void)
+{
+ sprintf(g_dasm_str, "addq.w #%d, %s", g_3bit_qdata_table[(g_cpu_ir>>9)&7], get_ea_mode_str_16(g_cpu_ir));
+}
+
+static void d68000_addq_32(void)
+{
+ sprintf(g_dasm_str, "addq.l #%d, %s", g_3bit_qdata_table[(g_cpu_ir>>9)&7], get_ea_mode_str_32(g_cpu_ir));
+}
+
+static void d68000_addx_rr_8(void)
+{
+ sprintf(g_dasm_str, "addx.b D%d, D%d", g_cpu_ir&7, (g_cpu_ir>>9)&7);
+}
+
+static void d68000_addx_rr_16(void)
+{
+ sprintf(g_dasm_str, "addx.w D%d, D%d", g_cpu_ir&7, (g_cpu_ir>>9)&7);
+}
+
+static void d68000_addx_rr_32(void)
+{
+ sprintf(g_dasm_str, "addx.l D%d, D%d", g_cpu_ir&7, (g_cpu_ir>>9)&7);
+}
+
+static void d68000_addx_mm_8(void)
+{
+ sprintf(g_dasm_str, "addx.b -(A%d), -(A%d)", g_cpu_ir&7, (g_cpu_ir>>9)&7);
+}
+
+static void d68000_addx_mm_16(void)
+{
+ sprintf(g_dasm_str, "addx.w -(A%d), -(A%d)", g_cpu_ir&7, (g_cpu_ir>>9)&7);
+}
+
+static void d68000_addx_mm_32(void)
+{
+ sprintf(g_dasm_str, "addx.l -(A%d), -(A%d)", g_cpu_ir&7, (g_cpu_ir>>9)&7);
+}
+
+static void d68000_and_er_8(void)
+{
+ sprintf(g_dasm_str, "and.b %s, D%d", get_ea_mode_str_8(g_cpu_ir), (g_cpu_ir>>9)&7);
+}
+
+static void d68000_and_er_16(void)
+{
+ sprintf(g_dasm_str, "and.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7);
+}
+
+static void d68000_and_er_32(void)
+{
+ sprintf(g_dasm_str, "and.l %s, D%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7);
+}
+
+static void d68000_and_re_8(void)
+{
+ sprintf(g_dasm_str, "and.b D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir));
+}
+
+static void d68000_and_re_16(void)
+{
+ sprintf(g_dasm_str, "and.w D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_16(g_cpu_ir));
+}
+
+static void d68000_and_re_32(void)
+{
+ sprintf(g_dasm_str, "and.l D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_32(g_cpu_ir));
+}
+
+static void d68000_andi_8(void)
+{
+ char* str = get_imm_str_u8();
+ sprintf(g_dasm_str, "andi.b %s, %s", str, get_ea_mode_str_8(g_cpu_ir));
+}
+
+static void d68000_andi_16(void)
+{
+ char* str = get_imm_str_u16();
+ sprintf(g_dasm_str, "andi.w %s, %s", str, get_ea_mode_str_16(g_cpu_ir));
+}
+
+static void d68000_andi_32(void)
+{
+ char* str = get_imm_str_u32();
+ sprintf(g_dasm_str, "andi.l %s, %s", str, get_ea_mode_str_32(g_cpu_ir));
+}
+
+static void d68000_andi_to_ccr(void)
+{
+ sprintf(g_dasm_str, "andi %s, CCR", get_imm_str_u8());
+}
+
+static void d68000_andi_to_sr(void)
+{
+ sprintf(g_dasm_str, "andi %s, SR", get_imm_str_u16());
+}
+
+static void d68000_asr_s_8(void)
+{
+ sprintf(g_dasm_str, "asr.b #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7);
+}
+
+static void d68000_asr_s_16(void)
+{
+ sprintf(g_dasm_str, "asr.w #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7);
+}
+
+static void d68000_asr_s_32(void)
+{
+ sprintf(g_dasm_str, "asr.l #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7);
+}
+
+static void d68000_asr_r_8(void)
+{
+ sprintf(g_dasm_str, "asr.b D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7);
+}
+
+static void d68000_asr_r_16(void)
+{
+ sprintf(g_dasm_str, "asr.w D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7);
+}
+
+static void d68000_asr_r_32(void)
+{
+ sprintf(g_dasm_str, "asr.l D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7);
+}
+
+static void d68000_asr_ea(void)
+{
+ sprintf(g_dasm_str, "asr.w %s", get_ea_mode_str_16(g_cpu_ir));
+}
+
+static void d68000_asl_s_8(void)
+{
+ sprintf(g_dasm_str, "asl.b #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7);
+}
+
+static void d68000_asl_s_16(void)
+{
+ sprintf(g_dasm_str, "asl.w #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7);
+}
+
+static void d68000_asl_s_32(void)
+{
+ sprintf(g_dasm_str, "asl.l #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7);
+}
+
+static void d68000_asl_r_8(void)
+{
+ sprintf(g_dasm_str, "asl.b D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7);
+}
+
+static void d68000_asl_r_16(void)
+{
+ sprintf(g_dasm_str, "asl.w D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7);
+}
+
+static void d68000_asl_r_32(void)
+{
+ sprintf(g_dasm_str, "asl.l D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7);
+}
+
+static void d68000_asl_ea(void)
+{
+ sprintf(g_dasm_str, "asl.w %s", get_ea_mode_str_16(g_cpu_ir));
+}
+
+static void d68000_bcc_8(void)
+{
+ UINT32 temp_pc = g_cpu_pc;
+ sprintf(g_dasm_str, "b%-2s $%x", g_cc[(g_cpu_ir>>8)&0xf], temp_pc + make_int_8(g_cpu_ir));
+}
+
+static void d68000_bcc_16(void)
+{
+ UINT32 temp_pc = g_cpu_pc;
+ sprintf(g_dasm_str, "b%-2s $%x", g_cc[(g_cpu_ir>>8)&0xf], temp_pc + make_int_16(read_imm_16()));
+}
+
+static void d68020_bcc_32(void)
+{
+ UINT32 temp_pc = g_cpu_pc;
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ sprintf(g_dasm_str, "b%-2s $%x; (2+)", g_cc[(g_cpu_ir>>8)&0xf], temp_pc + read_imm_32());
+}
+
+static void d68000_bchg_r(void)
+{
+ sprintf(g_dasm_str, "bchg D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir));
+}
+
+static void d68000_bchg_s(void)
+{
+ char* str = get_imm_str_u8();
+ sprintf(g_dasm_str, "bchg %s, %s", str, get_ea_mode_str_8(g_cpu_ir));
+}
+
+static void d68000_bclr_r(void)
+{
+ sprintf(g_dasm_str, "bclr D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir));
+}
+
+static void d68000_bclr_s(void)
+{
+ char* str = get_imm_str_u8();
+ sprintf(g_dasm_str, "bclr %s, %s", str, get_ea_mode_str_8(g_cpu_ir));
+}
+
+static void d68010_bkpt(void)
+{
+ LIMIT_CPU_TYPES(M68010_PLUS);
+ sprintf(g_dasm_str, "bkpt #%d; (1+)", g_cpu_ir&7);
+}
+
+static void d68020_bfchg(void)
+{
+ UINT32 extension;
+ char offset[3];
+ char width[3];
+
+ LIMIT_CPU_TYPES(M68020_PLUS);
+
+ extension = read_imm_16();
+
+ if(BIT_B(extension))
+ sprintf(offset, "D%d", (extension>>6)&7);
+ else
+ sprintf(offset, "%d", (extension>>6)&31);
+ if(BIT_5(extension))
+ sprintf(width, "D%d", extension&7);
+ else
+ sprintf(width, "%d", g_5bit_data_table[extension&31]);
+ sprintf(g_dasm_str, "bfchg %s {%s:%s}; (2+)", get_ea_mode_str_8(g_cpu_ir), offset, width);
+}
+
+static void d68020_bfclr(void)
+{
+ UINT32 extension;
+ char offset[3];
+ char width[3];
+
+ LIMIT_CPU_TYPES(M68020_PLUS);
+
+ extension = read_imm_16();
+
+ if(BIT_B(extension))
+ sprintf(offset, "D%d", (extension>>6)&7);
+ else
+ sprintf(offset, "%d", (extension>>6)&31);
+ if(BIT_5(extension))
+ sprintf(width, "D%d", extension&7);
+ else
+ sprintf(width, "%d", g_5bit_data_table[extension&31]);
+ sprintf(g_dasm_str, "bfclr %s {%s:%s}; (2+)", get_ea_mode_str_8(g_cpu_ir), offset, width);
+}
+
+static void d68020_bfexts(void)
+{
+ UINT32 extension;
+ char offset[3];
+ char width[3];
+
+ LIMIT_CPU_TYPES(M68020_PLUS);
+
+ extension = read_imm_16();
+
+ if(BIT_B(extension))
+ sprintf(offset, "D%d", (extension>>6)&7);
+ else
+ sprintf(offset, "%d", (extension>>6)&31);
+ if(BIT_5(extension))
+ sprintf(width, "D%d", extension&7);
+ else
+ sprintf(width, "%d", g_5bit_data_table[extension&31]);
+ sprintf(g_dasm_str, "bfexts D%d, %s {%s:%s}; (2+)", (extension>>12)&7, get_ea_mode_str_8(g_cpu_ir), offset, width);
+}
+
+static void d68020_bfextu(void)
+{
+ UINT32 extension;
+ char offset[3];
+ char width[3];
+
+ LIMIT_CPU_TYPES(M68020_PLUS);
+
+ extension = read_imm_16();
+
+ if(BIT_B(extension))
+ sprintf(offset, "D%d", (extension>>6)&7);
+ else
+ sprintf(offset, "%d", (extension>>6)&31);
+ if(BIT_5(extension))
+ sprintf(width, "D%d", extension&7);
+ else
+ sprintf(width, "%d", g_5bit_data_table[extension&31]);
+ sprintf(g_dasm_str, "bfextu D%d, %s {%s:%s}; (2+)", (extension>>12)&7, get_ea_mode_str_8(g_cpu_ir), offset, width);
+}
+
+static void d68020_bfffo(void)
+{
+ UINT32 extension;
+ char offset[3];
+ char width[3];
+
+ LIMIT_CPU_TYPES(M68020_PLUS);
+
+ extension = read_imm_16();
+
+ if(BIT_B(extension))
+ sprintf(offset, "D%d", (extension>>6)&7);
+ else
+ sprintf(offset, "%d", (extension>>6)&31);
+ if(BIT_5(extension))
+ sprintf(width, "D%d", extension&7);
+ else
+ sprintf(width, "%d", g_5bit_data_table[extension&31]);
+ sprintf(g_dasm_str, "bfffo D%d, %s {%s:%s}; (2+)", (extension>>12)&7, get_ea_mode_str_8(g_cpu_ir), offset, width);
+}
+
+static void d68020_bfins(void)
+{
+ UINT32 extension;
+ char offset[3];
+ char width[3];
+
+ LIMIT_CPU_TYPES(M68020_PLUS);
+
+ extension = read_imm_16();
+
+ if(BIT_B(extension))
+ sprintf(offset, "D%d", (extension>>6)&7);
+ else
+ sprintf(offset, "%d", (extension>>6)&31);
+ if(BIT_5(extension))
+ sprintf(width, "D%d", extension&7);
+ else
+ sprintf(width, "%d", g_5bit_data_table[extension&31]);
+ sprintf(g_dasm_str, "bfins D%d, %s {%s:%s}; (2+)", (extension>>12)&7, get_ea_mode_str_8(g_cpu_ir), offset, width);
+}
+
+static void d68020_bfset(void)
+{
+ UINT32 extension;
+ char offset[3];
+ char width[3];
+
+ LIMIT_CPU_TYPES(M68020_PLUS);
+
+ extension = read_imm_16();
+
+ if(BIT_B(extension))
+ sprintf(offset, "D%d", (extension>>6)&7);
+ else
+ sprintf(offset, "%d", (extension>>6)&31);
+ if(BIT_5(extension))
+ sprintf(width, "D%d", extension&7);
+ else
+ sprintf(width, "%d", g_5bit_data_table[extension&31]);
+ sprintf(g_dasm_str, "bfset %s {%s:%s}; (2+)", get_ea_mode_str_8(g_cpu_ir), offset, width);
+}
+
+static void d68020_bftst(void)
+{
+ UINT32 extension;
+ char offset[3];
+ char width[3];
+
+ LIMIT_CPU_TYPES(M68020_PLUS);
+
+ extension = read_imm_16();
+
+ if(BIT_B(extension))
+ sprintf(offset, "D%d", (extension>>6)&7);
+ else
+ sprintf(offset, "%d", (extension>>6)&31);
+ if(BIT_5(extension))
+ sprintf(width, "D%d", extension&7);
+ else
+ sprintf(width, "%d", g_5bit_data_table[extension&31]);
+ sprintf(g_dasm_str, "bftst %s {%s:%s}; (2+)", get_ea_mode_str_8(g_cpu_ir), offset, width);
+}
+
+static void d68000_bra_8(void)
+{
+ UINT32 temp_pc = g_cpu_pc;
+ sprintf(g_dasm_str, "bra $%x", temp_pc + make_int_8(g_cpu_ir));
+}
+
+static void d68000_bra_16(void)
+{
+ UINT32 temp_pc = g_cpu_pc;
+ sprintf(g_dasm_str, "bra $%x", temp_pc + make_int_16(read_imm_16()));
+}
+
+static void d68020_bra_32(void)
+{
+ UINT32 temp_pc = g_cpu_pc;
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ sprintf(g_dasm_str, "bra $%x; (2+)", temp_pc + read_imm_32());
+}
+
+static void d68000_bset_r(void)
+{
+ sprintf(g_dasm_str, "bset D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir));
+}
+
+static void d68000_bset_s(void)
+{
+ char* str = get_imm_str_u8();
+ sprintf(g_dasm_str, "bset %s, %s", str, get_ea_mode_str_8(g_cpu_ir));
+}
+
+static void d68000_bsr_8(void)
+{
+ UINT32 temp_pc = g_cpu_pc;
+ sprintf(g_dasm_str, "bsr $%x", temp_pc + make_int_8(g_cpu_ir));
+ SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER);
+}
+
+static void d68000_bsr_16(void)
+{
+ UINT32 temp_pc = g_cpu_pc;
+ sprintf(g_dasm_str, "bsr $%x", temp_pc + make_int_16(read_imm_16()));
+ SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER);
+}
+
+static void d68020_bsr_32(void)
+{
+ UINT32 temp_pc = g_cpu_pc;
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ sprintf(g_dasm_str, "bsr $%x; (2+)", temp_pc + read_imm_32());
+ SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER);
+}
+
+static void d68000_btst_r(void)
+{
+ sprintf(g_dasm_str, "btst D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir));
+}
+
+static void d68000_btst_s(void)
+{
+ char* str = get_imm_str_u8();
+ sprintf(g_dasm_str, "btst %s, %s", str, get_ea_mode_str_8(g_cpu_ir));
+}
+
+static void d68020_callm(void)
+{
+ char* str;
+ LIMIT_CPU_TYPES(M68020_ONLY);
+ str = get_imm_str_u8();
+
+ sprintf(g_dasm_str, "callm %s, %s; (2)", str, get_ea_mode_str_8(g_cpu_ir));
+}
+
+static void d68020_cas_8(void)
+{
+ UINT32 extension;
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ extension = read_imm_16();
+ sprintf(g_dasm_str, "cas.b D%d, D%d, %s; (2+)", extension&7, (extension>>8)&7, get_ea_mode_str_8(g_cpu_ir));
+}
+
+static void d68020_cas_16(void)
+{
+ UINT32 extension;
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ extension = read_imm_16();
+ sprintf(g_dasm_str, "cas.w D%d, D%d, %s; (2+)", extension&7, (extension>>8)&7, get_ea_mode_str_16(g_cpu_ir));
+}
+
+static void d68020_cas_32(void)
+{
+ UINT32 extension;
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ extension = read_imm_16();
+ sprintf(g_dasm_str, "cas.l D%d, D%d, %s; (2+)", extension&7, (extension>>8)&7, get_ea_mode_str_32(g_cpu_ir));
+}
+
+static void d68020_cas2_16(void)
+{
+/* CAS2 Dc1:Dc2,Du1:Dc2:(Rn1):(Rn2)
+f e d c b a 9 8 7 6 5 4 3 2 1 0
+ DARn1 0 0 0 Du1 0 0 0 Dc1
+ DARn2 0 0 0 Du2 0 0 0 Dc2
+*/
+
+ UINT32 extension;
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ extension = read_imm_32();
+ sprintf(g_dasm_str, "cas2.w D%d:D%d:D%d:D%d, (%c%d):(%c%d); (2+)",
+ (extension>>16)&7, extension&7, (extension>>22)&7, (extension>>6)&7,
+ BIT_1F(extension) ? 'A' : 'D', (extension>>28)&7,
+ BIT_F(extension) ? 'A' : 'D', (extension>>12)&7);
+}
+
+static void d68020_cas2_32(void)
+{
+ UINT32 extension;
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ extension = read_imm_32();
+ sprintf(g_dasm_str, "cas2.l D%d:D%d:D%d:D%d, (%c%d):(%c%d); (2+)",
+ (extension>>16)&7, extension&7, (extension>>22)&7, (extension>>6)&7,
+ BIT_1F(extension) ? 'A' : 'D', (extension>>28)&7,
+ BIT_F(extension) ? 'A' : 'D', (extension>>12)&7);
+}
+
+static void d68000_chk_16(void)
+{
+ sprintf(g_dasm_str, "chk.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7);
+ SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER);
+}
+
+static void d68020_chk_32(void)
+{
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ sprintf(g_dasm_str, "chk.l %s, D%d; (2+)", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7);
+ SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER);
+}
+
+static void d68020_chk2_cmp2_8(void)
+{
+ UINT32 extension;
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ extension = read_imm_16();
+ sprintf(g_dasm_str, "%s.b %s, %c%d; (2+)", BIT_B(extension) ? "chk2" : "cmp2", get_ea_mode_str_8(g_cpu_ir), BIT_F(extension) ? 'A' : 'D', (extension>>12)&7);
+}
+
+static void d68020_chk2_cmp2_16(void)
+{
+ UINT32 extension;
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ extension = read_imm_16();
+ sprintf(g_dasm_str, "%s.w %s, %c%d; (2+)", BIT_B(extension) ? "chk2" : "cmp2", get_ea_mode_str_16(g_cpu_ir), BIT_F(extension) ? 'A' : 'D', (extension>>12)&7);
+}
+
+static void d68020_chk2_cmp2_32(void)
+{
+ UINT32 extension;
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ extension = read_imm_16();
+ sprintf(g_dasm_str, "%s.l %s, %c%d; (2+)", BIT_B(extension) ? "chk2" : "cmp2", get_ea_mode_str_32(g_cpu_ir), BIT_F(extension) ? 'A' : 'D', (extension>>12)&7);
+}
+
+static void d68040_cinv(void)
+{
+ LIMIT_CPU_TYPES(M68040_PLUS);
+ switch((g_cpu_ir>>3)&3)
+ {
+ static const char *cachetype[4] = { "nop", "data", "inst", "both" };
+
+ case 0:
+ sprintf(g_dasm_str, "cinv (illegal scope); (4)");
+ break;
+ case 1:
+ sprintf(g_dasm_str, "cinvl %s, (A%d); (4)", cachetype[(g_cpu_ir>>6)&3], g_cpu_ir&7);
+ break;
+ case 2:
+ sprintf(g_dasm_str, "cinvp %s, (A%d); (4)", cachetype[(g_cpu_ir>>6)&3], g_cpu_ir&7);
+ break;
+ case 3:
+ sprintf(g_dasm_str, "cinva %s; (4)", cachetype[(g_cpu_ir>>6)&3]);
+ break;
+ }
+}
+
+static void d68000_clr_8(void)
+{
+ sprintf(g_dasm_str, "clr.b %s", get_ea_mode_str_8(g_cpu_ir));
+}
+
+static void d68000_clr_16(void)
+{
+ sprintf(g_dasm_str, "clr.w %s", get_ea_mode_str_16(g_cpu_ir));
+}
+
+static void d68000_clr_32(void)
+{
+ sprintf(g_dasm_str, "clr.l %s", get_ea_mode_str_32(g_cpu_ir));
+}
+
+static void d68000_cmp_8(void)
+{
+ sprintf(g_dasm_str, "cmp.b %s, D%d", get_ea_mode_str_8(g_cpu_ir), (g_cpu_ir>>9)&7);
+}
+
+static void d68000_cmp_16(void)
+{
+ sprintf(g_dasm_str, "cmp.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7);
+}
+
+static void d68000_cmp_32(void)
+{
+ sprintf(g_dasm_str, "cmp.l %s, D%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7);
+}
+
+static void d68000_cmpa_16(void)
+{
+ sprintf(g_dasm_str, "cmpa.w %s, A%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7);
+}
+
+static void d68000_cmpa_32(void)
+{
+ sprintf(g_dasm_str, "cmpa.l %s, A%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7);
+}
+
+static void d68000_cmpi_8(void)
+{
+ char* str = get_imm_str_s8();
+ sprintf(g_dasm_str, "cmpi.b %s, %s", str, get_ea_mode_str_8(g_cpu_ir));
+}
+
+static void d68020_cmpi_pcdi_8(void)
+{
+ char* str;
+ LIMIT_CPU_TYPES(M68010_PLUS);
+ str = get_imm_str_s8();
+ sprintf(g_dasm_str, "cmpi.b %s, %s; (2+)", str, get_ea_mode_str_8(g_cpu_ir));
+}
+
+static void d68020_cmpi_pcix_8(void)
+{
+ char* str;
+ LIMIT_CPU_TYPES(M68010_PLUS);
+ str = get_imm_str_s8();
+ sprintf(g_dasm_str, "cmpi.b %s, %s; (2+)", str, get_ea_mode_str_8(g_cpu_ir));
+}
+
+static void d68000_cmpi_16(void)
+{
+ char* str;
+ str = get_imm_str_s16();
+ sprintf(g_dasm_str, "cmpi.w %s, %s", str, get_ea_mode_str_16(g_cpu_ir));
+}
+
+static void d68020_cmpi_pcdi_16(void)
+{
+ char* str;
+ LIMIT_CPU_TYPES(M68010_PLUS);
+ str = get_imm_str_s16();
+ sprintf(g_dasm_str, "cmpi.w %s, %s; (2+)", str, get_ea_mode_str_16(g_cpu_ir));
+}
+
+static void d68020_cmpi_pcix_16(void)
+{
+ char* str;
+ LIMIT_CPU_TYPES(M68010_PLUS);
+ str = get_imm_str_s16();
+ sprintf(g_dasm_str, "cmpi.w %s, %s; (2+)", str, get_ea_mode_str_16(g_cpu_ir));
+}
+
+static void d68000_cmpi_32(void)
+{
+ char* str;
+ str = get_imm_str_s32();
+ sprintf(g_dasm_str, "cmpi.l %s, %s", str, get_ea_mode_str_32(g_cpu_ir));
+}
+
+static void d68020_cmpi_pcdi_32(void)
+{
+ char* str;
+ LIMIT_CPU_TYPES(M68010_PLUS);
+ str = get_imm_str_s32();
+ sprintf(g_dasm_str, "cmpi.l %s, %s; (2+)", str, get_ea_mode_str_32(g_cpu_ir));
+}
+
+static void d68020_cmpi_pcix_32(void)
+{
+ char* str;
+ LIMIT_CPU_TYPES(M68010_PLUS);
+ str = get_imm_str_s32();
+ sprintf(g_dasm_str, "cmpi.l %s, %s; (2+)", str, get_ea_mode_str_32(g_cpu_ir));
+}
+
+static void d68000_cmpm_8(void)
+{
+ sprintf(g_dasm_str, "cmpm.b (A%d)+, (A%d)+", g_cpu_ir&7, (g_cpu_ir>>9)&7);
+}
+
+static void d68000_cmpm_16(void)
+{
+ sprintf(g_dasm_str, "cmpm.w (A%d)+, (A%d)+", g_cpu_ir&7, (g_cpu_ir>>9)&7);
+}
+
+static void d68000_cmpm_32(void)
+{
+ sprintf(g_dasm_str, "cmpm.l (A%d)+, (A%d)+", g_cpu_ir&7, (g_cpu_ir>>9)&7);
+}
+
+static void d68020_cpbcc_16(void)
+{
+ UINT32 extension;
+ UINT32 new_pc = g_cpu_pc;
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ extension = read_imm_16();
+ new_pc += make_int_16(read_imm_16());
+ sprintf(g_dasm_str, "%db%-4s %s; %x (extension = %x) (2-3)", (g_cpu_ir>>9)&7, g_cpcc[g_cpu_ir&0x3f], get_imm_str_s16(), new_pc, extension);
+}
+
+static void d68020_cpbcc_32(void)
+{
+ UINT32 extension;
+ UINT32 new_pc = g_cpu_pc;
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ extension = read_imm_16();
+ new_pc += read_imm_32();
+ sprintf(g_dasm_str, "%db%-4s %s; %x (extension = %x) (2-3)", (g_cpu_ir>>9)&7, g_cpcc[g_cpu_ir&0x3f], get_imm_str_s16(), new_pc, extension);
+}
+
+static void d68020_cpdbcc(void)
+{
+ UINT32 extension1;
+ UINT32 extension2;
+ UINT32 new_pc = g_cpu_pc;
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ extension1 = read_imm_16();
+ extension2 = read_imm_16();
+ new_pc += make_int_16(read_imm_16());
+ sprintf(g_dasm_str, "%ddb%-4s D%d,%s; %x (extension = %x) (2-3)", (g_cpu_ir>>9)&7, g_cpcc[extension1&0x3f], g_cpu_ir&7, get_imm_str_s16(), new_pc, extension2);
+}
+
+static void d68020_cpgen(void)
+{
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ sprintf(g_dasm_str, "%dgen %s; (2-3)", (g_cpu_ir>>9)&7, get_imm_str_u32());
+}
+
+static void d68020_cprestore(void)
+{
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ if (((g_cpu_ir>>9)&7) == 1)
+ {
+ sprintf(g_dasm_str, "frestore %s", get_ea_mode_str_8(g_cpu_ir));
+ }
+ else
+ {
+ sprintf(g_dasm_str, "%drestore %s; (2-3)", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir));
+ }
+}
+
+static void d68020_cpsave(void)
+{
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ if (((g_cpu_ir>>9)&7) == 1)
+ {
+ sprintf(g_dasm_str, "fsave %s", get_ea_mode_str_8(g_cpu_ir));
+ }
+ else
+ {
+ sprintf(g_dasm_str, "%dsave %s; (2-3)", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir));
+ }
+}
+
+static void d68020_cpscc(void)
+{
+ UINT32 extension1;
+ UINT32 extension2;
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ extension1 = read_imm_16();
+ extension2 = read_imm_16();
+ sprintf(g_dasm_str, "%ds%-4s %s; (extension = %x) (2-3)", (g_cpu_ir>>9)&7, g_cpcc[extension1&0x3f], get_ea_mode_str_8(g_cpu_ir), extension2);
+}
+
+static void d68020_cptrapcc_0(void)
+{
+ UINT32 extension1;
+ UINT32 extension2;
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ extension1 = read_imm_16();
+ extension2 = read_imm_16();
+ sprintf(g_dasm_str, "%dtrap%-4s; (extension = %x) (2-3)", (g_cpu_ir>>9)&7, g_cpcc[extension1&0x3f], extension2);
+}
+
+static void d68020_cptrapcc_16(void)
+{
+ UINT32 extension1;
+ UINT32 extension2;
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ extension1 = read_imm_16();
+ extension2 = read_imm_16();
+ sprintf(g_dasm_str, "%dtrap%-4s %s; (extension = %x) (2-3)", (g_cpu_ir>>9)&7, g_cpcc[extension1&0x3f], get_imm_str_u16(), extension2);
+}
+
+static void d68020_cptrapcc_32(void)
+{
+ UINT32 extension1;
+ UINT32 extension2;
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ extension1 = read_imm_16();
+ extension2 = read_imm_16();
+ sprintf(g_dasm_str, "%dtrap%-4s %s; (extension = %x) (2-3)", (g_cpu_ir>>9)&7, g_cpcc[extension1&0x3f], get_imm_str_u32(), extension2);
+}
+
+static void d68040_cpush(void)
+{
+ static const char *cachetype[4] = { "nop", "data", "inst", "both" };
+
+ LIMIT_CPU_TYPES(M68040_PLUS);
+ switch((g_cpu_ir>>3)&3)
+ {
+ case 0:
+ sprintf(g_dasm_str, "cpush (illegal scope); (4)");
+ break;
+ case 1:
+ sprintf(g_dasm_str, "cpushl %s, (A%d); (4)", cachetype[(g_cpu_ir>>6)&3], g_cpu_ir&7);
+ break;
+ case 2:
+ sprintf(g_dasm_str, "cpushp %s, (A%d); (4)", cachetype[(g_cpu_ir>>6)&3], g_cpu_ir&7);
+ break;
+ case 3:
+ sprintf(g_dasm_str, "cpusha %s; (4)", cachetype[(g_cpu_ir>>6)&3]);
+ break;
+ }
+}
+
+static void d68000_dbra(void)
+{
+ UINT32 temp_pc = g_cpu_pc;
+ sprintf(g_dasm_str, "dbra D%d, $%x", g_cpu_ir & 7, temp_pc + make_int_16(read_imm_16()));
+ SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER);
+}
+
+static void d68000_dbcc(void)
+{
+ UINT32 temp_pc = g_cpu_pc;
+ sprintf(g_dasm_str, "db%-2s D%d, $%x", g_cc[(g_cpu_ir>>8)&0xf], g_cpu_ir & 7, temp_pc + make_int_16(read_imm_16()));
+ SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER);
+}
+
+static void d68000_divs(void)
+{
+ sprintf(g_dasm_str, "divs.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7);
+}
+
+static void d68000_divu(void)
+{
+ sprintf(g_dasm_str, "divu.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7);
+}
+
+static void d68020_divl(void)
+{
+ UINT32 extension;
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ extension = read_imm_16();
+
+ if(BIT_A(extension))
+ sprintf(g_dasm_str, "div%c.l %s, D%d:D%d; (2+)", BIT_B(extension) ? 's' : 'u', get_ea_mode_str_32(g_cpu_ir), extension&7, (extension>>12)&7);
+ else if((extension&7) == ((extension>>12)&7))
+ sprintf(g_dasm_str, "div%c.l %s, D%d; (2+)", BIT_B(extension) ? 's' : 'u', get_ea_mode_str_32(g_cpu_ir), (extension>>12)&7);
+ else
+ sprintf(g_dasm_str, "div%cl.l %s, D%d:D%d; (2+)", BIT_B(extension) ? 's' : 'u', get_ea_mode_str_32(g_cpu_ir), extension&7, (extension>>12)&7);
+}
+
+static void d68000_eor_8(void)
+{
+ sprintf(g_dasm_str, "eor.b D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir));
+}
+
+static void d68000_eor_16(void)
+{
+ sprintf(g_dasm_str, "eor.w D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_16(g_cpu_ir));
+}
+
+static void d68000_eor_32(void)
+{
+ sprintf(g_dasm_str, "eor.l D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_32(g_cpu_ir));
+}
+
+static void d68000_eori_8(void)
+{
+ char* str = get_imm_str_u8();
+ sprintf(g_dasm_str, "eori.b %s, %s", str, get_ea_mode_str_8(g_cpu_ir));
+}
+
+static void d68000_eori_16(void)
+{
+ char* str = get_imm_str_u16();
+ sprintf(g_dasm_str, "eori.w %s, %s", str, get_ea_mode_str_16(g_cpu_ir));
+}
+
+static void d68000_eori_32(void)
+{
+ char* str = get_imm_str_u32();
+ sprintf(g_dasm_str, "eori.l %s, %s", str, get_ea_mode_str_32(g_cpu_ir));
+}
+
+static void d68000_eori_to_ccr(void)
+{
+ sprintf(g_dasm_str, "eori %s, CCR", get_imm_str_u8());
+}
+
+static void d68000_eori_to_sr(void)
+{
+ sprintf(g_dasm_str, "eori %s, SR", get_imm_str_u16());
+}
+
+static void d68000_exg_dd(void)
+{
+ sprintf(g_dasm_str, "exg D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7);
+}
+
+static void d68000_exg_aa(void)
+{
+ sprintf(g_dasm_str, "exg A%d, A%d", (g_cpu_ir>>9)&7, g_cpu_ir&7);
+}
+
+static void d68000_exg_da(void)
+{
+ sprintf(g_dasm_str, "exg D%d, A%d", (g_cpu_ir>>9)&7, g_cpu_ir&7);
+}
+
+static void d68000_ext_16(void)
+{
+ sprintf(g_dasm_str, "ext.w D%d", g_cpu_ir&7);
+}
+
+static void d68000_ext_32(void)
+{
+ sprintf(g_dasm_str, "ext.l D%d", g_cpu_ir&7);
+}
+
+static void d68020_extb_32(void)
+{
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ sprintf(g_dasm_str, "extb.l D%d; (2+)", g_cpu_ir&7);
+}
+
+static void d68040_fpu(void)
+{
+ char float_data_format[8][3] =
+ {
+ ".l", ".s", ".x", ".p", ".w", ".d", ".b", ".p"
+ };
+
+ char mnemonic[40];
+ UINT32 w2, src, dst_reg;
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ w2 = read_imm_16();
+
+ src = (w2 >> 10) & 0x7;
+ dst_reg = (w2 >> 7) & 0x7;
+
+ // special override for FMOVECR
+ if ((((w2 >> 13) & 0x7) == 2) && (((w2>>10)&0x7) == 7))
+ {
+ sprintf(g_dasm_str, "fmovecr #$%0x, fp%d", (w2&0x7f), dst_reg);
+ return;
+ }
+
+ switch ((w2 >> 13) & 0x7)
+ {
+ case 0x0:
+ case 0x2:
+ {
+ switch(w2 & 0x7f)
+ {
+ case 0x00: sprintf(mnemonic, "fmove"); break;
+ case 0x01: sprintf(mnemonic, "fint"); break;
+ case 0x02: sprintf(mnemonic, "fsinh"); break;
+ case 0x03: sprintf(mnemonic, "fintrz"); break;
+ case 0x04: sprintf(mnemonic, "fsqrt"); break;
+ case 0x06: sprintf(mnemonic, "flognp1"); break;
+ case 0x08: sprintf(mnemonic, "fetoxm1"); break;
+ case 0x09: sprintf(mnemonic, "ftanh1"); break;
+ case 0x0a: sprintf(mnemonic, "fatan"); break;
+ case 0x0c: sprintf(mnemonic, "fasin"); break;
+ case 0x0d: sprintf(mnemonic, "fatanh"); break;
+ case 0x0e: sprintf(mnemonic, "fsin"); break;
+ case 0x0f: sprintf(mnemonic, "ftan"); break;
+ case 0x10: sprintf(mnemonic, "fetox"); break;
+ case 0x11: sprintf(mnemonic, "ftwotox"); break;
+ case 0x12: sprintf(mnemonic, "ftentox"); break;
+ case 0x14: sprintf(mnemonic, "flogn"); break;
+ case 0x15: sprintf(mnemonic, "flog10"); break;
+ case 0x16: sprintf(mnemonic, "flog2"); break;
+ case 0x18: sprintf(mnemonic, "fabs"); break;
+ case 0x19: sprintf(mnemonic, "fcosh"); break;
+ case 0x1a: sprintf(mnemonic, "fneg"); break;
+ case 0x1c: sprintf(mnemonic, "facos"); break;
+ case 0x1d: sprintf(mnemonic, "fcos"); break;
+ case 0x1e: sprintf(mnemonic, "fgetexp"); break;
+ case 0x1f: sprintf(mnemonic, "fgetman"); break;
+ case 0x20: sprintf(mnemonic, "fdiv"); break;
+ case 0x21: sprintf(mnemonic, "fmod"); break;
+ case 0x22: sprintf(mnemonic, "fadd"); break;
+ case 0x23: sprintf(mnemonic, "fmul"); break;
+ case 0x24: sprintf(mnemonic, "fsgldiv"); break;
+ case 0x25: sprintf(mnemonic, "frem"); break;
+ case 0x26: sprintf(mnemonic, "fscale"); break;
+ case 0x27: sprintf(mnemonic, "fsglmul"); break;
+ case 0x28: sprintf(mnemonic, "fsub"); break;
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
+ sprintf(mnemonic, "fsincos"); break;
+ case 0x38: sprintf(mnemonic, "fcmp"); break;
+ case 0x3a: sprintf(mnemonic, "ftst"); break;
+ case 0x41: sprintf(mnemonic, "fssqrt"); break;
+ case 0x45: sprintf(mnemonic, "fdsqrt"); break;
+ case 0x58: sprintf(mnemonic, "fsabs"); break;
+ case 0x5a: sprintf(mnemonic, "fsneg"); break;
+ case 0x5c: sprintf(mnemonic, "fdabs"); break;
+ case 0x5e: sprintf(mnemonic, "fdneg"); break;
+ case 0x60: sprintf(mnemonic, "fsdiv"); break;
+ case 0x62: sprintf(mnemonic, "fsadd"); break;
+ case 0x63: sprintf(mnemonic, "fsmul"); break;
+ case 0x64: sprintf(mnemonic, "fddiv"); break;
+ case 0x66: sprintf(mnemonic, "fdadd"); break;
+ case 0x67: sprintf(mnemonic, "fdmul"); break;
+ case 0x68: sprintf(mnemonic, "fssub"); break;
+ case 0x6c: sprintf(mnemonic, "fdsub"); break;
+
+ default: sprintf(mnemonic, "FPU (?)"); break;
+ }
+
+ if (w2 & 0x4000)
+ {
+ sprintf(g_dasm_str, "%s%s %s, FP%d", mnemonic, float_data_format[src], get_ea_mode_str_32(g_cpu_ir), dst_reg);
+ }
+ else
+ {
+ sprintf(g_dasm_str, "%s.x FP%d, FP%d", mnemonic, src, dst_reg);
+ }
+ break;
+ }
+
+ case 0x3:
+ {
+ switch ((w2>>10)&7)
+ {
+ case 3: // packed decimal w/fixed k-factor
+ sprintf(g_dasm_str, "fmove%s FP%d, %s {#%d}", float_data_format[(w2>>10)&7], dst_reg, get_ea_mode_str_32(g_cpu_ir), sext_7bit_int(w2&0x7f));
+ break;
+
+ case 7: // packed decimal w/dynamic k-factor (register)
+ sprintf(g_dasm_str, "fmove%s FP%d, %s {D%d}", float_data_format[(w2>>10)&7], dst_reg, get_ea_mode_str_32(g_cpu_ir), (w2>>4)&7);
+ break;
+
+ default:
+ sprintf(g_dasm_str, "fmove%s FP%d, %s", float_data_format[(w2>>10)&7], dst_reg, get_ea_mode_str_32(g_cpu_ir));
+ break;
+ }
+ break;
+ }
+
+ case 0x4: // ea to control
+ {
+ sprintf(g_dasm_str, "fmovem.l %s, ", get_ea_mode_str_32(g_cpu_ir));
+ if (w2 & 0x1000) strcat(g_dasm_str, "fpcr");
+ if (w2 & 0x0800) strcat(g_dasm_str, "/fpsr");
+ if (w2 & 0x0400) strcat(g_dasm_str, "/fpiar");
+ break;
+ }
+
+ case 0x5: // control to ea
+ {
+
+ strcpy(g_dasm_str, "fmovem.l ");
+ if (w2 & 0x1000) strcat(g_dasm_str, "fpcr");
+ if (w2 & 0x0800) strcat(g_dasm_str, "/fpsr");
+ if (w2 & 0x0400) strcat(g_dasm_str, "/fpiar");
+ strcat(g_dasm_str, ", ");
+ strcat(g_dasm_str, get_ea_mode_str_32(g_cpu_ir));
+ break;
+ }
+
+ case 0x6: // memory to FPU, list
+ {
+ char temp[32];
+
+ if ((w2>>11) & 1) // dynamic register list
+ {
+ sprintf(g_dasm_str, "fmovem.x %s, D%d", get_ea_mode_str_32(g_cpu_ir), (w2>>4)&7);
+ }
+ else // static register list
+ {
+ int i;
+
+ sprintf(g_dasm_str, "fmovem.x %s, ", get_ea_mode_str_32(g_cpu_ir));
+
+ for (i = 0; i < 8; i++)
+ {
+ if (w2 & (1<<i))
+ {
+ if ((w2>>12) & 1) // postincrement or control
+ {
+ sprintf(temp, "FP%d ", 7-i);
+ }
+ else // predecrement
+ {
+ sprintf(temp, "FP%d ", i);
+ }
+ strcat(g_dasm_str, temp);
+ }
+ }
+ }
+ break;
+ }
+
+ case 0x7: // FPU to memory, list
+ {
+ char temp[32];
+
+ if ((w2>>11) & 1) // dynamic register list
+ {
+ sprintf(g_dasm_str, "fmovem.x D%d, %s", (w2>>4)&7, get_ea_mode_str_32(g_cpu_ir));
+ }
+ else // static register list
+ {
+ int i;
+
+ sprintf(g_dasm_str, "fmovem.x ");
+
+ for (i = 0; i < 8; i++)
+ {
+ if (w2 & (1<<i))
+ {
+ if ((w2>>12) & 1) // postincrement or control
+ {
+ sprintf(temp, "FP%d ", 7-i);
+ }
+ else // predecrement
+ {
+ sprintf(temp, "FP%d ", i);
+ }
+ strcat(g_dasm_str, temp);
+ }
+ }
+
+ strcat(g_dasm_str, ", ");
+ strcat(g_dasm_str, get_ea_mode_str_32(g_cpu_ir));
+ }
+ break;
+ }
+
+ default:
+ {
+ sprintf(g_dasm_str, "FPU (?) ");
+ break;
+ }
+ }
+}
+
+static void d68000_jmp(void)
+{
+ sprintf(g_dasm_str, "jmp %s", get_ea_mode_str_32(g_cpu_ir));
+}
+
+static void d68000_jsr(void)
+{
+ sprintf(g_dasm_str, "jsr %s", get_ea_mode_str_32(g_cpu_ir));
+ SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER);
+}
+
+static void d68000_lea(void)
+{
+ sprintf(g_dasm_str, "lea %s, A%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7);
+}
+
+static void d68000_link_16(void)
+{
+ sprintf(g_dasm_str, "link A%d, %s", g_cpu_ir&7, get_imm_str_s16());
+}
+
+static void d68020_link_32(void)
+{
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ sprintf(g_dasm_str, "link A%d, %s; (2+)", g_cpu_ir&7, get_imm_str_s32());
+}
+
+static void d68000_lsr_s_8(void)
+{
+ sprintf(g_dasm_str, "lsr.b #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7);
+}
+
+static void d68000_lsr_s_16(void)
+{
+ sprintf(g_dasm_str, "lsr.w #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7);
+}
+
+static void d68000_lsr_s_32(void)
+{
+ sprintf(g_dasm_str, "lsr.l #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7);
+}
+
+static void d68000_lsr_r_8(void)
+{
+ sprintf(g_dasm_str, "lsr.b D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7);
+}
+
+static void d68000_lsr_r_16(void)
+{
+ sprintf(g_dasm_str, "lsr.w D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7);
+}
+
+static void d68000_lsr_r_32(void)
+{
+ sprintf(g_dasm_str, "lsr.l D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7);
+}
+
+static void d68000_lsr_ea(void)
+{
+ sprintf(g_dasm_str, "lsr.w %s", get_ea_mode_str_32(g_cpu_ir));
+}
+
+static void d68000_lsl_s_8(void)
+{
+ sprintf(g_dasm_str, "lsl.b #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7);
+}
+
+static void d68000_lsl_s_16(void)
+{
+ sprintf(g_dasm_str, "lsl.w #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7);
+}
+
+static void d68000_lsl_s_32(void)
+{
+ sprintf(g_dasm_str, "lsl.l #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7);
+}
+
+static void d68000_lsl_r_8(void)
+{
+ sprintf(g_dasm_str, "lsl.b D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7);
+}
+
+static void d68000_lsl_r_16(void)
+{
+ sprintf(g_dasm_str, "lsl.w D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7);
+}
+
+static void d68000_lsl_r_32(void)
+{
+ sprintf(g_dasm_str, "lsl.l D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7);
+}
+
+static void d68000_lsl_ea(void)
+{
+ sprintf(g_dasm_str, "lsl.w %s", get_ea_mode_str_32(g_cpu_ir));
+}
+
+static void d68000_move_8(void)
+{
+ char* str = get_ea_mode_str_8(g_cpu_ir);
+ sprintf(g_dasm_str, "move.b %s, %s", str, get_ea_mode_str_8(((g_cpu_ir>>9) & 7) | ((g_cpu_ir>>3) & 0x38)));
+}
+
+static void d68000_move_16(void)
+{
+ char* str = get_ea_mode_str_16(g_cpu_ir);
+ sprintf(g_dasm_str, "move.w %s, %s", str, get_ea_mode_str_16(((g_cpu_ir>>9) & 7) | ((g_cpu_ir>>3) & 0x38)));
+}
+
+static void d68000_move_32(void)
+{
+ char* str = get_ea_mode_str_32(g_cpu_ir);
+ sprintf(g_dasm_str, "move.l %s, %s", str, get_ea_mode_str_32(((g_cpu_ir>>9) & 7) | ((g_cpu_ir>>3) & 0x38)));
+}
+
+static void d68000_movea_16(void)
+{
+ sprintf(g_dasm_str, "movea.w %s, A%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7);
+}
+
+static void d68000_movea_32(void)
+{
+ sprintf(g_dasm_str, "movea.l %s, A%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7);
+}
+
+static void d68000_move_to_ccr(void)
+{
+ sprintf(g_dasm_str, "move %s, CCR", get_ea_mode_str_8(g_cpu_ir));
+}
+
+static void d68010_move_fr_ccr(void)
+{
+ LIMIT_CPU_TYPES(M68010_PLUS);
+ sprintf(g_dasm_str, "move CCR, %s; (1+)", get_ea_mode_str_8(g_cpu_ir));
+}
+
+static void d68000_move_fr_sr(void)
+{
+ sprintf(g_dasm_str, "move SR, %s", get_ea_mode_str_16(g_cpu_ir));
+}
+
+static void d68000_move_to_sr(void)
+{
+ sprintf(g_dasm_str, "move %s, SR", get_ea_mode_str_16(g_cpu_ir));
+}
+
+static void d68000_move_fr_usp(void)
+{
+ sprintf(g_dasm_str, "move USP, A%d", g_cpu_ir&7);
+}
+
+static void d68000_move_to_usp(void)
+{
+ sprintf(g_dasm_str, "move A%d, USP", g_cpu_ir&7);
+}
+
+static void d68010_movec(void)
+{
+ UINT32 extension;
+ const char* reg_name;
+ const char* processor;
+ LIMIT_CPU_TYPES(M68010_PLUS);
+ extension = read_imm_16();
+
+ switch(extension & 0xfff)
+ {
+ case 0x000:
+ reg_name = "SFC";
+ processor = "1+";
+ break;
+ case 0x001:
+ reg_name = "DFC";
+ processor = "1+";
+ break;
+ case 0x800:
+ reg_name = "USP";
+ processor = "1+";
+ break;
+ case 0x801:
+ reg_name = "VBR";
+ processor = "1+";
+ break;
+ case 0x002:
+ reg_name = "CACR";
+ processor = "2+";
+ break;
+ case 0x802:
+ reg_name = "CAAR";
+ processor = "2,3";
+ break;
+ case 0x803:
+ reg_name = "MSP";
+ processor = "2+";
+ break;
+ case 0x804:
+ reg_name = "ISP";
+ processor = "2+";
+ break;
+ case 0x003:
+ reg_name = "TC";
+ processor = "4+";
+ break;
+ case 0x004:
+ reg_name = "ITT0";
+ processor = "4+";
+ break;
+ case 0x005:
+ reg_name = "ITT1";
+ processor = "4+";
+ break;
+ case 0x006:
+ reg_name = "DTT0";
+ processor = "4+";
+ break;
+ case 0x007:
+ reg_name = "DTT1";
+ processor = "4+";
+ break;
+ case 0x805:
+ reg_name = "MMUSR";
+ processor = "4+";
+ break;
+ case 0x806:
+ reg_name = "URP";
+ processor = "4+";
+ break;
+ case 0x807:
+ reg_name = "SRP";
+ processor = "4+";
+ break;
+ default:
+ reg_name = make_signed_hex_str_16(extension & 0xfff);
+ processor = "?";
+ }
+
+ if(BIT_0(g_cpu_ir))
+ sprintf(g_dasm_str, "movec %c%d, %s; (%s)", BIT_F(extension) ? 'A' : 'D', (extension>>12)&7, reg_name, processor);
+ else
+ sprintf(g_dasm_str, "movec %s, %c%d; (%s)", reg_name, BIT_F(extension) ? 'A' : 'D', (extension>>12)&7, processor);
+}
+
+static void d68000_movem_pd_16(void)
+{
+ UINT32 data = read_imm_16();
+ char buffer[40];
+ UINT32 first;
+ UINT32 run_length;
+ UINT32 i;
+
+ buffer[0] = 0;
+ for(i=0;i<8;i++)
+ {
+ if(data&(1<<(15-i)))
+ {
+ first = i;
+ run_length = 0;
+ while(i<7 && (data&(1<<(15-(i+1)))))
+ {
+ i++;
+ run_length++;
+ }
+ if(buffer[0] != 0)
+ strcat(buffer, "/");
+ sprintf(buffer+strlen(buffer), "D%d", first);
+ if(run_length > 0)
+ sprintf(buffer+strlen(buffer), "-D%d", first + run_length);
+ }
+ }
+ for(i=0;i<8;i++)
+ {
+ if(data&(1<<(7-i)))
+ {
+ first = i;
+ run_length = 0;
+ while(i<7 && (data&(1<<(7-(i+1)))))
+ {
+ i++;
+ run_length++;
+ }
+ if(buffer[0] != 0)
+ strcat(buffer, "/");
+ sprintf(buffer+strlen(buffer), "A%d", first);
+ if(run_length > 0)
+ sprintf(buffer+strlen(buffer), "-A%d", first + run_length);
+ }
+ }
+ sprintf(g_dasm_str, "movem.w %s, %s", buffer, get_ea_mode_str_16(g_cpu_ir));
+}
+
+static void d68000_movem_pd_32(void)
+{
+ UINT32 data = read_imm_16();
+ char buffer[40];
+ UINT32 first;
+ UINT32 run_length;
+ UINT32 i;
+
+ buffer[0] = 0;
+ for(i=0;i<8;i++)
+ {
+ if(data&(1<<(15-i)))
+ {
+ first = i;
+ run_length = 0;
+ while(i<7 && (data&(1<<(15-(i+1)))))
+ {
+ i++;
+ run_length++;
+ }
+ if(buffer[0] != 0)
+ strcat(buffer, "/");
+ sprintf(buffer+strlen(buffer), "D%d", first);
+ if(run_length > 0)
+ sprintf(buffer+strlen(buffer), "-D%d", first + run_length);
+ }
+ }
+ for(i=0;i<8;i++)
+ {
+ if(data&(1<<(7-i)))
+ {
+ first = i;
+ run_length = 0;
+ while(i<7 && (data&(1<<(7-(i+1)))))
+ {
+ i++;
+ run_length++;
+ }
+ if(buffer[0] != 0)
+ strcat(buffer, "/");
+ sprintf(buffer+strlen(buffer), "A%d", first);
+ if(run_length > 0)
+ sprintf(buffer+strlen(buffer), "-A%d", first + run_length);
+ }
+ }
+ sprintf(g_dasm_str, "movem.l %s, %s", buffer, get_ea_mode_str_32(g_cpu_ir));
+}
+
+static void d68000_movem_er_16(void)
+{
+ UINT32 data = read_imm_16();
+ char buffer[40];
+ UINT32 first;
+ UINT32 run_length;
+ UINT32 i;
+
+ buffer[0] = 0;
+ for(i=0;i<8;i++)
+ {
+ if(data&(1<<i))
+ {
+ first = i;
+ run_length = 0;
+ while(i<7 && (data&(1<<(i+1))))
+ {
+ i++;
+ run_length++;
+ }
+ if(buffer[0] != 0)
+ strcat(buffer, "/");
+ sprintf(buffer+strlen(buffer), "D%d", first);
+ if(run_length > 0)
+ sprintf(buffer+strlen(buffer), "-D%d", first + run_length);
+ }
+ }
+ for(i=0;i<8;i++)
+ {
+ if(data&(1<<(i+8)))
+ {
+ first = i;
+ run_length = 0;
+ while(i<7 && (data&(1<<(i+8+1))))
+ {
+ i++;
+ run_length++;
+ }
+ if(buffer[0] != 0)
+ strcat(buffer, "/");
+ sprintf(buffer+strlen(buffer), "A%d", first);
+ if(run_length > 0)
+ sprintf(buffer+strlen(buffer), "-A%d", first + run_length);
+ }
+ }
+ sprintf(g_dasm_str, "movem.w %s, %s", get_ea_mode_str_16(g_cpu_ir), buffer);
+}
+
+static void d68000_movem_er_32(void)
+{
+ UINT32 data = read_imm_16();
+ char buffer[40];
+ UINT32 first;
+ UINT32 run_length;
+ UINT32 i;
+
+ buffer[0] = 0;
+ for(i=0;i<8;i++)
+ {
+ if(data&(1<<i))
+ {
+ first = i;
+ run_length = 0;
+ while(i<7 && (data&(1<<(i+1))))
+ {
+ i++;
+ run_length++;
+ }
+ if(buffer[0] != 0)
+ strcat(buffer, "/");
+ sprintf(buffer+strlen(buffer), "D%d", first);
+ if(run_length > 0)
+ sprintf(buffer+strlen(buffer), "-D%d", first + run_length);
+ }
+ }
+ for(i=0;i<8;i++)
+ {
+ if(data&(1<<(i+8)))
+ {
+ first = i;
+ run_length = 0;
+ while(i<7 && (data&(1<<(i+8+1))))
+ {
+ i++;
+ run_length++;
+ }
+ if(buffer[0] != 0)
+ strcat(buffer, "/");
+ sprintf(buffer+strlen(buffer), "A%d", first);
+ if(run_length > 0)
+ sprintf(buffer+strlen(buffer), "-A%d", first + run_length);
+ }
+ }
+ sprintf(g_dasm_str, "movem.l %s, %s", get_ea_mode_str_32(g_cpu_ir), buffer);
+}
+
+static void d68000_movem_re_16(void)
+{
+ UINT32 data = read_imm_16();
+ char buffer[40];
+ UINT32 first;
+ UINT32 run_length;
+ UINT32 i;
+
+ buffer[0] = 0;
+ for(i=0;i<8;i++)
+ {
+ if(data&(1<<i))
+ {
+ first = i;
+ run_length = 0;
+ while(i<7 && (data&(1<<(i+1))))
+ {
+ i++;
+ run_length++;
+ }
+ if(buffer[0] != 0)
+ strcat(buffer, "/");
+ sprintf(buffer+strlen(buffer), "D%d", first);
+ if(run_length > 0)
+ sprintf(buffer+strlen(buffer), "-D%d", first + run_length);
+ }
+ }
+ for(i=0;i<8;i++)
+ {
+ if(data&(1<<(i+8)))
+ {
+ first = i;
+ run_length = 0;
+ while(i<7 && (data&(1<<(i+8+1))))
+ {
+ i++;
+ run_length++;
+ }
+ if(buffer[0] != 0)
+ strcat(buffer, "/");
+ sprintf(buffer+strlen(buffer), "A%d", first);
+ if(run_length > 0)
+ sprintf(buffer+strlen(buffer), "-A%d", first + run_length);
+ }
+ }
+ sprintf(g_dasm_str, "movem.w %s, %s", buffer, get_ea_mode_str_16(g_cpu_ir));
+}
+
+static void d68000_movem_re_32(void)
+{
+ UINT32 data = read_imm_16();
+ char buffer[40];
+ UINT32 first;
+ UINT32 run_length;
+ UINT32 i;
+
+ buffer[0] = 0;
+ for(i=0;i<8;i++)
+ {
+ if(data&(1<<i))
+ {
+ first = i;
+ run_length = 0;
+ while(i<7 && (data&(1<<(i+1))))
+ {
+ i++;
+ run_length++;
+ }
+ if(buffer[0] != 0)
+ strcat(buffer, "/");
+ sprintf(buffer+strlen(buffer), "D%d", first);
+ if(run_length > 0)
+ sprintf(buffer+strlen(buffer), "-D%d", first + run_length);
+ }
+ }
+ for(i=0;i<8;i++)
+ {
+ if(data&(1<<(i+8)))
+ {
+ first = i;
+ run_length = 0;
+ while(i<7 && (data&(1<<(i+8+1))))
+ {
+ i++;
+ run_length++;
+ }
+ if(buffer[0] != 0)
+ strcat(buffer, "/");
+ sprintf(buffer+strlen(buffer), "A%d", first);
+ if(run_length > 0)
+ sprintf(buffer+strlen(buffer), "-A%d", first + run_length);
+ }
+ }
+ sprintf(g_dasm_str, "movem.l %s, %s", buffer, get_ea_mode_str_32(g_cpu_ir));
+}
+
+static void d68000_movep_re_16(void)
+{
+ sprintf(g_dasm_str, "movep.w D%d, ($%x,A%d)", (g_cpu_ir>>9)&7, read_imm_16(), g_cpu_ir&7);
+}
+
+static void d68000_movep_re_32(void)
+{
+ sprintf(g_dasm_str, "movep.l D%d, ($%x,A%d)", (g_cpu_ir>>9)&7, read_imm_16(), g_cpu_ir&7);
+}
+
+static void d68000_movep_er_16(void)
+{
+ sprintf(g_dasm_str, "movep.w ($%x,A%d), D%d", read_imm_16(), g_cpu_ir&7, (g_cpu_ir>>9)&7);
+}
+
+static void d68000_movep_er_32(void)
+{
+ sprintf(g_dasm_str, "movep.l ($%x,A%d), D%d", read_imm_16(), g_cpu_ir&7, (g_cpu_ir>>9)&7);
+}
+
+static void d68010_moves_8(void)
+{
+ UINT32 extension;
+ LIMIT_CPU_TYPES(M68010_PLUS);
+ extension = read_imm_16();
+ if(BIT_B(extension))
+ sprintf(g_dasm_str, "moves.b %c%d, %s; (1+)", BIT_F(extension) ? 'A' : 'D', (extension>>12)&7, get_ea_mode_str_8(g_cpu_ir));
+ else
+ sprintf(g_dasm_str, "moves.b %s, %c%d; (1+)", get_ea_mode_str_8(g_cpu_ir), BIT_F(extension) ? 'A' : 'D', (extension>>12)&7);
+}
+
+static void d68010_moves_16(void)
+{
+ UINT32 extension;
+ LIMIT_CPU_TYPES(M68010_PLUS);
+ extension = read_imm_16();
+ if(BIT_B(extension))
+ sprintf(g_dasm_str, "moves.w %c%d, %s; (1+)", BIT_F(extension) ? 'A' : 'D', (extension>>12)&7, get_ea_mode_str_16(g_cpu_ir));
+ else
+ sprintf(g_dasm_str, "moves.w %s, %c%d; (1+)", get_ea_mode_str_16(g_cpu_ir), BIT_F(extension) ? 'A' : 'D', (extension>>12)&7);
+}
+
+static void d68010_moves_32(void)
+{
+ UINT32 extension;
+ LIMIT_CPU_TYPES(M68010_PLUS);
+ extension = read_imm_16();
+ if(BIT_B(extension))
+ sprintf(g_dasm_str, "moves.l %c%d, %s; (1+)", BIT_F(extension) ? 'A' : 'D', (extension>>12)&7, get_ea_mode_str_32(g_cpu_ir));
+ else
+ sprintf(g_dasm_str, "moves.l %s, %c%d; (1+)", get_ea_mode_str_32(g_cpu_ir), BIT_F(extension) ? 'A' : 'D', (extension>>12)&7);
+}
+
+static void d68000_moveq(void)
+{
+ sprintf(g_dasm_str, "moveq #%s, D%d", make_signed_hex_str_8(g_cpu_ir), (g_cpu_ir>>9)&7);
+}
+
+static void d68040_move16_pi_pi(void)
+{
+ LIMIT_CPU_TYPES(M68040_PLUS);
+ sprintf(g_dasm_str, "move16 (A%d)+, (A%d)+; (4)", g_cpu_ir&7, (read_imm_16()>>12)&7);
+}
+
+static void d68040_move16_pi_al(void)
+{
+ LIMIT_CPU_TYPES(M68040_PLUS);
+ sprintf(g_dasm_str, "move16 (A%d)+, %s; (4)", g_cpu_ir&7, get_imm_str_u32());
+}
+
+static void d68040_move16_al_pi(void)
+{
+ LIMIT_CPU_TYPES(M68040_PLUS);
+ sprintf(g_dasm_str, "move16 %s, (A%d)+; (4)", get_imm_str_u32(), g_cpu_ir&7);
+}
+
+static void d68040_move16_ai_al(void)
+{
+ LIMIT_CPU_TYPES(M68040_PLUS);
+ sprintf(g_dasm_str, "move16 (A%d), %s; (4)", g_cpu_ir&7, get_imm_str_u32());
+}
+
+static void d68040_move16_al_ai(void)
+{
+ LIMIT_CPU_TYPES(M68040_PLUS);
+ sprintf(g_dasm_str, "move16 %s, (A%d); (4)", get_imm_str_u32(), g_cpu_ir&7);
+}
+
+static void d68000_muls(void)
+{
+ sprintf(g_dasm_str, "muls.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7);
+}
+
+static void d68000_mulu(void)
+{
+ sprintf(g_dasm_str, "mulu.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7);
+}
+
+static void d68020_mull(void)
+{
+ UINT32 extension;
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ extension = read_imm_16();
+
+ if(BIT_A(extension))
+ sprintf(g_dasm_str, "mul%c.l %s, D%d-D%d; (2+)", BIT_B(extension) ? 's' : 'u', get_ea_mode_str_32(g_cpu_ir), extension&7, (extension>>12)&7);
+ else
+ sprintf(g_dasm_str, "mul%c.l %s, D%d; (2+)", BIT_B(extension) ? 's' : 'u', get_ea_mode_str_32(g_cpu_ir), (extension>>12)&7);
+}
+
+static void d68000_nbcd(void)
+{
+ sprintf(g_dasm_str, "nbcd %s", get_ea_mode_str_8(g_cpu_ir));
+}
+
+static void d68000_neg_8(void)
+{
+ sprintf(g_dasm_str, "neg.b %s", get_ea_mode_str_8(g_cpu_ir));
+}
+
+static void d68000_neg_16(void)
+{
+ sprintf(g_dasm_str, "neg.w %s", get_ea_mode_str_16(g_cpu_ir));
+}
+
+static void d68000_neg_32(void)
+{
+ sprintf(g_dasm_str, "neg.l %s", get_ea_mode_str_32(g_cpu_ir));
+}
+
+static void d68000_negx_8(void)
+{
+ sprintf(g_dasm_str, "negx.b %s", get_ea_mode_str_8(g_cpu_ir));
+}
+
+static void d68000_negx_16(void)
+{
+ sprintf(g_dasm_str, "negx.w %s", get_ea_mode_str_16(g_cpu_ir));
+}
+
+static void d68000_negx_32(void)
+{
+ sprintf(g_dasm_str, "negx.l %s", get_ea_mode_str_32(g_cpu_ir));
+}
+
+static void d68000_nop(void)
+{
+ sprintf(g_dasm_str, "nop");
+}
+
+static void d68000_not_8(void)
+{
+ sprintf(g_dasm_str, "not.b %s", get_ea_mode_str_8(g_cpu_ir));
+}
+
+static void d68000_not_16(void)
+{
+ sprintf(g_dasm_str, "not.w %s", get_ea_mode_str_16(g_cpu_ir));
+}
+
+static void d68000_not_32(void)
+{
+ sprintf(g_dasm_str, "not.l %s", get_ea_mode_str_32(g_cpu_ir));
+}
+
+static void d68000_or_er_8(void)
+{
+ sprintf(g_dasm_str, "or.b %s, D%d", get_ea_mode_str_8(g_cpu_ir), (g_cpu_ir>>9)&7);
+}
+
+static void d68000_or_er_16(void)
+{
+ sprintf(g_dasm_str, "or.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7);
+}
+
+static void d68000_or_er_32(void)
+{
+ sprintf(g_dasm_str, "or.l %s, D%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7);
+}
+
+static void d68000_or_re_8(void)
+{
+ sprintf(g_dasm_str, "or.b D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir));
+}
+
+static void d68000_or_re_16(void)
+{
+ sprintf(g_dasm_str, "or.w D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_16(g_cpu_ir));
+}
+
+static void d68000_or_re_32(void)
+{
+ sprintf(g_dasm_str, "or.l D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_32(g_cpu_ir));
+}
+
+static void d68000_ori_8(void)
+{
+ char* str = get_imm_str_u8();
+ sprintf(g_dasm_str, "ori.b %s, %s", str, get_ea_mode_str_8(g_cpu_ir));
+}
+
+static void d68000_ori_16(void)
+{
+ char* str = get_imm_str_u16();
+ sprintf(g_dasm_str, "ori.w %s, %s", str, get_ea_mode_str_16(g_cpu_ir));
+}
+
+static void d68000_ori_32(void)
+{
+ char* str = get_imm_str_u32();
+ sprintf(g_dasm_str, "ori.l %s, %s", str, get_ea_mode_str_32(g_cpu_ir));
+}
+
+static void d68000_ori_to_ccr(void)
+{
+ sprintf(g_dasm_str, "ori %s, CCR", get_imm_str_u8());
+}
+
+static void d68000_ori_to_sr(void)
+{
+ sprintf(g_dasm_str, "ori %s, SR", get_imm_str_u16());
+}
+
+static void d68020_pack_rr(void)
+{
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ sprintf(g_dasm_str, "pack D%d, D%d, %s; (2+)", g_cpu_ir&7, (g_cpu_ir>>9)&7, get_imm_str_u16());
+}
+
+static void d68020_pack_mm(void)
+{
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ sprintf(g_dasm_str, "pack -(A%d), -(A%d), %s; (2+)", g_cpu_ir&7, (g_cpu_ir>>9)&7, get_imm_str_u16());
+}
+
+static void d68000_pea(void)
+{
+ sprintf(g_dasm_str, "pea %s", get_ea_mode_str_32(g_cpu_ir));
+}
+
+// this is a 68040-specific form of PFLUSH
+static void d68040_pflush(void)
+{
+ LIMIT_CPU_TYPES(M68040_PLUS);
+
+ if (g_cpu_ir & 0x10)
+ {
+ sprintf(g_dasm_str, "pflusha%s", (g_cpu_ir & 8) ? "" : "n");
+ }
+ else
+ {
+ sprintf(g_dasm_str, "pflush%s(A%d)", (g_cpu_ir & 8) ? "" : "n", g_cpu_ir & 7);
+ }
+}
+
+static void d68000_reset(void)
+{
+ sprintf(g_dasm_str, "reset");
+}
+
+static void d68000_ror_s_8(void)
+{
+ sprintf(g_dasm_str, "ror.b #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7);
+}
+
+static void d68000_ror_s_16(void)
+{
+ sprintf(g_dasm_str, "ror.w #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7],g_cpu_ir&7);
+}
+
+static void d68000_ror_s_32(void)
+{
+ sprintf(g_dasm_str, "ror.l #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7);
+}
+
+static void d68000_ror_r_8(void)
+{
+ sprintf(g_dasm_str, "ror.b D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7);
+}
+
+static void d68000_ror_r_16(void)
+{
+ sprintf(g_dasm_str, "ror.w D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7);
+}
+
+static void d68000_ror_r_32(void)
+{
+ sprintf(g_dasm_str, "ror.l D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7);
+}
+
+static void d68000_ror_ea(void)
+{
+ sprintf(g_dasm_str, "ror.w %s", get_ea_mode_str_32(g_cpu_ir));
+}
+
+static void d68000_rol_s_8(void)
+{
+ sprintf(g_dasm_str, "rol.b #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7);
+}
+
+static void d68000_rol_s_16(void)
+{
+ sprintf(g_dasm_str, "rol.w #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7);
+}
+
+static void d68000_rol_s_32(void)
+{
+ sprintf(g_dasm_str, "rol.l #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7);
+}
+
+static void d68000_rol_r_8(void)
+{
+ sprintf(g_dasm_str, "rol.b D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7);
+}
+
+static void d68000_rol_r_16(void)
+{
+ sprintf(g_dasm_str, "rol.w D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7);
+}
+
+static void d68000_rol_r_32(void)
+{
+ sprintf(g_dasm_str, "rol.l D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7);
+}
+
+static void d68000_rol_ea(void)
+{
+ sprintf(g_dasm_str, "rol.w %s", get_ea_mode_str_32(g_cpu_ir));
+}
+
+static void d68000_roxr_s_8(void)
+{
+ sprintf(g_dasm_str, "roxr.b #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7);
+}
+
+static void d68000_roxr_s_16(void)
+{
+ sprintf(g_dasm_str, "roxr.w #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7);
+}
+
+
+static void d68000_roxr_s_32(void)
+{
+ sprintf(g_dasm_str, "roxr.l #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7);
+}
+
+static void d68000_roxr_r_8(void)
+{
+ sprintf(g_dasm_str, "roxr.b D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7);
+}
+
+static void d68000_roxr_r_16(void)
+{
+ sprintf(g_dasm_str, "roxr.w D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7);
+}
+
+static void d68000_roxr_r_32(void)
+{
+ sprintf(g_dasm_str, "roxr.l D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7);
+}
+
+static void d68000_roxr_ea(void)
+{
+ sprintf(g_dasm_str, "roxr.w %s", get_ea_mode_str_32(g_cpu_ir));
+}
+
+static void d68000_roxl_s_8(void)
+{
+ sprintf(g_dasm_str, "roxl.b #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7);
+}
+
+static void d68000_roxl_s_16(void)
+{
+ sprintf(g_dasm_str, "roxl.w #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7);
+}
+
+static void d68000_roxl_s_32(void)
+{
+ sprintf(g_dasm_str, "roxl.l #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7);
+}
+
+static void d68000_roxl_r_8(void)
+{
+ sprintf(g_dasm_str, "roxl.b D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7);
+}
+
+static void d68000_roxl_r_16(void)
+{
+ sprintf(g_dasm_str, "roxl.w D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7);
+}
+
+static void d68000_roxl_r_32(void)
+{
+ sprintf(g_dasm_str, "roxl.l D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7);
+}
+
+static void d68000_roxl_ea(void)
+{
+ sprintf(g_dasm_str, "roxl.w %s", get_ea_mode_str_32(g_cpu_ir));
+}
+
+static void d68010_rtd(void)
+{
+ LIMIT_CPU_TYPES(M68010_PLUS);
+ sprintf(g_dasm_str, "rtd %s; (1+)", get_imm_str_s16());
+ SET_OPCODE_FLAGS(DASMFLAG_STEP_OUT);
+}
+
+static void d68000_rte(void)
+{
+ sprintf(g_dasm_str, "rte");
+ SET_OPCODE_FLAGS(DASMFLAG_STEP_OUT);
+}
+
+static void d68020_rtm(void)
+{
+ LIMIT_CPU_TYPES(M68020_ONLY);
+ sprintf(g_dasm_str, "rtm %c%d; (2+)", BIT_3(g_cpu_ir) ? 'A' : 'D', g_cpu_ir&7);
+ SET_OPCODE_FLAGS(DASMFLAG_STEP_OUT);
+}
+
+static void d68000_rtr(void)
+{
+ sprintf(g_dasm_str, "rtr");
+ SET_OPCODE_FLAGS(DASMFLAG_STEP_OUT);
+}
+
+static void d68000_rts(void)
+{
+ sprintf(g_dasm_str, "rts");
+ SET_OPCODE_FLAGS(DASMFLAG_STEP_OUT);
+}
+
+static void d68000_sbcd_rr(void)
+{
+ sprintf(g_dasm_str, "sbcd D%d, D%d", g_cpu_ir&7, (g_cpu_ir>>9)&7);
+}
+
+static void d68000_sbcd_mm(void)
+{
+ sprintf(g_dasm_str, "sbcd -(A%d), -(A%d)", g_cpu_ir&7, (g_cpu_ir>>9)&7);
+}
+
+static void d68000_scc(void)
+{
+ sprintf(g_dasm_str, "s%-2s %s", g_cc[(g_cpu_ir>>8)&0xf], get_ea_mode_str_8(g_cpu_ir));
+}
+
+static void d68000_stop(void)
+{
+ sprintf(g_dasm_str, "stop %s", get_imm_str_s16());
+}
+
+static void d68000_sub_er_8(void)
+{
+ sprintf(g_dasm_str, "sub.b %s, D%d", get_ea_mode_str_8(g_cpu_ir), (g_cpu_ir>>9)&7);
+}
+
+static void d68000_sub_er_16(void)
+{
+ sprintf(g_dasm_str, "sub.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7);
+}
+
+static void d68000_sub_er_32(void)
+{
+ sprintf(g_dasm_str, "sub.l %s, D%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7);
+}
+
+static void d68000_sub_re_8(void)
+{
+ sprintf(g_dasm_str, "sub.b D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir));
+}
+
+static void d68000_sub_re_16(void)
+{
+ sprintf(g_dasm_str, "sub.w D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_16(g_cpu_ir));
+}
+
+static void d68000_sub_re_32(void)
+{
+ sprintf(g_dasm_str, "sub.l D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_32(g_cpu_ir));
+}
+
+static void d68000_suba_16(void)
+{
+ sprintf(g_dasm_str, "suba.w %s, A%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7);
+}
+
+static void d68000_suba_32(void)
+{
+ sprintf(g_dasm_str, "suba.l %s, A%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7);
+}
+
+static void d68000_subi_8(void)
+{
+ char* str = get_imm_str_s8();
+ sprintf(g_dasm_str, "subi.b %s, %s", str, get_ea_mode_str_8(g_cpu_ir));
+}
+
+static void d68000_subi_16(void)
+{
+ char* str = get_imm_str_s16();
+ sprintf(g_dasm_str, "subi.w %s, %s", str, get_ea_mode_str_16(g_cpu_ir));
+}
+
+static void d68000_subi_32(void)
+{
+ char* str = get_imm_str_s32();
+ sprintf(g_dasm_str, "subi.l %s, %s", str, get_ea_mode_str_32(g_cpu_ir));
+}
+
+static void d68000_subq_8(void)
+{
+ sprintf(g_dasm_str, "subq.b #%d, %s", g_3bit_qdata_table[(g_cpu_ir>>9)&7], get_ea_mode_str_8(g_cpu_ir));
+}
+
+static void d68000_subq_16(void)
+{
+ sprintf(g_dasm_str, "subq.w #%d, %s", g_3bit_qdata_table[(g_cpu_ir>>9)&7], get_ea_mode_str_16(g_cpu_ir));
+}
+
+static void d68000_subq_32(void)
+{
+ sprintf(g_dasm_str, "subq.l #%d, %s", g_3bit_qdata_table[(g_cpu_ir>>9)&7], get_ea_mode_str_32(g_cpu_ir));
+}
+
+static void d68000_subx_rr_8(void)
+{
+ sprintf(g_dasm_str, "subx.b D%d, D%d", g_cpu_ir&7, (g_cpu_ir>>9)&7);
+}
+
+static void d68000_subx_rr_16(void)
+{
+ sprintf(g_dasm_str, "subx.w D%d, D%d", g_cpu_ir&7, (g_cpu_ir>>9)&7);
+}
+
+static void d68000_subx_rr_32(void)
+{
+ sprintf(g_dasm_str, "subx.l D%d, D%d", g_cpu_ir&7, (g_cpu_ir>>9)&7);
+}
+
+static void d68000_subx_mm_8(void)
+{
+ sprintf(g_dasm_str, "subx.b -(A%d), -(A%d)", g_cpu_ir&7, (g_cpu_ir>>9)&7);
+}
+
+static void d68000_subx_mm_16(void)
+{
+ sprintf(g_dasm_str, "subx.w -(A%d), -(A%d)", g_cpu_ir&7, (g_cpu_ir>>9)&7);
+}
+
+static void d68000_subx_mm_32(void)
+{
+ sprintf(g_dasm_str, "subx.l -(A%d), -(A%d)", g_cpu_ir&7, (g_cpu_ir>>9)&7);
+}
+
+static void d68000_swap(void)
+{
+ sprintf(g_dasm_str, "swap D%d", g_cpu_ir&7);
+}
+
+static void d68000_tas(void)
+{
+ sprintf(g_dasm_str, "tas %s", get_ea_mode_str_8(g_cpu_ir));
+}
+
+static void d68000_trap(void)
+{
+ sprintf(g_dasm_str, "trap #$%x", g_cpu_ir&0xf);
+}
+
+static void d68020_trapcc_0(void)
+{
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ sprintf(g_dasm_str, "trap%-2s; (2+)", g_cc[(g_cpu_ir>>8)&0xf]);
+ SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER);
+}
+
+static void d68020_trapcc_16(void)
+{
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ sprintf(g_dasm_str, "trap%-2s %s; (2+)", g_cc[(g_cpu_ir>>8)&0xf], get_imm_str_u16());
+ SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER);
+}
+
+static void d68020_trapcc_32(void)
+{
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ sprintf(g_dasm_str, "trap%-2s %s; (2+)", g_cc[(g_cpu_ir>>8)&0xf], get_imm_str_u32());
+ SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER);
+}
+
+static void d68000_trapv(void)
+{
+ sprintf(g_dasm_str, "trapv");
+ SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER);
+}
+
+static void d68000_tst_8(void)
+{
+ sprintf(g_dasm_str, "tst.b %s", get_ea_mode_str_8(g_cpu_ir));
+}
+
+static void d68020_tst_pcdi_8(void)
+{
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ sprintf(g_dasm_str, "tst.b %s; (2+)", get_ea_mode_str_8(g_cpu_ir));
+}
+
+static void d68020_tst_pcix_8(void)
+{
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ sprintf(g_dasm_str, "tst.b %s; (2+)", get_ea_mode_str_8(g_cpu_ir));
+}
+
+static void d68020_tst_i_8(void)
+{
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ sprintf(g_dasm_str, "tst.b %s; (2+)", get_ea_mode_str_8(g_cpu_ir));
+}
+
+static void d68000_tst_16(void)
+{
+ sprintf(g_dasm_str, "tst.w %s", get_ea_mode_str_16(g_cpu_ir));
+}
+
+static void d68020_tst_a_16(void)
+{
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ sprintf(g_dasm_str, "tst.w %s; (2+)", get_ea_mode_str_16(g_cpu_ir));
+}
+
+static void d68020_tst_pcdi_16(void)
+{
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ sprintf(g_dasm_str, "tst.w %s; (2+)", get_ea_mode_str_16(g_cpu_ir));
+}
+
+static void d68020_tst_pcix_16(void)
+{
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ sprintf(g_dasm_str, "tst.w %s; (2+)", get_ea_mode_str_16(g_cpu_ir));
+}
+
+static void d68020_tst_i_16(void)
+{
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ sprintf(g_dasm_str, "tst.w %s; (2+)", get_ea_mode_str_16(g_cpu_ir));
+}
+
+static void d68000_tst_32(void)
+{
+ sprintf(g_dasm_str, "tst.l %s", get_ea_mode_str_32(g_cpu_ir));
+}
+
+static void d68020_tst_a_32(void)
+{
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ sprintf(g_dasm_str, "tst.l %s; (2+)", get_ea_mode_str_32(g_cpu_ir));
+}
+
+static void d68020_tst_pcdi_32(void)
+{
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ sprintf(g_dasm_str, "tst.l %s; (2+)", get_ea_mode_str_32(g_cpu_ir));
+}
+
+static void d68020_tst_pcix_32(void)
+{
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ sprintf(g_dasm_str, "tst.l %s; (2+)", get_ea_mode_str_32(g_cpu_ir));
+}
+
+static void d68020_tst_i_32(void)
+{
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ sprintf(g_dasm_str, "tst.l %s; (2+)", get_ea_mode_str_32(g_cpu_ir));
+}
+
+static void d68000_unlk(void)
+{
+ sprintf(g_dasm_str, "unlk A%d", g_cpu_ir&7);
+}
+
+static void d68020_unpk_rr(void)
+{
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ sprintf(g_dasm_str, "unpk D%d, D%d, %s; (2+)", g_cpu_ir&7, (g_cpu_ir>>9)&7, get_imm_str_u16());
+}
+
+static void d68020_unpk_mm(void)
+{
+ LIMIT_CPU_TYPES(M68020_PLUS);
+ sprintf(g_dasm_str, "unpk -(A%d), -(A%d), %s; (2+)", g_cpu_ir&7, (g_cpu_ir>>9)&7, get_imm_str_u16());
+}
+
+
+// PFLUSH: 001xxx0xxxxxxxxx
+// PLOAD: 001000x0000xxxxx
+// PVALID1: 0010100000000000
+// PVALID2: 0010110000000xxx
+// PMOVE 1: 010xxxx000000000
+// PMOVE 2: 011xxxx0000xxx00
+// PMOVE 3: 011xxxx000000000
+// PTEST: 100xxxxxxxxxxxxx
+// PFLUSHR: 1010000000000000
+static void d68851_p000(void)
+{
+ char* str;
+ UINT16 modes = read_imm_16();
+
+ // do this after fetching the second PMOVE word so we properly get the 3rd if necessary
+ str = get_ea_mode_str_32(g_cpu_ir);
+
+ if ((modes & 0xfde0) == 0x2000) // PLOAD
+ {
+ if (modes & 0x0200)
+ {
+ sprintf(g_dasm_str, "pload #%d, %s", (modes>>10)&7, str);
+ }
+ else
+ {
+ sprintf(g_dasm_str, "pload %s, #%d", str, (modes>>10)&7);
+ }
+ return;
+ }
+
+ if ((modes & 0xe200) == 0x2000) // PFLUSH
+ {
+ sprintf(g_dasm_str, "pflushr %x, %x, %s", modes & 0x1f, (modes>>5)&0xf, str);
+ return;
+ }
+
+ if (modes == 0xa000) // PFLUSHR
+ {
+ sprintf(g_dasm_str, "pflushr %s", str);
+ }
+
+ if (modes == 0x2800) // PVALID (FORMAT 1)
+ {
+ sprintf(g_dasm_str, "pvalid VAL, %s", str);
+ return;
+ }
+
+ if ((modes & 0xfff8) == 0x2c00) // PVALID (FORMAT 2)
+ {
+ sprintf(g_dasm_str, "pvalid A%d, %s", modes & 0xf, str);
+ return;
+ }
+
+ if ((modes & 0xe000) == 0x8000) // PTEST
+ {
+ sprintf(g_dasm_str, "ptest #%d, %s", modes & 0x1f, str);
+ return;
+ }
+
+ switch ((modes>>13) & 0x7)
+ {
+ case 0: // MC68030/040 form with FD bit
+ case 2: // MC68881 form, FD never set
+ if (modes & 0x0100)
+ {
+ if (modes & 0x0200)
+ {
+ sprintf(g_dasm_str, "pmovefd %s, %s", g_mmuregs[(modes>>10)&7], str);
+ }
+ else
+ {
+ sprintf(g_dasm_str, "pmovefd %s, %s", str, g_mmuregs[(modes>>10)&7]);
+ }
+ }
+ else
+ {
+ if (modes & 0x0200)
+ {
+ sprintf(g_dasm_str, "pmove %s, %s", g_mmuregs[(modes>>10)&7], str);
+ }
+ else
+ {
+ sprintf(g_dasm_str, "pmove %s, %s", str, g_mmuregs[(modes>>10)&7]);
+ }
+ }
+ break;
+
+ case 3: // MC68030 to/from status reg
+ if (modes & 0x0200)
+ {
+ sprintf(g_dasm_str, "pmove mmusr, %s", str);
+ }
+ else
+ {
+ sprintf(g_dasm_str, "pmove %s, mmusr", str);
+ }
+ break;
+
+ default:
+ sprintf(g_dasm_str, "pmove [unknown form] %s", str);
+ break;
+ }
+}
+
+static void d68851_pbcc16(void)
+{
+ UINT32 temp_pc = g_cpu_pc;
+
+ sprintf(g_dasm_str, "pb%s %x", g_mmucond[g_cpu_ir&0xf], temp_pc + make_int_16(read_imm_16()));
+}
+
+static void d68851_pbcc32(void)
+{
+ UINT32 temp_pc = g_cpu_pc;
+
+ sprintf(g_dasm_str, "pb%s %x", g_mmucond[g_cpu_ir&0xf], temp_pc + make_int_32(read_imm_32()));
+}
+
+static void d68851_pdbcc(void)
+{
+ UINT32 temp_pc = g_cpu_pc;
+ UINT16 modes = read_imm_16();
+
+ sprintf(g_dasm_str, "pb%s %x", g_mmucond[modes&0xf], temp_pc + make_int_16(read_imm_16()));
+}
+
+// PScc: 0000000000xxxxxx
+static void d68851_p001(void)
+{
+ sprintf(g_dasm_str, "MMU 001 group");
+}
+
+/* ======================================================================== */
+/* ======================= INSTRUCTION TABLE BUILDER ====================== */
+/* ======================================================================== */
+
+/* EA Masks:
+800 = data register direct
+400 = address register direct
+200 = address register indirect
+100 = ARI postincrement
+ 80 = ARI pre-decrement
+ 40 = ARI displacement
+ 20 = ARI index
+ 10 = absolute short
+ 8 = absolute long
+ 4 = immediate / sr
+ 2 = pc displacement
+ 1 = pc idx
+*/
+
+static const opcode_struct g_opcode_info[] =
+{
+/* opcode handler mask match ea mask */
+ {d68000_1010 , 0xf000, 0xa000, 0x000},
+ {d68000_1111 , 0xf000, 0xf000, 0x000},
+ {d68000_abcd_rr , 0xf1f8, 0xc100, 0x000},
+ {d68000_abcd_mm , 0xf1f8, 0xc108, 0x000},
+ {d68000_add_er_8 , 0xf1c0, 0xd000, 0xbff},
+ {d68000_add_er_16 , 0xf1c0, 0xd040, 0xfff},
+ {d68000_add_er_32 , 0xf1c0, 0xd080, 0xfff},
+ {d68000_add_re_8 , 0xf1c0, 0xd100, 0x3f8},
+ {d68000_add_re_16 , 0xf1c0, 0xd140, 0x3f8},
+ {d68000_add_re_32 , 0xf1c0, 0xd180, 0x3f8},
+ {d68000_adda_16 , 0xf1c0, 0xd0c0, 0xfff},
+ {d68000_adda_32 , 0xf1c0, 0xd1c0, 0xfff},
+ {d68000_addi_8 , 0xffc0, 0x0600, 0xbf8},
+ {d68000_addi_16 , 0xffc0, 0x0640, 0xbf8},
+ {d68000_addi_32 , 0xffc0, 0x0680, 0xbf8},
+ {d68000_addq_8 , 0xf1c0, 0x5000, 0xbf8},
+ {d68000_addq_16 , 0xf1c0, 0x5040, 0xff8},
+ {d68000_addq_32 , 0xf1c0, 0x5080, 0xff8},
+ {d68000_addx_rr_8 , 0xf1f8, 0xd100, 0x000},
+ {d68000_addx_rr_16 , 0xf1f8, 0xd140, 0x000},
+ {d68000_addx_rr_32 , 0xf1f8, 0xd180, 0x000},
+ {d68000_addx_mm_8 , 0xf1f8, 0xd108, 0x000},
+ {d68000_addx_mm_16 , 0xf1f8, 0xd148, 0x000},
+ {d68000_addx_mm_32 , 0xf1f8, 0xd188, 0x000},
+ {d68000_and_er_8 , 0xf1c0, 0xc000, 0xbff},
+ {d68000_and_er_16 , 0xf1c0, 0xc040, 0xbff},
+ {d68000_and_er_32 , 0xf1c0, 0xc080, 0xbff},
+ {d68000_and_re_8 , 0xf1c0, 0xc100, 0x3f8},
+ {d68000_and_re_16 , 0xf1c0, 0xc140, 0x3f8},
+ {d68000_and_re_32 , 0xf1c0, 0xc180, 0x3f8},
+ {d68000_andi_to_ccr , 0xffff, 0x023c, 0x000},
+ {d68000_andi_to_sr , 0xffff, 0x027c, 0x000},
+ {d68000_andi_8 , 0xffc0, 0x0200, 0xbf8},
+ {d68000_andi_16 , 0xffc0, 0x0240, 0xbf8},
+ {d68000_andi_32 , 0xffc0, 0x0280, 0xbf8},
+ {d68000_asr_s_8 , 0xf1f8, 0xe000, 0x000},
+ {d68000_asr_s_16 , 0xf1f8, 0xe040, 0x000},
+ {d68000_asr_s_32 , 0xf1f8, 0xe080, 0x000},
+ {d68000_asr_r_8 , 0xf1f8, 0xe020, 0x000},
+ {d68000_asr_r_16 , 0xf1f8, 0xe060, 0x000},
+ {d68000_asr_r_32 , 0xf1f8, 0xe0a0, 0x000},
+ {d68000_asr_ea , 0xffc0, 0xe0c0, 0x3f8},
+ {d68000_asl_s_8 , 0xf1f8, 0xe100, 0x000},
+ {d68000_asl_s_16 , 0xf1f8, 0xe140, 0x000},
+ {d68000_asl_s_32 , 0xf1f8, 0xe180, 0x000},
+ {d68000_asl_r_8 , 0xf1f8, 0xe120, 0x000},
+ {d68000_asl_r_16 , 0xf1f8, 0xe160, 0x000},
+ {d68000_asl_r_32 , 0xf1f8, 0xe1a0, 0x000},
+ {d68000_asl_ea , 0xffc0, 0xe1c0, 0x3f8},
+ {d68000_bcc_8 , 0xf000, 0x6000, 0x000},
+ {d68000_bcc_16 , 0xf0ff, 0x6000, 0x000},
+ {d68020_bcc_32 , 0xf0ff, 0x60ff, 0x000},
+ {d68000_bchg_r , 0xf1c0, 0x0140, 0xbf8},
+ {d68000_bchg_s , 0xffc0, 0x0840, 0xbf8},
+ {d68000_bclr_r , 0xf1c0, 0x0180, 0xbf8},
+ {d68000_bclr_s , 0xffc0, 0x0880, 0xbf8},
+ {d68020_bfchg , 0xffc0, 0xeac0, 0xa78},
+ {d68020_bfclr , 0xffc0, 0xecc0, 0xa78},
+ {d68020_bfexts , 0xffc0, 0xebc0, 0xa7b},
+ {d68020_bfextu , 0xffc0, 0xe9c0, 0xa7b},
+ {d68020_bfffo , 0xffc0, 0xedc0, 0xa7b},
+ {d68020_bfins , 0xffc0, 0xefc0, 0xa78},
+ {d68020_bfset , 0xffc0, 0xeec0, 0xa78},
+ {d68020_bftst , 0xffc0, 0xe8c0, 0xa7b},
+ {d68010_bkpt , 0xfff8, 0x4848, 0x000},
+ {d68000_bra_8 , 0xff00, 0x6000, 0x000},
+ {d68000_bra_16 , 0xffff, 0x6000, 0x000},
+ {d68020_bra_32 , 0xffff, 0x60ff, 0x000},
+ {d68000_bset_r , 0xf1c0, 0x01c0, 0xbf8},
+ {d68000_bset_s , 0xffc0, 0x08c0, 0xbf8},
+ {d68000_bsr_8 , 0xff00, 0x6100, 0x000},
+ {d68000_bsr_16 , 0xffff, 0x6100, 0x000},
+ {d68020_bsr_32 , 0xffff, 0x61ff, 0x000},
+ {d68000_btst_r , 0xf1c0, 0x0100, 0xbff},
+ {d68000_btst_s , 0xffc0, 0x0800, 0xbfb},
+ {d68020_callm , 0xffc0, 0x06c0, 0x27b},
+ {d68020_cas_8 , 0xffc0, 0x0ac0, 0x3f8},
+ {d68020_cas_16 , 0xffc0, 0x0cc0, 0x3f8},
+ {d68020_cas_32 , 0xffc0, 0x0ec0, 0x3f8},
+ {d68020_cas2_16 , 0xffff, 0x0cfc, 0x000},
+ {d68020_cas2_32 , 0xffff, 0x0efc, 0x000},
+ {d68000_chk_16 , 0xf1c0, 0x4180, 0xbff},
+ {d68020_chk_32 , 0xf1c0, 0x4100, 0xbff},
+ {d68020_chk2_cmp2_8 , 0xffc0, 0x00c0, 0x27b},
+ {d68020_chk2_cmp2_16 , 0xffc0, 0x02c0, 0x27b},
+ {d68020_chk2_cmp2_32 , 0xffc0, 0x04c0, 0x27b},
+ {d68040_cinv , 0xff20, 0xf400, 0x000},
+ {d68000_clr_8 , 0xffc0, 0x4200, 0xbf8},
+ {d68000_clr_16 , 0xffc0, 0x4240, 0xbf8},
+ {d68000_clr_32 , 0xffc0, 0x4280, 0xbf8},
+ {d68000_cmp_8 , 0xf1c0, 0xb000, 0xbff},
+ {d68000_cmp_16 , 0xf1c0, 0xb040, 0xfff},
+ {d68000_cmp_32 , 0xf1c0, 0xb080, 0xfff},
+ {d68000_cmpa_16 , 0xf1c0, 0xb0c0, 0xfff},
+ {d68000_cmpa_32 , 0xf1c0, 0xb1c0, 0xfff},
+ {d68000_cmpi_8 , 0xffc0, 0x0c00, 0xbf8},
+ {d68020_cmpi_pcdi_8 , 0xffff, 0x0c3a, 0x000},
+ {d68020_cmpi_pcix_8 , 0xffff, 0x0c3b, 0x000},
+ {d68000_cmpi_16 , 0xffc0, 0x0c40, 0xbf8},
+ {d68020_cmpi_pcdi_16 , 0xffff, 0x0c7a, 0x000},
+ {d68020_cmpi_pcix_16 , 0xffff, 0x0c7b, 0x000},
+ {d68000_cmpi_32 , 0xffc0, 0x0c80, 0xbf8},
+ {d68020_cmpi_pcdi_32 , 0xffff, 0x0cba, 0x000},
+ {d68020_cmpi_pcix_32 , 0xffff, 0x0cbb, 0x000},
+ {d68000_cmpm_8 , 0xf1f8, 0xb108, 0x000},
+ {d68000_cmpm_16 , 0xf1f8, 0xb148, 0x000},
+ {d68000_cmpm_32 , 0xf1f8, 0xb188, 0x000},
+ {d68020_cpbcc_16 , 0xf1c0, 0xf080, 0x000},
+ {d68020_cpbcc_32 , 0xf1c0, 0xf0c0, 0x000},
+ {d68020_cpdbcc , 0xf1f8, 0xf048, 0x000},
+ {d68020_cpgen , 0xf1c0, 0xf000, 0x000},
+ {d68020_cprestore , 0xf1c0, 0xf140, 0x37f},
+ {d68020_cpsave , 0xf1c0, 0xf100, 0x2f8},
+ {d68020_cpscc , 0xf1c0, 0xf040, 0xbf8},
+ {d68020_cptrapcc_0 , 0xf1ff, 0xf07c, 0x000},
+ {d68020_cptrapcc_16 , 0xf1ff, 0xf07a, 0x000},
+ {d68020_cptrapcc_32 , 0xf1ff, 0xf07b, 0x000},
+ {d68040_cpush , 0xff20, 0xf420, 0x000},
+ {d68000_dbcc , 0xf0f8, 0x50c8, 0x000},
+ {d68000_dbra , 0xfff8, 0x51c8, 0x000},
+ {d68000_divs , 0xf1c0, 0x81c0, 0xbff},
+ {d68000_divu , 0xf1c0, 0x80c0, 0xbff},
+ {d68020_divl , 0xffc0, 0x4c40, 0xbff},
+ {d68000_eor_8 , 0xf1c0, 0xb100, 0xbf8},
+ {d68000_eor_16 , 0xf1c0, 0xb140, 0xbf8},
+ {d68000_eor_32 , 0xf1c0, 0xb180, 0xbf8},
+ {d68000_eori_to_ccr , 0xffff, 0x0a3c, 0x000},
+ {d68000_eori_to_sr , 0xffff, 0x0a7c, 0x000},
+ {d68000_eori_8 , 0xffc0, 0x0a00, 0xbf8},
+ {d68000_eori_16 , 0xffc0, 0x0a40, 0xbf8},
+ {d68000_eori_32 , 0xffc0, 0x0a80, 0xbf8},
+ {d68000_exg_dd , 0xf1f8, 0xc140, 0x000},
+ {d68000_exg_aa , 0xf1f8, 0xc148, 0x000},
+ {d68000_exg_da , 0xf1f8, 0xc188, 0x000},
+ {d68020_extb_32 , 0xfff8, 0x49c0, 0x000},
+ {d68000_ext_16 , 0xfff8, 0x4880, 0x000},
+ {d68000_ext_32 , 0xfff8, 0x48c0, 0x000},
+ {d68040_fpu , 0xffc0, 0xf200, 0x000},
+ {d68000_illegal , 0xffff, 0x4afc, 0x000},
+ {d68000_jmp , 0xffc0, 0x4ec0, 0x27b},
+ {d68000_jsr , 0xffc0, 0x4e80, 0x27b},
+ {d68000_lea , 0xf1c0, 0x41c0, 0x27b},
+ {d68000_link_16 , 0xfff8, 0x4e50, 0x000},
+ {d68020_link_32 , 0xfff8, 0x4808, 0x000},
+ {d68000_lsr_s_8 , 0xf1f8, 0xe008, 0x000},
+ {d68000_lsr_s_16 , 0xf1f8, 0xe048, 0x000},
+ {d68000_lsr_s_32 , 0xf1f8, 0xe088, 0x000},
+ {d68000_lsr_r_8 , 0xf1f8, 0xe028, 0x000},
+ {d68000_lsr_r_16 , 0xf1f8, 0xe068, 0x000},
+ {d68000_lsr_r_32 , 0xf1f8, 0xe0a8, 0x000},
+ {d68000_lsr_ea , 0xffc0, 0xe2c0, 0x3f8},
+ {d68000_lsl_s_8 , 0xf1f8, 0xe108, 0x000},
+ {d68000_lsl_s_16 , 0xf1f8, 0xe148, 0x000},
+ {d68000_lsl_s_32 , 0xf1f8, 0xe188, 0x000},
+ {d68000_lsl_r_8 , 0xf1f8, 0xe128, 0x000},
+ {d68000_lsl_r_16 , 0xf1f8, 0xe168, 0x000},
+ {d68000_lsl_r_32 , 0xf1f8, 0xe1a8, 0x000},
+ {d68000_lsl_ea , 0xffc0, 0xe3c0, 0x3f8},
+ {d68000_move_8 , 0xf000, 0x1000, 0xbff},
+ {d68000_move_16 , 0xf000, 0x3000, 0xfff},
+ {d68000_move_32 , 0xf000, 0x2000, 0xfff},
+ {d68000_movea_16 , 0xf1c0, 0x3040, 0xfff},
+ {d68000_movea_32 , 0xf1c0, 0x2040, 0xfff},
+ {d68000_move_to_ccr , 0xffc0, 0x44c0, 0xbff},
+ {d68010_move_fr_ccr , 0xffc0, 0x42c0, 0xbf8},
+ {d68000_move_to_sr , 0xffc0, 0x46c0, 0xbff},
+ {d68000_move_fr_sr , 0xffc0, 0x40c0, 0xbf8},
+ {d68000_move_to_usp , 0xfff8, 0x4e60, 0x000},
+ {d68000_move_fr_usp , 0xfff8, 0x4e68, 0x000},
+ {d68010_movec , 0xfffe, 0x4e7a, 0x000},
+ {d68000_movem_pd_16 , 0xfff8, 0x48a0, 0x000},
+ {d68000_movem_pd_32 , 0xfff8, 0x48e0, 0x000},
+ {d68000_movem_re_16 , 0xffc0, 0x4880, 0x2f8},
+ {d68000_movem_re_32 , 0xffc0, 0x48c0, 0x2f8},
+ {d68000_movem_er_16 , 0xffc0, 0x4c80, 0x37b},
+ {d68000_movem_er_32 , 0xffc0, 0x4cc0, 0x37b},
+ {d68000_movep_er_16 , 0xf1f8, 0x0108, 0x000},
+ {d68000_movep_er_32 , 0xf1f8, 0x0148, 0x000},
+ {d68000_movep_re_16 , 0xf1f8, 0x0188, 0x000},
+ {d68000_movep_re_32 , 0xf1f8, 0x01c8, 0x000},
+ {d68010_moves_8 , 0xffc0, 0x0e00, 0x3f8},
+ {d68010_moves_16 , 0xffc0, 0x0e40, 0x3f8},
+ {d68010_moves_32 , 0xffc0, 0x0e80, 0x3f8},
+ {d68000_moveq , 0xf100, 0x7000, 0x000},
+ {d68040_move16_pi_pi , 0xfff8, 0xf620, 0x000},
+ {d68040_move16_pi_al , 0xfff8, 0xf600, 0x000},
+ {d68040_move16_al_pi , 0xfff8, 0xf608, 0x000},
+ {d68040_move16_ai_al , 0xfff8, 0xf610, 0x000},
+ {d68040_move16_al_ai , 0xfff8, 0xf618, 0x000},
+ {d68000_muls , 0xf1c0, 0xc1c0, 0xbff},
+ {d68000_mulu , 0xf1c0, 0xc0c0, 0xbff},
+ {d68020_mull , 0xffc0, 0x4c00, 0xbff},
+ {d68000_nbcd , 0xffc0, 0x4800, 0xbf8},
+ {d68000_neg_8 , 0xffc0, 0x4400, 0xbf8},
+ {d68000_neg_16 , 0xffc0, 0x4440, 0xbf8},
+ {d68000_neg_32 , 0xffc0, 0x4480, 0xbf8},
+ {d68000_negx_8 , 0xffc0, 0x4000, 0xbf8},
+ {d68000_negx_16 , 0xffc0, 0x4040, 0xbf8},
+ {d68000_negx_32 , 0xffc0, 0x4080, 0xbf8},
+ {d68000_nop , 0xffff, 0x4e71, 0x000},
+ {d68000_not_8 , 0xffc0, 0x4600, 0xbf8},
+ {d68000_not_16 , 0xffc0, 0x4640, 0xbf8},
+ {d68000_not_32 , 0xffc0, 0x4680, 0xbf8},
+ {d68000_or_er_8 , 0xf1c0, 0x8000, 0xbff},
+ {d68000_or_er_16 , 0xf1c0, 0x8040, 0xbff},
+ {d68000_or_er_32 , 0xf1c0, 0x8080, 0xbff},
+ {d68000_or_re_8 , 0xf1c0, 0x8100, 0x3f8},
+ {d68000_or_re_16 , 0xf1c0, 0x8140, 0x3f8},
+ {d68000_or_re_32 , 0xf1c0, 0x8180, 0x3f8},
+ {d68000_ori_to_ccr , 0xffff, 0x003c, 0x000},
+ {d68000_ori_to_sr , 0xffff, 0x007c, 0x000},
+ {d68000_ori_8 , 0xffc0, 0x0000, 0xbf8},
+ {d68000_ori_16 , 0xffc0, 0x0040, 0xbf8},
+ {d68000_ori_32 , 0xffc0, 0x0080, 0xbf8},
+ {d68020_pack_rr , 0xf1f8, 0x8140, 0x000},
+ {d68020_pack_mm , 0xf1f8, 0x8148, 0x000},
+ {d68000_pea , 0xffc0, 0x4840, 0x27b},
+ {d68040_pflush , 0xffe0, 0xf500, 0x000},
+ {d68000_reset , 0xffff, 0x4e70, 0x000},
+ {d68000_ror_s_8 , 0xf1f8, 0xe018, 0x000},
+ {d68000_ror_s_16 , 0xf1f8, 0xe058, 0x000},
+ {d68000_ror_s_32 , 0xf1f8, 0xe098, 0x000},
+ {d68000_ror_r_8 , 0xf1f8, 0xe038, 0x000},
+ {d68000_ror_r_16 , 0xf1f8, 0xe078, 0x000},
+ {d68000_ror_r_32 , 0xf1f8, 0xe0b8, 0x000},
+ {d68000_ror_ea , 0xffc0, 0xe6c0, 0x3f8},
+ {d68000_rol_s_8 , 0xf1f8, 0xe118, 0x000},
+ {d68000_rol_s_16 , 0xf1f8, 0xe158, 0x000},
+ {d68000_rol_s_32 , 0xf1f8, 0xe198, 0x000},
+ {d68000_rol_r_8 , 0xf1f8, 0xe138, 0x000},
+ {d68000_rol_r_16 , 0xf1f8, 0xe178, 0x000},
+ {d68000_rol_r_32 , 0xf1f8, 0xe1b8, 0x000},
+ {d68000_rol_ea , 0xffc0, 0xe7c0, 0x3f8},
+ {d68000_roxr_s_8 , 0xf1f8, 0xe010, 0x000},
+ {d68000_roxr_s_16 , 0xf1f8, 0xe050, 0x000},
+ {d68000_roxr_s_32 , 0xf1f8, 0xe090, 0x000},
+ {d68000_roxr_r_8 , 0xf1f8, 0xe030, 0x000},
+ {d68000_roxr_r_16 , 0xf1f8, 0xe070, 0x000},
+ {d68000_roxr_r_32 , 0xf1f8, 0xe0b0, 0x000},
+ {d68000_roxr_ea , 0xffc0, 0xe4c0, 0x3f8},
+ {d68000_roxl_s_8 , 0xf1f8, 0xe110, 0x000},
+ {d68000_roxl_s_16 , 0xf1f8, 0xe150, 0x000},
+ {d68000_roxl_s_32 , 0xf1f8, 0xe190, 0x000},
+ {d68000_roxl_r_8 , 0xf1f8, 0xe130, 0x000},
+ {d68000_roxl_r_16 , 0xf1f8, 0xe170, 0x000},
+ {d68000_roxl_r_32 , 0xf1f8, 0xe1b0, 0x000},
+ {d68000_roxl_ea , 0xffc0, 0xe5c0, 0x3f8},
+ {d68010_rtd , 0xffff, 0x4e74, 0x000},
+ {d68000_rte , 0xffff, 0x4e73, 0x000},
+ {d68020_rtm , 0xfff0, 0x06c0, 0x000},
+ {d68000_rtr , 0xffff, 0x4e77, 0x000},
+ {d68000_rts , 0xffff, 0x4e75, 0x000},
+ {d68000_sbcd_rr , 0xf1f8, 0x8100, 0x000},
+ {d68000_sbcd_mm , 0xf1f8, 0x8108, 0x000},
+ {d68000_scc , 0xf0c0, 0x50c0, 0xbf8},
+ {d68000_stop , 0xffff, 0x4e72, 0x000},
+ {d68000_sub_er_8 , 0xf1c0, 0x9000, 0xbff},
+ {d68000_sub_er_16 , 0xf1c0, 0x9040, 0xfff},
+ {d68000_sub_er_32 , 0xf1c0, 0x9080, 0xfff},
+ {d68000_sub_re_8 , 0xf1c0, 0x9100, 0x3f8},
+ {d68000_sub_re_16 , 0xf1c0, 0x9140, 0x3f8},
+ {d68000_sub_re_32 , 0xf1c0, 0x9180, 0x3f8},
+ {d68000_suba_16 , 0xf1c0, 0x90c0, 0xfff},
+ {d68000_suba_32 , 0xf1c0, 0x91c0, 0xfff},
+ {d68000_subi_8 , 0xffc0, 0x0400, 0xbf8},
+ {d68000_subi_16 , 0xffc0, 0x0440, 0xbf8},
+ {d68000_subi_32 , 0xffc0, 0x0480, 0xbf8},
+ {d68000_subq_8 , 0xf1c0, 0x5100, 0xbf8},
+ {d68000_subq_16 , 0xf1c0, 0x5140, 0xff8},
+ {d68000_subq_32 , 0xf1c0, 0x5180, 0xff8},
+ {d68000_subx_rr_8 , 0xf1f8, 0x9100, 0x000},
+ {d68000_subx_rr_16 , 0xf1f8, 0x9140, 0x000},
+ {d68000_subx_rr_32 , 0xf1f8, 0x9180, 0x000},
+ {d68000_subx_mm_8 , 0xf1f8, 0x9108, 0x000},
+ {d68000_subx_mm_16 , 0xf1f8, 0x9148, 0x000},
+ {d68000_subx_mm_32 , 0xf1f8, 0x9188, 0x000},
+ {d68000_swap , 0xfff8, 0x4840, 0x000},
+ {d68000_tas , 0xffc0, 0x4ac0, 0xbf8},
+ {d68000_trap , 0xfff0, 0x4e40, 0x000},
+ {d68020_trapcc_0 , 0xf0ff, 0x50fc, 0x000},
+ {d68020_trapcc_16 , 0xf0ff, 0x50fa, 0x000},
+ {d68020_trapcc_32 , 0xf0ff, 0x50fb, 0x000},
+ {d68000_trapv , 0xffff, 0x4e76, 0x000},
+ {d68000_tst_8 , 0xffc0, 0x4a00, 0xbf8},
+ {d68020_tst_pcdi_8 , 0xffff, 0x4a3a, 0x000},
+ {d68020_tst_pcix_8 , 0xffff, 0x4a3b, 0x000},
+ {d68020_tst_i_8 , 0xffff, 0x4a3c, 0x000},
+ {d68000_tst_16 , 0xffc0, 0x4a40, 0xbf8},
+ {d68020_tst_a_16 , 0xfff8, 0x4a48, 0x000},
+ {d68020_tst_pcdi_16 , 0xffff, 0x4a7a, 0x000},
+ {d68020_tst_pcix_16 , 0xffff, 0x4a7b, 0x000},
+ {d68020_tst_i_16 , 0xffff, 0x4a7c, 0x000},
+ {d68000_tst_32 , 0xffc0, 0x4a80, 0xbf8},
+ {d68020_tst_a_32 , 0xfff8, 0x4a88, 0x000},
+ {d68020_tst_pcdi_32 , 0xffff, 0x4aba, 0x000},
+ {d68020_tst_pcix_32 , 0xffff, 0x4abb, 0x000},
+ {d68020_tst_i_32 , 0xffff, 0x4abc, 0x000},
+ {d68000_unlk , 0xfff8, 0x4e58, 0x000},
+ {d68020_unpk_rr , 0xf1f8, 0x8180, 0x000},
+ {d68020_unpk_mm , 0xf1f8, 0x8188, 0x000},
+ {d68851_p000 , 0xffc0, 0xf000, 0x000},
+ {d68851_pbcc16 , 0xffc0, 0xf080, 0x000},
+ {d68851_pbcc32 , 0xffc0, 0xf0c0, 0x000},
+ {d68851_pdbcc , 0xfff8, 0xf048, 0x000},
+ {d68851_p001 , 0xffc0, 0xf040, 0x000},
+ {0, 0, 0, 0}
+};
+
+/* Check if opcode is using a valid ea mode */
+static int valid_ea(UINT32 opcode, UINT32 mask)
+{
+ if(mask == 0)
+ return 1;
+
+ switch(opcode & 0x3f)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03:
+ case 0x04: case 0x05: case 0x06: case 0x07:
+ return (mask & 0x800) != 0;
+ case 0x08: case 0x09: case 0x0a: case 0x0b:
+ case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ return (mask & 0x400) != 0;
+ case 0x10: case 0x11: case 0x12: case 0x13:
+ case 0x14: case 0x15: case 0x16: case 0x17:
+ return (mask & 0x200) != 0;
+ case 0x18: case 0x19: case 0x1a: case 0x1b:
+ case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ return (mask & 0x100) != 0;
+ case 0x20: case 0x21: case 0x22: case 0x23:
+ case 0x24: case 0x25: case 0x26: case 0x27:
+ return (mask & 0x080) != 0;
+ case 0x28: case 0x29: case 0x2a: case 0x2b:
+ case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ return (mask & 0x040) != 0;
+ case 0x30: case 0x31: case 0x32: case 0x33:
+ case 0x34: case 0x35: case 0x36: case 0x37:
+ return (mask & 0x020) != 0;
+ case 0x38:
+ return (mask & 0x010) != 0;
+ case 0x39:
+ return (mask & 0x008) != 0;
+ case 0x3a:
+ return (mask & 0x002) != 0;
+ case 0x3b:
+ return (mask & 0x001) != 0;
+ case 0x3c:
+ return (mask & 0x004) != 0;
+ }
+ return 0;
+
+}
+
+/* Used by qsort */
+static int DECL_SPEC compare_nof_true_bits(const void *aptr, const void *bptr)
+{
+ UINT32 a = ((const opcode_struct*)aptr)->mask;
+ UINT32 b = ((const opcode_struct*)bptr)->mask;
+
+ a = ((a & 0xAAAA) >> 1) + (a & 0x5555);
+ a = ((a & 0xCCCC) >> 2) + (a & 0x3333);
+ a = ((a & 0xF0F0) >> 4) + (a & 0x0F0F);
+ a = ((a & 0xFF00) >> 8) + (a & 0x00FF);
+
+ b = ((b & 0xAAAA) >> 1) + (b & 0x5555);
+ b = ((b & 0xCCCC) >> 2) + (b & 0x3333);
+ b = ((b & 0xF0F0) >> 4) + (b & 0x0F0F);
+ b = ((b & 0xFF00) >> 8) + (b & 0x00FF);
+
+ return b - a; /* reversed to get greatest to least sorting */
+}
+
+/* build the opcode handler jump table */
+static void build_opcode_table(void)
+{
+ UINT32 i;
+ UINT32 opcode;
+ opcode_struct* ostruct;
+ opcode_struct opcode_info[ARRAY_LENGTH(g_opcode_info)];
+
+ memcpy(opcode_info, g_opcode_info, sizeof(g_opcode_info));
+ qsort((void *)opcode_info, ARRAY_LENGTH(opcode_info)-1, sizeof(opcode_info[0]), compare_nof_true_bits);
+
+ for(i=0;i<0x10000;i++)
+ {
+ g_instruction_table[i] = d68000_illegal; /* default to illegal */
+ opcode = i;
+ /* search through opcode info for a match */
+ for(ostruct = opcode_info;ostruct->opcode_handler != 0;ostruct++)
+ {
+ /* match opcode mask and allowed ea modes */
+ if((opcode & ostruct->mask) == ostruct->match)
+ {
+ /* Handle destination ea for move instructions */
+ if((ostruct->opcode_handler == d68000_move_8 ||
+ ostruct->opcode_handler == d68000_move_16 ||
+ ostruct->opcode_handler == d68000_move_32) &&
+ !valid_ea(((opcode>>9)&7) | ((opcode>>3)&0x38), 0xbf8))
+ continue;
+ if(valid_ea(opcode, ostruct->ea_mask))
+ {
+ g_instruction_table[i] = ostruct->opcode_handler;
+ break;
+ }
+ }
+ }
+ }
+}
+
+
+
+/* ======================================================================== */
+/* ================================= API ================================== */
+/* ======================================================================== */
+
+/* Disasemble one instruction at pc and store in str_buff */
+static unsigned int m68k_disassemble(char* str_buff, unsigned int pc, unsigned int cpu_type)
+{
+ if(!g_initialized)
+ {
+ build_opcode_table();
+ g_initialized = 1;
+ }
+ switch(cpu_type)
+ {
+ case M68K_CPU_TYPE_68000:
+ g_cpu_type = TYPE_68000;
+ break;
+ case M68K_CPU_TYPE_68008:
+ g_cpu_type = TYPE_68008;
+ break;
+ case M68K_CPU_TYPE_68010:
+ g_cpu_type = TYPE_68010;
+ break;
+ case M68K_CPU_TYPE_68EC020:
+ case M68K_CPU_TYPE_68020:
+ g_cpu_type = TYPE_68020;
+ break;
+ case M68K_CPU_TYPE_68EC030:
+ case M68K_CPU_TYPE_68030:
+ g_cpu_type = TYPE_68030;
+ break;
+ case M68K_CPU_TYPE_68040:
+ case M68K_CPU_TYPE_68EC040:
+ case M68K_CPU_TYPE_68LC040:
+ g_cpu_type = TYPE_68040;
+ break;
+ default:
+ return 0;
+ }
+
+ g_cpu_pc = pc;
+ g_helper_str[0] = 0;
+ g_cpu_ir = read_imm_16();
+ g_opcode_type = 0;
+ g_instruction_table[g_cpu_ir]();
+ sprintf(str_buff, "%s%s", g_dasm_str, g_helper_str);
+ return COMBINE_OPCODE_FLAGS(g_cpu_pc - pc);
+}
+
+#ifdef UNUSED_FUNCTION
+char* m68ki_disassemble_quick(unsigned int pc, unsigned int cpu_type)
+{
+ static char buff[100];
+ buff[0] = 0;
+ m68k_disassemble(buff, pc, cpu_type);
+ return buff;
+}
+#endif
+
+unsigned int m68k_disassemble_raw(char* str_buff, unsigned int pc, const unsigned char* opdata, const unsigned char* argdata, unsigned int cpu_type)
+{
+ unsigned int result;
+
+ g_rawop = opdata;
+ g_rawbasepc = pc;
+ result = m68k_disassemble(str_buff, pc, cpu_type);
+ g_rawop = NULL;
+ return result;
+}
+
+#ifdef UNUSED_FUNCTION
+/* Check if the instruction is a valid one */
+unsigned int m68k_is_valid_instruction(unsigned int instruction, unsigned int cpu_type)
+{
+ if(!g_initialized)
+ {
+ build_opcode_table();
+ g_initialized = 1;
+ }
+
+ instruction &= 0xffff;
+ if(g_instruction_table[instruction] == d68000_illegal)
+ return 0;
+
+ switch(cpu_type)
+ {
+ case M68K_CPU_TYPE_68000:
+ case M68K_CPU_TYPE_68008:
+ if(g_instruction_table[instruction] == d68010_bkpt)
+ return 0;
+ if(g_instruction_table[instruction] == d68010_move_fr_ccr)
+ return 0;
+ if(g_instruction_table[instruction] == d68010_movec)
+ return 0;
+ if(g_instruction_table[instruction] == d68010_moves_8)
+ return 0;
+ if(g_instruction_table[instruction] == d68010_moves_16)
+ return 0;
+ if(g_instruction_table[instruction] == d68010_moves_32)
+ return 0;
+ if(g_instruction_table[instruction] == d68010_rtd)
+ return 0;
+ case M68K_CPU_TYPE_68010:
+ if(g_instruction_table[instruction] == d68020_bcc_32)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_bfchg)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_bfclr)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_bfexts)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_bfextu)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_bfffo)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_bfins)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_bfset)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_bftst)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_bra_32)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_bsr_32)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_callm)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_cas_8)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_cas_16)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_cas_32)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_cas2_16)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_cas2_32)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_chk_32)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_chk2_cmp2_8)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_chk2_cmp2_16)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_chk2_cmp2_32)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_cmpi_pcdi_8)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_cmpi_pcix_8)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_cmpi_pcdi_16)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_cmpi_pcix_16)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_cmpi_pcdi_32)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_cmpi_pcix_32)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_cpbcc_16)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_cpbcc_32)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_cpdbcc)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_cpgen)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_cprestore)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_cpsave)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_cpscc)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_cptrapcc_0)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_cptrapcc_16)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_cptrapcc_32)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_divl)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_extb_32)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_link_32)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_mull)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_pack_rr)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_pack_mm)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_rtm)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_trapcc_0)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_trapcc_16)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_trapcc_32)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_tst_pcdi_8)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_tst_pcix_8)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_tst_i_8)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_tst_a_16)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_tst_pcdi_16)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_tst_pcix_16)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_tst_i_16)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_tst_a_32)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_tst_pcdi_32)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_tst_pcix_32)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_tst_i_32)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_unpk_rr)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_unpk_mm)
+ return 0;
+ case M68K_CPU_TYPE_68EC020:
+ case M68K_CPU_TYPE_68020:
+ case M68K_CPU_TYPE_68030:
+ case M68K_CPU_TYPE_68EC030:
+ if(g_instruction_table[instruction] == d68040_cinv)
+ return 0;
+ if(g_instruction_table[instruction] == d68040_cpush)
+ return 0;
+ if(g_instruction_table[instruction] == d68040_move16_pi_pi)
+ return 0;
+ if(g_instruction_table[instruction] == d68040_move16_pi_al)
+ return 0;
+ if(g_instruction_table[instruction] == d68040_move16_al_pi)
+ return 0;
+ if(g_instruction_table[instruction] == d68040_move16_ai_al)
+ return 0;
+ if(g_instruction_table[instruction] == d68040_move16_al_ai)
+ return 0;
+ case M68K_CPU_TYPE_68040:
+ case M68K_CPU_TYPE_68EC040:
+ case M68K_CPU_TYPE_68LC040:
+ if(g_instruction_table[instruction] == d68020_cpbcc_16)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_cpbcc_32)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_cpdbcc)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_cpgen)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_cprestore)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_cpsave)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_cpscc)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_cptrapcc_0)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_cptrapcc_16)
+ return 0;
+ if(g_instruction_table[instruction] == d68020_cptrapcc_32)
+ return 0;
+ if(g_instruction_table[instruction] == d68040_pflush)
+ return 0;
+ }
+ if(cpu_type != M68K_CPU_TYPE_68020 && cpu_type != M68K_CPU_TYPE_68EC020 &&
+ (g_instruction_table[instruction] == d68020_callm ||
+ g_instruction_table[instruction] == d68020_rtm))
+ return 0;
+
+ return 1;
+}
+#endif
+
+CPU_DISASSEMBLE( m68000 )
+{
+ return m68k_disassemble_raw(buffer, pc, oprom, opram, M68K_CPU_TYPE_68000);
+}
+
+CPU_DISASSEMBLE( m68008 )
+{
+ return m68k_disassemble_raw(buffer, pc, oprom, opram, M68K_CPU_TYPE_68008);
+}
+
+CPU_DISASSEMBLE( m68010 )
+{
+ return m68k_disassemble_raw(buffer, pc, oprom, opram, M68K_CPU_TYPE_68010);
+}
+
+CPU_DISASSEMBLE( m68020 )
+{
+ return m68k_disassemble_raw(buffer, pc, oprom, opram, M68K_CPU_TYPE_68020);
+}
+
+CPU_DISASSEMBLE( m68030 )
+{
+ return m68k_disassemble_raw(buffer, pc, oprom, opram, M68K_CPU_TYPE_68030);
+}
+
+CPU_DISASSEMBLE( m68040 )
+{
+ return m68k_disassemble_raw(buffer, pc, oprom, opram, M68K_CPU_TYPE_68040);
+}
+
+// f028 2215 0008
+
+/* ======================================================================== */
+/* ============================== END OF FILE ============================= */
+/* ======================================================================== */
diff --git a/trunk/src/emu/cpu/m68000/m68kfpu.c b/trunk/src/emu/cpu/m68000/m68kfpu.c
new file mode 100644
index 00000000000..9556df0a6c2
--- /dev/null
+++ b/trunk/src/emu/cpu/m68000/m68kfpu.c
@@ -0,0 +1,1993 @@
+#include <math.h>
+
+#define FPCC_N 0x08000000
+#define FPCC_Z 0x04000000
+#define FPCC_I 0x02000000
+#define FPCC_NAN 0x01000000
+
+#define DOUBLE_INFINITY U64(0x7ff0000000000000)
+#define DOUBLE_EXPONENT U64(0x7ff0000000000000)
+#define DOUBLE_MANTISSA U64(0x000fffffffffffff)
+
+extern flag floatx80_is_nan( floatx80 a );
+
+// masks for packed dwords, positive k-factor
+static const UINT32 pkmask2[18] =
+{
+ 0xffffffff, 0, 0xf0000000, 0xff000000, 0xfff00000, 0xffff0000,
+ 0xfffff000, 0xffffff00, 0xfffffff0, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff
+};
+
+static const UINT32 pkmask3[18] =
+{
+ 0xffffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xf0000000, 0xff000000, 0xfff00000, 0xffff0000,
+ 0xfffff000, 0xffffff00, 0xfffffff0, 0xffffffff,
+};
+
+INLINE double fx80_to_double(floatx80 fx)
+{
+ UINT64 d;
+ double *foo;
+
+ foo = (double *)&d;
+
+ d = floatx80_to_float64(fx);
+
+ return *foo;
+}
+
+INLINE floatx80 double_to_fx80(double in)
+{
+ UINT64 *d;
+
+ d = (UINT64 *)&in;
+
+ return float64_to_floatx80(*d);
+}
+
+INLINE floatx80 load_extended_float80(m68ki_cpu_core *m68k, UINT32 ea)
+{
+ UINT32 d1,d2;
+ UINT16 d3;
+ floatx80 fp;
+
+ d3 = m68ki_read_16(m68k, ea);
+ d1 = m68ki_read_32(m68k, ea+4);
+ d2 = m68ki_read_32(m68k, ea+8);
+
+ fp.high = d3;
+ fp.low = ((UINT64)d1<<32) | (d2 & 0xffffffff);
+
+ return fp;
+}
+
+INLINE void store_extended_float80(m68ki_cpu_core *m68k, UINT32 ea, floatx80 fpr)
+{
+ m68ki_write_16(m68k, ea+0, fpr.high);
+ m68ki_write_16(m68k, ea+2, 0);
+ m68ki_write_32(m68k, ea+4, (fpr.low>>32)&0xffffffff);
+ m68ki_write_32(m68k, ea+8, fpr.low&0xffffffff);
+}
+
+INLINE floatx80 load_pack_float80(m68ki_cpu_core *m68k, UINT32 ea)
+{
+ UINT32 dw1, dw2, dw3;
+ floatx80 result;
+ double tmp;
+ char str[128], *ch;
+
+ dw1 = m68ki_read_32(m68k, ea);
+ dw2 = m68ki_read_32(m68k, ea+4);
+ dw3 = m68ki_read_32(m68k, ea+8);
+
+ ch = &str[0];
+ if (dw1 & 0x80000000) // mantissa sign
+ {
+ *ch++ = '-';
+ }
+ *ch++ = (char)((dw1 & 0xf) + '0');
+ *ch++ = '.';
+ *ch++ = (char)(((dw2 >> 28) & 0xf) + '0');
+ *ch++ = (char)(((dw2 >> 24) & 0xf) + '0');
+ *ch++ = (char)(((dw2 >> 20) & 0xf) + '0');
+ *ch++ = (char)(((dw2 >> 16) & 0xf) + '0');
+ *ch++ = (char)(((dw2 >> 12) & 0xf) + '0');
+ *ch++ = (char)(((dw2 >> 8) & 0xf) + '0');
+ *ch++ = (char)(((dw2 >> 4) & 0xf) + '0');
+ *ch++ = (char)(((dw2 >> 0) & 0xf) + '0');
+ *ch++ = (char)(((dw3 >> 28) & 0xf) + '0');
+ *ch++ = (char)(((dw3 >> 24) & 0xf) + '0');
+ *ch++ = (char)(((dw3 >> 20) & 0xf) + '0');
+ *ch++ = (char)(((dw3 >> 16) & 0xf) + '0');
+ *ch++ = (char)(((dw3 >> 12) & 0xf) + '0');
+ *ch++ = (char)(((dw3 >> 8) & 0xf) + '0');
+ *ch++ = (char)(((dw3 >> 4) & 0xf) + '0');
+ *ch++ = (char)(((dw3 >> 0) & 0xf) + '0');
+ *ch++ = 'E';
+ if (dw1 & 0x40000000) // exponent sign
+ {
+ *ch++ = '-';
+ }
+ *ch++ = (char)(((dw1 >> 24) & 0xf) + '0');
+ *ch++ = (char)(((dw1 >> 20) & 0xf) + '0');
+ *ch++ = (char)(((dw1 >> 16) & 0xf) + '0');
+ *ch = '\0';
+
+ sscanf(str, "%le", &tmp);
+
+ result = double_to_fx80(tmp);
+
+ return result;
+}
+
+INLINE void store_pack_float80(m68ki_cpu_core *m68k, UINT32 ea, int k, floatx80 fpr)
+{
+ UINT32 dw1, dw2, dw3;
+ char str[128], *ch;
+ int i, j, exp;
+
+ dw1 = dw2 = dw3 = 0;
+ ch = &str[0];
+
+ sprintf(str, "%.16e", fx80_to_double(fpr));
+
+ if (*ch == '-')
+ {
+ ch++;
+ dw1 = 0x80000000;
+ }
+
+ if (*ch == '+')
+ {
+ ch++;
+ }
+
+ dw1 |= (*ch++ - '0');
+
+ if (*ch == '.')
+ {
+ ch++;
+ }
+
+ // handle negative k-factor here
+ if ((k <= 0) && (k >= -13))
+ {
+ exp = 0;
+ for (i = 0; i < 3; i++)
+ {
+ if (ch[18+i] >= '0' && ch[18+i] <= '9')
+ {
+ exp = (exp << 4) | (ch[18+i] - '0');
+ }
+ }
+
+ if (ch[17] == '-')
+ {
+ exp = -exp;
+ }
+
+ k = -k;
+ // last digit is (k + exponent - 1)
+ k += (exp - 1);
+
+ // round up the last significant mantissa digit
+ if (ch[k+1] >= '5')
+ {
+ ch[k]++;
+ }
+
+ // zero out the rest of the mantissa digits
+ for (j = (k+1); j < 16; j++)
+ {
+ ch[j] = '0';
+ }
+
+ // now zero out K to avoid tripping the positive K detection below
+ k = 0;
+ }
+
+ // crack 8 digits of the mantissa
+ for (i = 0; i < 8; i++)
+ {
+ dw2 <<= 4;
+ if (*ch >= '0' && *ch <= '9')
+ {
+ dw2 |= *ch++ - '0';
+ }
+ }
+
+ // next 8 digits of the mantissa
+ for (i = 0; i < 8; i++)
+ {
+ dw3 <<= 4;
+ if (*ch >= '0' && *ch <= '9')
+ dw3 |= *ch++ - '0';
+ }
+
+ // handle masking if k is positive
+ if (k >= 1)
+ {
+ if (k <= 17)
+ {
+ dw2 &= pkmask2[k];
+ dw3 &= pkmask3[k];
+ }
+ else
+ {
+ dw2 &= pkmask2[17];
+ dw3 &= pkmask3[17];
+// m68k->fpcr |= (need to set OPERR bit)
+ }
+ }
+
+ // finally, crack the exponent
+ if (*ch == 'e' || *ch == 'E')
+ {
+ ch++;
+ if (*ch == '-')
+ {
+ ch++;
+ dw1 |= 0x40000000;
+ }
+
+ if (*ch == '+')
+ {
+ ch++;
+ }
+
+ j = 0;
+ for (i = 0; i < 3; i++)
+ {
+ if (*ch >= '0' && *ch <= '9')
+ {
+ j = (j << 4) | (*ch++ - '0');
+ }
+ }
+
+ dw1 |= (j << 16);
+ }
+
+ m68ki_write_32(m68k, ea, dw1);
+ m68ki_write_32(m68k, ea+4, dw2);
+ m68ki_write_32(m68k, ea+8, dw3);
+}
+
+INLINE void SET_CONDITION_CODES(m68ki_cpu_core *m68k, floatx80 reg)
+{
+// UINT64 *regi;
+
+// regi = (UINT64 *)&reg;
+
+ REG_FPSR &= ~(FPCC_N|FPCC_Z|FPCC_I|FPCC_NAN);
+
+ // sign flag
+ if (reg.high & 0x8000)
+ {
+ REG_FPSR |= FPCC_N;
+ }
+
+ // zero flag
+ if (((reg.high & 0x7fff) == 0) && ((reg.low<<1) == 0))
+ {
+ REG_FPSR |= FPCC_Z;
+ }
+
+ // infinity flag
+ if (((reg.high & 0x7fff) == 0x7fff) && ((reg.low<<1) == 0))
+ {
+ REG_FPSR |= FPCC_I;
+ }
+
+ // NaN flag
+ if (floatx80_is_nan(reg))
+ {
+ REG_FPSR |= FPCC_NAN;
+ }
+}
+
+INLINE int TEST_CONDITION(m68ki_cpu_core *m68k, int condition)
+{
+ int n = (REG_FPSR & FPCC_N) != 0;
+ int z = (REG_FPSR & FPCC_Z) != 0;
+ int nan = (REG_FPSR & FPCC_NAN) != 0;
+ int r = 0;
+ switch (condition)
+ {
+ case 0x10:
+ case 0x00: return 0; // False
+
+ case 0x11:
+ case 0x01: return (z); // Equal
+
+ case 0x12:
+ case 0x02: return (!(nan || z || n)); // Greater Than
+
+ case 0x13:
+ case 0x03: return (z || !(nan || n)); // Greater or Equal
+
+ case 0x14:
+ case 0x04: return (n && !(nan || z)); // Less Than
+
+ case 0x15:
+ case 0x05: return (z || (n && !nan)); // Less Than or Equal
+
+ case 0x16:
+ case 0x06: return !nan && !z;
+
+ case 0x17:
+ case 0x07: return !nan;
+
+ case 0x18:
+ case 0x08: return nan;
+
+ case 0x19:
+ case 0x09: return nan || z;
+
+ case 0x1a:
+ case 0x0a: return (nan || !(n || z)); // Not Less Than or Equal
+
+ case 0x1b:
+ case 0x0b: return (nan || z || !n); // Not Less Than
+
+ case 0x1c:
+ case 0x0c: return (nan || (n && !z)); // Not Greater or Equal Than
+
+ case 0x1d:
+ case 0x0d: return (nan || z || n); // Not Greater Than
+
+ case 0x1e:
+ case 0x0e: return (!z); // Not Equal
+
+ case 0x1f:
+ case 0x0f: return 1; // True
+
+ default: fatalerror("M68kFPU: test_condition: unhandled condition %02X\n", condition);
+ }
+
+ return r;
+}
+
+static UINT8 READ_EA_8(m68ki_cpu_core *m68k, int ea)
+{
+ int mode = (ea >> 3) & 0x7;
+ int reg = (ea & 0x7);
+
+ switch (mode)
+ {
+ case 0: // Dn
+ {
+ return REG_D[reg];
+ }
+ case 2: // (An)
+ {
+ UINT32 ea = REG_A[reg];
+ return m68ki_read_8(m68k, ea);
+ }
+ case 3: // (An)+
+ {
+ UINT32 ea = EA_AY_PI_8(m68k);
+ return m68ki_read_8(m68k, ea);
+ }
+ case 4: // -(An)
+ {
+ UINT32 ea = EA_AY_PD_8(m68k);
+ return m68ki_read_8(m68k, ea);
+ }
+ case 5: // (d16, An)
+ {
+ UINT32 ea = EA_AY_DI_8(m68k);
+ return m68ki_read_8(m68k, ea);
+ }
+ case 6: // (An) + (Xn) + d8
+ {
+ UINT32 ea = EA_AY_IX_8(m68k);
+ return m68ki_read_8(m68k, ea);
+ }
+ case 7:
+ {
+ switch (reg)
+ {
+ case 0: // (xxx).W
+ {
+ UINT32 ea = (UINT32)OPER_I_16(m68k);
+ return m68ki_read_8(m68k, ea);
+ }
+ case 1: // (xxx).L
+ {
+ UINT32 d1 = OPER_I_16(m68k);
+ UINT32 d2 = OPER_I_16(m68k);
+ UINT32 ea = (d1 << 16) | d2;
+ return m68ki_read_8(m68k, ea);
+ }
+ case 2: // (d16, PC)
+ {
+ UINT32 ea = EA_PCDI_8(m68k);
+ return m68ki_read_8(m68k, ea);
+ }
+ case 3: // (PC) + (Xn) + d8
+ {
+ UINT32 ea = EA_PCIX_8(m68k);
+ return m68ki_read_8(m68k, ea);
+ }
+ case 4: // #<data>
+ {
+ return OPER_I_8(m68k);
+ }
+ default: fatalerror("M68kFPU: READ_EA_8: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
+ }
+ break;
+ }
+ default: fatalerror("M68kFPU: READ_EA_8: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
+ }
+
+ return 0;
+}
+
+static UINT16 READ_EA_16(m68ki_cpu_core *m68k, int ea)
+{
+ int mode = (ea >> 3) & 0x7;
+ int reg = (ea & 0x7);
+
+ switch (mode)
+ {
+ case 0: // Dn
+ {
+ return (UINT16)(REG_D[reg]);
+ }
+ case 2: // (An)
+ {
+ UINT32 ea = REG_A[reg];
+ return m68ki_read_16(m68k, ea);
+ }
+ case 3: // (An)+
+ {
+ UINT32 ea = EA_AY_PI_16(m68k);
+ return m68ki_read_16(m68k, ea);
+ }
+ case 4: // -(An)
+ {
+ UINT32 ea = EA_AY_PD_16(m68k);
+ return m68ki_read_16(m68k, ea);
+ }
+ case 5: // (d16, An)
+ {
+ UINT32 ea = EA_AY_DI_16(m68k);
+ return m68ki_read_16(m68k, ea);
+ }
+ case 6: // (An) + (Xn) + d8
+ {
+ UINT32 ea = EA_AY_IX_16(m68k);
+ return m68ki_read_16(m68k, ea);
+ }
+ case 7:
+ {
+ switch (reg)
+ {
+ case 0: // (xxx).W
+ {
+ UINT32 ea = (UINT32)OPER_I_16(m68k);
+ return m68ki_read_16(m68k, ea);
+ }
+ case 1: // (xxx).L
+ {
+ UINT32 d1 = OPER_I_16(m68k);
+ UINT32 d2 = OPER_I_16(m68k);
+ UINT32 ea = (d1 << 16) | d2;
+ return m68ki_read_16(m68k, ea);
+ }
+ case 2: // (d16, PC)
+ {
+ UINT32 ea = EA_PCDI_16(m68k);
+ return m68ki_read_16(m68k, ea);
+ }
+ case 3: // (PC) + (Xn) + d8
+ {
+ UINT32 ea = EA_PCIX_16(m68k);
+ return m68ki_read_16(m68k, ea);
+ }
+ case 4: // #<data>
+ {
+ return OPER_I_16(m68k);
+ }
+
+ default: fatalerror("M68kFPU: READ_EA_16: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
+ }
+ break;
+ }
+ default: fatalerror("M68kFPU: READ_EA_16: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
+ }
+
+ return 0;
+}
+
+static UINT32 READ_EA_32(m68ki_cpu_core *m68k, int ea)
+{
+ int mode = (ea >> 3) & 0x7;
+ int reg = (ea & 0x7);
+
+ switch (mode)
+ {
+ case 0: // Dn
+ {
+ return REG_D[reg];
+ }
+ case 2: // (An)
+ {
+ UINT32 ea = REG_A[reg];
+ return m68ki_read_32(m68k, ea);
+ }
+ case 3: // (An)+
+ {
+ UINT32 ea = EA_AY_PI_32(m68k);
+ return m68ki_read_32(m68k, ea);
+ }
+ case 4: // -(An)
+ {
+ UINT32 ea = EA_AY_PD_32(m68k);
+ return m68ki_read_32(m68k, ea);
+ }
+ case 5: // (d16, An)
+ {
+ UINT32 ea = EA_AY_DI_32(m68k);
+ return m68ki_read_32(m68k, ea);
+ }
+ case 6: // (An) + (Xn) + d8
+ {
+ UINT32 ea = EA_AY_IX_32(m68k);
+ return m68ki_read_32(m68k, ea);
+ }
+ case 7:
+ {
+ switch (reg)
+ {
+ case 0: // (xxx).W
+ {
+ UINT32 ea = (UINT32)OPER_I_16(m68k);
+ return m68ki_read_32(m68k, ea);
+ }
+ case 1: // (xxx).L
+ {
+ UINT32 d1 = OPER_I_16(m68k);
+ UINT32 d2 = OPER_I_16(m68k);
+ UINT32 ea = (d1 << 16) | d2;
+ return m68ki_read_32(m68k, ea);
+ }
+ case 2: // (d16, PC)
+ {
+ UINT32 ea = EA_PCDI_32(m68k);
+ return m68ki_read_32(m68k, ea);
+ }
+ case 3: // (PC) + (Xn) + d8
+ {
+ UINT32 ea = EA_PCIX_32(m68k);
+ return m68ki_read_32(m68k, ea);
+ }
+ case 4: // #<data>
+ {
+ return OPER_I_32(m68k);
+ }
+ default: fatalerror("M68kFPU: READ_EA_32: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
+ }
+ break;
+ }
+ default: fatalerror("M68kFPU: READ_EA_32: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
+ }
+ return 0;
+}
+
+static UINT64 READ_EA_64(m68ki_cpu_core *m68k, int ea)
+{
+ int mode = (ea >> 3) & 0x7;
+ int reg = (ea & 0x7);
+ UINT32 h1, h2;
+
+ switch (mode)
+ {
+ case 2: // (An)
+ {
+ UINT32 ea = REG_A[reg];
+ h1 = m68ki_read_32(m68k, ea+0);
+ h2 = m68ki_read_32(m68k, ea+4);
+ return (UINT64)(h1) << 32 | (UINT64)(h2);
+ }
+ case 3: // (An)+
+ {
+ UINT32 ea = REG_A[reg];
+ REG_A[reg] += 8;
+ h1 = m68ki_read_32(m68k, ea+0);
+ h2 = m68ki_read_32(m68k, ea+4);
+ return (UINT64)(h1) << 32 | (UINT64)(h2);
+ }
+ case 4: // -(An)
+ {
+ UINT32 ea = REG_A[reg]-8;
+ REG_A[reg] -= 8;
+ h1 = m68ki_read_32(m68k, ea+0);
+ h2 = m68ki_read_32(m68k, ea+4);
+ return (UINT64)(h1) << 32 | (UINT64)(h2);
+ }
+ case 5: // (d16, An)
+ {
+ UINT32 ea = EA_AY_DI_32(m68k);
+ h1 = m68ki_read_32(m68k, ea+0);
+ h2 = m68ki_read_32(m68k, ea+4);
+ return (UINT64)(h1) << 32 | (UINT64)(h2);
+ }
+ case 6: // (An) + (Xn) + d8
+ {
+ UINT32 ea = EA_AY_IX_32(m68k);
+ h1 = m68ki_read_32(m68k, ea+0);
+ h2 = m68ki_read_32(m68k, ea+4);
+ return (UINT64)(h1) << 32 | (UINT64)(h2);
+ }
+ case 7:
+ {
+ switch (reg)
+ {
+ case 1: // (xxx).L
+ {
+ UINT32 d1 = OPER_I_16(m68k);
+ UINT32 d2 = OPER_I_16(m68k);
+ UINT32 ea = (d1 << 16) | d2;
+ return (UINT64)(m68ki_read_32(m68k, ea)) << 32 | (UINT64)(m68ki_read_32(m68k, ea+4));
+ }
+ case 3: // (PC) + (Xn) + d8
+ {
+ UINT32 ea = EA_PCIX_32(m68k);
+ h1 = m68ki_read_32(m68k, ea+0);
+ h2 = m68ki_read_32(m68k, ea+4);
+ return (UINT64)(h1) << 32 | (UINT64)(h2);
+ }
+ case 4: // #<data>
+ {
+ h1 = OPER_I_32(m68k);
+ h2 = OPER_I_32(m68k);
+ return (UINT64)(h1) << 32 | (UINT64)(h2);
+ }
+ case 2: // (d16, PC)
+ {
+ UINT32 ea = EA_PCDI_32(m68k);
+ h1 = m68ki_read_32(m68k, ea+0);
+ h2 = m68ki_read_32(m68k, ea+4);
+ return (UINT64)(h1) << 32 | (UINT64)(h2);
+ }
+ default: fatalerror("M68kFPU: READ_EA_64: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
+ }
+ break;
+ }
+ default: fatalerror("M68kFPU: READ_EA_64: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
+ }
+
+ return 0;
+}
+
+
+static floatx80 READ_EA_FPE(m68ki_cpu_core *m68k, int ea)
+{
+ floatx80 fpr;
+ int mode = (ea >> 3) & 0x7;
+ int reg = (ea & 0x7);
+
+ switch (mode)
+ {
+ case 2: // (An)
+ {
+ UINT32 ea = REG_A[reg];
+ fpr = load_extended_float80(m68k, ea);
+ break;
+ }
+
+ case 3: // (An)+
+ {
+ UINT32 ea = REG_A[reg];
+ REG_A[reg] += 12;
+ fpr = load_extended_float80(m68k, ea);
+ break;
+ }
+ case 4: // -(An)
+ {
+ UINT32 ea = REG_A[reg]-12;
+ REG_A[reg] -= 12;
+ fpr = load_extended_float80(m68k, ea);
+ break;
+ }
+ case 5: // (d16, An)
+ {
+ // FIXME: will fail for fmovem
+ UINT32 ea = EA_AY_DI_32(m68k);
+ fpr = load_extended_float80(m68k, ea);
+ break;
+ }
+ case 6: // (An) + (Xn) + d8
+ {
+ // FIXME: will fail for fmovem
+ UINT32 ea = EA_AY_IX_32(m68k);
+ fpr = load_extended_float80(m68k, ea);
+ break;
+ }
+
+ case 7: // extended modes
+ {
+ switch (reg)
+ {
+ case 2: // (d16, PC)
+ {
+ UINT32 ea = EA_PCDI_32(m68k);
+ fpr = load_extended_float80(m68k, ea);
+ }
+ break;
+
+ case 3: // (d16,PC,Dx.w)
+ {
+ UINT32 ea = EA_PCIX_32(m68k);
+ fpr = load_extended_float80(m68k, ea);
+ }
+ break;
+
+ default:
+ fatalerror("M68kFPU: READ_EA_FPE: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC);
+ break;
+ }
+ }
+ break;
+
+ default: fatalerror("M68kFPU: READ_EA_FPE: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC); break;
+ }
+
+ return fpr;
+}
+
+static floatx80 READ_EA_PACK(m68ki_cpu_core *m68k, int ea)
+{
+ floatx80 fpr;
+ int mode = (ea >> 3) & 0x7;
+ int reg = (ea & 0x7);
+
+ switch (mode)
+ {
+ case 2: // (An)
+ {
+ UINT32 ea = REG_A[reg];
+ fpr = load_pack_float80(m68k, ea);
+ break;
+ }
+
+ case 3: // (An)+
+ {
+ UINT32 ea = REG_A[reg];
+ REG_A[reg] += 12;
+ fpr = load_pack_float80(m68k, ea);
+ break;
+ }
+
+ case 7: // extended modes
+ {
+ switch (reg)
+ {
+ case 3: // (d16,PC,Dx.w)
+ {
+ UINT32 ea = EA_PCIX_32(m68k);
+ fpr = load_pack_float80(m68k, ea);
+ }
+ break;
+
+ default:
+ fatalerror("M68kFPU: READ_EA_PACK: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC);
+ break;
+ }
+ }
+ break;
+
+ default: fatalerror("M68kFPU: READ_EA_PACK: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC); break;
+ }
+
+ return fpr;
+}
+
+static void WRITE_EA_8(m68ki_cpu_core *m68k, int ea, UINT8 data)
+{
+ int mode = (ea >> 3) & 0x7;
+ int reg = (ea & 0x7);
+
+ switch (mode)
+ {
+ case 0: // Dn
+ {
+ REG_D[reg] = data;
+ break;
+ }
+ case 2: // (An)
+ {
+ UINT32 ea = REG_A[reg];
+ m68ki_write_8(m68k, ea, data);
+ break;
+ }
+ case 3: // (An)+
+ {
+ UINT32 ea = EA_AY_PI_8(m68k);
+ m68ki_write_8(m68k, ea, data);
+ break;
+ }
+ case 4: // -(An)
+ {
+ UINT32 ea = EA_AY_PD_8(m68k);
+ m68ki_write_8(m68k, ea, data);
+ break;
+ }
+ case 5: // (d16, An)
+ {
+ UINT32 ea = EA_AY_DI_8(m68k);
+ m68ki_write_8(m68k, ea, data);
+ break;
+ }
+ case 6: // (An) + (Xn) + d8
+ {
+ UINT32 ea = EA_AY_IX_8(m68k);
+ m68ki_write_8(m68k, ea, data);
+ break;
+ }
+ case 7:
+ {
+ switch (reg)
+ {
+ case 1: // (xxx).B
+ {
+ UINT32 d1 = OPER_I_16(m68k);
+ UINT32 d2 = OPER_I_16(m68k);
+ UINT32 ea = (d1 << 16) | d2;
+ m68ki_write_8(m68k, ea, data);
+ break;
+ }
+ case 2: // (d16, PC)
+ {
+ UINT32 ea = EA_PCDI_16(m68k);
+ m68ki_write_8(m68k, ea, data);
+ break;
+ }
+ default: fatalerror("M68kFPU: WRITE_EA_8: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
+ }
+ break;
+ }
+ default: fatalerror("M68kFPU: WRITE_EA_8: unhandled mode %d, reg %d, data %08X at %08X\n", mode, reg, data, REG_PC);
+ }
+}
+
+static void WRITE_EA_16(m68ki_cpu_core *m68k, int ea, UINT16 data)
+{
+ int mode = (ea >> 3) & 0x7;
+ int reg = (ea & 0x7);
+
+ switch (mode)
+ {
+ case 0: // Dn
+ {
+ REG_D[reg] = data;
+ break;
+ }
+ case 2: // (An)
+ {
+ UINT32 ea = REG_A[reg];
+ m68ki_write_16(m68k, ea, data);
+ break;
+ }
+ case 3: // (An)+
+ {
+ UINT32 ea = EA_AY_PI_16(m68k);
+ m68ki_write_16(m68k, ea, data);
+ break;
+ }
+ case 4: // -(An)
+ {
+ UINT32 ea = EA_AY_PD_16(m68k);
+ m68ki_write_16(m68k, ea, data);
+ break;
+ }
+ case 5: // (d16, An)
+ {
+ UINT32 ea = EA_AY_DI_16(m68k);
+ m68ki_write_16(m68k, ea, data);
+ break;
+ }
+ case 6: // (An) + (Xn) + d8
+ {
+ UINT32 ea = EA_AY_IX_16(m68k);
+ m68ki_write_16(m68k, ea, data);
+ break;
+ }
+ case 7:
+ {
+ switch (reg)
+ {
+ case 1: // (xxx).W
+ {
+ UINT32 d1 = OPER_I_16(m68k);
+ UINT32 d2 = OPER_I_16(m68k);
+ UINT32 ea = (d1 << 16) | d2;
+ m68ki_write_16(m68k, ea, data);
+ break;
+ }
+ case 2: // (d16, PC)
+ {
+ UINT32 ea = EA_PCDI_16(m68k);
+ m68ki_write_16(m68k, ea, data);
+ break;
+ }
+ default: fatalerror("M68kFPU: WRITE_EA_16: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
+ }
+ break;
+ }
+ default: fatalerror("M68kFPU: WRITE_EA_16: unhandled mode %d, reg %d, data %08X at %08X\n", mode, reg, data, REG_PC);
+ }
+}
+
+static void WRITE_EA_32(m68ki_cpu_core *m68k, int ea, UINT32 data)
+{
+ int mode = (ea >> 3) & 0x7;
+ int reg = (ea & 0x7);
+
+ switch (mode)
+ {
+ case 0: // Dn
+ {
+ REG_D[reg] = data;
+ break;
+ }
+ case 1: // An
+ {
+ REG_A[reg] = data;
+ break;
+ }
+ case 2: // (An)
+ {
+ UINT32 ea = REG_A[reg];
+ m68ki_write_32(m68k, ea, data);
+ break;
+ }
+ case 3: // (An)+
+ {
+ UINT32 ea = EA_AY_PI_32(m68k);
+ m68ki_write_32(m68k, ea, data);
+ break;
+ }
+ case 4: // -(An)
+ {
+ UINT32 ea = EA_AY_PD_32(m68k);
+ m68ki_write_32(m68k, ea, data);
+ break;
+ }
+ case 5: // (d16, An)
+ {
+ UINT32 ea = EA_AY_DI_32(m68k);
+ m68ki_write_32(m68k, ea, data);
+ break;
+ }
+ case 6: // (An) + (Xn) + d8
+ {
+ UINT32 ea = EA_AY_IX_32(m68k);
+ m68ki_write_32(m68k, ea, data);
+ break;
+ }
+ case 7:
+ {
+ switch (reg)
+ {
+ case 1: // (xxx).L
+ {
+ UINT32 d1 = OPER_I_16(m68k);
+ UINT32 d2 = OPER_I_16(m68k);
+ UINT32 ea = (d1 << 16) | d2;
+ m68ki_write_32(m68k, ea, data);
+ break;
+ }
+ case 2: // (d16, PC)
+ {
+ UINT32 ea = EA_PCDI_32(m68k);
+ m68ki_write_32(m68k, ea, data);
+ break;
+ }
+ default: fatalerror("M68kFPU: WRITE_EA_32: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
+ }
+ break;
+ }
+ default: fatalerror("M68kFPU: WRITE_EA_32: unhandled mode %d, reg %d, data %08X at %08X\n", mode, reg, data, REG_PC);
+ }
+}
+
+static void WRITE_EA_64(m68ki_cpu_core *m68k, int ea, UINT64 data)
+{
+ int mode = (ea >> 3) & 0x7;
+ int reg = (ea & 0x7);
+
+ switch (mode)
+ {
+ case 2: // (An)
+ {
+ UINT32 ea = REG_A[reg];
+ m68ki_write_32(m68k, ea, (UINT32)(data >> 32));
+ m68ki_write_32(m68k, ea+4, (UINT32)(data));
+ break;
+ }
+ case 3: // (An)+
+ {
+ UINT32 ea = REG_A[reg];
+ REG_A[reg] += 8;
+ m68ki_write_32(m68k, ea+0, (UINT32)(data >> 32));
+ m68ki_write_32(m68k, ea+4, (UINT32)(data));
+ break;
+ }
+ case 4: // -(An)
+ {
+ UINT32 ea;
+ REG_A[reg] -= 8;
+ ea = REG_A[reg];
+ m68ki_write_32(m68k, ea+0, (UINT32)(data >> 32));
+ m68ki_write_32(m68k, ea+4, (UINT32)(data));
+ break;
+ }
+ case 5: // (d16, An)
+ {
+ UINT32 ea = EA_AY_DI_32(m68k);
+ m68ki_write_32(m68k, ea+0, (UINT32)(data >> 32));
+ m68ki_write_32(m68k, ea+4, (UINT32)(data));
+ break;
+ }
+ case 6: // (An) + (Xn) + d8
+ {
+ UINT32 ea = EA_AY_IX_32(m68k);
+ m68ki_write_32(m68k, ea+0, (UINT32)(data >> 32));
+ m68ki_write_32(m68k, ea+4, (UINT32)(data));
+ break;
+ }
+ case 7:
+ {
+ switch (reg)
+ {
+ case 1: // (xxx).L
+ {
+ UINT32 d1 = OPER_I_16(m68k);
+ UINT32 d2 = OPER_I_16(m68k);
+ UINT32 ea = (d1 << 16) | d2;
+ m68ki_write_32(m68k, ea+0, (UINT32)(data >> 32));
+ m68ki_write_32(m68k, ea+4, (UINT32)(data));
+ break;
+ }
+ case 2: // (d16, PC)
+ {
+ UINT32 ea = EA_PCDI_32(m68k);
+ m68ki_write_32(m68k, ea+0, (UINT32)(data >> 32));
+ m68ki_write_32(m68k, ea+4, (UINT32)(data));
+ break;
+ }
+ default: fatalerror("M68kFPU: WRITE_EA_64: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
+ }
+ break;
+ }
+ default: fatalerror("M68kFPU: WRITE_EA_64: unhandled mode %d, reg %d, data %08X%08X at %08X\n", mode, reg, (UINT32)(data >> 32), (UINT32)(data), REG_PC);
+ }
+}
+
+static void WRITE_EA_FPE(m68ki_cpu_core *m68k, int ea, floatx80 fpr)
+{
+ int mode = (ea >> 3) & 0x7;
+ int reg = (ea & 0x7);
+
+ switch (mode)
+ {
+ case 2: // (An)
+ {
+ UINT32 ea;
+ ea = REG_A[reg];
+ store_extended_float80(m68k, ea, fpr);
+ break;
+ }
+
+ case 3: // (An)+
+ {
+ UINT32 ea;
+ ea = REG_A[reg];
+ store_extended_float80(m68k, ea, fpr);
+ REG_A[reg] += 12;
+ break;
+ }
+
+ case 4: // -(An)
+ {
+ UINT32 ea;
+ REG_A[reg] -= 12;
+ ea = REG_A[reg];
+ store_extended_float80(m68k, ea, fpr);
+ break;
+ }
+
+ case 7:
+ {
+ switch (reg)
+ {
+ default: fatalerror("M68kFPU: WRITE_EA_FPE: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC);
+ }
+ }
+ default: fatalerror("M68kFPU: WRITE_EA_FPE: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC);
+ }
+}
+
+static void WRITE_EA_PACK(m68ki_cpu_core *m68k, int ea, int k, floatx80 fpr)
+{
+ int mode = (ea >> 3) & 0x7;
+ int reg = (ea & 0x7);
+
+ switch (mode)
+ {
+ case 2: // (An)
+ {
+ UINT32 ea;
+ ea = REG_A[reg];
+ store_pack_float80(m68k, ea, k, fpr);
+ break;
+ }
+
+ case 3: // (An)+
+ {
+ UINT32 ea;
+ ea = REG_A[reg];
+ store_pack_float80(m68k, ea, k, fpr);
+ REG_A[reg] += 12;
+ break;
+ }
+
+ case 4: // -(An)
+ {
+ UINT32 ea;
+ REG_A[reg] -= 12;
+ ea = REG_A[reg];
+ store_pack_float80(m68k, ea, k, fpr);
+ break;
+ }
+
+ case 7:
+ {
+ switch (reg)
+ {
+ default: fatalerror("M68kFPU: WRITE_EA_PACK: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC);
+ }
+ }
+ default: fatalerror("M68kFPU: WRITE_EA_PACK: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC);
+ }
+}
+
+static void fpgen_rm_reg(m68ki_cpu_core *m68k, UINT16 w2)
+{
+ int ea = m68k->ir & 0x3f;
+ int rm = (w2 >> 14) & 0x1;
+ int src = (w2 >> 10) & 0x7;
+ int dst = (w2 >> 7) & 0x7;
+ int opmode = w2 & 0x7f;
+ floatx80 source;
+
+ // fmovecr #$f, fp0 f200 5c0f
+
+ if (rm)
+ {
+ switch (src)
+ {
+ case 0: // Long-Word Integer
+ {
+ INT32 d = READ_EA_32(m68k, ea);
+ source = int32_to_floatx80(d);
+ break;
+ }
+ case 1: // Single-precision Real
+ {
+ UINT32 d = READ_EA_32(m68k, ea);
+ source = float32_to_floatx80(d);
+ break;
+ }
+ case 2: // Extended-precision Real
+ {
+ source = READ_EA_FPE(m68k, ea);
+ break;
+ }
+ case 3: // Packed-decimal Real
+ {
+ source = READ_EA_PACK(m68k, ea);
+ break;
+ }
+ case 4: // Word Integer
+ {
+ INT16 d = READ_EA_16(m68k, ea);
+ source = int32_to_floatx80((INT32)d);
+ break;
+ }
+ case 5: // Double-precision Real
+ {
+ UINT64 d = READ_EA_64(m68k, ea);
+
+ source = float64_to_floatx80(d);
+ break;
+ }
+ case 6: // Byte Integer
+ {
+ INT8 d = READ_EA_8(m68k, ea);
+ source = int32_to_floatx80((INT32)d);
+ break;
+ }
+ case 7: // FMOVECR load from constant ROM
+ {
+ switch (w2 & 0x7f)
+ {
+ case 0x0: // Pi
+ source.high = 0x4000;
+ source.low = U64(0xc90fdaa22168c235);
+ break;
+
+ case 0xb: // log10(2)
+ source.high = 0x3ffd;
+ source.low = U64(0x9a209a84fbcff798);
+ break;
+
+ case 0xc: // e
+ source.high = 0x4000;
+ source.low = U64(0xadf85458a2bb4a9b);
+ break;
+
+ case 0xd: // log2(e)
+ source.high = 0x3fff;
+ source.low = U64(0xb8aa3b295c17f0bc);
+ break;
+
+ case 0xe: // log10(e)
+ source.high = 0x3ffd;
+ source.low = U64(0xde5bd8a937287195);
+ break;
+
+ case 0xf: // 0.0
+ source = int32_to_floatx80((INT32)0);
+ break;
+
+ case 0x30: // ln(2)
+ source.high = 0x3ffe;
+ source.low = U64(0xb17217f7d1cf79ac);
+ break;
+
+ case 0x31: // ln(10)
+ source.high = 0x4000;
+ source.low = U64(0x935d8dddaaa8ac17);
+ break;
+
+ case 0x32: // 1 (or 100? manuals are unclear, but 1 would make more sense)
+ source = int32_to_floatx80((INT32)1);
+ break;
+
+ case 0x33: // 10^1
+ source = int32_to_floatx80((INT32)10);
+ break;
+
+ case 0x34: // 10^2
+ source = int32_to_floatx80((INT32)10*10);
+ break;
+
+ default:
+ fatalerror("fmove_rm_reg: unknown constant ROM offset %x at %08x\n", w2&0x7f, REG_PC-4);
+ break;
+ }
+
+ // handle it right here, the usual opmode bits aren't valid in the FMOVECR case
+ REG_FP[dst] = source;
+ m68k->remaining_cycles -= 4;
+ return;
+ }
+ default: fatalerror("fmove_rm_reg: invalid source specifier %x at %08X\n", src, REG_PC-4);
+ }
+ }
+ else
+ {
+ source = REG_FP[src];
+ }
+
+
+
+ switch (opmode)
+ {
+ case 0x00: // FMOVE
+ {
+ REG_FP[dst] = source;
+ SET_CONDITION_CODES(m68k, REG_FP[dst]);
+ m68k->remaining_cycles -= 4;
+ break;
+ }
+ case 0x01: // FINT
+ {
+ INT32 temp;
+ temp = floatx80_to_int32(source);
+ REG_FP[dst] = int32_to_floatx80(temp);
+ break;
+ }
+ case 0x03: // FINTRZ
+ {
+ INT32 temp;
+ temp = floatx80_to_int32_round_to_zero(source);
+ REG_FP[dst] = int32_to_floatx80(temp);
+ break;
+ }
+ case 0x04: // FSQRT
+ {
+ REG_FP[dst] = floatx80_sqrt(source);
+ SET_CONDITION_CODES(m68k, REG_FP[dst]);
+ m68k->remaining_cycles -= 109;
+ break;
+ }
+ case 0x0e: // FSIN
+ {
+ REG_FP[dst] = source;
+ floatx80_fsin(REG_FP[dst]);
+ SET_CONDITION_CODES(m68k, REG_FP[dst]);
+ m68k->remaining_cycles -= 75;
+ break;
+ }
+ case 0x0f: // FTAN
+ {
+ REG_FP[dst] = source;
+ floatx80_ftan(REG_FP[dst]);
+ SET_CONDITION_CODES(m68k, REG_FP[dst]);
+ m68k->remaining_cycles -= 75;
+ break;
+ }
+ case 0x18: // FABS
+ {
+ REG_FP[dst] = source;
+ REG_FP[dst].high &= 0x7fff;
+ SET_CONDITION_CODES(m68k, REG_FP[dst]);
+ m68k->remaining_cycles -= 3;
+ break;
+ }
+ case 0x1a: // FNEG
+ {
+ REG_FP[dst] = source;
+ REG_FP[dst].high ^= 0x8000;
+ SET_CONDITION_CODES(m68k, REG_FP[dst]);
+ m68k->remaining_cycles -= 3;
+ break;
+ }
+ case 0x1d: // FCOS
+ {
+ REG_FP[dst] = source;
+ floatx80_fcos(REG_FP[dst]);
+ SET_CONDITION_CODES(m68k, REG_FP[dst]);
+ m68k->remaining_cycles -= 75;
+ break;
+ }
+ case 0x1e: // FGETEXP
+ {
+ INT16 temp2;
+
+ temp2 = source.high; // get the exponent
+ temp2 -= 0x3fff; // take off the bias
+ REG_FP[dst] = double_to_fx80((double)temp2);
+ SET_CONDITION_CODES(m68k, REG_FP[dst]);
+ m68k->remaining_cycles -= 6;
+ }
+ case 0x20: // FDIV
+ {
+ REG_FP[dst] = floatx80_div(REG_FP[dst], source);
+ m68k->remaining_cycles -= 43;
+ break;
+ }
+ case 0x22: // FADD
+ {
+ REG_FP[dst] = floatx80_add(REG_FP[dst], source);
+ SET_CONDITION_CODES(m68k, REG_FP[dst]);
+ m68k->remaining_cycles -= 9;
+ break;
+ }
+ case 0x23: // FMUL
+ {
+ REG_FP[dst] = floatx80_mul(REG_FP[dst], source);
+ SET_CONDITION_CODES(m68k, REG_FP[dst]);
+ m68k->remaining_cycles -= 11;
+ break;
+ }
+ case 0x24: // FSGLDIV
+ {
+ REG_FP[dst] = floatx80_div(REG_FP[dst], source);
+ m68k->remaining_cycles -= 43; // // ? (value is from FDIV)
+ break;
+ }
+ case 0x25: // FREM
+ {
+ REG_FP[dst] = floatx80_rem(REG_FP[dst], source);
+ SET_CONDITION_CODES(m68k, REG_FP[dst]);
+ m68k->remaining_cycles -= 43; // guess
+ break;
+ }
+ case 0x27: // FSGLMUL
+ {
+ REG_FP[dst] = floatx80_mul(REG_FP[dst], source);
+ SET_CONDITION_CODES(m68k, REG_FP[dst]);
+ m68k->remaining_cycles -= 11; // ? (value is from FMUL)
+ break;
+ }
+ case 0x28: // FSUB
+ {
+ REG_FP[dst] = floatx80_sub(REG_FP[dst], source);
+ SET_CONDITION_CODES(m68k, REG_FP[dst]);
+ m68k->remaining_cycles -= 9;
+ break;
+ }
+ case 0x38: // FCMP
+ {
+ floatx80 res;
+ res = floatx80_sub(REG_FP[dst], source);
+ SET_CONDITION_CODES(m68k, res);
+ m68k->remaining_cycles -= 7;
+ break;
+ }
+ case 0x3a: // FTST
+ {
+ floatx80 res;
+ res = source;
+ SET_CONDITION_CODES(m68k, res);
+ m68k->remaining_cycles -= 7;
+ break;
+ }
+
+ default: fatalerror("fpgen_rm_reg: unimplemented opmode %02X at %08X\n", opmode, REG_PPC);
+ }
+}
+
+static void fmove_reg_mem(m68ki_cpu_core *m68k, UINT16 w2)
+{
+ int ea = m68k->ir & 0x3f;
+ int src = (w2 >> 7) & 0x7;
+ int dst = (w2 >> 10) & 0x7;
+ int k = (w2 & 0x7f);
+
+ switch (dst)
+ {
+ case 0: // Long-Word Integer
+ {
+ INT32 d = (INT32)floatx80_to_int32(REG_FP[src]);
+ WRITE_EA_32(m68k, ea, d);
+ break;
+ }
+ case 1: // Single-precision Real
+ {
+ UINT32 d = floatx80_to_float32(REG_FP[src]);
+ WRITE_EA_32(m68k, ea, d);
+ break;
+ }
+ case 2: // Extended-precision Real
+ {
+ WRITE_EA_FPE(m68k, ea, REG_FP[src]);
+ break;
+ }
+ case 3: // Packed-decimal Real with Static K-factor
+ {
+ // sign-extend k
+ k = (k & 0x40) ? (k | 0xffffff80) : (k & 0x7f);
+ WRITE_EA_PACK(m68k, ea, k, REG_FP[src]);
+ break;
+ }
+ case 4: // Word Integer
+ {
+ WRITE_EA_16(m68k, ea, (INT16)floatx80_to_int32(REG_FP[src]));
+ break;
+ }
+ case 5: // Double-precision Real
+ {
+ UINT64 d;
+
+ d = floatx80_to_float64(REG_FP[src]);
+
+ WRITE_EA_64(m68k, ea, d);
+ break;
+ }
+ case 6: // Byte Integer
+ {
+ WRITE_EA_8(m68k, ea, (INT8)floatx80_to_int32(REG_FP[src]));
+ break;
+ }
+ case 7: // Packed-decimal Real with Dynamic K-factor
+ {
+ WRITE_EA_PACK(m68k, ea, REG_D[k>>4], REG_FP[src]);
+ break;
+ }
+ }
+
+ m68k->remaining_cycles -= 12;
+}
+
+static void fmove_fpcr(m68ki_cpu_core *m68k, UINT16 w2)
+{
+ int ea = m68k->ir & 0x3f;
+ int dir = (w2 >> 13) & 0x1;
+ int regsel = (w2 >> 10) & 0x7;
+ int mode = (ea >> 3) & 0x7;
+
+ if ((mode == 5) || (mode == 6))
+ {
+ UINT32 address = 0xffffffff; // force a bus error if this doesn't get assigned
+
+ if (mode == 5)
+ {
+ address = EA_AY_DI_32(m68k);
+ }
+ else if (mode == 6)
+ {
+ address = EA_AY_IX_32(m68k);
+ }
+
+ if (dir) // From system control reg to <ea>
+ {
+ if (regsel & 4) { m68ki_write_32(m68k, address, REG_FPCR); address += 4; }
+ if (regsel & 2) { m68ki_write_32(m68k, address, REG_FPSR); address += 4; }
+ if (regsel & 1) { m68ki_write_32(m68k, address, REG_FPIAR); address += 4; }
+ }
+ else // From <ea> to system control reg
+ {
+ if (regsel & 4) { REG_FPCR = m68ki_read_32(m68k, address); address += 4; }
+ if (regsel & 2) { REG_FPSR = m68ki_read_32(m68k, address); address += 4; }
+ if (regsel & 1) { REG_FPIAR = m68ki_read_32(m68k, address); address += 4; }
+ }
+ }
+ else
+ {
+ if (dir) // From system control reg to <ea>
+ {
+ if (regsel & 4) WRITE_EA_32(m68k, ea, REG_FPCR);
+ if (regsel & 2) WRITE_EA_32(m68k, ea, REG_FPSR);
+ if (regsel & 1) WRITE_EA_32(m68k, ea, REG_FPIAR);
+ }
+ else // From <ea> to system control reg
+ {
+ if (regsel & 4) REG_FPCR = READ_EA_32(m68k, ea);
+ if (regsel & 2) REG_FPSR = READ_EA_32(m68k, ea);
+ if (regsel & 1) REG_FPIAR = READ_EA_32(m68k, ea);
+ }
+ }
+
+ m68k->remaining_cycles -= 10;
+}
+
+static void fmovem(m68ki_cpu_core *m68k, UINT16 w2)
+{
+ int i;
+ int ea = m68k->ir & 0x3f;
+ int dir = (w2 >> 13) & 0x1;
+ int mode = (w2 >> 11) & 0x3;
+ int reglist = w2 & 0xff;
+
+ UINT32 mem_addr = 0;
+ switch (ea >> 3)
+ {
+ case 5: // (d16, An)
+ mem_addr= EA_AY_DI_32(m68k);
+ break;
+ case 6: // (An) + (Xn) + d8
+ mem_addr= EA_AY_IX_32(m68k);
+ break;
+ }
+
+ if (dir) // From FP regs to mem
+ {
+ switch (mode)
+ {
+ case 1: // Dynamic register list, postincrement or control addressing mode.
+ // FIXME: not really tested, but seems to work
+ reglist = REG_D[(reglist >> 4) & 7];
+
+ case 0: // Static register list, predecrement or control addressing mode
+ {
+ for (i=0; i < 8; i++)
+ {
+ if (reglist & (1 << i))
+ {
+ switch (ea >> 3)
+ {
+ case 5: // (d16, An)
+ case 6: // (An) + (Xn) + d8
+ store_extended_float80(m68k, mem_addr, REG_FP[i]);
+ mem_addr += 12;
+ break;
+ default:
+ WRITE_EA_FPE(m68k, ea, REG_FP[i]);
+ break;
+ }
+
+ m68k->remaining_cycles -= 2;
+ }
+ }
+ break;
+ }
+
+ case 2: // Static register list, postdecrement or control addressing mode
+ {
+ for (i=0; i < 8; i++)
+ {
+ if (reglist & (1 << i))
+ {
+ switch (ea >> 3)
+ {
+ case 5: // (d16, An)
+ case 6: // (An) + (Xn) + d8
+ store_extended_float80(m68k, mem_addr, REG_FP[7-i]);
+ mem_addr += 12;
+ break;
+ default:
+ WRITE_EA_FPE(m68k, ea, REG_FP[7-i]);
+ break;
+ }
+
+ m68k->remaining_cycles -= 2;
+ }
+ }
+ break;
+ }
+
+ default: fatalerror("M680x0: FMOVEM: mode %d unimplemented at %08X\n", mode, REG_PC-4);
+ }
+ }
+ else // From mem to FP regs
+ {
+ switch (mode)
+ {
+ case 3: // Dynamic register list, predecrement addressing mode.
+ // FIXME: not really tested, but seems to work
+ reglist = REG_D[(reglist >> 4) & 7];
+
+ case 2: // Static register list, postincrement or control addressing mode
+ {
+ for (i=0; i < 8; i++)
+ {
+ if (reglist & (1 << i))
+ {
+ switch (ea >> 3)
+ {
+ case 5: // (d16, An)
+ case 6: // (An) + (Xn) + d8
+ REG_FP[7-i] = load_extended_float80(m68k, mem_addr);
+ mem_addr += 12;
+ break;
+ default:
+ REG_FP[7-i] = READ_EA_FPE(m68k, ea);
+ break;
+ }
+ m68k->remaining_cycles -= 2;
+ }
+ }
+ break;
+ }
+
+ default: fatalerror("M680x0: FMOVEM: mode %d unimplemented at %08X\n", mode, REG_PC-4);
+ }
+ }
+}
+
+static void fscc(m68ki_cpu_core *m68k)
+{
+ int ea = m68k->ir & 0x3f;
+ int condition = (INT16)(OPER_I_16(m68k));
+
+ WRITE_EA_8(m68k, ea, TEST_CONDITION(m68k, condition) ? 0xff : 0);
+ m68k->remaining_cycles -= 7; // ???
+}
+
+static void fbcc16(m68ki_cpu_core *m68k)
+{
+ INT32 offset;
+ int condition = m68k->ir & 0x3f;
+
+ offset = (INT16)(OPER_I_16(m68k));
+
+ // TODO: condition and jump!!!
+ if (TEST_CONDITION(m68k, condition))
+ {
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+ m68ki_branch_16(m68k, offset-2);
+ }
+
+ m68k->remaining_cycles -= 7;
+}
+
+static void fbcc32(m68ki_cpu_core *m68k)
+{
+ INT32 offset;
+ int condition = m68k->ir & 0x3f;
+
+ offset = OPER_I_32(m68k);
+
+ // TODO: condition and jump!!!
+ if (TEST_CONDITION(m68k, condition))
+ {
+ m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
+ m68ki_branch_32(m68k, offset-4);
+ }
+
+ m68k->remaining_cycles -= 7;
+}
+
+
+void m68040_fpu_op0(m68ki_cpu_core *m68k)
+{
+ m68k->fpu_just_reset = 0;
+
+ switch ((m68k->ir >> 6) & 0x3)
+ {
+ case 0:
+ {
+ UINT16 w2 = OPER_I_16(m68k);
+ switch ((w2 >> 13) & 0x7)
+ {
+ case 0x0: // FPU ALU FP, FP
+ case 0x2: // FPU ALU ea, FP
+ {
+ fpgen_rm_reg(m68k, w2);
+ break;
+ }
+
+ case 0x3: // FMOVE FP, ea
+ {
+ fmove_reg_mem(m68k, w2);
+ break;
+ }
+
+ case 0x4: // FMOVEM ea, FPCR
+ case 0x5: // FMOVEM FPCR, ea
+ {
+ fmove_fpcr(m68k, w2);
+ break;
+ }
+
+ case 0x6: // FMOVEM ea, list
+ case 0x7: // FMOVEM list, ea
+ {
+ fmovem(m68k, w2);
+ break;
+ }
+
+ default: fatalerror("M68kFPU: unimplemented subop %d at %08X\n", (w2 >> 13) & 0x7, REG_PC-4);
+ }
+ break;
+ }
+
+ case 1: // FBcc disp16
+ {
+ switch ((m68k->ir >> 3) & 0x7) {
+ case 1: // FDBcc
+ // TODO:
+ break;
+ default: // FScc (?)
+ fscc(m68k);
+ return;
+ }
+ fatalerror("M68kFPU: unimplemented main op %d with mode %d at %08X\n", (m68k->ir >> 6) & 0x3, (m68k->ir >> 3) & 0x7, REG_PPC);
+ }
+
+ case 2: // FBcc disp16
+ {
+ fbcc16(m68k);
+ break;
+ }
+ case 3: // FBcc disp32
+ {
+ fbcc32(m68k);
+ break;
+ }
+
+ default: fatalerror("M68kFPU: unimplemented main op %d\n", (m68k->ir >> 6) & 0x3);
+ }
+}
+
+static void perform_fsave(m68ki_cpu_core *m68k, UINT32 addr, int inc)
+{
+ if (inc)
+ {
+ // 68881 IDLE, version 0x1f
+ m68ki_write_32(m68k, addr, 0x1f180000);
+ m68ki_write_32(m68k, addr+4, 0);
+ m68ki_write_32(m68k, addr+8, 0);
+ m68ki_write_32(m68k, addr+12, 0);
+ m68ki_write_32(m68k, addr+16, 0);
+ m68ki_write_32(m68k, addr+20, 0);
+ m68ki_write_32(m68k, addr+24, 0x70000000);
+ }
+ else
+ {
+ m68ki_write_32(m68k, addr, 0x70000000);
+ m68ki_write_32(m68k, addr-4, 0);
+ m68ki_write_32(m68k, addr-8, 0);
+ m68ki_write_32(m68k, addr-12, 0);
+ m68ki_write_32(m68k, addr-16, 0);
+ m68ki_write_32(m68k, addr-20, 0);
+ m68ki_write_32(m68k, addr-24, 0x1f180000);
+ }
+}
+
+// FRESTORE on a NULL frame reboots the FPU - all registers to NaN, the 3 status regs to 0
+static void do_frestore_null(m68ki_cpu_core *m68k)
+{
+ int i;
+
+ REG_FPCR = 0;
+ REG_FPSR = 0;
+ REG_FPIAR = 0;
+ for (i = 0; i < 8; i++)
+ {
+ REG_FP[i].high = 0x7fff;
+ REG_FP[i].low = U64(0xffffffffffffffff);
+ }
+
+ // Mac IIci at 408458e6 wants an FSAVE of a just-restored NULL frame to also be NULL
+ // The PRM says it's possible to generate a NULL frame, but not how/when/why. (need the 68881/68882 manual!)
+ m68k->fpu_just_reset = 1;
+}
+
+void m68040_fpu_op1(m68ki_cpu_core *m68k)
+{
+ int ea = m68k->ir & 0x3f;
+ int mode = (ea >> 3) & 0x7;
+ int reg = (ea & 0x7);
+ UINT32 addr, temp;
+
+ switch ((m68k->ir >> 6) & 0x3)
+ {
+ case 0: // FSAVE <ea>
+ {
+ switch (mode)
+ {
+ case 2: // (An)
+ addr = REG_A[reg];
+
+ if (m68k->fpu_just_reset)
+ {
+ m68ki_write_32(m68k, addr, 0);
+ }
+ else
+ {
+ // we normally generate an IDLE frame
+ perform_fsave(m68k, addr, 1);
+ }
+ break;
+
+ case 3: // (An)+
+ addr = EA_AY_PI_32(m68k);
+
+ if (m68k->fpu_just_reset)
+ {
+ m68ki_write_32(m68k, addr, 0);
+ }
+ else
+ {
+ // we normally generate an IDLE frame
+ REG_A[reg] += 6*4;
+ perform_fsave(m68k, addr, 1);
+ }
+ break;
+
+ case 4: // -(An)
+ addr = EA_AY_PD_32(m68k);
+
+ if (m68k->fpu_just_reset)
+ {
+ m68ki_write_32(m68k, addr, 0);
+ }
+ else
+ {
+ // we normally generate an IDLE frame
+ REG_A[reg] -= 6*4;
+ perform_fsave(m68k, addr, 0);
+ }
+ break;
+
+ default:
+ fatalerror("M68kFPU: FSAVE unhandled mode %d reg %d at %x\n", mode, reg, REG_PC);
+ }
+ break;
+ }
+ break;
+
+ case 1: // FRESTORE <ea>
+ {
+ switch (mode)
+ {
+ case 2: // (An)
+ addr = REG_A[reg];
+ temp = m68ki_read_32(m68k, addr);
+
+ // check for NULL frame
+ if (temp & 0xff000000)
+ {
+ // we don't handle non-NULL frames and there's no pre/post inc/dec to do here
+ m68k->fpu_just_reset = 0;
+ }
+ else
+ {
+ do_frestore_null(m68k);
+ }
+ break;
+
+ case 3: // (An)+
+ addr = EA_AY_PI_32(m68k);
+ temp = m68ki_read_32(m68k, addr);
+
+ // check for NULL frame
+ if (temp & 0xff000000)
+ {
+ m68k->fpu_just_reset = 0;
+
+ // how about an IDLE frame?
+ if ((temp & 0x00ff0000) == 0x00180000)
+ {
+ REG_A[reg] += 6*4;
+ } // check UNIMP
+ else if ((temp & 0x00ff0000) == 0x00380000)
+ {
+ REG_A[reg] += 14*4;
+ } // check BUSY
+ else if ((temp & 0x00ff0000) == 0x00b40000)
+ {
+ REG_A[reg] += 45*4;
+ }
+ }
+ else
+ {
+ do_frestore_null(m68k);
+ }
+ break;
+
+ case 5: // (D16, An)
+ addr = EA_AY_DI_16(m68k);
+ temp = m68ki_read_32(m68k, addr);
+
+ // check for NULL frame
+ if (temp & 0xff000000)
+ {
+ // we don't handle non-NULL frames and there's no pre/post inc/dec to do here
+ m68k->fpu_just_reset = 0;
+ }
+ else
+ {
+ do_frestore_null(m68k);
+ }
+ break;
+
+ case 7: //
+ switch (reg)
+ {
+ case 2: // (d16, PC)
+ {
+ addr = EA_PCDI_16(m68k);;
+ temp = m68ki_read_32(m68k, addr);
+
+ // check for NULL frame
+ if (temp & 0xff000000)
+ {
+ // we don't handle non-NULL frames and there's no pre/post inc/dec to do here
+ m68k->fpu_just_reset = 0;
+ }
+ else
+ {
+ do_frestore_null(m68k);
+ }
+ break;
+ }
+ default:
+ fatalerror("M68kFPU: FRESTORE unhandled mode %d reg %d at %x\n", mode, reg, REG_PC);
+ }
+
+ break;
+
+ default:
+ fatalerror("M68kFPU: FRESTORE unhandled mode %d reg %d at %x\n", mode, reg, REG_PC);
+ }
+ break;
+ }
+ break;
+
+ default: fatalerror("m68040_fpu_op1: unimplemented op %d at %08X\n", (m68k->ir >> 6) & 0x3, REG_PC-2);
+ }
+}
+
+
+
diff --git a/trunk/src/emu/cpu/m68000/m68kmake.c b/trunk/src/emu/cpu/m68000/m68kmake.c
new file mode 100644
index 00000000000..d8c6fb3ec9c
--- /dev/null
+++ b/trunk/src/emu/cpu/m68000/m68kmake.c
@@ -0,0 +1,1433 @@
+/* ======================================================================== */
+/* ========================= LICENSING & COPYRIGHT ======================== */
+/* ======================================================================== */
+/*
+ * MUSASHI
+ * Version 4.70
+ *
+ * A portable Motorola M680x0 processor emulation engine.
+ * Copyright Karl Stenerud. All rights reserved.
+ * FPU and MMU by R. Belmont.
+ *
+ * This code may be freely used for non-commercial purposes as long as this
+ * copyright notice remains unaltered in the source code and any binary files
+ * containing this code in compiled form.
+ *
+ * All other licensing terms must be negotiated with the author
+ * (Karl Stenerud).
+ *
+ * The latest version of this code can be obtained at:
+ * http://kstenerud.cjb.net or http://mamedev.org/
+ */
+
+/*
+ * Modified For OpenVMS By: Robert Alan Byer
+ * byer@mail.ourservers.net
+ *
+ * 68030 and PMMU by R. Belmont and Hans Ostermeyer
+ * 68040 and FPU by Ville Linde, R. Belmont, and Hans Ostermeyer
+ */
+
+
+/* ======================================================================== */
+/* ============================ CODE GENERATOR ============================ */
+/* ======================================================================== */
+/*
+ * This is the code generator program which will generate the opcode table
+ * and the final opcode handlers.
+ *
+ * It requires an input file to function (default m68k_in.c), but you can
+ * specify your own like so:
+ *
+ * m68kmake <output path> <input file>
+ *
+ * where output path is the path where the output files should be placed, and
+ * input file is the file to use for input.
+ *
+ * If you modify the input file greatly from its released form, you may have
+ * to tweak the configuration section a bit since I'm using static allocation
+ * to keep things simple.
+ *
+ *
+ * TODO: - build a better code generator for the move instruction.
+ * - Add callm and rtm instructions
+ * - Fix RTE to handle other format words
+ * - Add address error (and bus error?) handling
+ */
+
+
+static const char g_version[] = "4.70";
+
+/* ======================================================================== */
+/* =============================== INCLUDES =============================== */
+/* ======================================================================== */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdarg.h>
+
+
+
+/* ======================================================================== */
+/* ============================= CONFIGURATION ============================ */
+/* ======================================================================== */
+
+#define M68K_MAX_PATH 1024
+#define M68K_MAX_DIR 1024
+
+#define MAX_LINE_LENGTH 200 /* length of 1 line */
+#define MAX_BODY_LENGTH 300 /* Number of lines in 1 function */
+#define MAX_REPLACE_LENGTH 30 /* Max number of replace strings */
+#define MAX_INSERT_LENGTH 5000 /* Max size of insert piece */
+#define MAX_NAME_LENGTH 30 /* Max length of ophandler name */
+#define MAX_SPEC_PROC_LENGTH 4 /* Max length of special processing str */
+#define MAX_SPEC_EA_LENGTH 5 /* Max length of specified EA str */
+#define EA_ALLOWED_LENGTH 11 /* Max length of ea allowed str */
+#define MAX_OPCODE_INPUT_TABLE_LENGTH 1000 /* Max length of opcode handler tbl */
+#define MAX_OPCODE_OUTPUT_TABLE_LENGTH 3000 /* Max length of opcode handler tbl */
+
+/* Default filenames */
+#define FILENAME_INPUT "m68k_in.c"
+#define FILENAME_PROTOTYPE "m68kops.h"
+#define FILENAME_TABLE "m68kops.c"
+
+
+/* Identifier sequences recognized by this program */
+
+#define ID_INPUT_SEPARATOR "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+
+#define ID_BASE "M68KMAKE"
+#define ID_PROTOTYPE_HEADER ID_BASE "_PROTOTYPE_HEADER"
+#define ID_PROTOTYPE_FOOTER ID_BASE "_PROTOTYPE_FOOTER"
+#define ID_TABLE_HEADER ID_BASE "_TABLE_HEADER"
+#define ID_TABLE_FOOTER ID_BASE "_TABLE_FOOTER"
+#define ID_TABLE_BODY ID_BASE "_TABLE_BODY"
+#define ID_TABLE_START ID_BASE "_TABLE_START"
+#define ID_OPHANDLER_HEADER ID_BASE "_OPCODE_HANDLER_HEADER"
+#define ID_OPHANDLER_FOOTER ID_BASE "_OPCODE_HANDLER_FOOTER"
+#define ID_OPHANDLER_BODY ID_BASE "_OPCODE_HANDLER_BODY"
+#define ID_END ID_BASE "_END"
+
+#define ID_OPHANDLER_NAME ID_BASE "_OP"
+#define ID_OPHANDLER_EA_AY_8 ID_BASE "_GET_EA_AY_8"
+#define ID_OPHANDLER_EA_AY_16 ID_BASE "_GET_EA_AY_16"
+#define ID_OPHANDLER_EA_AY_32 ID_BASE "_GET_EA_AY_32"
+#define ID_OPHANDLER_OPER_AY_8 ID_BASE "_GET_OPER_AY_8"
+#define ID_OPHANDLER_OPER_AY_16 ID_BASE "_GET_OPER_AY_16"
+#define ID_OPHANDLER_OPER_AY_32 ID_BASE "_GET_OPER_AY_32"
+#define ID_OPHANDLER_CC ID_BASE "_CC"
+#define ID_OPHANDLER_NOT_CC ID_BASE "_NOT_CC"
+
+
+#ifndef DECL_SPEC
+#define DECL_SPEC
+#endif /* DECL_SPEC */
+
+
+
+/* ======================================================================== */
+/* ============================== PROTOTYPES ============================== */
+/* ======================================================================== */
+
+enum
+{
+ CPU_TYPE_000 = 0,
+ CPU_TYPE_010,
+ CPU_TYPE_020,
+ CPU_TYPE_030,
+ CPU_TYPE_040,
+ NUM_CPUS
+};
+
+#define UNSPECIFIED "."
+#define UNSPECIFIED_CH '.'
+
+#define HAS_NO_EA_MODE(A) (strcmp(A, "..........") == 0)
+#define HAS_EA_AI(A) ((A)[0] == 'A')
+#define HAS_EA_PI(A) ((A)[1] == '+')
+#define HAS_EA_PD(A) ((A)[2] == '-')
+#define HAS_EA_DI(A) ((A)[3] == 'D')
+#define HAS_EA_IX(A) ((A)[4] == 'X')
+#define HAS_EA_AW(A) ((A)[5] == 'W')
+#define HAS_EA_AL(A) ((A)[6] == 'L')
+#define HAS_EA_PCDI(A) ((A)[7] == 'd')
+#define HAS_EA_PCIX(A) ((A)[8] == 'x')
+#define HAS_EA_I(A) ((A)[9] == 'I')
+
+enum
+{
+ EA_MODE_NONE, /* No special addressing mode */
+ EA_MODE_AI, /* Address register indirect */
+ EA_MODE_PI, /* Address register indirect with postincrement */
+ EA_MODE_PI7, /* Address register 7 indirect with postincrement */
+ EA_MODE_PD, /* Address register indirect with predecrement */
+ EA_MODE_PD7, /* Address register 7 indirect with predecrement */
+ EA_MODE_DI, /* Address register indirect with displacement */
+ EA_MODE_IX, /* Address register indirect with index */
+ EA_MODE_AW, /* Absolute word */
+ EA_MODE_AL, /* Absolute long */
+ EA_MODE_PCDI, /* Program counter indirect with displacement */
+ EA_MODE_PCIX, /* Program counter indirect with index */
+ EA_MODE_I /* Immediate */
+};
+
+
+/* Everything we need to know about an opcode */
+typedef struct
+{
+ char name[MAX_NAME_LENGTH]; /* opcode handler name */
+ unsigned char size; /* Size of operation */
+ char spec_proc[MAX_SPEC_PROC_LENGTH]; /* Special processing mode */
+ char spec_ea[MAX_SPEC_EA_LENGTH]; /* Specified effective addressing mode */
+ unsigned char bits; /* Number of significant bits (used for sorting the table) */
+ unsigned short op_mask; /* Mask to apply for matching an opcode to a handler */
+ unsigned short op_match; /* Value to match after masking */
+ char ea_allowed[EA_ALLOWED_LENGTH]; /* Effective addressing modes allowed */
+ char cpu_mode[NUM_CPUS]; /* User or supervisor mode */
+ char cpus[NUM_CPUS+1]; /* Allowed CPUs */
+ unsigned char cycles[NUM_CPUS]; /* cycles for 000, 010, 020, 030, 040 */
+} opcode_struct;
+
+
+/* All modifications necessary for a specific EA mode of an instruction */
+typedef struct
+{
+ const char* fname_add;
+ const char* ea_add;
+ unsigned int mask_add;
+ unsigned int match_add;
+} ea_info_struct;
+
+
+/* Holds the body of a function */
+typedef struct
+{
+ char body[MAX_BODY_LENGTH][MAX_LINE_LENGTH+1];
+ int length;
+} body_struct;
+
+
+/* Holds a sequence of search / replace strings */
+typedef struct
+{
+ char replace[MAX_REPLACE_LENGTH][2][MAX_LINE_LENGTH+1];
+ int length;
+} replace_struct;
+
+
+/* Function Prototypes */
+static void error_exit(const char* fmt, ...);
+static void perror_exit(const char* fmt, ...);
+static int check_strsncpy(char* dst, char* src, int maxlength);
+static int check_atoi(char* str, int *result);
+static int skip_spaces(char* str);
+static int num_bits(int value);
+//int atoh(char* buff);
+static int fgetline(char* buff, int nchars, FILE* file);
+static int get_oper_cycles(opcode_struct* op, int ea_mode, int cpu_type);
+static opcode_struct* find_opcode(char* name, int size, char* spec_proc, char* spec_ea);
+//opcode_struct* find_illegal_opcode(void);
+static int extract_opcode_info(char* src, char* name, int* size, char* spec_proc, char* spec_ea);
+static void add_replace_string(replace_struct* replace, const char* search_str, const char* replace_str);
+static void write_body(FILE* filep, body_struct* body, replace_struct* replace);
+static void get_base_name(char* base_name, opcode_struct* op);
+static void write_function_name(FILE* filep, char* base_name);
+static void add_opcode_output_table_entry(opcode_struct* op, char* name);
+static int DECL_SPEC compare_nof_true_bits(const void* aptr, const void* bptr);
+static void print_opcode_output_table(FILE* filep);
+static void write_table_entry(FILE* filep, opcode_struct* op);
+static void set_opcode_struct(opcode_struct* src, opcode_struct* dst, int ea_mode);
+static void generate_opcode_handler(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* opinfo, int ea_mode);
+static void generate_opcode_ea_variants(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* op);
+static void generate_opcode_cc_variants(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* op_in, int offset);
+static void process_opcode_handlers(FILE* filep);
+static void populate_table(void);
+static void read_insert(char* insert);
+
+
+
+/* ======================================================================== */
+/* ================================= DATA ================================= */
+/* ======================================================================== */
+
+/* Name of the input file */
+static char g_input_filename[M68K_MAX_PATH];
+
+/* File handles */
+static FILE* g_input_file = NULL;
+static FILE* g_prototype_file = NULL;
+static FILE* g_table_file = NULL;
+
+static int g_num_functions = 0; /* Number of functions processed */
+static int g_num_primitives = 0; /* Number of function primitives read */
+static int g_line_number = 1; /* Current line number */
+
+/* Opcode handler table */
+static opcode_struct g_opcode_input_table[MAX_OPCODE_INPUT_TABLE_LENGTH];
+
+static opcode_struct g_opcode_output_table[MAX_OPCODE_OUTPUT_TABLE_LENGTH];
+static int g_opcode_output_table_length = 0;
+
+static const ea_info_struct g_ea_info_table[13] =
+{/* fname ea mask match */
+ {"", "", 0x00, 0x00}, /* EA_MODE_NONE */
+ {"ai", "AY_AI", 0x38, 0x10}, /* EA_MODE_AI */
+ {"pi", "AY_PI", 0x38, 0x18}, /* EA_MODE_PI */
+ {"pi7", "A7_PI", 0x3f, 0x1f}, /* EA_MODE_PI7 */
+ {"pd", "AY_PD", 0x38, 0x20}, /* EA_MODE_PD */
+ {"pd7", "A7_PD", 0x3f, 0x27}, /* EA_MODE_PD7 */
+ {"di", "AY_DI", 0x38, 0x28}, /* EA_MODE_DI */
+ {"ix", "AY_IX", 0x38, 0x30}, /* EA_MODE_IX */
+ {"aw", "AW", 0x3f, 0x38}, /* EA_MODE_AW */
+ {"al", "AL", 0x3f, 0x39}, /* EA_MODE_AL */
+ {"pcdi", "PCDI", 0x3f, 0x3a}, /* EA_MODE_PCDI */
+ {"pcix", "PCIX", 0x3f, 0x3b}, /* EA_MODE_PCIX */
+ {"i", "I", 0x3f, 0x3c}, /* EA_MODE_I */
+};
+
+
+static const char *const g_cc_table[16][2] =
+{
+ { "t", "T"}, /* 0000 */
+ { "f", "F"}, /* 0001 */
+ {"hi", "HI"}, /* 0010 */
+ {"ls", "LS"}, /* 0011 */
+ {"cc", "CC"}, /* 0100 */
+ {"cs", "CS"}, /* 0101 */
+ {"ne", "NE"}, /* 0110 */
+ {"eq", "EQ"}, /* 0111 */
+ {"vc", "VC"}, /* 1000 */
+ {"vs", "VS"}, /* 1001 */
+ {"pl", "PL"}, /* 1010 */
+ {"mi", "MI"}, /* 1011 */
+ {"ge", "GE"}, /* 1100 */
+ {"lt", "LT"}, /* 1101 */
+ {"gt", "GT"}, /* 1110 */
+ {"le", "LE"}, /* 1111 */
+};
+
+/* size to index translator (0 -> 0, 8 and 16 -> 1, 32 -> 2) */
+static const int g_size_select_table[33] =
+{
+ 0, /* unsized */
+ 0, 0, 0, 0, 0, 0, 0, 1, /* 8 */
+ 0, 0, 0, 0, 0, 0, 0, 1, /* 16 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 /* 32 */
+};
+
+/* Extra cycles required for certain EA modes */
+/* TODO: correct timings for 030, 040 */
+static const int g_ea_cycle_table[13][NUM_CPUS][3] =
+{/* 000 010 020 030 040 */
+ {{ 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0}}, /* EA_MODE_NONE */
+ {{ 0, 4, 8}, { 0, 4, 8}, { 0, 4, 4}, { 0, 4, 4}, { 0, 4, 4}}, /* EA_MODE_AI */
+ {{ 0, 4, 8}, { 0, 4, 8}, { 0, 4, 4}, { 0, 4, 4}, { 0, 4, 4}}, /* EA_MODE_PI */
+ {{ 0, 4, 8}, { 0, 4, 8}, { 0, 4, 4}, { 0, 4, 4}, { 0, 4, 4}}, /* EA_MODE_PI7 */
+ {{ 0, 6, 10}, { 0, 6, 10}, { 0, 5, 5}, { 0, 5, 5}, { 0, 5, 5}}, /* EA_MODE_PD */
+ {{ 0, 6, 10}, { 0, 6, 10}, { 0, 5, 5}, { 0, 5, 5}, { 0, 5, 5}}, /* EA_MODE_PD7 */
+ {{ 0, 8, 12}, { 0, 8, 12}, { 0, 5, 5}, { 0, 5, 5}, { 0, 5, 5}}, /* EA_MODE_DI */
+ {{ 0, 10, 14}, { 0, 10, 14}, { 0, 7, 7}, { 0, 7, 7}, { 0, 7, 7}}, /* EA_MODE_IX */
+ {{ 0, 8, 12}, { 0, 8, 12}, { 0, 4, 4}, { 0, 4, 4}, { 0, 4, 4}}, /* EA_MODE_AW */
+ {{ 0, 12, 16}, { 0, 12, 16}, { 0, 4, 4}, { 0, 4, 4}, { 0, 4, 4}}, /* EA_MODE_AL */
+ {{ 0, 8, 12}, { 0, 8, 12}, { 0, 5, 5}, { 0, 5, 5}, { 0, 5, 5}}, /* EA_MODE_PCDI */
+ {{ 0, 10, 14}, { 0, 10, 14}, { 0, 7, 7}, { 0, 7, 7}, { 0, 7, 7}}, /* EA_MODE_PCIX */
+ {{ 0, 4, 8}, { 0, 4, 8}, { 0, 2, 4}, { 0, 2, 4}, { 0, 2, 4}}, /* EA_MODE_I */
+};
+
+/* Extra cycles for JMP instruction (000, 010) */
+static const int g_jmp_cycle_table[13] =
+{
+ 0, /* EA_MODE_NONE */
+ 4, /* EA_MODE_AI */
+ 0, /* EA_MODE_PI */
+ 0, /* EA_MODE_PI7 */
+ 0, /* EA_MODE_PD */
+ 0, /* EA_MODE_PD7 */
+ 6, /* EA_MODE_DI */
+ 10, /* EA_MODE_IX */
+ 6, /* EA_MODE_AW */
+ 8, /* EA_MODE_AL */
+ 6, /* EA_MODE_PCDI */
+ 10, /* EA_MODE_PCIX */
+ 0, /* EA_MODE_I */
+};
+
+/* Extra cycles for JSR instruction (000, 010) */
+static const int g_jsr_cycle_table[13] =
+{
+ 0, /* EA_MODE_NONE */
+ 4, /* EA_MODE_AI */
+ 0, /* EA_MODE_PI */
+ 0, /* EA_MODE_PI7 */
+ 0, /* EA_MODE_PD */
+ 0, /* EA_MODE_PD7 */
+ 6, /* EA_MODE_DI */
+ 10, /* EA_MODE_IX */
+ 6, /* EA_MODE_AW */
+ 8, /* EA_MODE_AL */
+ 6, /* EA_MODE_PCDI */
+ 10, /* EA_MODE_PCIX */
+ 0, /* EA_MODE_I */
+};
+
+/* Extra cycles for LEA instruction (000, 010) */
+static const int g_lea_cycle_table[13] =
+{
+ 0, /* EA_MODE_NONE */
+ 4, /* EA_MODE_AI */
+ 0, /* EA_MODE_PI */
+ 0, /* EA_MODE_PI7 */
+ 0, /* EA_MODE_PD */
+ 0, /* EA_MODE_PD7 */
+ 8, /* EA_MODE_DI */
+ 12, /* EA_MODE_IX */
+ 8, /* EA_MODE_AW */
+ 12, /* EA_MODE_AL */
+ 8, /* EA_MODE_PCDI */
+ 12, /* EA_MODE_PCIX */
+ 0, /* EA_MODE_I */
+};
+
+/* Extra cycles for PEA instruction (000, 010) */
+static const int g_pea_cycle_table[13] =
+{
+ 0, /* EA_MODE_NONE */
+ 6, /* EA_MODE_AI */
+ 0, /* EA_MODE_PI */
+ 0, /* EA_MODE_PI7 */
+ 0, /* EA_MODE_PD */
+ 0, /* EA_MODE_PD7 */
+ 10, /* EA_MODE_DI */
+ 14, /* EA_MODE_IX */
+ 10, /* EA_MODE_AW */
+ 14, /* EA_MODE_AL */
+ 10, /* EA_MODE_PCDI */
+ 14, /* EA_MODE_PCIX */
+ 0, /* EA_MODE_I */
+};
+
+/* Extra cycles for MOVEM instruction (000, 010) */
+static const int g_movem_cycle_table[13] =
+{
+ 0, /* EA_MODE_NONE */
+ 0, /* EA_MODE_AI */
+ 0, /* EA_MODE_PI */
+ 0, /* EA_MODE_PI7 */
+ 0, /* EA_MODE_PD */
+ 0, /* EA_MODE_PD7 */
+ 4, /* EA_MODE_DI */
+ 6, /* EA_MODE_IX */
+ 4, /* EA_MODE_AW */
+ 8, /* EA_MODE_AL */
+ 0, /* EA_MODE_PCDI */
+ 0, /* EA_MODE_PCIX */
+ 0, /* EA_MODE_I */
+};
+
+/* Extra cycles for MOVES instruction (010) */
+static const int g_moves_cycle_table[13][3] =
+{
+ { 0, 0, 0}, /* EA_MODE_NONE */
+ { 0, 4, 6}, /* EA_MODE_AI */
+ { 0, 4, 6}, /* EA_MODE_PI */
+ { 0, 4, 6}, /* EA_MODE_PI7 */
+ { 0, 6, 12}, /* EA_MODE_PD */
+ { 0, 6, 12}, /* EA_MODE_PD7 */
+ { 0, 12, 16}, /* EA_MODE_DI */
+ { 0, 16, 20}, /* EA_MODE_IX */
+ { 0, 12, 16}, /* EA_MODE_AW */
+ { 0, 16, 20}, /* EA_MODE_AL */
+ { 0, 0, 0}, /* EA_MODE_PCDI */
+ { 0, 0, 0}, /* EA_MODE_PCIX */
+ { 0, 0, 0}, /* EA_MODE_I */
+};
+
+/* Extra cycles for CLR instruction (010) */
+static const int g_clr_cycle_table[13][3] =
+{
+ { 0, 0, 0}, /* EA_MODE_NONE */
+ { 0, 4, 6}, /* EA_MODE_AI */
+ { 0, 4, 6}, /* EA_MODE_PI */
+ { 0, 4, 6}, /* EA_MODE_PI7 */
+ { 0, 6, 8}, /* EA_MODE_PD */
+ { 0, 6, 8}, /* EA_MODE_PD7 */
+ { 0, 8, 10}, /* EA_MODE_DI */
+ { 0, 10, 14}, /* EA_MODE_IX */
+ { 0, 8, 10}, /* EA_MODE_AW */
+ { 0, 10, 14}, /* EA_MODE_AL */
+ { 0, 0, 0}, /* EA_MODE_PCDI */
+ { 0, 0, 0}, /* EA_MODE_PCIX */
+ { 0, 0, 0}, /* EA_MODE_I */
+};
+
+
+
+/* ======================================================================== */
+/* =========================== UTILITY FUNCTIONS ========================== */
+/* ======================================================================== */
+
+/* Print an error message and exit with status error */
+static void error_exit(const char* fmt, ...)
+{
+ va_list args;
+ fprintf(stderr, "In %s, near or on line %d:\n\t", g_input_filename, g_line_number);
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+
+ if(g_prototype_file) fclose(g_prototype_file);
+ if(g_table_file) fclose(g_table_file);
+ if(g_input_file) fclose(g_input_file);
+
+ exit(EXIT_FAILURE);
+}
+
+/* Print an error message, call perror(), and exit with status error */
+static void perror_exit(const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+ perror("");
+
+ if(g_prototype_file) fclose(g_prototype_file);
+ if(g_table_file) fclose(g_table_file);
+ if(g_input_file) fclose(g_input_file);
+
+ exit(EXIT_FAILURE);
+}
+
+
+/* copy until 0 or space and exit with error if we read too far */
+static int check_strsncpy(char* dst, char* src, int maxlength)
+{
+ char* p = dst;
+ while(*src && *src != ' ')
+ {
+ *p++ = *src++;
+ if(p - dst > maxlength)
+ error_exit("Field too long");
+ }
+ *p = 0;
+ return p - dst;
+}
+
+/* copy until 0 or specified character and exit with error if we read too far */
+static int check_strcncpy(char* dst, char* src, char delim, int maxlength)
+{
+ char* p = dst;
+ while(*src && *src != delim)
+ {
+ *p++ = *src++;
+ if(p - dst > maxlength)
+ error_exit("Field too long");
+ }
+ *p = 0;
+ return p - dst;
+}
+
+/* convert ascii to integer and exit with error if we find invalid data */
+static int check_atoi(char* str, int *result)
+{
+ int accum = 0;
+ char* p = str;
+ while(*p >= '0' && *p <= '9')
+ {
+ accum *= 10;
+ accum += *p++ - '0';
+ }
+ if(*p != ' ' && *p != 0)
+ error_exit("Malformed integer value (%c)", *p);
+ *result = accum;
+ return p - str;
+}
+
+/* Skip past spaces in a string */
+static int skip_spaces(char* str)
+{
+ char* p = str;
+
+ while(*p == ' ')
+ p++;
+
+ return p - str;
+}
+
+/* Count the number of set bits in a value */
+static int num_bits(int value)
+{
+ value = ((value & 0xaaaa) >> 1) + (value & 0x5555);
+ value = ((value & 0xcccc) >> 2) + (value & 0x3333);
+ value = ((value & 0xf0f0) >> 4) + (value & 0x0f0f);
+ value = ((value & 0xff00) >> 8) + (value & 0x00ff);
+ return value;
+}
+
+#ifdef UNUSED_FUNCTION
+/* Convert a hex value written in ASCII */
+int atoh(char* buff)
+{
+ int accum = 0;
+
+ for(;;buff++)
+ {
+ if(*buff >= '0' && *buff <= '9')
+ {
+ accum <<= 4;
+ accum += *buff - '0';
+ }
+ else if(*buff >= 'a' && *buff <= 'f')
+ {
+ accum <<= 4;
+ accum += *buff - 'a' + 10;
+ }
+ else break;
+ }
+ return accum;
+}
+#endif
+
+/* Get a line of text from a file, discarding any end-of-line characters */
+static int fgetline(char* buff, int nchars, FILE* file)
+{
+ int length;
+
+ if(fgets(buff, nchars, file) == NULL)
+ return -1;
+ if(buff[0] == '\r')
+ memcpy(buff, buff + 1, nchars - 1);
+
+ length = strlen(buff);
+ while(length && (buff[length-1] == '\r' || buff[length-1] == '\n'))
+ length--;
+ buff[length] = 0;
+ g_line_number++;
+
+ return length;
+}
+
+
+
+/* ======================================================================== */
+/* =========================== HELPER FUNCTIONS =========================== */
+/* ======================================================================== */
+
+/* Calculate the number of cycles an opcode requires */
+static int get_oper_cycles(opcode_struct* op, int ea_mode, int cpu_type)
+{
+ int size = g_size_select_table[op->size];
+
+ if(op->cpus[cpu_type] == '.')
+ return 255;
+
+ if(cpu_type < CPU_TYPE_020)
+ {
+ if(cpu_type == CPU_TYPE_010)
+ {
+ if(strcmp(op->name, "moves") == 0)
+ return op->cycles[cpu_type] + g_moves_cycle_table[ea_mode][size];
+ if(strcmp(op->name, "clr") == 0)
+ return op->cycles[cpu_type] + g_clr_cycle_table[ea_mode][size];
+ }
+
+ /* ASG: added these cases -- immediate modes take 2 extra cycles here */
+ /* SV: but only when operating on long, and also on register direct mode */
+ if(cpu_type == CPU_TYPE_000 && (ea_mode == EA_MODE_I || ea_mode == EA_MODE_NONE) && op->size == 32 &&
+ ((strcmp(op->name, "add") == 0 && strcmp(op->spec_proc, "er") == 0) ||
+ strcmp(op->name, "adda") == 0 ||
+ (strcmp(op->name, "and") == 0 && strcmp(op->spec_proc, "er") == 0) ||
+ (strcmp(op->name, "or") == 0 && strcmp(op->spec_proc, "er") == 0) ||
+ (strcmp(op->name, "sub") == 0 && strcmp(op->spec_proc, "er") == 0) ||
+ strcmp(op->name, "suba") == 0))
+ return op->cycles[cpu_type] + g_ea_cycle_table[ea_mode][cpu_type][size] + 2;
+
+ if(strcmp(op->name, "jmp") == 0)
+ return op->cycles[cpu_type] + g_jmp_cycle_table[ea_mode];
+ if(strcmp(op->name, "jsr") == 0)
+ return op->cycles[cpu_type] + g_jsr_cycle_table[ea_mode];
+ if(strcmp(op->name, "lea") == 0)
+ return op->cycles[cpu_type] + g_lea_cycle_table[ea_mode];
+ if(strcmp(op->name, "pea") == 0)
+ return op->cycles[cpu_type] + g_pea_cycle_table[ea_mode];
+ if(strcmp(op->name, "movem") == 0)
+ return op->cycles[cpu_type] + g_movem_cycle_table[ea_mode];
+ }
+ return op->cycles[cpu_type] + g_ea_cycle_table[ea_mode][cpu_type][size];
+}
+
+/* Find an opcode in the opcode handler list */
+static opcode_struct* find_opcode(char* name, int size, char* spec_proc, char* spec_ea)
+{
+ opcode_struct* op;
+
+
+ for(op = g_opcode_input_table;op->name != NULL;op++)
+ {
+ if( strcmp(name, op->name) == 0 &&
+ (size == op->size) &&
+ strcmp(spec_proc, op->spec_proc) == 0 &&
+ strcmp(spec_ea, op->spec_ea) == 0)
+ return op;
+ }
+ return NULL;
+}
+
+#ifdef UNUSED_FUNCTION
+/* Specifically find the illegal opcode in the list */
+opcode_struct* find_illegal_opcode(void)
+{
+ opcode_struct* op;
+
+ for(op = g_opcode_input_table;op->name != NULL;op++)
+ {
+ if(strcmp(op->name, "illegal") == 0)
+ return op;
+ }
+ return NULL;
+}
+#endif
+
+/* Parse an opcode handler name */
+static int extract_opcode_info(char* src, char* name, int* size, char* spec_proc, char* spec_ea)
+{
+ char* ptr = strstr(src, ID_OPHANDLER_NAME);
+
+ if(ptr == NULL)
+ return 0;
+
+ ptr += strlen(ID_OPHANDLER_NAME) + 1;
+
+ ptr += check_strcncpy(name, ptr, ',', MAX_NAME_LENGTH);
+ if(*ptr != ',') return 0;
+ ptr++;
+ ptr += skip_spaces(ptr);
+
+ *size = atoi(ptr);
+ ptr = strstr(ptr, ",");
+ if(ptr == NULL) return 0;
+ ptr++;
+ ptr += skip_spaces(ptr);
+
+ ptr += check_strcncpy(spec_proc, ptr, ',', MAX_SPEC_PROC_LENGTH);
+ if(*ptr != ',') return 0;
+ ptr++;
+ ptr += skip_spaces(ptr);
+
+ ptr += check_strcncpy(spec_ea, ptr, ')', MAX_SPEC_EA_LENGTH);
+ if(*ptr != ')') return 0;
+ ptr++;
+ ptr += skip_spaces(ptr);
+
+ return 1;
+}
+
+
+/* Add a search/replace pair to a replace structure */
+static void add_replace_string(replace_struct* replace, const char* search_str, const char* replace_str)
+{
+ if(replace->length >= MAX_REPLACE_LENGTH)
+ error_exit("overflow in replace structure");
+
+ strcpy(replace->replace[replace->length][0], search_str);
+ strcpy(replace->replace[replace->length++][1], replace_str);
+}
+
+/* Write a function body while replacing any selected strings */
+static void write_body(FILE* filep, body_struct* body, replace_struct* replace)
+{
+ int i;
+ int j;
+ char* ptr;
+ char output[MAX_LINE_LENGTH+1];
+ char temp_buff[MAX_LINE_LENGTH+1];
+ int found;
+
+ for(i=0;i<body->length;i++)
+ {
+ strcpy(output, body->body[i]);
+ /* Check for the base directive header */
+ if(strstr(output, ID_BASE) != NULL)
+ {
+ /* Search for any text we need to replace */
+ found = 0;
+ for(j=0;j<replace->length;j++)
+ {
+ ptr = strstr(output, replace->replace[j][0]);
+ if(ptr)
+ {
+ /* We found something to replace */
+ found = 1;
+ strcpy(temp_buff, ptr+strlen(replace->replace[j][0]));
+ strcpy(ptr, replace->replace[j][1]);
+ strcat(ptr, temp_buff);
+ }
+ }
+ /* Found a directive with no matching replace string */
+ if(!found)
+ error_exit("Unknown " ID_BASE " directive [%s]", output);
+ }
+ fprintf(filep, "%s\n", output);
+ }
+ fprintf(filep, "\n\n");
+}
+
+/* Generate a base function name from an opcode struct */
+static void get_base_name(char* base_name, opcode_struct* op)
+{
+ sprintf(base_name, "m68k_op_%s", op->name);
+ if(op->size > 0)
+ sprintf(base_name+strlen(base_name), "_%d", op->size);
+ if(strcmp(op->spec_proc, UNSPECIFIED) != 0)
+ sprintf(base_name+strlen(base_name), "_%s", op->spec_proc);
+ if(strcmp(op->spec_ea, UNSPECIFIED) != 0)
+ sprintf(base_name+strlen(base_name), "_%s", op->spec_ea);
+}
+
+/* Write the name of an opcode handler function */
+static void write_function_name(FILE* filep, char* base_name)
+{
+ fprintf(filep, "static void %s(m68ki_cpu_core *m68k)\n", base_name);
+}
+
+static void add_opcode_output_table_entry(opcode_struct* op, char* name)
+{
+ opcode_struct* ptr;
+ if(g_opcode_output_table_length > MAX_OPCODE_OUTPUT_TABLE_LENGTH)
+ error_exit("Opcode output table overflow");
+
+ ptr = g_opcode_output_table + g_opcode_output_table_length++;
+
+ *ptr = *op;
+ strcpy(ptr->name, name);
+ ptr->bits = num_bits(ptr->op_mask);
+}
+
+/*
+ * Comparison function for qsort()
+ * For entries with an equal number of set bits in
+ * the mask compare the match values
+ */
+static int DECL_SPEC compare_nof_true_bits(const void* aptr, const void* bptr)
+{
+ const opcode_struct *a = (const opcode_struct *)aptr, *b = (const opcode_struct *)bptr;
+ if(a->bits != b->bits)
+ return a->bits - b->bits;
+ if(a->op_mask != b->op_mask)
+ return a->op_mask - b->op_mask;
+ return a->op_match - b->op_match;
+}
+
+static void print_opcode_output_table(FILE* filep)
+{
+ int i;
+ qsort((void *)g_opcode_output_table, g_opcode_output_table_length, sizeof(g_opcode_output_table[0]), compare_nof_true_bits);
+
+ for(i=0;i<g_opcode_output_table_length;i++)
+ write_table_entry(filep, g_opcode_output_table+i);
+}
+
+/* Write an entry in the opcode handler table */
+static void write_table_entry(FILE* filep, opcode_struct* op)
+{
+ int i;
+
+ fprintf(filep, "\t{%-28s, 0x%04x, 0x%04x, {",
+ op->name, op->op_mask, op->op_match);
+
+ for(i=0;i<NUM_CPUS;i++)
+ {
+ fprintf(filep, "%3d", op->cycles[i]);
+ if(i < NUM_CPUS-1)
+ fprintf(filep, ", ");
+ }
+
+ fprintf(filep, "}},\n");
+}
+
+/* Fill out an opcode struct with a specific addressing mode of the source opcode struct */
+static void set_opcode_struct(opcode_struct* src, opcode_struct* dst, int ea_mode)
+{
+ int i;
+
+ *dst = *src;
+
+ for(i=0;i<NUM_CPUS;i++)
+ dst->cycles[i] = get_oper_cycles(dst, ea_mode, i);
+ if(strcmp(dst->spec_ea, UNSPECIFIED) == 0 && ea_mode != EA_MODE_NONE)
+ sprintf(dst->spec_ea, "%s", g_ea_info_table[ea_mode].fname_add);
+ dst->op_mask |= g_ea_info_table[ea_mode].mask_add;
+ dst->op_match |= g_ea_info_table[ea_mode].match_add;
+}
+
+
+/* Generate a final opcode handler from the provided data */
+static void generate_opcode_handler(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* opinfo, int ea_mode)
+{
+ char str[MAX_LINE_LENGTH+1];
+ opcode_struct* op = (opcode_struct *)malloc(sizeof(opcode_struct));
+
+ /* Set the opcode structure and write the tables, prototypes, etc */
+ set_opcode_struct(opinfo, op, ea_mode);
+ get_base_name(str, op);
+ add_opcode_output_table_entry(op, str);
+ write_function_name(filep, str);
+
+ /* Add any replace strings needed */
+ if(ea_mode != EA_MODE_NONE)
+ {
+ sprintf(str, "EA_%s_8(m68k)", g_ea_info_table[ea_mode].ea_add);
+ add_replace_string(replace, ID_OPHANDLER_EA_AY_8, str);
+ sprintf(str, "EA_%s_16(m68k)", g_ea_info_table[ea_mode].ea_add);
+ add_replace_string(replace, ID_OPHANDLER_EA_AY_16, str);
+ sprintf(str, "EA_%s_32(m68k)", g_ea_info_table[ea_mode].ea_add);
+ add_replace_string(replace, ID_OPHANDLER_EA_AY_32, str);
+ sprintf(str, "OPER_%s_8(m68k)", g_ea_info_table[ea_mode].ea_add);
+ add_replace_string(replace, ID_OPHANDLER_OPER_AY_8, str);
+ sprintf(str, "OPER_%s_16(m68k)", g_ea_info_table[ea_mode].ea_add);
+ add_replace_string(replace, ID_OPHANDLER_OPER_AY_16, str);
+ sprintf(str, "OPER_%s_32(m68k)", g_ea_info_table[ea_mode].ea_add);
+ add_replace_string(replace, ID_OPHANDLER_OPER_AY_32, str);
+ }
+
+ /* Now write the function body with the selected replace strings */
+ write_body(filep, body, replace);
+ g_num_functions++;
+ free(op);
+}
+
+/* Generate opcode variants based on available addressing modes */
+static void generate_opcode_ea_variants(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* op)
+{
+ int old_length = replace->length;
+
+ /* No ea modes available for this opcode */
+ if(HAS_NO_EA_MODE(op->ea_allowed))
+ {
+ generate_opcode_handler(filep, body, replace, op, EA_MODE_NONE);
+ return;
+ }
+
+ /* Check for and create specific opcodes for each available addressing mode */
+ if(HAS_EA_AI(op->ea_allowed))
+ generate_opcode_handler(filep, body, replace, op, EA_MODE_AI);
+ replace->length = old_length;
+ if(HAS_EA_PI(op->ea_allowed))
+ {
+ generate_opcode_handler(filep, body, replace, op, EA_MODE_PI);
+ replace->length = old_length;
+ if(op->size == 8)
+ generate_opcode_handler(filep, body, replace, op, EA_MODE_PI7);
+ }
+ replace->length = old_length;
+ if(HAS_EA_PD(op->ea_allowed))
+ {
+ generate_opcode_handler(filep, body, replace, op, EA_MODE_PD);
+ replace->length = old_length;
+ if(op->size == 8)
+ generate_opcode_handler(filep, body, replace, op, EA_MODE_PD7);
+ }
+ replace->length = old_length;
+ if(HAS_EA_DI(op->ea_allowed))
+ generate_opcode_handler(filep, body, replace, op, EA_MODE_DI);
+ replace->length = old_length;
+ if(HAS_EA_IX(op->ea_allowed))
+ generate_opcode_handler(filep, body, replace, op, EA_MODE_IX);
+ replace->length = old_length;
+ if(HAS_EA_AW(op->ea_allowed))
+ generate_opcode_handler(filep, body, replace, op, EA_MODE_AW);
+ replace->length = old_length;
+ if(HAS_EA_AL(op->ea_allowed))
+ generate_opcode_handler(filep, body, replace, op, EA_MODE_AL);
+ replace->length = old_length;
+ if(HAS_EA_PCDI(op->ea_allowed))
+ generate_opcode_handler(filep, body, replace, op, EA_MODE_PCDI);
+ replace->length = old_length;
+ if(HAS_EA_PCIX(op->ea_allowed))
+ generate_opcode_handler(filep, body, replace, op, EA_MODE_PCIX);
+ replace->length = old_length;
+ if(HAS_EA_I(op->ea_allowed))
+ generate_opcode_handler(filep, body, replace, op, EA_MODE_I);
+ replace->length = old_length;
+}
+
+/* Generate variants of condition code opcodes */
+static void generate_opcode_cc_variants(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* op_in, int offset)
+{
+ char repl[20];
+ char replnot[20];
+ int i;
+ int old_length = replace->length;
+ opcode_struct* op = (opcode_struct *)malloc(sizeof(opcode_struct));
+
+ *op = *op_in;
+
+ op->op_mask |= 0x0f00;
+
+ /* Do all condition codes except t and f */
+ for(i=2;i<16;i++)
+ {
+ /* Add replace strings for this condition code */
+ sprintf(repl, "COND_%s(m68k)", g_cc_table[i][1]);
+ sprintf(replnot, "COND_NOT_%s(m68k)", g_cc_table[i][1]);
+
+ add_replace_string(replace, ID_OPHANDLER_CC, repl);
+ add_replace_string(replace, ID_OPHANDLER_NOT_CC, replnot);
+
+ /* Set the new opcode info */
+ strcpy(op->name+offset, g_cc_table[i][0]);
+
+ op->op_match = (op->op_match & 0xf0ff) | (i<<8);
+
+ /* Generate all opcode variants for this modified opcode */
+ generate_opcode_ea_variants(filep, body, replace, op);
+ /* Remove the above replace strings */
+ replace->length = old_length;
+ }
+ free(op);
+}
+
+/* Process the opcode handlers section of the input file */
+static void process_opcode_handlers(FILE* filep)
+{
+ FILE* input_file = g_input_file;
+ char func_name[MAX_LINE_LENGTH+1];
+ char oper_name[MAX_LINE_LENGTH+1];
+ int oper_size = 0;
+ char oper_spec_proc[MAX_LINE_LENGTH+1];
+ char oper_spec_ea[MAX_LINE_LENGTH+1];
+ opcode_struct* opinfo;
+ replace_struct* replace = (replace_struct*)malloc(sizeof(replace_struct));
+ body_struct* body = (body_struct*)malloc(sizeof(body_struct));
+
+ for(;;)
+ {
+ /* Find the first line of the function */
+ func_name[0] = 0;
+ while(strstr(func_name, ID_OPHANDLER_NAME) == NULL)
+ {
+ if(strcmp(func_name, ID_INPUT_SEPARATOR) == 0)
+ {
+ free(replace);
+ free(body);
+ return; /* all done */
+ }
+ if(fgetline(func_name, MAX_LINE_LENGTH, input_file) < 0)
+ error_exit("Premature end of file when getting function name");
+ }
+ /* Get the rest of the function */
+ for(body->length=0;;body->length++)
+ {
+ if(body->length > MAX_BODY_LENGTH)
+ error_exit("Function too long");
+
+ if(fgetline(body->body[body->length], MAX_LINE_LENGTH, input_file) < 0)
+ error_exit("Premature end of file when getting function body");
+
+ if(body->body[body->length][0] == '}')
+ {
+ body->length++;
+ break;
+ }
+ }
+
+ g_num_primitives++;
+
+ /* Extract the function name information */
+ if(!extract_opcode_info(func_name, oper_name, &oper_size, oper_spec_proc, oper_spec_ea))
+ error_exit("Invalid " ID_OPHANDLER_NAME " format");
+
+ /* Find the corresponding table entry */
+ opinfo = find_opcode(oper_name, oper_size, oper_spec_proc, oper_spec_ea);
+ if(opinfo == NULL)
+ error_exit("Unable to find matching table entry for %s", func_name);
+
+ replace->length = 0;
+
+ /* Generate opcode variants */
+ if(strcmp(opinfo->name, "bcc") == 0 || strcmp(opinfo->name, "scc") == 0)
+ generate_opcode_cc_variants(filep, body, replace, opinfo, 1);
+ else if(strcmp(opinfo->name, "dbcc") == 0)
+ generate_opcode_cc_variants(filep, body, replace, opinfo, 2);
+ else if(strcmp(opinfo->name, "trapcc") == 0)
+ generate_opcode_cc_variants(filep, body, replace, opinfo, 4);
+ else
+ generate_opcode_ea_variants(filep, body, replace, opinfo);
+ }
+
+ free(replace);
+ free(body);
+}
+
+
+/* Populate the opcode handler table from the input file */
+static void populate_table(void)
+{
+ char* ptr;
+ char bitpattern[17];
+ opcode_struct* op;
+ char buff[MAX_LINE_LENGTH];
+ int i;
+ int temp;
+
+ buff[0] = 0;
+
+ /* Find the start of the table */
+ while(strcmp(buff, ID_TABLE_START) != 0)
+ if(fgetline(buff, MAX_LINE_LENGTH, g_input_file) < 0)
+ error_exit("(table_start) Premature EOF while reading table");
+
+ /* Process the entire table */
+ for(op = g_opcode_input_table;;op++)
+ {
+ if(fgetline(buff, MAX_LINE_LENGTH, g_input_file) < 0)
+ error_exit("(inline) Premature EOF while reading table");
+ if(strlen(buff) == 0)
+ continue;
+ /* We finish when we find an input separator */
+ if(strcmp(buff, ID_INPUT_SEPARATOR) == 0)
+ break;
+
+ /* Extract the info from the table */
+ ptr = buff;
+
+ /* Name */
+ ptr += skip_spaces(ptr);
+ ptr += check_strsncpy(op->name, ptr, MAX_NAME_LENGTH);
+
+ /* Size */
+ ptr += skip_spaces(ptr);
+ ptr += check_atoi(ptr, &temp);
+ op->size = (unsigned char)temp;
+
+ /* Special processing */
+ ptr += skip_spaces(ptr);
+ ptr += check_strsncpy(op->spec_proc, ptr, MAX_SPEC_PROC_LENGTH);
+
+ /* Specified EA Mode */
+ ptr += skip_spaces(ptr);
+ ptr += check_strsncpy(op->spec_ea, ptr, MAX_SPEC_EA_LENGTH);
+
+ /* Bit Pattern (more processing later) */
+ ptr += skip_spaces(ptr);
+ ptr += check_strsncpy(bitpattern, ptr, 17);
+
+ /* Allowed Addressing Mode List */
+ ptr += skip_spaces(ptr);
+ ptr += check_strsncpy(op->ea_allowed, ptr, EA_ALLOWED_LENGTH);
+
+ /* CPU operating mode (U = user or supervisor, S = supervisor only */
+ ptr += skip_spaces(ptr);
+ for(i=0;i<NUM_CPUS;i++)
+ {
+ op->cpu_mode[i] = *ptr++;
+ ptr += skip_spaces(ptr);
+ }
+
+ /* Allowed CPUs for this instruction */
+ for(i=0;i<NUM_CPUS;i++)
+ {
+ ptr += skip_spaces(ptr);
+ if(*ptr == UNSPECIFIED_CH)
+ {
+ op->cpus[i] = UNSPECIFIED_CH;
+ op->cycles[i] = 0;
+ ptr++;
+ }
+ else
+ {
+ op->cpus[i] = '0' + i;
+ ptr += check_atoi(ptr, &temp);
+ op->cycles[i] = (unsigned char)temp;
+ }
+ }
+
+ /* generate mask and match from bitpattern */
+ op->op_mask = 0;
+ op->op_match = 0;
+ for(i=0;i<16;i++)
+ {
+ op->op_mask |= (bitpattern[i] != '.') << (15-i);
+ op->op_match |= (bitpattern[i] == '1') << (15-i);
+ }
+ }
+ /* Terminate the list */
+ op->name[0] = 0;
+}
+
+/* Read a header or footer insert from the input file */
+static void read_insert(char* insert)
+{
+ char* ptr = insert;
+ char* overflow = insert + MAX_INSERT_LENGTH - MAX_LINE_LENGTH;
+ int length;
+ char* first_blank = NULL;
+
+ first_blank = NULL;
+
+ /* Skip any leading blank lines */
+ for(length = 0;length == 0;length = fgetline(ptr, MAX_LINE_LENGTH, g_input_file))
+ if(ptr >= overflow)
+ error_exit("Buffer overflow reading inserts");
+ if(length < 0)
+ error_exit("Premature EOF while reading inserts");
+
+ /* Advance and append newline */
+ ptr += length;
+ strcpy(ptr++, "\n");
+
+ /* Read until next separator */
+ for(;;)
+ {
+ /* Read a new line */
+ if(ptr >= overflow)
+ error_exit("Buffer overflow reading inserts");
+ if((length = fgetline(ptr, MAX_LINE_LENGTH, g_input_file)) < 0)
+ error_exit("Premature EOF while reading inserts");
+
+ /* Stop if we read a separator */
+ if(strcmp(ptr, ID_INPUT_SEPARATOR) == 0)
+ break;
+
+ /* keep track in case there are trailing blanks */
+ if(length == 0)
+ {
+ if(first_blank == NULL)
+ first_blank = ptr;
+ }
+ else
+ first_blank = NULL;
+
+ /* Advance and append newline */
+ ptr += length;
+ strcpy(ptr++, "\n");
+ }
+
+ /* kill any trailing blank lines */
+ if(first_blank)
+ ptr = first_blank;
+ *ptr++ = 0;
+}
+
+
+
+/* ======================================================================== */
+/* ============================= MAIN FUNCTION ============================ */
+/* ======================================================================== */
+
+int main(int argc, char *argv[])
+{
+ /* File stuff */
+ char output_path[M68K_MAX_DIR] = "";
+ char filename[M68K_MAX_PATH];
+ /* Section identifier */
+ char section_id[MAX_LINE_LENGTH+1];
+ /* Inserts */
+ char temp_insert[MAX_INSERT_LENGTH+1];
+ char prototype_footer_insert[MAX_INSERT_LENGTH+1];
+ char table_header_insert[MAX_INSERT_LENGTH+1];
+ char table_footer_insert[MAX_INSERT_LENGTH+1];
+ char ophandler_header_insert[MAX_INSERT_LENGTH+1];
+ char ophandler_footer_insert[MAX_INSERT_LENGTH+1];
+ /* Flags if we've processed certain parts already */
+ int prototype_header_read = 0;
+ int prototype_footer_read = 0;
+ int table_header_read = 0;
+ int table_footer_read = 0;
+ int ophandler_header_read = 0;
+ int ophandler_footer_read = 0;
+ int table_body_read = 0;
+ int ophandler_body_read = 0;
+
+ printf("\n\tMusashi v%s 68000, 68008, 68010, 68EC020, 68020, 68EC030, 68030, 68EC040, 68040 emulator\n", g_version);
+ printf("\tCopyright Karl Stenerud\n\n");
+
+ /* Check if output path and source for the input file are given */
+ if(argc > 1)
+ {
+ char *ptr;
+ strcpy(output_path, argv[1]);
+
+ for(ptr = strchr(output_path, '\\'); ptr; ptr = strchr(ptr, '\\'))
+ *ptr = '/';
+
+#if !(defined(__DECC) && defined(VMS))
+ if(output_path[strlen(output_path)-1] != '/')
+ strcat(output_path, "/");
+#endif
+ }
+
+ strcpy(g_input_filename, (argc > 2) ? argv[2] : FILENAME_INPUT);
+
+#if defined(__DECC) && defined(VMS)
+
+ /* Open the files we need */
+ sprintf(filename, "%s%s", output_path, FILENAME_PROTOTYPE);
+ if((g_prototype_file = fopen(filename, "w")) == NULL)
+ perror_exit("Unable to create prototype file (%s)\n", filename);
+
+ sprintf(filename, "%s%s", output_path, FILENAME_TABLE);
+ if((g_table_file = fopen(filename, "w")) == NULL)
+ perror_exit("Unable to create table file (%s)\n", filename);
+
+ if((g_input_file=fopen(g_input_filename, "r")) == NULL)
+ perror_exit("can't open %s for input", g_input_filename);
+
+#else
+
+
+ /* Open the files we need */
+ sprintf(filename, "%s%s", output_path, FILENAME_PROTOTYPE);
+ if((g_prototype_file = fopen(filename, "wt")) == NULL)
+ perror_exit("Unable to create prototype file (%s)\n", filename);
+
+ sprintf(filename, "%s%s", output_path, FILENAME_TABLE);
+ if((g_table_file = fopen(filename, "wt")) == NULL)
+ perror_exit("Unable to create table file (%s)\n", filename);
+
+ if((g_input_file=fopen(g_input_filename, "rt")) == NULL)
+ perror_exit("can't open %s for input", g_input_filename);
+
+#endif
+
+ /* Get to the first section of the input file */
+ section_id[0] = 0;
+ while(strcmp(section_id, ID_INPUT_SEPARATOR) != 0)
+ if(fgetline(section_id, MAX_LINE_LENGTH, g_input_file) < 0)
+ error_exit("Premature EOF while reading input file");
+
+ /* Now process all sections */
+ for(;;)
+ {
+ if(fgetline(section_id, MAX_LINE_LENGTH, g_input_file) < 0)
+ error_exit("Premature EOF while reading input file");
+ if(strcmp(section_id, ID_PROTOTYPE_HEADER) == 0)
+ {
+ if(prototype_header_read)
+ error_exit("Duplicate prototype header");
+ read_insert(temp_insert);
+ fprintf(g_prototype_file, "%s\n\n", temp_insert);
+ prototype_header_read = 1;
+ }
+ else if(strcmp(section_id, ID_TABLE_HEADER) == 0)
+ {
+ if(table_header_read)
+ error_exit("Duplicate table header");
+ read_insert(table_header_insert);
+ table_header_read = 1;
+ }
+ else if(strcmp(section_id, ID_OPHANDLER_HEADER) == 0)
+ {
+ if(ophandler_header_read)
+ error_exit("Duplicate opcode handler header");
+ read_insert(ophandler_header_insert);
+ ophandler_header_read = 1;
+ }
+ else if(strcmp(section_id, ID_PROTOTYPE_FOOTER) == 0)
+ {
+ if(prototype_footer_read)
+ error_exit("Duplicate prototype footer");
+ read_insert(prototype_footer_insert);
+ prototype_footer_read = 1;
+ }
+ else if(strcmp(section_id, ID_TABLE_FOOTER) == 0)
+ {
+ if(table_footer_read)
+ error_exit("Duplicate table footer");
+ read_insert(table_footer_insert);
+ table_footer_read = 1;
+ }
+ else if(strcmp(section_id, ID_OPHANDLER_FOOTER) == 0)
+ {
+ if(ophandler_footer_read)
+ error_exit("Duplicate opcode handler footer");
+ read_insert(ophandler_footer_insert);
+ ophandler_footer_read = 1;
+ }
+ else if(strcmp(section_id, ID_TABLE_BODY) == 0)
+ {
+ if(!prototype_header_read)
+ error_exit("Table body encountered before prototype header");
+ if(!table_header_read)
+ error_exit("Table body encountered before table header");
+ if(!ophandler_header_read)
+ error_exit("Table body encountered before opcode handler header");
+
+ if(table_body_read)
+ error_exit("Duplicate table body");
+
+ populate_table();
+ table_body_read = 1;
+ }
+ else if(strcmp(section_id, ID_OPHANDLER_BODY) == 0)
+ {
+ if(!prototype_header_read)
+ error_exit("Opcode handlers encountered before prototype header");
+ if(!table_header_read)
+ error_exit("Opcode handlers encountered before table header");
+ if(!ophandler_header_read)
+ error_exit("Opcode handlers encountered before opcode handler header");
+ if(!table_body_read)
+ error_exit("Opcode handlers encountered before table body");
+
+ if(ophandler_body_read)
+ error_exit("Duplicate opcode handler section");
+
+ fprintf(g_table_file, "%s\n\n", ophandler_header_insert);
+ process_opcode_handlers(g_table_file);
+ fprintf(g_table_file, "%s\n\n", ophandler_footer_insert);
+
+ ophandler_body_read = 1;
+ }
+ else if(strcmp(section_id, ID_END) == 0)
+ {
+ /* End of input file. Do a sanity check and then write footers */
+ if(!prototype_header_read)
+ error_exit("Missing prototype header");
+ if(!prototype_footer_read)
+ error_exit("Missing prototype footer");
+ if(!table_header_read)
+ error_exit("Missing table header");
+ if(!table_footer_read)
+ error_exit("Missing table footer");
+ if(!table_body_read)
+ error_exit("Missing table body");
+ if(!ophandler_header_read)
+ error_exit("Missing opcode handler header");
+ if(!ophandler_footer_read)
+ error_exit("Missing opcode handler footer");
+ if(!ophandler_body_read)
+ error_exit("Missing opcode handler body");
+
+ fprintf(g_table_file, "%s\n\n", table_header_insert);
+ print_opcode_output_table(g_table_file);
+ fprintf(g_table_file, "%s\n\n", table_footer_insert);
+
+ fprintf(g_prototype_file, "%s\n\n", prototype_footer_insert);
+
+ break;
+ }
+ else
+ {
+ error_exit("Unknown section identifier: %s", section_id);
+ }
+ }
+
+ /* Close all files and exit */
+ fclose(g_prototype_file);
+ fclose(g_table_file);
+ fclose(g_input_file);
+
+ printf("Generated %d opcode handlers from %d primitives\n", g_num_functions, g_num_primitives);
+
+ return 0;
+}
+
+
+
+/* ======================================================================== */
+/* ============================== END OF FILE ============================= */
+/* ======================================================================== */
diff --git a/trunk/src/emu/cpu/m68000/m68kmmu.h b/trunk/src/emu/cpu/m68000/m68kmmu.h
new file mode 100644
index 00000000000..1995bca1e16
--- /dev/null
+++ b/trunk/src/emu/cpu/m68000/m68kmmu.h
@@ -0,0 +1,806 @@
+/*
+ m68kmmu.h - PMMU implementation for 68851/68030/68040
+ HMMU implementation for 68020 (II and LC variants)
+
+ By R. Belmont
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+*/
+
+// MMU status register bit definitions
+
+#define M68K_MMU_SR_BUS_ERROR 0x8000
+#define M68K_MMU_SR_SUPERVISOR_ONLY 0x2000
+#define M68K_MMU_SR_WRITE_PROTECT 0x0800
+#define M68K_MMU_SR_INVALID 0x0400
+#define M68K_MMU_SR_MODIFIED 0x0200
+#define M68K_MMU_SR_LEVEL_0 0x0000
+#define M68K_MMU_SR_LEVEL_1 0x0001
+#define M68K_MMU_SR_LEVEL_2 0x0002
+#define M68K_MMU_SR_LEVEL_3 0x0003
+
+// MMU translation table descriptor field definitions
+
+#define M68K_MMU_DF_DT 0x0003
+#define M68K_MMU_DF_DT0 0x0000
+#define M68K_MMU_DF_DT1 0x0001
+#define M68K_MMU_DF_DT2 0x0002
+#define M68K_MMU_DF_DT3 0x0003
+#define M68K_MMU_DF_WP 0x0004
+#define M68K_MMU_DF_USED 0x0008
+#define M68K_MMU_DF_MODIFIED 0x0010
+#define M68K_MMU_DF_CI 0x0040
+#define M68K_MMU_DF_SUPERVISOR 0x0100
+
+// MMU ATC Fields
+
+#define M68K_MMU_ATC_BUSERROR 0x08000000
+#define M68K_MMU_ATC_CACHE_IN 0x04000000
+#define M68K_MMU_ATC_WRITE_PR 0x02000000
+#define M68K_MMU_ATC_MODIFIED 0x01000000
+#define M68K_MMU_ATC_MASK 0x00ffffff
+#define M68K_MMU_ATC_SHIFT 8
+#define M68K_MMU_ATC_VALID 0x08000000
+
+// MMU Translation Control register
+#define M68K_MMU_TC_SRE 0x02000000
+
+/* decodes the effective address */
+static UINT32 DECODE_EA_32(m68ki_cpu_core *m68k, int ea)
+{
+ int mode = (ea >> 3) & 0x7;
+ int reg = (ea & 0x7);
+
+ switch (mode)
+ {
+ case 2: // (An)
+ {
+ return REG_A[reg];
+ }
+ case 3: // (An)+
+ {
+ UINT32 ea = EA_AY_PI_32(m68k);
+ return ea;
+ }
+ case 5: // (d16, An)
+ {
+ UINT32 ea = EA_AY_DI_32(m68k);
+ return ea;
+ }
+ case 6: // (An) + (Xn) + d8
+ {
+ UINT32 ea = EA_AY_IX_32(m68k);
+ return ea;
+ }
+ case 7:
+ {
+ switch (reg)
+ {
+ case 0: // (xxx).W
+ {
+ UINT32 ea = (UINT32)OPER_I_16(m68k);
+ return ea;
+ }
+ case 1: // (xxx).L
+ {
+ UINT32 d1 = OPER_I_16(m68k);
+ UINT32 d2 = OPER_I_16(m68k);
+ UINT32 ea = (d1 << 16) | d2;
+ return ea;
+ }
+ case 2: // (d16, PC)
+ {
+ UINT32 ea = EA_PCDI_32(m68k);
+ return ea;
+ }
+ default: fatalerror("m68k: DECODE_EA_32: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
+ }
+ break;
+ }
+ default: fatalerror("m68k: DECODE_EA_32: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
+ }
+ return 0;
+}
+
+/*
+ pmmu_atc_add: adds this address to the ATC
+*/
+void pmmu_atc_add(m68ki_cpu_core *m68k, UINT32 logical, UINT32 physical, int fc)
+{
+ int i, found;
+
+ // get page size (i.e. # of bits to ignore); is 10 for Apollo
+ int ps = (m68k->mmu_tc >> 20) & 0xf;
+ // Note: exact emulation would use (logical >> ps) << (ps-8)
+ UINT32 atc_tag = M68K_MMU_ATC_VALID | ((fc &7) << 24)| logical >> ps;
+
+ // first see if this is already in the cache
+ for (i = 0; i < MMU_ATC_ENTRIES; i++)
+ {
+ // if tag bits and function code match, don't add
+ if (m68k->mmu_atc_tag[i] == atc_tag)
+ {
+ return;
+ }
+ }
+
+ // find an open entry
+ found = -1;
+ for (i = 0; i < MMU_ATC_ENTRIES; i++)
+ {
+ if (!(m68k->mmu_atc_tag[i] & M68K_MMU_ATC_VALID))
+ {
+ found = i;
+ break;
+ }
+ }
+
+ // did we find an entry? steal one by round-robin then
+ if (found == -1)
+ {
+ found = m68k->mmu_atc_rr++;
+
+ if (m68k->mmu_atc_rr >= MMU_ATC_ENTRIES)
+ {
+ m68k->mmu_atc_rr = 0;
+ }
+ }
+
+ // add the entry
+ // logerror("ATC[%2d] add: log %08x -> phys %08x (fc=%d)\n", found, (logical>>ps) << ps, (physical >> ps) << ps, fc);
+ m68k->mmu_atc_tag[found] = atc_tag;
+ m68k->mmu_atc_data[found] = (physical >> ps) << (ps-8);
+
+ if (m68k->mmu_tmp_sr & M68K_MMU_SR_WRITE_PROTECT)
+ {
+ m68k->mmu_atc_data[found] |= M68K_MMU_ATC_WRITE_PR;
+ }
+}
+
+/*
+ pmmu_atc_flush: flush entire ATC
+
+ 7fff0003 001ffd10 80f05750 is what should load
+*/
+void pmmu_atc_flush(m68ki_cpu_core *m68k)
+{
+ int i;
+ // logerror("ATC flush: pc=%08x\n", REG_PPC);
+
+ for (i = 0; i < MMU_ATC_ENTRIES; i++)
+ {
+ m68k->mmu_atc_tag[i] = 0;
+ }
+
+ m68k->mmu_atc_rr = 0;
+}
+
+
+INLINE UINT32 get_dt2_table_entry(m68ki_cpu_core *m68k, UINT32 tptr, UINT8 ptest)
+{
+ UINT32 tbl_entry = m68k->program->read_dword(tptr);
+ UINT32 dt = tbl_entry & M68K_MMU_DF_DT;
+
+ m68k->mmu_tmp_sr |= tbl_entry & 0x0004 ? M68K_MMU_SR_WRITE_PROTECT : 0;
+
+ if (!ptest && dt != M68K_MMU_DF_DT0)
+ {
+ if (dt == M68K_MMU_DF_DT1 && !m68k->mmu_tmp_rw && !(m68k->mmu_tmp_sr & M68K_MMU_SR_WRITE_PROTECT))
+ {
+ // set used and modified
+ m68k->program->write_dword( tptr, tbl_entry | M68K_MMU_DF_USED | M68K_MMU_DF_MODIFIED);
+ }
+ else if (!(tbl_entry & M68K_MMU_DF_USED))
+ {
+ m68k->program->write_dword( tptr, tbl_entry | M68K_MMU_DF_USED);
+ }
+ }
+ return tbl_entry;
+}
+
+INLINE UINT32 get_dt3_table_entry(m68ki_cpu_core *m68k, UINT32 tptr, UINT8 fc, UINT8 ptest)
+{
+ UINT32 tbl_entry2 = m68k->program->read_dword(tptr);
+ UINT32 tbl_entry = m68k->program->read_dword(tptr + 4);
+ UINT32 dt = tbl_entry2 & M68K_MMU_DF_DT;
+
+ m68k->mmu_tmp_sr |= ((tbl_entry2 & 0x0100) && !(fc & 4)) ? M68K_MMU_SR_SUPERVISOR_ONLY : 0;
+ m68k->mmu_tmp_sr |= tbl_entry2 & 0x0004 ? M68K_MMU_SR_WRITE_PROTECT : 0;
+
+ if (!ptest)
+ {
+ if (dt == M68K_MMU_DF_DT1 && !m68k->mmu_tmp_rw && !(m68k->mmu_tmp_sr & M68K_MMU_SR_WRITE_PROTECT))
+ {
+ // set modified
+ m68k->program->write_dword( tptr, tbl_entry2 | M68K_MMU_DF_USED | M68K_MMU_DF_MODIFIED);
+ }
+ else if (!(tbl_entry2 & M68K_MMU_DF_USED))
+ {
+ m68k->program->write_dword( tptr, tbl_entry2 | M68K_MMU_DF_USED);
+ }
+ }
+
+ return (tbl_entry & ~M68K_MMU_DF_DT) | dt;
+}
+
+/*
+ pmmu_translate_addr_with_fc: perform 68851/68030-style PMMU address translation
+*/
+/*INLINE*/ static UINT32 pmmu_translate_addr_with_fc(m68ki_cpu_core *m68k, UINT32 addr_in, UINT8 fc, UINT8 ptest)
+{
+ UINT32 addr_out, tbl_entry = 0, tamode = 0, tbmode = 0, tcmode = 0;
+ UINT32 root_aptr, root_limit, tofs, ps, is, abits, bbits, cbits;
+ UINT32 resolved, tptr, shift, last_entry_ptr;
+ int i;
+ UINT32 atc_tag;
+// int verbose = 0;
+
+// static UINT32 pmmu_access_count = 0;
+// static UINT32 pmmu_atc_count = 0;
+
+ resolved = 0;
+ addr_out = addr_in;
+ m68k->mmu_tmp_sr = 0;
+
+ if (fc == 7)
+ {
+ return addr_in;
+ }
+
+ if (m68k->mmu_tt0 & 0x8000)
+ {
+ // transparent translation register 0 enabled
+ UINT32 address_base = m68k->mmu_tt0 & 0xff000000;
+ UINT32 address_mask = ((m68k->mmu_tt0 << 8) & 0xff000000) ^ 0xff000000;
+ if ((addr_in & address_mask) == address_base)
+ {
+// logerror("PMMU: pc=%x TT0 fc=%x addr_in=%08x address_mask=%08x address_base=%08x\n", m68k->ppc, fc, addr_in, address_mask, address_base);
+ return addr_in;
+ }
+ }
+
+// if ((++pmmu_access_count % 10000000) == 0) {
+// logerror("pmmu_translate_addr_with_fc: atc usage = %d%%\n", pmmu_atc_count*100/pmmu_access_count);
+// pmmu_atc_count = pmmu_access_count = 0;
+// }
+
+ // get page size (i.e. # of bits to ignore); ps is 10 or 12 for Apollo, 8 otherwise
+ ps = (m68k->mmu_tc >> 20) & 0xf;
+ atc_tag = M68K_MMU_ATC_VALID | ((fc &7) << 24) | addr_in >> ps;
+
+ // first see if this is already in the ATC
+ for (i = 0; i < MMU_ATC_ENTRIES; i++)
+ {
+ if (m68k->mmu_atc_tag[i] != atc_tag)
+ {
+ // tag bits and function code don't match
+ }
+ else if (!m68k->mmu_tmp_rw && (m68k->mmu_atc_data[i] & M68K_MMU_ATC_WRITE_PR))
+ {
+ // write mode, but write protected
+ }
+ else if (!m68k->mmu_tmp_rw && !(m68k->mmu_atc_data[i] & M68K_MMU_ATC_MODIFIED))
+ {
+ // first write; must set modified in PMMU tables as well
+ }
+ else
+ {
+ // read access or write access and not write protected
+ if (!m68k->mmu_tmp_rw && !ptest)
+ {
+ // FIXME: must set modified in PMMU tables as well
+ m68k->mmu_atc_data[i] |= M68K_MMU_ATC_MODIFIED;
+ }
+ else
+ {
+ // FIXME: supervisor mode?
+ m68k->mmu_tmp_sr = M68K_MMU_SR_MODIFIED;
+ }
+ addr_out = (m68k->mmu_atc_data[i] << 8) | (addr_in & ~(~0 << ps));
+// logerror("ATC[%2d] hit: log %08x -> phys %08x pc=%08x fc=%d\n", i, addr_in, addr_out, REG_PPC, fc);
+// pmmu_atc_count++;
+ return addr_out;
+ }
+ }
+
+ // if SRP is enabled and we're in supervisor mode, use it
+ if ((m68k->mmu_tc & M68K_MMU_TC_SRE) && (fc & 4))
+ {
+ root_aptr = m68k->mmu_srp_aptr;
+ root_limit = m68k->mmu_srp_limit;
+ }
+ else // else use the CRP
+ {
+ root_aptr = m68k->mmu_crp_aptr;
+ root_limit = m68k->mmu_crp_limit;
+ }
+
+ // get initial shift (# of top bits to ignore)
+ is = (m68k->mmu_tc >> 16) & 0xf;
+ ps = (m68k->mmu_tc >> 20) & 0xf;
+ abits = (m68k->mmu_tc >> 12) & 0xf;
+ bbits = (m68k->mmu_tc >> 8) & 0xf;
+ cbits = (m68k->mmu_tc >> 4) & 0xf;
+
+// logerror("PMMU: tcr %08x limit %08x aptr %08x is %x abits %d bbits %d cbits %d\n", m68k->mmu_tc, root_limit, root_aptr, is, abits, bbits, cbits);
+
+ // get table A offset
+ tofs = (addr_in<<is)>>(32-abits);
+ tptr = root_aptr & 0xfffffff0;
+
+ // find out what format table A is
+ switch (root_limit & M68K_MMU_DF_DT)
+ {
+ case M68K_MMU_DF_DT0: // invalid, will cause MMU exception
+ m68k->mmu_tmp_sr |= M68K_MMU_SR_INVALID;
+ return root_aptr;
+
+ case M68K_MMU_DF_DT1: // page descriptor, will cause direct mapping
+ addr_out = tptr + addr_in;
+// logerror("PMMU: PC=%x root mode %d (addr_in %08x -> %08x)\n", m68k->ppc, M68K_MMU_DF_DT1, addr_in, addr_out);
+ return addr_out;
+
+ case M68K_MMU_DF_DT2: // valid 4 byte descriptors
+ tofs *= 4;
+// if (verbose) logerror("PMMU: reading table A entry at %08x\n", tofs + tptr);
+ tbl_entry = get_dt2_table_entry(m68k, tptr + tofs, ptest);
+ tamode = tbl_entry & M68K_MMU_DF_DT;
+// if (verbose) logerror("PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tamode, tofs);
+ break;
+
+ case M68K_MMU_DF_DT3: // valid 8 byte descriptors
+ tofs *= 8;
+// if (verbose) logerror("PMMU: reading table A entries at %08x\n", tofs + tptr);
+ tbl_entry = get_dt3_table_entry(m68k, tofs + tptr, fc, ptest);
+ tamode = tbl_entry & M68K_MMU_DF_DT;
+// if (verbose) logerror("PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tamode, tofs);
+ break;
+ }
+
+ last_entry_ptr = tptr + tofs;
+
+ // get table B offset and pointer
+ tofs = (addr_in<<(is+abits))>>(32-bbits);
+ tptr = tbl_entry & 0xfffffff0;
+
+ // find out what format table B is, if any
+ switch (tamode)
+ {
+ case M68K_MMU_DF_DT0: // invalid, will cause MMU exception (but not for ptest)
+ m68k->mmu_tmp_sr |= (M68K_MMU_SR_INVALID | M68K_MMU_SR_LEVEL_1);
+ // last valid pointer (for ptest)
+ addr_out = last_entry_ptr;
+ resolved = 1;
+ break;
+
+ case M68K_MMU_DF_DT2: // 4-byte table B descriptor
+ tofs *= 4;
+// if (verbose) logerror("PMMU: reading table B entry at %08x\n", tofs + tptr);
+ tbl_entry = get_dt2_table_entry(m68k, tptr + tofs, ptest);
+ tbmode = tbl_entry & M68K_MMU_DF_DT;
+// if (verbose) logerror("PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tbmode, tofs);
+ break;
+
+ case M68K_MMU_DF_DT3: // 8-byte table B descriptor
+ tofs *= 8;
+// if (verbose) logerror("PMMU: reading table B entries at %08x\n", tofs + tptr);
+ tbl_entry = get_dt3_table_entry(m68k, tptr + tofs, fc, ptest);
+ tbmode = tbl_entry & M68K_MMU_DF_DT;
+ tbl_entry &= ~M68K_MMU_DF_DT;
+// if (verbose) logerror("PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tbmode, tofs);
+ break;
+
+ case M68K_MMU_DF_DT1: // early termination descriptor
+ tbl_entry &= (~0 << ps);
+
+ shift = is+abits;
+ addr_out = ((addr_in<<shift)>>shift) + tbl_entry;
+ resolved = 1;
+ break;
+ }
+
+ // if table A wasn't early-out, continue to process table B
+ if (!resolved)
+ {
+ last_entry_ptr = tptr + tofs;
+
+ // get table C offset and pointer
+ tofs = (addr_in<<(is+abits+bbits))>>(32-cbits);
+ tptr = tbl_entry & 0xfffffff0;
+
+ switch (tbmode)
+ {
+ case M68K_MMU_DF_DT0: // invalid, will cause MMU exception (but not for ptest)
+ m68k->mmu_tmp_sr |= (M68K_MMU_SR_INVALID | M68K_MMU_SR_LEVEL_2);
+ // last valid pointer (for ptest)
+ addr_out = last_entry_ptr;
+ resolved = 1;
+ break;
+
+ case M68K_MMU_DF_DT2: // 4-byte table C descriptor
+ tofs *= 4;
+// if (verbose) logerror("PMMU: reading table C entry at %08x\n", tofs + tptr);
+ tbl_entry = get_dt2_table_entry(m68k, tptr + tofs, ptest);
+ tcmode = tbl_entry & M68K_MMU_DF_DT;
+// if (verbose) logerror("PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tbmode, tofs);
+ break;
+
+ case M68K_MMU_DF_DT3: // 8-byte table C descriptor
+ tofs *= 8;
+// if (verbose) logerror("PMMU: reading table C entries at %08x\n", tofs + tptr);
+ tbl_entry = get_dt3_table_entry(m68k, tptr+ tofs, fc, ptest);
+ tcmode = tbl_entry & M68K_MMU_DF_DT;
+// if (verbose) logerror("PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tcmode, tofs);
+ break;
+
+ case M68K_MMU_DF_DT1: // termination descriptor
+ tbl_entry &= (~0 << ps);
+
+ shift = is+abits+bbits;
+ addr_out = ((addr_in<<shift)>>shift) + tbl_entry;
+ resolved = 1;
+ break;
+ }
+ }
+
+ if (!resolved)
+ {
+ switch (tcmode)
+ {
+ case M68K_MMU_DF_DT0: // invalid, will cause MMU exception (unless ptest)
+ m68k->mmu_tmp_sr |= (M68K_MMU_SR_INVALID | M68K_MMU_SR_LEVEL_3);
+ addr_out = tptr + tofs;
+ resolved = 1;
+ break;
+
+ case M68K_MMU_DF_DT2: // 4-byte (short-form) indirect descriptor
+ case M68K_MMU_DF_DT3: // 8-byte (long-form) indirect descriptor
+ fatalerror("PMMU: pc=%08x Unhandled Table C mode %d (addr_in %08x)\n", m68k->ppc, tcmode, addr_in);
+ break;
+
+ case M68K_MMU_DF_DT1: // termination descriptor
+ tbl_entry &= (~0 << ps);
+
+ shift = is+abits+bbits+cbits;
+ addr_out = ((addr_in<<shift)>>shift) + tbl_entry;
+ resolved = 1;
+ break;
+ }
+ }
+
+ if (!ptest)
+ {
+ if (m68k->mmu_tmp_sr & M68K_MMU_SR_INVALID)
+ {
+ if (++m68k->mmu_tmp_buserror_occurred == 1)
+ {
+ m68k->mmu_tmp_buserror_address = addr_in;
+ }
+ }
+ else if (m68k->mmu_tmp_sr & M68K_MMU_SR_SUPERVISOR_ONLY)
+ {
+ if (++m68k->mmu_tmp_buserror_occurred == 1)
+ {
+ m68k->mmu_tmp_buserror_address = addr_in;
+ }
+ }
+ else if ((m68k->mmu_tmp_sr & M68K_MMU_SR_WRITE_PROTECT) && !m68k->mmu_tmp_rw)
+ {
+ if (++m68k->mmu_tmp_buserror_occurred == 1)
+ {
+ m68k->mmu_tmp_buserror_address = addr_in;
+ }
+ }
+
+ if (!m68k->mmu_tmp_buserror_occurred)
+ {
+ // we add only valid entries
+ pmmu_atc_add(m68k, addr_in, addr_out, fc);
+ }
+ }
+
+ //logerror("PMMU: [%08x] => [%08x]\n", addr_in, addr_out);
+
+ return addr_out;
+}
+
+/*
+ pmmu_translate_addr: perform 68851/68030-style PMMU address translation
+*/
+/*INLINE*/ static UINT32 pmmu_translate_addr(m68ki_cpu_core *m68k, UINT32 addr_in)
+{
+ UINT32 addr_out = pmmu_translate_addr_with_fc(m68k, addr_in, m68k->mmu_tmp_fc, 0);
+
+// if (m68k->mmu_tmp_buserror_occurred > 0) {
+// logerror("PMMU: pc=%08x sp=%08x va=%08x pa=%08x - invalid Table mode for level=%d (buserror %d)\n",
+// REG_PPC, REG_A[7], addr_in, addr_out, m68k->mmu_tmp_sr & M68K_MMU_SR_LEVEL_3,
+// m68k->mmu_tmp_buserror_occurred);
+// }
+
+ return addr_out;
+}
+
+/*
+ m68881_mmu_ops: COP 0 MMU opcode handling
+
+*/
+
+void m68881_mmu_ops(m68ki_cpu_core *m68k)
+{
+ UINT16 modes;
+ UINT32 ea = m68k->ir & 0x3f;
+ UINT64 temp64;
+
+
+ // catch the 2 "weird" encodings up front (PBcc)
+ if ((m68k->ir & 0xffc0) == 0xf0c0)
+ {
+ logerror("680x0: unhandled PBcc\n");
+ return;
+ }
+ else if ((m68k->ir & 0xffc0) == 0xf080)
+ {
+ logerror("680x0: unhandled PBcc\n");
+ return;
+ }
+ else // the rest are 1111000xxxXXXXXX where xxx is the instruction family
+ {
+ switch ((m68k->ir>>9) & 0x7)
+ {
+ case 0:
+ modes = OPER_I_16(m68k);
+
+ if ((modes & 0xfde0) == 0x2000) // PLOAD
+ {
+ UINT32 ltmp = DECODE_EA_32(m68k, ea);
+ UINT32 ptmp;
+
+ ptmp = ltmp;
+ if (m68k->pmmu_enabled)
+ {
+ ptmp = pmmu_translate_addr_with_fc(m68k, ltmp, modes & 0x07, 0);
+ }
+
+ logerror("680x0: PLOADing ATC with logical %08x => phys %08x\n", ltmp, ptmp);
+ // FIXME: rw bit?
+ pmmu_atc_add(m68k, ltmp, ptmp, modes & 0x07);
+ return;
+ }
+ else if ((modes & 0xe200) == 0x2000) // PFLUSH
+ {
+ pmmu_atc_flush(m68k);
+ return;
+ }
+ else if (modes == 0xa000) // PFLUSHR
+ {
+ pmmu_atc_flush(m68k);
+ return;
+ }
+ else if (modes == 0x2800) // PVALID (FORMAT 1)
+ {
+ logerror("680x0: unhandled PVALID1\n");
+ return;
+ }
+ else if ((modes & 0xfff8) == 0x2c00) // PVALID (FORMAT 2)
+ {
+ logerror("680x0: unhandled PVALID2\n");
+ return;
+ }
+ else if ((modes & 0xe000) == 0x8000) // PTEST
+ {
+ UINT32 v_addr = DECODE_EA_32(m68k, ea);
+ UINT32 p_addr;
+ UINT32 fc = modes & 0x1f;
+ switch (fc >> 3) {
+ case 0:
+ fc = fc == 0 ? m68k->sfc : m68k->dfc;
+ break;
+ case 1:
+ fc = REG_D[fc &7] &7;
+ break;
+ case 2:
+ fc &=7;
+ break;
+ }
+
+ p_addr = pmmu_translate_addr_with_fc(m68k, v_addr, fc, 1);
+ m68k->mmu_sr = m68k->mmu_tmp_sr;
+
+// logerror("PMMU: pc=%08x sp=%08x va=%08x pa=%08x PTEST fc=%x level=%x mmu_sr=%04x\n",
+// m68k->ppc, REG_A[7], v_addr, p_addr, fc, (modes >> 10) & 0x07, m68k->mmu_sr);
+
+ if (modes & 0x100)
+ {
+ int areg = (modes >> 5) & 7;
+ WRITE_EA_32(m68k, 0x08 | areg, p_addr);
+ }
+ return;
+ }
+ else
+ {
+ switch ((modes>>13) & 0x7)
+ {
+ case 0: // MC68030/040 form with FD bit
+ case 2: // MC68881 form, FD never set
+ if (modes & 0x200)
+ {
+ switch ((modes>>10) & 0x3f)
+ {
+ case 0x02: // transparent translation register 0
+ WRITE_EA_32(m68k, ea, m68k->mmu_tt0);
+// logerror("PMMU: pc=%x PMOVE from mmu_tt0=%08x\n", m68k->ppc, m68k->mmu_tt0);
+ break;
+ case 0x03: // transparent translation register 1
+ WRITE_EA_32(m68k, ea, m68k->mmu_tt1);
+// logerror("PMMU: pc=%x PMOVE from mmu_tt1=%08x\n", m68k->ppc, m68k->mmu_tt1);
+ break;
+ case 0x10: // translation control register
+ WRITE_EA_32(m68k, ea, m68k->mmu_tc);
+// logerror("PMMU: pc=%x PMOVE from mmu_tc=%08x\n", m68k->ppc, m68k->mmu_tc);
+ break;
+
+ case 0x12: // supervisor root pointer
+ WRITE_EA_64(m68k, ea, (UINT64)m68k->mmu_srp_limit<<32 | (UINT64)m68k->mmu_srp_aptr);
+// logerror("PMMU: pc=%x PMOVE from SRP limit = %08x, aptr = %08x\n", REG_PPC, m68k->mmu_srp_limit, m68k->mmu_srp_aptr);
+ break;
+
+ case 0x13: // CPU root pointer
+ WRITE_EA_64(m68k, ea, (UINT64)m68k->mmu_crp_limit<<32 | (UINT64)m68k->mmu_crp_aptr);
+// logerror("PMMU: pc=%x PMOVE from CRP limit = %08x, aptr = %08x\n", REG_PPC, m68k->mmu_crp_limit, m68k->mmu_crp_aptr);
+ break;
+
+ default:
+ logerror("680x0: PMOVE from unknown MMU register %x, PC %x\n", (modes>>10) & 7, m68k->pc);
+ break;
+ }
+
+ }
+ else // top 3 bits of modes: 010 for this, 011 for status, 000 for transparent translation regs
+ {
+ switch ((modes>>13) & 7)
+ {
+ case 0:
+ {
+ UINT32 temp = READ_EA_32(m68k, ea);
+
+ if (((modes>>10) & 7) == 2)
+ {
+ m68k->mmu_tt0 = temp;
+ }
+ else if (((modes>>10) & 7) == 3)
+ {
+ m68k->mmu_tt1 = temp;
+ }
+ }
+ break;
+
+ case 1:
+ logerror("680x0: unknown PMOVE case 1, PC %x\n", m68k->pc);
+ break;
+
+ case 2:
+ switch ((modes>>10) & 7)
+ {
+ case 0: // translation control register
+ m68k->mmu_tc = READ_EA_32(m68k, ea);
+// logerror("PMMU: TC = %08x\n", m68k->mmu_tc);
+
+ if (m68k->mmu_tc & 0x80000000)
+ {
+ m68k->pmmu_enabled = 1;
+// logerror("PMMU enabled\n");
+ }
+ else
+ {
+ m68k->pmmu_enabled = 0;
+// logerror("PMMU disabled\n");
+ }
+
+ if (!(modes & 0x100)) // flush ATC on moves to TC, SRP, CRP with FD bit clear
+ {
+ pmmu_atc_flush(m68k);
+ }
+ break;
+
+ case 2: // supervisor root pointer
+ temp64 = READ_EA_64(m68k, ea);
+ m68k->mmu_srp_limit = (temp64>>32) & 0xffffffff;
+ m68k->mmu_srp_aptr = temp64 & 0xffffffff;
+// logerror("PMMU: SRP limit = %08x aptr = %08x\n", m68k->mmu_srp_limit, m68k->mmu_srp_aptr);
+ if (!(modes & 0x100))
+ {
+ pmmu_atc_flush(m68k);
+ }
+ break;
+
+ case 3: // CPU root pointer
+ temp64 = READ_EA_64(m68k, ea);
+ m68k->mmu_crp_limit = (temp64>>32) & 0xffffffff;
+ m68k->mmu_crp_aptr = temp64 & 0xffffffff;
+// logerror("PMMU: CRP limit = %08x aptr = %08x\n", m68k->mmu_crp_limit, m68k->mmu_crp_aptr);
+ if (!(modes & 0x100))
+ {
+ pmmu_atc_flush(m68k);
+ }
+ break;
+
+ default:
+ logerror("680x0: PMOVE to unknown MMU register %x, PC %x\n", (modes>>10) & 7, m68k->pc);
+ break;
+ }
+ break;
+
+ case 3: // MMU status
+ {
+ UINT32 temp = READ_EA_32(m68k, ea);
+ logerror("680x0: unsupported PMOVE %x to MMU status, PC %x\n", temp, m68k->pc);
+ }
+ break;
+ }
+ }
+ break;
+
+ case 3: // MC68030 to/from status reg
+ if (modes & 0x200)
+ {
+ WRITE_EA_16(m68k, ea, m68k->mmu_sr);
+ }
+ else
+ {
+ m68k->mmu_sr = READ_EA_16(m68k, ea);
+ }
+ break;
+
+ default:
+ logerror("680x0: unknown PMOVE mode %x (modes %04x) (PC %x)\n", (modes>>13) & 0x7, modes, m68k->pc);
+ break;
+
+ }
+ }
+ break;
+
+ default:
+ logerror("680x0: unknown PMMU instruction group %d\n", (m68k->ir>>9) & 0x7);
+ break;
+ }
+ }
+}
+
+
+/* Apple HMMU translation is much simpler */
+INLINE UINT32 hmmu_translate_addr(m68ki_cpu_core *m68k, UINT32 addr_in)
+{
+ UINT32 addr_out;
+
+ addr_out = addr_in;
+
+ // check if LC 24-bit mode is enabled - this simply blanks out A31, the V8 ignores A30-24 always
+ if (m68k->hmmu_enabled == M68K_HMMU_ENABLE_LC)
+ {
+ addr_out = addr_in & 0xffffff;
+ }
+ else if (m68k->hmmu_enabled == M68K_HMMU_ENABLE_II) // the original II does a more complex translation
+ {
+ addr_out = addr_in & 0xffffff;
+
+ if ((addr_out >= 0x800000) && (addr_out <= 0x8fffff))
+ {
+ addr_out |= 0x40000000; // ROM
+ }
+ else if ((addr_out >= 0x900000) && (addr_out <= 0xefffff))
+ {
+ addr_out = 0xf0000000; // NuBus
+ addr_out |= ((addr_in & 0xf00000)<<4);
+ addr_out |= (addr_in & 0xfffff);
+ }
+ else if (addr_out >= 0xf00000)
+ {
+ addr_out |= 0x50000000; // I/O
+ }
+
+ // (RAM is at 0 and doesn't need special massaging)
+ }
+
+ return addr_out;
+}
diff --git a/trunk/src/emu/cpu/m6805/6805dasm.c b/trunk/src/emu/cpu/m6805/6805dasm.c
new file mode 100644
index 00000000000..74e9c740b7d
--- /dev/null
+++ b/trunk/src/emu/cpu/m6805/6805dasm.c
@@ -0,0 +1,212 @@
+/*
+ * A quick-hack 68(7)05 disassembler
+ *
+ * Note: this is not the good and proper way to disassemble anything, but it works
+ *
+ * I'm afraid to put my name on it, but I feel obligated:
+ * This code written by Aaron Giles (agiles@sirius.com) for the MAME project
+ *
+ */
+
+#include "emu.h"
+#include "debugger.h"
+#include "m6805.h"
+
+enum addr_mode {
+ _imp=0, /* implicit */
+ _btr, /* bit test and relative */
+ _bit, /* bit set/clear */
+ _rel, /* relative */
+ _imm, /* immediate */
+ _dir, /* direct address */
+ _ext, /* extended address */
+ _idx, /* indexed */
+ _ix1, /* indexed + byte offset */
+ _ix2 /* indexed + word offset */
+};
+
+enum op_names {
+ adca=0, adda, anda, asl, asla, aslx, asr, asra,
+ asrx, bcc, bclr, bcs, beq, bhcc, bhcs, bhi,
+ bih, bil, bita, bls, bmc, bmi, bms, bne,
+ bpl, bra, brclr, brn, brset, bset, bsr, clc,
+ cli, clr, clra, clrx, cmpa, com, coma, comx,
+ cpx, dec, deca, decx, eora, ill, inc, inca,
+ incx, jmp, jsr, lda, ldx, lsr, lsra, lsrx,
+ neg, nega, negx, nop, ora, rol, rola, rolx,
+ ror, rora, rorx, rsp, rti, rts, sbca, sec,
+ sei, sta, stx, suba, swi, tax, tst, tsta,
+ tstx, txa
+};
+
+static const char *const op_name_str[] = {
+ "adca", "adda", "anda", "asl", "asla", "aslx", "asr", "asra",
+ "asrx", "bcc", "bclr", "bcs", "beq", "bhcc", "bhcs", "bhi",
+ "bih", "bil", "bita", "bls", "bmc", "bmi", "bms", "bne",
+ "bpl", "bra", "brclr","brn", "brset","bset", "bsr", "clc",
+ "cli", "clr", "clra", "clrx", "cmpa", "com", "coma", "comx",
+ "cpx", "dec", "deca", "decx", "eora", "*ill", "inc", "inca",
+ "incx", "jmp", "jsr", "lda", "ldx", "lsr", "lsra", "lsrx",
+ "neg", "nega", "negx", "nop", "ora", "rol", "rola", "rolx",
+ "ror", "rora", "rorx", "rsp", "rti", "rts", "sbca", "sec",
+ "sei", "sta", "stx", "suba", "swi", "tax", "tst", "tsta",
+ "tstx", "txa"
+};
+
+static const unsigned char disasm[0x100][2] = {
+ {brset,_btr},{brclr,_btr},{brset,_btr},{brclr,_btr},/* 00 */
+ {brset,_btr},{brclr,_btr},{brset,_btr},{brclr,_btr},
+ {brset,_btr},{brclr,_btr},{brset,_btr},{brclr,_btr},
+ {brset,_btr},{brclr,_btr},{brset,_btr},{brclr,_btr},
+ {bset, _bit},{bclr, _bit},{bset, _bit},{bclr, _bit},/* 10 */
+ {bset, _bit},{bclr, _bit},{bset, _bit},{bclr, _bit},
+ {bset, _bit},{bclr, _bit},{bset, _bit},{bclr, _bit},
+ {bset, _bit},{bclr, _bit},{bset, _bit},{bclr, _bit},
+ {bra, _rel},{brn, _rel},{bhi, _rel},{bls, _rel},/* 20 */
+ {bcc, _rel},{bcs, _rel},{bne, _rel},{beq, _rel},
+ {bhcc, _rel},{bhcs, _rel},{bpl, _rel},{bmi, _rel},
+ {bmc, _rel},{bms, _rel},{bil, _rel},{bih, _rel},
+ {neg, _dir},{ill, _imp},{ill, _imp},{com, _dir},/* 30 */
+ {lsr, _dir},{ill, _imp},{ror, _dir},{asr, _dir},
+ {asl, _dir},{rol, _dir},{dec, _dir},{ill, _imp},
+ {inc, _dir},{tst, _dir},{ill, _imp},{clr, _dir},
+ {nega, _imp},{ill, _imp},{ill, _imp},{coma, _imp},/* 40 */
+ {lsra, _imp},{ill, _imp},{rora, _imp},{asra, _imp},
+ {asla, _imp},{rola, _imp},{deca, _imp},{ill, _imp},
+ {inca, _imp},{tsta, _imp},{ill, _imp},{clra, _imp},
+ {negx, _imp},{ill, _imp},{ill, _imp},{comx, _imp},/* 50 */
+ {lsrx, _imp},{ill, _imp},{rorx, _imp},{asrx, _imp},
+ {aslx, _imp},{rolx, _imp},{decx, _imp},{ill, _imp},
+ {incx, _imp},{tstx, _imp},{ill, _imp},{clrx, _imp},
+ {neg, _ix1},{ill, _imp},{ill, _imp},{com, _ix1},/* 60 */
+ {lsr, _ix1},{ill, _imp},{ror, _ix1},{asr, _ix1},
+ {asl, _ix1},{rol, _ix1},{dec, _ix1},{ill, _imp},
+ {inc, _ix1},{tst, _ix1},{jmp, _ix1},{clr, _ix1},
+ {neg, _idx},{ill, _imp},{ill, _imp},{com, _idx},/* 70 */
+ {lsr, _idx},{ill, _imp},{ror, _idx},{asr, _idx},
+ {asl, _idx},{rol, _idx},{dec, _idx},{ill, _imp},
+ {inc, _idx},{tst, _idx},{jmp, _idx},{clr, _idx},
+ {rti, _imp},{rts, _imp},{ill, _imp},{swi, _imp},/* 80 */
+ {ill, _imp},{ill, _imp},{ill, _imp},{ill, _imp},
+ {ill, _imp},{ill, _imp},{ill, _imp},{ill, _imp},
+ {ill, _imp},{ill, _imp},{ill, _imp},{ill, _imp},
+ {ill, _imp},{ill, _imp},{ill, _imp},{ill, _imp},/* 90 */
+ {ill, _imp},{ill, _imp},{ill, _imp},{tax, _imp},
+ {clc, _imp},{sec, _imp},{cli, _imp},{sei, _imp},
+ {rsp, _imp},{nop, _imp},{ill, _imp},{txa, _imp},
+ {suba, _imm},{cmpa, _imm},{sbca, _imm},{cpx, _imm},/* a0 */
+ {anda, _imm},{bita, _imm},{lda, _imm},{ill, _imp},
+ {eora, _imm},{adca, _imm},{ora, _imm},{adda, _imm},
+ {ill, _imp},{bsr, _rel},{ldx, _imm},{ill, _imp},
+ {suba, _dir},{cmpa, _dir},{sbca, _dir},{cpx, _dir},/* b0 */
+ {anda, _dir},{bita, _dir},{lda, _dir},{sta, _dir},
+ {eora, _dir},{adca, _dir},{ora, _dir},{adda, _dir},
+ {jmp, _dir},{jsr, _dir},{ldx, _dir},{stx, _dir},
+ {suba, _ext},{cmpa, _ext},{sbca, _ext},{cpx, _ext},/* c0 */
+ {anda, _ext},{bita, _ext},{lda, _ext},{sta, _ext},
+ {eora, _ext},{adca, _ext},{ora, _ext},{adda, _ext},
+ {jmp, _ext},{jsr, _ext},{ldx, _ext},{stx, _ext},
+ {suba, _ix2},{cmpa, _ix2},{sbca, _ix2},{cpx, _ix2},/* d0 */
+ {anda, _ix2},{bita, _ix2},{lda, _ix2},{sta, _ix2},
+ {eora, _ix2},{adca, _ix2},{ora, _ix2},{adda, _ix2},
+ {jmp, _ix2},{jsr, _ix2},{ldx, _ix2},{stx, _ix2},
+ {suba, _ix1},{cmpa, _ix1},{sbca, _ix1},{cpx, _ix1},/* e0 */
+ {anda, _ix1},{bita, _ix1},{lda, _ix1},{sta, _ix1},
+ {eora, _ix1},{adca, _ix1},{ora, _ix1},{adda, _ix1},
+ {jmp, _ix1},{jsr, _ix1},{ldx, _ix1},{stx, _ix1},
+ {suba, _idx},{cmpa, _idx},{sbca, _idx},{cpx, _idx},/* f0 */
+ {anda, _idx},{bita, _idx},{lda, _idx},{sta, _idx},
+ {eora, _idx},{adca, _idx},{ora, _idx},{adda, _idx},
+ {jmp, _idx},{jsr, _idx},{ldx, _idx},{stx, _idx}
+};
+
+#if 0
+static const char *const opcode_strings[0x0100] =
+{
+ "brset0", "brclr0", "brset1", "brclr1", "brset2", "brclr2", "brset3", "brclr3", /*00*/
+ "brset4", "brclr4", "brset5", "brclr5", "brset6", "brclr6", "brset7", "brclr7",
+ "bset0", "bclr0", "bset1", "bclr1", "bset2", "bclr2", "bset3", "bclr3", /*10*/
+ "bset4", "bclr4", "bset5", "bclr5", "bset6", "bclr6", "bset7", "bclr7",
+ "bra", "brn", "bhi", "bls", "bcc", "bcs", "bne", "beq", /*20*/
+ "bhcc", "bhcs", "bpl", "bmi", "bmc", "bms", "bil", "bih",
+ "neg_di", "illegal", "illegal", "com_di", "lsr_di", "illegal", "ror_di", "asr_di", /*30*/
+ "asl_di", "rol_di", "dec_di", "illegal", "inc_di", "tst_di", "illegal", "clr_di",
+ "nega", "illegal", "illegal", "coma", "lsra", "illegal", "rora", "asra", /*40*/
+ "asla", "rola", "deca", "illegal", "inca", "tsta", "illegal", "clra",
+ "negx", "illegal", "illegal", "comx", "lsrx", "illegal", "rorx", "asrx", /*50*/
+ "aslx", "rolx", "decx", "illegal", "incx", "tstx", "illegal", "clrx",
+ "neg_ix1", "illegal", "illegal", "com_ix1", "lsr_ix1", "illegal", "ror_ix1", "asr_ix1", /*60*/
+ "asl_ix1", "rol_ix1", "dec_ix1", "illegal", "inc_ix1", "tst_ix1", "jmp_ix1", "clr_ix1",
+ "neg_ix", "illegal", "illegal", "com_ix", "lsr_ix", "illegal", "ror_ix", "asr_ix", /*70*/
+ "asl_ix", "rol_ix", "dec_ix", "illegal", "inc_ix", "tst_ix", "jmp_ix", "clr_ix",
+ "rti", "rts", "illegal", "swi", "illegal", "illegal", "illegal", "illegal", /*80*/
+ "illegal", "illegal", "illegal", "illegal", "illegal", "illegal", "illegal", "illegal",
+ "illegal", "illegal", "illegal", "illegal", "illegal", "illegal", "illegal", "tax", /*90*/
+ "clc", "sec", "cli", "sei", "rsp", "nop", "illegal", "txa",
+ "suba_im", "cmpa_im", "sbca_im", "cpx_im", "anda_im", "bita_im", "lda_im", "illegal", /*A0*/
+ "eora_im", "adca_im", "ora_im", "adda_im", "illegal", "bsr", "ldx_im", "illegal",
+ "suba_di", "cmpa_di", "sbca_di", "cpx_di", "anda_di", "bita_di", "lda_di", "sta_di", /*B0*/
+ "eora_di", "adca_di", "ora_di", "adda_di", "jmp_di", "jsr_di", "ldx_di", "stx_di",
+ "suba_ex", "cmpa_ex", "sbca_ex", "cpx_ex", "anda_ex", "bita_ex", "lda_ex", "sta_ex", /*C0*/
+ "eora_ex", "adca_ex", "ora_ex", "adda_ex", "jmp_ex", "jsr_ex", "ldx_ex", "stx_ex",
+ "suba_ix2", "cmpa_ix2", "sbca_ix2", "cpx_ix2", "anda_ix2", "bita_ix2", "lda_ix2", "sta_ix2", /*D0*/
+ "eora_ix2", "adca_ix2", "ora_ix2", "adda_ix2", "jmp_ix2", "jsr_ix2", "ldx_ix2", "stx_ix2",
+ "suba_ix1", "cmpa_ix1", "sbca_ix1", "cpx_ix1", "anda_ix1", "bita_ix1", "lda_ix1", "sta_ix1", /*E0*/
+ "eora_ix1", "adca_ix1", "ora_ix1", "adda_ix1", "jmp_ix1", "jsr_ix1", "ldx_ix1", "stx_ix1",
+ "suba_ix", "cmpa_ix", "sbca_ix", "cpx_ix", "anda_ix", "bita_ix", "lda_ix", "sta_ix", /*F0*/
+ "eora_ix", "adca_ix", "ora_ix", "adda_ix", "jmp_ix", "jsr_ix", "ldx_ix", "stx_ix"
+};
+#endif
+
+CPU_DISASSEMBLE( m6805 )
+{
+ int code, bit;
+ UINT16 ea;
+ UINT32 flags = 0;
+
+ code = oprom[0];
+
+ if (disasm[code][0] == bsr || disasm[code][0] == jsr)
+ flags = DASMFLAG_STEP_OVER;
+ else if (disasm[code][0] == rts || disasm[code][0] == rti)
+ flags = DASMFLAG_STEP_OUT;
+
+ buffer += sprintf(buffer, "%-6s", op_name_str[disasm[code][0]]);
+
+ switch( disasm[code][1] )
+ {
+ case _btr: /* bit test and relative branch */
+ bit = (code >> 1) & 7;
+ sprintf (buffer, "%d,$%02X,$%03X", bit, opram[1], pc + 3 + (INT8)opram[2]);
+ return 3 | flags | DASMFLAG_SUPPORTED;
+ case _bit: /* bit test */
+ bit = (code >> 1) & 7;
+ sprintf (buffer, "%d,$%03X", bit, opram[1]);
+ return 2 | flags | DASMFLAG_SUPPORTED;
+ case _rel: /* relative */
+ sprintf (buffer, "$%03X", pc + 2 + (INT8)opram[1]);
+ return 2 | flags | DASMFLAG_SUPPORTED;
+ case _imm: /* immediate */
+ sprintf (buffer, "#$%02X", opram[1]);
+ return 2 | flags | DASMFLAG_SUPPORTED;
+ case _dir: /* direct (zero page address) */
+ sprintf (buffer, "$%02X", opram[1]);
+ return 2 | flags | DASMFLAG_SUPPORTED;
+ case _ext: /* extended (16 bit address) */
+ ea = (opram[1] << 8) + opram[2];
+ sprintf (buffer, "$%04X", ea);
+ return 3 | flags | DASMFLAG_SUPPORTED;
+ case _idx: /* indexed */
+ sprintf (buffer, "(x)");
+ return 1 | flags | DASMFLAG_SUPPORTED;
+ case _ix1: /* indexed + byte (zero page) */
+ sprintf (buffer, "(x+$%02X)", opram[1]);
+ return 2 | flags | DASMFLAG_SUPPORTED;
+ case _ix2: /* indexed + word (16 bit address) */
+ ea = (opram[1] << 8) + opram[2];
+ sprintf (buffer, "(x+$%04X)", ea);
+ return 3 | flags | DASMFLAG_SUPPORTED;
+ default: /* implicit */
+ return 1 | flags | DASMFLAG_SUPPORTED;
+ }
+}
diff --git a/trunk/src/emu/cpu/m6805/6805ops.c b/trunk/src/emu/cpu/m6805/6805ops.c
new file mode 100644
index 00000000000..fba19931e1f
--- /dev/null
+++ b/trunk/src/emu/cpu/m6805/6805ops.c
@@ -0,0 +1,1799 @@
+
+/*
+
+HNZC
+
+? = undefined
+* = affected
+- = unaffected
+0 = cleared
+1 = set
+# = ccr directly affected by instruction
+@ = special - carry set if bit 7 is set
+
+*/
+
+#define OP_HANDLER(_name) INLINE void _name (m6805_Regs* cpustate)
+
+#define OP_HANDLER_BIT(_name) INLINE void _name (m6805_Regs* cpustate, UINT8 bit)
+
+OP_HANDLER( illegal )
+{
+ logerror("M6805: illegal opcode\n");
+}
+
+/* $00/$02/$04/$06/$08/$0A/$0C/$0E BRSET direct,relative ---- */
+OP_HANDLER_BIT( brset )
+{
+ UINT8 t,r;
+ DIRBYTE(r);
+ IMMBYTE(t);
+
+ CLC;
+
+ if (r&bit) {
+ SEC;
+ PC+=SIGNED(t);
+ }
+}
+
+/* $01/$03/$05/$07/$09/$0B/$0D/$0F BRCLR direct,relative ---- */
+OP_HANDLER_BIT( brclr )
+{
+ UINT8 t,r;
+ DIRBYTE(r);
+ IMMBYTE(t);
+
+ SEC;
+
+ if (!(r&bit)) {
+ CLC;
+ PC+=SIGNED(t);
+ }
+}
+
+/* $10/$12/$14/$16/$18/$1A/$1C/$1E BSET direct ---- */
+OP_HANDLER_BIT( bset )
+{
+ UINT8 t,r;
+ DIRBYTE(t); r=t|bit;
+ WM(EAD,r);
+}
+
+/* $11/$13/$15/$17/$19/$1B/$1D/$1F BCLR direct ---- */
+OP_HANDLER_BIT( bclr)
+{
+ UINT8 t,r;
+ DIRBYTE(t); r=t&(~bit);
+ WM(EAD,r);
+}
+
+/* $20 BRA relative ---- */
+OP_HANDLER( bra )
+{
+ UINT8 t;
+ IMMBYTE(t);
+ PC+=SIGNED(t);
+}
+
+/* $21 BRN relative ---- */
+static UINT8 m6805_brn_t; // hack around GCC 4.6 error because we need the side effects of IMMBYTE
+OP_HANDLER( brn )
+{
+ IMMBYTE(m6805_brn_t);
+}
+
+/* $22 BHI relative ---- */
+OP_HANDLER( bhi )
+{
+ BRANCH( !(CC&(CFLAG|ZFLAG)) );
+}
+
+/* $23 BLS relative ---- */
+OP_HANDLER( bls )
+{
+ BRANCH( CC&(CFLAG|ZFLAG) );
+}
+
+/* $24 BCC relative ---- */
+OP_HANDLER( bcc )
+{
+ BRANCH( !(CC&CFLAG) );
+}
+
+/* $25 BCS relative ---- */
+OP_HANDLER( bcs )
+{
+ BRANCH( CC&CFLAG );
+}
+
+/* $26 BNE relative ---- */
+OP_HANDLER( bne )
+{
+ BRANCH( !(CC&ZFLAG) );
+}
+
+/* $27 BEQ relative ---- */
+OP_HANDLER( beq )
+{
+ BRANCH( CC&ZFLAG );
+}
+
+/* $28 BHCC relative ---- */
+OP_HANDLER( bhcc )
+{
+ BRANCH( !(CC&HFLAG) );
+}
+
+/* $29 BHCS relative ---- */
+OP_HANDLER( bhcs )
+{
+ BRANCH( CC&HFLAG );
+}
+
+/* $2a BPL relative ---- */
+OP_HANDLER( bpl )
+{
+ BRANCH( !(CC&NFLAG) );
+}
+
+/* $2b BMI relative ---- */
+OP_HANDLER( bmi )
+{
+ BRANCH( CC&NFLAG );
+}
+
+/* $2c BMC relative ---- */
+OP_HANDLER( bmc )
+{
+ BRANCH( !(CC&IFLAG) );
+}
+
+/* $2d BMS relative ---- */
+OP_HANDLER( bms )
+{
+ BRANCH( CC&IFLAG );
+}
+
+/* $2e BIL relative ---- */
+OP_HANDLER( bil )
+{
+ if(SUBTYPE==SUBTYPE_HD63705)
+ {
+ BRANCH( cpustate->nmi_state!=CLEAR_LINE );
+ }
+ else
+ {
+ BRANCH( cpustate->irq_state[0]!=CLEAR_LINE );
+ }
+}
+
+/* $2f BIH relative ---- */
+OP_HANDLER( bih )
+{
+ if(SUBTYPE==SUBTYPE_HD63705)
+ {
+ BRANCH( cpustate->nmi_state==CLEAR_LINE );
+ }
+ else
+ {
+ BRANCH( cpustate->irq_state[0]==CLEAR_LINE );
+ }
+}
+
+/* $30 NEG direct -*** */
+OP_HANDLER( neg_di )
+{
+ UINT8 t;
+ UINT16 r;
+ DIRBYTE(t);
+ r=-t;
+ CLR_NZC;
+ SET_FLAGS8(0,t,r);
+ WM(EAD,r);
+}
+
+/* $31 ILLEGAL */
+
+/* $32 ILLEGAL */
+
+/* $33 COM direct -**1 */
+OP_HANDLER( com_di )
+{
+ UINT8 t;
+ DIRBYTE(t);
+ t = ~t;
+ CLR_NZ;
+ SET_NZ8(t);
+ SEC;
+ WM(EAD,t);
+}
+
+/* $34 LSR direct -0** */
+OP_HANDLER( lsr_di )
+{
+ UINT8 t;
+ DIRBYTE(t);
+ CLR_NZC;
+ CC |= (t&0x01);
+ t >>= 1;
+ SET_Z8(t);
+ WM(EAD,t);
+}
+
+/* $35 ILLEGAL */
+
+/* $36 ROR direct -*** */
+OP_HANDLER( ror_di )
+{
+ UINT8 t,r;
+ DIRBYTE(t);
+ r = (CC & 0x01) << 7;
+ CLR_NZC;
+ CC |= (t & 0x01);
+ r |= t>>1;
+ SET_NZ8(r);
+ WM(EAD,r);
+}
+
+/* $37 ASR direct ?*** */
+OP_HANDLER( asr_di )
+{
+ UINT8 t;
+ DIRBYTE(t);
+ CLR_NZC; CC|=(t&0x01);
+ t>>=1; t|=((t&0x40)<<1);
+ SET_NZ8(t);
+ WM(EAD,t);
+}
+
+/* $38 LSL direct ?*** */
+OP_HANDLER( lsl_di )
+{
+ UINT8 t;
+ UINT16 r;
+ DIRBYTE(t);
+ r = t << 1;
+ CLR_NZC;
+ SET_FLAGS8(t,t,r);
+ WM(EAD,r);
+}
+
+/* $39 ROL direct -*** */
+OP_HANDLER( rol_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = CC & 0x01;
+ r |= t << 1;
+ CLR_NZC;
+ SET_FLAGS8(t,t,r);
+ WM(EAD,r);
+}
+
+/* $3a DEC direct -**- */
+OP_HANDLER( dec_di )
+{
+ UINT8 t;
+ DIRBYTE(t);
+ --t;
+ CLR_NZ; SET_FLAGS8D(t);
+ WM(EAD,t);
+}
+
+/* $3b ILLEGAL */
+
+/* $3c INC direct -**- */
+OP_HANDLER( inc_di )
+{
+ UINT8 t;
+ DIRBYTE(t);
+ ++t;
+ CLR_NZ; SET_FLAGS8I(t);
+ WM(EAD,t);
+}
+
+/* $3d TST direct -**- */
+OP_HANDLER( tst_di )
+{
+ UINT8 t;
+ DIRBYTE(t);
+ CLR_NZ; SET_NZ8(t);
+}
+
+/* $3e ILLEGAL */
+
+/* $3f CLR direct -0100 */
+OP_HANDLER( clr_di )
+{
+ DIRECT;
+ CLR_NZC; SEZ;
+ WM(EAD,0);
+}
+
+/* $40 NEGA inherent ?*** */
+OP_HANDLER( nega )
+{
+ UINT16 r;
+ r = -A;
+ CLR_NZC; SET_FLAGS8(0,A,r);
+ A = r;
+}
+
+/* $41 ILLEGAL */
+
+/* $42 ILLEGAL */
+
+/* $43 COMA inherent -**1 */
+OP_HANDLER( coma )
+{
+ A = ~A;
+ CLR_NZ;
+ SET_NZ8(A);
+ SEC;
+}
+
+/* $44 LSRA inherent -0** */
+OP_HANDLER( lsra )
+{
+ CLR_NZC;
+ CC |= (A & 0x01);
+ A >>= 1;
+ SET_Z8(A);
+}
+
+/* $45 ILLEGAL */
+
+/* $46 RORA inherent -*** */
+OP_HANDLER( rora )
+{
+ UINT8 r;
+ r = (CC & 0x01) << 7;
+ CLR_NZC;
+ CC |= (A & 0x01);
+ r |= A >> 1;
+ SET_NZ8(r);
+ A = r;
+}
+
+/* $47 ASRA inherent ?*** */
+OP_HANDLER( asra )
+{
+ CLR_NZC;
+ CC |= (A & 0x01);
+ A = (A & 0x80) | (A >> 1);
+ SET_NZ8(A);
+}
+
+/* $48 LSLA inherent ?*** */
+OP_HANDLER( lsla )
+{
+ UINT16 r;
+ r = A << 1;
+ CLR_NZC;
+ SET_FLAGS8(A,A,r);
+ A = r;
+}
+
+/* $49 ROLA inherent -*** */
+OP_HANDLER( rola )
+{
+ UINT16 t,r;
+ t = A;
+ r = CC & 0x01;
+ r |= t << 1;
+ CLR_NZC;
+ SET_FLAGS8(t,t,r);
+ A = r;
+}
+
+/* $4a DECA inherent -**- */
+OP_HANDLER( deca )
+{
+ --A;
+ CLR_NZ;
+ SET_FLAGS8D(A);
+}
+
+/* $4b ILLEGAL */
+
+/* $4c INCA inherent -**- */
+OP_HANDLER( inca )
+{
+ ++A;
+ CLR_NZ;
+ SET_FLAGS8I(A);
+}
+
+/* $4d TSTA inherent -**- */
+OP_HANDLER( tsta )
+{
+ CLR_NZ;
+ SET_NZ8(A);
+}
+
+/* $4e ILLEGAL */
+
+/* $4f CLRA inherent -010 */
+OP_HANDLER( clra )
+{
+ A = 0;
+ CLR_NZ;
+ SEZ;
+}
+
+/* $50 NEGX inherent ?*** */
+OP_HANDLER( negx )
+{
+ UINT16 r;
+ r = -X;
+ CLR_NZC;
+ SET_FLAGS8(0,X,r);
+ X = r;
+}
+
+/* $51 ILLEGAL */
+
+/* $52 ILLEGAL */
+
+/* $53 COMX inherent -**1 */
+OP_HANDLER( comx )
+{
+ X = ~X;
+ CLR_NZ;
+ SET_NZ8(X);
+ SEC;
+}
+
+/* $54 LSRX inherent -0** */
+OP_HANDLER( lsrx )
+{
+ CLR_NZC;
+ CC |= (X & 0x01);
+ X >>= 1;
+ SET_Z8(X);
+}
+
+/* $55 ILLEGAL */
+
+/* $56 RORX inherent -*** */
+OP_HANDLER( rorx )
+{
+ UINT8 r;
+ r = (CC & 0x01) << 7;
+ CLR_NZC;
+ CC |= (X & 0x01);
+ r |= X>>1;
+ SET_NZ8(r);
+ X = r;
+}
+
+/* $57 ASRX inherent ?*** */
+OP_HANDLER( asrx )
+{
+ CLR_NZC;
+ CC |= (X & 0x01);
+ X = (X & 0x80) | (X >> 1);
+ SET_NZ8(X);
+}
+
+/* $58 ASLX inherent ?*** */
+OP_HANDLER( aslx )
+{
+ UINT16 r;
+ r = X << 1;
+ CLR_NZC;
+ SET_FLAGS8(X,X,r);
+ X = r;
+}
+
+/* $59 ROLX inherent -*** */
+OP_HANDLER( rolx )
+{
+ UINT16 t,r;
+ t = X;
+ r = CC & 0x01;
+ r |= t<<1;
+ CLR_NZC;
+ SET_FLAGS8(t,t,r);
+ X = r;
+}
+
+/* $5a DECX inherent -**- */
+OP_HANDLER( decx )
+{
+ --X;
+ CLR_NZ;
+ SET_FLAGS8D(X);
+}
+
+/* $5b ILLEGAL */
+
+/* $5c INCX inherent -**- */
+OP_HANDLER( incx )
+{
+ ++X;
+ CLR_NZ;
+ SET_FLAGS8I(X);
+}
+
+/* $5d TSTX inherent -**- */
+OP_HANDLER( tstx )
+{
+ CLR_NZ;
+ SET_NZ8(X);
+}
+
+/* $5e ILLEGAL */
+
+/* $5f CLRX inherent -010 */
+OP_HANDLER( clrx )
+{
+ X = 0;
+ CLR_NZC;
+ SEZ;
+}
+
+/* $60 NEG indexed, 1 byte offset -*** */
+OP_HANDLER( neg_ix1 )
+{
+ UINT8 t;
+ UINT16 r;
+ IDX1BYTE(t); r=-t;
+ CLR_NZC; SET_FLAGS8(0,t,r);
+ WM(EAD,r);
+}
+
+/* $61 ILLEGAL */
+
+/* $62 ILLEGAL */
+
+/* $63 COM indexed, 1 byte offset -**1 */
+OP_HANDLER( com_ix1 )
+{
+ UINT8 t;
+ IDX1BYTE(t); t = ~t;
+ CLR_NZ; SET_NZ8(t); SEC;
+ WM(EAD,t);
+}
+
+/* $64 LSR indexed, 1 byte offset -0** */
+OP_HANDLER( lsr_ix1 )
+{
+ UINT8 t;
+ IDX1BYTE(t);
+ CLR_NZC;
+ CC |= (t & 0x01);
+ t >>= 1;
+ SET_Z8(t);
+ WM(EAD,t);
+}
+
+/* $65 ILLEGAL */
+
+/* $66 ROR indexed, 1 byte offset -*** */
+OP_HANDLER( ror_ix1 )
+{
+ UINT8 t,r;
+ IDX1BYTE(t);
+ r = (CC & 0x01) << 7;
+ CLR_NZC;
+ CC |= (t & 0x01);
+ r |= t>>1;
+ SET_NZ8(r);
+ WM(EAD,r);
+}
+
+/* $67 ASR indexed, 1 byte offset ?*** */
+OP_HANDLER( asr_ix1 )
+{
+ UINT8 t;
+ IDX1BYTE(t);
+ CLR_NZC; CC|=(t&0x01);
+ t>>=1; t|=((t&0x40)<<1);
+ SET_NZ8(t);
+ WM(EAD,t);
+}
+
+/* $68 LSL indexed, 1 byte offset ?*** */
+OP_HANDLER( lsl_ix1 )
+{
+ UINT8 t;
+ UINT16 r;
+ IDX1BYTE(t);
+ r = t << 1;
+ CLR_NZC;
+ SET_FLAGS8(t,t,r);
+ WM(EAD,r);
+}
+
+/* $69 ROL indexed, 1 byte offset -*** */
+OP_HANDLER( rol_ix1 )
+{
+ UINT16 t,r;
+ IDX1BYTE(t);
+ r = CC & 0x01;
+ r |= t << 1;
+ CLR_NZC;
+ SET_FLAGS8(t,t,r);
+ WM(EAD,r);
+}
+
+/* $6a DEC indexed, 1 byte offset -**- */
+OP_HANDLER( dec_ix1 )
+{
+ UINT8 t;
+ IDX1BYTE(t);
+ --t;
+ CLR_NZ; SET_FLAGS8D(t);
+ WM(EAD,t);
+}
+
+/* $6b ILLEGAL */
+
+/* $6c INC indexed, 1 byte offset -**- */
+OP_HANDLER( inc_ix1 )
+{
+ UINT8 t;
+ IDX1BYTE(t);
+ ++t;
+ CLR_NZ; SET_FLAGS8I(t);
+ WM(EAD,t);
+}
+
+/* $6d TST indexed, 1 byte offset -**- */
+OP_HANDLER( tst_ix1 )
+{
+ UINT8 t;
+ IDX1BYTE(t);
+ CLR_NZ; SET_NZ8(t);
+}
+
+/* $6e ILLEGAL */
+
+/* $6f CLR indexed, 1 byte offset -0100 */
+OP_HANDLER( clr_ix1 )
+{
+ INDEXED1;
+ CLR_NZC; SEZ;
+ WM(EAD,0);
+}
+
+/* $70 NEG indexed -*** */
+OP_HANDLER( neg_ix )
+{
+ UINT8 t;
+ UINT16 r;
+ IDXBYTE(t); r=-t;
+ CLR_NZC; SET_FLAGS8(0,t,r);
+ WM(EAD,r);
+}
+
+/* $71 ILLEGAL */
+
+/* $72 ILLEGAL */
+
+/* $73 COM indexed -**1 */
+OP_HANDLER( com_ix )
+{
+ UINT8 t;
+ IDXBYTE(t); t = ~t;
+ CLR_NZ; SET_NZ8(t); SEC;
+ WM(EAD,t);
+}
+
+/* $74 LSR indexed -0** */
+OP_HANDLER( lsr_ix )
+{
+ UINT8 t;
+ IDXBYTE(t);
+ CLR_NZC;
+ CC |= (t & 0x01);
+ t >>= 1;
+ SET_Z8(t);
+ WM(EAD,t);
+}
+
+/* $75 ILLEGAL */
+
+/* $76 ROR indexed -*** */
+OP_HANDLER( ror_ix )
+{
+ UINT8 t,r;
+ IDXBYTE(t);
+ r = (CC & 0x01) << 7;
+ CLR_NZC;
+ CC |= (t & 0x01);
+ r |= t >> 1;
+ SET_NZ8(r);
+ WM(EAD,r);
+}
+
+/* $77 ASR indexed ?*** */
+OP_HANDLER( asr_ix )
+{
+ UINT8 t;
+ IDXBYTE(t);
+ CLR_NZC;
+ CC |= (t & 0x01);
+ t = (t & 0x80) | (t >> 1);
+ SET_NZ8(t);
+ WM(EAD,t);
+}
+
+/* $78 LSL indexed ?*** */
+OP_HANDLER( lsl_ix )
+{
+ UINT8 t;
+ UINT16 r;
+ IDXBYTE(t); r=t<<1;
+ CLR_NZC; SET_FLAGS8(t,t,r);
+ WM(EAD,r);
+}
+
+/* $79 ROL indexed -*** */
+OP_HANDLER( rol_ix )
+{
+ UINT16 t,r;
+ IDXBYTE(t);
+ r = CC & 0x01;
+ r |= t << 1;
+ CLR_NZC;
+ SET_FLAGS8(t,t,r);
+ WM(EAD,r);
+}
+
+/* $7a DEC indexed -**- */
+OP_HANDLER( dec_ix )
+{
+ UINT8 t;
+ IDXBYTE(t);
+ --t;
+ CLR_NZ; SET_FLAGS8D(t);
+ WM(EAD,t);
+}
+
+/* $7b ILLEGAL */
+
+/* $7c INC indexed -**- */
+OP_HANDLER( inc_ix )
+{
+ UINT8 t;
+ IDXBYTE(t);
+ ++t;
+ CLR_NZ; SET_FLAGS8I(t);
+ WM(EAD,t);
+}
+
+/* $7d TST indexed -**- */
+OP_HANDLER( tst_ix )
+{
+ UINT8 t;
+ IDXBYTE(t);
+ CLR_NZ; SET_NZ8(t);
+}
+
+/* $7e ILLEGAL */
+
+/* $7f CLR indexed -0100 */
+OP_HANDLER( clr_ix )
+{
+ INDEXED;
+ CLR_NZC; SEZ;
+ WM(EAD,0);
+}
+
+/* $80 RTI inherent #### */
+OP_HANDLER( rti )
+{
+ PULLBYTE(CC);
+ PULLBYTE(A);
+ PULLBYTE(X);
+ PULLWORD(pPC);
+#if IRQ_LEVEL_DETECT
+ if( m6805.irq_state != CLEAR_LINE && (CC & IFLAG) == 0 )
+ m6805.pending_interrupts |= M6805_INT_IRQ;
+#endif
+}
+
+/* $81 RTS inherent ---- */
+OP_HANDLER( rts )
+{
+ PULLWORD(pPC);
+}
+
+/* $82 ILLEGAL */
+
+/* $83 SWI absolute indirect ---- */
+OP_HANDLER( swi )
+{
+ PUSHWORD(cpustate->pc);
+ PUSHBYTE(cpustate->x);
+ PUSHBYTE(cpustate->a);
+ PUSHBYTE(cpustate->cc);
+ SEI;
+ if(SUBTYPE==SUBTYPE_HD63705) RM16( cpustate, 0x1ffa, &pPC ); else RM16( cpustate, 0xfffc, &pPC );
+}
+
+/* $84 ILLEGAL */
+
+/* $85 ILLEGAL */
+
+/* $86 ILLEGAL */
+
+/* $87 ILLEGAL */
+
+/* $88 ILLEGAL */
+
+/* $89 ILLEGAL */
+
+/* $8A ILLEGAL */
+
+/* $8B ILLEGAL */
+
+/* $8C ILLEGAL */
+
+/* $8D ILLEGAL */
+
+/* $8E ILLEGAL */
+
+/* $8F ILLEGAL */
+
+/* $90 ILLEGAL */
+
+/* $91 ILLEGAL */
+
+/* $92 ILLEGAL */
+
+/* $93 ILLEGAL */
+
+/* $94 ILLEGAL */
+
+/* $95 ILLEGAL */
+
+/* $96 ILLEGAL */
+
+/* $97 TAX inherent ---- */
+OP_HANDLER( tax )
+{
+ X = A;
+}
+
+/* $98 CLC */
+
+/* $99 SEC */
+
+/* $9A CLI */
+
+/* $9B SEI */
+
+/* $9C RSP inherent ---- */
+OP_HANDLER( rsp )
+{
+ S = SP_MASK;
+}
+
+/* $9D NOP inherent ---- */
+OP_HANDLER( nop )
+{
+}
+
+/* $9E ILLEGAL */
+
+/* $9F TXA inherent ---- */
+OP_HANDLER( txa )
+{
+ A = X;
+}
+
+/* $a0 SUBA immediate ?*** */
+OP_HANDLER( suba_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t);
+ r = A - t;
+ CLR_NZC;
+ SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $a1 CMPA immediate ?*** */
+OP_HANDLER( cmpa_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t);
+ r = A - t;
+ CLR_NZC;
+ SET_FLAGS8(A,t,r);
+}
+
+/* $a2 SBCA immediate ?*** */
+OP_HANDLER( sbca_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t);
+ r = A - t - (CC & 0x01);
+ CLR_NZC;
+ SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $a3 CPX immediate -*** */
+OP_HANDLER( cpx_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t);
+ r = X - t;
+ CLR_NZC;
+ SET_FLAGS8(X,t,r);
+}
+
+/* $a4 ANDA immediate -**- */
+OP_HANDLER( anda_im )
+{
+ UINT8 t;
+ IMMBYTE(t);
+ A &= t;
+ CLR_NZ;
+ SET_NZ8(A);
+}
+
+/* $a5 BITA immediate -**- */
+OP_HANDLER( bita_im )
+{
+ UINT8 t,r;
+ IMMBYTE(t);
+ r = A & t;
+ CLR_NZ;
+ SET_NZ8(r);
+}
+
+/* $a6 LDA immediate -**- */
+OP_HANDLER( lda_im )
+{
+ IMMBYTE(A);
+ CLR_NZ;
+ SET_NZ8(A);
+}
+
+/* $a7 ILLEGAL */
+
+/* $a8 EORA immediate -**- */
+OP_HANDLER( eora_im )
+{
+ UINT8 t;
+ IMMBYTE(t);
+ A ^= t;
+ CLR_NZ;
+ SET_NZ8(A);
+}
+
+/* $a9 ADCA immediate **** */
+OP_HANDLER( adca_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t);
+ r = A + t + (CC & 0x01);
+ CLR_HNZC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $aa ORA immediate -**- */
+OP_HANDLER( ora_im )
+{
+ UINT8 t;
+ IMMBYTE(t);
+ A |= t;
+ CLR_NZ;
+ SET_NZ8(A);
+}
+
+/* $ab ADDA immediate **** */
+OP_HANDLER( adda_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t);
+ r = A + t;
+ CLR_HNZC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $ac ILLEGAL */
+
+/* $ad BSR ---- */
+OP_HANDLER( bsr )
+{
+ UINT8 t;
+ IMMBYTE(t);
+ PUSHWORD(cpustate->pc);
+ PC += SIGNED(t);
+}
+
+/* $ae LDX immediate -**- */
+OP_HANDLER( ldx_im )
+{
+ IMMBYTE(X);
+ CLR_NZ;
+ SET_NZ8(X);
+}
+
+/* $af ILLEGAL */
+
+/* $b0 SUBA direct ?*** */
+OP_HANDLER( suba_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = A - t;
+ CLR_NZC;
+ SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $b1 CMPA direct ?*** */
+OP_HANDLER( cmpa_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = A - t;
+ CLR_NZC;
+ SET_FLAGS8(A,t,r);
+}
+
+/* $b2 SBCA direct ?*** */
+OP_HANDLER( sbca_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = A - t - (CC & 0x01);
+ CLR_NZC;
+ SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $b3 CPX direct -*** */
+OP_HANDLER( cpx_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = X - t;
+ CLR_NZC;
+ SET_FLAGS8(X,t,r);
+}
+
+/* $b4 ANDA direct -**- */
+OP_HANDLER( anda_di )
+{
+ UINT8 t;
+ DIRBYTE(t);
+ A &= t;
+ CLR_NZ;
+ SET_NZ8(A);
+}
+
+/* $b5 BITA direct -**- */
+OP_HANDLER( bita_di )
+{
+ UINT8 t,r;
+ DIRBYTE(t);
+ r = A & t;
+ CLR_NZ;
+ SET_NZ8(r);
+}
+
+/* $b6 LDA direct -**- */
+OP_HANDLER( lda_di )
+{
+ DIRBYTE(A);
+ CLR_NZ;
+ SET_NZ8(A);
+}
+
+/* $b7 STA direct -**- */
+OP_HANDLER( sta_di )
+{
+ CLR_NZ;
+ SET_NZ8(A);
+ DIRECT;
+ WM(EAD,A);
+}
+
+/* $b8 EORA direct -**- */
+OP_HANDLER( eora_di )
+{
+ UINT8 t;
+ DIRBYTE(t);
+ A ^= t;
+ CLR_NZ;
+ SET_NZ8(A);
+}
+
+/* $b9 ADCA direct **** */
+OP_HANDLER( adca_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = A + t + (CC & 0x01);
+ CLR_HNZC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $ba ORA direct -**- */
+OP_HANDLER( ora_di )
+{
+ UINT8 t;
+ DIRBYTE(t);
+ A |= t;
+ CLR_NZ;
+ SET_NZ8(A);
+}
+
+/* $bb ADDA direct **** */
+OP_HANDLER( adda_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = A + t;
+ CLR_HNZC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $bc JMP direct -*** */
+OP_HANDLER( jmp_di )
+{
+ DIRECT;
+ PC = EA;
+}
+
+/* $bd JSR direct ---- */
+OP_HANDLER( jsr_di )
+{
+ DIRECT;
+ PUSHWORD(cpustate->pc);
+ PC = EA;
+}
+
+/* $be LDX direct -**- */
+OP_HANDLER( ldx_di )
+{
+ DIRBYTE(X);
+ CLR_NZ;
+ SET_NZ8(X);
+}
+
+/* $bf STX direct -**- */
+OP_HANDLER( stx_di )
+{
+ CLR_NZ;
+ SET_NZ8(X);
+ DIRECT;
+ WM(EAD,X);
+}
+
+/* $c0 SUBA extended ?*** */
+OP_HANDLER( suba_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = A - t;
+ CLR_NZC;
+ SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $c1 CMPA extended ?*** */
+OP_HANDLER( cmpa_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = A - t;
+ CLR_NZC;
+ SET_FLAGS8(A,t,r);
+}
+
+/* $c2 SBCA extended ?*** */
+OP_HANDLER( sbca_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = A - t - (CC & 0x01);
+ CLR_NZC;
+ SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $c3 CPX extended -*** */
+OP_HANDLER( cpx_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = X - t;
+ CLR_NZC;
+ SET_FLAGS8(X,t,r);
+}
+
+/* $c4 ANDA extended -**- */
+OP_HANDLER( anda_ex )
+{
+ UINT8 t;
+ EXTBYTE(t);
+ A &= t;
+ CLR_NZ;
+ SET_NZ8(A);
+}
+
+/* $c5 BITA extended -**- */
+OP_HANDLER( bita_ex )
+{
+ UINT8 t,r;
+ EXTBYTE(t);
+ r = A & t;
+ CLR_NZ;
+ SET_NZ8(r);
+}
+
+/* $c6 LDA extended -**- */
+OP_HANDLER( lda_ex )
+{
+ EXTBYTE(A);
+ CLR_NZ;
+ SET_NZ8(A);
+}
+
+/* $c7 STA extended -**- */
+OP_HANDLER( sta_ex )
+{
+ CLR_NZ;
+ SET_NZ8(A);
+ EXTENDED;
+ WM(EAD,A);
+}
+
+/* $c8 EORA extended -**- */
+OP_HANDLER( eora_ex )
+{
+ UINT8 t;
+ EXTBYTE(t);
+ A ^= t;
+ CLR_NZ;
+ SET_NZ8(A);
+}
+
+/* $c9 ADCA extended **** */
+OP_HANDLER( adca_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = A + t + (CC & 0x01);
+ CLR_HNZC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $ca ORA extended -**- */
+OP_HANDLER( ora_ex )
+{
+ UINT8 t;
+ EXTBYTE(t);
+ A |= t;
+ CLR_NZ;
+ SET_NZ8(A);
+}
+
+/* $cb ADDA extended **** */
+OP_HANDLER( adda_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = A + t;
+ CLR_HNZC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $cc JMP extended -*** */
+OP_HANDLER( jmp_ex )
+{
+ EXTENDED;
+ PC = EA;
+}
+
+/* $cd JSR extended ---- */
+OP_HANDLER( jsr_ex )
+{
+ EXTENDED;
+ PUSHWORD(cpustate->pc);
+ PC = EA;
+}
+
+/* $ce LDX extended -**- */
+OP_HANDLER( ldx_ex )
+{
+ EXTBYTE(X);
+ CLR_NZ;
+ SET_NZ8(X);
+}
+
+/* $cf STX extended -**- */
+OP_HANDLER( stx_ex )
+{
+ CLR_NZ;
+ SET_NZ8(X);
+ EXTENDED;
+ WM(EAD,X);
+}
+
+/* $d0 SUBA indexed, 2 byte offset ?*** */
+OP_HANDLER( suba_ix2 )
+{
+ UINT16 t,r;
+ IDX2BYTE(t);
+ r = A - t;
+ CLR_NZC;
+ SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $d1 CMPA indexed, 2 byte offset ?*** */
+OP_HANDLER( cmpa_ix2 )
+{
+ UINT16 t,r;
+ IDX2BYTE(t);
+ r = A - t;
+ CLR_NZC;
+ SET_FLAGS8(A,t,r);
+}
+
+/* $d2 SBCA indexed, 2 byte offset ?*** */
+OP_HANDLER( sbca_ix2 )
+{
+ UINT16 t,r;
+ IDX2BYTE(t);
+ r = A - t - (CC & 0x01);
+ CLR_NZC;
+ SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $d3 CPX indexed, 2 byte offset -*** */
+OP_HANDLER( cpx_ix2 )
+{
+ UINT16 t,r;
+ IDX2BYTE(t);
+ r = X - t;
+ CLR_NZC;
+ SET_FLAGS8(X,t,r);
+}
+
+/* $d4 ANDA indexed, 2 byte offset -**- */
+OP_HANDLER( anda_ix2 )
+{
+ UINT8 t;
+ IDX2BYTE(t);
+ A &= t;
+ CLR_NZ;
+ SET_NZ8(A);
+}
+
+/* $d5 BITA indexed, 2 byte offset -**- */
+OP_HANDLER( bita_ix2 )
+{
+ UINT8 t,r;
+ IDX2BYTE(t);
+ r = A & t;
+ CLR_NZ;
+ SET_NZ8(r);
+}
+
+/* $d6 LDA indexed, 2 byte offset -**- */
+OP_HANDLER( lda_ix2 )
+{
+ IDX2BYTE(A);
+ CLR_NZ;
+ SET_NZ8(A);
+}
+
+/* $d7 STA indexed, 2 byte offset -**- */
+OP_HANDLER( sta_ix2 )
+{
+ CLR_NZ;
+ SET_NZ8(A);
+ INDEXED2;
+ WM(EAD,A);
+}
+
+/* $d8 EORA indexed, 2 byte offset -**- */
+OP_HANDLER( eora_ix2 )
+{
+ UINT8 t;
+ IDX2BYTE(t);
+ A ^= t;
+ CLR_NZ;
+ SET_NZ8(A);
+}
+
+/* $d9 ADCA indexed, 2 byte offset **** */
+OP_HANDLER( adca_ix2 )
+{
+ UINT16 t,r;
+ IDX2BYTE(t);
+ r = A + t + (CC & 0x01);
+ CLR_HNZC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $da ORA indexed, 2 byte offset -**- */
+OP_HANDLER( ora_ix2 )
+{
+ UINT8 t;
+ IDX2BYTE(t);
+ A |= t;
+ CLR_NZ;
+ SET_NZ8(A);
+}
+
+/* $db ADDA indexed, 2 byte offset **** */
+OP_HANDLER( adda_ix2 )
+{
+ UINT16 t,r;
+ IDX2BYTE(t);
+ r = A + t;
+ CLR_HNZC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $dc JMP indexed, 2 byte offset -*** */
+OP_HANDLER( jmp_ix2 )
+{
+ INDEXED2;
+ PC = EA;
+}
+
+/* $dd JSR indexed, 2 byte offset ---- */
+OP_HANDLER( jsr_ix2 )
+{
+ INDEXED2;
+ PUSHWORD(cpustate->pc);
+ PC = EA;
+}
+
+/* $de LDX indexed, 2 byte offset -**- */
+OP_HANDLER( ldx_ix2 )
+{
+ IDX2BYTE(X);
+ CLR_NZ;
+ SET_NZ8(X);
+}
+
+/* $df STX indexed, 2 byte offset -**- */
+OP_HANDLER( stx_ix2 )
+{
+ CLR_NZ;
+ SET_NZ8(X);
+ INDEXED2;
+ WM(EAD,X);
+}
+
+/* $e0 SUBA indexed, 1 byte offset ?*** */
+OP_HANDLER( suba_ix1 )
+{
+ UINT16 t,r;
+ IDX1BYTE(t);
+ r = A - t;
+ CLR_NZC;
+ SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $e1 CMPA indexed, 1 byte offset ?*** */
+OP_HANDLER( cmpa_ix1 )
+{
+ UINT16 t,r;
+ IDX1BYTE(t);
+ r = A - t;
+ CLR_NZC;
+ SET_FLAGS8(A,t,r);
+}
+
+/* $e2 SBCA indexed, 1 byte offset ?*** */
+OP_HANDLER( sbca_ix1 )
+{
+ UINT16 t,r;
+ IDX1BYTE(t);
+ r = A - t - (CC & 0x01);
+ CLR_NZC;
+ SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $e3 CPX indexed, 1 byte offset -*** */
+OP_HANDLER( cpx_ix1 )
+{
+ UINT16 t,r;
+ IDX1BYTE(t);
+ r = X - t;
+ CLR_NZC;
+ SET_FLAGS8(X,t,r);
+}
+
+/* $e4 ANDA indexed, 1 byte offset -**- */
+OP_HANDLER( anda_ix1 )
+{
+ UINT8 t;
+ IDX1BYTE(t);
+ A &= t;
+ CLR_NZ;
+ SET_NZ8(A);
+}
+
+/* $e5 BITA indexed, 1 byte offset -**- */
+OP_HANDLER( bita_ix1 )
+{
+ UINT8 t,r;
+ IDX1BYTE(t);
+ r = A & t;
+ CLR_NZ;
+ SET_NZ8(r);
+}
+
+/* $e6 LDA indexed, 1 byte offset -**- */
+OP_HANDLER( lda_ix1 )
+{
+ IDX1BYTE(A);
+ CLR_NZ;
+ SET_NZ8(A);
+}
+
+/* $e7 STA indexed, 1 byte offset -**- */
+OP_HANDLER( sta_ix1 )
+{
+ CLR_NZ;
+ SET_NZ8(A);
+ INDEXED1;
+ WM(EAD,A);
+}
+
+/* $e8 EORA indexed, 1 byte offset -**- */
+OP_HANDLER( eora_ix1 )
+{
+ UINT8 t;
+ IDX1BYTE(t);
+ A ^= t;
+ CLR_NZ;
+ SET_NZ8(A);
+}
+
+/* $e9 ADCA indexed, 1 byte offset **** */
+OP_HANDLER( adca_ix1 )
+{
+ UINT16 t,r;
+ IDX1BYTE(t);
+ r = A + t + (CC & 0x01);
+ CLR_HNZC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $ea ORA indexed, 1 byte offset -**- */
+OP_HANDLER( ora_ix1 )
+{
+ UINT8 t;
+ IDX1BYTE(t);
+ A |= t;
+ CLR_NZ;
+ SET_NZ8(A);
+}
+
+/* $eb ADDA indexed, 1 byte offset **** */
+OP_HANDLER( adda_ix1 )
+{
+ UINT16 t,r;
+ IDX1BYTE(t);
+ r = A + t;
+ CLR_HNZC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $ec JMP indexed, 1 byte offset -*** */
+OP_HANDLER( jmp_ix1 )
+{
+ INDEXED1;
+ PC = EA;
+}
+
+/* $ed JSR indexed, 1 byte offset ---- */
+OP_HANDLER( jsr_ix1 )
+{
+ INDEXED1;
+ PUSHWORD(cpustate->pc);
+ PC = EA;
+}
+
+/* $ee LDX indexed, 1 byte offset -**- */
+OP_HANDLER( ldx_ix1 )
+{
+ IDX1BYTE(X);
+ CLR_NZ;
+ SET_NZ8(X);
+}
+
+/* $ef STX indexed, 1 byte offset -**- */
+OP_HANDLER( stx_ix1 )
+{
+ CLR_NZ;
+ SET_NZ8(X);
+ INDEXED1;
+ WM(EAD,X);
+}
+
+/* $f0 SUBA indexed ?*** */
+OP_HANDLER( suba_ix )
+{
+ UINT16 t,r;
+ IDXBYTE(t);
+ r = A - t;
+ CLR_NZC;
+ SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $f1 CMPA indexed ?*** */
+OP_HANDLER( cmpa_ix )
+{
+ UINT16 t,r;
+ IDXBYTE(t);
+ r = A - t;
+ CLR_NZC;
+ SET_FLAGS8(A,t,r);
+}
+
+/* $f2 SBCA indexed ?*** */
+OP_HANDLER( sbca_ix )
+{
+ UINT16 t,r;
+ IDXBYTE(t);
+ r = A - t - (CC & 0x01);
+ CLR_NZC;
+ SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $f3 CPX indexed -*** */
+OP_HANDLER( cpx_ix )
+{
+ UINT16 t,r;
+ IDXBYTE(t);
+ r = X - t;
+ CLR_NZC;
+ SET_FLAGS8(X,t,r);
+}
+
+/* $f4 ANDA indexed -**- */
+OP_HANDLER( anda_ix )
+{
+ UINT8 t;
+ IDXBYTE(t);
+ A &= t;
+ CLR_NZ;
+ SET_NZ8(A);
+}
+
+/* $f5 BITA indexed -**- */
+OP_HANDLER( bita_ix )
+{
+ UINT8 t,r;
+ IDXBYTE(t);
+ r = A & t;
+ CLR_NZ;
+ SET_NZ8(r);
+}
+
+/* $f6 LDA indexed -**- */
+OP_HANDLER( lda_ix )
+{
+ IDXBYTE(A);
+ CLR_NZ;
+ SET_NZ8(A);
+}
+
+/* $f7 STA indexed -**- */
+OP_HANDLER( sta_ix )
+{
+ CLR_NZ;
+ SET_NZ8(A);
+ INDEXED;
+ WM(EAD,A);
+}
+
+/* $f8 EORA indexed -**- */
+OP_HANDLER( eora_ix )
+{
+ UINT8 t;
+ IDXBYTE(t);
+ A ^= t;
+ CLR_NZ;
+ SET_NZ8(A);
+}
+
+/* $f9 ADCA indexed **** */
+OP_HANDLER( adca_ix )
+{
+ UINT16 t,r;
+ IDXBYTE(t);
+ r = A + t + (CC & 0x01);
+ CLR_HNZC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $fa ORA indexed -**- */
+OP_HANDLER( ora_ix )
+{
+ UINT8 t;
+ IDXBYTE(t);
+ A |= t;
+ CLR_NZ;
+ SET_NZ8(A);
+}
+
+/* $fb ADDA indexed **** */
+OP_HANDLER( adda_ix )
+{
+ UINT16 t,r;
+ IDXBYTE(t);
+ r = A + t;
+ CLR_HNZC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $fc JMP indexed -*** */
+OP_HANDLER( jmp_ix )
+{
+ INDEXED;
+ PC = EA;
+}
+
+/* $fd JSR indexed ---- */
+OP_HANDLER( jsr_ix )
+{
+ INDEXED;
+ PUSHWORD(cpustate->pc);
+ PC = EA;
+}
+
+/* $fe LDX indexed -**- */
+OP_HANDLER( ldx_ix )
+{
+ IDXBYTE(X);
+ CLR_NZ;
+ SET_NZ8(X);
+}
+
+/* $ff STX indexed -**- */
+OP_HANDLER( stx_ix )
+{
+ CLR_NZ;
+ SET_NZ8(X);
+ INDEXED;
+ WM(EAD,X);
+}
diff --git a/trunk/src/emu/cpu/m6805/m6805.c b/trunk/src/emu/cpu/m6805/m6805.c
new file mode 100644
index 00000000000..fc9467117e9
--- /dev/null
+++ b/trunk/src/emu/cpu/m6805/m6805.c
@@ -0,0 +1,1182 @@
+/*** m6805: Portable 6805 emulator ******************************************
+
+ m6805.c (Also supports hd68705 and hd63705 variants)
+
+ References:
+
+ 6809 Simulator V09, By L.C. Benschop, Eidnhoven The Netherlands.
+
+ m6809: Portable 6809 emulator, DS (6809 code in MAME, derived from
+ the 6809 Simulator V09)
+
+ 6809 Microcomputer Programming & Interfacing with Experiments"
+ by Andrew C. Staugaard, Jr.; Howard W. Sams & Co., Inc.
+
+ System dependencies: UINT16 must be 16 bit unsigned int
+ UINT8 must be 8 bit unsigned int
+ UINT32 must be more than 16 bits
+ arrays up to 65536 bytes must be supported
+ machine must be twos complement
+
+ Additional Notes:
+
+ K.Wilkins 18/03/99 - Added 63705 functonality and modified all CPU functions
+ necessary to support:
+ Variable width address bus
+ Different stack pointer
+ Alternate boot vectors
+ Alternate interrups vectors
+
+
+*****************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "m6805.h"
+
+#define IRQ_LEVEL_DETECT 0
+
+enum
+{
+ SUBTYPE_M6805,
+ SUBTYPE_M68705,
+ SUBTYPE_HD63705,
+ SUBTYPE_M68HC05EG
+};
+
+/* 6805 Registers */
+typedef struct
+{
+ /* Pre-pointerafied public globals */
+ int iCount;
+ PAIR ea; /* effective address */
+
+ int subtype; /* Which sub-type is being emulated */
+ UINT32 sp_mask; /* Stack pointer address mask */
+ UINT32 sp_low; /* Stack pointer low water mark (or floor) */
+ PAIR pc; /* Program counter */
+ PAIR s; /* Stack pointer */
+ UINT8 a; /* Accumulator */
+ UINT8 x; /* Index register */
+ UINT8 cc; /* Condition codes */
+
+ UINT16 pending_interrupts; /* MB */
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ int irq_state[9]; /* KW Additional lines for HD63705 */
+ int nmi_state;
+} m6805_Regs;
+
+INLINE m6805_Regs *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == M6805 ||
+ device->type() == M68705 ||
+ device->type() == HD63705 ||
+ device->type() == M68HC05EG);
+ return (m6805_Regs *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+/****************************************************************************/
+/* Read a byte from given memory location */
+/****************************************************************************/
+#define M6805_RDMEM(Addr) ((unsigned)cpustate->program->read_byte(Addr))
+
+/****************************************************************************/
+/* Write a byte to given memory location */
+/****************************************************************************/
+#define M6805_WRMEM(Addr,Value) (cpustate->program->write_byte(Addr,Value))
+
+/****************************************************************************/
+/* M6805_RDOP() is identical to M6805_RDMEM() except it is used for reading */
+/* opcodes. In case of system with memory mapped I/O, this function can be */
+/* used to greatly speed up emulation */
+/****************************************************************************/
+#define M6805_RDOP(Addr) ((unsigned)cpustate->direct->read_decrypted_byte(Addr))
+
+/****************************************************************************/
+/* M6805_RDOP_ARG() is identical to M6805_RDOP() but it's used for reading */
+/* opcode arguments. This difference can be used to support systems that */
+/* use different encoding mechanisms for opcodes and opcode arguments */
+/****************************************************************************/
+#define M6805_RDOP_ARG(Addr) ((unsigned)cpustate->direct->read_raw_byte(Addr))
+
+#define SUBTYPE cpustate->subtype /* CPU Type */
+#define SP_MASK cpustate->sp_mask /* stack pointer mask */
+#define SP_LOW cpustate->sp_low /* stack pointer low water mark */
+#define pPC cpustate->pc /* program counter PAIR */
+#define PC cpustate->pc.w.l /* program counter lower word */
+#define S cpustate->s.w.l /* stack pointer lower word */
+#define A cpustate->a /* accumulator */
+#define X cpustate->x /* index register */
+#define CC cpustate->cc /* condition codes */
+
+#define EAD cpustate->ea.d
+#define EA cpustate->ea.w.l
+
+
+/* DS -- THESE ARE RE-DEFINED IN m6805.h TO RAM, ROM or FUNCTIONS IN cpuintrf.c */
+#define RM(Addr) M6805_RDMEM(Addr)
+#define WM(Addr,Value) M6805_WRMEM(Addr,Value)
+#define M_RDOP(Addr) M6805_RDOP(Addr)
+#define M_RDOP_ARG(Addr) M6805_RDOP_ARG(Addr)
+
+/* macros to tweak the PC and SP */
+#define SP_INC if( ++S > SP_MASK) S = SP_LOW
+#define SP_DEC if( --S < SP_LOW) S = SP_MASK
+#define SP_ADJUST(s) ( ( (s) & SP_MASK ) | SP_LOW )
+
+/* macros to access memory */
+#define IMMBYTE(b) {b = M_RDOP_ARG(PC++);}
+#define IMMWORD(w) {w.d = 0; w.b.h = M_RDOP_ARG(PC); w.b.l = M_RDOP_ARG(PC+1); PC+=2;}
+
+#define PUSHBYTE(b) wr_s_handler_b(cpustate, &b)
+#define PUSHWORD(w) wr_s_handler_w(cpustate, &w)
+#define PULLBYTE(b) rd_s_handler_b(cpustate, &b)
+#define PULLWORD(w) rd_s_handler_w(cpustate, &w)
+
+/* CC masks H INZC
+ 7654 3210 */
+#define CFLAG 0x01
+#define ZFLAG 0x02
+#define NFLAG 0x04
+#define IFLAG 0x08
+#define HFLAG 0x10
+
+#define CLR_NZ CC&=~(NFLAG|ZFLAG)
+#define CLR_HNZC CC&=~(HFLAG|NFLAG|ZFLAG|CFLAG)
+#define CLR_Z CC&=~(ZFLAG)
+#define CLR_NZC CC&=~(NFLAG|ZFLAG|CFLAG)
+#define CLR_ZC CC&=~(ZFLAG|CFLAG)
+
+/* macros for CC -- CC bits affected should be reset before calling */
+#define SET_Z(a) if(!a)SEZ
+#define SET_Z8(a) SET_Z((UINT8)a)
+#define SET_N8(a) CC|=((a&0x80)>>5)
+#define SET_H(a,b,r) CC|=((a^b^r)&0x10)
+#define SET_C8(a) CC|=((a&0x100)>>8)
+
+static const UINT8 flags8i[256]= /* increment */
+{
+0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04
+};
+static const UINT8 flags8d[256]= /* decrement */
+{
+0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04
+};
+#define SET_FLAGS8I(a) {CC|=flags8i[(a)&0xff];}
+#define SET_FLAGS8D(a) {CC|=flags8d[(a)&0xff];}
+
+/* combos */
+#define SET_NZ8(a) {SET_N8(a);SET_Z(a);}
+#define SET_FLAGS8(a,b,r) {SET_N8(r);SET_Z8(r);SET_C8(r);}
+
+/* for treating an unsigned UINT8 as a signed INT16 */
+#define SIGNED(b) ((INT16)(b&0x80?b|0xff00:b))
+
+/* Macros for addressing modes */
+#define DIRECT EAD=0;IMMBYTE(cpustate->ea.b.l)
+#define IMM8 EA=PC++
+#define EXTENDED IMMWORD(cpustate->ea)
+#define INDEXED EA=X
+#define INDEXED1 {EAD=0; IMMBYTE(cpustate->ea.b.l); EA+=X;}
+#define INDEXED2 {IMMWORD(cpustate->ea); EA+=X;}
+
+/* macros to set status flags */
+#if defined(SEC)
+#undef SEC
+#endif
+#define SEC CC|=CFLAG
+#define CLC CC&=~CFLAG
+#define SEZ CC|=ZFLAG
+#define CLZ CC&=~ZFLAG
+#define SEN CC|=NFLAG
+#define CLN CC&=~NFLAG
+#define SEH CC|=HFLAG
+#define CLH CC&=~HFLAG
+#define SEI CC|=IFLAG
+#define CLI CC&=~IFLAG
+
+/* macros for convenience */
+#define DIRBYTE(b) {DIRECT;b=RM(EAD);}
+#define EXTBYTE(b) {EXTENDED;b=RM(EAD);}
+#define IDXBYTE(b) {INDEXED;b=RM(EAD);}
+#define IDX1BYTE(b) {INDEXED1;b=RM(EAD);}
+#define IDX2BYTE(b) {INDEXED2;b=RM(EAD);}
+/* Macros for branch instructions */
+#define BRANCH(f) { UINT8 t; IMMBYTE(t); if(f) { PC+=SIGNED(t); if (t==0xfe) { /* speed up busy loops */ if(cpustate->iCount > 0) cpustate->iCount = 0; } } }
+
+/* what they say it is ... */
+static const unsigned char cycles1[] =
+{
+ /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
+ /*0*/ 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
+ /*1*/ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ /*2*/ 4, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ /*3*/ 6, 0, 0, 6, 6, 0, 6, 6, 6, 6, 6, 6, 0, 6, 6, 0,
+ /*4*/ 4, 0, 0, 4, 4, 0, 4, 4, 4, 4, 4, 0, 4, 4, 0, 4,
+ /*5*/ 4, 0, 0, 4, 4, 0, 4, 4, 4, 4, 4, 0, 4, 4, 0, 4,
+ /*6*/ 7, 0, 0, 7, 7, 0, 7, 7, 7, 7, 7, 0, 7, 7, 0, 7,
+ /*7*/ 6, 0, 0, 6, 6, 0, 6, 6, 6, 6, 6, 0, 6, 6, 0, 6,
+ /*8*/ 9, 6, 0,11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /*9*/ 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2,
+ /*A*/ 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 8, 2, 0,
+ /*B*/ 4, 4, 4, 4, 4, 4, 4, 5, 4, 4, 4, 4, 3, 7, 4, 5,
+ /*C*/ 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 4, 8, 5, 6,
+ /*D*/ 6, 6, 6, 6, 6, 6, 6, 7, 6, 6, 6, 6, 5, 9, 6, 7,
+ /*E*/ 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 4, 8, 5, 6,
+ /*F*/ 4, 4, 4, 4, 4, 4, 4, 5, 4, 4, 4, 4, 3, 7, 4, 5
+};
+
+
+/* pre-clear a PAIR union; clearing h2 and h3 only might be faster? */
+#define CLEAR_PAIR(p) p->d = 0
+
+INLINE void rd_s_handler_b( m6805_Regs *cpustate, UINT8 *b )
+{
+ SP_INC;
+ *b = RM( S );
+}
+
+INLINE void rd_s_handler_w( m6805_Regs *cpustate, PAIR *p )
+{
+ CLEAR_PAIR(p);
+ SP_INC;
+ p->b.h = RM( S );
+ SP_INC;
+ p->b.l = RM( S );
+}
+
+INLINE void wr_s_handler_b( m6805_Regs *cpustate, UINT8 *b )
+{
+ WM( S, *b );
+ SP_DEC;
+}
+
+INLINE void wr_s_handler_w( m6805_Regs *cpustate, PAIR *p )
+{
+ WM( S, p->b.l );
+ SP_DEC;
+ WM( S, p->b.h );
+ SP_DEC;
+}
+
+INLINE void RM16( m6805_Regs *cpustate, UINT32 Addr, PAIR *p )
+{
+ CLEAR_PAIR(p);
+ p->b.h = RM(Addr);
+ ++Addr;
+// if( ++Addr > AMASK ) Addr = 0;
+ p->b.l = RM(Addr);
+}
+
+#ifdef UNUSED_FUNCTION
+INLINE void WM16( m6805_Regs *cpustate, UINT32 Addr, PAIR *p )
+{
+ WM( Addr, p->b.h );
+ ++Addr;
+// if( ++Addr > AMASK ) Addr = 0;
+ WM( Addr, p->b.l );
+}
+#endif
+
+
+/* Generate interrupt - m68705 version */
+static void m68705_Interrupt( m6805_Regs *cpustate )
+{
+ if( (cpustate->pending_interrupts & ((1<<M6805_IRQ_LINE)|M68705_INT_MASK)) != 0 )
+ {
+ if ( (CC & IFLAG) == 0 )
+ {
+ PUSHWORD(cpustate->pc);
+ PUSHBYTE(cpustate->x);
+ PUSHBYTE(cpustate->a);
+ PUSHBYTE(cpustate->cc);
+ SEI;
+ if (cpustate->irq_callback)
+ (*cpustate->irq_callback)(cpustate->device, 0);
+
+ if ((cpustate->pending_interrupts & (1<<M68705_IRQ_LINE)) != 0 )
+ {
+ cpustate->pending_interrupts &= ~(1<<M68705_IRQ_LINE);
+ RM16( cpustate, 0xfffa, &pPC);
+ }
+ else if((cpustate->pending_interrupts&(1<<M68705_INT_TIMER))!=0)
+ {
+ cpustate->pending_interrupts &= ~(1<<M68705_INT_TIMER);
+ RM16( cpustate, 0xfff8, &pPC);
+ }
+ }
+ cpustate->iCount -= 11;
+ }
+}
+
+/* Generate interrupts */
+static void Interrupt( m6805_Regs *cpustate )
+{
+ /* the 6805 latches interrupt requests internally, so we don't clear */
+ /* pending_interrupts until the interrupt is taken, no matter what the */
+ /* external IRQ pin does. */
+
+ if( (cpustate->pending_interrupts & (1<<HD63705_INT_NMI)) != 0)
+ {
+ PUSHWORD(cpustate->pc);
+ PUSHBYTE(cpustate->x);
+ PUSHBYTE(cpustate->a);
+ PUSHBYTE(cpustate->cc);
+ SEI;
+ /* no vectors supported, just do the callback to clear irq_state if needed */
+ if (cpustate->irq_callback)
+ (*cpustate->irq_callback)(cpustate->device, 0);
+
+ RM16( cpustate, 0x1ffc, &pPC);
+ cpustate->pending_interrupts &= ~(1<<HD63705_INT_NMI);
+
+ cpustate->iCount -= 11;
+
+ }
+ else if( (cpustate->pending_interrupts & ((1<<M6805_IRQ_LINE)|HD63705_INT_MASK)) != 0 ) {
+ if ( (CC & IFLAG) == 0 ) {
+ {
+ /* standard IRQ */
+//#if (HAS_HD63705)
+// if(SUBTYPE!=SUBTYPE_HD63705)
+//#endif
+// PC |= ~AMASK;
+ PUSHWORD(cpustate->pc);
+ PUSHBYTE(cpustate->x);
+ PUSHBYTE(cpustate->a);
+ PUSHBYTE(cpustate->cc);
+ SEI;
+ /* no vectors supported, just do the callback to clear irq_state if needed */
+ if (cpustate->irq_callback)
+ (*cpustate->irq_callback)(cpustate->device, 0);
+
+
+ if(SUBTYPE==SUBTYPE_HD63705)
+ {
+ /* Need to add emulation of other interrupt sources here KW-2/4/99 */
+ /* This is just a quick patch for Namco System 2 operation */
+
+ if((cpustate->pending_interrupts&(1<<HD63705_INT_IRQ1))!=0)
+ {
+ cpustate->pending_interrupts &= ~(1<<HD63705_INT_IRQ1);
+ RM16( cpustate, 0x1ff8, &pPC);
+ }
+ else if((cpustate->pending_interrupts&(1<<HD63705_INT_IRQ2))!=0)
+ {
+ cpustate->pending_interrupts &= ~(1<<HD63705_INT_IRQ2);
+ RM16( cpustate, 0x1fec, &pPC);
+ }
+ else if((cpustate->pending_interrupts&(1<<HD63705_INT_ADCONV))!=0)
+ {
+ cpustate->pending_interrupts &= ~(1<<HD63705_INT_ADCONV);
+ RM16( cpustate, 0x1fea, &pPC);
+ }
+ else if((cpustate->pending_interrupts&(1<<HD63705_INT_TIMER1))!=0)
+ {
+ cpustate->pending_interrupts &= ~(1<<HD63705_INT_TIMER1);
+ RM16( cpustate, 0x1ff6, &pPC);
+ }
+ else if((cpustate->pending_interrupts&(1<<HD63705_INT_TIMER2))!=0)
+ {
+ cpustate->pending_interrupts &= ~(1<<HD63705_INT_TIMER2);
+ RM16( cpustate, 0x1ff4, &pPC);
+ }
+ else if((cpustate->pending_interrupts&(1<<HD63705_INT_TIMER3))!=0)
+ {
+ cpustate->pending_interrupts &= ~(1<<HD63705_INT_TIMER3);
+ RM16( cpustate, 0x1ff2, &pPC);
+ }
+ else if((cpustate->pending_interrupts&(1<<HD63705_INT_PCI))!=0)
+ {
+ cpustate->pending_interrupts &= ~(1<<HD63705_INT_PCI);
+ RM16( cpustate, 0x1ff0, &pPC);
+ }
+ else if((cpustate->pending_interrupts&(1<<HD63705_INT_SCI))!=0)
+ {
+ cpustate->pending_interrupts &= ~(1<<HD63705_INT_SCI);
+ RM16( cpustate, 0x1fee, &pPC);
+ }
+ }
+ else if (SUBTYPE == SUBTYPE_M68HC05EG)
+ {
+ if((cpustate->pending_interrupts&(1<<M68HC05EG_INT_IRQ))!=0)
+ {
+ cpustate->pending_interrupts &= ~(1<<M68HC05EG_INT_IRQ);
+ RM16( cpustate, 0x1ffa, &pPC);
+ }
+ else if((cpustate->pending_interrupts&(1<<M68HC05EG_INT_TIMER))!=0)
+ {
+ cpustate->pending_interrupts &= ~(1<<M68HC05EG_INT_TIMER);
+ RM16( cpustate, 0x1ff8, &pPC);
+ }
+ else if((cpustate->pending_interrupts&(1<<M68HC05EG_INT_CPI))!=0)
+ {
+ cpustate->pending_interrupts &= ~(1<<M68HC05EG_INT_CPI);
+ RM16( cpustate, 0x1ff6, &pPC);
+ }
+ }
+ else
+ {
+ RM16( cpustate, 0xffff - 5, &pPC );
+ }
+
+ } // CC & IFLAG
+ cpustate->pending_interrupts &= ~(1<<M6805_IRQ_LINE);
+ }
+ cpustate->iCount -= 11;
+ }
+}
+
+static void state_register(m6805_Regs *cpustate, const char *type, legacy_cpu_device *device)
+{
+ device->save_item(NAME(A));
+ device->save_item(NAME(PC));
+ device->save_item(NAME(S));
+ device->save_item(NAME(X));
+ device->save_item(NAME(CC));
+ device->save_item(NAME(cpustate->pending_interrupts));
+ device->save_item(NAME(cpustate->irq_state));
+}
+
+static CPU_INIT( m6805 )
+{
+ m6805_Regs *cpustate = get_safe_token(device);
+
+ state_register(cpustate, "m6805", device);
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+}
+
+static CPU_RESET( m6805 )
+{
+ m6805_Regs *cpustate = get_safe_token(device);
+
+ device_irq_callback save_irqcallback = cpustate->irq_callback;
+ memset(cpustate, 0, sizeof(*cpustate));
+
+ cpustate->iCount=50000; /* Used to be global */
+ cpustate->irq_callback = save_irqcallback;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+
+ /* Force CPU sub-type and relevant masks */
+ cpustate->subtype = SUBTYPE_M6805;
+ SP_MASK = 0x07f;
+ SP_LOW = 0x060;
+
+ /* Initial stack pointer */
+ S = SP_MASK;
+
+ /* IRQ disabled */
+ SEI;
+ RM16( cpustate, 0xfffe, &pPC );
+}
+
+static CPU_EXIT( m6805 )
+{
+ /* nothing to do */
+}
+
+
+static void set_irq_line( m6805_Regs *cpustate, int irqline, int state )
+{
+ /* Basic 6805 only has one IRQ line */
+ /* See HD63705 specific version */
+ if (cpustate->irq_state[0] == state) return;
+
+ cpustate->irq_state[0] = state;
+ if (state != CLEAR_LINE)
+ cpustate->pending_interrupts |= 1<<M6805_IRQ_LINE;
+}
+
+#include "6805ops.c"
+
+
+/* execute instructions on this CPU until icount expires */
+static CPU_EXECUTE( m6805 )
+{
+ UINT8 ireg;
+ m6805_Regs *cpustate = get_safe_token(device);
+
+ S = SP_ADJUST( S ); /* Taken from CPU_SET_CONTEXT when pointer'afying */
+
+ do
+ {
+ if (cpustate->pending_interrupts != 0)
+ {
+ if (SUBTYPE==SUBTYPE_M68705)
+ {
+ m68705_Interrupt(cpustate);
+ }
+ else
+ {
+ Interrupt(cpustate);
+ }
+ }
+
+ debugger_instruction_hook(device, PC);
+
+ ireg=M_RDOP(PC++);
+
+ switch( ireg )
+ {
+ case 0x00: brset(cpustate, 0x01); break;
+ case 0x01: brclr(cpustate, 0x01); break;
+ case 0x02: brset(cpustate, 0x02); break;
+ case 0x03: brclr(cpustate, 0x02); break;
+ case 0x04: brset(cpustate, 0x04); break;
+ case 0x05: brclr(cpustate, 0x04); break;
+ case 0x06: brset(cpustate, 0x08); break;
+ case 0x07: brclr(cpustate, 0x08); break;
+ case 0x08: brset(cpustate, 0x10); break;
+ case 0x09: brclr(cpustate, 0x10); break;
+ case 0x0A: brset(cpustate, 0x20); break;
+ case 0x0B: brclr(cpustate, 0x20); break;
+ case 0x0C: brset(cpustate, 0x40); break;
+ case 0x0D: brclr(cpustate, 0x40); break;
+ case 0x0E: brset(cpustate, 0x80); break;
+ case 0x0F: brclr(cpustate, 0x80); break;
+ case 0x10: bset(cpustate, 0x01); break;
+ case 0x11: bclr(cpustate, 0x01); break;
+ case 0x12: bset(cpustate, 0x02); break;
+ case 0x13: bclr(cpustate, 0x02); break;
+ case 0x14: bset(cpustate, 0x04); break;
+ case 0x15: bclr(cpustate, 0x04); break;
+ case 0x16: bset(cpustate, 0x08); break;
+ case 0x17: bclr(cpustate, 0x08); break;
+ case 0x18: bset(cpustate, 0x10); break;
+ case 0x19: bclr(cpustate, 0x10); break;
+ case 0x1a: bset(cpustate, 0x20); break;
+ case 0x1b: bclr(cpustate, 0x20); break;
+ case 0x1c: bset(cpustate, 0x40); break;
+ case 0x1d: bclr(cpustate, 0x40); break;
+ case 0x1e: bset(cpustate, 0x80); break;
+ case 0x1f: bclr(cpustate, 0x80); break;
+ case 0x20: bra(cpustate); break;
+ case 0x21: brn(cpustate); break;
+ case 0x22: bhi(cpustate); break;
+ case 0x23: bls(cpustate); break;
+ case 0x24: bcc(cpustate); break;
+ case 0x25: bcs(cpustate); break;
+ case 0x26: bne(cpustate); break;
+ case 0x27: beq(cpustate); break;
+ case 0x28: bhcc(cpustate); break;
+ case 0x29: bhcs(cpustate); break;
+ case 0x2a: bpl(cpustate); break;
+ case 0x2b: bmi(cpustate); break;
+ case 0x2c: bmc(cpustate); break;
+ case 0x2d: bms(cpustate); break;
+ case 0x2e: bil(cpustate); break;
+ case 0x2f: bih(cpustate); break;
+ case 0x30: neg_di(cpustate); break;
+ case 0x31: illegal(cpustate); break;
+ case 0x32: illegal(cpustate); break;
+ case 0x33: com_di(cpustate); break;
+ case 0x34: lsr_di(cpustate); break;
+ case 0x35: illegal(cpustate); break;
+ case 0x36: ror_di(cpustate); break;
+ case 0x37: asr_di(cpustate); break;
+ case 0x38: lsl_di(cpustate); break;
+ case 0x39: rol_di(cpustate); break;
+ case 0x3a: dec_di(cpustate); break;
+ case 0x3b: illegal(cpustate); break;
+ case 0x3c: inc_di(cpustate); break;
+ case 0x3d: tst_di(cpustate); break;
+ case 0x3e: illegal(cpustate); break;
+ case 0x3f: clr_di(cpustate); break;
+ case 0x40: nega(cpustate); break;
+ case 0x41: illegal(cpustate); break;
+ case 0x42: illegal(cpustate); break;
+ case 0x43: coma(cpustate); break;
+ case 0x44: lsra(cpustate); break;
+ case 0x45: illegal(cpustate); break;
+ case 0x46: rora(cpustate); break;
+ case 0x47: asra(cpustate); break;
+ case 0x48: lsla(cpustate); break;
+ case 0x49: rola(cpustate); break;
+ case 0x4a: deca(cpustate); break;
+ case 0x4b: illegal(cpustate); break;
+ case 0x4c: inca(cpustate); break;
+ case 0x4d: tsta(cpustate); break;
+ case 0x4e: illegal(cpustate); break;
+ case 0x4f: clra(cpustate); break;
+ case 0x50: negx(cpustate); break;
+ case 0x51: illegal(cpustate); break;
+ case 0x52: illegal(cpustate); break;
+ case 0x53: comx(cpustate); break;
+ case 0x54: lsrx(cpustate); break;
+ case 0x55: illegal(cpustate); break;
+ case 0x56: rorx(cpustate); break;
+ case 0x57: asrx(cpustate); break;
+ case 0x58: aslx(cpustate); break;
+ case 0x59: rolx(cpustate); break;
+ case 0x5a: decx(cpustate); break;
+ case 0x5b: illegal(cpustate); break;
+ case 0x5c: incx(cpustate); break;
+ case 0x5d: tstx(cpustate); break;
+ case 0x5e: illegal(cpustate); break;
+ case 0x5f: clrx(cpustate); break;
+ case 0x60: neg_ix1(cpustate); break;
+ case 0x61: illegal(cpustate); break;
+ case 0x62: illegal(cpustate); break;
+ case 0x63: com_ix1(cpustate); break;
+ case 0x64: lsr_ix1(cpustate); break;
+ case 0x65: illegal(cpustate); break;
+ case 0x66: ror_ix1(cpustate); break;
+ case 0x67: asr_ix1(cpustate); break;
+ case 0x68: lsl_ix1(cpustate); break;
+ case 0x69: rol_ix1(cpustate); break;
+ case 0x6a: dec_ix1(cpustate); break;
+ case 0x6b: illegal(cpustate); break;
+ case 0x6c: inc_ix1(cpustate); break;
+ case 0x6d: tst_ix1(cpustate); break;
+ case 0x6e: illegal(cpustate); break;
+ case 0x6f: clr_ix1(cpustate); break;
+ case 0x70: neg_ix(cpustate); break;
+ case 0x71: illegal(cpustate); break;
+ case 0x72: illegal(cpustate); break;
+ case 0x73: com_ix(cpustate); break;
+ case 0x74: lsr_ix(cpustate); break;
+ case 0x75: illegal(cpustate); break;
+ case 0x76: ror_ix(cpustate); break;
+ case 0x77: asr_ix(cpustate); break;
+ case 0x78: lsl_ix(cpustate); break;
+ case 0x79: rol_ix(cpustate); break;
+ case 0x7a: dec_ix(cpustate); break;
+ case 0x7b: illegal(cpustate); break;
+ case 0x7c: inc_ix(cpustate); break;
+ case 0x7d: tst_ix(cpustate); break;
+ case 0x7e: illegal(cpustate); break;
+ case 0x7f: clr_ix(cpustate); break;
+ case 0x80: rti(cpustate); break;
+ case 0x81: rts(cpustate); break;
+ case 0x82: illegal(cpustate); break;
+ case 0x83: swi(cpustate); break;
+ case 0x84: illegal(cpustate); break;
+ case 0x85: illegal(cpustate); break;
+ case 0x86: illegal(cpustate); break;
+ case 0x87: illegal(cpustate); break;
+ case 0x88: illegal(cpustate); break;
+ case 0x89: illegal(cpustate); break;
+ case 0x8a: illegal(cpustate); break;
+ case 0x8b: illegal(cpustate); break;
+ case 0x8c: illegal(cpustate); break;
+ case 0x8d: illegal(cpustate); break;
+ case 0x8e: illegal(cpustate); break;
+ case 0x8f: illegal(cpustate); break;
+ case 0x90: illegal(cpustate); break;
+ case 0x91: illegal(cpustate); break;
+ case 0x92: illegal(cpustate); break;
+ case 0x93: illegal(cpustate); break;
+ case 0x94: illegal(cpustate); break;
+ case 0x95: illegal(cpustate); break;
+ case 0x96: illegal(cpustate); break;
+ case 0x97: tax(cpustate); break;
+ case 0x98: CLC; break;
+ case 0x99: SEC; break;
+#if IRQ_LEVEL_DETECT
+ case 0x9a: CLI; if (m6805.irq_state != CLEAR_LINE) m6805.pending_interrupts |= 1<<M6805_IRQ_LINE; break;
+#else
+ case 0x9a: CLI; break;
+#endif
+ case 0x9b: SEI; break;
+ case 0x9c: rsp(cpustate); break;
+ case 0x9d: nop(cpustate); break;
+ case 0x9e: illegal(cpustate); break;
+ case 0x9f: txa(cpustate); break;
+ case 0xa0: suba_im(cpustate); break;
+ case 0xa1: cmpa_im(cpustate); break;
+ case 0xa2: sbca_im(cpustate); break;
+ case 0xa3: cpx_im(cpustate); break;
+ case 0xa4: anda_im(cpustate); break;
+ case 0xa5: bita_im(cpustate); break;
+ case 0xa6: lda_im(cpustate); break;
+ case 0xa7: illegal(cpustate); break;
+ case 0xa8: eora_im(cpustate); break;
+ case 0xa9: adca_im(cpustate); break;
+ case 0xaa: ora_im(cpustate); break;
+ case 0xab: adda_im(cpustate); break;
+ case 0xac: illegal(cpustate); break;
+ case 0xad: bsr(cpustate); break;
+ case 0xae: ldx_im(cpustate); break;
+ case 0xaf: illegal(cpustate); break;
+ case 0xb0: suba_di(cpustate); break;
+ case 0xb1: cmpa_di(cpustate); break;
+ case 0xb2: sbca_di(cpustate); break;
+ case 0xb3: cpx_di(cpustate); break;
+ case 0xb4: anda_di(cpustate); break;
+ case 0xb5: bita_di(cpustate); break;
+ case 0xb6: lda_di(cpustate); break;
+ case 0xb7: sta_di(cpustate); break;
+ case 0xb8: eora_di(cpustate); break;
+ case 0xb9: adca_di(cpustate); break;
+ case 0xba: ora_di(cpustate); break;
+ case 0xbb: adda_di(cpustate); break;
+ case 0xbc: jmp_di(cpustate); break;
+ case 0xbd: jsr_di(cpustate); break;
+ case 0xbe: ldx_di(cpustate); break;
+ case 0xbf: stx_di(cpustate); break;
+ case 0xc0: suba_ex(cpustate); break;
+ case 0xc1: cmpa_ex(cpustate); break;
+ case 0xc2: sbca_ex(cpustate); break;
+ case 0xc3: cpx_ex(cpustate); break;
+ case 0xc4: anda_ex(cpustate); break;
+ case 0xc5: bita_ex(cpustate); break;
+ case 0xc6: lda_ex(cpustate); break;
+ case 0xc7: sta_ex(cpustate); break;
+ case 0xc8: eora_ex(cpustate); break;
+ case 0xc9: adca_ex(cpustate); break;
+ case 0xca: ora_ex(cpustate); break;
+ case 0xcb: adda_ex(cpustate); break;
+ case 0xcc: jmp_ex(cpustate); break;
+ case 0xcd: jsr_ex(cpustate); break;
+ case 0xce: ldx_ex(cpustate); break;
+ case 0xcf: stx_ex(cpustate); break;
+ case 0xd0: suba_ix2(cpustate); break;
+ case 0xd1: cmpa_ix2(cpustate); break;
+ case 0xd2: sbca_ix2(cpustate); break;
+ case 0xd3: cpx_ix2(cpustate); break;
+ case 0xd4: anda_ix2(cpustate); break;
+ case 0xd5: bita_ix2(cpustate); break;
+ case 0xd6: lda_ix2(cpustate); break;
+ case 0xd7: sta_ix2(cpustate); break;
+ case 0xd8: eora_ix2(cpustate); break;
+ case 0xd9: adca_ix2(cpustate); break;
+ case 0xda: ora_ix2(cpustate); break;
+ case 0xdb: adda_ix2(cpustate); break;
+ case 0xdc: jmp_ix2(cpustate); break;
+ case 0xdd: jsr_ix2(cpustate); break;
+ case 0xde: ldx_ix2(cpustate); break;
+ case 0xdf: stx_ix2(cpustate); break;
+ case 0xe0: suba_ix1(cpustate); break;
+ case 0xe1: cmpa_ix1(cpustate); break;
+ case 0xe2: sbca_ix1(cpustate); break;
+ case 0xe3: cpx_ix1(cpustate); break;
+ case 0xe4: anda_ix1(cpustate); break;
+ case 0xe5: bita_ix1(cpustate); break;
+ case 0xe6: lda_ix1(cpustate); break;
+ case 0xe7: sta_ix1(cpustate); break;
+ case 0xe8: eora_ix1(cpustate); break;
+ case 0xe9: adca_ix1(cpustate); break;
+ case 0xea: ora_ix1(cpustate); break;
+ case 0xeb: adda_ix1(cpustate); break;
+ case 0xec: jmp_ix1(cpustate); break;
+ case 0xed: jsr_ix1(cpustate); break;
+ case 0xee: ldx_ix1(cpustate); break;
+ case 0xef: stx_ix1(cpustate); break;
+ case 0xf0: suba_ix(cpustate); break;
+ case 0xf1: cmpa_ix(cpustate); break;
+ case 0xf2: sbca_ix(cpustate); break;
+ case 0xf3: cpx_ix(cpustate); break;
+ case 0xf4: anda_ix(cpustate); break;
+ case 0xf5: bita_ix(cpustate); break;
+ case 0xf6: lda_ix(cpustate); break;
+ case 0xf7: sta_ix(cpustate); break;
+ case 0xf8: eora_ix(cpustate); break;
+ case 0xf9: adca_ix(cpustate); break;
+ case 0xfa: ora_ix(cpustate); break;
+ case 0xfb: adda_ix(cpustate); break;
+ case 0xfc: jmp_ix(cpustate); break;
+ case 0xfd: jsr_ix(cpustate); break;
+ case 0xfe: ldx_ix(cpustate); break;
+ case 0xff: stx_ix(cpustate); break;
+ }
+ cpustate->iCount -= cycles1[ireg];
+ } while( cpustate->iCount > 0 );
+}
+
+/****************************************************************************
+ * M68HC05EG section
+ ****************************************************************************/
+static CPU_INIT( m68hc05eg )
+{
+ m6805_Regs *cpustate = get_safe_token(device);
+ state_register(cpustate, "m68hc05eg", device);
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+}
+
+static CPU_RESET( m68hc05eg )
+{
+ m6805_Regs *cpustate = get_safe_token(device);
+ CPU_RESET_CALL(m6805);
+
+ /* Overide default 6805 type */
+ cpustate->subtype = SUBTYPE_M68HC05EG;
+ SP_MASK = 0xff;
+ SP_LOW = 0xc0;
+ RM16( cpustate, 0x1ffe, &cpustate->pc );
+}
+
+static void m68hc05eg_set_irq_line(m6805_Regs *cpustate, int irqline, int state)
+{
+ if (cpustate->irq_state[irqline] != state)
+ {
+ cpustate->irq_state[irqline] = state;
+
+ if (state != CLEAR_LINE)
+ {
+ cpustate->pending_interrupts |= 1<<irqline;
+ }
+ }
+}
+
+
+/****************************************************************************
+ * M68705 section
+ ****************************************************************************/
+static CPU_INIT( m68705 )
+{
+ m6805_Regs *cpustate = get_safe_token(device);
+ state_register(cpustate, "m68705", device);
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+}
+
+static CPU_RESET( m68705 )
+{
+ m6805_Regs *cpustate = get_safe_token(device);
+ CPU_RESET_CALL(m6805);
+
+ /* Overide default 6805 type */
+ cpustate->subtype = SUBTYPE_M68705;
+ RM16( cpustate, 0xfffe, &cpustate->pc );
+}
+
+static void m68705_set_irq_line(m6805_Regs *cpustate, int irqline, int state)
+{
+ if (cpustate->irq_state[irqline] == state ) return;
+ cpustate->irq_state[irqline] = state;
+ if (state != CLEAR_LINE) cpustate->pending_interrupts |= 1<<irqline;
+}
+
+
+/****************************************************************************
+ * HD63705 section
+ ****************************************************************************/
+static CPU_INIT( hd63705 )
+{
+ m6805_Regs *cpustate = get_safe_token(device);
+ state_register(cpustate, "hd63705", device);
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+}
+
+static CPU_RESET( hd63705 )
+{
+ m6805_Regs *cpustate = get_safe_token(device);
+ CPU_RESET_CALL(m6805);
+
+ /* Overide default 6805 types */
+ cpustate->subtype = SUBTYPE_HD63705;
+ SP_MASK = 0x17f;
+ SP_LOW = 0x100;
+ RM16( cpustate, 0x1ffe, &cpustate->pc );
+ S = 0x17f;
+}
+
+static void hd63705_set_irq_line(m6805_Regs *cpustate, int irqline, int state)
+{
+ if (irqline == INPUT_LINE_NMI)
+ {
+ if (cpustate->nmi_state == state) return;
+
+ cpustate->nmi_state = state;
+ if (state != CLEAR_LINE)
+ cpustate->pending_interrupts |= 1<<HD63705_INT_NMI;
+ }
+ else if (irqline <= HD63705_INT_ADCONV)
+ {
+ if (cpustate->irq_state[irqline] == state) return;
+ cpustate->irq_state[irqline] = state;
+ if (state != CLEAR_LINE) cpustate->pending_interrupts |= 1<<irqline;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( m6805 )
+{
+ m6805_Regs *cpustate = get_safe_token(device);
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + M6805_IRQ_LINE: set_irq_line(cpustate, M6805_IRQ_LINE, info->i); break;
+
+ case CPUINFO_INT_REGISTER + M6805_A: A = info->i; break;
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + M6805_PC: PC = info->i; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + M6805_S: S = SP_ADJUST(info->i); break;
+ case CPUINFO_INT_REGISTER + M6805_X: X = info->i; break;
+ case CPUINFO_INT_REGISTER + M6805_CC: CC = info->i; break;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+CPU_GET_INFO( m6805 )
+{
+ m6805_Regs *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(m6805_Regs); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 1; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 4; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 3; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 2; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 10; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 12; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_INPUT_STATE + M6805_IRQ_LINE: info->i = cpustate->irq_state[M6805_IRQ_LINE]; break;
+
+ case CPUINFO_INT_PREVIOUSPC: /* not implemented */ break;
+
+ case CPUINFO_INT_REGISTER + M6805_A: info->i = A; break;
+ case CPUINFO_INT_PC: info->i = PC; break;
+ case CPUINFO_INT_REGISTER + M6805_PC: info->i = PC; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + M6805_S: info->i = SP_ADJUST(S); break;
+ case CPUINFO_INT_REGISTER + M6805_X: info->i = X; break;
+ case CPUINFO_INT_REGISTER + M6805_CC: info->i = CC; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(m6805); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(m6805); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(m6805); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(m6805); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(m6805); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(m6805);break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->iCount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "M6805"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Motorola 6805"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "The MAME team."); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c%c%c%c%c%c%c",
+ cpustate->cc & 0x80 ? '?':'.',
+ cpustate->cc & 0x40 ? '?':'.',
+ cpustate->cc & 0x20 ? '?':'.',
+ cpustate->cc & 0x10 ? 'H':'.',
+ cpustate->cc & 0x08 ? 'I':'.',
+ cpustate->cc & 0x04 ? 'N':'.',
+ cpustate->cc & 0x02 ? 'Z':'.',
+ cpustate->cc & 0x01 ? 'C':'.');
+ break;
+
+ case CPUINFO_STR_REGISTER + M6805_A: sprintf(info->s, "A:%02X", cpustate->a); break;
+ case CPUINFO_STR_REGISTER + M6805_PC: sprintf(info->s, "PC:%04X", cpustate->pc.w.l); break;
+ case CPUINFO_STR_REGISTER + M6805_S: sprintf(info->s, "S:%02X", cpustate->s.w.l); break;
+ case CPUINFO_STR_REGISTER + M6805_X: sprintf(info->s, "X:%02X", cpustate->x); break;
+ case CPUINFO_STR_REGISTER + M6805_CC: sprintf(info->s, "CC:%02X", cpustate->cc); break;
+ }
+}
+
+/**************************************************************************
+ * CPU-specific set_info for 68HC05EG
+ **************************************************************************/
+static CPU_SET_INFO( m68hc05eg )
+{
+ m6805_Regs *cpustate = get_safe_token(device);
+
+ switch(state)
+ {
+ case CPUINFO_INT_INPUT_STATE + M68HC05EG_INT_IRQ: m68hc05eg_set_irq_line(cpustate, M68HC05EG_INT_IRQ, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + M68HC05EG_INT_TIMER: m68hc05eg_set_irq_line(cpustate, M68HC05EG_INT_TIMER, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + M68HC05EG_INT_CPI: m68hc05eg_set_irq_line(cpustate, M68HC05EG_INT_CPI, info->i); break;
+
+ default: CPU_SET_INFO_CALL(m6805); break;
+ }
+}
+
+CPU_GET_INFO( m68hc05eg )
+{
+ m6805_Regs *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + M68HC05EG_INT_IRQ: info->i = cpustate->irq_state[M68HC05EG_INT_IRQ]; break;
+ case CPUINFO_INT_INPUT_STATE + M68HC05EG_INT_TIMER: info->i = cpustate->irq_state[M68HC05EG_INT_TIMER]; break;
+ case CPUINFO_INT_INPUT_STATE + M68HC05EG_INT_CPI: info->i = cpustate->irq_state[M68HC05EG_INT_CPI]; break;
+
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 13; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(m68hc05eg); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(m68hc05eg); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(m68hc05eg); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "M68HC05EG"); break;
+
+ default: CPU_GET_INFO_CALL(m6805); break;
+ }
+}
+
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+static CPU_SET_INFO( m68705 )
+{
+ m6805_Regs *cpustate = get_safe_token(device);
+
+ switch(state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + M68705_INT_TIMER: m68705_set_irq_line(cpustate, M68705_INT_TIMER, info->i); break;
+
+ default: CPU_SET_INFO_CALL(m6805); break;
+ }
+}
+
+CPU_GET_INFO( m68705 )
+{
+ m6805_Regs *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + M68705_INT_TIMER: info->i = cpustate->irq_state[M68705_INT_TIMER]; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(m68705); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(m68705); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(m68705); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "M68705"); break;
+
+ default: CPU_GET_INFO_CALL(m6805); break;
+ }
+}
+
+
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( hd63705 )
+{
+ m6805_Regs *cpustate = get_safe_token(device);
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + HD63705_INT_IRQ1: hd63705_set_irq_line(cpustate, HD63705_INT_IRQ1, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + HD63705_INT_IRQ2: hd63705_set_irq_line(cpustate, HD63705_INT_IRQ2, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + HD63705_INT_TIMER1: hd63705_set_irq_line(cpustate, HD63705_INT_TIMER1, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + HD63705_INT_TIMER2: hd63705_set_irq_line(cpustate, HD63705_INT_TIMER2, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + HD63705_INT_TIMER3: hd63705_set_irq_line(cpustate, HD63705_INT_TIMER3, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + HD63705_INT_PCI: hd63705_set_irq_line(cpustate, HD63705_INT_PCI, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + HD63705_INT_SCI: hd63705_set_irq_line(cpustate, HD63705_INT_SCI, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + HD63705_INT_ADCONV: hd63705_set_irq_line(cpustate, HD63705_INT_ADCONV, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: hd63705_set_irq_line(cpustate, INPUT_LINE_NMI, info->i); break;
+
+ default: CPU_SET_INFO_CALL(m6805);break;
+ }
+}
+
+CPU_GET_INFO( hd63705 )
+{
+ m6805_Regs *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + HD63705_INT_IRQ1: info->i = cpustate->irq_state[HD63705_INT_IRQ1]; break;
+ case CPUINFO_INT_INPUT_STATE + HD63705_INT_IRQ2: info->i = cpustate->irq_state[HD63705_INT_IRQ2]; break;
+ case CPUINFO_INT_INPUT_STATE + HD63705_INT_TIMER1: info->i = cpustate->irq_state[HD63705_INT_TIMER1]; break;
+ case CPUINFO_INT_INPUT_STATE + HD63705_INT_TIMER2: info->i = cpustate->irq_state[HD63705_INT_TIMER2]; break;
+ case CPUINFO_INT_INPUT_STATE + HD63705_INT_TIMER3: info->i = cpustate->irq_state[HD63705_INT_TIMER3]; break;
+ case CPUINFO_INT_INPUT_STATE + HD63705_INT_PCI: info->i = cpustate->irq_state[HD63705_INT_PCI]; break;
+ case CPUINFO_INT_INPUT_STATE + HD63705_INT_SCI: info->i = cpustate->irq_state[HD63705_INT_SCI]; break;
+ case CPUINFO_INT_INPUT_STATE + HD63705_INT_ADCONV: info->i = cpustate->irq_state[HD63705_INT_ADCONV]; break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: info->i = cpustate->irq_state[HD63705_INT_NMI]; break;
+
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(hd63705); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(hd63705); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(hd63705); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "HD63705"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Keith Wilkins, Juergen Buchmueller"); break;
+
+ default: CPU_GET_INFO_CALL(m6805); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(M6805, m6805);
+DEFINE_LEGACY_CPU_DEVICE(M68HC05EG, m68hc05eg);
+DEFINE_LEGACY_CPU_DEVICE(M68705, m68705);
+DEFINE_LEGACY_CPU_DEVICE(HD63705, hd63705);
diff --git a/trunk/src/emu/cpu/m6805/m6805.h b/trunk/src/emu/cpu/m6805/m6805.h
new file mode 100644
index 00000000000..f4a195ec508
--- /dev/null
+++ b/trunk/src/emu/cpu/m6805/m6805.h
@@ -0,0 +1,70 @@
+/*** m6805: Portable 6805 emulator ******************************************/
+
+#pragma once
+
+#ifndef __M6805_H__
+#define __M6805_H__
+
+
+enum { M6805_PC=1, M6805_S, M6805_CC, M6805_A, M6805_X, M6805_IRQ_STATE };
+
+#define M6805_IRQ_LINE 0
+
+DECLARE_LEGACY_CPU_DEVICE(M6805, m6805);
+
+/****************************************************************************
+ * 68HC05EG section
+ ****************************************************************************/
+
+#define M68HC05EG_INT_IRQ (M6805_IRQ_LINE)
+#define M68HC05EG_INT_TIMER (M6805_IRQ_LINE+1)
+#define M68HC05EG_INT_CPI (M6805_IRQ_LINE+2)
+
+DECLARE_LEGACY_CPU_DEVICE(M68HC05EG, m68hc05eg);
+
+/****************************************************************************
+ * 68705 section
+ ****************************************************************************/
+#define M68705_A M6805_A
+#define M68705_PC M6805_PC
+#define M68705_S M6805_S
+#define M68705_X M6805_X
+#define M68705_CC M6805_CC
+#define M68705_IRQ_STATE M6805_IRQ_STATE
+
+#define M68705_INT_MASK 0x03
+#define M68705_IRQ_LINE M6805_IRQ_LINE
+#define M68705_INT_TIMER 0x01
+
+DECLARE_LEGACY_CPU_DEVICE(M68705, m68705);
+
+/****************************************************************************
+ * HD63705 section
+ ****************************************************************************/
+#define HD63705_A M6805_A
+#define HD63705_PC M6805_PC
+#define HD63705_S M6805_S
+#define HD63705_X M6805_X
+#define HD63705_CC M6805_CC
+#define HD63705_NMI_STATE M6805_IRQ_STATE
+#define HD63705_IRQ1_STATE M6805_IRQ_STATE+1
+#define HD63705_IRQ2_STATE M6805_IRQ_STATE+2
+#define HD63705_ADCONV_STATE M6805_IRQ_STATE+3
+
+#define HD63705_INT_MASK 0x1ff
+
+#define HD63705_INT_IRQ1 0x00
+#define HD63705_INT_IRQ2 0x01
+#define HD63705_INT_TIMER1 0x02
+#define HD63705_INT_TIMER2 0x03
+#define HD63705_INT_TIMER3 0x04
+#define HD63705_INT_PCI 0x05
+#define HD63705_INT_SCI 0x06
+#define HD63705_INT_ADCONV 0x07
+#define HD63705_INT_NMI 0x08
+
+DECLARE_LEGACY_CPU_DEVICE(HD63705, hd63705);
+
+CPU_DISASSEMBLE( m6805 );
+
+#endif /* __M6805_H__ */
diff --git a/trunk/src/emu/cpu/m6809/6809dasm.c b/trunk/src/emu/cpu/m6809/6809dasm.c
new file mode 100644
index 00000000000..cb77184a4e2
--- /dev/null
+++ b/trunk/src/emu/cpu/m6809/6809dasm.c
@@ -0,0 +1,619 @@
+/*****************************************************************************
+
+ 6809dasm.c - a 6809 opcode disassembler
+ Version 1.4 1-MAR-95
+ Copyright Sean Riddle
+
+ Thanks to Franklin Bowen for bug fixes, ideas
+
+ Freely distributable on any medium given all copyrights are retained
+ by the author and no charge greater than $7.00 is made for obtaining
+ this software
+
+ Please send all bug reports, update ideas and data files to:
+ sriddle@ionet.net
+
+*****************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "m6809.h"
+
+// Opcode structure
+typedef struct
+{
+ UINT8 opcode; // 8-bit opcode value
+ UINT8 length; // Opcode length in bytes
+ char name[6]; // Opcode name
+ UINT8 mode; // Addressing mode
+ unsigned flags; // Disassembly flags
+} opcodeinfo;
+
+enum m6809_addressing_modes
+{
+ INH, // Inherent
+ DIR, // Direct
+ IND, // Indexed
+ REL, // Relative (8 bit)
+ LREL, // Long relative (16 bit)
+ EXT, // Extended
+ IMM, // Immediate
+ IMM_RR, // Register-to-register
+ PG1, // Switch to page 1 opcodes
+ PG2 // Switch to page 2 opcodes
+};
+
+// Page 0 opcodes (single byte)
+static const opcodeinfo m6809_pg0opcodes[] =
+{
+ { 0x00, 2, "NEG", DIR },
+ { 0x03, 2, "COM", DIR },
+ { 0x04, 2, "LSR", DIR },
+ { 0x06, 2, "ROR", DIR },
+ { 0x07, 2, "ASR", DIR },
+ { 0x08, 2, "ASL", DIR },
+ { 0x09, 2, "ROL", DIR },
+ { 0x0A, 2, "DEC", DIR },
+ { 0x0C, 2, "INC", DIR },
+ { 0x0D, 2, "TST", DIR },
+ { 0x0E, 2, "JMP", DIR },
+ { 0x0F, 2, "CLR", DIR },
+
+ { 0x10, 1, "page1", PG1 },
+ { 0x11, 1, "page2", PG2 },
+ { 0x12, 1, "NOP", INH },
+ { 0x13, 1, "SYNC", INH },
+ { 0x16, 3, "LBRA", LREL },
+ { 0x17, 3, "LBSR", LREL , DASMFLAG_STEP_OVER },
+ { 0x19, 1, "DAA", INH },
+ { 0x1A, 2, "ORCC", IMM },
+ { 0x1C, 2, "ANDCC", IMM },
+ { 0x1D, 1, "SEX", INH },
+ { 0x1E, 2, "EXG", IMM_RR },
+ { 0x1F, 2, "TFR", IMM_RR },
+
+ { 0x20, 2, "BRA", REL },
+ { 0x21, 2, "BRN", REL },
+ { 0x22, 2, "BHI", REL },
+ { 0x23, 2, "BLS", REL },
+ { 0x24, 2, "BCC", REL },
+ { 0x25, 2, "BCS", REL },
+ { 0x26, 2, "BNE", REL },
+ { 0x27, 2, "BEQ", REL },
+ { 0x28, 2, "BVC", REL },
+ { 0x29, 2, "BVS", REL },
+ { 0x2A, 2, "BPL", REL },
+ { 0x2B, 2, "BMI", REL },
+ { 0x2C, 2, "BGE", REL },
+ { 0x2D, 2, "BLT", REL },
+ { 0x2E, 2, "BGT", REL },
+ { 0x2F, 2, "BLE", REL },
+
+ { 0x30, 2, "LEAX", IND },
+ { 0x31, 2, "LEAY", IND },
+ { 0x32, 2, "LEAS", IND },
+ { 0x33, 2, "LEAU", IND },
+ { 0x34, 2, "PSHS", INH },
+ { 0x35, 2, "PULS", INH },
+ { 0x36, 2, "PSHU", INH },
+ { 0x37, 2, "PULU", INH },
+ { 0x39, 1, "RTS", INH },
+ { 0x3A, 1, "ABX", INH },
+ { 0x3B, 1, "RTI", INH },
+ { 0x3C, 2, "CWAI", IMM },
+ { 0x3D, 1, "MUL", INH },
+ { 0x3F, 1, "SWI", INH },
+
+ { 0x40, 1, "NEGA", INH },
+ { 0x43, 1, "COMA", INH },
+ { 0x44, 1, "LSRA", INH },
+ { 0x46, 1, "RORA", INH },
+ { 0x47, 1, "ASRA", INH },
+ { 0x48, 1, "ASLA", INH },
+ { 0x49, 1, "ROLA", INH },
+ { 0x4A, 1, "DECA", INH },
+ { 0x4C, 1, "INCA", INH },
+ { 0x4D, 1, "TSTA", INH },
+ { 0x4F, 1, "CLRA", INH },
+
+ { 0x50, 1, "NEGB", INH },
+ { 0x53, 1, "COMB", INH },
+ { 0x54, 1, "LSRB", INH },
+ { 0x56, 1, "RORB", INH },
+ { 0x57, 1, "ASRB", INH },
+ { 0x58, 1, "ASLB", INH },
+ { 0x59, 1, "ROLB", INH },
+ { 0x5A, 1, "DECB", INH },
+ { 0x5C, 1, "INCB", INH },
+ { 0x5D, 1, "TSTB", INH },
+ { 0x5F, 1, "CLRB", INH },
+
+ { 0x60, 2, "NEG", IND },
+ { 0x63, 2, "COM", IND },
+ { 0x64, 2, "LSR", IND },
+ { 0x66, 2, "ROR", IND },
+ { 0x67, 2, "ASR", IND },
+ { 0x68, 2, "ASL", IND },
+ { 0x69, 2, "ROL", IND },
+ { 0x6A, 2, "DEC", IND },
+ { 0x6C, 2, "INC", IND },
+ { 0x6D, 2, "TST", IND },
+ { 0x6E, 2, "JMP", IND },
+ { 0x6F, 2, "CLR", IND },
+
+ { 0x70, 3, "NEG", EXT },
+ { 0x73, 3, "COM", EXT },
+ { 0x74, 3, "LSR", EXT },
+ { 0x76, 3, "ROR", EXT },
+ { 0x77, 3, "ASR", EXT },
+ { 0x78, 3, "ASL", EXT },
+ { 0x79, 3, "ROL", EXT },
+ { 0x7A, 3, "DEC", EXT },
+ { 0x7C, 3, "INC", EXT },
+ { 0x7D, 3, "TST", EXT },
+ { 0x7E, 3, "JMP", EXT },
+ { 0x7F, 3, "CLR", EXT },
+
+ { 0x80, 2, "SUBA", IMM },
+ { 0x81, 2, "CMPA", IMM },
+ { 0x82, 2, "SBCA", IMM },
+ { 0x83, 3, "SUBD", IMM },
+ { 0x84, 2, "ANDA", IMM },
+ { 0x85, 2, "BITA", IMM },
+ { 0x86, 2, "LDA", IMM },
+ { 0x88, 2, "EORA", IMM },
+ { 0x89, 2, "ADCA", IMM },
+ { 0x8A, 2, "ORA", IMM },
+ { 0x8B, 2, "ADDA", IMM },
+ { 0x8C, 3, "CMPX", IMM },
+ { 0x8D, 2, "BSR", REL , DASMFLAG_STEP_OVER },
+ { 0x8E, 3, "LDX", IMM },
+
+ { 0x90, 2, "SUBA", DIR },
+ { 0x91, 2, "CMPA", DIR },
+ { 0x92, 2, "SBCA", DIR },
+ { 0x93, 2, "SUBD", DIR },
+ { 0x94, 2, "ANDA", DIR },
+ { 0x95, 2, "BITA", DIR },
+ { 0x96, 2, "LDA", DIR },
+ { 0x97, 2, "STA", DIR },
+ { 0x98, 2, "EORA", DIR },
+ { 0x99, 2, "ADCA", DIR },
+ { 0x9A, 2, "ORA", DIR },
+ { 0x9B, 2, "ADDA", DIR },
+ { 0x9C, 2, "CMPX", DIR },
+ { 0x9D, 2, "JSR", DIR , DASMFLAG_STEP_OVER },
+ { 0x9E, 2, "LDX", DIR },
+ { 0x9F, 2, "STX", DIR },
+
+ { 0xA0, 2, "SUBA", IND },
+ { 0xA1, 2, "CMPA", IND },
+ { 0xA2, 2, "SBCA", IND },
+ { 0xA3, 2, "SUBD", IND },
+ { 0xA4, 2, "ANDA", IND },
+ { 0xA5, 2, "BITA", IND },
+ { 0xA6, 2, "LDA", IND },
+ { 0xA7, 2, "STA", IND },
+ { 0xA8, 2, "EORA", IND },
+ { 0xA9, 2, "ADCA", IND },
+ { 0xAA, 2, "ORA", IND },
+ { 0xAB, 2, "ADDA", IND },
+ { 0xAC, 2, "CMPX", IND },
+ { 0xAD, 2, "JSR", IND , DASMFLAG_STEP_OVER },
+ { 0xAE, 2, "LDX", IND },
+ { 0xAF, 2, "STX", IND },
+
+ { 0xB0, 3, "SUBA", EXT },
+ { 0xB1, 3, "CMPA", EXT },
+ { 0xB2, 3, "SBCA", EXT },
+ { 0xB3, 3, "SUBD", EXT },
+ { 0xB4, 3, "ANDA", EXT },
+ { 0xB5, 3, "BITA", EXT },
+ { 0xB6, 3, "LDA", EXT },
+ { 0xB7, 3, "STA", EXT },
+ { 0xB8, 3, "EORA", EXT },
+ { 0xB9, 3, "ADCA", EXT },
+ { 0xBA, 3, "ORA", EXT },
+ { 0xBB, 3, "ADDA", EXT },
+ { 0xBC, 3, "CMPX", EXT },
+ { 0xBD, 3, "JSR", EXT , DASMFLAG_STEP_OVER },
+ { 0xBE, 3, "LDX", EXT },
+ { 0xBF, 3, "STX", EXT },
+
+ { 0xC0, 2, "SUBB", IMM },
+ { 0xC1, 2, "CMPB", IMM },
+ { 0xC2, 2, "SBCB", IMM },
+ { 0xC3, 3, "ADDD", IMM },
+ { 0xC4, 2, "ANDB", IMM },
+ { 0xC5, 2, "BITB", IMM },
+ { 0xC6, 2, "LDB", IMM },
+ { 0xC8, 2, "EORB", IMM },
+ { 0xC9, 2, "ADCB", IMM },
+ { 0xCA, 2, "ORB", IMM },
+ { 0xCB, 2, "ADDB", IMM },
+ { 0xCC, 3, "LDD", IMM },
+ { 0xCE, 3, "LDU", IMM },
+
+ { 0xD0, 2, "SUBB", DIR },
+ { 0xD1, 2, "CMPB", DIR },
+ { 0xD2, 2, "SBCB", DIR },
+ { 0xD3, 2, "ADDD", DIR },
+ { 0xD4, 2, "ANDB", DIR },
+ { 0xD5, 2, "BITB", DIR },
+ { 0xD6, 2, "LDB", DIR },
+ { 0xD7, 2, "STB", DIR },
+ { 0xD8, 2, "EORB", DIR },
+ { 0xD9, 2, "ADCB", DIR },
+ { 0xDA, 2, "ORB", DIR },
+ { 0xDB, 2, "ADDB", DIR },
+ { 0xDC, 2, "LDD", DIR },
+ { 0xDD, 2, "STD", DIR },
+ { 0xDE, 2, "LDU", DIR },
+ { 0xDF, 2, "STU", DIR },
+
+ { 0xE0, 2, "SUBB", IND },
+ { 0xE1, 2, "CMPB", IND },
+ { 0xE2, 2, "SBCB", IND },
+ { 0xE3, 2, "ADDD", IND },
+ { 0xE4, 2, "ANDB", IND },
+ { 0xE5, 2, "BITB", IND },
+ { 0xE6, 2, "LDB", IND },
+ { 0xE7, 2, "STB", IND },
+ { 0xE8, 2, "EORB", IND },
+ { 0xE9, 2, "ADCB", IND },
+ { 0xEA, 2, "ORB", IND },
+ { 0xEB, 2, "ADDB", IND },
+ { 0xEC, 2, "LDD", IND },
+ { 0xED, 2, "STD", IND },
+ { 0xEE, 2, "LDU", IND },
+ { 0xEF, 2, "STU", IND },
+
+ { 0xF0, 3, "SUBB", EXT },
+ { 0xF1, 3, "CMPB", EXT },
+ { 0xF2, 3, "SBCB", EXT },
+ { 0xF3, 3, "ADDD", EXT },
+ { 0xF4, 3, "ANDB", EXT },
+ { 0xF5, 3, "BITB", EXT },
+ { 0xF6, 3, "LDB", EXT },
+ { 0xF7, 3, "STB", EXT },
+ { 0xF8, 3, "EORB", EXT },
+ { 0xF9, 3, "ADCB", EXT },
+ { 0xFA, 3, "ORB", EXT },
+ { 0xFB, 3, "ADDB", EXT },
+ { 0xFC, 3, "LDD", EXT },
+ { 0xFD, 3, "STD", EXT },
+ { 0xFE, 3, "LDU", EXT },
+ { 0xFF, 3, "STU", EXT }
+};
+
+// Page 1 opcodes (0x10 0x..)
+static const opcodeinfo m6809_pg1opcodes[] =
+{
+ { 0x21, 4, "LBRN", LREL },
+ { 0x22, 4, "LBHI", LREL },
+ { 0x23, 4, "LBLS", LREL },
+ { 0x24, 4, "LBCC", LREL },
+ { 0x25, 4, "LBCS", LREL },
+ { 0x26, 4, "LBNE", LREL },
+ { 0x27, 4, "LBEQ", LREL },
+ { 0x28, 4, "LBVC", LREL },
+ { 0x29, 4, "LBVS", LREL },
+ { 0x2A, 4, "LBPL", LREL },
+ { 0x2B, 4, "LBMI", LREL },
+ { 0x2C, 4, "LBGE", LREL },
+ { 0x2D, 4, "LBLT", LREL },
+ { 0x2E, 4, "LBGT", LREL },
+ { 0x2F, 4, "LBLE", LREL },
+ { 0x3F, 2, "SWI2", INH },
+ { 0x83, 4, "CMPD", IMM },
+ { 0x8C, 4, "CMPY", IMM },
+ { 0x8E, 4, "LDY", IMM },
+ { 0x93, 3, "CMPD", DIR },
+ { 0x9C, 3, "CMPY", DIR },
+ { 0x9E, 3, "LDY", DIR },
+ { 0x9F, 3, "STY", DIR },
+ { 0xA3, 3, "CMPD", IND },
+ { 0xAC, 3, "CMPY", IND },
+ { 0xAE, 3, "LDY", IND },
+ { 0xAF, 3, "STY", IND },
+ { 0xB3, 4, "CMPD", EXT },
+ { 0xBC, 4, "CMPY", EXT },
+ { 0xBE, 4, "LDY", EXT },
+ { 0xBF, 4, "STY", EXT },
+ { 0xCE, 4, "LDS", IMM },
+ { 0xDE, 3, "LDS", DIR },
+ { 0xDF, 3, "STS", DIR },
+ { 0xEE, 3, "LDS", IND },
+ { 0xEF, 3, "STS", IND },
+ { 0xFE, 4, "LDS", EXT },
+ { 0xFF, 4, "STS", EXT }
+};
+
+// Page 2 opcodes (0x11 0x..)
+static const opcodeinfo m6809_pg2opcodes[] =
+{
+ { 0x3F, 2, "SWI3", INH },
+ { 0x83, 4, "CMPU", IMM },
+ { 0x8C, 4, "CMPS", IMM },
+ { 0x93, 3, "CMPU", DIR },
+ { 0x9C, 3, "CMPS", DIR },
+ { 0xA3, 3, "CMPU", IND },
+ { 0xAC, 3, "CMPS", IND },
+ { 0xB3, 4, "CMPU", EXT },
+ { 0xBC, 4, "CMPS", EXT }
+};
+
+static const opcodeinfo *const m6809_pgpointers[3] =
+{
+ m6809_pg0opcodes, m6809_pg1opcodes, m6809_pg2opcodes
+};
+
+static const int m6809_numops[3] =
+{
+ sizeof(m6809_pg0opcodes) / sizeof(m6809_pg0opcodes[0]),
+ sizeof(m6809_pg1opcodes) / sizeof(m6809_pg1opcodes[0]),
+ sizeof(m6809_pg2opcodes) / sizeof(m6809_pg2opcodes[0])
+};
+
+static const char *const m6809_regs[5] = { "X", "Y", "U", "S", "PC" };
+
+static const char *const m6809_regs_te[16] =
+{
+ "D", "X", "Y", "U", "S", "PC", "inv", "inv",
+ "A", "B", "CC", "DP", "inv", "inv", "inv", "inv"
+};
+
+CPU_DISASSEMBLE( m6809 )
+{
+ UINT8 opcode, mode, pb, pbm, reg;
+ const UINT8 *operandarray;
+ unsigned int ea, flags;
+ int numoperands, offset, indirect;
+ const m6809_config *configdata = device ? (const m6809_config *)device->static_config() : NULL;
+ int encrypt_only_first_byte = configdata ? configdata->encrypt_only_first_byte : 0;
+
+ int i, p = 0, page = 0, opcode_found = FALSE;
+
+ do
+ {
+ if (encrypt_only_first_byte)
+ opcode = page == 0 ? oprom[p++] : opram[p++];
+ else
+ opcode = oprom[p++];
+
+ for (i = 0; i < m6809_numops[page]; i++)
+ if (m6809_pgpointers[page][i].opcode == opcode)
+ break;
+
+ if (i < m6809_numops[page])
+ opcode_found = TRUE;
+ else
+ {
+ strcpy(buffer, "Illegal Opcode");
+ return p | DASMFLAG_SUPPORTED;
+ }
+
+ if (m6809_pgpointers[page][i].mode >= PG1)
+ {
+ page = m6809_pgpointers[page][i].mode - PG1 + 1;
+ opcode_found = FALSE;
+ }
+ } while (!opcode_found);
+
+ if (page == 0)
+ numoperands = m6809_pgpointers[page][i].length - 1;
+ else
+ numoperands = m6809_pgpointers[page][i].length - 2;
+
+ operandarray = &opram[p];
+ p += numoperands;
+ pc += p;
+ mode = m6809_pgpointers[page][i].mode;
+ flags = m6809_pgpointers[page][i].flags;
+
+ buffer += sprintf(buffer, "%-6s", m6809_pgpointers[page][i].name);
+
+ switch (mode)
+ {
+ case INH:
+ switch (opcode)
+ {
+ case 0x34: // PSHS
+ case 0x36: // PSHU
+ pb = operandarray[0];
+ if (pb & 0x80)
+ buffer += sprintf(buffer, "PC");
+ if (pb & 0x40)
+ buffer += sprintf(buffer, "%s%s", (pb&0x80)?",":"", (opcode==0x34)?"U":"S");
+ if (pb & 0x20)
+ buffer += sprintf(buffer, "%sY", (pb&0xc0)?",":"");
+ if (pb & 0x10)
+ buffer += sprintf(buffer, "%sX", (pb&0xe0)?",":"");
+ if (pb & 0x08)
+ buffer += sprintf(buffer, "%sDP", (pb&0xf0)?",":"");
+ if (pb & 0x04)
+ buffer += sprintf(buffer, "%sB", (pb&0xf8)?",":"");
+ if (pb & 0x02)
+ buffer += sprintf(buffer, "%sA", (pb&0xfc)?",":"");
+ if (pb & 0x01)
+ buffer += sprintf(buffer, "%sCC", (pb&0xfe)?",":"");
+ break;
+ case 0x35: // PULS
+ case 0x37: // PULU
+ pb = operandarray[0];
+ if (pb & 0x01)
+ buffer += sprintf(buffer, "CC");
+ if (pb & 0x02)
+ buffer += sprintf(buffer, "%sA", (pb&0x01)?",":"");
+ if (pb & 0x04)
+ buffer += sprintf(buffer, "%sB", (pb&0x03)?",":"");
+ if (pb & 0x08)
+ buffer += sprintf(buffer, "%sDP", (pb&0x07)?",":"");
+ if (pb & 0x10)
+ buffer += sprintf(buffer, "%sX", (pb&0x0f)?",":"");
+ if (pb & 0x20)
+ buffer += sprintf(buffer, "%sY", (pb&0x1f)?",":"");
+ if (pb & 0x40)
+ buffer += sprintf(buffer, "%s%s", (pb&0x3f)?",":"", (opcode==0x35)?"U":"S");
+ if (pb & 0x80)
+ buffer += sprintf(buffer, "%sPC ; (PUL? PC=RTS)", (pb&0x7f)?",":"");
+ break;
+ default:
+ // No operands
+ break;
+ }
+ break;
+
+ case DIR:
+ ea = operandarray[0];
+ buffer += sprintf(buffer, "$%02X", ea);
+ break;
+
+ case REL:
+ offset = (INT8)operandarray[0];
+ buffer += sprintf(buffer, "$%04X", (pc + offset) & 0xffff);
+ break;
+
+ case LREL:
+ offset = (INT16)((operandarray[0] << 8) + operandarray[1]);
+ buffer += sprintf(buffer, "$%04X", (pc + offset) & 0xffff);
+ break;
+
+ case EXT:
+ ea = (operandarray[0] << 8) + operandarray[1];
+ buffer += sprintf(buffer, "$%04X", ea);
+ break;
+
+ case IND:
+ pb = operandarray[0];
+ reg = (pb >> 5) & 3;
+ pbm = pb & 0x8f;
+ indirect = ((pb & 0x90) == 0x90 )? TRUE : FALSE;
+
+ // open brackets if indirect
+ if (indirect && pbm != 0x80 && pbm != 0x82)
+ buffer += sprintf(buffer, "[");
+
+ switch (pbm)
+ {
+ case 0x80: // ,R+
+ if (indirect)
+ strcpy(buffer, "Illegal Postbyte");
+ else
+ buffer += sprintf(buffer, ",%s+", m6809_regs[reg]);
+ break;
+
+ case 0x81: // ,R++
+ buffer += sprintf(buffer, ",%s++", m6809_regs[reg]);
+ break;
+
+ case 0x82: // ,-R
+ if (indirect)
+ strcpy(buffer, "Illegal Postbyte");
+ else
+ buffer += sprintf(buffer, ",-%s", m6809_regs[reg]);
+ break;
+
+ case 0x83: // ,--R
+ buffer += sprintf(buffer, ",--%s", m6809_regs[reg]);
+ break;
+
+ case 0x84: // ,R
+ buffer += sprintf(buffer, ",%s", m6809_regs[reg]);
+ break;
+
+ case 0x85: // (+/- B),R
+ buffer += sprintf(buffer, "B,%s", m6809_regs[reg]);
+ break;
+
+ case 0x86: // (+/- A),R
+ buffer += sprintf(buffer, "A,%s", m6809_regs[reg]);
+ break;
+
+ case 0x87:
+ strcpy(buffer, "Illegal Postbyte");
+ break;
+
+ case 0x88: // (+/- 7 bit offset),R
+ offset = (INT8)opram[p++];
+ buffer += sprintf(buffer, "%s", (offset < 0) ? "-" : "");
+ buffer += sprintf(buffer, "$%02X,", (offset < 0) ? -offset : offset);
+ buffer += sprintf(buffer, "%s", m6809_regs[reg]);
+ break;
+
+ case 0x89: // (+/- 15 bit offset),R
+ offset = (INT16)((opram[p+0] << 8) + opram[p+1]);
+ p += 2;
+ buffer += sprintf(buffer, "%s", (offset < 0) ? "-" : "");
+ buffer += sprintf(buffer, "$%04X,", (offset < 0) ? -offset : offset);
+ buffer += sprintf(buffer, "%s", m6809_regs[reg]);
+ break;
+
+ case 0x8a:
+ strcpy(buffer, "Illegal Postbyte");
+ break;
+
+ case 0x8b: // (+/- D),R
+ buffer += sprintf(buffer, "D,%s", m6809_regs[reg]);
+ break;
+
+ case 0x8c: // (+/- 7 bit offset),PC
+ offset = (INT8)opram[p++];
+ buffer += sprintf(buffer, "%s", (offset < 0) ? "-" : "");
+ buffer += sprintf(buffer, "$%02X,PC", (offset < 0) ? -offset : offset);
+ break;
+
+ case 0x8d: // (+/- 15 bit offset),PC
+ offset = (INT16)((opram[p+0] << 8) + opram[p+1]);
+ p += 2;
+ buffer += sprintf(buffer, "%s", (offset < 0) ? "-" : "");
+ buffer += sprintf(buffer, "$%04X,PC", (offset < 0) ? -offset : offset);
+ break;
+
+ case 0x8e:
+ strcpy(buffer, "Illegal Postbyte");
+ break;
+
+ case 0x8f: // address
+ ea = (UINT16)((opram[p+0] << 8) + opram[p+1]);
+ p += 2;
+ buffer += sprintf(buffer, "$%04X", ea);
+ break;
+
+ default: // (+/- 4 bit offset),R
+ offset = pb & 0x1f;
+ if (offset > 15)
+ offset = offset - 32;
+ buffer += sprintf(buffer, "%s", (offset < 0) ? "-" : "");
+ buffer += sprintf(buffer, "$%X,", (offset < 0) ? -offset : offset);
+ buffer += sprintf(buffer, "%s", m6809_regs[reg]);
+ break;
+ }
+
+ // close brackets if indirect
+ if (indirect && pbm != 0x80 && pbm != 0x82)
+ buffer += sprintf(buffer, "]");
+ break;
+
+ case IMM:
+ if (numoperands == 2)
+ {
+ ea = (operandarray[0] << 8) + operandarray[1];
+ buffer += sprintf(buffer, "#$%04X", ea);
+ }
+ else
+ if (numoperands == 1)
+ {
+ ea = operandarray[0];
+ buffer += sprintf(buffer, "#$%02X", ea);
+ }
+ break;
+
+ case IMM_RR:
+ pb = operandarray[0];
+ buffer += sprintf(buffer, "%s,%s", m6809_regs_te[(pb >> 4) & 0xf], m6809_regs_te[pb & 0xf]);
+ break;
+ }
+
+ return p | flags | DASMFLAG_SUPPORTED;
+}
diff --git a/trunk/src/emu/cpu/m6809/6809ops.c b/trunk/src/emu/cpu/m6809/6809ops.c
new file mode 100644
index 00000000000..e9942d418ef
--- /dev/null
+++ b/trunk/src/emu/cpu/m6809/6809ops.c
@@ -0,0 +1,2977 @@
+/*
+
+HNZVC
+
+? = undefined
+* = affected
+- = unaffected
+0 = cleared
+1 = set
+# = CCr directly affected by instruction
+@ = special - carry set if bit 7 is set
+
+*/
+
+#define OP_HANDLER(_name) INLINE void _name (m68_state_t *m68_state)
+
+OP_HANDLER( illegal )
+{
+ logerror("M6809: illegal opcode at %04x\n",PC);
+}
+
+static void IIError(m68_state_t *m68_state)
+{
+ illegal(m68_state); // Vector to Trap handler
+}
+
+/* $00 NEG direct ?**** */
+OP_HANDLER( neg_di )
+{
+ UINT16 r,t;
+ DIRBYTE(t);
+ r = -t;
+ CLR_NZVC;
+ SET_FLAGS8(0,t,r);
+ WM(EAD,r);
+}
+
+/* $01 ILLEGAL, same as $00 */
+
+/* $02 ILLEGAL, same as $03 */
+
+/* $03 COM direct -**01 */
+OP_HANDLER( com_di )
+{
+ UINT8 t;
+ DIRBYTE(t);
+ t = ~t;
+ CLR_NZV;
+ SET_NZ8(t);
+ SEC;
+ WM(EAD,t);
+}
+
+/* $04 LSR direct -0*-* */
+OP_HANDLER( lsr_di )
+{
+ UINT8 t;
+ DIRBYTE(t);
+ CLR_NZC;
+ CC |= (t & CC_C);
+ t >>= 1;
+ SET_Z8(t);
+ WM(EAD,t);
+}
+
+/* $05 ILLEGAL, same as $04 */
+
+/* $06 ROR direct -**-* */
+OP_HANDLER( ror_di )
+{
+ UINT8 t,r;
+ DIRBYTE(t);
+ r= (CC & CC_C) << 7;
+ CLR_NZC;
+ CC |= (t & CC_C);
+ r |= t>>1;
+ SET_NZ8(r);
+ WM(EAD,r);
+}
+
+/* $07 ASR direct ?**-* */
+OP_HANDLER( asr_di )
+{
+ UINT8 t;
+ DIRBYTE(t);
+ CLR_NZC;
+ CC |= (t & CC_C);
+ t = (t & 0x80) | (t >> 1);
+ SET_NZ8(t);
+ WM(EAD,t);
+}
+
+/* $08 ASL direct ?**** */
+OP_HANDLER( asl_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = t << 1;
+ CLR_NZVC;
+ SET_FLAGS8(t,t,r);
+ WM(EAD,r);
+}
+
+/* $09 ROL direct -**** */
+OP_HANDLER( rol_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = (CC & CC_C) | (t << 1);
+ CLR_NZVC;
+ SET_FLAGS8(t,t,r);
+ WM(EAD,r);
+}
+
+/* $0A DEC direct -***- */
+OP_HANDLER( dec_di )
+{
+ UINT8 t;
+ DIRBYTE(t);
+ --t;
+ CLR_NZV;
+ SET_FLAGS8D(t);
+ WM(EAD,t);
+}
+
+/* $0B ILLEGAL, same as $0A */
+
+/* $OC INC direct -***- */
+OP_HANDLER( inc_di )
+{
+ UINT8 t;
+ DIRBYTE(t);
+ ++t;
+ CLR_NZV;
+ SET_FLAGS8I(t);
+ WM(EAD,t);
+}
+
+/* $OD TST direct -**0- */
+OP_HANDLER( tst_di )
+{
+ UINT8 t;
+ DIRBYTE(t);
+ CLR_NZV;
+ SET_NZ8(t);
+}
+
+/* $0E JMP direct ----- */
+OP_HANDLER( jmp_di )
+{
+ DIRECT;
+ PCD = EAD;
+}
+
+/* $0F CLR direct -0100 */
+OP_HANDLER( clr_di )
+{
+ DIRECT;
+ (void)RM(EAD);
+ WM(EAD,0);
+ CLR_NZVC;
+ SEZ;
+}
+
+/* $10 FLAG */
+
+/* $11 FLAG */
+
+/* $12 NOP inherent ----- */
+OP_HANDLER( nop )
+{
+ ;
+}
+
+/* $13 SYNC inherent ----- */
+OP_HANDLER( sync )
+{
+ /* SYNC stops processing instructions until an interrupt request happens. */
+ /* This doesn't require the corresponding interrupt to be enabled: if it */
+ /* is disabled, execution continues with the next instruction. */
+ m68_state->int_state |= M6809_SYNC; /* HJB 990227 */
+ check_irq_lines(m68_state);
+ /* if M6809_SYNC has not been cleared by check_irq_lines(m68_state),
+ * stop execution until the interrupt lines change. */
+ if( m68_state->int_state & M6809_SYNC )
+ if (m68_state->icount > 0) m68_state->icount = 0;
+}
+
+/* $14 ILLEGAL */
+
+/* $15 ILLEGAL */
+
+/* $16 LBRA relative ----- */
+OP_HANDLER( lbra )
+{
+ IMMWORD(EAP);
+ PC += EA;
+}
+
+/* $17 LBSR relative ----- */
+OP_HANDLER( lbsr )
+{
+ IMMWORD(EAP);
+ PUSHWORD(pPC);
+ PC += EA;
+}
+
+/* $18 ILLEGAL */
+
+/* $19 DAA inherent (A) -**0* */
+OP_HANDLER( daa )
+{
+ UINT8 msn, lsn;
+ UINT16 t, cf = 0;
+ msn = A & 0xf0; lsn = A & 0x0f;
+ if( lsn>0x09 || CC & CC_H) cf |= 0x06;
+ if( msn>0x80 && lsn>0x09 ) cf |= 0x60;
+ if( msn>0x90 || CC & CC_C) cf |= 0x60;
+ t = cf + A;
+ CLR_NZV; /* keep carry from previous operation */
+ SET_NZ8((UINT8)t); SET_C8(t);
+ A = t;
+}
+
+/* $1A ORCC immediate ##### */
+OP_HANDLER( orcc )
+{
+ UINT8 t;
+ IMMBYTE(t);
+ CC |= t;
+ check_irq_lines(m68_state); /* HJB 990116 */
+}
+
+/* $1B ILLEGAL */
+
+/* $1C ANDCC immediate ##### */
+OP_HANDLER( andcc )
+{
+ UINT8 t;
+ IMMBYTE(t);
+ CC &= t;
+ check_irq_lines(m68_state); /* HJB 990116 */
+}
+
+/* $1D SEX inherent -**-- */
+OP_HANDLER( sex )
+{
+ UINT16 t;
+ t = SIGNED(B);
+ D = t;
+ // CLR_NZV; Tim Lindner 20020905: verified that V flag is not affected
+ CLR_NZ;
+ SET_NZ16(t);
+}
+
+/* $1E EXG inherent ----- */
+OP_HANDLER( exg )
+{
+ UINT16 t1,t2;
+ UINT8 tb;
+
+ IMMBYTE(tb);
+ if( (tb^(tb>>4)) & 0x08 ) /* HJB 990225: mixed 8/16 bit case? */
+ {
+ /* transfer $ff to both registers */
+ t1 = t2 = 0xff;
+ }
+ else
+ {
+ switch(tb>>4) {
+ case 0: t1 = D; break;
+ case 1: t1 = X; break;
+ case 2: t1 = Y; break;
+ case 3: t1 = U; break;
+ case 4: t1 = S; break;
+ case 5: t1 = PC; break;
+ case 8: t1 = A; break;
+ case 9: t1 = B; break;
+ case 10: t1 = CC; break;
+ case 11: t1 = DP; break;
+ default: t1 = 0xff;
+ }
+ switch(tb&15) {
+ case 0: t2 = D; break;
+ case 1: t2 = X; break;
+ case 2: t2 = Y; break;
+ case 3: t2 = U; break;
+ case 4: t2 = S; break;
+ case 5: t2 = PC; break;
+ case 8: t2 = A; break;
+ case 9: t2 = B; break;
+ case 10: t2 = CC; break;
+ case 11: t2 = DP; break;
+ default: t2 = 0xff;
+ }
+ }
+ switch(tb>>4) {
+ case 0: D = t2; break;
+ case 1: X = t2; break;
+ case 2: Y = t2; break;
+ case 3: U = t2; break;
+ case 4: S = t2; break;
+ case 5: PC = t2; break;
+ case 8: A = t2; break;
+ case 9: B = t2; break;
+ case 10: CC = t2; break;
+ case 11: DP = t2; break;
+ }
+ switch(tb&15) {
+ case 0: D = t1; break;
+ case 1: X = t1; break;
+ case 2: Y = t1; break;
+ case 3: U = t1; break;
+ case 4: S = t1; break;
+ case 5: PC = t1; break;
+ case 8: A = t1; break;
+ case 9: B = t1; break;
+ case 10: CC = t1; break;
+ case 11: DP = t1; break;
+ }
+}
+
+/* $1F TFR inherent ----- */
+OP_HANDLER( tfr )
+{
+ UINT8 tb;
+ UINT16 t;
+
+ IMMBYTE(tb);
+ if( (tb^(tb>>4)) & 0x08 ) /* HJB 990225: mixed 8/16 bit case? */
+ {
+ /* transfer $ff to register */
+ t = 0xff;
+ }
+ else
+ {
+ switch(tb>>4) {
+ case 0: t = D; break;
+ case 1: t = X; break;
+ case 2: t = Y; break;
+ case 3: t = U; break;
+ case 4: t = S; break;
+ case 5: t = PC; break;
+ case 8: t = A; break;
+ case 9: t = B; break;
+ case 10: t = CC; break;
+ case 11: t = DP; break;
+ default: t = 0xff;
+ }
+ }
+ switch(tb&15) {
+ case 0: D = t; break;
+ case 1: X = t; break;
+ case 2: Y = t; break;
+ case 3: U = t; break;
+ case 4: S = t; break;
+ case 5: PC = t; break;
+ case 8: A = t; break;
+ case 9: B = t; break;
+ case 10: CC = t; break;
+ case 11: DP = t; break;
+ }
+}
+
+/* $20 BRA relative ----- */
+OP_HANDLER( bra )
+{
+ UINT8 t;
+ IMMBYTE(t);
+ PC += SIGNED(t);
+}
+
+/* $21 BRN relative ----- */
+static UINT8 m6809_brn_t; // hack around GCC 4.6 error because we need the side effects of IMMBYTE
+OP_HANDLER( brn )
+{
+ IMMBYTE(m6809_brn_t);
+}
+
+/* $1021 LBRN relative ----- */
+OP_HANDLER( lbrn )
+{
+ IMMWORD(EAP);
+}
+
+/* $22 BHI relative ----- */
+OP_HANDLER( bhi )
+{
+ BRANCH( !(CC & (CC_Z|CC_C)) );
+}
+
+/* $1022 LBHI relative ----- */
+OP_HANDLER( lbhi )
+{
+ LBRANCH( !(CC & (CC_Z|CC_C)) );
+}
+
+/* $23 BLS relative ----- */
+OP_HANDLER( bls )
+{
+ BRANCH( (CC & (CC_Z|CC_C)) );
+}
+
+/* $1023 LBLS relative ----- */
+OP_HANDLER( lbls )
+{
+ LBRANCH( (CC&(CC_Z|CC_C)) );
+}
+
+/* $24 BCC relative ----- */
+OP_HANDLER( bcc )
+{
+ BRANCH( !(CC&CC_C) );
+}
+
+/* $1024 LBCC relative ----- */
+OP_HANDLER( lbcc )
+{
+ LBRANCH( !(CC&CC_C) );
+}
+
+/* $25 BCS relative ----- */
+OP_HANDLER( bcs )
+{
+ BRANCH( (CC&CC_C) );
+}
+
+/* $1025 LBCS relative ----- */
+OP_HANDLER( lbcs )
+{
+ LBRANCH( (CC&CC_C) );
+}
+
+/* $26 BNE relative ----- */
+OP_HANDLER( bne )
+{
+ BRANCH( !(CC&CC_Z) );
+}
+
+/* $1026 LBNE relative ----- */
+OP_HANDLER( lbne )
+{
+ LBRANCH( !(CC&CC_Z) );
+}
+
+/* $27 BEQ relative ----- */
+OP_HANDLER( beq )
+{
+ BRANCH( (CC&CC_Z) );
+}
+
+/* $1027 LBEQ relative ----- */
+OP_HANDLER( lbeq )
+{
+ LBRANCH( (CC&CC_Z) );
+}
+
+/* $28 BVC relative ----- */
+OP_HANDLER( bvc )
+{
+ BRANCH( !(CC&CC_V) );
+}
+
+/* $1028 LBVC relative ----- */
+OP_HANDLER( lbvc )
+{
+ LBRANCH( !(CC&CC_V) );
+}
+
+/* $29 BVS relative ----- */
+OP_HANDLER( bvs )
+{
+ BRANCH( (CC&CC_V) );
+}
+
+/* $1029 LBVS relative ----- */
+OP_HANDLER( lbvs )
+{
+ LBRANCH( (CC&CC_V) );
+}
+
+/* $2A BPL relative ----- */
+OP_HANDLER( bpl )
+{
+ BRANCH( !(CC&CC_N) );
+}
+
+/* $102A LBPL relative ----- */
+OP_HANDLER( lbpl )
+{
+ LBRANCH( !(CC&CC_N) );
+}
+
+/* $2B BMI relative ----- */
+OP_HANDLER( bmi )
+{
+ BRANCH( (CC&CC_N) );
+}
+
+/* $102B LBMI relative ----- */
+OP_HANDLER( lbmi )
+{
+ LBRANCH( (CC&CC_N) );
+}
+
+/* $2C BGE relative ----- */
+OP_HANDLER( bge )
+{
+ BRANCH( !NXORV );
+}
+
+/* $102C LBGE relative ----- */
+OP_HANDLER( lbge )
+{
+ LBRANCH( !NXORV );
+}
+
+/* $2D BLT relative ----- */
+OP_HANDLER( blt )
+{
+ BRANCH( NXORV );
+}
+
+/* $102D LBLT relative ----- */
+OP_HANDLER( lblt )
+{
+ LBRANCH( NXORV );
+}
+
+/* $2E BGT relative ----- */
+OP_HANDLER( bgt )
+{
+ BRANCH( !(NXORV || (CC&CC_Z)) );
+}
+
+/* $102E LBGT relative ----- */
+OP_HANDLER( lbgt )
+{
+ LBRANCH( !(NXORV || (CC&CC_Z)) );
+}
+
+/* $2F BLE relative ----- */
+OP_HANDLER( ble )
+{
+ BRANCH( (NXORV || (CC&CC_Z)) );
+}
+
+/* $102F LBLE relative ----- */
+OP_HANDLER( lble )
+{
+ LBRANCH( (NXORV || (CC&CC_Z)) );
+}
+
+/* $30 LEAX indexed --*-- */
+OP_HANDLER( leax )
+{
+ fetch_effective_address(m68_state);
+ X = EA;
+ CLR_Z;
+ SET_Z(X);
+}
+
+/* $31 LEAY indexed --*-- */
+OP_HANDLER( leay )
+{
+ fetch_effective_address(m68_state);
+ Y = EA;
+ CLR_Z;
+ SET_Z(Y);
+}
+
+/* $32 LEAS indexed ----- */
+OP_HANDLER( leas )
+{
+ fetch_effective_address(m68_state);
+ S = EA;
+ m68_state->int_state |= M6809_LDS;
+}
+
+/* $33 LEAU indexed ----- */
+OP_HANDLER( leau )
+{
+ fetch_effective_address(m68_state);
+ U = EA;
+}
+
+/* $34 PSHS inherent ----- */
+OP_HANDLER( pshs )
+{
+ UINT8 t;
+ IMMBYTE(t);
+ if( t&0x80 ) { PUSHWORD(pPC); m68_state->icount -= 2; }
+ if( t&0x40 ) { PUSHWORD(pU); m68_state->icount -= 2; }
+ if( t&0x20 ) { PUSHWORD(pY); m68_state->icount -= 2; }
+ if( t&0x10 ) { PUSHWORD(pX); m68_state->icount -= 2; }
+ if( t&0x08 ) { PUSHBYTE(DP); m68_state->icount -= 1; }
+ if( t&0x04 ) { PUSHBYTE(B); m68_state->icount -= 1; }
+ if( t&0x02 ) { PUSHBYTE(A); m68_state->icount -= 1; }
+ if( t&0x01 ) { PUSHBYTE(CC); m68_state->icount -= 1; }
+}
+
+/* 35 PULS inherent ----- */
+OP_HANDLER( puls )
+{
+ UINT8 t;
+ IMMBYTE(t);
+ if( t&0x01 ) { PULLBYTE(CC); m68_state->icount -= 1; }
+ if( t&0x02 ) { PULLBYTE(A); m68_state->icount -= 1; }
+ if( t&0x04 ) { PULLBYTE(B); m68_state->icount -= 1; }
+ if( t&0x08 ) { PULLBYTE(DP); m68_state->icount -= 1; }
+ if( t&0x10 ) { PULLWORD(XD); m68_state->icount -= 2; }
+ if( t&0x20 ) { PULLWORD(YD); m68_state->icount -= 2; }
+ if( t&0x40 ) { PULLWORD(UD); m68_state->icount -= 2; }
+ if( t&0x80 ) { PULLWORD(PCD); m68_state->icount -= 2; }
+
+ /* HJB 990225: moved check after all PULLs */
+ if( t&0x01 ) { check_irq_lines(m68_state); }
+}
+
+/* $36 PSHU inherent ----- */
+OP_HANDLER( pshu )
+{
+ UINT8 t;
+ IMMBYTE(t);
+ if( t&0x80 ) { PSHUWORD(pPC); m68_state->icount -= 2; }
+ if( t&0x40 ) { PSHUWORD(pS); m68_state->icount -= 2; }
+ if( t&0x20 ) { PSHUWORD(pY); m68_state->icount -= 2; }
+ if( t&0x10 ) { PSHUWORD(pX); m68_state->icount -= 2; }
+ if( t&0x08 ) { PSHUBYTE(DP); m68_state->icount -= 1; }
+ if( t&0x04 ) { PSHUBYTE(B); m68_state->icount -= 1; }
+ if( t&0x02 ) { PSHUBYTE(A); m68_state->icount -= 1; }
+ if( t&0x01 ) { PSHUBYTE(CC); m68_state->icount -= 1; }
+}
+
+/* 37 PULU inherent ----- */
+OP_HANDLER( pulu )
+{
+ UINT8 t;
+ IMMBYTE(t);
+ if( t&0x01 ) { PULUBYTE(CC); m68_state->icount -= 1; }
+ if( t&0x02 ) { PULUBYTE(A); m68_state->icount -= 1; }
+ if( t&0x04 ) { PULUBYTE(B); m68_state->icount -= 1; }
+ if( t&0x08 ) { PULUBYTE(DP); m68_state->icount -= 1; }
+ if( t&0x10 ) { PULUWORD(XD); m68_state->icount -= 2; }
+ if( t&0x20 ) { PULUWORD(YD); m68_state->icount -= 2; }
+ if( t&0x40 ) { PULUWORD(SD); m68_state->icount -= 2; }
+ if( t&0x80 ) { PULUWORD(PCD); m68_state->icount -= 2; }
+
+ /* HJB 990225: moved check after all PULLs */
+ if( t&0x01 ) { check_irq_lines(m68_state); }
+}
+
+/* $38 ILLEGAL */
+
+/* $39 RTS inherent ----- */
+OP_HANDLER( rts )
+{
+ PULLWORD(PCD);
+}
+
+/* $3A ABX inherent ----- */
+OP_HANDLER( abx )
+{
+ X += B;
+}
+
+/* $3B RTI inherent ##### */
+OP_HANDLER( rti )
+{
+ UINT8 t;
+ PULLBYTE(CC);
+ t = CC & CC_E; /* HJB 990225: entire state saved? */
+ if(t)
+ {
+ m68_state->icount -= 9;
+ PULLBYTE(A);
+ PULLBYTE(B);
+ PULLBYTE(DP);
+ PULLWORD(XD);
+ PULLWORD(YD);
+ PULLWORD(UD);
+ }
+ PULLWORD(PCD);
+ check_irq_lines(m68_state); /* HJB 990116 */
+}
+
+/* $3C CWAI inherent ----1 */
+OP_HANDLER( cwai )
+{
+ UINT8 t;
+ IMMBYTE(t);
+ CC &= t;
+ /*
+ * CWAI stacks the entire machine state on the hardware stack,
+ * then waits for an interrupt; when the interrupt is taken
+ * later, the state is *not* saved again after CWAI.
+ */
+ CC |= CC_E; /* HJB 990225: save entire state */
+ PUSHWORD(pPC);
+ PUSHWORD(pU);
+ PUSHWORD(pY);
+ PUSHWORD(pX);
+ PUSHBYTE(DP);
+ PUSHBYTE(B);
+ PUSHBYTE(A);
+ PUSHBYTE(CC);
+ m68_state->int_state |= M6809_CWAI; /* HJB 990228 */
+ check_irq_lines(m68_state); /* HJB 990116 */
+ if( m68_state->int_state & M6809_CWAI )
+ if( m68_state->icount > 0 )
+ m68_state->icount = 0;
+}
+
+/* $3D MUL inherent --*-@ */
+OP_HANDLER( mul )
+{
+ UINT16 t;
+ t = A * B;
+ CLR_ZC; SET_Z16(t); if(t&0x80) SEC;
+ D = t;
+}
+
+/* $3E ILLEGAL */
+
+/* $3F SWI (SWI2 SWI3) absolute indirect ----- */
+OP_HANDLER( swi )
+{
+ CC |= CC_E; /* HJB 980225: save entire state */
+ PUSHWORD(pPC);
+ PUSHWORD(pU);
+ PUSHWORD(pY);
+ PUSHWORD(pX);
+ PUSHBYTE(DP);
+ PUSHBYTE(B);
+ PUSHBYTE(A);
+ PUSHBYTE(CC);
+ CC |= CC_IF | CC_II; /* inhibit FIRQ and IRQ */
+ PCD=RM16(m68_state, 0xfffa);
+}
+
+/* $103F SWI2 absolute indirect ----- */
+OP_HANDLER( swi2 )
+{
+ CC |= CC_E; /* HJB 980225: save entire state */
+ PUSHWORD(pPC);
+ PUSHWORD(pU);
+ PUSHWORD(pY);
+ PUSHWORD(pX);
+ PUSHBYTE(DP);
+ PUSHBYTE(B);
+ PUSHBYTE(A);
+ PUSHBYTE(CC);
+ PCD = RM16(m68_state, 0xfff4);
+}
+
+/* $113F SWI3 absolute indirect ----- */
+OP_HANDLER( swi3 )
+{
+ CC |= CC_E; /* HJB 980225: save entire state */
+ PUSHWORD(pPC);
+ PUSHWORD(pU);
+ PUSHWORD(pY);
+ PUSHWORD(pX);
+ PUSHBYTE(DP);
+ PUSHBYTE(B);
+ PUSHBYTE(A);
+ PUSHBYTE(CC);
+ PCD = RM16(m68_state, 0xfff2);
+}
+
+/* $40 NEGA inherent ?**** */
+OP_HANDLER( nega )
+{
+ UINT16 r;
+ r = -A;
+ CLR_NZVC;
+ SET_FLAGS8(0,A,r);
+ A = r;
+}
+
+/* $41 ILLEGAL, same as $40 */
+
+/* $42 ILLEGAL, same as $43 */
+
+/* $43 COMA inherent -**01 */
+OP_HANDLER( coma )
+{
+ A = ~A;
+ CLR_NZV;
+ SET_NZ8(A);
+ SEC;
+}
+
+/* $44 LSRA inherent -0*-* */
+OP_HANDLER( lsra )
+{
+ CLR_NZC;
+ CC |= (A & CC_C);
+ A >>= 1;
+ SET_Z8(A);
+}
+
+/* $45 ILLEGAL, same as $44 */
+
+/* $46 RORA inherent -**-* */
+OP_HANDLER( rora )
+{
+ UINT8 r;
+ r = (CC & CC_C) << 7;
+ CLR_NZC;
+ CC |= (A & CC_C);
+ r |= A >> 1;
+ SET_NZ8(r);
+ A = r;
+}
+
+/* $47 ASRA inherent ?**-* */
+OP_HANDLER( asra )
+{
+ CLR_NZC;
+ CC |= (A & CC_C);
+ A = (A & 0x80) | (A >> 1);
+ SET_NZ8(A);
+}
+
+/* $48 ASLA inherent ?**** */
+OP_HANDLER( asla )
+{
+ UINT16 r;
+ r = A << 1;
+ CLR_NZVC;
+ SET_FLAGS8(A,A,r);
+ A = r;
+}
+
+/* $49 ROLA inherent -**** */
+OP_HANDLER( rola )
+{
+ UINT16 t,r;
+ t = A;
+ r = (CC & CC_C) | (t<<1);
+ CLR_NZVC; SET_FLAGS8(t,t,r);
+ A = r;
+}
+
+/* $4A DECA inherent -***- */
+OP_HANDLER( deca )
+{
+ --A;
+ CLR_NZV;
+ SET_FLAGS8D(A);
+}
+
+/* $4B ILLEGAL, same as $4A */
+
+/* $4C INCA inherent -***- */
+OP_HANDLER( inca )
+{
+ ++A;
+ CLR_NZV;
+ SET_FLAGS8I(A);
+}
+
+/* $4D TSTA inherent -**0- */
+OP_HANDLER( tsta )
+{
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $4E ILLEGAL, same as $4F */
+
+/* $4F CLRA inherent -0100 */
+OP_HANDLER( clra )
+{
+ A = 0;
+ CLR_NZVC; SEZ;
+}
+
+/* $50 NEGB inherent ?**** */
+OP_HANDLER( negb )
+{
+ UINT16 r;
+ r = -B;
+ CLR_NZVC;
+ SET_FLAGS8(0,B,r);
+ B = r;
+}
+
+/* $51 ILLEGAL, same as $50 */
+
+/* $52 ILLEGAL, same as $53 */
+
+/* $53 COMB inherent -**01 */
+OP_HANDLER( comb )
+{
+ B = ~B;
+ CLR_NZV;
+ SET_NZ8(B);
+ SEC;
+}
+
+/* $54 LSRB inherent -0*-* */
+OP_HANDLER( lsrb )
+{
+ CLR_NZC;
+ CC |= (B & CC_C);
+ B >>= 1;
+ SET_Z8(B);
+}
+
+/* $55 ILLEGAL, same as $54 */
+
+/* $56 RORB inherent -**-* */
+OP_HANDLER( rorb )
+{
+ UINT8 r;
+ r = (CC & CC_C) << 7;
+ CLR_NZC;
+ CC |= (B & CC_C);
+ r |= B >> 1;
+ SET_NZ8(r);
+ B = r;
+}
+
+/* $57 ASRB inherent ?**-* */
+OP_HANDLER( asrb )
+{
+ CLR_NZC;
+ CC |= (B & CC_C);
+ B= (B & 0x80) | (B >> 1);
+ SET_NZ8(B);
+}
+
+/* $58 ASLB inherent ?**** */
+OP_HANDLER( aslb )
+{
+ UINT16 r;
+ r = B << 1;
+ CLR_NZVC;
+ SET_FLAGS8(B,B,r);
+ B = r;
+}
+
+/* $59 ROLB inherent -**** */
+OP_HANDLER( rolb )
+{
+ UINT16 t,r;
+ t = B;
+ r = CC & CC_C;
+ r |= t << 1;
+ CLR_NZVC;
+ SET_FLAGS8(t,t,r);
+ B = r;
+}
+
+/* $5A DECB inherent -***- */
+OP_HANDLER( decb )
+{
+ --B;
+ CLR_NZV;
+ SET_FLAGS8D(B);
+}
+
+/* $5B ILLEGAL, same as $5A */
+
+/* $5C INCB inherent -***- */
+OP_HANDLER( incb )
+{
+ ++B;
+ CLR_NZV;
+ SET_FLAGS8I(B);
+}
+
+/* $5D TSTB inherent -**0- */
+OP_HANDLER( tstb )
+{
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $5E ILLEGAL, same as $5F */
+
+/* $5F CLRB inherent -0100 */
+OP_HANDLER( clrb )
+{
+ B = 0;
+ CLR_NZVC; SEZ;
+}
+
+/* $60 NEG indexed ?**** */
+OP_HANDLER( neg_ix )
+{
+ UINT16 r,t;
+ fetch_effective_address(m68_state);
+ t = RM(EAD);
+ r=-t;
+ CLR_NZVC;
+ SET_FLAGS8(0,t,r);
+ WM(EAD,r);
+}
+
+/* $61 ILLEGAL, same as $60 */
+
+/* $62 ILLEGAL, same as $63 */
+
+/* $63 COM indexed -**01 */
+OP_HANDLER( com_ix )
+{
+ UINT8 t;
+ fetch_effective_address(m68_state);
+ t = ~RM(EAD);
+ CLR_NZV;
+ SET_NZ8(t);
+ SEC;
+ WM(EAD,t);
+}
+
+/* $64 LSR indexed -0*-* */
+OP_HANDLER( lsr_ix )
+{
+ UINT8 t;
+ fetch_effective_address(m68_state);
+ t=RM(EAD);
+ CLR_NZC;
+ CC |= (t & CC_C);
+ t>>=1; SET_Z8(t);
+ WM(EAD,t);
+}
+
+/* $65 ILLEGAL, same as $64 */
+
+/* $66 ROR indexed -**-* */
+OP_HANDLER( ror_ix )
+{
+ UINT8 t,r;
+ fetch_effective_address(m68_state);
+ t=RM(EAD);
+ r = (CC & CC_C) << 7;
+ CLR_NZC;
+ CC |= (t & CC_C);
+ r |= t>>1; SET_NZ8(r);
+ WM(EAD,r);
+}
+
+/* $67 ASR indexed ?**-* */
+OP_HANDLER( asr_ix )
+{
+ UINT8 t;
+ fetch_effective_address(m68_state);
+ t=RM(EAD);
+ CLR_NZC;
+ CC |= (t & CC_C);
+ t=(t&0x80)|(t>>1);
+ SET_NZ8(t);
+ WM(EAD,t);
+}
+
+/* $68 ASL indexed ?**** */
+OP_HANDLER( asl_ix )
+{
+ UINT16 t,r;
+ fetch_effective_address(m68_state);
+ t=RM(EAD);
+ r = t << 1;
+ CLR_NZVC;
+ SET_FLAGS8(t,t,r);
+ WM(EAD,r);
+}
+
+/* $69 ROL indexed -**** */
+OP_HANDLER( rol_ix )
+{
+ UINT16 t,r;
+ fetch_effective_address(m68_state);
+ t=RM(EAD);
+ r = CC & CC_C;
+ r |= t << 1;
+ CLR_NZVC;
+ SET_FLAGS8(t,t,r);
+ WM(EAD,r);
+}
+
+/* $6A DEC indexed -***- */
+OP_HANDLER( dec_ix )
+{
+ UINT8 t;
+ fetch_effective_address(m68_state);
+ t = RM(EAD) - 1;
+ CLR_NZV; SET_FLAGS8D(t);
+ WM(EAD,t);
+}
+
+/* $6B ILLEGAL, same as $6A */
+
+/* $6C INC indexed -***- */
+OP_HANDLER( inc_ix )
+{
+ UINT8 t;
+ fetch_effective_address(m68_state);
+ t = RM(EAD) + 1;
+ CLR_NZV; SET_FLAGS8I(t);
+ WM(EAD,t);
+}
+
+/* $6D TST indexed -**0- */
+OP_HANDLER( tst_ix )
+{
+ UINT8 t;
+ fetch_effective_address(m68_state);
+ t = RM(EAD);
+ CLR_NZV;
+ SET_NZ8(t);
+}
+
+/* $6E JMP indexed ----- */
+OP_HANDLER( jmp_ix )
+{
+ fetch_effective_address(m68_state);
+ PCD = EAD;
+}
+
+/* $6F CLR indexed -0100 */
+OP_HANDLER( clr_ix )
+{
+ fetch_effective_address(m68_state);
+ (void)RM(EAD);
+ WM(EAD,0);
+ CLR_NZVC; SEZ;
+}
+
+/* $70 NEG extended ?**** */
+OP_HANDLER( neg_ex )
+{
+ UINT16 r,t;
+ EXTBYTE(t); r=-t;
+ CLR_NZVC; SET_FLAGS8(0,t,r);
+ WM(EAD,r);
+}
+
+/* $71 ILLEGAL, same as $70 */
+
+/* $72 ILLEGAL, same as $73 */
+
+/* $73 COM extended -**01 */
+OP_HANDLER( com_ex )
+{
+ UINT8 t;
+ EXTBYTE(t); t = ~t;
+ CLR_NZV; SET_NZ8(t); SEC;
+ WM(EAD,t);
+}
+
+/* $74 LSR extended -0*-* */
+OP_HANDLER( lsr_ex )
+{
+ UINT8 t;
+ EXTBYTE(t); CLR_NZC; CC |= (t & CC_C);
+ t>>=1; SET_Z8(t);
+ WM(EAD,t);
+}
+
+/* $75 ILLEGAL, same as $74 */
+
+/* $76 ROR extended -**-* */
+OP_HANDLER( ror_ex )
+{
+ UINT8 t,r;
+ EXTBYTE(t); r=(CC & CC_C) << 7;
+ CLR_NZC; CC |= (t & CC_C);
+ r |= t>>1; SET_NZ8(r);
+ WM(EAD,r);
+}
+
+/* $77 ASR extended ?**-* */
+OP_HANDLER( asr_ex )
+{
+ UINT8 t;
+ EXTBYTE(t); CLR_NZC; CC |= (t & CC_C);
+ t=(t&0x80)|(t>>1);
+ SET_NZ8(t);
+ WM(EAD,t);
+}
+
+/* $78 ASL extended ?**** */
+OP_HANDLER( asl_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t); r=t<<1;
+ CLR_NZVC; SET_FLAGS8(t,t,r);
+ WM(EAD,r);
+}
+
+/* $79 ROL extended -**** */
+OP_HANDLER( rol_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t); r = (CC & CC_C) | (t << 1);
+ CLR_NZVC; SET_FLAGS8(t,t,r);
+ WM(EAD,r);
+}
+
+/* $7A DEC extended -***- */
+OP_HANDLER( dec_ex )
+{
+ UINT8 t;
+ EXTBYTE(t); --t;
+ CLR_NZV; SET_FLAGS8D(t);
+ WM(EAD,t);
+}
+
+/* $7B ILLEGAL, same as $7A */
+
+/* $7C INC extended -***- */
+OP_HANDLER( inc_ex )
+{
+ UINT8 t;
+ EXTBYTE(t); ++t;
+ CLR_NZV; SET_FLAGS8I(t);
+ WM(EAD,t);
+}
+
+/* $7D TST extended -**0- */
+OP_HANDLER( tst_ex )
+{
+ UINT8 t;
+ EXTBYTE(t); CLR_NZV; SET_NZ8(t);
+}
+
+/* $7E JMP extended ----- */
+OP_HANDLER( jmp_ex )
+{
+ EXTENDED;
+ PCD = EAD;
+}
+
+/* $7F CLR extended -0100 */
+OP_HANDLER( clr_ex )
+{
+ EXTENDED;
+ (void)RM(EAD);
+ WM(EAD,0);
+ CLR_NZVC; SEZ;
+}
+
+/* $80 SUBA immediate ?**** */
+OP_HANDLER( suba_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t);
+ r = A - t;
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $81 CMPA immediate ?**** */
+OP_HANDLER( cmpa_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t);
+ r = A - t;
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+}
+
+/* $82 SBCA immediate ?**** */
+OP_HANDLER( sbca_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t);
+ r = A - t - (CC & CC_C);
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $83 SUBD (CMPD CMPU) immediate -**** */
+OP_HANDLER( subd_im )
+{
+ UINT32 r,d;
+ PAIR b;
+ IMMWORD(b);
+ d = D;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ D = r;
+}
+
+/* $1083 CMPD immediate -**** */
+OP_HANDLER( cmpd_im )
+{
+ UINT32 r,d;
+ PAIR b;
+ IMMWORD(b);
+ d = D;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $1183 CMPU immediate -**** */
+OP_HANDLER( cmpu_im )
+{
+ UINT32 r, d;
+ PAIR b;
+ IMMWORD(b);
+ d = U;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $84 ANDA immediate -**0- */
+OP_HANDLER( anda_im )
+{
+ UINT8 t;
+ IMMBYTE(t);
+ A &= t;
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $85 BITA immediate -**0- */
+OP_HANDLER( bita_im )
+{
+ UINT8 t,r;
+ IMMBYTE(t);
+ r = A & t;
+ CLR_NZV;
+ SET_NZ8(r);
+}
+
+/* $86 LDA immediate -**0- */
+OP_HANDLER( lda_im )
+{
+ IMMBYTE(A);
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* is this a legal instruction? */
+/* $87 STA immediate -**0- */
+OP_HANDLER( sta_im )
+{
+ CLR_NZV;
+ SET_NZ8(A);
+ IMM8;
+ WM(EAD,A);
+}
+
+/* $88 EORA immediate -**0- */
+OP_HANDLER( eora_im )
+{
+ UINT8 t;
+ IMMBYTE(t);
+ A ^= t;
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $89 ADCA immediate ***** */
+OP_HANDLER( adca_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t);
+ r = A + t + (CC & CC_C);
+ CLR_HNZVC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $8A ORA immediate -**0- */
+OP_HANDLER( ora_im )
+{
+ UINT8 t;
+ IMMBYTE(t);
+ A |= t;
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $8B ADDA immediate ***** */
+OP_HANDLER( adda_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t);
+ r = A + t;
+ CLR_HNZVC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $8C CMPX (CMPY CMPS) immediate -**** */
+OP_HANDLER( cmpx_im )
+{
+ UINT32 r,d;
+ PAIR b;
+ IMMWORD(b);
+ d = X;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $108C CMPY immediate -**** */
+OP_HANDLER( cmpy_im )
+{
+ UINT32 r,d;
+ PAIR b;
+ IMMWORD(b);
+ d = Y;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $118C CMPS immediate -**** */
+OP_HANDLER( cmps_im )
+{
+ UINT32 r,d;
+ PAIR b;
+ IMMWORD(b);
+ d = S;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $8D BSR ----- */
+OP_HANDLER( bsr )
+{
+ UINT8 t;
+ IMMBYTE(t);
+ PUSHWORD(pPC);
+ PC += SIGNED(t);
+}
+
+/* $8E LDX (LDY) immediate -**0- */
+OP_HANDLER( ldx_im )
+{
+ IMMWORD(pX);
+ CLR_NZV;
+ SET_NZ16(X);
+}
+
+/* $108E LDY immediate -**0- */
+OP_HANDLER( ldy_im )
+{
+ IMMWORD(pY);
+ CLR_NZV;
+ SET_NZ16(Y);
+}
+
+/* is this a legal instruction? */
+/* $8F STX (STY) immediate -**0- */
+OP_HANDLER( stx_im )
+{
+ CLR_NZV;
+ SET_NZ16(X);
+ IMM16;
+ WM16(m68_state, EAD,&pX);
+}
+
+/* is this a legal instruction? */
+/* $108F STY immediate -**0- */
+OP_HANDLER( sty_im )
+{
+ CLR_NZV;
+ SET_NZ16(Y);
+ IMM16;
+ WM16(m68_state, EAD,&pY);
+}
+
+/* $90 SUBA direct ?**** */
+OP_HANDLER( suba_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = A - t;
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $91 CMPA direct ?**** */
+OP_HANDLER( cmpa_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = A - t;
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+}
+
+/* $92 SBCA direct ?**** */
+OP_HANDLER( sbca_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = A - t - (CC & CC_C);
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $93 SUBD (CMPD CMPU) direct -**** */
+OP_HANDLER( subd_di )
+{
+ UINT32 r,d;
+ PAIR b;
+ DIRWORD(b);
+ d = D;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ D = r;
+}
+
+/* $1093 CMPD direct -**** */
+OP_HANDLER( cmpd_di )
+{
+ UINT32 r,d;
+ PAIR b;
+ DIRWORD(b);
+ d = D;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $1193 CMPU direct -**** */
+OP_HANDLER( cmpu_di )
+{
+ UINT32 r,d;
+ PAIR b;
+ DIRWORD(b);
+ d = U;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(U,b.d,r);
+}
+
+/* $94 ANDA direct -**0- */
+OP_HANDLER( anda_di )
+{
+ UINT8 t;
+ DIRBYTE(t);
+ A &= t;
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $95 BITA direct -**0- */
+OP_HANDLER( bita_di )
+{
+ UINT8 t,r;
+ DIRBYTE(t);
+ r = A & t;
+ CLR_NZV;
+ SET_NZ8(r);
+}
+
+/* $96 LDA direct -**0- */
+OP_HANDLER( lda_di )
+{
+ DIRBYTE(A);
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $97 STA direct -**0- */
+OP_HANDLER( sta_di )
+{
+ CLR_NZV;
+ SET_NZ8(A);
+ DIRECT;
+ WM(EAD,A);
+}
+
+/* $98 EORA direct -**0- */
+OP_HANDLER( eora_di )
+{
+ UINT8 t;
+ DIRBYTE(t);
+ A ^= t;
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $99 ADCA direct ***** */
+OP_HANDLER( adca_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = A + t + (CC & CC_C);
+ CLR_HNZVC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $9A ORA direct -**0- */
+OP_HANDLER( ora_di )
+{
+ UINT8 t;
+ DIRBYTE(t);
+ A |= t;
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $9B ADDA direct ***** */
+OP_HANDLER( adda_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = A + t;
+ CLR_HNZVC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $9C CMPX (CMPY CMPS) direct -**** */
+OP_HANDLER( cmpx_di )
+{
+ UINT32 r,d;
+ PAIR b;
+ DIRWORD(b);
+ d = X;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $109C CMPY direct -**** */
+OP_HANDLER( cmpy_di )
+{
+ UINT32 r,d;
+ PAIR b;
+ DIRWORD(b);
+ d = Y;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $119C CMPS direct -**** */
+OP_HANDLER( cmps_di )
+{
+ UINT32 r,d;
+ PAIR b;
+ DIRWORD(b);
+ d = S;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $9D JSR direct ----- */
+OP_HANDLER( jsr_di )
+{
+ DIRECT;
+ PUSHWORD(pPC);
+ PCD = EAD;
+}
+
+/* $9E LDX (LDY) direct -**0- */
+OP_HANDLER( ldx_di )
+{
+ DIRWORD(pX);
+ CLR_NZV;
+ SET_NZ16(X);
+}
+
+/* $109E LDY direct -**0- */
+OP_HANDLER( ldy_di )
+{
+ DIRWORD(pY);
+ CLR_NZV;
+ SET_NZ16(Y);
+}
+
+/* $9F STX (STY) direct -**0- */
+OP_HANDLER( stx_di )
+{
+ CLR_NZV;
+ SET_NZ16(X);
+ DIRECT;
+ WM16(m68_state, EAD,&pX);
+}
+
+/* $109F STY direct -**0- */
+OP_HANDLER( sty_di )
+{
+ CLR_NZV;
+ SET_NZ16(Y);
+ DIRECT;
+ WM16(m68_state, EAD,&pY);
+}
+
+/* $a0 SUBA indexed ?**** */
+OP_HANDLER( suba_ix )
+{
+ UINT16 t,r;
+ fetch_effective_address(m68_state);
+ t = RM(EAD);
+ r = A - t;
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $a1 CMPA indexed ?**** */
+OP_HANDLER( cmpa_ix )
+{
+ UINT16 t,r;
+ fetch_effective_address(m68_state);
+ t = RM(EAD);
+ r = A - t;
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+}
+
+/* $a2 SBCA indexed ?**** */
+OP_HANDLER( sbca_ix )
+{
+ UINT16 t,r;
+ fetch_effective_address(m68_state);
+ t = RM(EAD);
+ r = A - t - (CC & CC_C);
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $a3 SUBD (CMPD CMPU) indexed -**** */
+OP_HANDLER( subd_ix )
+{
+ UINT32 r,d;
+ PAIR b;
+ fetch_effective_address(m68_state);
+ b.d=RM16(m68_state, EAD);
+ d = D;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ D = r;
+}
+
+/* $10a3 CMPD indexed -**** */
+OP_HANDLER( cmpd_ix )
+{
+ UINT32 r,d;
+ PAIR b;
+ fetch_effective_address(m68_state);
+ b.d=RM16(m68_state, EAD);
+ d = D;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $11a3 CMPU indexed -**** */
+OP_HANDLER( cmpu_ix )
+{
+ UINT32 r;
+ PAIR b;
+ fetch_effective_address(m68_state);
+ b.d=RM16(m68_state, EAD);
+ r = U - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(U,b.d,r);
+}
+
+/* $a4 ANDA indexed -**0- */
+OP_HANDLER( anda_ix )
+{
+ fetch_effective_address(m68_state);
+ A &= RM(EAD);
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $a5 BITA indexed -**0- */
+OP_HANDLER( bita_ix )
+{
+ UINT8 r;
+ fetch_effective_address(m68_state);
+ r = A & RM(EAD);
+ CLR_NZV;
+ SET_NZ8(r);
+}
+
+/* $a6 LDA indexed -**0- */
+OP_HANDLER( lda_ix )
+{
+ fetch_effective_address(m68_state);
+ A = RM(EAD);
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $a7 STA indexed -**0- */
+OP_HANDLER( sta_ix )
+{
+ fetch_effective_address(m68_state);
+ CLR_NZV;
+ SET_NZ8(A);
+ WM(EAD,A);
+}
+
+/* $a8 EORA indexed -**0- */
+OP_HANDLER( eora_ix )
+{
+ fetch_effective_address(m68_state);
+ A ^= RM(EAD);
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $a9 ADCA indexed ***** */
+OP_HANDLER( adca_ix )
+{
+ UINT16 t,r;
+ fetch_effective_address(m68_state);
+ t = RM(EAD);
+ r = A + t + (CC & CC_C);
+ CLR_HNZVC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $aA ORA indexed -**0- */
+OP_HANDLER( ora_ix )
+{
+ fetch_effective_address(m68_state);
+ A |= RM(EAD);
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $aB ADDA indexed ***** */
+OP_HANDLER( adda_ix )
+{
+ UINT16 t,r;
+ fetch_effective_address(m68_state);
+ t = RM(EAD);
+ r = A + t;
+ CLR_HNZVC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $aC CMPX (CMPY CMPS) indexed -**** */
+OP_HANDLER( cmpx_ix )
+{
+ UINT32 r,d;
+ PAIR b;
+ fetch_effective_address(m68_state);
+ b.d=RM16(m68_state, EAD);
+ d = X;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $10aC CMPY indexed -**** */
+OP_HANDLER( cmpy_ix )
+{
+ UINT32 r,d;
+ PAIR b;
+ fetch_effective_address(m68_state);
+ b.d=RM16(m68_state, EAD);
+ d = Y;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $11aC CMPS indexed -**** */
+OP_HANDLER( cmps_ix )
+{
+ UINT32 r,d;
+ PAIR b;
+ fetch_effective_address(m68_state);
+ b.d=RM16(m68_state, EAD);
+ d = S;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $aD JSR indexed ----- */
+OP_HANDLER( jsr_ix )
+{
+ fetch_effective_address(m68_state);
+ PUSHWORD(pPC);
+ PCD = EAD;
+}
+
+/* $aE LDX (LDY) indexed -**0- */
+OP_HANDLER( ldx_ix )
+{
+ fetch_effective_address(m68_state);
+ X=RM16(m68_state, EAD);
+ CLR_NZV;
+ SET_NZ16(X);
+}
+
+/* $10aE LDY indexed -**0- */
+OP_HANDLER( ldy_ix )
+{
+ fetch_effective_address(m68_state);
+ Y=RM16(m68_state, EAD);
+ CLR_NZV;
+ SET_NZ16(Y);
+}
+
+/* $aF STX (STY) indexed -**0- */
+OP_HANDLER( stx_ix )
+{
+ fetch_effective_address(m68_state);
+ CLR_NZV;
+ SET_NZ16(X);
+ WM16(m68_state, EAD,&pX);
+}
+
+/* $10aF STY indexed -**0- */
+OP_HANDLER( sty_ix )
+{
+ fetch_effective_address(m68_state);
+ CLR_NZV;
+ SET_NZ16(Y);
+ WM16(m68_state, EAD,&pY);
+}
+
+/* $b0 SUBA extended ?**** */
+OP_HANDLER( suba_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = A - t;
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $b1 CMPA extended ?**** */
+OP_HANDLER( cmpa_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = A - t;
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+}
+
+/* $b2 SBCA extended ?**** */
+OP_HANDLER( sbca_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = A - t - (CC & CC_C);
+ CLR_NZVC;
+ SET_FLAGS8(A,t,r);
+ A = r;
+}
+
+/* $b3 SUBD (CMPD CMPU) extended -**** */
+OP_HANDLER( subd_ex )
+{
+ UINT32 r,d;
+ PAIR b;
+ EXTWORD(b);
+ d = D;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ D = r;
+}
+
+/* $10b3 CMPD extended -**** */
+OP_HANDLER( cmpd_ex )
+{
+ UINT32 r,d;
+ PAIR b;
+ EXTWORD(b);
+ d = D;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $11b3 CMPU extended -**** */
+OP_HANDLER( cmpu_ex )
+{
+ UINT32 r,d;
+ PAIR b;
+ EXTWORD(b);
+ d = U;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $b4 ANDA extended -**0- */
+OP_HANDLER( anda_ex )
+{
+ UINT8 t;
+ EXTBYTE(t);
+ A &= t;
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $b5 BITA extended -**0- */
+OP_HANDLER( bita_ex )
+{
+ UINT8 t,r;
+ EXTBYTE(t);
+ r = A & t;
+ CLR_NZV; SET_NZ8(r);
+}
+
+/* $b6 LDA extended -**0- */
+OP_HANDLER( lda_ex )
+{
+ EXTBYTE(A);
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $b7 STA extended -**0- */
+OP_HANDLER( sta_ex )
+{
+ CLR_NZV;
+ SET_NZ8(A);
+ EXTENDED;
+ WM(EAD,A);
+}
+
+/* $b8 EORA extended -**0- */
+OP_HANDLER( eora_ex )
+{
+ UINT8 t;
+ EXTBYTE(t);
+ A ^= t;
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $b9 ADCA extended ***** */
+OP_HANDLER( adca_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = A + t + (CC & CC_C);
+ CLR_HNZVC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $bA ORA extended -**0- */
+OP_HANDLER( ora_ex )
+{
+ UINT8 t;
+ EXTBYTE(t);
+ A |= t;
+ CLR_NZV;
+ SET_NZ8(A);
+}
+
+/* $bB ADDA extended ***** */
+OP_HANDLER( adda_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = A + t;
+ CLR_HNZVC;
+ SET_FLAGS8(A,t,r);
+ SET_H(A,t,r);
+ A = r;
+}
+
+/* $bC CMPX (CMPY CMPS) extended -**** */
+OP_HANDLER( cmpx_ex )
+{
+ UINT32 r,d;
+ PAIR b;
+ EXTWORD(b);
+ d = X;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $10bC CMPY extended -**** */
+OP_HANDLER( cmpy_ex )
+{
+ UINT32 r,d;
+ PAIR b;
+ EXTWORD(b);
+ d = Y;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $11bC CMPS extended -**** */
+OP_HANDLER( cmps_ex )
+{
+ UINT32 r,d;
+ PAIR b;
+ EXTWORD(b);
+ d = S;
+ r = d - b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+}
+
+/* $bD JSR extended ----- */
+OP_HANDLER( jsr_ex )
+{
+ EXTENDED;
+ PUSHWORD(pPC);
+ PCD = EAD;
+}
+
+/* $bE LDX (LDY) extended -**0- */
+OP_HANDLER( ldx_ex )
+{
+ EXTWORD(pX);
+ CLR_NZV;
+ SET_NZ16(X);
+}
+
+/* $10bE LDY extended -**0- */
+OP_HANDLER( ldy_ex )
+{
+ EXTWORD(pY);
+ CLR_NZV;
+ SET_NZ16(Y);
+}
+
+/* $bF STX (STY) extended -**0- */
+OP_HANDLER( stx_ex )
+{
+ CLR_NZV;
+ SET_NZ16(X);
+ EXTENDED;
+ WM16(m68_state, EAD,&pX);
+}
+
+/* $10bF STY extended -**0- */
+OP_HANDLER( sty_ex )
+{
+ CLR_NZV;
+ SET_NZ16(Y);
+ EXTENDED;
+ WM16(m68_state, EAD,&pY);
+}
+
+/* $c0 SUBB immediate ?**** */
+OP_HANDLER( subb_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t);
+ r = B - t;
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+ B = r;
+}
+
+/* $c1 CMPB immediate ?**** */
+OP_HANDLER( cmpb_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t);
+ r = B - t;
+ CLR_NZVC; SET_FLAGS8(B,t,r);
+}
+
+/* $c2 SBCB immediate ?**** */
+OP_HANDLER( sbcb_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t);
+ r = B - t - (CC & CC_C);
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+ B = r;
+}
+
+/* $c3 ADDD immediate -**** */
+OP_HANDLER( addd_im )
+{
+ UINT32 r,d;
+ PAIR b;
+ IMMWORD(b);
+ d = D;
+ r = d + b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ D = r;
+}
+
+/* $c4 ANDB immediate -**0- */
+OP_HANDLER( andb_im )
+{
+ UINT8 t;
+ IMMBYTE(t);
+ B &= t;
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $c5 BITB immediate -**0- */
+OP_HANDLER( bitb_im )
+{
+ UINT8 t,r;
+ IMMBYTE(t);
+ r = B & t;
+ CLR_NZV;
+ SET_NZ8(r);
+}
+
+/* $c6 LDB immediate -**0- */
+OP_HANDLER( ldb_im )
+{
+ IMMBYTE(B);
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* is this a legal instruction? */
+/* $c7 STB immediate -**0- */
+OP_HANDLER( stb_im )
+{
+ CLR_NZV;
+ SET_NZ8(B);
+ IMM8;
+ WM(EAD,B);
+}
+
+/* $c8 EORB immediate -**0- */
+OP_HANDLER( eorb_im )
+{
+ UINT8 t;
+ IMMBYTE(t);
+ B ^= t;
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $c9 ADCB immediate ***** */
+OP_HANDLER( adcb_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t);
+ r = B + t + (CC & CC_C);
+ CLR_HNZVC;
+ SET_FLAGS8(B,t,r);
+ SET_H(B,t,r);
+ B = r;
+}
+
+/* $cA ORB immediate -**0- */
+OP_HANDLER( orb_im )
+{
+ UINT8 t;
+ IMMBYTE(t);
+ B |= t;
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $cB ADDB immediate ***** */
+OP_HANDLER( addb_im )
+{
+ UINT16 t,r;
+ IMMBYTE(t);
+ r = B + t;
+ CLR_HNZVC;
+ SET_FLAGS8(B,t,r);
+ SET_H(B,t,r);
+ B = r;
+}
+
+/* $cC LDD immediate -**0- */
+OP_HANDLER( ldd_im )
+{
+ IMMWORD(pD);
+ CLR_NZV;
+ SET_NZ16(D);
+}
+
+/* is this a legal instruction? */
+/* $cD STD immediate -**0- */
+OP_HANDLER( std_im )
+{
+ CLR_NZV;
+ SET_NZ16(D);
+ IMM16;
+ WM16(m68_state, EAD,&pD);
+}
+
+/* $cE LDU (LDS) immediate -**0- */
+OP_HANDLER( ldu_im )
+{
+ IMMWORD(pU);
+ CLR_NZV;
+ SET_NZ16(U);
+}
+
+/* $10cE LDS immediate -**0- */
+OP_HANDLER( lds_im )
+{
+ IMMWORD(pS);
+ CLR_NZV;
+ SET_NZ16(S);
+ m68_state->int_state |= M6809_LDS;
+}
+
+/* is this a legal instruction? */
+/* $cF STU (STS) immediate -**0- */
+OP_HANDLER( stu_im )
+{
+ CLR_NZV;
+ SET_NZ16(U);
+ IMM16;
+ WM16(m68_state, EAD,&pU);
+}
+
+/* is this a legal instruction? */
+/* $10cF STS immediate -**0- */
+OP_HANDLER( sts_im )
+{
+ CLR_NZV;
+ SET_NZ16(S);
+ IMM16;
+ WM16(m68_state, EAD,&pS);
+}
+
+/* $d0 SUBB direct ?**** */
+OP_HANDLER( subb_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = B - t;
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+ B = r;
+}
+
+/* $d1 CMPB direct ?**** */
+OP_HANDLER( cmpb_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = B - t;
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+}
+
+/* $d2 SBCB direct ?**** */
+OP_HANDLER( sbcb_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = B - t - (CC & CC_C);
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+ B = r;
+}
+
+/* $d3 ADDD direct -**** */
+OP_HANDLER( addd_di )
+{
+ UINT32 r,d;
+ PAIR b;
+ DIRWORD(b);
+ d = D;
+ r = d + b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ D = r;
+}
+
+/* $d4 ANDB direct -**0- */
+OP_HANDLER( andb_di )
+{
+ UINT8 t;
+ DIRBYTE(t);
+ B &= t;
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $d5 BITB direct -**0- */
+OP_HANDLER( bitb_di )
+{
+ UINT8 t,r;
+ DIRBYTE(t);
+ r = B & t;
+ CLR_NZV;
+ SET_NZ8(r);
+}
+
+/* $d6 LDB direct -**0- */
+OP_HANDLER( ldb_di )
+{
+ DIRBYTE(B);
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $d7 STB direct -**0- */
+OP_HANDLER( stb_di )
+{
+ CLR_NZV;
+ SET_NZ8(B);
+ DIRECT;
+ WM(EAD,B);
+}
+
+/* $d8 EORB direct -**0- */
+OP_HANDLER( eorb_di )
+{
+ UINT8 t;
+ DIRBYTE(t);
+ B ^= t;
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $d9 ADCB direct ***** */
+OP_HANDLER( adcb_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = B + t + (CC & CC_C);
+ CLR_HNZVC;
+ SET_FLAGS8(B,t,r);
+ SET_H(B,t,r);
+ B = r;
+}
+
+/* $dA ORB direct -**0- */
+OP_HANDLER( orb_di )
+{
+ UINT8 t;
+ DIRBYTE(t);
+ B |= t;
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $dB ADDB direct ***** */
+OP_HANDLER( addb_di )
+{
+ UINT16 t,r;
+ DIRBYTE(t);
+ r = B + t;
+ CLR_HNZVC;
+ SET_FLAGS8(B,t,r);
+ SET_H(B,t,r);
+ B = r;
+}
+
+/* $dC LDD direct -**0- */
+OP_HANDLER( ldd_di )
+{
+ DIRWORD(pD);
+ CLR_NZV;
+ SET_NZ16(D);
+}
+
+/* $dD STD direct -**0- */
+OP_HANDLER( std_di )
+{
+ CLR_NZV;
+ SET_NZ16(D);
+ DIRECT;
+ WM16(m68_state, EAD,&pD);
+}
+
+/* $dE LDU (LDS) direct -**0- */
+OP_HANDLER( ldu_di )
+{
+ DIRWORD(pU);
+ CLR_NZV;
+ SET_NZ16(U);
+}
+
+/* $10dE LDS direct -**0- */
+OP_HANDLER( lds_di )
+{
+ DIRWORD(pS);
+ CLR_NZV;
+ SET_NZ16(S);
+ m68_state->int_state |= M6809_LDS;
+}
+
+/* $dF STU (STS) direct -**0- */
+OP_HANDLER( stu_di )
+{
+ CLR_NZV;
+ SET_NZ16(U);
+ DIRECT;
+ WM16(m68_state, EAD,&pU);
+}
+
+/* $10dF STS direct -**0- */
+OP_HANDLER( sts_di )
+{
+ CLR_NZV;
+ SET_NZ16(S);
+ DIRECT;
+ WM16(m68_state, EAD,&pS);
+}
+
+/* $e0 SUBB indexed ?**** */
+OP_HANDLER( subb_ix )
+{
+ UINT16 t,r;
+ fetch_effective_address(m68_state);
+ t = RM(EAD);
+ r = B - t;
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+ B = r;
+}
+
+/* $e1 CMPB indexed ?**** */
+OP_HANDLER( cmpb_ix )
+{
+ UINT16 t,r;
+ fetch_effective_address(m68_state);
+ t = RM(EAD);
+ r = B - t;
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+}
+
+/* $e2 SBCB indexed ?**** */
+OP_HANDLER( sbcb_ix )
+{
+ UINT16 t,r;
+ fetch_effective_address(m68_state);
+ t = RM(EAD);
+ r = B - t - (CC & CC_C);
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+ B = r;
+}
+
+/* $e3 ADDD indexed -**** */
+OP_HANDLER( addd_ix )
+{
+ UINT32 r,d;
+ PAIR b;
+ fetch_effective_address(m68_state);
+ b.d=RM16(m68_state, EAD);
+ d = D;
+ r = d + b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ D = r;
+}
+
+/* $e4 ANDB indexed -**0- */
+OP_HANDLER( andb_ix )
+{
+ fetch_effective_address(m68_state);
+ B &= RM(EAD);
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $e5 BITB indexed -**0- */
+OP_HANDLER( bitb_ix )
+{
+ UINT8 r;
+ fetch_effective_address(m68_state);
+ r = B & RM(EAD);
+ CLR_NZV;
+ SET_NZ8(r);
+}
+
+/* $e6 LDB indexed -**0- */
+OP_HANDLER( ldb_ix )
+{
+ fetch_effective_address(m68_state);
+ B = RM(EAD);
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $e7 STB indexed -**0- */
+OP_HANDLER( stb_ix )
+{
+ fetch_effective_address(m68_state);
+ CLR_NZV;
+ SET_NZ8(B);
+ WM(EAD,B);
+}
+
+/* $e8 EORB indexed -**0- */
+OP_HANDLER( eorb_ix )
+{
+ fetch_effective_address(m68_state);
+ B ^= RM(EAD);
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $e9 ADCB indexed ***** */
+OP_HANDLER( adcb_ix )
+{
+ UINT16 t,r;
+ fetch_effective_address(m68_state);
+ t = RM(EAD);
+ r = B + t + (CC & CC_C);
+ CLR_HNZVC;
+ SET_FLAGS8(B,t,r);
+ SET_H(B,t,r);
+ B = r;
+}
+
+/* $eA ORB indexed -**0- */
+OP_HANDLER( orb_ix )
+{
+ fetch_effective_address(m68_state);
+ B |= RM(EAD);
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $eB ADDB indexed ***** */
+OP_HANDLER( addb_ix )
+{
+ UINT16 t,r;
+ fetch_effective_address(m68_state);
+ t = RM(EAD);
+ r = B + t;
+ CLR_HNZVC;
+ SET_FLAGS8(B,t,r);
+ SET_H(B,t,r);
+ B = r;
+}
+
+/* $eC LDD indexed -**0- */
+OP_HANDLER( ldd_ix )
+{
+ fetch_effective_address(m68_state);
+ D=RM16(m68_state, EAD);
+ CLR_NZV; SET_NZ16(D);
+}
+
+/* $eD STD indexed -**0- */
+OP_HANDLER( std_ix )
+{
+ fetch_effective_address(m68_state);
+ CLR_NZV;
+ SET_NZ16(D);
+ WM16(m68_state, EAD,&pD);
+}
+
+/* $eE LDU (LDS) indexed -**0- */
+OP_HANDLER( ldu_ix )
+{
+ fetch_effective_address(m68_state);
+ U=RM16(m68_state, EAD);
+ CLR_NZV;
+ SET_NZ16(U);
+}
+
+/* $10eE LDS indexed -**0- */
+OP_HANDLER( lds_ix )
+{
+ fetch_effective_address(m68_state);
+ S=RM16(m68_state, EAD);
+ CLR_NZV;
+ SET_NZ16(S);
+ m68_state->int_state |= M6809_LDS;
+}
+
+/* $eF STU (STS) indexed -**0- */
+OP_HANDLER( stu_ix )
+{
+ fetch_effective_address(m68_state);
+ CLR_NZV;
+ SET_NZ16(U);
+ WM16(m68_state, EAD,&pU);
+}
+
+/* $10eF STS indexed -**0- */
+OP_HANDLER( sts_ix )
+{
+ fetch_effective_address(m68_state);
+ CLR_NZV;
+ SET_NZ16(S);
+ WM16(m68_state, EAD,&pS);
+}
+
+/* $f0 SUBB extended ?**** */
+OP_HANDLER( subb_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = B - t;
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+ B = r;
+}
+
+/* $f1 CMPB extended ?**** */
+OP_HANDLER( cmpb_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = B - t;
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+}
+
+/* $f2 SBCB extended ?**** */
+OP_HANDLER( sbcb_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = B - t - (CC & CC_C);
+ CLR_NZVC;
+ SET_FLAGS8(B,t,r);
+ B = r;
+}
+
+/* $f3 ADDD extended -**** */
+OP_HANDLER( addd_ex )
+{
+ UINT32 r,d;
+ PAIR b;
+ EXTWORD(b);
+ d = D;
+ r = d + b.d;
+ CLR_NZVC;
+ SET_FLAGS16(d,b.d,r);
+ D = r;
+}
+
+/* $f4 ANDB extended -**0- */
+OP_HANDLER( andb_ex )
+{
+ UINT8 t;
+ EXTBYTE(t);
+ B &= t;
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $f5 BITB extended -**0- */
+OP_HANDLER( bitb_ex )
+{
+ UINT8 t,r;
+ EXTBYTE(t);
+ r = B & t;
+ CLR_NZV;
+ SET_NZ8(r);
+}
+
+/* $f6 LDB extended -**0- */
+OP_HANDLER( ldb_ex )
+{
+ EXTBYTE(B);
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $f7 STB extended -**0- */
+OP_HANDLER( stb_ex )
+{
+ CLR_NZV;
+ SET_NZ8(B);
+ EXTENDED;
+ WM(EAD,B);
+}
+
+/* $f8 EORB extended -**0- */
+OP_HANDLER( eorb_ex )
+{
+ UINT8 t;
+ EXTBYTE(t);
+ B ^= t;
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $f9 ADCB extended ***** */
+OP_HANDLER( adcb_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = B + t + (CC & CC_C);
+ CLR_HNZVC;
+ SET_FLAGS8(B,t,r);
+ SET_H(B,t,r);
+ B = r;
+}
+
+/* $fA ORB extended -**0- */
+OP_HANDLER( orb_ex )
+{
+ UINT8 t;
+ EXTBYTE(t);
+ B |= t;
+ CLR_NZV;
+ SET_NZ8(B);
+}
+
+/* $fB ADDB extended ***** */
+OP_HANDLER( addb_ex )
+{
+ UINT16 t,r;
+ EXTBYTE(t);
+ r = B + t;
+ CLR_HNZVC;
+ SET_FLAGS8(B,t,r);
+ SET_H(B,t,r);
+ B = r;
+}
+
+/* $fC LDD extended -**0- */
+OP_HANDLER( ldd_ex )
+{
+ EXTWORD(pD);
+ CLR_NZV;
+ SET_NZ16(D);
+}
+
+/* $fD STD extended -**0- */
+OP_HANDLER( std_ex )
+{
+ CLR_NZV;
+ SET_NZ16(D);
+ EXTENDED;
+ WM16(m68_state, EAD,&pD);
+}
+
+/* $fE LDU (LDS) extended -**0- */
+OP_HANDLER( ldu_ex )
+{
+ EXTWORD(pU);
+ CLR_NZV;
+ SET_NZ16(U);
+}
+
+/* $10fE LDS extended -**0- */
+OP_HANDLER( lds_ex )
+{
+ EXTWORD(pS);
+ CLR_NZV;
+ SET_NZ16(S);
+ m68_state->int_state |= M6809_LDS;
+}
+
+/* $fF STU (STS) extended -**0- */
+OP_HANDLER( stu_ex )
+{
+ CLR_NZV;
+ SET_NZ16(U);
+ EXTENDED;
+ WM16(m68_state, EAD,&pU);
+}
+
+/* $10fF STS extended -**0- */
+OP_HANDLER( sts_ex )
+{
+ CLR_NZV;
+ SET_NZ16(S);
+ EXTENDED;
+ WM16(m68_state, EAD,&pS);
+}
+
+/* $10xx opcodes */
+OP_HANDLER( pref10 )
+{
+ UINT8 ireg2 = m68_state->config->encrypt_only_first_byte ? ROP_ARG(PCD) : ROP(PCD);
+ PC++;
+ switch( ireg2 )
+ {
+ case 0x21: lbrn(m68_state); m68_state->icount-=5; break;
+ case 0x22: lbhi(m68_state); m68_state->icount-=5; break;
+ case 0x23: lbls(m68_state); m68_state->icount-=5; break;
+ case 0x24: lbcc(m68_state); m68_state->icount-=5; break;
+ case 0x25: lbcs(m68_state); m68_state->icount-=5; break;
+ case 0x26: lbne(m68_state); m68_state->icount-=5; break;
+ case 0x27: lbeq(m68_state); m68_state->icount-=5; break;
+ case 0x28: lbvc(m68_state); m68_state->icount-=5; break;
+ case 0x29: lbvs(m68_state); m68_state->icount-=5; break;
+ case 0x2a: lbpl(m68_state); m68_state->icount-=5; break;
+ case 0x2b: lbmi(m68_state); m68_state->icount-=5; break;
+ case 0x2c: lbge(m68_state); m68_state->icount-=5; break;
+ case 0x2d: lblt(m68_state); m68_state->icount-=5; break;
+ case 0x2e: lbgt(m68_state); m68_state->icount-=5; break;
+ case 0x2f: lble(m68_state); m68_state->icount-=5; break;
+
+ case 0x3f: swi2(m68_state); m68_state->icount-=20; break;
+
+ case 0x83: cmpd_im(m68_state); m68_state->icount-=5; break;
+ case 0x8c: cmpy_im(m68_state); m68_state->icount-=5; break;
+ case 0x8e: ldy_im(m68_state); m68_state->icount-=4; break;
+ case 0x8f: sty_im(m68_state); m68_state->icount-=4; break;
+
+ case 0x93: cmpd_di(m68_state); m68_state->icount-=7; break;
+ case 0x9c: cmpy_di(m68_state); m68_state->icount-=7; break;
+ case 0x9e: ldy_di(m68_state); m68_state->icount-=6; break;
+ case 0x9f: sty_di(m68_state); m68_state->icount-=6; break;
+
+ case 0xa3: cmpd_ix(m68_state); m68_state->icount-=7; break;
+ case 0xac: cmpy_ix(m68_state); m68_state->icount-=7; break;
+ case 0xae: ldy_ix(m68_state); m68_state->icount-=6; break;
+ case 0xaf: sty_ix(m68_state); m68_state->icount-=6; break;
+
+ case 0xb3: cmpd_ex(m68_state); m68_state->icount-=8; break;
+ case 0xbc: cmpy_ex(m68_state); m68_state->icount-=8; break;
+ case 0xbe: ldy_ex(m68_state); m68_state->icount-=7; break;
+ case 0xbf: sty_ex(m68_state); m68_state->icount-=7; break;
+
+ case 0xce: lds_im(m68_state); m68_state->icount-=4; break;
+ case 0xcf: sts_im(m68_state); m68_state->icount-=4; break;
+
+ case 0xde: lds_di(m68_state); m68_state->icount-=6; break;
+ case 0xdf: sts_di(m68_state); m68_state->icount-=6; break;
+
+ case 0xee: lds_ix(m68_state); m68_state->icount-=6; break;
+ case 0xef: sts_ix(m68_state); m68_state->icount-=6; break;
+
+ case 0xfe: lds_ex(m68_state); m68_state->icount-=7; break;
+ case 0xff: sts_ex(m68_state); m68_state->icount-=7; break;
+
+ default: IIError(m68_state); break;
+ }
+}
+
+/* $11xx opcodes */
+OP_HANDLER( pref11 )
+{
+ UINT8 ireg2 = m68_state->config->encrypt_only_first_byte ? ROP_ARG(PCD) : ROP(PCD);
+ PC++;
+ switch( ireg2 )
+ {
+ case 0x3f: swi3(m68_state); m68_state->icount-=20; break;
+
+ case 0x83: cmpu_im(m68_state); m68_state->icount-=5; break;
+ case 0x8c: cmps_im(m68_state); m68_state->icount-=5; break;
+
+ case 0x93: cmpu_di(m68_state); m68_state->icount-=7; break;
+ case 0x9c: cmps_di(m68_state); m68_state->icount-=7; break;
+
+ case 0xa3: cmpu_ix(m68_state); m68_state->icount-=7; break;
+ case 0xac: cmps_ix(m68_state); m68_state->icount-=7; break;
+
+ case 0xb3: cmpu_ex(m68_state); m68_state->icount-=8; break;
+ case 0xbc: cmps_ex(m68_state); m68_state->icount-=8; break;
+
+ default: IIError(m68_state); break;
+ }
+}
+
diff --git a/trunk/src/emu/cpu/m6809/6809tbl.c b/trunk/src/emu/cpu/m6809/6809tbl.c
new file mode 100644
index 00000000000..372642eb04d
--- /dev/null
+++ b/trunk/src/emu/cpu/m6809/6809tbl.c
@@ -0,0 +1,414 @@
+INLINE void abx(m68_state_t *m68_state);
+INLINE void adca_di(m68_state_t *m68_state);
+INLINE void adca_ex(m68_state_t *m68_state);
+INLINE void adca_im(m68_state_t *m68_state);
+INLINE void adca_ix(m68_state_t *m68_state);
+INLINE void adcb_di(m68_state_t *m68_state);
+INLINE void adcb_ex(m68_state_t *m68_state);
+INLINE void adcb_im(m68_state_t *m68_state);
+INLINE void adcb_ix(m68_state_t *m68_state);
+INLINE void adda_di(m68_state_t *m68_state);
+INLINE void adda_ex(m68_state_t *m68_state);
+INLINE void adda_im(m68_state_t *m68_state);
+INLINE void adda_ix(m68_state_t *m68_state);
+INLINE void addb_di(m68_state_t *m68_state);
+INLINE void addb_ex(m68_state_t *m68_state);
+INLINE void addb_im(m68_state_t *m68_state);
+INLINE void addb_ix(m68_state_t *m68_state);
+INLINE void addd_di(m68_state_t *m68_state);
+INLINE void addd_ex(m68_state_t *m68_state);
+INLINE void addd_im(m68_state_t *m68_state);
+INLINE void addd_ix(m68_state_t *m68_state);
+INLINE void anda_di(m68_state_t *m68_state);
+INLINE void anda_ex(m68_state_t *m68_state);
+INLINE void anda_im(m68_state_t *m68_state);
+INLINE void anda_ix(m68_state_t *m68_state);
+INLINE void andb_di(m68_state_t *m68_state);
+INLINE void andb_ex(m68_state_t *m68_state);
+INLINE void andb_im(m68_state_t *m68_state);
+INLINE void andb_ix(m68_state_t *m68_state);
+INLINE void andcc(m68_state_t *m68_state);
+INLINE void asla(m68_state_t *m68_state);
+INLINE void aslb(m68_state_t *m68_state);
+INLINE void asl_di(m68_state_t *m68_state);
+INLINE void asl_ex(m68_state_t *m68_state);
+INLINE void asl_ix(m68_state_t *m68_state);
+INLINE void asra(m68_state_t *m68_state);
+INLINE void asrb(m68_state_t *m68_state);
+INLINE void asr_di(m68_state_t *m68_state);
+INLINE void asr_ex(m68_state_t *m68_state);
+INLINE void asr_ix(m68_state_t *m68_state);
+INLINE void bcc(m68_state_t *m68_state);
+INLINE void bcs(m68_state_t *m68_state);
+INLINE void beq(m68_state_t *m68_state);
+INLINE void bge(m68_state_t *m68_state);
+INLINE void bgt(m68_state_t *m68_state);
+INLINE void bhi(m68_state_t *m68_state);
+INLINE void bita_di(m68_state_t *m68_state);
+INLINE void bita_ex(m68_state_t *m68_state);
+INLINE void bita_im(m68_state_t *m68_state);
+INLINE void bita_ix(m68_state_t *m68_state);
+INLINE void bitb_di(m68_state_t *m68_state);
+INLINE void bitb_ex(m68_state_t *m68_state);
+INLINE void bitb_im(m68_state_t *m68_state);
+INLINE void bitb_ix(m68_state_t *m68_state);
+INLINE void ble(m68_state_t *m68_state);
+INLINE void bls(m68_state_t *m68_state);
+INLINE void blt(m68_state_t *m68_state);
+INLINE void bmi(m68_state_t *m68_state);
+INLINE void bne(m68_state_t *m68_state);
+INLINE void bpl(m68_state_t *m68_state);
+INLINE void bra(m68_state_t *m68_state);
+INLINE void brn(m68_state_t *m68_state);
+INLINE void bsr(m68_state_t *m68_state);
+INLINE void bvc(m68_state_t *m68_state);
+INLINE void bvs(m68_state_t *m68_state);
+INLINE void clra(m68_state_t *m68_state);
+INLINE void clrb(m68_state_t *m68_state);
+INLINE void clr_di(m68_state_t *m68_state);
+INLINE void clr_ex(m68_state_t *m68_state);
+INLINE void clr_ix(m68_state_t *m68_state);
+INLINE void cmpa_di(m68_state_t *m68_state);
+INLINE void cmpa_ex(m68_state_t *m68_state);
+INLINE void cmpa_im(m68_state_t *m68_state);
+INLINE void cmpa_ix(m68_state_t *m68_state);
+INLINE void cmpb_di(m68_state_t *m68_state);
+INLINE void cmpb_ex(m68_state_t *m68_state);
+INLINE void cmpb_im(m68_state_t *m68_state);
+INLINE void cmpb_ix(m68_state_t *m68_state);
+INLINE void cmpd_di(m68_state_t *m68_state);
+INLINE void cmpd_ex(m68_state_t *m68_state);
+INLINE void cmpd_im(m68_state_t *m68_state);
+INLINE void cmpd_ix(m68_state_t *m68_state);
+INLINE void cmps_di(m68_state_t *m68_state);
+INLINE void cmps_ex(m68_state_t *m68_state);
+INLINE void cmps_im(m68_state_t *m68_state);
+INLINE void cmps_ix(m68_state_t *m68_state);
+INLINE void cmpu_di(m68_state_t *m68_state);
+INLINE void cmpu_ex(m68_state_t *m68_state);
+INLINE void cmpu_im(m68_state_t *m68_state);
+INLINE void cmpu_ix(m68_state_t *m68_state);
+INLINE void cmpx_di(m68_state_t *m68_state);
+INLINE void cmpx_ex(m68_state_t *m68_state);
+INLINE void cmpx_im(m68_state_t *m68_state);
+INLINE void cmpx_ix(m68_state_t *m68_state);
+INLINE void cmpy_di(m68_state_t *m68_state);
+INLINE void cmpy_ex(m68_state_t *m68_state);
+INLINE void cmpy_im(m68_state_t *m68_state);
+INLINE void cmpy_ix(m68_state_t *m68_state);
+INLINE void coma(m68_state_t *m68_state);
+INLINE void comb(m68_state_t *m68_state);
+INLINE void com_di(m68_state_t *m68_state);
+INLINE void com_ex(m68_state_t *m68_state);
+INLINE void com_ix(m68_state_t *m68_state);
+INLINE void cwai(m68_state_t *m68_state);
+INLINE void daa(m68_state_t *m68_state);
+INLINE void deca(m68_state_t *m68_state);
+INLINE void decb(m68_state_t *m68_state);
+INLINE void dec_di(m68_state_t *m68_state);
+INLINE void dec_ex(m68_state_t *m68_state);
+INLINE void dec_ix(m68_state_t *m68_state);
+INLINE void eora_di(m68_state_t *m68_state);
+INLINE void eora_ex(m68_state_t *m68_state);
+INLINE void eora_im(m68_state_t *m68_state);
+INLINE void eora_ix(m68_state_t *m68_state);
+INLINE void eorb_di(m68_state_t *m68_state);
+INLINE void eorb_ex(m68_state_t *m68_state);
+INLINE void eorb_im(m68_state_t *m68_state);
+INLINE void eorb_ix(m68_state_t *m68_state);
+INLINE void exg(m68_state_t *m68_state);
+INLINE void illegal(m68_state_t *m68_state);
+INLINE void inca(m68_state_t *m68_state);
+INLINE void incb(m68_state_t *m68_state);
+INLINE void inc_di(m68_state_t *m68_state);
+INLINE void inc_ex(m68_state_t *m68_state);
+INLINE void inc_ix(m68_state_t *m68_state);
+INLINE void jmp_di(m68_state_t *m68_state);
+INLINE void jmp_ex(m68_state_t *m68_state);
+INLINE void jmp_ix(m68_state_t *m68_state);
+INLINE void jsr_di(m68_state_t *m68_state);
+INLINE void jsr_ex(m68_state_t *m68_state);
+INLINE void jsr_ix(m68_state_t *m68_state);
+INLINE void lbcc(m68_state_t *m68_state);
+INLINE void lbcs(m68_state_t *m68_state);
+INLINE void lbeq(m68_state_t *m68_state);
+INLINE void lbge(m68_state_t *m68_state);
+INLINE void lbgt(m68_state_t *m68_state);
+INLINE void lbhi(m68_state_t *m68_state);
+INLINE void lble(m68_state_t *m68_state);
+INLINE void lbls(m68_state_t *m68_state);
+INLINE void lblt(m68_state_t *m68_state);
+INLINE void lbmi(m68_state_t *m68_state);
+INLINE void lbne(m68_state_t *m68_state);
+INLINE void lbpl(m68_state_t *m68_state);
+INLINE void lbra(m68_state_t *m68_state);
+INLINE void lbrn(m68_state_t *m68_state);
+INLINE void lbsr(m68_state_t *m68_state);
+INLINE void lbvc(m68_state_t *m68_state);
+INLINE void lbvs(m68_state_t *m68_state);
+INLINE void lda_di(m68_state_t *m68_state);
+INLINE void lda_ex(m68_state_t *m68_state);
+INLINE void lda_im(m68_state_t *m68_state);
+INLINE void lda_ix(m68_state_t *m68_state);
+INLINE void ldb_di(m68_state_t *m68_state);
+INLINE void ldb_ex(m68_state_t *m68_state);
+INLINE void ldb_im(m68_state_t *m68_state);
+INLINE void ldb_ix(m68_state_t *m68_state);
+INLINE void ldd_di(m68_state_t *m68_state);
+INLINE void ldd_ex(m68_state_t *m68_state);
+INLINE void ldd_im(m68_state_t *m68_state);
+INLINE void ldd_ix(m68_state_t *m68_state);
+INLINE void lds_di(m68_state_t *m68_state);
+INLINE void lds_ex(m68_state_t *m68_state);
+INLINE void lds_im(m68_state_t *m68_state);
+INLINE void lds_ix(m68_state_t *m68_state);
+INLINE void ldu_di(m68_state_t *m68_state);
+INLINE void ldu_ex(m68_state_t *m68_state);
+INLINE void ldu_im(m68_state_t *m68_state);
+INLINE void ldu_ix(m68_state_t *m68_state);
+INLINE void ldx_di(m68_state_t *m68_state);
+INLINE void ldx_ex(m68_state_t *m68_state);
+INLINE void ldx_im(m68_state_t *m68_state);
+INLINE void ldx_ix(m68_state_t *m68_state);
+INLINE void ldy_di(m68_state_t *m68_state);
+INLINE void ldy_ex(m68_state_t *m68_state);
+INLINE void ldy_im(m68_state_t *m68_state);
+INLINE void ldy_ix(m68_state_t *m68_state);
+INLINE void leas(m68_state_t *m68_state);
+INLINE void leau(m68_state_t *m68_state);
+INLINE void leax(m68_state_t *m68_state);
+INLINE void leay(m68_state_t *m68_state);
+INLINE void lsra(m68_state_t *m68_state);
+INLINE void lsrb(m68_state_t *m68_state);
+INLINE void lsr_di(m68_state_t *m68_state);
+INLINE void lsr_ex(m68_state_t *m68_state);
+INLINE void lsr_ix(m68_state_t *m68_state);
+INLINE void mul(m68_state_t *m68_state);
+INLINE void nega(m68_state_t *m68_state);
+INLINE void negb(m68_state_t *m68_state);
+INLINE void neg_di(m68_state_t *m68_state);
+INLINE void neg_ex(m68_state_t *m68_state);
+INLINE void neg_ix(m68_state_t *m68_state);
+INLINE void nop(m68_state_t *m68_state);
+INLINE void ora_di(m68_state_t *m68_state);
+INLINE void ora_ex(m68_state_t *m68_state);
+INLINE void ora_im(m68_state_t *m68_state);
+INLINE void ora_ix(m68_state_t *m68_state);
+INLINE void orb_di(m68_state_t *m68_state);
+INLINE void orb_ex(m68_state_t *m68_state);
+INLINE void orb_im(m68_state_t *m68_state);
+INLINE void orb_ix(m68_state_t *m68_state);
+INLINE void orcc(m68_state_t *m68_state);
+INLINE void pref10(m68_state_t *m68_state);
+INLINE void pref11(m68_state_t *m68_state);
+INLINE void pshs(m68_state_t *m68_state);
+INLINE void pshu(m68_state_t *m68_state);
+INLINE void puls(m68_state_t *m68_state);
+INLINE void pulu(m68_state_t *m68_state);
+INLINE void rola(m68_state_t *m68_state);
+INLINE void rolb(m68_state_t *m68_state);
+INLINE void rol_di(m68_state_t *m68_state);
+INLINE void rol_ex(m68_state_t *m68_state);
+INLINE void rol_ix(m68_state_t *m68_state);
+INLINE void rora(m68_state_t *m68_state);
+INLINE void rorb(m68_state_t *m68_state);
+INLINE void ror_di(m68_state_t *m68_state);
+INLINE void ror_ex(m68_state_t *m68_state);
+INLINE void ror_ix(m68_state_t *m68_state);
+INLINE void rti(m68_state_t *m68_state);
+INLINE void rts(m68_state_t *m68_state);
+INLINE void sbca_di(m68_state_t *m68_state);
+INLINE void sbca_ex(m68_state_t *m68_state);
+INLINE void sbca_im(m68_state_t *m68_state);
+INLINE void sbca_ix(m68_state_t *m68_state);
+INLINE void sbcb_di(m68_state_t *m68_state);
+INLINE void sbcb_ex(m68_state_t *m68_state);
+INLINE void sbcb_im(m68_state_t *m68_state);
+INLINE void sbcb_ix(m68_state_t *m68_state);
+INLINE void sex(m68_state_t *m68_state);
+INLINE void sta_di(m68_state_t *m68_state);
+INLINE void sta_ex(m68_state_t *m68_state);
+INLINE void sta_im(m68_state_t *m68_state);
+INLINE void sta_ix(m68_state_t *m68_state);
+INLINE void stb_di(m68_state_t *m68_state);
+INLINE void stb_ex(m68_state_t *m68_state);
+INLINE void stb_im(m68_state_t *m68_state);
+INLINE void stb_ix(m68_state_t *m68_state);
+INLINE void std_di(m68_state_t *m68_state);
+INLINE void std_ex(m68_state_t *m68_state);
+INLINE void std_im(m68_state_t *m68_state);
+INLINE void std_ix(m68_state_t *m68_state);
+INLINE void sts_di(m68_state_t *m68_state);
+INLINE void sts_ex(m68_state_t *m68_state);
+INLINE void sts_im(m68_state_t *m68_state);
+INLINE void sts_ix(m68_state_t *m68_state);
+INLINE void stu_di(m68_state_t *m68_state);
+INLINE void stu_ex(m68_state_t *m68_state);
+INLINE void stu_im(m68_state_t *m68_state);
+INLINE void stu_ix(m68_state_t *m68_state);
+INLINE void stx_di(m68_state_t *m68_state);
+INLINE void stx_ex(m68_state_t *m68_state);
+INLINE void stx_im(m68_state_t *m68_state);
+INLINE void stx_ix(m68_state_t *m68_state);
+INLINE void sty_di(m68_state_t *m68_state);
+INLINE void sty_ex(m68_state_t *m68_state);
+INLINE void sty_im(m68_state_t *m68_state);
+INLINE void sty_ix(m68_state_t *m68_state);
+INLINE void suba_di(m68_state_t *m68_state);
+INLINE void suba_ex(m68_state_t *m68_state);
+INLINE void suba_im(m68_state_t *m68_state);
+INLINE void suba_ix(m68_state_t *m68_state);
+INLINE void subb_di(m68_state_t *m68_state);
+INLINE void subb_ex(m68_state_t *m68_state);
+INLINE void subb_im(m68_state_t *m68_state);
+INLINE void subb_ix(m68_state_t *m68_state);
+INLINE void subd_di(m68_state_t *m68_state);
+INLINE void subd_ex(m68_state_t *m68_state);
+INLINE void subd_im(m68_state_t *m68_state);
+INLINE void subd_ix(m68_state_t *m68_state);
+INLINE void swi2(m68_state_t *m68_state);
+INLINE void swi3(m68_state_t *m68_state);
+INLINE void swi(m68_state_t *m68_state);
+INLINE void sync(m68_state_t *m68_state);
+INLINE void tfr(m68_state_t *m68_state);
+INLINE void tsta(m68_state_t *m68_state);
+INLINE void tstb(m68_state_t *m68_state);
+INLINE void tst_di(m68_state_t *m68_state);
+INLINE void tst_ex(m68_state_t *m68_state);
+INLINE void tst_ix(m68_state_t *m68_state);
+
+static const UINT8 flags8i[256]= /* increment */
+{
+CC_Z,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+CC_N|CC_V,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N
+};
+static const UINT8 flags8d[256]= /* decrement */
+{
+CC_Z,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,CC_V,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,
+CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N,CC_N
+};
+
+/* FIXME: Cycles differ slighly from hd6309 emulation */
+static const UINT8 index_cycle_em[256] = { /* Index Loopup cycle counts */
+/* 0xX0, 0xX1, 0xX2, 0xX3, 0xX4, 0xX5, 0xX6, 0xX7, 0xX8, 0xX9, 0xXA, 0xXB, 0xXC, 0xXD, 0xXE, 0xXF */
+
+/* 0x0X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+/* 0x1X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+/* 0x2X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+/* 0x3X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+/* 0x4X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+/* 0x5X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+/* 0x6X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+/* 0x7X */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+/* 0x8X */ 2, 3, 2, 3, 0, 1, 1, 0, 1, 4, 0, 4, 1, 5, 0, 5,
+/* 0x9X */ 5, 6, 5, 6, 3, 4, 4, 0, 4, 7, 0, 7, 4, 8, 0, 8,
+/* 0xAX */ 2, 3, 2, 3, 0, 1, 1, 0, 1, 4, 0, 4, 1, 5, 0, 5,
+/* 0xBX */ 5, 6, 5, 6, 3, 4, 4, 0, 4, 7, 0, 7, 4, 8, 0, 8,
+/* 0xCX */ 2, 3, 2, 3, 0, 1, 1, 0, 1, 4, 0, 4, 1, 5, 0, 3,
+/* 0xDX */ 5, 6, 5, 6, 3, 4, 4, 0, 4, 7, 0, 7, 4, 8, 0, 8,
+/* 0xEX */ 2, 3, 2, 3, 0, 1, 1, 0, 1, 4, 0, 4, 1, 5, 0, 5,
+/* 0xFX */ 4, 6, 5, 6, 3, 4, 4, 0, 4, 7, 0, 7, 4, 8, 0, 8
+};
+
+/* timings for 1-byte opcodes */
+static const UINT8 cycles1[] =
+{
+ /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
+ /*0*/ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 6,
+ /*1*/ 0, 0, 2, 4, 2, 2, 5, 9, 2, 2, 3, 2, 3, 2, 8, 6,
+ /*2*/ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ /*3*/ 4, 4, 4, 4, 5, 5, 5, 5, 2, 5, 3, 6,20,11, 2,19,
+ /*4*/ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ /*5*/ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ /*6*/ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 6,
+ /*7*/ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 4, 7,
+ /*8*/ 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 2, 4, 7, 3, 2,
+ /*9*/ 4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 4, 6, 7, 5, 5,
+ /*A*/ 4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 4, 6, 7, 5, 5,
+ /*B*/ 5, 5, 5, 7, 5, 5, 5, 5, 5, 5, 5, 5, 7, 8, 6, 6,
+ /*C*/ 2, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 3, 3,
+ /*D*/ 4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5,
+ /*E*/ 4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5,
+ /*F*/ 5, 5, 5, 7, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6
+};
+
+static void (*const m6809_main[0x100])(m68_state_t *) = {
+/* 0xX0, 0xX1, 0xX2, 0xX3, 0xX4, 0xX5, 0xX6, 0xX7,
+ 0xX8, 0xX9, 0xXA, 0xXB, 0xXC, 0xXD, 0xXE, 0xXF */
+
+/* 0x0X */ neg_di, neg_di, com_di, com_di, lsr_di, lsr_di, ror_di, asr_di,
+ asl_di, rol_di, dec_di, dec_di, inc_di, tst_di, jmp_di, clr_di,
+
+/* 0x1X */ pref10, pref11, nop, sync, illegal,illegal,lbra, lbsr,
+ illegal,daa, orcc, illegal,andcc, sex, exg, tfr,
+
+/* 0x2X */ bra, brn, bhi, bls, bcc, bcs, bne, beq,
+ bvc, bvs, bpl, bmi, bge, blt, bgt, ble,
+
+/* 0x3X */ leax, leay, leas, leau, pshs, puls, pshu, pulu,
+ illegal,rts, abx, rti, cwai, mul, illegal,swi,
+
+/* 0x4X */ nega, nega, coma, coma, lsra, lsra, rora, asra,
+ asla, rola, deca, deca, inca, tsta, clra, clra,
+
+/* 0x5X */ negb, negb, comb, comb, lsrb, lsrb, rorb, asrb,
+ aslb, rolb, decb, decb, incb, tstb, clrb, clrb,
+
+/* 0x6X */ neg_ix, neg_ix, com_ix, com_ix, lsr_ix, lsr_ix, ror_ix, asr_ix,
+ asl_ix, rol_ix, dec_ix, dec_ix, inc_ix, tst_ix, jmp_ix, clr_ix,
+
+/* 0x7X */ neg_ex, neg_ex, com_ex, com_ex, lsr_ex, lsr_ex, ror_ex, asr_ex,
+ asl_ex, rol_ex, dec_ex, dec_ex, inc_ex, tst_ex, jmp_ex, clr_ex,
+
+/* 0x8X */ suba_im,cmpa_im,sbca_im,subd_im,anda_im,bita_im,lda_im, sta_im,
+ eora_im,adca_im,ora_im, adda_im,cmpx_im,bsr, ldx_im, stx_im,
+
+/* 0x9X */ suba_di,cmpa_di,sbca_di,subd_di,anda_di,bita_di,lda_di, sta_di,
+ eora_di,adca_di,ora_di, adda_di,cmpx_di,jsr_di, ldx_di, stx_di,
+
+/* 0xAX */ suba_ix,cmpa_ix,sbca_ix,subd_ix,anda_ix,bita_ix,lda_ix, sta_ix,
+ eora_ix,adca_ix,ora_ix, adda_ix,cmpx_ix,jsr_ix, ldx_ix, stx_ix,
+
+/* 0xBX */ suba_ex,cmpa_ex,sbca_ex,subd_ex,anda_ex,bita_ex,lda_ex, sta_ex,
+ eora_ex,adca_ex,ora_ex, adda_ex,cmpx_ex,jsr_ex, ldx_ex, stx_ex,
+
+/* 0xCX */ subb_im,cmpb_im,sbcb_im,addd_im,andb_im,bitb_im,ldb_im, stb_im,
+ eorb_im,adcb_im,orb_im, addb_im,ldd_im, std_im, ldu_im, stu_im,
+
+/* 0xDX */ subb_di,cmpb_di,sbcb_di,addd_di,andb_di,bitb_di,ldb_di, stb_di,
+ eorb_di,adcb_di,orb_di, addb_di,ldd_di, std_di, ldu_di, stu_di,
+
+/* 0xEX */ subb_ix,cmpb_ix,sbcb_ix,addd_ix,andb_ix,bitb_ix,ldb_ix, stb_ix,
+ eorb_ix,adcb_ix,orb_ix, addb_ix,ldd_ix, std_ix, ldu_ix, stu_ix,
+
+/* 0xFX */ subb_ex,cmpb_ex,sbcb_ex,addd_ex,andb_ex,bitb_ex,ldb_ex, stb_ex,
+ eorb_ex,adcb_ex,orb_ex, addb_ex,ldd_ex, std_ex, ldu_ex, stu_ex
+};
diff --git a/trunk/src/emu/cpu/m6809/m6809.c b/trunk/src/emu/cpu/m6809/m6809.c
new file mode 100644
index 00000000000..367f12a4982
--- /dev/null
+++ b/trunk/src/emu/cpu/m6809/m6809.c
@@ -0,0 +1,942 @@
+/*** m6809: Portable 6809 emulator ******************************************
+
+ Copyright John Butler
+
+ References:
+
+ 6809 Simulator V09, By L.C. Benschop, Eidnhoven The Netherlands.
+
+ m6809: Portable 6809 emulator, DS (6809 code in MAME, derived from
+ the 6809 Simulator V09)
+
+ 6809 Microcomputer Programming & Interfacing with Experiments"
+ by Andrew C. Staugaard, Jr.; Howard W. Sams & Co., Inc.
+
+ System dependencies: UINT16 must be 16 bit unsigned int
+ UINT8 must be 8 bit unsigned int
+ UINT32 must be more than 16 bits
+ arrays up to 65536 bytes must be supported
+ machine must be twos complement
+
+ History:
+991026 HJB:
+ Fixed missing calls to cpu_changepc() for the TFR and EXG ocpodes.
+ Replaced m6809_slapstic checks by a macro (CHANGE_PC). ESB still
+ needs the tweaks.
+
+991024 HJB:
+ Tried to improve speed: Using bit7 of cycles1/2 as flag for multi
+ byte opcodes is gone, those opcodes now call fetch_effective_address().
+ Got rid of the slow/fast flags for stack (S and U) memory accesses.
+ Minor changes to use 32 bit values as arguments to memory functions
+ and added defines for that purpose (e.g. X = 16bit XD = 32bit).
+
+990312 HJB:
+ Added bugfixes according to Aaron's findings.
+ Reset only sets CC_II and CC_IF, DP to zero and PC from reset vector.
+990311 HJB:
+ Added _info functions. Now uses static m6808_Regs struct instead
+ of single statics. Changed the 16 bit registers to use the generic
+ PAIR union. Registers defined using macros. Split the core into
+ four execution loops for M6802, M6803, M6808 and HD63701.
+ TST, TSTA and TSTB opcodes reset carry flag.
+ Modified the read/write stack handlers to push LSB first then MSB
+ and pull MSB first then LSB.
+
+990228 HJB:
+ Changed the interrupt handling again. Now interrupts are taken
+ either right at the moment the lines are asserted or whenever
+ an interrupt is enabled and the corresponding line is still
+ asserted. That way the pending_interrupts checks are not
+ needed anymore. However, the CWAI and SYNC flags still need
+ some flags, so I changed the name to 'int_state'.
+ This core also has the code for the old interrupt system removed.
+
+990225 HJB:
+ Cleaned up the code here and there, added some comments.
+ Slightly changed the SAR opcodes (similiar to other CPU cores).
+ Added symbolic names for the flag bits.
+ Changed the way CWAI/Interrupt() handle CPU state saving.
+ A new flag M6809_STATE in pending_interrupts is used to determine
+ if a state save is needed on interrupt entry or already done by CWAI.
+ Added M6809_IRQ_LINE and M6809_FIRQ_LINE defines to m6809.h
+ Moved the internal interrupt_pending flags from m6809.h to m6809.c
+ Changed CWAI cycles2[0x3c] to be 2 (plus all or at least 19 if
+ CWAI actually pushes the entire state).
+ Implemented undocumented TFR/EXG for undefined source and mixed 8/16
+ bit transfers (they should transfer/exchange the constant $ff).
+ Removed unused jmp/jsr _slap functions from 6809ops.c,
+ m6809_slapstick check moved into the opcode functions.
+
+*****************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "m6809.h"
+
+#define VERBOSE 0
+
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+/* 6809 Registers */
+typedef struct _m68_state_t m68_state_t;
+struct _m68_state_t
+{
+ PAIR pc; /* Program counter */
+ PAIR ppc; /* Previous program counter */
+ PAIR d; /* Accumulator a and b */
+ PAIR dp; /* Direct Page register (page in MSB) */
+ PAIR u, s; /* Stack pointers */
+ PAIR x, y; /* Index registers */
+ UINT8 cc;
+ UINT8 ireg; /* First opcode */
+ UINT8 irq_state[2];
+
+ int extra_cycles; /* cycles used up by interrupts */
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ const m6809_config *config;
+ int icount;
+ PAIR ea; /* effective address */
+
+ /* Memory spaces */
+ address_space *program;
+ direct_read_data *direct;
+
+ UINT8 int_state; /* SYNC and CWAI flags */
+ UINT8 nmi_state;
+};
+
+INLINE m68_state_t *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == M6809 ||
+ device->type() == M6809E);
+ return (m68_state_t *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+static void check_irq_lines( m68_state_t *m68_state );
+static void IIError(m68_state_t *m68_state);
+
+INLINE void fetch_effective_address( m68_state_t *m68_state );
+
+/* flag bits in the cc register */
+#define CC_C 0x01 /* Carry */
+#define CC_V 0x02 /* Overflow */
+#define CC_Z 0x04 /* Zero */
+#define CC_N 0x08 /* Negative */
+#define CC_II 0x10 /* Inhibit IRQ */
+#define CC_H 0x20 /* Half (auxiliary) carry */
+#define CC_IF 0x40 /* Inhibit FIRQ */
+#define CC_E 0x80 /* entire state pushed */
+
+#define pPPC m68_state->ppc
+#define pPC m68_state->pc
+#define pU m68_state->u
+#define pS m68_state->s
+#define pX m68_state->x
+#define pY m68_state->y
+#define pD m68_state->d
+
+#define PPC m68_state->ppc.w.l
+#define PC m68_state->pc.w.l
+#define PCD m68_state->pc.d
+#define U m68_state->u.w.l
+#define UD m68_state->u.d
+#define S m68_state->s.w.l
+#define SD m68_state->s.d
+#define X m68_state->x.w.l
+#define XD m68_state->x.d
+#define Y m68_state->y.w.l
+#define YD m68_state->y.d
+#define D m68_state->d.w.l
+#define A m68_state->d.b.h
+#define B m68_state->d.b.l
+#define DP m68_state->dp.b.h
+#define DPD m68_state->dp.d
+#define CC m68_state->cc
+
+#define EA m68_state->ea.w.l
+#define EAD m68_state->ea.d
+#define EAP m68_state->ea
+
+#define M6809_CWAI 8 /* set when CWAI is waiting for an interrupt */
+#define M6809_SYNC 16 /* set when SYNC is waiting for an interrupt */
+#define M6809_LDS 32 /* set when LDS occurred at least once */
+
+
+/****************************************************************************/
+/* Read a byte from given memory location */
+/****************************************************************************/
+#define RM(Addr) ((unsigned)m68_state->program->read_byte(Addr))
+
+/****************************************************************************/
+/* Write a byte to given memory location */
+/****************************************************************************/
+#define WM(Addr,Value) (m68_state->program->write_byte(Addr,Value))
+
+/****************************************************************************/
+/* Z80_RDOP() is identical to Z80_RDMEM() except it is used for reading */
+/* opcodes. In case of system with memory mapped I/O, this function can be */
+/* used to greatly speed up emulation */
+/****************************************************************************/
+#define ROP(Addr) ((unsigned)m68_state->direct->read_decrypted_byte(Addr))
+
+/****************************************************************************/
+/* Z80_RDOP_ARG() is identical to Z80_RDOP() except it is used for reading */
+/* opcode arguments. This difference can be used to support systems that */
+/* use different encoding mechanisms for opcodes and opcode arguments */
+/****************************************************************************/
+#define ROP_ARG(Addr) ((unsigned)m68_state->direct->read_raw_byte(Addr))
+
+/* macros to access memory */
+#define IMMBYTE(b) b = ROP_ARG(PCD); PC++
+#define IMMWORD(w) w.d = (ROP_ARG(PCD)<<8) | ROP_ARG((PCD+1)&0xffff); PC+=2
+
+#define PUSHBYTE(b) --S; WM(SD,b)
+#define PUSHWORD(w) --S; WM(SD,w.b.l); --S; WM(SD,w.b.h)
+#define PULLBYTE(b) b = RM(SD); S++
+#define PULLWORD(w) w = RM(SD)<<8; S++; w |= RM(SD); S++
+
+#define PSHUBYTE(b) --U; WM(UD,b);
+#define PSHUWORD(w) --U; WM(UD,w.b.l); --U; WM(UD,w.b.h)
+#define PULUBYTE(b) b = RM(UD); U++
+#define PULUWORD(w) w = RM(UD)<<8; U++; w |= RM(UD); U++
+
+#define CLR_HNZVC CC&=~(CC_H|CC_N|CC_Z|CC_V|CC_C)
+#define CLR_NZV CC&=~(CC_N|CC_Z|CC_V)
+#define CLR_NZ CC&=~(CC_N|CC_Z)
+#define CLR_HNZC CC&=~(CC_H|CC_N|CC_Z|CC_C)
+#define CLR_NZVC CC&=~(CC_N|CC_Z|CC_V|CC_C)
+#define CLR_Z CC&=~(CC_Z)
+#define CLR_NZC CC&=~(CC_N|CC_Z|CC_C)
+#define CLR_ZC CC&=~(CC_Z|CC_C)
+
+/* macros for CC -- CC bits affected should be reset before calling */
+#define SET_Z(a) if(!a)SEZ
+#define SET_Z8(a) SET_Z((UINT8)a)
+#define SET_Z16(a) SET_Z((UINT16)a)
+#define SET_N8(a) CC|=((a&0x80)>>4)
+#define SET_N16(a) CC|=((a&0x8000)>>12)
+#define SET_H(a,b,r) CC|=(((a^b^r)&0x10)<<1)
+#define SET_C8(a) CC|=((a&0x100)>>8)
+#define SET_C16(a) CC|=((a&0x10000)>>16)
+#define SET_V8(a,b,r) CC|=(((a^b^r^(r>>1))&0x80)>>6)
+#define SET_V16(a,b,r) CC|=(((a^b^r^(r>>1))&0x8000)>>14)
+
+#define SET_FLAGS8I(a) {CC|=flags8i[(a)&0xff];}
+#define SET_FLAGS8D(a) {CC|=flags8d[(a)&0xff];}
+
+/* combos */
+#define SET_NZ8(a) {SET_N8(a);SET_Z(a);}
+#define SET_NZ16(a) {SET_N16(a);SET_Z(a);}
+#define SET_FLAGS8(a,b,r) {SET_N8(r);SET_Z8(r);SET_V8(a,b,r);SET_C8(r);}
+#define SET_FLAGS16(a,b,r) {SET_N16(r);SET_Z16(r);SET_V16(a,b,r);SET_C16(r);}
+
+#define NXORV ((CC&CC_N)^((CC&CC_V)<<2))
+
+/* for treating an unsigned byte as a signed word */
+#define SIGNED(b) ((UINT16)(b&0x80?b|0xff00:b))
+
+/* macros for addressing modes (postbytes have their own code) */
+#define DIRECT EAD = DPD; IMMBYTE(m68_state->ea.b.l)
+#define IMM8 EAD = PCD; PC++
+#define IMM16 EAD = PCD; PC+=2
+#define EXTENDED IMMWORD(EAP)
+
+/* macros to set status flags */
+#if defined(SEC)
+#undef SEC
+#endif
+#define SEC CC|=CC_C
+#define CLC CC&=~CC_C
+#define SEZ CC|=CC_Z
+#define CLZ CC&=~CC_Z
+#define SEN CC|=CC_N
+#define CLN CC&=~CC_N
+#define SEV CC|=CC_V
+#define CLV CC&=~CC_V
+#define SEH CC|=CC_H
+#define CLH CC&=~CC_H
+
+/* macros for convenience */
+#define DIRBYTE(b) {DIRECT;b=RM(EAD);}
+#define DIRWORD(w) {DIRECT;w.d=RM16(m68_state, EAD);}
+#define EXTBYTE(b) {EXTENDED;b=RM(EAD);}
+#define EXTWORD(w) {EXTENDED;w.d=RM16(m68_state, EAD);}
+
+/* macros for branch instructions */
+#define BRANCH(f) { \
+ UINT8 t; \
+ IMMBYTE(t); \
+ if( f ) \
+ { \
+ PC += SIGNED(t); \
+ } \
+}
+
+#define LBRANCH(f) { \
+ PAIR t; \
+ IMMWORD(t); \
+ if( f ) \
+ { \
+ m68_state->icount -= 1; \
+ PC += t.w.l; \
+ } \
+}
+
+/* macros for setting/getting registers in TFR/EXG instructions */
+
+INLINE UINT32 RM16(m68_state_t *m68_state, UINT32 Addr )
+{
+ UINT32 result = RM(Addr) << 8;
+ return result | RM((Addr+1)&0xffff);
+}
+
+INLINE void WM16( m68_state_t *m68_state, UINT32 Addr, PAIR *p )
+{
+ WM( Addr, p->b.h );
+ WM( (Addr+1)&0xffff, p->b.l );
+}
+
+static void UpdateState(m68_state_t *m68_state)
+{
+ /* compatibility with 6309 */
+}
+
+static void check_irq_lines(m68_state_t *m68_state)
+{
+ if( m68_state->irq_state[M6809_IRQ_LINE] != CLEAR_LINE ||
+ m68_state->irq_state[M6809_FIRQ_LINE] != CLEAR_LINE )
+ m68_state->int_state &= ~M6809_SYNC; /* clear SYNC flag */
+ if( m68_state->irq_state[M6809_FIRQ_LINE]!=CLEAR_LINE && !(CC & CC_IF) )
+ {
+ /* fast IRQ */
+ /* HJB 990225: state already saved by CWAI? */
+ if( m68_state->int_state & M6809_CWAI )
+ {
+ m68_state->int_state &= ~M6809_CWAI; /* clear CWAI */
+ m68_state->extra_cycles += 7; /* subtract +7 cycles */
+ }
+ else
+ {
+ CC &= ~CC_E; /* save 'short' state */
+ PUSHWORD(pPC);
+ PUSHBYTE(CC);
+ m68_state->extra_cycles += 10; /* subtract +10 cycles */
+ }
+ CC |= CC_IF | CC_II; /* inhibit FIRQ and IRQ */
+ PCD=RM16(m68_state, 0xfff6);
+ (void)(*m68_state->irq_callback)(m68_state->device, M6809_FIRQ_LINE);
+ }
+ else
+ if( m68_state->irq_state[M6809_IRQ_LINE]!=CLEAR_LINE && !(CC & CC_II) )
+ {
+ /* standard IRQ */
+ /* HJB 990225: state already saved by CWAI? */
+ if( m68_state->int_state & M6809_CWAI )
+ {
+ m68_state->int_state &= ~M6809_CWAI; /* clear CWAI flag */
+ m68_state->extra_cycles += 7; /* subtract +7 cycles */
+ }
+ else
+ {
+ CC |= CC_E; /* save entire state */
+ PUSHWORD(pPC);
+ PUSHWORD(pU);
+ PUSHWORD(pY);
+ PUSHWORD(pX);
+ PUSHBYTE(DP);
+ PUSHBYTE(B);
+ PUSHBYTE(A);
+ PUSHBYTE(CC);
+ m68_state->extra_cycles += 19; /* subtract +19 cycles */
+ }
+ CC |= CC_II; /* inhibit IRQ */
+ PCD=RM16(m68_state, 0xfff8);
+ (void)(*m68_state->irq_callback)(m68_state->device, M6809_IRQ_LINE);
+ }
+}
+
+
+
+/****************************************************************************/
+/* Reset registers to their initial values */
+/****************************************************************************/
+static CPU_INIT( m6809 )
+{
+ /* default configuration */
+ static const m6809_config default_config =
+ {
+ 0
+ };
+
+ const m6809_config *configdata = device->static_config() ? (const m6809_config *)device->static_config() : &default_config;
+ m68_state_t *m68_state = get_safe_token(device);
+
+ m68_state->config = configdata;
+ m68_state->irq_callback = irqcallback;
+ m68_state->device = device;
+
+ m68_state->program = device->space(AS_PROGRAM);
+ m68_state->direct = &m68_state->program->direct();
+
+ /* setup regtable */
+
+ device->save_item(NAME(PC));
+ device->save_item(NAME(PPC));
+ device->save_item(NAME(D));
+ device->save_item(NAME(DP));
+ device->save_item(NAME(U));
+ device->save_item(NAME(S));
+ device->save_item(NAME(X));
+ device->save_item(NAME(Y));
+ device->save_item(NAME(CC));
+ device->save_item(NAME(m68_state->irq_state));
+ device->save_item(NAME(m68_state->int_state));
+ device->save_item(NAME(m68_state->nmi_state));
+
+}
+
+/****************************************************************************/
+/* Reset registers to their initial values */
+/****************************************************************************/
+static CPU_RESET( m6809 )
+{
+ m68_state_t *m68_state = get_safe_token(device);
+
+ m68_state->int_state = 0;
+ m68_state->nmi_state = CLEAR_LINE;
+ m68_state->irq_state[0] = CLEAR_LINE;
+ m68_state->irq_state[1] = CLEAR_LINE;
+
+ DPD = 0; /* Reset direct page register */
+
+ CC |= CC_II; /* IRQ disabled */
+ CC |= CC_IF; /* FIRQ disabled */
+
+ PCD = RM16(m68_state, 0xfffe);
+ UpdateState(m68_state);
+}
+
+static CPU_EXIT( m6809 )
+{
+ /* nothing to do ? */
+}
+
+/****************************************************************************
+ * Set IRQ line state
+ ****************************************************************************/
+static void set_irq_line(m68_state_t *m68_state, int irqline, int state)
+{
+ if (irqline == INPUT_LINE_NMI)
+ {
+ if (m68_state->nmi_state == state) return;
+ m68_state->nmi_state = state;
+ LOG(("M6809 '%s' set_irq_line (NMI) %d\n", m68_state->device->tag(), state));
+ if( state == CLEAR_LINE ) return;
+
+ /* if the stack was not yet initialized */
+ if( !(m68_state->int_state & M6809_LDS) ) return;
+
+ m68_state->int_state &= ~M6809_SYNC;
+ /* HJB 990225: state already saved by CWAI? */
+ if( m68_state->int_state & M6809_CWAI )
+ {
+ m68_state->int_state &= ~M6809_CWAI;
+ m68_state->extra_cycles += 7; /* subtract +7 cycles next time */
+ }
+ else
+ {
+ CC |= CC_E; /* save entire state */
+ PUSHWORD(pPC);
+ PUSHWORD(pU);
+ PUSHWORD(pY);
+ PUSHWORD(pX);
+ PUSHBYTE(DP);
+ PUSHBYTE(B);
+ PUSHBYTE(A);
+ PUSHBYTE(CC);
+ m68_state->extra_cycles += 19; /* subtract +19 cycles next time */
+ }
+ CC |= CC_IF | CC_II; /* inhibit FIRQ and IRQ */
+ PCD = RM16(m68_state, 0xfffc);
+ }
+ else if (irqline < 2)
+ {
+ LOG(("M6809 '%s' set_irq_line %d, %d\n", m68_state->device->tag(), irqline, state));
+ m68_state->irq_state[irqline] = state;
+ if (state == CLEAR_LINE) return;
+ check_irq_lines(m68_state);
+ }
+}
+
+/****************************************************************************
+ * includes the actual opcode implementations
+ ****************************************************************************/
+#include "6809tbl.c"
+
+#include "6809ops.c"
+
+/* execute instructions on this CPU until icount expires */
+static CPU_EXECUTE( m6809 ) /* NS 970908 */
+{
+ m68_state_t *m68_state = get_safe_token(device);
+
+ m68_state->icount -= m68_state->extra_cycles;
+ m68_state->extra_cycles = 0;
+
+ check_irq_lines(m68_state);
+
+ if (m68_state->int_state & (M6809_CWAI | M6809_SYNC))
+ {
+ debugger_instruction_hook(device, PCD);
+ m68_state->icount = 0;
+ }
+ else
+ {
+ do
+ {
+ pPPC = pPC;
+
+ debugger_instruction_hook(device, PCD);
+
+ m68_state->ireg = ROP(PCD);
+ PC++;
+ (*m6809_main[m68_state->ireg])(m68_state);
+ m68_state->icount -= cycles1[m68_state->ireg];
+
+ } while( m68_state->icount > 0 );
+
+ m68_state->icount -= m68_state->extra_cycles;
+ m68_state->extra_cycles = 0;
+ }
+}
+
+INLINE void fetch_effective_address( m68_state_t *m68_state )
+{
+ UINT8 postbyte = ROP_ARG(PCD);
+ PC++;
+
+ switch(postbyte)
+ {
+ case 0x00: EA=X; break;
+ case 0x01: EA=X+1; break;
+ case 0x02: EA=X+2; break;
+ case 0x03: EA=X+3; break;
+ case 0x04: EA=X+4; break;
+ case 0x05: EA=X+5; break;
+ case 0x06: EA=X+6; break;
+ case 0x07: EA=X+7; break;
+ case 0x08: EA=X+8; break;
+ case 0x09: EA=X+9; break;
+ case 0x0a: EA=X+10; break;
+ case 0x0b: EA=X+11; break;
+ case 0x0c: EA=X+12; break;
+ case 0x0d: EA=X+13; break;
+ case 0x0e: EA=X+14; break;
+ case 0x0f: EA=X+15; break;
+
+ case 0x10: EA=X-16; break;
+ case 0x11: EA=X-15; break;
+ case 0x12: EA=X-14; break;
+ case 0x13: EA=X-13; break;
+ case 0x14: EA=X-12; break;
+ case 0x15: EA=X-11; break;
+ case 0x16: EA=X-10; break;
+ case 0x17: EA=X-9; break;
+ case 0x18: EA=X-8; break;
+ case 0x19: EA=X-7; break;
+ case 0x1a: EA=X-6; break;
+ case 0x1b: EA=X-5; break;
+ case 0x1c: EA=X-4; break;
+ case 0x1d: EA=X-3; break;
+ case 0x1e: EA=X-2; break;
+ case 0x1f: EA=X-1; break;
+
+ case 0x20: EA=Y; break;
+ case 0x21: EA=Y+1; break;
+ case 0x22: EA=Y+2; break;
+ case 0x23: EA=Y+3; break;
+ case 0x24: EA=Y+4; break;
+ case 0x25: EA=Y+5; break;
+ case 0x26: EA=Y+6; break;
+ case 0x27: EA=Y+7; break;
+ case 0x28: EA=Y+8; break;
+ case 0x29: EA=Y+9; break;
+ case 0x2a: EA=Y+10; break;
+ case 0x2b: EA=Y+11; break;
+ case 0x2c: EA=Y+12; break;
+ case 0x2d: EA=Y+13; break;
+ case 0x2e: EA=Y+14; break;
+ case 0x2f: EA=Y+15; break;
+
+ case 0x30: EA=Y-16; break;
+ case 0x31: EA=Y-15; break;
+ case 0x32: EA=Y-14; break;
+ case 0x33: EA=Y-13; break;
+ case 0x34: EA=Y-12; break;
+ case 0x35: EA=Y-11; break;
+ case 0x36: EA=Y-10; break;
+ case 0x37: EA=Y-9; break;
+ case 0x38: EA=Y-8; break;
+ case 0x39: EA=Y-7; break;
+ case 0x3a: EA=Y-6; break;
+ case 0x3b: EA=Y-5; break;
+ case 0x3c: EA=Y-4; break;
+ case 0x3d: EA=Y-3; break;
+ case 0x3e: EA=Y-2; break;
+ case 0x3f: EA=Y-1; break;
+
+ case 0x40: EA=U; break;
+ case 0x41: EA=U+1; break;
+ case 0x42: EA=U+2; break;
+ case 0x43: EA=U+3; break;
+ case 0x44: EA=U+4; break;
+ case 0x45: EA=U+5; break;
+ case 0x46: EA=U+6; break;
+ case 0x47: EA=U+7; break;
+ case 0x48: EA=U+8; break;
+ case 0x49: EA=U+9; break;
+ case 0x4a: EA=U+10; break;
+ case 0x4b: EA=U+11; break;
+ case 0x4c: EA=U+12; break;
+ case 0x4d: EA=U+13; break;
+ case 0x4e: EA=U+14; break;
+ case 0x4f: EA=U+15; break;
+
+ case 0x50: EA=U-16; break;
+ case 0x51: EA=U-15; break;
+ case 0x52: EA=U-14; break;
+ case 0x53: EA=U-13; break;
+ case 0x54: EA=U-12; break;
+ case 0x55: EA=U-11; break;
+ case 0x56: EA=U-10; break;
+ case 0x57: EA=U-9; break;
+ case 0x58: EA=U-8; break;
+ case 0x59: EA=U-7; break;
+ case 0x5a: EA=U-6; break;
+ case 0x5b: EA=U-5; break;
+ case 0x5c: EA=U-4; break;
+ case 0x5d: EA=U-3; break;
+ case 0x5e: EA=U-2; break;
+ case 0x5f: EA=U-1; break;
+
+ case 0x60: EA=S; break;
+ case 0x61: EA=S+1; break;
+ case 0x62: EA=S+2; break;
+ case 0x63: EA=S+3; break;
+ case 0x64: EA=S+4; break;
+ case 0x65: EA=S+5; break;
+ case 0x66: EA=S+6; break;
+ case 0x67: EA=S+7; break;
+ case 0x68: EA=S+8; break;
+ case 0x69: EA=S+9; break;
+ case 0x6a: EA=S+10; break;
+ case 0x6b: EA=S+11; break;
+ case 0x6c: EA=S+12; break;
+ case 0x6d: EA=S+13; break;
+ case 0x6e: EA=S+14; break;
+ case 0x6f: EA=S+15; break;
+
+ case 0x70: EA=S-16; break;
+ case 0x71: EA=S-15; break;
+ case 0x72: EA=S-14; break;
+ case 0x73: EA=S-13; break;
+ case 0x74: EA=S-12; break;
+ case 0x75: EA=S-11; break;
+ case 0x76: EA=S-10; break;
+ case 0x77: EA=S-9; break;
+ case 0x78: EA=S-8; break;
+ case 0x79: EA=S-7; break;
+ case 0x7a: EA=S-6; break;
+ case 0x7b: EA=S-5; break;
+ case 0x7c: EA=S-4; break;
+ case 0x7d: EA=S-3; break;
+ case 0x7e: EA=S-2; break;
+ case 0x7f: EA=S-1; break;
+
+ case 0x80: EA=X; X++; break;
+ case 0x81: EA=X; X+=2; break;
+ case 0x82: X--; EA=X; break;
+ case 0x83: X-=2; EA=X; break;
+ case 0x84: EA=X; break;
+ case 0x85: EA=X+SIGNED(B); break;
+ case 0x86: EA=X+SIGNED(A); break;
+ case 0x87: EA=0; break; /* ILLEGAL*/
+ case 0x88: IMMBYTE(EA); EA=X+SIGNED(EA); break;
+ case 0x89: IMMWORD(EAP); EA+=X; break;
+ case 0x8a: EA=0; break; /* IIError*/
+ case 0x8b: EA=X+D; break;
+ case 0x8c: IMMBYTE(EA); EA=PC+SIGNED(EA); break;
+ case 0x8d: IMMWORD(EAP); EA+=PC; break;
+ case 0x8e: EA=0; break; /* ILLEGAL*/
+ case 0x8f: IMMWORD(EAP); break;
+
+ case 0x90: EA=X; X++; EAD=RM16(m68_state, EAD); break; /* Indirect ,R+ not in my specs */
+ case 0x91: EA=X; X+=2; EAD=RM16(m68_state, EAD); break;
+ case 0x92: X--; EA=X; EAD=RM16(m68_state, EAD); break;
+ case 0x93: X-=2; EA=X; EAD=RM16(m68_state, EAD); break;
+ case 0x94: EA=X; EAD=RM16(m68_state, EAD); break;
+ case 0x95: EA=X+SIGNED(B); EAD=RM16(m68_state, EAD); break;
+ case 0x96: EA=X+SIGNED(A); EAD=RM16(m68_state, EAD); break;
+ case 0x97: EA=0; break; /* ILLEGAL*/
+ case 0x98: IMMBYTE(EA); EA=X+SIGNED(EA); EAD=RM16(m68_state, EAD); break;
+ case 0x99: IMMWORD(EAP); EA+=X; EAD=RM16(m68_state, EAD); break;
+ case 0x9a: EA=0; break; /* ILLEGAL*/
+ case 0x9b: EA=X+D; EAD=RM16(m68_state, EAD); break;
+ case 0x9c: IMMBYTE(EA); EA=PC+SIGNED(EA); EAD=RM16(m68_state, EAD); break;
+ case 0x9d: IMMWORD(EAP); EA+=PC; EAD=RM16(m68_state, EAD); break;
+ case 0x9e: EA=0; break; /* ILLEGAL*/
+ case 0x9f: IMMWORD(EAP); EAD=RM16(m68_state, EAD); break;
+
+ case 0xa0: EA=Y; Y++; break;
+ case 0xa1: EA=Y; Y+=2; break;
+ case 0xa2: Y--; EA=Y; break;
+ case 0xa3: Y-=2; EA=Y; break;
+ case 0xa4: EA=Y; break;
+ case 0xa5: EA=Y+SIGNED(B); break;
+ case 0xa6: EA=Y+SIGNED(A); break;
+ case 0xa7: EA=0; break; /* ILLEGAL*/
+ case 0xa8: IMMBYTE(EA); EA=Y+SIGNED(EA); break;
+ case 0xa9: IMMWORD(EAP); EA+=Y; break;
+ case 0xaa: EA=0; break; /* ILLEGAL*/
+ case 0xab: EA=Y+D; break;
+ case 0xac: IMMBYTE(EA); EA=PC+SIGNED(EA); break;
+ case 0xad: IMMWORD(EAP); EA+=PC; break;
+ case 0xae: EA=0; break; /* ILLEGAL*/
+ case 0xaf: IMMWORD(EAP); break;
+
+ case 0xb0: EA=Y; Y++; EAD=RM16(m68_state, EAD); break;
+ case 0xb1: EA=Y; Y+=2; EAD=RM16(m68_state, EAD); break;
+ case 0xb2: Y--; EA=Y; EAD=RM16(m68_state, EAD); break;
+ case 0xb3: Y-=2; EA=Y; EAD=RM16(m68_state, EAD); break;
+ case 0xb4: EA=Y; EAD=RM16(m68_state, EAD); break;
+ case 0xb5: EA=Y+SIGNED(B); EAD=RM16(m68_state, EAD); break;
+ case 0xb6: EA=Y+SIGNED(A); EAD=RM16(m68_state, EAD); break;
+ case 0xb7: EA=0; break; /* ILLEGAL*/
+ case 0xb8: IMMBYTE(EA); EA=Y+SIGNED(EA); EAD=RM16(m68_state, EAD); break;
+ case 0xb9: IMMWORD(EAP); EA+=Y; EAD=RM16(m68_state, EAD); break;
+ case 0xba: EA=0; break; /* ILLEGAL*/
+ case 0xbb: EA=Y+D; EAD=RM16(m68_state, EAD); break;
+ case 0xbc: IMMBYTE(EA); EA=PC+SIGNED(EA); EAD=RM16(m68_state, EAD); break;
+ case 0xbd: IMMWORD(EAP); EA+=PC; EAD=RM16(m68_state, EAD); break;
+ case 0xbe: EA=0; break; /* ILLEGAL*/
+ case 0xbf: IMMWORD(EAP); EAD=RM16(m68_state, EAD); break;
+
+ case 0xc0: EA=U; U++; break;
+ case 0xc1: EA=U; U+=2; break;
+ case 0xc2: U--; EA=U; break;
+ case 0xc3: U-=2; EA=U; break;
+ case 0xc4: EA=U; break;
+ case 0xc5: EA=U+SIGNED(B); break;
+ case 0xc6: EA=U+SIGNED(A); break;
+ case 0xc7: EA=0; break; /*ILLEGAL*/
+ case 0xc8: IMMBYTE(EA); EA=U+SIGNED(EA); break;
+ case 0xc9: IMMWORD(EAP); EA+=U; break;
+ case 0xca: EA=0; break; /*ILLEGAL*/
+ case 0xcb: EA=U+D; break;
+ case 0xcc: IMMBYTE(EA); EA=PC+SIGNED(EA); break;
+ case 0xcd: IMMWORD(EAP); EA+=PC; break;
+ case 0xce: EA=0; break; /*ILLEGAL*/
+ case 0xcf: IMMWORD(EAP); break;
+
+ case 0xd0: EA=U; U++; EAD=RM16(m68_state, EAD); break;
+ case 0xd1: EA=U; U+=2; EAD=RM16(m68_state, EAD); break;
+ case 0xd2: U--; EA=U; EAD=RM16(m68_state, EAD); break;
+ case 0xd3: U-=2; EA=U; EAD=RM16(m68_state, EAD); break;
+ case 0xd4: EA=U; EAD=RM16(m68_state, EAD); break;
+ case 0xd5: EA=U+SIGNED(B); EAD=RM16(m68_state, EAD); break;
+ case 0xd6: EA=U+SIGNED(A); EAD=RM16(m68_state, EAD); break;
+ case 0xd7: EA=0; break; /*ILLEGAL*/
+ case 0xd8: IMMBYTE(EA); EA=U+SIGNED(EA); EAD=RM16(m68_state, EAD); break;
+ case 0xd9: IMMWORD(EAP); EA+=U; EAD=RM16(m68_state, EAD); break;
+ case 0xda: EA=0; break; /*ILLEGAL*/
+ case 0xdb: EA=U+D; EAD=RM16(m68_state, EAD); break;
+ case 0xdc: IMMBYTE(EA); EA=PC+SIGNED(EA); EAD=RM16(m68_state, EAD); break;
+ case 0xdd: IMMWORD(EAP); EA+=PC; EAD=RM16(m68_state, EAD); break;
+ case 0xde: EA=0; break; /*ILLEGAL*/
+ case 0xdf: IMMWORD(EAP); EAD=RM16(m68_state, EAD); break;
+
+ case 0xe0: EA=S; S++; break;
+ case 0xe1: EA=S; S+=2; break;
+ case 0xe2: S--; EA=S; break;
+ case 0xe3: S-=2; EA=S; break;
+ case 0xe4: EA=S; break;
+ case 0xe5: EA=S+SIGNED(B); break;
+ case 0xe6: EA=S+SIGNED(A); break;
+ case 0xe7: EA=0; break; /*ILLEGAL*/
+ case 0xe8: IMMBYTE(EA); EA=S+SIGNED(EA); break;
+ case 0xe9: IMMWORD(EAP); EA+=S; break;
+ case 0xea: EA=0; break; /*ILLEGAL*/
+ case 0xeb: EA=S+D; break;
+ case 0xec: IMMBYTE(EA); EA=PC+SIGNED(EA); break;
+ case 0xed: IMMWORD(EAP); EA+=PC; break;
+ case 0xee: EA=0; break; /*ILLEGAL*/
+ case 0xef: IMMWORD(EAP); break;
+
+ case 0xf0: EA=S; S++; EAD=RM16(m68_state, EAD); break;
+ case 0xf1: EA=S; S+=2; EAD=RM16(m68_state, EAD); break;
+ case 0xf2: S--; EA=S; EAD=RM16(m68_state, EAD); break;
+ case 0xf3: S-=2; EA=S; EAD=RM16(m68_state, EAD); break;
+ case 0xf4: EA=S; EAD=RM16(m68_state, EAD); break;
+ case 0xf5: EA=S+SIGNED(B); EAD=RM16(m68_state, EAD); break;
+ case 0xf6: EA=S+SIGNED(A); EAD=RM16(m68_state, EAD); break;
+ case 0xf7: EA=0; break; /*ILLEGAL*/
+ case 0xf8: IMMBYTE(EA); EA=S+SIGNED(EA); EAD=RM16(m68_state, EAD); break;
+ case 0xf9: IMMWORD(EAP); EA+=S; EAD=RM16(m68_state, EAD); break;
+ case 0xfa: EA=0; break; /*ILLEGAL*/
+ case 0xfb: EA=S+D; EAD=RM16(m68_state, EAD); break;
+ case 0xfc: IMMBYTE(EA); EA=PC+SIGNED(EA); EAD=RM16(m68_state, EAD); break;
+ case 0xfd: IMMWORD(EAP); EA+=PC; EAD=RM16(m68_state, EAD); break;
+ case 0xfe: EA=0; break; /*ILLEGAL*/
+ case 0xff: IMMWORD(EAP); EAD=RM16(m68_state, EAD); break;
+ }
+ m68_state->icount -= index_cycle_em[postbyte];
+}
+
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( m6809 )
+{
+ m68_state_t *m68_state = get_safe_token(device);
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + M6809_IRQ_LINE: set_irq_line(m68_state, M6809_IRQ_LINE, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + M6809_FIRQ_LINE: set_irq_line(m68_state, M6809_FIRQ_LINE, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: set_irq_line(m68_state, INPUT_LINE_NMI, info->i); break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + M6809_PC: PC = info->i; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + M6809_S: S = info->i; break;
+ case CPUINFO_INT_REGISTER + M6809_CC: CC = info->i; check_irq_lines(m68_state); break;
+ case CPUINFO_INT_REGISTER + M6809_U: U = info->i; break;
+ case CPUINFO_INT_REGISTER + M6809_A: A = info->i; break;
+ case CPUINFO_INT_REGISTER + M6809_B: B = info->i; break;
+ case CPUINFO_INT_REGISTER + M6809_X: X = info->i; break;
+ case CPUINFO_INT_REGISTER + M6809_Y: Y = info->i; break;
+ case CPUINFO_INT_REGISTER + M6809_DP: DP = info->i; break;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+CPU_GET_INFO( m6809 )
+{
+ m68_state_t *m68_state = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(m68_state_t); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 2; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 5; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 2; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 19; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_INPUT_STATE + M6809_IRQ_LINE: info->i = m68_state->irq_state[M6809_IRQ_LINE]; break;
+ case CPUINFO_INT_INPUT_STATE + M6809_FIRQ_LINE: info->i = m68_state->irq_state[M6809_FIRQ_LINE]; break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: info->i = m68_state->nmi_state; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = PPC; break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + M6809_PC: info->i = PC; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + M6809_S: info->i = S; break;
+ case CPUINFO_INT_REGISTER + M6809_CC: info->i = CC; break;
+ case CPUINFO_INT_REGISTER + M6809_U: info->i = U; break;
+ case CPUINFO_INT_REGISTER + M6809_A: info->i = A; break;
+ case CPUINFO_INT_REGISTER + M6809_B: info->i = B; break;
+ case CPUINFO_INT_REGISTER + M6809_X: info->i = X; break;
+ case CPUINFO_INT_REGISTER + M6809_Y: info->i = Y; break;
+ case CPUINFO_INT_REGISTER + M6809_DP: info->i = DP; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(m6809); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(m6809); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(m6809); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(m6809); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(m6809); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(m6809); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &m68_state->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "M6809"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Motorola 6809"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.11"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright John Butler"); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c%c%c%c%c%c%c",
+ m68_state->cc & 0x80 ? 'E':'.',
+ m68_state->cc & 0x40 ? 'F':'.',
+ m68_state->cc & 0x20 ? 'H':'.',
+ m68_state->cc & 0x10 ? 'I':'.',
+ m68_state->cc & 0x08 ? 'N':'.',
+ m68_state->cc & 0x04 ? 'Z':'.',
+ m68_state->cc & 0x02 ? 'V':'.',
+ m68_state->cc & 0x01 ? 'C':'.');
+ break;
+
+ case CPUINFO_STR_REGISTER + M6809_PC: sprintf(info->s, "PC:%04X", m68_state->pc.w.l); break;
+ case CPUINFO_STR_REGISTER + M6809_S: sprintf(info->s, "S:%04X", m68_state->s.w.l); break;
+ case CPUINFO_STR_REGISTER + M6809_CC: sprintf(info->s, "CC:%02X", m68_state->cc); break;
+ case CPUINFO_STR_REGISTER + M6809_U: sprintf(info->s, "U:%04X", m68_state->u.w.l); break;
+ case CPUINFO_STR_REGISTER + M6809_A: sprintf(info->s, "A:%02X", m68_state->d.b.h); break;
+ case CPUINFO_STR_REGISTER + M6809_B: sprintf(info->s, "B:%02X", m68_state->d.b.l); break;
+ case CPUINFO_STR_REGISTER + M6809_X: sprintf(info->s, "X:%04X", m68_state->x.w.l); break;
+ case CPUINFO_STR_REGISTER + M6809_Y: sprintf(info->s, "Y:%04X", m68_state->y.w.l); break;
+ case CPUINFO_STR_REGISTER + M6809_DP: sprintf(info->s, "DP:%02X", m68_state->dp.b.h); break;
+ }
+}
+
+
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+
+CPU_GET_INFO( m6809e )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 4; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "M6809E"); break;
+
+ default: CPU_GET_INFO_CALL(m6809); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(M6809, m6809);
+DEFINE_LEGACY_CPU_DEVICE(M6809E, m6809e);
diff --git a/trunk/src/emu/cpu/m6809/m6809.h b/trunk/src/emu/cpu/m6809/m6809.h
new file mode 100644
index 00000000000..1b1381322f8
--- /dev/null
+++ b/trunk/src/emu/cpu/m6809/m6809.h
@@ -0,0 +1,32 @@
+/*** m6809: Portable 6809 emulator ******************************************/
+
+#pragma once
+
+#ifndef __M6809_H__
+#define __M6809_H__
+
+
+enum
+{
+ M6809_PC=1, M6809_S, M6809_CC ,M6809_A, M6809_B, M6809_U, M6809_X, M6809_Y,
+ M6809_DP
+};
+
+#define M6809_IRQ_LINE 0 /* IRQ line number */
+#define M6809_FIRQ_LINE 1 /* FIRQ line number */
+
+DECLARE_LEGACY_CPU_DEVICE(M6809, m6809);
+DECLARE_LEGACY_CPU_DEVICE(M6809E, m6809e);
+
+/* M6809e has LIC line to indicate opcode/data fetch */
+
+
+CPU_DISASSEMBLE( m6809 );
+
+typedef struct _m6809_config m6809_config;
+struct _m6809_config
+{
+ UINT8 encrypt_only_first_byte; /* encrypt only the first byte in 10 xx and 11 xx opcodes */
+};
+
+#endif /* __M6809_H__ */
diff --git a/trunk/src/emu/cpu/mb86233/mb86233.c b/trunk/src/emu/cpu/mb86233/mb86233.c
new file mode 100644
index 00000000000..ebb8b4da5dd
--- /dev/null
+++ b/trunk/src/emu/cpu/mb86233/mb86233.c
@@ -0,0 +1,1716 @@
+/***************************************************************************
+
+ mb86233.c
+ Core implementation for the portable Fujitsu MB86233 series DSP emulator.
+
+ Written by ElSemi
+ MAME version by Ernesto Corvi
+
+ TODO:
+ - Properly emulate the TGP Tables from the ROM (See GETEXTERNAL)
+ - Many unknown opcodes and addressing modes
+ - Interrupts?
+
+***************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "mb86233.h"
+
+CPU_DISASSEMBLE( mb86233 );
+
+/***************************************************************************
+ STRUCTURES & TYPEDEFS
+***************************************************************************/
+
+typedef union
+{
+ INT32 i;
+ UINT32 u;
+ float f;
+} MB86233_REG;
+
+typedef struct _mb86233_state mb86233_state;
+struct _mb86233_state
+{
+ UINT16 pc;
+ MB86233_REG a;
+ MB86233_REG b;
+ MB86233_REG d;
+ MB86233_REG p;
+
+ UINT16 reps;
+ UINT16 pcs[4];
+ UINT8 pcsp;
+ UINT32 eb;
+ UINT32 shift;
+ UINT32 repcnt;
+ UINT16 sr;
+
+ UINT32 gpr[16];
+ UINT32 extport[0x30];
+
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ int icount;
+
+ /* FIFO */
+ int fifo_wait;
+ mb86233_fifo_read_func fifo_read_cb;
+ mb86233_fifo_write_func fifo_write_cb;
+
+ /* internal RAM */
+ UINT32 *RAM;
+ UINT32 *ARAM, *BRAM;
+ UINT32 *Tables;
+};
+
+INLINE mb86233_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == MB86233);
+ return (mb86233_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+#define GETPC() cpustate->pc
+#define GETA() cpustate->a
+#define GETB() cpustate->b
+#define GETD() cpustate->d
+#define GETP() cpustate->p
+#define GETSR() cpustate->sr
+#define GETGPR(a) cpustate->gpr[a]
+#define GETSHIFT() cpustate->shift
+#define GETPCS() cpustate->pcs
+#define GETPCSP() cpustate->pcsp
+#define GETEB() cpustate->eb
+#define GETREPS() cpustate->reps
+#define GETEXTPORT() cpustate->extport
+#define GETFIFOWAIT() cpustate->fifo_wait
+#define GETARAM() cpustate->ARAM
+#define GETBRAM() cpustate->BRAM
+#define ALU(cs,a) mb86233_alu(cs,a)
+#define GETREPCNT() cpustate->repcnt
+
+#define ROPCODE(a) cpustate->direct->read_decrypted_dword(a<<2)
+#define RDMEM(a) cpustate->program->read_dword((a<<2))
+#define WRMEM(a,v) cpustate->program->write_dword((a<<2), v)
+
+/***************************************************************************
+ Initialization and Shutdown
+***************************************************************************/
+
+static CPU_INIT( mb86233 )
+{
+ mb86233_state *cpustate = get_safe_token(device);
+ mb86233_cpu_core * _config = (mb86233_cpu_core *)device->static_config();
+ (void)irqcallback;
+
+ memset(cpustate, 0, sizeof( *cpustate ) );
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+
+ if ( _config )
+ {
+ cpustate->fifo_read_cb = _config->fifo_read_cb;
+ cpustate->fifo_write_cb = _config->fifo_write_cb;
+ cpustate->Tables = (UINT32*) device->machine().region(_config->tablergn)->base();
+ }
+
+ cpustate->RAM = auto_alloc_array(device->machine(), UINT32, 2 * 0x200); /* 2x 2KB */
+ memset( cpustate->RAM, 0, 2 * 0x200 * sizeof(UINT32) );
+ cpustate->ARAM = &cpustate->RAM[0];
+ cpustate->BRAM = &cpustate->RAM[0x200];
+
+ state_save_register_global_pointer(device->machine(), cpustate->RAM,2 * 0x200 * sizeof(UINT32));
+}
+
+static CPU_RESET( mb86233 )
+{
+ mb86233_state *cpustate = get_safe_token(device);
+
+ /* zero registers and flags */
+ cpustate->pc = 0;
+ cpustate->sr = 0;
+ cpustate->pcsp = 0;
+ cpustate->eb = 0;
+ cpustate->shift = 0;
+ cpustate->fifo_wait = 0;
+}
+
+
+
+/***************************************************************************
+ Status Register
+***************************************************************************/
+
+#define ZERO_FLAG (1 << 0)
+#define SIGN_FLAG (1 << 1)
+#define EXTERNAL_FLAG (1 << 2) //This seems to be a flag coming from some external circuit??
+
+static void FLAGSF( mb86233_state *cpustate, float v )
+{
+ GETSR() = 0;
+
+ if ( v == 0 )
+ GETSR() |= ZERO_FLAG;
+
+ if ( v < 0 )
+ GETSR() |= SIGN_FLAG;
+}
+
+static void FLAGSI( mb86233_state *cpustate, UINT32 v )
+{
+ GETSR() = 0;
+
+ if ( v == 0 )
+ GETSR() |= ZERO_FLAG;
+
+ if ( v & 0x80000000 )
+ GETSR() |= SIGN_FLAG;
+}
+
+
+
+/***************************************************************************
+ Condition Codes
+***************************************************************************/
+
+static int COND( mb86233_state *cpustate, UINT32 cond )
+{
+ switch( cond )
+ {
+ case 0x00: /* eq */
+ if ( (GETSR() & ZERO_FLAG) ) return 1;
+ break;
+
+ case 0x01: /* ge */
+ if ( (GETSR() & ZERO_FLAG) || ((GETSR() & SIGN_FLAG)==0) ) return 1;
+ break;
+
+ case 0x02: /* le */
+ if ( (GETSR() & ZERO_FLAG) || (GETSR() & SIGN_FLAG) ) return 1;
+ break;
+
+ case 0x06: /* never */
+ break;
+
+ case 0x0a:
+ if(GETSR() & EXTERNAL_FLAG) return 1;
+ break;
+
+ case 0x10: /* --r12 != 0 */
+ GETGPR(12)--;
+ if ( GETGPR(12) != 0 ) return 1;
+ break;
+
+ case 0x11: /* --r13 != 0 */
+ GETGPR(13)--;
+ if ( GETGPR(13) != 0 ) return 1;
+ break;
+
+ case 0x16: /* always */
+ return 1;
+
+ default:
+ logerror( "TGP: Unknown condition code (cc=%d) at PC:%x\n", cond, GETPC());
+ break;
+ }
+
+ return 0;
+}
+
+
+
+/***************************************************************************
+ ALU
+***************************************************************************/
+
+static void ALU( mb86233_state *cpustate, UINT32 alu)
+{
+ float ftmp;
+
+ switch(alu)
+ {
+ case 0x00: /* NOP */
+ break;
+
+ case 0x01: /* D = D & A */
+ GETD().u &= GETA().u;
+ FLAGSI(cpustate, GETD().u);
+ break;
+
+ case 0x02: /* D = D | A */
+ GETD().u |= GETA().u;
+ FLAGSI(cpustate, GETD().u);
+ break;
+
+ case 0x03: /* D = D ^ A */
+ GETD().u ^= GETA().u;
+ FLAGSI(cpustate, GETD().u);
+ break;
+
+ case 0x05: /* CMP D,A */
+ ftmp = GETD().f - GETA().f;
+ FLAGSF(cpustate, ftmp);
+ cpustate->icount--;
+ break;
+
+ case 0x06: /* D = D + A */
+ GETD().f += GETA().f;
+ FLAGSF(cpustate, GETD().f);
+ cpustate->icount--;
+ break;
+
+ case 0x07: /* D = D - A */
+ GETD().f -= GETA().f;
+ FLAGSF(cpustate, GETD().f);
+ cpustate->icount--;
+ break;
+
+ case 0x08: /* P = A * B */
+ GETP().f = GETA().f * GETB().f;
+ cpustate->icount--;
+ break;
+
+ case 0x09: /* D = D + P; P = A * B */
+ GETD().f += GETP().f;
+ GETP().f = GETA().f * GETB().f;
+ FLAGSF(cpustate, GETD().f);
+ cpustate->icount--;
+ break;
+
+ case 0x0A: /* D = D - P; P = A * B */
+ GETD().f -= GETP().f;
+ GETP().f = GETA().f * GETB().f;
+ FLAGSF(cpustate, GETD().f);
+ cpustate->icount--;
+ break;
+
+ case 0x0B: /* D = fabs(D) */
+ GETD().f = fabs( GETD().f );
+ FLAGSF(cpustate, GETD().f);
+ cpustate->icount--;
+ break;
+
+ case 0x0C: /* D = D + P */
+ GETD().f += GETP().f;
+ FLAGSF(cpustate, GETD().f);
+ cpustate->icount--;
+ break;
+
+ case 0x0D: /* D = P; P = A * B */
+ GETD().f = GETP().f;
+ GETP().f = GETA().f * GETB().f;
+ FLAGSF(cpustate, GETD().f);
+ cpustate->icount--;
+ break;
+
+ case 0x0E: /* D = float(D) */
+ GETD().f = (float)GETD().i;
+ FLAGSF(cpustate, GETD().f);
+ cpustate->icount--;
+ break;
+
+ case 0x0F: /* D = int(D) */
+ GETD().i = (INT32)GETD().f;
+ FLAGSI(cpustate, GETD().u);
+ break;
+
+ case 0x10: /* D = D / A */
+ if ( GETA().u != 0 )
+ GETD().f = GETD().f / GETA().f;
+ FLAGSF(cpustate, GETD().f);
+ cpustate->icount--;
+ break;
+
+ case 0x11: /* D = -D */
+ GETD().f = -GETD().f;
+ FLAGSF(cpustate, GETD().f);
+ cpustate->icount--;
+ break;
+
+ case 0x13: /* D = A + B */
+ GETD().f = GETA().f + GETB().f;
+ FLAGSF(cpustate, GETD().f);
+ cpustate->icount--;
+ break;
+
+ case 0x14: /* D = B - A */
+ GETD().f = GETB().f - GETA().f;
+ FLAGSF(cpustate, GETD().f);
+ cpustate->icount--;
+ break;
+
+ case 0x16: /* LSR D, SHIFT */
+ GETD().u >>= GETSHIFT();
+ FLAGSI(cpustate, GETD().u);
+ break;
+
+ case 0x17: /* LSL D, SHIFT */
+ GETD().u <<= GETSHIFT();
+ FLAGSI(cpustate, GETD().u);
+ break;
+
+ case 0x18: /* ASR D, SHIFT */
+// GETD().u = (GETD().u & 0x80000000) | (GETD().u >> GETSHIFT());
+ GETD().i >>= GETSHIFT();
+ FLAGSI(cpustate, GETD().u);
+ break;
+
+ case 0x1A: /* D = D + A */
+ GETD().i += GETA().i;
+ FLAGSI(cpustate, GETD().u);
+ break;
+
+ case 0x1B: /* D = D - A */
+ GETD().i -= GETA().i;
+ FLAGSI(cpustate, GETD().u);
+ break;
+
+ default:
+ logerror( "TGP: Unknown ALU op %x at PC:%04x\n", alu, GETPC() );
+ break;
+ }
+}
+
+
+
+/***************************************************************************
+ Memory Access
+***************************************************************************/
+
+static UINT32 ScaleExp(unsigned int v,int scale)
+{
+ int exp=(v>>23)&0xff;
+ exp+=scale;
+ v&=~0x7f800000;
+ return v|(exp<<23);
+}
+
+
+static UINT32 GETEXTERNAL( mb86233_state *cpustate, UINT32 EB, UINT32 offset )
+{
+ UINT32 addr;
+
+ if ( EB == 0 && offset >= 0x20 && offset <= 0x2f ) /* TGP Tables in ROM - FIXME - */
+ {
+ if(offset>=0x20 && offset<=0x23) //SIN from value at RAM(0x20) in 0x4000/PI steps
+ {
+ UINT32 r;
+ UINT32 value=GETEXTPORT()[0x20];
+ UINT32 off;
+ value+=(offset-0x20)<<14;
+ off=value&0x3fff;
+ if((value&0x7fff)==0)
+ r=0;
+ else if((value&0x7fff)==0x4000)
+ r=0x3f800000;
+ else
+ {
+ if(value&0x4000)
+ off=0x4000-off;
+ r=cpustate->Tables[off];
+ }
+ if(value&0x8000)
+ r|=1<<31;
+ return r;
+ }
+
+ if(offset==0x27)
+ {
+ unsigned int value=GETEXTPORT()[0x27];
+ int exp=(value>>23)&0xff;
+ unsigned int res=0;
+ unsigned int sign=0;
+ MB86233_REG a,b;
+ int index;
+
+ a.u=GETEXTPORT()[0x24];
+ b.u=GETEXTPORT()[0x25];
+
+
+ if(!exp)
+ {
+ if((a.u&0x7fffffff)<=(b.u&0x7fffffff))
+ {
+ if(b.u&0x80000000)
+ res=0xc000;
+ else
+ res=0x4000;
+ }
+ else
+ {
+ if(a.u&0x80000000)
+ res=0x8000;
+ else
+ res=0x0000;
+ }
+ return res;
+ }
+
+ if((a.u^b.u)&0x80000000)
+ sign=16; //the negative values are in the high word
+
+ if((exp&0x70)!=0x70)
+ index=0;
+ else if(exp<0x70 || exp>0x7e)
+ index=0x3fff;
+ else
+ {
+ int expdif=exp-0x71;
+ int base;
+ int mask;
+ int shift;
+
+
+ if(expdif<0)
+ expdif=0;
+ base=1<<expdif;
+ mask=base-1;
+ shift=23-expdif;
+
+ index=base+((value>>shift)&mask);
+
+ }
+
+ res=(cpustate->Tables[index+0x10000/4]>>sign)&0xffff;
+
+ if((a.u&0x7fffffff)<=(b.u&0x7fffffff))
+ res=0x4000-res;
+
+
+ if((a.u&0x80000000) && (b.u&0x80000000)) //3rd quadrant
+ {
+ res=0x8000|res;
+ }
+ else if((a.u&0x80000000) && !(b.u&0x80000000)) //2nd quadrant
+ {
+ res=res&0x7fff;
+ }
+ else if(!(a.u&0x80000000) && (b.u&0x80000000)) //2nd quadrant
+ {
+ res=0x8000|res;
+ }
+
+ return res;
+
+ }
+
+ if(offset==0x28)
+ {
+ UINT32 offset=(GETEXTPORT()[0x28]>>10)&0x1fff;
+ UINT32 value=cpustate->Tables[offset*2+0x20000/4];
+ UINT32 srcexp=(GETEXTPORT()[0x28]>>23)&0xff;
+
+ value&=0x7FFFFFFF;
+
+ return ScaleExp(value,0x7f-srcexp);
+ }
+ if(offset==0x29)
+ {
+ UINT32 offset=(GETEXTPORT()[0x28]>>10)&0x1fff;
+ UINT32 value=cpustate->Tables[offset*2+(0x20000/4)+1];
+ UINT32 srcexp=(GETEXTPORT()[0x28]>>23)&0xff;
+
+ value&=0x7FFFFFFF;
+ if(GETEXTPORT()[0x28]&(1<<31))
+ value|=1<<31;
+
+ return ScaleExp(value,0x7f-srcexp);
+ }
+ if(offset==0x2a)
+ {
+ UINT32 offset=((GETEXTPORT()[0x2a]>>11)&0x1fff)^0x1000;
+ UINT32 value=cpustate->Tables[offset*2+0x30000/4];
+ UINT32 srcexp=(GETEXTPORT()[0x2a]>>24)&0x7f;
+
+ value&=0x7FFFFFFF;
+
+ return ScaleExp(value,0x3f-srcexp);
+ }
+ if(offset==0x2b)
+ {
+ UINT32 offset=((GETEXTPORT()[0x2a]>>11)&0x1fff)^0x1000;
+ UINT32 value=cpustate->Tables[offset*2+(0x30000/4)+1];
+ UINT32 srcexp=(GETEXTPORT()[0x2a]>>24)&0x7f;
+
+ value&=0x7FFFFFFF;
+ if(GETEXTPORT()[0x2a]&(1<<31))
+ value|=1<<31;
+
+ return ScaleExp(value,0x3f-srcexp);
+ }
+
+ return GETEXTPORT()[offset];
+ }
+
+ addr = ( EB & 0xFFFF0000 ) | ( offset & 0xFFFF );
+
+ return RDMEM(addr);
+}
+
+static void SETEXTERNAL( mb86233_state *cpustate, UINT32 EB, UINT32 offset, UINT32 value )
+{
+ UINT32 addr;
+
+ if ( EB == 0 && offset >= 0x20 && offset <= 0x2f ) /* TGP Tables in ROM - FIXME - */
+ {
+ GETEXTPORT()[offset] = value;
+
+ if(offset==0x25 || offset==0x24)
+ {
+ if((GETEXTPORT()[0x24]&0x7fffffff)<=(GETEXTPORT()[0x25]&0x7fffffff))
+ {
+ GETSR()|=EXTERNAL_FLAG;
+ }
+ else
+ {
+ GETSR()&=~EXTERNAL_FLAG;
+ }
+ }
+ return;
+ }
+
+ addr = ( EB & 0xFFFF0000 ) | ( offset & 0xFFFF );
+
+ WRMEM( addr, value );
+}
+
+
+
+/***************************************************************************
+ Register Access
+***************************************************************************/
+
+static UINT32 GETREGS( mb86233_state *cpustate, UINT32 reg, int source )
+{
+ UINT32 mode = ( reg >> 6 ) & 0x07;
+
+ reg &= 0x3f;
+
+ if ( mode == 0 || mode == 1 || mode == 3 )
+ {
+ if ( reg < 0x10 )
+ {
+ return GETGPR(reg);
+ }
+
+ switch( reg )
+ {
+ case 0x10: /* A */
+ return GETA().u;
+
+ case 0x11: /* A.e */
+ return (GETA().u >> 23) & 0xff;
+
+ case 0x12: /* A.m */
+ return (GETA().u & 0x7fffff) | ((GETA().u&0x80000000) >> 8);
+
+ case 0x13: /* B */
+ return GETB().u;
+
+ case 0x14: /* B.e */
+ return (GETB().u >> 23) & 0xff;
+
+ case 0x15: /* B.m */
+ return (GETB().u & 0x7fffff) | ((GETB().u&0x80000000) >> 8);
+
+ case 0x19: /* D */
+ return GETD().u;
+
+ case 0x1A: /* D.e */
+ return (GETD().u >> 23) & 0xff;
+
+ case 0x1B: /* D.m */
+ return (GETD().u & 0x7fffff) | ((GETD().u&0x80000000) >> 8);
+
+ case 0x1C: /* P */
+ return GETP().u;
+
+ case 0x1D: /* P.e */
+ return (GETP().u >> 23) & 0xff;
+
+ case 0x1E: /* P.m */
+ return (GETP().u & 0x7fffff) | ((GETP().u&0x80000000) >> 8);
+
+ case 0x1F: /* Shift */
+ return GETSHIFT();
+
+ case 0x20: /* Parallel Port */
+ logerror( "TGP: Parallel port read at PC:%04x\n", GETPC() );
+ return 0;
+
+ case 0x21: /* FIn */
+ {
+ UINT32 fifo_data;
+
+ if ( cpustate->fifo_read_cb )
+ {
+ if ( cpustate->fifo_read_cb(cpustate->device, &fifo_data) )
+ {
+ return fifo_data;
+ }
+ }
+
+ GETFIFOWAIT() = 1;
+ return 0;
+ }
+
+ case 0x22: /* FOut */
+ return 0;
+
+ case 0x23: /* EB */
+ return GETEB();
+
+ case 0x34:
+ return GETREPCNT();
+
+ default:
+ logerror( "TGP: Unknown GETREG (%d) at PC=%04x\n", reg, GETPC() );
+ break;
+ }
+ }
+ else if ( mode == 2 ) /* Indexed */
+ {
+ UINT32 addr = reg & 0x1f;
+
+ if ( source )
+ {
+ if( !( reg & 0x20 ) )
+ addr += GETGPR(0);
+
+ addr += GETGPR(2);
+ }
+ else
+ {
+ if( !( reg & 0x20 ) )
+ addr += GETGPR(1);
+
+ addr += GETGPR(3);
+ }
+
+ return addr;
+ }
+ else if( mode == 6 ) /* Indexed with postop */
+ {
+ UINT32 addr = 0;
+
+ if ( source )
+ {
+ if( !( reg & 0x20 ) )
+ addr += GETGPR(0);
+
+ addr += GETGPR(2);
+ }
+ else
+ {
+ if( !( reg & 0x20 ) )
+ addr += GETGPR(1);
+
+ addr += GETGPR(3);
+ }
+
+ if ( reg & 0x10 )
+ {
+ if ( source )
+ GETGPR(2) -= 0x20 - ( reg & 0x1f );
+ else
+ GETGPR(3) -= 0x20 - ( reg & 0x1f );
+ }
+ else
+ {
+ if ( source )
+ GETGPR(2) += ( reg & 0x1f );
+ else
+ GETGPR(3) += ( reg & 0x1f );
+ }
+
+ return addr;
+ }
+ else
+ {
+ fatalerror( "TGP: Unknown GETREG mode %d at PC:%04x\n", mode, GETPC() );
+ }
+
+ return 0;
+}
+
+static void SETREGS( mb86233_state *cpustate, UINT32 reg, UINT32 val )
+{
+ int mode = ( reg >> 6) & 0x07;
+
+ reg &= 0x3f;
+
+ if( mode == 0 || mode == 1 || mode == 3 )
+ {
+ if ( reg < 0x10 )
+ {
+ if ( reg == 12 || reg == 13 )
+ val &= 0xff;
+
+ GETGPR(reg) = val;
+ return;
+ }
+
+ switch( reg )
+ {
+ case 0x10: /* A */
+ GETA().u = val;
+ break;
+
+ case 0x11: /* A.e */
+ GETA().u &= ~((0x0000007f) << 23);
+ GETA().u |= (( val & 0xff ) << 23 );
+ break;
+
+ case 0x12: /* A.m */
+ GETA().u &= ~( 0x807fffff );
+ GETA().u |= ( val & 0x7fffff );
+ GETA().u |= ( val & 0x800000 ) << 8;
+ break;
+
+ case 0x13: /* B */
+ GETB().u = val;
+ break;
+
+ case 0x14: /* B.e */
+ GETB().u &= ~((0x0000007f) << 23);
+ GETB().u |= (( val & 0xff ) << 23 );
+ break;
+
+ case 0x15: /* B.m */
+ GETB().u &= ~( 0x807fffff );
+ GETB().u |= ( val & 0x7fffff );
+ GETB().u |= ( val & 0x800000 ) << 8;
+ break;
+
+ case 0x19: /* D */
+ GETD().u = val;
+ break;
+
+ case 0x1A: /* D.e */
+ GETD().u &= ~((0x0000007f) << 23);
+ GETD().u |= (( val & 0xff ) << 23 );
+ break;
+
+ case 0x1B: /* B.m */
+ GETD().u &= ~( 0x807fffff );
+ GETD().u |= ( val & 0x7fffff );
+ GETD().u |= ( val & 0x800000 ) << 8;
+ break;
+
+ case 0x1C: /* P */
+ GETP().u = val;
+ break;
+
+ case 0x1D: /* P.e */
+ GETP().u &= ~((0x0000007f) << 23);
+ GETP().u |= (( val & 0xff ) << 23 );
+ break;
+
+ case 0x1E: /* P.m */
+ GETP().u &= ~( 0x807fffff );
+ GETP().u |= ( val & 0x7fffff );
+ GETP().u |= ( val & 0x800000 ) << 8;
+ break;
+
+ case 0x1F:
+ GETSHIFT() = val;
+ break;
+
+ case 0x20: /* Parallel Port */
+ logerror( "TGP: Parallel port write: %08x at PC:%04x\n", val, GETPC() );
+ break;
+
+ case 0x22: /* FOut */
+ if ( cpustate->fifo_write_cb )
+ {
+ cpustate->fifo_write_cb( cpustate->device, val );
+ }
+ break;
+
+ case 0x23:
+ GETEB() = val;
+ break;
+
+ case 0x34:
+ GETREPCNT() = val;
+ break;
+
+ default:
+ {
+ fatalerror( "TGP: Unknown register write (r:%d, mode:%d) at PC:%04x\n", reg, mode, GETPC());
+ }
+ break;
+ }
+ }
+ else
+ {
+ fatalerror( "TGP: Unknown register write (r:%d, mode:%d) at PC:%04x\n", reg, mode, GETPC());
+ }
+}
+
+
+/***************************************************************************
+ Addressing Modes
+***************************************************************************/
+
+static UINT32 INDIRECT( mb86233_state *cpustate, UINT32 reg, int source )
+{
+ UINT32 mode = ( reg >> 6 ) & 0x07;
+
+ if ( mode == 0 || mode == 1 || mode == 3 )
+ {
+ return reg;
+ }
+ else if ( mode == 2 )
+ {
+ UINT32 addr = reg & 0x1f;
+
+ if ( source )
+ {
+ if( !(reg & 0x20) )
+ addr += GETGPR(0);
+
+ addr += GETGPR(2);
+ }
+ else
+ {
+ if( !(reg & 0x20) )
+ addr += GETGPR(1);
+
+ addr += GETGPR(3);
+ }
+
+ return addr;
+ }
+ else if ( mode == 6 || mode == 7 )
+ {
+ UINT32 addr = 0;
+
+ if ( source )
+ {
+ if ( !( reg & 0x20 ) )
+ addr += GETGPR(0);
+
+ addr += GETGPR(2);
+ }
+ else
+ {
+ if ( !( reg & 0x20 ) )
+ addr += GETGPR(1);
+
+ addr += GETGPR(3);
+ }
+
+ if ( reg & 0x10 )
+ {
+ if ( source )
+ GETGPR(2) -= 0x20 - ( reg & 0x1f );
+ else
+ GETGPR(3) -= 0x20 - ( reg & 0x1f );
+ }
+ else
+ {
+ if ( source )
+ GETGPR(2) += ( reg & 0x1f );
+ else
+ GETGPR(3) += ( reg & 0x1f );
+ }
+
+ return addr;
+ }
+ else
+ {
+ fatalerror( "TGP: Unknown INDIRECT mode %d at PC:%04x\n", mode, GETPC() );
+ }
+
+ return 0;
+}
+
+/***************************************************************************
+ Core Execution Loop
+***************************************************************************/
+
+static CPU_EXECUTE( mb86233 )
+{
+ mb86233_state *cpustate = get_safe_token(device);
+
+ while( cpustate->icount > 0 )
+ {
+ UINT32 val;
+ UINT32 opcode;
+
+ debugger_instruction_hook(device, GETPC());
+
+ opcode = ROPCODE(GETPC());
+
+ GETFIFOWAIT() = 0;
+
+ switch( (opcode >> 26) & 0x3f )
+ {
+ case 0x00: /* dual move */
+ {
+ UINT32 r1 = opcode & 0x1ff;
+ UINT32 r2 = ( opcode >> 9 ) & 0x7f;
+ UINT32 alu = ( opcode >> 21 ) & 0x1f;
+ UINT32 op = ( opcode >> 16 ) & 0x1f;
+
+ ALU( cpustate, alu );
+
+ switch( op )
+ {
+ case 0x0C:
+ GETA().u = GETARAM()[r1];
+ GETB().u = GETBRAM()[r2];
+ break;
+
+ case 0x0D:
+ GETA().u = GETARAM()[INDIRECT(cpustate,r1,0)];
+ GETB().u = GETBRAM()[INDIRECT(cpustate,r2|2<<6,0)];
+ break;
+
+ case 0x0F:
+ GETA().u = GETARAM()[r1];
+ GETB().u = GETBRAM()[INDIRECT(cpustate,r2|6<<6,0)];
+ break;
+
+ case 0x10:
+ GETA().u = GETBRAM()[INDIRECT(cpustate,r1,1)];
+ GETB().u = GETARAM()[r2];
+ break;
+
+ case 0x11:
+ GETA().u = GETARAM()[INDIRECT(cpustate,r1,1)];
+ GETB().u = GETBRAM()[INDIRECT(cpustate,r2|(2<<6),0)];
+ break;
+
+ default:
+ logerror( "TGP: Unknown TGP double move (op=%d) at PC:%x\n", op, GETPC());
+ break;
+ }
+ }
+ break;
+
+ case 0x7: /* LD/MOV */
+ {
+ UINT32 r1 = opcode & 0x1ff;
+ UINT32 r2 = ( opcode >> 9 ) & 0x7f;
+ UINT32 alu = ( opcode >> 21 ) & 0x1f;
+ UINT32 op = ( opcode >> 16 ) & 0x1f;
+
+ switch( op )
+ {
+ case 0x04: /* MOV RAM->External */
+ {
+ SETEXTERNAL(cpustate, GETEB(), r2, GETARAM()[r1]);
+ ALU(cpustate, alu);
+ }
+ break;
+
+ case 0x0c: /* MOV RAM->BRAM */
+ {
+ GETBRAM()[r2] = GETARAM()[r1];
+ ALU(cpustate, alu);
+ }
+ break;
+
+ case 0x1d: /* MOV RAM->Reg */
+ {
+ if ( r1 & 0x180 )
+ {
+ val = GETARAM()[GETREGS(cpustate,r1,0)];
+ }
+ else
+ {
+ val = GETARAM()[r1];
+ }
+
+ /* if we're waiting for data, don't complete the instruction */
+ if ( GETFIFOWAIT() )
+ break;
+
+ ALU(cpustate, alu);
+ SETREGS(cpustate,r2,val);
+ }
+ break;
+
+ case 0x1c: /* MOV Reg->RAMInd */
+ {
+ val = GETREGS(cpustate,r2,1);
+
+ /* if we're waiting for data, don't complete the instruction */
+ if ( GETFIFOWAIT() )
+ break;
+
+ ALU(cpustate, alu);
+
+ if ( ( r2 >> 6 ) & 0x01)
+ {
+ SETEXTERNAL(cpustate, GETEB(),INDIRECT(cpustate,r1,0),val);
+ }
+ else
+ {
+ GETARAM()[INDIRECT(cpustate,r1,0)] = val;
+ }
+ }
+ break;
+
+ case 0x1f: /* MOV Reg->Reg */
+ {
+ if ( r1 == 0x10 && r2 == 0xf )
+ {
+ /* NOP */
+ ALU(cpustate, alu);
+ }
+ else
+ {
+ val = GETREGS(cpustate,r1,1);
+
+ /* if we're waiting for data, don't complete the instruction */
+ if ( GETFIFOWAIT() )
+ break;
+
+ ALU(cpustate, alu);
+ SETREGS(cpustate, r2, val );
+ }
+ }
+ break;
+
+ case 0x0f: /* MOV RAMInd->BRAMInd */
+ {
+ val = GETARAM()[INDIRECT(cpustate,r1,1)];
+ ALU(cpustate, alu);
+ GETBRAM()[INDIRECT(cpustate,r2|(6<<6),0)] = val;
+ }
+ break;
+
+ case 0x13: /* MOV BRAMInd->RAMInd */
+ {
+ val = GETBRAM()[INDIRECT(cpustate,r1,1)];
+ ALU(cpustate, alu);
+ GETARAM()[INDIRECT(cpustate,r2|(6<<6),0)] = val;
+ }
+ break;
+
+ case 0x10: /* MOV RAMInd->RAM */
+ {
+ val = GETBRAM()[INDIRECT(cpustate,r1,1)];
+ ALU(cpustate, alu);
+ GETARAM()[r2] = val;
+ }
+ break;
+
+ case 0x1e: /* External->Reg */
+ {
+ UINT32 offset;
+
+ if ( ( r2 >> 6 ) & 1 )
+ offset = INDIRECT(cpustate,r1,1);
+ else
+ offset = INDIRECT(cpustate,r1,0);
+
+ val = GETEXTERNAL(cpustate, GETEB(),offset);
+ ALU(cpustate, alu);
+ SETREGS(cpustate,r2,val);
+ }
+ break;
+
+ case 0x03: /* RAM->External Ind */
+ {
+ val = GETARAM()[r1];
+ ALU(cpustate, alu);
+ SETEXTERNAL(cpustate, GETEB(),INDIRECT(cpustate,r2|(6<<6),0),val);
+ }
+ break;
+
+ case 0x07: /* RAMInd->External */
+ {
+ val = GETARAM()[INDIRECT(cpustate,r1,1)];
+ ALU(cpustate, alu);
+ SETEXTERNAL(cpustate, GETEB(),INDIRECT(cpustate,r2|(6<<6),0),val);
+ }
+ break;
+
+ case 0x08: /* External->RAM */
+ {
+ val = GETEXTERNAL(cpustate, GETEB(),INDIRECT(cpustate,r1,1));
+ ALU(cpustate, alu);
+ GETARAM()[r2] = val;
+ }
+ break;
+
+ case 0x0b: /* External->RAMInd */
+ {
+ val = GETEXTERNAL(cpustate, GETEB(),INDIRECT(cpustate,r1,1));
+ ALU(cpustate, alu);
+ GETARAM()[INDIRECT(cpustate,r2|(6<<6),0)] = val;
+ }
+ break;
+
+ default:
+ logerror( "TGP: Unknown TGP move (op=%d) at PC:%x\n", op, GETPC());
+ break;
+ }
+ }
+ break;
+
+ case 0x0e: /* LDIMM24 */
+ {
+ UINT32 sub = (opcode>>24) & 0x03;
+ UINT32 imm = opcode & 0xffffff;
+
+ /* sign extend 24->32 */
+ if ( imm & 0x800000 )
+ imm |= 0xFF000000;
+
+ switch( sub )
+ {
+ case 0x00: /* P */
+ GETP().u = imm;
+ break;
+
+ case 0x01: /* A */
+ GETA().u = imm;
+ break;
+
+ case 0x02: /* B */
+ GETB().u = imm;
+ break;
+
+ case 0x03: /* D */
+ GETD().u = imm;
+ break;
+ }
+ }
+ break;
+
+ case 0x0f: /* REP/CLEAR/FLAGS */
+ {
+ UINT32 alu = ( opcode >> 20 ) & 0x1f;
+ UINT32 sub2 = ( opcode >> 16 ) & 0x0f;
+
+ ALU(cpustate, alu );
+
+ if( sub2 == 0x00 ) /* CLEAR reg */
+ {
+ UINT32 reg = opcode & 0x1f;
+
+ switch( reg )
+ {
+ case 0x10:
+ GETD().u = 0;
+ break;
+
+ case 0x08:
+ GETB().u = 0;
+ break;
+
+ case 0x04:
+ GETA().u = 0;
+ break;
+ }
+ }
+ else if ( sub2 == 0x04 ) /* REP xxx */
+ {
+ UINT32 sub3 = ( opcode >> 12 ) & 0x0f;
+
+ if ( sub3 == 0 )
+ {
+ GETREPS() = opcode & 0xfff;
+
+ if ( GETREPS() == 0 )
+ GETREPS() = 0x100;
+
+ GETPC()++;
+ }
+ else if ( sub3 == 8 )
+ {
+ GETREPS() = GETREGS(cpustate, opcode & 0xfff, 0 );
+ GETPC()++;
+ }
+ }
+ else if ( sub2 == 0x02 ) /* CLRFLAGS */
+ {
+ GETSR() &= ~(opcode&0xfff);
+ }
+ else if ( sub2 == 0x06 ) /* SETFLAGS */
+ {
+ GETSR() |= (opcode&0xfff);
+ }
+ }
+ break;
+
+ case 0x10: /* LDIMM rx */
+ {
+ UINT32 sub = (opcode>>24) & 0x03;
+ UINT32 imm = opcode & 0xffff;
+
+ GETGPR(sub) = imm;
+ }
+ break;
+
+ case 0x13: /* LDIMM r1x */
+ {
+ UINT32 sub = (opcode>>24) & 0x03;
+ UINT32 imm = opcode & 0xffffff;
+
+ if ( sub == 0 ) /* R12 */
+ GETGPR(12) = imm & 0xff;
+ else if ( sub == 1 ) /* R13 */
+ GETGPR(13) = imm & 0xff;
+ else
+ logerror( "TGP: Unknown LDIMM r12 (sub=%d) at PC:%04x\n", sub, GETPC() );
+ }
+ break;
+
+ case 0x14: /* LDIMM m,e */
+ {
+ UINT32 sub = (opcode>>24) & 0x03;
+ UINT32 imm = opcode & 0xffffff;
+
+ if ( sub == 0 ) /* A */
+ {
+ GETA().u = imm;
+ }
+ else if ( sub == 1 ) /* A.e */
+ {
+ GETA().u &= ~0x7f800000;
+ GETA().u |= (imm & 0xff) << 23;
+ }
+ else if ( sub == 2 ) /* A.m */
+ {
+ GETA().u &= 0x7f800000;
+ GETA().u |= (imm & 0x7fffff ) | ((imm & 0x800000) << 8);
+ }
+ else
+ {
+ logerror( "TGP: Unknown LDIMM m,e (sub=%d) at PC:%04x\n", sub, GETPC() );
+ }
+ }
+ break;
+
+ case 0x15: /* LDIMM m,e */
+ {
+ UINT32 sub = (opcode>>24) & 0x03;
+ UINT32 imm = opcode & 0xffffff;
+
+ if ( sub == 0 ) /* B.e again? */
+ {
+ //GETB().u = ((imm & 0x7f) << 23) | ((imm & 0xff) << 8) | ( imm & 0xff );
+ GETB().u &= ~0x7f800000;
+ GETB().u |= (imm & 0xff) << 23;
+ }
+ else if ( sub == 1 ) /* B.e */
+ {
+ GETB().u &= ~0x7f800000;
+ GETB().u |= (imm & 0xff) << 23;
+ }
+ else if ( sub == 2 ) /* B.m */
+ {
+ GETB().u &= 0x7f800000;
+ GETB().u |= (imm & 0x7fffff ) | ((imm & 0x800000) << 8);
+ }
+ else
+ {
+ logerror( "TGP: Unknown LDIMM m,e (sub=%d) at PC:%04x\n", sub, GETPC() );
+ }
+ }
+ break;
+
+ case 0x16: /* LDIMM m,e */
+ {
+ UINT32 sub = (opcode>>24) & 0x03;
+ UINT32 imm = opcode & 0xffffff;
+
+ if ( sub == 1 ) /* clear + D.m */
+ {
+ GETD().u = (imm & 0x7fffff ) | ((imm & 0x800000) << 8);
+ }
+ else if ( sub == 2 ) /* D.e */
+ {
+ GETD().u &= ~0x7f800000;
+ GETD().u |= (imm & 0xff) << 23;
+ }
+ else if ( sub == 3 ) /* D.m */
+ {
+ GETD().u &= 0x7f800000;
+ GETD().u |= (imm & 0x7fffff ) | ((imm & 0x800000) << 8);
+ }
+ else
+ {
+ logerror( "TGP: Unknown LDIMM m,e (sub=%d) at PC:%04x\n", sub, GETPC() );
+ }
+ }
+ break;
+
+ case 0x17: /* LDIMM special reg */
+ {
+ UINT32 sub = (opcode>>24) & 0x03;
+ UINT32 imm = opcode & 0xffffff;
+
+ if ( sub == 0x03 )
+ {
+ GETSHIFT() = imm;
+ }
+ else
+ {
+ logerror( "TGP: Unknown LDIMM special reg (sub=%d) at PC:%04x\n", sub, GETPC() );
+ }
+ }
+ break;
+
+ case 0x18: /* LDIMM external reg */
+ {
+ UINT32 sub = (opcode>>24) & 0x03;
+ UINT32 imm = opcode & 0xffffff;
+
+ if ( sub == 0x03 )
+ {
+ GETEB() = imm;
+ }
+ else
+ {
+ logerror( "TGP: Unknown LDIMM external reg (sub=%d) at PC:%04x\n", sub, GETPC() );
+ }
+ }
+ break;
+
+ case 0x1d: //LDIMM to Rep regs
+ {
+ UINT32 sub = (opcode>>24)&0x3;
+ UINT32 imm = opcode&0xffffff;
+ if(sub == 0x00)
+ {
+ GETREPCNT() = imm;
+ }
+ else
+ {
+ logerror( "TGP: Unknown LDIMM REPCnt (sub=%d) at PC:%04x\n", sub, GETPC() );
+ }
+ }
+ break;
+
+ case 0x2f: /* Conditional Branches */
+ {
+ UINT32 cond = ( opcode >> 20 ) & 0x1f;
+ UINT32 subtype = ( opcode >> 16 ) & 0x0f;
+ UINT32 data = opcode & 0xffff;
+
+ if( COND(cpustate, cond) )
+ {
+ switch( subtype )
+ {
+ case 0x00: /* BRIF <addr> */
+ GETPC() = data - 1;
+ break;
+
+ case 0x02: /* BRIF indirect */
+ if ( data & 0x4000 )
+ data = GETREGS(cpustate,data&0x3f,0) - 1;
+ else
+ data = ((GETARAM()[data&0x3ff])&0xffff)-1;
+
+ /* if we're waiting for data, don't complete the instruction */
+ if ( GETFIFOWAIT() )
+ break;
+
+ GETPC() = data;
+ break;
+
+ case 0x04: /* BSIF <addr> */
+ GETPCS()[GETPCSP()] = GETPC();
+ GETPCSP()++;
+ GETPC() = data - 1;
+ break;
+
+ case 0x06: /* BSIF indirect */
+ GETPCS()[GETPCSP()] = GETPC();
+ GETPCSP()++;
+ if ( data & 0x4000 )
+ data = GETREGS(cpustate,data&0x3f,0) - 1;
+ else
+ data = ((GETARAM()[data&0x3ff])&0xffff)-1;
+
+ /* if we're waiting for data, don't complete the instruction */
+ if ( GETFIFOWAIT() )
+ break;
+
+ GETPC() = data;
+ break;
+
+ case 0x0a: /* RTIF */
+ --GETPCSP();
+ GETPC() = GETPCS()[GETPCSP()];
+ break;
+
+ case 0x0c: /* LDIF */
+ SETREGS(cpustate,((data>>9)&0x3f), GETARAM()[data&0x1FF] );
+ break;
+
+ case 0x0e: /* RIIF */
+ logerror( "TGP: RIIF unimplemented at PC:%04x\n", GETPC() );
+ break;
+
+ default:
+ logerror( "TGP: Unknown Branch opcode (subtype=%d) at PC:%04x\n", subtype, GETPC() );
+ break;
+ }
+ }
+ }
+ break;
+
+ case 0x3f: /* Inverse Conditional Branches */
+ {
+ UINT32 cond = ( opcode >> 20 ) & 0x1f;
+ UINT32 subtype = ( opcode >> 16 ) & 0x0f;
+ UINT32 data = opcode & 0xffff;
+
+ if( !COND(cpustate, cond) )
+ {
+ switch( subtype )
+ {
+ case 0x00: /* BRUL <addr> */
+ GETPC() = data - 1;
+ break;
+
+ case 0x02: /* BRUL indirect */
+ if ( data & 0x4000 )
+ data = GETREGS(cpustate,data&0x3f,0) - 1;
+ else
+ data = ((GETARAM()[data&0x3ff])&0xffff)-1;
+
+ /* if we're waiting for data, don't complete the instruction */
+ if ( GETFIFOWAIT() )
+ break;
+
+ GETPC() = data;
+ break;
+
+ case 0x04: /* BSUL <addr> */
+ GETPCS()[GETPCSP()] = GETPC();
+ GETPCSP()++;
+ GETPC() = data - 1;
+ break;
+
+ case 0x06: /* BSUL indirect */
+ GETPCS()[GETPCSP()] = GETPC();
+ GETPCSP()++;
+ if ( data & 0x4000 )
+ data = GETREGS(cpustate,data&0x3f,0) - 1;
+ else
+ data = ((GETARAM()[data&0x3ff])&0xffff)-1;
+
+ /* if we're waiting for data, don't complete the instruction */
+ if ( GETFIFOWAIT() )
+ break;
+
+ GETPC() = data;
+ break;
+
+ case 0x0a: /* RTUL */
+ --GETPCSP();
+ GETPC() = GETPCS()[GETPCSP()];
+ break;
+
+ case 0x0c: /* LDUL */
+ SETREGS(cpustate,((data>>9)&0x3f), GETARAM()[data&0x1FF] );
+ break;
+
+ case 0x0e: /* RIUL */
+ logerror( "TGP: RIIF unimplemented at PC:%04x\n", GETPC() );
+ break;
+
+ default:
+ logerror( "TGP: Unknown Branch opcode (subtype=%d) at PC:%04x\n", subtype, GETPC() );
+ break;
+ }
+ }
+ }
+ break;
+
+ default:
+ logerror( "TGP: unknown opcode %08x at PC:%04x\n", opcode, GETPC() );
+ break;
+ }
+
+ if ( GETFIFOWAIT() == 0 )
+ {
+ if( GETREPS() == 0 )
+ GETPC()++;
+ else
+ --GETREPS();
+
+ cpustate->icount--;
+ }
+ else
+ {
+ cpustate->icount = 0;
+ }
+ }
+}
+
+/***************************************************************************
+ Information Setters
+***************************************************************************/
+
+static CPU_SET_INFO( mb86233 )
+{
+ mb86233_state *cpustate = get_safe_token(device);
+
+ switch (state)
+ {
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + MB86233_PC: GETPC() = info->i; break;
+ case CPUINFO_INT_REGISTER + MB86233_A: GETA().u = info->i; break;
+ case CPUINFO_INT_REGISTER + MB86233_B: GETB().u = info->i; break;
+ case CPUINFO_INT_REGISTER + MB86233_P: GETP().u = info->i; break;
+ case CPUINFO_INT_REGISTER + MB86233_D: GETD().u = info->i; break;
+ case CPUINFO_INT_REGISTER + MB86233_REP: GETREPS() = info->i; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + MB86233_SP: GETPCSP() = info->i; break;
+ case CPUINFO_INT_REGISTER + MB86233_EB: GETEB() = info->i; break;
+ case CPUINFO_INT_REGISTER + MB86233_SHIFT: GETSHIFT() = info->i; break;
+ case CPUINFO_INT_REGISTER + MB86233_FLAGS: GETSR() = info->i; break;
+ case CPUINFO_INT_REGISTER + MB86233_R0: GETGPR(0) = info->i; break;
+ case CPUINFO_INT_REGISTER + MB86233_R1: GETGPR(1) = info->i; break;
+ case CPUINFO_INT_REGISTER + MB86233_R2: GETGPR(2) = info->i; break;
+ case CPUINFO_INT_REGISTER + MB86233_R3: GETGPR(3) = info->i; break;
+ case CPUINFO_INT_REGISTER + MB86233_R4: GETGPR(4) = info->i; break;
+ case CPUINFO_INT_REGISTER + MB86233_R5: GETGPR(5) = info->i; break;
+ case CPUINFO_INT_REGISTER + MB86233_R6: GETGPR(6) = info->i; break;
+ case CPUINFO_INT_REGISTER + MB86233_R7: GETGPR(7) = info->i; break;
+ case CPUINFO_INT_REGISTER + MB86233_R8: GETGPR(8) = info->i; break;
+ case CPUINFO_INT_REGISTER + MB86233_R9: GETGPR(9) = info->i; break;
+ case CPUINFO_INT_REGISTER + MB86233_R10: GETGPR(10) = info->i; break;
+ case CPUINFO_INT_REGISTER + MB86233_R11: GETGPR(11) = info->i; break;
+ case CPUINFO_INT_REGISTER + MB86233_R12: GETGPR(12) = info->i; break;
+ case CPUINFO_INT_REGISTER + MB86233_R13: GETGPR(13) = info->i; break;
+ case CPUINFO_INT_REGISTER + MB86233_R14: GETGPR(14) = info->i; break;
+ case CPUINFO_INT_REGISTER + MB86233_R15: GETGPR(15) = info->i; break;
+ }
+}
+
+/***************************************************************************
+ Information Getters
+***************************************************************************/
+
+CPU_GET_INFO( mb86233 )
+{
+ mb86233_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(mb86233_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 0; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 2; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = -2; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 32; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 32; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_PREVIOUSPC: /* not implemented */ break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + MB86233_PC: info->i = GETPC(); break;
+ case CPUINFO_INT_REGISTER + MB86233_A: info->i = GETA().u; break;
+ case CPUINFO_INT_REGISTER + MB86233_B: info->i = GETB().u; break;
+ case CPUINFO_INT_REGISTER + MB86233_P: info->i = GETP().u; break;
+ case CPUINFO_INT_REGISTER + MB86233_D: info->i = GETD().u; break;
+ case CPUINFO_INT_REGISTER + MB86233_REP: info->i = GETREPS(); break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + MB86233_SP: info->i = GETPCSP(); break;
+ case CPUINFO_INT_REGISTER + MB86233_EB: info->i = GETEB(); break;
+ case CPUINFO_INT_REGISTER + MB86233_SHIFT: info->i = GETSHIFT(); break;
+ case CPUINFO_INT_REGISTER + MB86233_FLAGS: info->i = GETSR(); break;
+ case CPUINFO_INT_REGISTER + MB86233_R0: info->i = GETGPR(0); break;
+ case CPUINFO_INT_REGISTER + MB86233_R1: info->i = GETGPR(1); break;
+ case CPUINFO_INT_REGISTER + MB86233_R2: info->i = GETGPR(2); break;
+ case CPUINFO_INT_REGISTER + MB86233_R3: info->i = GETGPR(3); break;
+ case CPUINFO_INT_REGISTER + MB86233_R4: info->i = GETGPR(4); break;
+ case CPUINFO_INT_REGISTER + MB86233_R5: info->i = GETGPR(5); break;
+ case CPUINFO_INT_REGISTER + MB86233_R6: info->i = GETGPR(6); break;
+ case CPUINFO_INT_REGISTER + MB86233_R7: info->i = GETGPR(7); break;
+ case CPUINFO_INT_REGISTER + MB86233_R8: info->i = GETGPR(8); break;
+ case CPUINFO_INT_REGISTER + MB86233_R9: info->i = GETGPR(9); break;
+ case CPUINFO_INT_REGISTER + MB86233_R10: info->i = GETGPR(10); break;
+ case CPUINFO_INT_REGISTER + MB86233_R11: info->i = GETGPR(11); break;
+ case CPUINFO_INT_REGISTER + MB86233_R12: info->i = GETGPR(12); break;
+ case CPUINFO_INT_REGISTER + MB86233_R13: info->i = GETGPR(13); break;
+ case CPUINFO_INT_REGISTER + MB86233_R14: info->i = GETGPR(14); break;
+ case CPUINFO_INT_REGISTER + MB86233_R15: info->i = GETGPR(15); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(mb86233); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(mb86233); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(mb86233); break;
+ case CPUINFO_FCT_EXIT: info->exit = NULL; break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(mb86233); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(mb86233); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "MB86233"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Fujitsu MB86233"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Miguel Angel Horna and Ernesto Corvi"); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c", (GETSR()&SIGN_FLAG) ? 'N' : 'n', (GETSR()&ZERO_FLAG) ? 'Z' : 'z' );
+ break;
+
+ case CPUINFO_STR_REGISTER + MB86233_FLAGS:
+ sprintf(info->s, "FL:%c%c", (GETSR()&SIGN_FLAG) ? 'N' : 'n', (GETSR()&ZERO_FLAG) ? 'Z' : 'z' );
+ break;
+
+ case CPUINFO_STR_REGISTER + MB86233_PC: sprintf(info->s, "PC:%04X", GETPC()); break;
+ case CPUINFO_STR_REGISTER + MB86233_A: sprintf(info->s, "PA:%08X (%f)", GETA().u, GETA().f); break;
+ case CPUINFO_STR_REGISTER + MB86233_B: sprintf(info->s, "PB:%08X (%f)", GETB().u, GETB().f); break;
+ case CPUINFO_STR_REGISTER + MB86233_P: sprintf(info->s, "PP:%08X (%f)", GETP().u, GETP().f); break;
+ case CPUINFO_STR_REGISTER + MB86233_D: sprintf(info->s, "PD:%08X (%f)", GETD().u, GETD().f); break;
+ case CPUINFO_STR_REGISTER + MB86233_REP: sprintf(info->s, "REPS:%08X", GETREPS()); break;
+ case CPUINFO_STR_REGISTER + MB86233_SP: sprintf(info->s, "PCSP:%1X", GETPCSP()); break;
+ case CPUINFO_STR_REGISTER + MB86233_EB: sprintf(info->s, "EB:%08X", GETEB()); break;
+ case CPUINFO_STR_REGISTER + MB86233_SHIFT: sprintf(info->s, "SHIFT:%08X", GETSHIFT()); break;
+ case CPUINFO_STR_REGISTER + MB86233_R0: sprintf(info->s, "R0:%08X", GETGPR(0)); break;
+ case CPUINFO_STR_REGISTER + MB86233_R1: sprintf(info->s, "R1:%08X", GETGPR(1)); break;
+ case CPUINFO_STR_REGISTER + MB86233_R2: sprintf(info->s, "R2:%08X", GETGPR(2)); break;
+ case CPUINFO_STR_REGISTER + MB86233_R3: sprintf(info->s, "R3:%08X", GETGPR(3)); break;
+ case CPUINFO_STR_REGISTER + MB86233_R4: sprintf(info->s, "R4:%08X", GETGPR(4)); break;
+ case CPUINFO_STR_REGISTER + MB86233_R5: sprintf(info->s, "R5:%08X", GETGPR(5)); break;
+ case CPUINFO_STR_REGISTER + MB86233_R6: sprintf(info->s, "R6:%08X", GETGPR(6)); break;
+ case CPUINFO_STR_REGISTER + MB86233_R7: sprintf(info->s, "R7:%08X", GETGPR(7)); break;
+ case CPUINFO_STR_REGISTER + MB86233_R8: sprintf(info->s, "R8:%08X", GETGPR(8)); break;
+ case CPUINFO_STR_REGISTER + MB86233_R9: sprintf(info->s, "R9:%08X", GETGPR(9)); break;
+ case CPUINFO_STR_REGISTER + MB86233_R10: sprintf(info->s, "R10:%08X", GETGPR(10)); break;
+ case CPUINFO_STR_REGISTER + MB86233_R11: sprintf(info->s, "R11:%08X", GETGPR(11)); break;
+ case CPUINFO_STR_REGISTER + MB86233_R12: sprintf(info->s, "R12:%08X", GETGPR(12)); break;
+ case CPUINFO_STR_REGISTER + MB86233_R13: sprintf(info->s, "R13:%08X", GETGPR(13)); break;
+ case CPUINFO_STR_REGISTER + MB86233_R14: sprintf(info->s, "R14:%08X", GETGPR(14)); break;
+ case CPUINFO_STR_REGISTER + MB86233_R15: sprintf(info->s, "R15:%08X", GETGPR(15)); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(MB86233, mb86233);
diff --git a/trunk/src/emu/cpu/mb86233/mb86233.h b/trunk/src/emu/cpu/mb86233/mb86233.h
new file mode 100644
index 00000000000..19631f900cc
--- /dev/null
+++ b/trunk/src/emu/cpu/mb86233/mb86233.h
@@ -0,0 +1,58 @@
+#pragma once
+
+#ifndef __MB86233_H__
+#define __MB86233_H__
+
+
+/***************************************************************************
+ REGISTER ENUMERATION
+***************************************************************************/
+
+enum
+{
+ MB86233_PC=1,
+ MB86233_A,
+ MB86233_B,
+ MB86233_D,
+ MB86233_P,
+ MB86233_REP,
+ MB86233_SP,
+ MB86233_EB,
+ MB86233_SHIFT,
+ MB86233_FLAGS,
+ MB86233_R0,
+ MB86233_R1,
+ MB86233_R2,
+ MB86233_R3,
+ MB86233_R4,
+ MB86233_R5,
+ MB86233_R6,
+ MB86233_R7,
+ MB86233_R8,
+ MB86233_R9,
+ MB86233_R10,
+ MB86233_R11,
+ MB86233_R12,
+ MB86233_R13,
+ MB86233_R14,
+ MB86233_R15
+};
+
+/***************************************************************************
+ STRUCTURES
+***************************************************************************/
+
+typedef int (*mb86233_fifo_read_func)(device_t *device, UINT32 *data);
+typedef void (*mb86233_fifo_write_func)(device_t *device, UINT32 data);
+
+typedef struct _mb86233_cpu_core mb86233_cpu_core;
+struct _mb86233_cpu_core
+{
+ mb86233_fifo_read_func fifo_read_cb;
+ mb86233_fifo_write_func fifo_write_cb;
+ const char *tablergn;
+};
+
+DECLARE_LEGACY_CPU_DEVICE(MB86233, mb86233);
+
+#endif /* __MB86233_H__ */
diff --git a/trunk/src/emu/cpu/mb86233/mb86233d.c b/trunk/src/emu/cpu/mb86233/mb86233d.c
new file mode 100644
index 00000000000..40c41adb410
--- /dev/null
+++ b/trunk/src/emu/cpu/mb86233/mb86233d.c
@@ -0,0 +1,782 @@
+#include "emu.h"
+#include "debugger.h"
+#include "mb86233.h"
+
+static char * COND(unsigned int cond)
+{
+ static char bufs[4][256];
+ static int bufindex = 0;
+ char *buf = &bufs[bufindex++][0];
+
+ bufindex &= 3;
+
+ switch(cond)
+ {
+ case 0x16:
+ sprintf(buf,"always");
+ return buf;
+
+ case 0x00:
+ sprintf(buf,"eq");
+ return buf;
+
+ case 0x01:
+ sprintf(buf,"ge");
+ return buf;
+
+ case 0x02:
+ sprintf(buf,"le");
+ return buf;
+
+ case 0x06:
+ sprintf(buf,"never");
+ return buf;
+
+ case 0x10:
+ sprintf(buf,"(--r12)!=0");
+ return buf;
+
+ case 0x11:
+ sprintf(buf,"(--r13)!=0");
+ return buf;
+ }
+
+ sprintf(buf,"unk (%x)",cond);
+ return buf;
+}
+
+static char * REGS( UINT32 reg, int IsSource )
+{
+ static char bufs[4][256];
+ static int bufindex = 0;
+ char *buf = &bufs[bufindex++][0];
+ int mode = (reg >> 6 ) & 0x07;
+
+ bufindex &= 3;
+
+ reg &= 0x3f;
+
+ if ( mode == 0 || mode == 1 || mode == 3 )
+ {
+ if ( reg < 0x10 )
+ {
+ sprintf(buf,"r%d",reg);
+ return buf;
+ }
+
+ switch(reg)
+ {
+ case 0x10:
+ sprintf(buf,"a");
+ break;
+
+ case 0x11:
+ sprintf(buf,"a.e");
+ break;
+
+ case 0x12:
+ sprintf(buf,"a.m");
+ break;
+
+ case 0x13:
+ sprintf(buf,"b");
+ break;
+
+ case 0x14:
+ sprintf(buf,"b.e");
+ break;
+
+ case 0x15:
+ sprintf(buf,"b.m");
+ break;
+
+ case 0x19:
+ sprintf(buf,"d");
+ break;
+
+ case 0x1a:
+ sprintf(buf,"d.e");
+ break;
+
+ case 0x1b:
+ sprintf(buf,"d.m");
+ break;
+
+ case 0x1c:
+ sprintf(buf,"p");
+ break;
+
+ case 0x1d:
+ sprintf(buf,"p.e");
+ break;
+
+ case 0x1e:
+ sprintf(buf,"p.m");
+ break;
+
+ case 0x1f:
+ sprintf(buf,"shift");
+ break;
+
+ case 0x20:
+ sprintf(buf,"parport");
+ break;
+
+ case 0x21:
+ sprintf(buf,"FIn");
+ break;
+
+ case 0x22:
+ sprintf(buf,"FOut");
+ break;
+
+ case 0x23:
+ sprintf(buf,"EB");
+ break;
+
+ default:
+ sprintf(buf,"Unkreg (%x)",reg);
+ break;
+ }
+ }
+ else if ( mode == 2 )
+ {
+ char *p = buf;
+
+ p += sprintf(p,"0x%x+",reg & 0x1f);
+
+ if ( IsSource )
+ {
+ if ( !( reg & 0x20 ) )
+ p += sprintf(p,"r0+");
+
+ p += sprintf(p,"r2");
+ }
+ else
+ {
+ if ( !( reg & 0x20 ) )
+ p += sprintf(p,"r1+");
+
+ p += sprintf(p,"r3");
+ }
+ }
+ else if ( mode == 6 )
+ {
+ char *p = buf;
+
+ if ( IsSource )
+ {
+ if ( !( reg & 0x20 ) )
+ p += sprintf(p,"r0+");
+
+ p += sprintf(p,"r2");
+ }
+ else
+ {
+ if ( !( reg & 0x20 ) )
+ p += sprintf(p,"r1+");
+
+ p += sprintf(p,"r3");
+ }
+
+ if ( reg & 0x10 )
+ p += sprintf(p,"--%d", 0x20 - ( reg & 0x1f ) );
+ else
+ p += sprintf(p,"++%d", reg & 0x1f );
+ }
+ else
+ {
+ sprintf(buf,"UNKMOD %x (0x%x)", mode, reg);
+ }
+
+ return buf;
+}
+
+static char * INDIRECT( UINT32 reg, int IsSource )
+{
+ static char bufs[4][256];
+ static int bufindex = 0;
+ char *buf = &bufs[bufindex++][0];
+ int mode = ( reg >> 6 ) & 0x07;
+
+ bufindex &= 3;
+
+ if ( mode == 0 || mode == 3 || mode == 1)
+ {
+ sprintf(buf,"0x%x",reg);
+ }
+ else if ( mode == 2 )
+ {
+ char *p = buf;
+
+ p += sprintf(p,"0x%x+",reg&0x1f);
+
+ if ( IsSource )
+ {
+ if ( !(reg & 0x20) )
+ p += sprintf(p,"r0+");
+
+ p += sprintf(p,"r2");
+ }
+ else
+ {
+ if ( !(reg & 0x20) )
+ p += sprintf(p,"r1+");
+
+ p += sprintf(p,"r3");
+ }
+ }
+ else if ( mode == 6 || mode == 7 )
+ {
+ char *p = buf;
+
+ if ( IsSource )
+ {
+ if ( !( reg & 0x20 ) )
+ p += sprintf(p,"r0+");
+
+ p += sprintf(p,"r2");
+ }
+ else
+ {
+ if( !( reg & 0x20 ) )
+ p += sprintf(p,"r1+");
+
+ p += sprintf(p,"r3");
+ }
+
+ if ( reg & 0x10 )
+ p += sprintf(p,"--%d",0x20 - ( reg & 0x1f ));
+ else
+ p += sprintf(p,"++%d",reg & 0x1f);
+ }
+ else
+ {
+ sprintf(buf,"UNKMOD %x (0x%x)", mode, reg);
+ }
+
+ return buf;
+}
+
+
+static char * ALU( UINT32 alu)
+{
+ static char bufs[4][256];
+ static int bufindex = 0;
+ char *buf = &bufs[bufindex++][0];
+
+ bufindex &= 3;
+
+ switch( alu )
+ {
+ case 0x0:
+ buf[0] = 0;
+ break;
+
+ case 0x1:
+ sprintf(buf,"d=d&a");
+ break;
+
+ case 0x2:
+ sprintf(buf,"d=d|a");
+ break;
+
+ case 0x3:
+ sprintf(buf,"d=d^a");
+ break;
+
+ case 0x5:
+ sprintf(buf,"cmp d,a");
+ break;
+
+ case 0x6:
+ sprintf(buf,"d=d+a");
+ break;
+
+ case 0x7:
+ sprintf(buf,"d=d-a");
+ break;
+
+ case 0x8:
+ sprintf(buf,"p=a*b");
+ break;
+
+ case 0x9:
+ sprintf(buf,"d=d+p, p=a*b");
+ break;
+
+ case 0xa:
+ sprintf(buf,"d=d-p, p=a*b");
+ break;
+
+ case 0xb:
+ sprintf(buf,"d=fabs d");
+ break;
+
+ case 0xc:
+ sprintf(buf,"d=d+p");
+ break;
+
+ case 0xd:
+ sprintf(buf,"d=p, p=a*b");
+ break;
+
+ case 0xe:
+ sprintf(buf,"d=float(d)");
+ break;
+
+ case 0xf:
+ sprintf(buf,"d=int(d)");
+ break;
+
+ case 0x10:
+ sprintf(buf,"d=d/a");
+ break;
+
+ case 0x11:
+ sprintf(buf,"d=-d");
+ break;
+
+ case 0x13:
+ sprintf(buf,"d=a+b");
+ break;
+
+ case 0x14:
+ sprintf(buf,"d=b-a");
+ break;
+
+ case 0x16:
+ sprintf(buf,"d=(lsr d,shift)");
+ break;
+
+ case 0x17:
+ sprintf(buf,"d=(lsl d,shift)");
+ break;
+
+ case 0x18:
+ sprintf(buf,"d=(asr d,shift)");
+ break;
+
+ case 0x1a:
+ sprintf(buf,"d=d+a (int)");
+ break;
+
+ case 0x1b:
+ sprintf(buf,"d=d-a (int)");
+ break;
+
+ default:
+ sprintf(buf,"ALU UNK(%x)",alu);
+ break;
+ }
+
+ return buf;
+}
+
+static unsigned dasm_mb86233(char *buffer, UINT32 opcode )
+{
+ char *p = buffer;
+ UINT32 grp = ( opcode >> 26 ) & 0x3f;
+
+ switch( grp )
+ {
+ case 0x0: /* Dual move */
+ {
+ UINT32 r1=opcode & 0x1ff;
+ UINT32 r2=(opcode>>9) & 0x7f;
+ UINT32 alu=(opcode>>21) & 0x1f;
+ UINT32 op=(opcode>>16) & 0x1f;
+
+ if ( alu != 0 )
+ p += sprintf(p, "%s, ", ALU(alu) );
+
+ switch( op )
+ {
+ case 0x0c: /* a = RAM[addr], b = BRAM[addr] */
+ p += sprintf(p,"LAB RAM(0x%x)->a,BRAM(0x%x)->b",r1,r2);
+ break;
+
+ case 0x0d: /* a = RAM[addr], b = BRAM[addr] */
+ p += sprintf(p,"LAB RAM(0x%x)->a,BRAM(%s)->b",r1,INDIRECT(r2|(2<<6),0));
+ break;
+
+ case 0x0f: /* a = RAM[addr], b = BRAM[reg] */
+ p += sprintf(p,"LAB RAM(0x%x)->a,BRAM(%s)->b",r1,INDIRECT(r2|(6<<6),0));
+ break;
+
+ case 0x10: /* a = BRAM[reg], b = RAM[addr] */
+ p += sprintf(p,"LAB BRAM(%s)->a,RAM(0x%x)->b",INDIRECT(r1,1),r2);
+ break;
+
+ default:
+ p += sprintf(p,"UNKDUAL (%x)",op);
+ break;
+ }
+ }
+ break;
+
+ case 0x7: /* LD/MOV */
+ {
+ UINT32 r1=opcode & 0x1ff;
+ UINT32 r2=(opcode>>9) & 0x7f;
+ UINT32 alu=(opcode>>21) & 0x1f;
+ UINT32 op=(opcode>>16) & 0x1f;
+
+ if ( alu != 0 )
+ {
+ p += sprintf(p, "%s", ALU(alu) );
+
+ if ( !(op == 0x1f && r1 == 0x10 && r2 == 0x0f) )
+ p += sprintf(p, ", ");
+ }
+
+ switch(op)
+ {
+ case 0x03: /* RAM->External Indirect */
+ {
+ p += sprintf(p,"MOV RAM(0x%x)->E(EB+%s)",r1,INDIRECT(r2|(6<<6),0));
+ }
+ break;
+
+ case 0x04: /* MOV RAM->External */
+ {
+ p += sprintf(p,"MOV RAM(0x%x)->E(EB+0x%x)",r1,r2);
+ }
+ break;
+
+ case 0x07: /* RAMInd->External */
+ {
+ p += sprintf(p,"MOV RAM(%s)->E(EB+%s)",INDIRECT(r1,1),INDIRECT(r2|(6<<6),0));
+ }
+ break;
+
+ case 0x08: /* External->RAM */
+ {
+ p += sprintf(p,"MOV EXT(EB+");
+ p += sprintf(p,"%s",INDIRECT(r1,1));
+ p += sprintf(p,")->RAM(0x%x)",r2);
+ }
+ break;
+
+ case 0x0b: /* External->RAMInd */
+ {
+ int mode = ( r1 >> 6 ) & 0x07;
+
+ p += sprintf(p,"MOV EXT(EB+");
+
+ if ( mode == 0 || mode == 3 || mode == 1 )
+ p += sprintf(p,"RAM(");
+
+ p += sprintf(p,"%s",INDIRECT(r1,1));
+
+ if ( mode == 0 || mode == 3 || mode == 1)
+ p += sprintf(p,")");
+
+ p += sprintf(p,")->RAM(%s)",INDIRECT(r2|(6<<6),0));
+ }
+ break;
+
+ case 0x0c: /* MOV RAM->BRAM */
+ p += sprintf(p,"MOV RAM(0x%x)->BRAM(0x%x)",r1,r2);
+ break;
+
+ case 0x0f: /* MOV RAMInd->BRAMInd */
+ p += sprintf(p,"MOV RAM(%s)->BRAM(%s)",INDIRECT(r1,1),INDIRECT(r2|(6<<6),0));
+ break;
+
+ case 0x10: /* MOV BRAMInd->RAM */
+ p += sprintf(p,"MOV BRAM(%s)->RAM(0x%x)",INDIRECT(r1,1),r2);
+ break;
+
+ case 0x13: /* MOV BRAMInd->RAMInd */
+ p += sprintf(p,"MOV BRAM(%s)->RAM(%s)",INDIRECT(r1,1),INDIRECT(r2|(6<<6),0));
+ break;
+
+ case 0x1c: /* MOV Reg->RAMInd */
+ if ( ( r2 >> 6 ) & 0x01)
+ {
+ p += sprintf(p,"MOV %s->EXT(EB+%s)",REGS(r2,1),INDIRECT(r1,0));
+ }
+ else
+ {
+ p += sprintf(p,"MOV %s->RAM(%s)",REGS(r2,1),INDIRECT(r1,0));
+ }
+ break;
+
+ case 0x1d: /* MOV RAM->Reg */
+ {
+ if ( r1 & 0x180 )
+ {
+ p += sprintf(p,"MOV RAM(%s)->%s",REGS(r1,0),REGS(r2,0));
+ }
+ else
+ {
+ p += sprintf(p,"MOV RAM(0x%x)->%s",r1,REGS(r2,0));
+ }
+ }
+ break;
+
+ case 0x1e: /* External->Reg */
+ {
+ int mode2 = (r2 >> 6) & 1;
+ p += sprintf(p,"MOV EXT(EB+%s)->%s",INDIRECT(r1,mode2),REGS(r2,0));
+ }
+ break;
+
+ case 0x1f: /* MOV Reg->Reg */
+ if ( !(r1 == 0x10 && r2 == 0x0f) )
+ {
+ p += sprintf(p,"MOV %s->%s",REGS(r1,1),REGS(r2,0));
+ }
+ break;
+
+ default:
+ p += sprintf(p,"UNKMV (0x%x)",op);
+ break;
+ }
+ }
+ break;
+
+ case 0x0e: /* Load 24 bit val */
+ {
+ UINT32 sub=(opcode>>24)&0x3;
+ static const char regs[4] = { 'p', 'a', 'b', 'd' };
+
+ p += sprintf(p,"LDIMM24 0x%X->%c",opcode&0xffffff, regs[sub]);
+ }
+ break;
+
+ case 0x0f: /* repeat */
+ {
+ UINT32 alu = ( opcode >> 20 ) & 0x1f;
+ UINT32 sub2 = ( opcode >> 16 ) & 0x0f;
+
+ if ( alu != 0 )
+ p += sprintf(p, "%s, ", ALU(alu) );
+
+ if ( sub2 == 0x00 )
+ {
+ p += sprintf(p,"CLEAR ");
+
+ switch( opcode & 0x3f )
+ {
+ case 0x04: p += sprintf(p, "a" ); break;
+ case 0x08: p += sprintf(p, "b" ); break;
+ case 0x10: p += sprintf(p, "d" ); break;
+ default: p += sprintf(p, "UNKNOWN REG(%x)",opcode&0x3F); break;
+ }
+ }
+ else if ( sub2 == 0x02 )
+ p += sprintf(p,"CLRFLAG 0x%x",opcode&0xffff);
+ else if ( sub2==0x4 )
+ {
+ if ( (opcode & 0xfff) == 0 )
+ p += sprintf(p,"REP 0x100");
+ else
+ p += sprintf(p,"REP 0x%x",opcode&0xff);
+ }
+ else if ( sub2 == 0x06 )
+ p += sprintf(p,"SETFLAG 0x%x",opcode&0xffff);
+ }
+ break;
+
+ case 0x10:
+ {
+ UINT32 dst=(opcode>>24)&0xf;
+ UINT32 imm=(opcode)&0xFFFF;
+
+ if ( dst <= 3 )
+ p += sprintf(p,"LDIMM 0x%x->r%d",imm,dst);
+ else
+ p += sprintf(p,"LDIMM 0x%x->UNKDST(0x%x)",imm,dst);
+ }
+ break;
+
+ case 0x13:
+ {
+ UINT32 sub = ( opcode >> 24 ) & 0x03;
+
+ p += sprintf(p,"LDIMM 0x%X->",opcode&0xffffff);
+
+ if ( sub == 0 ) p += sprintf(p,"r12");
+ else if ( sub == 1 ) p += sprintf(p,"r13");
+ else p += sprintf(p,"UNKREG(%x)", sub);
+ }
+ break;
+
+ case 0x14:
+ {
+ UINT32 sub = ( opcode >> 24 ) & 0x03;
+
+ p += sprintf(p,"LDIMM 0x%X->",opcode&0xffffff);
+
+ if ( sub == 0 ) p += sprintf(p,"a.exp");
+ else if ( sub == 1 ) p += sprintf(p,"a.e");
+ else if ( sub == 2 ) p += sprintf(p,"a.m");
+ else p += sprintf(p,"UNKREG(%x)", sub);
+ }
+ break;
+
+ case 0x15:
+ {
+ UINT32 sub = ( opcode >> 24 ) & 0x03;
+
+ p += sprintf(p,"LDIMM 0x%X->",opcode&0xffffff);
+
+ if ( sub == 0 ) p += sprintf(p,"b.exp");
+ else if ( sub == 1 ) p += sprintf(p,"b.e");
+ else if ( sub == 2 ) p += sprintf(p,"b.m");
+ else p += sprintf(p,"UNKREG(%x)", sub);
+ }
+ break;
+
+ case 0x16:
+ {
+ UINT32 sub = ( opcode >> 24 ) & 0x03;
+
+ p += sprintf(p,"LDIMM 0x%X->",opcode&0xffffff);
+
+ if ( sub == 2 ) p += sprintf(p,"d.e");
+ else if ( sub == 3 ) p += sprintf(p,"d.m");
+ else p += sprintf(p,"UNKREG(%x)", sub);
+ }
+ break;
+
+ case 0x17:
+ {
+ UINT32 sub = ( opcode >> 24 ) & 0x03;
+
+ p += sprintf(p,"LDIMM 0x%X->",opcode&0xffffff);
+
+ if ( sub == 0x03 ) p += sprintf(p,"shift");
+ else p += sprintf(p,"UNKREG(%x)", sub);
+ }
+ break;
+
+ case 0x18:
+ {
+ UINT32 sub = ( opcode >> 24 ) & 0x03;
+
+ p += sprintf(p,"LDIMM24 0x%X->",opcode&0xffffff);
+
+ if ( sub == 0x03 ) p += sprintf(p,"EB");
+ else p += sprintf(p,"UNKREG(%x)", sub);
+ }
+ break;
+
+ case 0x2f:
+ {
+ UINT32 cond = ( opcode >> 20 ) & 0x1f;
+ UINT32 subtype = ( opcode >> 16 ) & 0x0f;
+ UINT32 data = opcode & 0xffff;
+
+ switch( subtype )
+ {
+ case 0:
+ p += sprintf(p,"BRIF %s 0x%X", COND(cond), data);
+ break;
+
+ case 2:
+ p += sprintf(p,"BRIF %s ", COND(cond));
+ if ( data & 0x4000 )
+ p += sprintf(p,"%s",REGS(data&0x3f,0));
+ else
+ p += sprintf(p,"RAM(0x%x)",data);
+ break;
+
+ case 4:
+ p += sprintf(p,"BSIF %s 0x%X", COND(cond), data);
+ break;
+
+ case 0x6:
+ p += sprintf(p,"BSIF %s ", COND(cond));
+ if ( data & 0x4000 )
+ p += sprintf(p,"%s",REGS(data&0x3f,0));
+ else
+ p += sprintf(p,"RAM(0x%x)",data);
+ break;
+
+ case 0xa:
+ p += sprintf(p,"RTIF %s", COND(cond));
+ break;
+
+ case 0xc:
+ p += sprintf(p,"LDIF %s RAM(0x%x)->%s", COND(cond),data&0x1ff,REGS((data>>9)&0x3f,0));
+ break;
+
+ case 0xe:
+ p += sprintf(p,"RIIF %s", COND(cond));
+ break;
+
+ default:
+ p += sprintf(p,"UNKG5 (%x cond %x)",subtype,cond);
+ break;
+ }
+ }
+ break;
+
+ case 0x3f:
+ {
+ UINT32 cond = ( opcode >> 20 ) & 0x1f;
+ UINT32 subtype = ( opcode >> 16 ) & 0x0f;
+ UINT32 data = opcode & 0xffff;
+
+ switch( subtype )
+ {
+ case 0:
+ p += sprintf(p,"BRUL %s 0x%X", COND(cond), data);
+ break;
+
+ case 2:
+ p += sprintf(p,"BRUL %s ", COND(cond));
+ if ( data & 0x4000 )
+ p += sprintf(p,"%s",REGS(data&0x3f,0));
+ else
+ p += sprintf(p,"RAM(0x%x)",data);
+ break;
+
+ case 4:
+ p += sprintf(p,"BSUL %s 0x%X", COND(cond), data);
+ break;
+
+ case 0x6:
+ p += sprintf(p,"BSUL %s ", COND(cond));
+ if ( data & 0x4000 )
+ p += sprintf(p,"%s",REGS(data&0x3f,0));
+ else
+ p += sprintf(p,"RAM(0x%x)",data);
+ break;
+
+ case 0xa:
+ p += sprintf(p,"RTUL %s", COND(cond));
+ break;
+
+ case 0xc:
+ p += sprintf(p,"LDUL %s RAM(0x%x)->%s", COND(cond),data&0x1ff,REGS((data>>9)&0x3f,0));
+ break;
+
+ case 0xe:
+ p += sprintf(p,"RIUL %s", COND(cond));
+ break;
+
+ default:
+ p += sprintf(p,"UNKG5 (%x cond %x)",subtype,cond);
+ break;
+ }
+ }
+ break;
+
+ default:
+ p += sprintf(p,"UNKOP");
+ break;
+ }
+
+ return (1 | DASMFLAG_SUPPORTED);
+}
+
+CPU_DISASSEMBLE( mb86233 )
+{
+ UINT32 op = *(UINT32 *)oprom;
+ op = LITTLE_ENDIANIZE_INT32(op);
+ return dasm_mb86233(buffer, op);
+}
diff --git a/trunk/src/emu/cpu/mb88xx/mb88dasm.c b/trunk/src/emu/cpu/mb88xx/mb88dasm.c
new file mode 100644
index 00000000000..a0459a7cc20
--- /dev/null
+++ b/trunk/src/emu/cpu/mb88xx/mb88dasm.c
@@ -0,0 +1,222 @@
+/*******************************************************************************
+
+ mb88dasm.c
+ Core implementation for the portable Fujitsu MB88xx series MCU disassembler.
+
+ Written by Ernesto Corvi
+
+*******************************************************************************/
+
+#include "emu.h"
+#include "mb88xx.h"
+
+
+CPU_DISASSEMBLE( mb88 )
+{
+ unsigned startpc = pc;
+ UINT8 op = oprom[pc++ - startpc];
+ UINT8 arg = oprom[pc - startpc];
+
+ switch( op )
+ {
+ case 0x00: sprintf( buffer, "nop" ); break;
+ case 0x01: sprintf( buffer, "outO (PortO<=A)" ); break;
+ case 0x02: sprintf( buffer, "outP" ); break;
+ case 0x03: sprintf( buffer, "outR (PortR[Y]<=A)" ); break;
+ case 0x04: sprintf( buffer, "tay (Y<=A)" ); break;
+ case 0x05: sprintf( buffer, "tath (TH<=A)" ); break;
+ case 0x06: sprintf( buffer, "tatl (TL<=A)" ); break;
+ case 0x07: sprintf( buffer, "tas (SB<=A)" ); break;
+ case 0x08: sprintf( buffer, "icy (Y++)" ); break;
+ case 0x09: sprintf( buffer, "icm (M[X,Y]++)" ); break;
+ case 0x0A: sprintf( buffer, "stic (M[X,Y]<=A; Y++)" ); break;
+ case 0x0B: sprintf( buffer, "x (A<=>M[X,Y])" ); break;
+ case 0x0C: sprintf( buffer, "rol" ); break;
+ case 0x0D: sprintf( buffer, "load (A<=M[X,Y])" ); break;
+ case 0x0E: sprintf( buffer, "adc (A<=A+M[X,Y]+cf)" ); break;
+ case 0x0F: sprintf( buffer, "and (A<=A & M[X,Y])" ); break;
+ case 0x10: sprintf( buffer, "daa (A<=A+6 if (A>9 | cf=1)" ); break;
+ case 0x11: sprintf( buffer, "das (A<=A+10 if (A>9 | cf=1)" ); break;
+ case 0x12: sprintf( buffer, "inK (A<=PortK)" ); break;
+ case 0x13: sprintf( buffer, "inR (A<=PortR[Y])" ); break;
+ case 0x14: sprintf( buffer, "tya (A<=Y)" ); break;
+ case 0x15: sprintf( buffer, "ttha (A<=TH)" ); break;
+ case 0x16: sprintf( buffer, "ttla (A<=TL)" ); break;
+ case 0x17: sprintf( buffer, "tsa (A<=S)" ); break;
+ case 0x18: sprintf( buffer, "dcy (Y--)" ); break;
+ case 0x19: sprintf( buffer, "dcm (M[X,Y]--)" ); break;
+ case 0x1A: sprintf( buffer, "stdc (M[X,Y]<=A; Y--)" ); break;
+ case 0x1B: sprintf( buffer, "xx (A<=>X)" ); break;
+ case 0x1C: sprintf( buffer, "ror" ); break;
+ case 0x1D: sprintf( buffer, "store (M[X,Y]<=A)" ); break;
+ case 0x1E: sprintf( buffer, "sbc (A<=M[X,Y]-A-cf)" ); break;
+ case 0x1F: sprintf( buffer, "or (A<=A | M[X,Y])" ); break;
+ case 0x20: sprintf( buffer, "setR (PortR bit[Y]<=1)" ); break;
+ case 0x21: sprintf( buffer, "setc (cf<=1)" ); break;
+ case 0x22: sprintf( buffer, "rstR (PortR bit[Y]<=0)" ); break;
+ case 0x23: sprintf( buffer, "rstc (cf<=0)" ); break;
+ case 0x24: sprintf( buffer, "tstR (st<=PortR bit[Y])" ); break;
+ case 0x25: sprintf( buffer, "tsti (st<=IRQ Line)" ); break;
+ case 0x26: sprintf( buffer, "tstv (st<=vf)" ); break;
+ case 0x27: sprintf( buffer, "tsts (st<=sf)" ); break;
+ case 0x28: sprintf( buffer, "tstc (st<=cf)" ); break;
+ case 0x29: sprintf( buffer, "tstz (st<=zf)" ); break;
+ case 0x2A: sprintf( buffer, "sts (M[X,Y]<=SB)" ); break;
+ case 0x2B: sprintf( buffer, "ls (SB<=M[X,Y])" ); break;
+ case 0x2C: sprintf( buffer, "rts" ); break;
+ case 0x2D: sprintf( buffer, "neg (A=-A)" ); break;
+ case 0x2E: sprintf( buffer, "c (A==M[X,Y])" ); break;
+ case 0x2F: sprintf( buffer, "eor (A ^ M[X,Y])" ); break;
+ case 0x30:
+ case 0x31:
+ case 0x32:
+ case 0x33: sprintf( buffer, "sbit%d (M[X,Y] bit%d=1)", op&3, op&3 ); break;
+ case 0x34:
+ case 0x35:
+ case 0x36:
+ case 0x37: sprintf( buffer, "rbit%d (M[X,Y] bit%d=0)", op&3, op&3 ); break;
+ case 0x38:
+ case 0x39:
+ case 0x3A:
+ case 0x3B: sprintf( buffer, "tbit%d (M[X,Y] bit%d == 1)", op&3, op&3 ); break;
+ case 0x3C: sprintf( buffer, "rti" ); break;
+ case 0x3D: sprintf( buffer, "jpa #$%02x (jump always)", arg ); pc++; break;
+ case 0x3E: sprintf( buffer, "en #$%02x (enable bits)", arg ); pc++; break;
+ case 0x3F: sprintf( buffer, "dis #$%02x (disable bits)", arg ); pc++; break;
+ case 0x40:
+ case 0x41:
+ case 0x42:
+ case 0x43: sprintf( buffer, "setd%d (PortR bit%d<=1)", op&3, op&3 ); break;
+ case 0x44:
+ case 0x45:
+ case 0x46:
+ case 0x47: sprintf( buffer, "rstd%d (PortR bit%d<=0)", op&3, op&3 ); break;
+ case 0x48:
+ case 0x49:
+ case 0x4A:
+ case 0x4B: sprintf( buffer, "tstd%d (PortR bit%d == 1)", (op&3)+8, (op&3)+8 ); break;
+ case 0x4C:
+ case 0x4D:
+ case 0x4E:
+ case 0x4F: sprintf( buffer, "tba%d (A bit%d == 1)", op&3, op&3 ); break;
+ case 0x50:
+ case 0x51:
+ case 0x52:
+ case 0x53: sprintf( buffer, "xd%d (A<=>M[0,%d])", op&3, op&3 ); break;
+ case 0x54:
+ case 0x55:
+ case 0x56:
+ case 0x57: sprintf( buffer, "xyd%d (Y<=>M[0,%d])", (op&3)+4, (op&3)+4 ); break;
+ case 0x58:
+ case 0x59:
+ case 0x5A:
+ case 0x5B:
+ case 0x5C:
+ case 0x5D:
+ case 0x5E:
+ case 0x5F: sprintf( buffer, "lxi #$%1x (X<=$%1x)", op&7, op&7 ); break;
+ case 0x60:
+ case 0x61:
+ case 0x62:
+ case 0x63:
+ case 0x64:
+ case 0x65:
+ case 0x66:
+ case 0x67: sprintf( buffer, "call %02x%02x (call if st=1)", op&7, arg ); pc++; break;
+ case 0x68:
+ case 0x69:
+ case 0x6A:
+ case 0x6B:
+ case 0x6C:
+ case 0x6D:
+ case 0x6E:
+ case 0x6F: sprintf( buffer, "jpl %02x%02x (jump if st=1)", op&7, arg ); pc++; break;
+ case 0x70:
+ case 0x71:
+ case 0x72:
+ case 0x73:
+ case 0x74:
+ case 0x75:
+ case 0x76:
+ case 0x77:
+ case 0x78:
+ case 0x79:
+ case 0x7A:
+ case 0x7B:
+ case 0x7C:
+ case 0x7D:
+ case 0x7E:
+ case 0x7F: sprintf( buffer, "ai #$%1x (A<=A+$%1x)", op&0xf, op&0xf ); break;
+ case 0x80:
+ case 0x81:
+ case 0x82:
+ case 0x83:
+ case 0x84:
+ case 0x85:
+ case 0x86:
+ case 0x87:
+ case 0x88:
+ case 0x89:
+ case 0x8A:
+ case 0x8B:
+ case 0x8C:
+ case 0x8D:
+ case 0x8E:
+ case 0x8F: sprintf( buffer, "lyi #$%1x (Y<=$%1x)", op&0xf, op&0xf ); break;
+ case 0x90:
+ case 0x91:
+ case 0x92:
+ case 0x93:
+ case 0x94:
+ case 0x95:
+ case 0x96:
+ case 0x97:
+ case 0x98:
+ case 0x99:
+ case 0x9A:
+ case 0x9B:
+ case 0x9C:
+ case 0x9D:
+ case 0x9E:
+ case 0x9F: sprintf( buffer, "li #$%1x (A<=$%1x)", op&0xf, op&0xf ); break;
+ case 0xA0:
+ case 0xA1:
+ case 0xA2:
+ case 0xA3:
+ case 0xA4:
+ case 0xA5:
+ case 0xA6:
+ case 0xA7:
+ case 0xA8:
+ case 0xA9:
+ case 0xAA:
+ case 0xAB:
+ case 0xAC:
+ case 0xAD:
+ case 0xAE:
+ case 0xAF: sprintf( buffer, "cyi #$%1x (Y==$%1x)", op&0xf, op&0xf ); break;
+ case 0xB0:
+ case 0xB1:
+ case 0xB2:
+ case 0xB3:
+ case 0xB4:
+ case 0xB5:
+ case 0xB6:
+ case 0xB7:
+ case 0xB8:
+ case 0xB9:
+ case 0xBA:
+ case 0xBB:
+ case 0xBC:
+ case 0xBD:
+ case 0xBE:
+ case 0xBF: sprintf( buffer, "ci #$%1x (A==$%1x)", op&0xf, op&0xf ); break;
+
+ default:
+ /* C0-FF */
+ sprintf( buffer, "jmp $%04x (jump if st=1)", (pc&(~0x3f))+ op-0xC0 );
+ break;
+ }
+
+ return (pc - startpc) | DASMFLAG_SUPPORTED;
+}
diff --git a/trunk/src/emu/cpu/mb88xx/mb88xx.c b/trunk/src/emu/cpu/mb88xx/mb88xx.c
new file mode 100644
index 00000000000..0972d89901c
--- /dev/null
+++ b/trunk/src/emu/cpu/mb88xx/mb88xx.c
@@ -0,0 +1,1121 @@
+/***************************************************************************
+
+ mb88xx.c
+ Core implementation for the portable Fujitsu MB88xx series MCU emulator.
+
+ Written by Ernesto Corvi
+
+
+ TODO:
+ - Add support for the timer
+ - Add support for the serial interface
+ - Split the core to support multiple CPU types?
+
+***************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "mb88xx.h"
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define SERIAL_PRESCALE 6 /* guess */
+#define TIMER_PRESCALE 32 /* guess */
+
+#define SERIAL_DISABLE_THRESH 1000 /* at this value, we give up driving the serial port */
+
+#define INT_CAUSE_SERIAL 0x01
+#define INT_CAUSE_TIMER 0x02
+#define INT_CAUSE_EXTERNAL 0x04
+
+
+
+/***************************************************************************
+ STRUCTURES & TYPEDEFS
+***************************************************************************/
+
+typedef struct _mb88_state mb88_state;
+struct _mb88_state
+{
+ UINT8 PC; /* Program Counter: 6 bits */
+ UINT8 PA; /* Page Address: 4 bits */
+ UINT16 SP[4]; /* Stack is 4*10 bit addresses deep, but we also use 3 top bits per address to store flags during irq */
+ UINT8 SI; /* Stack index: 2 bits */
+ UINT8 A; /* Accumulator: 4 bits */
+ UINT8 X; /* Index X: 4 bits */
+ UINT8 Y; /* Index Y: 4 bits */
+ UINT8 st; /* State flag: 1 bit */
+ UINT8 zf; /* Zero flag: 1 bit */
+ UINT8 cf; /* Carry flag: 1 bit */
+ UINT8 vf; /* Timer overflow flag: 1 bit */
+ UINT8 sf; /* Serial Full/Empty flag: 1 bit */
+ UINT8 nf; /* Interrupt flag: 1 bit */
+
+ /* Peripheral Control */
+ UINT8 pio; /* Peripheral enable bits: 8 bits */
+
+ /* Timer registers */
+ UINT8 TH; /* Timer High: 4 bits */
+ UINT8 TL; /* Timer Low: 4 bits */
+ UINT8 TP; /* Timer Prescale: 6 bits? */
+ UINT8 ctr; /* current external counter value */
+
+ /* Serial registers */
+ UINT8 SB; /* Serial buffer: 4 bits */
+ UINT16 SBcount; /* number of bits received */
+ emu_timer *serial;
+
+ /* PLA configuration */
+ UINT8 * PLA;
+
+ /* IRQ handling */
+ UINT8 pending_interrupt;
+ device_irq_callback irqcallback;
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ address_space *data;
+ address_space *io;
+ int icount;
+};
+
+INLINE mb88_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == MB88 ||
+ device->type() == MB8841 ||
+ device->type() == MB8842 ||
+ device->type() == MB8843 ||
+ device->type() == MB8844);
+ return (mb88_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+static TIMER_CALLBACK( serial_timer );
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+#define READOP(a) (cpustate->direct->read_decrypted_byte(a))
+
+#define RDMEM(a) (cpustate->data->read_byte(a))
+#define WRMEM(a,v) (cpustate->data->write_byte((a), (v)))
+
+#define READPORT(a) (cpustate->io->read_byte(a))
+#define WRITEPORT(a,v) (cpustate->io->write_byte((a), (v)))
+
+#define TEST_ST() (cpustate->st & 1)
+#define TEST_ZF() (cpustate->zf & 1)
+#define TEST_CF() (cpustate->cf & 1)
+#define TEST_VF() (cpustate->vf & 1)
+#define TEST_SF() (cpustate->sf & 1)
+#define TEST_NF() (cpustate->nf & 1)
+
+#define UPDATE_ST_C(v) cpustate->st=(v&0x10) ? 0 : 1
+#define UPDATE_ST_Z(v) cpustate->st=(v==0) ? 0 : 1
+
+#define UPDATE_CF(v) cpustate->cf=((v&0x10)==0) ? 0 : 1
+#define UPDATE_ZF(v) cpustate->zf=(v!=0) ? 0 : 1
+
+#define CYCLES(x) do { cpustate->icount -= (x); } while (0)
+
+#define GETPC() (((int)cpustate->PA << 6)+cpustate->PC)
+#define GETEA() ((cpustate->X << 4)+cpustate->Y)
+
+#define INCPC() do { cpustate->PC++; if ( cpustate->PC >= 0x40 ) { cpustate->PC = 0; cpustate->PA++; } } while (0)
+
+
+/***************************************************************************
+ INITIALIZATION AND SHUTDOWN
+***************************************************************************/
+
+static CPU_INIT( mb88 )
+{
+ mb88_state *cpustate = get_safe_token(device);
+
+ if ( device->static_config() )
+ {
+ const mb88_cpu_core *_config = (const mb88_cpu_core*)device->static_config();
+ cpustate->PLA = _config->PLA_config;
+ }
+
+ cpustate->irqcallback = irqcallback;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+ cpustate->data = device->space(AS_DATA);
+ cpustate->io = device->space(AS_IO);
+
+ cpustate->serial = device->machine().scheduler().timer_alloc(FUNC(serial_timer), (void *)device);
+
+ device->save_item(NAME(cpustate->PC));
+ device->save_item(NAME(cpustate->PA));
+ device->save_item(NAME(cpustate->SP[0]));
+ device->save_item(NAME(cpustate->SP[1]));
+ device->save_item(NAME(cpustate->SP[2]));
+ device->save_item(NAME(cpustate->SP[3]));
+ device->save_item(NAME(cpustate->SI));
+ device->save_item(NAME(cpustate->A));
+ device->save_item(NAME(cpustate->X));
+ device->save_item(NAME(cpustate->Y));
+ device->save_item(NAME(cpustate->st));
+ device->save_item(NAME(cpustate->zf));
+ device->save_item(NAME(cpustate->cf));
+ device->save_item(NAME(cpustate->vf));
+ device->save_item(NAME(cpustate->sf));
+ device->save_item(NAME(cpustate->nf));
+ device->save_item(NAME(cpustate->pio));
+ device->save_item(NAME(cpustate->TH));
+ device->save_item(NAME(cpustate->TL));
+ device->save_item(NAME(cpustate->TP));
+ device->save_item(NAME(cpustate->ctr));
+ device->save_item(NAME(cpustate->SB));
+ device->save_item(NAME(cpustate->SBcount));
+ device->save_item(NAME(cpustate->pending_interrupt));
+}
+
+static CPU_RESET( mb88 )
+{
+ mb88_state *cpustate = get_safe_token(device);
+
+ /* zero registers and flags */
+ cpustate->PC = 0;
+ cpustate->PA = 0;
+ cpustate->SP[0] = cpustate->SP[1] = cpustate->SP[2] = cpustate->SP[3] = 0;
+ cpustate->SI = 0;
+ cpustate->A = 0;
+ cpustate->X = 0;
+ cpustate->Y = 0;
+ cpustate->st = 1; /* start off with st=1 */
+ cpustate->zf = 0;
+ cpustate->cf = 0;
+ cpustate->vf = 0;
+ cpustate->sf = 0;
+ cpustate->nf = 0;
+ cpustate->pio = 0;
+ cpustate->TH = 0;
+ cpustate->TL = 0;
+ cpustate->TP = 0;
+ cpustate->SB = 0;
+ cpustate->SBcount = 0;
+ cpustate->pending_interrupt = 0;
+}
+
+/***************************************************************************
+ CORE EXECUTION LOOP
+***************************************************************************/
+
+static TIMER_CALLBACK( serial_timer )
+{
+ mb88_state *cpustate = get_safe_token((cpu_device *)ptr);
+
+ cpustate->SBcount++;
+
+ /* if we get too many interrupts with no servicing, disable the timer
+ until somebody does something */
+ if (cpustate->SBcount >= SERIAL_DISABLE_THRESH)
+ cpustate->serial->adjust(attotime::never);
+
+ /* only read if not full; this is needed by the Namco 52xx to ensure that
+ the program can write to S and recover the value even if serial is enabled */
+ if (!cpustate->sf)
+ {
+ cpustate->SB = (cpustate->SB >> 1) | (READPORT(MB88_PORTSI) ? 8 : 0);
+
+ if (cpustate->SBcount >= 4)
+ {
+ cpustate->sf = 1;
+ cpustate->pending_interrupt |= INT_CAUSE_SERIAL;
+ }
+ }
+
+}
+
+static int pla( mb88_state *cpustate, int inA, int inB )
+{
+ int index = ((inB&1) << 4) | (inA&0x0f);
+
+ if ( cpustate->PLA )
+ return cpustate->PLA[index];
+
+ return index;
+}
+
+static void set_irq_line(mb88_state *cpustate, int state)
+{
+ /* on falling edge trigger interrupt */
+ if ( (cpustate->pio & 0x04) && cpustate->nf == 0 && state != CLEAR_LINE )
+ {
+ cpustate->pending_interrupt |= INT_CAUSE_EXTERNAL;
+ }
+
+ cpustate->nf = (state != CLEAR_LINE) ? 1 : 0;
+}
+
+static void update_pio_enable( mb88_state *cpustate, UINT8 newpio )
+{
+ /* if the serial state has changed, configure the timer */
+ if ((cpustate->pio ^ newpio) & 0x30)
+ {
+ if ((newpio & 0x30) == 0)
+ cpustate->serial->adjust(attotime::never);
+ else if ((newpio & 0x30) == 0x20)
+ cpustate->serial->adjust(attotime::from_hz(cpustate->device->clock() / SERIAL_PRESCALE), 0, attotime::from_hz(cpustate->device->clock() / SERIAL_PRESCALE));
+ else
+ fatalerror("mb88xx: update_pio_enable set serial enable to unsupported value %02X\n", newpio & 0x30);
+ }
+
+ cpustate->pio = newpio;
+}
+
+static void increment_timer( mb88_state *cpustate )
+{
+ cpustate->TL = (cpustate->TL + 1) & 0x0f;
+ if (cpustate->TL == 0)
+ {
+ cpustate->TH = (cpustate->TH + 1) & 0x0f;
+ if (cpustate->TH == 0)
+ {
+ cpustate->vf = 1;
+ cpustate->pending_interrupt |= INT_CAUSE_TIMER;
+ }
+ }
+}
+
+static void update_pio( mb88_state *cpustate, int cycles )
+{
+ /* TODO: improve/validate serial and timer support */
+
+ /* internal clock enable */
+ if ( cpustate->pio & 0x80 )
+ {
+ cpustate->TP += cycles;
+ while (cpustate->TP >= TIMER_PRESCALE)
+ {
+ cpustate->TP -= TIMER_PRESCALE;
+ increment_timer(cpustate);
+ }
+ }
+
+ /* process pending interrupts */
+ if (cpustate->pending_interrupt & cpustate->pio)
+ {
+ cpustate->SP[cpustate->SI] = GETPC();
+ cpustate->SP[cpustate->SI] |= TEST_CF() << 15;
+ cpustate->SP[cpustate->SI] |= TEST_ZF() << 14;
+ cpustate->SP[cpustate->SI] |= TEST_ST() << 13;
+ cpustate->SI = ( cpustate->SI + 1 ) & 3;
+
+ /* the datasheet doesn't mention interrupt vectors but
+ the Arabian MCU program expects the following */
+ if (cpustate->pending_interrupt & cpustate->pio & INT_CAUSE_EXTERNAL)
+ {
+ /* if we have a live external source, call the irqcallback */
+ (*cpustate->irqcallback)(cpustate->device, 0);
+ cpustate->PC = 0x02;
+ }
+ else if (cpustate->pending_interrupt & cpustate->pio & INT_CAUSE_TIMER)
+ {
+ cpustate->PC = 0x04;
+ }
+ else if (cpustate->pending_interrupt & cpustate->pio & INT_CAUSE_SERIAL)
+ {
+ cpustate->PC = 0x06;
+ }
+
+ cpustate->PA = 0x00;
+ cpustate->st = 1;
+ cpustate->pending_interrupt = 0;
+
+ CYCLES(3); /* ? */
+ }
+}
+
+void mb88_external_clock_w(device_t *device, int state)
+{
+ mb88_state *cpustate = get_safe_token(device);
+ if (state != cpustate->ctr)
+ {
+ cpustate->ctr = state;
+
+ /* on a falling clock, increment the timer, but only if enabled */
+ if (cpustate->ctr == 0 && (cpustate->pio & 0x40))
+ increment_timer(cpustate);
+ }
+}
+
+
+static CPU_EXECUTE( mb88 )
+{
+ mb88_state *cpustate = get_safe_token(device);
+
+ while (cpustate->icount > 0)
+ {
+ UINT8 opcode, arg, oc;
+
+ /* fetch the opcode */
+ debugger_instruction_hook(device, GETPC());
+ opcode = READOP(GETPC());
+
+ /* increment the PC */
+ INCPC();
+
+ /* start with instruction doing 1 cycle */
+ oc = 1;
+
+ switch (opcode)
+ {
+ case 0x00: /* nop ZCS:...*/
+ cpustate->st = 1;
+ break;
+
+ case 0x01: /* outO ZCS:...*/
+ WRITEPORT( MB88_PORTO, pla(cpustate, cpustate->A,TEST_CF()) );
+ cpustate->st = 1;
+ break;
+
+ case 0x02: /* outP ZCS:... */
+ WRITEPORT( MB88_PORTP, cpustate->A );
+ cpustate->st = 1;
+ break;
+
+ case 0x03: /* outR ZCS:... */
+ arg = cpustate->Y;
+ WRITEPORT( MB88_PORTR0+(arg&3), cpustate->A );
+ cpustate->st = 1;
+ break;
+
+ case 0x04: /* tay ZCS:... */
+ cpustate->Y = cpustate->A;
+ cpustate->st = 1;
+ break;
+
+ case 0x05: /* tath ZCS:... */
+ cpustate->TH = cpustate->A;
+ cpustate->st = 1;
+ break;
+
+ case 0x06: /* tatl ZCS:... */
+ cpustate->TL = cpustate->A;
+ cpustate->st = 1;
+ break;
+
+ case 0x07: /* tas ZCS:... */
+ cpustate->SB = cpustate->A;
+ cpustate->st = 1;
+ break;
+
+ case 0x08: /* icy ZCS:x.x */
+ cpustate->Y++;
+ UPDATE_ST_C(cpustate->Y);
+ cpustate->Y &= 0x0f;
+ UPDATE_ZF(cpustate->Y);
+ break;
+
+ case 0x09: /* icm ZCS:x.x */
+ arg=RDMEM(GETEA());
+ arg++;
+ UPDATE_ST_C(arg);
+ arg &= 0x0f;
+ UPDATE_ZF(arg);
+ WRMEM(GETEA(),arg);
+ break;
+
+ case 0x0a: /* stic ZCS:x.x */
+ WRMEM(GETEA(),cpustate->A);
+ cpustate->Y++;
+ UPDATE_ST_C(cpustate->Y);
+ cpustate->Y &= 0x0f;
+ UPDATE_ZF(cpustate->Y);
+ break;
+
+ case 0x0b: /* x ZCS:x.. */
+ arg = RDMEM(GETEA());
+ WRMEM(GETEA(),cpustate->A);
+ cpustate->A = arg;
+ UPDATE_ZF(cpustate->A);
+ cpustate->st = 1;
+ break;
+
+ case 0x0c: /* rol ZCS:xxx */
+ cpustate->A <<= 1;
+ cpustate->A |= TEST_CF();
+ UPDATE_ST_C(cpustate->A);
+ cpustate->cf = cpustate->st ^ 1;
+ cpustate->A &= 0x0f;
+ UPDATE_ZF(cpustate->A);
+ break;
+
+ case 0x0d: /* l ZCS:x.. */
+ cpustate->A = RDMEM(GETEA());
+ UPDATE_ZF(cpustate->A);
+ cpustate->st = 1;
+ break;
+
+ case 0x0e: /* adc ZCS:xxx */
+ arg = RDMEM(GETEA());
+ arg += cpustate->A;
+ arg += TEST_CF();
+ UPDATE_ST_C(arg);
+ cpustate->cf = cpustate->st ^ 1;
+ cpustate->A = arg & 0x0f;
+ UPDATE_ZF(cpustate->A);
+ break;
+
+ case 0x0f: /* and ZCS:x.x */
+ cpustate->A &= RDMEM(GETEA());
+ UPDATE_ZF(cpustate->A);
+ cpustate->st = cpustate->zf ^ 1;
+ break;
+
+ case 0x10: /* daa ZCS:.xx */
+ if ( TEST_CF() || cpustate->A > 9 ) cpustate->A += 6;
+ UPDATE_ST_C(cpustate->A);
+ cpustate->cf = cpustate->st ^ 1;
+ cpustate->A &= 0x0f;
+ break;
+
+ case 0x11: /* das ZCS:.xx */
+ if ( TEST_CF() || cpustate->A > 9 ) cpustate->A += 10;
+ UPDATE_ST_C(cpustate->A);
+ cpustate->cf = cpustate->st ^ 1;
+ cpustate->A &= 0x0f;
+ break;
+
+ case 0x12: /* inK ZCS:x.. */
+ cpustate->A = READPORT( MB88_PORTK ) & 0x0f;
+ UPDATE_ZF(cpustate->A);
+ cpustate->st = 1;
+ break;
+
+ case 0x13: /* inR ZCS:x.. */
+ arg = cpustate->Y;
+ cpustate->A = READPORT( MB88_PORTR0+(arg&3) ) & 0x0f;
+ UPDATE_ZF(cpustate->A);
+ cpustate->st = 1;
+ break;
+
+ case 0x14: /* tya ZCS:x.. */
+ cpustate->A = cpustate->Y;
+ UPDATE_ZF(cpustate->A);
+ cpustate->st = 1;
+ break;
+
+ case 0x15: /* ttha ZCS:x.. */
+ cpustate->A = cpustate->TH;
+ UPDATE_ZF(cpustate->A);
+ cpustate->st = 1;
+ break;
+
+ case 0x16: /* ttla ZCS:x.. */
+ cpustate->A = cpustate->TL;
+ UPDATE_ZF(cpustate->A);
+ cpustate->st = 1;
+ break;
+
+ case 0x17: /* tsa ZCS:x.. */
+ cpustate->A = cpustate->SB;
+ UPDATE_ZF(cpustate->A);
+ cpustate->st = 1;
+ break;
+
+ case 0x18: /* dcy ZCS:..x */
+ cpustate->Y--;
+ UPDATE_ST_C(cpustate->Y);
+ cpustate->Y &= 0x0f;
+ break;
+
+ case 0x19: /* dcm ZCS:x.x */
+ arg=RDMEM(GETEA());
+ arg--;
+ UPDATE_ST_C(arg);
+ arg &= 0x0f;
+ UPDATE_ZF(arg);
+ WRMEM(GETEA(),arg);
+ break;
+
+ case 0x1a: /* stdc ZCS:x.x */
+ WRMEM(GETEA(),cpustate->A);
+ cpustate->Y--;
+ UPDATE_ST_C(cpustate->Y);
+ cpustate->Y &= 0x0f;
+ UPDATE_ZF(cpustate->Y);
+ break;
+
+ case 0x1b: /* xx ZCS:x.. */
+ arg = cpustate->X;
+ cpustate->X = cpustate->A;
+ cpustate->A = arg;
+ UPDATE_ZF(cpustate->A);
+ cpustate->st = 1;
+ break;
+
+ case 0x1c: /* ror ZCS:xxx */
+ cpustate->A |= TEST_CF() << 4;
+ UPDATE_ST_C(cpustate->A << 4);
+ cpustate->cf = cpustate->st ^ 1;
+ cpustate->A >>= 1;
+ cpustate->A &= 0x0f;
+ UPDATE_ZF(cpustate->A);
+ break;
+
+ case 0x1d: /* st ZCS:x.. */
+ WRMEM(GETEA(),cpustate->A);
+ cpustate->st = 1;
+ break;
+
+ case 0x1e: /* sbc ZCS:xxx */
+ arg = RDMEM(GETEA());
+ arg -= cpustate->A;
+ arg -= TEST_CF();
+ UPDATE_ST_C(arg);
+ cpustate->cf = cpustate->st ^ 1;
+ cpustate->A = arg & 0x0f;
+ UPDATE_ZF(cpustate->A);
+ break;
+
+ case 0x1f: /* or ZCS:x.x */
+ cpustate->A |= RDMEM(GETEA());
+ UPDATE_ZF(cpustate->A);
+ cpustate->st = cpustate->zf ^ 1;
+ break;
+
+ case 0x20: /* setR ZCS:... */
+ arg = READPORT( MB88_PORTR0+(cpustate->Y/4) );
+ WRITEPORT( MB88_PORTR0+(cpustate->Y/4), arg | ( 1 << (cpustate->Y%4) ) );
+ cpustate->st = 1;
+ break;
+
+ case 0x21: /* setc ZCS:.xx */
+ cpustate->cf = 1;
+ cpustate->st = 1;
+ break;
+
+ case 0x22: /* rstR ZCS:... */
+ arg = READPORT( MB88_PORTR0+(cpustate->Y/4) );
+ WRITEPORT( MB88_PORTR0+(cpustate->Y/4), arg & ~( 1 << (cpustate->Y%4) ) );
+ cpustate->st = 1;
+ break;
+
+ case 0x23: /* rstc ZCS:.xx */
+ cpustate->cf = 0;
+ cpustate->st = 1;
+ break;
+
+ case 0x24: /* tstr ZCS:..x */
+ arg = READPORT( MB88_PORTR0+(cpustate->Y/4) );
+ cpustate->st = ( arg & ( 1 << (cpustate->Y%4) ) ) ? 0 : 1;
+ break;
+
+ case 0x25: /* tsti ZCS:..x */
+ cpustate->st = cpustate->nf ^ 1;
+ break;
+
+ case 0x26: /* tstv ZCS:..x */
+ cpustate->st = cpustate->vf ^ 1;
+ cpustate->vf = 0;
+ break;
+
+ case 0x27: /* tsts ZCS:..x */
+ cpustate->st = cpustate->sf ^ 1;
+ if (cpustate->sf)
+ {
+ /* re-enable the timer if we disabled it previously */
+ if (cpustate->SBcount >= SERIAL_DISABLE_THRESH)
+ cpustate->serial->adjust(attotime::from_hz(cpustate->device->clock() / SERIAL_PRESCALE), 0, attotime::from_hz(cpustate->device->clock() / SERIAL_PRESCALE));
+ cpustate->SBcount = 0;
+ }
+ cpustate->sf = 0;
+ break;
+
+ case 0x28: /* tstc ZCS:..x */
+ cpustate->st = cpustate->cf ^ 1;
+ break;
+
+ case 0x29: /* tstz ZCS:..x */
+ cpustate->st = cpustate->zf ^ 1;
+ break;
+
+ case 0x2a: /* sts ZCS:x.. */
+ WRMEM(GETEA(),cpustate->SB);
+ UPDATE_ZF(cpustate->SB);
+ cpustate->st = 1;
+ break;
+
+ case 0x2b: /* ls ZCS:x.. */
+ cpustate->SB = RDMEM(GETEA());
+ UPDATE_ZF(cpustate->SB);
+ cpustate->st = 1;
+ break;
+
+ case 0x2c: /* rts ZCS:... */
+ cpustate->SI = ( cpustate->SI - 1 ) & 3;
+ cpustate->PC = cpustate->SP[cpustate->SI] & 0x3f;
+ cpustate->PA = (cpustate->SP[cpustate->SI] >> 6) & 0x1f;
+ cpustate->st = 1;
+ break;
+
+ case 0x2d: /* neg ZCS: ..x */
+ cpustate->A = (~cpustate->A)+1;
+ cpustate->A &= 0x0f;
+ UPDATE_ST_Z(cpustate->A);
+ break;
+
+ case 0x2e: /* c ZCS:xxx */
+ arg = RDMEM(GETEA());
+ arg -= cpustate->A;
+ UPDATE_CF(arg);
+ arg &= 0x0f;
+ UPDATE_ST_Z(arg);
+ cpustate->zf = cpustate->st ^ 1;
+ break;
+
+ case 0x2f: /* eor ZCS:x.x */
+ cpustate->A ^= RDMEM(GETEA());
+ UPDATE_ST_Z(cpustate->A);
+ cpustate->zf = cpustate->st ^ 1;
+ break;
+
+ case 0x30: case 0x31: case 0x32: case 0x33: /* sbit ZCS:... */
+ arg = RDMEM(GETEA());
+ WRMEM(GETEA(), arg | (1 << (opcode&3)));
+ cpustate->st = 1;
+ break;
+
+ case 0x34: case 0x35: case 0x36: case 0x37: /* rbit ZCS:... */
+ arg = RDMEM(GETEA());
+ WRMEM(GETEA(), arg & ~(1 << (opcode&3)));
+ cpustate->st = 1;
+ break;
+
+ case 0x38: case 0x39: case 0x3a: case 0x3b: /* tbit ZCS:... */
+ arg = RDMEM(GETEA());
+ cpustate->st = ( arg & (1 << (opcode&3) ) ) ? 0 : 1;
+ break;
+
+ case 0x3c: /* rti ZCS:... */
+ /* restore address and saved state flags on the top bits of the stack */
+ cpustate->SI = ( cpustate->SI - 1 ) & 3;
+ cpustate->PC = cpustate->SP[cpustate->SI] & 0x3f;
+ cpustate->PA = (cpustate->SP[cpustate->SI] >> 6) & 0x1f;
+ cpustate->st = (cpustate->SP[cpustate->SI] >> 13)&1;
+ cpustate->zf = (cpustate->SP[cpustate->SI] >> 14)&1;
+ cpustate->cf = (cpustate->SP[cpustate->SI] >> 15)&1;
+ break;
+
+ case 0x3d: /* jpa imm ZCS:..x */
+ cpustate->PA = READOP(GETPC()) & 0x1f;
+ cpustate->PC = cpustate->A * 4;
+ oc = 2;
+ cpustate->st = 1;
+ break;
+
+ case 0x3e: /* en imm ZCS:... */
+ update_pio_enable(cpustate, cpustate->pio | READOP(GETPC()));
+ INCPC();
+ oc = 2;
+ cpustate->st = 1;
+ break;
+
+ case 0x3f: /* dis imm ZCS:... */
+ update_pio_enable(cpustate, cpustate->pio & ~(READOP(GETPC())));
+ INCPC();
+ oc = 2;
+ cpustate->st = 1;
+ break;
+
+ case 0x40: case 0x41: case 0x42: case 0x43: /* setD ZCS:... */
+ arg = READPORT(MB88_PORTR0);
+ arg |= (1 << (opcode&3));
+ WRITEPORT(MB88_PORTR0,arg);
+ cpustate->st = 1;
+ break;
+
+ case 0x44: case 0x45: case 0x46: case 0x47: /* rstD ZCS:... */
+ arg = READPORT(MB88_PORTR0);
+ arg &= ~(1 << (opcode&3));
+ WRITEPORT(MB88_PORTR0,arg);
+ cpustate->st = 1;
+ break;
+
+ case 0x48: case 0x49: case 0x4a: case 0x4b: /* tstD ZCS:..x */
+ arg = READPORT(MB88_PORTR2);
+ cpustate->st = (arg & (1 << (opcode&3))) ? 0 : 1;
+ break;
+
+ case 0x4c: case 0x4d: case 0x4e: case 0x4f: /* tba ZCS:..x */
+ cpustate->st = (cpustate->A & (1 << (opcode&3))) ? 0 : 1;
+ break;
+
+ case 0x50: case 0x51: case 0x52: case 0x53: /* xd ZCS:x.. */
+ arg = RDMEM(opcode&3);
+ WRMEM((opcode&3),cpustate->A);
+ cpustate->A = arg;
+ UPDATE_ZF(cpustate->A);
+ cpustate->st = 1;
+ break;
+
+ case 0x54: case 0x55: case 0x56: case 0x57: /* xyd ZCS:x.. */
+ arg = RDMEM((opcode&3)+4);
+ WRMEM((opcode&3)+4,cpustate->Y);
+ cpustate->Y = arg;
+ UPDATE_ZF(cpustate->Y);
+ cpustate->st = 1;
+ break;
+
+ case 0x58: case 0x59: case 0x5a: case 0x5b:
+ case 0x5c: case 0x5d: case 0x5e: case 0x5f: /* lxi ZCS:x.. */
+ cpustate->X = opcode & 7;
+ UPDATE_ZF(cpustate->X);
+ cpustate->st = 1;
+ break;
+
+ case 0x60: case 0x61: case 0x62: case 0x63:
+ case 0x64: case 0x65: case 0x66: case 0x67: /* call imm ZCS:..x */
+ arg = READOP(GETPC());
+ INCPC();
+ oc = 2;
+ if ( TEST_ST() )
+ {
+ cpustate->SP[cpustate->SI] = GETPC();
+ cpustate->SI = ( cpustate->SI + 1 ) & 3;
+ cpustate->PC = arg & 0x3f;
+ cpustate->PA = ( ( opcode & 7 ) << 2 ) | ( arg >> 6 );
+ }
+ cpustate->st = 1;
+ break;
+
+ case 0x68: case 0x69: case 0x6a: case 0x6b:
+ case 0x6c: case 0x6d: case 0x6e: case 0x6f: /* jpl imm ZCS:..x */
+ arg = READOP(GETPC());
+ INCPC();
+ oc = 2;
+ if ( TEST_ST() )
+ {
+ cpustate->PC = arg & 0x3f;
+ cpustate->PA = ( ( opcode & 7 ) << 2 ) | ( arg >> 6 );
+ }
+ cpustate->st = 1;
+ break;
+
+ case 0x70: case 0x71: case 0x72: case 0x73:
+ case 0x74: case 0x75: case 0x76: case 0x77:
+ case 0x78: case 0x79: case 0x7a: case 0x7b:
+ case 0x7c: case 0x7d: case 0x7e: case 0x7f: /* ai ZCS:xxx */
+ arg = opcode & 0x0f;
+ arg += cpustate->A;
+ UPDATE_ST_C(arg);
+ cpustate->cf = cpustate->st ^ 1;
+ cpustate->A = arg & 0x0f;
+ UPDATE_ZF(cpustate->A);
+ break;
+
+ case 0x80: case 0x81: case 0x82: case 0x83:
+ case 0x84: case 0x85: case 0x86: case 0x87:
+ case 0x88: case 0x89: case 0x8a: case 0x8b:
+ case 0x8c: case 0x8d: case 0x8e: case 0x8f: /* lxi ZCS:x.. */
+ cpustate->Y = opcode & 0x0f;
+ UPDATE_ZF(cpustate->Y);
+ cpustate->st = 1;
+ break;
+
+ case 0x90: case 0x91: case 0x92: case 0x93:
+ case 0x94: case 0x95: case 0x96: case 0x97:
+ case 0x98: case 0x99: case 0x9a: case 0x9b:
+ case 0x9c: case 0x9d: case 0x9e: case 0x9f: /* li ZCS:x.. */
+ cpustate->A = opcode & 0x0f;
+ UPDATE_ZF(cpustate->A);
+ cpustate->st = 1;
+ break;
+
+ case 0xa0: case 0xa1: case 0xa2: case 0xa3:
+ case 0xa4: case 0xa5: case 0xa6: case 0xa7:
+ case 0xa8: case 0xa9: case 0xaa: case 0xab:
+ case 0xac: case 0xad: case 0xae: case 0xaf: /* cyi ZCS:xxx */
+ arg = (opcode & 0x0f) - cpustate->Y;
+ UPDATE_CF(arg);
+ arg &= 0x0f;
+ UPDATE_ST_Z(arg);
+ cpustate->zf = cpustate->st ^ 1;
+ break;
+
+ case 0xb0: case 0xb1: case 0xb2: case 0xb3:
+ case 0xb4: case 0xb5: case 0xb6: case 0xb7:
+ case 0xb8: case 0xb9: case 0xba: case 0xbb:
+ case 0xbc: case 0xbd: case 0xbe: case 0xbf: /* ci ZCS:xxx */
+ arg = (opcode & 0x0f) - cpustate->A;
+ UPDATE_CF(arg);
+ arg &= 0x0f;
+ UPDATE_ST_Z(arg);
+ cpustate->zf = cpustate->st ^ 1;
+ break;
+
+ default: /* jmp ZCS:..x */
+ if ( TEST_ST() )
+ {
+ cpustate->PC = opcode & 0x3f;
+ }
+ cpustate->st = 1;
+ break;
+ }
+
+ /* update cycle counts */
+ CYCLES( oc );
+
+ /* update interrupts, serial and timer flags */
+ update_pio(cpustate, oc);
+ }
+}
+
+/***************************************************************************
+ ADDRESS MAPS
+***************************************************************************/
+
+static ADDRESS_MAP_START(program_10bit, AS_PROGRAM, 8)
+ AM_RANGE(0x000, 0x3ff) AM_ROM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START(program_11bit, AS_PROGRAM, 8)
+ AM_RANGE(0x000, 0x7ff) AM_ROM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START(data_6bit, AS_DATA, 8)
+ AM_RANGE(0x00, 0x3f) AM_RAM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START(data_7bit, AS_DATA, 8)
+ AM_RANGE(0x00, 0x7f) AM_RAM
+ADDRESS_MAP_END
+
+/***************************************************************************
+ INFORMATION SETTERS
+***************************************************************************/
+
+static CPU_SET_INFO( mb88 )
+{
+ mb88_state *cpustate = get_safe_token(device);
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + MB88_IRQ_LINE: set_irq_line(cpustate, info->i); break;
+
+ case CPUINFO_INT_PC:
+ cpustate->PC = info->i & 0x3f;
+ cpustate->PA = (info->i >> 6) & 0x1f;
+ break;
+ case CPUINFO_INT_REGISTER + MB88_PC: cpustate->PC = info->i; break;
+ case CPUINFO_INT_REGISTER + MB88_PA: cpustate->PA = info->i; break;
+ case CPUINFO_INT_REGISTER + MB88_FLAGS:
+ cpustate->st = (info->i & 0x01) ? 1 : 0;
+ cpustate->zf = (info->i & 0x02) ? 1 : 0;
+ cpustate->cf = (info->i & 0x04) ? 1 : 0;
+ cpustate->vf = (info->i & 0x08) ? 1 : 0;
+ cpustate->sf = (info->i & 0x10) ? 1 : 0;
+ cpustate->nf = (info->i & 0x20) ? 1 : 0;
+ break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + MB88_SI: cpustate->SI = info->i & 0x03; break;
+ case CPUINFO_INT_REGISTER + MB88_A: cpustate->A = info->i & 0x0f; break;
+ case CPUINFO_INT_REGISTER + MB88_X: cpustate->X = info->i & 0x0f; break;
+ case CPUINFO_INT_REGISTER + MB88_Y: cpustate->Y = info->i & 0x0f; break;
+ case CPUINFO_INT_REGISTER + MB88_PIO: cpustate->pio = info->i & 0xff; break;
+ case CPUINFO_INT_REGISTER + MB88_TH: cpustate->TH = info->i & 0x0f; break;
+ case CPUINFO_INT_REGISTER + MB88_TL: cpustate->TL = info->i & 0x0f; break;
+ case CPUINFO_INT_REGISTER + MB88_SB: cpustate->SB = info->i & 0x0f; break;
+ }
+}
+
+/***************************************************************************
+ INFORMATION GETTERS
+***************************************************************************/
+
+CPU_GET_INFO( mb88 )
+{
+ mb88_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(mb88_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 1; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 6; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 2; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 3; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 11; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 7; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 3; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_INPUT_STATE + MB88_IRQ_LINE: info->i = cpustate->pending_interrupt ? ASSERT_LINE : CLEAR_LINE; break;
+
+ case CPUINFO_INT_PREVIOUSPC: /* not implemented */ break;
+
+ case CPUINFO_INT_PC: info->i = GETPC(); break;
+ case CPUINFO_INT_REGISTER + MB88_PC: info->i = cpustate->PC; break;
+ case CPUINFO_INT_REGISTER + MB88_PA: info->i = cpustate->PA; break;
+ case CPUINFO_INT_REGISTER + MB88_FLAGS: info->i = 0;
+ if (TEST_ST()) info->i |= 0x01;
+ if (TEST_ZF()) info->i |= 0x02;
+ if (TEST_CF()) info->i |= 0x04;
+ if (TEST_VF()) info->i |= 0x08;
+ if (TEST_SF()) info->i |= 0x10;
+ if (TEST_NF()) info->i |= 0x20;
+ break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + MB88_SI: info->i = cpustate->SI; break;
+ case CPUINFO_INT_REGISTER + MB88_A: info->i = cpustate->A; break;
+ case CPUINFO_INT_REGISTER + MB88_X: info->i = cpustate->X; break;
+ case CPUINFO_INT_REGISTER + MB88_Y: info->i = cpustate->Y; break;
+ case CPUINFO_INT_REGISTER + MB88_PIO: info->i = cpustate->pio; break;
+ case CPUINFO_INT_REGISTER + MB88_TH: info->i = cpustate->TH; break;
+ case CPUINFO_INT_REGISTER + MB88_TL: info->i = cpustate->TL; break;
+ case CPUINFO_INT_REGISTER + MB88_SB: info->i = cpustate->SB; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(mb88); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(mb88); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(mb88); break;
+ case CPUINFO_FCT_EXIT: info->exit = NULL; break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(mb88); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(mb88); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME(program_11bit); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = ADDRESS_MAP_NAME(data_7bit); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "MB88xx"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Fujitsu MB88xx"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Ernesto Corvi"); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c%c%c%c%c",
+ TEST_ST() ? 'T' : 't',
+ TEST_ZF() ? 'Z' : 'z',
+ TEST_CF() ? 'C' : 'c',
+ TEST_VF() ? 'V' : 'v',
+ TEST_SF() ? 'S' : 's',
+ TEST_NF() ? 'I' : 'i');
+ break;
+
+ case CPUINFO_STR_REGISTER + MB88_FLAGS:
+ sprintf(info->s, "FL:%c%c%c%c%c%c",
+ TEST_ST() ? 'T' : 't',
+ TEST_ZF() ? 'Z' : 'z',
+ TEST_CF() ? 'C' : 'c',
+ TEST_VF() ? 'V' : 'v',
+ TEST_SF() ? 'S' : 's',
+ TEST_NF() ? 'I' : 'i');
+ break;
+
+ case CPUINFO_STR_REGISTER + MB88_PC: sprintf(info->s, "PC:%02X", cpustate->PC); break;
+ case CPUINFO_STR_REGISTER + MB88_PA: sprintf(info->s, "PA:%02X", cpustate->PA); break;
+ case CPUINFO_STR_REGISTER + MB88_SI: sprintf(info->s, "SI:%1X", cpustate->SI); break;
+ case CPUINFO_STR_REGISTER + MB88_A: sprintf(info->s, "A:%1X", cpustate->A); break;
+ case CPUINFO_STR_REGISTER + MB88_X: sprintf(info->s, "X:%1X", cpustate->X); break;
+ case CPUINFO_STR_REGISTER + MB88_Y: sprintf(info->s, "Y:%1X", cpustate->Y); break;
+ case CPUINFO_STR_REGISTER + MB88_PIO: sprintf(info->s, "PIO:%02X", cpustate->pio); break;
+ case CPUINFO_STR_REGISTER + MB88_TH: sprintf(info->s, "TH:%1X", cpustate->TH); break;
+ case CPUINFO_STR_REGISTER + MB88_TL: sprintf(info->s, "TL:%1X", cpustate->TL); break;
+ case CPUINFO_STR_REGISTER + MB88_SB: sprintf(info->s, "SB:%1X", cpustate->SB); break;
+ }
+}
+
+CPU_GET_INFO( mb8841 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 11; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 7; break;
+
+ /* --- the following bits of info are returned as pointers --- */
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME(program_11bit); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = ADDRESS_MAP_NAME(data_7bit); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "MB8841"); break;
+
+ default: CPU_GET_INFO_CALL(mb88); break;
+ }
+}
+
+CPU_GET_INFO( mb8842 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 11; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 7; break;
+
+ /* --- the following bits of info are returned as pointers --- */
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME(program_11bit); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = ADDRESS_MAP_NAME(data_7bit); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "MB8842"); break;
+
+ default: CPU_GET_INFO_CALL(mb88); break;
+ }
+}
+
+CPU_GET_INFO( mb8843 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 10; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 6; break;
+
+ /* --- the following bits of info are returned as pointers --- */
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME(program_10bit); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = ADDRESS_MAP_NAME(data_6bit); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "MB8843"); break;
+
+ default: CPU_GET_INFO_CALL(mb88); break;
+ }
+}
+
+CPU_GET_INFO( mb8844 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 10; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 6; break;
+
+ /* --- the following bits of info are returned as pointers --- */
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME(program_10bit); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = ADDRESS_MAP_NAME(data_6bit); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "MB8844"); break;
+
+ default: CPU_GET_INFO_CALL(mb88); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(MB88, mb88);
+DEFINE_LEGACY_CPU_DEVICE(MB8841, mb8841);
+DEFINE_LEGACY_CPU_DEVICE(MB8842, mb8842);
+DEFINE_LEGACY_CPU_DEVICE(MB8843, mb8843);
+DEFINE_LEGACY_CPU_DEVICE(MB8844, mb8844);
diff --git a/trunk/src/emu/cpu/mb88xx/mb88xx.h b/trunk/src/emu/cpu/mb88xx/mb88xx.h
new file mode 100644
index 00000000000..053806918f7
--- /dev/null
+++ b/trunk/src/emu/cpu/mb88xx/mb88xx.h
@@ -0,0 +1,77 @@
+/***************************************************************************
+
+ mb88xx.h
+ Core implementation for the portable Fujitsu MB88xx series MCU emulator.
+
+ Written by Ernesto Corvi
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __MB88XX_H__
+#define __MB88XX_H__
+
+
+/***************************************************************************
+ PORT ENUMERATION
+***************************************************************************/
+
+enum
+{
+ MB88_PORTK = 0, /* input only, 4 bits */
+ MB88_PORTO, /* output only, PLA function output */
+ MB88_PORTP, /* 4 bits */
+ MB88_PORTR0, /* R0-R3, 4 bits */
+ MB88_PORTR1, /* R4-R7, 4 bits */
+ MB88_PORTR2, /* R8-R11, 4 bits */
+ MB88_PORTR3, /* R12-R15, 4 bits */
+ MB88_PORTSI /* SI, 1 bit */
+};
+
+/***************************************************************************
+ REGISTER ENUMERATION
+***************************************************************************/
+
+enum
+{
+ MB88_PC=1,
+ MB88_PA,
+ MB88_FLAGS,
+ MB88_SI,
+ MB88_A,
+ MB88_X,
+ MB88_Y,
+ MB88_PIO,
+ MB88_TH,
+ MB88_TL,
+ MB88_SB
+};
+
+#define MB88_IRQ_LINE 0
+
+/***************************************************************************
+ CONFIG STRUCTURE
+***************************************************************************/
+
+typedef struct _mb88_cpu_core mb88_cpu_core;
+struct _mb88_cpu_core
+{
+ UINT8 *PLA_config; /* PLA configuration (32 byte values), if NULL assume direct output */
+};
+
+/***************************************************************************
+ PUBLIC FUNCTIONS
+***************************************************************************/
+
+DECLARE_LEGACY_CPU_DEVICE(MB88, mb88);
+DECLARE_LEGACY_CPU_DEVICE(MB8841, mb8841);
+DECLARE_LEGACY_CPU_DEVICE(MB8842, mb8842);
+DECLARE_LEGACY_CPU_DEVICE(MB8843, mb8843);
+DECLARE_LEGACY_CPU_DEVICE(MB8844, mb8844);
+
+CPU_DISASSEMBLE( mb88 );
+
+void mb88_external_clock_w(device_t *device, int state);
+
+#endif /* __MB88XX_H__ */
diff --git a/trunk/src/emu/cpu/mc68hc11/hc11dasm.c b/trunk/src/emu/cpu/mc68hc11/hc11dasm.c
new file mode 100644
index 00000000000..07c154c9e6d
--- /dev/null
+++ b/trunk/src/emu/cpu/mc68hc11/hc11dasm.c
@@ -0,0 +1,1297 @@
+/*
+ Motorola M68HC11 disassembler
+
+ Written by Ville Linde
+*/
+
+#include "emu.h"
+
+enum
+{
+ EA_IMM8 = 1,
+ EA_IMM16,
+ EA_EXT,
+ EA_REL,
+ EA_DIRECT,
+ EA_DIRECT_IMM8,
+ EA_DIRECT_IMM8_REL,
+ EA_IND_X,
+ EA_IND_X_IMM8,
+ EA_IND_X_IMM8_REL,
+ EA_IND_Y,
+ EA_IND_Y_IMM8,
+ EA_IND_Y_IMM8_REL,
+ PAGE2,
+ PAGE3,
+ PAGE4,
+};
+
+typedef struct {
+ char mnemonic[32];
+ int address_mode;
+} M68HC11_OPCODE;
+
+static const M68HC11_OPCODE opcode_table[256] =
+{
+ /* 0x00 - 0x0f */
+ { "test", 0, },
+ { "nop", 0, },
+ { "idiv", 0, },
+ { "fdiv", 0, },
+ { "lsrd", 0, },
+ { "asld", 0, },
+ { "tap", 0, },
+ { "tpa", 0, },
+ { "inx", 0, },
+ { "dex", 0, },
+ { "clv", 0, },
+ { "sev", 0, },
+ { "clc", 0, },
+ { "sec", 0, },
+ { "cli", 0, },
+ { "sei", 0, },
+ /* 0x10 - 0x1f */
+ { "sba", 0, },
+ { "cba", 0, },
+ { "brset", EA_DIRECT_IMM8_REL, },
+ { "brclr", EA_DIRECT_IMM8_REL, },
+ { "bset", EA_DIRECT_IMM8, },
+ { "bclr", EA_DIRECT_IMM8, },
+ { "tab", 0, },
+ { "tba", 0, },
+ { "page2", PAGE2, },
+ { "daa", 0, },
+ { "page3", PAGE3, },
+ { "aba", 0, },
+ { "bset", EA_IND_X_IMM8, },
+ { "bclr", EA_IND_X_IMM8, },
+ { "brset", EA_IND_X_IMM8_REL, },
+ { "brclr", EA_IND_X_IMM8_REL, },
+ /* 0x20 - 0x2f */
+ { "bra", EA_REL, },
+ { "brn", EA_REL, },
+ { "bhi", EA_REL, },
+ { "bls", EA_REL, },
+ { "bcc", EA_REL, },
+ { "bcs", EA_REL, },
+ { "bne", EA_REL, },
+ { "beq", EA_REL, },
+ { "bvc", EA_REL, },
+ { "bvs", EA_REL, },
+ { "bpl", EA_REL, },
+ { "bmi", EA_REL, },
+ { "bge", EA_REL, },
+ { "blt", EA_REL, },
+ { "bgt", EA_REL, },
+ { "ble", EA_REL, },
+ /* 0x30 - 0x3f */
+ { "tsx", 0, },
+ { "ins", 0, },
+ { "pula", 0, },
+ { "pulb", 0, },
+ { "des", 0, },
+ { "txs", 0, },
+ { "psha", 0, },
+ { "pshb", 0, },
+ { "pulx", 0, },
+ { "rts", 0, },
+ { "abx", 0, },
+ { "rti", 0, },
+ { "pshx", 0, },
+ { "mul", 0, },
+ { "wai", 0, },
+ { "swi", 0, },
+ /* 0x40 - 0x4f */
+ { "nega", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "coma", 0, },
+ { "lsra", 0, },
+ { "?", 0, },
+ { "rora", 0, },
+ { "asra", 0, },
+ { "asla", 0, },
+ { "rola", 0, },
+ { "deca", 0, },
+ { "?", 0, },
+ { "inca", 0, },
+ { "tsta", 0, },
+ { "?", 0, },
+ { "clra", 0, },
+ /* 0x50 - 0x5f */
+ { "negb", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "comb", 0, },
+ { "lsrb", 0, },
+ { "?", 0, },
+ { "rorb", 0, },
+ { "asrb", 0, },
+ { "aslb", 0, },
+ { "rolb", 0, },
+ { "decb", 0, },
+ { "?", 0, },
+ { "incb", 0, },
+ { "tstb", 0, },
+ { "?", 0, },
+ { "clrb", 0, },
+ /* 0x60 - 0x6f */
+ { "neg", EA_IND_X, },
+ { "?", 0, },
+ { "?", 0, },
+ { "com", EA_IND_X, },
+ { "lsr", EA_IND_X, },
+ { "?", 0, },
+ { "ror", EA_IND_X, },
+ { "asr", EA_IND_X, },
+ { "asl", EA_IND_X, },
+ { "rol", EA_IND_X, },
+ { "dec", EA_IND_X, },
+ { "?", 0, },
+ { "inc", EA_IND_X, },
+ { "tst", EA_IND_X, },
+ { "jmp", EA_IND_X, },
+ { "clr", EA_IND_X, },
+ /* 0x70 - 0x7f */
+ { "neg", EA_EXT, },
+ { "?", 0, },
+ { "?", 0, },
+ { "com", EA_EXT, },
+ { "lsr", EA_EXT, },
+ { "?", 0, },
+ { "ror", EA_EXT, },
+ { "asr", EA_EXT, },
+ { "asl", EA_EXT, },
+ { "rol", EA_EXT, },
+ { "dec", EA_EXT, },
+ { "?", 0, },
+ { "inc", EA_EXT, },
+ { "tst", EA_EXT, },
+ { "jmp", EA_EXT, },
+ { "clr", EA_EXT, },
+ /* 0x80 - 0x8f */
+ { "suba", EA_IMM8, },
+ { "cmpa", EA_IMM8, },
+ { "sbca", EA_IMM8, },
+ { "subd", EA_IMM16, },
+ { "anda", EA_IMM8, },
+ { "bita", EA_IMM8, },
+ { "ldaa", EA_IMM8, },
+ { "?", 0, },
+ { "eora", EA_IMM8, },
+ { "adca", EA_IMM8, },
+ { "oraa", EA_IMM8, },
+ { "adda", EA_IMM8, },
+ { "cpx", EA_IMM16, },
+ { "bsr", EA_REL, },
+ { "lds", EA_IMM16, },
+ { "xgdx", 0, },
+ /* 0x90 - 0x9f */
+ { "suba", EA_DIRECT, },
+ { "cmpa", EA_DIRECT, },
+ { "sbca", EA_DIRECT, },
+ { "subd", EA_DIRECT, },
+ { "anda", EA_DIRECT, },
+ { "bita", EA_DIRECT, },
+ { "ldaa", EA_DIRECT, },
+ { "staa", EA_DIRECT, },
+ { "eora", EA_DIRECT, },
+ { "adca", EA_DIRECT, },
+ { "oraa", EA_DIRECT, },
+ { "adda", EA_DIRECT, },
+ { "cpx", EA_DIRECT, },
+ { "jsr", EA_DIRECT, },
+ { "lds", EA_DIRECT, },
+ { "sts", EA_DIRECT, },
+ /* 0xa0 - 0xaf */
+ { "suba", EA_IND_X, },
+ { "cmpa", EA_IND_X, },
+ { "sbca", EA_IND_X, },
+ { "subd", EA_IND_X, },
+ { "anda", EA_IND_X, },
+ { "bita", EA_IND_X, },
+ { "ldaa", EA_IND_X, },
+ { "staa", EA_IND_X, },
+ { "eora", EA_IND_X, },
+ { "adca", EA_IND_X, },
+ { "oraa", EA_IND_X, },
+ { "adda", EA_IND_X, },
+ { "cpx", EA_IND_X, },
+ { "jsr", EA_IND_X, },
+ { "lds", EA_IND_X, },
+ { "sts", EA_IND_X, },
+ /* 0xb0 - 0xbf */
+ { "suba", EA_EXT, },
+ { "cmpa", EA_EXT, },
+ { "sbca", EA_EXT, },
+ { "subd", EA_EXT, },
+ { "anda", EA_EXT, },
+ { "bita", EA_EXT, },
+ { "ldaa", EA_EXT, },
+ { "staa", EA_EXT, },
+ { "eora", EA_EXT, },
+ { "adca", EA_EXT, },
+ { "oraa", EA_EXT, },
+ { "adda", EA_EXT, },
+ { "cpx", EA_EXT, },
+ { "jsr", EA_EXT, },
+ { "lds", EA_EXT, },
+ { "sts", EA_EXT, },
+ /* 0xc0 - 0xcf */
+ { "subb", EA_IMM8, },
+ { "cmpb", EA_IMM8, },
+ { "sbcb", EA_IMM8, },
+ { "addd", EA_IMM16, },
+ { "andb", EA_IMM8, },
+ { "bitb", EA_IMM8, },
+ { "ldab", EA_IMM8, },
+ { "?", 0, },
+ { "eorb", EA_IMM8, },
+ { "adcb", EA_IMM8, },
+ { "orab", EA_IMM8, },
+ { "addb", EA_IMM8, },
+ { "ldd", EA_IMM16, },
+ { "page4", PAGE4, },
+ { "ldx", EA_IMM16, },
+ { "stop", 0, },
+ /* 0xd0 - 0xdf */
+ { "subb", EA_DIRECT, },
+ { "cmpb", EA_DIRECT, },
+ { "sbcb", EA_DIRECT, },
+ { "addd", EA_DIRECT, },
+ { "andb", EA_DIRECT, },
+ { "bitb", EA_DIRECT, },
+ { "ldab", EA_DIRECT, },
+ { "stab", EA_DIRECT, },
+ { "eorb", EA_DIRECT, },
+ { "adcb", EA_DIRECT, },
+ { "orab", EA_DIRECT, },
+ { "addb", EA_DIRECT, },
+ { "ldd", EA_DIRECT, },
+ { "std", EA_DIRECT, },
+ { "ldx", EA_DIRECT, },
+ { "stx", EA_DIRECT, },
+ /* 0xe0 - 0xef */
+ { "subb", EA_IND_X, },
+ { "cmpb", EA_IND_X, },
+ { "sbcb", EA_IND_X, },
+ { "addd", EA_IND_X, },
+ { "andb", EA_IND_X, },
+ { "bitb", EA_IND_X, },
+ { "ldab", EA_IND_X, },
+ { "stab", EA_IND_X, },
+ { "eorb", EA_IND_X, },
+ { "adcb", EA_IND_X, },
+ { "orab", EA_IND_X, },
+ { "addb", EA_IND_X, },
+ { "ldd", EA_IND_X, },
+ { "std", EA_IND_X, },
+ { "ldx", EA_IND_X, },
+ { "stx", EA_IND_X, },
+ /* 0xf0 - 0xff */
+ { "subb", EA_EXT, },
+ { "cmpb", EA_EXT, },
+ { "sbcb", EA_EXT, },
+ { "addd", EA_EXT, },
+ { "andb", EA_EXT, },
+ { "bitb", EA_EXT, },
+ { "ldab", EA_EXT, },
+ { "stab", EA_EXT, },
+ { "eorb", EA_EXT, },
+ { "adcb", EA_EXT, },
+ { "orab", EA_EXT, },
+ { "addb", EA_EXT, },
+ { "ldd", EA_EXT, },
+ { "std", EA_EXT, },
+ { "ldx", EA_EXT, },
+ { "stx", EA_EXT, },
+};
+
+
+/*****************************************************************************/
+
+
+static const M68HC11_OPCODE opcode_table_page2[256] =
+{
+ /* 0x00 - 0x0f */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "iny", 0, },
+ { "dey", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ /* 0x10 - 0x1f */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "bset", EA_IND_Y_IMM8, },
+ { "bclr", EA_IND_Y_IMM8, },
+ { "brset", EA_IND_Y_IMM8_REL, },
+ { "brlcr", EA_IND_Y_IMM8_REL, },
+ /* 0x20 - 0x2f */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ /* 0x30 - 0x3f */
+ { "tsy", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "tys", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "puly", 0, },
+ { "?", 0, },
+ { "aby", 0, },
+ { "?", 0, },
+ { "pshy", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ /* 0x40 - 0x4f */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ /* 0x50 - 0x5f */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ /* 0x60 - 0x6f */
+ { "neg", EA_IND_Y, },
+ { "?", 0, },
+ { "?", 0, },
+ { "com", EA_IND_Y, },
+ { "lsr", EA_IND_Y, },
+ { "?", 0, },
+ { "ror", EA_IND_Y, },
+ { "asr", EA_IND_Y, },
+ { "asl", EA_IND_Y, },
+ { "rol", EA_IND_Y, },
+ { "dec", EA_IND_Y, },
+ { "?", 0, },
+ { "inc", EA_IND_Y, },
+ { "tst", EA_IND_Y, },
+ { "jmp", EA_IND_Y, },
+ { "clr", EA_IND_Y, },
+ /* 0x70 - 0x7f */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ /* 0x80 - 0x8f */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "cpy", EA_IMM16, },
+ { "?", 0, },
+ { "?", 0, },
+ { "xgdy", 0, },
+ /* 0x90 - 0x9f */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "cpy", EA_DIRECT, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ /* 0xa0 - 0xaf */
+ { "suba", EA_IND_Y, },
+ { "cmpa", EA_IND_Y, },
+ { "sbca", EA_IND_Y, },
+ { "subd", EA_IND_Y, },
+ { "anda", EA_IND_Y, },
+ { "bita", EA_IND_Y, },
+ { "ldaa", EA_IND_Y, },
+ { "staa", EA_IND_Y, },
+ { "eora", EA_IND_Y, },
+ { "adca", EA_IND_Y, },
+ { "oraa", EA_IND_Y, },
+ { "adda", EA_IND_Y, },
+ { "cpy", EA_IND_Y, },
+ { "jsr", EA_IND_Y, },
+ { "lds", EA_IND_Y, },
+ { "sts", EA_IND_Y, },
+ /* 0xb0 - 0xbf */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "cpy", EA_EXT, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ /* 0xc0 - 0xcf */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "ldy", EA_IMM16, },
+ { "?", 0, },
+ /* 0xd0 - 0xdf */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "ldy", EA_DIRECT, },
+ { "sty", EA_DIRECT, },
+ /* 0xe0 - 0xef */
+ { "subb", EA_IND_Y, },
+ { "cmpb", EA_IND_Y, },
+ { "sbcb", EA_IND_Y, },
+ { "addd", EA_IND_Y, },
+ { "andb", EA_IND_Y, },
+ { "bitb", EA_IND_Y, },
+ { "ldab", EA_IND_Y, },
+ { "stab", EA_IND_Y, },
+ { "eorb", EA_IND_Y, },
+ { "adcb", EA_IND_Y, },
+ { "orab", EA_IND_Y, },
+ { "addb", EA_IND_Y, },
+ { "ldd", EA_IND_Y, },
+ { "std", EA_IND_Y, },
+ { "ldy", EA_IND_Y, },
+ { "sty", EA_IND_Y, },
+ /* 0xf0 - 0xff */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "ldy", EA_EXT, },
+ { "sty", EA_EXT, },
+};
+
+
+/*****************************************************************************/
+
+
+static const M68HC11_OPCODE opcode_table_page3[256] =
+{
+ /* 0x00 - 0x0f */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ /* 0x10 - 0x1f */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ /* 0x20 - 0x2f */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ /* 0x30 - 0x3f */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ /* 0x40 - 0x4f */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ /* 0x50 - 0x5f */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ /* 0x60 - 0x6f */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ /* 0x70 - 0x7f */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ /* 0x80 - 0x8f */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "cpd", EA_IMM16, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ /* 0x90 - 0x9f */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "cpd", EA_DIRECT, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ /* 0xa0 - 0xaf */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "cpd", EA_IND_X, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "cpy", EA_IND_X, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ /* 0xb0 - 0xbf */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "cpd", EA_EXT, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ /* 0xc0 - 0xcf */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ /* 0xd0 - 0xdf */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ /* 0xe0 - 0xef */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "ldy", EA_IND_X, },
+ { "sty", EA_IND_X, },
+ /* 0xf0 - 0xff */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+};
+
+
+/*****************************************************************************/
+
+
+static const M68HC11_OPCODE opcode_table_page4[256] =
+{
+ /* 0x00 - 0x0f */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ /* 0x10 - 0x1f */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ /* 0x20 - 0x2f */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ /* 0x30 - 0x3f */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ /* 0x40 - 0x4f */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ /* 0x50 - 0x5f */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ /* 0x60 - 0x6f */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ /* 0x70 - 0x7f */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ /* 0x80 - 0x8f */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ /* 0x90 - 0x9f */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ /* 0xa0 - 0xaf */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "cpd", EA_IND_Y, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "cpx", EA_IND_Y, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ /* 0xb0 - 0xbf */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ /* 0xc0 - 0xcf */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ /* 0xd0 - 0xdf */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ /* 0xe0 - 0xef */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "ldx", EA_IND_Y, },
+ { "stx", EA_IND_Y, },
+ /* 0xf0 - 0xff */
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+ { "?", 0, },
+};
+
+
+/*****************************************************************************/
+
+static char *output;
+static const UINT8 *rombase;
+
+static void ATTR_PRINTF(1,2) print(const char *fmt, ...)
+{
+ va_list vl;
+
+ va_start(vl, fmt);
+ output += vsprintf(output, fmt, vl);
+ va_end(vl);
+}
+
+static UINT8 fetch(void)
+{
+ return *rombase++;
+}
+
+static UINT16 fetch16(void)
+{
+ UINT16 w;
+ w = (rombase[0] << 8) | rombase[1];
+ rombase+=2;
+ return w;
+}
+
+static UINT32 decode_opcode(UINT32 pc, const M68HC11_OPCODE *op_table)
+{
+ UINT8 imm8, mask;
+ INT8 rel8;
+ UINT16 imm16;
+ UINT8 op2;
+ UINT32 flags = 0;
+
+ if (!strcmp(op_table->mnemonic, "jsr") || !strcmp(op_table->mnemonic, "bsr"))
+ flags = DASMFLAG_STEP_OVER;
+ else if (!strcmp(op_table->mnemonic, "rts") || !strcmp(op_table->mnemonic, "rti"))
+ flags = DASMFLAG_STEP_OUT;
+
+ switch(op_table->address_mode)
+ {
+ case EA_IMM8:
+ imm8 = fetch();
+ print("%s 0x%02X", op_table->mnemonic, imm8);
+ break;
+
+ case EA_IMM16:
+ imm16 = fetch16();
+ print("%s 0x%04X", op_table->mnemonic, imm16);
+ break;
+
+ case EA_DIRECT:
+ imm8 = fetch();
+ print("%s (0x%04X)", op_table->mnemonic, imm8);
+ break;
+
+ case EA_EXT:
+ imm16 = fetch16();
+ print("%s (0x%04X)", op_table->mnemonic, imm16);
+ break;
+
+ case EA_IND_X:
+ imm8 = fetch();
+ print("%s (X+0x%02X)", op_table->mnemonic, imm8);
+ break;
+
+ case EA_REL:
+ rel8 = fetch();
+ print("%s [0x%04X]", op_table->mnemonic, pc+2+rel8);
+ break;
+
+ case EA_DIRECT_IMM8:
+ imm8 = fetch();
+ mask = fetch();
+ print("%s (0x%04X), 0x%02X", op_table->mnemonic, imm8, mask);
+ break;
+
+ case EA_IND_X_IMM8:
+ imm8 = fetch();
+ mask = fetch();
+ print("%s (X+0x%02X), 0x%02X", op_table->mnemonic, imm8, mask);
+ break;
+
+ case EA_DIRECT_IMM8_REL:
+ imm8 = fetch();
+ mask = fetch();
+ rel8 = fetch();
+ print("%s (0x%04X), 0x%02X, [0x%04X]", op_table->mnemonic, imm8, mask, pc+4+rel8);
+ break;
+
+ case EA_IND_X_IMM8_REL:
+ imm8 = fetch();
+ mask = fetch();
+ rel8 = fetch();
+ print("%s (X+0x%02X), 0x%02X, [0x%04X]", op_table->mnemonic, imm8, mask, pc+4+rel8);
+ break;
+
+ case EA_IND_Y:
+ imm8 = fetch();
+ print("%s (Y+0x%02X)", op_table->mnemonic, imm8);
+ break;
+
+ case EA_IND_Y_IMM8:
+ imm8 = fetch();
+ mask = fetch();
+ print("%s (Y+0x%02X), 0x%02X", op_table->mnemonic, imm8, mask);
+ break;
+
+ case EA_IND_Y_IMM8_REL:
+ imm8 = fetch();
+ mask = fetch();
+ rel8 = fetch();
+ print("%s (Y+0x%02X), 0x%02X, [0x%04X]", op_table->mnemonic, imm8, mask, pc+2+rel8);
+ break;
+
+ case PAGE2:
+ op2 = fetch();
+ return decode_opcode(pc, &opcode_table_page2[op2]);
+
+ case PAGE3:
+ op2 = fetch();
+ return decode_opcode(pc, &opcode_table_page3[op2]);
+
+ case PAGE4:
+ op2 = fetch();
+ return decode_opcode(pc, &opcode_table_page4[op2]);
+
+ default:
+ print("%s", op_table->mnemonic);
+ }
+ return flags;
+}
+
+CPU_DISASSEMBLE( hc11 )
+{
+ UINT32 flags = 0;
+ UINT8 opcode;
+
+ output = buffer;
+ rombase = oprom;
+
+ opcode = fetch();
+ flags = decode_opcode(pc, &opcode_table[opcode]);
+
+ return (rombase-oprom) | flags | DASMFLAG_SUPPORTED;
+}
diff --git a/trunk/src/emu/cpu/mc68hc11/hc11ops.c b/trunk/src/emu/cpu/mc68hc11/hc11ops.c
new file mode 100644
index 00000000000..da0f9672696
--- /dev/null
+++ b/trunk/src/emu/cpu/mc68hc11/hc11ops.c
@@ -0,0 +1,3509 @@
+#define SET_Z8(r) (cpustate->ccr |= ((UINT8)r == 0) ? CC_Z : 0)
+#define SET_Z16(r) (cpustate->ccr |= ((UINT16)r == 0) ? CC_Z : 0)
+#define SET_N8(r) (cpustate->ccr |= (r & 0x80) ? CC_N : 0)
+#define SET_N16(r) (cpustate->ccr |= (r & 0x80) ? CC_N : 0)
+#define SET_V_ADD8(r,s,d) (cpustate->ccr |= (((r) ^ (s)) & ((r) ^ (d)) & 0x80) ? CC_V : 0)
+#define SET_V_SUB8(r,s,d) (cpustate->ccr |= (((d) ^ (s)) & ((d) ^ (r)) & 0x80) ? CC_V : 0)
+#define SET_V_ADD16(r,s,d) (cpustate->ccr |= (((r) ^ (s)) & ((r) ^ (d)) & 0x8000) ? CC_V : 0)
+#define SET_V_SUB16(r,s,d) (cpustate->ccr |= (((d) ^ (s)) & ((d) ^ (r)) & 0x8000) ? CC_V : 0)
+#define SET_H(r,s,d) (cpustate->ccr |= ((((s) & (d)) | ((d) & (r)) | ((r) & (s))) & 0x10) ? CC_H : 0)
+#define SET_C8(x) (cpustate->ccr |= ((x) & 0x100) ? CC_C : 0)
+#define SET_C16(x) (cpustate->ccr |= ((x) & 0x10000) ? CC_C : 0)
+#define CLEAR_Z(cpustate) (cpustate->ccr &= ~(CC_Z))
+#define CLEAR_C(cpustate) (cpustate->ccr &= ~(CC_C))
+#define CLEAR_NZV(cpustate) (cpustate->ccr &= ~(CC_N | CC_Z | CC_V))
+#define CLEAR_ZVC(cpustate) (cpustate->ccr &= ~(CC_Z | CC_V | CC_C))
+#define CLEAR_NZVC(cpustate) (cpustate->ccr &= ~(CC_N | CC_Z | CC_V | CC_C))
+#define CLEAR_HNZVC(cpustate) (cpustate->ccr &= ~(CC_H | CC_N | CC_Z | CC_V | CC_C))
+
+#define SET_ZFLAG(cpustate) (cpustate->ccr |= CC_Z)
+#define SET_NFLAG(cpustate) (cpustate->ccr |= CC_N)
+#define SET_VFLAG(cpustate) (cpustate->ccr |= CC_V)
+
+#define REG_A cpustate->d.d8.a
+#define REG_B cpustate->d.d8.b
+#define REG_D cpustate->d.d16
+
+INLINE void CYCLES(hc11_state *cpustate, int cycles)
+{
+ cpustate->icount -= cycles;
+}
+
+INLINE void SET_PC(hc11_state *cpustate, int pc)
+{
+ cpustate->pc = pc;
+}
+
+INLINE void PUSH8(hc11_state *cpustate, UINT8 value)
+{
+ WRITE8(cpustate, cpustate->sp--, value);
+}
+
+INLINE void PUSH16(hc11_state *cpustate, UINT16 value)
+{
+ WRITE8(cpustate, cpustate->sp--, (value >> 0) & 0xff);
+ WRITE8(cpustate, cpustate->sp--, (value >> 8) & 0xff);
+}
+
+INLINE UINT8 POP8(hc11_state *cpustate)
+{
+ return READ8(cpustate, ++cpustate->sp);
+}
+
+INLINE UINT16 POP16(hc11_state *cpustate)
+{
+ UINT16 r = 0;
+ r |= (READ8(cpustate, ++cpustate->sp) << 8);
+ r |= (READ8(cpustate, ++cpustate->sp) << 0);
+ return r;
+}
+
+
+
+/*****************************************************************************/
+
+/* ABA 0x1B */
+static void HC11OP(aba)(hc11_state *cpustate)
+{
+ UINT16 r = REG_A + REG_B;
+ CLEAR_HNZVC(cpustate);
+ SET_H(r, REG_B, REG_A);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_ADD8(r, REG_B, REG_A);
+ SET_C8(r);
+ REG_A = (UINT8)r;
+ CYCLES(cpustate, 2);
+}
+
+
+/* ABX 0x3A */
+static void HC11OP(abx)(hc11_state *cpustate)
+{
+ cpustate->ix += REG_B;
+ CYCLES(cpustate, 3);
+}
+
+
+/* ABY 0x18, 0x3A */
+static void HC11OP(aby)(hc11_state *cpustate)
+{
+ cpustate->iy += REG_B;
+ CYCLES(cpustate, 4);
+}
+
+
+/* ADCA IMM 0x89 */
+static void HC11OP(adca_imm)(hc11_state *cpustate)
+{
+ int c = (cpustate->ccr & CC_C) ? 1 : 0;
+ UINT8 i = FETCH(cpustate);
+ UINT16 r = REG_A + i + c;
+ CLEAR_HNZVC(cpustate);
+ SET_H(r, i+c, REG_A);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_ADD8(r, i+c, REG_A);
+ SET_C8(r);
+ REG_A = (UINT8)r;
+ CYCLES(cpustate, 2);
+}
+
+/* ADCA DIR 0x99 */
+static void HC11OP(adca_dir)(hc11_state *cpustate)
+{
+ int c = (cpustate->ccr & CC_C) ? 1 : 0;
+ UINT8 d = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, d);
+ UINT16 r = REG_A + i + c;
+ CLEAR_HNZVC(cpustate);
+ SET_H(r, i+c, REG_A);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_ADD8(r, i+c, REG_A);
+ SET_C8(r);
+ REG_A = (UINT8)r;
+ CYCLES(cpustate, 3);
+}
+
+/* ADCA EXT 0xB9 */
+static void HC11OP(adca_ext)(hc11_state *cpustate)
+{
+ int c = (cpustate->ccr & CC_C) ? 1 : 0;
+ UINT16 adr = FETCH16(cpustate);
+ UINT8 i = READ8(cpustate, adr);
+ UINT16 r = REG_A + i + c;
+ CLEAR_HNZVC(cpustate);
+ SET_H(r, i+c, REG_A);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_ADD8(r, i+c, REG_A);
+ SET_C8(r);
+ REG_A = (UINT8)r;
+ CYCLES(cpustate, 4);
+}
+
+/* ADCA IND, X 0xA9 */
+static void HC11OP(adca_indx)(hc11_state *cpustate)
+{
+ int c = (cpustate->ccr & CC_C) ? 1 : 0;
+ UINT8 offset = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->ix + offset);
+ UINT16 r = REG_A + i + c;
+ CLEAR_HNZVC(cpustate);
+ SET_H(r, i+c, REG_A);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_ADD8(r, i+c, REG_A);
+ SET_C8(r);
+ REG_A = (UINT8)r;
+ CYCLES(cpustate, 4);
+}
+
+/* ADCA IND, Y 0x18, 0xA9 */
+static void HC11OP(adca_indy)(hc11_state *cpustate)
+{
+ int c = (cpustate->ccr & CC_C) ? 1 : 0;
+ UINT8 offset = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->iy + offset);
+ UINT16 r = REG_A + i + c;
+ CLEAR_HNZVC(cpustate);
+ SET_H(r, i+c, REG_A);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_ADD8(r, i+c, REG_A);
+ SET_C8(r);
+ REG_A = (UINT8)r;
+ CYCLES(cpustate, 5);
+}
+
+
+/* ADCB IMM 0xC9 */
+static void HC11OP(adcb_imm)(hc11_state *cpustate)
+{
+ int c = (cpustate->ccr & CC_C) ? 1 : 0;
+ UINT8 i = FETCH(cpustate);
+ UINT16 r = REG_B + i + c;
+ CLEAR_HNZVC(cpustate);
+ SET_H(r, i+c, REG_B);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_ADD8(r, i+c, REG_B);
+ SET_C8(r);
+ REG_B = (UINT8)r;
+ CYCLES(cpustate, 2);
+}
+
+/* ADCB DIR 0xD9 */
+static void HC11OP(adcb_dir)(hc11_state *cpustate)
+{
+ int c = (cpustate->ccr & CC_C) ? 1 : 0;
+ UINT8 d = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, d);
+ UINT16 r = REG_B + i + c;
+ CLEAR_HNZVC(cpustate);
+ SET_H(r, i+c, REG_B);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_ADD8(r, i+c, REG_B);
+ SET_C8(r);
+ REG_B = (UINT8)r;
+ CYCLES(cpustate, 3);
+}
+
+/* ADCB EXT 0xF9 */
+static void HC11OP(adcb_ext)(hc11_state *cpustate)
+{
+ int c = (cpustate->ccr & CC_C) ? 1 : 0;
+ UINT16 adr = FETCH16(cpustate);
+ UINT8 i = READ8(cpustate, adr);
+ UINT16 r = REG_B + i + c;
+ CLEAR_HNZVC(cpustate);
+ SET_H(r, i+c, REG_B);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_ADD8(r, i+c, REG_B);
+ SET_C8(r);
+ REG_B = (UINT8)r;
+ CYCLES(cpustate, 4);
+}
+
+/* ADCB IND, X 0xE9 */
+static void HC11OP(adcb_indx)(hc11_state *cpustate)
+{
+ int c = (cpustate->ccr & CC_C) ? 1 : 0;
+ UINT8 offset = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->ix + offset);
+ UINT16 r = REG_B + i + c;
+ CLEAR_HNZVC(cpustate);
+ SET_H(r, i+c, REG_B);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_ADD8(r, i+c, REG_B);
+ SET_C8(r);
+ REG_B = (UINT8)r;
+ CYCLES(cpustate, 4);
+}
+
+/* ADCB IND, Y 0x18, 0xE9 */
+static void HC11OP(adcb_indy)(hc11_state *cpustate)
+{
+ int c = (cpustate->ccr & CC_C) ? 1 : 0;
+ UINT8 offset = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->iy + offset);
+ UINT16 r = REG_B + i + c;
+ CLEAR_HNZVC(cpustate);
+ SET_H(r, i+c, REG_B);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_ADD8(r, i+c, REG_B);
+ SET_C8(r);
+ REG_B = (UINT8)r;
+ CYCLES(cpustate, 5);
+}
+
+
+/* ADDA IMM 0x8B */
+static void HC11OP(adda_imm)(hc11_state *cpustate)
+{
+ UINT8 i = FETCH(cpustate);
+ UINT16 r = REG_A + i;
+ CLEAR_HNZVC(cpustate);
+ SET_H(r, i, REG_A);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_ADD8(r, i, REG_A);
+ SET_C8(r);
+ REG_A = (UINT8)r;
+ CYCLES(cpustate, 2);
+}
+
+/* ADDA DIR 0x9B */
+static void HC11OP(adda_dir)(hc11_state *cpustate)
+{
+ UINT8 d = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, d);
+ UINT16 r = REG_A + i;
+ CLEAR_HNZVC(cpustate);
+ SET_H(r, i, REG_A);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_ADD8(r, i, REG_A);
+ SET_C8(r);
+ REG_A = (UINT8)r;
+ CYCLES(cpustate, 3);
+}
+
+/* ADDA EXT 0xBB */
+static void HC11OP(adda_ext)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH16(cpustate);
+ UINT8 i = READ8(cpustate, adr);
+ UINT16 r = REG_A + i;
+ CLEAR_HNZVC(cpustate);
+ SET_H(r, i, REG_A);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_ADD8(r, i, REG_A);
+ SET_C8(r);
+ REG_A = (UINT8)r;
+ CYCLES(cpustate, 4);
+}
+
+/* ADDA IND, X 0xAB */
+static void HC11OP(adda_indx)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->ix + offset);
+ UINT16 r = REG_A + i;
+ CLEAR_HNZVC(cpustate);
+ SET_H(r, i, REG_A);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_ADD8(r, i, REG_A);
+ SET_C8(r);
+ REG_A = (UINT8)r;
+ CYCLES(cpustate, 4);
+}
+
+/* ADDA IND, Y 0x18, 0xAB */
+static void HC11OP(adda_indy)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->iy + offset);
+ UINT16 r = REG_A + i;
+ CLEAR_HNZVC(cpustate);
+ SET_H(r, i, REG_A);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_ADD8(r, i, REG_A);
+ SET_C8(r);
+ REG_A = (UINT8)r;
+ CYCLES(cpustate, 5);
+}
+
+
+/* ADDB IMM 0xCB */
+static void HC11OP(addb_imm)(hc11_state *cpustate)
+{
+ UINT8 i = FETCH(cpustate);
+ UINT16 r = REG_B + i;
+ CLEAR_HNZVC(cpustate);
+ SET_H(r, i, REG_B);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_ADD8(r, i, REG_B);
+ SET_C8(r);
+ REG_B = (UINT8)r;
+ CYCLES(cpustate, 2);
+}
+
+/* ADDB DIR 0xDB */
+static void HC11OP(addb_dir)(hc11_state *cpustate)
+{
+ UINT8 d = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, d);
+ UINT16 r = REG_B + i;
+ CLEAR_HNZVC(cpustate);
+ SET_H(r, i, REG_B);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_ADD8(r, i, REG_B);
+ SET_C8(r);
+ REG_B = (UINT8)r;
+ CYCLES(cpustate, 3);
+}
+
+/* ADDB EXT 0xFB */
+static void HC11OP(addb_ext)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH16(cpustate);
+ UINT8 i = READ8(cpustate, adr);
+ UINT16 r = REG_B + i;
+ CLEAR_HNZVC(cpustate);
+ SET_H(r, i, REG_B);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_ADD8(r, i, REG_B);
+ SET_C8(r);
+ REG_B = (UINT8)r;
+ CYCLES(cpustate, 4);
+}
+
+/* ADDB IND, X 0xEB */
+static void HC11OP(addb_indx)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->ix + offset);
+ UINT16 r = REG_B + i;
+ CLEAR_HNZVC(cpustate);
+ SET_H(r, i, REG_B);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_ADD8(r, i, REG_B);
+ SET_C8(r);
+ REG_B = (UINT8)r;
+ CYCLES(cpustate, 4);
+}
+
+/* ADDB IND, Y 0x18, 0xEB */
+static void HC11OP(addb_indy)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->iy + offset);
+ UINT16 r = REG_B + i;
+ CLEAR_HNZVC(cpustate);
+ SET_H(r, i, REG_B);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_ADD8(r, i, REG_B);
+ SET_C8(r);
+ REG_B = (UINT8)r;
+ CYCLES(cpustate, 5);
+}
+
+
+/* ADDD IMM 0xC3 */
+static void HC11OP(addd_imm)(hc11_state *cpustate)
+{
+ UINT16 i = FETCH16(cpustate);
+ UINT32 r = REG_D + i;
+ CLEAR_NZVC(cpustate);
+ SET_N16(r);
+ SET_Z16(r);
+ SET_V_ADD16(r, i, REG_D);
+ SET_C16(r);
+ REG_D = (UINT16)r;
+ CYCLES(cpustate, 4);
+}
+
+/* ADDD DIR 0xD3 */
+static void HC11OP(addd_dir)(hc11_state *cpustate)
+{
+ UINT8 d = FETCH(cpustate);
+ UINT16 i = READ16(cpustate, d);
+ UINT32 r = REG_D + i;
+ CLEAR_NZVC(cpustate);
+ SET_N16(r);
+ SET_Z16(r);
+ SET_V_ADD16(r, i, REG_D);
+ SET_C16(r);
+ REG_D = (UINT16)r;
+ CYCLES(cpustate, 5);
+}
+
+/* ADDD EXT 0xF3 */
+static void HC11OP(addd_ext)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH16(cpustate);
+ UINT16 i = READ16(cpustate, adr);
+ UINT32 r = REG_D + i;
+ CLEAR_NZVC(cpustate);
+ SET_N16(r);
+ SET_Z16(r);
+ SET_V_ADD16(r, i, REG_D);
+ SET_C16(r);
+ REG_D = (UINT16)r;
+ CYCLES(cpustate, 6);
+}
+
+/* ADDD IND, X 0xE3 */
+static void HC11OP(addd_indx)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT16 i = READ16(cpustate, cpustate->ix + offset);
+ UINT32 r = REG_D + i;
+ CLEAR_NZVC(cpustate);
+ SET_N16(r);
+ SET_Z16(r);
+ SET_V_ADD16(r, i, REG_D);
+ SET_C16(r);
+ REG_D = (UINT16)r;
+ CYCLES(cpustate, 6);
+}
+
+/* ADDD IND, Y 0x18, 0xE3 */
+static void HC11OP(addd_indy)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT16 i = READ16(cpustate, cpustate->iy + offset);
+ UINT32 r = REG_D + i;
+ CLEAR_NZVC(cpustate);
+ SET_N16(r);
+ SET_Z16(r);
+ SET_V_ADD16(r, i, REG_D);
+ SET_C16(r);
+ REG_D = (UINT16)r;
+ CYCLES(cpustate, 7);
+}
+
+
+/* ANDA IMM 0x84 */
+static void HC11OP(anda_imm)(hc11_state *cpustate)
+{
+ UINT8 i = FETCH(cpustate);
+ CLEAR_NZV(cpustate);
+ REG_A &= i;
+ SET_N8(REG_A);
+ SET_Z8(REG_A);
+ CYCLES(cpustate, 2);
+}
+
+/* ANDA DIR 0x94 */
+static void HC11OP(anda_dir)(hc11_state *cpustate)
+{
+ UINT8 d = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, d);
+ CLEAR_NZV(cpustate);
+ REG_A &= i;
+ SET_N8(REG_A);
+ SET_Z8(REG_A);
+ CYCLES(cpustate, 3);
+}
+
+/* ANDA EXT 0xB4 */
+static void HC11OP(anda_ext)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH16(cpustate);
+ UINT8 i = READ8(cpustate, adr);
+ CLEAR_NZV(cpustate);
+ REG_A &= i;
+ SET_N8(REG_A);
+ SET_Z8(REG_A);
+ CYCLES(cpustate, 4);
+}
+
+/* ANDA IND, X 0xA4 */
+static void HC11OP(anda_indx)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->ix + offset);
+ CLEAR_NZV(cpustate);
+ REG_A &= i;
+ SET_N8(REG_A);
+ SET_Z8(REG_A);
+ CYCLES(cpustate, 4);
+}
+
+/* ANDA IND, Y 0x18, 0xA4 */
+static void HC11OP(anda_indy)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->iy + offset);
+ CLEAR_NZV(cpustate);
+ REG_A &= i;
+ SET_N8(REG_A);
+ SET_Z8(REG_A);
+ CYCLES(cpustate, 5);
+}
+
+
+/* ANDB IMM 0xC4 */
+static void HC11OP(andb_imm)(hc11_state *cpustate)
+{
+ UINT8 i = FETCH(cpustate);
+ CLEAR_NZV(cpustate);
+ REG_B &= i;
+ SET_N8(REG_B);
+ SET_Z8(REG_B);
+ CYCLES(cpustate, 2);
+}
+
+/* ANDB DIR 0xD4 */
+static void HC11OP(andb_dir)(hc11_state *cpustate)
+{
+ UINT8 d = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, d);
+ CLEAR_NZV(cpustate);
+ REG_B &= i;
+ SET_N8(REG_B);
+ SET_Z8(REG_B);
+ CYCLES(cpustate, 3);
+}
+
+/* ANDB EXT 0xF4 */
+static void HC11OP(andb_ext)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH16(cpustate);
+ UINT8 i = READ8(cpustate, adr);
+ CLEAR_NZV(cpustate);
+ REG_B &= i;
+ SET_N8(REG_B);
+ SET_Z8(REG_B);
+ CYCLES(cpustate, 4);
+}
+
+/* ANDB IND, X 0xE4 */
+static void HC11OP(andb_indx)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->ix + offset);
+ CLEAR_NZV(cpustate);
+ REG_B &= i;
+ SET_N8(REG_B);
+ SET_Z8(REG_B);
+ CYCLES(cpustate, 4);
+}
+
+/* ANDB IND, Y 0x18, 0xE4 */
+static void HC11OP(andb_indy)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->iy + offset);
+ CLEAR_NZV(cpustate);
+ REG_B &= i;
+ SET_N8(REG_B);
+ SET_Z8(REG_B);
+ CYCLES(cpustate, 5);
+}
+
+/* ASLA 0x48 */
+static void HC11OP(asla)(hc11_state *cpustate)
+{
+ UINT16 r = REG_A << 1;
+ CLEAR_NZVC(cpustate);
+ SET_C8(r);
+ REG_A = (UINT16)(r);
+ SET_N8(REG_A);
+ SET_Z8(REG_A);
+
+ if (((cpustate->ccr & CC_N) == CC_N && (cpustate->ccr & CC_C) == 0) ||
+ ((cpustate->ccr & CC_N) == 0 && (cpustate->ccr & CC_C) == CC_C))
+ {
+ cpustate->ccr |= CC_V;
+ }
+
+ CYCLES(cpustate, 2);
+}
+
+/* ASLB 0x58 */
+static void HC11OP(aslb)(hc11_state *cpustate)
+{
+ UINT16 r = REG_B << 1;
+ CLEAR_NZVC(cpustate);
+ SET_C8(r);
+ REG_B = (UINT16)(r);
+ SET_N8(REG_B);
+ SET_Z8(REG_B);
+
+ if (((cpustate->ccr & CC_N) == CC_N && (cpustate->ccr & CC_C) == 0) ||
+ ((cpustate->ccr & CC_N) == 0 && (cpustate->ccr & CC_C) == CC_C))
+ {
+ cpustate->ccr |= CC_V;
+ }
+
+ CYCLES(cpustate, 2);
+}
+
+/* BITA IMM 0x85 */
+static void HC11OP(bita_imm)(hc11_state *cpustate)
+{
+ UINT8 i = FETCH(cpustate);
+ UINT8 r = REG_A & i;
+ CLEAR_NZV(cpustate);
+ SET_N8(r);
+ SET_Z8(r);
+ CYCLES(cpustate, 2);
+}
+
+/* BITA DIR 0x95 */
+static void HC11OP(bita_dir)(hc11_state *cpustate)
+{
+ UINT8 d = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, d);
+ UINT8 r = REG_A & i;
+ CLEAR_NZV(cpustate);
+ SET_N8(r);
+ SET_Z8(r);
+ CYCLES(cpustate, 3);
+}
+
+/* BITA EXT 0xB5 */
+static void HC11OP(bita_ext)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH16(cpustate);
+ UINT8 i = READ8(cpustate, adr);
+ UINT8 r = REG_A & i;
+ CLEAR_NZV(cpustate);
+ SET_N8(r);
+ SET_Z8(r);
+ CYCLES(cpustate, 4);
+}
+
+/* BITA IND, X 0xA5 */
+static void HC11OP(bita_indx)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->ix + offset);
+ UINT8 r = REG_A & i;
+ CLEAR_NZV(cpustate);
+ SET_N8(r);
+ SET_Z8(r);
+ CYCLES(cpustate, 4);
+}
+
+/* BITA IND, Y 0x18, 0xA5 */
+static void HC11OP(bita_indy)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->iy + offset);
+ UINT8 r = REG_A & i;
+ CLEAR_NZV(cpustate);
+ SET_N8(r);
+ SET_Z8(r);
+ CYCLES(cpustate, 5);
+}
+
+
+/* BITB IMM 0xC5 */
+static void HC11OP(bitb_imm)(hc11_state *cpustate)
+{
+ UINT8 i = FETCH(cpustate);
+ UINT8 r = REG_B & i;
+ CLEAR_NZV(cpustate);
+ SET_N8(r);
+ SET_Z8(r);
+ CYCLES(cpustate, 2);
+}
+
+/* BITB DIR 0xD5 */
+static void HC11OP(bitb_dir)(hc11_state *cpustate)
+{
+ UINT8 d = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, d);
+ UINT8 r = REG_B & i;
+ CLEAR_NZV(cpustate);
+ SET_N8(r);
+ SET_Z8(r);
+ CYCLES(cpustate, 3);
+}
+
+/* BITB EXT 0xF5 */
+static void HC11OP(bitb_ext)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH16(cpustate);
+ UINT8 i = READ8(cpustate, adr);
+ UINT8 r = REG_B & i;
+ CLEAR_NZV(cpustate);
+ SET_N8(r);
+ SET_Z8(r);
+ CYCLES(cpustate, 4);
+}
+
+/* BITB IND, X 0xE5 */
+static void HC11OP(bitb_indx)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->ix + offset);
+ UINT8 r = REG_B & i;
+ CLEAR_NZV(cpustate);
+ SET_N8(r);
+ SET_Z8(r);
+ CYCLES(cpustate, 4);
+}
+
+/* BITB IND, Y 0x18, 0xE5 */
+static void HC11OP(bitb_indy)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->iy + offset);
+ UINT8 r = REG_B & i;
+ CLEAR_NZV(cpustate);
+ SET_N8(r);
+ SET_Z8(r);
+ CYCLES(cpustate, 5);
+}
+
+/* BCC 0x24 */
+static void HC11OP(bcc)(hc11_state *cpustate)
+{
+ INT8 rel = FETCH(cpustate);
+ if ((cpustate->ccr & CC_C) == 0) /* Branch if C flag clear */
+ {
+ SET_PC(cpustate, cpustate->ppc + rel + 2);
+ }
+ CYCLES(cpustate, 3);
+}
+
+/* BCLR INDX 0x1d */
+static void HC11OP(bclr_indx)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT8 mask = FETCH(cpustate);
+ UINT8 r = READ8(cpustate, cpustate->ix + offset);
+ r = r & ~mask;
+ WRITE8(cpustate, cpustate->ix + offset, r);
+ CLEAR_NZV(cpustate);
+ SET_N8(r);
+ SET_Z8(r);
+
+ CYCLES(cpustate, 7);
+}
+
+/* BCS 0x25 */
+static void HC11OP(bcs)(hc11_state *cpustate)
+{
+ INT8 rel = FETCH(cpustate);
+ if (cpustate->ccr & CC_C) /* Branch if C flag set */
+ {
+ SET_PC(cpustate, cpustate->ppc + rel + 2);
+ }
+ CYCLES(cpustate, 3);
+}
+
+
+/* BEQ 0x27 */
+static void HC11OP(beq)(hc11_state *cpustate)
+{
+ INT8 rel = FETCH(cpustate);
+ if (cpustate->ccr & CC_Z) /* Branch if Z flag set */
+ {
+ SET_PC(cpustate, cpustate->ppc + rel + 2);
+ }
+ CYCLES(cpustate, 3);
+}
+
+
+/* BHI 0x22 */
+static void HC11OP(bhi)(hc11_state *cpustate)
+{
+ INT8 rel = FETCH(cpustate);
+ if (((cpustate->ccr & CC_C) == 0) && ((cpustate->ccr & CC_Z) == 0)) /* Branch if C and Z flag clear */
+ {
+ SET_PC(cpustate, cpustate->ppc + rel + 2);
+ }
+ CYCLES(cpustate, 3);
+}
+
+
+/* BNE 0x26 */
+static void HC11OP(bne)(hc11_state *cpustate)
+{
+ INT8 rel = FETCH(cpustate);
+ if ((cpustate->ccr & CC_Z) == 0) /* Branch if Z flag clear */
+ {
+ SET_PC(cpustate, cpustate->ppc + rel + 2);
+ }
+ CYCLES(cpustate, 3);
+}
+
+
+/* BLE 0x2F */
+static void HC11OP(ble)(hc11_state *cpustate)
+{
+ UINT8 n = (cpustate->ccr & CC_N) ? 1 : 0;
+ UINT8 v = (cpustate->ccr & CC_V) ? 1 : 0;
+ INT8 rel = FETCH(cpustate);
+ if ((cpustate->ccr & CC_Z) || (n ^ v)) /* Branch if Z flag set or (N ^ V) */
+ {
+ SET_PC(cpustate, cpustate->ppc + rel + 2);
+ }
+ CYCLES(cpustate, 3);
+}
+
+/* BLS 0x23 */
+static void HC11OP(bls)(hc11_state *cpustate)
+{
+ INT8 rel = FETCH(cpustate);
+ if (cpustate->ccr & CC_C || cpustate->ccr & CC_Z) /* Branch if C or Z flag set */
+ {
+ SET_PC(cpustate, cpustate->ppc + rel + 2);
+ }
+ CYCLES(cpustate, 3);
+}
+
+/* BMI 0x2B */
+static void HC11OP(bmi)(hc11_state *cpustate)
+{
+ INT8 rel = FETCH(cpustate);
+ if (cpustate->ccr & CC_N) /* Branch if N flag set */
+ {
+ SET_PC(cpustate, cpustate->ppc + rel + 2);
+ }
+ CYCLES(cpustate, 3);
+}
+
+/* BPL 0x2A */
+static void HC11OP(bpl)(hc11_state *cpustate)
+{
+ INT8 rel = FETCH(cpustate);
+ if ((cpustate->ccr & CC_N) == 0) /* Branch if N flag clear */
+ {
+ SET_PC(cpustate, cpustate->ppc + rel + 2);
+ }
+ CYCLES(cpustate, 3);
+}
+
+
+/* BRA 0x20 */
+static void HC11OP(bra)(hc11_state *cpustate)
+{
+ INT8 rel = FETCH(cpustate);
+ SET_PC(cpustate, cpustate->ppc + rel + 2);
+ CYCLES(cpustate, 3);
+}
+
+/* BRCLR DIR 0x13 */
+static void HC11OP(brclr_dir)(hc11_state *cpustate)
+{
+ UINT8 d = FETCH(cpustate);
+ UINT8 mask = FETCH(cpustate);
+ INT8 rel = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, d);
+
+ if(!(i & mask))
+ {
+ SET_PC(cpustate, cpustate->ppc + rel + 4);
+ }
+
+ CYCLES(cpustate, 6);
+}
+
+
+/* BRCLR INDX 0x1F */
+static void HC11OP(brclr_indx)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT8 mask = FETCH(cpustate);
+ INT8 rel = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->ix + offset);
+
+ if(!(i & mask))
+ {
+ SET_PC(cpustate, cpustate->ppc + rel + 4);
+ }
+
+ CYCLES(cpustate, 7);
+}
+
+/* BRSET DIR 0x12 */
+static void HC11OP(brset_dir)(hc11_state *cpustate)
+{
+ UINT8 d = FETCH(cpustate);
+ UINT8 mask = FETCH(cpustate);
+ INT8 rel = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, d);
+
+ if(i & mask)
+ {
+ SET_PC(cpustate, cpustate->ppc + rel + 4);
+ }
+
+ CYCLES(cpustate, 6);
+}
+
+
+/* BRSET INDX 0x1E */
+static void HC11OP(brset_indx)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT8 mask = FETCH(cpustate);
+ INT8 rel = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->ix + offset);
+
+ if(i & mask)
+ {
+ SET_PC(cpustate, cpustate->ppc + rel + 4);
+ }
+
+ CYCLES(cpustate, 7);
+}
+
+
+/* BRN 0x21 */
+static void HC11OP(brn)(hc11_state *cpustate)
+{
+ /* with this opcode the branch condition is always false. */
+ SET_PC(cpustate, cpustate->ppc + 2);
+ CYCLES(cpustate, 3);
+}
+
+/* BSET INDX 0x1c */
+static void HC11OP(bset_indx)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT8 mask = FETCH(cpustate);
+ UINT8 r = READ8(cpustate, cpustate->ix + offset);
+ r = (r & ~mask) | mask;
+ WRITE8(cpustate, cpustate->ix + offset, r);
+ CLEAR_NZV(cpustate);
+ SET_N8(r);
+ SET_Z8(r);
+
+ CYCLES(cpustate, 7);
+}
+
+/* BSR 0x8D */
+static void HC11OP(bsr)(hc11_state *cpustate)
+{
+ INT8 rel = FETCH(cpustate);
+ UINT16 rt_adr = cpustate->pc;
+ PUSH16(cpustate, rt_adr);
+ SET_PC(cpustate, cpustate->ppc + rel + 2);
+ CYCLES(cpustate, 6);
+}
+
+/* BVC 0x28 */
+static void HC11OP(bvc)(hc11_state *cpustate)
+{
+ INT8 rel = FETCH(cpustate);
+ if ((cpustate->ccr & CC_V) == 0) /* Branch if V flag clear */
+ {
+ SET_PC(cpustate, cpustate->ppc + rel + 2);
+ }
+ CYCLES(cpustate, 3);
+}
+
+/* BVS 0x29 */
+static void HC11OP(bvs)(hc11_state *cpustate)
+{
+ INT8 rel = FETCH(cpustate);
+ if (cpustate->ccr & CC_V) /* Branch if V flag set */
+ {
+ SET_PC(cpustate, cpustate->ppc + rel + 2);
+ }
+ CYCLES(cpustate, 3);
+}
+
+/* CBA 0x11 */
+static void HC11OP(cba)(hc11_state *cpustate)
+{
+ UINT16 r = REG_A - REG_B;
+ CLEAR_NZVC(cpustate);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_SUB8(r, REG_B, REG_A);
+ SET_C8(r);
+ CYCLES(cpustate, 2);
+}
+
+/* CLC 0x0C */
+static void HC11OP(clc)(hc11_state *cpustate)
+{
+ cpustate->ccr &= ~CC_C;
+ CYCLES(cpustate, 2);
+}
+
+
+/* CLI 0x0E */
+static void HC11OP(cli)(hc11_state *cpustate)
+{
+ cpustate->ccr &= ~CC_I;
+ CYCLES(cpustate, 2);
+}
+
+
+/* CLRA 0x4F */
+static void HC11OP(clra)(hc11_state *cpustate)
+{
+ REG_A = 0;
+ CLEAR_NZVC(cpustate);
+ SET_ZFLAG(cpustate);
+ CYCLES(cpustate, 2);
+}
+
+/* CLRB 0x5F */
+static void HC11OP(clrb)(hc11_state *cpustate)
+{
+ REG_B = 0;
+ CLEAR_NZVC(cpustate);
+ SET_ZFLAG(cpustate);
+ CYCLES(cpustate, 2);
+}
+
+/* CLR EXT 0x7F */
+static void HC11OP(clr_ext)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH16(cpustate);
+ WRITE8(cpustate, adr, 0);
+ CLEAR_NZVC(cpustate);
+ SET_ZFLAG(cpustate);
+ CYCLES(cpustate, 6);
+}
+
+/* CLR IND, X 0x6F */
+static void HC11OP(clr_indx)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ WRITE8(cpustate, cpustate->ix + offset, 0);
+ CLEAR_NZVC(cpustate);
+ SET_ZFLAG(cpustate);
+ CYCLES(cpustate, 6);
+}
+
+/* CLR IND, Y 0x18, 0x6F */
+static void HC11OP(clr_indy)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ WRITE8(cpustate, cpustate->iy + offset, 0);
+ CLEAR_NZVC(cpustate);
+ SET_ZFLAG(cpustate);
+ CYCLES(cpustate, 7);
+}
+
+
+/* CLV 0x0A */
+static void HC11OP(clv)(hc11_state *cpustate)
+{
+ cpustate->ccr &= ~CC_V;
+ CYCLES(cpustate, 2);
+}
+
+
+/* CMPA IMM 0x81 */
+static void HC11OP(cmpa_imm)(hc11_state *cpustate)
+{
+ UINT8 i = FETCH(cpustate);
+ UINT16 r = REG_A - i;
+ CLEAR_NZVC(cpustate);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_SUB8(r, i, REG_A);
+ SET_C8(r);
+ CYCLES(cpustate, 2);
+}
+
+/* CMPA DIR 0x91 */
+static void HC11OP(cmpa_dir)(hc11_state *cpustate)
+{
+ UINT8 d = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, d);
+ UINT16 r = REG_A - i;
+ CLEAR_NZVC(cpustate);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_SUB8(r, i, REG_A);
+ SET_C8(r);
+ CYCLES(cpustate, 3);
+}
+
+/* CMPA EXT 0xB1 */
+static void HC11OP(cmpa_ext)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH16(cpustate);
+ UINT8 i = READ8(cpustate, adr);
+ UINT16 r = REG_A - i;
+ CLEAR_NZVC(cpustate);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_SUB8(r, i, REG_A);
+ SET_C8(r);
+ CYCLES(cpustate, 4);
+}
+
+/* CMPA IND, X 0xA1 */
+static void HC11OP(cmpa_indx)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->ix + offset);
+ UINT16 r = REG_A - i;
+ CLEAR_NZVC(cpustate);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_SUB8(r, i, REG_A);
+ SET_C8(r);
+ CYCLES(cpustate, 4);
+}
+
+/* CMPA IND, Y 0x18, 0xA1 */
+static void HC11OP(cmpa_indy)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->iy + offset);
+ UINT16 r = REG_A - i;
+ CLEAR_NZVC(cpustate);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_SUB8(r, i, REG_A);
+ SET_C8(r);
+ CYCLES(cpustate, 5);
+}
+
+
+/* CMPB IMM 0xC1 */
+static void HC11OP(cmpb_imm)(hc11_state *cpustate)
+{
+ UINT8 i = FETCH(cpustate);
+ UINT16 r = REG_B - i;
+ CLEAR_NZVC(cpustate);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_SUB8(r, i, REG_B);
+ SET_C8(r);
+ CYCLES(cpustate, 2);
+}
+
+/* CMPB DIR 0xD1 */
+static void HC11OP(cmpb_dir)(hc11_state *cpustate)
+{
+ UINT8 d = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, d);
+ UINT16 r = REG_B - i;
+ CLEAR_NZVC(cpustate);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_SUB8(r, i, REG_B);
+ SET_C8(r);
+ CYCLES(cpustate, 3);
+}
+
+/* CMPB EXT 0xF1 */
+static void HC11OP(cmpb_ext)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH16(cpustate);
+ UINT8 i = READ8(cpustate, adr);
+ UINT16 r = REG_B - i;
+ CLEAR_NZVC(cpustate);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_SUB8(r, i, REG_B);
+ SET_C8(r);
+ CYCLES(cpustate, 4);
+}
+
+/* CMPB IND, X 0xE1 */
+static void HC11OP(cmpb_indx)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->ix + offset);
+ UINT16 r = REG_B - i;
+ CLEAR_NZVC(cpustate);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_SUB8(r, i, REG_B);
+ SET_C8(r);
+ CYCLES(cpustate, 4);
+}
+
+/* CMPB IND, Y 0x18, 0xE1 */
+static void HC11OP(cmpb_indy)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->iy + offset);
+ UINT16 r = REG_B - i;
+ CLEAR_NZVC(cpustate);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_SUB8(r, i, REG_B);
+ SET_C8(r);
+ CYCLES(cpustate, 5);
+}
+
+
+/* COMA , 0x43 */
+static void HC11OP(coma)(hc11_state *cpustate)
+{
+ UINT16 r = 0xff - REG_A;
+ CLEAR_NZVC(cpustate);
+ SET_N8(r);
+ SET_Z8(r);
+ cpustate->ccr |= CC_C; //always set for M6800 compatibility
+ REG_A = r;
+ CYCLES(cpustate, 2);
+}
+
+
+/* COMB , 0x53 */
+static void HC11OP(comb)(hc11_state *cpustate)
+{
+ UINT16 r = 0xff - REG_B;
+ CLEAR_NZVC(cpustate);
+ SET_N8(r);
+ SET_Z8(r);
+ cpustate->ccr |= CC_C; //always set for M6800 compatibility
+ REG_B = r;
+ CYCLES(cpustate, 2);
+}
+
+
+/* CPD IMM 0x1A, 0x83 */
+static void HC11OP(cpd_imm)(hc11_state *cpustate)
+{
+ UINT16 i = FETCH16(cpustate);
+ UINT32 r = REG_D - i;
+ CLEAR_NZVC(cpustate);
+ SET_N16(r);
+ SET_Z16(r);
+ SET_V_SUB16(r, i, REG_D);
+ SET_C16(r);
+ CYCLES(cpustate, 5);
+}
+
+/* CPD DIR 0x1A, 0x93 */
+static void HC11OP(cpd_dir)(hc11_state *cpustate)
+{
+ UINT8 d = FETCH(cpustate);
+ UINT16 i = READ16(cpustate, d);
+ UINT32 r = REG_D - i;
+ CLEAR_NZVC(cpustate);
+ SET_N16(r);
+ SET_Z16(r);
+ SET_V_SUB16(r, i, REG_D);
+ SET_C16(r);
+ CYCLES(cpustate, 6);
+}
+
+/* CPD EXT 0x1A, 0xB3 */
+static void HC11OP(cpd_ext)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH16(cpustate);
+ UINT16 i = READ16(cpustate, adr);
+ UINT32 r = REG_D - i;
+ CLEAR_NZVC(cpustate);
+ SET_N16(r);
+ SET_Z16(r);
+ SET_V_SUB16(r, i, REG_D);
+ SET_C16(r);
+ CYCLES(cpustate, 7);
+}
+
+/* CPD IND, X 0x1A, 0xA3 */
+static void HC11OP(cpd_indx)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT16 i = READ16(cpustate, cpustate->ix + offset);
+ UINT32 r = REG_D - i;
+ CLEAR_NZVC(cpustate);
+ SET_N16(r);
+ SET_Z16(r);
+ SET_V_SUB16(r, i, REG_D);
+ SET_C16(r);
+ CYCLES(cpustate, 7);
+}
+
+/* CPD IND, Y 0xCD, 0xA3 */
+static void HC11OP(cpd_indy)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT16 i = READ16(cpustate, cpustate->iy + offset);
+ UINT32 r = REG_D - i;
+ CLEAR_NZVC(cpustate);
+ SET_N16(r);
+ SET_Z16(r);
+ SET_V_SUB16(r, i, REG_D);
+ SET_C16(r);
+ CYCLES(cpustate, 7);
+}
+
+
+/* CPX IMM 0x8C */
+static void HC11OP(cpx_imm)(hc11_state *cpustate)
+{
+ UINT16 i = FETCH16(cpustate);
+ UINT32 r = cpustate->ix - i;
+ CLEAR_NZVC(cpustate);
+ SET_N16(r);
+ SET_Z16(r);
+ SET_V_SUB16(r, i, cpustate->ix);
+ SET_C16(r);
+ CYCLES(cpustate, 4);
+}
+
+/* CPX DIR 0x9C */
+static void HC11OP(cpx_dir)(hc11_state *cpustate)
+{
+ UINT8 d = FETCH(cpustate);
+ UINT16 i = READ16(cpustate, d);
+ UINT32 r = cpustate->ix - i;
+ CLEAR_NZVC(cpustate);
+ SET_N16(r);
+ SET_Z16(r);
+ SET_V_SUB16(r, i, cpustate->ix);
+ SET_C16(r);
+ CYCLES(cpustate, 5);
+}
+
+/* CPX EXT 0xBC */
+static void HC11OP(cpx_ext)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH16(cpustate);
+ UINT16 i = READ16(cpustate, adr);
+ UINT32 r = cpustate->ix - i;
+ CLEAR_NZVC(cpustate);
+ SET_N16(r);
+ SET_Z16(r);
+ SET_V_SUB16(r, i, cpustate->ix);
+ SET_C16(r);
+ CYCLES(cpustate, 6);
+}
+
+/* CPX IND, X 0xAC */
+static void HC11OP(cpx_indx)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT16 i = READ16(cpustate, cpustate->ix + offset);
+ UINT32 r = cpustate->ix - i;
+ CLEAR_NZVC(cpustate);
+ SET_N16(r);
+ SET_Z16(r);
+ SET_V_SUB16(r, i, cpustate->ix);
+ SET_C16(r);
+ CYCLES(cpustate, 6);
+}
+
+/* CPX IND, Y 0xCD, 0xAC */
+static void HC11OP(cpx_indy)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT16 i = READ16(cpustate, cpustate->iy + offset);
+ UINT32 r = cpustate->ix - i;
+ CLEAR_NZVC(cpustate);
+ SET_N16(r);
+ SET_Z16(r);
+ SET_V_SUB16(r, i, cpustate->ix);
+ SET_C16(r);
+ CYCLES(cpustate, 7);
+}
+
+/* CPY IMM 0x18, 0x8C */
+static void HC11OP(cpy_imm)(hc11_state *cpustate)
+{
+ UINT16 i = FETCH16(cpustate);
+ UINT32 r = cpustate->iy - i;
+ CLEAR_NZVC(cpustate);
+ SET_N16(r);
+ SET_Z16(r);
+ SET_V_SUB16(r, i, cpustate->iy);
+ SET_C16(r);
+ CYCLES(cpustate, 5);
+}
+
+/* CPY DIR 0x18 0x9C */
+static void HC11OP(cpy_dir)(hc11_state *cpustate)
+{
+ UINT8 d = FETCH(cpustate);
+ UINT16 i = READ16(cpustate, d);
+ UINT32 r = cpustate->iy - i;
+ CLEAR_NZVC(cpustate);
+ SET_N16(r);
+ SET_Z16(r);
+ SET_V_SUB16(r, i, cpustate->iy);
+ SET_C16(r);
+ CYCLES(cpustate, 6);
+}
+
+/* CPY EXT 0x18 0xBC */
+static void HC11OP(cpy_ext)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH16(cpustate);
+ UINT16 i = READ16(cpustate, adr);
+ UINT32 r = cpustate->iy - i;
+ CLEAR_NZVC(cpustate);
+ SET_N16(r);
+ SET_Z16(r);
+ SET_V_SUB16(r, i, cpustate->iy);
+ SET_C16(r);
+ CYCLES(cpustate, 7);
+}
+
+/* CPY IND, X 0x1A 0xAC */
+static void HC11OP(cpy_indx)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT16 i = READ16(cpustate, cpustate->ix + offset);
+ UINT32 r = cpustate->iy - i;
+ CLEAR_NZVC(cpustate);
+ SET_N16(r);
+ SET_Z16(r);
+ SET_V_SUB16(r, i, cpustate->iy);
+ SET_C16(r);
+ CYCLES(cpustate, 7);
+}
+
+/* CPY IND, Y 0x18 0xAC */
+static void HC11OP(cpy_indy)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT16 i = READ16(cpustate, cpustate->iy + offset);
+ UINT32 r = cpustate->iy - i;
+ CLEAR_NZVC(cpustate);
+ SET_N16(r);
+ SET_Z16(r);
+ SET_V_SUB16(r, i, cpustate->iy);
+ SET_C16(r);
+ CYCLES(cpustate, 7);
+}
+
+/* DECA 0x4A */
+static void HC11OP(deca)(hc11_state *cpustate)
+{
+ CLEAR_NZV(cpustate);
+ if (REG_A == 0x80)
+ SET_VFLAG(cpustate);
+ REG_A--;
+ SET_N8(REG_A);
+ SET_Z8(REG_A);
+ CYCLES(cpustate, 2);
+}
+
+/* DECB 0x5A */
+static void HC11OP(decb)(hc11_state *cpustate)
+{
+ CLEAR_NZV(cpustate);
+ if (REG_B == 0x80)
+ SET_VFLAG(cpustate);
+ REG_B--;
+ SET_N8(REG_B);
+ SET_Z8(REG_B);
+ CYCLES(cpustate, 2);
+}
+
+/* DEC EXT 0x7A */
+static void HC11OP(dec_ext)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH16(cpustate);
+ UINT8 i = READ8(cpustate, adr);
+
+ CLEAR_NZV(cpustate);
+ if (i == 0x80)
+ SET_VFLAG(cpustate);
+ i--;
+ SET_N8(i);
+ SET_Z8(i);
+ WRITE8(cpustate, adr, i);
+ CYCLES(cpustate, 6);
+}
+
+/* DEC INDX 0x6A */
+static void HC11OP(dec_indx)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->ix + offset);
+
+ CLEAR_NZV(cpustate);
+ if (i == 0x80)
+ SET_VFLAG(cpustate);
+ i--;
+ SET_N8(i);
+ SET_Z8(i);
+ WRITE8(cpustate, cpustate->ix + offset, i);
+ CYCLES(cpustate, 6);
+}
+
+/* DEC INDY 0x18 0x6A */
+static void HC11OP(dec_indy)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->iy + offset);
+
+ CLEAR_NZV(cpustate);
+ if (i == 0x80)
+ SET_VFLAG(cpustate);
+ i--;
+ SET_N8(i);
+ SET_Z8(i);
+ WRITE8(cpustate, cpustate->iy + offset, i);
+ CYCLES(cpustate, 7);
+}
+
+/* DEX 0x09 */
+static void HC11OP(dex)(hc11_state *cpustate)
+{
+ CLEAR_Z(cpustate);
+ cpustate->ix--;
+ SET_Z16(cpustate->ix);
+ CYCLES(cpustate, 3);
+}
+
+
+/* DEY 0x18, 0x09 */
+static void HC11OP(dey)(hc11_state *cpustate)
+{
+ CLEAR_Z(cpustate);
+ cpustate->iy--;
+ SET_Z16(cpustate->iy);
+ CYCLES(cpustate, 4);
+}
+
+
+/* EORA IMM 0x88 */
+static void HC11OP(eora_imm)(hc11_state *cpustate)
+{
+ UINT8 i = FETCH(cpustate);
+ CLEAR_NZV(cpustate);
+ REG_A ^= i;
+ SET_N8(REG_A);
+ SET_Z8(REG_A);
+ CYCLES(cpustate, 2);
+}
+
+/* EORA DIR 0x98 */
+static void HC11OP(eora_dir)(hc11_state *cpustate)
+{
+ UINT8 d = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, d);
+ CLEAR_NZV(cpustate);
+ REG_A ^= i;
+ SET_N8(REG_A);
+ SET_Z8(REG_A);
+ CYCLES(cpustate, 3);
+}
+
+/* EORA EXT 0xB8 */
+static void HC11OP(eora_ext)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH16(cpustate);
+ UINT8 i = READ8(cpustate, adr);
+ CLEAR_NZV(cpustate);
+ REG_A ^= i;
+ SET_N8(REG_A);
+ SET_Z8(REG_A);
+ CYCLES(cpustate, 4);
+}
+
+/* EORA IND, X 0xA8 */
+static void HC11OP(eora_indx)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->ix + offset);
+ CLEAR_NZV(cpustate);
+ REG_A ^= i;
+ SET_N8(REG_A);
+ SET_Z8(REG_A);
+ CYCLES(cpustate, 4);
+}
+
+/* EORA IND, Y 0x18, 0xA8 */
+static void HC11OP(eora_indy)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->iy + offset);
+ CLEAR_NZV(cpustate);
+ REG_A ^= i;
+ SET_N8(REG_A);
+ SET_Z8(REG_A);
+ CYCLES(cpustate, 5);
+}
+
+
+/* EORB IMM 0xC8 */
+static void HC11OP(eorb_imm)(hc11_state *cpustate)
+{
+ UINT8 i = FETCH(cpustate);
+ CLEAR_NZV(cpustate);
+ REG_B ^= i;
+ SET_N8(REG_B);
+ SET_Z8(REG_B);
+ CYCLES(cpustate, 2);
+}
+
+/* EORB DIR 0xD8 */
+static void HC11OP(eorb_dir)(hc11_state *cpustate)
+{
+ UINT8 d = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, d);
+ CLEAR_NZV(cpustate);
+ REG_B ^= i;
+ SET_N8(REG_B);
+ SET_Z8(REG_B);
+ CYCLES(cpustate, 3);
+}
+
+/* EORB EXT 0xF8 */
+static void HC11OP(eorb_ext)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH16(cpustate);
+ UINT8 i = READ8(cpustate, adr);
+ CLEAR_NZV(cpustate);
+ REG_B ^= i;
+ SET_N8(REG_B);
+ SET_Z8(REG_B);
+ CYCLES(cpustate, 4);
+}
+
+/* EORB IND, X 0xE8 */
+static void HC11OP(eorb_indx)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->ix + offset);
+ CLEAR_NZV(cpustate);
+ REG_B ^= i;
+ SET_N8(REG_B);
+ SET_Z8(REG_B);
+ CYCLES(cpustate, 4);
+}
+
+/* EORB IND, Y 0x18, 0xE8 */
+static void HC11OP(eorb_indy)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->iy + offset);
+ CLEAR_NZV(cpustate);
+ REG_B ^= i;
+ SET_N8(REG_B);
+ SET_Z8(REG_B);
+ CYCLES(cpustate, 5);
+}
+
+/* IDIV 0x02 */
+static void HC11OP(idiv)(hc11_state *cpustate)
+{
+ UINT16 numerator = REG_D;
+ UINT16 denominator = cpustate->ix;
+ UINT16 remainder;
+ UINT16 result;
+
+ CLEAR_ZVC(cpustate);
+ if(denominator == 0) // divide by zero behaviour
+ {
+ remainder = 0xffff; // TODO: undefined behaviour according to the docs
+ result = 0xffff;
+ logerror("HC11: divide by zero at PC=%04x\n",cpustate->pc-1);
+ cpustate->ccr |= CC_C;
+ }
+ else
+ {
+ remainder = numerator % denominator;
+ result = numerator / denominator;
+ }
+ cpustate->ix = result;
+ REG_D = remainder;
+ SET_Z16(result);
+
+ CYCLES(cpustate, 41);
+}
+
+/* INCA 0x4C */
+static void HC11OP(inca)(hc11_state *cpustate)
+{
+ CLEAR_NZV(cpustate);
+ if (REG_A == 0x7f)
+ SET_VFLAG(cpustate);
+ REG_A++;
+ SET_N8(REG_A);
+ SET_Z8(REG_A);
+ CYCLES(cpustate, 2);
+}
+
+/* INCB 0x5C */
+static void HC11OP(incb)(hc11_state *cpustate)
+{
+ CLEAR_NZV(cpustate);
+ if (REG_B == 0x7f)
+ SET_VFLAG(cpustate);
+ REG_B++;
+ SET_N8(REG_B);
+ SET_Z8(REG_B);
+ CYCLES(cpustate, 2);
+}
+
+/* INC EXT 0x7C */
+static void HC11OP(inc_ext)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH16(cpustate);
+ UINT8 i = READ8(cpustate, adr);
+
+ CLEAR_NZV(cpustate);
+ if (i == 0x7f)
+ SET_VFLAG(cpustate);
+ i++;
+ SET_N8(i);
+ SET_Z8(i);
+ WRITE8(cpustate, adr, i);
+ CYCLES(cpustate, 6);
+}
+
+/* INC INDX 0x6C */
+static void HC11OP(inc_indx)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->ix + offset);
+
+ CLEAR_NZV(cpustate);
+ if (i == 0x7f)
+ SET_VFLAG(cpustate);
+ i++;
+ SET_N8(i);
+ SET_Z8(i);
+ WRITE8(cpustate, cpustate->ix + offset, i);
+ CYCLES(cpustate, 6);
+}
+
+
+/* INC INDY 0x18 0x6C */
+static void HC11OP(inc_indy)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->iy + offset);
+
+ CLEAR_NZV(cpustate);
+ if (i == 0x7f)
+ SET_VFLAG(cpustate);
+ i++;
+ SET_N8(i);
+ SET_Z8(i);
+ WRITE8(cpustate, cpustate->iy + offset, i);
+ CYCLES(cpustate, 7);
+}
+
+
+/* INX 0x08 */
+static void HC11OP(inx)(hc11_state *cpustate)
+{
+ CLEAR_Z(cpustate);
+ cpustate->ix++;
+ SET_Z16(cpustate->ix);
+ CYCLES(cpustate, 3);
+}
+
+/* INY 0x18, 0x08 */
+static void HC11OP(iny)(hc11_state *cpustate)
+{
+ CLEAR_Z(cpustate);
+ cpustate->iy++;
+ SET_Z16(cpustate->iy);
+ CYCLES(cpustate, 4);
+}
+
+/* JMP IND X 0x6E */
+static void HC11OP(jmp_indx)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH(cpustate);
+ SET_PC(cpustate, cpustate->ix + adr);
+ CYCLES(cpustate, 3);
+}
+
+/* JMP IND Y 0x18 0x6E */
+static void HC11OP(jmp_indy)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH(cpustate);
+ SET_PC(cpustate, cpustate->iy + adr);
+ CYCLES(cpustate, 4);
+}
+
+/* JMP EXT 0x7E */
+static void HC11OP(jmp_ext)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH16(cpustate);
+ SET_PC(cpustate, adr);
+ CYCLES(cpustate, 3);
+}
+
+
+/* JSR DIR 0x9D */
+static void HC11OP(jsr_dir)(hc11_state *cpustate)
+{
+ UINT8 i = FETCH(cpustate);
+ UINT16 rt_adr = cpustate->pc;
+ PUSH16(cpustate, rt_adr);
+ SET_PC(cpustate, i);
+ CYCLES(cpustate, 5);
+}
+
+/* JSR EXT 0xBD */
+static void HC11OP(jsr_ext)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH16(cpustate);
+ UINT16 rt_adr = cpustate->pc;
+ PUSH16(cpustate, rt_adr);
+ SET_PC(cpustate, adr);
+ CYCLES(cpustate, 6);
+}
+
+/* JSR IND, X 0xAD */
+static void HC11OP(jsr_indx)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT16 rt_adr = cpustate->pc;
+ PUSH16(cpustate, rt_adr);
+ SET_PC(cpustate, cpustate->ix + offset);
+ CYCLES(cpustate, 6);
+}
+
+/* JSR IND, Y 0x18, 0xAD */
+static void HC11OP(jsr_indy)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT16 rt_adr = cpustate->pc;
+ PUSH16(cpustate, rt_adr);
+ SET_PC(cpustate, cpustate->iy + offset);
+ CYCLES(cpustate, 6);
+}
+
+
+/* LDAA IMM 0x86 */
+static void HC11OP(ldaa_imm)(hc11_state *cpustate)
+{
+ CLEAR_NZV(cpustate);
+ REG_A = FETCH(cpustate);
+ SET_N8(REG_A);
+ SET_Z8(REG_A);
+ CYCLES(cpustate, 2);
+}
+
+/* LDAA DIR 0x96 */
+static void HC11OP(ldaa_dir)(hc11_state *cpustate)
+{
+ UINT8 d = FETCH(cpustate);
+ CLEAR_NZV(cpustate);
+ REG_A = READ8(cpustate, d);
+ SET_N8(REG_A);
+ SET_Z8(REG_A);
+ CYCLES(cpustate, 3);
+}
+
+/* LDAA EXT 0xB6 */
+static void HC11OP(ldaa_ext)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH16(cpustate);
+ CLEAR_NZV(cpustate);
+ REG_A = READ8(cpustate, adr);
+ SET_N8(REG_A);
+ SET_Z8(REG_A);
+ CYCLES(cpustate, 4);
+}
+
+/* LDAA IND, X 0xA6 */
+static void HC11OP(ldaa_indx)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ CLEAR_NZV(cpustate);
+ REG_A = READ8(cpustate, cpustate->ix + offset);
+ SET_N8(REG_A);
+ SET_Z8(REG_A);
+ CYCLES(cpustate, 4);
+}
+
+/* LDAA IND, Y 0x18, 0xA6 */
+static void HC11OP(ldaa_indy)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ CLEAR_NZV(cpustate);
+ REG_A = READ8(cpustate, cpustate->iy + offset);
+ SET_N8(REG_A);
+ SET_Z8(REG_A);
+ CYCLES(cpustate, 5);
+}
+
+/* LDAB IMM 0xC6 */
+static void HC11OP(ldab_imm)(hc11_state *cpustate)
+{
+ CLEAR_NZV(cpustate);
+ REG_B = FETCH(cpustate);
+ SET_N8(REG_B);
+ SET_Z8(REG_B);
+ CYCLES(cpustate, 2);
+}
+
+/* LDAB DIR 0xD6 */
+static void HC11OP(ldab_dir)(hc11_state *cpustate)
+{
+ UINT8 d = FETCH(cpustate);
+ CLEAR_NZV(cpustate);
+ REG_B = READ8(cpustate, d);
+ SET_N8(REG_B);
+ SET_Z8(REG_B);
+ CYCLES(cpustate, 3);
+}
+
+/* LDAB EXT 0xF6 */
+static void HC11OP(ldab_ext)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH16(cpustate);
+ CLEAR_NZV(cpustate);
+ REG_B = READ8(cpustate, adr);
+ SET_N8(REG_B);
+ SET_Z8(REG_B);
+ CYCLES(cpustate, 4);
+}
+
+/* LDAB IND, X 0xE6 */
+static void HC11OP(ldab_indx)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ CLEAR_NZV(cpustate);
+ REG_B = READ8(cpustate, cpustate->ix + offset);
+ SET_N8(REG_B);
+ SET_Z8(REG_B);
+ CYCLES(cpustate, 4);
+}
+
+/* LDAB IND, Y 0x18, 0xE6 */
+static void HC11OP(ldab_indy)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ CLEAR_NZV(cpustate);
+ REG_B = READ8(cpustate, cpustate->iy + offset);
+ SET_N8(REG_B);
+ SET_Z8(REG_B);
+ CYCLES(cpustate, 5);
+}
+
+
+/* LDD IMM 0xCC */
+static void HC11OP(ldd_imm)(hc11_state *cpustate)
+{
+ CLEAR_NZV(cpustate);
+ REG_D = FETCH16(cpustate);
+ SET_N16(REG_D);
+ SET_Z16(REG_D);
+ CYCLES(cpustate, 3);
+}
+
+/* LDD DIR 0xDC */
+static void HC11OP(ldd_dir)(hc11_state *cpustate)
+{
+ UINT8 d = FETCH(cpustate);
+ CLEAR_NZV(cpustate);
+ REG_D = READ16(cpustate, d);
+ SET_N16(REG_D);
+ SET_Z16(REG_D);
+ CYCLES(cpustate, 4);
+}
+
+/* LDD EXT 0xFC */
+static void HC11OP(ldd_ext)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH16(cpustate);
+ CLEAR_NZV(cpustate);
+ REG_D = READ16(cpustate, adr);
+ SET_N16(REG_D);
+ SET_Z16(REG_D);
+ CYCLES(cpustate, 5);
+}
+
+/* LDD IND, X 0xEC */
+static void HC11OP(ldd_indx)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ CLEAR_NZV(cpustate);
+ REG_D = READ16(cpustate, cpustate->ix + offset);
+ SET_N16(REG_D);
+ SET_Z16(REG_D);
+ CYCLES(cpustate, 5);
+}
+
+/* LDD IND, Y 0x18, 0xEC */
+static void HC11OP(ldd_indy)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ CLEAR_NZV(cpustate);
+ REG_D = READ16(cpustate, cpustate->iy + offset);
+ SET_N16(REG_D);
+ SET_Z16(REG_D);
+ CYCLES(cpustate, 6);
+}
+
+
+/* LDS IMM 0x8E */
+static void HC11OP(lds_imm)(hc11_state *cpustate)
+{
+ CLEAR_NZV(cpustate);
+ cpustate->sp = FETCH16(cpustate);
+ SET_N16(cpustate->sp);
+ SET_Z16(cpustate->sp);
+ CYCLES(cpustate, 3);
+}
+
+/* LDS DIR 0x9E */
+static void HC11OP(lds_dir)(hc11_state *cpustate)
+{
+ UINT8 i = FETCH(cpustate);
+ CLEAR_NZV(cpustate);
+ cpustate->sp = READ16(cpustate, i);
+ SET_N16(cpustate->sp);
+ SET_Z16(cpustate->sp);
+ CYCLES(cpustate, 4);
+}
+
+/* LDS EXT 0xBE */
+static void HC11OP(lds_ext)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH16(cpustate);
+ CLEAR_NZV(cpustate);
+ cpustate->sp = READ16(cpustate, adr);
+ SET_N16(cpustate->sp);
+ SET_Z16(cpustate->sp);
+ CYCLES(cpustate, 5);
+}
+
+/* LDS IND, X 0xAE */
+static void HC11OP(lds_indx)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ CLEAR_NZV(cpustate);
+ cpustate->sp = READ16(cpustate, cpustate->ix + offset);
+ SET_N16(cpustate->sp);
+ SET_Z16(cpustate->sp);
+ CYCLES(cpustate, 5);
+}
+
+/* LDS IND, Y 0x18, 0xAE */
+static void HC11OP(lds_indy)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ CLEAR_NZV(cpustate);
+ cpustate->sp = READ16(cpustate, cpustate->iy + offset);
+ SET_N16(cpustate->sp);
+ SET_Z16(cpustate->sp);
+ CYCLES(cpustate, 6);
+}
+
+
+/* LDX IMM 0xCE */
+static void HC11OP(ldx_imm)(hc11_state *cpustate)
+{
+ CLEAR_NZV(cpustate);
+ cpustate->ix = FETCH16(cpustate);
+ SET_N16(cpustate->ix);
+ SET_Z16(cpustate->ix);
+ CYCLES(cpustate, 3);
+}
+
+/* LDX DIR 0xDE */
+static void HC11OP(ldx_dir)(hc11_state *cpustate)
+{
+ UINT8 d = FETCH(cpustate);
+ CLEAR_NZV(cpustate);
+ cpustate->ix = READ16(cpustate, d);
+ SET_N16(cpustate->ix);
+ SET_Z16(cpustate->ix);
+ CYCLES(cpustate, 4);
+}
+
+/* LDX EXT 0xFE */
+static void HC11OP(ldx_ext)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH16(cpustate);
+ CLEAR_NZV(cpustate);
+ cpustate->ix = READ16(cpustate, adr);
+ SET_N16(cpustate->ix);
+ SET_Z16(cpustate->ix);
+ CYCLES(cpustate, 5);
+}
+
+/* LDX IND, X 0xEE */
+static void HC11OP(ldx_indx)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ CLEAR_NZV(cpustate);
+ cpustate->ix = READ16(cpustate, cpustate->ix + offset);
+ SET_N16(cpustate->ix);
+ SET_Z16(cpustate->ix);
+ CYCLES(cpustate, 5);
+}
+
+/* LDX IND, Y 0xCD, 0xEE */
+static void HC11OP(ldx_indy)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ CLEAR_NZV(cpustate);
+ cpustate->ix = READ16(cpustate, cpustate->iy + offset);
+ SET_N16(cpustate->ix);
+ SET_Z16(cpustate->ix);
+ CYCLES(cpustate, 6);
+}
+
+
+/* LDY IMM 0x18, 0xCE */
+static void HC11OP(ldy_imm)(hc11_state *cpustate)
+{
+ CLEAR_NZV(cpustate);
+ cpustate->iy = FETCH16(cpustate);
+ SET_N16(cpustate->iy);
+ SET_Z16(cpustate->iy);
+ CYCLES(cpustate, 4);
+}
+
+/* LDY DIR 0x18, 0xDE */
+static void HC11OP(ldy_dir)(hc11_state *cpustate)
+{
+ UINT8 d = FETCH(cpustate);
+ CLEAR_NZV(cpustate);
+ cpustate->iy = READ16(cpustate, d);
+ SET_N16(cpustate->iy);
+ SET_Z16(cpustate->iy);
+ CYCLES(cpustate, 5);
+}
+
+/* LDY EXT 0x18, 0xFE */
+static void HC11OP(ldy_ext)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH16(cpustate);
+ CLEAR_NZV(cpustate);
+ cpustate->iy = READ16(cpustate, adr);
+ SET_N16(cpustate->iy);
+ SET_Z16(cpustate->iy);
+ CYCLES(cpustate, 6);
+}
+
+/* LDY IND, X 0x1A, 0xEE */
+static void HC11OP(ldy_indx)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ CLEAR_NZV(cpustate);
+ cpustate->iy = READ16(cpustate, cpustate->ix + offset);
+ SET_N16(cpustate->iy);
+ SET_Z16(cpustate->iy);
+ CYCLES(cpustate, 6);
+}
+
+/* LDY IND, Y 0x18, 0xEE */
+static void HC11OP(ldy_indy)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ CLEAR_NZV(cpustate);
+ cpustate->iy = READ16(cpustate, cpustate->iy + offset);
+ SET_N16(cpustate->iy);
+ SET_Z16(cpustate->iy);
+ CYCLES(cpustate, 6);
+}
+
+/* LSLD 0x05 */
+static void HC11OP(lsld)(hc11_state *cpustate)
+{
+ UINT32 r = REG_D << 1;
+ CLEAR_NZVC(cpustate);
+ SET_C16(r);
+ REG_D = (UINT16)(r);
+ SET_N16(REG_D);
+ SET_Z16(REG_D);
+
+ if (((cpustate->ccr & CC_N) == CC_N && (cpustate->ccr & CC_C) == 0) ||
+ ((cpustate->ccr & CC_N) == 0 && (cpustate->ccr & CC_C) == CC_C))
+ {
+ cpustate->ccr |= CC_V;
+ }
+
+ CYCLES(cpustate, 3);
+}
+
+/* LSRA 0x44 */
+static void HC11OP(lsra)(hc11_state *cpustate)
+{
+ UINT16 r = REG_A >> 1;
+ CLEAR_NZVC(cpustate);
+ cpustate->ccr |= (REG_A & 1) ? CC_C : 0;
+ REG_A = (UINT8)(r);
+ cpustate->ccr |= ((cpustate->ccr & CC_C) == CC_C) ? CC_V : 0;
+ SET_Z8(REG_A);
+
+ CYCLES(cpustate, 2);
+}
+
+/* LSRB 0x54 */
+static void HC11OP(lsrb)(hc11_state *cpustate)
+{
+ UINT16 r = REG_B >> 1;
+ CLEAR_NZVC(cpustate);
+ cpustate->ccr |= (REG_B & 1) ? CC_C : 0;
+ REG_B = (UINT8)(r);
+ cpustate->ccr |= ((cpustate->ccr & CC_C) == CC_C) ? CC_V : 0;
+ SET_Z8(REG_B);
+
+ CYCLES(cpustate, 2);
+}
+
+/* LSRD 0x04 */
+static void HC11OP(lsrd)(hc11_state *cpustate)
+{
+ UINT32 r = REG_D >> 1;
+ CLEAR_NZVC(cpustate);
+ cpustate->ccr |= (REG_D & 1) ? CC_C : 0;
+ REG_D = (UINT16)(r);
+ cpustate->ccr |= ((cpustate->ccr & CC_C) == CC_C) ? CC_V : 0;
+
+ SET_N16(REG_D);
+ SET_Z16(REG_D);
+
+ CYCLES(cpustate, 3);
+}
+
+/* MUL 0x3d */
+static void HC11OP(mul)(hc11_state *cpustate)
+{
+ UINT16 r = (UINT8)REG_A * (UINT8)REG_B;
+ REG_D = r;
+ CLEAR_C(cpustate);
+ cpustate->ccr |= (REG_B & 0x80) ? CC_C : 0;
+ CYCLES(cpustate, 10);
+}
+
+/* NEGA 0x40 */
+static void HC11OP(nega)(hc11_state *cpustate)
+{
+ INT8 r = 0x00 - REG_A;
+ REG_A = r;
+ CLEAR_NZVC(cpustate);
+ SET_N8(r);
+ SET_Z8(r);
+ cpustate->ccr |= (REG_A == 0x80) ? CC_V : 0;
+ cpustate->ccr |= (REG_A == 0x00) ? CC_C : 0;
+ CYCLES(cpustate, 2);
+}
+
+/* NEGB 0x50 */
+static void HC11OP(negb)(hc11_state *cpustate)
+{
+ INT8 r = 0x00 - REG_B;
+ REG_B = r;
+ CLEAR_NZVC(cpustate);
+ SET_N8(r);
+ SET_Z8(r);
+ cpustate->ccr |= (REG_B == 0x80) ? CC_V : 0;
+ cpustate->ccr |= (REG_B == 0x00) ? CC_C : 0;
+ CYCLES(cpustate, 2);
+}
+
+
+/* NEG EXT 0x70 */
+static void HC11OP(neg_ext)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH16(cpustate);
+ UINT8 i = READ8(cpustate, adr);
+ INT8 r = 0x00 - i;
+ i = r;
+ CLEAR_NZVC(cpustate);
+ SET_N8(r);
+ SET_Z8(r);
+ cpustate->ccr |= (i == 0x80) ? CC_V : 0;
+ cpustate->ccr |= (i == 0x00) ? CC_C : 0;
+ WRITE8(cpustate, adr, i);
+ CYCLES(cpustate, 6);
+}
+
+
+/* NEG INDX 0x60 */
+static void HC11OP(neg_indx)(hc11_state *cpustate)
+{
+ UINT16 offset = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->ix + offset);
+ INT8 r = 0x00 - i;
+ i = r;
+ CLEAR_NZVC(cpustate);
+ SET_N8(r);
+ SET_Z8(r);
+ cpustate->ccr |= (i == 0x80) ? CC_V : 0;
+ cpustate->ccr |= (i == 0x00) ? CC_C : 0;
+ WRITE8(cpustate, cpustate->ix + offset, i);
+ CYCLES(cpustate, 6);
+}
+
+
+/* NEG INDY 0x18 0x60 */
+static void HC11OP(neg_indy)(hc11_state *cpustate)
+{
+ UINT16 offset = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->iy + offset);
+ INT8 r = 0x00 - i;
+ i = r;
+ CLEAR_NZVC(cpustate);
+ SET_N8(r);
+ SET_Z8(r);
+ cpustate->ccr |= (i == 0x80) ? CC_V : 0;
+ cpustate->ccr |= (i == 0x00) ? CC_C : 0;
+ WRITE8(cpustate, cpustate->iy + offset, i);
+ CYCLES(cpustate, 7);
+}
+
+
+/* NOP 0x01 */
+static void HC11OP(nop)(hc11_state *cpustate)
+{
+ CYCLES(cpustate, 2);
+}
+
+/* PSHA 0x36 */
+static void HC11OP(psha)(hc11_state *cpustate)
+{
+ PUSH8(cpustate, REG_A);
+ CYCLES(cpustate, 3);
+}
+
+/* ORAA IMM 0x8A */
+static void HC11OP(oraa_imm)(hc11_state *cpustate)
+{
+ UINT8 i = FETCH(cpustate);
+ CLEAR_NZV(cpustate);
+ REG_A |= i;
+ SET_N8(REG_A);
+ SET_Z8(REG_A);
+ CYCLES(cpustate, 2);
+}
+
+/* ORAA DIR 0x9A */
+static void HC11OP(oraa_dir)(hc11_state *cpustate)
+{
+ UINT8 d = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, d);
+ CLEAR_NZV(cpustate);
+ REG_A |= i;
+ SET_N8(REG_A);
+ SET_Z8(REG_A);
+ CYCLES(cpustate, 3);
+}
+
+/* ORAA EXT 0xBA */
+static void HC11OP(oraa_ext)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH16(cpustate);
+ UINT8 i = READ8(cpustate, adr);
+ CLEAR_NZV(cpustate);
+ REG_A |= i;
+ SET_N8(REG_A);
+ SET_Z8(REG_A);
+ CYCLES(cpustate, 4);
+}
+
+/* ORAA IND, X 0xAA */
+static void HC11OP(oraa_indx)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->ix + offset);
+ CLEAR_NZV(cpustate);
+ REG_A |= i;
+ SET_N8(REG_A);
+ SET_Z8(REG_A);
+ CYCLES(cpustate, 4);
+}
+
+/* ORAA IND, Y 0x18, 0xAA */
+static void HC11OP(oraa_indy)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->iy + offset);
+ CLEAR_NZV(cpustate);
+ REG_A |= i;
+ SET_N8(REG_A);
+ SET_Z8(REG_A);
+ CYCLES(cpustate, 5);
+}
+
+
+/* ORAB IMM 0xCA */
+static void HC11OP(orab_imm)(hc11_state *cpustate)
+{
+ UINT8 i = FETCH(cpustate);
+ CLEAR_NZV(cpustate);
+ REG_B |= i;
+ SET_N8(REG_B);
+ SET_Z8(REG_B);
+ CYCLES(cpustate, 2);
+}
+
+/* ORAB DIR 0xDA */
+static void HC11OP(orab_dir)(hc11_state *cpustate)
+{
+ UINT8 d = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, d);
+ CLEAR_NZV(cpustate);
+ REG_B |= i;
+ SET_N8(REG_B);
+ SET_Z8(REG_B);
+ CYCLES(cpustate, 3);
+}
+
+/* ORAB EXT 0xFA */
+static void HC11OP(orab_ext)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH16(cpustate);
+ UINT8 i = READ8(cpustate, adr);
+ CLEAR_NZV(cpustate);
+ REG_B |= i;
+ SET_N8(REG_B);
+ SET_Z8(REG_B);
+ CYCLES(cpustate, 4);
+}
+
+/* ORAB IND, X 0xEA */
+static void HC11OP(orab_indx)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->ix + offset);
+ CLEAR_NZV(cpustate);
+ REG_B |= i;
+ SET_N8(REG_B);
+ SET_Z8(REG_B);
+ CYCLES(cpustate, 4);
+}
+
+/* ORAB IND, Y 0x18, 0xEA */
+static void HC11OP(orab_indy)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->iy + offset);
+ CLEAR_NZV(cpustate);
+ REG_B |= i;
+ SET_N8(REG_B);
+ SET_Z8(REG_B);
+ CYCLES(cpustate, 5);
+}
+
+
+/* PSHB 0x37 */
+static void HC11OP(pshb)(hc11_state *cpustate)
+{
+ PUSH8(cpustate, REG_B);
+ CYCLES(cpustate, 3);
+}
+
+
+/* PSHX 0x3C */
+static void HC11OP(pshx)(hc11_state *cpustate)
+{
+ PUSH16(cpustate, cpustate->ix);
+ CYCLES(cpustate, 4);
+}
+
+
+/* PSHY 0x18, 0x3C */
+static void HC11OP(pshy)(hc11_state *cpustate)
+{
+ PUSH16(cpustate, cpustate->iy);
+ CYCLES(cpustate, 5);
+}
+
+
+/* PULA 0x32 */
+static void HC11OP(pula)(hc11_state *cpustate)
+{
+ REG_A = POP8(cpustate);
+ CYCLES(cpustate, 4);
+}
+
+
+/* PULB 0x33 */
+static void HC11OP(pulb)(hc11_state *cpustate)
+{
+ REG_B = POP8(cpustate);
+ CYCLES(cpustate, 4);
+}
+
+
+/* PULX 0x38 */
+static void HC11OP(pulx)(hc11_state *cpustate)
+{
+ cpustate->ix = POP16(cpustate);
+ CYCLES(cpustate, 5);
+}
+
+
+/* PULY 0x18, 0x38 */
+static void HC11OP(puly)(hc11_state *cpustate)
+{
+ cpustate->iy = POP16(cpustate);
+ CYCLES(cpustate, 6);
+}
+
+/* ROLA 0x49 */
+static void HC11OP(rola)(hc11_state *cpustate)
+{
+ UINT8 c = (REG_A & 0x80);
+ UINT16 r = ((REG_A & 0x7f) << 1) | (cpustate->ccr & CC_C ? 1 : 0);
+ CLEAR_NZVC(cpustate);
+ cpustate->ccr |= (c & 0x80) ? CC_C : 0;
+ REG_A = (UINT16)(r);
+ SET_N8(REG_A);
+ SET_Z8(REG_A);
+
+ if (((cpustate->ccr & CC_N) == CC_N && (cpustate->ccr & CC_C) == 0) ||
+ ((cpustate->ccr & CC_N) == 0 && (cpustate->ccr & CC_C) == CC_C))
+ {
+ cpustate->ccr |= CC_V;
+ }
+
+ CYCLES(cpustate, 2);
+}
+
+/* ROLB 0x59 */
+static void HC11OP(rolb)(hc11_state *cpustate)
+{
+ UINT8 c = (REG_B & 0x80);
+ UINT16 r = (REG_B << 1) | (cpustate->ccr & CC_C ? 1 : 0);
+ CLEAR_NZVC(cpustate);
+ cpustate->ccr |= (c & 0x80) ? CC_C : 0;
+ REG_B = (UINT16)(r);
+ SET_N8(REG_B);
+ SET_Z8(REG_B);
+
+ if (((cpustate->ccr & CC_N) == CC_N && (cpustate->ccr & CC_C) == 0) ||
+ ((cpustate->ccr & CC_N) == 0 && (cpustate->ccr & CC_C) == CC_C))
+ {
+ cpustate->ccr |= CC_V;
+ }
+
+ CYCLES(cpustate, 2);
+}
+
+/* RORA 0x46 */
+static void HC11OP(rora)(hc11_state *cpustate)
+{
+ UINT8 c = (REG_A & 1);
+ UINT16 r = ((REG_A & 0x7f) >> 1) | (cpustate->ccr & CC_C ? 0x80 : 0);
+ CLEAR_NZVC(cpustate);
+ cpustate->ccr |= (c & 1) ? CC_C : 0;
+ REG_A = (UINT16)(r);
+ SET_N8(REG_A);
+ SET_Z8(REG_A);
+
+ if (((cpustate->ccr & CC_N) == CC_N && (cpustate->ccr & CC_C) == 0) ||
+ ((cpustate->ccr & CC_N) == 0 && (cpustate->ccr & CC_C) == CC_C))
+ {
+ cpustate->ccr |= CC_V;
+ }
+
+ CYCLES(cpustate, 2);
+}
+
+/* RORB 0x56 */
+static void HC11OP(rorb)(hc11_state *cpustate)
+{
+ UINT8 c = (REG_B & 1);
+ UINT16 r = ((REG_B & 0x7f) >> 1) | (cpustate->ccr & CC_C ? 0x80 : 0);
+ CLEAR_NZVC(cpustate);
+ cpustate->ccr |= (c & 1) ? CC_C : 0;
+ REG_B = (UINT16)(r);
+ SET_N8(REG_B);
+ SET_Z8(REG_B);
+
+ if (((cpustate->ccr & CC_N) == CC_N && (cpustate->ccr & CC_C) == 0) ||
+ ((cpustate->ccr & CC_N) == 0 && (cpustate->ccr & CC_C) == CC_C))
+ {
+ cpustate->ccr |= CC_V;
+ }
+
+ CYCLES(cpustate, 2);
+}
+
+/* RTI 0x3B */
+static void HC11OP(rti)(hc11_state *cpustate)
+{
+ UINT16 rt_adr;
+ UINT8 x_flag = cpustate->ccr & CC_X;
+ cpustate->ccr = POP8(cpustate);
+ if(x_flag == 0 && cpustate->ccr & CC_X) //X flag cannot do a 0->1 transition with this instruction.
+ cpustate->ccr &= ~CC_X;
+ REG_B = POP8(cpustate);
+ REG_A = POP8(cpustate);
+ cpustate->ix = POP16(cpustate);
+ cpustate->iy = POP16(cpustate);
+ rt_adr = POP16(cpustate);
+ SET_PC(cpustate, rt_adr);
+ CYCLES(cpustate, 12);
+}
+
+/* RTS 0x39 */
+static void HC11OP(rts)(hc11_state *cpustate)
+{
+ UINT16 rt_adr = POP16(cpustate);
+ SET_PC(cpustate, rt_adr);
+ CYCLES(cpustate, 5);
+}
+
+
+/* SBA 0x10 */
+static void HC11OP(sba)(hc11_state *cpustate)
+{
+ UINT16 r = REG_A - REG_B;
+ CLEAR_NZVC(cpustate);
+// SET_H(r, i, REG_A);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_SUB8(r, REG_B, REG_A);
+ cpustate->ccr|= (REG_B > REG_A) ? CC_C : 0;
+ REG_A = (UINT8)r;
+ CYCLES(cpustate, 2);
+}
+
+
+/* SBCA IMM 0x82 */
+static void HC11OP(sbca_imm)(hc11_state *cpustate)
+{
+ int c = (cpustate->ccr & CC_C) ? 1 : 0;
+ UINT8 i = FETCH(cpustate);
+ UINT16 r = (REG_A - i) - c;
+ CLEAR_NZVC(cpustate);
+// SET_H(r, i-c, REG_A);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_SUB8(r, i-c, REG_A);
+ SET_C8(r);
+ REG_A = (UINT8)r;
+ CYCLES(cpustate, 2);
+}
+
+/* SBCA IND, X 0xA2 */
+static void HC11OP(sbca_indx)(hc11_state *cpustate)
+{
+ int c = (cpustate->ccr & CC_C) ? 1 : 0;
+ UINT8 offset = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->ix + offset);
+ UINT16 r = (REG_A - i) - c;
+ CLEAR_NZVC(cpustate);
+// SET_H(r, i-c, REG_A);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_SUB8(r, i-c, REG_A);
+ SET_C8(r);
+ REG_A = (UINT8)r;
+ CYCLES(cpustate, 4);
+}
+
+/* SBCA IND, Y 0x18, 0xA2 */
+static void HC11OP(sbca_indy)(hc11_state *cpustate)
+{
+ int c = (cpustate->ccr & CC_C) ? 1 : 0;
+ UINT8 offset = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->iy + offset);
+ UINT16 r = (REG_A - i) - c;
+ CLEAR_NZVC(cpustate);
+// SET_H(r, i-c, REG_A);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_SUB8(r, i-c, REG_A);
+ SET_C8(r);
+ REG_A = (UINT8)r;
+ CYCLES(cpustate, 5);
+}
+
+/* SBCB IMM 0xC2 */
+static void HC11OP(sbcb_imm)(hc11_state *cpustate)
+{
+ int c = (cpustate->ccr & CC_C) ? 1 : 0;
+ UINT8 i = FETCH(cpustate);
+ UINT16 r = (REG_B - i) - c;
+ CLEAR_NZVC(cpustate);
+// SET_H(r, i-c, REG_B);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_SUB8(r, i-c, REG_B);
+ SET_C8(r);
+ REG_B = (UINT8)r;
+ CYCLES(cpustate, 2);
+}
+
+/* SBCB IND, X 0xE2 */
+static void HC11OP(sbcb_indx)(hc11_state *cpustate)
+{
+ int c = (cpustate->ccr & CC_C) ? 1 : 0;
+ UINT8 offset = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->ix + offset);
+ UINT16 r = (REG_B - i) - c;
+ CLEAR_NZVC(cpustate);
+// SET_H(r, i-c, REG_B);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_SUB8(r, i-c, REG_B);
+ SET_C8(r);
+ REG_B = (UINT8)r;
+ CYCLES(cpustate, 4);
+}
+
+/* SBCB IND, Y 0x18, 0xE2 */
+static void HC11OP(sbcb_indy)(hc11_state *cpustate)
+{
+ int c = (cpustate->ccr & CC_C) ? 1 : 0;
+ UINT8 offset = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->iy + offset);
+ UINT16 r = (REG_B - i) - c;
+ CLEAR_NZVC(cpustate);
+// SET_H(r, i-c, REG_B);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_SUB8(r, i-c, REG_B);
+ SET_C8(r);
+ REG_B = (UINT8)r;
+ CYCLES(cpustate, 5);
+}
+
+/* SEC 0x0D */
+static void HC11OP(sec)(hc11_state *cpustate)
+{
+ cpustate->ccr |= CC_C;
+ CYCLES(cpustate, 2);
+}
+
+/* SEI 0x0F */
+static void HC11OP(sei)(hc11_state *cpustate)
+{
+ cpustate->ccr |= CC_I;
+ CYCLES(cpustate, 2);
+}
+
+/* SEV 0x0B */
+static void HC11OP(sev)(hc11_state *cpustate)
+{
+ cpustate->ccr |= CC_V;
+ CYCLES(cpustate, 2);
+}
+
+/* STAA DIR 0x97 */
+static void HC11OP(staa_dir)(hc11_state *cpustate)
+{
+ UINT8 d = FETCH(cpustate);
+ CLEAR_NZV(cpustate);
+ SET_N8(REG_A);
+ SET_Z8(REG_A);
+ WRITE8(cpustate, d, REG_A);
+ CYCLES(cpustate, 3);
+}
+
+/* STAA EXT 0xB7 */
+static void HC11OP(staa_ext)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH16(cpustate);
+ CLEAR_NZV(cpustate);
+ SET_N8(REG_A);
+ SET_Z8(REG_A);
+ WRITE8(cpustate, adr, REG_A);
+ CYCLES(cpustate, 4);
+}
+
+/* STAA IND, X 0xA7 */
+static void HC11OP(staa_indx)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ CLEAR_NZV(cpustate);
+ SET_N8(REG_A);
+ SET_Z8(REG_A);
+ WRITE8(cpustate, cpustate->ix + offset, REG_A);
+ CYCLES(cpustate, 4);
+}
+
+/* STAA IND, Y 0x18, 0xA7 */
+static void HC11OP(staa_indy)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ CLEAR_NZV(cpustate);
+ SET_N8(REG_A);
+ SET_Z8(REG_A);
+ WRITE8(cpustate, cpustate->iy + offset, REG_A);
+ CYCLES(cpustate, 5);
+}
+
+/* STAB DIR 0xD7 */
+static void HC11OP(stab_dir)(hc11_state *cpustate)
+{
+ UINT8 d = FETCH(cpustate);
+ CLEAR_NZV(cpustate);
+ SET_N8(REG_B);
+ SET_Z8(REG_B);
+ WRITE8(cpustate, d, REG_B);
+ CYCLES(cpustate, 3);
+}
+
+/* STAB EXT 0xF7 */
+static void HC11OP(stab_ext)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH16(cpustate);
+ CLEAR_NZV(cpustate);
+ SET_N8(REG_B);
+ SET_Z8(REG_B);
+ WRITE8(cpustate, adr, REG_B);
+ CYCLES(cpustate, 4);
+}
+
+/* STAB IND, X 0xE7 */
+static void HC11OP(stab_indx)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ CLEAR_NZV(cpustate);
+ SET_N8(REG_B);
+ SET_Z8(REG_B);
+ WRITE8(cpustate, cpustate->ix + offset, REG_B);
+ CYCLES(cpustate, 4);
+}
+
+/* STAB IND, Y 0x18, 0xE7 */
+static void HC11OP(stab_indy)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ CLEAR_NZV(cpustate);
+ SET_N8(REG_B);
+ SET_Z8(REG_B);
+ WRITE8(cpustate, cpustate->iy + offset, REG_B);
+ CYCLES(cpustate, 5);
+}
+
+
+/* STD DIR 0xDD */
+static void HC11OP(std_dir)(hc11_state *cpustate)
+{
+ UINT8 d = FETCH(cpustate);
+ CLEAR_NZV(cpustate);
+ WRITE16(cpustate, d, REG_D);
+ SET_N16(REG_D);
+ SET_Z16(REG_D);
+ CYCLES(cpustate, 4);
+}
+
+/* STD EXT 0xFD */
+static void HC11OP(std_ext)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH16(cpustate);
+ CLEAR_NZV(cpustate);
+ WRITE16(cpustate, adr, REG_D);
+ SET_N16(REG_D);
+ SET_Z16(REG_D);
+ CYCLES(cpustate, 5);
+}
+
+/* STD IND, X 0xED */
+static void HC11OP(std_indx)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ CLEAR_NZV(cpustate);
+ WRITE16(cpustate, cpustate->ix + offset, REG_D);
+ SET_N16(REG_D);
+ SET_Z16(REG_D);
+ CYCLES(cpustate, 5);
+}
+
+/* STD IND, Y 0x18, 0xED */
+static void HC11OP(std_indy)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ CLEAR_NZV(cpustate);
+ WRITE16(cpustate, cpustate->iy + offset, REG_D);
+ SET_N16(REG_D);
+ SET_Z16(REG_D);
+ CYCLES(cpustate, 6);
+}
+
+/* STX DIR 0xDF */
+static void HC11OP(stx_dir)(hc11_state *cpustate)
+{
+ UINT8 adr = FETCH(cpustate);
+ UINT16 r = cpustate->ix;
+ CLEAR_NZV(cpustate);
+ WRITE8(cpustate, adr, (r & 0xff00) >> 8);
+ WRITE8(cpustate, adr + 1, (r & 0xff));
+ SET_N16(r);
+ SET_Z16(r);
+ CYCLES(cpustate, 4);
+}
+
+/* STX EXT 0xFF */
+static void HC11OP(stx_ext)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH16(cpustate);
+ UINT16 r = cpustate->ix;
+ CLEAR_NZV(cpustate);
+ WRITE8(cpustate, adr, (r & 0xff00) >> 8);
+ WRITE8(cpustate, adr + 1, (r & 0xff));
+ SET_N16(r);
+ SET_Z16(r);
+ CYCLES(cpustate, 5);
+}
+
+
+/* STX INDX 0xEF */
+static void HC11OP(stx_indx)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH(cpustate);
+ UINT16 r = cpustate->ix;
+ CLEAR_NZV(cpustate);
+ WRITE8(cpustate, cpustate->ix + adr, (r & 0xff00) >> 8);
+ WRITE8(cpustate, cpustate->ix + adr + 1, (r & 0xff));
+ SET_N16(r);
+ SET_Z16(r);
+ CYCLES(cpustate, 5);
+}
+
+
+/* STX INDY 0xCD 0xEF */
+static void HC11OP(stx_indy)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH(cpustate);
+ UINT16 r = cpustate->ix;
+ CLEAR_NZV(cpustate);
+ WRITE8(cpustate, cpustate->iy + adr, (r & 0xff00) >> 8);
+ WRITE8(cpustate, cpustate->iy + adr + 1, (r & 0xff));
+ SET_N16(r);
+ SET_Z16(r);
+ CYCLES(cpustate, 6);
+}
+
+/* STY DIR 0x18 0xDF */
+static void HC11OP(sty_dir)(hc11_state *cpustate)
+{
+ UINT8 adr = FETCH(cpustate);
+ UINT16 r = cpustate->iy;
+ CLEAR_NZV(cpustate);
+ WRITE8(cpustate, adr, (r & 0xff00) >> 8);
+ WRITE8(cpustate, adr + 1, (r & 0xff));
+ SET_N16(r);
+ SET_Z16(r);
+ CYCLES(cpustate, 5);
+}
+
+
+/* STY EXT 0x18 0xFF */
+static void HC11OP(sty_ext)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH16(cpustate);
+ UINT16 r = cpustate->iy;
+ CLEAR_NZV(cpustate);
+ WRITE8(cpustate, adr, (r & 0xff00) >> 8);
+ WRITE8(cpustate, adr + 1, (r & 0xff));
+ SET_N16(r);
+ SET_Z16(r);
+ CYCLES(cpustate, 6);
+}
+
+/* STY INDX 0x1A 0xEF */
+static void HC11OP(sty_indx)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH(cpustate);
+ UINT16 r = cpustate->iy;
+ CLEAR_NZV(cpustate);
+ WRITE8(cpustate, cpustate->ix + adr, (r & 0xff00) >> 8);
+ WRITE8(cpustate, cpustate->ix + adr + 1, (r & 0xff));
+ SET_N16(r);
+ SET_Z16(r);
+ CYCLES(cpustate, 6);
+}
+
+/* STY INDY 0x18 0xEF */
+static void HC11OP(sty_indy)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH(cpustate);
+ UINT16 r = cpustate->iy;
+ CLEAR_NZV(cpustate);
+ WRITE8(cpustate, cpustate->iy + adr, (r & 0xff00) >> 8);
+ WRITE8(cpustate, cpustate->iy + adr + 1, (r & 0xff));
+ SET_N16(r);
+ SET_Z16(r);
+ CYCLES(cpustate, 6);
+}
+
+/* STOP 0xCF */
+static void HC11OP(stop)(hc11_state *cpustate)
+{
+ if(cpustate->stop_state == 0 && ((cpustate->ccr & CC_S) == 0))
+ {
+ cpustate->stop_state = 1;
+ }
+
+ if(cpustate->stop_state == 1)
+ {
+ SET_PC(cpustate, cpustate->ppc); // wait for an exception
+ }
+
+ if(cpustate->stop_state == 2)
+ {
+ cpustate->stop_state = 0;
+ }
+
+ CYCLES(cpustate, 2);
+}
+
+
+/* SUBA IMM 0x80 */
+static void HC11OP(suba_imm)(hc11_state *cpustate)
+{
+ UINT8 i = FETCH(cpustate);
+ UINT16 r = REG_A - i;
+ CLEAR_NZVC(cpustate);
+// SET_H(r, i, REG_A);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_SUB8(r, i, REG_A);
+ SET_C8(r);
+ REG_A = (UINT8)r;
+ CYCLES(cpustate, 2);
+}
+
+
+/* SUBA DIR 0xd0 */
+static void HC11OP(suba_dir)(hc11_state *cpustate)
+{
+ UINT8 d = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, d);
+ UINT16 r = REG_A - i;
+ CLEAR_NZVC(cpustate);
+// SET_H(r, i, REG_A);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_SUB8(r, i, REG_A);
+ SET_C8(r);
+ REG_A = (UINT8)r;
+ CYCLES(cpustate, 3);
+}
+
+
+/* SUBA EXT 0xE0 */
+static void HC11OP(suba_ext)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH16(cpustate);
+ UINT8 i = READ8(cpustate, adr);
+ UINT16 r = REG_A - i;
+ CLEAR_NZVC(cpustate);
+// SET_H(r, i, REG_A);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_SUB8(r, i, REG_A);
+ SET_C8(r);
+ REG_A = (UINT8)r;
+ CYCLES(cpustate, 4);
+}
+
+
+/* SUBA INDX 0xA0 */
+static void HC11OP(suba_indx)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->ix + adr);
+ UINT16 r = REG_A - i;
+ CLEAR_NZVC(cpustate);
+// SET_H(r, i, REG_A);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_SUB8(r, i, REG_A);
+ SET_C8(r);
+ REG_A = (UINT8)r;
+ CYCLES(cpustate, 4);
+}
+
+
+/* SUBA INDY 0x18 0xA0 */
+static void HC11OP(suba_indy)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->iy + adr);
+ UINT16 r = REG_A - i;
+ CLEAR_NZVC(cpustate);
+// SET_H(r, i, REG_A);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_SUB8(r, i, REG_A);
+ SET_C8(r);
+ REG_A = (UINT8)r;
+ CYCLES(cpustate, 5);
+}
+
+
+/* SUBB IMM 0xC0 */
+static void HC11OP(subb_imm)(hc11_state *cpustate)
+{
+ UINT8 i = FETCH(cpustate);
+ UINT16 r = REG_B - i;
+ CLEAR_NZVC(cpustate);
+// SET_H(r, i, REG_B);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_SUB8(r, i, REG_B);
+ SET_C8(r);
+ REG_B = (UINT8)r;
+ CYCLES(cpustate, 2);
+}
+
+
+/* SUBB DIR 0xD0 */
+static void HC11OP(subb_dir)(hc11_state *cpustate)
+{
+ UINT8 d = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, d);
+ UINT16 r = REG_B - i;
+ CLEAR_NZVC(cpustate);
+// SET_H(r, i, REG_B);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_SUB8(r, i, REG_B);
+ SET_C8(r);
+ REG_B = (UINT8)r;
+ CYCLES(cpustate, 3);
+}
+
+
+/* SUBB EXT 0xF0 */
+static void HC11OP(subb_ext)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH16(cpustate);
+ UINT8 i = READ8(cpustate, adr);
+ UINT16 r = REG_B - i;
+ CLEAR_NZVC(cpustate);
+// SET_H(r, i, REG_B);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_SUB8(r, i, REG_B);
+ SET_C8(r);
+ REG_B = (UINT8)r;
+ CYCLES(cpustate, 4);
+}
+
+
+/* SUBB INDX 0xE0 */
+static void HC11OP(subb_indx)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->ix + adr);
+ UINT16 r = REG_B - i;
+ CLEAR_NZVC(cpustate);
+// SET_H(r, i, REG_B);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_SUB8(r, i, REG_B);
+ SET_C8(r);
+ REG_B = (UINT8)r;
+ CYCLES(cpustate, 4);
+}
+
+/* SUBB INDY 0x18 0xE0 */
+static void HC11OP(subb_indy)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->iy + adr);
+ UINT16 r = REG_B - i;
+ CLEAR_NZVC(cpustate);
+// SET_H(r, i, REG_B);
+ SET_N8(r);
+ SET_Z8(r);
+ SET_V_SUB8(r, i, REG_B);
+ SET_C8(r);
+ REG_B = (UINT8)r;
+ CYCLES(cpustate, 5);
+}
+
+/* SUBD IMM 0x83 */
+static void HC11OP(subd_imm)(hc11_state *cpustate)
+{
+ UINT16 i = FETCH16(cpustate);
+ UINT32 r = REG_D - i;
+ CLEAR_NZVC(cpustate);
+ SET_N16(r);
+ SET_Z16(r);
+ SET_V_SUB16(r, i, REG_D);
+ SET_C16(r);
+ REG_D = (UINT16)r;
+ CYCLES(cpustate, 4);
+}
+
+/* SUBD DIR 0x93 */
+static void HC11OP(subd_dir)(hc11_state *cpustate)
+{
+ UINT8 d = FETCH(cpustate);
+ UINT16 i = READ16(cpustate, d);
+ UINT32 r = REG_D - i;
+ CLEAR_NZVC(cpustate);
+ SET_N16(r);
+ SET_Z16(r);
+ SET_V_SUB16(r, i, REG_D);
+ SET_C16(r);
+ REG_D = (UINT16)r;
+ CYCLES(cpustate, 5);
+}
+
+/* SUBD EXT 0xB3 */
+static void HC11OP(subd_ext)(hc11_state *cpustate)
+{
+ UINT16 addr = FETCH16(cpustate);
+ UINT16 i = READ16(cpustate, addr);
+ UINT32 r = REG_D - i;
+ CLEAR_NZVC(cpustate);
+ SET_N16(r);
+ SET_Z16(r);
+ SET_V_SUB16(r, i, REG_D);
+ SET_C16(r);
+ REG_D = (UINT16)r;
+ CYCLES(cpustate, 6);
+}
+
+/* SUBD INDX 0xA3 */
+static void HC11OP(subd_indx)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT16 i = READ16(cpustate, cpustate->ix + offset);
+ UINT32 r = REG_D - i;
+ CLEAR_NZVC(cpustate);
+ SET_N16(r);
+ SET_Z16(r);
+ SET_V_SUB16(r, i, REG_D);
+ SET_C16(r);
+ REG_D = (UINT16)r;
+ CYCLES(cpustate, 6);
+}
+
+/* SUBD INDY 0x18 0xA3 */
+static void HC11OP(subd_indy)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT16 i = READ16(cpustate, cpustate->iy + offset);
+ UINT32 r = REG_D - i;
+ CLEAR_NZVC(cpustate);
+ SET_N16(r);
+ SET_Z16(r);
+ SET_V_SUB16(r, i, REG_D);
+ SET_C16(r);
+ REG_D = (UINT16)r;
+ CYCLES(cpustate, 7);
+}
+
+/* SWI 0x3F */
+static void HC11OP(swi)(hc11_state *cpustate)
+{
+ UINT16 pc_vector;
+ //cpustate->pc++;
+ PUSH16(cpustate, cpustate->pc);
+ PUSH16(cpustate, cpustate->iy);
+ PUSH16(cpustate, cpustate->ix);
+ PUSH8(cpustate, REG_A);
+ PUSH8(cpustate, REG_B);
+ PUSH8(cpustate, cpustate->ccr);
+ pc_vector = READ16(cpustate, 0xfff6);
+ SET_PC(cpustate, pc_vector);
+ cpustate->ccr |= CC_I; //irq taken, mask the flag
+ CYCLES(cpustate, 14);
+}
+
+/* TAB 0x16 */
+static void HC11OP(tab)(hc11_state *cpustate)
+{
+ CLEAR_NZV(cpustate);
+ REG_B = REG_A;
+ SET_N8(REG_B);
+ SET_Z8(REG_B);
+ CYCLES(cpustate, 2);
+}
+
+/* TAP 0x06 */
+static void HC11OP(tap)(hc11_state *cpustate)
+{
+ UINT8 x_flag = cpustate->ccr & CC_X;
+ cpustate->ccr = REG_A;
+ if(x_flag == 0 && cpustate->ccr & CC_X) //X flag cannot do a 0->1 transition with this instruction.
+ cpustate->ccr &= ~CC_X;
+
+ CYCLES(cpustate, 2);
+}
+
+/* TBA 0x17 */
+static void HC11OP(tba)(hc11_state *cpustate)
+{
+ CLEAR_NZV(cpustate);
+ REG_A = REG_B;
+ SET_N8(REG_A);
+ SET_Z8(REG_A);
+ CYCLES(cpustate, 2);
+}
+
+/* TEST 0x00 */
+static void HC11OP(test)(hc11_state *cpustate)
+{
+// if(cpustate->test_mode)
+ SET_PC(cpustate, cpustate->ppc); // Note: docs says "incremented" but the behaviour makes me think that's actually "decremented".
+// else
+// {
+// TODO: execute an illegal opcode exception here (NMI)
+// }
+
+ CYCLES(cpustate, 1);
+}
+
+/* TPA 0x07 */
+static void HC11OP(tpa)(hc11_state *cpustate)
+{
+ REG_A = cpustate->ccr;
+ CYCLES(cpustate, 2);
+}
+
+
+/* TSTA 0x4D */
+static void HC11OP(tsta)(hc11_state *cpustate)
+{
+ CLEAR_NZVC(cpustate);
+ SET_N8(REG_A);
+ SET_Z8(REG_A);
+ CYCLES(cpustate, 2);
+}
+
+/* TSTB 0x5D */
+static void HC11OP(tstb)(hc11_state *cpustate)
+{
+ CLEAR_NZVC(cpustate);
+ SET_N8(REG_B);
+ SET_Z8(REG_B);
+ CYCLES(cpustate, 2);
+}
+
+/* TST EXT 0x7D */
+static void HC11OP(tst_ext)(hc11_state *cpustate)
+{
+ UINT16 adr = FETCH16(cpustate);
+ UINT8 i = READ8(cpustate, adr);
+ CLEAR_NZVC(cpustate);
+ SET_N8(i);
+ SET_Z8(i);
+ CYCLES(cpustate, 6);
+}
+
+/* TST IND, X 0x6D */
+static void HC11OP(tst_indx)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->ix + offset);
+ CLEAR_NZVC(cpustate);
+ SET_N8(i);
+ SET_Z8(i);
+ CYCLES(cpustate, 6);
+}
+
+/* TST IND, Y 0x18, 0x6D */
+static void HC11OP(tst_indy)(hc11_state *cpustate)
+{
+ UINT8 offset = FETCH(cpustate);
+ UINT8 i = READ8(cpustate, cpustate->iy + offset);
+ CLEAR_NZVC(cpustate);
+ SET_N8(i);
+ SET_Z8(i);
+ CYCLES(cpustate, 6);
+}
+
+/* TSX 0x30 */
+static void HC11OP(tsx)(hc11_state *cpustate)
+{
+ cpustate->ix = cpustate->sp + 1;
+ CYCLES(cpustate, 3);
+}
+
+/* TSY 0x18 0x30 */
+static void HC11OP(tsy)(hc11_state *cpustate)
+{
+ cpustate->iy = cpustate->sp + 1;
+ CYCLES(cpustate, 4);
+}
+
+/* TXS 0x35 */
+static void HC11OP(txs)(hc11_state *cpustate)
+{
+ cpustate->sp = cpustate->ix - 1;
+ CYCLES(cpustate, 3);
+}
+
+/* TYS 0x18 0x35 */
+static void HC11OP(tys)(hc11_state *cpustate)
+{
+ cpustate->sp = cpustate->iy - 1;
+ CYCLES(cpustate, 4);
+}
+
+/* WAI 0x3E */
+static void HC11OP(wai)(hc11_state *cpustate)
+{
+ if(cpustate->wait_state == 0)
+ {
+ /* TODO: the following is bogus, pushes regs HERE in an instruction that wants an irq to go out? */
+ PUSH16(cpustate, cpustate->pc);
+ PUSH16(cpustate, cpustate->iy);
+ PUSH16(cpustate, cpustate->ix);
+ PUSH8(cpustate, REG_A);
+ PUSH8(cpustate, REG_B);
+ PUSH8(cpustate, cpustate->ccr);
+ CYCLES(cpustate, 14);
+ cpustate->wait_state = 1;
+ }
+ if(cpustate->wait_state == 1)
+ {
+ SET_PC(cpustate, cpustate->ppc); // wait for an exception
+ CYCLES(cpustate, 1);
+ }
+ if(cpustate->wait_state == 2)
+ {
+ cpustate->wait_state = 0;
+ CYCLES(cpustate, 1);
+ }
+}
+
+/* XGDX 0x8F */
+static void HC11OP(xgdx)(hc11_state *cpustate)
+{
+ UINT16 tmp = REG_D;
+ REG_D = cpustate->ix;
+ cpustate->ix = tmp;
+ CYCLES(cpustate, 3);
+}
+
+
+/* XGDY 0x18, 0x8F */
+static void HC11OP(xgdy)(hc11_state *cpustate)
+{
+ UINT16 tmp = REG_D;
+ REG_D = cpustate->iy;
+ cpustate->iy = tmp;
+ CYCLES(cpustate, 4);
+}
+
+/*****************************************************************************/
+
+static void HC11OP(page2)(hc11_state *cpustate)
+{
+ UINT8 op2 = FETCH(cpustate);
+ hc11_optable_page2[op2](cpustate);
+}
+
+static void HC11OP(page3)(hc11_state *cpustate)
+{
+ UINT8 op2 = FETCH(cpustate);
+ hc11_optable_page3[op2](cpustate);
+}
+
+static void HC11OP(page4)(hc11_state *cpustate)
+{
+ UINT8 op2 = FETCH(cpustate);
+ hc11_optable_page4[op2](cpustate);
+}
+
+static void HC11OP(invalid)(hc11_state *cpustate)
+{
+ fatalerror("HC11: Invalid opcode 0x%02X at %04X", READ8(cpustate, cpustate->pc-1), cpustate->pc-1);
+}
diff --git a/trunk/src/emu/cpu/mc68hc11/hc11ops.h b/trunk/src/emu/cpu/mc68hc11/hc11ops.h
new file mode 100644
index 00000000000..9e2a2f0044e
--- /dev/null
+++ b/trunk/src/emu/cpu/mc68hc11/hc11ops.h
@@ -0,0 +1,324 @@
+typedef struct _hc11_opcode_list_struct hc11_opcode_list_struct;
+struct _hc11_opcode_list_struct
+{
+ int page;
+ int opcode;
+ void (*handler)(hc11_state *cpustate);
+};
+
+static const hc11_opcode_list_struct hc11_opcode_list[] =
+{
+ /* page opcode handler */
+ { 0, 0x1b, HC11OP(aba) },
+ { 0, 0x3a, HC11OP(abx) },
+ { 0x18, 0x3a, HC11OP(aby) },
+ { 0, 0x89, HC11OP(adca_imm) },
+ { 0, 0x99, HC11OP(adca_dir) },
+ { 0, 0xb9, HC11OP(adca_ext) },
+ { 0, 0xa9, HC11OP(adca_indx) },
+ { 0x18, 0xa9, HC11OP(adca_indy) },
+ { 0, 0xc9, HC11OP(adcb_imm) },
+ { 0, 0xd9, HC11OP(adcb_dir) },
+ { 0, 0xf9, HC11OP(adcb_ext) },
+ { 0, 0xe9, HC11OP(adcb_indx) },
+ { 0x18, 0xe9, HC11OP(adcb_indy) },
+ { 0, 0x8b, HC11OP(adda_imm) },
+ { 0, 0x9b, HC11OP(adda_dir) },
+ { 0, 0xbb, HC11OP(adda_ext) },
+ { 0, 0xab, HC11OP(adda_indx) },
+ { 0x18, 0xab, HC11OP(adda_indy) },
+ { 0, 0xcb, HC11OP(addb_imm) },
+ { 0, 0xdb, HC11OP(addb_dir) },
+ { 0, 0xfb, HC11OP(addb_ext) },
+ { 0, 0xeb, HC11OP(addb_indx) },
+ { 0x18, 0xeb, HC11OP(addb_indy) },
+ { 0, 0xc3, HC11OP(addd_imm) },
+ { 0, 0xd3, HC11OP(addd_dir) },
+ { 0, 0xf3, HC11OP(addd_ext) },
+ { 0, 0xe3, HC11OP(addd_indx) },
+ { 0x18, 0xe3, HC11OP(addd_indy) },
+ { 0, 0x84, HC11OP(anda_imm) },
+ { 0, 0x94, HC11OP(anda_dir) },
+ { 0, 0xb4, HC11OP(anda_ext) },
+ { 0, 0xa4, HC11OP(anda_indx) },
+ { 0x18, 0xa4, HC11OP(anda_indy) },
+ { 0, 0xc4, HC11OP(andb_imm) },
+ { 0, 0xd4, HC11OP(andb_dir) },
+ { 0, 0xf4, HC11OP(andb_ext) },
+ { 0, 0xe4, HC11OP(andb_indx) },
+ { 0x18, 0xe4, HC11OP(andb_indy) },
+ { 0, 0x48, HC11OP(asla) },
+ { 0, 0x58, HC11OP(aslb) },
+// { 0, 0x78, HC11OP(asl_ext) },
+// { 0, 0x68, HC11OP(asl_indx) },
+// { 0x18, 0x68, HC11OP(asl_indy) },
+// { 0, 0x47, HC11OP(asra) },
+// { 0, 0x57, HC11OP(asrb) },
+// { 0, 0x77, HC11OP(asr_ext) },
+// { 0, 0x67, HC11OP(asr_indx) },
+// { 0x18, 0x67, HC11OP(asr_indy) },
+ { 0, 0x24, HC11OP(bcc) },
+// { 0, 0x15, HC11OP(bclr_dir) },
+ { 0, 0x1d, HC11OP(bclr_indx) },
+// { 0x18, 0x1d, HC11OP(bclr_indy) },
+ { 0, 0x25, HC11OP(bcs) },
+ { 0, 0x27, HC11OP(beq) },
+// { 0, 0x2c, HC11OP(bge) },
+// { 0, 0x2e, HC11OP(bgt) },
+ { 0, 0x22, HC11OP(bhi) },
+ { 0, 0x85, HC11OP(bita_imm) },
+ { 0, 0x95, HC11OP(bita_dir) },
+ { 0, 0xb5, HC11OP(bita_ext) },
+ { 0, 0xa5, HC11OP(bita_indx) },
+ { 0x18, 0xa5, HC11OP(bita_indy) },
+ { 0, 0xc5, HC11OP(bitb_imm) },
+ { 0, 0xd5, HC11OP(bitb_dir) },
+ { 0, 0xf5, HC11OP(bitb_ext) },
+ { 0, 0xe5, HC11OP(bitb_indx) },
+ { 0x18, 0xe5, HC11OP(bitb_indy) },
+ { 0, 0x2f, HC11OP(ble) },
+ { 0, 0x23, HC11OP(bls) },
+// { 0, 0x2d, HC11OP(blt) },
+ { 0, 0x2b, HC11OP(bmi) },
+ { 0, 0x26, HC11OP(bne) },
+ { 0, 0x2a, HC11OP(bpl) },
+ { 0, 0x20, HC11OP(bra) },
+ { 0, 0x13, HC11OP(brclr_dir) },
+ { 0, 0x1f, HC11OP(brclr_indx) },
+// { 0x18, 0x1f, HC11OP(brclr_indy) },
+ { 0, 0x21, HC11OP(brn) },
+ { 0, 0x12, HC11OP(brset_dir) },
+ { 0, 0x1e, HC11OP(brset_indx) },
+// { 0x18, 0x1e, HC11OP(brset_indy) },
+// { 0, 0x14, HC11OP(bset_dir) },
+ { 0, 0x1c, HC11OP(bset_indx) },
+// { 0x18, 0x1c, HC11OP(bset_indy) },
+ { 0, 0x8d, HC11OP(bsr) },
+ { 0, 0x28, HC11OP(bvc) },
+ { 0, 0x29, HC11OP(bvs) },
+ { 0, 0x11, HC11OP(cba) },
+ { 0, 0x0c, HC11OP(clc) },
+ { 0, 0x0e, HC11OP(cli) },
+ { 0, 0x4f, HC11OP(clra) },
+ { 0, 0x5f, HC11OP(clrb) },
+ { 0, 0x7f, HC11OP(clr_ext) },
+ { 0, 0x6f, HC11OP(clr_indx) },
+ { 0x18, 0x6f, HC11OP(clr_indy) },
+ { 0, 0x0a, HC11OP(clv) },
+ { 0, 0x81, HC11OP(cmpa_imm) },
+ { 0, 0x91, HC11OP(cmpa_dir) },
+ { 0, 0xb1, HC11OP(cmpa_ext) },
+ { 0, 0xa1, HC11OP(cmpa_indx) },
+ { 0x18, 0xa1, HC11OP(cmpa_indy) },
+ { 0, 0xc1, HC11OP(cmpb_imm) },
+ { 0, 0xd1, HC11OP(cmpb_dir) },
+ { 0, 0xf1, HC11OP(cmpb_ext) },
+ { 0, 0xe1, HC11OP(cmpb_indx) },
+ { 0x18, 0xe1, HC11OP(cmpb_indy) },
+ { 0, 0x43, HC11OP(coma) },
+ { 0, 0x53, HC11OP(comb) },
+// { 0, 0x73, HC11OP(com_ext) },
+// { 0, 0x63, HC11OP(com_indx) },
+// { 0x18, 0x63, HC11OP(com_indy) },
+ { 0x1a, 0x83, HC11OP(cpd_imm) },
+ { 0x1a, 0x93, HC11OP(cpd_dir) },
+ { 0x1a, 0xb3, HC11OP(cpd_ext) },
+ { 0x1a, 0xa3, HC11OP(cpd_indx) },
+ { 0xcd, 0xa3, HC11OP(cpd_indy) },
+ { 0, 0x8c, HC11OP(cpx_imm) },
+ { 0, 0x9c, HC11OP(cpx_dir) },
+ { 0, 0xbc, HC11OP(cpx_ext) },
+ { 0, 0xac, HC11OP(cpx_indx) },
+ { 0xcd, 0xac, HC11OP(cpx_indy) },
+ { 0x18, 0x8c, HC11OP(cpy_imm) },
+ { 0x18, 0x9c, HC11OP(cpy_dir) },
+ { 0x18, 0xbc, HC11OP(cpy_ext) },
+ { 0x1a, 0xac, HC11OP(cpy_indx) },
+ { 0x18, 0xac, HC11OP(cpy_indy) },
+// { 0, 0x19, HC11OP(daa) },
+ { 0, 0x4a, HC11OP(deca) },
+ { 0, 0x5a, HC11OP(decb) },
+ { 0, 0x7a, HC11OP(dec_ext) },
+ { 0, 0x6a, HC11OP(dec_indx) },
+ { 0x18, 0x6a, HC11OP(dec_indy) },
+// { 0, 0x34, HC11OP(des) },
+ { 0, 0x09, HC11OP(dex) },
+ { 0x18, 0x09, HC11OP(dey) },
+ { 0, 0x88, HC11OP(eora_imm) },
+ { 0, 0x98, HC11OP(eora_dir) },
+ { 0, 0xb8, HC11OP(eora_ext) },
+ { 0, 0xa8, HC11OP(eora_indx) },
+ { 0x18, 0xa8, HC11OP(eora_indy) },
+ { 0, 0xc8, HC11OP(eorb_imm) },
+ { 0, 0xd8, HC11OP(eorb_dir) },
+ { 0, 0xf8, HC11OP(eorb_ext) },
+ { 0, 0xe8, HC11OP(eorb_indx) },
+ { 0x18, 0xe8, HC11OP(eorb_indy) },
+// { 0, 0x03, HC11OP(fdiv) },
+ { 0, 0x02, HC11OP(idiv) },
+ { 0, 0x4c, HC11OP(inca) },
+ { 0, 0x5c, HC11OP(incb) },
+ { 0, 0x7c, HC11OP(inc_ext) },
+ { 0, 0x6c, HC11OP(inc_indx) },
+ { 0x18, 0x6c, HC11OP(inc_indy) },
+// { 0, 0x31, HC11OP(ins) },
+ { 0, 0x08, HC11OP(inx) },
+ { 0x18, 0x08, HC11OP(iny) },
+ { 0, 0x7e, HC11OP(jmp_ext) },
+ { 0, 0x6e, HC11OP(jmp_indx) },
+ { 0x18, 0x6e, HC11OP(jmp_indy) },
+ { 0, 0x9d, HC11OP(jsr_dir) },
+ { 0, 0xbd, HC11OP(jsr_ext) },
+ { 0, 0xad, HC11OP(jsr_indx) },
+ { 0x18, 0xad, HC11OP(jsr_indy) },
+ { 0, 0x86, HC11OP(ldaa_imm) },
+ { 0, 0x96, HC11OP(ldaa_dir) },
+ { 0, 0xb6, HC11OP(ldaa_ext) },
+ { 0, 0xa6, HC11OP(ldaa_indx) },
+ { 0x18, 0xa6, HC11OP(ldaa_indy) },
+ { 0, 0xc6, HC11OP(ldab_imm) },
+ { 0, 0xd6, HC11OP(ldab_dir) },
+ { 0, 0xf6, HC11OP(ldab_ext) },
+ { 0, 0xe6, HC11OP(ldab_indx) },
+ { 0x18, 0xe6, HC11OP(ldab_indy) },
+ { 0, 0xcc, HC11OP(ldd_imm) },
+ { 0, 0xdc, HC11OP(ldd_dir) },
+ { 0, 0xfc, HC11OP(ldd_ext) },
+ { 0, 0xec, HC11OP(ldd_indx) },
+ { 0x18, 0xec, HC11OP(ldd_indy) },
+ { 0, 0x8e, HC11OP(lds_imm) },
+ { 0, 0x9e, HC11OP(lds_dir) },
+ { 0, 0xbe, HC11OP(lds_ext) },
+ { 0, 0xae, HC11OP(lds_indx) },
+ { 0x18, 0xae, HC11OP(lds_indy) },
+ { 0, 0xce, HC11OP(ldx_imm) },
+ { 0, 0xde, HC11OP(ldx_dir) },
+ { 0, 0xfe, HC11OP(ldx_ext) },
+ { 0, 0xee, HC11OP(ldx_indx) },
+ { 0xcd, 0xee, HC11OP(ldx_indy) },
+ { 0x18, 0xce, HC11OP(ldy_imm) },
+ { 0x18, 0xde, HC11OP(ldy_dir) },
+ { 0x18, 0xfe, HC11OP(ldy_ext) },
+ { 0x1a, 0xee, HC11OP(ldy_indx) },
+ { 0x18, 0xee, HC11OP(ldy_indy) },
+ { 0, 0x05, HC11OP(lsld) },
+ { 0, 0x44, HC11OP(lsra) },
+ { 0, 0x54, HC11OP(lsrb) },
+// { 0, 0x74, HC11OP(lsr_ext) },
+// { 0, 0x64, HC11OP(lsr_indx) },
+// { 0x18, 0x64, HC11OP(lsr_indy) },
+ { 0, 0x04, HC11OP(lsrd) },
+ { 0, 0x3d, HC11OP(mul) },
+ { 0, 0x40, HC11OP(nega) },
+ { 0, 0x50, HC11OP(negb) },
+ { 0, 0x70, HC11OP(neg_ext) },
+ { 0, 0x60, HC11OP(neg_indx) },
+ { 0x18, 0x60, HC11OP(neg_indy) },
+ { 0, 0x01, HC11OP(nop) },
+ { 0, 0x8a, HC11OP(oraa_imm) },
+ { 0, 0x9a, HC11OP(oraa_dir) },
+ { 0, 0xba, HC11OP(oraa_ext) },
+ { 0, 0xaa, HC11OP(oraa_indx) },
+ { 0x18, 0xaa, HC11OP(oraa_indy) },
+ { 0, 0xca, HC11OP(orab_imm) },
+ { 0, 0xda, HC11OP(orab_dir) },
+ { 0, 0xfa, HC11OP(orab_ext) },
+ { 0, 0xea, HC11OP(orab_indx) },
+ { 0x18, 0xea, HC11OP(orab_indy) },
+ { 0, 0x36, HC11OP(psha) },
+ { 0, 0x37, HC11OP(pshb) },
+ { 0, 0x3c, HC11OP(pshx) },
+ { 0x18, 0x3c, HC11OP(pshy) },
+ { 0, 0x32, HC11OP(pula) },
+ { 0, 0x33, HC11OP(pulb) },
+ { 0, 0x38, HC11OP(pulx) },
+ { 0x18, 0x38, HC11OP(puly) },
+ { 0, 0x49, HC11OP(rola) },
+ { 0, 0x59, HC11OP(rolb) },
+// { 0, 0x79, HC11OP(rol_ext) },
+// { 0, 0x69, HC11OP(rol_indx) },
+// { 0x18, 0x69, HC11OP(rol_indy) },
+ { 0, 0x46, HC11OP(rora) },
+ { 0, 0x56, HC11OP(rorb) },
+// { 0, 0x76, HC11OP(ror_ext) },
+// { 0, 0x66, HC11OP(ror_indx) },
+// { 0x18, 0x66, HC11OP(ror_indy) },
+ { 0, 0x3b, HC11OP(rti) },
+ { 0, 0x39, HC11OP(rts) },
+ { 0, 0x10, HC11OP(sba) },
+ { 0, 0x82, HC11OP(sbca_imm) },
+// { 0, 0x92, HC11OP(sbca_dir) },
+// { 0, 0xb2, HC11OP(sbca_ext) },
+ { 0, 0xa2, HC11OP(sbca_indx) },
+ { 0x18, 0xa2, HC11OP(sbca_indy) },
+ { 0, 0xc2, HC11OP(sbcb_imm) },
+// { 0, 0xd2, HC11OP(sbcb_dir) },
+// { 0, 0xf2, HC11OP(sbcb_ext) },
+ { 0, 0xe2, HC11OP(sbcb_indx) },
+ { 0x18, 0xe2, HC11OP(sbcb_indy) },
+ { 0, 0x0d, HC11OP(sec) },
+ { 0, 0x0f, HC11OP(sei) },
+ { 0, 0x0b, HC11OP(sev) },
+ { 0, 0x97, HC11OP(staa_dir) },
+ { 0, 0xb7, HC11OP(staa_ext) },
+ { 0, 0xa7, HC11OP(staa_indx) },
+ { 0x18, 0xa7, HC11OP(staa_indy) },
+ { 0, 0xd7, HC11OP(stab_dir) },
+ { 0, 0xf7, HC11OP(stab_ext) },
+ { 0, 0xe7, HC11OP(stab_indx) },
+ { 0x18, 0xe7, HC11OP(stab_indy) },
+ { 0, 0xdd, HC11OP(std_dir) },
+ { 0, 0xfd, HC11OP(std_ext) },
+ { 0, 0xed, HC11OP(std_indx) },
+ { 0x18, 0xed, HC11OP(std_indy) },
+// { 0, 0x9f, HC11OP(sts_dir) },
+// { 0, 0xbf, HC11OP(sts_ext) },
+// { 0, 0xaf, HC11OP(sts_indx) },
+// { 0x18, 0xaf, HC11OP(sts_indy) },
+ { 0, 0xdf, HC11OP(stx_dir) },
+ { 0, 0xff, HC11OP(stx_ext) },
+ { 0, 0xef, HC11OP(stx_indx) },
+ { 0xcd, 0xef, HC11OP(stx_indy) },
+ { 0x18, 0xdf, HC11OP(sty_dir) },
+ { 0x18, 0xff, HC11OP(sty_ext) },
+ { 0x1a, 0xef, HC11OP(sty_indx) },
+ { 0x18, 0xef, HC11OP(sty_indy) },
+ { 0, 0xcf, HC11OP(stop) },
+ { 0, 0x80, HC11OP(suba_imm) },
+ { 0, 0x90, HC11OP(suba_dir) },
+ { 0, 0xb0, HC11OP(suba_ext) },
+ { 0, 0xa0, HC11OP(suba_indx) },
+ { 0x18, 0xa0, HC11OP(suba_indy) },
+ { 0, 0xc0, HC11OP(subb_imm) },
+ { 0, 0xd0, HC11OP(subb_dir) },
+ { 0, 0xf0, HC11OP(subb_ext) },
+ { 0, 0xe0, HC11OP(subb_indx) },
+ { 0x18, 0xe0, HC11OP(subb_indy) },
+ { 0, 0x83, HC11OP(subd_imm) },
+ { 0, 0x93, HC11OP(subd_dir) },
+ { 0, 0xb3, HC11OP(subd_ext) },
+ { 0, 0xa3, HC11OP(subd_indx) },
+ { 0x18, 0xa3, HC11OP(subd_indy) },
+ { 0, 0x3f, HC11OP(swi) },
+ { 0, 0x16, HC11OP(tab) },
+ { 0, 0x06, HC11OP(tap) },
+ { 0, 0x17, HC11OP(tba) },
+ { 0, 0x00, HC11OP(test) },
+ { 0, 0x07, HC11OP(tpa) },
+ { 0, 0x4d, HC11OP(tsta) },
+ { 0, 0x5d, HC11OP(tstb) },
+ { 0, 0x7d, HC11OP(tst_ext) },
+ { 0, 0x6d, HC11OP(tst_indx) },
+ { 0x18, 0x6d, HC11OP(tst_indy) },
+ { 0, 0x30, HC11OP(tsx) },
+ { 0x18, 0x30, HC11OP(tsy) },
+ { 0, 0x35, HC11OP(txs) },
+ { 0x18, 0x35, HC11OP(tys) },
+ { 0, 0x3e, HC11OP(wai) },
+ { 0, 0x8f, HC11OP(xgdx) },
+ { 0x18, 0x8f, HC11OP(xgdy) },
+
+ { 0, 0x18, HC11OP(page2) },
+ { 0, 0x1a, HC11OP(page3) },
+ { 0, 0xcd, HC11OP(page4) },
+};
diff --git a/trunk/src/emu/cpu/mc68hc11/mc68hc11.c b/trunk/src/emu/cpu/mc68hc11/mc68hc11.c
new file mode 100644
index 00000000000..ebcf5151f02
--- /dev/null
+++ b/trunk/src/emu/cpu/mc68hc11/mc68hc11.c
@@ -0,0 +1,613 @@
+/*
+ Motorola MC68HC11 emulator
+
+ Written by Ville Linde & Angelo Salese
+
+TODO:
+- Interrupts handling is really bare-bones, just to make Hit Poker happy;
+- Complete opcodes hook-up;
+- Emulate the MC68HC12 (same as HC11 with a bunch of new opcodes);
+
+ */
+
+#include "emu.h"
+#include "debugger.h"
+#include "mc68hc11.h"
+
+enum
+{
+ HC11_PC = 1,
+ HC11_SP,
+ HC11_A,
+ HC11_B,
+ HC11_IX,
+ HC11_IY
+};
+
+#define CC_S 0x80
+#define CC_X 0x40
+#define CC_H 0x20
+#define CC_I 0x10
+#define CC_N 0x08
+#define CC_Z 0x04
+#define CC_V 0x02
+#define CC_C 0x01
+
+typedef struct _hc11_state hc11_state;
+struct _hc11_state
+{
+ union {
+ struct {
+#ifdef LSB_FIRST
+ UINT8 b;
+ UINT8 a;
+#else
+ UINT8 a;
+ UINT8 b;
+#endif
+ } d8;
+ UINT16 d16;
+ } d;
+
+ UINT16 ix;
+ UINT16 iy;
+ UINT16 sp;
+ UINT16 pc;
+ UINT16 ppc;
+ UINT8 ccr;
+
+ UINT8 adctl;
+ int ad_channel;
+
+ device_irq_callback irq_callback;
+ UINT8 irq_state[2];
+ legacy_cpu_device *device;
+ direct_read_data *direct;
+ address_space *program;
+ address_space *io;
+ int icount;
+
+ int ram_position;
+ int reg_position;
+ UINT8 *internal_ram;
+
+ int has_extended_io; // extended I/O enable flag
+ int internal_ram_size;
+
+ UINT8 wait_state,stop_state;
+
+ UINT8 tflg1;
+};
+
+INLINE hc11_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == MC68HC11);
+ return (hc11_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+#define HC11OP(XX) hc11_##XX
+
+/*****************************************************************************/
+/* Internal registers */
+
+static UINT8 hc11_regs_r(hc11_state *cpustate, UINT32 address)
+{
+ int reg = address & 0xff;
+
+ switch(reg)
+ {
+ case 0x00: /* PORTA */
+ return cpustate->io->read_byte(MC68HC11_IO_PORTA);
+ case 0x01: /* DDRA */
+ return 0;
+ case 0x02: /* PIOC */
+ return 0;
+ case 0x03: /* PORTC */
+ return cpustate->io->read_byte(MC68HC11_IO_PORTC);
+ case 0x04: /* PORTB */
+ return cpustate->io->read_byte(MC68HC11_IO_PORTB);
+ case 0x08: /* PORTD */
+ return cpustate->io->read_byte(MC68HC11_IO_PORTD);
+ case 0x09: /* DDRD */
+ return 0;
+ case 0x0a: /* PORTE */
+ return cpustate->io->read_byte(MC68HC11_IO_PORTE);
+ case 0x23:
+ return cpustate->tflg1;
+ case 0x28: /* SPCR1 */
+ return 0;
+ case 0x30: /* ADCTL */
+ return 0x80;
+ case 0x31: /* ADR1 */
+ {
+ if (cpustate->adctl & 0x10)
+ {
+ return cpustate->io->read_byte((cpustate->adctl & 0x4) + MC68HC11_IO_AD0);
+ }
+ else
+ {
+ return cpustate->io->read_byte((cpustate->adctl & 0x7) + MC68HC11_IO_AD0);
+ }
+ }
+ case 0x32: /* ADR2 */
+ {
+ if (cpustate->adctl & 0x10)
+ {
+ return cpustate->io->read_byte((cpustate->adctl & 0x4) + MC68HC11_IO_AD1);
+ }
+ else
+ {
+ return cpustate->io->read_byte((cpustate->adctl & 0x7) + MC68HC11_IO_AD0);
+ }
+ }
+ case 0x33: /* ADR3 */
+ {
+ if (cpustate->adctl & 0x10)
+ {
+ return cpustate->io->read_byte((cpustate->adctl & 0x4) + MC68HC11_IO_AD2);
+ }
+ else
+ {
+ return cpustate->io->read_byte((cpustate->adctl & 0x7) + MC68HC11_IO_AD0);
+ }
+ }
+ case 0x34: /* ADR4 */
+ {
+ if (cpustate->adctl & 0x10)
+ {
+ return cpustate->io->read_byte((cpustate->adctl & 0x4) + MC68HC11_IO_AD3);
+ }
+ else
+ {
+ return cpustate->io->read_byte((cpustate->adctl & 0x7) + MC68HC11_IO_AD0);
+ }
+ }
+ case 0x38: /* OPT2 */
+ return 0;
+ case 0x70: /* SCBDH */
+ return 0;
+ case 0x71: /* SCBDL */
+ return 0;
+ case 0x72: /* SCCR1 */
+ return 0;
+ case 0x73: /* SCCR2 */
+ return 0;
+ case 0x74: /* SCSR1 */
+ return 0x40;
+ case 0x7c: /* PORTH */
+ return cpustate->io->read_byte(MC68HC11_IO_PORTH);
+ case 0x7e: /* PORTG */
+ return cpustate->io->read_byte(MC68HC11_IO_PORTG);
+ case 0x7f: /* DDRG */
+ return 0;
+
+ case 0x88: /* SPCR2 */
+ return 0;
+ case 0x89: /* SPSR2 */
+ return 0x80;
+ case 0x8a: /* SPDR2 */
+ return cpustate->io->read_byte(MC68HC11_IO_SPI2_DATA);
+
+ case 0x8b: /* OPT4 */
+ return 0;
+ }
+
+ logerror("HC11: regs_r %02X\n", reg);
+ return 0; // Dummy
+}
+
+static void hc11_regs_w(hc11_state *cpustate, UINT32 address, UINT8 value)
+{
+ int reg = address & 0xff;
+
+ switch(reg)
+ {
+ case 0x00: /* PORTA */
+ cpustate->io->write_byte(MC68HC11_IO_PORTA, value);
+ return;
+ case 0x01: /* DDRA */
+ //mame_printf_debug("HC11: ddra = %02X\n", value);
+ return;
+ case 0x03: /* PORTC */
+ cpustate->io->write_byte(MC68HC11_IO_PORTC, value);
+ return;
+ case 0x04: /* PORTC */
+ cpustate->io->write_byte(MC68HC11_IO_PORTB, value);
+ return;
+ case 0x08: /* PORTD */
+ cpustate->io->write_byte(MC68HC11_IO_PORTD, value); //mask & 0x3f?
+ return;
+ case 0x09: /* DDRD */
+ //mame_printf_debug("HC11: ddrd = %02X\n", value);
+ return;
+ case 0x0a: /* PORTE */
+ cpustate->io->write_byte(MC68HC11_IO_PORTE, value);
+ return;
+ case 0x22: /* TMSK1 */
+ return;
+ case 0x23:
+ cpustate->tflg1 = value;
+ return;
+ case 0x24: /* TMSK2 */
+ return;
+ case 0x28: /* SPCR1 */
+ return;
+ case 0x30: /* ADCTL */
+ cpustate->adctl = value;
+ return;
+ case 0x38: /* OPT2 */
+ return;
+ case 0x39: /* OPTION */
+ return;
+ case 0x3a: /* COPRST (watchdog) */
+ return;
+
+ case 0x3d: /* INIT */
+ {
+ int reg_page = value & 0xf;
+ int ram_page = (value >> 4) & 0xf;
+
+ if (reg_page == ram_page) {
+ cpustate->reg_position = reg_page << 12;
+ cpustate->ram_position = (ram_page << 12) + 0x100;
+ } else {
+ cpustate->reg_position = reg_page << 12;
+ cpustate->ram_position = ram_page << 12;
+ }
+ return;
+ }
+
+ case 0x3f: /* CONFIG */
+ return;
+
+ case 0x70: /* SCBDH */
+ return;
+ case 0x71: /* SCBDL */
+ return;
+ case 0x72: /* SCCR1 */
+ return;
+ case 0x73: /* SCCR2 */
+ return;
+ case 0x77: /* SCDRL */
+ return;
+ case 0x7c: /* PORTH */
+ cpustate->io->write_byte(MC68HC11_IO_PORTH, value);
+ return;
+ case 0x7d: /* DDRH */
+ //mame_printf_debug("HC11: ddrh = %02X at %04X\n", value, cpustate->pc);
+ return;
+ case 0x7e: /* PORTG */
+ cpustate->io->write_byte(MC68HC11_IO_PORTG, value);
+ return;
+ case 0x7f: /* DDRG */
+ //mame_printf_debug("HC11: ddrg = %02X at %04X\n", value, cpustate->pc);
+ return;
+
+ case 0x88: /* SPCR2 */
+ return;
+ case 0x89: /* SPSR2 */
+ return;
+ case 0x8a: /* SPDR2 */
+ cpustate->io->write_byte(MC68HC11_IO_SPI2_DATA, value);
+ return;
+
+ case 0x8b: /* OPT4 */
+ return;
+
+ }
+
+ logerror("HC11: regs_w %02X, %02X\n", reg, value);
+}
+
+/*****************************************************************************/
+
+INLINE UINT8 FETCH(hc11_state *cpustate)
+{
+ return cpustate->direct->read_decrypted_byte(cpustate->pc++);
+}
+
+INLINE UINT16 FETCH16(hc11_state *cpustate)
+{
+ UINT16 w;
+ w = (cpustate->direct->read_decrypted_byte(cpustate->pc) << 8) | (cpustate->direct->read_decrypted_byte(cpustate->pc+1));
+ cpustate->pc += 2;
+ return w;
+}
+
+INLINE UINT8 READ8(hc11_state *cpustate, UINT32 address)
+{
+ if(address >= cpustate->reg_position && address < cpustate->reg_position+(cpustate->has_extended_io ? 0x100 : 0x40))
+ {
+ return hc11_regs_r(cpustate, address);
+ }
+ else if(address >= cpustate->ram_position && address < cpustate->ram_position+cpustate->internal_ram_size)
+ {
+ return cpustate->internal_ram[address-cpustate->ram_position];
+ }
+ return cpustate->program->read_byte(address);
+}
+
+INLINE void WRITE8(hc11_state *cpustate, UINT32 address, UINT8 value)
+{
+ if(address >= cpustate->reg_position && address < cpustate->reg_position+(cpustate->has_extended_io ? 0x100 : 0x40))
+ {
+ hc11_regs_w(cpustate, address, value);
+ return;
+ }
+ else if(address >= cpustate->ram_position && address < cpustate->ram_position+cpustate->internal_ram_size)
+ {
+ cpustate->internal_ram[address-cpustate->ram_position] = value;
+ return;
+ }
+ cpustate->program->write_byte(address, value);
+}
+
+INLINE UINT16 READ16(hc11_state *cpustate, UINT32 address)
+{
+ return (READ8(cpustate, address) << 8) | (READ8(cpustate, address+1));
+}
+
+INLINE void WRITE16(hc11_state *cpustate, UINT32 address, UINT16 value)
+{
+ WRITE8(cpustate, address+0, (value >> 8) & 0xff);
+ WRITE8(cpustate, address+1, (value >> 0) & 0xff);
+}
+
+/*****************************************************************************/
+
+static void (*hc11_optable[256])(hc11_state *cpustate);
+static void (*hc11_optable_page2[256])(hc11_state *cpustate);
+static void (*hc11_optable_page3[256])(hc11_state *cpustate);
+static void (*hc11_optable_page4[256])(hc11_state *cpustate);
+
+#include "hc11ops.c"
+#include "hc11ops.h"
+
+static CPU_INIT( hc11 )
+{
+ hc11_state *cpustate = get_safe_token(device);
+ int i;
+
+ const hc11_config *conf = (const hc11_config *)device->static_config();
+
+ /* clear the opcode tables */
+ for(i=0; i < 256; i++) {
+ hc11_optable[i] = HC11OP(invalid);
+ hc11_optable_page2[i] = HC11OP(invalid);
+ hc11_optable_page3[i] = HC11OP(invalid);
+ hc11_optable_page4[i] = HC11OP(invalid);
+ }
+ /* fill the opcode tables */
+ for(i=0; i < sizeof(hc11_opcode_list)/sizeof(hc11_opcode_list_struct); i++)
+ {
+ switch(hc11_opcode_list[i].page)
+ {
+ case 0x00:
+ hc11_optable[hc11_opcode_list[i].opcode] = hc11_opcode_list[i].handler;
+ break;
+ case 0x18:
+ hc11_optable_page2[hc11_opcode_list[i].opcode] = hc11_opcode_list[i].handler;
+ break;
+ case 0x1A:
+ hc11_optable_page3[hc11_opcode_list[i].opcode] = hc11_opcode_list[i].handler;
+ break;
+ case 0xCD:
+ hc11_optable_page4[hc11_opcode_list[i].opcode] = hc11_opcode_list[i].handler;
+ break;
+ }
+ }
+
+ if(conf)
+ {
+ cpustate->has_extended_io = conf->has_extended_io;
+ cpustate->internal_ram_size = conf->internal_ram_size;
+ }
+ else
+ {
+ /* defaults it to the HC11M0 version for now (I might strip this down on a later date) */
+ cpustate->has_extended_io = 1;
+ cpustate->internal_ram_size = 1280;
+ }
+
+ cpustate->internal_ram = auto_alloc_array(device->machine(), UINT8, cpustate->internal_ram_size);
+
+ cpustate->reg_position = 0;
+ cpustate->ram_position = 0x100;
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+ cpustate->io = device->space(AS_IO);
+}
+
+static CPU_RESET( hc11 )
+{
+ hc11_state *cpustate = get_safe_token(device);
+ cpustate->pc = READ16(cpustate, 0xfffe);
+ cpustate->wait_state = 0;
+ cpustate->stop_state = 0;
+ cpustate->ccr = CC_X | CC_I | CC_S;
+ cpustate->reg_position = 0x1000;
+ cpustate->ram_position = 0;
+}
+
+static CPU_EXIT( hc11 )
+{
+
+}
+
+/*
+IRQ table vectors:
+0xffd6: SCI
+0xffd8: SPI
+0xffda: Pulse Accumulator Input Edge
+0xffdc: Pulse Accumulator Overflow
+0xffde: Timer Overflow
+0xffe0: Timer Output Capture 5
+0xffe2: Timer Output Capture 4
+0xffe4: Timer Output Capture 3
+0xffe6: Timer Output Capture 2
+0xffe8: Timer Output Capture 1
+0xffea: Timer Input Capture 3
+0xffec: Timer Input Capture 2
+0xffee: Timer Input Capture 1
+0xfff0: Real Time Int
+0xfff2: IRQ
+0xfff4: XIRQ
+0xfff6: SWI (Trap IRQ)
+0xfff8: Illegal Opcode (NMI)
+0xfffa: CO-Processor Fail
+0xfffc: Clock Monitor
+0xfffe: RESET
+*/
+
+static void check_irq_lines(hc11_state *cpustate)
+{
+ if( cpustate->irq_state[MC68HC11_IRQ_LINE]!=CLEAR_LINE && (!(cpustate->ccr & CC_I)) )
+ {
+ UINT16 pc_vector;
+
+ if(cpustate->wait_state == 0)
+ {
+ PUSH16(cpustate, cpustate->pc);
+ PUSH16(cpustate, cpustate->iy);
+ PUSH16(cpustate, cpustate->ix);
+ PUSH8(cpustate, REG_A);
+ PUSH8(cpustate, REG_B);
+ PUSH8(cpustate, cpustate->ccr);
+ }
+ pc_vector = READ16(cpustate, 0xfff2);
+ SET_PC(cpustate, pc_vector);
+ cpustate->ccr |= CC_I; //irq taken, mask the flag
+ if(cpustate->wait_state == 1) { cpustate->wait_state = 2; }
+ if(cpustate->stop_state == 1) { cpustate->stop_state = 2; }
+ (void)(*cpustate->irq_callback)(cpustate->device, MC68HC11_IRQ_LINE);
+ }
+}
+
+static void set_irq_line(hc11_state *cpustate, int irqline, int state)
+{
+ cpustate->irq_state[irqline] = state;
+ if (state == CLEAR_LINE) return;
+ check_irq_lines(cpustate);
+}
+
+static CPU_EXECUTE( hc11 )
+{
+ hc11_state *cpustate = get_safe_token(device);
+
+ while(cpustate->icount > 0)
+ {
+ UINT8 op;
+
+ check_irq_lines(cpustate);
+
+ cpustate->ppc = cpustate->pc;
+ debugger_instruction_hook(device, cpustate->pc);
+
+ op = FETCH(cpustate);
+ hc11_optable[op](cpustate);
+ }
+}
+
+/*****************************************************************************/
+
+static CPU_SET_INFO( mc68hc11 )
+{
+ hc11_state *cpustate = get_safe_token(device);
+
+ switch (state)
+ {
+ case CPUINFO_INT_INPUT_STATE + MC68HC11_IRQ_LINE: set_irq_line(cpustate, MC68HC11_IRQ_LINE, info->i); break;
+
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_PC: cpustate->pc = info->i; break;
+ case CPUINFO_INT_REGISTER + HC11_PC: cpustate->pc = info->i; break;
+ case CPUINFO_INT_REGISTER + HC11_SP: cpustate->sp = info->i; break;
+ case CPUINFO_INT_REGISTER + HC11_A: cpustate->d.d8.a = info->i; break;
+ case CPUINFO_INT_REGISTER + HC11_B: cpustate->d.d8.b = info->i; break;
+ case CPUINFO_INT_REGISTER + HC11_IX: cpustate->ix = info->i; break;
+ case CPUINFO_INT_REGISTER + HC11_IY: cpustate->iy = info->i; break;
+ }
+}
+
+CPU_GET_INFO( mc68hc11 )
+{
+ hc11_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch(state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(hc11_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 1; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 5; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 41; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_INPUT_STATE + MC68HC11_IRQ_LINE: info->i = cpustate->irq_state[MC68HC11_IRQ_LINE]; break;
+
+ case CPUINFO_INT_PREVIOUSPC: /* not implemented */ break;
+
+ case CPUINFO_INT_PC: /* intentional fallthrough */
+ case CPUINFO_INT_REGISTER + HC11_PC: info->i = cpustate->pc; break;
+ case CPUINFO_INT_REGISTER + HC11_SP: info->i = cpustate->sp; break;
+ case CPUINFO_INT_REGISTER + HC11_A: info->i = cpustate->d.d8.a; break;
+ case CPUINFO_INT_REGISTER + HC11_B: info->i = cpustate->d.d8.b; break;
+ case CPUINFO_INT_REGISTER + HC11_IX: info->i = cpustate->ix; break;
+ case CPUINFO_INT_REGISTER + HC11_IY: info->i = cpustate->iy; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(mc68hc11); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(hc11); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(hc11); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(hc11); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(hc11); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(hc11); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "MC68HC11"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Motorola MC68HC11"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Ville Linde"); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c%c%c%c%c%c%c",
+ (cpustate->ccr & CC_S) ? 'S' : '.',
+ (cpustate->ccr & CC_X) ? 'X' : '.',
+ (cpustate->ccr & CC_H) ? 'H' : '.',
+ (cpustate->ccr & CC_I) ? 'I' : '.',
+ (cpustate->ccr & CC_N) ? 'N' : '.',
+ (cpustate->ccr & CC_Z) ? 'Z' : '.',
+ (cpustate->ccr & CC_V) ? 'V' : '.',
+ (cpustate->ccr & CC_C) ? 'C' : '.');
+ break;
+
+ case CPUINFO_STR_REGISTER + HC11_PC: sprintf(info->s, "PC: %04X", cpustate->pc); break;
+ case CPUINFO_STR_REGISTER + HC11_SP: sprintf(info->s, "SP: %04X", cpustate->sp); break;
+ case CPUINFO_STR_REGISTER + HC11_A: sprintf(info->s, "A: %02X", cpustate->d.d8.a); break;
+ case CPUINFO_STR_REGISTER + HC11_B: sprintf(info->s, "B: %02X", cpustate->d.d8.b); break;
+ case CPUINFO_STR_REGISTER + HC11_IX: sprintf(info->s, "IX: %04X", cpustate->ix); break;
+ case CPUINFO_STR_REGISTER + HC11_IY: sprintf(info->s, "IY: %04X", cpustate->iy); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(MC68HC11, mc68hc11);
diff --git a/trunk/src/emu/cpu/mc68hc11/mc68hc11.h b/trunk/src/emu/cpu/mc68hc11/mc68hc11.h
new file mode 100644
index 00000000000..6c20c812295
--- /dev/null
+++ b/trunk/src/emu/cpu/mc68hc11/mc68hc11.h
@@ -0,0 +1,41 @@
+#pragma once
+
+#ifndef __MC68HC11_H__
+#define __MC68HC11_H__
+
+
+CPU_DISASSEMBLE( hc11 );
+
+DECLARE_LEGACY_CPU_DEVICE(MC68HC11, mc68hc11);
+
+
+#define MC68HC11_IO_PORTA 0x00
+#define MC68HC11_IO_PORTB 0x01
+#define MC68HC11_IO_PORTC 0x02
+#define MC68HC11_IO_PORTD 0x03
+#define MC68HC11_IO_PORTE 0x04
+#define MC68HC11_IO_PORTF 0x05
+#define MC68HC11_IO_PORTG 0x06
+#define MC68HC11_IO_PORTH 0x07
+#define MC68HC11_IO_SPI1_DATA 0x08
+#define MC68HC11_IO_SPI2_DATA 0x09
+#define MC68HC11_IO_AD0 0x10
+#define MC68HC11_IO_AD1 0x11
+#define MC68HC11_IO_AD2 0x12
+#define MC68HC11_IO_AD3 0x13
+#define MC68HC11_IO_AD4 0x14
+#define MC68HC11_IO_AD5 0x15
+#define MC68HC11_IO_AD6 0x16
+#define MC68HC11_IO_AD7 0x17
+
+#define MC68HC11_IRQ_LINE 0
+
+typedef struct _hc11_config hc11_config;
+struct _hc11_config
+{
+ int has_extended_io; // I/O enable flag
+ int internal_ram_size;
+};
+
+
+#endif /* __MC68HC11_H__ */
diff --git a/trunk/src/emu/cpu/mcs48/mcs48.c b/trunk/src/emu/cpu/mcs48/mcs48.c
new file mode 100644
index 00000000000..71864db4398
--- /dev/null
+++ b/trunk/src/emu/cpu/mcs48/mcs48.c
@@ -0,0 +1,1546 @@
+/*
+EA pin - defined by architecture, must implement:
+ 1 means external access, bypassing internal ROM
+ reimplement as a push, not a pull
+T0 output clock
+*/
+
+/***************************************************************************
+
+ mcs48.c
+
+ Intel MCS-48/UPI-41 Portable Emulator
+
+ Copyright Mirko Buffoni
+ Based on the original work Copyright Dan Boris, an 8048 emulator
+ You are not allowed to distribute this software commercially
+
+****************************************************************************
+
+ Note that the default internal divisor for this chip is by 3 and
+ then again by 5, or by 15 total.
+
+****************************************************************************
+
+ Chip RAM ROM I/O
+ ---- --- --- ---
+ 8021 64 1k 21 (ROM, reduced instruction set)
+
+ 8035 64 0 27 (external ROM)
+ 8048 64 1k 27 (ROM)
+ 8648 64 1k 27 (OTPROM)
+ 8748 64 1k 27 (EPROM)
+ 8884 64 1k
+ N7751 128 2k
+
+ 8039 128 0 27 (external ROM)
+ 8049 128 2k 27 (ROM)
+ 8749 128 2k 27 (EPROM)
+ M58715 128 0 (external ROM)
+
+****************************************************************************
+
+ UPI-41/42 chips are MCS-48 derived, with some opcode changes:
+
+ MCS-48 opcode UPI-41/42 opcode
+ ------------- ----------------
+ 02: OUTL BUS,A OUT DBB,A
+ 08: INS BUS,A <illegal>
+ 22: <illegal> IN DBB,A
+ 75: ENT0 CLK <illegal>
+ 80: MOVX A,@R0 <illegal>
+ 81: MOVX A,@R1 <illegal>
+ 86: JNI <dest> JOBF <dest>
+ 88: ORL BUS,#n <illegal>
+ 90: MOVX @R0,A MOV STS,A
+ 91: MOVX @R1,A <illegal>
+ 98: ANL BUS,#n <illegal>
+ D6: <illegal> JNIBF <dest>
+ E5: SEL MB0 EN DMA
+ F5: SEL MB1 EN FLAGS
+
+ Chip numbers are similar to the MCS-48 series:
+
+ Chip RAM ROM I/O
+ ---- --- --- ---
+ 8041 128 1k
+ 8741 128 1k (EPROM)
+
+ 8042 256 2k
+ 8242 256 2k
+ 8242 256 2k
+
+***************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "mcs48.h"
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+/* timer/counter enable bits */
+#define TIMER_ENABLED 0x01
+#define COUNTER_ENABLED 0x02
+
+/* flag bits */
+#define C_FLAG 0x80
+#define A_FLAG 0x40
+#define F_FLAG 0x20
+#define B_FLAG 0x10
+
+/* status bits (UPI-41) */
+#define STS_F1 0x08
+#define STS_F0 0x04
+#define STS_IBF 0x02
+#define STS_OBF 0x01
+
+/* port 2 bits (UPI-41) */
+#define P2_OBF 0x10
+#define P2_NIBF 0x20
+#define P2_DRQ 0x40
+#define P2_NDACK 0x80
+
+/* enable bits (UPI-41) */
+#define ENABLE_FLAGS 0x01
+#define ENABLE_DMA 0x02
+
+/* feature masks */
+#define MCS48_FEATURE 0x01
+#define UPI41_FEATURE 0x02
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+/* live processor state */
+typedef struct _mcs48_state mcs48_state;
+struct _mcs48_state
+{
+ UINT16 prevpc; /* 16-bit previous program counter */
+ UINT16 pc; /* 16-bit program counter */
+
+ UINT8 a; /* 8-bit accumulator */
+ UINT8 * regptr; /* pointer to r0-r7 */
+ UINT8 psw; /* 8-bit cpustate->psw */
+ UINT8 p1; /* 8-bit latched port 1 */
+ UINT8 p2; /* 8-bit latched port 2 */
+ UINT8 ea; /* 1-bit latched ea input */
+ UINT8 timer; /* 8-bit timer */
+ UINT8 prescaler; /* 5-bit timer prescaler */
+ UINT8 t1_history; /* 8-bit history of the T1 input */
+ UINT8 sts; /* 8-bit status register (UPI-41 only, except for F1) */
+ UINT8 dbbi; /* 8-bit input data buffer (UPI-41 only) */
+ UINT8 dbbo; /* 8-bit output data buffer (UPI-41 only) */
+
+ UINT8 irq_state; /* TRUE if an IRQ is pending */
+ UINT8 irq_in_progress; /* TRUE if an IRQ is in progress */
+ UINT8 timer_overflow; /* TRUE on a timer overflow; cleared by taking interrupt */
+ UINT8 timer_flag; /* TRUE on a timer overflow; cleared on JTF */
+ UINT8 tirq_enabled; /* TRUE if the timer IRQ is enabled */
+ UINT8 xirq_enabled; /* TRUE if the external IRQ is enabled */
+ UINT8 timecount_enabled; /* bitmask of timer/counter enabled */
+ UINT8 flags_enabled; /* TRUE if I/O flags have been enabled (UPI-41 only) */
+ UINT8 dma_enabled; /* TRUE if DMA has been enabled (UPI-41 only) */
+
+ UINT16 a11; /* A11 value, either 0x000 or 0x800 */
+
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ int icount;
+
+ /* Memory spaces */
+ address_space *program;
+ direct_read_data *direct;
+ address_space *data;
+ address_space *io;
+
+ UINT8 feature_mask; /* processor feature flags */
+ UINT16 int_rom_size; /* internal rom size */
+
+ UINT8 rtemp; /* temporary for import/export */
+};
+
+
+/* opcode table entry */
+typedef int (*mcs48_ophandler)(mcs48_state *state);
+
+
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+/* ROM is mapped to AS_PROGRAM */
+#define program_r(a) cpustate->program->read_byte(a)
+
+/* RAM is mapped to AS_DATA */
+#define ram_r(a) cpustate->data->read_byte(a)
+#define ram_w(a,V) cpustate->data->write_byte(a, V)
+
+/* ports are mapped to AS_IO */
+#define ext_r(a) cpustate->io->read_byte(a)
+#define ext_w(a,V) cpustate->io->write_byte(a, V)
+#define port_r(a) cpustate->io->read_byte(MCS48_PORT_P0 + a)
+#define port_w(a,V) cpustate->io->write_byte(MCS48_PORT_P0 + a, V)
+#define test_r(a) cpustate->io->read_byte(MCS48_PORT_T0 + a)
+#define test_w(a,V) cpustate->io->write_byte(MCS48_PORT_T0 + a, V)
+#define bus_r() cpustate->io->read_byte(MCS48_PORT_BUS)
+#define bus_w(V) cpustate->io->write_byte(MCS48_PORT_BUS, V)
+#define ea_r() cpustate->io->read_byte(MCS48_PORT_EA)
+#define prog_w(V) cpustate->io->write_byte(MCS48_PORT_PROG, V)
+
+/* r0-r7 map to memory via the regptr */
+#define R0 regptr[0]
+#define R1 regptr[1]
+#define R2 regptr[2]
+#define R3 regptr[3]
+#define R4 regptr[4]
+#define R5 regptr[5]
+#define R6 regptr[6]
+#define R7 regptr[7]
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static int check_irqs(mcs48_state *cpustate);
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+INLINE mcs48_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == I8021 ||
+ device->type() == I8022 ||
+ device->type() == I8035 ||
+ device->type() == I8048 ||
+ device->type() == I8648 ||
+ device->type() == I8748 ||
+ device->type() == I8039 ||
+ device->type() == I8049 ||
+ device->type() == I8749 ||
+ device->type() == I8040 ||
+ device->type() == I8050 ||
+ device->type() == I8041 ||
+ device->type() == I8741 ||
+ device->type() == I8042 ||
+ device->type() == I8242 ||
+ device->type() == I8742 ||
+ device->type() == MB8884 ||
+ device->type() == N7751 ||
+ device->type() == M58715);
+ return (mcs48_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+
+/*-------------------------------------------------
+ opcode_fetch - fetch an opcode byte
+-------------------------------------------------*/
+
+INLINE UINT8 opcode_fetch(mcs48_state *cpustate)
+{
+ return cpustate->direct->read_decrypted_byte(cpustate->pc++);
+}
+
+
+/*-------------------------------------------------
+ argument_fetch - fetch an opcode argument
+ byte
+-------------------------------------------------*/
+
+INLINE UINT8 argument_fetch(mcs48_state *cpustate)
+{
+ return cpustate->direct->read_raw_byte(cpustate->pc++);
+}
+
+
+/*-------------------------------------------------
+ update_regptr - update the regptr member to
+ point to the appropriate register bank
+-------------------------------------------------*/
+
+INLINE void update_regptr(mcs48_state *cpustate)
+{
+ cpustate->regptr = (UINT8 *)cpustate->data->get_write_ptr((cpustate->psw & B_FLAG) ? 24 : 0);
+}
+
+
+/*-------------------------------------------------
+ push_pc_psw - push the cpustate->pc and cpustate->psw values onto
+ the stack
+-------------------------------------------------*/
+
+INLINE void push_pc_psw(mcs48_state *cpustate)
+{
+ UINT8 sp = cpustate->psw & 0x07;
+ ram_w(8 + 2*sp, cpustate->pc);
+ ram_w(9 + 2*sp, ((cpustate->pc >> 8) & 0x0f) | (cpustate->psw & 0xf0));
+ cpustate->psw = (cpustate->psw & 0xf8) | ((sp + 1) & 0x07);
+}
+
+
+/*-------------------------------------------------
+ pull_pc_psw - pull the PC and PSW values from
+ the stack
+-------------------------------------------------*/
+
+INLINE void pull_pc_psw(mcs48_state *cpustate)
+{
+ UINT8 sp = (cpustate->psw - 1) & 0x07;
+ cpustate->pc = ram_r(8 + 2*sp);
+ cpustate->pc |= ram_r(9 + 2*sp) << 8;
+ cpustate->psw = ((cpustate->pc >> 8) & 0xf0) | 0x08 | sp;
+ cpustate->pc &= 0xfff;
+ update_regptr(cpustate);
+}
+
+
+/*-------------------------------------------------
+ pull_pc - pull the PC value from the stack,
+ leaving the upper part of PSW intact
+-------------------------------------------------*/
+
+INLINE void pull_pc(mcs48_state *cpustate)
+{
+ UINT8 sp = (cpustate->psw - 1) & 0x07;
+ cpustate->pc = ram_r(8 + 2*sp);
+ cpustate->pc |= ram_r(9 + 2*sp) << 8;
+ cpustate->pc &= 0xfff;
+ cpustate->psw = (cpustate->psw & 0xf0) | 0x08 | sp;
+}
+
+
+/*-------------------------------------------------
+ execute_add - perform the logic of an ADD
+ instruction
+-------------------------------------------------*/
+
+INLINE void execute_add(mcs48_state *cpustate, UINT8 dat)
+{
+ UINT16 temp = cpustate->a + dat;
+ UINT16 temp4 = (cpustate->a & 0x0f) + (dat & 0x0f);
+
+ cpustate->psw &= ~(C_FLAG | A_FLAG);
+ cpustate->psw |= (temp4 << 2) & A_FLAG;
+ cpustate->psw |= (temp >> 1) & C_FLAG;
+ cpustate->a = temp;
+}
+
+
+/*-------------------------------------------------
+ execute_addc - perform the logic of an ADDC
+ instruction
+-------------------------------------------------*/
+
+INLINE void execute_addc(mcs48_state *cpustate, UINT8 dat)
+{
+ UINT8 carryin = (cpustate->psw & C_FLAG) >> 7;
+ UINT16 temp = cpustate->a + dat + carryin;
+ UINT16 temp4 = (cpustate->a & 0x0f) + (dat & 0x0f) + carryin;
+
+ cpustate->psw &= ~(C_FLAG | A_FLAG);
+ cpustate->psw |= (temp4 << 2) & A_FLAG;
+ cpustate->psw |= (temp >> 1) & C_FLAG;
+ cpustate->a = temp;
+}
+
+
+/*-------------------------------------------------
+ execute_jmp - perform the logic of a JMP
+ instruction
+-------------------------------------------------*/
+
+INLINE void execute_jmp(mcs48_state *cpustate, UINT16 address)
+{
+ UINT16 a11 = (cpustate->irq_in_progress) ? 0 : cpustate->a11;
+ cpustate->pc = address | a11;
+}
+
+
+/*-------------------------------------------------
+ execute_call - perform the logic of a CALL
+ instruction
+-------------------------------------------------*/
+
+INLINE void execute_call(mcs48_state *cpustate, UINT16 address)
+{
+ push_pc_psw(cpustate);
+ execute_jmp(cpustate, address);
+}
+
+
+/*-------------------------------------------------
+ execute_jcc - perform the logic of a
+ conditional jump instruction
+-------------------------------------------------*/
+
+INLINE void execute_jcc(mcs48_state *cpustate, UINT8 result)
+{
+ UINT8 offset = argument_fetch(cpustate);
+ if (result != 0)
+ cpustate->pc = ((cpustate->pc - 1) & 0xf00) | offset;
+}
+
+
+/*-------------------------------------------------
+ p2_mask - return the mask of bits that the
+ code can directly affect
+-------------------------------------------------*/
+
+INLINE UINT8 p2_mask(mcs48_state *cpustate)
+{
+ UINT8 result = 0xff;
+ if ((cpustate->feature_mask & UPI41_FEATURE) == 0)
+ return result;
+ if (cpustate->flags_enabled)
+ result &= ~(P2_OBF | P2_NIBF);
+ if (cpustate->dma_enabled)
+ result &= ~(P2_DRQ | P2_NDACK);
+ return result;
+}
+
+
+/*-------------------------------------------------
+ expander_operation - perform an operation via
+ the 8243 expander chip
+-------------------------------------------------*/
+
+INLINE void expander_operation(mcs48_state *cpustate, UINT8 operation, UINT8 port)
+{
+ /* put opcode/data on low 4 bits of P2 */
+ port_w(2, cpustate->p2 = (cpustate->p2 & 0xf0) | (operation << 2) | (port & 3));
+
+ /* generate high-to-low transition on PROG line */
+ prog_w(0);
+
+ /* put data on low 4 bits of P2 */
+ if (operation != 0)
+ port_w(2, cpustate->p2 = (cpustate->p2 & 0xf0) | (cpustate->a & 0x0f));
+ else
+ cpustate->a = port_r(2) | 0x0f;
+
+ /* generate low-to-high transition on PROG line */
+ prog_w(1);
+}
+
+
+
+/***************************************************************************
+ OPCODE HANDLERS
+***************************************************************************/
+
+#define OPHANDLER(_name) static int _name(mcs48_state *cpustate)
+
+#define SPLIT_OPHANDLER(_name, _mcs48name, _upi41name) \
+OPHANDLER(_name) { return (!(cpustate->feature_mask & UPI41_FEATURE)) ? _mcs48name(cpustate) : _upi41name(cpustate); }
+
+
+OPHANDLER( illegal )
+{
+ logerror("MCS-48 PC:%04X - Illegal opcode = %02x\n", cpustate->pc - 1, program_r(cpustate->pc - 1));
+ return 1;
+}
+
+OPHANDLER( add_a_r0 ) { execute_add(cpustate, cpustate->R0); return 1; }
+OPHANDLER( add_a_r1 ) { execute_add(cpustate, cpustate->R1); return 1; }
+OPHANDLER( add_a_r2 ) { execute_add(cpustate, cpustate->R2); return 1; }
+OPHANDLER( add_a_r3 ) { execute_add(cpustate, cpustate->R3); return 1; }
+OPHANDLER( add_a_r4 ) { execute_add(cpustate, cpustate->R4); return 1; }
+OPHANDLER( add_a_r5 ) { execute_add(cpustate, cpustate->R5); return 1; }
+OPHANDLER( add_a_r6 ) { execute_add(cpustate, cpustate->R6); return 1; }
+OPHANDLER( add_a_r7 ) { execute_add(cpustate, cpustate->R7); return 1; }
+OPHANDLER( add_a_xr0 ) { execute_add(cpustate, ram_r(cpustate->R0)); return 1; }
+OPHANDLER( add_a_xr1 ) { execute_add(cpustate, ram_r(cpustate->R1)); return 1; }
+OPHANDLER( add_a_n ) { execute_add(cpustate, argument_fetch(cpustate)); return 2; }
+
+OPHANDLER( adc_a_r0 ) { execute_addc(cpustate, cpustate->R0); return 1; }
+OPHANDLER( adc_a_r1 ) { execute_addc(cpustate, cpustate->R1); return 1; }
+OPHANDLER( adc_a_r2 ) { execute_addc(cpustate, cpustate->R2); return 1; }
+OPHANDLER( adc_a_r3 ) { execute_addc(cpustate, cpustate->R3); return 1; }
+OPHANDLER( adc_a_r4 ) { execute_addc(cpustate, cpustate->R4); return 1; }
+OPHANDLER( adc_a_r5 ) { execute_addc(cpustate, cpustate->R5); return 1; }
+OPHANDLER( adc_a_r6 ) { execute_addc(cpustate, cpustate->R6); return 1; }
+OPHANDLER( adc_a_r7 ) { execute_addc(cpustate, cpustate->R7); return 1; }
+OPHANDLER( adc_a_xr0 ) { execute_addc(cpustate, ram_r(cpustate->R0)); return 1; }
+OPHANDLER( adc_a_xr1 ) { execute_addc(cpustate, ram_r(cpustate->R1)); return 1; }
+OPHANDLER( adc_a_n ) { execute_addc(cpustate, argument_fetch(cpustate)); return 2; }
+
+OPHANDLER( anl_a_r0 ) { cpustate->a &= cpustate->R0; return 1; }
+OPHANDLER( anl_a_r1 ) { cpustate->a &= cpustate->R1; return 1; }
+OPHANDLER( anl_a_r2 ) { cpustate->a &= cpustate->R2; return 1; }
+OPHANDLER( anl_a_r3 ) { cpustate->a &= cpustate->R3; return 1; }
+OPHANDLER( anl_a_r4 ) { cpustate->a &= cpustate->R4; return 1; }
+OPHANDLER( anl_a_r5 ) { cpustate->a &= cpustate->R5; return 1; }
+OPHANDLER( anl_a_r6 ) { cpustate->a &= cpustate->R6; return 1; }
+OPHANDLER( anl_a_r7 ) { cpustate->a &= cpustate->R7; return 1; }
+OPHANDLER( anl_a_xr0 ) { cpustate->a &= ram_r(cpustate->R0); return 1; }
+OPHANDLER( anl_a_xr1 ) { cpustate->a &= ram_r(cpustate->R1); return 1; }
+OPHANDLER( anl_a_n ) { cpustate->a &= argument_fetch(cpustate); return 2; }
+
+OPHANDLER( anl_bus_n ) { bus_w(bus_r() & argument_fetch(cpustate)); return 2; }
+OPHANDLER( anl_p1_n ) { port_w(1, cpustate->p1 &= argument_fetch(cpustate)); return 2; }
+OPHANDLER( anl_p2_n ) { port_w(2, cpustate->p2 &= argument_fetch(cpustate) | ~p2_mask(cpustate)); return 2; }
+OPHANDLER( anld_p4_a ) { expander_operation(cpustate, MCS48_EXPANDER_OP_AND, 4); return 2; }
+OPHANDLER( anld_p5_a ) { expander_operation(cpustate, MCS48_EXPANDER_OP_AND, 5); return 2; }
+OPHANDLER( anld_p6_a ) { expander_operation(cpustate, MCS48_EXPANDER_OP_AND, 6); return 2; }
+OPHANDLER( anld_p7_a ) { expander_operation(cpustate, MCS48_EXPANDER_OP_AND, 7); return 2; }
+
+OPHANDLER( call_0 ) { execute_call(cpustate, argument_fetch(cpustate) | 0x000); return 2; }
+OPHANDLER( call_1 ) { execute_call(cpustate, argument_fetch(cpustate) | 0x100); return 2; }
+OPHANDLER( call_2 ) { execute_call(cpustate, argument_fetch(cpustate) | 0x200); return 2; }
+OPHANDLER( call_3 ) { execute_call(cpustate, argument_fetch(cpustate) | 0x300); return 2; }
+OPHANDLER( call_4 ) { execute_call(cpustate, argument_fetch(cpustate) | 0x400); return 2; }
+OPHANDLER( call_5 ) { execute_call(cpustate, argument_fetch(cpustate) | 0x500); return 2; }
+OPHANDLER( call_6 ) { execute_call(cpustate, argument_fetch(cpustate) | 0x600); return 2; }
+OPHANDLER( call_7 ) { execute_call(cpustate, argument_fetch(cpustate) | 0x700); return 2; }
+
+OPHANDLER( clr_a ) { cpustate->a = 0; return 1; }
+OPHANDLER( clr_c ) { cpustate->psw &= ~C_FLAG; return 1; }
+OPHANDLER( clr_f0 ) { cpustate->psw &= ~F_FLAG; cpustate->sts &= ~STS_F0; return 1; }
+OPHANDLER( clr_f1 ) { cpustate->sts &= ~STS_F1; return 1; }
+
+OPHANDLER( cpl_a ) { cpustate->a ^= 0xff; return 1; }
+OPHANDLER( cpl_c ) { cpustate->psw ^= C_FLAG; return 1; }
+OPHANDLER( cpl_f0 ) { cpustate->psw ^= F_FLAG; cpustate->sts ^= STS_F0; return 1; }
+OPHANDLER( cpl_f1 ) { cpustate->sts ^= STS_F1; return 1; }
+
+OPHANDLER( da_a )
+{
+ if ((cpustate->a & 0x0f) > 0x09 || (cpustate->psw & A_FLAG))
+ {
+ cpustate->a += 0x06;
+ if ((cpustate->a & 0xf0) == 0x00)
+ cpustate->psw |= C_FLAG;
+ }
+ if ((cpustate->a & 0xf0) > 0x90 || (cpustate->psw & C_FLAG))
+ {
+ cpustate->a += 0x60;
+ cpustate->psw |= C_FLAG;
+ }
+ else
+ cpustate->psw &= ~C_FLAG;
+ return 1;
+}
+
+OPHANDLER( dec_a ) { cpustate->a--; return 1; }
+OPHANDLER( dec_r0 ) { cpustate->R0--; return 1; }
+OPHANDLER( dec_r1 ) { cpustate->R1--; return 1; }
+OPHANDLER( dec_r2 ) { cpustate->R2--; return 1; }
+OPHANDLER( dec_r3 ) { cpustate->R3--; return 1; }
+OPHANDLER( dec_r4 ) { cpustate->R4--; return 1; }
+OPHANDLER( dec_r5 ) { cpustate->R5--; return 1; }
+OPHANDLER( dec_r6 ) { cpustate->R6--; return 1; }
+OPHANDLER( dec_r7 ) { cpustate->R7--; return 1; }
+
+OPHANDLER( dis_i ) { cpustate->xirq_enabled = FALSE; return 1; }
+OPHANDLER( dis_tcnti ) { cpustate->tirq_enabled = FALSE; cpustate->timer_overflow = FALSE; return 1; }
+
+OPHANDLER( djnz_r0 ) { execute_jcc(cpustate, --cpustate->R0 != 0); return 2; }
+OPHANDLER( djnz_r1 ) { execute_jcc(cpustate, --cpustate->R1 != 0); return 2; }
+OPHANDLER( djnz_r2 ) { execute_jcc(cpustate, --cpustate->R2 != 0); return 2; }
+OPHANDLER( djnz_r3 ) { execute_jcc(cpustate, --cpustate->R3 != 0); return 2; }
+OPHANDLER( djnz_r4 ) { execute_jcc(cpustate, --cpustate->R4 != 0); return 2; }
+OPHANDLER( djnz_r5 ) { execute_jcc(cpustate, --cpustate->R5 != 0); return 2; }
+OPHANDLER( djnz_r6 ) { execute_jcc(cpustate, --cpustate->R6 != 0); return 2; }
+OPHANDLER( djnz_r7 ) { execute_jcc(cpustate, --cpustate->R7 != 0); return 2; }
+
+OPHANDLER( en_i ) { cpustate->xirq_enabled = TRUE; return 1 + check_irqs(cpustate); }
+OPHANDLER( en_tcnti ) { cpustate->tirq_enabled = TRUE; return 1 + check_irqs(cpustate); }
+OPHANDLER( en_dma ) { cpustate->dma_enabled = TRUE; port_w(2, cpustate->p2); return 1; }
+OPHANDLER( en_flags ) { cpustate->flags_enabled = TRUE; port_w(2, cpustate->p2); return 1; }
+OPHANDLER( ent0_clk )
+{
+ logerror("MCS-48 PC:%04X - Unimplemented opcode = %02x\n", cpustate->pc - 1, program_r(cpustate->pc - 1));
+ return 1;
+}
+
+OPHANDLER( in_a_p1 ) { cpustate->a = port_r(1) & cpustate->p1; return 2; }
+OPHANDLER( in_a_p2 ) { cpustate->a = port_r(2) & cpustate->p2; return 2; }
+OPHANDLER( ins_a_bus ) { cpustate->a = bus_r(); return 2; }
+OPHANDLER( in_a_dbb )
+{
+ /* acknowledge the IBF IRQ and clear the bit in STS */
+ if ((cpustate->sts & STS_IBF) != 0 && cpustate->irq_callback != NULL)
+ (*cpustate->irq_callback)(cpustate->device, UPI41_INPUT_IBF);
+ cpustate->sts &= ~STS_IBF;
+
+ /* if P2 flags are enabled, update the state of P2 */
+ if (cpustate->flags_enabled && (cpustate->p2 & P2_NIBF) == 0)
+ port_w(2, cpustate->p2 |= P2_NIBF);
+ cpustate->a = cpustate->dbbi;
+ return 2;
+}
+
+OPHANDLER( inc_a ) { cpustate->a++; return 1; }
+OPHANDLER( inc_r0 ) { cpustate->R0++; return 1; }
+OPHANDLER( inc_r1 ) { cpustate->R1++; return 1; }
+OPHANDLER( inc_r2 ) { cpustate->R2++; return 1; }
+OPHANDLER( inc_r3 ) { cpustate->R3++; return 1; }
+OPHANDLER( inc_r4 ) { cpustate->R4++; return 1; }
+OPHANDLER( inc_r5 ) { cpustate->R5++; return 1; }
+OPHANDLER( inc_r6 ) { cpustate->R6++; return 1; }
+OPHANDLER( inc_r7 ) { cpustate->R7++; return 1; }
+OPHANDLER( inc_xr0 ) { ram_w(cpustate->R0, ram_r(cpustate->R0) + 1); return 1; }
+OPHANDLER( inc_xr1 ) { ram_w(cpustate->R1, ram_r(cpustate->R1) + 1); return 1; }
+
+OPHANDLER( jb_0 ) { execute_jcc(cpustate, (cpustate->a & 0x01) != 0); return 2; }
+OPHANDLER( jb_1 ) { execute_jcc(cpustate, (cpustate->a & 0x02) != 0); return 2; }
+OPHANDLER( jb_2 ) { execute_jcc(cpustate, (cpustate->a & 0x04) != 0); return 2; }
+OPHANDLER( jb_3 ) { execute_jcc(cpustate, (cpustate->a & 0x08) != 0); return 2; }
+OPHANDLER( jb_4 ) { execute_jcc(cpustate, (cpustate->a & 0x10) != 0); return 2; }
+OPHANDLER( jb_5 ) { execute_jcc(cpustate, (cpustate->a & 0x20) != 0); return 2; }
+OPHANDLER( jb_6 ) { execute_jcc(cpustate, (cpustate->a & 0x40) != 0); return 2; }
+OPHANDLER( jb_7 ) { execute_jcc(cpustate, (cpustate->a & 0x80) != 0); return 2; }
+OPHANDLER( jc ) { execute_jcc(cpustate, (cpustate->psw & C_FLAG) != 0); return 2; }
+OPHANDLER( jf0 ) { execute_jcc(cpustate, (cpustate->psw & F_FLAG) != 0); return 2; }
+OPHANDLER( jf1 ) { execute_jcc(cpustate, (cpustate->sts & STS_F1) != 0); return 2; }
+OPHANDLER( jnc ) { execute_jcc(cpustate, (cpustate->psw & C_FLAG) == 0); return 2; }
+OPHANDLER( jni ) { execute_jcc(cpustate, cpustate->irq_state != 0); return 2; }
+OPHANDLER( jnibf ) { execute_jcc(cpustate, (cpustate->sts & STS_IBF) == 0); return 2; }
+OPHANDLER( jnt_0 ) { execute_jcc(cpustate, test_r(0) == 0); return 2; }
+OPHANDLER( jnt_1 ) { execute_jcc(cpustate, test_r(1) == 0); return 2; }
+OPHANDLER( jnz ) { execute_jcc(cpustate, cpustate->a != 0); return 2; }
+OPHANDLER( jobf ) { execute_jcc(cpustate, (cpustate->sts & STS_OBF) != 0); return 2; }
+OPHANDLER( jtf ) { execute_jcc(cpustate, cpustate->timer_flag); cpustate->timer_flag = FALSE; return 2; }
+OPHANDLER( jt_0 ) { execute_jcc(cpustate, test_r(0) != 0); return 2; }
+OPHANDLER( jt_1 ) { execute_jcc(cpustate, test_r(1) != 0); return 2; }
+OPHANDLER( jz ) { execute_jcc(cpustate, cpustate->a == 0); return 2; }
+
+OPHANDLER( jmp_0 ) { execute_jmp(cpustate, argument_fetch(cpustate) | 0x000); return 2; }
+OPHANDLER( jmp_1 ) { execute_jmp(cpustate, argument_fetch(cpustate) | 0x100); return 2; }
+OPHANDLER( jmp_2 ) { execute_jmp(cpustate, argument_fetch(cpustate) | 0x200); return 2; }
+OPHANDLER( jmp_3 ) { execute_jmp(cpustate, argument_fetch(cpustate) | 0x300); return 2; }
+OPHANDLER( jmp_4 ) { execute_jmp(cpustate, argument_fetch(cpustate) | 0x400); return 2; }
+OPHANDLER( jmp_5 ) { execute_jmp(cpustate, argument_fetch(cpustate) | 0x500); return 2; }
+OPHANDLER( jmp_6 ) { execute_jmp(cpustate, argument_fetch(cpustate) | 0x600); return 2; }
+OPHANDLER( jmp_7 ) { execute_jmp(cpustate, argument_fetch(cpustate) | 0x700); return 2; }
+OPHANDLER( jmpp_xa ) { cpustate->pc &= 0xf00; cpustate->pc |= program_r(cpustate->pc | cpustate->a); return 2; }
+
+OPHANDLER( mov_a_n ) { cpustate->a = argument_fetch(cpustate); return 2; }
+OPHANDLER( mov_a_psw ) { cpustate->a = cpustate->psw; return 1; }
+OPHANDLER( mov_a_r0 ) { cpustate->a = cpustate->R0; return 1; }
+OPHANDLER( mov_a_r1 ) { cpustate->a = cpustate->R1; return 1; }
+OPHANDLER( mov_a_r2 ) { cpustate->a = cpustate->R2; return 1; }
+OPHANDLER( mov_a_r3 ) { cpustate->a = cpustate->R3; return 1; }
+OPHANDLER( mov_a_r4 ) { cpustate->a = cpustate->R4; return 1; }
+OPHANDLER( mov_a_r5 ) { cpustate->a = cpustate->R5; return 1; }
+OPHANDLER( mov_a_r6 ) { cpustate->a = cpustate->R6; return 1; }
+OPHANDLER( mov_a_r7 ) { cpustate->a = cpustate->R7; return 1; }
+OPHANDLER( mov_a_xr0 ) { cpustate->a = ram_r(cpustate->R0); return 1; }
+OPHANDLER( mov_a_xr1 ) { cpustate->a = ram_r(cpustate->R1); return 1; }
+OPHANDLER( mov_a_t ) { cpustate->a = cpustate->timer; return 1; }
+
+OPHANDLER( mov_psw_a ) { cpustate->psw = cpustate->a; update_regptr(cpustate); return 1; }
+OPHANDLER( mov_sts_a ) { cpustate->sts = (cpustate->sts & 0x0f) | (cpustate->a & 0xf0); return 1; }
+OPHANDLER( mov_r0_a ) { cpustate->R0 = cpustate->a; return 1; }
+OPHANDLER( mov_r1_a ) { cpustate->R1 = cpustate->a; return 1; }
+OPHANDLER( mov_r2_a ) { cpustate->R2 = cpustate->a; return 1; }
+OPHANDLER( mov_r3_a ) { cpustate->R3 = cpustate->a; return 1; }
+OPHANDLER( mov_r4_a ) { cpustate->R4 = cpustate->a; return 1; }
+OPHANDLER( mov_r5_a ) { cpustate->R5 = cpustate->a; return 1; }
+OPHANDLER( mov_r6_a ) { cpustate->R6 = cpustate->a; return 1; }
+OPHANDLER( mov_r7_a ) { cpustate->R7 = cpustate->a; return 1; }
+OPHANDLER( mov_r0_n ) { cpustate->R0 = argument_fetch(cpustate); return 2; }
+OPHANDLER( mov_r1_n ) { cpustate->R1 = argument_fetch(cpustate); return 2; }
+OPHANDLER( mov_r2_n ) { cpustate->R2 = argument_fetch(cpustate); return 2; }
+OPHANDLER( mov_r3_n ) { cpustate->R3 = argument_fetch(cpustate); return 2; }
+OPHANDLER( mov_r4_n ) { cpustate->R4 = argument_fetch(cpustate); return 2; }
+OPHANDLER( mov_r5_n ) { cpustate->R5 = argument_fetch(cpustate); return 2; }
+OPHANDLER( mov_r6_n ) { cpustate->R6 = argument_fetch(cpustate); return 2; }
+OPHANDLER( mov_r7_n ) { cpustate->R7 = argument_fetch(cpustate); return 2; }
+OPHANDLER( mov_t_a ) { cpustate->timer = cpustate->a; return 1; }
+OPHANDLER( mov_xr0_a ) { ram_w(cpustate->R0, cpustate->a); return 1; }
+OPHANDLER( mov_xr1_a ) { ram_w(cpustate->R1, cpustate->a); return 1; }
+OPHANDLER( mov_xr0_n ) { ram_w(cpustate->R0, argument_fetch(cpustate)); return 2; }
+OPHANDLER( mov_xr1_n ) { ram_w(cpustate->R1, argument_fetch(cpustate)); return 2; }
+
+OPHANDLER( movd_a_p4 ) { expander_operation(cpustate, MCS48_EXPANDER_OP_READ, 4); return 2; }
+OPHANDLER( movd_a_p5 ) { expander_operation(cpustate, MCS48_EXPANDER_OP_READ, 5); return 2; }
+OPHANDLER( movd_a_p6 ) { expander_operation(cpustate, MCS48_EXPANDER_OP_READ, 6); return 2; }
+OPHANDLER( movd_a_p7 ) { expander_operation(cpustate, MCS48_EXPANDER_OP_READ, 7); return 2; }
+OPHANDLER( movd_p4_a ) { expander_operation(cpustate, MCS48_EXPANDER_OP_WRITE, 4); return 2; }
+OPHANDLER( movd_p5_a ) { expander_operation(cpustate, MCS48_EXPANDER_OP_WRITE, 5); return 2; }
+OPHANDLER( movd_p6_a ) { expander_operation(cpustate, MCS48_EXPANDER_OP_WRITE, 6); return 2; }
+OPHANDLER( movd_p7_a ) { expander_operation(cpustate, MCS48_EXPANDER_OP_WRITE, 7); return 2; }
+
+OPHANDLER( movp_a_xa ) { cpustate->a = program_r((cpustate->pc & 0xf00) | cpustate->a); return 2; }
+OPHANDLER( movp3_a_xa ) { cpustate->a = program_r(0x300 | cpustate->a); return 2; }
+
+OPHANDLER( movx_a_xr0 ) { cpustate->a = ext_r(cpustate->R0); return 2; }
+OPHANDLER( movx_a_xr1 ) { cpustate->a = ext_r(cpustate->R1); return 2; }
+OPHANDLER( movx_xr0_a ) { ext_w(cpustate->R0, cpustate->a); return 2; }
+OPHANDLER( movx_xr1_a ) { ext_w(cpustate->R1, cpustate->a); return 2; }
+
+OPHANDLER( nop ) { return 1; }
+
+OPHANDLER( orl_a_r0 ) { cpustate->a |= cpustate->R0; return 1; }
+OPHANDLER( orl_a_r1 ) { cpustate->a |= cpustate->R1; return 1; }
+OPHANDLER( orl_a_r2 ) { cpustate->a |= cpustate->R2; return 1; }
+OPHANDLER( orl_a_r3 ) { cpustate->a |= cpustate->R3; return 1; }
+OPHANDLER( orl_a_r4 ) { cpustate->a |= cpustate->R4; return 1; }
+OPHANDLER( orl_a_r5 ) { cpustate->a |= cpustate->R5; return 1; }
+OPHANDLER( orl_a_r6 ) { cpustate->a |= cpustate->R6; return 1; }
+OPHANDLER( orl_a_r7 ) { cpustate->a |= cpustate->R7; return 1; }
+OPHANDLER( orl_a_xr0 ) { cpustate->a |= ram_r(cpustate->R0); return 1; }
+OPHANDLER( orl_a_xr1 ) { cpustate->a |= ram_r(cpustate->R1); return 1; }
+OPHANDLER( orl_a_n ) { cpustate->a |= argument_fetch(cpustate); return 2; }
+
+OPHANDLER( orl_bus_n ) { bus_w(bus_r() | argument_fetch(cpustate)); return 2; }
+OPHANDLER( orl_p1_n ) { port_w(1, cpustate->p1 |= argument_fetch(cpustate)); return 2; }
+OPHANDLER( orl_p2_n ) { port_w(2, cpustate->p2 |= argument_fetch(cpustate) & p2_mask(cpustate)); return 2; }
+OPHANDLER( orld_p4_a ) { expander_operation(cpustate, MCS48_EXPANDER_OP_OR, 4); return 2; }
+OPHANDLER( orld_p5_a ) { expander_operation(cpustate, MCS48_EXPANDER_OP_OR, 5); return 2; }
+OPHANDLER( orld_p6_a ) { expander_operation(cpustate, MCS48_EXPANDER_OP_OR, 6); return 2; }
+OPHANDLER( orld_p7_a ) { expander_operation(cpustate, MCS48_EXPANDER_OP_OR, 7); return 2; }
+
+OPHANDLER( outl_bus_a ) { bus_w(cpustate->a); return 2; }
+OPHANDLER( outl_p1_a ) { port_w(1, cpustate->p1 = cpustate->a); return 2; }
+OPHANDLER( outl_p2_a ) { UINT8 mask = p2_mask(cpustate); port_w(2, cpustate->p2 = (cpustate->p2 & ~mask) | (cpustate->a & mask)); return 2; }
+OPHANDLER( out_dbb_a )
+{
+ /* copy to the DBBO and update the bit in STS */
+ cpustate->dbbo = cpustate->a;
+ cpustate->sts |= STS_OBF;
+
+ /* if P2 flags are enabled, update the state of P2 */
+ if (cpustate->flags_enabled && (cpustate->p2 & P2_OBF) == 0)
+ port_w(2, cpustate->p2 |= P2_OBF);
+ return 2;
+}
+
+
+OPHANDLER( ret ) { pull_pc(cpustate); return 2; }
+OPHANDLER( retr )
+{
+ pull_pc_psw(cpustate);
+
+ /* implicitly clear the IRQ in progress flip flop and re-check interrupts */
+ cpustate->irq_in_progress = FALSE;
+ return 2 + check_irqs(cpustate);
+}
+
+OPHANDLER( rl_a ) { cpustate->a = (cpustate->a << 1) | (cpustate->a >> 7); return 1; }
+OPHANDLER( rlc_a ) { UINT8 newc = cpustate->a & C_FLAG; cpustate->a = (cpustate->a << 1) | (cpustate->psw >> 7); cpustate->psw = (cpustate->psw & ~C_FLAG) | newc; return 1; }
+
+OPHANDLER( rr_a ) { cpustate->a = (cpustate->a >> 1) | (cpustate->a << 7); return 1; }
+OPHANDLER( rrc_a ) { UINT8 newc = (cpustate->a << 7) & C_FLAG; cpustate->a = (cpustate->a >> 1) | (cpustate->psw & C_FLAG); cpustate->psw = (cpustate->psw & ~C_FLAG) | newc; return 1; }
+
+OPHANDLER( sel_mb0 ) { cpustate->a11 = 0x000; return 1; }
+OPHANDLER( sel_mb1 ) { cpustate->a11 = 0x800; return 1; }
+
+OPHANDLER( sel_rb0 ) { cpustate->psw &= ~B_FLAG; update_regptr(cpustate); return 1; }
+OPHANDLER( sel_rb1 ) { cpustate->psw |= B_FLAG; update_regptr(cpustate); return 1; }
+
+OPHANDLER( stop_tcnt ) { cpustate->timecount_enabled = 0; return 1; }
+
+OPHANDLER( strt_cnt ) { cpustate->timecount_enabled = COUNTER_ENABLED; cpustate->t1_history = test_r(1); return 1; }
+OPHANDLER( strt_t ) { cpustate->timecount_enabled = TIMER_ENABLED; cpustate->prescaler = 0; return 1; }
+
+OPHANDLER( swap_a ) { cpustate->a = (cpustate->a << 4) | (cpustate->a >> 4); return 1; }
+
+OPHANDLER( xch_a_r0 ) { UINT8 tmp = cpustate->a; cpustate->a = cpustate->R0; cpustate->R0 = tmp; return 1; }
+OPHANDLER( xch_a_r1 ) { UINT8 tmp = cpustate->a; cpustate->a = cpustate->R1; cpustate->R1 = tmp; return 1; }
+OPHANDLER( xch_a_r2 ) { UINT8 tmp = cpustate->a; cpustate->a = cpustate->R2; cpustate->R2 = tmp; return 1; }
+OPHANDLER( xch_a_r3 ) { UINT8 tmp = cpustate->a; cpustate->a = cpustate->R3; cpustate->R3 = tmp; return 1; }
+OPHANDLER( xch_a_r4 ) { UINT8 tmp = cpustate->a; cpustate->a = cpustate->R4; cpustate->R4 = tmp; return 1; }
+OPHANDLER( xch_a_r5 ) { UINT8 tmp = cpustate->a; cpustate->a = cpustate->R5; cpustate->R5 = tmp; return 1; }
+OPHANDLER( xch_a_r6 ) { UINT8 tmp = cpustate->a; cpustate->a = cpustate->R6; cpustate->R6 = tmp; return 1; }
+OPHANDLER( xch_a_r7 ) { UINT8 tmp = cpustate->a; cpustate->a = cpustate->R7; cpustate->R7 = tmp; return 1; }
+OPHANDLER( xch_a_xr0 ) { UINT8 tmp = cpustate->a; cpustate->a = ram_r(cpustate->R0); ram_w(cpustate->R0, tmp); return 1; }
+OPHANDLER( xch_a_xr1 ) { UINT8 tmp = cpustate->a; cpustate->a = ram_r(cpustate->R1); ram_w(cpustate->R1, tmp); return 1; }
+
+OPHANDLER( xchd_a_xr0 ) { UINT8 oldram = ram_r(cpustate->R0); ram_w(cpustate->R0, (oldram & 0xf0) | (cpustate->a & 0x0f)); cpustate->a = (cpustate->a & 0xf0) | (oldram & 0x0f); return 1; }
+OPHANDLER( xchd_a_xr1 ) { UINT8 oldram = ram_r(cpustate->R1); ram_w(cpustate->R1, (oldram & 0xf0) | (cpustate->a & 0x0f)); cpustate->a = (cpustate->a & 0xf0) | (oldram & 0x0f); return 1; }
+
+OPHANDLER( xrl_a_r0 ) { cpustate->a ^= cpustate->R0; return 1; }
+OPHANDLER( xrl_a_r1 ) { cpustate->a ^= cpustate->R1; return 1; }
+OPHANDLER( xrl_a_r2 ) { cpustate->a ^= cpustate->R2; return 1; }
+OPHANDLER( xrl_a_r3 ) { cpustate->a ^= cpustate->R3; return 1; }
+OPHANDLER( xrl_a_r4 ) { cpustate->a ^= cpustate->R4; return 1; }
+OPHANDLER( xrl_a_r5 ) { cpustate->a ^= cpustate->R5; return 1; }
+OPHANDLER( xrl_a_r6 ) { cpustate->a ^= cpustate->R6; return 1; }
+OPHANDLER( xrl_a_r7 ) { cpustate->a ^= cpustate->R7; return 1; }
+OPHANDLER( xrl_a_xr0 ) { cpustate->a ^= ram_r(cpustate->R0); return 1; }
+OPHANDLER( xrl_a_xr1 ) { cpustate->a ^= ram_r(cpustate->R1); return 1; }
+OPHANDLER( xrl_a_n ) { cpustate->a ^= argument_fetch(cpustate); return 2; }
+
+SPLIT_OPHANDLER( split_02, outl_bus_a, out_dbb_a )
+SPLIT_OPHANDLER( split_08, ins_a_bus, illegal )
+SPLIT_OPHANDLER( split_22, illegal, in_a_dbb )
+SPLIT_OPHANDLER( split_75, ent0_clk, illegal )
+SPLIT_OPHANDLER( split_80, movx_a_xr0, illegal )
+SPLIT_OPHANDLER( split_81, movx_a_xr1, illegal )
+SPLIT_OPHANDLER( split_86, jni, jobf )
+SPLIT_OPHANDLER( split_88, orl_bus_n, illegal )
+SPLIT_OPHANDLER( split_90, movx_xr0_a, mov_sts_a )
+SPLIT_OPHANDLER( split_91, movx_xr1_a, illegal )
+SPLIT_OPHANDLER( split_98, anl_bus_n, illegal )
+SPLIT_OPHANDLER( split_d6, illegal, jnibf )
+SPLIT_OPHANDLER( split_e5, sel_mb0, en_dma )
+SPLIT_OPHANDLER( split_f5, sel_mb1, en_flags )
+
+
+
+/***************************************************************************
+ OPCODE TABLES
+***************************************************************************/
+
+static const mcs48_ophandler opcode_table[256]=
+{
+ nop, illegal, split_02, add_a_n, jmp_0, en_i, illegal, dec_a, /* 00 */
+ split_08, in_a_p1, in_a_p2, illegal, movd_a_p4, movd_a_p5, movd_a_p6, movd_a_p7,
+ inc_xr0, inc_xr1, jb_0, adc_a_n, call_0, dis_i, jtf, inc_a, /* 10 */
+ inc_r0, inc_r1, inc_r2, inc_r3, inc_r4, inc_r5, inc_r6, inc_r7,
+ xch_a_xr0, xch_a_xr1, split_22, mov_a_n, jmp_1, en_tcnti, jnt_0, clr_a, /* 20 */
+ xch_a_r0, xch_a_r1, xch_a_r2, xch_a_r3, xch_a_r4, xch_a_r5, xch_a_r6, xch_a_r7,
+ xchd_a_xr0, xchd_a_xr1, jb_1, illegal, call_1, dis_tcnti, jt_0, cpl_a, /* 30 */
+ illegal, outl_p1_a, outl_p2_a, illegal, movd_p4_a, movd_p5_a, movd_p6_a, movd_p7_a,
+ orl_a_xr0, orl_a_xr1, mov_a_t, orl_a_n, jmp_2, strt_cnt, jnt_1, swap_a, /* 40 */
+ orl_a_r0, orl_a_r1, orl_a_r2, orl_a_r3, orl_a_r4, orl_a_r5, orl_a_r6, orl_a_r7,
+ anl_a_xr0, anl_a_xr1, jb_2, anl_a_n, call_2, strt_t, jt_1, da_a, /* 50 */
+ anl_a_r0, anl_a_r1, anl_a_r2, anl_a_r3, anl_a_r4, anl_a_r5, anl_a_r6, anl_a_r7,
+ add_a_xr0, add_a_xr1, mov_t_a, illegal, jmp_3, stop_tcnt, illegal, rrc_a, /* 60 */
+ add_a_r0, add_a_r1, add_a_r2, add_a_r3, add_a_r4, add_a_r5, add_a_r6, add_a_r7,
+ adc_a_xr0, adc_a_xr1, jb_3, illegal, call_3, split_75, jf1, rr_a, /* 70 */
+ adc_a_r0, adc_a_r1, adc_a_r2, adc_a_r3, adc_a_r4, adc_a_r5, adc_a_r6, adc_a_r7,
+ split_80, split_81, illegal, ret, jmp_4, clr_f0, split_86, illegal, /* 80 */
+ split_88, orl_p1_n, orl_p2_n, illegal, orld_p4_a, orld_p5_a, orld_p6_a, orld_p7_a,
+ split_90, split_91, jb_4, retr, call_4, cpl_f0, jnz, clr_c, /* 90 */
+ split_98, anl_p1_n, anl_p2_n, illegal, anld_p4_a, anld_p5_a, anld_p6_a, anld_p7_a,
+ mov_xr0_a, mov_xr1_a, illegal, movp_a_xa, jmp_5, clr_f1, illegal, cpl_c, /* A0 */
+ mov_r0_a, mov_r1_a, mov_r2_a, mov_r3_a, mov_r4_a, mov_r5_a, mov_r6_a, mov_r7_a,
+ mov_xr0_n, mov_xr1_n, jb_5, jmpp_xa, call_5, cpl_f1, jf0, illegal, /* B0 */
+ mov_r0_n, mov_r1_n, mov_r2_n, mov_r3_n, mov_r4_n, mov_r5_n, mov_r6_n, mov_r7_n,
+ illegal, illegal, illegal, illegal, jmp_6, sel_rb0, jz, mov_a_psw, /* C0 */
+ dec_r0, dec_r1, dec_r2, dec_r3, dec_r4, dec_r5, dec_r6, dec_r7,
+ xrl_a_xr0, xrl_a_xr1, jb_6, xrl_a_n, call_6, sel_rb1, split_d6, mov_psw_a, /* D0 */
+ xrl_a_r0, xrl_a_r1, xrl_a_r2, xrl_a_r3, xrl_a_r4, xrl_a_r5, xrl_a_r6, xrl_a_r7,
+ illegal, illegal, illegal, movp3_a_xa,jmp_7, split_e5, jnc, rl_a, /* E0 */
+ djnz_r0, djnz_r1, djnz_r2, djnz_r3, djnz_r4, djnz_r5, djnz_r6, djnz_r7,
+ mov_a_xr0, mov_a_xr1, jb_7, illegal, call_7, split_f5, jc, rlc_a, /* F0 */
+ mov_a_r0, mov_a_r1, mov_a_r2, mov_a_r3, mov_a_r4, mov_a_r5, mov_a_r6, mov_a_r7
+};
+
+
+
+/***************************************************************************
+ INITIALIZATION/RESET
+***************************************************************************/
+
+/*-------------------------------------------------
+ mcs48_init - generic MCS-48 initialization
+-------------------------------------------------*/
+
+static void mcs48_init(legacy_cpu_device *device, device_irq_callback irqcallback, UINT8 feature_mask, UINT16 romsize)
+{
+ mcs48_state *cpustate = get_safe_token(device);
+
+ /* External access line
+ * EA=1 : read from external rom
+ * EA=0 : read from internal rom
+ */
+
+ /* FIXME: Current implementation suboptimal */
+ cpustate->ea = (romsize ? 0 : 1);
+
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+ cpustate->int_rom_size = romsize;
+ cpustate->feature_mask = feature_mask;
+
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+ cpustate->data = device->space(AS_DATA);
+ cpustate->io = device->space(AS_IO);
+
+ /* set up the state table */
+ {
+ device_state_interface *state;
+ device->interface(state);
+ state->state_add(MCS48_PC, "PC", cpustate->pc).mask(0xfff);
+ state->state_add(STATE_GENPC, "GENPC", cpustate->pc).mask(0xfff).noshow();
+ state->state_add(STATE_GENPCBASE, "GENPCBASE", cpustate->prevpc).mask(0xfff).noshow();
+ state->state_add(STATE_GENSP, "GENSP", cpustate->psw).mask(0x7).noshow();
+ state->state_add(STATE_GENFLAGS, "GENFLAGS", cpustate->psw).noshow().formatstr("%10s");
+ state->state_add(MCS48_A, "A", cpustate->a);
+ state->state_add(MCS48_TC, "TC", cpustate->timer);
+ state->state_add(MCS48_TPRE, "TPRE", cpustate->prescaler).mask(0x1f);
+ state->state_add(MCS48_P1, "P1", cpustate->p1);
+ state->state_add(MCS48_P2, "P2", cpustate->p2);
+
+ astring tempstr;
+ for (int regnum = 0; regnum < 8; regnum++)
+ state->state_add(MCS48_R0 + regnum, tempstr.format("R%d", regnum), cpustate->rtemp).callimport().callexport();
+
+ state->state_add(MCS48_EA, "EA", cpustate->ea).mask(0x1);
+
+ if (feature_mask & UPI41_FEATURE)
+ {
+ state->state_add(MCS48_STS, "STS", cpustate->sts);
+ state->state_add(MCS48_DBBI, "DBBI", cpustate->dbbi);
+ state->state_add(MCS48_DBBO, "DBBO", cpustate->dbbo);
+ }
+
+ }
+
+ /* ensure that regptr is valid before get_info gets called */
+ update_regptr(cpustate);
+
+ device->save_item(NAME(cpustate->prevpc));
+ device->save_item(NAME(cpustate->pc));
+
+ device->save_item(NAME(cpustate->a));
+ device->save_item(NAME(cpustate->psw));
+ device->save_item(NAME(cpustate->p1));
+ device->save_item(NAME(cpustate->p2));
+ device->save_item(NAME(cpustate->ea));
+ device->save_item(NAME(cpustate->timer));
+ device->save_item(NAME(cpustate->prescaler));
+ device->save_item(NAME(cpustate->t1_history));
+ device->save_item(NAME(cpustate->sts));
+ device->save_item(NAME(cpustate->dbbi));
+ device->save_item(NAME(cpustate->dbbo));
+
+ device->save_item(NAME(cpustate->irq_state));
+ device->save_item(NAME(cpustate->irq_in_progress));
+ device->save_item(NAME(cpustate->timer_overflow));
+ device->save_item(NAME(cpustate->timer_flag));
+ device->save_item(NAME(cpustate->tirq_enabled));
+ device->save_item(NAME(cpustate->xirq_enabled));
+ device->save_item(NAME(cpustate->timecount_enabled));
+ device->save_item(NAME(cpustate->flags_enabled));
+ device->save_item(NAME(cpustate->dma_enabled));
+
+ device->save_item(NAME(cpustate->a11));
+}
+
+
+/*-------------------------------------------------
+ mcs48_norom_init - initialization for systems
+ with no internal ROM
+-------------------------------------------------*/
+
+static CPU_INIT( mcs48_norom )
+{
+ mcs48_init(device, irqcallback, MCS48_FEATURE, 0x0);
+}
+
+
+/*-------------------------------------------------
+ mcs48_1k_rom_init - initialization for systems
+ with 1k of internal ROM
+-------------------------------------------------*/
+
+static CPU_INIT( mcs48_1k_rom )
+{
+ mcs48_init(device, irqcallback, MCS48_FEATURE, 0x400);
+}
+
+
+/*-------------------------------------------------
+ mcs48_2k_rom - initialization for systems
+ with 2k of internal ROM
+-------------------------------------------------*/
+
+static CPU_INIT( mcs48_2k_rom )
+{
+ mcs48_init(device, irqcallback, MCS48_FEATURE, 0x800);
+}
+
+
+/*-------------------------------------------------
+ mcs48_4k_rom - initialization for systems
+ with 2k of internal ROM
+-------------------------------------------------*/
+
+static CPU_INIT( mcs48_4k_rom )
+{
+ mcs48_init(device, irqcallback, MCS48_FEATURE, 0x1000);
+}
+
+
+/*-------------------------------------------------
+ upi41_1k_rom_init - initialization for systems
+ with 1k of internal ROM
+-------------------------------------------------*/
+
+static CPU_INIT( upi41_1k_rom )
+{
+ mcs48_init(device, irqcallback, UPI41_FEATURE, 0x400);
+}
+
+
+/*-------------------------------------------------
+ upi41_2k_rom_init - initialization for systems
+ with 2k of internal ROM
+-------------------------------------------------*/
+
+static CPU_INIT( upi41_2k_rom )
+{
+ mcs48_init(device, irqcallback, UPI41_FEATURE, 0x800);
+}
+
+
+/*-------------------------------------------------
+ mcs48_reset - general reset routine
+-------------------------------------------------*/
+
+static CPU_RESET( mcs48 )
+{
+ mcs48_state *cpustate = get_safe_token(device);
+
+ /* confirmed from reset description */
+ cpustate->pc = 0;
+ cpustate->psw = (cpustate->psw & (C_FLAG | A_FLAG)) | 0x08;
+ cpustate->a11 = 0x000;
+ bus_w(0xff);
+ cpustate->p1 = 0xff;
+ cpustate->p2 = 0xff;
+ port_w(1, cpustate->p1);
+ port_w(2, cpustate->p2);
+ cpustate->tirq_enabled = FALSE;
+ cpustate->xirq_enabled = FALSE;
+ cpustate->timecount_enabled = 0;
+ cpustate->timer_flag = FALSE;
+ cpustate->sts = 0;
+ cpustate->flags_enabled = FALSE;
+ cpustate->dma_enabled = FALSE;
+
+ /* confirmed from interrupt logic description */
+ cpustate->irq_in_progress = FALSE;
+ cpustate->timer_overflow = FALSE;
+}
+
+
+
+/***************************************************************************
+ EXECUTION
+***************************************************************************/
+
+/*-------------------------------------------------
+ check_irqs - check for and process IRQs
+-------------------------------------------------*/
+
+static int check_irqs(mcs48_state *cpustate)
+{
+ /* if something is in progress, we do nothing */
+ if (cpustate->irq_in_progress)
+ return 0;
+
+ /* external interrupts take priority */
+ if ((cpustate->irq_state || (cpustate->sts & STS_IBF) != 0) && cpustate->xirq_enabled)
+ {
+ cpustate->irq_in_progress = TRUE;
+
+ /* transfer to location 0x03 */
+ push_pc_psw(cpustate);
+ cpustate->pc = 0x03;
+
+ /* indicate we took the external IRQ */
+ if (cpustate->irq_callback != NULL)
+ (*cpustate->irq_callback)(cpustate->device, 0);
+ return 2;
+ }
+
+ /* timer overflow interrupts follow */
+ if (cpustate->timer_overflow && cpustate->tirq_enabled)
+ {
+ cpustate->irq_in_progress = TRUE;
+
+ /* transfer to location 0x07 */
+ push_pc_psw(cpustate);
+ cpustate->pc = 0x07;
+
+ /* timer overflow flip-flop is reset once taken */
+ cpustate->timer_overflow = FALSE;
+ return 2;
+ }
+ return 0;
+}
+
+
+/*-------------------------------------------------
+ burn_cycles - burn cycles, processing timers
+ and counters
+-------------------------------------------------*/
+
+static void burn_cycles(mcs48_state *cpustate, int count)
+{
+ int timerover = FALSE;
+
+ /* if the timer is enabled, accumulate prescaler cycles */
+ if (cpustate->timecount_enabled & TIMER_ENABLED)
+ {
+ UINT8 oldtimer = cpustate->timer;
+ cpustate->prescaler += count;
+ cpustate->timer += cpustate->prescaler >> 5;
+ cpustate->prescaler &= 0x1f;
+ timerover = (oldtimer != 0 && cpustate->timer == 0);
+ }
+
+ /* if the counter is enabled, poll the T1 test input once for each cycle */
+ else if (cpustate->timecount_enabled & COUNTER_ENABLED)
+ for ( ; count > 0; count--)
+ {
+ cpustate->t1_history = (cpustate->t1_history << 1) | (test_r(1) & 1);
+ if ((cpustate->t1_history & 3) == 2)
+ timerover = (++cpustate->timer == 0);
+ }
+
+ /* if either source caused a timer overflow, set the flags and check IRQs */
+ if (timerover)
+ {
+ cpustate->timer_flag = TRUE;
+
+ /* according to the docs, if an overflow occurs with interrupts disabled, the overflow is not stored */
+ if (cpustate->tirq_enabled)
+ {
+ cpustate->timer_overflow = TRUE;
+ check_irqs(cpustate);
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ mcs48_execute - execute until we run out
+ of cycles
+-------------------------------------------------*/
+
+static CPU_EXECUTE( mcs48 )
+{
+ mcs48_state *cpustate = get_safe_token(device);
+ int curcycles;
+
+ update_regptr(cpustate);
+
+ /* external interrupts may have been set since we last checked */
+ curcycles = check_irqs(cpustate);
+ cpustate->icount -= curcycles;
+ if (cpustate->timecount_enabled != 0)
+ burn_cycles(cpustate, curcycles);
+
+ /* iterate over remaining cycles, guaranteeing at least one instruction */
+ do
+ {
+ unsigned opcode;
+
+ /* fetch next opcode */
+ cpustate->prevpc = cpustate->pc;
+ debugger_instruction_hook(device, cpustate->pc);
+ opcode = opcode_fetch(cpustate);
+
+ /* process opcode and count cycles */
+ curcycles = (*opcode_table[opcode])(cpustate);
+
+ /* burn the cycles */
+ cpustate->icount -= curcycles;
+ if (cpustate->timecount_enabled != 0)
+ burn_cycles(cpustate, curcycles);
+
+ } while (cpustate->icount > 0);
+}
+
+
+
+/***************************************************************************
+ DATA ACCESS HELPERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ upi41_master_r - master CPU data/status
+ read
+-------------------------------------------------*/
+
+UINT8 upi41_master_r(device_t *device, UINT8 a0)
+{
+ mcs48_state *cpustate = get_safe_token(device);
+
+ /* if just reading the status, return it */
+ if ((a0 & 1) != 0)
+ return cpustate->sts;
+
+ /* if the output buffer was full, it gets cleared now */
+ if (cpustate->sts & STS_OBF)
+ {
+ cpustate->sts &= ~STS_OBF;
+ if (cpustate->flags_enabled)
+ port_w(2, cpustate->p2 &= ~P2_OBF);
+ }
+ return cpustate->dbbo;
+}
+
+
+/*-------------------------------------------------
+ upi41_master_w - master CPU command/data
+ write
+-------------------------------------------------*/
+
+static TIMER_CALLBACK( master_callback )
+{
+ legacy_cpu_device *device = (legacy_cpu_device *)ptr;
+ mcs48_state *cpustate = get_safe_token(device);
+ UINT8 a0 = (param >> 8) & 1;
+ UINT8 data = param;
+
+ /* data always goes to the input buffer */
+ cpustate->dbbi = data;
+
+ /* set the appropriate flags */
+ if ((cpustate->sts & STS_IBF) == 0)
+ {
+ cpustate->sts |= STS_IBF;
+ if (cpustate->flags_enabled)
+ port_w(2, cpustate->p2 &= ~P2_NIBF);
+ }
+
+ /* set F1 accordingly */
+ if (a0 == 0)
+ cpustate->sts &= ~STS_F1;
+ else
+ cpustate->sts |= STS_F1;
+}
+
+void upi41_master_w(device_t *_device, UINT8 a0, UINT8 data)
+{
+ legacy_cpu_device *device = downcast<legacy_cpu_device *>(_device);
+ device->machine().scheduler().synchronize(FUNC(master_callback), (a0 << 8) | data, (void *)device);
+}
+
+
+
+/***************************************************************************
+ ADDRESS MAPS
+***************************************************************************/
+
+/* FIXME: the memory maps should probably support rom banking for EA */
+static ADDRESS_MAP_START(program_10bit, AS_PROGRAM, 8)
+ AM_RANGE(0x000, 0x3ff) AM_ROM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START(program_11bit, AS_PROGRAM, 8)
+ AM_RANGE(0x000, 0x7ff) AM_ROM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START(program_12bit, AS_PROGRAM, 8)
+ AM_RANGE(0x000, 0xfff) AM_ROM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START(data_6bit, AS_DATA, 8)
+ AM_RANGE(0x00, 0x3f) AM_RAM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START(data_7bit, AS_DATA, 8)
+ AM_RANGE(0x00, 0x7f) AM_RAM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START(data_8bit, AS_DATA, 8)
+ AM_RANGE(0x00, 0xff) AM_RAM
+ADDRESS_MAP_END
+
+
+
+/***************************************************************************
+ GENERAL CONTEXT ACCESS
+***************************************************************************/
+
+/*-------------------------------------------------
+ mcs48_import_state - import state from the
+ debugger into our internal format
+-------------------------------------------------*/
+
+static CPU_IMPORT_STATE( mcs48 )
+{
+ mcs48_state *cpustate = get_safe_token(device);
+
+ switch (entry.index())
+ {
+ case MCS48_R0:
+ case MCS48_R1:
+ case MCS48_R2:
+ case MCS48_R3:
+ case MCS48_R4:
+ case MCS48_R5:
+ case MCS48_R6:
+ case MCS48_R7:
+ cpustate->regptr[entry.index() - MCS48_R0] = cpustate->rtemp;
+ break;
+
+ default:
+ fatalerror("CPU_IMPORT_STATE(mcs48) called for unexpected value\n");
+ break;
+ }
+}
+
+
+/*-------------------------------------------------
+ mcs48_export_state - prepare state for
+ exporting to the debugger
+-------------------------------------------------*/
+
+static CPU_EXPORT_STATE( mcs48 )
+{
+ mcs48_state *cpustate = get_safe_token(device);
+
+ switch (entry.index())
+ {
+ case MCS48_R0:
+ case MCS48_R1:
+ case MCS48_R2:
+ case MCS48_R3:
+ case MCS48_R4:
+ case MCS48_R5:
+ case MCS48_R6:
+ case MCS48_R7:
+ cpustate->rtemp = cpustate->regptr[entry.index() - MCS48_R0];
+ break;
+
+ default:
+ fatalerror("CPU_EXPORT_STATE(mcs48) called for unexpected value\n");
+ break;
+ }
+}
+
+static CPU_EXPORT_STRING( mcs48 )
+{
+ mcs48_state *cpustate = get_safe_token(device);
+
+ switch (entry.index())
+ {
+ case CPUINFO_STR_FLAGS:
+ string.printf("%c%c %c%c%c%c%c%c%c%c",
+ cpustate->irq_state ? 'I':'.',
+ cpustate->a11 ? 'M':'.',
+ cpustate->psw & 0x80 ? 'C':'.',
+ cpustate->psw & 0x40 ? 'A':'.',
+ cpustate->psw & 0x20 ? 'F':'.',
+ cpustate->psw & 0x10 ? 'B':'.',
+ cpustate->psw & 0x08 ? '?':'.',
+ cpustate->psw & 0x04 ? '4':'.',
+ cpustate->psw & 0x02 ? '2':'.',
+ cpustate->psw & 0x01 ? '1':'.');
+ break;
+ }
+}
+
+/*-------------------------------------------------
+ mcs48_set_info - set a piece of information
+ on the CPU core
+-------------------------------------------------*/
+
+static CPU_SET_INFO( mcs48 )
+{
+ mcs48_state *cpustate = get_safe_token(device);
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + MCS48_INPUT_IRQ: cpustate->irq_state = (info->i != CLEAR_LINE); break;
+ case CPUINFO_INT_INPUT_STATE + MCS48_INPUT_EA: cpustate->ea = (info->i != CLEAR_LINE); break;
+ }
+}
+
+
+/*-------------------------------------------------
+ mcs48_get_info - retrieve a piece of
+ information from the CPU core
+-------------------------------------------------*/
+
+static CPU_GET_INFO( mcs48 )
+{
+ mcs48_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(mcs48_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 2; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = MCS48_INPUT_IRQ; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 3*5; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 2; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 3; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 12; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: /*info->i = 6 or 7 or 8;*/ break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 9; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_INPUT_STATE + MCS48_INPUT_IRQ: info->i = cpustate->irq_state ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + MCS48_INPUT_EA: info->i = cpustate->ea; break;
+
+ /* --- the following bits of info are returned as pointers to functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(mcs48); break;
+ case CPUINFO_FCT_INIT: /* set per-core */ break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(mcs48); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(mcs48); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(mcs48); break;
+ case CPUINFO_FCT_IMPORT_STATE: info->import_state = CPU_IMPORT_STATE_NAME(mcs48); break;
+ case CPUINFO_FCT_EXPORT_STATE: info->export_state = CPU_EXPORT_STATE_NAME(mcs48); break;
+ case CPUINFO_FCT_EXPORT_STRING: info->export_string = CPU_EXPORT_STRING_NAME(mcs48); break;
+
+ /* --- the following bits of info are returned as pointers --- */
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: /* set per-core */ break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: /* set per-core */ break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: /* set per-core */ break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Intel 8039"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.2"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Mirko Buffoni\nBased on the original work Copyright Dan Boris"); break;
+ }
+}
+
+
+
+/***************************************************************************
+ CPU-SPECIFIC CONTEXT ACCESS
+***************************************************************************/
+
+static void mcs48_generic_get_info(legacy_cpu_device *device, UINT32 state, cpuinfo *info, UINT8 features, int romsize, int ramsize, const char *name)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA:
+ if (ramsize == 64)
+ info->i = 6;
+ else if (ramsize == 128)
+ info->i = 7;
+ else if (ramsize == 256)
+ info->i = 8;
+ else
+ fatalerror("mcs48_generic_get_info: Invalid RAM size");
+ break;
+
+ /* --- the following bits of info are returned as pointers to functions --- */
+ case CPUINFO_FCT_INIT:
+ if (romsize == 0)
+ info->init = CPU_INIT_NAME(mcs48_norom);
+ else if (romsize == 1024)
+ info->init = (features == UPI41_FEATURE) ? CPU_INIT_NAME(upi41_1k_rom) : CPU_INIT_NAME(mcs48_1k_rom);
+ else if (romsize == 2048)
+ info->init = (features == UPI41_FEATURE) ? CPU_INIT_NAME(upi41_2k_rom) : CPU_INIT_NAME(mcs48_2k_rom);
+ else if (romsize == 4096)
+ info->init = CPU_INIT_NAME(mcs48_4k_rom);
+ else
+ fatalerror("mcs48_generic_get_info: Invalid ROM size");
+ break;
+
+ case CPUINFO_FCT_DISASSEMBLE:
+ if (features == UPI41_FEATURE)
+ info->disassemble = CPU_DISASSEMBLE_NAME(upi41);
+ else
+ info->disassemble = CPU_DISASSEMBLE_NAME(mcs48);
+ break;
+
+ /* --- the following bits of info are returned as pointers --- */
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM:
+ if (romsize == 0)
+ info->internal_map8 = NULL;
+ else if (romsize == 1024)
+ info->internal_map8 = ADDRESS_MAP_NAME(program_10bit);
+ else if (romsize == 2048)
+ info->internal_map8 = ADDRESS_MAP_NAME(program_11bit);
+ else if (romsize == 4096)
+ info->internal_map8 = ADDRESS_MAP_NAME(program_12bit);
+ else
+ fatalerror("mcs48_generic_get_info: Invalid RAM size");
+ break;
+
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA:
+ if (ramsize == 64)
+ info->internal_map8 = ADDRESS_MAP_NAME(data_6bit);
+ else if (ramsize == 128)
+ info->internal_map8 = ADDRESS_MAP_NAME(data_7bit);
+ else if (ramsize == 256)
+ info->internal_map8 = ADDRESS_MAP_NAME(data_8bit);
+ else
+ fatalerror("mcs48_generic_get_info: Invalid RAM size");
+ break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME:
+ strcpy(info->s, name);
+ break;
+
+ /* default case */
+ default:
+ CPU_GET_INFO_CALL(mcs48);
+ break;
+ }
+}
+
+
+/* Official Intel MCS-48 parts */
+CPU_GET_INFO( i8021 ) { mcs48_generic_get_info(device, state, info, MCS48_FEATURE, 1024, 64, "I8021"); }
+CPU_GET_INFO( i8022 ) { mcs48_generic_get_info(device, state, info, MCS48_FEATURE, 2048, 128, "I8022"); }
+CPU_GET_INFO( i8035 ) { mcs48_generic_get_info(device, state, info, MCS48_FEATURE, 0, 64, "I8035"); }
+CPU_GET_INFO( i8048 ) { mcs48_generic_get_info(device, state, info, MCS48_FEATURE, 1024, 64, "I8048"); }
+CPU_GET_INFO( i8648 ) { mcs48_generic_get_info(device, state, info, MCS48_FEATURE, 1024, 64, "I8648"); }
+CPU_GET_INFO( i8748 ) { mcs48_generic_get_info(device, state, info, MCS48_FEATURE, 1024, 64, "I8748"); }
+CPU_GET_INFO( i8039 ) { mcs48_generic_get_info(device, state, info, MCS48_FEATURE, 0, 128, "I8039"); }
+CPU_GET_INFO( i8049 ) { mcs48_generic_get_info(device, state, info, MCS48_FEATURE, 2048, 128, "I8049"); }
+CPU_GET_INFO( i8749 ) { mcs48_generic_get_info(device, state, info, MCS48_FEATURE, 2048, 128, "I8749"); }
+CPU_GET_INFO( i8040 ) { mcs48_generic_get_info(device, state, info, MCS48_FEATURE, 0, 256, "I8040"); }
+CPU_GET_INFO( i8050 ) { mcs48_generic_get_info(device, state, info, MCS48_FEATURE, 4096, 256, "I8050"); }
+
+
+/* Official Intel UPI-41 parts */
+CPU_GET_INFO( i8041 ) { mcs48_generic_get_info(device, state, info, UPI41_FEATURE, 1024, 128, "I8041"); }
+CPU_GET_INFO( i8741 ) { mcs48_generic_get_info(device, state, info, UPI41_FEATURE, 1024, 128, "I8741"); }
+CPU_GET_INFO( i8042 ) { mcs48_generic_get_info(device, state, info, UPI41_FEATURE, 2048, 256, "I8042"); }
+CPU_GET_INFO( i8242 ) { mcs48_generic_get_info(device, state, info, UPI41_FEATURE, 2048, 256, "I8242"); }
+CPU_GET_INFO( i8742 ) { mcs48_generic_get_info(device, state, info, UPI41_FEATURE, 2048, 256, "I8742"); }
+
+
+/* Clones */
+CPU_GET_INFO( mb8884 ) { mcs48_generic_get_info(device, state, info, MCS48_FEATURE, 0, 64, "MB8884"); }
+CPU_GET_INFO( n7751 ) { mcs48_generic_get_info(device, state, info, MCS48_FEATURE, 1024, 64, "N7751"); }
+CPU_GET_INFO( m58715 ) { mcs48_generic_get_info(device, state, info, MCS48_FEATURE, 2048, 128, "M58715"); }
+
+/* Official Intel MCS-48 parts */
+DEFINE_LEGACY_CPU_DEVICE(I8021, i8021); /* 1k internal ROM, 64 bytes internal RAM */
+DEFINE_LEGACY_CPU_DEVICE(I8022, i8022); /* 2k internal ROM, 128 bytes internal RAM */
+DEFINE_LEGACY_CPU_DEVICE(I8035, i8035); /* external ROM, 64 bytes internal RAM */
+DEFINE_LEGACY_CPU_DEVICE(I8048, i8048); /* 1k internal ROM, 64 bytes internal RAM */
+DEFINE_LEGACY_CPU_DEVICE(I8648, i8648); /* 1k internal OTP ROM, 64 bytes internal RAM */
+DEFINE_LEGACY_CPU_DEVICE(I8748, i8748); /* 1k internal EEPROM, 64 bytes internal RAM */
+DEFINE_LEGACY_CPU_DEVICE(I8039, i8039); /* external ROM, 128 bytes internal RAM */
+DEFINE_LEGACY_CPU_DEVICE(I8049, i8049); /* 2k internal ROM, 128 bytes internal RAM */
+DEFINE_LEGACY_CPU_DEVICE(I8749, i8749); /* 2k internal EEPROM, 128 bytes internal RAM */
+DEFINE_LEGACY_CPU_DEVICE(I8040, i8040); /* external ROM, 256 bytes internal RAM */
+DEFINE_LEGACY_CPU_DEVICE(I8050, i8050); /* 4k internal ROM, 256 bytes internal RAM */
+
+/* Official Intel UPI-41 parts */
+DEFINE_LEGACY_CPU_DEVICE(I8041, i8041); /* 1k internal ROM, 128 bytes internal RAM */
+DEFINE_LEGACY_CPU_DEVICE(I8741, i8741); /* 1k internal EEPROM, 128 bytes internal RAM */
+DEFINE_LEGACY_CPU_DEVICE(I8042, i8042); /* 2k internal ROM, 256 bytes internal RAM */
+DEFINE_LEGACY_CPU_DEVICE(I8242, i8242); /* 2k internal ROM, 256 bytes internal RAM */
+DEFINE_LEGACY_CPU_DEVICE(I8742, i8742); /* 2k internal EEPROM, 256 bytes internal RAM */
+
+/* Clones */
+DEFINE_LEGACY_CPU_DEVICE(MB8884, mb8884); /* 8035 clone */
+DEFINE_LEGACY_CPU_DEVICE(N7751, n7751); /* 8048 clone */
+DEFINE_LEGACY_CPU_DEVICE(M58715, m58715); /* 8049 clone */
diff --git a/trunk/src/emu/cpu/mcs48/mcs48.h b/trunk/src/emu/cpu/mcs48/mcs48.h
new file mode 100644
index 00000000000..a31366e997b
--- /dev/null
+++ b/trunk/src/emu/cpu/mcs48/mcs48.h
@@ -0,0 +1,134 @@
+/***************************************************************************
+
+ mcs48.c
+
+ Intel MCS-48/UPI-41 Portable Emulator
+
+ Copyright Mirko Buffoni
+ Based on the original work Copyright Dan Boris, an 8048 emulator
+ You are not allowed to distribute this software commercially
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __MCS48_H__
+#define __MCS48_H__
+
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+/* register access indexes */
+enum
+{
+ MCS48_PC,
+ MCS48_PSW,
+ MCS48_A,
+ MCS48_TC,
+ MCS48_TPRE,
+ MCS48_P1,
+ MCS48_P2,
+ MCS48_R0,
+ MCS48_R1,
+ MCS48_R2,
+ MCS48_R3,
+ MCS48_R4,
+ MCS48_R5,
+ MCS48_R6,
+ MCS48_R7,
+ MCS48_EA,
+ MCS48_STS, /* UPI-41 systems only */
+ MCS48_DBBO, /* UPI-41 systems only */
+ MCS48_DBBI, /* UPI-41 systems only */
+
+ MCS48_GENPC = STATE_GENPC,
+ MCS48_GENSP = STATE_GENSP,
+ MCS48_GENPCBASE = STATE_GENPCBASE
+};
+
+
+/* I/O port access indexes */
+enum
+{
+ MCS48_INPUT_IRQ = 0,
+ UPI41_INPUT_IBF = 0,
+ MCS48_INPUT_EA
+};
+
+
+/* special I/O space ports */
+enum
+{
+ MCS48_PORT_P0 = 0x100, /* Not used */
+ MCS48_PORT_P1 = 0x101,
+ MCS48_PORT_P2 = 0x102,
+ MCS48_PORT_T0 = 0x110,
+ MCS48_PORT_T1 = 0x111,
+ MCS48_PORT_BUS = 0x120,
+ MCS48_PORT_PROG = 0x121 /* PROG line to 8243 expander */
+};
+
+
+/* 8243 expander operations */
+enum
+{
+ MCS48_EXPANDER_OP_READ = 0,
+ MCS48_EXPANDER_OP_WRITE = 1,
+ MCS48_EXPANDER_OP_OR = 2,
+ MCS48_EXPANDER_OP_AND = 3
+};
+
+
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+#define MCS48_ALE_CLOCK(_clock) \
+ attotime::from_hz(_clock/(3*5))
+
+/* Official Intel MCS-48 parts */
+DECLARE_LEGACY_CPU_DEVICE(I8021, i8021); /* 1k internal ROM, 64 bytes internal RAM */
+DECLARE_LEGACY_CPU_DEVICE(I8022, i8022); /* 2k internal ROM, 128 bytes internal RAM */
+DECLARE_LEGACY_CPU_DEVICE(I8035, i8035); /* external ROM, 64 bytes internal RAM */
+DECLARE_LEGACY_CPU_DEVICE(I8048, i8048); /* 1k internal ROM, 64 bytes internal RAM */
+DECLARE_LEGACY_CPU_DEVICE(I8648, i8648); /* 1k internal OTP ROM, 64 bytes internal RAM */
+DECLARE_LEGACY_CPU_DEVICE(I8748, i8748); /* 1k internal EEPROM, 64 bytes internal RAM */
+DECLARE_LEGACY_CPU_DEVICE(I8039, i8039); /* external ROM, 128 bytes internal RAM */
+DECLARE_LEGACY_CPU_DEVICE(I8049, i8049); /* 2k internal ROM, 128 bytes internal RAM */
+DECLARE_LEGACY_CPU_DEVICE(I8749, i8749); /* 2k internal EEPROM, 128 bytes internal RAM */
+DECLARE_LEGACY_CPU_DEVICE(I8040, i8040); /* external ROM, 256 bytes internal RAM */
+DECLARE_LEGACY_CPU_DEVICE(I8050, i8050); /* 4k internal ROM, 256 bytes internal RAM */
+
+/* Official Intel UPI-41 parts */
+DECLARE_LEGACY_CPU_DEVICE(I8041, i8041); /* 1k internal ROM, 128 bytes internal RAM */
+DECLARE_LEGACY_CPU_DEVICE(I8741, i8741); /* 1k internal EEPROM, 128 bytes internal RAM */
+DECLARE_LEGACY_CPU_DEVICE(I8042, i8042); /* 2k internal ROM, 256 bytes internal RAM */
+DECLARE_LEGACY_CPU_DEVICE(I8242, i8242); /* 2k internal ROM, 256 bytes internal RAM */
+DECLARE_LEGACY_CPU_DEVICE(I8742, i8742); /* 2k internal EEPROM, 256 bytes internal RAM */
+
+/* Clones */
+DECLARE_LEGACY_CPU_DEVICE(MB8884, mb8884); /* 8035 clone */
+DECLARE_LEGACY_CPU_DEVICE(N7751, n7751); /* 8048 clone */
+DECLARE_LEGACY_CPU_DEVICE(M58715, m58715); /* 8049 clone */
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+/* functions for talking to the input/output buffers on the UPI41-class chips */
+UINT8 upi41_master_r(device_t *device, UINT8 a0);
+void upi41_master_w(device_t *device, UINT8 a0, UINT8 data);
+
+
+/* disassemblers */
+CPU_DISASSEMBLE( mcs48 );
+CPU_DISASSEMBLE( upi41 );
+
+
+#endif /* __MCS48_H__ */
diff --git a/trunk/src/emu/cpu/mcs48/mcs48dsm.c b/trunk/src/emu/cpu/mcs48/mcs48dsm.c
new file mode 100644
index 00000000000..d527d190ff8
--- /dev/null
+++ b/trunk/src/emu/cpu/mcs48/mcs48dsm.c
@@ -0,0 +1,310 @@
+/***************************************************************************
+
+ mcs48dsm.c
+
+ Simple MCS-48/UPI-41 disassembler.
+ Written by Aaron Giles
+
+***************************************************************************/
+
+#include "emu.h"
+
+
+static UINT32 common_dasm(device_t *device, char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, int upi41)
+{
+ const UINT8 *startram = opram;
+ UINT32 flags = 0;
+
+ opram++;
+ switch (*oprom++)
+ {
+ case 0x00: sprintf(buffer, "nop"); break;
+ case 0x02: if (!upi41)
+ sprintf(buffer, "out bus,a");
+ else
+ sprintf(buffer, "out dbb,a"); break;
+ case 0x03: sprintf(buffer, "add a,#$%02X", *opram++); break;
+ case 0x04: sprintf(buffer, "jmp $0%02X", *opram++); break;
+ case 0x05: sprintf(buffer, "en i"); break;
+ case 0x07: sprintf(buffer, "dec a"); break;
+ case 0x08: if (!upi41)
+ sprintf(buffer, "in a,bus");
+ else
+ sprintf(buffer, "illegal"); break;
+ case 0x09: sprintf(buffer, "in a,p1"); break;
+ case 0x0a: sprintf(buffer, "in a,p2"); break;
+ case 0x0c: sprintf(buffer, "movd a,p4"); break;
+ case 0x0d: sprintf(buffer, "movd a,p5"); break;
+ case 0x0e: sprintf(buffer, "movd a,p6"); break;
+ case 0x0f: sprintf(buffer, "movd a,p7"); break;
+ case 0x10: sprintf(buffer, "inc @r0"); break;
+ case 0x11: sprintf(buffer, "inc @r1"); break;
+ case 0x12: sprintf(buffer, "jb0 $%03X", (pc & 0xf00) | *opram++); break;
+ case 0x13: sprintf(buffer, "addc a,#$%02X", *opram++); break;
+ case 0x14: sprintf(buffer, "call $0%02X", *opram++); flags = DASMFLAG_STEP_OVER; break;
+ case 0x15: sprintf(buffer, "dis i"); break;
+ case 0x16: sprintf(buffer, "jtf $%03X", (pc & 0xf00) | *opram++); break;
+ case 0x17: sprintf(buffer, "inc a"); break;
+ case 0x18: sprintf(buffer, "inc r0"); break;
+ case 0x19: sprintf(buffer, "inc r1"); break;
+ case 0x1a: sprintf(buffer, "inc r2"); break;
+ case 0x1b: sprintf(buffer, "inc r3"); break;
+ case 0x1c: sprintf(buffer, "inc r4"); break;
+ case 0x1d: sprintf(buffer, "inc r5"); break;
+ case 0x1e: sprintf(buffer, "inc r6"); break;
+ case 0x1f: sprintf(buffer, "inc r7"); break;
+ case 0x20: sprintf(buffer, "xch a,@r0"); break;
+ case 0x21: sprintf(buffer, "xch a,@r1"); break;
+ case 0x22: if (!upi41)
+ sprintf(buffer, "illegal");
+ else
+ sprintf(buffer, "in a,dbb"); break;
+ case 0x23: sprintf(buffer, "mov a,#$%02X", *opram++); break;
+ case 0x24: sprintf(buffer, "jmp $1%02X", *opram++); break;
+ case 0x25: sprintf(buffer, "en tcnti"); break;
+ case 0x26: sprintf(buffer, "jnt0 $%03X", (pc & 0xf00) | *opram++); break;
+ case 0x27: sprintf(buffer, "clr a"); break;
+ case 0x28: sprintf(buffer, "xch a,r0"); break;
+ case 0x29: sprintf(buffer, "xch a,r1"); break;
+ case 0x2a: sprintf(buffer, "xch a,r2"); break;
+ case 0x2b: sprintf(buffer, "xch a,r3"); break;
+ case 0x2c: sprintf(buffer, "xch a,r4"); break;
+ case 0x2d: sprintf(buffer, "xch a,r5"); break;
+ case 0x2e: sprintf(buffer, "xch a,r6"); break;
+ case 0x2f: sprintf(buffer, "xch a,r7"); break;
+ case 0x30: sprintf(buffer, "xchd a,@r0"); break;
+ case 0x31: sprintf(buffer, "xchd a,@r1"); break;
+ case 0x32: sprintf(buffer, "jb1 $%03X", (pc & 0xf00) | *opram++); break;
+ case 0x34: sprintf(buffer, "call $1%02X", *opram++); flags = DASMFLAG_STEP_OVER; break;
+ case 0x35: sprintf(buffer, "dis tcnti"); break;
+ case 0x36: sprintf(buffer, "jt0 $%03X", (pc & 0xf00) | *opram++); break;
+ case 0x37: sprintf(buffer, "cpl a"); break;
+ case 0x39: sprintf(buffer, "outl p1,a"); break;
+ case 0x3a: sprintf(buffer, "outl p2,a"); break;
+ case 0x3c: sprintf(buffer, "movd p4,a"); break;
+ case 0x3d: sprintf(buffer, "movd p5,a"); break;
+ case 0x3e: sprintf(buffer, "movd p6,a"); break;
+ case 0x3f: sprintf(buffer, "movd p7,a"); break;
+ case 0x40: sprintf(buffer, "orl a,@r0"); break;
+ case 0x41: sprintf(buffer, "orl a,@r1"); break;
+ case 0x42: sprintf(buffer, "mov a,t"); break;
+ case 0x43: sprintf(buffer, "orl a,#$%02X", *opram++); break;
+ case 0x44: sprintf(buffer, "jmp $2%02X", *opram++); break;
+ case 0x45: sprintf(buffer, "strt cnt"); break;
+ case 0x46: sprintf(buffer, "jnt1 $%03X", (pc & 0xf00) | *opram++); break;
+ case 0x47: sprintf(buffer, "swap a"); break;
+ case 0x48: sprintf(buffer, "orl a,r0"); break;
+ case 0x49: sprintf(buffer, "orl a,r1"); break;
+ case 0x4a: sprintf(buffer, "orl a,r2"); break;
+ case 0x4b: sprintf(buffer, "orl a,r3"); break;
+ case 0x4c: sprintf(buffer, "orl a,r4"); break;
+ case 0x4d: sprintf(buffer, "orl a,r5"); break;
+ case 0x4e: sprintf(buffer, "orl a,r6"); break;
+ case 0x4f: sprintf(buffer, "orl a,r7"); break;
+ case 0x50: sprintf(buffer, "anl a,@r0"); break;
+ case 0x51: sprintf(buffer, "anl a,@r1"); break;
+ case 0x52: sprintf(buffer, "jb2 $%03X", (pc & 0xf00) | *opram++); break;
+ case 0x53: sprintf(buffer, "anl a,#$%02X", *opram++); break;
+ case 0x54: sprintf(buffer, "call $2%02X", *opram++); flags = DASMFLAG_STEP_OVER; break;
+ case 0x55: sprintf(buffer, "strt t"); break;
+ case 0x56: sprintf(buffer, "jt1 $%03X", (pc & 0xf00) | *opram++); break;
+ case 0x57: sprintf(buffer, "da a"); break;
+ case 0x58: sprintf(buffer, "anl a,r0"); break;
+ case 0x59: sprintf(buffer, "anl a,r1"); break;
+ case 0x5a: sprintf(buffer, "anl a,r2"); break;
+ case 0x5b: sprintf(buffer, "anl a,r3"); break;
+ case 0x5c: sprintf(buffer, "anl a,r4"); break;
+ case 0x5d: sprintf(buffer, "anl a,r5"); break;
+ case 0x5e: sprintf(buffer, "anl a,r6"); break;
+ case 0x5f: sprintf(buffer, "anl a,r7"); break;
+ case 0x60: sprintf(buffer, "add a,@r0"); break;
+ case 0x61: sprintf(buffer, "add a,@r1"); break;
+ case 0x62: sprintf(buffer, "mov t,a"); break;
+ case 0x64: sprintf(buffer, "jmp $3%02X", *opram++); break;
+ case 0x65: sprintf(buffer, "stop tcnt"); break;
+ case 0x67: sprintf(buffer, "rrc a"); break;
+ case 0x68: sprintf(buffer, "add a,r0"); break;
+ case 0x69: sprintf(buffer, "add a,r1"); break;
+ case 0x6a: sprintf(buffer, "add a,r2"); break;
+ case 0x6b: sprintf(buffer, "add a,r3"); break;
+ case 0x6c: sprintf(buffer, "add a,r4"); break;
+ case 0x6d: sprintf(buffer, "add a,r5"); break;
+ case 0x6e: sprintf(buffer, "add a,r6"); break;
+ case 0x6f: sprintf(buffer, "add a,r7"); break;
+ case 0x70: sprintf(buffer, "addc a,@r0"); break;
+ case 0x71: sprintf(buffer, "addc a,@r1"); break;
+ case 0x72: sprintf(buffer, "jb3 $%03X", (pc & 0xf00) | *opram++); break;
+ case 0x74: sprintf(buffer, "call $3%02X", *opram++); flags = DASMFLAG_STEP_OVER; break;
+ case 0x75: if (!upi41)
+ sprintf(buffer, "ent0 clk");
+ else
+ sprintf(buffer, "illegal"); break;
+ case 0x76: sprintf(buffer, "jf1 $%03X", (pc & 0xf00) | *opram++); break;
+ case 0x77: sprintf(buffer, "rr a"); break;
+ case 0x78: sprintf(buffer, "addc a,r0"); break;
+ case 0x79: sprintf(buffer, "addc a,r1"); break;
+ case 0x7a: sprintf(buffer, "addc a,r2"); break;
+ case 0x7b: sprintf(buffer, "addc a,r3"); break;
+ case 0x7c: sprintf(buffer, "addc a,r4"); break;
+ case 0x7d: sprintf(buffer, "addc a,r5"); break;
+ case 0x7e: sprintf(buffer, "addc a,r6"); break;
+ case 0x7f: sprintf(buffer, "addc a,r7"); break;
+ case 0x80: if (!upi41)
+ sprintf(buffer, "movx a,@r0");
+ else
+ sprintf(buffer, "illegal"); break;
+ case 0x81: if (!upi41)
+ sprintf(buffer, "movx a,@r1");
+ else
+ sprintf(buffer, "illegal"); break;
+ case 0x83: sprintf(buffer, "ret"); flags = DASMFLAG_STEP_OUT; break;
+ case 0x84: sprintf(buffer, "jmp $4%02X", *opram++); break;
+ case 0x85: sprintf(buffer, "clr f0"); break;
+ case 0x86: if (!upi41)
+ sprintf(buffer, "jni $%03X", (pc & 0xf00) | *opram++);
+ else
+ sprintf(buffer, "jobf $%03X", (pc & 0xf00) | *opram++); break;
+ case 0x88: if (!upi41)
+ sprintf(buffer, "orl bus,#$%02X", *opram++);
+ else
+ sprintf(buffer, "illegal"); break;
+ case 0x89: sprintf(buffer, "orl p1,#$%02X", *opram++); break;
+ case 0x8a: sprintf(buffer, "orl p2,#$%02X", *opram++); break;
+ case 0x8c: sprintf(buffer, "orld p4,a"); break;
+ case 0x8d: sprintf(buffer, "orld p5,a"); break;
+ case 0x8e: sprintf(buffer, "orld p6,a"); break;
+ case 0x8f: sprintf(buffer, "orld p7,a"); break;
+ case 0x90: if (!upi41)
+ sprintf(buffer, "movx @r0,a");
+ else
+ sprintf(buffer, "mov sts,a"); break;
+ case 0x91: if (!upi41)
+ sprintf(buffer, "movx @r1,a");
+ else
+ sprintf(buffer, "illegal"); break;
+ case 0x92: sprintf(buffer, "jb4 $%03X", (pc & 0xf00) | *opram++); break;
+ case 0x93: sprintf(buffer, "retr"); flags = DASMFLAG_STEP_OUT; break;
+ case 0x94: sprintf(buffer, "call $4%02X", *opram++); flags = DASMFLAG_STEP_OVER; break;
+ case 0x95: sprintf(buffer, "cpl f0"); break;
+ case 0x96: sprintf(buffer, "jnz $%03X", (pc & 0xf00) | *opram++); break;
+ case 0x97: sprintf(buffer, "clr c"); break;
+ case 0x98: if (!upi41)
+ sprintf(buffer, "anl bus,#$%02X", *opram++);
+ else
+ sprintf(buffer, "illegal"); break;
+ case 0x99: sprintf(buffer, "anl p1,#$%02X", *opram++); break;
+ case 0x9a: sprintf(buffer, "anl p2,#$%02X", *opram++); break;
+ case 0x9c: sprintf(buffer, "anld p4,a"); break;
+ case 0x9d: sprintf(buffer, "anld p5,a"); break;
+ case 0x9e: sprintf(buffer, "anld p6,a"); break;
+ case 0x9f: sprintf(buffer, "anld p7,a"); break;
+ case 0xa0: sprintf(buffer, "mov @r0,a"); break;
+ case 0xa1: sprintf(buffer, "mov @r1,a"); break;
+ case 0xa3: sprintf(buffer, "movp a,@a"); break;
+ case 0xa4: sprintf(buffer, "jmp $5%02X", *opram++); break;
+ case 0xa5: sprintf(buffer, "clr f1"); break;
+ case 0xa7: sprintf(buffer, "cpl c"); break;
+ case 0xa8: sprintf(buffer, "mov r0,a"); break;
+ case 0xa9: sprintf(buffer, "mov r1,a"); break;
+ case 0xaa: sprintf(buffer, "mov r2,a"); break;
+ case 0xab: sprintf(buffer, "mov r3,a"); break;
+ case 0xac: sprintf(buffer, "mov r4,a"); break;
+ case 0xad: sprintf(buffer, "mov r5,a"); break;
+ case 0xae: sprintf(buffer, "mov r6,a"); break;
+ case 0xaf: sprintf(buffer, "mov r7,a"); break;
+ case 0xb0: sprintf(buffer, "mov @r0,#$%02X", *opram++); break;
+ case 0xb1: sprintf(buffer, "mov @r1,#$%02X", *opram++); break;
+ case 0xb2: sprintf(buffer, "jb5 $%03X", (pc & 0xf00) | *opram++); break;
+ case 0xb3: sprintf(buffer, "jmpp @a"); break;
+ case 0xb4: sprintf(buffer, "call $5%02X", *opram++); flags = DASMFLAG_STEP_OVER; break;
+ case 0xb5: sprintf(buffer, "cpl f1"); break;
+ case 0xb6: sprintf(buffer, "jf0 $%03X", (pc & 0xf00) | *opram++); break;
+ case 0xb8: sprintf(buffer, "mov r0,#$%02X", *opram++); break;
+ case 0xb9: sprintf(buffer, "mov r1,#$%02X", *opram++); break;
+ case 0xba: sprintf(buffer, "mov r2,#$%02X", *opram++); break;
+ case 0xbb: sprintf(buffer, "mov r3,#$%02X", *opram++); break;
+ case 0xbc: sprintf(buffer, "mov r4,#$%02X", *opram++); break;
+ case 0xbd: sprintf(buffer, "mov r5,#$%02X", *opram++); break;
+ case 0xbe: sprintf(buffer, "mov r6,#$%02X", *opram++); break;
+ case 0xbf: sprintf(buffer, "mov r7,#$%02X", *opram++); break;
+ case 0xc4: sprintf(buffer, "jmp $6%02X", *opram++); break;
+ case 0xc5: sprintf(buffer, "sel rb0"); break;
+ case 0xc6: sprintf(buffer, "jz $%03X", (pc & 0xf00) | *opram++); break;
+ case 0xc7: sprintf(buffer, "mov a,psw"); break;
+ case 0xc8: sprintf(buffer, "dec r0"); break;
+ case 0xc9: sprintf(buffer, "dec r1"); break;
+ case 0xca: sprintf(buffer, "dec r2"); break;
+ case 0xcb: sprintf(buffer, "dec r3"); break;
+ case 0xcc: sprintf(buffer, "dec r4"); break;
+ case 0xcd: sprintf(buffer, "dec r5"); break;
+ case 0xce: sprintf(buffer, "dec r6"); break;
+ case 0xcf: sprintf(buffer, "dec r7"); break;
+ case 0xd0: sprintf(buffer, "xrl a,@r0"); break;
+ case 0xd1: sprintf(buffer, "xrl a,@r1"); break;
+ case 0xd2: sprintf(buffer, "jb6 $%03X", (pc & 0xf00) | *opram++); break;
+ case 0xd3: sprintf(buffer, "xrl a,#$%02X", *opram++); break;
+ case 0xd4: sprintf(buffer, "call $6%02X", *opram++); flags = DASMFLAG_STEP_OVER; break;
+ case 0xd5: sprintf(buffer, "sel rb1"); break;
+ case 0xd6: if (!upi41)
+ sprintf(buffer, "illegal");
+ else
+ sprintf(buffer, "jnibf $%03X", (pc & 0xf00) | *opram++); break;
+ case 0xd7: sprintf(buffer, "mov psw,a"); break;
+ case 0xd8: sprintf(buffer, "xrl a,r0"); break;
+ case 0xd9: sprintf(buffer, "xrl a,r1"); break;
+ case 0xda: sprintf(buffer, "xrl a,r2"); break;
+ case 0xdb: sprintf(buffer, "xrl a,r3"); break;
+ case 0xdc: sprintf(buffer, "xrl a,r4"); break;
+ case 0xdd: sprintf(buffer, "xrl a,r5"); break;
+ case 0xde: sprintf(buffer, "xrl a,r6"); break;
+ case 0xdf: sprintf(buffer, "xrl a,r7"); break;
+ case 0xe3: sprintf(buffer, "movp3 a,@a"); break;
+ case 0xe4: sprintf(buffer, "jmp $7%02X", *opram++); break;
+ case 0xe5: if (!upi41)
+ sprintf(buffer, "sel mb0");
+ else
+ sprintf(buffer, "en dma"); break;
+ case 0xe6: sprintf(buffer, "jnc $%03X", (pc & 0xf00) | *opram++); break;
+ case 0xe7: sprintf(buffer, "rl a"); break;
+ case 0xe8: sprintf(buffer, "djnz r0,$%03X", (pc & 0xf00) | *opram++); flags = DASMFLAG_STEP_OVER; break;
+ case 0xe9: sprintf(buffer, "djnz r1,$%03X", (pc & 0xf00) | *opram++); flags = DASMFLAG_STEP_OVER; break;
+ case 0xea: sprintf(buffer, "djnz r2,$%03X", (pc & 0xf00) | *opram++); flags = DASMFLAG_STEP_OVER; break;
+ case 0xeb: sprintf(buffer, "djnz r3,$%03X", (pc & 0xf00) | *opram++); flags = DASMFLAG_STEP_OVER; break;
+ case 0xec: sprintf(buffer, "djnz r4,$%03X", (pc & 0xf00) | *opram++); flags = DASMFLAG_STEP_OVER; break;
+ case 0xed: sprintf(buffer, "djnz r5,$%03X", (pc & 0xf00) | *opram++); flags = DASMFLAG_STEP_OVER; break;
+ case 0xee: sprintf(buffer, "djnz r6,$%03X", (pc & 0xf00) | *opram++); flags = DASMFLAG_STEP_OVER; break;
+ case 0xef: sprintf(buffer, "djnz r7,$%03X", (pc & 0xf00) | *opram++); flags = DASMFLAG_STEP_OVER; break;
+ case 0xf0: sprintf(buffer, "mov a,@r0"); break;
+ case 0xf1: sprintf(buffer, "mov a,@r1"); break;
+ case 0xf2: sprintf(buffer, "jb7 $%03X", (pc & 0xf00) | *opram++); break;
+ case 0xf4: sprintf(buffer, "call $7%02X", *opram++); flags = DASMFLAG_STEP_OVER; break;
+ case 0xf5: if (!upi41)
+ sprintf(buffer, "sel mb1");
+ else
+ sprintf(buffer, "en flags"); break;
+ case 0xf6: sprintf(buffer, "jc $%03X", (pc & 0xf00) | *opram++); break;
+ case 0xf7: sprintf(buffer, "rlc a"); break;
+ case 0xf8: sprintf(buffer, "mov a,r0"); break;
+ case 0xf9: sprintf(buffer, "mov a,r1"); break;
+ case 0xfa: sprintf(buffer, "mov a,r2"); break;
+ case 0xfb: sprintf(buffer, "mov a,r3"); break;
+ case 0xfc: sprintf(buffer, "mov a,r4"); break;
+ case 0xfd: sprintf(buffer, "mov a,r5"); break;
+ case 0xfe: sprintf(buffer, "mov a,r6"); break;
+ case 0xff: sprintf(buffer, "mov a,r7"); break;
+ }
+
+ return (opram - startram) | flags | DASMFLAG_SUPPORTED;
+}
+
+
+CPU_DISASSEMBLE( mcs48 )
+{
+ return common_dasm(device, buffer, pc, oprom, opram, FALSE);
+}
+
+
+CPU_DISASSEMBLE( upi41 )
+{
+ return common_dasm(device, buffer, pc, oprom, opram, TRUE);
+}
diff --git a/trunk/src/emu/cpu/mcs51/mcs51.c b/trunk/src/emu/cpu/mcs51/mcs51.c
new file mode 100644
index 00000000000..b2db9af668e
--- /dev/null
+++ b/trunk/src/emu/cpu/mcs51/mcs51.c
@@ -0,0 +1,2767 @@
+/*****************************************************************************
+ *
+ * i8051.c
+ * Portable MCS-51 Family Emulator
+ *
+ * Chips in the family:
+ * 8051 Product Line (8031,8051,8751)
+ * 8052 Product Line (8032,8052,8752)
+ * 8054 Product Line (8054)
+ * 8058 Product Line (8058)
+ *
+ * Copyright Steve Ellenoff, all rights reserved.
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * sellenoff@hotmail.com
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ * This work is based on:
+ * #1) 'Intel(tm) MC51 Microcontroller Family Users Manual' and
+ * #2) 8051 simulator by Travis Marlatte
+ * #3) Portable UPI-41/8041/8741/8042/8742 emulator V0.1 by Juergen Buchmueller (MAME CORE)
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * DS5002FP emulator by Manuel Abadia
+ *
+ * October 2008, couriersud: Merged back in mcs51
+ *
+ * What has been added?
+ * - Extra SFRs
+ * - Bytewide Bus Support
+ * - Memory Partition and Memory Range
+ * - Bootstrap Configuration
+ * - Power Fail Interrupt
+ * - Timed Access
+ * - Stop Mode
+ * - Idle Mode
+ *
+ * What is not implemented?
+ * - Peripherals and Reprogrammable Peripheral Controller
+ * - CRC-16
+ * - Watchdog timer
+ *
+ * The main features of the DS5002FP are:
+ * - 100% code-compatible with 8051
+ * - Directly addresses 64kB program/64kB data memory
+ * - Nonvolatile memory control circuitry
+ * - 10-year data retention in the absence of power
+ * - In-system reprogramming via serial port
+ * - Dedicated memory bus, preserving four 8-bit ports for general purpose I/O
+ * - Power-fail reset
+ * - Early warning power-fail interrupt
+ * - Watchdog timer
+ * - Accesses up to 128kB on the bytewide bus
+ * - Decodes memory for 32kB x 8 or 128kB x 8 SRAMs
+ * - Four additional decoded peripheral-chip enables
+ * - CRC hardware for checking memory validity
+ * - Optionally emulates an 8042-style slave interface
+ * - Memory encryption using an 80-bit encryption key
+ * - Automatic random generation of encryption keys
+ * - Self-destruct input for tamper protection
+ * - Optional top-coating prevents microprobe
+ *
+ *****************************************************************************/
+
+/******************************************************************************
+ * Notes:
+ *
+ * The term cycles is used here to really refer to clock oscilations, because 1 machine cycle
+ * actually takes 12 oscilations.
+ *
+ * Read/Write/Modify Instruction -
+ * Data is read from the Port Latch (not the Port Pin!), possibly modified, and
+ * written back to (the pin? and) the latch!
+ *
+ * The following all perform this on a port address..
+ * (anl, orl, xrl, jbc, cpl, inc, dec, djnz, mov px.y,c, clr px.y, setb px.y)
+ *
+ * Serial UART emulation is not really accurate, but faked enough to work as far as i can tell
+ *
+ * August 27,2003: Currently support for only 8031/8051/8751 chips (ie 128 RAM)
+ * October 14,2003: Added initial support for the 8752 (ie 256 RAM)
+ * October 22,2003: Full support for the 8752 (ie 256 RAM)
+ * July 28,2004: Fixed MOVX command and added External Ram Paging Support
+ * July 31,2004: Added Serial Mode 0 Support & Fixed Interrupt Flags for Serial Port
+ *
+ * October, 2008, Couriersud - Major rewrite
+ *
+ *****************************************************************************/
+
+/* TODO: Varios
+ * - EA pin - defined by architecture, must implement:
+ * 1 means external access, bypassing internal ROM
+ * - T0 output clock ?
+ *
+ * - Implement 80C52 extended serial capabilities
+ * - Fix serial communication - This is a big hack (but working) right now.
+ * - Implement 83C751 in sslam.c
+ * - Fix cardline.c
+ * most likely due to different behaviour of I/O pins. The boards
+ * actually use 80CXX, i.e. CMOS versions.
+ * "Normal" 805X will return a 0 if reading from a output port which has
+ * a 0 written to it's latch. At least cardline expects a 1 here.
+ *
+ * Done: (Couriersud)
+ * - Merged DS5002FP
+ * - Disassembler now uses type specific memory names
+ * - Merged DS5002FP disasm
+ * - added 83C751 memory names to disassembler
+ * - Pointer-ified
+ * - Implemented cmos features
+ * - Implemented 80C52 interrupt handling
+ * - Fix segas18.c (segaic16.c) memory handling.
+ * - Fix sslam.c
+ * - Fix limenko.c videopkr.c : Issue with core allocation of ram (duplicate savestate)
+ * - Handle internal ram better (debugger visible)
+ * - Fixed port reading
+ * - Rewrote Macros for better readibility
+ * - Fixed and rewrote Interrupt handling
+ * - Now returns INTERNAL_DIVIDER, adjusted cycle counts
+ * - Remove unnecessary and duplicated code
+ * - Remove unnecessary functions
+ * - Rewrite to have sfr-registers stored in int_ram.
+ * - Debugger may now watch sfr-registers as well.
+ * - implemented interrupt callbacks (HOLD_LINE now supported)
+ * - Runtime switch for processor type - remove ifdefs
+ * - internal memory maps for internal rom versions (internal ram now displayed in debugger)
+ * - more timer cleanups from manual
+ */
+
+#include "emu.h"
+#include "debugger.h"
+#include "mcs51.h"
+
+#define VERBOSE 0
+
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+enum
+{
+ FEATURE_NONE = 0x00,
+ FEATURE_I8052 = 0x01,
+ FEATURE_CMOS = 0x02,
+ FEATURE_I80C52 = 0x04,
+ FEATURE_DS5002FP = 0x08,
+};
+
+/* Internal address in SFR of registers */
+enum
+{
+ ADDR_PSW = 0xd0,
+ ADDR_ACC = 0xe0,
+ ADDR_B = 0xf0,
+
+ ADDR_P0 = 0x80,
+ ADDR_SP = 0x81,
+ ADDR_DPL = 0x82,
+ ADDR_DPH = 0x83,
+ ADDR_PCON = 0x87,
+ ADDR_TCON = 0x88,
+ ADDR_TMOD = 0x89,
+ ADDR_TL0 = 0x8a,
+ ADDR_TL1 = 0x8b,
+ ADDR_TH0 = 0x8c,
+ ADDR_TH1 = 0x8d,
+ ADDR_P1 = 0x90,
+ ADDR_SCON = 0x98,
+ ADDR_SBUF = 0x99,
+ ADDR_P2 = 0xa0,
+ ADDR_IE = 0xa8,
+ ADDR_P3 = 0xb0,
+ ADDR_IP = 0xb8,
+
+ /* 8052 Only registers */
+ ADDR_T2CON = 0xc8,
+ ADDR_RCAP2L = 0xca,
+ ADDR_RCAP2H = 0xcb,
+ ADDR_TL2 = 0xcc,
+ ADDR_TH2 = 0xcd,
+
+ /* 80C52 Only registers */
+ ADDR_IPH = 0xb7,
+ ADDR_SADDR = 0xa9,
+ ADDR_SADEN = 0xb9,
+
+ /* Philips 80C52 */
+ ADDR_AUXR = 0x8e,
+ ADDR_AUXR1 = 0xa2,
+
+ /* DS5002FP */
+ ADDR_CRCR = 0xc1,
+ ADDR_CRCL = 0xc2,
+ ADDR_CRCH = 0xc3,
+ ADDR_MCON = 0xc6,
+ ADDR_TA = 0xc7,
+ ADDR_RNR = 0xcf,
+ ADDR_RPCTL = 0xd8,
+ ADDR_RPS = 0xda,
+
+};
+
+/* PC vectors */
+
+enum
+{
+ V_RESET = 0x000, /* power on address */
+ V_IE0 = 0x003, /* External Interrupt 0 */
+ V_TF0 = 0x00b, /* Timer 0 Overflow */
+ V_IE1 = 0x013, /* External Interrupt 1 */
+ V_TF1 = 0x01b, /* Timer 1 Overflow */
+ V_RITI = 0x023, /* Serial Receive/Transmit */
+
+ /* 8052 Only Vectors */
+ V_TF2 = 0x02b, /* Timer 2 Overflow */
+
+ /* DS5002FP */
+ V_PFI = 0x02b, /* Power Failure Interrupt */
+};
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _mcs51_uart mcs51_uart;
+struct _mcs51_uart
+{
+ UINT8 data_out; //Data to send out
+ UINT8 bits_to_send; //How many bits left to send when transmitting out the serial port
+
+ int smod_div; /* signal divided by 2^SMOD */
+ int rx_clk; /* rx clock */
+ int tx_clk; /* tx clock */
+ UINT8 delay_cycles; //Gross Hack;
+};
+
+typedef struct _mcs51_state_t mcs51_state_t;
+struct _mcs51_state_t
+{
+ //Internal stuff
+ UINT16 ppc; //previous pc
+ UINT16 pc; //current pc
+ UINT16 features; //features of this cpu
+ UINT8 rwm; //Signals that the current instruction is a read/write/modify instruction
+
+ int inst_cycles; /* cycles for the current instruction */
+ int ram_mask; /* second ram bank for indirect access available ? */
+ int num_interrupts; /* number of interrupts supported */
+ int recalc_parity; /* recalculate parity before next instruction */
+ UINT32 last_line_state; /* last state of input lines line */
+ int t0_cnt; /* number of 0->1 transistions on T0 line */
+ int t1_cnt; /* number of 0->1 transistions on T1 line */
+ int t2_cnt; /* number of 0->1 transistions on T2 line */
+ int t2ex_cnt; /* number of 0->1 transistions on T2EX line */
+ int cur_irq_prio; /* Holds value of the current IRQ Priority Level; -1 if no irq */
+ UINT8 irq_active; /* mask which irq levels are serviced */
+ UINT8 irq_prio[8]; /* interrupt priority */
+
+ int icount;
+
+ mcs51_uart uart; /* internal uart */
+
+ /* Internal Ram */
+ UINT8 *internal_ram; /* 128 RAM (8031/51) + 128 RAM in second bank (8032/52) */
+ UINT8 *sfr_ram; /* 128 SFR - these are in 0x80 - 0xFF */
+
+ /* SFR Callbacks */
+ void (*sfr_write)(mcs51_state_t *mcs51_state, size_t offset, UINT8 data);
+ UINT8 (*sfr_read)(mcs51_state_t *mcs51_state, size_t offset);
+
+ /* Interrupt Callback */
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+
+ /* Memory spaces */
+ address_space *program;
+ direct_read_data *direct;
+ address_space *data;
+ address_space *io;
+
+ /* Serial Port TX/RX Callbacks */
+ // TODO: Move to special port r/w
+ mcs51_serial_tx_func serial_tx_callback; //Call back funciton when sending data out of serial port
+ mcs51_serial_rx_func serial_rx_callback; //Call back function to retrieve data when receiving serial port data
+
+ /* DS5002FP */
+ struct {
+ UINT8 previous_ta; /* Previous Timed Access value */
+ UINT8 ta_window; /* Limed Access window */
+ UINT8 range; /* Memory Range */
+ const ds5002fp_config *config; /* Bootstrap Configuration */
+ } ds5002fp;
+
+
+};
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+/* Read Opcode/Opcode Arguments from Program Code */
+#define ROP(pc) mcs51_state->direct->read_decrypted_byte(pc)
+#define ROP_ARG(pc) mcs51_state->direct->read_raw_byte(pc)
+
+/* Read a byte from External Code Memory (Usually Program Rom(s) Space) */
+#define CODEMEM_R(a) (UINT8)mcs51_state->program->read_byte(a)
+
+/* Read/Write a byte from/to External Data Memory (Usually RAM or other I/O) */
+#define DATAMEM_R(a) (UINT8)mcs51_state->io->read_byte(a)
+#define DATAMEM_W(a,v) mcs51_state->io->write_byte(a, v)
+
+/* Read/Write a byte from/to the Internal RAM */
+
+#define IRAM_R(a) iram_read(mcs51_state, a)
+#define IRAM_W(a, d) iram_write(mcs51_state, a, d)
+
+/* Read/Write a byte from/to the Internal RAM indirectly */
+/* (called from indirect addressing) */
+INLINE UINT8 iram_iread(mcs51_state_t *mcs51_state, offs_t a) { return (a <= mcs51_state->ram_mask) ? mcs51_state->data->read_byte(a) : 0xff; }
+INLINE void iram_iwrite(mcs51_state_t *mcs51_state, offs_t a, UINT8 d) { if (a <= mcs51_state->ram_mask) mcs51_state->data->write_byte(a, d); }
+
+#define IRAM_IR(a) iram_iread(mcs51_state, a)
+#define IRAM_IW(a, d) iram_iwrite(mcs51_state, a, d)
+
+/* Form an Address to Read/Write to External RAM indirectly */
+/* (called from indirect addressing) */
+#define ERAM_ADDR(a,m) external_ram_iaddr(mcs51_state, a,m)
+
+/* Read/Write a bit from Bit Addressable Memory */
+#define BIT_R(a) bit_address_r(mcs51_state, a)
+#define BIT_W(a,v) bit_address_w(mcs51_state, a, v)
+
+/* Input/Output a byte from given I/O port */
+#define IN(port) ((UINT8)mcs51_state->io->read_byte(port))
+#define OUT(port,value) mcs51_state->io->write_byte(port,value)
+
+
+/***************************************************************************
+ SHORTCUTS
+***************************************************************************/
+
+#define PPC mcs51_state->ppc
+#define PC mcs51_state->pc
+#define RWM mcs51_state->rwm
+
+/* SFR Registers - These are accessed directly for speed on read */
+/* Read accessors */
+
+#define SFR_A(a) mcs51_state->sfr_ram[(a)]
+#define SET_SFR_A(a,v) do { SFR_A(a) = (v); } while (0)
+
+#define ACC ((const UINT8) SFR_A(ADDR_ACC))
+#define PSW ((const UINT8) SFR_A(ADDR_PSW))
+
+#define P0 ((const UINT8) SFR_A(ADDR_P0))
+#define P1 ((const UINT8) SFR_A(ADDR_P1))
+#define P2 ((const UINT8) SFR_A(ADDR_P2))
+#define P3 ((const UINT8) SFR_A(ADDR_P3))
+
+#define SP SFR_A(ADDR_SP)
+#define DPL SFR_A(ADDR_DPL)
+#define DPH SFR_A(ADDR_DPH)
+#define PCON SFR_A(ADDR_PCON)
+#define TCON SFR_A(ADDR_TCON)
+#define TMOD SFR_A(ADDR_TMOD)
+#define TL0 SFR_A(ADDR_TL0)
+#define TL1 SFR_A(ADDR_TL1)
+#define TH0 SFR_A(ADDR_TH0)
+#define TH1 SFR_A(ADDR_TH1)
+#define SCON SFR_A(ADDR_SCON)
+#define IE SFR_A(ADDR_IE)
+#define IP SFR_A(ADDR_IP)
+#define B SFR_A(ADDR_B)
+#define SBUF SFR_A(ADDR_SBUF)
+
+#define R_REG(r) mcs51_state->internal_ram[(r) | (PSW & 0x18)]
+#define DPTR ((DPH<<8) | DPL)
+
+/* 8052 Only registers */
+#define T2CON SFR_A(ADDR_T2CON)
+#define RCAP2L SFR_A(ADDR_RCAP2L)
+#define RCAP2H SFR_A(ADDR_RCAP2H)
+#define TL2 SFR_A(ADDR_TL2)
+#define TH2 SFR_A(ADDR_TH2)
+
+/* 80C52 Only registers */
+#define IPH SFR_A(ADDR_IPH)
+#define SADDR SFR_A(ADDR_SADDR)
+#define SADEN SFR_A(ADDR_SADEN)
+
+/* Philips 80C52 */
+/* ============= */
+/* Reduced EMI Mode
+ * The AO bit (AUXR.0) in the AUXR register when set disables the
+ * ALE output.
+ */
+#define AUXR SFR_A(ADDR_AUXR)
+
+/* The dual DPTR structure (see Figure 12) is a way by which the
+ * 80C52/54/58 will specify the address of an external data memory
+ * location. There are two 16-bit DPTR registers that address the
+ * external memory, and a single bit called DPS = AUXR1/bit0 that
+ * allows the program code to switch between them.
+ */
+#define AUXR1 SFR_A(ADDR_AUXR1)
+
+/* DS5002FP only registers */
+#define CRCR SFR_A(ADDR_CRCR)
+#define CRCL SFR_A(ADDR_CRCL)
+#define CRCH SFR_A(ADDR_CRCH)
+#define MCON SFR_A(ADDR_MCON)
+#define TA SFR_A(ADDR_TA)
+#define RNR SFR_A(ADDR_RNR)
+#define RPCTL SFR_A(ADDR_RPCTL)
+#define RPS SFR_A(ADDR_RPS)
+
+
+/* WRITE accessors */
+
+/* Shortcuts */
+
+#define SET_PSW(v) do { SFR_A(ADDR_PSW) = (v); SET_PARITY(); } while (0)
+#define SET_ACC(v) do { SFR_A(ADDR_ACC) = (v); SET_PARITY(); } while (0)
+
+/* These trigger actions on modification and have to be written through SFR_W */
+#define SET_P0(v) IRAM_W(ADDR_P0, v)
+#define SET_P1(v) IRAM_W(ADDR_P1, v)
+#define SET_P2(v) IRAM_W(ADDR_P2, v)
+#define SET_P3(v) IRAM_W(ADDR_P3, v)
+
+/* Within the cpu core, do not trigger a send */
+#define SET_SBUF(v) SET_SFR_A(ADDR_SBUF, v)
+
+/* No actions triggered on write */
+#define SET_REG(r, v) do { mcs51_state->internal_ram[(r) | (PSW & 0x18)] = (v); } while (0)
+
+#define SET_DPTR(n) do { DPH = ((n) >> 8) & 0xff; DPL = (n) & 0xff; } while (0)
+
+/* Macros for Setting Flags */
+#define SET_X(R, v) do { R = (v);} while (0)
+
+#define SET_CY(n) SET_PSW((PSW & 0x7f) | (n<<7)) //Carry Flag
+#define SET_AC(n) SET_PSW((PSW & 0xbf) | (n<<6)) //Aux.Carry Flag
+#define SET_FO(n) SET_PSW((PSW & 0xdf) | (n<<5)) //User Flag
+#define SET_RS(n) SET_PSW((PSW & 0xe7) | (n<<3)) //R Bank Select
+#define SET_OV(n) SET_PSW((PSW & 0xfb) | (n<<2)) //Overflow Flag
+#define SET_P(n) SET_PSW((PSW & 0xfe) | (n<<0)) //Parity Flag
+
+#define SET_BIT(R, n, v) do { R = (R & ~(1<<(n))) | ((v) << (n));} while (0)
+#define GET_BIT(R, n) (((R)>>(n)) & 0x01)
+
+#define SET_EA(n) SET_BIT(IE, 7, n) //Global Interrupt Enable/Disable
+#define SET_ES(n) SET_BIT(IE, 4, v) //Serial Interrupt Enable/Disable
+#define SET_ET1(n) SET_BIT(IE, 3, n) //Timer 1 Interrupt Enable/Disable
+#define SET_EX1(n) SET_BIT(IE, 2, n) //External Int 1 Interrupt Enable/Disable
+#define SET_ET0(n) SET_BIT(IE, 1, n) //Timer 0 Interrupt Enable/Disable
+#define SET_EX0(n) SET_BIT(IE, 0, n) //External Int 0 Interrupt Enable/Disable
+/* 8052 Only flags */
+#define SET_ET2(n) SET_BIT(IE, 5, n) //Timer 2 Interrupt Enable/Disable
+
+/* 8052 Only flags */
+#define SET_PT2(n) SET_BIT(IP, 5, n); //Set Timer 2 Priority Level
+
+#define SET_PS0(n) SET_BIT(IP, 4, n) //Set Serial Priority Level
+#define SET_PT1(n) SET_BIT(IP, 3, n) //Set Timer 1 Priority Level
+#define SET_PX1(n) SET_BIT(IP, 2, n) //Set External Int 1 Priority Level
+#define SET_PT0(n) SET_BIT(IP, 1, n) //Set Timer 0 Priority Level
+#define SET_PX0(n) SET_BIT(IP, 0, n) //Set External Int 0 Priority Level
+
+#define SET_TF1(n) SET_BIT(TCON, 7, n) //Indicated Timer 1 Overflow Int Triggered
+#define SET_TR1(n) SET_BIT(TCON, 6, n) //IndicateS Timer 1 is running
+#define SET_TF0(n) SET_BIT(TCON, 5, n) //Indicated Timer 0 Overflow Int Triggered
+#define SET_TR0(n) SET_BIT(TCON, 4, n) //IndicateS Timer 0 is running
+#define SET_IE1(n) SET_BIT(TCON, 3, n) //Indicated External Int 1 Triggered
+#define SET_IT1(n) SET_BIT(TCON, 2, n) //Indicates how External Int 1 is Triggered
+#define SET_IE0(n) SET_BIT(TCON, 1, n) //Indicated External Int 0 Triggered
+#define SET_IT0(n) SET_BIT(TCON, 0, n) //Indicates how External Int 0 is Triggered
+
+#define SET_SM0(n) SET_BIT(SCON, 7, n) //Sets Serial Port Mode
+#define SET_SM1(n) SET_BIT(SCON, 6, n) //Sets Serial Port Mode
+#define SET_SM2(n) SET_BIT(SCON, 5, n) //Sets Serial Port Mode (Multiprocesser mode)
+#define SET_REN(n) SET_BIT(SCON, 4, n) //Sets Serial Port Receive Enable
+#define SET_TB8(n) SET_BIT(SCON, 3, n) //Transmit 8th Bit
+#define SET_RB8(n) SET_BIT(SCON, 2, n) //Receive 8th Bit
+#define SET_TI(n) SET_BIT(SCON, 1, n) //Indicates Transmit Interrupt Occurred
+#define SET_RI(n) SET_BIT(SCON, 0, n) //Indicates Receive Interrupt Occurred
+
+#define SET_GATE1(n) SET_BIT(TMOD, 7, n) //Timer 1 Gate Mode
+#define SET_CT1(n) SET_BIT(TMOD, 6, n) //Timer 1 Counter Mode
+#define SET_M1_1(n) SET_BIT(TMOD, 5, n) //Timer 1 Timer Mode Bit 1
+#define SET_M1_0(n) SET_BIT(TMOD, 4, n) //Timer 1 Timer Mode Bit 0
+#define SET_GATE0(n) SET_BIT(TMOD, 3, n) //Timer 0 Gate Mode
+#define SET_CT0(n) SET_BIT(TMOD, 2, n) //Timer 0 Counter Mode
+#define SET_M0_1(n) SET_BIT(TMOD, 1, n) //Timer 0 Timer Mode Bit 1
+#define SET_M0_0(n) SET_BIT(TMOD, 0, n) //Timer 0 Timer Mode Bit 0
+
+
+
+/* 8052 Only flags - T2CON Flags */
+#define SET_TF2(n) SET_BIT(T2CON, 7, n) //Indicated Timer 2 Overflow Int Triggered
+#define SET_EXF2(n) SET_BIT(T2CON, 6, n) //Indicates Timer 2 External Flag
+#define SET_RCLK(n) SET_BIT(T2CON, 5, n) //Receive Clock
+#define SET_TCLK(n) SET_BIT(T2CON, 4, n) //Transmit Clock
+#define SET_EXEN2(n) SET_BIT(T2CON, 3, n) //Timer 2 External Interrupt Enable
+#define SET_TR2(n) SET_BIT(T2CON, 2, n) //Indicates Timer 2 is running
+#define SET_CT2(n) SET_BIT(T2CON, 1, n) //Sets Timer 2 Counter/Timer Mode
+#define SET_CP(n) SET_BIT(T2CON, 0, n) //Sets Timer 2 Capture/Reload Mode
+
+#define SET_GF1(n) SET_BIT(PCON, 3, n)
+#define SET_GF0(n) SET_BIT(PCON, 2, n)
+#define SET_PD(n) SET_BIT(PCON, 1, n)
+#define SET_IDL(n) SET_BIT(PCON, 0, n)
+
+/* Macros for accessing flags */
+
+#define GET_CY GET_BIT(PSW, 7)
+#define GET_AC GET_BIT(PSW, 6)
+#define GET_FO GET_BIT(PSW, 5)
+#define GET_RS GET_BIT(PSW, 3)
+#define GET_OV GET_BIT(PSW, 2)
+#define GET_P GET_BIT(PSW, 0)
+
+#define GET_EA GET_BIT(IE, 7)
+#define GET_ET2 GET_BIT(IE, 5)
+#define GET_ES GET_BIT(IE, 4)
+#define GET_ET1 GET_BIT(IE, 3)
+#define GET_EX1 GET_BIT(IE, 2)
+#define GET_ET0 GET_BIT(IE, 1)
+#define GET_EX0 GET_BIT(IE, 0)
+
+/* 8052 Only flags */
+#define GET_PT2 GET_BIT(IP, 5)
+
+#define GET_PS GET_BIT(IP, 4)
+#define GET_PT1 GET_BIT(IP, 3)
+#define GET_PX1 GET_BIT(IP, 2)
+#define GET_PT0 GET_BIT(IP, 1)
+#define GET_PX0 GET_BIT(IP, 0)
+
+#define GET_TF1 GET_BIT(TCON, 7)
+#define GET_TR1 GET_BIT(TCON, 6)
+#define GET_TF0 GET_BIT(TCON, 5)
+#define GET_TR0 GET_BIT(TCON, 4)
+#define GET_IE1 GET_BIT(TCON, 3)
+#define GET_IT1 GET_BIT(TCON, 2)
+#define GET_IE0 GET_BIT(TCON, 1)
+#define GET_IT0 GET_BIT(TCON, 0)
+
+#define GET_SM0 GET_BIT(SCON, 7)
+#define GET_SM1 GET_BIT(SCON, 6)
+#define GET_SM2 GET_BIT(SCON, 5)
+#define GET_REN GET_BIT(SCON, 4)
+#define GET_TB8 GET_BIT(SCON, 3)
+#define GET_RB8 GET_BIT(SCON, 2)
+#define GET_TI GET_BIT(SCON, 1)
+#define GET_RI GET_BIT(SCON, 0)
+
+#define GET_GATE1 GET_BIT(TMOD, 7)
+#define GET_CT1 GET_BIT(TMOD, 6)
+#define GET_M1_1 GET_BIT(TMOD, 5)
+#define GET_M1_0 GET_BIT(TMOD, 4)
+#define GET_GATE0 GET_BIT(TMOD, 3)
+#define GET_CT0 GET_BIT(TMOD, 2)
+#define GET_M0_1 GET_BIT(TMOD, 1)
+#define GET_M0_0 GET_BIT(TMOD, 0)
+
+#define GET_SMOD GET_BIT(PCON, 7)
+
+/* Only in 80C51BH & other cmos */
+
+#define GET_GF1 GET_BIT(PCON, 3)
+#define GET_GF0 GET_BIT(PCON, 2)
+#define GET_PD GET_BIT(PCON, 1)
+#define GET_IDL (GET_BIT(PCON, 0) & ~(GET_PD)) /* PD takes precedence! */
+
+/* 8052 Only flags */
+#define GET_TF2 GET_BIT(T2CON, 7)
+#define GET_EXF2 GET_BIT(T2CON, 6)
+#define GET_RCLK GET_BIT(T2CON, 5)
+#define GET_TCLK GET_BIT(T2CON, 4)
+#define GET_EXEN2 GET_BIT(T2CON, 3)
+#define GET_TR2 GET_BIT(T2CON, 2)
+#define GET_CT2 GET_BIT(T2CON, 1)
+#define GET_CP GET_BIT(T2CON, 0)
+
+/* DS5002FP Only flags */
+
+/* PCON Flags - DS5002FP */
+
+#define GET_POR GET_BIT(PCON, 6)
+#define GET_PFW GET_BIT(PCON, 5)
+#define GET_WTR GET_BIT(PCON, 4)
+#define GET_EPFW GET_BIT(PCON, 3)
+#define GET_EWT GET_BIT(PCON, 2)
+
+#define SET_PFW(n) SET_BIT(PCON, 5, n)
+
+/* MCON Flags - DS5002FP */
+
+#define GET_PA ((MCON & 0xf0)>>4)
+#define GET_RG1 GET_BIT(MCON, 3)
+#define GET_PES GET_BIT(MCON, 2)
+#define GET_PM GET_BIT(MCON, 1)
+#define GET_SL GET_BIT(MCON, 0)
+
+/* RPCTL Flags - DS5002FP */
+#define GET_RNR GET_BIT(RPCTL, 7) /* Bit 6 ?? */
+#define GET_EXBS GET_BIT(RPCTL, 5)
+#define GET_AE GET_BIT(RPCTL, 4)
+#define GET_IBI GET_BIT(RPCTL, 3)
+#define GET_DMA GET_BIT(RPCTL, 2)
+#define GET_RPCON GET_BIT(RPCTL, 1)
+#define GET_RG0 GET_BIT(RPCTL, 0)
+
+
+/*Add and Subtract Flag settings*/
+#define DO_ADD_FLAGS(a,d,c) do_add_flags(mcs51_state, a, d, c)
+#define DO_SUB_FLAGS(a,d,c) do_sub_flags(mcs51_state, a, d, c)
+
+#define SET_PARITY() do {mcs51_state->recalc_parity |= 1;} while (0)
+#define PUSH_PC() push_pc(mcs51_state)
+#define POP_PC() pop_pc(mcs51_state)
+
+/* Clear Current IRQ */
+#define CLEAR_CURRENT_IRQ() clear_current_irq(mcs51_state)
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static void check_irqs(mcs51_state_t *mcs51_state);
+INLINE void serial_transmit(mcs51_state_t *mcs51_state, UINT8 data);
+
+/* Hold callback functions so they can be set by caller (before the cpu reset) */
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+INLINE mcs51_state_t *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == I8031 ||
+ device->type() == I8032 ||
+ device->type() == I8051 ||
+ device->type() == I8751 ||
+ device->type() == I8052 ||
+ device->type() == I8752 ||
+ device->type() == I80C31 ||
+ device->type() == I80C32 ||
+ device->type() == I80C51 ||
+ device->type() == I80C52 ||
+ device->type() == I87C51 ||
+ device->type() == I87C52 ||
+ device->type() == AT89C4051 ||
+ device->type() == DS5002FP);
+ return (mcs51_state_t *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+INLINE void clear_current_irq(mcs51_state_t *mcs51_state)
+{
+ if (mcs51_state->cur_irq_prio >= 0)
+ mcs51_state->irq_active &= ~(1 << mcs51_state->cur_irq_prio);
+ if (mcs51_state->irq_active & 4)
+ mcs51_state->cur_irq_prio = 2;
+ else if (mcs51_state->irq_active & 2)
+ mcs51_state->cur_irq_prio = 1;
+ else if (mcs51_state->irq_active & 1)
+ mcs51_state->cur_irq_prio = 0;
+ else
+ mcs51_state->cur_irq_prio = -1;
+ LOG(("New: %d %02x\n", mcs51_state->cur_irq_prio, mcs51_state->irq_active));
+}
+
+INLINE UINT8 r_acc(mcs51_state_t *mcs51_state) { return SFR_A(ADDR_ACC); }
+
+INLINE UINT8 r_psw(mcs51_state_t *mcs51_state) { return SFR_A(ADDR_PSW); }
+
+INLINE void update_ptrs(mcs51_state_t *mcs51_state)
+{
+ mcs51_state->internal_ram = (UINT8 *)mcs51_state->data->get_write_ptr(0x00);
+ mcs51_state->sfr_ram = (UINT8 *)mcs51_state->data->get_write_ptr(0x100);
+}
+
+
+/* Generate an external ram address for read/writing using indirect addressing mode */
+
+/*The lowest 8 bits of the address are passed in (from the R0/R1 register), however
+ the hardware can be configured to set the rest of the address lines to any available output port pins, which
+ means the only way we can implement this is to allow the driver to setup a callback to generate the
+ address as defined by the specific hardware setup. We'll assume the address won't be bigger than 32 bits
+
+ Couriersud, October 2008:
+ There is no way external hardware can distinguish between 8bit access and 16 bit access.
+ During 16bit access the high order byte of the address is output on port 2. We therefore
+ assume that most hardware will use port 2 for 8bit access as well.
+
+ On configurations where 8 bit access in conjunction with other ports is used,
+ it is up to the driver to use AM_MIRROR to mask out the high level address and
+ provide it's own mapping.
+*/
+
+/*
+ The DS5002FP has 2 16 bits data address buses (the byte-wide bus and the expanded bus). The exact memory position accessed depends on the
+ partition mode, the memory range and the expanded bus select. The partition mode and the expanded bus select can be changed at any time.
+
+ In order to simplify memory mapping to the data address bus, the following address map is assumed for partitioned mode:
+
+ 0x00000-0x0ffff -> data memory on the expanded bus
+ 0x10000-0x1ffff -> data memory on the byte-wide bus
+
+ For non-partitioned mode the following memory map is assumed:
+
+ 0x0000-0xffff -> data memory (the bus used to access it does not matter)
+*/
+
+INLINE offs_t external_ram_iaddr(mcs51_state_t *mcs51_state, offs_t offset, offs_t mem_mask)
+{
+ /* Memory Range (RG1 and RG0 @ MCON and RPCTL registers) */
+ static const UINT16 ds5002fp_ranges[4] = { 0x1fff, 0x3fff, 0x7fff, 0xffff };
+ /* Memory Partition Table (RG1 & RG0 @ MCON & RPCTL registers) */
+ static const UINT32 ds5002fp_partitions[16] = {
+ 0x0000, 0x1000, 0x2000, 0x3000, 0x4000, 0x5000, 0x6000, 0x7000,
+ 0x8000, 0x9000, 0xa000, 0xb000, 0xc000, 0xd000, 0xe000, 0x10000 };
+
+ /* if partition mode is set, adjust offset based on the bus */
+ if (mcs51_state->features & FEATURE_DS5002FP)
+ {
+ if (!GET_PM) {
+ if (!GET_EXBS) {
+ if ((offset >= ds5002fp_partitions[GET_PA]) && (offset <= ds5002fp_ranges[mcs51_state->ds5002fp.range])) {
+ offset += 0x10000;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (mem_mask == 0x00ff)
+ return (offset & mem_mask) | (P2 << 8);
+ }
+ return offset;
+}
+
+/* Internal ram read/write */
+
+INLINE UINT8 iram_read(mcs51_state_t *mcs51_state, size_t offset)
+{
+ return (((offset) < 0x80) ? mcs51_state->data->read_byte(offset) : mcs51_state->sfr_read(mcs51_state, offset));
+}
+
+INLINE void iram_write(mcs51_state_t *mcs51_state, size_t offset, UINT8 data)
+{
+ if ((offset) < 0x80)
+ mcs51_state->data->write_byte(offset, data);
+ else
+ mcs51_state->sfr_write(mcs51_state, offset, data);
+}
+
+/*Push the current PC to the stack*/
+INLINE void push_pc(mcs51_state_t *mcs51_state)
+{
+ UINT8 tmpSP = SP+1; //Grab and Increment Stack Pointer
+ IRAM_IW(tmpSP, (PC & 0xff)); //Store low byte of PC to Internal Ram (Use IRAM_IW to store stack above 128 bytes)
+ tmpSP++; // ""
+ SP = tmpSP; // ""
+ IRAM_IW(tmpSP, ( (PC & 0xff00) >> 8)); //Store hi byte of PC to next address in Internal Ram (Use IRAM_IW to store stack above 128 bytes)
+}
+
+/*Pop the current PC off the stack and into the pc*/
+INLINE void pop_pc(mcs51_state_t *mcs51_state)
+{
+ UINT8 tmpSP = SP; //Grab Stack Pointer
+ PC = (IRAM_IR(tmpSP--) & 0xff) << 8; //Store hi byte to PC (must use IRAM_IR to access stack pointing above 128 bytes)
+ PC = PC | IRAM_IR(tmpSP--); //Store lo byte to PC (must use IRAM_IR to access stack pointing above 128 bytes)
+ SP = tmpSP; //Decrement Stack Pointer
+}
+
+//Set the PSW Parity Flag
+INLINE void set_parity(mcs51_state_t *mcs51_state)
+{
+ //This flag will be set when the accumulator contains an odd # of bits set..
+ UINT8 p = 0;
+ int i;
+ UINT8 a = ACC;
+
+ for (i=0; i<8; i++) { //Test for each of the 8 bits in the ACC!
+ p ^= (a & 1);
+ a = (a >> 1);
+ }
+
+ SET_P(p & 1);
+}
+
+INLINE UINT8 bit_address_r(mcs51_state_t *mcs51_state, UINT8 offset)
+{
+ UINT8 word;
+ UINT8 mask;
+ int bit_pos;
+ int distance; /* distance between bit addressable words */
+ /* 1 for normal bits, 8 for sfr bit addresses */
+
+ //User defined bit addresses 0x20-0x2f (values are 0x0-0x7f)
+ if (offset < 0x80) {
+ distance = 1;
+ word = ( (offset & 0x78) >> 3) * distance + 0x20;
+ bit_pos = offset & 0x7;
+ mask = (0x1 << bit_pos);
+ return((IRAM_R(word) & mask) >> bit_pos);
+ }
+ //SFR bit addressable registers
+ else {
+ distance = 8;
+ word = ( (offset & 0x78) >> 3) * distance + 0x80;
+ bit_pos = offset & 0x7;
+ mask = (0x1 << bit_pos);
+ return ((IRAM_R(word) & mask) >> bit_pos);
+ }
+}
+
+
+INLINE void bit_address_w(mcs51_state_t *mcs51_state, UINT8 offset, UINT8 bit)
+{
+ int word;
+ UINT8 mask;
+ int bit_pos;
+ UINT8 result;
+ int distance;
+
+ /* User defined bit addresses 0x20-0x2f (values are 0x0-0x7f) */
+ if (offset < 0x80) {
+ distance = 1;
+ word = ((offset & 0x78) >> 3) * distance + 0x20;
+ bit_pos = offset & 0x7;
+ bit = (bit & 0x1) << bit_pos;
+ mask = ~(1 << bit_pos) & 0xff;
+ result = IRAM_R(word) & mask;
+ result = result | bit;
+ IRAM_W(word, result);
+ }
+ /* SFR bit addressable registers */
+ else {
+ distance = 8;
+ word = ((offset & 0x78) >> 3) * distance + 0x80;
+ bit_pos = offset & 0x7;
+ bit = (bit & 0x1) << bit_pos;
+ mask = ~(1 << bit_pos) & 0xff;
+ result = IRAM_R(word) & mask;
+ result = result | bit;
+ IRAM_W(word, result);
+ }
+}
+
+INLINE void do_add_flags(mcs51_state_t *mcs51_state, UINT8 a, UINT8 data, UINT8 c)
+{
+ UINT16 result = a+data+c;
+ INT16 result1 = (INT8)a+(INT8)data+c;
+
+ SET_CY((result & 0x100) >> 8);
+ result = (a&0x0f)+(data&0x0f)+c;
+ SET_AC((result & 0x10) >> 4);
+ SET_OV(result1 < -128 || result1 > 127);
+}
+
+INLINE void do_sub_flags(mcs51_state_t *mcs51_state, UINT8 a, UINT8 data, UINT8 c)
+{
+ UINT16 result = a-(data+c);
+ INT16 result1 = (INT8)a-(INT8)(data+c);
+
+ SET_CY((result & 0x100) >> 8);
+ result = (a&0x0f)-((data&0x0f)+c);
+ SET_AC((result & 0x10) >> 4);
+ SET_OV((result1 < -128 || result1 > 127));
+}
+
+INLINE void transmit_receive(mcs51_state_t *mcs51_state, int source)
+{
+ int mode = (GET_SM0<<1) | GET_SM1;
+
+ if (source == 1) /* timer1 */
+ mcs51_state->uart.smod_div = (mcs51_state->uart.smod_div + 1) & (2-GET_SMOD);
+
+ switch(mode) {
+ //8 bit shifter ( + start,stop bit ) - baud set by clock freq / 12
+ case 0:
+ mcs51_state->uart.rx_clk += (source == 0) ? 16 : 0; /* clock / 12 */
+ mcs51_state->uart.tx_clk += (source == 0) ? 16 : 0; /* clock / 12 */
+ break;
+ //8 bit uart ( + start,stop bit ) - baud set by timer1 or timer2
+ case 1:
+ case 3:
+ if (source == 1)
+ {
+ mcs51_state->uart.tx_clk += (GET_TCLK ? 0 : !mcs51_state->uart.smod_div);
+ mcs51_state->uart.rx_clk += (GET_RCLK ? 0 : !mcs51_state->uart.smod_div);
+ }
+ if (source == 2)
+ {
+ mcs51_state->uart.tx_clk += (GET_TCLK ? 1 : 0);
+ mcs51_state->uart.rx_clk += (GET_RCLK ? 1 : 0);
+ }
+ break;
+ //9 bit uart
+ case 2:
+ mcs51_state->uart.rx_clk += (source == 0) ? (GET_SMOD ? 6 : 3) : 0; /* clock / 12 * 3 / 8 (16) = clock / 32 (64)*/
+ mcs51_state->uart.tx_clk += (source == 0) ? (GET_SMOD ? 6 : 3) : 0; /* clock / 12 */
+ break;
+ }
+ /* transmit ? */
+ if (mcs51_state->uart.tx_clk >= 16)
+ {
+ mcs51_state->uart.tx_clk &= 0x0f;
+ if(mcs51_state->uart.bits_to_send)
+ {
+ mcs51_state->uart.bits_to_send--;
+ if(mcs51_state->uart.bits_to_send == 0) {
+ //Call the callback function
+ if(mcs51_state->serial_tx_callback)
+ mcs51_state->serial_tx_callback(mcs51_state->device, mcs51_state->uart.data_out);
+ //Set Interrupt Flag
+ SET_TI(1);
+ }
+ }
+
+ }
+ /* receive */
+ if (mcs51_state->uart.rx_clk >= 16)
+ {
+ mcs51_state->uart.rx_clk &= 0x0f;
+ if (mcs51_state->uart.delay_cycles>0)
+ {
+ mcs51_state->uart.delay_cycles--;
+ if (mcs51_state->uart.delay_cycles == 0)
+ {
+ int data = 0;
+ //Call our callball function to retrieve the data
+ if(mcs51_state->serial_rx_callback)
+ data = mcs51_state->serial_rx_callback(mcs51_state->device);
+ LOG(("RX Deliver %d\n", data));
+ SET_SBUF(data);
+ //Flag the IRQ
+ SET_RI(1);
+ }
+ }
+ }
+}
+
+
+INLINE void update_timer_t0(mcs51_state_t *mcs51_state, int cycles)
+{
+ int mode = (GET_M0_1<<1) | GET_M0_0;
+ UINT32 count = 0;
+
+ if (GET_TR0)
+ {
+ UINT32 delta;
+
+ /* counter / external input */
+ delta = GET_CT0 ? mcs51_state->t0_cnt : cycles;
+ /* taken, reset */
+ mcs51_state->t0_cnt = 0;
+ /* TODO: Not sure about IE0. The manual specifies INT0=high,
+ * which in turn means CLEAR_LINE.
+ * IE0 may be edge triggered depending on IT0 */
+ if (GET_GATE0 && !GET_IE0)
+ delta = 0;
+
+ switch(mode) {
+ case 0: /* 13 Bit Timer Mode */
+ count = ((TH0<<5) | ( TL0 & 0x1f ) );
+ count += delta;
+ if ( count & 0xffffe000 ) /* Check for overflow */
+ SET_TF0(1);
+ TH0 = (count>>5) & 0xff;
+ TL0 = count & 0x1f ;
+ break;
+ case 1: /* 16 Bit Timer Mode */
+ count = ((TH0<<8) | TL0);
+ count += delta;
+ if ( count & 0xffff0000 ) /* Check for overflow */
+ SET_TF0(1);
+ TH0 = (count>>8) & 0xff;
+ TL0 = count & 0xff;
+ break;
+ case 2: /* 8 Bit Autoreload */
+ count = ((UINT32) TL0) + delta;
+ if ( count & 0xffffff00 ) /* Check for overflow */
+ {
+ SET_TF0(1);
+ count += TH0; /* Reload timer */
+ }
+ /* Update new values of the counter */
+ TL0 = count & 0xff;
+ break;
+ case 3:
+ /* Split Timer 1 */
+ count = ((UINT32) TL0) + delta;
+ if ( count & 0xffffff00 ) /* Check for overflow */
+ SET_TF0(1);
+ TL0 = count & 0xff; /* Update new values of the counter */
+ break;
+ }
+ }
+ if (GET_TR1)
+ {
+ switch(mode)
+ {
+ case 3:
+ /* Split Timer 2 */
+ count = ((UINT32) TH0) + cycles; /* No gate control or counting !*/
+ if ( count & 0xffffff00 ) /* Check for overflow */
+ SET_TF1(1);
+ TH0 = count & 0xff; /* Update new values of the counter */
+ break;
+ }
+ }
+}
+
+/* From the DS5002FP User Manual
+When Timer 1 is selected for operation in Mode 3, it stops counting and holds its current value. This
+action is the same as setting TR1 = 0. When Timer 0 is selected in Mode 3, Timer 1???s control bits are
+stolen as described above. As a result, Timer 1???s functions are limited in this MODE. It is forced to
+operate as a timer whose clock in-put is 12 tCLK and it cannot generate an interrupt on overflow. In
+addition, it also cannot be used with the GATE function. However, it can be started and stopped by
+switching it into or out of Mode 3 or it can be assigned as a baud rate generator for the serial port.
+*/
+
+/* Intel documentation:
+ * Timer 1 may still be used in modes 0, 1, and 2, while timer 0
+ * is in mode 3. With one important exception: No interrupts
+ * will be generated by timer 1 while timer 0 is using the TF1
+ * overflow flag
+ */
+
+INLINE void update_timer_t1(mcs51_state_t *mcs51_state, int cycles)
+{
+ UINT8 mode = (GET_M1_1<<1) | GET_M1_0;
+ UINT8 mode_0 = (GET_M0_1<<1) | GET_M0_0;
+ UINT32 count = 0;
+
+ if (mode_0 != 3)
+ {
+ if (GET_TR1)
+ {
+ UINT32 delta;
+ UINT32 overflow = 0;
+
+ /* counter / external input */
+ delta = GET_CT1 ? mcs51_state->t1_cnt : cycles;
+ /* taken, reset */
+ mcs51_state->t1_cnt = 0;
+ /* TODO: Not sure about IE0. The manual specifies INT0=high,
+ * which in turn means CLEAR_LINE. Change to access last_state?
+ * IE0 may be edge triggered depending on IT0 */
+ if (GET_GATE1 && !GET_IE1)
+ delta = 0;
+
+ switch(mode) {
+ case 0: /* 13 Bit Timer Mode */
+ count = ((TH1<<5) | ( TL1 & 0x1f ) );
+ count += delta;
+ overflow = count & 0xffffe000; /* Check for overflow */
+ TH1 = (count>>5) & 0xff;
+ TL1 = count & 0x1f ;
+ break;
+ case 1: /* 16 Bit Timer Mode */
+ count = ((TH1<<8) | TL1);
+ count += delta;
+ overflow = count & 0xffff0000; /* Check for overflow */
+ TH1 = (count>>8) & 0xff;
+ TL1 = count & 0xff;
+ break;
+ case 2: /* 8 Bit Autoreload */
+ count = ((UINT32) TL1) + delta;
+ overflow = count & 0xffffff00; /* Check for overflow */
+ if ( overflow )
+ {
+ count += TH1; /* Reload timer */
+ }
+ /* Update new values of the counter */
+ TL1 = count & 0xff;
+ break;
+ case 3:
+ /* do nothing */
+ break;
+ }
+ if (overflow)
+ {
+ SET_TF1(1);
+ transmit_receive(mcs51_state, 1);
+ }
+ }
+ }
+ else
+ {
+ UINT32 delta;
+ UINT32 overflow = 0;
+
+ delta = cycles;
+ /* taken, reset */
+ mcs51_state->t1_cnt = 0;
+ switch(mode) {
+ case 0: /* 13 Bit Timer Mode */
+ count = ((TH1<<5) | ( TL1 & 0x1f ) );
+ count += delta;
+ overflow = count & 0xffffe000; /* Check for overflow */
+ TH1 = (count>>5) & 0xff;
+ TL1 = count & 0x1f ;
+ break;
+ case 1: /* 16 Bit Timer Mode */
+ count = ((TH1<<8) | TL1);
+ count += delta;
+ overflow = count & 0xffff0000; /* Check for overflow */
+ TH1 = (count>>8) & 0xff;
+ TL1 = count & 0xff;
+ break;
+ case 2: /* 8 Bit Autoreload */
+ count = ((UINT32) TL1) + delta;
+ overflow = count & 0xffffff00; /* Check for overflow */
+ if ( overflow )
+ {
+ count += TH1; /* Reload timer */
+ }
+ /* Update new values of the counter */
+ TL1 = count & 0xff;
+ break;
+ case 3:
+ /* do nothing */
+ break;
+ }
+ if (overflow)
+ {
+ transmit_receive(mcs51_state, 1);
+ }
+ }
+}
+
+INLINE void update_timer_t2(mcs51_state_t *mcs51_state, int cycles)
+{
+ /* Update Timer 2 */
+ if(GET_TR2) {
+ int mode = ((GET_TCLK | GET_RCLK) << 1) | GET_CP;
+ int delta = GET_CT2 ? mcs51_state->t2_cnt : (mode & 2) ? cycles * (12/2) : cycles;
+
+ UINT32 count = ((TH2<<8) | TL2) + delta;
+ mcs51_state->t2_cnt = 0;
+
+ switch (mode)
+ {
+ case 0: /* 16 Bit Auto Reload */
+ if ( count & 0xffff0000 )
+ {
+ SET_TF2(1);
+ count += ((RCAP2H<<8) | RCAP2L);
+ }
+ else if (GET_EXEN2 && mcs51_state->t2ex_cnt>0)
+ {
+ count += ((RCAP2H<<8) | RCAP2L);
+ mcs51_state->t2ex_cnt = 0;
+ }
+ TH2 = (count>>8) & 0xff;
+ TL2 = count & 0xff;
+ break;
+ case 1: /* 16 Bit Capture */
+ if ( count & 0xffff0000 )
+ SET_TF2(1);
+ TH2 = (count>>8) & 0xff;
+ TL2 = count & 0xff;
+
+ if (GET_EXEN2 && mcs51_state->t2ex_cnt>0)
+ {
+ RCAP2H = TH2;
+ RCAP2L = TL2;
+ mcs51_state->t2ex_cnt = 0;
+ }
+ break;
+ case 2:
+ case 3: /* Baud rate */
+ if ( count & 0xffff0000 )
+ {
+ count += ((RCAP2H<<8) | RCAP2L);
+ transmit_receive(mcs51_state, 2);
+ }
+ TH2 = (count>>8) & 0xff;
+ TL2 = count & 0xff;
+ break;
+ }
+ }
+}
+
+INLINE void update_timers(mcs51_state_t *mcs51_state, int cycles)
+{
+ /* Update Timer 0 */
+ update_timer_t0(mcs51_state, cycles);
+ update_timer_t1(mcs51_state, cycles);
+
+ if (mcs51_state->features & FEATURE_I8052)
+ {
+ update_timer_t2(mcs51_state, cycles);
+ }
+}
+
+//Set up to transmit data out of serial port
+//NOTE: Enable Serial Port Interrupt bit is NOT required to send/receive data!
+
+INLINE void serial_transmit(mcs51_state_t *mcs51_state, UINT8 data)
+{
+ int mode = (GET_SM0<<1) | GET_SM1;
+
+ //Flag that we're sending data
+ mcs51_state->uart.data_out = data;
+ LOG(("serial_tansmit: %x %x\n", mode, data));
+ switch(mode) {
+ //8 bit shifter ( + start,stop bit ) - baud set by clock freq / 12
+ case 0:
+ mcs51_state->uart.bits_to_send = 8+2;
+ break;
+ //8 bit uart ( + start,stop bit ) - baud set by timer1 or timer2
+ case 1:
+ mcs51_state->uart.bits_to_send = 8+2;
+ break;
+ //9 bit uart
+ case 2:
+ case 3:
+ LOG(("Serial mode %d not supported in mcs51!\n", mode));
+ break;
+ }
+}
+
+INLINE void serial_receive(mcs51_state_t *mcs51_state)
+{
+ int mode = (GET_SM0<<1) | GET_SM1;
+
+ if (GET_REN) {
+ switch(mode) {
+ //8 bit shifter ( + start,stop bit ) - baud set by clock freq / 12
+ case 0:
+ mcs51_state->uart.delay_cycles = 8+2;
+ break;
+ //8 bit uart ( + start,stop bit ) - baud set by timer1 or timer2
+ case 1:
+ mcs51_state->uart.delay_cycles = 8+2;
+ break;
+ //9 bit uart
+ case 2:
+ case 3:
+ LOG(("Serial mode %d not supported in mcs51!\n", mode));
+ break;
+ }
+ }
+}
+
+/* Check and update status of serial port */
+INLINE void update_serial(mcs51_state_t *mcs51_state, int cycles)
+{
+ while (--cycles>=0)
+ transmit_receive(mcs51_state, 0);
+}
+
+/* Check and update status of serial port */
+INLINE void update_irq_prio(mcs51_state_t *mcs51_state, UINT8 ipl, UINT8 iph)
+{
+ int i;
+ for (i=0; i<8; i++)
+ mcs51_state->irq_prio[i] = ((ipl >> i) & 1) | (((iph >>i ) & 1) << 1);
+}
+
+/***************************************************************************
+ CALLBACKS - TODO: Remove
+***************************************************************************/
+
+
+void i8051_set_serial_tx_callback(device_t *device, mcs51_serial_tx_func tx_func)
+{
+ mcs51_state_t *mcs51_state = get_safe_token(device);
+ mcs51_state->serial_tx_callback = tx_func;
+}
+
+void i8051_set_serial_rx_callback(device_t *device, mcs51_serial_rx_func rx_func)
+{
+ mcs51_state_t *mcs51_state = get_safe_token(device);
+ mcs51_state->serial_rx_callback = rx_func;
+}
+
+/***************************************************************************
+ OPCODES
+***************************************************************************/
+
+#define OPHANDLER( _name ) INLINE void _name (mcs51_state_t *mcs51_state, UINT8 r)
+
+#include "mcs51ops.c"
+
+
+static void execute_op(mcs51_state_t *mcs51_state, UINT8 op)
+{
+ if (mcs51_state->recalc_parity)
+ {
+ set_parity(mcs51_state);
+ mcs51_state->recalc_parity = 0;
+ }
+
+ switch( op )
+ {
+
+ case 0x00: nop(mcs51_state, op); break; //NOP
+ case 0x01: ajmp(mcs51_state, op); break; //AJMP code addr
+ case 0x02: ljmp(mcs51_state, op); break; //LJMP code addr
+ case 0x03: rr_a(mcs51_state, op); break; //RR A
+ case 0x04: inc_a(mcs51_state, op); break; //INC A
+ case 0x05: RWM=1; inc_mem(mcs51_state, op); RWM=0; break; //INC data addr
+
+ case 0x06:
+ case 0x07: inc_ir(mcs51_state,op&1); break; //INC @R0/@R1
+
+ case 0x08:
+ case 0x09:
+ case 0x0a:
+ case 0x0b:
+ case 0x0c:
+ case 0x0d:
+ case 0x0e:
+ case 0x0f: inc_r(mcs51_state, op&7); break; //INC R0 to R7
+
+ case 0x10: RWM=1; jbc(mcs51_state, op); RWM=0; break; //JBC bit addr, code addr
+ case 0x11: acall(mcs51_state, op); break; //ACALL code addr
+ case 0x12: lcall(mcs51_state, op); break; //LCALL code addr
+ case 0x13: rrc_a(mcs51_state, op); break; //RRC A
+ case 0x14: dec_a(mcs51_state, op); break; //DEC A
+ case 0x15: RWM=1; dec_mem(mcs51_state, op); RWM=0; break; //DEC data addr
+
+ case 0x16:
+ case 0x17: dec_ir(mcs51_state, op&1); break; //DEC @R0/@R1
+
+ case 0x18:
+ case 0x19:
+ case 0x1a:
+ case 0x1b:
+ case 0x1c:
+ case 0x1d:
+ case 0x1e:
+ case 0x1f: dec_r(mcs51_state, op&7); break; //DEC R0 to R7
+
+ case 0x20: jb(mcs51_state, op); break; //JB bit addr, code addr
+ case 0x21: ajmp(mcs51_state, op); break; //AJMP code addr
+ case 0x22: ret(mcs51_state, op); break; //RET
+ case 0x23: rl_a(mcs51_state, op); break; //RL A
+ case 0x24: add_a_byte(mcs51_state, op); break; //ADD A, #data
+ case 0x25: add_a_mem(mcs51_state, op); break; //ADD A, data addr
+
+ case 0x26:
+ case 0x27: add_a_ir(mcs51_state, op&1); break; //ADD A, @R0/@R1
+
+ case 0x28:
+ case 0x29:
+ case 0x2a:
+ case 0x2b:
+ case 0x2c:
+ case 0x2d:
+ case 0x2e:
+ case 0x2f: add_a_r(mcs51_state, op&7); break; //ADD A, R0 to R7
+
+ case 0x30: jnb(mcs51_state, op); break; //JNB bit addr, code addr
+ case 0x31: acall(mcs51_state, op); break; //ACALL code addr
+ case 0x32: reti(mcs51_state, op); break; //RETI
+ case 0x33: rlc_a(mcs51_state, op); break; //RLC A
+ case 0x34: addc_a_byte(mcs51_state, op); break; //ADDC A, #data
+ case 0x35: addc_a_mem(mcs51_state, op); break; //ADDC A, data addr
+
+ case 0x36:
+ case 0x37: addc_a_ir(mcs51_state, op&1); break; //ADDC A, @R0/@R1
+
+ case 0x38:
+ case 0x39:
+ case 0x3a:
+ case 0x3b:
+ case 0x3c:
+ case 0x3d:
+ case 0x3e:
+ case 0x3f: addc_a_r(mcs51_state, op&7); break; //ADDC A, R0 to R7
+
+ case 0x40: jc(mcs51_state, op); break; //JC code addr
+ case 0x41: ajmp(mcs51_state, op); break; //AJMP code addr
+ case 0x42: RWM=1; orl_mem_a(mcs51_state, op); RWM=0; break; //ORL data addr, A
+ case 0x43: RWM=1; orl_mem_byte(mcs51_state, op); RWM=0; break; //ORL data addr, #data
+ case 0x44: orl_a_byte(mcs51_state, op); break;
+ case 0x45: orl_a_mem(mcs51_state, op); break; //ORL A, data addr
+
+ case 0x46:
+ case 0x47: orl_a_ir(mcs51_state, op&1); break; //ORL A, @RO/@R1
+
+ case 0x48:
+ case 0x49:
+ case 0x4a:
+ case 0x4b:
+ case 0x4c:
+ case 0x4d:
+ case 0x4e:
+ case 0x4f: orl_a_r(mcs51_state, op&7); break; //ORL A, RO to R7
+
+ case 0x50: jnc(mcs51_state, op); break; //JNC code addr
+ case 0x51: acall(mcs51_state, op); break; //ACALL code addr
+ case 0x52: RWM=1; anl_mem_a(mcs51_state, op); RWM=0; break; //ANL data addr, A
+ case 0x53: RWM=1; anl_mem_byte(mcs51_state, op); RWM=0; break; //ANL data addr, #data
+ case 0x54: anl_a_byte(mcs51_state, op); break; //ANL A, #data
+ case 0x55: anl_a_mem(mcs51_state, op); break; //ANL A, data addr
+
+ case 0x56:
+ case 0x57: anl_a_ir(mcs51_state, op&1); break; //ANL A, @RO/@R1
+
+ case 0x58:
+ case 0x59:
+ case 0x5a:
+ case 0x5b:
+ case 0x5c:
+ case 0x5d:
+ case 0x5e:
+ case 0x5f: anl_a_r(mcs51_state, op&7); break; //ANL A, RO to R7
+
+ case 0x60: jz(mcs51_state, op); break; //JZ code addr
+ case 0x61: ajmp(mcs51_state, op); break; //AJMP code addr
+ case 0x62: RWM=1; xrl_mem_a(mcs51_state, op); RWM=0; break; //XRL data addr, A
+ case 0x63: RWM=1; xrl_mem_byte(mcs51_state, op); RWM=0; break; //XRL data addr, #data
+ case 0x64: xrl_a_byte(mcs51_state, op); break; //XRL A, #data
+ case 0x65: xrl_a_mem(mcs51_state, op); break; //XRL A, data addr
+
+ case 0x66:
+ case 0x67: xrl_a_ir(mcs51_state, op&1); break; //XRL A, @R0/@R1
+
+ case 0x68:
+ case 0x69:
+ case 0x6a:
+ case 0x6b:
+ case 0x6c:
+ case 0x6d:
+ case 0x6e:
+ case 0x6f: xrl_a_r(mcs51_state, op&7); break; //XRL A, R0 to R7
+
+ case 0x70: jnz(mcs51_state, op); break; //JNZ code addr
+ case 0x71: acall(mcs51_state, op); break; //ACALL code addr
+ case 0x72: orl_c_bitaddr(mcs51_state, op); break; //ORL C, bit addr
+ case 0x73: jmp_iadptr(mcs51_state, op); break; //JMP @A+DPTR
+ case 0x74: mov_a_byte(mcs51_state, op); break; //MOV A, #data
+ case 0x75: mov_mem_byte(mcs51_state, op); break; //MOV data addr, #data
+
+ case 0x76:
+ case 0x77: mov_ir_byte(mcs51_state, op&1); break; //MOV @R0/@R1, #data
+
+ case 0x78:
+ case 0x79:
+ case 0x7a:
+ case 0x7b:
+ case 0x7c:
+ case 0x7d:
+ case 0x7e:
+ case 0x7f: mov_r_byte(mcs51_state, op&7); break; //MOV R0 to R7, #data
+
+ case 0x80: sjmp(mcs51_state, op); break; //SJMP code addr
+ case 0x81: ajmp(mcs51_state, op); break; //AJMP code addr
+ case 0x82: anl_c_bitaddr(mcs51_state, op); break; //ANL C, bit addr
+ case 0x83: movc_a_iapc(mcs51_state, op); break; //MOVC A, @A + PC
+ case 0x84: div_ab(mcs51_state, op); break; //DIV AB
+ case 0x85: mov_mem_mem(mcs51_state, op); break; //MOV data addr, data addr
+
+ case 0x86:
+ case 0x87: mov_mem_ir(mcs51_state, op&1); break; //MOV data addr, @R0/@R1
+
+ case 0x88:
+ case 0x89:
+ case 0x8a:
+ case 0x8b:
+ case 0x8c:
+ case 0x8d:
+ case 0x8e:
+ case 0x8f: mov_mem_r(mcs51_state, op&7); break; //MOV data addr,R0 to R7
+
+ case 0x90: mov_dptr_byte(mcs51_state, op); break; //MOV DPTR, #data
+ case 0x91: acall(mcs51_state, op); break; //ACALL code addr
+ case 0x92: RWM = 1; mov_bitaddr_c(mcs51_state, op); RWM = 0; break; //MOV bit addr, C
+ case 0x93: movc_a_iadptr(mcs51_state, op); break; //MOVC A, @A + DPTR
+ case 0x94: subb_a_byte(mcs51_state, op); break; //SUBB A, #data
+ case 0x95: subb_a_mem(mcs51_state, op); break; //SUBB A, data addr
+
+ case 0x96:
+ case 0x97: subb_a_ir(mcs51_state, op&1); break; //SUBB A, @R0/@R1
+
+ case 0x98:
+ case 0x99:
+ case 0x9a:
+ case 0x9b:
+ case 0x9c:
+ case 0x9d:
+ case 0x9e:
+ case 0x9f: subb_a_r(mcs51_state, op&7); break; //SUBB A, R0 to R7
+
+ case 0xa0: orl_c_nbitaddr(mcs51_state, op); break; //ORL C, /bit addr
+ case 0xa1: ajmp(mcs51_state, op); break; //AJMP code addr
+ case 0xa2: mov_c_bitaddr(mcs51_state, op); break; //MOV C, bit addr
+ case 0xa3: inc_dptr(mcs51_state, op); break; //INC DPTR
+ case 0xa4: mul_ab(mcs51_state, op); break; //MUL AB
+ case 0xa5: illegal(mcs51_state, op); break; //reserved
+
+ case 0xa6:
+ case 0xa7: mov_ir_mem(mcs51_state, op&1); break; //MOV @R0/@R1, data addr
+
+ case 0xa8:
+ case 0xa9:
+ case 0xaa:
+ case 0xab:
+ case 0xac:
+ case 0xad:
+ case 0xae:
+ case 0xaf: mov_r_mem(mcs51_state, op&7); break; //MOV R0 to R7, data addr
+
+ case 0xb0: anl_c_nbitaddr(mcs51_state, op); break; //ANL C,/bit addr
+ case 0xb1: acall(mcs51_state, op); break; //ACALL code addr
+ case 0xb2: RWM=1; cpl_bitaddr(mcs51_state, op); RWM=0; break; //CPL bit addr
+ case 0xb3: cpl_c(mcs51_state, op); break; //CPL C
+ case 0xb4: cjne_a_byte(mcs51_state, op); break; //CJNE A, #data, code addr
+ case 0xb5: cjne_a_mem(mcs51_state, op); break; //CJNE A, data addr, code addr
+
+ case 0xb6:
+ case 0xb7: cjne_ir_byte(mcs51_state, op&1); break; //CJNE @R0/@R1, #data, code addr
+
+ case 0xb8:
+ case 0xb9:
+ case 0xba:
+ case 0xbb:
+ case 0xbc:
+ case 0xbd:
+ case 0xbe:
+ case 0xbf: cjne_r_byte(mcs51_state, op&7); break; //CJNE R0 to R7, #data, code addr
+
+ case 0xc0: push(mcs51_state, op); break; //PUSH data addr
+ case 0xc1: ajmp(mcs51_state, op); break; //AJMP code addr
+ case 0xc2: RWM=1; clr_bitaddr(mcs51_state, op); RWM=0; break; //CLR bit addr
+ case 0xc3: clr_c(mcs51_state, op); break; //CLR C
+ case 0xc4: swap_a(mcs51_state, op); break; //SWAP A
+ case 0xc5: xch_a_mem(mcs51_state, op); break; //XCH A, data addr
+
+ case 0xc6:
+ case 0xc7: xch_a_ir(mcs51_state, op&1); break; //XCH A, @RO/@R1
+
+ case 0xc8:
+ case 0xc9:
+ case 0xca:
+ case 0xcb:
+ case 0xcc:
+ case 0xcd:
+ case 0xce:
+ case 0xcf: xch_a_r(mcs51_state, op&7); break; //XCH A, RO to R7
+
+ case 0xd0: pop(mcs51_state, op); break; //POP data addr
+ case 0xd1: acall(mcs51_state, op); break; //ACALL code addr
+ case 0xd2: RWM=1; setb_bitaddr(mcs51_state, op); RWM=0; break; //SETB bit addr
+ case 0xd3: setb_c(mcs51_state, op); break; //SETB C
+ case 0xd4: da_a(mcs51_state, op); break; //DA A
+ case 0xd5: RWM=1; djnz_mem(mcs51_state, op); RWM=0; break; //DJNZ data addr, code addr
+
+ case 0xd6:
+ case 0xd7: xchd_a_ir(mcs51_state, op&1); break; //XCHD A, @R0/@R1
+
+ case 0xd8:
+ case 0xd9:
+ case 0xda:
+ case 0xdb:
+ case 0xdc:
+ case 0xdd:
+ case 0xde:
+ case 0xdf: djnz_r(mcs51_state, op&7); break; //DJNZ R0 to R7,code addr
+
+ case 0xe0: movx_a_idptr(mcs51_state, op); break; //MOVX A,@DPTR
+ case 0xe1: ajmp(mcs51_state, op); break; //AJMP code addr
+
+ case 0xe2:
+ case 0xe3: movx_a_ir(mcs51_state, op&1); break; //MOVX A, @R0/@R1
+
+ case 0xe4: clr_a(mcs51_state, op); break; //CLR A
+ case 0xe5: mov_a_mem(mcs51_state, op); break; //MOV A, data addr
+ case 0xe6:
+ case 0xe7: mov_a_ir(mcs51_state, op&1); break; //MOV A,@RO/@R1
+
+ case 0xe8:
+ case 0xe9:
+ case 0xea:
+ case 0xeb:
+ case 0xec:
+ case 0xed:
+ case 0xee:
+ case 0xef: mov_a_r(mcs51_state, op&7); break; //MOV A,R0 to R7
+
+ case 0xf0: movx_idptr_a(mcs51_state, op); break; //MOVX @DPTR,A
+ case 0xf1: acall(mcs51_state, op); break; //ACALL code addr
+
+ case 0xf2:
+ case 0xf3: movx_ir_a(mcs51_state, op&1); break; //MOVX @R0/@R1,A
+
+ case 0xf4: cpl_a(mcs51_state, op); break; //CPL A
+ case 0xf5: mov_mem_a(mcs51_state, op); break; //MOV data addr, A
+
+ case 0xf6:
+ case 0xf7: mov_ir_a(mcs51_state, op&1); break; //MOV @R0/@R1, A
+
+ case 0xf8:
+ case 0xf9:
+ case 0xfa:
+ case 0xfb:
+ case 0xfc:
+ case 0xfd:
+ case 0xfe:
+ case 0xff: mov_r_a(mcs51_state, op&7); break; //MOV R0 to R7, A
+ default:
+ illegal(mcs51_state, op);
+ }
+}
+
+/***************************************************************************
+ OPCODE CYCLES
+***************************************************************************/
+
+/* # of oscilations each opcode requires*/
+static const UINT8 mcs51_cycles[] = {
+ 1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,2,2,1,2,1,1,1,1,1,1,1,1,1,1,
+ 2,2,2,2,4,2,2,2,2,2,2,2,2,2,2,2,
+ 2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,1,2,4,1,2,2,2,2,2,2,2,2,2,2,
+ 2,2,1,1,2,2,2,2,2,2,2,2,2,2,2,2,
+ 2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,1,1,1,2,1,1,2,2,2,2,2,2,2,2,
+ 2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1
+};
+
+/***********************************************************************************
+ Check for pending Interrupts and process - returns # of cycles used for the int
+
+ Note about priority & interrupting interrupts..
+ 1) A high priority interrupt cannot be interrupted by anything!
+ 2) A low priority interrupt can ONLY be interrupted by a high priority interrupt
+ 3) If more than 1 Interrupt Flag is set (ie, 2 simultaneous requests occur),
+ the following logic works as follows:
+ 1) If two requests come in of different priority levels, the higher one is selected..
+ 2) If the requests are of the same level, an internal order is used:
+ a) IEO
+ b) TFO
+ c) IE1
+ d) TF1
+ e) RI+TI
+ f) TF2+EXF2
+ **********************************************************************************/
+static void check_irqs(mcs51_state_t *mcs51_state)
+{
+ UINT8 ints = (GET_IE0 | (GET_TF0<<1) | (GET_IE1<<2) | (GET_TF1<<3)
+ | ((GET_RI|GET_TI)<<4));
+ UINT8 int_vec = 0;
+ UINT8 int_mask = 0;
+ int priority_request = -1;
+ int i;
+
+ //If All Inerrupts Disabled or no pending abort..
+ int_mask = (GET_EA ? IE : 0x00);
+
+ if (mcs51_state->features & FEATURE_I8052)
+ ints |= ((GET_TF2|GET_EXF2)<<5);
+
+ if (mcs51_state->features & FEATURE_DS5002FP)
+ {
+ ints |= ((GET_PFW)<<5);
+ mcs51_state->irq_prio[6] = 3; /* force highest priority */
+ /* mask out interrupts not enabled */
+ ints &= ((int_mask & 0x1f) | ((GET_EPFW)<<5));
+ }
+ else
+ {
+ /* mask out interrupts not enabled */
+ ints &= int_mask;
+ }
+
+ if (!ints) return;
+
+ /* CLear IDL - got enabled interrupt */
+ if (mcs51_state->features & FEATURE_CMOS)
+ {
+ /* any interrupt terminates idle mode */
+ SET_IDL(0);
+ /* external interrupt wakes up */
+ if (ints & (GET_IE0 | GET_IE1))
+ /* but not the DS5002FP */
+ if (!(mcs51_state->features & FEATURE_DS5002FP))
+ SET_PD(0);
+ }
+
+ for (i=0; i<mcs51_state->num_interrupts; i++)
+ {
+ if (ints & (1<<i))
+ {
+ if (mcs51_state->irq_prio[i] > priority_request)
+ {
+ priority_request = mcs51_state->irq_prio[i];
+ int_vec = (i<<3) | 3;
+ }
+ }
+ }
+
+ /* Skip the interrupt request if currently processing interrupt
+ * and the new request does not have a higher priority
+ */
+
+ LOG(("Request: %d\n", priority_request));
+ if (mcs51_state->irq_active && (priority_request <= mcs51_state->cur_irq_prio))
+ {
+ LOG(("higher or equal priority irq in progress already, skipping ...\n"));
+ return;
+ }
+
+ /* also break out of jb int0,<self> loops */
+ if (ROP(PC) == 0x20 && ROP_ARG(PC+1) == 0xb2 && ROP_ARG(PC+2) == 0xfd)
+ PC += 3;
+
+ //Save current pc to stack, set pc to new interrupt vector
+ push_pc(mcs51_state);
+ PC = int_vec;
+
+ /* interrupts take 24 cycles */
+ mcs51_state->inst_cycles += 2;
+
+ //Set current Irq & Priority being serviced
+ mcs51_state->cur_irq_prio = priority_request;
+ mcs51_state->irq_active |= (1 << priority_request);
+
+ LOG(("Take: %d %02x\n", mcs51_state->cur_irq_prio, mcs51_state->irq_active));
+
+ //Clear any interrupt flags that should be cleared since we're servicing the irq!
+ switch(int_vec) {
+ case V_IE0:
+ //External Int Flag only cleared when configured as Edge Triggered..
+ if(GET_IT0) /* for some reason having this, breaks alving dmd games */
+ SET_IE0(0);
+
+ /* indicate we took the external IRQ */
+ if (mcs51_state->irq_callback != NULL)
+ (*mcs51_state->irq_callback)(mcs51_state->device, 0);
+
+ break;
+ case V_TF0:
+ //Timer 0 - Always clear Flag
+ SET_TF0(0);
+ break;
+ case V_IE1:
+ //External Int Flag only cleared when configured as Edge Triggered..
+ if(GET_IT1) /* for some reason having this, breaks alving dmd games */
+ SET_IE1(0);
+ /* indicate we took the external IRQ */
+ if (mcs51_state->irq_callback != NULL)
+ (*mcs51_state->irq_callback)(mcs51_state->device, 1);
+
+ break;
+ case V_TF1:
+ //Timer 1 - Always clear Flag
+ SET_TF1(0);
+ break;
+ case V_RITI:
+ /* no flags are cleared, TI and RI remain set until reset by software */
+ break;
+ /* I8052 specific */
+ case V_TF2:
+ /* no flags are cleared according to manual */
+ break;
+ /* DS5002FP specific */
+ /* case V_PFI:
+ * no flags are cleared, PFW is reset by software
+ * This has the same vector as V_TF2.
+ */
+
+ }
+}
+
+INLINE void burn_cycles(mcs51_state_t *mcs51_state, int cycles)
+{
+ /* Update Timer (if any timers are running) */
+ update_timers(mcs51_state, cycles);
+
+ /* Update Serial (only for mode 0) */
+ update_serial(mcs51_state, cycles);
+
+ /* check_irqs */
+ check_irqs(mcs51_state);
+}
+
+static void mcs51_set_irq_line(mcs51_state_t *mcs51_state, int irqline, int state)
+{
+ /* From the manual:
+ *
+ * <cite>In operation all the interrupt flags are latched into the
+ * interrupt control system during State 5 of every machine cycle.
+ * The samples are polled during the following machine cycle.</cite>
+ *
+ * ==> Since we do not emulate sub-states, this assumes that the signal is present
+ * for at least one cycle (12 states)
+ *
+ */
+ UINT32 new_state = (mcs51_state->last_line_state & ~(1 << irqline)) | ((state != CLEAR_LINE) << irqline);
+ /* detect 0->1 transistions */
+ UINT32 tr_state = (~mcs51_state->last_line_state) & new_state;
+
+ switch( irqline )
+ {
+ //External Interrupt 0
+ case MCS51_INT0_LINE:
+ //Line Asserted?
+ if (state != CLEAR_LINE) {
+ //Need cleared->active line transition? (Logical 1-0 Pulse on the line) - CLEAR->ASSERT Transition since INT0 active lo!
+ if (GET_IT0) {
+ if (GET_BIT(tr_state, MCS51_INT0_LINE))
+ SET_IE0(1);
+ }
+ else
+ SET_IE0(1); //Nope, just set it..
+ }
+ else
+ {
+ if (!GET_IT0) /* clear if level triggered */
+ SET_IE0(0);
+ }
+
+ break;
+
+ //External Interrupt 1
+ case MCS51_INT1_LINE:
+
+ //Line Asserted?
+ if (state != CLEAR_LINE) {
+ //Need cleared->active line transition? (Logical 1-0 Pulse on the line) - CLEAR->ASSERT Transition since INT1 active lo!
+ if(GET_IT1){
+ if (GET_BIT(tr_state, MCS51_INT1_LINE))
+ SET_IE1(1);
+ }
+ else
+ SET_IE1(1); //Nope, just set it..
+ }
+ else
+ {
+ if (!GET_IT1) /* clear if level triggered */
+ SET_IE1(0);
+ }
+ break;
+
+ case MCS51_T0_LINE:
+ if (GET_BIT(tr_state, MCS51_T0_LINE) && GET_TR0)
+ mcs51_state->t0_cnt++;
+ break;
+
+ case MCS51_T1_LINE:
+ if (GET_BIT(tr_state, MCS51_T1_LINE) && GET_TR1)
+ mcs51_state->t1_cnt++;
+ break;
+
+ case MCS51_T2_LINE:
+ if (mcs51_state->features & FEATURE_I8052)
+ {
+ if (GET_BIT(tr_state, MCS51_T2_LINE) && GET_TR1)
+ mcs51_state->t2_cnt++;
+ }
+ else
+ fatalerror("mcs51: Trying to set T2_LINE on a non I8052 type cpu.\n");
+ break;
+
+ case MCS51_T2EX_LINE:
+ if (mcs51_state->features & FEATURE_I8052)
+ {
+ if (GET_BIT(tr_state, MCS51_T2EX_LINE))
+ {
+ SET_EXF2(1);
+ mcs51_state->t2ex_cnt++;
+ }
+ }
+ else
+ fatalerror("mcs51: Trying to set T2EX_LINE on a non I8052 type cpu.\n");
+ break;
+
+ case MCS51_RX_LINE: /* Serial Port Receive */
+ /* Is the enable flags for this interrupt set? */
+ if (state != CLEAR_LINE)
+ {
+ serial_receive(mcs51_state);
+ }
+ break;
+
+ /* Power Fail Interrupt */
+ case DS5002FP_PFI_LINE:
+ if (mcs51_state->features & FEATURE_DS5002FP)
+ {
+ /* Need cleared->active line transition? (Logical 1-0 Pulse on the line) - CLEAR->ASSERT Transition since INT1 active lo! */
+ if (GET_BIT(tr_state, MCS51_INT1_LINE))
+ SET_PFW(1);
+ }
+ else
+ fatalerror("mcs51: Trying to set DS5002FP_PFI_LINE on a non DS5002FP type cpu.\n");
+ break;
+ }
+ mcs51_state->last_line_state = new_state;
+}
+
+/* Execute cycles - returns number of cycles actually run */
+static CPU_EXECUTE( mcs51 )
+{
+ mcs51_state_t *mcs51_state = get_safe_token(device);
+ UINT8 op;
+
+ update_ptrs(mcs51_state);
+
+ /* external interrupts may have been set since we last checked */
+ mcs51_state->inst_cycles = 0;
+ check_irqs(mcs51_state);
+
+ /* if in powerdown, just return */
+ if ((mcs51_state->features & FEATURE_CMOS) && GET_PD)
+ {
+ mcs51_state->icount = 0;
+ return;
+ }
+
+ mcs51_state->icount -= mcs51_state->inst_cycles;
+ burn_cycles(mcs51_state, mcs51_state->inst_cycles);
+
+ if ((mcs51_state->features & FEATURE_CMOS) && GET_IDL)
+ {
+ do
+ {
+ /* burn the cycles */
+ mcs51_state->icount--;
+ burn_cycles(mcs51_state, 1);
+ } while( mcs51_state->icount > 0 );
+ return;
+ }
+
+ do
+ {
+ /* Read next opcode */
+ PPC = PC;
+ debugger_instruction_hook(device, PC);
+ op = mcs51_state->direct->read_decrypted_byte(PC++);
+
+ /* process opcode and count cycles */
+ mcs51_state->inst_cycles = mcs51_cycles[op];
+ execute_op(mcs51_state, op);
+
+ /* burn the cycles */
+ mcs51_state->icount -= mcs51_state->inst_cycles;
+
+ /* if in powerdown, just return */
+ if ((mcs51_state->features & FEATURE_CMOS) && GET_PD)
+ return;
+
+ burn_cycles(mcs51_state, mcs51_state->inst_cycles);
+
+ /* decrement the timed access window */
+ if (mcs51_state->features & FEATURE_DS5002FP)
+ mcs51_state->ds5002fp.ta_window = (mcs51_state->ds5002fp.ta_window ? (mcs51_state->ds5002fp.ta_window - 1) : 0x00);
+
+ /* If the chip entered in idle mode, end the loop */
+ if ((mcs51_state->features & FEATURE_CMOS) && GET_IDL)
+ return;
+
+ } while( mcs51_state->icount > 0 );
+}
+
+
+/****************************************************************************
+ * MCS51/8051 Section
+ ****************************************************************************/
+
+static void mcs51_sfr_write(mcs51_state_t *mcs51_state, size_t offset, UINT8 data)
+{
+ /* update register */
+ assert(offset >= 0x80 && offset <= 0xff);
+
+ switch (offset)
+ {
+ case ADDR_P0: OUT(MCS51_PORT_P0,data); break;
+ case ADDR_P1: OUT(MCS51_PORT_P1,data); break;
+ case ADDR_P2: OUT(MCS51_PORT_P2,data); break;
+ case ADDR_P3: OUT(MCS51_PORT_P3,data); break;
+ case ADDR_SBUF: serial_transmit(mcs51_state, data); break;
+ case ADDR_PSW: SET_PARITY(); break;
+ case ADDR_ACC: SET_PARITY(); break;
+ case ADDR_IP: update_irq_prio(mcs51_state, data, 0); break;
+ /* R_SBUF = data; //This register is used only for "Receiving data coming in!" */
+
+ case ADDR_B:
+ case ADDR_SP:
+ case ADDR_DPL:
+ case ADDR_DPH:
+ case ADDR_PCON:
+ case ADDR_TCON:
+ case ADDR_TMOD:
+ case ADDR_IE:
+ case ADDR_TL0:
+ case ADDR_TL1:
+ case ADDR_TH0:
+ case ADDR_TH1:
+ case ADDR_SCON:
+ break;
+ default:
+ LOG(("mcs51 '%s': attemping to write to an invalid/non-implemented SFR address: %x at 0x%04x, data=%x\n", mcs51_state->device->tag(), (UINT32)offset,PC,data));
+ /* no write in this case according to manual */
+ return;
+ }
+ mcs51_state->data->write_byte((size_t)offset | 0x100, data);
+}
+
+static UINT8 mcs51_sfr_read(mcs51_state_t *mcs51_state, size_t offset)
+{
+ assert(offset >= 0x80 && offset <= 0xff);
+
+ switch (offset)
+ {
+ /* Read/Write/Modify operations read the port latch ! */
+ /* Move to memory map */
+ case ADDR_P0: return RWM ? P0 : P0 & IN(MCS51_PORT_P0);
+ case ADDR_P1: return RWM ? P1 : P1 & IN(MCS51_PORT_P1);
+ case ADDR_P2: return RWM ? P2 : P2 & IN(MCS51_PORT_P2);
+ case ADDR_P3: return RWM ? P3 : P3 & IN(MCS51_PORT_P3);
+
+ case ADDR_PSW:
+ case ADDR_ACC:
+ case ADDR_B:
+ case ADDR_SP:
+ case ADDR_DPL:
+ case ADDR_DPH:
+ case ADDR_PCON:
+ case ADDR_TCON:
+ case ADDR_TMOD:
+ case ADDR_TL0:
+ case ADDR_TL1:
+ case ADDR_TH0:
+ case ADDR_TH1:
+ case ADDR_SCON:
+ case ADDR_SBUF:
+ case ADDR_IE:
+ case ADDR_IP:
+ return mcs51_state->data->read_byte((size_t) offset | 0x100);
+ /* Illegal or non-implemented sfr */
+ default:
+ LOG(("mcs51 '%s': attemping to read an invalid/non-implemented SFR address: %x at 0x%04x\n", mcs51_state->device->tag(), (UINT32)offset,PC));
+ /* according to the manual, the read may return random bits */
+ return 0xff;
+ }
+}
+
+
+static CPU_INIT( mcs51 )
+{
+ mcs51_state_t *mcs51_state = get_safe_token(device);
+
+ mcs51_state->irq_callback = irqcallback;
+ mcs51_state->device = device;
+
+ mcs51_state->program = device->space(AS_PROGRAM);
+ mcs51_state->direct = &mcs51_state->program->direct();
+ mcs51_state->data = device->space(AS_DATA);
+ mcs51_state->io = device->space(AS_IO);
+
+ mcs51_state->features = FEATURE_NONE;
+ mcs51_state->ram_mask = 0x7F; /* 128 bytes of ram */
+ mcs51_state->num_interrupts = 5; /* 5 interrupts */
+ mcs51_state->sfr_read = mcs51_sfr_read;
+ mcs51_state->sfr_write = mcs51_sfr_write;
+
+ /* ensure these pointers are set before get_info is called */
+ update_ptrs(mcs51_state);
+
+ /* Save states */
+
+ device->save_item(NAME(mcs51_state->ppc));
+ device->save_item(NAME(mcs51_state->pc));
+ device->save_item(NAME(mcs51_state->rwm) );
+ device->save_item(NAME(mcs51_state->cur_irq_prio) );
+ device->save_item(NAME(mcs51_state->last_line_state) );
+ device->save_item(NAME(mcs51_state->t0_cnt) );
+ device->save_item(NAME(mcs51_state->t1_cnt) );
+ device->save_item(NAME(mcs51_state->t2_cnt) );
+ device->save_item(NAME(mcs51_state->t2ex_cnt) );
+ device->save_item(NAME(mcs51_state->recalc_parity) );
+ device->save_item(NAME(mcs51_state->irq_prio) );
+ device->save_item(NAME(mcs51_state->irq_active) );
+}
+
+static CPU_INIT( i80c51 )
+{
+ mcs51_state_t *mcs51_state = get_safe_token(device);
+ CPU_INIT_CALL(mcs51);
+ mcs51_state->features |= FEATURE_CMOS;
+}
+
+/* Reset registers to the initial values */
+static CPU_RESET( mcs51 )
+{
+ mcs51_state_t *mcs51_state = get_safe_token(device);
+
+ update_ptrs(mcs51_state);
+
+ mcs51_state->last_line_state = 0;
+ mcs51_state->t0_cnt = 0;
+ mcs51_state->t1_cnt = 0;
+ mcs51_state->t2_cnt = 0;
+ mcs51_state->t2ex_cnt = 0;
+ /* Flag as NO IRQ in Progress */
+ mcs51_state->irq_active = 0;
+ mcs51_state->cur_irq_prio = -1;
+
+ /* these are all defined reset states */
+ PC = 0;
+ SP = 0x7;
+ SET_PSW(0);
+ SET_ACC(0);
+ DPH = 0;
+ DPL = 0;
+ B = 0;
+ IP = 0;
+ update_irq_prio(mcs51_state, IP, 0);
+ IE = 0;
+ SCON = 0;
+ TCON = 0;
+ TMOD = 0;
+ PCON = 0;
+ TH1 = 0;
+ TH0 = 0;
+ TL1 = 0;
+ TL0 = 0;
+ /* set the port configurations to all 1's */
+ SET_P3(0xff);
+ SET_P2(0xff);
+ SET_P1(0xff);
+ SET_P0(0xff);
+
+ /* 8052 Only registers */
+ if (mcs51_state->features & FEATURE_I8052)
+ {
+ T2CON = 0;
+ RCAP2L = 0;
+ RCAP2H = 0;
+ TL2 = 0;
+ TH2 = 0;
+ }
+
+ /* 80C52 Only registers */
+ if (mcs51_state->features & FEATURE_I80C52)
+ {
+ IPH = 0;
+ update_irq_prio(mcs51_state, IP, IPH);
+ SADDR = 0;
+ SADEN = 0;
+ }
+
+ /* DS5002FP Only registers */
+ if (mcs51_state->features & FEATURE_DS5002FP)
+ {
+ // set initial values (some of them are set using the bootstrap loader)
+ PCON = 0;
+ MCON = mcs51_state->ds5002fp.config->mcon & 0xfb;
+ RPCTL = mcs51_state->ds5002fp.config->rpctl & 0x01;
+ RPS = 0;
+ RNR = 0;
+ CRCR = mcs51_state->ds5002fp.config->crc & 0xf0;
+ CRCL = 0;
+ CRCH = 0;
+ TA = 0;
+
+ // set internal CPU state
+ mcs51_state->ds5002fp.previous_ta = 0;
+ mcs51_state->ds5002fp.ta_window = 0;
+ mcs51_state->ds5002fp.range = (GET_RG1 << 1) | GET_RG0;
+ }
+
+}
+
+/* Shut down CPU core */
+static CPU_EXIT( mcs51 )
+{
+ /* nothing to do */
+}
+
+/****************************************************************************
+ * 8052 Section
+ ****************************************************************************/
+
+static void i8052_sfr_write(mcs51_state_t *mcs51_state, size_t offset, UINT8 data)
+{
+ switch (offset)
+ {
+ /* 8052 family specific */
+ case ADDR_T2CON:
+ case ADDR_RCAP2L:
+ case ADDR_RCAP2H:
+ case ADDR_TL2:
+ case ADDR_TH2:
+ mcs51_state->data->write_byte((size_t) offset | 0x100, data);
+ break;
+
+ default:
+ mcs51_sfr_write(mcs51_state, offset, data);
+ }
+}
+
+static UINT8 i8052_sfr_read(mcs51_state_t *mcs51_state, size_t offset)
+{
+ switch (offset)
+ {
+ /* 8052 family specific */
+ case ADDR_T2CON:
+ case ADDR_RCAP2L:
+ case ADDR_RCAP2H:
+ case ADDR_TL2:
+ case ADDR_TH2:
+ return mcs51_state->data->read_byte((size_t) offset | 0x100);
+ default:
+ return mcs51_sfr_read(mcs51_state, offset);
+ }
+}
+
+static CPU_INIT( i8052 )
+{
+ mcs51_state_t *mcs51_state = get_safe_token(device);
+ CPU_INIT_CALL(mcs51);
+
+ mcs51_state->ram_mask = 0xFF; /* 256 bytes of ram */
+ mcs51_state->num_interrupts = 6; /* 6 interrupts */
+
+ mcs51_state->features |= FEATURE_I8052;
+ mcs51_state->sfr_read = i8052_sfr_read;
+ mcs51_state->sfr_write = i8052_sfr_write;
+}
+
+/****************************************************************************
+ * 80C52 Section
+ ****************************************************************************/
+
+static void i80c52_sfr_write(mcs51_state_t *mcs51_state, size_t offset, UINT8 data)
+{
+ switch (offset)
+ {
+ /* 80c52 family specific */
+ case ADDR_IP:
+ update_irq_prio(mcs51_state, data, IPH);
+ break;
+ case ADDR_IPH:
+ update_irq_prio(mcs51_state, IP, data);
+ break;
+ case ADDR_SADDR:
+ case ADDR_SADEN:
+ break;
+
+ default:
+ i8052_sfr_write(mcs51_state, offset, data);
+ return;
+ }
+ mcs51_state->data->write_byte((size_t) offset | 0x100, data);
+}
+
+static UINT8 i80c52_sfr_read(mcs51_state_t *mcs51_state, size_t offset)
+{
+ switch (offset)
+ {
+ /* 80c52 family specific */
+ case ADDR_IPH:
+ case ADDR_SADDR:
+ case ADDR_SADEN:
+ return mcs51_state->data->read_byte((size_t) offset | 0x100);
+ default:
+ return i8052_sfr_read(mcs51_state, offset);
+ }
+}
+
+static CPU_INIT( i80c52 )
+{
+ mcs51_state_t *mcs51_state = get_safe_token(device);
+ CPU_INIT_CALL(i8052);
+
+ mcs51_state->features |= (FEATURE_I80C52 | FEATURE_CMOS);
+ mcs51_state->sfr_read = i80c52_sfr_read;
+ mcs51_state->sfr_write = i80c52_sfr_write;
+}
+
+static CPU_INIT( i80c31 )
+{
+ mcs51_state_t *mcs51_state = get_safe_token(device);
+ CPU_INIT_CALL(i8052);
+
+ mcs51_state->ram_mask = 0x7F; /* 128 bytes of ram */
+}
+
+/****************************************************************************
+ * DS5002FP Section
+ ****************************************************************************/
+
+
+#define DS5_LOGW(a, d) LOG(("ds5002fp '%s': write to " # a " register at 0x%04x, data=%x\n", mcs51_state->device->tag(), PC, d))
+#define DS5_LOGR(a, d) LOG(("ds5002fp '%s': read from " # a " register at 0x%04x\n", mcs51_state->device->tag(), PC))
+
+INLINE UINT8 ds5002fp_protected(mcs51_state_t *mcs51_state, size_t offset, UINT8 data, UINT8 ta_mask, UINT8 mask)
+{
+ UINT8 is_timed_access;
+
+ is_timed_access = (mcs51_state->ds5002fp.ta_window > 0) && (TA == 0x55);
+ if (is_timed_access)
+ {
+ ta_mask = 0xff;
+ }
+ data = (mcs51_state->sfr_ram[offset] & (~ta_mask)) | (data & ta_mask);
+ return (mcs51_state->sfr_ram[offset] & (~mask)) | (data & mask);
+}
+
+static void ds5002fp_sfr_write(mcs51_state_t *mcs51_state, size_t offset, UINT8 data)
+{
+ switch (offset)
+ {
+
+ case ADDR_TA:
+ mcs51_state->ds5002fp.previous_ta = TA;
+ /* init the time window after having wrote 0xaa */
+ if ((data == 0xaa) && (mcs51_state->ds5002fp.ta_window == 0))
+ {
+ mcs51_state->ds5002fp.ta_window = 6; /* 4*12 + 2*12 */
+ LOG(("ds5002fp '%s': TA window initiated at 0x%04x\n", mcs51_state->device->tag(), PC));
+ }
+ break;
+ case ADDR_MCON: data = ds5002fp_protected(mcs51_state, ADDR_MCON, data, 0x0f, 0xf7); DS5_LOGW(MCON, data); break;
+ case ADDR_RPCTL: data = ds5002fp_protected(mcs51_state, ADDR_RPCTL, data, 0xef, 0xfe); DS5_LOGW(RPCTL, data); break;
+ case ADDR_CRCR: data = ds5002fp_protected(mcs51_state, ADDR_CRCR, data, 0xff, 0x0f); DS5_LOGW(CRCR, data); break;
+ case ADDR_PCON: data = ds5002fp_protected(mcs51_state, ADDR_PCON, data, 0xb9, 0xff); break;
+ case ADDR_IP: data = ds5002fp_protected(mcs51_state, ADDR_IP, data, 0x7f, 0xff); break;
+ case ADDR_CRCL: DS5_LOGW(CRCL, data); break;
+ case ADDR_CRCH: DS5_LOGW(CRCH, data); break;
+ case ADDR_RNR: DS5_LOGW(RNR, data); break;
+ case ADDR_RPS: DS5_LOGW(RPS, data); break;
+ default:
+ mcs51_sfr_write(mcs51_state, offset, data);
+ return;
+ }
+ mcs51_state->data->write_byte((size_t) offset | 0x100, data);
+}
+
+static UINT8 ds5002fp_sfr_read(mcs51_state_t *mcs51_state, size_t offset)
+{
+ switch (offset)
+ {
+ case ADDR_CRCR: DS5_LOGR(CRCR, data); break;
+ case ADDR_CRCL: DS5_LOGR(CRCL, data); break;
+ case ADDR_CRCH: DS5_LOGR(CRCH, data); break;
+ case ADDR_MCON: DS5_LOGR(MCON, data); break;
+ case ADDR_TA: DS5_LOGR(TA, data); break;
+ case ADDR_RNR: DS5_LOGR(RNR, data); break;
+ case ADDR_RPCTL: DS5_LOGR(RPCTL, data); break;
+ case ADDR_RPS: DS5_LOGR(RPS, data); break;
+ case ADDR_PCON:
+ SET_PFW(0); /* reset PFW flag */
+ return mcs51_sfr_read(mcs51_state, offset);
+ default:
+ return mcs51_sfr_read(mcs51_state, offset);
+ }
+ return mcs51_state->data->read_byte((size_t) offset | 0x100);
+}
+
+static CPU_INIT( ds5002fp )
+{
+ /* default configuration */
+ static const ds5002fp_config default_config = { 0x00, 0x00, 0x00 };
+ const ds5002fp_config *sconfig = device->static_config() ? (const ds5002fp_config *)device->static_config() : &default_config;
+ mcs51_state_t *mcs51_state = get_safe_token(device);
+
+ CPU_INIT_CALL( mcs51 );
+
+ mcs51_state->ds5002fp.config = sconfig;
+ mcs51_state->features |= (FEATURE_DS5002FP | FEATURE_CMOS);
+ mcs51_state->sfr_read = ds5002fp_sfr_read;
+ mcs51_state->sfr_write = ds5002fp_sfr_write;
+
+ device->save_item(NAME(mcs51_state->ds5002fp.previous_ta) );
+ device->save_item(NAME(mcs51_state->ds5002fp.ta_window) );
+ device->save_item(NAME(mcs51_state->ds5002fp.range) );
+
+}
+
+/***************************************************************************
+ ADDRESS MAPS
+***************************************************************************/
+
+static ADDRESS_MAP_START(program_12bit, AS_PROGRAM, 8)
+ AM_RANGE(0x00, 0x0fff) AM_ROM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START(program_13bit, AS_PROGRAM, 8)
+ AM_RANGE(0x00, 0x1fff) AM_ROM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START(data_7bit, AS_DATA, 8)
+ AM_RANGE(0x0000, 0x007f) AM_RAM
+ AM_RANGE(0x0100, 0x01ff) AM_RAM /* SFR */
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START(data_8bit, AS_DATA, 8)
+ AM_RANGE(0x0000, 0x00ff) AM_RAM
+ AM_RANGE(0x0100, 0x01ff) AM_RAM /* SFR */
+ADDRESS_MAP_END
+
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( mcs51 )
+{
+ mcs51_state_t *mcs51_state = get_safe_token(device);
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_PC: PC = info->i; break;
+ case CPUINFO_INT_SP: SP = info->i; break;
+
+ case CPUINFO_INT_INPUT_STATE + MCS51_INT0_LINE: mcs51_set_irq_line(mcs51_state, MCS51_INT0_LINE, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + MCS51_INT1_LINE: mcs51_set_irq_line(mcs51_state, MCS51_INT1_LINE, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + MCS51_T0_LINE: mcs51_set_irq_line(mcs51_state, MCS51_T0_LINE, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + MCS51_T1_LINE: mcs51_set_irq_line(mcs51_state, MCS51_T1_LINE, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + MCS51_RX_LINE: mcs51_set_irq_line(mcs51_state, MCS51_RX_LINE, info->i); break;
+
+ case CPUINFO_INT_REGISTER + MCS51_PC: PC = info->i; break;
+ case CPUINFO_INT_REGISTER + MCS51_SP: SP = info->i; break;
+ case CPUINFO_INT_REGISTER + MCS51_PSW: SET_PSW(info->i); break;
+ case CPUINFO_INT_REGISTER + MCS51_ACC: SET_ACC(info->i); break;
+ case CPUINFO_INT_REGISTER + MCS51_B: B = info->i; break;
+ case CPUINFO_INT_REGISTER + MCS51_DPH: DPH = info->i; break;
+ case CPUINFO_INT_REGISTER + MCS51_DPL: DPL = info->i; break;
+ case CPUINFO_INT_REGISTER + MCS51_IE: IE = info->i; break;
+ case CPUINFO_INT_REGISTER + MCS51_R0: SET_REG(0, info->i); break;
+ case CPUINFO_INT_REGISTER + MCS51_R1: SET_REG(1, info->i); break;
+ case CPUINFO_INT_REGISTER + MCS51_R2: SET_REG(2, info->i); break;
+ case CPUINFO_INT_REGISTER + MCS51_R3: SET_REG(3, info->i); break;
+ case CPUINFO_INT_REGISTER + MCS51_R4: SET_REG(4, info->i); break;
+ case CPUINFO_INT_REGISTER + MCS51_R5: SET_REG(5, info->i); break;
+ case CPUINFO_INT_REGISTER + MCS51_R6: SET_REG(6, info->i); break;
+ case CPUINFO_INT_REGISTER + MCS51_R7: SET_REG(7, info->i); break;
+ case CPUINFO_INT_REGISTER + MCS51_RB: SET_RS(info->i); break;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+static CPU_GET_INFO( mcs51 )
+{
+ mcs51_state_t *mcs51_state = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(mcs51_state_t); break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 12; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 5; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 20; /* rough guess */ break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 3; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 9; /* due to sfr mapping */ break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 18; /* 128k for ds5002fp */ break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = PPC; break;
+ case CPUINFO_INT_PC: info->i = PC; break;
+ case CPUINFO_INT_SP: info->i = SP; break;
+
+ case CPUINFO_INT_REGISTER + MCS51_PC: info->i = PC; break;
+ case CPUINFO_INT_REGISTER + MCS51_SP: info->i = SP; break;
+ case CPUINFO_INT_REGISTER + MCS51_PSW: info->i = PSW; break;
+ case CPUINFO_INT_REGISTER + MCS51_ACC: info->i = ACC; break;
+ case CPUINFO_INT_REGISTER + MCS51_B: info->i = B; break;
+ case CPUINFO_INT_REGISTER + MCS51_DPH: info->i = DPH; break;
+ case CPUINFO_INT_REGISTER + MCS51_DPL: info->i = DPL; break;
+ case CPUINFO_INT_REGISTER + MCS51_IE: info->i = IE; break;
+ case CPUINFO_INT_REGISTER + MCS51_R0: info->i = R_REG(0); break;
+ case CPUINFO_INT_REGISTER + MCS51_R1: info->i = R_REG(1); break;
+ case CPUINFO_INT_REGISTER + MCS51_R2: info->i = R_REG(2); break;
+ case CPUINFO_INT_REGISTER + MCS51_R3: info->i = R_REG(3); break;
+ case CPUINFO_INT_REGISTER + MCS51_R4: info->i = R_REG(4); break;
+ case CPUINFO_INT_REGISTER + MCS51_R5: info->i = R_REG(5); break;
+ case CPUINFO_INT_REGISTER + MCS51_R6: info->i = R_REG(6); break;
+ case CPUINFO_INT_REGISTER + MCS51_R7: info->i = R_REG(7); break;
+ case CPUINFO_INT_REGISTER + MCS51_RB: info->i = R_REG(8); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(mcs51); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(mcs51); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(mcs51); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(mcs51); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(mcs51); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(i8051); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &mcs51_state->icount; break;
+
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = NULL; break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = NULL; break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_IO: info->internal_map8 = NULL; break;
+
+ case DEVINFO_STR_NAME: strcpy(info->s, "I8051"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "MCS-51"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Steve Ellenoff"); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c%c%c%c%c%c%c",
+ PSW & 0x80 ? 'C':'.',
+ PSW & 0x40 ? 'A':'.',
+ PSW & 0x20 ? 'F':'.',
+ PSW & 0x10 ? '0':'.',
+ PSW & 0x08 ? '1':'.',
+ PSW & 0x04 ? 'V':'.',
+ PSW & 0x02 ? '?':'.',
+ PSW & 0x01 ? 'P':'.');
+ break;
+
+ case CPUINFO_STR_REGISTER + MCS51_PC: sprintf(info->s, "PC:%04X", mcs51_state->pc); break;
+ case CPUINFO_STR_REGISTER + MCS51_SP: sprintf(info->s, "SP:%02X", SP); break;
+ case CPUINFO_STR_REGISTER + MCS51_PSW: sprintf(info->s, "PSW:%02X", PSW); break;
+ case CPUINFO_STR_REGISTER + MCS51_ACC: sprintf(info->s, "A:%02X", ACC); break;
+ case CPUINFO_STR_REGISTER + MCS51_B: sprintf(info->s, "B:%02X", B); break;
+ case CPUINFO_STR_REGISTER + MCS51_DPH: sprintf(info->s, "DPH:%02X", DPH); break;
+ case CPUINFO_STR_REGISTER + MCS51_DPL: sprintf(info->s, "DPL:%02X", DPL); break;
+ case CPUINFO_STR_REGISTER + MCS51_IE: sprintf(info->s, "IE:%02X", IE); break;
+ case CPUINFO_STR_REGISTER + MCS51_R0: sprintf(info->s, "R0:%02X", R_REG(0)); break;
+ case CPUINFO_STR_REGISTER + MCS51_R1: sprintf(info->s, "R1:%02X", R_REG(1)); break;
+ case CPUINFO_STR_REGISTER + MCS51_R2: sprintf(info->s, "R2:%02X", R_REG(2)); break;
+ case CPUINFO_STR_REGISTER + MCS51_R3: sprintf(info->s, "R3:%02X", R_REG(3)); break;
+ case CPUINFO_STR_REGISTER + MCS51_R4: sprintf(info->s, "R4:%02X", R_REG(4)); break;
+ case CPUINFO_STR_REGISTER + MCS51_R5: sprintf(info->s, "R5:%02X", R_REG(5)); break;
+ case CPUINFO_STR_REGISTER + MCS51_R6: sprintf(info->s, "R6:%02X", R_REG(6)); break;
+ case CPUINFO_STR_REGISTER + MCS51_R7: sprintf(info->s, "R7:%02X", R_REG(7)); break;
+ case CPUINFO_STR_REGISTER + MCS51_RB: sprintf(info->s, "RB:%02X", ((PSW & 0x18)>>3)); break;
+ }
+}
+
+/**************************************************************************
+ * Specific get_info
+ **************************************************************************/
+
+CPU_GET_INFO( i8031 )
+{
+ switch (state)
+ {
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = ADDRESS_MAP_NAME(data_7bit); break;
+ case DEVINFO_STR_NAME: strcpy(info->s, "I8031"); break;
+ default: CPU_GET_INFO_CALL(mcs51); break;
+ }
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+}
+
+CPU_GET_INFO( i8051 )
+{
+ switch (state)
+ {
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME(program_12bit); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = ADDRESS_MAP_NAME(data_7bit); break;
+ case DEVINFO_STR_NAME: strcpy(info->s, "I8051"); break;
+ default: CPU_GET_INFO_CALL(mcs51); break;
+ }
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+}
+
+CPU_GET_INFO( i8032 )
+{
+ switch (state)
+ {
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(i8052); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = ADDRESS_MAP_NAME(data_8bit); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(i8052); break;
+ case DEVINFO_STR_NAME: strcpy(info->s, "I8032"); break;
+ default: CPU_GET_INFO_CALL(mcs51); break;
+ }
+}
+
+CPU_GET_INFO( i8052 )
+{
+ switch (state)
+ {
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(i8052); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME(program_13bit); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = ADDRESS_MAP_NAME(data_8bit); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(i8052); break;
+ case DEVINFO_STR_NAME: strcpy(info->s, "I8052"); break;
+ default: CPU_GET_INFO_CALL(mcs51); break;
+ }
+}
+
+CPU_GET_INFO( i8751 )
+{
+ switch (state)
+ {
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME(program_12bit); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = ADDRESS_MAP_NAME(data_7bit); break;
+ case DEVINFO_STR_NAME: strcpy(info->s, "I8751"); break;
+ default: CPU_GET_INFO_CALL(mcs51); break;
+ }
+}
+
+CPU_GET_INFO( i8752 )
+{
+ switch (state)
+ {
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(i8052); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME(program_13bit); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = ADDRESS_MAP_NAME(data_8bit); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(i8052); break;
+ case DEVINFO_STR_NAME: strcpy(info->s, "I8752"); break;
+ default: CPU_GET_INFO_CALL(mcs51); break;
+ }
+}
+
+/**************************************************************************
+ * CMOS get_info
+ **************************************************************************/
+
+CPU_GET_INFO( i80c31 )
+{
+ /* according to PHILIPS datasheet this is a stripped down version
+ * of i80c52 with 128 bytes internal ram */
+ switch (state)
+ {
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(i80c31); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = NULL; break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = ADDRESS_MAP_NAME(data_7bit); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(i80c51); break;
+ case DEVINFO_STR_NAME: strcpy(info->s, "I80C31"); break;
+ default: CPU_GET_INFO_CALL(i8031); break;
+ }
+}
+
+CPU_GET_INFO( i80c51 )
+{
+ switch (state)
+ {
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(i80c51); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(i80c51); break;
+ case DEVINFO_STR_NAME: strcpy(info->s, "I80C51"); break;
+ default: CPU_GET_INFO_CALL(i8051); break;
+ }
+}
+
+CPU_GET_INFO( i80c32 )
+{
+ switch (state)
+ {
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(i80c52); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(i80c52); break;
+ case DEVINFO_STR_NAME: strcpy(info->s, "I80C32"); break;
+ default: CPU_GET_INFO_CALL(i8032); break;
+ }
+}
+
+CPU_GET_INFO( i80c52 )
+{
+ switch (state)
+ {
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(i80c52); break;
+ case DEVINFO_STR_NAME: strcpy(info->s, "I80C52"); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(i80c52); break;
+ default: CPU_GET_INFO_CALL(i8052); break;
+ }
+}
+
+CPU_GET_INFO( i87c51 )
+{
+ switch (state)
+ {
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(i80c51); break;
+ case DEVINFO_STR_NAME: strcpy(info->s, "I87C51"); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(i80c51); break;
+ default: CPU_GET_INFO_CALL(i8751); break;
+ }
+}
+
+CPU_GET_INFO( i87c52 )
+{
+ switch (state)
+ {
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(i80c52); break;
+ case DEVINFO_STR_NAME: strcpy(info->s, "I87C52"); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(i80c52); break;
+ default: CPU_GET_INFO_CALL(i8752); break;
+ }
+}
+
+/**************************************************************************
+ * Other variants get_info
+ **************************************************************************/
+
+CPU_GET_INFO( at89c4051 )
+{
+ switch (state)
+ {
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(i80c51); break;
+ case DEVINFO_STR_NAME: strcpy(info->s, "AT89C4051"); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(i80c51); break;
+ default: CPU_GET_INFO_CALL(i8051); break;
+ }
+}
+
+CPU_GET_INFO( ds5002fp )
+{
+ switch (state)
+ {
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(ds5002fp); break;
+ case DEVINFO_STR_NAME: strcpy(info->s, "DS5002FP"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Dallas"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Manuel Abadia"); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(ds5002fp); break;
+ default: CPU_GET_INFO_CALL(i8051); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(I8031, i8031);
+DEFINE_LEGACY_CPU_DEVICE(I8032, i8032);
+DEFINE_LEGACY_CPU_DEVICE(I8051, i8051);
+DEFINE_LEGACY_CPU_DEVICE(I8751, i8751);
+DEFINE_LEGACY_CPU_DEVICE(I8052, i8052);
+DEFINE_LEGACY_CPU_DEVICE(I8752, i8752);
+DEFINE_LEGACY_CPU_DEVICE(I80C31, i80c31);
+DEFINE_LEGACY_CPU_DEVICE(I80C51, i80c51);
+DEFINE_LEGACY_CPU_DEVICE(I87C51, i87c51);
+DEFINE_LEGACY_CPU_DEVICE(I80C32, i80c32);
+DEFINE_LEGACY_CPU_DEVICE(I80C52, i80c52);
+DEFINE_LEGACY_CPU_DEVICE(I87C52, i87c52);
+DEFINE_LEGACY_CPU_DEVICE(AT89C4051, at89c4051);
+DEFINE_LEGACY_CPU_DEVICE(DS5002FP, ds5002fp);
diff --git a/trunk/src/emu/cpu/mcs51/mcs51.h b/trunk/src/emu/cpu/mcs51/mcs51.h
new file mode 100644
index 00000000000..dbc8ccaa7f8
--- /dev/null
+++ b/trunk/src/emu/cpu/mcs51/mcs51.h
@@ -0,0 +1,153 @@
+/*****************************************************************************
+ *
+ * mcs51.h
+ * Portable MCS-51 Family Emulator
+ *
+ * Chips in the family:
+ * 8051 Product Line (8031,8051,8751)
+ * 8052 Product Line (8032,8052,8752)
+ * 8054 Product Line (8054)
+ * 8058 Product Line (8058)
+ *
+ * Copyright Steve Ellenoff, all rights reserved.
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * sellenoff@hotmail.com
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ * This work is based on:
+ * #1) 'Intel(tm) MC51 Microcontroller Family Users Manual' and
+ * #2) 8051 simulator by Travis Marlatte
+ * #3) Portable UPI-41/8041/8741/8042/8742 emulator V0.1 by Juergen Buchmueller (MAME CORE)
+ *
+ * 2008, October, Couriersud
+ * - Rewrite of timer, interrupt and serial code
+ * - addition of CMOS features
+ * - internal memory maps
+ * - addition of new processor types
+ * - full emulation of 8xCx2 processors
+ *****************************************************************************/
+
+#pragma once
+
+#ifndef __MCS51_H__
+#define __MCS51_H__
+
+
+enum
+{
+ MCS51_PC=1, MCS51_SP, MCS51_PSW, MCS51_ACC, MCS51_B, MCS51_DPH, MCS51_DPL, MCS51_IE,
+ MCS51_R0, MCS51_R1, MCS51_R2, MCS51_R3, MCS51_R4, MCS51_R5, MCS51_R6, MCS51_R7, MCS51_RB
+};
+
+enum
+{
+ MCS51_INT0_LINE = 0, /* P3.2: External Interrupt 0 */
+ MCS51_INT1_LINE, /* P3.3: External Interrupt 1 */
+ MCS51_RX_LINE, /* P3.0: Serial Port Receive Line */
+ MCS51_T0_LINE, /* P3,4: Timer 0 External Input */
+ MCS51_T1_LINE, /* P3.5: Timer 1 External Input */
+ MCS51_T2_LINE, /* P1.0: Timer 2 External Input */
+ MCS51_T2EX_LINE, /* P1.1: Timer 2 Capture Reload Trigger */
+
+ DS5002FP_PFI_LINE, /* DS5002FP Power fail interrupt */
+};
+
+/* special I/O space ports */
+
+enum
+{
+ MCS51_PORT_P0 = 0x20000,
+ MCS51_PORT_P1 = 0x20001,
+ MCS51_PORT_P2 = 0x20002,
+ MCS51_PORT_P3 = 0x20003,
+ MCS51_PORT_TX = 0x20004, /* P3.1 */
+};
+
+/***************************************************************************
+ CONFIGURATION
+***************************************************************************/
+
+/* configuration of the DS5002FP */
+typedef struct _ds5002fp_config ds5002fp_config;
+struct _ds5002fp_config
+{
+ UINT8 mcon; /* bootstrap loader MCON register */
+ UINT8 rpctl; /* bootstrap loader RPCTL register */
+ UINT8 crc; /* bootstrap loader CRC register */
+};
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+typedef void (*mcs51_serial_tx_func)(device_t *device, int data);
+typedef int (*mcs51_serial_rx_func)(device_t *device);
+
+extern void i8051_set_serial_tx_callback(device_t *device, mcs51_serial_tx_func tx_func);
+extern void i8051_set_serial_rx_callback(device_t *device, mcs51_serial_rx_func rx_func);
+
+/* variants with no internal rom and 128 byte internal memory */
+DECLARE_LEGACY_CPU_DEVICE(I8031, i8031);
+
+/* variants with no internal rom and 256 byte internal memory */
+DECLARE_LEGACY_CPU_DEVICE(I8032, i8032);
+
+/* variants 4k internal rom and 128 byte internal memory */
+DECLARE_LEGACY_CPU_DEVICE(I8051, i8051);
+DECLARE_LEGACY_CPU_DEVICE(I8751, i8751);
+
+/* variants 8k internal rom and 256 byte internal memory and more registers */
+DECLARE_LEGACY_CPU_DEVICE(I8052, i8052);
+DECLARE_LEGACY_CPU_DEVICE(I8752, i8752);
+
+/* cmos variants */
+DECLARE_LEGACY_CPU_DEVICE(I80C31, i80c31);
+DECLARE_LEGACY_CPU_DEVICE(I80C51, i80c51);
+DECLARE_LEGACY_CPU_DEVICE(I87C51, i87c51);
+
+DECLARE_LEGACY_CPU_DEVICE(I80C32, i80c32);
+DECLARE_LEGACY_CPU_DEVICE(I80C52, i80c52);
+DECLARE_LEGACY_CPU_DEVICE(I87C52, i87c52);
+
+/* 4k internal perom and 128 internal ram and 2 analog comparators */
+DECLARE_LEGACY_CPU_DEVICE(AT89C4051, at89c4051);
+
+/*
+ * The DS5002FP has 2 16 bits data address buses (the byte-wide bus and the expanded bus). The exact memory position accessed depends on the
+ * partition mode, the memory range and the expanded bus select. The partition mode and the expanded bus select can be changed at any time.
+ *
+ * In order to simplify memory mapping to the data address bus, the following address map is assumed for partitioned mode:
+
+ * 0x00000-0x0ffff -> data memory on the expanded bus
+ * 0x10000-0x1ffff -> data memory on the byte-wide bus
+
+ * For non-partitioned mode the following memory map is assumed:
+
+ * 0x0000-0xffff -> data memory (the bus used to access it does not matter)
+ *
+ * Internal ram 128k and security features
+ */
+
+DECLARE_LEGACY_CPU_DEVICE(DS5002FP, ds5002fp);
+
+
+/****************************************************************************
+ * Disassembler
+ ****************************************************************************/
+
+CPU_DISASSEMBLE( i8051 );
+CPU_DISASSEMBLE( i80c51 );
+CPU_DISASSEMBLE( i8052 );
+CPU_DISASSEMBLE( i80c52 );
+CPU_DISASSEMBLE( ds5002fp );
+
+#endif /* __MCS51_H__ */
diff --git a/trunk/src/emu/cpu/mcs51/mcs51dasm.c b/trunk/src/emu/cpu/mcs51/mcs51dasm.c
new file mode 100644
index 00000000000..ac7b0854d94
--- /dev/null
+++ b/trunk/src/emu/cpu/mcs51/mcs51dasm.c
@@ -0,0 +1,1223 @@
+/*****************************************************************************
+ *
+ * i8051dasm.c
+ * Portable MCS-51 Family Emulator
+ *
+ * Chips in the family:
+ * 8051 Product Line (8031,8051,8751)
+ * 8052 Product Line (8032,8052,8752)
+ * 8054 Product Line (8054)
+ * 8058 Product Line (8058)
+ *
+ * Copyright Steve Ellenoff, all rights reserved.
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * sellenoff@hotmail.com
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ * This work is based on:
+ * #1) 'Intel(tm) MC51 Microcontroller Family Users Manual' and
+ * #2) 8051 simulator by Travis Marlatte
+ * #3) Portable UPI-41/8041/8741/8042/8742 emulator V0.1 by Juergen Buchmueller (MAME CORE)
+ *
+ *****************************************************************************
+ * Symbol Memory Name Tables borrowed from:
+ * D52 8052 Disassembler - Copyright Jeffery L. Post
+ *****************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "mcs51.h"
+
+enum
+{
+ FEATURE_NONE = 0x00,
+ FEATURE_I8052 = 0x01,
+ FEATURE_CMOS = 0x02,
+ FEATURE_I80C52 = 0x04,
+ FEATURE_DS5002FP = 0x08,
+ FEATURE_I83C751 = 0x08,
+};
+
+
+#define SHOW_MEMORY_NAMES 1
+
+#ifdef SHOW_MEMORY_NAMES
+
+/*Display the memory address names for data & bit address access*/
+
+//SFR Names
+
+static const struct {
+ int feature;
+ int addr;
+ const char *name;
+} mem_name_feature[] =
+{
+ { FEATURE_NONE, 0x00, "rb0r0" },
+ { FEATURE_NONE, 0x01, "rb0r1" },
+ { FEATURE_NONE, 0x02, "rb0r2" },
+ { FEATURE_NONE, 0x03, "rb0r3" },
+ { FEATURE_NONE, 0x04, "rb0r4" },
+ { FEATURE_NONE, 0x05, "rb0r5" },
+ { FEATURE_NONE, 0x06, "rb0r6" },
+ { FEATURE_NONE, 0x07, "rb0r7" },
+ { FEATURE_NONE, 0x08, "rb1r0" },
+ { FEATURE_NONE, 0x09, "rb1r1" },
+ { FEATURE_NONE, 0x0a, "rb1r2" },
+ { FEATURE_NONE, 0x0b, "rb1r3" },
+ { FEATURE_NONE, 0x0c, "rb1r4" },
+ { FEATURE_NONE, 0x0d, "rb1r5" },
+ { FEATURE_NONE, 0x0e, "rb1r6" },
+ { FEATURE_NONE, 0x0f, "rb1r7" },
+ { FEATURE_NONE, 0x10, "rb2r0" },
+ { FEATURE_NONE, 0x11, "rb2r1" },
+ { FEATURE_NONE, 0x12, "rb2r2" },
+ { FEATURE_NONE, 0x13, "rb2r3" },
+ { FEATURE_NONE, 0x14, "rb2r4" },
+ { FEATURE_NONE, 0x15, "rb2r5" },
+ { FEATURE_NONE, 0x16, "rb2r6" },
+ { FEATURE_NONE, 0x17, "rb2r7" },
+ { FEATURE_NONE, 0x18, "rb3r0" },
+ { FEATURE_NONE, 0x19, "rb3r1" },
+ { FEATURE_NONE, 0x1a, "rb3r2" },
+ { FEATURE_NONE, 0x1b, "rb3r3" },
+ { FEATURE_NONE, 0x1c, "rb3r4" },
+ { FEATURE_NONE, 0x1d, "rb3r5" },
+ { FEATURE_NONE, 0x1e, "rb3r6" },
+ { FEATURE_NONE, 0x1f, "rb3r7" },
+
+ { FEATURE_NONE, 0x80, "p0" },
+ { FEATURE_NONE, 0x81, "sp" },
+ { FEATURE_NONE, 0x82, "dpl" },
+ { FEATURE_NONE, 0x83, "dph" },
+ { FEATURE_NONE, 0x87, "pcon" },
+ { FEATURE_NONE, 0x88, "tcon" },
+ { FEATURE_NONE, 0x89, "tmod" },
+ { FEATURE_NONE, 0x8a, "tl0" },
+ { FEATURE_NONE, 0x8b, "tl1" },
+ { FEATURE_NONE, 0x8c, "th0" },
+ { FEATURE_NONE, 0x8d, "th1" },
+ { FEATURE_NONE, 0x90, "p1" },
+ { FEATURE_NONE, 0x98, "scon" },
+ { FEATURE_NONE, 0x99, "sbuf" },
+ { FEATURE_NONE, 0xa0, "p2" },
+ { FEATURE_NONE, 0xa8, "ie" },
+ { FEATURE_NONE, 0xb0, "p3" },
+ { FEATURE_NONE, 0xb8, "ip" },
+ { FEATURE_NONE, 0xd0, "psw" },
+ { FEATURE_NONE, 0xe0, "acc" },
+ { FEATURE_NONE, 0xf0, "b" },
+
+ { FEATURE_I8052, 0xc8, "t2con" },
+ { FEATURE_I8052, 0xca, "rcap2l" },
+ { FEATURE_I8052, 0xcb, "rcap2h" },
+ { FEATURE_I8052, 0xcc, "tl2" },
+ { FEATURE_I8052, 0xcd, "th2" },
+
+ { FEATURE_I80C52, 0xb7, "iph" },
+ { FEATURE_I80C52, 0xa9, "saddr" },
+ { FEATURE_I80C52, 0xb9, "saden" },
+
+ { FEATURE_DS5002FP, 0x8e, "pwcm" },
+ { FEATURE_DS5002FP, 0x8f, "pwmp" },
+ { FEATURE_DS5002FP, 0xc1, "crcr" },
+ { FEATURE_DS5002FP, 0xc2, "crcl" },
+ { FEATURE_DS5002FP, 0xc3, "crch" },
+ { FEATURE_DS5002FP, 0xc6, "mcon" },
+ { FEATURE_DS5002FP, 0xc7, "ta" },
+ { FEATURE_DS5002FP, 0xcf, "rnr" },
+ { FEATURE_DS5002FP, 0xd8, "rpctl" },
+ { FEATURE_DS5002FP, 0xd9, "rps" },
+
+ { FEATURE_I83C751, 0x98, "i2con" },
+ { FEATURE_I83C751, 0x99, "i2dat" },
+ { FEATURE_I83C751, 0xd8, "i2cfg" },
+ { FEATURE_I83C751, 0xf8, "i2sta" }, /* read only */
+
+ /* bit addresses */
+
+ { FEATURE_NONE, 0x188, "it0" },
+ { FEATURE_NONE, 0x189, "ie0" },
+ { FEATURE_NONE, 0x18a, "it1" },
+ { FEATURE_NONE, 0x18b, "ie1" },
+ { FEATURE_NONE, 0x18c, "tr0" },
+ { FEATURE_NONE, 0x18d, "tf0" },
+ { FEATURE_NONE, 0x18e, "tr1" },
+ { FEATURE_NONE, 0x18f, "tf1" },
+
+ { FEATURE_NONE, 0x198, "ri" },
+ { FEATURE_NONE, 0x199, "ti" },
+ { FEATURE_NONE, 0x19a, "rb8" },
+ { FEATURE_NONE, 0x19b, "tb8" },
+ { FEATURE_NONE, 0x19c, "ren" },
+ { FEATURE_NONE, 0x19d, "sm2" },
+ { FEATURE_NONE, 0x19e, "sm1" },
+ { FEATURE_NONE, 0x19f, "sm0" },
+
+ { FEATURE_I83C751, 0x198, "xstp" }, /* read: no function */
+ { FEATURE_I83C751, 0x199, "xstr" }, /* read: MASTER */
+ { FEATURE_I83C751, 0x19a, "cstp" }, /* read: STP */
+ { FEATURE_I83C751, 0x19b, "cstr" }, /* read: STR */
+ { FEATURE_I83C751, 0x19c, "carl" }, /* read: ARL */
+ { FEATURE_I83C751, 0x19d, "cdr" }, /* read: DRDY */
+ { FEATURE_I83C751, 0x19e, "idle" }, /* read: ATN */
+ { FEATURE_I83C751, 0x19f, "cxa" }, /* read: RDAT */
+
+ { FEATURE_NONE, 0x1a8, "ex0" },
+ { FEATURE_NONE, 0x1a9, "et0" },
+ { FEATURE_NONE, 0x1aa, "ex1" },
+ { FEATURE_NONE, 0x1ab, "et1" },
+ { FEATURE_NONE, 0x1ac, "es" },
+ { FEATURE_NONE, 0x1ad, "ie.5" },
+ { FEATURE_NONE, 0x1ae, "ie.6" },
+ { FEATURE_NONE, 0x1af, "ea" },
+
+ { FEATURE_I83C751, 0x1ac, "ei2" },
+ { FEATURE_I8052, 0x1ad, "et2" },
+
+ /* FIXME: port 3 - depends on external circuits and not really
+ * implemented in the core. TBD */
+ { FEATURE_NONE, 0x1b0, "rxd" },
+ { FEATURE_NONE, 0x1b1, "txd" },
+ { FEATURE_NONE, 0x1b2, "int0" },
+ { FEATURE_NONE, 0x1b3, "int1" },
+ { FEATURE_NONE, 0x1b4, "t0" },
+ { FEATURE_NONE, 0x1b5, "t1" },
+ { FEATURE_NONE, 0x1b6, "wr" },
+ { FEATURE_NONE, 0x1b7, "rd" },
+
+ { FEATURE_NONE, 0x1b8, "px0" },
+ { FEATURE_NONE, 0x1b9, "pt0" },
+ { FEATURE_NONE, 0x1ba, "px1" },
+ { FEATURE_NONE, 0x1bb, "pt1" },
+ { FEATURE_NONE, 0x1bc, "ps" },
+ { FEATURE_NONE, 0x1bd, "ip.5" },
+ { FEATURE_NONE, 0x1be, "ip.6" },
+ { FEATURE_NONE, 0x1bf, "ip.7" },
+
+ { FEATURE_I8052, 0x1bd, "pt2" },
+ { FEATURE_I83C751, 0x1bc, "pi2" },
+
+ { FEATURE_I8052, 0x1c8, "cprl2" },
+ { FEATURE_I8052, 0x1c9, "ct2" },
+ { FEATURE_I8052, 0x1ca, "tr2" },
+ { FEATURE_I8052, 0x1cb, "exen2" },
+ { FEATURE_I8052, 0x1cc, "tclk" },
+ { FEATURE_I8052, 0x1cd, "rclk" },
+ { FEATURE_I8052, 0x1ce, "exf2" },
+ { FEATURE_I8052, 0x1cf, "tf2" },
+
+ { FEATURE_NONE, 0x1d0, "p" },
+ { FEATURE_NONE, 0x1d1, "psw.1" },
+ { FEATURE_NONE, 0x1d2, "ov" },
+ { FEATURE_NONE, 0x1d3, "rs0" },
+ { FEATURE_NONE, 0x1d4, "rs1" },
+ { FEATURE_NONE, 0x1d5, "f0" },
+ { FEATURE_NONE, 0x1d6, "ac" },
+ { FEATURE_NONE, 0x1d7, "cy" },
+
+ { FEATURE_DS5002FP, 0x1d8, "rg0" },
+ { FEATURE_DS5002FP, 0x1d9, "rpc" },
+ { FEATURE_DS5002FP, 0x1da, "dma" },
+ { FEATURE_DS5002FP, 0x1db, "ibi" },
+ { FEATURE_DS5002FP, 0x1dc, "ae" },
+ { FEATURE_DS5002FP, 0x1dd, "exbs" },
+ { FEATURE_DS5002FP, 0x1de, "d8.6" },
+ { FEATURE_DS5002FP, 0x1df, "rnr" },
+
+ { FEATURE_I83C751, 0x1d8, "ct0" },
+ { FEATURE_I83C751, 0x1d9, "ct1" },
+ { FEATURE_I83C751, 0x1da, "i2cfg.2" },
+ { FEATURE_I83C751, 0x1db, "i2cfg.3" },
+ { FEATURE_I83C751, 0x1dc, "tirun" },
+ { FEATURE_I83C751, 0x1dd, "clrti" },
+ { FEATURE_I83C751, 0x1de, "masterq" },
+ { FEATURE_I83C751, 0x1df, "slaven" },
+
+ { FEATURE_I83C751, 0x1f8, "xstp" },
+ { FEATURE_I83C751, 0x1f9, "xstr" },
+ { FEATURE_I83C751, 0x1fa, "makstp" },
+ { FEATURE_I83C751, 0x1fb, "makstr" },
+ { FEATURE_I83C751, 0x1fc, "xactv" },
+ { FEATURE_I83C751, 0x1fd, "xdata" },
+ { FEATURE_I83C751, 0x1fe, "idle" },
+ { FEATURE_I83C751, 0x1ff, "i2sta.7" },
+
+ /* unknown
+ * "ibf", "obf", "idsm", "obfc", e8 - eb
+ * "ma0", "ma1", "mb0", "mb1", ec - ef
+ */
+
+ { -1 }
+};
+
+static void init_mem_names(int feature_set, const char **mem_names)
+{
+ int i;
+ int feature;
+
+ /* Set defaults / i8051 */
+ for (i = 0; feature = mem_name_feature[i].feature, feature >= 0; i++)
+ {
+ if ( feature == FEATURE_NONE )
+ mem_names[mem_name_feature[i].addr] = mem_name_feature[i].name;
+ }
+
+ /* Set specific memory names */
+ for (i = 0; feature = mem_name_feature[i].feature, feature >= 0; i++)
+ {
+ if (feature & feature_set)
+ mem_names[mem_name_feature[i].addr] = mem_name_feature[i].name;
+ }
+
+}
+
+static const char *get_data_address( const char **mem_names, UINT8 arg )
+{
+ static char buffer_array[4][32];
+ static int whichbuf;
+ char *buffer = &buffer_array[++whichbuf % 4][0];
+
+ if (mem_names[arg] == NULL)
+ sprintf(buffer,"$%02X",arg);
+ else
+ sprintf(buffer,"%s", mem_names[arg]);
+ return buffer;
+}
+
+static const char *get_bit_address( const char **mem_names, UINT8 arg )
+{
+ static char buffer[32];
+
+ if(arg < 0x80)
+ {
+ //Bit address 0-7F can be referred to as 20.0, 20.1, to 20.7 for address 0, and 2f.0,2f.1 to 2f.7 for address 7f
+ if(arg < 0x7f)
+ sprintf(buffer,"$%02X.%d",(arg >> 3) | 0x20, arg & 0x07);
+ else
+ sprintf(buffer,"$%02X",arg);
+ }
+ else
+ {
+ if (mem_names[arg | 0x100] == NULL)
+ {
+ if (mem_names[arg & 0xf8] == NULL)
+ sprintf(buffer,"$%02X.%d", arg & 0xf8, arg & 0x07);
+ else
+ sprintf(buffer,"%s.%d", mem_names[arg & 0xf8], arg & 0x07);
+ }
+ else
+ sprintf(buffer,"%s", mem_names[arg | 0x100]);
+ }
+ return buffer;
+}
+
+#else
+
+/*Just display the actual memory address for data & bit address access*/
+
+static const char *get_data_address( UINT8 arg )
+{
+ static char buffer[32];
+ sprintf(buffer,"$%02X",arg);
+ return buffer;
+}
+
+static const char *get_bit_address( UINT8 arg )
+{
+ static char buffer[32];
+ sprintf(buffer,"$%02X",arg);
+ return buffer;
+}
+
+#endif
+
+static offs_t mcs51_dasm( const char **mem_names, char *dst, offs_t pc, const UINT8 *oprom, const UINT8 *opram)
+{
+ UINT32 flags = 0;
+ unsigned PC = pc;
+ const char *sym, *sym2;
+ UINT8 op, data;
+ UINT16 addr;
+ INT8 rel;
+
+ op = oprom[PC++ - pc];
+ switch( op )
+ {
+ //NOP
+ case 0x00: /* 1: 0000 0000 */
+ sprintf(dst, "nop");
+ break;
+
+ //AJMP code addr /* 1: aaa0 0001 */
+ case 0x01:
+ case 0x21:
+ case 0x41:
+ case 0x61:
+ case 0x81:
+ case 0xa1:
+ case 0xc1:
+ case 0xe1:
+ addr = opram[PC++ - pc];
+ addr|= (PC & 0xf800) | ((op & 0xe0) << 3);
+ sprintf(dst, "ajmp $%04X", addr);
+ break;
+
+ //LJMP code addr
+ case 0x02: /* 1: 0000 0010 */
+ addr = (opram[PC++ - pc]<<8) & 0xff00;
+ addr|= opram[PC++ - pc];
+ sprintf(dst, "ljmp $%04X", addr);
+ break;
+
+ //RR A
+ case 0x03: /* 1: 0000 0011 */
+ sprintf(dst, "rr a");
+ break;
+
+ //INC A
+ case 0x04: /* 1: 0000 0100 */
+ sprintf(dst, "inc a");
+ break;
+
+ //INC data addr
+ case 0x05: /* 1: 0000 0101 */
+ sym = get_data_address(mem_names, opram[PC++ - pc]);
+ sprintf(dst, "inc %s", sym);
+ break;
+
+ //INC @R0/@R1 /* 1: 0000 011i */
+ case 0x06:
+ case 0x07:
+ sprintf(dst, "inc @r%d", op&1);
+ break;
+
+ //INC R0 to R7 /* 1: 0000 1rrr */
+ case 0x08:
+ case 0x09:
+ case 0x0a:
+ case 0x0b:
+ case 0x0c:
+ case 0x0d:
+ case 0x0e:
+ case 0x0f:
+ sprintf(dst, "inc r%d", op&7);
+ break;
+
+ //JBC bit addr, code addr
+ case 0x10: /* 1: 0001 0000 */
+ sym = get_bit_address(mem_names, opram[PC++ - pc]);
+ rel = opram[PC++ - pc];
+ sprintf(dst, "jbc %s,$%04X", sym, PC + rel);
+ break;
+
+ //ACALL code addr /* 1: aaa1 0001 */
+ case 0x11:
+ case 0x31:
+ case 0x51:
+ case 0x71:
+ case 0x91:
+ case 0xb1:
+ case 0xd1:
+ case 0xf1:
+ sprintf(dst, "acall $%04X", (PC & 0xf800) | ((op & 0xe0) << 3) | opram[PC - pc]);
+ PC++;
+ flags = DASMFLAG_STEP_OVER;
+ break;
+
+ //LCALL code addr
+ case 0x12: /* 1: 0001 0010 */
+ addr = (opram[PC++ - pc]<<8) & 0xff00;
+ addr|= opram[PC++ - pc];
+ sprintf(dst, "lcall $%04X", addr);
+ flags = DASMFLAG_STEP_OVER;
+ break;
+
+ //RRC A
+ case 0x13: /* 1: 0001 0011 */
+ sprintf(dst, "rrc a");
+ break;
+
+ //DEC A
+ case 0x14: /* 1: 0001 0100 */
+ sprintf(dst, "dec a");
+ break;
+
+ //DEC data addr
+ case 0x15: /* 1: 0001 0101 */
+ sym = get_data_address(mem_names, opram[PC++ - pc]);
+ sprintf(dst, "dec %s", sym);
+ break;
+
+ //Unable to test
+ //DEC @R0/@R1 /* 1: 0001 011i */
+ case 0x16:
+ case 0x17:
+ sprintf(dst, "dec @r%d", op&1);
+ break;
+
+ //DEC R0 to R7 /* 1: 0001 1rrr */
+ case 0x18:
+ case 0x19:
+ case 0x1a:
+ case 0x1b:
+ case 0x1c:
+ case 0x1d:
+ case 0x1e:
+ case 0x1f:
+ sprintf(dst, "dec r%d", op&7);
+ break;
+
+ //JB bit addr, code addr
+ case 0x20: /* 1: 0010 0000 */
+ sym = get_bit_address(mem_names, opram[PC++ - pc]);
+ rel = opram[PC++ - pc];
+ sprintf(dst, "jb %s,$%04X", sym, (PC + rel));
+ break;
+
+ //RET
+ case 0x22: /* 1: 0010 0010 */
+ sprintf(dst, "ret");
+ flags = DASMFLAG_STEP_OUT;
+ break;
+
+ //RL A
+ case 0x23: /* 1: 0010 0011 */
+ sprintf(dst, "rl a");
+ break;
+
+ //ADD A, #data
+ case 0x24: /* 1: 0010 0100 */
+ sprintf(dst, "add a,#$%02X", opram[PC++ - pc]);
+ break;
+
+ //ADD A, data addr
+ case 0x25: /* 1: 0010 0101 */
+ sym = get_data_address(mem_names, opram[PC++ - pc]);
+ sprintf(dst, "add a,%s", sym);
+ break;
+
+ //Unable to Test
+ //ADD A, @R0/@R1 /* 1: 0010 011i */
+ case 0x26:
+ case 0x27:
+ sprintf(dst, "add a,@r%d", op&1);
+ break;
+
+ //ADD A, R0 to R7 /* 1: 0010 1rrr */
+ case 0x28:
+ case 0x29:
+ case 0x2a:
+ case 0x2b:
+ case 0x2c:
+ case 0x2d:
+ case 0x2e:
+ case 0x2f:
+ sprintf(dst, "add a,r%d", op&7);
+ break;
+
+ //JNB bit addr, code addr
+ case 0x30: /* 1: 0011 0000 */
+ sym = get_bit_address(mem_names, opram[PC++ - pc]);
+ rel = opram[PC++ - pc];
+ sprintf(dst, "jnb %s,$%04X", sym, (PC + rel));
+ break;
+
+ //RETI
+ case 0x32: /* 1: 0011 0010 */
+ sprintf(dst, "reti");
+ flags = DASMFLAG_STEP_OUT;
+ break;
+
+ //RLC A
+ case 0x33: /* 1: 0011 0011 */
+ sprintf(dst, "rlc a");
+ break;
+
+ //ADDC A, #data
+ case 0x34: /* 1: 0011 0100 */
+ sprintf(dst, "addc a,#$%02X", opram[PC++ - pc]);
+ break;
+
+ //ADDC A, data addr
+ case 0x35: /* 1: 0011 0101 */
+ sym = get_data_address(mem_names, opram[PC++ - pc]);
+ sprintf(dst, "addc a,%s", sym);
+ break;
+
+ //ADDC A, @R0/@R1 /* 1: 0011 011i */
+ case 0x36:
+ case 0x37:
+ sprintf(dst, "addc a,@r%d", op&1);
+ break;
+
+ //ADDC A, R0 to R7 /* 1: 0011 1rrr */
+ case 0x38:
+ case 0x39:
+ case 0x3a:
+ case 0x3b:
+ case 0x3c:
+ case 0x3d:
+ case 0x3e:
+ case 0x3f:
+ sprintf(dst, "addc a,r%d", op&7);
+ break;
+
+ //JC code addr
+ case 0x40: /* 1: 0100 0000 */
+ rel = opram[PC++ - pc];
+ sprintf(dst, "jc $%04X", PC + rel);
+ break;
+
+ //ORL data addr, A
+ case 0x42: /* 1: 0100 0010 */
+ sym = get_data_address(mem_names, opram[PC++ - pc]);
+ sprintf(dst, "orl %s,a", sym);
+ break;
+
+ //ORL data addr, #data
+ case 0x43: /* 1: 0100 0011 */
+ sym = get_data_address(mem_names, opram[PC++ - pc]);
+ sprintf(dst, "orl %s,#$%02X", sym, opram[PC++ - pc]);
+ break;
+
+ //Unable to Test
+ //ORL A, #data
+ case 0x44: /* 1: 0100 0100 */
+ sprintf(dst, "orl a,#$%02X", opram[PC++ - pc]);
+ break;
+
+ //ORL A, data addr
+ case 0x45: /* 1: 0100 0101 */
+ sym = get_data_address(mem_names, opram[PC++ - pc]);
+ sprintf(dst, "orl a,%s", sym);
+ break;
+
+ //ORL A, @RO/@R1 /* 1: 0100 011i */
+ case 0x46:
+ case 0x47:
+ sprintf(dst, "orl a,@r%d", op&1);
+ break;
+
+ //ORL A, RO to R7 /* 1: 0100 1rrr */
+ case 0x48:
+ case 0x49:
+ case 0x4a:
+ case 0x4b:
+ case 0x4c:
+ case 0x4d:
+ case 0x4e:
+ case 0x4f:
+ sprintf(dst, "orl a,r%d", op&7);
+ break;
+
+ //JNC code addr
+ case 0x50: /* 1: 0101 0000 */
+ rel = opram[PC++ - pc];
+ sprintf(dst, "jnc $%04X", PC + rel);
+ break;
+
+ //Unable to test
+ //ANL data addr, A
+ case 0x52: /* 1: 0101 0010 */
+ sym = get_data_address(mem_names, opram[PC++ - pc]);
+ sprintf(dst, "anl %s,a", sym);
+ break;
+
+ //Unable to test
+ //ANL data addr, #data
+ case 0x53: /* 1: 0101 0011 */
+ sym = get_data_address(mem_names, opram[PC++ - pc]);
+ sprintf(dst, "anl %s,#$%02X", sym, opram[PC++ - pc]);
+ break;
+
+ //ANL A, #data
+ case 0x54: /* 1: 0101 0100 */
+ sprintf(dst, "anl a,#$%02X", opram[PC++ - pc]);
+ break;
+
+ //ANL A, data addr
+ case 0x55: /* 1: 0101 0101 */
+ sym = get_data_address(mem_names, opram[PC++ - pc]);
+ sprintf(dst, "anl a,%s", sym);
+ break;
+
+ //Unable to test
+ //ANL A, @RO/@R1 /* 1: 0101 011i */
+ case 0x56:
+ case 0x57:
+ sprintf(dst, "anl a,@r%d", op&1);
+ break;
+
+ //ANL A, RO to R7 /* 1: 0101 1rrr */
+ case 0x58:
+ case 0x59:
+ case 0x5a:
+ case 0x5b:
+ case 0x5c:
+ case 0x5d:
+ case 0x5e:
+ case 0x5f:
+ sprintf(dst, "anl a,r%d", op&7);
+ break;
+
+ //JZ code addr
+ case 0x60: /* 1: 0110 0000 */
+ rel = opram[PC++ - pc];
+ sprintf(dst, "jz $%04X", PC + rel);
+ break;
+
+ //Unable to test
+ //XRL data addr, A
+ case 0x62: /* 1: 0110 0010 */
+ sym = get_data_address(mem_names, opram[PC++ - pc]);
+ sprintf(dst, "xrl %s,a", sym);
+ break;
+
+ //XRL data addr, #data
+ case 0x63: /* 1: 0110 0011 */
+ sym = get_data_address(mem_names, opram[PC++ - pc]);
+ sprintf(dst, "xrl %s,#$%02X", sym, opram[PC++ - pc]);
+ break;
+
+ //XRL A, #data
+ case 0x64: /* 1: 0110 0100 */
+ sprintf(dst, "xrl a,#$%02X", opram[PC++ - pc]);
+ break;
+
+ //XRL A, data addr
+ case 0x65: /* 1: 0110 0101 */
+ sym = get_data_address(mem_names, opram[PC++ - pc]);
+ sprintf(dst, "xrl a,%s", sym);
+ break;
+
+ //Unable to test
+ //XRL A, @R0/@R1 /* 1: 0110 011i */
+ case 0x66:
+ case 0x67:
+ sprintf(dst, "xrl a,@r%d", op&1);
+ break;
+
+ //XRL A, R0 to R7 /* 1: 0110 1rrr */
+ case 0x68:
+ case 0x69:
+ case 0x6a:
+ case 0x6b:
+ case 0x6c:
+ case 0x6d:
+ case 0x6e:
+ case 0x6f:
+ sprintf(dst, "xrl a,r%d", op&7);
+ break;
+
+ //JNZ code addr
+ case 0x70: /* 1: 0111 0000 */
+ rel = opram[PC++ - pc];
+ sprintf(dst, "jnz $%04X", PC + rel);
+ break;
+
+ //Unable to test
+ //ORL C, bit addr
+ case 0x72: /* 1: 0111 0010 */
+ sym = get_bit_address(mem_names, opram[PC++ - pc]);
+ sprintf(dst, "orl c,%s", sym);
+ break;
+
+ //Unable to test
+ //JMP @A+DPTR
+ case 0x73: /* 1: 0111 0011 */
+ sprintf(dst, "jmp @a+dptr");
+ break;
+
+ //MOV A, #data
+ case 0x74: /* 1: 0111 0100 */
+ sprintf(dst, "mov a,#$%02X", opram[PC++ - pc]);
+ break;
+
+ //MOV data addr, #data
+ case 0x75: /* 1: 0111 0101 */
+ sym = get_data_address(mem_names, opram[PC++ - pc]);
+ sprintf(dst, "mov %s,#$%02X", sym, opram[PC++ - pc]);
+ break;
+
+ //Unable to test
+ //MOV @R0/@R1, #data /* 1: 0111 011i */
+ case 0x76:
+ case 0x77:
+ sprintf(dst, "mov @r%d,#$%02X", op&1, opram[PC++ - pc]);
+ break;
+
+ //MOV R0 to R7, #data /* 1: 0111 1rrr */
+ case 0x78:
+ case 0x79:
+ case 0x7a:
+ case 0x7b:
+ case 0x7c:
+ case 0x7d:
+ case 0x7e:
+ case 0x7f:
+ sprintf(dst, "mov r%d,#$%02X", (op & 7), opram[PC++ - pc]);
+ break;
+
+ //SJMP code addr
+ case 0x80: /* 1: 1000 0000 */
+ rel = opram[PC++ - pc];
+ sprintf(dst, "sjmp $%04X", PC + rel);
+ break;
+
+ //ANL C, bit addr
+ case 0x82: /* 1: 1000 0010 */
+ sym = get_bit_address(mem_names, opram[PC++ - pc]);
+ sprintf(dst, "anl c,%s", sym);
+ break;
+
+ //MOVC A, @A + PC
+ case 0x83: /* 1: 1000 0011 */
+ sprintf(dst, "movc a,@a+pc");
+ break;
+
+ //DIV AB
+ case 0x84: /* 1: 1000 0100 */
+ sprintf(dst, "div ab");
+ break;
+
+ //MOV data addr, data addr (Note: 1st address is src, 2nd is dst, but the mov command works as mov dst,src)
+ case 0x85: /* 1: 1000 0101 */
+ sym = get_data_address(mem_names, opram[PC++ - pc]);
+ sym2 = get_data_address(mem_names, opram[PC++ - pc]);
+ sprintf(dst, "mov %s,%s", sym2, sym);
+ break;
+
+ //Unable to test
+ //MOV data addr, @R0/@R1/* 1: 1000 011i */
+ case 0x86:
+ case 0x87:
+ sym = get_data_address(mem_names, opram[PC++ - pc]);
+ sprintf(dst, "mov %s,@r%d", sym, op&1);
+ break;
+
+ //MOV data addr,R0 to R7/* 1: 1000 1rrr */
+ case 0x88:
+ case 0x89:
+ case 0x8a:
+ case 0x8b:
+ case 0x8c:
+ case 0x8d:
+ case 0x8e:
+ case 0x8f:
+ sym = get_data_address(mem_names, opram[PC++ - pc]);
+ sprintf(dst, "mov %s,r%d", sym, op&7);
+ break;
+
+ //MOV DPTR, #data16
+ case 0x90: /* 1: 1001 0000 */
+ addr = (opram[PC++ - pc]<<8) & 0xff00;
+ addr|= opram[PC++ - pc];
+ sprintf(dst, "mov dptr,#$%04X", addr);
+ break;
+
+ //MOV bit addr, C
+ case 0x92: /* 1: 1001 0010 */
+ sym = get_bit_address(mem_names, opram[PC++ - pc]);
+ sprintf(dst, "mov %s,c", sym);
+ break;
+
+ //MOVC A, @A + DPTR
+ case 0x93: /* 1: 1001 0011 */
+ sprintf(dst, "movc a,@a+dptr");
+ break;
+
+ //SUBB A, #data
+ case 0x94: /* 1: 1001 0100 */
+ sprintf(dst, "subb a,#$%02X", opram[PC++ - pc]);
+ break;
+
+ //SUBB A, data addr
+ case 0x95: /* 1: 1001 0101 */
+ sym = get_data_address(mem_names, opram[PC++ - pc]);
+ sprintf(dst, "subb a,%s", sym);
+ break;
+
+ //Unable to test
+ //SUBB A, @R0/@R1 /* 1: 1001 011i */
+ case 0x96:
+ case 0x97:
+ sprintf(dst, "subb a,@r%d", op&1);
+ break;
+
+ //SUBB A, R0 to R7 /* 1: 1001 1rrr */
+ case 0x98:
+ case 0x99:
+ case 0x9a:
+ case 0x9b:
+ case 0x9c:
+ case 0x9d:
+ case 0x9e:
+ case 0x9f:
+ sprintf(dst, "subb a,r%d", op&7);
+ break;
+
+ //Unable to test
+ //ORL C, /bit addr
+ case 0xa0: /* 1: 1010 0000 */
+ sym = get_bit_address(mem_names, opram[PC++ - pc]);
+ sprintf(dst, "orl c,/%s", sym);
+ break;
+
+ //MOV C, bit addr
+ case 0xa2: /* 1: 1010 0010 */
+ sym = get_bit_address(mem_names, opram[PC++ - pc]);
+ sprintf(dst, "mov c,%s", sym);
+ break;
+
+ //INC DPTR
+ case 0xa3: /* 1: 1010 0011 */
+ sprintf(dst, "inc dptr");
+ break;
+
+ //MUL AB
+ case 0xa4: /* 1: 1010 0100 */
+ sprintf(dst, "mul ab");
+ break;
+
+ //reserved
+ case 0xa5: /* 1: 1010 0101 */
+ sprintf(dst, "ill/rsv");
+ break;
+
+ //Unable to test
+ //MOV @R0/@R1, data addr /* 1: 1010 011i */
+ case 0xa6:
+ case 0xa7:
+ sym = get_data_address(mem_names, opram[PC++ - pc]);
+ sprintf(dst, "mov @r%d,%s", op&1, sym);
+ break;
+
+ //MOV R0 to R7, data addr /* 1: 1010 1rrr */
+ case 0xa8:
+ case 0xa9:
+ case 0xaa:
+ case 0xab:
+ case 0xac:
+ case 0xad:
+ case 0xae:
+ case 0xaf:
+ sym = get_data_address(mem_names, opram[PC++ - pc]);
+ sprintf(dst, "mov r%d,%s", op&7, sym);
+ break;
+
+ //ANL C,/bit addr
+ case 0xb0: /* 1: 1011 0000 */
+ sym = get_bit_address(mem_names, opram[PC++ - pc]);
+ sprintf(dst, "anl c,/%s", sym);
+ break;
+
+ //CPL bit addr
+ case 0xb2: /* 1: 1011 0010 */
+ sym = get_bit_address(mem_names, opram[PC++ - pc]);
+ sprintf(dst, "cpl %s", sym);
+ break;
+
+ //Unable to test
+ //CPL C
+ case 0xb3: /* 1: 1011 0011 */
+ sprintf(dst, "cpl c");
+ break;
+
+ //CJNE A, #data, code addr
+ case 0xb4: /* 1: 1011 0100 */
+ data = opram[PC++ - pc];
+ rel = opram[PC++ - pc];
+ sprintf(dst, "cjne a,#$%02X,$%04X", data, PC + rel);
+ break;
+
+ //CJNE A, data addr, code addr
+ case 0xb5: /* 1: 1011 0101 */
+ sym = get_data_address(mem_names, opram[PC++ - pc]);
+ rel = opram[PC++ - pc];
+ sprintf(dst, "cjne a,%s,$%04X", sym, PC + rel);
+ break;
+
+ //Unable to test
+ //CJNE @R0/@R1, #data, code addr /* 1: 1011 011i */
+ case 0xb6:
+ case 0xb7:
+ data = opram[PC++ - pc];
+ rel = opram[PC++ - pc];
+ sprintf(dst, "cjne @r%d,#$%02X,$%04X", op&1, data, PC + rel);
+ break;
+
+ //CJNE R0 to R7, #data, code addr/* 1: 1011 1rrr */
+ case 0xb8:
+ case 0xb9:
+ case 0xba:
+ case 0xbb:
+ case 0xbc:
+ case 0xbd:
+ case 0xbe:
+ case 0xbf:
+ data = opram[PC++ - pc];
+ rel = opram[PC++ - pc];
+ sprintf(dst, "cjne r%d,#$%02X,$%04X", op&7, data, PC + rel);
+ break;
+
+ //PUSH data addr
+ case 0xc0: /* 1: 1100 0000 */
+ sym = get_data_address(mem_names, opram[PC++ - pc]);
+ sprintf(dst, "push %s", sym);
+ break;
+
+ //CLR bit addr
+ case 0xc2: /* 1: 1100 0010 */
+ sym = get_bit_address(mem_names, opram[PC++ - pc]);
+ sprintf(dst, "clr %s", sym);
+ break;
+
+ //CLR C
+ case 0xc3: /* 1: 1100 0011 */
+ sprintf(dst, "clr c");
+ break;
+
+ //SWAP A
+ case 0xc4: /* 1: 1100 0100 */
+ sprintf(dst, "swap a");
+ break;
+
+ //XCH A, data addr
+ case 0xc5: /* 1: 1100 0101 */
+ sym = get_data_address(mem_names, opram[PC++ - pc]);
+ sprintf(dst, "xch a,%s", sym);
+ break;
+
+ //XCH A, @RO/@R1 /* 1: 1100 011i */
+ case 0xc6:
+ case 0xc7:
+ sprintf(dst, "xch a,@r%d", op&1);
+ break;
+
+ //XCH A, RO to R7 /* 1: 1100 1rrr */
+ case 0xc8:
+ case 0xc9:
+ case 0xca:
+ case 0xcb:
+ case 0xcc:
+ case 0xcd:
+ case 0xce:
+ case 0xcf:
+ sprintf(dst, "xch a,r%d", op&7);
+ break;
+
+ //POP data addr
+ case 0xd0: /* 1: 1101 0000 */
+ sym = get_data_address(mem_names, opram[PC++ - pc]);
+ sprintf(dst, "pop %s", sym);
+ break;
+
+ //SETB bit addr
+ case 0xd2: /* 1: 1101 0010 */
+ sym = get_bit_address(mem_names, opram[PC++ - pc]);
+ sprintf(dst, "setb %s", sym);
+ break;
+
+ //SETB C
+ case 0xd3: /* 1: 1101 0011 */
+ sprintf(dst, "setb c");
+ break;
+
+ //Unable to test
+ //DA A
+ case 0xd4: /* 1: 1101 0100 */
+ sprintf(dst, "da a");
+ break;
+
+ //DJNZ data addr, code addr
+ case 0xd5: /* 1: 1101 0101 */
+ sym = get_data_address(mem_names, opram[PC++ - pc]);
+ rel = opram[PC++ - pc];
+ sprintf(dst, "djnz %s,$%04X", sym, PC + rel);
+ flags = DASMFLAG_STEP_OVER;
+ break;
+
+ //XCHD A, @R0/@R1 /* 1: 1101 011i */
+ case 0xd6:
+ case 0xd7:
+ sprintf(dst, "xchd a,@r%d", op&1);
+ break;
+
+ //DJNZ R0 to R7,code addr /* 1: 1101 1rrr */
+ case 0xd8:
+ case 0xd9:
+ case 0xda:
+ case 0xdb:
+ case 0xdc:
+ case 0xdd:
+ case 0xde:
+ case 0xdf:
+ rel = opram[PC++ - pc];
+ sprintf(dst, "djnz r%d,$%04X", op&7, (PC + rel));
+ flags = DASMFLAG_STEP_OVER;
+ break;
+
+ //MOVX A,@DPTR
+ case 0xe0: /* 1: 1110 0000 */
+ sprintf(dst, "movx a,@dptr");
+ break;
+
+ //Unable to test
+ //MOVX A, @R0/@R1 /* 1: 1110 001i */
+ case 0xe2:
+ case 0xe3:
+ sprintf(dst, "movx a,@r%d", op&1);
+ break;
+
+ //CLR A
+ case 0xe4: /* 1: 1110 0100 */
+ sprintf(dst, "clr a");
+ break;
+
+ //MOV A, data addr
+ case 0xe5: /* 1: 1110 0101 */
+ sym = get_data_address(mem_names, opram[PC++ - pc]);
+ sprintf(dst, "mov a,%s", sym);
+ break;
+
+ //Unable to test
+ //MOV A,@RO/@R1 /* 1: 1110 011i */
+ case 0xe6:
+ case 0xe7:
+ sprintf(dst, "mov a,@r%d", op&1);
+ break;
+
+ //MOV A,R0 to R7 /* 1: 1110 1rrr */
+ case 0xe8:
+ case 0xe9:
+ case 0xea:
+ case 0xeb:
+ case 0xec:
+ case 0xed:
+ case 0xee:
+ case 0xef:
+ sprintf(dst, "mov a,r%d", op&7);
+ break;
+
+ //MOVX @DPTR,A
+ case 0xf0: /* 1: 1111 0000 */
+ sprintf(dst, "movx @dptr,a");
+ break;
+
+ //Unable to test
+ //MOVX @R0/@R1,A /* 1: 1111 001i */
+ case 0xf2:
+ case 0xf3:
+ sprintf(dst, "movx @r%d,a", op&1);
+ break;
+
+ //CPL A
+ case 0xf4: /* 1: 1111 0100 */
+ sprintf(dst, "cpl a");
+ break;
+
+ //MOV data addr, A
+ case 0xf5: /* 1: 1111 0101 */
+ sym = get_data_address(mem_names, opram[PC++ - pc]);
+ sprintf(dst, "mov %s,a", sym);
+ break;
+
+ //MOV @R0/@R1, A /* 1: 1111 011i */
+ case 0xf6:
+ case 0xf7:
+ sprintf(dst, "mov @r%d,a", op&1);
+ break;
+
+ //MOV R0 to R7, A /* 1: 1111 1rrr */
+ case 0xf8:
+ case 0xf9:
+ case 0xfa:
+ case 0xfb:
+ case 0xfc:
+ case 0xfd:
+ case 0xfe:
+ case 0xff:
+ sprintf(dst, "mov r%d,a", op&7);
+ break;
+
+ default:
+ sprintf(dst, "illegal");
+ }
+ return (PC - pc) | flags | DASMFLAG_SUPPORTED;
+
+}
+
+CPU_DISASSEMBLE( i8051 )
+{
+ static const char *mem_names[0x200];
+ static int mem_names_initialized = 0;
+
+ if (!mem_names_initialized)
+ {
+ init_mem_names( FEATURE_NONE, mem_names);
+ mem_names_initialized = 1;
+ }
+ return mcs51_dasm(mem_names, buffer, pc, oprom, opram);
+}
+
+CPU_DISASSEMBLE( i8052 )
+{
+ static const char *mem_names[0x200];
+ static int mem_names_initialized = 0;
+
+ if (!mem_names_initialized)
+ {
+ init_mem_names( FEATURE_I8052, mem_names);
+ mem_names_initialized = 1;
+ }
+ return mcs51_dasm(mem_names, buffer, pc, oprom, opram);
+}
+
+CPU_DISASSEMBLE( i80c51 )
+{
+ static const char *mem_names[0x200];
+ static int mem_names_initialized = 0;
+
+ if (!mem_names_initialized)
+ {
+ init_mem_names( FEATURE_CMOS, mem_names);
+ mem_names_initialized = 1;
+ }
+ return mcs51_dasm(mem_names, buffer, pc, oprom, opram);
+}
+
+CPU_DISASSEMBLE( i80c52 )
+{
+ static const char *mem_names[0x200];
+ static int mem_names_initialized = 0;
+
+ if (!mem_names_initialized)
+ {
+ init_mem_names( FEATURE_I8052 | FEATURE_CMOS | FEATURE_I80C52, mem_names);
+ mem_names_initialized = 1;
+ }
+ return mcs51_dasm(mem_names, buffer, pc, oprom, opram);
+}
+
+CPU_DISASSEMBLE( ds5002fp )
+{
+ static const char *mem_names[0x200];
+ static int mem_names_initialized = 0;
+
+ if (!mem_names_initialized)
+ {
+ init_mem_names( FEATURE_DS5002FP | FEATURE_CMOS, mem_names);
+ mem_names_initialized = 1;
+ }
+ return mcs51_dasm(mem_names, buffer, pc, oprom, opram);
+}
diff --git a/trunk/src/emu/cpu/mcs51/mcs51ops.c b/trunk/src/emu/cpu/mcs51/mcs51ops.c
new file mode 100644
index 00000000000..7cbaf78575c
--- /dev/null
+++ b/trunk/src/emu/cpu/mcs51/mcs51ops.c
@@ -0,0 +1,980 @@
+/*******************************************************************************************
+ NOTE: All registers are accessed directly, instead of using the SFR_R() function for speed
+ Direct register access is availabe from the R_(register name) macros.. ex: ACC for the ACC
+ with the exception of the PC
+********************************************************************************************/
+
+//ACALL code addr /* 1: aaa1 0001 */
+OPHANDLER( acall )
+{
+ UINT8 addr = ROP_ARG(PC++); //Grab code address byte
+ PUSH_PC(); //Save PC to the stack
+ //Thanks Gerrit for help with this! :)
+ PC = (PC & 0xf800) | ((r & 0xe0) << 3) | addr;
+}
+
+//ADD A, #data /* 1: 0010 0100 */
+OPHANDLER( add_a_byte )
+{
+ UINT8 data = ROP_ARG(PC++); //Grab data
+ UINT8 result = ACC + data; //Add data to accumulator
+ DO_ADD_FLAGS(ACC,data,0); //Set Flags
+ SET_ACC(result); //Store 8 bit result of addtion in ACC
+}
+
+//ADD A, data addr /* 1: 0010 0101 */
+OPHANDLER( add_a_mem )
+{
+ UINT8 addr = ROP_ARG(PC++); //Grab data address
+ UINT8 data = IRAM_R(addr); //Grab data from data address
+ UINT8 result = ACC + data; //Add data to accumulator
+ DO_ADD_FLAGS(ACC,data,0); //Set Flags
+ SET_ACC(result); //Store 8 bit result of addtion in ACC
+}
+
+//ADD A, @R0/@R1 /* 1: 0010 011i */
+OPHANDLER( add_a_ir )
+{
+ UINT8 data = IRAM_IR(R_REG(r)); //Grab data from memory pointed to by R0 or R1
+ UINT8 result = ACC + data; //Add data to accumulator
+ DO_ADD_FLAGS(ACC,data,0); //Set Flags
+ SET_ACC(result); //Store 8 bit result of addtion in ACC
+}
+
+//ADD A, R0 to R7 /* 1: 0010 1rrr */
+OPHANDLER( add_a_r )
+{
+ UINT8 data = R_REG(r); //Grab data from R0 - R7
+ UINT8 result = ACC + data; //Add data to accumulator
+ DO_ADD_FLAGS(ACC,data,0); //Set Flags
+ SET_ACC(result); //Store 8 bit result of addtion in ACC
+}
+
+//ADDC A, #data /* 1: 0011 0100 */
+OPHANDLER( addc_a_byte )
+{
+ UINT8 data = ROP_ARG(PC++); //Grab data
+ UINT8 result = ACC + data + GET_CY; //Add data + carry flag to accumulator
+ DO_ADD_FLAGS(ACC,data,GET_CY); //Set Flags
+ SET_ACC(result); //Store 8 bit result of addtion in ACC
+}
+
+//ADDC A, data addr /* 1: 0011 0101 */
+OPHANDLER( addc_a_mem )
+{
+ UINT8 addr = ROP_ARG(PC++); //Grab data address
+ UINT8 data = IRAM_R(addr); //Grab data from data address
+ UINT8 result = ACC + data + GET_CY; //Add data + carry flag to accumulator
+ DO_ADD_FLAGS(ACC,data,GET_CY); //Set Flags
+ SET_ACC(result); //Store 8 bit result of addtion in ACC
+}
+
+//ADDC A, @R0/@R1 /* 1: 0011 011i */
+OPHANDLER( addc_a_ir )
+{
+ UINT8 data = IRAM_IR(R_REG(r)); //Grab data from memory pointed to by R0 or R1
+ UINT8 result = ACC + data + GET_CY; //Add data + carry flag to accumulator
+ DO_ADD_FLAGS(ACC,data,GET_CY); //Set Flags
+ SET_ACC(result); //Store 8 bit result of addtion in ACC
+}
+
+//ADDC A, R0 to R7 /* 1: 0011 1rrr */
+OPHANDLER( addc_a_r )
+{
+ UINT8 data = R_REG(r); //Grab data from R0 - R7
+ UINT8 result = ACC + data + GET_CY; //Add data + carry flag to accumulator
+ DO_ADD_FLAGS(ACC,data,GET_CY); //Set Flags
+ SET_ACC(result); //Store 8 bit result of addtion in ACC
+}
+
+//AJMP code addr /* 1: aaa0 0001 */
+OPHANDLER( ajmp )
+{
+ UINT8 addr = ROP_ARG(PC++); //Grab code address byte
+ //Thanks Gerrit for help with this! :)
+ PC = (PC & 0xf800) | ((r & 0xe0) << 3) | addr;
+}
+
+//ANL data addr, A /* 1: 0101 0010 */
+OPHANDLER( anl_mem_a )
+{
+ UINT8 addr = ROP_ARG(PC++); //Grab data address
+ UINT8 data = IRAM_R(addr); //Grab data from data address
+ IRAM_W(addr,data & ACC); //Set data address value to it's value Logical AND with ACC
+}
+
+//ANL data addr, #data /* 1: 0101 0011 */
+OPHANDLER( anl_mem_byte )
+{
+ UINT8 addr = ROP_ARG(PC++); //Grab data address
+ UINT8 data = ROP_ARG(PC++); //Grab data
+ UINT8 srcdata = IRAM_R(addr); //Grab data from data address
+ IRAM_W(addr,srcdata & data); //Set data address value to it's value Logical AND with Data
+}
+
+//ANL A, #data /* 1: 0101 0100 */
+OPHANDLER( anl_a_byte )
+{
+ UINT8 data = ROP_ARG(PC++); //Grab data
+ SET_ACC(ACC & data); //Set ACC to value of ACC Logical AND with Data
+}
+
+//ANL A, data addr /* 1: 0101 0101 */
+OPHANDLER( anl_a_mem )
+{
+ UINT8 addr = ROP_ARG(PC++); //Grab data address
+ UINT8 data = IRAM_R(addr); //Grab data from data address
+ SET_ACC(ACC & data); //Set ACC to value of ACC Logical AND with Data
+}
+
+//ANL A, @RO/@R1 /* 1: 0101 011i */
+OPHANDLER( anl_a_ir )
+{
+ UINT8 data = IRAM_IR(R_REG(r)); //Grab data from address R0 or R1 points to
+ SET_ACC(ACC & data); //Set ACC to value of ACC Logical AND with Data
+}
+
+//ANL A, RO to R7 /* 1: 0101 1rrr */
+OPHANDLER( anl_a_r )
+{
+ UINT8 data = R_REG(r); //Grab data from R0 - R7
+ SET_ACC(ACC & data); //Set ACC to value of ACC Logical AND with Data
+}
+
+//ANL C, bit addr /* 1: 1000 0010 */
+OPHANDLER( anl_c_bitaddr )
+{
+ int cy = GET_CY;
+ UINT8 addr = ROP_ARG(PC++); //Grab bit address
+ UINT8 bit = BIT_R(addr); //Grab bit data from bit address
+ SET_CY( (cy & bit) ); //Set Carry flag to Carry Flag Value Logical AND with Bit
+}
+
+//ANL C,/bit addr /* 1: 1011 0000 */
+OPHANDLER( anl_c_nbitaddr )
+{
+ int cy = GET_CY;
+ UINT8 addr = ROP_ARG(PC++); //Grab bit address
+ UINT8 bit = BIT_R(addr); //Grab bit data from bit address
+ bit = ((~bit)&1); //Complement bit
+ SET_CY( (cy & bit) ); //Set Carry flag to Carry Flag Value Logical AND with Complemented Bit
+}
+
+//CJNE A, #data, code addr /* 1: 1011 0100 */
+OPHANDLER( cjne_a_byte )
+{
+ UINT8 data = ROP_ARG(PC++); //Grab data
+ INT8 rel_addr = ROP_ARG(PC++); //Grab relative code address
+
+ if(ACC != data) //Jump if values are not equal
+ {
+ PC = PC + rel_addr;
+ }
+
+ //Set carry flag to 1 if 1st compare value is < 2nd compare value
+ SET_CY( (ACC < data) );
+}
+
+//CJNE A, data addr, code addr /* 1: 1011 0101 */
+OPHANDLER( cjne_a_mem )
+{
+ UINT8 addr = ROP_ARG(PC++); //Grab data address
+ INT8 rel_addr = ROP_ARG(PC++); //Grab relative code address
+ UINT8 data = IRAM_R(addr); //Pull value from data address
+
+ if(ACC != data) //Jump if values are not equal
+ {
+ PC = PC + rel_addr;
+ }
+
+ //Set carry flag to 1 if 1st compare value is < 2nd compare value
+ SET_CY( (ACC < data) );
+}
+
+//CJNE @R0/@R1, #data, code addr /* 1: 1011 011i */
+OPHANDLER( cjne_ir_byte )
+{
+ UINT8 data = ROP_ARG(PC++); //Grab data
+ INT8 rel_addr = ROP_ARG(PC++); //Grab relative code address
+ UINT8 srcdata = IRAM_IR(R_REG(r)); //Grab value pointed to by R0 or R1
+
+ if(srcdata != data) //Jump if values are not equal
+ {
+ PC = PC + rel_addr;
+ }
+
+ //Set carry flag to 1 if 1st compare value is < 2nd compare value
+ SET_CY( (srcdata < data) );
+}
+
+//CJNE R0 to R7, #data, code addr /* 1: 1011 1rrr */
+OPHANDLER( cjne_r_byte )
+{
+ UINT8 data = ROP_ARG(PC++); //Grab data
+ INT8 rel_addr = ROP_ARG(PC++); //Grab relative code address
+ UINT8 srcdata = R_REG(r); //Grab value of R0 - R7
+
+ if(srcdata != data) //Jump if values are not equal
+ {
+ PC = PC + rel_addr;
+ }
+
+ //Set carry flag to 1 if 1st compare value is < 2nd compare value
+ SET_CY( (srcdata < data) );
+}
+
+//CLR bit addr /* 1: 1100 0010 */
+OPHANDLER( clr_bitaddr )
+{
+ UINT8 addr = ROP_ARG(PC++); //Grab bit address
+ BIT_W(addr,0); //Clear bit at specified bit address
+}
+
+//CLR C /* 1: 1100 0011 */
+OPHANDLER( clr_c )
+{
+ SET_CY(0); //Clear Carry Flag
+}
+
+//CLR A /* 1: 1110 0100 */
+OPHANDLER( clr_a )
+{
+ SET_ACC(0); //Clear Accumulator
+}
+
+//CPL bit addr /* 1: 1011 0010 */
+OPHANDLER( cpl_bitaddr )
+{
+ UINT8 addr = ROP_ARG(PC++); //Grab bit address
+ UINT8 data = (~BIT_R(addr))&1;
+ BIT_W(addr,data); //Complement bit at specified bit address
+}
+
+//CPL C /* 1: 1011 0011 */
+OPHANDLER( cpl_c )
+{
+ UINT8 bit = (~GET_CY)&1; //Complement Carry Flag
+ SET_CY(bit);
+}
+
+//CPL A /* 1: 1111 0100 */
+OPHANDLER( cpl_a )
+{
+ UINT8 data = ((~ACC)&0xff);
+ SET_ACC(data); //Complement Accumulator
+}
+
+//DA A /* 1: 1101 0100 */
+OPHANDLER( da_a )
+{
+/*From several sources, since none said the same thing:
+ The decimal adjust instruction is associated with the use of the ADD and ADDC instructions.
+ The eight-bit value in the accumulator is adjusted to form two BCD digits of four bits each.
+ If the accumulator contents bits 0-3 are greater than 9, OR the AC flag is set, then six is added to
+ produce a proper BCD digit.
+ If the carry is set, OR the four high bits 4-7 exceed nine, six is added to the value of these bits.
+ The carry flag will be set if the result is > 0x99, but not cleared otherwise */
+
+ UINT16 new_acc = ACC & 0xff;
+ if(GET_AC || (new_acc & 0x0f) > 0x09)
+ new_acc += 0x06;
+ if(GET_CY || ((new_acc & 0xf0) > 0x90) || (new_acc & ~0xff))
+ new_acc += 0x60;
+ SET_ACC(new_acc&0xff);
+ if(new_acc & ~0xff)
+ SET_CY(1);
+}
+
+//DEC A /* 1: 0001 0100 */
+OPHANDLER( dec_a )
+{
+ SET_ACC(ACC-1);
+}
+
+//DEC data addr /* 1: 0001 0101 */
+OPHANDLER( dec_mem )
+{
+ UINT8 addr = ROP_ARG(PC++); //Grab data address
+ UINT8 data = IRAM_R(addr);
+ IRAM_W(addr,data-1);
+}
+
+//DEC @R0/@R1 /* 1: 0001 011i */
+OPHANDLER( dec_ir )
+{
+ UINT8 data = IRAM_IR(R_REG(r));
+ IRAM_W(R_REG(r),data-1);
+}
+
+//DEC R0 to R7 /* 1: 0001 1rrr */
+OPHANDLER( dec_r )
+{
+ SET_REG(r, R_REG(r) - 1);
+}
+
+//DIV AB /* 1: 1000 0100 */
+OPHANDLER( div_ab )
+{
+ if( B == 0 ) {
+ //Overflow flag is set!
+ SET_OV(1);
+ //Really the values are undefined according to the manual, but we'll just leave them as is..
+ //SET_ACC(0xff);
+ //SFR_W(B,0xff);
+ }
+ else {
+ int a = (int)ACC / B;
+ int b = (int)ACC % B;
+ //A gets quotient byte, B gets remainder byte
+ SET_ACC(a);
+ B = b;
+ //Overflow flag is cleared
+ SET_OV(0);
+ }
+ //Carry Flag is always cleared
+ SET_CY(0);
+}
+
+//DJNZ data addr, code addr /* 1: 1101 0101 */
+OPHANDLER( djnz_mem )
+{
+ UINT8 addr = ROP_ARG(PC++); //Grab data address
+ INT8 rel_addr = ROP_ARG(PC++); //Grab relative code address
+ IRAM_W(addr,IRAM_R(addr) - 1); //Decrement value contained at data address
+ if(IRAM_R(addr) != 0) //Branch if contents of data address is not 0
+ {
+ PC = PC + rel_addr;
+ }
+}
+
+//DJNZ R0 to R7,code addr /* 1: 1101 1rrr */
+OPHANDLER( djnz_r )
+{
+ INT8 rel_addr = ROP_ARG(PC++); //Grab relative code address
+ SET_REG(r ,R_REG(r) - 1); //Decrement value
+ if(R_REG(r) != 0) //Branch if contents of R0 - R7 is not 0
+ {
+ PC = PC + rel_addr;
+ }
+}
+
+//INC A /* 1: 0000 0100 */
+OPHANDLER( inc_a )
+{
+ SET_ACC(ACC+1);
+}
+
+//INC data addr /* 1: 0000 0101 */
+OPHANDLER( inc_mem )
+{
+ UINT8 addr = ROP_ARG(PC++); //Grab data address
+ UINT8 data = IRAM_R(addr);
+ IRAM_W(addr,data+1);
+}
+
+//INC @R0/@R1 /* 1: 0000 011i */
+OPHANDLER( inc_ir )
+{
+ UINT8 data = IRAM_IR(R_REG(r));
+ IRAM_W(R_REG(r),data+1);
+}
+
+//INC R0 to R7 /* 1: 0000 1rrr */
+OPHANDLER( inc_r )
+{
+ UINT8 data = R_REG(r);
+ SET_REG(r, data + 1);
+}
+
+//INC DPTR /* 1: 1010 0011 */
+OPHANDLER( inc_dptr )
+{
+ UINT16 dptr = (DPTR)+1;
+ SET_DPTR(dptr);
+}
+
+//JB bit addr, code addr /* 1: 0010 0000 */
+OPHANDLER( jb )
+{
+ UINT8 addr = ROP_ARG(PC++); //Grab bit address
+ INT8 rel_addr = ROP_ARG(PC++); //Grab relative code address
+ if(BIT_R(addr)) //If bit set at specified bit address, jump
+ {
+ PC = PC + rel_addr;
+ }
+}
+
+//JBC bit addr, code addr /* 1: 0001 0000 */
+OPHANDLER( jbc )
+{
+ UINT8 addr = ROP_ARG(PC++); //Grab bit address
+ INT8 rel_addr = ROP_ARG(PC++); //Grab relative code address
+ if(BIT_R(addr)) { //If bit set at specified bit address, jump
+ PC = PC + rel_addr;
+ BIT_W(addr,0); //Clear Bit also
+ }
+}
+
+//JC code addr /* 1: 0100 0000 */
+OPHANDLER( jc )
+{
+ INT8 rel_addr = ROP_ARG(PC++); //Grab relative code address
+ if(GET_CY) //Jump if Carry Flag Set
+ {
+ PC = PC + rel_addr;
+ }
+}
+
+//JMP @A+DPTR /* 1: 0111 0011 */
+OPHANDLER( jmp_iadptr )
+{
+ PC = ACC + DPTR;
+}
+
+//JNB bit addr, code addr /* 1: 0011 0000 */
+OPHANDLER( jnb )
+{
+ UINT8 addr = ROP_ARG(PC++); //Grab bit address
+ INT8 rel_addr = ROP_ARG(PC++); //Grab relative code address
+ if(!BIT_R(addr)) //If bit NOT set at specified bit address, jump
+ {
+ PC = PC + rel_addr;
+ }
+}
+
+//JNC code addr /* 1: 0101 0000 */
+OPHANDLER( jnc )
+{
+ INT8 rel_addr = ROP_ARG(PC++); //Grab relative code address
+ if(!GET_CY) //Jump if Carry Flag not set
+ {
+ PC = PC + rel_addr;
+ }
+}
+
+//JNZ code addr /* 1: 0111 0000 */
+OPHANDLER( jnz )
+{
+ INT8 rel_addr = ROP_ARG(PC++); //Grab relative code address
+ if(ACC != 0) //Branch if ACC is not 0
+ {
+ PC = PC+rel_addr;
+ }
+}
+
+//JZ code addr /* 1: 0110 0000 */
+OPHANDLER( jz )
+{
+ INT8 rel_addr = ROP_ARG(PC++); //Grab relative code address
+ if(ACC == 0) //Branch if ACC is 0
+ {
+ PC = PC+rel_addr;
+ }
+}
+
+//LCALL code addr /* 1: 0001 0010 */
+OPHANDLER( lcall )
+{
+ UINT8 addr_hi, addr_lo;
+ addr_hi = ROP_ARG(PC++);
+ addr_lo = ROP_ARG(PC++);
+ PUSH_PC();
+ PC = (UINT16)((addr_hi<<8) | addr_lo);
+}
+
+//LJMP code addr /* 1: 0000 0010 */
+OPHANDLER( ljmp )
+{
+ UINT8 addr_hi, addr_lo;
+ addr_hi = ROP_ARG(PC++);
+ addr_lo = ROP_ARG(PC++);
+ PC = (UINT16)((addr_hi<<8) | addr_lo);
+}
+
+//MOV A, #data /* 1: 0111 0100 */
+OPHANDLER( mov_a_byte )
+{
+ UINT8 data = ROP_ARG(PC++); //Grab data
+ SET_ACC(data); //Store data to ACC
+}
+
+//MOV A, data addr /* 1: 1110 0101 */
+OPHANDLER( mov_a_mem )
+{
+ UINT8 addr = ROP_ARG(PC++); //Grab data address
+ SET_ACC(IRAM_R(addr)); //Store contents of data address to ACC
+}
+
+//MOV A,@RO/@R1 /* 1: 1110 011i */
+OPHANDLER( mov_a_ir )
+{
+ SET_ACC(IRAM_IR(R_REG(r))); //Store contents of address pointed by R0 or R1 to ACC
+}
+
+//MOV A,R0 to R7 /* 1: 1110 1rrr */
+OPHANDLER( mov_a_r )
+{
+ SET_ACC(R_REG(r)); //Store contents of R0 - R7 to ACC
+}
+
+//MOV data addr, #data /* 1: 0111 0101 */
+OPHANDLER( mov_mem_byte )
+{
+ UINT8 addr = ROP_ARG(PC++); //Grab data address
+ UINT8 data = ROP_ARG(PC++); //Grab data
+ IRAM_W(addr,data); //Store data to data address location
+}
+
+//MOV data addr, data addr /* 1: 1000 0101 */
+OPHANDLER( mov_mem_mem )
+{
+ //1st address is src, 2nd is dst, but the mov command works as mov dst,src)
+ UINT8 src,dst;
+ src = ROP_ARG(PC++); //Grab source data address
+ dst = ROP_ARG(PC++); //Grab destination data address
+ IRAM_W(dst,IRAM_R(src)); //Read source address contents and store to destination address
+}
+
+//MOV @R0/@R1, #data /* 1: 0111 011i */
+OPHANDLER( mov_ir_byte )
+{
+ UINT8 data = ROP_ARG(PC++); //Grab data
+ IRAM_IW(R_REG(r),data); //Store data to address pointed by R0 or R1
+}
+
+//MOV R0 to R7, #data /* 1: 0111 1rrr */
+OPHANDLER( mov_r_byte )
+{
+ UINT8 data = ROP_ARG(PC++); //Grab data
+ SET_REG(r, data); //Store to R0 - R7
+}
+
+//MOV data addr, @R0/@R1 /* 1: 1000 011i */
+OPHANDLER( mov_mem_ir )
+{
+ UINT8 addr = ROP_ARG(PC++); //Grab data address
+ IRAM_W(addr,IRAM_IR(R_REG(r))); //Store contents pointed to by R0 or R1 to data address
+}
+
+//MOV data addr,R0 to R7 /* 1: 1000 1rrr */
+OPHANDLER( mov_mem_r )
+{
+ UINT8 addr = ROP_ARG(PC++); //Grab data address
+ IRAM_W(addr,R_REG(r)); //Store contents of R0 - R7 to data address
+}
+
+//MOV DPTR, #data16 /* 1: 1001 0000 */
+OPHANDLER( mov_dptr_byte )
+{
+ UINT8 data_hi, data_lo;
+ data_hi = ROP_ARG(PC++); //Grab hi byte
+ data_lo = ROP_ARG(PC++); //Grab lo byte
+ SET_DPTR((UINT16)((data_hi<<8)|data_lo)); //Store to DPTR
+}
+
+//MOV bit addr, C /* 1: 1001 0010 */
+OPHANDLER( mov_bitaddr_c )
+{
+ UINT8 addr = ROP_ARG(PC++); //Grab bit address
+ BIT_W(addr,GET_CY); //Store Carry Flag to Bit Address
+}
+
+//MOV @R0/@R1, data addr /* 1: 1010 011i */
+OPHANDLER( mov_ir_mem )
+{
+ UINT8 addr = ROP_ARG(PC++); //Grab data address
+ IRAM_IW(R_REG(r),IRAM_R(addr)); //Store data from data address to address pointed to by R0 or R1
+}
+
+//MOV R0 to R7, data addr /* 1: 1010 1rrr */
+OPHANDLER( mov_r_mem )
+{
+ UINT8 addr = ROP_ARG(PC++); //Grab data address
+ SET_REG(r, IRAM_R(addr)); //Store to R0 - R7
+}
+
+//MOV data addr, A /* 1: 1111 0101 */
+OPHANDLER( mov_mem_a )
+{
+ UINT8 addr = ROP_ARG(PC++); //Grab data address
+ IRAM_W(addr,ACC); //Store A to data address
+}
+
+//MOV @R0/@R1, A /* 1: 1111 011i */
+OPHANDLER( mov_ir_a )
+{
+ IRAM_IW(R_REG(r),ACC); //Store A to location pointed to by R0 or R1
+}
+
+//MOV R0 to R7, A /* 1: 1111 1rrr */
+OPHANDLER( mov_r_a )
+{
+ SET_REG(r, ACC); //Store A to R0-R7
+}
+
+//MOVC A, @A + PC /* 1: 1000 0011 */
+OPHANDLER( movc_a_iapc )
+{
+ UINT8 data;
+ data = CODEMEM_R(ACC+PC); //Move a byte from CODE(Program) Memory and store to ACC
+ SET_ACC(data);
+}
+
+//MOV C, bit addr /* 1: 1010 0010 */
+OPHANDLER( mov_c_bitaddr )
+{
+ UINT8 addr = ROP_ARG(PC++); //Grab bit address
+ SET_CY( (BIT_R(addr)) ); //Store Bit from Bit Address to Carry Flag
+}
+
+//MOVC A, @A + DPTR /* 1: 1001 0011 */
+OPHANDLER( movc_a_iadptr )
+{
+ UINT8 data;
+ data = CODEMEM_R(ACC + DPTR); //Move a byte from CODE(Program) Memory and store to ACC
+ SET_ACC(data);
+}
+
+//MOVX A,@DPTR /* 1: 1110 0000 */
+//(Move External Ram 16 bit address to A)
+OPHANDLER( movx_a_idptr )
+{
+// UINT8 byte = DATAMEM_R(R_DPTR); //Grab 1 byte from External DATA memory pointed to by dptr
+ UINT32 addr = ERAM_ADDR(DPTR, 0xFFFF);
+ UINT8 byte = DATAMEM_R(addr); //Grab 1 byte from External DATA memory pointed to by dptr
+ SET_ACC(byte); //Store to ACC
+}
+
+//MOVX A, @R0/@R1 /* 1: 1110 001i */
+//(Move External Ram 8 bit address to A)
+OPHANDLER( movx_a_ir )
+{
+ UINT32 addr = ERAM_ADDR(R_REG(r),0xFF); //Grab address by reading location pointed to by R0 or R1
+ UINT8 byte = DATAMEM_R(addr); //Grab 1 byte from External DATA memory pointed to by address
+ SET_ACC(byte); //Store to ACC
+}
+
+//MOVX @DPTR,A /* 1: 1111 0000 */
+//(Move A to External Ram 16 bit address)
+OPHANDLER( movx_idptr_a )
+{
+// DATAMEM_W(R_DPTR, ACC); //Store ACC to External DATA memory address pointed to by DPTR
+ UINT32 addr = ERAM_ADDR(DPTR, 0xFFFF);
+ DATAMEM_W(addr, ACC); //Store ACC to External DATA memory address pointed to by DPTR
+}
+
+//MOVX @R0/@R1,A /* 1: 1111 001i */
+//(Move A to External Ram 8 bit address)
+OPHANDLER( movx_ir_a )
+{
+ UINT32 addr = ERAM_ADDR(R_REG(r),0xFF); //Grab address by reading location pointed to by R0 or R1
+ DATAMEM_W(addr, ACC); //Store ACC to External DATA memory address
+}
+
+//MUL AB /* 1: 1010 0100 */
+OPHANDLER( mul_ab )
+{
+ UINT16 result = ACC * B;
+ //A gets lo bits, B gets hi bits of result
+ B = (UINT8) ((result & 0xFF00) >> 8);
+ SET_ACC((UINT8)(result & 0x00FF));
+ //Set flags
+ SET_OV( ((result & 0x100) >> 8) ); //Set/Clear Overflow Flag if result > 255
+ SET_CY(0); //Carry Flag always cleared
+}
+
+//NOP /* 1: 0000 0000 */
+OPHANDLER( nop )
+{
+}
+
+//ORL data addr, A /* 1: 0100 0010 */
+OPHANDLER( orl_mem_a )
+{
+ UINT8 addr = ROP_ARG(PC++); //Grab data address
+ UINT8 data = IRAM_R(addr); //Grab data from data address
+ IRAM_W(addr,data | ACC); //Set data address value to it's value Logical OR with ACC
+}
+
+//ORL data addr, #data /* 1: 0100 0011 */
+OPHANDLER( orl_mem_byte )
+{
+ UINT8 addr = ROP_ARG(PC++); //Grab data address
+ UINT8 data = ROP_ARG(PC++); //Grab data
+ UINT8 srcdata = IRAM_R(addr); //Grab data from data address
+ IRAM_W(addr,srcdata | data); //Set data address value to it's value Logical OR with Data
+}
+
+//ORL A, #data /* 1: 0100 0100 */
+OPHANDLER( orl_a_byte )
+{
+ UINT8 data = ROP_ARG(PC++); //Grab data
+ SET_ACC(ACC | data); //Set ACC to value of ACC Logical OR with Data
+}
+
+//ORL A, data addr /* 1: 0100 0101 */
+OPHANDLER( orl_a_mem )
+{
+ UINT8 addr = ROP_ARG(PC++); //Grab data address
+ UINT8 data = IRAM_R(addr); //Grab data from data address
+ SET_ACC(ACC | data); //Set ACC to value of ACC Logical OR with Data
+}
+
+//ORL A, @RO/@R1 /* 1: 0100 011i */
+OPHANDLER( orl_a_ir )
+{
+ UINT8 data = IRAM_IR(R_REG(r)); //Grab data from address R0 or R1 points to
+ SET_ACC(ACC | data); //Set ACC to value of ACC Logical OR with Data
+}
+
+//ORL A, RO to R7 /* 1: 0100 1rrr */
+OPHANDLER( orl_a_r )
+{
+ UINT8 data = R_REG(r); //Grab data from R0 - R7
+ SET_ACC(ACC | data); //Set ACC to value of ACC Logical OR with Data
+}
+
+//ORL C, bit addr /* 1: 0111 0010 */
+OPHANDLER( orl_c_bitaddr )
+{
+ int cy = GET_CY;
+ UINT8 addr = ROP_ARG(PC++); //Grab bit address
+ UINT8 bit = BIT_R(addr); //Grab bit data from bit address
+ SET_CY( (cy | bit) ); //Set Carry flag to Carry Flag Value Logical OR with Bit
+}
+
+//ORL C, /bit addr /* 1: 1010 0000 */
+OPHANDLER( orl_c_nbitaddr )
+{
+ int cy = GET_CY;
+ UINT8 addr = ROP_ARG(PC++); //Grab bit address
+ UINT8 bit = BIT_R(addr); //Grab bit data from bit address
+ bit = ((~bit)&1); //Complement bit
+ SET_CY( (cy | bit) ); //Set Carry flag to Carry Flag Value Logical OR with Complemented Bit
+}
+
+//POP data addr /* 1: 1101 0000 */
+OPHANDLER( pop )
+{
+ UINT8 addr = ROP_ARG(PC++); //Grab data address
+ IRAM_W(addr, IRAM_IR(SP)); //Store to contents of data addr, data pointed to by Stack - IRAM_IR needed to access upper 128 bytes of stack
+ //IRAM_IW(addr, IRAM_IR(R_SP)); //Store to contents of data addr, data pointed to by Stack - doesn't work, sfr's are not restored this way and it's not an indirect access anyway
+ SP = SP-1; //Decrement SP
+}
+
+//PUSH data addr /* 1: 1100 0000 */
+OPHANDLER( push )
+{
+ UINT8 addr = ROP_ARG(PC++); //Grab data address
+ UINT8 tmpSP = SP+1; //Grab and Increment Stack Pointer
+ SP = tmpSP; // ""
+ IRAM_IW(tmpSP, IRAM_R(addr)); //Store to stack contents of data address - IRAM_IW needed to store to upper 128 bytes of stack, however, can't use IRAM_IR because that won't store the sfrs and it's not an indirect access anyway
+}
+
+//RET /* 1: 0010 0010 */
+OPHANDLER( ret )
+{
+ POP_PC();
+}
+
+//RETI /* 1: 0011 0010 */
+OPHANDLER( reti )
+{
+ POP_PC();
+ CLEAR_CURRENT_IRQ();
+}
+
+//RL A /* 1: 0010 0011 */
+OPHANDLER( rl_a )
+{
+ //Left Shift A, Bit 7 carries to Bit 0
+ int carry = ((ACC & 0x80) >> 7);
+ int data = (ACC<<1) & 0xfe;
+ SET_ACC( data | carry);
+}
+
+//RLC A /* 1: 0011 0011 */
+OPHANDLER( rlc_a )
+{
+ //Left Shift A, Bit 7 goes to Carry Flag, Original Carry Flag goes to Bit 0 of ACC
+ int carry = ((ACC & 0x80) >> 7);
+ int data = ((ACC<<1) & 0xfe) | GET_CY;
+ SET_ACC( data);
+ SET_CY(carry);
+}
+
+//RR A /* 1: 0000 0011 */
+OPHANDLER( rr_a )
+{
+ //Right Shift A, Bit 0 carries to Bit 7
+ int carry = ((ACC & 1) << 7);
+ int data = (ACC>>1) & 0x7f;
+ SET_ACC( data | carry);
+}
+
+//RRC A /* 1: 0001 0011 */
+OPHANDLER( rrc_a )
+{
+ //Right Shift A, Bit 0 goes to Carry Flag, Bit 7 of ACC gets set to original Carry Flag
+ int carry = (ACC & 1);
+ int data = ((ACC>>1) & 0x7f) | (GET_CY<<7);
+ SET_ACC( data);
+ SET_CY(carry);
+}
+
+//SETB C /* 1: 1101 0011 */
+OPHANDLER( setb_c )
+{
+ SET_CY(1); //Set Carry Flag
+}
+
+//SETB bit addr /* 1: 1101 0010 */
+OPHANDLER( setb_bitaddr )
+{
+ UINT8 addr = ROP_ARG(PC++); //Grab bit address
+ BIT_W(addr,1); //Set Bit at Bit Address
+}
+
+//SJMP code addr /* 1: 1000 0000 */
+OPHANDLER( sjmp )
+{
+ INT8 rel_addr = ROP_ARG(PC++); //Grab relative code address
+ PC = PC + rel_addr; //Update PC
+}
+
+//SUBB A, #data /* 1: 1001 0100 */
+OPHANDLER( subb_a_byte )
+{
+ UINT8 data = ROP_ARG(PC++); //Grab data
+ UINT8 result = ACC - data - GET_CY; //Subtract data & carry flag from accumulator
+ DO_SUB_FLAGS(ACC,data,GET_CY); //Set Flags
+ SET_ACC(result); //Store 8 bit result of addtion in ACC
+
+}
+
+//SUBB A, data addr /* 1: 1001 0101 */
+OPHANDLER( subb_a_mem )
+{
+ UINT8 addr = ROP_ARG(PC++); //Grab data address
+ UINT8 data = IRAM_R(addr); //Grab data from data address
+ UINT8 result = ACC - data - GET_CY; //Subtract data & carry flag from accumulator
+ DO_SUB_FLAGS(ACC,data,GET_CY); //Set Flags
+ SET_ACC(result); //Store 8 bit result of addtion in ACC
+}
+
+//SUBB A, @R0/@R1 /* 1: 1001 011i */
+OPHANDLER( subb_a_ir )
+{
+ UINT8 data = IRAM_IR(R_REG(r)); //Grab data from memory pointed to by R0 or R1
+ UINT8 result = ACC - data - GET_CY; //Subtract data & carry flag from accumulator
+ DO_SUB_FLAGS(ACC,data,GET_CY); //Set Flags
+ SET_ACC(result); //Store 8 bit result of addtion in ACC
+}
+
+//SUBB A, R0 to R7 /* 1: 1001 1rrr */
+OPHANDLER( subb_a_r )
+{
+ UINT8 data = R_REG(r); //Grab data from R0 - R7
+ UINT8 result = ACC - data - GET_CY; //Subtract data & carry flag from accumulator
+ DO_SUB_FLAGS(ACC,data,GET_CY); //Set Flags
+ SET_ACC(result); //Store 8 bit result of addtion in ACC
+}
+
+//SWAP A /* 1: 1100 0100 */
+OPHANDLER( swap_a )
+{
+ UINT8 a_nib_lo, a_nib_hi;
+ a_nib_hi = (ACC & 0x0f) << 4; //Grab lo byte of ACC and move to hi
+ a_nib_lo = (ACC & 0xf0) >> 4; //Grab hi byte of ACC and move to lo
+ SET_ACC( a_nib_hi | a_nib_lo);
+}
+
+//XCH A, data addr /* 1: 1100 0101 */
+OPHANDLER( xch_a_mem )
+{
+ UINT8 addr = ROP_ARG(PC++); //Grab data address
+ UINT8 data = IRAM_R(addr); //Grab data
+ UINT8 oldACC = ACC; //Hold value of ACC
+ SET_ACC(data); //Sets ACC to data
+ IRAM_W(addr,oldACC); //Sets data address to old value of ACC
+}
+
+//XCH A, @RO/@R1 /* 1: 1100 011i */
+OPHANDLER( xch_a_ir )
+{
+ UINT8 data = IRAM_IR(R_REG(r)); //Grab data pointed to by R0 or R1
+ UINT8 oldACC = ACC; //Hold value of ACC
+ SET_ACC(data); //Sets ACC to data
+ IRAM_W(R_REG(r),oldACC); //Sets data address to old value of ACC
+}
+
+//XCH A, RO to R7 /* 1: 1100 1rrr */
+OPHANDLER( xch_a_r )
+{
+ UINT8 data = R_REG(r); //Grab data from R0-R7
+ UINT8 oldACC = ACC; //Hold value of ACC
+ SET_ACC(data); //Sets ACC to data
+ SET_REG(r, oldACC); //Sets data address to old value of ACC
+}
+
+//XCHD A, @R0/@R1 /* 1: 1101 011i */
+OPHANDLER( xchd_a_ir )
+{
+ UINT8 acc, ir_data;
+ ir_data = IRAM_IR(R_REG(r)); //Grab data pointed to by R0 or R1
+ acc = ACC; //Grab ACC value
+ SET_ACC( (acc & 0xf0) | (ir_data & 0x0f) ); //Set ACC to lower nibble of data pointed to by R0 or R1
+ IRAM_W(R_REG(r), (ir_data & 0xf0) | (acc & 0x0f) ); //Set data pointed to by R0 or R1 to lower nibble of ACC
+}
+
+//XRL data addr, A /* 1: 0110 0010 */
+OPHANDLER( xrl_mem_a )
+{
+ UINT8 addr = ROP_ARG(PC++); //Grab data address
+ UINT8 data = IRAM_R(addr); //Grab data from data address
+ IRAM_W(addr,data ^ ACC); //Set data address value to it's value Logical XOR with ACC
+}
+
+//XRL data addr, #data /* 1: 0110 0011 */
+OPHANDLER( xrl_mem_byte )
+{
+ UINT8 addr = ROP_ARG(PC++); //Grab data address
+ UINT8 data = ROP_ARG(PC++); //Grab data
+ UINT8 srcdata = IRAM_R(addr); //Grab data from data address
+ IRAM_W(addr,srcdata ^ data); //Set data address value to it's value Logical XOR with Data
+}
+
+//XRL A, #data /* 1: 0110 0100 */
+OPHANDLER( xrl_a_byte )
+{
+ UINT8 data = ROP_ARG(PC++); //Grab data
+ SET_ACC(ACC ^ data); //Set ACC to value of ACC Logical XOR with Data
+}
+
+//XRL A, data addr /* 1: 0110 0101 */
+OPHANDLER( xrl_a_mem )
+{
+ UINT8 addr = ROP_ARG(PC++); //Grab data address
+ UINT8 data = IRAM_R(addr); //Grab data from data address
+ SET_ACC(ACC ^ data); //Set ACC to value of ACC Logical XOR with Data
+}
+
+//XRL A, @R0/@R1 /* 1: 0110 011i */
+OPHANDLER( xrl_a_ir )
+{
+ UINT8 data = IRAM_IR(R_REG(r)); //Grab data from address R0 or R1 points to
+ SET_ACC(ACC ^ data); //Set ACC to value of ACC Logical XOR with Data
+}
+
+//XRL A, R0 to R7 /* 1: 0110 1rrr */
+OPHANDLER( xrl_a_r )
+{
+ UINT8 data = R_REG(r); //Grab data from R0 - R7
+ SET_ACC(ACC ^ data); //Set ACC to value of ACC Logical XOR with Data
+}
+
+//illegal opcodes
+OPHANDLER( illegal )
+{
+ LOG(("i8051 '%s': illegal opcode at 0x%03x: %02x\n", mcs51_state->device->tag(), PC-1, r));
+}
diff --git a/trunk/src/emu/cpu/minx/minx.c b/trunk/src/emu/cpu/minx/minx.c
new file mode 100644
index 00000000000..59fa2138597
--- /dev/null
+++ b/trunk/src/emu/cpu/minx/minx.c
@@ -0,0 +1,397 @@
+/*
+ Implementation for the Nintendo Minx CPU.
+
+ Registers (mindX13.txt):
+ 8bit: A B H L FLAGS N U V
+ 16bit: BA
+ 24bit: HL, X1, X2, NN, SP
+
+
+ "sunlab":
+ 16bit:
+ V:PC if high bit set, extended to 23 bits, upper 8 bits V
+ SP
+ BA
+ I:HL
+ (XI:)X
+ (YI:)Y
+
+ 8bit:
+ A, B, H, L
+ U - delayed jump bank. When a jump occurs, V is set to this value
+ V
+ F - flags IDLBSOCZ
+ I - Interrupt branch
+ D - Interrupt disable
+ L - low mask mode enable
+ B - bcd decimal mode enable
+ S - sign flag
+ O - overflow flag
+ C - carry flag
+ Z - zero flag
+ E - exception register
+ I
+ N
+ XI - index/extension
+ YI - index/extension
+
+TODO:
+- Add support for O and C flags in NEG8 instruction
+- Verify MUL (CE D8) and DIV (CE D9)
+- Doublecheck behaviour of CMPN instructions ( CF 60 .. CF 63 )
+
+*/
+
+#include "emu.h"
+#include "debugger.h"
+#include "minx.h"
+
+#define FLAG_I 0x80
+#define FLAG_D 0x40
+#define FLAG_L 0x20
+#define FLAG_B 0x10
+#define FLAG_S 0x08
+#define FLAG_O 0x04
+#define FLAG_C 0x02
+#define FLAG_Z 0x01
+
+#define EXEC_X0 0x80
+#define EXEC_X1 0x40
+#define EXEC_X2 0x20
+#define EXEC_DZ 0x10
+#define EXEC_EN 0x08
+#define EXEC_04 0x04
+#define EXEC_02 0x02
+#define EXEC_01 0x01
+
+
+typedef struct {
+// MINX_CONFIG config;
+ UINT16 PC;
+ UINT16 SP;
+ UINT16 BA;
+ UINT16 HL;
+ UINT16 X;
+ UINT16 Y;
+ UINT8 U;
+ UINT8 V;
+ UINT8 F;
+ UINT8 E;
+ UINT8 N;
+ UINT8 I;
+ UINT8 XI;
+ UINT8 YI;
+ UINT8 halted;
+ UINT8 interrupt_pending;
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ address_space *program;
+ int icount;
+} minx_state;
+
+#define RD(offset) minx->program->read_byte( offset )
+#define WR(offset,data) minx->program->write_byte( offset, data )
+#define GET_MINX_PC ( ( minx->PC & 0x8000 ) ? ( minx->V << 15 ) | (minx->PC & 0x7FFF ) : minx->PC )
+
+INLINE minx_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == MINX);
+
+ return (minx_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+INLINE UINT16 rd16( minx_state *minx, UINT32 offset )
+{
+ return RD( offset ) | ( RD( offset + 1 ) << 8 );
+}
+
+
+INLINE void wr16( minx_state *minx, UINT32 offset, UINT16 data )
+{
+ WR( offset, ( data & 0x00FF ) );
+ WR( offset + 1, ( data >> 8 ) );
+}
+
+
+static CPU_INIT( minx )
+{
+ minx_state *minx = get_safe_token(device);
+ minx->irq_callback = irqcallback;
+ minx->device = device;
+ minx->program = device->space(AS_PROGRAM);
+ if ( device->static_config() != NULL )
+ {
+ }
+ else
+ {
+ }
+}
+
+
+static CPU_RESET( minx )
+{
+ minx_state *minx = get_safe_token(device);
+ minx->SP = minx->BA = minx->HL = minx->X = minx->Y = 0;
+ minx->U = minx->V = minx->F = minx->E = minx->I = minx->XI = minx->YI = 0;
+ minx->halted = minx->interrupt_pending = 0;
+
+ minx->PC = rd16( minx, 0 );
+}
+
+
+static CPU_EXIT( minx )
+{
+}
+
+
+INLINE UINT8 rdop( minx_state *minx )
+{
+ UINT8 op = RD( GET_MINX_PC );
+ minx->PC++;
+ return op;
+}
+
+
+INLINE UINT16 rdop16( minx_state *minx )
+{
+ UINT16 op = rdop(minx);
+ op = op | ( rdop(minx) << 8 );
+ return op;
+}
+
+
+#include "minxfunc.h"
+#include "minxopce.h"
+#include "minxopcf.h"
+#include "minxops.h"
+
+
+static CPU_EXECUTE( minx )
+{
+// UINT32 oldpc;
+ UINT8 op;
+ minx_state *minx = get_safe_token(device);
+
+ do
+ {
+ debugger_instruction_hook(device, GET_MINX_PC);
+// oldpc = GET_MINX_PC;
+
+ if ( minx->interrupt_pending )
+ {
+ minx->halted = 0;
+ if ( ! ( minx->F & 0xc0 ) && minx->U == minx->V )
+ {
+ //logerror("minx_execute(): taking IRQ\n");
+ PUSH8( minx, minx->V );
+ PUSH16( minx, minx->PC );
+ PUSH8( minx, minx->F );
+
+ /* Set Interrupt Branch flag */
+ minx->F |= 0x80;
+ minx->V = 0;
+ minx->PC = rd16( minx, minx->irq_callback( minx->device, 0 ) << 1 );
+ minx->icount -= 28; /* This cycle count is a guess */
+ }
+ }
+
+ if ( minx->halted )
+ {
+ minx->icount -= insnminx_cycles_CE[0xAE];
+ }
+ else
+ {
+ op = rdop(minx);
+ insnminx[op](minx);
+ minx->icount -= insnminx_cycles[op];
+ }
+ } while ( minx->icount > 0 );
+}
+
+
+static CPU_BURN( minx )
+{
+ minx_state *minx = get_safe_token(device);
+ minx->icount = 0;
+}
+
+
+static unsigned minx_get_reg( minx_state *minx, int regnum )
+{
+ switch( regnum )
+ {
+ case STATE_GENPC: return GET_MINX_PC;
+ case MINX_PC: return minx->PC;
+ case STATE_GENSP:
+ case MINX_SP: return minx->SP;
+ case MINX_BA: return minx->BA;
+ case MINX_HL: return minx->HL;
+ case MINX_X: return minx->X;
+ case MINX_Y: return minx->Y;
+ case MINX_U: return minx->U;
+ case MINX_V: return minx->V;
+ case MINX_F: return minx->F;
+ case MINX_E: return minx->E;
+ case MINX_N: return minx->N;
+ case MINX_I: return minx->I;
+ case MINX_XI: return minx->XI;
+ case MINX_YI: return minx->YI;
+ }
+ return 0;
+}
+
+
+static void minx_set_reg( minx_state *minx, int regnum, unsigned val )
+{
+ switch( regnum )
+ {
+ case STATE_GENPC: break;
+ case MINX_PC: minx->PC = val; break;
+ case STATE_GENSP:
+ case MINX_SP: minx->SP = val; break;
+ case MINX_BA: minx->BA = val; break;
+ case MINX_HL: minx->HL = val; break;
+ case MINX_X: minx->X = val; break;
+ case MINX_Y: minx->Y = val; break;
+ case MINX_U: minx->U = val; break;
+ case MINX_V: minx->V = val; break;
+ case MINX_F: minx->F = val; break;
+ case MINX_E: minx->E = val; break;
+ case MINX_N: minx->N = val; break;
+ case MINX_I: minx->I = val; break;
+ case MINX_XI: minx->XI = val; break;
+ case MINX_YI: minx->YI = val; break;
+ }
+}
+
+
+static void minx_set_irq_line( minx_state *minx, int irqline, int state )
+{
+ if ( state == ASSERT_LINE )
+ {
+ minx->interrupt_pending = 1;
+ }
+ else
+ {
+ minx->interrupt_pending = 0;
+ }
+}
+
+
+static CPU_SET_INFO( minx )
+{
+ minx_state *minx = get_safe_token(device);
+ switch( state )
+ {
+ case CPUINFO_INT_INPUT_STATE + 0:
+ minx_set_irq_line( minx, state - CPUINFO_INT_INPUT_STATE, info->i ); break;
+
+ case CPUINFO_INT_REGISTER + MINX_PC:
+ case CPUINFO_INT_REGISTER + MINX_SP:
+ case CPUINFO_INT_REGISTER + MINX_BA:
+ case CPUINFO_INT_REGISTER + MINX_HL:
+ case CPUINFO_INT_REGISTER + MINX_X:
+ case CPUINFO_INT_REGISTER + MINX_Y:
+ case CPUINFO_INT_REGISTER + MINX_U:
+ case CPUINFO_INT_REGISTER + MINX_V:
+ case CPUINFO_INT_REGISTER + MINX_F:
+ case CPUINFO_INT_REGISTER + MINX_E:
+ case CPUINFO_INT_REGISTER + MINX_N:
+ case CPUINFO_INT_REGISTER + MINX_I:
+ case CPUINFO_INT_REGISTER + MINX_XI:
+ case CPUINFO_INT_REGISTER + MINX_YI:
+ minx_set_reg( minx, state - CPUINFO_INT_REGISTER, info->i ); break;
+ }
+}
+
+
+CPU_GET_INFO( minx )
+{
+ minx_state *minx = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+ switch( state )
+ {
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(minx_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 1; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0x00; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 5; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 4; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 24; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+ case CPUINFO_INT_INPUT_STATE + 0: info->i = 0; break;
+ case CPUINFO_INT_REGISTER + STATE_GENPC: info->i = GET_MINX_PC; break;
+ case CPUINFO_INT_REGISTER + STATE_GENSP:
+ case CPUINFO_INT_REGISTER + MINX_PC:
+ case CPUINFO_INT_REGISTER + MINX_SP:
+ case CPUINFO_INT_REGISTER + MINX_BA:
+ case CPUINFO_INT_REGISTER + MINX_HL:
+ case CPUINFO_INT_REGISTER + MINX_X:
+ case CPUINFO_INT_REGISTER + MINX_Y:
+ case CPUINFO_INT_REGISTER + MINX_U:
+ case CPUINFO_INT_REGISTER + MINX_V:
+ case CPUINFO_INT_REGISTER + MINX_F:
+ case CPUINFO_INT_REGISTER + MINX_E:
+ case CPUINFO_INT_REGISTER + MINX_N:
+ case CPUINFO_INT_REGISTER + MINX_I:
+ case CPUINFO_INT_REGISTER + MINX_XI:
+ case CPUINFO_INT_REGISTER + MINX_YI: info->i = minx_get_reg( minx, state - CPUINFO_INT_REGISTER ); break;
+ case CPUINFO_INT_PREVIOUSPC: info->i = 0x0000; break;
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(minx); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(minx); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(minx); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(minx); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(minx); break;
+ case CPUINFO_FCT_BURN: info->burn = CPU_BURN_NAME(minx); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(minx); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &minx->icount; break;
+ case DEVINFO_STR_NAME: strcpy( info->s, "Minx" ); break;
+ case DEVINFO_STR_FAMILY: strcpy( info->s, "Nintendo Minx" ); break;
+ case DEVINFO_STR_VERSION: strcpy( info->s, "0.1" ); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy( info->s, __FILE__ ); break;
+ case DEVINFO_STR_CREDITS: strcpy( info->s, "Copyright The MESS Team." ); break;
+ case CPUINFO_STR_FLAGS:
+ sprintf( info->s, "%c%c%c%c%c%c%c%c-%c%c%c%c%c",
+ minx->F & FLAG_I ? 'I' : '.',
+ minx->F & FLAG_D ? 'D' : '.',
+ minx->F & FLAG_L ? 'L' : '.',
+ minx->F & FLAG_B ? 'B' : '.',
+ minx->F & FLAG_S ? 'S' : '.',
+ minx->F & FLAG_O ? 'O' : '.',
+ minx->F & FLAG_C ? 'C' : '.',
+ minx->F & FLAG_Z ? 'Z' : '.',
+ minx->E & EXEC_X0 ? '0' : '.',
+ minx->E & EXEC_X1 ? '1' : '.',
+ minx->E & EXEC_X2 ? '2' : '.',
+ minx->E & EXEC_DZ ? 'z' : '.',
+ minx->E & EXEC_EN ? 'E' : '.' );
+ break;
+ case CPUINFO_STR_REGISTER + MINX_PC: sprintf( info->s, "PC:%04X", minx->PC ); break;
+ case CPUINFO_STR_REGISTER + MINX_SP: sprintf( info->s, "SP:%04X", minx->SP ); break;
+ case CPUINFO_STR_REGISTER + MINX_BA: sprintf( info->s, "BA:%04X", minx->BA ); break;
+ case CPUINFO_STR_REGISTER + MINX_HL: sprintf( info->s, "HL:%04X", minx->HL ); break;
+ case CPUINFO_STR_REGISTER + MINX_X: sprintf( info->s, "X:%04X", minx->X ); break;
+ case CPUINFO_STR_REGISTER + MINX_Y: sprintf( info->s, "Y:%04X", minx->Y ); break;
+ case CPUINFO_STR_REGISTER + MINX_U: sprintf( info->s, "U:%02X", minx->U ); break;
+ case CPUINFO_STR_REGISTER + MINX_V: sprintf( info->s, "V:%02X", minx->V ); break;
+ case CPUINFO_STR_REGISTER + MINX_F: sprintf( info->s, "F:%02X", minx->F ); break;
+ case CPUINFO_STR_REGISTER + MINX_E: sprintf( info->s, "E:%02X", minx->E ); break;
+ case CPUINFO_STR_REGISTER + MINX_N: sprintf( info->s, "N:%02X", minx->N ); break;
+ case CPUINFO_STR_REGISTER + MINX_I: sprintf( info->s, "I:%02X", minx->I ); break;
+ case CPUINFO_STR_REGISTER + MINX_XI: sprintf( info->s, "XI:%02X", minx->XI ); break;
+ case CPUINFO_STR_REGISTER + MINX_YI: sprintf( info->s, "YI:%02X", minx->YI ); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(MINX, minx);
diff --git a/trunk/src/emu/cpu/minx/minx.h b/trunk/src/emu/cpu/minx/minx.h
new file mode 100644
index 00000000000..5604c8cb055
--- /dev/null
+++ b/trunk/src/emu/cpu/minx/minx.h
@@ -0,0 +1,18 @@
+#pragma once
+
+#ifndef __MINX_H__
+#define __MINX_H__
+
+
+enum
+{
+ MINX_PC=1, MINX_SP, MINX_BA, MINX_HL, MINX_X, MINX_Y,
+ MINX_U, MINX_V, MINX_F, MINX_E, MINX_N, MINX_I,
+ MINX_XI, MINX_YI,
+};
+
+DECLARE_LEGACY_CPU_DEVICE(MINX, minx);
+
+extern CPU_DISASSEMBLE( minx );
+
+#endif /* __MINX_H__ */
diff --git a/trunk/src/emu/cpu/minx/minxd.c b/trunk/src/emu/cpu/minx/minxd.c
new file mode 100644
index 00000000000..c51f0f833d0
--- /dev/null
+++ b/trunk/src/emu/cpu/minx/minxd.c
@@ -0,0 +1,467 @@
+/************************************************************
+
+ Nintendo Minx CPU disassembly
+
+
+************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "minx.h"
+
+enum e_mnemonic {
+ zADD=0, zADDC, zAND, zBCDD, zBCDE, zBCDX, zCALL, zCALLC, zCALLG, zCALLGE, zCALLL,
+ zCALLLE, zCALLN, zCALLNC, zCALLNO, zCALLNZ, zCALLO, zCALLP, zCALLNX0,
+ zCALLNX1, zCALLNX2, zCALLNX3, zCALLX0, zCALLX1, zCALLX2, zCALLX3, zCALLZ,
+ zCMP, zCMPN, zDEC, zDIV, zEXT, zHALT, zINC, zINT,
+ zJC, zJDBNZ, zJG, zJGE, zJINT, zJL, zJLE, zJMP,
+ zJN, zJNX0, zJNX1, zJNX2, zJNX3, zJNC, zJNO, zJNZ,
+ zJO, zJP, zJX0, zJX1, zJX2, zJX3, zJZ, zMOV,
+ zMUL, zNEG, zNOP, zNOT, zOR, zPOP, zPOPA, zPOPAX,
+ zPOPX, zPUSH, zPUSHA, zPUSHAX, zPUSHX, zRET, zRETI, zRETSKIP,
+ zROL, zROLC, zROR, zRORC, zSAL, zSAR, zSHL, zSHR, zSUB,
+ zSUBC, zTEST, zXCHG, zXOR, zDB
+};
+
+enum e_operand {
+ R_A=1, /* A */
+ R_B, /* B */
+ R_L, /* L */
+ R_H, /* H */
+ R_N, /* N */
+ R_F, /* F */
+ R_SP, /* SP */
+ R_BA, /* BA */
+ R_HL, /* HL */
+ R_X, /* X */
+ R_Y, /* Y */
+ R_U, /* U */
+ R_V, /* V */
+ R_I, /* I */
+ R_XI, /* XI */
+ R_YI, /* YI */
+ R_PC, /* PC */
+ I_8, /* 8 bit immediate */
+ I_16, /* 16 bit immediate */
+ D_8, /* PC + 8 bit displacement (signed) */
+ D_16, /* PC + 16 bit displacement */
+ S_8, /* SP + 8 bit displacement (signed) */
+ M_IHL, /* [I+HL] */
+ M_N8, /* [I+N+ofs8] */
+ M_I16, /* [I+ofs16] */
+ M_X, /* [X] */
+ M_Y, /* [Y] */
+ M_X8, /* [X + 8 bit displacement (signed)] */
+ M_Y8, /* [Y + 8 bit displacement (signed)] */
+ M_XL, /* [X + L (signed)] */
+ M_YL, /* [Y + L (signed)] */
+ M_16, /* [16bit] */
+ M_HL, /* [HL] */
+ OP, OP1
+};
+
+static const char *const s_mnemonic[] = {
+ "add", "addc", "and", "bcdd", "bcde", "bcdx", "call", "callc", "callg", "callge", "calll",
+ "callle", "calln", "callnc", "callno", "callnz", "callo", "callp", "callnx0",
+ "callnx1", "callnx2", "callnx3", "callx0", "callx1", "callx2", "callx3", "callz",
+ "cmp", "cmpn", "dec", "div", "ext", "halt", "inc", "int",
+ "jc", "jdbnz", "jg", "jge", "jint", "jl", "jle", "jmp",
+ "jn", "jnx0", "jnx1", "jnx2", "jnx3", "jnc", "jno", "jnz",
+ "jo", "jp", "jx0", "jx1", "jx2", "jx3", "jz", "mov",
+ "mul", "neg", "nop", "not", "or", "pop", "popa", "popax",
+ "popx", "push", "pusha", "pushax", "pushx", "ret", "reti", "retskip",
+ "rol", "rolc", "ror", "rorc", "sal", "sar", "shl", "shr", "sub",
+ "subc", "test", "xchg", "xor", "db"
+};
+
+#define _OVER DASMFLAG_STEP_OVER
+#define _OUT DASMFLAG_STEP_OUT
+
+static const UINT32 s_flags[] = {
+ 0, 0, 0, 0, 0, 0, _OVER, _OVER, _OVER, _OVER, _OVER,
+ _OVER, _OVER, _OVER, _OVER, _OVER, _OVER, _OVER, _OVER,
+ _OVER, _OVER, _OVER, _OVER, _OVER, _OVER, _OVER, _OVER,
+ 0, 0, 0, 0, 0, _OVER, 0, _OVER,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, _OUT, _OUT, _OUT,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+};
+
+typedef struct {
+ UINT8 mnemonic;
+ UINT8 argument1;
+ UINT8 argument2;
+} minxdasm;
+
+static const minxdasm mnemonic[256] = {
+ /* 00 - 0F */
+ {zADD,R_A,R_A}, {zADD,R_A,R_B}, {zADD,R_A,I_8}, {zADD,R_A,M_IHL},
+ {zADD,R_A,M_N8}, {zADD,R_A,M_I16}, {zADD,R_A,M_X}, {zADD,R_A,M_Y},
+ {zADDC,R_A,R_A}, {zADDC,R_A,R_B}, {zADDC,R_A,I_8}, {zADDC,R_A,M_IHL},
+ {zADDC,R_A,M_N8}, {zADDC,R_A,M_I16}, {zADDC,R_A,M_X}, {zADDC,R_A,M_Y},
+ /* 10 - 1F */
+ {zSUB,R_A,R_A}, {zSUB,R_A,R_B}, {zSUB,R_A,I_8}, {zSUB,R_A,M_IHL},
+ {zSUB,R_A,M_N8}, {zSUB,R_A,M_I16}, {zSUB,R_A,M_X}, {zSUB,R_A,M_Y},
+ {zSUBC,R_A,R_A}, {zSUBC,R_A,R_B}, {zSUBC,R_A,I_8}, {zSUBC,R_A,M_IHL},
+ {zSUBC,R_A,M_N8}, {zSUBC,R_A,M_I16}, {zSUBC,R_A,M_X}, {zSUBC,R_A,M_Y},
+ /* 20 - 2F */
+ {zAND,R_A,R_A}, {zAND,R_A,R_B}, {zAND,R_A,I_8}, {zAND,R_A,M_IHL},
+ {zAND,R_A,M_N8}, {zAND,R_A,M_I16}, {zAND,R_A,M_X}, {zAND,R_A,M_Y},
+ {zOR,R_A,R_A}, {zOR,R_A,R_B}, {zOR,R_A,I_8}, {zOR,R_A,M_IHL},
+ {zOR,R_A,M_N8}, {zOR,R_A,M_I16}, {zOR,R_A,M_X}, {zOR,R_A,M_Y},
+ /* 30 - 3F */
+ {zCMP,R_A,R_A}, {zCMP,R_A,R_B}, {zCMP,R_A,I_8}, {zCMP,R_A,M_IHL},
+ {zCMP,R_A,M_N8}, {zCMP,R_A,M_I16}, {zCMP,R_A,M_X}, {zCMP,R_A,M_Y},
+ {zXOR,R_A,R_A}, {zXOR,R_A,R_B}, {zXOR,R_A,I_8}, {zXOR,R_A,M_IHL},
+ {zXOR,R_A,M_N8}, {zXOR,R_A,M_I16}, {zXOR,R_A,M_X}, {zXOR,R_A,M_Y},
+ /* 40 - 4F */
+ {zMOV,R_A,R_A}, {zMOV,R_A,R_B}, {zMOV,R_A,R_L}, {zMOV,R_A,R_H},
+ {zMOV,R_A,M_N8}, {zMOV,R_A,M_IHL}, {zMOV,R_A,M_X}, {zMOV,R_A,M_Y},
+ {zMOV,R_B,R_A}, {zMOV,R_B,R_B}, {zMOV,R_B,R_L}, {zMOV,R_B,R_H},
+ {zMOV,R_B,M_N8}, {zMOV,R_B,M_IHL}, {zMOV,R_B,M_X}, {zMOV,R_B,M_Y},
+ /* 50 - 5F */
+ {zMOV,R_L,R_A}, {zMOV,R_L,R_B}, {zMOV,R_L,R_L}, {zMOV,R_L,R_H},
+ {zMOV,R_L,M_N8}, {zMOV,R_L,M_IHL}, {zMOV,R_L,M_X}, {zMOV,R_L,M_Y},
+ {zMOV,R_H,R_A}, {zMOV,R_H,R_B}, {zMOV,R_H,R_L}, {zMOV,R_H,R_H},
+ {zMOV,R_H,M_N8}, {zMOV,R_H,M_IHL}, {zMOV,R_H,M_X}, {zMOV,R_H,M_Y},
+ /* 60 - 6F */
+ {zMOV,M_X,R_A}, {zMOV,M_X,R_B}, {zMOV,M_X,R_L}, {zMOV,M_X,R_H},
+ {zMOV,M_X,M_N8}, {zMOV,M_X,M_IHL}, {zMOV,M_X,M_X}, {zMOV,M_X,M_Y},
+ {zMOV,M_IHL,R_A}, {zMOV,M_IHL,R_B}, {zMOV,M_IHL,R_L}, {zMOV,M_IHL,R_H},
+ {zMOV,M_IHL,M_N8}, {zMOV,M_IHL,M_IHL}, {zMOV,M_IHL,M_X}, {zMOV,M_IHL,M_Y},
+ /* 70 - 7F */
+ {zMOV,M_Y,R_A}, {zMOV,M_Y,R_B}, {zMOV,M_Y,R_L}, {zMOV,M_Y,R_H},
+ {zMOV,M_Y,M_N8}, {zMOV,M_Y,M_IHL}, {zMOV,M_Y,M_X}, {zMOV,M_Y,M_Y},
+ {zMOV,M_N8,R_A}, {zMOV,M_N8,R_B}, {zMOV,M_N8,R_L}, {zMOV,M_N8,R_H},
+ {zDB,OP,0}, {zMOV,M_N8,M_IHL}, {zMOV,M_N8,M_X}, {zMOV,M_N8,M_Y},
+ /* 80 - 8F */
+ {zINC,R_A,0}, {zINC,R_B,0}, {zINC,R_L,0}, {zINC,R_H,0},
+ {zINC,R_N,0}, {zINC,M_N8,0}, {zINC,M_IHL,0}, {zINC,R_SP,0},
+ {zDEC,R_A,0}, {zDEC,R_B,0}, {zDEC,R_L,0}, {zDEC,R_H,0},
+ {zDEC,R_N,0}, {zDEC,M_N8,0}, {zDEC,M_IHL,0}, {zDEC,R_SP,0},
+ /* 90 - 9F */
+ {zINC,R_BA,0}, {zINC,R_HL,0}, {zINC,R_X,0}, {zINC,R_Y,0},
+ {zTEST,R_A,R_B}, {zTEST,M_IHL,I_8}, {zTEST,R_A,I_8}, {zTEST,R_B,I_8},
+ {zDEC,R_BA,0}, {zDEC,R_HL,0}, {zDEC,R_X,0}, {zDEC,R_Y,0},
+ {zAND,R_F,I_8}, {zOR,R_F,I_8}, {zXOR,R_F,I_8}, {zMOV,R_F,I_8},
+ /* A0 - AF */
+ {zPUSH,R_BA,0}, {zPUSH,R_HL,0}, {zPUSH,R_X,0}, {zPUSH,R_Y,0},
+ {zPUSH,R_N,0}, {zPUSH,R_I,0}, {zPUSHX,0,0}, {zPUSH,R_F,0},
+ {zPOP,R_BA,0}, {zPOP,R_HL,0}, {zPOP,R_X,0}, {zPOP,R_Y,0},
+ {zPOP,R_N,0}, {zPOP,R_I,0}, {zPOP,0,0}, {zPOP,R_F,0},
+ /* B0 - BF */
+ {zMOV,R_A,I_8}, {zMOV,R_B,I_8}, {zMOV,R_L,I_8}, {zMOV,R_H,I_8},
+ {zMOV,R_N,I_8}, {zMOV,M_IHL,I_8}, {zMOV,M_X,I_8}, {zMOV,M_Y,I_8},
+ {zMOV,R_BA,M_I16}, {zMOV,R_HL,M_I16}, {zMOV,R_X,M_I16}, {zMOV,R_Y,M_I16},
+ {zMOV,M_I16,R_BA}, {zMOV,M_I16,R_HL}, {zMOV,M_I16,R_X}, {zMOV,M_I16,R_Y},
+ /* C0 - CF */
+ {zADD,R_BA,I_16}, {zADD,R_HL,I_16}, {zADD,R_X,I_16}, {zADD,R_Y,I_16},
+ {zMOV,R_BA,I_16}, {zMOV,R_HL,I_16}, {zMOV,R_X,I_16}, {zMOV,R_Y,I_16},
+ {zXCHG,R_BA,R_HL}, {zXCHG,R_BA,R_X}, {zXCHG,R_BA,R_Y}, {zXCHG,R_BA,R_SP},
+ {zXCHG,R_A,R_B}, {zXCHG,R_A,M_IHL}, {zDB,0,0}, {zDB,0,0},
+ /* D0 - DF */
+ {zSUB,R_BA,I_16}, {zSUB,R_HL,I_16}, {zSUB,R_X,I_16}, {zSUB,R_Y,I_16},
+ {zCMP,R_BA,I_16}, {zCMP,R_HL,I_16}, {zCMP,R_X,I_16}, {zCMP,R_Y,I_16},
+ {zAND,M_N8,I_8}, {zOR,M_N8,I_8}, {zXOR,M_N8,I_8}, {zCMP,M_N8,I_8},
+ {zTEST,M_N8,I_8}, {zMOV,M_N8,I_8}, {zBCDE,0,0}, {zBCDD,0,0},
+ /* E0 - EF */
+ {zCALLC,D_8,0}, {zCALLNC,D_8,0}, {zCALLZ,D_8,0}, {zCALLNZ,D_8,0},
+ {zJC,D_8,0}, {zJNC,D_8,0}, {zJZ,D_8,0}, {zJNZ,D_8,0},
+ {zCALLC,D_16,0}, {zCALLNC,D_16,0}, {zCALLZ,D_16,0}, {zCALLNZ,D_16,0},
+ {zJC,D_16,0}, {zJNC,D_16,0}, {zJZ,D_16,0}, {zJNZ,D_16,0},
+ /* F0 - FF */
+ {zCALL,D_8,0}, {zJMP,D_8,0}, {zCALL,D_16}, {zJMP,D_16},
+ {zJMP,R_HL,0}, {zJDBNZ,D_8,0}, {zBCDX,R_A,0}, {zBCDX,M_IHL,0},
+ {zRET,0,0}, {zRETI,0,0}, {zRETSKIP,0,0}, {zCALL,M_I16},
+ {zINT,I_8,0}, {zJINT,I_8,0}, {zDB,OP,0}, {zNOP,0,0}
+};
+
+static const minxdasm mnemonic_ce[256] = {
+ /* 00 - 0F */
+ {zADD,R_A,M_X8}, {zADD,R_A,M_Y8}, {zADD,R_A,M_XL}, {zADD,R_A,M_YL},
+ {zADD,M_IHL,R_A}, {zADD,M_IHL,I_8}, {zADD,M_IHL,M_X}, {zADD,M_IHL,M_Y},
+ {zADDC,R_A,M_X8}, {zADDC,R_A,M_Y8}, {zADDC,R_A,M_XL}, {zADDC,R_A,M_YL},
+ {zADDC,M_IHL,R_A}, {zADDC,M_IHL,I_8}, {zADDC,M_IHL,M_X}, {zADDC,M_IHL,M_Y},
+ /* 10 - 1F */
+ {zSUB,R_A,M_X8}, {zSUB,R_A,M_Y8}, {zSUB,R_A,M_XL}, {zSUB,R_A,M_YL},
+ {zSUB,M_IHL,R_A}, {zSUB,M_IHL,I_8}, {zSUB,M_IHL,M_X}, {zSUB,M_IHL,M_Y},
+ {zSUBC,R_A,M_X8}, {zSUBC,R_A,M_Y8}, {zSUBC,R_A,M_XL}, {zSUBC,R_A,M_YL},
+ {zSUBC,M_IHL,R_A}, {zSUBC,M_IHL,I_8}, {zSUBC,M_IHL,M_X}, {zSUBC,M_IHL,M_Y},
+ /* 20 - 2F */
+ {zAND,R_A,M_X8}, {zAND,R_A,M_Y8}, {zAND,R_A,M_XL}, {zAND,R_A,M_YL},
+ {zAND,M_IHL,R_A}, {zAND,M_IHL,I_8}, {zAND,M_IHL,M_X}, {zAND,M_IHL,M_Y},
+ {zOR,R_A,M_X8}, {zOR,R_A,M_Y8}, {zOR,R_A,M_XL}, {zOR,R_A,M_YL},
+ {zOR,M_IHL,R_A}, {zOR,M_IHL,I_8}, {zOR,M_IHL,M_X}, {zOR,M_IHL,M_Y},
+ /* 30 - 3F */
+ {zCMP,R_A,M_X8}, {zCMP,R_A,M_Y8}, {zCMP,R_A,M_XL}, {zCMP,R_A,M_YL},
+ {zCMP,M_IHL,R_A}, {zCMP,M_IHL,I_8}, {zCMP,M_IHL,M_X}, {zCMP,M_IHL,M_Y},
+ {zXOR,R_A,M_X8}, {zXOR,R_A,M_Y8}, {zXOR,R_A,M_XL}, {zXOR,R_A,M_YL},
+ {zXOR,M_IHL,R_A}, {zXOR,M_IHL,I_8}, {zXOR,M_IHL,M_X}, {zXOR,M_IHL,M_Y},
+ /* 40 - 4F */
+ {zMOV,R_A,M_X8}, {zMOV,R_A,M_Y8}, {zMOV,R_A,M_XL}, {zMOV,R_A,M_YL},
+ {zMOV,M_X8,R_A}, {zMOV,M_Y8,R_A}, {zMOV,M_X,R_A}, {zMOV,M_Y,R_A},
+ {zMOV,R_B,M_X8}, {zMOV,R_B,M_Y8}, {zMOV,R_B,M_XL}, {zMOV,R_B,M_YL},
+ {zMOV,M_X8,R_B}, {zMOV,M_Y8,R_B}, {zMOV,M_X,R_B}, {zMOV,M_Y,R_B},
+ /* 50 - 5F */
+ {zMOV,R_L,M_X8}, {zMOV,R_L,M_Y8}, {zMOV,R_L,M_XL}, {zMOV,R_L,M_YL},
+ {zMOV,M_X8,R_L}, {zMOV,M_Y8,R_L}, {zMOV,M_X,R_L}, {zMOV,M_Y,R_L},
+ {zMOV,R_H,M_X8}, {zMOV,R_H,M_Y8}, {zMOV,R_H,M_XL}, {zMOV,R_H,M_YL},
+ {zMOV,M_X8,R_H}, {zMOV,M_Y8,R_H}, {zMOV,M_X,R_H}, {zMOV,M_Y,R_H},
+ /* 60 - 6F */
+ {zMOV,M_IHL,M_X8}, {zMOV,M_IHL,M_Y8}, {zMOV,M_IHL,M_XL}, {zMOV,M_IHL,M_YL},
+ {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP},
+ {zMOV,M_X,M_X8}, {zMOV,M_X,M_Y8}, {zMOV,M_X,M_XL}, {zMOV,M_X,M_YL},
+ {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP},
+ /* 70 - 7F */
+ {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP},
+ {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP},
+ {zMOV,M_Y,M_X8}, {zMOV,M_Y,M_Y8}, {zMOV,M_Y,M_XL}, {zMOV,M_Y,M_YL},
+ {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP},
+ /* 80 - 8F */
+ {zSAL,R_A,0}, {zSAL,R_B,0}, {zSAL,M_N8,0}, {zSAL,M_IHL,0},
+ {zSHL,R_A,0}, {zSHL,R_B,0}, {zSHL,M_N8,0}, {zSHL,M_IHL,0},
+ {zSAR,R_A,0}, {zSAR,R_B,0}, {zSAR,M_N8,0}, {zSAR,M_IHL,0},
+ {zSHR,R_A,0}, {zSHR,R_B,0}, {zSHR,M_N8,0}, {zSHR,M_IHL,0},
+ /* 90 - 9F */
+ {zROLC,R_A,0}, {zROLC,R_B,0}, {zROLC,M_N8,0}, {zROLC,M_IHL,0},
+ {zROL,R_A,0}, {zROL,R_B,0}, {zROL,M_N8,0}, {zROL,M_IHL,0},
+ {zRORC,R_A,0}, {zRORC,R_B,0}, {zRORC,M_N8,0}, {zRORC,M_IHL,0},
+ {zROR,R_A,0}, {zROR,R_B,0}, {zROR,M_N8,0}, {zROR,M_IHL,0},
+ /* A0 - AF */
+ {zNOT,R_A,0}, {zNOT,R_B,0}, {zNOT,M_N8,0}, {zNOT,M_IHL,0},
+ {zNEG,R_A,0}, {zNEG,R_B,0}, {zNEG,M_N8,0}, {zNEG,M_IHL,0},
+ {zEXT,R_BA,R_A}, {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP},
+ {zDB,OP1,OP}, {zDB,OP1,OP}, {zHALT,0,0}, {zNOP,0,0},
+ /* B0 - BF */
+ {zAND,R_B,I_8}, {zAND,R_L,I_8}, {zAND,R_H,I_8}, {zDB,OP1,OP},
+ {zOR,R_B,I_8}, {zOR,R_L,I_8}, {zOR,R_H,I_8}, {zDB,OP1,OP},
+ {zXOR,R_B,I_8}, {zXOR,R_L,I_8}, {zXOR,R_H,I_8}, {zDB,OP1,OP},
+ {zCMP,R_B,I_8}, {zCMP,R_L,I_8}, {zCMP,R_H,I_8}, {zCMP,R_N,I_8},
+ /* C0 - CF */
+ {zMOV,R_A,R_N}, {zMOV,R_A,R_F}, {zMOV,R_N,R_A}, {zMOV,R_F,R_A},
+ {zMOV,R_U,I_8}, {zMOV,R_I,I_8}, {zMOV,R_XI,I_8}, {zMOV,R_YI,I_8},
+ {zMOV,R_A,R_V}, {zMOV,R_A,R_I}, {zMOV,R_A,R_XI}, {zMOV,R_A,R_YI},
+ {zMOV,R_U,R_A}, {zMOV,R_I,R_A}, {zMOV,R_XI,R_A}, {zMOV,R_YI,R_A},
+ /* D0 - DF */
+ {zMOV,R_A,M_16}, {zMOV,R_B,M_16}, {zMOV,R_H,M_16}, {zMOV,R_L,M_16},
+ {zMOV,M_16,R_A}, {zMOV,M_16,R_B}, {zMOV,M_16,R_H}, {zMOV,M_16,R_L},
+ {zMUL,R_HL,R_A}, {zDIV,R_HL,R_A}, {zDB,OP1,OP}, {zDB,OP1,OP},
+ {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP},
+ /* E0 - EF */
+ {zJL,D_8,0}, {zJLE,D_8,0}, {zJG,D_8,0}, {zJGE,D_8,0},
+ {zJO,D_8,0}, {zJNO,D_8,0}, {zJP,D_8,0}, {zJN,D_8,0},
+ {zJNX0,D_8,0}, {zJNX1,D_8,0}, {zJNX2,D_8,0}, {zJNX3,D_8,0},
+ {zJX0,D_8,0}, {zJX1,D_8,0}, {zJX2,D_8,0}, {zJX3,D_8,0},
+ /* F0 - FF */
+ {zCALLL,D_8,0}, {zCALLLE,D_8,0}, {zCALLG,D_8,0}, {zCALLGE,D_8,0},
+ {zCALLO,D_8,0}, {zCALLNO,D_8,0}, {zCALLP,D_8,0}, {zCALLN,D_8,0},
+ {zCALLNX0,D_8,0}, {zCALLNX1,D_8,0}, {zCALLNX2,D_8,0}, {zCALLNX3,D_8,0},
+ {zCALLX0,D_8,0}, {zCALLX1,D_8,0}, {zCALLX2,D_8,0}, {zCALLX3,D_8,0}
+};
+
+static const minxdasm mnemonic_cf[256] = {
+ /* 00 - 0F */
+ {zADD,R_BA,R_BA}, {zADD,R_BA,R_HL}, {zADD,R_BA,R_X}, {zADD,R_BA,R_Y},
+ {zADDC,R_BA,R_BA}, {zADDC,R_BA,R_HL}, {zADDC,R_BA,R_X}, {zADDC,R_BA,R_Y},
+ {zSUB,R_BA,R_BA}, {zSUB,R_BA,R_HL}, {zSUB,R_BA,R_X}, {zSUB,R_BA,R_Y},
+ {zSUBC,R_BA,R_BA}, {zSUBC,R_BA,R_HL}, {zSUBC,R_BA,R_X}, {zSUBC,R_BA,R_Y},
+ /* 10 - 1F */
+ {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP},
+ {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP},
+ {zCMP,R_BA,R_BA}, {zCMP,R_BA,R_HL}, {zCMP,R_BA,R_X}, {zCMP,R_BA,R_Y},
+ {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP},
+ /* 20 - 2F */
+ {zADD,R_HL,R_BA}, {zADD,R_HL,R_HL}, {zADD,R_HL,R_X}, {zADD,R_HL,R_Y},
+ {zADDC,R_HL,R_BA}, {zADDC,R_HL,R_HL}, {zADDC,R_HL,R_X}, {zADDC,R_HL,R_Y},
+ {zSUB,R_HL,R_BA}, {zSUB,R_HL,R_HL}, {zSUB,R_HL,R_X}, {zSUB,R_HL,R_Y},
+ {zSUBC,R_HL,R_BA}, {zSUBC,R_HL,R_HL}, {zSUBC,R_HL,R_X}, {zSUBC,R_HL,R_Y},
+ /* 30 - 3F */
+ {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP},
+ {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP},
+ {zCMP,R_HL,R_BA}, {zCMP,R_HL,R_HL}, {zCMP,R_HL,R_X}, {zCMP,R_HL,R_Y},
+ {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP},
+ /* 40 - 4F */
+ {zADD,R_X,R_BA}, {zADD,R_X,R_HL}, {zADD,R_Y,R_BA}, {zADD,R_Y,R_HL},
+ {zADD,R_SP,R_BA}, {zADD,R_SP,R_HL}, {zDB,OP1,}, {zDB,OP1,OP},
+ {zSUB,R_X,R_BA}, {zSUB,R_X,R_HL}, {zSUB,R_Y,R_BA}, {zSUB,R_Y,R_HL},
+ {zSUB,R_SP,R_BA}, {zSUB,R_SP,R_HL}, {zDB,OP1,OP}, {zDB,OP1,OP},
+ /* 50 - 5F */
+ {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP},
+ {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP},
+ {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP},
+ {zCMP,R_SP,R_BA}, {zCMP,R_SP,R_HL}, {zDB,OP1,OP}, {zDB,OP1,OP},
+ /* 60 - 6F */
+ {zCMPN,R_BA,I_16}, {zCMPN,R_HL,I_16}, {zCMPN,R_X,I_16}, {zCMPN,R_Y,I_16},
+ {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP},
+ {zADD,R_SP,I_16}, {zDB,OP1,OP}, {zSUB,R_SP,I_16}, {zDB,OP1,OP},
+ {zCMP,R_SP,I_16}, {zDB,OP1,OP}, {zMOV,R_SP,I_16}, {zDB,OP1,OP},
+ /* 70 - 7F */
+ {zMOV,R_BA,S_8}, {zMOV,R_HL,S_8}, {zMOV,R_X,S_8}, {zMOV,R_Y,S_8},
+ {zMOV,S_8,R_BA}, {zMOV,S_8,R_HL}, {zMOV,S_8,R_X}, {zMOV,S_8,R_Y},
+ {zMOV,R_SP,M_I16}, {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP},
+ {zMOV,M_I16,R_SP}, {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP},
+ /* 80 - 8F */
+ {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP},
+ {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP},
+ {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP},
+ {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP},
+ /* 90 - 9F */
+ {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP},
+ {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP},
+ {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP},
+ {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP},
+ /* A0 - AF */
+ {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP},
+ {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP},
+ {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP},
+ {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP},
+ /* B0 - BF */
+ {zPUSH,R_A,0}, {zPUSH,R_B,0}, {zPUSH,R_L,0}, {zPUSH,R_H,0},
+ {zPOP,R_A,0}, {zPOP,R_B,0}, {zPOP,R_L,0}, {zPOP,R_H,0},
+ {zPUSHA,0,0}, {zPUSHAX,0,0}, {zDB,OP1,OP}, {zDB,OP1,OP},
+ {zPOPA,0,0}, {zPOPAX,0,0}, {zDB,OP1,OP}, {zDB,OP1,OP},
+ /* C0 - CF */
+ {zMOV,R_BA,M_HL}, {zMOV,R_HL,M_HL}, {zMOV,R_X,M_HL}, {zMOV,R_Y,M_HL},
+ {zMOV,M_HL,R_BA}, {zMOV,M_HL,R_HL}, {zMOV,M_HL,R_X}, {zMOV,M_HL,R_Y},
+ {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP},
+ {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP}, {zDB,OP1,OP},
+ /* D0 - DF */
+ {zMOV,R_BA,M_X}, {zMOV,R_HL,M_X}, {zMOV,R_X,M_X}, {zMOV,R_Y,M_X},
+ {zMOV,M_X,R_BA}, {zMOV,M_X,R_HL}, {zMOV,M_X,R_X}, {zMOV,M_X,R_Y},
+ {zMOV,R_BA,M_Y}, {zMOV,R_HL,M_Y}, {zMOV,R_X,M_Y}, {zMOV,R_Y,M_Y},
+ {zMOV,M_Y,R_BA}, {zMOV,M_Y,R_HL}, {zMOV,M_Y,R_X}, {zMOV,M_Y,R_Y},
+ /* E0 - EF */
+ {zMOV,R_BA,R_BA}, {zMOV,R_BA,R_HL}, {zMOV,R_BA,R_X}, {zMOV,R_BA,R_Y},
+ {zMOV,R_HL,R_BA}, {zMOV,R_HL,R_HL}, {zMOV,R_HL,R_X}, {zMOV,R_HL,R_Y},
+ {zMOV,R_X,R_BA}, {zMOV,R_X,R_HL}, {zMOV,R_X,R_X}, {zMOV,R_X,R_Y},
+ {zMOV,R_Y,R_BA}, {zMOV,R_Y,R_HL}, {zMOV,R_Y,R_X}, {zMOV,R_Y,R_Y},
+ /* F0 - FF */
+ {zMOV,R_SP,R_BA}, {zMOV,R_SP,R_HL}, {zMOV,R_SP,R_X}, {zMOV,R_SP,R_Y},
+ {zMOV,R_HL,R_SP}, {zMOV,R_HL,R_PC}, {zDB,OP1,OP}, {zDB,OP1,OP},
+ {zMOV,R_BA,R_SP}, {zMOV,R_BA,R_PC}, {zMOV,R_X,R_SP}, {zDB,OP1,OP},
+ {zDB,OP1,OP}, {zDB,OP1,OP}, {zMOV,R_Y,R_SP}, {zDB,OP1,OP}
+};
+
+#define HANDLE_ARGUMENT \
+case R_A: dst += sprintf( dst, "%cA", fill ); break; \
+case R_B: dst += sprintf( dst, "%cB", fill ); break; \
+case R_L: dst += sprintf( dst, "%cL", fill ); break; \
+case R_H: dst += sprintf( dst, "%cH", fill ); break; \
+case R_N: dst += sprintf( dst, "%cN", fill ); break; \
+case R_F: dst += sprintf( dst, "%cF", fill ); break; \
+case R_SP: dst += sprintf( dst, "%cSP", fill ); break; \
+case R_BA: dst += sprintf( dst, "%cBA", fill ); break; \
+case R_HL: dst += sprintf( dst, "%cHL", fill ); break; \
+case R_X: dst += sprintf( dst, "%cX", fill ); break; \
+case R_Y: dst += sprintf( dst, "%cY", fill ); break; \
+case R_U: dst += sprintf( dst, "%cU", fill ); break; \
+case R_V: dst += sprintf( dst, "%cV", fill ); break; \
+case R_I: dst += sprintf( dst, "%cI", fill ); break; \
+case R_XI: dst += sprintf( dst, "%cXI", fill ); break; \
+case R_YI: dst += sprintf( dst, "%cYI", fill ); break; \
+case R_PC: dst += sprintf( dst, "%cPC", fill ); break; \
+case I_8: /* 8 bit immediate */ \
+ ea = oprom[pos++]; \
+ dst += sprintf( dst, "%c$%02X", fill, ea ); \
+ break; \
+case I_16: /* 16 bit immediate */ \
+ ea = oprom[pos++]; \
+ ea += oprom[pos++] << 8; \
+ dst += sprintf( dst, "%c$%04X", fill, ea ); \
+ break; \
+case D_8: /* PC + 8 bit displacement (signed) */ \
+ ofs8 = oprom[pos++]; \
+ dst += sprintf( dst, "%c$%04X", fill, pc + pos - 1 + ofs8 ); \
+ break; \
+case D_16: /* PC + 16 bit displacement */ \
+ ea = oprom[pos++]; \
+ ea += oprom[pos++] << 8; \
+ ea = ea - 1; \
+ dst += sprintf( dst, "%c$%04X", fill, pc + pos + ea ); \
+ break; \
+case S_8: /* SP + 8 bit displacement (signed) */ \
+ ea = oprom[pos++]; \
+ dst += sprintf( dst, "%cSP+$%02X", fill, ea ); \
+ break; \
+case M_IHL: dst += sprintf( dst, "%c[I+HL]", fill ); break; \
+case M_N8: /* [I+N+ofs8] */ \
+ ea = oprom[pos++]; \
+ dst += sprintf( dst, "%c[I+N+$%02X]", fill, ea ); \
+ break; \
+case M_I16: /* [I+ofs16] */ \
+ ea = oprom[pos++]; \
+ ea += oprom[pos++] << 8; \
+ dst += sprintf( dst, "%c[I+$%04X]", fill, ea ); \
+ break; \
+case M_X: dst += sprintf( dst, "%c[X]", fill ); break; \
+case M_Y: dst += sprintf( dst, "%c[Y]", fill ); break; \
+case M_X8: /* [X + 8 bit displacement (signed)] */ \
+ ea = oprom[pos++]; \
+ dst += sprintf( dst, "%c[X+$%02X]", fill, ea ); \
+ break; \
+case M_Y8: /* [Y + 8 bit displacement (signed)] */ \
+ ea = oprom[pos++]; \
+ dst += sprintf( dst, "%c[Y+$%02X]", fill, ea ); \
+ break; \
+case M_XL: dst += sprintf( dst, "%c[X+L]", fill ); break; \
+case M_YL: dst += sprintf( dst, "%c[Y+L]", fill ); break; \
+case M_16: /* [16bit] */ \
+ ea = oprom[pos++]; \
+ ea += oprom[pos++] << 8; \
+ dst += sprintf( dst, "%c[$%04X]", fill, ea ); \
+ break; \
+case M_HL: dst += sprintf( dst, "%c[HL]", fill ); break; \
+case OP: dst += sprintf( dst, "%c$%02X", fill, op ); break; \
+case OP1: dst += sprintf( dst, "%c$%02X", fill, op1 ); break;
+
+CPU_DISASSEMBLE( minx )
+{
+ const minxdasm *instr;
+ UINT8 op, op1;
+ INT8 ofs8 = 0;
+ UINT16 ea = 0;
+ int pos = 0;
+ char *dst = buffer;
+
+ op1 = op = oprom[pos++];
+
+ switch (op) {
+ case 0xCE:
+ op = oprom[pos++];
+ instr = &mnemonic_ce[op];
+ break;
+ case 0xCF:
+ op = oprom[pos++];
+ instr = &mnemonic_cf[op];
+ break;
+ default:
+ instr = &mnemonic[op];
+ break;
+ }
+
+ dst += sprintf( dst, "%-6s", s_mnemonic[ instr->mnemonic ] );
+
+ if ( instr->argument1 ) {
+ char fill = ' ';
+ //int arg = 0;
+ switch( instr->argument1 ) {
+ HANDLE_ARGUMENT;
+ }
+ }
+ if ( instr->argument2 ) {
+ char fill = ',';
+ //int arg = 1;
+ switch( instr->argument2 ) {
+ HANDLE_ARGUMENT;
+ }
+ }
+ return pos | s_flags[instr->mnemonic] | DASMFLAG_SUPPORTED;
+}
+
+
+
+
diff --git a/trunk/src/emu/cpu/minx/minxfunc.h b/trunk/src/emu/cpu/minx/minxfunc.h
new file mode 100644
index 00000000000..1716418def1
--- /dev/null
+++ b/trunk/src/emu/cpu/minx/minxfunc.h
@@ -0,0 +1,362 @@
+INLINE UINT8 ADD8( minx_state *minx, UINT8 arg1, UINT8 arg2 )
+{
+ UINT32 res = arg1 + arg2;
+ minx->F = ( minx->F & ~ ( FLAG_S | FLAG_O | FLAG_C | FLAG_Z ) )
+ | ( ( res & 0x80 ) ? FLAG_S : 0 )
+ | ( ( ( arg2 ^ arg1 ^ 0x80 ) & ( arg2 ^ res ) & 0x80 ) ? FLAG_O : 0 )
+ | ( ( res & 0xFF00 ) ? FLAG_C : 0 )
+ | ( ( res ) ? 0 : FLAG_Z )
+ ;
+ return res & 0xFF;
+}
+
+
+INLINE UINT16 ADD16( minx_state *minx, UINT16 arg1, UINT16 arg2 )
+{
+ UINT32 res = arg1 + arg2;
+ minx->F = ( minx->F & ~ ( FLAG_S | FLAG_O | FLAG_C | FLAG_Z ) )
+ | ( ( res & 0x8000 ) ? FLAG_S : 0 )
+ | ( ( ( arg2 ^ arg1 ^ 0x8000 ) & ( arg2 ^ res ) & 0x8000 ) ? FLAG_O : 0 )
+ | ( ( res & 0xFF0000 ) ? FLAG_C : 0 )
+ | ( ( res ) ? 0 : FLAG_Z )
+ ;
+ return res & 0xFFFF;
+}
+
+
+INLINE UINT8 ADDC8( minx_state *minx, UINT8 arg1, UINT8 arg2 )
+{
+ UINT32 res = arg1 + arg2 + ( ( minx->F & FLAG_C ) ? 1 : 0 );
+ minx->F = ( minx->F & ~ ( FLAG_S | FLAG_O | FLAG_C | FLAG_Z ) )
+ | ( ( res & 0x80 ) ? FLAG_S : 0 )
+ | ( ( ( arg2 ^ arg1 ^ 0x80 ) & ( arg2 ^ res ) & 0x80 ) ? FLAG_O : 0 )
+ | ( ( res & 0xFF00 ) ? FLAG_C : 0 )
+ | ( ( res ) ? 0 : FLAG_Z )
+ ;
+ return res & 0xFF;
+}
+
+
+INLINE UINT16 ADDC16( minx_state *minx, UINT16 arg1, UINT16 arg2 )
+{
+ UINT32 res = arg1 + arg2 + ( ( minx->F & FLAG_C ) ? 1 : 0 );
+ minx->F = ( minx->F & ~ ( FLAG_S | FLAG_O | FLAG_C | FLAG_Z ) )
+ | ( ( res & 0x8000 ) ? FLAG_S : 0 )
+ | ( ( ( arg2 ^ arg1 ^ 0x8000 ) & ( arg2 ^ res ) & 0x8000 ) ? FLAG_O : 0 )
+ | ( ( res & 0xFF0000 ) ? FLAG_C : 0 )
+ | ( ( res ) ? 0 : FLAG_Z )
+ ;
+ return res & 0xFFFF;
+}
+
+
+INLINE UINT8 INC8( minx_state *minx, UINT8 arg )
+{
+ UINT8 old_F = minx->F;
+ UINT8 res = ADD8( minx, arg, 1 );
+ minx->F = ( old_F & ~ ( FLAG_Z ) )
+ | ( ( res ) ? 0 : FLAG_Z )
+ ;
+ return res;
+}
+
+
+INLINE UINT16 INC16( minx_state *minx, UINT16 arg )
+{
+ UINT8 old_F = minx->F;
+ UINT16 res = ADD16( minx, arg, 1 );
+ minx->F = ( old_F & ~ ( FLAG_Z ) )
+ | ( ( res ) ? 0 : FLAG_Z )
+ ;
+ return res;
+}
+
+
+INLINE UINT8 SUB8( minx_state *minx, UINT8 arg1, UINT8 arg2 )
+{
+ UINT32 res = arg1 - arg2;
+ minx->F = ( minx->F & ~ ( FLAG_S | FLAG_O | FLAG_C | FLAG_Z ) )
+ | ( ( res & 0x80 ) ? FLAG_S : 0 )
+ | ( ( ( arg2 ^ arg1 ) & ( arg1 ^ res ) & 0x80 ) ? FLAG_O : 0 )
+ | ( ( res & 0xFF00 ) ? FLAG_C : 0 )
+ | ( ( res ) ? 0 : FLAG_Z )
+ ;
+ return res & 0xFF;
+}
+
+
+INLINE UINT16 SUB16( minx_state *minx, UINT16 arg1, UINT16 arg2 )
+{
+ UINT32 res = arg1 - arg2;
+ minx->F = ( minx->F & ~ ( FLAG_S | FLAG_O | FLAG_C | FLAG_Z ) )
+ | ( ( res & 0x8000 ) ? FLAG_S : 0 )
+ | ( ( ( arg2 ^ arg1 ) & ( arg1 ^ res ) & 0x8000 ) ? FLAG_O : 0 )
+ | ( ( res & 0xFF0000 ) ? FLAG_C : 0 )
+ | ( ( res ) ? 0 : FLAG_Z )
+ ;
+ return res & 0xFFFF;
+}
+
+
+INLINE UINT8 SUBC8( minx_state *minx, UINT8 arg1, UINT8 arg2 )
+{
+ UINT32 res = arg1 - arg2 - ( ( minx->F & FLAG_C ) ? 1 : 0 );
+ minx->F = ( minx->F & ~ ( FLAG_S | FLAG_O | FLAG_C | FLAG_Z ) )
+ | ( ( res & 0x80 ) ? FLAG_S : 0 )
+ | ( ( ( arg2 ^ arg1 ) & ( arg1 ^ res ) & 0x80 ) ? FLAG_O : 0 )
+ | ( ( res & 0xFF00 ) ? FLAG_C : 0 )
+ | ( ( res ) ? 0 : FLAG_Z )
+ ;
+ return res & 0xFF;
+}
+
+
+INLINE UINT16 SUBC16( minx_state *minx, UINT16 arg1, UINT16 arg2 )
+{
+ UINT32 res = arg1 - arg2 - ( ( minx->F & FLAG_C ) ? 1 : 0 );
+ minx->F = ( minx->F & ~ ( FLAG_S | FLAG_O | FLAG_C | FLAG_Z ) )
+ | ( ( res & 0x8000 ) ? FLAG_S : 0 )
+ | ( ( ( arg2 ^ arg1 ) & ( arg1 ^ res ) & 0x8000 ) ? FLAG_O : 0 )
+ | ( ( res & 0xFF0000 ) ? FLAG_C : 0 )
+ | ( ( res ) ? 0 : FLAG_Z )
+ ;
+ return res & 0xFFFF;
+}
+
+
+INLINE UINT8 DEC8( minx_state *minx, UINT8 arg )
+{
+ UINT8 old_F = minx->F;
+ UINT8 res = SUB8( minx, arg, 1 );
+ minx->F = ( old_F & ~ ( FLAG_Z ) )
+ | ( ( res ) ? 0 : FLAG_Z )
+ ;
+ return res;
+}
+
+
+INLINE UINT16 DEC16( minx_state *minx, UINT16 arg )
+{
+ UINT8 old_F = minx->F;
+ UINT16 res = SUB16( minx, arg, 1 );
+ minx->F = ( old_F & ~ ( FLAG_Z ) )
+ | ( ( res ) ? 0 : FLAG_Z )
+ ;
+ return res;
+}
+
+
+INLINE UINT8 AND8( minx_state *minx, UINT8 arg1, UINT8 arg2 )
+{
+ UINT8 res = arg1 & arg2;
+ minx->F = ( minx->F & ~ ( FLAG_S | FLAG_Z ) )
+ | ( ( res & 0x80 ) ? FLAG_S : 0 )
+ | ( ( res ) ? 0 : FLAG_Z )
+ ;
+ return res;
+}
+
+
+INLINE UINT8 OR8( minx_state *minx, UINT8 arg1, UINT8 arg2 )
+{
+ UINT8 res = arg1 | arg2;
+ minx->F = ( minx->F & ~ ( FLAG_S | FLAG_Z ) )
+ | ( ( res & 0x80 ) ? FLAG_S : 0 )
+ | ( ( res ) ? 0 : FLAG_Z )
+ ;
+ return res;
+}
+
+
+INLINE UINT8 XOR8( minx_state *minx, UINT8 arg1, UINT8 arg2 )
+{
+ UINT8 res = arg1 ^ arg2;
+ minx->F = ( minx->F & ~ ( FLAG_S | FLAG_Z ) )
+ | ( ( res & 0x80 ) ? FLAG_S : 0 )
+ | ( ( res ) ? 0 : FLAG_Z )
+ ;
+ return res;
+}
+
+
+INLINE UINT8 NOT8( minx_state *minx, UINT8 arg )
+{
+ UINT8 res = ~arg;
+ minx->F = ( minx->F & ~ ( FLAG_S | FLAG_Z ) )
+ | ( ( res & 0x80 ) ? FLAG_S : 0 )
+ | ( ( res ) ? 0 : FLAG_Z )
+ ;
+ return res;
+}
+
+
+INLINE UINT8 NEG8( minx_state *minx, UINT8 arg )
+{
+ UINT8 res = -arg;
+ minx->F = ( minx->F & ~ ( FLAG_S | FLAG_O | FLAG_C | FLAG_Z ) )
+ | ( ( res & 0x80 ) ? FLAG_S : 0 )
+ | ( ( res ) ? 0 : FLAG_Z )
+ ;
+ return res;
+}
+
+
+INLINE UINT8 SAL8( minx_state *minx, UINT8 arg )
+{
+ UINT16 res = arg << 1;
+ minx->F = ( minx->F & ~ ( FLAG_S | FLAG_O | FLAG_C | FLAG_Z ) )
+ | ( ( res & 0x80 ) ? FLAG_S : 0 )
+ | ( ( arg != 0 && res == 0 ) ? FLAG_O : 0 )
+ | ( ( arg & 0x80 ) ? FLAG_C : 0 )
+ | ( ( res ) ? 0 : FLAG_Z )
+ ;
+ return res;
+}
+
+
+INLINE UINT8 SAR8( minx_state *minx, UINT8 arg )
+{
+ UINT16 res = ( arg >> 1 ) | ( arg & 0x80 );
+ minx->F = ( minx->F & ~ ( FLAG_S | FLAG_O | FLAG_C | FLAG_Z ) )
+ | ( ( res & 0x80 ) ? FLAG_S : 0 )
+ | ( ( arg != 0x80 && res == 0x80 ) ? FLAG_O : 0 )
+ | ( ( arg & 0x01 ) ? FLAG_C : 0 )
+ | ( ( res ) ? 0 : FLAG_Z )
+ ;
+ return res & 0xFF;
+}
+
+
+INLINE UINT8 SHL8( minx_state *minx, UINT8 arg )
+{
+ UINT16 res = arg << 1;
+ minx->F = ( minx->F & ~ ( FLAG_S | FLAG_C | FLAG_Z ) )
+ | ( ( res & 0x80 ) ? FLAG_S : 0 )
+ | ( ( arg & 0x80 ) ? FLAG_C : 0 )
+ | ( ( res ) ? 0 : FLAG_Z )
+ ;
+ return res;
+}
+
+
+INLINE UINT8 SHR8( minx_state *minx, UINT8 arg )
+{
+ UINT16 res = arg >> 1;
+ minx->F = ( minx->F & ~ ( FLAG_S | FLAG_C | FLAG_Z ) )
+ | ( ( res & 0x80 ) ? FLAG_S : 0 )
+ | ( ( arg & 0x01 ) ? FLAG_C : 0 )
+ | ( ( res ) ? 0 : FLAG_Z )
+ ;
+ return res & 0xFF;
+}
+
+
+INLINE UINT8 ROLC8( minx_state *minx, UINT8 arg )
+{
+ UINT16 res = ( arg << 1 ) | ( ( minx->F & FLAG_C ) ? 1 : 0 );
+ minx->F = ( minx->F & ~ ( FLAG_S | FLAG_C | FLAG_Z ) )
+ | ( ( res & 0x80 ) ? FLAG_S : 0 )
+ | ( ( arg & 0x80 ) ? FLAG_C : 0 )
+ | ( ( res ) ? 0 : FLAG_Z )
+ ;
+ return res & 0xFF;
+}
+
+
+INLINE UINT8 RORC8( minx_state *minx, UINT8 arg )
+{
+ UINT16 res = ( arg >> 1 ) | ( ( minx->F & FLAG_C ) ? 0x80 : 0 );
+ minx->F = ( minx->F & ~ ( FLAG_S | FLAG_C | FLAG_Z ) )
+ | ( ( res & 0x80 ) ? FLAG_S : 0 )
+ | ( ( arg & 0x01 ) ? FLAG_C : 0 )
+ | ( ( res ) ? 0 : FLAG_Z )
+ ;
+ return res & 0xFF;
+}
+
+
+INLINE UINT8 ROL8( minx_state *minx, UINT8 arg )
+{
+ UINT16 res = ( arg << 1 ) | ( ( arg & 0x80 ) ? 1 : 0 );
+ minx->F = ( minx->F & ~ ( FLAG_S | FLAG_C | FLAG_Z ) )
+ | ( ( res & 0x80 ) ? FLAG_S : 0 )
+ | ( ( arg & 0x80 ) ? FLAG_C : 0 )
+ | ( ( res ) ? 0 : FLAG_Z )
+ ;
+ return res & 0xFF;
+}
+
+
+INLINE UINT8 ROR8( minx_state *minx, UINT8 arg )
+{
+ UINT16 res = ( arg >> 1 ) | ( ( arg & 0x01 ) ? 0x80 : 0 );
+ minx->F = ( minx->F & ~ ( FLAG_S | FLAG_C | FLAG_Z ) )
+ | ( ( res & 0x80 ) ? FLAG_S : 0 )
+ | ( ( arg & 0x01 ) ? FLAG_C : 0 )
+ | ( ( res ) ? 0 : FLAG_Z )
+ ;
+ return res & 0xFF;
+}
+
+
+INLINE void PUSH8( minx_state *minx, UINT8 arg )
+{
+ minx->SP = minx->SP - 1;
+ WR( minx->SP, arg );
+}
+
+
+INLINE void PUSH16( minx_state *minx, UINT16 arg )
+{
+ PUSH8( minx, arg >> 8 );
+ PUSH8( minx, arg & 0x00FF );
+}
+
+
+INLINE UINT8 POP8( minx_state *minx )
+{
+ UINT8 res = RD( minx->SP );
+ minx->SP = minx->SP + 1;
+ return res;
+}
+
+
+INLINE UINT16 POP16( minx_state *minx )
+{
+ return POP8(minx) | ( POP8(minx) << 8 );
+}
+
+
+INLINE void JMP( minx_state *minx, UINT16 arg )
+{
+ minx->V = minx->U;
+ minx->PC = arg;
+}
+
+
+INLINE void CALL( minx_state *minx, UINT16 arg )
+{
+ PUSH8( minx, minx->V );
+ PUSH16( minx, minx->PC );
+ JMP( minx, arg );
+}
+
+
+#define AD1_IHL UINT32 addr1 = ( minx->I << 16 ) | minx->HL
+#define AD1_IN8 UINT32 addr1 = ( minx->I << 16 ) | ( minx->N << 8 ) | rdop(minx)
+#define AD1_I16 UINT32 addr1 = ( minx->I << 16 ) | rdop16(minx)
+#define AD1_XIX UINT32 addr1 = ( minx->XI << 16 ) | minx->X
+#define AD1_YIY UINT32 addr1 = ( minx->YI << 16 ) | minx->Y
+#define AD1_X8 UINT32 addr1 = ( minx->XI << 16 ) | ( minx->X + rdop(minx) )
+#define AD1_Y8 UINT32 addr1 = ( minx->YI << 16 ) | ( minx->Y + rdop(minx) )
+#define AD1_XL UINT32 addr1 = ( minx->XI << 16 ) | ( minx->X + ( minx->HL & 0x00FF ) )
+#define AD1_YL UINT32 addr1 = ( minx->YI << 16 ) | ( minx->Y + ( minx->HL & 0x00FF ) )
+#define AD2_IHL UINT32 addr2 = ( minx->I << 16 ) | minx->HL
+#define AD2_IN8 UINT32 addr2 = ( minx->I << 16 ) | ( minx->N << 8 ) | rdop(minx)
+#define AD2_I16 UINT32 addr2 = ( minx->I << 16 ) | rdop(minx); addr2 |= ( rdop(minx) << 8 )
+#define AD2_XIX UINT32 addr2 = ( minx->XI << 16 ) | minx->X
+#define AD2_YIY UINT32 addr2 = ( minx->YI << 16 ) | minx->Y
+#define AD2_X8 UINT32 addr2 = ( minx->XI << 16 ) | ( minx->X + rdop(minx) )
+#define AD2_Y8 UINT32 addr2 = ( minx->YI << 16 ) | ( minx->Y + rdop(minx) )
+#define AD2_XL UINT32 addr2 = ( minx->XI << 16 ) | ( minx->X + ( minx->HL & 0x00FF ) )
+#define AD2_YL UINT32 addr2 = ( minx->YI << 16 ) | ( minx->Y + ( minx->HL & 0x00FF ) )
diff --git a/trunk/src/emu/cpu/minx/minxopce.h b/trunk/src/emu/cpu/minx/minxopce.h
new file mode 100644
index 00000000000..282dccb3fab
--- /dev/null
+++ b/trunk/src/emu/cpu/minx/minxopce.h
@@ -0,0 +1,331 @@
+#undef OP
+#define OP(nn) INLINE void minx_CE_##nn(minx_state *minx)
+
+OP(00) { AD2_X8; minx->BA = ( minx->BA & 0xFF00 ) | ADD8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(01) { AD2_Y8; minx->BA = ( minx->BA & 0xFF00 ) | ADD8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(02) { AD2_XL; minx->BA = ( minx->BA & 0xFF00 ) | ADD8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(03) { AD2_YL; minx->BA = ( minx->BA & 0xFF00 ) | ADD8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(04) { AD1_IHL; WR( addr1, ADD8( minx, RD( addr1 ), ( minx->BA & 0x00FF ) ) ); }
+OP(05) { AD1_IHL; WR( addr1, ADD8( minx, RD( addr1 ), rdop(minx) ) ); }
+OP(06) { AD1_IHL; AD2_XIX; WR( addr1, ADD8( minx, RD( addr1 ), RD( addr2 ) ) ); }
+OP(07) { AD1_IHL; AD2_YIY; WR( addr1, ADD8( minx, RD( addr1 ), RD( addr2 ) ) ); }
+OP(08) { AD2_X8; minx->BA = ( minx->BA & 0xFF00 ) | ADDC8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(09) { AD2_Y8; minx->BA = ( minx->BA & 0xFF00 ) | ADDC8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(0A) { AD2_XL; minx->BA = ( minx->BA & 0xFF00 ) | ADDC8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(0B) { AD2_YL; minx->BA = ( minx->BA & 0xFF00 ) | ADDC8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(0C) { AD1_IHL; WR( addr1, ADDC8( minx, RD( addr1 ), ( minx->BA & 0x00FF ) ) ); }
+OP(0D) { AD1_IHL; WR( addr1, ADDC8( minx, RD( addr1 ), rdop(minx) ) ); }
+OP(0E) { AD1_IHL; AD2_XIX; WR( addr1, ADDC8( minx, RD( addr1 ), RD( addr2 ) ) ); }
+OP(0F) { AD1_IHL; AD2_YIY; WR( addr1, ADDC8( minx, RD( addr1 ), RD( addr2 ) ) ); }
+
+OP(10) { AD2_X8; minx->BA = ( minx->BA & 0xFF00 ) | SUB8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(11) { AD2_Y8; minx->BA = ( minx->BA & 0xFF00 ) | SUB8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(12) { AD2_XL; minx->BA = ( minx->BA & 0xFF00 ) | SUB8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(13) { AD2_YL; minx->BA = ( minx->BA & 0xFF00 ) | SUB8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(14) { AD1_IHL; WR( addr1, SUB8( minx, RD( addr1 ), ( minx->BA & 0x00FF ) ) ); }
+OP(15) { AD1_IHL; WR( addr1, SUB8( minx, RD( addr1 ), rdop(minx) ) ); }
+OP(16) { AD1_IHL; AD2_XIX; WR( addr1, SUB8( minx, RD( addr1 ), RD( addr2 ) ) ); }
+OP(17) { AD1_IHL; AD2_YIY; WR( addr1, SUB8( minx, RD( addr1 ), RD( addr2 ) ) ); }
+OP(18) { AD2_X8; minx->BA = ( minx->BA & 0xFF00 ) | SUBC8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(19) { AD2_Y8; minx->BA = ( minx->BA & 0xFF00 ) | SUBC8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(1A) { AD2_XL; minx->BA = ( minx->BA & 0xFF00 ) | SUBC8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(1B) { AD2_YL; minx->BA = ( minx->BA & 0xFF00 ) | SUBC8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(1C) { AD1_IHL; WR( addr1, SUBC8( minx, RD( addr1 ), ( minx->BA & 0x00FF ) ) ); }
+OP(1D) { AD1_IHL; WR( addr1, SUBC8( minx, RD( addr1 ), rdop(minx) ) ); }
+OP(1E) { AD1_IHL; AD2_XIX; WR( addr1, SUBC8( minx, RD( addr1 ), RD( addr2 ) ) ); }
+OP(1F) { AD1_IHL; AD2_YIY; WR( addr1, SUBC8( minx, RD( addr1 ), RD( addr2 ) ) ); }
+
+OP(20) { AD2_X8; minx->BA = ( minx->BA & 0xFF00 ) | AND8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(21) { AD2_Y8; minx->BA = ( minx->BA & 0xFF00 ) | AND8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(22) { AD2_XL; minx->BA = ( minx->BA & 0xFF00 ) | AND8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(23) { AD2_YL; minx->BA = ( minx->BA & 0xFF00 ) | AND8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(24) { AD1_IHL; WR( addr1, AND8( minx, RD( addr1 ), ( minx->BA & 0x00FF ) ) ); }
+OP(25) { AD1_IHL; WR( addr1, AND8( minx, RD( addr1 ), rdop(minx) ) ); }
+OP(26) { AD1_IHL; AD2_XIX; WR( addr1, AND8( minx, RD( addr1 ), RD( addr2 ) ) ); }
+OP(27) { AD1_IHL; AD2_YIY; WR( addr1, AND8( minx, RD( addr1 ), RD( addr2 ) ) ); }
+OP(28) { AD2_X8; minx->BA = ( minx->BA & 0xFF00 ) | OR8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(29) { AD2_Y8; minx->BA = ( minx->BA & 0xFF00 ) | OR8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(2A) { AD2_XL; minx->BA = ( minx->BA & 0xFF00 ) | OR8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(2B) { AD2_YL; minx->BA = ( minx->BA & 0xFF00 ) | OR8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(2C) { AD1_IHL; WR( addr1, OR8( minx, RD( addr1 ), ( minx->BA & 0x00FF ) ) ); }
+OP(2D) { AD1_IHL; WR( addr1, OR8( minx, RD( addr1 ), rdop(minx) ) ); }
+OP(2E) { AD1_IHL; AD2_XIX; WR( addr1, OR8( minx, RD( addr1 ), RD( addr2 ) ) ); }
+OP(2F) { AD1_IHL; AD2_YIY; WR( addr1, OR8( minx, RD( addr1 ), RD( addr2 ) ) ); }
+
+OP(30) { AD2_X8; SUB8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(31) { AD2_Y8; SUB8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(32) { AD2_XL; SUB8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(33) { AD2_YL; SUB8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(34) { AD1_IHL; SUB8( minx, RD( addr1 ), ( minx->BA & 0x00FF ) ); }
+OP(35) { AD1_IHL; SUB8( minx, RD( addr1 ), rdop(minx) ); }
+OP(36) { AD1_IHL; AD2_XIX; SUB8( minx, RD( addr1 ), RD( addr2 ) ); }
+OP(37) { AD1_IHL; AD2_YIY; SUB8( minx, RD( addr1 ), RD( addr2 ) ); }
+OP(38) { AD2_X8; minx->BA = ( minx->BA & 0xFF00 ) | XOR8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(39) { AD2_Y8; minx->BA = ( minx->BA & 0xFF00 ) | XOR8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(3A) { AD2_XL; minx->BA = ( minx->BA & 0xFF00 ) | XOR8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(3B) { AD2_YL; minx->BA = ( minx->BA & 0xFF00 ) | XOR8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(3C) { AD1_IHL; WR( addr1, XOR8( minx, RD( addr1 ), ( minx->BA & 0x00FF ) ) ); }
+OP(3D) { AD1_IHL; WR( addr1, XOR8( minx, RD( addr1 ), rdop(minx) ) ); }
+OP(3E) { AD1_IHL; AD2_XIX; WR( addr1, XOR8( minx, RD( addr1 ), RD( addr2 ) ) ); }
+OP(3F) { AD1_IHL; AD2_YIY; WR( addr1, XOR8( minx, RD( addr1 ), RD( addr2 ) ) ); }
+
+OP(40) { AD2_X8; minx->BA = ( minx->BA & 0xFF00 ) | RD( addr2 ); }
+OP(41) { AD2_Y8; minx->BA = ( minx->BA & 0xFF00 ) | RD( addr2 ); }
+OP(42) { AD2_XL; minx->BA = ( minx->BA & 0xFF00 ) | RD( addr2 ); }
+OP(43) { AD2_YL; minx->BA = ( minx->BA & 0xFF00 ) | RD( addr2 ); }
+OP(44) { AD1_X8; WR( addr1, ( minx->BA & 0x00FF ) ); }
+OP(45) { AD1_Y8; WR( addr1, ( minx->BA & 0x00FF ) ); }
+OP(46) { AD1_XL; WR( addr1, ( minx->BA & 0x00FF ) ); }
+OP(47) { AD1_YL; WR( addr1, ( minx->BA & 0x00FF ) ); }
+OP(48) { AD2_X8; minx->BA = ( minx->BA & 0x00FF ) | ( RD( addr2 ) << 8 ); }
+OP(49) { AD2_Y8; minx->BA = ( minx->BA & 0x00FF ) | ( RD( addr2 ) << 8 ); }
+OP(4A) { AD2_XL; minx->BA = ( minx->BA & 0x00FF ) | ( RD( addr2 ) << 8 ); }
+OP(4B) { AD2_YL; minx->BA = ( minx->BA & 0x00FF ) | ( RD( addr2 ) << 8 ); }
+OP(4C) { AD1_X8; WR( addr1, ( minx->BA >> 8 ) ); }
+OP(4D) { AD1_Y8; WR( addr1, ( minx->BA >> 8 ) ); }
+OP(4E) { AD1_XL; WR( addr1, ( minx->BA >> 8 ) ); }
+OP(4F) { AD1_YL; WR( addr1, ( minx->BA >> 8 ) ); }
+
+OP(50) { AD2_X8; minx->HL = ( minx->HL & 0xFF00 ) | RD( addr2 ); }
+OP(51) { AD2_Y8; minx->HL = ( minx->HL & 0xFF00 ) | RD( addr2 ); }
+OP(52) { AD2_XL; minx->HL = ( minx->HL & 0xFF00 ) | RD( addr2 ); }
+OP(53) { AD2_YL; minx->HL = ( minx->HL & 0xFF00 ) | RD( addr2 ); }
+OP(54) { AD1_X8; WR( addr1, ( minx->HL & 0x00FF ) ); }
+OP(55) { AD1_Y8; WR( addr1, ( minx->HL & 0x00FF ) ); }
+OP(56) { AD1_XL; WR( addr1, ( minx->HL & 0x00FF ) ); }
+OP(57) { AD1_YL; WR( addr1, ( minx->HL & 0x00FF ) ); }
+OP(58) { AD2_X8; minx->HL = ( minx->HL & 0x00FF ) | ( RD( addr2 ) << 8 ); }
+OP(59) { AD2_Y8; minx->HL = ( minx->HL & 0x00FF ) | ( RD( addr2 ) << 8 ); }
+OP(5A) { AD2_XL; minx->HL = ( minx->HL & 0x00FF ) | ( RD( addr2 ) << 8 ); }
+OP(5B) { AD2_YL; minx->HL = ( minx->HL & 0x00FF ) | ( RD( addr2 ) << 8 ); }
+OP(5C) { AD1_X8; WR( addr1, ( minx->HL >> 8 ) ); }
+OP(5D) { AD1_Y8; WR( addr1, ( minx->HL >> 8 ) ); }
+OP(5E) { AD1_XL; WR( addr1, ( minx->HL >> 8 ) ); }
+OP(5F) { AD1_YL; WR( addr1, ( minx->HL >> 8 ) ); }
+
+OP(60) { AD1_IHL; AD2_X8; WR( addr1, RD( addr2 ) ); }
+OP(61) { AD1_IHL; AD2_Y8; WR( addr1, RD( addr2 ) ); }
+OP(62) { AD1_IHL; AD2_XL; WR( addr1, RD( addr2 ) ); }
+OP(63) { AD1_IHL; AD2_YL; WR( addr1, RD( addr2 ) ); }
+OP(64) { /* illegal operation? */ }
+OP(65) { /* illegal operation? */ }
+OP(66) { /* illegal operation? */ }
+OP(67) { /* illegal operation? */ }
+OP(68) { AD1_XIX; AD2_X8; WR( addr1, RD( addr2 ) ); }
+OP(69) { AD1_XIX; AD2_Y8; WR( addr1, RD( addr2 ) ); }
+OP(6A) { AD1_XIX; AD2_XL; WR( addr1, RD( addr2 ) ); }
+OP(6B) { AD1_XIX; AD2_YL; WR( addr1, RD( addr2 ) ); }
+OP(6C) { /* illegal operation? */ }
+OP(6D) { /* illegal operation? */ }
+OP(6E) { /* illegal operation? */ }
+OP(6F) { /* illegal operation? */ }
+
+OP(70) { /* illegal operation? */ }
+OP(71) { /* illegal operation? */ }
+OP(72) { /* illegal operation? */ }
+OP(73) { /* illegal operation? */ }
+OP(74) { /* illegal operation? */ }
+OP(75) { /* illegal operation? */ }
+OP(76) { /* illegal operation? */ }
+OP(77) { /* illegal operation? */ }
+OP(78) { AD1_YIY; AD2_X8; WR( addr1, RD( addr2 ) ); }
+OP(79) { AD1_YIY; AD2_Y8; WR( addr1, RD( addr2 ) ); }
+OP(7A) { AD1_YIY; AD2_XL; WR( addr1, RD( addr2 ) ); }
+OP(7B) { AD1_YIY; AD2_YL; WR( addr1, RD( addr2 ) ); }
+OP(7C) { /* illegal operation? */ }
+OP(7D) { /* illegal operation? */ }
+OP(7E) { /* illegal operation? */ }
+OP(7F) { /* illegal operation? */ }
+
+OP(80) { minx->BA = ( minx->BA & 0xFF00 ) | SAL8( minx, minx->BA & 0x00FF ); }
+OP(81) { minx->BA = ( minx->BA & 0x00FF ) | ( SAL8( minx, minx->BA >> 8 )<< 8 ); }
+OP(82) { AD1_IN8; WR( addr1, SAL8( minx, RD( addr1 ) ) ); }
+OP(83) { AD1_IHL; WR( addr1, SAL8( minx, RD( addr1 ) ) ); }
+OP(84) { minx->BA = ( minx->BA & 0xFF00 ) | SHL8( minx, minx->BA & 0x00FF ); }
+OP(85) { minx->BA = ( minx->BA & 0x00FF ) | ( SHL8( minx, minx->BA >> 8 ) << 8 ); }
+OP(86) { AD1_IN8; WR( addr1, SHL8( minx, RD( addr1 ) ) ); }
+OP(87) { AD1_IHL; WR( addr1, SHL8( minx, RD( addr1 ) ) ); }
+OP(88) { minx->BA = ( minx->BA & 0xFF00 ) | SAR8( minx, minx->BA & 0x00FF ); }
+OP(89) { minx->BA = ( minx->BA & 0x00FF ) | ( SAR8( minx, minx->BA >> 8 ) << 8 ); }
+OP(8A) { AD1_IN8; WR( addr1, SAR8( minx, RD( addr1 ) ) ); }
+OP(8B) { AD1_IHL; WR( addr1, SAR8( minx, RD( addr1 ) ) ); }
+OP(8C) { minx->BA = ( minx->BA & 0xFF00 ) | SHR8( minx, minx->BA & 0x00FF ); }
+OP(8D) { minx->BA = ( minx->BA & 0x00FF ) | ( SHR8( minx, minx->BA >> 8 ) << 8 ); }
+OP(8E) { AD1_IN8; WR( addr1, SHR8( minx, RD( addr1 ) ) ); }
+OP(8F) { AD1_IHL; WR( addr1, SHR8( minx, RD( addr1 ) ) ); }
+
+OP(90) { minx->BA = ( minx->BA & 0xFF00 ) | ROLC8( minx, minx->BA & 0x00FF ); }
+OP(91) { minx->BA = ( minx->BA & 0x00FF ) | ( ROLC8( minx, minx->BA >> 8 ) << 8 ); }
+OP(92) { AD1_IN8; WR( addr1, ROLC8( minx, RD( addr1 ) ) ); }
+OP(93) { AD1_IHL; WR( addr1, ROLC8( minx, RD( addr1 ) ) ); }
+OP(94) { minx->BA = ( minx->BA & 0xFF00 ) | ROL8( minx, minx->BA & 0x00FF ); }
+OP(95) { minx->BA = ( minx->BA & 0x00FF ) | ( ROL8( minx, minx->BA >> 8 ) << 8 ); }
+OP(96) { AD1_IN8; WR( addr1, ROL8( minx, RD( addr1 ) ) ); }
+OP(97) { AD1_IHL; WR( addr1, ROL8( minx, RD( addr1 ) ) ); }
+OP(98) { minx->BA = ( minx->BA & 0xFF00 ) | RORC8( minx, minx->BA & 0x00FF ); }
+OP(99) { minx->BA = ( minx->BA & 0x00FF ) | ( RORC8( minx, minx->BA >> 8 ) << 8 ); }
+OP(9A) { AD1_IN8; WR( addr1, RORC8( minx, RD( addr1 ) ) ); }
+OP(9B) { AD1_IHL; WR( addr1, RORC8( minx, RD( addr1 ) ) ); }
+OP(9C) { minx->BA = ( minx->BA & 0xFF00 ) | ROR8( minx, minx->BA & 0x00FF ); }
+OP(9D) { minx->BA = ( minx->BA & 0x00FF ) | ( ROR8( minx, minx->BA >> 8 ) << 8 ); }
+OP(9E) { AD1_IN8; WR( addr1, ROR8( minx, RD( addr1 ) ) ); }
+OP(9F) { AD1_IHL; WR( addr1, ROR8( minx, RD( addr1 ) ) ); }
+
+OP(A0) { minx->BA = ( minx->BA & 0xFF00 ) | NOT8( minx, minx->BA & 0x00FF ); }
+OP(A1) { minx->BA = ( minx->BA & 0x00FF ) | ( NOT8( minx, minx->BA >> 8 ) << 8 ); }
+OP(A2) { AD1_IN8; WR( addr1, NOT8( minx, RD( addr1 ) ) ); }
+OP(A3) { AD1_IHL; WR( addr1, NOT8( minx, RD( addr1 ) ) ); }
+OP(A4) { minx->BA = ( minx->BA & 0xFF00 ) | NEG8( minx, minx->BA & 0x00FF ); }
+OP(A5) { minx->BA = ( minx->BA & 0x00FF ) | ( NEG8( minx, minx->BA >> 8 ) << 8 ); }
+OP(A6) { AD1_IN8; WR( addr1, NEG8( minx, RD( addr1 ) ) ); }
+OP(A7) { AD1_IHL; WR( addr1, NEG8( minx, RD( addr1 ) ) ); }
+OP(A8) { minx->BA = ( ( minx->BA & 0x0080 ) ? ( 0xFF00 | minx->BA ) : ( minx->BA & 0x00FF ) ); }
+OP(A9) { /* illegal operation? */ }
+OP(AA) { /* illegal operation? */ }
+OP(AB) { /* illegal operation? */ }
+OP(AC) { /* illegal operation? */ }
+OP(AD) { /* illegal operation? */ }
+OP(AE) { /* HALT */ minx->halted = 1; }
+OP(AF) { }
+
+OP(B0) { minx->BA = ( minx->BA & 0x00FF ) | ( AND8( minx, ( minx->BA >> 8 ), rdop(minx) ) << 8 ); }
+OP(B1) { minx->HL = ( minx->HL & 0xFF00 ) | AND8( minx, ( minx->HL & 0x00FF ), rdop(minx) ); }
+OP(B2) { minx->HL = ( minx->HL & 0x00FF ) | ( AND8( minx, ( minx->HL >> 8 ), rdop(minx) ) << 8 ); }
+OP(B3) { /* illegal operation? */ }
+OP(B4) { minx->BA = ( minx->BA & 0x00FF ) | ( OR8( minx, ( minx->BA >> 8 ), rdop(minx) ) << 8 ); }
+OP(B5) { minx->HL = ( minx->HL & 0xFF00 ) | OR8( minx, ( minx->HL & 0x00FF ), rdop(minx) ); }
+OP(B6) { minx->HL = ( minx->HL & 0x00FF ) | ( OR8( minx, ( minx->HL >> 8 ), rdop(minx) ) << 8 ); }
+OP(B7) { /* illegal operation? */ }
+OP(B8) { minx->BA = ( minx->BA & 0x00FF ) | ( XOR8( minx, ( minx->BA >> 8 ), rdop(minx) ) << 8 ); }
+OP(B9) { minx->HL = ( minx->HL & 0xFF00 ) | XOR8( minx, ( minx->HL & 0x00FF ), rdop(minx) ); }
+OP(BA) { minx->HL = ( minx->HL & 0x00FF ) | ( XOR8( minx, ( minx->HL >> 8 ), rdop(minx) ) << 8 ); }
+OP(BB) { /* illegal operation? */ }
+OP(BC) { SUB8( minx, ( minx->BA >> 8 ), rdop(minx) ); }
+OP(BD) { SUB8( minx, ( minx->HL & 0x00FF), rdop(minx) ); }
+OP(BE) { SUB8( minx, ( minx->HL >> 8 ), rdop(minx) ); }
+OP(BF) { SUB8( minx, minx->N, rdop(minx) ); }
+
+OP(C0) { minx->BA = ( minx->BA & 0xFF00 ) | minx->N; }
+OP(C1) { minx->BA = ( minx->BA & 0xFF00 ) | minx->F; }
+OP(C2) { minx->N = ( minx->BA & 0x00FF ); }
+OP(C3) { minx->F = ( minx->BA & 0x00FF ); }
+OP(C4) { minx->U = rdop(minx); }
+OP(C5) { minx->I = rdop(minx); }
+OP(C6) { minx->XI = rdop(minx); }
+OP(C7) { minx->YI = rdop(minx); }
+OP(C8) { minx->BA = ( minx->BA & 0xFF00 ) | minx->V; }
+OP(C9) { minx->BA = ( minx->BA & 0xFF00 ) | minx->I; }
+OP(CA) { minx->BA = ( minx->BA & 0xFF00 ) | minx->XI; }
+OP(CB) { minx->BA = ( minx->BA & 0xFF00 ) | minx->YI; }
+OP(CC) { minx->U = ( minx->BA & 0x00FF ); }
+OP(CD) { minx->I = ( minx->BA & 0x00FF ); }
+OP(CE) { minx->XI = ( minx->BA & 0x00FF ); }
+OP(CF) { minx->YI = ( minx->BA & 0x00FF ); }
+
+OP(D0) { AD2_I16; minx->BA = ( minx->BA & 0xFF00 ) | RD( addr2 ); }
+OP(D1) { AD2_I16; minx->BA = ( minx->BA & 0x00FF ) | ( RD( addr2 ) << 8 ); }
+OP(D2) { AD2_I16; minx->HL = ( minx->HL & 0xFF00 ) | RD( addr2 ); }
+OP(D3) { AD2_I16; minx->HL = ( minx->HL & 0x00FF ) | ( RD( addr2 ) << 8 ); }
+OP(D4) { AD1_I16; WR( addr1, ( minx->BA & 0x00FF ) ); }
+OP(D5) { AD1_I16; WR( addr1, ( minx->BA >> 8 ) ); }
+OP(D6) { AD1_I16; WR( addr1, ( minx->HL & 0x00FF ) ); }
+OP(D7) { AD1_I16; WR( addr1, ( minx->HL >> 8 ) ); }
+OP(D8) { minx->HL = ( minx->HL & 0x00FF ) * ( minx->BA & 0x00FF ); }
+OP(D9) { int d = minx->HL / ( minx->BA & 0x00FF ); minx->HL = ( ( minx->HL - ( ( minx->BA & 0x00FF ) * d ) ) << 8 ) | d; }
+OP(DA) { /* illegal operation? */ }
+OP(DB) { /* illegal operation? */ }
+OP(DC) { /* illegal operation? */ }
+OP(DD) { /* illegal operation? */ }
+OP(DE) { /* illegal operation? */ }
+OP(DF) { /* illegal operation? */ }
+
+OP(E0) { INT8 d8 = rdop(minx); if ( ( ( minx->F & ( FLAG_S | FLAG_O ) ) == FLAG_S ) || ( ( minx->F & ( FLAG_S | FLAG_O ) ) == FLAG_O ) ) { JMP( minx, minx->PC + d8 - 1 ); } }
+OP(E1) { INT8 d8 = rdop(minx); if ( ( minx->F & FLAG_Z ) || ( ( minx->F & ( FLAG_S | FLAG_O ) ) == FLAG_S ) || ( ( minx->F & ( FLAG_S | FLAG_O ) ) == FLAG_O ) ) { JMP( minx, minx->PC + d8 - 1 ); } }
+OP(E2) { INT8 d8 = rdop(minx); if ( !( minx->F & FLAG_Z ) && ( ( ( minx->F & ( FLAG_S | FLAG_O ) ) == 0 ) || ( ( minx->F & ( FLAG_S | FLAG_O ) ) == ( FLAG_S | FLAG_O ) ) ) ) { JMP( minx, minx->PC + d8 - 1 ); } }
+OP(E3) { INT8 d8 = rdop(minx); if ( ( ( minx->F & ( FLAG_S | FLAG_O ) ) == 0 ) || ( ( minx->F & ( FLAG_S | FLAG_O ) ) == ( FLAG_S | FLAG_O ) ) ) { JMP( minx, minx->PC + d8 - 1 ); } }
+OP(E4) { INT8 d8 = rdop(minx); if ( ( minx->F & FLAG_O ) ) { JMP( minx, minx->PC + d8 - 1 ); } }
+OP(E5) { INT8 d8 = rdop(minx); if ( ! ( minx->F & FLAG_O ) ) { JMP( minx, minx->PC + d8 - 1 ); } }
+OP(E6) { INT8 d8 = rdop(minx); if ( ! ( minx->F & FLAG_S ) ) { JMP( minx, minx->PC + d8 - 1 ); } }
+OP(E7) { INT8 d8 = rdop(minx); if ( ( minx->F & FLAG_S ) ) { JMP( minx, minx->PC + d8 - 1 ); } }
+OP(E8) { INT8 d8 = rdop(minx); if ( ! ( minx->E & EXEC_X0 ) ) { JMP( minx, minx->PC + d8 - 1 ); } }
+OP(E9) { INT8 d8 = rdop(minx); if ( ! ( minx->E & EXEC_X1 ) ) { JMP( minx, minx->PC + d8 - 1 ); } }
+OP(EA) { INT8 d8 = rdop(minx); if ( ! ( minx->E & EXEC_X2 ) ) { JMP( minx, minx->PC + d8 - 1 ); } }
+OP(EB) { INT8 d8 = rdop(minx); if ( ! ( minx->E & EXEC_DZ ) ) { JMP( minx, minx->PC + d8 - 1 ); } }
+OP(EC) { INT8 d8 = rdop(minx); if ( ( minx->E & EXEC_X0 ) ) { JMP( minx, minx->PC + d8 - 1 ); } }
+OP(ED) { INT8 d8 = rdop(minx); if ( ( minx->E & EXEC_X1 ) ) { JMP( minx, minx->PC + d8 - 1 ); } }
+OP(EE) { INT8 d8 = rdop(minx); if ( ( minx->E & EXEC_X2 ) ) { JMP( minx, minx->PC + d8 - 1 ); } }
+OP(EF) { INT8 d8 = rdop(minx); if ( ( minx->E & EXEC_DZ ) ) { JMP( minx, minx->PC + d8 - 1 ); } }
+
+OP(F0) { INT8 d8 = rdop(minx); if ( ( ( minx->F & ( FLAG_S | FLAG_O ) ) == FLAG_S ) || ( ( minx->F & ( FLAG_S | FLAG_O ) ) == FLAG_O ) ) { CALL( minx, minx->PC + d8 - 1 ); minx->icount -= 12; } }
+OP(F1) { INT8 d8 = rdop(minx); if ( ( minx->F & FLAG_Z ) || ( ( minx->F & ( FLAG_S | FLAG_O ) ) == FLAG_S ) || ( ( minx->F & ( FLAG_S | FLAG_O ) ) == FLAG_O ) ) { CALL( minx, minx->PC + d8 - 1 ); minx->icount -= 12; } }
+OP(F2) { INT8 d8 = rdop(minx); if ( !( minx->F & FLAG_Z ) && ( ( ( minx->F & ( FLAG_S | FLAG_O ) ) == 0 ) || ( ( minx->F & ( FLAG_S | FLAG_O ) ) == ( FLAG_S | FLAG_O ) ) ) ) { CALL( minx, minx->PC + d8 - 1 ); minx->icount -= 12; } }
+OP(F3) { INT8 d8 = rdop(minx); if ( ( ( minx->F & ( FLAG_S | FLAG_O ) ) == 0 ) || ( ( minx->F & ( FLAG_S | FLAG_O ) ) == ( FLAG_S | FLAG_O ) ) ) { CALL( minx, minx->PC + d8 - 1 ); } }
+OP(F4) { INT8 d8 = rdop(minx); if ( ( minx->F & FLAG_O ) ) { CALL( minx, minx->PC + d8 - 1 ); minx->icount -= 12; } }
+OP(F5) { INT8 d8 = rdop(minx); if ( ! ( minx->F & FLAG_O ) ) { CALL( minx, minx->PC + d8 - 1 ); minx->icount -= 12; } }
+OP(F6) { INT8 d8 = rdop(minx); if ( ! ( minx->F & FLAG_S ) ) { CALL( minx, minx->PC + d8 - 1 ); minx->icount -= 12; } }
+OP(F7) { INT8 d8 = rdop(minx); if ( ( minx->F & FLAG_S ) ) { CALL( minx, minx->PC + d8 - 1 ); minx->icount -= 12; } }
+OP(F8) { INT8 d8 = rdop(minx); if ( ! ( minx->E & EXEC_X0 ) ) { CALL( minx, minx->PC + d8 - 1 ); minx->icount -= 12; } }
+OP(F9) { INT8 d8 = rdop(minx); if ( ! ( minx->E & EXEC_X1 ) ) { CALL( minx, minx->PC + d8 - 1 ); minx->icount -= 12; } }
+OP(FA) { INT8 d8 = rdop(minx); if ( ! ( minx->E & EXEC_X2 ) ) { CALL( minx, minx->PC + d8 - 1 ); minx->icount -= 12; } }
+OP(FB) { INT8 d8 = rdop(minx); if ( ! ( minx->E & EXEC_DZ ) ) { CALL( minx, minx->PC + d8 - 1 ); minx->icount -= 12; } }
+OP(FC) { INT8 d8 = rdop(minx); if ( ( minx->E & EXEC_X0 ) ) { CALL( minx, minx->PC + d8 - 1 ); minx->icount -= 12; } }
+OP(FD) { INT8 d8 = rdop(minx); if ( ( minx->E & EXEC_X1 ) ) { CALL( minx, minx->PC + d8 - 1 ); minx->icount -= 12; } }
+OP(FE) { INT8 d8 = rdop(minx); if ( ( minx->E & EXEC_X2 ) ) { CALL( minx, minx->PC + d8 - 1 ); minx->icount -= 12; } }
+OP(FF) { INT8 d8 = rdop(minx); if ( ( minx->E & EXEC_DZ ) ) { CALL( minx, minx->PC + d8 - 1 ); minx->icount -= 12; } }
+
+static void (*const insnminx_CE[256])(minx_state *minx) = {
+ minx_CE_00, minx_CE_01, minx_CE_02, minx_CE_03, minx_CE_04, minx_CE_05, minx_CE_06, minx_CE_07,
+ minx_CE_08, minx_CE_09, minx_CE_0A, minx_CE_0B, minx_CE_0C, minx_CE_0D, minx_CE_0E, minx_CE_0F,
+ minx_CE_10, minx_CE_11, minx_CE_12, minx_CE_13, minx_CE_14, minx_CE_15, minx_CE_16, minx_CE_17,
+ minx_CE_18, minx_CE_19, minx_CE_1A, minx_CE_1B, minx_CE_1C, minx_CE_1D, minx_CE_1E, minx_CE_1F,
+ minx_CE_20, minx_CE_21, minx_CE_22, minx_CE_23, minx_CE_24, minx_CE_25, minx_CE_26, minx_CE_27,
+ minx_CE_28, minx_CE_29, minx_CE_2A, minx_CE_2B, minx_CE_2C, minx_CE_2D, minx_CE_2E, minx_CE_2F,
+ minx_CE_30, minx_CE_31, minx_CE_32, minx_CE_33, minx_CE_34, minx_CE_35, minx_CE_36, minx_CE_37,
+ minx_CE_38, minx_CE_39, minx_CE_3A, minx_CE_3B, minx_CE_3C, minx_CE_3D, minx_CE_3E, minx_CE_3F,
+ minx_CE_40, minx_CE_41, minx_CE_42, minx_CE_43, minx_CE_44, minx_CE_45, minx_CE_46, minx_CE_47,
+ minx_CE_48, minx_CE_49, minx_CE_4A, minx_CE_4B, minx_CE_4C, minx_CE_4D, minx_CE_4E, minx_CE_4F,
+ minx_CE_50, minx_CE_51, minx_CE_52, minx_CE_53, minx_CE_54, minx_CE_55, minx_CE_56, minx_CE_57,
+ minx_CE_58, minx_CE_59, minx_CE_5A, minx_CE_5B, minx_CE_5C, minx_CE_5D, minx_CE_5E, minx_CE_5F,
+ minx_CE_60, minx_CE_61, minx_CE_62, minx_CE_63, minx_CE_64, minx_CE_65, minx_CE_66, minx_CE_67,
+ minx_CE_68, minx_CE_69, minx_CE_6A, minx_CE_6B, minx_CE_6C, minx_CE_6D, minx_CE_6E, minx_CE_6F,
+ minx_CE_70, minx_CE_71, minx_CE_72, minx_CE_73, minx_CE_74, minx_CE_75, minx_CE_76, minx_CE_77,
+ minx_CE_78, minx_CE_79, minx_CE_7A, minx_CE_7B, minx_CE_7C, minx_CE_7D, minx_CE_7E, minx_CE_7F,
+ minx_CE_80, minx_CE_81, minx_CE_82, minx_CE_83, minx_CE_84, minx_CE_85, minx_CE_86, minx_CE_87,
+ minx_CE_88, minx_CE_89, minx_CE_8A, minx_CE_8B, minx_CE_8C, minx_CE_8D, minx_CE_8E, minx_CE_8F,
+ minx_CE_90, minx_CE_91, minx_CE_92, minx_CE_93, minx_CE_94, minx_CE_95, minx_CE_96, minx_CE_97,
+ minx_CE_98, minx_CE_99, minx_CE_9A, minx_CE_9B, minx_CE_9C, minx_CE_9D, minx_CE_9E, minx_CE_9F,
+ minx_CE_A0, minx_CE_A1, minx_CE_A2, minx_CE_A3, minx_CE_A4, minx_CE_A5, minx_CE_A6, minx_CE_A7,
+ minx_CE_A8, minx_CE_A9, minx_CE_AA, minx_CE_AB, minx_CE_AC, minx_CE_AD, minx_CE_AE, minx_CE_AF,
+ minx_CE_B0, minx_CE_B1, minx_CE_B2, minx_CE_B3, minx_CE_B4, minx_CE_B5, minx_CE_B6, minx_CE_B7,
+ minx_CE_B8, minx_CE_B9, minx_CE_BA, minx_CE_BB, minx_CE_BC, minx_CE_BD, minx_CE_BE, minx_CE_BF,
+ minx_CE_C0, minx_CE_C1, minx_CE_C2, minx_CE_C3, minx_CE_C4, minx_CE_C5, minx_CE_C6, minx_CE_C7,
+ minx_CE_C8, minx_CE_C9, minx_CE_CA, minx_CE_CB, minx_CE_CC, minx_CE_CD, minx_CE_CE, minx_CE_CF,
+ minx_CE_D0, minx_CE_D1, minx_CE_D2, minx_CE_D3, minx_CE_D4, minx_CE_D5, minx_CE_D6, minx_CE_D7,
+ minx_CE_D8, minx_CE_D9, minx_CE_DA, minx_CE_DB, minx_CE_DC, minx_CE_DD, minx_CE_DE, minx_CE_DF,
+ minx_CE_E0, minx_CE_E1, minx_CE_E2, minx_CE_E3, minx_CE_E4, minx_CE_E5, minx_CE_E6, minx_CE_E7,
+ minx_CE_E8, minx_CE_E9, minx_CE_EA, minx_CE_EB, minx_CE_EC, minx_CE_ED, minx_CE_EE, minx_CE_EF,
+ minx_CE_F0, minx_CE_F1, minx_CE_F2, minx_CE_F3, minx_CE_F4, minx_CE_F5, minx_CE_F6, minx_CE_F7,
+ minx_CE_F8, minx_CE_F9, minx_CE_FA, minx_CE_FB, minx_CE_FC, minx_CE_FD, minx_CE_FE, minx_CE_FF
+};
+
+static const int insnminx_cycles_CE[256] = {
+ 16, 16, 16, 16, 16, 20, 20, 20, 16, 16, 16, 16, 16, 20, 20, 20,
+ 16, 16, 16, 16, 16, 20, 20, 20, 16, 16, 16, 16, 16, 20, 20, 20,
+ 16, 16, 16, 16, 16, 20, 20, 20, 16, 16, 16, 16, 16, 20, 20, 20,
+ 16, 16, 16, 16, 16, 20, 20, 20, 16, 16, 16, 16, 16, 20, 20, 20,
+
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 20, 20, 20, 20, 1, 1, 1, 1, 20, 20, 20, 20, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 20, 20, 20, 20, 1, 1, 1, 1,
+
+ 12, 12, 20, 16, 12, 12, 20, 16, 12, 12, 20, 16, 12, 12, 20, 16,
+ 12, 12, 20, 16, 12, 12, 20, 16, 12, 12, 20, 16, 12, 12, 20, 16,
+ 12, 12, 20, 16, 12, 12, 20, 16, 12, 1, 1, 1, 1, 1, 8, 8,
+ 12, 12, 12, 1, 12, 12, 12, 1, 20, 20, 20, 20, 12, 12, 12, 1,
+
+ 8, 8, 8, 12, 16, 12, 12, 12, 8, 8, 8, 8, 12, 8, 8, 8,
+ 20, 20, 20, 20, 20, 20, 20, 20, 48, 52, 1, 1, 1, 1, 1, 1,
+ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12
+};
diff --git a/trunk/src/emu/cpu/minx/minxopcf.h b/trunk/src/emu/cpu/minx/minxopcf.h
new file mode 100644
index 00000000000..ed606a2b68f
--- /dev/null
+++ b/trunk/src/emu/cpu/minx/minxopcf.h
@@ -0,0 +1,331 @@
+#undef OP
+#define OP(nn) INLINE void minx_CF_##nn(minx_state *minx)
+
+OP(00) { minx->BA = ADD16( minx, minx->BA, minx->BA ); }
+OP(01) { minx->BA = ADD16( minx, minx->BA, minx->HL ); }
+OP(02) { minx->BA = ADD16( minx, minx->BA, minx->X ); }
+OP(03) { minx->BA = ADD16( minx, minx->BA, minx->Y ); }
+OP(04) { minx->BA = ADDC16( minx, minx->BA, minx->BA ); }
+OP(05) { minx->BA = ADDC16( minx, minx->BA, minx->HL ); }
+OP(06) { minx->BA = ADDC16( minx, minx->BA, minx->X ); }
+OP(07) { minx->BA = ADDC16( minx, minx->BA, minx->Y ); }
+OP(08) { minx->BA = SUB16( minx, minx->BA, minx->BA ); }
+OP(09) { minx->BA = SUB16( minx, minx->BA, minx->HL ); }
+OP(0A) { minx->BA = SUB16( minx, minx->BA, minx->X ); }
+OP(0B) { minx->BA = SUB16( minx, minx->BA, minx->Y ); }
+OP(0C) { minx->BA = SUBC16( minx, minx->BA, minx->BA ); }
+OP(0D) { minx->BA = SUBC16( minx, minx->BA, minx->HL ); }
+OP(0E) { minx->BA = SUBC16( minx, minx->BA, minx->X ); }
+OP(0F) { minx->BA = SUBC16( minx, minx->BA, minx->Y ); }
+
+OP(10) { /* illegal instruction? */ }
+OP(11) { /* illegal instruction? */ }
+OP(12) { /* illegal instruction? */ }
+OP(13) { /* illegal instruction? */ }
+OP(14) { /* illegal instruction? */ }
+OP(15) { /* illegal instruction? */ }
+OP(16) { /* illegal instruction? */ }
+OP(17) { /* illegal instruction? */ }
+OP(18) { SUB16( minx, minx->BA, minx->BA ); }
+OP(19) { SUB16( minx, minx->BA, minx->HL ); }
+OP(1A) { SUB16( minx, minx->BA, minx->X ); }
+OP(1B) { SUB16( minx, minx->BA, minx->Y ); }
+OP(1C) { /* illegal instruction? */ }
+OP(1D) { /* illegal instruction? */ }
+OP(1E) { /* illegal instruction? */ }
+OP(1F) { /* illegal instruction? */ }
+
+OP(20) { minx->HL = ADD16( minx, minx->HL, minx->BA ); }
+OP(21) { minx->HL = ADD16( minx, minx->HL, minx->HL ); }
+OP(22) { minx->HL = ADD16( minx, minx->HL, minx->X ); }
+OP(23) { minx->HL = ADD16( minx, minx->HL, minx->Y ); }
+OP(24) { minx->HL = ADDC16( minx, minx->HL, minx->BA ); }
+OP(25) { minx->HL = ADDC16( minx, minx->HL, minx->HL ); }
+OP(26) { minx->HL = ADDC16( minx, minx->HL, minx->X ); }
+OP(27) { minx->HL = ADDC16( minx, minx->HL, minx->Y ); }
+OP(28) { minx->HL = SUB16( minx, minx->HL, minx->BA ); }
+OP(29) { minx->HL = SUB16( minx, minx->HL, minx->HL ); }
+OP(2A) { minx->HL = SUB16( minx, minx->HL, minx->X ); }
+OP(2B) { minx->HL = SUB16( minx, minx->HL, minx->Y ); }
+OP(2C) { minx->HL = SUBC16( minx, minx->HL, minx->BA ); }
+OP(2D) { minx->HL = SUBC16( minx, minx->HL, minx->HL ); }
+OP(2E) { minx->HL = SUBC16( minx, minx->HL, minx->X ); }
+OP(2F) { minx->HL = SUBC16( minx, minx->HL, minx->Y ); }
+
+OP(30) { /* illegal instruction? */ }
+OP(31) { /* illegal instruction? */ }
+OP(32) { /* illegal instruction? */ }
+OP(33) { /* illegal instruction? */ }
+OP(34) { /* illegal instruction? */ }
+OP(35) { /* illegal instruction? */ }
+OP(36) { /* illegal instruction? */ }
+OP(37) { /* illegal instruction? */ }
+OP(38) { SUB16( minx, minx->HL, minx->BA ); }
+OP(39) { SUB16( minx, minx->HL, minx->HL ); }
+OP(3A) { SUB16( minx, minx->HL, minx->X ); }
+OP(3B) { SUB16( minx, minx->HL, minx->Y ); }
+OP(3C) { /* illegal instruction? */ }
+OP(3D) { /* illegal instruction? */ }
+OP(3E) { /* illegal instruction? */ }
+OP(3F) { /* illegal instruction? */ }
+
+OP(40) { minx->X = ADD16( minx, minx->X, minx->BA ); }
+OP(41) { minx->X = ADD16( minx, minx->X, minx->HL ); }
+OP(42) { minx->Y = ADD16( minx, minx->Y, minx->BA ); }
+OP(43) { minx->Y = ADD16( minx, minx->Y, minx->HL ); }
+OP(44) { minx->SP = ADD16( minx, minx->SP, minx->BA ); }
+OP(45) { minx->SP = ADD16( minx, minx->SP, minx->HL ); }
+OP(46) { /* illegal instruction? */ }
+OP(47) { /* illegal instruction? */ }
+OP(48) { minx->X = SUB16( minx, minx->X, minx->BA ); }
+OP(49) { minx->X = SUB16( minx, minx->X, minx->HL ); }
+OP(4A) { minx->Y = SUB16( minx, minx->Y, minx->BA ); }
+OP(4B) { minx->Y = SUB16( minx, minx->Y, minx->HL ); }
+OP(4C) { minx->SP = SUB16( minx, minx->SP, minx->BA ); }
+OP(4D) { minx->SP = SUB16( minx, minx->SP, minx->HL ); }
+OP(4E) { /* illegal instruction? */ }
+OP(4F) { /* illegal instruction? */ }
+
+OP(50) { /* illegal instruction? */ }
+OP(51) { /* illegal instruction? */ }
+OP(52) { /* illegal instruction? */ }
+OP(53) { /* illegal instruction? */ }
+OP(54) { /* illegal instruction? */ }
+OP(55) { /* illegal instruction? */ }
+OP(56) { /* illegal instruction? */ }
+OP(57) { /* illegal instruction? */ }
+OP(58) { /* illegal instruction? */ }
+OP(59) { /* illegal instruction? */ }
+OP(5A) { /* illegal instruction? */ }
+OP(5B) { /* illegal instruction? */ }
+OP(5C) { SUB16( minx, minx->SP, minx->BA ); }
+OP(5D) { SUB16( minx, minx->SP, minx->HL ); }
+OP(5E) { /* illegal instruction? */ }
+OP(5F) { /* illegal instruction? */ }
+
+OP(60) { ADDC16( minx, minx->BA, rdop16(minx) ); /* ??? */ }
+OP(61) { ADDC16( minx, minx->HL, rdop16(minx) ); /* ??? */ }
+OP(62) { ADDC16( minx, minx->X, rdop16(minx) ); /* ??? */ }
+OP(63) { ADDC16( minx, minx->Y, rdop16(minx) ); /* ??? */ }
+OP(64) { /* illegal instruction? */ }
+OP(65) { /* illegal instruction? */ }
+OP(66) { /* illegal instruction? */ }
+OP(67) { /* illegal instruction? */ }
+OP(68) { minx->SP = ADD16( minx, minx->SP, rdop16(minx) ); }
+OP(69) { /* illegal instruction? */ }
+OP(6A) { minx->SP = SUB16( minx, minx->SP, rdop16(minx) ); }
+OP(6B) { /* illegal instruction? */ }
+OP(6C) { SUB16( minx, minx->SP, rdop16(minx) ); }
+OP(6D) { /* illegal instruction? */ }
+OP(6E) { minx->SP = rdop16(minx); }
+OP(6F) { /* illegal instruction? */ }
+
+OP(70) { UINT8 ofs8 = rdop(minx); minx->BA = rd16( minx, minx->SP + ofs8 ); }
+OP(71) { UINT8 ofs8 = rdop(minx); minx->HL = rd16( minx, minx->SP + ofs8 ); }
+OP(72) { UINT8 ofs8 = rdop(minx); minx->X = rd16( minx, minx->SP + ofs8 ); }
+OP(73) { UINT8 ofs8 = rdop(minx); minx->Y = rd16( minx, minx->SP + ofs8 ); }
+OP(74) { UINT8 ofs8 = rdop(minx); wr16( minx, minx->SP + ofs8, minx->BA ); }
+OP(75) { UINT8 ofs8 = rdop(minx); wr16( minx, minx->SP + ofs8, minx->HL ); }
+OP(76) { UINT8 ofs8 = rdop(minx); wr16( minx, minx->SP + ofs8, minx->X ); }
+OP(77) { UINT8 ofs8 = rdop(minx); wr16( minx, minx->SP + ofs8, minx->Y ); }
+OP(78) { AD2_I16; minx->SP = rd16( minx, addr2 ); }
+OP(79) { /* illegal instruction? */ }
+OP(7A) { /* illegal instruction? */ }
+OP(7B) { /* illegal instruction? */ }
+OP(7C) { AD1_I16; wr16( minx, addr1, minx->SP ); }
+OP(7D) { /* illegal instruction? */ }
+OP(7E) { /* illegal instruction? */ }
+OP(7F) { /* illegal instruction? */ }
+
+OP(80) { /* illegal instruction? */ }
+OP(81) { /* illegal instruction? */ }
+OP(82) { /* illegal instruction? */ }
+OP(83) { /* illegal instruction? */ }
+OP(84) { /* illegal instruction? */ }
+OP(85) { /* illegal instruction? */ }
+OP(86) { /* illegal instruction? */ }
+OP(87) { /* illegal instruction? */ }
+OP(88) { /* illegal instruction? */ }
+OP(89) { /* illegal instruction? */ }
+OP(8A) { /* illegal instruction? */ }
+OP(8B) { /* illegal instruction? */ }
+OP(8C) { /* illegal instruction? */ }
+OP(8D) { /* illegal instruction? */ }
+OP(8E) { /* illegal instruction? */ }
+OP(8F) { /* illegal instruction? */ }
+
+OP(90) { /* illegal instruction? */ }
+OP(91) { /* illegal instruction? */ }
+OP(92) { /* illegal instruction? */ }
+OP(93) { /* illegal instruction? */ }
+OP(94) { /* illegal instruction? */ }
+OP(95) { /* illegal instruction? */ }
+OP(96) { /* illegal instruction? */ }
+OP(97) { /* illegal instruction? */ }
+OP(98) { /* illegal instruction? */ }
+OP(99) { /* illegal instruction? */ }
+OP(9A) { /* illegal instruction? */ }
+OP(9B) { /* illegal instruction? */ }
+OP(9C) { /* illegal instruction? */ }
+OP(9D) { /* illegal instruction? */ }
+OP(9E) { /* illegal instruction? */ }
+OP(9F) { /* illegal instruction? */ }
+
+OP(A0) { /* illegal instruction? */ }
+OP(A1) { /* illegal instruction? */ }
+OP(A2) { /* illegal instruction? */ }
+OP(A3) { /* illegal instruction? */ }
+OP(A4) { /* illegal instruction? */ }
+OP(A5) { /* illegal instruction? */ }
+OP(A6) { /* illegal instruction? */ }
+OP(A7) { /* illegal instruction? */ }
+OP(A8) { /* illegal instruction? */ }
+OP(A9) { /* illegal instruction? */ }
+OP(AA) { /* illegal instruction? */ }
+OP(AB) { /* illegal instruction? */ }
+OP(AC) { /* illegal instruction? */ }
+OP(AD) { /* illegal instruction? */ }
+OP(AE) { /* illegal instruction? */ }
+OP(AF) { /* illegal instruction? */ }
+
+OP(B0) { PUSH8( minx, minx->BA & 0x00FF ); }
+OP(B1) { PUSH8( minx, minx->BA >> 8 ); }
+OP(B2) { PUSH8( minx, minx->HL & 0x00FF ); }
+OP(B3) { PUSH8( minx, minx->HL >> 8 ); }
+OP(B4) { minx->BA = ( minx->BA & 0xFF00 ) | POP8(minx); }
+OP(B5) { minx->BA = ( minx->BA & 0x00FF ) | ( POP8(minx) << 8 ); }
+OP(B6) { minx->HL = ( minx->HL & 0xFF00 ) | POP8(minx); }
+OP(B7) { minx->HL = ( minx->HL & 0x00FF ) | ( POP8(minx) << 8 ); }
+OP(B8) { PUSH16( minx, minx->BA ); PUSH16( minx, minx->HL ); PUSH16( minx, minx->X ); PUSH16( minx, minx->Y ); PUSH8( minx, minx->N ); }
+OP(B9) { PUSH16( minx, minx->BA ); PUSH16( minx, minx->HL ); PUSH16( minx, minx->X ); PUSH16( minx, minx->Y ); PUSH8( minx, minx->N ); PUSH8( minx, minx->I ); PUSH8( minx, minx->XI ); PUSH8( minx, minx->YI ); }
+OP(BA) { /* illegal instruction? */ }
+OP(BB) { /* illegal instruction? */ }
+OP(BC) { minx->N = POP8(minx); minx->Y = POP16(minx); minx->X = POP16(minx); minx->HL = POP16(minx); minx->BA = POP16(minx); }
+OP(BD) { minx->YI = POP8(minx); minx->XI = POP8(minx); minx->I = POP8(minx); minx->N = POP8(minx); minx->Y = POP16(minx); minx->X = POP16(minx); minx->HL = POP16(minx); minx->BA = POP16(minx); }
+OP(BE) { /* illegal instruction? */ }
+OP(BF) { /* illegal instruction? */ }
+
+OP(C0) { AD2_IHL; minx->BA = rd16( minx, addr2 ); }
+OP(C1) { AD2_IHL; minx->HL = rd16( minx, addr2 ); }
+OP(C2) { AD2_IHL; minx->X = rd16( minx, addr2 ); }
+OP(C3) { AD2_IHL; minx->Y = rd16( minx, addr2 ); }
+OP(C4) { AD1_IHL; wr16( minx, addr1, minx->BA ); }
+OP(C5) { AD1_IHL; wr16( minx, addr1, minx->HL ); }
+OP(C6) { AD1_IHL; wr16( minx, addr1, minx->X ); }
+OP(C7) { AD1_IHL; wr16( minx, addr1, minx->Y ); }
+OP(C8) { /* illegal instruction? */ }
+OP(C9) { /* illegal instruction? */ }
+OP(CA) { /* illegal instruction? */ }
+OP(CB) { /* illegal instruction? */ }
+OP(CC) { /* illegal instruction? */ }
+OP(CD) { /* illegal instruction? */ }
+OP(CE) { /* illegal instruction? */ }
+OP(CF) { /* illegal instruction? */ }
+
+OP(D0) { AD2_XIX; minx->BA = rd16( minx, addr2 ); }
+OP(D1) { AD2_XIX; minx->HL = rd16( minx, addr2 ); }
+OP(D2) { AD2_XIX; minx->X = rd16( minx, addr2 ); }
+OP(D3) { AD2_XIX; minx->Y = rd16( minx, addr2 ); }
+OP(D4) { AD1_XIX; wr16( minx, addr1, minx->BA ); }
+OP(D5) { AD1_XIX; wr16( minx, addr1, minx->HL ); }
+OP(D6) { AD1_XIX; wr16( minx, addr1, minx->X ); }
+OP(D7) { AD1_XIX; wr16( minx, addr1, minx->Y ); }
+OP(D8) { AD2_YIY; minx->BA = rd16( minx, addr2 ); }
+OP(D9) { AD2_YIY; minx->HL = rd16( minx, addr2 ); }
+OP(DA) { AD2_YIY; minx->X = rd16( minx, addr2 ); }
+OP(DB) { AD2_YIY; minx->Y = rd16( minx, addr2 ); }
+OP(DC) { AD1_YIY; wr16( minx, addr1, minx->BA ); }
+OP(DD) { AD1_YIY; wr16( minx, addr1, minx->HL ); }
+OP(DE) { AD1_YIY; wr16( minx, addr1, minx->X ); }
+OP(DF) { AD1_YIY; wr16( minx, addr1, minx->Y ); }
+
+OP(E0) { minx->BA = minx->BA; }
+OP(E1) { minx->BA = minx->HL; }
+OP(E2) { minx->BA = minx->X; }
+OP(E3) { minx->BA = minx->Y; }
+OP(E4) { minx->HL = minx->BA; }
+OP(E5) { minx->HL = minx->HL; }
+OP(E6) { minx->HL = minx->X; }
+OP(E7) { minx->HL = minx->Y; }
+OP(E8) { minx->X = minx->BA; }
+OP(E9) { minx->X = minx->HL; }
+OP(EA) { minx->X = minx->X; }
+OP(EB) { minx->X = minx->Y; }
+OP(EC) { minx->Y = minx->BA; }
+OP(ED) { minx->Y = minx->HL; }
+OP(EE) { minx->Y = minx->X; }
+OP(EF) { minx->Y = minx->Y; }
+
+OP(F0) { minx->SP = minx->BA; }
+OP(F1) { minx->SP = minx->HL; }
+OP(F2) { minx->SP = minx->X; }
+OP(F3) { minx->SP = minx->Y; }
+OP(F4) { minx->HL = minx->SP; }
+OP(F5) { minx->HL = minx->PC; }
+OP(F6) { /* illegal instruction? */ }
+OP(F7) { /* illegal instruction? */ }
+OP(F8) { minx->BA = minx->SP; }
+OP(F9) { minx->BA = minx->PC; }
+OP(FA) { minx->X = minx->SP; }
+OP(FB) { /* illegal instruction? */ }
+OP(FC) { /* illegal instruction? */ }
+OP(FD) { /* illegal instruction? */ }
+OP(FE) { minx->Y = minx->SP; }
+OP(FF) { /* illegal instruction? */ }
+
+static void (*const insnminx_CF[256])(minx_state *minx) = {
+ minx_CF_00, minx_CF_01, minx_CF_02, minx_CF_03, minx_CF_04, minx_CF_05, minx_CF_06, minx_CF_07,
+ minx_CF_08, minx_CF_09, minx_CF_0A, minx_CF_0B, minx_CF_0C, minx_CF_0D, minx_CF_0E, minx_CF_0F,
+ minx_CF_10, minx_CF_11, minx_CF_12, minx_CF_13, minx_CF_14, minx_CF_15, minx_CF_16, minx_CF_17,
+ minx_CF_18, minx_CF_19, minx_CF_1A, minx_CF_1B, minx_CF_1C, minx_CF_1D, minx_CF_1E, minx_CF_1F,
+ minx_CF_20, minx_CF_21, minx_CF_22, minx_CF_23, minx_CF_24, minx_CF_25, minx_CF_26, minx_CF_27,
+ minx_CF_28, minx_CF_29, minx_CF_2A, minx_CF_2B, minx_CF_2C, minx_CF_2D, minx_CF_2E, minx_CF_2F,
+ minx_CF_30, minx_CF_31, minx_CF_32, minx_CF_33, minx_CF_34, minx_CF_35, minx_CF_36, minx_CF_37,
+ minx_CF_38, minx_CF_39, minx_CF_3A, minx_CF_3B, minx_CF_3C, minx_CF_3D, minx_CF_3E, minx_CF_3F,
+ minx_CF_40, minx_CF_41, minx_CF_42, minx_CF_43, minx_CF_44, minx_CF_45, minx_CF_46, minx_CF_47,
+ minx_CF_48, minx_CF_49, minx_CF_4A, minx_CF_4B, minx_CF_4C, minx_CF_4D, minx_CF_4E, minx_CF_4F,
+ minx_CF_50, minx_CF_51, minx_CF_52, minx_CF_53, minx_CF_54, minx_CF_55, minx_CF_56, minx_CF_57,
+ minx_CF_58, minx_CF_59, minx_CF_5A, minx_CF_5B, minx_CF_5C, minx_CF_5D, minx_CF_5E, minx_CF_5F,
+ minx_CF_60, minx_CF_61, minx_CF_62, minx_CF_63, minx_CF_64, minx_CF_65, minx_CF_66, minx_CF_67,
+ minx_CF_68, minx_CF_69, minx_CF_6A, minx_CF_6B, minx_CF_6C, minx_CF_6D, minx_CF_6E, minx_CF_6F,
+ minx_CF_70, minx_CF_71, minx_CF_72, minx_CF_73, minx_CF_74, minx_CF_75, minx_CF_76, minx_CF_77,
+ minx_CF_78, minx_CF_79, minx_CF_7A, minx_CF_7B, minx_CF_7C, minx_CF_7D, minx_CF_7E, minx_CF_7F,
+ minx_CF_80, minx_CF_81, minx_CF_82, minx_CF_83, minx_CF_84, minx_CF_85, minx_CF_86, minx_CF_87,
+ minx_CF_88, minx_CF_89, minx_CF_8A, minx_CF_8B, minx_CF_8C, minx_CF_8D, minx_CF_8E, minx_CF_8F,
+ minx_CF_90, minx_CF_91, minx_CF_92, minx_CF_93, minx_CF_94, minx_CF_95, minx_CF_96, minx_CF_97,
+ minx_CF_98, minx_CF_99, minx_CF_9A, minx_CF_9B, minx_CF_9C, minx_CF_9D, minx_CF_9E, minx_CF_9F,
+ minx_CF_A0, minx_CF_A1, minx_CF_A2, minx_CF_A3, minx_CF_A4, minx_CF_A5, minx_CF_A6, minx_CF_A7,
+ minx_CF_A8, minx_CF_A9, minx_CF_AA, minx_CF_AB, minx_CF_AC, minx_CF_AD, minx_CF_AE, minx_CF_AF,
+ minx_CF_B0, minx_CF_B1, minx_CF_B2, minx_CF_B3, minx_CF_B4, minx_CF_B5, minx_CF_B6, minx_CF_B7,
+ minx_CF_B8, minx_CF_B9, minx_CF_BA, minx_CF_BB, minx_CF_BC, minx_CF_BD, minx_CF_BE, minx_CF_BF,
+ minx_CF_C0, minx_CF_C1, minx_CF_C2, minx_CF_C3, minx_CF_C4, minx_CF_C5, minx_CF_C6, minx_CF_C7,
+ minx_CF_C8, minx_CF_C9, minx_CF_CA, minx_CF_CB, minx_CF_CC, minx_CF_CD, minx_CF_CE, minx_CF_CF,
+ minx_CF_D0, minx_CF_D1, minx_CF_D2, minx_CF_D3, minx_CF_D4, minx_CF_D5, minx_CF_D6, minx_CF_D7,
+ minx_CF_D8, minx_CF_D9, minx_CF_DA, minx_CF_DB, minx_CF_DC, minx_CF_DD, minx_CF_DE, minx_CF_DF,
+ minx_CF_E0, minx_CF_E1, minx_CF_E2, minx_CF_E3, minx_CF_E4, minx_CF_E5, minx_CF_E6, minx_CF_E7,
+ minx_CF_E8, minx_CF_E9, minx_CF_EA, minx_CF_EB, minx_CF_EC, minx_CF_ED, minx_CF_EE, minx_CF_EF,
+ minx_CF_F0, minx_CF_F1, minx_CF_F2, minx_CF_F3, minx_CF_F4, minx_CF_F5, minx_CF_F6, minx_CF_F7,
+ minx_CF_F8, minx_CF_F9, minx_CF_FA, minx_CF_FB, minx_CF_FC, minx_CF_FD, minx_CF_FE, minx_CF_FF
+};
+
+static const int insnminx_cycles_CF[256] = {
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 1, 1, 1, 1,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 16, 16, 1, 1, 1, 1,
+
+ 16, 16, 16, 16, 16, 16, 1, 1, 16, 16, 16, 16, 16, 16, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 16, 1, 1,
+ 16, 16, 16, 16, 1, 1, 1, 1, 16, 1, 16, 1, 16, 1, 16, 1,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 1, 1, 1, 24, 1, 1, 1,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 12, 12, 12, 12, 12, 12, 12, 12, 48, 60, 1, 1, 32, 40, 1, 1,
+
+ 20, 20, 20, 20, 20, 20, 20, 20, 1, 1, 1, 1, 1, 1, 1, 1,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 1, 1, 8, 8, 8, 1, 1, 1, 8, 1
+};
diff --git a/trunk/src/emu/cpu/minx/minxops.h b/trunk/src/emu/cpu/minx/minxops.h
new file mode 100644
index 00000000000..fce4bb70652
--- /dev/null
+++ b/trunk/src/emu/cpu/minx/minxops.h
@@ -0,0 +1,331 @@
+#undef OP
+#define OP(nn) INLINE void minx_##nn(minx_state *minx)
+
+OP(00) { minx->BA = ( minx->BA & 0xFF00 ) | ADD8( minx, ( minx->BA & 0x00FF ), ( minx->BA & 0xFF ) ); }
+OP(01) { minx->BA = ( minx->BA & 0xFF00 ) | ADD8( minx, ( minx->BA & 0x00FF ), ( minx->BA >> 8 ) ); }
+OP(02) { minx->BA = ( minx->BA & 0xFF00 ) | ADD8( minx, ( minx->BA & 0x00FF ), rdop(minx) ); }
+OP(03) { AD2_IHL; minx->BA = ( minx->BA & 0xFF00 ) | ADD8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(04) { AD2_IN8; minx->BA = ( minx->BA & 0xFF00 ) | ADD8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(05) { AD2_I16; minx->BA = ( minx->BA & 0xFF00 ) | ADD8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(06) { AD2_XIX; minx->BA = ( minx->BA & 0xFF00 ) | ADD8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(07) { AD2_YIY; minx->BA = ( minx->BA & 0xFF00 ) | ADD8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(08) { minx->BA = ( minx->BA & 0xFF00 ) | ADDC8( minx, ( minx->BA & 0x00FF ), ( minx->BA & 0xFF ) ); }
+OP(09) { minx->BA = ( minx->BA & 0xFF00 ) | ADDC8( minx, ( minx->BA & 0x00FF ), ( minx->BA >> 8 ) ); }
+OP(0A) { minx->BA = ( minx->BA & 0xFF00 ) | ADDC8( minx, ( minx->BA & 0x00FF ), rdop(minx) ); }
+OP(0B) { AD2_IHL; minx->BA = ( minx->BA & 0xFF00 ) | ADDC8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(0C) { AD2_IN8; minx->BA = ( minx->BA & 0xFF00 ) | ADDC8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(0D) { AD2_I16; minx->BA = ( minx->BA & 0xFF00 ) | ADDC8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(0E) { AD2_XIX; minx->BA = ( minx->BA & 0xFF00 ) | ADDC8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(0F) { AD2_YIY; minx->BA = ( minx->BA & 0xFF00 ) | ADDC8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+
+OP(10) { minx->BA = ( minx->BA & 0xFF00 ) | SUB8( minx, ( minx->BA & 0x00FF ), ( minx->BA & 0xFF ) ); }
+OP(11) { minx->BA = ( minx->BA & 0xFF00 ) | SUB8( minx, ( minx->BA & 0x00FF ), ( minx->BA >> 8 ) ); }
+OP(12) { minx->BA = ( minx->BA & 0xFF00 ) | SUB8( minx, ( minx->BA & 0x00FF ), rdop(minx) ); }
+OP(13) { AD2_IHL; minx->BA = ( minx->BA & 0xFF00 ) | SUB8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(14) { AD2_IN8; minx->BA = ( minx->BA & 0xFF00 ) | SUB8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(15) { AD2_I16; minx->BA = ( minx->BA & 0xFF00 ) | SUB8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(16) { AD2_XIX; minx->BA = ( minx->BA & 0xFF00 ) | SUB8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(17) { AD2_YIY; minx->BA = ( minx->BA & 0xFF00 ) | SUB8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(18) { minx->BA = ( minx->BA & 0xFF00 ) | SUBC8( minx, ( minx->BA & 0x00FF ), ( minx->BA & 0xFF ) ); }
+OP(19) { minx->BA = ( minx->BA & 0xFF00 ) | SUBC8( minx, ( minx->BA & 0x00FF ), ( minx->BA >> 8 ) ); }
+OP(1A) { minx->BA = ( minx->BA & 0xFF00 ) | SUBC8( minx, ( minx->BA & 0x00FF ), rdop(minx) ); }
+OP(1B) { AD2_IHL; minx->BA = ( minx->BA & 0xFF00 ) | SUBC8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(1C) { AD2_IN8; minx->BA = ( minx->BA & 0xFF00 ) | SUBC8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(1D) { AD2_I16; minx->BA = ( minx->BA & 0xFF00 ) | SUBC8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(1E) { AD2_XIX; minx->BA = ( minx->BA & 0xFF00 ) | SUBC8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(1F) { AD2_YIY; minx->BA = ( minx->BA & 0xFF00 ) | SUBC8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+
+OP(20) { minx->BA = ( minx->BA & 0xFF00 ) | AND8( minx, ( minx->BA & 0x00FF ), ( minx->BA & 0xFF ) ); }
+OP(21) { minx->BA = ( minx->BA & 0xFF00 ) | AND8( minx, ( minx->BA & 0x00FF ), ( minx->BA >> 8 ) ); }
+OP(22) { minx->BA = ( minx->BA & 0xFF00 ) | AND8( minx, ( minx->BA & 0x00FF ), rdop(minx) ); }
+OP(23) { AD2_IHL; minx->BA = ( minx->BA & 0xFF00 ) | AND8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(24) { AD2_IN8; minx->BA = ( minx->BA & 0xFF00 ) | AND8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(25) { AD2_I16; minx->BA = ( minx->BA & 0xFF00 ) | AND8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(26) { AD2_XIX; minx->BA = ( minx->BA & 0xFF00 ) | AND8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(27) { AD2_YIY; minx->BA = ( minx->BA & 0xFF00 ) | AND8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(28) { minx->BA = ( minx->BA & 0xFF00 ) | OR8( minx, ( minx->BA & 0x00FF ), ( minx->BA & 0xFF ) ); }
+OP(29) { minx->BA = ( minx->BA & 0xFF00 ) | OR8( minx, ( minx->BA & 0x00FF ), ( minx->BA >> 8 ) ); }
+OP(2A) { minx->BA = ( minx->BA & 0xFF00 ) | OR8( minx, ( minx->BA & 0x00FF ), rdop(minx) ); }
+OP(2B) { AD2_IHL; minx->BA = ( minx->BA & 0xFF00 ) | OR8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(2C) { AD2_IN8; minx->BA = ( minx->BA & 0xFF00 ) | OR8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(2D) { AD2_I16; minx->BA = ( minx->BA & 0xFF00 ) | OR8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(2E) { AD2_XIX; minx->BA = ( minx->BA & 0xFF00 ) | OR8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(2F) { AD2_YIY; minx->BA = ( minx->BA & 0xFF00 ) | OR8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+
+OP(30) { SUB8( minx, ( minx->BA & 0x00FF ), ( minx->BA & 0xFF ) ); }
+OP(31) { SUB8( minx, ( minx->BA & 0x00FF ), ( minx->BA >> 8 ) ); }
+OP(32) { SUB8( minx, ( minx->BA & 0x00FF ), rdop(minx) ); }
+OP(33) { AD2_IHL; SUB8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(34) { AD2_IN8; SUB8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(35) { AD2_I16; SUB8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(36) { AD2_XIX; SUB8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(37) { AD2_YIY; SUB8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(38) { minx->BA = ( minx->BA & 0xFF00 ) | XOR8( minx, ( minx->BA & 0x00FF ), ( minx->BA & 0xFF ) ); }
+OP(39) { minx->BA = ( minx->BA & 0xFF00 ) | XOR8( minx, ( minx->BA & 0x00FF ), ( minx->BA >> 8 ) ); }
+OP(3A) { minx->BA = ( minx->BA & 0xFF00 ) | XOR8( minx, ( minx->BA & 0x00FF ), rdop(minx) ); }
+OP(3B) { AD2_IHL; minx->BA = ( minx->BA & 0xFF00 ) | XOR8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(3C) { AD2_IN8; minx->BA = ( minx->BA & 0xFF00 ) | XOR8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(3D) { AD2_I16; minx->BA = ( minx->BA & 0xFF00 ) | XOR8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(3E) { AD2_XIX; minx->BA = ( minx->BA & 0xFF00 ) | XOR8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+OP(3F) { AD2_YIY; minx->BA = ( minx->BA & 0xFF00 ) | XOR8( minx, ( minx->BA & 0x00FF ), RD( addr2 ) ); }
+
+OP(40) { minx->BA = ( minx->BA & 0xFF00 ) | ( minx->BA & 0x00FF); }
+OP(41) { minx->BA = ( minx->BA & 0xFF00 ) | ( minx->BA >> 8 ); }
+OP(42) { minx->BA = ( minx->BA & 0xFF00 ) | ( minx->HL & 0x00FF); }
+OP(43) { minx->BA = ( minx->BA & 0xFF00 ) | ( minx->HL >> 8 ); }
+OP(44) { AD2_IN8; minx->BA = ( minx->BA & 0xFF00 ) | RD( addr2 ); }
+OP(45) { AD2_IHL; minx->BA = ( minx->BA & 0xFF00 ) | RD( addr2 ); }
+OP(46) { AD2_XIX; minx->BA = ( minx->BA & 0xFF00 ) | RD( addr2 ); }
+OP(47) { AD2_YIY; minx->BA = ( minx->BA & 0xFF00 ) | RD( addr2 ); }
+OP(48) { minx->BA = ( minx->BA & 0x00FF ) | ( ( minx->BA & 0x00FF) << 8 ); }
+OP(49) { minx->BA = ( minx->BA & 0x00FF ) | ( ( minx->BA >> 8 ) << 8 ); }
+OP(4A) { minx->BA = ( minx->BA & 0x00FF ) | ( ( minx->HL & 0x00FF) << 8 ); }
+OP(4B) { minx->BA = ( minx->BA & 0x00FF ) | ( ( minx->HL >> 8 ) << 8 ); }
+OP(4C) { AD2_IN8; minx->BA = ( minx->BA & 0x00FF ) | ( RD( addr2 ) << 8 ); }
+OP(4D) { AD2_IHL; minx->BA = ( minx->BA & 0x00FF ) | ( RD( addr2 ) << 8 ); }
+OP(4E) { AD2_XIX; minx->BA = ( minx->BA & 0x00FF ) | ( RD( addr2 ) << 8 ); }
+OP(4F) { AD2_YIY; minx->BA = ( minx->BA & 0x00FF ) | ( RD( addr2 ) << 8 ); }
+
+OP(50) { minx->HL = ( minx->HL & 0xFF00 ) | ( minx->BA & 0x00FF); }
+OP(51) { minx->HL = ( minx->HL & 0xFF00 ) | ( minx->BA >> 8 ); }
+OP(52) { minx->HL = ( minx->HL & 0xFF00 ) | ( minx->HL & 0x00FF); }
+OP(53) { minx->HL = ( minx->HL & 0xFF00 ) | ( minx->HL >> 8 ); }
+OP(54) { AD2_IN8; minx->HL = ( minx->HL & 0xFF00 ) | RD( addr2 ); }
+OP(55) { AD2_IHL; minx->HL = ( minx->HL & 0xFF00 ) | RD( addr2 ); }
+OP(56) { AD2_XIX; minx->HL = ( minx->HL & 0xFF00 ) | RD( addr2 ); }
+OP(57) { AD2_YIY; minx->HL = ( minx->HL & 0xFF00 ) | RD( addr2 ); }
+OP(58) { minx->HL = ( minx->HL & 0x00FF ) | ( ( minx->BA & 0x00FF) << 8 ); }
+OP(59) { minx->HL = ( minx->HL & 0x00FF ) | ( ( minx->BA >> 8 ) << 8 ); }
+OP(5A) { minx->HL = ( minx->HL & 0x00FF ) | ( ( minx->HL & 0x00FF) << 8 ); }
+OP(5B) { minx->HL = ( minx->HL & 0x00FF ) | ( ( minx->HL >> 8 ) << 8 ); }
+OP(5C) { AD2_IN8; minx->HL = ( minx->HL & 0x00FF ) | ( RD( addr2 ) << 8 ); }
+OP(5D) { AD2_IHL; minx->HL = ( minx->HL & 0x00FF ) | ( RD( addr2 ) << 8 ); }
+OP(5E) { AD2_XIX; minx->HL = ( minx->HL & 0x00FF ) | ( RD( addr2 ) << 8 ); }
+OP(5F) { AD2_YIY; minx->HL = ( minx->HL & 0x00FF ) | ( RD( addr2 ) << 8 ); }
+
+OP(60) { AD1_XIX; WR( addr1, ( minx->BA & 0x00FF ) ); }
+OP(61) { AD1_XIX; WR( addr1, ( minx->BA >> 8 ) ); }
+OP(62) { AD1_XIX; WR( addr1, ( minx->HL & 0x00FF ) ); }
+OP(63) { AD1_XIX; WR( addr1, ( minx->HL >> 8 ) ); }
+OP(64) { AD1_XIX; AD2_IN8; WR( addr1, RD( addr2 ) ); }
+OP(65) { AD1_XIX; AD2_IHL; WR( addr1, RD( addr2 ) ); }
+OP(66) { AD1_XIX; AD2_XIX; WR( addr1, RD( addr2 ) ); }
+OP(67) { AD1_XIX; AD2_YIY; WR( addr1, RD( addr2 ) ); }
+OP(68) { AD1_IHL; WR( addr1, ( minx->BA & 0x00FF ) ); }
+OP(69) { AD1_IHL; WR( addr1, ( minx->BA >> 8 ) ); }
+OP(6A) { AD1_IHL; WR( addr1, ( minx->HL & 0x00FF ) ); }
+OP(6B) { AD1_IHL; WR( addr1, ( minx->HL >> 8 ) ); }
+OP(6C) { AD1_IHL; AD2_IN8; WR( addr1, RD( addr2 ) ); }
+OP(6D) { AD1_IHL; AD2_IHL; WR( addr1, RD( addr2 ) ); }
+OP(6E) { AD1_IHL; AD2_XIX; WR( addr1, RD( addr2 ) ); }
+OP(6F) { AD1_IHL; AD2_YIY; WR( addr1, RD( addr2 ) ); }
+
+OP(70) { AD1_YIY; WR( addr1, ( minx->BA & 0x00FF ) ); }
+OP(71) { AD1_YIY; WR( addr1, ( minx->BA >> 8 ) ); }
+OP(72) { AD1_YIY; WR( addr1, ( minx->HL & 0x00FF ) ); }
+OP(73) { AD1_YIY; WR( addr1, ( minx->HL >> 8 ) ); }
+OP(74) { AD1_YIY; AD2_IN8; WR( addr1, RD( addr2 ) ); }
+OP(75) { AD1_YIY; AD2_IHL; WR( addr1, RD( addr2 ) ); }
+OP(76) { AD1_YIY; AD2_XIX; WR( addr1, RD( addr2 ) ); }
+OP(77) { AD1_YIY; AD2_YIY; WR( addr1, RD( addr2 ) ); }
+OP(78) { AD1_IN8; WR( addr1, ( minx->BA & 0x00FF ) ); }
+OP(79) { AD1_IN8; WR( addr1, ( minx->BA >> 8 ) ); }
+OP(7A) { AD1_IN8; WR( addr1, ( minx->HL & 0x00FF ) ); }
+OP(7B) { AD1_IN8; WR( addr1, ( minx->HL >> 8 ) ); }
+OP(7C) { /* illegal operation? */ }
+OP(7D) { AD1_IN8; AD2_IHL; WR( addr1, RD( addr2 ) ); }
+OP(7E) { AD1_IN8; AD2_XIX; WR( addr1, RD( addr2 ) ); }
+OP(7F) { AD1_IN8; AD2_YIY; WR( addr1, RD( addr2 ) ); }
+
+OP(80) { minx->BA = ( minx->BA & 0xFF00 ) | INC8( minx, minx->BA & 0x00FF ); }
+OP(81) { minx->BA = ( minx->BA & 0x00FF ) | ( INC8( minx, minx->BA >> 8 ) << 8 ); }
+OP(82) { minx->HL = ( minx->HL & 0xFF00 ) | INC8( minx, minx->HL & 0x00FF ); }
+OP(83) { minx->HL = ( minx->HL & 0x00FF ) | ( INC8( minx, minx->HL >> 8 ) << 8 ); }
+OP(84) { minx->N = INC8( minx, minx->N ); }
+OP(85) { AD1_IN8; WR( addr1, INC8( minx, RD( addr1 ) ) ); }
+OP(86) { AD1_IHL; WR( addr1, INC8( minx, RD( addr1 ) ) ); }
+OP(87) { minx->SP = INC16( minx, minx->SP ); }
+OP(88) { minx->BA = ( minx->BA & 0xFF00 ) | DEC8( minx, minx->BA & 0x00FF ); }
+OP(89) { minx->BA = ( minx->BA & 0x00FF ) | ( DEC8( minx, minx->BA >> 8 ) << 8 ); }
+OP(8A) { minx->HL = ( minx->HL & 0xFF00 ) | DEC8( minx, minx->HL & 0x00FF ); }
+OP(8B) { minx->HL = ( minx->HL & 0x00FF ) | ( DEC8( minx, minx->HL >> 8 ) << 8 ); }
+OP(8C) { minx->N = DEC8( minx, minx->N ); }
+OP(8D) { AD1_IN8; WR( addr1, DEC8( minx, RD( addr1 ) ) ); }
+OP(8E) { AD1_IHL; WR( addr1, DEC8( minx, RD( addr1 ) ) ); }
+OP(8F) { minx->SP = DEC8( minx, minx->SP ); }
+
+OP(90) { minx->BA = INC16( minx, minx->BA ); }
+OP(91) { minx->HL = INC16( minx, minx->HL ); }
+OP(92) { minx->X = INC16( minx, minx->X ); }
+OP(93) { minx->Y = INC16( minx, minx->Y ); }
+OP(94) { minx->F = ( AND8( minx, ( minx->BA & 0x00FF ), ( minx->BA >> 8 ) ) ) ? minx->F & ~FLAG_Z : minx->F | FLAG_Z;}
+OP(95) { AD1_IHL; minx->F = ( AND8( minx, RD( addr1 ), rdop(minx) ) ) ? minx->F & ~FLAG_Z : minx->F | FLAG_Z; }
+OP(96) { minx->F = ( AND8( minx, ( minx->BA & 0x00FF ), rdop(minx) ) ) ? minx->F & ~FLAG_Z : minx->F | FLAG_Z; }
+OP(97) { minx->F = ( AND8( minx, ( minx->BA >> 8 ), rdop(minx) ) ) ? minx->F & ~FLAG_Z : minx->F | FLAG_Z; }
+OP(98) { minx->BA = DEC16( minx, minx->BA ); }
+OP(99) { minx->HL = DEC16( minx, minx->HL ); }
+OP(9A) { minx->X = DEC16( minx, minx->X ); }
+OP(9B) { minx->Y = DEC16( minx, minx->Y ); }
+OP(9C) { minx->F = minx->F & rdop(minx); }
+OP(9D) { minx->F = minx->F | rdop(minx); }
+OP(9E) { minx->F = minx->F ^ rdop(minx); }
+OP(9F) { minx->F = rdop(minx); }
+
+OP(A0) { PUSH16( minx, minx->BA ); }
+OP(A1) { PUSH16( minx, minx->HL ); }
+OP(A2) { PUSH16( minx, minx->X ); }
+OP(A3) { PUSH16( minx, minx->Y ); }
+OP(A4) { PUSH8( minx, minx->N ); }
+OP(A5) { PUSH8( minx, minx->I ); }
+OP(A6) { PUSH8( minx, minx->XI ); PUSH8( minx, minx->YI ); }
+OP(A7) { PUSH8( minx, minx->F ); }
+OP(A8) { minx->BA = POP16(minx); }
+OP(A9) { minx->HL = POP16(minx);}
+OP(AA) { minx->X = POP16(minx); }
+OP(AB) { minx->Y = POP16(minx); }
+OP(AC) { minx->N = POP8(minx); }
+OP(AD) { minx->I = POP8(minx); }
+OP(AE) { minx->YI = POP8(minx); minx->XI = POP8(minx); }
+OP(AF) { minx->F = POP8(minx); }
+
+OP(B0) { UINT8 op = rdop(minx); minx->BA = ( minx->BA & 0xFF00 ) | op; }
+OP(B1) { UINT8 op = rdop(minx); minx->BA = ( minx->BA & 0x00FF ) | ( op << 8 ); }
+OP(B2) { UINT8 op = rdop(minx); minx->HL = ( minx->HL & 0xFF00 ) | op; }
+OP(B3) { UINT8 op = rdop(minx); minx->HL = ( minx->HL & 0x00FF ) | ( op << 8 ); }
+OP(B4) { UINT8 op = rdop(minx); minx->N = op; }
+OP(B5) { AD1_IHL; UINT8 op = rdop(minx); WR( addr1, op); }
+OP(B6) { AD1_XIX; UINT8 op = rdop(minx); WR( addr1, op ); }
+OP(B7) { AD1_YIY; UINT8 op = rdop(minx); WR( addr1, op ); }
+OP(B8) { AD2_I16; minx->BA = rd16( minx, addr2 ); }
+OP(B9) { AD2_I16; minx->HL = rd16( minx, addr2 ); }
+OP(BA) { AD2_I16; minx->X = rd16( minx, addr2 ); }
+OP(BB) { AD2_I16; minx->Y = rd16( minx, addr2 ); }
+OP(BC) { AD1_I16; wr16( minx, addr1, minx->BA ); }
+OP(BD) { AD1_I16; wr16( minx, addr1, minx->HL ); }
+OP(BE) { AD1_I16; wr16( minx, addr1, minx->X ); }
+OP(BF) { AD1_I16; wr16( minx, addr1, minx->Y ); }
+
+OP(C0) { minx->BA = ADD16( minx, minx->BA, rdop16(minx) ); }
+OP(C1) { minx->HL = ADD16( minx, minx->HL, rdop16(minx) ); }
+OP(C2) { minx->X = ADD16( minx, minx->X, rdop16(minx) ); }
+OP(C3) { minx->Y = ADD16( minx, minx->Y, rdop16(minx) ); }
+OP(C4) { minx->BA = rdop16(minx); }
+OP(C5) { minx->HL = rdop16(minx); }
+OP(C6) { minx->X = rdop16(minx); }
+OP(C7) { minx->Y = rdop16(minx); }
+OP(C8) { UINT16 t = minx->BA; minx->BA = minx->HL; minx->HL = t; }
+OP(C9) { UINT16 t = minx->BA; minx->BA = minx->X; minx->X = t; }
+OP(CA) { UINT16 t = minx->BA; minx->BA = minx->Y; minx->Y = t; }
+OP(CB) { UINT16 t = minx->BA; minx->BA = minx->SP; minx->SP = t; }
+OP(CC) { minx->BA = ( minx->BA >> 8 ) | ( ( minx->BA & 0x00FF ) << 8 ); }
+OP(CD) { UINT8 t; AD2_IHL; t = RD( addr2 ); WR( addr2, ( minx->BA & 0x00FF ) ); minx->BA = ( minx->BA & 0xFF00 ) | t; }
+OP(CE) { UINT8 op = rdop(minx); insnminx_CE[op](minx); minx->icount -= insnminx_cycles_CE[op]; }
+OP(CF) { UINT8 op = rdop(minx); insnminx_CF[op](minx); minx->icount -= insnminx_cycles_CF[op]; }
+
+OP(D0) { minx->BA = SUB16( minx, minx->BA, rdop16(minx) ); }
+OP(D1) { minx->HL = SUB16( minx, minx->HL, rdop16(minx) ); }
+OP(D2) { minx->X = SUB16( minx, minx->X, rdop16(minx) ); }
+OP(D3) { minx->Y = SUB16( minx, minx->Y, rdop16(minx) ); }
+OP(D4) { SUB16( minx, minx->BA, rdop16(minx) ); }
+OP(D5) { SUB16( minx, minx->HL, rdop16(minx) ); }
+OP(D6) { SUB16( minx, minx->X, rdop16(minx) ); }
+OP(D7) { SUB16( minx, minx->Y, rdop16(minx) ); }
+OP(D8) { AD1_IN8; WR( addr1, AND8( minx, RD( addr1 ), rdop(minx) ) ); }
+OP(D9) { AD1_IN8; WR( addr1, OR8( minx, RD( addr1 ), rdop(minx) ) ); }
+OP(DA) { AD1_IN8; WR( addr1, XOR8( minx, RD( addr1 ), rdop(minx) ) ); }
+OP(DB) { AD1_IN8; SUB8( minx, RD( addr1 ), rdop(minx) ); }
+OP(DC) { AD1_IN8; minx->F = ( AND8( minx, RD( addr1 ), rdop(minx) ) ) ? minx->F & ~FLAG_Z : minx->F | FLAG_Z; }
+OP(DD) { AD1_IN8; WR( addr1, rdop(minx) ); }
+OP(DE) { minx->BA = ( minx->BA & 0xFF00 ) | ( ( minx->BA & 0x000F ) | ( ( minx->BA & 0x0F00 ) >> 4 ) ); }
+OP(DF) { minx->BA = ( ( minx->BA & 0x0080 ) ? 0xFF00 : 0x0000 ) | ( minx->BA & 0x000F ); }
+
+OP(E0) { INT8 d8 = rdop(minx); if ( minx->F & FLAG_C ) { CALL( minx, minx->PC + d8 - 1 ); minx->icount -= 12; } }
+OP(E1) { INT8 d8 = rdop(minx); if ( ! ( minx->F & FLAG_C ) ) { CALL( minx, minx->PC + d8- 1 ); minx->icount -= 12; } }
+OP(E2) { INT8 d8 = rdop(minx); if ( minx->F & FLAG_Z ) { CALL( minx, minx->PC + d8 - 1 ); minx->icount -= 12; } }
+OP(E3) { INT8 d8 = rdop(minx); if ( ! ( minx->F & FLAG_Z ) ) { CALL( minx, minx->PC + d8 - 1 ); minx->icount -= 12; } }
+OP(E4) { INT8 d8 = rdop(minx); if ( minx->F & FLAG_C ) { JMP( minx, minx->PC + d8 - 1 ); } }
+OP(E5) { INT8 d8 = rdop(minx); if ( ! ( minx->F & FLAG_C ) ) { JMP( minx, minx->PC + d8 - 1 ); } }
+OP(E6) { INT8 d8 = rdop(minx); if ( minx->F & FLAG_Z ) { JMP( minx, minx->PC + d8 - 1 ); } }
+OP(E7) { INT8 d8 = rdop(minx); if ( ! ( minx->F & FLAG_Z ) ) { JMP( minx, minx->PC + d8 - 1 ); } }
+OP(E8) { UINT16 d16 = rdop16(minx); if ( minx->F & FLAG_C ) { CALL( minx, minx->PC + d16 - 1 ); minx->icount -= 12; } }
+OP(E9) { UINT16 d16 = rdop16(minx); if ( ! ( minx->F & FLAG_C ) ) { CALL( minx, minx->PC + d16 - 1 ); minx->icount -= 12; } }
+OP(EA) { UINT16 d16 = rdop16(minx); if ( minx->F & FLAG_Z ) { CALL( minx, minx->PC + d16 - 1 ); minx->icount -= 12; } }
+OP(EB) { UINT16 d16 = rdop16(minx); if ( ! ( minx->F & FLAG_Z ) ) { CALL( minx, minx->PC + d16 - 1 ); minx->icount -= 12; } }
+OP(EC) { UINT16 d16 = rdop16(minx); if ( minx->F & FLAG_C ) { JMP( minx, minx->PC + d16 - 1 ); } }
+OP(ED) { UINT16 d16 = rdop16(minx); if ( ! ( minx->F & FLAG_C ) ) { JMP( minx, minx->PC + d16 - 1 ); } }
+OP(EE) { UINT16 d16 = rdop16(minx); if ( minx->F & FLAG_Z ) { JMP( minx, minx->PC + d16 - 1 ); } }
+OP(EF) { UINT16 d16 = rdop16(minx); if ( ! ( minx->F & FLAG_Z ) ) { JMP( minx, minx->PC + d16 - 1 ); } }
+
+OP(F0) { INT8 d8 = rdop(minx); CALL( minx, minx->PC + d8 - 1 ); }
+OP(F1) { INT8 d8 = rdop(minx); JMP( minx, minx->PC + d8 - 1 ); }
+OP(F2) { UINT16 d16 = rdop16(minx); CALL( minx, minx->PC + d16 - 1 ); }
+OP(F3) { UINT16 d16 = rdop16(minx); JMP( minx, minx->PC + d16 - 1 ); }
+OP(F4) { JMP( minx, minx->HL ); }
+OP(F5) { INT8 d8 = rdop(minx); minx->BA = minx->BA - 0x0100; if ( minx->BA & 0xFF00 ) { JMP( minx, minx->PC + d8 - 1 ); } }
+OP(F6) { minx->BA = ( minx->BA & 0xFF00 ) | ( ( minx->BA & 0x00F0 ) >> 4 ) | ( ( minx->BA & 0x000F ) << 4 ); }
+OP(F7) { UINT8 d; AD1_IHL; d = RD( addr1 ); WR( addr1, ( ( d & 0xF0 ) >> 4 ) | ( ( d & 0x0F ) << 4 ) ); }
+OP(F8) { minx->PC = POP16(minx); minx->V = POP8(minx); minx->U = minx->V; }
+OP(F9) { minx->F = POP8(minx); minx->PC = POP16(minx); minx->V = POP8(minx); minx->U = minx->V; }
+OP(FA) { minx->PC = POP16(minx) + 2; minx->V = POP8(minx); minx->U = minx->V; }
+OP(FB) { AD1_I16; CALL( minx, rd16( minx, addr1 ) ); }
+OP(FC) { UINT8 i = rdop(minx) & 0xFE; CALL( minx, rd16( minx, i ) ); PUSH8( minx, minx->F ); }
+OP(FD) { UINT8 i = rdop(minx) & 0xFE; JMP( minx, rd16( minx, i ) ); /* PUSH8( minx, minx->F );?? */ }
+OP(FE) { /* illegal operation? */ }
+OP(FF) { }
+
+static void (*const insnminx[256])(minx_state *minx) = {
+ minx_00, minx_01, minx_02, minx_03, minx_04, minx_05, minx_06, minx_07,
+ minx_08, minx_09, minx_0A, minx_0B, minx_0C, minx_0D, minx_0E, minx_0F,
+ minx_10, minx_11, minx_12, minx_13, minx_14, minx_15, minx_16, minx_17,
+ minx_18, minx_19, minx_1A, minx_1B, minx_1C, minx_1D, minx_1E, minx_1F,
+ minx_20, minx_21, minx_22, minx_23, minx_24, minx_25, minx_26, minx_27,
+ minx_28, minx_29, minx_2A, minx_2B, minx_2C, minx_2D, minx_2E, minx_2F,
+ minx_30, minx_31, minx_32, minx_33, minx_34, minx_35, minx_36, minx_37,
+ minx_38, minx_39, minx_3A, minx_3B, minx_3C, minx_3D, minx_3E, minx_3F,
+ minx_40, minx_41, minx_42, minx_43, minx_44, minx_45, minx_46, minx_47,
+ minx_48, minx_49, minx_4A, minx_4B, minx_4C, minx_4D, minx_4E, minx_4F,
+ minx_50, minx_51, minx_52, minx_53, minx_54, minx_55, minx_56, minx_57,
+ minx_58, minx_59, minx_5A, minx_5B, minx_5C, minx_5D, minx_5E, minx_5F,
+ minx_60, minx_61, minx_62, minx_63, minx_64, minx_65, minx_66, minx_67,
+ minx_68, minx_69, minx_6A, minx_6B, minx_6C, minx_6D, minx_6E, minx_6F,
+ minx_70, minx_71, minx_72, minx_73, minx_74, minx_75, minx_76, minx_77,
+ minx_78, minx_79, minx_7A, minx_7B, minx_7C, minx_7D, minx_7E, minx_7F,
+ minx_80, minx_81, minx_82, minx_83, minx_84, minx_85, minx_86, minx_87,
+ minx_88, minx_89, minx_8A, minx_8B, minx_8C, minx_8D, minx_8E, minx_8F,
+ minx_90, minx_91, minx_92, minx_93, minx_94, minx_95, minx_96, minx_97,
+ minx_98, minx_99, minx_9A, minx_9B, minx_9C, minx_9D, minx_9E, minx_9F,
+ minx_A0, minx_A1, minx_A2, minx_A3, minx_A4, minx_A5, minx_A6, minx_A7,
+ minx_A8, minx_A9, minx_AA, minx_AB, minx_AC, minx_AD, minx_AE, minx_AF,
+ minx_B0, minx_B1, minx_B2, minx_B3, minx_B4, minx_B5, minx_B6, minx_B7,
+ minx_B8, minx_B9, minx_BA, minx_BB, minx_BC, minx_BD, minx_BE, minx_BF,
+ minx_C0, minx_C1, minx_C2, minx_C3, minx_C4, minx_C5, minx_C6, minx_C7,
+ minx_C8, minx_C9, minx_CA, minx_CB, minx_CC, minx_CD, minx_CE, minx_CF,
+ minx_D0, minx_D1, minx_D2, minx_D3, minx_D4, minx_D5, minx_D6, minx_D7,
+ minx_D8, minx_D9, minx_DA, minx_DB, minx_DC, minx_DD, minx_DE, minx_DF,
+ minx_E0, minx_E1, minx_E2, minx_E3, minx_E4, minx_E5, minx_E6, minx_E7,
+ minx_E8, minx_E9, minx_EA, minx_EB, minx_EC, minx_ED, minx_EE, minx_EF,
+ minx_F0, minx_F1, minx_F2, minx_F3, minx_F4, minx_F5, minx_F6, minx_F7,
+ minx_F8, minx_F9, minx_FA, minx_FB, minx_FC, minx_FD, minx_FE, minx_FF
+};
+
+static const int insnminx_cycles[256] = {
+ 8, 8, 8, 8, 12, 16, 8, 8, 8, 8, 8, 8, 12, 16, 8, 8,
+ 8, 8, 8, 8, 12, 16, 8, 8, 8, 8, 8, 8, 12, 16, 8, 8,
+ 8, 8, 8, 8, 12, 16, 8, 8, 8, 8, 8, 8, 12, 16, 8, 8,
+ 8, 8, 8, 8, 12, 16, 8, 8, 8, 8, 8, 8, 12, 16, 8, 8,
+
+ 4, 4, 4, 4, 12, 8, 8, 8, 4, 4, 4, 4, 12, 8, 8, 8,
+ 4, 4, 4, 4, 12, 8, 8, 8, 4, 4, 4, 4, 12, 8, 8, 8,
+ 8, 8, 8, 8, 16, 12, 12, 12, 8, 8, 8, 8, 16, 12, 12, 12,
+ 8, 8, 8, 8, 16, 12, 12, 12, 12, 12, 12, 12, 1, 16, 16, 16,
+
+ 8, 8, 8, 8, 8, 16, 12, 8, 8, 8, 8, 8, 8, 16, 12, 8,
+ 8, 8, 8, 8, 8, 12, 8, 8, 8, 8, 8, 8, 12, 12, 12, 12,
+ 16, 16, 16, 16, 12, 12, 16, 12, 12, 12, 12, 12, 8, 8, 12, 8,
+ 8, 8, 8, 8, 8, 12, 12, 12, 20, 20, 20, 20, 1, 1, 1, 1,
+
+ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 8, 12, 0, 0,
+ 12, 12, 12, 12, 12, 12, 12, 12, 20, 20, 20, 16, 16, 16, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, 12, 12, 12, 12, 12,
+ 20, 8, 24, 12, 8, 1, 8, 12, 8, 8, 8, 20, 20, 1, 1, 8
+};
diff --git a/trunk/src/emu/cpu/mips/mips3.c b/trunk/src/emu/cpu/mips/mips3.c
new file mode 100644
index 00000000000..b1d2c0b4356
--- /dev/null
+++ b/trunk/src/emu/cpu/mips/mips3.c
@@ -0,0 +1,2767 @@
+/***************************************************************************
+
+ mips3.c
+ Core implementation for the portable MIPS III/IV emulator.
+ Written by Aaron Giles
+
+ Still not implemented:
+ * DMULT needs to be fixed properly
+
+***************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "profiler.h"
+#include "mips3.h"
+#include "mips3com.h"
+
+
+#define ENABLE_OVERFLOWS 0
+
+#ifndef MIPS3_USE_DRC
+
+/***************************************************************************
+ HELPER MACROS
+***************************************************************************/
+
+#define RSVAL32 ((UINT32)mips3.core.r[RSREG])
+#define RTVAL32 ((UINT32)mips3.core.r[RTREG])
+#define RDVAL32 ((UINT32)mips3.core.r[RDREG])
+
+#define RSVAL64 (mips3.core.r[RSREG])
+#define RTVAL64 (mips3.core.r[RTREG])
+#define RDVAL64 (mips3.core.r[RDREG])
+
+#define FRVALS_FR0 (((float *)&mips3.core.cpr[1][0])[FRREG])
+#define FTVALS_FR0 (((float *)&mips3.core.cpr[1][0])[FTREG])
+#define FSVALS_FR0 (((float *)&mips3.core.cpr[1][0])[FSREG])
+#define FDVALS_FR0 (((float *)&mips3.core.cpr[1][0])[FDREG])
+#define FSVALW_FR0 (((UINT32 *)&mips3.core.cpr[1][0])[FSREG])
+#define FDVALW_FR0 (((UINT32 *)&mips3.core.cpr[1][0])[FDREG])
+
+#define FRVALD_FR0 (*(double *)&mips3.core.cpr[1][FRREG/2])
+#define FTVALD_FR0 (*(double *)&mips3.core.cpr[1][FTREG/2])
+#define FSVALD_FR0 (*(double *)&mips3.core.cpr[1][FSREG/2])
+#define FDVALD_FR0 (*(double *)&mips3.core.cpr[1][FDREG/2])
+#define FSVALL_FR0 (((UINT64 *)&mips3.core.cpr[1][0])[FSREG/2])
+#define FDVALL_FR0 (((UINT64 *)&mips3.core.cpr[1][0])[FDREG/2])
+
+#define FRVALS_FR1 (((float *)&mips3.core.cpr[1][FRREG])[BYTE_XOR_LE(0)])
+#define FTVALS_FR1 (((float *)&mips3.core.cpr[1][FTREG])[BYTE_XOR_LE(0)])
+#define FSVALS_FR1 (((float *)&mips3.core.cpr[1][FSREG])[BYTE_XOR_LE(0)])
+#define FDVALS_FR1 (((float *)&mips3.core.cpr[1][FDREG])[BYTE_XOR_LE(0)])
+#define FSVALW_FR1 (((UINT32 *)&mips3.core.cpr[1][FSREG])[BYTE_XOR_LE(0)])
+#define FDVALW_FR1 (((UINT32 *)&mips3.core.cpr[1][FDREG])[BYTE_XOR_LE(0)])
+
+#define FRVALD_FR1 (*(double *)&mips3.core.cpr[1][FRREG])
+#define FTVALD_FR1 (*(double *)&mips3.core.cpr[1][FTREG])
+#define FSVALD_FR1 (*(double *)&mips3.core.cpr[1][FSREG])
+#define FDVALD_FR1 (*(double *)&mips3.core.cpr[1][FDREG])
+#define FSVALL_FR1 (*(UINT64 *)&mips3.core.cpr[1][FSREG])
+#define FDVALL_FR1 (*(UINT64 *)&mips3.core.cpr[1][FDREG])
+
+#define ADDPC(x) mips3.nextpc = mips3.core.pc + ((x) << 2)
+#define ADDPCL(x,l) { mips3.nextpc = mips3.core.pc + ((x) << 2); mips3.core.r[l] = (INT32)(mips3.core.pc + 4); }
+#define ABSPC(x) mips3.nextpc = (mips3.core.pc & 0xf0000000) | ((x) << 2)
+#define ABSPCL(x,l) { mips3.nextpc = (mips3.core.pc & 0xf0000000) | ((x) << 2); mips3.core.r[l] = (INT32)(mips3.core.pc + 4); }
+#define SETPC(x) mips3.nextpc = (x)
+#define SETPCL(x,l) { mips3.nextpc = (x); mips3.core.r[l] = (INT32)(mips3.core.pc + 4); }
+
+#define HIVAL (UINT32)mips3.core.r[REG_HI]
+#define LOVAL (UINT32)mips3.core.r[REG_LO]
+#define HIVAL64 mips3.core.r[REG_HI]
+#define LOVAL64 mips3.core.r[REG_LO]
+#define SR mips3.core.cpr[0][COP0_Status]
+#define CAUSE mips3.core.cpr[0][COP0_Cause]
+
+#define GET_FCC(n) (mips3.cf[1][n])
+#define SET_FCC(n,v) (mips3.cf[1][n] = (v))
+
+#define IS_FR0 (!(SR & SR_FR))
+#define IS_FR1 (SR & SR_FR)
+
+
+
+/***************************************************************************
+ STRUCTURES & TYPEDEFS
+***************************************************************************/
+
+/* MIPS3 Registers */
+typedef struct
+{
+ /* core state */
+ mips3_state core;
+
+ /* internal stuff */
+ UINT32 ppc;
+ UINT32 nextpc;
+ UINT32 pcbase;
+ UINT8 cf[4][8];
+ int op;
+ int interrupt_cycles;
+ UINT32 ll_value;
+ UINT64 lld_value;
+ UINT32 badcop_value;
+ const vtlb_entry *tlb_table;
+
+ /* endian-dependent load/store */
+ void (*lwl)(UINT32 op);
+ void (*lwr)(UINT32 op);
+ void (*swl)(UINT32 op);
+ void (*swr)(UINT32 op);
+ void (*ldl)(UINT32 op);
+ void (*ldr)(UINT32 op);
+ void (*sdl)(UINT32 op);
+ void (*sdr)(UINT32 op);
+} mips3_regs;
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static void lwl_be(UINT32 op);
+static void lwr_be(UINT32 op);
+static void swl_be(UINT32 op);
+static void swr_be(UINT32 op);
+
+static void lwl_le(UINT32 op);
+static void lwr_le(UINT32 op);
+static void swl_le(UINT32 op);
+static void swr_le(UINT32 op);
+
+static void ldl_be(UINT32 op);
+static void ldr_be(UINT32 op);
+static void sdl_be(UINT32 op);
+static void sdr_be(UINT32 op);
+
+static void ldl_le(UINT32 op);
+static void ldr_le(UINT32 op);
+static void sdl_le(UINT32 op);
+static void sdr_le(UINT32 op);
+
+static const UINT8 fcc_shift[8] = { 23, 25, 26, 27, 28, 29, 30, 31 };
+
+
+
+/***************************************************************************
+ PRIVATE GLOBAL VARIABLES
+***************************************************************************/
+
+static mips3_regs mips3;
+
+
+
+/***************************************************************************
+ MEMORY ACCESSORS
+***************************************************************************/
+
+#define ROPCODE(pc) mips3.core.direct->read_decrypted_dword(pc)
+
+
+/***************************************************************************
+ DRC COMPATIBILITY
+***************************************************************************/
+
+void mips3drc_set_options(device_t *device, UINT32 options)
+{
+}
+
+void mips3drc_add_fastram(device_t *device, offs_t start, offs_t end, UINT8 readonly, void *base)
+{
+}
+
+void mips3drc_add_hotspot(device_t *device, offs_t pc, UINT32 opcode, UINT32 cycles)
+{
+}
+
+/***************************************************************************
+ EXECEPTION HANDLING
+***************************************************************************/
+
+INLINE void generate_exception(int exception, int backup)
+{
+ UINT32 offset = 0x180;
+/*
+ useful for catching exceptions:
+
+ if (exception != 0)
+ {
+ fprintf(stderr, "Exception: PC=%08X, PPC=%08X\n", mips3.core.pc, mips3.ppc);
+ debugger_break(Machine);
+ }
+*/
+
+ /* back up if necessary */
+ if (backup)
+ mips3.core.pc = mips3.ppc;
+
+ /* translate our fake fill exceptions into real exceptions */
+ if (exception == EXCEPTION_TLBLOAD_FILL || exception == EXCEPTION_TLBSTORE_FILL)
+ {
+ offset = 0;
+ exception = (exception - EXCEPTION_TLBLOAD_FILL) + EXCEPTION_TLBLOAD;
+ }
+
+ /* set the exception PC */
+ mips3.core.cpr[0][COP0_EPC] = mips3.core.pc;
+
+ /* put the cause in the low 8 bits and clear the branch delay flag */
+ CAUSE = (CAUSE & ~0x800000ff) | (exception << 2);
+
+ /* set the appropriate bits for coprocessor exceptions */
+ if(exception == EXCEPTION_BADCOP)
+ {
+ CAUSE |= mips3.badcop_value << 28;
+ }
+
+ /* if we were in a branch delay slot, adjust */
+ if (mips3.nextpc != ~0)
+ {
+ mips3.nextpc = ~0;
+ mips3.core.cpr[0][COP0_EPC] -= 4;
+ CAUSE |= 0x80000000;
+ }
+
+ /* set the exception level */
+ SR |= SR_EXL;
+
+ /* based on the BEV bit, we either go to ROM or RAM */
+ mips3.core.pc = (SR & SR_BEV) ? 0xbfc00200 : 0x80000000;
+
+ /* most exceptions go to offset 0x180, except for TLB stuff */
+ if (exception >= EXCEPTION_TLBMOD && exception <= EXCEPTION_TLBSTORE)
+ {
+ mame_printf_debug("TLB miss @ %08X\n", (UINT32)mips3.core.cpr[0][COP0_BadVAddr]);
+ }
+ mips3.core.pc += offset;
+
+/*
+ useful for tracking interrupts
+
+ if ((CAUSE & 0x7f) == 0)
+ logerror("Took interrupt -- Cause = %08X, PC = %08X\n", (UINT32)CAUSE, mips3.core.pc);
+*/
+}
+
+
+static void generate_tlb_exception(int exception, offs_t address)
+{
+ mips3.core.cpr[0][COP0_BadVAddr] = address;
+ if(exception == EXCEPTION_TLBLOAD || exception == EXCEPTION_TLBSTORE || exception == EXCEPTION_TLBLOAD_FILL || exception == EXCEPTION_TLBSTORE_FILL)
+ {
+ mips3.core.cpr[0][COP0_Context] = (mips3.core.cpr[0][COP0_Context] & 0xff800000) | ((address >> 9) & 0x007ffff0);
+ mips3.core.cpr[0][COP0_EntryHi] = (address & 0xffffe000) | (mips3.core.cpr[0][COP0_EntryHi] & 0xff);
+ }
+ generate_exception(exception, 1);
+}
+
+
+INLINE void invalid_instruction(UINT32 op)
+{
+ generate_exception(EXCEPTION_INVALIDOP, 1);
+}
+
+
+
+/***************************************************************************
+ IRQ HANDLING
+***************************************************************************/
+
+static void check_irqs(void)
+{
+ if ((CAUSE & SR & 0xfc00) && (SR & SR_IE) && !(SR & SR_EXL) && !(SR & SR_ERL))
+ generate_exception(EXCEPTION_INTERRUPT, 0);
+}
+
+
+
+/***************************************************************************
+ CORE CALLBACKS
+***************************************************************************/
+
+static CPU_RESET( mips3 )
+{
+ /* common reset */
+ mips3com_reset(&mips3.core);
+ mips3.nextpc = ~0;
+ memset(mips3.cf, 0, sizeof(mips3.cf));
+
+ /* set up the endianness */
+ if (mips3.core.bigendian)
+ {
+ mips3.lwl = lwl_be;
+ mips3.lwr = lwr_be;
+ mips3.swl = swl_be;
+ mips3.swr = swr_be;
+ mips3.ldl = ldl_be;
+ mips3.ldr = ldr_be;
+ mips3.sdl = sdl_be;
+ mips3.sdr = sdr_be;
+ }
+ else
+ {
+ mips3.lwl = lwl_le;
+ mips3.lwr = lwr_le;
+ mips3.swl = swl_le;
+ mips3.swr = swr_le;
+ mips3.ldl = ldl_le;
+ mips3.ldr = ldr_le;
+ mips3.sdl = sdl_le;
+ mips3.sdr = sdr_le;
+ }
+}
+
+
+static CPU_TRANSLATE( mips3 )
+{
+ /* common translate */
+ return mips3com_translate_address(&mips3.core, space, intention, address);
+}
+
+
+CPU_DISASSEMBLE( mips3 )
+{
+ /* common disassemble */
+ return mips3com_dasm(&mips3.core, buffer, pc, oprom, opram);
+}
+
+
+
+/***************************************************************************
+ TLB HANDLING
+***************************************************************************/
+
+INLINE int RBYTE(offs_t address, UINT32 *result)
+{
+ UINT32 tlbval = mips3.tlb_table[address >> 12];
+ if (tlbval & VTLB_READ_ALLOWED)
+ {
+ *result = (*mips3.core.memory.read_byte)(mips3.core.program, (tlbval & ~0xfff) | (address & 0xfff));
+ }
+ else
+ {
+ if(tlbval & VTLB_FLAG_FIXED)
+ {
+ generate_tlb_exception(EXCEPTION_TLBLOAD, address);
+ }
+ else
+ {
+ generate_tlb_exception(EXCEPTION_TLBLOAD_FILL, address);
+ }
+ *result = 0;
+ return 0;
+ }
+ return 1;
+}
+
+
+INLINE int RHALF(offs_t address, UINT32 *result)
+{
+ UINT32 tlbval = mips3.tlb_table[address >> 12];
+ if (tlbval & VTLB_READ_ALLOWED)
+ {
+ *result = (*mips3.core.memory.read_word)(mips3.core.program, (tlbval & ~0xfff) | (address & 0xfff));
+ }
+ else
+ {
+ if(tlbval & VTLB_FLAG_FIXED)
+ {
+ generate_tlb_exception(EXCEPTION_TLBLOAD, address);
+ }
+ else
+ {
+ generate_tlb_exception(EXCEPTION_TLBLOAD_FILL, address);
+ }
+ *result = 0;
+ return 0;
+ }
+ return 1;
+}
+
+
+INLINE int RWORD(offs_t address, UINT32 *result)
+{
+ UINT32 tlbval = mips3.tlb_table[address >> 12];
+ if (tlbval & VTLB_READ_ALLOWED)
+ {
+ *result = (*mips3.core.memory.read_dword)(mips3.core.program, (tlbval & ~0xfff) | (address & 0xfff));
+ }
+ else
+ {
+ if(tlbval & VTLB_FLAG_FIXED)
+ {
+ generate_tlb_exception(EXCEPTION_TLBLOAD, address);
+ }
+ else
+ {
+ generate_tlb_exception(EXCEPTION_TLBLOAD_FILL, address);
+ }
+ *result = 0;
+ return 0;
+ }
+ return 1;
+}
+
+
+INLINE int RWORD_MASKED(offs_t address, UINT32 *result, UINT32 mem_mask)
+{
+ UINT32 tlbval = mips3.tlb_table[address >> 12];
+ if (tlbval & VTLB_READ_ALLOWED)
+ {
+ *result = (*mips3.core.memory.read_dword_masked)(mips3.core.program, (tlbval & ~0xfff) | (address & 0xfff), mem_mask);
+ }
+ else
+ {
+ if(tlbval & VTLB_FLAG_FIXED)
+ {
+ generate_tlb_exception(EXCEPTION_TLBLOAD, address);
+ }
+ else
+ {
+ generate_tlb_exception(EXCEPTION_TLBLOAD_FILL, address);
+ }
+ *result = 0;
+ return 0;
+ }
+ return 1;
+}
+
+
+INLINE int RDOUBLE(offs_t address, UINT64 *result)
+{
+ UINT32 tlbval = mips3.tlb_table[address >> 12];
+ if (tlbval & VTLB_READ_ALLOWED)
+ {
+ *result = (*mips3.core.memory.read_qword)(mips3.core.program, (tlbval & ~0xfff) | (address & 0xfff));
+ }
+ else
+ {
+ if(tlbval & VTLB_FLAG_FIXED)
+ {
+ generate_tlb_exception(EXCEPTION_TLBLOAD, address);
+ }
+ else
+ {
+ generate_tlb_exception(EXCEPTION_TLBLOAD_FILL, address);
+ }
+ *result = 0;
+ return 0;
+ }
+ return 1;
+}
+
+
+INLINE int RDOUBLE_MASKED(offs_t address, UINT64 *result, UINT64 mem_mask)
+{
+ UINT32 tlbval = mips3.tlb_table[address >> 12];
+ if (tlbval & VTLB_READ_ALLOWED)
+ {
+ *result = (*mips3.core.memory.read_qword_masked)(mips3.core.program, (tlbval & ~0xfff) | (address & 0xfff), mem_mask);
+ }
+ else
+ {
+ if(tlbval & VTLB_FLAG_FIXED)
+ {
+ generate_tlb_exception(EXCEPTION_TLBLOAD, address);
+ }
+ else
+ {
+ generate_tlb_exception(EXCEPTION_TLBLOAD_FILL, address);
+ }
+ *result = 0;
+ return 0;
+ }
+ return 1;
+}
+
+
+INLINE void WBYTE(offs_t address, UINT8 data)
+{
+ UINT32 tlbval = mips3.tlb_table[address >> 12];
+ if (tlbval & VTLB_WRITE_ALLOWED)
+ {
+ (*mips3.core.memory.write_byte)(mips3.core.program, (tlbval & ~0xfff) | (address & 0xfff), data);
+ }
+ else
+ {
+ if(tlbval & VTLB_READ_ALLOWED)
+ {
+ generate_tlb_exception(EXCEPTION_TLBMOD, address);
+ }
+ else if(tlbval & VTLB_FLAG_FIXED)
+ {
+ generate_tlb_exception(EXCEPTION_TLBSTORE, address);
+ }
+ else
+ {
+ generate_tlb_exception(EXCEPTION_TLBSTORE_FILL, address);
+ }
+ }
+}
+
+
+INLINE void WHALF(offs_t address, UINT16 data)
+{
+ UINT32 tlbval = mips3.tlb_table[address >> 12];
+ if (tlbval & VTLB_WRITE_ALLOWED)
+ {
+ (*mips3.core.memory.write_word)(mips3.core.program, (tlbval & ~0xfff) | (address & 0xfff), data);
+ }
+ else
+ {
+ if(tlbval & VTLB_READ_ALLOWED)
+ {
+ generate_tlb_exception(EXCEPTION_TLBMOD, address);
+ }
+ else if(tlbval & VTLB_FLAG_FIXED)
+ {
+ generate_tlb_exception(EXCEPTION_TLBSTORE, address);
+ }
+ else
+ {
+ generate_tlb_exception(EXCEPTION_TLBSTORE_FILL, address);
+ }
+ }
+}
+
+
+INLINE void WWORD(offs_t address, UINT32 data)
+{
+ UINT32 tlbval = mips3.tlb_table[address >> 12];
+ if (tlbval & VTLB_WRITE_ALLOWED)
+ {
+ (*mips3.core.memory.write_dword)(mips3.core.program, (tlbval & ~0xfff) | (address & 0xfff), data);
+ }
+ else
+ {
+ if(tlbval & VTLB_READ_ALLOWED)
+ {
+ generate_tlb_exception(EXCEPTION_TLBMOD, address);
+ }
+ else if(tlbval & VTLB_FLAG_FIXED)
+ {
+ generate_tlb_exception(EXCEPTION_TLBSTORE, address);
+ }
+ else
+ {
+ generate_tlb_exception(EXCEPTION_TLBSTORE_FILL, address);
+ }
+ }
+}
+
+
+INLINE void WWORD_MASKED(offs_t address, UINT32 data, UINT32 mem_mask)
+{
+ UINT32 tlbval = mips3.tlb_table[address >> 12];
+ if (tlbval & VTLB_WRITE_ALLOWED)
+ {
+ (*mips3.core.memory.write_dword_masked)(mips3.core.program, (tlbval & ~0xfff) | (address & 0xfff), data, mem_mask);
+ }
+ else
+ {
+ if(tlbval & VTLB_READ_ALLOWED)
+ {
+ generate_tlb_exception(EXCEPTION_TLBMOD, address);
+ }
+ else if(tlbval & VTLB_FLAG_FIXED)
+ {
+ generate_tlb_exception(EXCEPTION_TLBSTORE, address);
+ }
+ else
+ {
+ generate_tlb_exception(EXCEPTION_TLBSTORE_FILL, address);
+ }
+ }
+}
+
+
+INLINE void WDOUBLE(offs_t address, UINT64 data)
+{
+ UINT32 tlbval = mips3.tlb_table[address >> 12];
+ //printf("%08x: %08x\n", (UINT32)address, (UINT32)tlbval);
+ if (tlbval & VTLB_WRITE_ALLOWED)
+ {
+ (*mips3.core.memory.write_qword)(mips3.core.program, (tlbval & ~0xfff) | (address & 0xfff), data);
+ }
+ else
+ {
+ if(tlbval & VTLB_READ_ALLOWED)
+ {
+ generate_tlb_exception(EXCEPTION_TLBMOD, address);
+ }
+ else if(tlbval & VTLB_FLAG_FIXED)
+ {
+ generate_tlb_exception(EXCEPTION_TLBSTORE, address);
+ }
+ else
+ {
+ generate_tlb_exception(EXCEPTION_TLBSTORE_FILL, address);
+ }
+ }
+}
+
+
+INLINE void WDOUBLE_MASKED(offs_t address, UINT64 data, UINT64 mem_mask)
+{
+ UINT32 tlbval = mips3.tlb_table[address >> 12];
+ if (tlbval & VTLB_WRITE_ALLOWED)
+ {
+ (*mips3.core.memory.write_qword_masked)(mips3.core.program, (tlbval & ~0xfff) | (address & 0xfff), data, mem_mask);
+ }
+ else
+ {
+ if(tlbval & VTLB_READ_ALLOWED)
+ {
+ generate_tlb_exception(EXCEPTION_TLBMOD, address);
+ }
+ else if(tlbval & VTLB_FLAG_FIXED)
+ {
+ generate_tlb_exception(EXCEPTION_TLBSTORE, address);
+ }
+ else
+ {
+ generate_tlb_exception(EXCEPTION_TLBSTORE_FILL, address);
+ }
+ }
+}
+
+
+
+/***************************************************************************
+ COP0 (SYSTEM) EXECUTION HANDLING
+***************************************************************************/
+
+INLINE UINT64 get_cop0_reg(int idx)
+{
+ if (idx == COP0_Count)
+ {
+ /* it doesn't really take 250 cycles to read this register, but it helps speed */
+ /* up loops that hammer on it */
+ if (mips3.core.icount >= MIPS3_COUNT_READ_CYCLES)
+ mips3.core.icount -= MIPS3_COUNT_READ_CYCLES;
+ else
+ mips3.core.icount = 0;
+ return (UINT32)((mips3.core.device->total_cycles() - mips3.core.count_zero_time) / 2);
+ }
+ else if (idx == COP0_Cause)
+ {
+ /* it doesn't really take 250 cycles to read this register, but it helps speed */
+ /* up loops that hammer on it */
+ if (mips3.core.icount >= MIPS3_CAUSE_READ_CYCLES)
+ mips3.core.icount -= MIPS3_CAUSE_READ_CYCLES;
+ else
+ mips3.core.icount = 0;
+ }
+ else if (idx == COP0_Random)
+ {
+ int wired = mips3.core.cpr[0][COP0_Wired] & 0x3f;
+ int range = 48 - wired;
+ if (range > 0)
+ return ((mips3.core.device->total_cycles() - mips3.core.count_zero_time) % range + wired) & 0x3f;
+ else
+ return 47;
+ }
+ return mips3.core.cpr[0][idx];
+}
+
+INLINE void set_cop0_reg(int idx, UINT64 val)
+{
+ switch (idx)
+ {
+ case COP0_Cause:
+ CAUSE = (CAUSE & 0xfc00) | (val & ~0xfc00);
+ if (CAUSE & 0x300)
+ {
+ /* if we're in a delay slot, propogate the target PC before generating the exception */
+ if (mips3.nextpc != ~0)
+ {
+ mips3.core.pc = mips3.nextpc;
+ mips3.nextpc = ~0;
+ }
+ generate_exception(EXCEPTION_INTERRUPT, 0);
+ }
+ break;
+
+ case COP0_Status:
+ {
+ /* update interrupts and cycle counting */
+ UINT32 diff = mips3.core.cpr[0][idx] ^ val;
+// if (val & 0xe0)
+// fatalerror("System set 64-bit addressing mode, SR=%08X", val);
+ mips3.core.cpr[0][idx] = val;
+ if (diff & 0x8000)
+ mips3com_update_cycle_counting(&mips3.core);
+ check_irqs();
+ break;
+ }
+
+ case COP0_Count:
+ mips3.core.cpr[0][idx] = val;
+ mips3.core.count_zero_time = mips3.core.device->total_cycles() - ((UINT64)(UINT32)val * 2);
+ mips3com_update_cycle_counting(&mips3.core);
+ break;
+
+ case COP0_Compare:
+ mips3.core.compare_armed = 1;
+ CAUSE &= ~0x8000;
+ mips3.core.cpr[0][idx] = val & 0xffffffff;
+ mips3com_update_cycle_counting(&mips3.core);
+ break;
+
+ case COP0_PRId:
+ break;
+
+ case COP0_Config:
+ mips3.core.cpr[0][idx] = (mips3.core.cpr[0][idx] & ~7) | (val & 7);
+ break;
+
+ case COP0_EntryHi:
+ /* if the ASID changes, remap */
+ if ((mips3.core.cpr[0][idx] ^ val) & 0xff)
+ {
+ mips3.core.cpr[0][idx] = val;
+ mips3com_asid_changed(&mips3.core);
+ }
+ mips3.core.cpr[0][idx] = val;
+ break;
+
+ default:
+ mips3.core.cpr[0][idx] = val;
+ break;
+ }
+}
+
+INLINE UINT64 get_cop0_creg(int idx)
+{
+ return mips3.core.ccr[0][idx];
+}
+
+INLINE void set_cop0_creg(int idx, UINT64 val)
+{
+ mips3.core.ccr[0][idx] = val;
+}
+
+INLINE void handle_cop0(UINT32 op)
+{
+ if ((SR & SR_KSU_MASK) != SR_KSU_KERNEL && !(SR & SR_COP0))
+ {
+ mips3.badcop_value = 0;
+ generate_exception(EXCEPTION_BADCOP, 1);
+ }
+
+ switch (RSREG)
+ {
+ case 0x00: /* MFCz */ if (RTREG) RTVAL64 = (INT32)get_cop0_reg(RDREG); break;
+ case 0x01: /* DMFCz */ if (RTREG) RTVAL64 = get_cop0_reg(RDREG); break;
+ case 0x02: /* CFCz */ if (RTREG) RTVAL64 = (INT32)get_cop0_creg(RDREG); break;
+ case 0x04: /* MTCz */ set_cop0_reg(RDREG, RTVAL32); break;
+ case 0x05: /* DMTCz */ set_cop0_reg(RDREG, RTVAL64); break;
+ case 0x06: /* CTCz */ set_cop0_creg(RDREG, RTVAL32); break;
+ case 0x08: /* BC */
+ switch (RTREG)
+ {
+ case 0x00: /* BCzF */ if (!mips3.cf[0]) ADDPC(SIMMVAL); break;
+ case 0x01: /* BCzF */ if (mips3.cf[0]) ADDPC(SIMMVAL); break;
+ case 0x02: /* BCzFL */ invalid_instruction(op); break;
+ case 0x03: /* BCzTL */ invalid_instruction(op); break;
+ default: invalid_instruction(op); break;
+ }
+ break;
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ case 0x13:
+ case 0x14:
+ case 0x15:
+ case 0x16:
+ case 0x17:
+ case 0x18:
+ case 0x19:
+ case 0x1a:
+ case 0x1b:
+ case 0x1c:
+ case 0x1d:
+ case 0x1e:
+ case 0x1f: /* COP */
+ switch (op & 0x01ffffff)
+ {
+ case 0x01: /* TLBR */
+ mips3com_tlbr(&mips3.core);
+ break;
+
+ case 0x02: /* TLBWI */
+ mips3com_tlbwi(&mips3.core);
+ break;
+
+ case 0x06: /* TLBWR */
+ mips3com_tlbwr(&mips3.core);
+ break;
+
+ case 0x08: /* TLBP */
+ mips3com_tlbp(&mips3.core);
+ break;
+
+ case 0x10: /* RFE */ invalid_instruction(op); break;
+ case 0x18: /* ERET */ logerror("ERET\n"); mips3.core.pc = mips3.core.cpr[0][COP0_EPC]; SR &= ~SR_EXL; check_irqs(); mips3.lld_value ^= 0xffffffff; mips3.ll_value ^= 0xffffffff; break;
+ case 0x20: /* WAIT */ break;
+ default: invalid_instruction(op); break;
+ }
+ break;
+ default: invalid_instruction(op); break;
+ }
+}
+
+
+
+/***************************************************************************
+ COP1 (FPU) EXECUTION HANDLING
+***************************************************************************/
+
+INLINE UINT32 get_cop1_reg32(int idx)
+{
+ if (IS_FR0)
+ return ((UINT32 *)&mips3.core.cpr[1][0])[idx];
+ else
+ return mips3.core.cpr[1][idx];
+}
+
+INLINE UINT64 get_cop1_reg64(int idx)
+{
+ if (IS_FR0)
+ return ((UINT64 *)&mips3.core.cpr[1][0])[idx/2];
+ else
+ return mips3.core.cpr[1][idx];
+}
+
+INLINE void set_cop1_reg32(int idx, UINT32 val)
+{
+ if (IS_FR0)
+ ((UINT32 *)&mips3.core.cpr[1][0])[idx] = val;
+ else
+ mips3.core.cpr[1][idx] = val;
+}
+
+INLINE void set_cop1_reg64(int idx, UINT64 val)
+{
+ if (IS_FR0)
+ ((UINT64 *)&mips3.core.cpr[1][0])[idx/2] = val;
+ else
+ mips3.core.cpr[1][idx] = val;
+}
+
+INLINE UINT64 get_cop1_creg(int idx)
+{
+ if (idx == 31)
+ {
+ UINT32 result = mips3.core.ccr[1][31] & ~0xfe800000;
+ int i;
+
+ for (i = 0; i < 8; i++)
+ if (mips3.cf[1][i])
+ result |= 1 << fcc_shift[i];
+ return result;
+ }
+ return mips3.core.ccr[1][idx];
+}
+
+INLINE void set_cop1_creg(int idx, UINT64 val)
+{
+ mips3.core.ccr[1][idx] = val;
+ if (idx == 31)
+ {
+ int i;
+
+ for (i = 0; i < 8; i++)
+ mips3.cf[1][i] = (val >> fcc_shift[i]) & 1;
+ }
+}
+
+INLINE void handle_cop1_fr0(UINT32 op)
+{
+ double dtemp;
+
+ /* note: additional condition codes available on R5000 only */
+
+ if (!(SR & SR_COP1))
+ {
+ mips3.badcop_value = 1;
+ generate_exception(EXCEPTION_BADCOP, 1);
+ }
+
+ switch (RSREG)
+ {
+ case 0x00: /* MFCz */ if (RTREG) RTVAL64 = (INT32)get_cop1_reg32(RDREG); break;
+ case 0x01: /* DMFCz */ if (RTREG) RTVAL64 = get_cop1_reg64(RDREG); break;
+ case 0x02: /* CFCz */ if (RTREG) RTVAL64 = (INT32)get_cop1_creg(RDREG); break;
+ case 0x04: /* MTCz */ set_cop1_reg32(RDREG, RTVAL32); break;
+ case 0x05: /* DMTCz */ set_cop1_reg64(RDREG, RTVAL64); break;
+ case 0x06: /* CTCz */ set_cop1_creg(RDREG, RTVAL32); break;
+ case 0x08: /* BC */
+ switch ((op >> 16) & 3)
+ {
+ case 0x00: /* BCzF */ if (!GET_FCC((op >> 18) & 7)) ADDPC(SIMMVAL); break;
+ case 0x01: /* BCzT */ if (GET_FCC((op >> 18) & 7)) ADDPC(SIMMVAL); break;
+ case 0x02: /* BCzFL */ if (!GET_FCC((op >> 18) & 7)) ADDPC(SIMMVAL); else mips3.core.pc += 4; break;
+ case 0x03: /* BCzTL */ if (GET_FCC((op >> 18) & 7)) ADDPC(SIMMVAL); else mips3.core.pc += 4; break;
+ }
+ break;
+ default:
+ switch (op & 0x3f)
+ {
+ case 0x00:
+ if (IS_SINGLE(op)) /* ADD.S */
+ FDVALS_FR0 = FSVALS_FR0 + FTVALS_FR0;
+ else /* ADD.D */
+ FDVALD_FR0 = FSVALD_FR0 + FTVALD_FR0;
+ break;
+
+ case 0x01:
+ if (IS_SINGLE(op)) /* SUB.S */
+ FDVALS_FR0 = FSVALS_FR0 - FTVALS_FR0;
+ else /* SUB.D */
+ FDVALD_FR0 = FSVALD_FR0 - FTVALD_FR0;
+ break;
+
+ case 0x02:
+ if (IS_SINGLE(op)) /* MUL.S */
+ FDVALS_FR0 = FSVALS_FR0 * FTVALS_FR0;
+ else /* MUL.D */
+ FDVALD_FR0 = FSVALD_FR0 * FTVALD_FR0;
+ break;
+
+ case 0x03:
+ if (IS_SINGLE(op)) /* DIV.S */
+ FDVALS_FR0 = FSVALS_FR0 / FTVALS_FR0;
+ else /* DIV.D */
+ FDVALD_FR0 = FSVALD_FR0 / FTVALD_FR0;
+ break;
+
+ case 0x04:
+ if (IS_SINGLE(op)) /* SQRT.S */
+ FDVALS_FR0 = sqrt(FSVALS_FR0);
+ else /* SQRT.D */
+ FDVALD_FR0 = sqrt(FSVALD_FR0);
+ break;
+
+ case 0x05:
+ if (IS_SINGLE(op)) /* ABS.S */
+ FDVALS_FR0 = fabs(FSVALS_FR0);
+ else /* ABS.D */
+ FDVALD_FR0 = fabs(FSVALD_FR0);
+ break;
+
+ case 0x06:
+ if (IS_SINGLE(op)) /* MOV.S */
+ FDVALS_FR0 = FSVALS_FR0;
+ else /* MOV.D */
+ FDVALD_FR0 = FSVALD_FR0;
+ break;
+
+ case 0x07:
+ if (IS_SINGLE(op)) /* NEG.S */
+ FDVALS_FR0 = -FSVALS_FR0;
+ else /* NEG.D */
+ FDVALD_FR0 = -FSVALD_FR0;
+ break;
+
+ case 0x08:
+ if (IS_SINGLE(op)) /* ROUND.L.S */
+ {
+ double temp = FSVALS_FR0;
+ if (temp < 0)
+ temp = ceil(temp - 0.5);
+ else
+ temp = floor(temp + 0.5);
+ FDVALL_FR0 = (INT64)temp;
+ }
+ else /* ROUND.L.D */
+ {
+ double temp = FSVALD_FR0;
+ if (temp < 0)
+ temp = ceil(temp - 0.5);
+ else
+ temp = floor(temp + 0.5);
+ FDVALL_FR0 = (INT64)temp;
+ }
+ break;
+
+ case 0x09:
+ if (IS_SINGLE(op)) /* TRUNC.L.S */
+ {
+ double temp = FSVALS_FR0;
+ if (temp < 0)
+ temp = ceil(temp);
+ else
+ temp = floor(temp);
+ FDVALL_FR0 = (INT64)temp;
+ }
+ else /* TRUNC.L.D */
+ {
+ double temp = FSVALD_FR0;
+ if (temp < 0)
+ temp = ceil(temp);
+ else
+ temp = floor(temp);
+ FDVALL_FR0 = (INT64)temp;
+ }
+ break;
+
+ case 0x0a:
+ if (IS_SINGLE(op)) /* CEIL.L.S */
+ dtemp = ceil(FSVALS_FR0);
+ else /* CEIL.L.D */
+ dtemp = ceil(FSVALD_FR0);
+ FDVALL_FR0 = (INT64)dtemp;
+ break;
+
+ case 0x0b:
+ if (IS_SINGLE(op)) /* FLOOR.L.S */
+ dtemp = floor(FSVALS_FR0);
+ else /* FLOOR.L.D */
+ dtemp = floor(FSVALD_FR0);
+ FDVALL_FR0 = (INT64)dtemp;
+ break;
+
+ case 0x0c:
+ if (IS_SINGLE(op)) /* ROUND.W.S */
+ {
+ dtemp = FSVALS_FR0;
+ if (dtemp < 0)
+ dtemp = ceil(dtemp - 0.5);
+ else
+ dtemp = floor(dtemp + 0.5);
+ FDVALW_FR0 = (INT32)dtemp;
+ }
+ else /* ROUND.W.D */
+ {
+ dtemp = FSVALD_FR0;
+ if (dtemp < 0)
+ dtemp = ceil(dtemp - 0.5);
+ else
+ dtemp = floor(dtemp + 0.5);
+ FDVALW_FR0 = (INT32)dtemp;
+ }
+ break;
+
+ case 0x0d:
+ if (IS_SINGLE(op)) /* TRUNC.W.S */
+ {
+ dtemp = FSVALS_FR0;
+ if (dtemp < 0)
+ dtemp = ceil(dtemp);
+ else
+ dtemp = floor(dtemp);
+ FDVALW_FR0 = (INT32)dtemp;
+ }
+ else /* TRUNC.W.D */
+ {
+ dtemp = FSVALD_FR0;
+ if (dtemp < 0)
+ dtemp = ceil(dtemp);
+ else
+ dtemp = floor(dtemp);
+ FDVALW_FR0 = (INT32)dtemp;
+ }
+ break;
+
+ case 0x0e:
+ if (IS_SINGLE(op)) /* CEIL.W.S */
+ dtemp = ceil(FSVALS_FR0);
+ else /* CEIL.W.D */
+ dtemp = ceil(FSVALD_FR0);
+ FDVALW_FR0 = (INT32)dtemp;
+ break;
+
+ case 0x0f:
+ if (IS_SINGLE(op)) /* FLOOR.W.S */
+ dtemp = floor(FSVALS_FR0);
+ else /* FLOOR.W.D */
+ dtemp = floor(FSVALD_FR0);
+ FDVALW_FR0 = (INT32)dtemp;
+ break;
+
+ case 0x11: /* R5000 */
+ if (GET_FCC((op >> 18) & 7) == ((op >> 16) & 1))
+ {
+ if (IS_SINGLE(op)) /* MOVT/F.S */
+ FDVALS_FR0 = FSVALS_FR0;
+ else /* MOVT/F.D */
+ FDVALD_FR0 = FSVALD_FR0;
+ }
+ break;
+
+ case 0x12: /* R5000 */
+ if (RTVAL64 == 0)
+ {
+ if (IS_SINGLE(op)) /* MOVZ.S */
+ FDVALS_FR0 = FSVALS_FR0;
+ else /* MOVZ.D */
+ FDVALD_FR0 = FSVALD_FR0;
+ }
+ break;
+
+ case 0x13: /* R5000 */
+ if (RTVAL64 != 0)
+ {
+ if (IS_SINGLE(op)) /* MOVN.S */
+ FDVALS_FR0 = FSVALS_FR0;
+ else /* MOVN.D */
+ FDVALD_FR0 = FSVALD_FR0;
+ }
+ break;
+
+ case 0x15: /* R5000 */
+ if (IS_SINGLE(op)) /* RECIP.S */
+ FDVALS_FR0 = 1.0f / FSVALS_FR0;
+ else /* RECIP.D */
+ FDVALD_FR0 = 1.0 / FSVALD_FR0;
+ break;
+
+ case 0x16: /* R5000 */
+ if (IS_SINGLE(op)) /* RSQRT.S */
+ FDVALS_FR0 = 1.0f / sqrt(FSVALS_FR0);
+ else /* RSQRT.D */
+ FDVALD_FR0 = 1.0 / sqrt(FSVALD_FR0);
+ break;
+
+ case 0x20:
+ if (IS_INTEGRAL(op))
+ {
+ if (IS_SINGLE(op)) /* CVT.S.W */
+ FDVALS_FR0 = (INT32)FSVALW_FR0;
+ else /* CVT.S.L */
+ FDVALS_FR0 = (INT64)FSVALL_FR0;
+ }
+ else /* CVT.S.D */
+ FDVALS_FR0 = FSVALD_FR0;
+ break;
+
+ case 0x21:
+ if (IS_INTEGRAL(op))
+ {
+ if (IS_SINGLE(op)) /* CVT.D.W */
+ FDVALD_FR0 = (INT32)FSVALW_FR0;
+ else /* CVT.D.L */
+ FDVALD_FR0 = (INT64)FSVALL_FR0;
+ }
+ else /* CVT.D.S */
+ FDVALD_FR0 = FSVALS_FR0;
+ break;
+
+ case 0x24:
+ if (IS_SINGLE(op)) /* CVT.W.S */
+ FDVALW_FR0 = (INT32)FSVALS_FR0;
+ else
+ FDVALW_FR0 = (INT32)FSVALD_FR0;
+ break;
+
+ case 0x25:
+ if (IS_SINGLE(op)) /* CVT.L.S */
+ FDVALL_FR0 = (INT64)FSVALS_FR0;
+ else /* CVT.L.D */
+ FDVALL_FR0 = (INT64)FSVALD_FR0;
+ break;
+
+ case 0x30:
+ case 0x38:
+ if (IS_SINGLE(op)) /* C.F.S */
+ SET_FCC((op >> 8) & 7, 0);
+ else /* C.F.D */
+ SET_FCC((op >> 8) & 7, 0);
+ break;
+
+ case 0x31:
+ case 0x39:
+ if (IS_SINGLE(op)) /* C.UN.S */
+ SET_FCC((op >> 8) & 7, 0);
+ else /* C.UN.D */
+ SET_FCC((op >> 8) & 7, 0);
+ break;
+
+ case 0x32:
+ case 0x3a:
+ if (IS_SINGLE(op)) /* C.EQ.S */
+ SET_FCC((op >> 8) & 7, (FSVALS_FR0 == FTVALS_FR0));
+ else /* C.EQ.D */
+ SET_FCC((op >> 8) & 7, (FSVALD_FR0 == FTVALD_FR0));
+ break;
+
+ case 0x33:
+ case 0x3b:
+ if (IS_SINGLE(op)) /* C.UEQ.S */
+ SET_FCC((op >> 8) & 7, (FSVALS_FR0 == FTVALS_FR0));
+ else /* C.UEQ.D */
+ SET_FCC((op >> 8) & 7, (FSVALD_FR0 == FTVALD_FR0));
+ break;
+
+ case 0x34:
+ case 0x3c:
+ if (IS_SINGLE(op)) /* C.OLT.S */
+ SET_FCC((op >> 8) & 7, (FSVALS_FR0 < FTVALS_FR0));
+ else /* C.OLT.D */
+ SET_FCC((op >> 8) & 7, (FSVALD_FR0 < FTVALD_FR0));
+ break;
+
+ case 0x35:
+ case 0x3d:
+ if (IS_SINGLE(op)) /* C.ULT.S */
+ SET_FCC((op >> 8) & 7, (FSVALS_FR0 < FTVALS_FR0));
+ else /* C.ULT.D */
+ SET_FCC((op >> 8) & 7, (FSVALD_FR0 < FTVALD_FR0));
+ break;
+
+ case 0x36:
+ case 0x3e:
+ if (IS_SINGLE(op)) /* C.OLE.S */
+ SET_FCC((op >> 8) & 7, (FSVALS_FR0 <= FTVALS_FR0));
+ else /* C.OLE.D */
+ SET_FCC((op >> 8) & 7, (FSVALD_FR0 <= FTVALD_FR0));
+ break;
+
+ case 0x37:
+ case 0x3f:
+ if (IS_SINGLE(op)) /* C.ULE.S */
+ SET_FCC((op >> 8) & 7, (FSVALS_FR0 <= FTVALS_FR0));
+ else /* C.ULE.D */
+ SET_FCC((op >> 8) & 7, (FSVALD_FR0 <= FTVALD_FR0));
+ break;
+
+ default:
+ fprintf(stderr, "cop1 %X\n", op);
+ break;
+ }
+ break;
+ }
+}
+
+
+INLINE void handle_cop1_fr1(UINT32 op)
+{
+ double dtemp;
+
+ /* note: additional condition codes available on R5000 only */
+
+ if (!(SR & SR_COP1))
+ {
+ mips3.badcop_value = 1;
+ generate_exception(EXCEPTION_BADCOP, 1);
+ }
+
+ switch (RSREG)
+ {
+ case 0x00: /* MFCz */ if (RTREG) RTVAL64 = (INT32)get_cop1_reg32(RDREG); break;
+ case 0x01: /* DMFCz */ if (RTREG) RTVAL64 = get_cop1_reg64(RDREG); break;
+ case 0x02: /* CFCz */ if (RTREG) RTVAL64 = (INT32)get_cop1_creg(RDREG); break;
+ case 0x04: /* MTCz */ set_cop1_reg32(RDREG, RTVAL32); break;
+ case 0x05: /* DMTCz */ set_cop1_reg64(RDREG, RTVAL64); break;
+ case 0x06: /* CTCz */ set_cop1_creg(RDREG, RTVAL32); break;
+ case 0x08: /* BC */
+ switch ((op >> 16) & 3)
+ {
+ case 0x00: /* BCzF */ if (!GET_FCC((op >> 18) & 7)) ADDPC(SIMMVAL); break;
+ case 0x01: /* BCzT */ if (GET_FCC((op >> 18) & 7)) ADDPC(SIMMVAL); break;
+ case 0x02: /* BCzFL */ if (!GET_FCC((op >> 18) & 7)) ADDPC(SIMMVAL); else mips3.core.pc += 4; break;
+ case 0x03: /* BCzTL */ if (GET_FCC((op >> 18) & 7)) ADDPC(SIMMVAL); else mips3.core.pc += 4; break;
+ }
+ break;
+ default:
+ switch (op & 0x3f)
+ {
+ case 0x00:
+ if (IS_SINGLE(op)) /* ADD.S */
+ FDVALS_FR1 = FSVALS_FR1 + FTVALS_FR1;
+ else /* ADD.D */
+ FDVALD_FR1 = FSVALD_FR1 + FTVALD_FR1;
+ break;
+
+ case 0x01:
+ if (IS_SINGLE(op)) /* SUB.S */
+ FDVALS_FR1 = FSVALS_FR1 - FTVALS_FR1;
+ else /* SUB.D */
+ FDVALD_FR1 = FSVALD_FR1 - FTVALD_FR1;
+ break;
+
+ case 0x02:
+ if (IS_SINGLE(op)) /* MUL.S */
+ FDVALS_FR1 = FSVALS_FR1 * FTVALS_FR1;
+ else /* MUL.D */
+ FDVALD_FR1 = FSVALD_FR1 * FTVALD_FR1;
+ break;
+
+ case 0x03:
+ if (IS_SINGLE(op)) /* DIV.S */
+ FDVALS_FR1 = FSVALS_FR1 / FTVALS_FR1;
+ else /* DIV.D */
+ FDVALD_FR1 = FSVALD_FR1 / FTVALD_FR1;
+ break;
+
+ case 0x04:
+ if (IS_SINGLE(op)) /* SQRT.S */
+ FDVALS_FR1 = sqrt(FSVALS_FR1);
+ else /* SQRT.D */
+ FDVALD_FR1 = sqrt(FSVALD_FR1);
+ break;
+
+ case 0x05:
+ if (IS_SINGLE(op)) /* ABS.S */
+ FDVALS_FR1 = fabs(FSVALS_FR1);
+ else /* ABS.D */
+ FDVALD_FR1 = fabs(FSVALD_FR1);
+ break;
+
+ case 0x06:
+ if (IS_SINGLE(op)) /* MOV.S */
+ FDVALS_FR1 = FSVALS_FR1;
+ else /* MOV.D */
+ FDVALD_FR1 = FSVALD_FR1;
+ break;
+
+ case 0x07:
+ if (IS_SINGLE(op)) /* NEG.S */
+ FDVALS_FR1 = -FSVALS_FR1;
+ else /* NEG.D */
+ FDVALD_FR1 = -FSVALD_FR1;
+ break;
+
+ case 0x08:
+ if (IS_SINGLE(op)) /* ROUND.L.S */
+ {
+ double temp = FSVALS_FR1;
+ if (temp < 0)
+ temp = ceil(temp - 0.5);
+ else
+ temp = floor(temp + 0.5);
+ FDVALL_FR1 = (INT64)temp;
+ }
+ else /* ROUND.L.D */
+ {
+ double temp = FSVALD_FR1;
+ if (temp < 0)
+ temp = ceil(temp - 0.5);
+ else
+ temp = floor(temp + 0.5);
+ FDVALL_FR1 = (INT64)temp;
+ }
+ break;
+
+ case 0x09:
+ if (IS_SINGLE(op)) /* TRUNC.L.S */
+ {
+ double temp = FSVALS_FR1;
+ if (temp < 0)
+ temp = ceil(temp);
+ else
+ temp = floor(temp);
+ FDVALL_FR1 = (INT64)temp;
+ }
+ else /* TRUNC.L.D */
+ {
+ double temp = FSVALD_FR1;
+ if (temp < 0)
+ temp = ceil(temp);
+ else
+ temp = floor(temp);
+ FDVALL_FR1 = (INT64)temp;
+ }
+ break;
+
+ case 0x0a:
+ if (IS_SINGLE(op)) /* CEIL.L.S */
+ dtemp = ceil(FSVALS_FR1);
+ else /* CEIL.L.D */
+ dtemp = ceil(FSVALD_FR1);
+ FDVALL_FR1 = (INT64)dtemp;
+ break;
+
+ case 0x0b:
+ if (IS_SINGLE(op)) /* FLOOR.L.S */
+ dtemp = floor(FSVALS_FR1);
+ else /* FLOOR.L.D */
+ dtemp = floor(FSVALD_FR1);
+ FDVALL_FR1 = (INT64)dtemp;
+ break;
+
+ case 0x0c:
+ if (IS_SINGLE(op)) /* ROUND.W.S */
+ {
+ dtemp = FSVALS_FR1;
+ if (dtemp < 0)
+ dtemp = ceil(dtemp - 0.5);
+ else
+ dtemp = floor(dtemp + 0.5);
+ FDVALW_FR1 = (INT32)dtemp;
+ }
+ else /* ROUND.W.D */
+ {
+ dtemp = FSVALD_FR1;
+ if (dtemp < 0)
+ dtemp = ceil(dtemp - 0.5);
+ else
+ dtemp = floor(dtemp + 0.5);
+ FDVALW_FR1 = (INT32)dtemp;
+ }
+ break;
+
+ case 0x0d:
+ if (IS_SINGLE(op)) /* TRUNC.W.S */
+ {
+ dtemp = FSVALS_FR1;
+ if (dtemp < 0)
+ dtemp = ceil(dtemp);
+ else
+ dtemp = floor(dtemp);
+ FDVALW_FR1 = (INT32)dtemp;
+ }
+ else /* TRUNC.W.D */
+ {
+ dtemp = FSVALD_FR1;
+ if (dtemp < 0)
+ dtemp = ceil(dtemp);
+ else
+ dtemp = floor(dtemp);
+ FDVALW_FR1 = (INT32)dtemp;
+ }
+ break;
+
+ case 0x0e:
+ if (IS_SINGLE(op)) /* CEIL.W.S */
+ dtemp = ceil(FSVALS_FR1);
+ else /* CEIL.W.D */
+ dtemp = ceil(FSVALD_FR1);
+ FDVALW_FR1 = (INT32)dtemp;
+ break;
+
+ case 0x0f:
+ if (IS_SINGLE(op)) /* FLOOR.W.S */
+ dtemp = floor(FSVALS_FR1);
+ else /* FLOOR.W.D */
+ dtemp = floor(FSVALD_FR1);
+ FDVALW_FR1 = (INT32)dtemp;
+ break;
+
+ case 0x11: /* R5000 */
+ if (GET_FCC((op >> 18) & 7) == ((op >> 16) & 1))
+ {
+ if (IS_SINGLE(op)) /* MOVT/F.S */
+ FDVALS_FR1 = FSVALS_FR1;
+ else /* MOVT/F.D */
+ FDVALD_FR1 = FSVALD_FR1;
+ }
+ break;
+
+ case 0x12: /* R5000 */
+ if (RTVAL64 == 0)
+ {
+ if (IS_SINGLE(op)) /* MOVZ.S */
+ FDVALS_FR1 = FSVALS_FR1;
+ else /* MOVZ.D */
+ FDVALD_FR1 = FSVALD_FR1;
+ }
+ break;
+
+ case 0x13: /* R5000 */
+ if (RTVAL64 != 0)
+ {
+ if (IS_SINGLE(op)) /* MOVN.S */
+ FDVALS_FR1 = FSVALS_FR1;
+ else /* MOVN.D */
+ FDVALD_FR1 = FSVALD_FR1;
+ }
+ break;
+
+ case 0x15: /* R5000 */
+ if (IS_SINGLE(op)) /* RECIP.S */
+ FDVALS_FR1 = 1.0f / FSVALS_FR1;
+ else /* RECIP.D */
+ FDVALD_FR1 = 1.0 / FSVALD_FR1;
+ break;
+
+ case 0x16: /* R5000 */
+ if (IS_SINGLE(op)) /* RSQRT.S */
+ FDVALS_FR1 = 1.0f / sqrt(FSVALS_FR1);
+ else /* RSQRT.D */
+ FDVALD_FR1 = 1.0 / sqrt(FSVALD_FR1);
+ break;
+
+ case 0x20:
+ if (IS_INTEGRAL(op))
+ {
+ if (IS_SINGLE(op)) /* CVT.S.W */
+ FDVALS_FR1 = (INT32)FSVALW_FR1;
+ else /* CVT.S.L */
+ FDVALS_FR1 = (INT64)FSVALL_FR1;
+ }
+ else /* CVT.S.D */
+ FDVALS_FR1 = FSVALD_FR1;
+ break;
+
+ case 0x21:
+ if (IS_INTEGRAL(op))
+ {
+ if (IS_SINGLE(op)) /* CVT.D.W */
+ FDVALD_FR1 = (INT32)FSVALW_FR1;
+ else /* CVT.D.L */
+ FDVALD_FR1 = (INT64)FSVALL_FR1;
+ }
+ else /* CVT.D.S */
+ FDVALD_FR1 = FSVALS_FR1;
+ break;
+
+ case 0x24:
+ if (IS_SINGLE(op)) /* CVT.W.S */
+ FDVALW_FR1 = (INT32)FSVALS_FR1;
+ else
+ FDVALW_FR1 = (INT32)FSVALD_FR1;
+ break;
+
+ case 0x25:
+ if (IS_SINGLE(op)) /* CVT.L.S */
+ FDVALL_FR1 = (INT64)FSVALS_FR1;
+ else /* CVT.L.D */
+ FDVALL_FR1 = (INT64)FSVALD_FR1;
+ break;
+
+ case 0x30:
+ case 0x38:
+ if (IS_SINGLE(op)) /* C.F.S */
+ SET_FCC((op >> 8) & 7, 0);
+ else /* C.F.D */
+ SET_FCC((op >> 8) & 7, 0);
+ break;
+
+ case 0x31:
+ case 0x39:
+ if (IS_SINGLE(op)) /* C.UN.S */
+ SET_FCC((op >> 8) & 7, 0);
+ else /* C.UN.D */
+ SET_FCC((op >> 8) & 7, 0);
+ break;
+
+ case 0x32:
+ case 0x3a:
+ if (IS_SINGLE(op)) /* C.EQ.S */
+ SET_FCC((op >> 8) & 7, (FSVALS_FR1 == FTVALS_FR1));
+ else /* C.EQ.D */
+ SET_FCC((op >> 8) & 7, (FSVALD_FR1 == FTVALD_FR1));
+ break;
+
+ case 0x33:
+ case 0x3b:
+ if (IS_SINGLE(op)) /* C.UEQ.S */
+ SET_FCC((op >> 8) & 7, (FSVALS_FR1 == FTVALS_FR1));
+ else /* C.UEQ.D */
+ SET_FCC((op >> 8) & 7, (FSVALD_FR1 == FTVALD_FR1));
+ break;
+
+ case 0x34:
+ case 0x3c:
+ if (IS_SINGLE(op)) /* C.OLT.S */
+ SET_FCC((op >> 8) & 7, (FSVALS_FR1 < FTVALS_FR1));
+ else /* C.OLT.D */
+ SET_FCC((op >> 8) & 7, (FSVALD_FR1 < FTVALD_FR1));
+ break;
+
+ case 0x35:
+ case 0x3d:
+ if (IS_SINGLE(op)) /* C.ULT.S */
+ SET_FCC((op >> 8) & 7, (FSVALS_FR1 < FTVALS_FR1));
+ else /* C.ULT.D */
+ SET_FCC((op >> 8) & 7, (FSVALD_FR1 < FTVALD_FR1));
+ break;
+
+ case 0x36:
+ case 0x3e:
+ if (IS_SINGLE(op)) /* C.OLE.S */
+ SET_FCC((op >> 8) & 7, (FSVALS_FR1 <= FTVALS_FR1));
+ else /* C.OLE.D */
+ SET_FCC((op >> 8) & 7, (FSVALD_FR1 <= FTVALD_FR1));
+ break;
+
+ case 0x37:
+ case 0x3f:
+ if (IS_SINGLE(op)) /* C.ULE.S */
+ SET_FCC((op >> 8) & 7, (FSVALS_FR1 <= FTVALS_FR1));
+ else /* C.ULE.D */
+ SET_FCC((op >> 8) & 7, (FSVALD_FR1 <= FTVALD_FR1));
+ break;
+
+ default:
+ fprintf(stderr, "cop1 %X\n", op);
+ break;
+ }
+ break;
+ }
+}
+
+
+
+/***************************************************************************
+ COP1X (FPU EXTRA) EXECUTION HANDLING
+***************************************************************************/
+
+INLINE void handle_cop1x_fr0(UINT32 op)
+{
+ UINT64 temp64;
+ UINT32 temp;
+
+ if (!(SR & SR_COP1))
+ {
+ mips3.badcop_value = 1;
+ generate_exception(EXCEPTION_BADCOP, 1);
+ }
+
+ switch (op & 0x3f)
+ {
+ case 0x00: /* LWXC1 */
+ if (RWORD(RSVAL32 + RTVAL32, &temp)) FDVALW_FR0 = temp;
+ break;
+
+ case 0x01: /* LDXC1 */
+ if (RDOUBLE(RSVAL32 + RTVAL32, &temp64)) FDVALL_FR0 = temp64;
+ break;
+
+ case 0x08: /* SWXC1 */
+ WWORD(RSVAL32 + RTVAL32, get_cop1_reg32(FDREG));
+ break;
+
+ case 0x09: /* SDXC1 */
+ WDOUBLE(RSVAL32 + RTVAL32, get_cop1_reg64(FDREG));
+ break;
+
+ case 0x0f: /* PREFX */
+ break;
+
+ case 0x20: /* MADD.S */
+ FDVALS_FR0 = FSVALS_FR0 * FTVALS_FR0 + FRVALS_FR0;
+ break;
+
+ case 0x21: /* MADD.D */
+ FDVALD_FR0 = FSVALD_FR0 * FTVALD_FR0 + FRVALD_FR0;
+ break;
+
+ case 0x28: /* MSUB.S */
+ FDVALS_FR0 = FSVALS_FR0 * FTVALS_FR0 - FRVALS_FR0;
+ break;
+
+ case 0x29: /* MSUB.D */
+ FDVALD_FR0 = FSVALD_FR0 * FTVALD_FR0 - FRVALD_FR0;
+ break;
+
+ case 0x30: /* NMADD.S */
+ FDVALS_FR0 = -(FSVALS_FR0 * FTVALS_FR0 + FRVALS_FR0);
+ break;
+
+ case 0x31: /* NMADD.D */
+ FDVALD_FR0 = -(FSVALD_FR0 * FTVALD_FR0 + FRVALD_FR0);
+ break;
+
+ case 0x38: /* NMSUB.S */
+ FDVALS_FR0 = -(FSVALS_FR0 * FTVALS_FR0 - FRVALS_FR0);
+ break;
+
+ case 0x39: /* NMSUB.D */
+ FDVALD_FR0 = -(FSVALD_FR0 * FTVALD_FR0 - FRVALD_FR0);
+ break;
+
+ case 0x24: /* MADD.W */
+ case 0x25: /* MADD.L */
+ case 0x2c: /* MSUB.W */
+ case 0x2d: /* MSUB.L */
+ case 0x34: /* NMADD.W */
+ case 0x35: /* NMADD.L */
+ case 0x3c: /* NMSUB.W */
+ case 0x3d: /* NMSUB.L */
+ default:
+ fprintf(stderr, "cop1x %X\n", op);
+ break;
+ }
+}
+
+
+INLINE void handle_cop1x_fr1(UINT32 op)
+{
+ UINT64 temp64;
+ UINT32 temp;
+
+ if (!(SR & SR_COP1))
+ {
+ mips3.badcop_value = 1;
+ generate_exception(EXCEPTION_BADCOP, 1);
+ }
+
+ switch (op & 0x3f)
+ {
+ case 0x00: /* LWXC1 */
+ if (RWORD(RSVAL32 + RTVAL32, &temp)) FDVALW_FR1 = temp;
+ break;
+
+ case 0x01: /* LDXC1 */
+ if (RDOUBLE(RSVAL32 + RTVAL32, &temp64)) FDVALL_FR1 = temp64;
+ break;
+
+ case 0x08: /* SWXC1 */
+ WWORD(RSVAL32 + RTVAL32, get_cop1_reg32(FDREG));
+ break;
+
+ case 0x09: /* SDXC1 */
+ WDOUBLE(RSVAL32 + RTVAL32, get_cop1_reg64(FDREG));
+ break;
+
+ case 0x0f: /* PREFX */
+ break;
+
+ case 0x20: /* MADD.S */
+ FDVALS_FR1 = FSVALS_FR1 * FTVALS_FR1 + FRVALS_FR1;
+ break;
+
+ case 0x21: /* MADD.D */
+ FDVALD_FR1 = FSVALD_FR1 * FTVALD_FR1 + FRVALD_FR1;
+ break;
+
+ case 0x28: /* MSUB.S */
+ FDVALS_FR1 = FSVALS_FR1 * FTVALS_FR1 - FRVALS_FR1;
+ break;
+
+ case 0x29: /* MSUB.D */
+ FDVALD_FR1 = FSVALD_FR1 * FTVALD_FR1 - FRVALD_FR1;
+ break;
+
+ case 0x30: /* NMADD.S */
+ FDVALS_FR1 = -(FSVALS_FR1 * FTVALS_FR1 + FRVALS_FR1);
+ break;
+
+ case 0x31: /* NMADD.D */
+ FDVALD_FR1 = -(FSVALD_FR1 * FTVALD_FR1 + FRVALD_FR1);
+ break;
+
+ case 0x38: /* NMSUB.S */
+ FDVALS_FR1 = -(FSVALS_FR1 * FTVALS_FR1 - FRVALS_FR1);
+ break;
+
+ case 0x39: /* NMSUB.D */
+ FDVALD_FR1 = -(FSVALD_FR1 * FTVALD_FR1 - FRVALD_FR1);
+ break;
+
+ case 0x24: /* MADD.W */
+ case 0x25: /* MADD.L */
+ case 0x2c: /* MSUB.W */
+ case 0x2d: /* MSUB.L */
+ case 0x34: /* NMADD.W */
+ case 0x35: /* NMADD.L */
+ case 0x3c: /* NMSUB.W */
+ case 0x3d: /* NMSUB.L */
+ default:
+ fprintf(stderr, "cop1x %X\n", op);
+ break;
+ }
+}
+
+
+
+/***************************************************************************
+ COP2 (CUSTOM) EXECUTION HANDLING
+***************************************************************************/
+
+INLINE UINT64 get_cop2_reg(int idx)
+{
+ return mips3.core.cpr[2][idx];
+}
+
+INLINE void set_cop2_reg(int idx, UINT64 val)
+{
+ mips3.core.cpr[2][idx] = val;
+}
+
+INLINE UINT64 get_cop2_creg(int idx)
+{
+ return mips3.core.ccr[2][idx];
+}
+
+INLINE void set_cop2_creg(int idx, UINT64 val)
+{
+ mips3.core.ccr[2][idx] = val;
+}
+
+INLINE void handle_cop2(UINT32 op)
+{
+ if (!(SR & SR_COP2))
+ {
+ mips3.badcop_value = 2;
+ generate_exception(EXCEPTION_BADCOP, 1);
+ }
+
+ switch (RSREG)
+ {
+ case 0x00: /* MFCz */ if (RTREG) RTVAL64 = (INT32)get_cop2_reg(RDREG); break;
+ case 0x01: /* DMFCz */ if (RTREG) RTVAL64 = get_cop2_reg(RDREG); break;
+ case 0x02: /* CFCz */ if (RTREG) RTVAL64 = (INT32)get_cop2_creg(RDREG); break;
+ case 0x04: /* MTCz */ set_cop2_reg(RDREG, RTVAL32); break;
+ case 0x05: /* DMTCz */ set_cop2_reg(RDREG, RTVAL64); break;
+ case 0x06: /* CTCz */ set_cop2_creg(RDREG, RTVAL32); break;
+ case 0x08: /* BC */
+ switch (RTREG)
+ {
+ case 0x00: /* BCzF */ if (!mips3.cf[2]) ADDPC(SIMMVAL); break;
+ case 0x01: /* BCzF */ if (mips3.cf[2]) ADDPC(SIMMVAL); break;
+ case 0x02: /* BCzFL */ invalid_instruction(op); break;
+ case 0x03: /* BCzTL */ invalid_instruction(op); break;
+ default: invalid_instruction(op); break;
+ }
+ break;
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ case 0x13:
+ case 0x14:
+ case 0x15:
+ case 0x16:
+ case 0x17:
+ case 0x18:
+ case 0x19:
+ case 0x1a:
+ case 0x1b:
+ case 0x1c:
+ case 0x1d:
+ case 0x1e:
+ case 0x1f: /* COP */ invalid_instruction(op); break;
+ default: invalid_instruction(op); break;
+ }
+}
+
+
+
+/***************************************************************************
+ CORE EXECUTION LOOP
+***************************************************************************/
+
+CPU_EXECUTE( mips3 )
+{
+ /* count cycles and interrupt cycles */
+ mips3.core.icount -= mips3.interrupt_cycles;
+ mips3.interrupt_cycles = 0;
+
+ /* update timers & such */
+ mips3com_update_cycle_counting(&mips3.core);
+
+ /* check for IRQs */
+ check_irqs();
+
+ /* core execution loop */
+ do
+ {
+ UINT32 op;
+ UINT64 temp64 = 0;
+ UINT32 temp;
+
+ /* debugging */
+ mips3.ppc = mips3.core.pc;
+ debugger_instruction_hook(device, mips3.core.pc);
+
+ /* instruction fetch */
+ if(!RWORD(mips3.core.pc, &op))
+ {
+ continue;
+ }
+
+ /* adjust for next PC */
+ if (mips3.nextpc != ~0)
+ {
+ mips3.core.pc = mips3.nextpc;
+ mips3.nextpc = ~0;
+ }
+ else
+ mips3.core.pc += 4;
+
+ /* parse the instruction */
+ switch (op >> 26)
+ {
+ case 0x00: /* SPECIAL */
+ switch (op & 63)
+ {
+ case 0x00: /* SLL */ if (RDREG) RDVAL64 = (INT32)(RTVAL32 << SHIFT); break;
+ case 0x01: /* MOVF - R5000*/if (RDREG && GET_FCC((op >> 18) & 7) == ((op >> 16) & 1)) RDVAL64 = RSVAL64; break;
+ case 0x02: /* SRL */ if (RDREG) RDVAL64 = (INT32)(RTVAL32 >> SHIFT); break;
+ case 0x03: /* SRA */ if (RDREG) RDVAL64 = (INT32)RTVAL32 >> SHIFT; break;
+ case 0x04: /* SLLV */ if (RDREG) RDVAL64 = (INT32)(RTVAL32 << (RSVAL32 & 31)); break;
+ case 0x06: /* SRLV */ if (RDREG) RDVAL64 = (INT32)(RTVAL32 >> (RSVAL32 & 31)); break;
+ case 0x07: /* SRAV */ if (RDREG) RDVAL64 = (INT32)RTVAL32 >> (RSVAL32 & 31); break;
+ case 0x08: /* JR */ SETPC(RSVAL32); break;
+ case 0x09: /* JALR */ SETPCL(RSVAL32,RDREG); break;
+ case 0x0a: /* MOVZ - R5000 */if (RTVAL64 == 0) { if (RDREG) RDVAL64 = RSVAL64; } break;
+ case 0x0b: /* MOVN - R5000 */if (RTVAL64 != 0) { if (RDREG) RDVAL64 = RSVAL64; } break;
+ case 0x0c: /* SYSCALL */ generate_exception(EXCEPTION_SYSCALL, 1); break;
+ case 0x0d: /* BREAK */ generate_exception(EXCEPTION_BREAK, 1); break;
+ case 0x0f: /* SYNC */ /* effective no-op */ break;
+ case 0x10: /* MFHI */ if (RDREG) RDVAL64 = HIVAL64; break;
+ case 0x11: /* MTHI */ HIVAL64 = RSVAL64; break;
+ case 0x12: /* MFLO */ if (RDREG) RDVAL64 = LOVAL64; break;
+ case 0x13: /* MTLO */ LOVAL64 = RSVAL64; break;
+ case 0x14: /* DSLLV */ if (RDREG) RDVAL64 = RTVAL64 << (RSVAL32 & 63); break;
+ case 0x16: /* DSRLV */ if (RDREG) RDVAL64 = RTVAL64 >> (RSVAL32 & 63); break;
+ case 0x17: /* DSRAV */ if (RDREG) RDVAL64 = (INT64)RTVAL64 >> (RSVAL32 & 63); break;
+ case 0x18: /* MULT */
+ temp64 = (INT64)(INT32)RSVAL32 * (INT64)(INT32)RTVAL32;
+ LOVAL64 = (INT32)temp64;
+ HIVAL64 = (INT32)(temp64 >> 32);
+ mips3.core.icount -= 3;
+ break;
+ case 0x19: /* MULTU */
+ temp64 = (UINT64)RSVAL32 * (UINT64)RTVAL32;
+ LOVAL64 = (INT32)temp64;
+ HIVAL64 = (INT32)(temp64 >> 32);
+ mips3.core.icount -= 3;
+ break;
+ case 0x1a: /* DIV */
+ if (RTVAL32)
+ {
+ LOVAL64 = (INT32)((INT32)RSVAL32 / (INT32)RTVAL32);
+ HIVAL64 = (INT32)((INT32)RSVAL32 % (INT32)RTVAL32);
+ }
+ mips3.core.icount -= 35;
+ break;
+ case 0x1b: /* DIVU */
+ if (RTVAL32)
+ {
+ LOVAL64 = (INT32)(RSVAL32 / RTVAL32);
+ HIVAL64 = (INT32)(RSVAL32 % RTVAL32);
+ }
+ mips3.core.icount -= 35;
+ break;
+ case 0x1c: /* DMULT */
+ temp64 = (INT64)RSVAL64 * (INT64)RTVAL64;
+ LOVAL64 = temp64;
+ HIVAL64 = (INT64)temp64 >> 63;
+ mips3.core.icount -= 7;
+ break;
+ case 0x1d: /* DMULTU */
+ temp64 = (UINT64)RSVAL64 * (UINT64)RTVAL64;
+ LOVAL64 = temp64;
+ HIVAL64 = 0;
+ mips3.core.icount -= 7;
+ break;
+ case 0x1e: /* DDIV */
+ if (RTVAL64)
+ {
+ LOVAL64 = (INT64)RSVAL64 / (INT64)RTVAL64;
+ HIVAL64 = (INT64)RSVAL64 % (INT64)RTVAL64;
+ }
+ mips3.core.icount -= 67;
+ break;
+ case 0x1f: /* DDIVU */
+ if (RTVAL64)
+ {
+ LOVAL64 = RSVAL64 / RTVAL64;
+ HIVAL64 = RSVAL64 % RTVAL64;
+ }
+ mips3.core.icount -= 67;
+ break;
+ case 0x20: /* ADD */
+ if (ENABLE_OVERFLOWS && RSVAL32 > ~RTVAL32) generate_exception(EXCEPTION_OVERFLOW, 1);
+ else if (RDREG) RDVAL64 = (INT32)(RSVAL32 + RTVAL32);
+ break;
+ case 0x21: /* ADDU */ if (RDREG) RDVAL64 = (INT32)(RSVAL32 + RTVAL32); break;
+ case 0x22: /* SUB */
+ if (ENABLE_OVERFLOWS && RSVAL32 < RTVAL32) generate_exception(EXCEPTION_OVERFLOW, 1);
+ else if (RDREG) RDVAL64 = (INT32)(RSVAL32 - RTVAL32);
+ break;
+ case 0x23: /* SUBU */ if (RDREG) RDVAL64 = (INT32)(RSVAL32 - RTVAL32); break;
+ case 0x24: /* AND */ if (RDREG) RDVAL64 = RSVAL64 & RTVAL64; break;
+ case 0x25: /* OR */ if (RDREG) RDVAL64 = RSVAL64 | RTVAL64; break;
+ case 0x26: /* XOR */ if (RDREG) RDVAL64 = RSVAL64 ^ RTVAL64; break;
+ case 0x27: /* NOR */ if (RDREG) RDVAL64 = ~(RSVAL64 | RTVAL64); break;
+ case 0x2a: /* SLT */ if (RDREG) RDVAL64 = (INT64)RSVAL64 < (INT64)RTVAL64; break;
+ case 0x2b: /* SLTU */ if (RDREG) RDVAL64 = (UINT64)RSVAL64 < (UINT64)RTVAL64; break;
+ case 0x2c: /* DADD */
+ if (ENABLE_OVERFLOWS && RSVAL64 > ~RTVAL64) generate_exception(EXCEPTION_OVERFLOW, 1);
+ else if (RDREG) RDVAL64 = RSVAL64 + RTVAL64;
+ break;
+ case 0x2d: /* DADDU */ if (RDREG) RDVAL64 = RSVAL64 + RTVAL64; break;
+ case 0x2e: /* DSUB */
+ if (ENABLE_OVERFLOWS && RSVAL64 < RTVAL64) generate_exception(EXCEPTION_OVERFLOW, 1);
+ else if (RDREG) RDVAL64 = RSVAL64 - RTVAL64;
+ break;
+ case 0x2f: /* DSUBU */ if (RDREG) RDVAL64 = RSVAL64 - RTVAL64; break;
+ case 0x30: /* TGE */ if ((INT64)RSVAL64 >= (INT64)RTVAL64) generate_exception(EXCEPTION_TRAP, 1); break;
+ case 0x31: /* TGEU */ if (RSVAL64 >= RTVAL64) generate_exception(EXCEPTION_TRAP, 1); break;
+ case 0x32: /* TLT */ if ((INT64)RSVAL64 < (INT64)RTVAL64) generate_exception(EXCEPTION_TRAP, 1); break;
+ case 0x33: /* TLTU */ if (RSVAL64 < RTVAL64) generate_exception(EXCEPTION_TRAP, 1); break;
+ case 0x34: /* TEQ */ if (RSVAL64 == RTVAL64) generate_exception(EXCEPTION_TRAP, 1); break;
+ case 0x36: /* TNE */ if (RSVAL64 != RTVAL64) generate_exception(EXCEPTION_TRAP, 1); break;
+ case 0x38: /* DSLL */ if (RDREG) RDVAL64 = RTVAL64 << SHIFT; break;
+ case 0x3a: /* DSRL */ if (RDREG) RDVAL64 = RTVAL64 >> SHIFT; break;
+ case 0x3b: /* DSRA */ if (RDREG) RDVAL64 = (INT64)RTVAL64 >> SHIFT; break;
+ case 0x3c: /* DSLL32 */ if (RDREG) RDVAL64 = RTVAL64 << (SHIFT + 32); break;
+ case 0x3e: /* DSRL32 */ if (RDREG) RDVAL64 = RTVAL64 >> (SHIFT + 32); break;
+ case 0x3f: /* DSRA32 */ if (RDREG) RDVAL64 = (INT64)RTVAL64 >> (SHIFT + 32); break;
+ default: /* ??? */ invalid_instruction(op); break;
+ }
+ break;
+
+ case 0x01: /* REGIMM */
+ switch (RTREG)
+ {
+ case 0x00: /* BLTZ */ if ((INT64)RSVAL64 < 0) ADDPC(SIMMVAL); break;
+ case 0x01: /* BGEZ */ if ((INT64)RSVAL64 >= 0) ADDPC(SIMMVAL); break;
+ case 0x02: /* BLTZL */ if ((INT64)RSVAL64 < 0) ADDPC(SIMMVAL); else mips3.core.pc += 4; break;
+ case 0x03: /* BGEZL */ if ((INT64)RSVAL64 >= 0) ADDPC(SIMMVAL); else mips3.core.pc += 4; break;
+ case 0x08: /* TGEI */ if ((INT64)RSVAL64 >= SIMMVAL) generate_exception(EXCEPTION_TRAP, 1); break;
+ case 0x09: /* TGEIU */ if (RSVAL64 >= SIMMVAL) generate_exception(EXCEPTION_TRAP, 1); break;
+ case 0x0a: /* TLTI */ if ((INT64)RSVAL64 < SIMMVAL) generate_exception(EXCEPTION_TRAP, 1); break;
+ case 0x0b: /* TLTIU */ if (RSVAL64 >= SIMMVAL) generate_exception(EXCEPTION_TRAP, 1); break;
+ case 0x0c: /* TEQI */ if (RSVAL64 == SIMMVAL) generate_exception(EXCEPTION_TRAP, 1); break;
+ case 0x0e: /* TNEI */ if (RSVAL64 != SIMMVAL) generate_exception(EXCEPTION_TRAP, 1); break;
+ case 0x10: /* BLTZAL */ if ((INT64)RSVAL64 < 0) ADDPCL(SIMMVAL,31); break;
+ case 0x11: /* BGEZAL */ if ((INT64)RSVAL64 >= 0) ADDPCL(SIMMVAL,31); break;
+ case 0x12: /* BLTZALL */ if ((INT64)RSVAL64 < 0) ADDPCL(SIMMVAL,31) else mips3.core.pc += 4; break;
+ case 0x13: /* BGEZALL */ if ((INT64)RSVAL64 >= 0) ADDPCL(SIMMVAL,31) else mips3.core.pc += 4; break;
+ default: /* ??? */ invalid_instruction(op); break;
+ }
+ break;
+
+ case 0x02: /* J */ ABSPC(LIMMVAL); break;
+ case 0x03: /* JAL */ ABSPCL(LIMMVAL,31); break;
+ case 0x04: /* BEQ */ if (RSVAL64 == RTVAL64) ADDPC(SIMMVAL); break;
+ case 0x05: /* BNE */ if (RSVAL64 != RTVAL64) ADDPC(SIMMVAL); break;
+ case 0x06: /* BLEZ */ if ((INT64)RSVAL64 <= 0) ADDPC(SIMMVAL); break;
+ case 0x07: /* BGTZ */ if ((INT64)RSVAL64 > 0) ADDPC(SIMMVAL); break;
+ case 0x08: /* ADDI */
+ if (ENABLE_OVERFLOWS && RSVAL32 > ~SIMMVAL) generate_exception(EXCEPTION_OVERFLOW, 1);
+ else if (RTREG) RTVAL64 = (INT32)(RSVAL32 + SIMMVAL);
+ break;
+ case 0x09: /* ADDIU */ if (RTREG) RTVAL64 = (INT32)(RSVAL32 + SIMMVAL); break;
+ case 0x0a: /* SLTI */ if (RTREG) RTVAL64 = (INT64)RSVAL64 < (INT64)SIMMVAL; break;
+ case 0x0b: /* SLTIU */ if (RTREG) RTVAL64 = (UINT64)RSVAL64 < (UINT64)SIMMVAL; break;
+ case 0x0c: /* ANDI */ if (RTREG) RTVAL64 = RSVAL64 & UIMMVAL; break;
+ case 0x0d: /* ORI */ if (RTREG) RTVAL64 = RSVAL64 | UIMMVAL; break;
+ case 0x0e: /* XORI */ if (RTREG) RTVAL64 = RSVAL64 ^ UIMMVAL; break;
+ case 0x0f: /* LUI */ if (RTREG) RTVAL64 = (INT32)(UIMMVAL << 16); break;
+ case 0x10: /* COP0 */ handle_cop0(op); break;
+ case 0x11: /* COP1 */ if (IS_FR0) handle_cop1_fr0(op); else handle_cop1_fr1(op); break;
+ case 0x12: /* COP2 */ handle_cop2(op); break;
+ case 0x13: /* COP1X - R5000 */if (IS_FR0) handle_cop1x_fr0(op); else handle_cop1x_fr1(op); break;
+ case 0x14: /* BEQL */ if (RSVAL64 == RTVAL64) ADDPC(SIMMVAL); else mips3.core.pc += 4; break;
+ case 0x15: /* BNEL */ if (RSVAL64 != RTVAL64) ADDPC(SIMMVAL); else mips3.core.pc += 4; break;
+ case 0x16: /* BLEZL */ if ((INT64)RSVAL64 <= 0) ADDPC(SIMMVAL); else mips3.core.pc += 4; break;
+ case 0x17: /* BGTZL */ if ((INT64)RSVAL64 > 0) ADDPC(SIMMVAL); else mips3.core.pc += 4; break;
+ case 0x18: /* DADDI */
+ if (ENABLE_OVERFLOWS && RSVAL64 > ~SIMMVAL) generate_exception(EXCEPTION_OVERFLOW, 1);
+ else if (RTREG) RTVAL64 = RSVAL64 + (INT64)SIMMVAL;
+ break;
+ case 0x19: /* DADDIU */ if (RTREG) RTVAL64 = RSVAL64 + (UINT64)SIMMVAL; break;
+ case 0x1a: /* LDL */ (*mips3.ldl)(op); break;
+ case 0x1b: /* LDR */ (*mips3.ldr)(op); break;
+ case 0x1c: /* IDT-specific opcodes: mad/madu/mul on R4640/4650, msub on RC32364 */
+ switch (op & 0x1f)
+ {
+ case 2: /* MUL */
+ RDVAL64 = (INT32)((INT32)RSVAL32 * (INT32)RTVAL32);
+ mips3.core.icount -= 3;
+ break;
+ default: invalid_instruction(op);
+ }
+ break;
+ case 0x20: /* LB */ if (RBYTE(SIMMVAL+RSVAL32, &temp) && RTREG) RTVAL64 = (INT8)temp; break;
+ case 0x21: /* LH */ if (RHALF(SIMMVAL+RSVAL32, &temp) && RTREG) RTVAL64 = (INT16)temp; break;
+ case 0x22: /* LWL */ (*mips3.lwl)(op); break;
+ case 0x23: /* LW */ if (RWORD(SIMMVAL+RSVAL32, &temp) && RTREG) RTVAL64 = (INT32)temp; break;
+ case 0x24: /* LBU */ if (RBYTE(SIMMVAL+RSVAL32, &temp) && RTREG) RTVAL64 = (UINT8)temp; break;
+ case 0x25: /* LHU */ if (RHALF(SIMMVAL+RSVAL32, &temp) && RTREG) RTVAL64 = (UINT16)temp; break;
+ case 0x26: /* LWR */ (*mips3.lwr)(op); break;
+ case 0x27: /* LWU */ if (RWORD(SIMMVAL+RSVAL32, &temp) && RTREG) RTVAL64 = (UINT32)temp; break;
+ case 0x28: /* SB */ WBYTE(SIMMVAL+RSVAL32, RTVAL32); break;
+ case 0x29: /* SH */ WHALF(SIMMVAL+RSVAL32, RTVAL32); break;
+ case 0x2a: /* SWL */ (*mips3.swl)(op); break;
+ case 0x2b: /* SW */ WWORD(SIMMVAL+RSVAL32, RTVAL32); break;
+ case 0x2c: /* SDL */ (*mips3.sdl)(op); break;
+ case 0x2d: /* SDR */ (*mips3.sdr)(op); break;
+ case 0x2e: /* SWR */ (*mips3.swr)(op); break;
+ case 0x2f: /* CACHE */ /* effective no-op */ break;
+ case 0x30: /* LL */ if (RWORD(SIMMVAL+RSVAL32, &temp) && RTREG) RTVAL64 = (UINT32)temp; mips3.ll_value = RTVAL32; break;
+ case 0x31: /* LWC1 */ if (RWORD(SIMMVAL+RSVAL32, &temp)) set_cop1_reg32(RTREG, temp); break;
+ case 0x32: /* LWC2 */ if (RWORD(SIMMVAL+RSVAL32, &temp)) set_cop2_reg(RTREG, temp); break;
+ case 0x33: /* PREF */ /* effective no-op */ break;
+ case 0x34: /* LLD */ if (RDOUBLE(SIMMVAL+RSVAL32, &temp64) && RTREG) RTVAL64 = temp64; mips3.lld_value = temp64; break;
+ case 0x35: /* LDC1 */ if (RDOUBLE(SIMMVAL+RSVAL32, &temp64)) set_cop1_reg64(RTREG, temp64); break;
+ case 0x36: /* LDC2 */ if (RDOUBLE(SIMMVAL+RSVAL32, &temp64)) set_cop2_reg(RTREG, temp64); break;
+ case 0x37: /* LD */ if (RDOUBLE(SIMMVAL+RSVAL32, &temp64) && RTREG) RTVAL64 = temp64; break;
+ case 0x38: /* SC */ if (RWORD(SIMMVAL+RSVAL32, &temp) && RTREG)
+ {
+ if (temp == mips3.ll_value)
+ {
+ WWORD(SIMMVAL+RSVAL32, RTVAL32);
+ RTVAL64 = (UINT32)1;
+ }
+ else
+ {
+ RTVAL64 = (UINT32)0;
+ }
+ }
+ break;
+ case 0x39: /* SWC1 */ WWORD(SIMMVAL+RSVAL32, get_cop1_reg32(RTREG)); break;
+ case 0x3a: /* SWC2 */ WWORD(SIMMVAL+RSVAL32, get_cop2_reg(RTREG)); break;
+ case 0x3b: /* SWC3 */ invalid_instruction(op); break;
+ case 0x3c: /* SCD */ if (RDOUBLE(SIMMVAL+RSVAL32, &temp64) && RTREG)
+ {
+ if (temp64 == mips3.lld_value)
+ {
+ WDOUBLE(SIMMVAL+RSVAL32, RTVAL64);
+ RTVAL64 = 1;
+ }
+ else
+ {
+ RTVAL64 = 0;
+ }
+ }
+ break;
+ case 0x3d: /* SDC1 */ WDOUBLE(SIMMVAL+RSVAL32, get_cop1_reg64(RTREG)); break;
+ case 0x3e: /* SDC2 */ WDOUBLE(SIMMVAL+RSVAL32, get_cop2_reg(RTREG)); break;
+ case 0x3f: /* SD */ WDOUBLE(SIMMVAL+RSVAL32, RTVAL64); break;
+ default: /* ??? */ invalid_instruction(op); break;
+ }
+ mips3.core.icount--;
+
+ } while (mips3.core.icount > 0 || mips3.nextpc != ~0);
+
+ mips3.core.icount -= mips3.interrupt_cycles;
+ mips3.interrupt_cycles = 0;
+}
+
+
+
+/***************************************************************************
+ COMPLEX OPCODE IMPLEMENTATIONS
+***************************************************************************/
+
+static void lwl_be(UINT32 op)
+{
+ offs_t offs = SIMMVAL + RSVAL32;
+ int shift = 8 * (offs & 3);
+ UINT32 mask = 0xffffffffUL << shift;
+ UINT32 temp;
+
+ if (RWORD_MASKED(offs & ~3, &temp, mask >> shift) && RTREG)
+ RTVAL64 = (INT32)((RTVAL32 & ~mask) | (temp << shift));
+}
+
+static void lwr_be(UINT32 op)
+{
+ offs_t offs = SIMMVAL + RSVAL32;
+ int shift = 8 * (~offs & 3);
+ UINT32 mask = 0xffffffffUL >> shift;
+ UINT32 temp;
+
+ if (RWORD_MASKED(offs & ~3, &temp, mask << shift) && RTREG)
+ RTVAL64 = (INT32)((RTVAL32 & ~mask) | (temp >> shift));
+}
+
+static void ldl_be(UINT32 op)
+{
+ offs_t offs = SIMMVAL + RSVAL32;
+ int shift = 8 * (offs & 7);
+ UINT64 mask = U64(0xffffffffffffffff) << shift;
+ UINT64 temp;
+
+ if (RDOUBLE_MASKED(offs & ~7, &temp, mask >> shift) && RTREG)
+ RTVAL64 = (RTVAL64 & ~mask) | (temp << shift);
+}
+
+static void ldr_be(UINT32 op)
+{
+ offs_t offs = SIMMVAL + RSVAL32;
+ int shift = 8 * (~offs & 7);
+ UINT64 mask = U64(0xffffffffffffffff) >> shift;
+ UINT64 temp;
+
+ if (RDOUBLE_MASKED(offs & ~7, &temp, mask << shift) && RTREG)
+ RTVAL64 = (RTVAL64 & ~mask) | (temp >> shift);
+}
+
+static void swl_be(UINT32 op)
+{
+ offs_t offs = SIMMVAL + RSVAL32;
+ int shift = 8 * (offs & 3);
+ UINT32 mask = 0xffffffffUL >> shift;
+ WWORD_MASKED(offs & ~3, RTVAL32 >> shift, mask);
+}
+
+static void swr_be(UINT32 op)
+{
+ offs_t offs = SIMMVAL + RSVAL32;
+ int shift = 8 * (~offs & 3);
+ UINT32 mask = 0xffffffffUL << shift;
+ WWORD_MASKED(offs & ~3, RTVAL32 << shift, mask);
+}
+
+static void sdl_be(UINT32 op)
+{
+ offs_t offs = SIMMVAL + RSVAL32;
+ int shift = 8 * (offs & 7);
+ UINT64 mask = U64(0xffffffffffffffff) >> shift;
+ WDOUBLE_MASKED(offs & ~7, RTVAL64 >> shift, mask);
+}
+
+static void sdr_be(UINT32 op)
+{
+ offs_t offs = SIMMVAL + RSVAL32;
+ int shift = 8 * (~offs & 7);
+ UINT64 mask = U64(0xffffffffffffffff) << shift;
+ WDOUBLE_MASKED(offs & ~7, RTVAL64 << shift, mask);
+}
+
+
+
+static void lwl_le(UINT32 op)
+{
+ offs_t offs = SIMMVAL + RSVAL32;
+ int shift = 8 * (~offs & 3);
+ UINT32 mask = 0xffffffffUL << shift;
+ UINT32 temp;
+
+ if (RWORD_MASKED(offs & ~3, &temp, mask >> shift) && RTREG)
+ RTVAL64 = (INT32)((RTVAL32 & ~mask) | (temp << shift));
+}
+
+static void lwr_le(UINT32 op)
+{
+ offs_t offs = SIMMVAL + RSVAL32;
+ int shift = 8 * (offs & 3);
+ UINT32 mask = 0xffffffffUL >> shift;
+ UINT32 temp;
+
+ if (RWORD_MASKED(offs & ~3, &temp, mask << shift) && RTREG)
+ RTVAL64 = (INT32)((RTVAL32 & ~mask) | (temp >> shift));
+}
+
+static void ldl_le(UINT32 op)
+{
+ offs_t offs = SIMMVAL + RSVAL32;
+ int shift = 8 * (~offs & 7);
+ UINT64 mask = U64(0xffffffffffffffff) << shift;
+ UINT64 temp;
+
+ if (RDOUBLE_MASKED(offs & ~7, &temp, mask >> shift) && RTREG)
+ RTVAL64 = (RTVAL64 & ~mask) | (temp << shift);
+}
+
+static void ldr_le(UINT32 op)
+{
+ offs_t offs = SIMMVAL + RSVAL32;
+ int shift = 8 * (offs & 7);
+ UINT64 mask = U64(0xffffffffffffffff) >> shift;
+ UINT64 temp;
+
+ if (RDOUBLE_MASKED(offs & ~7, &temp, mask << shift) && RTREG)
+ RTVAL64 = (RTVAL64 & ~mask) | (temp >> shift);
+}
+
+static void swl_le(UINT32 op)
+{
+ offs_t offs = SIMMVAL + RSVAL32;
+ int shift = 8 * (~offs & 3);
+ UINT32 mask = 0xffffffffUL >> shift;
+ WWORD_MASKED(offs & ~3, RTVAL32 >> shift, mask);
+}
+
+static void swr_le(UINT32 op)
+{
+ offs_t offs = SIMMVAL + RSVAL32;
+ int shift = 8 * (offs & 3);
+ UINT32 mask = 0xffffffffUL << shift;
+ WWORD_MASKED(offs & ~3, RTVAL32 << shift, mask);
+}
+
+static void sdl_le(UINT32 op)
+{
+ offs_t offs = SIMMVAL + RSVAL32;
+ int shift = 8 * (~offs & 7);
+ UINT64 mask = U64(0xffffffffffffffff) >> shift;
+ WDOUBLE_MASKED(offs & ~7, RTVAL64 >> shift, mask);
+}
+
+static void sdr_le(UINT32 op)
+{
+ offs_t offs = SIMMVAL + RSVAL32;
+ int shift = 8 * (offs & 7);
+ UINT64 mask = U64(0xffffffffffffffff) << shift;
+ WDOUBLE_MASKED(offs & ~7, RTVAL64 << shift, mask);
+}
+
+
+
+/***************************************************************************
+ GENERIC GET/SET INFO
+***************************************************************************/
+
+static CPU_SET_INFO( mips3 )
+{
+ /* everything is handled generically here */
+ mips3com_set_info(&mips3.core, state, info);
+}
+
+
+static CPU_GET_INFO( mips3 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(mips3); break;
+ case CPUINFO_INT_PREVIOUSPC: info->i = mips3.ppc; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(mips3); break;
+ case CPUINFO_FCT_INIT: /* provided per-CPU */ break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(mips3); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(mips3); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(mips3); break;
+ case CPUINFO_FCT_TRANSLATE: info->translate = CPU_TRANSLATE_NAME(mips3); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+
+ /* --- everything else is handled generically --- */
+ default: mips3com_get_info(&mips3.core, state, info); break;
+ }
+}
+
+
+
+/***************************************************************************
+ NEC VR4300 VARIANTS
+***************************************************************************/
+
+// NEC VR4300 series is MIPS III with 32-bit address bus and slightly custom COP0/TLB
+static CPU_INIT( vr4300be )
+{
+ mips3com_init(&mips3.core, MIPS3_TYPE_VR4300, TRUE, device, irqcallback);
+ mips3.tlb_table = vtlb_table(mips3.core.vtlb);
+}
+
+static CPU_INIT( vr4300le )
+{
+ mips3com_init(&mips3.core, MIPS3_TYPE_VR4300, FALSE, device, irqcallback);
+ mips3.tlb_table = vtlb_table(mips3.core.vtlb);
+}
+
+CPU_GET_INFO( vr4300be )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(vr4300be); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "VR4300 (big)"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(mips3); break;
+ }
+}
+
+CPU_GET_INFO( vr4300le )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(vr4300le); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "VR4300 (little)"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(mips3); break;
+ }
+}
+
+// VR4310 = VR4300 with different speed bin
+CPU_GET_INFO( vr4310be )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(vr4300be); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "VR4310 (big)"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(mips3); break;
+ }
+}
+
+CPU_GET_INFO( vr4310le )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(vr4300le); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "VR4310 (little)"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(mips3); break;
+ }
+}
+
+
+/***************************************************************************
+ R4600 VARIANTS
+***************************************************************************/
+
+static CPU_INIT( r4600be )
+{
+ mips3com_init(&mips3.core, MIPS3_TYPE_R4600, TRUE, device, irqcallback);
+ mips3.tlb_table = vtlb_table(mips3.core.vtlb);
+}
+
+static CPU_INIT( r4600le )
+{
+ mips3com_init(&mips3.core, MIPS3_TYPE_R4600, FALSE, device, irqcallback);
+ mips3.tlb_table = vtlb_table(mips3.core.vtlb);
+}
+
+CPU_GET_INFO( r4600be )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(r4600be); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "R4600 (big)"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(mips3); break;
+ }
+}
+
+CPU_GET_INFO( r4600le )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(r4600le); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "R4600 (little)"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(mips3); break;
+ }
+}
+
+
+
+/***************************************************************************
+ R4650 VARIANTS
+***************************************************************************/
+
+static CPU_INIT( r4650be )
+{
+ mips3com_init(&mips3.core, MIPS3_TYPE_R4650, TRUE, device, irqcallback);
+ mips3.tlb_table = vtlb_table(mips3.core.vtlb);
+}
+
+static CPU_INIT( r4650le )
+{
+ mips3com_init(&mips3.core, MIPS3_TYPE_R4650, FALSE, device, irqcallback);
+ mips3.tlb_table = vtlb_table(mips3.core.vtlb);
+}
+
+CPU_GET_INFO( r4650be )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(r4650be); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "IDT R4650 (big)"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(mips3); break;
+ }
+}
+
+CPU_GET_INFO( r4650le )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(r4650le); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "IDT R4650 (little)"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(mips3); break;
+ }
+}
+
+
+
+/***************************************************************************
+ R4700 VARIANTS
+***************************************************************************/
+
+static CPU_INIT( r4700be )
+{
+ mips3com_init(&mips3.core, MIPS3_TYPE_R4700, TRUE, device, irqcallback);
+ mips3.tlb_table = vtlb_table(mips3.core.vtlb);
+}
+
+static CPU_INIT( r4700le )
+{
+ mips3com_init(&mips3.core, MIPS3_TYPE_R4700, FALSE, device, irqcallback);
+ mips3.tlb_table = vtlb_table(mips3.core.vtlb);
+}
+
+CPU_GET_INFO( r4700be )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(r4700be); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "R4700 (big)"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(mips3); break;
+ }
+}
+
+
+CPU_GET_INFO( r4700le )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(r4700le); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "R4700 (little)"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(mips3); break;
+ }
+}
+
+
+
+/***************************************************************************
+ R5000 VARIANTS
+***************************************************************************/
+
+static CPU_INIT( r5000be )
+{
+ mips3com_init(&mips3.core, MIPS3_TYPE_R5000, TRUE, device, irqcallback);
+ mips3.tlb_table = vtlb_table(mips3.core.vtlb);
+}
+
+static CPU_INIT( r5000le )
+{
+ mips3com_init(&mips3.core, MIPS3_TYPE_R5000, FALSE, device, irqcallback);
+ mips3.tlb_table = vtlb_table(mips3.core.vtlb);
+}
+
+CPU_GET_INFO( r5000be )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(r5000be); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "R5000 (big)"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(mips3); break;
+ }
+}
+
+CPU_GET_INFO( r5000le )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(r5000le); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "R5000 (little)"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(mips3); break;
+ }
+}
+
+
+
+/***************************************************************************
+ QED5271 VARIANTS
+***************************************************************************/
+
+static CPU_INIT( qed5271be )
+{
+ mips3com_init(&mips3.core, MIPS3_TYPE_QED5271, TRUE, device, irqcallback);
+ mips3.tlb_table = vtlb_table(mips3.core.vtlb);
+}
+
+static CPU_INIT( qed5271le )
+{
+ mips3com_init(&mips3.core, MIPS3_TYPE_QED5271, FALSE, device, irqcallback);
+ mips3.tlb_table = vtlb_table(mips3.core.vtlb);
+}
+
+CPU_GET_INFO( qed5271be )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(qed5271be); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "QED5271 (big)"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(mips3); break;
+ }
+}
+
+CPU_GET_INFO( qed5271le )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(qed5271le); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "QED5271 (little)"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(mips3); break;
+ }
+}
+
+
+
+/***************************************************************************
+ RM7000 VARIANTS
+***************************************************************************/
+
+static CPU_INIT( rm7000be )
+{
+ mips3com_init(&mips3.core, MIPS3_TYPE_RM7000, TRUE, device, irqcallback);
+ mips3.tlb_table = vtlb_table(mips3.core.vtlb);
+}
+
+static CPU_INIT( rm7000le )
+{
+ mips3com_init(&mips3.core, MIPS3_TYPE_RM7000, FALSE, device, irqcallback);
+ mips3.tlb_table = vtlb_table(mips3.core.vtlb);
+}
+
+CPU_GET_INFO( rm7000be )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(rm7000be); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "RM7000 (big)"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(mips3); break;
+ }
+}
+
+CPU_GET_INFO( rm7000le )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(rm7000le); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "RM7000 (little)"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(mips3); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(VR4300BE, vr4300be);
+DEFINE_LEGACY_CPU_DEVICE(VR4300LE, vr4300le);
+DEFINE_LEGACY_CPU_DEVICE(VR4310BE, vr4310be);
+DEFINE_LEGACY_CPU_DEVICE(VR4310LE, vr4310le);
+
+DEFINE_LEGACY_CPU_DEVICE(R4600BE, r4600be);
+DEFINE_LEGACY_CPU_DEVICE(R4600LE, r4600le);
+
+DEFINE_LEGACY_CPU_DEVICE(R4650BE, r4650be);
+DEFINE_LEGACY_CPU_DEVICE(R4650LE, r4650le);
+
+DEFINE_LEGACY_CPU_DEVICE(R4700BE, r4700be);
+DEFINE_LEGACY_CPU_DEVICE(R4700LE, r4700le);
+
+DEFINE_LEGACY_CPU_DEVICE(R5000BE, r5000be);
+DEFINE_LEGACY_CPU_DEVICE(R5000LE, r5000le);
+
+DEFINE_LEGACY_CPU_DEVICE(QED5271BE, qed5271be);
+DEFINE_LEGACY_CPU_DEVICE(QED5271LE, qed5271le);
+
+DEFINE_LEGACY_CPU_DEVICE(RM7000BE, rm7000be);
+DEFINE_LEGACY_CPU_DEVICE(RM7000LE, rm7000le);
+
+#endif
diff --git a/trunk/src/emu/cpu/mips/mips3.h b/trunk/src/emu/cpu/mips/mips3.h
new file mode 100644
index 00000000000..996cecf5a28
--- /dev/null
+++ b/trunk/src/emu/cpu/mips/mips3.h
@@ -0,0 +1,272 @@
+/***************************************************************************
+
+ mips3.h
+
+ Interface file for the universal machine language-based
+ MIPS III/IV emulator.
+
+ Copyright Aaron Giles
+ Released for general non-commercial use under the MAME license
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __MIPS3_H__
+#define __MIPS3_H__
+
+
+
+/***************************************************************************
+ REGISTER ENUMERATION
+***************************************************************************/
+
+enum
+{
+ MIPS3_PC = 1,
+ MIPS3_R0,
+ MIPS3_R1,
+ MIPS3_R2,
+ MIPS3_R3,
+ MIPS3_R4,
+ MIPS3_R5,
+ MIPS3_R6,
+ MIPS3_R7,
+ MIPS3_R8,
+ MIPS3_R9,
+ MIPS3_R10,
+ MIPS3_R11,
+ MIPS3_R12,
+ MIPS3_R13,
+ MIPS3_R14,
+ MIPS3_R15,
+ MIPS3_R16,
+ MIPS3_R17,
+ MIPS3_R18,
+ MIPS3_R19,
+ MIPS3_R20,
+ MIPS3_R21,
+ MIPS3_R22,
+ MIPS3_R23,
+ MIPS3_R24,
+ MIPS3_R25,
+ MIPS3_R26,
+ MIPS3_R27,
+ MIPS3_R28,
+ MIPS3_R29,
+ MIPS3_R30,
+ MIPS3_R31,
+ MIPS3_HI,
+ MIPS3_LO,
+ MIPS3_FPR0,
+ MIPS3_FPS0,
+ MIPS3_FPD0,
+ MIPS3_FPR1,
+ MIPS3_FPS1,
+ MIPS3_FPD1,
+ MIPS3_FPR2,
+ MIPS3_FPS2,
+ MIPS3_FPD2,
+ MIPS3_FPR3,
+ MIPS3_FPS3,
+ MIPS3_FPD3,
+ MIPS3_FPR4,
+ MIPS3_FPS4,
+ MIPS3_FPD4,
+ MIPS3_FPR5,
+ MIPS3_FPS5,
+ MIPS3_FPD5,
+ MIPS3_FPR6,
+ MIPS3_FPS6,
+ MIPS3_FPD6,
+ MIPS3_FPR7,
+ MIPS3_FPS7,
+ MIPS3_FPD7,
+ MIPS3_FPR8,
+ MIPS3_FPS8,
+ MIPS3_FPD8,
+ MIPS3_FPR9,
+ MIPS3_FPS9,
+ MIPS3_FPD9,
+ MIPS3_FPR10,
+ MIPS3_FPS10,
+ MIPS3_FPD10,
+ MIPS3_FPR11,
+ MIPS3_FPS11,
+ MIPS3_FPD11,
+ MIPS3_FPR12,
+ MIPS3_FPS12,
+ MIPS3_FPD12,
+ MIPS3_FPR13,
+ MIPS3_FPS13,
+ MIPS3_FPD13,
+ MIPS3_FPR14,
+ MIPS3_FPS14,
+ MIPS3_FPD14,
+ MIPS3_FPR15,
+ MIPS3_FPS15,
+ MIPS3_FPD15,
+ MIPS3_FPR16,
+ MIPS3_FPS16,
+ MIPS3_FPD16,
+ MIPS3_FPR17,
+ MIPS3_FPS17,
+ MIPS3_FPD17,
+ MIPS3_FPR18,
+ MIPS3_FPS18,
+ MIPS3_FPD18,
+ MIPS3_FPR19,
+ MIPS3_FPS19,
+ MIPS3_FPD19,
+ MIPS3_FPR20,
+ MIPS3_FPS20,
+ MIPS3_FPD20,
+ MIPS3_FPR21,
+ MIPS3_FPS21,
+ MIPS3_FPD21,
+ MIPS3_FPR22,
+ MIPS3_FPS22,
+ MIPS3_FPD22,
+ MIPS3_FPR23,
+ MIPS3_FPS23,
+ MIPS3_FPD23,
+ MIPS3_FPR24,
+ MIPS3_FPS24,
+ MIPS3_FPD24,
+ MIPS3_FPR25,
+ MIPS3_FPS25,
+ MIPS3_FPD25,
+ MIPS3_FPR26,
+ MIPS3_FPS26,
+ MIPS3_FPD26,
+ MIPS3_FPR27,
+ MIPS3_FPS27,
+ MIPS3_FPD27,
+ MIPS3_FPR28,
+ MIPS3_FPS28,
+ MIPS3_FPD28,
+ MIPS3_FPR29,
+ MIPS3_FPS29,
+ MIPS3_FPD29,
+ MIPS3_FPR30,
+ MIPS3_FPS30,
+ MIPS3_FPD30,
+ MIPS3_FPR31,
+ MIPS3_FPS31,
+ MIPS3_FPD31,
+ MIPS3_CCR1_31,
+ MIPS3_SR,
+ MIPS3_EPC,
+ MIPS3_CAUSE,
+ MIPS3_COUNT,
+ MIPS3_COMPARE,
+ MIPS3_INDEX,
+ MIPS3_RANDOM,
+ MIPS3_ENTRYHI,
+ MIPS3_ENTRYLO0,
+ MIPS3_ENTRYLO1,
+ MIPS3_PAGEMASK,
+ MIPS3_WIRED,
+ MIPS3_BADVADDR
+};
+
+#define MIPS3_MAX_FASTRAM 4
+#define MIPS3_MAX_HOTSPOTS 16
+
+enum
+{
+ CPUINFO_INT_MIPS3_DRC_OPTIONS = CPUINFO_INT_CPU_SPECIFIC,
+
+ CPUINFO_INT_MIPS3_FASTRAM_SELECT,
+ CPUINFO_INT_MIPS3_FASTRAM_START,
+ CPUINFO_INT_MIPS3_FASTRAM_END,
+ CPUINFO_INT_MIPS3_FASTRAM_READONLY,
+
+ CPUINFO_INT_MIPS3_HOTSPOT_SELECT,
+ CPUINFO_INT_MIPS3_HOTSPOT_PC,
+ CPUINFO_INT_MIPS3_HOTSPOT_OPCODE,
+ CPUINFO_INT_MIPS3_HOTSPOT_CYCLES,
+
+ CPUINFO_PTR_MIPS3_FASTRAM_BASE = CPUINFO_PTR_CPU_SPECIFIC
+};
+
+
+
+/***************************************************************************
+ INTERRUPT CONSTANTS
+***************************************************************************/
+
+#define MIPS3_IRQ0 0 /* IRQ0 */
+#define MIPS3_IRQ1 1 /* IRQ1 */
+#define MIPS3_IRQ2 2 /* IRQ2 */
+#define MIPS3_IRQ3 3 /* IRQ3 */
+#define MIPS3_IRQ4 4 /* IRQ4 */
+#define MIPS3_IRQ5 5 /* IRQ5 */
+
+
+
+/***************************************************************************
+ STRUCTURES
+***************************************************************************/
+
+typedef struct _mips3_config mips3_config;
+struct _mips3_config
+{
+ size_t icache; /* code cache size */
+ size_t dcache; /* data cache size */
+ UINT32 system_clock; /* system clock rate */
+};
+
+
+
+/***************************************************************************
+ PUBLIC FUNCTIONS
+***************************************************************************/
+
+void mips3drc_set_options(device_t *device, UINT32 options);
+void mips3drc_add_fastram(device_t *device, offs_t start, offs_t end, UINT8 readonly, void *base);
+void mips3drc_add_hotspot(device_t *device, offs_t pc, UINT32 opcode, UINT32 cycles);
+
+DECLARE_LEGACY_CPU_DEVICE(VR4300BE, vr4300be);
+DECLARE_LEGACY_CPU_DEVICE(VR4300LE, vr4300le);
+DECLARE_LEGACY_CPU_DEVICE(VR4310BE, vr4310be);
+DECLARE_LEGACY_CPU_DEVICE(VR4310LE, vr4310le);
+
+DECLARE_LEGACY_CPU_DEVICE(R4600BE, r4600be);
+DECLARE_LEGACY_CPU_DEVICE(R4600LE, r4600le);
+
+DECLARE_LEGACY_CPU_DEVICE(R4650BE, r4650be);
+DECLARE_LEGACY_CPU_DEVICE(R4650LE, r4650le);
+
+DECLARE_LEGACY_CPU_DEVICE(R4700BE, r4700be);
+DECLARE_LEGACY_CPU_DEVICE(R4700LE, r4700le);
+
+DECLARE_LEGACY_CPU_DEVICE(R5000BE, r5000be);
+DECLARE_LEGACY_CPU_DEVICE(R5000LE, r5000le);
+
+DECLARE_LEGACY_CPU_DEVICE(QED5271BE, qed5271be);
+DECLARE_LEGACY_CPU_DEVICE(QED5271LE, qed5271le);
+
+DECLARE_LEGACY_CPU_DEVICE(RM7000BE, rm7000be);
+DECLARE_LEGACY_CPU_DEVICE(RM7000LE, rm7000le);
+
+
+
+/***************************************************************************
+ COMPILER-SPECIFIC OPTIONS
+***************************************************************************/
+
+/* fix me -- how do we make this work?? */
+#define MIPS3DRC_STRICT_VERIFY 0x0001 /* verify all instructions */
+#define MIPS3DRC_STRICT_COP1 0x0002 /* validate all COP1 instructions */
+#define MIPS3DRC_STRICT_COP2 0x0004 /* validate all COP2 instructions */
+#define MIPS3DRC_FLUSH_PC 0x0008 /* flush the PC value before each memory access */
+#define MIPS3DRC_CHECK_OVERFLOWS 0x0010 /* actually check overflows on add/sub instructions */
+
+#define MIPS3DRC_COMPATIBLE_OPTIONS (MIPS3DRC_STRICT_VERIFY | MIPS3DRC_STRICT_COP1 | MIPS3DRC_STRICT_COP2 | MIPS3DRC_FLUSH_PC)
+#define MIPS3DRC_FASTEST_OPTIONS (0)
+
+
+
+#endif /* __MIPS3_H__ */
diff --git a/trunk/src/emu/cpu/mips/mips3com.c b/trunk/src/emu/cpu/mips/mips3com.c
new file mode 100644
index 00000000000..e8327a440c3
--- /dev/null
+++ b/trunk/src/emu/cpu/mips/mips3com.c
@@ -0,0 +1,986 @@
+/***************************************************************************
+
+ mips3com.c
+
+ Common MIPS III/IV definitions and functions
+
+***************************************************************************/
+
+#include "emu.h"
+#include "mips3com.h"
+
+
+/***************************************************************************
+ DEBUGGING
+***************************************************************************/
+
+#define PRINTF_TLB (0)
+#define USE_ABI_REG_NAMES (1)
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static TIMER_CALLBACK( compare_int_callback );
+
+static UINT32 compute_config_register(const mips3_state *mips);
+static UINT32 compute_prid_register(const mips3_state *mips);
+
+static void tlb_map_entry(mips3_state *mips, int tlbindex);
+static void tlb_write_common(mips3_state *mips, int tlbindex);
+static void tlb_entry_log_half(mips3_tlb_entry *entry, int tlbindex, int which);
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ tlb_entry_matches_asid - TRUE if the given
+ TLB entry matches the provided ASID
+-------------------------------------------------*/
+
+INLINE int tlb_entry_matches_asid(const mips3_tlb_entry *entry, UINT8 asid)
+{
+ return (entry->entry_hi & 0xff) == asid;
+}
+
+
+/*-------------------------------------------------
+ tlb_entry_is_global - TRUE if the given
+ TLB entry is global
+-------------------------------------------------*/
+
+INLINE int tlb_entry_is_global(const mips3_tlb_entry *entry)
+{
+ return (entry->entry_lo[0] & entry->entry_lo[1] & TLB_GLOBAL);
+}
+
+
+
+/***************************************************************************
+ INITIALIZATION AND SHUTDOWN
+***************************************************************************/
+
+/*-------------------------------------------------
+ mips3com_init - initialize the mips3_state
+ structure based on the configured type
+-------------------------------------------------*/
+
+void mips3com_init(mips3_state *mips, mips3_flavor flavor, int bigendian, legacy_cpu_device *device, device_irq_callback irqcallback)
+{
+ const mips3_config *config = (const mips3_config *)device->static_config();
+ int tlbindex;
+
+ /* initialize based on the config */
+ memset(mips, 0, sizeof(*mips));
+ mips->flavor = flavor;
+ mips->bigendian = bigendian;
+ mips->cpu_clock = device->clock();
+ mips->irq_callback = irqcallback;
+ mips->device = device;
+ mips->program = device->space(AS_PROGRAM);
+ mips->direct = &mips->program->direct();
+ mips->icache_size = config->icache;
+ mips->dcache_size = config->dcache;
+ mips->system_clock = config->system_clock;
+
+ /* configure flavor-specific parameters */
+ mips->pfnmask = 0x00ffffff;
+ mips->tlbentries = MIPS3_MAX_TLB_ENTRIES;
+
+ /* VR4300 and VR5432 have 4 fewer PFN bits, and only 32 TLB entries */
+ if (flavor == MIPS3_TYPE_VR4300)
+ {
+ mips->pfnmask = 0x000fffff;
+ mips->tlbentries = 32;
+ }
+
+ /* set up the endianness */
+ mips->program->accessors(mips->memory);
+
+ /* allocate the virtual TLB */
+ mips->vtlb = vtlb_alloc(device, AS_PROGRAM, 2 * mips->tlbentries + 2, 0);
+
+ /* allocate a timer for the compare interrupt */
+ mips->compare_int_timer = device->machine().scheduler().timer_alloc(FUNC(compare_int_callback), (void *)device);
+
+ /* reset the state */
+ mips3com_reset(mips);
+
+ /* register for save states */
+ device->save_item(NAME(mips->pc));
+ device->save_item(NAME(mips->r));
+ device->save_item(NAME(mips->cpr));
+ device->save_item(NAME(mips->ccr));
+ device->save_item(NAME(mips->llbit));
+ device->save_item(NAME(mips->count_zero_time));
+ for (tlbindex = 0; tlbindex < mips->tlbentries; tlbindex++)
+ {
+ device->save_item(NAME(mips->tlb[tlbindex].page_mask), tlbindex);
+ device->save_item(NAME(mips->tlb[tlbindex].entry_hi), tlbindex);
+ device->save_item(NAME(mips->tlb[tlbindex].entry_lo), tlbindex);
+ }
+}
+
+
+/*-------------------------------------------------
+ mips3com_exit - common cleanup/exit
+-------------------------------------------------*/
+
+void mips3com_exit(mips3_state *mips)
+{
+ if (mips->vtlb != NULL)
+ vtlb_free(mips->vtlb);
+}
+
+
+/*-------------------------------------------------
+ mips3com_reset - reset the state of all the
+ registers
+-------------------------------------------------*/
+
+void mips3com_reset(mips3_state *mips)
+{
+ int tlbindex;
+
+ /* initialize the state */
+ mips->pc = 0xbfc00000;
+ mips->cpr[0][COP0_Status] = SR_BEV | SR_ERL;
+ mips->cpr[0][COP0_Wired] = 0;
+ mips->cpr[0][COP0_Compare] = 0xffffffff;
+ mips->cpr[0][COP0_Count] = 0;
+ mips->cpr[0][COP0_Config] = compute_config_register(mips);
+ mips->cpr[0][COP0_PRId] = compute_prid_register(mips);
+ mips->count_zero_time = mips->device->total_cycles();
+
+ /* initialize the TLB state */
+ for (tlbindex = 0; tlbindex < mips->tlbentries; tlbindex++)
+ {
+ mips3_tlb_entry *entry = &mips->tlb[tlbindex];
+ entry->page_mask = 0;
+ entry->entry_hi = 0xffffffff;
+ entry->entry_lo[0] = 0xfffffff8;
+ entry->entry_lo[1] = 0xfffffff8;
+ vtlb_load(mips->vtlb, 2 * tlbindex + 0, 0, 0, 0);
+ vtlb_load(mips->vtlb, 2 * tlbindex + 1, 0, 0, 0);
+ }
+
+ /* load the fixed TLB range */
+ vtlb_load(mips->vtlb, 2 * mips->tlbentries + 0, (0xa0000000 - 0x80000000) >> MIPS3_MIN_PAGE_SHIFT, 0x80000000, 0x00000000 | VTLB_READ_ALLOWED | VTLB_WRITE_ALLOWED | VTLB_FETCH_ALLOWED | VTLB_FLAG_VALID);
+ vtlb_load(mips->vtlb, 2 * mips->tlbentries + 1, (0xc0000000 - 0xa0000000) >> MIPS3_MIN_PAGE_SHIFT, 0xa0000000, 0x00000000 | VTLB_READ_ALLOWED | VTLB_WRITE_ALLOWED | VTLB_FETCH_ALLOWED | VTLB_FLAG_VALID);
+}
+
+
+/*-------------------------------------------------
+ mips3com_dasm - handle disassembly for a
+ CPU
+-------------------------------------------------*/
+
+offs_t mips3com_dasm(mips3_state *mips, char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram)
+{
+ extern unsigned dasmmips3(char *, unsigned, UINT32);
+ UINT32 op = *(UINT32 *)oprom;
+ if (mips->bigendian)
+ op = BIG_ENDIANIZE_INT32(op);
+ else
+ op = LITTLE_ENDIANIZE_INT32(op);
+ return dasmmips3(buffer, pc, op);
+}
+
+
+/*-------------------------------------------------
+ mips3com_update_cycle_counting - update cycle
+ counts and the timers
+-------------------------------------------------*/
+
+void mips3com_update_cycle_counting(mips3_state *mips)
+{
+ /* modify the timer to go off */
+ if (mips->compare_armed && (mips->cpr[0][COP0_Status] & SR_IMEX5))
+ {
+ UINT32 count = (mips->device->total_cycles() - mips->count_zero_time) / 2;
+ UINT32 compare = mips->cpr[0][COP0_Compare];
+ UINT32 delta = compare - count;
+ attotime newtime = mips->device->cycles_to_attotime((UINT64)delta * 2);
+ mips->compare_int_timer->adjust(newtime);
+ return;
+ }
+ mips->compare_int_timer->adjust(attotime::never);
+}
+
+
+
+/***************************************************************************
+ TLB HANDLING
+***************************************************************************/
+
+/*-------------------------------------------------
+ mips3com_asid_changed - remap all non-global
+ TLB entries
+-------------------------------------------------*/
+
+void mips3com_asid_changed(mips3_state *mips)
+{
+ int tlbindex;
+
+ /* iterate over all non-global TLB entries and remap them */
+ for (tlbindex = 0; tlbindex < mips->tlbentries; tlbindex++)
+ if (!tlb_entry_is_global(&mips->tlb[tlbindex]))
+ tlb_map_entry(mips, tlbindex);
+}
+
+
+/*-------------------------------------------------
+ mips3com_translate_address - translate an address
+ from logical to physical
+-------------------------------------------------*/
+
+int mips3com_translate_address(mips3_state *mips, address_spacenum space, int intention, offs_t *address)
+{
+ /* only applies to the program address space */
+ if (space == AS_PROGRAM)
+ {
+ const vtlb_entry *table = vtlb_table(mips->vtlb);
+ vtlb_entry entry = table[*address >> MIPS3_MIN_PAGE_SHIFT];
+ if ((entry & (1 << (intention & (TRANSLATE_TYPE_MASK | TRANSLATE_USER_MASK)))) == 0)
+ return FALSE;
+ *address = (entry & ~MIPS3_MIN_PAGE_MASK) | (*address & MIPS3_MIN_PAGE_MASK);
+ }
+ return TRUE;
+}
+
+
+/*-------------------------------------------------
+ mips3com_tlbr - execute the tlbr instruction
+-------------------------------------------------*/
+
+void mips3com_tlbr(mips3_state *mips)
+{
+ UINT32 tlbindex = mips->cpr[0][COP0_Index] & 0x3f;
+
+ /* only handle entries within the TLB */
+ if (tlbindex < mips->tlbentries)
+ {
+ mips3_tlb_entry *entry = &mips->tlb[tlbindex];
+
+ /* copy data from the TLB entry into the COP0 registers */
+ mips->cpr[0][COP0_PageMask] = entry->page_mask;
+ mips->cpr[0][COP0_EntryHi] = entry->entry_hi;
+ mips->cpr[0][COP0_EntryLo0] = entry->entry_lo[0];
+ mips->cpr[0][COP0_EntryLo1] = entry->entry_lo[1];
+ }
+}
+
+
+/*-------------------------------------------------
+ mips3com_tlbwi - execute the tlbwi instruction
+-------------------------------------------------*/
+
+void mips3com_tlbwi(mips3_state *mips)
+{
+ /* use the common handler and write based off the COP0 Index register */
+ tlb_write_common(mips, mips->cpr[0][COP0_Index] & 0x3f);
+}
+
+
+/*-------------------------------------------------
+ mips3com_tlbwr - execute the tlbwr instruction
+-------------------------------------------------*/
+
+void mips3com_tlbwr(mips3_state *mips)
+{
+ UINT32 wired = mips->cpr[0][COP0_Wired] & 0x3f;
+ UINT32 unwired = mips->tlbentries - wired;
+ UINT32 tlbindex = mips->tlbentries - 1;
+
+ /* "random" is based off of the current cycle counting through the non-wired pages */
+ if (unwired > 0)
+ tlbindex = ((mips->device->total_cycles() - mips->count_zero_time) % unwired + wired) & 0x3f;
+
+ /* use the common handler to write to this tlbindex */
+ tlb_write_common(mips, tlbindex);
+}
+
+
+/*-------------------------------------------------
+ mips3com_tlbp - execute the tlbp instruction
+-------------------------------------------------*/
+
+void mips3com_tlbp(mips3_state *mips)
+{
+ UINT32 tlbindex;
+// UINT64 vpn;
+
+ /* iterate over TLB entries */
+ for (tlbindex = 0; tlbindex < mips->tlbentries; tlbindex++)
+ {
+ mips3_tlb_entry *entry = &mips->tlb[tlbindex];
+ UINT64 mask = ~((entry->page_mask >> 13) & 0xfff) << 13;
+
+ /* if the relevant bits of EntryHi match the relevant bits of the TLB */
+ if ((entry->entry_hi & mask) == (mips->cpr[0][COP0_EntryHi] & mask))
+
+ /* and if we are either global or matching the current ASID, then stop */
+ if ((entry->entry_hi & 0xff) == (mips->cpr[0][COP0_EntryHi] & 0xff) || ((entry->entry_lo[0] & entry->entry_lo[1]) & TLB_GLOBAL))
+ break;
+ }
+
+ /* validate that our tlb_table was in sync */
+// vpn = ((mips->cpr[0][COP0_EntryHi] >> 13) & 0x07ffffff) << 1;
+ if (tlbindex != mips->tlbentries)
+ mips->cpr[0][COP0_Index] = tlbindex;
+ else
+ mips->cpr[0][COP0_Index] = 0x80000000;
+}
+
+
+
+/***************************************************************************
+ COMMON GET/SET INFO
+***************************************************************************/
+
+/*-------------------------------------------------
+ mips3com_set_info - set information about
+ a MIPS 3 CPU
+-------------------------------------------------*/
+
+void mips3com_set_info(mips3_state *mips, UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + MIPS3_IRQ0: mips3com_set_irq_line(mips, MIPS3_IRQ0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + MIPS3_IRQ1: mips3com_set_irq_line(mips, MIPS3_IRQ1, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + MIPS3_IRQ2: mips3com_set_irq_line(mips, MIPS3_IRQ2, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + MIPS3_IRQ3: mips3com_set_irq_line(mips, MIPS3_IRQ3, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + MIPS3_IRQ4: mips3com_set_irq_line(mips, MIPS3_IRQ4, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + MIPS3_IRQ5: mips3com_set_irq_line(mips, MIPS3_IRQ5, info->i); break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + MIPS3_PC: mips->pc = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_SR: mips->cpr[0][COP0_Status] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_EPC: mips->cpr[0][COP0_EPC] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_CAUSE: mips->cpr[0][COP0_Cause] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_COUNT: mips->cpr[0][COP0_Count] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_COMPARE: mips->cpr[0][COP0_Compare] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_INDEX: mips->cpr[0][COP0_Index] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_RANDOM: mips->cpr[0][COP0_Random] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_ENTRYHI: mips->cpr[0][COP0_EntryHi] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_ENTRYLO0: mips->cpr[0][COP0_EntryLo0] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_ENTRYLO1: mips->cpr[0][COP0_EntryLo1] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_PAGEMASK: mips->cpr[0][COP0_PageMask] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_WIRED: mips->cpr[0][COP0_Wired] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_BADVADDR: mips->cpr[0][COP0_BadVAddr] = info->i; break;
+
+ case CPUINFO_INT_REGISTER + MIPS3_R0: /* can't change R0 */ break;
+ case CPUINFO_INT_REGISTER + MIPS3_R1: mips->r[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R2: mips->r[2] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R3: mips->r[3] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R4: mips->r[4] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R5: mips->r[5] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R6: mips->r[6] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R7: mips->r[7] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R8: mips->r[8] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R9: mips->r[9] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R10: mips->r[10] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R11: mips->r[11] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R12: mips->r[12] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R13: mips->r[13] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R14: mips->r[14] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R15: mips->r[15] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R16: mips->r[16] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R17: mips->r[17] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R18: mips->r[18] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R19: mips->r[19] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R20: mips->r[20] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R21: mips->r[21] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R22: mips->r[22] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R23: mips->r[23] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R24: mips->r[24] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R25: mips->r[25] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R26: mips->r[26] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R27: mips->r[27] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R28: mips->r[28] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R29: mips->r[29] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R30: mips->r[30] = info->i; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + MIPS3_R31: mips->r[31] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_HI: mips->r[REG_HI] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_LO: mips->r[REG_LO] = info->i; break;
+
+ case CPUINFO_INT_REGISTER + MIPS3_FPR0: mips->cpr[1][0] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR1: mips->cpr[1][1] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR2: mips->cpr[1][2] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR3: mips->cpr[1][3] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR4: mips->cpr[1][4] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR5: mips->cpr[1][5] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR6: mips->cpr[1][6] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR7: mips->cpr[1][7] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR8: mips->cpr[1][8] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR9: mips->cpr[1][9] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR10: mips->cpr[1][10] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR11: mips->cpr[1][11] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR12: mips->cpr[1][12] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR13: mips->cpr[1][13] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR14: mips->cpr[1][14] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR15: mips->cpr[1][15] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR16: mips->cpr[1][16] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR17: mips->cpr[1][17] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR18: mips->cpr[1][18] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR19: mips->cpr[1][19] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR20: mips->cpr[1][20] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR21: mips->cpr[1][21] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR22: mips->cpr[1][22] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR23: mips->cpr[1][23] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR24: mips->cpr[1][24] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR25: mips->cpr[1][25] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR26: mips->cpr[1][26] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR27: mips->cpr[1][27] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR28: mips->cpr[1][28] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR29: mips->cpr[1][29] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR30: mips->cpr[1][30] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR31: mips->cpr[1][31] = info->i; break;
+ }
+}
+
+
+/*-------------------------------------------------
+ mips3com_get_info - get information about
+ a MIPS 3 CPU
+-------------------------------------------------*/
+
+void mips3com_get_info(mips3_state *mips, UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: /* provided by core */ break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 6; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = mips->bigendian ? ENDIANNESS_BIG : ENDIANNESS_LITTLE; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 40; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = MIPS3_MAX_PADDR_SHIFT;break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case CPUINFO_INT_LOGADDR_WIDTH_PROGRAM: info->i = 32; break;
+ case CPUINFO_INT_PAGE_SHIFT_PROGRAM: info->i = MIPS3_MIN_PAGE_SHIFT; break;
+
+ case CPUINFO_INT_INPUT_STATE + MIPS3_IRQ0: info->i = (mips->cpr[0][COP0_Cause] & 0x400) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + MIPS3_IRQ1: info->i = (mips->cpr[0][COP0_Cause] & 0x800) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + MIPS3_IRQ2: info->i = (mips->cpr[0][COP0_Cause] & 0x1000) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + MIPS3_IRQ3: info->i = (mips->cpr[0][COP0_Cause] & 0x2000) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + MIPS3_IRQ4: info->i = (mips->cpr[0][COP0_Cause] & 0x4000) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + MIPS3_IRQ5: info->i = (mips->cpr[0][COP0_Cause] & 0x8000) ? ASSERT_LINE : CLEAR_LINE; break;
+
+ case CPUINFO_INT_PREVIOUSPC: /* optionally implemented */ break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + MIPS3_PC: info->i = mips->pc; break;
+ case CPUINFO_INT_REGISTER + MIPS3_SR: info->i = mips->cpr[0][COP0_Status]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_EPC: info->i = mips->cpr[0][COP0_EPC]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_CAUSE: info->i = mips->cpr[0][COP0_Cause]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_COUNT: info->i = ((mips->device->total_cycles() - mips->count_zero_time) / 2); break;
+ case CPUINFO_INT_REGISTER + MIPS3_COMPARE: info->i = mips->cpr[0][COP0_Compare]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_INDEX: info->i = mips->cpr[0][COP0_Index]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_RANDOM: info->i = mips->cpr[0][COP0_Random]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_ENTRYHI: info->i = mips->cpr[0][COP0_EntryHi]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_ENTRYLO0: info->i = mips->cpr[0][COP0_EntryLo0]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_ENTRYLO1: info->i = mips->cpr[0][COP0_EntryLo1]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_PAGEMASK: info->i = mips->cpr[0][COP0_PageMask]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_WIRED: info->i = mips->cpr[0][COP0_Wired]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_BADVADDR: info->i = mips->cpr[0][COP0_BadVAddr]; break;
+
+ case CPUINFO_INT_REGISTER + MIPS3_R0: info->i = mips->r[0]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R1: info->i = mips->r[1]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R2: info->i = mips->r[2]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R3: info->i = mips->r[3]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R4: info->i = mips->r[4]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R5: info->i = mips->r[5]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R6: info->i = mips->r[6]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R7: info->i = mips->r[7]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R8: info->i = mips->r[8]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R9: info->i = mips->r[9]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R10: info->i = mips->r[10]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R11: info->i = mips->r[11]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R12: info->i = mips->r[12]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R13: info->i = mips->r[13]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R14: info->i = mips->r[14]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R15: info->i = mips->r[15]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R16: info->i = mips->r[16]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R17: info->i = mips->r[17]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R18: info->i = mips->r[18]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R19: info->i = mips->r[19]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R20: info->i = mips->r[20]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R21: info->i = mips->r[21]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R22: info->i = mips->r[22]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R23: info->i = mips->r[23]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R24: info->i = mips->r[24]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R25: info->i = mips->r[25]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R26: info->i = mips->r[26]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R27: info->i = mips->r[27]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R28: info->i = mips->r[28]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R29: info->i = mips->r[29]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R30: info->i = mips->r[30]; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + MIPS3_R31: info->i = mips->r[31]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_HI: info->i = mips->r[REG_HI]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_LO: info->i = mips->r[REG_LO]; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: /* provided by core */ break;
+ case CPUINFO_FCT_INIT: /* provided by core */ break;
+ case CPUINFO_FCT_RESET: /* provided by core */ break;
+ case CPUINFO_FCT_EXIT: /* provided by core */ break;
+ case CPUINFO_FCT_EXECUTE: /* provided by core */ break;
+ case CPUINFO_FCT_TRANSLATE: /* provided by core */ break;
+ case CPUINFO_FCT_DISASSEMBLE: /* provided by core */ break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &mips->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "MIPS III"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "MIPS III"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "3.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: /* provided by core */ break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Aaron Giles"); break;
+
+ case CPUINFO_STR_FLAGS: strcpy(info->s, " "); break;
+
+ case CPUINFO_STR_REGISTER + MIPS3_PC: sprintf(info->s, "PC: %08X", mips->pc); break;
+ case CPUINFO_STR_REGISTER + MIPS3_SR: sprintf(info->s, "SR: %08X", (UINT32)mips->cpr[0][COP0_Status]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_EPC: sprintf(info->s, "EPC:%08X", (UINT32)mips->cpr[0][COP0_EPC]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_CAUSE: sprintf(info->s, "Cause:%08X", (UINT32)mips->cpr[0][COP0_Cause]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_COUNT: sprintf(info->s, "Count:%08X", (UINT32)((mips->device->total_cycles() - mips->count_zero_time) / 2)); break;
+ case CPUINFO_STR_REGISTER + MIPS3_COMPARE: sprintf(info->s, "Compare:%08X", (UINT32)mips->cpr[0][COP0_Compare]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_INDEX: sprintf(info->s, "Index:%08X", (UINT32)mips->cpr[0][COP0_Index]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_RANDOM: sprintf(info->s, "Random:%08X", (UINT32)mips->cpr[0][COP0_Random]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_ENTRYHI: sprintf(info->s, "EntryHi:%08X%08X", (UINT32)(mips->cpr[0][COP0_EntryHi] >> 32), (UINT32)mips->cpr[0][COP0_EntryHi]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_ENTRYLO0: sprintf(info->s, "EntryLo0:%08X%08X", (UINT32)(mips->cpr[0][COP0_EntryLo0] >> 32), (UINT32)mips->cpr[0][COP0_EntryLo0]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_ENTRYLO1: sprintf(info->s, "EntryLo1:%08X%08X", (UINT32)(mips->cpr[0][COP0_EntryLo1] >> 32), (UINT32)mips->cpr[0][COP0_EntryLo1]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_PAGEMASK: sprintf(info->s, "PageMask:%08X%08X", (UINT32)(mips->cpr[0][COP0_PageMask] >> 32), (UINT32)mips->cpr[0][COP0_PageMask]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_WIRED: sprintf(info->s, "Wired:%08X", (UINT32)mips->cpr[0][COP0_Wired]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_BADVADDR: sprintf(info->s, "BadVAddr:%08X", (UINT32)mips->cpr[0][COP0_BadVAddr]); break;
+
+#if USE_ABI_REG_NAMES
+ case CPUINFO_STR_REGISTER + MIPS3_R0: sprintf(info->s, "$zero: %08X%08X", (UINT32)(mips->r[0] >> 32), (UINT32)mips->r[0]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R1: sprintf(info->s, " $at: %08X%08X", (UINT32)(mips->r[1] >> 32), (UINT32)mips->r[1]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R2: sprintf(info->s, " $v0: %08X%08X", (UINT32)(mips->r[2] >> 32), (UINT32)mips->r[2]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R3: sprintf(info->s, " $v1: %08X%08X", (UINT32)(mips->r[3] >> 32), (UINT32)mips->r[3]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R4: sprintf(info->s, " $a0: %08X%08X", (UINT32)(mips->r[4] >> 32), (UINT32)mips->r[4]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R5: sprintf(info->s, " $a1: %08X%08X", (UINT32)(mips->r[5] >> 32), (UINT32)mips->r[5]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R6: sprintf(info->s, " $a2: %08X%08X", (UINT32)(mips->r[6] >> 32), (UINT32)mips->r[6]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R7: sprintf(info->s, " $a3: %08X%08X", (UINT32)(mips->r[7] >> 32), (UINT32)mips->r[7]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R8: sprintf(info->s, " $t0: %08X%08X", (UINT32)(mips->r[8] >> 32), (UINT32)mips->r[8]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R9: sprintf(info->s, " $t1: %08X%08X", (UINT32)(mips->r[9] >> 32), (UINT32)mips->r[9]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R10: sprintf(info->s, " $t2:%08X%08X", (UINT32)(mips->r[10] >> 32), (UINT32)mips->r[10]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R11: sprintf(info->s, " $t3:%08X%08X", (UINT32)(mips->r[11] >> 32), (UINT32)mips->r[11]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R12: sprintf(info->s, " $t4:%08X%08X", (UINT32)(mips->r[12] >> 32), (UINT32)mips->r[12]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R13: sprintf(info->s, " $t5:%08X%08X", (UINT32)(mips->r[13] >> 32), (UINT32)mips->r[13]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R14: sprintf(info->s, " $t6:%08X%08X", (UINT32)(mips->r[14] >> 32), (UINT32)mips->r[14]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R15: sprintf(info->s, " $t7:%08X%08X", (UINT32)(mips->r[15] >> 32), (UINT32)mips->r[15]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R16: sprintf(info->s, " $s0:%08X%08X", (UINT32)(mips->r[16] >> 32), (UINT32)mips->r[16]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R17: sprintf(info->s, " $s1:%08X%08X", (UINT32)(mips->r[17] >> 32), (UINT32)mips->r[17]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R18: sprintf(info->s, " $s2:%08X%08X", (UINT32)(mips->r[18] >> 32), (UINT32)mips->r[18]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R19: sprintf(info->s, " $s3:%08X%08X", (UINT32)(mips->r[19] >> 32), (UINT32)mips->r[19]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R20: sprintf(info->s, " $s4:%08X%08X", (UINT32)(mips->r[20] >> 32), (UINT32)mips->r[20]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R21: sprintf(info->s, " $s5:%08X%08X", (UINT32)(mips->r[21] >> 32), (UINT32)mips->r[21]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R22: sprintf(info->s, " $s6:%08X%08X", (UINT32)(mips->r[22] >> 32), (UINT32)mips->r[22]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R23: sprintf(info->s, " $s7:%08X%08X", (UINT32)(mips->r[23] >> 32), (UINT32)mips->r[23]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R24: sprintf(info->s, " $t8:%08X%08X", (UINT32)(mips->r[24] >> 32), (UINT32)mips->r[24]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R25: sprintf(info->s, " $t9:%08X%08X", (UINT32)(mips->r[25] >> 32), (UINT32)mips->r[25]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R26: sprintf(info->s, " $k0:%08X%08X", (UINT32)(mips->r[26] >> 32), (UINT32)mips->r[26]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R27: sprintf(info->s, " $k1:%08X%08X", (UINT32)(mips->r[27] >> 32), (UINT32)mips->r[27]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R28: sprintf(info->s, " $gp:%08X%08X", (UINT32)(mips->r[28] >> 32), (UINT32)mips->r[28]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R29: sprintf(info->s, " $sp:%08X%08X", (UINT32)(mips->r[29] >> 32), (UINT32)mips->r[29]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R30: sprintf(info->s, " $fp:%08X%08X", (UINT32)(mips->r[30] >> 32), (UINT32)mips->r[30]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R31: sprintf(info->s, " $ra:%08X%08X", (UINT32)(mips->r[31] >> 32), (UINT32)mips->r[31]); break;
+#else
+ case CPUINFO_STR_REGISTER + MIPS3_R0: sprintf(info->s, " R0: %08X%08X", (UINT32)(mips->r[0] >> 32), (UINT32)mips->r[0]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R1: sprintf(info->s, " R1: %08X%08X", (UINT32)(mips->r[1] >> 32), (UINT32)mips->r[1]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R2: sprintf(info->s, " R2: %08X%08X", (UINT32)(mips->r[2] >> 32), (UINT32)mips->r[2]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R3: sprintf(info->s, " R3: %08X%08X", (UINT32)(mips->r[3] >> 32), (UINT32)mips->r[3]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R4: sprintf(info->s, " R4: %08X%08X", (UINT32)(mips->r[4] >> 32), (UINT32)mips->r[4]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R5: sprintf(info->s, " R5: %08X%08X", (UINT32)(mips->r[5] >> 32), (UINT32)mips->r[5]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R6: sprintf(info->s, " R6: %08X%08X", (UINT32)(mips->r[6] >> 32), (UINT32)mips->r[6]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R7: sprintf(info->s, " R7: %08X%08X", (UINT32)(mips->r[7] >> 32), (UINT32)mips->r[7]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R8: sprintf(info->s, " R8: %08X%08X", (UINT32)(mips->r[8] >> 32), (UINT32)mips->r[8]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R9: sprintf(info->s, " R9: %08X%08X", (UINT32)(mips->r[9] >> 32), (UINT32)mips->r[9]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R10: sprintf(info->s, "R10: %08X%08X", (UINT32)(mips->r[10] >> 32), (UINT32)mips->r[10]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R11: sprintf(info->s, "R11: %08X%08X", (UINT32)(mips->r[11] >> 32), (UINT32)mips->r[11]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R12: sprintf(info->s, "R12: %08X%08X", (UINT32)(mips->r[12] >> 32), (UINT32)mips->r[12]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R13: sprintf(info->s, "R13: %08X%08X", (UINT32)(mips->r[13] >> 32), (UINT32)mips->r[13]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R14: sprintf(info->s, "R14: %08X%08X", (UINT32)(mips->r[14] >> 32), (UINT32)mips->r[14]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R15: sprintf(info->s, "R15: %08X%08X", (UINT32)(mips->r[15] >> 32), (UINT32)mips->r[15]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R16: sprintf(info->s, "R16: %08X%08X", (UINT32)(mips->r[16] >> 32), (UINT32)mips->r[16]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R17: sprintf(info->s, "R17: %08X%08X", (UINT32)(mips->r[17] >> 32), (UINT32)mips->r[17]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R18: sprintf(info->s, "R18: %08X%08X", (UINT32)(mips->r[18] >> 32), (UINT32)mips->r[18]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R19: sprintf(info->s, "R19: %08X%08X", (UINT32)(mips->r[19] >> 32), (UINT32)mips->r[19]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R20: sprintf(info->s, "R20: %08X%08X", (UINT32)(mips->r[20] >> 32), (UINT32)mips->r[20]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R21: sprintf(info->s, "R21: %08X%08X", (UINT32)(mips->r[21] >> 32), (UINT32)mips->r[21]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R22: sprintf(info->s, "R22: %08X%08X", (UINT32)(mips->r[22] >> 32), (UINT32)mips->r[22]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R23: sprintf(info->s, "R23: %08X%08X", (UINT32)(mips->r[23] >> 32), (UINT32)mips->r[23]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R24: sprintf(info->s, "R24: %08X%08X", (UINT32)(mips->r[24] >> 32), (UINT32)mips->r[24]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R25: sprintf(info->s, "R25: %08X%08X", (UINT32)(mips->r[25] >> 32), (UINT32)mips->r[25]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R26: sprintf(info->s, "R26: %08X%08X", (UINT32)(mips->r[26] >> 32), (UINT32)mips->r[26]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R27: sprintf(info->s, "R27: %08X%08X", (UINT32)(mips->r[27] >> 32), (UINT32)mips->r[27]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R28: sprintf(info->s, "R28: %08X%08X", (UINT32)(mips->r[28] >> 32), (UINT32)mips->r[28]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R29: sprintf(info->s, "R29: %08X%08X", (UINT32)(mips->r[29] >> 32), (UINT32)mips->r[29]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R30: sprintf(info->s, "R30: %08X%08X", (UINT32)(mips->r[30] >> 32), (UINT32)mips->r[30]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R31: sprintf(info->s, "R31: %08X%08X", (UINT32)(mips->r[31] >> 32), (UINT32)mips->r[31]); break;
+#endif
+ case CPUINFO_STR_REGISTER + MIPS3_HI: sprintf(info->s, "HI: %08X%08X", (UINT32)(mips->r[REG_HI] >> 32), (UINT32)mips->r[REG_HI]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_LO: sprintf(info->s, "LO: %08X%08X", (UINT32)(mips->r[REG_LO] >> 32), (UINT32)mips->r[REG_LO]); break;
+
+ case CPUINFO_STR_REGISTER + MIPS3_CCR1_31: sprintf(info->s, "CCR31:%08X", (UINT32)mips->ccr[1][31]); break;
+
+ case CPUINFO_STR_REGISTER + MIPS3_FPR0: sprintf(info->s, "FPR0: %08X%08X", (UINT32)(mips->cpr[1][0] >> 32), (UINT32)mips->cpr[1][0]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPS0: sprintf(info->s, "FPS0: !%16g", *(float *)&mips->cpr[1][0]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPD0: sprintf(info->s, "FPD0: !%16g", *(double *)&mips->cpr[1][0]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR1: sprintf(info->s, "FPR1: %08X%08X", (UINT32)(mips->cpr[1][1] >> 32), (UINT32)mips->cpr[1][1]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPS1: sprintf(info->s, "FPS1: !%16g", *(float *)&mips->cpr[1][1]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPD1: sprintf(info->s, "FPD1: !%16g", *(double *)&mips->cpr[1][1]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR2: sprintf(info->s, "FPR2: %08X%08X", (UINT32)(mips->cpr[1][2] >> 32), (UINT32)mips->cpr[1][2]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPS2: sprintf(info->s, "FPS2: !%16g", *(float *)&mips->cpr[1][2]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPD2: sprintf(info->s, "FPD2: !%16g", *(double *)&mips->cpr[1][2]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR3: sprintf(info->s, "FPR3: %08X%08X", (UINT32)(mips->cpr[1][3] >> 32), (UINT32)mips->cpr[1][3]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPS3: sprintf(info->s, "FPS3: !%16g", *(float *)&mips->cpr[1][3]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPD3: sprintf(info->s, "FPD3: !%16g", *(double *)&mips->cpr[1][3]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR4: sprintf(info->s, "FPR4: %08X%08X", (UINT32)(mips->cpr[1][4] >> 32), (UINT32)mips->cpr[1][4]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPS4: sprintf(info->s, "FPS4: !%16g", *(float *)&mips->cpr[1][4]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPD4: sprintf(info->s, "FPD4: !%16g", *(double *)&mips->cpr[1][4]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR5: sprintf(info->s, "FPR5: %08X%08X", (UINT32)(mips->cpr[1][5] >> 32), (UINT32)mips->cpr[1][5]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPS5: sprintf(info->s, "FPS5: !%16g", *(float *)&mips->cpr[1][5]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPD5: sprintf(info->s, "FPD5: !%16g", *(double *)&mips->cpr[1][5]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR6: sprintf(info->s, "FPR6: %08X%08X", (UINT32)(mips->cpr[1][6] >> 32), (UINT32)mips->cpr[1][6]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPS6: sprintf(info->s, "FPS6: !%16g", *(float *)&mips->cpr[1][6]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPD6: sprintf(info->s, "FPD6: !%16g", *(double *)&mips->cpr[1][6]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR7: sprintf(info->s, "FPR7: %08X%08X", (UINT32)(mips->cpr[1][7] >> 32), (UINT32)mips->cpr[1][7]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPS7: sprintf(info->s, "FPS7: !%16g", *(float *)&mips->cpr[1][7]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPD7: sprintf(info->s, "FPD7: !%16g", *(double *)&mips->cpr[1][7]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR8: sprintf(info->s, "FPR8: %08X%08X", (UINT32)(mips->cpr[1][8] >> 32), (UINT32)mips->cpr[1][8]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPS8: sprintf(info->s, "FPS8: !%16g", *(float *)&mips->cpr[1][8]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPD8: sprintf(info->s, "FPD8: !%16g", *(double *)&mips->cpr[1][8]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR9: sprintf(info->s, "FPR9: %08X%08X", (UINT32)(mips->cpr[1][9] >> 32), (UINT32)mips->cpr[1][9]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPS9: sprintf(info->s, "FPS9: !%16g", *(float *)&mips->cpr[1][9]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPD9: sprintf(info->s, "FPD9: !%16g", *(double *)&mips->cpr[1][9]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR10: sprintf(info->s, "FPR10:%08X%08X", (UINT32)(mips->cpr[1][10] >> 32), (UINT32)mips->cpr[1][10]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPS10: sprintf(info->s, "FPS10:!%16g", *(float *)&mips->cpr[1][10]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPD10: sprintf(info->s, "FPD10:!%16g", *(double *)&mips->cpr[1][10]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR11: sprintf(info->s, "FPR11:%08X%08X", (UINT32)(mips->cpr[1][11] >> 32), (UINT32)mips->cpr[1][11]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPS11: sprintf(info->s, "FPS11:!%16g", *(float *)&mips->cpr[1][11]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPD11: sprintf(info->s, "FPD11:!%16g", *(double *)&mips->cpr[1][11]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR12: sprintf(info->s, "FPR12:%08X%08X", (UINT32)(mips->cpr[1][12] >> 32), (UINT32)mips->cpr[1][12]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPS12: sprintf(info->s, "FPS12:!%16g", *(float *)&mips->cpr[1][12]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPD12: sprintf(info->s, "FPD12:!%16g", *(double *)&mips->cpr[1][12]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR13: sprintf(info->s, "FPR13:%08X%08X", (UINT32)(mips->cpr[1][13] >> 32), (UINT32)mips->cpr[1][13]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPS13: sprintf(info->s, "FPS13:!%16g", *(float *)&mips->cpr[1][13]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPD13: sprintf(info->s, "FPD13:!%16g", *(double *)&mips->cpr[1][13]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR14: sprintf(info->s, "FPR14:%08X%08X", (UINT32)(mips->cpr[1][14] >> 32), (UINT32)mips->cpr[1][14]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPS14: sprintf(info->s, "FPS14:!%16g", *(float *)&mips->cpr[1][14]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPD14: sprintf(info->s, "FPD14:!%16g", *(double *)&mips->cpr[1][14]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR15: sprintf(info->s, "FPR15:%08X%08X", (UINT32)(mips->cpr[1][15] >> 32), (UINT32)mips->cpr[1][15]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPS15: sprintf(info->s, "FPS15:!%16g", *(float *)&mips->cpr[1][15]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPD15: sprintf(info->s, "FPD15:!%16g", *(double *)&mips->cpr[1][15]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR16: sprintf(info->s, "FPR16:%08X%08X", (UINT32)(mips->cpr[1][16] >> 32), (UINT32)mips->cpr[1][16]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPS16: sprintf(info->s, "FPS16:!%16g", *(float *)&mips->cpr[1][16]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPD16: sprintf(info->s, "FPD16:!%16g", *(double *)&mips->cpr[1][16]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR17: sprintf(info->s, "FPR17:%08X%08X", (UINT32)(mips->cpr[1][17] >> 32), (UINT32)mips->cpr[1][17]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPS17: sprintf(info->s, "FPS17:!%16g", *(float *)&mips->cpr[1][17]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPD17: sprintf(info->s, "FPD17:!%16g", *(double *)&mips->cpr[1][17]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR18: sprintf(info->s, "FPR18:%08X%08X", (UINT32)(mips->cpr[1][18] >> 32), (UINT32)mips->cpr[1][18]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPS18: sprintf(info->s, "FPS18:!%16g", *(float *)&mips->cpr[1][18]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPD18: sprintf(info->s, "FPD18:!%16g", *(double *)&mips->cpr[1][18]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR19: sprintf(info->s, "FPR19:%08X%08X", (UINT32)(mips->cpr[1][19] >> 32), (UINT32)mips->cpr[1][19]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPS19: sprintf(info->s, "FPS19:!%16g", *(float *)&mips->cpr[1][19]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPD19: sprintf(info->s, "FPD19:!%16g", *(double *)&mips->cpr[1][19]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR20: sprintf(info->s, "FPR20:%08X%08X", (UINT32)(mips->cpr[1][20] >> 32), (UINT32)mips->cpr[1][20]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPS20: sprintf(info->s, "FPS20:!%16g", *(float *)&mips->cpr[1][20]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPD20: sprintf(info->s, "FPD20:!%16g", *(double *)&mips->cpr[1][20]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR21: sprintf(info->s, "FPR21:%08X%08X", (UINT32)(mips->cpr[1][21] >> 32), (UINT32)mips->cpr[1][21]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPS21: sprintf(info->s, "FPS21:!%16g", *(float *)&mips->cpr[1][21]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPD21: sprintf(info->s, "FPD21:!%16g", *(double *)&mips->cpr[1][21]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR22: sprintf(info->s, "FPR22:%08X%08X", (UINT32)(mips->cpr[1][22] >> 32), (UINT32)mips->cpr[1][22]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPS22: sprintf(info->s, "FPS22:!%16g", *(float *)&mips->cpr[1][22]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPD22: sprintf(info->s, "FPD22:!%16g", *(double *)&mips->cpr[1][22]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR23: sprintf(info->s, "FPR23:%08X%08X", (UINT32)(mips->cpr[1][23] >> 32), (UINT32)mips->cpr[1][23]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPS23: sprintf(info->s, "FPS23:!%16g", *(float *)&mips->cpr[1][23]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPD23: sprintf(info->s, "FPD23:!%16g", *(double *)&mips->cpr[1][23]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR24: sprintf(info->s, "FPR24:%08X%08X", (UINT32)(mips->cpr[1][24] >> 32), (UINT32)mips->cpr[1][24]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPS24: sprintf(info->s, "FPS24:!%16g", *(float *)&mips->cpr[1][24]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPD24: sprintf(info->s, "FPD24:!%16g", *(double *)&mips->cpr[1][24]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR25: sprintf(info->s, "FPR25:%08X%08X", (UINT32)(mips->cpr[1][25] >> 32), (UINT32)mips->cpr[1][25]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPS25: sprintf(info->s, "FPS25:!%16g", *(float *)&mips->cpr[1][25]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPD25: sprintf(info->s, "FPD25:!%16g", *(double *)&mips->cpr[1][25]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR26: sprintf(info->s, "FPR26:%08X%08X", (UINT32)(mips->cpr[1][26] >> 32), (UINT32)mips->cpr[1][26]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPS26: sprintf(info->s, "FPS26:!%16g", *(float *)&mips->cpr[1][26]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPD26: sprintf(info->s, "FPD26:!%16g", *(double *)&mips->cpr[1][26]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR27: sprintf(info->s, "FPR27:%08X%08X", (UINT32)(mips->cpr[1][27] >> 32), (UINT32)mips->cpr[1][27]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPS27: sprintf(info->s, "FPS27:!%16g", *(float *)&mips->cpr[1][27]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPD27: sprintf(info->s, "FPD27:!%16g", *(double *)&mips->cpr[1][27]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR28: sprintf(info->s, "FPR28:%08X%08X", (UINT32)(mips->cpr[1][28] >> 32), (UINT32)mips->cpr[1][28]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPS28: sprintf(info->s, "FPS28:!%16g", *(float *)&mips->cpr[1][28]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPD28: sprintf(info->s, "FPD28:!%16g", *(double *)&mips->cpr[1][28]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR29: sprintf(info->s, "FPR29:%08X%08X", (UINT32)(mips->cpr[1][29] >> 32), (UINT32)mips->cpr[1][29]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPS29: sprintf(info->s, "FPS29:!%16g", *(float *)&mips->cpr[1][29]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPD29: sprintf(info->s, "FPD29:!%16g", *(double *)&mips->cpr[1][29]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR30: sprintf(info->s, "FPR30:%08X%08X", (UINT32)(mips->cpr[1][30] >> 32), (UINT32)mips->cpr[1][30]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPS30: sprintf(info->s, "FPS30:!%16g", *(float *)&mips->cpr[1][30]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPD30: sprintf(info->s, "FPD30:!%16g", *(double *)&mips->cpr[1][30]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR31: sprintf(info->s, "FPR31:%08X%08X", (UINT32)(mips->cpr[1][31] >> 32), (UINT32)mips->cpr[1][31]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPS31: sprintf(info->s, "FPS31:!%16g", *(float *)&mips->cpr[1][31]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPD31: sprintf(info->s, "FPD31:!%16g", *(double *)&mips->cpr[1][31]); break;
+ }
+}
+
+
+/***************************************************************************
+ INTERNAL HELPERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ compare_int_callback - callback that fires
+ whenever a compare interrupt is generated
+-------------------------------------------------*/
+
+static TIMER_CALLBACK( compare_int_callback )
+{
+ legacy_cpu_device *device = (legacy_cpu_device *)ptr;
+ device_set_input_line(device, MIPS3_IRQ5, ASSERT_LINE);
+}
+
+
+/*-------------------------------------------------
+ compute_config_register - compute the value
+ of the config register
+-------------------------------------------------*/
+
+static UINT32 compute_config_register(const mips3_state *mips)
+{
+ /* set the cache line size to 32 bytes */
+ UINT32 configreg = 0x00026030;
+ int divisor;
+
+ // NEC VR series does not use a 100% compatible COP0/TLB implementation
+ if (mips->flavor == MIPS3_TYPE_VR4300)
+ {
+ /*
+ For VR43xx, Config is as follows:
+ bit 31 = always 0
+ bits 28-30 = EC
+ bits 24-27 = EP
+ bits 16-23 = always b0000010
+ bit 15 = endian indicator as standard MIPS III
+ bits 4-14 = always b11001000110
+ bit 3 = CU
+ bits 0-2 = K0 ("Coherency algorithm of kseg0")
+ */
+
+ configreg = 0x6460;
+ }
+ else
+ {
+ /* set the data cache size */
+ if (mips->icache_size <= 0x01000) configreg |= 0 << 6;
+ else if (mips->icache_size <= 0x02000) configreg |= 1 << 6;
+ else if (mips->icache_size <= 0x04000) configreg |= 2 << 6;
+ else if (mips->icache_size <= 0x08000) configreg |= 3 << 6;
+ else if (mips->icache_size <= 0x10000) configreg |= 4 << 6;
+ else if (mips->icache_size <= 0x20000) configreg |= 5 << 6;
+ else if (mips->icache_size <= 0x40000) configreg |= 6 << 6;
+ else configreg |= 7 << 6;
+
+ /* set the instruction cache size */
+ if (mips->icache_size <= 0x01000) configreg |= 0 << 9;
+ else if (mips->icache_size <= 0x02000) configreg |= 1 << 9;
+ else if (mips->icache_size <= 0x04000) configreg |= 2 << 9;
+ else if (mips->icache_size <= 0x08000) configreg |= 3 << 9;
+ else if (mips->icache_size <= 0x10000) configreg |= 4 << 9;
+ else if (mips->icache_size <= 0x20000) configreg |= 5 << 9;
+ else if (mips->icache_size <= 0x40000) configreg |= 6 << 9;
+ else configreg |= 7 << 9;
+
+
+ /* set the system clock divider */
+ divisor = 2;
+ if (mips->system_clock != 0)
+ {
+ divisor = mips->cpu_clock / mips->system_clock;
+ if (mips->system_clock * divisor != mips->cpu_clock)
+ {
+ configreg |= 0x80000000;
+ divisor = mips->cpu_clock * 2 / mips->system_clock;
+ }
+ }
+ configreg |= (((divisor < 2) ? 2 : (divisor > 8) ? 8 : divisor) - 2) << 28;
+ }
+
+ /* set the endianness bit */
+ if (mips->bigendian)
+ configreg |= 0x00008000;
+
+ return configreg;
+}
+
+
+/*-------------------------------------------------
+ compute_prid_register - compute the value
+ of the PRId register
+-------------------------------------------------*/
+
+static UINT32 compute_prid_register(const mips3_state *mips)
+{
+ switch (mips->flavor)
+ {
+ case MIPS3_TYPE_VR4300:
+ return 0x0b00;
+
+ case MIPS3_TYPE_R4600:
+ case MIPS3_TYPE_R4650:
+ return 0x2000;
+
+ case MIPS3_TYPE_R4700:
+ return 0x2100;
+
+ case MIPS3_TYPE_R5000:
+ case MIPS3_TYPE_QED5271:
+ return 0x2300;
+
+ case MIPS3_TYPE_RM7000:
+ return 0x2700;
+
+ default:
+ fatalerror("Unknown MIPS flavor specified");
+ }
+ return 0x2000;
+}
+
+
+/*-------------------------------------------------
+ tlb_map_entry - map a single TLB
+ entry
+-------------------------------------------------*/
+
+static void tlb_map_entry(mips3_state *mips, int tlbindex)
+{
+ int current_asid = mips->cpr[0][COP0_EntryHi] & 0xff;
+ mips3_tlb_entry *entry = &mips->tlb[tlbindex];
+ UINT32 count, vpn;
+ int which;
+
+ /* the ASID doesn't match the current ASID, and if the page isn't global, unmap it from the TLB */
+ if (!tlb_entry_matches_asid(entry, current_asid) && !tlb_entry_is_global(entry))
+ {
+ vtlb_load(mips->vtlb, 2 * tlbindex + 0, 0, 0, 0);
+ vtlb_load(mips->vtlb, 2 * tlbindex + 1, 0, 0, 0);
+ return;
+ }
+
+ /* extract the VPN index; ignore if the virtual address is beyond 32 bits */
+ vpn = ((entry->entry_hi >> 13) & 0x07ffffff) << 1;
+ if (vpn >= (1 << (MIPS3_MAX_PADDR_SHIFT - MIPS3_MIN_PAGE_SHIFT)))
+ {
+ vtlb_load(mips->vtlb, 2 * tlbindex + 0, 0, 0, 0);
+ vtlb_load(mips->vtlb, 2 * tlbindex + 1, 0, 0, 0);
+ return;
+ }
+
+ /* get the number of pages from the page mask */
+ count = ((entry->page_mask >> 13) & 0x00fff) + 1;
+
+ /* loop over both the even and odd pages */
+ for (which = 0; which < 2; which++)
+ {
+ UINT32 effvpn = vpn + count * which;
+ UINT64 lo = entry->entry_lo[which];
+ UINT32 pfn;
+ UINT32 flags = 0;
+
+ /* compute physical page index */
+ pfn = (lo >> 6) & mips->pfnmask;
+
+ /* valid? */
+ if ((lo & 2) != 0)
+ {
+ flags |= VTLB_FLAG_VALID | VTLB_READ_ALLOWED | VTLB_FETCH_ALLOWED;
+
+ /* writable? */
+ if ((lo & 4) != 0)
+ flags |= VTLB_WRITE_ALLOWED;
+
+ /* mirror the flags for user mode if the VPN is in user space */
+ if (effvpn < (0x80000000 >> MIPS3_MIN_PAGE_SHIFT))
+ flags |= (flags << 4) & (VTLB_USER_READ_ALLOWED | VTLB_USER_WRITE_ALLOWED | VTLB_USER_FETCH_ALLOWED);
+ }
+
+ /* load the virtual TLB with the corresponding entries */
+ if ((effvpn + count) <= (0x80000000 >> MIPS3_MIN_PAGE_SHIFT) || effvpn >= (0xc0000000 >> MIPS3_MIN_PAGE_SHIFT))
+ vtlb_load(mips->vtlb, 2 * tlbindex + which, count, effvpn << MIPS3_MIN_PAGE_SHIFT, (pfn << MIPS3_MIN_PAGE_SHIFT) | flags);
+ else
+ vtlb_load(mips->vtlb, 2 * tlbindex + which, 0, 0, 0);
+ }
+}
+
+
+/*-------------------------------------------------
+ tlb_write_common - common routine for writing
+ a TLB entry
+-------------------------------------------------*/
+
+static void tlb_write_common(mips3_state *mips, int tlbindex)
+{
+ /* only handle entries within the TLB */
+ if (tlbindex < mips->tlbentries)
+ {
+ mips3_tlb_entry *entry = &mips->tlb[tlbindex];
+
+ /* fill in the new TLB entry from the COP0 registers */
+ entry->page_mask = mips->cpr[0][COP0_PageMask];
+ entry->entry_hi = mips->cpr[0][COP0_EntryHi] & ~(entry->page_mask & U64(0x0000000001ffe000));
+ entry->entry_lo[0] = mips->cpr[0][COP0_EntryLo0];
+ entry->entry_lo[1] = mips->cpr[0][COP0_EntryLo1];
+
+ /* remap this TLB entry */
+ tlb_map_entry(mips, tlbindex);
+
+ /* log the two halves once they are in */
+ tlb_entry_log_half(entry, tlbindex, 0);
+ tlb_entry_log_half(entry, tlbindex, 1);
+ }
+}
+
+
+/*-------------------------------------------------
+ tlb_entry_log_half - log half of a single TLB
+ entry
+-------------------------------------------------*/
+
+static void tlb_entry_log_half(mips3_tlb_entry *entry, int tlbindex, int which)
+{
+if (PRINTF_TLB)
+{
+ UINT64 hi = entry->entry_hi;
+ UINT64 lo = entry->entry_lo[which];
+ UINT32 vpn = (((hi >> 13) & 0x07ffffff) << 1);
+ UINT32 asid = hi & 0xff;
+ UINT32 r = (hi >> 62) & 3;
+ UINT32 pfn = (lo >> 6) & 0x00ffffff;
+ UINT32 c = (lo >> 3) & 7;
+ UINT32 pagesize = (((entry->page_mask >> 13) & 0xfff) + 1) << MIPS3_MIN_PAGE_SHIFT;
+ UINT64 vaddr = (UINT64)vpn * MIPS3_MIN_PAGE_SIZE;
+ UINT64 paddr = (UINT64)pfn * MIPS3_MIN_PAGE_SIZE;
+
+ vaddr += pagesize * which;
+
+ printf("index=%08X pagesize=%08X vaddr=%08X%08X paddr=%08X%08X asid=%02X r=%X c=%X dvg=%c%c%c\n",
+ tlbindex, pagesize, (UINT32)(vaddr >> 32), (UINT32)vaddr, (UINT32)(paddr >> 32), (UINT32)paddr,
+ asid, r, c, (lo & 4) ? 'd' : '.', (lo & 2) ? 'v' : '.', (lo & 1) ? 'g' : '.');
+}
+}
diff --git a/trunk/src/emu/cpu/mips/mips3com.h b/trunk/src/emu/cpu/mips/mips3com.h
new file mode 100644
index 00000000000..ac89400fa71
--- /dev/null
+++ b/trunk/src/emu/cpu/mips/mips3com.h
@@ -0,0 +1,271 @@
+/***************************************************************************
+
+ mips3com.h
+
+ Common MIPS III/IV definitions and functions
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __MIPS3COM_H__
+#define __MIPS3COM_H__
+
+#include "mips3.h"
+#include "cpu/vtlb.h"
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define MIPS3_USE_DRC
+
+/* core parameters */
+#define MIPS3_MIN_PAGE_SHIFT 12
+#define MIPS3_MIN_PAGE_SIZE (1 << MIPS3_MIN_PAGE_SHIFT)
+#define MIPS3_MIN_PAGE_MASK (MIPS3_MIN_PAGE_SIZE - 1)
+#define MIPS3_MAX_PADDR_SHIFT 32
+#define MIPS3_MAX_TLB_ENTRIES 48
+
+/* cycle parameters */
+#define MIPS3_COUNT_READ_CYCLES 250
+#define MIPS3_CAUSE_READ_CYCLES 250
+
+/* MIPS flavors */
+enum _mips3_flavor
+{
+ /* MIPS III variants */
+ MIPS3_TYPE_MIPS_III,
+ MIPS3_TYPE_VR4300,
+ MIPS3_TYPE_R4600,
+ MIPS3_TYPE_R4650,
+ MIPS3_TYPE_R4700,
+
+ /* MIPS IV variants */
+ MIPS3_TYPE_MIPS_IV,
+ MIPS3_TYPE_R5000,
+ MIPS3_TYPE_QED5271,
+ MIPS3_TYPE_RM7000
+};
+typedef enum _mips3_flavor mips3_flavor;
+
+/* TLB bits */
+#define TLB_GLOBAL 0x01
+#define TLB_VALID 0x02
+#define TLB_DIRTY 0x04
+#define TLB_PRESENT 0x08
+
+/* COP0 registers */
+#define COP0_Index 0
+#define COP0_Random 1
+#define COP0_EntryLo 2
+#define COP0_EntryLo0 2
+#define COP0_EntryLo1 3
+#define COP0_Context 4
+#define COP0_PageMask 5
+#define COP0_Wired 6
+#define COP0_BadVAddr 8
+#define COP0_Count 9
+#define COP0_EntryHi 10
+#define COP0_Compare 11
+#define COP0_Status 12
+#define COP0_Cause 13
+#define COP0_EPC 14
+#define COP0_PRId 15
+#define COP0_Config 16
+#define COP0_LLAddr 17
+#define COP0_XContext 20
+#define COP0_ECC 26
+#define COP0_CacheErr 27
+#define COP0_TagLo 28
+#define COP0_TagHi 29
+#define COP0_ErrorPC 30
+
+/* Status register bits */
+#define SR_IE 0x00000001
+#define SR_EXL 0x00000002
+#define SR_ERL 0x00000004
+#define SR_KSU_MASK 0x00000018
+#define SR_KSU_KERNEL 0x00000000
+#define SR_KSU_SUPERVISOR 0x00000008
+#define SR_KSU_USER 0x00000010
+#define SR_IMSW0 0x00000100
+#define SR_IMSW1 0x00000200
+#define SR_IMEX0 0x00000400
+#define SR_IMEX1 0x00000800
+#define SR_IMEX2 0x00001000
+#define SR_IMEX3 0x00002000
+#define SR_IMEX4 0x00004000
+#define SR_IMEX5 0x00008000
+#define SR_DE 0x00010000
+#define SR_CE 0x00020000
+#define SR_CH 0x00040000
+#define SR_SR 0x00100000
+#define SR_TS 0x00200000
+#define SR_BEV 0x00400000
+#define SR_ITS 0x01000000 /* VR4300 only, Application Note doesn't give purpose */
+#define SR_RE 0x02000000
+#define SR_FR 0x04000000
+#define SR_RP 0x08000000
+#define SR_COP0 0x10000000
+#define SR_COP1 0x20000000
+#define SR_COP2 0x40000000
+#define SR_COP3 0x80000000
+
+/* exception types */
+#define EXCEPTION_INTERRUPT 0
+#define EXCEPTION_TLBMOD 1
+#define EXCEPTION_TLBLOAD 2
+#define EXCEPTION_TLBSTORE 3
+#define EXCEPTION_ADDRLOAD 4
+#define EXCEPTION_ADDRSTORE 5
+#define EXCEPTION_BUSINST 6
+#define EXCEPTION_BUSDATA 7
+#define EXCEPTION_SYSCALL 8
+#define EXCEPTION_BREAK 9
+#define EXCEPTION_INVALIDOP 10
+#define EXCEPTION_BADCOP 11
+#define EXCEPTION_OVERFLOW 12
+#define EXCEPTION_TRAP 13
+#define EXCEPTION_TLBLOAD_FILL 16
+#define EXCEPTION_TLBSTORE_FILL 17
+#define EXCEPTION_COUNT 18
+
+
+
+/***************************************************************************
+ HELPER MACROS
+***************************************************************************/
+
+#define REG_LO 32
+#define REG_HI 33
+
+#define RSREG ((op >> 21) & 31)
+#define RTREG ((op >> 16) & 31)
+#define RDREG ((op >> 11) & 31)
+#define SHIFT ((op >> 6) & 31)
+
+#define FRREG ((op >> 21) & 31)
+#define FTREG ((op >> 16) & 31)
+#define FSREG ((op >> 11) & 31)
+#define FDREG ((op >> 6) & 31)
+
+#define IS_SINGLE(o) (((o) & (1 << 21)) == 0)
+#define IS_DOUBLE(o) (((o) & (1 << 21)) != 0)
+#define IS_FLOAT(o) (((o) & (1 << 23)) == 0)
+#define IS_INTEGRAL(o) (((o) & (1 << 23)) != 0)
+
+#define SIMMVAL ((INT16)op)
+#define UIMMVAL ((UINT16)op)
+#define LIMMVAL (op & 0x03ffffff)
+
+
+
+/***************************************************************************
+ STRUCTURES & TYPEDEFS
+***************************************************************************/
+
+/* MIPS3 TLB entry */
+typedef struct _mips3_tlb_entry mips3_tlb_entry;
+struct _mips3_tlb_entry
+{
+ UINT64 page_mask;
+ UINT64 entry_hi;
+ UINT64 entry_lo[2];
+};
+
+
+/* forward declaration of implementation-specific state */
+typedef struct _mips3imp_state mips3imp_state;
+
+
+/* MIPS3 state */
+typedef struct _mips3_state mips3_state;
+struct _mips3_state
+{
+ /* core registers */
+ UINT32 pc;
+ int icount;
+ UINT64 r[35];
+
+ /* COP registers */
+ UINT64 cpr[3][32];
+ UINT64 ccr[3][32];
+ UINT32 llbit;
+
+ /* internal stuff */
+ mips3_flavor flavor;
+ device_irq_callback irq_callback;
+ legacy_cpu_device * device;
+ address_space *program;
+ direct_read_data *direct;
+ UINT32 system_clock;
+ UINT32 cpu_clock;
+ UINT64 count_zero_time;
+ UINT32 compare_armed;
+ emu_timer * compare_int_timer;
+
+ /* derived info based on flavor */
+ UINT32 pfnmask;
+ UINT8 tlbentries;
+
+ /* memory accesses */
+ UINT8 bigendian;
+ data_accessors memory;
+
+ /* cache memory */
+ size_t icache_size;
+ size_t dcache_size;
+
+ /* MMU */
+ vtlb_state * vtlb;
+ mips3_tlb_entry tlb[MIPS3_MAX_TLB_ENTRIES];
+
+ /* for use by specific implementations */
+ mips3imp_state *impstate;
+};
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+void mips3com_init(mips3_state *mips, mips3_flavor flavor, int bigendian, legacy_cpu_device *device, device_irq_callback irqcallback);
+void mips3com_exit(mips3_state *mips);
+
+void mips3com_reset(mips3_state *mips);
+offs_t mips3com_dasm(mips3_state *mips, char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram);
+void mips3com_update_cycle_counting(mips3_state *mips);
+
+void mips3com_asid_changed(mips3_state *mips);
+int mips3com_translate_address(mips3_state *mips, address_spacenum space, int intention, offs_t *address);
+void mips3com_tlbr(mips3_state *mips);
+void mips3com_tlbwi(mips3_state *mips);
+void mips3com_tlbwr(mips3_state *mips);
+void mips3com_tlbp(mips3_state *mips);
+
+void mips3com_set_info(mips3_state *mips, UINT32 state, cpuinfo *info);
+void mips3com_get_info(mips3_state *mips, UINT32 state, cpuinfo *info);
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ mips3com_set_irq_line - set or clear the given
+ IRQ line
+-------------------------------------------------*/
+
+INLINE void mips3com_set_irq_line(mips3_state *mips, int irqline, int state)
+{
+ if (state != CLEAR_LINE)
+ mips->cpr[0][COP0_Cause] |= 0x400 << irqline;
+ else
+ mips->cpr[0][COP0_Cause] &= ~(0x400 << irqline);
+}
+
+#endif /* __MIPS3COM_H__ */
diff --git a/trunk/src/emu/cpu/mips/mips3drc.c b/trunk/src/emu/cpu/mips/mips3drc.c
new file mode 100644
index 00000000000..f62c4d16c8b
--- /dev/null
+++ b/trunk/src/emu/cpu/mips/mips3drc.c
@@ -0,0 +1,4104 @@
+/***************************************************************************
+
+ mips3drc.c
+
+ Universal machine language-based MIPS III/IV emulator.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+****************************************************************************
+
+ Future improvements/changes:
+
+ * Add DRC option to flush PC before calling memory handlers
+
+ * Constant tracking? (hasn't bought us much in the past)
+
+ * Customized mapped/unmapped memory handlers
+ - create 3 sets of handlers: cached, uncached, general
+ - default to general
+ - in general case, if cached use RECALL to point to cached code
+ - (same for uncached)
+ - in cached/uncached case, fall back to general case
+
+***************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "profiler.h"
+#include "mips3com.h"
+#include "mips3fe.h"
+#include "cpu/drcfe.h"
+#include "cpu/drcuml.h"
+#include "cpu/drcumlsh.h"
+
+extern unsigned dasmmips3(char *buffer, unsigned pc, UINT32 op);
+
+#ifdef MIPS3_USE_DRC
+
+using namespace uml;
+
+/***************************************************************************
+ DEBUGGING
+***************************************************************************/
+
+#define FORCE_C_BACKEND (0)
+#define LOG_UML (0)
+#define LOG_NATIVE (0)
+
+#define DISABLE_FAST_REGISTERS (0)
+#define SINGLE_INSTRUCTION_MODE (0)
+
+#define PRINTF_EXCEPTIONS (0)
+#define PRINTF_MMU (0)
+
+#define PROBE_ADDRESS ~0
+
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+/* map variables */
+#define MAPVAR_PC M0
+#define MAPVAR_CYCLES M1
+
+/* modes */
+#define MODE_KERNEL 0
+#define MODE_SUPER 1
+#define MODE_USER 2
+
+/* size of the execution code cache */
+#define CACHE_SIZE (32 * 1024 * 1024)
+
+/* compilation boundaries -- how far back/forward does the analysis extend? */
+#define COMPILE_BACKWARDS_BYTES 128
+#define COMPILE_FORWARDS_BYTES 512
+#define COMPILE_MAX_INSTRUCTIONS ((COMPILE_BACKWARDS_BYTES/4) + (COMPILE_FORWARDS_BYTES/4))
+#define COMPILE_MAX_SEQUENCE 64
+
+/* exit codes */
+#define EXECUTE_OUT_OF_CYCLES 0
+#define EXECUTE_MISSING_CODE 1
+#define EXECUTE_UNMAPPED_CODE 2
+#define EXECUTE_RESET_CACHE 3
+
+
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+#define LOPTR(x) ((UINT32 *)(x) + NATIVE_ENDIAN_VALUE_LE_BE(0,1))
+
+#define R32(reg) mips3->impstate->regmaplo[reg]
+#define LO32 R32(REG_LO)
+#define HI32 R32(REG_HI)
+#define CPR032(reg) mem(LOPTR(&mips3->cpr[0][reg]))
+#define CCR032(reg) mem(LOPTR(&mips3->ccr[0][reg]))
+#define FPR32(reg) mem(((mips3->impstate->mode & 1) == 0) ? &((float *)&mips3->cpr[1][0])[reg] : (float *)&mips3->cpr[1][reg])
+#define CCR132(reg) mem(LOPTR(&mips3->ccr[1][reg]))
+#define CPR232(reg) mem(LOPTR(&mips3->cpr[2][reg]))
+#define CCR232(reg) mem(LOPTR(&mips3->ccr[2][reg]))
+
+#define R64(reg) mips3->impstate->regmap[reg]
+#define LO64 R64(REG_LO)
+#define HI64 R64(REG_HI)
+#define CPR064(reg) mem(&mips3->cpr[0][reg])
+#define CCR064(reg) mem(&mips3->ccr[0][reg])
+#define FPR64(reg) mem(((mips3->impstate->mode & 1) == 0) ? (double *)&mips3->cpr[1][(reg)/2] : (double *)&mips3->cpr[1][reg])
+#define CCR164(reg) mem(&mips3->ccr[1][reg])
+#define CPR264(reg) mem(&mips3->cpr[2][reg])
+#define CCR264(reg) mem(&mips3->ccr[2][reg])
+
+#define FCCSHIFT(which) fcc_shift[(mips3->flavor < MIPS3_TYPE_MIPS_IV) ? 0 : ((which) & 7)]
+#define FCCMASK(which) ((UINT32)(1 << FCCSHIFT(which)))
+
+
+
+/***************************************************************************
+ STRUCTURES & TYPEDEFS
+***************************************************************************/
+
+/* fast RAM info */
+typedef struct _fast_ram_info fast_ram_info;
+struct _fast_ram_info
+{
+ offs_t start; /* start of the RAM block */
+ offs_t end; /* end of the RAM block */
+ UINT8 readonly; /* TRUE if read-only */
+ void * base; /* base in memory where the RAM lives */
+};
+
+
+/* hotspot info */
+typedef struct _hotspot_info hotspot_info;
+struct _hotspot_info
+{
+ offs_t pc; /* PC to consider */
+ UINT32 opcode; /* required opcode at that PC */
+ UINT32 cycles; /* number of cycles to eat when hit */
+};
+
+
+/* internal compiler state */
+typedef struct _compiler_state compiler_state;
+struct _compiler_state
+{
+ UINT32 cycles; /* accumulated cycles */
+ UINT8 checkints; /* need to check interrupts before next instruction */
+ UINT8 checksoftints; /* need to check software interrupts before next instruction */
+ code_label labelnum; /* index for local labels */
+};
+
+
+/* MIPS3 registers */
+struct _mips3imp_state
+{
+ /* core state */
+ drc_cache * cache; /* pointer to the DRC code cache */
+ drcuml_state * drcuml; /* DRC UML generator state */
+ mips3_frontend * drcfe; /* pointer to the DRC front-end state */
+ UINT32 drcoptions; /* configurable DRC options */
+
+ /* internal stuff */
+ UINT8 cache_dirty; /* true if we need to flush the cache */
+ UINT32 jmpdest; /* destination jump target */
+
+ /* parameters for subroutines */
+ UINT64 numcycles; /* return value from gettotalcycles */
+ UINT32 mode; /* current global mode */
+ const char * format; /* format string for print_debug */
+ UINT32 arg0; /* print_debug argument 1 */
+ UINT32 arg1; /* print_debug argument 2 */
+
+ /* tables */
+ UINT8 fpmode[4]; /* FPU mode table */
+
+ /* register mappings */
+ parameter regmap[34]; /* parameter to register mappings for all 32 integer registers */
+ parameter regmaplo[34]; /* parameter to register mappings for all 32 integer registers */
+
+ /* subroutines */
+ code_handle * entry; /* entry point */
+ code_handle * nocode; /* nocode exception handler */
+ code_handle * out_of_cycles; /* out of cycles exception handler */
+ code_handle * tlb_mismatch; /* tlb mismatch handler */
+ code_handle * read8[3]; /* read byte */
+ code_handle * write8[3]; /* write byte */
+ code_handle * read16[3]; /* read half */
+ code_handle * write16[3]; /* write half */
+ code_handle * read32[3]; /* read word */
+ code_handle * read32mask[3]; /* read word masked */
+ code_handle * write32[3]; /* write word */
+ code_handle * write32mask[3]; /* write word masked */
+ code_handle * read64[3]; /* read double */
+ code_handle * read64mask[3]; /* read double masked */
+ code_handle * write64[3]; /* write double */
+ code_handle * write64mask[3]; /* write double masked */
+ code_handle * exception[EXCEPTION_COUNT]; /* array of exception handlers */
+ code_handle * exception_norecover[EXCEPTION_COUNT]; /* array of no-recover exception handlers */
+
+ /* fast RAM */
+ UINT32 fastram_select;
+ fast_ram_info fastram[MIPS3_MAX_FASTRAM];
+
+ /* hotspots */
+ UINT32 hotspot_select;
+ hotspot_info hotspot[MIPS3_MAX_HOTSPOTS];
+};
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static void code_flush_cache(mips3_state *mips3);
+static void code_compile_block(mips3_state *mips3, UINT8 mode, offs_t pc);
+
+static void cfunc_printf_exception(void *param);
+static void cfunc_get_cycles(void *param);
+static void cfunc_printf_probe(void *param);
+
+static void static_generate_entry_point(mips3_state *mips3);
+static void static_generate_nocode_handler(mips3_state *mips3);
+static void static_generate_out_of_cycles(mips3_state *mips3);
+static void static_generate_tlb_mismatch(mips3_state *mips3);
+static void static_generate_exception(mips3_state *mips3, UINT8 exception, int recover, const char *name);
+static void static_generate_memory_accessor(mips3_state *mips3, int mode, int size, int iswrite, int ismasked, const char *name, code_handle **handleptr);
+
+static void generate_update_mode(mips3_state *mips3, drcuml_block *block);
+static void generate_update_cycles(mips3_state *mips3, drcuml_block *block, compiler_state *compiler, parameter param, int allow_exception);
+static void generate_checksum_block(mips3_state *mips3, drcuml_block *block, compiler_state *compiler, const opcode_desc *seqhead, const opcode_desc *seqlast);
+static void generate_sequence_instruction(mips3_state *mips3, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+static void generate_delay_slot_and_branch(mips3_state *mips3, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT8 linkreg);
+static int generate_opcode(mips3_state *mips3, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+static int generate_special(mips3_state *mips3, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+static int generate_regimm(mips3_state *mips3, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+static int generate_idt(mips3_state *mips3, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+static int generate_set_cop0_reg(mips3_state *mips3, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT8 reg);
+static int generate_get_cop0_reg(mips3_state *mips3, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT8 reg);
+static int generate_cop0(mips3_state *mips3, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+static int generate_cop1(mips3_state *mips3, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+static int generate_cop1x(mips3_state *mips3, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+
+static void log_add_disasm_comment(mips3_state *mips3, drcuml_block *block, UINT32 pc, UINT32 op);
+static const char *log_desc_flags_to_string(UINT32 flags);
+static void log_register_list(drcuml_state *drcuml, const char *string, const UINT32 *reglist, const UINT32 *regnostarlist);
+static void log_opcode_desc(drcuml_state *drcuml, const opcode_desc *desclist, int indent);
+
+
+
+/***************************************************************************
+ PRIVATE GLOBAL VARIABLES
+***************************************************************************/
+
+/* bit indexes for various FCCs */
+static const UINT8 fcc_shift[8] = { 23, 25, 26, 27, 28, 29, 30, 31 };
+
+/* lookup table for FP modes */
+static const UINT8 fpmode_source[4] =
+{
+ ROUND_ROUND,
+ ROUND_TRUNC,
+ ROUND_CEIL,
+ ROUND_FLOOR
+};
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+INLINE mips3_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == VR4300BE ||
+ device->type() == VR4300LE ||
+ device->type() == VR4310BE ||
+ device->type() == VR4310LE ||
+ device->type() == R4600BE ||
+ device->type() == R4600LE ||
+ device->type() == R4650BE ||
+ device->type() == R4650LE ||
+ device->type() == R4700BE ||
+ device->type() == R4700LE ||
+ device->type() == R5000BE ||
+ device->type() == R5000LE ||
+ device->type() == QED5271BE ||
+ device->type() == QED5271LE ||
+ device->type() == RM7000BE ||
+ device->type() == RM7000LE);
+ return *(mips3_state **)downcast<legacy_cpu_device *>(device)->token();
+}
+
+
+/*-------------------------------------------------
+ epc - compute the exception PC from a
+ descriptor
+-------------------------------------------------*/
+
+INLINE UINT32 epc(const opcode_desc *desc)
+{
+ return (desc->flags & OPFLAG_IN_DELAY_SLOT) ? (desc->pc - 3) : desc->pc;
+}
+
+
+/*-------------------------------------------------
+ alloc_handle - allocate a handle if not
+ already allocated
+-------------------------------------------------*/
+
+INLINE void alloc_handle(drcuml_state *drcuml, code_handle **handleptr, const char *name)
+{
+ if (*handleptr == NULL)
+ *handleptr = drcuml->handle_alloc(name);
+}
+
+
+/*-------------------------------------------------
+ load_fast_iregs - load any fast integer
+ registers
+-------------------------------------------------*/
+
+INLINE void load_fast_iregs(mips3_state *mips3, drcuml_block *block)
+{
+ int regnum;
+
+ for (regnum = 0; regnum < ARRAY_LENGTH(mips3->impstate->regmap); regnum++)
+ if (mips3->impstate->regmap[regnum].is_int_register())
+ UML_DMOV(block, ireg(mips3->impstate->regmap[regnum].ireg() - REG_I0), mem(&mips3->r[regnum]));
+}
+
+
+/*-------------------------------------------------
+ save_fast_iregs - save any fast integer
+ registers
+-------------------------------------------------*/
+
+INLINE void save_fast_iregs(mips3_state *mips3, drcuml_block *block)
+{
+ int regnum;
+
+ for (regnum = 0; regnum < ARRAY_LENGTH(mips3->impstate->regmap); regnum++)
+ if (mips3->impstate->regmap[regnum].is_int_register())
+ UML_DMOV(block, mem(&mips3->r[regnum]), ireg(mips3->impstate->regmap[regnum].ireg() - REG_I0));
+}
+
+
+
+/***************************************************************************
+ CORE CALLBACKS
+***************************************************************************/
+
+/*-------------------------------------------------
+ mips3_init - initialize the processor
+-------------------------------------------------*/
+
+static void mips3_init(mips3_flavor flavor, int bigendian, legacy_cpu_device *device, device_irq_callback irqcallback)
+{
+ mips3_state *mips3;
+ drc_cache *cache;
+ drcbe_info beinfo;
+ UINT32 flags = 0;
+ int regnum;
+
+ /* allocate enough space for the cache and the core */
+ cache = auto_alloc(device->machine(), drc_cache(CACHE_SIZE + sizeof(*mips3)));
+ if (cache == NULL)
+ fatalerror("Unable to allocate cache of size %d", (UINT32)(CACHE_SIZE + sizeof(*mips3)));
+
+ /* allocate the core memory */
+ *(mips3_state **)device->token() = mips3 = (mips3_state *)cache->alloc_near(sizeof(*mips3));
+ memset(mips3, 0, sizeof(*mips3));
+
+ /* initialize the core */
+ mips3com_init(mips3, flavor, bigendian, device, irqcallback);
+
+ /* allocate the implementation-specific state from the full cache */
+ mips3->impstate = (mips3imp_state *)cache->alloc_near(sizeof(*mips3->impstate));
+ memset(mips3->impstate, 0, sizeof(*mips3->impstate));
+ mips3->impstate->cache = cache;
+
+ /* initialize the UML generator */
+ if (FORCE_C_BACKEND)
+ flags |= DRCUML_OPTION_USE_C;
+ if (LOG_UML)
+ flags |= DRCUML_OPTION_LOG_UML;
+ if (LOG_NATIVE)
+ flags |= DRCUML_OPTION_LOG_NATIVE;
+ mips3->impstate->drcuml = auto_alloc(device->machine(), drcuml_state(*device, *cache, flags, 8, 32, 2));
+
+ /* add symbols for our stuff */
+ mips3->impstate->drcuml->symbol_add(&mips3->pc, sizeof(mips3->pc), "pc");
+ mips3->impstate->drcuml->symbol_add(&mips3->icount, sizeof(mips3->icount), "icount");
+ for (regnum = 0; regnum < 32; regnum++)
+ {
+ char buf[10];
+ sprintf(buf, "r%d", regnum);
+ mips3->impstate->drcuml->symbol_add(&mips3->r[regnum], sizeof(mips3->r[regnum]), buf);
+ sprintf(buf, "f%d", regnum);
+ mips3->impstate->drcuml->symbol_add(&mips3->cpr[1][regnum], sizeof(mips3->cpr[1][regnum]), buf);
+ }
+ mips3->impstate->drcuml->symbol_add(&mips3->r[REG_LO], sizeof(mips3->r[REG_LO]), "lo");
+ mips3->impstate->drcuml->symbol_add(&mips3->r[REG_HI], sizeof(mips3->r[REG_LO]), "hi");
+ mips3->impstate->drcuml->symbol_add(&mips3->cpr[0][COP0_Index], sizeof(mips3->cpr[0][COP0_Index]), "Index");
+ mips3->impstate->drcuml->symbol_add(&mips3->cpr[0][COP0_Random], sizeof(mips3->cpr[0][COP0_Random]), "Random");
+ mips3->impstate->drcuml->symbol_add(&mips3->cpr[0][COP0_EntryLo0], sizeof(mips3->cpr[0][COP0_EntryLo0]), "EntryLo0");
+ mips3->impstate->drcuml->symbol_add(&mips3->cpr[0][COP0_EntryLo1], sizeof(mips3->cpr[0][COP0_EntryLo1]), "EntryLo1");
+ mips3->impstate->drcuml->symbol_add(&mips3->cpr[0][COP0_Context], sizeof(mips3->cpr[0][COP0_Context]), "Context");
+ mips3->impstate->drcuml->symbol_add(&mips3->cpr[0][COP0_PageMask], sizeof(mips3->cpr[0][COP0_PageMask]), "PageMask");
+ mips3->impstate->drcuml->symbol_add(&mips3->cpr[0][COP0_Wired], sizeof(mips3->cpr[0][COP0_Wired]), "Wired");
+ mips3->impstate->drcuml->symbol_add(&mips3->cpr[0][COP0_BadVAddr], sizeof(mips3->cpr[0][COP0_BadVAddr]), "BadVAddr");
+ mips3->impstate->drcuml->symbol_add(&mips3->cpr[0][COP0_Count], sizeof(mips3->cpr[0][COP0_Count]), "Count");
+ mips3->impstate->drcuml->symbol_add(&mips3->cpr[0][COP0_EntryHi], sizeof(mips3->cpr[0][COP0_EntryHi]), "EntryHi");
+ mips3->impstate->drcuml->symbol_add(&mips3->cpr[0][COP0_Compare], sizeof(mips3->cpr[0][COP0_Compare]), "Compare");
+ mips3->impstate->drcuml->symbol_add(&mips3->cpr[0][COP0_Status], sizeof(mips3->cpr[0][COP0_Status]), "Status");
+ mips3->impstate->drcuml->symbol_add(&mips3->cpr[0][COP0_Cause], sizeof(mips3->cpr[0][COP0_Cause]), "Cause");
+ mips3->impstate->drcuml->symbol_add(&mips3->cpr[0][COP0_EPC], sizeof(mips3->cpr[0][COP0_EPC]), "EPC");
+ mips3->impstate->drcuml->symbol_add(&mips3->cpr[0][COP0_PRId], sizeof(mips3->cpr[0][COP0_PRId]), "PRId");
+ mips3->impstate->drcuml->symbol_add(&mips3->cpr[0][COP0_Config], sizeof(mips3->cpr[0][COP0_Config]), "Config");
+ mips3->impstate->drcuml->symbol_add(&mips3->cpr[0][COP0_LLAddr], sizeof(mips3->cpr[0][COP0_LLAddr]), "LLAddr");
+ mips3->impstate->drcuml->symbol_add(&mips3->cpr[0][COP0_XContext], sizeof(mips3->cpr[0][COP0_XContext]), "XContext");
+ mips3->impstate->drcuml->symbol_add(&mips3->cpr[0][COP0_ECC], sizeof(mips3->cpr[0][COP0_ECC]), "ECC");
+ mips3->impstate->drcuml->symbol_add(&mips3->cpr[0][COP0_CacheErr], sizeof(mips3->cpr[0][COP0_CacheErr]), "CacheErr");
+ mips3->impstate->drcuml->symbol_add(&mips3->cpr[0][COP0_TagLo], sizeof(mips3->cpr[0][COP0_TagLo]), "TagLo");
+ mips3->impstate->drcuml->symbol_add(&mips3->cpr[0][COP0_TagHi], sizeof(mips3->cpr[0][COP0_TagHi]), "TagHi");
+ mips3->impstate->drcuml->symbol_add(&mips3->cpr[0][COP0_ErrorPC], sizeof(mips3->cpr[0][COP0_ErrorPC]), "ErrorPC");
+ mips3->impstate->drcuml->symbol_add(&mips3->ccr[1][31], sizeof(mips3->cpr[1][31]), "fcr31");
+ mips3->impstate->drcuml->symbol_add(&mips3->impstate->mode, sizeof(mips3->impstate->mode), "mode");
+ mips3->impstate->drcuml->symbol_add(&mips3->impstate->arg0, sizeof(mips3->impstate->arg0), "arg0");
+ mips3->impstate->drcuml->symbol_add(&mips3->impstate->arg1, sizeof(mips3->impstate->arg1), "arg1");
+ mips3->impstate->drcuml->symbol_add(&mips3->impstate->numcycles, sizeof(mips3->impstate->numcycles), "numcycles");
+ mips3->impstate->drcuml->symbol_add(&mips3->impstate->fpmode, sizeof(mips3->impstate->fpmode), "fpmode");
+
+ /* initialize the front-end helper */
+ mips3->impstate->drcfe = auto_alloc(device->machine(), mips3_frontend(*mips3, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE));
+
+ /* allocate memory for cache-local state and initialize it */
+ memcpy(mips3->impstate->fpmode, fpmode_source, sizeof(fpmode_source));
+
+ /* compute the register parameters */
+ for (regnum = 0; regnum < 34; regnum++)
+ {
+ mips3->impstate->regmap[regnum] = (regnum == 0) ? parameter(0) : parameter::make_memory(&mips3->r[regnum]);
+ mips3->impstate->regmaplo[regnum] = (regnum == 0) ? parameter(0) : parameter::make_memory(LOPTR(&mips3->r[regnum]));
+ }
+
+ /* if we have registers to spare, assign r2, r3, r4 to leftovers */
+ if (!DISABLE_FAST_REGISTERS)
+ {
+ mips3->impstate->drcuml->get_backend_info(beinfo);
+ if (beinfo.direct_iregs > 4)
+ {
+ mips3->impstate->regmap[2] = I4;
+ mips3->impstate->regmaplo[2] = I4;
+ }
+ if (beinfo.direct_iregs > 5)
+ {
+ mips3->impstate->regmap[3] = I5;
+ mips3->impstate->regmaplo[3] = I5;
+ }
+ if (beinfo.direct_iregs > 6)
+ {
+ mips3->impstate->regmap[4] = I6;
+ mips3->impstate->regmaplo[4] = I6;
+ }
+ }
+
+ /* mark the cache dirty so it is updated on next execute */
+ mips3->impstate->cache_dirty = TRUE;
+}
+
+
+/*-------------------------------------------------
+ mips3_reset - reset the processor
+-------------------------------------------------*/
+
+static CPU_RESET( mips3 )
+{
+ mips3_state *mips3 = get_safe_token(device);
+
+ /* reset the common code and mark the cache dirty */
+ mips3com_reset(mips3);
+ mips3->impstate->mode = (MODE_KERNEL << 1) | 0;
+ mips3->impstate->cache_dirty = TRUE;
+}
+
+
+/*-------------------------------------------------
+ mips3_execute - execute the CPU for the
+ specified number of cycles
+-------------------------------------------------*/
+
+static CPU_EXECUTE( mips3 )
+{
+ mips3_state *mips3 = get_safe_token(device);
+ drcuml_state *drcuml = mips3->impstate->drcuml;
+ int execute_result;
+
+ /* reset the cache if dirty */
+ if (mips3->impstate->cache_dirty)
+ code_flush_cache(mips3);
+ mips3->impstate->cache_dirty = FALSE;
+
+ /* execute */
+ do
+ {
+ /* run as much as we can */
+ execute_result = drcuml->execute(*mips3->impstate->entry);
+
+ /* if we need to recompile, do it */
+ if (execute_result == EXECUTE_MISSING_CODE)
+ code_compile_block(mips3, mips3->impstate->mode, mips3->pc);
+ else if (execute_result == EXECUTE_UNMAPPED_CODE)
+ fatalerror("Attempted to execute unmapped code at PC=%08X\n", mips3->pc);
+ else if (execute_result == EXECUTE_RESET_CACHE)
+ code_flush_cache(mips3);
+
+ } while (execute_result != EXECUTE_OUT_OF_CYCLES);
+}
+
+
+/*-------------------------------------------------
+ mips3_exit - cleanup from execution
+-------------------------------------------------*/
+
+static CPU_EXIT( mips3 )
+{
+ mips3_state *mips3 = get_safe_token(device);
+ mips3com_exit(mips3);
+
+ /* clean up the DRC */
+ auto_free(device->machine(), mips3->impstate->drcfe);
+ auto_free(device->machine(), mips3->impstate->drcuml);
+ auto_free(device->machine(), mips3->impstate->cache);
+}
+
+
+/*-------------------------------------------------
+ mips3_translate - perform virtual-to-physical
+ address translation
+-------------------------------------------------*/
+
+static CPU_TRANSLATE( mips3 )
+{
+ mips3_state *mips3 = get_safe_token(device);
+ return mips3com_translate_address(mips3, space, intention, address);
+}
+
+
+/*-------------------------------------------------
+ mips3_dasm - disassemble an instruction
+-------------------------------------------------*/
+
+static CPU_DISASSEMBLE( mips3 )
+{
+ mips3_state *mips3 = get_safe_token(device);
+ return mips3com_dasm(mips3, buffer, pc, oprom, opram);
+}
+
+
+/*-------------------------------------------------
+ mips3_set_info - set information about a given
+ CPU instance
+-------------------------------------------------*/
+
+static CPU_SET_INFO( mips3 )
+{
+ mips3_state *mips3 = get_safe_token(device);
+
+ /* --- everything is handled generically --- */
+ mips3com_set_info(mips3, state, info);
+}
+
+
+/*-------------------------------------------------
+ mips3_get_info - return information about a
+ given CPU instance
+-------------------------------------------------*/
+
+static CPU_GET_INFO( mips3 )
+{
+ mips3_state *mips3 = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(mips3_state *); break;
+ case CPUINFO_INT_PREVIOUSPC: /* not implemented */ break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(mips3); break;
+ case CPUINFO_FCT_INIT: /* provided per-CPU */ break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(mips3); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(mips3); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(mips3); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(mips3);break;
+ case CPUINFO_FCT_TRANSLATE: info->translate = CPU_TRANSLATE_NAME(mips3); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+
+ /* --- everything else is handled generically --- */
+ default: mips3com_get_info(mips3, state, info); break;
+ }
+}
+
+
+/*-------------------------------------------------
+ mips3drc_set_options - configure DRC options
+-------------------------------------------------*/
+
+void mips3drc_set_options(device_t *device, UINT32 options)
+{
+ mips3_state *mips3 = get_safe_token(device);
+ mips3->impstate->drcoptions = options;
+}
+
+
+/*-------------------------------------------------
+ mips3drc_add_fastram - add a new fastram
+ region
+-------------------------------------------------*/
+
+void mips3drc_add_fastram(device_t *device, offs_t start, offs_t end, UINT8 readonly, void *base)
+{
+ mips3_state *mips3 = get_safe_token(device);
+ if (mips3->impstate->fastram_select < ARRAY_LENGTH(mips3->impstate->fastram))
+ {
+ mips3->impstate->fastram[mips3->impstate->fastram_select].start = start;
+ mips3->impstate->fastram[mips3->impstate->fastram_select].end = end;
+ mips3->impstate->fastram[mips3->impstate->fastram_select].readonly = readonly;
+ mips3->impstate->fastram[mips3->impstate->fastram_select].base = base;
+ mips3->impstate->fastram_select++;
+ }
+}
+
+
+/*-------------------------------------------------
+ mips3drc_add_hotspot - add a new hotspot
+-------------------------------------------------*/
+
+void mips3drc_add_hotspot(device_t *device, offs_t pc, UINT32 opcode, UINT32 cycles)
+{
+ mips3_state *mips3 = get_safe_token(device);
+ if (mips3->impstate->hotspot_select < ARRAY_LENGTH(mips3->impstate->hotspot))
+ {
+ mips3->impstate->hotspot[mips3->impstate->hotspot_select].pc = pc;
+ mips3->impstate->hotspot[mips3->impstate->hotspot_select].opcode = opcode;
+ mips3->impstate->hotspot[mips3->impstate->hotspot_select].cycles = cycles;
+ mips3->impstate->hotspot_select++;
+ }
+}
+
+
+
+/***************************************************************************
+ CACHE MANAGEMENT
+***************************************************************************/
+
+/*-------------------------------------------------
+ code_flush_cache - flush the cache and
+ regenerate static code
+-------------------------------------------------*/
+
+static void code_flush_cache(mips3_state *mips3)
+{
+ int mode;
+
+ /* empty the transient cache contents */
+ mips3->impstate->drcuml->reset();
+
+ try
+ {
+ /* generate the entry point and out-of-cycles handlers */
+ static_generate_entry_point(mips3);
+ static_generate_nocode_handler(mips3);
+ static_generate_out_of_cycles(mips3);
+ static_generate_tlb_mismatch(mips3);
+
+ /* append exception handlers for various types */
+ static_generate_exception(mips3, EXCEPTION_INTERRUPT, TRUE, "exception_interrupt");
+ static_generate_exception(mips3, EXCEPTION_INTERRUPT, FALSE, "exception_interrupt_norecover");
+ static_generate_exception(mips3, EXCEPTION_TLBMOD, TRUE, "exception_tlbmod");
+ static_generate_exception(mips3, EXCEPTION_TLBLOAD, TRUE, "exception_tlbload");
+ static_generate_exception(mips3, EXCEPTION_TLBSTORE, TRUE, "exception_tlbstore");
+ static_generate_exception(mips3, EXCEPTION_TLBLOAD_FILL, TRUE, "exception_tlbload_fill");
+ static_generate_exception(mips3, EXCEPTION_TLBSTORE_FILL, TRUE, "exception_tlbstore_fill");
+ static_generate_exception(mips3, EXCEPTION_ADDRLOAD, TRUE, "exception_addrload");
+ static_generate_exception(mips3, EXCEPTION_ADDRSTORE, TRUE, "exception_addrstore");
+ static_generate_exception(mips3, EXCEPTION_SYSCALL, TRUE, "exception_syscall");
+ static_generate_exception(mips3, EXCEPTION_BREAK, TRUE, "exception_break");
+ static_generate_exception(mips3, EXCEPTION_INVALIDOP, TRUE, "exception_invalidop");
+ static_generate_exception(mips3, EXCEPTION_BADCOP, TRUE, "exception_badcop");
+ static_generate_exception(mips3, EXCEPTION_OVERFLOW, TRUE, "exception_overflow");
+ static_generate_exception(mips3, EXCEPTION_TRAP, TRUE, "exception_trap");
+
+ /* add subroutines for memory accesses */
+ for (mode = 0; mode < 3; mode++)
+ {
+ static_generate_memory_accessor(mips3, mode, 1, FALSE, FALSE, "read8", &mips3->impstate->read8[mode]);
+ static_generate_memory_accessor(mips3, mode, 1, TRUE, FALSE, "write8", &mips3->impstate->write8[mode]);
+ static_generate_memory_accessor(mips3, mode, 2, FALSE, FALSE, "read16", &mips3->impstate->read16[mode]);
+ static_generate_memory_accessor(mips3, mode, 2, TRUE, FALSE, "write16", &mips3->impstate->write16[mode]);
+ static_generate_memory_accessor(mips3, mode, 4, FALSE, FALSE, "read32", &mips3->impstate->read32[mode]);
+ static_generate_memory_accessor(mips3, mode, 4, FALSE, TRUE, "read32mask", &mips3->impstate->read32mask[mode]);
+ static_generate_memory_accessor(mips3, mode, 4, TRUE, FALSE, "write32", &mips3->impstate->write32[mode]);
+ static_generate_memory_accessor(mips3, mode, 4, TRUE, TRUE, "write32mask", &mips3->impstate->write32mask[mode]);
+ static_generate_memory_accessor(mips3, mode, 8, FALSE, FALSE, "read64", &mips3->impstate->read64[mode]);
+ static_generate_memory_accessor(mips3, mode, 8, FALSE, TRUE, "read64mask", &mips3->impstate->read64mask[mode]);
+ static_generate_memory_accessor(mips3, mode, 8, TRUE, FALSE, "write64", &mips3->impstate->write64[mode]);
+ static_generate_memory_accessor(mips3, mode, 8, TRUE, TRUE, "write64mask", &mips3->impstate->write64mask[mode]);
+ }
+ }
+ catch (drcuml_block::abort_compilation &)
+ {
+ fatalerror("Unrecoverable error generating static code");
+ }
+}
+
+
+/*-------------------------------------------------
+ code_compile_block - compile a block of the
+ given mode at the specified pc
+-------------------------------------------------*/
+
+static void code_compile_block(mips3_state *mips3, UINT8 mode, offs_t pc)
+{
+ drcuml_state *drcuml = mips3->impstate->drcuml;
+ compiler_state compiler = { 0 };
+ const opcode_desc *seqhead, *seqlast;
+ const opcode_desc *desclist;
+ int override = FALSE;
+ drcuml_block *block;
+
+ g_profiler.start(PROFILER_DRC_COMPILE);
+
+ /* get a description of this sequence */
+ desclist = mips3->impstate->drcfe->describe_code(pc);
+ if (LOG_UML || LOG_NATIVE)
+ log_opcode_desc(drcuml, desclist, 0);
+
+ /* if we get an error back, flush the cache and try again */
+ bool succeeded = false;
+ while (!succeeded)
+ {
+ try
+ {
+ /* start the block */
+ block = drcuml->begin_block(4096);
+
+ /* loop until we get through all instruction sequences */
+ for (seqhead = desclist; seqhead != NULL; seqhead = seqlast->next())
+ {
+ const opcode_desc *curdesc;
+ UINT32 nextpc;
+
+ /* add a code log entry */
+ if (LOG_UML)
+ block->append_comment("-------------------------"); // comment
+
+ /* determine the last instruction in this sequence */
+ for (seqlast = seqhead; seqlast != NULL; seqlast = seqlast->next())
+ if (seqlast->flags & OPFLAG_END_SEQUENCE)
+ break;
+ assert(seqlast != NULL);
+
+ /* if we don't have a hash for this mode/pc, or if we are overriding all, add one */
+ if (override || !drcuml->hash_exists(mode, seqhead->pc))
+ UML_HASH(block, mode, seqhead->pc); // hash mode,pc
+
+ /* if we already have a hash, and this is the first sequence, assume that we */
+ /* are recompiling due to being out of sync and allow future overrides */
+ else if (seqhead == desclist)
+ {
+ override = TRUE;
+ UML_HASH(block, mode, seqhead->pc); // hash mode,pc
+ }
+
+ /* otherwise, redispatch to that fixed PC and skip the rest of the processing */
+ else
+ {
+ UML_LABEL(block, seqhead->pc | 0x80000000); // label seqhead->pc | 0x80000000
+ UML_HASHJMP(block, mips3->impstate->mode, seqhead->pc, *mips3->impstate->nocode);
+ // hashjmp <mode>,seqhead->pc,nocode
+ continue;
+ }
+
+ /* validate this code block if we're not pointing into ROM */
+ if (mips3->program->get_write_ptr(seqhead->physpc) != NULL)
+ generate_checksum_block(mips3, block, &compiler, seqhead, seqlast);
+
+ /* label this instruction, if it may be jumped to locally */
+ if (seqhead->flags & OPFLAG_IS_BRANCH_TARGET)
+ UML_LABEL(block, seqhead->pc | 0x80000000); // label seqhead->pc | 0x80000000
+
+ /* iterate over instructions in the sequence and compile them */
+ for (curdesc = seqhead; curdesc != seqlast->next(); curdesc = curdesc->next())
+ generate_sequence_instruction(mips3, block, &compiler, curdesc);
+
+ /* if we need to return to the start, do it */
+ if (seqlast->flags & OPFLAG_RETURN_TO_START)
+ nextpc = pc;
+
+ /* otherwise we just go to the next instruction */
+ else
+ nextpc = seqlast->pc + (seqlast->skipslots + 1) * 4;
+
+ /* count off cycles and go there */
+ generate_update_cycles(mips3, block, &compiler, nextpc, TRUE); // <subtract cycles>
+
+ /* if the last instruction can change modes, use a variable mode; otherwise, assume the same mode */
+ if (seqlast->flags & OPFLAG_CAN_CHANGE_MODES)
+ UML_HASHJMP(block, mem(&mips3->impstate->mode), nextpc, *mips3->impstate->nocode);
+ // hashjmp <mode>,nextpc,nocode
+ else if (seqlast->next() == NULL || seqlast->next()->pc != nextpc)
+ UML_HASHJMP(block, mips3->impstate->mode, nextpc, *mips3->impstate->nocode);
+ // hashjmp <mode>,nextpc,nocode
+ }
+
+ /* end the sequence */
+ block->end();
+ g_profiler.stop();
+ succeeded = true;
+ }
+ catch (drcuml_block::abort_compilation &)
+ {
+ code_flush_cache(mips3);
+ }
+ }
+}
+
+
+
+/***************************************************************************
+ C FUNCTION CALLBACKS
+***************************************************************************/
+
+/*-------------------------------------------------
+ cfunc_get_cycles - compute the total number
+ of cycles executed so far
+-------------------------------------------------*/
+
+static void cfunc_get_cycles(void *param)
+{
+ mips3_state *mips3 = (mips3_state *)param;
+ mips3->impstate->numcycles = mips3->device->total_cycles();
+}
+
+
+/*-------------------------------------------------
+ cfunc_printf_exception - log any exceptions that
+ aren't interrupts
+-------------------------------------------------*/
+
+static void cfunc_printf_exception(void *param)
+{
+ mips3_state *mips3 = (mips3_state *)param;
+ printf("Exception: EPC=%08X Cause=%08X BadVAddr=%08X Jmp=%08X\n", (UINT32)mips3->cpr[0][COP0_EPC], (UINT32)mips3->cpr[0][COP0_Cause], (UINT32)mips3->cpr[0][COP0_BadVAddr], mips3->pc);
+ cfunc_printf_probe(mips3);
+}
+
+
+/*-------------------------------------------------
+ cfunc_printf_debug - generic printf for
+ debugging
+-------------------------------------------------*/
+
+static void cfunc_printf_debug(void *param)
+{
+ mips3_state *mips3 = (mips3_state *)param;
+ printf(mips3->impstate->format, mips3->impstate->arg0, mips3->impstate->arg1);
+}
+
+
+/*-------------------------------------------------
+ cfunc_printf_probe - print the current CPU
+ state and return
+-------------------------------------------------*/
+
+static void cfunc_printf_probe(void *param)
+{
+ mips3_state *mips3 = (mips3_state *)param;
+
+ printf(" PC=%08X r1=%08X%08X r2=%08X%08X r3=%08X%08X\n",
+ mips3->pc,
+ (UINT32)(mips3->r[1] >> 32), (UINT32)mips3->r[1],
+ (UINT32)(mips3->r[2] >> 32), (UINT32)mips3->r[2],
+ (UINT32)(mips3->r[3] >> 32), (UINT32)mips3->r[3]);
+ printf(" r4=%08X%08X r5=%08X%08X r6=%08X%08X r7=%08X%08X\n",
+ (UINT32)(mips3->r[4] >> 32), (UINT32)mips3->r[4],
+ (UINT32)(mips3->r[5] >> 32), (UINT32)mips3->r[5],
+ (UINT32)(mips3->r[6] >> 32), (UINT32)mips3->r[6],
+ (UINT32)(mips3->r[7] >> 32), (UINT32)mips3->r[7]);
+ printf(" r8=%08X%08X r9=%08X%08X r10=%08X%08X r11=%08X%08X\n",
+ (UINT32)(mips3->r[8] >> 32), (UINT32)mips3->r[8],
+ (UINT32)(mips3->r[9] >> 32), (UINT32)mips3->r[9],
+ (UINT32)(mips3->r[10] >> 32), (UINT32)mips3->r[10],
+ (UINT32)(mips3->r[11] >> 32), (UINT32)mips3->r[11]);
+ printf("r12=%08X%08X r13=%08X%08X r14=%08X%08X r15=%08X%08X\n",
+ (UINT32)(mips3->r[12] >> 32), (UINT32)mips3->r[12],
+ (UINT32)(mips3->r[13] >> 32), (UINT32)mips3->r[13],
+ (UINT32)(mips3->r[14] >> 32), (UINT32)mips3->r[14],
+ (UINT32)(mips3->r[15] >> 32), (UINT32)mips3->r[15]);
+ printf("r16=%08X%08X r17=%08X%08X r18=%08X%08X r19=%08X%08X\n",
+ (UINT32)(mips3->r[16] >> 32), (UINT32)mips3->r[16],
+ (UINT32)(mips3->r[17] >> 32), (UINT32)mips3->r[17],
+ (UINT32)(mips3->r[18] >> 32), (UINT32)mips3->r[18],
+ (UINT32)(mips3->r[19] >> 32), (UINT32)mips3->r[19]);
+ printf("r20=%08X%08X r21=%08X%08X r22=%08X%08X r23=%08X%08X\n",
+ (UINT32)(mips3->r[20] >> 32), (UINT32)mips3->r[20],
+ (UINT32)(mips3->r[21] >> 32), (UINT32)mips3->r[21],
+ (UINT32)(mips3->r[22] >> 32), (UINT32)mips3->r[22],
+ (UINT32)(mips3->r[23] >> 32), (UINT32)mips3->r[23]);
+ printf("r24=%08X%08X r25=%08X%08X r26=%08X%08X r27=%08X%08X\n",
+ (UINT32)(mips3->r[24] >> 32), (UINT32)mips3->r[24],
+ (UINT32)(mips3->r[25] >> 32), (UINT32)mips3->r[25],
+ (UINT32)(mips3->r[26] >> 32), (UINT32)mips3->r[26],
+ (UINT32)(mips3->r[27] >> 32), (UINT32)mips3->r[27]);
+ printf("r28=%08X%08X r29=%08X%08X r30=%08X%08X r31=%08X%08X\n",
+ (UINT32)(mips3->r[28] >> 32), (UINT32)mips3->r[28],
+ (UINT32)(mips3->r[29] >> 32), (UINT32)mips3->r[29],
+ (UINT32)(mips3->r[30] >> 32), (UINT32)mips3->r[30],
+ (UINT32)(mips3->r[31] >> 32), (UINT32)mips3->r[31]);
+ printf(" hi=%08X%08X lo=%08X%08X\n",
+ (UINT32)(mips3->r[REG_HI] >> 32), (UINT32)mips3->r[REG_HI],
+ (UINT32)(mips3->r[REG_LO] >> 32), (UINT32)mips3->r[REG_LO]);
+}
+
+
+/*-------------------------------------------------
+ cfunc_unimplemented - handler for
+ unimplemented opcdes
+-------------------------------------------------*/
+
+static void cfunc_unimplemented(void *param)
+{
+ mips3_state *mips3 = (mips3_state *)param;
+ UINT32 opcode = mips3->impstate->arg0;
+ fatalerror("PC=%08X: Unimplemented op %08X (%02X,%02X)", mips3->pc, opcode, opcode >> 26, opcode & 0x3f);
+}
+
+
+
+/***************************************************************************
+ STATIC CODEGEN
+***************************************************************************/
+
+/*-------------------------------------------------
+ static_generate_entry_point - generate a
+ static entry point
+-------------------------------------------------*/
+
+static void static_generate_entry_point(mips3_state *mips3)
+{
+ drcuml_state *drcuml = mips3->impstate->drcuml;
+ code_label skip = 1;
+ drcuml_block *block;
+
+ block = drcuml->begin_block(20);
+
+ /* forward references */
+ alloc_handle(drcuml, &mips3->impstate->exception_norecover[EXCEPTION_INTERRUPT], "interrupt_norecover");
+ alloc_handle(drcuml, &mips3->impstate->nocode, "nocode");
+
+ alloc_handle(drcuml, &mips3->impstate->entry, "entry");
+ UML_HANDLE(block, *mips3->impstate->entry); // handle entry
+
+ /* reset the FPU mode */
+ UML_AND(block, I0, CCR132(31), 3); // and i0,ccr1[31],3
+ UML_LOAD(block, I0, &mips3->impstate->fpmode[0], I0, SIZE_BYTE, SCALE_x1);// load i0,fpmode,i0,byte
+ UML_SETFMOD(block, I0); // setfmod i0
+
+ /* load fast integer registers */
+ load_fast_iregs(mips3, block);
+
+ /* check for interrupts */
+ UML_AND(block, I0, CPR032(COP0_Cause), CPR032(COP0_Status)); // and i0,[Cause],[Status]
+ UML_AND(block, I0, I0, 0xfc00); // and i0,i0,0xfc00,Z
+ UML_JMPc(block, COND_Z, skip); // jmp skip,Z
+ UML_TEST(block, CPR032(COP0_Status), SR_IE); // test [Status],SR_IE
+ UML_JMPc(block, COND_Z, skip); // jmp skip,Z
+ UML_TEST(block, CPR032(COP0_Status), SR_EXL | SR_ERL); // test [Status],SR_EXL | SR_ERL
+ UML_JMPc(block, COND_NZ, skip); // jmp skip,NZ
+ UML_MOV(block, I0, mem(&mips3->pc)); // mov i0,pc
+ UML_MOV(block, I1, 0); // mov i1,0
+ UML_CALLH(block, *mips3->impstate->exception_norecover[EXCEPTION_INTERRUPT]); // callh exception_norecover
+ UML_LABEL(block, skip); // skip:
+
+ /* generate a hash jump via the current mode and PC */
+ UML_HASHJMP(block, mem(&mips3->impstate->mode), mem(&mips3->pc), *mips3->impstate->nocode);
+ // hashjmp <mode>,<pc>,nocode
+ block->end();
+}
+
+
+/*-------------------------------------------------
+ static_generate_nocode_handler - generate an
+ exception handler for "out of code"
+-------------------------------------------------*/
+
+static void static_generate_nocode_handler(mips3_state *mips3)
+{
+ drcuml_state *drcuml = mips3->impstate->drcuml;
+ drcuml_block *block;
+
+ /* begin generating */
+ block = drcuml->begin_block(10);
+
+ /* generate a hash jump via the current mode and PC */
+ alloc_handle(drcuml, &mips3->impstate->nocode, "nocode");
+ UML_HANDLE(block, *mips3->impstate->nocode); // handle nocode
+ UML_GETEXP(block, I0); // getexp i0
+ UML_MOV(block, mem(&mips3->pc), I0); // mov [pc],i0
+ save_fast_iregs(mips3, block);
+ UML_EXIT(block, EXECUTE_MISSING_CODE); // exit EXECUTE_MISSING_CODE
+
+ block->end();
+}
+
+
+/*-------------------------------------------------
+ static_generate_out_of_cycles - generate an
+ out of cycles exception handler
+-------------------------------------------------*/
+
+static void static_generate_out_of_cycles(mips3_state *mips3)
+{
+ drcuml_state *drcuml = mips3->impstate->drcuml;
+ drcuml_block *block;
+
+ /* begin generating */
+ block = drcuml->begin_block(10);
+
+ /* generate a hash jump via the current mode and PC */
+ alloc_handle(drcuml, &mips3->impstate->out_of_cycles, "out_of_cycles");
+ UML_HANDLE(block, *mips3->impstate->out_of_cycles); // handle out_of_cycles
+ UML_GETEXP(block, I0); // getexp i0
+ UML_MOV(block, mem(&mips3->pc), I0); // mov <pc>,i0
+ save_fast_iregs(mips3, block);
+ UML_EXIT(block, EXECUTE_OUT_OF_CYCLES); // exit EXECUTE_OUT_OF_CYCLES
+
+ block->end();
+}
+
+
+/*-------------------------------------------------
+ static_generate_tlb_mismatch - generate a
+ TLB mismatch handler
+-------------------------------------------------*/
+
+static void static_generate_tlb_mismatch(mips3_state *mips3)
+{
+ drcuml_state *drcuml = mips3->impstate->drcuml;
+ drcuml_block *block;
+
+ /* forward references */
+ alloc_handle(drcuml, &mips3->impstate->exception[EXCEPTION_TLBLOAD], "exception_tlbload");
+ alloc_handle(drcuml, &mips3->impstate->exception[EXCEPTION_TLBLOAD_FILL], "exception_tlbload_fill");
+
+ /* begin generating */
+ block = drcuml->begin_block(20);
+
+ /* generate a hash jump via the current mode and PC */
+ alloc_handle(drcuml, &mips3->impstate->tlb_mismatch, "tlb_mismatch");
+ UML_HANDLE(block, *mips3->impstate->tlb_mismatch); // handle tlb_mismatch
+ UML_RECOVER(block, I0, MAPVAR_PC); // recover i0,PC
+ UML_MOV(block, mem(&mips3->pc), I0); // mov <pc>,i0
+ UML_SHR(block, I1, I0, 12); // shr i1,i0,12
+ UML_LOAD(block, I1, (void *)vtlb_table(mips3->vtlb), I1, SIZE_DWORD, SCALE_x4);// load i1,[vtlb_table],i1,dword
+ if (PRINTF_MMU)
+ {
+ static const char text[] = "TLB mismatch @ %08X (ent=%08X)\n";
+ UML_MOV(block, mem(&mips3->impstate->format), (FPTR)text); // mov [format],text
+ UML_MOV(block, mem(&mips3->impstate->arg0), I0); // mov [arg0],i0
+ UML_MOV(block, mem(&mips3->impstate->arg1), I1); // mov [arg1],i1
+ UML_CALLC(block, cfunc_printf_debug, mips3); // callc printf_debug
+ }
+ UML_TEST(block, I1, VTLB_FETCH_ALLOWED); // test i1,VTLB_FETCH_ALLOWED
+ UML_JMPc(block, COND_NZ, 1); // jmp 1,nz
+ UML_TEST(block, I1, VTLB_FLAG_FIXED); // test i1,VTLB_FLAG_FIXED
+ UML_EXHc(block, COND_NZ, *mips3->impstate->exception[EXCEPTION_TLBLOAD], I0); // exh exception[TLBLOAD],i0,nz
+ UML_EXH(block, *mips3->impstate->exception[EXCEPTION_TLBLOAD_FILL], I0); // exh exception[TLBLOAD_FILL],i0
+ UML_LABEL(block, 1); // 1:
+ save_fast_iregs(mips3, block);
+
+ // the saved PC may be set 1 instruction back with the low bit set to indicate
+ // a delay slot; in this path we want the original instruction address, so recover it
+ UML_ADD(block, I0, mem(&mips3->pc), 3); // add i0,<pc>,3
+ UML_AND(block, mem(&mips3->pc), I0, ~3); // and <pc>,i0,~3
+ UML_EXIT(block, EXECUTE_MISSING_CODE); // exit EXECUTE_MISSING_CODE
+
+ block->end();
+}
+
+
+/*-------------------------------------------------
+ static_generate_exception - generate a static
+ exception handler
+-------------------------------------------------*/
+
+static void static_generate_exception(mips3_state *mips3, UINT8 exception, int recover, const char *name)
+{
+ code_handle *&exception_handle = recover ? mips3->impstate->exception[exception] : mips3->impstate->exception_norecover[exception];
+ drcuml_state *drcuml = mips3->impstate->drcuml;
+ UINT32 offset = 0x180;
+ code_label next = 1;
+ code_label skip = 2;
+ drcuml_block *block;
+
+ /* translate our fake fill exceptions into real exceptions */
+ if (exception == EXCEPTION_TLBLOAD_FILL || exception == EXCEPTION_TLBSTORE_FILL)
+ {
+ offset = 0x000;
+ exception = (exception - EXCEPTION_TLBLOAD_FILL) + EXCEPTION_TLBLOAD;
+ }
+
+ /* begin generating */
+ block = drcuml->begin_block(1024);
+
+ /* add a global entry for this */
+ alloc_handle(drcuml, &exception_handle, name);
+ UML_HANDLE(block, *exception_handle); // handle name
+
+ /* exception parameter is expected to be the fault address in this case */
+ if (exception == EXCEPTION_TLBLOAD || exception == EXCEPTION_TLBSTORE || exception == EXCEPTION_TLBMOD || exception == EXCEPTION_ADDRLOAD || exception == EXCEPTION_ADDRSTORE)
+ {
+ /* set BadVAddr to the fault address */
+ UML_GETEXP(block, I0); // getexp i0
+ UML_TEST(block, CPR032(COP0_Status), SR_EXL); // test [Status],SR_EXL
+ UML_MOVc(block, COND_Z, CPR032(COP0_BadVAddr), I0); // mov [BadVAddr],i0,Z
+ }
+
+ if (exception == EXCEPTION_TLBLOAD || exception == EXCEPTION_TLBSTORE)
+ {
+ /* set the upper bits of EntryHi and the lower bits of Context to the fault page */
+ UML_ROLINS(block, CPR032(COP0_EntryHi), I0, 0, 0xffffe000); // rolins [EntryHi],i0,0,0xffffe000
+ UML_ROLINS(block, CPR032(COP0_Context), I0, 32-9, 0x7ffff0); // rolins [Context],i0,32-9,0x7ffff0
+ }
+
+ /* set the EPC and Cause registers */
+ if (recover)
+ {
+ UML_RECOVER(block, I0, MAPVAR_PC); // recover i0,PC
+ UML_RECOVER(block, I1, MAPVAR_CYCLES); // recover i1,CYCLES
+ }
+
+ UML_AND(block, I2, CPR032(COP0_Cause), ~0x800000ff); // and i2,[Cause],~0x800000ff
+ UML_TEST(block, I0, 1); // test i0,1
+ UML_JMPc(block, COND_Z, next); // jz <next>
+ UML_OR(block, I2, I2, 0x80000000); // or i2,i2,0x80000000
+ UML_SUB(block, I0, I0, 1); // sub i0,i0,1
+ UML_LABEL(block, next); // <next>:
+ UML_MOV(block, I3, offset); // mov i3,offset
+ UML_TEST(block, CPR032(COP0_Status), SR_EXL); // test [Status],SR_EXL
+ UML_MOVc(block, COND_Z, CPR032(COP0_EPC), I0); // mov [EPC],i0,Z
+ UML_MOVc(block, COND_NZ, I3, 0x180); // mov i3,0x180,NZ
+ UML_OR(block, CPR032(COP0_Cause), I2, exception << 2); // or [Cause],i2,exception << 2
+
+ /* for BADCOP exceptions, we use the exception parameter to know which COP */
+ if (exception == EXCEPTION_BADCOP)
+ {
+ UML_GETEXP(block, I0); // getexp i0
+ UML_ROLINS(block, CPR032(COP0_Cause), I0, 28, 0x30000000); // rolins [Cause],i0,28,0x30000000
+ }
+
+ /* set EXL in the SR */
+ UML_OR(block, I0, CPR032(COP0_Status), SR_EXL); // or i0,[Status],SR_EXL
+ UML_MOV(block, CPR032(COP0_Status), I0); // mov [Status],i0
+ generate_update_mode(mips3, block);
+
+ /* optionally print exceptions */
+ if ((PRINTF_EXCEPTIONS && exception != EXCEPTION_INTERRUPT && exception != EXCEPTION_SYSCALL) ||
+ (PRINTF_MMU && (exception == EXCEPTION_TLBLOAD || exception == EXCEPTION_TLBSTORE)))
+ {
+ UML_CALLC(block, cfunc_printf_exception, mips3); // callc cfunc_printf_exception,NULL
+ }
+
+ /* choose our target PC */
+ UML_ADD(block, I0, I3, 0xbfc00200); // add i0,i3,0xbfc00200
+ UML_TEST(block, I1, SR_BEV); // test i1,SR_BEV
+ UML_JMPc(block, COND_NZ, skip); // jnz <skip>
+ UML_ADD(block, I0, I3, 0x80000000); // add i0,i3,0x80000000,z
+ UML_LABEL(block, skip); // <skip>:
+
+ /* adjust cycles */
+ UML_SUB(block, mem(&mips3->icount), mem(&mips3->icount), I1); // sub icount,icount,cycles,S
+ UML_EXHc(block, COND_S, *mips3->impstate->out_of_cycles, I0); // exh out_of_cycles,i0
+
+ UML_HASHJMP(block, mem(&mips3->impstate->mode), I0, *mips3->impstate->nocode);// hashjmp <mode>,i0,nocode
+
+ block->end();
+}
+
+
+/*------------------------------------------------------------------
+ static_generate_memory_accessor
+------------------------------------------------------------------*/
+
+static void static_generate_memory_accessor(mips3_state *mips3, int mode, int size, int iswrite, int ismasked, const char *name, code_handle **handleptr)
+{
+ /* on entry, address is in I0; data for writes is in I1; mask for accesses is in I2 */
+ /* on exit, read result is in I0 */
+ /* routine trashes I0-I3 */
+ code_handle &exception_tlb = *mips3->impstate->exception[iswrite ? EXCEPTION_TLBSTORE : EXCEPTION_TLBLOAD];
+ code_handle &exception_tlbfill = *mips3->impstate->exception[iswrite ? EXCEPTION_TLBSTORE_FILL : EXCEPTION_TLBLOAD_FILL];
+ code_handle &exception_addrerr = *mips3->impstate->exception[iswrite ? EXCEPTION_ADDRSTORE : EXCEPTION_ADDRLOAD];
+ drcuml_state *drcuml = mips3->impstate->drcuml;
+ drcuml_block *block;
+ int tlbmiss = 0;
+ int label = 1;
+ int ramnum;
+
+ /* begin generating */
+ block = drcuml->begin_block(1024);
+
+ /* add a global entry for this */
+ alloc_handle(drcuml, handleptr, name);
+ UML_HANDLE(block, **handleptr); // handle *handleptr
+
+ /* user mode? generate address exception if top bit is set */
+ if (mode == MODE_USER)
+ {
+ UML_TEST(block, I0, 0x80000000); // test i0,0x80000000
+ UML_EXHc(block, COND_NZ, exception_addrerr, I0); // exh addrerr,i0,nz
+ }
+
+ /* supervisor mode? generate address exception if not in user space or in $C0000000-DFFFFFFF */
+ if (mode == MODE_SUPER)
+ {
+ int addrok;
+ UML_TEST(block, I0, 0x80000000); // test i0,0x80000000
+ UML_JMPc(block, COND_Z, addrok = label++); // jz addrok
+ UML_SHR(block, I3, I0, 29); // shr i3,i0,29
+ UML_CMP(block, I3, 6); // cmp i3,6
+ UML_EXHc(block, COND_NE, exception_addrerr, I0); // exh addrerr,i0,ne
+ UML_LABEL(block, addrok); // addrok:
+ }
+
+ /* general case: assume paging and perform a translation */
+ UML_SHR(block, I3, I0, 12); // shr i3,i0,12
+ UML_LOAD(block, I3, (void *)vtlb_table(mips3->vtlb), I3, SIZE_DWORD, SCALE_x4);// load i3,[vtlb_table],i3,dword
+ UML_TEST(block, I3, iswrite ? VTLB_WRITE_ALLOWED : VTLB_READ_ALLOWED);// test i3,iswrite ? VTLB_WRITE_ALLOWED : VTLB_READ_ALLOWED
+ UML_JMPc(block, COND_Z, tlbmiss = label++); // jmp tlbmiss,z
+ UML_ROLINS(block, I0, I3, 0, 0xfffff000); // rolins i0,i3,0,0xfffff000
+
+ if ((mips3->device->machine().debug_flags & DEBUG_FLAG_ENABLED) == 0)
+ for (ramnum = 0; ramnum < MIPS3_MAX_FASTRAM; ramnum++)
+ if (mips3->impstate->fastram[ramnum].base != NULL && (!iswrite || !mips3->impstate->fastram[ramnum].readonly))
+ {
+ void *fastbase = (UINT8 *)mips3->impstate->fastram[ramnum].base - mips3->impstate->fastram[ramnum].start;
+ UINT32 skip = label++;
+ if (mips3->impstate->fastram[ramnum].end != 0xffffffff)
+ {
+ UML_CMP(block, I0, mips3->impstate->fastram[ramnum].end); // cmp i0,end
+ UML_JMPc(block, COND_A, skip); // ja skip
+ }
+ if (mips3->impstate->fastram[ramnum].start != 0x00000000)
+ {
+ UML_CMP(block, I0, mips3->impstate->fastram[ramnum].start);// cmp i0,fastram_start
+ UML_JMPc(block, COND_B, skip); // jb skip
+ }
+
+ if (!iswrite)
+ {
+ if (size == 1)
+ {
+ UML_XOR(block, I0, I0, mips3->bigendian ? BYTE4_XOR_BE(0) : BYTE4_XOR_LE(0));
+ // xor i0,i0,bytexor
+ UML_LOAD(block, I0, fastbase, I0, SIZE_BYTE, SCALE_x1); // load i0,fastbase,i0,byte
+ }
+ else if (size == 2)
+ {
+ UML_XOR(block, I0, I0, mips3->bigendian ? WORD_XOR_BE(0) : WORD_XOR_LE(0));
+ // xor i0,i0,wordxor
+ UML_LOAD(block, I0, fastbase, I0, SIZE_WORD, SCALE_x1); // load i0,fastbase,i0,word_x1
+ }
+ else if (size == 4)
+ {
+ UML_LOAD(block, I0, fastbase, I0, SIZE_DWORD, SCALE_x1); // load i0,fastbase,i0,dword_x1
+ }
+ else if (size == 8)
+ {
+ UML_DLOAD(block, I0, fastbase, I0, SIZE_QWORD, SCALE_x1); // dload i0,fastbase,i0,qword_x1
+ UML_DROR(block, I0, I0, 32 * (mips3->bigendian ? BYTE_XOR_BE(0) : BYTE_XOR_LE(0)));
+ // dror i0,i0,32*bytexor
+ }
+ UML_RET(block); // ret
+ }
+ else
+ {
+ if (size == 1)
+ {
+ UML_XOR(block, I0, I0, mips3->bigendian ? BYTE4_XOR_BE(0) : BYTE4_XOR_LE(0));
+ // xor i0,i0,bytexor
+ UML_STORE(block, fastbase, I0, I1, SIZE_BYTE, SCALE_x1);// store fastbase,i0,i1,byte
+ }
+ else if (size == 2)
+ {
+ UML_XOR(block, I0, I0, mips3->bigendian ? WORD_XOR_BE(0) : WORD_XOR_LE(0));
+ // xor i0,i0,wordxor
+ UML_STORE(block, fastbase, I0, I1, SIZE_WORD, SCALE_x1);// store fastbase,i0,i1,word_x1
+ }
+ else if (size == 4)
+ {
+ if (ismasked)
+ {
+ UML_LOAD(block, I3, fastbase, I0, SIZE_DWORD, SCALE_x1); // load i3,fastbase,i0,dword_x1
+ UML_ROLINS(block, I3, I1, 0, I2); // rolins i3,i1,0,i2
+ UML_STORE(block, fastbase, I0, I3, SIZE_DWORD, SCALE_x1); // store fastbase,i0,i3,dword_x1
+ }
+ else
+ UML_STORE(block, fastbase, I0, I1, SIZE_DWORD, SCALE_x1); // store fastbase,i0,i1,dword_x1
+ }
+ else if (size == 8)
+ {
+ UML_DROR(block, I1, I1, 32 * (mips3->bigendian ? BYTE_XOR_BE(0) : BYTE_XOR_LE(0)));
+ // dror i1,i1,32*bytexor
+ if (ismasked)
+ {
+ UML_DROR(block, I2, I2, 32 * (mips3->bigendian ? BYTE_XOR_BE(0) : BYTE_XOR_LE(0)));
+ // dror i2,i2,32*bytexor
+ UML_DLOAD(block, I3, fastbase, I0, SIZE_QWORD, SCALE_x1); // dload i3,fastbase,i0,qword_x1
+ UML_DROLINS(block, I3, I1, 0, I2); // drolins i3,i1,0,i2
+ UML_DSTORE(block, fastbase, I0, I3, SIZE_QWORD, SCALE_x1); // dstore fastbase,i0,i3,qword_x1
+ }
+ else
+ UML_DSTORE(block, fastbase, I0, I1, SIZE_QWORD, SCALE_x1); // dstore fastbase,i0,i1,qword_x1
+ }
+ UML_RET(block); // ret
+ }
+
+ UML_LABEL(block, skip); // skip:
+ }
+
+ switch (size)
+ {
+ case 1:
+ if (iswrite)
+ UML_WRITE(block, I0, I1, SIZE_BYTE, SPACE_PROGRAM); // write i0,i1,program_byte
+ else
+ UML_READ(block, I0, I0, SIZE_BYTE, SPACE_PROGRAM); // read i0,i0,program_byte
+ break;
+
+ case 2:
+ if (iswrite)
+ UML_WRITE(block, I0, I1, SIZE_WORD, SPACE_PROGRAM); // write i0,i1,program_word
+ else
+ UML_READ(block, I0, I0, SIZE_WORD, SPACE_PROGRAM); // read i0,i0,program_word
+ break;
+
+ case 4:
+ if (iswrite)
+ {
+ if (!ismasked)
+ UML_WRITE(block, I0, I1, SIZE_DWORD, SPACE_PROGRAM); // write i0,i1,program_dword
+ else
+ UML_WRITEM(block, I0, I1, I2, SIZE_DWORD, SPACE_PROGRAM); // writem i0,i1,i2,program_dword
+ }
+ else
+ {
+ if (!ismasked)
+ UML_READ(block, I0, I0, SIZE_DWORD, SPACE_PROGRAM); // read i0,i0,program_dword
+ else
+ UML_READM(block, I0, I0, I2, SIZE_DWORD, SPACE_PROGRAM); // readm i0,i0,i2,program_dword
+ }
+ break;
+
+ case 8:
+ if (iswrite)
+ {
+ if (!ismasked)
+ UML_DWRITE(block, I0, I1, SIZE_QWORD, SPACE_PROGRAM); // dwrite i0,i1,program_qword
+ else
+ UML_DWRITEM(block, I0, I1, I2, SIZE_QWORD, SPACE_PROGRAM); // dwritem i0,i1,i2,program_qword
+ }
+ else
+ {
+ if (!ismasked)
+ UML_DREAD(block, I0, I0, SIZE_QWORD, SPACE_PROGRAM); // dread i0,i0,program_qword
+ else
+ UML_DREADM(block, I0, I0, I2, SIZE_QWORD, SPACE_PROGRAM); // dreadm i0,i0,i2,program_qword
+ }
+ break;
+ }
+ UML_RET(block); // ret
+
+ if (tlbmiss != 0)
+ {
+ UML_LABEL(block, tlbmiss); // tlbmiss:
+ if (iswrite)
+ {
+ UML_TEST(block, I3, VTLB_READ_ALLOWED); // test i3,VTLB_READ_ALLOWED
+ UML_EXHc(block, COND_NZ, *mips3->impstate->exception[EXCEPTION_TLBMOD], I0);
+ // exh tlbmod,i0,nz
+ }
+ UML_TEST(block, I3, VTLB_FLAG_FIXED); // test i3,VTLB_FLAG_FIXED
+ UML_EXHc(block, COND_NZ, exception_tlb, I0); // exh tlb,i0,nz
+ UML_EXH(block, exception_tlbfill, I0); // exh tlbfill,i0
+ }
+
+ block->end();
+}
+
+
+
+/***************************************************************************
+ CODE GENERATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ generate_update_mode - update the mode based
+ on a new SR (in i0); trashes i2
+-------------------------------------------------*/
+
+static void generate_update_mode(mips3_state *mips3, drcuml_block *block)
+{
+ UML_ROLAND(block, I2, I0, 32-2, 0x06); // roland i2,i0,32-2,0x06
+ UML_TEST(block, I0, SR_EXL | SR_ERL); // test i0,SR_EXL | SR_ERL
+ UML_MOVc(block, COND_NZ, I2, 0); // mov i2,0,nz
+ UML_ROLINS(block, I2, I0, 32-26, 0x01); // rolins i2,i0,32-26,0x01
+ UML_MOV(block, mem(&mips3->impstate->mode), I2); // mov [mode],i2
+}
+
+
+/*-------------------------------------------------
+ generate_update_cycles - generate code to
+ subtract cycles from the icount and generate
+ an exception if out
+-------------------------------------------------*/
+
+static void generate_update_cycles(mips3_state *mips3, drcuml_block *block, compiler_state *compiler, parameter param, int allow_exception)
+{
+ /* check software interrupts if pending */
+ if (compiler->checksoftints)
+ {
+ code_label skip;
+
+ compiler->checksoftints = FALSE;
+ UML_AND(block, I0, CPR032(COP0_Cause), CPR032(COP0_Status)); // and i0,[Cause],[Status]
+ UML_AND(block, I0, I0, 0x0300); // and i0,i0,0x0300
+ UML_JMPc(block, COND_Z, skip = compiler->labelnum++); // jmp skip,Z
+ UML_MOV(block, I0, param); // mov i0,nextpc
+ UML_MOV(block, I1, compiler->cycles); // mov i1,cycles
+ UML_CALLH(block, *mips3->impstate->exception_norecover[EXCEPTION_INTERRUPT]);// callh interrupt_norecover
+ UML_LABEL(block, skip); // skip:
+ }
+
+ /* check full interrupts if pending */
+ if (compiler->checkints)
+ {
+ code_label skip;
+
+ compiler->checkints = FALSE;
+ UML_AND(block, I0, CPR032(COP0_Cause), CPR032(COP0_Status)); // and i0,[Cause],[Status]
+ UML_AND(block, I0, I0, 0xfc00); // and i0,i0,0xfc00
+ UML_JMPc(block, COND_Z, skip = compiler->labelnum++); // jmp skip,Z
+ UML_TEST(block, CPR032(COP0_Status), SR_IE); // test [Status],SR_IE
+ UML_JMPc(block, COND_Z, skip); // jmp skip,Z
+ UML_TEST(block, CPR032(COP0_Status), SR_EXL | SR_ERL); // test [Status],SR_EXL | SR_ERL
+ UML_JMPc(block, COND_NZ, skip); // jmp skip,NZ
+ UML_MOV(block, I0, param); // mov i0,nextpc
+ UML_MOV(block, I1, compiler->cycles); // mov i1,cycles
+ UML_CALLH(block, *mips3->impstate->exception_norecover[EXCEPTION_INTERRUPT]);// callh interrupt_norecover
+ UML_LABEL(block, skip); // skip:
+ }
+
+ /* account for cycles */
+ if (compiler->cycles > 0)
+ {
+ UML_SUB(block, mem(&mips3->icount), mem(&mips3->icount), MAPVAR_CYCLES); // sub icount,icount,cycles
+ UML_MAPVAR(block, MAPVAR_CYCLES, 0); // mapvar cycles,0
+ if (allow_exception)
+ UML_EXHc(block, COND_S, *mips3->impstate->out_of_cycles, param);
+ // exh out_of_cycles,nextpc
+ }
+ compiler->cycles = 0;
+}
+
+
+/*-------------------------------------------------
+ generate_checksum_block - generate code to
+ validate a sequence of opcodes
+-------------------------------------------------*/
+
+static void generate_checksum_block(mips3_state *mips3, drcuml_block *block, compiler_state *compiler, const opcode_desc *seqhead, const opcode_desc *seqlast)
+{
+ const opcode_desc *curdesc;
+ if (LOG_UML)
+ block->append_comment("[Validation for %08X]", seqhead->pc); // comment
+
+ /* loose verify or single instruction: just compare and fail */
+ if (!(mips3->impstate->drcoptions & MIPS3DRC_STRICT_VERIFY) || seqhead->next() == NULL)
+ {
+ if (!(seqhead->flags & OPFLAG_VIRTUAL_NOOP))
+ {
+ void *base = mips3->direct->read_decrypted_ptr(seqhead->physpc);
+ UML_LOAD(block, I0, base, 0, SIZE_DWORD, SCALE_x4); // load i0,base,0,dword
+ UML_CMP(block, I0, seqhead->opptr.l[0]); // cmp i0,opptr[0]
+ UML_EXHc(block, COND_NE, *mips3->impstate->nocode, epc(seqhead)); // exne nocode,seqhead->pc
+ }
+ }
+
+ /* full verification; sum up everything */
+ else
+ {
+#if 0
+ for (curdesc = seqhead->next(); curdesc != seqlast->next(); curdesc = curdesc->next())
+ if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP))
+ {
+ void *base = mips3->direct->read_decrypted_ptr(seqhead->physpc);
+ UML_LOAD(block, I0, base, 0, SIZE_DWORD, SCALE_x4); // load i0,base,0,dword
+ UML_CMP(block, I0, curdesc->opptr.l[0]); // cmp i0,opptr[0]
+ UML_EXHc(block, COND_NE, *mips3->impstate->nocode, epc(seqhead)); // exne nocode,seqhead->pc
+ }
+#else
+ UINT32 sum = 0;
+ void *base = mips3->direct->read_decrypted_ptr(seqhead->physpc);
+ UML_LOAD(block, I0, base, 0, SIZE_DWORD, SCALE_x4); // load i0,base,0,dword
+ sum += seqhead->opptr.l[0];
+ for (curdesc = seqhead->next(); curdesc != seqlast->next(); curdesc = curdesc->next())
+ if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP))
+ {
+ base = mips3->direct->read_decrypted_ptr(curdesc->physpc);
+ UML_LOAD(block, I1, base, 0, SIZE_DWORD, SCALE_x4); // load i1,base,dword
+ UML_ADD(block, I0, I0, I1); // add i0,i0,i1
+ sum += curdesc->opptr.l[0];
+
+ if (curdesc->delay.first() != NULL && (curdesc == seqlast || (curdesc->next() != NULL && curdesc->next()->physpc != curdesc->delay.first()->physpc)))
+ {
+ base = mips3->direct->read_decrypted_ptr(curdesc->delay.first()->physpc);
+ UML_LOAD(block, I1, base, 0, SIZE_DWORD, SCALE_x4); // load i1,base,dword
+ UML_ADD(block, I0, I0, I1); // add i0,i0,i1
+ sum += curdesc->delay.first()->opptr.l[0];
+ }
+ }
+ UML_CMP(block, I0, sum); // cmp i0,sum
+ UML_EXHc(block, COND_NE, *mips3->impstate->nocode, epc(seqhead)); // exne nocode,seqhead->pc
+#endif
+ }
+}
+
+
+/*-------------------------------------------------
+ generate_sequence_instruction - generate code
+ for a single instruction in a sequence
+-------------------------------------------------*/
+
+static void generate_sequence_instruction(mips3_state *mips3, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
+{
+ offs_t expc;
+ int hotnum;
+
+ /* add an entry for the log */
+ if (LOG_UML && !(desc->flags & OPFLAG_VIRTUAL_NOOP))
+ log_add_disasm_comment(mips3, block, desc->pc, desc->opptr.l[0]);
+
+ /* set the PC map variable */
+ expc = (desc->flags & OPFLAG_IN_DELAY_SLOT) ? desc->pc - 3 : desc->pc;
+ UML_MAPVAR(block, MAPVAR_PC, expc); // mapvar PC,expc
+
+ /* accumulate total cycles */
+ compiler->cycles += desc->cycles;
+
+ /* is this a hotspot? */
+ for (hotnum = 0; hotnum < MIPS3_MAX_HOTSPOTS; hotnum++)
+ if (mips3->impstate->hotspot[hotnum].pc != 0 && desc->pc == mips3->impstate->hotspot[hotnum].pc && desc->opptr.l[0] == mips3->impstate->hotspot[hotnum].opcode)
+ {
+ compiler->cycles += mips3->impstate->hotspot[hotnum].cycles;
+ break;
+ }
+
+ /* update the icount map variable */
+ UML_MAPVAR(block, MAPVAR_CYCLES, compiler->cycles); // mapvar CYCLES,compiler->cycles
+
+ /* if we want a probe, add it here */
+ if (desc->pc == PROBE_ADDRESS)
+ {
+ UML_MOV(block, mem(&mips3->pc), desc->pc); // mov [pc],desc->pc
+ UML_CALLC(block, cfunc_printf_probe, mips3); // callc cfunc_printf_probe,mips3
+ }
+
+ /* if we are debugging, call the debugger */
+ if ((mips3->device->machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ {
+ UML_MOV(block, mem(&mips3->pc), desc->pc); // mov [pc],desc->pc
+ save_fast_iregs(mips3, block);
+ UML_DEBUG(block, desc->pc); // debug desc->pc
+ }
+
+ /* if we hit an unmapped address, fatal error */
+ if (desc->flags & OPFLAG_COMPILER_UNMAPPED)
+ {
+ UML_MOV(block, mem(&mips3->pc), desc->pc); // mov [pc],desc->pc
+ save_fast_iregs(mips3, block);
+ UML_EXIT(block, EXECUTE_UNMAPPED_CODE); // exit EXECUTE_UNMAPPED_CODE
+ }
+
+ /* if we hit a compiler page fault, it's just like a TLB mismatch */
+ if (desc->flags & OPFLAG_COMPILER_PAGE_FAULT)
+ {
+ if (PRINTF_MMU)
+ {
+ static const char text[] = "Compiler page fault @ %08X";
+ UML_MOV(block, mem(&mips3->impstate->format), (FPTR)text); // mov [format],text
+ UML_MOV(block, mem(&mips3->impstate->arg0), desc->pc); // mov [arg0],desc->pc
+ UML_CALLC(block, cfunc_printf_debug, mips3); // callc printf_debug
+ }
+ UML_EXH(block, *mips3->impstate->tlb_mismatch, 0); // exh tlb_mismatch,0
+ }
+
+ /* validate our TLB entry at this PC; if we fail, we need to handle it */
+ if ((desc->flags & OPFLAG_VALIDATE_TLB) && (desc->pc < 0x80000000 || desc->pc >= 0xc0000000))
+ {
+ const vtlb_entry *tlbtable = vtlb_table(mips3->vtlb);
+
+ /* if we currently have a valid TLB read entry, we just verify */
+ if (tlbtable[desc->pc >> 12] & VTLB_FETCH_ALLOWED)
+ {
+ if (PRINTF_MMU)
+ {
+ static const char text[] = "Checking TLB at @ %08X\n";
+ UML_MOV(block, mem(&mips3->impstate->format), (FPTR)text); // mov [format],text
+ UML_MOV(block, mem(&mips3->impstate->arg0), desc->pc); // mov [arg0],desc->pc
+ UML_CALLC(block, cfunc_printf_debug, mips3); // callc printf_debug
+ }
+ UML_LOAD(block, I0, &tlbtable[desc->pc >> 12], 0, SIZE_DWORD, SCALE_x4); // load i0,tlbtable[desc->pc >> 12],0,dword
+ UML_CMP(block, I0, tlbtable[desc->pc >> 12]); // cmp i0,*tlbentry
+ UML_EXHc(block, COND_NE, *mips3->impstate->tlb_mismatch, 0); // exh tlb_mismatch,0,NE
+ }
+
+ /* otherwise, we generate an unconditional exception */
+ else
+ {
+ if (PRINTF_MMU)
+ {
+ static const char text[] = "No valid TLB @ %08X\n";
+ UML_MOV(block, mem(&mips3->impstate->format), (FPTR)text); // mov [format],text
+ UML_MOV(block, mem(&mips3->impstate->arg0), desc->pc); // mov [arg0],desc->pc
+ UML_CALLC(block, cfunc_printf_debug, mips3); // callc printf_debug
+ }
+ UML_EXH(block, *mips3->impstate->tlb_mismatch, 0); // exh tlb_mismatch,0
+ }
+ }
+
+ /* if this is an invalid opcode, generate the exception now */
+ if (desc->flags & OPFLAG_INVALID_OPCODE)
+ UML_EXH(block, *mips3->impstate->exception[EXCEPTION_INVALIDOP], 0); // exh invalidop,0
+
+ /* otherwise, unless this is a virtual no-op, it's a regular instruction */
+ else if (!(desc->flags & OPFLAG_VIRTUAL_NOOP))
+ {
+ /* compile the instruction */
+ if (!generate_opcode(mips3, block, compiler, desc))
+ {
+ UML_MOV(block, mem(&mips3->pc), desc->pc); // mov [pc],desc->pc
+ UML_MOV(block, mem(&mips3->impstate->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_unimplemented, mips3); // callc cfunc_unimplemented
+ }
+ }
+}
+
+
+/*------------------------------------------------------------------
+ generate_delay_slot_and_branch
+------------------------------------------------------------------*/
+
+static void generate_delay_slot_and_branch(mips3_state *mips3, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT8 linkreg)
+{
+ compiler_state compiler_temp = *compiler;
+ UINT32 op = desc->opptr.l[0];
+
+ /* fetch the target register if dynamic, in case it is modified by the delay slot */
+ if (desc->targetpc == BRANCH_TARGET_DYNAMIC)
+ UML_MOV(block, mem(&mips3->impstate->jmpdest), R32(RSREG)); // mov [jmpdest],<rsreg>
+
+ /* set the link if needed -- before the delay slot */
+ if (linkreg != 0)
+ UML_DMOV(block, R64(linkreg), (INT32)(desc->pc + 8)); // dmov <linkreg>,desc->pc + 8
+
+ /* compile the delay slot using temporary compiler state */
+ assert(desc->delay.first() != NULL);
+ generate_sequence_instruction(mips3, block, &compiler_temp, desc->delay.first()); // <next instruction>
+
+ /* update the cycles and jump through the hash table to the target */
+ if (desc->targetpc != BRANCH_TARGET_DYNAMIC)
+ {
+ generate_update_cycles(mips3, block, &compiler_temp, desc->targetpc, TRUE); // <subtract cycles>
+ if (desc->flags & OPFLAG_INTRABLOCK_BRANCH)
+ UML_JMP(block, desc->targetpc | 0x80000000); // jmp desc->targetpc | 0x80000000
+ else
+ UML_HASHJMP(block, mips3->impstate->mode, desc->targetpc, *mips3->impstate->nocode);
+ // hashjmp <mode>,desc->targetpc,nocode
+ }
+ else
+ {
+ generate_update_cycles(mips3, block, &compiler_temp, mem(&mips3->impstate->jmpdest), TRUE);
+ // <subtract cycles>
+ UML_HASHJMP(block, mips3->impstate->mode, mem(&mips3->impstate->jmpdest), *mips3->impstate->nocode);
+ // hashjmp <mode>,<rsreg>,nocode
+ }
+
+ /* update the label */
+ compiler->labelnum = compiler_temp.labelnum;
+
+ /* reset the mapvar to the current cycles and account for skipped slots */
+ compiler->cycles += desc->skipslots;
+ UML_MAPVAR(block, MAPVAR_CYCLES, compiler->cycles); // mapvar CYCLES,compiler->cycles
+}
+
+
+/*-------------------------------------------------
+ generate_opcode - generate code for a specific
+ opcode
+-------------------------------------------------*/
+
+static int generate_opcode(mips3_state *mips3, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
+{
+ int in_delay_slot = ((desc->flags & OPFLAG_IN_DELAY_SLOT) != 0);
+ UINT32 op = desc->opptr.l[0];
+ UINT8 opswitch = op >> 26;
+ code_label skip;
+
+ switch (opswitch)
+ {
+ /* ----- sub-groups ----- */
+
+ case 0x00: /* SPECIAL - MIPS I */
+ return generate_special(mips3, block, compiler, desc);
+
+ case 0x01: /* REGIMM - MIPS I */
+ return generate_regimm(mips3, block, compiler, desc);
+
+ case 0x1c: /* IDT-specific */
+ return generate_idt(mips3, block, compiler, desc);
+
+
+ /* ----- jumps and branches ----- */
+
+ case 0x02: /* J - MIPS I */
+ generate_delay_slot_and_branch(mips3, block, compiler, desc, 0); // <next instruction + hashjmp>
+ return TRUE;
+
+ case 0x03: /* JAL - MIPS I */
+ generate_delay_slot_and_branch(mips3, block, compiler, desc, 31); // <next instruction + hashjmp>
+ return TRUE;
+
+ case 0x04: /* BEQ - MIPS I */
+ case 0x14: /* BEQL - MIPS II */
+ UML_DCMP(block, R64(RSREG), R64(RTREG)); // dcmp <rsreg>,<rtreg>
+ UML_JMPc(block, COND_NE, skip = compiler->labelnum++); // jmp skip,NE
+ generate_delay_slot_and_branch(mips3, block, compiler, desc, 0); // <next instruction + hashjmp>
+ UML_LABEL(block, skip); // skip:
+ return TRUE;
+
+ case 0x05: /* BNE - MIPS I */
+ case 0x15: /* BNEL - MIPS II */
+ UML_DCMP(block, R64(RSREG), R64(RTREG)); // dcmp <rsreg>,<rtreg>
+ UML_JMPc(block, COND_E, skip = compiler->labelnum++); // jmp skip,E
+ generate_delay_slot_and_branch(mips3, block, compiler, desc, 0); // <next instruction + hashjmp>
+ UML_LABEL(block, skip); // skip:
+ return TRUE;
+
+ case 0x06: /* BLEZ - MIPS I */
+ case 0x16: /* BLEZL - MIPS II */
+ if (RSREG != 0)
+ {
+ UML_DCMP(block, R64(RSREG), 0); // dcmp <rsreg>,0
+ UML_JMPc(block, COND_G, skip = compiler->labelnum++); // jmp skip,G
+ generate_delay_slot_and_branch(mips3, block, compiler, desc, 0); // <next instruction + hashjmp>
+ UML_LABEL(block, skip); // skip:
+ }
+ else
+ generate_delay_slot_and_branch(mips3, block, compiler, desc, 0); // <next instruction + hashjmp>
+ return TRUE;
+
+ case 0x07: /* BGTZ - MIPS I */
+ case 0x17: /* BGTZL - MIPS II */
+ UML_DCMP(block, R64(RSREG), 0); // dcmp <rsreg>,0
+ UML_JMPc(block, COND_LE, skip = compiler->labelnum++); // jmp skip,LE
+ generate_delay_slot_and_branch(mips3, block, compiler, desc, 0); // <next instruction + hashjmp>
+ UML_LABEL(block, skip); // skip:
+ return TRUE;
+
+
+ /* ----- immediate arithmetic ----- */
+
+ case 0x0f: /* LUI - MIPS I */
+ if (RTREG != 0)
+ UML_DMOV(block, R64(RTREG), SIMMVAL << 16); // dmov <rtreg>,SIMMVAL << 16
+ return TRUE;
+
+ case 0x08: /* ADDI - MIPS I */
+ UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
+ if (mips3->impstate->drcoptions & MIPS3DRC_CHECK_OVERFLOWS)
+ UML_EXHc(block, COND_V, *mips3->impstate->exception[EXCEPTION_OVERFLOW], 0);
+ // exh overflow,0
+ if (RTREG != 0)
+ UML_DSEXT(block, R64(RTREG), I0, SIZE_DWORD); // dsext <rtreg>,i0,dword
+ return TRUE;
+
+ case 0x09: /* ADDIU - MIPS I */
+ if (RTREG != 0)
+ {
+ UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL,V
+ UML_DSEXT(block, R64(RTREG), I0, SIZE_DWORD); // dsext <rtreg>,i0,dword
+ }
+ return TRUE;
+
+ case 0x18: /* DADDI - MIPS III */
+ UML_DADD(block, I0, R64(RSREG), SIMMVAL); // dadd i0,<rsreg>,SIMMVAL
+ if (mips3->impstate->drcoptions & MIPS3DRC_CHECK_OVERFLOWS)
+ UML_EXHc(block, COND_V, *mips3->impstate->exception[EXCEPTION_OVERFLOW], 0);
+ // exh overflow,0
+ if (RTREG != 0)
+ UML_DMOV(block, R64(RTREG), I0); // dmov <rtreg>,i0
+ return TRUE;
+
+ case 0x19: /* DADDIU - MIPS III */
+ if (RTREG != 0)
+ UML_DADD(block, R64(RTREG), R64(RSREG), SIMMVAL); // dadd <rtreg>,<rsreg>,SIMMVAL
+ return TRUE;
+
+ case 0x0c: /* ANDI - MIPS I */
+ if (RTREG != 0)
+ UML_DAND(block, R64(RTREG), R64(RSREG), UIMMVAL); // dand <rtreg>,<rsreg>,UIMMVAL
+ return TRUE;
+
+ case 0x0d: /* ORI - MIPS I */
+ if (RTREG != 0)
+ UML_DOR(block, R64(RTREG), R64(RSREG), UIMMVAL); // dor <rtreg>,<rsreg>,UIMMVAL
+ return TRUE;
+
+ case 0x0e: /* XORI - MIPS I */
+ if (RTREG != 0)
+ UML_DXOR(block, R64(RTREG), R64(RSREG), UIMMVAL); // dxor <rtreg>,<rsreg>,UIMMVAL
+ return TRUE;
+
+ case 0x0a: /* SLTI - MIPS I */
+ if (RTREG != 0)
+ {
+ UML_DCMP(block, R64(RSREG), SIMMVAL); // dcmp <rsreg>,SIMMVAL
+ UML_DSETc(block, COND_L, R64(RTREG)); // dset <rtreg>,l
+ }
+ return TRUE;
+
+ case 0x0b: /* SLTIU - MIPS I */
+ if (RTREG != 0)
+ {
+ UML_DCMP(block, R64(RSREG), SIMMVAL); // dcmp <rsreg>,SIMMVAL
+ UML_DSETc(block, COND_B, R64(RTREG)); // dset <rtreg>,b
+ }
+ return TRUE;
+
+
+ /* ----- memory load operations ----- */
+
+ case 0x20: /* LB - MIPS I */
+ UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
+ UML_CALLH(block, *mips3->impstate->read8[mips3->impstate->mode >> 1]); // callh read8
+ if (RTREG != 0)
+ UML_DSEXT(block, R64(RTREG), I0, SIZE_BYTE); // dsext <rtreg>,i0,byte
+ if (!in_delay_slot)
+ generate_update_cycles(mips3, block, compiler, desc->pc + 4, TRUE);
+ return TRUE;
+
+ case 0x21: /* LH - MIPS I */
+ UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
+ UML_CALLH(block, *mips3->impstate->read16[mips3->impstate->mode >> 1]); // callh read16
+ if (RTREG != 0)
+ UML_DSEXT(block, R64(RTREG), I0, SIZE_WORD); // dsext <rtreg>,i0,word
+ if (!in_delay_slot)
+ generate_update_cycles(mips3, block, compiler, desc->pc + 4, TRUE);
+ return TRUE;
+
+ case 0x23: /* LW - MIPS I */
+ UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
+ UML_CALLH(block, *mips3->impstate->read32[mips3->impstate->mode >> 1]); // callh read32
+ if (RTREG != 0)
+ UML_DSEXT(block, R64(RTREG), I0, SIZE_DWORD); // dsext <rtreg>,i0
+ if (!in_delay_slot)
+ generate_update_cycles(mips3, block, compiler, desc->pc + 4, TRUE);
+ return TRUE;
+
+ case 0x30: /* LL - MIPS II */
+ UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
+ UML_CALLH(block, *mips3->impstate->read32[mips3->impstate->mode >> 1]); // callh read32
+ if (RTREG != 0)
+ UML_DSEXT(block, R64(RTREG), I0, SIZE_DWORD); // dsext <rtreg>,i0
+ UML_MOV(block, mem(&mips3->llbit), 1); // mov [llbit],1
+ if (!in_delay_slot)
+ generate_update_cycles(mips3, block, compiler, desc->pc + 4, TRUE);
+ return TRUE;
+
+ case 0x24: /* LBU - MIPS I */
+ UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
+ UML_CALLH(block, *mips3->impstate->read8[mips3->impstate->mode >> 1]); // callh read8
+ if (RTREG != 0)
+ UML_DAND(block, R64(RTREG), I0, 0xff); // dand <rtreg>,i0,0xff
+ if (!in_delay_slot)
+ generate_update_cycles(mips3, block, compiler, desc->pc + 4, TRUE);
+ return TRUE;
+
+ case 0x25: /* LHU - MIPS I */
+ UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
+ UML_CALLH(block, *mips3->impstate->read16[mips3->impstate->mode >> 1]); // callh read16
+ if (RTREG != 0)
+ UML_DAND(block, R64(RTREG), I0, 0xffff); // dand <rtreg>,i0,0xffff
+ if (!in_delay_slot)
+ generate_update_cycles(mips3, block, compiler, desc->pc + 4, TRUE);
+ return TRUE;
+
+ case 0x27: /* LWU - MIPS III */
+ UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
+ UML_CALLH(block, *mips3->impstate->read32[mips3->impstate->mode >> 1]); // callh read32
+ if (RTREG != 0)
+ UML_DAND(block, R64(RTREG), I0, 0xffffffff); // dand <rtreg>,i0,0xffffffff
+ if (!in_delay_slot)
+ generate_update_cycles(mips3, block, compiler, desc->pc + 4, TRUE);
+ return TRUE;
+
+ case 0x37: /* LD - MIPS III */
+ UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
+ UML_CALLH(block, *mips3->impstate->read64[mips3->impstate->mode >> 1]); // callh read64
+ if (RTREG != 0)
+ UML_DMOV(block, R64(RTREG), I0); // dmov <rtreg>,i0
+ if (!in_delay_slot)
+ generate_update_cycles(mips3, block, compiler, desc->pc + 4, TRUE);
+ return TRUE;
+
+ case 0x34: /* LLD - MIPS III */
+ UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
+ UML_CALLH(block, *mips3->impstate->read64[mips3->impstate->mode >> 1]); // callh read64
+ if (RTREG != 0)
+ UML_DMOV(block, R64(RTREG), I0); // dmov <rtreg>,i0
+ UML_MOV(block, mem(&mips3->llbit), 1); // mov [llbit],1
+ if (!in_delay_slot)
+ generate_update_cycles(mips3, block, compiler, desc->pc + 4, TRUE);
+ return TRUE;
+
+ case 0x22: /* LWL - MIPS I */
+ UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
+ UML_SHL(block, I1, I0, 3); // shl i1,i0,3
+ UML_AND(block, I0, I0, ~3); // and i0,i0,~3
+ if (!mips3->bigendian)
+ UML_XOR(block, I1, I1, 0x18); // xor i1,i1,0x18
+ UML_SHR(block, I2, ~0, I1); // shr i2,~0,i1
+ UML_CALLH(block, *mips3->impstate->read32mask[mips3->impstate->mode >> 1]);
+ // callh read32mask
+ if (RTREG != 0)
+ {
+ UML_SHL(block, I2, ~0, I1); // shl i2,~0,i1
+ UML_MOV(block, I3, R32(RTREG)); // mov i3,<rtreg>
+ UML_ROLINS(block, I3, I0, I1, I2); // rolins i3,i0,i1,i2
+ UML_DSEXT(block, R64(RTREG), I3, SIZE_DWORD); // dsext <rtreg>,i3,dword
+ }
+ if (!in_delay_slot)
+ generate_update_cycles(mips3, block, compiler, desc->pc + 4, TRUE);
+ return TRUE;
+
+ case 0x26: /* LWR - MIPS I */
+ UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
+ UML_SHL(block, I1, I0, 3); // shl i1,i0,3
+ UML_AND(block, I0, I0, ~3); // and i0,i0,~3
+ if (mips3->bigendian)
+ UML_XOR(block, I1, I1, 0x18); // xor i1,i1,0x18
+ UML_SHL(block, I2, ~0, I1); // shl i2,~0,i1
+ UML_CALLH(block, *mips3->impstate->read32mask[mips3->impstate->mode >> 1]);
+ // callh read32mask
+ if (RTREG != 0)
+ {
+ UML_SHR(block, I2, ~0, I1); // shr i2,~0,i1
+ UML_SUB(block, I1, 32, I1); // sub i1,32,i1
+ UML_MOV(block, I3, R32(RTREG)); // mov i3,<rtreg>
+ UML_ROLINS(block, I3, I0, I1, I2); // rolins i3,i0,i1,i2
+ UML_DSEXT(block, R64(RTREG), I3, SIZE_DWORD); // dsext <rtreg>,i3,dword
+ }
+ if (!in_delay_slot)
+ generate_update_cycles(mips3, block, compiler, desc->pc + 4, TRUE);
+ return TRUE;
+
+ case 0x1a: /* LDL - MIPS III */
+ UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
+ UML_SHL(block, I1, I0, 3); // shl i1,i0,3
+ UML_AND(block, I0, I0, ~7); // and i0,i0,~7
+ if (!mips3->bigendian)
+ UML_XOR(block, I1, I1, 0x38); // xor i1,i1,0x38
+ UML_DSHR(block, I2, (UINT64)~0, I1); // dshr i2,~0,i1
+ UML_CALLH(block, *mips3->impstate->read64mask[mips3->impstate->mode >> 1]);
+ // callh read64mask
+ if (RTREG != 0)
+ {
+ UML_DSHL(block, I2, (UINT64)~0, I1); // dshl i2,~0,i1
+ UML_DROLINS(block, R64(RTREG), I0, I1, I2); // drolins <rtreg>,i0,i1,i2
+ }
+ if (!in_delay_slot)
+ generate_update_cycles(mips3, block, compiler, desc->pc + 4, TRUE);
+ return TRUE;
+
+ case 0x1b: /* LDR - MIPS III */
+ UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
+ UML_SHL(block, I1, I0, 3); // shl i1,i0,3
+ UML_AND(block, I0, I0, ~7); // and i0,i0,~7
+ if (mips3->bigendian)
+ UML_XOR(block, I1, I1, 0x38); // xor i1,i1,0x38
+ UML_DSHL(block, I2, (UINT64)~0, I1); // dshl i2,~0,i1
+ UML_CALLH(block, *mips3->impstate->read64mask[mips3->impstate->mode >> 1]);
+ // callh read64mask
+ if (RTREG != 0)
+ {
+ UML_DSHR(block, I2, (UINT64)~0, I1); // dshr i2,~0,i1
+ UML_SUB(block, I1, 64, I1); // sub i1,64,i1
+ UML_DROLINS(block, R64(RTREG), I0, I1, I2); // drolins <rtreg>,i0,i1,i2
+ }
+ if (!in_delay_slot)
+ generate_update_cycles(mips3, block, compiler, desc->pc + 4, TRUE);
+ return TRUE;
+
+ case 0x31: /* LWC1 - MIPS I */
+ UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
+ UML_CALLH(block, *mips3->impstate->read32[mips3->impstate->mode >> 1]); // callh read32
+ UML_MOV(block, FPR32(RTREG), I0); // mov <cpr1_rt>,i0
+ if (!in_delay_slot)
+ generate_update_cycles(mips3, block, compiler, desc->pc + 4, TRUE);
+ return TRUE;
+
+ case 0x35: /* LDC1 - MIPS III */
+ UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
+ UML_CALLH(block, *mips3->impstate->read64[mips3->impstate->mode >> 1]); // callh read64
+ UML_DMOV(block, FPR64(RTREG), I0); // dmov <cpr1_rt>,i0
+ if (!in_delay_slot)
+ generate_update_cycles(mips3, block, compiler, desc->pc + 4, TRUE);
+ return TRUE;
+
+ case 0x32: /* LWC2 - MIPS I */
+ UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
+ UML_CALLH(block, *mips3->impstate->read32[mips3->impstate->mode >> 1]); // callh read32
+ UML_DAND(block, CPR264(RTREG), I0, 0xffffffff); // dand <cpr2_rt>,i0,0xffffffff
+ if (!in_delay_slot)
+ generate_update_cycles(mips3, block, compiler, desc->pc + 4, TRUE);
+ return TRUE;
+
+ case 0x36: /* LDC2 - MIPS II */
+ UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
+ UML_CALLH(block, *mips3->impstate->read64[mips3->impstate->mode >> 1]); // callh read64
+ UML_DMOV(block, CPR264(RTREG), I0); // dmov <cpr2_rt>,i0
+ if (!in_delay_slot)
+ generate_update_cycles(mips3, block, compiler, desc->pc + 4, TRUE);
+ return TRUE;
+
+
+ /* ----- memory store operations ----- */
+
+ case 0x28: /* SB - MIPS I */
+ UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
+ UML_MOV(block, I1, R32(RTREG)); // mov i1,<rtreg>
+ UML_CALLH(block, *mips3->impstate->write8[mips3->impstate->mode >> 1]); // callh write8
+ if (!in_delay_slot)
+ generate_update_cycles(mips3, block, compiler, desc->pc + 4, TRUE);
+ return TRUE;
+
+ case 0x29: /* SH - MIPS I */
+ UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
+ UML_MOV(block, I1, R32(RTREG)); // mov i1,<rtreg>
+ UML_CALLH(block, *mips3->impstate->write16[mips3->impstate->mode >> 1]); // callh write16
+ if (!in_delay_slot)
+ generate_update_cycles(mips3, block, compiler, desc->pc + 4, TRUE);
+ return TRUE;
+
+ case 0x2b: /* SW - MIPS I */
+ UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
+ UML_MOV(block, I1, R32(RTREG)); // mov i1,<rtreg>
+ UML_CALLH(block, *mips3->impstate->write32[mips3->impstate->mode >> 1]); // callh write32
+ if (!in_delay_slot)
+ generate_update_cycles(mips3, block, compiler, desc->pc + 4, TRUE);
+ return TRUE;
+
+ case 0x38: /* SC - MIPS II */
+ UML_CMP(block, mem(&mips3->llbit), 0); // cmp [llbit],0
+ UML_JMPc(block, COND_E, skip = compiler->labelnum++); // je skip
+ UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
+ UML_MOV(block, I1, R32(RTREG)); // mov i1,<rtreg>
+ UML_CALLH(block, *mips3->impstate->write32[mips3->impstate->mode >> 1]); // callh write32
+ UML_LABEL(block, skip); // skip:
+ UML_DSEXT(block, R64(RTREG), mem(&mips3->llbit), SIZE_DWORD); // dsext <rtreg>,[llbit],dword
+ if (!in_delay_slot)
+ generate_update_cycles(mips3, block, compiler, desc->pc + 4, TRUE);
+ return TRUE;
+
+ case 0x3f: /* SD - MIPS III */
+ UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
+ UML_DMOV(block, I1, R64(RTREG)); // dmov i1,<rtreg>
+ UML_CALLH(block, *mips3->impstate->write64[mips3->impstate->mode >> 1]); // callh write64
+ if (!in_delay_slot)
+ generate_update_cycles(mips3, block, compiler, desc->pc + 4, TRUE);
+ return TRUE;
+
+ case 0x3c: /* SCD - MIPS III */
+ UML_CMP(block, mem(&mips3->llbit), 0); // cmp [llbit],0
+ UML_JMPc(block, COND_E, skip = compiler->labelnum++); // je skip
+ UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
+ UML_DMOV(block, I1, R64(RTREG)); // dmov i1,<rtreg>
+ UML_CALLH(block, *mips3->impstate->write64[mips3->impstate->mode >> 1]); // callh write64
+ UML_LABEL(block, skip); // skip:
+ UML_DSEXT(block, R64(RTREG), mem(&mips3->llbit), SIZE_DWORD); // dsext <rtreg>,[llbit],dword
+ if (!in_delay_slot)
+ generate_update_cycles(mips3, block, compiler, desc->pc + 4, TRUE);
+ return TRUE;
+
+ case 0x2a: /* SWL - MIPS I */
+ UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
+ UML_SHL(block, I3, I0, 3); // shl i3,i0,3
+ UML_AND(block, I0, I0, ~3); // and i0,i0,~3
+ UML_MOV(block, I1, R32(RTREG)); // mov i1,<rtreg>
+ if (!mips3->bigendian)
+ UML_XOR(block, I3, I3, 0x18); // xor i3,i3,0x18
+ UML_SHR(block, I2, ~0, I3); // shr i2,~0,i3
+ UML_SHR(block, I1, I1, I3); // shr i1,i1,i3
+ UML_CALLH(block, *mips3->impstate->write32mask[mips3->impstate->mode >> 1]);
+ // callh write32mask
+ if (!in_delay_slot)
+ generate_update_cycles(mips3, block, compiler, desc->pc + 4, TRUE);
+ return TRUE;
+
+ case 0x2e: /* SWR - MIPS I */
+ UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
+ UML_SHL(block, I3, I0, 3); // shl i3,i0,3
+ UML_AND(block, I0, I0, ~3); // and i0,i0,~3
+ UML_MOV(block, I1, R32(RTREG)); // mov i1,<rtreg>
+ if (mips3->bigendian)
+ UML_XOR(block, I3, I3, 0x18); // xor i3,i3,0x18
+ UML_SHL(block, I2, ~0, I3); // shl i2,~0,i3
+ UML_SHL(block, I1, I1, I3); // shl i1,i1,i3
+ UML_CALLH(block, *mips3->impstate->write32mask[mips3->impstate->mode >> 1]);
+ // callh write32mask
+ if (!in_delay_slot)
+ generate_update_cycles(mips3, block, compiler, desc->pc + 4, TRUE);
+ return TRUE;
+
+ case 0x2c: /* SDL - MIPS III */
+ UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
+ UML_SHL(block, I3, I0, 3); // shl i3,i0,3
+ UML_AND(block, I0, I0, ~7); // and i0,i0,~7
+ UML_DMOV(block, I1, R64(RTREG)); // dmov i1,<rtreg>
+ if (!mips3->bigendian)
+ UML_XOR(block, I3, I3, 0x38); // xor i3,i3,0x38
+ UML_DSHR(block, I2, (UINT64)~0, I3); // dshr i2,~0,i3
+ UML_DSHR(block, I1, I1, I3); // dshr i1,i1,i3
+ UML_CALLH(block, *mips3->impstate->write64mask[mips3->impstate->mode >> 1]);
+ // callh write64mask
+ if (!in_delay_slot)
+ generate_update_cycles(mips3, block, compiler, desc->pc + 4, TRUE);
+ return TRUE;
+
+ case 0x2d: /* SDR - MIPS III */
+ UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
+ UML_SHL(block, I3, I0, 3); // shl i3,i0,3
+ UML_AND(block, I0, I0, ~7); // and i0,i0,~7
+ UML_DMOV(block, I1, R64(RTREG)); // dmov i1,<rtreg>
+ if (mips3->bigendian)
+ UML_XOR(block, I3, I3, 0x38); // xor i3,i3,0x38
+ UML_DSHL(block, I2, (UINT64)~0, I3); // dshl i2,~0,i3
+ UML_DSHL(block, I1, I1, I3); // dshl i1,i1,i3
+ UML_CALLH(block, *mips3->impstate->write64mask[mips3->impstate->mode >> 1]);
+ // callh write64mask
+ if (!in_delay_slot)
+ generate_update_cycles(mips3, block, compiler, desc->pc + 4, TRUE);
+ return TRUE;
+
+ case 0x39: /* SWC1 - MIPS I */
+ UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
+ UML_MOV(block, I1, FPR32(RTREG)); // mov i1,<cpr1_rt>
+ UML_CALLH(block, *mips3->impstate->write32[mips3->impstate->mode >> 1]); // callh write32
+ if (!in_delay_slot)
+ generate_update_cycles(mips3, block, compiler, desc->pc + 4, TRUE);
+ return TRUE;
+
+ case 0x3d: /* SDC1 - MIPS III */
+ UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
+ UML_DMOV(block, I1, FPR64(RTREG)); // dmov i1,<cpr1_rt>
+ UML_CALLH(block, *mips3->impstate->write64[mips3->impstate->mode >> 1]); // callh write64
+ if (!in_delay_slot)
+ generate_update_cycles(mips3, block, compiler, desc->pc + 4, TRUE);
+ return TRUE;
+
+ case 0x3a: /* SWC2 - MIPS I */
+ UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
+ UML_MOV(block, I1, CPR232(RTREG)); // mov i1,<cpr2_rt>
+ UML_CALLH(block, *mips3->impstate->write32[mips3->impstate->mode >> 1]); // callh write32
+ if (!in_delay_slot)
+ generate_update_cycles(mips3, block, compiler, desc->pc + 4, TRUE);
+ return TRUE;
+
+ case 0x3e: /* SDC2 - MIPS II */
+ UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
+ UML_DMOV(block, I1, CPR264(RTREG)); // dmov i1,<cpr2_rt>
+ UML_CALLH(block, *mips3->impstate->write64[mips3->impstate->mode >> 1]); // callh write64
+ if (!in_delay_slot)
+ generate_update_cycles(mips3, block, compiler, desc->pc + 4, TRUE);
+ return TRUE;
+
+
+ /* ----- effective no-ops ----- */
+
+ case 0x2f: /* CACHE - MIPS II */
+ case 0x33: /* PREF - MIPS IV */
+ return TRUE;
+
+
+ /* ----- coprocessor instructions ----- */
+
+ case 0x10: /* COP0 - MIPS I */
+ return generate_cop0(mips3, block, compiler, desc);
+
+ case 0x11: /* COP1 - MIPS I */
+ return generate_cop1(mips3, block, compiler, desc);
+
+ case 0x13: /* COP1X - MIPS IV */
+ return generate_cop1x(mips3, block, compiler, desc);
+
+ case 0x12: /* COP2 - MIPS I */
+ UML_EXH(block, *mips3->impstate->exception[EXCEPTION_INVALIDOP], 0);// exh invalidop,0
+ return TRUE;
+
+
+ /* ----- unimplemented/illegal instructions ----- */
+
+// default: /* ??? */ invalid_instruction(op); break;
+ }
+
+ return FALSE;
+}
+
+
+/*-------------------------------------------------
+ generate_special - compile opcodes in the
+ 'SPECIAL' group
+-------------------------------------------------*/
+
+static int generate_special(mips3_state *mips3, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
+{
+ UINT32 op = desc->opptr.l[0];
+ UINT8 opswitch = op & 63;
+
+ switch (opswitch)
+ {
+ /* ----- shift instructions ----- */
+
+ case 0x00: /* SLL - MIPS I */
+ if (RDREG != 0)
+ {
+ UML_SHL(block, I0, R32(RTREG), SHIFT); // shl i0,<rtreg>,<shift>
+ UML_DSEXT(block, R64(RDREG), I0, SIZE_DWORD); // dsext <rdreg>,i0,dword
+ }
+ return TRUE;
+
+ case 0x02: /* SRL - MIPS I */
+ if (RDREG != 0)
+ {
+ UML_SHR(block, I0, R32(RTREG), SHIFT); // shr i0,<rtreg>,<shift>
+ UML_DSEXT(block, R64(RDREG), I0, SIZE_DWORD); // dsext <rdreg>,i0,dword
+ }
+ return TRUE;
+
+ case 0x03: /* SRA - MIPS I */
+ if (RDREG != 0)
+ {
+ UML_SAR(block, I0, R32(RTREG), SHIFT); // sar i0,<rtreg>,<shift>
+ UML_DSEXT(block, R64(RDREG), I0, SIZE_DWORD); // dsext <rdreg>,i0,dword
+ }
+ return TRUE;
+
+ case 0x04: /* SLLV - MIPS I */
+ if (RDREG != 0)
+ {
+ UML_SHL(block, I0, R32(RTREG), R32(RSREG)); // shl i0,<rtreg>,<rsreg>
+ UML_DSEXT(block, R64(RDREG), I0, SIZE_DWORD); // dsext <rdreg>,i0,dword
+ }
+ return TRUE;
+
+ case 0x06: /* SRLV - MIPS I */
+ if (RDREG != 0)
+ {
+ UML_SHR(block, I0, R32(RTREG), R32(RSREG)); // shr i0,<rtreg>,<rsreg>
+ UML_DSEXT(block, R64(RDREG), I0, SIZE_DWORD); // dsext <rdreg>,i0,dword
+ }
+ return TRUE;
+
+ case 0x07: /* SRAV - MIPS I */
+ if (RDREG != 0)
+ {
+ UML_SAR(block, I0, R32(RTREG), R32(RSREG)); // sar i0,<rtreg>,<rsreg>
+ UML_DSEXT(block, R64(RDREG), I0, SIZE_DWORD); // dsext <rdreg>,i0,dword
+ }
+ return TRUE;
+
+ case 0x38: /* DSLL - MIPS III */
+ if (RDREG != 0)
+ UML_DSHL(block, R64(RDREG), R64(RTREG), SHIFT); // dshl <rdreg>,<rtreg>,<shift>
+ return TRUE;
+
+ case 0x3a: /* DSRL - MIPS III */
+ if (RDREG != 0)
+ UML_DSHR(block, R64(RDREG), R64(RTREG), SHIFT); // dshr <rdreg>,<rtreg>,<shift>
+ return TRUE;
+
+ case 0x3b: /* DSRA - MIPS III */
+ if (RDREG != 0)
+ UML_DSAR(block, R64(RDREG), R64(RTREG), SHIFT); // dsar <rdreg>,<rtreg>,<shift>
+ return TRUE;
+
+ case 0x3c: /* DSLL32 - MIPS III */
+ if (RDREG != 0)
+ UML_DSHL(block, R64(RDREG), R64(RTREG), SHIFT + 32); // dshl <rdreg>,<rtreg>,<shift>+32
+ return TRUE;
+
+ case 0x3e: /* DSRL32 - MIPS III */
+ if (RDREG != 0)
+ UML_DSHR(block, R64(RDREG), R64(RTREG), SHIFT + 32); // dshr <rdreg>,<rtreg>,<shift>+32
+ return TRUE;
+
+ case 0x3f: /* DSRA32 - MIPS III */
+ if (RDREG != 0)
+ UML_DSAR(block, R64(RDREG), R64(RTREG), SHIFT + 32); // dsar <rdreg>,<rtreg>,<shift>+32
+ return TRUE;
+
+ case 0x14: /* DSLLV - MIPS III */
+ if (RDREG != 0)
+ UML_DSHL(block, R64(RDREG), R64(RTREG), R64(RSREG)); // dshl <rdreg>,<rtreg>,<rsreg>
+ return TRUE;
+
+ case 0x16: /* DSRLV - MIPS III */
+ if (RDREG != 0)
+ UML_DSHR(block, R64(RDREG), R64(RTREG), R64(RSREG)); // dshr <rdreg>,<rtreg>,<rsreg>
+ return TRUE;
+
+ case 0x17: /* DSRAV - MIPS III */
+ if (RDREG != 0)
+ UML_DSAR(block, R64(RDREG), R64(RTREG), R64(RSREG)); // dsar <rdreg>,<rtreg>,<rsreg>
+ return TRUE;
+
+
+ /* ----- basic arithmetic ----- */
+
+ case 0x20: /* ADD - MIPS I */
+ if (mips3->impstate->drcoptions & MIPS3DRC_CHECK_OVERFLOWS)
+ {
+ UML_ADD(block, I0, R32(RSREG), R32(RTREG)); // add i0,<rsreg>,<rtreg>
+ UML_EXHc(block, COND_V, *mips3->impstate->exception[EXCEPTION_OVERFLOW], 0);
+ // exh overflow,0,V
+ if (RDREG != 0)
+ UML_DSEXT(block, R64(RDREG), I0, SIZE_DWORD); // dsext <rdreg>,i0,dword
+ }
+ else if (RDREG != 0)
+ {
+ UML_ADD(block, I0, R32(RSREG), R32(RTREG)); // add i0,<rsreg>,<rtreg>
+ UML_DSEXT(block, R64(RDREG), I0, SIZE_DWORD); // dsext <rdreg>,i0,dword
+ }
+ return TRUE;
+
+ case 0x21: /* ADDU - MIPS I */
+ if (RDREG != 0)
+ {
+ UML_ADD(block, I0, R32(RSREG), R32(RTREG)); // add i0,<rsreg>,<rtreg>
+ UML_DSEXT(block, R64(RDREG), I0, SIZE_DWORD); // dsext <rdreg>,i0,dword
+ }
+ return TRUE;
+
+ case 0x2c: /* DADD - MIPS III */
+ if (mips3->impstate->drcoptions & MIPS3DRC_CHECK_OVERFLOWS)
+ {
+ UML_DADD(block, I0, R64(RSREG), R64(RTREG)); // dadd i0,<rsreg>,<rtreg>
+ UML_EXHc(block, COND_V, *mips3->impstate->exception[EXCEPTION_OVERFLOW], 0);
+ // exh overflow,0,V
+ if (RDREG != 0)
+ UML_DMOV(block, R64(RDREG), I0); // dmov <rdreg>,i0
+ }
+ else if (RDREG != 0)
+ UML_DADD(block, R64(RDREG), R64(RSREG), R64(RTREG)); // dadd <rdreg>,<rsreg>,<rtreg>
+ return TRUE;
+
+ case 0x2d: /* DADDU - MIPS III */
+ if (RDREG != 0)
+ UML_DADD(block, R64(RDREG), R64(RSREG), R64(RTREG)); // dadd <rdreg>,<rsreg>,<rtreg>
+ return TRUE;
+
+ case 0x22: /* SUB - MIPS I */
+ if (mips3->impstate->drcoptions & MIPS3DRC_CHECK_OVERFLOWS)
+ {
+ UML_SUB(block, I0, R32(RSREG), R32(RTREG)); // sub i0,<rsreg>,<rtreg>
+ UML_EXHc(block, COND_V, *mips3->impstate->exception[EXCEPTION_OVERFLOW], 0);
+ // exh overflow,0,V
+ if (RDREG != 0)
+ UML_DSEXT(block, R64(RDREG), I0, SIZE_DWORD); // dsext <rdreg>,i0,dword
+ }
+ else if (RDREG != 0)
+ {
+ UML_SUB(block, I0, R32(RSREG), R32(RTREG)); // sub i0,<rsreg>,<rtreg>
+ UML_DSEXT(block, R64(RDREG), I0, SIZE_DWORD); // dsext <rdreg>,i0,dword
+ }
+ return TRUE;
+
+ case 0x23: /* SUBU - MIPS I */
+ if (RDREG != 0)
+ {
+ UML_SUB(block, I0, R32(RSREG), R32(RTREG)); // sub i0,<rsreg>,<rtreg>
+ UML_DSEXT(block, R64(RDREG), I0, SIZE_DWORD); // dsext <rdreg>,i0,dword
+ }
+ return TRUE;
+
+ case 0x2e: /* DSUB - MIPS III */
+ if (mips3->impstate->drcoptions & MIPS3DRC_CHECK_OVERFLOWS)
+ {
+ UML_DSUB(block, I0, R64(RSREG), R64(RTREG)); // dsub i0,<rsreg>,<rtreg>
+ UML_EXHc(block, COND_V, *mips3->impstate->exception[EXCEPTION_OVERFLOW], 0);
+ // exh overflow,0,V
+ if (RDREG != 0)
+ UML_DMOV(block, R64(RDREG), I0); // dmov <rdreg>,i0
+ }
+ else if (RDREG != 0)
+ UML_DSUB(block, R64(RDREG), R64(RSREG), R64(RTREG)); // dsub <rdreg>,<rsreg>,<rtreg>
+ return TRUE;
+
+ case 0x2f: /* DSUBU - MIPS III */
+ if (RDREG != 0)
+ UML_DSUB(block, R64(RDREG), R64(RSREG), R64(RTREG)); // dsub <rdreg>,<rsreg>,<rtreg>
+ return TRUE;
+
+ case 0x18: /* MULT - MIPS I */
+ UML_MULS(block, I0, I1, R32(RSREG), R32(RTREG)); // muls i0,i1,<rsreg>,<rtreg>
+ UML_DSEXT(block, LO64, I0, SIZE_DWORD); // dsext lo,i0,dword
+ UML_DSEXT(block, HI64, I1, SIZE_DWORD); // dsext hi,i1,dword
+ return TRUE;
+
+ case 0x19: /* MULTU - MIPS I */
+ UML_MULU(block, I0, I1, R32(RSREG), R32(RTREG)); // mulu i0,i1,<rsreg>,<rtreg>
+ UML_DSEXT(block, LO64, I0, SIZE_DWORD); // dsext lo,i0,dword
+ UML_DSEXT(block, HI64, I1, SIZE_DWORD); // dsext hi,i1,dword
+ return TRUE;
+
+ case 0x1c: /* DMULT - MIPS III */
+ UML_DMULS(block, LO64, HI64, R64(RSREG), R64(RTREG)); // dmuls lo,hi,<rsreg>,<rtreg>
+ return TRUE;
+
+ case 0x1d: /* DMULTU - MIPS III */
+ UML_DMULU(block, LO64, HI64, R64(RSREG), R64(RTREG)); // dmulu lo,hi,<rsreg>,<rtreg>
+ return TRUE;
+
+ case 0x1a: /* DIV - MIPS I */
+ UML_DIVS(block, I0, I1, R32(RSREG), R32(RTREG)); // divs i0,i1,<rsreg>,<rtreg>
+ UML_DSEXT(block, LO64, I0, SIZE_DWORD); // dsext lo,i0,dword
+ UML_DSEXT(block, HI64, I1, SIZE_DWORD); // dsext hi,i1,dword
+ return TRUE;
+
+ case 0x1b: /* DIVU - MIPS I */
+ UML_DIVU(block, I0, I1, R32(RSREG), R32(RTREG)); // divu i0,i1,<rsreg>,<rtreg>
+ UML_DSEXT(block, LO64, I0, SIZE_DWORD); // dsext lo,i0,dword
+ UML_DSEXT(block, HI64, I1, SIZE_DWORD); // dsext hi,i1,dword
+ return TRUE;
+
+ case 0x1e: /* DDIV - MIPS III */
+ UML_DDIVS(block, LO64, HI64, R64(RSREG), R64(RTREG)); // ddivs lo,hi,<rsreg>,<rtreg>
+ return TRUE;
+
+ case 0x1f: /* DDIVU - MIPS III */
+ UML_DDIVU(block, LO64, HI64, R64(RSREG), R64(RTREG)); // ddivu lo,hi,<rsreg>,<rtreg>
+ return TRUE;
+
+
+ /* ----- basic logical ops ----- */
+
+ case 0x24: /* AND - MIPS I */
+ if (RDREG != 0)
+ UML_DAND(block, R64(RDREG), R64(RSREG), R64(RTREG)); // dand <rdreg>,<rsreg>,<rtreg>
+ return TRUE;
+
+ case 0x25: /* OR - MIPS I */
+ if (RDREG != 0)
+ UML_DOR(block, R64(RDREG), R64(RSREG), R64(RTREG)); // dor <rdreg>,<rsreg>,<rtreg>
+ return TRUE;
+
+ case 0x26: /* XOR - MIPS I */
+ if (RDREG != 0)
+ UML_DXOR(block, R64(RDREG), R64(RSREG), R64(RTREG)); // dxor <rdreg>,<rsreg>,<rtreg>
+ return TRUE;
+
+ case 0x27: /* NOR - MIPS I */
+ if (RDREG != 0)
+ {
+ UML_DOR(block, I0, R64(RSREG), R64(RTREG)); // dor i0,<rsreg>,<rtreg>
+ UML_DXOR(block, R64(RDREG), I0, (UINT64)~0); // dxor <rdreg>,i0,~0
+ }
+ return TRUE;
+
+
+ /* ----- basic comparisons ----- */
+
+ case 0x2a: /* SLT - MIPS I */
+ if (RDREG != 0)
+ {
+ UML_DCMP(block, R64(RSREG), R64(RTREG)); // dcmp <rsreg>,<rtreg>
+ UML_DSETc(block, COND_L, R64(RDREG)); // dset <rdreg>,l
+ }
+ return TRUE;
+
+ case 0x2b: /* SLTU - MIPS I */
+ if (RDREG != 0)
+ {
+ UML_DCMP(block, R64(RSREG), R64(RTREG)); // dcmp <rsreg>,<rtreg>
+ UML_DSETc(block, COND_B, R64(RDREG)); // dset <rdreg>,b
+ }
+ return TRUE;
+
+
+ /* ----- conditional traps ----- */
+
+ case 0x30: /* TGE - MIPS II */
+ UML_DCMP(block, R64(RSREG), R64(RTREG)); // dcmp <rsreg>,<rtreg>
+ UML_EXHc(block, COND_GE, *mips3->impstate->exception[EXCEPTION_TRAP], 0);// exh trap,0,GE
+ return TRUE;
+
+ case 0x31: /* TGEU - MIPS II */
+ UML_DCMP(block, R64(RSREG), R64(RTREG)); // dcmp <rsreg>,<rtreg>
+ UML_EXHc(block, COND_AE, *mips3->impstate->exception[EXCEPTION_TRAP], 0);// exh trap,0,AE
+ return TRUE;
+
+ case 0x32: /* TLT - MIPS II */
+ UML_DCMP(block, R64(RSREG), R64(RTREG)); // dcmp <rsreg>,<rtreg>
+ UML_EXHc(block, COND_L, *mips3->impstate->exception[EXCEPTION_TRAP], 0);// exh trap,0,LT
+ return TRUE;
+
+ case 0x33: /* TLTU - MIPS II */
+ UML_DCMP(block, R64(RSREG), R64(RTREG)); // dcmp <rsreg>,<rtreg>
+ UML_EXHc(block, COND_B, *mips3->impstate->exception[EXCEPTION_TRAP], 0);// exh trap,0,B
+ return TRUE;
+
+ case 0x34: /* TEQ - MIPS II */
+ UML_DCMP(block, R64(RSREG), R64(RTREG)); // dcmp <rsreg>,<rtreg>
+ UML_EXHc(block, COND_E, *mips3->impstate->exception[EXCEPTION_TRAP], 0);// exh trap,0,E
+ return TRUE;
+
+ case 0x36: /* TNE - MIPS II */
+ UML_DCMP(block, R64(RSREG), R64(RTREG)); // dcmp <rsreg>,<rtreg>
+ UML_EXHc(block, COND_NE, *mips3->impstate->exception[EXCEPTION_TRAP], 0);// exh trap,0,NE
+ return TRUE;
+
+
+ /* ----- conditional moves ----- */
+
+ case 0x0a: /* MOVZ - MIPS IV */
+ if (RDREG != 0)
+ {
+ UML_DCMP(block, R64(RTREG), 0); // dcmp <rtreg>,0
+ UML_DMOVc(block, COND_Z, R64(RDREG), R64(RSREG)); // dmov <rdreg>,<rsreg>,Z
+ }
+ return TRUE;
+
+ case 0x0b: /* MOVN - MIPS IV */
+ if (RDREG != 0)
+ {
+ UML_DCMP(block, R64(RTREG), 0); // dcmp <rtreg>,0
+ UML_DMOVc(block, COND_NZ, R64(RDREG), R64(RSREG)); // dmov <rdreg>,<rsreg>,NZ
+ }
+ return TRUE;
+
+ case 0x01: /* MOVF/MOVT - MIPS IV */
+ if (RDREG != 0)
+ {
+ UML_TEST(block, CCR132(31), FCCMASK(op >> 18)); // test ccr31,fcc_mask[x]
+ UML_DMOVc(block, ((op >> 16) & 1) ? COND_NZ : COND_Z, R64(RDREG), R64(RSREG));
+ // dmov <rdreg>,<rsreg>,NZ/Z
+ }
+ return TRUE;
+
+
+ /* ----- jumps and branches ----- */
+
+ case 0x08: /* JR - MIPS I */
+ generate_delay_slot_and_branch(mips3, block, compiler, desc, 0); // <next instruction + hashjmp>
+ return TRUE;
+
+ case 0x09: /* JALR - MIPS I */
+ generate_delay_slot_and_branch(mips3, block, compiler, desc, RDREG); // <next instruction + hashjmp>
+ return TRUE;
+
+
+ /* ----- system calls ----- */
+
+ case 0x0c: /* SYSCALL - MIPS I */
+ UML_EXH(block, *mips3->impstate->exception[EXCEPTION_SYSCALL], 0); // exh syscall,0
+ return TRUE;
+
+ case 0x0d: /* BREAK - MIPS I */
+ UML_EXH(block, *mips3->impstate->exception[EXCEPTION_BREAK], 0); // exh break,0
+ return TRUE;
+
+
+ /* ----- effective no-ops ----- */
+
+ case 0x0f: /* SYNC - MIPS II */
+ return TRUE;
+
+
+ /* ----- hi/lo register access ----- */
+
+ case 0x10: /* MFHI - MIPS I */
+ if (RDREG != 0)
+ UML_DMOV(block, R64(RDREG), HI64); // dmov <rdreg>,hi
+ return TRUE;
+
+ case 0x11: /* MTHI - MIPS I */
+ UML_DMOV(block, HI64, R64(RSREG)); // dmov hi,<rsreg>
+ return TRUE;
+
+ case 0x12: /* MFLO - MIPS I */
+ if (RDREG != 0)
+ UML_DMOV(block, R64(RDREG), LO64); // dmov <rdreg>,lo
+ return TRUE;
+
+ case 0x13: /* MTLO - MIPS I */
+ UML_DMOV(block, LO64, R64(RSREG)); // dmov lo,<rsreg>
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+/*-------------------------------------------------
+ generate_regimm - compile opcodes in the
+ 'REGIMM' group
+-------------------------------------------------*/
+
+static int generate_regimm(mips3_state *mips3, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
+{
+ UINT32 op = desc->opptr.l[0];
+ UINT8 opswitch = RTREG;
+ code_label skip;
+
+ switch (opswitch)
+ {
+ case 0x00: /* BLTZ */
+ case 0x02: /* BLTZL */
+ case 0x10: /* BLTZAL */
+ case 0x12: /* BLTZALL */
+ if (RSREG != 0)
+ {
+ UML_DCMP(block, R64(RSREG), 0); // dcmp <rsreg>,0
+ UML_JMPc(block, COND_GE, skip = compiler->labelnum++); // jmp skip,GE
+ generate_delay_slot_and_branch(mips3, block, compiler, desc, (opswitch & 0x10) ? 31 : 0);
+ // <next instruction + hashjmp>
+ UML_LABEL(block, skip); // skip:
+ }
+ return TRUE;
+
+ case 0x01: /* BGEZ */
+ case 0x03: /* BGEZL */
+ case 0x11: /* BGEZAL */
+ case 0x13: /* BGEZALL */
+ if (RSREG != 0)
+ {
+ UML_DCMP(block, R64(RSREG), 0); // dcmp <rsreg>,0
+ UML_JMPc(block, COND_L, skip = compiler->labelnum++); // jmp skip,L
+ generate_delay_slot_and_branch(mips3, block, compiler, desc, (opswitch & 0x10) ? 31 : 0);
+ // <next instruction + hashjmp>
+ UML_LABEL(block, skip); // skip:
+ }
+ else
+ generate_delay_slot_and_branch(mips3, block, compiler, desc, (opswitch & 0x10) ? 31 : 0);
+ // <next instruction + hashjmp>
+ return TRUE;
+
+ case 0x08: /* TGEI */
+ UML_DCMP(block, R64(RSREG), SIMMVAL); // dcmp <rsreg>,SIMMVAL
+ UML_EXHc(block, COND_GE, *mips3->impstate->exception[EXCEPTION_TRAP], 0);// exh trap,0,GE
+ return TRUE;
+
+ case 0x09: /* TGEIU */
+ UML_DCMP(block, R64(RSREG), SIMMVAL); // dcmp <rsreg>,SIMMVAL
+ UML_EXHc(block, COND_AE, *mips3->impstate->exception[EXCEPTION_TRAP], 0);// exh trap,0,AE
+ return TRUE;
+
+ case 0x0a: /* TLTI */
+ UML_DCMP(block, R64(RSREG), SIMMVAL); // dcmp <rsreg>,SIMMVAL
+ UML_EXHc(block, COND_L, *mips3->impstate->exception[EXCEPTION_TRAP], 0);// exh trap,0,L
+ return TRUE;
+
+ case 0x0b: /* TLTIU */
+ UML_DCMP(block, R64(RSREG), SIMMVAL); // dcmp <rsreg>,SIMMVAL
+ UML_EXHc(block, COND_B, *mips3->impstate->exception[EXCEPTION_TRAP], 0);// exh trap,0,B
+ return TRUE;
+
+ case 0x0c: /* TEQI */
+ UML_DCMP(block, R64(RSREG), SIMMVAL); // dcmp <rsreg>,SIMMVAL
+ UML_EXHc(block, COND_E, *mips3->impstate->exception[EXCEPTION_TRAP], 0);// exh trap,0,E
+ return TRUE;
+
+ case 0x0e: /* TNEI */
+ UML_DCMP(block, R64(RSREG), SIMMVAL); // dcmp <rsreg>,SIMMVAL
+ UML_EXHc(block, COND_NE, *mips3->impstate->exception[EXCEPTION_TRAP], 0);// exh trap,0,NE
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+/*-------------------------------------------------
+ generate_idt - compile opcodes in the IDT-
+ specific group
+-------------------------------------------------*/
+
+static int generate_idt(mips3_state *mips3, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
+{
+ UINT32 op = desc->opptr.l[0];
+ UINT8 opswitch = op & 0x1f;
+
+ /* only enabled on IDT processors */
+ if (mips3->flavor != MIPS3_TYPE_R4650)
+ return FALSE;
+
+ switch (opswitch)
+ {
+ case 0: /* MAD */
+ if (RSREG != 0 && RTREG != 0)
+ {
+ UML_MULS(block, I0, I1, R32(RSREG), R32(RTREG)); // muls i0,i1,rsreg,rtreg
+ UML_ADD(block, I0, I0, LO32); // add i0,i0,lo
+ UML_ADDC(block, I1, I1, HI32); // addc i1,i1,hi
+ UML_DSEXT(block, LO64, I0, SIZE_DWORD); // dsext lo,i0,dword
+ UML_DSEXT(block, HI64, I1, SIZE_DWORD); // dsext hi,i1,dword
+ }
+ return TRUE;
+
+ case 1: /* MADU */
+ if (RSREG != 0 && RTREG != 0)
+ {
+ UML_MULU(block, I0, I1, R32(RSREG), R32(RTREG)); // mulu i0,i1,rsreg,rtreg
+ UML_ADD(block, I0, I0, LO32); // add i0,i0,lo
+ UML_ADDC(block, I1, I1, HI32); // addc i1,i1,hi
+ UML_DSEXT(block, LO64, I0, SIZE_DWORD); // dsext lo,i0,dword
+ UML_DSEXT(block, HI64, I1, SIZE_DWORD); // dsext hi,i1,dword
+ }
+ return TRUE;
+
+ case 2: /* MUL */
+ if (RDREG != 0)
+ {
+ UML_MULS(block, I0, I0, R32(RSREG), R32(RTREG)); // muls i0,i0,rsreg,rtreg
+ UML_DSEXT(block, R64(RDREG), I0, SIZE_DWORD); // dsext rdreg,i0,dword
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+/*-------------------------------------------------
+ generate_set_cop0_reg - generate code to
+ handle special COP0 registers
+-------------------------------------------------*/
+
+static int generate_set_cop0_reg(mips3_state *mips3, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT8 reg)
+{
+ int in_delay_slot = ((desc->flags & OPFLAG_IN_DELAY_SLOT) != 0);
+ code_label link;
+
+ switch (reg)
+ {
+ case COP0_Cause:
+ UML_ROLINS(block, CPR032(COP0_Cause), I0, 0, ~0xfc00); // rolins [Cause],i0,0,~0xfc00
+ compiler->checksoftints = TRUE;
+ if (!in_delay_slot)
+ generate_update_cycles(mips3, block, compiler, desc->pc + 4, TRUE);
+ return TRUE;
+
+ case COP0_Status:
+ generate_update_cycles(mips3, block, compiler, desc->pc, !in_delay_slot); // <subtract cycles>
+ UML_MOV(block, I1, CPR032(COP0_Status)); // mov i1,[Status]
+ UML_MOV(block, CPR032(COP0_Status), I0); // mov [Status],i0
+ generate_update_mode(mips3, block); // <update mode>
+ UML_XOR(block, I0, I0, I1); // xor i0,i0,i1
+ UML_TEST(block, I0, 0x8000); // test i0,0x8000
+ UML_CALLCc(block, COND_NZ, (c_function)mips3com_update_cycle_counting, mips3); // callc mips3com_update_cycle_counting,mips.core,NZ
+ compiler->checkints = TRUE;
+ if (!in_delay_slot)
+ generate_update_cycles(mips3, block, compiler, desc->pc + 4, TRUE);
+ return TRUE;
+
+ case COP0_Count:
+ generate_update_cycles(mips3, block, compiler, desc->pc, !in_delay_slot); // <subtract cycles>
+ UML_MOV(block, CPR032(COP0_Count), I0); // mov [Count],i0
+ UML_CALLC(block, cfunc_get_cycles, mips3); // callc cfunc_get_cycles,mips3
+ UML_DAND(block, I0, I0, 0xffffffff); // and i0,i0,0xffffffff
+ UML_DADD(block, I0, I0, I0); // dadd i0,i0,i0
+ UML_DSUB(block, mem(&mips3->count_zero_time), mem(&mips3->impstate->numcycles), I0);
+ // dsub [count_zero_time],[mips3->impstate->numcycles],i0
+ UML_CALLC(block, (c_function)mips3com_update_cycle_counting, mips3); // callc mips3com_update_cycle_counting,mips.core
+ return TRUE;
+
+ case COP0_Compare:
+ UML_MOV(block, mem(&mips3->compare_armed), 1); // mov [compare_armed],1
+ generate_update_cycles(mips3, block, compiler, desc->pc, !in_delay_slot); // <subtract cycles>
+ UML_MOV(block, CPR032(COP0_Compare), I0); // mov [Compare],i0
+ UML_AND(block, CPR032(COP0_Cause), CPR032(COP0_Cause), ~0x8000); // and [Cause],[Cause],~0x8000
+ UML_CALLC(block, (c_function)mips3com_update_cycle_counting, mips3); // callc mips3com_update_cycle_counting,mips.core
+ return TRUE;
+
+ case COP0_PRId:
+ return TRUE;
+
+ case COP0_Config:
+ UML_ROLINS(block, CPR032(COP0_Config), I0, 0, 0x0007); // rolins [Config],i0,0,0x0007
+ return TRUE;
+
+ case COP0_EntryHi:
+ UML_XOR(block, I1, I0, CPR032(reg)); // xor i1,i0,cpr0[reg]
+ UML_MOV(block, CPR032(reg), I0); // mov cpr0[reg],i0
+ UML_TEST(block, I1, 0xff); // test i1,0xff
+ UML_JMPc(block, COND_Z, link = compiler->labelnum++); // jmp link,z
+ UML_CALLC(block, (c_function)mips3com_asid_changed, mips3); // callc mips3com_asid_changed
+ UML_LABEL(block, link); // link:
+ return TRUE;
+
+ default:
+ UML_MOV(block, CPR032(reg), I0); // mov cpr0[reg],i0
+ return TRUE;
+ }
+}
+
+
+/*-------------------------------------------------
+ generate_get_cop0_reg - generate code to
+ read special COP0 registers
+-------------------------------------------------*/
+
+static int generate_get_cop0_reg(mips3_state *mips3, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT8 reg)
+{
+ code_label link1, link2;
+
+ switch (reg)
+ {
+ case COP0_Count:
+ generate_update_cycles(mips3, block, compiler, desc->pc, FALSE); // <subtract cycles>
+ UML_CALLC(block, cfunc_get_cycles, mips3); // callc cfunc_get_cycles,mips3
+ UML_DSUB(block, I0, mem(&mips3->impstate->numcycles), mem(&mips3->count_zero_time));
+ // dsub i0,[numcycles],[count_zero_time]
+ UML_DSHR(block, I0, I0, 1); // dshr i0,i0,1
+ UML_DSEXT(block, I0, I0, SIZE_DWORD); // dsext i0,i0,dword
+ return TRUE;
+
+ case COP0_Random:
+ generate_update_cycles(mips3, block, compiler, desc->pc, FALSE); // <subtract cycles>
+ UML_CALLC(block, cfunc_get_cycles, mips3); // callc cfunc_get_cycles,mips3
+ UML_DSUB(block, I0, mem(&mips3->impstate->numcycles), mem(&mips3->count_zero_time));
+ // dsub i0,[numcycles],[count_zero_time]
+ UML_AND(block, I1, CPR032(COP0_Wired), 0x3f); // and i1,[Wired],0x3f
+ UML_SUB(block, I2, 48, I1); // sub i2,48,i1
+ UML_JMPc(block, COND_BE, link1 = compiler->labelnum++); // jmp link1,BE
+ UML_DAND(block, I2, I2, 0xffffffff); // dand i2,i2,0xffffffff
+ UML_DDIVU(block, I0, I2, I0, I2); // ddivu i0,i2,i0,i2
+ UML_ADD(block, I0, I2, I1); // add i0,i2,i1
+ UML_DAND(block, I0, I0, 0x3f); // dand i0,i0,0x3f
+ UML_JMP(block, link2 = compiler->labelnum++); // jmp link2
+ UML_LABEL(block, link1); // link1:
+ UML_DMOV(block, I0, 47); // dmov i0,47
+ UML_LABEL(block, link2); // link2:
+ return TRUE;
+
+ default:
+ UML_DSEXT(block, I0, CPR032(reg), SIZE_DWORD); // dsext i0,cpr0[reg],dword
+ return TRUE;
+ }
+}
+
+
+/*-------------------------------------------------
+ generate_cop0 - compile COP0 opcodes
+-------------------------------------------------*/
+
+static int generate_cop0(mips3_state *mips3, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
+{
+ UINT32 op = desc->opptr.l[0];
+ UINT8 opswitch = RSREG;
+ int skip;
+
+ /* generate an exception if COP0 is disabled unless we are in kernel mode */
+ if ((mips3->impstate->mode >> 1) != MODE_KERNEL)
+ {
+ UML_TEST(block, CPR032(COP0_Status), SR_COP0); // test [Status],SR_COP0
+ UML_EXHc(block, COND_Z, *mips3->impstate->exception[EXCEPTION_BADCOP], 0);// exh cop,0,Z
+ }
+
+ switch (opswitch)
+ {
+ case 0x00: /* MFCz */
+ if (RTREG != 0)
+ {
+ generate_get_cop0_reg(mips3, block, compiler, desc, RDREG); // <get cop0 reg>
+ UML_DSEXT(block, R64(RTREG), I0, SIZE_DWORD); // dsext <rtreg>,i0,dword
+ }
+ return TRUE;
+
+ case 0x01: /* DMFCz */
+ if (RTREG != 0)
+ {
+ generate_get_cop0_reg(mips3, block, compiler, desc, RDREG); // <get cop0 reg>
+ UML_DMOV(block, R64(RTREG), I0); // dmov <rtreg>,i0
+ }
+ return TRUE;
+
+ case 0x02: /* CFCz */
+ if (RTREG != 0)
+ UML_DSEXT(block, R64(RTREG), CCR032(RDREG), SIZE_DWORD); // dsext <rtreg>,ccr0[rdreg],dword
+ return TRUE;
+
+ case 0x04: /* MTCz */
+ UML_DSEXT(block, I0, R32(RTREG), SIZE_DWORD); // dsext i0,<rtreg>,dword
+ generate_set_cop0_reg(mips3, block, compiler, desc, RDREG); // <set cop0 reg>
+ return TRUE;
+
+ case 0x05: /* DMTCz */
+ UML_DMOV(block, I0, R64(RTREG)); // dmov i0,<rtreg>
+ generate_set_cop0_reg(mips3, block, compiler, desc, RDREG); // <set cop0 reg>
+ return TRUE;
+
+ case 0x06: /* CTCz */
+ UML_DSEXT(block, CCR064(RDREG), R32(RTREG), SIZE_DWORD); // dsext ccr0[rdreg],<rtreg>,dword
+ return TRUE;
+
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ case 0x13:
+ case 0x14:
+ case 0x15:
+ case 0x16:
+ case 0x17:
+ case 0x18:
+ case 0x19:
+ case 0x1a:
+ case 0x1b:
+ case 0x1c:
+ case 0x1d:
+ case 0x1e:
+ case 0x1f: /* COP */
+ switch (op & 0x01ffffff)
+ {
+ case 0x01: /* TLBR */
+ UML_CALLC(block, (c_function)mips3com_tlbr, mips3); // callc mips3com_tlbr,mips3
+ return TRUE;
+
+ case 0x02: /* TLBWI */
+ UML_CALLC(block, (c_function)mips3com_tlbwi, mips3); // callc mips3com_tlbwi,mips3
+ return TRUE;
+
+ case 0x06: /* TLBWR */
+ UML_CALLC(block, (c_function)mips3com_tlbwr, mips3); // callc mips3com_tlbwr,mips3
+ return TRUE;
+
+ case 0x08: /* TLBP */
+ UML_CALLC(block, (c_function)mips3com_tlbp, mips3); // callc mips3com_tlbp,mips3
+ return TRUE;
+
+ case 0x18: /* ERET */
+ UML_MOV(block, mem(&mips3->llbit), 0); // mov [llbit],0
+ UML_MOV(block, I0, CPR032(COP0_Status)); // mov i0,[Status]
+ UML_TEST(block, I0, SR_ERL); // test i0,SR_ERL
+ UML_JMPc(block, COND_NZ, skip = compiler->labelnum++); // jmp skip,nz
+ UML_AND(block, I0, I0, ~SR_EXL); // and i0,i0,~SR_EXL
+ UML_MOV(block, CPR032(COP0_Status), I0); // mov [Status],i0
+ generate_update_mode(mips3, block);
+ compiler->checkints = TRUE;
+ generate_update_cycles(mips3, block, compiler, CPR032(COP0_EPC), TRUE);// <subtract cycles>
+ UML_HASHJMP(block, mem(&mips3->impstate->mode), CPR032(COP0_EPC), *mips3->impstate->nocode);
+ // hashjmp <mode>,[EPC],nocode
+ UML_LABEL(block, skip); // skip:
+ UML_AND(block, I0, I0, ~SR_ERL); // and i0,i0,~SR_ERL
+ UML_MOV(block, CPR032(COP0_Status), I0); // mov [Status],i0
+ generate_update_mode(mips3, block);
+ compiler->checkints = TRUE;
+ generate_update_cycles(mips3, block, compiler, CPR032(COP0_ErrorPC), TRUE);
+ // <subtract cycles>
+ UML_HASHJMP(block, mem(&mips3->impstate->mode), CPR032(COP0_ErrorPC), *mips3->impstate->nocode);
+ // hashjmp <mode>,[EPC],nocode
+ return TRUE;
+
+ case 0x20: /* WAIT */
+ return TRUE;
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+
+
+/***************************************************************************
+ COP1 RECOMPILATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ generate_cop1 - compile COP1 opcodes
+-------------------------------------------------*/
+
+static int generate_cop1(mips3_state *mips3, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
+{
+ UINT32 op = desc->opptr.l[0];
+ code_label skip;
+ condition_t condition;
+
+ /* generate an exception if COP1 is disabled */
+ if (mips3->impstate->drcoptions & MIPS3DRC_STRICT_COP1)
+ {
+ UML_TEST(block, CPR032(COP0_Status), SR_COP1); // test [Status],SR_COP1
+ UML_EXHc(block, COND_Z, *mips3->impstate->exception[EXCEPTION_BADCOP], 1);// exh cop,1,Z
+ }
+
+ switch (RSREG)
+ {
+ case 0x00: /* MFCz - MIPS I */
+ if (RTREG != 0)
+ UML_DSEXT(block, R64(RTREG), FPR32(RDREG), SIZE_DWORD); // dsext <rtreg>,fpr[rdreg],dword
+ return TRUE;
+
+ case 0x01: /* DMFCz - MIPS III */
+ if (RTREG != 0)
+ UML_DMOV(block, R64(RTREG), FPR64(RDREG)); // dmov <rtreg>,fpr[rdreg]
+ return TRUE;
+
+ case 0x02: /* CFCz - MIPS I */
+ if (RTREG != 0)
+ UML_DSEXT(block, R64(RTREG), CCR132(RDREG), SIZE_DWORD); // dsext <rtreg>,ccr132[rdreg],dword
+ return TRUE;
+
+ case 0x04: /* MTCz - MIPS I */
+ UML_MOV(block, FPR32(RDREG), R32(RTREG)); // mov fpr[rdreg],<rtreg>
+ return TRUE;
+
+ case 0x05: /* DMTCz - MIPS III */
+ UML_DMOV(block, FPR64(RDREG), R64(RTREG)); // dmov fpr[rdreg],<rtreg>
+ return TRUE;
+
+ case 0x06: /* CTCz - MIPS I */
+ if (RDREG != 31)
+ UML_DSEXT(block, CCR164(RDREG), R32(RTREG), SIZE_DWORD); // dsext ccr1[rdreg],<rtreg>,dword
+ else
+ {
+ UML_XOR(block, I0, CCR132(31), R32(RTREG)); // xor i0,ccr1[31],<rtreg>
+ UML_DSEXT(block, CCR164(31), R32(RTREG), SIZE_DWORD); // dsext ccr1[31],<rtreg>,dword
+ UML_TEST(block, I0, 3); // test i0,3
+ UML_JMPc(block, COND_Z, skip = compiler->labelnum++); // jmp skip,Z
+ UML_AND(block, I0, CCR132(31), 3); // and i0,ccr1[31],3
+ UML_LOAD(block, I0, &mips3->impstate->fpmode[0], I0, SIZE_BYTE, SCALE_x1);// load i0,fpmode,i0,byte
+ UML_SETFMOD(block, I0); // setfmod i0
+ UML_LABEL(block, skip); // skip:
+ }
+ return TRUE;
+
+ case 0x08: /* BC */
+ switch ((op >> 16) & 3)
+ {
+ case 0x00: /* BCzF - MIPS I */
+ case 0x02: /* BCzFL - MIPS II */
+ UML_TEST(block, CCR132(31), FCCMASK(op >> 18)); // test ccr1[31],fccmask[which]
+ UML_JMPc(block, COND_NZ, skip = compiler->labelnum++); // jmp skip,NZ
+ generate_delay_slot_and_branch(mips3, block, compiler, desc, 0);// <next instruction + hashjmp>
+ UML_LABEL(block, skip); // skip:
+ return TRUE;
+
+ case 0x01: /* BCzT - MIPS I */
+ case 0x03: /* BCzTL - MIPS II */
+ UML_TEST(block, CCR132(31), FCCMASK(op >> 18)); // test ccr1[31],fccmask[which]
+ UML_JMPc(block, COND_Z, skip = compiler->labelnum++); // jmp skip,Z
+ generate_delay_slot_and_branch(mips3, block, compiler, desc, 0);// <next instruction + hashjmp>
+ UML_LABEL(block, skip); // skip:
+ return TRUE;
+ }
+ break;
+
+ default:
+ switch (op & 0x3f)
+ {
+ case 0x00:
+ if (IS_SINGLE(op)) /* ADD.S - MIPS I */
+ UML_FSADD(block, FPR32(FDREG), FPR32(FSREG), FPR32(FTREG)); // fsadd <fdreg>,<fsreg>,<ftreg>
+ else /* ADD.D - MIPS I */
+ UML_FDADD(block, FPR64(FDREG), FPR64(FSREG), FPR64(FTREG)); // fdadd <fdreg>,<fsreg>,<ftreg>
+ return TRUE;
+
+ case 0x01:
+ if (IS_SINGLE(op)) /* SUB.S - MIPS I */
+ UML_FSSUB(block, FPR32(FDREG), FPR32(FSREG), FPR32(FTREG)); // fssub <fdreg>,<fsreg>,<ftreg>
+ else /* SUB.D - MIPS I */
+ UML_FDSUB(block, FPR64(FDREG), FPR64(FSREG), FPR64(FTREG)); // fdsub <fdreg>,<fsreg>,<ftreg>
+ return TRUE;
+
+ case 0x02:
+ if (IS_SINGLE(op)) /* MUL.S - MIPS I */
+ UML_FSMUL(block, FPR32(FDREG), FPR32(FSREG), FPR32(FTREG)); // fsmul <fdreg>,<fsreg>,<ftreg>
+ else /* MUL.D - MIPS I */
+ UML_FDMUL(block, FPR64(FDREG), FPR64(FSREG), FPR64(FTREG)); // fdmul <fdreg>,<fsreg>,<ftreg>
+ return TRUE;
+
+ case 0x03:
+ if (IS_SINGLE(op)) /* DIV.S - MIPS I */
+ UML_FSDIV(block, FPR32(FDREG), FPR32(FSREG), FPR32(FTREG)); // fsdiv <fdreg>,<fsreg>,<ftreg>
+ else /* DIV.D - MIPS I */
+ UML_FDDIV(block, FPR64(FDREG), FPR64(FSREG), FPR64(FTREG)); // fddiv <fdreg>,<fsreg>,<ftreg>
+ return TRUE;
+
+ case 0x04:
+ if (IS_SINGLE(op)) /* SQRT.S - MIPS II */
+ UML_FSSQRT(block, FPR32(FDREG), FPR32(FSREG)); // fssqrt <fdreg>,<fsreg>
+ else /* SQRT.D - MIPS II */
+ UML_FDSQRT(block, FPR64(FDREG), FPR64(FSREG)); // fdsqrt <fdreg>,<fsreg>
+ return TRUE;
+
+ case 0x05:
+ if (IS_SINGLE(op)) /* ABS.S - MIPS I */
+ UML_FSABS(block, FPR32(FDREG), FPR32(FSREG)); // fsabs <fdreg>,<fsreg>
+ else /* ABS.D - MIPS I */
+ UML_FDABS(block, FPR64(FDREG), FPR64(FSREG)); // fdabs <fdreg>,<fsreg>
+ return TRUE;
+
+ case 0x06:
+ if (IS_SINGLE(op)) /* MOV.S - MIPS I */
+ UML_FSMOV(block, FPR32(FDREG), FPR32(FSREG)); // fsmov <fdreg>,<fsreg>
+ else /* MOV.D - MIPS I */
+ UML_FDMOV(block, FPR64(FDREG), FPR64(FSREG)); // fdmov <fdreg>,<fsreg>
+ return TRUE;
+
+ case 0x07:
+ if (IS_SINGLE(op)) /* NEG.S - MIPS I */
+ UML_FSNEG(block, FPR32(FDREG), FPR32(FSREG)); // fsneg <fdreg>,<fsreg>
+ else /* NEG.D - MIPS I */
+ UML_FDNEG(block, FPR64(FDREG), FPR64(FSREG)); // fdneg <fdreg>,<fsreg>
+ return TRUE;
+
+ case 0x08:
+ if (IS_SINGLE(op)) /* ROUND.L.S - MIPS III */
+ UML_FSTOINT(block, FPR64(FDREG), FPR32(FSREG), SIZE_QWORD, ROUND_ROUND);// fstoint <fdreg>,<fsreg>,qword,round
+ else /* ROUND.L.D - MIPS III */
+ UML_FDTOINT(block, FPR64(FDREG), FPR64(FSREG), SIZE_QWORD, ROUND_ROUND);// fdtoint <fdreg>,<fsreg>,qword,round
+ return TRUE;
+
+ case 0x09:
+ if (IS_SINGLE(op)) /* TRUNC.L.S - MIPS III */
+ UML_FSTOINT(block, FPR64(FDREG), FPR32(FSREG), SIZE_QWORD, ROUND_TRUNC);// fstoint <fdreg>,<fsreg>,qword,trunc
+ else /* TRUNC.L.D - MIPS III */
+ UML_FDTOINT(block, FPR64(FDREG), FPR64(FSREG), SIZE_QWORD, ROUND_TRUNC);// fdtoint <fdreg>,<fsreg>,qword,trunc
+ return TRUE;
+
+ case 0x0a:
+ if (IS_SINGLE(op)) /* CEIL.L.S - MIPS III */
+ UML_FSTOINT(block, FPR64(FDREG), FPR32(FSREG), SIZE_QWORD, ROUND_CEIL);// fstoint <fdreg>,<fsreg>,qword,ceil
+ else /* CEIL.L.D - MIPS III */
+ UML_FDTOINT(block, FPR64(FDREG), FPR64(FSREG), SIZE_QWORD, ROUND_CEIL);// fdtoint <fdreg>,<fsreg>,qword,ceil
+ return TRUE;
+
+ case 0x0b:
+ if (IS_SINGLE(op)) /* FLOOR.L.S - MIPS III */
+ UML_FSTOINT(block, FPR64(FDREG), FPR32(FSREG), SIZE_QWORD, ROUND_FLOOR);// fstoint <fdreg>,<fsreg>,qword,floor
+ else /* FLOOR.L.D - MIPS III */
+ UML_FDTOINT(block, FPR64(FDREG), FPR64(FSREG), SIZE_QWORD, ROUND_FLOOR);// fdtoint <fdreg>,<fsreg>,qword,floor
+ return TRUE;
+
+ case 0x0c:
+ if (IS_SINGLE(op)) /* ROUND.W.S - MIPS II */
+ UML_FSTOINT(block, FPR32(FDREG), FPR32(FSREG), SIZE_DWORD, ROUND_ROUND);// fstoint <fdreg>,<fsreg>,dword,round
+ else /* ROUND.W.D - MIPS II */
+ UML_FDTOINT(block, FPR32(FDREG), FPR64(FSREG), SIZE_DWORD, ROUND_ROUND);// fdtoint <fdreg>,<fsreg>,dword,round
+ return TRUE;
+
+ case 0x0d:
+ if (IS_SINGLE(op)) /* TRUNC.W.S - MIPS II */
+ UML_FSTOINT(block, FPR32(FDREG), FPR32(FSREG), SIZE_DWORD, ROUND_TRUNC);// fstoint <fdreg>,<fsreg>,dword,trunc
+ else /* TRUNC.W.D - MIPS II */
+ UML_FDTOINT(block, FPR32(FDREG), FPR64(FSREG), SIZE_DWORD, ROUND_TRUNC);// fdtoint <fdreg>,<fsreg>,dword,trunc
+ return TRUE;
+
+ case 0x0e:
+ if (IS_SINGLE(op)) /* CEIL.W.S - MIPS II */
+ UML_FSTOINT(block, FPR32(FDREG), FPR32(FSREG), SIZE_DWORD, ROUND_CEIL);// fstoint <fdreg>,<fsreg>,dword,ceil
+ else /* CEIL.W.D - MIPS II */
+ UML_FDTOINT(block, FPR32(FDREG), FPR64(FSREG), SIZE_DWORD, ROUND_CEIL);// fdtoint <fdreg>,<fsreg>,dword,ceil
+ return TRUE;
+
+ case 0x0f:
+ if (IS_SINGLE(op)) /* FLOOR.W.S - MIPS II */
+ UML_FSTOINT(block, FPR32(FDREG), FPR32(FSREG), SIZE_DWORD, ROUND_FLOOR);// fstoint <fdreg>,<fsreg>,dword,floor
+ else /* FLOOR.W.D - MIPS II */
+ UML_FDTOINT(block, FPR32(FDREG), FPR64(FSREG), SIZE_DWORD, ROUND_FLOOR);// fdtoint <fdreg>,<fsreg>,dword,floor
+ return TRUE;
+
+ case 0x11:
+ condition = ((op >> 16) & 1) ? COND_NZ : COND_Z;
+ UML_TEST(block, CCR132(31), FCCMASK(op >> 18)); // test ccr31,fccmask[op]
+ if (IS_SINGLE(op)) /* MOVT/F.S - MIPS IV */
+ UML_FSMOVc(block, condition, FPR32(FDREG), FPR32(FSREG)); // fsmov <fdreg>,<fsreg>,condition
+ else /* MOVT/F.D - MIPS IV */
+ UML_FDMOVc(block, condition, FPR64(FDREG), FPR64(FSREG)); // fdmov <fdreg>,<fsreg>,condition
+ return TRUE;
+
+ case 0x12:
+ UML_DCMP(block, R64(RTREG), 0); // dcmp <rtreg>,0
+ if (IS_SINGLE(op)) /* MOVZ.S - MIPS IV */
+ UML_FSMOVc(block, COND_Z, FPR32(FDREG), FPR32(FSREG)); // fsmov <fdreg>,<fsreg>,Z
+ else /* MOVZ.D - MIPS IV */
+ UML_FDMOVc(block, COND_Z, FPR64(FDREG), FPR64(FSREG)); // fdmov <fdreg>,<fsreg>,Z
+ return TRUE;
+
+ case 0x13:
+ UML_DCMP(block, R64(RTREG), 0); // dcmp <rtreg>,0
+ if (IS_SINGLE(op)) /* MOVN.S - MIPS IV */
+ UML_FSMOVc(block, COND_NZ, FPR32(FDREG), FPR32(FSREG)); // fsmov <fdreg>,<fsreg>,NZ
+ else /* MOVN.D - MIPS IV */
+ UML_FDMOVc(block, COND_NZ, FPR64(FDREG), FPR64(FSREG)); // fdmov <fdreg>,<fsreg>,NZ
+ return TRUE;
+
+ case 0x15:
+ if (IS_SINGLE(op)) /* RECIP.S - MIPS IV */
+ UML_FSRECIP(block, FPR32(FDREG), FPR32(FSREG)); // fsrecip <fdreg>,<fsreg>
+ else /* RECIP.D - MIPS IV */
+ UML_FDRECIP(block, FPR64(FDREG), FPR64(FSREG)); // fdrecip <fdreg>,<fsreg>
+ return TRUE;
+
+ case 0x16:
+ if (IS_SINGLE(op)) /* RSQRT.S - MIPS IV */
+ UML_FSRSQRT(block, FPR32(FDREG), FPR32(FSREG)); // fsrsqrt <fdreg>,<fsreg>
+ else /* RSQRT.D - MIPS IV */
+ UML_FDRSQRT(block, FPR64(FDREG), FPR64(FSREG)); // fdrsqrt <fdreg>,<fsreg>
+ return TRUE;
+
+ case 0x20:
+ if (IS_INTEGRAL(op))
+ {
+ if (IS_SINGLE(op)) /* CVT.S.W - MIPS I */
+ UML_FSFRINT(block, FPR32(FDREG), FPR32(FSREG), SIZE_DWORD); // fsfrint <fdreg>,<fsreg>,dword
+ else /* CVT.S.L - MIPS I */
+ UML_FSFRINT(block, FPR32(FDREG), FPR64(FSREG), SIZE_QWORD); // fsfrint <fdreg>,<fsreg>,qword
+ }
+ else /* CVT.S.D - MIPS I */
+ UML_FSFRFLT(block, FPR32(FDREG), FPR64(FSREG), SIZE_QWORD); // fsfrflt <fdreg>,<fsreg>,qword
+ return TRUE;
+
+ case 0x21:
+ if (IS_INTEGRAL(op))
+ {
+ if (IS_SINGLE(op)) /* CVT.D.W - MIPS I */
+ UML_FDFRINT(block, FPR64(FDREG), FPR32(FSREG), SIZE_DWORD); // fdfrint <fdreg>,<fsreg>,dword
+ else /* CVT.D.L - MIPS I */
+ UML_FDFRINT(block, FPR64(FDREG), FPR64(FSREG), SIZE_QWORD); // fdfrint <fdreg>,<fsreg>,qword
+ }
+ else /* CVT.D.S - MIPS I */
+ UML_FDFRFLT(block, FPR64(FDREG), FPR32(FSREG), SIZE_DWORD); // fdfrflt <fdreg>,<fsreg>,dword
+ return TRUE;
+
+ case 0x24:
+ if (IS_SINGLE(op)) /* CVT.W.S - MIPS I */
+ UML_FSTOINT(block, FPR32(FDREG), FPR32(FSREG), SIZE_DWORD, ROUND_DEFAULT);// fstoint <fdreg>,<fsreg>,dword,default
+ else /* CVT.W.D - MIPS I */
+ UML_FDTOINT(block, FPR32(FDREG), FPR64(FSREG), SIZE_DWORD, ROUND_DEFAULT);// fdtoint <fdreg>,<fsreg>,dword,default
+ return TRUE;
+
+ case 0x25:
+ if (IS_SINGLE(op)) /* CVT.L.S - MIPS I */
+ UML_FSTOINT(block, FPR64(FDREG), FPR32(FSREG), SIZE_QWORD, ROUND_DEFAULT);// fstoint <fdreg>,<fsreg>,qword,default
+ else /* CVT.L.D - MIPS I */
+ UML_FDTOINT(block, FPR64(FDREG), FPR64(FSREG), SIZE_QWORD, ROUND_DEFAULT);// fdtoint <fdreg>,<fsreg>,qword,default
+ return TRUE;
+
+ case 0x30:
+ case 0x38: /* C.F.S/D - MIPS I */
+ UML_AND(block, CCR132(31), CCR132(31), ~FCCMASK(op >> 8)); // and ccr31,ccr31,~fccmask[op]
+ return TRUE;
+
+ case 0x31:
+ case 0x39:
+ if (IS_SINGLE(op)) /* C.UN.S - MIPS I */
+ UML_FSCMP(block, FPR32(FSREG), FPR32(FTREG)); // fscmp <fsreg>,<ftreg>
+ else /* C.UN.D - MIPS I */
+ UML_FDCMP(block, FPR64(FSREG), FPR64(FTREG)); // fdcmp <fsreg>,<ftreg>
+ UML_SETc(block, COND_U, I0); // set i0,u
+ UML_ROLINS(block, CCR132(31), I0, FCCSHIFT(op >> 8), FCCMASK(op >> 8));
+ // rolins ccr31,i0,fccshift,fcc
+ return TRUE;
+
+ case 0x32:
+ case 0x3a:
+ if (IS_SINGLE(op)) /* C.EQ.S - MIPS I */
+ UML_FSCMP(block, FPR32(FSREG), FPR32(FTREG)); // fscmp <fsreg>,<ftreg>
+ else /* C.EQ.D - MIPS I */
+ UML_FDCMP(block, FPR64(FSREG), FPR64(FTREG)); // fdcmp <fsreg>,<ftreg>
+ UML_SETc(block, COND_E, I0); // set i0,e
+ UML_SETc(block, COND_NU, I1); // set i1,nu
+ UML_AND(block, I0, I0, I1); // and i0,i0,i1
+ UML_ROLINS(block, CCR132(31), I0, FCCSHIFT(op >> 8), FCCMASK(op >> 8));
+ // rolins ccr31,i0,fccshift,fcc
+ return TRUE;
+
+ case 0x33:
+ case 0x3b:
+ if (IS_SINGLE(op)) /* C.UEQ.S - MIPS I */
+ UML_FSCMP(block, FPR32(FSREG), FPR32(FTREG)); // fscmp <fsreg>,<ftreg>
+ else /* C.UEQ.D - MIPS I */
+ UML_FDCMP(block, FPR64(FSREG), FPR64(FTREG)); // fdcmp <fsreg>,<ftreg>
+ UML_SETc(block, COND_U, I0); // set i0,u
+ UML_SETc(block, COND_E, I1); // set i1,e
+ UML_OR(block, I0, I0, I1); // or i0,i0,i1
+ UML_ROLINS(block, CCR132(31), I0, FCCSHIFT(op >> 8), FCCMASK(op >> 8));
+ // rolins ccr31,i0,fccshift,fcc
+ return TRUE;
+
+ case 0x34:
+ case 0x3c:
+ if (IS_SINGLE(op)) /* C.OLT.S - MIPS I */
+ UML_FSCMP(block, FPR32(FSREG), FPR32(FTREG)); // fscmp <fsreg>,<ftreg>
+ else /* C.OLT.D - MIPS I */
+ UML_FDCMP(block, FPR64(FSREG), FPR64(FTREG)); // fdcmp <fsreg>,<ftreg>
+ UML_SETc(block, COND_B, I0); // set i0,b
+ UML_SETc(block, COND_NU, I1); // set i1,nu
+ UML_AND(block, I0, I0, I1); // and i0,i0,i1
+ UML_ROLINS(block, CCR132(31), I0, FCCSHIFT(op >> 8), FCCMASK(op >> 8));
+ // rolins ccr31,i0,fccshift,fcc
+ return TRUE;
+
+ case 0x35:
+ case 0x3d:
+ if (IS_SINGLE(op)) /* C.ULT.S - MIPS I */
+ UML_FSCMP(block, FPR32(FSREG), FPR32(FTREG)); // fscmp <fsreg>,<ftreg>
+ else /* C.ULT.D - MIPS I */
+ UML_FDCMP(block, FPR64(FSREG), FPR64(FTREG)); // fdcmp <fsreg>,<ftreg>
+ UML_SETc(block, COND_U, I0); // set i0,u
+ UML_SETc(block, COND_B, I1); // set i1,b
+ UML_OR(block, I0, I0, I1); // or i0,i0,i1
+ UML_ROLINS(block, CCR132(31), I0, FCCSHIFT(op >> 8), FCCMASK(op >> 8));
+ // rolins ccr31,i0,fccshift,fcc
+ return TRUE;
+
+ case 0x36:
+ case 0x3e:
+ if (IS_SINGLE(op)) /* C.OLE.S - MIPS I */
+ UML_FSCMP(block, FPR32(FSREG), FPR32(FTREG)); // fscmp <fsreg>,<ftreg>
+ else /* C.OLE.D - MIPS I */
+ UML_FDCMP(block, FPR64(FSREG), FPR64(FTREG)); // fdcmp <fsreg>,<ftreg>
+ UML_SETc(block, COND_BE, I0); // set i0,be
+ UML_SETc(block, COND_NU, I1); // set i1,nu
+ UML_AND(block, I0, I0, I1); // and i0,i0,i1
+ UML_ROLINS(block, CCR132(31), I0, FCCSHIFT(op >> 8), FCCMASK(op >> 8));
+ // rolins ccr31,i0,fccshift,fcc
+ return TRUE;
+
+ case 0x37:
+ case 0x3f:
+ if (IS_SINGLE(op)) /* C.ULE.S - MIPS I */
+ UML_FSCMP(block, FPR32(FSREG), FPR32(FTREG)); // fscmp <fsreg>,<ftreg>
+ else /* C.ULE.D - MIPS I */
+ UML_FDCMP(block, FPR64(FSREG), FPR64(FTREG)); // fdcmp <fsreg>,<ftreg>
+ UML_SETc(block, COND_U, I0); // set i0,u
+ UML_SETc(block, COND_BE, I1); // set i1,be
+ UML_OR(block, I0, I0, I1); // or i0,i0,i1
+ UML_ROLINS(block, CCR132(31), I0, FCCSHIFT(op >> 8), FCCMASK(op >> 8));
+ // rolins ccr31,i0,fccshift,fcc
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+
+
+/***************************************************************************
+ COP1X RECOMPILATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ generate_cop1x - compile COP1X opcodes
+-------------------------------------------------*/
+
+static int generate_cop1x(mips3_state *mips3, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
+{
+ int in_delay_slot = ((desc->flags & OPFLAG_IN_DELAY_SLOT) != 0);
+ UINT32 op = desc->opptr.l[0];
+
+ if (mips3->impstate->drcoptions & MIPS3DRC_STRICT_COP1)
+ {
+ UML_TEST(block, CPR032(COP0_Status), SR_COP1); // test [Status],SR_COP1
+ UML_EXHc(block, COND_Z, *mips3->impstate->exception[EXCEPTION_BADCOP], 1);// exh cop,1,Z
+ }
+
+ switch (op & 0x3f)
+ {
+ case 0x00: /* LWXC1 - MIPS IV */
+ UML_ADD(block, I0, R32(RSREG), R32(RTREG)); // add i0,<rsreg>,<rtreg>
+ UML_CALLH(block, *mips3->impstate->read32[mips3->impstate->mode >> 1]); // callh read32
+ UML_MOV(block, FPR32(FDREG), I0); // mov <cpr1_fd>,i0
+ if (!in_delay_slot)
+ generate_update_cycles(mips3, block, compiler, desc->pc + 4, TRUE);
+ return TRUE;
+
+ case 0x01: /* LDXC1 - MIPS IV */
+ UML_ADD(block, I0, R32(RSREG), R32(RTREG)); // add i0,<rsreg>,<rtreg>
+ UML_CALLH(block, *mips3->impstate->read64[mips3->impstate->mode >> 1]); // callh read64
+ UML_DMOV(block, FPR64(FDREG), I0); // dmov <cpr1_fd>,i0
+ if (!in_delay_slot)
+ generate_update_cycles(mips3, block, compiler, desc->pc + 4, TRUE);
+ return TRUE;
+
+ case 0x08: /* SWXC1 - MIPS IV */
+ UML_ADD(block, I0, R32(RSREG), R32(RTREG)); // add i0,<rsreg>,<rtreg>
+ UML_MOV(block, I1, FPR32(FSREG)); // mov i1,<cpr1_fs>
+ UML_CALLH(block, *mips3->impstate->write32[mips3->impstate->mode >> 1]); // callh write32
+ if (!in_delay_slot)
+ generate_update_cycles(mips3, block, compiler, desc->pc + 4, TRUE);
+ return TRUE;
+
+ case 0x09: /* SDXC1 - MIPS IV */
+ UML_ADD(block, I0, R32(RSREG), R32(RTREG)); // add i0,<rsreg>,<rtreg>
+ UML_DMOV(block, I1, FPR64(FSREG)); // dmov i1,<cpr1_fs>
+ UML_CALLH(block, *mips3->impstate->write64[mips3->impstate->mode >> 1]); // callh write64
+ if (!in_delay_slot)
+ generate_update_cycles(mips3, block, compiler, desc->pc + 4, TRUE);
+ return TRUE;
+
+ case 0x0f: /* PREFX */
+ return TRUE;
+
+ case 0x20: /* MADD.S - MIPS IV */
+ UML_FSMUL(block, F0, FPR32(FSREG), FPR32(FTREG)); // fsmul f0,<fsreg>,<ftreg>
+ UML_FSADD(block, FPR32(FDREG), F0, FPR32(FRREG)); // fsadd <fdreg>,f0,<frreg>
+ return TRUE;
+
+ case 0x21: /* MADD.D - MIPS IV */
+ UML_FDMUL(block, F0, FPR64(FSREG), FPR64(FTREG)); // fdmul f0,<fsreg>,<ftreg>
+ UML_FDADD(block, FPR64(FDREG), F0, FPR64(FRREG)); // fdadd <fdreg>,f0,<frreg>
+ return TRUE;
+
+ case 0x28: /* MSUB.S - MIPS IV */
+ UML_FSMUL(block, F0, FPR32(FSREG), FPR32(FTREG)); // fsmul f0,<fsreg>,<ftreg>
+ UML_FSSUB(block, FPR32(FDREG), F0, FPR32(FRREG)); // fssub <fdreg>,f0,<frreg>
+ return TRUE;
+
+ case 0x29: /* MSUB.D - MIPS IV */
+ UML_FDMUL(block, F0, FPR64(FSREG), FPR64(FTREG)); // fdmul f0,<fsreg>,<ftreg>
+ UML_FDSUB(block, FPR64(FDREG), F0, FPR64(FRREG)); // fdsub <fdreg>,f0,<frreg>
+ return TRUE;
+
+ case 0x30: /* NMADD.S - MIPS IV */
+ UML_FSMUL(block, F0, FPR32(FSREG), FPR32(FTREG)); // fsmul f0,<fsreg>,<ftreg>
+ UML_FSADD(block, F0, F0, FPR32(FRREG)); // fsadd f0,f0,<frreg>
+ UML_FSNEG(block, FPR32(FDREG), F0); // fsneg <fdreg>,f0
+ return TRUE;
+
+ case 0x31: /* NMADD.D - MIPS IV */
+ UML_FDMUL(block, F0, FPR64(FSREG), FPR64(FTREG)); // fdmul f0,<fsreg>,<ftreg>
+ UML_FDADD(block, F0, F0, FPR64(FRREG)); // fdadd f0,f0,<frreg>
+ UML_FDNEG(block, FPR64(FDREG), F0); // fdneg <fdreg>,f0
+ return TRUE;
+
+ case 0x38: /* NMSUB.S - MIPS IV */
+ UML_FSMUL(block, F0, FPR32(FSREG), FPR32(FTREG)); // fsmul f0,<fsreg>,<ftreg>
+ UML_FSSUB(block, FPR32(FDREG), FPR32(FRREG), F0); // fssub <fdreg>,<frreg>,f0
+ return TRUE;
+
+ case 0x39: /* NMSUB.D - MIPS IV */
+ UML_FDMUL(block, F0, FPR64(FSREG), FPR64(FTREG)); // fdmul f0,<fsreg>,<ftreg>
+ UML_FDSUB(block, FPR64(FDREG), FPR64(FRREG), F0); // fdsub <fdreg>,<frreg>,f0
+ return TRUE;
+
+ default:
+ fprintf(stderr, "cop1x %X\n", op);
+ break;
+ }
+ return FALSE;
+}
+
+
+
+/***************************************************************************
+ CODE LOGGING HELPERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ log_add_disasm_comment - add a comment
+ including disassembly of a MIPS instruction
+-------------------------------------------------*/
+
+static void log_add_disasm_comment(mips3_state *mips3, drcuml_block *block, UINT32 pc, UINT32 op)
+{
+#if (LOG_UML)
+ char buffer[100];
+ dasmmips3(buffer, pc, op);
+ block->append_comment("%08X: %s", pc, buffer); // comment
+#endif
+}
+
+
+/*-------------------------------------------------
+ log_desc_flags_to_string - generate a string
+ representing the instruction description
+ flags
+-------------------------------------------------*/
+
+static const char *log_desc_flags_to_string(UINT32 flags)
+{
+ static char tempbuf[30];
+ char *dest = tempbuf;
+
+ /* branches */
+ if (flags & OPFLAG_IS_UNCONDITIONAL_BRANCH)
+ *dest++ = 'U';
+ else if (flags & OPFLAG_IS_CONDITIONAL_BRANCH)
+ *dest++ = 'C';
+ else
+ *dest++ = '.';
+
+ /* intrablock branches */
+ *dest++ = (flags & OPFLAG_INTRABLOCK_BRANCH) ? 'i' : '.';
+
+ /* branch targets */
+ *dest++ = (flags & OPFLAG_IS_BRANCH_TARGET) ? 'B' : '.';
+
+ /* delay slots */
+ *dest++ = (flags & OPFLAG_IN_DELAY_SLOT) ? 'D' : '.';
+
+ /* exceptions */
+ if (flags & OPFLAG_WILL_CAUSE_EXCEPTION)
+ *dest++ = 'E';
+ else if (flags & OPFLAG_CAN_CAUSE_EXCEPTION)
+ *dest++ = 'e';
+ else
+ *dest++ = '.';
+
+ /* read/write */
+ if (flags & OPFLAG_READS_MEMORY)
+ *dest++ = 'R';
+ else if (flags & OPFLAG_WRITES_MEMORY)
+ *dest++ = 'W';
+ else
+ *dest++ = '.';
+
+ /* TLB validation */
+ *dest++ = (flags & OPFLAG_VALIDATE_TLB) ? 'V' : '.';
+
+ /* TLB modification */
+ *dest++ = (flags & OPFLAG_MODIFIES_TRANSLATION) ? 'T' : '.';
+
+ /* redispatch */
+ *dest++ = (flags & OPFLAG_REDISPATCH) ? 'R' : '.';
+ return tempbuf;
+}
+
+
+/*-------------------------------------------------
+ log_register_list - log a list of GPR registers
+-------------------------------------------------*/
+
+static void log_register_list(drcuml_state *drcuml, const char *string, const UINT32 *reglist, const UINT32 *regnostarlist)
+{
+ int count = 0;
+ int regnum;
+
+ /* skip if nothing */
+ if (reglist[0] == 0 && reglist[1] == 0 && reglist[2] == 0)
+ return;
+
+ drcuml->log_printf("[%s:", string);
+
+ for (regnum = 1; regnum < 32; regnum++)
+ if (reglist[0] & REGFLAG_R(regnum))
+ {
+ drcuml->log_printf("%sr%d", (count++ == 0) ? "" : ",", regnum);
+ if (regnostarlist != NULL && !(regnostarlist[0] & REGFLAG_R(regnum)))
+ drcuml->log_printf("*");
+ }
+
+ for (regnum = 0; regnum < 32; regnum++)
+ if (reglist[1] & REGFLAG_CPR1(regnum))
+ {
+ drcuml->log_printf("%sfr%d", (count++ == 0) ? "" : ",", regnum);
+ if (regnostarlist != NULL && !(regnostarlist[1] & REGFLAG_CPR1(regnum)))
+ drcuml->log_printf("*");
+ }
+
+ if (reglist[2] & REGFLAG_LO)
+ {
+ drcuml->log_printf("%slo", (count++ == 0) ? "" : ",");
+ if (regnostarlist != NULL && !(regnostarlist[2] & REGFLAG_LO))
+ drcuml->log_printf("*");
+ }
+ if (reglist[2] & REGFLAG_HI)
+ {
+ drcuml->log_printf("%shi", (count++ == 0) ? "" : ",");
+ if (regnostarlist != NULL && !(regnostarlist[2] & REGFLAG_HI))
+ drcuml->log_printf("*");
+ }
+ if (reglist[2] & REGFLAG_FCC)
+ {
+ drcuml->log_printf("%sfcc", (count++ == 0) ? "" : ",");
+ if (regnostarlist != NULL && !(regnostarlist[2] & REGFLAG_FCC))
+ drcuml->log_printf("*");
+ }
+
+ drcuml->log_printf("] ");
+}
+
+
+/*-------------------------------------------------
+ log_opcode_desc - log a list of descriptions
+-------------------------------------------------*/
+
+static void log_opcode_desc(drcuml_state *drcuml, const opcode_desc *desclist, int indent)
+{
+ /* open the file, creating it if necessary */
+ if (indent == 0)
+ drcuml->log_printf("\nDescriptor list @ %08X\n", desclist->pc);
+
+ /* output each descriptor */
+ for ( ; desclist != NULL; desclist = desclist->next())
+ {
+ char buffer[100];
+
+ /* disassemle the current instruction and output it to the log */
+#if (LOG_UML || LOG_NATIVE)
+ if (desclist->flags & OPFLAG_VIRTUAL_NOOP)
+ strcpy(buffer, "<virtual nop>");
+ else
+ dasmmips3(buffer, desclist->pc, desclist->opptr.l[0]);
+#else
+ strcpy(buffer, "???");
+#endif
+ drcuml->log_printf("%08X [%08X] t:%08X f:%s: %-30s", desclist->pc, desclist->physpc, desclist->targetpc, log_desc_flags_to_string(desclist->flags), buffer);
+
+ /* output register states */
+ log_register_list(drcuml, "use", desclist->regin, NULL);
+ log_register_list(drcuml, "mod", desclist->regout, desclist->regreq);
+ drcuml->log_printf("\n");
+
+ /* if we have a delay slot, output it recursively */
+ if (desclist->delay.first() != NULL)
+ log_opcode_desc(drcuml, desclist->delay.first(), indent + 1);
+
+ /* at the end of a sequence add a dividing line */
+ if (desclist->flags & OPFLAG_END_SEQUENCE)
+ drcuml->log_printf("-----\n");
+ }
+}
+
+/***************************************************************************
+ NEC VR4300 VARIANTS
+***************************************************************************/
+
+// NEC VR4300 series is MIPS III with 32-bit address bus and slightly custom COP0/TLB
+static CPU_INIT( vr4300be )
+{
+ mips3_init(MIPS3_TYPE_VR4300, TRUE, device, irqcallback);
+}
+
+static CPU_INIT( vr4300le )
+{
+ mips3_init(MIPS3_TYPE_VR4300, FALSE, device, irqcallback);
+}
+
+CPU_GET_INFO( vr4300be )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(vr4300be); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "VR4300 (big)"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(mips3); break;
+ }
+}
+
+CPU_GET_INFO( vr4300le )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(vr4300le); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "VR4300 (little)"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(mips3); break;
+ }
+}
+
+// VR4310 = VR4300 with different speed bin
+CPU_GET_INFO( vr4310be )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(vr4300be); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "VR4310 (big)"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(mips3); break;
+ }
+}
+
+CPU_GET_INFO( vr4310le )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(vr4300le); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "VR4310 (little)"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(mips3); break;
+ }
+}
+
+
+/***************************************************************************
+ R4600 VARIANTS
+***************************************************************************/
+
+static CPU_INIT( r4600be )
+{
+ mips3_init(MIPS3_TYPE_R4600, TRUE, device, irqcallback);
+}
+
+static CPU_INIT( r4600le )
+{
+ mips3_init(MIPS3_TYPE_R4600, FALSE, device, irqcallback);
+}
+
+CPU_GET_INFO( r4600be )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(r4600be); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "R4600 (big)"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(mips3); break;
+ }
+}
+
+CPU_GET_INFO( r4600le )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(r4600le); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "R4600 (little)"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(mips3); break;
+ }
+}
+
+
+
+/***************************************************************************
+ R4650 VARIANTS
+***************************************************************************/
+
+static CPU_INIT( r4650be )
+{
+ mips3_init(MIPS3_TYPE_R4650, TRUE, device, irqcallback);
+}
+
+static CPU_INIT( r4650le )
+{
+ mips3_init(MIPS3_TYPE_R4650, FALSE, device, irqcallback);
+}
+
+CPU_GET_INFO( r4650be )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(r4650be); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "IDT R4650 (big)"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(mips3); break;
+ }
+}
+
+CPU_GET_INFO( r4650le )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(r4650le); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "IDT R4650 (little)"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(mips3); break;
+ }
+}
+
+
+
+/***************************************************************************
+ R4700 VARIANTS
+***************************************************************************/
+
+static CPU_INIT( r4700be )
+{
+ mips3_init(MIPS3_TYPE_R4700, TRUE, device, irqcallback);
+}
+
+static CPU_INIT( r4700le )
+{
+ mips3_init(MIPS3_TYPE_R4700, FALSE, device, irqcallback);
+}
+
+CPU_GET_INFO( r4700be )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(r4700be); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "R4700 (big)"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(mips3); break;
+ }
+}
+
+CPU_GET_INFO( r4700le )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(r4700le); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "R4700 (little)"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(mips3); break;
+ }
+}
+
+
+
+/***************************************************************************
+ R5000 VARIANTS
+***************************************************************************/
+
+static CPU_INIT( r5000be )
+{
+ mips3_init(MIPS3_TYPE_R5000, TRUE, device, irqcallback);
+}
+
+static CPU_INIT( r5000le )
+{
+ mips3_init(MIPS3_TYPE_R5000, FALSE, device, irqcallback);
+}
+
+CPU_GET_INFO( r5000be )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(r5000be); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "R5000 (big)"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(mips3); break;
+ }
+}
+
+CPU_GET_INFO( r5000le )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(r5000le); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "R5000 (little)"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(mips3); break;
+ }
+}
+
+
+
+/***************************************************************************
+ QED5271 VARIANTS
+***************************************************************************/
+
+static CPU_INIT( qed5271be )
+{
+ mips3_init(MIPS3_TYPE_QED5271, TRUE, device, irqcallback);
+}
+
+static CPU_INIT( qed5271le )
+{
+ mips3_init(MIPS3_TYPE_QED5271, FALSE, device, irqcallback);
+}
+
+CPU_GET_INFO( qed5271be )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(qed5271be); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "QED5271 (big)"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(mips3); break;
+ }
+}
+
+CPU_GET_INFO( qed5271le )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(qed5271le); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "QED5271 (little)"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(mips3); break;
+ }
+}
+
+
+
+/***************************************************************************
+ RM7000 VARIANTS
+***************************************************************************/
+
+static CPU_INIT( rm7000be )
+{
+ mips3_init(MIPS3_TYPE_RM7000, TRUE, device, irqcallback);
+}
+
+static CPU_INIT( rm7000le )
+{
+ mips3_init(MIPS3_TYPE_RM7000, FALSE, device, irqcallback);
+}
+
+CPU_GET_INFO( rm7000be )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(rm7000be); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "RM7000 (big)"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(mips3); break;
+ }
+}
+
+CPU_GET_INFO( rm7000le )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(rm7000le); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "RM7000 (little)"); break;
+
+ /* --- everything else is handled generically --- */
+ default: CPU_GET_INFO_CALL(mips3); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(VR4300BE, vr4300be);
+DEFINE_LEGACY_CPU_DEVICE(VR4300LE, vr4300le);
+DEFINE_LEGACY_CPU_DEVICE(VR4310BE, vr4310be);
+DEFINE_LEGACY_CPU_DEVICE(VR4310LE, vr4310le);
+
+DEFINE_LEGACY_CPU_DEVICE(R4600BE, r4600be);
+DEFINE_LEGACY_CPU_DEVICE(R4600LE, r4600le);
+
+DEFINE_LEGACY_CPU_DEVICE(R4650BE, r4650be);
+DEFINE_LEGACY_CPU_DEVICE(R4650LE, r4650le);
+
+DEFINE_LEGACY_CPU_DEVICE(R4700BE, r4700be);
+DEFINE_LEGACY_CPU_DEVICE(R4700LE, r4700le);
+
+DEFINE_LEGACY_CPU_DEVICE(R5000BE, r5000be);
+DEFINE_LEGACY_CPU_DEVICE(R5000LE, r5000le);
+
+DEFINE_LEGACY_CPU_DEVICE(QED5271BE, qed5271be);
+DEFINE_LEGACY_CPU_DEVICE(QED5271LE, qed5271le);
+
+DEFINE_LEGACY_CPU_DEVICE(RM7000BE, rm7000be);
+DEFINE_LEGACY_CPU_DEVICE(RM7000LE, rm7000le);
+
+#endif // MIPS3_USE_DRC
+
diff --git a/trunk/src/emu/cpu/mips/mips3dsm.c b/trunk/src/emu/cpu/mips/mips3dsm.c
new file mode 100644
index 00000000000..a392ef69427
--- /dev/null
+++ b/trunk/src/emu/cpu/mips/mips3dsm.c
@@ -0,0 +1,541 @@
+/***************************************************************************
+
+ mips3dsm.c
+ Disassembler for the portable MIPS 3 emulator.
+ Written by Aaron Giles
+
+***************************************************************************/
+
+#include "emu.h"
+
+#define USE_ABI_REG_NAMES (1)
+
+#if USE_ABI_REG_NAMES
+static const char *const reg[32] =
+{
+ "$0", "$at", "$v0", "$v1", "$a0", "$a1", "$a2", "$a3",
+ "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7",
+ "$s0", "$s1", "$s2", "$s3", "$s4", "$s5", "$s6", "$s7",
+ "$t8", "$t9", "$k0", "$k1", "$gp", "$sp", "$fp", "$ra"
+};
+#else
+static const char *const reg[32] =
+{
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+ "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"
+};
+#endif
+
+
+
+static const char *const cpreg[4][32] =
+{
+ {
+ "Index","Random","EntryLo0","EntryLo1","Context","PageMask","Wired","Error",
+ "BadVAddr","Count","EntryHi","Compare","SR","Cause","EPC","PRId",
+ "Config","LLAddr","WatchLo","WatchHi","XContext","cpr21","cpr22","cpr23",
+ "cpr24","cpr25","ECC","CacheError","TagLo","TagHi","ErrorEPC","cpr31"
+ },
+ {
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
+ "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
+ "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
+ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"
+ },
+ {
+ "cpr0", "cpr1", "cpr2", "cpr3", "cpr4", "cpr5", "cpr6", "cpr7",
+ "cpr8", "cpr9", "cpr10","cpr11","cpr12","cpr13","cpr14","cpr15",
+ "cpr16","cpr17","cpr18","cpr19","cpr20","cpr21","cpr22","cpr23",
+ "cpr24","cpr25","cpr26","cpr27","cpr28","cpr29","cpr30","cpr31"
+ },
+ {
+ "cpr0", "cpr1", "cpr2", "cpr3", "cpr4", "cpr5", "cpr6", "cpr7",
+ "cpr8", "cpr9", "cpr10","cpr11","cpr12","cpr13","cpr14","cpr15",
+ "cpr16","cpr17","cpr18","cpr19","cpr20","cpr21","cpr22","cpr23",
+ "cpr24","cpr25","cpr26","cpr27","cpr28","cpr29","cpr30","cpr31"
+ }
+};
+
+
+static const char *const ccreg[4][32] =
+{
+ {
+ "ccr0", "ccr1", "ccr2", "ccr3", "ccr4", "ccr5", "ccr6", "ccr7",
+ "ccr8", "ccr9", "ccr10","ccr11","ccr12","ccr13","ccr14","ccr15",
+ "ccr16","ccr17","ccr18","ccr19","ccr20","ccr21","ccr22","ccr23",
+ "ccr24","ccr25","ccr26","ccr27","ccr28","ccr29","ccr30","ccr31"
+ },
+ {
+ "ccr0", "ccr1", "ccr2", "ccr3", "ccr4", "ccr5", "ccr6", "ccr7",
+ "ccr8", "ccr9", "ccr10","ccr11","ccr12","ccr13","ccr14","ccr15",
+ "ccr16","ccr17","ccr18","ccr19","ccr20","ccr21","ccr22","ccr23",
+ "ccr24","ccr25","ccr26","ccr27","ccr28","ccr29","ccr30","ccr31"
+ },
+ {
+ "ccr0", "ccr1", "ccr2", "ccr3", "ccr4", "ccr5", "ccr6", "ccr7",
+ "ccr8", "ccr9", "ccr10","ccr11","ccr12","ccr13","ccr14","ccr15",
+ "ccr16","ccr17","ccr18","ccr19","ccr20","ccr21","ccr22","ccr23",
+ "ccr24","ccr25","ccr26","ccr27","ccr28","ccr29","ccr30","ccr31"
+ },
+ {
+ "ccr0", "ccr1", "ccr2", "ccr3", "ccr4", "ccr5", "ccr6", "ccr7",
+ "ccr8", "ccr9", "ccr10","ccr11","ccr12","ccr13","ccr14","ccr15",
+ "ccr16","ccr17","ccr18","ccr19","ccr20","ccr21","ccr22","ccr23",
+ "ccr24","ccr25","ccr26","ccr27","ccr28","ccr29","ccr30","ccr31"
+ }
+};
+
+
+/***************************************************************************
+ CODE CODE
+***************************************************************************/
+
+INLINE char *signed_16bit(INT16 val)
+{
+ static char temp[10];
+ if (val < 0)
+ sprintf(temp, "-$%x", -val);
+ else
+ sprintf(temp, "$%x", val);
+ return temp;
+}
+
+static UINT32 dasm_cop0(UINT32 pc, UINT32 op, char *buffer)
+{
+ int rt = (op >> 16) & 31;
+ int rd = (op >> 11) & 31;
+ UINT32 flags = 0;
+
+ switch ((op >> 21) & 31)
+ {
+ case 0x00: sprintf(buffer, "mfc0 %s,%s", reg[rt], cpreg[0][rd]); break;
+ case 0x01: sprintf(buffer, "dmfc0 %s,%s", reg[rt], cpreg[0][rd]); break;
+ case 0x02: sprintf(buffer, "cfc0 %s,%s", reg[rt], ccreg[0][rd]); break;
+ case 0x04: sprintf(buffer, "mtc0 %s,%s", reg[rt], cpreg[0][rd]); break;
+ case 0x05: sprintf(buffer, "dmtc0 %s,%s", reg[rt], cpreg[0][rd]); break;
+ case 0x06: sprintf(buffer, "ctc0 %s,%s", reg[rt], ccreg[0][rd]); break;
+ case 0x08: /* BC */
+ switch (rt)
+ {
+ case 0x00: sprintf(buffer, "bc0f $%08x", pc + 4 + ((INT16)op << 2)); break;
+ case 0x01: sprintf(buffer, "bc0t $%08x", pc + 4 + ((INT16)op << 2)); break;
+ case 0x02: sprintf(buffer, "bc0fl [invalid]"); break;
+ case 0x03: sprintf(buffer, "bc0tl [invalid]"); break;
+ default: sprintf(buffer, "dc.l $%08x [invalid]", op); break;
+ }
+ break;
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ case 0x13:
+ case 0x14:
+ case 0x15:
+ case 0x16:
+ case 0x17:
+ case 0x18:
+ case 0x19:
+ case 0x1a:
+ case 0x1b:
+ case 0x1c:
+ case 0x1d:
+ case 0x1e:
+ case 0x1f: /* COP */
+ switch (op & 0x01ffffff)
+ {
+ case 0x01: sprintf(buffer, "tlbr"); break;
+ case 0x02: sprintf(buffer, "tlbwi"); break;
+ case 0x06: sprintf(buffer, "tlbwr"); break;
+ case 0x08: sprintf(buffer, "tlbp"); break;
+ case 0x10: sprintf(buffer, "rfe"); flags = DASMFLAG_STEP_OUT; break;
+ case 0x18: sprintf(buffer, "eret [invalid]"); break;
+ default: sprintf(buffer, "cop0 $%07x", op & 0x01ffffff); break;
+ }
+ break;
+ default: sprintf(buffer, "dc.l $%08x [invalid]", op); break;
+ }
+ return flags;
+}
+
+static UINT32 dasm_cop1(UINT32 pc, UINT32 op, char *buffer)
+{
+ static const char *const format_table[] =
+ {
+ "?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?",
+ "s","d","?","?","w","l","?","?","?","?","?","?","?","?","?","?"
+ };
+ const char *fmt = format_table[(op >> 21) & 31];
+ int ft = (op >> 16) & 31;
+ int fs = (op >> 11) & 31;
+ int fd = (op >> 6) & 31;
+ int rt = (op >> 16) & 31;
+ int rd = (op >> 11) & 31;
+ UINT32 flags = 0;
+
+ switch ((op >> 21) & 31)
+ {
+ case 0x00: sprintf(buffer, "mfc1 %s,%s", reg[rt], cpreg[1][rd]); break;
+ case 0x01: sprintf(buffer, "dmfc1 %s,%s", reg[rt], cpreg[1][rd]); break;
+ case 0x02: sprintf(buffer, "cfc1 %s,%s", reg[rt], ccreg[1][rd]); break;
+ case 0x04: sprintf(buffer, "mtc1 %s,%s", reg[rt], cpreg[1][rd]); break;
+ case 0x05: sprintf(buffer, "dmtc1 %s,%s", reg[rt], cpreg[1][rd]); break;
+ case 0x06: sprintf(buffer, "ctc1 %s,%s", reg[rt], ccreg[1][rd]); break;
+ case 0x08: /* BC */
+ switch (rt & 3)
+ {
+ case 0x00: sprintf(buffer, "bc1f $%08x,%d", pc + 4 + ((INT16)op << 2), (op >> 18) & 7); break;
+ case 0x01: sprintf(buffer, "bc1t $%08x,%d", pc + 4 + ((INT16)op << 2), (op >> 18) & 7); break;
+ case 0x02: sprintf(buffer, "bc1fl $%08x,%d", pc + 4 + ((INT16)op << 2), (op >> 18) & 7); flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1); break;
+ case 0x03: sprintf(buffer, "bc1tl $%08x,%d", pc + 4 + ((INT16)op << 2), (op >> 18) & 7); flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1); break;
+ }
+ break;
+ default: /* COP */
+ switch (op & 0x3f)
+ {
+ case 0x00: sprintf(buffer, "add.%s %s,%s,%s", fmt, cpreg[1][fd], cpreg[1][fs], cpreg[1][ft]); break;
+ case 0x01: sprintf(buffer, "sub.%s %s,%s,%s", fmt, cpreg[1][fd], cpreg[1][fs], cpreg[1][ft]); break;
+ case 0x02: sprintf(buffer, "mul.%s %s,%s,%s", fmt, cpreg[1][fd], cpreg[1][fs], cpreg[1][ft]); break;
+ case 0x03: sprintf(buffer, "div.%s %s,%s,%s", fmt, cpreg[1][fd], cpreg[1][fs], cpreg[1][ft]); break;
+ case 0x04: sprintf(buffer, "sqrt.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
+ case 0x05: sprintf(buffer, "abs.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
+ case 0x06: sprintf(buffer, "mov.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
+ case 0x07: sprintf(buffer, "neg.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
+ case 0x08: sprintf(buffer, "round.l.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
+ case 0x09: sprintf(buffer, "trunc.l.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
+ case 0x0a: sprintf(buffer, "ceil.l.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
+ case 0x0b: sprintf(buffer, "floor.l.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
+ case 0x0c: sprintf(buffer, "round.w.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
+ case 0x0d: sprintf(buffer, "trunc.w.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
+ case 0x0e: sprintf(buffer, "ceil.w.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
+ case 0x0f: sprintf(buffer, "floor.w.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
+ case 0x11: sprintf(buffer, "mov%c.%s %s,%s,%d", ((op >> 16) & 1) ? 't' : 'f', fmt, cpreg[1][fd], cpreg[1][fs], (op >> 18) & 7); break;
+ case 0x12: sprintf(buffer, "movz.%s %s,%s,%s", fmt, cpreg[1][fd], cpreg[1][fs], reg[rt]); break;
+ case 0x13: sprintf(buffer, "movn.%s %s,%s,%s", fmt, cpreg[1][fd], cpreg[1][fs], reg[rt]); break;
+ case 0x15: sprintf(buffer, "recip.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
+ case 0x16: sprintf(buffer, "rsqrt.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
+ case 0x20: sprintf(buffer, "cvt.s.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
+ case 0x21: sprintf(buffer, "cvt.d.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
+ case 0x24: sprintf(buffer, "cvt.w.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
+ case 0x25: sprintf(buffer, "cvt.l.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
+ case 0x30: sprintf(buffer, "c.f.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
+ case 0x31: sprintf(buffer, "c.un.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
+ case 0x32: sprintf(buffer, "c.eq.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
+ case 0x33: sprintf(buffer, "c.ueq.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
+ case 0x34: sprintf(buffer, "c.olt.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
+ case 0x35: sprintf(buffer, "c.ult.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
+ case 0x36: sprintf(buffer, "c.ole.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
+ case 0x37: sprintf(buffer, "c.ule.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
+ case 0x38: sprintf(buffer, "c.sf.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
+ case 0x39: sprintf(buffer, "c.ngle.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7);break;
+ case 0x3a: sprintf(buffer, "c.seq.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
+ case 0x3b: sprintf(buffer, "c.ngl.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
+ case 0x3c: sprintf(buffer, "c.lt.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
+ case 0x3d: sprintf(buffer, "c.nge.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
+ case 0x3e: sprintf(buffer, "c.le.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
+ case 0x3f: sprintf(buffer, "c.ngt.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
+ default: sprintf(buffer, "cop1 $%07x", op & 0x01ffffff); break;
+ }
+ break;
+ }
+ return flags;
+}
+
+static UINT32 dasm_cop1x(UINT32 pc, UINT32 op, char *buffer)
+{
+ static const char *const format3_table[] =
+ {
+ "s","d","?","?","w","l","?","?"
+ };
+ const char *fmt3 = format3_table[op & 7];
+ int fr = (op >> 21) & 31;
+ int ft = (op >> 16) & 31;
+ int fs = (op >> 11) & 31;
+ int fd = (op >> 6) & 31;
+ int rs = (op >> 21) & 31;
+ int rt = (op >> 16) & 31;
+ int rd = (op >> 11) & 31;
+ UINT32 flags = 0;
+
+ switch (op & 0x3f)
+ {
+ case 0x00: sprintf(buffer, "lwxc1 %s,%s(%s)", cpreg[1][fd], reg[rt], reg[rs]); break;
+ case 0x01: sprintf(buffer, "ldxc1 %s,%s(%s)", cpreg[1][fd], reg[rt], reg[rs]); break;
+ case 0x08: sprintf(buffer, "swxc1 %s,%s(%s)", cpreg[1][fd], reg[rt], reg[rs]); break;
+ case 0x09: sprintf(buffer, "sdxc1 %s,%s(%s)", cpreg[1][fd], reg[rt], reg[rs]); break;
+ case 0x0f: sprintf(buffer, "prefx %d,%s(%s)", rd, reg[rt], reg[rs]); break;
+ case 0x20:
+ case 0x21:
+ case 0x22:
+ case 0x23:
+ case 0x24:
+ case 0x25:
+ case 0x26:
+ case 0x27: sprintf(buffer, "madd.%s %s,%s,%s,%s", fmt3, cpreg[1][fd], cpreg[1][fr], cpreg[1][fs], cpreg[1][ft]); break;
+ case 0x28:
+ case 0x29:
+ case 0x2a:
+ case 0x2b:
+ case 0x2c:
+ case 0x2d:
+ case 0x2e:
+ case 0x2f: sprintf(buffer, "msub.%s %s,%s,%s,%s", fmt3, cpreg[1][fd], cpreg[1][fr], cpreg[1][fs], cpreg[1][ft]); break;
+ case 0x30:
+ case 0x31:
+ case 0x32:
+ case 0x33:
+ case 0x34:
+ case 0x35:
+ case 0x36:
+ case 0x37: sprintf(buffer, "nmadd.%s %s,%s,%s,%s", fmt3, cpreg[1][fd], cpreg[1][fr], cpreg[1][fs], cpreg[1][ft]); break;
+ case 0x38:
+ case 0x39:
+ case 0x3a:
+ case 0x3b:
+ case 0x3c:
+ case 0x3d:
+ case 0x3e:
+ case 0x3f: sprintf(buffer, "nmsub.%s %s,%s,%s,%s", fmt3, cpreg[1][fd], cpreg[1][fr], cpreg[1][fs], cpreg[1][ft]); break;
+ default: sprintf(buffer, "cop1 $%07x", op & 0x01ffffff); break;
+ }
+ return flags;
+}
+
+static UINT32 dasm_cop2(UINT32 pc, UINT32 op, char *buffer)
+{
+ int rt = (op >> 16) & 31;
+ int rd = (op >> 11) & 31;
+ UINT32 flags = 0;
+
+ switch ((op >> 21) & 31)
+ {
+ case 0x00: sprintf(buffer, "mfc2 %s,%s", reg[rt], cpreg[2][rd]); break;
+ case 0x01: sprintf(buffer, "dmfc2 %s,%s", reg[rt], cpreg[2][rd]); break;
+ case 0x02: sprintf(buffer, "cfc2 %s,%s", reg[rt], ccreg[2][rd]); break;
+ case 0x04: sprintf(buffer, "mtc2 %s,%s", reg[rt], cpreg[2][rd]); break;
+ case 0x05: sprintf(buffer, "dmtc2 %s,%s", reg[rt], cpreg[2][rd]); break;
+ case 0x06: sprintf(buffer, "ctc2 %s,%s", reg[rt], ccreg[2][rd]); break;
+ case 0x08: /* BC */
+ switch (rt)
+ {
+ case 0x00: sprintf(buffer, "bc2f $%08x", pc + 4 + ((INT16)op << 2)); break;
+ case 0x01: sprintf(buffer, "bc2t $%08x", pc + 4 + ((INT16)op << 2)); break;
+ case 0x02: sprintf(buffer, "bc2fl [invalid]"); break;
+ case 0x03: sprintf(buffer, "bc2tl [invalid]"); break;
+ default: sprintf(buffer, "dc.l $%08x [invalid]", op); break;
+ }
+ break;
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ case 0x13:
+ case 0x14:
+ case 0x15:
+ case 0x16:
+ case 0x17:
+ case 0x18:
+ case 0x19:
+ case 0x1a:
+ case 0x1b:
+ case 0x1c:
+ case 0x1d:
+ case 0x1e:
+ case 0x1f: /* COP */
+ sprintf(buffer, "cop2 $%07x", op & 0x01ffffff);
+ break;
+ default: sprintf(buffer, "dc.l $%08x [invalid]", op); break;
+ }
+ return flags;
+}
+
+unsigned dasmmips3(char *buffer, unsigned pc, UINT32 op)
+{
+ int rs = (op >> 21) & 31;
+ int rt = (op >> 16) & 31;
+ int rd = (op >> 11) & 31;
+ int shift = (op >> 6) & 31;
+ UINT32 flags = 0;
+
+ switch (op >> 26)
+ {
+ case 0x00: /* SPECIAL */
+ switch (op & 63)
+ {
+ case 0x00: if (op == 0)
+ sprintf(buffer, "nop");
+ else
+ sprintf(buffer, "sll %s,%s,%d", reg[rd], reg[rt], shift); break;
+ case 0x01: sprintf(buffer, "mov%c %s,%s,%d", ((op >> 16) & 1) ? 't' : 'f', reg[rd], reg[rs], (op >> 18) & 7); break;
+ case 0x02: sprintf(buffer, "srl %s,%s,%d", reg[rd], reg[rt], shift); break;
+ case 0x03: sprintf(buffer, "sra %s,%s,%d", reg[rd], reg[rt], shift); break;
+ case 0x04: sprintf(buffer, "sllv %s,%s,%s", reg[rd], reg[rt], reg[rs]); break;
+ case 0x06: sprintf(buffer, "srlv %s,%s,%s", reg[rd], reg[rt], reg[rs]); break;
+ case 0x07: sprintf(buffer, "srav %s,%s,%s", reg[rd], reg[rt], reg[rs]); break;
+ case 0x08: sprintf(buffer, "jr %s", reg[rs]); if (rs == 31) flags = DASMFLAG_STEP_OUT; break;
+ case 0x09: if (rd == 31)
+ sprintf(buffer, "jalr %s", reg[rs]);
+ else
+ sprintf(buffer, "jalr %s,%s", reg[rs], reg[rd]); flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1); break;
+ case 0x0a: sprintf(buffer, "movz %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
+ case 0x0b: sprintf(buffer, "movn %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
+ case 0x0c: sprintf(buffer, "syscall"); flags = DASMFLAG_STEP_OVER; break;
+ case 0x0d: sprintf(buffer, "break"); flags = DASMFLAG_STEP_OVER; break;
+ case 0x0f: sprintf(buffer, "sync"); break;
+ case 0x10: sprintf(buffer, "mfhi %s", reg[rd]); break;
+ case 0x11: sprintf(buffer, "mthi %s", reg[rs]); break;
+ case 0x12: sprintf(buffer, "mflo %s", reg[rd]); break;
+ case 0x13: sprintf(buffer, "mtlo %s", reg[rs]); break;
+ case 0x14: sprintf(buffer, "dsllv %s,%s,%s", reg[rd], reg[rt], reg[rs]); break;
+ case 0x16: sprintf(buffer, "dsrlv %s,%s,%s", reg[rd], reg[rt], reg[rs]); break;
+ case 0x17: sprintf(buffer, "dsrav %s,%s,%s", reg[rd], reg[rt], reg[rs]); break;
+ case 0x18: sprintf(buffer, "mult %s,%s", reg[rs], reg[rt]); break;
+ case 0x19: sprintf(buffer, "multu %s,%s", reg[rs], reg[rt]); break;
+ case 0x1a: sprintf(buffer, "div %s,%s", reg[rs], reg[rt]); break;
+ case 0x1b: sprintf(buffer, "divu %s,%s", reg[rs], reg[rt]); break;
+ case 0x1c: sprintf(buffer, "dmult %s,%s", reg[rs], reg[rt]); break;
+ case 0x1d: sprintf(buffer, "dmultu %s,%s", reg[rs], reg[rt]); break;
+ case 0x1e: sprintf(buffer, "ddiv %s,%s", reg[rs], reg[rt]); break;
+ case 0x1f: sprintf(buffer, "ddivu %s,%s", reg[rs], reg[rt]); break;
+ case 0x20: sprintf(buffer, "add %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
+ case 0x21: sprintf(buffer, "addu %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
+ case 0x22: sprintf(buffer, "sub %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
+ case 0x23: sprintf(buffer, "subu %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
+ case 0x24: sprintf(buffer, "and %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
+ case 0x25: sprintf(buffer, "or %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
+ case 0x26: sprintf(buffer, "xor %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
+ case 0x27: sprintf(buffer, "nor %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
+ case 0x2a: sprintf(buffer, "slt %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
+ case 0x2b: sprintf(buffer, "sltu %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
+ case 0x2c: sprintf(buffer, "dadd %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
+ case 0x2d: sprintf(buffer, "daddu %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
+ case 0x2e: sprintf(buffer, "dsub %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
+ case 0x2f: sprintf(buffer, "dsubu %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
+ case 0x30: sprintf(buffer, "tge %s,%s", reg[rs], reg[rt]); flags = DASMFLAG_STEP_OVER; break;
+ case 0x31: sprintf(buffer, "tgeu %s,%s", reg[rs], reg[rt]); flags = DASMFLAG_STEP_OVER; break;
+ case 0x32: sprintf(buffer, "tlt %s,%s", reg[rs], reg[rt]); flags = DASMFLAG_STEP_OVER; break;
+ case 0x33: sprintf(buffer, "tltu %s,%s", reg[rs], reg[rt]); flags = DASMFLAG_STEP_OVER; break;
+ case 0x34: sprintf(buffer, "teq %s,%s", reg[rs], reg[rt]); flags = DASMFLAG_STEP_OVER; break;
+ case 0x36: sprintf(buffer, "tne %s,%s", reg[rs], reg[rt]) ;flags = DASMFLAG_STEP_OVER; break;
+ case 0x38: sprintf(buffer, "dsll %s,%s,%d", reg[rd], reg[rt], shift); break;
+ case 0x3a: sprintf(buffer, "dsrl %s,%s,%d", reg[rd], reg[rt], shift); break;
+ case 0x3b: sprintf(buffer, "dsra %s,%s,%d", reg[rd], reg[rt], shift); break;
+ case 0x3c: sprintf(buffer, "dsll %s,%s,%d", reg[rd], reg[rt], shift+32); break;
+ case 0x3e: sprintf(buffer, "dsrl %s,%s,%d", reg[rd], reg[rt], shift+32); break;
+ case 0x3f: sprintf(buffer, "dsra %s,%s,%d", reg[rd], reg[rt], shift+32); break;
+ default: sprintf(buffer, "dc.l $%08x [invalid]", op); break;
+ }
+ break;
+
+ case 0x01: /* REGIMM */
+ switch ((op >> 16) & 31)
+ {
+ case 0x00: sprintf(buffer, "bltz %s,$%08x", reg[rs], pc + 4 + ((INT16)op << 2)); break;
+ case 0x01: sprintf(buffer, "bgez %s,$%08x", reg[rs], pc + 4 + ((INT16)op << 2)); break;
+ case 0x02: sprintf(buffer, "bltzl %s,$%08x", reg[rs], pc + 4 + ((INT16)op << 2)); break;
+ case 0x03: sprintf(buffer, "bgezl %s,$%08x", reg[rs], pc + 4 + ((INT16)op << 2)); break;
+ case 0x08: sprintf(buffer, "tgei %s,%s", reg[rs], signed_16bit(op)); flags = DASMFLAG_STEP_OVER; break;
+ case 0x09: sprintf(buffer, "tgeiu %s,%s", reg[rs], signed_16bit(op)); flags = DASMFLAG_STEP_OVER; break;
+ case 0x0a: sprintf(buffer, "tlti %s,%s", reg[rs], signed_16bit(op)); flags = DASMFLAG_STEP_OVER; break;
+ case 0x0b: sprintf(buffer, "tltiu %s,%s", reg[rs], signed_16bit(op)); flags = DASMFLAG_STEP_OVER; break;
+ case 0x0c: sprintf(buffer, "teqi %s,%s", reg[rs], signed_16bit(op)); flags = DASMFLAG_STEP_OVER; break;
+ case 0x0e: sprintf(buffer, "tnei %s,%s", reg[rs], signed_16bit(op)); flags = DASMFLAG_STEP_OVER; break;
+ case 0x10: sprintf(buffer, "bltzal %s,$%08x", reg[rs], pc + 4 + ((INT16)op << 2)); flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1); break;
+ case 0x11: sprintf(buffer, "bgezal %s,$%08x", reg[rs], pc + 4 + ((INT16)op << 2)); flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1); break;
+ case 0x12: sprintf(buffer, "bltzall %s,$%08x", reg[rs], pc + 4 + ((INT16)op << 2)); flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1); break;
+ case 0x13: sprintf(buffer, "bgezall %s,$%08x", reg[rs], pc + 4 + ((INT16)op << 2)); flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1); break;
+ default: sprintf(buffer, "dc.l $%08x [invalid]", op); break;
+ }
+ break;
+
+ case 0x02: sprintf(buffer, "j $%08x", (pc & 0xf0000000) | ((op & 0x03ffffff) << 2)); break;
+ case 0x03: sprintf(buffer, "jal $%08x", (pc & 0xf0000000) | ((op & 0x03ffffff) << 2)); flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1); break;
+ case 0x04: if (rs == 0 && rt == 0)
+ sprintf(buffer, "b $%08x", pc + 4 + ((INT16)op << 2));
+ else
+ sprintf(buffer, "beq %s,%s,$%08x", reg[rs], reg[rt], pc + 4 + ((INT16)op << 2));break;
+ case 0x05: sprintf(buffer, "bne %s,%s,$%08x", reg[rs], reg[rt], pc + 4 + ((INT16)op << 2));break;
+ case 0x06: sprintf(buffer, "blez %s,$%08x", reg[rs], pc + 4 + ((INT16)op << 2)); break;
+ case 0x07: sprintf(buffer, "bgtz %s,$%08x", reg[rs], pc + 4 + ((INT16)op << 2)); break;
+ case 0x08: sprintf(buffer, "addi %s,%s,%s", reg[rt], reg[rs], signed_16bit(op)); break;
+ case 0x09: sprintf(buffer, "addiu %s,%s,%s", reg[rt], reg[rs], signed_16bit(op)); break;
+ case 0x0a: sprintf(buffer, "slti %s,%s,%s", reg[rt], reg[rs], signed_16bit(op)); break;
+ case 0x0b: sprintf(buffer, "sltiu %s,%s,%s", reg[rt], reg[rs], signed_16bit(op)); break;
+ case 0x0c: sprintf(buffer, "andi %s,%s,$%04x", reg[rt], reg[rs], (UINT16)op); break;
+ case 0x0d: sprintf(buffer, "ori %s,%s,$%04x", reg[rt], reg[rs], (UINT16)op); break;
+ case 0x0e: sprintf(buffer, "xori %s,%s,$%04x", reg[rt], reg[rs], (UINT16)op); break;
+ case 0x0f: sprintf(buffer, "lui %s,$%04x", reg[rt], (UINT16)op); break;
+ case 0x10: flags = dasm_cop0(pc, op, buffer); break;
+ case 0x11: flags = dasm_cop1(pc, op, buffer); break;
+ case 0x12: flags = dasm_cop2(pc, op, buffer); break;
+ case 0x13: flags = dasm_cop1x(pc, op, buffer); break;
+ case 0x14: sprintf(buffer, "beql %s,%s,$%08x", reg[rs], reg[rt], pc + 4 + ((INT16)op << 2));break;
+ case 0x15: sprintf(buffer, "bnel %s,%s,$%08x", reg[rs], reg[rt], pc + 4 + ((INT16)op << 2));break;
+ case 0x16: sprintf(buffer, "blezl %s,%s,$%08x", reg[rs], reg[rt], pc + 4 + ((INT16)op << 2));break;
+ case 0x17: sprintf(buffer, "bgtzl %s,%s,$%08x", reg[rs], reg[rt], pc + 4 + ((INT16)op << 2));break;
+ case 0x18: sprintf(buffer, "daddi %s,%s,%s", reg[rt], reg[rs], signed_16bit(op)); break;
+ case 0x19: sprintf(buffer, "daddiu %s,%s,%s", reg[rt], reg[rs], signed_16bit(op)); break;
+ case 0x1a: sprintf(buffer, "ldl %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
+ case 0x1b: sprintf(buffer, "ldr %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
+ case 0x1c: /* IDT-specific opcodes: mad/madu/mul on R4640/4650, msub on RC32364 */
+ switch (op & 0x1f)
+ {
+ case 0: sprintf(buffer, "mad %s,%s", reg[rs], reg[rt]); break;
+ case 1: sprintf(buffer, "madu %s,%s", reg[rs], reg[rt]); break;
+ case 2: sprintf(buffer, "mul %s,%s,%s", reg[rs], reg[rt], reg[rd]); break;
+ case 4: sprintf(buffer, "msub %s,%s", reg[rs], reg[rt]); break;
+ default:sprintf(buffer, "dc.l $%08x [invalid]", op); break;
+ }
+ break;
+ case 0x20: sprintf(buffer, "lb %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
+ case 0x21: sprintf(buffer, "lh %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
+ case 0x22: sprintf(buffer, "lwl %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
+ case 0x23: sprintf(buffer, "lw %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
+ case 0x24: sprintf(buffer, "lbu %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
+ case 0x25: sprintf(buffer, "lhu %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
+ case 0x26: sprintf(buffer, "lwr %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
+ case 0x27: sprintf(buffer, "lwu %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
+ case 0x28: sprintf(buffer, "sb %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
+ case 0x29: sprintf(buffer, "sh %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
+ case 0x2a: sprintf(buffer, "swl %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
+ case 0x2b: sprintf(buffer, "sw %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
+ case 0x2c: sprintf(buffer, "sdl %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
+ case 0x2d: sprintf(buffer, "sdr %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
+ case 0x2e: sprintf(buffer, "swr %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
+ case 0x2f: sprintf(buffer, "cache %s(%s)", reg[rs], signed_16bit(op)); break;
+ case 0x30: sprintf(buffer, "ll %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
+ case 0x31: sprintf(buffer, "lwc1 %s,%s(%s)", cpreg[1][rt], signed_16bit(op), reg[rs]); break;
+ case 0x32: sprintf(buffer, "lwc2 %s,%s(%s)", cpreg[2][rt], signed_16bit(op), reg[rs]); break;
+ case 0x33: sprintf(buffer, "pref $%x,%s(%s)", rt, signed_16bit(op), reg[rs]); break;
+ case 0x34: sprintf(buffer, "lld %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
+ case 0x35: sprintf(buffer, "ldc1 %s,%s(%s)", cpreg[1][rt], signed_16bit(op), reg[rs]); break;
+ case 0x36: sprintf(buffer, "ldc2 %s,%s(%s)", cpreg[2][rt], signed_16bit(op), reg[rs]); break;
+ case 0x37: sprintf(buffer, "ld %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
+ case 0x38: sprintf(buffer, "sc %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
+ case 0x39: sprintf(buffer, "swc1 %s,%s(%s)", cpreg[1][rt], signed_16bit(op), reg[rs]); break;
+ case 0x3a: sprintf(buffer, "swc2 %s,%s(%s)", cpreg[2][rt], signed_16bit(op), reg[rs]); break;
+ case 0x3c: sprintf(buffer, "scd %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
+ case 0x3d: sprintf(buffer, "sdc1 %s,%s(%s)", cpreg[1][rt], signed_16bit(op), reg[rs]); break;
+ case 0x3e: sprintf(buffer, "sdc2 %s,%s(%s)", cpreg[2][rt], signed_16bit(op), reg[rs]); break;
+ case 0x3f: sprintf(buffer, "sd %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
+ default: sprintf(buffer, "dc.l $%08x [invalid]", op); break;
+ }
+ return 4 | flags | DASMFLAG_SUPPORTED;
+}
+
+
+CPU_DISASSEMBLE( mips3be )
+{
+ UINT32 op = *(UINT32 *)oprom;
+ op = BIG_ENDIANIZE_INT32(op);
+ return dasmmips3(buffer, pc, op);
+}
+
+
+CPU_DISASSEMBLE( mips3le )
+{
+ UINT32 op = *(UINT32 *)oprom;
+ op = LITTLE_ENDIANIZE_INT32(op);
+ return dasmmips3(buffer, pc, op);
+}
+
+
diff --git a/trunk/src/emu/cpu/mips/mips3fe.c b/trunk/src/emu/cpu/mips/mips3fe.c
new file mode 100644
index 00000000000..9f2b50a14e7
--- /dev/null
+++ b/trunk/src/emu/cpu/mips/mips3fe.c
@@ -0,0 +1,770 @@
+/***************************************************************************
+
+ mips3fe.c
+
+ Front-end for MIPS3 recompiler
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "mips3fe.h"
+#include "mips3com.h"
+
+
+//**************************************************************************
+// MIPS3 FRONTEND
+//**************************************************************************
+
+//-------------------------------------------------
+// mips3_frontend - constructor
+//-------------------------------------------------
+
+mips3_frontend::mips3_frontend(mips3_state &state, UINT32 window_start, UINT32 window_end, UINT32 max_sequence)
+ : drc_frontend(*state.device, window_start, window_end, max_sequence),
+ m_context(state)
+{
+}
+
+
+//-------------------------------------------------
+// describe - build a description of a single
+// instruction
+//-------------------------------------------------
+
+bool mips3_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
+{
+ UINT32 op, opswitch;
+
+ // compute the physical PC
+ assert((desc.physpc & 3) == 0);
+ if (!mips3com_translate_address(&m_context, AS_PROGRAM, TRANSLATE_FETCH, &desc.physpc))
+ {
+ // uh-oh: a page fault; leave the description empty and just if this is the first instruction, leave it empty and
+ // mark as needing to validate; otherwise, just end the sequence here
+ desc.flags |= OPFLAG_VALIDATE_TLB | OPFLAG_CAN_CAUSE_EXCEPTION | OPFLAG_COMPILER_PAGE_FAULT | OPFLAG_VIRTUAL_NOOP | OPFLAG_END_SEQUENCE;
+ return true;
+ }
+
+ // fetch the opcode
+ assert((desc.physpc & 3) == 0);
+ op = desc.opptr.l[0] = m_context.direct->read_decrypted_dword(desc.physpc);
+
+ // all instructions are 4 bytes and default to a single cycle each
+ desc.length = 4;
+ desc.cycles = 1;
+
+ // parse the instruction
+ opswitch = op >> 26;
+ switch (opswitch)
+ {
+ case 0x00: // SPECIAL
+ return describe_special(op, desc);
+
+ case 0x01: // REGIMM
+ return describe_regimm(op, desc);
+
+ case 0x10: // COP0
+ return describe_cop0(op, desc);
+
+ case 0x11: // COP1
+ return describe_cop1(op, desc);
+
+ case 0x12: // COP2
+ return describe_cop2(op, desc);
+
+ case 0x13: // COP1X - MIPS IV
+ if (m_context.flavor < MIPS3_TYPE_MIPS_IV)
+ return false;
+ return describe_cop1x(op, desc);
+
+ case 0x1c: // IDT-specific opcodes: mad/madu/mul on R4640/4650, msub on RC32364
+ return describe_idt(op, desc);
+
+ case 0x02: // J
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ desc.targetpc = (desc.pc & 0xf0000000) | (LIMMVAL << 2);
+ desc.delayslots = 1;
+ return true;
+
+ case 0x03: // JAL
+ desc.regout[0] |= REGFLAG_R(31);
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ desc.targetpc = (desc.pc & 0xf0000000) | (LIMMVAL << 2);
+ desc.delayslots = 1;
+ return true;
+
+ case 0x04: // BEQ
+ case 0x05: // BNE
+ case 0x14: // BEQL
+ case 0x15: // BNEL
+ if ((opswitch == 0x04 || opswitch == 0x14) && RSREG == RTREG)
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ else
+ {
+ desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
+ desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
+ }
+ desc.targetpc = desc.pc + 4 + (SIMMVAL << 2);
+ desc.delayslots = 1;
+ desc.skipslots = (opswitch & 0x10) ? 1 : 0;
+ return true;
+
+ case 0x06: // BLEZ
+ case 0x07: // BGTZ
+ case 0x16: // BLEZL
+ case 0x17: // BGTZL
+ if ((opswitch == 0x06 || opswitch == 0x16) && RSREG == 0)
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ else
+ {
+ desc.regin[0] |= REGFLAG_R(RSREG);
+ desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
+ }
+ desc.targetpc = desc.pc + 4 + (SIMMVAL << 2);
+ desc.delayslots = 1;
+ desc.skipslots = (opswitch & 0x10) ? 1 : 0;
+ return true;
+
+ case 0x08: // ADDI
+ case 0x18: // DADDI
+ desc.regin[0] |= REGFLAG_R(RSREG);
+ desc.regout[0] |= REGFLAG_R(RTREG);
+ desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
+
+ case 0x09: // ADDIU
+ case 0x0a: // SLTI
+ case 0x0b: // SLTIU
+ case 0x0c: // ANDI
+ case 0x0d: // ORI
+ case 0x0e: // XORI
+ case 0x19: // DADDIU
+ desc.regin[0] |= REGFLAG_R(RSREG);
+ desc.regout[0] |= REGFLAG_R(RTREG);
+ return true;
+
+ case 0x0f: // LUI
+ desc.regout[0] |= REGFLAG_R(RTREG);
+ return true;
+
+ case 0x1a: // LDL
+ case 0x1b: // LDR
+ case 0x22: // LWL
+ case 0x26: // LWR
+ desc.regin[0] |= REGFLAG_R(RTREG);
+ case 0x20: // LB
+ case 0x21: // LH
+ case 0x23: // LW
+ case 0x24: // LBU
+ case 0x25: // LHU
+ case 0x27: // LWU
+ case 0x30: // LL
+ case 0x34: // LLD
+ case 0x37: // LD
+ desc.regin[0] |= REGFLAG_R(RSREG);
+ desc.regout[0] |= REGFLAG_R(RTREG);
+ desc.flags |= OPFLAG_READS_MEMORY | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
+
+ case 0x28: // SB
+ case 0x29: // SH
+ case 0x2a: // SWL
+ case 0x2b: // SW
+ case 0x2c: // SDL
+ case 0x2d: // SDR
+ case 0x2e: // SWR
+ case 0x3f: // SD
+ desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
+ desc.flags |= OPFLAG_WRITES_MEMORY | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
+
+ case 0x38: // SC
+ case 0x3c: // SCD
+ desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
+ desc.regout[0] |= REGFLAG_R(RTREG);
+ desc.flags |= OPFLAG_WRITES_MEMORY | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
+
+ case 0x31: // LWC1
+ case 0x35: // LDC1
+ desc.regin[0] |= REGFLAG_R(RSREG);
+ desc.regout[1] |= REGFLAG_CPR1(RTREG);
+ desc.flags |= OPFLAG_READS_MEMORY | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
+
+ case 0x39: // SWC1
+ case 0x3d: // SDC1
+ desc.regin[0] |= REGFLAG_R(RSREG);
+ desc.regin[1] |= REGFLAG_CPR1(RTREG);
+ desc.flags |= OPFLAG_WRITES_MEMORY | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
+
+ case 0x32: // LWC2
+ case 0x36: // LDC2
+ desc.regin[0] |= REGFLAG_R(RSREG);
+ desc.flags |= OPFLAG_READS_MEMORY | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
+
+ case 0x3a: // SWC2
+ case 0x3e: // SDC2
+ desc.regin[0] |= REGFLAG_R(RSREG);
+ desc.flags |= OPFLAG_WRITES_MEMORY | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
+
+ case 0x33: // PREF
+ if (m_context.flavor < MIPS3_TYPE_MIPS_IV)
+ return false;
+ case 0x2f: // CACHE
+ // effective no-op
+ return true;
+ }
+
+ return false;
+}
+
+
+//-------------------------------------------------
+// describe_special - build a description of a
+// single instruction in the 'special' group
+//-------------------------------------------------
+
+bool mips3_frontend::describe_special(UINT32 op, opcode_desc &desc)
+{
+ switch (op & 63)
+ {
+ case 0x00: // SLL
+ case 0x02: // SRL
+ case 0x03: // SRA
+ case 0x38: // DSLL
+ case 0x3a: // DSRL
+ case 0x3b: // DSRA
+ case 0x3c: // DSLL32
+ case 0x3e: // DSRL32
+ case 0x3f: // DSRA32
+ desc.regin[0] |= REGFLAG_R(RTREG);
+ desc.regout[0] |= REGFLAG_R(RDREG);
+ return true;
+
+ case 0x0a: // MOVZ - MIPS IV
+ case 0x0b: // MOVN - MIPS IV
+ if (m_context.flavor < MIPS3_TYPE_MIPS_IV)
+ return false;
+ desc.regin[0] |= REGFLAG_R(RDREG);
+ case 0x04: // SLLV
+ case 0x06: // SRLV
+ case 0x07: // SRAV
+ case 0x14: // DSLLV
+ case 0x16: // DSRLV
+ case 0x17: // DSRAV
+ case 0x21: // ADDU
+ case 0x23: // SUBU
+ case 0x24: // AND
+ case 0x25: // OR
+ case 0x26: // XOR
+ case 0x27: // NOR
+ case 0x2a: // SLT
+ case 0x2b: // SLTU
+ case 0x2d: // DADDU
+ case 0x2f: // DSUBU
+ desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
+ desc.regout[0] |= REGFLAG_R(RDREG);
+ return true;
+
+ case 0x20: // ADD
+ case 0x22: // SUB
+ case 0x2c: // DADD
+ case 0x2e: // DSUB
+ desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
+ desc.regout[0] |= REGFLAG_R(RDREG);
+ desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
+
+ case 0x30: // TGE
+ case 0x31: // TGEU
+ case 0x32: // TLT
+ case 0x33: // TLTU
+ case 0x34: // TEQ
+ case 0x36: // TNE
+ desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
+ desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
+
+ case 0x01: // MOVF - MIPS IV
+ if (m_context.flavor < MIPS3_TYPE_MIPS_IV)
+ return false;
+ desc.regin[0] |= REGFLAG_R(RSREG);
+ desc.regin[2] |= REGFLAG_FCC;
+ desc.regout[0] |= REGFLAG_R(RDREG);
+ return true;
+
+ case 0x08: // JR
+ desc.regin[0] |= REGFLAG_R(RSREG);
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ desc.targetpc = BRANCH_TARGET_DYNAMIC;
+ desc.delayslots = 1;
+ return true;
+
+ case 0x09: // JALR
+ desc.regin[0] |= REGFLAG_R(RSREG);
+ desc.regout[0] |= REGFLAG_R(RDREG);
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ desc.targetpc = BRANCH_TARGET_DYNAMIC;
+ desc.delayslots = 1;
+ return true;
+
+ case 0x10: // MFHI
+ desc.regin[0] |= REGFLAG_HI;
+ desc.regout[0] |= REGFLAG_R(RDREG);
+ return true;
+
+ case 0x11: // MTHI
+ desc.regin[0] |= REGFLAG_R(RSREG);
+ desc.regout[0] |= REGFLAG_HI;
+ return true;
+
+ case 0x12: // MFLO
+ desc.regin[2] |= REGFLAG_LO;
+ desc.regout[0] |= REGFLAG_R(RDREG);
+ return true;
+
+ case 0x13: // MTLO
+ desc.regin[0] |= REGFLAG_R(RSREG);
+ desc.regout[2] |= REGFLAG_LO;
+ return true;
+
+ case 0x18: // MULT
+ case 0x19: // MULTU
+ desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
+ desc.regout[2] |= REGFLAG_LO | REGFLAG_HI;
+ desc.cycles = 3;
+ return true;
+
+ case 0x1a: // DIV
+ case 0x1b: // DIVU
+ desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
+ desc.regout[2] |= REGFLAG_LO | REGFLAG_HI;
+ desc.cycles = 35;
+ return true;
+
+ case 0x1c: // DMULT
+ case 0x1d: // DMULTU
+ desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
+ desc.regout[2] |= REGFLAG_LO | REGFLAG_HI;
+ desc.cycles = 7;
+ return true;
+
+ case 0x1e: // DDIV
+ case 0x1f: // DDIVU
+ desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
+ desc.regout[2] |= REGFLAG_LO | REGFLAG_HI;
+ desc.cycles = 67;
+ return true;
+
+ case 0x0c: // SYSCALL
+ case 0x0d: // BREAK
+ desc.flags |= OPFLAG_WILL_CAUSE_EXCEPTION | OPFLAG_END_SEQUENCE;
+ return true;
+
+ case 0x0f: // SYNC
+ // effective no-op
+ return true;
+ }
+
+ return false;
+}
+
+
+//-------------------------------------------------
+// describe_regimm - build a description of a
+// single instruction in the 'regimm' group
+//-------------------------------------------------
+
+bool mips3_frontend::describe_regimm(UINT32 op, opcode_desc &desc)
+{
+ switch (RTREG)
+ {
+ case 0x00: // BLTZ
+ case 0x01: // BGEZ
+ case 0x02: // BLTZL
+ case 0x03: // BGEZL
+ if (RTREG == 0x01 && RSREG == 0)
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ else
+ {
+ desc.regin[0] |= REGFLAG_R(RSREG);
+ desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
+ }
+ desc.targetpc = desc.pc + 4 + (SIMMVAL << 2);
+ desc.delayslots = 1;
+ desc.skipslots = (RTREG & 0x02) ? 1 : 0;
+ return true;
+
+ case 0x08: // TGEI
+ case 0x09: // TGEIU
+ case 0x0a: // TLTI
+ case 0x0b: // TLTIU
+ case 0x0c: // TEQI
+ case 0x0e: // TNEI
+ desc.regin[0] |= REGFLAG_R(RSREG);
+ desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
+ return true;
+
+ case 0x10: // BLTZAL
+ case 0x11: // BGEZAL
+ case 0x12: // BLTZALL
+ case 0x13: // BGEZALL
+ if (RTREG == 0x11 && RSREG == 0)
+ desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ else
+ {
+ desc.regin[0] |= REGFLAG_R(RSREG);
+ desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
+ }
+ desc.regout[0] |= REGFLAG_R(31);
+ desc.targetpc = desc.pc + 4 + (SIMMVAL << 2);
+ desc.delayslots = 1;
+ desc.skipslots = (RTREG & 0x02) ? 1 : 0;
+ return true;
+ }
+
+ return false;
+}
+
+
+//-------------------------------------------------
+// describe_idt - build a description of a single
+// instruction in the IDT-specific group
+//-------------------------------------------------
+
+bool mips3_frontend::describe_idt(UINT32 op, opcode_desc &desc)
+{
+ // only on the R4650
+ if (m_context.flavor != MIPS3_TYPE_R4650)
+ return false;
+
+ switch (op & 0x1f)
+ {
+ case 0: // MAD
+ case 1: // MADU
+ desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
+ desc.regin[2] |= REGFLAG_LO | REGFLAG_HI;
+ desc.regout[2] |= REGFLAG_LO | REGFLAG_HI;
+ return true;
+
+ case 2: // MUL
+ desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
+ desc.regout[0] |= REGFLAG_R(RDREG);
+ desc.cycles = 3;
+ return true;
+ }
+
+ return false;
+}
+
+
+//-------------------------------------------------
+// describe_cop0 - build a description of a
+// single instruction in the COP0 group
+//-------------------------------------------------
+
+bool mips3_frontend::describe_cop0(UINT32 op, opcode_desc &desc)
+{
+ // any COP0 instruction can potentially cause an exception
+ desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
+
+ switch (RSREG)
+ {
+ case 0x00: // MFCz
+ case 0x01: // DMFCz
+ if (RDREG == COP0_Count)
+ desc.cycles += MIPS3_COUNT_READ_CYCLES;
+ if (RDREG == COP0_Cause)
+ desc.cycles += MIPS3_CAUSE_READ_CYCLES;
+ desc.regout[0] |= REGFLAG_R(RTREG);
+ return true;
+
+ case 0x02: // CFCz
+ desc.regout[0] |= REGFLAG_R(RTREG);
+ return true;
+
+ case 0x04: // MTCz
+ case 0x05: // DMTCz
+ case 0x06: // CTCz
+ desc.regin[0] |= REGFLAG_R(RTREG);
+ if (RSREG == 0x04 || RSREG == 0x05)
+ {
+ if (RDREG == COP0_Cause)
+ desc.flags |= OPFLAG_CAN_TRIGGER_SW_INT;
+ if (RDREG == COP0_Status)
+ desc.flags |= OPFLAG_CAN_EXPOSE_EXTERNAL_INT | OPFLAG_CAN_CHANGE_MODES | OPFLAG_END_SEQUENCE;
+ }
+ return true;
+
+ case 0x08: // BC
+ switch (RTREG)
+ {
+ case 0x00: // BCzF
+ case 0x01: // BCzT
+ desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
+ desc.targetpc = desc.pc + 4 + (SIMMVAL << 2);
+ desc.delayslots = 1;
+ return true;
+ }
+ return false;
+
+ case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
+ case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: // COP
+ switch (op & 0x01ffffff)
+ {
+ case 0x01: // TLBR
+ case 0x08: // TLBP
+ case 0x20: // WAIT
+ return true;
+
+ case 0x02: // TLBWI
+ case 0x06: // TLBWR
+ desc.flags |= OPFLAG_MODIFIES_TRANSLATION;
+ return true;
+
+ case 0x18: // ERET
+ desc.flags |= OPFLAG_CAN_CHANGE_MODES | OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ return true;
+ }
+ return false;
+ }
+
+ return false;
+}
+
+
+//-------------------------------------------------
+// describe_cop1 - build a description of a
+// single instruction in the COP1 group
+//-------------------------------------------------
+
+bool mips3_frontend::describe_cop1(UINT32 op, opcode_desc &desc)
+{
+ // any COP1 instruction can potentially cause an exception
+// desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
+
+ switch (RSREG)
+ {
+ case 0x00: // MFCz
+ case 0x01: // DMFCz
+ desc.regin[1] |= REGFLAG_CPR1(RDREG);
+ desc.regout[0] |= REGFLAG_R(RTREG);
+ return true;
+
+ case 0x02: // CFCz
+ desc.regout[0] |= REGFLAG_R(RTREG);
+ return true;
+
+ case 0x04: // MTCz
+ case 0x05: // DMTCz
+ desc.regin[0] |= REGFLAG_R(RTREG);
+ desc.regout[1] |= REGFLAG_CPR1(RDREG);
+ return true;
+
+ case 0x06: // CTCz
+ desc.regin[0] |= REGFLAG_R(RTREG);
+ return true;
+
+ case 0x08: // BC
+ switch (RTREG & 3)
+ {
+ case 0x00: // BCzF
+ case 0x01: // BCzT
+ case 0x02: // BCzFL
+ case 0x03: // BCzTL
+ desc.regin[2] |= REGFLAG_FCC;
+ desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
+ desc.targetpc = desc.pc + 4 + (SIMMVAL << 2);
+ desc.delayslots = 1;
+ desc.skipslots = (RTREG & 0x02) ? 1 : 0;
+ return true;
+ }
+ return false;
+
+ case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
+ case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: // COP
+ switch (op & 0x3f)
+ {
+ case 0x12: // MOVZ - MIPS IV
+ case 0x13: // MOVN - MIPS IV
+ if (m_context.flavor < MIPS3_TYPE_MIPS_IV)
+ return false;
+ case 0x00: // ADD
+ case 0x01: // SUB
+ case 0x02: // MUL
+ case 0x03: // DIV
+ desc.regin[1] |= REGFLAG_CPR1(FSREG) | REGFLAG_CPR1(FTREG);
+ desc.regout[1] |= REGFLAG_CPR1(FDREG);
+ return true;
+
+ case 0x15: // RECIP - MIPS IV
+ case 0x16: // RSQRT - MIPS IV
+ if (m_context.flavor < MIPS3_TYPE_MIPS_IV)
+ return false;
+ case 0x04: // SQRT
+ case 0x05: // ABS
+ case 0x06: // MOV
+ case 0x07: // NEG
+ case 0x08: // ROUND.L
+ case 0x09: // TRUNC.L
+ case 0x0a: // CEIL.L
+ case 0x0b: // FLOOR.L
+ case 0x0c: // ROUND.W
+ case 0x0d: // TRUNC.W
+ case 0x0e: // CEIL.W
+ case 0x0f: // FLOOR.W
+ case 0x20: // CVT.S
+ case 0x21: // CVT.D
+ case 0x24: // CVT.W
+ case 0x25: // CVT.L
+ desc.regin[1] |= REGFLAG_CPR1(FSREG);
+ desc.regout[1] |= REGFLAG_CPR1(FDREG);
+ return true;
+
+ case 0x11: // MOVT/F - MIPS IV
+ if (m_context.flavor < MIPS3_TYPE_MIPS_IV)
+ return false;
+ desc.regin[1] |= REGFLAG_CPR1(FSREG);
+ desc.regin[2] |= REGFLAG_FCC;
+ desc.regout[1] |= REGFLAG_CPR1(FDREG);
+ return true;
+
+ case 0x30: case 0x38: // C.F
+ case 0x31: case 0x39: // C.UN
+ desc.regout[2] |= REGFLAG_FCC;
+ return true;
+
+ case 0x32: case 0x3a: // C.EQ
+ case 0x33: case 0x3b: // C.UEQ
+ case 0x34: case 0x3c: // C.OLT
+ case 0x35: case 0x3d: // C.ULT
+ case 0x36: case 0x3e: // C.OLE
+ case 0x37: case 0x3f: // C.ULE
+ desc.regin[1] |= REGFLAG_CPR1(FSREG) | REGFLAG_CPR1(FTREG);
+ desc.regout[2] |= REGFLAG_FCC;
+ return true;
+ }
+ return false;
+ }
+
+ return false;
+}
+
+
+//-------------------------------------------------
+// describe_cop1x - build a description of a
+// single instruction in the COP1X group
+//-------------------------------------------------
+
+bool mips3_frontend::describe_cop1x(UINT32 op, opcode_desc &desc)
+{
+ // any COP1 instruction can potentially cause an exception
+// desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
+
+ switch (op & 0x3f)
+ {
+ case 0x00: // LWXC1
+ case 0x01: // LDXC1
+ desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
+ desc.regout[1] |= REGFLAG_CPR1(FDREG);
+ desc.flags |= OPFLAG_READS_MEMORY;
+ return true;
+
+ case 0x08: // SWXC1
+ case 0x09: // SDXC1
+ desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
+ desc.regin[1] |= REGFLAG_CPR1(FDREG);
+ desc.flags |= OPFLAG_WRITES_MEMORY;
+ return true;
+
+ case 0x0f: // PREFX
+ // effective no-op
+ return true;
+
+ case 0x20: case 0x21: // MADD
+ case 0x28: case 0x29: // MSUB
+ case 0x30: case 0x31: // NMADD
+ case 0x38: case 0x39: // NMSUB
+ desc.regin[1] |= REGFLAG_CPR1(FSREG) | REGFLAG_CPR1(FTREG) | REGFLAG_CPR1(FRREG);
+ desc.regout[1] |= REGFLAG_CPR1(FDREG);
+ return true;
+ }
+
+ return false;
+}
+
+
+//-------------------------------------------------
+// describe_cop2 - build a description of a
+// single instruction in the COP2 group
+//-------------------------------------------------
+
+bool mips3_frontend::describe_cop2(UINT32 op, opcode_desc &desc)
+{
+ // any COP2 instruction can potentially cause an exception
+ desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
+
+ switch (RSREG)
+ {
+ case 0x00: // MFCz
+ case 0x01: // DMFCz
+ case 0x02: // CFCz
+ desc.regout[0] |= REGFLAG_R(RTREG);
+ return true;
+
+ case 0x04: // MTCz
+ case 0x05: // DMTCz
+ case 0x06: // CTCz
+ desc.regin[0] |= REGFLAG_R(RTREG);
+ return true;
+
+ case 0x08: // BC
+ switch (RTREG)
+ {
+ case 0x00: // BCzF
+ case 0x01: // BCzT
+ desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
+ desc.targetpc = desc.pc + 4 + (SIMMVAL << 2);
+ desc.delayslots = 1;
+ return true;
+ }
+ return false;
+ }
+
+ return false;
+}
diff --git a/trunk/src/emu/cpu/mips/mips3fe.h b/trunk/src/emu/cpu/mips/mips3fe.h
new file mode 100644
index 00000000000..aefcc676795
--- /dev/null
+++ b/trunk/src/emu/cpu/mips/mips3fe.h
@@ -0,0 +1,95 @@
+/***************************************************************************
+
+ mips3fe.h
+
+ Front-end for MIPS3 recompiler
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __MIPS3FE_H__
+#define __MIPS3FE_H__
+
+#include "mips3com.h"
+#include "cpu/drcfe.h"
+
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+// register flags 0
+#define REGFLAG_R(n) (((n) == 0) ? 0 : (1 << (n)))
+
+// register flags 1
+#define REGFLAG_CPR1(n) (1 << (n))
+
+// register flags 2
+#define REGFLAG_LO (1 << 0)
+#define REGFLAG_HI (1 << 1)
+#define REGFLAG_FCC (1 << 2)
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class mips3_frontend : public drc_frontend
+{
+public:
+ // construction/destruction
+ mips3_frontend(mips3_state &state, UINT32 window_start, UINT32 window_end, UINT32 max_sequence);
+
+protected:
+ // required overrides
+ virtual bool describe(opcode_desc &desc, const opcode_desc *prev);
+
+private:
+ // internal helpers
+ bool describe_special(UINT32 op, opcode_desc &desc);
+ bool describe_regimm(UINT32 op, opcode_desc &desc);
+ bool describe_idt(UINT32 op, opcode_desc &desc);
+ bool describe_cop0(UINT32 op, opcode_desc &desc);
+ bool describe_cop1(UINT32 op, opcode_desc &desc);
+ bool describe_cop1x(UINT32 op, opcode_desc &desc);
+ bool describe_cop2(UINT32 op, opcode_desc &desc);
+
+ // internal state
+ mips3_state &m_context;
+};
+
+
+#endif /* __MIPS3FE_H__ */
diff --git a/trunk/src/emu/cpu/mips/r3000.c b/trunk/src/emu/cpu/mips/r3000.c
new file mode 100644
index 00000000000..e28bc8bee47
--- /dev/null
+++ b/trunk/src/emu/cpu/mips/r3000.c
@@ -0,0 +1,1377 @@
+/***************************************************************************
+
+ r3000->c
+ Core implementation for the portable MIPS R3000 emulator.
+ Written by Aaron Giles
+
+***************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "r3000.h"
+
+CPU_DISASSEMBLE( r3000be );
+CPU_DISASSEMBLE( r3000le );
+
+#define ENABLE_OVERFLOWS 0
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define COP0_Index 0
+#define COP0_Random 1
+#define COP0_EntryLo 2
+#define COP0_Context 4
+#define COP0_BadVAddr 8
+#define COP0_Status 12
+#define COP0_Cause 13
+#define COP0_EPC 14
+#define COP0_PRId 15
+
+#define SR_IEc 0x00000001
+#define SR_KUc 0x00000002
+#define SR_IEp 0x00000004
+#define SR_KUp 0x00000008
+#define SR_IEo 0x00000010
+#define SR_KUo 0x00000020
+#define SR_IMSW0 0x00000100
+#define SR_IMSW1 0x00000200
+#define SR_IMEX0 0x00000400
+#define SR_IMEX1 0x00000800
+#define SR_IMEX2 0x00001000
+#define SR_IMEX3 0x00002000
+#define SR_IMEX4 0x00004000
+#define SR_IMEX5 0x00008000
+#define SR_IsC 0x00010000
+#define SR_SwC 0x00020000
+#define SR_PZ 0x00040000
+#define SR_CM 0x00080000
+#define SR_PE 0x00100000
+#define SR_TS 0x00200000
+#define SR_BEV 0x00400000
+#define SR_RE 0x02000000
+#define SR_COP0 0x10000000
+#define SR_COP1 0x20000000
+#define SR_COP2 0x40000000
+#define SR_COP3 0x80000000
+
+#define EXCEPTION_INTERRUPT 0
+#define EXCEPTION_TLBMOD 1
+#define EXCEPTION_TLBLOAD 2
+#define EXCEPTION_TLBSTORE 3
+#define EXCEPTION_ADDRLOAD 4
+#define EXCEPTION_ADDRSTORE 5
+#define EXCEPTION_BUSINST 6
+#define EXCEPTION_BUSDATA 7
+#define EXCEPTION_SYSCALL 8
+#define EXCEPTION_BREAK 9
+#define EXCEPTION_INVALIDOP 10
+#define EXCEPTION_BADCOP 11
+#define EXCEPTION_OVERFLOW 12
+#define EXCEPTION_TRAP 13
+
+
+
+/***************************************************************************
+ HELPER MACROS
+***************************************************************************/
+
+#define RSREG ((op >> 21) & 31)
+#define RTREG ((op >> 16) & 31)
+#define RDREG ((op >> 11) & 31)
+#define SHIFT ((op >> 6) & 31)
+
+#define RSVAL r[RSREG]
+#define RTVAL r[RTREG]
+#define RDVAL r[RDREG]
+
+#define SIMMVAL ((INT16)op)
+#define UIMMVAL ((UINT16)op)
+#define LIMMVAL (op & 0x03ffffff)
+
+#define ADDPC(R,x) do { (R)->nextpc = (R)->pc + ((x) << 2); } while (0)
+#define ADDPCL(R,x,l) do { (R)->nextpc = (R)->pc + ((x) << 2); (R)->r[l] = (R)->pc + 4; } while (0)
+#define ABSPC(R,x) do { (R)->nextpc = ((R)->pc & 0xf0000000) | ((x) << 2); } while (0)
+#define ABSPCL(R,x,l) do { (R)->nextpc = ((R)->pc & 0xf0000000) | ((x) << 2); (R)->r[l] = (R)->pc + 4; } while (0)
+#define SETPC(R,x) do { (R)->nextpc = (x); } while (0)
+#define SETPCL(R,x,l) do { (R)->nextpc = (x); (R)->r[l] = (R)->pc + 4; } while (0)
+
+#define RBYTE(R,x) (*(R)->cur.read_byte)((R)->program, x)
+#define RWORD(R,x) (*(R)->cur.read_word)((R)->program, x)
+#define RLONG(R,x) (*(R)->cur.read_dword)((R)->program, x)
+
+#define WBYTE(R,x,v) (*(R)->cur.write_byte)((R)->program, x, v)
+#define WWORD(R,x,v) (*(R)->cur.write_word)((R)->program, x, v)
+#define WLONG(R,x,v) (*(R)->cur.write_dword)((R)->program, x, v)
+
+#define SR cpr[0][COP0_Status]
+#define CAUSE cpr[0][COP0_Cause]
+
+
+
+/***************************************************************************
+ STRUCTURES & TYPEDEFS
+***************************************************************************/
+
+/* R3000 Registers */
+typedef struct _r3000_state r3000_state;
+struct _r3000_state
+{
+ /* core registers */
+ UINT32 pc;
+ UINT32 hi;
+ UINT32 lo;
+ UINT32 r[32];
+
+ /* COP registers */
+ UINT32 cpr[4][32];
+ UINT32 ccr[4][32];
+ UINT8 cf[4];
+
+ /* internal stuff */
+ UINT32 ppc;
+ UINT32 nextpc;
+ int op;
+ int icount;
+ int interrupt_cycles;
+ int hasfpu;
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+
+ /* endian-dependent load/store */
+ void (*lwl)(r3000_state *r3000, UINT32 op);
+ void (*lwr)(r3000_state *r3000, UINT32 op);
+ void (*swl)(r3000_state *r3000, UINT32 op);
+ void (*swr)(r3000_state *r3000, UINT32 op);
+
+ /* memory accesses */
+ UINT8 bigendian;
+ data_accessors cur;
+ data_accessors memory_hand;
+ const data_accessors *cache_hand;
+
+ /* cache memory */
+ UINT32 * cache;
+ UINT32 * icache;
+ UINT32 * dcache;
+ size_t cache_size;
+ size_t icache_size;
+ size_t dcache_size;
+};
+
+INLINE r3000_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == R3000BE ||
+ device->type() == R3000LE ||
+ device->type() == R3041BE ||
+ device->type() == R3041LE);
+ return (r3000_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static void lwl_be(r3000_state *r3000, UINT32 op);
+static void lwr_be(r3000_state *r3000, UINT32 op);
+static void swl_be(r3000_state *r3000, UINT32 op);
+static void swr_be(r3000_state *r3000, UINT32 op);
+
+static void lwl_le(r3000_state *r3000, UINT32 op);
+static void lwr_le(r3000_state *r3000, UINT32 op);
+static void swl_le(r3000_state *r3000, UINT32 op);
+static void swr_le(r3000_state *r3000, UINT32 op);
+
+static UINT8 readcache_be(address_space *space, offs_t offset);
+static UINT16 readcache_be_word(address_space *space, offs_t offset);
+static UINT32 readcache_be_dword(address_space *space, offs_t offset);
+static void writecache_be(address_space *space, offs_t offset, UINT8 data);
+static void writecache_be_word(address_space *space, offs_t offset, UINT16 data);
+static void writecache_be_dword(address_space *space, offs_t offset, UINT32 data);
+
+static UINT8 readcache_le(address_space *space, offs_t offset);
+static UINT16 readcache_le_word(address_space *space, offs_t offset);
+static UINT32 readcache_le_dword(address_space *space, offs_t offset);
+static void writecache_le(address_space *space, offs_t offset, UINT8 data);
+static void writecache_le_word(address_space *space, offs_t offset, UINT16 data);
+static void writecache_le_dword(address_space *space, offs_t offset, UINT32 data);
+
+
+
+/***************************************************************************
+ PRIVATE GLOBAL VARIABLES
+***************************************************************************/
+
+static const data_accessors be_cache =
+{
+ readcache_be, readcache_be_word, NULL, readcache_be_dword, NULL, NULL, NULL,
+ writecache_be, writecache_be_word, NULL, writecache_be_dword, NULL, NULL, NULL
+};
+
+static const data_accessors le_cache =
+{
+ readcache_le, readcache_le_word, NULL, readcache_le_dword, NULL, NULL, NULL,
+ writecache_le, writecache_le_word, NULL, writecache_le_dword, NULL, NULL, NULL
+};
+
+
+
+/***************************************************************************
+ MEMORY ACCESSORS
+***************************************************************************/
+
+#define ROPCODE(R,pc) (R)->direct->read_decrypted_dword(pc)
+
+
+
+/***************************************************************************
+ EXECEPTION HANDLING
+***************************************************************************/
+
+INLINE void generate_exception(r3000_state *r3000, int exception)
+{
+ /* set the exception PC */
+ r3000->cpr[0][COP0_EPC] = r3000->pc;
+
+ /* put the cause in the low 8 bits and clear the branch delay flag */
+ r3000->CAUSE = (r3000->CAUSE & ~0x800000ff) | (exception << 2);
+
+ /* if we were in a branch delay slot, adjust */
+ if (r3000->nextpc != ~0)
+ {
+ r3000->nextpc = ~0;
+ r3000->cpr[0][COP0_EPC] -= 4;
+ r3000->CAUSE |= 0x80000000;
+ }
+
+ /* shift the exception bits */
+ r3000->SR = (r3000->SR & 0xffffffc0) | ((r3000->SR << 2) & 0x3c);
+
+ /* based on the BEV bit, we either go to ROM or RAM */
+ r3000->pc = (r3000->SR & SR_BEV) ? 0xbfc00000 : 0x80000000;
+
+ /* most exceptions go to offset 0x180, except for TLB stuff */
+ if (exception >= EXCEPTION_TLBMOD && exception <= EXCEPTION_TLBSTORE)
+ r3000->pc += 0x80;
+ else
+ r3000->pc += 0x180;
+}
+
+
+INLINE void invalid_instruction(r3000_state *r3000, UINT32 op)
+{
+ generate_exception(r3000, EXCEPTION_INVALIDOP);
+}
+
+
+
+/***************************************************************************
+ IRQ HANDLING
+***************************************************************************/
+
+static void check_irqs(r3000_state *r3000)
+{
+ if ((r3000->CAUSE & r3000->SR & 0xff00) && (r3000->SR & SR_IEc))
+ generate_exception(r3000, EXCEPTION_INTERRUPT);
+}
+
+
+static void set_irq_line(r3000_state *r3000, int irqline, int state)
+{
+ if (state != CLEAR_LINE)
+ r3000->CAUSE |= 0x400 << irqline;
+ else
+ r3000->CAUSE &= ~(0x400 << irqline);
+ check_irqs(r3000);
+}
+
+
+
+/***************************************************************************
+ INITIALIZATION AND SHUTDOWN
+***************************************************************************/
+
+static CPU_INIT( r3000 )
+{
+ const r3000_cpu_core *configdata = (const r3000_cpu_core *)device->static_config();
+ r3000_state *r3000 = get_safe_token(device);
+
+ /* allocate memory */
+ r3000->icache = auto_alloc_array(device->machine(), UINT32, configdata->icache/4);
+ r3000->dcache = auto_alloc_array(device->machine(), UINT32, configdata->dcache/4);
+
+ r3000->icache_size = configdata->icache;
+ r3000->dcache_size = configdata->dcache;
+ r3000->hasfpu = configdata->hasfpu;
+
+ r3000->irq_callback = irqcallback;
+ r3000->device = device;
+ r3000->program = device->space(AS_PROGRAM);
+ r3000->direct = &r3000->program->direct();
+}
+
+
+static void r3000_reset(r3000_state *r3000, int bigendian)
+{
+ /* set up the endianness */
+ r3000->bigendian = bigendian;
+ r3000->program->accessors(r3000->memory_hand);
+ if (r3000->bigendian)
+ {
+ r3000->cache_hand = &be_cache;
+ r3000->lwl = lwl_be;
+ r3000->lwr = lwr_be;
+ r3000->swl = swl_be;
+ r3000->swr = swr_be;
+ }
+ else
+ {
+ r3000->cache_hand = &le_cache;
+ r3000->lwl = lwl_le;
+ r3000->lwr = lwr_le;
+ r3000->swl = swl_le;
+ r3000->swr = swr_le;
+ }
+
+ /* initialize the rest of the config */
+ r3000->cur = r3000->memory_hand;
+ r3000->cache = r3000->dcache;
+ r3000->cache_size = r3000->dcache_size;
+
+ /* initialize the state */
+ r3000->pc = 0xbfc00000;
+ r3000->nextpc = ~0;
+ r3000->cpr[0][COP0_PRId] = 0x0200;
+ r3000->cpr[0][COP0_Status] = 0x0000;
+}
+
+static CPU_RESET( r3000be )
+{
+ r3000_reset(get_safe_token(device), 1);
+}
+
+static CPU_RESET( r3000le )
+{
+ r3000_reset(get_safe_token(device), 0);
+}
+
+
+static CPU_EXIT( r3000 )
+{
+}
+
+
+
+/***************************************************************************
+ COP0 (SYSTEM) EXECUTION HANDLING
+***************************************************************************/
+
+INLINE UINT32 get_cop0_reg(r3000_state *r3000, int idx)
+{
+ return r3000->cpr[0][idx];
+}
+
+INLINE void set_cop0_reg(r3000_state *r3000, int idx, UINT32 val)
+{
+ if (idx == COP0_Cause)
+ {
+ r3000->CAUSE = (r3000->CAUSE & 0xfc00) | (val & ~0xfc00);
+
+ /* update interrupts -- software ints can occur this way */
+ check_irqs(r3000);
+ }
+ else if (idx == COP0_Status)
+ {
+ UINT32 oldsr = r3000->cpr[0][idx];
+ UINT32 diff = oldsr ^ val;
+
+ /* handle cache isolation */
+ if (diff & SR_IsC)
+ {
+ if (val & SR_IsC)
+ r3000->cur = *r3000->cache_hand;
+ else
+ r3000->cur = r3000->memory_hand;
+ }
+
+ /* handle cache switching */
+ if (diff & SR_SwC)
+ {
+ if (val & SR_SwC)
+ r3000->cache = r3000->icache, r3000->cache_size = r3000->icache_size;
+ else
+ r3000->cache = r3000->dcache, r3000->cache_size = r3000->dcache_size;
+ }
+ r3000->cpr[0][idx] = val;
+
+ /* update interrupts */
+ check_irqs(r3000);
+ }
+ else
+ r3000->cpr[0][idx] = val;
+}
+
+INLINE UINT32 get_cop0_creg(r3000_state *r3000, int idx)
+{
+ return r3000->ccr[0][idx];
+}
+
+INLINE void set_cop0_creg(r3000_state *r3000, int idx, UINT32 val)
+{
+ r3000->ccr[0][idx] = val;
+}
+
+INLINE void handle_cop0(r3000_state *r3000, UINT32 op)
+{
+ if (!(r3000->SR & SR_COP0) && (r3000->SR & SR_KUc))
+ generate_exception(r3000, EXCEPTION_BADCOP);
+
+ switch (RSREG)
+ {
+ case 0x00: /* MFCz */ if (RTREG) r3000->RTVAL = get_cop0_reg(r3000, RDREG); break;
+ case 0x02: /* CFCz */ if (RTREG) r3000->RTVAL = get_cop0_creg(r3000, RDREG); break;
+ case 0x04: /* MTCz */ set_cop0_reg(r3000, RDREG, r3000->RTVAL); break;
+ case 0x06: /* CTCz */ set_cop0_creg(r3000, RDREG, r3000->RTVAL); break;
+ case 0x08: /* BC */
+ switch (RTREG)
+ {
+ case 0x00: /* BCzF */ if (!r3000->cf[0]) ADDPC(r3000, SIMMVAL); break;
+ case 0x01: /* BCzF */ if (r3000->cf[0]) ADDPC(r3000, SIMMVAL); break;
+ case 0x02: /* BCzFL */ invalid_instruction(r3000, op); break;
+ case 0x03: /* BCzTL */ invalid_instruction(r3000, op); break;
+ default: invalid_instruction(r3000, op); break;
+ }
+ break;
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ case 0x13:
+ case 0x14:
+ case 0x15:
+ case 0x16:
+ case 0x17:
+ case 0x18:
+ case 0x19:
+ case 0x1a:
+ case 0x1b:
+ case 0x1c:
+ case 0x1d:
+ case 0x1e:
+ case 0x1f: /* COP */
+ switch (op & 0x01ffffff)
+ {
+ case 0x01: /* TLBR */ break;
+ case 0x02: /* TLBWI */ break;
+ case 0x06: /* TLBWR */ break;
+ case 0x08: /* TLBP */ break;
+ case 0x10: /* RFE */ r3000->SR = (r3000->SR & 0xfffffff0) | ((r3000->SR >> 2) & 0x0f); break;
+ case 0x18: /* ERET */ invalid_instruction(r3000, op); break;
+ default: invalid_instruction(r3000, op); break;
+ }
+ break;
+ default: invalid_instruction(r3000, op); break;
+ }
+}
+
+
+
+/***************************************************************************
+ COP1 (FPU) EXECUTION HANDLING
+***************************************************************************/
+
+INLINE UINT32 get_cop1_reg(r3000_state *r3000, int idx)
+{
+ return r3000->cpr[1][idx];
+}
+
+INLINE void set_cop1_reg(r3000_state *r3000, int idx, UINT32 val)
+{
+ r3000->cpr[1][idx] = val;
+}
+
+INLINE UINT32 get_cop1_creg(r3000_state *r3000, int idx)
+{
+ return r3000->ccr[1][idx];
+}
+
+INLINE void set_cop1_creg(r3000_state *r3000, int idx, UINT32 val)
+{
+ r3000->ccr[1][idx] = val;
+}
+
+INLINE void handle_cop1(r3000_state *r3000, UINT32 op)
+{
+ if (!(r3000->SR & SR_COP1))
+ generate_exception(r3000, EXCEPTION_BADCOP);
+ if (!r3000->hasfpu)
+ return;
+
+ switch (RSREG)
+ {
+ case 0x00: /* MFCz */ if (RTREG) r3000->RTVAL = get_cop1_reg(r3000, RDREG); break;
+ case 0x02: /* CFCz */ if (RTREG) r3000->RTVAL = get_cop1_creg(r3000, RDREG); break;
+ case 0x04: /* MTCz */ set_cop1_reg(r3000, RDREG, r3000->RTVAL); break;
+ case 0x06: /* CTCz */ set_cop1_creg(r3000, RDREG, r3000->RTVAL); break;
+ case 0x08: /* BC */
+ switch (RTREG)
+ {
+ case 0x00: /* BCzF */ if (!r3000->cf[1]) ADDPC(r3000, SIMMVAL); break;
+ case 0x01: /* BCzF */ if (r3000->cf[1]) ADDPC(r3000, SIMMVAL); break;
+ case 0x02: /* BCzFL */ invalid_instruction(r3000, op); break;
+ case 0x03: /* BCzTL */ invalid_instruction(r3000, op); break;
+ default: invalid_instruction(r3000, op); break;
+ }
+ break;
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ case 0x13:
+ case 0x14:
+ case 0x15:
+ case 0x16:
+ case 0x17:
+ case 0x18:
+ case 0x19:
+ case 0x1a:
+ case 0x1b:
+ case 0x1c:
+ case 0x1d:
+ case 0x1e:
+ case 0x1f: /* COP */ invalid_instruction(r3000, op); break;
+ default: invalid_instruction(r3000, op); break;
+ }
+}
+
+
+
+/***************************************************************************
+ COP2 (CUSTOM) EXECUTION HANDLING
+***************************************************************************/
+
+INLINE UINT32 get_cop2_reg(r3000_state *r3000, int idx)
+{
+ return r3000->cpr[2][idx];
+}
+
+INLINE void set_cop2_reg(r3000_state *r3000, int idx, UINT32 val)
+{
+ r3000->cpr[2][idx] = val;
+}
+
+INLINE UINT32 get_cop2_creg(r3000_state *r3000, int idx)
+{
+ return r3000->ccr[2][idx];
+}
+
+INLINE void set_cop2_creg(r3000_state *r3000, int idx, UINT32 val)
+{
+ r3000->ccr[2][idx] = val;
+}
+
+INLINE void handle_cop2(r3000_state *r3000, UINT32 op)
+{
+ if (!(r3000->SR & SR_COP2))
+ generate_exception(r3000, EXCEPTION_BADCOP);
+
+ switch (RSREG)
+ {
+ case 0x00: /* MFCz */ if (RTREG) r3000->RTVAL = get_cop2_reg(r3000, RDREG); break;
+ case 0x02: /* CFCz */ if (RTREG) r3000->RTVAL = get_cop2_creg(r3000, RDREG); break;
+ case 0x04: /* MTCz */ set_cop2_reg(r3000, RDREG, r3000->RTVAL); break;
+ case 0x06: /* CTCz */ set_cop2_creg(r3000, RDREG, r3000->RTVAL); break;
+ case 0x08: /* BC */
+ switch (RTREG)
+ {
+ case 0x00: /* BCzF */ if (!r3000->cf[2]) ADDPC(r3000, SIMMVAL); break;
+ case 0x01: /* BCzF */ if (r3000->cf[2]) ADDPC(r3000, SIMMVAL); break;
+ case 0x02: /* BCzFL */ invalid_instruction(r3000, op); break;
+ case 0x03: /* BCzTL */ invalid_instruction(r3000, op); break;
+ default: invalid_instruction(r3000, op); break;
+ }
+ break;
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ case 0x13:
+ case 0x14:
+ case 0x15:
+ case 0x16:
+ case 0x17:
+ case 0x18:
+ case 0x19:
+ case 0x1a:
+ case 0x1b:
+ case 0x1c:
+ case 0x1d:
+ case 0x1e:
+ case 0x1f: /* COP */ invalid_instruction(r3000, op); break;
+ default: invalid_instruction(r3000, op); break;
+ }
+}
+
+
+
+/***************************************************************************
+ COP3 (CUSTOM) EXECUTION HANDLING
+***************************************************************************/
+
+INLINE UINT32 get_cop3_reg(r3000_state *r3000, int idx)
+{
+ return r3000->cpr[3][idx];
+}
+
+INLINE void set_cop3_reg(r3000_state *r3000, int idx, UINT32 val)
+{
+ r3000->cpr[3][idx] = val;
+}
+
+INLINE UINT32 get_cop3_creg(r3000_state *r3000, int idx)
+{
+ return r3000->ccr[3][idx];
+}
+
+INLINE void set_cop3_creg(r3000_state *r3000, int idx, UINT32 val)
+{
+ r3000->ccr[3][idx] = val;
+}
+
+INLINE void handle_cop3(r3000_state *r3000, UINT32 op)
+{
+ if (!(r3000->SR & SR_COP3))
+ generate_exception(r3000, EXCEPTION_BADCOP);
+
+ switch (RSREG)
+ {
+ case 0x00: /* MFCz */ if (RTREG) r3000->RTVAL = get_cop3_reg(r3000, RDREG); break;
+ case 0x02: /* CFCz */ if (RTREG) r3000->RTVAL = get_cop3_creg(r3000, RDREG); break;
+ case 0x04: /* MTCz */ set_cop3_reg(r3000, RDREG, r3000->RTVAL); break;
+ case 0x06: /* CTCz */ set_cop3_creg(r3000, RDREG, r3000->RTVAL); break;
+ case 0x08: /* BC */
+ switch (RTREG)
+ {
+ case 0x00: /* BCzF */ if (!r3000->cf[3]) ADDPC(r3000, SIMMVAL); break;
+ case 0x01: /* BCzF */ if (r3000->cf[3]) ADDPC(r3000, SIMMVAL); break;
+ case 0x02: /* BCzFL */ invalid_instruction(r3000, op); break;
+ case 0x03: /* BCzTL */ invalid_instruction(r3000, op); break;
+ default: invalid_instruction(r3000, op); break;
+ }
+ break;
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ case 0x13:
+ case 0x14:
+ case 0x15:
+ case 0x16:
+ case 0x17:
+ case 0x18:
+ case 0x19:
+ case 0x1a:
+ case 0x1b:
+ case 0x1c:
+ case 0x1d:
+ case 0x1e:
+ case 0x1f: /* COP */ invalid_instruction(r3000, op); break;
+ default: invalid_instruction(r3000, op); break;
+ }
+}
+
+
+
+/***************************************************************************
+ CORE EXECUTION LOOP
+***************************************************************************/
+
+static CPU_EXECUTE( r3000 )
+{
+ r3000_state *r3000 = get_safe_token(device);
+
+ /* count cycles and interrupt cycles */
+ r3000->icount -= r3000->interrupt_cycles;
+ r3000->interrupt_cycles = 0;
+
+ /* check for IRQs */
+ check_irqs(r3000);
+
+ /* core execution loop */
+ do
+ {
+ UINT32 op;
+ UINT64 temp64;
+ int temp;
+
+ /* debugging */
+ r3000->ppc = r3000->pc;
+ debugger_instruction_hook(device, r3000->pc);
+
+ /* instruction fetch */
+ op = ROPCODE(r3000, r3000->pc);
+
+ /* adjust for next PC */
+ if (r3000->nextpc != ~0)
+ {
+ r3000->pc = r3000->nextpc;
+ r3000->nextpc = ~0;
+ }
+ else
+ r3000->pc += 4;
+
+ /* parse the instruction */
+ switch (op >> 26)
+ {
+ case 0x00: /* SPECIAL */
+ switch (op & 63)
+ {
+ case 0x00: /* SLL */ if (RDREG) r3000->RDVAL = r3000->RTVAL << SHIFT; break;
+ case 0x02: /* SRL */ if (RDREG) r3000->RDVAL = r3000->RTVAL >> SHIFT; break;
+ case 0x03: /* SRA */ if (RDREG) r3000->RDVAL = (INT32)r3000->RTVAL >> SHIFT; break;
+ case 0x04: /* SLLV */ if (RDREG) r3000->RDVAL = r3000->RTVAL << (r3000->RSVAL & 31); break;
+ case 0x06: /* SRLV */ if (RDREG) r3000->RDVAL = r3000->RTVAL >> (r3000->RSVAL & 31); break;
+ case 0x07: /* SRAV */ if (RDREG) r3000->RDVAL = (INT32)r3000->RTVAL >> (r3000->RSVAL & 31); break;
+ case 0x08: /* JR */ SETPC(r3000, r3000->RSVAL); break;
+ case 0x09: /* JALR */ SETPCL(r3000, r3000->RSVAL, RDREG); break;
+ case 0x0c: /* SYSCALL */ generate_exception(r3000, EXCEPTION_SYSCALL); break;
+ case 0x0d: /* BREAK */ generate_exception(r3000, EXCEPTION_BREAK); break;
+ case 0x0f: /* SYNC */ invalid_instruction(r3000, op); break;
+ case 0x10: /* MFHI */ if (RDREG) r3000->RDVAL = r3000->hi; break;
+ case 0x11: /* MTHI */ r3000->hi = r3000->RSVAL; break;
+ case 0x12: /* MFLO */ if (RDREG) r3000->RDVAL = r3000->lo; break;
+ case 0x13: /* MTLO */ r3000->lo = r3000->RSVAL; break;
+ case 0x18: /* MULT */
+ temp64 = (INT64)(INT32)r3000->RSVAL * (INT64)(INT32)r3000->RTVAL;
+ r3000->lo = (UINT32)temp64;
+ r3000->hi = (UINT32)(temp64 >> 32);
+ r3000->icount -= 11;
+ break;
+ case 0x19: /* MULTU */
+ temp64 = (UINT64)r3000->RSVAL * (UINT64)r3000->RTVAL;
+ r3000->lo = (UINT32)temp64;
+ r3000->hi = (UINT32)(temp64 >> 32);
+ r3000->icount -= 11;
+ break;
+ case 0x1a: /* DIV */
+ if (r3000->RTVAL)
+ {
+ r3000->lo = (INT32)r3000->RSVAL / (INT32)r3000->RTVAL;
+ r3000->hi = (INT32)r3000->RSVAL % (INT32)r3000->RTVAL;
+ }
+ r3000->icount -= 34;
+ break;
+ case 0x1b: /* DIVU */
+ if (r3000->RTVAL)
+ {
+ r3000->lo = r3000->RSVAL / r3000->RTVAL;
+ r3000->hi = r3000->RSVAL % r3000->RTVAL;
+ }
+ r3000->icount -= 34;
+ break;
+ case 0x20: /* ADD */
+ if (ENABLE_OVERFLOWS && r3000->RSVAL > ~r3000->RTVAL) generate_exception(r3000, EXCEPTION_OVERFLOW);
+ else r3000->RDVAL = r3000->RSVAL + r3000->RTVAL;
+ break;
+ case 0x21: /* ADDU */ if (RDREG) r3000->RDVAL = r3000->RSVAL + r3000->RTVAL; break;
+ case 0x22: /* SUB */
+ if (ENABLE_OVERFLOWS && r3000->RSVAL < r3000->RTVAL) generate_exception(r3000, EXCEPTION_OVERFLOW);
+ else r3000->RDVAL = r3000->RSVAL - r3000->RTVAL;
+ break;
+ case 0x23: /* SUBU */ if (RDREG) r3000->RDVAL = r3000->RSVAL - r3000->RTVAL; break;
+ case 0x24: /* AND */ if (RDREG) r3000->RDVAL = r3000->RSVAL & r3000->RTVAL; break;
+ case 0x25: /* OR */ if (RDREG) r3000->RDVAL = r3000->RSVAL | r3000->RTVAL; break;
+ case 0x26: /* XOR */ if (RDREG) r3000->RDVAL = r3000->RSVAL ^ r3000->RTVAL; break;
+ case 0x27: /* NOR */ if (RDREG) r3000->RDVAL = ~(r3000->RSVAL | r3000->RTVAL); break;
+ case 0x2a: /* SLT */ if (RDREG) r3000->RDVAL = (INT32)r3000->RSVAL < (INT32)r3000->RTVAL; break;
+ case 0x2b: /* SLTU */ if (RDREG) r3000->RDVAL = (UINT32)r3000->RSVAL < (UINT32)r3000->RTVAL; break;
+ case 0x30: /* TEQ */ invalid_instruction(r3000, op); break;
+ case 0x31: /* TGEU */ invalid_instruction(r3000, op); break;
+ case 0x32: /* TLT */ invalid_instruction(r3000, op); break;
+ case 0x33: /* TLTU */ invalid_instruction(r3000, op); break;
+ case 0x34: /* TGE */ invalid_instruction(r3000, op); break;
+ case 0x36: /* TNE */ invalid_instruction(r3000, op); break;
+ default: /* ??? */ invalid_instruction(r3000, op); break;
+ }
+ break;
+
+ case 0x01: /* REGIMM */
+ switch (RTREG)
+ {
+ case 0x00: /* BLTZ */ if ((INT32)r3000->RSVAL < 0) ADDPC(r3000, SIMMVAL); break;
+ case 0x01: /* BGEZ */ if ((INT32)r3000->RSVAL >= 0) ADDPC(r3000, SIMMVAL); break;
+ case 0x02: /* BLTZL */ invalid_instruction(r3000, op); break;
+ case 0x03: /* BGEZL */ invalid_instruction(r3000, op); break;
+ case 0x08: /* TGEI */ invalid_instruction(r3000, op); break;
+ case 0x09: /* TGEIU */ invalid_instruction(r3000, op); break;
+ case 0x0a: /* TLTI */ invalid_instruction(r3000, op); break;
+ case 0x0b: /* TLTIU */ invalid_instruction(r3000, op); break;
+ case 0x0c: /* TEQI */ invalid_instruction(r3000, op); break;
+ case 0x0e: /* TNEI */ invalid_instruction(r3000, op); break;
+ case 0x10: /* BLTZAL */ if ((INT32)r3000->RSVAL < 0) ADDPCL(r3000,SIMMVAL,31); break;
+ case 0x11: /* BGEZAL */ if ((INT32)r3000->RSVAL >= 0) ADDPCL(r3000,SIMMVAL,31); break;
+ case 0x12: /* BLTZALL */ invalid_instruction(r3000, op); break;
+ case 0x13: /* BGEZALL */ invalid_instruction(r3000, op); break;
+ default: /* ??? */ invalid_instruction(r3000, op); break;
+ }
+ break;
+
+ case 0x02: /* J */ ABSPC(r3000, LIMMVAL); break;
+ case 0x03: /* JAL */ ABSPCL(r3000, LIMMVAL,31); break;
+ case 0x04: /* BEQ */ if (r3000->RSVAL == r3000->RTVAL) ADDPC(r3000, SIMMVAL); break;
+ case 0x05: /* BNE */ if (r3000->RSVAL != r3000->RTVAL) ADDPC(r3000, SIMMVAL); break;
+ case 0x06: /* BLEZ */ if ((INT32)r3000->RSVAL <= 0) ADDPC(r3000, SIMMVAL); break;
+ case 0x07: /* BGTZ */ if ((INT32)r3000->RSVAL > 0) ADDPC(r3000, SIMMVAL); break;
+ case 0x08: /* ADDI */
+ if (ENABLE_OVERFLOWS && r3000->RSVAL > ~SIMMVAL) generate_exception(r3000, EXCEPTION_OVERFLOW);
+ else if (RTREG) r3000->RTVAL = r3000->RSVAL + SIMMVAL;
+ break;
+ case 0x09: /* ADDIU */ if (RTREG) r3000->RTVAL = r3000->RSVAL + SIMMVAL; break;
+ case 0x0a: /* SLTI */ if (RTREG) r3000->RTVAL = (INT32)r3000->RSVAL < (INT32)SIMMVAL; break;
+ case 0x0b: /* SLTIU */ if (RTREG) r3000->RTVAL = (UINT32)r3000->RSVAL < (UINT32)SIMMVAL; break;
+ case 0x0c: /* ANDI */ if (RTREG) r3000->RTVAL = r3000->RSVAL & UIMMVAL; break;
+ case 0x0d: /* ORI */ if (RTREG) r3000->RTVAL = r3000->RSVAL | UIMMVAL; break;
+ case 0x0e: /* XORI */ if (RTREG) r3000->RTVAL = r3000->RSVAL ^ UIMMVAL; break;
+ case 0x0f: /* LUI */ if (RTREG) r3000->RTVAL = UIMMVAL << 16; break;
+ case 0x10: /* COP0 */ handle_cop0(r3000, op); break;
+ case 0x11: /* COP1 */ handle_cop1(r3000, op); break;
+ case 0x12: /* COP2 */ handle_cop2(r3000, op); break;
+ case 0x13: /* COP3 */ handle_cop3(r3000, op); break;
+ case 0x14: /* BEQL */ invalid_instruction(r3000, op); break;
+ case 0x15: /* BNEL */ invalid_instruction(r3000, op); break;
+ case 0x16: /* BLEZL */ invalid_instruction(r3000, op); break;
+ case 0x17: /* BGTZL */ invalid_instruction(r3000, op); break;
+ case 0x20: /* LB */ temp = RBYTE(r3000, SIMMVAL+r3000->RSVAL); if (RTREG) r3000->RTVAL = (INT8)temp; break;
+ case 0x21: /* LH */ temp = RWORD(r3000, SIMMVAL+r3000->RSVAL); if (RTREG) r3000->RTVAL = (INT16)temp; break;
+ case 0x22: /* LWL */ (*r3000->lwl)(r3000, op); break;
+ case 0x23: /* LW */ temp = RLONG(r3000, SIMMVAL+r3000->RSVAL); if (RTREG) r3000->RTVAL = temp; break;
+ case 0x24: /* LBU */ temp = RBYTE(r3000, SIMMVAL+r3000->RSVAL); if (RTREG) r3000->RTVAL = (UINT8)temp; break;
+ case 0x25: /* LHU */ temp = RWORD(r3000, SIMMVAL+r3000->RSVAL); if (RTREG) r3000->RTVAL = (UINT16)temp; break;
+ case 0x26: /* LWR */ (*r3000->lwr)(r3000, op); break;
+ case 0x28: /* SB */ WBYTE(r3000, SIMMVAL+r3000->RSVAL, r3000->RTVAL); break;
+ case 0x29: /* SH */ WWORD(r3000, SIMMVAL+r3000->RSVAL, r3000->RTVAL); break;
+ case 0x2a: /* SWL */ (*r3000->swl)(r3000, op); break;
+ case 0x2b: /* SW */ WLONG(r3000, SIMMVAL+r3000->RSVAL, r3000->RTVAL); break;
+ case 0x2e: /* SWR */ (*r3000->swr)(r3000, op); break;
+ case 0x2f: /* CACHE */ invalid_instruction(r3000, op); break;
+ case 0x30: /* LL */ invalid_instruction(r3000, op); break;
+ case 0x31: /* LWC1 */ set_cop1_reg(r3000, RTREG, RLONG(r3000, SIMMVAL+r3000->RSVAL)); break;
+ case 0x32: /* LWC2 */ set_cop2_reg(r3000, RTREG, RLONG(r3000, SIMMVAL+r3000->RSVAL)); break;
+ case 0x33: /* LWC3 */ set_cop3_reg(r3000, RTREG, RLONG(r3000, SIMMVAL+r3000->RSVAL)); break;
+ case 0x34: /* LDC0 */ invalid_instruction(r3000, op); break;
+ case 0x35: /* LDC1 */ invalid_instruction(r3000, op); break;
+ case 0x36: /* LDC2 */ invalid_instruction(r3000, op); break;
+ case 0x37: /* LDC3 */ invalid_instruction(r3000, op); break;
+ case 0x38: /* SC */ invalid_instruction(r3000, op); break;
+ case 0x39: /* LWC1 */ WLONG(r3000, SIMMVAL+r3000->RSVAL, get_cop1_reg(r3000, RTREG)); break;
+ case 0x3a: /* LWC2 */ WLONG(r3000, SIMMVAL+r3000->RSVAL, get_cop2_reg(r3000, RTREG)); break;
+ case 0x3b: /* LWC3 */ WLONG(r3000, SIMMVAL+r3000->RSVAL, get_cop3_reg(r3000, RTREG)); break;
+ case 0x3c: /* SDC0 */ invalid_instruction(r3000, op); break;
+ case 0x3d: /* SDC1 */ invalid_instruction(r3000, op); break;
+ case 0x3e: /* SDC2 */ invalid_instruction(r3000, op); break;
+ case 0x3f: /* SDC3 */ invalid_instruction(r3000, op); break;
+ default: /* ??? */ invalid_instruction(r3000, op); break;
+ }
+ r3000->icount--;
+
+ } while (r3000->icount > 0 || r3000->nextpc != ~0);
+
+ r3000->icount -= r3000->interrupt_cycles;
+ r3000->interrupt_cycles = 0;
+}
+
+
+
+/***************************************************************************
+ DISASSEMBLY HOOK
+***************************************************************************/
+
+
+/***************************************************************************
+ CACHE I/O
+***************************************************************************/
+
+static UINT8 readcache_be(address_space *space, offs_t offset)
+{
+ r3000_state *r3000 = get_safe_token(&space->device());
+ offset &= 0x1fffffff;
+ return (offset * 4 < r3000->cache_size) ? r3000->cache[BYTE4_XOR_BE(offset)] : 0xff;
+}
+
+static UINT16 readcache_be_word(address_space *space, offs_t offset)
+{
+ r3000_state *r3000 = get_safe_token(&space->device());
+ offset &= 0x1fffffff;
+ return (offset * 4 < r3000->cache_size) ? *(UINT16 *)&r3000->cache[WORD_XOR_BE(offset)] : 0xffff;
+}
+
+static UINT32 readcache_be_dword(address_space *space, offs_t offset)
+{
+ r3000_state *r3000 = get_safe_token(&space->device());
+ offset &= 0x1fffffff;
+ return (offset * 4 < r3000->cache_size) ? *(UINT32 *)&r3000->cache[offset] : 0xffffffff;
+}
+
+static void writecache_be(address_space *space, offs_t offset, UINT8 data)
+{
+ r3000_state *r3000 = get_safe_token(&space->device());
+ offset &= 0x1fffffff;
+ if (offset * 4 < r3000->cache_size) r3000->cache[BYTE4_XOR_BE(offset)] = data;
+}
+
+static void writecache_be_word(address_space *space, offs_t offset, UINT16 data)
+{
+ r3000_state *r3000 = get_safe_token(&space->device());
+ offset &= 0x1fffffff;
+ if (offset * 4 < r3000->cache_size) *(UINT16 *)&r3000->cache[WORD_XOR_BE(offset)] = data;
+}
+
+static void writecache_be_dword(address_space *space, offs_t offset, UINT32 data)
+{
+ r3000_state *r3000 = get_safe_token(&space->device());
+ offset &= 0x1fffffff;
+ if (offset * 4 < r3000->cache_size) *(UINT32 *)&r3000->cache[offset] = data;
+}
+
+static UINT8 readcache_le(address_space *space, offs_t offset)
+{
+ r3000_state *r3000 = get_safe_token(&space->device());
+ offset &= 0x1fffffff;
+ return (offset * 4 < r3000->cache_size) ? r3000->cache[BYTE4_XOR_LE(offset)] : 0xff;
+}
+
+static UINT16 readcache_le_word(address_space *space, offs_t offset)
+{
+ r3000_state *r3000 = get_safe_token(&space->device());
+ offset &= 0x1fffffff;
+ return (offset * 4 < r3000->cache_size) ? *(UINT16 *)&r3000->cache[WORD_XOR_LE(offset)] : 0xffff;
+}
+
+static UINT32 readcache_le_dword(address_space *space, offs_t offset)
+{
+ r3000_state *r3000 = get_safe_token(&space->device());
+ offset &= 0x1fffffff;
+ return (offset * 4 < r3000->cache_size) ? *(UINT32 *)&r3000->cache[offset] : 0xffffffff;
+}
+
+static void writecache_le(address_space *space, offs_t offset, UINT8 data)
+{
+ r3000_state *r3000 = get_safe_token(&space->device());
+ offset &= 0x1fffffff;
+ if (offset * 4 < r3000->cache_size) r3000->cache[BYTE4_XOR_LE(offset)] = data;
+}
+
+static void writecache_le_word(address_space *space, offs_t offset, UINT16 data)
+{
+ r3000_state *r3000 = get_safe_token(&space->device());
+ offset &= 0x1fffffff;
+ if (offset * 4 < r3000->cache_size) *(UINT16 *)&r3000->cache[WORD_XOR_LE(offset)] = data;
+}
+
+static void writecache_le_dword(address_space *space, offs_t offset, UINT32 data)
+{
+ r3000_state *r3000 = get_safe_token(&space->device());
+ offset &= 0x1fffffff;
+ if (offset * 4 < r3000->cache_size) *(UINT32 *)&r3000->cache[offset] = data;
+}
+
+
+
+/***************************************************************************
+ COMPLEX OPCODE IMPLEMENTATIONS
+***************************************************************************/
+
+static void lwl_be(r3000_state *r3000, UINT32 op)
+{
+ offs_t offs = SIMMVAL + r3000->RSVAL;
+ UINT32 temp = RLONG(r3000, offs & ~3);
+ if (RTREG)
+ {
+ if (!(offs & 3)) r3000->RTVAL = temp;
+ else
+ {
+ int shift = 8 * (offs & 3);
+ r3000->RTVAL = (r3000->RTVAL & (0x00ffffff >> (24 - shift))) | (temp << shift);
+ }
+ }
+}
+
+static void lwr_be(r3000_state *r3000, UINT32 op)
+{
+ offs_t offs = SIMMVAL + r3000->RSVAL;
+ UINT32 temp = RLONG(r3000, offs & ~3);
+ if (RTREG)
+ {
+ if ((offs & 3) == 3) r3000->RTVAL = temp;
+ else
+ {
+ int shift = 8 * (offs & 3);
+ r3000->RTVAL = (r3000->RTVAL & (0xffffff00 << shift)) | (temp >> (24 - shift));
+ }
+ }
+}
+
+static void swl_be(r3000_state *r3000, UINT32 op)
+{
+ offs_t offs = SIMMVAL + r3000->RSVAL;
+ if (!(offs & 3)) WLONG(r3000, offs, r3000->RTVAL);
+ else
+ {
+ UINT32 temp = RLONG(r3000, offs & ~3);
+ int shift = 8 * (offs & 3);
+ WLONG(r3000, offs & ~3, (temp & (0xffffff00 << (24 - shift))) | (r3000->RTVAL >> shift));
+ }
+}
+
+
+static void swr_be(r3000_state *r3000, UINT32 op)
+{
+ offs_t offs = SIMMVAL + r3000->RSVAL;
+ if ((offs & 3) == 3) WLONG(r3000, offs & ~3, r3000->RTVAL);
+ else
+ {
+ UINT32 temp = RLONG(r3000, offs & ~3);
+ int shift = 8 * (offs & 3);
+ WLONG(r3000, offs & ~3, (temp & (0x00ffffff >> shift)) | (r3000->RTVAL << (24 - shift)));
+ }
+}
+
+
+
+static void lwl_le(r3000_state *r3000, UINT32 op)
+{
+ offs_t offs = SIMMVAL + r3000->RSVAL;
+ UINT32 temp = RLONG(r3000, offs & ~3);
+ if (RTREG)
+ {
+ if (!(offs & 3)) r3000->RTVAL = temp;
+ else
+ {
+ int shift = 8 * (offs & 3);
+ r3000->RTVAL = (r3000->RTVAL & (0xffffff00 << (24 - shift))) | (temp >> shift);
+ }
+ }
+}
+
+static void lwr_le(r3000_state *r3000, UINT32 op)
+{
+ offs_t offs = SIMMVAL + r3000->RSVAL;
+ UINT32 temp = RLONG(r3000, offs & ~3);
+ if (RTREG)
+ {
+ if ((offs & 3) == 3) r3000->RTVAL = temp;
+ else
+ {
+ int shift = 8 * (offs & 3);
+ r3000->RTVAL = (r3000->RTVAL & (0x00ffffff >> shift)) | (temp << (24 - shift));
+ }
+ }
+}
+
+static void swl_le(r3000_state *r3000, UINT32 op)
+{
+ offs_t offs = SIMMVAL + r3000->RSVAL;
+ if (!(offs & 3)) WLONG(r3000, offs, r3000->RTVAL);
+ else
+ {
+ UINT32 temp = RLONG(r3000, offs & ~3);
+ int shift = 8 * (offs & 3);
+ WLONG(r3000, offs & ~3, (temp & (0x00ffffff >> (24 - shift))) | (r3000->RTVAL << shift));
+ }
+}
+
+static void swr_le(r3000_state *r3000, UINT32 op)
+{
+ offs_t offs = SIMMVAL + r3000->RSVAL;
+ if ((offs & 3) == 3) WLONG(r3000, offs & ~3, r3000->RTVAL);
+ else
+ {
+ UINT32 temp = RLONG(r3000, offs & ~3);
+ int shift = 8 * (offs & 3);
+ WLONG(r3000, offs & ~3, (temp & (0xffffff00 << shift)) | (r3000->RTVAL >> (24 - shift)));
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( r3000 )
+{
+ r3000_state *r3000 = get_safe_token(device);
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + R3000_IRQ0: set_irq_line(r3000, R3000_IRQ0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + R3000_IRQ1: set_irq_line(r3000, R3000_IRQ1, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + R3000_IRQ2: set_irq_line(r3000, R3000_IRQ2, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + R3000_IRQ3: set_irq_line(r3000, R3000_IRQ3, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + R3000_IRQ4: set_irq_line(r3000, R3000_IRQ4, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + R3000_IRQ5: set_irq_line(r3000, R3000_IRQ5, info->i); break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + R3000_PC: r3000->pc = info->i; break;
+ case CPUINFO_INT_REGISTER + R3000_SR: r3000->SR = info->i; break;
+
+ case CPUINFO_INT_REGISTER + R3000_R0: r3000->r[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + R3000_R1: r3000->r[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + R3000_R2: r3000->r[2] = info->i; break;
+ case CPUINFO_INT_REGISTER + R3000_R3: r3000->r[3] = info->i; break;
+ case CPUINFO_INT_REGISTER + R3000_R4: r3000->r[4] = info->i; break;
+ case CPUINFO_INT_REGISTER + R3000_R5: r3000->r[5] = info->i; break;
+ case CPUINFO_INT_REGISTER + R3000_R6: r3000->r[6] = info->i; break;
+ case CPUINFO_INT_REGISTER + R3000_R7: r3000->r[7] = info->i; break;
+ case CPUINFO_INT_REGISTER + R3000_R8: r3000->r[8] = info->i; break;
+ case CPUINFO_INT_REGISTER + R3000_R9: r3000->r[9] = info->i; break;
+ case CPUINFO_INT_REGISTER + R3000_R10: r3000->r[10] = info->i; break;
+ case CPUINFO_INT_REGISTER + R3000_R11: r3000->r[11] = info->i; break;
+ case CPUINFO_INT_REGISTER + R3000_R12: r3000->r[12] = info->i; break;
+ case CPUINFO_INT_REGISTER + R3000_R13: r3000->r[13] = info->i; break;
+ case CPUINFO_INT_REGISTER + R3000_R14: r3000->r[14] = info->i; break;
+ case CPUINFO_INT_REGISTER + R3000_R15: r3000->r[15] = info->i; break;
+ case CPUINFO_INT_REGISTER + R3000_R16: r3000->r[16] = info->i; break;
+ case CPUINFO_INT_REGISTER + R3000_R17: r3000->r[17] = info->i; break;
+ case CPUINFO_INT_REGISTER + R3000_R18: r3000->r[18] = info->i; break;
+ case CPUINFO_INT_REGISTER + R3000_R19: r3000->r[19] = info->i; break;
+ case CPUINFO_INT_REGISTER + R3000_R20: r3000->r[20] = info->i; break;
+ case CPUINFO_INT_REGISTER + R3000_R21: r3000->r[21] = info->i; break;
+ case CPUINFO_INT_REGISTER + R3000_R22: r3000->r[22] = info->i; break;
+ case CPUINFO_INT_REGISTER + R3000_R23: r3000->r[23] = info->i; break;
+ case CPUINFO_INT_REGISTER + R3000_R24: r3000->r[24] = info->i; break;
+ case CPUINFO_INT_REGISTER + R3000_R25: r3000->r[25] = info->i; break;
+ case CPUINFO_INT_REGISTER + R3000_R26: r3000->r[26] = info->i; break;
+ case CPUINFO_INT_REGISTER + R3000_R27: r3000->r[27] = info->i; break;
+ case CPUINFO_INT_REGISTER + R3000_R28: r3000->r[28] = info->i; break;
+ case CPUINFO_INT_REGISTER + R3000_R29: r3000->r[29] = info->i; break;
+ case CPUINFO_INT_REGISTER + R3000_R30: r3000->r[30] = info->i; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + R3000_R31: r3000->r[31] = info->i; break;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+static CPU_GET_INFO( r3000 )
+{
+ r3000_state *r3000 = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(r3000_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 6; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 40; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 29; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_INPUT_STATE + R3000_IRQ0: info->i = (r3000->cpr[0][COP0_Cause] & 0x400) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + R3000_IRQ1: info->i = (r3000->cpr[0][COP0_Cause] & 0x800) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + R3000_IRQ2: info->i = (r3000->cpr[0][COP0_Cause] & 0x1000) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + R3000_IRQ3: info->i = (r3000->cpr[0][COP0_Cause] & 0x2000) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + R3000_IRQ4: info->i = (r3000->cpr[0][COP0_Cause] & 0x4000) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + R3000_IRQ5: info->i = (r3000->cpr[0][COP0_Cause] & 0x8000) ? ASSERT_LINE : CLEAR_LINE; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = r3000->ppc; break;
+
+ case CPUINFO_INT_PC: info->i = r3000->pc & 0x1fffffff; break;
+ case CPUINFO_INT_REGISTER + R3000_PC: info->i = r3000->pc; break;
+ case CPUINFO_INT_REGISTER + R3000_SR: info->i = r3000->SR; break;
+
+ case CPUINFO_INT_REGISTER + R3000_R0: info->i = r3000->r[0]; break;
+ case CPUINFO_INT_REGISTER + R3000_R1: info->i = r3000->r[1]; break;
+ case CPUINFO_INT_REGISTER + R3000_R2: info->i = r3000->r[2]; break;
+ case CPUINFO_INT_REGISTER + R3000_R3: info->i = r3000->r[3]; break;
+ case CPUINFO_INT_REGISTER + R3000_R4: info->i = r3000->r[4]; break;
+ case CPUINFO_INT_REGISTER + R3000_R5: info->i = r3000->r[5]; break;
+ case CPUINFO_INT_REGISTER + R3000_R6: info->i = r3000->r[6]; break;
+ case CPUINFO_INT_REGISTER + R3000_R7: info->i = r3000->r[7]; break;
+ case CPUINFO_INT_REGISTER + R3000_R8: info->i = r3000->r[8]; break;
+ case CPUINFO_INT_REGISTER + R3000_R9: info->i = r3000->r[9]; break;
+ case CPUINFO_INT_REGISTER + R3000_R10: info->i = r3000->r[10]; break;
+ case CPUINFO_INT_REGISTER + R3000_R11: info->i = r3000->r[11]; break;
+ case CPUINFO_INT_REGISTER + R3000_R12: info->i = r3000->r[12]; break;
+ case CPUINFO_INT_REGISTER + R3000_R13: info->i = r3000->r[13]; break;
+ case CPUINFO_INT_REGISTER + R3000_R14: info->i = r3000->r[14]; break;
+ case CPUINFO_INT_REGISTER + R3000_R15: info->i = r3000->r[15]; break;
+ case CPUINFO_INT_REGISTER + R3000_R16: info->i = r3000->r[16]; break;
+ case CPUINFO_INT_REGISTER + R3000_R17: info->i = r3000->r[17]; break;
+ case CPUINFO_INT_REGISTER + R3000_R18: info->i = r3000->r[18]; break;
+ case CPUINFO_INT_REGISTER + R3000_R19: info->i = r3000->r[19]; break;
+ case CPUINFO_INT_REGISTER + R3000_R20: info->i = r3000->r[20]; break;
+ case CPUINFO_INT_REGISTER + R3000_R21: info->i = r3000->r[21]; break;
+ case CPUINFO_INT_REGISTER + R3000_R22: info->i = r3000->r[22]; break;
+ case CPUINFO_INT_REGISTER + R3000_R23: info->i = r3000->r[23]; break;
+ case CPUINFO_INT_REGISTER + R3000_R24: info->i = r3000->r[24]; break;
+ case CPUINFO_INT_REGISTER + R3000_R25: info->i = r3000->r[25]; break;
+ case CPUINFO_INT_REGISTER + R3000_R26: info->i = r3000->r[26]; break;
+ case CPUINFO_INT_REGISTER + R3000_R27: info->i = r3000->r[27]; break;
+ case CPUINFO_INT_REGISTER + R3000_R28: info->i = r3000->r[28]; break;
+ case CPUINFO_INT_REGISTER + R3000_R29: info->i = r3000->r[29]; break;
+ case CPUINFO_INT_REGISTER + R3000_R30: info->i = r3000->r[30]; break;
+ case CPUINFO_INT_SP: info->i = r3000->r[31] & 0x1fffffff; break;
+ case CPUINFO_INT_REGISTER + R3000_R31: info->i = r3000->r[31]; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(r3000); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(r3000); break;
+ case CPUINFO_FCT_RESET: /* provided per-CPU */ break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(r3000); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(r3000); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: /* provided per-CPU */ break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &r3000->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "R3000"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "MIPS II"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Aaron Giles"); break;
+
+ case CPUINFO_STR_FLAGS: strcpy(info->s, " "); break;
+
+ case CPUINFO_STR_REGISTER + R3000_PC: sprintf(info->s, "PC: %08X", r3000->pc); break;
+ case CPUINFO_STR_REGISTER + R3000_SR: sprintf(info->s, "SR: %08X", r3000->SR); break;
+
+ case CPUINFO_STR_REGISTER + R3000_R0: sprintf(info->s, "R0: %08X", r3000->r[0]); break;
+ case CPUINFO_STR_REGISTER + R3000_R1: sprintf(info->s, "R1: %08X", r3000->r[1]); break;
+ case CPUINFO_STR_REGISTER + R3000_R2: sprintf(info->s, "R2: %08X", r3000->r[2]); break;
+ case CPUINFO_STR_REGISTER + R3000_R3: sprintf(info->s, "R3: %08X", r3000->r[3]); break;
+ case CPUINFO_STR_REGISTER + R3000_R4: sprintf(info->s, "R4: %08X", r3000->r[4]); break;
+ case CPUINFO_STR_REGISTER + R3000_R5: sprintf(info->s, "R5: %08X", r3000->r[5]); break;
+ case CPUINFO_STR_REGISTER + R3000_R6: sprintf(info->s, "R6: %08X", r3000->r[6]); break;
+ case CPUINFO_STR_REGISTER + R3000_R7: sprintf(info->s, "R7: %08X", r3000->r[7]); break;
+ case CPUINFO_STR_REGISTER + R3000_R8: sprintf(info->s, "R8: %08X", r3000->r[8]); break;
+ case CPUINFO_STR_REGISTER + R3000_R9: sprintf(info->s, "R9: %08X", r3000->r[9]); break;
+ case CPUINFO_STR_REGISTER + R3000_R10: sprintf(info->s, "R10:%08X", r3000->r[10]); break;
+ case CPUINFO_STR_REGISTER + R3000_R11: sprintf(info->s, "R11:%08X", r3000->r[11]); break;
+ case CPUINFO_STR_REGISTER + R3000_R12: sprintf(info->s, "R12:%08X", r3000->r[12]); break;
+ case CPUINFO_STR_REGISTER + R3000_R13: sprintf(info->s, "R13:%08X", r3000->r[13]); break;
+ case CPUINFO_STR_REGISTER + R3000_R14: sprintf(info->s, "R14:%08X", r3000->r[14]); break;
+ case CPUINFO_STR_REGISTER + R3000_R15: sprintf(info->s, "R15:%08X", r3000->r[15]); break;
+ case CPUINFO_STR_REGISTER + R3000_R16: sprintf(info->s, "R16:%08X", r3000->r[16]); break;
+ case CPUINFO_STR_REGISTER + R3000_R17: sprintf(info->s, "R17:%08X", r3000->r[17]); break;
+ case CPUINFO_STR_REGISTER + R3000_R18: sprintf(info->s, "R18:%08X", r3000->r[18]); break;
+ case CPUINFO_STR_REGISTER + R3000_R19: sprintf(info->s, "R19:%08X", r3000->r[19]); break;
+ case CPUINFO_STR_REGISTER + R3000_R20: sprintf(info->s, "R20:%08X", r3000->r[20]); break;
+ case CPUINFO_STR_REGISTER + R3000_R21: sprintf(info->s, "R21:%08X", r3000->r[21]); break;
+ case CPUINFO_STR_REGISTER + R3000_R22: sprintf(info->s, "R22:%08X", r3000->r[22]); break;
+ case CPUINFO_STR_REGISTER + R3000_R23: sprintf(info->s, "R23:%08X", r3000->r[23]); break;
+ case CPUINFO_STR_REGISTER + R3000_R24: sprintf(info->s, "R24:%08X", r3000->r[24]); break;
+ case CPUINFO_STR_REGISTER + R3000_R25: sprintf(info->s, "R25:%08X", r3000->r[25]); break;
+ case CPUINFO_STR_REGISTER + R3000_R26: sprintf(info->s, "R26:%08X", r3000->r[26]); break;
+ case CPUINFO_STR_REGISTER + R3000_R27: sprintf(info->s, "R27:%08X", r3000->r[27]); break;
+ case CPUINFO_STR_REGISTER + R3000_R28: sprintf(info->s, "R28:%08X", r3000->r[28]); break;
+ case CPUINFO_STR_REGISTER + R3000_R29: sprintf(info->s, "R29:%08X", r3000->r[29]); break;
+ case CPUINFO_STR_REGISTER + R3000_R30: sprintf(info->s, "R30:%08X", r3000->r[30]); break;
+ case CPUINFO_STR_REGISTER + R3000_R31: sprintf(info->s, "R31:%08X", r3000->r[31]); break;
+ }
+}
+
+
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+
+CPU_GET_INFO( r3000be )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(r3000be); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(r3000be); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "R3000 (big)"); break;
+
+ default: CPU_GET_INFO_CALL(r3000); break;
+ }
+}
+
+
+CPU_GET_INFO( r3000le )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(r3000le); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(r3000le); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "R3000 (little)"); break;
+
+ default: CPU_GET_INFO_CALL(r3000); break;
+ }
+}
+
+
+CPU_GET_INFO( r3041be )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(r3000be); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(r3000be); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "R3041 (big)"); break;
+
+ default: CPU_GET_INFO_CALL(r3000); break;
+ }
+}
+
+
+CPU_GET_INFO( r3041le )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(r3000le); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(r3000le); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "R3041 (little)"); break;
+
+ default: CPU_GET_INFO_CALL(r3000); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(R3000BE, r3000be);
+DEFINE_LEGACY_CPU_DEVICE(R3000LE, r3000le);
+
+DEFINE_LEGACY_CPU_DEVICE(R3041BE, r3041be);
+DEFINE_LEGACY_CPU_DEVICE(R3041LE, r3041le);
diff --git a/trunk/src/emu/cpu/mips/r3000.h b/trunk/src/emu/cpu/mips/r3000.h
new file mode 100644
index 00000000000..d2c6789fbb3
--- /dev/null
+++ b/trunk/src/emu/cpu/mips/r3000.h
@@ -0,0 +1,68 @@
+/***************************************************************************
+
+ r3000.h
+ Interface file for the portable MIPS R3000 emulator.
+ Written by Aaron Giles
+
+***************************************************************************/
+
+#ifndef __R3000_H__
+#define __R3000_H__
+
+
+
+/***************************************************************************
+ COMPILE-TIME DEFINITIONS
+***************************************************************************/
+
+
+/***************************************************************************
+ REGISTER ENUMERATION
+***************************************************************************/
+
+enum
+{
+ R3000_PC=1,R3000_SR,
+ R3000_R0,R3000_R1,R3000_R2,R3000_R3,R3000_R4,R3000_R5,R3000_R6,R3000_R7,
+ R3000_R8,R3000_R9,R3000_R10,R3000_R11,R3000_R12,R3000_R13,R3000_R14,R3000_R15,
+ R3000_R16,R3000_R17,R3000_R18,R3000_R19,R3000_R20,R3000_R21,R3000_R22,R3000_R23,
+ R3000_R24,R3000_R25,R3000_R26,R3000_R27,R3000_R28,R3000_R29,R3000_R30,R3000_R31
+};
+
+
+/***************************************************************************
+ INTERRUPT CONSTANTS
+***************************************************************************/
+
+#define R3000_IRQ0 0 /* IRQ0 */
+#define R3000_IRQ1 1 /* IRQ1 */
+#define R3000_IRQ2 2 /* IRQ2 */
+#define R3000_IRQ3 3 /* IRQ3 */
+#define R3000_IRQ4 4 /* IRQ4 */
+#define R3000_IRQ5 5 /* IRQ5 */
+
+
+/***************************************************************************
+ STRUCTURES
+***************************************************************************/
+
+typedef struct _r3000_cpu_core r3000_cpu_core;
+struct _r3000_cpu_core
+{
+ UINT8 hasfpu; /* 1 if we have an FPU, 0 otherwise */
+ size_t icache; /* code cache size */
+ size_t dcache; /* data cache size */
+};
+
+
+/***************************************************************************
+ PUBLIC FUNCTIONS
+***************************************************************************/
+
+DECLARE_LEGACY_CPU_DEVICE(R3000BE, r3000be);
+DECLARE_LEGACY_CPU_DEVICE(R3000LE, r3000le);
+
+DECLARE_LEGACY_CPU_DEVICE(R3041BE, r3041be);
+DECLARE_LEGACY_CPU_DEVICE(R3041LE, r3041le);
+
+#endif /* __R3000_H__ */
diff --git a/trunk/src/emu/cpu/mips/r3kdasm.c b/trunk/src/emu/cpu/mips/r3kdasm.c
new file mode 100644
index 00000000000..88a96c9fe3e
--- /dev/null
+++ b/trunk/src/emu/cpu/mips/r3kdasm.c
@@ -0,0 +1,387 @@
+/***************************************************************************
+
+ r3kdasm.c
+ Disassembler for the portable R3000 emulator.
+ Written by Aaron Giles
+
+***************************************************************************/
+
+#include "emu.h"
+
+
+static const char *const reg[32] =
+{
+ "0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+ "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"
+};
+
+
+static const char *const cpreg[4][32] =
+{
+ {
+ "Index","Random","EntryLo","cpr3", "Context", "cpr5", "cpr6", "cpr7",
+ "BadVAddr", "cpr9", "EntryHi","cpr11","SR","Cause","EPC","PRId",
+ "cpr16","cpr17","cpr18","cpr19","cpr20","cpr21","cpr22","cpr23",
+ "cpr24","cpr25","cpr26","cpr27","cpr28","cpr29","cpr30","cpr31"
+ },
+ {
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
+ "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
+ "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
+ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"
+ },
+ {
+ "cpr0", "cpr1", "cpr2", "cpr3", "cpr4", "cpr5", "cpr6", "cpr7",
+ "cpr8", "cpr9", "cpr10","cpr11","cpr12","cpr13","cpr14","cpr15",
+ "cpr16","cpr17","cpr18","cpr19","cpr20","cpr21","cpr22","cpr23",
+ "cpr24","cpr25","cpr26","cpr27","cpr28","cpr29","cpr30","cpr31"
+ },
+ {
+ "cpr0", "cpr1", "cpr2", "cpr3", "cpr4", "cpr5", "cpr6", "cpr7",
+ "cpr8", "cpr9", "cpr10","cpr11","cpr12","cpr13","cpr14","cpr15",
+ "cpr16","cpr17","cpr18","cpr19","cpr20","cpr21","cpr22","cpr23",
+ "cpr24","cpr25","cpr26","cpr27","cpr28","cpr29","cpr30","cpr31"
+ }
+};
+
+
+static const char *const ccreg[4][32] =
+{
+ {
+ "ccr0", "ccr1", "ccr2", "ccr3", "ccr4", "ccr5", "ccr6", "ccr7",
+ "ccr8", "ccr9", "ccr10","ccr11","ccr12","ccr13","ccr14","ccr15",
+ "ccr16","ccr17","ccr18","ccr19","ccr20","ccr21","ccr22","ccr23",
+ "ccr24","ccr25","ccr26","ccr27","ccr28","ccr29","ccr30","ccr31"
+ },
+ {
+ "ccr0", "ccr1", "ccr2", "ccr3", "ccr4", "ccr5", "ccr6", "ccr7",
+ "ccr8", "ccr9", "ccr10","ccr11","ccr12","ccr13","ccr14","ccr15",
+ "ccr16","ccr17","ccr18","ccr19","ccr20","ccr21","ccr22","ccr23",
+ "ccr24","ccr25","ccr26","ccr27","ccr28","ccr29","ccr30","ccr31"
+ },
+ {
+ "ccr0", "ccr1", "ccr2", "ccr3", "ccr4", "ccr5", "ccr6", "ccr7",
+ "ccr8", "ccr9", "ccr10","ccr11","ccr12","ccr13","ccr14","ccr15",
+ "ccr16","ccr17","ccr18","ccr19","ccr20","ccr21","ccr22","ccr23",
+ "ccr24","ccr25","ccr26","ccr27","ccr28","ccr29","ccr30","ccr31"
+ },
+ {
+ "ccr0", "ccr1", "ccr2", "ccr3", "ccr4", "ccr5", "ccr6", "ccr7",
+ "ccr8", "ccr9", "ccr10","ccr11","ccr12","ccr13","ccr14","ccr15",
+ "ccr16","ccr17","ccr18","ccr19","ccr20","ccr21","ccr22","ccr23",
+ "ccr24","ccr25","ccr26","ccr27","ccr28","ccr29","ccr30","ccr31"
+ }
+};
+
+
+/***************************************************************************
+ CODE CODE
+***************************************************************************/
+
+INLINE char *signed_16bit(INT16 val)
+{
+ static char temp[10];
+ if (val < 0)
+ sprintf(temp, "-$%x", -val);
+ else
+ sprintf(temp, "$%x", val);
+ return temp;
+}
+
+static UINT32 dasm_cop(UINT32 pc, int cop, UINT32 op, char *buffer)
+{
+ int rt = (op >> 16) & 31;
+ int rd = (op >> 11) & 31;
+ UINT32 flags = 0;
+
+ switch ((op >> 21) & 31)
+ {
+ case 0x00: sprintf(buffer, "mfc%d %s,%s", cop, reg[rt], cpreg[cop][rd]); break;
+ case 0x02: sprintf(buffer, "cfc%d %s,%s", cop, reg[rt], ccreg[cop][rd]); break;
+ case 0x04: sprintf(buffer, "mtc%d %s,%s", cop, reg[rt], cpreg[cop][rd]); break;
+ case 0x06: sprintf(buffer, "ctc%d %s,%s", cop, reg[rt], ccreg[cop][rd]); break;
+ case 0x08: /* BC */
+ switch (rt)
+ {
+ case 0x00: sprintf(buffer, "bc%df $%08x", cop, pc + 4 + ((INT16)op << 2)); break;
+ case 0x01: sprintf(buffer, "bc%dt $%08x", cop, pc + 4 + ((INT16)op << 2)); break;
+ case 0x02: sprintf(buffer, "bc%dfl [invalid]", cop); break;
+ case 0x03: sprintf(buffer, "bc%dtl [invalid]", cop); break;
+ default: sprintf(buffer, "dc.l $%08x [invalid]", op); break;
+ }
+ break;
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ case 0x13:
+ case 0x14:
+ case 0x15:
+ case 0x16:
+ case 0x17:
+ case 0x18:
+ case 0x19:
+ case 0x1a:
+ case 0x1b:
+ case 0x1c:
+ case 0x1d:
+ case 0x1e:
+ case 0x1f: /* COP */
+ if (cop == 0)
+ {
+ switch (op & 0x01ffffff)
+ {
+ case 0x01: sprintf(buffer, "tlbr"); break;
+ case 0x02: sprintf(buffer, "tlbwi"); break;
+ case 0x06: sprintf(buffer, "tlbwr"); break;
+ case 0x08: sprintf(buffer, "tlbp"); break;
+ case 0x10: sprintf(buffer, "rfe"); break;
+ case 0x18: sprintf(buffer, "eret [invalid]"); break;
+ default: sprintf(buffer, "cop%d $%07x", cop, op & 0x01ffffff); break;
+ }
+ }
+ else
+ sprintf(buffer, "cop%d $%07x", cop, op & 0x01ffffff); break;
+ default: sprintf(buffer, "dc.l $%08x [invalid]", op); break;
+ }
+
+ return flags;
+}
+
+static UINT32 dasm_cop1(UINT32 pc, UINT32 op, char *buffer)
+{
+ static const char *const format_table[] =
+ {
+ "?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?",
+ "s","d","?","?","w","l","?","?","?","?","?","?","?","?","?","?"
+ };
+ const char *fmt = format_table[(op >> 21) & 31];
+ int ft = (op >> 16) & 31;
+ int fs = (op >> 11) & 31;
+ int fd = (op >> 6) & 31;
+ int rt = (op >> 16) & 31;
+ int rd = (op >> 11) & 31;
+ UINT32 flags = 0;
+
+ switch ((op >> 21) & 31)
+ {
+ case 0x00: sprintf(buffer, "mfc1 %s,%s", reg[rt], cpreg[1][rd]); break;
+ case 0x01: sprintf(buffer, "dmfc1 %s,%s", reg[rt], cpreg[1][rd]); break;
+ case 0x02: sprintf(buffer, "cfc1 %s,%s", reg[rt], ccreg[1][rd]); break;
+ case 0x04: sprintf(buffer, "mtc1 %s,%s", reg[rt], cpreg[1][rd]); break;
+ case 0x05: sprintf(buffer, "dmtc1 %s,%s", reg[rt], cpreg[1][rd]); break;
+ case 0x06: sprintf(buffer, "ctc1 %s,%s", reg[rt], ccreg[1][rd]); break;
+ case 0x08: /* BC */
+ switch (rt & 3)
+ {
+ case 0x00: sprintf(buffer, "bc1f $%08x,%d", pc + 4 + ((INT16)op << 2), (op >> 18) & 7); break;
+ case 0x01: sprintf(buffer, "bc1t $%08x,%d", pc + 4 + ((INT16)op << 2), (op >> 18) & 7); break;
+ case 0x02: sprintf(buffer, "bc1fl $%08x,%d", pc + 4 + ((INT16)op << 2), (op >> 18) & 7); flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1); break;
+ case 0x03: sprintf(buffer, "bc1tl $%08x,%d", pc + 4 + ((INT16)op << 2), (op >> 18) & 7); flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1); break;
+ }
+ break;
+ default: /* COP */
+ switch (op & 0x3f)
+ {
+ case 0x00: sprintf(buffer, "add.%s %s,%s,%s", fmt, cpreg[1][fd], cpreg[1][fs], cpreg[1][ft]); break;
+ case 0x01: sprintf(buffer, "sub.%s %s,%s,%s", fmt, cpreg[1][fd], cpreg[1][fs], cpreg[1][ft]); break;
+ case 0x02: sprintf(buffer, "mul.%s %s,%s,%s", fmt, cpreg[1][fd], cpreg[1][fs], cpreg[1][ft]); break;
+ case 0x03: sprintf(buffer, "div.%s %s,%s,%s", fmt, cpreg[1][fd], cpreg[1][fs], cpreg[1][ft]); break;
+ case 0x04: sprintf(buffer, "sqrt.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
+ case 0x05: sprintf(buffer, "abs.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
+ case 0x06: sprintf(buffer, "mov.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
+ case 0x07: sprintf(buffer, "neg.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
+ case 0x08: sprintf(buffer, "round.l.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
+ case 0x09: sprintf(buffer, "trunc.l.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
+ case 0x0a: sprintf(buffer, "ceil.l.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
+ case 0x0b: sprintf(buffer, "floor.l.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
+ case 0x0c: sprintf(buffer, "round.w.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
+ case 0x0d: sprintf(buffer, "trunc.w.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
+ case 0x0e: sprintf(buffer, "ceil.w.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
+ case 0x0f: sprintf(buffer, "floor.w.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
+ case 0x11: sprintf(buffer, "mov%c.%s %s,%s,%d", ((op >> 16) & 1) ? 't' : 'f', fmt, cpreg[1][fd], cpreg[1][fs], (op >> 18) & 7); break;
+ case 0x12: sprintf(buffer, "movz.%s %s,%s,%s", fmt, cpreg[1][fd], cpreg[1][fs], reg[rt]); break;
+ case 0x13: sprintf(buffer, "movn.%s %s,%s,%s", fmt, cpreg[1][fd], cpreg[1][fs], reg[rt]); break;
+ case 0x15: sprintf(buffer, "recip.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
+ case 0x16: sprintf(buffer, "rsqrt.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
+ case 0x20: sprintf(buffer, "cvt.s.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
+ case 0x21: sprintf(buffer, "cvt.d.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
+ case 0x24: sprintf(buffer, "cvt.w.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
+ case 0x25: sprintf(buffer, "cvt.l.%s %s,%s", fmt, cpreg[1][fd], cpreg[1][fs]); break;
+ case 0x30: sprintf(buffer, "c.f.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
+ case 0x31: sprintf(buffer, "c.un.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
+ case 0x32: sprintf(buffer, "c.eq.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
+ case 0x33: sprintf(buffer, "c.ueq.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
+ case 0x34: sprintf(buffer, "c.olt.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
+ case 0x35: sprintf(buffer, "c.ult.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
+ case 0x36: sprintf(buffer, "c.ole.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
+ case 0x37: sprintf(buffer, "c.ule.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
+ case 0x38: sprintf(buffer, "c.sf.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
+ case 0x39: sprintf(buffer, "c.ngle.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7);break;
+ case 0x3a: sprintf(buffer, "c.seq.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
+ case 0x3b: sprintf(buffer, "c.ngl.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
+ case 0x3c: sprintf(buffer, "c.lt.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
+ case 0x3d: sprintf(buffer, "c.nge.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
+ case 0x3e: sprintf(buffer, "c.le.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
+ case 0x3f: sprintf(buffer, "c.ngt.%s %s,%s,%d", fmt, cpreg[1][fs], cpreg[1][ft], (op >> 8) & 7); break;
+ default: sprintf(buffer, "cop1 $%07x", op & 0x01ffffff); break;
+ }
+ break;
+ }
+ return flags;
+}
+
+static unsigned dasmr3k(char *buffer, unsigned pc, UINT32 op)
+{
+ int rs = (op >> 21) & 31;
+ int rt = (op >> 16) & 31;
+ int rd = (op >> 11) & 31;
+ int shift = (op >> 6) & 31;
+ UINT32 flags = 0;
+
+ switch (op >> 26)
+ {
+ case 0x00: /* SPECIAL */
+ switch (op & 63)
+ {
+ case 0x00: if (op == 0)
+ sprintf(buffer, "nop");
+ else
+ sprintf(buffer, "sll %s,%s,%d", reg[rd], reg[rt], shift); break;
+ case 0x02: sprintf(buffer, "srl %s,%s,%d", reg[rd], reg[rt], shift); break;
+ case 0x03: sprintf(buffer, "sra %s,%s,%d", reg[rd], reg[rt], shift); break;
+ case 0x04: sprintf(buffer, "sllv %s,%s,%s", reg[rd], reg[rt], reg[rs]); break;
+ case 0x06: sprintf(buffer, "srlv %s,%s,%s", reg[rd], reg[rt], reg[rs]); break;
+ case 0x07: sprintf(buffer, "srav %s,%s,%s", reg[rd], reg[rt], reg[rs]); break;
+ case 0x08: sprintf(buffer, "jr %s", reg[rs]); if (rs == 31) flags = DASMFLAG_STEP_OUT; break;
+ case 0x09: if (rd == 31)
+ sprintf(buffer, "jalr %s", reg[rs]);
+ else
+ sprintf(buffer, "jalr %s,%s", reg[rs], reg[rd]); flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1); break;
+ case 0x0c: sprintf(buffer, "syscall"); flags = DASMFLAG_STEP_OVER; break;
+ case 0x0d: sprintf(buffer, "break"); flags = DASMFLAG_STEP_OVER; break;
+ case 0x0f: sprintf(buffer, "sync [invalid]"); break;
+ case 0x10: sprintf(buffer, "mfhi %s", reg[rd]); break;
+ case 0x11: sprintf(buffer, "mthi %s", reg[rs]); break;
+ case 0x12: sprintf(buffer, "mflo %s", reg[rd]); break;
+ case 0x13: sprintf(buffer, "mtlo %s", reg[rs]); break;
+ case 0x18: sprintf(buffer, "mult %s,%s", reg[rs], reg[rt]); break;
+ case 0x19: sprintf(buffer, "multu %s,%s", reg[rs], reg[rt]); break;
+ case 0x1a: sprintf(buffer, "div %s,%s", reg[rs], reg[rt]); break;
+ case 0x1b: sprintf(buffer, "divu %s,%s", reg[rs], reg[rt]); break;
+ case 0x20: sprintf(buffer, "add %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
+ case 0x21: sprintf(buffer, "addu %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
+ case 0x22: sprintf(buffer, "sub %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
+ case 0x23: sprintf(buffer, "subu %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
+ case 0x24: sprintf(buffer, "and %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
+ case 0x25: sprintf(buffer, "or %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
+ case 0x26: sprintf(buffer, "xor %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
+ case 0x27: sprintf(buffer, "nor %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
+ case 0x2a: sprintf(buffer, "slt %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
+ case 0x2b: sprintf(buffer, "sltu %s,%s,%s", reg[rd], reg[rs], reg[rt]); break;
+ case 0x30: sprintf(buffer, "teq [invalid]"); break;
+ case 0x31: sprintf(buffer, "tgeu [invalid]"); break;
+ case 0x32: sprintf(buffer, "tlt [invalid]"); break;
+ case 0x33: sprintf(buffer, "tltu [invalid]"); break;
+ case 0x34: sprintf(buffer, "tge [invalid]"); break;
+ case 0x36: sprintf(buffer, "tne [invalid]"); break;
+ default: sprintf(buffer, "dc.l $%08x [invalid]", op); break;
+ }
+ break;
+
+ case 0x01: /* REGIMM */
+ switch ((op >> 16) & 31)
+ {
+ case 0x00: sprintf(buffer, "bltz %s,$%08x", reg[rs], pc + 4 + ((INT16)op << 2)); break;
+ case 0x01: sprintf(buffer, "bgez %s,$%08x", reg[rs], pc + 4 + ((INT16)op << 2)); break;
+ case 0x02: sprintf(buffer, "bltzl [invalid]"); break;
+ case 0x03: sprintf(buffer, "bgezl [invalid]"); break;
+ case 0x08: sprintf(buffer, "tgei [invalid]"); break;
+ case 0x09: sprintf(buffer, "tgeiu [invalid]"); break;
+ case 0x0a: sprintf(buffer, "tlti [invalid]"); break;
+ case 0x0b: sprintf(buffer, "tltiu [invalid]"); break;
+ case 0x0c: sprintf(buffer, "teqi [invalid]"); break;
+ case 0x0e: sprintf(buffer, "tnei [invalid]"); break;
+ case 0x10: sprintf(buffer, "bltzal %s,$%08x", reg[rs], pc + 4 + ((INT16)op << 2)); flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1); break;
+ case 0x11: sprintf(buffer, "bgezal %s,$%08x", reg[rs], pc + 4 + ((INT16)op << 2)); flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1); break;
+ case 0x12: sprintf(buffer, "bltzall [invalid]"); break;
+ case 0x13: sprintf(buffer, "bgezall [invalid]"); break;
+ default: sprintf(buffer, "dc.l $%08x [invalid]", op); break;
+ }
+ break;
+
+ case 0x02: sprintf(buffer, "j $%08x", (pc & 0xf0000000) | ((op & 0x0fffffff) << 2)); break;
+ case 0x03: sprintf(buffer, "jal $%08x", (pc & 0xf0000000) | ((op & 0x0fffffff) << 2)); flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1); break;
+ case 0x04: if (rs == 0 && rt == 0)
+ sprintf(buffer, "b $%08x", pc + 4 + ((INT16)op << 2));
+ else
+ sprintf(buffer, "beq %s,%s,$%08x", reg[rs], reg[rt], pc + 4 + ((INT16)op << 2));break;
+ case 0x05: sprintf(buffer, "bne %s,%s,$%08x", reg[rs], reg[rt], pc + 4 + ((INT16)op << 2));break;
+ case 0x06: sprintf(buffer, "blez %s,$%08x", reg[rs], pc + 4 + ((INT16)op << 2)); break;
+ case 0x07: sprintf(buffer, "bgtz %s,$%08x", reg[rs], pc + 4 + ((INT16)op << 2)); break;
+ case 0x08: sprintf(buffer, "addi %s,%s,%s", reg[rt], reg[rs], signed_16bit(op)); break;
+ case 0x09: sprintf(buffer, "addiu %s,%s,%s", reg[rt], reg[rs], signed_16bit(op)); break;
+ case 0x0a: sprintf(buffer, "slti %s,%s,%s", reg[rt], reg[rs], signed_16bit(op)); break;
+ case 0x0b: sprintf(buffer, "sltiu %s,%s,%s", reg[rt], reg[rs], signed_16bit(op)); break;
+ case 0x0c: sprintf(buffer, "andi %s,%s,$%04x", reg[rt], reg[rs], (UINT16)op); break;
+ case 0x0d: sprintf(buffer, "ori %s,%s,$%04x", reg[rt], reg[rs], (UINT16)op); break;
+ case 0x0e: sprintf(buffer, "xori %s,%s,$%04x", reg[rt], reg[rs], (UINT16)op); break;
+ case 0x0f: sprintf(buffer, "lui %s,$%04x", reg[rt], (UINT16)op); break;
+ case 0x10: flags = dasm_cop(pc, 0, op, buffer); break;
+ case 0x11: flags = dasm_cop1(pc, op, buffer); break;
+ case 0x12: flags = dasm_cop(pc, 2, op, buffer); break;
+ case 0x13: flags = dasm_cop(pc, 3, op, buffer); break;
+ case 0x14: sprintf(buffer, "beql [invalid]"); break;
+ case 0x15: sprintf(buffer, "bnel [invalid]"); break;
+ case 0x16: sprintf(buffer, "blezl [invalid]"); break;
+ case 0x17: sprintf(buffer, "bgtzl [invalid]"); break;
+ case 0x20: sprintf(buffer, "lb %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
+ case 0x21: sprintf(buffer, "lh %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
+ case 0x22: sprintf(buffer, "lwl %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
+ case 0x23: sprintf(buffer, "lw %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
+ case 0x24: sprintf(buffer, "lbu %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
+ case 0x25: sprintf(buffer, "lhu %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
+ case 0x26: sprintf(buffer, "lwr %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
+ case 0x28: sprintf(buffer, "sb %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
+ case 0x29: sprintf(buffer, "sh %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
+ case 0x2a: sprintf(buffer, "swl %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
+ case 0x2b: sprintf(buffer, "sw %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
+ case 0x2e: sprintf(buffer, "swr %s,%s(%s)", reg[rt], signed_16bit(op), reg[rs]); break;
+ case 0x2f: sprintf(buffer, "cache [invalid]"); break;
+ case 0x30: sprintf(buffer, "ll [invalid]"); break;
+ case 0x31: sprintf(buffer, "lwc1 %s,%s(%s)", cpreg[1][rt], signed_16bit(op), reg[rs]); break;
+ case 0x32: sprintf(buffer, "lwc2 %s,%s(%s)", cpreg[2][rt], signed_16bit(op), reg[rs]); break;
+ case 0x33: sprintf(buffer, "lwc3 %s,%s(%s)", cpreg[3][rt], signed_16bit(op), reg[rs]); break;
+ case 0x34: sprintf(buffer, "ldc0 [invalid]"); break;
+ case 0x35: sprintf(buffer, "ldc1 [invalid]"); break;
+ case 0x36: sprintf(buffer, "ldc2 [invalid]"); break;
+ case 0x37: sprintf(buffer, "ldc3 [invalid]"); break;
+ case 0x38: sprintf(buffer, "sc [invalid]"); break;
+ case 0x39: sprintf(buffer, "swc1 %s,%s(%s)", cpreg[1][rt], signed_16bit(op), reg[rs]); break;
+ case 0x3a: sprintf(buffer, "swc2 %s,%s(%s)", cpreg[2][rt], signed_16bit(op), reg[rs]); break;
+ case 0x3b: sprintf(buffer, "swc3 %s,%s(%s)", cpreg[3][rt], signed_16bit(op), reg[rs]); break;
+ case 0x3c: sprintf(buffer, "sdc0 [invalid]"); break;
+ case 0x3d: sprintf(buffer, "sdc1 [invalid]"); break;
+ case 0x3e: sprintf(buffer, "sdc2 [invalid]"); break;
+ case 0x3f: sprintf(buffer, "sdc3 [invalid]"); break;
+ default: sprintf(buffer, "dc.l $%08x [invalid]", op); break;
+ }
+ return 4 | flags | DASMFLAG_SUPPORTED;
+}
+
+
+CPU_DISASSEMBLE( r3000be )
+{
+ UINT32 op = *(UINT32 *)oprom;
+ op = BIG_ENDIANIZE_INT32(op);
+ return dasmr3k(buffer, pc, op);
+}
+
+
+CPU_DISASSEMBLE( r3000le )
+{
+ UINT32 op = *(UINT32 *)oprom;
+ op = LITTLE_ENDIANIZE_INT32(op);
+ return dasmr3k(buffer, pc, op);
+}
diff --git a/trunk/src/emu/cpu/mn10200/mn10200.c b/trunk/src/emu/cpu/mn10200/mn10200.c
new file mode 100644
index 00000000000..4ffb6ac3a88
--- /dev/null
+++ b/trunk/src/emu/cpu/mn10200/mn10200.c
@@ -0,0 +1,2440 @@
+/*
+ Panasonic MN10200 emulator
+
+ Written by Olivier Galibert
+ MAME conversion, timers, and IRQ controller by R. Belmont
+
+*/
+
+#include "emu.h"
+#include "debugger.h"
+#include "mn10200.h"
+
+#define log_write(...)
+#define log_event(...)
+
+#define MEM_BYTE (0)
+#define MEM_WORD (1)
+
+#define NUM_PRESCALERS (2)
+#define NUM_TIMERS_8BIT (10)
+#define NUM_IRQ_GROUPS (31)
+
+extern int mn102_disassemble(char *buffer, UINT32 pc, const UINT8 *oprom);
+
+typedef struct _mn102_info mn102_info;
+struct _mn102_info
+{
+ // The UINT32s are really UINT24
+ UINT32 pc;
+ UINT32 d[4];
+ UINT32 a[4];
+
+ UINT8 nmicr, iagr;
+ UINT8 icrl[NUM_IRQ_GROUPS], icrh[NUM_IRQ_GROUPS];
+ UINT16 psw;
+ UINT16 mdr;
+
+ struct _simple_timer {
+ UINT8 mode;
+ UINT8 base;
+ UINT8 cur;
+ } simple_timer[NUM_TIMERS_8BIT];
+
+ emu_timer *timer_timers[NUM_TIMERS_8BIT];
+
+ struct _prescaler {
+ UINT8 cycles;
+ UINT8 mode;
+ } prescaler[NUM_PRESCALERS];
+
+ struct _dma {
+ UINT32 adr;
+ UINT32 count;
+ UINT16 iadr;
+ UINT8 ctrll, ctrlh, irq;
+ } dma[8];
+
+ struct _serial {
+ UINT8 ctrll, ctrlh;
+ UINT8 buf;
+ } serial[2];
+
+ UINT8 ddr[8];
+
+ int cycles;
+
+ legacy_cpu_device *device;
+ address_space *program;
+ address_space *io;
+};
+
+static void mn10200_w(mn102_info *mn102, UINT32 adr, UINT32 data, int type);
+static UINT32 mn10200_r(mn102_info *mn102, UINT32 adr, int type);
+
+INLINE UINT8 mn102_read_byte(mn102_info *mn102, UINT32 address)
+{
+ if (address >= 0xfc00 && address < 0x10000)
+ {
+ return mn10200_r(mn102, address-0xfc00, MEM_BYTE);
+ }
+
+ return mn102->program->read_byte(address);
+}
+
+INLINE UINT16 mn102_read_word(mn102_info *mn102, UINT32 address)
+{
+ if (address >= 0xfc00 && address < 0x10000)
+ {
+ return mn10200_r(mn102, address-0xfc00, MEM_WORD);
+ }
+
+ if (address & 1)
+ {
+ return mn102->program->read_byte(address) | (mn102->program->read_byte(address+1)<<8);
+ }
+
+ return mn102->program->read_word(address);
+}
+
+INLINE void mn102_write_byte(mn102_info *mn102, UINT32 address, UINT8 data)
+{
+ if (address >= 0xfc00 && address < 0x10000)
+ {
+ mn10200_w(mn102, address-0xfc00, data, MEM_BYTE);
+ return;
+ }
+
+ mn102->program->write_byte(address, data);
+}
+
+INLINE void mn102_write_word(mn102_info *mn102, UINT32 address, UINT16 data)
+{
+ if (address >= 0xfc00 && address < 0x10000)
+ {
+ mn10200_w(mn102, address-0xfc00, data, MEM_WORD);
+ return;
+ }
+
+ if (address & 1)
+ {
+ mn102->program->write_byte(address, data&0xff);
+ mn102->program->write_byte(address+1, (data>>8)&0xff);
+ return;
+ }
+
+ mn102->program->write_word(address, data);
+}
+
+INLINE INT32 r24u(mn102_info *mn102, offs_t adr)
+{
+ return mn102_read_word(mn102, adr)|(mn102_read_byte(mn102, adr+2)<<16);
+}
+
+INLINE void w24(mn102_info *mn102, offs_t adr, UINT32 val)
+{
+/* if(adr == 0x4075aa || adr == 0x40689a || adr == 0x4075a2) {
+ log_write("TRACE", adr, val, MEM_LONG);
+ }*/
+ mn102_write_byte(mn102, adr, val);
+ mn102_write_byte(mn102, adr+1, val>>8);
+ mn102_write_byte(mn102, adr+2, val>>16);
+}
+
+INLINE void mn102_change_pc(mn102_info *mn102, UINT32 pc)
+{
+ mn102->pc = pc & 0xffffff;
+}
+
+INLINE mn102_info *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == MN10200);
+
+ return (mn102_info *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+static void mn102_take_irq(mn102_info *mn102, int level, int group)
+{
+ if(!(mn102->psw & 0x800))
+ {
+// if (group != 8) printf("MN10200: Dropping irq L %d G %d pc=%x, a3=%x\n", level, group, mn102->pc, mn102->a[3]);
+ return;
+ }
+
+// if (group != 8) printf("MN10200: Taking irq L %d G %d pc=%x, a3=%x\n", level, group, mn102->pc, mn102->a[3]);
+
+ mn102->a[3] -= 6;
+ w24(mn102, mn102->a[3]+2, mn102->pc);
+ mn102_write_word(mn102, mn102->a[3], mn102->psw);
+ mn102_change_pc(mn102, 0x80008);
+ mn102->psw = (mn102->psw & 0xf0ff) | (level << 8);
+ mn102->iagr = group << 1;
+}
+
+static void refresh_timer(mn102_info *cpustate, int tmr)
+{
+ // enabled?
+ if (cpustate->simple_timer[tmr].mode & 0x80)
+ {
+ UINT8 source = (cpustate->simple_timer[tmr].mode & 3);
+
+ // source is a prescaler?
+ if (source >= 2)
+ {
+ INT32 rate;
+
+ // is prescaler enabled?
+ if (cpustate->prescaler[source-2].mode & 0x80)
+ {
+ // rate = (sysclock / prescaler) / our count
+ rate = cpustate->device->unscaled_clock() / cpustate->prescaler[source-2].cycles;
+ rate /= cpustate->simple_timer[tmr].base;
+
+ if (tmr != 8) // HACK: timer 8 is run at 500 kHz by the Taito program for no obvious reason, which kills performance
+ cpustate->timer_timers[tmr]->adjust(attotime::from_hz(rate), tmr);
+ }
+ else
+ {
+ logerror("MN10200: timer %d using prescaler %d which isn't enabled!\n", tmr, source-2);
+ }
+ }
+ }
+ else // disabled, so stop it
+ {
+ cpustate->timer_timers[tmr]->adjust(attotime::never, tmr);
+ }
+}
+
+INLINE void timer_tick_simple(mn102_info *cpustate, int tmr)
+{
+ cpustate->simple_timer[tmr].cur--;
+
+ // did we expire?
+ if (cpustate->simple_timer[tmr].cur == 0)
+ {
+ int group, irq_in_grp, level;
+
+ // does timer auto-reload? apparently.
+ cpustate->simple_timer[tmr].cur = cpustate->simple_timer[tmr].base;
+
+ // signal the cascade if we're not timer 9
+ if (tmr < (NUM_TIMERS_8BIT-1))
+ {
+ // is next timer enabled?
+ if (cpustate->simple_timer[tmr+1].mode & 0x80)
+ {
+ // is it's source "cascade"?
+ if ((cpustate->simple_timer[tmr+1].mode & 0x3) == 1)
+ {
+ // recurse!
+ timer_tick_simple(cpustate, tmr+1);
+ }
+ }
+ }
+
+ // interrupt from this timer if possible
+ group = (tmr / 4);
+ irq_in_grp = (tmr % 4);
+ level = (cpustate->icrh[group]>>4) & 0x7;
+
+ // indicate interrupt pending
+ cpustate->icrl[group] |= (1 << (4 + irq_in_grp));
+
+ // interrupt detect = pending AND enable
+ cpustate->icrl[group] |= (cpustate->icrh[group]&0x0f) & (cpustate->icrl[group]>>4);
+
+ // is the result enabled?
+ if (cpustate->icrl[group] & (1 << irq_in_grp))
+ {
+// printf("Timer %d IRQ! (Group %d in_grp %d ICRH %x ICRL %x\n", tmr, group, irq_in_grp, cpustate->icrh[group], cpustate->icrl[group]);
+ // try to take it now
+ mn102_take_irq(cpustate, level, group + 1);
+ }
+ }
+}
+
+static TIMER_CALLBACK( simple_timer_cb )
+{
+ mn102_info *cpustate = (mn102_info *)ptr;
+ int tmr = param;
+
+ // handle our expiring and also tick our cascaded children
+ cpustate->simple_timer[tmr].cur = 1;
+ timer_tick_simple(cpustate, tmr);
+
+ // refresh this timer
+ refresh_timer(cpustate, tmr);
+}
+
+static CPU_INIT(mn10200)
+{
+ mn102_info *cpustate = get_safe_token(device);
+ int tmr;
+
+ memset(cpustate, 0, sizeof(mn102_info));
+
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->io = device->space(AS_IO);
+
+ device->save_item(NAME(cpustate->pc));
+ device->save_item(NAME(cpustate->d));
+ device->save_item(NAME(cpustate->a));
+ device->save_item(NAME(cpustate->nmicr));
+ device->save_item(NAME(cpustate->iagr));
+ device->save_item(NAME(cpustate->icrl));
+ device->save_item(NAME(cpustate->icrh));
+ device->save_item(NAME(cpustate->psw));
+ device->save_item(NAME(cpustate->mdr));
+// device->save_item(NAME(cpustate->simple_timer));
+// device->save_item(NAME(cpustate->prescaler));
+// device->save_item(NAME(cpustate->dma));
+// device->save_item(NAME(cpustate->serial));
+ device->save_item(NAME(cpustate->ddr));
+
+ for (tmr = 0; tmr < NUM_TIMERS_8BIT; tmr++)
+ {
+ cpustate->timer_timers[tmr] = device->machine().scheduler().timer_alloc(FUNC(simple_timer_cb), cpustate);
+ cpustate->timer_timers[tmr]->adjust(attotime::never, tmr);
+ }
+}
+
+static CPU_RESET(mn10200)
+{
+ mn102_info *cpustate = get_safe_token(device);
+ int tmr, grp;
+
+ memset(cpustate->d, 0, sizeof(cpustate->d));
+ memset(cpustate->a, 0, sizeof(cpustate->a));
+ cpustate->pc = 0x80000;
+ cpustate->psw = 0;
+ cpustate->nmicr = 0;
+ memset(cpustate->icrl, 0, sizeof(cpustate->icrl));
+ memset(cpustate->icrh, 0, sizeof(cpustate->icrh));
+
+ // reset all timers
+ for (tmr = 0; tmr < NUM_TIMERS_8BIT; tmr++)
+ {
+ cpustate->simple_timer[tmr].mode = 0;
+ cpustate->simple_timer[tmr].cur = 0;
+ cpustate->simple_timer[tmr].base = 0;
+ cpustate->timer_timers[tmr]->adjust(attotime::never, tmr);
+ }
+
+ // clear all interrupt groups
+ for (grp = 0; grp < NUM_IRQ_GROUPS; grp++)
+ {
+ cpustate->icrl[grp] = cpustate->icrh[grp] = 0;
+ }
+}
+
+static CPU_EXIT(mn10200)
+{
+}
+
+static void unemul(mn102_info *mn102)
+{
+ fatalerror("MN10200: unknown opcode @ PC=%x\n", mn102->pc);
+}
+
+static UINT32 do_add(mn102_info *mn102, UINT32 a, UINT32 b)
+{
+ UINT32 r24, r16;
+ r24 = (a & 0xffffff) + (b & 0xffffff);
+ r16 = (a & 0xffff) + (b & 0xffff);
+
+ mn102->psw &= 0xff00;
+ if((~(a^b)) & (a^r24) & 0x00800000)
+ mn102->psw |= 0x80;
+ if(r24 & 0x01000000)
+ mn102->psw |= 0x40;
+ if(r24 & 0x00800000)
+ mn102->psw |= 0x20;
+ if(!(r24 & 0x00ffffff))
+ mn102->psw |= 0x10;
+ if((~(a^b)) & (a^r16) & 0x00008000)
+ mn102->psw |= 0x08;
+ if(r16 & 0x00010000)
+ mn102->psw |= 0x04;
+ if(r16 & 0x00008000)
+ mn102->psw |= 0x02;
+ if(!(r16 & 0x0000ffff))
+ mn102->psw |= 0x01;
+ return r24 & 0xffffff;
+}
+
+static UINT32 do_addc(mn102_info *mn102, UINT32 a, UINT32 b)
+{
+ UINT32 r24, r16;
+ r24 = (a & 0xffffff) + (b & 0xffffff);
+ r16 = (a & 0xffff) + (b & 0xffff);
+
+ if(mn102->psw & 0x04) {
+ r24++;
+ r16++;
+ }
+
+ mn102->psw &= 0xff00;
+ if((~(a^b)) & (a^r24) & 0x00800000)
+ mn102->psw |= 0x80;
+ if(r24 & 0x01000000)
+ mn102->psw |= 0x40;
+ if(r24 & 0x00800000)
+ mn102->psw |= 0x20;
+ if(!(r24 & 0x00ffffff))
+ mn102->psw |= 0x10;
+ if((~(a^b)) & (a^r16) & 0x00008000)
+ mn102->psw |= 0x08;
+ if(r16 & 0x00010000)
+ mn102->psw |= 0x04;
+ if(r16 & 0x00008000)
+ mn102->psw |= 0x02;
+ if(!(r16 & 0x0000ffff))
+ mn102->psw |= 0x01;
+ return r24 & 0xffffff;
+}
+
+static UINT32 do_sub(mn102_info *mn102, UINT32 a, UINT32 b)
+{
+ UINT32 r24, r16;
+ r24 = (a & 0xffffff) - (b & 0xffffff);
+ r16 = (a & 0xffff) - (b & 0xffff);
+
+ mn102->psw &= 0xff00;
+ if((a^b) & (a^r24) & 0x00800000)
+ mn102->psw |= 0x80;
+ if(r24 & 0x01000000)
+ mn102->psw |= 0x40;
+ if(r24 & 0x00800000)
+ mn102->psw |= 0x20;
+ if(!(r24 & 0x00ffffff))
+ mn102->psw |= 0x10;
+ if((a^b) & (a^r16) & 0x00008000)
+ mn102->psw |= 0x08;
+ if(r16 & 0x00010000)
+ mn102->psw |= 0x04;
+ if(r16 & 0x00008000)
+ mn102->psw |= 0x02;
+ if(!(r16 & 0x0000ffff))
+ mn102->psw |= 0x01;
+ return r24 & 0xffffff;
+}
+
+static UINT32 do_subc(mn102_info *mn102, UINT32 a, UINT32 b)
+{
+ UINT32 r24, r16;
+ r24 = (a & 0xffffff) - (b & 0xffffff);
+ r16 = (a & 0xffff) - (b & 0xffff);
+
+ if(mn102->psw & 0x04) {
+ r24--;
+ r16--;
+ }
+
+ mn102->psw &= 0xff00;
+ if(r24 >= 0x00800000 && r24 < 0xff800000)
+ mn102->psw |= 0x80;
+ if(r24 & 0x01000000)
+ mn102->psw |= 0x40;
+ if(r24 & 0x00800000)
+ mn102->psw |= 0x20;
+ if(!(r24 & 0x00ffffff))
+ mn102->psw |= 0x10;
+ if(r16 >= 0x00008000 && r16 < 0xffff8000)
+ mn102->psw |= 0x08;
+ if(r16 & 0x00010000)
+ mn102->psw |= 0x04;
+ if(r16 & 0x00008000)
+ mn102->psw |= 0x02;
+ if(!(r16 & 0x0000ffff))
+ mn102->psw |= 0x01;
+ return r24 & 0xffffff;
+}
+
+INLINE void test_nz16(mn102_info *mn102, UINT16 v)
+{
+ mn102->psw &= 0xfff0;
+ if(v & 0x8000)
+ mn102->psw |= 2;
+ if(!v)
+ mn102->psw |= 1;
+}
+
+INLINE void do_jsr(mn102_info *mn102, UINT32 to, UINT32 ret)
+{
+ mn102_change_pc(mn102, to & 0xffffff);
+ mn102->a[3] -= 4;
+ w24(mn102, mn102->a[3], ret);
+}
+
+#if 0
+ log_event("MN102", "PSW change S=%d irq=%s im=%d %c%c%c%c %c%c%c%c",
+ (psw >> 12) & 3,
+ psw & 0x0800 ? "on" : "off",
+ (psw >> 8) & 7,
+ psw & 0x0080 ? 'V' : '-',
+ psw & 0x0040 ? 'C' : '-',
+ psw & 0x0020 ? 'N' : '-',
+ psw & 0x0010 ? 'Z' : '-',
+ psw & 0x0008 ? 'v' : '-',
+ psw & 0x0004 ? 'c' : '-',
+ psw & 0x0002 ? 'n' : '-',
+ psw & 0x0001 ? 'z' : '-');
+#endif
+
+// take an external IRQ
+static void mn102_extirq(mn102_info *mn102, int irqnum, int status)
+{
+ int level = (mn102->icrh[7]>>4)&0x7;
+
+// printf("mn102_extirq: irq %d status %d G8 ICRL %x\n", irqnum, status, mn102->icrl[7]);
+
+ // if interrupt is enabled, handle it
+ if (status)
+ {
+ // indicate interrupt pending
+ mn102->icrl[7] |= (1 << (4 + irqnum));
+
+ // set interrupt detect = pending AND enable
+ mn102->icrl[7] |= (mn102->icrh[7]&0x0f) & (mn102->icrl[7]>>4);
+
+ // is the result enabled?
+ if (mn102->icrl[7] & (1 << irqnum))
+ {
+ // try to take it now
+ mn102_take_irq(mn102, level, 8);
+ }
+ }
+}
+
+static CPU_EXECUTE(mn10200)
+{
+ mn102_info *mn102 = get_safe_token(device);
+
+ while(mn102->cycles > 0)
+ {
+ UINT8 opcode;
+
+ debugger_instruction_hook(device, mn102->pc);
+
+ opcode = mn102_read_byte(mn102, mn102->pc);
+ switch(opcode) {
+ // mov dm, (an)
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+ case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ mn102->cycles -= 1;
+ mn102_write_word(mn102, mn102->a[(opcode>>2)&3], (UINT16)mn102->d[opcode & 3]);
+ mn102->pc += 1;
+ break;
+
+ // movb dm, (an)
+ case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
+ case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ mn102->cycles -= 1;
+ mn102_write_byte(mn102, mn102->a[(opcode>>2)&3], (UINT8)mn102->d[opcode & 3]);
+ mn102->pc += 1;
+ break;
+
+ // mov (an), dm
+ case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ mn102->cycles -= 1;
+ mn102->d[opcode & 3] = (INT16)mn102_read_word(mn102, mn102->a[(opcode>>2)&3]);
+ mn102->pc += 1;
+ break;
+
+ // movbu (an), dm
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
+ case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
+ mn102->cycles -= 1;
+ mn102->d[opcode & 3] = mn102_read_byte(mn102, mn102->a[(opcode>>2)&3]);
+ mn102->pc += 1;
+ break;
+
+ // mov dm, (d8, an)
+ case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47:
+ case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f:
+ mn102->cycles -= 1;
+ mn102_write_word(mn102, (mn102->a[(opcode>>2)&3]+(INT8)mn102_read_byte(mn102, mn102->pc+1)) & 0xffffff, (UINT16)mn102->d[opcode & 3]);
+ mn102->pc += 2;
+ break;
+
+ // mov am, (d8, an)
+ case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57:
+ case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f:
+ mn102->cycles -= 2;
+ w24(mn102, (mn102->a[(opcode>>2)&3]+(INT8)mn102_read_byte(mn102, mn102->pc+1)) & 0xffffff, mn102->a[opcode & 3]);
+ mn102->pc += 2;
+ break;
+
+ // mov (d8, an), dm
+ case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67:
+ case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6e: case 0x6f:
+ mn102->cycles -= 1;
+ mn102->d[opcode & 3] = (INT16)mn102_read_word(mn102, (mn102->a[(opcode>>2) & 3] + (INT8)mn102_read_byte(mn102, mn102->pc+1)) & 0xffffff);
+ mn102->pc += 2;
+ break;
+
+ // mov (d8, an), am
+ case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77:
+ case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f:
+ mn102->cycles -= 2;
+ mn102->a[opcode & 3] = r24u(mn102, (mn102->a[(opcode>>2) & 3] + (INT8)mn102_read_byte(mn102, mn102->pc+1)) & 0xffffff);
+ mn102->pc += 2;
+ break;
+
+ // mov dm, dn
+ case 0x81: case 0x82: case 0x83: case 0x84: case 0x86: case 0x87:
+ case 0x88: case 0x89: case 0x8b: case 0x8c: case 0x8d: case 0x8e:
+ mn102->cycles -= 1;
+ mn102->d[opcode & 3] = mn102->d[(opcode>>2) & 3];
+ mn102->pc += 1;
+ break;
+
+ // mov imm8, dn
+ case 0x80: case 0x85: case 0x8a: case 0x8f:
+ mn102->cycles -= 1;
+ mn102->d[opcode & 3] = (INT8)mn102_read_byte(mn102, mn102->pc+1);
+ mn102->pc += 2;
+ break;
+
+ // add dn, dm
+ case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97:
+ case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f:
+ mn102->cycles -= 1;
+ mn102->d[opcode & 3] = do_add(mn102, mn102->d[opcode & 3], mn102->d[(opcode >> 2) & 3]);
+ mn102->pc += 1;
+ break;
+
+ // sub dn, dm
+ case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7:
+ case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf:
+ mn102->cycles -= 1;
+ mn102->d[opcode & 3] = do_sub(mn102, mn102->d[opcode & 3], mn102->d[(opcode >> 2) & 3]);
+ mn102->pc += 1;
+ break;
+
+ // extx dn
+ case 0xb0: case 0xb1: case 0xb2: case 0xb3:
+ mn102->cycles -= 1;
+ mn102->d[opcode & 3] = (INT16)mn102->d[opcode & 3] & 0xffffff;
+ mn102->pc += 1;
+ break;
+
+ // extxu dn
+ case 0xb4: case 0xb5: case 0xb6: case 0xb7:
+ mn102->cycles -= 1;
+ mn102->d[opcode & 3] = (UINT16)mn102->d[opcode & 3];
+ mn102->pc += 1;
+ break;
+
+ // extxb dn
+ case 0xb8: case 0xb9: case 0xba: case 0xbb:
+ mn102->cycles -= 1;
+ mn102->d[opcode & 3] = (INT8)mn102->d[opcode & 3] & 0xffffff;
+ mn102->pc += 1;
+ break;
+
+ // extxbu dn
+ case 0xbc: case 0xbd: case 0xbe: case 0xbf:
+ mn102->cycles -= 1;
+ mn102->d[opcode & 3] = (UINT8)mn102->d[opcode & 3];
+ mn102->pc += 1;
+ break;
+
+ // mov dn, (imm16)
+ case 0xc0: case 0xc1: case 0xc2: case 0xc3:
+ mn102->cycles -= 2;
+ mn102_write_word(mn102, mn102_read_word(mn102, mn102->pc+1), (UINT16)mn102->d[opcode & 3]);
+ mn102->pc += 3;
+ break;
+
+ // movb dn, (imm16)
+ case 0xc4: case 0xc5: case 0xc6: case 0xc7:
+ mn102->cycles -= 1;
+ mn102_write_byte(mn102, mn102_read_word(mn102, mn102->pc+1), (UINT8)mn102->d[opcode & 3]);
+ mn102->pc += 3;
+ break;
+
+ // mov (abs16), dn
+ case 0xc8: case 0xc9: case 0xca: case 0xcb:
+ mn102->cycles -= 1;
+ mn102->d[opcode & 3] = (INT16)mn102_read_word(mn102, mn102_read_word(mn102, mn102->pc+1));
+ mn102->pc += 3;
+ break;
+
+ // movbu (abs16), dn
+ case 0xcc: case 0xcd: case 0xce: case 0xcf:
+ mn102->cycles -= 2;
+ mn102->d[opcode & 3] = mn102_read_byte(mn102, mn102_read_word(mn102, mn102->pc+1));
+ mn102->pc += 3;
+ break;
+
+ // add imm8, an
+ case 0xd0: case 0xd1: case 0xd2: case 0xd3:
+ mn102->cycles -= 1;
+ mn102->a[opcode & 3] = do_add(mn102, mn102->a[opcode & 3], (INT8)mn102_read_byte(mn102, mn102->pc+1));
+ mn102->pc += 2;
+ break;
+
+ // add imm8, dn
+ case 0xd4: case 0xd5: case 0xd6: case 0xd7:
+ mn102->cycles -= 1;
+ mn102->d[opcode & 3] = do_add(mn102, mn102->d[opcode & 3], (INT8)mn102_read_byte(mn102, mn102->pc+1));
+ mn102->pc += 2;
+ break;
+
+ // cmp imm8, dn
+ case 0xd8: case 0xd9: case 0xda: case 0xdb:
+ mn102->cycles -= 1;
+ do_sub(mn102, mn102->d[opcode & 3], (INT8)mn102_read_byte(mn102, mn102->pc+1));
+ mn102->pc += 2;
+ break;
+
+ // mov imm16, an
+ case 0xdc: case 0xdd: case 0xde: case 0xdf:
+ mn102->cycles -= 1;
+ mn102->a[opcode & 3] = mn102_read_word(mn102, mn102->pc+1);
+ mn102->pc += 3;
+ break;
+
+ // blt label8
+ case 0xe0:
+ if(((mn102->psw & 0x0a) == 2) || ((mn102->psw & 0x0a) == 8))
+ {
+ mn102->cycles -= 2;
+ mn102_change_pc(mn102, mn102->pc+2+(INT8)mn102_read_byte(mn102, mn102->pc+1));
+ }
+ else
+ {
+ mn102->cycles -= 1;
+ mn102->pc += 2;
+ }
+ break;
+
+ // bgt label8
+ case 0xe1:
+ if(((mn102->psw & 0x0b) == 0) || ((mn102->psw & 0x0b) == 0xa))
+ {
+ mn102->cycles -= 2;
+ mn102_change_pc(mn102, mn102->pc+2+(INT8)mn102_read_byte(mn102, mn102->pc+1));
+ }
+ else
+ {
+ mn102->cycles -= 1;
+ mn102->pc += 2;
+ }
+ break;
+
+ // bge label8
+ case 0xe2:
+ if(((mn102->psw & 0x0a) == 0) || ((mn102->psw & 0x0a) == 0xa))
+ {
+ mn102->cycles -= 2;
+ mn102_change_pc(mn102, mn102->pc+2+(INT8)mn102_read_byte(mn102, mn102->pc+1));
+ }
+ else
+ {
+ mn102->cycles -= 1;
+ mn102->pc += 2;
+ }
+ break;
+
+ // ble label8
+ case 0xe3:
+ if((mn102->psw & 0x01) || ((mn102->psw & 0x0a) == 2) || ((mn102->psw & 0x0a) == 8))
+ {
+ mn102->cycles -= 2;
+ mn102_change_pc(mn102, mn102->pc+2+(INT8)mn102_read_byte(mn102, mn102->pc+1));
+ }
+ else
+ {
+ mn102->cycles -= 1;
+ mn102->pc += 2;
+ }
+ break;
+
+ // bcs label8
+ case 0xe4:
+ if(mn102->psw & 0x04)
+ {
+ mn102->cycles -= 2;
+ mn102_change_pc(mn102, mn102->pc+2+(INT8)mn102_read_byte(mn102, mn102->pc+1));
+ }
+ else
+ {
+ mn102->cycles -= 1;
+ mn102->pc += 2;
+ }
+ break;
+
+ // bhi label8
+ case 0xe5:
+ if(!(mn102->psw & 0x05))
+ {
+ mn102->cycles -= 2;
+ mn102_change_pc(mn102, mn102->pc+2+(INT8)mn102_read_byte(mn102, mn102->pc+1));
+ }
+ else
+ {
+ mn102->cycles -= 1;
+ mn102->pc += 2;
+ }
+ break;
+
+ // bcc label8
+ case 0xe6:
+ if(!(mn102->psw & 0x04))
+ {
+ mn102->cycles -= 2;
+ mn102_change_pc(mn102, mn102->pc+2+(INT8)mn102_read_byte(mn102, mn102->pc+1));
+ }
+ else
+ {
+ mn102->cycles -= 1;
+ mn102->pc += 2;
+ }
+ break;
+
+ // bls label8
+ case 0xe7:
+ if(mn102->psw & 0x05)
+ {
+ mn102->cycles -= 2;
+ mn102_change_pc(mn102, mn102->pc+2+(INT8)mn102_read_byte(mn102, mn102->pc+1));
+ }
+ else
+ {
+ mn102->cycles -= 1;
+ mn102->pc += 2;
+ }
+ break;
+
+ // beq label8
+ case 0xe8:
+ if(mn102->psw & 0x01)
+ {
+ mn102->cycles -= 2;
+ mn102_change_pc(mn102, mn102->pc+2+(INT8)mn102_read_byte(mn102, mn102->pc+1));
+ }
+ else
+ {
+ mn102->cycles -= 1;
+ mn102->pc += 2;
+ }
+ break;
+
+ // bne label8
+ case 0xe9:
+ if(!(mn102->psw & 0x01))
+ {
+ mn102->cycles -= 2;
+ mn102_change_pc(mn102, mn102->pc+2+(INT8)mn102_read_byte(mn102, mn102->pc+1));
+ }
+ else
+ {
+ mn102->cycles -= 1;
+ mn102->pc += 2;
+ }
+ break;
+
+ // bra label8
+ case 0xea:
+ mn102->cycles -= 2;
+ mn102_change_pc(mn102, mn102->pc+2+(INT8)mn102_read_byte(mn102, mn102->pc+1));
+ break;
+
+ // rti
+ case 0xeb:
+ mn102->cycles -= 6;
+ mn102->psw = mn102_read_word(mn102, mn102->a[3]);
+ mn102_change_pc(mn102, r24u(mn102, mn102->a[3]+2));
+ mn102->a[3] += 6;
+ break;
+
+ // cmp imm16, an
+ case 0xec: case 0xed: case 0xee: case 0xef:
+ mn102->cycles -= 1;
+ do_sub(mn102, mn102->a[opcode & 3], mn102_read_word(mn102, mn102->pc+1));
+ mn102->pc += 3;
+ break;
+
+ case 0xf0:
+ opcode = mn102_read_byte(mn102, mn102->pc+1);
+ switch(opcode) {
+ // jmp (an)
+ case 0x00: case 0x04: case 0x08: case 0x0c:
+ mn102->cycles -= 3;
+ mn102_change_pc(mn102, mn102->a[(opcode>>2) & 3]);
+ break;
+
+ // jsr (an)
+ case 0x01: case 0x05: case 0x09: case 0x0d:
+ mn102->cycles -= 5;
+ do_jsr(mn102, mn102->a[(opcode>>2) & 3], mn102->pc+2);
+ break;
+
+ // bset dm, (an)
+ case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f: {
+ UINT8 v;
+ mn102->cycles -= 5;
+ v = mn102_read_byte(mn102, mn102->a[(opcode>>2) & 3]);
+ test_nz16(mn102, v & mn102->d[opcode & 3]);
+ mn102_write_byte(mn102, mn102->a[(opcode>>2) & 3], v | mn102->d[opcode & 3]);
+ mn102->pc += 2;
+ break;
+ }
+
+ // bclr dm, (an)
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
+ case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f: {
+ UINT8 v;
+ mn102->cycles -= 5;
+ v = mn102_read_byte(mn102, mn102->a[(opcode>>2) & 3]);
+ test_nz16(mn102, v & mn102->d[opcode & 3]);
+ mn102_write_byte(mn102, mn102->a[(opcode>>2) & 3], v & ~mn102->d[opcode & 3]);
+ mn102->pc += 2;
+ break;
+ }
+
+ // movb (di, an), dm
+ case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47:
+ case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f:
+ case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57:
+ case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f:
+ case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67:
+ case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6e: case 0x6f:
+ case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77:
+ case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f:
+ mn102->cycles -= 2;
+ mn102->d[opcode & 3] = (INT8)mn102_read_byte(mn102, (mn102->a[(opcode>>2) & 3] + mn102->d[(opcode>>4) & 3]) & 0xffffff);
+ mn102->pc += 2;
+ break;
+
+ // movbu (di, an), dm
+ case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87:
+ case 0x88: case 0x89: case 0x8a: case 0x8b: case 0x8c: case 0x8d: case 0x8e: case 0x8f:
+ case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97:
+ case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f:
+ case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7:
+ case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf:
+ case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7:
+ case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf:
+ mn102->cycles -= 2;
+ mn102->d[opcode & 3] = mn102_read_byte(mn102, (mn102->a[(opcode>>2) & 3] + mn102->d[(opcode>>4) & 3]) & 0xffffff);
+ mn102->pc += 2;
+ break;
+
+ // movb dm, (di, an)
+ case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7:
+ case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf:
+ case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7:
+ case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf:
+ case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7:
+ case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef:
+ case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7:
+ case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff:
+ mn102->cycles -= 2;
+ mn102_write_byte(mn102, (mn102->a[(opcode>>2) & 3] + mn102->d[(opcode>>4) & 3]) & 0xffffff, mn102->d[opcode & 3]);
+ mn102->pc += 2;
+ break;
+
+ default:
+ unemul(mn102);
+ break;
+ }
+ break;
+
+ case 0xf1:
+ opcode = mn102_read_byte(mn102, mn102->pc+1);
+ switch(opcode>>6) {
+
+ // mov (di, an), am
+ case 0:
+ mn102->cycles -= 3;
+ mn102->a[opcode & 3] = r24u(mn102, (mn102->a[(opcode>>2) & 3] + mn102->d[(opcode>>4) & 3]) & 0xffffff);
+ mn102->pc += 2;
+ break;
+
+ // mov (di, an), dm
+ case 1:
+ mn102->cycles -= 2;
+ mn102->d[opcode & 3] = mn102_read_word(mn102, (mn102->a[(opcode>>2) & 3] + mn102->d[(opcode>>4) & 3]) & 0xffffff);
+ mn102->pc += 2;
+ break;
+
+ // mov am, (di, an)
+ case 2:
+ mn102->cycles -= 3;
+ w24(mn102, (mn102->a[(opcode>>2) & 3] + mn102->d[(opcode>>4) & 3]) & 0xffffff, mn102->a[opcode & 3]);
+ mn102->pc += 2;
+ break;
+
+ // mov dm, (di, an)
+ case 3:
+ mn102->cycles -= 2;
+ mn102_write_word(mn102, (mn102->a[(opcode>>2) & 3] + mn102->d[(opcode>>4) & 3]) & 0xffffff, mn102->d[opcode & 3]);
+ mn102->pc += 2;
+ break;
+
+ default:
+ unemul(mn102);
+ break;
+ }
+ break;
+
+ case 0xf2:
+ opcode = mn102_read_byte(mn102, mn102->pc+1);
+ switch(opcode>>4) {
+ // add dm, an
+ case 0x0:
+ mn102->cycles -= 2;
+ mn102->a[opcode & 3] = do_add(mn102, mn102->a[opcode & 3], mn102->d[(opcode>>2) & 3]);
+ mn102->pc += 2;
+ break;
+
+ // sub dm, an
+ case 0x1:
+ mn102->cycles -= 2;
+ mn102->a[opcode & 3] = do_sub(mn102, mn102->a[opcode & 3], mn102->d[(opcode>>2) & 3]);
+ mn102->pc += 2;
+ break;
+
+ // cmp dm, an
+ case 0x2:
+ mn102->cycles -= 2;
+ do_sub(mn102, mn102->a[opcode & 3], mn102->d[(opcode>>2) & 3]);
+ mn102->pc += 2;
+ break;
+
+ // mov am, dn
+ case 0x3:
+ mn102->cycles -= 2;
+ mn102->a[opcode & 3] = mn102->d[(opcode>>2) & 3];
+ mn102->pc += 2;
+ break;
+
+ // add am, an
+ case 0x4:
+ mn102->cycles -= 2;
+ mn102->a[opcode & 3] = do_add(mn102, mn102->a[opcode & 3], mn102->a[(opcode>>2) & 3]);
+ mn102->pc += 2;
+ break;
+
+ // sub am, an
+ case 0x5:
+ mn102->cycles -= 2;
+ mn102->a[opcode & 3] = do_sub(mn102, mn102->a[opcode & 3], mn102->a[(opcode>>2) & 3]);
+ mn102->pc += 2;
+ break;
+
+ // cmp am, an
+ case 0x6:
+ mn102->cycles -= 2;
+ do_sub(mn102, mn102->a[opcode & 3], mn102->a[(opcode>>2) & 3]);
+ mn102->pc += 2;
+ break;
+
+ // mov am, an
+ case 0x7:
+ mn102->cycles -= 2;
+ mn102->a[opcode & 3] = mn102->a[(opcode>>2) & 3];
+ mn102->pc += 2;
+ break;
+
+ // addc dm, dn
+ case 0x8:
+ mn102->cycles -= 2;
+ mn102->d[opcode & 3] = do_addc(mn102, mn102->d[opcode & 3], mn102->d[(opcode>>2) & 3]);
+ mn102->pc += 2;
+ break;
+
+ // subc dm, dn
+ case 0x9:
+ mn102->cycles -= 2;
+ mn102->d[opcode & 3] = do_subc(mn102, mn102->d[opcode & 3], mn102->d[(opcode>>2) & 3]);
+ mn102->pc += 2;
+ break;
+
+ // add am, dn
+ case 0xc:
+ mn102->cycles -= 2;
+ mn102->d[opcode & 3] = do_add(mn102, mn102->d[opcode & 3], mn102->a[(opcode>>2) & 3]);
+ mn102->pc += 2;
+ break;
+
+ // sub am, dn
+ case 0xd:
+ mn102->cycles -= 2;
+ mn102->d[opcode & 3] = do_sub(mn102, mn102->d[opcode & 3], mn102->a[(opcode>>2) & 3]);
+ mn102->pc += 2;
+ break;
+
+ // cmp am, dn
+ case 0xe:
+ mn102->cycles -= 2;
+ do_sub(mn102, mn102->d[opcode & 3], mn102->a[(opcode>>2) & 3]);
+ mn102->pc += 2;
+ break;
+
+ // mov an, dm
+ case 0xf:
+ mn102->cycles -= 2;
+ mn102->d[opcode & 3] = mn102->a[(opcode>>2) & 3];
+ mn102->pc += 2;
+ break;
+
+ default:
+ unemul(mn102);
+ break;
+ }
+ break;
+
+ case 0xf3:
+ opcode = mn102_read_byte(mn102, mn102->pc+1);
+ switch(opcode) {
+ // and dm, dn
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+ case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ mn102->cycles -= 2;
+ test_nz16(mn102, mn102->d[opcode & 3] &= 0xff0000|mn102->d[(opcode>>2) & 3]);
+ mn102->pc += 2;
+ break;
+
+ // or dm, dn
+ case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
+ case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ mn102->cycles -= 2;
+ test_nz16(mn102, mn102->d[opcode & 3] |= 0x00ffff&mn102->d[(opcode>>2) & 3]);
+ mn102->pc += 2;
+ break;
+
+ // xor dm, dn
+ case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ mn102->cycles -= 2;
+ test_nz16(mn102, mn102->d[opcode & 3] ^= 0x00ffff&mn102->d[(opcode>>2) & 3]);
+ mn102->pc += 2;
+ break;
+
+ // rol dn
+ case 0x30: case 0x31: case 0x32: case 0x33: {
+ UINT32 d = mn102->d[opcode & 3];
+ mn102->cycles -= 2;
+ test_nz16(mn102, mn102->d[opcode & 3] = (d & 0xff0000) | ((d << 1) & 0x00fffe) | ((mn102->psw & 0x04) ? 1 : 0));
+ if(d & 0x8000)
+ mn102->psw |= 0x04;
+ mn102->pc += 2;
+ break;
+ }
+
+ // ror dn
+ case 0x34: case 0x35: case 0x36: case 0x37: {
+ UINT32 d = mn102->d[opcode & 3];
+ mn102->cycles -= 2;
+ test_nz16(mn102, mn102->d[opcode & 3] = (d & 0xff0000) | ((d >> 1) & 0x007fff) | ((mn102->psw & 0x04) ? 0x8000 : 0));
+ if(d & 1)
+ mn102->psw |= 0x04;
+ mn102->pc += 2;
+ break;
+ }
+
+ // asr dn
+ case 0x38: case 0x39: case 0x3a: case 0x3b: {
+ UINT32 d = mn102->d[opcode & 3];
+ mn102->cycles -= 2;
+ test_nz16(mn102, mn102->d[opcode & 3] = (d & 0xff8000) | ((d >> 1) & 0x007fff));
+ if(d & 1)
+ mn102->psw |= 0x04;
+ mn102->pc += 2;
+ break;
+ }
+
+ // lsr dn
+ case 0x3c: case 0x3d: case 0x3e: case 0x3f: {
+ UINT32 d = mn102->d[opcode & 3];
+ mn102->cycles -= 2;
+ test_nz16(mn102, mn102->d[opcode & 3] = (d & 0xff0000) | ((d >> 1) & 0x007fff));
+ if(d & 1)
+ mn102->psw |= 0x04;
+ mn102->pc += 2;
+ break;
+ }
+
+ // mul dn, dm
+ case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47:
+ case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f: {
+ UINT32 res;
+ mn102->cycles -= 12;
+ res = ((INT16)mn102->d[opcode & 3])*((INT16)mn102->d[(opcode>>2) & 3]);
+ mn102->d[opcode & 3] = res & 0xffffff;
+ mn102->psw &= 0xff00;
+ if(res & 0x80000000)
+ mn102->psw |= 2;
+ if(!res)
+ mn102->psw |= 1;
+ mn102->mdr = res >> 16;
+ mn102->pc += 2;
+ break;
+ }
+
+ // mulu dn, dm
+ case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57:
+ case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f: {
+ UINT32 res;
+ mn102->cycles -= 12;
+ res = ((UINT16)mn102->d[opcode & 3])*((UINT16)mn102->d[(opcode>>2) & 3]);
+ mn102->d[opcode & 3] = res & 0xffffff;
+ mn102->psw &= 0xff00;
+ if(res & 0x80000000)
+ mn102->psw |= 2;
+ if(!res)
+ mn102->psw |= 1;
+ mn102->mdr = res >> 16;
+ mn102->pc += 2;
+ break;
+ }
+
+ // divu dn, dm
+ case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67:
+ case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6e: case 0x6f: {
+ UINT32 n, d, q, r;
+ mn102->cycles -= 13;
+ mn102->pc += 2;
+ mn102->psw &= 0xff00;
+
+ n = (mn102->mdr<<16)|(UINT16)mn102->d[opcode & 3];
+ d = (UINT16)mn102->d[(opcode>>2) & 3];
+ if(!d) {
+ mn102->psw |= 8;
+ break;
+ }
+ q = n/d;
+ r = n%d;
+ if(q >= 0x10000) {
+ mn102->psw |= 8;
+ break;
+ }
+ mn102->d[opcode & 3] = q;
+ mn102->mdr = r;
+ if(!q)
+ mn102->psw |= 0x11;
+ if(q & 0x8000)
+ mn102->psw |= 2;
+ break;
+ }
+
+ // cmp dm, dn
+ case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97:
+ case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f:
+ mn102->cycles -= 2;
+ do_sub(mn102, mn102->d[opcode & 3], mn102->d[(opcode>>2) & 3]);
+ mn102->pc += 2;
+ break;
+
+ // mov mdr, dn
+ case 0xc0: case 0xc4: case 0xc8: case 0xcc:
+ mn102->cycles -= 2;
+ mn102->mdr = mn102->d[(opcode>>2) & 3];
+ mn102->pc += 2;
+ break;
+
+ // ext dn
+ case 0xc1: case 0xc5: case 0xc9: case 0xcd:
+ mn102->cycles -= 3;
+ mn102->mdr = mn102->d[(opcode>>2) & 3] & 0x8000 ? 0xffff : 0x0000;
+ mn102->pc += 2;
+ break;
+
+ // mov dn, psw
+ case 0xd0: case 0xd4: case 0xd8: case 0xdc:
+ mn102->cycles -= 3;
+ mn102->psw = mn102->d[(opcode>>2) & 3];
+ mn102->pc += 2;
+ break;
+
+ // mov dn, mdr
+ case 0xe0: case 0xe1: case 0xe2: case 0xe3:
+ mn102->cycles -= 2;
+ mn102->d[opcode & 3] = mn102->mdr;
+ mn102->pc += 2;
+ break;
+
+ // not dn
+ case 0xe4: case 0xe5: case 0xe6: case 0xe7:
+ mn102->cycles -= 2;
+ test_nz16(mn102, mn102->d[opcode & 3] ^= 0x00ffff);
+ mn102->pc += 2;
+ break;
+
+ // mov psw, dn
+ case 0xf0: case 0xf1: case 0xf2: case 0xf3:
+ mn102->cycles -= 3;
+ mn102->d[(opcode>>2) & 3] = mn102->psw;
+ mn102->pc += 2;
+ break;
+
+ default:
+ unemul(mn102);
+ break;
+ }
+ break;
+
+ case 0xf4:
+ opcode = mn102_read_byte(mn102, mn102->pc+1);
+ switch(opcode) {
+ // mov dm, (abs24, an)
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+ case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ mn102->cycles -= 3;
+ mn102_write_word(mn102, (r24u(mn102, mn102->pc+2) + mn102->a[(opcode>>2) & 3]) & 0xffffff, mn102->d[opcode & 3]);
+ mn102->pc += 5;
+ break;
+
+ // mov am, (abs24, an)
+ case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
+ case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ mn102->cycles -= 4;
+ w24(mn102, (r24u(mn102, mn102->pc+2) + mn102->a[(opcode>>2) & 3]) & 0xffffff, mn102->a[opcode & 3]);
+ mn102->pc += 5;
+ break;
+
+ // movb dm, (abs24, an)
+ case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ mn102->cycles -= 3;
+ mn102_write_byte(mn102, (r24u(mn102, mn102->pc+2) + mn102->a[(opcode>>2) & 3]) & 0xffffff, mn102->d[opcode & 3]);
+ mn102->pc += 5;
+ break;
+
+ // movx dm, (abs24, an)
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
+ case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
+ mn102->cycles -= 4;
+ w24(mn102, (r24u(mn102, mn102->pc+2) + mn102->a[(opcode>>2) & 3]) & 0xffffff, mn102->d[opcode & 3]);
+ mn102->pc += 5;
+ break;
+
+ // mov dn, (abs24)
+ case 0x40: case 0x41: case 0x42: case 0x43:
+ mn102->cycles -= 3;
+ mn102_write_word(mn102, r24u(mn102, mn102->pc+2), mn102->d[opcode & 3]);
+ mn102->pc += 5;
+ break;
+
+ // movb dn, (abs24)
+ case 0x44: case 0x45: case 0x46: case 0x47:
+ mn102->cycles -= 3;
+ mn102_write_byte(mn102, r24u(mn102, mn102->pc+2), mn102->d[opcode & 3]);
+ mn102->pc += 5;
+ break;
+
+ // mov an, (abs24)
+ case 0x50: case 0x51: case 0x52: case 0x53:
+ mn102->cycles -= 4;
+ w24(mn102, r24u(mn102, mn102->pc+2), mn102->a[opcode & 3]);
+ mn102->pc += 5;
+ break;
+
+ // add abs24, dn
+ case 0x60: case 0x61: case 0x62: case 0x63:
+ mn102->cycles -= 3;
+ mn102->d[opcode & 3] = do_add(mn102, mn102->d[opcode & 3], r24u(mn102, mn102->pc+2));
+ mn102->pc += 5;
+ break;
+
+ // add abs24, an
+ case 0x64: case 0x65: case 0x66: case 0x67:
+ mn102->cycles -= 3;
+ mn102->a[opcode & 3] = do_add(mn102, mn102->a[opcode & 3], r24u(mn102, mn102->pc+2));
+ mn102->pc += 5;
+ break;
+
+ // sub abs24, dn
+ case 0x68: case 0x69: case 0x6a: case 0x6b:
+ mn102->cycles -= 3;
+ mn102->d[opcode & 3] = do_sub(mn102, mn102->d[opcode & 3], r24u(mn102, mn102->pc+2));
+ mn102->pc += 5;
+ break;
+
+ // sub abs24, an
+ case 0x6c: case 0x6d: case 0x6e: case 0x6f:
+ mn102->cycles -= 3;
+ mn102->a[opcode & 3] = do_sub(mn102, mn102->a[opcode & 3], r24u(mn102, mn102->pc+2));
+ mn102->pc += 5;
+ break;
+
+ // mov imm24, dn
+ case 0x70: case 0x71: case 0x72: case 0x73:
+ mn102->cycles -= 3;
+ mn102->d[opcode & 3] = r24u(mn102, mn102->pc+2);
+ mn102->pc += 5;
+ break;
+
+ // mov imm24, an
+ case 0x74: case 0x75: case 0x76: case 0x77:
+ mn102->cycles -= 3;
+ mn102->a[opcode & 3] = r24u(mn102, mn102->pc+2);
+ mn102->pc += 5;
+ break;
+
+ // cmp abs24, dn
+ case 0x78: case 0x79: case 0x7a: case 0x7b:
+ mn102->cycles -= 3;
+ do_sub(mn102, mn102->d[opcode & 3], r24u(mn102, mn102->pc+2));
+ mn102->pc += 5;
+ break;
+
+ // cmp abs24, an
+ case 0x7c: case 0x7d: case 0x7e: case 0x7f:
+ mn102->cycles -= 3;
+ do_sub(mn102, mn102->a[opcode & 3], r24u(mn102, mn102->pc+2));
+ mn102->pc += 5;
+ break;
+
+ // mov (abs24, an), dm
+ case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87:
+ case 0x88: case 0x89: case 0x8a: case 0x8b: case 0x8c: case 0x8d: case 0x8e: case 0x8f:
+ mn102->cycles -= 3;
+ mn102->d[opcode & 3] = (INT16)mn102_read_word(mn102, (mn102->a[(opcode>>2) & 3] + r24u(mn102, mn102->pc+2)) & 0xffffff);
+ mn102->pc += 5;
+ break;
+
+ // movbu (abs24, an), dm
+ case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97:
+ case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f:
+ mn102->cycles -= 3;
+ mn102->d[opcode & 3] = mn102_read_byte(mn102, (mn102->a[(opcode>>2) & 3] + r24u(mn102, mn102->pc+2)) & 0xffffff);
+ mn102->pc += 5;
+ break;
+
+ // movb (abs24, an), dm
+ case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7:
+ case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf:
+ mn102->cycles -= 3;
+ mn102->d[opcode & 3] = (INT8)mn102_read_byte(mn102, (mn102->a[(opcode>>2) & 3] + r24u(mn102, mn102->pc+2)) & 0xffffff);
+ mn102->pc += 5;
+ break;
+
+ // movx (abs24, an), dm
+ case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7:
+ case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf:
+ mn102->cycles -= 4;
+ mn102->d[opcode & 3] = r24u(mn102, (mn102->a[(opcode>>2) & 3] + r24u(mn102, mn102->pc+2)) & 0xffffff);
+ mn102->pc += 5;
+ break;
+
+ // mov (abs24), dn
+ case 0xc0: case 0xc1: case 0xc2: case 0xc3:
+ mn102->cycles -= 3;
+ mn102->d[opcode & 3] = (INT16)mn102_read_word(mn102, r24u(mn102, mn102->pc+2));
+ mn102->pc += 5;
+ break;
+
+ // movb (abs24), dn
+ case 0xc4: case 0xc5: case 0xc6: case 0xc7:
+ mn102->cycles -= 3;
+ mn102->d[opcode & 3] = (INT8)mn102_read_byte(mn102, r24u(mn102, mn102->pc+2));
+ mn102->pc += 5;
+ break;
+
+ // movbu (abs24), dn
+ case 0xc8: case 0xc9: case 0xca: case 0xcb:
+ mn102->cycles -= 3;
+ mn102->d[opcode & 3] = mn102_read_byte(mn102, r24u(mn102, mn102->pc+2));
+ mn102->pc += 5;
+ break;
+
+ // mov (abs24), an
+ case 0xd0: case 0xd1: case 0xd2: case 0xd3:
+ mn102->cycles -= 4;
+ mn102->a[opcode & 3] = r24u(mn102, r24u(mn102, mn102->pc+2));
+ mn102->pc += 5;
+ break;
+
+ // jmp imm24
+ case 0xe0:
+ mn102->cycles -= 4;
+ mn102_change_pc(mn102, mn102->pc+5+r24u(mn102, mn102->pc+2));
+ break;
+
+ // jsr label24
+ case 0xe1:
+ mn102->cycles -= 5;
+ do_jsr(mn102, mn102->pc+5+r24u(mn102, mn102->pc+2), mn102->pc+5);
+ break;
+
+
+ // mov (abs24, an), am
+ case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7:
+ case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff:
+ mn102->cycles -= 4;
+ mn102->a[opcode & 3] = r24u(mn102, (mn102->a[(opcode>>2) & 3] + r24u(mn102, mn102->pc+2)) & 0xffffff);
+ mn102->pc += 5;
+ break;
+
+ default:
+ unemul(mn102);
+ break;
+ }
+ break;
+
+ case 0xf5:
+ opcode = mn102_read_byte(mn102, mn102->pc+1);
+ switch(opcode) {
+
+ // and imm8, dn
+ case 0x00: case 0x01: case 0x02: case 0x03:
+ mn102->cycles -= 2;
+ test_nz16(mn102, mn102->d[opcode & 3] &= 0xff0000|mn102_read_byte(mn102, mn102->pc+2));
+ mn102->pc += 3;
+ break;
+
+ // btst imm8, dn
+ case 0x04: case 0x05: case 0x06: case 0x07:
+ mn102->cycles -= 2;
+ test_nz16(mn102, mn102->d[opcode & 3] & mn102_read_byte(mn102, mn102->pc+2));
+ mn102->pc += 3;
+ break;
+
+ // or imm8, dn
+ case 0x08: case 0x09: case 0x0a: case 0x0b:
+ mn102->cycles -= 2;
+ test_nz16(mn102, mn102->d[opcode & 3] |= mn102_read_byte(mn102, mn102->pc+2));
+ mn102->pc += 3;
+ break;
+
+ // addnf imm8, an
+ case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ mn102->cycles -= 2;
+ mn102->a[opcode & 3] = mn102->a[opcode & 3] +(INT8)mn102_read_byte(mn102, mn102->pc+2);
+ mn102->pc += 3;
+ break;
+
+ // movb dm, (d8, an)
+ case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
+ case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ mn102->cycles -= 2;
+ mn102_write_byte(mn102, (mn102->a[(opcode>>2) & 3]+(INT8)mn102_read_byte(mn102, mn102->pc+2)) & 0xffffff, mn102->d[opcode & 3]);
+ mn102->pc += 3;
+ break;
+
+ // movb (d8, an), dm
+ case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ mn102->cycles -= 2;
+ mn102->d[opcode & 3] = (INT8)mn102_read_byte(mn102, (mn102->a[(opcode>>2) & 3]+(INT8)mn102_read_byte(mn102, mn102->pc+2)) & 0xffffff);
+ mn102->pc += 3;
+ break;
+
+ // movbu (d8, an), dm
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
+ case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
+ mn102->cycles -= 2;
+ mn102->d[opcode & 3] = mn102_read_byte(mn102, (mn102->a[(opcode>>2) & 3]+(INT8)mn102_read_byte(mn102, mn102->pc+2)) & 0xffffff);
+ mn102->pc += 3;
+ break;
+
+ // movx dm, (d8, an)
+ case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57:
+ case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f:
+ mn102->cycles -= 3;
+ w24(mn102, (mn102->a[(opcode>>2) & 3]+(INT8)mn102_read_byte(mn102, mn102->pc+2)) & 0xffffff, mn102->d[opcode & 3]);
+ mn102->pc += 3;
+ break;
+
+ // movx (d8, an), dm
+ case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77:
+ case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f:
+ mn102->cycles -= 3;
+ mn102->d[opcode & 3] = r24u(mn102, (mn102->a[(opcode>>2) & 3]+(INT8)mn102_read_byte(mn102, mn102->pc+2)) & 0xffffff);
+ mn102->pc += 3;
+ break;
+
+ // bltx label8
+ case 0xe0:
+ if(((mn102->psw & 0xa0) == 0x20) || ((mn102->psw & 0xa0) == 0x80)) {
+ mn102->cycles -= 3;
+ mn102_change_pc(mn102, mn102->pc+3+(INT8)mn102_read_byte(mn102, mn102->pc+2));
+ } else {
+ mn102->cycles -= 2;
+ mn102->pc += 3;
+ }
+ break;
+
+ // bgtx label8
+ case 0xe1:
+ if(((mn102->psw & 0xb0) == 0) || ((mn102->psw & 0xb0) == 0xa0)) {
+ mn102->cycles -= 3;
+ mn102_change_pc(mn102, mn102->pc+3+(INT8)mn102_read_byte(mn102, mn102->pc+2));
+ } else {
+ mn102->cycles -= 2;
+ mn102->pc += 3;
+ }
+ break;
+
+ // bgex label8
+ case 0xe2:
+ if(((mn102->psw & 0xa0) == 0) || ((mn102->psw & 0xa0) == 0xa0)) {
+ mn102->cycles -= 3;
+ mn102_change_pc(mn102, mn102->pc+3+(INT8)mn102_read_byte(mn102, mn102->pc+2));
+ } else {
+ mn102->cycles -= 2;
+ mn102->pc += 3;
+ }
+ break;
+
+ // blex label8
+ case 0xe3:
+ if((mn102->psw & 0x10) || ((mn102->psw & 0xa0) == 0x20) || ((mn102->psw & 0xa0) == 0x80)) {
+ mn102->cycles -= 3;
+ mn102_change_pc(mn102, mn102->pc+3+(INT8)mn102_read_byte(mn102, mn102->pc+2));
+ } else {
+ mn102->cycles -= 2;
+ mn102->pc += 3;
+ }
+ break;
+
+ // bcsx label8
+ case 0xe4:
+ if(mn102->psw & 0x40) {
+ mn102->cycles -= 3;
+ mn102_change_pc(mn102, mn102->pc+3+(INT8)mn102_read_byte(mn102, mn102->pc+2));
+ } else {
+ mn102->cycles -= 2;
+ mn102->pc += 3;
+ }
+ break;
+
+ // bhix label8
+ case 0xe5:
+ if(!(mn102->psw & 0x50)) {
+ mn102->cycles -= 3;
+ mn102_change_pc(mn102, mn102->pc+3+(INT8)mn102_read_byte(mn102, mn102->pc+2));
+ } else {
+ mn102->cycles -= 2;
+ mn102->pc += 3;
+ }
+ break;
+
+ // bccx label8
+ case 0xe6:
+ if(!(mn102->psw & 0x40)) {
+ mn102->cycles -= 3;
+ mn102_change_pc(mn102, mn102->pc+3+(INT8)mn102_read_byte(mn102, mn102->pc+2));
+ } else {
+ mn102->cycles -= 2;
+ mn102->pc += 3;
+ }
+ break;
+
+ // blsx label8
+ case 0xe7:
+ if(mn102->psw & 0x50) {
+ mn102->cycles -= 3;
+ mn102_change_pc(mn102, mn102->pc+3+(INT8)mn102_read_byte(mn102, mn102->pc+2));
+ } else {
+ mn102->cycles -= 2;
+ mn102->pc += 3;
+ }
+ break;
+
+ // beqx label8
+ case 0xe8:
+ if(mn102->psw & 0x10) {
+ mn102->cycles -= 3;
+ mn102_change_pc(mn102, mn102->pc+3+(INT8)mn102_read_byte(mn102, mn102->pc+2));
+ } else {
+ mn102->cycles -= 2;
+ mn102->pc += 3;
+ }
+ break;
+
+ // bnex label8
+ case 0xe9:
+ if(!(mn102->psw & 0x10)) {
+ mn102->cycles -= 3;
+ mn102_change_pc(mn102, mn102->pc+3+(INT8)mn102_read_byte(mn102, mn102->pc+2));
+ } else {
+ mn102->cycles -= 2;
+ mn102->pc += 3;
+ }
+ break;
+
+
+ // bnc label8
+ case 0xfe:
+ if(!(mn102->psw & 0x02)) {
+ mn102->cycles -= 3;
+ mn102_change_pc(mn102, mn102->pc+3+(INT8)mn102_read_byte(mn102, mn102->pc+2));
+ } else {
+ mn102->cycles -= 2;
+ mn102->pc += 3;
+ }
+ break;
+
+ default:
+ unemul(mn102);
+ break;
+ }
+ break;
+
+ case 0xf7:
+ opcode = mn102_read_byte(mn102, mn102->pc+1);
+ switch(opcode) {
+ // and imm16, dn
+ case 0x00: case 0x01: case 0x02: case 0x03:
+ mn102->cycles -= 2;
+ test_nz16(mn102, mn102->d[opcode & 3] &= 0xff0000|mn102_read_word(mn102, mn102->pc+2));
+ mn102->pc += 4;
+ break;
+
+ // btst imm16, dn
+ case 0x04: case 0x05: case 0x06: case 0x07:
+ mn102->cycles -= 2;
+ test_nz16(mn102, mn102->d[opcode & 3] & mn102_read_word(mn102, mn102->pc+2));
+ mn102->pc += 4;
+ break;
+
+ // add imm16, an
+ case 0x08: case 0x09: case 0x0a: case 0x0b:
+ mn102->cycles -= 2;
+ mn102->a[opcode & 3] = do_add(mn102, mn102->a[opcode & 3], (INT16)mn102_read_word(mn102, mn102->pc+2));
+ mn102->pc += 4;
+ break;
+
+ // sub imm16, an
+ case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ mn102->cycles -= 2;
+ mn102->a[opcode & 3] = do_sub(mn102, mn102->a[opcode & 3], (INT16)mn102_read_word(mn102, mn102->pc+2));
+ mn102->pc += 4;
+ break;
+
+ // and imm16, psw
+ case 0x10:
+ mn102->cycles -= 3;
+ mn102->psw &= mn102_read_word(mn102, mn102->pc+2);
+ mn102->pc += 4;
+ break;
+
+ // or imm16, psw
+ case 0x14:
+ mn102->cycles -= 3;
+ mn102->psw |= mn102_read_word(mn102, mn102->pc+2);
+ mn102->pc += 4;
+ break;
+
+ // add imm16, dn
+ case 0x18: case 0x19: case 0x1a: case 0x1b:
+ mn102->cycles -= 2;
+ mn102->d[opcode & 3] = do_add(mn102, mn102->d[opcode & 3], (INT16)mn102_read_word(mn102, mn102->pc+2));
+ mn102->pc += 4;
+ break;
+
+ // sub imm16, dn
+ case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ mn102->cycles -= 2;
+ mn102->d[opcode & 3] = do_sub(mn102, mn102->d[opcode & 3], (INT16)mn102_read_word(mn102, mn102->pc+2));
+ mn102->pc += 4;
+ break;
+
+ // or imm16, dn
+ case 0x40: case 0x41: case 0x42: case 0x43:
+ mn102->cycles -= 3;
+ test_nz16(mn102, mn102->d[opcode & 3] |= mn102_read_word(mn102, mn102->pc+2));
+ mn102->pc += 4;
+ break;
+
+ // cmp imm16, dn
+ case 0x48: case 0x49: case 0x4a: case 0x4b:
+ mn102->cycles -= 2;
+ do_sub(mn102, mn102->d[opcode & 3], (INT16)mn102_read_word(mn102, mn102->pc+2));
+ mn102->pc += 4;
+ break;
+
+ // xor imm16, dn
+ case 0x4c: case 0x4d: case 0x4e: case 0x4f:
+ mn102->cycles -= 3;
+ test_nz16(mn102, mn102->d[opcode & 3] ^= mn102_read_word(mn102, mn102->pc+2));
+ mn102->pc += 4;
+ break;
+
+ // mov dm, (imm16, an)
+ case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87:
+ case 0x88: case 0x89: case 0x8a: case 0x8b: case 0x8c: case 0x8d: case 0x8e: case 0x8f:
+ mn102->cycles -= 2;
+ mn102_write_word(mn102, (mn102->a[(opcode>>2)&3]+(INT16)mn102_read_word(mn102, mn102->pc+2)) & 0xffffff, (UINT16)mn102->d[opcode & 3]);
+ mn102->pc += 4;
+ break;
+
+ // mov (imm16, an), dm
+ case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7:
+ case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf:
+ mn102->cycles -= 2;
+ mn102->d[opcode & 3] = (INT16)mn102_read_word(mn102, (mn102->a[(opcode>>2) & 3] + (INT16)mn102_read_byte(mn102, mn102->pc+2)) & 0xffffff) & 0xffffff;
+ mn102->pc += 4;
+ break;
+
+
+ default:
+ unemul(mn102);
+ break;
+ }
+ break;
+
+ // mov imm16, dn
+ case 0xf8: case 0xf9: case 0xfa: case 0xfb:
+ mn102->cycles -= 1;
+ mn102->d[opcode & 3] = (INT16)mn102_read_word(mn102, mn102->pc+1);
+ mn102->pc += 3;
+ break;
+
+ // jmp label16
+ case 0xfc:
+ mn102->cycles -= 2;
+ mn102_change_pc(mn102, mn102->pc+3+(INT16)mn102_read_word(mn102, mn102->pc+1));
+ break;
+
+ // jsr label16
+ case 0xfd:
+ mn102->cycles -= 4;
+ do_jsr(mn102, mn102->pc+3+(INT16)mn102_read_word(mn102, mn102->pc+1), mn102->pc+3);
+ break;
+
+ // rts
+ case 0xfe:
+ mn102->cycles -= 5;
+ mn102_change_pc(mn102, r24u(mn102, mn102->a[3]));
+ mn102->a[3] += 4;
+ break;
+
+ default:
+ unemul(mn102);
+ break;
+ }
+ }
+}
+
+static const char *const inames[10][4] = {
+ { "timer0", "timer1", "timer2", "timer3" },
+ { "timer4", "timer5", "timer6", "timer7" },
+ { "timer8", "timer9", "timer12a", "timer12b" },
+ { "timer10u", "timer10a", "timer10b", "?" },
+ { "timer11u", "timer11a", "timer11b", "?" },
+ { "dma0", "dma1", "dma2", "dma3" },
+ { "dma4", "dma5", "dma6", "dma7" },
+ { "X0", "X1", "X2", "X3" },
+ { "ser0tx", "ser0rx", "ser1tx", "ser1rx" },
+ { "key", "a/d", "?", "?" }
+};
+
+static void mn10200_w(mn102_info *mn102, UINT32 adr, UINT32 data, int type)
+{
+ if(type == MEM_WORD) {
+ mn10200_w(mn102, adr, data & 0xff, MEM_BYTE);
+ mn10200_w(mn102, adr+1, (data>>8) & 0xff, MEM_BYTE);
+ return;
+ }
+
+ switch(adr) {
+ case 0x000:
+ if(data & 12) {
+ log_event("CPU", "Stop request");
+ }
+ break;
+ case 0x001:
+ log_event("WATCHDOG", "Write %d", data>>7);
+ break;
+
+ case 0x002: case 0x003: // Memory control
+ break;
+
+ case 0x030: case 0x031: // Memory mode reg 0
+ case 0x032: case 0x033: // Memory mode reg 1
+ case 0x034: case 0x035: // Memory mode reg 2
+ case 0x036: case 0x037: // Memory mode reg 3
+ break;
+
+ // Non-Maskable irqs
+ case 0x040:
+ mn102->nmicr = data & 6;
+ break;
+ case 0x041:
+ break;
+
+ // Maskable irq control
+ case 0x042: case 0x044: case 0x046: case 0x048: case 0x04a:
+ case 0x04c: case 0x04e: case 0x050: case 0x052: case 0x054:
+ {
+ // note: writes here ack interrupts
+ mn102->icrl[((adr & 0x3f)>>1)-1] = data;
+ }
+ break;
+
+ case 0x043: case 0x045: case 0x047: case 0x049: case 0x04b:
+ case 0x04d: case 0x04f: case 0x051: case 0x053: case 0x055: {
+ int irq = ((adr & 0x3f)>>1)-1;
+ if((mn102->icrh[irq] != data) && (data & 15)) {
+ printf("MN10200: irq %d enabled, level=%x, enable= %s %s %s %s\n", irq+1, (data >> 4) & 7,
+ data & 1 ? inames[irq][0] : "-",
+ data & 2 ? inames[irq][1] : "-",
+ data & 4 ? inames[irq][2] : "-",
+ data & 8 ? inames[irq][3] : "-");
+ }
+ if((mn102->icrh[irq] != data) && !(data & 15)) {
+ printf("MN10200: irq %d disabled\n", irq+1);
+ }
+ mn102->icrh[irq] = data;
+ break;
+ }
+
+ case 0x056: {
+// const char *modes[4] = { "l", "h", "fall", "rise" };
+// log_event("MN102", "irq3=%s irq2=%s irq1=%s irq0=%s",
+// modes[(data >> 6) & 3], modes[(data >> 4) & 3], modes[(data >> 2) & 3], modes[data & 3]);
+ break;
+ }
+
+ case 0x057: {
+// const char *modes[4] = { "l", "1", "fall", "3" };
+// log_event("MN102", "irq_ki=%s", modes[data & 3]);
+ break;
+ }
+
+ case 0x100: case 0x101: // DRAM control reg
+ case 0x102: case 0x103: // Refresh counter
+ break;
+
+ case 0x180: case 0x190: {
+ int ser = (adr-0x180) >> 4;
+// const char *parity[8] = { "no", "1", "2", "3", "l", "h", "even", "odd" };
+// const char *source[4] = { "sbt0", "timer 8", "2", "timer 9" };
+ mn102->serial[ser].ctrll = data;
+
+// log_event("MN102", "Serial %d length=%c, parity=%s, stop=%c, source=%s",
+// ser,
+// data & 0x80 ? '8' : '7', parity[(data >> 4) & 7],
+// data & 8 ? '2' : '1', source[data & 3]);
+ break;
+ }
+
+ case 0x181: case 0x191: {
+ int ser = (adr-0x180) >> 4;
+ mn102->serial[ser].ctrlh = data;
+// log_event("MN102", "Serial %d transmit=%s, receive=%s, break=%s, proto=%s, order=%s",
+// ser,
+// data & 0x80 ? "on" : "off", data & 0x40 ? "on" : "off",
+// data & 0x20 ? "on" : "off", data & 8 ? "sync" : "async",
+// data & 2 ? "msb" : "lsb");
+ break;
+ }
+
+ case 0x182: case 0x192: {
+ int ser = (adr-0x180) >> 4;
+ mn102->serial[ser].buf = data;
+ log_event("MN102", "Serial %d buffer=%02x", ser, data);
+ break;
+ }
+
+ case 0x1a0:
+ log_event("MN102", "AN %s timer7=%s /%d %s %s",
+ data & 0x80 ? "on" : "off", data & 0x40 ? "on" : "off",
+ 1 << ((data >> 2) & 3), data & 2 ? "continuous" : "single", data & 1 ? "one" : "multi");
+ break;
+
+ case 0x1a1:
+ log_event("MN102", "AN chans=0-%d current=%d", (data >> 4) & 7, data & 7);
+ break;
+
+ case 0x210: case 0x211: case 0x212: case 0x213: case 0x214:
+ case 0x215: case 0x216: case 0x217: case 0x218: case 0x219:
+ mn102->simple_timer[adr-0x210].base = data + 1;
+// printf("MN10200: Timer %d value set %02x\n", adr-0x210, data);
+ refresh_timer(mn102, adr-0x210);
+ break;
+
+ case 0x21a:
+ mn102->prescaler[0].cycles = data+1;
+// printf("MN10200: Prescale 0 cycle count %d\n", data+1);
+ break;
+
+ case 0x21b:
+ mn102->prescaler[1].cycles = data+1;
+// printf("MN10200: Prescale 1 cycle count %d\n", data+1);
+ break;
+
+ case 0x220: case 0x221: case 0x222: case 0x223: case 0x224:
+ case 0x225: case 0x226: case 0x227: case 0x228: case 0x229:
+ {
+// const char *source[4] = { "TMxIO", "cascade", "prescale 0", "prescale 1" };
+ mn102->simple_timer[adr-0x220].mode = data;
+// printf("MN10200: Timer %d %s b6=%d, source=%s\n", adr-0x220, data & 0x80 ? "on" : "off", (data & 0x40) != 0, source[data & 3]);
+
+ if (data & 0x40)
+ {
+// printf("MN10200: loading timer %d\n", adr-0x220);
+ mn102->simple_timer[adr-0x220].cur = mn102->simple_timer[adr-0x220].base;
+ }
+ refresh_timer(mn102, adr-0x220);
+ break;
+ }
+
+ case 0x22a:
+// printf("MN10200: Prescale 0 %s, ps0bc %s\n",
+// data & 0x80 ? "on" : "off", data & 0x40 ? "-> ps0br" : "off");
+ mn102->prescaler[0].mode = data;
+ break;
+
+ case 0x22b:
+// printf("MN10200: Prescale 1 %s, ps1bc %s\n",
+// data & 0x80 ? "on" : "off", data & 0x40 ? "-> ps1br" : "off");
+ mn102->prescaler[1].mode = data;
+ break;
+
+ case 0x230: case 0x240: case 0x250:
+ {
+// const char *modes[4] = { "single", "double", "ioa", "iob" };
+// const char *sources[8] = { "pres.0", "pres.1", "iob", "sysclk", "*4", "*1", "6", "7" };
+// printf("MN10200: Timer %d comp=%s on_1=%s on_match=%s phase=%s source=%s\n",
+// 10 + ((adr-0x230) >> 4),
+// modes[data >> 6], data & 0x20 ? "cleared" : "not cleared", data & 0x10 ? "cleared" : "not cleared",
+// data & 8 ? "tff" : "rsff", sources[data & 7]);
+ break;
+ }
+
+ case 0x231: case 0x241: case 0x251:
+ {
+// const char *modes[4] = { "up", "down", "up on ioa", "up on iob" };
+// printf("MN10200: Timer %d %s ff=%s op=%s ext_trig=%s %s\n",
+// 10 + ((adr-0x230) >> 4),
+// data & 0x80 ? "enable" : "disable", data & 0x40 ? "operate" : "clear",
+// modes[(data >> 4) & 3], data & 2 ? "on" : "off", data & 1 ? "one-shot" : "repeat");
+
+ break;
+ }
+
+ case 0x234: case 0x244: case 0x254:
+ log_event("MN102", "Timer %d ca=--%02x", 10 + ((adr-0x230) >> 4), data);
+ break;
+
+ case 0x235: case 0x245: case 0x255:
+ log_event("MN102", "Timer %d ca=%02x--", 10 + ((adr-0x230) >> 4), data);
+ break;
+
+ case 0x236: case 0x246: case 0x256:
+ log_event("MN102", "Timer %d ca read trigger", 10 + ((adr-0x230) >> 4));
+ break;
+
+ case 0x237: case 0x247: case 0x257: break;
+
+ case 0x238: case 0x248: case 0x258:
+ log_event("MN102", "Timer %d cb=--%02x", 10 + ((adr-0x230) >> 4), data);
+ break;
+
+ case 0x239: case 0x249: case 0x259:
+ log_event("MN102", "Timer %d cb=%02x--", 10 + ((adr-0x230) >> 4), data);
+ break;
+
+ case 0x23a: case 0x24a: case 0x25a:
+ log_event("MN102", "Timer %d cb read trigger", 10 + ((adr-0x230) >> 4));
+ break;
+
+ case 0x23b: case 0x24b: case 0x25b: break;
+
+ case 0x260: case 0x261: {
+// const char *mode[4] = { "sysbuf", "4-phase", "4-phase 1/2", "3" };
+// log_event("MN102", "Sync Output %c timing=%s out=%s dir=%s mode=%s",
+// adr == 0x261 ? 'B' : 'A',
+// data & 0x10 ? "12A" : "1", data & 8 ? "sync a" :"P13-10",
+// data & 4 ? "ccw" : "cw", mode[data & 3]);
+ break;
+ }
+
+ case 0x262:
+ log_event("MN102", "Sync Output buffer = %02x", data);
+ break;
+
+ case 0x264:
+ mn102->io->write_byte(MN10200_PORT1, data);
+ break;
+
+ case 0x280: case 0x290: case 0x2a0: case 0x2b0: case 0x2c0: case 0x2d0: case 0x2e0: case 0x2f0: {
+ int dma = (adr-0x280) >> 4;
+ mn102->dma[dma].adr = (mn102->dma[dma].adr & 0x00ffff00) | data;
+ logerror("MN10200: DMA %d adr=%06x\n", dma, mn102->dma[dma].adr);
+ break;
+ }
+
+ case 0x281: case 0x291: case 0x2a1: case 0x2b1: case 0x2c1: case 0x2d1: case 0x2e1: case 0x2f1: {
+ int dma = (adr-0x280) >> 4;
+ mn102->dma[dma].adr = (mn102->dma[dma].adr & 0x00ff00ff) | (data << 8);
+ logerror("MN10200: DMA %d adr=%06x\n", dma, mn102->dma[dma].adr);
+ break;
+ }
+
+ case 0x282: case 0x292: case 0x2a2: case 0x2b2: case 0x2c2: case 0x2d2: case 0x2e2: case 0x2f2: {
+ int dma = (adr-0x280) >> 4;
+ mn102->dma[dma].adr = (mn102->dma[dma].adr & 0x0000ffff) | (data << 16);
+ logerror("MN10200: DMA %d adr=%06x\n", dma, mn102->dma[dma].adr);
+ break;
+ }
+
+ case 0x283: case 0x293: case 0x2a3: case 0x2b3: case 0x2c3: case 0x2d3: case 0x2e3: case 0x2f3:
+ break;
+
+ case 0x284: case 0x294: case 0x2a4: case 0x2b4: case 0x2c4: case 0x2d4: case 0x2e4: case 0x2f4: {
+ int dma = (adr-0x280) >> 4;
+ mn102->dma[dma].count = (mn102->dma[dma].count & 0x00ffff00) | data;
+ logerror("MN10200: DMA %d count=%06x\n", dma, mn102->dma[dma].count);
+ break;
+ }
+
+ case 0x285: case 0x295: case 0x2a5: case 0x2b5: case 0x2c5: case 0x2d5: case 0x2e5: case 0x2f5: {
+ int dma = (adr-0x280) >> 4;
+ mn102->dma[dma].count = (mn102->dma[dma].count & 0x00ff00ff) | (data << 8);
+ logerror("MN10200: DMA %d count=%06x\n", dma, mn102->dma[dma].count);
+ break;
+ }
+
+ case 0x286: case 0x296: case 0x2a6: case 0x2b6: case 0x2c6: case 0x2d6: case 0x2e6: case 0x2f6: {
+ int dma = (adr-0x280) >> 4;
+ mn102->dma[dma].count = (mn102->dma[dma].count & 0x0000ffff) | (data << 16);
+ logerror("MN10200: DMA %d count=%06x\n", dma, mn102->dma[dma].count);
+ break;
+ }
+
+ case 0x287: case 0x297: case 0x2a7: case 0x2b7: case 0x2c7: case 0x2d7: case 0x2e7: case 0x2f7:
+ break;
+
+ case 0x288: case 0x298: case 0x2a8: case 0x2b8: case 0x2c8: case 0x2d8: case 0x2e8: case 0x2f8: {
+ int dma = (adr-0x280) >> 4;
+ mn102->dma[dma].iadr = (mn102->dma[dma].iadr & 0xff00) | data;
+ logerror("MN10200: DMA %d iadr=%03x\n", dma, mn102->dma[dma].iadr);
+ break;
+ }
+
+ case 0x289: case 0x299: case 0x2a9: case 0x2b9: case 0x2c9: case 0x2d9: case 0x2e9: case 0x2f9: {
+ int dma = (adr-0x280) >> 4;
+ mn102->dma[dma].iadr = (mn102->dma[dma].iadr & 0x00ff) | ((data & 3) << 8);
+ logerror("MN10200: DMA %d iadr=%03x\n", dma, mn102->dma[dma].iadr);
+ break;
+ }
+
+ case 0x28a: case 0x29a: case 0x2aa: case 0x2ba: case 0x2ca: case 0x2da: case 0x2ea: case 0x2fa: {
+ static const char *const trans[4] = { "M-IO", "M-M", "M-X1", "m-X2" };
+ static const char *const start[32] = {
+ "soft", "a/d", "ser0tx", "set0rx", "ser1tx", "ser1rx",
+ "timer0", "timer1", "timer2", "timer3", "timer4", "timer5", "timer6", "timer7", "timer8", "timer9",
+ "timer10u", "timer10a", "timer10b",
+ "timer11u", "timer11a", "timer12b",
+ "timer12a", "timer12b",
+ "irq0", "irq1", "irq2", "irq3",
+ "X0e", "X1e", "X0l", "X1l"
+ };
+
+ int dma = (adr-0x280) >> 4;
+ mn102->dma[dma].ctrll = data;
+ logerror("MN10200: DMA %d control ack=%s, trans=%s, start=%s\n",
+ dma,
+ data & 0x80 ? "level" : "pulse",
+ trans[(data >> 5) & 3],
+ start[data & 31]);
+ break;
+ }
+
+ case 0x28b: case 0x29b: case 0x2ab: case 0x2bb: case 0x2cb: case 0x2db: case 0x2eb: case 0x2fb: {
+ static const char *const tradr[4] = { "inc", "dec", "fixed", "reserved" };
+ int dma = (adr-0x280) >> 4;
+ mn102->dma[dma].ctrlh = data;
+ logerror("MN10200: DMA %d control %s irq=%s %s %s dir=%s %s %s\n",
+ dma,
+ data & 0x80 ? "enable" : "disable",
+ data & 0x40 ? "off" : "on",
+ data & 0x20 ? "byte" : "word",
+ data & 0x10 ? "burst" : "single",
+ data & 0x08 ? "dst" : "src",
+ data & 0x04 ? "continue" : "normal",
+ tradr[data & 3]);
+ break;
+ }
+
+ case 0x28c: case 0x29c: case 0x2ac: case 0x2bc: case 0x2cc: case 0x2dc: case 0x2ec: case 0x2fc: {
+ int dma = (adr-0x280) >> 4;
+ mn102->dma[dma].irq = data & 7;
+ logerror("MN10200: DMA %d irq=%d\n", dma, data & 7);
+ break;
+ }
+
+ case 0x28d: case 0x29d: case 0x2ad: case 0x2bd: case 0x2cd: case 0x2dd: case 0x2ed: case 0x2fd:
+ break;
+
+ case 0x3b0:
+ log_event("MN102", "Pull-ups 0-7 = -%c%c%c%c%c%c%c",
+ data & 0x40 ? '#' : '.',
+ data & 0x20 ? '#' : '.',
+ data & 0x10 ? '#' : '.',
+ data & 0x08 ? '#' : '.',
+ data & 0x04 ? '#' : '.',
+ data & 0x02 ? '#' : '.',
+ data & 0x01 ? '#' : '.');
+ break;
+
+ case 0x3b1:
+ log_event("MN102", "Pull-ups 8-f = --%c%c%c%c%c%c",
+ data & 0x20 ? '#' : '.',
+ data & 0x10 ? '#' : '.',
+ data & 0x08 ? '#' : '.',
+ data & 0x04 ? '#' : '.',
+ data & 0x02 ? '#' : '.',
+ data & 0x01 ? '#' : '.');
+ break;
+
+ case 0x3b2:
+ log_event("MN102", "Timer I/O 4-0 = %c%c%c%c%c",
+ data & 0x10 ? 'o' : 'i',
+ data & 0x08 ? 'o' : 'i',
+ data & 0x04 ? 'o' : 'i',
+ data & 0x02 ? 'o' : 'i',
+ data & 0x01 ? 'o' : 'i');
+ break;
+
+ case 0x3b3:
+ log_event("MN102", "Timer I/O 12b/a-10b/a = %c%c %c%c %c%c",
+ data & 0x20 ? 'o' : 'i',
+ data & 0x10 ? 'o' : 'i',
+ data & 0x08 ? 'o' : 'i',
+ data & 0x04 ? 'o' : 'i',
+ data & 0x02 ? 'o' : 'i',
+ data & 0x01 ? 'o' : 'i');
+ break;
+
+ case 0x3c0: // port 0 data
+ mn102->io->write_byte(MN10200_PORT0, data);
+ break;
+
+ case 0x3c2: // port 2 data
+ mn102->io->write_byte(MN10200_PORT2, data);
+ break;
+
+ case 0x3c3: // port 3 data
+ mn102->io->write_byte(MN10200_PORT3, data);
+ break;
+
+ case 0x3e0: // port0 ddr
+ mn102->ddr[0] = data;
+ break;
+
+ case 0x3e1: // port1 ddr
+ mn102->ddr[1] = data;
+ break;
+
+ case 0x3e2: // port2 ddr
+ mn102->ddr[2] = data;
+ break;
+
+ case 0x3e3: // port3 ddr
+ mn102->ddr[3] = data;
+ break;
+
+ case 0x3f3:
+/* log_event("MN102", "Port 3 bits 4=%s 3=%s 2=%s 1=%s 0=%s",
+ data & 0x10 ? data & 0x40 ? "serial_1" : "tm9" : "p34",
+ data & 0x08 ? data & 0x20 ? "serial_0" : "tm8" : "p33",
+ data & 0x04 ? "tm7" : "p32",
+ data & 0x04 ? "tm6" : "p31",
+ data & 0x04 ? "tm5" : "p30");*/
+ break;
+
+
+ default:
+ log_event("MN102", "internal_w %04x, %02x (%03x)", adr+0xfc00, data, adr);
+ break;
+ }
+}
+
+static UINT32 mn10200_r(mn102_info *mn102, UINT32 adr, int type)
+{
+ if(type == MEM_WORD)
+ {
+ return mn10200_r(mn102, adr, MEM_BYTE) | (mn10200_r(mn102, adr+1, MEM_BYTE) << 8);
+ }
+
+ switch(adr) {
+ case 0x00e:
+ return mn102->iagr;
+
+ case 0x00f:
+ return 0;
+
+ case 0x042: case 0x044: case 0x046: case 0x048: case 0x04a:
+ case 0x04c: case 0x04e: case 0x050: case 0x052: case 0x054:
+ return mn102->icrl[((adr & 0x3f)>>1)-1];
+
+ case 0x043: case 0x045: case 0x047: case 0x049: case 0x04b:
+ case 0x04d: case 0x04f: case 0x051: case 0x053: case 0x055:
+ return mn102->icrh[((adr & 0x3f)>>1)-1];
+
+ case 0x056:
+ return 0;
+
+ // p4i1 = tms empty line
+ case 0x057:
+ return 0x20;
+
+ case 0x180: case 0x190:
+ return mn102->serial[(adr-0x180) >> 4].ctrll;
+
+ case 0x181: case 0x191:
+ return mn102->serial[(adr-0x180) >> 4].ctrlh;
+
+ case 0x182: {
+ static int zz;
+ return zz++;
+ }
+
+ case 0x183:
+ return 0x10;
+
+ case 0x200: case 0x201: case 0x202: case 0x203: case 0x204:
+ case 0x205: case 0x206: case 0x207: case 0x208: case 0x209:
+// printf("MN10200: timer %d value read = %d\n", adr-0x200, mn102->simple_timer[adr-0x200].cur);
+ return mn102->simple_timer[adr-0x200].cur;
+ break;
+
+ case 0x264: // port 1 data
+ return mn102->io->read_byte(MN10200_PORT1);
+
+ case 0x28c: case 0x29c: case 0x2ac: case 0x2bc: case 0x2cc: case 0x2dc: case 0x2ec: case 0x2fc:
+ {
+ int dma = (adr-0x280) >> 4;
+ return mn102->dma[dma].irq;
+ }
+
+ case 0x3c0: // port 0 data
+ return mn102->io->read_byte(MN10200_PORT0);
+
+ case 0x3c2: // port 2 data
+ return mn102->io->read_byte(MN10200_PORT2);
+
+ case 0x3c3: // port 3 data
+ return mn102->io->read_byte(MN10200_PORT3);
+
+ default:
+ log_event("MN102", "internal_r %04x (%03x)", adr+0xfc00, adr);
+ }
+
+ return 0;
+}
+
+static CPU_SET_INFO(mn10200)
+{
+ mn102_info *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_PC: /* intentional fallthrough */
+ case CPUINFO_INT_REGISTER + MN10200_PC: cpustate->pc = info->i; break;
+ case CPUINFO_INT_REGISTER + MN10200_PSW: cpustate->psw = info->i; break;
+ case CPUINFO_INT_REGISTER + MN10200_MDR: cpustate->mdr = info->i; break;
+ case CPUINFO_INT_REGISTER + MN10200_D0: cpustate->d[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + MN10200_D1: cpustate->d[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + MN10200_D2: cpustate->d[2] = info->i; break;
+ case CPUINFO_INT_REGISTER + MN10200_D3: cpustate->d[3] = info->i; break;
+ case CPUINFO_INT_REGISTER + MN10200_A0: cpustate->a[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + MN10200_A1: cpustate->a[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + MN10200_A2: cpustate->a[2] = info->i; break;
+ case CPUINFO_INT_REGISTER + MN10200_A3: cpustate->a[3] = info->i; break;
+ case CPUINFO_INT_REGISTER + MN10200_NMICR: cpustate->nmicr = info->i; break;
+ case CPUINFO_INT_REGISTER + MN10200_IAGR: cpustate->iagr = info->i; break;
+
+ case CPUINFO_INT_INPUT_STATE + MN10200_IRQ0: mn102_extirq(cpustate, 0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + MN10200_IRQ1: mn102_extirq(cpustate, 1, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + MN10200_IRQ2: mn102_extirq(cpustate, 2, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + MN10200_IRQ3: mn102_extirq(cpustate, 3, info->i); break;
+ }
+}
+
+CPU_GET_INFO( mn10200 )
+{
+ mn102_info *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch(state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(mn102_info); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 0; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 8; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 24; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_PC: /* intentional fallthrough */
+ case CPUINFO_INT_REGISTER + MN10200_PC: info->i = cpustate->pc; break;
+ case CPUINFO_INT_REGISTER + MN10200_PSW: info->i = cpustate->psw; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(mn10200); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(mn10200); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(mn10200); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(mn10200); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(mn10200); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(mn10200); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->cycles; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "Panasonic MN10200"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "MN10200"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Nicola Salmoria and the MAME Team"); break;
+
+ case CPUINFO_STR_FLAGS: // intentional fallthrough
+ case CPUINFO_STR_REGISTER + MN10200_PSW: sprintf(info->s, "S=%d irq=%s im=%d %c%c%c%c %c%c%c%c",
+ (cpustate->psw >> 12) & 3,
+ cpustate->psw & 0x0800 ? "on" : "off",
+ (cpustate->psw >> 8) & 7,
+ cpustate->psw & 0x0080 ? 'V' : '-',
+ cpustate->psw & 0x0040 ? 'C' : '-',
+ cpustate->psw & 0x0020 ? 'N' : '-',
+ cpustate->psw & 0x0010 ? 'Z' : '-',
+ cpustate->psw & 0x0008 ? 'v' : '-',
+ cpustate->psw & 0x0004 ? 'c' : '-',
+ cpustate->psw & 0x0002 ? 'n' : '-',
+ cpustate->psw & 0x0001 ? 'z' : '-');
+ break;
+
+ case CPUINFO_STR_REGISTER + MN10200_MDR: sprintf(info->s, "MDR: %04x", cpustate->mdr); break;
+
+ case CPUINFO_STR_REGISTER + MN10200_D0: sprintf(info->s, "D0: %06x", cpustate->d[0]); break;
+ case CPUINFO_STR_REGISTER + MN10200_D1: sprintf(info->s, "D1: %06x", cpustate->d[1]); break;
+ case CPUINFO_STR_REGISTER + MN10200_D2: sprintf(info->s, "D2: %06x", cpustate->d[2]); break;
+ case CPUINFO_STR_REGISTER + MN10200_D3: sprintf(info->s, "D3: %06x", cpustate->d[3]); break;
+ case CPUINFO_STR_REGISTER + MN10200_A0: sprintf(info->s, "A0: %06x", cpustate->a[0]); break;
+ case CPUINFO_STR_REGISTER + MN10200_A1: sprintf(info->s, "A1: %06x", cpustate->a[1]); break;
+ case CPUINFO_STR_REGISTER + MN10200_A2: sprintf(info->s, "A2: %06x", cpustate->a[2]); break;
+ case CPUINFO_STR_REGISTER + MN10200_A3: sprintf(info->s, "A3: %06x", cpustate->a[3]); break;
+
+ case CPUINFO_STR_REGISTER + MN10200_NMICR: sprintf(info->s, "MNICR: %02x", cpustate->nmicr); break;
+ case CPUINFO_STR_REGISTER + MN10200_IAGR: sprintf(info->s, "IAGR: %02x", cpustate->iagr); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(MN10200, mn10200);
diff --git a/trunk/src/emu/cpu/mn10200/mn10200.h b/trunk/src/emu/cpu/mn10200/mn10200.h
new file mode 100644
index 00000000000..4aa45352fda
--- /dev/null
+++ b/trunk/src/emu/cpu/mn10200/mn10200.h
@@ -0,0 +1,52 @@
+/*
+ Panasonic MN10200 emulator
+
+ Written by Olivier Galibert
+ MAME conversion by R. Belmont
+
+*/
+
+#pragma once
+
+#ifndef MN10200_H
+#define MN10200_H
+
+enum
+{
+ MN10200_PC,
+ MN10200_PSW,
+ MN10200_MDR,
+ MN10200_D0,
+ MN10200_D1,
+ MN10200_D2,
+ MN10200_D3,
+ MN10200_A0,
+ MN10200_A1,
+ MN10200_A2,
+ MN10200_A3,
+ MN10200_NMICR,
+ MN10200_IAGR
+};
+
+enum
+{
+ MN10200_PORT0,
+ MN10200_PORT1,
+ MN10200_PORT2,
+ MN10200_PORT3,
+ MN10200_PORT4
+};
+
+enum
+{
+ MN10200_IRQ0,
+ MN10200_IRQ1,
+ MN10200_IRQ2,
+ MN10200_IRQ3
+};
+
+DECLARE_LEGACY_CPU_DEVICE(MN10200, mn10200);
+
+CPU_DISASSEMBLE( mn10200 );
+
+#endif
diff --git a/trunk/src/emu/cpu/mn10200/mn102dis.c b/trunk/src/emu/cpu/mn10200/mn102dis.c
new file mode 100644
index 00000000000..6c0da6fbe7c
--- /dev/null
+++ b/trunk/src/emu/cpu/mn10200/mn102dis.c
@@ -0,0 +1,1033 @@
+#include "emu.h"
+
+#include <stdio.h>
+
+static const UINT8 *sOpROM; // current opROM pointer
+static UINT32 sBasePC;
+
+static UINT8 program_read_byte(offs_t pc)
+{
+ return sOpROM[pc - sBasePC];
+}
+
+static UINT32 r16u(offs_t pc)
+{
+ return sOpROM[pc - sBasePC] | (sOpROM[pc - sBasePC + 1]<<8);
+}
+
+static INT32 r16s(offs_t pc)
+{
+ return (INT16)(sOpROM[pc - sBasePC] | (sOpROM[pc - sBasePC + 1]<<8));
+}
+
+static INT32 r24u(offs_t pc)
+{
+ return sOpROM[pc - sBasePC] | (sOpROM[pc - sBasePC + 1]<<8) | (sOpROM[pc - sBasePC + 2]<<16);
+}
+
+static INT32 r24s(offs_t pc)
+{
+ return sOpROM[pc - sBasePC] | (sOpROM[pc - sBasePC + 1]<<8) | ((INT8)sOpROM[pc - sBasePC + 2]<<16);
+}
+
+static const char *i8str(INT8 v)
+{
+ static char res[4];
+ if(v>=0)
+ sprintf(res, "%x", v);
+ else
+ sprintf(res, "-%x", (UINT8)(-v));
+ return res;
+}
+
+static const char *i16str(INT16 v)
+{
+ static char res[6];
+ if(v>=0)
+ sprintf(res, "%x", v);
+ else
+ sprintf(res, "-%x", (UINT16)(-v));
+ return res;
+}
+
+static const char *i24str(INT32 v)
+{
+ static char res[8];
+ if(v>=0)
+ sprintf(res, "%x", v);
+ else
+ sprintf(res, "-%x", -v);
+ return res;
+}
+
+
+static int mn102_disassemble(char *buffer, UINT32 pc, const UINT8 *oprom)
+{
+ UINT8 opcode;
+
+ sOpROM = oprom;
+ sBasePC = pc;
+
+ opcode = program_read_byte(pc);
+ switch(opcode) {
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+ case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ sprintf(buffer, "mov d%d, (a%d)", opcode & 3, (opcode>>2) & 3);
+ return 1;
+
+ case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
+ case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ sprintf(buffer, "movb d%d, (a%d)", opcode & 3, (opcode>>2) & 3);
+ return 1;
+
+ case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ sprintf(buffer, "mov (a%d), d%d", (opcode>>2) & 3, opcode & 3);
+ return 1;
+
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
+ case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
+ sprintf(buffer, "movbu (a%d), d%d", (opcode>>2) & 3, opcode & 3);
+ return 1;
+
+ case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47:
+ case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f:
+ sprintf(buffer, "mov d%d, (%s, a%d)", opcode & 3, i8str(program_read_byte(pc+1)), (opcode>>2) & 3);
+ return 2;
+
+ case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57:
+ case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f:
+ sprintf(buffer, "mov a%d, (%s, a%d)", opcode & 3, i8str(program_read_byte(pc+1)), (opcode>>2) & 3);
+ return 2;
+
+ case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67:
+ case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6e: case 0x6f:
+ sprintf(buffer, "mov (%s, a%d), d%d", i8str(program_read_byte(pc+1)), (opcode>>2) & 3, opcode & 3);
+ return 2;
+
+ case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77:
+ case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f:
+ sprintf(buffer, "mov (%s, a%d), a%d", i8str(program_read_byte(pc+1)), (opcode>>2) & 3, opcode & 3);
+ return 2;
+
+ case 0x81: case 0x82: case 0x83: case 0x84: case 0x86: case 0x87:
+ case 0x88: case 0x89: case 0x8b: case 0x8c: case 0x8d: case 0x8e:
+ sprintf(buffer, "mov d%d, d%d", (opcode>>2) & 3, opcode & 3);
+ return 1;
+
+ case 0x80: case 0x85: case 0x8a: case 0x8f:
+ sprintf(buffer, "mov %s, d%d", i8str(program_read_byte(pc+1)), opcode & 3);
+ return 2;
+
+ case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97:
+ case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f:
+ sprintf(buffer, "add d%d, d%d", (opcode>>2) & 3, opcode & 3);
+ return 1;
+
+ case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7:
+ case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf:
+ sprintf(buffer, "sub d%d, d%d", (opcode>>2) & 3, opcode & 3);
+ return 1;
+
+ case 0xb0: case 0xb1: case 0xb2: case 0xb3:
+ sprintf(buffer, "extx d%d", opcode & 3);
+ return 1;
+
+ case 0xb4: case 0xb5: case 0xb6: case 0xb7:
+ sprintf(buffer, "extxu d%d", opcode & 3);
+ return 1;
+
+ case 0xb8: case 0xb9: case 0xba: case 0xbb:
+ sprintf(buffer, "extxb d%d", opcode & 3);
+ return 1;
+
+ case 0xbc: case 0xbd: case 0xbe: case 0xbf:
+ sprintf(buffer, "extxbu d%d", opcode & 3);
+ return 1;
+
+ case 0xc0: case 0xc1: case 0xc2: case 0xc3:
+ sprintf(buffer, "mov d%d, (%x)", opcode & 3, r16u(pc+1));
+ return 3;
+
+ case 0xc4: case 0xc5: case 0xc6: case 0xc7:
+ sprintf(buffer, "movb d%d, (%04x)", opcode & 3, r16u(pc+1));
+ return 3;
+
+ case 0xc8: case 0xc9: case 0xca: case 0xcb:
+ sprintf(buffer, "mov (%04x), d%d", r16u(pc+1), opcode & 3);
+ return 3;
+
+ case 0xcc: case 0xcd: case 0xce: case 0xcf:
+ sprintf(buffer, "movbu (%04x), d%d", r16u(pc+1), opcode & 3);
+ return 3;
+
+ case 0xd0: case 0xd1: case 0xd2: case 0xd3:
+ sprintf(buffer, "add %s, a%d", i8str(program_read_byte(pc+1)), opcode & 3);
+ return 2;
+
+ case 0xd4: case 0xd5: case 0xd6: case 0xd7:
+ sprintf(buffer, "add %s, d%d", i8str(program_read_byte(pc+1)), opcode & 3);
+ return 2;
+
+ case 0xd8: case 0xd9: case 0xda: case 0xdb:
+ sprintf(buffer, "cmp %s, d%d", i8str(program_read_byte(pc+1)), opcode & 3);
+ return 2;
+
+ case 0xdc: case 0xdd: case 0xde: case 0xdf:
+ sprintf(buffer, "move %x, a%d", r16u(pc+1), opcode & 3);
+ return 3;
+
+ case 0xe0:
+ sprintf(buffer, "blt %x", (pc+2+(INT8)program_read_byte(pc+1)) & 0xffffff);
+ return 2;
+
+ case 0xe1:
+ sprintf(buffer, "bgt %x", (pc+2+(INT8)program_read_byte(pc+1)) & 0xffffff);
+ return 2;
+
+ case 0xe2:
+ sprintf(buffer, "bge %x", (pc+2+(INT8)program_read_byte(pc+1)) & 0xffffff);
+ return 2;
+
+ case 0xe3:
+ sprintf(buffer, "ble %x", (pc+2+(INT8)program_read_byte(pc+1)) & 0xffffff);
+ return 2;
+
+ case 0xe4:
+ sprintf(buffer, "bcs %x", (pc+2+(INT8)program_read_byte(pc+1)) & 0xffffff);
+ return 2;
+
+ case 0xe5:
+ sprintf(buffer, "bhi %x", (pc+2+(INT8)program_read_byte(pc+1)) & 0xffffff);
+ return 2;
+
+ case 0xe6:
+ sprintf(buffer, "bcc %x", (pc+2+(INT8)program_read_byte(pc+1)) & 0xffffff);
+ return 2;
+
+ case 0xe7:
+ sprintf(buffer, "bls %x", (pc+2+(INT8)program_read_byte(pc+1)) & 0xffffff);
+ return 2;
+
+ case 0xe8:
+ sprintf(buffer, "beq %x", (pc+2+(INT8)program_read_byte(pc+1)) & 0xffffff);
+ return 2;
+
+ case 0xe9:
+ sprintf(buffer, "bne %x", (pc+2+(INT8)program_read_byte(pc+1)) & 0xffffff);
+ return 2;
+
+ case 0xea:
+ sprintf(buffer, "bra %x", (pc+2+(INT8)program_read_byte(pc+1)) & 0xffffff);
+ return 2;
+
+ case 0xeb:
+ sprintf(buffer, "rti");
+ return 1;
+
+ case 0xec: case 0xed: case 0xee: case 0xef:
+ sprintf(buffer, "cmp %x, a%d", r16u(pc+1), opcode & 3);
+ return 3;
+
+ case 0xf0:
+ opcode = program_read_byte(pc+1);
+ switch(opcode) {
+ case 0x00: case 0x04: case 0x08: case 0x0c:
+ sprintf(buffer, "jmp (a%d)", (opcode>>2) & 3);
+ return 2;
+
+ case 0x01: case 0x05: case 0x09: case 0x0d:
+ sprintf(buffer, "jsr (a%d)", (opcode>>2) & 3);
+ return 2;
+
+ case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ sprintf(buffer, "bset d%d, (a%d)", opcode & 3, (opcode>>2) & 3);
+ return 2;
+
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
+ case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
+ sprintf(buffer, "bclr d%d, (a%d)", opcode & 3, (opcode>>2) & 3);
+ return 2;
+
+ case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47:
+ case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f:
+ case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57:
+ case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f:
+ case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67:
+ case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6e: case 0x6f:
+ case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77:
+ case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f:
+ sprintf(buffer, "movb (d%d, a%d), d%d", (opcode>>4) & 3, (opcode>>2) & 3, opcode & 3);
+ return 2;
+
+ case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87:
+ case 0x88: case 0x89: case 0x8a: case 0x8b: case 0x8c: case 0x8d: case 0x8e: case 0x8f:
+ case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97:
+ case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f:
+ case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7:
+ case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf:
+ case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7:
+ case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf:
+ sprintf(buffer, "movbu (d%d, a%d), d%d", (opcode>>4) & 3, (opcode>>2) & 3, opcode & 3);
+ return 2;
+
+ case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7:
+ case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf:
+ case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7:
+ case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf:
+ case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7:
+ case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef:
+ case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7:
+ case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff:
+ sprintf(buffer, "movb d%d, (d%d, a%d)", opcode & 3, (opcode>>4) & 3, (opcode>>2) & 3);
+ return 2;
+
+ default:
+ goto illegal2;
+ }
+ break;
+
+ case 0xf1:
+ opcode = program_read_byte(pc+1);
+ switch(opcode>>6) {
+ case 0x00:
+ sprintf(buffer, "mov (d%d, a%d), a%d", (opcode>>4) & 3, (opcode>>2) & 3, opcode & 3);
+ return 2;
+
+ case 0x01:
+ sprintf(buffer, "mov (d%d, a%d), d%d", (opcode>>4) & 3, (opcode>>2) & 3, opcode & 3);
+ return 2;
+
+ case 0x02:
+ sprintf(buffer, "mov a%d, (d%d, a%d)", opcode & 3, (opcode>>4) & 3, (opcode>>2) & 3);
+ return 2;
+
+ case 0x03:
+ sprintf(buffer, "mov d%d, (d%d, a%d)", opcode & 3, (opcode>>4) & 3, (opcode>>2) & 3);
+ return 2;
+
+ default:
+ goto illegal2;
+ }
+ break;
+
+ case 0xf2:
+ opcode = program_read_byte(pc+1);
+ switch(opcode>>4) {
+ case 0x0:
+ sprintf(buffer, "add d%d, a%d", (opcode>>2) & 3, opcode & 3);
+ return 2;
+
+ case 0x1:
+ sprintf(buffer, "sub d%d, a%d", (opcode>>2) & 3, opcode & 3);
+ return 2;
+
+ case 0x2:
+ sprintf(buffer, "cmp d%d, a%d", (opcode>>2) & 3, opcode & 3);
+ return 2;
+
+ case 0x3:
+ sprintf(buffer, "mov d%d, a%d", (opcode>>2) & 3, opcode & 3);
+ return 2;
+
+ case 0x4:
+ sprintf(buffer, "add a%d, a%d", (opcode>>2) & 3, opcode & 3);
+ return 2;
+
+ case 0x5:
+ sprintf(buffer, "sub a%d, a%d", (opcode>>2) & 3, opcode & 3);
+ return 2;
+
+ case 0x6:
+ sprintf(buffer, "cmp a%d, a%d", (opcode>>2) & 3, opcode & 3);
+ return 2;
+
+ case 0x7:
+ sprintf(buffer, "mov a%d, a%d", (opcode>>2) & 3, opcode & 3);
+ return 2;
+
+ case 0x8:
+ sprintf(buffer, "addc d%d, d%d", (opcode>>2) & 3, opcode & 3);
+ return 2;
+
+ case 0x9:
+ sprintf(buffer, "subc d%d, d%d", (opcode>>2) & 3, opcode & 3);
+ return 2;
+
+ case 0xc:
+ sprintf(buffer, "add a%d, d%d", (opcode>>2) & 3, opcode & 3);
+ return 2;
+
+ case 0xd:
+ sprintf(buffer, "sub a%d, d%d", (opcode>>2) & 3, opcode & 3);
+ return 2;
+
+ case 0xe:
+ sprintf(buffer, "cmp a%d, d%d", (opcode>>2) & 3, opcode & 3);
+ return 2;
+
+ case 0xf:
+ sprintf(buffer, "mov a%d, d%d", (opcode>>2) & 3, opcode & 3);
+ return 2;
+
+ default:
+ goto illegal2;
+ }
+ break;
+
+ case 0xf3:
+ opcode = program_read_byte(pc+1);
+ switch(opcode) {
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+ case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ sprintf(buffer, "and d%d, d%d", (opcode>>2) & 3, opcode & 3);
+ return 2;
+
+ case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
+ case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ sprintf(buffer, "or d%d, d%d", (opcode>>2) & 3, opcode & 3);
+ return 2;
+
+ case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ sprintf(buffer, "xor d%d, d%d", (opcode>>2) & 3, opcode & 3);
+ return 2;
+
+ case 0x30: case 0x31: case 0x32: case 0x33:
+ sprintf(buffer, "rol d%d", opcode & 3);
+ return 2;
+
+ case 0x34: case 0x35: case 0x36: case 0x37:
+ sprintf(buffer, "ror d%d", opcode & 3);
+ return 2;
+
+ case 0x38: case 0x39: case 0x3a: case 0x3b:
+ sprintf(buffer, "asr d%d", opcode & 3);
+ return 2;
+
+ case 0x3c: case 0x3d: case 0x3e: case 0x3f:
+ sprintf(buffer, "lsr d%d", opcode & 3);
+ return 2;
+
+ case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47:
+ case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f:
+ sprintf(buffer, "mul d%d, d%d", (opcode>>2) & 3, opcode & 3);
+ return 2;
+
+ case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57:
+ case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f:
+ sprintf(buffer, "mulu d%d, d%d", (opcode>>2) & 3, opcode & 3);
+ return 2;
+
+ case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67:
+ case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6e: case 0x6f:
+ sprintf(buffer, "divu d%d, d%d", (opcode>>2) & 3, opcode & 3);
+ return 2;
+
+ case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97:
+ case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f:
+ sprintf(buffer, "cmp d%d, d%d", (opcode>>2) & 3, opcode & 3);
+ return 2;
+
+ case 0xc0: case 0xc4: case 0xc8: case 0xcc:
+ sprintf(buffer, "mov d%d, mdr", (opcode>>2) & 3);
+ return 2;
+
+ case 0xc1: case 0xc5: case 0xc9: case 0xcd:
+ sprintf(buffer, "ext d%d", (opcode>>2) & 3);
+ return 2;
+
+ case 0xd0: case 0xd4: case 0xd8: case 0xdc:
+ sprintf(buffer, "mov d%d, psw", (opcode>>2) & 3);
+ return 2;
+
+ case 0xe0: case 0xe1: case 0xe2: case 0xe3:
+ sprintf(buffer, "mov mdr, d%d", opcode & 3);
+ return 2;
+
+ case 0xe4: case 0xe5: case 0xe6: case 0xe7:
+ sprintf(buffer, "not d%d", opcode & 3);
+ return 2;
+
+ case 0xf0: case 0xf1: case 0xf2: case 0xf3:
+ sprintf(buffer, "mov psw, d%d", opcode & 3);
+ return 2;
+
+ case 0xfc:
+ sprintf(buffer, "pxst");
+ return 2;
+
+ case 0xfe:
+ opcode = program_read_byte(pc+2);
+ switch(opcode) {
+ case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7:
+ sprintf(buffer, "tbz (%x) %d, %x", r24u(pc+3), opcode & 7,
+ (pc+7+(INT8)program_read_byte(pc+6)) & 0xffffff);
+ return 7;
+
+ case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf:
+ sprintf(buffer, "tbnz (%x) %d, %x", r24u(pc+3), opcode & 7,
+ (pc+7+(INT8)program_read_byte(pc+6)) & 0xffffff);
+ return 7;
+
+ case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7:
+ sprintf(buffer, "bset (%x) %d", r24u(pc+2), opcode & 7);
+ return 6;
+
+ case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf:
+ sprintf(buffer, "bclr (%x) %d", r24u(pc+2), opcode & 7);
+ return 6;
+
+ default:
+ goto illegal3;
+ }
+ break;
+
+ case 0xff:
+ opcode = program_read_byte(pc+2);
+ switch(opcode) {
+ case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87:
+ case 0x88: case 0x89: case 0x8a: case 0x8b: case 0x8c: case 0x8d: case 0x8e: case 0x8f:
+ sprintf(buffer, "tbz (%s, a%d) %d, %x", i8str(program_read_byte(pc+3)), 2+((opcode>>3)&1), opcode & 7,
+ (pc+5+(INT8)program_read_byte(pc+4)) & 0xffffff);
+ return 5;
+
+ case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97:
+ case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f:
+ sprintf(buffer, "bset (%s, a%d) %d", i8str(program_read_byte(pc+3)), 2+((opcode>>3)&1), opcode & 7);
+ return 4;
+
+ case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7:
+ case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf:
+ sprintf(buffer, "tbnz (%s, a%d) %d, %x", i8str(program_read_byte(pc+3)), 2+((opcode>>3)&1), opcode & 7,
+ (pc+5+(INT8)program_read_byte(pc+4)) & 0xffffff);
+ return 5;
+
+ case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7:
+ case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf:
+ sprintf(buffer, "bclr (%s, a%d) %d", i8str(program_read_byte(pc+3)), 2+((opcode>>3)&1), opcode & 7);
+ return 4;
+
+ default:
+ goto illegal3;
+ }
+ break;
+
+ default:
+ goto illegal2;
+ }
+ break;
+
+ case 0xf4:
+ opcode = program_read_byte(pc+1);
+ switch(opcode) {
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+ case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ sprintf(buffer, "mov d%d, (%s, a%d)", opcode & 3, i24str(r24s(pc+2)), (opcode>>2) & 3);
+ return 5;
+
+ case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
+ case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ sprintf(buffer, "mov a%d, (%s, a%d)", opcode & 3, i24str(r24s(pc+2)), (opcode>>2) & 3);
+ return 5;
+
+ case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ sprintf(buffer, "movb d%d, (%s, a%d)", opcode & 3, i24str(r24s(pc+2)), (opcode>>2) & 3);
+ return 5;
+
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
+ case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
+ sprintf(buffer, "movx d%d, (%s, a%d)", opcode & 3, i24str(r24s(pc+2)), (opcode>>2) & 3);
+ return 5;
+
+ case 0x40: case 0x41: case 0x42: case 0x43:
+ sprintf(buffer, "mov d%d, (%x)", opcode & 3, r24u(pc+2));
+ return 5;
+
+ case 0x44: case 0x45: case 0x46: case 0x47:
+ sprintf(buffer, "movb d%d, (%x)", opcode & 3, r24u(pc+2));
+ return 5;
+
+ #if 0 // huh?
+ case 0x4b:
+ sprintf(buffer, "bset %02x, (%x)", program_read_byte(pc+5), r24u(pc+2));
+ return 6;
+
+ case 0x4f:
+ sprintf(buffer, "bclr %02x, (%x)", program_read_byte(pc+5), r24u(pc+2));
+ return 6;
+ #endif
+
+ case 0x50: case 0x51: case 0x52: case 0x53:
+ sprintf(buffer, "mov a%d, (%x)", opcode & 3, r24u(pc+2));
+ return 5;
+
+ case 0x60: case 0x61: case 0x62: case 0x63:
+ sprintf(buffer, "add %s, d%d", i24str(r24s(pc+2)), opcode & 3);
+ return 5;
+
+ case 0x64: case 0x65: case 0x66: case 0x67:
+ sprintf(buffer, "add %s, a%d", i24str(r24s(pc+2)), opcode & 3);
+ return 5;
+
+ case 0x68: case 0x69: case 0x6a: case 0x6b:
+ sprintf(buffer, "sub %s, d%d", i24str(r24s(pc+2)), opcode & 3);
+ return 5;
+
+ case 0x6c: case 0x6d: case 0x6e: case 0x6f:
+ sprintf(buffer, "sub %s, a%d", i24str(r24s(pc+2)), opcode & 3);
+ return 5;
+
+ case 0x70: case 0x71: case 0x72: case 0x73:
+ sprintf(buffer, "mov %s, d%d", i24str(r24s(pc+2)), opcode & 3);
+ return 5;
+
+ case 0x74: case 0x75: case 0x76: case 0x77:
+ sprintf(buffer, "mov %x, a%d", r24u(pc+2), opcode & 3);
+ return 5;
+
+ case 0x78: case 0x79: case 0x7a: case 0x7b:
+ sprintf(buffer, "cmp %s, d%d", i24str(r24s(pc+2)), opcode & 3);
+ return 5;
+
+ case 0x7c: case 0x7d: case 0x7e: case 0x7f:
+ sprintf(buffer, "cmp %x, a%d", r24u(pc+2), opcode & 3);
+ return 5;
+
+ case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87:
+ case 0x88: case 0x89: case 0x8a: case 0x8b: case 0x8c: case 0x8d: case 0x8e: case 0x8f:
+ sprintf(buffer, "mov (%s, a%d), d%d", i24str(r24s(pc+2)), (opcode>>2) & 3, opcode & 3);
+ return 5;
+
+ case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97:
+ case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f:
+ sprintf(buffer, "movbu (%s, a%d), d%d", i24str(r24s(pc+2)), (opcode>>2) & 3, opcode & 3);
+ return 5;
+
+ case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7:
+ case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf:
+ sprintf(buffer, "movb (%s, a%d), d%d", i24str(r24s(pc+2)), (opcode>>2) & 3, opcode & 3);
+ return 5;
+
+ case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7:
+ case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf:
+ sprintf(buffer, "movx (%s, a%d), d%d", i24str(r24s(pc+2)), (opcode>>2) & 3, opcode & 3);
+ return 5;
+
+ case 0xc0: case 0xc1: case 0xc2: case 0xc3:
+ sprintf(buffer, "mov (%x), d%d", r24u(pc+2), opcode & 3);
+ return 5;
+
+ case 0xc4: case 0xc5: case 0xc6: case 0xc7:
+ sprintf(buffer, "movb (%x), d%d", r24u(pc+2), opcode & 3);
+ return 5;
+
+ case 0xc8: case 0xc9: case 0xca: case 0xcb:
+ sprintf(buffer, "movbu (%x), d%d", r24u(pc+2), opcode & 3);
+ return 5;
+
+ case 0xd0: case 0xd1: case 0xd2: case 0xd3:
+ sprintf(buffer, "mov (%x), a%d", r24u(pc+2), opcode & 3);
+ return 5;
+
+ case 0xe0:
+ sprintf(buffer, "jmp %x", (pc+5+r24s(pc+2)) & 0xffffff);
+ return 5;
+
+ case 0xe1:
+ sprintf(buffer, "jsr %x", (pc+5+r24s(pc+2)) & 0xffffff);
+ return 5;
+
+ case 0xe3:
+ sprintf(buffer, "bset %02x, (%x)", program_read_byte(pc+4), r16u(pc+2));
+ return 6;
+
+ case 0xe7:
+ sprintf(buffer, "bclr %02x, (%x)", program_read_byte(pc+4), r16u(pc+2));
+ return 6;
+
+ case 0xe8: case 0xe9: case 0xea: case 0xeb:
+ sprintf(buffer, "bset %02x, (%s, a%d)", program_read_byte(pc+3), i8str(program_read_byte(pc+2)), opcode & 3);
+ return 4;
+
+ case 0xec: case 0xed: case 0xee: case 0xef:
+ sprintf(buffer, "bclr %02x, (%s, a%d)", program_read_byte(pc+3), i8str(program_read_byte(pc+2)), opcode & 3);
+ return 4;
+
+ case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7:
+ case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff:
+ sprintf(buffer, "mov (%s, a%d), a%d", i24str(r24s(pc+2)), (opcode>>2) & 3, opcode & 3);
+ return 5;
+
+ default:
+ goto illegal2;
+ }
+ break;
+
+ case 0xf5:
+ opcode = program_read_byte(pc+1);
+ switch(opcode) {
+ case 0x00: case 0x01: case 0x02: case 0x03:
+ sprintf(buffer, "and %02x, d%d", program_read_byte(pc+2), opcode & 3);
+ return 3;
+
+ case 0x04: case 0x05: case 0x06: case 0x07:
+ sprintf(buffer, "btst %02x, d%d", program_read_byte(pc+2), opcode & 3);
+ return 3;
+
+ case 0x08: case 0x09: case 0x0a: case 0x0b:
+ sprintf(buffer, "or %02x, d%d", program_read_byte(pc+2), opcode & 3);
+ return 3;
+
+ case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ sprintf(buffer, "addnf %s, a%d", i8str(program_read_byte(pc+2)), opcode & 3);
+ return 3;
+
+ case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
+ case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ sprintf(buffer, "movb d%d, (%s, a%d)", opcode & 3, i8str(program_read_byte(pc+2)), (opcode>>2) & 3);
+ return 3;
+
+ case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ sprintf(buffer, "movb (%s, a%d), d%d", i8str(program_read_byte(pc+2)), (opcode>>2) & 3, opcode & 3);
+ return 3;
+
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
+ case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
+ sprintf(buffer, "movbu (%s, a%d), d%d", i8str(program_read_byte(pc+2)), (opcode>>2) & 3, opcode & 3);
+ return 3;
+
+ case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47:
+ case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f: {
+ UINT8 opcode2 = program_read_byte(pc+2);
+ switch(opcode2) {
+ case 0x00:
+ sprintf(buffer, "mulql d%d, d%d", (opcode>>3) & 3, opcode & 3);
+ return 3;
+
+ case 0x01:
+ sprintf(buffer, "mulqh d%d, d%d", (opcode>>3) & 3, opcode & 3);
+ return 3;
+
+ default:
+ goto illegal3;
+ }
+ break;
+ }
+
+ case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57:
+ case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f:
+ sprintf(buffer, "movx d%d, (%s, a%d)", opcode & 3, i8str(program_read_byte(pc+2)), (opcode>>2) & 3);
+ return 3;
+
+ case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67:
+ case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6e: case 0x6f: {
+ UINT8 opcode2 = program_read_byte(pc+2);
+ switch(opcode2) {
+ case 0x10:
+ sprintf(buffer, "mulq d%d, d%d", (opcode>>3) & 3, opcode & 3);
+ return 3;
+
+ default:
+ goto illegal3;
+ }
+ break;
+ }
+
+ case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77:
+ case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f:
+ sprintf(buffer, "movx (%s, a%d), d%d", i8str(program_read_byte(pc+2)), (opcode>>2) & 3, opcode & 3);
+ return 3;
+
+ case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87:
+ case 0x88: case 0x89: case 0x8a: case 0x8b: case 0x8c: case 0x8d: case 0x8e: case 0x8f:
+ sprintf(buffer, "tbz (%s, a%d) %d, %x", i8str(program_read_byte(pc+2)), (opcode>>3)&1, opcode & 7,
+ (pc+4+(INT8)program_read_byte(pc+3)) & 0xffffff);
+ return 4;
+
+ case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97:
+ case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f:
+ sprintf(buffer, "bset (%s, a%d) %d", i8str(program_read_byte(pc+2)), (opcode>>3)&1, opcode & 7);
+ return 3;
+
+ case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7:
+ case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf:
+ sprintf(buffer, "tbnz (%s, a%d) %d, %x", i8str(program_read_byte(pc+2)), (opcode>>3)&1, opcode & 7,
+ (pc+4+(INT8)program_read_byte(pc+3)) & 0xffffff);
+ return 4;
+
+ case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7:
+ case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf:
+ sprintf(buffer, "bclr (%s, a%d) %d", i8str(program_read_byte(pc+2)), (opcode>>3)&1, opcode & 7);
+ return 3;
+
+ case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7:
+ sprintf(buffer, "tbz (%x) %d, %x", r16u(pc+2), opcode & 7,
+ (pc+5+(INT8)program_read_byte(pc+4)) & 0xffffff);
+ return 5;
+
+ case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf:
+ sprintf(buffer, "tbnz (%x) %d, %x", r16u(pc+2), opcode & 7,
+ (pc+5+(INT8)program_read_byte(pc+4)) & 0xffffff);
+ return 5;
+
+ case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7:
+ sprintf(buffer, "bset (%x) %d", r16u(pc+2), opcode & 7);
+ return 4;
+
+ case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf:
+ sprintf(buffer, "bclr (%x) %d", r16u(pc+2), opcode & 7);
+ return 4;
+
+ case 0xe0:
+ sprintf(buffer, "bltx %x", (pc+3+(INT8)program_read_byte(pc+2)) & 0xffffff);
+ return 3;
+
+ case 0xe1:
+ sprintf(buffer, "bgtx %x", (pc+3+(INT8)program_read_byte(pc+2)) & 0xffffff);
+ return 3;
+
+ case 0xe2:
+ sprintf(buffer, "bgex %x", (pc+3+(INT8)program_read_byte(pc+2)) & 0xffffff);
+ return 3;
+
+ case 0xe3:
+ sprintf(buffer, "blex %x", (pc+3+(INT8)program_read_byte(pc+2)) & 0xffffff);
+ return 3;
+
+ case 0xe4:
+ sprintf(buffer, "bcsx %x", (pc+3+(INT8)program_read_byte(pc+2)) & 0xffffff);
+ return 3;
+
+ case 0xe5:
+ sprintf(buffer, "bhix %x", (pc+3+(INT8)program_read_byte(pc+2)) & 0xffffff);
+ return 3;
+
+ case 0xe6:
+ sprintf(buffer, "bccx %x", (pc+3+(INT8)program_read_byte(pc+2)) & 0xffffff);
+ return 3;
+
+ case 0xe7:
+ sprintf(buffer, "blsx %x", (pc+3+(INT8)program_read_byte(pc+2)) & 0xffffff);
+ return 3;
+
+ case 0xe8:
+ sprintf(buffer, "beqx %x", (pc+3+(INT8)program_read_byte(pc+2)) & 0xffffff);
+ return 3;
+
+ case 0xe9:
+ sprintf(buffer, "bnex %x", (pc+3+(INT8)program_read_byte(pc+2)) & 0xffffff);
+ return 3;
+
+ case 0xec:
+ sprintf(buffer, "bvcx %x", (pc+3+(INT8)program_read_byte(pc+2)) & 0xffffff);
+ return 3;
+
+ case 0xed:
+ sprintf(buffer, "bvsx %x", (pc+3+(INT8)program_read_byte(pc+2)) & 0xffffff);
+ return 3;
+
+ case 0xee:
+ sprintf(buffer, "bncx %x", (pc+3+(INT8)program_read_byte(pc+2)) & 0xffffff);
+ return 3;
+
+ case 0xef:
+ sprintf(buffer, "bnsx %x", (pc+3+(INT8)program_read_byte(pc+2)) & 0xffffff);
+ return 3;
+
+ case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7: {
+ UINT8 opcode2 = program_read_byte(pc+2);
+ switch(opcode2) {
+ case 0x04:
+ sprintf(buffer, "mulql %s, d%d", i8str(program_read_byte(pc+3)), opcode & 3);
+ return 4;
+
+ case 0x05:
+ sprintf(buffer, "mulqh %s, d%d", i8str(program_read_byte(pc+3)), opcode & 3);
+ return 4;
+
+ case 0x08:
+ sprintf(buffer, "mulql %s, d%d", i16str(r16s(pc+3)), opcode & 3);
+ return 5;
+
+ case 0x09:
+ sprintf(buffer, "mulqh %s, d%d", i16str(r16s(pc+3)), opcode & 3);
+ return 5;
+
+ default:
+ goto illegal3;
+ }
+ break;
+ }
+
+ case 0xfc:
+ sprintf(buffer, "bvc %x", (pc+3+(INT8)program_read_byte(pc+2)) & 0xffffff);
+ return 3;
+
+ case 0xfd:
+ sprintf(buffer, "bvs %x", (pc+3+(INT8)program_read_byte(pc+2)) & 0xffffff);
+ return 3;
+
+ case 0xfe:
+ sprintf(buffer, "bnc %x", (pc+3+(INT8)program_read_byte(pc+2)) & 0xffffff);
+ return 3;
+
+ case 0xff:
+ sprintf(buffer, "bns %x", (pc+3+(INT8)program_read_byte(pc+2)) & 0xffffff);
+ return 3;
+
+ default:
+ goto illegal2;
+ }
+ break;
+
+ case 0xf6:
+ sprintf(buffer, "nop");
+ return 1;
+
+ case 0xf7:
+ opcode = program_read_byte(pc+1);
+ switch(opcode) {
+ case 0x00: case 0x01: case 0x02: case 0x03:
+ sprintf(buffer, "and %04x, d%d", r16u(pc+2), opcode & 3);
+ return 4;
+
+ case 0x04: case 0x05: case 0x06: case 0x07:
+ sprintf(buffer, "btst %04x, d%d", r16u(pc+2), opcode & 3);
+ return 4;
+
+ case 0x08: case 0x09: case 0x0a: case 0x0b:
+ sprintf(buffer, "add %s, a%d", i16str(r16s(pc+2)), opcode & 3);
+ return 4;
+
+ case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ sprintf(buffer, "sub %s, a%d", i16str(r16s(pc+2)), opcode & 3);
+ return 4;
+
+ case 0x10:
+ sprintf(buffer, "and %04x, psw", r16u(pc+2));
+ return 4;
+
+ case 0x14:
+ sprintf(buffer, "or %04x, psw", r16u(pc+2));
+ return 4;
+
+ case 0x18: case 0x19: case 0x1a: case 0x1b:
+ sprintf(buffer, "add %s, d%d", i16str(r16u(pc+2)), opcode & 3);
+ return 4;
+
+ case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ sprintf(buffer, "sub %s, d%d", i16str(r16s(pc+2)), opcode & 3);
+ return 4;
+
+ case 0x20: case 0x21: case 0x22: case 0x23:
+ sprintf(buffer, "move a%d, (%x)", opcode & 3, r16u(pc+2));
+ return 4;
+
+ case 0x30: case 0x31: case 0x32: case 0x33:
+ sprintf(buffer, "move (%x), a%d", r16u(pc+2), opcode & 3);
+ return 4;
+
+ case 0x40: case 0x41: case 0x42: case 0x43:
+ sprintf(buffer, "or %04x, d%d", r16u(pc+2), opcode & 3);
+ return 4;
+
+ case 0x48: case 0x49: case 0x4a: case 0x4b:
+ sprintf(buffer, "cmp %s, d%d", i16str(r16u(pc+2)), opcode & 3);
+ return 4;
+
+ case 0x4c: case 0x4d: case 0x4e: case 0x4f:
+ sprintf(buffer, "xor %04x, d%d", r16u(pc+2), opcode & 3);
+ return 4;
+
+ case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57:
+ case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f:
+ sprintf(buffer, "movbu (%s, a%d), d%d", i16str(r16s(pc+2)), (opcode>>2) & 3, opcode & 3);
+ return 4;
+
+ case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67:
+ case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6e: case 0x6f:
+ sprintf(buffer, "movx d%d, (%s, a%d)", opcode & 3, i16str(r16s(pc+2)), (opcode>>2) & 3);
+ return 4;
+
+ case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77:
+ case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f:
+ sprintf(buffer, "movx (%s, a%d), d%d", i16str(r16s(pc+2)), (opcode>>2) & 3, opcode & 3);
+ return 4;
+
+ case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87:
+ case 0x88: case 0x89: case 0x8a: case 0x8b: case 0x8c: case 0x8d: case 0x8e: case 0x8f:
+ sprintf(buffer, "mov d%d, (%s, a%d)", opcode & 3, i16str(r16s(pc+2)), (opcode>>2) & 3);
+ return 4;
+
+ case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97:
+ case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f:
+ sprintf(buffer, "movb d%d, (%s, a%d)", opcode & 3, i16str(r16s(pc+2)), (opcode>>2) & 3);
+ return 4;
+
+ case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7:
+ case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf:
+ sprintf(buffer, "mov a%d, (%s, a%d)", opcode & 3, i16str(r16s(pc+2)), (opcode>>2) & 3);
+ return 4;
+
+ case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7:
+ case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf:
+ sprintf(buffer, "mov (%s, a%d), a%d", i16str(r16s(pc+2)), (opcode>>2) & 3, opcode & 3);
+ return 4;
+
+ case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7:
+ case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf:
+ sprintf(buffer, "mov (%s, a%d), d%d", i16str(r16s(pc+2)), (opcode>>2) & 3, opcode & 3);
+ return 4;
+
+ case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7:
+ case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf:
+ sprintf(buffer, "movb (%s, a%d), d%d", i16str(r16s(pc+2)), (opcode>>2) & 3, opcode & 3);
+ return 4;
+
+ default:
+ goto illegal2;
+ }
+ break;
+
+ case 0xf8: case 0xf9: case 0xfa: case 0xfb:
+ sprintf(buffer, "mov %s, d%d", i16str(r16s(pc+1)), opcode & 3);
+ return 3;
+
+ case 0xfc:
+ sprintf(buffer, "jmp %x", (pc+3+r16s(pc+1)) & 0xffffff);
+ return 3;
+
+ case 0xfd:
+ sprintf(buffer, "jsr %x", (pc+3+r16s(pc+1)) & 0xffffff);
+ return 3;
+
+ case 0xfe:
+ sprintf(buffer, "rts");
+ return 1;
+
+ default:
+ goto illegal1;
+ };
+
+ illegal1:
+ sprintf(buffer, "dc.b %02x", program_read_byte(pc));
+ return 1;
+
+ illegal2:
+ sprintf(buffer, "dc.b %02x %02x", program_read_byte(pc), program_read_byte(pc+1));
+ return 2;
+
+ illegal3:
+ sprintf(buffer, "dc.b %02x %02x %02x", program_read_byte(pc), program_read_byte(pc+1), program_read_byte(pc+2));
+ return 3;
+}
+
+CPU_DISASSEMBLE( mn10200 )
+{
+ return mn102_disassemble(buffer, pc, oprom);
+}
+
diff --git a/trunk/src/emu/cpu/nec/nec.c b/trunk/src/emu/cpu/nec/nec.c
new file mode 100644
index 00000000000..afbfa8052c6
--- /dev/null
+++ b/trunk/src/emu/cpu/nec/nec.c
@@ -0,0 +1,685 @@
+/****************************************************************************
+
+ NEC V20/V30/V33 emulator
+
+ ---------------------------------------------
+
+ V20 = uPD70108 = 8-bit data bus @ 5MHz or 8MHz
+ V20HL = uPD70108H = V20 with EMS support (24-bit address bus)
+
+ V25 = uPD70320 = V20 with on-chip features:
+ - 256 bytes on-chip RAM
+ - 8 register banks
+ - 4-bit input port
+ - 20-bit I/O port
+ - 2 channel serial interface
+ - interrupt controller
+ - 2 channel DMA controller
+ - 2 channel 16-bit timer
+ - new instructions: BTCLR, RETRBI, STOP, BRKCS, TSKSW,
+ MOVSPA, MOVSPB
+
+ V25+ = uPD70325 = V25 @ 8MHz or 10MHz plus changes:
+ - faster DMA
+ - improved serial interface
+
+ ---------------------------------------------
+
+ V30 = uPD70116 = 16-bit data bus version of V20
+ V30HL = uPD70116H = 16-bit data bus version of V20HL
+ V30MX = V30HL with separate address and data busses
+
+ V35 = uPD70330 = 16-bit data bus version of V25
+
+ V35+ = uPD70335 = 16-bit data bus version of V25+
+
+ ---------------------------------------------
+
+ V40 = uPD70208 = 8-bit data bus @ 10MHz
+ V40HL = uPD70208H = V40 with support up to 20Mhz
+
+ ---------------------------------------------
+
+ V50 = uPD70216 = 16-bit data bus version of V40
+ V50HL = uPD70216H = 16-bit data bus version of V40HL
+
+ ---------------------------------------------
+
+ V41 = uPD70270
+
+ V51 = uPD70280
+
+
+
+ V33A = uPD70136A
+
+ V53A = uPD70236A
+
+
+
+ Instruction differences:
+ V20, V30, V40, V50 have dedicated emulation instructions
+ (BRKEM, RETEM, CALLN)
+
+ V33A, V53A has dedicated address mode instructions
+ (BRKXA, RETXA)
+
+
+
+ (Re)Written June-September 2000 by Bryan McPhail (mish@tendril.co.uk) based
+ on code by Oliver Bergmann (Raul_Bloodworth@hotmail.com) who based code
+ on the i286 emulator by Fabrice Frances which had initial work based on
+ David Hedley's pcemu(!).
+
+ This new core features 99% accurate cycle counts for each processor,
+ there are still some complex situations where cycle counts are wrong,
+ typically where a few instructions have differing counts for odd/even
+ source and odd/even destination memory operands.
+
+ Flag settings are also correct for the NEC processors rather than the
+ I86 versions.
+
+ Changelist:
+
+ 22/02/2003:
+ Removed cycle counts from memory accesses - they are certainly wrong,
+ and there is already a memory access cycle penalty in the opcodes
+ using them.
+
+ Fixed save states.
+
+ Fixed ADJBA/ADJBS/ADJ4A/ADJ4S flags/return values for all situations.
+ (Fixes bugs in Geostorm and Thunderblaster)
+
+ Fixed carry flag on NEG (I thought this had been fixed circa Mame 0.58,
+ but it seems I never actually submitted the fix).
+
+ Fixed many cycle counts in instructions and bug in cycle count
+ macros (odd word cases were testing for odd instruction word address
+ not data address).
+
+ Todo!
+ Double check cycle timing is 100%.
+
+****************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+
+typedef UINT8 BOOLEAN;
+typedef UINT8 BYTE;
+typedef UINT16 WORD;
+typedef UINT32 DWORD;
+
+#include "nec.h"
+#include "necpriv.h"
+
+extern int necv_dasm_one(char *buffer, UINT32 eip, const UINT8 *oprom, const nec_config *config);
+
+INLINE nec_state_t *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == V20 ||
+ device->type() == V30 ||
+ device->type() == V33);
+ return (nec_state_t *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+INLINE void prefetch(nec_state_t *nec_state)
+{
+ nec_state->prefetch_count--;
+}
+
+static void do_prefetch(nec_state_t *nec_state, int previous_ICount)
+{
+ int diff = previous_ICount - (int) nec_state->icount;
+
+ /* The implementation is not accurate, but comes close.
+ * It does not respect that the V30 will fetch two bytes
+ * at once directly, but instead uses only 2 cycles instead
+ * of 4. There are however only very few sources publicly
+ * available and they are vague.
+ */
+ while (nec_state->prefetch_count<0)
+ {
+ nec_state->prefetch_count++;
+ if (diff>nec_state->prefetch_cycles)
+ diff -= nec_state->prefetch_cycles;
+ else
+ nec_state->icount -= nec_state->prefetch_cycles;
+ }
+
+ if (nec_state->prefetch_reset)
+ {
+ nec_state->prefetch_count = 0;
+ nec_state->prefetch_reset = 0;
+ return;
+ }
+
+ while (diff>=nec_state->prefetch_cycles && nec_state->prefetch_count < nec_state->prefetch_size)
+ {
+ diff -= nec_state->prefetch_cycles;
+ nec_state->prefetch_count++;
+ }
+
+}
+
+INLINE UINT8 fetch(nec_state_t *nec_state)
+{
+ prefetch(nec_state);
+ return nec_state->direct->read_raw_byte((Sreg(PS)<<4)+nec_state->ip++, nec_state->fetch_xor);
+}
+
+INLINE UINT16 fetchword(nec_state_t *nec_state)
+{
+ UINT16 r = FETCH();
+ r |= (FETCH()<<8);
+ return r;
+}
+
+#include "necinstr.h"
+#include "necmacro.h"
+#include "necea.h"
+#include "necmodrm.h"
+
+static UINT8 parity_table[256];
+
+static UINT8 fetchop(nec_state_t *nec_state)
+{
+ prefetch(nec_state);
+ return nec_state->direct->read_decrypted_byte(( Sreg(PS)<<4)+nec_state->ip++, nec_state->fetch_xor);
+}
+
+
+
+/***************************************************************************/
+
+static CPU_RESET( nec )
+{
+ nec_state_t *nec_state = get_safe_token(device);
+
+ memset( &nec_state->regs.w, 0, sizeof(nec_state->regs.w));
+
+ nec_state->ip = 0;
+ nec_state->TF = 0;
+ nec_state->IF = 0;
+ nec_state->DF = 0;
+ nec_state->MF = 1; // brkem should set to 0 when implemented
+ nec_state->SignVal = 0;
+ nec_state->AuxVal = 0;
+ nec_state->OverVal = 0;
+ nec_state->ZeroVal = 1;
+ nec_state->CarryVal = 0;
+ nec_state->ParityVal = 1;
+ nec_state->pending_irq = 0;
+ nec_state->nmi_state = 0;
+ nec_state->irq_state = 0;
+ nec_state->poll_state = 1;
+ nec_state->halted = 0;
+
+ Sreg(PS) = 0xffff;
+ Sreg(SS) = 0;
+ Sreg(DS0) = 0;
+ Sreg(DS1) = 0;
+
+ CHANGE_PC;
+}
+
+static CPU_EXIT( nec )
+{
+
+}
+
+static void nec_interrupt(nec_state_t *nec_state, unsigned int_num, INTSOURCES source)
+{
+ UINT32 dest_seg, dest_off;
+
+ i_pushf(nec_state);
+ nec_state->TF = nec_state->IF = 0;
+
+ if (source == INT_IRQ) /* get vector */
+ int_num = (*nec_state->irq_callback)(nec_state->device, 0);
+
+ dest_off = read_mem_word(int_num*4);
+ dest_seg = read_mem_word(int_num*4+2);
+
+ PUSH(Sreg(PS));
+ PUSH(nec_state->ip);
+ nec_state->ip = (WORD)dest_off;
+ Sreg(PS) = (WORD)dest_seg;
+ CHANGE_PC;
+}
+
+static void nec_trap(nec_state_t *nec_state)
+{
+ nec_instruction[fetchop(nec_state)](nec_state);
+ nec_interrupt(nec_state, NEC_TRAP_VECTOR, BRK);
+}
+
+static void external_int(nec_state_t *nec_state)
+{
+ if (nec_state->pending_irq & NMI_IRQ)
+ {
+ nec_interrupt(nec_state, NEC_NMI_VECTOR, NMI_IRQ);
+ nec_state->pending_irq &= ~NMI_IRQ;
+ }
+ else if (nec_state->pending_irq)
+ {
+ /* the actual vector is retrieved after pushing flags */
+ /* and clearing the IF */
+ nec_interrupt(nec_state, (UINT32)-1, INT_IRQ);
+ nec_state->irq_state = CLEAR_LINE;
+ nec_state->pending_irq &= ~INT_IRQ;
+ }
+}
+
+/****************************************************************************/
+/* OPCODES */
+/****************************************************************************/
+
+#include "necinstr.c"
+
+/*****************************************************************************/
+
+static void set_irq_line(nec_state_t *nec_state, int irqline, int state)
+{
+ switch (irqline)
+ {
+ case 0:
+ nec_state->irq_state = state;
+ if (state == CLEAR_LINE)
+ nec_state->pending_irq &= ~INT_IRQ;
+ else
+ {
+ nec_state->pending_irq |= INT_IRQ;
+ nec_state->halted = 0;
+ }
+ break;
+ case INPUT_LINE_NMI:
+ if (nec_state->nmi_state == state) return;
+ nec_state->nmi_state = state;
+ if (state != CLEAR_LINE)
+ {
+ nec_state->pending_irq |= NMI_IRQ;
+ nec_state->halted = 0;
+ }
+ break;
+ case NEC_INPUT_LINE_POLL:
+ nec_state->poll_state = state;
+ break;
+ }
+}
+
+static CPU_DISASSEMBLE( nec )
+{
+ return necv_dasm_one(buffer, pc, oprom, NULL);
+}
+
+static void nec_init(legacy_cpu_device *device, device_irq_callback irqcallback)
+{
+ nec_state_t *nec_state = get_safe_token(device);
+
+ unsigned int i, j, c;
+
+ static const WREGS wreg_name[8]={ AW, CW, DW, BW, SP, BP, IX, IY };
+ static const BREGS breg_name[8]={ AL, CL, DL, BL, AH, CH, DH, BH };
+
+ for (i = 0; i < 256; i++)
+ {
+ for (j = i, c = 0; j > 0; j >>= 1)
+ if (j & 1) c++;
+ parity_table[i] = !(c & 1);
+ }
+
+ for (i = 0; i < 256; i++)
+ {
+ Mod_RM.reg.b[i] = breg_name[(i & 0x38) >> 3];
+ Mod_RM.reg.w[i] = wreg_name[(i & 0x38) >> 3];
+ }
+
+ for (i = 0xc0; i < 0x100; i++)
+ {
+ Mod_RM.RM.w[i] = wreg_name[i & 7];
+ Mod_RM.RM.b[i] = breg_name[i & 7];
+ }
+
+ memset(nec_state, 0, sizeof(*nec_state));
+
+ device->save_item(NAME(nec_state->regs.w));
+ device->save_item(NAME(nec_state->sregs));
+
+ device->save_item(NAME(nec_state->ip));
+ device->save_item(NAME(nec_state->TF));
+ device->save_item(NAME(nec_state->IF));
+ device->save_item(NAME(nec_state->DF));
+ device->save_item(NAME(nec_state->MF));
+ device->save_item(NAME(nec_state->SignVal));
+ device->save_item(NAME(nec_state->AuxVal));
+ device->save_item(NAME(nec_state->OverVal));
+ device->save_item(NAME(nec_state->ZeroVal));
+ device->save_item(NAME(nec_state->CarryVal));
+ device->save_item(NAME(nec_state->ParityVal));
+ device->save_item(NAME(nec_state->pending_irq));
+ device->save_item(NAME(nec_state->nmi_state));
+ device->save_item(NAME(nec_state->irq_state));
+ device->save_item(NAME(nec_state->poll_state));
+ device->save_item(NAME(nec_state->halted));
+
+ nec_state->irq_callback = irqcallback;
+ nec_state->device = device;
+ nec_state->program = device->space(AS_PROGRAM);
+ nec_state->direct = &nec_state->program->direct();
+ nec_state->io = device->space(AS_IO);
+}
+
+
+
+static CPU_EXECUTE( necv )
+{
+ nec_state_t *nec_state = get_safe_token(device);
+ int prev_ICount;
+
+ if (nec_state->halted)
+ {
+ nec_state->icount = 0;
+ debugger_instruction_hook(device, (Sreg(PS)<<4) + nec_state->ip);
+ return;
+ }
+
+ while(nec_state->icount>0) {
+ /* Dispatch IRQ */
+ if (nec_state->pending_irq && nec_state->no_interrupt==0)
+ {
+ if (nec_state->pending_irq & NMI_IRQ)
+ external_int(nec_state);
+ else if (nec_state->IF)
+ external_int(nec_state);
+ }
+
+ /* No interrupt allowed between last instruction and this one */
+ if (nec_state->no_interrupt)
+ nec_state->no_interrupt--;
+
+ debugger_instruction_hook(device, (Sreg(PS)<<4) + nec_state->ip);
+ prev_ICount = nec_state->icount;
+ nec_instruction[fetchop(nec_state)](nec_state);
+ do_prefetch(nec_state, prev_ICount);
+ }
+}
+
+/* Wrappers for the different CPU types */
+static CPU_INIT( v20 )
+{
+ nec_state_t *nec_state = get_safe_token(device);
+
+ nec_init(device, irqcallback);
+ nec_state->fetch_xor = 0;
+ nec_state->chip_type=V20_TYPE;
+ nec_state->prefetch_size = 4; /* 3 words */
+ nec_state->prefetch_cycles = 4; /* four cycles per byte */
+}
+
+static CPU_INIT( v30 )
+{
+ nec_state_t *nec_state = get_safe_token(device);
+
+ nec_init(device, irqcallback);
+ nec_state->fetch_xor = BYTE_XOR_LE(0);
+ nec_state->chip_type=V30_TYPE;
+ nec_state->prefetch_size = 6; /* 3 words */
+ nec_state->prefetch_cycles = 2; /* two cycles per byte / four per word */
+
+}
+
+static CPU_INIT( v33 )
+{
+ nec_state_t *nec_state = get_safe_token(device);
+
+ nec_init(device, irqcallback);
+ nec_state->chip_type=V33_TYPE;
+ nec_state->prefetch_size = 6;
+ /* FIXME: Need information about prefetch size and cycles for V33.
+ * complete guess below, nbbatman will not work
+ * properly without. */
+ nec_state->prefetch_cycles = 1; /* two cycles per byte / four per word */
+
+ nec_state->fetch_xor = BYTE_XOR_LE(0);
+}
+
+
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( nec )
+{
+ nec_state_t *nec_state = get_safe_token(device);
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + 0: set_irq_line(nec_state, 0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: set_irq_line(nec_state, INPUT_LINE_NMI, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + NEC_INPUT_LINE_POLL: set_irq_line(nec_state, NEC_INPUT_LINE_POLL, info->i); break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + NEC_PC:
+ if( info->i - (Sreg(PS)<<4) < 0x10000 )
+ {
+ nec_state->ip = info->i - (Sreg(PS)<<4);
+ }
+ else
+ {
+ Sreg(PS) = info->i >> 4;
+ nec_state->ip = info->i & 0x0000f;
+ }
+ break;
+ case CPUINFO_INT_REGISTER + NEC_IP: nec_state->ip = info->i; break;
+ case CPUINFO_INT_SP:
+ if( info->i - (Sreg(SS)<<4) < 0x10000 )
+ {
+ Wreg(SP) = info->i - (Sreg(SS)<<4);
+ }
+ else
+ {
+ Sreg(SS) = info->i >> 4;
+ Wreg(SP) = info->i & 0x0000f;
+ }
+ break;
+ case CPUINFO_INT_REGISTER + NEC_SP: Wreg(SP) = info->i; break;
+ case CPUINFO_INT_REGISTER + NEC_FLAGS: ExpandFlags(info->i); break;
+ case CPUINFO_INT_REGISTER + NEC_AW: Wreg(AW) = info->i; break;
+ case CPUINFO_INT_REGISTER + NEC_CW: Wreg(CW) = info->i; break;
+ case CPUINFO_INT_REGISTER + NEC_DW: Wreg(DW) = info->i; break;
+ case CPUINFO_INT_REGISTER + NEC_BW: Wreg(BW) = info->i; break;
+ case CPUINFO_INT_REGISTER + NEC_BP: Wreg(BP) = info->i; break;
+ case CPUINFO_INT_REGISTER + NEC_IX: Wreg(IX) = info->i; break;
+ case CPUINFO_INT_REGISTER + NEC_IY: Wreg(IY) = info->i; break;
+ case CPUINFO_INT_REGISTER + NEC_ES: Sreg(DS1) = info->i; break;
+ case CPUINFO_INT_REGISTER + NEC_CS: Sreg(PS) = info->i; break;
+ case CPUINFO_INT_REGISTER + NEC_SS: Sreg(SS) = info->i; break;
+ case CPUINFO_INT_REGISTER + NEC_DS: Sreg(DS0) = info->i; break;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+static CPU_GET_INFO( nec )
+{
+ nec_state_t *nec_state = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+ int flags;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(nec_state_t); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 1; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0xff; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 8; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 80; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 20; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_INPUT_STATE + 0: info->i = (nec_state->pending_irq & INT_IRQ) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: info->i = nec_state->nmi_state; break;
+ case CPUINFO_INT_INPUT_STATE + NEC_INPUT_LINE_POLL: info->i = nec_state->poll_state; break;
+
+ case CPUINFO_INT_PREVIOUSPC: /* not supported */ break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + NEC_PC: info->i = ((Sreg(PS)<<4) + nec_state->ip); break;
+ case CPUINFO_INT_REGISTER + NEC_IP: info->i = nec_state->ip; break;
+ case CPUINFO_INT_SP: info->i = (Sreg(SS)<<4) + Wreg(SP); break;
+ case CPUINFO_INT_REGISTER + NEC_SP: info->i = Wreg(SP); break;
+ case CPUINFO_INT_REGISTER + NEC_FLAGS: info->i = CompressFlags(); break;
+ case CPUINFO_INT_REGISTER + NEC_AW: info->i = Wreg(AW); break;
+ case CPUINFO_INT_REGISTER + NEC_CW: info->i = Wreg(CW); break;
+ case CPUINFO_INT_REGISTER + NEC_DW: info->i = Wreg(DW); break;
+ case CPUINFO_INT_REGISTER + NEC_BW: info->i = Wreg(BW); break;
+ case CPUINFO_INT_REGISTER + NEC_BP: info->i = Wreg(BP); break;
+ case CPUINFO_INT_REGISTER + NEC_IX: info->i = Wreg(IX); break;
+ case CPUINFO_INT_REGISTER + NEC_IY: info->i = Wreg(IY); break;
+ case CPUINFO_INT_REGISTER + NEC_ES: info->i = Sreg(DS1); break;
+ case CPUINFO_INT_REGISTER + NEC_CS: info->i = Sreg(PS); break;
+ case CPUINFO_INT_REGISTER + NEC_SS: info->i = Sreg(SS); break;
+ case CPUINFO_INT_REGISTER + NEC_DS: info->i = Sreg(DS0); break;
+ case CPUINFO_INT_REGISTER + NEC_PENDING: info->i = nec_state->pending_irq; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(nec); break;
+ case CPUINFO_FCT_INIT: /* set per-CPU */ break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(nec); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(nec); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(necv); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(nec); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &nec_state->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "NEC"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "NEC V-Series"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "2.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Bryan McPhail (V25/V35 support added by Alex W. Jackson)"); break;
+
+ case CPUINFO_STR_FLAGS:
+ flags = CompressFlags();
+ sprintf(info->s, "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c",
+ flags & 0x8000 ? 'N':'E',
+ flags & 0x4000 ? '?':'.',
+ flags & 0x2000 ? '?':'.',
+ flags & 0x1000 ? '?':'.',
+ flags & 0x0800 ? 'O':'.',
+ flags & 0x0400 ? 'D':'.',
+ flags & 0x0200 ? 'I':'.',
+ flags & 0x0100 ? 'T':'.',
+ flags & 0x0080 ? 'S':'.',
+ flags & 0x0040 ? 'Z':'.',
+ flags & 0x0020 ? '?':'.',
+ flags & 0x0010 ? 'A':'.',
+ flags & 0x0008 ? '?':'.',
+ flags & 0x0004 ? 'P':'.',
+ flags & 0x0002 ? '.':'?',
+ flags & 0x0001 ? 'C':'.');
+ break;
+
+ case CPUINFO_STR_REGISTER + NEC_PC: sprintf(info->s, "PC:%05X", (Sreg(PS)<<4) + nec_state->ip); break;
+ case CPUINFO_STR_REGISTER + NEC_IP: sprintf(info->s, "IP:%04X", nec_state->ip); break;
+ case CPUINFO_STR_REGISTER + NEC_SP: sprintf(info->s, "SP:%04X", Wreg(SP)); break;
+ case CPUINFO_STR_REGISTER + NEC_FLAGS: sprintf(info->s, "F:%04X", CompressFlags()); break;
+ case CPUINFO_STR_REGISTER + NEC_AW: sprintf(info->s, "AW:%04X", Wreg(AW)); break;
+ case CPUINFO_STR_REGISTER + NEC_CW: sprintf(info->s, "CW:%04X", Wreg(CW)); break;
+ case CPUINFO_STR_REGISTER + NEC_DW: sprintf(info->s, "DW:%04X", Wreg(DW)); break;
+ case CPUINFO_STR_REGISTER + NEC_BW: sprintf(info->s, "BW:%04X", Wreg(BW)); break;
+ case CPUINFO_STR_REGISTER + NEC_BP: sprintf(info->s, "BP:%04X", Wreg(BP)); break;
+ case CPUINFO_STR_REGISTER + NEC_IX: sprintf(info->s, "IX:%04X", Wreg(IX)); break;
+ case CPUINFO_STR_REGISTER + NEC_IY: sprintf(info->s, "IY:%04X", Wreg(IY)); break;
+ case CPUINFO_STR_REGISTER + NEC_ES: sprintf(info->s, "DS1:%04X", Sreg(DS1)); break;
+ case CPUINFO_STR_REGISTER + NEC_CS: sprintf(info->s, "PS:%04X", Sreg(PS)); break;
+ case CPUINFO_STR_REGISTER + NEC_SS: sprintf(info->s, "SS:%04X", Sreg(SS)); break;
+ case CPUINFO_STR_REGISTER + NEC_DS: sprintf(info->s, "DS0:%04X", Sreg(DS0)); break;
+ }
+}
+
+
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+
+CPU_GET_INFO( v20 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 8; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(v20); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "V20"); break;
+
+ default: CPU_GET_INFO_CALL(nec); break;
+ }
+}
+
+
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+
+CPU_GET_INFO( v30 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(v30); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "V30"); break;
+
+ default: CPU_GET_INFO_CALL(nec); break;
+ }
+}
+
+
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+
+CPU_GET_INFO( v33 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(v33); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "V33"); break;
+
+ default: CPU_GET_INFO_CALL(nec); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(V20, v20);
+DEFINE_LEGACY_CPU_DEVICE(V30, v30);
+DEFINE_LEGACY_CPU_DEVICE(V33, v33);
diff --git a/trunk/src/emu/cpu/nec/nec.h b/trunk/src/emu/cpu/nec/nec.h
new file mode 100644
index 00000000000..d0a6e4816c5
--- /dev/null
+++ b/trunk/src/emu/cpu/nec/nec.h
@@ -0,0 +1,37 @@
+/* ASG 971222 -- rewrote this interface */
+#ifndef __NEC_H_
+#define __NEC_H_
+
+
+typedef struct _nec_config nec_config;
+struct _nec_config
+{
+ const UINT8* v25v35_decryptiontable; // internal decryption table
+};
+
+#define NEC_INPUT_LINE_INTP0 10
+#define NEC_INPUT_LINE_INTP1 11
+#define NEC_INPUT_LINE_INTP2 12
+#define NEC_INPUT_LINE_POLL 20
+
+#define V25_PORT_P0 0x10000
+#define V25_PORT_P1 0x10002
+#define V25_PORT_P2 0x10004
+#define V25_PORT_PT 0x10006
+
+enum
+{
+ NEC_PC=0,
+ NEC_IP, NEC_AW, NEC_CW, NEC_DW, NEC_BW, NEC_SP, NEC_BP, NEC_IX, NEC_IY,
+ NEC_FLAGS, NEC_ES, NEC_CS, NEC_SS, NEC_DS,
+ NEC_PENDING
+};
+
+/* Public functions */
+DECLARE_LEGACY_CPU_DEVICE(V20, v20);
+DECLARE_LEGACY_CPU_DEVICE(V25, v25);
+DECLARE_LEGACY_CPU_DEVICE(V30, v30);
+DECLARE_LEGACY_CPU_DEVICE(V33, v33);
+DECLARE_LEGACY_CPU_DEVICE(V35, v35);
+
+#endif
diff --git a/trunk/src/emu/cpu/nec/necdasm.c b/trunk/src/emu/cpu/nec/necdasm.c
new file mode 100644
index 00000000000..ba4662a598b
--- /dev/null
+++ b/trunk/src/emu/cpu/nec/necdasm.c
@@ -0,0 +1,1613 @@
+/*
+ NEC V-series Disassembler
+
+ Originally Written for i386 by Ville Linde
+ Converted to NEC-V by Aaron Giles
+*/
+
+#include "emu.h"
+
+typedef struct _nec_config nec_config;
+struct _nec_config
+{
+ const UINT8* v25v35_decryptiontable; // internal decryption table
+};
+
+/* default configuration */
+static const nec_config default_config =
+{
+ NULL
+};
+
+static const nec_config *Iconfig;
+
+enum
+{
+ PARAM_REG8 = 1, /* 8-bit register */
+ PARAM_REG16, /* 16-bit register */
+ PARAM_REG2_8, /* 8-bit register */
+ PARAM_REG2_16, /* 16-bit register */
+ PARAM_RM8, /* 8-bit memory or register */
+ PARAM_RM16, /* 16-bit memory or register */
+ PARAM_RMPTR8, /* 8-bit memory or register */
+ PARAM_RMPTR16, /* 16-bit memory or register */
+ PARAM_I3, /* 3-bit immediate */
+ PARAM_I4, /* 4-bit immediate */
+ PARAM_I8, /* 8-bit signed immediate */
+ PARAM_I16, /* 16-bit signed immediate */
+ PARAM_UI8, /* 8-bit unsigned immediate */
+ PARAM_IMM, /* 16-bit immediate */
+ PARAM_ADDR, /* 16:16 address */
+ PARAM_REL8, /* 8-bit PC-relative displacement */
+ PARAM_REL16, /* 16-bit PC-relative displacement */
+ PARAM_MEM_OFFS, /* 16-bit mem offset */
+ PARAM_SREG, /* segment register */
+ PARAM_SFREG, /* V25/V35 special function register */
+ PARAM_1, /* used by shift/rotate instructions */
+ PARAM_AL,
+ PARAM_CL,
+ PARAM_DL,
+ PARAM_BL,
+ PARAM_AH,
+ PARAM_CH,
+ PARAM_DH,
+ PARAM_BH,
+ PARAM_AW,
+ PARAM_CW,
+ PARAM_DW,
+ PARAM_BW,
+ PARAM_SP,
+ PARAM_BP,
+ PARAM_IX,
+ PARAM_IY
+};
+
+enum
+{
+ MODRM = 1,
+ GROUP,
+ FPU,
+ TWO_BYTE,
+ PREFIX,
+ SEG_PS,
+ SEG_DS0,
+ SEG_DS1,
+ SEG_SS
+};
+
+typedef struct {
+ char mnemonic[32];
+ UINT32 flags;
+ UINT32 param1;
+ UINT32 param2;
+ UINT32 param3;
+ offs_t dasm_flags;
+} I386_OPCODE;
+
+typedef struct {
+ char mnemonic[32];
+ const I386_OPCODE *opcode;
+} GROUP_OP;
+
+static const UINT8 *opcode_ptr;
+static const UINT8 *opcode_ptr_base;
+
+static const I386_OPCODE necv_opcode_table1[256] =
+{
+ // 0x00
+ {"add", MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {"add", MODRM, PARAM_RM16, PARAM_REG16, 0 },
+ {"add", MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {"add", MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {"add", 0, PARAM_AL, PARAM_UI8, 0 },
+ {"add", 0, PARAM_AW, PARAM_IMM, 0 },
+ {"push ds1", 0, 0, 0, 0 },
+ {"pop ds1", 0, 0, 0, 0 },
+ {"or", MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {"or", MODRM, PARAM_RM16, PARAM_REG16, 0 },
+ {"or", MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {"or", MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {"or", 0, PARAM_AL, PARAM_UI8, 0 },
+ {"or", 0, PARAM_AW, PARAM_IMM, 0 },
+ {"push ps", 0, 0, 0, 0 },
+ {"two_byte", TWO_BYTE, 0, 0, 0 },
+ // 0x10
+ {"addc", MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {"addc", MODRM, PARAM_RM16, PARAM_REG16, 0 },
+ {"addc", MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {"addc", MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {"addc", 0, PARAM_AL, PARAM_UI8, 0 },
+ {"addc", 0, PARAM_AW, PARAM_IMM, 0 },
+ {"push ss", 0, 0, 0, 0 },
+ {"pop ss", 0, 0, 0, 0 },
+ {"subc", MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {"subc", MODRM, PARAM_RM16, PARAM_REG16, 0 },
+ {"subc", MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {"subc", MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {"subc", 0, PARAM_AL, PARAM_UI8, 0 },
+ {"subc", 0, PARAM_AW, PARAM_IMM, 0 },
+ {"push ds0", 0, 0, 0, 0 },
+ {"pop ds0", 0, 0, 0, 0 },
+ // 0x20
+ {"and", MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {"and", MODRM, PARAM_RM16, PARAM_REG16, 0 },
+ {"and", MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {"and", MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {"and", 0, PARAM_AL, PARAM_UI8, 0 },
+ {"and", 0, PARAM_AW, PARAM_IMM, 0 },
+ {"ds1:", SEG_DS1, 0, 0, 0 },
+ {"adj4a", 0, 0, 0, 0 },
+ {"sub", MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {"sub", MODRM, PARAM_RM16, PARAM_REG16, 0 },
+ {"sub", MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {"sub", MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {"sub", 0, PARAM_AL, PARAM_UI8, 0 },
+ {"sub", 0, PARAM_AW, PARAM_IMM, 0 },
+ {"ps:", SEG_PS, 0, 0, 0 },
+ {"adj4s", 0, 0, 0, 0 },
+ // 0x30
+ {"xor", MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {"xor", MODRM, PARAM_RM16, PARAM_REG16, 0 },
+ {"xor", MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {"xor", MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {"xor", 0, PARAM_AL, PARAM_UI8, 0 },
+ {"xor", 0, PARAM_AW, PARAM_IMM, 0 },
+ {"ss:", SEG_SS, 0, 0, 0 },
+ {"adjba", 0, 0, 0, 0 },
+ {"cmp", MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {"cmp", MODRM, PARAM_RM16, PARAM_REG16, 0 },
+ {"cmp", MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {"cmp", MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {"cmp", 0, PARAM_AL, PARAM_UI8, 0 },
+ {"cmp", 0, PARAM_AW, PARAM_IMM, 0 },
+ {"ds0:", SEG_DS0, 0, 0, 0 },
+ {"adjbs", 0, 0, 0, 0 },
+ // 0x40
+ {"inc", 0, PARAM_AW, 0, 0 },
+ {"inc", 0, PARAM_CW, 0, 0 },
+ {"inc", 0, PARAM_DW, 0, 0 },
+ {"inc", 0, PARAM_BW, 0, 0 },
+ {"inc", 0, PARAM_SP, 0, 0 },
+ {"inc", 0, PARAM_BP, 0, 0 },
+ {"inc", 0, PARAM_IX, 0, 0 },
+ {"inc", 0, PARAM_IY, 0, 0 },
+ {"dec", 0, PARAM_AW, 0, 0 },
+ {"dec", 0, PARAM_CW, 0, 0 },
+ {"dec", 0, PARAM_DW, 0, 0 },
+ {"dec", 0, PARAM_BW, 0, 0 },
+ {"dec", 0, PARAM_SP, 0, 0 },
+ {"dec", 0, PARAM_BP, 0, 0 },
+ {"dec", 0, PARAM_IX, 0, 0 },
+ {"dec", 0, PARAM_IY, 0, 0 },
+ // 0x50
+ {"push", 0, PARAM_AW, 0, 0 },
+ {"push", 0, PARAM_CW, 0, 0 },
+ {"push", 0, PARAM_DW, 0, 0 },
+ {"push", 0, PARAM_BW, 0, 0 },
+ {"push", 0, PARAM_SP, 0, 0 },
+ {"push", 0, PARAM_BP, 0, 0 },
+ {"push", 0, PARAM_IX, 0, 0 },
+ {"push", 0, PARAM_IY, 0, 0 },
+ {"pop", 0, PARAM_AW, 0, 0 },
+ {"pop", 0, PARAM_CW, 0, 0 },
+ {"pop", 0, PARAM_DW, 0, 0 },
+ {"pop", 0, PARAM_BW, 0, 0 },
+ {"pop", 0, PARAM_SP, 0, 0 },
+ {"pop", 0, PARAM_BP, 0, 0 },
+ {"pop", 0, PARAM_IX, 0, 0 },
+ {"pop", 0, PARAM_IY, 0, 0 },
+ // 0x60
+ {"push r", 0, 0, 0, 0 },
+ {"pop r", 0, 0, 0, 0 },
+ {"chkind", MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {"brkn", 0, PARAM_UI8, 0, 0, DASMFLAG_STEP_OVER}, /* V25S/V35S only */
+ {"repnc", PREFIX, 0, 0, 0 },
+ {"repc", PREFIX, 0, 0, 0 },
+ {"fpo2 0", 0, 0, 0, 0 }, /* for a coprocessor that was never made */
+ {"fpo2 1", 0, 0, 0, 0 }, /* for a coprocessor that was never made */
+ {"push", 0, PARAM_IMM, 0, 0 },
+ {"mul", MODRM, PARAM_REG16, PARAM_RM16, PARAM_IMM },
+ {"push", 0, PARAM_I8, 0, 0 },
+ {"mul", MODRM, PARAM_REG16, PARAM_RM16, PARAM_I8 },
+ {"inmb", 0, 0, 0, 0 },
+ {"inmw", 0, 0, 0, 0 },
+ {"outmb", 0, 0, 0, 0 },
+ {"outmw", 0, 0, 0, 0 },
+ // 0x70
+ {"bv", 0, PARAM_REL8, 0, 0 },
+ {"bnv", 0, PARAM_REL8, 0, 0 },
+ {"bc", 0, PARAM_REL8, 0, 0 },
+ {"bnc", 0, PARAM_REL8, 0, 0 },
+ {"be", 0, PARAM_REL8, 0, 0 },
+ {"bne", 0, PARAM_REL8, 0, 0 },
+ {"bnh", 0, PARAM_REL8, 0, 0 },
+ {"bh", 0, PARAM_REL8, 0, 0 },
+ {"bn", 0, PARAM_REL8, 0, 0 },
+ {"bp", 0, PARAM_REL8, 0, 0 },
+ {"bpe", 0, PARAM_REL8, 0, 0 },
+ {"bpo", 0, PARAM_REL8, 0, 0 },
+ {"blt", 0, PARAM_REL8, 0, 0 },
+ {"bge", 0, PARAM_REL8, 0, 0 },
+ {"ble", 0, PARAM_REL8, 0, 0 },
+ {"bgt", 0, PARAM_REL8, 0, 0 },
+ // 0x80
+ {"immb", GROUP, 0, 0, 0 },
+ {"immw", GROUP, 0, 0, 0 },
+ {"immb", GROUP, 0, 0, 0 },
+ {"immws", GROUP, 0, 0, 0 },
+ {"test", MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {"test", MODRM, PARAM_RM16, PARAM_REG16, 0 },
+ {"xch", MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {"xch", MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {"mov", MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {"mov", MODRM, PARAM_RM16, PARAM_REG16, 0 },
+ {"mov", MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {"mov", MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {"mov", MODRM, PARAM_RM16, PARAM_SREG, 0 },
+ {"ldea", MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {"mov", MODRM, PARAM_SREG, PARAM_RM16, 0 },
+ {"pop", MODRM, PARAM_RM16, 0, 0 },
+ // 0x90
+ {"nop", 0, 0, 0, 0 },
+ {"xch", 0, PARAM_AW, PARAM_CW, 0 },
+ {"xch", 0, PARAM_AW, PARAM_DW, 0 },
+ {"xch", 0, PARAM_AW, PARAM_BW, 0 },
+ {"xch", 0, PARAM_AW, PARAM_SP, 0 },
+ {"xch", 0, PARAM_AW, PARAM_BP, 0 },
+ {"xch", 0, PARAM_AW, PARAM_IX, 0 },
+ {"xch", 0, PARAM_AW, PARAM_IY, 0 },
+ {"cvtbw", 0, 0, 0, 0 },
+ {"cvtwl", 0, 0, 0, 0 },
+ {"call", 0, PARAM_ADDR, 0, 0, DASMFLAG_STEP_OVER},
+ {"poll", 0, 0, 0, 0 },
+ {"push psw", 0, 0, 0, 0 },
+ {"pop psw", 0, 0, 0, 0 },
+ {"mov psw,ah", 0, 0, 0, 0 },
+ {"mov ah,psw", 0, 0, 0, 0 },
+ // 0xa0
+ {"mov", 0, PARAM_AL, PARAM_MEM_OFFS, 0 },
+ {"mov", 0, PARAM_AW, PARAM_MEM_OFFS, 0 },
+ {"mov", 0, PARAM_MEM_OFFS, PARAM_AL, 0 },
+ {"mov", 0, PARAM_MEM_OFFS, PARAM_AW, 0 },
+ {"movbkb", 0, 0, 0, 0 },
+ {"movbkw", 0, 0, 0, 0 },
+ {"cmpbkb", 0, 0, 0, 0 },
+ {"cmpbkw", 0, 0, 0, 0 },
+ {"test", 0, PARAM_AL, PARAM_UI8, 0 },
+ {"test", 0, PARAM_AW, PARAM_IMM, 0 },
+ {"stmb", 0, 0, 0, 0 },
+ {"stmw", 0, 0, 0, 0 },
+ {"ldmb", 0, 0, 0, 0 },
+ {"ldmw", 0, 0, 0, 0 },
+ {"cmpmb", 0, 0, 0, 0 },
+ {"cmpmw", 0, 0, 0, 0 },
+ // 0xb0
+ {"mov", 0, PARAM_AL, PARAM_UI8, 0 },
+ {"mov", 0, PARAM_CL, PARAM_UI8, 0 },
+ {"mov", 0, PARAM_DL, PARAM_UI8, 0 },
+ {"mov", 0, PARAM_BL, PARAM_UI8, 0 },
+ {"mov", 0, PARAM_AH, PARAM_UI8, 0 },
+ {"mov", 0, PARAM_CH, PARAM_UI8, 0 },
+ {"mov", 0, PARAM_DH, PARAM_UI8, 0 },
+ {"mov", 0, PARAM_BH, PARAM_UI8, 0 },
+ {"mov", 0, PARAM_AW, PARAM_IMM, 0 },
+ {"mov", 0, PARAM_CW, PARAM_IMM, 0 },
+ {"mov", 0, PARAM_DW, PARAM_IMM, 0 },
+ {"mov", 0, PARAM_BW, PARAM_IMM, 0 },
+ {"mov", 0, PARAM_SP, PARAM_IMM, 0 },
+ {"mov", 0, PARAM_BP, PARAM_IMM, 0 },
+ {"mov", 0, PARAM_IX, PARAM_IMM, 0 },
+ {"mov", 0, PARAM_IY, PARAM_IMM, 0 },
+ // 0xc0
+ {"shiftbi", GROUP, 0, 0, 0 },
+ {"shiftwi", GROUP, 0, 0, 0 },
+ {"ret", 0, PARAM_I16, 0, 0, DASMFLAG_STEP_OUT},
+ {"ret", 0, 0, 0, 0, DASMFLAG_STEP_OUT},
+ {"mov ds1,", MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {"mov ds0,", MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {"mov", MODRM, PARAM_RMPTR8, PARAM_UI8, 0 },
+ {"mov", MODRM, PARAM_RMPTR16, PARAM_IMM, 0 },
+ {"prepare", 0, PARAM_I16, PARAM_UI8, 0 },
+ {"dispose", 0, 0, 0, 0 },
+ {"retf", 0, PARAM_I16, 0, 0, DASMFLAG_STEP_OUT},
+ {"retf", 0, 0, 0, 0, DASMFLAG_STEP_OUT},
+ {"brk 3", 0, 0, 0, 0, DASMFLAG_STEP_OVER},
+ {"brk", 0, PARAM_UI8, 0, 0, DASMFLAG_STEP_OVER},
+ {"brkv", 0, 0, 0, 0 },
+ {"reti", 0, 0, 0, 0, DASMFLAG_STEP_OUT},
+ // 0xd0
+ {"shiftb", GROUP, 0, 0, 0 },
+ {"shiftw", GROUP, 0, 0, 0 },
+ {"shiftbv", GROUP, 0, 0, 0 },
+ {"shiftwv", GROUP, 0, 0, 0 },
+ {"cvtbd", 0, PARAM_I8, 0, 0 },
+ {"cvtdb", 0, PARAM_I8, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"trans", 0, 0, 0, 0 },
+ {"escape", FPU, 0, 0, 0 },
+ {"escape", FPU, 0, 0, 0 },
+ {"escape", FPU, 0, 0, 0 },
+ {"escape", FPU, 0, 0, 0 },
+ {"escape", FPU, 0, 0, 0 },
+ {"escape", FPU, 0, 0, 0 },
+ {"escape", FPU, 0, 0, 0 },
+ {"escape", FPU, 0, 0, 0 },
+ // 0xe0
+ {"dbnzne", 0, PARAM_REL8, 0, 0, DASMFLAG_STEP_OVER},
+ {"dbnze", 0, PARAM_REL8, 0, 0, DASMFLAG_STEP_OVER},
+ {"dbnz", 0, PARAM_REL8, 0, 0, DASMFLAG_STEP_OVER},
+ {"bcwz", 0, PARAM_REL8, 0, 0 },
+ {"in", 0, PARAM_AL, PARAM_UI8, 0 },
+ {"in", 0, PARAM_AW, PARAM_UI8, 0 },
+ {"out", 0, PARAM_UI8, PARAM_AL, 0 },
+ {"out", 0, PARAM_UI8, PARAM_AW, 0 },
+ {"call", 0, PARAM_REL16, 0, 0, DASMFLAG_STEP_OVER},
+ {"br", 0, PARAM_REL16, 0, 0 },
+ {"br", 0, PARAM_ADDR, 0, 0 },
+ {"br", 0, PARAM_REL8, 0, 0 },
+ {"in", 0, PARAM_AL, PARAM_DW, 0 },
+ {"in", 0, PARAM_AW, PARAM_DW, 0 },
+ {"out", 0, PARAM_DW, PARAM_AL, 0 },
+ {"out", 0, PARAM_DW, PARAM_AW, 0 },
+ // 0xf0
+ {"buslock", PREFIX, 0, 0, 0 },
+ {"brks", 0, PARAM_UI8, 0, 0, DASMFLAG_STEP_OVER}, /* V25S/V35S only */
+ {"repne", PREFIX, 0, 0, 0 },
+ {"rep", PREFIX, 0, 0, 0 },
+ {"halt", 0, 0, 0, 0 },
+ {"not1 cy", 0, 0, 0, 0 },
+ {"group1b", GROUP, 0, 0, 0 },
+ {"group1w", GROUP, 0, 0, 0 },
+ {"clr1 cy", 0, 0, 0, 0 },
+ {"set1 cy", 0, 0, 0, 0 },
+ {"di", 0, 0, 0, 0 },
+ {"ei", 0, 0, 0, 0 },
+ {"clr1 dir", 0, 0, 0, 0 },
+ {"set1 dir", 0, 0, 0, 0 },
+ {"group2b", GROUP, 0, 0, 0 },
+ {"group2w", GROUP, 0, 0, 0 }
+};
+
+static const I386_OPCODE necv_opcode_table2[256] =
+{
+ // 0x00
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ // 0x10
+ {"test1", MODRM, PARAM_RMPTR8, PARAM_CL, 0 },
+ {"test1", MODRM, PARAM_RMPTR16, PARAM_CL, 0 },
+ {"clr1", MODRM, PARAM_RMPTR8, PARAM_CL, 0 },
+ {"clr1", MODRM, PARAM_RMPTR16, PARAM_CL, 0 },
+ {"set1", MODRM, PARAM_RMPTR8, PARAM_CL, 0 },
+ {"set1", MODRM, PARAM_RMPTR16, PARAM_CL, 0 },
+ {"not1", MODRM, PARAM_RMPTR8, PARAM_CL, 0 },
+ {"not1", MODRM, PARAM_RMPTR16, PARAM_CL, 0 },
+ {"test1", MODRM, PARAM_RMPTR8, PARAM_I3, 0 },
+ {"test1", MODRM, PARAM_RMPTR16, PARAM_I4, 0 },
+ {"clr1", MODRM, PARAM_RMPTR8, PARAM_I3, 0 },
+ {"clr1", MODRM, PARAM_RMPTR16, PARAM_I4, 0 },
+ {"set1", MODRM, PARAM_RMPTR8, PARAM_I3, 0 },
+ {"set1", MODRM, PARAM_RMPTR16, PARAM_I4, 0 },
+ {"not1", MODRM, PARAM_RMPTR8, PARAM_I3, 0 },
+ {"not1", MODRM, PARAM_RMPTR16, PARAM_I4, 0 },
+ // 0x20
+ {"add4s", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"sub4s", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"movspa", 0, 0, 0, 0 }, /* V25/V35 only */
+ {"cmp4s", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"rol4", MODRM, PARAM_RMPTR8, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"ror4", MODRM, PARAM_RMPTR8, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"brkcs", MODRM, PARAM_REG2_16, 0, 0, DASMFLAG_STEP_OVER}, /* V25/V35 only */
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ // 0x30
+ {"???", 0, 0, 0, 0 },
+ {"ins", MODRM, PARAM_REG2_8, PARAM_REG8, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"ext", MODRM, PARAM_REG2_8, PARAM_REG8, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"ins", MODRM, PARAM_REG2_8, PARAM_I4, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"ext", MODRM, PARAM_REG2_8, PARAM_I4, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ // 0x40
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ // 0x50
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ // 0x60
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ // 0x70
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ // 0x80
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ // 0x90
+ {"???", 0, 0, 0, 0 },
+ {"retrbi", 0, 0, 0, 0 }, /* V25/V35 only */
+ {"fint", 0, 0, 0, 0 }, /* V25/V35 only */
+ {"???", 0, 0, 0, 0 },
+ {"tsksw", MODRM, PARAM_REG2_16, 0, 0 }, /* V25/V35 only */
+ {"movspb", MODRM, PARAM_REG2_16, 0, 0 }, /* V25/V35 only */
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"btclr", 0, PARAM_SFREG, PARAM_I3, PARAM_REL8 }, /* V25/V35 only */
+ {"???", 0, 0, 0, 0 },
+ {"stop", 0, 0, 0, 0 }, /* V25/V35 only */
+ {"???", 0, 0, 0, 0 },
+ // 0xa0
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ // 0xb0
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ // 0xc0
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ // 0xd0
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ // 0xe0
+ {"brkxa", 0, PARAM_UI8, 0, 0 }, /* V33,53 only */
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ // 0xf0
+ {"retxa", 0, PARAM_UI8, 0, 0 }, /* V33,53 only */
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"brkem", 0, PARAM_UI8, 0, 0 } /* V20,30,40,50 only */
+};
+
+static const I386_OPCODE immb_table[8] =
+{
+ {"add", 0, PARAM_RMPTR8, PARAM_UI8, 0 },
+ {"or", 0, PARAM_RMPTR8, PARAM_UI8, 0 },
+ {"addc", 0, PARAM_RMPTR8, PARAM_UI8, 0 },
+ {"subc", 0, PARAM_RMPTR8, PARAM_UI8, 0 },
+ {"and", 0, PARAM_RMPTR8, PARAM_UI8, 0 },
+ {"sub", 0, PARAM_RMPTR8, PARAM_UI8, 0 },
+ {"xor", 0, PARAM_RMPTR8, PARAM_UI8, 0 },
+ {"cmp", 0, PARAM_RMPTR8, PARAM_UI8, 0 }
+};
+
+static const I386_OPCODE immw_table[8] =
+{
+ {"add", 0, PARAM_RMPTR16, PARAM_IMM, 0 },
+ {"or", 0, PARAM_RMPTR16, PARAM_IMM, 0 },
+ {"addc", 0, PARAM_RMPTR16, PARAM_IMM, 0 },
+ {"subc", 0, PARAM_RMPTR16, PARAM_IMM, 0 },
+ {"and", 0, PARAM_RMPTR16, PARAM_IMM, 0 },
+ {"sub", 0, PARAM_RMPTR16, PARAM_IMM, 0 },
+ {"xor", 0, PARAM_RMPTR16, PARAM_IMM, 0 },
+ {"cmp", 0, PARAM_RMPTR16, PARAM_IMM, 0 }
+};
+
+static const I386_OPCODE immws_table[8] =
+{
+ {"add", 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {"or", 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {"addc", 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {"subc", 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {"and", 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {"sub", 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {"xor", 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {"cmp", 0, PARAM_RMPTR16, PARAM_I8, 0 }
+};
+
+static const I386_OPCODE shiftbi_table[8] =
+{
+ {"rol", 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {"ror", 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {"rolc", 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {"rorc", 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {"shl", 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {"shr", 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {"???", 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {"shra", 0, PARAM_RMPTR8, PARAM_I8, 0 }
+};
+
+static const I386_OPCODE shiftwi_table[8] =
+{
+ {"rol", 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {"ror", 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {"rolc", 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {"rorc", 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {"shl", 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {"shr", 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {"???", 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {"shra", 0, PARAM_RMPTR16, PARAM_I8, 0 }
+};
+
+static const I386_OPCODE shiftb_table[8] =
+{
+ {"rol", 0, PARAM_RMPTR8, PARAM_1, 0 },
+ {"ror", 0, PARAM_RMPTR8, PARAM_1, 0 },
+ {"rolc", 0, PARAM_RMPTR8, PARAM_1, 0 },
+ {"rorc", 0, PARAM_RMPTR8, PARAM_1, 0 },
+ {"shl", 0, PARAM_RMPTR8, PARAM_1, 0 },
+ {"shr", 0, PARAM_RMPTR8, PARAM_1, 0 },
+ {"???", 0, PARAM_RMPTR8, PARAM_1, 0 },
+ {"shra", 0, PARAM_RMPTR8, PARAM_1, 0 }
+};
+
+static const I386_OPCODE shiftw_table[8] =
+{
+ {"rol", 0, PARAM_RMPTR16, PARAM_1, 0 },
+ {"ror", 0, PARAM_RMPTR16, PARAM_1, 0 },
+ {"rolc", 0, PARAM_RMPTR16, PARAM_1, 0 },
+ {"rorc", 0, PARAM_RMPTR16, PARAM_1, 0 },
+ {"shl", 0, PARAM_RMPTR16, PARAM_1, 0 },
+ {"shr", 0, PARAM_RMPTR16, PARAM_1, 0 },
+ {"???", 0, PARAM_RMPTR16, PARAM_1, 0 },
+ {"shra", 0, PARAM_RMPTR16, PARAM_1, 0 }
+};
+
+static const I386_OPCODE shiftbv_table[8] =
+{
+ {"rol", 0, PARAM_RMPTR8, PARAM_CL, 0 },
+ {"ror", 0, PARAM_RMPTR8, PARAM_CL, 0 },
+ {"rolc", 0, PARAM_RMPTR8, PARAM_CL, 0 },
+ {"rorc", 0, PARAM_RMPTR8, PARAM_CL, 0 },
+ {"shl", 0, PARAM_RMPTR8, PARAM_CL, 0 },
+ {"shr", 0, PARAM_RMPTR8, PARAM_CL, 0 },
+ {"???", 0, PARAM_RMPTR8, PARAM_CL, 0 },
+ {"shra", 0, PARAM_RMPTR8, PARAM_CL, 0 }
+};
+
+static const I386_OPCODE shiftwv_table[8] =
+{
+ {"rol", 0, PARAM_RMPTR16, PARAM_CL, 0 },
+ {"ror", 0, PARAM_RMPTR16, PARAM_CL, 0 },
+ {"rolc", 0, PARAM_RMPTR16, PARAM_CL, 0 },
+ {"rorc", 0, PARAM_RMPTR16, PARAM_CL, 0 },
+ {"shl", 0, PARAM_RMPTR16, PARAM_CL, 0 },
+ {"shr", 0, PARAM_RMPTR16, PARAM_CL, 0 },
+ {"???", 0, PARAM_RMPTR16, PARAM_CL, 0 },
+ {"shra", 0, PARAM_RMPTR16, PARAM_CL, 0 }
+};
+
+static const I386_OPCODE group1b_table[8] =
+{
+ {"test", 0, PARAM_RMPTR8, PARAM_UI8, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"not", 0, PARAM_RMPTR8, 0, 0 },
+ {"neg", 0, PARAM_RMPTR8, 0, 0 },
+ {"mulu", 0, PARAM_RMPTR8, 0, 0 },
+ {"mul", 0, PARAM_RMPTR8, 0, 0 },
+ {"divu", 0, PARAM_RMPTR8, 0, 0 },
+ {"div", 0, PARAM_RMPTR8, 0, 0 }
+};
+
+static const I386_OPCODE group1w_table[8] =
+{
+ {"test", 0, PARAM_RMPTR16, PARAM_IMM, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"not", 0, PARAM_RMPTR16, 0, 0 },
+ {"neg", 0, PARAM_RMPTR16, 0, 0 },
+ {"mulu", 0, PARAM_RMPTR16, 0, 0 },
+ {"mul", 0, PARAM_RMPTR16, 0, 0 },
+ {"divu", 0, PARAM_RMPTR16, 0, 0 },
+ {"div", 0, PARAM_RMPTR16, 0, 0 }
+};
+
+static const I386_OPCODE group2b_table[8] =
+{
+ {"inc", 0, PARAM_RMPTR8, 0, 0 },
+ {"dec", 0, PARAM_RMPTR8, 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 }
+};
+
+static const I386_OPCODE group2w_table[8] =
+{
+ {"inc", 0, PARAM_RMPTR16, 0, 0 },
+ {"dec", 0, PARAM_RMPTR16, 0, 0 },
+ {"call", 0, PARAM_RMPTR16, 0, 0, DASMFLAG_STEP_OVER},
+ {"call far ptr ",0, PARAM_RM16, 0, 0, DASMFLAG_STEP_OVER},
+ {"br", 0, PARAM_RMPTR16, 0, 0 },
+ {"br far ptr ",0, PARAM_RM16, 0, 0 },
+ {"push", 0, PARAM_RMPTR16, 0, 0 },
+ {"???", 0, 0, 0, 0 }
+};
+
+static const GROUP_OP group_op_table[] =
+{
+ { "immb", immb_table },
+ { "immw", immw_table },
+ { "immws", immws_table },
+ { "shiftbi", shiftbi_table },
+ { "shiftwi", shiftwi_table },
+ { "shiftb", shiftb_table },
+ { "shiftw", shiftw_table },
+ { "shiftbv", shiftbv_table },
+ { "shiftwv", shiftwv_table },
+ { "group1b", group1b_table },
+ { "group1w", group1w_table },
+ { "group2b", group2b_table },
+ { "group2w", group2w_table }
+};
+
+
+
+static const char *const nec_reg[8] = { "aw", "cw", "dw", "bw", "sp", "bp", "ix", "iy" };
+static const char *const nec_reg8[8] = { "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh" };
+static const char *const nec_sreg[8] = { "ds1", "ps", "ss", "ds0", "???", "???", "???", "???" };
+static const char *const nec_sfreg[256] =
+{
+ /* 0x00 */
+ "p0", "pm0", "pmc0", "???", "???", "???", "???", "???",
+ "p1", "pm1", "pmc1", "???", "???", "???", "???", "???",
+ /* 0x10 */
+ "p2", "pm2", "pmc2", "???", "???", "???", "???", "???",
+ "???", "???", "???", "???", "???", "???", "???", "???",
+ /* 0x20 */
+ "???", "???", "???", "???", "???", "???", "???", "???",
+ "???", "???", "???", "???", "???", "???", "???", "???",
+ /* 0x30 */
+ "???", "???", "???", "???", "???", "???", "???", "???",
+ "pt", "???", "???", "pmt", "???", "???", "???", "???",
+ /* 0x40 */
+ "intm", "???", "???", "???", "ems0", "ems1", "ems2", "???",
+ "???", "???", "???", "???", "exic0","exic1","exic2","???",
+ /* 0x50 */
+ "???", "???", "???", "???", "???", "???", "???", "???",
+ "???", "???", "???", "???", "???", "???", "???", "???",
+ /* 0x60 */
+ "rxb0", "???", "txb0", "???", "???", "srms0","stms0","???",
+ "scm0", "scc0", "brg0", "scs0", "seic0","sric0","stic0","???",
+ /* 0x70 */
+ "rxb1", "???", "txb1", "???", "???", "srms1","stms1","???",
+ "scm1", "scc1", "brg1", "scs1", "seic1","sric1","stic1","???",
+ /* 0x80 */
+ "tm0", "???", "md0", "???", "???", "???", "???", "???",
+ "tm1", "???", "md1", "???", "???", "???", "???", "???",
+ /* 0x90 */
+ "tmc0", "tmc1", "???", "???", "tmms0","tmms1","tmms2","???",
+ "???", "???", "???", "???", "tmic0","tmic1","tmic2","???",
+ /* 0xa0 */
+ "dmac0","dmam0","dmac1","dmam1","???", "???", "???", "???",
+ "???", "???", "???", "???", "dic0", "dic1", "???", "???",
+ /* 0xb0 */
+ "???", "???", "???", "???", "???", "???", "???", "???",
+ "???", "???", "???", "???", "???", "???", "???", "???",
+ /* 0xc0 */
+ "sar0l","sar0m","sar0h","???", "dar0l","dar0m","dar0h","???",
+ "tc0l", "tc0h", "???", "???", "???", "???", "???", "???",
+ /* 0xd0 */
+ "sar1l","sar1m","sar1h","???", "dar1l","dar1m","dar1h","???",
+ "tc1l", "tc1h", "???", "???", "???", "???", "???", "???",
+ /* 0xe0 */
+ "stbc", "rfm", "???", "???", "???", "???", "???", "???",
+ "wtc", "???", "flag", "prc", "tbic", "???", "???", "irqs",
+ /* 0xf0 */
+ "???", "???", "???", "???", "???", "???", "???", "???",
+ "???", "???", "???", "???", "ispr", "???", "???", "idb"
+};
+
+static UINT32 pc;
+static UINT8 modrm;
+static UINT32 segment;
+static offs_t dasm_flags;
+static char modrm_string[256];
+
+#define MODRM_REG1 ((modrm >> 3) & 0x7)
+#define MODRM_REG2 (modrm & 0x7)
+
+#define MAX_LENGTH 8
+
+INLINE UINT8 FETCH(void)
+{
+ if ((opcode_ptr - opcode_ptr_base) + 1 > MAX_LENGTH)
+ return 0xff;
+ pc++;
+ return *opcode_ptr++;
+}
+
+INLINE UINT16 FETCH16(void)
+{
+ UINT16 d;
+ if ((opcode_ptr - opcode_ptr_base) + 2 > MAX_LENGTH)
+ return 0xffff;
+ d = opcode_ptr[0] | (opcode_ptr[1] << 8);
+ opcode_ptr += 2;
+ pc += 2;
+ return d;
+}
+
+INLINE UINT8 FETCHD(void)
+{
+ if ((opcode_ptr - opcode_ptr_base) + 1 > MAX_LENGTH)
+ return 0xff;
+ pc++;
+ return *opcode_ptr++;
+}
+
+INLINE UINT16 FETCHD16(void)
+{
+ UINT16 d;
+ if ((opcode_ptr - opcode_ptr_base) + 2 > MAX_LENGTH)
+ return 0xffff;
+ d = opcode_ptr[0] | (opcode_ptr[1] << 8);
+ opcode_ptr += 2;
+ pc += 2;
+ return d;
+}
+
+static char *hexstring(UINT32 value, int digits)
+{
+ static char buffer[20];
+ buffer[0] = '0';
+ if (digits)
+ sprintf(&buffer[1], "%0*Xh", digits, value);
+ else
+ sprintf(&buffer[1], "%Xh", value);
+ return (buffer[1] >= '0' && buffer[1] <= '9') ? &buffer[1] : &buffer[0];
+}
+
+static char *shexstring(UINT32 value, int digits, int always)
+{
+ static char buffer[20];
+ if (value >= 0x80000000)
+ sprintf(buffer, "-%s", hexstring(-value, digits));
+ else if (always)
+ sprintf(buffer, "+%s", hexstring(value, digits));
+ else
+ return hexstring(value, digits);
+ return buffer;
+}
+
+static void handle_modrm(char* s)
+{
+ INT8 disp8;
+ INT16 disp16;
+ UINT8 mod, rm;
+
+ modrm = FETCHD();
+ mod = (modrm >> 6) & 0x3;
+ rm = (modrm & 0x7);
+
+ if( modrm >= 0xc0 )
+ return;
+
+ switch(segment)
+ {
+ case SEG_PS: s += sprintf( s, "ps:" ); break;
+ case SEG_DS0: s += sprintf( s, "ds0:" ); break;
+ case SEG_DS1: s += sprintf( s, "ds1:" ); break;
+ case SEG_SS: s += sprintf( s, "ss:" ); break;
+ }
+
+ s += sprintf( s, "[" );
+ switch( rm )
+ {
+ case 0: s += sprintf( s, "bw+ix" ); break;
+ case 1: s += sprintf( s, "bw+iy" ); break;
+ case 2: s += sprintf( s, "bp+ix" ); break;
+ case 3: s += sprintf( s, "bp+iy" ); break;
+ case 4: s += sprintf( s, "ix" ); break;
+ case 5: s += sprintf( s, "iy" ); break;
+ case 6:
+ if( mod == 0 ) {
+ disp16 = FETCHD16();
+ s += sprintf( s, "%s", hexstring((unsigned) (UINT16) disp16, 0) );
+ } else {
+ s += sprintf( s, "bp" );
+ }
+ break;
+ case 7: s += sprintf( s, "bw" ); break;
+ }
+ if( mod == 1 ) {
+ disp8 = FETCHD();
+ s += sprintf( s, "%s", shexstring((INT32)disp8, 0, TRUE) );
+ } else if( mod == 2 ) {
+ disp16 = FETCHD16();
+ s += sprintf( s, "%s", shexstring((INT32)disp16, 0, TRUE) );
+ }
+ s += sprintf( s, "]" );
+}
+
+static char* handle_param(char* s, UINT32 param)
+{
+ UINT8 i8;
+ UINT16 i16;
+ UINT16 ptr;
+ UINT32 addr;
+ INT8 d8;
+ INT16 d16;
+
+ switch(param)
+ {
+ case PARAM_REG8:
+ s += sprintf( s, "%s", nec_reg8[MODRM_REG1] );
+ break;
+
+ case PARAM_REG16:
+ s += sprintf( s, "%s", nec_reg[MODRM_REG1] );
+ break;
+
+ case PARAM_REG2_8:
+ s += sprintf( s, "%s", nec_reg8[MODRM_REG2] );
+ break;
+
+ case PARAM_REG2_16:
+ s += sprintf( s, "%s", nec_reg[MODRM_REG2] );
+ break;
+
+ case PARAM_RM8:
+ case PARAM_RMPTR8:
+ if( modrm >= 0xc0 ) {
+ s += sprintf( s, "%s", nec_reg8[MODRM_REG2] );
+ } else {
+ if (param == PARAM_RMPTR8)
+ s += sprintf( s, "byte ptr " );
+ s += sprintf( s, "%s", modrm_string );
+ }
+ break;
+
+ case PARAM_RM16:
+ case PARAM_RMPTR16:
+ if( modrm >= 0xc0 ) {
+ s += sprintf( s, "%s", nec_reg[MODRM_REG2] );
+ } else {
+ if (param == PARAM_RMPTR16)
+ s += sprintf( s, "word ptr " );
+ s += sprintf( s, "%s", modrm_string );
+ }
+ break;
+
+ case PARAM_I3:
+ i8 = FETCHD();
+ s += sprintf( s, "%d", i8 & 0x07 );
+ break;
+
+ case PARAM_I4:
+ i8 = FETCHD();
+ s += sprintf( s, "%d", i8 & 0x0f );
+ break;
+
+ case PARAM_I8:
+ i8 = FETCHD();
+ s += sprintf( s, "%s", shexstring((INT8)i8, 0, FALSE) );
+ break;
+
+ case PARAM_I16:
+ i16 = FETCHD16();
+ s += sprintf( s, "%s", shexstring((INT16)i16, 0, FALSE) );
+ break;
+
+ case PARAM_UI8:
+ i8 = FETCHD();
+ s += sprintf( s, "%s", shexstring((UINT8)i8, 0, FALSE) );
+ break;
+
+ case PARAM_IMM:
+ i16 = FETCHD16();
+ s += sprintf( s, "%s", hexstring(i16, 0) );
+ break;
+
+ case PARAM_ADDR:
+ addr = FETCHD16();
+ ptr = FETCHD16();
+ s += sprintf( s, "%s:", hexstring(ptr, 4) );
+ s += sprintf( s, "%s", hexstring(addr, 0) );
+ break;
+
+ case PARAM_REL16:
+ /* make sure to keep the relative offset within the segment */
+ d16 = FETCHD16();
+ s += sprintf( s, "%s", hexstring((pc & 0xFFFF0000) | ((pc + d16) & 0x0000FFFF), 0) );
+ break;
+
+ case PARAM_REL8:
+ d8 = FETCHD();
+ s += sprintf( s, "%s", hexstring(pc + d8, 0) );
+ break;
+
+ case PARAM_MEM_OFFS:
+ switch(segment)
+ {
+ case SEG_PS: s += sprintf( s, "ps:" ); break;
+ case SEG_DS0: s += sprintf( s, "ds0:" ); break;
+ case SEG_DS1: s += sprintf( s, "ds1:" ); break;
+ case SEG_SS: s += sprintf( s, "ss:" ); break;
+ }
+
+ i16 = FETCHD16();
+ s += sprintf( s, "[%s]", hexstring(i16, 0) );
+ break;
+
+ case PARAM_SREG:
+ s += sprintf( s, "%s", nec_sreg[MODRM_REG1] );
+ break;
+
+ case PARAM_SFREG:
+ i8 = FETCHD();
+ s += sprintf( s, "%s", nec_sfreg[i8] );
+ break;
+
+ case PARAM_1:
+ s += sprintf( s, "1" );
+ break;
+
+ case PARAM_AL: s += sprintf( s, "al" ); break;
+ case PARAM_CL: s += sprintf( s, "cl" ); break;
+ case PARAM_DL: s += sprintf( s, "dl" ); break;
+ case PARAM_BL: s += sprintf( s, "bl" ); break;
+ case PARAM_AH: s += sprintf( s, "ah" ); break;
+ case PARAM_CH: s += sprintf( s, "ch" ); break;
+ case PARAM_DH: s += sprintf( s, "dh" ); break;
+ case PARAM_BH: s += sprintf( s, "bh" ); break;
+
+ case PARAM_AW: s += sprintf( s, "aw" ); break;
+ case PARAM_CW: s += sprintf( s, "cw" ); break;
+ case PARAM_DW: s += sprintf( s, "dw" ); break;
+ case PARAM_BW: s += sprintf( s, "bw" ); break;
+ case PARAM_SP: s += sprintf( s, "sp" ); break;
+ case PARAM_BP: s += sprintf( s, "bp" ); break;
+ case PARAM_IX: s += sprintf( s, "ix" ); break;
+ case PARAM_IY: s += sprintf( s, "iy" ); break;
+ }
+ return s;
+}
+
+static void handle_fpu(char *s, UINT8 op1, UINT8 op2)
+{
+ switch (op1 & 0x7)
+ {
+ case 0: // Group D8
+ {
+ if (op2 < 0xc0)
+ {
+ pc--; // adjust fetch pointer, so modrm byte read again
+ opcode_ptr--;
+ handle_modrm( modrm_string );
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: sprintf(s, "fadd dword ptr %s", modrm_string); break;
+ case 1: sprintf(s, "fmul dword ptr %s", modrm_string); break;
+ case 2: sprintf(s, "fcom dword ptr %s", modrm_string); break;
+ case 3: sprintf(s, "fcomp dword ptr %s", modrm_string); break;
+ case 4: sprintf(s, "fsub dword ptr %s", modrm_string); break;
+ case 5: sprintf(s, "fsubr dword ptr %s", modrm_string); break;
+ case 6: sprintf(s, "fdiv dword ptr %s", modrm_string); break;
+ case 7: sprintf(s, "fdivr dword ptr %s", modrm_string); break;
+ }
+ }
+ else
+ {
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: sprintf(s, "fadd st(0),st(%d)", op2 & 0x7); break;
+ case 1: sprintf(s, "fcom st(0),st(%d)", op2 & 0x7); break;
+ case 2: sprintf(s, "fsub st(0),st(%d)", op2 & 0x7); break;
+ case 3: sprintf(s, "fdiv st(0),st(%d)", op2 & 0x7); break;
+ case 4: sprintf(s, "fmul st(0),st(%d)", op2 & 0x7); break;
+ case 5: sprintf(s, "fcomp st(0),st(%d)", op2 & 0x7); break;
+ case 6: sprintf(s, "fsubr st(0),st(%d)", op2 & 0x7); break;
+ case 7: sprintf(s, "fdivr st(0),st(%d)", op2 & 0x7); break;
+ }
+ }
+ break;
+ }
+
+ case 1: // Group D9
+ {
+ if (op2 < 0xc0)
+ {
+ pc--; // adjust fetch pointer, so modrm byte read again
+ opcode_ptr--;
+ handle_modrm( modrm_string );
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: sprintf(s, "fld dword ptr %s", modrm_string); break;
+ case 1: sprintf(s, "??? (FPU)"); break;
+ case 2: sprintf(s, "fst dword ptr %s", modrm_string); break;
+ case 3: sprintf(s, "fstp dword ptr %s", modrm_string); break;
+ case 4: sprintf(s, "fldenv word ptr %s", modrm_string); break;
+ case 5: sprintf(s, "fldcw word ptr %s", modrm_string); break;
+ case 6: sprintf(s, "fstenv word ptr %s", modrm_string); break;
+ case 7: sprintf(s, "fstcw word ptr %s", modrm_string); break;
+ }
+ }
+ else
+ {
+ switch (op2 & 0x3f)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+ sprintf(s, "fld st(0),st(%d)", op2 & 0x7); break;
+
+ case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ sprintf(s, "fxch st(0),st(%d)", op2 & 0x7); break;
+
+ case 0x10: sprintf(s, "fnop"); break;
+ case 0x20: sprintf(s, "fchs"); break;
+ case 0x21: sprintf(s, "fabs"); break;
+ case 0x24: sprintf(s, "ftst"); break;
+ case 0x25: sprintf(s, "fxam"); break;
+ case 0x28: sprintf(s, "fld1"); break;
+ case 0x29: sprintf(s, "fldl2t"); break;
+ case 0x2a: sprintf(s, "fldl2e"); break;
+ case 0x2b: sprintf(s, "fldpi"); break;
+ case 0x2c: sprintf(s, "fldlg2"); break;
+ case 0x2d: sprintf(s, "fldln2"); break;
+ case 0x2e: sprintf(s, "fldz"); break;
+ case 0x30: sprintf(s, "f2xm1"); break;
+ case 0x31: sprintf(s, "fyl2x"); break;
+ case 0x32: sprintf(s, "fptan"); break;
+ case 0x33: sprintf(s, "fpatan"); break;
+ case 0x34: sprintf(s, "fxtract"); break;
+ case 0x35: sprintf(s, "fprem1"); break;
+ case 0x36: sprintf(s, "fdecstp"); break;
+ case 0x37: sprintf(s, "fincstp"); break;
+ case 0x38: sprintf(s, "fprem"); break;
+ case 0x39: sprintf(s, "fyl2xp1"); break;
+ case 0x3a: sprintf(s, "fsqrt"); break;
+ case 0x3b: sprintf(s, "fsincos"); break;
+ case 0x3c: sprintf(s, "frndint"); break;
+ case 0x3d: sprintf(s, "fscale"); break;
+ case 0x3e: sprintf(s, "fsin"); break;
+ case 0x3f: sprintf(s, "fcos"); break;
+
+ default: sprintf(s, "??? (FPU)"); break;
+ }
+ }
+ break;
+ }
+
+ case 2: // Group DA
+ {
+ if (op2 < 0xc0)
+ {
+ pc--; // adjust fetch pointer, so modrm byte read again
+ opcode_ptr--;
+ handle_modrm( modrm_string );
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: sprintf(s, "fiadd dword ptr %s", modrm_string); break;
+ case 1: sprintf(s, "fimul dword ptr %s", modrm_string); break;
+ case 2: sprintf(s, "ficom dword ptr %s", modrm_string); break;
+ case 3: sprintf(s, "ficomp dword ptr %s", modrm_string); break;
+ case 4: sprintf(s, "fisub dword ptr %s", modrm_string); break;
+ case 5: sprintf(s, "fisubr dword ptr %s", modrm_string); break;
+ case 6: sprintf(s, "fidiv dword ptr %s", modrm_string); break;
+ case 7: sprintf(s, "fidivr dword ptr %s", modrm_string); break;
+ }
+ }
+ else
+ {
+ switch (op2 & 0x3f)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+ sprintf(s, "fcmovb st(0),st(%d)", op2 & 0x7); break;
+
+ case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ sprintf(s, "fcmove st(0),st(%d)", op2 & 0x7); break;
+
+ case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
+ sprintf(s, "fcmovbe st(0),st(%d)", op2 & 0x7); break;
+
+ case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ sprintf(s, "fcmovu st(0),st(%d)", op2 & 0x7); break;
+
+ default: sprintf(s, "??? (FPU)"); break;
+
+ }
+ }
+ break;
+ }
+
+ case 3: // Group DB
+ {
+ if (op2 < 0xc0)
+ {
+ pc--; // adjust fetch pointer, so modrm byte read again
+ opcode_ptr--;
+ handle_modrm( modrm_string );
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: sprintf(s, "fild dword ptr %s", modrm_string); break;
+ case 1: sprintf(s, "??? (FPU)"); break;
+ case 2: sprintf(s, "fist dword ptr %s", modrm_string); break;
+ case 3: sprintf(s, "fistp dword ptr %s", modrm_string); break;
+ case 4: sprintf(s, "??? (FPU)"); break;
+ case 5: sprintf(s, "fld tword ptr %s", modrm_string); break;
+ case 6: sprintf(s, "??? (FPU)"); break;
+ case 7: sprintf(s, "fstp tword ptr %s", modrm_string); break;
+ }
+ }
+ else
+ {
+ switch (op2 & 0x3f)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+ sprintf(s, "fcmovnb st(0),st(%d)", op2 & 0x7); break;
+
+ case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ sprintf(s, "fcmovne st(0),st(%d)", op2 & 0x7); break;
+
+ case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
+ sprintf(s, "fcmovnbe st(0),st(%d)", op2 & 0x7); break;
+
+ case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ sprintf(s, "fcmovnu st(0),st(%d)", op2 & 0x7); break;
+
+ case 0x22: sprintf(s, "fclex"); break;
+ case 0x23: sprintf(s, "finit"); break;
+
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ sprintf(s, "fucomi st(0),st(%d)", op2 & 0x7); break;
+
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
+ sprintf(s, "fcomi st(0),st(%d)", op2 & 0x7); break;
+
+ default: sprintf(s, "??? (FPU)"); break;
+ }
+ }
+ break;
+ }
+
+ case 4: // Group DC
+ {
+ if (op2 < 0xc0)
+ {
+ pc--; // adjust fetch pointer, so modrm byte read again
+ opcode_ptr--;
+ handle_modrm( modrm_string );
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: sprintf(s, "fadd qword ptr %s", modrm_string); break;
+ case 1: sprintf(s, "fmul qword ptr %s", modrm_string); break;
+ case 2: sprintf(s, "fcom qword ptr %s", modrm_string); break;
+ case 3: sprintf(s, "fcomp qword ptr %s", modrm_string); break;
+ case 4: sprintf(s, "fsub qword ptr %s", modrm_string); break;
+ case 5: sprintf(s, "fsubr qword ptr %s", modrm_string); break;
+ case 6: sprintf(s, "fdiv qword ptr %s", modrm_string); break;
+ case 7: sprintf(s, "fdivr qword ptr %s", modrm_string); break;
+ }
+ }
+ else
+ {
+ switch (op2 & 0x3f)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+ sprintf(s, "fadd st(%d),st(0)", op2 & 0x7); break;
+
+ case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ sprintf(s, "fmul st(%d),st(0)", op2 & 0x7); break;
+
+ case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
+ sprintf(s, "fsubr st(%d),st(0)", op2 & 0x7); break;
+
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ sprintf(s, "fsub st(%d),st(0)", op2 & 0x7); break;
+
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
+ sprintf(s, "fdivr st(%d),st(0)", op2 & 0x7); break;
+
+ case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
+ sprintf(s, "fdiv st(%d),st(0)", op2 & 0x7); break;
+
+ default: sprintf(s, "??? (FPU)"); break;
+ }
+ }
+ break;
+ }
+
+ case 5: // Group DD
+ {
+ if (op2 < 0xc0)
+ {
+ pc--; // adjust fetch pointer, so modrm byte read again
+ opcode_ptr--;
+ handle_modrm( modrm_string );
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: sprintf(s, "fld qword ptr %s", modrm_string); break;
+ case 1: sprintf(s, "??? (FPU)"); break;
+ case 2: sprintf(s, "fst qword ptr %s", modrm_string); break;
+ case 3: sprintf(s, "fstp qword ptr %s", modrm_string); break;
+ case 4: sprintf(s, "frstor %s", modrm_string); break;
+ case 5: sprintf(s, "??? (FPU)"); break;
+ case 6: sprintf(s, "fsave %s", modrm_string); break;
+ case 7: sprintf(s, "fstsw word ptr %s", modrm_string); break;
+ }
+ }
+ else
+ {
+ switch (op2 & 0x3f)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+ sprintf(s, "ffree st(%d)", op2 & 0x7); break;
+
+ case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
+ sprintf(s, "fst st(%d)", op2 & 0x7); break;
+
+ case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ sprintf(s, "fstp st(%d)", op2 & 0x7); break;
+
+ case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
+ sprintf(s, "fucom st(%d), st(0)", op2 & 0x7); break;
+
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ sprintf(s, "fucomp st(%d)", op2 & 0x7); break;
+
+ default: sprintf(s, "??? (FPU)"); break;
+ }
+ }
+ break;
+ }
+
+ case 6: // Group DE
+ {
+ if (op2 < 0xc0)
+ {
+ pc--; // adjust fetch pointer, so modrm byte read again
+ opcode_ptr--;
+ handle_modrm( modrm_string );
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: sprintf(s, "fiadd word ptr %s", modrm_string); break;
+ case 1: sprintf(s, "fimul word ptr %s", modrm_string); break;
+ case 2: sprintf(s, "ficom word ptr %s", modrm_string); break;
+ case 3: sprintf(s, "ficomp word ptr %s", modrm_string); break;
+ case 4: sprintf(s, "fisub word ptr %s", modrm_string); break;
+ case 5: sprintf(s, "fisubr word ptr %s", modrm_string); break;
+ case 6: sprintf(s, "fidiv word ptr %s", modrm_string); break;
+ case 7: sprintf(s, "fidivr word ptr %s", modrm_string); break;
+ }
+ }
+ else
+ {
+ switch (op2 & 0x3f)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+ sprintf(s, "faddp st(%d)", op2 & 0x7); break;
+
+ case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ sprintf(s, "fmulp st(%d)", op2 & 0x7); break;
+
+ case 0x19: sprintf(s, "fcompp"); break;
+
+ case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
+ sprintf(s, "fsubrp st(%d)", op2 & 0x7); break;
+
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ sprintf(s, "fsubp st(%d)", op2 & 0x7); break;
+
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
+ sprintf(s, "fdivrp st(%d), st(0)", op2 & 0x7); break;
+
+ case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
+ sprintf(s, "fdivp st(%d)", op2 & 0x7); break;
+
+ default: sprintf(s, "??? (FPU)"); break;
+ }
+ }
+ break;
+ }
+
+ case 7: // Group DF
+ {
+ if (op2 < 0xc0)
+ {
+ pc--; // adjust fetch pointer, so modrm byte read again
+ opcode_ptr--;
+ handle_modrm( modrm_string );
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: sprintf(s, "fild word ptr %s", modrm_string); break;
+ case 1: sprintf(s, "??? (FPU)"); break;
+ case 2: sprintf(s, "fist word ptr %s", modrm_string); break;
+ case 3: sprintf(s, "fistp word ptr %s", modrm_string); break;
+ case 4: sprintf(s, "fbld %s", modrm_string); break;
+ case 5: sprintf(s, "fild qword ptr %s", modrm_string); break;
+ case 6: sprintf(s, "fbstp %s", modrm_string); break;
+ case 7: sprintf(s, "fistp qword ptr %s", modrm_string); break;
+ }
+ }
+ else
+ {
+ switch (op2 & 0x3f)
+ {
+ case 0x20: sprintf(s, "fstsw aw"); break;
+
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ sprintf(s, "fucomip st(%d)", op2 & 0x7); break;
+
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
+ sprintf(s, "fcomip st(%d),st(0)", op2 & 0x7); break;
+
+ default: sprintf(s, "??? (FPU)"); break;
+ }
+ }
+ break;
+ }
+ }
+}
+
+static void decode_opcode(char *s, const I386_OPCODE *op, UINT8 op1 )
+{
+ int i;
+ UINT8 op2;
+
+ switch( op->flags )
+ {
+ case TWO_BYTE:
+ op2 = FETCHD();
+ decode_opcode( s, &necv_opcode_table2[op2], op1 );
+ return;
+
+ case SEG_PS:
+ case SEG_DS0:
+ case SEG_DS1:
+ case SEG_SS:
+ segment = op->flags;
+ op2 = FETCH();
+ if (Iconfig->v25v35_decryptiontable) op2 = Iconfig->v25v35_decryptiontable[op2];
+ decode_opcode( s, &necv_opcode_table1[op2], op1 );
+ return;
+
+ case PREFIX:
+ s += sprintf( s, "%-8s", op->mnemonic );
+ op2 = FETCH();
+ if (Iconfig->v25v35_decryptiontable) op2 = Iconfig->v25v35_decryptiontable[op2];
+ decode_opcode( s, &necv_opcode_table1[op2], op1 );
+ return;
+
+ case GROUP:
+ handle_modrm( modrm_string );
+ for( i=0; i < ARRAY_LENGTH(group_op_table); i++ ) {
+ if( strcmp(op->mnemonic, group_op_table[i].mnemonic) == 0 )
+ {
+ decode_opcode( s, &group_op_table[i].opcode[MODRM_REG1], op1 );
+ return;
+ }
+ }
+ goto handle_unknown;
+
+ case FPU:
+ op2 = FETCHD();
+ handle_fpu( s, op1, op2);
+ return;
+
+ case MODRM:
+ handle_modrm( modrm_string );
+ break;
+ }
+
+ s += sprintf( s, "%-8s", op->mnemonic );
+ dasm_flags = op->dasm_flags;
+
+ if( op->param1 != 0 ) {
+ s = handle_param( s, op->param1 );
+ }
+
+ if( op->param2 != 0 ) {
+ s += sprintf( s, "," );
+ s = handle_param( s, op->param2 );
+ }
+
+ if( op->param3 != 0 ) {
+ s += sprintf( s, "," );
+ s = handle_param( s, op->param3 );
+ }
+ return;
+
+handle_unknown:
+ sprintf(s, "???");
+}
+
+int necv_dasm_one(char *buffer, UINT32 eip, const UINT8 *oprom, const nec_config *_config)
+{
+ UINT8 op;
+ const nec_config *config = _config ? _config : &default_config;
+ Iconfig = config;
+
+ opcode_ptr = opcode_ptr_base = oprom;
+ pc = eip;
+ dasm_flags = 0;
+ segment = 0;
+
+ op = FETCH();
+
+ if (Iconfig->v25v35_decryptiontable) op = Iconfig->v25v35_decryptiontable[op];
+
+ decode_opcode( buffer, &necv_opcode_table1[op], op );
+ return (pc-eip) | dasm_flags | DASMFLAG_SUPPORTED;
+}
+
+CPU_DISASSEMBLE( nec_generic )
+{
+ return necv_dasm_one(buffer, pc, oprom, NULL);
+}
+
diff --git a/trunk/src/emu/cpu/nec/necea.h b/trunk/src/emu/cpu/nec/necea.h
new file mode 100644
index 00000000000..cafbb27a620
--- /dev/null
+++ b/trunk/src/emu/cpu/nec/necea.h
@@ -0,0 +1,60 @@
+
+static UINT32 EA;
+static UINT16 EO;
+static UINT16 E16;
+
+static unsigned EA_000(nec_state_t *nec_state) { EO=Wreg(BW)+Wreg(IX); EA=DefaultBase(DS0)+EO; return EA; }
+static unsigned EA_001(nec_state_t *nec_state) { EO=Wreg(BW)+Wreg(IY); EA=DefaultBase(DS0)+EO; return EA; }
+static unsigned EA_002(nec_state_t *nec_state) { EO=Wreg(BP)+Wreg(IX); EA=DefaultBase(SS)+EO; return EA; }
+static unsigned EA_003(nec_state_t *nec_state) { EO=Wreg(BP)+Wreg(IY); EA=DefaultBase(SS)+EO; return EA; }
+static unsigned EA_004(nec_state_t *nec_state) { EO=Wreg(IX); EA=DefaultBase(DS0)+EO; return EA; }
+static unsigned EA_005(nec_state_t *nec_state) { EO=Wreg(IY); EA=DefaultBase(DS0)+EO; return EA; }
+static unsigned EA_006(nec_state_t *nec_state) { EO=FETCH(); EO+=FETCH()<<8; EA=DefaultBase(DS0)+EO; return EA; }
+static unsigned EA_007(nec_state_t *nec_state) { EO=Wreg(BW); EA=DefaultBase(DS0)+EO; return EA; }
+
+static unsigned EA_100(nec_state_t *nec_state) { EO=(Wreg(BW)+Wreg(IX)+(INT8)FETCH()); EA=DefaultBase(DS0)+EO; return EA; }
+static unsigned EA_101(nec_state_t *nec_state) { EO=(Wreg(BW)+Wreg(IY)+(INT8)FETCH()); EA=DefaultBase(DS0)+EO; return EA; }
+static unsigned EA_102(nec_state_t *nec_state) { EO=(Wreg(BP)+Wreg(IX)+(INT8)FETCH()); EA=DefaultBase(SS)+EO; return EA; }
+static unsigned EA_103(nec_state_t *nec_state) { EO=(Wreg(BP)+Wreg(IY)+(INT8)FETCH()); EA=DefaultBase(SS)+EO; return EA; }
+static unsigned EA_104(nec_state_t *nec_state) { EO=(Wreg(IX)+(INT8)FETCH()); EA=DefaultBase(DS0)+EO; return EA; }
+static unsigned EA_105(nec_state_t *nec_state) { EO=(Wreg(IY)+(INT8)FETCH()); EA=DefaultBase(DS0)+EO; return EA; }
+static unsigned EA_106(nec_state_t *nec_state) { EO=(Wreg(BP)+(INT8)FETCH()); EA=DefaultBase(SS)+EO; return EA; }
+static unsigned EA_107(nec_state_t *nec_state) { EO=(Wreg(BW)+(INT8)FETCH()); EA=DefaultBase(DS0)+EO; return EA; }
+
+static unsigned EA_200(nec_state_t *nec_state) { E16=FETCH(); E16+=FETCH()<<8; EO=Wreg(BW)+Wreg(IX)+(INT16)E16; EA=DefaultBase(DS0)+EO; return EA; }
+static unsigned EA_201(nec_state_t *nec_state) { E16=FETCH(); E16+=FETCH()<<8; EO=Wreg(BW)+Wreg(IY)+(INT16)E16; EA=DefaultBase(DS0)+EO; return EA; }
+static unsigned EA_202(nec_state_t *nec_state) { E16=FETCH(); E16+=FETCH()<<8; EO=Wreg(BP)+Wreg(IX)+(INT16)E16; EA=DefaultBase(SS)+EO; return EA; }
+static unsigned EA_203(nec_state_t *nec_state) { E16=FETCH(); E16+=FETCH()<<8; EO=Wreg(BP)+Wreg(IY)+(INT16)E16; EA=DefaultBase(SS)+EO; return EA; }
+static unsigned EA_204(nec_state_t *nec_state) { E16=FETCH(); E16+=FETCH()<<8; EO=Wreg(IX)+(INT16)E16; EA=DefaultBase(DS0)+EO; return EA; }
+static unsigned EA_205(nec_state_t *nec_state) { E16=FETCH(); E16+=FETCH()<<8; EO=Wreg(IY)+(INT16)E16; EA=DefaultBase(DS0)+EO; return EA; }
+static unsigned EA_206(nec_state_t *nec_state) { E16=FETCH(); E16+=FETCH()<<8; EO=Wreg(BP)+(INT16)E16; EA=DefaultBase(SS)+EO; return EA; }
+static unsigned EA_207(nec_state_t *nec_state) { E16=FETCH(); E16+=FETCH()<<8; EO=Wreg(BW)+(INT16)E16; EA=DefaultBase(DS0)+EO; return EA; }
+
+static unsigned (*const GetEA[192])(nec_state_t *)={
+ EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007,
+ EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007,
+ EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007,
+ EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007,
+ EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007,
+ EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007,
+ EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007,
+ EA_000, EA_001, EA_002, EA_003, EA_004, EA_005, EA_006, EA_007,
+
+ EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107,
+ EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107,
+ EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107,
+ EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107,
+ EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107,
+ EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107,
+ EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107,
+ EA_100, EA_101, EA_102, EA_103, EA_104, EA_105, EA_106, EA_107,
+
+ EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207,
+ EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207,
+ EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207,
+ EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207,
+ EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207,
+ EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207,
+ EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207,
+ EA_200, EA_201, EA_202, EA_203, EA_204, EA_205, EA_206, EA_207
+};
diff --git a/trunk/src/emu/cpu/nec/necinstr.c b/trunk/src/emu/cpu/nec/necinstr.c
new file mode 100644
index 00000000000..63fb0270c56
--- /dev/null
+++ b/trunk/src/emu/cpu/nec/necinstr.c
@@ -0,0 +1,671 @@
+#define OP(num,func_name) static void func_name(nec_state_t *nec_state)
+
+OP( 0x00, i_add_br8 ) { DEF_br8; ADDB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); }
+OP( 0x01, i_add_wr16 ) { DEF_wr16; ADDW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,EA);}
+OP( 0x02, i_add_r8b ) { DEF_r8b; ADDB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); }
+OP( 0x03, i_add_r16w ) { DEF_r16w; ADDW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,EA); }
+OP( 0x04, i_add_ald8 ) { DEF_ald8; ADDB; Breg(AL)=dst; CLKS(4,4,2); }
+OP( 0x05, i_add_axd16) { DEF_axd16; ADDW; Wreg(AW)=dst; CLKS(4,4,2); }
+OP( 0x06, i_push_es ) { PUSH(Sreg(DS1)); CLKS(12,8,3); }
+OP( 0x07, i_pop_es ) { POP(Sreg(DS1)); CLKS(12,8,5); }
+
+OP( 0x08, i_or_br8 ) { DEF_br8; ORB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); }
+OP( 0x09, i_or_wr16 ) { DEF_wr16; ORW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,EA);}
+OP( 0x0a, i_or_r8b ) { DEF_r8b; ORB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); }
+OP( 0x0b, i_or_r16w ) { DEF_r16w; ORW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,EA); }
+OP( 0x0c, i_or_ald8 ) { DEF_ald8; ORB; Breg(AL)=dst; CLKS(4,4,2); }
+OP( 0x0d, i_or_axd16 ) { DEF_axd16; ORW; Wreg(AW)=dst; CLKS(4,4,2); }
+OP( 0x0e, i_push_cs ) { PUSH(Sreg(PS)); CLKS(12,8,3); }
+OP( 0x0f, i_pre_nec ) { UINT32 ModRM, tmp, tmp2;
+ switch (FETCH()) {
+ case 0x10 : BITOP_BYTE; CLKS(3,3,4); tmp2 = Breg(CL) & 0x7; nec_state->ZeroVal = (tmp & (1<<tmp2)) ? 1 : 0; nec_state->CarryVal=nec_state->OverVal=0; break; /* Test */
+ case 0x11 : BITOP_WORD; CLKS(3,3,4); tmp2 = Breg(CL) & 0xf; nec_state->ZeroVal = (tmp & (1<<tmp2)) ? 1 : 0; nec_state->CarryVal=nec_state->OverVal=0; break; /* Test */
+ case 0x12 : BITOP_BYTE; CLKS(5,5,4); tmp2 = Breg(CL) & 0x7; tmp &= ~(1<<tmp2); PutbackRMByte(ModRM,tmp); break; /* Clr */
+ case 0x13 : BITOP_WORD; CLKS(5,5,4); tmp2 = Breg(CL) & 0xf; tmp &= ~(1<<tmp2); PutbackRMWord(ModRM,tmp); break; /* Clr */
+ case 0x14 : BITOP_BYTE; CLKS(4,4,4); tmp2 = Breg(CL) & 0x7; tmp |= (1<<tmp2); PutbackRMByte(ModRM,tmp); break; /* Set */
+ case 0x15 : BITOP_WORD; CLKS(4,4,4); tmp2 = Breg(CL) & 0xf; tmp |= (1<<tmp2); PutbackRMWord(ModRM,tmp); break; /* Set */
+ case 0x16 : BITOP_BYTE; CLKS(4,4,4); tmp2 = Breg(CL) & 0x7; BIT_NOT; PutbackRMByte(ModRM,tmp); break; /* Not */
+ case 0x17 : BITOP_WORD; CLKS(4,4,4); tmp2 = Breg(CL) & 0xf; BIT_NOT; PutbackRMWord(ModRM,tmp); break; /* Not */
+
+ case 0x18 : BITOP_BYTE; CLKS(4,4,4); tmp2 = (FETCH()) & 0x7; nec_state->ZeroVal = (tmp & (1<<tmp2)) ? 1 : 0; nec_state->CarryVal=nec_state->OverVal=0; break; /* Test */
+ case 0x19 : BITOP_WORD; CLKS(4,4,4); tmp2 = (FETCH()) & 0xf; nec_state->ZeroVal = (tmp & (1<<tmp2)) ? 1 : 0; nec_state->CarryVal=nec_state->OverVal=0; break; /* Test */
+ case 0x1a : BITOP_BYTE; CLKS(6,6,4); tmp2 = (FETCH()) & 0x7; tmp &= ~(1<<tmp2); PutbackRMByte(ModRM,tmp); break; /* Clr */
+ case 0x1b : BITOP_WORD; CLKS(6,6,4); tmp2 = (FETCH()) & 0xf; tmp &= ~(1<<tmp2); PutbackRMWord(ModRM,tmp); break; /* Clr */
+ case 0x1c : BITOP_BYTE; CLKS(5,5,4); tmp2 = (FETCH()) & 0x7; tmp |= (1<<tmp2); PutbackRMByte(ModRM,tmp); break; /* Set */
+ case 0x1d : BITOP_WORD; CLKS(5,5,4); tmp2 = (FETCH()) & 0xf; tmp |= (1<<tmp2); PutbackRMWord(ModRM,tmp); break; /* Set */
+ case 0x1e : BITOP_BYTE; CLKS(5,5,4); tmp2 = (FETCH()) & 0x7; BIT_NOT; PutbackRMByte(ModRM,tmp); break; /* Not */
+ case 0x1f : BITOP_WORD; CLKS(5,5,4); tmp2 = (FETCH()) & 0xf; BIT_NOT; PutbackRMWord(ModRM,tmp); break; /* Not */
+
+ case 0x20 : ADD4S; CLKS(7,7,2); break;
+ case 0x22 : SUB4S; CLKS(7,7,2); break;
+ case 0x26 : CMP4S; CLKS(7,7,2); break;
+ case 0x28 : ModRM = FETCH(); tmp = GetRMByte(ModRM); tmp <<= 4; tmp |= Breg(AL) & 0xf; Breg(AL) = (Breg(AL) & 0xf0) | ((tmp>>8)&0xf); tmp &= 0xff; PutbackRMByte(ModRM,tmp); CLKM(13,13,9,28,28,15); break;
+ case 0x2a : ModRM = FETCH(); tmp = GetRMByte(ModRM); tmp2 = (Breg(AL) & 0xf)<<4; Breg(AL) = (Breg(AL) & 0xf0) | (tmp&0xf); tmp = tmp2 | (tmp>>4); PutbackRMByte(ModRM,tmp); CLKM(17,17,13,32,32,19); break;
+ case 0x31 : ModRM = FETCH(); ModRM=0; logerror("%06x: Unimplemented bitfield INS\n",PC(nec_state)); break;
+ case 0x33 : ModRM = FETCH(); ModRM=0; logerror("%06x: Unimplemented bitfield EXT\n",PC(nec_state)); break;
+ case 0xe0 : ModRM = FETCH(); ModRM=0; logerror("%06x: V33 unimplemented BRKXA (break to expansion address)\n",PC(nec_state)); break;
+ case 0xf0 : ModRM = FETCH(); ModRM=0; logerror("%06x: V33 unimplemented RETXA (return from expansion address)\n",PC(nec_state)); break;
+ case 0xff : ModRM = FETCH(); ModRM=0; logerror("%06x: unimplemented BRKEM (break to 8080 emulation mode)\n",PC(nec_state)); break;
+ default: logerror("%06x: Unknown V20 instruction\n",PC(nec_state)); break;
+ }
+}
+
+OP( 0x10, i_adc_br8 ) { DEF_br8; src+=CF; ADDB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); }
+OP( 0x11, i_adc_wr16 ) { DEF_wr16; src+=CF; ADDW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,EA);}
+OP( 0x12, i_adc_r8b ) { DEF_r8b; src+=CF; ADDB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); }
+OP( 0x13, i_adc_r16w ) { DEF_r16w; src+=CF; ADDW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,EA); }
+OP( 0x14, i_adc_ald8 ) { DEF_ald8; src+=CF; ADDB; Breg(AL)=dst; CLKS(4,4,2); }
+OP( 0x15, i_adc_axd16) { DEF_axd16; src+=CF; ADDW; Wreg(AW)=dst; CLKS(4,4,2); }
+OP( 0x16, i_push_ss ) { PUSH(Sreg(SS)); CLKS(12,8,3); }
+OP( 0x17, i_pop_ss ) { POP(Sreg(SS)); CLKS(12,8,5); nec_state->no_interrupt=1; }
+
+OP( 0x18, i_sbb_br8 ) { DEF_br8; src+=CF; SUBB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); }
+OP( 0x19, i_sbb_wr16 ) { DEF_wr16; src+=CF; SUBW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,EA);}
+OP( 0x1a, i_sbb_r8b ) { DEF_r8b; src+=CF; SUBB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); }
+OP( 0x1b, i_sbb_r16w ) { DEF_r16w; src+=CF; SUBW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,EA); }
+OP( 0x1c, i_sbb_ald8 ) { DEF_ald8; src+=CF; SUBB; Breg(AL)=dst; CLKS(4,4,2); }
+OP( 0x1d, i_sbb_axd16) { DEF_axd16; src+=CF; SUBW; Wreg(AW)=dst; CLKS(4,4,2); }
+OP( 0x1e, i_push_ds ) { PUSH(Sreg(DS0)); CLKS(12,8,3); }
+OP( 0x1f, i_pop_ds ) { POP(Sreg(DS0)); CLKS(12,8,5); }
+
+OP( 0x20, i_and_br8 ) { DEF_br8; ANDB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); }
+OP( 0x21, i_and_wr16 ) { DEF_wr16; ANDW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,EA);}
+OP( 0x22, i_and_r8b ) { DEF_r8b; ANDB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); }
+OP( 0x23, i_and_r16w ) { DEF_r16w; ANDW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,EA); }
+OP( 0x24, i_and_ald8 ) { DEF_ald8; ANDB; Breg(AL)=dst; CLKS(4,4,2); }
+OP( 0x25, i_and_axd16) { DEF_axd16; ANDW; Wreg(AW)=dst; CLKS(4,4,2); }
+OP( 0x26, i_es ) { nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(DS1)<<4; CLK(2); nec_instruction[fetchop(nec_state)](nec_state); nec_state->seg_prefix=FALSE; }
+OP( 0x27, i_daa ) { ADJ4(6,0x60); CLKS(3,3,2); }
+
+OP( 0x28, i_sub_br8 ) { DEF_br8; SUBB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); }
+OP( 0x29, i_sub_wr16 ) { DEF_wr16; SUBW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,EA);}
+OP( 0x2a, i_sub_r8b ) { DEF_r8b; SUBB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); }
+OP( 0x2b, i_sub_r16w ) { DEF_r16w; SUBW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,EA); }
+OP( 0x2c, i_sub_ald8 ) { DEF_ald8; SUBB; Breg(AL)=dst; CLKS(4,4,2); }
+OP( 0x2d, i_sub_axd16) { DEF_axd16; SUBW; Wreg(AW)=dst; CLKS(4,4,2); }
+OP( 0x2e, i_cs ) { nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(PS)<<4; CLK(2); nec_instruction[fetchop(nec_state)](nec_state); nec_state->seg_prefix=FALSE; }
+OP( 0x2f, i_das ) { ADJ4(-6,-0x60); CLKS(3,3,2); }
+
+OP( 0x30, i_xor_br8 ) { DEF_br8; XORB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); }
+OP( 0x31, i_xor_wr16 ) { DEF_wr16; XORW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,EA);}
+OP( 0x32, i_xor_r8b ) { DEF_r8b; XORB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); }
+OP( 0x33, i_xor_r16w ) { DEF_r16w; XORW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,EA); }
+OP( 0x34, i_xor_ald8 ) { DEF_ald8; XORB; Breg(AL)=dst; CLKS(4,4,2); }
+OP( 0x35, i_xor_axd16) { DEF_axd16; XORW; Wreg(AW)=dst; CLKS(4,4,2); }
+OP( 0x36, i_ss ) { nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(SS)<<4; CLK(2); nec_instruction[fetchop(nec_state)](nec_state); nec_state->seg_prefix=FALSE; }
+OP( 0x37, i_aaa ) { ADJB(6, (Breg(AL) > 0xf9) ? 2 : 1); CLKS(7,7,4); }
+
+OP( 0x38, i_cmp_br8 ) { DEF_br8; SUBB; CLKM(2,2,2,11,11,6); }
+OP( 0x39, i_cmp_wr16 ) { DEF_wr16; SUBW; CLKR(15,15,8,15,11,6,2,EA);}
+OP( 0x3a, i_cmp_r8b ) { DEF_r8b; SUBB; CLKM(2,2,2,11,11,6); }
+OP( 0x3b, i_cmp_r16w ) { DEF_r16w; SUBW; CLKR(15,15,8,15,11,6,2,EA); }
+OP( 0x3c, i_cmp_ald8 ) { DEF_ald8; SUBB; CLKS(4,4,2); }
+OP( 0x3d, i_cmp_axd16) { DEF_axd16; SUBW; CLKS(4,4,2); }
+OP( 0x3e, i_ds ) { nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(DS0)<<4; CLK(2); nec_instruction[fetchop(nec_state)](nec_state); nec_state->seg_prefix=FALSE; }
+OP( 0x3f, i_aas ) { ADJB(-6, (Breg(AL) < 6) ? -2 : -1); CLKS(7,7,4); }
+
+OP( 0x40, i_inc_ax ) { IncWordReg(AW); CLK(2); }
+OP( 0x41, i_inc_cx ) { IncWordReg(CW); CLK(2); }
+OP( 0x42, i_inc_dx ) { IncWordReg(DW); CLK(2); }
+OP( 0x43, i_inc_bx ) { IncWordReg(BW); CLK(2); }
+OP( 0x44, i_inc_sp ) { IncWordReg(SP); CLK(2); }
+OP( 0x45, i_inc_bp ) { IncWordReg(BP); CLK(2); }
+OP( 0x46, i_inc_si ) { IncWordReg(IX); CLK(2); }
+OP( 0x47, i_inc_di ) { IncWordReg(IY); CLK(2); }
+
+OP( 0x48, i_dec_ax ) { DecWordReg(AW); CLK(2); }
+OP( 0x49, i_dec_cx ) { DecWordReg(CW); CLK(2); }
+OP( 0x4a, i_dec_dx ) { DecWordReg(DW); CLK(2); }
+OP( 0x4b, i_dec_bx ) { DecWordReg(BW); CLK(2); }
+OP( 0x4c, i_dec_sp ) { DecWordReg(SP); CLK(2); }
+OP( 0x4d, i_dec_bp ) { DecWordReg(BP); CLK(2); }
+OP( 0x4e, i_dec_si ) { DecWordReg(IX); CLK(2); }
+OP( 0x4f, i_dec_di ) { DecWordReg(IY); CLK(2); }
+
+OP( 0x50, i_push_ax ) { PUSH(Wreg(AW)); CLKS(12,8,3); }
+OP( 0x51, i_push_cx ) { PUSH(Wreg(CW)); CLKS(12,8,3); }
+OP( 0x52, i_push_dx ) { PUSH(Wreg(DW)); CLKS(12,8,3); }
+OP( 0x53, i_push_bx ) { PUSH(Wreg(BW)); CLKS(12,8,3); }
+OP( 0x54, i_push_sp ) { PUSH(Wreg(SP)); CLKS(12,8,3); }
+OP( 0x55, i_push_bp ) { PUSH(Wreg(BP)); CLKS(12,8,3); }
+OP( 0x56, i_push_si ) { PUSH(Wreg(IX)); CLKS(12,8,3); }
+OP( 0x57, i_push_di ) { PUSH(Wreg(IY)); CLKS(12,8,3); }
+
+OP( 0x58, i_pop_ax ) { POP(Wreg(AW)); CLKS(12,8,5); }
+OP( 0x59, i_pop_cx ) { POP(Wreg(CW)); CLKS(12,8,5); }
+OP( 0x5a, i_pop_dx ) { POP(Wreg(DW)); CLKS(12,8,5); }
+OP( 0x5b, i_pop_bx ) { POP(Wreg(BW)); CLKS(12,8,5); }
+OP( 0x5c, i_pop_sp ) { POP(Wreg(SP)); CLKS(12,8,5); }
+OP( 0x5d, i_pop_bp ) { POP(Wreg(BP)); CLKS(12,8,5); }
+OP( 0x5e, i_pop_si ) { POP(Wreg(IX)); CLKS(12,8,5); }
+OP( 0x5f, i_pop_di ) { POP(Wreg(IY)); CLKS(12,8,5); }
+
+OP( 0x60, i_pusha ) {
+ unsigned tmp=Wreg(SP);
+ PUSH(Wreg(AW));
+ PUSH(Wreg(CW));
+ PUSH(Wreg(DW));
+ PUSH(Wreg(BW));
+ PUSH(tmp);
+ PUSH(Wreg(BP));
+ PUSH(Wreg(IX));
+ PUSH(Wreg(IY));
+ CLKS(67,35,20);
+}
+static unsigned nec_popa_tmp;
+OP( 0x61, i_popa ) {
+ POP(Wreg(IY));
+ POP(Wreg(IX));
+ POP(Wreg(BP));
+ POP(nec_popa_tmp);
+ POP(Wreg(BW));
+ POP(Wreg(DW));
+ POP(Wreg(CW));
+ POP(Wreg(AW));
+ CLKS(75,43,22);
+}
+OP( 0x62, i_chkind ) {
+ UINT32 low,high,tmp;
+ GetModRM;
+ low = GetRMWord(ModRM);
+ high= GetnextRMWord;
+ tmp= RegWord(ModRM);
+ if (tmp<low || tmp>high) {
+ nec_interrupt(nec_state, NEC_CHKIND_VECTOR, BRK);
+ }
+ nec_state->icount-=20;
+ logerror("%06x: bound %04x high %04x low %04x tmp\n",PC(nec_state),high,low,tmp);
+}
+OP( 0x64, i_repnc ) { UINT32 next = fetchop(nec_state); UINT16 c = Wreg(CW);
+ switch(next) { /* Segments */
+ case 0x26: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(DS1)<<4; next = fetchop(nec_state); CLK(2); break;
+ case 0x2e: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(PS)<<4; next = fetchop(nec_state); CLK(2); break;
+ case 0x36: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(SS)<<4; next = fetchop(nec_state); CLK(2); break;
+ case 0x3e: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(DS0)<<4; next = fetchop(nec_state); CLK(2); break;
+ }
+
+ switch(next) {
+ case 0x6c: CLK(2); if (c) do { i_insb(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break;
+ case 0x6d: CLK(2); if (c) do { i_insw(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break;
+ case 0x6e: CLK(2); if (c) do { i_outsb(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break;
+ case 0x6f: CLK(2); if (c) do { i_outsw(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break;
+ case 0xa4: CLK(2); if (c) do { i_movsb(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break;
+ case 0xa5: CLK(2); if (c) do { i_movsw(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break;
+ case 0xa6: CLK(2); if (c) do { i_cmpsb(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break;
+ case 0xa7: CLK(2); if (c) do { i_cmpsw(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break;
+ case 0xaa: CLK(2); if (c) do { i_stosb(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break;
+ case 0xab: CLK(2); if (c) do { i_stosw(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break;
+ case 0xac: CLK(2); if (c) do { i_lodsb(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break;
+ case 0xad: CLK(2); if (c) do { i_lodsw(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break;
+ case 0xae: CLK(2); if (c) do { i_scasb(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break;
+ case 0xaf: CLK(2); if (c) do { i_scasw(nec_state); c--; } while (c>0 && !CF); Wreg(CW)=c; break;
+ default: logerror("%06x: REPNC invalid\n",PC(nec_state)); nec_instruction[next](nec_state);
+ }
+ nec_state->seg_prefix=FALSE;
+}
+
+OP( 0x65, i_repc ) { UINT32 next = fetchop(nec_state); UINT16 c = Wreg(CW);
+ switch(next) { /* Segments */
+ case 0x26: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(DS1)<<4; next = fetchop(nec_state); CLK(2); break;
+ case 0x2e: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(PS)<<4; next = fetchop(nec_state); CLK(2); break;
+ case 0x36: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(SS)<<4; next = fetchop(nec_state); CLK(2); break;
+ case 0x3e: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(DS0)<<4; next = fetchop(nec_state); CLK(2); break;
+ }
+
+ switch(next) {
+ case 0x6c: CLK(2); if (c) do { i_insb(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break;
+ case 0x6d: CLK(2); if (c) do { i_insw(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break;
+ case 0x6e: CLK(2); if (c) do { i_outsb(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break;
+ case 0x6f: CLK(2); if (c) do { i_outsw(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break;
+ case 0xa4: CLK(2); if (c) do { i_movsb(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break;
+ case 0xa5: CLK(2); if (c) do { i_movsw(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break;
+ case 0xa6: CLK(2); if (c) do { i_cmpsb(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break;
+ case 0xa7: CLK(2); if (c) do { i_cmpsw(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break;
+ case 0xaa: CLK(2); if (c) do { i_stosb(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break;
+ case 0xab: CLK(2); if (c) do { i_stosw(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break;
+ case 0xac: CLK(2); if (c) do { i_lodsb(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break;
+ case 0xad: CLK(2); if (c) do { i_lodsw(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break;
+ case 0xae: CLK(2); if (c) do { i_scasb(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break;
+ case 0xaf: CLK(2); if (c) do { i_scasw(nec_state); c--; } while (c>0 && CF); Wreg(CW)=c; break;
+ default: logerror("%06x: REPC invalid\n",PC(nec_state)); nec_instruction[next](nec_state);
+ }
+ nec_state->seg_prefix=FALSE;
+}
+
+OP( 0x68, i_push_d16 ) { UINT32 tmp; tmp = FETCHWORD(); PUSH(tmp); CLKW(12,12,5,12,8,5,Wreg(SP)); }
+OP( 0x69, i_imul_d16 ) { UINT32 tmp; DEF_r16w; tmp = FETCHWORD(); dst = (INT32)((INT16)src)*(INT32)((INT16)tmp); nec_state->CarryVal = nec_state->OverVal = (((INT32)dst) >> 15 != 0) && (((INT32)dst) >> 15 != -1); RegWord(ModRM)=(WORD)dst; nec_state->icount-=(ModRM >=0xc0 )?38:47;}
+OP( 0x6a, i_push_d8 ) { UINT32 tmp = (WORD)((INT16)((INT8)FETCH())); PUSH(tmp); CLKW(11,11,5,11,7,3,Wreg(SP)); }
+OP( 0x6b, i_imul_d8 ) { UINT32 src2; DEF_r16w; src2= (WORD)((INT16)((INT8)FETCH())); dst = (INT32)((INT16)src)*(INT32)((INT16)src2); nec_state->CarryVal = nec_state->OverVal = (((INT32)dst) >> 15 != 0) && (((INT32)dst) >> 15 != -1); RegWord(ModRM)=(WORD)dst; nec_state->icount-=(ModRM >=0xc0 )?31:39; }
+OP( 0x6c, i_insb ) { PutMemB(DS1,Wreg(IY),read_port_byte(Wreg(DW))); Wreg(IY)+= -2 * nec_state->DF + 1; CLK(8); }
+OP( 0x6d, i_insw ) { PutMemW(DS1,Wreg(IY),read_port_word(Wreg(DW))); Wreg(IY)+= -4 * nec_state->DF + 2; CLKS(18,10,8); }
+OP( 0x6e, i_outsb ) { write_port_byte(Wreg(DW),GetMemB(DS0,Wreg(IX))); Wreg(IX)+= -2 * nec_state->DF + 1; CLK(8); }
+OP( 0x6f, i_outsw ) { write_port_word(Wreg(DW),GetMemW(DS0,Wreg(IX))); Wreg(IX)+= -4 * nec_state->DF + 2; CLKS(18,10,8); }
+
+OP( 0x70, i_jo ) { JMP( OF); CLKS(4,4,3); }
+OP( 0x71, i_jno ) { JMP(!OF); CLKS(4,4,3); }
+OP( 0x72, i_jc ) { JMP( CF); CLKS(4,4,3); }
+OP( 0x73, i_jnc ) { JMP(!CF); CLKS(4,4,3); }
+OP( 0x74, i_jz ) { JMP( ZF); CLKS(4,4,3); }
+OP( 0x75, i_jnz ) { JMP(!ZF); CLKS(4,4,3); }
+OP( 0x76, i_jce ) { JMP(CF || ZF); CLKS(4,4,3); }
+OP( 0x77, i_jnce ) { JMP(!(CF || ZF)); CLKS(4,4,3); }
+OP( 0x78, i_js ) { JMP( SF); CLKS(4,4,3); }
+OP( 0x79, i_jns ) { JMP(!SF); CLKS(4,4,3); }
+OP( 0x7a, i_jp ) { JMP( PF); CLKS(4,4,3); }
+OP( 0x7b, i_jnp ) { JMP(!PF); CLKS(4,4,3); }
+OP( 0x7c, i_jl ) { JMP((SF!=OF)&&(!ZF)); CLKS(4,4,3); }
+OP( 0x7d, i_jnl ) { JMP((ZF)||(SF==OF)); CLKS(4,4,3); }
+OP( 0x7e, i_jle ) { JMP((ZF)||(SF!=OF)); CLKS(4,4,3); }
+OP( 0x7f, i_jnle ) { JMP((SF==OF)&&(!ZF)); CLKS(4,4,3); }
+
+OP( 0x80, i_80pre ) { UINT32 dst, src; GetModRM; dst = GetRMByte(ModRM); src = FETCH();
+ if (ModRM >=0xc0 ) CLKS(4,4,2) else if ((ModRM & 0x38)==0x38) CLKS(13,13,6) else CLKS(18,18,7)
+ switch (ModRM & 0x38) {
+ case 0x00: ADDB; PutbackRMByte(ModRM,dst); break;
+ case 0x08: ORB; PutbackRMByte(ModRM,dst); break;
+ case 0x10: src+=CF; ADDB; PutbackRMByte(ModRM,dst); break;
+ case 0x18: src+=CF; SUBB; PutbackRMByte(ModRM,dst); break;
+ case 0x20: ANDB; PutbackRMByte(ModRM,dst); break;
+ case 0x28: SUBB; PutbackRMByte(ModRM,dst); break;
+ case 0x30: XORB; PutbackRMByte(ModRM,dst); break;
+ case 0x38: SUBB; break; /* CMP */
+ }
+}
+
+OP( 0x81, i_81pre ) { UINT32 dst, src; GetModRM; dst = GetRMWord(ModRM); src = FETCH(); src+= (FETCH() << 8);
+ if (ModRM >=0xc0 ) CLKS(4,4,2) else if ((ModRM & 0x38)==0x38) CLKW(17,17,8,17,13,6,EA) else CLKW(26,26,11,26,18,7,EA)
+ switch (ModRM & 0x38) {
+ case 0x00: ADDW; PutbackRMWord(ModRM,dst); break;
+ case 0x08: ORW; PutbackRMWord(ModRM,dst); break;
+ case 0x10: src+=CF; ADDW; PutbackRMWord(ModRM,dst); break;
+ case 0x18: src+=CF; SUBW; PutbackRMWord(ModRM,dst); break;
+ case 0x20: ANDW; PutbackRMWord(ModRM,dst); break;
+ case 0x28: SUBW; PutbackRMWord(ModRM,dst); break;
+ case 0x30: XORW; PutbackRMWord(ModRM,dst); break;
+ case 0x38: SUBW; break; /* CMP */
+ }
+}
+
+OP( 0x82, i_82pre ) { UINT32 dst, src; GetModRM; dst = GetRMByte(ModRM); src = (BYTE)((INT8)FETCH());
+ if (ModRM >=0xc0 ) CLKS(4,4,2) else if ((ModRM & 0x38)==0x38) CLKS(13,13,6) else CLKS(18,18,7)
+ switch (ModRM & 0x38) {
+ case 0x00: ADDB; PutbackRMByte(ModRM,dst); break;
+ case 0x08: ORB; PutbackRMByte(ModRM,dst); break;
+ case 0x10: src+=CF; ADDB; PutbackRMByte(ModRM,dst); break;
+ case 0x18: src+=CF; SUBB; PutbackRMByte(ModRM,dst); break;
+ case 0x20: ANDB; PutbackRMByte(ModRM,dst); break;
+ case 0x28: SUBB; PutbackRMByte(ModRM,dst); break;
+ case 0x30: XORB; PutbackRMByte(ModRM,dst); break;
+ case 0x38: SUBB; break; /* CMP */
+ }
+}
+
+OP( 0x83, i_83pre ) { UINT32 dst, src; GetModRM; dst = GetRMWord(ModRM); src = (WORD)((INT16)((INT8)FETCH()));
+ if (ModRM >=0xc0 ) CLKS(4,4,2) else if ((ModRM & 0x38)==0x38) CLKW(17,17,8,17,13,6,EA) else CLKW(26,26,11,26,18,7,EA)
+ switch (ModRM & 0x38) {
+ case 0x00: ADDW; PutbackRMWord(ModRM,dst); break;
+ case 0x08: ORW; PutbackRMWord(ModRM,dst); break;
+ case 0x10: src+=CF; ADDW; PutbackRMWord(ModRM,dst); break;
+ case 0x18: src+=CF; SUBW; PutbackRMWord(ModRM,dst); break;
+ case 0x20: ANDW; PutbackRMWord(ModRM,dst); break;
+ case 0x28: SUBW; PutbackRMWord(ModRM,dst); break;
+ case 0x30: XORW; PutbackRMWord(ModRM,dst); break;
+ case 0x38: SUBW; break; /* CMP */
+ }
+}
+
+OP( 0x84, i_test_br8 ) { DEF_br8; ANDB; CLKM(2,2,2,10,10,6); }
+OP( 0x85, i_test_wr16 ) { DEF_wr16; ANDW; CLKR(14,14,8,14,10,6,2,EA); }
+OP( 0x86, i_xchg_br8 ) { DEF_br8; RegByte(ModRM)=dst; PutbackRMByte(ModRM,src); CLKM(3,3,3,16,18,8); }
+OP( 0x87, i_xchg_wr16 ) { DEF_wr16; RegWord(ModRM)=dst; PutbackRMWord(ModRM,src); CLKR(24,24,12,24,16,8,3,EA); }
+
+OP( 0x88, i_mov_br8 ) { UINT8 src; GetModRM; src = RegByte(ModRM); PutRMByte(ModRM,src); CLKM(2,2,2,9,9,3); }
+OP( 0x89, i_mov_wr16 ) { UINT16 src; GetModRM; src = RegWord(ModRM); PutRMWord(ModRM,src); CLKR(13,13,5,13,9,3,2,EA); }
+OP( 0x8a, i_mov_r8b ) { UINT8 src; GetModRM; src = GetRMByte(ModRM); RegByte(ModRM)=src; CLKM(2,2,2,11,11,5); }
+OP( 0x8b, i_mov_r16w ) { UINT16 src; GetModRM; src = GetRMWord(ModRM); RegWord(ModRM)=src; CLKR(15,15,7,15,11,5,2,EA); }
+OP( 0x8c, i_mov_wsreg ) { GetModRM;
+ switch (ModRM & 0x38) {
+ case 0x00: PutRMWord(ModRM,Sreg(DS1)); CLKR(14,14,5,14,10,3,2,EA); break;
+ case 0x08: PutRMWord(ModRM,Sreg(PS)); CLKR(14,14,5,14,10,3,2,EA); break;
+ case 0x10: PutRMWord(ModRM,Sreg(SS)); CLKR(14,14,5,14,10,3,2,EA); break;
+ case 0x18: PutRMWord(ModRM,Sreg(DS0)); CLKR(14,14,5,14,10,3,2,EA); break;
+ default: logerror("%06x: MOV Sreg - Invalid register\n",PC(nec_state));
+ }
+}
+OP( 0x8d, i_lea ) { UINT16 ModRM = FETCH(); (void)(*GetEA[ModRM])(nec_state); RegWord(ModRM)=EO; CLKS(4,4,2); }
+OP( 0x8e, i_mov_sregw ) { UINT16 src; GetModRM; src = GetRMWord(ModRM); CLKR(15,15,7,15,11,5,2,EA);
+ switch (ModRM & 0x38) {
+ case 0x00: Sreg(DS1) = src; break; /* mov es,ew */
+ case 0x08: Sreg(PS) = src; break; /* mov cs,ew */
+ case 0x10: Sreg(SS) = src; break; /* mov ss,ew */
+ case 0x18: Sreg(DS0) = src; break; /* mov ds,ew */
+ default: logerror("%06x: MOV Sreg - Invalid register\n",PC(nec_state));
+ }
+ nec_state->no_interrupt=1;
+}
+OP( 0x8f, i_popw ) { UINT16 tmp; GetModRM; POP(tmp); PutRMWord(ModRM,tmp); nec_state->icount-=21; }
+OP( 0x90, i_nop ) { CLK(3); /* { if (nec_state->MF == 0) printf("90 -> %06x: \n",PC(nec_state)); } */ }
+OP( 0x91, i_xchg_axcx ) { XchgAWReg(CW); CLK(3); }
+OP( 0x92, i_xchg_axdx ) { XchgAWReg(DW); CLK(3); }
+OP( 0x93, i_xchg_axbx ) { XchgAWReg(BW); CLK(3); }
+OP( 0x94, i_xchg_axsp ) { XchgAWReg(SP); CLK(3); }
+OP( 0x95, i_xchg_axbp ) { XchgAWReg(BP); CLK(3); }
+OP( 0x96, i_xchg_axsi ) { XchgAWReg(IX); CLK(3); }
+OP( 0x97, i_xchg_axdi ) { XchgAWReg(IY); CLK(3); }
+
+OP( 0x98, i_cbw ) { Breg(AH) = (Breg(AL) & 0x80) ? 0xff : 0; CLK(2); }
+OP( 0x99, i_cwd ) { Wreg(DW) = (Breg(AH) & 0x80) ? 0xffff : 0; CLK(4); }
+OP( 0x9a, i_call_far ) { UINT32 tmp, tmp2; tmp = FETCHWORD(); tmp2 = FETCHWORD(); PUSH(Sreg(PS)); PUSH(nec_state->ip); nec_state->ip = (WORD)tmp; Sreg(PS) = (WORD)tmp2; CHANGE_PC; CLKW(29,29,13,29,21,9,Wreg(SP)); }
+OP( 0x9b, i_wait ) { if (!nec_state->poll_state) nec_state->ip--; CLK(5); }
+OP( 0x9c, i_pushf ) { UINT16 tmp = CompressFlags(); PUSH( tmp ); CLKS(12,8,3); }
+OP( 0x9d, i_popf ) { UINT32 tmp; POP(tmp); ExpandFlags(tmp); CLKS(12,8,5); if (nec_state->TF) nec_trap(nec_state); }
+OP( 0x9e, i_sahf ) { UINT32 tmp = (CompressFlags() & 0xff00) | (Breg(AH) & 0xd5); ExpandFlags(tmp); CLKS(3,3,2); }
+OP( 0x9f, i_lahf ) { Breg(AH) = CompressFlags() & 0xff; CLKS(3,3,2); }
+
+OP( 0xa0, i_mov_aldisp ) { UINT32 addr; addr = FETCHWORD(); Breg(AL) = GetMemB(DS0, addr); CLKS(10,10,5); }
+OP( 0xa1, i_mov_axdisp ) { UINT32 addr; addr = FETCHWORD(); Wreg(AW) = GetMemW(DS0, addr); CLKW(14,14,7,14,10,5,addr); }
+OP( 0xa2, i_mov_dispal ) { UINT32 addr; addr = FETCHWORD(); PutMemB(DS0, addr, Breg(AL)); CLKS(9,9,3); }
+OP( 0xa3, i_mov_dispax ) { UINT32 addr; addr = FETCHWORD(); PutMemW(DS0, addr, Wreg(AW)); CLKW(13,13,5,13,9,3,addr); }
+OP( 0xa4, i_movsb ) { UINT32 tmp = GetMemB(DS0,Wreg(IX)); PutMemB(DS1,Wreg(IY), tmp); Wreg(IY) += -2 * nec_state->DF + 1; Wreg(IX) += -2 * nec_state->DF + 1; CLKS(8,8,6); }
+OP( 0xa5, i_movsw ) { UINT32 tmp = GetMemW(DS0,Wreg(IX)); PutMemW(DS1,Wreg(IY), tmp); Wreg(IY) += -4 * nec_state->DF + 2; Wreg(IX) += -4 * nec_state->DF + 2; CLKS(16,16,10); }
+OP( 0xa6, i_cmpsb ) { UINT32 src = GetMemB(DS1, Wreg(IY)); UINT32 dst = GetMemB(DS0, Wreg(IX)); SUBB; Wreg(IY) += -2 * nec_state->DF + 1; Wreg(IX) += -2 * nec_state->DF + 1; CLKS(14,14,14); }
+OP( 0xa7, i_cmpsw ) { UINT32 src = GetMemW(DS1, Wreg(IY)); UINT32 dst = GetMemW(DS0, Wreg(IX)); SUBW; Wreg(IY) += -4 * nec_state->DF + 2; Wreg(IX) += -4 * nec_state->DF + 2; CLKS(14,14,14); }
+
+OP( 0xa8, i_test_ald8 ) { DEF_ald8; ANDB; CLKS(4,4,2); }
+OP( 0xa9, i_test_axd16 ) { DEF_axd16; ANDW; CLKS(4,4,2); }
+OP( 0xaa, i_stosb ) { PutMemB(DS1,Wreg(IY),Breg(AL)); Wreg(IY) += -2 * nec_state->DF + 1; CLKS(4,4,3); }
+OP( 0xab, i_stosw ) { PutMemW(DS1,Wreg(IY),Wreg(AW)); Wreg(IY) += -4 * nec_state->DF + 2; CLKW(8,8,5,8,4,3,Wreg(IY)); }
+OP( 0xac, i_lodsb ) { Breg(AL) = GetMemB(DS0,Wreg(IX)); Wreg(IX) += -2 * nec_state->DF + 1; CLKS(4,4,3); }
+OP( 0xad, i_lodsw ) { Wreg(AW) = GetMemW(DS0,Wreg(IX)); Wreg(IX) += -4 * nec_state->DF + 2; CLKW(8,8,5,8,4,3,Wreg(IX)); }
+OP( 0xae, i_scasb ) { UINT32 src = GetMemB(DS1, Wreg(IY)); UINT32 dst = Breg(AL); SUBB; Wreg(IY) += -2 * nec_state->DF + 1; CLKS(4,4,3); }
+OP( 0xaf, i_scasw ) { UINT32 src = GetMemW(DS1, Wreg(IY)); UINT32 dst = Wreg(AW); SUBW; Wreg(IY) += -4 * nec_state->DF + 2; CLKW(8,8,5,8,4,3,Wreg(IY)); }
+
+OP( 0xb0, i_mov_ald8 ) { Breg(AL) = FETCH(); CLKS(4,4,2); }
+OP( 0xb1, i_mov_cld8 ) { Breg(CL) = FETCH(); CLKS(4,4,2); }
+OP( 0xb2, i_mov_dld8 ) { Breg(DL) = FETCH(); CLKS(4,4,2); }
+OP( 0xb3, i_mov_bld8 ) { Breg(BL) = FETCH(); CLKS(4,4,2); }
+OP( 0xb4, i_mov_ahd8 ) { Breg(AH) = FETCH(); CLKS(4,4,2); }
+OP( 0xb5, i_mov_chd8 ) { Breg(CH) = FETCH(); CLKS(4,4,2); }
+OP( 0xb6, i_mov_dhd8 ) { Breg(DH) = FETCH(); CLKS(4,4,2); }
+OP( 0xb7, i_mov_bhd8 ) { Breg(BH) = FETCH(); CLKS(4,4,2); }
+
+OP( 0xb8, i_mov_axd16 ) { Breg(AL) = FETCH(); Breg(AH) = FETCH(); CLKS(4,4,2); }
+OP( 0xb9, i_mov_cxd16 ) { Breg(CL) = FETCH(); Breg(CH) = FETCH(); CLKS(4,4,2); }
+OP( 0xba, i_mov_dxd16 ) { Breg(DL) = FETCH(); Breg(DH) = FETCH(); CLKS(4,4,2); }
+OP( 0xbb, i_mov_bxd16 ) { Breg(BL) = FETCH(); Breg(BH) = FETCH(); CLKS(4,4,2); }
+OP( 0xbc, i_mov_spd16 ) { Wreg(SP) = FETCHWORD(); CLKS(4,4,2); }
+OP( 0xbd, i_mov_bpd16 ) { Wreg(BP) = FETCHWORD(); CLKS(4,4,2); }
+OP( 0xbe, i_mov_sid16 ) { Wreg(IX) = FETCHWORD(); CLKS(4,4,2); }
+OP( 0xbf, i_mov_did16 ) { Wreg(IY) = FETCHWORD(); CLKS(4,4,2); }
+
+OP( 0xc0, i_rotshft_bd8 ) {
+ UINT32 src, dst; UINT8 c;
+ GetModRM; src = (unsigned)GetRMByte(ModRM); dst=src;
+ c=FETCH();
+ CLKM(7,7,2,19,19,6);
+ if (c) switch (ModRM & 0x38) {
+ case 0x00: do { ROL_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break;
+ case 0x08: do { ROR_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break;
+ case 0x10: do { ROLC_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break;
+ case 0x18: do { RORC_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break;
+ case 0x20: SHL_BYTE(c); break;
+ case 0x28: SHR_BYTE(c); break;
+ case 0x30: logerror("%06x: Undefined opcode 0xc0 0x30 (SHLA)\n",PC(nec_state)); break;
+ case 0x38: SHRA_BYTE(c); break;
+ }
+}
+
+OP( 0xc1, i_rotshft_wd8 ) {
+ UINT32 src, dst; UINT8 c;
+ GetModRM; src = (unsigned)GetRMWord(ModRM); dst=src;
+ c=FETCH();
+ CLKM(7,7,2,27,19,6);
+ if (c) switch (ModRM & 0x38) {
+ case 0x00: do { ROL_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break;
+ case 0x08: do { ROR_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break;
+ case 0x10: do { ROLC_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break;
+ case 0x18: do { RORC_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break;
+ case 0x20: SHL_WORD(c); break;
+ case 0x28: SHR_WORD(c); break;
+ case 0x30: logerror("%06x: Undefined opcode 0xc1 0x30 (SHLA)\n",PC(nec_state)); break;
+ case 0x38: SHRA_WORD(c); break;
+ }
+}
+
+OP( 0xc2, i_ret_d16 ) { UINT32 count = FETCH(); count += FETCH() << 8; POP(nec_state->ip); Wreg(SP)+=count; CHANGE_PC; CLKS(24,24,10); }
+OP( 0xc3, i_ret ) { POP(nec_state->ip); CHANGE_PC; CLKS(19,19,10); }
+OP( 0xc4, i_les_dw ) { GetModRM; WORD tmp = GetRMWord(ModRM); RegWord(ModRM)=tmp; Sreg(DS1) = GetnextRMWord; CLKW(26,26,14,26,18,10,EA); }
+OP( 0xc5, i_lds_dw ) { GetModRM; WORD tmp = GetRMWord(ModRM); RegWord(ModRM)=tmp; Sreg(DS0) = GetnextRMWord; CLKW(26,26,14,26,18,10,EA); }
+OP( 0xc6, i_mov_bd8 ) { GetModRM; PutImmRMByte(ModRM); nec_state->icount-=(ModRM >=0xc0 )?4:11; }
+OP( 0xc7, i_mov_wd16 ) { GetModRM; PutImmRMWord(ModRM); nec_state->icount-=(ModRM >=0xc0 )?4:15; }
+
+OP( 0xc8, i_enter ) {
+ UINT32 nb = FETCH();
+ UINT32 i,level;
+
+ nec_state->icount-=23;
+ nb += FETCH() << 8;
+ level = FETCH();
+ PUSH(Wreg(BP));
+ Wreg(BP)=Wreg(SP);
+ Wreg(SP) -= nb;
+ for (i=1;i<level;i++) {
+ PUSH(GetMemW(SS,Wreg(BP)-i*2));
+ nec_state->icount-=16;
+ }
+ if (level) PUSH(Wreg(BP));
+}
+OP( 0xc9, i_leave ) {
+ Wreg(SP)=Wreg(BP);
+ POP(Wreg(BP));
+ nec_state->icount-=8;
+}
+OP( 0xca, i_retf_d16 ) { UINT32 count = FETCH(); count += FETCH() << 8; POP(nec_state->ip); POP(Sreg(PS)); Wreg(SP)+=count; CHANGE_PC; CLKS(32,32,16); }
+OP( 0xcb, i_retf ) { POP(nec_state->ip); POP(Sreg(PS)); CHANGE_PC; CLKS(29,29,16); }
+OP( 0xcc, i_int3 ) { nec_interrupt(nec_state, 3, BRK); CLKS(50,50,24); }
+OP( 0xcd, i_int ) { nec_interrupt(nec_state, FETCH(), BRK); CLKS(50,50,24); }
+OP( 0xce, i_into ) { if (OF) { nec_interrupt(nec_state, NEC_BRKV_VECTOR, BRK); CLKS(52,52,26); } else CLK(3); }
+OP( 0xcf, i_iret ) { POP(nec_state->ip); POP(Sreg(PS)); i_popf(nec_state); CHANGE_PC; CLKS(39,39,19); }
+
+OP( 0xd0, i_rotshft_b ) {
+ UINT32 src, dst; GetModRM; src = (UINT32)GetRMByte(ModRM); dst=src;
+ CLKM(6,6,2,16,16,7);
+ switch (ModRM & 0x38) {
+ case 0x00: ROL_BYTE; PutbackRMByte(ModRM,(BYTE)dst); nec_state->OverVal = (src^dst)&0x80; break;
+ case 0x08: ROR_BYTE; PutbackRMByte(ModRM,(BYTE)dst); nec_state->OverVal = (src^dst)&0x80; break;
+ case 0x10: ROLC_BYTE; PutbackRMByte(ModRM,(BYTE)dst); nec_state->OverVal = (src^dst)&0x80; break;
+ case 0x18: RORC_BYTE; PutbackRMByte(ModRM,(BYTE)dst); nec_state->OverVal = (src^dst)&0x80; break;
+ case 0x20: SHL_BYTE(1); nec_state->OverVal = (src^dst)&0x80; break;
+ case 0x28: SHR_BYTE(1); nec_state->OverVal = (src^dst)&0x80; break;
+ case 0x30: logerror("%06x: Undefined opcode 0xd0 0x30 (SHLA)\n",PC(nec_state)); break;
+ case 0x38: SHRA_BYTE(1); nec_state->OverVal = 0; break;
+ }
+}
+
+OP( 0xd1, i_rotshft_w ) {
+ UINT32 src, dst; GetModRM; src = (UINT32)GetRMWord(ModRM); dst=src;
+ CLKM(6,6,2,24,16,7);
+ switch (ModRM & 0x38) {
+ case 0x00: ROL_WORD; PutbackRMWord(ModRM,(WORD)dst); nec_state->OverVal = (src^dst)&0x8000; break;
+ case 0x08: ROR_WORD; PutbackRMWord(ModRM,(WORD)dst); nec_state->OverVal = (src^dst)&0x8000; break;
+ case 0x10: ROLC_WORD; PutbackRMWord(ModRM,(WORD)dst); nec_state->OverVal = (src^dst)&0x8000; break;
+ case 0x18: RORC_WORD; PutbackRMWord(ModRM,(WORD)dst); nec_state->OverVal = (src^dst)&0x8000; break;
+ case 0x20: SHL_WORD(1); nec_state->OverVal = (src^dst)&0x8000; break;
+ case 0x28: SHR_WORD(1); nec_state->OverVal = (src^dst)&0x8000; break;
+ case 0x30: logerror("%06x: Undefined opcode 0xd1 0x30 (SHLA)\n",PC(nec_state)); break;
+ case 0x38: SHRA_WORD(1); nec_state->OverVal = 0; break;
+ }
+}
+
+OP( 0xd2, i_rotshft_bcl ) {
+ UINT32 src, dst; UINT8 c; GetModRM; src = (UINT32)GetRMByte(ModRM); dst=src;
+ c=Breg(CL);
+ CLKM(7,7,2,19,19,6);
+ if (c) switch (ModRM & 0x38) {
+ case 0x00: do { ROL_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break;
+ case 0x08: do { ROR_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break;
+ case 0x10: do { ROLC_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break;
+ case 0x18: do { RORC_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break;
+ case 0x20: SHL_BYTE(c); break;
+ case 0x28: SHR_BYTE(c); break;
+ case 0x30: logerror("%06x: Undefined opcode 0xd2 0x30 (SHLA)\n",PC(nec_state)); break;
+ case 0x38: SHRA_BYTE(c); break;
+ }
+}
+
+OP( 0xd3, i_rotshft_wcl ) {
+ UINT32 src, dst; UINT8 c; GetModRM; src = (UINT32)GetRMWord(ModRM); dst=src;
+ c=Breg(CL);
+ CLKM(7,7,2,27,19,6);
+ if (c) switch (ModRM & 0x38) {
+ case 0x00: do { ROL_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break;
+ case 0x08: do { ROR_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break;
+ case 0x10: do { ROLC_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break;
+ case 0x18: do { RORC_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break;
+ case 0x20: SHL_WORD(c); break;
+ case 0x28: SHR_WORD(c); break;
+ case 0x30: logerror("%06x: Undefined opcode 0xd3 0x30 (SHLA)\n",PC(nec_state)); break;
+ case 0x38: SHRA_WORD(c); break;
+ }
+}
+
+OP( 0xd4, i_aam ) { FETCH(); Breg(AH) = Breg(AL) / 10; Breg(AL) %= 10; SetSZPF_Word(Wreg(AW)); CLKS(15,15,12); }
+OP( 0xd5, i_aad ) { FETCH(); Breg(AL) = Breg(AH) * 10 + Breg(AL); Breg(AH) = 0; SetSZPF_Byte(Breg(AL)); CLKS(7,7,8); }
+OP( 0xd6, i_setalc ) { Breg(AL) = (CF)?0xff:0x00; nec_state->icount-=3; logerror("%06x: Undefined opcode (SETALC)\n",PC(nec_state)); }
+OP( 0xd7, i_trans ) { UINT32 dest = (Wreg(BW)+Breg(AL))&0xffff; Breg(AL) = GetMemB(DS0, dest); CLKS(9,9,5); }
+OP( 0xd8, i_fpo ) { GetModRM; nec_state->icount-=2; logerror("%06x: Unimplemented floating point control %04x\n",PC(nec_state),ModRM); }
+
+OP( 0xe0, i_loopne ) { INT8 disp = (INT8)FETCH(); Wreg(CW)--; if (!ZF && Wreg(CW)) { nec_state->ip = (WORD)(nec_state->ip+disp); /*CHANGE_PC;*/ CLKS(14,14,6); } else CLKS(5,5,3); }
+OP( 0xe1, i_loope ) { INT8 disp = (INT8)FETCH(); Wreg(CW)--; if ( ZF && Wreg(CW)) { nec_state->ip = (WORD)(nec_state->ip+disp); /*CHANGE_PC;*/ CLKS(14,14,6); } else CLKS(5,5,3); }
+OP( 0xe2, i_loop ) { INT8 disp = (INT8)FETCH(); Wreg(CW)--; if (Wreg(CW)) { nec_state->ip = (WORD)(nec_state->ip+disp); /*CHANGE_PC;*/ CLKS(13,13,6); } else CLKS(5,5,3); }
+OP( 0xe3, i_jcxz ) { INT8 disp = (INT8)FETCH(); if (Wreg(CW) == 0) { nec_state->ip = (WORD)(nec_state->ip+disp); /*CHANGE_PC;*/ CLKS(13,13,6); } else CLKS(5,5,3); }
+OP( 0xe4, i_inal ) { UINT8 port = FETCH(); Breg(AL) = read_port_byte(port); CLKS(9,9,5); }
+OP( 0xe5, i_inax ) { UINT8 port = FETCH(); Wreg(AW) = read_port_word(port); CLKW(13,13,7,13,9,5,port); }
+OP( 0xe6, i_outal ) { UINT8 port = FETCH(); write_port_byte(port, Breg(AL)); CLKS(8,8,3); }
+OP( 0xe7, i_outax ) { UINT8 port = FETCH(); write_port_word(port, Wreg(AW)); CLKW(12,12,5,12,8,3,port); }
+
+OP( 0xe8, i_call_d16 ) { UINT32 tmp; tmp = FETCHWORD(); PUSH(nec_state->ip); nec_state->ip = (WORD)(nec_state->ip+(INT16)tmp); CHANGE_PC; nec_state->icount-=24; }
+OP( 0xe9, i_jmp_d16 ) { UINT32 tmp; tmp = FETCHWORD(); nec_state->ip = (WORD)(nec_state->ip+(INT16)tmp); CHANGE_PC; nec_state->icount-=15; }
+OP( 0xea, i_jmp_far ) { UINT32 tmp,tmp1; tmp = FETCHWORD(); tmp1 = FETCHWORD(); Sreg(PS) = (WORD)tmp1; nec_state->ip = (WORD)tmp; CHANGE_PC; nec_state->icount-=27; }
+OP( 0xeb, i_jmp_d8 ) { int tmp = (int)((INT8)FETCH()); nec_state->icount-=12; nec_state->ip = (WORD)(nec_state->ip+tmp); }
+OP( 0xec, i_inaldx ) { Breg(AL) = read_port_byte(Wreg(DW)); CLKS(8,8,5);}
+OP( 0xed, i_inaxdx ) { Wreg(AW) = read_port_word(Wreg(DW)); CLKW(12,12,7,12,8,5,Wreg(DW)); }
+OP( 0xee, i_outdxal ) { write_port_byte(Wreg(DW), Breg(AL)); CLKS(8,8,3); }
+OP( 0xef, i_outdxax ) { write_port_word(Wreg(DW), Wreg(AW)); CLKW(12,12,5,12,8,3,Wreg(DW)); }
+
+OP( 0xf0, i_lock ) { logerror("%06x: Warning - BUSLOCK\n",PC(nec_state)); nec_state->no_interrupt=1; CLK(2); }
+OP( 0xf2, i_repne ) { UINT32 next = fetchop(nec_state); UINT16 c = Wreg(CW);
+ switch(next) { /* Segments */
+ case 0x26: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(DS1)<<4; next = fetchop(nec_state); CLK(2); break;
+ case 0x2e: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(PS)<<4; next = fetchop(nec_state); CLK(2); break;
+ case 0x36: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(SS)<<4; next = fetchop(nec_state); CLK(2); break;
+ case 0x3e: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(DS0)<<4; next = fetchop(nec_state); CLK(2); break;
+ }
+
+ switch(next) {
+ case 0x6c: CLK(2); if (c) do { i_insb(nec_state); c--; } while (c>0); Wreg(CW)=c; break;
+ case 0x6d: CLK(2); if (c) do { i_insw(nec_state); c--; } while (c>0); Wreg(CW)=c; break;
+ case 0x6e: CLK(2); if (c) do { i_outsb(nec_state); c--; } while (c>0); Wreg(CW)=c; break;
+ case 0x6f: CLK(2); if (c) do { i_outsw(nec_state); c--; } while (c>0); Wreg(CW)=c; break;
+ case 0xa4: CLK(2); if (c) do { i_movsb(nec_state); c--; } while (c>0); Wreg(CW)=c; break;
+ case 0xa5: CLK(2); if (c) do { i_movsw(nec_state); c--; } while (c>0); Wreg(CW)=c; break;
+ case 0xa6: CLK(2); if (c) do { i_cmpsb(nec_state); c--; } while (c>0 && ZF==0); Wreg(CW)=c; break;
+ case 0xa7: CLK(2); if (c) do { i_cmpsw(nec_state); c--; } while (c>0 && ZF==0); Wreg(CW)=c; break;
+ case 0xaa: CLK(2); if (c) do { i_stosb(nec_state); c--; } while (c>0); Wreg(CW)=c; break;
+ case 0xab: CLK(2); if (c) do { i_stosw(nec_state); c--; } while (c>0); Wreg(CW)=c; break;
+ case 0xac: CLK(2); if (c) do { i_lodsb(nec_state); c--; } while (c>0); Wreg(CW)=c; break;
+ case 0xad: CLK(2); if (c) do { i_lodsw(nec_state); c--; } while (c>0); Wreg(CW)=c; break;
+ case 0xae: CLK(2); if (c) do { i_scasb(nec_state); c--; } while (c>0 && ZF==0); Wreg(CW)=c; break;
+ case 0xaf: CLK(2); if (c) do { i_scasw(nec_state); c--; } while (c>0 && ZF==0); Wreg(CW)=c; break;
+ default: logerror("%06x: REPNE invalid\n",PC(nec_state)); nec_instruction[next](nec_state);
+ }
+ nec_state->seg_prefix=FALSE;
+}
+OP( 0xf3, i_repe ) { UINT32 next = fetchop(nec_state); UINT16 c = Wreg(CW);
+ switch(next) { /* Segments */
+ case 0x26: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(DS1)<<4; next = fetchop(nec_state); CLK(2); break;
+ case 0x2e: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(PS)<<4; next = fetchop(nec_state); CLK(2); break;
+ case 0x36: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(SS)<<4; next = fetchop(nec_state); CLK(2); break;
+ case 0x3e: nec_state->seg_prefix=TRUE; nec_state->prefix_base=Sreg(DS0)<<4; next = fetchop(nec_state); CLK(2); break;
+ }
+
+ switch(next) {
+ case 0x6c: CLK(2); if (c) do { i_insb(nec_state); c--; } while (c>0); Wreg(CW)=c; break;
+ case 0x6d: CLK(2); if (c) do { i_insw(nec_state); c--; } while (c>0); Wreg(CW)=c; break;
+ case 0x6e: CLK(2); if (c) do { i_outsb(nec_state); c--; } while (c>0); Wreg(CW)=c; break;
+ case 0x6f: CLK(2); if (c) do { i_outsw(nec_state); c--; } while (c>0); Wreg(CW)=c; break;
+ case 0xa4: CLK(2); if (c) do { i_movsb(nec_state); c--; } while (c>0); Wreg(CW)=c; break;
+ case 0xa5: CLK(2); if (c) do { i_movsw(nec_state); c--; } while (c>0); Wreg(CW)=c; break;
+ case 0xa6: CLK(2); if (c) do { i_cmpsb(nec_state); c--; } while (c>0 && ZF==1); Wreg(CW)=c; break;
+ case 0xa7: CLK(2); if (c) do { i_cmpsw(nec_state); c--; } while (c>0 && ZF==1); Wreg(CW)=c; break;
+ case 0xaa: CLK(2); if (c) do { i_stosb(nec_state); c--; } while (c>0); Wreg(CW)=c; break;
+ case 0xab: CLK(2); if (c) do { i_stosw(nec_state); c--; } while (c>0); Wreg(CW)=c; break;
+ case 0xac: CLK(2); if (c) do { i_lodsb(nec_state); c--; } while (c>0); Wreg(CW)=c; break;
+ case 0xad: CLK(2); if (c) do { i_lodsw(nec_state); c--; } while (c>0); Wreg(CW)=c; break;
+ case 0xae: CLK(2); if (c) do { i_scasb(nec_state); c--; } while (c>0 && ZF==1); Wreg(CW)=c; break;
+ case 0xaf: CLK(2); if (c) do { i_scasw(nec_state); c--; } while (c>0 && ZF==1); Wreg(CW)=c; break;
+ default: logerror("%06x: REPE invalid\n",PC(nec_state)); nec_instruction[next](nec_state);
+ }
+ nec_state->seg_prefix=FALSE;
+}
+OP( 0xf4, i_hlt ) { logerror("%06x: HALT\n",PC(nec_state)); nec_state->halted=1; nec_state->icount=0; }
+OP( 0xf5, i_cmc ) { nec_state->CarryVal = !CF; CLK(2); }
+OP( 0xf6, i_f6pre ) { UINT32 tmp; UINT32 uresult,uresult2; INT32 result,result2;
+ GetModRM; tmp = GetRMByte(ModRM);
+ switch (ModRM & 0x38) {
+ case 0x00: tmp &= FETCH(); nec_state->CarryVal = nec_state->OverVal = 0; SetSZPF_Byte(tmp); nec_state->icount-=(ModRM >=0xc0 )?4:11; break; /* TEST */
+ case 0x08: logerror("%06x: Undefined opcode 0xf6 0x08\n",PC(nec_state)); break;
+ case 0x10: PutbackRMByte(ModRM,~tmp); nec_state->icount-=(ModRM >=0xc0 )?2:16; break; /* NOT */
+ case 0x18: nec_state->CarryVal=(tmp!=0); tmp=(~tmp)+1; SetSZPF_Byte(tmp); PutbackRMByte(ModRM,tmp&0xff); nec_state->icount-=(ModRM >=0xc0 )?2:16; break; /* NEG */
+ case 0x20: uresult = Breg(AL)*tmp; Wreg(AW)=(WORD)uresult; nec_state->CarryVal=nec_state->OverVal=(Breg(AH)!=0); nec_state->icount-=(ModRM >=0xc0 )?30:36; break; /* MULU */
+ case 0x28: result = (INT16)((INT8)Breg(AL))*(INT16)((INT8)tmp); Wreg(AW)=(WORD)result; nec_state->CarryVal=nec_state->OverVal=(Breg(AH)!=0); nec_state->icount-=(ModRM >=0xc0 )?30:36; break; /* MUL */
+ case 0x30: if (tmp) { DIVUB; } else nec_interrupt(nec_state, NEC_DIVIDE_VECTOR, BRK); nec_state->icount-=(ModRM >=0xc0 )?43:53; break;
+ case 0x38: if (tmp) { DIVB; } else nec_interrupt(nec_state, NEC_DIVIDE_VECTOR, BRK); nec_state->icount-=(ModRM >=0xc0 )?43:53; break;
+ }
+}
+
+OP( 0xf7, i_f7pre ) { UINT32 tmp,tmp2; UINT32 uresult,uresult2; INT32 result,result2;
+ GetModRM; tmp = GetRMWord(ModRM);
+ switch (ModRM & 0x38) {
+ case 0x00: tmp2 = FETCHWORD(); tmp &= tmp2; nec_state->CarryVal = nec_state->OverVal = 0; SetSZPF_Word(tmp); nec_state->icount-=(ModRM >=0xc0 )?4:11; break; /* TEST */
+ case 0x08: logerror("%06x: Undefined opcode 0xf7 0x08\n",PC(nec_state)); break;
+ case 0x10: PutbackRMWord(ModRM,~tmp); nec_state->icount-=(ModRM >=0xc0 )?2:16; break; /* NOT */
+ case 0x18: nec_state->CarryVal=(tmp!=0); tmp=(~tmp)+1; SetSZPF_Word(tmp); PutbackRMWord(ModRM,tmp&0xffff); nec_state->icount-=(ModRM >=0xc0 )?2:16; break; /* NEG */
+ case 0x20: uresult = Wreg(AW)*tmp; Wreg(AW)=uresult&0xffff; Wreg(DW)=((UINT32)uresult)>>16; nec_state->CarryVal=nec_state->OverVal=(Wreg(DW)!=0); nec_state->icount-=(ModRM >=0xc0 )?30:36; break; /* MULU */
+ case 0x28: result = (INT32)((INT16)Wreg(AW))*(INT32)((INT16)tmp); Wreg(AW)=result&0xffff; Wreg(DW)=result>>16; nec_state->CarryVal=nec_state->OverVal=(Wreg(DW)!=0); nec_state->icount-=(ModRM >=0xc0 )?30:36; break; /* MUL */
+ case 0x30: if (tmp) { DIVUW; } else nec_interrupt(nec_state, NEC_DIVIDE_VECTOR, BRK); nec_state->icount-=(ModRM >=0xc0 )?43:53; break;
+ case 0x38: if (tmp) { DIVW; } else nec_interrupt(nec_state, NEC_DIVIDE_VECTOR, BRK); nec_state->icount-=(ModRM >=0xc0 )?43:53; break;
+ }
+}
+
+OP( 0xf8, i_clc ) { nec_state->CarryVal = 0; CLK(2); }
+OP( 0xf9, i_stc ) { nec_state->CarryVal = 1; CLK(2); }
+OP( 0xfa, i_di ) { SetIF(0); CLK(2); }
+OP( 0xfb, i_ei ) { SetIF(1); CLK(2); }
+OP( 0xfc, i_cld ) { SetDF(0); CLK(2); }
+OP( 0xfd, i_std ) { SetDF(1); CLK(2); }
+OP( 0xfe, i_fepre ) { UINT32 tmp, tmp1; GetModRM; tmp=GetRMByte(ModRM);
+ switch(ModRM & 0x38) {
+ case 0x00: tmp1 = tmp+1; nec_state->OverVal = (tmp==0x7f); SetAF(tmp1,tmp,1); SetSZPF_Byte(tmp1); PutbackRMByte(ModRM,(BYTE)tmp1); CLKM(2,2,2,16,16,7); break; /* INC */
+ case 0x08: tmp1 = tmp-1; nec_state->OverVal = (tmp==0x80); SetAF(tmp1,tmp,1); SetSZPF_Byte(tmp1); PutbackRMByte(ModRM,(BYTE)tmp1); CLKM(2,2,2,16,16,7); break; /* DEC */
+ default: logerror("%06x: FE Pre with unimplemented mod\n",PC(nec_state));
+ }
+}
+OP( 0xff, i_ffpre ) { UINT32 tmp, tmp1; GetModRM; tmp=GetRMWord(ModRM);
+ switch(ModRM & 0x38) {
+ case 0x00: tmp1 = tmp+1; nec_state->OverVal = (tmp==0x7fff); SetAF(tmp1,tmp,1); SetSZPF_Word(tmp1); PutbackRMWord(ModRM,(WORD)tmp1); CLKM(2,2,2,24,16,7); break; /* INC */
+ case 0x08: tmp1 = tmp-1; nec_state->OverVal = (tmp==0x8000); SetAF(tmp1,tmp,1); SetSZPF_Word(tmp1); PutbackRMWord(ModRM,(WORD)tmp1); CLKM(2,2,2,24,16,7); break; /* DEC */
+ case 0x10: PUSH(nec_state->ip); nec_state->ip = (WORD)tmp; CHANGE_PC; nec_state->icount-=(ModRM >=0xc0 )?16:20; break; /* CALL */
+ case 0x18: tmp1 = Sreg(PS); Sreg(PS) = GetnextRMWord; PUSH(tmp1); PUSH(nec_state->ip); nec_state->ip = tmp; CHANGE_PC; nec_state->icount-=(ModRM >=0xc0 )?16:26; break; /* CALL FAR */
+ case 0x20: nec_state->ip = tmp; CHANGE_PC; nec_state->icount-=13; break; /* JMP */
+ case 0x28: nec_state->ip = tmp; Sreg(PS) = GetnextRMWord; CHANGE_PC; nec_state->icount-=15; break; /* JMP FAR */
+ case 0x30: PUSH(tmp); nec_state->icount-=4; break;
+ default: logerror("%06x: FF Pre with unimplemented mod\n",PC(nec_state));
+ }
+}
+
+static void i_invalid(nec_state_t *nec_state)
+{
+ nec_state->icount-=10;
+ logerror("%06x: Invalid Opcode\n",PC(nec_state));
+}
diff --git a/trunk/src/emu/cpu/nec/necinstr.h b/trunk/src/emu/cpu/nec/necinstr.h
new file mode 100644
index 00000000000..30bc3ffcbb2
--- /dev/null
+++ b/trunk/src/emu/cpu/nec/necinstr.h
@@ -0,0 +1,507 @@
+static void i_add_br8(nec_state_t *nec_state);
+static void i_add_wr16(nec_state_t *nec_state);
+static void i_add_r8b(nec_state_t *nec_state);
+static void i_add_r16w(nec_state_t *nec_state);
+static void i_add_ald8(nec_state_t *nec_state);
+static void i_add_axd16(nec_state_t *nec_state);
+static void i_push_es(nec_state_t *nec_state);
+static void i_pop_es(nec_state_t *nec_state);
+static void i_or_br8(nec_state_t *nec_state);
+static void i_or_r8b(nec_state_t *nec_state);
+static void i_or_wr16(nec_state_t *nec_state);
+static void i_or_r16w(nec_state_t *nec_state);
+static void i_or_ald8(nec_state_t *nec_state);
+static void i_or_axd16(nec_state_t *nec_state);
+static void i_push_cs(nec_state_t *nec_state);
+static void i_pre_nec(nec_state_t *nec_state);
+static void i_adc_br8(nec_state_t *nec_state);
+static void i_adc_wr16(nec_state_t *nec_state);
+static void i_adc_r8b(nec_state_t *nec_state);
+static void i_adc_r16w(nec_state_t *nec_state);
+static void i_adc_ald8(nec_state_t *nec_state);
+static void i_adc_axd16(nec_state_t *nec_state);
+static void i_push_ss(nec_state_t *nec_state);
+static void i_pop_ss(nec_state_t *nec_state);
+static void i_sbb_br8(nec_state_t *nec_state);
+static void i_sbb_wr16(nec_state_t *nec_state);
+static void i_sbb_r8b(nec_state_t *nec_state);
+static void i_sbb_r16w(nec_state_t *nec_state);
+static void i_sbb_ald8(nec_state_t *nec_state);
+static void i_sbb_axd16(nec_state_t *nec_state);
+static void i_push_ds(nec_state_t *nec_state);
+static void i_pop_ds(nec_state_t *nec_state);
+static void i_and_br8(nec_state_t *nec_state);
+static void i_and_r8b(nec_state_t *nec_state);
+static void i_and_wr16(nec_state_t *nec_state);
+static void i_and_r16w(nec_state_t *nec_state);
+static void i_and_ald8(nec_state_t *nec_state);
+static void i_and_axd16(nec_state_t *nec_state);
+static void i_es(nec_state_t *nec_state);
+static void i_daa(nec_state_t *nec_state);
+static void i_sub_br8(nec_state_t *nec_state);
+static void i_sub_wr16(nec_state_t *nec_state);
+static void i_sub_r8b(nec_state_t *nec_state);
+static void i_sub_r16w(nec_state_t *nec_state);
+static void i_sub_ald8(nec_state_t *nec_state);
+static void i_sub_axd16(nec_state_t *nec_state);
+static void i_cs(nec_state_t *nec_state);
+static void i_das(nec_state_t *nec_state);
+static void i_xor_br8(nec_state_t *nec_state);
+static void i_xor_r8b(nec_state_t *nec_state);
+static void i_xor_wr16(nec_state_t *nec_state);
+static void i_xor_r16w(nec_state_t *nec_state);
+static void i_xor_ald8(nec_state_t *nec_state);
+static void i_xor_axd16(nec_state_t *nec_state);
+static void i_ss(nec_state_t *nec_state);
+static void i_aaa(nec_state_t *nec_state);
+static void i_cmp_br8(nec_state_t *nec_state);
+static void i_cmp_wr16(nec_state_t *nec_state);
+static void i_cmp_r8b(nec_state_t *nec_state);
+static void i_cmp_r16w(nec_state_t *nec_state);
+static void i_cmp_ald8(nec_state_t *nec_state);
+static void i_cmp_axd16(nec_state_t *nec_state);
+static void i_ds(nec_state_t *nec_state);
+static void i_aas(nec_state_t *nec_state);
+static void i_inc_ax(nec_state_t *nec_state);
+static void i_inc_cx(nec_state_t *nec_state);
+static void i_inc_dx(nec_state_t *nec_state);
+static void i_inc_bx(nec_state_t *nec_state);
+static void i_inc_sp(nec_state_t *nec_state);
+static void i_inc_bp(nec_state_t *nec_state);
+static void i_inc_si(nec_state_t *nec_state);
+static void i_inc_di(nec_state_t *nec_state);
+static void i_dec_ax(nec_state_t *nec_state);
+static void i_dec_cx(nec_state_t *nec_state);
+static void i_dec_dx(nec_state_t *nec_state);
+static void i_dec_bx(nec_state_t *nec_state);
+static void i_dec_sp(nec_state_t *nec_state);
+static void i_dec_bp(nec_state_t *nec_state);
+static void i_dec_si(nec_state_t *nec_state);
+static void i_dec_di(nec_state_t *nec_state);
+static void i_push_ax(nec_state_t *nec_state);
+static void i_push_cx(nec_state_t *nec_state);
+static void i_push_dx(nec_state_t *nec_state);
+static void i_push_bx(nec_state_t *nec_state);
+static void i_push_sp(nec_state_t *nec_state);
+static void i_push_bp(nec_state_t *nec_state);
+static void i_push_si(nec_state_t *nec_state);
+static void i_push_di(nec_state_t *nec_state);
+static void i_pop_ax(nec_state_t *nec_state);
+static void i_pop_cx(nec_state_t *nec_state);
+static void i_pop_dx(nec_state_t *nec_state);
+static void i_pop_bx(nec_state_t *nec_state);
+static void i_pop_sp(nec_state_t *nec_state);
+static void i_pop_bp(nec_state_t *nec_state);
+static void i_pop_si(nec_state_t *nec_state);
+static void i_pop_di(nec_state_t *nec_state);
+static void i_pusha(nec_state_t *nec_state);
+static void i_popa(nec_state_t *nec_state);
+static void i_chkind(nec_state_t *nec_state);
+static void i_repnc(nec_state_t *nec_state);
+static void i_repc(nec_state_t *nec_state);
+static void i_push_d16(nec_state_t *nec_state);
+static void i_imul_d16(nec_state_t *nec_state);
+static void i_push_d8(nec_state_t *nec_state);
+static void i_imul_d8(nec_state_t *nec_state);
+static void i_insb(nec_state_t *nec_state);
+static void i_insw(nec_state_t *nec_state);
+static void i_outsb(nec_state_t *nec_state);
+static void i_outsw(nec_state_t *nec_state);
+static void i_jo(nec_state_t *nec_state);
+static void i_jno(nec_state_t *nec_state);
+static void i_jc(nec_state_t *nec_state);
+static void i_jnc(nec_state_t *nec_state);
+static void i_jz(nec_state_t *nec_state);
+static void i_jnz(nec_state_t *nec_state);
+static void i_jce(nec_state_t *nec_state);
+static void i_jnce(nec_state_t *nec_state);
+static void i_js(nec_state_t *nec_state);
+static void i_jns(nec_state_t *nec_state);
+static void i_jp(nec_state_t *nec_state);
+static void i_jnp(nec_state_t *nec_state);
+static void i_jl(nec_state_t *nec_state);
+static void i_jnl(nec_state_t *nec_state);
+static void i_jle(nec_state_t *nec_state);
+static void i_jnle(nec_state_t *nec_state);
+static void i_80pre(nec_state_t *nec_state);
+static void i_82pre(nec_state_t *nec_state);
+static void i_81pre(nec_state_t *nec_state);
+static void i_83pre(nec_state_t *nec_state);
+static void i_test_br8(nec_state_t *nec_state);
+static void i_test_wr16(nec_state_t *nec_state);
+static void i_xchg_br8(nec_state_t *nec_state);
+static void i_xchg_wr16(nec_state_t *nec_state);
+static void i_mov_br8(nec_state_t *nec_state);
+static void i_mov_r8b(nec_state_t *nec_state);
+static void i_mov_wr16(nec_state_t *nec_state);
+static void i_mov_r16w(nec_state_t *nec_state);
+static void i_mov_wsreg(nec_state_t *nec_state);
+static void i_lea(nec_state_t *nec_state);
+static void i_mov_sregw(nec_state_t *nec_state);
+static void i_invalid(nec_state_t *nec_state);
+static void i_popw(nec_state_t *nec_state);
+static void i_nop(nec_state_t *nec_state);
+static void i_xchg_axcx(nec_state_t *nec_state);
+static void i_xchg_axdx(nec_state_t *nec_state);
+static void i_xchg_axbx(nec_state_t *nec_state);
+static void i_xchg_axsp(nec_state_t *nec_state);
+static void i_xchg_axbp(nec_state_t *nec_state);
+static void i_xchg_axsi(nec_state_t *nec_state);
+static void i_xchg_axdi(nec_state_t *nec_state);
+static void i_cbw(nec_state_t *nec_state);
+static void i_cwd(nec_state_t *nec_state);
+static void i_call_far(nec_state_t *nec_state);
+static void i_pushf(nec_state_t *nec_state);
+static void i_popf(nec_state_t *nec_state);
+static void i_sahf(nec_state_t *nec_state);
+static void i_lahf(nec_state_t *nec_state);
+static void i_mov_aldisp(nec_state_t *nec_state);
+static void i_mov_axdisp(nec_state_t *nec_state);
+static void i_mov_dispal(nec_state_t *nec_state);
+static void i_mov_dispax(nec_state_t *nec_state);
+static void i_movsb(nec_state_t *nec_state);
+static void i_movsw(nec_state_t *nec_state);
+static void i_cmpsb(nec_state_t *nec_state);
+static void i_cmpsw(nec_state_t *nec_state);
+static void i_test_ald8(nec_state_t *nec_state);
+static void i_test_axd16(nec_state_t *nec_state);
+static void i_stosb(nec_state_t *nec_state);
+static void i_stosw(nec_state_t *nec_state);
+static void i_lodsb(nec_state_t *nec_state);
+static void i_lodsw(nec_state_t *nec_state);
+static void i_scasb(nec_state_t *nec_state);
+static void i_scasw(nec_state_t *nec_state);
+static void i_mov_ald8(nec_state_t *nec_state);
+static void i_mov_cld8(nec_state_t *nec_state);
+static void i_mov_dld8(nec_state_t *nec_state);
+static void i_mov_bld8(nec_state_t *nec_state);
+static void i_mov_ahd8(nec_state_t *nec_state);
+static void i_mov_chd8(nec_state_t *nec_state);
+static void i_mov_dhd8(nec_state_t *nec_state);
+static void i_mov_bhd8(nec_state_t *nec_state);
+static void i_mov_axd16(nec_state_t *nec_state);
+static void i_mov_cxd16(nec_state_t *nec_state);
+static void i_mov_dxd16(nec_state_t *nec_state);
+static void i_mov_bxd16(nec_state_t *nec_state);
+static void i_mov_spd16(nec_state_t *nec_state);
+static void i_mov_bpd16(nec_state_t *nec_state);
+static void i_mov_sid16(nec_state_t *nec_state);
+static void i_mov_did16(nec_state_t *nec_state);
+static void i_rotshft_bd8(nec_state_t *nec_state);
+static void i_rotshft_wd8(nec_state_t *nec_state);
+static void i_ret_d16(nec_state_t *nec_state);
+static void i_ret(nec_state_t *nec_state);
+static void i_les_dw(nec_state_t *nec_state);
+static void i_lds_dw(nec_state_t *nec_state);
+static void i_mov_bd8(nec_state_t *nec_state);
+static void i_mov_wd16(nec_state_t *nec_state);
+static void i_enter(nec_state_t *nec_state);
+static void i_leave(nec_state_t *nec_state);
+static void i_retf_d16(nec_state_t *nec_state);
+static void i_retf(nec_state_t *nec_state);
+static void i_int3(nec_state_t *nec_state);
+static void i_int(nec_state_t *nec_state);
+static void i_into(nec_state_t *nec_state);
+static void i_iret(nec_state_t *nec_state);
+static void i_rotshft_b(nec_state_t *nec_state);
+static void i_rotshft_w(nec_state_t *nec_state);
+static void i_rotshft_bcl(nec_state_t *nec_state);
+static void i_rotshft_wcl(nec_state_t *nec_state);
+static void i_aam(nec_state_t *nec_state);
+static void i_aad(nec_state_t *nec_state);
+static void i_setalc(nec_state_t *nec_state);
+static void i_trans(nec_state_t *nec_state);
+static void i_fpo(nec_state_t *nec_state);
+static void i_loopne(nec_state_t *nec_state);
+static void i_loope(nec_state_t *nec_state);
+static void i_loop(nec_state_t *nec_state);
+static void i_jcxz(nec_state_t *nec_state);
+static void i_inal(nec_state_t *nec_state);
+static void i_inax(nec_state_t *nec_state);
+static void i_outal(nec_state_t *nec_state);
+static void i_outax(nec_state_t *nec_state);
+static void i_call_d16(nec_state_t *nec_state);
+static void i_jmp_d16(nec_state_t *nec_state);
+static void i_jmp_far(nec_state_t *nec_state);
+static void i_jmp_d8(nec_state_t *nec_state);
+static void i_inaldx(nec_state_t *nec_state);
+static void i_inaxdx(nec_state_t *nec_state);
+static void i_outdxal(nec_state_t *nec_state);
+static void i_outdxax(nec_state_t *nec_state);
+static void i_lock(nec_state_t *nec_state);
+static void i_repne(nec_state_t *nec_state);
+static void i_repe(nec_state_t *nec_state);
+static void i_hlt(nec_state_t *nec_state);
+static void i_cmc(nec_state_t *nec_state);
+static void i_f6pre(nec_state_t *nec_state);
+static void i_f7pre(nec_state_t *nec_state);
+static void i_clc(nec_state_t *nec_state);
+static void i_stc(nec_state_t *nec_state);
+static void i_di(nec_state_t *nec_state);
+static void i_ei(nec_state_t *nec_state);
+static void i_cld(nec_state_t *nec_state);
+static void i_std(nec_state_t *nec_state);
+static void i_fepre(nec_state_t *nec_state);
+static void i_ffpre(nec_state_t *nec_state);
+
+static void i_wait(nec_state_t *nec_state);
+
+static void (*const nec_instruction[256])(nec_state_t *nec_state) =
+{
+ i_add_br8, /* 0x00 */
+ i_add_wr16, /* 0x01 */
+ i_add_r8b, /* 0x02 */
+ i_add_r16w, /* 0x03 */
+ i_add_ald8, /* 0x04 */
+ i_add_axd16, /* 0x05 */
+ i_push_es, /* 0x06 */
+ i_pop_es, /* 0x07 */
+ i_or_br8, /* 0x08 */
+ i_or_wr16, /* 0x09 */
+ i_or_r8b, /* 0x0a */
+ i_or_r16w, /* 0x0b */
+ i_or_ald8, /* 0x0c */
+ i_or_axd16, /* 0x0d */
+ i_push_cs, /* 0x0e */
+ i_pre_nec, /* 0x0f */
+ i_adc_br8, /* 0x10 */
+ i_adc_wr16, /* 0x11 */
+ i_adc_r8b, /* 0x12 */
+ i_adc_r16w, /* 0x13 */
+ i_adc_ald8, /* 0x14 */
+ i_adc_axd16, /* 0x15 */
+ i_push_ss, /* 0x16 */
+ i_pop_ss, /* 0x17 */
+ i_sbb_br8, /* 0x18 */
+ i_sbb_wr16, /* 0x19 */
+ i_sbb_r8b, /* 0x1a */
+ i_sbb_r16w, /* 0x1b */
+ i_sbb_ald8, /* 0x1c */
+ i_sbb_axd16, /* 0x1d */
+ i_push_ds, /* 0x1e */
+ i_pop_ds, /* 0x1f */
+ i_and_br8, /* 0x20 */
+ i_and_wr16, /* 0x21 */
+ i_and_r8b, /* 0x22 */
+ i_and_r16w, /* 0x23 */
+ i_and_ald8, /* 0x24 */
+ i_and_axd16, /* 0x25 */
+ i_es, /* 0x26 */
+ i_daa, /* 0x27 */
+ i_sub_br8, /* 0x28 */
+ i_sub_wr16, /* 0x29 */
+ i_sub_r8b, /* 0x2a */
+ i_sub_r16w, /* 0x2b */
+ i_sub_ald8, /* 0x2c */
+ i_sub_axd16, /* 0x2d */
+ i_cs, /* 0x2e */
+ i_das, /* 0x2f */
+ i_xor_br8, /* 0x30 */
+ i_xor_wr16, /* 0x31 */
+ i_xor_r8b, /* 0x32 */
+ i_xor_r16w, /* 0x33 */
+ i_xor_ald8, /* 0x34 */
+ i_xor_axd16, /* 0x35 */
+ i_ss, /* 0x36 */
+ i_aaa, /* 0x37 */
+ i_cmp_br8, /* 0x38 */
+ i_cmp_wr16, /* 0x39 */
+ i_cmp_r8b, /* 0x3a */
+ i_cmp_r16w, /* 0x3b */
+ i_cmp_ald8, /* 0x3c */
+ i_cmp_axd16, /* 0x3d */
+ i_ds, /* 0x3e */
+ i_aas, /* 0x3f */
+ i_inc_ax, /* 0x40 */
+ i_inc_cx, /* 0x41 */
+ i_inc_dx, /* 0x42 */
+ i_inc_bx, /* 0x43 */
+ i_inc_sp, /* 0x44 */
+ i_inc_bp, /* 0x45 */
+ i_inc_si, /* 0x46 */
+ i_inc_di, /* 0x47 */
+ i_dec_ax, /* 0x48 */
+ i_dec_cx, /* 0x49 */
+ i_dec_dx, /* 0x4a */
+ i_dec_bx, /* 0x4b */
+ i_dec_sp, /* 0x4c */
+ i_dec_bp, /* 0x4d */
+ i_dec_si, /* 0x4e */
+ i_dec_di, /* 0x4f */
+ i_push_ax, /* 0x50 */
+ i_push_cx, /* 0x51 */
+ i_push_dx, /* 0x52 */
+ i_push_bx, /* 0x53 */
+ i_push_sp, /* 0x54 */
+ i_push_bp, /* 0x55 */
+ i_push_si, /* 0x56 */
+ i_push_di, /* 0x57 */
+ i_pop_ax, /* 0x58 */
+ i_pop_cx, /* 0x59 */
+ i_pop_dx, /* 0x5a */
+ i_pop_bx, /* 0x5b */
+ i_pop_sp, /* 0x5c */
+ i_pop_bp, /* 0x5d */
+ i_pop_si, /* 0x5e */
+ i_pop_di, /* 0x5f */
+ i_pusha, /* 0x60 */
+ i_popa, /* 0x61 */
+ i_chkind, /* 0x62 */
+ i_invalid, /* 0x63 */
+ i_repnc, /* 0x64 */
+ i_repc, /* 0x65 */
+ i_invalid, /* 0x66 */
+ i_invalid, /* 0x67 */
+ i_push_d16, /* 0x68 */
+ i_imul_d16, /* 0x69 */
+ i_push_d8, /* 0x6a */
+ i_imul_d8, /* 0x6b */
+ i_insb, /* 0x6c */
+ i_insw, /* 0x6d */
+ i_outsb, /* 0x6e */
+ i_outsw, /* 0x6f */
+ i_jo, /* 0x70 */
+ i_jno, /* 0x71 */
+ i_jc, /* 0x72 */
+ i_jnc, /* 0x73 */
+ i_jz, /* 0x74 */
+ i_jnz, /* 0x75 */
+ i_jce, /* 0x76 */
+ i_jnce, /* 0x77 */
+ i_js, /* 0x78 */
+ i_jns, /* 0x79 */
+ i_jp, /* 0x7a */
+ i_jnp, /* 0x7b */
+ i_jl, /* 0x7c */
+ i_jnl, /* 0x7d */
+ i_jle, /* 0x7e */
+ i_jnle, /* 0x7f */
+ i_80pre, /* 0x80 */
+ i_81pre, /* 0x81 */
+ i_82pre, /* 0x82 */
+ i_83pre, /* 0x83 */
+ i_test_br8, /* 0x84 */
+ i_test_wr16, /* 0x85 */
+ i_xchg_br8, /* 0x86 */
+ i_xchg_wr16, /* 0x87 */
+ i_mov_br8, /* 0x88 */
+ i_mov_wr16, /* 0x89 */
+ i_mov_r8b, /* 0x8a */
+ i_mov_r16w, /* 0x8b */
+ i_mov_wsreg, /* 0x8c */
+ i_lea, /* 0x8d */
+ i_mov_sregw, /* 0x8e */
+ i_popw, /* 0x8f */
+ i_nop, /* 0x90 */
+ i_xchg_axcx, /* 0x91 */
+ i_xchg_axdx, /* 0x92 */
+ i_xchg_axbx, /* 0x93 */
+ i_xchg_axsp, /* 0x94 */
+ i_xchg_axbp, /* 0x95 */
+ i_xchg_axsi, /* 0x96 */
+ i_xchg_axdi, /* 0x97 */
+ i_cbw, /* 0x98 */
+ i_cwd, /* 0x99 */
+ i_call_far, /* 0x9a */
+ i_wait, /* 0x9b */
+ i_pushf, /* 0x9c */
+ i_popf, /* 0x9d */
+ i_sahf, /* 0x9e */
+ i_lahf, /* 0x9f */
+ i_mov_aldisp, /* 0xa0 */
+ i_mov_axdisp, /* 0xa1 */
+ i_mov_dispal, /* 0xa2 */
+ i_mov_dispax, /* 0xa3 */
+ i_movsb, /* 0xa4 */
+ i_movsw, /* 0xa5 */
+ i_cmpsb, /* 0xa6 */
+ i_cmpsw, /* 0xa7 */
+ i_test_ald8, /* 0xa8 */
+ i_test_axd16, /* 0xa9 */
+ i_stosb, /* 0xaa */
+ i_stosw, /* 0xab */
+ i_lodsb, /* 0xac */
+ i_lodsw, /* 0xad */
+ i_scasb, /* 0xae */
+ i_scasw, /* 0xaf */
+ i_mov_ald8, /* 0xb0 */
+ i_mov_cld8, /* 0xb1 */
+ i_mov_dld8, /* 0xb2 */
+ i_mov_bld8, /* 0xb3 */
+ i_mov_ahd8, /* 0xb4 */
+ i_mov_chd8, /* 0xb5 */
+ i_mov_dhd8, /* 0xb6 */
+ i_mov_bhd8, /* 0xb7 */
+ i_mov_axd16, /* 0xb8 */
+ i_mov_cxd16, /* 0xb9 */
+ i_mov_dxd16, /* 0xba */
+ i_mov_bxd16, /* 0xbb */
+ i_mov_spd16, /* 0xbc */
+ i_mov_bpd16, /* 0xbd */
+ i_mov_sid16, /* 0xbe */
+ i_mov_did16, /* 0xbf */
+ i_rotshft_bd8, /* 0xc0 */
+ i_rotshft_wd8, /* 0xc1 */
+ i_ret_d16, /* 0xc2 */
+ i_ret, /* 0xc3 */
+ i_les_dw, /* 0xc4 */
+ i_lds_dw, /* 0xc5 */
+ i_mov_bd8, /* 0xc6 */
+ i_mov_wd16, /* 0xc7 */
+ i_enter, /* 0xc8 */
+ i_leave, /* 0xc9 */
+ i_retf_d16, /* 0xca */
+ i_retf, /* 0xcb */
+ i_int3, /* 0xcc */
+ i_int, /* 0xcd */
+ i_into, /* 0xce */
+ i_iret, /* 0xcf */
+ i_rotshft_b, /* 0xd0 */
+ i_rotshft_w, /* 0xd1 */
+ i_rotshft_bcl, /* 0xd2 */
+ i_rotshft_wcl, /* 0xd3 */
+ i_aam, /* 0xd4 */
+ i_aad, /* 0xd5 */
+ i_setalc, /* 0xd6 */
+ i_trans, /* 0xd7 */
+ i_fpo, /* 0xd8 */
+ i_fpo, /* 0xd9 */
+ i_fpo, /* 0xda */
+ i_fpo, /* 0xdb */
+ i_fpo, /* 0xdc */
+ i_fpo, /* 0xdd */
+ i_fpo, /* 0xde */
+ i_fpo, /* 0xdf */
+ i_loopne, /* 0xe0 */
+ i_loope, /* 0xe1 */
+ i_loop, /* 0xe2 */
+ i_jcxz, /* 0xe3 */
+ i_inal, /* 0xe4 */
+ i_inax, /* 0xe5 */
+ i_outal, /* 0xe6 */
+ i_outax, /* 0xe7 */
+ i_call_d16, /* 0xe8 */
+ i_jmp_d16, /* 0xe9 */
+ i_jmp_far, /* 0xea */
+ i_jmp_d8, /* 0xeb */
+ i_inaldx, /* 0xec */
+ i_inaxdx, /* 0xed */
+ i_outdxal, /* 0xee */
+ i_outdxax, /* 0xef */
+ i_lock, /* 0xf0 */
+ i_invalid, /* 0xf1 */
+ i_repne, /* 0xf2 */
+ i_repe, /* 0xf3 */
+ i_hlt, /* 0xf4 */
+ i_cmc, /* 0xf5 */
+ i_f6pre, /* 0xf6 */
+ i_f7pre, /* 0xf7 */
+ i_clc, /* 0xf8 */
+ i_stc, /* 0xf9 */
+ i_di, /* 0xfa */
+ i_ei, /* 0xfb */
+ i_cld, /* 0xfc */
+ i_std, /* 0xfd */
+ i_fepre, /* 0xfe */
+ i_ffpre /* 0xff */
+};
diff --git a/trunk/src/emu/cpu/nec/necmacro.h b/trunk/src/emu/cpu/nec/necmacro.h
new file mode 100644
index 00000000000..e244b2b4cfe
--- /dev/null
+++ b/trunk/src/emu/cpu/nec/necmacro.h
@@ -0,0 +1,267 @@
+/* parameter x = result, y = source 1, z = source 2 */
+
+#define SetTF(x) (nec_state->TF = (x))
+#define SetIF(x) (nec_state->IF = (x))
+#define SetDF(x) (nec_state->DF = (x))
+#define SetMD(x) (nec_state->MF = (x)) /* OB [19.07.99] Mode Flag V30 */
+
+#define SetCFB(x) (nec_state->CarryVal = (x) & 0x100)
+#define SetCFW(x) (nec_state->CarryVal = (x) & 0x10000)
+#define SetAF(x,y,z) (nec_state->AuxVal = ((x) ^ ((y) ^ (z))) & 0x10)
+#define SetSF(x) (nec_state->SignVal = (x))
+#define SetZF(x) (nec_state->ZeroVal = (x))
+#define SetPF(x) (nec_state->ParityVal = (x))
+
+#define SetSZPF_Byte(x) (nec_state->SignVal=nec_state->ZeroVal=nec_state->ParityVal=(INT8)(x))
+#define SetSZPF_Word(x) (nec_state->SignVal=nec_state->ZeroVal=nec_state->ParityVal=(INT16)(x))
+
+#define SetOFW_Add(x,y,z) (nec_state->OverVal = ((x) ^ (y)) & ((x) ^ (z)) & 0x8000)
+#define SetOFB_Add(x,y,z) (nec_state->OverVal = ((x) ^ (y)) & ((x) ^ (z)) & 0x80)
+#define SetOFW_Sub(x,y,z) (nec_state->OverVal = ((z) ^ (y)) & ((z) ^ (x)) & 0x8000)
+#define SetOFB_Sub(x,y,z) (nec_state->OverVal = ((z) ^ (y)) & ((z) ^ (x)) & 0x80)
+
+#define ADDB { UINT32 res=dst+src; SetCFB(res); SetOFB_Add(res,src,dst); SetAF(res,src,dst); SetSZPF_Byte(res); dst=(BYTE)res; }
+#define ADDW { UINT32 res=dst+src; SetCFW(res); SetOFW_Add(res,src,dst); SetAF(res,src,dst); SetSZPF_Word(res); dst=(WORD)res; }
+
+#define SUBB { UINT32 res=dst-src; SetCFB(res); SetOFB_Sub(res,src,dst); SetAF(res,src,dst); SetSZPF_Byte(res); dst=(BYTE)res; }
+#define SUBW { UINT32 res=dst-src; SetCFW(res); SetOFW_Sub(res,src,dst); SetAF(res,src,dst); SetSZPF_Word(res); dst=(WORD)res; }
+
+#define ORB dst|=src; nec_state->CarryVal=nec_state->OverVal=nec_state->AuxVal=0; SetSZPF_Byte(dst)
+#define ORW dst|=src; nec_state->CarryVal=nec_state->OverVal=nec_state->AuxVal=0; SetSZPF_Word(dst)
+
+#define ANDB dst&=src; nec_state->CarryVal=nec_state->OverVal=nec_state->AuxVal=0; SetSZPF_Byte(dst)
+#define ANDW dst&=src; nec_state->CarryVal=nec_state->OverVal=nec_state->AuxVal=0; SetSZPF_Word(dst)
+
+#define XORB dst^=src; nec_state->CarryVal=nec_state->OverVal=nec_state->AuxVal=0; SetSZPF_Byte(dst)
+#define XORW dst^=src; nec_state->CarryVal=nec_state->OverVal=nec_state->AuxVal=0; SetSZPF_Word(dst)
+
+#define IncWordReg(Reg) \
+ unsigned tmp = (unsigned)Wreg(Reg); \
+ unsigned tmp1 = tmp+1; \
+ nec_state->OverVal = (tmp == 0x7fff); \
+ SetAF(tmp1,tmp,1); \
+ SetSZPF_Word(tmp1); \
+ Wreg(Reg)=tmp1
+
+#define DecWordReg(Reg) \
+ unsigned tmp = (unsigned)Wreg(Reg); \
+ unsigned tmp1 = tmp-1; \
+ nec_state->OverVal = (tmp == 0x8000); \
+ SetAF(tmp1,tmp,1); \
+ SetSZPF_Word(tmp1); \
+ Wreg(Reg)=tmp1
+
+#define JMP(flag) \
+ int tmp; \
+ EMPTY_PREFETCH(); \
+ tmp = (int)((INT8)FETCH()); \
+ if (flag) \
+ { \
+ static const UINT8 table[3]={3,10,10}; \
+ nec_state->ip = (WORD)(nec_state->ip+tmp); \
+ nec_state->icount-=table[nec_state->chip_type/8]; \
+ CHANGE_PC; \
+ return; \
+ }
+
+#define ADJ4(param1,param2) \
+ if (AF || ((Breg(AL) & 0xf) > 9)) \
+ { \
+ UINT16 tmp; \
+ tmp = Breg(AL) + param1; \
+ Breg(AL) = tmp; \
+ nec_state->AuxVal = 1; \
+ nec_state->CarryVal |= tmp & 0x100; \
+ } \
+ if (CF || (Breg(AL)>0x9f)) \
+ { \
+ Breg(AL) += param2; \
+ nec_state->CarryVal = 1; \
+ } \
+ SetSZPF_Byte(Breg(AL))
+
+#define ADJB(param1,param2) \
+ if (AF || ((Breg(AL) & 0xf) > 9)) \
+ { \
+ Breg(AL) += param1; \
+ Breg(AH) += param2; \
+ nec_state->AuxVal = 1; \
+ nec_state->CarryVal = 1; \
+ } \
+ else \
+ { \
+ nec_state->AuxVal = 0; \
+ nec_state->CarryVal = 0; \
+ } \
+ Breg(AL) &= 0x0F
+
+#define BITOP_BYTE \
+ ModRM = FETCH(); \
+ if (ModRM >= 0xc0) { \
+ tmp=Breg(Mod_RM.RM.b[ModRM]); \
+ } \
+ else { \
+ (*GetEA[ModRM])(nec_state); \
+ tmp=read_mem_byte(EA); \
+ }
+
+#define BITOP_WORD \
+ ModRM = FETCH(); \
+ if (ModRM >= 0xc0) { \
+ tmp=Wreg(Mod_RM.RM.w[ModRM]); \
+ } \
+ else { \
+ (*GetEA[ModRM])(nec_state); \
+ tmp=read_mem_word(EA); \
+ }
+
+#define BIT_NOT \
+ if (tmp & (1<<tmp2)) \
+ tmp &= ~(1<<tmp2); \
+ else \
+ tmp |= (1<<tmp2)
+
+#define XchgAWReg(Reg) \
+ WORD tmp; \
+ tmp = Wreg(Reg); \
+ Wreg(Reg) = Wreg(AW); \
+ Wreg(AW) = tmp
+
+#define ROL_BYTE nec_state->CarryVal = dst & 0x80; dst = (dst << 1)+CF
+#define ROL_WORD nec_state->CarryVal = dst & 0x8000; dst = (dst << 1)+CF
+#define ROR_BYTE nec_state->CarryVal = dst & 0x1; dst = (dst >> 1)+(CF<<7)
+#define ROR_WORD nec_state->CarryVal = dst & 0x1; dst = (dst >> 1)+(CF<<15)
+#define ROLC_BYTE dst = (dst << 1) + CF; SetCFB(dst)
+#define ROLC_WORD dst = (dst << 1) + CF; SetCFW(dst)
+#define RORC_BYTE dst = (CF<<8)+dst; nec_state->CarryVal = dst & 0x01; dst >>= 1
+#define RORC_WORD dst = (CF<<16)+dst; nec_state->CarryVal = dst & 0x01; dst >>= 1
+#define SHL_BYTE(c) nec_state->icount-=c; dst <<= c; SetCFB(dst); SetSZPF_Byte(dst); PutbackRMByte(ModRM,(BYTE)dst)
+#define SHL_WORD(c) nec_state->icount-=c; dst <<= c; SetCFW(dst); SetSZPF_Word(dst); PutbackRMWord(ModRM,(WORD)dst)
+#define SHR_BYTE(c) nec_state->icount-=c; dst >>= c-1; nec_state->CarryVal = dst & 0x1; dst >>= 1; SetSZPF_Byte(dst); PutbackRMByte(ModRM,(BYTE)dst)
+#define SHR_WORD(c) nec_state->icount-=c; dst >>= c-1; nec_state->CarryVal = dst & 0x1; dst >>= 1; SetSZPF_Word(dst); PutbackRMWord(ModRM,(WORD)dst)
+#define SHRA_BYTE(c) nec_state->icount-=c; dst = ((INT8)dst) >> (c-1); nec_state->CarryVal = dst & 0x1; dst = ((INT8)((BYTE)dst)) >> 1; SetSZPF_Byte(dst); PutbackRMByte(ModRM,(BYTE)dst)
+#define SHRA_WORD(c) nec_state->icount-=c; dst = ((INT16)dst) >> (c-1); nec_state->CarryVal = dst & 0x1; dst = ((INT16)((WORD)dst)) >> 1; SetSZPF_Word(dst); PutbackRMWord(ModRM,(WORD)dst)
+
+#define DIVUB \
+ uresult = Wreg(AW); \
+ uresult2 = uresult % tmp; \
+ if ((uresult /= tmp) > 0xff) { \
+ nec_interrupt(nec_state, NEC_DIVIDE_VECTOR, BRK); break; \
+ } else { \
+ Breg(AL) = uresult; \
+ Breg(AH) = uresult2; \
+ }
+
+#define DIVB \
+ result = (INT16)Wreg(AW); \
+ result2 = result % (INT16)((INT8)tmp); \
+ if ((result /= (INT16)((INT8)tmp)) > 0xff) { \
+ nec_interrupt(nec_state, NEC_DIVIDE_VECTOR, BRK); break; \
+ } else { \
+ Breg(AL) = result; \
+ Breg(AH) = result2; \
+ }
+
+#define DIVUW \
+ uresult = (((UINT32)Wreg(DW)) << 16) | Wreg(AW);\
+ uresult2 = uresult % tmp; \
+ if ((uresult /= tmp) > 0xffff) { \
+ nec_interrupt(nec_state, NEC_DIVIDE_VECTOR, BRK); break; \
+ } else { \
+ Wreg(AW)=uresult; \
+ Wreg(DW)=uresult2; \
+ }
+
+#define DIVW \
+ result = ((UINT32)Wreg(DW) << 16) + Wreg(AW); \
+ result2 = result % (INT32)((INT16)tmp); \
+ if ((result /= (INT32)((INT16)tmp)) > 0xffff) { \
+ nec_interrupt(nec_state, NEC_DIVIDE_VECTOR, BRK); break; \
+ } else { \
+ Wreg(AW)=result; \
+ Wreg(DW)=result2; \
+ }
+
+#define ADD4S { \
+ int i,v1,v2,result; \
+ int count = (Breg(CL)+1)/2; \
+ unsigned di = Wreg(IY); \
+ unsigned si = Wreg(IX); \
+ static const UINT8 table[3]={18,19,19}; \
+ if (nec_state->seg_prefix) logerror("%06x: Warning: seg_prefix defined for add4s\n",PC(nec_state)); \
+ nec_state->ZeroVal = nec_state->CarryVal = 0; \
+ for (i=0;i<count;i++) { \
+ nec_state->icount-=table[nec_state->chip_type/8]; \
+ tmp = GetMemB(DS0, si); \
+ tmp2 = GetMemB(DS1, di); \
+ v1 = (tmp>>4)*10 + (tmp&0xf); \
+ v2 = (tmp2>>4)*10 + (tmp2&0xf); \
+ result = v1+v2+nec_state->CarryVal; \
+ nec_state->CarryVal = result > 99 ? 1 : 0; \
+ result = result % 100; \
+ v1 = ((result/10)<<4) | (result % 10); \
+ PutMemB(DS1, di,v1); \
+ if (v1) nec_state->ZeroVal = 1; \
+ si++; \
+ di++; \
+ } \
+}
+
+#define SUB4S { \
+ int count = (Breg(CL)+1)/2; \
+ int i,v1,v2,result; \
+ unsigned di = Wreg(IY); \
+ unsigned si = Wreg(IX); \
+ static const UINT8 table[3]={18,19,19}; \
+ if (nec_state->seg_prefix) logerror("%06x: Warning: seg_prefix defined for sub4s\n",PC(nec_state)); \
+ nec_state->ZeroVal = nec_state->CarryVal = 0; \
+ for (i=0;i<count;i++) { \
+ nec_state->icount-=table[nec_state->chip_type/8]; \
+ tmp = GetMemB(DS1, di); \
+ tmp2 = GetMemB(DS0, si); \
+ v1 = (tmp>>4)*10 + (tmp&0xf); \
+ v2 = (tmp2>>4)*10 + (tmp2&0xf); \
+ if (v1 < (v2+nec_state->CarryVal)) { \
+ v1+=100; \
+ result = v1-(v2+nec_state->CarryVal); \
+ nec_state->CarryVal = 1; \
+ } else { \
+ result = v1-(v2+nec_state->CarryVal); \
+ nec_state->CarryVal = 0; \
+ } \
+ v1 = ((result/10)<<4) | (result % 10); \
+ PutMemB(DS1, di,v1); \
+ if (v1) nec_state->ZeroVal = 1; \
+ si++; \
+ di++; \
+ } \
+}
+
+#define CMP4S { \
+ int count = (Breg(CL)+1)/2; \
+ int i,v1,v2,result; \
+ unsigned di = Wreg(IY); \
+ unsigned si = Wreg(IX); \
+ static const UINT8 table[3]={14,19,19}; \
+ if (nec_state->seg_prefix) logerror("%06x: Warning: seg_prefix defined for cmp4s\n",PC(nec_state)); \
+ nec_state->ZeroVal = nec_state->CarryVal = 0; \
+ for (i=0;i<count;i++) { \
+ nec_state->icount-=table[nec_state->chip_type/8]; \
+ tmp = GetMemB(DS1, di); \
+ tmp2 = GetMemB(DS0, si); \
+ v1 = (tmp>>4)*10 + (tmp&0xf); \
+ v2 = (tmp2>>4)*10 + (tmp2&0xf); \
+ if (v1 < (v2+nec_state->CarryVal)) { \
+ v1+=100; \
+ result = v1-(v2+nec_state->CarryVal); \
+ nec_state->CarryVal = 1; \
+ } else { \
+ result = v1-(v2+nec_state->CarryVal); \
+ nec_state->CarryVal = 0; \
+ } \
+ v1 = ((result/10)<<4) | (result % 10); \
+ if (v1) nec_state->ZeroVal = 1; \
+ si++; \
+ di++; \
+ } \
+}
diff --git a/trunk/src/emu/cpu/nec/necmodrm.h b/trunk/src/emu/cpu/nec/necmodrm.h
new file mode 100644
index 00000000000..cf8956b8106
--- /dev/null
+++ b/trunk/src/emu/cpu/nec/necmodrm.h
@@ -0,0 +1,104 @@
+static struct {
+ struct {
+ WREGS w[256];
+ BREGS b[256];
+ } reg;
+ struct {
+ WREGS w[256];
+ BREGS b[256];
+ } RM;
+} Mod_RM;
+
+#define RegWord(ModRM) Wreg(Mod_RM.reg.w[ModRM])
+#define RegByte(ModRM) Breg(Mod_RM.reg.b[ModRM])
+
+#define GetRMWord(ModRM) \
+ ((ModRM) >= 0xc0 ? Wreg(Mod_RM.RM.w[ModRM]) : ( (*GetEA[ModRM])(nec_state), read_mem_word( EA ) ))
+
+#define PutbackRMWord(ModRM,val) \
+{ \
+ if (ModRM >= 0xc0) Wreg(Mod_RM.RM.w[ModRM])=val; \
+ else write_mem_word(EA,val); \
+}
+
+#define GetnextRMWord read_mem_word((EA&0xf0000)|((EA+2)&0xffff))
+
+#define PutRMWord(ModRM,val) \
+{ \
+ if (ModRM >= 0xc0) \
+ Wreg(Mod_RM.RM.w[ModRM])=val; \
+ else { \
+ (*GetEA[ModRM])(nec_state); \
+ write_mem_word( EA ,val); \
+ } \
+}
+
+#define PutImmRMWord(ModRM) \
+{ \
+ WORD val; \
+ if (ModRM >= 0xc0) \
+ Wreg(Mod_RM.RM.w[ModRM]) = FETCHWORD(); \
+ else { \
+ (*GetEA[ModRM])(nec_state); \
+ val = FETCHWORD(); \
+ write_mem_word( EA , val); \
+ } \
+}
+
+#define GetRMByte(ModRM) \
+ ((ModRM) >= 0xc0 ? Breg(Mod_RM.RM.b[ModRM]) : read_mem_byte( (*GetEA[ModRM])(nec_state) ))
+
+#define PutRMByte(ModRM,val) \
+{ \
+ if (ModRM >= 0xc0) \
+ Breg(Mod_RM.RM.b[ModRM])=val; \
+ else \
+ write_mem_byte( (*GetEA[ModRM])(nec_state) ,val); \
+}
+
+#define PutImmRMByte(ModRM) \
+{ \
+ if (ModRM >= 0xc0) \
+ Breg(Mod_RM.RM.b[ModRM])=FETCH(); \
+ else { \
+ (*GetEA[ModRM])(nec_state); \
+ write_mem_byte( EA , FETCH() ); \
+ } \
+}
+
+#define PutbackRMByte(ModRM,val) \
+{ \
+ if (ModRM >= 0xc0) \
+ Breg(Mod_RM.RM.b[ModRM])=val; \
+ else \
+ write_mem_byte(EA,val); \
+}
+
+#define DEF_br8 \
+ UINT32 ModRM = FETCH(),src,dst; \
+ src = RegByte(ModRM); \
+ dst = GetRMByte(ModRM)
+
+#define DEF_wr16 \
+ UINT32 ModRM = FETCH(),src,dst; \
+ src = RegWord(ModRM); \
+ dst = GetRMWord(ModRM)
+
+#define DEF_r8b \
+ UINT32 ModRM = FETCH(),src,dst; \
+ dst = RegByte(ModRM); \
+ src = GetRMByte(ModRM)
+
+#define DEF_r16w \
+ UINT32 ModRM = FETCH(),src,dst; \
+ dst = RegWord(ModRM); \
+ src = GetRMWord(ModRM)
+
+#define DEF_ald8 \
+ UINT32 src = FETCH(); \
+ UINT32 dst = Breg(AL)
+
+#define DEF_axd16 \
+ UINT32 src = FETCH(); \
+ UINT32 dst = Wreg(AW); \
+ src += (FETCH() << 8)
diff --git a/trunk/src/emu/cpu/nec/necpriv.h b/trunk/src/emu/cpu/nec/necpriv.h
new file mode 100644
index 00000000000..ae27a451f9c
--- /dev/null
+++ b/trunk/src/emu/cpu/nec/necpriv.h
@@ -0,0 +1,174 @@
+/* Cpu types, steps of 8 to help the cycle count calculation */
+#define V33_TYPE 0
+#define V30_TYPE 8
+#define V20_TYPE 16
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE 1
+#endif
+
+/* interrupt vectors */
+enum
+{
+ NEC_DIVIDE_VECTOR = 0,
+ NEC_TRAP_VECTOR = 1,
+ NEC_NMI_VECTOR = 2,
+ NEC_BRKV_VECTOR = 4,
+ NEC_CHKIND_VECTOR = 5,
+};
+
+/* interrupt sources */
+typedef enum
+{
+ BRK = 0,
+ INT_IRQ = 1,
+ NMI_IRQ = 2,
+} INTSOURCES;
+
+/* NEC registers */
+typedef union
+{ /* eight general registers */
+ UINT16 w[8]; /* viewed as 16 bits registers */
+ UINT8 b[16]; /* or as 8 bit registers */
+} necbasicregs;
+
+typedef struct _nec_state_t nec_state_t;
+struct _nec_state_t
+{
+ necbasicregs regs;
+ offs_t fetch_xor;
+ UINT16 sregs[4];
+
+ UINT16 ip;
+
+ /* PSW flags */
+ INT32 SignVal;
+ UINT32 AuxVal, OverVal, ZeroVal, CarryVal, ParityVal; /* 0 or non-0 valued flags */
+ UINT8 TF, IF, DF, MF; /* 0 or 1 valued flags */
+
+ /* interrupt related */
+ UINT32 pending_irq;
+ UINT32 nmi_state;
+ UINT32 irq_state;
+ UINT32 poll_state;
+ UINT8 no_interrupt;
+ UINT8 halted;
+
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ address_space *io;
+ int icount;
+
+ UINT8 prefetch_size;
+ UINT8 prefetch_cycles;
+ INT8 prefetch_count;
+ UINT8 prefetch_reset;
+ UINT32 chip_type;
+
+ UINT32 prefix_base; /* base address of the latest prefix segment */
+ UINT8 seg_prefix; /* prefix segment indicator */
+};
+
+typedef enum { DS1, PS, SS, DS0 } SREGS;
+typedef enum { AW, CW, DW, BW, SP, BP, IX, IY } WREGS;
+typedef enum {
+ AL = NATIVE_ENDIAN_VALUE_LE_BE(0x0, 0x1),
+ AH = NATIVE_ENDIAN_VALUE_LE_BE(0x1, 0x0),
+ CL = NATIVE_ENDIAN_VALUE_LE_BE(0x2, 0x3),
+ CH = NATIVE_ENDIAN_VALUE_LE_BE(0x3, 0x2),
+ DL = NATIVE_ENDIAN_VALUE_LE_BE(0x4, 0x5),
+ DH = NATIVE_ENDIAN_VALUE_LE_BE(0x5, 0x4),
+ BL = NATIVE_ENDIAN_VALUE_LE_BE(0x6, 0x7),
+ BH = NATIVE_ENDIAN_VALUE_LE_BE(0x7, 0x6),
+} BREGS;
+
+#define Sreg(x) nec_state->sregs[x]
+#define Wreg(x) nec_state->regs.w[x]
+#define Breg(x) nec_state->regs.b[x]
+
+#define PC(n) ((Sreg(PS)<<4)+(n)->ip)
+
+#define CF (nec_state->CarryVal!=0)
+#define SF (nec_state->SignVal<0)
+#define ZF (nec_state->ZeroVal==0)
+#define PF parity_table[(BYTE)nec_state->ParityVal]
+#define AF (nec_state->AuxVal!=0)
+#define OF (nec_state->OverVal!=0)
+
+/************************************************************************/
+
+#define read_mem_byte(a) nec_state->program->read_byte(a)
+#define read_mem_word(a) nec_state->program->read_word_unaligned(a)
+#define write_mem_byte(a,d) nec_state->program->write_byte((a),(d))
+#define write_mem_word(a,d) nec_state->program->write_word_unaligned((a),(d))
+
+#define read_port_byte(a) nec_state->io->read_byte(a)
+#define read_port_word(a) nec_state->io->read_word_unaligned(a)
+#define write_port_byte(a,d) nec_state->io->write_byte((a),(d))
+#define write_port_word(a,d) nec_state->io->write_word_unaligned((a),(d))
+
+/************************************************************************/
+
+#define CHANGE_PC do { EMPTY_PREFETCH(); } while (0)
+
+#define SegBase(Seg) (Sreg(Seg) << 4)
+
+#define DefaultBase(Seg) ((nec_state->seg_prefix && (Seg==DS0 || Seg==SS)) ? nec_state->prefix_base : Sreg(Seg) << 4)
+
+#define GetMemB(Seg,Off) (read_mem_byte(DefaultBase(Seg) + (Off)))
+#define GetMemW(Seg,Off) (read_mem_word(DefaultBase(Seg) + (Off)))
+
+#define PutMemB(Seg,Off,x) { write_mem_byte(DefaultBase(Seg) + (Off), (x)); }
+#define PutMemW(Seg,Off,x) { write_mem_word(DefaultBase(Seg) + (Off), (x)); }
+
+/* prefetch timing */
+
+#define FETCH() fetch(nec_state)
+#define FETCHWORD() fetchword(nec_state)
+#define EMPTY_PREFETCH() nec_state->prefetch_reset = 1
+
+
+#define PUSH(val) { Wreg(SP) -= 2; write_mem_word(((Sreg(SS)<<4)+Wreg(SP)), val); }
+#define POP(var) { Wreg(SP) += 2; var = read_mem_word(((Sreg(SS)<<4) + ((Wreg(SP)-2) & 0xffff))); }
+
+#define GetModRM UINT32 ModRM=FETCH()
+
+/* Cycle count macros:
+ CLK - cycle count is the same on all processors
+ CLKS - cycle count differs between processors, list all counts
+ CLKW - cycle count for word read/write differs for odd/even source/destination address
+ CLKM - cycle count for reg/mem instructions
+ CLKR - cycle count for reg/mem instructions with different counts for odd/even addresses
+
+
+ Prefetch & buswait time is not emulated.
+ Extra cycles for PUSH'ing or POP'ing registers to odd addresses is not emulated.
+*/
+
+#define CLK(all) nec_state->icount-=all
+#define CLKS(v20,v30,v33) { const UINT32 ccount=(v20<<16)|(v30<<8)|v33; nec_state->icount-=(ccount>>nec_state->chip_type)&0x7f; }
+#define CLKW(v20o,v30o,v33o,v20e,v30e,v33e,addr) { const UINT32 ocount=(v20o<<16)|(v30o<<8)|v33o, ecount=(v20e<<16)|(v30e<<8)|v33e; nec_state->icount-=(addr&1)?((ocount>>nec_state->chip_type)&0x7f):((ecount>>nec_state->chip_type)&0x7f); }
+#define CLKM(v20,v30,v33,v20m,v30m,v33m) { const UINT32 ccount=(v20<<16)|(v30<<8)|v33, mcount=(v20m<<16)|(v30m<<8)|v33m; nec_state->icount-=( ModRM >=0xc0 )?((ccount>>nec_state->chip_type)&0x7f):((mcount>>nec_state->chip_type)&0x7f); }
+#define CLKR(v20o,v30o,v33o,v20e,v30e,v33e,vall,addr) { const UINT32 ocount=(v20o<<16)|(v30o<<8)|v33o, ecount=(v20e<<16)|(v30e<<8)|v33e; if (ModRM >=0xc0) nec_state->icount-=vall; else nec_state->icount-=(addr&1)?((ocount>>nec_state->chip_type)&0x7f):((ecount>>nec_state->chip_type)&0x7f); }
+
+/************************************************************************/
+#define CompressFlags() (WORD)(int(CF) | 0x02 | (int(PF) << 2) | (int(AF) << 4) | (int(ZF) << 6) \
+ | (int(SF) << 7) | (nec_state->TF << 8) | (nec_state->IF << 9) \
+ | (nec_state->DF << 10) | (int(OF) << 11) | 0x7000 | (nec_state->MF << 15))
+
+#define ExpandFlags(f) \
+{ \
+ nec_state->CarryVal = (f) & 0x0001; \
+ nec_state->ParityVal = !((f) & 0x0004); \
+ nec_state->AuxVal = (f) & 0x0010; \
+ nec_state->ZeroVal = !((f) & 0x0040); \
+ nec_state->SignVal = (f) & 0x0080 ? -1 : 0; \
+ nec_state->TF = ((f) & 0x0100) == 0x0100; \
+ nec_state->IF = ((f) & 0x0200) == 0x0200; \
+ nec_state->DF = ((f) & 0x0400) == 0x0400; \
+ nec_state->OverVal = (f) & 0x0800; \
+ nec_state->MF = ((f) & 0x8000) == 0x8000; \
+}
diff --git a/trunk/src/emu/cpu/nec/v25.c b/trunk/src/emu/cpu/nec/v25.c
new file mode 100644
index 00000000000..039bba02b56
--- /dev/null
+++ b/trunk/src/emu/cpu/nec/v25.c
@@ -0,0 +1,805 @@
+/****************************************************************************
+
+ NEC V25/V35 emulator
+
+ ---------------------------------------------
+
+ TODO:
+
+ Using V20/V30 cycle counts for now. V25/V35 cycle counts
+ vary based on whether internal RAM access is enabled (RAMEN).
+ Likewise, the programmable clock divider (PCK) currently only
+ affects the timers, not instruction execution.
+
+ BTCLR and STOP instructions not implemented.
+
+ IBRK flag (trap I/O instructions) not implemented.
+
+ Interrupt macro service function not implemented.
+
+ Port implementation is incomplete: mode control registers are ignored.
+
+ Timer implementation is incomplete: polling is not implemented
+ (reading any of the registers just returns the last value written)
+
+ Serial interface and DMA functions not implemented.
+ Note that these functions differ considerably between
+ the V25/35 and the V25+/35+.
+
+ Make internal RAM into a real RAM region, and use an
+ internal address map (remapped when IDB is written to)
+ instead of memory access wrapper functions.
+ That way the internal RAM would be visible to the debugger,
+ among other benefits.
+
+****************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+
+typedef UINT8 BOOLEAN;
+typedef UINT8 BYTE;
+typedef UINT16 WORD;
+typedef UINT32 DWORD;
+
+#include "nec.h"
+#include "v25priv.h"
+
+/* default configuration */
+static const nec_config default_config =
+{
+ NULL
+};
+
+extern int necv_dasm_one(char *buffer, UINT32 eip, const UINT8 *oprom, const nec_config *config);
+
+INLINE v25_state_t *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == V25 || device->type() == V35);
+ return (v25_state_t *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+static TIMER_CALLBACK(v25_timer_callback)
+{
+ v25_state_t *nec_state = (v25_state_t *)ptr;
+ nec_state->pending_irq |= param;
+}
+
+INLINE void prefetch(v25_state_t *nec_state)
+{
+ nec_state->prefetch_count--;
+}
+
+static void do_prefetch(v25_state_t *nec_state, int previous_ICount)
+{
+ int diff = previous_ICount - (int) nec_state->icount;
+
+ /* The implementation is not accurate, but comes close.
+ * It does not respect that the V30 will fetch two bytes
+ * at once directly, but instead uses only 2 cycles instead
+ * of 4. There are however only very few sources publicly
+ * available and they are vague.
+ */
+ while (nec_state->prefetch_count<0)
+ {
+ nec_state->prefetch_count++;
+ if (diff>nec_state->prefetch_cycles)
+ diff -= nec_state->prefetch_cycles;
+ else
+ nec_state->icount -= nec_state->prefetch_cycles;
+ }
+
+ if (nec_state->prefetch_reset)
+ {
+ nec_state->prefetch_count = 0;
+ nec_state->prefetch_reset = 0;
+ return;
+ }
+
+ while (diff>=nec_state->prefetch_cycles && nec_state->prefetch_count < nec_state->prefetch_size)
+ {
+ diff -= nec_state->prefetch_cycles;
+ nec_state->prefetch_count++;
+ }
+
+}
+
+INLINE UINT8 fetch(v25_state_t *nec_state)
+{
+ prefetch(nec_state);
+ return nec_state->direct->read_raw_byte((Sreg(PS)<<4)+nec_state->ip++, nec_state->fetch_xor);
+}
+
+INLINE UINT16 fetchword(v25_state_t *nec_state)
+{
+ UINT16 r = FETCH();
+ r |= (FETCH()<<8);
+ return r;
+}
+
+#define nec_state_t v25_state_t
+
+#include "v25instr.h"
+#include "necmacro.h"
+#include "necea.h"
+#include "necmodrm.h"
+
+static UINT8 parity_table[256];
+
+static UINT8 fetchop(v25_state_t *nec_state)
+{
+ UINT8 ret;
+
+ prefetch(nec_state);
+ ret = nec_state->direct->read_decrypted_byte(( Sreg(PS)<<4)+nec_state->ip++, nec_state->fetch_xor);
+
+ if (nec_state->MF == 0)
+ if (nec_state->config->v25v35_decryptiontable)
+ {
+ ret = nec_state->config->v25v35_decryptiontable[ret];
+ }
+ return ret;
+}
+
+
+
+/***************************************************************************/
+
+static CPU_RESET( v25 )
+{
+ v25_state_t *nec_state = get_safe_token(device);
+ int tmp;
+ attotime time;
+
+ nec_state->ip = 0;
+ nec_state->IBRK = 1;
+ nec_state->F0 = 0;
+ nec_state->F1 = 0;
+ nec_state->TF = 0;
+ nec_state->IF = 0;
+ nec_state->DF = 0;
+ nec_state->SignVal = 0;
+ nec_state->AuxVal = 0;
+ nec_state->OverVal = 0;
+ nec_state->ZeroVal = 1;
+ nec_state->CarryVal = 0;
+ nec_state->ParityVal = 1;
+ nec_state->pending_irq = 0;
+ nec_state->unmasked_irq = INT_IRQ | NMI_IRQ;
+ nec_state->bankswitch_irq = 0;
+ nec_state->priority_inttu = 7;
+ nec_state->priority_intd = 7;
+ nec_state->priority_intp = 7;
+ nec_state->priority_ints0 = 7;
+ nec_state->priority_ints1 = 7;
+ nec_state->IRQS = nec_state->ISPR = 0;
+ nec_state->nmi_state = 0;
+ nec_state->irq_state = 0;
+ nec_state->poll_state = 1;
+ nec_state->mode_state = nec_state->MF = (nec_state->config->v25v35_decryptiontable) ? 0 : 1;
+ nec_state->intp_state[0] = 0;
+ nec_state->intp_state[1] = 0;
+ nec_state->intp_state[2] = 0;
+ nec_state->halted = 0;
+
+ nec_state->TM0 = nec_state->MD0 = nec_state->TM1 = nec_state->MD1 = 0;
+ nec_state->TMC0 = nec_state->TMC1 = 0;
+
+ nec_state->RAMEN = 1;
+ nec_state->TB = 20;
+ nec_state->PCK = 8;
+ nec_state->IDB = 0xFFE00;
+
+ tmp = nec_state->PCK << nec_state->TB;
+ time = attotime::from_hz(nec_state->device->unscaled_clock()) * tmp;
+ nec_state->timers[3]->adjust(time, INTTB, time);
+
+ nec_state->timers[0]->adjust(attotime::never);
+ nec_state->timers[1]->adjust(attotime::never);
+ nec_state->timers[2]->adjust(attotime::never);
+
+ SetRB(7);
+ Sreg(PS) = 0xffff;
+ Sreg(SS) = 0;
+ Sreg(DS0) = 0;
+ Sreg(DS1) = 0;
+
+ CHANGE_PC;
+}
+
+static CPU_EXIT( v25 )
+{
+
+}
+
+static void nec_interrupt(v25_state_t *nec_state, unsigned int_num, INTSOURCES source)
+{
+ UINT32 dest_seg, dest_off;
+
+ i_pushf(nec_state);
+ nec_state->TF = nec_state->IF = 0;
+ nec_state->MF = nec_state->mode_state;
+
+ switch(source)
+ {
+ case BRKN: /* force native mode */
+ nec_state->MF = 1;
+ break;
+ case BRKS: /* force secure mode */
+ if (nec_state->config->v25v35_decryptiontable)
+ nec_state->MF = 0;
+ else
+ logerror("%06x: BRKS executed with no decryption table\n",PC(nec_state));
+ break;
+ case INT_IRQ: /* get vector */
+ int_num = (*nec_state->irq_callback)(nec_state->device, 0);
+ break;
+ default:
+ break;
+ }
+
+ dest_off = read_mem_word(int_num*4);
+ dest_seg = read_mem_word(int_num*4+2);
+
+ PUSH(Sreg(PS));
+ PUSH(nec_state->ip);
+ nec_state->ip = (WORD)dest_off;
+ Sreg(PS) = (WORD)dest_seg;
+ CHANGE_PC;
+}
+
+static void nec_bankswitch(v25_state_t *nec_state, unsigned bank_num)
+{
+ int tmp = CompressFlags();
+
+ nec_state->TF = nec_state->IF = 0;
+ nec_state->MF = nec_state->mode_state;
+
+ SetRB(bank_num);
+
+ Wreg(PSW_SAVE) = tmp;
+ Wreg(PC_SAVE) = nec_state->ip;
+ nec_state->ip = Wreg(VECTOR_PC);
+ CHANGE_PC;
+}
+
+static void nec_trap(v25_state_t *nec_state)
+{
+ nec_instruction[fetchop(nec_state)](nec_state);
+ nec_interrupt(nec_state, NEC_TRAP_VECTOR, BRK);
+}
+
+#define INTERRUPT(source, vector, priority) \
+ if(pending & (source)) { \
+ nec_state->IRQS = vector; \
+ nec_state->ISPR |= (1 << (priority)); \
+ nec_state->pending_irq &= ~(source); \
+ if(nec_state->bankswitch_irq & (source)) \
+ nec_bankswitch(nec_state, priority); \
+ else \
+ nec_interrupt(nec_state, vector, source); \
+ break; /* break out of loop */ \
+ }
+
+/* interrupt sources subject to priority control */
+#define SOURCES (INTTU0 | INTTU1 | INTTU2 | INTD0 | INTD1 | INTP0 | INTP1 | INTP2 \
+ | INTSER0 | INTSR0 | INTST0 | INTSER1 | INTSR1 | INTST1 | INTTB)
+
+static void external_int(v25_state_t *nec_state)
+{
+ int pending = nec_state->pending_irq & nec_state->unmasked_irq;
+
+ if (pending & NMI_IRQ)
+ {
+ nec_interrupt(nec_state, NEC_NMI_VECTOR, NMI_IRQ);
+ nec_state->pending_irq &= ~NMI_IRQ;
+ }
+ else if (pending & SOURCES)
+ {
+ for(int i = 0; i < 8; i++)
+ {
+ if (nec_state->ISPR & (1 << i)) break;
+
+ if (nec_state->priority_inttu == i)
+ {
+ INTERRUPT(INTTU0, NEC_INTTU0_VECTOR, i)
+ INTERRUPT(INTTU1, NEC_INTTU1_VECTOR, i)
+ INTERRUPT(INTTU2, NEC_INTTU2_VECTOR, i)
+ }
+
+ if (nec_state->priority_intd == i)
+ {
+ INTERRUPT(INTD0, NEC_INTD0_VECTOR, i)
+ INTERRUPT(INTD1, NEC_INTD1_VECTOR, i)
+ }
+
+ if (nec_state->priority_intp == i)
+ {
+ INTERRUPT(INTP0, NEC_INTP0_VECTOR, i)
+ INTERRUPT(INTP1, NEC_INTP1_VECTOR, i)
+ INTERRUPT(INTP2, NEC_INTP2_VECTOR, i)
+ }
+
+ if (nec_state->priority_ints0 == i)
+ {
+ INTERRUPT(INTSER0, NEC_INTSER0_VECTOR, i)
+ INTERRUPT(INTSR0, NEC_INTSR0_VECTOR, i)
+ INTERRUPT(INTST0, NEC_INTST0_VECTOR, i)
+ }
+
+ if (nec_state->priority_ints1 == i)
+ {
+ INTERRUPT(INTSER1, NEC_INTSER1_VECTOR, i)
+ INTERRUPT(INTSR1, NEC_INTSR1_VECTOR, i)
+ INTERRUPT(INTST1, NEC_INTST1_VECTOR, i)
+ }
+
+ if (i == 7)
+ INTERRUPT(INTTB, NEC_INTTB_VECTOR, 7)
+ }
+ }
+ else if (pending & INT_IRQ)
+ {
+ /* the actual vector is retrieved after pushing flags */
+ /* and clearing the IF */
+ nec_interrupt(nec_state, (UINT32)-1, INT_IRQ);
+ nec_state->irq_state = CLEAR_LINE;
+ nec_state->pending_irq &= ~INT_IRQ;
+ }
+}
+
+/****************************************************************************/
+/* OPCODES */
+/****************************************************************************/
+
+#include "necinstr.c"
+#include "v25instr.c"
+
+/*****************************************************************************/
+
+static void set_irq_line(v25_state_t *nec_state, int irqline, int state)
+{
+ switch (irqline)
+ {
+ case 0:
+ nec_state->irq_state = state;
+ if (state == CLEAR_LINE)
+ nec_state->pending_irq &= ~INT_IRQ;
+ else
+ {
+ nec_state->pending_irq |= INT_IRQ;
+ nec_state->halted = 0;
+ }
+ break;
+ case INPUT_LINE_NMI:
+ if (nec_state->nmi_state == state) return;
+ nec_state->nmi_state = state;
+ if (state != CLEAR_LINE)
+ {
+ nec_state->pending_irq |= NMI_IRQ;
+ nec_state->halted = 0;
+ }
+ break;
+ case NEC_INPUT_LINE_INTP0:
+ case NEC_INPUT_LINE_INTP1:
+ case NEC_INPUT_LINE_INTP2:
+ irqline -= NEC_INPUT_LINE_INTP0;
+ if (nec_state->intp_state[irqline] == state) return;
+ nec_state->intp_state[irqline] = state;
+ if (state != CLEAR_LINE)
+ nec_state->pending_irq |= (INTP0 << irqline);
+ break;
+ case NEC_INPUT_LINE_POLL:
+ nec_state->poll_state = state;
+ break;
+ }
+}
+
+static CPU_DISASSEMBLE( v25 )
+{
+ v25_state_t *nec_state = get_safe_token(device);
+
+ return necv_dasm_one(buffer, pc, oprom, nec_state->config);
+}
+
+static void v25_init(legacy_cpu_device *device, device_irq_callback irqcallback)
+{
+ const nec_config *config = device->static_config() ? (const nec_config *)device->static_config() : &default_config;
+ v25_state_t *nec_state = get_safe_token(device);
+
+ unsigned int i, j, c;
+
+ static const WREGS wreg_name[8]={ AW, CW, DW, BW, SP, BP, IX, IY };
+ static const BREGS breg_name[8]={ AL, CL, DL, BL, AH, CH, DH, BH };
+
+ for (i = 0; i < 256; i++)
+ {
+ for (j = i, c = 0; j > 0; j >>= 1)
+ if (j & 1) c++;
+ parity_table[i] = !(c & 1);
+ }
+
+ for (i = 0; i < 256; i++)
+ {
+ Mod_RM.reg.b[i] = breg_name[(i & 0x38) >> 3];
+ Mod_RM.reg.w[i] = wreg_name[(i & 0x38) >> 3];
+ }
+
+ for (i = 0xc0; i < 0x100; i++)
+ {
+ Mod_RM.RM.w[i] = wreg_name[i & 7];
+ Mod_RM.RM.b[i] = breg_name[i & 7];
+ }
+
+ memset(nec_state, 0, sizeof(*nec_state));
+
+ nec_state->config = config;
+
+ for (i = 0; i < 4; i++)
+ nec_state->timers[i] = device->machine().scheduler().timer_alloc(FUNC(v25_timer_callback), nec_state);
+
+ device->save_item(NAME(nec_state->ram.w));
+ device->save_item(NAME(nec_state->intp_state));
+
+ device->save_item(NAME(nec_state->ip));
+ device->save_item(NAME(nec_state->IBRK));
+ device->save_item(NAME(nec_state->F0));
+ device->save_item(NAME(nec_state->F1));
+ device->save_item(NAME(nec_state->TF));
+ device->save_item(NAME(nec_state->IF));
+ device->save_item(NAME(nec_state->DF));
+ device->save_item(NAME(nec_state->MF));
+ device->save_item(NAME(nec_state->RBW));
+ device->save_item(NAME(nec_state->RBB));
+ device->save_item(NAME(nec_state->SignVal));
+ device->save_item(NAME(nec_state->AuxVal));
+ device->save_item(NAME(nec_state->OverVal));
+ device->save_item(NAME(nec_state->ZeroVal));
+ device->save_item(NAME(nec_state->CarryVal));
+ device->save_item(NAME(nec_state->ParityVal));
+ device->save_item(NAME(nec_state->pending_irq));
+ device->save_item(NAME(nec_state->unmasked_irq));
+ device->save_item(NAME(nec_state->bankswitch_irq));
+ device->save_item(NAME(nec_state->priority_inttu));
+ device->save_item(NAME(nec_state->priority_intd));
+ device->save_item(NAME(nec_state->priority_intp));
+ device->save_item(NAME(nec_state->priority_ints0));
+ device->save_item(NAME(nec_state->priority_ints1));
+ device->save_item(NAME(nec_state->IRQS));
+ device->save_item(NAME(nec_state->ISPR));
+ device->save_item(NAME(nec_state->nmi_state));
+ device->save_item(NAME(nec_state->irq_state));
+ device->save_item(NAME(nec_state->poll_state));
+ device->save_item(NAME(nec_state->mode_state));
+ device->save_item(NAME(nec_state->halted));
+ device->save_item(NAME(nec_state->TM0));
+ device->save_item(NAME(nec_state->MD0));
+ device->save_item(NAME(nec_state->TM1));
+ device->save_item(NAME(nec_state->MD1));
+ device->save_item(NAME(nec_state->TMC0));
+ device->save_item(NAME(nec_state->TMC1));
+ device->save_item(NAME(nec_state->RAMEN));
+ device->save_item(NAME(nec_state->TB));
+ device->save_item(NAME(nec_state->PCK));
+ device->save_item(NAME(nec_state->IDB));
+
+ nec_state->irq_callback = irqcallback;
+ nec_state->device = device;
+ nec_state->program = device->space(AS_PROGRAM);
+ nec_state->direct = &nec_state->program->direct();
+ nec_state->io = device->space(AS_IO);
+}
+
+
+
+static CPU_EXECUTE( v25 )
+{
+ v25_state_t *nec_state = get_safe_token(device);
+ int prev_ICount;
+
+ int pending = nec_state->pending_irq & nec_state->unmasked_irq;
+
+ if (nec_state->halted && pending)
+ {
+ for(int i = 0; i < 8; i++)
+ {
+ if (nec_state->ISPR & (1 << i)) break;
+
+ if (nec_state->priority_inttu == i && (pending & (INTTU0|INTTU1|INTTU2)))
+ nec_state->halted = 0;
+
+ if (nec_state->priority_intd == i && (pending & (INTD0|INTD1)))
+ nec_state->halted = 0;
+
+ if (nec_state->priority_intp == i && (pending & (INTP0|INTP1|INTP2)))
+ nec_state->halted = 0;
+
+ if (nec_state->priority_ints0 == i && (pending & (INTSER0|INTSR0|INTST0)))
+ nec_state->halted = 0;
+
+ if (nec_state->priority_ints1 == i && (pending & (INTSER1|INTSR1|INTST1)))
+ nec_state->halted = 0;
+
+ if (i == 7 && (pending & INTTB))
+ nec_state->halted = 0;
+ }
+ }
+
+ if (nec_state->halted)
+ {
+ nec_state->icount = 0;
+ debugger_instruction_hook(device, (Sreg(PS)<<4) + nec_state->ip);
+ return;
+ }
+
+ while(nec_state->icount>0) {
+ /* Dispatch IRQ */
+ if (nec_state->no_interrupt==0 && (nec_state->pending_irq & nec_state->unmasked_irq))
+ {
+ if (nec_state->pending_irq & NMI_IRQ)
+ external_int(nec_state);
+ else if (nec_state->IF)
+ external_int(nec_state);
+ }
+
+ /* No interrupt allowed between last instruction and this one */
+ if (nec_state->no_interrupt)
+ nec_state->no_interrupt--;
+
+ debugger_instruction_hook(device, (Sreg(PS)<<4) + nec_state->ip);
+ prev_ICount = nec_state->icount;
+ nec_instruction[fetchop(nec_state)](nec_state);
+ do_prefetch(nec_state, prev_ICount);
+ }
+}
+
+/* Wrappers for the different CPU types */
+static CPU_INIT( v25 )
+{
+ v25_state_t *nec_state = get_safe_token(device);
+
+ v25_init(device, irqcallback);
+ nec_state->fetch_xor = 0;
+ nec_state->chip_type=V20_TYPE;
+ nec_state->prefetch_size = 4; /* 3 words */
+ nec_state->prefetch_cycles = 4; /* four cycles per byte */
+}
+
+static CPU_INIT( v35 )
+{
+ v25_state_t *nec_state = get_safe_token(device);
+
+ v25_init(device, irqcallback);
+ nec_state->fetch_xor = BYTE_XOR_LE(0);
+ nec_state->chip_type=V30_TYPE;
+ nec_state->prefetch_size = 6; /* 3 words */
+ nec_state->prefetch_cycles = 2; /* two cycles per byte / four per word */
+
+}
+
+
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( v25 )
+{
+ v25_state_t *nec_state = get_safe_token(device);
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + 0: set_irq_line(nec_state, 0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: set_irq_line(nec_state, INPUT_LINE_NMI, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + NEC_INPUT_LINE_INTP0: set_irq_line(nec_state, NEC_INPUT_LINE_INTP0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + NEC_INPUT_LINE_INTP1: set_irq_line(nec_state, NEC_INPUT_LINE_INTP1, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + NEC_INPUT_LINE_INTP2: set_irq_line(nec_state, NEC_INPUT_LINE_INTP2, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + NEC_INPUT_LINE_POLL: set_irq_line(nec_state, NEC_INPUT_LINE_POLL, info->i); break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + NEC_PC:
+ if( info->i - (Sreg(PS)<<4) < 0x10000 )
+ {
+ nec_state->ip = info->i - (Sreg(PS)<<4);
+ }
+ else
+ {
+ Sreg(PS) = info->i >> 4;
+ nec_state->ip = info->i & 0x0000f;
+ }
+ break;
+ case CPUINFO_INT_REGISTER + NEC_IP: nec_state->ip = info->i; break;
+ case CPUINFO_INT_SP:
+ if( info->i - (Sreg(SS)<<4) < 0x10000 )
+ {
+ Wreg(SP) = info->i - (Sreg(SS)<<4);
+ }
+ else
+ {
+ Sreg(SS) = info->i >> 4;
+ Wreg(SP) = info->i & 0x0000f;
+ }
+ break;
+ case CPUINFO_INT_REGISTER + NEC_SP: Wreg(SP) = info->i; break;
+ case CPUINFO_INT_REGISTER + NEC_FLAGS: ExpandFlags(info->i); break;
+ case CPUINFO_INT_REGISTER + NEC_AW: Wreg(AW) = info->i; break;
+ case CPUINFO_INT_REGISTER + NEC_CW: Wreg(CW) = info->i; break;
+ case CPUINFO_INT_REGISTER + NEC_DW: Wreg(DW) = info->i; break;
+ case CPUINFO_INT_REGISTER + NEC_BW: Wreg(BW) = info->i; break;
+ case CPUINFO_INT_REGISTER + NEC_BP: Wreg(BP) = info->i; break;
+ case CPUINFO_INT_REGISTER + NEC_IX: Wreg(IX) = info->i; break;
+ case CPUINFO_INT_REGISTER + NEC_IY: Wreg(IY) = info->i; break;
+ case CPUINFO_INT_REGISTER + NEC_ES: Sreg(DS1) = info->i; break;
+ case CPUINFO_INT_REGISTER + NEC_CS: Sreg(PS) = info->i; break;
+ case CPUINFO_INT_REGISTER + NEC_SS: Sreg(SS) = info->i; break;
+ case CPUINFO_INT_REGISTER + NEC_DS: Sreg(DS0) = info->i; break;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+static CPU_GET_INFO( v25v35 )
+{
+ v25_state_t *nec_state = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+ int flags;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(v25_state_t); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 1; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0xff; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 2; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 8; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 80; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 20; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 17; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_INPUT_STATE + 0: info->i = (nec_state->pending_irq & INT_IRQ) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: info->i = nec_state->nmi_state; break;
+ case CPUINFO_INT_INPUT_STATE + NEC_INPUT_LINE_INTP0: info->i = nec_state->intp_state[0]; break;
+ case CPUINFO_INT_INPUT_STATE + NEC_INPUT_LINE_INTP1: info->i = nec_state->intp_state[1]; break;
+ case CPUINFO_INT_INPUT_STATE + NEC_INPUT_LINE_INTP2: info->i = nec_state->intp_state[2]; break;
+ case CPUINFO_INT_INPUT_STATE + NEC_INPUT_LINE_POLL: info->i = nec_state->poll_state; break;
+
+ case CPUINFO_INT_PREVIOUSPC: /* not supported */ break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + NEC_PC: info->i = ((Sreg(PS)<<4) + nec_state->ip); break;
+ case CPUINFO_INT_REGISTER + NEC_IP: info->i = nec_state->ip; break;
+ case CPUINFO_INT_SP: info->i = (Sreg(SS)<<4) + Wreg(SP); break;
+ case CPUINFO_INT_REGISTER + NEC_SP: info->i = Wreg(SP); break;
+ case CPUINFO_INT_REGISTER + NEC_FLAGS: info->i = CompressFlags(); break;
+ case CPUINFO_INT_REGISTER + NEC_AW: info->i = Wreg(AW); break;
+ case CPUINFO_INT_REGISTER + NEC_CW: info->i = Wreg(CW); break;
+ case CPUINFO_INT_REGISTER + NEC_DW: info->i = Wreg(DW); break;
+ case CPUINFO_INT_REGISTER + NEC_BW: info->i = Wreg(BW); break;
+ case CPUINFO_INT_REGISTER + NEC_BP: info->i = Wreg(BP); break;
+ case CPUINFO_INT_REGISTER + NEC_IX: info->i = Wreg(IX); break;
+ case CPUINFO_INT_REGISTER + NEC_IY: info->i = Wreg(IY); break;
+ case CPUINFO_INT_REGISTER + NEC_ES: info->i = Sreg(DS1); break;
+ case CPUINFO_INT_REGISTER + NEC_CS: info->i = Sreg(PS); break;
+ case CPUINFO_INT_REGISTER + NEC_SS: info->i = Sreg(SS); break;
+ case CPUINFO_INT_REGISTER + NEC_DS: info->i = Sreg(DS0); break;
+ case CPUINFO_INT_REGISTER + NEC_PENDING: info->i = nec_state->pending_irq; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(v25); break;
+ case CPUINFO_FCT_INIT: /* set per-CPU */ break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(v25); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(v25); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(v25); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(v25); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &nec_state->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "NEC"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "NEC V-Series"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "2.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Bryan McPhail (V25/V35 support added by Alex W. Jackson)"); break;
+
+ case CPUINFO_STR_FLAGS:
+ flags = CompressFlags();
+ sprintf(info->s, "%c %d %c%c%c%c%c%c%c%c%c%c%c%c",
+ flags & 0x8000 ? 'N':'S',
+ (flags & 0x7000) >> 12,
+ flags & 0x0800 ? 'O':'.',
+ flags & 0x0400 ? 'D':'.',
+ flags & 0x0200 ? 'I':'.',
+ flags & 0x0100 ? 'T':'.',
+ flags & 0x0080 ? 'S':'.',
+ flags & 0x0040 ? 'Z':'.',
+ flags & 0x0020 ? '1':'.',
+ flags & 0x0010 ? 'A':'.',
+ flags & 0x0008 ? '0':'.',
+ flags & 0x0004 ? 'P':'.',
+ flags & 0x0002 ? '.':'I',
+ flags & 0x0001 ? 'C':'.');
+ break;
+
+ case CPUINFO_STR_REGISTER + NEC_PC: sprintf(info->s, "PC:%05X", (Sreg(PS)<<4) + nec_state->ip); break;
+ case CPUINFO_STR_REGISTER + NEC_IP: sprintf(info->s, "IP:%04X", nec_state->ip); break;
+ case CPUINFO_STR_REGISTER + NEC_SP: sprintf(info->s, "SP:%04X", Wreg(SP)); break;
+ case CPUINFO_STR_REGISTER + NEC_FLAGS: sprintf(info->s, "F:%04X", CompressFlags()); break;
+ case CPUINFO_STR_REGISTER + NEC_AW: sprintf(info->s, "AW:%04X", Wreg(AW)); break;
+ case CPUINFO_STR_REGISTER + NEC_CW: sprintf(info->s, "CW:%04X", Wreg(CW)); break;
+ case CPUINFO_STR_REGISTER + NEC_DW: sprintf(info->s, "DW:%04X", Wreg(DW)); break;
+ case CPUINFO_STR_REGISTER + NEC_BW: sprintf(info->s, "BW:%04X", Wreg(BW)); break;
+ case CPUINFO_STR_REGISTER + NEC_BP: sprintf(info->s, "BP:%04X", Wreg(BP)); break;
+ case CPUINFO_STR_REGISTER + NEC_IX: sprintf(info->s, "IX:%04X", Wreg(IX)); break;
+ case CPUINFO_STR_REGISTER + NEC_IY: sprintf(info->s, "IY:%04X", Wreg(IY)); break;
+ case CPUINFO_STR_REGISTER + NEC_ES: sprintf(info->s, "DS1:%04X", Sreg(DS1)); break;
+ case CPUINFO_STR_REGISTER + NEC_CS: sprintf(info->s, "PS:%04X", Sreg(PS)); break;
+ case CPUINFO_STR_REGISTER + NEC_SS: sprintf(info->s, "SS:%04X", Sreg(SS)); break;
+ case CPUINFO_STR_REGISTER + NEC_DS: sprintf(info->s, "DS0:%04X", Sreg(DS0)); break;
+ }
+}
+
+
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+
+CPU_GET_INFO( v25 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 8; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(v25); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "V25"); break;
+
+ default: CPU_GET_INFO_CALL(v25v35); break;
+ }
+}
+
+
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+
+CPU_GET_INFO( v35 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 16; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(v35); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "V35"); break;
+
+ default: CPU_GET_INFO_CALL(v25v35); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(V25, v25);
+DEFINE_LEGACY_CPU_DEVICE(V35, v35);
diff --git a/trunk/src/emu/cpu/nec/v25instr.c b/trunk/src/emu/cpu/nec/v25instr.c
new file mode 100644
index 00000000000..72cc1c9f7e3
--- /dev/null
+++ b/trunk/src/emu/cpu/nec/v25instr.c
@@ -0,0 +1,82 @@
+#define GetRB \
+ ModRM = FETCH(); \
+ if (ModRM >= 0xc0) \
+ tmp = Wreg(Mod_RM.RM.w[ModRM]) & 0x7; \
+ else { \
+ logerror("%06x: Invalid MODRM for register banking instruction\n",PC(nec_state)); \
+ tmp = 0; \
+ }
+
+#define RETRBI \
+ tmp = (Wreg(PSW_SAVE) & 0x7000) >> 12; \
+ nec_state->ip = Wreg(PC_SAVE); \
+ ExpandFlags(Wreg(PSW_SAVE)); \
+ SetRB(tmp); \
+ CHANGE_PC
+
+#define TSKSW \
+ Wreg(PSW_SAVE) = CompressFlags(); \
+ Wreg(PC_SAVE) = nec_state->ip; \
+ SetRB(tmp); \
+ nec_state->ip = Wreg(PC_SAVE); \
+ ExpandFlags(Wreg(PSW_SAVE)); \
+ CHANGE_PC
+
+#define MOVSPA \
+ tmp = (Wreg(PSW_SAVE) & 0x7000) >> 8; \
+ Sreg(SS) = nec_state->ram.w[tmp+SS]; \
+ Wreg(SP) = nec_state->ram.w[tmp+SP]
+
+#define MOVSPB \
+ tmp <<= 4; \
+ nec_state->ram.w[tmp+SS] = Sreg(SS); \
+ nec_state->ram.w[tmp+SP] = Wreg(SP)
+
+#define FINT \
+ for(tmp = 1; tmp < 0x100; tmp <<= 1) { \
+ if(nec_state->ISPR & tmp) { \
+ nec_state->ISPR &= ~tmp; \
+ break; \
+ } \
+ }
+
+OP( 0x0f, i_pre_v25 ) { UINT32 ModRM, tmp, tmp2;
+ switch (FETCH()) {
+ case 0x10 : BITOP_BYTE; CLKS(3,3,4); tmp2 = Breg(CL) & 0x7; nec_state->ZeroVal = (tmp & (1<<tmp2)) ? 1 : 0; nec_state->CarryVal=nec_state->OverVal=0; break; /* Test */
+ case 0x11 : BITOP_WORD; CLKS(3,3,4); tmp2 = Breg(CL) & 0xf; nec_state->ZeroVal = (tmp & (1<<tmp2)) ? 1 : 0; nec_state->CarryVal=nec_state->OverVal=0; break; /* Test */
+ case 0x12 : BITOP_BYTE; CLKS(5,5,4); tmp2 = Breg(CL) & 0x7; tmp &= ~(1<<tmp2); PutbackRMByte(ModRM,tmp); break; /* Clr */
+ case 0x13 : BITOP_WORD; CLKS(5,5,4); tmp2 = Breg(CL) & 0xf; tmp &= ~(1<<tmp2); PutbackRMWord(ModRM,tmp); break; /* Clr */
+ case 0x14 : BITOP_BYTE; CLKS(4,4,4); tmp2 = Breg(CL) & 0x7; tmp |= (1<<tmp2); PutbackRMByte(ModRM,tmp); break; /* Set */
+ case 0x15 : BITOP_WORD; CLKS(4,4,4); tmp2 = Breg(CL) & 0xf; tmp |= (1<<tmp2); PutbackRMWord(ModRM,tmp); break; /* Set */
+ case 0x16 : BITOP_BYTE; CLKS(4,4,4); tmp2 = Breg(CL) & 0x7; BIT_NOT; PutbackRMByte(ModRM,tmp); break; /* Not */
+ case 0x17 : BITOP_WORD; CLKS(4,4,4); tmp2 = Breg(CL) & 0xf; BIT_NOT; PutbackRMWord(ModRM,tmp); break; /* Not */
+
+ case 0x18 : BITOP_BYTE; CLKS(4,4,4); tmp2 = (FETCH()) & 0x7; nec_state->ZeroVal = (tmp & (1<<tmp2)) ? 1 : 0; nec_state->CarryVal=nec_state->OverVal=0; break; /* Test */
+ case 0x19 : BITOP_WORD; CLKS(4,4,4); tmp2 = (FETCH()) & 0xf; nec_state->ZeroVal = (tmp & (1<<tmp2)) ? 1 : 0; nec_state->CarryVal=nec_state->OverVal=0; break; /* Test */
+ case 0x1a : BITOP_BYTE; CLKS(6,6,4); tmp2 = (FETCH()) & 0x7; tmp &= ~(1<<tmp2); PutbackRMByte(ModRM,tmp); break; /* Clr */
+ case 0x1b : BITOP_WORD; CLKS(6,6,4); tmp2 = (FETCH()) & 0xf; tmp &= ~(1<<tmp2); PutbackRMWord(ModRM,tmp); break; /* Clr */
+ case 0x1c : BITOP_BYTE; CLKS(5,5,4); tmp2 = (FETCH()) & 0x7; tmp |= (1<<tmp2); PutbackRMByte(ModRM,tmp); break; /* Set */
+ case 0x1d : BITOP_WORD; CLKS(5,5,4); tmp2 = (FETCH()) & 0xf; tmp |= (1<<tmp2); PutbackRMWord(ModRM,tmp); break; /* Set */
+ case 0x1e : BITOP_BYTE; CLKS(5,5,4); tmp2 = (FETCH()) & 0x7; BIT_NOT; PutbackRMByte(ModRM,tmp); break; /* Not */
+ case 0x1f : BITOP_WORD; CLKS(5,5,4); tmp2 = (FETCH()) & 0xf; BIT_NOT; PutbackRMWord(ModRM,tmp); break; /* Not */
+
+ case 0x20 : ADD4S; CLKS(7,7,2); break;
+ case 0x22 : SUB4S; CLKS(7,7,2); break;
+ case 0x25 : MOVSPA; CLK(16); break;
+ case 0x26 : CMP4S; CLKS(7,7,2); break;
+ case 0x28 : ModRM = FETCH(); tmp = GetRMByte(ModRM); tmp <<= 4; tmp |= Breg(AL) & 0xf; Breg(AL) = (Breg(AL) & 0xf0) | ((tmp>>8)&0xf); tmp &= 0xff; PutbackRMByte(ModRM,tmp); CLKM(13,13,9,28,28,15); break;
+ case 0x2a : ModRM = FETCH(); tmp = GetRMByte(ModRM); tmp2 = (Breg(AL) & 0xf)<<4; Breg(AL) = (Breg(AL) & 0xf0) | (tmp&0xf); tmp = tmp2 | (tmp>>4); PutbackRMByte(ModRM,tmp); CLKM(17,17,13,32,32,19); break;
+ case 0x2d : GetRB; nec_bankswitch(nec_state, tmp); CLK(15); break;
+ case 0x31 : ModRM = FETCH(); ModRM=0; logerror("%06x: Unimplemented bitfield INS\n",PC(nec_state)); break;
+ case 0x33 : ModRM = FETCH(); ModRM=0; logerror("%06x: Unimplemented bitfield EXT\n",PC(nec_state)); break;
+ case 0x91 : RETRBI; CLK(12); break;
+ case 0x92 : FINT; CLK(2); nec_state->no_interrupt = 1; break;
+ case 0x94 : GetRB; TSKSW; CLK(20); break;
+ case 0x95 : GetRB; MOVSPB; CLK(11); break;
+ case 0x9e : logerror("%06x: STOP\n",PC(nec_state)); nec_state->icount=0; break;
+ default: logerror("%06x: Unknown V25 instruction\n",PC(nec_state)); break;
+ }
+}
+
+OP( 0x63, i_brkn ) { nec_interrupt(nec_state, FETCH(), BRKN); CLKS(50,50,24); }
+OP( 0xF1, i_brks ) { nec_interrupt(nec_state, FETCH(), BRKS); CLKS(50,50,24); }
diff --git a/trunk/src/emu/cpu/nec/v25instr.h b/trunk/src/emu/cpu/nec/v25instr.h
new file mode 100644
index 00000000000..77a8503bc2f
--- /dev/null
+++ b/trunk/src/emu/cpu/nec/v25instr.h
@@ -0,0 +1,510 @@
+static void i_add_br8(nec_state_t *nec_state);
+static void i_add_wr16(nec_state_t *nec_state);
+static void i_add_r8b(nec_state_t *nec_state);
+static void i_add_r16w(nec_state_t *nec_state);
+static void i_add_ald8(nec_state_t *nec_state);
+static void i_add_axd16(nec_state_t *nec_state);
+static void i_push_es(nec_state_t *nec_state);
+static void i_pop_es(nec_state_t *nec_state);
+static void i_or_br8(nec_state_t *nec_state);
+static void i_or_r8b(nec_state_t *nec_state);
+static void i_or_wr16(nec_state_t *nec_state);
+static void i_or_r16w(nec_state_t *nec_state);
+static void i_or_ald8(nec_state_t *nec_state);
+static void i_or_axd16(nec_state_t *nec_state);
+static void i_push_cs(nec_state_t *nec_state);
+ATTR_UNUSED static void i_pre_nec(nec_state_t *nec_state);
+static void i_pre_v25(nec_state_t *nec_state);
+static void i_adc_br8(nec_state_t *nec_state);
+static void i_adc_wr16(nec_state_t *nec_state);
+static void i_adc_r8b(nec_state_t *nec_state);
+static void i_adc_r16w(nec_state_t *nec_state);
+static void i_adc_ald8(nec_state_t *nec_state);
+static void i_adc_axd16(nec_state_t *nec_state);
+static void i_push_ss(nec_state_t *nec_state);
+static void i_pop_ss(nec_state_t *nec_state);
+static void i_sbb_br8(nec_state_t *nec_state);
+static void i_sbb_wr16(nec_state_t *nec_state);
+static void i_sbb_r8b(nec_state_t *nec_state);
+static void i_sbb_r16w(nec_state_t *nec_state);
+static void i_sbb_ald8(nec_state_t *nec_state);
+static void i_sbb_axd16(nec_state_t *nec_state);
+static void i_push_ds(nec_state_t *nec_state);
+static void i_pop_ds(nec_state_t *nec_state);
+static void i_and_br8(nec_state_t *nec_state);
+static void i_and_r8b(nec_state_t *nec_state);
+static void i_and_wr16(nec_state_t *nec_state);
+static void i_and_r16w(nec_state_t *nec_state);
+static void i_and_ald8(nec_state_t *nec_state);
+static void i_and_axd16(nec_state_t *nec_state);
+static void i_es(nec_state_t *nec_state);
+static void i_daa(nec_state_t *nec_state);
+static void i_sub_br8(nec_state_t *nec_state);
+static void i_sub_wr16(nec_state_t *nec_state);
+static void i_sub_r8b(nec_state_t *nec_state);
+static void i_sub_r16w(nec_state_t *nec_state);
+static void i_sub_ald8(nec_state_t *nec_state);
+static void i_sub_axd16(nec_state_t *nec_state);
+static void i_cs(nec_state_t *nec_state);
+static void i_das(nec_state_t *nec_state);
+static void i_xor_br8(nec_state_t *nec_state);
+static void i_xor_r8b(nec_state_t *nec_state);
+static void i_xor_wr16(nec_state_t *nec_state);
+static void i_xor_r16w(nec_state_t *nec_state);
+static void i_xor_ald8(nec_state_t *nec_state);
+static void i_xor_axd16(nec_state_t *nec_state);
+static void i_ss(nec_state_t *nec_state);
+static void i_aaa(nec_state_t *nec_state);
+static void i_cmp_br8(nec_state_t *nec_state);
+static void i_cmp_wr16(nec_state_t *nec_state);
+static void i_cmp_r8b(nec_state_t *nec_state);
+static void i_cmp_r16w(nec_state_t *nec_state);
+static void i_cmp_ald8(nec_state_t *nec_state);
+static void i_cmp_axd16(nec_state_t *nec_state);
+static void i_ds(nec_state_t *nec_state);
+static void i_aas(nec_state_t *nec_state);
+static void i_inc_ax(nec_state_t *nec_state);
+static void i_inc_cx(nec_state_t *nec_state);
+static void i_inc_dx(nec_state_t *nec_state);
+static void i_inc_bx(nec_state_t *nec_state);
+static void i_inc_sp(nec_state_t *nec_state);
+static void i_inc_bp(nec_state_t *nec_state);
+static void i_inc_si(nec_state_t *nec_state);
+static void i_inc_di(nec_state_t *nec_state);
+static void i_dec_ax(nec_state_t *nec_state);
+static void i_dec_cx(nec_state_t *nec_state);
+static void i_dec_dx(nec_state_t *nec_state);
+static void i_dec_bx(nec_state_t *nec_state);
+static void i_dec_sp(nec_state_t *nec_state);
+static void i_dec_bp(nec_state_t *nec_state);
+static void i_dec_si(nec_state_t *nec_state);
+static void i_dec_di(nec_state_t *nec_state);
+static void i_push_ax(nec_state_t *nec_state);
+static void i_push_cx(nec_state_t *nec_state);
+static void i_push_dx(nec_state_t *nec_state);
+static void i_push_bx(nec_state_t *nec_state);
+static void i_push_sp(nec_state_t *nec_state);
+static void i_push_bp(nec_state_t *nec_state);
+static void i_push_si(nec_state_t *nec_state);
+static void i_push_di(nec_state_t *nec_state);
+static void i_pop_ax(nec_state_t *nec_state);
+static void i_pop_cx(nec_state_t *nec_state);
+static void i_pop_dx(nec_state_t *nec_state);
+static void i_pop_bx(nec_state_t *nec_state);
+static void i_pop_sp(nec_state_t *nec_state);
+static void i_pop_bp(nec_state_t *nec_state);
+static void i_pop_si(nec_state_t *nec_state);
+static void i_pop_di(nec_state_t *nec_state);
+static void i_pusha(nec_state_t *nec_state);
+static void i_popa(nec_state_t *nec_state);
+static void i_chkind(nec_state_t *nec_state);
+static void i_brkn(nec_state_t *nec_state);
+static void i_repnc(nec_state_t *nec_state);
+static void i_repc(nec_state_t *nec_state);
+static void i_push_d16(nec_state_t *nec_state);
+static void i_imul_d16(nec_state_t *nec_state);
+static void i_push_d8(nec_state_t *nec_state);
+static void i_imul_d8(nec_state_t *nec_state);
+static void i_insb(nec_state_t *nec_state);
+static void i_insw(nec_state_t *nec_state);
+static void i_outsb(nec_state_t *nec_state);
+static void i_outsw(nec_state_t *nec_state);
+static void i_jo(nec_state_t *nec_state);
+static void i_jno(nec_state_t *nec_state);
+static void i_jc(nec_state_t *nec_state);
+static void i_jnc(nec_state_t *nec_state);
+static void i_jz(nec_state_t *nec_state);
+static void i_jnz(nec_state_t *nec_state);
+static void i_jce(nec_state_t *nec_state);
+static void i_jnce(nec_state_t *nec_state);
+static void i_js(nec_state_t *nec_state);
+static void i_jns(nec_state_t *nec_state);
+static void i_jp(nec_state_t *nec_state);
+static void i_jnp(nec_state_t *nec_state);
+static void i_jl(nec_state_t *nec_state);
+static void i_jnl(nec_state_t *nec_state);
+static void i_jle(nec_state_t *nec_state);
+static void i_jnle(nec_state_t *nec_state);
+static void i_80pre(nec_state_t *nec_state);
+static void i_82pre(nec_state_t *nec_state);
+static void i_81pre(nec_state_t *nec_state);
+static void i_83pre(nec_state_t *nec_state);
+static void i_test_br8(nec_state_t *nec_state);
+static void i_test_wr16(nec_state_t *nec_state);
+static void i_xchg_br8(nec_state_t *nec_state);
+static void i_xchg_wr16(nec_state_t *nec_state);
+static void i_mov_br8(nec_state_t *nec_state);
+static void i_mov_r8b(nec_state_t *nec_state);
+static void i_mov_wr16(nec_state_t *nec_state);
+static void i_mov_r16w(nec_state_t *nec_state);
+static void i_mov_wsreg(nec_state_t *nec_state);
+static void i_lea(nec_state_t *nec_state);
+static void i_mov_sregw(nec_state_t *nec_state);
+static void i_invalid(nec_state_t *nec_state);
+static void i_popw(nec_state_t *nec_state);
+static void i_nop(nec_state_t *nec_state);
+static void i_xchg_axcx(nec_state_t *nec_state);
+static void i_xchg_axdx(nec_state_t *nec_state);
+static void i_xchg_axbx(nec_state_t *nec_state);
+static void i_xchg_axsp(nec_state_t *nec_state);
+static void i_xchg_axbp(nec_state_t *nec_state);
+static void i_xchg_axsi(nec_state_t *nec_state);
+static void i_xchg_axdi(nec_state_t *nec_state);
+static void i_cbw(nec_state_t *nec_state);
+static void i_cwd(nec_state_t *nec_state);
+static void i_call_far(nec_state_t *nec_state);
+static void i_pushf(nec_state_t *nec_state);
+static void i_popf(nec_state_t *nec_state);
+static void i_sahf(nec_state_t *nec_state);
+static void i_lahf(nec_state_t *nec_state);
+static void i_mov_aldisp(nec_state_t *nec_state);
+static void i_mov_axdisp(nec_state_t *nec_state);
+static void i_mov_dispal(nec_state_t *nec_state);
+static void i_mov_dispax(nec_state_t *nec_state);
+static void i_movsb(nec_state_t *nec_state);
+static void i_movsw(nec_state_t *nec_state);
+static void i_cmpsb(nec_state_t *nec_state);
+static void i_cmpsw(nec_state_t *nec_state);
+static void i_test_ald8(nec_state_t *nec_state);
+static void i_test_axd16(nec_state_t *nec_state);
+static void i_stosb(nec_state_t *nec_state);
+static void i_stosw(nec_state_t *nec_state);
+static void i_lodsb(nec_state_t *nec_state);
+static void i_lodsw(nec_state_t *nec_state);
+static void i_scasb(nec_state_t *nec_state);
+static void i_scasw(nec_state_t *nec_state);
+static void i_mov_ald8(nec_state_t *nec_state);
+static void i_mov_cld8(nec_state_t *nec_state);
+static void i_mov_dld8(nec_state_t *nec_state);
+static void i_mov_bld8(nec_state_t *nec_state);
+static void i_mov_ahd8(nec_state_t *nec_state);
+static void i_mov_chd8(nec_state_t *nec_state);
+static void i_mov_dhd8(nec_state_t *nec_state);
+static void i_mov_bhd8(nec_state_t *nec_state);
+static void i_mov_axd16(nec_state_t *nec_state);
+static void i_mov_cxd16(nec_state_t *nec_state);
+static void i_mov_dxd16(nec_state_t *nec_state);
+static void i_mov_bxd16(nec_state_t *nec_state);
+static void i_mov_spd16(nec_state_t *nec_state);
+static void i_mov_bpd16(nec_state_t *nec_state);
+static void i_mov_sid16(nec_state_t *nec_state);
+static void i_mov_did16(nec_state_t *nec_state);
+static void i_rotshft_bd8(nec_state_t *nec_state);
+static void i_rotshft_wd8(nec_state_t *nec_state);
+static void i_ret_d16(nec_state_t *nec_state);
+static void i_ret(nec_state_t *nec_state);
+static void i_les_dw(nec_state_t *nec_state);
+static void i_lds_dw(nec_state_t *nec_state);
+static void i_mov_bd8(nec_state_t *nec_state);
+static void i_mov_wd16(nec_state_t *nec_state);
+static void i_enter(nec_state_t *nec_state);
+static void i_leave(nec_state_t *nec_state);
+static void i_retf_d16(nec_state_t *nec_state);
+static void i_retf(nec_state_t *nec_state);
+static void i_int3(nec_state_t *nec_state);
+static void i_int(nec_state_t *nec_state);
+static void i_into(nec_state_t *nec_state);
+static void i_iret(nec_state_t *nec_state);
+static void i_rotshft_b(nec_state_t *nec_state);
+static void i_rotshft_w(nec_state_t *nec_state);
+static void i_rotshft_bcl(nec_state_t *nec_state);
+static void i_rotshft_wcl(nec_state_t *nec_state);
+static void i_aam(nec_state_t *nec_state);
+static void i_aad(nec_state_t *nec_state);
+static void i_setalc(nec_state_t *nec_state);
+static void i_trans(nec_state_t *nec_state);
+static void i_fpo(nec_state_t *nec_state);
+static void i_loopne(nec_state_t *nec_state);
+static void i_loope(nec_state_t *nec_state);
+static void i_loop(nec_state_t *nec_state);
+static void i_jcxz(nec_state_t *nec_state);
+static void i_inal(nec_state_t *nec_state);
+static void i_inax(nec_state_t *nec_state);
+static void i_outal(nec_state_t *nec_state);
+static void i_outax(nec_state_t *nec_state);
+static void i_call_d16(nec_state_t *nec_state);
+static void i_jmp_d16(nec_state_t *nec_state);
+static void i_jmp_far(nec_state_t *nec_state);
+static void i_jmp_d8(nec_state_t *nec_state);
+static void i_inaldx(nec_state_t *nec_state);
+static void i_inaxdx(nec_state_t *nec_state);
+static void i_outdxal(nec_state_t *nec_state);
+static void i_outdxax(nec_state_t *nec_state);
+static void i_lock(nec_state_t *nec_state);
+static void i_brks(nec_state_t *nec_state);
+static void i_repne(nec_state_t *nec_state);
+static void i_repe(nec_state_t *nec_state);
+static void i_hlt(nec_state_t *nec_state);
+static void i_cmc(nec_state_t *nec_state);
+static void i_f6pre(nec_state_t *nec_state);
+static void i_f7pre(nec_state_t *nec_state);
+static void i_clc(nec_state_t *nec_state);
+static void i_stc(nec_state_t *nec_state);
+static void i_di(nec_state_t *nec_state);
+static void i_ei(nec_state_t *nec_state);
+static void i_cld(nec_state_t *nec_state);
+static void i_std(nec_state_t *nec_state);
+static void i_fepre(nec_state_t *nec_state);
+static void i_ffpre(nec_state_t *nec_state);
+
+static void i_wait(nec_state_t *nec_state);
+
+static void (*const nec_instruction[256])(nec_state_t *nec_state) =
+{
+ i_add_br8, /* 0x00 */
+ i_add_wr16, /* 0x01 */
+ i_add_r8b, /* 0x02 */
+ i_add_r16w, /* 0x03 */
+ i_add_ald8, /* 0x04 */
+ i_add_axd16, /* 0x05 */
+ i_push_es, /* 0x06 */
+ i_pop_es, /* 0x07 */
+ i_or_br8, /* 0x08 */
+ i_or_wr16, /* 0x09 */
+ i_or_r8b, /* 0x0a */
+ i_or_r16w, /* 0x0b */
+ i_or_ald8, /* 0x0c */
+ i_or_axd16, /* 0x0d */
+ i_push_cs, /* 0x0e */
+ i_pre_v25, /* 0x0f */
+ i_adc_br8, /* 0x10 */
+ i_adc_wr16, /* 0x11 */
+ i_adc_r8b, /* 0x12 */
+ i_adc_r16w, /* 0x13 */
+ i_adc_ald8, /* 0x14 */
+ i_adc_axd16, /* 0x15 */
+ i_push_ss, /* 0x16 */
+ i_pop_ss, /* 0x17 */
+ i_sbb_br8, /* 0x18 */
+ i_sbb_wr16, /* 0x19 */
+ i_sbb_r8b, /* 0x1a */
+ i_sbb_r16w, /* 0x1b */
+ i_sbb_ald8, /* 0x1c */
+ i_sbb_axd16, /* 0x1d */
+ i_push_ds, /* 0x1e */
+ i_pop_ds, /* 0x1f */
+ i_and_br8, /* 0x20 */
+ i_and_wr16, /* 0x21 */
+ i_and_r8b, /* 0x22 */
+ i_and_r16w, /* 0x23 */
+ i_and_ald8, /* 0x24 */
+ i_and_axd16, /* 0x25 */
+ i_es, /* 0x26 */
+ i_daa, /* 0x27 */
+ i_sub_br8, /* 0x28 */
+ i_sub_wr16, /* 0x29 */
+ i_sub_r8b, /* 0x2a */
+ i_sub_r16w, /* 0x2b */
+ i_sub_ald8, /* 0x2c */
+ i_sub_axd16, /* 0x2d */
+ i_cs, /* 0x2e */
+ i_das, /* 0x2f */
+ i_xor_br8, /* 0x30 */
+ i_xor_wr16, /* 0x31 */
+ i_xor_r8b, /* 0x32 */
+ i_xor_r16w, /* 0x33 */
+ i_xor_ald8, /* 0x34 */
+ i_xor_axd16, /* 0x35 */
+ i_ss, /* 0x36 */
+ i_aaa, /* 0x37 */
+ i_cmp_br8, /* 0x38 */
+ i_cmp_wr16, /* 0x39 */
+ i_cmp_r8b, /* 0x3a */
+ i_cmp_r16w, /* 0x3b */
+ i_cmp_ald8, /* 0x3c */
+ i_cmp_axd16, /* 0x3d */
+ i_ds, /* 0x3e */
+ i_aas, /* 0x3f */
+ i_inc_ax, /* 0x40 */
+ i_inc_cx, /* 0x41 */
+ i_inc_dx, /* 0x42 */
+ i_inc_bx, /* 0x43 */
+ i_inc_sp, /* 0x44 */
+ i_inc_bp, /* 0x45 */
+ i_inc_si, /* 0x46 */
+ i_inc_di, /* 0x47 */
+ i_dec_ax, /* 0x48 */
+ i_dec_cx, /* 0x49 */
+ i_dec_dx, /* 0x4a */
+ i_dec_bx, /* 0x4b */
+ i_dec_sp, /* 0x4c */
+ i_dec_bp, /* 0x4d */
+ i_dec_si, /* 0x4e */
+ i_dec_di, /* 0x4f */
+ i_push_ax, /* 0x50 */
+ i_push_cx, /* 0x51 */
+ i_push_dx, /* 0x52 */
+ i_push_bx, /* 0x53 */
+ i_push_sp, /* 0x54 */
+ i_push_bp, /* 0x55 */
+ i_push_si, /* 0x56 */
+ i_push_di, /* 0x57 */
+ i_pop_ax, /* 0x58 */
+ i_pop_cx, /* 0x59 */
+ i_pop_dx, /* 0x5a */
+ i_pop_bx, /* 0x5b */
+ i_pop_sp, /* 0x5c */
+ i_pop_bp, /* 0x5d */
+ i_pop_si, /* 0x5e */
+ i_pop_di, /* 0x5f */
+ i_pusha, /* 0x60 */
+ i_popa, /* 0x61 */
+ i_chkind, /* 0x62 */
+ i_brkn, /* 0x63 - V25S/V35S only */
+ i_repnc, /* 0x64 */
+ i_repc, /* 0x65 */
+ i_invalid, /* 0x66 */
+ i_invalid, /* 0x67 */
+ i_push_d16, /* 0x68 */
+ i_imul_d16, /* 0x69 */
+ i_push_d8, /* 0x6a */
+ i_imul_d8, /* 0x6b */
+ i_insb, /* 0x6c */
+ i_insw, /* 0x6d */
+ i_outsb, /* 0x6e */
+ i_outsw, /* 0x6f */
+ i_jo, /* 0x70 */
+ i_jno, /* 0x71 */
+ i_jc, /* 0x72 */
+ i_jnc, /* 0x73 */
+ i_jz, /* 0x74 */
+ i_jnz, /* 0x75 */
+ i_jce, /* 0x76 */
+ i_jnce, /* 0x77 */
+ i_js, /* 0x78 */
+ i_jns, /* 0x79 */
+ i_jp, /* 0x7a */
+ i_jnp, /* 0x7b */
+ i_jl, /* 0x7c */
+ i_jnl, /* 0x7d */
+ i_jle, /* 0x7e */
+ i_jnle, /* 0x7f */
+ i_80pre, /* 0x80 */
+ i_81pre, /* 0x81 */
+ i_82pre, /* 0x82 */
+ i_83pre, /* 0x83 */
+ i_test_br8, /* 0x84 */
+ i_test_wr16, /* 0x85 */
+ i_xchg_br8, /* 0x86 */
+ i_xchg_wr16, /* 0x87 */
+ i_mov_br8, /* 0x88 */
+ i_mov_wr16, /* 0x89 */
+ i_mov_r8b, /* 0x8a */
+ i_mov_r16w, /* 0x8b */
+ i_mov_wsreg, /* 0x8c */
+ i_lea, /* 0x8d */
+ i_mov_sregw, /* 0x8e */
+ i_popw, /* 0x8f */
+ i_nop, /* 0x90 */
+ i_xchg_axcx, /* 0x91 */
+ i_xchg_axdx, /* 0x92 */
+ i_xchg_axbx, /* 0x93 */
+ i_xchg_axsp, /* 0x94 */
+ i_xchg_axbp, /* 0x95 */
+ i_xchg_axsi, /* 0x96 */
+ i_xchg_axdi, /* 0x97 */
+ i_cbw, /* 0x98 */
+ i_cwd, /* 0x99 */
+ i_call_far, /* 0x9a */
+ i_wait, /* 0x9b */
+ i_pushf, /* 0x9c */
+ i_popf, /* 0x9d */
+ i_sahf, /* 0x9e */
+ i_lahf, /* 0x9f */
+ i_mov_aldisp, /* 0xa0 */
+ i_mov_axdisp, /* 0xa1 */
+ i_mov_dispal, /* 0xa2 */
+ i_mov_dispax, /* 0xa3 */
+ i_movsb, /* 0xa4 */
+ i_movsw, /* 0xa5 */
+ i_cmpsb, /* 0xa6 */
+ i_cmpsw, /* 0xa7 */
+ i_test_ald8, /* 0xa8 */
+ i_test_axd16, /* 0xa9 */
+ i_stosb, /* 0xaa */
+ i_stosw, /* 0xab */
+ i_lodsb, /* 0xac */
+ i_lodsw, /* 0xad */
+ i_scasb, /* 0xae */
+ i_scasw, /* 0xaf */
+ i_mov_ald8, /* 0xb0 */
+ i_mov_cld8, /* 0xb1 */
+ i_mov_dld8, /* 0xb2 */
+ i_mov_bld8, /* 0xb3 */
+ i_mov_ahd8, /* 0xb4 */
+ i_mov_chd8, /* 0xb5 */
+ i_mov_dhd8, /* 0xb6 */
+ i_mov_bhd8, /* 0xb7 */
+ i_mov_axd16, /* 0xb8 */
+ i_mov_cxd16, /* 0xb9 */
+ i_mov_dxd16, /* 0xba */
+ i_mov_bxd16, /* 0xbb */
+ i_mov_spd16, /* 0xbc */
+ i_mov_bpd16, /* 0xbd */
+ i_mov_sid16, /* 0xbe */
+ i_mov_did16, /* 0xbf */
+ i_rotshft_bd8, /* 0xc0 */
+ i_rotshft_wd8, /* 0xc1 */
+ i_ret_d16, /* 0xc2 */
+ i_ret, /* 0xc3 */
+ i_les_dw, /* 0xc4 */
+ i_lds_dw, /* 0xc5 */
+ i_mov_bd8, /* 0xc6 */
+ i_mov_wd16, /* 0xc7 */
+ i_enter, /* 0xc8 */
+ i_leave, /* 0xc9 */
+ i_retf_d16, /* 0xca */
+ i_retf, /* 0xcb */
+ i_int3, /* 0xcc */
+ i_int, /* 0xcd */
+ i_into, /* 0xce */
+ i_iret, /* 0xcf */
+ i_rotshft_b, /* 0xd0 */
+ i_rotshft_w, /* 0xd1 */
+ i_rotshft_bcl, /* 0xd2 */
+ i_rotshft_wcl, /* 0xd3 */
+ i_aam, /* 0xd4 */
+ i_aad, /* 0xd5 */
+ i_setalc, /* 0xd6 */
+ i_trans, /* 0xd7 */
+ i_fpo, /* 0xd8 */
+ i_fpo, /* 0xd9 */
+ i_fpo, /* 0xda */
+ i_fpo, /* 0xdb */
+ i_fpo, /* 0xdc */
+ i_fpo, /* 0xdd */
+ i_fpo, /* 0xde */
+ i_fpo, /* 0xdf */
+ i_loopne, /* 0xe0 */
+ i_loope, /* 0xe1 */
+ i_loop, /* 0xe2 */
+ i_jcxz, /* 0xe3 */
+ i_inal, /* 0xe4 */
+ i_inax, /* 0xe5 */
+ i_outal, /* 0xe6 */
+ i_outax, /* 0xe7 */
+ i_call_d16, /* 0xe8 */
+ i_jmp_d16, /* 0xe9 */
+ i_jmp_far, /* 0xea */
+ i_jmp_d8, /* 0xeb */
+ i_inaldx, /* 0xec */
+ i_inaxdx, /* 0xed */
+ i_outdxal, /* 0xee */
+ i_outdxax, /* 0xef */
+ i_lock, /* 0xf0 */
+ i_brks, /* 0xf1 */
+ i_repne, /* 0xf2 */
+ i_repe, /* 0xf3 */
+ i_hlt, /* 0xf4 */
+ i_cmc, /* 0xf5 */
+ i_f6pre, /* 0xf6 */
+ i_f7pre, /* 0xf7 */
+ i_clc, /* 0xf8 */
+ i_stc, /* 0xf9 */
+ i_di, /* 0xfa */
+ i_ei, /* 0xfb */
+ i_cld, /* 0xfc */
+ i_std, /* 0xfd */
+ i_fepre, /* 0xfe */
+ i_ffpre /* 0xff */
+};
diff --git a/trunk/src/emu/cpu/nec/v25priv.h b/trunk/src/emu/cpu/nec/v25priv.h
new file mode 100644
index 00000000000..87ced6cdb2e
--- /dev/null
+++ b/trunk/src/emu/cpu/nec/v25priv.h
@@ -0,0 +1,258 @@
+/* Cpu types, steps of 8 to help the cycle count calculation */
+#define V33_TYPE 0
+#define V30_TYPE 8
+#define V20_TYPE 16
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE 1
+#endif
+
+/* interrupt vectors */
+enum
+{
+ NEC_DIVIDE_VECTOR = 0,
+ NEC_TRAP_VECTOR = 1,
+ NEC_NMI_VECTOR = 2,
+ NEC_BRKV_VECTOR = 4,
+ NEC_CHKIND_VECTOR = 5,
+ NEC_IBRK_VECTOR = 19,
+ NEC_INTTU0_VECTOR = 28,
+ NEC_INTTU1_VECTOR = 29,
+ NEC_INTTU2_VECTOR = 30,
+ NEC_INTD0_VECTOR = 20,
+ NEC_INTD1_VECTOR = 21,
+ NEC_INTP0_VECTOR = 24,
+ NEC_INTP1_VECTOR = 25,
+ NEC_INTP2_VECTOR = 26,
+ NEC_INTSER0_VECTOR = 12,
+ NEC_INTSR0_VECTOR = 13,
+ NEC_INTST0_VECTOR = 14,
+ NEC_INTSER1_VECTOR = 16,
+ NEC_INTSR1_VECTOR = 17,
+ NEC_INTST1_VECTOR = 18,
+ NEC_INTTB_VECTOR = 31
+};
+
+/* interrupt sources */
+typedef enum
+{
+ BRK = 0,
+ INT_IRQ = 1,
+ NMI_IRQ = 1 << 1,
+ INTTU0 = 1 << 2,
+ INTTU1 = 1 << 3,
+ INTTU2 = 1 << 4,
+ INTD0 = 1 << 5,
+ INTD1 = 1 << 6,
+ INTP0 = 1 << 7,
+ INTP1 = 1 << 8,
+ INTP2 = 1 << 9,
+ INTSER0 = 1 << 10,
+ INTSR0 = 1 << 11,
+ INTST0 = 1 << 12,
+ INTSER1 = 1 << 13,
+ INTSR1 = 1 << 14,
+ INTST1 = 1 << 15,
+ INTTB = 1 << 16,
+ BRKN = 1 << 17,
+ BRKS = 1 << 18
+} INTSOURCES;
+
+/* internal RAM and register banks */
+typedef union
+{
+ UINT16 w[128];
+ UINT8 b[256];
+} internalram;
+
+typedef struct _v25_state_t v25_state_t;
+struct _v25_state_t
+{
+ internalram ram;
+ offs_t fetch_xor;
+
+ UINT16 ip;
+
+ /* PSW flags */
+ INT32 SignVal;
+ UINT32 AuxVal, OverVal, ZeroVal, CarryVal, ParityVal; /* 0 or non-0 valued flags */
+ UINT8 IBRK, F0, F1, TF, IF, DF, MF; /* 0 or 1 valued flags */
+ UINT8 RBW, RBB; /* current register bank base, preshifted for word and byte registers */
+
+ /* interrupt related */
+ UINT32 pending_irq;
+ UINT32 unmasked_irq;
+ UINT32 bankswitch_irq;
+ UINT8 priority_inttu, priority_intd, priority_intp, priority_ints0, priority_ints1;
+ UINT8 IRQS, ISPR;
+ UINT32 nmi_state;
+ UINT32 irq_state;
+ UINT32 poll_state;
+ UINT32 mode_state;
+ UINT32 intp_state[3];
+ UINT8 no_interrupt;
+ UINT8 halted;
+
+ /* timer related */
+ UINT16 TM0, MD0, TM1, MD1;
+ UINT8 TMC0, TMC1;
+ emu_timer *timers[4];
+
+ /* system control */
+ UINT8 RAMEN, TB, PCK; /* PRC register */
+ UINT32 IDB;
+
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ address_space *io;
+ int icount;
+
+ const nec_config *config;
+
+ UINT8 prefetch_size;
+ UINT8 prefetch_cycles;
+ INT8 prefetch_count;
+ UINT8 prefetch_reset;
+ UINT32 chip_type;
+
+ UINT32 prefix_base; /* base address of the latest prefix segment */
+ UINT8 seg_prefix; /* prefix segment indicator */
+};
+
+enum {
+ VECTOR_PC = 0x02/2,
+ PSW_SAVE = 0x04/2,
+ PC_SAVE = 0x06/2
+};
+
+typedef enum {
+ DS1 = 0x0E/2,
+ PS = 0x0C/2,
+ SS = 0x0A/2,
+ DS0 = 0x08/2
+} SREGS;
+
+typedef enum {
+ AW = 0x1E/2,
+ CW = 0x1C/2,
+ DW = 0x1A/2,
+ BW = 0x18/2,
+ SP = 0x16/2,
+ BP = 0x14/2,
+ IX = 0x12/2,
+ IY = 0x10/2
+} WREGS;
+
+typedef enum {
+ AL = NATIVE_ENDIAN_VALUE_LE_BE(0x1E, 0x1F),
+ AH = NATIVE_ENDIAN_VALUE_LE_BE(0x1F, 0x1E),
+ CL = NATIVE_ENDIAN_VALUE_LE_BE(0x1C, 0x1D),
+ CH = NATIVE_ENDIAN_VALUE_LE_BE(0x1D, 0x1C),
+ DL = NATIVE_ENDIAN_VALUE_LE_BE(0x1A, 0x1B),
+ DH = NATIVE_ENDIAN_VALUE_LE_BE(0x1B, 0x1A),
+ BL = NATIVE_ENDIAN_VALUE_LE_BE(0x18, 0x19),
+ BH = NATIVE_ENDIAN_VALUE_LE_BE(0x19, 0x18)
+} BREGS;
+
+#define SetRB(x) do { nec_state->RBW = (x) << 4; nec_state->RBB = (x) << 5; } while (0)
+
+#define Sreg(x) nec_state->ram.w[nec_state->RBW + (x)]
+#define Wreg(x) nec_state->ram.w[nec_state->RBW + (x)]
+#define Breg(x) nec_state->ram.b[nec_state->RBB + (x)]
+
+#define PC(n) ((Sreg(PS)<<4)+(n)->ip)
+
+#define CF (nec_state->CarryVal!=0)
+#define SF (nec_state->SignVal<0)
+#define ZF (nec_state->ZeroVal==0)
+#define PF parity_table[(BYTE)nec_state->ParityVal]
+#define AF (nec_state->AuxVal!=0)
+#define OF (nec_state->OverVal!=0)
+#define RB (nec_state->RBW >> 4)
+
+/************************************************************************/
+
+UINT8 v25_read_byte(v25_state_t *nec_state, unsigned a);
+UINT16 v25_read_word(v25_state_t *nec_state, unsigned a);
+void v25_write_byte(v25_state_t *nec_state, unsigned a, UINT8 d);
+void v25_write_word(v25_state_t *nec_state, unsigned a, UINT16 d);
+
+#define read_mem_byte(a) v25_read_byte(nec_state,(a))
+#define read_mem_word(a) v25_read_word(nec_state,(a))
+#define write_mem_byte(a,d) v25_write_byte(nec_state,(a),(d))
+#define write_mem_word(a,d) v25_write_word(nec_state,(a),(d))
+
+#define read_port_byte(a) nec_state->io->read_byte(a)
+#define read_port_word(a) nec_state->io->read_word_unaligned(a)
+#define write_port_byte(a,d) nec_state->io->write_byte((a),(d))
+#define write_port_word(a,d) nec_state->io->write_word_unaligned((a),(d))
+
+/************************************************************************/
+
+#define CHANGE_PC do { EMPTY_PREFETCH(); } while (0)
+
+#define SegBase(Seg) (Sreg(Seg) << 4)
+
+#define DefaultBase(Seg) ((nec_state->seg_prefix && (Seg==DS0 || Seg==SS)) ? nec_state->prefix_base : Sreg(Seg) << 4)
+
+#define GetMemB(Seg,Off) (read_mem_byte(DefaultBase(Seg) + (Off)))
+#define GetMemW(Seg,Off) (read_mem_word(DefaultBase(Seg) + (Off)))
+
+#define PutMemB(Seg,Off,x) { write_mem_byte(DefaultBase(Seg) + (Off), (x)); }
+#define PutMemW(Seg,Off,x) { write_mem_word(DefaultBase(Seg) + (Off), (x)); }
+
+/* prefetch timing */
+
+#define FETCH() fetch(nec_state)
+#define FETCHWORD() fetchword(nec_state)
+#define EMPTY_PREFETCH() nec_state->prefetch_reset = 1
+
+
+#define PUSH(val) { Wreg(SP) -= 2; write_mem_word(((Sreg(SS)<<4)+Wreg(SP)), val); }
+#define POP(var) { Wreg(SP) += 2; var = read_mem_word(((Sreg(SS)<<4) + ((Wreg(SP)-2) & 0xffff))); }
+
+#define GetModRM UINT32 ModRM=FETCH()
+
+/* Cycle count macros:
+ CLK - cycle count is the same on all processors
+ CLKS - cycle count differs between processors, list all counts
+ CLKW - cycle count for word read/write differs for odd/even source/destination address
+ CLKM - cycle count for reg/mem instructions
+ CLKR - cycle count for reg/mem instructions with different counts for odd/even addresses
+
+
+ Prefetch & buswait time is not emulated.
+ Extra cycles for PUSH'ing or POP'ing registers to odd addresses is not emulated.
+*/
+
+#define CLK(all) nec_state->icount-=all
+#define CLKS(v20,v30,v33) { const UINT32 ccount=(v20<<16)|(v30<<8)|v33; nec_state->icount-=(ccount>>nec_state->chip_type)&0x7f; }
+#define CLKW(v20o,v30o,v33o,v20e,v30e,v33e,addr) { const UINT32 ocount=(v20o<<16)|(v30o<<8)|v33o, ecount=(v20e<<16)|(v30e<<8)|v33e; nec_state->icount-=(addr&1)?((ocount>>nec_state->chip_type)&0x7f):((ecount>>nec_state->chip_type)&0x7f); }
+#define CLKM(v20,v30,v33,v20m,v30m,v33m) { const UINT32 ccount=(v20<<16)|(v30<<8)|v33, mcount=(v20m<<16)|(v30m<<8)|v33m; nec_state->icount-=( ModRM >=0xc0 )?((ccount>>nec_state->chip_type)&0x7f):((mcount>>nec_state->chip_type)&0x7f); }
+#define CLKR(v20o,v30o,v33o,v20e,v30e,v33e,vall,addr) { const UINT32 ocount=(v20o<<16)|(v30o<<8)|v33o, ecount=(v20e<<16)|(v30e<<8)|v33e; if (ModRM >=0xc0) nec_state->icount-=vall; else nec_state->icount-=(addr&1)?((ocount>>nec_state->chip_type)&0x7f):((ecount>>nec_state->chip_type)&0x7f); }
+
+/************************************************************************/
+#define CompressFlags() (WORD)(CF | (nec_state->IBRK << 1) | (PF << 2) | (nec_state->F0 << 3) | (AF << 4) \
+ | (nec_state->F1 << 5) | (ZF << 6) | (SF << 7) | (nec_state->TF << 8) | (nec_state->IF << 9) \
+ | (nec_state->DF << 10) | (OF << 11) | (RB << 12) | (nec_state->MF << 15))
+
+#define ExpandFlags(f) \
+{ \
+ nec_state->CarryVal = (f) & 0x0001; \
+ nec_state->IBRK = ((f) & 0x0002) == 0x0002; \
+ nec_state->ParityVal = !((f) & 0x0004); \
+ nec_state->F0 = ((f) & 0x0008) == 0x0008; \
+ nec_state->AuxVal = (f) & 0x0010; \
+ nec_state->F1 = ((f) & 0x0020) == 0x0020; \
+ nec_state->ZeroVal = !((f) & 0x0040); \
+ nec_state->SignVal = (f) & 0x0080 ? -1 : 0; \
+ nec_state->TF = ((f) & 0x0100) == 0x0100; \
+ nec_state->IF = ((f) & 0x0200) == 0x0200; \
+ nec_state->DF = ((f) & 0x0400) == 0x0400; \
+ nec_state->OverVal = (f) & 0x0800; \
+ /* RB only changes on BRKCS/RETRBI/TSKSW, so skip it */ \
+ nec_state->MF = ((f) & 0x8000) == 0x8000; \
+}
diff --git a/trunk/src/emu/cpu/nec/v25sfr.c b/trunk/src/emu/cpu/nec/v25sfr.c
new file mode 100644
index 00000000000..95be5a0583f
--- /dev/null
+++ b/trunk/src/emu/cpu/nec/v25sfr.c
@@ -0,0 +1,400 @@
+/****************************************************************************
+
+ NEC V25/V35 special function registers and internal ram access
+
+****************************************************************************/
+
+#include "emu.h"
+#include "nec.h"
+#include "v25priv.h"
+
+static UINT8 read_irqcontrol(v25_state_t *nec_state, INTSOURCES source, UINT8 priority)
+{
+ return (((nec_state->pending_irq & source) ? 0x80 : 0x00)
+ | ((nec_state->unmasked_irq & source) ? 0x00 : 0x40)
+ | ((nec_state->bankswitch_irq & source) ? 0x10 : 0x00)
+ | priority);
+}
+
+static UINT8 read_sfr(v25_state_t *nec_state, unsigned o)
+{
+ UINT8 ret;
+
+ switch(o)
+ {
+ case 0x00: /* P0 */
+ ret = nec_state->io->read_byte(V25_PORT_P0);
+ break;
+ case 0x08: /* P1 */
+ /* P1 is combined with the interrupt lines */
+ ret = ((nec_state->io->read_byte(V25_PORT_P1) & 0xF0)
+ | (nec_state->nmi_state ? 0x00 : 0x01)
+ | (nec_state->intp_state[0] ? 0x00 : 0x02)
+ | (nec_state->intp_state[1] ? 0x00 : 0x04)
+ | (nec_state->intp_state[2] ? 0x00 : 0x08));
+ break;
+ case 0x10: /* P2 */
+ ret = nec_state->io->read_byte(V25_PORT_P2);
+ break;
+ case 0x38: /* PT */
+ ret = nec_state->io->read_byte(V25_PORT_PT);
+ break;
+ case 0x4C: /* EXIC0 */
+ ret = read_irqcontrol(nec_state, INTP0, nec_state->priority_intp);
+ break;
+ case 0x4D: /* EXIC1 */
+ ret = read_irqcontrol(nec_state, INTP1, 7);
+ break;
+ case 0x4E: /* EXIC2 */
+ ret = read_irqcontrol(nec_state, INTP2, 7);
+ break;
+ case 0x9C: /* TMIC0 */
+ ret = read_irqcontrol(nec_state, INTTU0, nec_state->priority_inttu);
+ break;
+ case 0x9D: /* TMIC1 */
+ ret = read_irqcontrol(nec_state, INTTU1, 7);
+ break;
+ case 0x9E: /* TMIC2 */
+ ret = read_irqcontrol(nec_state, INTTU2, 7);
+ break;
+ case 0xEA: /* FLAG */
+ ret = ((nec_state->F0 << 3) | (nec_state->F1 << 5));
+ break;
+ case 0xEB: /* PRC */
+ ret = (nec_state->RAMEN ? 0x40 : 0);
+ switch (nec_state->TB)
+ {
+ case 10:
+ break;
+ case 13:
+ ret |= 0x04;
+ break;
+ case 16:
+ ret |= 0x08;
+ break;
+ case 20:
+ ret |= 0x0C;
+ break;
+ }
+ switch (nec_state->PCK)
+ {
+ case 2:
+ break;
+ case 4:
+ ret |= 0x01;
+ break;
+ case 8:
+ ret |= 0x02;
+ break;
+ }
+ break;
+ case 0xEC: /* TBIC */
+ ret = read_irqcontrol(nec_state, INTTB, 7);
+ break;
+ case 0xEF: /* IRQS */
+ ret = nec_state->IRQS;
+ break;
+ case 0xFC: /* ISPR */
+ ret = nec_state->ISPR;
+ break;
+ case 0xFF: /* IDB */
+ ret = (nec_state->IDB >> 12);
+ break;
+ default:
+ logerror("%06x: Read from special function register %02x\n",PC(nec_state),o);
+ ret = 0;
+ }
+ return ret;
+}
+
+static UINT16 read_sfr_word(v25_state_t *nec_state, unsigned o)
+{
+ UINT16 ret;
+
+ switch(o)
+ {
+ case 0x80: /* TM0 */
+ logerror("%06x: Warning: read back TM0\n",PC(nec_state));
+ ret = nec_state->TM0;
+ break;
+ case 0x82: /* MD0 */
+ logerror("%06x: Warning: read back MD0\n",PC(nec_state));
+ ret = nec_state->MD0;
+ break;
+ case 0x88: /* TM1 */
+ logerror("%06x: Warning: read back TM1\n",PC(nec_state));
+ ret = nec_state->TM1;
+ break;
+ case 0x8A: /* MD1 */
+ logerror("%06x: Warning: read back MD1\n",PC(nec_state));
+ ret = nec_state->MD1;
+ break;
+ default:
+ ret = (read_sfr(nec_state, o) | (read_sfr(nec_state, o+1) << 8));
+ }
+ return ret;
+}
+
+static void write_irqcontrol(v25_state_t *nec_state, INTSOURCES source, UINT8 d)
+{
+ if(d & 0x80)
+ nec_state->pending_irq |= source;
+ else
+ nec_state->pending_irq &= ~source;
+
+ if(d & 0x40)
+ nec_state->unmasked_irq &= ~source;
+ else
+ nec_state->unmasked_irq |= source;
+
+ if(d & 0x20)
+ logerror("%06x: Warning: macro service function not implemented\n",PC(nec_state));
+
+ if(d & 0x10)
+ nec_state->bankswitch_irq |= source;
+ else
+ nec_state->bankswitch_irq &= ~source;
+}
+
+static void write_sfr(v25_state_t *nec_state, unsigned o, UINT8 d)
+{
+ int tmp;
+ attotime time;
+
+ static const int timebases[4] = { 10, 13, 16, 20 };
+ static const int clocks[4] = { 2, 4, 8, 0 };
+
+ switch(o)
+ {
+ case 0x00: /* P0 */
+ nec_state->io->write_byte(V25_PORT_P0, d);
+ break;
+ case 0x08: /* P1 */
+ /* only the upper four bits of P1 can be used as output */
+ nec_state->io->write_byte(V25_PORT_P1, d & 0xF0);
+ break;
+ case 0x10: /* P2 */
+ nec_state->io->write_byte(V25_PORT_P2, d);
+ break;
+ case 0x4C: /* EXIC0 */
+ write_irqcontrol(nec_state, INTP0, d);
+ nec_state->priority_intp = d & 0x7;
+ break;
+ case 0x4D: /* EXIC1 */
+ write_irqcontrol(nec_state, INTP1, d);
+ break;
+ case 0x4E: /* EXIC2 */
+ write_irqcontrol(nec_state, INTP2, d);
+ break;
+ case 0x90: /* TMC0 */
+ nec_state->TMC0 = d;
+ if(d & 1) /* oneshot mode */
+ {
+ if(d & 0x80)
+ {
+ tmp = nec_state->TM0 * nec_state->PCK * ((d & 0x40) ? 128 : 12 );
+ time = attotime::from_hz(nec_state->device->unscaled_clock()) * tmp;
+ nec_state->timers[0]->adjust(time, INTTU0);
+ }
+ else
+ nec_state->timers[0]->adjust(attotime::never);
+
+ if(d & 0x20)
+ {
+ tmp = nec_state->MD0 * nec_state->PCK * ((d & 0x10) ? 128 : 12 );
+ time = attotime::from_hz(nec_state->device->unscaled_clock()) * tmp;
+ nec_state->timers[1]->adjust(time, INTTU1);
+ }
+ else
+ nec_state->timers[1]->adjust(attotime::never);
+ }
+ else /* interval mode */
+ {
+ if(d & 0x80)
+ {
+ tmp = nec_state->MD0 * nec_state->PCK * ((d & 0x40) ? 128 : 6 );
+ time = attotime::from_hz(nec_state->device->unscaled_clock()) * tmp;
+ nec_state->timers[0]->adjust(time, INTTU0, time);
+ nec_state->timers[1]->adjust(attotime::never);
+ nec_state->TM0 = nec_state->MD0;
+ }
+ else
+ {
+ nec_state->timers[0]->adjust(attotime::never);
+ nec_state->timers[1]->adjust(attotime::never);
+ }
+ }
+ break;
+ case 0x91: /* TMC1 */
+ nec_state->TMC1 = d & 0xC0;
+ if(d & 0x80)
+ {
+ tmp = nec_state->MD1 * nec_state->PCK * ((d & 0x40) ? 128 : 6 );
+ time = attotime::from_hz(nec_state->device->unscaled_clock()) * tmp;
+ nec_state->timers[2]->adjust(time, INTTU2, time);
+ nec_state->TM1 = nec_state->MD1;
+ }
+ else
+ nec_state->timers[2]->adjust(attotime::never);
+ break;
+ case 0x9C: /* TMIC0 */
+ write_irqcontrol(nec_state, INTTU0, d);
+ nec_state->priority_inttu = d & 0x7;
+ break;
+ case 0x9D: /* TMIC1 */
+ write_irqcontrol(nec_state, INTTU1, d);
+ break;
+ case 0x9E: /* TMIC2 */
+ write_irqcontrol(nec_state, INTTU2, d);
+ break;
+ case 0xEA: /* FLAG */
+ nec_state->F0 = ((d & 0x08) == 0x08);
+ nec_state->F1 = ((d & 0x20) == 0x20);
+ break;
+ case 0xEB: /* PRC */
+ logerror("%06x: PRC set to %02x\n", PC(nec_state), d);
+ nec_state->RAMEN = ((d & 0x40) == 0x40);
+ nec_state->TB = timebases[(d & 0x0C) >> 2];
+ nec_state->PCK = clocks[d & 0x03];
+ if (nec_state->PCK == 0)
+ {
+ logerror(" Warning: invalid clock divider\n");
+ nec_state->PCK = 8;
+ }
+ tmp = nec_state->PCK << nec_state->TB;
+ time = attotime::from_hz(nec_state->device->unscaled_clock()) * tmp;
+ nec_state->timers[3]->adjust(time, INTTB, time);
+ logerror(" Internal RAM %sabled\n", (nec_state->RAMEN ? "en" : "dis"));
+ logerror(" Time base set to 2^%d\n", nec_state->TB);
+ logerror(" Clock divider set to %d\n", nec_state->PCK);
+ break;
+ case 0xEC: /* TBIC */
+ /* time base interrupt doesn't support macro service, bank switching or priority control */
+ write_irqcontrol(nec_state, INTTB, d & 0xC0);
+ break;
+ case 0xFF: /* IDB */
+ nec_state->IDB = (d << 12) | 0xE00;
+ logerror("%06x: IDB set to %02x\n",PC(nec_state),d);
+ break;
+ default:
+ logerror("%06x: Wrote %02x to special function register %02x\n",PC(nec_state),d,o);
+ }
+}
+
+static void write_sfr_word(v25_state_t *nec_state, unsigned o, UINT16 d)
+{
+ switch(o)
+ {
+ case 0x80: /* TM0 */
+ nec_state->TM0 = d;
+ break;
+ case 0x82: /* MD0 */
+ nec_state->MD0 = d;
+ break;
+ case 0x88: /* TM1 */
+ nec_state->TM1 = d;
+ break;
+ case 0x8A: /* MD1 */
+ nec_state->MD1 = d;
+ break;
+ default:
+ write_sfr(nec_state, o, d);
+ write_sfr(nec_state, o+1, d >> 8);
+ }
+}
+
+UINT8 v25_read_byte(v25_state_t *nec_state, unsigned a)
+{
+ if((a & 0xFFE00) == nec_state->IDB || a == 0xFFFFF)
+ {
+ unsigned o = a & 0x1FF;
+
+ if(nec_state->RAMEN && o < 0x100)
+ return nec_state->ram.b[BYTE_XOR_LE(o)];
+
+ if(o >= 0x100)
+ return read_sfr(nec_state, o-0x100);
+ }
+
+ return nec_state->program->read_byte(a);
+}
+
+UINT16 v25_read_word(v25_state_t *nec_state, unsigned a)
+{
+ if( a & 1 )
+ return (v25_read_byte(nec_state, a) | (v25_read_byte(nec_state, a + 1) << 8));
+
+ if((a & 0xFFE00) == nec_state->IDB)
+ {
+ unsigned o = a & 0x1FF;
+
+ if(nec_state->RAMEN && o < 0x100)
+ return nec_state->ram.w[o/2];
+
+ if(o >= 0x100)
+ return read_sfr_word(nec_state, o-0x100);
+ }
+
+ if(a == 0xFFFFE) /* not sure about this - manual says FFFFC-FFFFE are "reserved" */
+ return (nec_state->program->read_byte(a) | (read_sfr(nec_state, 0xFF) << 8));
+
+ return nec_state->program->read_word(a);
+}
+
+void v25_write_byte(v25_state_t *nec_state, unsigned a, UINT8 d)
+{
+ if((a & 0xFFE00) == nec_state->IDB || a == 0xFFFFF)
+ {
+ unsigned o = a & 0x1FF;
+
+ if(nec_state->RAMEN && o < 0x100)
+ {
+ nec_state->ram.b[BYTE_XOR_LE(o)] = d;
+ return;
+ }
+
+ if(o >= 0x100)
+ {
+ write_sfr(nec_state, o-0x100, d);
+ return;
+ }
+ }
+
+ nec_state->program->write_byte(a, d);
+}
+
+void v25_write_word(v25_state_t *nec_state, unsigned a, UINT16 d)
+{
+ if( a & 1 )
+ {
+ v25_write_byte(nec_state, a, d);
+ v25_write_byte(nec_state, a + 1, d >> 8);
+ return;
+ }
+
+ if((a & 0xFFE00) == nec_state->IDB)
+ {
+ unsigned o = a & 0x1FF;
+
+ if(nec_state->RAMEN && o < 0x100)
+ {
+ nec_state->ram.w[o/2] = d;
+ return;
+ }
+
+ if(o >= 0x100)
+ {
+ write_sfr_word(nec_state, o-0x100, d);
+ return;
+ }
+ }
+
+ if(a == 0xFFFFE) /* not sure about this - manual says FFFFC-FFFFE are "reserved" */
+ {
+ nec_state->program->write_byte(a, d);
+ write_sfr(nec_state, 0xFF, d >> 8);
+ return;
+ }
+
+ nec_state->program->write_word(a, d);
+}
diff --git a/trunk/src/emu/cpu/pdp1/pdp1.c b/trunk/src/emu/cpu/pdp1/pdp1.c
new file mode 100644
index 00000000000..f77ebb0a06b
--- /dev/null
+++ b/trunk/src/emu/cpu/pdp1/pdp1.c
@@ -0,0 +1,1890 @@
+/*
+ * Note: Original Java source written by:
+ *
+ * Barry Silverman mailto:barry@disus.com or mailto:bss@media.mit.edu
+ * Vadim Gerasimov mailto:vadim@media.mit.edu
+ *
+ * Basically, it has been rewritten entirely in order to perform cycle-level simulation
+ * (with only a few flip-flops being set one cycle too early or too late). I don't know if
+ * it is a good thing or a bad thing (it makes emulation more accurate, but slower, and
+ * code is more complex and less readable), but it appears to be the only way we could emulate
+ * mid-instruction sequence break. And it enables us to emulate the control panel fairly
+ * accurately.
+ *
+ * Additionnally, IOT functions have been modified to be external: IOT callback pointers are set
+ * at emulation initiation, and most IOT callback functions are part of the machine emulation.
+ *
+ *
+ * for the runnable java applet, with applet and Spacewar! source, go to:
+ * http://lcs.www.media.mit.edu/groups/el/projects/spacewar/
+ *
+ * for a complete html version of the pdp1 handbook go to:
+ * http://www.dbit.com/~greeng3/pdp1/index.html
+ *
+ * there is another java simulator (by the same people) which runs the
+ * original pdp1 LISP interpreter, go to:
+ * http://lcs.www.media.mit.edu/groups/el/projects/pdp1
+ *
+ * Another PDP1 emulator (or simulator) is at:
+ * ftp://minnie.cs.adfa.oz.au/pub/PDP-11/Sims/Supnik_2.3
+ * It seems to emulate pdp1 I/O more accurately than we do.
+ * However, there is no CRT emulation.
+ *
+ * and finally, there is a nice article about SPACEWAR!, go to:
+ * http://ars-www.uchicago.edu/~eric/lore/spacewar/spacewar.html
+ *
+ * some extra documentation is available on spies:
+ * http://www.spies.com/~aek/pdf/dec/pdp1/
+ * The file "F17_PDP1Maint.pdf" explains operation procedures and much of the internals of pdp-1.
+ * It was the main reference for this emulator.
+ * The file "F25_PDP1_IO.pdf" has interesting information on the I/O system, too.
+ *
+ * Following is an extract from the handbook:
+ *
+ * INTRODUCTION
+ *
+ * The Programmed Data Processor (PDP-1) is a high speed, solid state digital computer designed to
+ * operate with many types of input-output devices with no internal machine changes. It is a single
+ * address, single instruction, stored program computer with powerful program features. Five-megacycle
+ * circuits, a magnetic core memory and fully parallel processing make possible a computation rate of
+ * 100,000 additions per second. The PDP-1 is unusually versatile. It is easy to install, operate and
+ * maintain. Conventional 110-volt power is used, neither air conditioning nor floor reinforcement is
+ * necessary, and preventive maintenance is provided for by built-in marginal checking circuits.
+ *
+ * PDP-1 circuits are based on the designs of DEC's highly successful and reliable System Modules.
+ * Flip-flops and most switches use saturating transistors. Primary active elements are
+ * Micro-Alloy-Diffused transistors.
+ *
+ * The entire computer occupies only 17 square feet of floor space. It consists of four equipment frames,
+ * one of which is used as the operating station.
+ *
+ * CENTRAL PROCESSOR
+ *
+ * The Central Processor contains the control, arithmetic and memory addressing elements, and the memory
+ * buffer register. The word length is 18 binary digits. Instructions are performed in multiples of the
+ * memory cycle time of five microseconds. Add, subtract, deposit, and load, for example, are two-cycle
+ * instructions requiring 10 microseconds. Multiplication requires and average of 20 microseconds.
+ * Program features include: single address instructions, multiple step indirect addressing and logical
+ * arithmetic commands. Console features include: flip-flop indicators grouped for convenient octal
+ * reading, six program flags for automatic setting and computer sensing, and six sense switches for
+ * manual setting and computer sensing.
+ *
+ * MEMORY SYSTEM
+ *
+ * The coincident-current, magnetic core memory of a standard PDP-1 holds 4096 words of 18 bits each.
+ * Memory capacity may be readily expanded, in increments of 4096 words, to a maximum of 65,536 words.
+ * The read-rewrite time of the memory is five microseconds, the basic computer rate. Driving currents
+ * are automatically adjusted to compensate for temperature variations between 50 and 110 degrees
+ * Fahrenheit. The core memory storage may be supplemented by up to 24 magnetic tape transports.
+ *
+ * INPUT-OUTPUT
+ *
+ * PDP-1 is designed to operate a variety of buffered input-output devices. Standard equipment consistes
+ * of a perforated tape reader with a read speed of 400 lines per second, and alphanuermic typewriter for
+ * on-line operation in both input and output, and a perforated tape punch (alphanumeric or binary) with
+ * a speed of 63 lines per second. A variety of optional equipment is available, including the following:
+ *
+ * Precision CRT Display Type 30
+ * Ultra-Precision CRT Display Type 31
+ * Symbol Generator Type 33
+ * Light Pen Type 32
+ * Oscilloscope Display Type 34
+ * Card Punch Control Type 40-1
+ * Card Reader and Control Type 421
+ * Magnetic Tape Transport Type 50
+ * Programmed Magnetic Tape Control Type 51
+ * Automatic Magnetic Tape Control Type 52
+ * Automatic Magnetic Tape Control Type 510
+ * Parallel Drum Type 23
+ * Automatic Line Printer and Control Type 64
+ * 18-bit Real Time Clock
+ * 18-bit Output Relay Buffer Type 140
+ * Multiplexed A-D Converter Type 138/139
+ *
+ * All in-out operations are performed through the In-Out Register or through the high speed input-output
+ * channels.
+ *
+ * The PDP-1 is also available with the optional Sequence Break System. This is a multi-channel priority
+ * interrupt feature which permits concurrent operation of several in-out devices. A one-channel Sequence
+ * Break System is included in the standard PDP-1. Optional Sequence Break Systems consist of 16, 32, 64,
+ * 128, and 256 channels.
+ *
+ * ...
+ *
+ * BASIC INSTRUCTIONS
+ *
+ * OPER. TIME
+ * INSTRUCTION CODE # EXPLANATION (usec)
+ * ------------------------------------------------------------------------------
+ * add Y 40 Add C(Y) to C(AC) 10
+ * and Y 02 Logical AND C(Y) with C(AC) 10
+ * cal Y 16 Equals jda 100 10
+ * dac Y 24 Deposit C(AC) in Y 10
+ * dap Y 26 Deposit contents of address part of AC in Y 10
+ * dio Y 32 Deposit C(IO) in Y 10
+ * dip Y 30 Deposit contents of instruction part of AC in Y 10
+ * div Y 56 Divide 40 max
+ * dzm Y 34 Deposit zero in Y 10
+ * idx Y 44 Index (add one) C(Y), leave in Y & AC 10
+ * ior Y 04 Inclusive OR C(Y) with C(AC) 10
+ * iot Y 72 In-out transfer, see below
+ * isp Y 46 Index and skip if result is positive 10
+ * jda Y 17 Equals dac Y and jsp Y+1 10
+ * jmp Y 60 Take next instruction from Y 5
+ * jsp Y 62 Jump to Y and save program counter in AC 5
+ * lac Y 20 Load the AC with C(Y) 10
+ * law N 70 Load the AC with the number N 5
+ * law-N 71 Load the AC with the number -N 5
+ * lio Y 22 Load IO with C(Y) 10
+ * mul Y 54 Multiply 25 max
+ * opr 76 Operate, see below 5
+ * sad Y 50 Skip next instruction if C(AC) <> C(Y) 10
+ * sas Y 52 Skip next instruction if C(AC) = C(Y) 10
+ * sft 66 Shift, see below 5
+ * skp 64 Skip, see below 5
+ * sub Y 42 Subtract C(Y) from C(AC) 10
+ * xct Y 10 Execute instruction in Y 5+
+ * xor Y 06 Exclusive OR C(Y) with C(AC) 10
+ *
+ * OPERATE GROUP
+ *
+ * OPER. TIME
+ * INSTRUCTION CODE # EXPLANATION (usec)
+ * ------------------------------------------------------------------------------
+ * cla 760200 Clear AC 5
+ * clf 76000f Clear selected Program Flag (f = flag #) 5
+ * cli 764000 Clear IO 5
+ * cma 761000 Complement AC 5
+ * hlt 760400 Halt 5
+ * lap 760100 Load AC with Program Counter 5
+ * lat 762200 Load AC from Test Word switches 5
+ * nop 760000 No operation 5
+ * stf 76001f Set selected Program Flag 5
+ *
+ * IN-OUT TRANSFER GROUP
+ *
+ * PERFORATED TAPE READER
+ *
+ * INSTRUCTION CODE # EXPLANATION
+ * ------------------------------------------------------------------------------
+ * rpa 720001 Read Perforated Tape Alphanumeric
+ * rpb 720002 Read Perforated Tape Binary
+ * rrb 720030 Read Reader Buffer
+ *
+ * PERFORATED TAPE PUNCH
+ *
+ * INSTRUCTION CODE # EXPLANATION
+ * ------------------------------------------------------------------------------
+ * ppa 720005 Punch Perforated Tape Alphanumeric
+ * ppb 720006 Punch Perforated Tape Binary
+ *
+ * ALPHANUMERIC ON-LINE TYPEWRITER
+ *
+ * INSTRUCTION CODE # EXPLANATION
+ * ------------------------------------------------------------------------------
+ * tyo 720003 Type Out
+ * tyi 720004 Type In
+ *
+ * SEQUENCE BREAK SYSTEM TYPE 120
+ *
+ * INSTRUCTION CODE # EXPLANATION
+ * ------------------------------------------------------------------------------
+ * esm 720055 Enter Sequence Break Mode
+ * lsm 720054 Leave Sequence Break Mode
+ * cbs 720056 Clear Sequence Break System
+ * dsc 72kn50 Deactivate Sequence Break Channel
+ * asc 72kn51 Activate Sequence Break Channel
+ * isb 72kn52 Initiate Sequence Break
+ * cac 720053 Clear All Channels
+ *
+ * HIGH SPEED DATA CONTROL TYPE 131
+ *
+ * INSTRUCTION CODE # EXPLANATION
+ * ------------------------------------------------------------------------------
+ * swc 72x046 Set Word Counter
+ * sia 720346 Set Location Counter
+ * sdf 720146 Stop Data Flow
+ * rlc 720366 Read Location Counter
+ * shr 720446 Set High Speed Channel Request
+ *
+ * PRECISION CRT DISPLAY TYPE 30
+ *
+ * INSTRUCTION CODE # EXPLANATION
+ * ------------------------------------------------------------------------------
+ * dpy 720007 Display One Point
+ *
+ * SYMBOL GENERATOR TYPE 33
+ *
+ * INSTRUCTION CODE # EXPLANATION
+ * ------------------------------------------------------------------------------
+ * gpl 722027 Generator Plot Left
+ * gpr 720027 Generator Plot Right
+ * glf 722026 Load Format
+ * gsp 720026 Space
+ * sdb 722007 Load Buffer, No Intensity
+ *
+ * ULTRA-PRECISION CRT DISPLAY TYPE 31
+ *
+ * INSTRUCTION CODE # EXPLANATION
+ * ------------------------------------------------------------------------------
+ * dpp 720407 Display One Point on Ultra Precision CRT
+ *
+ * CARD PUNCH CONTROL TYPE 40-1
+ *
+ * INSTRUCTION CODE # EXPLANATION
+ * ------------------------------------------------------------------------------
+ * lag 720044 Load a Group
+ * pac 720043 Punch a Card
+ *
+ * CARD READER TYPE 421
+ *
+ * INSTRUCTION CODE # EXPLANATION
+ * ------------------------------------------------------------------------------
+ * rac 720041 Read Card Alpha
+ * rbc 720042 Read Card Binary
+ * rcc 720032 Read Card Column
+ *
+ * PROGRAMMED MAGNETIC TAPE CONTROL TYPE 51
+ *
+ * INSTRUCTION CODE # EXPLANATION
+ * ------------------------------------------------------------------------------
+ * msm 720073 Select Mode
+ * mcs 720034 Check Status
+ * mcb 720070 Clear Buffer
+ * mwc 720071 Write a Character
+ * mrc 720072 Read Character
+ *
+ * AUTOMATIC MAGNETIC TAPE CONTROL TYPE 52
+ *
+ * INSTRUCTION CODE # EXPLANATION
+ * ------------------------------------------------------------------------------
+ * muf 72ue76 Tape Unit and FinalT
+ * mic 72ue75 Initial and Command
+ * mrf 72u067 Reset Final
+ * mri 72ug66 Reset Initial
+ * mes 72u035 Examine States
+ * mel 72u036 Examine Location
+ * inr 72ur67 Initiate a High Speed Channel Request
+ * ccr 72s067 Clear Command Register
+ *
+ * AUTOMATIC MAGNETIC TAPE CONTROL TYPE 510
+ *
+ * INSTRUCTION CODE # EXPLANATION
+ * ------------------------------------------------------------------------------
+ * sfc 720072 Skip if Tape Control Free
+ * rsr 720172 Read State Register
+ * crf 720272 Clear End-of-Record Flip-Flop
+ * cpm 720472 Clear Proceed Mode
+ * dur 72xx70 Load Density, Unit, Rewind
+ * mtf 73xx71 Load Tape Function Register
+ * cgo 720073 Clear Go
+ *
+ * MULTIPLEXED A-D CONVERTER TYPE 138/139
+ *
+ * INSTRUCTION CODE # EXPLANATION
+ * ------------------------------------------------------------------------------
+ * rcb 720031 Read Converter Buffer
+ * cad 720040 Convert a Voltage
+ * scv 72mm47 Select Multiplexer (1 of 64 Channels)
+ * icv 720060 Index Multiplexer
+ *
+ * AUTOMATIC LINE PRINTER TYPE 64
+ *
+ * INSTRUCTION CODE # EXPLANATION
+ * ------------------------------------------------------------------------------
+ * clrbuf 722045 Clear Buffer
+ * lpb 720045 Load Printer Buffer
+ * pas 721x45 Print and Space
+ *
+ * SKIP GROUP
+ *
+ * OPER. TIME
+ * INSTRUCTION CODE # EXPLANATION (usec)
+ * ------------------------------------------------------------------------------
+ * sma 640400 Dkip on minus AC 5
+ * spa 640200 Skip on plus AC 5
+ * spi 642000 Skip on plus IO 5
+ * sza 640100 Skip on ZERO (+0) AC 5
+ * szf 6400f Skip on ZERO flag 5
+ * szo 641000 Skip on ZERO overflow (and clear overflow) 5
+ * szs 6400s0 Skip on ZERO sense switch 5
+ *
+ * SHIFT/ROTATE GROUP
+ *
+ * OPER. TIME
+ * INSTRUCTION CODE # EXPLANATION (usec)
+ * ------------------------------------------------------------------------------
+ * ral 661 Rotate AC left 5
+ * rar 671 Rotate AC right 5
+ * rcl 663 Rotate Combined AC & IO left 5
+ * rcr 673 Rotate Combined AC & IO right 5
+ * ril 662 Rotate IO left 5
+ * rir 672 Rotate IO right 5
+ * sal 665 Shift AC left 5
+ * sar 675 Shift AC right 5
+ * scl 667 Shift Combined AC & IO left 5
+ * scr 677 Shift Combined AC & IO right 5
+ * sil 666 Shift IO left 5
+ * sir 676 Shift IO right 5
+ */
+
+
+/*
+ TODO:
+ * support other extensions as time permits
+*/
+
+
+#include "emu.h"
+#include "debugger.h"
+#include "pdp1.h"
+
+#define LOG 0
+#define LOG_EXTRA 0
+#define LOG_IOT_EXTRA 0
+
+#define READ_PDP_18BIT(A) ((signed)cpustate->program->read_dword((A)<<2))
+#define WRITE_PDP_18BIT(A,V) (cpustate->program->write_dword((A)<<2,(V)))
+
+
+/* PDP1 Registers */
+typedef struct _pdp1_state pdp1_state;
+struct _pdp1_state
+{
+ /* processor registers */
+ UINT32 pc; /* program counter (12, 15 or 16 bits) */
+ int ir; /* basic operation code of current instruction (5 bits) */
+ int mb; /* memory buffer (used for holding the current instruction only) (18 bits) */
+ int ma; /* memory address (12, 15 or 16 bits) */
+ int ac; /* accumulator (18 bits) */
+ int io; /* i/o register (18 bits) */
+ int pf; /* program flag register (6 bits) */
+
+ /* operator panel switches */
+ int ta; /* current state of the 12 or 16 address switches */
+ int tw; /* current state of the 18 test word switches */
+ int ss; /* current state of the 6 sense switches on the operator panel (6 bits) */
+ unsigned int sngl_step : 1; /* stop every memory cycle */
+ unsigned int sngl_inst : 1; /* stop every instruction */
+ unsigned int extend_sw : 1; /* extend switch (loaded into the extend flip-flop on start/read-in) */
+
+ /* processor state flip-flops */
+ unsigned int run : 1; /* processor is running */
+ unsigned int cycle : 1; /* processor is in the midst of an instruction */
+ unsigned int defer : 1; /* processor is handling deferred (i.e. indirect) addressing */
+ unsigned int brk_ctr : 2; /* break counter */
+ unsigned int ov; /* overflow flip-flop */
+ unsigned int rim : 1; /* processor is in read-in mode */
+
+ unsigned int sbm : 1; /* processor is in sequence break mode (i.e. interrupts are enabled) */
+
+ unsigned int exd : 1; /* extend mode: processor is in extend mode */
+ unsigned int exc : 1; /* extend-mode cycle: current instruction cycle is done in extend mode */
+ unsigned int ioc : 1; /* i-o commands: seems to be equivalent to (! ioh) */
+ unsigned int ioh : 1; /* i-o halt: processor is executing an Input-Output Transfer wait */
+ unsigned int ios : 1; /* i-o synchronizer: set on i-o operation completion */
+
+ /* sequence break system */
+ unsigned int irq_state : 16; /* mirrors the state of the interrupt pins */
+ unsigned int b1 : 16; /* interrupt enable */
+ unsigned int b2 : 16; /* interrupt pulse request pending - asynchronous with computer operation (set by pulses on irq_state, cleared when interrupt is taken) */
+ /*unsigned int b3 : 16;*/ /* interrupt request pending - synchronous with computer operation (logical or of irq_state and b2???) */
+ unsigned int b4 : 16; /* interrupt in progress */
+
+ /* additional emulator state variables */
+ int rim_step; /* current step in rim execution */
+ int sbs_request; /* interrupt request (i.e. (b3 & (~ b4)) && (! sbm)) */
+ int sbs_level; /* interrupt request level (first bit in (b3 & (~ b4)) */
+ int sbs_restore; /* set when a jump instruction is an interrupt return */
+ int no_sequence_break; /* disable sequence break recognition for one cycle */
+
+ /* callbacks for iot instructions (required for any I/O) */
+ pdp1_extern_iot_func extern_iot[64];
+ /* read a word from the perforated tape reader (required for read-in mode) */
+ pdp1_read_binary_word_func read_binary_word;
+ /* callback called when sc is pulsed: IO devices should reset */
+ pdp1_io_sc_func io_sc_callback;
+
+ /* 0: no extend support, 1: extend with 15-bit address, 2: extend with 16-bit address */
+ int extend_support;
+
+ int extended_address_mask; /* 07777 with no extend support, 077777 or 0177777 with extend support */
+ int address_extension_mask; /* 00000 with no extend support, 070000 or 0170000 with extend support */
+
+ /* 1 to use hardware multiply/divide (MUL, DIV) instead of MUS, DIS */
+ int hw_mul_div;
+
+ /* 1 for 16-line sequence break system, 0 for default break system */
+ int type_20_sbs;
+
+ legacy_cpu_device *device;
+ address_space *program;
+ int icount;
+};
+
+INLINE pdp1_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == PDP1);
+ return (pdp1_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+static void execute_instruction(pdp1_state *cpustate);
+static void null_iot (device_t *device, int op2, int nac, int mb, int *io, int ac);
+static void lem_eem_iot(device_t *device, int op2, int nac, int mb, int *io, int ac);
+static void sbs_iot(device_t *device, int op2, int nac, int mb, int *io, int ac);
+static void type_20_sbs_iot(device_t *device, int op2, int nac, int mb, int *io, int ac);
+static void pulse_start_clear(pdp1_state *cpustate);
+
+
+
+#define PC cpustate->pc
+#define IR cpustate->ir
+#define MB cpustate->mb
+#define MA cpustate->ma
+#define AC cpustate->ac
+#define IO cpustate->io
+#define OV cpustate->ov
+#define EXD cpustate->exd
+/* note that we start counting flags/sense switches at 1, therefore n is in [1,6] */
+#define FLAGS cpustate->pf
+#define READFLAG(n) ((cpustate->pf >> (6-(n))) & 1)
+#define WRITEFLAG(n, data) (cpustate->pf = (cpustate->pf & ~(1 << (6-(n)))) | (((data) & 1) << (6-(n))))
+#define SENSE_SW cpustate->ss
+#define READSENSE(n) ((cpustate->ss >> (6-(n))) & 1)
+#define WRITESENSE(n, data) (cpustate->ss = (cpustate->ss & ~(1 << (6-(n)))) | (((data) & 1) << (6-(n))))
+
+#define EXTENDED_ADDRESS_MASK cpustate->extended_address_mask
+#define ADDRESS_EXTENSION_MASK cpustate->address_extension_mask
+#define BASE_ADDRESS_MASK 0007777
+
+#define INCREMENT_PC (PC = (PC & ADDRESS_EXTENSION_MASK) | ((PC+1) & BASE_ADDRESS_MASK))
+#define DECREMENT_PC (PC = (PC & ADDRESS_EXTENSION_MASK) | ((PC-1) & BASE_ADDRESS_MASK))
+#define INCREMENT_MA (MA = (MA & ADDRESS_EXTENSION_MASK) | ((MA+1) & BASE_ADDRESS_MASK))
+#define PREVIOUS_PC ((PC & ADDRESS_EXTENSION_MASK) | ((PC-1) & BASE_ADDRESS_MASK))
+
+
+
+/*
+ Interrupts are called "sequence break" in pdp1, but the general idea is the same.
+
+ There are several interrupt lines. With the standard sequence break system, all lines
+ are logically or'ed to trigger a single interrupt level. Interrupts can be triggered
+ by either a pulse or a level on the interrupt lines. With the optional type 120 sequence
+ break system, each of 16 lines triggers is wired to a different priority level: additionnally,
+ each interrupt line can be masked out, and interrupt can be triggered through software.
+
+ Also, instructions can be interrupted in the middle of execution. This is done by
+ decrementing the PC register: therefore the instruction is re-executed from start.
+
+ Interrupt routines should not execute most IOT, as the interrupt may interrupt another.
+
+ More details can be found in the handbook and the maintenance manual.
+*/
+/*
+ This function MUST be called every time cpustate->sbm, cpustate->b4, cpustate->irq_state or cpustate->b2 change.
+*/
+static void field_interrupt(pdp1_state *cpustate)
+{
+ /* current_irq: 1 bit for each active pending interrupt request
+ Pending interrupts are in b3 (simulated by (cpustate->irq_state & cpustate->b1) | cpustate->b2)), but they
+ are only honored if no higher priority interrupt routine is in execution (one bit set in b4
+ for each routine in execution). The revelant mask is created with (cpustate->b4 | (- cpustate->b4)),
+ as the carry chain (remember that -b4 = (~ b4) + 1) does precisely what we want.
+ b4: 0001001001000
+ -b4: 1110110111000
+ b4|-b4:1111111111000
+ Neat, uh?
+ */
+ int current_irq = ((cpustate->irq_state & cpustate->b1) | cpustate->b2) & ~ (cpustate->b4 | (- cpustate->b4));
+ int i;
+
+ if (cpustate->sbm && current_irq)
+ {
+ cpustate->sbs_request = 1;
+ for (i=0; /*i<16 &&*/ (! ((current_irq >> i) & 1)); i++)
+ ;
+ cpustate->sbs_level = i;
+ }
+ else
+ cpustate->sbs_request = 0;
+}
+
+static void pdp1_set_irq_line (pdp1_state *cpustate, int irqline, int state)
+{
+ if (irqline == INPUT_LINE_NMI)
+ {
+ /* no specific NMI line */
+ }
+ else if ((irqline >= 0) && (irqline < (cpustate->type_20_sbs ? 1 : 16)))
+ {
+ unsigned int new_state = state ? 1 : 0;
+
+ if (((cpustate->irq_state >> irqline) & 1) != new_state)
+ {
+ cpustate->irq_state = (cpustate->irq_state & ~ (1 << irqline)) | (new_state << irqline);
+
+ if ((new_state) && ((cpustate->b1 >> irqline) & 1))
+ cpustate->b2 |= (new_state << irqline);
+
+ /*cpustate->b3 = cpustate->irq_state | cpustate->b2;*/
+
+ field_interrupt(cpustate); /* interrupt state has changed */
+ }
+ }
+}
+
+
+static CPU_INIT( pdp1 )
+{
+ const pdp1_reset_param_t *param = (const pdp1_reset_param_t *)device->static_config();
+ pdp1_state *cpustate = get_safe_token(device);
+ int i;
+
+ /* clean-up */
+ memset (cpustate, 0, sizeof (*cpustate));
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+
+ /* set up params and callbacks */
+ for (i=0; i<64; i++)
+ {
+ cpustate->extern_iot[i] = (param && param->extern_iot[i])
+ ? param->extern_iot[i]
+ : null_iot;
+ }
+ cpustate->read_binary_word = (param) ? param->read_binary_word : NULL;
+ cpustate->io_sc_callback = (param) ? param->io_sc_callback : NULL;
+ cpustate->extend_support = (param) ? param->extend_support : 0;
+ cpustate->hw_mul_div = (param) ? param->hw_mul_div : 0;
+ cpustate->type_20_sbs = (param) ? param->type_20_sbs : 0;
+
+ switch (cpustate->extend_support)
+ {
+ default:
+ cpustate->extend_support = 0;
+ case 0: /* no extension */
+ cpustate->extended_address_mask = 07777;
+ cpustate->address_extension_mask = 00000;
+ break;
+ case 1: /* 15-bit extension */
+ cpustate->extended_address_mask = 077777;
+ cpustate->address_extension_mask = 070000;
+ break;
+ case 2: /* 16-bit extension */
+ cpustate->extended_address_mask = 0177777;
+ cpustate->address_extension_mask = 0170000;
+ break;
+ }
+
+ if (cpustate->extend_support)
+ {
+ cpustate->extern_iot[074] = lem_eem_iot;
+ }
+ cpustate->extern_iot[054] = cpustate->extern_iot[055] = cpustate->extern_iot[056] = sbs_iot;
+ if (cpustate->type_20_sbs)
+ {
+ cpustate->extern_iot[050] = cpustate->extern_iot[051] = cpustate->extern_iot[052] = cpustate->extern_iot[053]
+ = type_20_sbs_iot;
+ }
+
+ /* reset CPU flip-flops */
+ pulse_start_clear(cpustate);
+}
+
+static CPU_RESET( pdp1 )
+{
+ /* nothing to do */
+}
+
+/*
+ flags:
+ * 1 for each instruction which supports indirect addressing (memory reference instructions,
+ except cal and jda, and with the addition of jmp and jsp)
+ * 2 for memory reference instructions
+*/
+static const char instruction_kind[32] =
+{
+/* and ior xor xct cal/jda */
+ 0, 3, 3, 3, 3, 0, 0, 2,
+/* lac lio dac dap dip dio dzm */
+ 3, 3, 3, 3, 3, 3, 3, 0,
+/* add sub idx isp sad sas mus dis */
+ 3, 3, 3, 3, 3, 3, 3, 3,
+/* jmp jsp skp sft law iot opr */
+ 1, 1, 0, 0, 0, 0, 0, 0
+};
+
+
+/* execute instructions on this CPU until icount expires */
+static CPU_EXECUTE( pdp1 )
+{
+ pdp1_state *cpustate = get_safe_token(device);
+
+ do
+ {
+ debugger_instruction_hook(device, PC);
+
+
+ /* ioh should be cleared at the end of the instruction cycle, and ios at the
+ start of next instruction cycle, but who cares? */
+ if (cpustate->ioh && cpustate->ios)
+ {
+ cpustate->ioh = 0;
+ cpustate->ios = 0;
+ }
+
+
+ if ((! cpustate->run) && (! cpustate->rim))
+ cpustate->icount = 0; /* if processor is stopped, just burn cycles */
+ else if (cpustate->rim)
+ {
+ switch (cpustate->rim_step)
+ {
+ case 0:
+ /* read first word as instruction */
+ if (cpustate->read_binary_word)
+ (*cpustate->read_binary_word)(cpustate->device); /* data will be transferred to IO register */
+ cpustate->rim_step = 1;
+ break;
+
+ case 1:
+ if (! cpustate->ios)
+ { /* transfer incomplete: wait some more */
+ cpustate->icount = 0;
+ }
+ else
+ { /* data transfer complete */
+ cpustate->ios = 0;
+
+ MB = IO;
+ IR = MB >> 13; /* basic opcode */
+ if (IR == JMP) /* jmp instruction ? */
+ {
+ PC = (MA & ADDRESS_EXTENSION_MASK) | (MB & BASE_ADDRESS_MASK);
+ cpustate->rim = 0; /* exit read-in mode */
+ cpustate->run = 1;
+ cpustate->rim_step = 0;
+ }
+ else if ((IR == DIO) || (IR == DAC)) /* dio or dac instruction ? */
+ { /* there is a discrepancy: the pdp1 handbook tells that only dio should be used,
+ but the lisp tape uses the dac instruction instead */
+ /* Yet maintainance manual p. 6-25 states clearly that the data is located
+ in IO and transfered to MB, so DAC is likely to be a mistake. */
+ cpustate->rim_step = 2;
+ }
+ else
+ {
+ /* what the heck? */
+ if (LOG)
+ logerror("It seems this tape should not be operated in read-in mode\n");
+
+ cpustate->rim = 0; /* exit read-in mode (right???) */
+ cpustate->rim_step = 0;
+ }
+ }
+ break;
+
+ case 2:
+ /* read second word as data */
+ if (cpustate->read_binary_word)
+ (*cpustate->read_binary_word)(cpustate->device); /* data will be transferred to IO register */
+ cpustate->rim_step = 3;
+ break;
+
+ case 3:
+ if (! cpustate->ios)
+ { /* transfer incomplete: wait some more */
+ cpustate->icount = 0;
+ }
+ else
+ { /* data transfer complete */
+ cpustate->ios = 0;
+
+ MA = (PC & ADDRESS_EXTENSION_MASK) | (MB & BASE_ADDRESS_MASK);
+
+ MB = IO;
+ WRITE_PDP_18BIT(MA, MB);
+
+ cpustate->rim_step = 0;
+ }
+ break;
+ }
+ }
+ else
+ {
+ /* yes, interrupt can occur in the midst of an instruction (impressing, huh?) */
+ /* Note that break cannot occur during a one-cycle jump that is deferred only once,
+ or another break cycle. Also, it cannot interrupt the long cycle 1 of automatic
+ multiply/divide. (maintainance manual 6-19) */
+ if (cpustate->sbs_request && (! cpustate->no_sequence_break) && (! cpustate->brk_ctr))
+ { /* begin sequence break */
+ cpustate->brk_ctr = 1;
+ }
+ if (cpustate->brk_ctr)
+ { /* sequence break in progress */
+ switch (cpustate->brk_ctr)
+ {
+ case 1:
+ if (cpustate->cycle)
+ DECREMENT_PC; /* set PC to point to aborted instruction, so that it can be re-run */
+
+ cpustate->b4 |= (1 << cpustate->sbs_level); /* set "interrupt in progress" flag */
+ cpustate->b2 &= ~(1 << cpustate->sbs_level); /* clear interrupt request */
+ field_interrupt(cpustate);
+ MA = cpustate->sbs_level << 2; /* always 0 with standard sequence break system */
+ MB = AC; /* save AC to MB */
+ AC = (OV << 17) | (EXD << 16) | PC; /* save OV/EXD/PC to AC */
+ EXD = OV = 0; /* according to maintainance manual p. 8-17 and ?-?? */
+ cpustate->cycle = cpustate->defer = cpustate->exc = 0; /* mere guess */
+ WRITE_PDP_18BIT(MA, MB); /* save former AC to memory */
+ INCREMENT_MA;
+ cpustate->icount -= 5;
+ cpustate->brk_ctr++;
+ break;
+
+ case 2:
+ WRITE_PDP_18BIT(MA, MB = AC); /* save former OV/EXD/PC to memory */
+ INCREMENT_MA;
+ cpustate->icount -= 5;
+ cpustate->brk_ctr++;
+ break;
+
+ case 3:
+ WRITE_PDP_18BIT(MA, MB = IO); /* save IO to memory */
+ INCREMENT_MA;
+ PC = MA;
+ cpustate->icount -= 5;
+ cpustate->brk_ctr = 0;
+ break;
+ }
+ }
+ else
+ {
+ if (cpustate->no_sequence_break)
+ cpustate->no_sequence_break = 0;
+
+ if (! cpustate->cycle)
+ { /* no instruction in progress: time to fetch a new instruction, I guess */
+ MB = READ_PDP_18BIT(MA = PC);
+ INCREMENT_PC;
+ IR = MB >> 13; /* basic opcode */
+
+ if ((instruction_kind[IR] & 1) && (MB & 010000))
+ {
+ cpustate->defer = 1;
+ cpustate->cycle = 1; /* instruction shall be executed later */
+
+ /* detect deferred one-cycle jumps */
+ if ((IR == JMP) || (IR == JSP))
+ {
+ cpustate->no_sequence_break = 1;
+ /* detect JMP *(4*n+1) to memory module 0 if in sequence break mode */
+ if (((MB & 0777703) == 0610001) && (cpustate->sbm) && ! (MA & 0170000))
+ {
+ int level = (MB & 0000074) >> 2;
+
+ if ((cpustate->type_20_sbs) || (level == 0))
+ {
+ cpustate->b4 &= ~(1 << level);
+ field_interrupt(cpustate);
+ if (cpustate->extend_support)
+ EXD = 1; /* according to maintainance manual p. 6-33 */
+ cpustate->sbs_restore = 1;
+ }
+ }
+ }
+ }
+ else if (instruction_kind[IR] & 2)
+ cpustate->cycle = 1; /* instruction shall be executed later */
+ else
+ execute_instruction(cpustate); /* execute instruction at once */
+
+ cpustate->icount -= 5;
+ }
+ else if (cpustate->defer)
+ { /* defer cycle : handle indirect addressing */
+ MA = (PC & ADDRESS_EXTENSION_MASK) | (MB & BASE_ADDRESS_MASK);
+
+ MB = READ_PDP_18BIT(MA);
+
+ /* determinate new value of cpustate->defer */
+ if (EXD)
+ {
+ cpustate->defer = 0;
+ cpustate->exc = 1;
+ }
+ else
+ cpustate->defer = (MB & 010000) ? 1 : 0;
+
+ /* execute JMP and JSP immediately if applicable */
+ if ((! cpustate->defer) && (! (instruction_kind[IR] & 2)))
+ {
+ execute_instruction(cpustate); /* execute instruction at once */
+ /*cpustate->cycle = 0;*/
+ cpustate->exc = 0;
+
+ if (cpustate->sbs_restore)
+ { /* interrupt return: according to maintainance manual p. 6-33 */
+ if (cpustate->extend_support)
+ EXD = (MB >> 16) & 1;
+ OV = (MB >> 17) & 1;
+ cpustate->sbs_restore = 0;
+ }
+ }
+
+ cpustate->icount -= 5;
+ }
+ else
+ { /* memory reference instruction in cycle 1 */
+ if (cpustate->exc)
+ {
+ MA = MB & EXTENDED_ADDRESS_MASK;
+ cpustate->exc = 0;
+ }
+ else
+ MA = (PC & ADDRESS_EXTENSION_MASK) | (MB & BASE_ADDRESS_MASK);
+
+ execute_instruction(cpustate); /* execute instruction */
+
+ cpustate->icount -= 5;
+ }
+
+ if ((cpustate->sngl_inst) && (! cpustate->cycle))
+ cpustate->run = 0;
+ }
+ if (cpustate->sngl_step)
+ cpustate->run = 0;
+ }
+ }
+ while (cpustate->icount > 0);
+}
+
+
+static CPU_SET_INFO( pdp1 )
+{
+ pdp1_state *cpustate = get_safe_token(device);
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + 0:
+ case CPUINFO_INT_INPUT_STATE + 1:
+ case CPUINFO_INT_INPUT_STATE + 2:
+ case CPUINFO_INT_INPUT_STATE + 3:
+ case CPUINFO_INT_INPUT_STATE + 4:
+ case CPUINFO_INT_INPUT_STATE + 5:
+ case CPUINFO_INT_INPUT_STATE + 6:
+ case CPUINFO_INT_INPUT_STATE + 7:
+ case CPUINFO_INT_INPUT_STATE + 8:
+ case CPUINFO_INT_INPUT_STATE + 9:
+ case CPUINFO_INT_INPUT_STATE + 10:
+ case CPUINFO_INT_INPUT_STATE + 11:
+ case CPUINFO_INT_INPUT_STATE + 12:
+ case CPUINFO_INT_INPUT_STATE + 13:
+ case CPUINFO_INT_INPUT_STATE + 14:
+ case CPUINFO_INT_INPUT_STATE + 15: pdp1_set_irq_line(cpustate, state-CPUINFO_INT_INPUT_STATE, info->i); break;
+
+ case CPUINFO_INT_SP: (void) info->i; /* no SP */ break;
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + PDP1_PC: PC = info->i & EXTENDED_ADDRESS_MASK; break;
+ case CPUINFO_INT_REGISTER + PDP1_IR: IR = info->i & 037; /* weird idea */ break;
+ case CPUINFO_INT_REGISTER + PDP1_MB: MB = info->i & 0777777; break;
+ case CPUINFO_INT_REGISTER + PDP1_MA: MA = info->i & EXTENDED_ADDRESS_MASK; break;
+ case CPUINFO_INT_REGISTER + PDP1_AC: AC = info->i & 0777777; break;
+ case CPUINFO_INT_REGISTER + PDP1_IO: IO = info->i & 0777777; break;
+ case CPUINFO_INT_REGISTER + PDP1_OV: OV = info->i ? 1 : 0; break;
+ case CPUINFO_INT_REGISTER + PDP1_PF: FLAGS = info->i & 077; break;
+ case CPUINFO_INT_REGISTER + PDP1_PF1: WRITEFLAG(1, info->i ? 1 : 0); break;
+ case CPUINFO_INT_REGISTER + PDP1_PF2: WRITEFLAG(2, info->i ? 1 : 0); break;
+ case CPUINFO_INT_REGISTER + PDP1_PF3: WRITEFLAG(3, info->i ? 1 : 0); break;
+ case CPUINFO_INT_REGISTER + PDP1_PF4: WRITEFLAG(4, info->i ? 1 : 0); break;
+ case CPUINFO_INT_REGISTER + PDP1_PF5: WRITEFLAG(5, info->i ? 1 : 0); break;
+ case CPUINFO_INT_REGISTER + PDP1_PF6: WRITEFLAG(6, info->i ? 1 : 0); break;
+ case CPUINFO_INT_REGISTER + PDP1_TA: cpustate->ta = info->i & 0177777 /*07777 with simpler control panel*/; break;
+ case CPUINFO_INT_REGISTER + PDP1_TW: cpustate->tw = info->i & 0777777; break;
+ case CPUINFO_INT_REGISTER + PDP1_SS: SENSE_SW = info->i & 077; break;
+ case CPUINFO_INT_REGISTER + PDP1_SS1: WRITESENSE(1, info->i ? 1 : 0); break;
+ case CPUINFO_INT_REGISTER + PDP1_SS2: WRITESENSE(2, info->i ? 1 : 0); break;
+ case CPUINFO_INT_REGISTER + PDP1_SS3: WRITESENSE(3, info->i ? 1 : 0); break;
+ case CPUINFO_INT_REGISTER + PDP1_SS4: WRITESENSE(4, info->i ? 1 : 0); break;
+ case CPUINFO_INT_REGISTER + PDP1_SS5: WRITESENSE(5, info->i ? 1 : 0); break;
+ case CPUINFO_INT_REGISTER + PDP1_SS6: WRITESENSE(6, info->i ? 1 : 0); break;
+ case CPUINFO_INT_REGISTER + PDP1_SNGL_STEP: cpustate->sngl_step = info->i ? 1 : 0; break;
+ case CPUINFO_INT_REGISTER + PDP1_SNGL_INST: cpustate->sngl_inst = info->i ? 1 : 0; break;
+ case CPUINFO_INT_REGISTER + PDP1_EXTEND_SW: cpustate->extend_sw = info->i ? 1 : 0; break;
+ case CPUINFO_INT_REGISTER + PDP1_RUN: cpustate->run = info->i ? 1 : 0; break;
+ case CPUINFO_INT_REGISTER + PDP1_CYC: if (LOG) logerror("pdp1_set_reg to cycle flip-flop ignored\n");/* no way!*/ break;
+ case CPUINFO_INT_REGISTER + PDP1_DEFER: if (LOG) logerror("pdp1_set_reg to defer flip-flop ignored\n");/* no way!*/ break;
+ case CPUINFO_INT_REGISTER + PDP1_BRK_CTR: if (LOG) logerror("pdp1_set_reg to break counter ignored\n");/* no way!*/ break;
+ case CPUINFO_INT_REGISTER + PDP1_RIM: cpustate->rim = info->i ? 1 : 0; break;
+ case CPUINFO_INT_REGISTER + PDP1_SBM: cpustate->sbm = info->i ? 1 : 0; break;
+ case CPUINFO_INT_REGISTER + PDP1_EXD: EXD = (cpustate->extend_support && info->i) ? 1 : 0; break;
+ case CPUINFO_INT_REGISTER + PDP1_IOC: if (LOG) logerror("pdp1_set_reg to ioc flip-flop ignored\n");/* no way!*/ break;
+ case CPUINFO_INT_REGISTER + PDP1_IOH: if (LOG) logerror("pdp1_set_reg to ioh flip-flop ignored\n");/* no way!*/ break;
+ case CPUINFO_INT_REGISTER + PDP1_IOS: if (LOG) logerror("pdp1_set_reg to ios flip-flop ignored\n");/* no way!*/ break;
+ case CPUINFO_INT_REGISTER + PDP1_START_CLEAR: pulse_start_clear(cpustate); break;
+ case CPUINFO_INT_REGISTER + PDP1_IO_COMPLETE: cpustate->ios = 1; break;
+ }
+}
+
+
+CPU_GET_INFO( pdp1 )
+{
+ pdp1_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(pdp1_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 16; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; /*don't care*/ break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 5; /* 5us cycle time */ break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 31; /* we emulate individual 5us cycle, but MUL/DIV have longer timings */ break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 18; /*16+2 ignored bits to make double word address*/ break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_SP: info->i = 0; /* no SP */ break;
+ case CPUINFO_INT_PC: info->i = PC; break;
+ case CPUINFO_INT_PREVIOUSPC: info->i = PC; /* TODO??? */ break;
+
+ case CPUINFO_INT_INPUT_STATE + 0:
+ case CPUINFO_INT_INPUT_STATE + 1:
+ case CPUINFO_INT_INPUT_STATE + 2:
+ case CPUINFO_INT_INPUT_STATE + 3:
+ case CPUINFO_INT_INPUT_STATE + 4:
+ case CPUINFO_INT_INPUT_STATE + 5:
+ case CPUINFO_INT_INPUT_STATE + 6:
+ case CPUINFO_INT_INPUT_STATE + 7:
+ case CPUINFO_INT_INPUT_STATE + 8:
+ case CPUINFO_INT_INPUT_STATE + 9:
+ case CPUINFO_INT_INPUT_STATE + 10:
+ case CPUINFO_INT_INPUT_STATE + 11:
+ case CPUINFO_INT_INPUT_STATE + 12:
+ case CPUINFO_INT_INPUT_STATE + 13:
+ case CPUINFO_INT_INPUT_STATE + 14:
+ case CPUINFO_INT_INPUT_STATE + 15: info->i = (cpustate->irq_state >> (state-CPUINFO_INT_INPUT_STATE)) & 1; break;
+
+ case CPUINFO_INT_REGISTER + PDP1_PC: info->i = PC; break;
+ case CPUINFO_INT_REGISTER + PDP1_IR: info->i = IR; break;
+ case CPUINFO_INT_REGISTER + PDP1_MB: info->i = MB; break;
+ case CPUINFO_INT_REGISTER + PDP1_MA: info->i = MA; break;
+ case CPUINFO_INT_REGISTER + PDP1_AC: info->i = AC; break;
+ case CPUINFO_INT_REGISTER + PDP1_IO: info->i = IO; break;
+ case CPUINFO_INT_REGISTER + PDP1_OV: info->i = OV; break;
+ case CPUINFO_INT_REGISTER + PDP1_PF: info->i = FLAGS; break;
+ case CPUINFO_INT_REGISTER + PDP1_PF1: info->i = READFLAG(1); break;
+ case CPUINFO_INT_REGISTER + PDP1_PF2: info->i = READFLAG(2); break;
+ case CPUINFO_INT_REGISTER + PDP1_PF3: info->i = READFLAG(3); break;
+ case CPUINFO_INT_REGISTER + PDP1_PF4: info->i = READFLAG(4); break;
+ case CPUINFO_INT_REGISTER + PDP1_PF5: info->i = READFLAG(5); break;
+ case CPUINFO_INT_REGISTER + PDP1_PF6: info->i = READFLAG(6); break;
+ case CPUINFO_INT_REGISTER + PDP1_TA: info->i = cpustate->ta; break;
+ case CPUINFO_INT_REGISTER + PDP1_TW: info->i = cpustate->tw; break;
+ case CPUINFO_INT_REGISTER + PDP1_SS: info->i = SENSE_SW; break;
+ case CPUINFO_INT_REGISTER + PDP1_SS1: info->i = READSENSE(1); break;
+ case CPUINFO_INT_REGISTER + PDP1_SS2: info->i = READSENSE(2); break;
+ case CPUINFO_INT_REGISTER + PDP1_SS3: info->i = READSENSE(3); break;
+ case CPUINFO_INT_REGISTER + PDP1_SS4: info->i = READSENSE(4); break;
+ case CPUINFO_INT_REGISTER + PDP1_SS5: info->i = READSENSE(5); break;
+ case CPUINFO_INT_REGISTER + PDP1_SS6: info->i = READSENSE(6); break;
+ case CPUINFO_INT_REGISTER + PDP1_SNGL_STEP: info->i = cpustate->sngl_step; break;
+ case CPUINFO_INT_REGISTER + PDP1_SNGL_INST: info->i = cpustate->sngl_inst; break;
+ case CPUINFO_INT_REGISTER + PDP1_EXTEND_SW: info->i = cpustate->extend_sw; break;
+ case CPUINFO_INT_REGISTER + PDP1_RUN: info->i = cpustate->run; break;
+ case CPUINFO_INT_REGISTER + PDP1_CYC: info->i = cpustate->cycle; break;
+ case CPUINFO_INT_REGISTER + PDP1_DEFER: info->i = cpustate->defer; break;
+ case CPUINFO_INT_REGISTER + PDP1_BRK_CTR: info->i = cpustate->brk_ctr; break;
+ case CPUINFO_INT_REGISTER + PDP1_RIM: info->i = cpustate->rim; break;
+ case CPUINFO_INT_REGISTER + PDP1_SBM: info->i = cpustate->sbm; break;
+ case CPUINFO_INT_REGISTER + PDP1_EXD: info->i = EXD; break;
+ case CPUINFO_INT_REGISTER + PDP1_IOC: info->i = cpustate->ioc; break;
+ case CPUINFO_INT_REGISTER + PDP1_IOH: info->i = cpustate->ioh; break;
+ case CPUINFO_INT_REGISTER + PDP1_IOS: info->i = cpustate->ios; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(pdp1); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(pdp1); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(pdp1); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(pdp1); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(pdp1); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "PDP1"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "DEC PDP-1"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "2.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s,
+ "Brian Silverman (original Java Source)\n"
+ "Vadim Gerasimov (original Java Source)\n"
+ "Chris Salomon (MESS driver)\n"
+ "Raphael Nabet (MESS driver)\n");
+ break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c%c%c%c%c-%c%c%c%c%c%c",
+ (FLAGS & 040) ? '1' : '.',
+ (FLAGS & 020) ? '2' : '.',
+ (FLAGS & 010) ? '3' : '.',
+ (FLAGS & 004) ? '4' : '.',
+ (FLAGS & 002) ? '5' : '.',
+ (FLAGS & 001) ? '6' : '.',
+ (SENSE_SW & 040) ? '1' : '.',
+ (SENSE_SW & 020) ? '2' : '.',
+ (SENSE_SW & 010) ? '3' : '.',
+ (SENSE_SW & 004) ? '4' : '.',
+ (SENSE_SW & 002) ? '5' : '.',
+ (SENSE_SW & 001) ? '6' : '.');
+ break;
+
+
+ case CPUINFO_STR_REGISTER + PDP1_PC: sprintf(info->s, "PC:0%06o(%04X)", PC, PC); break;
+ case CPUINFO_STR_REGISTER + PDP1_IR: sprintf(info->s, "IR:0%02o", IR); break;
+ case CPUINFO_STR_REGISTER + PDP1_MB: sprintf(info->s, "MB:0%06o", MB); break;
+ case CPUINFO_STR_REGISTER + PDP1_MA: sprintf(info->s, "MA:0%06o", MA); break;
+ case CPUINFO_STR_REGISTER + PDP1_AC: sprintf(info->s, "AC:0%06o", AC); break;
+ case CPUINFO_STR_REGISTER + PDP1_IO: sprintf(info->s, "IO:0%06o", IO); break;
+ case CPUINFO_STR_REGISTER + PDP1_OV: sprintf(info->s, "OV:%X", OV); break;
+ case CPUINFO_STR_REGISTER + PDP1_PF: sprintf(info->s, "FLAGS:0%02o", FLAGS); break;
+ case CPUINFO_STR_REGISTER + PDP1_PF1: sprintf(info->s, "FLAG1:%X", READFLAG(1)); break;
+ case CPUINFO_STR_REGISTER + PDP1_PF2: sprintf(info->s, "FLAG2:%X", READFLAG(2)); break;
+ case CPUINFO_STR_REGISTER + PDP1_PF3: sprintf(info->s, "FLAG3:%X", READFLAG(3)); break;
+ case CPUINFO_STR_REGISTER + PDP1_PF4: sprintf(info->s, "FLAG4:%X", READFLAG(4)); break;
+ case CPUINFO_STR_REGISTER + PDP1_PF5: sprintf(info->s, "FLAG5:%X", READFLAG(5)); break;
+ case CPUINFO_STR_REGISTER + PDP1_PF6: sprintf(info->s, "FLAG6:%X", READFLAG(6)); break;
+ case CPUINFO_STR_REGISTER + PDP1_TA: sprintf(info->s, "TA:0%06o", cpustate->ta); break;
+ case CPUINFO_STR_REGISTER + PDP1_TW: sprintf(info->s, "TW:0%06o", cpustate->tw); break;
+ case CPUINFO_STR_REGISTER + PDP1_SS: sprintf(info->s, "SS:0%02o", SENSE_SW); break;
+ case CPUINFO_STR_REGISTER + PDP1_SS1: sprintf(info->s, "SENSE1:%X", READSENSE(1)); break;
+ case CPUINFO_STR_REGISTER + PDP1_SS2: sprintf(info->s, "SENSE2:%X", READSENSE(2)); break;
+ case CPUINFO_STR_REGISTER + PDP1_SS3: sprintf(info->s, "SENSE3:%X", READSENSE(3)); break;
+ case CPUINFO_STR_REGISTER + PDP1_SS4: sprintf(info->s, "SENSE4:%X", READSENSE(4)); break;
+ case CPUINFO_STR_REGISTER + PDP1_SS5: sprintf(info->s, "SENSE5:%X", READSENSE(5)); break;
+ case CPUINFO_STR_REGISTER + PDP1_SS6: sprintf(info->s, "SENSE6:%X", READSENSE(6)); break;
+ case CPUINFO_STR_REGISTER + PDP1_SNGL_STEP: sprintf(info->s, "SNGLSTEP:%X", cpustate->sngl_step); break;
+ case CPUINFO_STR_REGISTER + PDP1_SNGL_INST: sprintf(info->s, "SNGLINST:%X", cpustate->sngl_inst); break;
+ case CPUINFO_STR_REGISTER + PDP1_EXTEND_SW: sprintf(info->s, "EXS:%X", cpustate->extend_sw); break;
+ case CPUINFO_STR_REGISTER + PDP1_RUN: sprintf(info->s, "RUN:%X", cpustate->run); break;
+ case CPUINFO_STR_REGISTER + PDP1_CYC: sprintf(info->s, "CYC:%X", cpustate->cycle); break;
+ case CPUINFO_STR_REGISTER + PDP1_DEFER: sprintf(info->s, "DF:%X", cpustate->defer); break;
+ case CPUINFO_STR_REGISTER + PDP1_BRK_CTR: sprintf(info->s, "BRKCTR:%X", cpustate->brk_ctr); break;
+ case CPUINFO_STR_REGISTER + PDP1_RIM: sprintf(info->s, "RIM:%X", cpustate->rim); break;
+ case CPUINFO_STR_REGISTER + PDP1_SBM: sprintf(info->s, "SBM:%X", cpustate->sbm); break;
+ case CPUINFO_STR_REGISTER + PDP1_EXD: sprintf(info->s, "EXD:%X", EXD); break;
+ case CPUINFO_STR_REGISTER + PDP1_IOC: sprintf(info->s, "IOC:%X", cpustate->ioc); break;
+ case CPUINFO_STR_REGISTER + PDP1_IOH: sprintf(info->s, "IOH:%X", cpustate->ioh); break;
+ case CPUINFO_STR_REGISTER + PDP1_IOS: sprintf(info->s, "IOS:%X", cpustate->ios); break;
+ }
+}
+
+
+/* execute one instruction */
+static void execute_instruction(pdp1_state *cpustate)
+{
+ switch (IR)
+ {
+ case AND: /* Logical And */
+ AC &= (MB = READ_PDP_18BIT(MA));
+ break;
+ case IOR: /* Inclusive Or */
+ AC |= (MB = READ_PDP_18BIT(MA));
+ break;
+ case XOR: /* Exclusive Or */
+ AC ^= (MB = READ_PDP_18BIT(MA));
+ break;
+ case XCT: /* Execute */
+ MB = READ_PDP_18BIT(MA);
+ IR = MB >> 13; /* basic opcode */
+ if ((instruction_kind[IR] & 1) && (MB & 010000))
+ {
+ cpustate->defer = 1;
+ /*cpustate->cycle = 1;*/ /* instruction shall be executed later */
+ goto no_fetch; /* fall through to next instruction */
+ }
+ else if (instruction_kind[IR] & 2)
+ {
+ /*cpustate->cycle = 1;*/ /* instruction shall be executed later */
+ goto no_fetch; /* fall through to next instruction */
+ }
+ else
+ execute_instruction(cpustate); /* execute instruction at once */
+ break;
+ case CALJDA: /* Call subroutine and Jump and Deposit Accumulator instructions */
+ if (MB & 010000)
+ /* JDA */
+ MA = (PC & ADDRESS_EXTENSION_MASK) | (MB & BASE_ADDRESS_MASK);
+ else
+ /* CAL: equivalent to JDA 100 */
+ /* Note that I cannot tell for sure what happens to extension bits, but I did notice
+ that setting the extension bits to 0 would make cal basically useless, since
+ there would be no simple way the call routine could return to the callee
+ if it were located in another module with extend mode off (i.e. exd == 0). */
+ MA = (PC & ADDRESS_EXTENSION_MASK) | 0100;
+
+ WRITE_PDP_18BIT(MA, (MB = AC));
+ INCREMENT_MA;
+ AC = (OV << 17) | (EXD << 16) | PC;
+ PC = MA;
+ break;
+ case LAC: /* Load Accumulator */
+ AC = (MB = READ_PDP_18BIT(MA));
+ break;
+ case LIO: /* Load i/o register */
+ IO = (MB = READ_PDP_18BIT(MA));
+ break;
+ case DAC: /* Deposit Accumulator */
+ WRITE_PDP_18BIT(MA, (MB = AC));
+ break;
+ case DAP: /* Deposit Address Part */
+ WRITE_PDP_18BIT(MA, (MB = ((READ_PDP_18BIT(MA) & 0770000) | (AC & 0007777))));
+ break;
+ case DIP: /* Deposit Instruction Part */
+ WRITE_PDP_18BIT(MA, (MB = ((READ_PDP_18BIT(MA) & 0007777) | (AC & 0770000))));
+ break;
+ case DIO: /* Deposit I/O Register */
+ WRITE_PDP_18BIT(MA, (MB = IO));
+ break;
+ case DZM: /* Deposit Zero in Memory */
+ WRITE_PDP_18BIT(MA, (MB = 0));
+ break;
+ case ADD: /* Add */
+ {
+ /* overflow is set if the 2 operands have the same sign and the final result has another */
+ int ov2; /* 1 if the operands have the same sign*/
+
+ MB = READ_PDP_18BIT(MA);
+
+ ov2 = ((AC & 0400000) == (MB & 0400000));
+
+ AC = AC + MB;
+ AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */
+
+ /* I think we need to check for overflow before checking for -0,
+ because the sum -0+-0 = -0 = +0 would generate an overflow
+ otherwise. */
+ if (ov2 && ((AC & 0400000) != (MB & 0400000)))
+ OV = 1;
+
+ if (AC == 0777777) /* check for -0 */
+ AC = 0;
+
+ break;
+ }
+ case SUB: /* Subtract */
+ { /* maintainance manual 7-14 seems to imply that substract does not test for -0.
+ The sim 2.3 source says so explicitely, though they do not give a reference.
+ It sounds a bit weird, but the reason is probably that doing so would
+ require additionnal logic that does not exist. */
+ /* overflow is set if the 2 operands have the same sign and the final result has another */
+ int ov2; /* 1 if the operands have the same sign*/
+
+ AC ^= 0777777;
+
+ MB = READ_PDP_18BIT(MA);
+
+ ov2 = ((AC & 0400000) == (MB & 0400000));
+
+ AC = AC + MB;
+ AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */
+
+ if (ov2 && ((AC & 0400000) != (MB & 0400000)))
+ OV = 1;
+
+ AC ^= 0777777;
+
+ break;
+ }
+ case IDX: /* Index */
+ AC = READ_PDP_18BIT(MA) + 1;
+
+ #if 0
+ AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */
+ if (AC == 0777777) /* check for -0 */
+ AC = 0;
+ #else
+ if (AC >= 0777777)
+ AC = (AC + 1) & 0777777;
+ #endif
+
+ WRITE_PDP_18BIT(MA, (MB = AC));
+ break;
+ case ISP: /* Index and Skip if Positive */
+ AC = READ_PDP_18BIT(MA) + 1;
+
+ #if 0
+ AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */
+ if (AC == 0777777) /* check for -0 */
+ AC = 0;
+ #else
+ if (AC >= 0777777)
+ AC = (AC + 1) & 0777777;
+ #endif
+
+ WRITE_PDP_18BIT(MA, (MB = AC));
+ if ((AC & 0400000) == 0)
+ INCREMENT_PC;
+ break;
+ case SAD: /* Skip if Accumulator and Y differ */
+ if (AC != (MB = READ_PDP_18BIT(MA)))
+ INCREMENT_PC;
+ break;
+ case SAS: /* Skip if Accumulator and Y are the same */
+ if (AC == (MB = READ_PDP_18BIT(MA)))
+ INCREMENT_PC;
+ break;
+ case MUS_MUL: /* Multiply Step or Multiply */
+ if (cpustate->hw_mul_div)
+ { /* MUL */
+ int scr;
+ int smb, srm;
+ double etime = 4.; /* approximative */
+
+ IO = MB = AC;
+ MB = READ_PDP_18BIT(MA);
+ scr = 0;
+ if (MB & 0400000)
+ {
+ smb = 1;
+ MB = MB ^ 0777777;
+ }
+ else
+ smb = 0;
+ if (IO & 0400000)
+ {
+ srm = 1;
+ IO = IO ^ 0777777;
+ }
+ else
+ srm = 0;
+ AC = 0;
+ scr++;
+ while (scr < 022)
+ {
+ if (IO & 1)
+ {
+ /*assert(! (AC & 0400000));*/
+ AC = AC + MB;
+ /* we can save carry around since both numbers are positive */
+ /*AC = (AC + (AC >> 18)) & 0777777;*/
+ etime += .65; /* approximative */
+ }
+ IO = (IO >> 1) | ((AC & 1) << 17);
+ AC = AC >> 1;
+ scr++;
+ }
+ if (smb ^ srm)
+ {
+ AC = AC ^ 0777777;
+ IO = IO ^ 0777777;
+ }
+
+ cpustate->icount -= etime+.5; /* round to closest */
+ }
+ else
+ { /* MUS */
+ /* should we check for -0??? (Maintainance manual 7-14 seems to imply we should not:
+ as a matter of fact, since the MUS instruction is supposed to have positive operands,
+ there is no need to check for -0, therefore such a simplification does not sound
+ absurd.) */
+ if ((IO & 1) == 1)
+ {
+ AC = AC + (MB = READ_PDP_18BIT(MA));
+ AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */
+ }
+ IO = (IO >> 1 | AC << 17) & 0777777;
+ AC >>= 1;
+ }
+ break;
+ case DIS_DIV: /* Divide Step or Divide */
+ if (cpustate->hw_mul_div)
+ { /* DIV */
+ /* As a side note, the order of -0 detection and overflow checking does not matter,
+ because the sum of two positive number cannot give 0777777 (since positive
+ numbers are 0377777 at most, their sum is 0777776 at most).
+ Additionnally, we cannot have carry set and a result equal to 0777777 (since numbers
+ are 0777777 at most, their sum is 01777776 at most): this is nice, because it makes
+ the sequence:
+ AC = (AC + (AC >> 18)) & 0777777; // propagate carry around
+ if (AC == 0777777) // check for -0
+ AC = 0;
+ equivalent to:
+ if (AC >= 0777777)
+ AC = (AC + 1) & 0777777;
+ which is a bit more efficient. */
+ int acl;
+ int scr;
+ int smb, srm;
+ double etime = 0; /* approximative */
+
+ MB = READ_PDP_18BIT(MA);
+ scr = 0;
+ if (MB & 0400000)
+ {
+ smb = 1;
+ }
+ else
+ {
+ smb = 0;
+ MB = MB ^ 0777777;
+ }
+ if (AC & 0400000)
+ {
+ srm = 1;
+ AC = AC ^ 0777777;
+ IO = IO ^ 0777777;
+ }
+ else
+ srm = 0;
+ while (1)
+ {
+ AC = (AC + MB);
+ #if 1
+ AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */
+ if (AC == 0777777) /* check for -0 */
+ AC = 0;
+ #else
+ if (AC >= 0777777)
+ AC = (AC + 1) & 0777777;
+ #endif
+ if (MB & 0400000)
+ MB = MB ^ 0777777;
+
+ if (((scr == 0) && ! (AC & 0400000))
+ || (scr == 022))
+ break;
+
+ scr++;
+
+ if (! (AC & 0400000))
+ MB = MB ^ 0777777;
+
+ acl = AC >> 17;
+ AC = (AC << 1 | IO >> 17) & 0777777;
+ IO = ((IO << 1 | acl) & 0777777) ^ 1;
+ if (acl)
+ {
+ AC++;
+ AC = (AC + (AC >> 18)) & 0777777;
+ etime += .6; /* approximative */
+ }
+ }
+
+ AC = (AC + MB);
+ #if 1
+ AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */
+ if (AC == 0777777) /* check for -0 */
+ AC = 0;
+ #else
+ if (AC >= 0777777)
+ AC = (AC + 1) & 0777777;
+ #endif
+
+ if (scr)
+ {
+ INCREMENT_PC;
+ AC = AC >> 1;
+ }
+
+ if (srm && (AC != 0))
+ AC = AC ^ 0777777;
+
+ if (((! scr) && (srm))
+ || (scr && (srm ^ smb) && (IO != 0)))
+ IO = IO ^ 0777777;
+
+ if (scr)
+ {
+ MB = AC;
+ AC = IO;
+ IO = MB;
+ }
+ if (scr)
+ etime += 20; /* approximative */
+ else
+ etime += 2; /* approximative */
+
+ cpustate->icount -= etime+.5; /* round to closest */
+ }
+ else
+ { /* DIS */
+ int acl;
+
+ acl = AC >> 17;
+ AC = (AC << 1 | IO >> 17) & 0777777;
+ IO = ((IO << 1 | acl) & 0777777) ^ 1;
+ MB = READ_PDP_18BIT(MA);
+ if (IO & 1)
+ AC += (MB ^ 0777777);
+ else
+ /* Note that if AC+MB = 0777777, we are in trouble. I don't
+ know how a real PDP-1 behaves in this case. */
+ AC += MB + 1;
+ AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */
+ if (AC == 0777777) /* check for -0 */
+ AC = 0;
+ }
+ break;
+ case JMP: /* Jump */
+ if (cpustate->exc)
+ PC = MB & EXTENDED_ADDRESS_MASK;
+ else
+ PC = (MA & ADDRESS_EXTENSION_MASK) | (MB & BASE_ADDRESS_MASK);
+ break;
+ case JSP: /* Jump and Save Program Counter */
+ AC = (OV << 17) | (EXD << 16) | PC;
+ if (cpustate->exc)
+ PC = MB & EXTENDED_ADDRESS_MASK;
+ else
+ PC = (MA & ADDRESS_EXTENSION_MASK) | (MB & BASE_ADDRESS_MASK);
+ break;
+ case SKP: /* Skip Instruction Group */
+ {
+ int cond = ((MB & 0100) && (AC == 0)) /* ZERO Accumulator */
+ || ((MB & 0200) && (AC >> 17 == 0)) /* Plus Accumulator */
+ || ((MB & 0400) && (AC >> 17 == 1)) /* Minus Accumulator */
+ || ((MB & 01000) && (OV == 0)) /* ZERO Overflow */
+ || ((MB & 02000) && (IO >> 17 == 0)) /* Plus I/O Register */
+ || (((MB & 7) != 0) && (((MB & 7) == 7) ? ! FLAGS : ! READFLAG(MB & 7))) /* ZERO Flag (deleted by mistake in PDP-1 handbook) */
+ || (((MB & 070) != 0) && (((MB & 070) == 070) ? ! SENSE_SW : ! READSENSE((MB & 070) >> 3))); /* ZERO Switch */
+
+ if (! (MB & 010000))
+ {
+ if (cond)
+ INCREMENT_PC;
+ }
+ else
+ {
+ if (!cond)
+ INCREMENT_PC;
+ }
+ if (MB & 01000)
+ OV = 0;
+ break;
+ }
+ case SFT: /* Shift Instruction Group */
+ {
+ /* Bit 5 specifies direction of shift, Bit 6 specifies the character of the shift
+ (arithmetic or logical), Bits 7 and 8 enable the registers (01 = AC, 10 = IO,
+ and 11 = both) and Bits 9 through 17 specify the number of steps. */
+ int nshift = 0;
+ int mask = MB & 0777;
+
+ while (mask != 0)
+ {
+ nshift += mask & 1;
+ mask >>= 1;
+ }
+ switch ((MB >> 9) & 017)
+ {
+ int i;
+
+ case 1: /* ral rotate accumulator left */
+ for (i = 0; i < nshift; i++)
+ AC = (AC << 1 | AC >> 17) & 0777777;
+ break;
+ case 2: /* ril rotate i/o register left */
+ for (i = 0; i < nshift; i++)
+ IO = (IO << 1 | IO >> 17) & 0777777;
+ break;
+ case 3: /* rcl rotate AC and IO left */
+ for (i = 0; i < nshift; i++)
+ {
+ int tmp = AC;
+
+ AC = (AC << 1 | IO >> 17) & 0777777;
+ IO = (IO << 1 | tmp >> 17) & 0777777;
+ }
+ break;
+ case 5: /* sal shift accumulator left */
+ for (i = 0; i < nshift; i++)
+ AC = ((AC << 1 | AC >> 17) & 0377777) + (AC & 0400000);
+ break;
+ case 6: /* sil shift i/o register left */
+ for (i = 0; i < nshift; i++)
+ IO = ((IO << 1 | IO >> 17) & 0377777) + (IO & 0400000);
+ break;
+ case 7: /* scl shift AC and IO left */
+ for (i = 0; i < nshift; i++)
+ {
+ int tmp = AC;
+
+ AC = ((AC << 1 | IO >> 17) & 0377777) + (AC & 0400000); /* shouldn't that be IO?, no it is the sign! */
+ IO = (IO << 1 | tmp >> 17) & 0777777;
+ }
+ break;
+ case 9: /* rar rotate accumulator right */
+ for (i = 0; i < nshift; i++)
+ AC = (AC >> 1 | AC << 17) & 0777777;
+ break;
+ case 10: /* rir rotate i/o register right */
+ for (i = 0; i < nshift; i++)
+ IO = (IO >> 1 | IO << 17) & 0777777;
+ break;
+ case 11: /* rcr rotate AC and IO right */
+ for (i = 0; i < nshift; i++)
+ {
+ int tmp = AC;
+
+ AC = (AC >> 1 | IO << 17) & 0777777;
+ IO = (IO >> 1 | tmp << 17) & 0777777;
+ }
+ break;
+ case 13: /* sar shift accumulator right */
+ for (i = 0; i < nshift; i++)
+ AC = (AC >> 1) + (AC & 0400000);
+ break;
+ case 14: /* sir shift i/o register right */
+ for (i = 0; i < nshift; i++)
+ IO = (IO >> 1) + (IO & 0400000);
+ break;
+ case 15: /* scr shift AC and IO right */
+ for (i = 0; i < nshift; i++)
+ {
+ int tmp = AC;
+
+ AC = (AC >> 1) + (AC & 0400000); /* shouldn't that be IO, no it is the sign */
+ IO = (IO >> 1 | tmp << 17) & 0777777;
+ }
+ break;
+ default:
+ if (LOG)
+ logerror("Undefined shift: 0%06o at 0%06o\n", MB, PREVIOUS_PC);
+ break;
+ }
+ break;
+ }
+ case LAW: /* Load Accumulator with N */
+ AC = MB & 07777;
+ if (MB & 010000)
+ AC ^= 0777777;
+ break;
+ case IOT: /* In-Out Transfer Instruction Group */
+ /*
+ The variations within this group of instructions perform all the in-out control
+ and information transfer functions. If Bit 5 (normally the Indirect Address bit)
+ is a ONE, the computer will enter a special waiting state until the completion pulse
+ from the activated device has returned. When this device delivers its completion,
+ the computer will resume operation of the instruction sequence.
+
+ The computer may be interrupted from the special waiting state to serve a sequence
+ break request or a high speed channel request.
+
+ Most in-out operations require a known minimum time before completion. This time
+ may be utilized for programming. The appropriate In-Out Transfer can be given with
+ no in-out wait (Bit 5 a ZERO and Bit 6 a ONE). The instruction sequence then
+ continues. This sequence must include an iot instruction 730000 which performs
+ nothing but the in-out wait. The computer will then enter the special waiting state
+ until the device returns the in-out restart pulse. If the device has already
+ returned the completion pulse before the instruction 730000, the computer will
+ proceed immediately.
+
+ Bit 6 determines whether a completion pulse will or will not be received from
+ the in-out device. When it is different than Bit 5, a completion pulse will be
+ received. When it is the same as Bit 5, a completion pulse will not be received.
+
+ In addition to the control function of Bits 5 and 6, Bits 7 through 11 are also
+ used as control bits serving to extend greatly the power of the iot instructions.
+ For example, Bits 12 through 17, which are used to designate a class of input or
+ output devices such as typewriters, may be further defined by Bits 7 through 11
+ as referring to Typewriter 1, 2, 3, etc. In several of the optional in-out devices,
+ in particular the magnetic tape, Bits 7 through 11 specify particular functions
+ such as forward, backward etc. If a large number of specialized devices are to
+ be attached, these bits may be used to further the in-out transfer instruction
+ to perform totally distinct functions.
+
+ Note that ioc is supposed to be set at the beggining of the memory cycle after
+ ioh is cleared.
+ However, we cannot set ioc at the beggining of every memory cycle as we
+ did before, because it breaks in the following case:
+ a) IOT instruction enables IO wait
+ b) sequence break in the middle of IO-halt
+ c) ioh is cleared in middle of sequence break routine
+ d) re-execute IOT instruction. Unfortunately, ioc has been cleared, therefore
+ we perform an IOT command pulse and IO wait again, which is completely WRONG.
+ Therefore ioc is cleared only after a IOT with wait is executed.
+ */
+ if (MB & 010000)
+ { /* IOT with IO wait */
+ if (cpustate->ioc)
+ { /* the iot command line is pulsed only if ioc is asserted */
+ (*cpustate->extern_iot[MB & 0000077])(cpustate->device, MB & 0000077, (MB & 0004000) == 0, MB, &IO, AC);
+
+ cpustate->ioh = 1; /* enable io wait */
+
+ cpustate->ioc = 0; /* actually happens at the start of next memory cycle */
+
+ /* test ios now in case the IOT callback has sent a completion pulse immediately */
+ if (cpustate->ioh && cpustate->ios)
+ {
+ /* ioh should be cleared at the end of the instruction cycle, and ios at the
+ start of next instruction cycle, but who cares? */
+ cpustate->ioh = 0;
+ cpustate->ios = 0;
+ }
+ }
+
+ if (cpustate->ioh)
+ DECREMENT_PC;
+ else
+ cpustate->ioc = 1; /* actually happens at the start of next memory cycle */
+ }
+ else
+ { /* IOT with no IO wait */
+ (*cpustate->extern_iot[MB & 0000077])(cpustate->device, MB & 0000077, (MB & 0004000) != 0, MB, &IO, AC);
+ }
+ break;
+ case OPR: /* Operate Instruction Group */
+ {
+ int nflag;
+
+ if (MB & 00200) /* clear AC */
+ AC = 0;
+ if (MB & 04000) /* clear I/O register */
+ IO = 0;
+ if (MB & 02000) /* load Accumulator from Test Word */
+ AC |= cpustate->tw;
+ if (MB & 00100) /* load Accumulator with Program Counter */
+ AC |= (OV << 17) | (EXD << 16) | PC;
+ nflag = MB & 7;
+ if (nflag)
+ {
+ if (nflag == 7)
+ FLAGS = (MB & 010) ? 077 : 000;
+ else
+ WRITEFLAG(nflag, (MB & 010) ? 1 : 0);
+ }
+ if (MB & 01000) /* Complement AC */
+ AC ^= 0777777;
+ if (MB & 00400) /* Halt */
+ {
+ if (LOG_EXTRA)
+ logerror("PDP1 Program executed HALT: at 0%06o\n", PREVIOUS_PC);
+
+ cpustate->run = 0;
+ }
+ break;
+ }
+ default:
+ if (LOG)
+ logerror("Illegal instruction: 0%06o at 0%06o\n", MB, PREVIOUS_PC);
+
+ /* let us stop the CPU, like a real pdp-1 */
+ cpustate->run = 0;
+
+ break;
+ }
+ cpustate->cycle = 0;
+no_fetch:
+ ;
+}
+
+
+/*
+ Handle unimplemented IOT
+*/
+static void null_iot(device_t *device, int op2, int nac, int mb, int *io, int ac)
+{
+ pdp1_state *cpustate = get_safe_token(device);
+ /* Note that the dummy IOT 0 is used to wait for the completion pulse
+ generated by the a pending IOT (IOT with completion pulse but no IO wait) */
+ if (LOG_IOT_EXTRA)
+ {
+ if (op2 == 000)
+ logerror("IOT sync instruction: mb=0%06o, pc=0%06o\n", (unsigned) mb, (unsigned) cpu_get_reg(device, PDP1_PC));
+ }
+ if (LOG)
+ {
+ if (op2 != 000)
+ logerror("Not supported IOT command (no external IOT function given) 0%06o at 0%06o\n", mb, PREVIOUS_PC);
+ }
+}
+
+
+/*
+ Memory expansion control (type 15)
+
+ IOT 74: LEM/EEM
+*/
+static void lem_eem_iot(device_t *device, int op2, int nac, int mb, int *io, int ac)
+{
+ pdp1_state *cpustate = get_safe_token(device);
+ if (! cpustate->extend_support) /* extend mode supported? */
+ {
+ if (LOG)
+ logerror("Ignoring internal error in file " __FILE__ " line %d.\n", __LINE__);
+ return;
+ }
+ if (LOG_EXTRA)
+ {
+ logerror("EEM/LEM instruction: mb=0%06o, pc=0%06o\n", mb, cpustate->pc);
+ }
+ EXD = (mb & 0004000) ? 1 : 0;
+}
+
+
+/*
+ Standard sequence break system
+
+ IOT 54: lsm
+ IOT 55: esm
+ IOT 56: cbs
+*/
+static void sbs_iot(device_t *device, int op2, int nac, int mb, int *io, int ac)
+{
+ pdp1_state *cpustate = get_safe_token(device);
+ switch (op2)
+ {
+ case 054: /* LSM */
+ if (LOG_EXTRA)
+ logerror("LSM instruction: mb=0%06o, pc=0%06o\n", mb, cpustate->pc);
+
+ cpustate->sbm = 0;
+ field_interrupt(cpustate);
+ break;
+ case 055: /* ESM */
+ if (LOG_EXTRA)
+ logerror("ESM instruction: mb=0%06o, pc=0%06o\n", mb, cpustate->pc);
+
+ cpustate->sbm = 1;
+ field_interrupt(cpustate);
+ break;
+ case 056: /* CBS */
+ if (LOG_EXTRA)
+ logerror("CBS instruction: mb=0%06o, pc=0%06o\n", mb, cpustate->pc);
+
+ /*cpustate->b3 = 0;*/
+ cpustate->b4 = 0;
+ field_interrupt(cpustate);
+ break;
+ default:
+ if (LOG)
+ logerror("Ignoring internal error in file " __FILE__ " line %d.\n", __LINE__);
+
+ break;
+ }
+}
+
+
+/*
+ type 20 sequence break system
+
+ IOT 50: dsc
+ IOT 51: asc
+ IOT 52: isb
+ IOT 53: cac
+*/
+static void type_20_sbs_iot(device_t *device, int op2, int nac, int mb, int *io, int ac)
+{
+ pdp1_state *cpustate = get_safe_token(device);
+ int channel, mask;
+ if (! cpustate->type_20_sbs) /* type 20 sequence break system supported? */
+ {
+ if (LOG)
+ logerror("Ignoring internal error in file " __FILE__ " line %d.\n", __LINE__);
+ return;
+ }
+ channel = (mb >> 6) & 017;
+ mask = 1 << channel;
+ switch (op2)
+ {
+ case 050: /* DSC */
+ if (LOG_EXTRA)
+ logerror("DSC instruction: mb=0%06o, pc=0%06o\n", mb, cpustate->pc);
+
+ cpustate->b1 &= ~mask;
+ field_interrupt(cpustate);
+ break;
+ case 051: /* ASC */
+ if (LOG_EXTRA)
+ logerror("ASC instruction: mb=0%06o, pc=0%06o\n", mb, cpustate->pc);
+
+ cpustate->b1 |= mask;
+ field_interrupt(cpustate);
+ break;
+ case 052: /* ISB */
+ if (LOG_EXTRA)
+ logerror("ISB instruction: mb=0%06o, pc=0%06o\n", mb, cpustate->pc);
+
+ cpustate->b2 |= mask;
+ field_interrupt(cpustate);
+ break;
+ case 053: /* CAC */
+ if (LOG_EXTRA)
+ logerror("CAC instruction: mb=0%06o, pc=0%06o\n", mb, cpustate->pc);
+
+ cpustate->b1 = 0;
+ field_interrupt(cpustate);
+ break;
+ default:
+ if (LOG)
+ logerror("Ignoring internal error in file " __FILE__ " line %d.\n", __LINE__);
+
+ break;
+ }
+
+}
+
+
+/*
+ Simulate a pulse on start/clear line:
+ reset most registers and flip-flops, and initialize a few emulator state
+ variables.
+*/
+static void pulse_start_clear(pdp1_state *cpustate)
+{
+ /* processor registers */
+ PC = 0; /* according to maintainance manual p. 6-17 */
+ IR = 0; /* according to maintainance manual p. 6-13 */
+ /*MB = 0;*/ /* ??? */
+ /*MA = 0;*/ /* ??? */
+ /*AC = 0;*/ /* ??? */
+ /*IO = 0;*/ /* ??? */
+ /*PF = 0;*/ /* ??? */
+
+ /* processor state flip-flops */
+ cpustate->run = 0; /* ??? */
+ cpustate->cycle = 0; /* mere guess */
+ cpustate->defer = 0; /* mere guess */
+ cpustate->brk_ctr = 0; /* mere guess */
+ cpustate->ov = 0; /* according to maintainance manual p. 7-18 */
+ cpustate->rim = 0; /* ??? */
+ cpustate->sbm = 0; /* ??? */
+ EXD = 0; /* according to maintainance manual p. 8-16 */
+ cpustate->exc = 0; /* according to maintainance manual p. 8-16 */
+ cpustate->ioc = 1; /* according to maintainance manual p. 6-10 */
+ cpustate->ioh = 0; /* according to maintainance manual p. 6-10 */
+ cpustate->ios = 0; /* according to maintainance manual p. 6-10 */
+
+ cpustate->b1 = cpustate->type_20_sbs ? 0 : 1; /* mere guess */
+ cpustate->b2 = 0; /* mere guess */
+ cpustate->b4 = 0; /* mere guess */
+
+
+ cpustate->rim_step = 0;
+ cpustate->sbs_restore = 0; /* mere guess */
+ cpustate->no_sequence_break = 0; /* mere guess */
+
+ field_interrupt(cpustate);
+
+ /* now, we kindly ask IO devices to reset, too */
+ if (cpustate->io_sc_callback)
+ (*cpustate->io_sc_callback)(cpustate->device);
+}
+
+DEFINE_LEGACY_CPU_DEVICE(PDP1, pdp1);
diff --git a/trunk/src/emu/cpu/pdp1/pdp1.h b/trunk/src/emu/cpu/pdp1/pdp1.h
new file mode 100644
index 00000000000..7e31766b209
--- /dev/null
+++ b/trunk/src/emu/cpu/pdp1/pdp1.h
@@ -0,0 +1,83 @@
+#pragma once
+
+#ifndef __PDP1_H__
+#define __PDP1_H__
+
+
+
+/* register ids for pdp1_get_reg/pdp1_set_reg */
+enum
+{
+ PDP1_PC=1, PDP1_IR, PDP1_MB, PDP1_MA, PDP1_AC, PDP1_IO,
+ PDP1_PF, PDP1_PF1, PDP1_PF2, PDP1_PF3, PDP1_PF4, PDP1_PF5, PDP1_PF6,
+ PDP1_TA, PDP1_TW,
+ PDP1_SS, PDP1_SS1, PDP1_SS2, PDP1_SS3, PDP1_SS4, PDP1_SS5, PDP1_SS6,
+ PDP1_SNGL_STEP, PDP1_SNGL_INST, PDP1_EXTEND_SW,
+ PDP1_RUN, PDP1_CYC, PDP1_DEFER, PDP1_BRK_CTR, PDP1_OV, PDP1_RIM, PDP1_SBM, PDP1_EXD,
+ PDP1_IOC, PDP1_IOH, PDP1_IOS,
+ PDP1_START_CLEAR, /* hack, do not use directly, use pdp1_pulse_start_clear instead */
+ PDP1_IO_COMPLETE /* hack, do not use directly, use pdp1_pulse_iot_done instead */
+};
+
+#define pdp1_pulse_start_clear(cpudevice) cpu_set_reg(cpudevice, PDP1_START_CLEAR, (UINT64)0)
+#define pdp1_pulse_iot_done(cpudevice) cpu_set_reg(cpudevice, PDP1_IO_COMPLETE, (UINT64)0)
+
+typedef void (*pdp1_extern_iot_func)(device_t *device, int op2, int nac, int mb, int *io, int ac);
+typedef void (*pdp1_read_binary_word_func)(device_t *device);
+typedef void (*pdp1_io_sc_func)(device_t *device);
+
+
+typedef struct _pdp1_reset_param_t pdp1_reset_param_t;
+struct _pdp1_reset_param_t
+{
+ /* callbacks for iot instructions (required for any I/O) */
+ pdp1_extern_iot_func extern_iot[64];
+ /* read a word from the perforated tape reader (required for read-in mode) */
+ pdp1_read_binary_word_func read_binary_word;
+ /* callback called when sc is pulsed: IO devices should reset */
+ pdp1_io_sc_func io_sc_callback;
+
+ /* 0: no extend support, 1: extend with 15-bit address, 2: extend with 16-bit address */
+ int extend_support;
+ /* 1 to use hardware multiply/divide (MUL, DIV) instead of MUS, DIS */
+ int hw_mul_div;
+ /* 0: standard sequence break system 1: type 20 sequence break system */
+ int type_20_sbs;
+};
+
+#define IOT_NO_COMPLETION_PULSE -1
+
+/* PUBLIC FUNCTIONS */
+DECLARE_LEGACY_CPU_DEVICE(PDP1, pdp1);
+
+#define AND 001
+#define IOR 002
+#define XOR 003
+#define XCT 004
+#define CALJDA 007
+#define LAC 010
+#define LIO 011
+#define DAC 012
+#define DAP 013
+#define DIP 014
+#define DIO 015
+#define DZM 016
+#define ADD 020
+#define SUB 021
+#define IDX 022
+#define ISP 023
+#define SAD 024
+#define SAS 025
+#define MUS_MUL 026
+#define DIS_DIV 027
+#define JMP 030
+#define JSP 031
+#define SKP 032
+#define SFT 033
+#define LAW 034
+#define IOT 035
+#define OPR 037
+
+CPU_DISASSEMBLE( pdp1 );
+
+#endif /* __PDP1_H__ */
diff --git a/trunk/src/emu/cpu/pdp1/pdp1dasm.c b/trunk/src/emu/cpu/pdp1/pdp1dasm.c
new file mode 100644
index 00000000000..a712484537d
--- /dev/null
+++ b/trunk/src/emu/cpu/pdp1/pdp1dasm.c
@@ -0,0 +1,292 @@
+#include "emu.h"
+#include "cpu/pdp1/pdp1.h"
+
+/* PDP1 registers */
+static int ib;
+static int y;
+
+INLINE void ea (void)
+{
+/* while (1)
+ {
+ if (ib == 0)
+ return;
+ ib = (READ_PDP_18BIT (y) >> 12) & 1;
+ y = READ_PDP_18BIT (y) & 07777;
+ }*/
+}
+
+#define IN if (ib) sprintf(buffer+strlen(buffer)," i")
+
+CPU_DISASSEMBLE( pdp1 )
+{
+ int md;
+ //int etime = 0;
+
+ md = oprom[0] << 24 | oprom[1] << 16 | oprom[2] << 8 | oprom[3];
+
+ y = md & 07777;
+ ib = (md >> 12) & 1; /* */
+ switch (md >> 13)
+ {
+ case AND:
+ ea ();
+ sprintf (buffer, "AND (0%06o)", y);
+ IN;
+ //etime = 10;
+ break;
+ case IOR:
+ ea ();
+ sprintf (buffer, "IOR (0%06o)", y);
+ IN;
+ //etime = 10;
+ break;
+ case XOR:
+ ea ();
+ sprintf (buffer, "XOR (0%06o)", y);
+ IN;
+ //etime = 10;
+ break;
+ case XCT:
+ ea ();
+ sprintf (buffer, "XCT (0%06o)", y);
+ IN;
+ //etime = 5;
+ break;
+ case CALJDA:
+ {
+ if (ib == 1)
+ sprintf (buffer, "JDA 0%06o ", y);
+ if (ib == 0)
+ sprintf (buffer, "CAL ");
+ //etime = 10;
+ break;
+ }
+ case LAC:
+ ea ();
+ sprintf (buffer, "LAC (0%06o)", y);
+ IN;
+ //etime = 10;
+ break;
+ case LIO:
+ ea ();
+ sprintf (buffer, "LIO (0%06o)", y);
+ IN;
+ //etime = 10;
+ break;
+ case DAC:
+ ea ();
+ sprintf (buffer, "DAC 0%06o ", y);
+ IN;
+ //etime = 10;
+ break;
+ case DAP:
+ ea ();
+ sprintf (buffer, "DAP 0%06o ", y);
+ IN;
+ //etime = 10;
+ break;
+ case DIP:
+ ea ();
+ sprintf (buffer, "DIP 0%06o ", y);
+ IN;
+ //etime = 10;
+ break;
+ case DIO:
+ ea ();
+ sprintf (buffer, "DIO 0%06o ", y);
+ IN;
+ //etime = 10;
+ break;
+ case DZM:
+ ea ();
+ sprintf (buffer, "DZM 0%06o ", y);
+ IN;
+ //etime = 10;
+ break;
+ case ADD:
+ ea ();
+ sprintf (buffer, "ADD (0%06o)", y);
+ IN;
+ //etime = 10;
+ break;
+ case SUB:
+ ea ();
+ sprintf (buffer, "SUB (0%06o)", y);
+ IN;
+ //etime = 10;
+ break;
+ case IDX:
+ ea ();
+ sprintf (buffer, "IDX (0%06o)", y);
+ IN;
+ //etime = 10;
+ break;
+ case ISP:
+ ea ();
+ sprintf (buffer, "ISP (0%06o)", y);
+ IN;
+ //etime = 10;
+ break;
+ case SAD:
+ ea ();
+ sprintf (buffer, "SAD (0%06o)", y);
+ IN;
+ //etime = 10;
+ break;
+ case SAS:
+ ea ();
+ sprintf (buffer, "SAS (0%06o)", y);
+ IN;
+ //etime = 10;
+ break;
+ case MUS_MUL:
+ ea ();
+ sprintf (buffer, "MUS (0%06o)", y);
+ IN;
+ //etime = 10;
+ break;
+ case DIS_DIV:
+ ea ();
+ sprintf (buffer, "DIS (0%06o)", y);
+ IN;
+ //etime = 10;
+ break;
+ case JMP:
+ ea ();
+ sprintf (buffer, "JMP 0%06o ", y);
+ IN;
+ //etime = 5;
+ break;
+ case JSP:
+ ea ();
+ sprintf (buffer, "JSP 0%06o ", y);
+ IN;
+ //etime = 5;
+ break;
+ case SKP:
+ {
+ buffer[0] = 0;
+ if ((y & 0100) == 0100)
+ sprintf (buffer, "SZA ");
+ if ((y & 0200) == 0200)
+ sprintf (buffer + strlen (buffer), "SPA ");
+ if ((y & 0400) == 0400)
+ sprintf (buffer + strlen (buffer), "SMA ");
+ if ((y & 01000) == 01000)
+ sprintf (buffer + strlen (buffer), "SZO ");
+ if ((y & 02000) == 02000)
+ sprintf (buffer + strlen (buffer), "SPI ");
+ if (y & 070)
+ sprintf (buffer + strlen (buffer), "SZS 0%01o ", (y & 070));
+ if (y & 7)
+ sprintf (buffer + strlen (buffer), "SZF 0%01o ", (y & 7));
+ IN;
+ //etime = 5;
+ break;
+ }
+ case SFT:
+ {
+ int nshift = 0;
+ int mask = md & 0777;
+
+ while (mask != 0)
+ {
+ nshift += mask & 1;
+ mask = mask >> 1;
+ }
+ switch ((md >> 9) & 017)
+ {
+ case 1:
+ sprintf (buffer, "RAL 0%02o", nshift);
+ //etime = 5;
+ break;
+ case 2:
+ sprintf (buffer, "RIL 0%02o", nshift);
+ //etime = 5;
+ break;
+ case 3:
+ sprintf (buffer, "RCL 0%02o", nshift);
+ //etime = 5;
+ break;
+ case 5:
+ sprintf (buffer, "SAL 0%02o", nshift);
+ //etime = 5;
+ break;
+ case 6:
+ sprintf (buffer, "SIL 0%02o", nshift);
+ //etime = 5;
+ break;
+ case 7:
+ sprintf (buffer, "SCL 0%02o", nshift);
+ //etime = 5;
+ break;
+ case 9:
+ sprintf (buffer, "RAR 0%02o", nshift);
+ //etime = 5;
+ break;
+ case 10:
+ sprintf (buffer, "RIR 0%02o", nshift);
+ //etime = 5;
+ break;
+ case 11:
+ sprintf (buffer, "RCR 0%02o", nshift);
+ //etime = 5;
+ break;
+ case 13:
+ sprintf (buffer, "SAR 0%02o", nshift);
+ //etime = 5;
+ break;
+ case 14:
+ sprintf (buffer, "SIR 0%02o", nshift);
+ //etime = 5;
+ break;
+ case 15:
+ sprintf (buffer, "SCR 0%02o", nshift);
+ //etime = 5;
+ break;
+ default:
+ sprintf (buffer, "SKP ???");
+ //etime = 5;
+ break;
+ }
+ break;
+ }
+ case LAW:
+ sprintf (buffer, "LAW 0%06o", y);
+ IN;
+ //etime = 5;
+ break;
+ case IOT:
+ sprintf (buffer, "IOT 0%06o", md);
+ //etime = 10;
+ break;
+ case OPR:
+ {
+ buffer[0] = 0;
+ if ((y & 04000) == 04000)
+ sprintf (buffer + strlen (buffer), "CLI ");
+ if ((y & 02000) == 02000)
+ sprintf (buffer + strlen (buffer), "LAT ");
+ if ((y & 01000) == 01000)
+ sprintf (buffer + strlen (buffer), "CMA ");
+ if ((y & 0400) == 0400)
+ sprintf (buffer + strlen (buffer), "HLT ");
+ if ((y & 0100) == 0100)
+ sprintf (buffer + strlen (buffer), "LAP ");
+ if ((y & 010) && (y & 7))
+ sprintf (buffer + strlen (buffer), "STF 0%01o ", (y & 7));
+ if ((!(y & 010)) && (y & 7))
+ sprintf (buffer + strlen (buffer), "CLF 0%01o ", (y & 7));
+ if (!(y))
+ sprintf (buffer + strlen (buffer), "NOP ");
+ //etime = 5;
+ break;
+ }
+ default:
+ sprintf (buffer, "ILLEGAL");
+ //etime = 5;
+ break;
+ }
+ return 4;
+}
diff --git a/trunk/src/emu/cpu/pdp1/tx0.c b/trunk/src/emu/cpu/pdp1/tx0.c
new file mode 100644
index 00000000000..e446a0ecde4
--- /dev/null
+++ b/trunk/src/emu/cpu/pdp1/tx0.c
@@ -0,0 +1,1303 @@
+/*
+ TX-0 emulator
+
+ Two variants:
+ * initial model 64kWord RAM
+ * later model 8kWord RAM
+
+ Raphael Nabet 2004
+*/
+
+#include "emu.h"
+#include "debugger.h"
+#include "tx0.h"
+
+#define LOG 0
+#define LOG_EXTRA 0
+
+static void execute_instruction_64kw(device_t *device);
+static void execute_instruction_8kw(device_t *device);
+static void pulse_reset(device_t *device);
+
+
+/* TX-0 Registers */
+typedef struct _tx0_state tx0_state;
+struct _tx0_state
+{
+ const tx0_reset_param_t *iface;
+
+ /* processor registers */
+ int mbr; /* memory buffer register (18 bits) */
+ int ac; /* accumulator (18 bits) */
+ int mar; /* memory address register (16 (64kW) or 13 (8kW) bits) */
+ int pc; /* program counter (16 (64kW) or 13 (8kW) bits) */
+ int ir; /* instruction register (2 (64kW) or 5 (8kW) bits) */
+ int lr; /* live register (18 bits) */
+ int xr; /* index register (14 bits) (8kW only) */
+ int pf; /* program flags (6 bits expandable to 10) (8kW only) */
+
+ /* operator panel switches */
+ int tbr; /* toggle switch buffer register (18 bits) */
+ int tac; /* toggle switch accumulator (18 bits) */
+ int tss[16]; /* toggle switch storage (18 bits * 16) */
+ unsigned int cm_sel : 16; /* individual cm select (1 bit * 16) */
+ unsigned int lr_sel : 16; /* individual lr select (1 bit * 16) */
+ unsigned int gbl_cm_sel : 1;/* global cm select (1 bit) */
+ unsigned int stop_cyc0 : 1; /* stop on cycle 0 */
+ unsigned int stop_cyc1 : 1; /* stop on cycle 1 */
+
+ /* processor state flip-flops */
+ unsigned int run : 1; /* processor is running */
+ unsigned int rim : 1; /* processor is in read-in mode */
+ unsigned int cycle : 2; /* 0 -> fetch */
+ /* 1 -> execute (except for taken branches) */
+ /* 2 -> extra execute cycle for SXA and ADO */
+
+ unsigned int ioh : 1; /* i-o halt: processor is executing an Input-Output Transfer wait */
+ unsigned int ios : 1; /* i-o synchronizer: set on i-o operation completion */
+
+ /* additional emulator state variables */
+ int rim_step; /* current step in rim execution */
+
+ int address_mask; /* address mask */
+ int ir_mask; /* IR mask */
+
+ int icount;
+
+ legacy_cpu_device *device;
+ address_space *program;
+};
+
+INLINE tx0_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == TX0_64KW ||
+ device->type() == TX0_8KW);
+ return (tx0_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+#define READ_TX0_18BIT(A) ((signed)cpustate->program->read_dword((A)<<2))
+#define WRITE_TX0_18BIT(A,V) (cpustate->program->write_dword((A)<<2,(V)))
+
+
+#define io_handler_rim 3
+
+#define PC cpustate->pc
+#define IR cpustate->ir
+#define MBR cpustate->mbr
+#define MAR cpustate->mar
+#define AC cpustate->ac
+#define LR cpustate->lr
+#define XR cpustate->xr
+#define PF cpustate->pf
+
+#define ADDRESS_MASK_64KW 0177777
+#define ADDRESS_MASK_8KW 0017777
+
+#define INCREMENT_PC_64KW (PC = (PC+1) & ADDRESS_MASK_64KW)
+#define INCREMENT_PC_8KW (PC = (PC+1) & ADDRESS_MASK_8KW)
+
+
+static int tx0_read(tx0_state *cpustate, offs_t address)
+{
+ if ((address >= 16) || (cpustate->gbl_cm_sel) || ((cpustate->cm_sel >> address) & 1))
+ /* core memory (CM) */
+ return READ_TX0_18BIT(address);
+ else if ((cpustate->lr_sel >> address) & 1)
+ /* live register (LR) */
+ return LR;
+
+ /* toggle switch storage (TSS) */
+ return cpustate->tss[address];
+}
+
+static void tx0_write(tx0_state *cpustate, offs_t address, int data)
+{
+ if ((address >= 16) || (cpustate->gbl_cm_sel) || ((cpustate->cm_sel >> address) & 1))
+ /* core memory (CM) */
+ WRITE_TX0_18BIT(address, data);
+ else if ((cpustate->lr_sel >> address) & 1)
+ /* live register (LR) */
+ LR = data;
+ else
+ /* toggle switch storage (TSS) */
+ /* TSS is read-only */
+ ;
+}
+
+static void tx0_init_common(legacy_cpu_device *device, device_irq_callback irqcallback, int is_64kw)
+{
+ tx0_state *cpustate = get_safe_token(device);
+
+ /* clean-up */
+ cpustate->iface = (const tx0_reset_param_t *)device->static_config();
+
+ cpustate->address_mask = is_64kw ? ADDRESS_MASK_64KW : ADDRESS_MASK_8KW;
+ cpustate->ir_mask = is_64kw ? 03 : 037;
+
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+}
+
+static CPU_INIT( tx0_64kw )
+{
+ tx0_init_common(device, irqcallback, 1);
+}
+
+static CPU_INIT( tx0_8kw)
+{
+ tx0_init_common(device, irqcallback, 0);
+}
+
+static CPU_RESET( tx0 )
+{
+ tx0_state *cpustate = get_safe_token(device);
+
+ /* reset CPU flip-flops */
+ pulse_reset(device);
+
+ cpustate->gbl_cm_sel = 1; /* HACK */
+}
+
+/* execute instructions on this CPU until icount expires */
+static CPU_EXECUTE( tx0_64kw )
+{
+ tx0_state *cpustate = get_safe_token(device);
+
+ do
+ {
+ debugger_instruction_hook(device, PC);
+
+
+ if (cpustate->ioh && cpustate->ios)
+ {
+ cpustate->ioh = 0;
+ cpustate->ios = 0;
+ }
+
+
+ if ((! cpustate->run) && (! cpustate->rim))
+ cpustate->icount = 0; /* if processor is stopped, just burn cycles */
+ else if (cpustate->rim)
+ {
+ switch (cpustate->rim_step)
+ {
+ case 0:
+ /* read first word as instruction */
+ AC = 0;
+ if (cpustate->iface->io_handlers[io_handler_rim])
+ (*cpustate->iface->io_handlers[io_handler_rim])(device); /* data will be transferred to AC */
+ cpustate->rim_step = 1;
+ break;
+
+ case 1:
+ if (! cpustate->ios)
+ { /* transfer incomplete: wait some more */
+ cpustate->icount = 0;
+ }
+ else
+ { /* data transfer complete */
+ cpustate->ios = 0;
+
+ MBR = AC;
+ IR = MBR >> 16; /* basic opcode */
+ if ((IR == 2) || (IR == 1)) /* trn or add instruction? */
+ {
+ PC = MBR & ADDRESS_MASK_64KW;
+ cpustate->rim = 0; /* exit read-in mode */
+ cpustate->run = (IR == 2) ? 1 : 0; /* stop if add instruction */
+ cpustate->rim_step = 0;
+ }
+ else if ((IR == 0) || (IR == 3)) /* sto or opr instruction? */
+ {
+ MAR = MBR & ADDRESS_MASK_64KW;
+ cpustate->rim_step = 2;
+ }
+ }
+ break;
+
+ case 2:
+ /* read second word as data */
+ AC = 0;
+ if (cpustate->iface->io_handlers[io_handler_rim])
+ (*cpustate->iface->io_handlers[io_handler_rim])(device); /* data will be transferred to AC */
+ cpustate->rim_step = 3;
+ break;
+
+ case 3:
+ if (! cpustate->ios)
+ { /* transfer incomplete: wait some more */
+ cpustate->icount = 0;
+ }
+ else
+ { /* data transfer complete */
+ cpustate->ios = 0;
+
+ tx0_write(cpustate, MAR, MBR = AC);
+
+ cpustate->rim_step = 0;
+ }
+ break;
+ }
+ }
+ else
+ {
+ if (cpustate->cycle == 0)
+ { /* fetch new instruction */
+ MBR = tx0_read(cpustate, MAR = PC);
+ INCREMENT_PC_64KW;
+ IR = MBR >> 16; /* basic opcode */
+ MAR = MBR & ADDRESS_MASK_64KW;
+ }
+
+ if (! cpustate->ioh)
+ {
+ if ((cpustate->stop_cyc0 && (cpustate->cycle == 0))
+ || (cpustate->stop_cyc1 && (cpustate->cycle == 1)))
+ cpustate->run = 0;
+
+ execute_instruction_64kw(device); /* execute instruction */
+ }
+
+ cpustate->icount --;
+ }
+ }
+ while (cpustate->icount > 0);
+}
+
+/* execute instructions on this CPU until icount expires */
+static CPU_EXECUTE( tx0_8kw )
+{
+ tx0_state *cpustate = get_safe_token(device);
+
+ do
+ {
+ debugger_instruction_hook(device, PC);
+
+
+ if (cpustate->ioh && cpustate->ios)
+ {
+ cpustate->ioh = 0;
+ cpustate->ios = 0;
+ }
+
+
+ if ((! cpustate->run) && (! cpustate->rim))
+ cpustate->icount = 0; /* if processor is stopped, just burn cycles */
+ else if (cpustate->rim)
+ {
+ switch (cpustate->rim_step)
+ {
+ case 0:
+ /* read first word as instruction */
+ AC = 0;
+ if (cpustate->iface->io_handlers[io_handler_rim])
+ (*cpustate->iface->io_handlers[io_handler_rim])(device); /* data will be transferred to AC */
+ cpustate->rim_step = 1;
+ break;
+
+ case 1:
+ if (! cpustate->ios)
+ { /* transfer incomplete: wait some more */
+ cpustate->icount = 0;
+ }
+ else
+ { /* data transfer complete */
+ cpustate->ios = 0;
+
+ MBR = AC;
+ IR = MBR >> 13; /* basic opcode */
+ if ((IR == 16) || (IR == 8)) /* trn or add instruction? */
+ {
+ PC = MBR & ADDRESS_MASK_8KW;
+ cpustate->rim = 0; /* exit read-in mode */
+ cpustate->run = (IR == 16) ? 1 : 0; /* stop if add instruction */
+ cpustate->rim_step = 0;
+ }
+ else if ((IR == 0) || (IR == 24)) /* sto or opr instruction? */
+ {
+ MAR = MBR & ADDRESS_MASK_8KW;
+ cpustate->rim_step = 2;
+ }
+ }
+ break;
+
+ case 2:
+ /* read second word as data */
+ AC = 0;
+ if (cpustate->iface->io_handlers[io_handler_rim])
+ (*cpustate->iface->io_handlers[io_handler_rim])(device); /* data will be transferred to AC */
+ cpustate->rim_step = 3;
+ break;
+
+ case 3:
+ if (! cpustate->ios)
+ { /* transfer incomplete: wait some more */
+ cpustate->icount = 0;
+ }
+ else
+ { /* data transfer complete */
+ cpustate->ios = 0;
+
+ tx0_write(cpustate, MAR, MBR = AC);
+
+ cpustate->rim_step = 0;
+ }
+ break;
+ }
+ }
+ else
+ {
+ if (cpustate->cycle == 0)
+ { /* fetch new instruction */
+ MBR = tx0_read(cpustate, MAR = PC);
+ INCREMENT_PC_8KW;
+ IR = MBR >> 13; /* basic opcode */
+ MAR = MBR & ADDRESS_MASK_8KW;
+ }
+
+ if (! cpustate->ioh)
+ {
+ if ((cpustate->stop_cyc0 && (cpustate->cycle == 0))
+ || (cpustate->stop_cyc1 && (cpustate->cycle == 1)))
+ cpustate->run = 0;
+
+ execute_instruction_8kw(device); /* execute instruction */
+ }
+
+ cpustate->icount -= 1;
+ }
+ }
+ while (cpustate->icount > 0);
+}
+
+
+static CPU_SET_INFO( tx0 )
+{
+ tx0_state *cpustate = get_safe_token(device);
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_SP: (void) info->i; /* no SP */ break;
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + TX0_PC: PC = info->i & cpustate->address_mask; break;
+ case CPUINFO_INT_REGISTER + TX0_IR: IR = info->i & cpustate->ir_mask; /* weird idea */ break;
+ case CPUINFO_INT_REGISTER + TX0_MBR: MBR = info->i & 0777777; break;
+ case CPUINFO_INT_REGISTER + TX0_MAR: MAR = info->i & cpustate->address_mask; break;
+ case CPUINFO_INT_REGISTER + TX0_AC: AC = info->i & 0777777; break;
+ case CPUINFO_INT_REGISTER + TX0_LR: LR = info->i & 0777777; break;
+ case CPUINFO_INT_REGISTER + TX0_XR: XR = info->i & 0037777; break;
+ case CPUINFO_INT_REGISTER + TX0_PF: PF = info->i & 077; break;
+ case CPUINFO_INT_REGISTER + TX0_TBR: cpustate->tbr = info->i & 0777777; break;
+ case CPUINFO_INT_REGISTER + TX0_TAC: cpustate->tac = info->i & 0777777; break;
+ case CPUINFO_INT_REGISTER + TX0_TSS00:
+ case CPUINFO_INT_REGISTER + TX0_TSS01:
+ case CPUINFO_INT_REGISTER + TX0_TSS02:
+ case CPUINFO_INT_REGISTER + TX0_TSS03:
+ case CPUINFO_INT_REGISTER + TX0_TSS04:
+ case CPUINFO_INT_REGISTER + TX0_TSS05:
+ case CPUINFO_INT_REGISTER + TX0_TSS06:
+ case CPUINFO_INT_REGISTER + TX0_TSS07:
+ case CPUINFO_INT_REGISTER + TX0_TSS10:
+ case CPUINFO_INT_REGISTER + TX0_TSS11:
+ case CPUINFO_INT_REGISTER + TX0_TSS12:
+ case CPUINFO_INT_REGISTER + TX0_TSS13:
+ case CPUINFO_INT_REGISTER + TX0_TSS14:
+ case CPUINFO_INT_REGISTER + TX0_TSS15:
+ case CPUINFO_INT_REGISTER + TX0_TSS16:
+ case CPUINFO_INT_REGISTER + TX0_TSS17: cpustate->tss[state-(CPUINFO_INT_REGISTER + TX0_TSS00)] = info->i & 0777777; break;
+ case CPUINFO_INT_REGISTER + TX0_CM_SEL: cpustate->cm_sel = info->i & 0177777; break;
+ case CPUINFO_INT_REGISTER + TX0_LR_SEL: cpustate->lr_sel = info->i & 0177777; break;
+ case CPUINFO_INT_REGISTER + TX0_GBL_CM_SEL: cpustate->gbl_cm_sel = info->i ? 1 : 0; break;
+ case CPUINFO_INT_REGISTER + TX0_STOP_CYC0: cpustate->stop_cyc0 = info->i ? 1 : 0; break;
+ case CPUINFO_INT_REGISTER + TX0_STOP_CYC1: cpustate->stop_cyc1 = info->i ? 1 : 0; break;
+ case CPUINFO_INT_REGISTER + TX0_RUN: cpustate->run = info->i ? 1 : 0; break;
+ case CPUINFO_INT_REGISTER + TX0_RIM: cpustate->rim = info->i ? 1 : 0; break;
+ case CPUINFO_INT_REGISTER + TX0_CYCLE: if (LOG) logerror("tx0_set_reg to cycle counter ignored\n");/* no way!*/ break;
+ case CPUINFO_INT_REGISTER + TX0_IOH: if (LOG) logerror("tx0_set_reg to ioh flip-flop ignored\n");/* no way!*/ break;
+ case CPUINFO_INT_REGISTER + TX0_IOS: if (LOG) logerror("tx0_set_reg to ios flip-flop ignored\n");/* no way!*/ break;
+ case CPUINFO_INT_REGISTER + TX0_RESET: pulse_reset(device); break;
+ case CPUINFO_INT_REGISTER + TX0_IO_COMPLETE:cpustate->ios = 1; break;
+ }
+}
+
+
+CPU_GET_INFO( tx0_64kw )
+{
+ tx0_state *cpustate = ( device != NULL && device->token() != NULL ) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(tx0_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 0; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; /*don't care*/ break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 3; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = -2; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_SP: info->i = 0; /* no SP */ break;
+ case CPUINFO_INT_PC: info->i = PC; break;
+ case CPUINFO_INT_PREVIOUSPC: info->i = 0; /* TODO??? */ break;
+
+ case CPUINFO_INT_REGISTER + TX0_PC: info->i = PC; break;
+ case CPUINFO_INT_REGISTER + TX0_IR: info->i = IR; break;
+ case CPUINFO_INT_REGISTER + TX0_MBR: info->i = MBR; break;
+ case CPUINFO_INT_REGISTER + TX0_MAR: info->i = MAR; break;
+ case CPUINFO_INT_REGISTER + TX0_AC: info->i = AC; break;
+ case CPUINFO_INT_REGISTER + TX0_LR: info->i = LR; break;
+ case CPUINFO_INT_REGISTER + TX0_XR: info->i = XR; break;
+ case CPUINFO_INT_REGISTER + TX0_PF: info->i = PF; break;
+ case CPUINFO_INT_REGISTER + TX0_TBR: info->i = cpustate->tbr; break;
+ case CPUINFO_INT_REGISTER + TX0_TAC: info->i = cpustate->tac; break;
+ case CPUINFO_INT_REGISTER + TX0_TSS00:
+ case CPUINFO_INT_REGISTER + TX0_TSS01:
+ case CPUINFO_INT_REGISTER + TX0_TSS02:
+ case CPUINFO_INT_REGISTER + TX0_TSS03:
+ case CPUINFO_INT_REGISTER + TX0_TSS04:
+ case CPUINFO_INT_REGISTER + TX0_TSS05:
+ case CPUINFO_INT_REGISTER + TX0_TSS06:
+ case CPUINFO_INT_REGISTER + TX0_TSS07:
+ case CPUINFO_INT_REGISTER + TX0_TSS10:
+ case CPUINFO_INT_REGISTER + TX0_TSS11:
+ case CPUINFO_INT_REGISTER + TX0_TSS12:
+ case CPUINFO_INT_REGISTER + TX0_TSS13:
+ case CPUINFO_INT_REGISTER + TX0_TSS14:
+ case CPUINFO_INT_REGISTER + TX0_TSS15:
+ case CPUINFO_INT_REGISTER + TX0_TSS16:
+ case CPUINFO_INT_REGISTER + TX0_TSS17: info->i = cpustate->tss[state-(CPUINFO_INT_REGISTER + TX0_TSS00)]; break;
+ case CPUINFO_INT_REGISTER + TX0_CM_SEL: info->i = cpustate->cm_sel; break;
+ case CPUINFO_INT_REGISTER + TX0_LR_SEL: info->i = cpustate->lr_sel; break;
+ case CPUINFO_INT_REGISTER + TX0_GBL_CM_SEL: info->i = cpustate->gbl_cm_sel; break;
+ case CPUINFO_INT_REGISTER + TX0_STOP_CYC0: info->i = cpustate->stop_cyc0; break;
+ case CPUINFO_INT_REGISTER + TX0_STOP_CYC1: info->i = cpustate->stop_cyc1; break;
+ case CPUINFO_INT_REGISTER + TX0_RUN: info->i = cpustate->run; break;
+ case CPUINFO_INT_REGISTER + TX0_RIM: info->i = cpustate->rim; break;
+ case CPUINFO_INT_REGISTER + TX0_CYCLE: info->i = cpustate->cycle; break;
+ case CPUINFO_INT_REGISTER + TX0_IOH: info->i = cpustate->ioh; break;
+ case CPUINFO_INT_REGISTER + TX0_IOS: info->i = cpustate->ios; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(tx0); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(tx0_64kw); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(tx0); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(tx0_64kw); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(tx0_64kw); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "TX-0"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "TX-0"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Raphael Nabet"); break;
+
+ case CPUINFO_STR_FLAGS: strcpy(info->s, ""); break;
+
+ case CPUINFO_STR_REGISTER + TX0_PC: sprintf(info->s, "PC:0%06o", PC); break;
+ case CPUINFO_STR_REGISTER + TX0_IR: sprintf(info->s, "IR:0%02o", IR); break;
+ case CPUINFO_STR_REGISTER + TX0_MBR: sprintf(info->s, "MBR:0%06o", MBR); break;
+ case CPUINFO_STR_REGISTER + TX0_MAR: sprintf(info->s, "MAR:0%06o", MAR); break;
+ case CPUINFO_STR_REGISTER + TX0_AC: sprintf(info->s, "AC:0%06o", AC); break;
+ case CPUINFO_STR_REGISTER + TX0_LR: sprintf(info->s, "LR:0%06o", LR); break;
+ case CPUINFO_STR_REGISTER + TX0_XR: sprintf(info->s, "XR:0%05o", XR); break;
+ case CPUINFO_STR_REGISTER + TX0_PF: sprintf(info->s, "PF:0%02o", PF); break;
+ case CPUINFO_STR_REGISTER + TX0_TBR: sprintf(info->s, "TBR:0%06o", cpustate->tbr); break;
+ case CPUINFO_STR_REGISTER + TX0_TAC: sprintf(info->s, "TAC:0%06o", cpustate->tac); break;
+ case CPUINFO_STR_REGISTER + TX0_TSS00:
+ case CPUINFO_STR_REGISTER + TX0_TSS01:
+ case CPUINFO_STR_REGISTER + TX0_TSS02:
+ case CPUINFO_STR_REGISTER + TX0_TSS03:
+ case CPUINFO_STR_REGISTER + TX0_TSS04:
+ case CPUINFO_STR_REGISTER + TX0_TSS05:
+ case CPUINFO_STR_REGISTER + TX0_TSS06:
+ case CPUINFO_STR_REGISTER + TX0_TSS07:
+ case CPUINFO_STR_REGISTER + TX0_TSS10:
+ case CPUINFO_STR_REGISTER + TX0_TSS11:
+ case CPUINFO_STR_REGISTER + TX0_TSS12:
+ case CPUINFO_STR_REGISTER + TX0_TSS13:
+ case CPUINFO_STR_REGISTER + TX0_TSS14:
+ case CPUINFO_STR_REGISTER + TX0_TSS15:
+ case CPUINFO_STR_REGISTER + TX0_TSS16:
+ case CPUINFO_STR_REGISTER + TX0_TSS17: sprintf(info->s, "TSS%02o:0%06o", state-(CPUINFO_STR_REGISTER + TX0_TSS00), cpustate->tss[state-(CPUINFO_STR_REGISTER + TX0_TSS00)]); break;
+ case CPUINFO_STR_REGISTER + TX0_CM_SEL: sprintf(info->s, "CMSEL:0%06o", cpustate->cm_sel); break;
+ case CPUINFO_STR_REGISTER + TX0_LR_SEL: sprintf(info->s, "LRSEL:0%06o", cpustate->lr_sel); break;
+ case CPUINFO_STR_REGISTER + TX0_GBL_CM_SEL: sprintf(info->s, "GBLCMSEL:%X", cpustate->gbl_cm_sel); break;
+ case CPUINFO_STR_REGISTER + TX0_STOP_CYC0: sprintf(info->s, "STOPCYC0:%X", cpustate->stop_cyc0); break;
+ case CPUINFO_STR_REGISTER + TX0_STOP_CYC1: sprintf(info->s, "STOPCYC1:%X", cpustate->stop_cyc1); break;
+ case CPUINFO_STR_REGISTER + TX0_RUN: sprintf(info->s, "RUN:%X", cpustate->run); break;
+ case CPUINFO_STR_REGISTER + TX0_RIM: sprintf(info->s, "RIM:%X", cpustate->rim); break;
+ case CPUINFO_STR_REGISTER + TX0_CYCLE: sprintf(info->s, "CYCLE:%X", cpustate->cycle); break;
+ case CPUINFO_STR_REGISTER + TX0_IOH: sprintf(info->s, "IOH:%X", cpustate->ioh); break;
+ case CPUINFO_STR_REGISTER + TX0_IOS: sprintf(info->s, "IOS:%X", cpustate->ios); break;
+ }
+}
+
+CPU_GET_INFO( tx0_8kw )
+{
+ tx0_state *cpustate = ( device != NULL && device->token() != NULL ) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(tx0_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 0; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; /*don't care*/ break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 3; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 13; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = -2; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_SP: info->i = 0; /* no SP */ break;
+ case CPUINFO_INT_PC: info->i = PC; break;
+ case CPUINFO_INT_PREVIOUSPC: info->i = 0; /* TODO??? */ break;
+
+ case CPUINFO_INT_REGISTER + TX0_PC: info->i = PC; break;
+ case CPUINFO_INT_REGISTER + TX0_IR: info->i = IR; break;
+ case CPUINFO_INT_REGISTER + TX0_MBR: info->i = MBR; break;
+ case CPUINFO_INT_REGISTER + TX0_MAR: info->i = MAR; break;
+ case CPUINFO_INT_REGISTER + TX0_AC: info->i = AC; break;
+ case CPUINFO_INT_REGISTER + TX0_LR: info->i = LR; break;
+ case CPUINFO_INT_REGISTER + TX0_XR: info->i = XR; break;
+ case CPUINFO_INT_REGISTER + TX0_PF: info->i = PF; break;
+ case CPUINFO_INT_REGISTER + TX0_TBR: info->i = cpustate->tbr; break;
+ case CPUINFO_INT_REGISTER + TX0_TAC: info->i = cpustate->tac; break;
+ case CPUINFO_INT_REGISTER + TX0_TSS00:
+ case CPUINFO_INT_REGISTER + TX0_TSS01:
+ case CPUINFO_INT_REGISTER + TX0_TSS02:
+ case CPUINFO_INT_REGISTER + TX0_TSS03:
+ case CPUINFO_INT_REGISTER + TX0_TSS04:
+ case CPUINFO_INT_REGISTER + TX0_TSS05:
+ case CPUINFO_INT_REGISTER + TX0_TSS06:
+ case CPUINFO_INT_REGISTER + TX0_TSS07:
+ case CPUINFO_INT_REGISTER + TX0_TSS10:
+ case CPUINFO_INT_REGISTER + TX0_TSS11:
+ case CPUINFO_INT_REGISTER + TX0_TSS12:
+ case CPUINFO_INT_REGISTER + TX0_TSS13:
+ case CPUINFO_INT_REGISTER + TX0_TSS14:
+ case CPUINFO_INT_REGISTER + TX0_TSS15:
+ case CPUINFO_INT_REGISTER + TX0_TSS16:
+ case CPUINFO_INT_REGISTER + TX0_TSS17: info->i = cpustate->tss[state-(CPUINFO_INT_REGISTER + TX0_TSS00)]; break;
+ case CPUINFO_INT_REGISTER + TX0_CM_SEL: info->i = cpustate->cm_sel; break;
+ case CPUINFO_INT_REGISTER + TX0_LR_SEL: info->i = cpustate->lr_sel; break;
+ case CPUINFO_INT_REGISTER + TX0_GBL_CM_SEL: info->i = cpustate->gbl_cm_sel; break;
+ case CPUINFO_INT_REGISTER + TX0_STOP_CYC0: info->i = cpustate->stop_cyc0; break;
+ case CPUINFO_INT_REGISTER + TX0_STOP_CYC1: info->i = cpustate->stop_cyc1; break;
+ case CPUINFO_INT_REGISTER + TX0_RUN: info->i = cpustate->run; break;
+ case CPUINFO_INT_REGISTER + TX0_RIM: info->i = cpustate->rim; break;
+ case CPUINFO_INT_REGISTER + TX0_CYCLE: info->i = cpustate->cycle; break;
+ case CPUINFO_INT_REGISTER + TX0_IOH: info->i = cpustate->ioh; break;
+ case CPUINFO_INT_REGISTER + TX0_IOS: info->i = cpustate->ios; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(tx0); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(tx0_8kw); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(tx0); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(tx0_8kw); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(tx0_8kw); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "TX-0"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "TX-0"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Raphael Nabet"); break;
+
+ case CPUINFO_STR_FLAGS: strcpy(info->s, ""); break;
+
+ case CPUINFO_STR_REGISTER + TX0_PC: sprintf(info->s, "PC:0%06o", PC); break;
+ case CPUINFO_STR_REGISTER + TX0_IR: sprintf(info->s, "IR:0%02o", IR); break;
+ case CPUINFO_STR_REGISTER + TX0_MBR: sprintf(info->s, "MBR:0%06o", MBR); break;
+ case CPUINFO_STR_REGISTER + TX0_MAR: sprintf(info->s, "MAR:0%06o", MAR); break;
+ case CPUINFO_STR_REGISTER + TX0_AC: sprintf(info->s, "AC:0%06o", AC); break;
+ case CPUINFO_STR_REGISTER + TX0_LR: sprintf(info->s, "LR:0%06o", LR); break;
+ case CPUINFO_STR_REGISTER + TX0_XR: sprintf(info->s, "XR:0%05o", XR); break;
+ case CPUINFO_STR_REGISTER + TX0_PF: sprintf(info->s, "PF:0%02o", PF); break; break;
+ case CPUINFO_STR_REGISTER + TX0_TBR: sprintf(info->s, "TBR:0%06o", cpustate->tbr); break;
+ case CPUINFO_STR_REGISTER + TX0_TAC: sprintf(info->s, "TAC:0%06o", cpustate->tac); break;
+ case CPUINFO_STR_REGISTER + TX0_TSS00:
+ case CPUINFO_STR_REGISTER + TX0_TSS01:
+ case CPUINFO_STR_REGISTER + TX0_TSS02:
+ case CPUINFO_STR_REGISTER + TX0_TSS03:
+ case CPUINFO_STR_REGISTER + TX0_TSS04:
+ case CPUINFO_STR_REGISTER + TX0_TSS05:
+ case CPUINFO_STR_REGISTER + TX0_TSS06:
+ case CPUINFO_STR_REGISTER + TX0_TSS07:
+ case CPUINFO_STR_REGISTER + TX0_TSS10:
+ case CPUINFO_STR_REGISTER + TX0_TSS11:
+ case CPUINFO_STR_REGISTER + TX0_TSS12:
+ case CPUINFO_STR_REGISTER + TX0_TSS13:
+ case CPUINFO_STR_REGISTER + TX0_TSS14:
+ case CPUINFO_STR_REGISTER + TX0_TSS15:
+ case CPUINFO_STR_REGISTER + TX0_TSS16:
+ case CPUINFO_STR_REGISTER + TX0_TSS17: sprintf(info->s, "TSS%02o:0%06o", state-(CPUINFO_STR_REGISTER + TX0_TSS00), cpustate->tss[state-(CPUINFO_STR_REGISTER + TX0_TSS00)]); break;
+ case CPUINFO_STR_REGISTER + TX0_CM_SEL: sprintf(info->s, "CMSEL:0%06o", cpustate->cm_sel); break;
+ case CPUINFO_STR_REGISTER + TX0_LR_SEL: sprintf(info->s, "LRSEL:0%06o", cpustate->lr_sel); break;
+ case CPUINFO_STR_REGISTER + TX0_GBL_CM_SEL: sprintf(info->s, "GBLCMSEL:%X", cpustate->gbl_cm_sel); break;
+ case CPUINFO_STR_REGISTER + TX0_STOP_CYC0: sprintf(info->s, "STOPCYC0:%X", cpustate->stop_cyc0); break;
+ case CPUINFO_STR_REGISTER + TX0_STOP_CYC1: sprintf(info->s, "STOPCYC1:%X", cpustate->stop_cyc1); break;
+ case CPUINFO_STR_REGISTER + TX0_RUN: sprintf(info->s, "RUN:%X", cpustate->run); break;
+ case CPUINFO_STR_REGISTER + TX0_RIM: sprintf(info->s, "RIM:%X", cpustate->rim); break;
+ case CPUINFO_STR_REGISTER + TX0_CYCLE: sprintf(info->s, "CYCLE:%X", cpustate->cycle); break;
+ case CPUINFO_STR_REGISTER + TX0_IOH: sprintf(info->s, "IOH:%X", cpustate->ioh); break;
+ case CPUINFO_STR_REGISTER + TX0_IOS: sprintf(info->s, "IOS:%X", cpustate->ios); break;
+ }
+}
+
+
+/* execute one instruction */
+static void execute_instruction_64kw(device_t *device)
+{
+ tx0_state *cpustate = get_safe_token(device);
+
+ if (! cpustate->cycle)
+ {
+ cpustate->cycle = 1; /* most frequent case */
+ switch (IR)
+ {
+ case 0: /* STOre */
+ case 1: /* ADD */
+ break;
+
+ case 2: /* TRansfer on Negative */
+ if (AC & 0400000)
+ {
+ PC = MAR & ADDRESS_MASK_64KW;
+ cpustate->cycle = 0; /* instruction only takes one cycle if branch
+ is taken */
+ }
+ break;
+
+ case 3: /* OPeRate */
+ if (MAR & 0100000)
+ /* (0.8) CLL = Clear the left nine digital positions of the AC */
+ AC &= 0000777;
+
+ if (MAR & 0040000)
+ /* (0.8) CLR = Clear the right nine digital positions of the AC */
+ AC &= 0777000;
+
+ if (((MAR & 0030000) >> 12) == 1)
+ /* (0.8) IOS In-Out Stop = Stop machine so that an In-Out command
+ (specified by digits 6 7 8 of MAR) may be executed */
+ cpustate->ioh = 1;
+
+ if (((MAR & 0007000) >> 9) != 0)
+ {
+ /* ((MAR & 0007000) >> 9) is device ID */
+ /* 7: */
+ /* (0.8) P7H = Punch holes 1-6 in flexo tape specified by AC
+ digital positions 2, 5, 8, 11, 14, and 17. Also punches a 7th
+ hole on tape. */
+ /* 6: */
+ /* (0.8) P6H = Same as P7H but no seventh hole */
+ /* 4: */
+ /* (0.8) PNT = Print one flexowriter character specified by AC
+ digits 2, 5, 8, 11, 14, and 17. */
+ /* 1: */
+ /* (0.8) R1C = Read one line of flexo tape so that tape positions
+ 1, 2, 3, 4, 5, and 6 will be put in the AC digital positions 0,
+ 3, 6, 9, 12 and 15. */
+ /* 3: */
+ /* (0.8) R3C = Read one line of flexo tape into AC digits 0, 3, 6,
+ 9, 12 and 15. Then cycle the AC one digital position; read the
+ next line on tape into AC digits 0, 3, 6, 9, 12 and 15, cycle
+ the AC right one digital position and read the third and last
+ line into AC digits 0, 3, 6, 9, 12 and 15. (This command is
+ equal to a triple CYR-R1C.) */
+ /* 2: */
+ /* (0.8) DIS = Intensify a point on the scope with x and y
+ coordinates where x is specified by AC digits 0-8 with digit 0
+ being used as the sign and y is specified by AC digits 9-17
+ with digit 9 being used as the sign for y. The complement
+ system is in effect when the signs are negative. */
+ /* (5 is undefined) */
+ int index = (MAR & 0007000) >> 9;
+
+ if (cpustate->iface->io_handlers[index])
+ (*cpustate->iface->io_handlers[index])(device);
+ cpustate->ioh = 1;
+ }
+ break;
+ }
+ }
+ else
+ {
+ cpustate->cycle = 0; /* always true */
+ switch (IR)
+ {
+ case 0: /* STOre */
+ tx0_write(cpustate, MAR, (MBR = AC));
+ break;
+
+ case 1: /* ADD */
+ MBR = tx0_read(cpustate, MAR);
+
+ AC = AC + MBR;
+ AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */
+
+ if (AC == 0777777) /* check for -0 */
+ AC = 0;
+ break;
+
+ case 2: /* TRansfer on Negative */
+ break;
+
+ case 3: /* OPeRate */
+ if ((MAR & 0000104) == 0000100)
+ /* (1.1) PEN = Read the light pen flip-flops 1 and 2 into AC(0) and
+ AC(1). */
+ /*...*/{ }
+
+ if ((MAR & 0000104) == 0000004)
+ /* (1.1) TAC = Insert a one in each digital position of the AC
+ wherever there is a one in the corresponding digital position
+ of the TAC. */
+ /*...*/ { }
+
+ if (MAR & 0000040)
+ /* (1.2) COM = Complement every digit in the accumulator */
+ AC ^= 0777777;
+
+ if ((MAR & 0000003) == 1)
+ /* (1.2) AMB = Store the contents of the AC in the MBR. */
+ MBR = AC;
+
+ if ((MAR & 0000003) == 3)
+ /* (1.2) TBR = Store the contents of the TBR in the MBR. */
+ /*...*/ { }
+
+ if ((MAR & 0000003) == 2)
+ /* (1.3) LMB = Store the contents of the LR in the MBR. */
+ MBR = LR;
+ break;
+
+ if (((MAR & 0000600) >> 7) == 1)
+ /* (1.3) MLR = Store the contents of the MBR (memory buffer
+ register) in the live reg. */
+ LR = MBR;
+
+ if (((MAR & 0000600) >> 7) == 2)
+ /* (1.4) SHR = Shift the AC right one place, i.e. multiply the AC
+ by 2^-1 */
+ AC >>= 1;
+
+ if (((MAR & 0000600) >> 7) == 3)
+ /* (1.4) CYR = Cycle the AC right one digital position (AC(17) will
+ become AC(0)) */
+ AC = (AC >> 1) | ((AC & 1) << 17);
+
+ if (MAR & 0000020)
+ /* (1.4) PAD = Partial add AC to MBR, that is, for every digital
+ position of the MBR that contains a one, complement the digit
+ in the corresponding digital position of the AC. This is also
+ called a half add. */
+ AC ^= MBR;
+
+ if (MAR & 0000010)
+ { /* (1.7) CRY = Partial add the 18 digits of the AC to the
+ corresponding 18 digits of the carry.
+
+ To determine what the 18 digits of the carry are, use the
+ following rule:
+
+ "Grouping the AC and MBR digits into pairs and proceeding from
+ right to left, assign the carry digit of the next pair to a one
+ if in the present pair MBR = 1 and AC = 0 or if in the present
+ pair AC = 1 and carry 1.
+
+ (Note: the 0th digit pair determines the 17th pair's carry
+ digit)" */
+ AC ^= MBR;
+
+ AC = AC + MBR;
+ AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */
+
+ if (AC == 0777777) /* check for -0 */
+ AC = 0;
+ }
+
+ if (((MAR & 0030000) >> 12) == 3)
+ /* (1.8) Hlt = Halt the computer */
+ cpustate->run = 0;
+
+ break;
+ }
+ }
+}
+
+static void indexed_address_eval(tx0_state *cpustate)
+{
+ MAR = MAR + XR;
+ MAR = (MAR + (MAR >> 14)) & 0037777; /* propagate carry around */
+ //if (MAR == 0037777) /* check for -0 */
+ // MAR = 0;
+ if (MAR & 0020000) /* fix negative (right???) */
+ MAR = (MAR + 1) & 0017777;
+}
+
+/* execute one instruction */
+static void execute_instruction_8kw(device_t *device)
+{
+ tx0_state *cpustate = get_safe_token(device);
+
+ if (! cpustate->cycle)
+ {
+ cpustate->cycle = 1; /* most frequent case */
+ switch (IR)
+ {
+ case 0: /* STOre */
+ case 1: /* STore indeXed */
+ case 2: /* Store indeX in Address */
+ case 3: /* ADd One */
+ case 4: /* Store LR */
+ case 5: /* Store Lr indeXed */
+ case 6: /* STore Zero */
+ case 8: /* ADD */
+ case 9: /* ADd indeXed */
+ case 10: /* LoaD indeX */
+ case 11: /* AUgment indeX */
+ case 12: /* Load LR */
+ case 13: /* Load Lr indeXed */
+ case 14: /* LoaD Ac */
+ case 15: /* Load Ac indeXed */
+ break;
+
+ case 16: /* TRansfer on Negative */
+ if (AC & 0400000)
+ {
+ PC = MAR & 0017777;
+ cpustate->cycle = 0; /* instruction only takes one cycle if branch
+ is taken */
+ }
+ break;
+
+ case 17: /* Transfer on ZEro */
+ if ((AC == 0000000) || (AC == 0777777))
+ {
+ PC = MAR & 0017777;
+ cpustate->cycle = 0; /* instruction only takes one cycle if branch
+ is taken */
+ }
+ break;
+
+ case 18: /* Transfer and Set indeX */
+ XR = PC;
+ PC = MAR & 0017777;
+ cpustate->cycle = 0; /* instruction only takes one cycle if branch
+ is taken */
+ break;
+
+ case 19: /* Transfer and IndeX */
+ if ((XR != 0000000) && (XR != 0037777))
+ {
+ if (XR & 0020000)
+ XR ++;
+ else
+ XR--;
+ PC = MAR & 0017777;
+ cpustate->cycle = 0; /* instruction only takes one cycle if branch
+ is taken */
+ }
+ break;
+
+ case 21: /* TRansfer indeXed */
+ indexed_address_eval(cpustate);
+ case 20: /* TRAnsfer */
+ PC = MAR & 0017777;
+ cpustate->cycle = 0; /* instruction only takes one cycle if branch
+ is taken */
+ break;
+
+ case 22: /* Transfer on external LeVel */
+ /*if (...)
+ {
+ PC = MAR & 0017777;
+ cpustate->cycle = 0;*/ /* instruction only takes one cycle if branch
+ is taken */
+ /*}*/
+ break;
+
+ case 24: /* OPeRate */
+ case 25:
+ case 26:
+ case 27:
+ case 28:
+ case 29:
+ case 30:
+ case 31:
+ if (((IR & 001) == 00) && ((MAR & 017000) == 004000))
+ { /* Select class instruction */
+ if (IR & 004)
+ /* (0.8???) CLA = CLear Ac */
+ AC = 0;
+
+ /* (IOS???) SEL = SELect */
+ if (cpustate->iface->sel_handler)
+ (*cpustate->iface->sel_handler)(device);
+ }
+ else
+ { /* Normal operate class instruction */
+ if (((IR & 001) == 01) && ((MAR & 017000) == 011000))
+ /* (0.6) CLL = CLear Left 9 bits of ac */
+ AC &= 0000777;
+
+ if (((IR & 001) == 01) && ((MAR & 017000) == 012000))
+ /* (0.6) CLR = CLear Right 9 bits of ac */
+ AC &= 0777000;
+
+ if (IR & 002)
+ /* (0.7) AMB = transfer Ac to MBr */
+ MBR = AC;
+
+ if (IR & 004)
+ /* (0.8) CLA = CLear Ac */
+ AC = 0;
+
+ if (((IR & 001) == 01) && ((MAR & 010000) == 000000))
+ { /* (IOS) In-Out group commands */
+ /* ((MAR & 0007000) >> 9) is device ID */
+ /* 0: */
+ /* (***) CPY = CoPY synchronizes transmission of information
+ between in-out equipment and computer. */
+ /* 1: */
+ /* (IOS) R1L = Read 1 Line of tape from PETR into AC bits 0, 3,
+ 6, 9, 12, 15, with CYR before read (inclusive or) */
+ /* 3: */
+ /* (IOS) R3L = Read 3 Lines of tape from PETR into AC bits 0,
+ 3, 6, 9, 12, 15, with CYR before each read (inclusive or) */
+ /* 2: */
+ /* (IOS) DIS = DISplay a point on scope (AC bits 0-8 specify x
+ coordinate, AC bits 9-17 specify y coordinate). The
+ coordinate (0, 0) is usually at the lower left hand corner
+ of the scope. A console switch is available to relocate
+ (0,0) to the center. */
+ /* 6: */
+ /* (IOS) P6H = Punch one 6-bit line of flexo tape (without 7th
+ hole) from ac bits 2, 5, 8, 11, 14, 17. Note: lines
+ without 7th hole are ignored by PETR. */
+ /* 7: */
+ /* (IOS) P7H = same as P6H, but with 7th hole */
+ /* 4: */
+ /* (IOS) PRT = Print one six bit flexo character from AC bits
+ 2, 5, 8, 11, 14, 17. */
+ /* (5 is undefined) */
+ int index = (MAR & 0007000) >> 9;
+
+ if (cpustate->iface->io_handlers[index])
+ (*cpustate->iface->io_handlers[index])(device);
+ cpustate->ioh = 1;
+ }
+
+ if (((IR & 001) == 00) && ((MAR & 010000) == 010000))
+ { /* (IOS) EX0 through EX7 = operate user's EXternal equipment. */
+ switch ((MAR & 0007000) >> 9)
+ {
+ /* ... */
+ }
+ }
+ }
+ break;
+ }
+ }
+ else
+ {
+ if (((IR != 2) && (IR != 3)) || (cpustate->cycle == 2))
+ cpustate->cycle = 0;
+ else
+ cpustate->cycle = 2; /* SXA and ADO have an extra cycle 2 */
+ switch (IR)
+ {
+ case 1: /* STore indeXed */
+ indexed_address_eval(cpustate);
+ case 0: /* STOre */
+ tx0_write(cpustate, MAR, (MBR = AC));
+ break;
+
+ case 2: /* Store indeX in Address */
+ if (cpustate->cycle)
+ { /* cycle 1 */
+ MBR = tx0_read(cpustate, MAR);
+ MBR = (MBR & 0760000) | (XR & 0017777);
+ }
+ else
+ { /* cycle 2 */
+ tx0_write(cpustate, MAR, MBR);
+ }
+ break;
+
+ case 3: /* ADd One */
+ if (cpustate->cycle)
+ { /* cycle 1 */
+ AC = tx0_read(cpustate, MAR) + 1;
+
+ #if 0
+ AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */
+ if (AC == 0777777) /* check for -0 (right???) */
+ AC = 0;
+ #else
+ if (AC >= 0777777)
+ AC = (AC + 1) & 0777777;
+ #endif
+ }
+ else
+ { /* cycle 2 */
+ tx0_write(cpustate, MAR, (MBR = AC));
+ }
+ break;
+
+ case 5: /* Store Lr indeXed */
+ indexed_address_eval(cpustate);
+ case 4: /* Store LR */
+ tx0_write(cpustate, MAR, (MBR = LR));
+ break;
+
+ case 6: /* STore Zero */
+ tx0_write(cpustate, MAR, (MBR = 0));
+ break;
+
+ case 9: /* ADd indeXed */
+ indexed_address_eval(cpustate);
+ case 8: /* ADD */
+ MBR = tx0_read(cpustate, MAR);
+
+ AC = AC + MBR;
+ AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */
+
+ if (AC == 0777777) /* check for -0 */
+ AC = 0;
+ break;
+
+ case 10: /* LoaD indeX */
+ MBR = tx0_read(cpustate, MAR);
+ XR = (MBR & 0017777) | ((MBR >> 4) & 0020000);
+ break;
+
+ case 11: /* AUgment indeX */
+ MBR = tx0_read(cpustate, MAR);
+
+ XR = XR + ((MBR & 0017777) | ((MBR >> 4) & 0020000));
+ XR = (XR + (XR >> 14)) & 0037777; /* propagate carry around */
+
+ //if (XR == 0037777) /* check for -0 */
+ // XR = 0;
+ break;
+
+ case 13: /* Load Lr indeXed */
+ indexed_address_eval(cpustate);
+ case 12: /* Load LR */
+ LR = MBR = tx0_read(cpustate, MAR);
+ break;
+
+ case 15: /* Load Ac indeXed */
+ indexed_address_eval(cpustate);
+ case 14: /* LoaD Ac */
+ AC = MBR = tx0_read(cpustate, MAR);
+ break;
+
+ case 16: /* TRansfer on Negative */
+ case 17: /* Transfer on ZEro */
+ case 18: /* Transfer and Set indeX */
+ case 19: /* Transfer and IndeX */
+ case 20: /* TRAnsfer */
+ case 21: /* TRansfer indeXed */
+ case 22: /* Transfer on external LeVel */
+ break;
+
+ case 24: /* OPeRate */
+ case 25:
+ case 26:
+ case 27:
+ case 28:
+ case 29:
+ case 30:
+ case 31:
+ if (((IR & 001) == 00) && ((MAR & 017000) == 004000))
+ { /* Select class instruction */
+ }
+ else
+ { /* Normal operate class instruction */
+ if (((IR & 001) == 00) && ((MAR & 017000) == 003000))
+ { /* (1.1) PEN = set ac bit 0 from light PEN ff, and ac bit 1 from
+ light gun ff. (ffs contain one if pen or gun saw displayed
+ point.) Then clear both light pen and light gun ffs */
+ /*AC = (AC & 0177777) |?...;*/
+ /*... = 0;*/
+ }
+
+ if (((IR & 001) == 00) && ((MAR & 017000) == 001000))
+ /* (1.1) TAC = transfer TAC into ac (inclusive or) */
+ AC |= cpustate->tac;
+
+ if (((IR & 001) == 00) && ((MAR & 017000) == 002000))
+ /* (1.2) TBR = transfer TBR into mbr (inclusive or) */
+ MBR |= cpustate->tbr;
+
+ if (((IR & 001) == 00) && ((MAR & 017000) == 006000))
+ /* (1.2) RPF = Read Program Flag register into mbr (inclusive or) */
+ MBR |= PF << 8;
+
+ if (MAR & 0000040)
+ /* (1.2) COM = COMplement ac */
+ AC ^= 0777777;
+
+ if ((! (MAR & 0000400)) && (MAR & 0000100))
+ { /* (1.2) XMB = Transfer XR contents to MBR */
+ MBR = XR;
+ if (XR & 0020000)
+ MBR |= 0740000;
+ }
+
+ if (MAR & 0000004)
+ {
+ switch (MAR & 0000003)
+ {
+ case 0000003: /* (1.2) And LR and MBR */
+ MBR &= LR;
+ break;
+
+ case 0000001: /* (1.3) Or LR into MBR */
+ MBR |= LR;
+ break;
+
+ default:
+ if (LOG)
+ logerror("unrecognized instruction");
+ break;
+ }
+ }
+
+ if (((! (MAR & 0000400)) && (MAR & 0000200)) && ((! (MAR & 0000004)) && (MAR & 0000002)))
+ { /* LMB and MBL used simultaneously interchange LR and MBR */
+ int tmp = MBR;
+ MBR = LR;
+ LR = tmp;
+ }
+ else if ((! (MAR & 0000400)) && (MAR & 0000200))
+ /* (1.4) MBL = Transfer MBR contents to LR */
+ LR = MBR;
+ else if ((! (MAR & 0000004)) && (MAR & 0000002))
+ /* (1.4) LMB = Store the contents of the LR in the MBR. */
+ MBR = LR;
+
+ if (MAR & 0000020)
+ /* (1.5) PAD = Partial ADd mbr to ac */
+ AC ^= MBR;
+
+ if (MAR & 0000400)
+ {
+ switch (MAR & 0000300)
+ {
+ case 0000000: /* (1.6) CYR = CYcle ac contents Right one binary
+ position (AC(17) -> AC(0)) */
+ AC = (AC >> 1) | ((AC & 1) << 17);
+ break;
+
+ case 0000200: /* (1.6) CYcle ac contents Right one binary
+ position (AC(0) unchanged) */
+ AC = (AC >> 1) | (AC & 0400000);
+ break;
+
+ default:
+ if (LOG)
+ logerror("unrecognized instruction");
+ break;
+ }
+ }
+
+ if (((IR & 001) == 00) && ((MAR & 017000) == 007000))
+ /* (1.6) SPF = Set Program Flag register from mbr */
+ PF = (MBR >> 8) & 077;
+
+ if (MAR & 0000010)
+ { /* (1.7?) CRY = Partial ADd the 18 digits of the AC to the
+ corresponding 18 digits of the carry. */
+ AC ^= MBR;
+
+ AC = AC + MBR;
+ AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */
+
+ if (AC == 0777777) /* check for -0 */
+ AC = 0;
+ }
+
+ if ((! (MAR & 0000004)) && (MAR & 0000001))
+ /* (1.8) MBX = Transfer MBR contents to XR */
+ XR = (MBR & 0017777) | ((MBR >> 4) & 0020000);
+
+ if (((IR & 001) == 01) && ((MAR & 017000) == 010000))
+ /* (1.8) HLT = HaLT the computer and sound chime */
+ cpustate->run = 0;
+ }
+ break;
+
+ default: /* Illegal */
+ /* ... */
+ break;
+ }
+ }
+}
+
+/*
+ Simulate a pulse on reset line:
+ reset most registers and flip-flops, and initialize a few emulator state
+ variables.
+*/
+static void pulse_reset(device_t *device)
+{
+ tx0_state *cpustate = get_safe_token(device);
+
+ /* processor registers */
+ PC = 0; /* ??? */
+ IR = 0; /* ??? */
+ /*MBR = 0;*/ /* ??? */
+ /*MAR = 0;*/ /* ??? */
+ /*AC = 0;*/ /* ??? */
+ /*LR = 0;*/ /* ??? */
+
+ /* processor state flip-flops */
+ cpustate->run = 0; /* ??? */
+ cpustate->rim = 0; /* ??? */
+ cpustate->ioh = 0; /* ??? */
+ cpustate->ios = 0; /* ??? */
+
+ cpustate->rim_step = 0;
+
+ /* now, we kindly ask IO devices to reset, too */
+ if (cpustate->iface->io_reset_callback)
+ (*cpustate->iface->io_reset_callback)(device);
+}
+
+DEFINE_LEGACY_CPU_DEVICE(TX0_64KW, tx0_64kw);
+DEFINE_LEGACY_CPU_DEVICE(TX0_8KW, tx0_8kw);
diff --git a/trunk/src/emu/cpu/pdp1/tx0.h b/trunk/src/emu/cpu/pdp1/tx0.h
new file mode 100644
index 00000000000..d36c48082e0
--- /dev/null
+++ b/trunk/src/emu/cpu/pdp1/tx0.h
@@ -0,0 +1,52 @@
+#pragma once
+
+#ifndef __TX0_H__
+#define __TX0_H__
+
+
+
+/* register ids for tx0_get_reg/tx0_set_reg */
+enum
+{
+ TX0_MBR=1, TX0_AC, TX0_MAR, TX0_PC, TX0_IR, TX0_LR, TX0_XR, TX0_PF,
+ TX0_TBR, TX0_TAC,
+ TX0_TSS00, TX0_TSS01, TX0_TSS02, TX0_TSS03, TX0_TSS04, TX0_TSS05, TX0_TSS06, TX0_TSS07,
+ TX0_TSS10, TX0_TSS11, TX0_TSS12, TX0_TSS13, TX0_TSS14, TX0_TSS15, TX0_TSS16, TX0_TSS17,
+ TX0_CM_SEL, TX0_LR_SEL, TX0_GBL_CM_SEL,
+ TX0_STOP_CYC0, TX0_STOP_CYC1,
+ TX0_RUN, TX0_RIM,
+ TX0_CYCLE, TX0_IOH, TX0_IOS,
+ TX0_RESET, /* hack, do not use directly, use tx0_pulse_reset instead */
+ TX0_IO_COMPLETE /* hack, do not use directly, use tx0_pulse_io_complete instead */
+};
+
+#define tx0_pulse_reset(cpudevice) cpu_set_reg(cpudevice, TX0_RESET, 0)
+#define tx0_pulse_io_complete(cpudevice) cpu_set_reg(cpudevice, TX0_IO_COMPLETE, 0)
+
+typedef struct _tx0_reset_param_t tx0_reset_param_t;
+struct _tx0_reset_param_t
+{
+ /* 8 standard I/O handlers:
+ 0: cpy (8kW only)
+ 1: r1l
+ 2: dis
+ 3: r3l
+ 4: prt
+ 5: reserved (for unimplemented typ instruction?)
+ 6: p6h
+ 7: p7h */
+ void (*io_handlers[8])(device_t *device);
+ /* select instruction handler */
+ void (*sel_handler)(device_t *device);
+ /* callback called when reset line is pulsed: IO devices should reset */
+ void (*io_reset_callback)(device_t *device);
+};
+
+/* PUBLIC FUNCTIONS */
+DECLARE_LEGACY_CPU_DEVICE(TX0_64KW, tx0_64kw);
+DECLARE_LEGACY_CPU_DEVICE(TX0_8KW, tx0_8kw);
+
+CPU_DISASSEMBLE( tx0_64kw );
+CPU_DISASSEMBLE( tx0_8kw );
+
+#endif /* __TX0_H__ */
diff --git a/trunk/src/emu/cpu/pdp1/tx0dasm.c b/trunk/src/emu/cpu/pdp1/tx0dasm.c
new file mode 100644
index 00000000000..cbffead5fe8
--- /dev/null
+++ b/trunk/src/emu/cpu/pdp1/tx0dasm.c
@@ -0,0 +1,121 @@
+#include "emu.h"
+#include "cpu/pdp1/tx0.h"
+
+CPU_DISASSEMBLE( tx0_64kw )
+{
+ int md;
+ int x;
+
+ md = oprom[0] << 24 | oprom[1] << 16 | oprom[2] << 8 | oprom[3];
+
+ x = md & 0177777;
+ switch (md >> 16)
+ {
+ case 0:
+ sprintf (buffer, "sto 0%06o", x);
+ break;
+ case 1:
+ sprintf (buffer, "add 0%06o", x);
+ break;
+ case 2:
+ sprintf (buffer, "trn 0%06o", x);
+ break;
+ case 3:
+ sprintf (buffer, "opr 0%06o", x);
+ break;
+ }
+ return 1;
+}
+
+CPU_DISASSEMBLE( tx0_8kw )
+{
+ int md;
+ int x;
+
+ md = oprom[0] << 24 | oprom[1] << 16 | oprom[2] << 8 | oprom[3];
+
+ x = md & 0017777;
+ switch (md >> 13)
+ {
+ case 0:
+ sprintf (buffer, "sto 0%05o", x);
+ break;
+ case 1:
+ sprintf (buffer, "stx 0%05o", x);
+ break;
+ case 2:
+ sprintf (buffer, "sxa 0%05o", x);
+ break;
+ case 3:
+ sprintf (buffer, "ado 0%05o", x);
+ break;
+ case 4:
+ sprintf (buffer, "slr 0%05o", x);
+ break;
+ case 5:
+ sprintf (buffer, "slx 0%05o", x);
+ break;
+ case 6:
+ sprintf (buffer, "stz 0%05o", x);
+ break;
+ case 8:
+ sprintf (buffer, "add 0%05o", x);
+ break;
+ case 9:
+ sprintf (buffer, "adx 0%05o", x);
+ break;
+ case 10:
+ sprintf (buffer, "ldx 0%05o", x);
+ break;
+ case 11:
+ sprintf (buffer, "aux 0%05o", x);
+ break;
+ case 12:
+ sprintf (buffer, "llr 0%05o", x);
+ break;
+ case 13:
+ sprintf (buffer, "llx 0%05o", x);
+ break;
+ case 14:
+ sprintf (buffer, "lda 0%05o", x);
+ break;
+ case 15:
+ sprintf (buffer, "lax 0%05o", x);
+ break;
+ case 16:
+ sprintf (buffer, "trn 0%05o", x);
+ break;
+ case 17:
+ sprintf (buffer, "tze 0%05o", x);
+ break;
+ case 18:
+ sprintf (buffer, "tsx 0%05o", x);
+ break;
+ case 19:
+ sprintf (buffer, "tix 0%05o", x);
+ break;
+ case 20:
+ sprintf (buffer, "tra 0%05o", x);
+ break;
+ case 21:
+ sprintf (buffer, "trx 0%05o", x);
+ break;
+ case 22:
+ sprintf (buffer, "tlv 0%05o", x);
+ break;
+ case 24:
+ case 25:
+ case 26:
+ case 27:
+ case 28:
+ case 29:
+ case 30:
+ case 31:
+ sprintf (buffer, "opr 0%06o", md & 0177777);
+ break;
+ default:
+ sprintf (buffer, "illegal");
+ break;
+ }
+ return 1;
+}
diff --git a/trunk/src/emu/cpu/pic16c5x/16c5xdsm.c b/trunk/src/emu/cpu/pic16c5x/16c5xdsm.c
new file mode 100644
index 00000000000..3b2f997f42d
--- /dev/null
+++ b/trunk/src/emu/cpu/pic16c5x/16c5xdsm.c
@@ -0,0 +1,254 @@
+ /**************************************************************************\
+ * Microchip PIC16C5x Emulator *
+ * *
+ * Copyright Tony La Porta *
+ * Originally written for the MAME project. *
+ * *
+ * *
+ * Addressing architecture is based on the Harvard addressing scheme. *
+ * *
+ * Many thanks to those involved in the i8039 Disassembler *
+ * as this was based on it. *
+ * *
+ * *
+ * *
+ * A Address to jump to. *
+ * B Bit address within an 8-bit file register. *
+ * D Destination select (0 = store result in W (accumulator)) *
+ * (1 = store result in file register) *
+ * F Register file address (00-1F). *
+ * K Literal field, constant data. *
+ * *
+ \**************************************************************************/
+
+#include "emu.h"
+#include <ctype.h>
+
+static const UINT8 *rombase;
+static const UINT8 *rambase;
+static offs_t pcbase;
+#define READOP16(A) (rombase[(A) - pcbase] | (rombase[(A) + 1 - pcbase] << 8))
+#define READARG16(A) (rambase[(A) - pcbase] | (rambase[(A) + 1 - pcbase] << 8))
+
+
+
+typedef unsigned char byte;
+typedef unsigned short int word;
+
+#define FMT(a,b) a, b
+#define PTRS_PER_FORMAT 2
+
+static const char *const regfile[32] = { "Reg$00 (IND)", "Reg$01 (TMR)", "Reg$02 (PCL)", "Reg$03 (ST)", "Reg$04 (FSR)", "Reg$05 (PTA)", "Reg$06 (PTB)", "Reg$07 (PTC)",
+ "Reg$08", "Reg$09", "Reg$0A", "Reg$0B", "Reg$0C", "Reg$0D", "Reg$0E", "Reg$0F",
+ "Reg$10", "Reg$11", "Reg$12", "Reg$13", "Reg$14", "Reg$15", "Reg$16", "Reg$17",
+ "Reg$18", "Reg$19", "Reg$1A", "Reg$1B", "Reg$1C", "Reg$1D", "Reg$1E", "Reg$1F" };
+
+static const char *const dest[2] = { "W", "Reg" };
+
+static const char *const PIC16C5xFormats[] = {
+ FMT("000000000000", "nop"),
+ FMT("000000000010", "option"),
+ FMT("000000000011", "sleep"),
+ FMT("000000000100", "clrwdt"),
+ FMT("000000000101", "tris Port A"),
+ FMT("000000000110", "tris Port B"),
+ FMT("000000000111", "tris Port C"),
+ FMT("0000001fffff", "movwf %F"),
+ FMT("000001000000", "clrw"),
+ FMT("0000011fffff", "clrf %F"),
+ FMT("000010dfffff", "subwf %F,%D"),
+ FMT("000011dfffff", "decf %F,%D"),
+ FMT("000100dfffff", "iorwf %F,%D"),
+ FMT("000101dfffff", "andwf %F,%D"),
+ FMT("000110dfffff", "xorwf %F,%D"),
+ FMT("000111dfffff", "addwf %F,%D"),
+ FMT("001000dfffff", "movf %F,%D"),
+ FMT("001001dfffff", "comf %F,%D"),
+ FMT("001010dfffff", "incf %F,%D"),
+ FMT("001011dfffff", "decfsz %F,%D"),
+ FMT("001100dfffff", "rrf %F,%D"),
+ FMT("001101dfffff", "rlf %F,%D"),
+ FMT("001110dfffff", "swapf %F,%D"),
+ FMT("001111dfffff", "incfsz %F,%D"),
+ FMT("0100bbbfffff", "bcf %F,%B"),
+ FMT("0101bbbfffff", "bsf %F,%B"),
+ FMT("0110bbbfffff", "btfsc %F,%B"),
+ FMT("0111bbbfffff", "btfss %F,%B"),
+ FMT("1000kkkkkkkk", "retlw %K"),
+ FMT("1001aaaaaaaa", "call %A"),
+ FMT("101aaaaaaaaa", "goto %A"),
+ FMT("1100kkkkkkkk", "movlw %K"),
+ FMT("1101kkkkkkkk", "iorlw %K"),
+ FMT("1110kkkkkkkk", "andlw %K"),
+ FMT("1111kkkkkkkk", "xorlw %K"),
+ NULL
+};
+
+#define MAX_OPS (((sizeof(PIC16C5xFormats) / sizeof(PIC16C5xFormats[0])) - 1) / PTRS_PER_FORMAT)
+
+typedef struct opcode {
+ word mask; /* instruction mask */
+ word bits; /* constant bits */
+ word extcode; /* value that gets extension code */
+ const char *parse; /* how to parse bits */
+ const char *fmt; /* instruction format */
+} PIC16C5xOpcode;
+
+static PIC16C5xOpcode Op[MAX_OPS+1];
+static int OpInizialized = 0;
+
+static void InitDasm16C5x(void)
+{
+ const char *p;
+ const char *const *ops;
+ word mask, bits;
+ int bit;
+ int i;
+
+ ops = PIC16C5xFormats; i = 0;
+ while (*ops)
+ {
+ p = *ops;
+ mask = 0; bits = 0; bit = 11;
+ while (*p && bit >= 0)
+ {
+ switch (*p++)
+ {
+ case '1': mask |= 1<<bit; bits |= 1<<bit; bit--; break;
+ case '0': mask |= 1<<bit; bit--; break;
+ case ' ': break;
+ case 'a':
+ case 'b':
+ case 'd':
+ case 'f':
+ case 'k':
+ bit --;
+ break;
+ default: fatalerror("Invalid instruction encoding '%s %s'",
+ ops[0],ops[1]);
+ }
+ }
+ if (bit != -1 )
+ {
+ fatalerror("not enough bits in encoding '%s %s' %d",
+ ops[0],ops[1],bit);
+ }
+ while (isspace((UINT8)*p)) p++;
+ if (*p) Op[i].extcode = *p;
+ Op[i].bits = bits;
+ Op[i].mask = mask;
+ Op[i].fmt = ops[1];
+ Op[i].parse = ops[0];
+
+ ops += PTRS_PER_FORMAT;
+ i++;
+ }
+
+ OpInizialized = 1;
+}
+
+CPU_DISASSEMBLE( pic16c5x )
+{
+ int a, b, d, f, k; /* these can all be filled in by parsing an instruction */
+ int i;
+ int op;
+ int cnt = 1;
+ int code;
+ int bit;
+ //char *buffertmp;
+ const char *cp; /* character pointer in OpFormats */
+ UINT32 flags = 0;
+
+ rombase = oprom;
+ rambase = opram;
+ pcbase = 2*pc;
+
+ if (!OpInizialized) InitDasm16C5x();
+
+ op = -1; /* no matching opcode */
+ code = READOP16(2*pc);
+ for ( i = 0; i < MAX_OPS; i++)
+ {
+ if ((code & Op[i].mask) == Op[i].bits)
+ {
+ if (op != -1)
+ {
+ mame_printf_debug("Error: opcode %04Xh matches %d (%s) and %d (%s)\n",
+ code,i,Op[i].fmt,op,Op[op].fmt);
+ }
+ op = i;
+ }
+ }
+ if (op == -1)
+ {
+ sprintf(buffer,"???? dw %04Xh",code);
+ return cnt;
+ }
+ //buffertmp = buffer;
+ if (Op[op].extcode) /* Actually, theres no double length opcodes */
+ {
+ bit = 27;
+ code <<= 16;
+ code |= READARG16(2*(pc+cnt));
+ cnt++;
+ }
+ else
+ {
+ bit = 11;
+ }
+
+ /* shift out operands */
+ cp = Op[op].parse;
+ a = b = d = f = k = 0;
+
+ while (bit >= 0)
+ {
+ /* mame_printf_debug("{%c/%d}",*cp,bit); */
+ switch(*cp)
+ {
+ case 'a': a <<=1; a |= ((code & (1<<bit)) ? 1 : 0); bit--; break;
+ case 'b': b <<=1; b |= ((code & (1<<bit)) ? 1 : 0); bit--; break;
+ case 'd': d <<=1; d |= ((code & (1<<bit)) ? 1 : 0); bit--; break;
+ case 'f': f <<=1; f |= ((code & (1<<bit)) ? 1 : 0); bit--; break;
+ case 'k': k <<=1; k |= ((code & (1<<bit)) ? 1 : 0); bit--; break;
+ case ' ': break;
+ case '1': case '0': bit--; break;
+ case '\0': fatalerror("premature end of parse string, opcode %x, bit = %d",code,bit);
+ }
+ cp++;
+ }
+
+ /* now traverse format string */
+ cp = Op[op].fmt;
+ if (!strncmp(cp, "call", 4))
+ flags = DASMFLAG_STEP_OVER;
+ else if (!strncmp(cp, "ret", 3))
+ flags = DASMFLAG_STEP_OUT;
+
+ while (*cp)
+ {
+ if (*cp == '%')
+ {
+ char num[30], *q;
+ cp++;
+ switch (*cp++)
+ {
+ case 'A': sprintf(num,"$%03X",a); break;
+ case 'B': sprintf(num,"%d",b); break;
+ case 'D': sprintf(num,"%s",dest[d]); break;
+ case 'F': sprintf(num,"%s",regfile[f]); break;
+ case 'K': sprintf(num,"%02Xh",k); break;
+ default:
+ fatalerror("illegal escape character in format '%s'",Op[op].fmt);
+ }
+ q = num; while (*q) *buffer++ = *q++;
+ *buffer = '\0';
+ }
+ else
+ {
+ *buffer++ = *cp++;
+ *buffer = '\0';
+ }
+ }
+ return cnt | flags | DASMFLAG_SUPPORTED;
+}
diff --git a/trunk/src/emu/cpu/pic16c5x/dis16c5x.c b/trunk/src/emu/cpu/pic16c5x/dis16c5x.c
new file mode 100644
index 00000000000..d7e898f74c5
--- /dev/null
+++ b/trunk/src/emu/cpu/pic16c5x/dis16c5x.c
@@ -0,0 +1,134 @@
+ /**************************************************************************\
+ * Microchip PIC16C5x Emulator *
+ * *
+ * Copyright Tony La Porta *
+ * Originally written for the MAME project. *
+ * *
+ * *
+ * Notes : Data is expected to be read from source file as LSB first. *
+ * *
+ \**************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+
+#include "16c5xdsm.c"
+
+
+unsigned char *Buffer;
+
+
+int main(int argc,char *argv[])
+{
+ int length=0, length_to_dump=0, offset=0, disasm_words=0;
+ int filelength=0, bytes_read;
+ int Counter=0;
+
+ FILE *F;
+ char *String_Output;
+
+ if(argc<2)
+ {
+ printf("\n");
+ printf("PIC16C5x Disassembler 1.0 by Tony La Porta (C)2003+\n\n");
+ printf("Usage: dis16c5x <input-file> [ <start-addr> [ <num-of-addr> ] ]\n");
+ printf(" <input-file> source file data must be MSB first\n");
+ printf(" <start-addr> starting address to disassemble from (decimal)\n");
+ printf(" <num-of-addr> number of addresses to disassemble (decimal)\n");
+ printf(" Precede values with 0x if HEX values preffered\n");
+ exit(1);
+ }
+
+ if(!(F=fopen(argv[1],"rb")))
+ {
+ printf("\n%s: Can't open file %s\n",argv[0],argv[1]);
+ exit(2);
+ }
+ argv++; argc--;
+ if (argv[1])
+ {
+ offset = strtol(argv[1],NULL,0);
+ argv++; argc--;
+ }
+ if (argv[1])
+ {
+ length = strtol(argv[1],NULL,0);
+ argv++; argc--;
+ }
+
+ fseek(F,0, SEEK_END);
+ filelength = ftell(F);
+
+ length *= 2;
+
+ if ((length > (filelength - (offset*2))) || (length == 0)) length = filelength - (offset*2);
+ printf("Length=%04Xh(words) Offset=$%04Xh filelength=%04Xh(words) %04Xh(bytes)\n",length/2,offset,filelength/2,filelength);
+ length_to_dump = length;
+ printf("Starting from %d, dumping %d opcodes (word size)\n",offset,length/2);
+ Buffer = calloc((filelength+1),sizeof(char));
+ if (Buffer==NULL)
+ {
+ printf("Out of Memory !!!");
+ fclose(F);
+ exit(3);
+ }
+ String_Output = calloc(80,sizeof(char));
+ if (String_Output==NULL)
+ {
+ printf("Out of Memory !!!");
+ free(Buffer);
+ fclose(F);
+ exit(4);
+ }
+
+ if (fseek(F,0,SEEK_SET) != 0)
+ {
+ printf("Error seeking to beginning of file\n");
+ free(String_Output);
+ free(Buffer);
+ fclose(F);
+ exit(5);
+ }
+
+ Counter = offset;
+ bytes_read = fread(Buffer,sizeof(char),filelength,F);
+ if (bytes_read >= length)
+ {
+ for (; length > 0; length -= (disasm_words*2))
+ {
+ int ii;
+ disasm_words = Dasm16C5x(String_Output,Counter);
+ printf("$%03X: ",Counter);
+ for (ii = 0; ii < disasm_words; ii++)
+ {
+ if (((Counter*2) + ii) > filelength) /* Past end of length to dump ? */
+ {
+ sprintf(String_Output,"???? dw %02.2X%02.2Xh (Past end of disassembly !)",Buffer[((Counter-1)*2)+1],Buffer[((Counter-1)*2)]);
+ }
+ else
+ {
+ printf("%02.2x%02.2x ",Buffer[(Counter*2)+1],Buffer[(Counter*2)]);
+ }
+ Counter++ ;
+ }
+ for (; ii < 4; ii++)
+ {
+ printf(" ");
+ }
+ printf("\t%s\n",String_Output);
+ }
+ }
+ else
+ {
+ printf("ERROR length to dump was %d ", length_to_dump/2);
+ printf(", but bytes read from file were %d\n", bytes_read/2);
+ free(String_Output);
+ free(Buffer);
+ fclose(F);
+ exit(7);
+ }
+ free(String_Output);
+ free(Buffer);
+ fclose(F);
+ return(0);
+}
diff --git a/trunk/src/emu/cpu/pic16c5x/pic16c5x.c b/trunk/src/emu/cpu/pic16c5x/pic16c5x.c
new file mode 100644
index 00000000000..8ca1fe08f6b
--- /dev/null
+++ b/trunk/src/emu/cpu/pic16c5x/pic16c5x.c
@@ -0,0 +1,1393 @@
+ /**************************************************************************\
+ * Microchip PIC16C5x Emulator *
+ * *
+ * Copyright Tony La Porta *
+ * Originally written for the MAME project. *
+ * *
+ * *
+ * Addressing architecture is based on the Harvard addressing scheme. *
+ * *
+ * *
+ * **** Change Log **** *
+ * TLP (06-Apr-2003) *
+ * - First Public release. *
+ * BO (07-Apr-2003) Ver 1.01 *
+ * - Renamed 'sleep' function to 'sleepic' to avoid C conflicts. *
+ * TLP (09-Apr-2003) Ver 1.10 *
+ * - Fixed modification of file register $03 (Status). *
+ * - Corrected support for 7FFh (12-bit) size ROMs. *
+ * - The 'call' and 'goto' instructions weren't correctly handling the *
+ * STATUS page info correctly. *
+ * - The FSR register was incorrectly oring the data with 0xe0 when read. *
+ * - Prescaler masking information was set to 3 instead of 7. *
+ * - Prescaler assign bit was set to 4 instead of 8. *
+ * - Timer source and edge select flags/masks were wrong. *
+ * - Corrected the memory bank selection in GET/SET_REGFILE and also the *
+ * indirect register addressing. *
+ * BMP (18-May-2003) Ver 1.11 *
+ * - pic16c5x_get_reg functions were missing 'returns'. *
+ * TLP (27-May-2003) Ver 1.12 *
+ * - Fixed the WatchDog timer count. *
+ * - The Prescaler rate was incorrectly being zeroed, instead of the *
+ * actual Prescaler counter in the CLRWDT and SLEEP instructions. *
+ * - Added masking to the FSR register. Upper unused bits are always 1. *
+ * TLP (27-Aug-2009) Ver 1.13 *
+ * - Indirect addressing was not taking into account special purpose *
+ * memory mapped locations. *
+ * - 'iorlw' instruction was saving the result to memory instead of *
+ * the W register. *
+ * - 'tris' instruction no longer modifies Port-C on PIC models that *
+ * do not have Port-C implemented. *
+ * TLP (07-Sep-2009) Ver 1.14 *
+ * - Edge sense control for the T0 count input was incorrectly reversed *
+ * *
+ * *
+ * **** Notes: **** *
+ * PIC WatchDog Timer has a separate internal clock. For the moment, we're *
+ * basing the count on a 4MHz input clock, since 4MHz is the typical *
+ * input frequency (but by no means always). *
+ * A single scaler is available for the Counter/Timer or WatchDog Timer. *
+ * When connected to the Counter/Timer, it functions as a Prescaler, *
+ * hence prescale overflows, tick the Counter/Timer. *
+ * When connected to the WatchDog Timer, it functions as a Postscaler *
+ * hence WatchDog Timer overflows, tick the Postscaler. This scenario *
+ * means that the WatchDog timeout occurs when the Postscaler has *
+ * reached the scaler rate value, not when the WatchDog reaches zero. *
+ * CLRWDT should prevent the WatchDog Timer from timing out and generating *
+ * a device reset, but how is not known. The manual also mentions that *
+ * the WatchDog Timer can only be disabled during ROM programming, and *
+ * no other means seem to exist??? *
+ * *
+ \**************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "pic16c5x.h"
+
+
+
+
+typedef struct _pic16c5x_state pic16c5x_state;
+struct _pic16c5x_state
+{
+ /******************** CPU Internal Registers *******************/
+ UINT16 PC;
+ UINT16 PREVPC; /* previous program counter */
+ UINT8 W;
+ UINT8 OPTION;
+ UINT16 CONFIG;
+ UINT8 ALU;
+ UINT16 WDT;
+ UINT8 TRISA;
+ UINT8 TRISB;
+ UINT8 TRISC;
+ UINT16 STACK[2];
+ UINT16 prescaler; /* Note: this is really an 8-bit register */
+ PAIR opcode;
+ UINT8 *internalram;
+
+ int icount;
+ int reset_vector;
+ int picmodel;
+ int delay_timer;
+ UINT16 temp_config;
+ UINT8 old_T0;
+ INT8 old_data;
+ UINT8 picRAMmask;
+ int inst_cycles;
+
+
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ address_space *data;
+ address_space *io;
+};
+
+INLINE pic16c5x_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == PIC16C54 ||
+ device->type() == PIC16C55 ||
+ device->type() == PIC16C56 ||
+ device->type() == PIC16C57 ||
+ device->type() == PIC16C58);
+ return (pic16c5x_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+
+/* opcode table entry */
+typedef struct _pic16c5x_opcode pic16c5x_opcode;
+struct _pic16c5x_opcode
+{
+ UINT8 cycles;
+ void (*function)(pic16c5x_state *);
+};
+
+
+INLINE void update_internalram_ptr(pic16c5x_state *cpustate)
+{
+ cpustate->internalram = (UINT8 *)cpustate->data->get_write_ptr(0x00);
+}
+
+
+
+
+#define PIC16C5x_RDOP(A) (cpustate->direct->read_decrypted_word((A)<<1))
+#define PIC16C5x_RAM_RDMEM(A) ((UINT8)cpustate->data->read_byte(A))
+#define PIC16C5x_RAM_WRMEM(A,V) (cpustate->data->write_byte(A,V))
+#define PIC16C5x_In(Port) ((UINT8)cpustate->io->read_byte((Port)))
+#define PIC16C5x_Out(Port,Value) (cpustate->io->write_byte((Port),Value))
+/************ Read the state of the T0 Clock input signal ************/
+#define PIC16C5x_T0_In (cpustate->io->read_byte(PIC16C5x_T0))
+
+#define M_RDRAM(A) (((A) < 8) ? cpustate->internalram[A] : PIC16C5x_RAM_RDMEM(A))
+#define M_WRTRAM(A,V) do { if ((A) < 8) cpustate->internalram[A] = (V); else PIC16C5x_RAM_WRMEM(A,V); } while (0)
+#define M_RDOP(A) PIC16C5x_RDOP(A)
+#define P_IN(A) PIC16C5x_In(A)
+#define P_OUT(A,V) PIC16C5x_Out(A,V)
+#define S_T0_IN PIC16C5x_T0_In
+#define ADDR_MASK 0x7ff
+
+
+
+#define TMR0 internalram[1]
+#define PCL internalram[2]
+#define STATUS internalram[3]
+#define FSR internalram[4]
+#define PORTA internalram[5]
+#define PORTB internalram[6]
+#define PORTC internalram[7]
+#define INDF M_RDRAM(cpustate->FSR)
+
+#define ADDR (cpustate->opcode.b.l & 0x1f)
+
+#define RISING_EDGE_T0 (( (int)(T0_in - cpustate->old_T0) > 0) ? 1 : 0)
+#define FALLING_EDGE_T0 (( (int)(T0_in - cpustate->old_T0) < 0) ? 1 : 0)
+
+
+/******** The following is the Status Flag register definition. *********/
+ /* | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | */
+ /* | PA | TO | PD | Z | DC | C | */
+#define PA_REG 0xe0 /* PA Program Page Preselect - bit 8 is unused here */
+#define TO_FLAG 0x10 /* TO Time Out flag (WatchDog) */
+#define PD_FLAG 0x08 /* PD Power Down flag */
+#define Z_FLAG 0x04 /* Z Zero Flag */
+#define DC_FLAG 0x02 /* DC Digit Carry/Borrow flag (Nibble) */
+#define C_FLAG 0x01 /* C Carry/Borrow Flag (Byte) */
+
+#define PA (cpustate->STATUS & PA_REG)
+#define TO (cpustate->STATUS & TO_FLAG)
+#define PD (cpustate->STATUS & PD_FLAG)
+#define ZERO (cpustate->STATUS & Z_FLAG)
+#define DC (cpustate->STATUS & DC_FLAG)
+#define CARRY (cpustate->STATUS & C_FLAG)
+
+
+/******** The following is the Option Flag register definition. *********/
+ /* | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | */
+ /* | 0 | 0 | TOCS | TOSE | PSA | PS | */
+#define T0CS_FLAG 0x20 /* TOCS Timer 0 clock source select */
+#define T0SE_FLAG 0x10 /* TOSE Timer 0 clock source edge select */
+#define PSA_FLAG 0x08 /* PSA Prescaler Assignment bit */
+#define PS_REG 0x07 /* PS Prescaler Rate select */
+
+#define T0CS (cpustate->OPTION & T0CS_FLAG)
+#define T0SE (cpustate->OPTION & T0SE_FLAG)
+#define PSA (cpustate->OPTION & PSA_FLAG)
+#define PS (cpustate->OPTION & PS_REG)
+
+
+/******** The following is the Config Flag register definition. *********/
+ /* | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | */
+ /* | CP | WDTE | FOSC | */
+ /* CP Code Protect (ROM read protect) */
+#define WDTE_FLAG 0x04 /* WDTE WatchDog Timer enable */
+#define FOSC_FLAG 0x03 /* FOSC Oscillator source select */
+
+#define WDTE (cpustate->CONFIG & WDTE_FLAG)
+#define FOSC (cpustate->CONFIG & FOSC_FLAG)
+
+
+/************************************************************************
+ * Shortcuts
+ ************************************************************************/
+
+#define CLR(flagreg, flag) ( flagreg &= (UINT8)(~flag) )
+#define SET(flagreg, flag) ( flagreg |= flag )
+
+
+/* Easy bit position selectors */
+#define POS ((cpustate->opcode.b.l >> 5) & 7)
+static const unsigned int bit_clr[8] = { 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f };
+static const unsigned int bit_set[8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
+
+
+
+INLINE void CALCULATE_Z_FLAG(pic16c5x_state *cpustate)
+{
+ if (cpustate->ALU == 0) SET(cpustate->STATUS, Z_FLAG);
+ else CLR(cpustate->STATUS, Z_FLAG);
+}
+
+INLINE void CALCULATE_ADD_CARRY(pic16c5x_state *cpustate)
+{
+ if ((UINT8)(cpustate->old_data) > (UINT8)(cpustate->ALU)) {
+ SET(cpustate->STATUS, C_FLAG);
+ }
+ else {
+ CLR(cpustate->STATUS, C_FLAG);
+ }
+}
+
+INLINE void CALCULATE_ADD_DIGITCARRY(pic16c5x_state *cpustate)
+{
+ if (((UINT8)(cpustate->old_data) & 0x0f) > ((UINT8)(cpustate->ALU) & 0x0f)) {
+ SET(cpustate->STATUS, DC_FLAG);
+ }
+ else {
+ CLR(cpustate->STATUS, DC_FLAG);
+ }
+}
+
+INLINE void CALCULATE_SUB_CARRY(pic16c5x_state *cpustate)
+{
+ if ((UINT8)(cpustate->old_data) < (UINT8)(cpustate->ALU)) {
+ CLR(cpustate->STATUS, C_FLAG);
+ }
+ else {
+ SET(cpustate->STATUS, C_FLAG);
+ }
+}
+
+INLINE void CALCULATE_SUB_DIGITCARRY(pic16c5x_state *cpustate)
+{
+ if (((UINT8)(cpustate->old_data) & 0x0f) < ((UINT8)(cpustate->ALU) & 0x0f)) {
+ CLR(cpustate->STATUS, DC_FLAG);
+ }
+ else {
+ SET(cpustate->STATUS, DC_FLAG);
+ }
+}
+
+
+
+INLINE UINT16 POP_STACK(pic16c5x_state *cpustate)
+{
+ UINT16 data = cpustate->STACK[1];
+ cpustate->STACK[1] = cpustate->STACK[0];
+ return (data & ADDR_MASK);
+}
+INLINE void PUSH_STACK(pic16c5x_state *cpustate, UINT16 data)
+{
+ cpustate->STACK[0] = cpustate->STACK[1];
+ cpustate->STACK[1] = (data & ADDR_MASK);
+}
+
+
+
+INLINE UINT8 GET_REGFILE(pic16c5x_state *cpustate, offs_t addr) /* Read from internal memory */
+{
+ UINT8 data;
+
+ if (addr == 0) { /* Indirect addressing */
+ addr = (cpustate->FSR & cpustate->picRAMmask);
+ }
+
+ if ((cpustate->picmodel == 0x16C57) || (cpustate->picmodel == 0x16C58)) {
+ addr |= (cpustate->FSR & 0x60); /* FSR bits 6-5 are used for banking in direct mode */
+ }
+
+ if ((addr & 0x10) == 0) addr &= 0x0f;
+
+ switch(addr)
+ {
+ case 00: /* Not an actual register, so return 0 */
+ data = 0;
+ break;
+ case 04: data = (cpustate->FSR | (UINT8)(~cpustate->picRAMmask));
+ break;
+ case 05: data = P_IN(0);
+ data &= cpustate->TRISA;
+ data |= ((UINT8)(~cpustate->TRISA) & cpustate->PORTA);
+ data &= 0x0f; /* 4-bit port (only lower 4 bits used) */
+ break;
+ case 06: data = P_IN(1);
+ data &= cpustate->TRISB;
+ data |= ((UINT8)(~cpustate->TRISB) & cpustate->PORTB);
+ break;
+ case 07: if ((cpustate->picmodel == 0x16C55) || (cpustate->picmodel == 0x16C57)) {
+ data = P_IN(2);
+ data &= cpustate->TRISC;
+ data |= ((UINT8)(~cpustate->TRISC) & cpustate->PORTC);
+ }
+ else { /* PIC16C54, PIC16C56, PIC16C58 */
+ data = M_RDRAM(addr);
+ }
+ break;
+ default: data = M_RDRAM(addr);
+ break;
+ }
+ return data;
+}
+
+INLINE void STORE_REGFILE(pic16c5x_state *cpustate, offs_t addr, UINT8 data) /* Write to internal memory */
+{
+ if (addr == 0) { /* Indirect addressing */
+ addr = (cpustate->FSR & cpustate->picRAMmask);
+ }
+
+ if ((cpustate->picmodel == 0x16C57) || (cpustate->picmodel == 0x16C58)) {
+ addr |= (cpustate->FSR & 0x60); /* FSR bits 6-5 are used for banking in direct mode */
+ }
+
+ if ((addr & 0x10) == 0) addr &= 0x0f;
+
+ switch(addr)
+ {
+ case 00: /* Not an actual register, nothing to save */
+ break;
+ case 01: cpustate->delay_timer = 2; /* Timer starts after next two instructions */
+ if (PSA == 0) cpustate->prescaler = 0; /* Must clear the Prescaler */
+ cpustate->TMR0 = data;
+ break;
+ case 02: cpustate->PCL = data;
+ cpustate->PC = ((cpustate->STATUS & PA_REG) << 4) | data;
+ break;
+ case 03: cpustate->STATUS &= (UINT8)(~PA_REG); cpustate->STATUS |= (data & PA_REG);
+ break;
+ case 04: cpustate->FSR = (data | (UINT8)(~cpustate->picRAMmask));
+ break;
+ case 05: data &= 0x0f; /* 4-bit port (only lower 4 bits used) */
+ P_OUT(0,data & (UINT8)(~cpustate->TRISA)); cpustate->PORTA = data;
+ break;
+ case 06: P_OUT(1,data & (UINT8)(~cpustate->TRISB)); cpustate->PORTB = data;
+ break;
+ case 07: if ((cpustate->picmodel == 0x16C55) || (cpustate->picmodel == 0x16C57)) {
+ P_OUT(2,data & (UINT8)(~cpustate->TRISC));
+ cpustate->PORTC = data;
+ }
+ else { /* PIC16C54, PIC16C56, PIC16C58 */
+ M_WRTRAM(addr, data);
+ }
+ break;
+ default: M_WRTRAM(addr, data);
+ break;
+ }
+}
+
+
+INLINE void STORE_RESULT(pic16c5x_state *cpustate, offs_t addr, UINT8 data)
+{
+ if (cpustate->opcode.b.l & 0x20)
+ {
+ STORE_REGFILE(cpustate, addr, data);
+ }
+ else
+ {
+ cpustate->W = data;
+ }
+}
+
+
+/************************************************************************
+ * Emulate the Instructions
+ ************************************************************************/
+
+/* This following function is here to fill in the void for */
+/* the opcode call function. This function is never called. */
+
+
+static void illegal(pic16c5x_state *cpustate)
+{
+ logerror("PIC16C5x: PC=%03x, Illegal opcode = %04x\n", (cpustate->PC-1), cpustate->opcode.w.l);
+}
+
+
+static void addwf(pic16c5x_state *cpustate)
+{
+ cpustate->old_data = GET_REGFILE(cpustate, ADDR);
+ cpustate->ALU = cpustate->old_data + cpustate->W;
+ STORE_RESULT(cpustate, ADDR, cpustate->ALU);
+ CALCULATE_Z_FLAG(cpustate);
+ CALCULATE_ADD_CARRY(cpustate);
+ CALCULATE_ADD_DIGITCARRY(cpustate);
+}
+
+static void andwf(pic16c5x_state *cpustate)
+{
+ cpustate->ALU = GET_REGFILE(cpustate, ADDR) & cpustate->W;
+ STORE_RESULT(cpustate, ADDR, cpustate->ALU);
+ CALCULATE_Z_FLAG(cpustate);
+}
+
+static void andlw(pic16c5x_state *cpustate)
+{
+ cpustate->ALU = cpustate->opcode.b.l & cpustate->W;
+ cpustate->W = cpustate->ALU;
+ CALCULATE_Z_FLAG(cpustate);
+}
+
+static void bcf(pic16c5x_state *cpustate)
+{
+ cpustate->ALU = GET_REGFILE(cpustate, ADDR);
+ cpustate->ALU &= bit_clr[POS];
+ STORE_REGFILE(cpustate, ADDR, cpustate->ALU);
+}
+
+static void bsf(pic16c5x_state *cpustate)
+{
+ cpustate->ALU = GET_REGFILE(cpustate, ADDR);
+ cpustate->ALU |= bit_set[POS];
+ STORE_REGFILE(cpustate, ADDR, cpustate->ALU);
+}
+
+static void btfss(pic16c5x_state *cpustate)
+{
+ if ((GET_REGFILE(cpustate, ADDR) & bit_set[POS]) == bit_set[POS])
+ {
+ cpustate->PC++ ;
+ cpustate->PCL = cpustate->PC & 0xff;
+ cpustate->inst_cycles += 1; /* Add NOP cycles */
+ }
+}
+
+static void btfsc(pic16c5x_state *cpustate)
+{
+ if ((GET_REGFILE(cpustate, ADDR) & bit_set[POS]) == 0)
+ {
+ cpustate->PC++ ;
+ cpustate->PCL = cpustate->PC & 0xff;
+ cpustate->inst_cycles += 1; /* Add NOP cycles */
+ }
+}
+
+static void call(pic16c5x_state *cpustate)
+{
+ PUSH_STACK(cpustate, cpustate->PC);
+ cpustate->PC = ((cpustate->STATUS & PA_REG) << 4) | cpustate->opcode.b.l;
+ cpustate->PC &= 0x6ff;
+ cpustate->PCL = cpustate->PC & 0xff;
+}
+
+static void clrw(pic16c5x_state *cpustate)
+{
+ cpustate->W = 0;
+ SET(cpustate->STATUS, Z_FLAG);
+}
+
+static void clrf(pic16c5x_state *cpustate)
+{
+ STORE_REGFILE(cpustate, ADDR, 0);
+ SET(cpustate->STATUS, Z_FLAG);
+}
+
+static void clrwdt(pic16c5x_state *cpustate)
+{
+ cpustate->WDT = 0;
+ if (PSA) cpustate->prescaler = 0;
+ SET(cpustate->STATUS, TO_FLAG);
+ SET(cpustate->STATUS, PD_FLAG);
+}
+
+static void comf(pic16c5x_state *cpustate)
+{
+ cpustate->ALU = (UINT8)(~(GET_REGFILE(cpustate, ADDR)));
+ STORE_RESULT(cpustate, ADDR, cpustate->ALU);
+ CALCULATE_Z_FLAG(cpustate);
+}
+
+static void decf(pic16c5x_state *cpustate)
+{
+ cpustate->ALU = GET_REGFILE(cpustate, ADDR) - 1;
+ STORE_RESULT(cpustate, ADDR, cpustate->ALU);
+ CALCULATE_Z_FLAG(cpustate);
+}
+
+static void decfsz(pic16c5x_state *cpustate)
+{
+ cpustate->ALU = GET_REGFILE(cpustate, ADDR) - 1;
+ STORE_RESULT(cpustate, ADDR, cpustate->ALU);
+ if (cpustate->ALU == 0)
+ {
+ cpustate->PC++ ;
+ cpustate->PCL = cpustate->PC & 0xff;
+ cpustate->inst_cycles += 1; /* Add NOP cycles */
+ }
+}
+
+static void goto_op(pic16c5x_state *cpustate)
+{
+ cpustate->PC = ((cpustate->STATUS & PA_REG) << 4) | (cpustate->opcode.w.l & 0x1ff);
+ cpustate->PC &= ADDR_MASK;
+ cpustate->PCL = cpustate->PC & 0xff;
+}
+
+static void incf(pic16c5x_state *cpustate)
+{
+ cpustate->ALU = GET_REGFILE(cpustate, ADDR) + 1;
+ STORE_RESULT(cpustate, ADDR, cpustate->ALU);
+ CALCULATE_Z_FLAG(cpustate);
+}
+
+static void incfsz(pic16c5x_state *cpustate)
+{
+ cpustate->ALU = GET_REGFILE(cpustate, ADDR) + 1;
+ STORE_RESULT(cpustate, ADDR, cpustate->ALU);
+ if (cpustate->ALU == 0)
+ {
+ cpustate->PC++ ;
+ cpustate->PCL = cpustate->PC & 0xff;
+ cpustate->inst_cycles += 1; /* Add NOP cycles */
+ }
+}
+
+static void iorlw(pic16c5x_state *cpustate)
+{
+ cpustate->ALU = cpustate->opcode.b.l | cpustate->W;
+ cpustate->W = cpustate->ALU;
+ CALCULATE_Z_FLAG(cpustate);
+}
+
+static void iorwf(pic16c5x_state *cpustate)
+{
+ cpustate->ALU = GET_REGFILE(cpustate, ADDR) | cpustate->W;
+ STORE_RESULT(cpustate, ADDR, cpustate->ALU);
+ CALCULATE_Z_FLAG(cpustate);
+}
+
+static void movf(pic16c5x_state *cpustate)
+{
+ cpustate->ALU = GET_REGFILE(cpustate, ADDR);
+ STORE_RESULT(cpustate, ADDR, cpustate->ALU);
+ CALCULATE_Z_FLAG(cpustate);
+}
+
+static void movlw(pic16c5x_state *cpustate)
+{
+ cpustate->W = cpustate->opcode.b.l;
+}
+
+static void movwf(pic16c5x_state *cpustate)
+{
+ STORE_REGFILE(cpustate, ADDR, cpustate->W);
+}
+
+static void nop(pic16c5x_state *cpustate)
+{
+ /* Do nothing */
+}
+
+static void option(pic16c5x_state *cpustate)
+{
+ cpustate->OPTION = cpustate->W & (T0CS_FLAG | T0SE_FLAG | PSA_FLAG | PS_REG);
+}
+
+static void retlw(pic16c5x_state *cpustate)
+{
+ cpustate->W = cpustate->opcode.b.l;
+ cpustate->PC = POP_STACK(cpustate);
+ cpustate->PCL = cpustate->PC & 0xff;
+}
+
+static void rlf(pic16c5x_state *cpustate)
+{
+ cpustate->ALU = GET_REGFILE(cpustate, ADDR);
+ cpustate->ALU <<= 1;
+ if (cpustate->STATUS & C_FLAG) cpustate->ALU |= 1;
+ if (GET_REGFILE(cpustate, ADDR) & 0x80) SET(cpustate->STATUS, C_FLAG);
+ else CLR(cpustate->STATUS, C_FLAG);
+ STORE_RESULT(cpustate, ADDR, cpustate->ALU);
+}
+
+static void rrf(pic16c5x_state *cpustate)
+{
+ cpustate->ALU = GET_REGFILE(cpustate, ADDR);
+ cpustate->ALU >>= 1;
+ if (cpustate->STATUS & C_FLAG) cpustate->ALU |= 0x80;
+ if (GET_REGFILE(cpustate, ADDR) & 1) SET(cpustate->STATUS, C_FLAG);
+ else CLR(cpustate->STATUS, C_FLAG);
+ STORE_RESULT(cpustate, ADDR, cpustate->ALU);
+}
+
+static void sleepic(pic16c5x_state *cpustate)
+{
+ if (WDTE) cpustate->WDT = 0;
+ if (PSA) cpustate->prescaler = 0;
+ SET(cpustate->STATUS, TO_FLAG);
+ CLR(cpustate->STATUS, PD_FLAG);
+}
+
+static void subwf(pic16c5x_state *cpustate)
+{
+ cpustate->old_data = GET_REGFILE(cpustate, ADDR);
+ cpustate->ALU = cpustate->old_data - cpustate->W;
+ STORE_RESULT(cpustate, ADDR, cpustate->ALU);
+ CALCULATE_Z_FLAG(cpustate);
+ CALCULATE_SUB_CARRY(cpustate);
+ CALCULATE_SUB_DIGITCARRY(cpustate);
+}
+
+static void swapf(pic16c5x_state *cpustate)
+{
+ cpustate->ALU = ((GET_REGFILE(cpustate, ADDR) << 4) & 0xf0);
+ cpustate->ALU |= ((GET_REGFILE(cpustate, ADDR) >> 4) & 0x0f);
+ STORE_RESULT(cpustate, ADDR, cpustate->ALU);
+}
+
+static void tris(pic16c5x_state *cpustate)
+{
+ switch(cpustate->opcode.b.l & 0x7)
+ {
+ case 05: if (cpustate->TRISA == cpustate->W) break;
+ else { cpustate->TRISA = cpustate->W | 0xf0; P_OUT(0,cpustate->PORTA & (UINT8)(~cpustate->TRISA) & 0x0f); break; }
+ case 06: if (cpustate->TRISB == cpustate->W) break;
+ else { cpustate->TRISB = cpustate->W; P_OUT(1,cpustate->PORTB & (UINT8)(~cpustate->TRISB)); break; }
+ case 07: if ((cpustate->picmodel == 0x16C55) || (cpustate->picmodel == 0x16C57)) {
+ if (cpustate->TRISC == cpustate->W) break;
+ else { cpustate->TRISC = cpustate->W; P_OUT(2,cpustate->PORTC & (UINT8)(~cpustate->TRISC)); break; }
+ }
+ else {
+ illegal(cpustate); break;
+ }
+ default: illegal(cpustate); break;
+ }
+}
+
+static void xorlw(pic16c5x_state *cpustate)
+{
+ cpustate->ALU = cpustate->W ^ cpustate->opcode.b.l;
+ cpustate->W = cpustate->ALU;
+ CALCULATE_Z_FLAG(cpustate);
+}
+
+static void xorwf(pic16c5x_state *cpustate)
+{
+ cpustate->ALU = GET_REGFILE(cpustate, ADDR) ^ cpustate->W;
+ STORE_RESULT(cpustate, ADDR, cpustate->ALU);
+ CALCULATE_Z_FLAG(cpustate);
+}
+
+
+
+
+/***********************************************************************
+ * Opcode Table (Cycles, Instruction)
+ ***********************************************************************/
+
+static const pic16c5x_opcode opcode_main[256]=
+{
+/*00*/ {1, nop },{0, illegal },{1, movwf },{1, movwf },{1, clrw },{0, illegal },{1, clrf },{1, clrf },
+/*08*/ {1, subwf },{1, subwf },{1, subwf },{1, subwf },{1, decf },{1, decf },{1, decf },{1, decf },
+/*10*/ {1, iorwf },{1, iorwf },{1, iorwf },{1, iorwf },{1, andwf },{1, andwf },{1, andwf },{1, andwf },
+/*18*/ {1, xorwf },{1, xorwf },{1, xorwf },{1, xorwf },{1, addwf },{1, addwf },{1, addwf },{1, addwf },
+/*20*/ {1, movf },{1, movf },{1, movf },{1, movf },{1, comf },{1, comf },{1, comf },{1, comf },
+/*28*/ {1, incf },{1, incf },{1, incf },{1, incf },{1, decfsz },{1, decfsz },{1, decfsz },{1, decfsz },
+/*30*/ {1, rrf },{1, rrf },{1, rrf },{1, rrf },{1, rlf },{1, rlf },{1, rlf },{1, rlf },
+/*38*/ {1, swapf },{1, swapf },{1, swapf },{1, swapf },{1, incfsz },{1, incfsz },{1, incfsz },{1, incfsz },
+/*40*/ {1, bcf },{1, bcf },{1, bcf },{1, bcf },{1, bcf },{1, bcf },{1, bcf },{1, bcf },
+/*48*/ {1, bcf },{1, bcf },{1, bcf },{1, bcf },{1, bcf },{1, bcf },{1, bcf },{1, bcf },
+/*50*/ {1, bsf },{1, bsf },{1, bsf },{1, bsf },{1, bsf },{1, bsf },{1, bsf },{1, bsf },
+/*58*/ {1, bsf },{1, bsf },{1, bsf },{1, bsf },{1, bsf },{1, bsf },{1, bsf },{1, bsf },
+/*60*/ {1, btfsc },{1, btfsc },{1, btfsc },{1, btfsc },{1, btfsc },{1, btfsc },{1, btfsc },{1, btfsc },
+/*68*/ {1, btfsc },{1, btfsc },{1, btfsc },{1, btfsc },{1, btfsc },{1, btfsc },{1, btfsc },{1, btfsc },
+/*70*/ {1, btfss },{1, btfss },{1, btfss },{1, btfss },{1, btfss },{1, btfss },{1, btfss },{1, btfss },
+/*78*/ {1, btfss },{1, btfss },{1, btfss },{1, btfss },{1, btfss },{1, btfss },{1, btfss },{1, btfss },
+/*80*/ {2, retlw },{2, retlw },{2, retlw },{2, retlw },{2, retlw },{2, retlw },{2, retlw },{2, retlw },
+/*88*/ {2, retlw },{2, retlw },{2, retlw },{2, retlw },{2, retlw },{2, retlw },{2, retlw },{2, retlw },
+/*90*/ {2, call },{2, call },{2, call },{2, call },{2, call },{2, call },{2, call },{2, call },
+/*98*/ {2, call },{2, call },{2, call },{2, call },{2, call },{2, call },{2, call },{2, call },
+/*A0*/ {2, goto_op },{2, goto_op },{2, goto_op },{2, goto_op },{2, goto_op },{2, goto_op },{2, goto_op },{2, goto_op },
+/*A8*/ {2, goto_op },{2, goto_op },{2, goto_op },{2, goto_op },{2, goto_op },{2, goto_op },{2, goto_op },{2, goto_op },
+/*B0*/ {2, goto_op },{2, goto_op },{2, goto_op },{2, goto_op },{2, goto_op },{2, goto_op },{2, goto_op },{2, goto_op },
+/*B8*/ {2, goto_op },{2, goto_op },{2, goto_op },{2, goto_op },{2, goto_op },{2, goto_op },{2, goto_op },{2, goto_op },
+/*C0*/ {1, movlw },{1, movlw },{1, movlw },{1, movlw },{1, movlw },{1, movlw },{1, movlw },{1, movlw },
+/*C8*/ {1, movlw },{1, movlw },{1, movlw },{1, movlw },{1, movlw },{1, movlw },{1, movlw },{1, movlw },
+/*D0*/ {1, iorlw },{1, iorlw },{1, iorlw },{1, iorlw },{1, iorlw },{1, iorlw },{1, iorlw },{1, iorlw },
+/*D8*/ {1, iorlw },{1, iorlw },{1, iorlw },{1, iorlw },{1, iorlw },{1, iorlw },{1, iorlw },{1, iorlw },
+/*E0*/ {1, andlw },{1, andlw },{1, andlw },{1, andlw },{1, andlw },{1, andlw },{1, andlw },{1, andlw },
+/*E8*/ {1, andlw },{1, andlw },{1, andlw },{1, andlw },{1, andlw },{1, andlw },{1, andlw },{1, andlw },
+/*F0*/ {1, xorlw },{1, xorlw },{1, xorlw },{1, xorlw },{1, xorlw },{1, xorlw },{1, xorlw },{1, xorlw },
+/*F8*/ {1, xorlw },{1, xorlw },{1, xorlw },{1, xorlw },{1, xorlw },{1, xorlw },{1, xorlw },{1, xorlw }
+};
+
+
+static const pic16c5x_opcode opcode_00x[16]=
+{
+/*00*/ {1, nop },{0, illegal },{1, option },{1, sleepic },{1, clrwdt },{1, tris },{1, tris },{1, tris },
+/*08*/ {0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal },{0, illegal }
+};
+
+
+
+/****************************************************************************
+ * Inits CPU emulation
+ ****************************************************************************/
+
+static CPU_INIT( pic16c5x )
+{
+ pic16c5x_state *cpustate = get_safe_token(device);
+
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+ cpustate->data = device->space(AS_DATA);
+ cpustate->io = device->space(AS_IO);
+
+ /* ensure the internal ram pointers are set before get_info is called */
+ update_internalram_ptr(cpustate);
+
+ device->save_item(NAME(cpustate->W));
+ device->save_item(NAME(cpustate->ALU));
+ device->save_item(NAME(cpustate->OPTION));
+ device->save_item(NAME(cpustate->TMR0));
+ device->save_item(NAME(cpustate->PCL));
+ device->save_item(NAME(cpustate->STATUS));
+ device->save_item(NAME(cpustate->FSR));
+ device->save_item(NAME(cpustate->PORTA));
+ device->save_item(NAME(cpustate->PORTB));
+ device->save_item(NAME(cpustate->PORTC));
+ device->save_item(NAME(cpustate->TRISA));
+ device->save_item(NAME(cpustate->TRISB));
+ device->save_item(NAME(cpustate->TRISC));
+ device->save_item(NAME(cpustate->old_T0));
+ device->save_item(NAME(cpustate->old_data));
+ device->save_item(NAME(cpustate->picRAMmask));
+ device->save_item(NAME(cpustate->WDT));
+ device->save_item(NAME(cpustate->prescaler));
+ device->save_item(NAME(cpustate->STACK[0]));
+ device->save_item(NAME(cpustate->STACK[1]));
+ device->save_item(NAME(cpustate->PC));
+ device->save_item(NAME(cpustate->PREVPC));
+ device->save_item(NAME(cpustate->CONFIG));
+ device->save_item(NAME(cpustate->opcode.d));
+ device->save_item(NAME(cpustate->delay_timer));
+ device->save_item(NAME(cpustate->picmodel));
+ device->save_item(NAME(cpustate->reset_vector));
+
+ device->save_item(NAME(cpustate->icount));
+ device->save_item(NAME(cpustate->temp_config));
+ device->save_item(NAME(cpustate->inst_cycles));
+}
+
+
+/****************************************************************************
+ * Reset registers to their initial values
+ ****************************************************************************/
+
+static void pic16c5x_reset_regs(pic16c5x_state *cpustate)
+{
+ cpustate->PC = cpustate->reset_vector;
+ cpustate->CONFIG = cpustate->temp_config;
+ cpustate->TRISA = 0xff;
+ cpustate->TRISB = 0xff;
+ cpustate->TRISC = 0xff;
+ cpustate->OPTION = (T0CS_FLAG | T0SE_FLAG | PSA_FLAG | PS_REG);
+ cpustate->PCL = 0xff;
+ cpustate->FSR |= (UINT8)(~cpustate->picRAMmask);
+ cpustate->PORTA &= 0x0f;
+ cpustate->prescaler = 0;
+ cpustate->delay_timer = 0;
+ cpustate->old_T0 = 0;
+ cpustate->inst_cycles = 0;
+}
+
+static void pic16c5x_soft_reset(pic16c5x_state *cpustate)
+{
+ SET(cpustate->STATUS, (TO_FLAG | PD_FLAG | Z_FLAG | DC_FLAG | C_FLAG));
+ pic16c5x_reset_regs(cpustate);
+}
+
+void pic16c5x_set_config(device_t *cpu, int data)
+{
+ pic16c5x_state *cpustate = get_safe_token(cpu);
+
+ logerror("Writing %04x to the PIC16C5x config register\n",data);
+ cpustate->temp_config = (data & 0xfff);
+}
+
+
+/****************************************************************************
+ * Shut down CPU emulation
+ ****************************************************************************/
+
+static CPU_EXIT( pic16c5x )
+{
+ /* nothing to do */
+}
+
+
+/****************************************************************************
+ * WatchDog
+ ****************************************************************************/
+
+static void pic16c5x_update_watchdog(pic16c5x_state *cpustate, int counts)
+{
+ /* WatchDog is set up to count 18,000 (0x464f hex) ticks to provide */
+ /* the timeout period of 0.018ms based on a 4MHz input clock. */
+ /* Note: the 4MHz clock should be divided by the PIC16C5x_CLOCK_DIVIDER */
+ /* which effectively makes the PIC run at 1MHz internally. */
+
+ /* If the current instruction is CLRWDT or SLEEP, don't update the WDT */
+
+ if ((cpustate->opcode.w.l != 3) && (cpustate->opcode.w.l != 4))
+ {
+ UINT16 old_WDT = cpustate->WDT;
+
+ cpustate->WDT -= counts;
+
+ if (cpustate->WDT > 0x464f) {
+ cpustate->WDT = 0x464f - (0xffff - cpustate->WDT);
+ }
+
+ if (((old_WDT != 0) && (old_WDT < cpustate->WDT)) || (cpustate->WDT == 0))
+ {
+ if (PSA) {
+ cpustate->prescaler++;
+ if (cpustate->prescaler >= (1 << PS)) { /* Prescale values from 1 to 128 */
+ cpustate->prescaler = 0;
+ CLR(cpustate->STATUS, TO_FLAG);
+ pic16c5x_soft_reset(cpustate);
+ }
+ }
+ else {
+ CLR(cpustate->STATUS, TO_FLAG);
+ pic16c5x_soft_reset(cpustate);
+ }
+ }
+ }
+}
+
+
+/****************************************************************************
+ * Update Timer
+ ****************************************************************************/
+
+static void pic16c5x_update_timer(pic16c5x_state *cpustate, int counts)
+{
+ if (PSA == 0) {
+ cpustate->prescaler += counts;
+ if (cpustate->prescaler >= (2 << PS)) { /* Prescale values from 2 to 256 */
+ cpustate->TMR0 += (cpustate->prescaler / (2 << PS));
+ cpustate->prescaler %= (2 << PS); /* Overflow prescaler */
+ }
+ }
+ else {
+ cpustate->TMR0 += counts;
+ }
+}
+
+
+/****************************************************************************
+ * Execute IPeriod. Return 0 if emulation should be stopped
+ ****************************************************************************/
+
+static CPU_EXECUTE( pic16c5x )
+{
+ pic16c5x_state *cpustate = get_safe_token(device);
+ UINT8 T0_in;
+
+ update_internalram_ptr(cpustate);
+
+ do
+ {
+ if (PD == 0) /* Sleep Mode */
+ {
+ cpustate->inst_cycles = 1;
+ debugger_instruction_hook(device, cpustate->PC);
+ if (WDTE) {
+ pic16c5x_update_watchdog(cpustate, 1);
+ }
+ }
+ else
+ {
+ cpustate->PREVPC = cpustate->PC;
+
+ debugger_instruction_hook(device, cpustate->PC);
+
+ cpustate->opcode.d = M_RDOP(cpustate->PC);
+ cpustate->PC++;
+ cpustate->PCL++;
+
+ if ((cpustate->opcode.w.l & 0xff0) != 0x000) { /* Do all opcodes except the 00? ones */
+ cpustate->inst_cycles = opcode_main[((cpustate->opcode.w.l >> 4) & 0xff)].cycles;
+ (*opcode_main[((cpustate->opcode.w.l >> 4) & 0xff)].function)(cpustate);
+ }
+ else { /* Opcode 0x00? has many opcodes in its minor nibble */
+ cpustate->inst_cycles = opcode_00x[(cpustate->opcode.b.l & 0x1f)].cycles;
+ (*opcode_00x[(cpustate->opcode.b.l & 0x1f)].function)(cpustate);
+ }
+
+ if (T0CS) { /* Count mode */
+ T0_in = S_T0_IN;
+ if (T0_in) T0_in = 1;
+ if (T0SE) { /* Count falling edge T0 input */
+ if (FALLING_EDGE_T0) {
+ pic16c5x_update_timer(cpustate, 1);
+ }
+ }
+ else { /* Count rising edge T0 input */
+ if (RISING_EDGE_T0) {
+ pic16c5x_update_timer(cpustate, 1);
+ }
+ }
+ cpustate->old_T0 = T0_in;
+ }
+ else { /* Timer mode */
+ if (cpustate->delay_timer) {
+ cpustate->delay_timer--;
+ }
+ else {
+ pic16c5x_update_timer(cpustate, cpustate->inst_cycles);
+ }
+ }
+ if (WDTE) {
+ pic16c5x_update_watchdog(cpustate, cpustate->inst_cycles);
+ }
+ }
+
+ cpustate->icount -= cpustate->inst_cycles;
+
+ } while (cpustate->icount > 0);
+}
+
+
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( pic16c5x )
+{
+ pic16c5x_state *cpustate = get_safe_token(device);
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + PIC16C5x_PC: cpustate->PC = info->i; cpustate->PCL = info->i & 0xff ;break;
+ /* This is actually not a stack pointer, but the stack contents */
+ /* Stack is a 2 level First In Last Out stack */
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + PIC16C5x_STK1: cpustate->STACK[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + PIC16C5x_STK0: cpustate->STACK[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + PIC16C5x_W: cpustate->W = info->i; break;
+ case CPUINFO_INT_REGISTER + PIC16C5x_ALU: cpustate->ALU = info->i; break;
+ case CPUINFO_INT_REGISTER + PIC16C5x_STR: cpustate->STATUS = info->i; break;
+ case CPUINFO_INT_REGISTER + PIC16C5x_OPT: cpustate->OPTION = info->i & (T0CS_FLAG | T0SE_FLAG | PSA_FLAG | PS_REG); break;
+ case CPUINFO_INT_REGISTER + PIC16C5x_TMR0: cpustate->TMR0 = info->i; break;
+ case CPUINFO_INT_REGISTER + PIC16C5x_WDT: cpustate->WDT = info->i; break;
+ case CPUINFO_INT_REGISTER + PIC16C5x_PSCL: cpustate->prescaler = info->i; break;
+ case CPUINFO_INT_REGISTER + PIC16C5x_PRTA: cpustate->PORTA = info->i & 0x0f; break;
+ case CPUINFO_INT_REGISTER + PIC16C5x_PRTB: cpustate->PORTB = info->i; break;
+ case CPUINFO_INT_REGISTER + PIC16C5x_PRTC: cpustate->PORTC = info->i; break;
+ case CPUINFO_INT_REGISTER + PIC16C5x_FSR: cpustate->FSR = ((info->i & cpustate->picRAMmask) | (UINT8)(~cpustate->picRAMmask)); break;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+static CPU_GET_INFO( pic16c5x )
+{
+ pic16c5x_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(pic16c5x_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 1; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 4; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 2; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 2; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 2; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 9; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = -1; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 5; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 5; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = cpustate->PREVPC; break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + PIC16C5x_PC: info->i = cpustate->PC; break;
+ /* This is actually not a stack pointer, but the stack contents */
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + PIC16C5x_STK1: info->i = cpustate->STACK[1]; break;
+ case CPUINFO_INT_REGISTER + PIC16C5x_STK0: info->i = cpustate->STACK[0]; break;
+ case CPUINFO_INT_REGISTER + PIC16C5x_W: info->i = cpustate->W; break;
+ case CPUINFO_INT_REGISTER + PIC16C5x_ALU: info->i = cpustate->ALU; break;
+ case CPUINFO_INT_REGISTER + PIC16C5x_STR: info->i = cpustate->STATUS; break;
+ case CPUINFO_INT_REGISTER + PIC16C5x_OPT: info->i = cpustate->OPTION; break;
+ case CPUINFO_INT_REGISTER + PIC16C5x_TMR0: info->i = cpustate->TMR0; break;
+ case CPUINFO_INT_REGISTER + PIC16C5x_WDT: info->i = cpustate->WDT; break;
+ case CPUINFO_INT_REGISTER + PIC16C5x_PSCL: info->i = cpustate->prescaler; break;
+ case CPUINFO_INT_REGISTER + PIC16C5x_PRTA: info->i = cpustate->PORTA; break;
+ case CPUINFO_INT_REGISTER + PIC16C5x_PRTB: info->i = cpustate->PORTB; break;
+ case CPUINFO_INT_REGISTER + PIC16C5x_PRTC: info->i = cpustate->PORTC; break;
+ case CPUINFO_INT_REGISTER + PIC16C5x_FSR: info->i = ((cpustate->FSR & cpustate->picRAMmask) | (UINT8)(~cpustate->picRAMmask)); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(pic16c5x); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(pic16c5x); break;
+ case CPUINFO_FCT_RESET: /* set per-CPU */ break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(pic16c5x); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(pic16c5x); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(pic16c5x); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "PIC16C5x"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Microchip"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.14"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Tony La Porta"); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%01x%c%c%c%c%c %c%c%c%03x",
+ (cpustate->STATUS & 0xe0) >> 5,
+ cpustate->STATUS & 0x10 ? '.':'O', /* WDT Overflow */
+ cpustate->STATUS & 0x08 ? 'P':'D', /* Power/Down */
+ cpustate->STATUS & 0x04 ? 'Z':'.', /* Zero */
+ cpustate->STATUS & 0x02 ? 'c':'b', /* Nibble Carry/Borrow */
+ cpustate->STATUS & 0x01 ? 'C':'B', /* Carry/Borrow */
+
+ cpustate->OPTION & 0x20 ? 'C':'T', /* Counter/Timer */
+ cpustate->OPTION & 0x10 ? 'N':'P', /* Negative/Positive */
+ cpustate->OPTION & 0x08 ? 'W':'T', /* WatchDog/Timer */
+ cpustate->OPTION & 0x08 ? (1<<(cpustate->OPTION&7)) : (2<<(cpustate->OPTION&7)) );
+ break;
+
+ case CPUINFO_STR_REGISTER + PIC16C5x_PC: sprintf(info->s, "PC:%03X", cpustate->PC); break;
+ case CPUINFO_STR_REGISTER + PIC16C5x_W: sprintf(info->s, "W:%02X", cpustate->W); break;
+ case CPUINFO_STR_REGISTER + PIC16C5x_ALU: sprintf(info->s, "ALU:%02X", cpustate->ALU); break;
+ case CPUINFO_STR_REGISTER + PIC16C5x_STR: sprintf(info->s, "STR:%02X", cpustate->STATUS); break;
+ case CPUINFO_STR_REGISTER + PIC16C5x_TMR0: sprintf(info->s, "TMR:%02X", cpustate->TMR0); break;
+ case CPUINFO_STR_REGISTER + PIC16C5x_WDT: sprintf(info->s, "WDT:%04X", cpustate->WDT); break;
+ case CPUINFO_STR_REGISTER + PIC16C5x_OPT: sprintf(info->s, "OPT:%02X", cpustate->OPTION); break;
+ case CPUINFO_STR_REGISTER + PIC16C5x_STK0: sprintf(info->s, "STK0:%03X", cpustate->STACK[0]); break;
+ case CPUINFO_STR_REGISTER + PIC16C5x_STK1: sprintf(info->s, "STK1:%03X", cpustate->STACK[1]); break;
+ case CPUINFO_STR_REGISTER + PIC16C5x_PRTA: sprintf(info->s, "PRTA:%01X", ((cpustate->PORTA) & 0x0f)); break;
+ case CPUINFO_STR_REGISTER + PIC16C5x_PRTB: sprintf(info->s, "PRTB:%02X", cpustate->PORTB); break;
+ case CPUINFO_STR_REGISTER + PIC16C5x_PRTC: sprintf(info->s, "PRTC:%02X", cpustate->PORTC); break;
+ case CPUINFO_STR_REGISTER + PIC16C5x_TRSA: sprintf(info->s, "TRSA:%01X", ((cpustate->TRISA) & 0x0f)); break;
+ case CPUINFO_STR_REGISTER + PIC16C5x_TRSB: sprintf(info->s, "TRSB:%02X", cpustate->TRISB); break;
+ case CPUINFO_STR_REGISTER + PIC16C5x_TRSC: sprintf(info->s, "TRSC:%02X", cpustate->TRISC); break;
+ case CPUINFO_STR_REGISTER + PIC16C5x_FSR: sprintf(info->s, "FSR:%02X", ((cpustate->FSR) & cpustate->picRAMmask) | (UINT8)(~cpustate->picRAMmask)); break;
+ case CPUINFO_STR_REGISTER + PIC16C5x_PSCL: sprintf(info->s, "PSCL:%c%02X", ((cpustate->OPTION & 0x08) ? 'W':'T'), cpustate->prescaler); break;
+ }
+}
+
+
+
+/****************************************************************************
+ * Internal Memory Map
+ ****************************************************************************/
+
+static ADDRESS_MAP_START( pic16c54_rom, AS_PROGRAM, 16 )
+ AM_RANGE(0x000, 0x1ff) AM_ROM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( pic16c54_ram, AS_DATA, 8 )
+ AM_RANGE(0x00, 0x07) AM_RAM
+ AM_RANGE(0x08, 0x0f) AM_RAM
+ AM_RANGE(0x10, 0x1f) AM_RAM
+ADDRESS_MAP_END
+
+
+/****************************************************************************
+ * PIC16C54 Reset
+ ****************************************************************************/
+
+static CPU_RESET( pic16c54 )
+{
+ pic16c5x_state *cpustate = get_safe_token(device);
+
+ update_internalram_ptr(cpustate);
+
+ cpustate->picmodel = 0x16C54;
+ cpustate->picRAMmask = 0x1f;
+ cpustate->reset_vector = 0x1ff;
+ pic16c5x_reset_regs(cpustate);
+ CLR(cpustate->STATUS, PA_REG);
+ SET(cpustate->STATUS, (TO_FLAG | PD_FLAG));
+}
+
+
+/**************************************************************************
+ * CPU-specific get_info
+ **************************************************************************/
+
+CPU_GET_INFO( pic16c54 )
+{
+ switch (state)
+ {
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 9; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 5; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(pic16c54); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map16 = ADDRESS_MAP_NAME(pic16c54_rom); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = ADDRESS_MAP_NAME(pic16c54_ram); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "PIC16C54"); break;
+
+ default: CPU_GET_INFO_CALL(pic16c5x); break;
+ }
+}
+
+
+/****************************************************************************
+ * Internal Memory Map
+ ****************************************************************************/
+
+static ADDRESS_MAP_START( pic16c55_rom, AS_PROGRAM, 16 )
+ AM_RANGE(0x000, 0x1ff) AM_ROM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( pic16c55_ram, AS_DATA, 8 )
+ AM_RANGE(0x00, 0x07) AM_RAM
+ AM_RANGE(0x08, 0x0f) AM_RAM
+ AM_RANGE(0x10, 0x1f) AM_RAM
+ADDRESS_MAP_END
+
+
+/****************************************************************************
+ * PIC16C55 Reset
+ ****************************************************************************/
+
+static CPU_RESET( pic16c55 )
+{
+ pic16c5x_state *cpustate = get_safe_token(device);
+
+ update_internalram_ptr(cpustate);
+
+ cpustate->picmodel = 0x16C55;
+ cpustate->picRAMmask = 0x1f;
+ cpustate->reset_vector = 0x1ff;
+ pic16c5x_reset_regs(cpustate);
+ CLR(cpustate->STATUS, PA_REG);
+ SET(cpustate->STATUS, (TO_FLAG | PD_FLAG));
+}
+
+
+/**************************************************************************
+ * CPU-specific get_info
+ **************************************************************************/
+
+CPU_GET_INFO( pic16c55 )
+{
+ switch (state)
+ {
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 9; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 5; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(pic16c55); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map16 = ADDRESS_MAP_NAME(pic16c55_rom); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = ADDRESS_MAP_NAME(pic16c55_ram); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "PIC16C55"); break;
+
+ default: CPU_GET_INFO_CALL(pic16c5x); break;
+ }
+}
+
+
+/****************************************************************************
+ * Internal Memory Map
+ ****************************************************************************/
+
+static ADDRESS_MAP_START( pic16c56_rom, AS_PROGRAM, 16 )
+ AM_RANGE(0x000, 0x3ff) AM_ROM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( pic16c56_ram, AS_DATA, 8 )
+ AM_RANGE(0x00, 0x07) AM_RAM
+ AM_RANGE(0x08, 0x0f) AM_RAM
+ AM_RANGE(0x10, 0x1f) AM_RAM
+ADDRESS_MAP_END
+
+
+/****************************************************************************
+ * PIC16C56 Reset
+ ****************************************************************************/
+
+static CPU_RESET( pic16c56 )
+{
+ pic16c5x_state *cpustate = get_safe_token(device);
+
+ update_internalram_ptr(cpustate);
+
+ cpustate->picmodel = 0x16C56;
+ cpustate->picRAMmask = 0x1f;
+ cpustate->reset_vector = 0x3ff;
+ pic16c5x_reset_regs(cpustate);
+ CLR(cpustate->STATUS, PA_REG);
+ SET(cpustate->STATUS, (TO_FLAG | PD_FLAG));
+}
+
+
+/**************************************************************************
+ * CPU-specific get_info
+ **************************************************************************/
+
+CPU_GET_INFO( pic16c56 )
+{
+ switch (state)
+ {
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 10; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 5; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(pic16c56); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map16 = ADDRESS_MAP_NAME(pic16c56_rom); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = ADDRESS_MAP_NAME(pic16c56_ram); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "PIC16C56"); break;
+
+ default: CPU_GET_INFO_CALL(pic16c5x); break;
+ }
+}
+
+
+/****************************************************************************
+ * Internal Memory Map
+ ****************************************************************************/
+
+static ADDRESS_MAP_START( pic16c57_rom, AS_PROGRAM, 16 )
+ AM_RANGE(0x000, 0x7ff) AM_ROM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( pic16c57_ram, AS_DATA, 8 )
+ AM_RANGE(0x00, 0x07) AM_RAM AM_MIRROR(0x60)
+ AM_RANGE(0x08, 0x0f) AM_RAM AM_MIRROR(0x60)
+ AM_RANGE(0x10, 0x1f) AM_RAM
+ AM_RANGE(0x30, 0x3f) AM_RAM
+ AM_RANGE(0x50, 0x5f) AM_RAM
+ AM_RANGE(0x70, 0x7f) AM_RAM
+ADDRESS_MAP_END
+
+
+/****************************************************************************
+ * PIC16C57 Reset
+ ****************************************************************************/
+
+static CPU_RESET( pic16c57 )
+{
+ pic16c5x_state *cpustate = get_safe_token(device);
+
+ update_internalram_ptr(cpustate);
+
+ cpustate->picmodel = 0x16C57;
+ cpustate->picRAMmask = 0x7f;
+ cpustate->reset_vector = 0x7ff;
+ pic16c5x_reset_regs(cpustate);
+ CLR(cpustate->STATUS, PA_REG);
+ SET(cpustate->STATUS, (TO_FLAG | PD_FLAG));
+}
+
+
+/**************************************************************************
+ * CPU-specific get_info
+ **************************************************************************/
+
+CPU_GET_INFO( pic16c57 )
+{
+ switch (state)
+ {
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 11; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 7; break;
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(pic16c57); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map16 = ADDRESS_MAP_NAME(pic16c57_rom); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = ADDRESS_MAP_NAME(pic16c57_ram); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "PIC16C57"); break;
+
+ default: CPU_GET_INFO_CALL(pic16c5x); break;
+ }
+}
+
+
+/****************************************************************************
+ * Internal Memory Map
+ ****************************************************************************/
+
+static ADDRESS_MAP_START( pic16c58_rom, AS_PROGRAM, 16 )
+ AM_RANGE(0x000, 0x7ff) AM_ROM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( pic16c58_ram, AS_DATA, 8 )
+ AM_RANGE(0x00, 0x07) AM_RAM AM_MIRROR(0x60)
+ AM_RANGE(0x08, 0x0f) AM_RAM AM_MIRROR(0x60)
+ AM_RANGE(0x10, 0x1f) AM_RAM
+ AM_RANGE(0x30, 0x3f) AM_RAM
+ AM_RANGE(0x50, 0x5f) AM_RAM
+ AM_RANGE(0x70, 0x7f) AM_RAM
+ADDRESS_MAP_END
+
+
+/****************************************************************************
+ * PIC16C58 Reset
+ ****************************************************************************/
+
+static CPU_RESET( pic16c58 )
+{
+ pic16c5x_state *cpustate = get_safe_token(device);
+
+ update_internalram_ptr(cpustate);
+
+ cpustate->picmodel = 0x16C58;
+ cpustate->picRAMmask = 0x7f;
+ cpustate->reset_vector = 0x7ff;
+ pic16c5x_reset_regs(cpustate);
+ CLR(cpustate->STATUS, PA_REG);
+ SET(cpustate->STATUS, (TO_FLAG | PD_FLAG));
+}
+
+
+/**************************************************************************
+ * CPU-specific get_info
+ **************************************************************************/
+
+CPU_GET_INFO( pic16c58 )
+{
+ switch (state)
+ {
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 11; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 7; break;
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(pic16c58); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map16 = ADDRESS_MAP_NAME(pic16c58_rom); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = ADDRESS_MAP_NAME(pic16c58_ram); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "PIC16C58"); break;
+
+ default: CPU_GET_INFO_CALL(pic16c5x); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(PIC16C54, pic16c54);
+DEFINE_LEGACY_CPU_DEVICE(PIC16C55, pic16c55);
+DEFINE_LEGACY_CPU_DEVICE(PIC16C56, pic16c56);
+DEFINE_LEGACY_CPU_DEVICE(PIC16C57, pic16c57);
+DEFINE_LEGACY_CPU_DEVICE(PIC16C58, pic16c58);
diff --git a/trunk/src/emu/cpu/pic16c5x/pic16c5x.h b/trunk/src/emu/cpu/pic16c5x/pic16c5x.h
new file mode 100644
index 00000000000..5e8937daba3
--- /dev/null
+++ b/trunk/src/emu/cpu/pic16c5x/pic16c5x.h
@@ -0,0 +1,60 @@
+ /**************************************************************************\
+ * Microchip PIC16C5x Emulator *
+ * *
+ * Copyright Tony La Porta *
+ * Originally written for the MAME project. *
+ * *
+ * *
+ * Addressing architecture is based on the Harvard addressing scheme. *
+ * *
+ \**************************************************************************/
+
+#pragma once
+
+#ifndef __PIC16C5X_H__
+#define __PIC16C5X_H__
+
+
+
+
+/**************************************************************************
+ * Internal Clock divisor
+ *
+ * External Clock is divided internally by 4 for the instruction cycle
+ * times. (Each instruction cycle passes through 4 machine states). This
+ * is handled by the cpu execution engine.
+ */
+
+enum
+{
+ PIC16C5x_PC=1, PIC16C5x_STK0, PIC16C5x_STK1, PIC16C5x_FSR,
+ PIC16C5x_W, PIC16C5x_ALU, PIC16C5x_STR, PIC16C5x_OPT,
+ PIC16C5x_TMR0, PIC16C5x_PRTA, PIC16C5x_PRTB, PIC16C5x_PRTC,
+ PIC16C5x_WDT, PIC16C5x_TRSA, PIC16C5x_TRSB, PIC16C5x_TRSC,
+ PIC16C5x_PSCL
+};
+
+#define PIC16C5x_T0 0x10
+
+
+/****************************************************************************
+ * Function to configure the CONFIG register. This is actually hard-wired
+ * during ROM programming, so should be called in the driver INIT, with
+ * the value if known (available in HEX dumps of the ROM).
+ */
+
+void pic16c5x_set_config(device_t *cpu, int data);
+
+
+
+DECLARE_LEGACY_CPU_DEVICE(PIC16C54, pic16c54);
+DECLARE_LEGACY_CPU_DEVICE(PIC16C55, pic16c55);
+DECLARE_LEGACY_CPU_DEVICE(PIC16C56, pic16c56);
+DECLARE_LEGACY_CPU_DEVICE(PIC16C57, pic16c57);
+DECLARE_LEGACY_CPU_DEVICE(PIC16C58, pic16c58);
+
+
+CPU_DISASSEMBLE( pic16c5x );
+
+
+#endif /* __PIC16C5X_H__ */
diff --git a/trunk/src/emu/cpu/pic16c62x/16c62xdsm.c b/trunk/src/emu/cpu/pic16c62x/16c62xdsm.c
new file mode 100644
index 00000000000..4a5ec7c002e
--- /dev/null
+++ b/trunk/src/emu/cpu/pic16c62x/16c62xdsm.c
@@ -0,0 +1,265 @@
+ /**************************************************************************\
+ * Microchip PIC16C62X Emulator *
+ * *
+ * Based On *
+ * Microchip PIC16C5X Emulator *
+ * Copyright Tony La Porta *
+ * Originally written for the MAME project. *
+ * *
+ * *
+ * Addressing architecture is based on the Harvard addressing scheme. *
+ * *
+ * Many thanks to those involved in the i8039 Disassembler *
+ * as this was based on it. *
+ * *
+ * *
+ * *
+ * A Address to jump to. *
+ * B Bit address within an 8-bit file register. *
+ * D Destination select (0 = store result in W (accumulator)) *
+ * (1 = store result in file register) *
+ * F Register file address (00-1F). *
+ * K Literal field, constant data. *
+ * X Not used *
+ * *
+ \**************************************************************************/
+
+#include "emu.h"
+#include <ctype.h>
+
+static const UINT8 *rombase;
+static const UINT8 *rambase;
+static offs_t pcbase;
+#define READOP16(A) (rombase[(A) - pcbase] | (rombase[(A) + 1 - pcbase] << 8))
+#define READARG16(A) (rambase[(A) - pcbase] | (rambase[(A) + 1 - pcbase] << 8))
+
+
+
+typedef unsigned char byte;
+typedef unsigned short int word;
+
+#define FMT(a,b) a, b
+#define PTRS_PER_FORMAT 2
+
+/* Registers bank 0/1 */
+static const char *const regfile[32] = { "Reg$00 (INDF)", "Reg$01 (TMR0/OPTION)", "Reg$02 (PCL)", "Reg$03 (STATUS)", "Reg$04 (FSR)", "Reg$05 (PORTA/TRISA)", "Reg$06 (PORTB/TRISB)", "Reg$07",
+ "Reg$08", "Reg$09", "Reg$0A (PCLATH)", "Reg$0B (INTCON)", "Reg$0C (PIR1/PIE1)", "Reg$0D", "Reg$0E (none/PCON)", "Reg$0F",
+ "Reg$10", "Reg$11", "Reg$12", "Reg$13", "Reg$14", "Reg$15", "Reg$16", "Reg$17",
+ "Reg$18", "Reg$19", "Reg$1A", "Reg$1B", "Reg$1C", "Reg$1D", "Reg$1E", "Reg$1F (CMCON/VRCON)" };
+/* Registers bank 1 */
+/*static const char *const regfile1[32] = { "Reg$00 (INDF)", "Reg$01 (OPTION)", "Reg$02 (PCL)", "Reg$03 (STATUS)", "Reg$04 (FSR)", "Reg$05 (TRISA)", "Reg$06 (TRISB)", "Reg$07",
+ "Reg$08", "Reg$09", "Reg$0A (PCLATH)", "Reg$0B (INTCON)", "Reg$0C (PIE1)", "Reg$0D", "Reg$0E (PCON)", "Reg$0F",
+ "Reg$10", "Reg$11", "Reg$12", "Reg$13", "Reg$14", "Reg$15", "Reg$16", "Reg$17",
+ "Reg$18", "Reg$19", "Reg$1A", "Reg$1B", "Reg$1C", "Reg$1D", "Reg$1E", "Reg$1F (VRCON)" };
+static const char **regfile[2] = { regfile0, regfile1 };*/
+
+static const char *const dest[2] = { "W", "Reg" };
+
+static const char *const PIC16C62xFormats[] = {
+ FMT("0000000xx00000", "nop"),
+ FMT("00000000001000", "return"),
+ FMT("00000000001001", "retfie"),
+ FMT("00000001100011", "sleep"),
+ FMT("00000001100100", "clrwdt"),
+ FMT("0000001fffffff", "movwf %F"),
+ FMT("00000100000011", "clrw"),
+ FMT("0000011fffffff", "clrf %F"),
+ FMT("000010dfffffff", "subwf %F,%D"),
+ FMT("000011dfffffff", "decf %F,%D"),
+ FMT("000100dfffffff", "iorwf %F,%D"),
+ FMT("000101dfffffff", "andwf %F,%D"),
+ FMT("000110dfffffff", "xorwf %F,%D"),
+ FMT("000111dfffffff", "addwf %F,%D"),
+ FMT("001000dfffffff", "movf %F,%D"),
+ FMT("001001dfffffff", "comf %F,%D"),
+ FMT("001010dfffffff", "incf %F,%D"),
+ FMT("001011dfffffff", "decfsz %F,%D"),
+ FMT("001100dfffffff", "rrf %F,%D"),
+ FMT("001101dfffffff", "rlf %F,%D"),
+ FMT("001110dfffffff", "swapf %F,%D"),
+ FMT("001111dfffffff", "incfsz %F,%D"),
+ FMT("0100bbbfffffff", "bcf %F,%B"),
+ FMT("0101bbbfffffff", "bsf %F,%B"),
+ FMT("0110bbbfffffff", "btfsc %F,%B"),
+ FMT("0111bbbfffffff", "btfss %F,%B"),
+ FMT("1101xxkkkkkkkk", "retlw %K"),
+ FMT("100aaaaaaaaaaa", "call %A"),
+ FMT("101aaaaaaaaaaa", "goto %A"),
+ FMT("1100xxkkkkkkkk", "movlw %K"),
+ FMT("111000kkkkkkkk", "iorlw %K"),
+ FMT("111001kkkkkkkk", "andlw %K"),
+ FMT("111010kkkkkkkk", "xorlw %K"),
+ FMT("11110xkkkkkkkk", "sublw %K"),
+ FMT("11111xkkkkkkkk", "addlw %K"),
+ NULL
+};
+
+#define MAX_OPS (((sizeof(PIC16C62xFormats) / sizeof(PIC16C62xFormats[0])) - 1) / PTRS_PER_FORMAT)
+
+typedef struct opcode {
+ word mask; /* instruction mask */
+ word bits; /* constant bits */
+ word extcode; /* value that gets extension code */
+ const char *parse; /* how to parse bits */
+ const char *fmt; /* instruction format */
+} PIC16C62xOpcode;
+
+static PIC16C62xOpcode Op[MAX_OPS+1];
+static int OpInizialized = 0;
+
+static void InitDasm16C5x(void)
+{
+ const char *p;
+ const char *const *ops;
+ word mask, bits;
+ int bit;
+ int i;
+
+ ops = PIC16C62xFormats; i = 0;
+ while (*ops)
+ {
+ p = *ops;
+ mask = 0; bits = 0; bit = 13;
+ while (*p && bit >= 0)
+ {
+ switch (*p++)
+ {
+ case '1': mask |= 1<<bit; bits |= 1<<bit; bit--; break;
+ case '0': mask |= 1<<bit; bit--; break;
+ case ' ': break;
+ case 'a':
+ case 'b':
+ case 'd':
+ case 'f':
+ case 'k':
+ case 'x':
+ bit --;
+ break;
+ default: fatalerror("Invalid instruction encoding '%s %s'",
+ ops[0],ops[1]);
+ }
+ }
+ if (bit != -1 )
+ {
+ fatalerror("not enough bits in encoding '%s %s' %d",
+ ops[0],ops[1],bit);
+ }
+ while (isspace((UINT8)*p)) p++;
+ if (*p) Op[i].extcode = *p;
+ Op[i].bits = bits;
+ Op[i].mask = mask;
+ Op[i].fmt = ops[1];
+ Op[i].parse = ops[0];
+
+ ops += PTRS_PER_FORMAT;
+ i++;
+ }
+
+ OpInizialized = 1;
+}
+
+CPU_DISASSEMBLE( pic16c62x )
+{
+ int a, b, d, f, k; /* these can all be filled in by parsing an instruction */
+ int i;
+ int op;
+ int cnt = 1;
+ int code;
+ int bit;
+ //char *buffertmp;
+ const char *cp; /* character pointer in OpFormats */
+ UINT32 flags = 0;
+
+ rombase = oprom;
+ rambase = opram;
+ pcbase = 2*pc;
+
+ if (!OpInizialized) InitDasm16C5x();
+
+ op = -1; /* no matching opcode */
+ code = READOP16(2*pc);
+ for ( i = 0; i < MAX_OPS; i++)
+ {
+ if ((code & Op[i].mask) == Op[i].bits)
+ {
+ if (op != -1)
+ {
+ mame_printf_debug("Error: opcode %04Xh matches %d (%s) and %d (%s)\n",
+ code,i,Op[i].fmt,op,Op[op].fmt);
+ }
+ op = i;
+ }
+ }
+ if (op == -1)
+ {
+ sprintf(buffer,"???? dw %04Xh",code);
+ return cnt;
+ }
+ //buffertmp = buffer;
+ if (Op[op].extcode) /* Actually, theres no double length opcodes */
+ {
+ bit = 29;
+ code <<= 16;
+ code |= READARG16(2*(pc+cnt));
+ cnt++;
+ }
+ else
+ {
+ bit = 13;
+ }
+
+ /* shift out operands */
+ cp = Op[op].parse;
+ a = b = d = f = k = 0;
+
+ while (bit >= 0)
+ {
+ /* mame_printf_debug("{%c/%d}",*cp,bit); */
+ switch(*cp)
+ {
+ case 'a': a <<=1; a |= ((code & (1<<bit)) ? 1 : 0); bit--; break;
+ case 'b': b <<=1; b |= ((code & (1<<bit)) ? 1 : 0); bit--; break;
+ case 'd': d <<=1; d |= ((code & (1<<bit)) ? 1 : 0); bit--; break;
+ case 'f': f <<=1; f |= ((code & (1<<bit)) ? 1 : 0); bit--; break;
+ case 'k': k <<=1; k |= ((code & (1<<bit)) ? 1 : 0); bit--; break;
+ case ' ': break;
+ case '1': case '0': case 'x': bit--; break;
+ case '\0': fatalerror("premature end of parse string, opcode %x, bit = %d",code,bit);
+ }
+ cp++;
+ }
+
+ /* now traverse format string */
+ cp = Op[op].fmt;
+ if (!strncmp(cp, "call", 4))
+ flags = DASMFLAG_STEP_OVER;
+ else if (!strncmp(cp, "ret", 3))
+ flags = DASMFLAG_STEP_OUT;
+
+ while (*cp)
+ {
+ if (*cp == '%')
+ {
+ char num[30], *q;
+ cp++;
+ switch (*cp++)
+ {
+ case 'A': sprintf(num,"$%03X",a); break;
+ case 'B': sprintf(num,"%d",b); break;
+ case 'D': sprintf(num,"%s",dest[d]); break;
+ case 'F': if (f < 0x20) sprintf(num,"%s",regfile[f]); else sprintf(num,"Reg$%02X",f); break;
+ case 'K': sprintf(num,"%02Xh",k); break;
+ default:
+ fatalerror("illegal escape character in format '%s'",Op[op].fmt);
+ }
+ q = num; while (*q) *buffer++ = *q++;
+ *buffer = '\0';
+ }
+ else
+ {
+ *buffer++ = *cp++;
+ *buffer = '\0';
+ }
+ }
+ return cnt | flags | DASMFLAG_SUPPORTED;
+}
diff --git a/trunk/src/emu/cpu/pic16c62x/dis16c62x.c b/trunk/src/emu/cpu/pic16c62x/dis16c62x.c
new file mode 100644
index 00000000000..2da766d1d83
--- /dev/null
+++ b/trunk/src/emu/cpu/pic16c62x/dis16c62x.c
@@ -0,0 +1,136 @@
+ /**************************************************************************\
+ * Microchip PIC16C62X Emulator *
+ * *
+ * Based On *
+ * Microchip PIC16C5X Emulator *
+ * Copyright Tony La Porta *
+ * Originally written for the MAME project. *
+ * *
+ * *
+ * Notes : Data is expected to be read from source file as LSB first. *
+ * *
+ \**************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+
+#include "16c62xdsm.c"
+
+
+unsigned char *Buffer;
+
+
+int main(int argc,char *argv[])
+{
+ int length=0, length_to_dump=0, offset=0, disasm_words=0;
+ int filelength=0, bytes_read;
+ int Counter=0;
+
+ FILE *F;
+ char *String_Output;
+
+ if(argc<2)
+ {
+ printf("\n");
+ printf("PIC16C5x Disassembler 1.0 by Tony La Porta (C)2003+\n\n");
+ printf("Usage: dis16c5x <input-file> [ <start-addr> [ <num-of-addr> ] ]\n");
+ printf(" <input-file> source file data must be MSB first\n");
+ printf(" <start-addr> starting address to disassemble from (decimal)\n");
+ printf(" <num-of-addr> number of addresses to disassemble (decimal)\n");
+ printf(" Precede values with 0x if HEX values preffered\n");
+ exit(1);
+ }
+
+ if(!(F=fopen(argv[1],"rb")))
+ {
+ printf("\n%s: Can't open file %s\n",argv[0],argv[1]);
+ exit(2);
+ }
+ argv++; argc--;
+ if (argv[1])
+ {
+ offset = strtol(argv[1],NULL,0);
+ argv++; argc--;
+ }
+ if (argv[1])
+ {
+ length = strtol(argv[1],NULL,0);
+ argv++; argc--;
+ }
+
+ fseek(F,0, SEEK_END);
+ filelength = ftell(F);
+
+ length *= 2;
+
+ if ((length > (filelength - (offset*2))) || (length == 0)) length = filelength - (offset*2);
+ printf("Length=%04Xh(words) Offset=$%04Xh filelength=%04Xh(words) %04Xh(bytes)\n",length/2,offset,filelength/2,filelength);
+ length_to_dump = length;
+ printf("Starting from %d, dumping %d opcodes (word size)\n",offset,length/2);
+ Buffer = calloc((filelength+1),sizeof(char));
+ if (Buffer==NULL)
+ {
+ printf("Out of Memory !!!");
+ fclose(F);
+ exit(3);
+ }
+ String_Output = calloc(80,sizeof(char));
+ if (String_Output==NULL)
+ {
+ printf("Out of Memory !!!");
+ free(Buffer);
+ fclose(F);
+ exit(4);
+ }
+
+ if (fseek(F,0,SEEK_SET) != 0)
+ {
+ printf("Error seeking to beginning of file\n");
+ free(String_Output);
+ free(Buffer);
+ fclose(F);
+ exit(5);
+ }
+
+ Counter = offset;
+ bytes_read = fread(Buffer,sizeof(char),filelength,F);
+ if (bytes_read >= length)
+ {
+ for (; length > 0; length -= (disasm_words*2))
+ {
+ int ii;
+ disasm_words = Dasm16C5x(String_Output,Counter);
+ printf("$%03X: ",Counter);
+ for (ii = 0; ii < disasm_words; ii++)
+ {
+ if (((Counter*2) + ii) > filelength) /* Past end of length to dump ? */
+ {
+ sprintf(String_Output,"???? dw %02.2X%02.2Xh (Past end of disassembly !)",Buffer[((Counter-1)*2)+1],Buffer[((Counter-1)*2)]);
+ }
+ else
+ {
+ printf("%02.2x%02.2x ",Buffer[(Counter*2)+1],Buffer[(Counter*2)]);
+ }
+ Counter++ ;
+ }
+ for (; ii < 4; ii++)
+ {
+ printf(" ");
+ }
+ printf("\t%s\n",String_Output);
+ }
+ }
+ else
+ {
+ printf("ERROR length to dump was %d ", length_to_dump/2);
+ printf(", but bytes read from file were %d\n", bytes_read/2);
+ free(String_Output);
+ free(Buffer);
+ fclose(F);
+ exit(7);
+ }
+ free(String_Output);
+ free(Buffer);
+ fclose(F);
+ return(0);
+}
diff --git a/trunk/src/emu/cpu/pic16c62x/pic16c62x.c b/trunk/src/emu/cpu/pic16c62x/pic16c62x.c
new file mode 100644
index 00000000000..2e527d8b3c4
--- /dev/null
+++ b/trunk/src/emu/cpu/pic16c62x/pic16c62x.c
@@ -0,0 +1,1613 @@
+ /**************************************************************************\
+ * Microchip PIC16C62X Emulator *
+ * *
+ * Based On *
+ * Microchip PIC16C5X Emulator *
+ * Copyright Tony La Porta *
+ * Originally written for the MAME project. *
+ * *
+ * *
+ * Addressing architecture is based on the Harvard addressing scheme. *
+ * *
+ * *
+ * **** Change Log **** *
+ * SZ (22-Oct-2009) *
+ * - Improvements and tests *
+ * SZ (2-Oct-2009) *
+ * - Internal ram and registers *
+ * SZ (12-Sep-2009) *
+ * - Started working on it. *
+ * *
+ * *
+ * **** TODO **** *
+ * - Finish checking opcodes/instructions *
+ * - Internal devices *
+ * - Interrupts *
+ * - Everything ! *
+ * *
+ * **** DONE **** *
+ * - I/O ports *
+ * - Savestates *
+ * - Internal memory *
+ * - New opcodes *
+ * - Opcode disassembly *
+ * *
+ * **** Notes (from PIC16C5X): **** *
+ * PIC WatchDog Timer has a separate internal clock. For the moment, we're *
+ * basing the count on a 4MHz input clock, since 4MHz is the typical *
+ * input frequency (but by no means always). *
+ * A single scaler is available for the Counter/Timer or WatchDog Timer. *
+ * When connected to the Counter/Timer, it functions as a Prescaler, *
+ * hence prescale overflows, tick the Counter/Timer. *
+ * When connected to the WatchDog Timer, it functions as a Postscaler *
+ * hence WatchDog Timer overflows, tick the Postscaler. This scenario *
+ * means that the WatchDog timeout occurs when the Postscaler has *
+ * reached the scaler rate value, not when the WatchDog reaches zero. *
+ * CLRWDT should prevent the WatchDog Timer from timing out and generating *
+ * a device reset, but how is not known. The manual also mentions that *
+ * the WatchDog Timer can only be disabled during ROM programming, and *
+ * no other means seem to exist??? *
+ * *
+ \**************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "pic16c62x.h"
+
+
+
+
+typedef struct _pic16c62x_state pic16c62x_state;
+struct _pic16c62x_state
+{
+ /******************** CPU Internal Registers *******************/
+ UINT16 PC;
+ UINT16 PREVPC; /* previous program counter */
+ UINT8 W;
+ UINT8 PCLATH; /* 0a,8a */
+ UINT8 OPTION; /* 81 */
+ UINT16 CONFIG;
+ UINT8 ALU;
+ UINT16 WDT;
+ UINT8 TRISA; /* 85 */
+ UINT8 TRISB; /* 86 */
+ UINT16 STACK[8];
+ UINT16 prescaler; /* Note: this is really an 8-bit register */
+ PAIR opcode;
+ UINT8 *internalram;
+
+ int icount;
+ int reset_vector;
+ int picmodel;
+ int delay_timer;
+ UINT16 temp_config;
+ UINT8 old_T0;
+ INT8 old_data;
+ UINT8 picRAMmask;
+ int inst_cycles;
+
+
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ address_space *data;
+ address_space *io;
+};
+
+INLINE pic16c62x_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == PIC16C620 ||
+ device->type() == PIC16C620A ||
+// device->type() == PIC16CR620A ||
+ device->type() == PIC16C621 ||
+ device->type() == PIC16C621A ||
+ device->type() == PIC16C622 ||
+ device->type() == PIC16C622A);
+ return (pic16c62x_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+
+/* opcode table entry */
+typedef struct _pic16c62x_opcode pic16c62x_opcode;
+struct _pic16c62x_opcode
+{
+ UINT8 cycles;
+ void (*function)(pic16c62x_state *);
+};
+/* instruction list entry */
+typedef struct _pic16c62x_instruction pic16c62x_instruction;
+struct _pic16c62x_instruction
+{
+ char *format;
+ void (*function)(pic16c62x_state *);
+ UINT8 cycles;
+};
+
+
+INLINE void update_internalram_ptr(pic16c62x_state *cpustate)
+{
+ cpustate->internalram = (UINT8 *)cpustate->data->get_write_ptr(0x00);
+}
+
+#define PIC16C62x_RDOP(A) (cpustate->direct->read_decrypted_word((A)<<1))
+#define PIC16C62x_RAM_RDMEM(A) ((UINT8)cpustate->data->read_byte(A))
+#define PIC16C62x_RAM_WRMEM(A,V) (cpustate->data->write_byte(A,V))
+#define PIC16C62x_In(Port) ((UINT8)cpustate->io->read_byte((Port)))
+#define PIC16C62x_Out(Port,Value) (cpustate->io->write_byte((Port),Value))
+/************ Read the state of the T0 Clock input signal ************/
+#define PIC16C62x_T0_In (cpustate->io->read_byte(PIC16C62x_T0) >> 4)
+
+#define M_RDRAM(A) (((A) == 0) ? cpustate->internalram[0] : PIC16C62x_RAM_RDMEM(A))
+#define M_WRTRAM(A,V) do { if ((A) == 0) cpustate->internalram[0] = (V); else PIC16C62x_RAM_WRMEM(A,V); } while (0)
+#define M_RDOP(A) PIC16C62x_RDOP(A)
+#define P_IN(A) PIC16C62x_In(A)
+#define P_OUT(A,V) PIC16C62x_Out(A,V)
+#define S_T0_IN PIC16C62x_T0_In
+#define ADDR_MASK 0x1fff
+
+
+
+#define TMR0 internalram[1]
+#define PCL internalram[2]
+#define STATUS internalram[3]
+#define FSR internalram[4]
+#define PORTA internalram[5]
+#define PORTB internalram[6]
+#define INDF M_RDRAM(cpustate->FSR)
+
+#define RISING_EDGE_T0 (( (int)(T0_in - cpustate->old_T0) > 0) ? 1 : 0)
+#define FALLING_EDGE_T0 (( (int)(T0_in - cpustate->old_T0) < 0) ? 1 : 0)
+
+
+/******** The following is the Status Flag register definition. *********/
+ /* | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | */
+ /* |IRP|RP1|RP0| TO | PD | Z | DC | C | */
+#define IRP_FLAG 0x80 /* IRP Register Bank Select bit (used for indirect addressing) */
+#define RP1_FLAG 0x40 /* RP1 Register Bank Select bits (used for direct addressing) */
+#define RP0_FLAG 0x20 /* RP0 Register Bank Select bits (used for direct addressing) */
+#define TO_FLAG 0x10 /* TO Time Out flag (WatchDog) */
+#define PD_FLAG 0x08 /* PD Power Down flag */
+#define Z_FLAG 0x04 /* Z Zero Flag */
+#define DC_FLAG 0x02 /* DC Digit Carry/Borrow flag (Nibble) */
+#define C_FLAG 0x01 /* C Carry/Borrow Flag (Byte) */
+
+#define IRP (cpustate->STATUS & IRP_FLAG)
+#define RP1 (cpustate->STATUS & RP1_FLAG)
+#define RP0 (cpustate->STATUS & RP0_FLAG)
+#define TO (cpustate->STATUS & TO_FLAG)
+#define PD (cpustate->STATUS & PD_FLAG)
+#define ZERO (cpustate->STATUS & Z_FLAG)
+#define DC (cpustate->STATUS & DC_FLAG)
+#define CARRY (cpustate->STATUS & C_FLAG)
+
+#define ADDR ((cpustate->opcode.b.l & 0x7f) | (RP0 << 2))
+
+/******** The following is the Option Flag register definition. *********/
+ /* | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | */
+ /* | RBPU | INTEDG | TOCS | TOSE | PSA | PS | */
+#define RBPU_FLAG 0x80 /* RBPU Pull-up Enable */
+#define INTEDG_FLAG 0x40 /* INTEDG Interrupt Edge Select */
+#define T0CS_FLAG 0x20 /* TOCS Timer 0 clock source select */
+#define T0SE_FLAG 0x10 /* TOSE Timer 0 clock source edge select */
+#define PSA_FLAG 0x08 /* PSA Prescaler Assignment bit */
+#define PS_REG 0x07 /* PS Prescaler Rate select */
+
+#define T0CS (cpustate->OPTION & T0CS_FLAG)
+#define T0SE (cpustate->OPTION & T0SE_FLAG)
+#define PSA (cpustate->OPTION & PSA_FLAG)
+#define PS (cpustate->OPTION & PS_REG)
+
+/******** The following is the Config Flag register definition. *********/
+ /* | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | */
+ /* | CP | | BODEN | CP | PWRTE | WDTE | FOSC | */
+ /* CP Code Protect (ROM read protect) */
+#define BODEN_FLAG 0x40 /* BODEN Brown-out Reset Enable */
+#define PWRTE_FLAG 0x08 /* PWRTE Power-up Timer Enable */
+#define WDTE_FLAG 0x04 /* WDTE WatchDog Timer enable */
+#define FOSC_FLAG 0x03 /* FOSC Oscillator source select */
+
+#define WDTE (cpustate->CONFIG & WDTE_FLAG)
+#define FOSC (cpustate->CONFIG & FOSC_FLAG)
+
+
+/************************************************************************
+ * Shortcuts
+ ************************************************************************/
+
+#define CLR(flagreg, flag) ( flagreg &= (UINT8)(~flag) )
+#define SET(flagreg, flag) ( flagreg |= flag )
+
+
+/* Easy bit position selectors */
+#define POS ((cpustate->opcode.w.l >> 7) & 7)
+static const unsigned int bit_clr[8] = { 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f };
+static const unsigned int bit_set[8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
+
+
+
+INLINE void CALCULATE_Z_FLAG(pic16c62x_state *cpustate)
+{
+ if (cpustate->ALU == 0) SET(cpustate->STATUS, Z_FLAG);
+ else CLR(cpustate->STATUS, Z_FLAG);
+}
+
+INLINE void CALCULATE_ADD_CARRY(pic16c62x_state *cpustate)
+{
+ if ((UINT8)(cpustate->old_data) > (UINT8)(cpustate->ALU)) {
+ SET(cpustate->STATUS, C_FLAG);
+ }
+ else {
+ CLR(cpustate->STATUS, C_FLAG);
+ }
+}
+
+INLINE void CALCULATE_ADD_DIGITCARRY(pic16c62x_state *cpustate)
+{
+ if (((UINT8)(cpustate->old_data) & 0x0f) > ((UINT8)(cpustate->ALU) & 0x0f)) {
+ SET(cpustate->STATUS, DC_FLAG);
+ }
+ else {
+ CLR(cpustate->STATUS, DC_FLAG);
+ }
+}
+
+INLINE void CALCULATE_SUB_CARRY(pic16c62x_state *cpustate)
+{
+ if ((UINT8)(cpustate->old_data) < (UINT8)(cpustate->ALU)) {
+ CLR(cpustate->STATUS, C_FLAG);
+ }
+ else {
+ SET(cpustate->STATUS, C_FLAG);
+ }
+}
+
+INLINE void CALCULATE_SUB_DIGITCARRY(pic16c62x_state *cpustate)
+{
+ if (((UINT8)(cpustate->old_data) & 0x0f) < ((UINT8)(cpustate->ALU) & 0x0f)) {
+ CLR(cpustate->STATUS, DC_FLAG);
+ }
+ else {
+ SET(cpustate->STATUS, DC_FLAG);
+ }
+}
+
+
+
+INLINE UINT16 POP_STACK(pic16c62x_state *cpustate)
+{
+ UINT16 data = cpustate->STACK[7];
+ cpustate->STACK[7] = cpustate->STACK[6];
+ cpustate->STACK[6] = cpustate->STACK[5];
+ cpustate->STACK[5] = cpustate->STACK[4];
+ cpustate->STACK[4] = cpustate->STACK[3];
+ cpustate->STACK[3] = cpustate->STACK[2];
+ cpustate->STACK[2] = cpustate->STACK[1];
+ cpustate->STACK[1] = cpustate->STACK[0];
+ return (data & ADDR_MASK);
+}
+INLINE void PUSH_STACK(pic16c62x_state *cpustate, UINT16 data)
+{
+ cpustate->STACK[0] = cpustate->STACK[1];
+ cpustate->STACK[1] = cpustate->STACK[2];
+ cpustate->STACK[2] = cpustate->STACK[3];
+ cpustate->STACK[3] = cpustate->STACK[4];
+ cpustate->STACK[4] = cpustate->STACK[5];
+ cpustate->STACK[5] = cpustate->STACK[6];
+ cpustate->STACK[6] = cpustate->STACK[7];
+ cpustate->STACK[7] = (data & ADDR_MASK);
+}
+
+
+
+INLINE UINT8 GET_REGFILE(pic16c62x_state *cpustate, offs_t addr) /* Read from internal memory */
+{
+ UINT8 data;
+
+ if (addr == 0) { /* Indirect addressing */
+ addr = (cpustate->FSR & cpustate->picRAMmask);
+ }
+
+ switch(addr)
+ {
+ case 0x00: /* Not an actual register, so return 0 */
+ case 0x80:
+ data = 0;
+ break;
+ case 0x02:
+ case 0x03:
+ case 0x0b:
+ case 0x82:
+ case 0x83:
+ case 0x8b:
+ data = M_RDRAM(addr & 0x7f);
+ break;
+ case 0x84:
+ case 0x04: data = (cpustate->FSR | (UINT8)(~cpustate->picRAMmask));
+ break;
+ case 0x05: data = P_IN(0);
+ data &= cpustate->TRISA;
+ data |= ((UINT8)(~cpustate->TRISA) & cpustate->PORTA);
+ data &= 0x1f; /* 5-bit port (only lower 5 bits used) */
+ break;
+ case 0x06: data = P_IN(1);
+ data &= cpustate->TRISB;
+ data |= ((UINT8)(~cpustate->TRISB) & cpustate->PORTB);
+ break;
+ case 0x8a:
+ case 0x0a: data = cpustate->PCLATH;
+ break;
+ case 0x81: data = cpustate->OPTION;
+ break;
+ case 0x85: data = cpustate->TRISA;
+ break;
+ case 0x86: data = cpustate->TRISB;
+ break;
+ default: data = M_RDRAM(addr);
+ break;
+ }
+ return data;
+}
+
+INLINE void STORE_REGFILE(pic16c62x_state *cpustate, offs_t addr, UINT8 data) /* Write to internal memory */
+{
+ if (addr == 0) { /* Indirect addressing */
+ addr = (cpustate->FSR & cpustate->picRAMmask);
+ }
+
+ switch(addr)
+ {
+ case 0x80:
+ case 0x00: /* Not an actual register, nothing to save */
+ break;
+ case 0x01: cpustate->delay_timer = 2; /* Timer starts after next two instructions */
+ if (PSA == 0) cpustate->prescaler = 0; /* Must clear the Prescaler */
+ cpustate->TMR0 = data;
+ break;
+ case 0x82:
+ case 0x02: cpustate->PCL = data;
+ cpustate->PC = (cpustate->PCLATH << 8) | data;
+ break;
+ case 0x83:
+ case 0x03: cpustate->STATUS &= (UINT8)(~(IRP_FLAG|RP1_FLAG|RP0_FLAG)); cpustate->STATUS |= (data & (IRP_FLAG|RP1_FLAG|RP0_FLAG));
+ break;
+ case 0x84:
+ case 0x04: cpustate->FSR = (data | (UINT8)(~cpustate->picRAMmask));
+ break;
+ case 0x05: data &= 0x1f; /* 5-bit port (only lower 5 bits used) */
+ P_OUT(0,data & (UINT8)(~cpustate->TRISA)); cpustate->PORTA = data;
+ break;
+ case 0x06: P_OUT(1,data & (UINT8)(~cpustate->TRISB)); cpustate->PORTB = data;
+ break;
+ case 0x8a:
+ case 0x0a:
+ cpustate->PCLATH = data & 0x1f;
+ M_WRTRAM(0x0a, cpustate->PCLATH);
+ break;
+ case 0x8b:
+ case 0x0b: M_WRTRAM(0x0b, data);
+ break;
+ case 0x81: cpustate->OPTION = data;
+ M_WRTRAM(0x81, data);
+ break;
+ case 0x85: if (cpustate->TRISA != data)
+ {
+ cpustate->TRISA = data | 0xf0;
+ P_OUT(2,cpustate->TRISA);
+ P_OUT(0,cpustate->PORTA & (UINT8)(~cpustate->TRISA) & 0x0f);
+ M_WRTRAM(addr, data);
+ }
+ break;
+ case 0x86: if (cpustate->TRISB != data)
+ {
+ cpustate->TRISB = data;
+ P_OUT(3,cpustate->TRISB);
+ P_OUT(1,cpustate->PORTB & (UINT8)(~cpustate->TRISB));
+ M_WRTRAM(addr, data);
+ }
+ break;
+ default: M_WRTRAM(addr, data);
+ break;
+ }
+}
+
+
+INLINE void STORE_RESULT(pic16c62x_state *cpustate, offs_t addr, UINT8 data)
+{
+ if (cpustate->opcode.b.l & 0x80)
+ {
+ STORE_REGFILE(cpustate, addr, data);
+ }
+ else
+ {
+ cpustate->W = data;
+ }
+}
+
+
+/************************************************************************
+ * Emulate the Instructions
+ ************************************************************************/
+
+/* This following function is here to fill in the void for */
+/* the opcode call function. This function is never called. */
+
+
+static void illegal(pic16c62x_state *cpustate)
+{
+ logerror("PIC16C62x: PC=%03x, Illegal opcode = %04x\n", (cpustate->PC-1), cpustate->opcode.w.l);
+}
+
+
+static void addwf(pic16c62x_state *cpustate)
+{
+ cpustate->old_data = GET_REGFILE(cpustate, ADDR);
+ cpustate->ALU = cpustate->old_data + cpustate->W;
+ STORE_RESULT(cpustate, ADDR, cpustate->ALU);
+ CALCULATE_Z_FLAG(cpustate);
+ CALCULATE_ADD_CARRY(cpustate);
+ CALCULATE_ADD_DIGITCARRY(cpustate);
+}
+
+static void addlw(pic16c62x_state *cpustate)
+{
+ cpustate->ALU = (cpustate->opcode.b.l & 0xff) + cpustate->W;
+ cpustate->W = cpustate->ALU;
+ CALCULATE_Z_FLAG(cpustate);
+ CALCULATE_ADD_CARRY(cpustate);
+ CALCULATE_ADD_DIGITCARRY(cpustate);
+}
+
+static void andwf(pic16c62x_state *cpustate)
+{
+ cpustate->ALU = GET_REGFILE(cpustate, ADDR) & cpustate->W;
+ STORE_RESULT(cpustate, ADDR, cpustate->ALU);
+ CALCULATE_Z_FLAG(cpustate);
+}
+
+static void andlw(pic16c62x_state *cpustate)
+{
+ cpustate->ALU = cpustate->opcode.b.l & cpustate->W;
+ cpustate->W = cpustate->ALU;
+ CALCULATE_Z_FLAG(cpustate);
+}
+
+static void bcf(pic16c62x_state *cpustate)
+{
+ cpustate->ALU = GET_REGFILE(cpustate, ADDR);
+ cpustate->ALU &= bit_clr[POS];
+ STORE_REGFILE(cpustate, ADDR, cpustate->ALU);
+}
+
+static void bsf(pic16c62x_state *cpustate)
+{
+ cpustate->ALU = GET_REGFILE(cpustate, ADDR);
+ cpustate->ALU |= bit_set[POS];
+ STORE_REGFILE(cpustate, ADDR, cpustate->ALU);
+}
+
+static void btfss(pic16c62x_state *cpustate)
+{
+ if ((GET_REGFILE(cpustate, ADDR) & bit_set[POS]) == bit_set[POS])
+ {
+ cpustate->PC++ ;
+ cpustate->PCL = cpustate->PC & 0xff;
+ cpustate->inst_cycles += 1; /* Add NOP cycles */
+ }
+}
+
+static void btfsc(pic16c62x_state *cpustate)
+{
+ if ((GET_REGFILE(cpustate, ADDR) & bit_set[POS]) == 0)
+ {
+ cpustate->PC++ ;
+ cpustate->PCL = cpustate->PC & 0xff;
+ cpustate->inst_cycles += 1; /* Add NOP cycles */
+ }
+}
+
+static void call(pic16c62x_state *cpustate)
+{
+ PUSH_STACK(cpustate, cpustate->PC);
+ cpustate->PC = ((cpustate->PCLATH & 0x18) << 8) | (cpustate->opcode.w.l & 0x7ff);
+ cpustate->PC &= ADDR_MASK;
+ cpustate->PCL = cpustate->PC & 0xff;
+}
+
+static void clrw(pic16c62x_state *cpustate)
+{
+ cpustate->W = 0;
+ SET(cpustate->STATUS, Z_FLAG);
+}
+
+static void clrf(pic16c62x_state *cpustate)
+{
+ STORE_REGFILE(cpustate, ADDR, 0);
+ SET(cpustate->STATUS, Z_FLAG);
+}
+
+static void clrwdt(pic16c62x_state *cpustate)
+{
+ cpustate->WDT = 0;
+ if (PSA) cpustate->prescaler = 0;
+ SET(cpustate->STATUS, TO_FLAG);
+ SET(cpustate->STATUS, PD_FLAG);
+}
+
+static void comf(pic16c62x_state *cpustate)
+{
+ cpustate->ALU = (UINT8)(~(GET_REGFILE(cpustate, ADDR)));
+ STORE_RESULT(cpustate, ADDR, cpustate->ALU);
+ CALCULATE_Z_FLAG(cpustate);
+}
+
+static void decf(pic16c62x_state *cpustate)
+{
+ cpustate->ALU = GET_REGFILE(cpustate, ADDR) - 1;
+ STORE_RESULT(cpustate, ADDR, cpustate->ALU);
+ CALCULATE_Z_FLAG(cpustate);
+}
+
+static void decfsz(pic16c62x_state *cpustate)
+{
+ cpustate->ALU = GET_REGFILE(cpustate, ADDR) - 1;
+ STORE_RESULT(cpustate, ADDR, cpustate->ALU);
+ if (cpustate->ALU == 0)
+ {
+ cpustate->PC++ ;
+ cpustate->PCL = cpustate->PC & 0xff;
+ cpustate->inst_cycles += 1; /* Add NOP cycles */
+ }
+}
+
+static void goto_op(pic16c62x_state *cpustate)
+{
+ cpustate->PC = ((cpustate->PCLATH & 0x18) << 8) | (cpustate->opcode.w.l & 0x7ff);
+ cpustate->PC &= ADDR_MASK;
+ cpustate->PCL = cpustate->PC & 0xff;
+}
+
+static void incf(pic16c62x_state *cpustate)
+{
+ cpustate->ALU = GET_REGFILE(cpustate, ADDR) + 1;
+ STORE_RESULT(cpustate, ADDR, cpustate->ALU);
+ CALCULATE_Z_FLAG(cpustate);
+}
+
+static void incfsz(pic16c62x_state *cpustate)
+{
+ cpustate->ALU = GET_REGFILE(cpustate, ADDR) + 1;
+ STORE_RESULT(cpustate, ADDR, cpustate->ALU);
+ if (cpustate->ALU == 0)
+ {
+ cpustate->PC++ ;
+ cpustate->PCL = cpustate->PC & 0xff;
+ cpustate->inst_cycles += 1; /* Add NOP cycles */
+ }
+}
+
+static void iorlw(pic16c62x_state *cpustate)
+{
+ cpustate->ALU = cpustate->opcode.b.l | cpustate->W;
+ cpustate->W = cpustate->ALU;
+ CALCULATE_Z_FLAG(cpustate);
+}
+
+static void iorwf(pic16c62x_state *cpustate)
+{
+ cpustate->ALU = GET_REGFILE(cpustate, ADDR) | cpustate->W;
+ STORE_RESULT(cpustate, ADDR, cpustate->ALU);
+ CALCULATE_Z_FLAG(cpustate);
+}
+
+static void movf(pic16c62x_state *cpustate)
+{
+ cpustate->ALU = GET_REGFILE(cpustate, ADDR);
+ STORE_RESULT(cpustate, ADDR, cpustate->ALU);
+ CALCULATE_Z_FLAG(cpustate);
+}
+
+static void movlw(pic16c62x_state *cpustate)
+{
+ cpustate->W = cpustate->opcode.b.l;
+}
+
+static void movwf(pic16c62x_state *cpustate)
+{
+ STORE_REGFILE(cpustate, ADDR, cpustate->W);
+}
+
+static void nop(pic16c62x_state *cpustate)
+{
+ /* Do nothing */
+}
+
+static void option(pic16c62x_state *cpustate)
+{
+ cpustate->OPTION = cpustate->W;
+}
+
+static void retlw(pic16c62x_state *cpustate)
+{
+ cpustate->W = cpustate->opcode.b.l;
+ cpustate->PC = POP_STACK(cpustate);
+ cpustate->PCL = cpustate->PC & 0xff;
+}
+
+static void returns(pic16c62x_state *cpustate)
+{
+ cpustate->PC = POP_STACK(cpustate);
+ cpustate->PCL = cpustate->PC & 0xff;
+}
+
+static void retfie(pic16c62x_state *cpustate)
+{
+ cpustate->PC = POP_STACK(cpustate);
+ cpustate->PCL = cpustate->PC & 0xff;
+ //INTCON(7)=1;
+}
+
+static void rlf(pic16c62x_state *cpustate)
+{
+ cpustate->ALU = GET_REGFILE(cpustate, ADDR);
+ cpustate->ALU <<= 1;
+ if (cpustate->STATUS & C_FLAG) cpustate->ALU |= 1;
+ if (GET_REGFILE(cpustate, ADDR) & 0x80) SET(cpustate->STATUS, C_FLAG);
+ else CLR(cpustate->STATUS, C_FLAG);
+ STORE_RESULT(cpustate, ADDR, cpustate->ALU);
+}
+
+static void rrf(pic16c62x_state *cpustate)
+{
+ cpustate->ALU = GET_REGFILE(cpustate, ADDR);
+ cpustate->ALU >>= 1;
+ if (cpustate->STATUS & C_FLAG) cpustate->ALU |= 0x80;
+ if (GET_REGFILE(cpustate, ADDR) & 1) SET(cpustate->STATUS, C_FLAG);
+ else CLR(cpustate->STATUS, C_FLAG);
+ STORE_RESULT(cpustate, ADDR, cpustate->ALU);
+}
+
+static void sleepic(pic16c62x_state *cpustate)
+{
+ if (WDTE) cpustate->WDT = 0;
+ if (PSA) cpustate->prescaler = 0;
+ SET(cpustate->STATUS, TO_FLAG);
+ CLR(cpustate->STATUS, PD_FLAG);
+}
+
+static void subwf(pic16c62x_state *cpustate)
+{
+ cpustate->old_data = GET_REGFILE(cpustate, ADDR);
+ cpustate->ALU = cpustate->old_data - cpustate->W;
+ STORE_RESULT(cpustate, ADDR, cpustate->ALU);
+ CALCULATE_Z_FLAG(cpustate);
+ CALCULATE_SUB_CARRY(cpustate);
+ CALCULATE_SUB_DIGITCARRY(cpustate);
+}
+
+static void sublw(pic16c62x_state *cpustate)
+{
+ cpustate->ALU = (cpustate->opcode.b.l & 0xff) - cpustate->W;
+ cpustate->W = cpustate->ALU;
+ CALCULATE_Z_FLAG(cpustate);
+ CALCULATE_SUB_CARRY(cpustate);
+ CALCULATE_SUB_DIGITCARRY(cpustate);
+}
+
+static void swapf(pic16c62x_state *cpustate)
+{
+ cpustate->ALU = ((GET_REGFILE(cpustate, ADDR) << 4) & 0xf0);
+ cpustate->ALU |= ((GET_REGFILE(cpustate, ADDR) >> 4) & 0x0f);
+ STORE_RESULT(cpustate, ADDR, cpustate->ALU);
+}
+
+static void tris(pic16c62x_state *cpustate)
+{
+
+ switch(cpustate->opcode.b.l & 0x7)
+ {
+ case 05: STORE_REGFILE(cpustate, 0x85, cpustate->W); break;
+ case 06: STORE_REGFILE(cpustate, 0x86, cpustate->W); break;
+ default: illegal(cpustate); break;
+ }
+}
+
+static void xorlw(pic16c62x_state *cpustate)
+{
+ cpustate->ALU = cpustate->W ^ cpustate->opcode.b.l;
+ cpustate->W = cpustate->ALU;
+ CALCULATE_Z_FLAG(cpustate);
+}
+
+static void xorwf(pic16c62x_state *cpustate)
+{
+ cpustate->ALU = GET_REGFILE(cpustate, ADDR) ^ cpustate->W;
+ STORE_RESULT(cpustate, ADDR, cpustate->ALU);
+ CALCULATE_Z_FLAG(cpustate);
+}
+
+
+/***********************************************************************
+ * Instruction Table (Format, Instruction, Cycles)
+ ***********************************************************************/
+
+static const pic16c62x_instruction instructiontable[]=
+{
+ {(char *)"000111dfffffff", addwf, 1},
+ {(char *)"000101dfffffff", andwf, 1},
+ {(char *)"0000011fffffff", clrf, 1},
+ {(char *)"00000100000011", clrw, 1},
+ {(char *)"001001dfffffff", comf, 1},
+ {(char *)"000011dfffffff", decf, 1},
+ {(char *)"001011dfffffff", decfsz, 1},
+ {(char *)"001010dfffffff", incf, 1},
+ {(char *)"001111dfffffff", incfsz, 1},
+ {(char *)"000100dfffffff", iorwf, 1},
+ {(char *)"001000dfffffff", movf, 1},
+ {(char *)"0000001fffffff", movwf, 1},
+ {(char *)"0000000xx00000", nop, 1},
+ {(char *)"001101dfffffff", rlf, 1},
+ {(char *)"001100dfffffff", rrf, 1},
+ {(char *)"000010dfffffff", subwf, 1},
+ {(char *)"001110dfffffff", swapf, 1},
+ {(char *)"000110dfffffff", xorwf, 1},
+ {(char *)"0100bbbfffffff", bcf, 1},
+ {(char *)"0101bbbfffffff", bsf, 1},
+ {(char *)"0110bbbfffffff", btfsc, 1},
+ {(char *)"0111bbbfffffff", btfss, 1},
+ {(char *)"11111xkkkkkkkk", addlw, 1},
+ {(char *)"111001kkkkkkkk", andlw, 1},
+ {(char *)"100aaaaaaaaaaa", call, 2},
+ {(char *)"101aaaaaaaaaaa", goto_op, 2},
+ {(char *)"111000kkkkkkkk", iorlw, 1},
+ {(char *)"1100xxkkkkkkkk", movlw, 1},
+ {(char *)"00000000001001", retfie, 2},
+ {(char *)"1101xxkkkkkkkk", retlw, 2},
+ {(char *)"00000000001000", returns, 2},
+ {(char *)"00000001100011", sleepic, 1},
+ {(char *)"11110xkkkkkkkk", sublw, 1},
+ {(char *)"111010kkkkkkkk", xorlw, 1},
+ {(char *)"00000001100100", clrwdt, 1},
+ {(char *)"00000001100010", option, 1}, // deprecated
+ {(char *)"00000001100fff", tris, 1}, // deprecated
+ {NULL, NULL, 0}
+};
+
+/***********************************************************************
+ * Opcode Table (Cycles, Instruction)
+ ***********************************************************************/
+
+static pic16c62x_opcode opcode_table[16384];
+
+/***********************************************************************
+ * Opcode Table build function
+ ***********************************************************************/
+
+static void build_opcode_table(void)
+{
+int instr,mask,bits;
+int a;
+
+ // defaults
+ for ( a = 0; a < 16384; a++)
+ {
+ opcode_table[a].cycles = 0;
+ opcode_table[a].function = illegal;
+ }
+ // build table
+ for( instr = 0; instructiontable[instr].cycles != 0; instr++)
+ {
+ bits=0;
+ mask=0;
+ for ( a = 0; a < 14; a++)
+ {
+ switch (instructiontable[instr].format[a])
+ {
+ case '0':
+ bits = bits << 1;
+ mask = (mask << 1) | 1;
+ break;
+ case '1':
+ bits = (bits << 1) | 1;
+ mask = (mask << 1) | 1;
+ break;
+ default:
+ bits = bits << 1;
+ mask = mask << 1;
+ break;
+ }
+ }
+ for ( a = 0; a < 16384; a++)
+ {
+ if (((a & mask) == bits) && (opcode_table[a].cycles == 0))
+ {
+ opcode_table[a].cycles = instructiontable[instr].cycles;
+ opcode_table[a].function = instructiontable[instr].function;
+ }
+ }
+ }
+}
+
+/****************************************************************************
+ * Inits CPU emulation
+ ****************************************************************************/
+
+static CPU_INIT( pic16c62x )
+{
+ pic16c62x_state *cpustate = get_safe_token(device);
+
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+ cpustate->data = device->space(AS_DATA);
+ cpustate->io = device->space(AS_IO);
+
+ cpustate->CONFIG = 0x3fff;
+
+ /* ensure the internal ram pointers are set before get_info is called */
+ update_internalram_ptr(cpustate);
+
+ build_opcode_table();
+
+ device->save_item(NAME(cpustate->W));
+ device->save_item(NAME(cpustate->ALU));
+ device->save_item(NAME(cpustate->OPTION));
+ device->save_item(NAME(cpustate->PCLATH));
+ device->save_item(NAME(cpustate->TMR0));
+ device->save_item(NAME(cpustate->PCL));
+ device->save_item(NAME(cpustate->STATUS));
+ device->save_item(NAME(cpustate->FSR));
+ device->save_item(NAME(cpustate->PORTA));
+ device->save_item(NAME(cpustate->PORTB));
+ device->save_item(NAME(cpustate->TRISA));
+ device->save_item(NAME(cpustate->TRISB));
+ device->save_item(NAME(cpustate->old_T0));
+ device->save_item(NAME(cpustate->old_data));
+ device->save_item(NAME(cpustate->picRAMmask));
+ device->save_item(NAME(cpustate->WDT));
+ device->save_item(NAME(cpustate->prescaler));
+ device->save_item(NAME(cpustate->STACK[0]));
+ device->save_item(NAME(cpustate->STACK[1]));
+ device->save_item(NAME(cpustate->STACK[2]));
+ device->save_item(NAME(cpustate->STACK[3]));
+ device->save_item(NAME(cpustate->STACK[4]));
+ device->save_item(NAME(cpustate->STACK[5]));
+ device->save_item(NAME(cpustate->STACK[6]));
+ device->save_item(NAME(cpustate->STACK[7]));
+ device->save_item(NAME(cpustate->PC));
+ device->save_item(NAME(cpustate->PREVPC));
+ device->save_item(NAME(cpustate->CONFIG));
+ device->save_item(NAME(cpustate->opcode.d));
+ device->save_item(NAME(cpustate->delay_timer));
+ device->save_item(NAME(cpustate->picmodel));
+ device->save_item(NAME(cpustate->reset_vector));
+
+ device->save_item(NAME(cpustate->icount));
+ device->save_item(NAME(cpustate->temp_config));
+ device->save_item(NAME(cpustate->inst_cycles));
+}
+
+
+/****************************************************************************
+ * Reset registers to their initial values
+ ****************************************************************************/
+
+static void pic16c62x_reset_regs(pic16c62x_state *cpustate)
+{
+ cpustate->PC = cpustate->reset_vector;
+ cpustate->TRISA = 0x1f;
+ cpustate->TRISB = 0xff;
+ cpustate->OPTION = 0xff;
+ cpustate->STATUS = 0x18;
+ cpustate->PCL = 0;
+ cpustate->FSR |= (UINT8)(~cpustate->picRAMmask);
+ cpustate->PORTA = 0;
+ cpustate->prescaler = 0;
+ cpustate->delay_timer = 0;
+ cpustate->old_T0 = 0;
+ cpustate->inst_cycles = 0;
+ PIC16C62x_RAM_WRMEM(0x85,cpustate->TRISA);
+ PIC16C62x_RAM_WRMEM(0x86,cpustate->TRISB);
+ PIC16C62x_RAM_WRMEM(0x81,cpustate->OPTION);
+}
+
+static void pic16c62x_soft_reset(pic16c62x_state *cpustate)
+{
+ SET(cpustate->STATUS, (TO_FLAG | PD_FLAG | Z_FLAG | DC_FLAG | C_FLAG));
+ pic16c62x_reset_regs(cpustate);
+}
+
+void pic16c62x_set_config(device_t *cpu, int data)
+{
+ pic16c62x_state *cpustate = get_safe_token(cpu);
+
+ logerror("Writing %04x to the PIC16C62x configuration bits\n",data);
+ cpustate->CONFIG = (data & 0x3fff);
+}
+
+
+/****************************************************************************
+ * Shut down CPU emulation
+ ****************************************************************************/
+
+static CPU_EXIT( pic16c62x )
+{
+ /* nothing to do */
+}
+
+
+/****************************************************************************
+ * WatchDog
+ ****************************************************************************/
+
+static void pic16c62x_update_watchdog(pic16c62x_state *cpustate, int counts)
+{
+ /* TODO: needs updating */
+ /* WatchDog is set up to count 18,000 (0x464f hex) ticks to provide */
+ /* the timeout period of 0.018ms based on a 4MHz input clock. */
+ /* Note: the 4MHz clock should be divided by the PIC16C5x_CLOCK_DIVIDER */
+ /* which effectively makes the PIC run at 1MHz internally. */
+
+ /* If the current instruction is CLRWDT or SLEEP, don't update the WDT */
+
+ if ((cpustate->opcode.w.l != 0x64) && (cpustate->opcode.w.l != 0x63))
+ {
+ UINT16 old_WDT = cpustate->WDT;
+
+ cpustate->WDT -= counts;
+
+ if (cpustate->WDT > 0x464f) {
+ cpustate->WDT = 0x464f - (0xffff - cpustate->WDT);
+ }
+
+ if (((old_WDT != 0) && (old_WDT < cpustate->WDT)) || (cpustate->WDT == 0))
+ {
+ if (PSA) {
+ cpustate->prescaler++;
+ if (cpustate->prescaler >= (1 << PS)) { /* Prescale values from 1 to 128 */
+ cpustate->prescaler = 0;
+ CLR(cpustate->STATUS, TO_FLAG);
+ pic16c62x_soft_reset(cpustate);
+ }
+ }
+ else {
+ CLR(cpustate->STATUS, TO_FLAG);
+ pic16c62x_soft_reset(cpustate);
+ }
+ }
+ }
+}
+
+
+/****************************************************************************
+ * Update Timer
+ ****************************************************************************/
+
+static void pic16c62x_update_timer(pic16c62x_state *cpustate, int counts)
+{
+ if (PSA == 0) {
+ cpustate->prescaler += counts;
+ if (cpustate->prescaler >= (2 << PS)) { /* Prescale values from 2 to 256 */
+ cpustate->TMR0 += (cpustate->prescaler / (2 << PS));
+ cpustate->prescaler %= (2 << PS); /* Overflow prescaler */
+ }
+ }
+ else {
+ cpustate->TMR0 += counts;
+ }
+}
+
+
+/****************************************************************************
+ * Execute IPeriod. Return 0 if emulation should be stopped
+ ****************************************************************************/
+
+static CPU_EXECUTE( pic16c62x )
+{
+ pic16c62x_state *cpustate = get_safe_token(device);
+ UINT8 T0_in;
+
+ update_internalram_ptr(cpustate);
+
+ do
+ {
+ if (PD == 0) /* Sleep Mode */
+ {
+ cpustate->inst_cycles = 1;
+ debugger_instruction_hook(device, cpustate->PC);
+ if (WDTE) {
+ pic16c62x_update_watchdog(cpustate, 1);
+ }
+ }
+ else
+ {
+ cpustate->PREVPC = cpustate->PC;
+
+ debugger_instruction_hook(device, cpustate->PC);
+
+ cpustate->opcode.d = M_RDOP(cpustate->PC);
+ cpustate->PC++;
+ cpustate->PCL++;
+
+ cpustate->inst_cycles = opcode_table[cpustate->opcode.w.l & 16383].cycles;
+ (*opcode_table[cpustate->opcode.w.l & 16383].function)(cpustate);
+
+ if (T0CS) { /* Count mode */
+ T0_in = S_T0_IN;
+ if (T0_in) T0_in = 1;
+ if (T0SE) { /* Count falling edge T0 input */
+ if (FALLING_EDGE_T0) {
+ pic16c62x_update_timer(cpustate, 1);
+ }
+ }
+ else { /* Count rising edge T0 input */
+ if (RISING_EDGE_T0) {
+ pic16c62x_update_timer(cpustate, 1);
+ }
+ }
+ cpustate->old_T0 = T0_in;
+ }
+ else { /* Timer mode */
+ if (cpustate->delay_timer) {
+ cpustate->delay_timer--;
+ }
+ else {
+ pic16c62x_update_timer(cpustate, cpustate->inst_cycles);
+ }
+ }
+ if (WDTE) {
+ pic16c62x_update_watchdog(cpustate, cpustate->inst_cycles);
+ }
+ }
+
+ cpustate->icount -= cpustate->inst_cycles;
+
+ } while (cpustate->icount > 0);
+}
+
+
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( pic16c62x )
+{
+ pic16c62x_state *cpustate = get_safe_token(device);
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + PIC16C62x_PC: cpustate->PC = info->i; cpustate->PCL = info->i & 0xff ;break;
+ /* This is actually not a stack pointer, but the stack contents */
+ /* Stack is a 8 level First In Last Out stack */
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + PIC16C62x_STK7: cpustate->STACK[7] = info->i; break;
+ case CPUINFO_INT_REGISTER + PIC16C62x_STK6: cpustate->STACK[6] = info->i; break;
+ case CPUINFO_INT_REGISTER + PIC16C62x_STK5: cpustate->STACK[5] = info->i; break;
+ case CPUINFO_INT_REGISTER + PIC16C62x_STK4: cpustate->STACK[4] = info->i; break;
+ case CPUINFO_INT_REGISTER + PIC16C62x_STK3: cpustate->STACK[3] = info->i; break;
+ case CPUINFO_INT_REGISTER + PIC16C62x_STK2: cpustate->STACK[2] = info->i; break;
+ case CPUINFO_INT_REGISTER + PIC16C62x_STK1: cpustate->STACK[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + PIC16C62x_STK0: cpustate->STACK[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + PIC16C62x_W: cpustate->W = info->i; break;
+ case CPUINFO_INT_REGISTER + PIC16C62x_ALU: cpustate->ALU = info->i; break;
+ case CPUINFO_INT_REGISTER + PIC16C62x_OPT: cpustate->OPTION = info->i & (RBPU_FLAG | INTEDG_FLAG | T0CS_FLAG | T0SE_FLAG | PSA_FLAG | PS_REG); break;
+ case CPUINFO_INT_REGISTER + PIC16C62x_TMR0: cpustate->TMR0 = info->i; break;
+ case CPUINFO_INT_REGISTER + PIC16C62x_WDT: cpustate->WDT = info->i; break;
+ case CPUINFO_INT_REGISTER + PIC16C62x_PSCL: cpustate->prescaler = info->i; break;
+ case CPUINFO_INT_REGISTER + PIC16C62x_PRTA: cpustate->PORTA = info->i & 0x1f; break;
+ case CPUINFO_INT_REGISTER + PIC16C62x_PRTB: cpustate->PORTB = info->i; break;
+ case CPUINFO_INT_REGISTER + PIC16C62x_FSR: cpustate->FSR = ((info->i & cpustate->picRAMmask) | (UINT8)(~cpustate->picRAMmask)); break;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+static CPU_GET_INFO( pic16c62x )
+{
+ pic16c62x_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(pic16c62x_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 1; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 4; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 2; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 2; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 2; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 12; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = -1; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 5; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = cpustate->PREVPC; break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + PIC16C62x_PC: info->i = cpustate->PC; break;
+ /* This is actually not a stack pointer, but the stack contents */
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + PIC16C62x_STK7: info->i = cpustate->STACK[7]; break;
+ case CPUINFO_INT_REGISTER + PIC16C62x_STK6: info->i = cpustate->STACK[6]; break;
+ case CPUINFO_INT_REGISTER + PIC16C62x_STK5: info->i = cpustate->STACK[5]; break;
+ case CPUINFO_INT_REGISTER + PIC16C62x_STK4: info->i = cpustate->STACK[4]; break;
+ case CPUINFO_INT_REGISTER + PIC16C62x_STK3: info->i = cpustate->STACK[3]; break;
+ case CPUINFO_INT_REGISTER + PIC16C62x_STK2: info->i = cpustate->STACK[2]; break;
+ case CPUINFO_INT_REGISTER + PIC16C62x_STK1: info->i = cpustate->STACK[1]; break;
+ case CPUINFO_INT_REGISTER + PIC16C62x_STK0: info->i = cpustate->STACK[0]; break;
+ case CPUINFO_INT_REGISTER + PIC16C62x_W: info->i = cpustate->W; break;
+ case CPUINFO_INT_REGISTER + PIC16C62x_ALU: info->i = cpustate->ALU; break;
+ case CPUINFO_INT_REGISTER + PIC16C62x_STR: info->i = cpustate->STATUS; break;
+ case CPUINFO_INT_REGISTER + PIC16C62x_OPT: info->i = cpustate->OPTION; break;
+ case CPUINFO_INT_REGISTER + PIC16C62x_TMR0: info->i = cpustate->TMR0; break;
+ case CPUINFO_INT_REGISTER + PIC16C62x_WDT: info->i = cpustate->WDT; break;
+ case CPUINFO_INT_REGISTER + PIC16C62x_PSCL: info->i = cpustate->prescaler; break;
+ case CPUINFO_INT_REGISTER + PIC16C62x_PRTA: info->i = cpustate->PORTA; break;
+ case CPUINFO_INT_REGISTER + PIC16C62x_PRTB: info->i = cpustate->PORTB; break;
+ case CPUINFO_INT_REGISTER + PIC16C62x_FSR: info->i = ((cpustate->FSR & cpustate->picRAMmask) | (UINT8)(~cpustate->picRAMmask)); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(pic16c62x); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(pic16c62x); break;
+ case CPUINFO_FCT_RESET: /* set per-CPU */ break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(pic16c62x); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(pic16c62x); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(pic16c62x); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "PIC16C62x"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Microchip"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Tony La Porta"); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%01x%c%c%c%c%c %c%c%c%03x",
+ (cpustate->STATUS & 0xe0) >> 5, /* Register bank */
+ cpustate->STATUS & 0x10 ? '.':'O', /* WDT Overflow */
+ cpustate->STATUS & 0x08 ? 'P':'D', /* Power/Down */
+ cpustate->STATUS & 0x04 ? 'Z':'.', /* Zero */
+ cpustate->STATUS & 0x02 ? 'c':'b', /* Nibble Carry/Borrow */
+ cpustate->STATUS & 0x01 ? 'C':'B', /* Carry/Borrow */
+
+ cpustate->OPTION & 0x20 ? 'C':'T', /* Counter/Timer */
+ cpustate->OPTION & 0x10 ? 'N':'P', /* Negative/Positive */
+ cpustate->OPTION & 0x08 ? 'W':'T', /* WatchDog/Timer */
+ cpustate->OPTION & 0x08 ? (1<<(cpustate->OPTION&7)) : (2<<(cpustate->OPTION&7)) );
+ break;
+
+ case CPUINFO_STR_REGISTER + PIC16C62x_PC: sprintf(info->s, "PC:%03X", cpustate->PC); break;
+ case CPUINFO_STR_REGISTER + PIC16C62x_W: sprintf(info->s, "W:%02X", cpustate->W); break;
+ case CPUINFO_STR_REGISTER + PIC16C62x_ALU: sprintf(info->s, "ALU:%02X", cpustate->ALU); break;
+ case CPUINFO_STR_REGISTER + PIC16C62x_STR: sprintf(info->s, "STR:%02X", cpustate->STATUS); break;
+ case CPUINFO_STR_REGISTER + PIC16C62x_TMR0: sprintf(info->s, "TMR:%02X", cpustate->TMR0); break;
+ case CPUINFO_STR_REGISTER + PIC16C62x_WDT: sprintf(info->s, "WDT:%04X", cpustate->WDT); break;
+ case CPUINFO_STR_REGISTER + PIC16C62x_OPT: sprintf(info->s, "OPT:%02X", cpustate->OPTION); break;
+ case CPUINFO_STR_REGISTER + PIC16C62x_STK0: sprintf(info->s, "STK0:%03X", cpustate->STACK[0]); break;
+ case CPUINFO_STR_REGISTER + PIC16C62x_STK1: sprintf(info->s, "STK1:%03X", cpustate->STACK[1]); break;
+ case CPUINFO_STR_REGISTER + PIC16C62x_STK2: sprintf(info->s, "STK2:%03X", cpustate->STACK[2]); break;
+ case CPUINFO_STR_REGISTER + PIC16C62x_STK3: sprintf(info->s, "STK3:%03X", cpustate->STACK[3]); break;
+ case CPUINFO_STR_REGISTER + PIC16C62x_STK4: sprintf(info->s, "STK4:%03X", cpustate->STACK[4]); break;
+ case CPUINFO_STR_REGISTER + PIC16C62x_STK5: sprintf(info->s, "STK5:%03X", cpustate->STACK[5]); break;
+ case CPUINFO_STR_REGISTER + PIC16C62x_STK6: sprintf(info->s, "STK6:%03X", cpustate->STACK[6]); break;
+ case CPUINFO_STR_REGISTER + PIC16C62x_STK7: sprintf(info->s, "STK7:%03X", cpustate->STACK[7]); break;
+ case CPUINFO_STR_REGISTER + PIC16C62x_PRTA: sprintf(info->s, "PRTA:%01X", ((cpustate->PORTA) & 0x1f)); break;
+ case CPUINFO_STR_REGISTER + PIC16C62x_PRTB: sprintf(info->s, "PRTB:%02X", cpustate->PORTB); break;
+ case CPUINFO_STR_REGISTER + PIC16C62x_TRSA: sprintf(info->s, "TRSA:%01X", ((cpustate->TRISA) & 0x1f)); break;
+ case CPUINFO_STR_REGISTER + PIC16C62x_TRSB: sprintf(info->s, "TRSB:%02X", cpustate->TRISB); break;
+ case CPUINFO_STR_REGISTER + PIC16C62x_FSR: sprintf(info->s, "FSR:%02X", ((cpustate->FSR) & cpustate->picRAMmask) | (UINT8)(~cpustate->picRAMmask)); break;
+ case CPUINFO_STR_REGISTER + PIC16C62x_PSCL: sprintf(info->s, "PSCL:%c%02X", ((cpustate->OPTION & 0x08) ? 'W':'T'), cpustate->prescaler); break;
+ }
+}
+
+
+/****************************************************************************
+ * PIC16C620
+ ****************************************************************************/
+/****************************************************************************
+ * Internal Memory Map
+ ****************************************************************************/
+
+static ADDRESS_MAP_START( pic16c620_rom, AS_PROGRAM, 16 )
+ AM_RANGE(0x000, 0x1ff) AM_ROM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( pic16c620_ram, AS_DATA, 8 )
+ AM_RANGE(0x00, 0x06) AM_RAM
+ AM_RANGE(0x0a, 0x0c) AM_RAM
+ AM_RANGE(0x1f, 0x6f) AM_RAM
+ AM_RANGE(0x80, 0x86) AM_RAM
+ AM_RANGE(0x8a, 0x8e) AM_RAM
+ AM_RANGE(0x9f, 0x9f) AM_RAM
+ADDRESS_MAP_END
+
+
+/****************************************************************************
+ * PIC16C620 Reset
+ ****************************************************************************/
+
+static CPU_RESET( pic16c620 )
+{
+ pic16c62x_state *cpustate = get_safe_token(device);
+
+ update_internalram_ptr(cpustate);
+
+ cpustate->picmodel = 0x16C620;
+ cpustate->picRAMmask = 0xff;
+ cpustate->reset_vector = 0x0;
+ pic16c62x_reset_regs(cpustate);
+ SET(cpustate->STATUS, (TO_FLAG | PD_FLAG));
+}
+
+
+/**************************************************************************
+ * CPU-specific get_info
+ **************************************************************************/
+
+CPU_GET_INFO( pic16c620 )
+{
+ switch (state)
+ {
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 9; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 8; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(pic16c620); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map16 = ADDRESS_MAP_NAME(pic16c620_rom); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = ADDRESS_MAP_NAME(pic16c620_ram); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "PIC16C620"); break;
+
+ default: CPU_GET_INFO_CALL(pic16c62x); break;
+ }
+}
+
+
+/****************************************************************************
+ * PIC16C621
+ ****************************************************************************/
+/****************************************************************************
+ * Internal Memory Map
+ ****************************************************************************/
+
+static ADDRESS_MAP_START( pic16c621_rom, AS_PROGRAM, 16 )
+ AM_RANGE(0x000, 0x3ff) AM_ROM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( pic16c621_ram, AS_DATA, 8 )
+ AM_RANGE(0x00, 0x06) AM_RAM
+ AM_RANGE(0x0a, 0x0c) AM_RAM
+ AM_RANGE(0x1f, 0x6f) AM_RAM
+ AM_RANGE(0x80, 0x86) AM_RAM
+ AM_RANGE(0x8a, 0x8e) AM_RAM
+ AM_RANGE(0x9f, 0x9f) AM_RAM
+ADDRESS_MAP_END
+
+
+/****************************************************************************
+ * PIC16C621 Reset
+ ****************************************************************************/
+
+static CPU_RESET( pic16c621 )
+{
+ pic16c62x_state *cpustate = get_safe_token(device);
+
+ update_internalram_ptr(cpustate);
+
+ cpustate->picmodel = 0x16C621;
+ cpustate->picRAMmask = 0xff;
+ cpustate->reset_vector = 0x0;
+ pic16c62x_reset_regs(cpustate);
+ SET(cpustate->STATUS, (TO_FLAG | PD_FLAG));
+}
+
+
+/**************************************************************************
+ * CPU-specific get_info
+ **************************************************************************/
+
+CPU_GET_INFO( pic16c621 )
+{
+ switch (state)
+ {
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 10; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 8; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(pic16c621); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map16 = ADDRESS_MAP_NAME(pic16c621_rom); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = ADDRESS_MAP_NAME(pic16c621_ram); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "PIC16C621"); break;
+
+ default: CPU_GET_INFO_CALL(pic16c62x); break;
+ }
+}
+
+
+/****************************************************************************
+ * PIC16C622
+ ****************************************************************************/
+/****************************************************************************
+ * Internal Memory Map
+ ****************************************************************************/
+
+static ADDRESS_MAP_START( pic16c622_rom, AS_PROGRAM, 16 )
+ AM_RANGE(0x000, 0x7ff) AM_ROM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( pic16c622_ram, AS_DATA, 8 )
+ AM_RANGE(0x00, 0x06) AM_RAM
+ AM_RANGE(0x0a, 0x0c) AM_RAM
+ AM_RANGE(0x1f, 0x7f) AM_RAM
+ AM_RANGE(0x80, 0x86) AM_RAM
+ AM_RANGE(0x8a, 0x8e) AM_RAM
+ AM_RANGE(0x9f, 0xbf) AM_RAM
+ADDRESS_MAP_END
+
+
+/****************************************************************************
+ * PIC16C622 Reset
+ ****************************************************************************/
+
+static CPU_RESET( pic16c622 )
+{
+ pic16c62x_state *cpustate = get_safe_token(device);
+
+ update_internalram_ptr(cpustate);
+
+ cpustate->picmodel = 0x16C622;
+ cpustate->picRAMmask = 0xff;
+ cpustate->reset_vector = 0x0;
+ pic16c62x_reset_regs(cpustate);
+ SET(cpustate->STATUS, (TO_FLAG | PD_FLAG));
+}
+
+
+/**************************************************************************
+ * CPU-specific get_info
+ **************************************************************************/
+
+CPU_GET_INFO( pic16c622 )
+{
+ switch (state)
+ {
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 11; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 8; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(pic16c622); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map16 = ADDRESS_MAP_NAME(pic16c622_rom); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = ADDRESS_MAP_NAME(pic16c622_ram); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "PIC16C622"); break;
+
+ default: CPU_GET_INFO_CALL(pic16c62x); break;
+ }
+}
+
+
+/****************************************************************************
+ * PIC16C620A
+ ****************************************************************************/
+/****************************************************************************
+ * Internal Memory Map
+ ****************************************************************************/
+
+static ADDRESS_MAP_START( pic16c620a_rom, AS_PROGRAM, 16 )
+ AM_RANGE(0x000, 0x1ff) AM_ROM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( pic16c620a_ram, AS_DATA, 8 )
+ AM_RANGE(0x00, 0x06) AM_RAM
+ AM_RANGE(0x0a, 0x0c) AM_RAM
+ AM_RANGE(0x1f, 0x6f) AM_RAM
+ AM_RANGE(0x70, 0x7f) AM_RAM AM_SHARE(0)
+ AM_RANGE(0x80, 0x86) AM_RAM
+ AM_RANGE(0x8a, 0x8e) AM_RAM
+ AM_RANGE(0x9f, 0x9f) AM_RAM
+ AM_RANGE(0xf0, 0xff) AM_RAM AM_SHARE(0)
+ADDRESS_MAP_END
+
+
+/****************************************************************************
+ * PIC16C620A Reset
+ ****************************************************************************/
+
+static CPU_RESET( pic16c620a )
+{
+ pic16c62x_state *cpustate = get_safe_token(device);
+
+ update_internalram_ptr(cpustate);
+
+ cpustate->picmodel = 0x16C620A;
+ cpustate->picRAMmask = 0xff;
+ cpustate->reset_vector = 0x0;
+ pic16c62x_reset_regs(cpustate);
+ SET(cpustate->STATUS, (TO_FLAG | PD_FLAG));
+}
+
+
+/**************************************************************************
+ * CPU-specific get_info
+ **************************************************************************/
+
+CPU_GET_INFO( pic16c620a )
+{
+ switch (state)
+ {
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 9; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 8; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(pic16c620a); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map16 = ADDRESS_MAP_NAME(pic16c620a_rom); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = ADDRESS_MAP_NAME(pic16c620a_ram); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "PIC16C620A"); break;
+
+ default: CPU_GET_INFO_CALL(pic16c62x); break;
+ }
+}
+
+
+/****************************************************************************
+ * PIC16C621A
+ ****************************************************************************/
+/****************************************************************************
+ * Internal Memory Map
+ ****************************************************************************/
+
+static ADDRESS_MAP_START( pic16c621a_rom, AS_PROGRAM, 16 )
+ AM_RANGE(0x000, 0x3ff) AM_ROM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( pic16c621a_ram, AS_DATA, 8 )
+ AM_RANGE(0x00, 0x06) AM_RAM
+ AM_RANGE(0x0a, 0x0c) AM_RAM
+ AM_RANGE(0x1f, 0x6f) AM_RAM
+ AM_RANGE(0x70, 0x7f) AM_RAM AM_SHARE(0)
+ AM_RANGE(0x80, 0x86) AM_RAM
+ AM_RANGE(0x8a, 0x8e) AM_RAM
+ AM_RANGE(0x9f, 0x9f) AM_RAM
+ AM_RANGE(0xf0, 0xff) AM_RAM AM_SHARE(0)
+ADDRESS_MAP_END
+
+
+/****************************************************************************
+ * PIC16C621A Reset
+ ****************************************************************************/
+
+static CPU_RESET( pic16c621a )
+{
+ pic16c62x_state *cpustate = get_safe_token(device);
+
+ update_internalram_ptr(cpustate);
+
+ cpustate->picmodel = 0x16C621A;
+ cpustate->picRAMmask = 0xff;
+ cpustate->reset_vector = 0x0;
+ pic16c62x_reset_regs(cpustate);
+ SET(cpustate->STATUS, (TO_FLAG | PD_FLAG));
+}
+
+
+/**************************************************************************
+ * CPU-specific get_info
+ **************************************************************************/
+
+CPU_GET_INFO( pic16c621a )
+{
+ switch (state)
+ {
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 10; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 8; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(pic16c621a); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map16 = ADDRESS_MAP_NAME(pic16c621a_rom); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = ADDRESS_MAP_NAME(pic16c621a_ram); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "PIC16C621A"); break;
+
+ default: CPU_GET_INFO_CALL(pic16c62x); break;
+ }
+}
+
+
+/****************************************************************************
+ * PIC16C622A
+ ****************************************************************************/
+/****************************************************************************
+ * Internal Memory Map
+ ****************************************************************************/
+
+static ADDRESS_MAP_START( pic16c622a_rom, AS_PROGRAM, 16 )
+ AM_RANGE(0x000, 0x7ff) AM_ROM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( pic16c622a_ram, AS_DATA, 8 )
+ AM_RANGE(0x00, 0x06) AM_RAM
+ AM_RANGE(0x0a, 0x0c) AM_RAM
+ AM_RANGE(0x1f, 0x6f) AM_RAM
+ AM_RANGE(0x70, 0x7f) AM_RAM AM_SHARE(0)
+ AM_RANGE(0x80, 0x86) AM_RAM
+ AM_RANGE(0x8a, 0x8e) AM_RAM
+ AM_RANGE(0x9f, 0xbf) AM_RAM
+ AM_RANGE(0xf0, 0xff) AM_RAM AM_SHARE(0)
+ADDRESS_MAP_END
+
+
+/****************************************************************************
+ * PIC16C622A Reset
+ ****************************************************************************/
+
+static CPU_RESET( pic16c622a )
+{
+ pic16c62x_state *cpustate = get_safe_token(device);
+
+ update_internalram_ptr(cpustate);
+
+ cpustate->picmodel = 0x16C622A;
+ cpustate->picRAMmask = 0xff;
+ cpustate->reset_vector = 0x0;
+ pic16c62x_reset_regs(cpustate);
+ SET(cpustate->STATUS, (TO_FLAG | PD_FLAG));
+}
+
+
+/**************************************************************************
+ * CPU-specific get_info
+ **************************************************************************/
+
+CPU_GET_INFO( pic16c622a )
+{
+ switch (state)
+ {
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 11; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 8; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(pic16c622a); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map16 = ADDRESS_MAP_NAME(pic16c622a_rom); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = ADDRESS_MAP_NAME(pic16c622a_ram); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "PIC16C622A"); break;
+
+ default: CPU_GET_INFO_CALL(pic16c62x); break;
+ }
+}
+
+
+DEFINE_LEGACY_CPU_DEVICE(PIC16C620, pic16c620);
+DEFINE_LEGACY_CPU_DEVICE(PIC16C620A, pic16c620a);
+//DEFINE_LEGACY_CPU_DEVICE(PIC16CR620A, pic16cr620a);
+DEFINE_LEGACY_CPU_DEVICE(PIC16C621, pic16c621);
+DEFINE_LEGACY_CPU_DEVICE(PIC16C621A, pic16c621a);
+DEFINE_LEGACY_CPU_DEVICE(PIC16C622, pic16c622);
+DEFINE_LEGACY_CPU_DEVICE(PIC16C622A, pic16c622a);
+
diff --git a/trunk/src/emu/cpu/pic16c62x/pic16c62x.h b/trunk/src/emu/cpu/pic16c62x/pic16c62x.h
new file mode 100644
index 00000000000..2a5cd5c0562
--- /dev/null
+++ b/trunk/src/emu/cpu/pic16c62x/pic16c62x.h
@@ -0,0 +1,65 @@
+ /**************************************************************************\
+ * Microchip PIC16C62X Emulator *
+ * *
+ * Based On *
+ * Microchip PIC16C5X Emulator *
+ * Copyright Tony La Porta *
+ * Originally written for the MAME project. *
+ * *
+ * *
+ * Addressing architecture is based on the Harvard addressing scheme. *
+ * *
+ \**************************************************************************/
+
+#pragma once
+
+#ifndef __PIC16C62X_H__
+#define __PIC16C62X_H__
+
+
+
+
+/**************************************************************************
+ * Internal Clock divisor
+ *
+ * External Clock is divided internally by 4 for the instruction cycle
+ * times. (Each instruction cycle passes through 4 machine states). This
+ * is handled by the cpu execution engine.
+ */
+
+enum
+{
+ PIC16C62x_PC=1, PIC16C62x_STK0, PIC16C62x_STK1, PIC16C62x_STK2,
+ PIC16C62x_STK3, PIC16C62x_STK4, PIC16C62x_STK5, PIC16C62x_STK6,
+ PIC16C62x_STK7, PIC16C62x_FSR, PIC16C62x_W, PIC16C62x_ALU,
+ PIC16C62x_STR, PIC16C62x_OPT, PIC16C62x_TMR0, PIC16C62x_PRTA,
+ PIC16C62x_PRTB, PIC16C62x_WDT, PIC16C62x_TRSA, PIC16C62x_TRSB,
+ PIC16C62x_PSCL
+};
+
+#define PIC16C62x_T0 0
+
+
+/****************************************************************************
+ * Function to configure the CONFIG register. This is actually hard-wired
+ * during ROM programming, so should be called in the driver INIT, with
+ * the value if known (available in HEX dumps of the ROM).
+ */
+
+void pic16c62x_set_config(device_t *cpu, int data);
+
+
+
+DECLARE_LEGACY_CPU_DEVICE(PIC16C620, pic16c620);
+DECLARE_LEGACY_CPU_DEVICE(PIC16C620A, pic16c620a);
+//DECLARE_LEGACY_CPU_DEVICE(PIC16CR620A, pic16cr620a);
+DECLARE_LEGACY_CPU_DEVICE(PIC16C621, pic16c621);
+DECLARE_LEGACY_CPU_DEVICE(PIC16C621A, pic16c621a);
+DECLARE_LEGACY_CPU_DEVICE(PIC16C622, pic16c622);
+DECLARE_LEGACY_CPU_DEVICE(PIC16C622A, pic16c622a);
+
+
+CPU_DISASSEMBLE( pic16c62x );
+
+
+#endif /* __PIC16C62X_H__ */
diff --git a/trunk/src/emu/cpu/powerpc/drc_ops.c b/trunk/src/emu/cpu/powerpc/drc_ops.c
new file mode 100644
index 00000000000..40759911a39
--- /dev/null
+++ b/trunk/src/emu/cpu/powerpc/drc_ops.c
@@ -0,0 +1,3800 @@
+/* PowerPC common opcodes */
+
+// it really seems like this should be elsewhere - like maybe the floating point checks can hang out someplace else
+#include <math.h>
+
+#define USE_SSE2 0
+#define COMPILE_FPU 0
+
+/* recompiler flags */
+#define RECOMPILE_UNIMPLEMENTED 0x0000
+#define RECOMPILE_SUCCESSFUL 0x0001
+#define RECOMPILE_SUCCESSFUL_CP(c,p) (RECOMPILE_SUCCESSFUL | (((c) & 0xff) << 16) | (((p) & 0xff) << 24))
+#define RECOMPILE_END_OF_STRING 0x0002
+#define RECOMPILE_ADD_DISPATCH 0x0004
+
+INLINE void emit_mov_r64_m64(x86code **emitptr, UINT8 reghi, UINT8 reglo, DECLARE_MEMPARAMS)
+{
+ emit_mov_r32_m32(emitptr, reglo, MEMPARAMS);
+ emit_mov_r32_m32(emitptr, reghi, base, index, scale, disp+4);
+}
+
+INLINE void emit_mov_m64_r64(x86code **emitptr, DECLARE_MEMPARAMS, UINT8 reghi, UINT8 reglo)
+{
+ emit_mov_m32_r32(emitptr, MEMPARAMS, reglo);
+ emit_mov_m32_r32(emitptr, base, index, scale, disp+4, reghi);
+}
+
+
+static UINT32 compile_one(drc_core *drc, UINT32 pc);
+
+static void append_generate_exception(drc_core *drc, UINT8 exception);
+static void append_check_interrupts(drc_core *drc, int inline_generate);
+static UINT32 recompile_instruction(drc_core *drc, UINT32 pc, UINT32 *opptr);
+
+static UINT32 temp_ppc_pc;
+
+static void ppcdrc_init(void)
+{
+ drc_config drconfig;
+
+ /* fill in the config */
+ memset(&drconfig, 0, sizeof(drconfig));
+ drconfig.cache_size = CACHE_SIZE;
+ drconfig.max_instructions = MAX_INSTRUCTIONS;
+ drconfig.address_bits = 32;
+ drconfig.lsbs_to_ignore = 2;
+ drconfig.uses_fp = 1;
+ drconfig.uses_sse = USE_SSE2;
+ drconfig.pc_in_memory = 0;
+ drconfig.icount_in_memory = 0;
+ drconfig.pcptr = (UINT32 *)&ppc.pc;
+ drconfig.icountptr = (UINT32 *)&ppc_icount;
+ drconfig.esiptr = NULL;
+ drconfig.cb_reset = CPU_RESET_NAME(ppcdrc);
+ drconfig.cb_recompile = ppcdrc_recompile;
+ drconfig.cb_entrygen = ppcdrc_entrygen;
+
+ /* initialize the compiler */
+ ppc.drc = drc_init(cpunum_get_active(), &drconfig);
+ ppc.drcoptions = 0;
+}
+
+static void ppcdrc_reset(drc_core *drc)
+{
+ code_log_reset();
+
+ code_log("entry_point:", (x86code *)drc->entry_point, drc->out_of_cycles);
+ code_log("out_of_cycles:", drc->out_of_cycles, drc->recompile);
+ code_log("recompile:", drc->recompile, drc->dispatch);
+ code_log("dispatch:", drc->dispatch, drc->flush);
+ code_log("flush:", drc->flush, drc->cache_top);
+
+ ppc.invoke_exception_handler = drc->cache_top;
+ drc_append_restore_volatiles(drc);
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MBD(REG_ESP, 4));
+ emit_mov_r32_m32(DRCTOP, REG_ESP, MABS(&ppc.host_esp));
+ emit_mov_m32_r32(DRCTOP, MABS(&SRR0), REG_EDI); /* save return address */
+ emit_jmp_r32(DRCTOP, REG_EAX);
+ code_log("invoke_exception_handler:", ppc.invoke_exception_handler, drc->cache_top);
+
+ ppc.generate_interrupt_exception = drc->cache_top;
+ append_generate_exception(drc, EXCEPTION_IRQ);
+ code_log("generate_interrupt_exception:", ppc.generate_interrupt_exception, drc->cache_top);
+
+ ppc.generate_syscall_exception = drc->cache_top;
+ append_generate_exception(drc, EXCEPTION_SYSTEM_CALL);
+ code_log("generate_syscall_exception:", ppc.generate_syscall_exception, drc->cache_top);
+
+ ppc.generate_decrementer_exception = drc->cache_top;
+ append_generate_exception(drc, EXCEPTION_DECREMENTER);
+ code_log("generate_decrementer_exception:", ppc.generate_decrementer_exception, drc->cache_top);
+
+ ppc.generate_trap_exception = drc->cache_top;
+ append_generate_exception(drc, EXCEPTION_TRAP);
+ code_log("generate_trap_exception:", ppc.generate_trap_exception, drc->cache_top);
+
+ ppc.generate_dsi_exception = drc->cache_top;
+ append_generate_exception(drc, EXCEPTION_DSI);
+ code_log("generate_dsi_exception:", ppc.generate_dsi_exception, drc->cache_top);
+
+ ppc.generate_isi_exception = drc->cache_top;
+ append_generate_exception(drc, EXCEPTION_ISI);
+ code_log("generate_isi_exception:", ppc.generate_isi_exception, drc->cache_top);
+
+ if (!ppc.is603 && !ppc.is602)
+ {
+ ppc.generate_fit_exception = drc->cache_top;
+ append_generate_exception(drc, EXCEPTION_FIXED_INTERVAL_TIMER);
+ code_log("generate_fit_exception:", ppc.generate_fit_exception, drc->cache_top);
+ }
+}
+
+static CPU_EXIT( ppcdrc )
+{
+ drc_exit(ppc.drc);
+}
+
+static UINT32 *ppcdrc_getopptr(UINT32 address)
+{
+ UINT32 *result;
+ UINT32 offset = 0;
+
+ if (ppc.is603 || ppc.is602)
+ {
+ if (MSR & MSR_IR)
+ {
+ if (!ppc_translate_address(&address, PPC_TRANSLATE_CODE | PPC_TRANSLATE_READ | PPC_TRANSLATE_NOEXCEPTION))
+ return NULL;
+ }
+ address = DWORD_XOR_BE(address);
+ offset = (address & 0x07) / sizeof(*result);
+ address &= ~0x07;
+ }
+
+ result = (UINT32 *) memory_decrypted_read_ptr(ppc.core->program, address);
+ if (result)
+ result += offset;
+ return result;
+}
+
+static void ppcdrc_recompile(drc_core *drc)
+{
+ int remaining = MAX_INSTRUCTIONS;
+ x86code *start = drc->cache_top;
+ UINT32 pc = ppc.pc;
+ UINT32 *opptr;
+
+ (void)start;
+
+ /* begin the sequence */
+ drc_begin_sequence(drc, pc);
+ code_log_reset();
+
+ /* loose verification case: one verification here only */
+ if (!(ppc.drcoptions & PPCDRC_OPTIONS_CHECK_SELFMOD_CODE))
+ {
+ opptr = ppcdrc_getopptr(pc);
+ if (opptr)
+ drc_append_verify_code(drc, opptr, 4);
+ }
+
+ /* loop until we hit an unconditional branch */
+ while (--remaining != 0)
+ {
+ UINT32 result;
+
+ /* compile one instruction */
+ result = compile_one(drc, pc);
+ pc += (INT8)(result >> 24);
+ if (result & RECOMPILE_END_OF_STRING)
+ break;
+
+ /* do not recompile across MMU page boundaries */
+ if ((pc & 0x0FFF) == 0)
+ {
+ remaining = 0;
+ break;
+ }
+ }
+
+ /* add dispatcher just in case */
+ if (remaining == 0)
+ drc_append_dispatcher(drc);
+
+ /* end the sequence */
+ drc_end_sequence(drc);
+
+if (0)
+{
+ char label[40];
+ sprintf(label, "Code @ %08X", ppc.pc);
+ code_log(label, start, drc->cache_top);
+}
+}
+
+static void update_counters(drc_core *drc)
+{
+ emit_link link1;
+
+ /* decrementer */
+ if (ppc.is603 || ppc.is602)
+ {
+ emit_cmp_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_dec_trigger_cycle));
+ emit_jcc_short_link(DRCTOP, COND_NZ, &link1);
+ emit_or_m32_imm(DRCTOP, MABS(&ppc.exception_pending), 0x2);
+ resolve_link(DRCTOP, &link1);
+ }
+
+ /* FIT */
+ if (!ppc.is603 && !ppc.is602)
+ {
+ emit_link link2;
+ emit_cmp_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_fit_trigger_cycle));
+ emit_jcc_short_link(DRCTOP, COND_NZ, &link1);
+ emit_cmp_r32_m32(DRCTOP, REG_EBP, MABS(&ppc.fit_int_enable));
+ emit_jcc_short_link(DRCTOP, COND_Z, &link2);
+ emit_or_m32_imm(DRCTOP, MABS(&ppc.exception_pending), 0x4);
+ resolve_link(DRCTOP, &link1);
+ resolve_link(DRCTOP, &link2);
+ }
+}
+
+static void ppcdrc_entrygen(drc_core *drc)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc.host_esp), REG_ESP);
+ append_check_interrupts(drc, 0);
+}
+
+static UINT32 compile_one(drc_core *drc, UINT32 pc)
+{
+ int pcdelta, cycles;
+ UINT32 *opptr;
+ UINT32 result;
+
+ /* register this instruction */
+ drc_register_code_at_cache_top(drc, pc);
+
+ /* get a pointer to the current instruction */
+ opptr = ppcdrc_getopptr(pc);
+
+ //log_symbol(drc, ~2);
+ //log_symbol(drc, pc);
+
+ /* emit debugging call */
+ drc_append_call_debugger(drc);
+
+ /* null opptr? if legit, we need to generate an ISI exception */
+ if (!opptr)
+ {
+ /* first check to see if the code is up to date; if not, recompile */
+ emit_push_imm(DRCTOP, pc);
+ emit_call(DRCTOP, (x86code *)ppcdrc_getopptr);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_cmp_r32_imm(DRCTOP, REG_EAX, 0);
+ emit_jcc(DRCTOP, COND_NZ, drc->recompile);
+
+ /* code is up to date; do the exception */
+ emit_mov_m32_r32(DRCTOP, MABS(&SRR0), REG_EDI); /* save return address */
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&ppc.generate_isi_exception));
+ emit_jmp_r32(DRCTOP, REG_EAX);
+ return RECOMPILE_SUCCESSFUL | RECOMPILE_END_OF_STRING;
+ }
+
+ /* emit self-modifying code checks */
+ if (ppc.drcoptions & PPCDRC_OPTIONS_CHECK_SELFMOD_CODE)
+ {
+ drc_append_verify_code(drc, opptr, 4);
+ }
+
+ /* compile the instruction */
+ result = recompile_instruction(drc, pc, opptr);
+
+ /* handle the results */
+ if (!(result & RECOMPILE_SUCCESSFUL))
+ fatalerror("Unimplemented op %08X", *opptr);
+
+ pcdelta = (INT8)(result >> 24);
+ cycles = (INT8)(result >> 16);
+
+ /* epilogue */
+ update_counters(drc);
+ drc_append_standard_epilogue(drc, cycles, pcdelta, 1);
+
+ if (result & RECOMPILE_ADD_DISPATCH)
+ drc_append_dispatcher(drc);
+
+ return (result & 0xffff) | ((UINT8)cycles << 16) | ((UINT8)pcdelta << 24);
+}
+
+static UINT32 recompile_instruction(drc_core *drc, UINT32 pc, UINT32 *opptr)
+{
+ UINT32 opcode;
+ temp_ppc_pc = pc;
+
+ opcode = *opptr;
+
+ code_log_add_entry(pc, opcode, drc->cache_top);
+
+ if (opcode != 0) { // this is a little workaround for VF3
+ switch(opcode >> 26)
+ {
+ case 19: return ppc.optable19[(opcode >> 1) & 0x3ff](drc, opcode);
+ case 31: return ppc.optable31[(opcode >> 1) & 0x3ff](drc, opcode);
+ case 59: return ppc.optable59[(opcode >> 1) & 0x3ff](drc, opcode);
+ case 63: return ppc.optable63[(opcode >> 1) & 0x3ff](drc, opcode);
+ default: return ppc.optable[opcode >> 26](drc, opcode);
+ }
+ }
+ return RECOMPILE_SUCCESSFUL | RECOMPILE_END_OF_STRING;
+}
+
+
+static const UINT32 exception_vector[32] =
+{
+ 0x0000, 0x0500, 0x0900, 0x0700, 0x0c00, 0x1400, 0x0300, 0x0400,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x1000, 0x1010, 0x1020
+};
+
+static void append_generate_exception(drc_core *drc, UINT8 exception)
+{
+ emit_link link1, link2, link3;
+
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&ppc.msr));
+ emit_and_r32_imm(DRCTOP, REG_EAX, 0xff73);
+ emit_mov_m32_r32(DRCTOP, MABS(&SRR1), REG_EAX);
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&ppc.msr));
+
+ // Clear POW, EE, PR, FP, FE0, SE, BE, FE1, IR, DR, RI
+ emit_and_r32_imm(DRCTOP, REG_EAX, ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI));
+ // Set LE to ILE
+ emit_and_r32_imm(DRCTOP, REG_EAX, ~MSR_LE); // clear LE first
+ emit_test_r32_imm(DRCTOP, REG_EAX, MSR_ILE);
+ emit_jcc_short_link(DRCTOP, COND_Z, &link1); // if Z == 0, bit == 1
+ emit_or_r32_imm(DRCTOP, REG_EAX, MSR_LE); // set LE
+ resolve_link(DRCTOP, &link1);
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_r32(DRCTOP, REG_EAX);
+ emit_call(DRCTOP, (x86code *)ppc_set_msr);
+ emit_pop_r32(DRCTOP, REG_EDX);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ if (ppc.is603)
+ {
+ emit_mov_r32_imm(DRCTOP, REG_EDI, exception_vector[exception]); // first move the exception handler offset
+ emit_test_r32_imm(DRCTOP, REG_EDX, MSR_IP); // test if the base should be 0xfff0 or EVPR
+ emit_jcc_short_link(DRCTOP, COND_Z, &link2); // if Z == 1, bit == 0 means base == 0x00000000
+ emit_or_r32_imm(DRCTOP, REG_EDI, 0xfff00000); // else base == 0xfff00000
+ resolve_link(DRCTOP, &link2);
+ }
+ else if (ppc.is602)
+ {
+ emit_mov_r32_imm(DRCTOP, REG_EDI, exception_vector[exception]); // first move the exception handler offset
+ emit_test_r32_imm(DRCTOP, REG_EDX, MSR_IP); // test if the base should be 0xfff0 or IBR
+ emit_jcc_short_link(DRCTOP, COND_NZ, &link2); // if Z == 0, bit == 1 means base == 0xfff00000
+ emit_or_r32_m32(DRCTOP, REG_EDI, MABS(&ppc.ibr)); // else base == IBR
+ emit_jmp_short_link(DRCTOP, &link3);
+ resolve_link(DRCTOP, &link2);
+ emit_or_r32_imm(DRCTOP, REG_EDI, 0xfff00000);
+ resolve_link(DRCTOP, &link3);
+ }
+ else
+ {
+ emit_mov_r32_imm(DRCTOP, REG_EDI, exception_vector[exception]); // first move the exception handler offset
+ emit_test_r32_imm(DRCTOP, REG_EDX, MSR_IP); // test if the base should be 0xfff0 or EVPR
+ emit_jcc_short_link(DRCTOP, COND_NZ, &link2); // if Z == 0, bit == 1 means base == 0xfff00000
+ emit_or_r32_m32(DRCTOP, REG_EDI, MABS(&EVPR)); // else base == EVPR
+ emit_jmp_short_link(DRCTOP, &link3);
+ resolve_link(DRCTOP, &link2);
+ emit_or_r32_imm(DRCTOP, REG_EDI, 0xfff00000);
+ resolve_link(DRCTOP, &link3);
+ }
+
+ if (exception == EXCEPTION_IRQ)
+ {
+ emit_and_m32_imm(DRCTOP, MABS(&ppc.exception_pending), ~0x1); // clear pending irq
+ }
+ if (exception == EXCEPTION_DECREMENTER)
+ {
+ emit_and_m32_imm(DRCTOP, MABS(&ppc.exception_pending), ~0x2); // clear pending decrementer exception
+ }
+ if (exception == EXCEPTION_FIXED_INTERVAL_TIMER)
+ {
+ emit_and_m32_imm(DRCTOP, MABS(&ppc.exception_pending), ~0x4); // clear pending fit exception
+ }
+
+ drc_append_dispatcher(drc);
+}
+
+static void append_check_interrupts(drc_core *drc, int inline_generate)
+{
+ if (ppc.is602 || ppc.is603)
+ {
+ emit_link link1, link2, link3, link4;
+ emit_test_m32_imm(DRCTOP, MABS(&ppc.msr), MSR_EE); /* no interrupt if external interrupts are not enabled */
+ emit_jcc_short_link(DRCTOP, COND_Z, &link1); /* ZF = 1 if bit == 0 */
+
+ /* else check if any interrupt are pending */
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&ppc.exception_pending));
+ emit_cmp_r32_imm(DRCTOP, REG_EAX, 0);
+ emit_jcc_short_link(DRCTOP, COND_Z, &link2); /* reg == 0, no exceptions are pending */
+
+ /* else handle the first pending exception */
+ emit_test_r32_imm(DRCTOP, REG_EAX, 0x1); /* is it a IRQ? */
+ emit_jcc_short_link(DRCTOP, COND_Z, &link3);
+
+ emit_mov_m32_r32(DRCTOP, MABS(&SRR0), REG_EDI); /* save return address */
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&ppc.generate_interrupt_exception));
+ emit_jmp_r32(DRCTOP, REG_EAX);
+ resolve_link(DRCTOP, &link3);
+
+ emit_test_r32_imm(DRCTOP, REG_EAX, 0x2); /* is it a decrementer exception */
+ emit_jcc_short_link(DRCTOP, COND_Z, &link4);
+ emit_mov_m32_r32(DRCTOP, MABS(&SRR0), REG_EDI); /* save return address */
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&ppc.generate_decrementer_exception));
+ emit_jmp_r32(DRCTOP, REG_EAX);
+ resolve_link(DRCTOP, &link4);
+
+ resolve_link(DRCTOP, &link1);
+ resolve_link(DRCTOP, &link2);
+ }
+ else
+ {
+ emit_link link1, link2, link3, link4, link5, link6;
+ emit_test_m32_imm(DRCTOP, MABS(&ppc.msr), MSR_EE); /* no interrupt if external interrupts are not enabled */
+ emit_jcc_short_link(DRCTOP, COND_Z, &link1); /* ZF = 1 if bit == 0 */
+
+ /* else check if any interrupt are pending */
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&ppc.exception_pending));
+ emit_cmp_r32_imm(DRCTOP, REG_EAX, 0);
+ emit_jcc_short_link(DRCTOP, COND_Z, &link2); /* reg == 0, no exceptions are pending */
+
+ /* else handle the first pending exception */
+ emit_test_r32_imm(DRCTOP, REG_EAX, 0x1); /* is it a IRQ? */
+ emit_jcc_short_link(DRCTOP, COND_Z, &link3);
+
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&ppc.exisr));
+ emit_and_r32_m32(DRCTOP, REG_EAX, MABS(&ppc.exier));
+ emit_cmp_r32_imm(DRCTOP, REG_EAX, 0);
+ emit_jcc_short_link(DRCTOP, COND_Z, &link4);
+
+ emit_mov_m32_r32(DRCTOP, MABS(&SRR0), REG_EDI); /* save return address */
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&ppc.generate_interrupt_exception));
+ emit_jmp_r32(DRCTOP, REG_EAX);
+
+ /* check if it's FIT exception */
+ resolve_link(DRCTOP, &link3);
+ emit_test_r32_imm(DRCTOP, REG_EAX, 0x4);
+ emit_jcc_short_link(DRCTOP, COND_Z, &link5);
+
+ // check if FIT interrupts are enabled
+ emit_test_m32_imm(DRCTOP, MABS(&ppc.fit_int_enable), 0x1);
+ emit_jcc_short_link(DRCTOP, COND_Z, &link6);
+
+ // calculate the next trigger cycle for FIT
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&ppc_fit_trigger_cycle));
+ emit_sub_r32_m32(DRCTOP, REG_EAX, MABS(&ppc.fit_bit));
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_fit_trigger_cycle), REG_EAX);
+
+ emit_mov_m32_r32(DRCTOP, MABS(&SRR0), REG_EDI); /* save return address */
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&ppc.generate_fit_exception));
+ emit_jmp_r32(DRCTOP, REG_EAX);
+
+ resolve_link(DRCTOP, &link1);
+ resolve_link(DRCTOP, &link2);
+ resolve_link(DRCTOP, &link4);
+ resolve_link(DRCTOP, &link5);
+ resolve_link(DRCTOP, &link6);
+ }
+}
+
+static void append_branch_or_dispatch(drc_core *drc, UINT32 newpc, int cycles)
+{
+ void *code = drc_get_code_at_pc(drc, newpc);
+ emit_mov_r32_imm(DRCTOP, REG_EDI, newpc);
+
+ update_counters(drc);
+ append_check_interrupts(drc, 0);
+
+ drc_append_standard_epilogue(drc, cycles, 0, 1);
+
+
+ if (code)
+ emit_jmp(DRCTOP, code);
+ else
+ drc_append_tentative_fixed_dispatcher(drc, newpc);
+}
+
+/*
+// this table translates x86 SF and ZF flags to PPC CR values
+static const UINT8 condition_table[4] =
+{
+ 0x4, // x86 SF == 0, ZF == 0 --> PPC GT (positive)
+ 0x2, // x86 SF == 0, ZF == 1 --> PPC EQ (zero)
+ 0x8, // x86 SF == 1, ZF == 0 --> PPC LT (negative)
+ 0x0, // x86 SF == 1, ZF == 1 (impossible)
+};
+*/
+
+// expects the result value in EDX!!!
+static void append_set_cr0(drc_core *drc)
+{
+ emit_xor_r32_r32(DRCTOP, REG_EBX, REG_EBX);
+ emit_xor_r32_r32(DRCTOP, REG_EAX, REG_EAX);
+ emit_cmp_r32_imm(DRCTOP, REG_EDX, 0);
+/*
+ _lahf();
+
+ _shr_r32_imm(REG_EAX, 14);
+
+ _add_r32_imm(REG_EAX, &condition_table);
+ _mov_r8_m8bd(REG_BL, REG_EAX, 0);
+*/
+ emit_setcc_r8(DRCTOP, COND_Z, REG_AL);
+ emit_setcc_r8(DRCTOP, COND_L, REG_AH);
+ emit_setcc_r8(DRCTOP, COND_G, REG_BL);
+ emit_shl_r8_imm(DRCTOP, REG_AL, 1);
+ emit_shl_r8_imm(DRCTOP, REG_AH, 3);
+ emit_shl_r8_imm(DRCTOP, REG_BL, 2);
+ emit_or_r8_r8(DRCTOP, REG_BL, REG_AH);
+ emit_or_r8_r8(DRCTOP, REG_BL, REG_AL);
+
+ emit_bt_m32_imm(DRCTOP, MABS(&XER), 31); // set XER SO bit to carry
+ emit_adc_r32_imm(DRCTOP, REG_EBX, 0); // effectively sets bit 0 to carry
+
+ emit_mov_m8_r8(DRCTOP, MABS(&ppc.cr[0]), REG_BL);
+}
+
+#ifdef UNUSED_FUNCTION
+static void append_set_cr1(drc_core *drc)
+{
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&ppc.fpscr));
+ emit_shr_r32_imm(DRCTOP, REG_EAX, 28);
+ emit_and_r32_imm(DRCTOP, REG_EAX, 0xf);
+ emit_mov_m8_r8(DRCTOP, MABS(&ppc.cr[1]), REG_AL);
+}
+#endif
+
+static UINT32 recompile_addx(drc_core *drc, UINT32 op)
+{
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RA)));
+ emit_add_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RB)));
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RT)), REG_EDX);
+
+ if (OEBIT) {
+ mame_printf_debug("recompile_addx: OE bit set !\n");
+ return RECOMPILE_UNIMPLEMENTED;
+ }
+ if (RCBIT) {
+ append_set_cr0(drc);
+ }
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_addcx(drc_core *drc, UINT32 op)
+{
+ emit_xor_r32_r32(DRCTOP, REG_EAX, REG_EAX);
+ emit_mov_r32_m32(DRCTOP, REG_EBX, MABS(&XER));
+ emit_and_r32_imm(DRCTOP, REG_EBX, ~0x20000000); // clear carry
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RA)));
+ emit_add_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RB)));
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RT)), REG_EDX);
+
+ emit_setcc_r8(DRCTOP, COND_C, REG_AL); // carry to AL
+ emit_shl_r32_imm(DRCTOP, REG_EAX, 29); // shift to carry bit
+ emit_or_r32_r32(DRCTOP, REG_EBX, REG_EAX);
+ emit_mov_m32_r32(DRCTOP, MABS(&XER), REG_EBX);
+
+ if (OEBIT) {
+ mame_printf_debug("recompile_addcx: OE bit set !\n");
+ return RECOMPILE_UNIMPLEMENTED;
+ }
+ if (RCBIT) {
+ append_set_cr0(drc);
+ }
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_addex(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_addex);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_addi(drc_core *drc, UINT32 op)
+{
+ if (RA == 0)
+ {
+ emit_mov_m32_imm(DRCTOP, MABS(&REG(RT)), SIMM16);
+ }
+ else
+ {
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RA)));
+ emit_add_r32_imm(DRCTOP, REG_EAX, SIMM16);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RT)), REG_EAX);
+ }
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_addic(drc_core *drc, UINT32 op)
+{
+ emit_xor_r32_r32(DRCTOP, REG_EAX, REG_EAX);
+ emit_mov_r32_m32(DRCTOP, REG_EBX, MABS(&XER));
+ emit_and_r32_imm(DRCTOP, REG_EBX, ~0x20000000); // clear carry bit
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RA)));
+ emit_add_r32_imm(DRCTOP, REG_EDX, SIMM16);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RT)), REG_EDX);
+
+ emit_setcc_r8(DRCTOP, COND_C, REG_AL); // carry to AL
+ emit_shl_r32_imm(DRCTOP, REG_EAX, 29); // shift to carry bit
+ emit_or_r32_r32(DRCTOP, REG_EBX, REG_EAX);
+ emit_mov_m32_r32(DRCTOP, MABS(&XER), REG_EBX);
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_addic_rc(drc_core *drc, UINT32 op)
+{
+ emit_xor_r32_r32(DRCTOP, REG_EAX, REG_EAX);
+ emit_mov_r32_m32(DRCTOP, REG_EBX, MABS(&XER));
+ emit_and_r32_imm(DRCTOP, REG_EBX, ~0x20000000); // clear carry bit
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RA)));
+ emit_add_r32_imm(DRCTOP, REG_EDX, SIMM16);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RT)), REG_EDX);
+
+ emit_setcc_r8(DRCTOP, COND_C, REG_AL); // carry to AL
+ emit_shl_r32_imm(DRCTOP, REG_EAX, 29); // shift to carry bit
+ emit_or_r32_r32(DRCTOP, REG_EBX, REG_EAX);
+ emit_mov_m32_r32(DRCTOP, MABS(&XER), REG_EBX);
+
+ append_set_cr0(drc);
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_addis(drc_core *drc, UINT32 op)
+{
+ if (RA == 0)
+ {
+ emit_mov_m32_imm(DRCTOP, MABS(&REG(RT)), UIMM16 << 16);
+ }
+ else
+ {
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RA)));
+ emit_add_r32_imm(DRCTOP, REG_EAX, UIMM16 << 16);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RT)), REG_EAX);
+ }
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_addmex(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_addmex);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_addzex(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_addzex);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_andx(drc_core *drc, UINT32 op)
+{
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RS)));
+ emit_and_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RB)));
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EDX);
+
+ if (RCBIT) {
+ append_set_cr0(drc);
+ }
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_andcx(drc_core *drc, UINT32 op)
+{
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RS)));
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RB)));
+ emit_not_r32(DRCTOP, REG_EAX);
+ emit_and_r32_r32(DRCTOP, REG_EDX, REG_EAX);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EDX);
+
+ if (RCBIT) {
+ append_set_cr0(drc);
+ }
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_andi_rc(drc_core *drc, UINT32 op)
+{
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RS)));
+ emit_and_r32_imm(DRCTOP, REG_EDX, UIMM16);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EDX);
+
+ append_set_cr0(drc);
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_andis_rc(drc_core *drc, UINT32 op)
+{
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RS)));
+ emit_and_r32_imm(DRCTOP, REG_EDX, UIMM16 << 16);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EDX);
+
+ append_set_cr0(drc);
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_bx(drc_core *drc, UINT32 op)
+{
+ UINT32 newpc;
+ INT32 li = op & 0x3fffffc;
+ if( li & 0x2000000 )
+ li |= 0xfc000000;
+
+ if( AABIT ) {
+ newpc = li;
+ } else {
+ newpc = temp_ppc_pc + li;
+ }
+
+ if( LKBIT ) {
+ emit_mov_m32_imm(DRCTOP, MABS(&LR), temp_ppc_pc + 4);
+ }
+
+ append_branch_or_dispatch(drc, newpc, 1);
+
+ return RECOMPILE_SUCCESSFUL_CP(0,0) | RECOMPILE_END_OF_STRING;
+}
+
+static UINT32 recompile_bcx(drc_core *drc, UINT32 op)
+{
+ emit_link link1 = {0}, link2 = {0};
+ int do_link1 = 0, do_link2 = 0;
+ UINT32 newpc;
+
+ if( AABIT ) {
+ newpc = SIMM16 & ~0x3;
+ } else {
+ newpc = temp_ppc_pc + (SIMM16 & ~0x3);
+ }
+
+ if( LKBIT ) {
+ emit_mov_m32_imm(DRCTOP, MABS(&LR), temp_ppc_pc + 4);
+ }
+
+ if (BO == 20) /* condition is always true, so the basic block ends here */
+ {
+ append_branch_or_dispatch(drc, newpc, 1);
+
+ return RECOMPILE_SUCCESSFUL_CP(0,0) | RECOMPILE_END_OF_STRING;
+ }
+ else
+ {
+ // if BO[2] == 0, update CTR and check CTR condition
+ if ((BO & 0x4) == 0)
+ {
+ do_link1 = 1;
+ //_dec_m32abs(&CTR);
+ emit_sub_m32_imm(DRCTOP, MABS(&CTR), 1);
+
+ // if BO[1] == 0, branch if CTR != 0
+ if ((BO & 0x2) == 0)
+ {
+ emit_jcc_near_link(DRCTOP, COND_Z, &link1);
+ }
+ else
+ {
+ emit_jcc_near_link(DRCTOP, COND_NZ, &link1);
+ }
+ }
+
+ // if BO[0] == 0, check condition
+ if ((BO & 0x10) == 0)
+ {
+ do_link2 = 1;
+ emit_movzx_r32_m8(DRCTOP, REG_EAX, MABS(&ppc.cr[(BI)/4]));
+ emit_test_r32_imm(DRCTOP, REG_EAX, 1 << (3 - ((BI) & 0x3))); // test if condition register bit is set
+
+ // if BO[3] == 0, branch if condition == FALSE (bit zero)
+ if ((BO & 0x8) == 0)
+ {
+ emit_jcc_near_link(DRCTOP, COND_NZ, &link2); // bit not zero, skip branch
+ }
+ // if BO[3] == 1, branch if condition == TRUE (bit not zero)
+ else
+ {
+ emit_jcc_near_link(DRCTOP, COND_Z, &link2); // bit zero, skip branch
+ }
+ }
+
+ // take the branch
+ append_branch_or_dispatch(drc, newpc, 1);
+
+ // skip the branch
+ if (do_link1) {
+ resolve_link(DRCTOP, &link1);
+ }
+ if (do_link2) {
+ resolve_link(DRCTOP, &link2);
+ }
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+ }
+}
+
+static UINT32 recompile_bcctrx(drc_core *drc, UINT32 op)
+{
+ emit_link link1 = {0} ,link2 = {0};
+ int do_link1 = 0, do_link2 = 0;
+
+ if (BO == 20) /* condition is always true, so the basic block ends here */
+ {
+ emit_mov_r32_m32(DRCTOP, REG_EDI, MABS(&CTR)); // mov edi, CTR
+
+ if( LKBIT ) {
+ emit_mov_m32_imm(DRCTOP, MABS(&LR), temp_ppc_pc + 4);
+ }
+ return RECOMPILE_SUCCESSFUL_CP(1,0) | RECOMPILE_END_OF_STRING | RECOMPILE_ADD_DISPATCH;
+ }
+ else
+ {
+ // if BO[2] == 0, update CTR and check CTR condition
+ if ((BO & 0x4) == 0)
+ {
+ do_link1 = 1;
+ //_dec_m32abs(&CTR);
+ emit_sub_m32_imm(DRCTOP, MABS(&CTR), 1);
+
+ // if BO[1] == 0, branch if CTR != 0
+ if ((BO & 0x2) == 0)
+ {
+ emit_jcc_near_link(DRCTOP, COND_Z, &link1);
+ }
+ else
+ {
+ emit_jcc_near_link(DRCTOP, COND_NZ, &link1);
+ }
+ }
+
+ // if BO[0] == 0, check condition
+ if ((BO & 0x10) == 0)
+ {
+ do_link2 = 1;
+ emit_movzx_r32_m8(DRCTOP, REG_EAX, MABS(&ppc.cr[(BI)/4]));
+ emit_test_r32_imm(DRCTOP, REG_EAX, 1 << (3 - ((BI) & 0x3))); // test if condition register bit is set
+
+ // if BO[3] == 0, branch if condition == FALSE (bit zero)
+ if ((BO & 0x8) == 0)
+ {
+ emit_jcc_near_link(DRCTOP, COND_NZ, &link2); // bit not zero, skip branch
+ }
+ // if BO[3] == 1, branch if condition == TRUE (bit not zero)
+ else
+ {
+ emit_jcc_near_link(DRCTOP, COND_Z, &link2); // bit zero, skip branch
+ }
+ }
+
+ // take the branch
+ emit_mov_r32_m32(DRCTOP, REG_EDI, MABS(&CTR)); // mov edi, CTR
+ if( LKBIT ) {
+ emit_mov_m32_imm(DRCTOP, MABS(&LR), temp_ppc_pc + 4);
+ }
+ append_check_interrupts(drc, 0);
+ drc_append_standard_epilogue(drc, 1, 0, 1);
+ drc_append_dispatcher(drc);
+
+ // skip the branch
+ if (do_link1) {
+ resolve_link(DRCTOP, &link1);
+ }
+ if (do_link2) {
+ resolve_link(DRCTOP, &link2);
+ }
+ if( LKBIT ) {
+ emit_mov_m32_imm(DRCTOP, MABS(&LR), temp_ppc_pc + 4);
+ }
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+ }
+}
+
+static UINT32 recompile_bclrx(drc_core *drc, UINT32 op)
+{
+ emit_link link1 = {0}, link2 = {0};
+ int do_link1 = 0, do_link2 = 0;
+
+ if (BO == 20) /* condition is always true, so the basic block ends here */
+ {
+ emit_mov_r32_m32(DRCTOP, REG_EDI, MABS(&LR)); // mov edi, LR
+
+ if( LKBIT ) {
+ emit_mov_m32_imm(DRCTOP, MABS(&LR), temp_ppc_pc + 4);
+ }
+ return RECOMPILE_SUCCESSFUL_CP(1,0) | RECOMPILE_END_OF_STRING | RECOMPILE_ADD_DISPATCH;
+ }
+ else
+ {
+ // if BO[2] == 0, update CTR and check CTR condition
+ if ((BO & 0x4) == 0)
+ {
+ do_link1 = 1;
+ //_dec_m32abs(&CTR);
+ emit_sub_m32_imm(DRCTOP, MABS(&CTR), 1);
+
+ // if BO[1] == 0, branch if CTR != 0
+ if ((BO & 0x2) == 0)
+ {
+ emit_jcc_near_link(DRCTOP, COND_Z, &link1);
+ }
+ else
+ {
+ emit_jcc_near_link(DRCTOP, COND_NZ, &link1);
+ }
+ }
+
+ // if BO[0] == 0, check condition
+ if ((BO & 0x10) == 0)
+ {
+ do_link2 = 1;
+ emit_movzx_r32_m8(DRCTOP, REG_EAX, MABS(&ppc.cr[(BI)/4]));
+ emit_test_r32_imm(DRCTOP, REG_EAX, 1 << (3 - ((BI) & 0x3))); // test if condition register bit is set
+
+ // if BO[3] == 0, branch if condition == FALSE (bit zero)
+ if ((BO & 0x8) == 0)
+ {
+ emit_jcc_near_link(DRCTOP, COND_NZ, &link2); // bit not zero, skip branch
+ }
+ // if BO[3] == 1, branch if condition == TRUE (bit not zero)
+ else
+ {
+ emit_jcc_near_link(DRCTOP, COND_Z, &link2); // bit zero, skip branch
+ }
+ }
+
+ // take the branch
+ emit_mov_r32_m32(DRCTOP, REG_EDI, MABS(&LR)); // mov edi, LR
+ if( LKBIT ) {
+ emit_mov_m32_imm(DRCTOP, MABS(&LR), temp_ppc_pc + 4);
+ }
+ append_check_interrupts(drc, 0);
+ drc_append_standard_epilogue(drc, 1, 0, 1);
+ drc_append_dispatcher(drc);
+
+ // skip the branch
+ if (do_link1) {
+ resolve_link(DRCTOP, &link1);
+ }
+ if (do_link2) {
+ resolve_link(DRCTOP, &link2);
+ }
+ if( LKBIT ) {
+ emit_mov_m32_imm(DRCTOP, MABS(&LR), temp_ppc_pc + 4);
+ }
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+ }
+}
+
+static UINT32 recompile_cmp(drc_core *drc, UINT32 op)
+{
+ emit_xor_r32_r32(DRCTOP, REG_EAX, REG_EAX);
+ emit_xor_r32_r32(DRCTOP, REG_EBX, REG_EBX);
+ emit_mov_r32_m32(DRCTOP, REG_ECX, MABS(&REG(RA)));
+ emit_cmp_r32_m32(DRCTOP, REG_ECX, MABS(&REG(RB)));
+
+ emit_setcc_r8(DRCTOP, COND_Z, REG_AL);
+ emit_setcc_r8(DRCTOP, COND_L, REG_AH);
+ emit_setcc_r8(DRCTOP, COND_G, REG_BL);
+ emit_shl_r8_imm(DRCTOP, REG_AL, 1);
+ emit_shl_r8_imm(DRCTOP, REG_AH, 3);
+ emit_shl_r8_imm(DRCTOP, REG_BL, 2);
+ emit_or_r8_r8(DRCTOP, REG_BL, REG_AH);
+ emit_or_r8_r8(DRCTOP, REG_BL, REG_AL);
+
+ emit_bt_m32_imm(DRCTOP, MABS(&XER), 31); // set XER SO bit to carry
+ emit_adc_r32_imm(DRCTOP, REG_EBX, 0); // effectively sets bit 0 to carry
+ emit_mov_m8_r8(DRCTOP, MABS(&ppc.cr[CRFD]), REG_BL);
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_cmpi(drc_core *drc, UINT32 op)
+{
+ emit_xor_r32_r32(DRCTOP, REG_EAX, REG_EAX);
+ emit_xor_r32_r32(DRCTOP, REG_EBX, REG_EBX);
+ emit_mov_r32_m32(DRCTOP, REG_ECX, MABS(&REG(RA)));
+ emit_cmp_r32_imm(DRCTOP, REG_ECX, SIMM16);
+
+ emit_setcc_r8(DRCTOP, COND_Z, REG_AL);
+ emit_setcc_r8(DRCTOP, COND_L, REG_AH);
+ emit_setcc_r8(DRCTOP, COND_G, REG_BL);
+ emit_shl_r8_imm(DRCTOP, REG_AL, 1);
+ emit_shl_r8_imm(DRCTOP, REG_AH, 3);
+ emit_shl_r8_imm(DRCTOP, REG_BL, 2);
+ emit_or_r8_r8(DRCTOP, REG_BL, REG_AH);
+ emit_or_r8_r8(DRCTOP, REG_BL, REG_AL);
+
+ emit_bt_m32_imm(DRCTOP, MABS(&XER), 31); // set XER SO bit to carry
+ emit_adc_r32_imm(DRCTOP, REG_EBX, 0); // effectively sets bit 0 to carry
+ emit_mov_m8_r8(DRCTOP, MABS(&ppc.cr[CRFD]), REG_BL);
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_cmpl(drc_core *drc, UINT32 op)
+{
+ emit_xor_r32_r32(DRCTOP, REG_EAX, REG_EAX);
+ emit_xor_r32_r32(DRCTOP, REG_EBX, REG_EBX);
+ emit_mov_r32_m32(DRCTOP, REG_ECX, MABS(&REG(RA)));
+ emit_cmp_r32_m32(DRCTOP, REG_ECX, MABS(&REG(RB)));
+
+ emit_setcc_r8(DRCTOP, COND_Z, REG_AL);
+ emit_setcc_r8(DRCTOP, COND_B, REG_AH);
+ emit_setcc_r8(DRCTOP, COND_A, REG_BL);
+ emit_shl_r8_imm(DRCTOP, REG_AL, 1);
+ emit_shl_r8_imm(DRCTOP, REG_AH, 3);
+ emit_shl_r8_imm(DRCTOP, REG_BL, 2);
+ emit_or_r8_r8(DRCTOP, REG_BL, REG_AH);
+ emit_or_r8_r8(DRCTOP, REG_BL, REG_AL);
+
+ emit_bt_m32_imm(DRCTOP, MABS(&XER), 31); // set XER SO bit to carry
+ emit_adc_r32_imm(DRCTOP, REG_EBX, 0); // effectively sets bit 0 to carry
+ emit_mov_m8_r8(DRCTOP, MABS(&ppc.cr[CRFD]), REG_BL);
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_cmpli(drc_core *drc, UINT32 op)
+{
+ emit_xor_r32_r32(DRCTOP, REG_EAX, REG_EAX);
+ emit_xor_r32_r32(DRCTOP, REG_EBX, REG_EBX);
+ emit_mov_r32_m32(DRCTOP, REG_ECX, MABS(&REG(RA)));
+ emit_cmp_r32_imm(DRCTOP, REG_ECX, UIMM16);
+
+ emit_setcc_r8(DRCTOP, COND_Z, REG_AL);
+ emit_setcc_r8(DRCTOP, COND_B, REG_AH);
+ emit_setcc_r8(DRCTOP, COND_A, REG_BL);
+ emit_shl_r8_imm(DRCTOP, REG_AL, 1);
+ emit_shl_r8_imm(DRCTOP, REG_AH, 3);
+ emit_shl_r8_imm(DRCTOP, REG_BL, 2);
+ emit_or_r8_r8(DRCTOP, REG_BL, REG_AH);
+ emit_or_r8_r8(DRCTOP, REG_BL, REG_AL);
+
+ emit_bt_m32_imm(DRCTOP, MABS(&XER), 31); // set XER SO bit to carry
+ emit_adc_r32_imm(DRCTOP, REG_EBX, 0); // effectively sets bit 0 to carry
+ emit_mov_m8_r8(DRCTOP, MABS(&ppc.cr[CRFD]), REG_BL);
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_cntlzw(drc_core *drc, UINT32 op)
+{
+ emit_xor_r32_r32(DRCTOP, REG_EBX, REG_EBX);
+ emit_mov_r32_imm(DRCTOP, REG_EDX, 31);
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RT)));
+ emit_bsr_r32_r32(DRCTOP, REG_EAX, REG_EAX);
+ emit_setcc_r8(DRCTOP, COND_Z, REG_BL); // if all zeros, set BL to 1, so result becomes 32
+ emit_sub_r32_r32(DRCTOP, REG_EDX, REG_EAX);
+ emit_add_r32_r32(DRCTOP, REG_EDX, REG_EBX);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EDX);
+
+ if (RCBIT) {
+ append_set_cr0(drc);
+ }
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_crand(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_crand);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_crandc(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_crandc);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_creqv(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_creqv);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_crnand(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_crnand);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_crnor(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_crnor);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_cror(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_cror);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_crorc(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_crorc);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_crxor(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_crxor);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_dcbf(drc_core *drc, UINT32 op)
+{
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_dcbi(drc_core *drc, UINT32 op)
+{
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_dcbst(drc_core *drc, UINT32 op)
+{
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_dcbt(drc_core *drc, UINT32 op)
+{
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_dcbtst(drc_core *drc, UINT32 op)
+{
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_dcbz(drc_core *drc, UINT32 op)
+{
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_divwx(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_divwx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_divwux(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_divwux);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_eieio(drc_core *drc, UINT32 op)
+{
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_eqvx(drc_core *drc, UINT32 op)
+{
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RS)));
+ emit_xor_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RB)));
+ emit_not_r32(DRCTOP, REG_EDX);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EDX);
+
+ if (RCBIT) {
+ append_set_cr0(drc);
+ }
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_extsbx(drc_core *drc, UINT32 op)
+{
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RS)));
+ emit_movsx_r32_r8(DRCTOP, REG_EDX, REG_DL);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EDX);
+
+ if (RCBIT) {
+ append_set_cr0(drc);
+ }
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_extshx(drc_core *drc, UINT32 op)
+{
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RS)));
+ emit_movsx_r32_r16(DRCTOP, REG_EDX, REG_DX);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EDX);
+
+ if (RCBIT) {
+ append_set_cr0(drc);
+ }
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_icbi(drc_core *drc, UINT32 op)
+{
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_isync(drc_core *drc, UINT32 op)
+{
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_lbz(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ if (RA == 0)
+ {
+ emit_push_imm(DRCTOP, SIMM16);
+ }
+ else
+ {
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RA)));
+ emit_add_r32_imm(DRCTOP, REG_EAX, SIMM16);
+ emit_push_r32(DRCTOP, REG_EAX);
+ }
+ emit_call(DRCTOP, (x86code *)READ8);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_movzx_r32_r8(DRCTOP, REG_EAX, REG_AL);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RT)), REG_EAX);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_lbzu(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RA)));
+ emit_add_r32_imm(DRCTOP, REG_EDX, SIMM16);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EDX);
+ emit_push_r32(DRCTOP, REG_EDX);
+ emit_call(DRCTOP, (x86code *)READ8);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_movzx_r32_r8(DRCTOP, REG_EAX, REG_AL);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RT)), REG_EAX);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_lbzux(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RA)));
+ emit_add_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RB)));
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EDX);
+ emit_push_r32(DRCTOP, REG_EDX);
+ emit_call(DRCTOP, (x86code *)READ8);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_movzx_r32_r8(DRCTOP, REG_EAX, REG_AL);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RT)), REG_EAX);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_lbzx(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RB)));
+ if (RA != 0)
+ {
+ emit_add_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RA)));
+ }
+ emit_push_r32(DRCTOP, REG_EAX);
+ emit_call(DRCTOP, (x86code *)READ8);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_movzx_r32_r8(DRCTOP, REG_EAX, REG_AL);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RT)), REG_EAX);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_lha(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ if (RA == 0)
+ {
+ emit_push_imm(DRCTOP, SIMM16);
+ }
+ else
+ {
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RA)));
+ emit_add_r32_imm(DRCTOP, REG_EAX, SIMM16);
+ emit_push_r32(DRCTOP, REG_EAX);
+ }
+ emit_call(DRCTOP, (x86code *)READ16);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_movsx_r32_r16(DRCTOP, REG_EAX, REG_AX);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RT)), REG_EAX);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_lhau(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RA)));
+ emit_add_r32_imm(DRCTOP, REG_EDX, SIMM16);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EDX);
+ emit_push_r32(DRCTOP, REG_EDX);
+ emit_call(DRCTOP, (x86code *)READ16);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_movsx_r32_r16(DRCTOP, REG_EAX, REG_AX);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RT)), REG_EAX);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_lhaux(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RA)));
+ emit_add_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RB)));
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EDX);
+ emit_push_r32(DRCTOP, REG_EDX);
+ emit_call(DRCTOP, (x86code *)READ16);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_movsx_r32_r16(DRCTOP, REG_EAX, REG_AX);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RT)), REG_EAX);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_lhax(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RB)));
+ if (RA != 0)
+ {
+ emit_add_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RA)));
+ }
+ emit_push_r32(DRCTOP, REG_EAX);
+ emit_call(DRCTOP, (x86code *)READ16);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_movsx_r32_r16(DRCTOP, REG_EAX, REG_AX);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RT)), REG_EAX);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_lhbrx(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RB)));
+ if (RA != 0)
+ {
+ emit_add_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RA)));
+ }
+ emit_push_r32(DRCTOP, REG_EAX);
+ emit_call(DRCTOP, (x86code *)READ16);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_imm(DRCTOP, REG_ECX, 8);
+ emit_rol_r16_cl(DRCTOP, REG_AX);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RT)), REG_EAX);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_lhz(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ if (RA == 0)
+ {
+ emit_push_imm(DRCTOP, SIMM16);
+ }
+ else
+ {
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RA)));
+ emit_add_r32_imm(DRCTOP, REG_EAX, SIMM16);
+ emit_push_r32(DRCTOP, REG_EAX);
+ }
+ emit_call(DRCTOP, (x86code *)READ16);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RT)), REG_EAX);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_lhzu(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RA)));
+ emit_add_r32_imm(DRCTOP, REG_EDX, SIMM16);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EDX);
+ emit_push_r32(DRCTOP, REG_EDX);
+ emit_call(DRCTOP, (x86code *)READ16);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RT)), REG_EAX);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_lhzux(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RA)));
+ emit_add_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RB)));
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EDX);
+ emit_push_r32(DRCTOP, REG_EDX);
+ emit_call(DRCTOP, (x86code *)READ16);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RT)), REG_EAX);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_lhzx(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RB)));
+ if (RA != 0)
+ {
+ emit_add_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RA)));
+ }
+ emit_push_r32(DRCTOP, REG_EAX);
+ emit_call(DRCTOP, (x86code *)READ16);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RT)), REG_EAX);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_lmw(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_lmw);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_lswi(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_lswi);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_lswx(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_lswx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_lwarx(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_lwarx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_lwbrx(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RB)));
+ if (RA != 0)
+ {
+ emit_add_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RA)));
+ }
+ emit_push_r32(DRCTOP, REG_EAX);
+ emit_call(DRCTOP, (x86code *)READ32);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_bswap_r32(DRCTOP, REG_EAX);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RT)), REG_EAX);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_lwz(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ if (RA == 0)
+ {
+ emit_push_imm(DRCTOP, SIMM16);
+ }
+ else
+ {
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RA)));
+ emit_add_r32_imm(DRCTOP, REG_EAX, SIMM16);
+ emit_push_r32(DRCTOP, REG_EAX);
+ }
+ emit_call(DRCTOP, (x86code *)READ32);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RT)), REG_EAX);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_lwzu(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RA)));
+ emit_add_r32_imm(DRCTOP, REG_EDX, SIMM16);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EDX);
+ emit_push_r32(DRCTOP, REG_EDX);
+ emit_call(DRCTOP, (x86code *)READ32);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RT)), REG_EAX);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_lwzux(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RA)));
+ emit_add_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RB)));
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EDX);
+ emit_push_r32(DRCTOP, REG_EDX);
+ emit_call(DRCTOP, (x86code *)READ32);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RT)), REG_EAX);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_lwzx(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RB)));
+ if (RA != 0)
+ {
+ emit_add_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RA)));
+ }
+ emit_push_r32(DRCTOP, REG_EAX);
+ emit_call(DRCTOP, (x86code *)READ32);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RT)), REG_EAX);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_mcrf(drc_core *drc, UINT32 op)
+{
+ emit_mov_r8_m8(DRCTOP, REG_AL, MABS(&ppc.cr[RA >> 2]));
+ emit_mov_m8_r8(DRCTOP, MABS(&ppc.cr[RT >> 2]), REG_AL);
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_mcrxr(drc_core *drc, UINT32 op)
+{
+ mame_printf_debug("PPCDRC: recompile mcrxr\n");
+ return RECOMPILE_UNIMPLEMENTED;
+}
+
+static UINT32 recompile_mfcr(drc_core *drc, UINT32 op)
+{
+ int i;
+ emit_xor_r32_r32(DRCTOP, REG_EAX, REG_EAX);
+
+ // generate code for each condition register
+ for (i=0; i < 8; i++)
+ {
+ emit_xor_r32_r32(DRCTOP, REG_EDX, REG_EDX);
+ emit_mov_r8_m8(DRCTOP, REG_DL, MABS(&ppc.cr[i]));
+ emit_shl_r32_imm(DRCTOP, REG_EDX, ((7-i) * 4));
+ emit_or_r32_r32(DRCTOP, REG_EAX, REG_EDX);
+ }
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RT)), REG_EAX);
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_mfmsr(drc_core *drc, UINT32 op)
+{
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&ppc.msr));
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RT)), REG_EAX);
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_mfspr(drc_core *drc, UINT32 op)
+{
+ if (SPR == SPR_LR) // optimized case, LR
+ {
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&LR));
+ }
+ else if(SPR == SPR_CTR) // optimized case, CTR
+ {
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&CTR));
+ }
+ else
+ {
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, SPR);
+ emit_call(DRCTOP, (x86code *)ppc_get_spr);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+ }
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RT)), REG_EAX);
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_mtcrf(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_mtcrf);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_mtmsr(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RS)));
+ emit_push_r32(DRCTOP, REG_EAX);
+ emit_call(DRCTOP, (x86code *)ppc_set_msr);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_mtspr(drc_core *drc, UINT32 op)
+{
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RS)));
+ if (SPR == SPR_LR) // optimized case, LR
+ {
+ emit_mov_m32_r32(DRCTOP, MABS(&LR), REG_EAX);
+ }
+ else if(SPR == SPR_CTR) // optimized case, CTR
+ {
+ emit_mov_m32_r32(DRCTOP, MABS(&CTR), REG_EAX);
+ }
+ else
+ {
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_r32(DRCTOP, REG_EAX);
+ emit_push_imm(DRCTOP, SPR);
+ emit_call(DRCTOP, (x86code *)ppc_set_spr);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 8);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+ }
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_mulhwx(drc_core *drc, UINT32 op)
+{
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RA)));
+ emit_mov_r32_m32(DRCTOP, REG_EBX, MABS(&REG(RB)));
+ emit_imul_r32(DRCTOP, REG_EBX);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RT)), REG_EDX);
+
+ if (RCBIT) {
+ append_set_cr0(drc);
+ }
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_mulhwux(drc_core *drc, UINT32 op)
+{
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RA)));
+ emit_mov_r32_m32(DRCTOP, REG_EBX, MABS(&REG(RB)));
+ emit_mul_r32(DRCTOP, REG_EBX);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RT)), REG_EDX);
+
+ if (RCBIT) {
+ append_set_cr0(drc);
+ }
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_mulli(drc_core *drc, UINT32 op)
+{
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RA)));
+ emit_mov_r32_imm(DRCTOP, REG_EBX, SIMM16);
+ emit_imul_r32(DRCTOP, REG_EBX);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RT)), REG_EAX);
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_mullwx(drc_core *drc, UINT32 op)
+{
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RA)));
+ emit_mov_r32_m32(DRCTOP, REG_EBX, MABS(&REG(RB)));
+ emit_mul_r32(DRCTOP, REG_EBX);
+ emit_mov_r32_r32(DRCTOP, REG_EDX, REG_EAX);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RT)), REG_EDX);
+
+ if (OEBIT) {
+ mame_printf_debug("recompile_mullwx: OEBIT set!\n");
+ return RECOMPILE_UNIMPLEMENTED;
+ }
+
+ if (RCBIT) {
+ append_set_cr0(drc);
+ }
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_nandx(drc_core *drc, UINT32 op)
+{
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RS)));
+ emit_and_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RB)));
+ emit_not_r32(DRCTOP, REG_EDX);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EDX);
+
+ if (RCBIT) {
+ append_set_cr0(drc);
+ }
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_negx(drc_core *drc, UINT32 op)
+{
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RA)));
+ emit_neg_r32(DRCTOP, REG_EDX);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RT)), REG_EDX);
+
+ if (RCBIT) {
+ append_set_cr0(drc);
+ }
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_norx(drc_core *drc, UINT32 op)
+{
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RS)));
+ emit_or_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RB)));
+ emit_not_r32(DRCTOP, REG_EDX);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EDX);
+
+ if (RCBIT) {
+ append_set_cr0(drc);
+ }
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_orx(drc_core *drc, UINT32 op)
+{
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RS)));
+ emit_or_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RB)));
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EDX);
+
+ if (RCBIT) {
+ append_set_cr0(drc);
+ }
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_orcx(drc_core *drc, UINT32 op)
+{
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RB)));
+ emit_not_r32(DRCTOP, REG_EDX);
+ emit_or_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RS)));
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EDX);
+
+ if (RCBIT) {
+ append_set_cr0(drc);
+ }
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_ori(drc_core *drc, UINT32 op)
+{
+
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RS)));
+ emit_or_r32_imm(DRCTOP, REG_EAX, UIMM16);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EAX);
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_oris(drc_core *drc, UINT32 op)
+{
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RS)));
+ emit_or_r32_imm(DRCTOP, REG_EAX, UIMM16 << 16);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EAX);
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_rfi(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_mov_r32_m32(DRCTOP, REG_EDI, MABS(&ppc.srr0)); /* get saved PC from SRR0 */
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&ppc.srr1)); /* get saved MSR from SRR1 */
+
+ emit_push_r32(DRCTOP, REG_EAX);
+ emit_call(DRCTOP, (x86code *)ppc_set_msr); /* set MSR */
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,0) | RECOMPILE_END_OF_STRING | RECOMPILE_ADD_DISPATCH;
+}
+
+static UINT32 recompile_rlwimix(drc_core *drc, UINT32 op)
+{
+ UINT32 mask = GET_ROTATE_MASK(MB, ME);
+
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RS)));
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RA)));
+ emit_rol_r32_imm(DRCTOP, REG_EDX, (SH));
+ emit_and_r32_imm(DRCTOP, REG_EDX, mask);
+ emit_and_r32_imm(DRCTOP, REG_EAX, ~mask);
+ emit_or_r32_r32(DRCTOP, REG_EDX, REG_EAX);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EDX);
+
+ if (RCBIT) {
+ append_set_cr0(drc);
+ }
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_rlwinmx(drc_core *drc, UINT32 op)
+{
+ UINT32 mask = GET_ROTATE_MASK(MB, ME);
+
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RS)));
+ emit_rol_r32_imm(DRCTOP, REG_EDX, (SH));
+ emit_and_r32_imm(DRCTOP, REG_EDX, mask);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EDX);
+
+ if (RCBIT) {
+ append_set_cr0(drc);
+ }
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_rlwnmx(drc_core *drc, UINT32 op)
+{
+ UINT32 mask = GET_ROTATE_MASK(MB, ME);
+
+ emit_mov_r32_m32(DRCTOP, REG_ECX, MABS(&REG(RB))); // x86 rotate instruction use only 5 bits, so no need to mask this
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RS)));
+ emit_rol_r32_cl(DRCTOP, REG_EDX);
+ emit_and_r32_imm(DRCTOP, REG_EDX, mask);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EDX);
+
+ if (RCBIT) {
+ append_set_cr0(drc);
+ }
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_sc(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_imm(DRCTOP, MABS(&SRR0), temp_ppc_pc + 4);
+ emit_jmp(DRCTOP, ppc.generate_syscall_exception);
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_slwx(drc_core *drc, UINT32 op)
+{
+#if USE_SSE2
+ emit_mov_r32_m32(DRCTOP, REG_ECX, MABS(&REG(RB)));
+ emit_and_r32_imm(DRCTOP, REG_ECX, 0x3f);
+ emit_movd_r128_m32(DRCTOP, REG_XMM0, MABS(&REG(RS)));
+ emit_movd_r128_r32(DRCTOP, REG_XMM1, REG_ECX);
+ emit_psllq_r128_r128(DRCTOP, REG_XMM0, REG_XMM1);
+ emit_movd_r32_r128(DRCTOP, REG_EDX, REG_XMM0);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EDX);
+
+ if (RCBIT) {
+ append_set_cr0(drc);
+ }
+#else
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_slwx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+#endif
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_srawx(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_srawx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_srawix(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_srawix);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_srwx(drc_core *drc, UINT32 op)
+{
+#if USE_SSE2
+ emit_mov_r32_m32(DRCTOP, REG_ECX, MABS(&REG(RB)));
+ emit_and_r32_imm(DRCTOP, REG_ECX, 0x3f);
+ emit_movd_r128_m32(DRCTOP, REG_XMM0, MABS(&REG(RS)));
+ emit_movd_r128_r32(DRCTOP, REG_XMM1, REG_ECX);
+ emit_psrlq_r128_r128(DRCTOP, REG_XMM0, REG_XMM1);
+ emit_movd_r32_r128(DRCTOP, REG_EDX, REG_XMM0);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EDX);
+
+ if (RCBIT) {
+ append_set_cr0(drc);
+ }
+#else
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_srwx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+#endif
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_stb(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RS)));
+ emit_movzx_r32_r8(DRCTOP, REG_EAX, REG_AL);
+ emit_push_r32(DRCTOP, REG_EAX);
+
+ if (RA == 0)
+ {
+ emit_push_imm(DRCTOP, SIMM16);
+ }
+ else
+ {
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RA)));
+ emit_add_r32_imm(DRCTOP, REG_EAX, SIMM16);
+ emit_push_r32(DRCTOP, REG_EAX);
+ }
+ emit_call(DRCTOP, (x86code *)WRITE8);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 8);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_stbu(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RS)));
+ emit_movzx_r32_r8(DRCTOP, REG_EAX, REG_AL);
+ emit_push_r32(DRCTOP, REG_EAX);
+
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RA)));
+ emit_add_r32_imm(DRCTOP, REG_EDX, SIMM16);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EDX);
+ emit_push_r32(DRCTOP, REG_EDX);
+ emit_call(DRCTOP, (x86code *)WRITE8);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 8);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_stbux(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RS)));
+ emit_movzx_r32_r8(DRCTOP, REG_EAX, REG_AL);
+ emit_push_r32(DRCTOP, REG_EAX);
+
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RA)));
+ emit_add_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RB)));
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EDX);
+ emit_push_r32(DRCTOP, REG_EDX);
+ emit_call(DRCTOP, (x86code *)WRITE8);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 8);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_stbx(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RS)));
+ emit_movzx_r32_r8(DRCTOP, REG_EAX, REG_AL);
+ emit_push_r32(DRCTOP, REG_EAX);
+
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RB)));
+ if (RA != 0)
+ {
+ emit_add_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RA)));
+ }
+ emit_push_r32(DRCTOP, REG_EDX);
+ emit_call(DRCTOP, (x86code *)WRITE8);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 8);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_sth(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RS)));
+ emit_movzx_r32_r16(DRCTOP, REG_EAX, REG_AX);
+ emit_push_r32(DRCTOP, REG_EAX);
+
+ if (RA == 0)
+ {
+ emit_push_imm(DRCTOP, SIMM16);
+ }
+ else
+ {
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RA)));
+ emit_add_r32_imm(DRCTOP, REG_EDX, SIMM16);
+ emit_push_r32(DRCTOP, REG_EDX);
+ }
+ emit_call(DRCTOP, (x86code *)WRITE16);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 8);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_sthbrx(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RS)));
+ emit_movzx_r32_r16(DRCTOP, REG_EAX, REG_AX);
+ emit_mov_r32_imm(DRCTOP, REG_ECX, 8);
+ emit_rol_r16_cl(DRCTOP, REG_AX);
+ emit_push_r32(DRCTOP, REG_EAX);
+
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RB)));
+ if (RA != 0)
+ {
+ emit_add_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RA)));
+ }
+ emit_push_r32(DRCTOP, REG_EDX);
+ emit_call(DRCTOP, (x86code *)WRITE16);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 8);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_sthu(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RS)));
+ emit_movzx_r32_r16(DRCTOP, REG_EAX, REG_AX);
+ emit_push_r32(DRCTOP, REG_EAX);
+
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RA)));
+ emit_add_r32_imm(DRCTOP, REG_EDX, SIMM16);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EDX);
+ emit_push_r32(DRCTOP, REG_EDX);
+ emit_call(DRCTOP, (x86code *)WRITE16);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 8);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_sthux(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RS)));
+ emit_movzx_r32_r16(DRCTOP, REG_EAX, REG_AX);
+ emit_push_r32(DRCTOP, REG_EAX);
+
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RA)));
+ emit_add_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RB)));
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EDX);
+ emit_push_r32(DRCTOP, REG_EDX);
+ emit_call(DRCTOP, (x86code *)WRITE16);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 8);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_sthx(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RS)));
+ emit_movzx_r32_r16(DRCTOP, REG_EAX, REG_AX);
+ emit_push_r32(DRCTOP, REG_EAX);
+
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RB)));
+ if (RA != 0)
+ {
+ emit_add_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RA)));
+ }
+ emit_push_r32(DRCTOP, REG_EDX);
+ emit_call(DRCTOP, (x86code *)WRITE16);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 8);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_stmw(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_stmw);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_stswi(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_stswi);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_stswx(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_stswx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_stw(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_m32(DRCTOP, MABS(&REG(RS)));
+ if (RA == 0)
+ {
+ emit_push_imm(DRCTOP, SIMM16);
+ }
+ else
+ {
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RA)));
+ emit_add_r32_imm(DRCTOP, REG_EAX, SIMM16);
+ emit_push_r32(DRCTOP, REG_EAX);
+ }
+ emit_call(DRCTOP, (x86code *)WRITE32);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 8);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_stwbrx(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RS)));
+ emit_bswap_r32(DRCTOP, REG_EAX);
+ emit_push_r32(DRCTOP, REG_EAX);
+
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RB)));
+ if (RA != 0)
+ {
+ emit_add_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RA)));
+ }
+ emit_push_r32(DRCTOP, REG_EDX);
+ emit_call(DRCTOP, (x86code *)WRITE32);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 8);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_stwcx_rc(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_stwcx_rc);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_stwu(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_m32(DRCTOP, MABS(&REG(RS)));
+
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RA)));
+ emit_add_r32_imm(DRCTOP, REG_EAX, SIMM16);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EAX);
+ emit_push_r32(DRCTOP, REG_EAX);
+ emit_call(DRCTOP, (x86code *)WRITE32);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 8);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_stwux(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_m32(DRCTOP, MABS(&REG(RS)));
+
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RA)));
+ emit_add_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RB)));
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EAX);
+ emit_push_r32(DRCTOP, REG_EAX);
+ emit_call(DRCTOP, (x86code *)WRITE32);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 8);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_stwx(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_m32(DRCTOP, MABS(&REG(RS)));
+
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RB)));
+ if (RA != 0)
+ {
+ emit_add_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RA)));
+ }
+ emit_push_r32(DRCTOP, REG_EAX);
+ emit_call(DRCTOP, (x86code *)WRITE32);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 8);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_subfx(drc_core *drc, UINT32 op)
+{
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RB)));
+ emit_sub_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RA)));
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RT)), REG_EDX);
+
+ if (OEBIT) {
+ mame_printf_debug("recompile_subfx: OEBIT set !\n");
+ return RECOMPILE_UNIMPLEMENTED;
+ }
+ if (RCBIT) {
+ append_set_cr0(drc);
+ }
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_subfcx(drc_core *drc, UINT32 op)
+{
+ if (OEBIT)
+ {
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_subfcx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+ }
+ else
+ {
+ emit_xor_r32_r32(DRCTOP, REG_EAX, REG_EAX);
+ emit_mov_r32_m32(DRCTOP, REG_EBX, MABS(&XER));
+ emit_and_r32_imm(DRCTOP, REG_EBX, ~0x20000000); // clear carry
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RB)));
+ emit_sub_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RA)));
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RT)), REG_EDX);
+ emit_setcc_r8(DRCTOP, COND_NC, REG_AL); // subtract carry is inverse
+ emit_shl_r32_imm(DRCTOP, REG_EAX, 29); // move carry to correct location in XER
+ emit_or_r32_r32(DRCTOP, REG_EBX, REG_EAX); // insert carry to XER
+ emit_mov_m32_r32(DRCTOP, MABS(&XER), REG_EBX);
+
+ //if (OEBIT) {
+ // mame_printf_debug("recompile_subfcx: OEBIT set !\n");
+ // return RECOMPILE_UNIMPLEMENTED;
+ //}
+ if (RCBIT) {
+ append_set_cr0(drc);
+ }
+ }
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_subfex(drc_core *drc, UINT32 op)
+{
+ emit_xor_r32_r32(DRCTOP, REG_EAX, REG_EAX);
+ emit_mov_r32_m32(DRCTOP, REG_EBX, MABS(&XER));
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RB)));
+ emit_mov_r32_m32(DRCTOP, REG_ECX, MABS(&REG(RA)));
+ emit_bt_r32_imm(DRCTOP, REG_EBX, 29); // XER carry to carry flag
+ emit_cmc(DRCTOP); // invert carry
+ emit_adc_r32_imm(DRCTOP, REG_ECX, 0);
+ emit_sub_r32_r32(DRCTOP, REG_EDX, REG_ECX);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RT)), REG_EDX);
+ emit_setcc_r8(DRCTOP, COND_NC, REG_AL); // subtract carry is inverse
+ emit_and_r32_imm(DRCTOP, REG_EBX, ~0x20000000); // clear carry
+ emit_shl_r32_imm(DRCTOP, REG_EAX, 29); // move carry to correct location in XER
+ emit_or_r32_r32(DRCTOP, REG_EBX, REG_EAX); // insert carry to XER
+ emit_mov_m32_r32(DRCTOP, MABS(&XER), REG_EBX);
+
+ if (OEBIT) {
+ mame_printf_debug("recompile_subfex: OEBIT set !\n");
+ return RECOMPILE_UNIMPLEMENTED;
+ }
+ if (RCBIT) {
+ append_set_cr0(drc);
+ }
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_subfic(drc_core *drc, UINT32 op)
+{
+ emit_xor_r32_r32(DRCTOP, REG_EAX, REG_EAX);
+ emit_mov_r32_m32(DRCTOP, REG_EBX, MABS(&XER));
+ emit_and_r32_imm(DRCTOP, REG_EBX, ~0x20000000); // clear carry
+ emit_mov_r32_imm(DRCTOP, REG_EDX, SIMM16);
+ emit_sub_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RA)));
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RT)), REG_EDX);
+ emit_setcc_r8(DRCTOP, COND_NC, REG_AL); // subtract carry is inverse
+ emit_shl_r32_imm(DRCTOP, REG_EAX, 29); // move carry to correct location in XER
+ emit_or_r32_r32(DRCTOP, REG_EBX, REG_EAX); // insert carry to XER
+ emit_mov_m32_r32(DRCTOP, MABS(&XER), REG_EBX);
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_subfmex(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_subfmex);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_subfzex(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_subfzex);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_sync(drc_core *drc, UINT32 op)
+{
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_tw(drc_core *drc, UINT32 op)
+{
+ emit_link link1 = {0}, link2 = {0}, link3 = {0}, link4 = {0}, link5 = {0}, link6 = {0};
+ int do_link1 = 0;
+ int do_link2 = 0;
+ int do_link3 = 0;
+ int do_link4 = 0;
+ int do_link5 = 0;
+
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RA)));
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RB)));
+ emit_cmp_r32_r32(DRCTOP, REG_EAX, REG_EDX);
+
+ if (RT & 0x10) {
+ emit_jcc_near_link(DRCTOP, COND_L, &link1); // less than = signed <
+ do_link1 = 1;
+ }
+ if (RT & 0x08) {
+ emit_jcc_near_link(DRCTOP, COND_G, &link2); // greater = signed >
+ do_link2 = 1;
+ }
+ if (RT & 0x04) {
+ emit_jcc_near_link(DRCTOP, COND_E, &link3); // equal
+ do_link3 = 1;
+ }
+ if (RT & 0x02) {
+ emit_jcc_near_link(DRCTOP, COND_B, &link4); // below = unsigned <
+ do_link4 = 1;
+ }
+ if (RT & 0x01) {
+ emit_jcc_near_link(DRCTOP, COND_A, &link5); // above = unsigned >
+ do_link5 = 1;
+ }
+ emit_jmp_near_link(DRCTOP, &link6);
+
+ if (do_link1) {
+ resolve_link(DRCTOP, &link1);
+ }
+ if (do_link2) {
+ resolve_link(DRCTOP, &link2);
+ }
+ if (do_link3) {
+ resolve_link(DRCTOP, &link3);
+ }
+ if (do_link4) {
+ resolve_link(DRCTOP, &link4);
+ }
+ if (do_link5) {
+ resolve_link(DRCTOP, &link5);
+ }
+ // generate exception
+ emit_mov_m32_imm(DRCTOP, MABS(&SRR0), temp_ppc_pc + 4);
+ emit_jmp(DRCTOP, ppc.generate_trap_exception);
+
+ // no exception
+ resolve_link(DRCTOP, &link6);
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_twi(drc_core *drc, UINT32 op)
+{
+ emit_link link1 = {0}, link2 = {0}, link3 = {0}, link4 = {0}, link5 = {0}, link6 = {0};
+ int do_link1 = 0;
+ int do_link2 = 0;
+ int do_link3 = 0;
+ int do_link4 = 0;
+ int do_link5 = 0;
+
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RA)));
+ emit_mov_r32_imm(DRCTOP, REG_EDX, SIMM16);
+ emit_cmp_r32_r32(DRCTOP, REG_EAX, REG_EDX);
+
+ if (RT & 0x10) {
+ emit_jcc_near_link(DRCTOP, COND_L, &link1); // less than = signed <
+ do_link1 = 1;
+ }
+ if (RT & 0x08) {
+ emit_jcc_near_link(DRCTOP, COND_G, &link2); // greater = signed >
+ do_link2 = 1;
+ }
+ if (RT & 0x04) {
+ emit_jcc_near_link(DRCTOP, COND_E, &link3); // equal
+ do_link3 = 1;
+ }
+ if (RT & 0x02) {
+ emit_jcc_near_link(DRCTOP, COND_B, &link4); // below = unsigned <
+ do_link4 = 1;
+ }
+ if (RT & 0x01) {
+ emit_jcc_near_link(DRCTOP, COND_A, &link5); // above = unsigned >
+ do_link5 = 1;
+ }
+ emit_jmp_near_link(DRCTOP, &link6);
+
+ if (do_link1) {
+ resolve_link(DRCTOP, &link1);
+ }
+ if (do_link2) {
+ resolve_link(DRCTOP, &link2);
+ }
+ if (do_link3) {
+ resolve_link(DRCTOP, &link3);
+ }
+ if (do_link4) {
+ resolve_link(DRCTOP, &link4);
+ }
+ if (do_link5) {
+ resolve_link(DRCTOP, &link5);
+ }
+ // generate exception
+ emit_mov_m32_imm(DRCTOP, MABS(&SRR0), temp_ppc_pc + 4);
+ emit_jmp(DRCTOP, ppc.generate_trap_exception);
+
+ // no exception
+ resolve_link(DRCTOP, &link6);
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_xorx(drc_core *drc, UINT32 op)
+{
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RS)));
+ emit_xor_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RB)));
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EDX);
+
+ if (RCBIT) {
+ append_set_cr0(drc);
+ }
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_xori(drc_core *drc, UINT32 op)
+{
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RS)));
+ emit_xor_r32_imm(DRCTOP, REG_EDX, UIMM16);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EDX);
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_xoris(drc_core *drc, UINT32 op)
+{
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RS)));
+ emit_xor_r32_imm(DRCTOP, REG_EDX, UIMM16 << 16);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EDX);
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_dccci(drc_core *drc, UINT32 op)
+{
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_dcread(drc_core *drc, UINT32 op)
+{
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_icbt(drc_core *drc, UINT32 op)
+{
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_iccci(drc_core *drc, UINT32 op)
+{
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_icread(drc_core *drc, UINT32 op)
+{
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_rfci(drc_core *drc, UINT32 op)
+{
+ mame_printf_debug("PPCDRC: recompile rfci\n");
+ return RECOMPILE_UNIMPLEMENTED;
+}
+
+static UINT32 recompile_mfdcr(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_mfdcr);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_mtdcr(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_mtdcr);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_wrtee(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_wrtee);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_wrteei(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_wrteei);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+#endif
+
+
+
+static UINT32 recompile_invalid(drc_core *drc, UINT32 op)
+{
+ mame_printf_debug("PPCDRC: Invalid opcode %08X PC : %X\n", op, ppc.pc);
+ return RECOMPILE_UNIMPLEMENTED;
+}
+
+
+
+/* PowerPC 60x Recompilers */
+
+static UINT32 recompile_lfs(drc_core *drc,UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+#if USE_SSE2
+ if (RA == 0)
+ {
+ emit_push_imm(DRCTOP, SIMM16);
+ }
+ else
+ {
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RA)));
+ emit_add_r32_imm(DRCTOP, REG_EAX, SIMM16);
+ emit_push_r32(DRCTOP, REG_EAX);
+ }
+ emit_call(DRCTOP, (genf*)READ32);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_movd_r128_r32(DRCTOP, REG_XMM0, REG_EAX);
+ emit_cvtss2sd_r128_r128(DRCTOP, REG_XMM1, REG_XMM0); // convert float to double
+ emit_movq_m64_r128(DRCTOP, MABS(&FPR(RT)), REG_XMM1);
+#else
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_lfs);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+#endif
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_lfsu(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+#if USE_SSE2
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RA)));
+ emit_add_r32_imm(DRCTOP, REG_EDX, SIMM16);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EDX);
+ emit_push_r32(DRCTOP, REG_EDX);
+ emit_call(DRCTOP, (x86code *)READ32);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_movd_r128_r32(DRCTOP, REG_XMM0, REG_EAX);
+ emit_cvtss2sd_r128_r128(DRCTOP, REG_XMM1, REG_XMM0); // convert float to double
+ emit_movq_m64_r128(DRCTOP, MABS(&FPR(RT)), REG_XMM1);
+#else
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_lfsu);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+#endif
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_lfd(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ if (RA == 0)
+ {
+ emit_push_imm(DRCTOP, SIMM16);
+ }
+ else
+ {
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RA)));
+ emit_add_r32_imm(DRCTOP, REG_EAX, SIMM16);
+ emit_push_r32(DRCTOP, REG_EAX);
+ }
+ emit_call(DRCTOP, (x86code *)READ64);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_m64_r64(DRCTOP, MABS(&FPR(RT)), REG_EDX, REG_EAX);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_lfdu(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RA)));
+ emit_add_r32_imm(DRCTOP, REG_EDX, SIMM16);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EDX);
+ emit_push_r32(DRCTOP, REG_EDX);
+ emit_call(DRCTOP, (x86code *)READ64);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_m64_r64(DRCTOP, MABS(&FPR(RT)), REG_EDX, REG_EAX);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_stfs(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+#if USE_SSE2
+ emit_movq_r128_m64(DRCTOP, REG_XMM0, MABS(&FPR(RT)));
+ emit_cvtsd2ss_r128_r128(DRCTOP, REG_XMM1, REG_XMM0); // convert double to float
+ emit_movd_r32_r128(DRCTOP, REG_EAX, REG_XMM1);
+ emit_push_r32(DRCTOP, REG_EAX);
+ if (RA == 0)
+ {
+ emit_push_imm(DRCTOP, SIMM16);
+ }
+ else
+ {
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RA)));
+ emit_add_r32_imm(DRCTOP, REG_EAX, SIMM16);
+ emit_push_r32(DRCTOP, REG_EAX);
+ }
+ emit_call(DRCTOP, (x86code *)WRITE32);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 8);
+#else
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_stfs);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+#endif
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_stfsu(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+#if USE_SSE2
+ emit_movq_r128_m64(DRCTOP, REG_XMM0, MABS(&FPR(RT)));
+ emit_cvtsd2ss_r128_r128(DRCTOP, REG_XMM1, REG_XMM0); // convert double to float
+ emit_movd_r32_r128(DRCTOP, REG_EAX, REG_XMM1);
+ emit_push_r32(DRCTOP, REG_EAX);
+
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RA)));
+ emit_add_r32_imm(DRCTOP, REG_EAX, SIMM16);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EAX);
+ emit_push_r32(DRCTOP, REG_EAX);
+ emit_call(DRCTOP, (x86code *)WRITE32);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 8);
+#else
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_stfsu);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+#endif
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_stfd(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_mov_r64_m64(DRCTOP, REG_EDX, REG_EAX, MABS(&FPR(RT)));
+ emit_push_r32(DRCTOP, REG_EDX);
+ emit_push_r32(DRCTOP, REG_EAX);
+ if (RA == 0)
+ {
+ emit_push_imm(DRCTOP, SIMM16);
+ }
+ else
+ {
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RA)));
+ emit_add_r32_imm(DRCTOP, REG_EAX, SIMM16);
+ emit_push_r32(DRCTOP, REG_EAX);
+ }
+ emit_call(DRCTOP, (x86code *)WRITE64);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 12);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_stfdu(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_mov_r64_m64(DRCTOP, REG_EDX, REG_EAX, MABS(&FPR(RT)));
+ emit_push_r32(DRCTOP, REG_EDX);
+ emit_push_r32(DRCTOP, REG_EAX);
+
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RA)));
+ emit_add_r32_imm(DRCTOP, REG_EAX, SIMM16);
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EAX);
+ emit_push_r32(DRCTOP, REG_EAX);
+ emit_call(DRCTOP, (x86code *)WRITE64);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 12);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_lfdux(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RA)));
+ emit_add_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RB)));
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EDX);
+ emit_push_r32(DRCTOP, REG_EDX);
+ emit_call(DRCTOP, (x86code *)READ64);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_m64_r64(DRCTOP, MABS(&FPR(RT)), REG_EDX, REG_EAX);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_lfdx(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RB)));
+ if (RA != 0)
+ {
+ emit_add_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RA)));
+ }
+ emit_push_r32(DRCTOP, REG_EAX);
+ emit_call(DRCTOP, (x86code *)READ64);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_m64_r64(DRCTOP, MABS(&FPR(RT)), REG_EDX, REG_EAX);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_lfsux(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+#if USE_SSE2
+ emit_mov_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RA)));
+ emit_add_r32_m32(DRCTOP, REG_EDX, MABS(&REG(RB)));
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EDX);
+ emit_push_r32(DRCTOP, REG_EDX);
+ emit_call(DRCTOP, (x86code *)READ32);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_movd_r128_r32(DRCTOP, REG_XMM0, REG_EAX);
+ emit_cvtss2sd_r128_r128(DRCTOP, REG_XMM1, REG_XMM0); // convert float to double
+ emit_movq_m64_r128(DRCTOP, MABS(&FPR(RT)), REG_XMM1);
+#else
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_lfsux);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+#endif
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_lfsx(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+#if USE_SSE2
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RB)));
+ if (RA != 0)
+ {
+ emit_add_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RA)));
+ }
+ emit_push_r32(DRCTOP, REG_EAX);
+ emit_call(DRCTOP, (x86code *)READ32);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_movd_r128_r32(DRCTOP, REG_XMM0, REG_EAX);
+ emit_cvtss2sd_r128_r128(DRCTOP, REG_XMM1, REG_XMM0); // convert float to double
+ emit_movq_m64_r128(DRCTOP, MABS(&FPR(RT)), REG_XMM1);
+#else
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_lfsx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+#endif
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_mfsr(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_mfsr);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_mfsrin(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_mfsrin);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_mftb(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_mftb);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_mtsr(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_mtsr);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_mtsrin(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_mtsrin);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_dcba(drc_core *drc, UINT32 op)
+{
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_stfdux(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_mov_r64_m64(DRCTOP, REG_EDX, REG_EAX, MABS(&FPR(RT)));
+ emit_push_r32(DRCTOP, REG_EDX);
+ emit_push_r32(DRCTOP, REG_EAX);
+
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RA)));
+ emit_add_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RB)));
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EAX);
+ emit_push_r32(DRCTOP, REG_EAX);
+ emit_call(DRCTOP, (x86code *)WRITE64);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 12);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_stfdx(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_mov_r64_m64(DRCTOP, REG_EDX, REG_EAX, MABS(&FPR(RT)));
+ emit_push_r32(DRCTOP, REG_EDX);
+ emit_push_r32(DRCTOP, REG_EAX);
+
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RB)));
+ if (RA != 0)
+ {
+ emit_add_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RA)));
+ }
+ emit_push_r32(DRCTOP, REG_EAX);
+ emit_call(DRCTOP, (x86code *)WRITE64);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 12);
+
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_stfdx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_stfiwx(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+#if USE_SSE2
+ emit_movq_r128_m64(DRCTOP, REG_XMM0, MABS(&FPR(RT)));
+ emit_movd_r32_r128(DRCTOP, REG_EAX, REG_XMM0);
+ emit_push_r32(DRCTOP, REG_EAX);
+
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RB)));
+ if (RA != 0)
+ {
+ emit_add_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RA)));
+ }
+ emit_push_r32(DRCTOP, REG_EAX);
+ emit_call(DRCTOP, (x86code *)WRITE32);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 8);
+#else
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_stfiwx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+#endif
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_stfsux(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+#if USE_SSE2
+ emit_movq_r128_m64(DRCTOP, REG_XMM0, MABS(&FPR(RT)));
+ emit_cvtsd2ss_r128_r128(DRCTOP, REG_XMM1, REG_XMM0); // convert double to float
+ emit_movd_r32_r128(DRCTOP, REG_EAX, REG_XMM1);
+ emit_push_r32(DRCTOP, REG_EAX);
+
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RA)));
+ emit_add_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RB)));
+ emit_mov_m32_r32(DRCTOP, MABS(&REG(RA)), REG_EAX);
+ emit_push_r32(DRCTOP, REG_EAX);
+ emit_call(DRCTOP, (x86code *)WRITE32);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 8);
+#else
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_stfsux);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+#endif
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_stfsx(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+#if USE_SSE2
+ emit_movq_r128_m64(DRCTOP, REG_XMM0, MABS(&FPR(RT)));
+ emit_cvtsd2ss_r128_r128(DRCTOP, REG_XMM1, REG_XMM0); // convert double to float
+ emit_movd_r32_r128(DRCTOP, REG_EAX, REG_XMM1);
+ emit_push_r32(DRCTOP, REG_EAX);
+
+ emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RB)));
+ if (RA != 0)
+ {
+ emit_add_r32_m32(DRCTOP, REG_EAX, MABS(&REG(RA)));
+ }
+ emit_push_r32(DRCTOP, REG_EAX);
+ emit_call(DRCTOP, (x86code *)WRITE32);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 8);
+#else
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_stfsx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+#endif
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_tlbia(drc_core *drc, UINT32 op)
+{
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_tlbie(drc_core *drc, UINT32 op)
+{
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_tlbsync(drc_core *drc, UINT32 op)
+{
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_eciwx(drc_core *drc, UINT32 op)
+{
+ mame_printf_debug("PPCDRC: eciwx unimplemented\n");
+ return RECOMPILE_UNIMPLEMENTED;
+}
+
+static UINT32 recompile_ecowx(drc_core *drc, UINT32 op)
+{
+ mame_printf_debug("PPCDRC: ecowx unimplemented\n");
+ return RECOMPILE_UNIMPLEMENTED;
+}
+
+static UINT32 recompile_fabsx(drc_core *drc, UINT32 op)
+{
+#if !COMPILE_FPU || !USE_SSE2
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_fabsx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+#else
+ emit_mov_r64_m64(DRCTOP, REG_EDX, REG_EAX, MABS(&FPR(RB)));
+ emit_and_r32_imm(DRCTOP, REG_EDX, 0x7fffffff);
+ emit_mov_m64_r64(DRCTOP, MABS(&FPR(RT)), REG_EDX, REG_EAX);
+
+ if (RCBIT) {
+ append_set_cr1(drc);
+ }
+#endif
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_faddx(drc_core *drc, UINT32 op)
+{
+#if !COMPILE_FPU || !USE_SSE2
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_faddx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+#else
+ emit_movq_r128_m64(DRCTOP, REG_XMM0, MABS(&FPR(RA)));
+ emit_movq_r128_m64(DRCTOP, REG_XMM1, MABS(&FPR(RB)));
+ emit_addsd_r128_r128(DRCTOP, REG_XMM0, REG_XMM1);
+ emit_movq_m64_r128(DRCTOP, MABS(&FPR(RT)), REG_XMM0);
+
+ if (RCBIT) {
+ append_set_cr1(drc);
+ }
+#endif
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_fcmpo(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_fcmpo);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_fcmpu(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_fcmpu);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_fctiwx(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_fctiwx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_fctiwzx(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_fctiwzx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_fdivx(drc_core *drc, UINT32 op)
+{
+#if !COMPILE_FPU || !USE_SSE2
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_fdivx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+#else
+ emit_movq_r128_m64(DRCTOP, REG_XMM0, MABS(&FPR(RA)));
+ emit_movq_r128_m64(DRCTOP, REG_XMM1, MABS(&FPR(RB)));
+ emit_divsd_r128_r128(DRCTOP, REG_XMM0, REG_XMM1);
+ emit_movq_m64_r128(DRCTOP, MABS(&FPR(RT)), REG_XMM0);
+
+ if (RCBIT) {
+ append_set_cr1(drc);
+ }
+#endif
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_fmrx(drc_core *drc, UINT32 op)
+{
+#if USE_SSE2
+ emit_movq_r128_m64(DRCTOP, REG_XMM0, MABS(&FPR(RB)));
+ emit_movq_m64_r128(DRCTOP, MABS(&FPR(RT)), REG_XMM0);
+
+ if (RCBIT) {
+ append_set_cr1(drc);
+ }
+#else
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_fmrx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+#endif
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_fnabsx(drc_core *drc, UINT32 op)
+{
+#if !COMPILE_FPU || !USE_SSE2
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_fnabsx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+#else
+ emit_mov_r64_m64(DRCTOP, REG_EDX, REG_EAX, MABS(&FPR(RB)));
+ emit_or_r32_imm(DRCTOP, REG_EDX, 0x80000000);
+ emit_mov_m64_r64(DRCTOP, MABS(&FPR(RT)), REG_EDX, REG_EAX);
+
+ if (RCBIT) {
+ append_set_cr1(drc);
+ }
+#endif
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_fnegx(drc_core *drc, UINT32 op)
+{
+#if !COMPILE_FPU || !USE_SSE2
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_fnegx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+#else
+ emit_mov_r64_m64(DRCTOP, REG_EDX, REG_EAX, MABS(&FPR(RB)));
+ emit_xor_r32_imm(DRCTOP, REG_EDX, 0x80000000);
+ emit_mov_m64_r64(DRCTOP, MABS(&FPR(RT)), REG_EDX, REG_EAX);
+
+ if (RCBIT) {
+ append_set_cr1(drc);
+ }
+#endif
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_frspx(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_frspx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+/*
+ _movq_r128_m64(REG_XMM0, MABS(&FPR(RB)));
+ _movq_m64abs_r128(&FPR(RT), REG_XMM0);
+
+ if (RCBIT) {
+ append_set_cr1(drc);
+ }
+*/
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_frsqrtex(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_frsqrtex);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_fsqrtx(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_fsqrtx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_fsubx(drc_core *drc, UINT32 op)
+{
+#if !COMPILE_FPU || !USE_SSE2
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_fsubx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+#else
+ emit_movq_r128_m64(DRCTOP, REG_XMM0, MABS(&FPR(RA)));
+ emit_movq_r128_m64(DRCTOP, REG_XMM1, MABS(&FPR(RB)));
+ emit_subsd_r128_r128(DRCTOP, REG_XMM0, REG_XMM1);
+ emit_movq_m64_r128(DRCTOP, MABS(&FPR(RT)), REG_XMM0);
+
+ if (RCBIT) {
+ append_set_cr1(drc);
+ }
+#endif
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_mffsx(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_mffsx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_mtfsb0x(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_mtfsb0x);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_mtfsb1x(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_mtfsb1x);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_mtfsfx(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_mtfsfx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_mtfsfix(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_mtfsfix);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_mcrfs(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_mcrfs);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_faddsx(drc_core *drc, UINT32 op)
+{
+#if !COMPILE_FPU || !USE_SSE2
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_faddsx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+#else
+ emit_movq_r128_m64(DRCTOP, REG_XMM0, MABS(&FPR(RA)));
+ emit_movq_r128_m64(DRCTOP, REG_XMM1, MABS(&FPR(RB)));
+ emit_addsd_r128_r128(DRCTOP, REG_XMM0, REG_XMM1);
+ emit_movq_m64_r128(DRCTOP, MABS(&FPR(RT)), REG_XMM0);
+
+ if (RCBIT) {
+ append_set_cr1(drc);
+ }
+#endif
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_fdivsx(drc_core *drc, UINT32 op)
+{
+#if !COMPILE_FPU || !USE_SSE2
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_fdivsx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+#else
+ emit_movq_r128_m64(DRCTOP, REG_XMM0, MABS(&FPR(RA)));
+ emit_movq_r128_m64(DRCTOP, REG_XMM1, MABS(&FPR(RB)));
+ emit_divsd_r128_r128(DRCTOP, REG_XMM0, REG_XMM1);
+ emit_movq_m64_r128(DRCTOP, MABS(&FPR(RT)), REG_XMM0);
+
+ if (RCBIT) {
+ append_set_cr1(drc);
+ }
+#endif
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_fresx(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_fresx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_fsqrtsx(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_fsqrtsx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_fsubsx(drc_core *drc, UINT32 op)
+{
+#if !COMPILE_FPU || !USE_SSE2
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_fsubsx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+#else
+ emit_movq_r128_m64(DRCTOP, REG_XMM0, MABS(&FPR(RA)));
+ emit_movq_r128_m64(DRCTOP, REG_XMM1, MABS(&FPR(RB)));
+ emit_subsd_r128_r128(DRCTOP, REG_XMM0, REG_XMM1);
+ emit_movq_m64_r128(DRCTOP, MABS(&FPR(RT)), REG_XMM0);
+
+ if (RCBIT) {
+ append_set_cr1(drc);
+ }
+#endif
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_fmaddx(drc_core *drc, UINT32 op)
+{
+#if !COMPILE_FPU || !USE_SSE2
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_fmaddx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+#else
+ emit_movq_r128_m64(DRCTOP, REG_XMM0, MABS(&FPR(RA)));
+ emit_movq_r128_m64(DRCTOP, REG_XMM1, MABS(&FPR(RC)));
+ emit_movq_r128_m64(DRCTOP, REG_XMM2, MABS(&FPR(RB)));
+ emit_mulsd_r128_r128(DRCTOP, REG_XMM0, REG_XMM1);
+ emit_addsd_r128_r128(DRCTOP, REG_XMM0, REG_XMM2);
+ emit_movq_m64_r128(DRCTOP, MABS(&FPR(RT)), REG_XMM0);
+
+ if (RCBIT) {
+ append_set_cr1(drc);
+ }
+#endif
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_fmsubx(drc_core *drc, UINT32 op)
+{
+#if !COMPILE_FPU || !USE_SSE2
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_fmsubx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+#else
+ emit_movq_r128_m64(DRCTOP, REG_XMM0, MABS(&FPR(RA)));
+ emit_movq_r128_m64(DRCTOP, REG_XMM1, MABS(&FPR(RC)));
+ emit_movq_r128_m64(DRCTOP, REG_XMM2, MABS(&FPR(RB)));
+ emit_mulsd_r128_r128(DRCTOP, REG_XMM0, REG_XMM1);
+ emit_subsd_r128_r128(DRCTOP, REG_XMM0, REG_XMM2);
+ emit_movq_m64_r128(DRCTOP, MABS(&FPR(RT)), REG_XMM0);
+
+ if (RCBIT) {
+ append_set_cr1(drc);
+ }
+#endif
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_fmulx(drc_core *drc, UINT32 op)
+{
+#if !COMPILE_FPU || !USE_SSE2
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_fmulx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+#else
+ emit_movq_r128_m64(DRCTOP, REG_XMM0, MABS(&FPR(RA)));
+ emit_movq_r128_m64(DRCTOP, REG_XMM1, MABS(&FPR(RC)));
+ emit_mulsd_r128_r128(DRCTOP, REG_XMM0, REG_XMM1);
+ emit_movq_m64_r128(DRCTOP, MABS(&FPR(RT)), REG_XMM0);
+
+ if (RCBIT) {
+ append_set_cr1(drc);
+ }
+#endif
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_fnmaddx(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_fnmaddx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_fnmsubx(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_fnmsubx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_fselx(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_fselx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_fmaddsx(drc_core *drc, UINT32 op)
+{
+#if !COMPILE_FPU || !USE_SSE2
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_fmaddsx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+#else
+ emit_movq_r128_m64(DRCTOP, REG_XMM0, MABS(&FPR(RA)));
+ emit_movq_r128_m64(DRCTOP, REG_XMM1, MABS(&FPR(RC)));
+ emit_movq_r128_m64(DRCTOP, REG_XMM2, MABS(&FPR(RB)));
+ emit_mulsd_r128_r128(DRCTOP, REG_XMM0, REG_XMM1);
+ emit_addsd_r128_r128(DRCTOP, REG_XMM0, REG_XMM2);
+ emit_movq_m64_r128(DRCTOP, MABS(&FPR(RT)), REG_XMM0);
+
+ if (RCBIT) {
+ append_set_cr1(drc);
+ }
+#endif
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_fmsubsx(drc_core *drc, UINT32 op)
+{
+#if !COMPILE_FPU || !USE_SSE2
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_fmsubsx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+#else
+ emit_movq_r128_m64(DRCTOP, REG_XMM0, MABS(&FPR(RA)));
+ emit_movq_r128_m64(DRCTOP, REG_XMM1, MABS(&FPR(RC)));
+ emit_movq_r128_m64(DRCTOP, REG_XMM2, MABS(&FPR(RB)));
+ emit_mulsd_r128_r128(DRCTOP, REG_XMM0, REG_XMM1);
+ emit_subsd_r128_r128(DRCTOP, REG_XMM0, REG_XMM2);
+ emit_movq_m64_r128(DRCTOP, MABS(&FPR(RT)), REG_XMM0);
+
+ if (RCBIT) {
+ append_set_cr1(drc);
+ }
+#endif
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_fmulsx(drc_core *drc, UINT32 op)
+{
+#if !COMPILE_FPU || !USE_SSE2
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_fmulsx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+#else
+ emit_movq_r128_m64(DRCTOP, REG_XMM0, MABS(&FPR(RA)));
+ emit_movq_r128_m64(DRCTOP, REG_XMM1, MABS(&FPR(RC)));
+ emit_mulsd_r128_r128(DRCTOP, REG_XMM0, REG_XMM1);
+ emit_movq_m64_r128(DRCTOP, MABS(&FPR(RT)), REG_XMM0);
+
+ if (RCBIT) {
+ append_set_cr1(drc);
+ }
+#endif
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_fnmaddsx(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_fnmaddsx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_fnmsubsx(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_fnmsubsx);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+#endif
+
+// PPC602
+
+static UINT32 recompile_esa(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_esa);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_dsa(drc_core *drc, UINT32 op)
+{
+ emit_mov_m32_r32(DRCTOP, MABS(&ppc_icount), REG_EBP);
+ emit_push_imm(DRCTOP, op);
+ emit_call(DRCTOP, (x86code *)ppc_dsa);
+ emit_add_r32_imm(DRCTOP, REG_ESP, 4);
+ emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(&ppc_icount));
+
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_tlbli(drc_core *drc, UINT32 op)
+{
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
+static UINT32 recompile_tlbld(drc_core *drc, UINT32 op)
+{
+ return RECOMPILE_SUCCESSFUL_CP(1,4);
+}
+
diff --git a/trunk/src/emu/cpu/powerpc/drc_ops.h b/trunk/src/emu/cpu/powerpc/drc_ops.h
new file mode 100644
index 00000000000..ad9fe332994
--- /dev/null
+++ b/trunk/src/emu/cpu/powerpc/drc_ops.h
@@ -0,0 +1,143 @@
+static const PPC_OPCODE ppcdrc_opcode_common[] =
+{
+ /*code subcode handler */
+ { 31, 266, recompile_addx },
+ { 31, 266 | 512, recompile_addx },
+ { 31, 10, recompile_addcx },
+ { 31, 10 | 512, recompile_addcx },
+ { 31, 138, recompile_addex },
+ { 31, 138 | 512, recompile_addex },
+ { 14, -1, recompile_addi },
+ { 12, -1, recompile_addic },
+ { 13, -1, recompile_addic_rc },
+ { 15, -1, recompile_addis },
+ { 31, 234, recompile_addmex },
+ { 31, 234 | 512, recompile_addmex },
+ { 31, 202, recompile_addzex },
+ { 31, 202 | 512, recompile_addzex },
+ { 31, 28, recompile_andx },
+ { 31, 28 | 512, recompile_andx },
+ { 31, 60, recompile_andcx },
+ { 28, -1, recompile_andi_rc },
+ { 29, -1, recompile_andis_rc },
+ { 18, -1, recompile_bx },
+ { 16, -1, recompile_bcx },
+ { 19, 528, recompile_bcctrx },
+ { 19, 16, recompile_bclrx },
+ { 31, 0, recompile_cmp },
+ { 11, -1, recompile_cmpi },
+ { 31, 32, recompile_cmpl },
+ { 10, -1, recompile_cmpli },
+ { 31, 26, recompile_cntlzw },
+ { 19, 257, recompile_crand },
+ { 19, 129, recompile_crandc },
+ { 19, 289, recompile_creqv },
+ { 19, 225, recompile_crnand },
+ { 19, 33, recompile_crnor },
+ { 19, 449, recompile_cror },
+ { 19, 417, recompile_crorc },
+ { 19, 193, recompile_crxor },
+ { 31, 86, recompile_dcbf },
+ { 31, 470, recompile_dcbi },
+ { 31, 54, recompile_dcbst },
+ { 31, 278, recompile_dcbt },
+ { 31, 246, recompile_dcbtst },
+ { 31, 1014, recompile_dcbz },
+ { 31, 491, recompile_divwx },
+ { 31, 491 | 512, recompile_divwx },
+ { 31, 459, recompile_divwux },
+ { 31, 459 | 512, recompile_divwux },
+ { 31, 854, recompile_eieio },
+ { 31, 284, recompile_eqvx },
+ { 31, 954, recompile_extsbx },
+ { 31, 922, recompile_extshx },
+ { 31, 982, recompile_icbi },
+ { 19, 150, recompile_isync },
+ { 34, -1, recompile_lbz },
+ { 35, -1, recompile_lbzu },
+ { 31, 119, recompile_lbzux },
+ { 31, 87, recompile_lbzx },
+ { 42, -1, recompile_lha },
+ { 43, -1, recompile_lhau },
+ { 31, 375, recompile_lhaux },
+ { 31, 343, recompile_lhax },
+ { 31, 790, recompile_lhbrx },
+ { 40, -1, recompile_lhz },
+ { 41, -1, recompile_lhzu },
+ { 31, 311, recompile_lhzux },
+ { 31, 279, recompile_lhzx },
+ { 46, -1, recompile_lmw },
+ { 31, 597, recompile_lswi },
+ { 31, 533, recompile_lswx },
+ { 31, 20, recompile_lwarx },
+ { 31, 534, recompile_lwbrx },
+ { 32, -1, recompile_lwz },
+ { 33, -1, recompile_lwzu },
+ { 31, 55, recompile_lwzux },
+ { 31, 23, recompile_lwzx },
+ { 19, 0, recompile_mcrf },
+ { 31, 512, recompile_mcrxr },
+ { 31, 19, recompile_mfcr },
+ { 31, 83, recompile_mfmsr },
+ { 31, 339, recompile_mfspr },
+ { 31, 144, recompile_mtcrf },
+ { 31, 146, recompile_mtmsr },
+ { 31, 467, recompile_mtspr },
+ { 31, 75, recompile_mulhwx },
+ { 31, 11, recompile_mulhwux },
+ { 7, -1, recompile_mulli },
+ { 31, 235, recompile_mullwx },
+ { 31, 235 | 512, recompile_mullwx },
+ { 31, 476, recompile_nandx },
+ { 31, 104, recompile_negx },
+ { 31, 104 | 512, recompile_negx },
+ { 31, 124, recompile_norx },
+ { 31, 444, recompile_orx },
+ { 31, 412, recompile_orcx },
+ { 24, -1, recompile_ori },
+ { 25, -1, recompile_oris },
+ { 19, 50, recompile_rfi },
+ { 20, -1, recompile_rlwimix },
+ { 21, -1, recompile_rlwinmx },
+ { 23, -1, recompile_rlwnmx },
+ { 17, -1, recompile_sc },
+ { 31, 24, recompile_slwx },
+ { 31, 792, recompile_srawx },
+ { 31, 824, recompile_srawix },
+ { 31, 536, recompile_srwx },
+ { 38, -1, recompile_stb },
+ { 39, -1, recompile_stbu },
+ { 31, 247, recompile_stbux },
+ { 31, 215, recompile_stbx },
+ { 44, -1, recompile_sth },
+ { 31, 918, recompile_sthbrx },
+ { 45, -1, recompile_sthu },
+ { 31, 439, recompile_sthux },
+ { 31, 407, recompile_sthx },
+ { 47, -1, recompile_stmw },
+ { 31, 725, recompile_stswi },
+ { 31, 661, recompile_stswx },
+ { 36, -1, recompile_stw },
+ { 31, 662, recompile_stwbrx },
+ { 31, 150, recompile_stwcx_rc },
+ { 37, -1, recompile_stwu },
+ { 31, 183, recompile_stwux },
+ { 31, 151, recompile_stwx },
+ { 31, 40, recompile_subfx },
+ { 31, 40 | 512, recompile_subfx },
+ { 31, 8, recompile_subfcx },
+ { 31, 8 | 512, recompile_subfcx },
+ { 31, 136, recompile_subfex },
+ { 31, 136 | 512, recompile_subfex },
+ { 8, -1, recompile_subfic },
+ { 31, 232, recompile_subfmex },
+ { 31, 232 | 512, recompile_subfmex },
+ { 31, 200, recompile_subfzex },
+ { 31, 200 | 512, recompile_subfzex },
+ { 31, 598, recompile_sync },
+ { 31, 4, recompile_tw },
+ { 3, -1, recompile_twi },
+ { 31, 316, recompile_xorx },
+ { 26, -1, recompile_xori },
+ { 27, -1, recompile_xoris }
+};
diff --git a/trunk/src/emu/cpu/powerpc/ppc.c b/trunk/src/emu/cpu/powerpc/ppc.c
new file mode 100644
index 00000000000..2b9935b3b10
--- /dev/null
+++ b/trunk/src/emu/cpu/powerpc/ppc.c
@@ -0,0 +1,2108 @@
+/* IBM/Motorola PowerPC 4xx/6xx Emulator */
+
+#include <setjmp.h>
+#include "emu.h"
+#include "debugger.h"
+#include "ppc.h"
+
+// PLL Configuration based on the table in MPC603EUM page 7-31
+static const int mpc603e_pll_config[12][9] =
+{
+ // 16, 20, 25, 33, 40, 50, 60, 66, 75
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, -1, 0x0, -1 },
+ { -1, -1, -1, -1, -1, 0xc, -1, 0xc, -1 },
+ { 0x5, 0x5, 0x5, 0x4, 0x4, 0x4, -1, -1, -1 },
+ { -1, -1, -1, 0x6, 0x6, -1, -1, -1, -1 },
+ { -1, -1, 0x8, 0x8, -1, -1, -1, -1, -1 },
+ { -1, 0xe, 0xe, -1, -1, -1, -1, -1, -1 },
+ { 0xa, 0xa, 0xa, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+};
+
+// PLL Configuration based on the table in MPC603E7VEC page 29
+static const int mpc603ev_pll_config[12][9] =
+{
+ // 16, 20, 25, 33, 40, 50, 60, 66, 75
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ // 2:1
+ { -1, -1, -1, -1, -1, -1, -1, 0x4, 0x4 },
+ // 2.5:1
+ { -1, -1, -1, -1, -1, 0x6, 0x6, 0x6, 0x6 },
+ // 3:1
+ { -1, -1, -1, -1, 0x8, 0x8, 0x8, 0x8, 0x8 },
+ // 3.5:1
+ { -1, -1, -1, -1, 0xe, 0xe, 0xe, 0xe, -1 },
+ // 4:1
+ { -1, -1, -1, 0xa, 0xa, 0xa, 0xa, -1, -1 },
+ // 4.5:1
+ { -1, -1, -1, 0x7, 0x7, 0x7, -1, -1, -1 },
+ // 5:1
+ { -1, -1, 0xb, 0xb, 0xb, -1, -1, -1, -1 },
+ // 5.5:1
+ { -1, -1, 0x9, 0x9, 0x9, -1, -1, -1, -1 },
+ // 6:1
+ { -1, -1, 0xd, 0xd, 0xd, -1, -1, -1, -1 }
+};
+
+// PLL Configuration based on the table in MPC603E7TEC page 23
+static const int mpc603r_pll_config[12][9] =
+{
+ // 16, 20, 25, 33, 40, 50, 60, 66, 75
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ // 2:1
+ { -1, -1, -1, -1, 0x5, 0x5, 0x5, 0x5, 0x5 },
+ // 2.5:1
+ { -1, -1, -1, -1, -1, -1, 0x6, 0x6, 0x6 },
+ // 3:1
+ { -1, -1, -1, -1, -1, 0x8, 0x8, 0x8, 0x8 },
+ // 3.5:1
+ { -1, -1, -1, -1, -1, 0xe, 0xe, 0xe, 0xe },
+ // 4:1
+ { -1, -1, -1, -1, 0xa, 0xa, 0xa, 0xa, 0xa },
+ // 4.5:1
+ { -1, -1, -1, 0x7, 0x7, 0x7, 0x7, 0x7, -1 },
+ // 5:1
+ { -1, -1, -1, 0xb, 0xb, 0xb, 0xb, -1, -1 },
+ // 5.5:1
+ { -1, -1, -1, 0x9, 0x9, 0x9, -1, -1, -1 },
+ // 6:1
+ { -1, -1, 0xd, 0xd, 0xd, 0xd, -1, -1, -1 },
+};
+
+
+static void ppc603_exception(int exception);
+static void ppc602_exception(int exception);
+static void ppc403_exception(int exception);
+static UINT8 ppc403_spu_r(UINT32 a);
+static void ppc403_spu_w(UINT32 a, UINT8 d);
+
+#define RD ((op >> 21) & 0x1F)
+#define RT ((op >> 21) & 0x1f)
+#define RS ((op >> 21) & 0x1f)
+#define RA ((op >> 16) & 0x1f)
+#define RB ((op >> 11) & 0x1f)
+#define RC ((op >> 6) & 0x1f)
+
+#define MB ((op >> 6) & 0x1f)
+#define ME ((op >> 1) & 0x1f)
+#define SH ((op >> 11) & 0x1f)
+#define BO ((op >> 21) & 0x1f)
+#define BI ((op >> 16) & 0x1f)
+#define CRFD ((op >> 23) & 0x7)
+#define CRFA ((op >> 18) & 0x7)
+#define FXM ((op >> 12) & 0xff)
+#define SPR (((op >> 16) & 0x1f) | ((op >> 6) & 0x3e0))
+
+#define SIMM16 (INT32)(INT16)(op & 0xffff)
+#define UIMM16 (UINT32)(op & 0xffff)
+
+#define RCBIT (op & 0x1)
+#define OEBIT (op & 0x400)
+#define AABIT (op & 0x2)
+#define LKBIT (op & 0x1)
+
+#define REG(x) (ppc.r[x])
+#define LR (ppc.lr)
+#define CTR (ppc.ctr)
+#define XER (ppc.xer)
+#define CR(x) (ppc.cr[x])
+#define MSR (ppc.msr)
+#define SRR0 (ppc.srr0)
+#define SRR1 (ppc.srr1)
+#define SRR2 (ppc.srr2)
+#define SRR3 (ppc.srr3)
+#define EVPR (ppc.evpr)
+#define EXIER (ppc.exier)
+#define EXISR (ppc.exisr)
+#define DEC (ppc.dec)
+
+
+// Stuff added for the 6xx
+#define FPR(x) (ppc.fpr[x])
+#define FM ((op >> 17) & 0xFF)
+#define SPRF (((op >> 6) & 0x3E0) | ((op >> 16) & 0x1F))
+
+
+#define CHECK_SUPERVISOR() \
+ if((ppc.msr & 0x4000) != 0){ \
+ }
+
+#define CHECK_FPU_AVAILABLE() \
+ if((ppc.msr & 0x2000) == 0){ \
+ }
+
+static UINT32 ppc_field_xlat[256];
+
+
+
+#define FPSCR_FX 0x80000000
+#define FPSCR_FEX 0x40000000
+#define FPSCR_VX 0x20000000
+#define FPSCR_OX 0x10000000
+#define FPSCR_UX 0x08000000
+#define FPSCR_ZX 0x04000000
+#define FPSCR_XX 0x02000000
+
+
+
+#define BITMASK_0(n) (UINT32)(((UINT64)1 << n) - 1)
+#define CRBIT(x) ((ppc.cr[x / 4] & (1 << (3 - (x % 4)))) ? 1 : 0)
+#define _BIT(n) (1 << (n))
+#define GET_ROTATE_MASK(mb,me) (ppc_rotate_mask[mb][me])
+#define ADD_CA(r,a,b) ((UINT32)r < (UINT32)a)
+#define SUB_CA(r,a,b) (!((UINT32)a < (UINT32)b))
+#define ADD_OV(r,a,b) ((~((a) ^ (b)) & ((a) ^ (r))) & 0x80000000)
+#define SUB_OV(r,a,b) (( ((a) ^ (b)) & ((a) ^ (r))) & 0x80000000)
+
+#define XER_SO 0x80000000
+#define XER_OV 0x40000000
+#define XER_CA 0x20000000
+
+#define MSR_AP 0x00800000 /* Access privilege state (PPC602) */
+#define MSR_SA 0x00400000 /* Supervisor access mode (PPC602) */
+#define MSR_POW 0x00040000 /* Power Management Enable */
+#define MSR_WE 0x00040000
+#define MSR_CE 0x00020000
+#define MSR_ILE 0x00010000 /* Interrupt Little Endian Mode */
+#define MSR_EE 0x00008000 /* External Interrupt Enable */
+#define MSR_PR 0x00004000 /* Problem State */
+#define MSR_FP 0x00002000 /* Floating Point Available */
+#define MSR_ME 0x00001000 /* Machine Check Enable */
+#define MSR_FE0 0x00000800
+#define MSR_SE 0x00000400 /* Single Step Trace Enable */
+#define MSR_BE 0x00000200 /* Branch Trace Enable */
+#define MSR_DE 0x00000200
+#define MSR_FE1 0x00000100
+#define MSR_IP 0x00000040 /* Interrupt Prefix */
+#define MSR_IR 0x00000020 /* Instruction Relocate */
+#define MSR_DR 0x00000010 /* Data Relocate */
+#define MSR_PE 0x00000008
+#define MSR_PX 0x00000004
+#define MSR_RI 0x00000002 /* Recoverable Interrupt Enable */
+#define MSR_LE 0x00000001
+
+#define TSR_ENW 0x80000000
+#define TSR_WIS 0x40000000
+
+#define BYTE_REVERSE16(x) ((((x) >> 8) & 0xff) | (((x) << 8) & 0xff00))
+#define BYTE_REVERSE32(x) ((((x) >> 24) & 0xff) | (((x) >> 8) & 0xff00) | (((x) << 8) & 0xff0000) | (((x) << 24) & 0xff000000))
+
+typedef struct {
+ UINT32 cr;
+ UINT32 da;
+ UINT32 sa;
+ UINT32 ct;
+ UINT32 cc;
+} DMA_REGS;
+
+typedef struct {
+ UINT8 spls;
+ UINT8 sphs;
+ UINT16 brd;
+ UINT8 spctl;
+ UINT8 sprc;
+ UINT8 sptc;
+ UINT8 sprb;
+ UINT8 sptb;
+ emu_timer *rx_timer;
+ emu_timer *tx_timer;
+} SPU_REGS;
+
+typedef union {
+ UINT64 id;
+ double fd;
+} FPR;
+
+typedef union {
+ UINT32 i;
+ float f;
+} FPR32;
+
+typedef struct {
+ UINT32 u;
+ UINT32 l;
+} BATENT;
+
+
+typedef struct {
+ UINT32 r[32];
+ UINT32 pc;
+ UINT32 npc;
+
+ UINT32 lr;
+ UINT32 ctr;
+ UINT32 xer;
+ UINT32 msr;
+ UINT8 cr[8];
+ UINT32 pvr;
+ UINT32 srr0;
+ UINT32 srr1;
+ UINT32 srr2;
+ UINT32 srr3;
+ UINT32 hid0;
+ UINT32 hid1;
+ UINT32 hid2;
+ UINT32 sdr1;
+ UINT32 sprg[4];
+
+ UINT32 dsisr;
+ UINT32 dar;
+ UINT32 ear;
+ UINT32 dmiss;
+ UINT32 dcmp;
+ UINT32 hash1;
+ UINT32 hash2;
+ UINT32 imiss;
+ UINT32 icmp;
+ UINT32 rpa;
+
+
+ BATENT ibat[4];
+ BATENT dbat[4];
+
+ UINT32 evpr;
+ UINT32 exier;
+ UINT32 exisr;
+ UINT32 bear;
+ UINT32 besr;
+ UINT32 iocr;
+ UINT32 br[8];
+ UINT32 iabr;
+ UINT32 esr;
+ UINT32 iccr;
+ UINT32 dccr;
+ UINT32 pit;
+ UINT32 pit_counter;
+ UINT32 pit_int_enable;
+ UINT32 tsr;
+ UINT32 dbsr;
+ UINT32 sgr;
+ UINT32 pid;
+ UINT32 pbl1, pbl2, pbu1, pbu2;
+ UINT32 fit_bit;
+ UINT32 fit_int_enable;
+ UINT32 wdt_bit;
+ UINT32 wdt_int_enable;
+ UINT32 dac1, dac2;
+ UINT32 iac1, iac2;
+
+ SPU_REGS spu;
+ DMA_REGS dma[4];
+ UINT32 dmasr;
+
+ int reserved;
+ UINT32 reserved_address;
+
+ int interrupt_pending;
+
+ UINT64 tb; /* 56-bit timebase register */
+
+ device_irq_callback irq_callback;
+ legacy_cpu_device *device;
+ address_space *program;
+
+ // STUFF added for the 6xx series
+ UINT32 dec, dec_frac;
+ UINT32 fpscr;
+
+ FPR fpr[32];
+ UINT32 sr[16];
+
+ int is603;
+ int is602;
+
+ /* PowerPC 602 specific registers */
+ UINT32 lt;
+ UINT32 sp;
+ UINT32 tcr;
+ UINT32 ibr;
+ UINT32 esasrr;
+ UINT32 sebr;
+ UINT32 ser;
+
+ /* PowerPC function pointers for memory accesses/exceptions */
+ jmp_buf exception_jmpbuf;
+ UINT8 (*read8)(address_space *space, offs_t address);
+ UINT16 (*read16)(address_space *space, offs_t address);
+ UINT32 (*read32)(address_space *space, offs_t address);
+ UINT64 (*read64)(address_space *space, offs_t address);
+ void (*write8)(address_space *space, offs_t address, UINT8 data);
+ void (*write16)(address_space *space, offs_t address, UINT16 data);
+ void (*write32)(address_space *space, offs_t address, UINT32 data);
+ void (*write64)(address_space *space, offs_t address, UINT64 data);
+ UINT16 (*read16_unaligned)(address_space *space, offs_t address);
+ UINT32 (*read32_unaligned)(address_space *space, offs_t address);
+ UINT64 (*read64_unaligned)(address_space *space, offs_t address);
+ void (*write16_unaligned)(address_space *space, offs_t address, UINT16 data);
+ void (*write32_unaligned)(address_space *space, offs_t address, UINT32 data);
+ void (*write64_unaligned)(address_space *space, offs_t address, UINT64 data);
+
+ void (* optable19[1024])(UINT32);
+ void (* optable31[1024])(UINT32);
+ void (* optable59[1024])(UINT32);
+ void (* optable63[1024])(UINT32);
+ void (* optable[64])(UINT32);
+} PPC_REGS;
+
+
+
+typedef struct {
+ int code;
+ int subcode;
+ void (* handler)(UINT32);
+} PPC_OPCODE;
+
+
+
+static int ppc_icount;
+static int ppc_tb_base_icount;
+static int ppc_dec_base_icount;
+static int ppc_dec_trigger_cycle;
+static int bus_freq_multiplier = 1;
+static PPC_REGS ppc;
+static UINT32 ppc_rotate_mask[32][32];
+
+#define ROPCODE(pc) memory_decrypted_read_dword(ppc.program, pc)
+#define ROPCODE64(pc) memory_decrypted_read_qword(ppc.program, DWORD_XOR_BE(pc))
+
+/*********************************************************************/
+
+INLINE int IS_PPC602(void)
+{
+ return ppc.is602;
+}
+
+INLINE int IS_PPC603(void)
+{
+ return ppc.is603;
+}
+
+INLINE int IS_PPC403(void)
+{
+ return !IS_PPC602() && !IS_PPC603();
+}
+
+/*********************************************************************/
+
+
+INLINE void SET_CR0(INT32 rd)
+{
+ if( rd < 0 ) {
+ CR(0) = 0x8;
+ } else if( rd > 0 ) {
+ CR(0) = 0x4;
+ } else {
+ CR(0) = 0x2;
+ }
+
+ if( XER & XER_SO )
+ CR(0) |= 0x1;
+}
+
+INLINE void SET_CR1(void)
+{
+ CR(1) = (ppc.fpscr >> 28) & 0xf;
+}
+
+INLINE void SET_ADD_OV(UINT32 rd, UINT32 ra, UINT32 rb)
+{
+ if( ADD_OV(rd, ra, rb) )
+ XER |= XER_SO | XER_OV;
+ else
+ XER &= ~XER_OV;
+}
+
+INLINE void SET_SUB_OV(UINT32 rd, UINT32 ra, UINT32 rb)
+{
+ if( SUB_OV(rd, ra, rb) )
+ XER |= XER_SO | XER_OV;
+ else
+ XER &= ~XER_OV;
+}
+
+INLINE void SET_ADD_CA(UINT32 rd, UINT32 ra, UINT32 rb)
+{
+ if( ADD_CA(rd, ra, rb) )
+ XER |= XER_CA;
+ else
+ XER &= ~XER_CA;
+}
+
+INLINE void SET_SUB_CA(UINT32 rd, UINT32 ra, UINT32 rb)
+{
+ if( SUB_CA(rd, ra, rb) )
+ XER |= XER_CA;
+ else
+ XER &= ~XER_CA;
+}
+
+INLINE UINT32 check_condition_code(UINT32 bo, UINT32 bi)
+{
+ UINT32 ctr_ok;
+ UINT32 condition_ok;
+ UINT32 bo0 = (bo & 0x10) ? 1 : 0;
+ UINT32 bo1 = (bo & 0x08) ? 1 : 0;
+ UINT32 bo2 = (bo & 0x04) ? 1 : 0;
+ UINT32 bo3 = (bo & 0x02) ? 1 : 0;
+
+ if( bo2 == 0 )
+ --CTR;
+
+ ctr_ok = bo2 | ((CTR != 0) ^ bo3);
+ condition_ok = bo0 | (CRBIT(bi) ^ (~bo1 & 0x1));
+
+ return ctr_ok && condition_ok;
+}
+
+INLINE UINT64 ppc_read_timebase(void)
+{
+ int cycles = ppc_tb_base_icount - ppc_icount;
+
+ if (IS_PPC603() || IS_PPC602())
+ {
+ // timebase is incremented once every four core clock cycles, so adjust the cycles accordingly
+ return ppc.tb + (cycles / 4);
+ }
+ else
+ {
+ // timebase is incremented once every core cycle on PPC403
+ return ppc.tb + cycles;
+ }
+}
+
+INLINE void ppc_write_timebase_l(UINT32 tbl)
+{
+ ppc_tb_base_icount = ppc_icount;
+
+ ppc.tb &= ~0xffffffff;
+ ppc.tb |= tbl;
+}
+
+INLINE void ppc_write_timebase_h(UINT32 tbh)
+{
+ ppc_tb_base_icount = ppc_icount;
+
+ ppc.tb &= 0xffffffff;
+ ppc.tb |= (UINT64)(tbh) << 32;
+}
+
+INLINE UINT32 read_decrementer(void)
+{
+ int cycles = ppc_dec_base_icount - ppc_icount;
+
+ // decrementer is decremented once every four bus clock cycles, so adjust the cycles accordingly
+ return DEC - (cycles / (bus_freq_multiplier * 2));
+}
+
+INLINE void write_decrementer(UINT32 value)
+{
+ ppc_dec_base_icount = ppc_icount + (ppc_dec_base_icount - ppc_icount) % (bus_freq_multiplier * 2);
+
+ DEC = value;
+
+ // check if decrementer exception occurs during execution
+ if ((UINT32)(DEC - ppc_icount) > (UINT32)(DEC))
+ {
+ ppc_dec_trigger_cycle = ppc_icount - DEC;
+ }
+ else
+ {
+ ppc_dec_trigger_cycle = 0x7fffffff;
+ }
+}
+
+/*********************************************************************/
+
+INLINE void ppc_set_spr(int spr, UINT32 value)
+{
+ switch (spr)
+ {
+ case SPR_LR: LR = value; return;
+ case SPR_CTR: CTR = value; return;
+ case SPR_XER: XER = value; return;
+ case SPR_SRR0: ppc.srr0 = value; return;
+ case SPR_SRR1: ppc.srr1 = value; return;
+ case SPR_SPRG0: ppc.sprg[0] = value; return;
+ case SPR_SPRG1: ppc.sprg[1] = value; return;
+ case SPR_SPRG2: ppc.sprg[2] = value; return;
+ case SPR_SPRG3: ppc.sprg[3] = value; return;
+ case SPR_PVR: return;
+ }
+
+ if(IS_PPC602() || IS_PPC603()) {
+ switch(spr)
+ {
+ case SPR603E_DEC:
+ if((value & 0x80000000) && !(DEC & 0x80000000))
+ {
+ /* trigger interrupt */
+ if (IS_PPC602())
+ ppc602_exception(EXCEPTION_DECREMENTER);
+ if (IS_PPC603())
+ ppc603_exception(EXCEPTION_DECREMENTER);
+ }
+ write_decrementer(value);
+ return;
+
+ case SPR603E_TBL_W:
+ case SPR603E_TBL_R: // special 603e case
+ ppc_write_timebase_l(value);
+ return;
+
+ case SPR603E_TBU_R:
+ case SPR603E_TBU_W: // special 603e case
+ ppc_write_timebase_h(value);
+ return;
+
+ case SPR603E_HID0: ppc.hid0 = value; return;
+ case SPR603E_HID1: ppc.hid1 = value; return;
+ case SPR603E_HID2: ppc.hid2 = value; return;
+
+ case SPR603E_DSISR: ppc.dsisr = value; return;
+ case SPR603E_DAR: ppc.dar = value; return;
+ case SPR603E_EAR: ppc.ear = value; return;
+ case SPR603E_DMISS: ppc.dmiss = value; return;
+ case SPR603E_DCMP: ppc.dcmp = value; return;
+ case SPR603E_HASH1: ppc.hash1 = value; return;
+ case SPR603E_HASH2: ppc.hash2 = value; return;
+ case SPR603E_IMISS: ppc.imiss = value; return;
+ case SPR603E_ICMP: ppc.icmp = value; return;
+ case SPR603E_RPA: ppc.rpa = value; return;
+
+ case SPR603E_IBAT0L: ppc.ibat[0].l = value; return;
+ case SPR603E_IBAT0U: ppc.ibat[0].u = value; return;
+ case SPR603E_IBAT1L: ppc.ibat[1].l = value; return;
+ case SPR603E_IBAT1U: ppc.ibat[1].u = value; return;
+ case SPR603E_IBAT2L: ppc.ibat[2].l = value; return;
+ case SPR603E_IBAT2U: ppc.ibat[2].u = value; return;
+ case SPR603E_IBAT3L: ppc.ibat[3].l = value; return;
+ case SPR603E_IBAT3U: ppc.ibat[3].u = value; return;
+ case SPR603E_DBAT0L: ppc.dbat[0].l = value; return;
+ case SPR603E_DBAT0U: ppc.dbat[0].u = value; return;
+ case SPR603E_DBAT1L: ppc.dbat[1].l = value; return;
+ case SPR603E_DBAT1U: ppc.dbat[1].u = value; return;
+ case SPR603E_DBAT2L: ppc.dbat[2].l = value; return;
+ case SPR603E_DBAT2U: ppc.dbat[2].u = value; return;
+ case SPR603E_DBAT3L: ppc.dbat[3].l = value; return;
+ case SPR603E_DBAT3U: ppc.dbat[3].u = value; return;
+
+ case SPR603E_SDR1:
+ ppc.sdr1 = value;
+ return;
+
+ case SPR603E_IABR: ppc.iabr = value; return;
+ }
+ }
+
+ if (ppc.is602) {
+ switch(spr)
+ {
+ case SPR602_LT: ppc.lt = value; return;
+ case SPR602_IBR: ppc.ibr = value; return;
+ case SPR602_SEBR: ppc.sebr = value; return;
+ case SPR602_SER: ppc.ser = value; return;
+ case SPR602_SP: ppc.sp = value; return;
+ case SPR602_TCR: ppc.tcr = value; return;
+ }
+ }
+
+ if (IS_PPC403()) {
+ switch(spr)
+ {
+ case SPR403_TBHI: ppc_write_timebase_h(value); return;
+ case SPR403_TBLO: ppc_write_timebase_l(value); return;
+
+ case SPR403_TSR:
+ ppc.tsr &= ~value; // 1 clears, 0 does nothing
+ return;
+
+ case SPR403_TCR:
+ switch((value >> 24) & 0x3)
+ {
+ case 0: ppc.fit_bit = 1 << 8; break;
+ case 1: ppc.fit_bit = 1 << 12; break;
+ case 2: ppc.fit_bit = 1 << 16; break;
+ case 3: ppc.fit_bit = 1 << 20; break;
+ }
+ switch((value >> 30) & 0x3)
+ {
+ case 0: ppc.wdt_bit = 1 << 16; break;
+ case 1: ppc.wdt_bit = 1 << 20; break;
+ case 2: ppc.wdt_bit = 1 << 24; break;
+ case 3: ppc.wdt_bit = 1 << 28; break;
+ }
+ ppc.fit_int_enable = (value >> 23) & 0x1;
+ ppc.wdt_int_enable = (value >> 27) & 0x1;
+ ppc.tcr = value;
+
+ if (!ppc.fit_int_enable)
+ {
+ ppc.interrupt_pending &= ~0x4;
+ }
+ return;
+
+ case SPR403_ESR: ppc.esr = value; return;
+ case SPR403_ICCR: ppc.iccr = value; return;
+ case SPR403_DCCR: ppc.dccr = value; return;
+ case SPR403_EVPR: EVPR = value & 0xffff0000; return;
+ case SPR403_PIT: ppc.pit = value; return;
+ case SPR403_SGR: ppc.sgr = value; return;
+ case SPR403_DBSR: ppc.dbsr = value; return;
+ case SPR403_DCWR: return;
+ case SPR403_PID: ppc.pid = value; return;
+ case SPR403_PBL1: ppc.pbl1 = value; return;
+ case SPR403_PBU1: ppc.pbu1 = value; return;
+ case SPR403_PBL2: ppc.pbl2 = value; return;
+ case SPR403_PBU2: ppc.pbu2 = value; return;
+ case SPR403_SRR2: ppc.srr2 = value; return;
+ case SPR403_SRR3: ppc.srr3 = value; return;
+ case SPR403_DAC1: ppc.dac1 = value; return;
+ case SPR403_DAC2: ppc.dac2 = value; return;
+ case SPR403_IAC1: ppc.iac1 = value; return;
+ case SPR403_IAC2: ppc.iac2 = value; return;
+ }
+ }
+
+ fatalerror("ppc: set_spr: unknown spr %d (%03X) !", spr, spr);
+}
+
+INLINE UINT32 ppc_get_spr(int spr)
+{
+ switch(spr)
+ {
+ case SPR_LR: return LR;
+ case SPR_CTR: return CTR;
+ case SPR_XER: return XER;
+ case SPR_SRR0: return ppc.srr0;
+ case SPR_SRR1: return ppc.srr1;
+ case SPR_SPRG0: return ppc.sprg[0];
+ case SPR_SPRG1: return ppc.sprg[1];
+ case SPR_SPRG2: return ppc.sprg[2];
+ case SPR_SPRG3: return ppc.sprg[3];
+ case SPR_PVR: return ppc.pvr;
+ }
+
+ if (IS_PPC403())
+ {
+ switch (spr)
+ {
+ case SPR403_TBLU:
+ case SPR403_TBLO: return (UINT32)(ppc_read_timebase());
+ case SPR403_TBHU:
+ case SPR403_TBHI: return (UINT32)(ppc_read_timebase() >> 32);
+
+ case SPR403_EVPR: return EVPR;
+ case SPR403_ESR: return ppc.esr;
+ case SPR403_TCR: return ppc.tcr;
+ case SPR403_ICCR: return ppc.iccr;
+ case SPR403_DCCR: return ppc.dccr;
+ case SPR403_PIT: return ppc.pit;
+ case SPR403_DBSR: return ppc.dbsr;
+ case SPR403_SGR: return ppc.sgr;
+ case SPR403_TSR: return ppc.tsr;
+ case SPR403_PBL1: return ppc.pbl1;
+ case SPR403_PBU1: return ppc.pbu1;
+ case SPR403_PBL2: return ppc.pbl2;
+ case SPR403_PBU2: return ppc.pbu2;
+ case SPR403_SRR2: return ppc.srr2;
+ case SPR403_SRR3: return ppc.srr3;
+ case SPR403_DAC1: return ppc.dac1;
+ case SPR403_DAC2: return ppc.dac2;
+ case SPR403_IAC1: return ppc.iac1;
+ case SPR403_IAC2: return ppc.iac2;
+ }
+ }
+
+ if (ppc.is602) {
+ switch(spr)
+ {
+ case SPR602_LT: return ppc.lt;
+ case SPR602_IBR: return ppc.ibr;
+ case SPR602_ESASRR: return ppc.esasrr;
+ case SPR602_SEBR: return ppc.sebr;
+ case SPR602_SER: return ppc.ser;
+ case SPR602_SP: return ppc.sp;
+ case SPR602_TCR: return ppc.tcr;
+ }
+ }
+
+ if (IS_PPC603() || IS_PPC602())
+ {
+ switch (spr)
+ {
+ case SPR603E_TBL_R:
+ fatalerror("ppc: get_spr: TBL_R ");
+ break;
+
+ case SPR603E_TBU_R:
+ fatalerror("ppc: get_spr: TBU_R ");
+ break;
+
+ case SPR603E_TBL_W: return (UINT32)(ppc_read_timebase());
+ case SPR603E_TBU_W: return (UINT32)(ppc_read_timebase() >> 32);
+ case SPR603E_HID0: return ppc.hid0;
+ case SPR603E_HID1: return ppc.hid1;
+ case SPR603E_HID2: return ppc.hid2;
+ case SPR603E_DEC: return read_decrementer();
+ case SPR603E_SDR1: return ppc.sdr1;
+ case SPR603E_DSISR: return ppc.dsisr;
+ case SPR603E_DAR: return ppc.dar;
+ case SPR603E_EAR: return ppc.ear;
+ case SPR603E_DMISS: return ppc.dmiss;
+ case SPR603E_DCMP: return ppc.dcmp;
+ case SPR603E_HASH1: return ppc.hash1;
+ case SPR603E_HASH2: return ppc.hash2;
+ case SPR603E_IMISS: return ppc.imiss;
+ case SPR603E_ICMP: return ppc.icmp;
+ case SPR603E_RPA: return ppc.rpa;
+ case SPR603E_IBAT0L: return ppc.ibat[0].l;
+ case SPR603E_IBAT0U: return ppc.ibat[0].u;
+ case SPR603E_IBAT1L: return ppc.ibat[1].l;
+ case SPR603E_IBAT1U: return ppc.ibat[1].u;
+ case SPR603E_IBAT2L: return ppc.ibat[2].l;
+ case SPR603E_IBAT2U: return ppc.ibat[2].u;
+ case SPR603E_IBAT3L: return ppc.ibat[3].l;
+ case SPR603E_IBAT3U: return ppc.ibat[3].u;
+ case SPR603E_DBAT0L: return ppc.dbat[0].l;
+ case SPR603E_DBAT0U: return ppc.dbat[0].u;
+ case SPR603E_DBAT1L: return ppc.dbat[1].l;
+ case SPR603E_DBAT1U: return ppc.dbat[1].u;
+ case SPR603E_DBAT2L: return ppc.dbat[2].l;
+ case SPR603E_DBAT2U: return ppc.dbat[2].u;
+ case SPR603E_DBAT3L: return ppc.dbat[3].l;
+ case SPR603E_DBAT3U: return ppc.dbat[3].u;
+ }
+ }
+
+ fatalerror("ppc: get_spr: unknown spr %d (%03X) !", spr, spr);
+ return 0;
+}
+
+static UINT8 ppc_read8_translated(address_space *space, offs_t address);
+static UINT16 ppc_read16_translated(address_space *space, offs_t address);
+static UINT32 ppc_read32_translated(address_space *space, offs_t address);
+static UINT64 ppc_read64_translated(address_space *space, offs_t address);
+static void ppc_write8_translated(address_space *space, offs_t address, UINT8 data);
+static void ppc_write16_translated(address_space *space, offs_t address, UINT16 data);
+static void ppc_write32_translated(address_space *space, offs_t address, UINT32 data);
+static void ppc_write64_translated(address_space *space, offs_t address, UINT64 data);
+
+INLINE void ppc_set_msr(UINT32 value)
+{
+ if( value & (MSR_ILE | MSR_LE) )
+ fatalerror("ppc: set_msr: little_endian mode not supported !");
+
+ MSR = value;
+
+ if (IS_PPC603() || IS_PPC602())
+ {
+ if (!(MSR & MSR_DR))
+ {
+ ppc.read8 = memory_read_byte_64be;
+ ppc.read16 = memory_read_word_64be;
+ ppc.read32 = memory_read_dword_64be;
+ ppc.read64 = memory_read_qword_64be;
+ ppc.write8 = memory_write_byte_64be;
+ ppc.write16 = memory_write_word_64be;
+ ppc.write32 = memory_write_dword_64be;
+ ppc.write64 = memory_write_qword_64be;
+ }
+ else
+ {
+ ppc.read8 = ppc_read8_translated;
+ ppc.read16 = ppc_read16_translated;
+ ppc.read32 = ppc_read32_translated;
+ ppc.read64 = ppc_read64_translated;
+ ppc.write8 = ppc_write8_translated;
+ ppc.write16 = ppc_write16_translated;
+ ppc.write32 = ppc_write32_translated;
+ ppc.write64 = ppc_write64_translated;
+ }
+ }
+}
+
+INLINE UINT32 ppc_get_msr(void)
+{
+ return MSR;
+}
+
+INLINE void ppc_set_cr(UINT32 value)
+{
+ CR(0) = (value >> 28) & 0xf;
+ CR(1) = (value >> 24) & 0xf;
+ CR(2) = (value >> 20) & 0xf;
+ CR(3) = (value >> 16) & 0xf;
+ CR(4) = (value >> 12) & 0xf;
+ CR(5) = (value >> 8) & 0xf;
+ CR(6) = (value >> 4) & 0xf;
+ CR(7) = (value >> 0) & 0xf;
+}
+
+INLINE UINT32 ppc_get_cr(void)
+{
+ return CR(0) << 28 | CR(1) << 24 | CR(2) << 20 | CR(3) << 16 | CR(4) << 12 | CR(5) << 8 | CR(6) << 4 | CR(7);
+}
+
+INLINE void ppc_exception(int exception_type)
+{
+ longjmp(ppc.exception_jmpbuf, exception_type);
+}
+
+/***********************************************************************/
+
+#include "ppc_mem.c"
+
+#include "ppc403.c"
+#include "ppc602.c"
+#include "ppc603.c"
+
+/********************************************************************/
+
+#include "ppc_ops.c"
+#include "ppc_ops.h"
+
+/* Initialization and shutdown */
+
+static void ppc_init(void)
+{
+ int i,j;
+
+ memset(&ppc, 0, sizeof(ppc));
+
+ for( i=0; i < 64; i++ ) {
+ ppc.optable[i] = ppc_invalid;
+ }
+ for( i=0; i < 1024; i++ ) {
+ ppc.optable19[i] = ppc_invalid;
+ ppc.optable31[i] = ppc_invalid;
+ ppc.optable59[i] = ppc_invalid;
+ ppc.optable63[i] = ppc_invalid;
+ }
+
+ /* Fill the opcode tables */
+ for( i=0; i < (sizeof(ppc_opcode_common) / sizeof(PPC_OPCODE)); i++ ) {
+
+ switch(ppc_opcode_common[i].code)
+ {
+ case 19:
+ ppc.optable19[ppc_opcode_common[i].subcode] = ppc_opcode_common[i].handler;
+ break;
+
+ case 31:
+ ppc.optable31[ppc_opcode_common[i].subcode] = ppc_opcode_common[i].handler;
+ break;
+
+ case 59:
+ case 63:
+ break;
+
+ default:
+ ppc.optable[ppc_opcode_common[i].code] = ppc_opcode_common[i].handler;
+ }
+
+ }
+
+ /* Calculate rotate mask table */
+ for( i=0; i < 32; i++ ) {
+ for( j=0; j < 32; j++ ) {
+ UINT32 mask;
+ int mb = i;
+ int me = j;
+ mask = ((UINT32)0xFFFFFFFF >> mb) ^ ((me >= 31) ? 0 : ((UINT32)0xFFFFFFFF >> (me + 1)));
+ if( mb > me )
+ mask = ~mask;
+
+ ppc_rotate_mask[i][j] = mask;
+ }
+ }
+}
+
+
+// !!! probably should move this stuff elsewhere !!!
+static CPU_INIT( ppc403 )
+{
+ const ppc_config *configdata = device->static_config();
+
+ ppc_init();
+
+ /* PPC403 specific opcodes */
+ ppc.optable31[454] = ppc_dccci;
+ ppc.optable31[486] = ppc_dcread;
+ ppc.optable31[262] = ppc_icbt;
+ ppc.optable31[966] = ppc_iccci;
+ ppc.optable31[998] = ppc_icread;
+ ppc.optable31[323] = ppc_mfdcr;
+ ppc.optable31[451] = ppc_mtdcr;
+ ppc.optable31[131] = ppc_wrtee;
+ ppc.optable31[163] = ppc_wrteei;
+
+ // !!! why is rfci here !!!
+ ppc.optable19[51] = ppc_rfci;
+
+ ppc.spu.rx_timer = device->machine().scheduler().timer_alloc(FUNC(ppc403_spu_rx_callback));
+ ppc.spu.tx_timer = device->machine().scheduler().timer_alloc(FUNC(ppc403_spu_tx_callback));
+
+ ppc.read8 = ppc403_read8;
+ ppc.read16 = ppc403_read16;
+ ppc.read32 = ppc403_read32;
+ ppc.write8 = ppc403_write8;
+ ppc.write16 = ppc403_write16;
+ ppc.write32 = ppc403_write32;
+ ppc.read16_unaligned = ppc403_read16_unaligned;
+ ppc.read32_unaligned = ppc403_read32_unaligned;
+ ppc.write16_unaligned = ppc403_write16_unaligned;
+ ppc.write32_unaligned = ppc403_write32_unaligned;
+
+ ppc.irq_callback = irqcallback;
+ ppc.device = device;
+ ppc.program = device->space(AS_PROGRAM);
+
+ ppc.pvr = configdata->pvr;
+}
+
+static CPU_EXIT( ppc403 )
+{
+
+}
+
+static CPU_INIT( ppc603 )
+{
+ const ppc_config *configdata = device->static_config();
+ int pll_config = 0;
+ float multiplier;
+ int i ;
+
+ ppc_init() ;
+
+ ppc.optable[48] = ppc_lfs;
+ ppc.optable[49] = ppc_lfsu;
+ ppc.optable[50] = ppc_lfd;
+ ppc.optable[51] = ppc_lfdu;
+ ppc.optable[52] = ppc_stfs;
+ ppc.optable[53] = ppc_stfsu;
+ ppc.optable[54] = ppc_stfd;
+ ppc.optable[55] = ppc_stfdu;
+ ppc.optable31[631] = ppc_lfdux;
+ ppc.optable31[599] = ppc_lfdx;
+ ppc.optable31[567] = ppc_lfsux;
+ ppc.optable31[535] = ppc_lfsx;
+ ppc.optable31[595] = ppc_mfsr;
+ ppc.optable31[659] = ppc_mfsrin;
+ ppc.optable31[371] = ppc_mftb;
+ ppc.optable31[210] = ppc_mtsr;
+ ppc.optable31[242] = ppc_mtsrin;
+ ppc.optable31[758] = ppc_dcba;
+ ppc.optable31[759] = ppc_stfdux;
+ ppc.optable31[727] = ppc_stfdx;
+ ppc.optable31[983] = ppc_stfiwx;
+ ppc.optable31[695] = ppc_stfsux;
+ ppc.optable31[663] = ppc_stfsx;
+ ppc.optable31[370] = ppc_tlbia;
+ ppc.optable31[306] = ppc_tlbie;
+ ppc.optable31[566] = ppc_tlbsync;
+ ppc.optable31[310] = ppc_eciwx;
+ ppc.optable31[438] = ppc_ecowx;
+
+ ppc.optable63[264] = ppc_fabsx;
+ ppc.optable63[21] = ppc_faddx;
+ ppc.optable63[32] = ppc_fcmpo;
+ ppc.optable63[0] = ppc_fcmpu;
+ ppc.optable63[14] = ppc_fctiwx;
+ ppc.optable63[15] = ppc_fctiwzx;
+ ppc.optable63[18] = ppc_fdivx;
+ ppc.optable63[72] = ppc_fmrx;
+ ppc.optable63[136] = ppc_fnabsx;
+ ppc.optable63[40] = ppc_fnegx;
+ ppc.optable63[12] = ppc_frspx;
+ ppc.optable63[26] = ppc_frsqrtex;
+ ppc.optable63[22] = ppc_fsqrtx;
+ ppc.optable63[20] = ppc_fsubx;
+ ppc.optable63[583] = ppc_mffsx;
+ ppc.optable63[70] = ppc_mtfsb0x;
+ ppc.optable63[38] = ppc_mtfsb1x;
+ ppc.optable63[711] = ppc_mtfsfx;
+ ppc.optable63[134] = ppc_mtfsfix;
+ ppc.optable63[64] = ppc_mcrfs;
+
+ ppc.optable59[21] = ppc_faddsx;
+ ppc.optable59[18] = ppc_fdivsx;
+ ppc.optable59[24] = ppc_fresx;
+ ppc.optable59[22] = ppc_fsqrtsx;
+ ppc.optable59[20] = ppc_fsubsx;
+
+ for(i = 0; i < 32; i++)
+ {
+ ppc.optable63[i * 32 | 29] = ppc_fmaddx;
+ ppc.optable63[i * 32 | 28] = ppc_fmsubx;
+ ppc.optable63[i * 32 | 25] = ppc_fmulx;
+ ppc.optable63[i * 32 | 31] = ppc_fnmaddx;
+ ppc.optable63[i * 32 | 30] = ppc_fnmsubx;
+ ppc.optable63[i * 32 | 23] = ppc_fselx;
+
+ ppc.optable59[i * 32 | 29] = ppc_fmaddsx;
+ ppc.optable59[i * 32 | 28] = ppc_fmsubsx;
+ ppc.optable59[i * 32 | 25] = ppc_fmulsx;
+ ppc.optable59[i * 32 | 31] = ppc_fnmaddsx;
+ ppc.optable59[i * 32 | 30] = ppc_fnmsubsx;
+ }
+
+ ppc.optable31[978] = ppc_tlbld;
+
+ for(i = 0; i < 256; i++)
+ {
+ ppc_field_xlat[i] =
+ ((i & 0x80) ? 0xF0000000 : 0) |
+ ((i & 0x40) ? 0x0F000000 : 0) |
+ ((i & 0x20) ? 0x00F00000 : 0) |
+ ((i & 0x10) ? 0x000F0000 : 0) |
+ ((i & 0x08) ? 0x0000F000 : 0) |
+ ((i & 0x04) ? 0x00000F00 : 0) |
+ ((i & 0x02) ? 0x000000F0 : 0) |
+ ((i & 0x01) ? 0x0000000F : 0);
+ }
+
+ ppc.is603 = 1;
+
+ ppc.read8 = memory_read_byte_64be;
+ ppc.read16 = memory_read_word_64be;
+ ppc.read32 = memory_read_dword_64be;
+ ppc.read64 = memory_read_qword_64be;
+ ppc.write8 = memory_write_byte_64be;
+ ppc.write16 = memory_write_word_64be;
+ ppc.write32 = memory_write_dword_64be;
+ ppc.write64 = memory_write_qword_64be;
+ ppc.read16_unaligned = ppc_read16_unaligned;
+ ppc.read32_unaligned = ppc_read32_unaligned;
+ ppc.read64_unaligned = ppc_read64_unaligned;
+ ppc.write16_unaligned = ppc_write16_unaligned;
+ ppc.write32_unaligned = ppc_write32_unaligned;
+ ppc.write64_unaligned = ppc_write64_unaligned;
+
+ ppc.irq_callback = irqcallback;
+ ppc.device = device;
+ ppc.program = device->space(AS_PROGRAM);
+
+ ppc.pvr = configdata->pvr;
+
+ multiplier = (float)((configdata->bus_frequency_multiplier >> 4) & 0xf) +
+ (float)(configdata->bus_frequency_multiplier & 0xf) / 10.0f;
+ bus_freq_multiplier = (int)(multiplier * 2);
+
+ switch(config->pvr)
+ {
+ case PPC_MODEL_603E: pll_config = mpc603e_pll_config[bus_freq_multiplier-1][configdata->bus_frequency]; break;
+ case PPC_MODEL_603EV: pll_config = mpc603ev_pll_config[bus_freq_multiplier-1][configdata->bus_frequency]; break;
+ case PPC_MODEL_603R: pll_config = mpc603r_pll_config[bus_freq_multiplier-1][configdata->bus_frequency]; break;
+ default: break;
+ }
+
+ if (pll_config == -1)
+ {
+ fatalerror("PPC: Invalid bus/multiplier combination (bus frequency = %d, multiplier = %1.1f)", config->bus_frequency, multiplier);
+ }
+
+ ppc.hid1 = pll_config << 28;
+}
+
+static CPU_EXIT( ppc603 )
+{
+
+}
+
+static CPU_INIT( ppc602 )
+{
+ float multiplier;
+ const ppc_config *configdata = device->static_config();
+
+ int i ;
+
+ ppc_init() ;
+
+ ppc.optable[48] = ppc_lfs;
+ ppc.optable[49] = ppc_lfsu;
+ ppc.optable[50] = ppc_lfd;
+ ppc.optable[51] = ppc_lfdu;
+ ppc.optable[52] = ppc_stfs;
+ ppc.optable[53] = ppc_stfsu;
+ ppc.optable[54] = ppc_stfd;
+ ppc.optable[55] = ppc_stfdu;
+ ppc.optable31[631] = ppc_lfdux;
+ ppc.optable31[599] = ppc_lfdx;
+ ppc.optable31[567] = ppc_lfsux;
+ ppc.optable31[535] = ppc_lfsx;
+ ppc.optable31[595] = ppc_mfsr;
+ ppc.optable31[659] = ppc_mfsrin;
+ ppc.optable31[371] = ppc_mftb;
+ ppc.optable31[210] = ppc_mtsr;
+ ppc.optable31[242] = ppc_mtsrin;
+ ppc.optable31[758] = ppc_dcba;
+ ppc.optable31[759] = ppc_stfdux;
+ ppc.optable31[727] = ppc_stfdx;
+ ppc.optable31[983] = ppc_stfiwx;
+ ppc.optable31[695] = ppc_stfsux;
+ ppc.optable31[663] = ppc_stfsx;
+ ppc.optable31[370] = ppc_tlbia;
+ ppc.optable31[306] = ppc_tlbie;
+ ppc.optable31[566] = ppc_tlbsync;
+ ppc.optable31[310] = ppc_eciwx;
+ ppc.optable31[438] = ppc_ecowx;
+
+ ppc.optable63[264] = ppc_fabsx;
+ ppc.optable63[21] = ppc_faddx;
+ ppc.optable63[32] = ppc_fcmpo;
+ ppc.optable63[0] = ppc_fcmpu;
+ ppc.optable63[14] = ppc_fctiwx;
+ ppc.optable63[15] = ppc_fctiwzx;
+ ppc.optable63[18] = ppc_fdivx;
+ ppc.optable63[72] = ppc_fmrx;
+ ppc.optable63[136] = ppc_fnabsx;
+ ppc.optable63[40] = ppc_fnegx;
+ ppc.optable63[12] = ppc_frspx;
+ ppc.optable63[26] = ppc_frsqrtex;
+ ppc.optable63[22] = ppc_fsqrtx;
+ ppc.optable63[20] = ppc_fsubx;
+ ppc.optable63[583] = ppc_mffsx;
+ ppc.optable63[70] = ppc_mtfsb0x;
+ ppc.optable63[38] = ppc_mtfsb1x;
+ ppc.optable63[711] = ppc_mtfsfx;
+ ppc.optable63[134] = ppc_mtfsfix;
+ ppc.optable63[64] = ppc_mcrfs;
+
+ ppc.optable59[21] = ppc_faddsx;
+ ppc.optable59[18] = ppc_fdivsx;
+ ppc.optable59[24] = ppc_fresx;
+ ppc.optable59[22] = ppc_fsqrtsx;
+ ppc.optable59[20] = ppc_fsubsx;
+
+ for(i = 0; i < 32; i++)
+ {
+ ppc.optable63[i * 32 | 29] = ppc_fmaddx;
+ ppc.optable63[i * 32 | 28] = ppc_fmsubx;
+ ppc.optable63[i * 32 | 25] = ppc_fmulx;
+ ppc.optable63[i * 32 | 31] = ppc_fnmaddx;
+ ppc.optable63[i * 32 | 30] = ppc_fnmsubx;
+ ppc.optable63[i * 32 | 23] = ppc_fselx;
+
+ ppc.optable59[i * 32 | 29] = ppc_fmaddsx;
+ ppc.optable59[i * 32 | 28] = ppc_fmsubsx;
+ ppc.optable59[i * 32 | 25] = ppc_fmulsx;
+ ppc.optable59[i * 32 | 31] = ppc_fnmaddsx;
+ ppc.optable59[i * 32 | 30] = ppc_fnmsubsx;
+ }
+
+ for(i = 0; i < 256; i++)
+ {
+ ppc_field_xlat[i] =
+ ((i & 0x80) ? 0xF0000000 : 0) |
+ ((i & 0x40) ? 0x0F000000 : 0) |
+ ((i & 0x20) ? 0x00F00000 : 0) |
+ ((i & 0x10) ? 0x000F0000 : 0) |
+ ((i & 0x08) ? 0x0000F000 : 0) |
+ ((i & 0x04) ? 0x00000F00 : 0) |
+ ((i & 0x02) ? 0x000000F0 : 0) |
+ ((i & 0x01) ? 0x0000000F : 0);
+ }
+
+ // PPC602 specific opcodes
+ ppc.optable31[596] = ppc_esa;
+ ppc.optable31[628] = ppc_dsa;
+ ppc.optable31[1010] = ppc_tlbli;
+ ppc.optable31[978] = ppc_tlbld;
+
+ ppc.is602 = 1;
+
+ ppc.read8 = memory_read_byte_64be;
+ ppc.read16 = memory_read_word_64be;
+ ppc.read32 = memory_read_dword_64be;
+ ppc.read64 = memory_read_qword_64be;
+ ppc.write8 = memory_write_byte_64be;
+ ppc.write16 = memory_write_word_64be;
+ ppc.write32 = memory_write_dword_64be;
+ ppc.write64 = memory_write_qword_64be;
+ ppc.read16_unaligned = ppc_read16_unaligned;
+ ppc.read32_unaligned = ppc_read32_unaligned;
+ ppc.read64_unaligned = ppc_read64_unaligned;
+ ppc.write16_unaligned = ppc_write16_unaligned;
+ ppc.write32_unaligned = ppc_write32_unaligned;
+ ppc.write64_unaligned = ppc_write64_unaligned;
+
+ ppc.irq_callback = irqcallback;
+ ppc.device = device;
+ ppc.program = device->space(AS_PROGRAM);
+
+ ppc.pvr = configdata->pvr;
+
+ multiplier = (float)((configdata->bus_frequency_multiplier >> 4) & 0xf) +
+ (float)(configdata->bus_frequency_multiplier & 0xf) / 10.0f;
+ bus_freq_multiplier = (int)(multiplier * 2);
+}
+
+static CPU_EXIT( ppc602 )
+{
+
+}
+
+static void mpc8240_tlbli(UINT32 op)
+{
+
+}
+
+static void mpc8240_tlbld(UINT32 op)
+{
+
+}
+
+static CPU_INIT( mpc8240 )
+{
+ float multiplier;
+ const ppc_config *configdata = device->static_config();
+
+ int i ;
+
+ ppc_init();
+
+ ppc.optable[48] = ppc_lfs;
+ ppc.optable[49] = ppc_lfsu;
+ ppc.optable[50] = ppc_lfd;
+ ppc.optable[51] = ppc_lfdu;
+ ppc.optable[52] = ppc_stfs;
+ ppc.optable[53] = ppc_stfsu;
+ ppc.optable[54] = ppc_stfd;
+ ppc.optable[55] = ppc_stfdu;
+ ppc.optable31[631] = ppc_lfdux;
+ ppc.optable31[599] = ppc_lfdx;
+ ppc.optable31[567] = ppc_lfsux;
+ ppc.optable31[535] = ppc_lfsx;
+ ppc.optable31[595] = ppc_mfsr;
+ ppc.optable31[659] = ppc_mfsrin;
+ ppc.optable31[371] = ppc_mftb;
+ ppc.optable31[210] = ppc_mtsr;
+ ppc.optable31[242] = ppc_mtsrin;
+ ppc.optable31[758] = ppc_dcba;
+ ppc.optable31[759] = ppc_stfdux;
+ ppc.optable31[727] = ppc_stfdx;
+ ppc.optable31[983] = ppc_stfiwx;
+ ppc.optable31[695] = ppc_stfsux;
+ ppc.optable31[663] = ppc_stfsx;
+ ppc.optable31[370] = ppc_tlbia;
+ ppc.optable31[306] = ppc_tlbie;
+ ppc.optable31[566] = ppc_tlbsync;
+ ppc.optable31[310] = ppc_eciwx;
+ ppc.optable31[438] = ppc_ecowx;
+
+ ppc.optable63[264] = ppc_fabsx;
+ ppc.optable63[21] = ppc_faddx;
+ ppc.optable63[32] = ppc_fcmpo;
+ ppc.optable63[0] = ppc_fcmpu;
+ ppc.optable63[14] = ppc_fctiwx;
+ ppc.optable63[15] = ppc_fctiwzx;
+ ppc.optable63[18] = ppc_fdivx;
+ ppc.optable63[72] = ppc_fmrx;
+ ppc.optable63[136] = ppc_fnabsx;
+ ppc.optable63[40] = ppc_fnegx;
+ ppc.optable63[12] = ppc_frspx;
+ ppc.optable63[26] = ppc_frsqrtex;
+ ppc.optable63[22] = ppc_fsqrtx;
+ ppc.optable63[20] = ppc_fsubx;
+ ppc.optable63[583] = ppc_mffsx;
+ ppc.optable63[70] = ppc_mtfsb0x;
+ ppc.optable63[38] = ppc_mtfsb1x;
+ ppc.optable63[711] = ppc_mtfsfx;
+ ppc.optable63[134] = ppc_mtfsfix;
+ ppc.optable63[64] = ppc_mcrfs;
+
+ ppc.optable59[21] = ppc_faddsx;
+ ppc.optable59[18] = ppc_fdivsx;
+ ppc.optable59[24] = ppc_fresx;
+ ppc.optable59[22] = ppc_fsqrtsx;
+ ppc.optable59[20] = ppc_fsubsx;
+
+ for(i = 0; i < 32; i++)
+ {
+ ppc.optable63[i * 32 | 29] = ppc_fmaddx;
+ ppc.optable63[i * 32 | 28] = ppc_fmsubx;
+ ppc.optable63[i * 32 | 25] = ppc_fmulx;
+ ppc.optable63[i * 32 | 31] = ppc_fnmaddx;
+ ppc.optable63[i * 32 | 30] = ppc_fnmsubx;
+ ppc.optable63[i * 32 | 23] = ppc_fselx;
+
+ ppc.optable59[i * 32 | 29] = ppc_fmaddsx;
+ ppc.optable59[i * 32 | 28] = ppc_fmsubsx;
+ ppc.optable59[i * 32 | 25] = ppc_fmulsx;
+ ppc.optable59[i * 32 | 31] = ppc_fnmaddsx;
+ ppc.optable59[i * 32 | 30] = ppc_fnmsubsx;
+ }
+
+ for(i = 0; i < 256; i++)
+ {
+ ppc_field_xlat[i] =
+ ((i & 0x80) ? 0xF0000000 : 0) |
+ ((i & 0x40) ? 0x0F000000 : 0) |
+ ((i & 0x20) ? 0x00F00000 : 0) |
+ ((i & 0x10) ? 0x000F0000 : 0) |
+ ((i & 0x08) ? 0x0000F000 : 0) |
+ ((i & 0x04) ? 0x00000F00 : 0) |
+ ((i & 0x02) ? 0x000000F0 : 0) |
+ ((i & 0x01) ? 0x0000000F : 0);
+ }
+
+ // MPC8240 specific opcodes
+ ppc.optable31[978] = mpc8240_tlbld;
+ ppc.optable31[1010] = mpc8240_tlbli;
+
+ ppc.is603 = 1;
+
+ ppc.read8 = memory_read_byte_64be;
+ ppc.read16 = memory_read_word_64be;
+ ppc.read32 = memory_read_dword_64be;
+ ppc.read64 = memory_read_qword_64be;
+ ppc.write8 = memory_write_byte_64be;
+ ppc.write16 = memory_write_word_64be;
+ ppc.write32 = memory_write_dword_64be;
+ ppc.write64 = memory_write_qword_64be;
+ ppc.read16_unaligned = ppc_read16_unaligned;
+ ppc.read32_unaligned = ppc_read32_unaligned;
+ ppc.read64_unaligned = ppc_read64_unaligned;
+ ppc.write16_unaligned = ppc_write16_unaligned;
+ ppc.write32_unaligned = ppc_write32_unaligned;
+ ppc.write64_unaligned = ppc_write64_unaligned;
+
+ ppc.irq_callback = irqcallback;
+ ppc.device = device;
+ ppc.program = device->space(AS_PROGRAM);
+
+ ppc.pvr = configdata->pvr;
+
+ multiplier = (float)((configdata->bus_frequency_multiplier >> 4) & 0xf) +
+ (float)(configdata->bus_frequency_multiplier & 0xf) / 10.0f;
+ bus_freq_multiplier = (int)(multiplier * 2);
+}
+
+static CPU_EXIT( mpc8240 )
+{
+
+}
+
+static CPU_INIT( ppc601 )
+{
+ const ppc_config *configdata = device->static_config();
+ float multiplier;
+ int i ;
+
+ ppc_init() ;
+
+ ppc.optable[48] = ppc_lfs;
+ ppc.optable[49] = ppc_lfsu;
+ ppc.optable[50] = ppc_lfd;
+ ppc.optable[51] = ppc_lfdu;
+ ppc.optable[52] = ppc_stfs;
+ ppc.optable[53] = ppc_stfsu;
+ ppc.optable[54] = ppc_stfd;
+ ppc.optable[55] = ppc_stfdu;
+ ppc.optable31[631] = ppc_lfdux;
+ ppc.optable31[599] = ppc_lfdx;
+ ppc.optable31[567] = ppc_lfsux;
+ ppc.optable31[535] = ppc_lfsx;
+ ppc.optable31[595] = ppc_mfsr;
+ ppc.optable31[659] = ppc_mfsrin;
+ ppc.optable31[371] = ppc_mftb;
+ ppc.optable31[210] = ppc_mtsr;
+ ppc.optable31[242] = ppc_mtsrin;
+ ppc.optable31[758] = ppc_dcba;
+ ppc.optable31[759] = ppc_stfdux;
+ ppc.optable31[727] = ppc_stfdx;
+ ppc.optable31[983] = ppc_stfiwx;
+ ppc.optable31[695] = ppc_stfsux;
+ ppc.optable31[663] = ppc_stfsx;
+ ppc.optable31[370] = ppc_tlbia;
+ ppc.optable31[306] = ppc_tlbie;
+ ppc.optable31[566] = ppc_tlbsync;
+ ppc.optable31[310] = ppc_eciwx;
+ ppc.optable31[438] = ppc_ecowx;
+
+ ppc.optable63[264] = ppc_fabsx;
+ ppc.optable63[21] = ppc_faddx;
+ ppc.optable63[32] = ppc_fcmpo;
+ ppc.optable63[0] = ppc_fcmpu;
+ ppc.optable63[14] = ppc_fctiwx;
+ ppc.optable63[15] = ppc_fctiwzx;
+ ppc.optable63[18] = ppc_fdivx;
+ ppc.optable63[72] = ppc_fmrx;
+ ppc.optable63[136] = ppc_fnabsx;
+ ppc.optable63[40] = ppc_fnegx;
+ ppc.optable63[12] = ppc_frspx;
+ ppc.optable63[26] = ppc_frsqrtex;
+ ppc.optable63[22] = ppc_fsqrtx;
+ ppc.optable63[20] = ppc_fsubx;
+ ppc.optable63[583] = ppc_mffsx;
+ ppc.optable63[70] = ppc_mtfsb0x;
+ ppc.optable63[38] = ppc_mtfsb1x;
+ ppc.optable63[711] = ppc_mtfsfx;
+ ppc.optable63[134] = ppc_mtfsfix;
+ ppc.optable63[64] = ppc_mcrfs;
+
+ ppc.optable59[21] = ppc_faddsx;
+ ppc.optable59[18] = ppc_fdivsx;
+ ppc.optable59[24] = ppc_fresx;
+ ppc.optable59[22] = ppc_fsqrtsx;
+ ppc.optable59[20] = ppc_fsubsx;
+
+ for(i = 0; i < 32; i++)
+ {
+ ppc.optable63[i * 32 | 29] = ppc_fmaddx;
+ ppc.optable63[i * 32 | 28] = ppc_fmsubx;
+ ppc.optable63[i * 32 | 25] = ppc_fmulx;
+ ppc.optable63[i * 32 | 31] = ppc_fnmaddx;
+ ppc.optable63[i * 32 | 30] = ppc_fnmsubx;
+ ppc.optable63[i * 32 | 23] = ppc_fselx;
+
+ ppc.optable59[i * 32 | 29] = ppc_fmaddsx;
+ ppc.optable59[i * 32 | 28] = ppc_fmsubsx;
+ ppc.optable59[i * 32 | 25] = ppc_fmulsx;
+ ppc.optable59[i * 32 | 31] = ppc_fnmaddsx;
+ ppc.optable59[i * 32 | 30] = ppc_fnmsubsx;
+ }
+
+ for(i = 0; i < 256; i++)
+ {
+ ppc_field_xlat[i] =
+ ((i & 0x80) ? 0xF0000000 : 0) |
+ ((i & 0x40) ? 0x0F000000 : 0) |
+ ((i & 0x20) ? 0x00F00000 : 0) |
+ ((i & 0x10) ? 0x000F0000 : 0) |
+ ((i & 0x08) ? 0x0000F000 : 0) |
+ ((i & 0x04) ? 0x00000F00 : 0) |
+ ((i & 0x02) ? 0x000000F0 : 0) |
+ ((i & 0x01) ? 0x0000000F : 0);
+ }
+
+ ppc.is603 = 1;
+
+ ppc.read8 = memory_read_byte_64be;
+ ppc.read16 = memory_read_word_64be;
+ ppc.read32 = memory_read_dword_64be;
+ ppc.read64 = memory_read_qword_64be;
+ ppc.write8 = memory_write_byte_64be;
+ ppc.write16 = memory_write_word_64be;
+ ppc.write32 = memory_write_dword_64be;
+ ppc.write64 = memory_write_qword_64be;
+ ppc.read16_unaligned = ppc_read16_unaligned;
+ ppc.read32_unaligned = ppc_read32_unaligned;
+ ppc.read64_unaligned = ppc_read64_unaligned;
+ ppc.write16_unaligned = ppc_write16_unaligned;
+ ppc.write32_unaligned = ppc_write32_unaligned;
+ ppc.write64_unaligned = ppc_write64_unaligned;
+
+ ppc.irq_callback = irqcallback;
+ ppc.device = device;
+ ppc.program = device->space(AS_PROGRAM);
+
+ ppc.pvr = configdata->pvr;
+
+ multiplier = (float)((configdata->bus_frequency_multiplier >> 4) & 0xf) +
+ (float)(configdata->bus_frequency_multiplier & 0xf) / 10.0f;
+ bus_freq_multiplier = (int)(multiplier * 2);
+
+ ppc.hid1 = 0;
+}
+
+static CPU_EXIT( ppc601 )
+{
+
+}
+
+static CPU_INIT( ppc604 )
+{
+ const ppc_config *configdata = device->static_config();
+ float multiplier;
+ int i ;
+
+ ppc_init() ;
+
+ ppc.optable[48] = ppc_lfs;
+ ppc.optable[49] = ppc_lfsu;
+ ppc.optable[50] = ppc_lfd;
+ ppc.optable[51] = ppc_lfdu;
+ ppc.optable[52] = ppc_stfs;
+ ppc.optable[53] = ppc_stfsu;
+ ppc.optable[54] = ppc_stfd;
+ ppc.optable[55] = ppc_stfdu;
+ ppc.optable31[631] = ppc_lfdux;
+ ppc.optable31[599] = ppc_lfdx;
+ ppc.optable31[567] = ppc_lfsux;
+ ppc.optable31[535] = ppc_lfsx;
+ ppc.optable31[595] = ppc_mfsr;
+ ppc.optable31[659] = ppc_mfsrin;
+ ppc.optable31[371] = ppc_mftb;
+ ppc.optable31[210] = ppc_mtsr;
+ ppc.optable31[242] = ppc_mtsrin;
+ ppc.optable31[758] = ppc_dcba;
+ ppc.optable31[759] = ppc_stfdux;
+ ppc.optable31[727] = ppc_stfdx;
+ ppc.optable31[983] = ppc_stfiwx;
+ ppc.optable31[695] = ppc_stfsux;
+ ppc.optable31[663] = ppc_stfsx;
+ ppc.optable31[370] = ppc_tlbia;
+ ppc.optable31[306] = ppc_tlbie;
+ ppc.optable31[566] = ppc_tlbsync;
+ ppc.optable31[310] = ppc_eciwx;
+ ppc.optable31[438] = ppc_ecowx;
+
+ ppc.optable63[264] = ppc_fabsx;
+ ppc.optable63[21] = ppc_faddx;
+ ppc.optable63[32] = ppc_fcmpo;
+ ppc.optable63[0] = ppc_fcmpu;
+ ppc.optable63[14] = ppc_fctiwx;
+ ppc.optable63[15] = ppc_fctiwzx;
+ ppc.optable63[18] = ppc_fdivx;
+ ppc.optable63[72] = ppc_fmrx;
+ ppc.optable63[136] = ppc_fnabsx;
+ ppc.optable63[40] = ppc_fnegx;
+ ppc.optable63[12] = ppc_frspx;
+ ppc.optable63[26] = ppc_frsqrtex;
+ ppc.optable63[22] = ppc_fsqrtx;
+ ppc.optable63[20] = ppc_fsubx;
+ ppc.optable63[583] = ppc_mffsx;
+ ppc.optable63[70] = ppc_mtfsb0x;
+ ppc.optable63[38] = ppc_mtfsb1x;
+ ppc.optable63[711] = ppc_mtfsfx;
+ ppc.optable63[134] = ppc_mtfsfix;
+ ppc.optable63[64] = ppc_mcrfs;
+
+ ppc.optable59[21] = ppc_faddsx;
+ ppc.optable59[18] = ppc_fdivsx;
+ ppc.optable59[24] = ppc_fresx;
+ ppc.optable59[22] = ppc_fsqrtsx;
+ ppc.optable59[20] = ppc_fsubsx;
+
+ for(i = 0; i < 32; i++)
+ {
+ ppc.optable63[i * 32 | 29] = ppc_fmaddx;
+ ppc.optable63[i * 32 | 28] = ppc_fmsubx;
+ ppc.optable63[i * 32 | 25] = ppc_fmulx;
+ ppc.optable63[i * 32 | 31] = ppc_fnmaddx;
+ ppc.optable63[i * 32 | 30] = ppc_fnmsubx;
+ ppc.optable63[i * 32 | 23] = ppc_fselx;
+
+ ppc.optable59[i * 32 | 29] = ppc_fmaddsx;
+ ppc.optable59[i * 32 | 28] = ppc_fmsubsx;
+ ppc.optable59[i * 32 | 25] = ppc_fmulsx;
+ ppc.optable59[i * 32 | 31] = ppc_fnmaddsx;
+ ppc.optable59[i * 32 | 30] = ppc_fnmsubsx;
+ }
+
+ ppc.optable31[978] = ppc_tlbld;
+
+ for(i = 0; i < 256; i++)
+ {
+ ppc_field_xlat[i] =
+ ((i & 0x80) ? 0xF0000000 : 0) |
+ ((i & 0x40) ? 0x0F000000 : 0) |
+ ((i & 0x20) ? 0x00F00000 : 0) |
+ ((i & 0x10) ? 0x000F0000 : 0) |
+ ((i & 0x08) ? 0x0000F000 : 0) |
+ ((i & 0x04) ? 0x00000F00 : 0) |
+ ((i & 0x02) ? 0x000000F0 : 0) |
+ ((i & 0x01) ? 0x0000000F : 0);
+ }
+
+ ppc.is603 = 1;
+
+ ppc.read8 = memory_read_byte_64be;
+ ppc.read16 = memory_read_word_64be;
+ ppc.read32 = memory_read_dword_64be;
+ ppc.read64 = memory_read_qword_64be;
+ ppc.write8 = memory_write_byte_64be;
+ ppc.write16 = memory_write_word_64be;
+ ppc.write32 = memory_write_dword_64be;
+ ppc.write64 = memory_write_qword_64be;
+ ppc.read16_unaligned = ppc_read16_unaligned;
+ ppc.read32_unaligned = ppc_read32_unaligned;
+ ppc.read64_unaligned = ppc_read64_unaligned;
+ ppc.write16_unaligned = ppc_write16_unaligned;
+ ppc.write32_unaligned = ppc_write32_unaligned;
+ ppc.write64_unaligned = ppc_write64_unaligned;
+
+ ppc.irq_callback = irqcallback;
+ ppc.device = device;
+ ppc.program = device->space(AS_PROGRAM);
+
+ ppc.pvr = configdata->pvr;
+
+ multiplier = (float)((configdata->bus_frequency_multiplier >> 4) & 0xf) +
+ (float)(configdata->bus_frequency_multiplier & 0xf) / 10.0f;
+ bus_freq_multiplier = (int)(multiplier * 2);
+
+ ppc.hid1 = 0;
+}
+
+static CPU_EXIT( ppc604 )
+{
+
+}
+
+
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( ppc )
+{
+ switch (state)
+ {
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + PPC_PC: ppc.pc = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_MSR: ppc_set_msr(info->i); break;
+ case CPUINFO_INT_REGISTER + PPC_CR: ppc_set_cr(info->i); break;
+ case CPUINFO_INT_REGISTER + PPC_LR: LR = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_CTR: CTR = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_XER: XER = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_SRR0: SRR0 = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_SRR1: SRR1 = info->i; break;
+
+ case CPUINFO_INT_REGISTER + PPC_R0: ppc.r[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R1: ppc.r[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R2: ppc.r[2] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R3: ppc.r[3] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R4: ppc.r[4] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R5: ppc.r[5] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R6: ppc.r[6] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R7: ppc.r[7] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R8: ppc.r[8] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R9: ppc.r[9] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R10: ppc.r[10] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R11: ppc.r[11] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R12: ppc.r[12] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R13: ppc.r[13] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R14: ppc.r[14] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R15: ppc.r[15] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R16: ppc.r[16] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R17: ppc.r[17] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R18: ppc.r[18] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R19: ppc.r[19] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R20: ppc.r[20] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R21: ppc.r[21] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R22: ppc.r[22] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R23: ppc.r[23] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R24: ppc.r[24] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R25: ppc.r[25] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R26: ppc.r[26] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R27: ppc.r[27] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R28: ppc.r[28] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R29: ppc.r[29] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R30: ppc.r[30] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R31: ppc.r[31] = info->i; break;
+ }
+}
+
+static CPU_SET_INFO( ppc403 )
+{
+ if (state >= CPUINFO_INT_INPUT_STATE && state <= CPUINFO_INT_INPUT_STATE + 8)
+ {
+ ppc403_set_irq_line(state-CPUINFO_INT_INPUT_STATE, info->i);
+ return;
+ }
+ switch(state)
+ {
+ case CPUINFO_INT_REGISTER + PPC_EXIER: EXIER = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_EXISR: EXISR = info->i; break;
+ default: ppc_set_info(state, info); break;
+ }
+}
+
+static CPU_SET_INFO( ppc603 )
+{
+ if (state >= CPUINFO_INT_INPUT_STATE && state <= CPUINFO_INT_INPUT_STATE + 5)
+ {
+ ppc603_set_irq_line(state-CPUINFO_INT_INPUT_STATE, info->i);
+ return;
+ }
+ switch(state)
+ {
+ case CPUINFO_INT_REGISTER + PPC_DEC: write_decrementer(info->i); break;
+ case CPUINFO_INT_INPUT_STATE + PPC_INPUT_LINE_SMI: ppc603_set_smi_line(info->i); break;
+ default: ppc_set_info(state, info); break;
+ }
+}
+
+static CPU_GET_INFO( ppc )
+{
+ switch(state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(ppc); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 1; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 40; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_INPUT_STATE: info->i = CLEAR_LINE; break;
+
+ case CPUINFO_INT_PREVIOUSPC: /* not implemented */ break;
+
+ case CPUINFO_INT_PC: /* intentional fallthrough */
+ case CPUINFO_INT_REGISTER + PPC_PC: info->i = ppc.pc; break;
+ case CPUINFO_INT_REGISTER + PPC_MSR: info->i = ppc_get_msr(); break;
+ case CPUINFO_INT_REGISTER + PPC_CR: info->i = ppc_get_cr(); break;
+ case CPUINFO_INT_REGISTER + PPC_LR: info->i = LR; break;
+ case CPUINFO_INT_REGISTER + PPC_CTR: info->i = CTR; break;
+ case CPUINFO_INT_REGISTER + PPC_XER: info->i = XER; break;
+ case CPUINFO_INT_REGISTER + PPC_SRR0: info->i = SRR0; break;
+ case CPUINFO_INT_REGISTER + PPC_SRR1: info->i = SRR1; break;
+
+ case CPUINFO_INT_REGISTER + PPC_R0: info->i = ppc.r[0]; break;
+ case CPUINFO_INT_REGISTER + PPC_R1: info->i = ppc.r[1]; break;
+ case CPUINFO_INT_REGISTER + PPC_R2: info->i = ppc.r[2]; break;
+ case CPUINFO_INT_REGISTER + PPC_R3: info->i = ppc.r[3]; break;
+ case CPUINFO_INT_REGISTER + PPC_R4: info->i = ppc.r[4]; break;
+ case CPUINFO_INT_REGISTER + PPC_R5: info->i = ppc.r[5]; break;
+ case CPUINFO_INT_REGISTER + PPC_R6: info->i = ppc.r[6]; break;
+ case CPUINFO_INT_REGISTER + PPC_R7: info->i = ppc.r[7]; break;
+ case CPUINFO_INT_REGISTER + PPC_R8: info->i = ppc.r[8]; break;
+ case CPUINFO_INT_REGISTER + PPC_R9: info->i = ppc.r[9]; break;
+ case CPUINFO_INT_REGISTER + PPC_R10: info->i = ppc.r[10]; break;
+ case CPUINFO_INT_REGISTER + PPC_R11: info->i = ppc.r[11]; break;
+ case CPUINFO_INT_REGISTER + PPC_R12: info->i = ppc.r[12]; break;
+ case CPUINFO_INT_REGISTER + PPC_R13: info->i = ppc.r[13]; break;
+ case CPUINFO_INT_REGISTER + PPC_R14: info->i = ppc.r[14]; break;
+ case CPUINFO_INT_REGISTER + PPC_R15: info->i = ppc.r[15]; break;
+ case CPUINFO_INT_REGISTER + PPC_R16: info->i = ppc.r[16]; break;
+ case CPUINFO_INT_REGISTER + PPC_R17: info->i = ppc.r[17]; break;
+ case CPUINFO_INT_REGISTER + PPC_R18: info->i = ppc.r[18]; break;
+ case CPUINFO_INT_REGISTER + PPC_R19: info->i = ppc.r[19]; break;
+ case CPUINFO_INT_REGISTER + PPC_R20: info->i = ppc.r[20]; break;
+ case CPUINFO_INT_REGISTER + PPC_R21: info->i = ppc.r[21]; break;
+ case CPUINFO_INT_REGISTER + PPC_R22: info->i = ppc.r[22]; break;
+ case CPUINFO_INT_REGISTER + PPC_R23: info->i = ppc.r[23]; break;
+ case CPUINFO_INT_REGISTER + PPC_R24: info->i = ppc.r[24]; break;
+ case CPUINFO_INT_REGISTER + PPC_R25: info->i = ppc.r[25]; break;
+ case CPUINFO_INT_REGISTER + PPC_R26: info->i = ppc.r[26]; break;
+ case CPUINFO_INT_REGISTER + PPC_R27: info->i = ppc.r[27]; break;
+ case CPUINFO_INT_REGISTER + PPC_R28: info->i = ppc.r[28]; break;
+ case CPUINFO_INT_REGISTER + PPC_R29: info->i = ppc.r[29]; break;
+ case CPUINFO_INT_REGISTER + PPC_R30: info->i = ppc.r[30]; break;
+ case CPUINFO_INT_REGISTER + PPC_R31: info->i = ppc.r[31]; break;
+
+
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(ppc); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &ppc_icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "PPC403"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "PowerPC"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Nicola Salmoria and the MAME Team"); break;
+
+ case CPUINFO_STR_FLAGS: strcpy(info->s, " "); break;
+
+ case CPUINFO_STR_REGISTER + PPC_PC: sprintf(info->s, "PC: %08X", ppc.pc); break;
+ case CPUINFO_STR_REGISTER + PPC_MSR: sprintf(info->s, "MSR: %08X", ppc_get_msr()); break;
+ case CPUINFO_STR_REGISTER + PPC_CR: sprintf(info->s, "CR: %08X", ppc_get_cr()); break;
+ case CPUINFO_STR_REGISTER + PPC_LR: sprintf(info->s, "LR: %08X", LR); break;
+ case CPUINFO_STR_REGISTER + PPC_CTR: sprintf(info->s, "CTR: %08X", CTR); break;
+ case CPUINFO_STR_REGISTER + PPC_XER: sprintf(info->s, "XER: %08X", XER); break;
+ case CPUINFO_STR_REGISTER + PPC_SRR0: sprintf(info->s, "SRR0: %08X", SRR0); break;
+ case CPUINFO_STR_REGISTER + PPC_SRR1: sprintf(info->s, "SRR1: %08X", SRR1); break;
+
+ case CPUINFO_STR_REGISTER + PPC_R0: sprintf(info->s, "R0: %08X", ppc.r[0]); break;
+ case CPUINFO_STR_REGISTER + PPC_R1: sprintf(info->s, "R1: %08X", ppc.r[1]); break;
+ case CPUINFO_STR_REGISTER + PPC_R2: sprintf(info->s, "R2: %08X", ppc.r[2]); break;
+ case CPUINFO_STR_REGISTER + PPC_R3: sprintf(info->s, "R3: %08X", ppc.r[3]); break;
+ case CPUINFO_STR_REGISTER + PPC_R4: sprintf(info->s, "R4: %08X", ppc.r[4]); break;
+ case CPUINFO_STR_REGISTER + PPC_R5: sprintf(info->s, "R5: %08X", ppc.r[5]); break;
+ case CPUINFO_STR_REGISTER + PPC_R6: sprintf(info->s, "R6: %08X", ppc.r[6]); break;
+ case CPUINFO_STR_REGISTER + PPC_R7: sprintf(info->s, "R7: %08X", ppc.r[7]); break;
+ case CPUINFO_STR_REGISTER + PPC_R8: sprintf(info->s, "R8: %08X", ppc.r[8]); break;
+ case CPUINFO_STR_REGISTER + PPC_R9: sprintf(info->s, "R9: %08X", ppc.r[9]); break;
+ case CPUINFO_STR_REGISTER + PPC_R10: sprintf(info->s, "R10: %08X", ppc.r[10]); break;
+ case CPUINFO_STR_REGISTER + PPC_R11: sprintf(info->s, "R11: %08X", ppc.r[11]); break;
+ case CPUINFO_STR_REGISTER + PPC_R12: sprintf(info->s, "R12: %08X", ppc.r[12]); break;
+ case CPUINFO_STR_REGISTER + PPC_R13: sprintf(info->s, "R13: %08X", ppc.r[13]); break;
+ case CPUINFO_STR_REGISTER + PPC_R14: sprintf(info->s, "R14: %08X", ppc.r[14]); break;
+ case CPUINFO_STR_REGISTER + PPC_R15: sprintf(info->s, "R15: %08X", ppc.r[15]); break;
+ case CPUINFO_STR_REGISTER + PPC_R16: sprintf(info->s, "R16: %08X", ppc.r[16]); break;
+ case CPUINFO_STR_REGISTER + PPC_R17: sprintf(info->s, "R17: %08X", ppc.r[17]); break;
+ case CPUINFO_STR_REGISTER + PPC_R18: sprintf(info->s, "R18: %08X", ppc.r[18]); break;
+ case CPUINFO_STR_REGISTER + PPC_R19: sprintf(info->s, "R19: %08X", ppc.r[19]); break;
+ case CPUINFO_STR_REGISTER + PPC_R20: sprintf(info->s, "R20: %08X", ppc.r[20]); break;
+ case CPUINFO_STR_REGISTER + PPC_R21: sprintf(info->s, "R21: %08X", ppc.r[21]); break;
+ case CPUINFO_STR_REGISTER + PPC_R22: sprintf(info->s, "R22: %08X", ppc.r[22]); break;
+ case CPUINFO_STR_REGISTER + PPC_R23: sprintf(info->s, "R23: %08X", ppc.r[23]); break;
+ case CPUINFO_STR_REGISTER + PPC_R24: sprintf(info->s, "R24: %08X", ppc.r[24]); break;
+ case CPUINFO_STR_REGISTER + PPC_R25: sprintf(info->s, "R25: %08X", ppc.r[25]); break;
+ case CPUINFO_STR_REGISTER + PPC_R26: sprintf(info->s, "R26: %08X", ppc.r[26]); break;
+ case CPUINFO_STR_REGISTER + PPC_R27: sprintf(info->s, "R27: %08X", ppc.r[27]); break;
+ case CPUINFO_STR_REGISTER + PPC_R28: sprintf(info->s, "R28: %08X", ppc.r[28]); break;
+ case CPUINFO_STR_REGISTER + PPC_R29: sprintf(info->s, "R29: %08X", ppc.r[29]); break;
+ case CPUINFO_STR_REGISTER + PPC_R30: sprintf(info->s, "R30: %08X", ppc.r[30]); break;
+ case CPUINFO_STR_REGISTER + PPC_R31: sprintf(info->s, "R31: %08X", ppc.r[31]); break;
+ }
+}
+
+CPU_GET_INFO( ppc403 )
+{
+ switch(state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_LINES: info->i = 8; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+ case CPUINFO_INT_REGISTER + PPC_EXIER: info->i = EXIER; break;
+ case CPUINFO_INT_REGISTER + PPC_EXISR: info->i = EXISR; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(ppc403); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(ppc403); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(ppc403); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(ppc403); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(ppc403); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "PPC403"); break;
+ case CPUINFO_STR_REGISTER + PPC_EXIER: sprintf(info->s, "EXIER: %08X", EXIER); break;
+ case CPUINFO_STR_REGISTER + PPC_EXISR: sprintf(info->s, "EXISR: %08X", EXISR); break;
+
+ default: CPU_GET_INFO_CALL(ppc); break;
+ }
+}
+
+CPU_GET_INFO( ppc603 )
+{
+ switch(state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_LINES: info->i = 5; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 64; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+ case CPUINFO_INT_LOGADDR_WIDTH_PROGRAM: info->i = 32; break;
+ case CPUINFO_INT_PAGE_SHIFT_PROGRAM: info->i = 17; break;
+ case CPUINFO_INT_REGISTER + PPC_DEC: info->i = read_decrementer(); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(ppc603); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(ppc603); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(ppc603); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(ppc603); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(ppc603); break;
+ case CPUINFO_FCT_READ: info->read = CPU_GET_READ_NAME(ppc); break;
+ case CPUINFO_FCT_WRITE: info->write = CPU_GET_WRITE_NAME(ppc); break;
+ case CPUINFO_FCT_READOP: info->readop = CPU_GET_READOP_NAME(ppc); break;
+ case CPUINFO_FCT_TRANSLATE: info->translate = ppc_translate_address_cb; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "PPC603"); break;
+ case CPUINFO_STR_REGISTER + PPC_DEC: sprintf(info->s, "DEC: %08X", read_decrementer()); break;
+
+ default: CPU_GET_INFO_CALL(ppc); break;
+ }
+}
+
+static CPU_SET_INFO( ppc602 )
+{
+ if (state >= CPUINFO_INT_INPUT_STATE && state <= CPUINFO_INT_INPUT_STATE + 5)
+ {
+ ppc602_set_irq_line(state-CPUINFO_INT_INPUT_STATE, info->i);
+ return;
+ }
+ switch(state)
+ {
+ case CPUINFO_INT_INPUT_STATE + PPC_INPUT_LINE_SMI: ppc602_set_smi_line(info->i); break;
+ default: ppc_set_info(state, info); break;
+ }
+}
+
+CPU_GET_INFO( ppc602 )
+{
+ switch(state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_LINES: info->i = 5; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+ case CPUINFO_INT_REGISTER + PPC_IBR: info->i = ppc.ibr; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 64; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(ppc602); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(ppc602); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(ppc602); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(ppc602); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(ppc602); break;
+ case CPUINFO_FCT_READ: info->read = CPU_GET_READ_NAME(ppc); break;
+ case CPUINFO_FCT_WRITE: info->write = CPU_GET_WRITE_NAME(ppc); break;
+ case CPUINFO_FCT_READOP: info->readop = CPU_GET_READOP_NAME(ppc); break;
+ case CPUINFO_FCT_TRANSLATE: info->translate = ppc_translate_address_cb; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "PPC602"); break;
+ case CPUINFO_STR_REGISTER + PPC_IBR: sprintf(info->s, "IBR: %08X", ppc.ibr); break;
+
+ default: CPU_GET_INFO_CALL(ppc); break;
+ }
+}
+
+
+static CPU_SET_INFO( mpc8240 )
+{
+ if (state >= CPUINFO_INT_INPUT_STATE && state <= CPUINFO_INT_INPUT_STATE + 5)
+ {
+ ppc603_set_irq_line(state-CPUINFO_INT_INPUT_STATE, info->i);
+ return;
+ }
+ switch(state)
+ {
+ default: ppc_set_info(state, info); break;
+ }
+}
+
+CPU_GET_INFO( mpc8240 )
+{
+ switch(state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_LINES: info->i = 5; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 64; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(mpc8240); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(mpc8240); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(ppc603); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(mpc8240); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(ppc603); break;
+ case CPUINFO_FCT_READ: info->read = CPU_GET_READ_NAME(ppc); break;
+ case CPUINFO_FCT_WRITE: info->write = CPU_GET_WRITE_NAME(ppc); break;
+ case CPUINFO_FCT_READOP: info->readop = CPU_GET_READOP_NAME(ppc); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "MPC8240"); break;
+
+ default: CPU_GET_INFO_CALL(ppc); break;
+ }
+}
+
+static CPU_SET_INFO( ppc601 )
+{
+ if (state >= CPUINFO_INT_INPUT_STATE && state <= CPUINFO_INT_INPUT_STATE + 5)
+ {
+ ppc603_set_irq_line(state-CPUINFO_INT_INPUT_STATE, info->i);
+ return;
+ }
+ switch(state)
+ {
+ default: ppc_set_info(state, info); break;
+ }
+}
+
+CPU_GET_INFO( ppc601 )
+{
+ switch(state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_LINES: info->i = 5; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 64; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(ppc601); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(ppc601); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(ppc603); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(ppc601); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(ppc603); break;
+ case CPUINFO_FCT_READ: info->read = CPU_GET_READ_NAME(ppc); break;
+ case CPUINFO_FCT_WRITE: info->write = CPU_GET_WRITE_NAME(ppc); break;
+ case CPUINFO_FCT_READOP: info->readop = CPU_GET_READOP_NAME(ppc); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "PPC601"); break;
+
+ default: CPU_GET_INFO_CALL(ppc); break;
+ }
+}
+
+static CPU_SET_INFO( ppc604 )
+{
+ if (state >= CPUINFO_INT_INPUT_STATE && state <= CPUINFO_INT_INPUT_STATE + 5)
+ {
+ ppc603_set_irq_line(state-CPUINFO_INT_INPUT_STATE, info->i);
+ return;
+ }
+ switch(state)
+ {
+ default: ppc_set_info(state, info); break;
+ }
+}
+
+CPU_GET_INFO( ppc604 )
+{
+ switch(state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_LINES: info->i = 5; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 64; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(ppc604); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(ppc604); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(ppc603); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(ppc604); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(ppc603); break;
+ case CPUINFO_FCT_READ: info->read = CPU_GET_READ_NAME(ppc); break;
+ case CPUINFO_FCT_WRITE: info->write = CPU_GET_WRITE_NAME(ppc); break;
+ case CPUINFO_FCT_READOP: info->readop = CPU_GET_READOP_NAME(ppc); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "PPC604"); break;
+
+ default: CPU_GET_INFO_CALL(ppc); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(PPC403GA, ppc403ga);
+DEFINE_LEGACY_CPU_DEVICE(PPC403GCX, ppc403gcx);
+
+DEFINE_LEGACY_CPU_DEVICE(PPC601, ppc601);
+DEFINE_LEGACY_CPU_DEVICE(PPC602, ppc602);
+DEFINE_LEGACY_CPU_DEVICE(PPC603, ppc603);
+DEFINE_LEGACY_CPU_DEVICE(PPC603E, ppc603e);
+DEFINE_LEGACY_CPU_DEVICE(PPC603R, ppc603r);
+DEFINE_LEGACY_CPU_DEVICE(PPC604, ppc604);
+DEFINE_LEGACY_CPU_DEVICE(MPC8240, mpc8240);
+
diff --git a/trunk/src/emu/cpu/powerpc/ppc.h b/trunk/src/emu/cpu/powerpc/ppc.h
new file mode 100644
index 00000000000..478c5a5e8c5
--- /dev/null
+++ b/trunk/src/emu/cpu/powerpc/ppc.h
@@ -0,0 +1,182 @@
+/***************************************************************************
+
+ ppc.h
+
+ Interface file for the universal machine language-based
+ PowerPC emulator.
+
+ Copyright Aaron Giles
+ Released for general non-commercial use under the MAME license
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __PPC_H__
+#define __PPC_H__
+
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+/* general constants */
+#define PPC_MAX_FASTRAM 4
+#define PPC_MAX_HOTSPOTS 16
+
+
+/* interrupt types */
+#define PPC_IRQ 0 /* external IRQ */
+#define PPC_IRQ_LINE_0 0 /* (4XX) external IRQ0 */
+#define PPC_IRQ_LINE_1 1 /* (4XX) external IRQ1 */
+#define PPC_IRQ_LINE_2 2 /* (4XX) external IRQ2 */
+#define PPC_IRQ_LINE_3 3 /* (4XX) external IRQ3 */
+#define PPC_IRQ_LINE_4 4 /* (4XX) external IRQ4 */
+
+
+/* register enumeration */
+enum
+{
+ PPC_PC = 1,
+ PPC_R0,
+ PPC_R1,
+ PPC_R2,
+ PPC_R3,
+ PPC_R4,
+ PPC_R5,
+ PPC_R6,
+ PPC_R7,
+ PPC_R8,
+ PPC_R9,
+ PPC_R10,
+ PPC_R11,
+ PPC_R12,
+ PPC_R13,
+ PPC_R14,
+ PPC_R15,
+ PPC_R16,
+ PPC_R17,
+ PPC_R18,
+ PPC_R19,
+ PPC_R20,
+ PPC_R21,
+ PPC_R22,
+ PPC_R23,
+ PPC_R24,
+ PPC_R25,
+ PPC_R26,
+ PPC_R27,
+ PPC_R28,
+ PPC_R29,
+ PPC_R30,
+ PPC_R31,
+ PPC_CR,
+ PPC_LR,
+ PPC_CTR,
+ PPC_XER,
+
+ PPC_F0,
+ PPC_F1,
+ PPC_F2,
+ PPC_F3,
+ PPC_F4,
+ PPC_F5,
+ PPC_F6,
+ PPC_F7,
+ PPC_F8,
+ PPC_F9,
+ PPC_F10,
+ PPC_F11,
+ PPC_F12,
+ PPC_F13,
+ PPC_F14,
+ PPC_F15,
+ PPC_F16,
+ PPC_F17,
+ PPC_F18,
+ PPC_F19,
+ PPC_F20,
+ PPC_F21,
+ PPC_F22,
+ PPC_F23,
+ PPC_F24,
+ PPC_F25,
+ PPC_F26,
+ PPC_F27,
+ PPC_F28,
+ PPC_F29,
+ PPC_F30,
+ PPC_F31,
+ PPC_FPSCR,
+
+ PPC_MSR,
+ PPC_SRR0,
+ PPC_SRR1,
+ PPC_SPRG0,
+ PPC_SPRG1,
+ PPC_SPRG2,
+ PPC_SPRG3,
+ PPC_SDR1,
+ PPC_EXIER,
+ PPC_EXISR,
+ PPC_EVPR,
+ PPC_IOCR,
+ PPC_TBL,
+ PPC_TBH,
+ PPC_DEC
+};
+
+
+/* compiler-specific options */
+#define PPCDRC_STRICT_VERIFY 0x0001 /* verify all instructions */
+#define PPCDRC_FLUSH_PC 0x0002 /* flush the PC value before each memory access */
+#define PPCDRC_ACCURATE_SINGLES 0x0004 /* do excessive rounding to make single-precision results "accurate" */
+
+
+/* common sets of options */
+#define PPCDRC_COMPATIBLE_OPTIONS (PPCDRC_STRICT_VERIFY | PPCDRC_FLUSH_PC | PPCDRC_ACCURATE_SINGLES)
+#define PPCDRC_FASTEST_OPTIONS (0)
+
+
+
+/***************************************************************************
+ STRUCTURES AND TYPEDEFS
+***************************************************************************/
+
+typedef void (*ppc4xx_spu_tx_handler)(device_t *device, UINT8 data);
+
+typedef struct _powerpc_config powerpc_config;
+struct _powerpc_config
+{
+ UINT32 bus_frequency;
+};
+
+
+
+/***************************************************************************
+ PUBLIC FUNCTIONS
+***************************************************************************/
+
+void ppcdrc_set_options(device_t *device, UINT32 options);
+void ppcdrc_add_fastram(device_t *device, offs_t start, offs_t end, UINT8 readonly, void *base);
+void ppcdrc_add_hotspot(device_t *device, offs_t pc, UINT32 opcode, UINT32 cycles);
+
+void ppc4xx_spu_set_tx_handler(device_t *device, ppc4xx_spu_tx_handler handler);
+void ppc4xx_spu_receive_byte(device_t *device, UINT8 byteval);
+
+
+DECLARE_LEGACY_CPU_DEVICE(PPC403GA, ppc403ga);
+DECLARE_LEGACY_CPU_DEVICE(PPC403GCX, ppc403gcx);
+
+DECLARE_LEGACY_CPU_DEVICE(PPC601, ppc601);
+DECLARE_LEGACY_CPU_DEVICE(PPC602, ppc602);
+DECLARE_LEGACY_CPU_DEVICE(PPC603, ppc603);
+DECLARE_LEGACY_CPU_DEVICE(PPC603E, ppc603e);
+DECLARE_LEGACY_CPU_DEVICE(PPC603R, ppc603r);
+DECLARE_LEGACY_CPU_DEVICE(PPC604, ppc604);
+DECLARE_LEGACY_CPU_DEVICE(MPC8240, mpc8240);
+
+
+#endif /* __PPC_H__ */
diff --git a/trunk/src/emu/cpu/powerpc/ppc403.c b/trunk/src/emu/cpu/powerpc/ppc403.c
new file mode 100644
index 00000000000..3ee47476885
--- /dev/null
+++ b/trunk/src/emu/cpu/powerpc/ppc403.c
@@ -0,0 +1,953 @@
+/* PowerPC 403 specific functions */
+
+static void ppc403_dma_exec(int ch);
+
+#define DMA_CE 0x80000000
+#define DMA_CIE 0x40000000
+#define DMA_TD 0x20000000
+#define DMA_PL 0x10000000
+#define DMA_DAI 0x02000000
+#define DMA_SAI 0x01000000
+#define DMA_CP 0x00800000
+#define DMA_ETD 0x00000200
+#define DMA_TCE 0x00000100
+#define DMA_CH 0x00000080
+#define DMA_BME 0x00000040
+#define DMA_ECE 0x00000020
+#define DMA_TCD 0x00000010
+#define DMA_PCE 0x00000008
+
+static SPU_RX_HANDLER spu_rx_handler;
+static SPU_TX_HANDLER spu_tx_handler;
+static TIMER_CALLBACK( ppc403_spu_rx_callback );
+static TIMER_CALLBACK( ppc403_spu_tx_callback );
+
+static PPC_DMA_HANDLER spu_rx_dma_handler;
+static PPC_DMA_HANDLER spu_tx_dma_handler;
+static UINT8 *spu_rx_dma_ptr;
+static UINT8 *spu_tx_dma_ptr;
+
+static PPC_DMA_HANDLER dma_read_handler[4];
+static PPC_DMA_HANDLER dma_write_handler[4];
+static UINT8 *dma_read_ptr[4];
+static UINT8 *dma_write_ptr[4];
+
+INLINE void ppc_set_dcr(int dcr, UINT32 value)
+{
+ switch(dcr)
+ {
+ case DCR_BEAR: ppc.bear = value; break;
+ case DCR_BESR: ppc.besr = value; break;
+ case DCR_BR0: ppc.br[0] = value; break;
+ case DCR_BR1: ppc.br[1] = value; break;
+ case DCR_BR2: ppc.br[2] = value; break;
+ case DCR_BR3: ppc.br[3] = value; break;
+ case DCR_BR4: ppc.br[4] = value; break;
+ case DCR_BR5: ppc.br[5] = value; break;
+ case DCR_BR6: ppc.br[6] = value; break;
+ case DCR_BR7: ppc.br[7] = value; break;
+
+ case DCR_EXISR: ppc.exisr &= ~value; break;
+ case DCR_EXIER: EXIER = value; ppc.exisr &= EXIER; break;
+ case DCR_IOCR: ppc.iocr = value; break;
+ case DCR_DMASR: break; /* TODO */
+ case DCR_DMADA0: ppc.dma[0].da = value; break;
+ case DCR_DMADA1: ppc.dma[1].da = value; break;
+ case DCR_DMADA2: ppc.dma[2].da = value; break;
+ case DCR_DMADA3: ppc.dma[3].da = value; break;
+ case DCR_DMASA0: ppc.dma[0].sa = value; break;
+ case DCR_DMASA1: ppc.dma[1].sa = value; break;
+ case DCR_DMASA2: ppc.dma[2].sa = value; break;
+ case DCR_DMASA3: ppc.dma[3].sa = value; break;
+ case DCR_DMACT0: ppc.dma[0].ct = value; break;
+ case DCR_DMACT1: ppc.dma[1].ct = value; break;
+ case DCR_DMACT2: ppc.dma[2].ct = value; break;
+ case DCR_DMACT3: ppc.dma[3].ct = value; break;
+ case DCR_DMACR0: ppc.dma[0].cr = value; ppc403_dma_exec(0); break;
+ case DCR_DMACR1: ppc.dma[1].cr = value; ppc403_dma_exec(1); break;
+ case DCR_DMACR2: ppc.dma[2].cr = value; ppc403_dma_exec(2); break;
+ case DCR_DMACR3: ppc.dma[3].cr = value; ppc403_dma_exec(3); break;
+
+ default:
+ fatalerror("ppc: set_dcr: Unimplemented DCR %X", dcr);
+ break;
+ }
+}
+
+INLINE UINT32 ppc_get_dcr(int dcr)
+{
+ switch(dcr)
+ {
+ case DCR_BEAR: return ppc.bear;
+ case DCR_BESR: return ppc.besr;
+ case DCR_BR0: return ppc.br[0];
+ case DCR_BR1: return ppc.br[1];
+ case DCR_BR2: return ppc.br[2];
+ case DCR_BR3: return ppc.br[3];
+ case DCR_BR4: return ppc.br[4];
+ case DCR_BR5: return ppc.br[5];
+ case DCR_BR6: return ppc.br[6];
+ case DCR_BR7: return ppc.br[7];
+ case DCR_EXISR: return EXISR;
+ case DCR_EXIER: return EXIER;
+ case DCR_IOCR: return ppc.iocr;
+ case DCR_DMASR: return ppc.dmasr;
+ case DCR_DMADA0: return ppc.dma[0].da;
+ case DCR_DMADA1: return ppc.dma[1].da;
+ case DCR_DMADA2: return ppc.dma[2].da;
+ case DCR_DMADA3: return ppc.dma[3].da;
+ case DCR_DMASA0: return ppc.dma[0].sa;
+ case DCR_DMASA1: return ppc.dma[1].sa;
+ case DCR_DMASA2: return ppc.dma[2].sa;
+ case DCR_DMASA3: return ppc.dma[3].sa;
+ case DCR_DMACT0: return ppc.dma[0].ct;
+ case DCR_DMACT1: return ppc.dma[1].ct;
+ case DCR_DMACT2: return ppc.dma[2].ct;
+ case DCR_DMACT3: return ppc.dma[3].ct;
+ case DCR_DMACR0: return ppc.dma[0].cr;
+ case DCR_DMACR1: return ppc.dma[1].cr;
+ case DCR_DMACR2: return ppc.dma[2].cr;
+ case DCR_DMACR3: return ppc.dma[3].cr;
+
+ default:
+ fatalerror("ppc: get_dcr: Unimplemented DCR %X", dcr);
+ break;
+ }
+}
+
+
+
+#ifndef PPC_DRC
+INLINE void ppc403_check_interrupts(void)
+{
+ if (MSR & MSR_EE)
+ {
+ if (ppc.interrupt_pending != 0)
+ {
+ if (ppc.interrupt_pending & 0x1)
+ {
+ ppc403_exception(EXCEPTION_IRQ);
+ }
+ else if (ppc.interrupt_pending & 0x2)
+ {
+ ppc403_exception(EXCEPTION_PROGRAMMABLE_INTERVAL_TIMER);
+ }
+ else if (ppc.interrupt_pending & 0x4)
+ {
+ ppc403_exception(EXCEPTION_FIXED_INTERVAL_TIMER);
+ }
+ }
+ }
+}
+
+static CPU_RESET( ppc403 )
+{
+ ppc.pc = ppc.npc = 0xfffffffc;
+
+ ppc_set_msr(0);
+}
+
+static CPU_EXECUTE( ppc403 )
+{
+ UINT32 fit_trigger_cycle;
+ ppc_tb_base_icount = cycles;
+
+ fit_trigger_cycle = 0x7fffffff;
+
+ if (ppc.fit_int_enable)
+ {
+ UINT32 tb = (UINT32)ppc.tb;
+ UINT32 fit_cycles = 0;
+
+ if (ppc.tb & ppc.fit_bit)
+ {
+ fit_cycles += ppc.fit_bit;
+ tb += fit_cycles;
+ }
+
+ fit_cycles += ppc.fit_bit - (tb & (ppc.fit_bit-1));
+
+ fit_trigger_cycle = ppc_icount - fit_cycles;
+ }
+
+ while( ppc_icount > 0 )
+ {
+ UINT32 opcode;
+
+ debugger_instruction_hook(device, ppc.pc);
+ ppc.pc = ppc.npc;
+ ppc.npc += 4;
+ opcode = ROPCODE(ppc.pc);
+
+ switch(opcode >> 26)
+ {
+ case 19: ppc.optable19[(opcode >> 1) & 0x3ff](opcode); break;
+ case 31: ppc.optable31[(opcode >> 1) & 0x3ff](opcode); break;
+ case 59: ppc.optable59[(opcode >> 1) & 0x3ff](opcode); break;
+ case 63: ppc.optable63[(opcode >> 1) & 0x3ff](opcode); break;
+ default: ppc.optable[opcode >> 26](opcode); break;
+ }
+
+ ppc_icount--;
+
+ /* Programmable Interval Timer (PIT) */
+ if (ppc.pit_counter > 0)
+ {
+ ppc.pit_counter--;
+ if (ppc.pit_counter == 0)
+ {
+ if (ppc.pit_int_enable) {
+ ppc.interrupt_pending |= 0x2;
+ }
+ if (ppc.tcr & 0x00400000) // Automatic reload
+ {
+ ppc.pit_counter = ppc.pit;
+ }
+ }
+ }
+
+ /* Fixed Interval Timer */
+ if (fit_trigger_cycle != 0x7fffffff)
+ {
+ if (ppc_icount == fit_trigger_cycle)
+ {
+ if (ppc.fit_int_enable)
+ {
+ fit_trigger_cycle -= ppc.fit_bit;
+ ppc.interrupt_pending |= 0x4;
+ }
+ }
+ }
+
+#if 0
+ /* Watchdog Timer */
+ if (((UINT32)(ppc.tb) & ppc.wdt_bit) && (tblo & ppc.wdt_bit) == 0) {
+ switch((ppc.tsr >> 28) & 0x3)
+ {
+ case 0: ppc.tsr |= TSR_ENW; break;
+ case 1: ppc.tsr |= TSR_ENW; break;
+ case 2:
+ if (ppc.wdt_int_enable && (ppc.msr & MSR_CE)) {
+ ppc403_exception(EXCEPTION_WATCHDOG_TIMER);
+ }
+ break;
+ case 3:
+ fatalerror("PPC: Watchdog Timer caused reset");
+ break;
+ }
+ }
+#endif
+
+ ppc403_check_interrupts();
+ }
+
+ // update timebase
+ ppc.tb += (ppc_tb_base_icount - ppc_icount);
+}
+
+void ppc403_exception(int exception)
+{
+ switch( exception )
+ {
+ case EXCEPTION_IRQ: /* External Interrupt */
+ {
+ if( ppc_get_msr() & MSR_EE ) {
+ UINT32 msr = ppc_get_msr();
+
+ SRR0 = ppc.npc;
+ SRR1 = msr;
+
+ msr &= ~(MSR_WE | MSR_PR | MSR_EE | MSR_PE); // Clear WE, PR, EE, PR
+ if( msr & MSR_LE )
+ msr |= MSR_ILE;
+ else
+ msr &= ~MSR_ILE;
+ ppc_set_msr(msr);
+
+ ppc.npc = EVPR | 0x0500;
+
+ ppc.interrupt_pending &= ~0x1;
+ }
+ break;
+ }
+
+ case EXCEPTION_TRAP: /* Program exception / Trap */
+ {
+ UINT32 msr = ppc_get_msr();
+
+ SRR0 = ppc.pc;
+ SRR1 = msr;
+
+ msr &= ~(MSR_WE | MSR_PR | MSR_EE | MSR_PE); // Clear WE, PR, EE, PR
+ if( msr & MSR_ILE )
+ msr |= MSR_LE;
+ else
+ msr &= ~MSR_LE;
+ ppc_set_msr(msr);
+
+ if( msr & MSR_IP )
+ ppc.npc = 0xfff00000 | 0x0700;
+ else
+ ppc.npc = EVPR | 0x0700;
+ break;
+ }
+
+ case EXCEPTION_SYSTEM_CALL: /* System call */
+ {
+ UINT32 msr = ppc_get_msr();
+
+ SRR0 = ppc.npc;
+ SRR1 = msr;
+
+ msr &= ~(MSR_WE | MSR_PR | MSR_EE | MSR_PE); // Clear WE, PR, EE, PR
+ if( msr & MSR_ILE )
+ msr |= MSR_LE;
+ else
+ msr &= ~MSR_LE;
+ ppc_set_msr(msr);
+
+ if( msr & MSR_IP )
+ ppc.npc = 0xfff00000 | 0x0c00;
+ else
+ ppc.npc = EVPR | 0x0c00;
+ break;
+ }
+
+ case EXCEPTION_PROGRAMMABLE_INTERVAL_TIMER:
+ {
+ if( ppc_get_msr() & MSR_EE ) {
+ UINT32 msr = ppc_get_msr();
+
+ SRR0 = ppc.npc;
+ SRR1 = msr;
+
+ msr &= ~(MSR_WE | MSR_PR | MSR_EE | MSR_PE); // Clear WE, PR, EE, PR
+ if( msr & MSR_LE )
+ msr |= MSR_ILE;
+ else
+ msr &= ~MSR_ILE;
+ ppc_set_msr(msr);
+
+ ppc.npc = EVPR | 0x1000;
+
+ ppc.tsr |= 0x08000000; // PIT interrupt
+ ppc.interrupt_pending &= ~0x2;
+ }
+ break;
+ }
+
+ case EXCEPTION_FIXED_INTERVAL_TIMER: /* Fixed Interval Timer */
+ {
+ if( ppc_get_msr() & MSR_EE ) {
+ UINT32 msr = ppc_get_msr();
+
+ SRR0 = ppc.npc;
+ SRR1 = msr;
+
+ msr &= ~(MSR_WE | MSR_PR | MSR_EE | MSR_PE); // Clear WE, PR, EE, PR
+ if( msr & MSR_LE )
+ msr |= MSR_ILE;
+ else
+ msr &= ~MSR_ILE;
+ ppc_set_msr(msr);
+
+ ppc.npc = EVPR | 0x1010;
+ ppc.interrupt_pending &= ~0x4;
+ }
+ break;
+ }
+
+ case EXCEPTION_WATCHDOG_TIMER: /* Watchdog Timer */
+ {
+ UINT32 msr = ppc_get_msr();
+
+ SRR2 = ppc.npc;
+ SRR3 = msr;
+
+ msr &= ~(MSR_WE | MSR_PR | MSR_CE | MSR_EE | MSR_DE | MSR_PE | MSR_DR | MSR_IR);
+ if (msr & MSR_LE)
+ msr |= MSR_ILE;
+ else
+ msr &= ~MSR_ILE;
+ ppc_set_msr(msr);
+
+ ppc.npc = EVPR | 0x1020;
+ break;
+ }
+
+ case EXCEPTION_CRITICAL_INTERRUPT:
+ {
+ UINT32 msr = ppc_get_msr();
+
+ SRR2 = ppc.npc;
+ SRR3 = msr;
+
+ msr &= ~(MSR_WE | MSR_PR | MSR_CE | MSR_EE | MSR_DE | MSR_PE | MSR_DR | MSR_IR);
+ if (msr & MSR_LE)
+ msr |= MSR_ILE;
+ else
+ msr &= ~MSR_ILE;
+ ppc_set_msr(msr);
+
+ EXISR |= 0x80000000;
+ ppc.npc = EVPR | 0x100;
+ break;
+ }
+
+ default:
+ fatalerror("ppc: Unhandled exception %d", exception);
+ break;
+ }
+}
+
+static void ppc403_set_irq_line(int irqline, int state)
+{
+ if (irqline >= INPUT_LINE_IRQ0 && irqline <= INPUT_LINE_IRQ4)
+ {
+ UINT32 mask = (1 << (4 - irqline));
+ if( state == ASSERT_LINE) {
+ if( EXIER & mask ) {
+ ppc.exisr |= mask;
+ ppc.interrupt_pending |= 0x1;
+
+ if (ppc.irq_callback)
+ {
+ ppc.irq_callback(ppc.device, irqline);
+ }
+ }
+ }
+ // clear line is used to clear the interrupt when the interrupts are level-sensitive
+ else if (state == CLEAR_LINE)
+ {
+ ppc.exisr &= ~mask;
+ }
+ }
+ else if (irqline == PPC_IRQ_SPU_RX)
+ {
+ UINT32 mask = 0x08000000;
+ if (state) {
+ if( EXIER & mask ) {
+ ppc.exisr |= mask;
+ ppc.interrupt_pending |= 0x1;
+ }
+ }
+ }
+ else if (irqline == PPC_IRQ_SPU_TX)
+ {
+ UINT32 mask = 0x04000000;
+ if (state) {
+ if( EXIER & mask ) {
+ ppc.exisr |= mask;
+ ppc.interrupt_pending |= 0x1;
+ }
+ }
+ }
+ else if (irqline == PPC_IRQ_CRITICAL)
+ {
+ if (state) {
+ if (EXIER & 0x80000000) {
+ ppc403_exception(EXCEPTION_CRITICAL_INTERRUPT);
+ }
+ }
+ }
+ else
+ {
+ fatalerror("PPC: Unknown IRQ line %d", irqline);
+ }
+}
+
+static void ppc403_dma_set_irq_line(int dma, int state)
+{
+ UINT32 mask = (1 << (3 - dma)) << 20;
+ if( state ) {
+ if( EXIER & mask ) {
+ ppc.exisr |= mask;
+ ppc.interrupt_pending |= 0x1;
+ }
+ }
+}
+#endif
+
+#ifdef PPC_DRC
+static void ppc403_dma_set_irq_line(int dma, int state)
+{
+ UINT32 mask = (1 << (3 - dma)) << 20;
+ if( state ) {
+ if( EXIER & mask ) {
+ ppc.exisr |= mask;
+ ppc.exception_pending |= 0x1;
+ }
+ }
+}
+#endif
+
+
+
+
+
+
+#ifndef PPC_DRC
+static void ppc_dccci(UINT32 op)
+{
+
+}
+
+static void ppc_dcread(UINT32 op)
+{
+
+}
+
+static void ppc_icbt(UINT32 op)
+{
+
+}
+
+static void ppc_iccci(UINT32 op)
+{
+
+}
+
+static void ppc_icread(UINT32 op)
+{
+
+}
+
+static void ppc_rfci(UINT32 op)
+{
+ UINT32 msr;
+ ppc.npc = ppc.srr2;
+ msr = ppc.srr3;
+ ppc_set_msr( msr );
+
+}
+#endif
+
+static void ppc_mfdcr(UINT32 op)
+{
+ REG(RT) = ppc_get_dcr(SPR);
+}
+
+static void ppc_mtdcr(UINT32 op)
+{
+ ppc_set_dcr(SPR, REG(RS));
+}
+
+static void ppc_wrtee(UINT32 op)
+{
+ if( REG(RS) & 0x8000 )
+ ppc_set_msr( ppc_get_msr() | MSR_EE);
+ else
+ ppc_set_msr( ppc_get_msr() & ~MSR_EE);
+}
+
+static void ppc_wrteei(UINT32 op)
+{
+ if( op & 0x8000 )
+ ppc_set_msr( ppc_get_msr() | MSR_EE);
+ else
+ ppc_set_msr( ppc_get_msr() & ~MSR_EE);
+}
+
+
+
+/**************************************************************************/
+/* PPC403 Serial Port */
+
+static UINT8 ppc403_spu_r(UINT32 a)
+{
+ switch(a & 0xf)
+ {
+ case 0x0: return ppc.spu.spls | 0x6; /* transmit buffer is always empty */
+ case 0x2: return ppc.spu.sphs;
+ case 0x4: return (ppc.spu.brd >> 8) & 0xf;
+ case 0x5: return (ppc.spu.brd & 0xff);
+ case 0x6: return ppc.spu.spctl;
+ case 0x7: return ppc.spu.sprc;
+ case 0x8: return ppc.spu.sptc;
+ case 0x9: return ppc.spu.sprb;
+ default: fatalerror("ppc: spu_r: %02X", a & 0xf);
+ }
+}
+
+static void ppc403_spu_w(UINT32 a, UINT8 d)
+{
+ switch(a & 0xf)
+ {
+ case 0x0:
+ if( d & 0x80 ) ppc.spu.spls &= ~0x80;
+ if( d & 0x40 ) ppc.spu.spls &= ~0x40;
+ if( d & 0x20 ) ppc.spu.spls &= ~0x20;
+ if( d & 0x10 ) ppc.spu.spls &= ~0x10;
+ if( d & 0x08 ) ppc.spu.spls &= ~0x08;
+ break;
+
+ case 0x2:
+ ppc.spu.sphs = d;
+ break;
+
+ case 0x4:
+ ppc.spu.brd &= 0xff;
+ ppc.spu.brd |= (d << 8);
+ break;
+
+ case 0x5:
+ ppc.spu.brd &= 0xff00;
+ ppc.spu.brd |= d;
+ if (ppc.iocr & 0x2) {
+ mame_printf_debug("ppc: SPU Baud rate: %d\n", (3686400 / (ppc.spu.brd + 1)) / 16);
+ } else {
+ mame_printf_debug("ppc: SPU Baud rate: %d\n", (33333333 / (ppc.spu.brd + 1)) / 16);
+ }
+ break;
+
+ case 0x6:
+ ppc.spu.spctl = d;
+ break;
+
+ case 0x7:
+ ppc.spu.sprc = d;
+ if (ppc.spu.sprc & 0x80) /* enable RX */
+ {
+ /*
+ int baud_rate;
+ if (ppc.iocr & 0x2) {
+ baud_rate = (3686400 / (ppc.spu.brd + 1)) / 16;
+ } else {
+ baud_rate = (33333333 / (ppc.spu.brd + 1)) / 16;
+ }
+ */
+
+ /* check if serial port is hooked to a DMA channel */
+ /* if so, do a DMA operation */
+ if( ((((ppc.spu.sprc >> 5) & 0x3) == 2) && (ppc.dma[2].cr & DMA_CE)) ||
+ ((((ppc.spu.sprc >> 5) & 0x3) == 3) && (ppc.dma[3].cr & DMA_CE)) )
+ {
+ int i;
+ int ch = (ppc.spu.sprc >> 5) & 0x3;
+ // mame_printf_debug("ppc: DMA from serial port on channel %d (DA: %08X)\n", ch, ppc.dma[ch].da);
+
+ if (spu_rx_dma_handler)
+ {
+ int length = ppc.dma[ch].ct;
+
+ spu_rx_dma_handler(length);
+
+ for (i=0; i < length; i++)
+ {
+ ppc.program->write_byte(ppc.dma[ch].da++, spu_rx_dma_ptr[i]);
+ }
+ }
+
+ ppc.dmasr |= (1 << (27 - ch));
+
+ /* generate interrupts */
+ if( ppc.dma[ch].cr & DMA_CIE )
+ {
+ ppc403_dma_set_irq_line( ch, PULSE_LINE );
+ }
+
+ /* set receive buffer full */
+ ppc.spu.spls = 0x80;
+
+#ifndef PPC_DRC
+ ppc403_set_irq_line(PPC_IRQ_SPU_RX, ASSERT_LINE);
+#else
+ ppcdrc403_set_irq_line(PPC_IRQ_SPU_RX, ASSERT_LINE);
+#endif
+ }
+ }
+ else /* disable RX */
+ {
+ }
+ break;
+
+ case 0x8:
+ ppc.spu.sptc = d;
+ break;
+
+ case 0x9:
+ ppc.spu.sptb = d;
+ ppc403_spu_tx_callback(NULL/* Machine */, NULL, cpunum_get_active());
+ break;
+
+ default:
+ fatalerror("ppc: spu_w: %02X, %02X", a & 0xf, d);
+ break;
+ }
+ //mame_printf_debug("spu_w: %02X, %02X at %08X\n", a & 0xf, d, ppc.pc);
+}
+
+void ppc403_spu_rx(UINT8 data)
+{
+ ppc.spu.sprb = data;
+
+ /* set receive buffer full */
+ ppc.spu.spls = 0x80;
+
+ /* generate interrupt if DMA is disabled and RBR interrupt is enabled */
+ if (((ppc.spu.sprc >> 5) & 0x3) == 0x01) {
+#ifndef PPC_DRC
+ ppc403_set_irq_line(PPC_IRQ_SPU_RX, ASSERT_LINE);
+#else
+ ppcdrc403_set_irq_line(PPC_IRQ_SPU_RX, ASSERT_LINE);
+#endif
+ }
+}
+
+static TIMER_CALLBACK( ppc403_spu_rx_callback )
+{
+ if (spu_rx_handler != NULL)
+ {
+ ppc403_spu_rx(spu_rx_handler());
+ }
+}
+
+static TIMER_CALLBACK( ppc403_spu_tx_callback )
+{
+ if (spu_tx_handler != NULL)
+ {
+ spu_tx_handler(ppc.spu.sptb);
+
+ /* generate interrupt if DMA is disabled and TBR interrupt is enabled */
+ if (((ppc.spu.sptc >> 5) & 0x3) == 0x01) {
+#ifndef PPC_DRC
+ ppc403_set_irq_line(PPC_IRQ_SPU_TX, ASSERT_LINE);
+#else
+ ppcdrc403_set_irq_line(PPC_IRQ_SPU_TX, ASSERT_LINE);
+#endif
+ }
+ }
+}
+
+void ppc403_install_spu_rx_handler(SPU_RX_HANDLER rx_handler)
+{
+ spu_rx_handler = rx_handler;
+}
+
+void ppc403_install_spu_tx_handler(SPU_TX_HANDLER tx_handler)
+{
+ spu_tx_handler = tx_handler;
+}
+
+
+void ppc403_spu_rx_dma(UINT8 *data, int length)
+{
+
+}
+
+void ppc403_install_spu_rx_dma_handler(PPC_DMA_HANDLER rx_dma_handler, UINT8 *buffer)
+{
+ spu_rx_dma_handler = rx_dma_handler;
+ spu_rx_dma_ptr = buffer;
+}
+
+void ppc403_install_spu_tx_dma_handler(PPC_DMA_HANDLER tx_dma_handler, UINT8 *buffer)
+{
+ spu_tx_dma_handler = tx_dma_handler;
+ spu_tx_dma_ptr = buffer;
+}
+
+/*********************************************************************************/
+
+/* PPC 403 DMA */
+
+static const int dma_transfer_width[4] = { 1, 2, 4, 16 };
+
+void ppc403_install_dma_read_handler(int ch, PPC_DMA_HANDLER dma_handler, UINT8 *buffer)
+{
+ dma_read_handler[ch] = dma_handler;
+ dma_read_ptr[ch] = buffer;
+}
+
+void ppc403_install_dma_write_handler(int ch, PPC_DMA_HANDLER dma_handler, UINT8 *buffer)
+{
+ dma_write_handler[ch] = dma_handler;
+ dma_write_ptr[ch] = buffer;
+}
+
+static void ppc403_dma_exec(int ch)
+{
+ int i;
+ int dai, sai, width;
+
+ /* Is the DMA channel enabled ? */
+ if( ppc.dma[ch].cr & DMA_CE )
+ {
+ /* transfer width */
+ width = dma_transfer_width[(ppc.dma[ch].cr >> 26) & 0x3];
+
+ if( ppc.dma[ch].cr & DMA_DAI )
+ dai = width;
+ else
+ dai = 0; /* DA not incremented */
+
+ if( ppc.dma[ch].cr & DMA_SAI )
+ sai = width;
+ else
+ sai = 0; /* SA not incremented */
+
+
+ /* transfer mode */
+ switch( (ppc.dma[ch].cr >> 21) & 0x3 )
+ {
+ case 0: /* buffered DMA */
+ if( ppc.dma[ch].cr & DMA_TD ) /* peripheral to mem */
+ {
+ // nothing to do for now */
+ }
+ else /* mem to peripheral */
+ {
+
+ /* check if the serial port is hooked to channel 2 or 3 */
+ if( (ch == 2 && ((ppc.spu.sptc >> 5) & 0x3) == 2) ||
+ (ch == 3 && ((ppc.spu.sptc >> 5) & 0x3) == 3) )
+ {
+ mame_printf_debug("ppc: dma_exec: DMA to serial port on channel %d (DA: %08X)\n", ch, ppc.dma[ch].da);
+
+ if (spu_tx_dma_handler)
+ {
+ int length = ppc.dma[ch].ct;
+
+ for( i=0; i < length; i++ ) {
+ spu_tx_dma_ptr[i] = ppc.program->read_byte(ppc.dma[ch].da++);
+ }
+ spu_tx_dma_handler(length);
+ }
+
+#ifndef PPC_DRC
+ ppc403_set_irq_line(PPC_IRQ_SPU_TX, ASSERT_LINE);
+#else
+ ppcdrc403_set_irq_line(PPC_IRQ_SPU_TX, ASSERT_LINE);
+#endif
+ }
+ else {
+ fatalerror("ppc: dma_exec: buffered DMA to unknown peripheral ! (channel %d)", ch);
+ }
+
+ }
+ break;
+
+ case 1: /* fly-by DMA */
+ fatalerror("ppc: dma_exec: fly-by DMA not implemented");
+ break;
+
+ case 2: /* software initiated mem-to-mem DMA */
+ //mame_printf_debug("ppc: DMA (%d, SW mem-to-mem): SA = %08X, DA = %08X, CT = %08X\n", ch, ppc.dma[ch].sa, ppc.dma[ch].da, ppc.dma[ch].ct);
+
+ switch(width)
+ {
+ case 1: /* Byte transfer */
+ for (i=0; i < ppc.dma[ch].ct; i++)
+ {
+ UINT8 b = READ8(ppc.dma[ch].sa);
+ WRITE8(ppc.dma[ch].da, b);
+ ppc.dma[ch].sa += sai;
+ ppc.dma[ch].da += dai;
+ }
+ break;
+ case 2: /* Word transfer */
+ for (i=0; i < ppc.dma[ch].ct; i++)
+ {
+ UINT16 w = READ16(ppc.dma[ch].sa);
+ WRITE16(ppc.dma[ch].da, w);
+ ppc.dma[ch].sa += sai;
+ ppc.dma[ch].da += dai;
+ }
+ break;
+ case 4: /* Double word transfer */
+ for (i=0; i < ppc.dma[ch].ct; i++)
+ {
+ UINT32 d = READ32(ppc.dma[ch].sa);
+ WRITE32(ppc.dma[ch].da, d);
+ ppc.dma[ch].sa += sai;
+ ppc.dma[ch].da += dai;
+ }
+ break;
+ case 16: /* 16-byte transfer */
+ for (i=0; i < ppc.dma[ch].ct; i++)
+ {
+ UINT32 d1 = READ32(ppc.dma[ch].sa+0);
+ UINT32 d2 = READ32(ppc.dma[ch].sa+4);
+ UINT32 d3 = READ32(ppc.dma[ch].sa+8);
+ UINT32 d4 = READ32(ppc.dma[ch].sa+12);
+ WRITE32(ppc.dma[ch].da+0, d1);
+ WRITE32(ppc.dma[ch].da+4, d2);
+ WRITE32(ppc.dma[ch].da+8, d3);
+ WRITE32(ppc.dma[ch].da+12, d4);
+ ppc.dma[ch].sa += 16;
+ ppc.dma[ch].da += 16;
+ }
+ break;
+ default:
+ fatalerror("dma: dma_exec: SW mem-to-mem DMA, width = %d", width);
+ }
+ break;
+
+ case 3: /* hardware initiated mem-to-mem DMA */
+ fatalerror("ppc: dma_exec: HW mem-to-mem DMA not implemented");
+ break;
+ }
+
+ ppc.dmasr |= (1 << (27 - ch));
+
+ /* DEBUG: check for not yet supported features */
+ if( (ppc.dma[ch].cr & DMA_TCE) == 0 )
+ fatalerror("ppc: dma_exec: DMA_TCE == 0");
+
+ if( ppc.dma[ch].cr & DMA_CH )
+ fatalerror("ppc: dma_exec: DMA chaining not implemented");
+
+ /* generate interrupts */
+ if( ppc.dma[ch].cr & DMA_CIE )
+ ppc403_dma_set_irq_line( ch, PULSE_LINE );
+
+ }
+}
+
+/*********************************************************************************/
+
+static UINT8 ppc403_read8(address_space *space, UINT32 a)
+{
+ if(a >= 0x40000000 && a <= 0x4000000f) /* Serial Port */
+ return ppc403_spu_r(a);
+ return space->read_byte(a);
+}
+
+#define ppc403_read16 memory_read_word_32be
+#define ppc403_read32 memory_read_dword_32be
+
+static void ppc403_write8(address_space *space, UINT32 a, UINT8 d)
+{
+ if( a >= 0x40000000 && a <= 0x4000000f ) /* Serial Port */
+ {
+ ppc403_spu_w(a, d);
+ return;
+ }
+ space->write_byte(a, d);
+}
+
+#define ppc403_write16 memory_write_word_32be
+#define ppc403_write32 memory_write_dword_32be
+
+static UINT16 ppc403_read16_unaligned(address_space *space, UINT32 a)
+{
+ fatalerror("ppc: Unaligned read16 %08X at %08X", a, ppc.pc);
+ return 0;
+}
+
+static UINT32 ppc403_read32_unaligned(address_space *space, UINT32 a)
+{
+ fatalerror("ppc: Unaligned read32 %08X at %08X", a, ppc.pc);
+ return 0;
+}
+
+static void ppc403_write16_unaligned(address_space *space, UINT32 a, UINT16 d)
+{
+ fatalerror("ppc: Unaligned write16 %08X, %04X at %08X", a, d, ppc.pc);
+}
+
+static void ppc403_write32_unaligned(address_space *space, UINT32 a, UINT32 d)
+{
+ fatalerror("ppc: Unaligned write32 %08X, %08X at %08X", a, d, ppc.pc);
+}
+
diff --git a/trunk/src/emu/cpu/powerpc/ppc602.c b/trunk/src/emu/cpu/powerpc/ppc602.c
new file mode 100644
index 00000000000..9922b7940e1
--- /dev/null
+++ b/trunk/src/emu/cpu/powerpc/ppc602.c
@@ -0,0 +1,279 @@
+static void ppc_dsa(UINT32 op)
+{
+ UINT32 msr = ppc_get_msr();
+
+ msr &= ~(MSR_SA | MSR_EE | MSR_PR | MSR_AP);
+ if (ppc.esasrr & 0x8) msr |= MSR_PR;
+ if (ppc.esasrr & 0x4) msr |= MSR_AP;
+ if (ppc.esasrr & 0x2) msr |= MSR_SA;
+ if (ppc.esasrr & 0x1) msr |= MSR_EE;
+
+ ppc_set_msr(msr);
+}
+
+static void ppc_esa(UINT32 op)
+{
+ int sa, ee, pr, ap;
+ UINT32 msr = ppc_get_msr();
+
+ sa = (msr & MSR_SA) ? 1 : 0;
+ ee = (msr & MSR_EE) ? 1 : 0;
+ pr = (msr & MSR_PR) ? 1 : 0;
+ ap = (msr & MSR_AP) ? 1 : 0;
+
+ ppc.esasrr = (pr << 3) | (ap << 2) | (sa << 1) | (ee);
+
+ msr &= ~(MSR_EE | MSR_PR | MSR_AP);
+ msr |= MSR_SA;
+
+ ppc_set_msr(msr);
+}
+
+#ifndef PPC_DRC
+static void ppc_tlbli(UINT32 op)
+{
+
+}
+
+static void ppc_tlbld(UINT32 op)
+{
+
+}
+#endif
+
+#ifndef PPC_DRC
+void ppc602_exception(int exception)
+{
+ switch( exception )
+ {
+ case EXCEPTION_IRQ: /* External Interrupt */
+ if( ppc_get_msr() & MSR_EE ) {
+ UINT32 msr = ppc_get_msr();
+
+ SRR0 = ppc.npc;
+ SRR1 = msr & 0xff73;
+
+ msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
+ if( msr & MSR_ILE )
+ msr |= MSR_LE;
+ else
+ msr &= ~MSR_LE;
+ ppc_set_msr(msr);
+
+ if( msr & MSR_IP )
+ ppc.npc = 0xfff00000 | 0x0500;
+ else
+ ppc.npc = ppc.ibr | 0x0500;
+
+ ppc.interrupt_pending &= ~0x1;
+ }
+ break;
+
+ case EXCEPTION_DECREMENTER: /* Decrementer overflow exception */
+ if( ppc_get_msr() & MSR_EE ) {
+ UINT32 msr = ppc_get_msr();
+
+ SRR0 = ppc.npc;
+ SRR1 = msr & 0xff73;
+
+ msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
+ if( msr & MSR_ILE )
+ msr |= MSR_LE;
+ else
+ msr &= ~MSR_LE;
+ ppc_set_msr(msr);
+
+ if( msr & MSR_IP )
+ ppc.npc = 0xfff00000 | 0x0900;
+ else
+ ppc.npc = ppc.ibr | 0x0900;
+
+ ppc.interrupt_pending &= ~0x2;
+ }
+ break;
+
+ case EXCEPTION_TRAP: /* Program exception / Trap */
+ {
+ UINT32 msr = ppc_get_msr();
+
+ SRR0 = ppc.pc;
+ SRR1 = (msr & 0xff73) | 0x20000; /* 0x20000 = TRAP bit */
+
+ msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
+ if( msr & MSR_ILE )
+ msr |= MSR_LE;
+ else
+ msr &= ~MSR_LE;
+
+ if( msr & MSR_IP )
+ ppc.npc = 0xfff00000 | 0x0700;
+ else
+ ppc.npc = ppc.ibr | 0x0700;
+ }
+ break;
+
+ case EXCEPTION_SYSTEM_CALL: /* System call */
+ {
+ UINT32 msr = ppc_get_msr();
+
+ SRR0 = ppc.npc;
+ SRR1 = (msr & 0xff73);
+
+ msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
+ if( msr & MSR_ILE )
+ msr |= MSR_LE;
+ else
+ msr &= ~MSR_LE;
+
+ if( msr & MSR_IP )
+ ppc.npc = 0xfff00000 | 0x0c00;
+ else
+ ppc.npc = ppc.ibr | 0x0c00;
+ }
+ break;
+
+ case EXCEPTION_SMI:
+ if( ppc_get_msr() & MSR_EE ) {
+ UINT32 msr = ppc_get_msr();
+
+ SRR0 = ppc.npc;
+ SRR1 = msr & 0xff73;
+
+ msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
+ if( msr & MSR_ILE )
+ msr |= MSR_LE;
+ else
+ msr &= ~MSR_LE;
+ ppc_set_msr(msr);
+
+ if( msr & MSR_IP )
+ ppc.npc = 0xfff00000 | 0x1400;
+ else
+ ppc.npc = ppc.ibr | 0x1400;
+
+ ppc.interrupt_pending &= ~0x4;
+ }
+ break;
+
+
+ default:
+ fatalerror("ppc: Unhandled exception %d", exception);
+ break;
+ }
+}
+
+static void ppc602_set_irq_line(int irqline, int state)
+{
+ if( state ) {
+ ppc.interrupt_pending |= 0x1;
+ if (ppc.irq_callback)
+ {
+ ppc.irq_callback(ppc.device, irqline);
+ }
+ }
+}
+
+static void ppc602_set_smi_line(int state)
+{
+ if( state ) {
+ ppc.interrupt_pending |= 0x4;
+ }
+}
+
+INLINE void ppc602_check_interrupts(void)
+{
+ if (MSR & MSR_EE)
+ {
+ if (ppc.interrupt_pending != 0)
+ {
+ if (ppc.interrupt_pending & 0x1)
+ {
+ ppc602_exception(EXCEPTION_IRQ);
+ }
+ else if (ppc.interrupt_pending & 0x2)
+ {
+ ppc602_exception(EXCEPTION_DECREMENTER);
+ }
+ else if (ppc.interrupt_pending & 0x4)
+ {
+ ppc602_exception(EXCEPTION_SMI);
+ }
+ }
+ }
+}
+
+static CPU_RESET( ppc602 )
+{
+ ppc.pc = ppc.npc = 0xfff00100;
+
+ ppc_set_msr(0x40);
+
+ ppc.hid0 = 1;
+
+ ppc.interrupt_pending = 0;
+}
+
+static CPU_EXECUTE( ppc602 )
+{
+ int exception_type;
+ UINT32 opcode;
+ ppc_tb_base_icount = ppc_icount;
+ ppc_dec_base_icount = ppc_icount;
+
+ // check if decrementer exception occurs during execution
+ if ((UINT32)(DEC - ppc_icount) > (UINT32)(DEC))
+ {
+ ppc_dec_trigger_cycle = ppc_icount - DEC;
+ }
+ else
+ {
+ ppc_dec_trigger_cycle = 0x7fffffff;
+ }
+
+ // MinGW's optimizer kills setjmp()/longjmp()
+ SETJMP_GNUC_PROTECT();
+
+ exception_type = setjmp(ppc.exception_jmpbuf);
+ if (exception_type)
+ {
+ ppc.npc = ppc.pc;
+ ppc602_exception(exception_type);
+ }
+
+ while( ppc_icount > 0 )
+ {
+ ppc.pc = ppc.npc;
+ debugger_instruction_hook(device, ppc.pc);
+
+ if (MSR & MSR_IR)
+ opcode = ppc_readop_translated(ppc.program, ppc.pc);
+ else
+ opcode = ROPCODE64(ppc.pc);
+
+ ppc.npc = ppc.pc + 4;
+ switch(opcode >> 26)
+ {
+ case 19: ppc.optable19[(opcode >> 1) & 0x3ff](opcode); break;
+ case 31: ppc.optable31[(opcode >> 1) & 0x3ff](opcode); break;
+ case 59: ppc.optable59[(opcode >> 1) & 0x3ff](opcode); break;
+ case 63: ppc.optable63[(opcode >> 1) & 0x3ff](opcode); break;
+ default: ppc.optable[opcode >> 26](opcode); break;
+ }
+
+ ppc_icount--;
+
+ if(ppc_icount == ppc_dec_trigger_cycle) {
+ ppc.interrupt_pending |= 0x2;
+ }
+
+ ppc602_check_interrupts();
+ }
+
+ // update timebase
+ // timebase is incremented once every four core clock cycles, so adjust the cycles accordingly
+ ppc.tb += ((ppc_tb_base_icount - ppc_icount) / 4);
+
+ // update decrementer
+ DEC -= ((ppc_dec_base_icount - ppc_icount) / (bus_freq_multiplier * 2));
+}
+#endif // PPC_DRC
diff --git a/trunk/src/emu/cpu/powerpc/ppc603.c b/trunk/src/emu/cpu/powerpc/ppc603.c
new file mode 100644
index 00000000000..d4dd2ca926c
--- /dev/null
+++ b/trunk/src/emu/cpu/powerpc/ppc603.c
@@ -0,0 +1,283 @@
+void ppc603_exception(int exception)
+{
+ switch( exception )
+ {
+ case EXCEPTION_IRQ: /* External Interrupt */
+ if( ppc_get_msr() & MSR_EE ) {
+ UINT32 msr = ppc_get_msr();
+
+ SRR0 = ppc.npc;
+ SRR1 = msr & 0xff73;
+
+ msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
+ if( msr & MSR_ILE )
+ msr |= MSR_LE;
+ else
+ msr &= ~MSR_LE;
+ ppc_set_msr(msr);
+
+ if( msr & MSR_IP )
+ ppc.npc = 0xfff00000 | 0x0500;
+ else
+ ppc.npc = 0x00000000 | 0x0500;
+
+ ppc.interrupt_pending &= ~0x1;
+ }
+ break;
+
+ case EXCEPTION_DECREMENTER: /* Decrementer overflow exception */
+ if( ppc_get_msr() & MSR_EE ) {
+ UINT32 msr = ppc_get_msr();
+
+ SRR0 = ppc.npc;
+ SRR1 = msr & 0xff73;
+
+ msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
+ if( msr & MSR_ILE )
+ msr |= MSR_LE;
+ else
+ msr &= ~MSR_LE;
+ ppc_set_msr(msr);
+
+ if( msr & MSR_IP )
+ ppc.npc = 0xfff00000 | 0x0900;
+ else
+ ppc.npc = 0x00000000 | 0x0900;
+
+ ppc.interrupt_pending &= ~0x2;
+ }
+ break;
+
+ case EXCEPTION_TRAP: /* Program exception / Trap */
+ {
+ UINT32 msr = ppc_get_msr();
+
+ SRR0 = ppc.pc;
+ SRR1 = (msr & 0xff73) | 0x20000; /* 0x20000 = TRAP bit */
+
+ msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
+ if( msr & MSR_ILE )
+ msr |= MSR_LE;
+ else
+ msr &= ~MSR_LE;
+ ppc_set_msr(msr);
+
+ if( msr & MSR_IP )
+ ppc.npc = 0xfff00000 | 0x0700;
+ else
+ ppc.npc = 0x00000000 | 0x0700;
+ }
+ break;
+
+ case EXCEPTION_SYSTEM_CALL: /* System call */
+ {
+ UINT32 msr = ppc_get_msr();
+
+ SRR0 = ppc.npc;
+ SRR1 = (msr & 0xff73);
+
+ msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
+ if( msr & MSR_ILE )
+ msr |= MSR_LE;
+ else
+ msr &= ~MSR_LE;
+ ppc_set_msr(msr);
+
+ if( msr & MSR_IP )
+ ppc.npc = 0xfff00000 | 0x0c00;
+ else
+ ppc.npc = 0x00000000 | 0x0c00;
+ }
+ break;
+
+ case EXCEPTION_SMI:
+ if( ppc_get_msr() & MSR_EE ) {
+ UINT32 msr = ppc_get_msr();
+
+ SRR0 = ppc.npc;
+ SRR1 = msr & 0xff73;
+
+ msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
+ if( msr & MSR_ILE )
+ msr |= MSR_LE;
+ else
+ msr &= ~MSR_LE;
+ ppc_set_msr(msr);
+
+ if( msr & MSR_IP )
+ ppc.npc = 0xfff00000 | 0x1400;
+ else
+ ppc.npc = 0x00000000 | 0x1400;
+
+ ppc.interrupt_pending &= ~0x4;
+ }
+ break;
+
+ case EXCEPTION_DSI:
+ {
+ UINT32 msr = ppc_get_msr();
+
+ SRR0 = ppc.npc;
+ SRR1 = msr & 0xff73;
+
+ msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
+ if( msr & MSR_ILE )
+ msr |= MSR_LE;
+ else
+ msr &= ~MSR_LE;
+ ppc_set_msr(msr);
+
+ if( msr & MSR_IP )
+ ppc.npc = 0xfff00000 | 0x0300;
+ else
+ ppc.npc = 0x00000000 | 0x0300;
+
+ ppc.interrupt_pending &= ~0x4;
+ }
+ break;
+
+ case EXCEPTION_ISI:
+ {
+ UINT32 msr = ppc_get_msr();
+
+ SRR0 = ppc.npc;
+ SRR1 = msr & 0xff73;
+
+ msr &= ~(MSR_POW | MSR_EE | MSR_PR | MSR_FP | MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1 | MSR_IR | MSR_DR | MSR_RI);
+ if( msr & MSR_ILE )
+ msr |= MSR_LE;
+ else
+ msr &= ~MSR_LE;
+ ppc_set_msr(msr);
+
+ if( msr & MSR_IP )
+ ppc.npc = 0xfff00000 | 0x0400;
+ else
+ ppc.npc = 0x00000000 | 0x0400;
+
+ ppc.interrupt_pending &= ~0x4;
+ }
+ break;
+
+ default:
+ fatalerror("ppc: Unhandled exception %d", exception);
+ break;
+ }
+}
+
+static void ppc603_set_irq_line(int irqline, int state)
+{
+ if( state ) {
+ ppc.interrupt_pending |= 0x1;
+ if (ppc.irq_callback)
+ {
+ ppc.irq_callback(ppc.device, irqline);
+ }
+ }
+}
+
+static void ppc603_set_smi_line(int state)
+{
+ if( state ) {
+ ppc.interrupt_pending |= 0x4;
+ }
+}
+
+INLINE void ppc603_check_interrupts(void)
+{
+ if (MSR & MSR_EE)
+ {
+ if (ppc.interrupt_pending != 0)
+ {
+ if (ppc.interrupt_pending & 0x1)
+ {
+ ppc603_exception(EXCEPTION_IRQ);
+ }
+ else if (ppc.interrupt_pending & 0x2)
+ {
+ ppc603_exception(EXCEPTION_DECREMENTER);
+ }
+ else if (ppc.interrupt_pending & 0x4)
+ {
+ ppc603_exception(EXCEPTION_SMI);
+ }
+ }
+ }
+}
+
+static CPU_RESET( ppc603 )
+{
+ ppc.pc = ppc.npc = 0xfff00100;
+
+ ppc_set_msr(0x40);
+
+ ppc.hid0 = 1;
+
+ ppc.interrupt_pending = 0;
+}
+
+
+static CPU_EXECUTE( ppc603 )
+{
+ int exception_type;
+ UINT32 opcode;
+ ppc_tb_base_icount = ppc_icount;
+ ppc_dec_base_icount = ppc_icount + ppc.dec_frac;
+
+ // check if decrementer exception occurs during execution
+ if ((UINT32)(DEC - ppc_icount) > (UINT32)(DEC))
+ {
+ ppc_dec_trigger_cycle = ppc_icount - DEC;
+ }
+ else
+ {
+ ppc_dec_trigger_cycle = 0x7fffffff;
+ }
+
+ // MinGW's optimizer kills setjmp()/longjmp()
+ SETJMP_GNUC_PROTECT();
+
+ exception_type = setjmp(ppc.exception_jmpbuf);
+ if (exception_type)
+ {
+ ppc.npc = ppc.pc;
+ ppc603_exception(exception_type);
+ }
+
+ while( ppc_icount > 0 )
+ {
+ ppc.pc = ppc.npc;
+ debugger_instruction_hook(device, ppc.pc);
+
+ if (MSR & MSR_IR)
+ opcode = ppc_readop_translated(ppc.program, ppc.pc);
+ else
+ opcode = ROPCODE64(ppc.pc);
+
+ ppc.npc = ppc.pc + 4;
+ switch(opcode >> 26)
+ {
+ case 19: ppc.optable19[(opcode >> 1) & 0x3ff](opcode); break;
+ case 31: ppc.optable31[(opcode >> 1) & 0x3ff](opcode); break;
+ case 59: ppc.optable59[(opcode >> 1) & 0x3ff](opcode); break;
+ case 63: ppc.optable63[(opcode >> 1) & 0x3ff](opcode); break;
+ default: ppc.optable[opcode >> 26](opcode); break;
+ }
+
+ ppc_icount--;
+
+ if(ppc_icount == ppc_dec_trigger_cycle) {
+ ppc.interrupt_pending |= 0x2;
+ }
+
+ ppc603_check_interrupts();
+ }
+
+ // update timebase
+ // timebase is incremented once every four core clock cycles, so adjust the cycles accordingly
+ ppc.tb += ((ppc_tb_base_icount - ppc_icount) / 4);
+
+ // update decrementer
+ ppc.dec_frac = ((ppc_dec_base_icount - ppc_icount) % (bus_freq_multiplier * 2));
+ DEC -= ((ppc_dec_base_icount - ppc_icount) / (bus_freq_multiplier * 2));
+}
diff --git a/trunk/src/emu/cpu/powerpc/ppc_dasm.c b/trunk/src/emu/cpu/powerpc/ppc_dasm.c
new file mode 100644
index 00000000000..c53a446f06b
--- /dev/null
+++ b/trunk/src/emu/cpu/powerpc/ppc_dasm.c
@@ -0,0 +1,1175 @@
+/*
+ * disasm.c
+ *
+ * PowerPC 603e disassembler.
+ *
+ * When possible, invalid forms of instructions are checked for. To the best
+ * of my knowledge, all appropriate load/store instructions are checked. I'm
+ * not sure whether any other kinds of instructions need checking.
+ */
+
+/* Originally written by Bart Trzynadlowski for Supermodel project
+ *
+ * PowerPC 403 opcodes and MAME conversion by Ville Linde
+ */
+
+#include "emu.h"
+#include "debugger.h"
+#include "ppccom.h"
+
+/*
+ * Operand Formats
+ *
+ * These convey information on what operand fields are present and how they
+ * ought to be printed.
+ *
+ * I'm fairly certain all of these are used, but that is not guaranteed.
+ */
+
+enum
+{
+ F_NONE, // <no operands>
+ F_LI, // LI*4+PC if AA=0 else LI*4
+ F_BCx, // BO, BI, target_addr used only by BCx
+ F_RT_RA_0_SIMM, // rT, rA|0, SIMM rA|0 means if rA == 0, print 0
+ F_ADDIS, // rT, rA, SIMM (printed as unsigned) only used by ADDIS
+ F_RT_RA_SIMM, // rT, rA, SIMM
+ F_RA_RT_UIMM, // rA, rT, UIMM
+ F_CMP_SIMM, // crfD, L, A, SIMM
+ F_CMP_UIMM, // crfD, L, A, UIMM
+ F_RT_RA_0_RB, // rT, rA|0, rB
+ F_RT_RA_RB, // rT, rA, rB
+ F_RT_D_RA_0, // rT, d(rA|0)
+ F_RT_D_RA, // rT, d(rA)
+ F_RA_RT_RB, // rA, rT, rB
+ F_FRT_D_RA_0, // frT, d(RA|0)
+ F_FRT_D_RA, // frT, d(RA)
+ F_FRT_RA_0_RB, // frT, rA|0, rB
+ F_FRT_RA_RB, // frT, rA, rB
+ F_TWI, // TO, rA, SIMM only used by TWI instruction
+ F_CMP, // crfD, L, rA, rB
+ F_RA_RT, // rA, rT
+ F_RA_0_RB, // rA|0, rB
+ F_FRT_FRB, // frT, frB
+ F_FCMP, // crfD, frA, frB
+ F_CRFD_CRFS, // crfD, crfS
+ F_MCRXR, // crfD only used by MCRXR
+ F_RT, // rT
+ F_MFSR, // rT, SR only used by MFSR
+ F_MTSR, // SR, rT only used by MTSR
+ F_MFFSx, // frT only used by MFFSx
+ F_FCRBD, // crbD FPSCR[crbD]
+ F_MTFSFIx, // crfD, IMM only used by MTFSFIx
+ F_RB, // rB
+ F_TW, // TO, rA, rB only used by TW
+ F_RT_RA_0_NB, // rT, rA|0, NB print 32 if NB == 0
+ F_SRAWIx, // rA, rT, SH only used by SRAWIx
+ F_BO_BI, // BO, BI
+ F_CRBD_CRBA_CRBB, // crbD, crbA, crbB
+ F_RT_SPR, // rT, SPR and TBR
+ F_MTSPR, // SPR, rT only used by MTSPR
+ F_MTCRF, // CRM, rT only used by MTCRF
+ F_MTFSFx, // FM, frB only used by MTFSFx
+ F_RT_DCR, // rT, DCR
+ F_MTDCR, // DCR, rT
+ F_RT_RA, // rT, rA
+ F_FRT_FRA_FRC_FRB, // frT, frA, frC, frB
+ F_FRT_FRA_FRB, // frT, frA, frB
+ F_FRT_FRA_FRC, // frT, frA, frC
+ F_RA_RT_SH_MB_ME, // rA, rT, SH, MB, ME
+ F_RLWNMx, // rT, rA, rB, MB, ME only used by RLWNMx
+ F_RT_RB, // rT, rB
+};
+
+/*
+ * Flags
+ */
+
+#define FL_OE (1 << 0) // if there is an OE field
+#define FL_RC (1 << 1) // if there is an RC field
+#define FL_LK (1 << 2) // if there is an LK field
+#define FL_AA (1 << 3) // if there is an AA field
+#define FL_CHECK_RA_RT (1 << 4) // assert rA!=0 and rA!=rT
+#define FL_CHECK_RA (1 << 5) // assert rA!=0
+#define FL_CHECK_LSWI (1 << 6) // specific check for LSWI validity
+#define FL_CHECK_LSWX (1 << 7) // specific check for LSWX validity
+#define FL_SO (1 << 8) // use DASMFLAG_STEP_OUT
+
+
+/*
+ * Instruction Descriptor
+ *
+ * Describes the layout of an instruction.
+ */
+
+typedef struct
+{
+ char mnem[32]; // mnemonic
+ UINT32 match; // bit pattern of instruction after it has been masked
+ UINT32 mask; // mask of variable fields (AND with ~mask to compare w/
+ // bit pattern to determine a match)
+ int format; // operand format
+ int flags; // flags
+} IDESCR;
+
+/*
+ * Instruction Table
+ *
+ * Table of instruction descriptors which allows the disassembler to decode
+ * and print instructions.
+ */
+
+static const IDESCR itab[] =
+{
+ { "add", D_OP(31)|D_XO(266), M_RT|M_RA|M_RB|M_OE|M_RC, F_RT_RA_RB, FL_OE|FL_RC },
+ { "addc", D_OP(31)|D_XO(10), M_RT|M_RA|M_RB|M_OE|M_RC, F_RT_RA_RB, FL_OE|FL_RC },
+ { "adde", D_OP(31)|D_XO(138), M_RT|M_RA|M_RB|M_OE|M_RC, F_RT_RA_RB, FL_OE|FL_RC },
+ { "addi", D_OP(14), M_RT|M_RA|M_SIMM, F_RT_RA_0_SIMM, 0 },
+ { "addic", D_OP(12), M_RT|M_RA|M_SIMM, F_RT_RA_SIMM, 0 },
+ { "addic.", D_OP(13), M_RT|M_RA|M_SIMM, F_RT_RA_SIMM, 0 },
+ { "addis", D_OP(15), M_RT|M_RA|M_SIMM, F_ADDIS, 0 },
+ { "addme", D_OP(31)|D_XO(234), M_RT|M_RA|M_OE|M_RC, F_RT_RA, FL_OE|FL_RC },
+ { "addze", D_OP(31)|D_XO(202), M_RT|M_RA|M_OE|M_RC, F_RT_RA, FL_OE|FL_RC },
+ { "and", D_OP(31)|D_XO(28), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC },
+ { "andc", D_OP(31)|D_XO(60), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC },
+ { "andi.", D_OP(28), M_RT|M_RA|M_UIMM, F_RA_RT_UIMM, 0 },
+ { "andis.", D_OP(29), M_RT|M_RA|M_UIMM, F_RA_RT_UIMM, 0 },
+ { "b", D_OP(18), M_LI|M_AA|M_LK, F_LI, FL_AA|FL_LK },
+ { "bc", D_OP(16), M_BO|M_BI|M_BD|M_AA|M_LK, F_BCx, FL_AA|FL_LK },
+ { "bcctr", D_OP(19)|D_XO(528), M_BO|M_BI|M_LK, F_BO_BI, FL_LK },
+ { "bclr", D_OP(19)|D_XO(16), M_BO|M_BI|M_LK, F_BO_BI, FL_LK|FL_SO },
+ { "cmp", D_OP(31)|D_XO(0), M_CRFD|M_RA|M_RB, F_CMP, 0 },
+ { "cmpd", D_OP(31)|D_XO(0)|M_L,M_CRFD|M_RA|M_RB, F_CMP, 0 },
+ { "cmpi", D_OP(11), M_CRFD|M_RA|M_SIMM, F_CMP_SIMM, 0 },
+ { "cmpdi", D_OP(11)|M_L, M_CRFD|M_RA|M_SIMM, F_CMP_SIMM, 0 },
+ { "cmpl", D_OP(31)|D_XO(32), M_CRFD|M_RA|M_RB, F_CMP, 0 },
+ { "cmpld", D_OP(31)|D_XO(32)|M_L,M_CRFD|M_RA|M_RB, F_CMP, 0 },
+ { "cmpli", D_OP(10), M_CRFD|M_RA|M_UIMM, F_CMP_UIMM, 0 },
+ { "cmpldi", D_OP(10)|M_L, M_CRFD|M_RA|M_UIMM, F_CMP_UIMM, 0 },
+ { "cntlzw", D_OP(31)|D_XO(26), M_RT|M_RA|M_RC, F_RA_RT, FL_RC },
+ { "crand", D_OP(19)|D_XO(257), M_CRBD|M_CRBA|M_CRBB, F_CRBD_CRBA_CRBB, 0 },
+ { "crandc", D_OP(19)|D_XO(129), M_CRBD|M_CRBA|M_CRBB, F_CRBD_CRBA_CRBB, 0 },
+ { "creqv", D_OP(19)|D_XO(289), M_CRBD|M_CRBA|M_CRBB, F_CRBD_CRBA_CRBB, 0 },
+ { "crnand", D_OP(19)|D_XO(225), M_CRBD|M_CRBA|M_CRBB, F_CRBD_CRBA_CRBB, 0 },
+ { "crnor", D_OP(19)|D_XO(33), M_CRBD|M_CRBA|M_CRBB, F_CRBD_CRBA_CRBB, 0 },
+ { "cror", D_OP(19)|D_XO(449), M_CRBD|M_CRBA|M_CRBB, F_CRBD_CRBA_CRBB, 0 },
+ { "crorc", D_OP(19)|D_XO(417), M_CRBD|M_CRBA|M_CRBB, F_CRBD_CRBA_CRBB, 0 },
+ { "crxor", D_OP(19)|D_XO(193), M_CRBD|M_CRBA|M_CRBB, F_CRBD_CRBA_CRBB, 0 },
+ { "dcba", D_OP(31)|D_XO(758), M_RA|M_RB, F_RA_0_RB, 0 },
+ { "dcbf", D_OP(31)|D_XO(86), M_RA|M_RB, F_RA_0_RB, 0 },
+ { "dcbi", D_OP(31)|D_XO(470), M_RA|M_RB, F_RA_0_RB, 0 },
+ { "dcbst", D_OP(31)|D_XO(54), M_RA|M_RB, F_RA_0_RB, 0 },
+ { "dcbt", D_OP(31)|D_XO(278), M_RA|M_RB, F_RA_0_RB, 0 },
+ { "dcbtst", D_OP(31)|D_XO(246), M_RA|M_RB, F_RA_0_RB, 0 },
+ { "dcbz", D_OP(31)|D_XO(1014),M_RA|M_RB, F_RA_0_RB, 0 },
+ { "dccci", D_OP(31)|D_XO(454), M_RA|M_RB, F_RA_0_RB, 0 },
+ { "dcread", D_OP(31)|D_XO(486), M_RA|M_RB, F_RT_RA_RB, 0 },
+ { "divw", D_OP(31)|D_XO(491), M_RT|M_RA|M_RB|M_OE|M_RC, F_RT_RA_RB, FL_OE|FL_RC },
+ { "divwu", D_OP(31)|D_XO(459), M_RT|M_RA|M_RB|M_OE|M_RC, F_RT_RA_RB, FL_OE|FL_RC },
+ { "dsa", D_OP(31)|D_XO(628), 0, 0, 0 },
+ { "eciwx", D_OP(31)|D_XO(310), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0 },
+ { "ecowx", D_OP(31)|D_XO(438), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0 },
+ { "eieio", D_OP(31)|D_XO(854), 0, F_NONE, 0 },
+ { "eqv", D_OP(31)|D_XO(284), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC },
+ { "esa", D_OP(31)|D_XO(596), 0, 0, 0 },
+ { "extsb", D_OP(31)|D_XO(954), M_RT|M_RA|M_RC, F_RA_RT, FL_RC },
+ { "extsh", D_OP(31)|D_XO(922), M_RT|M_RA|M_RC, F_RA_RT, FL_RC },
+ { "fabs", D_OP(63)|D_XO(264), M_RT|M_RB|M_RC, F_FRT_FRB, FL_RC },
+ { "fadd", D_OP(63)|D_XO(21), M_RT|M_RA|M_RB|M_RC, F_FRT_FRA_FRB, FL_RC },
+ { "fadds", D_OP(59)|D_XO(21), M_RT|M_RA|M_RB|M_RC, F_FRT_FRA_FRB, FL_RC },
+ { "fcmpo", D_OP(63)|D_XO(32), M_CRFD|M_RA|M_RB, F_FCMP, 0 },
+ { "fcmpu", D_OP(63)|D_XO(0), M_CRFD|M_RA|M_RB, F_FCMP, 0 },
+ { "fctiw", D_OP(63)|D_XO(14), M_RT|M_RB|M_RC, F_FRT_FRB, FL_RC },
+ { "fctiwz", D_OP(63)|D_XO(15), M_RT|M_RB|M_RC, F_FRT_FRB, FL_RC },
+ { "fdiv", D_OP(63)|D_XO(18), M_RT|M_RA|M_RB|M_RC, F_FRT_FRA_FRB, FL_RC },
+ { "fdivs", D_OP(59)|D_XO(18), M_RT|M_RA|M_RB|M_RC, F_FRT_FRA_FRB, FL_RC },
+ { "fmadd", D_OP(63)|D_XO(29), M_RT|M_RA|M_RB|M_REGC|M_RC, F_FRT_FRA_FRC_FRB, FL_RC },
+ { "fmadds", D_OP(59)|D_XO(29), M_RT|M_RA|M_RB|M_REGC|M_RC, F_FRT_FRA_FRC_FRB, FL_RC },
+ { "fmr", D_OP(63)|D_XO(72), M_RT|M_RB|M_RC, F_FRT_FRB, FL_RC },
+ { "fmsub", D_OP(63)|D_XO(28), M_RT|M_RA|M_RB|M_REGC|M_RC, F_FRT_FRA_FRC_FRB, FL_RC },
+ { "fmsubs", D_OP(59)|D_XO(28), M_RT|M_RA|M_RB|M_REGC|M_RC, F_FRT_FRA_FRC_FRB, FL_RC },
+ { "fmul", D_OP(63)|D_XO(25), M_RT|M_RA|M_REGC|M_RC, F_FRT_FRA_FRC, FL_RC },
+ { "fmuls", D_OP(59)|D_XO(25), M_RT|M_RA|M_REGC|M_RC, F_FRT_FRA_FRC, FL_RC },
+ { "fnabs", D_OP(63)|D_XO(136), M_RT|M_RB|M_RC, F_FRT_FRB, FL_RC },
+ { "fneg", D_OP(63)|D_XO(40), M_RT|M_RB|M_RC, F_FRT_FRB, FL_RC },
+ { "fnmadd", D_OP(63)|D_XO(31), M_RT|M_RA|M_RB|M_REGC|M_RC, F_FRT_FRA_FRC_FRB, FL_RC },
+ { "fnmadds",D_OP(59)|D_XO(31), M_RT|M_RA|M_RB|M_REGC|M_RC, F_FRT_FRA_FRC_FRB, FL_RC },
+ { "fnmsub", D_OP(63)|D_XO(30), M_RT|M_RA|M_RB|M_REGC|M_RC, F_FRT_FRA_FRC_FRB, FL_RC },
+ { "fnmsubs",D_OP(59)|D_XO(30), M_RT|M_RA|M_RB|M_REGC|M_RC, F_FRT_FRA_FRC_FRB, FL_RC },
+ { "fres", D_OP(59)|D_XO(24), M_RT|M_RB|M_RC, F_FRT_FRB, FL_RC },
+ { "frsp", D_OP(63)|D_XO(12), M_RT|M_RB|M_RC, F_FRT_FRB, FL_RC },
+ { "frsqrte",D_OP(63)|D_XO(26), M_RT|M_RB|M_RC, F_FRT_FRB, FL_RC },
+ { "fsel", D_OP(63)|D_XO(23), M_RT|M_RA|M_RB|M_REGC|M_RC, F_FRT_FRA_FRC_FRB, FL_RC },
+ { "fsqrt", D_OP(63)|D_XO(22), M_RT|M_RB|M_RC, F_FRT_FRB, FL_RC },
+ { "fsqrts", D_OP(59)|D_XO(22), M_RT|M_RB|M_RC, F_FRT_FRB, FL_RC },
+ { "fsub", D_OP(63)|D_XO(20), M_RT|M_RA|M_RB|M_RC, F_FRT_FRA_FRB, FL_RC },
+ { "fsubs", D_OP(59)|D_XO(20), M_RT|M_RA|M_RB|M_RC, F_FRT_FRA_FRB, FL_RC },
+ { "icbi", D_OP(31)|D_XO(982), M_RA|M_RB, F_RA_0_RB, 0 },
+ { "icbt", D_OP(31)|D_XO(262), M_RA|M_RB, F_RA_0_RB, 0 },
+ { "iccci", D_OP(31)|D_XO(966), M_RA|M_RB, F_RA_0_RB, 0 },
+ { "icread", D_OP(31)|D_XO(998), M_RA|M_RB, F_RA_0_RB, 0 },
+ { "isync", D_OP(19)|D_XO(150), 0, F_NONE, 0 },
+ { "lbz", D_OP(34), M_RT|M_RA|M_D, F_RT_D_RA_0, 0 },
+ { "lbzu", D_OP(35), M_RT|M_RA|M_D, F_RT_D_RA, FL_CHECK_RA_RT },
+ { "lbzux", D_OP(31)|D_XO(119), M_RT|M_RA|M_RB, F_RT_RA_RB, FL_CHECK_RA_RT },
+ { "lbzx", D_OP(31)|D_XO(87), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0 },
+ { "lfd", D_OP(50), M_RT|M_RA|M_D, F_FRT_D_RA_0, 0 },
+ { "lfdu", D_OP(51), M_RT|M_RA|M_D, F_FRT_D_RA, FL_CHECK_RA },
+ { "lfdux", D_OP(31)|D_XO(631), M_RT|M_RA|M_RB, F_FRT_RA_RB, FL_CHECK_RA },
+ { "lfdx", D_OP(31)|D_XO(599), M_RT|M_RA|M_RB, F_FRT_RA_0_RB, 0 },
+ { "lfs", D_OP(48), M_RT|M_RA|M_D, F_FRT_D_RA_0, 0 },
+ { "lfsu", D_OP(49), M_RT|M_RA|M_D, F_FRT_D_RA, FL_CHECK_RA },
+ { "lfsux", D_OP(31)|D_XO(567), M_RT|M_RA|M_RB, F_FRT_RA_RB, FL_CHECK_RA },
+ { "lfsx", D_OP(31)|D_XO(535), M_RT|M_RA|M_RB, F_FRT_RA_0_RB, 0 },
+ { "lha", D_OP(42), M_RT|M_RA|M_D, F_RT_D_RA_0, 0 },
+ { "lhau", D_OP(43), M_RT|M_RA|M_D, F_RT_D_RA, FL_CHECK_RA_RT },
+ { "lhaux", D_OP(31)|D_XO(375), M_RT|M_RA|M_RB, F_RT_RA_RB, FL_CHECK_RA_RT },
+ { "lhax", D_OP(31)|D_XO(343), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0 },
+ { "lhbrx", D_OP(31)|D_XO(790), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0 },
+ { "lhz", D_OP(40), M_RT|M_RA|M_D, F_RT_D_RA_0, 0 },
+ { "lhzu", D_OP(41), M_RT|M_RA|M_D, F_RT_D_RA, FL_CHECK_RA_RT },
+ { "lhzux", D_OP(31)|D_XO(311), M_RT|M_RA|M_RB, F_RT_RA_RB, FL_CHECK_RA_RT },
+ { "lhzx", D_OP(31)|D_XO(279), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0 },
+ { "lmw", D_OP(46), M_RT|M_RA|M_D, F_RT_D_RA_0, 0 },
+ { "lswi", D_OP(31)|D_XO(597), M_RT|M_RA|M_NB, F_RT_RA_0_NB, FL_CHECK_LSWI },
+ { "lswx", D_OP(31)|D_XO(533), M_RT|M_RA|M_RB, F_RT_RA_0_RB, FL_CHECK_LSWX },
+ { "lwarx", D_OP(31)|D_XO(20), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0 },
+ { "lwbrx", D_OP(31)|D_XO(534), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0 },
+ { "lwz", D_OP(32), M_RT|M_RA|M_D, F_RT_D_RA_0, 0 },
+ { "lwzu", D_OP(33), M_RT|M_RA|M_D, F_RT_D_RA, FL_CHECK_RA_RT },
+ { "lwzux", D_OP(31)|D_XO(55), M_RT|M_RA|M_RB, F_RT_RA_RB, FL_CHECK_RA_RT },
+ { "lwzx", D_OP(31)|D_XO(23), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0 },
+ { "mcrf", D_OP(19)|D_XO(0), M_CRFD|M_CRFS, F_CRFD_CRFS, 0 },
+ { "mcrfs", D_OP(63)|D_XO(64), M_CRFD|M_CRFS, F_CRFD_CRFS, 0 },
+ { "mcrxr", D_OP(31)|D_XO(512), M_CRFD, F_MCRXR, 0 },
+ { "mfcr", D_OP(31)|D_XO(19), M_RT, F_RT, 0 },
+ { "mfdcr", D_OP(31)|D_XO(323), M_RT|M_DCR, F_RT_DCR, 0 },
+ { "mffs", D_OP(63)|D_XO(583), M_RT|M_RC, F_MFFSx, FL_RC },
+ { "mfmsr", D_OP(31)|D_XO(83), M_RT, F_RT, 0 },
+ { "mfspr", D_OP(31)|D_XO(339), M_RT|M_SPR, F_RT_SPR, 0 },
+ { "mfsr", D_OP(31)|D_XO(595), M_RT|M_SR, F_MFSR, 0 },
+ { "mfsrin", D_OP(31)|D_XO(659), M_RT|M_RB, F_RT_RB, 0 },
+ { "mftb", D_OP(31)|D_XO(371), M_RT|M_TBR, F_RT_SPR, 0 },
+ { "mtcrf", D_OP(31)|D_XO(144), M_RT|M_CRM, F_MTCRF, 0 },
+ { "mtdcr", D_OP(31)|D_XO(451), M_RT|M_DCR, F_MTDCR, 0 },
+ { "mtfsb0", D_OP(63)|D_XO(70), M_CRBD|M_RC, F_FCRBD, FL_RC },
+ { "mtfsb1", D_OP(63)|D_XO(38), M_CRBD|M_RC, F_FCRBD, FL_RC },
+ { "mtfsf", D_OP(63)|D_XO(711), M_FM|M_RB|M_RC, F_MTFSFx, FL_RC },
+ { "mtfsfi", D_OP(63)|D_XO(134), M_CRFD|M_IMM|M_RC, F_MTFSFIx, FL_RC },
+ { "mtmsr", D_OP(31)|D_XO(146), M_RT, F_RT, 0 },
+ { "mtspr", D_OP(31)|D_XO(467), M_RT|M_SPR, F_MTSPR, 0 },
+ { "mtsr", D_OP(31)|D_XO(210), M_RT|M_SR, F_MTSR, 0 },
+ { "mtsrin", D_OP(31)|D_XO(242), M_RT|M_RB, F_RT_RB, 0 },
+ { "mulhw", D_OP(31)|D_XO(75), M_RT|M_RA|M_RB|M_RC, F_RT_RA_RB, FL_RC },
+ { "mulhwu", D_OP(31)|D_XO(11), M_RT|M_RA|M_RB|M_RC, F_RT_RA_RB, FL_RC },
+ { "mulli", D_OP(7), M_RT|M_RA|M_SIMM, F_RT_RA_SIMM, 0 },
+ { "mullw", D_OP(31)|D_XO(235), M_RT|M_RA|M_RB|M_OE|M_RC, F_RT_RA_RB, FL_OE|FL_RC },
+ { "nand", D_OP(31)|D_XO(476), M_RA|M_RT|M_RB|M_RC, F_RA_RT_RB, FL_RC },
+ { "neg", D_OP(31)|D_XO(104), M_RT|M_RA|M_OE|M_RC, F_RT_RA, FL_OE|FL_RC },
+ { "nor", D_OP(31)|D_XO(124), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC },
+ { "or", D_OP(31)|D_XO(444), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC },
+ { "orc", D_OP(31)|D_XO(412), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC },
+ { "ori", D_OP(24), M_RT|M_RA|M_UIMM, F_RA_RT_UIMM, 0 },
+ { "oris", D_OP(25), M_RT|M_RA|M_UIMM, F_RA_RT_UIMM, 0 },
+ { "rfi", D_OP(19)|D_XO(50), 0, F_NONE, 0 },
+ { "rfci", D_OP(19)|D_XO(51), 0, F_NONE, 0 },
+ { "rlwimi", D_OP(20), M_RT|M_RA|M_SH|M_MB|M_ME|M_RC, F_RA_RT_SH_MB_ME, FL_RC },
+ { "rlwinm", D_OP(21), M_RT|M_RA|M_SH|M_MB|M_ME|M_RC, F_RA_RT_SH_MB_ME, FL_RC },
+ { "rlwnm", D_OP(23), M_RT|M_RA|M_RB|M_MB|M_ME|M_RC, F_RLWNMx, FL_RC },
+ { "sc", D_OP(17)|2, 0, F_NONE, 0 },
+ { "slw", D_OP(31)|D_XO(24), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC },
+ { "sraw", D_OP(31)|D_XO(792), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC },
+ { "srawi", D_OP(31)|D_XO(824), M_RT|M_RA|M_SH|M_RC, F_SRAWIx, FL_RC },
+ { "srw", D_OP(31)|D_XO(536), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC },
+ { "stb", D_OP(38), M_RT|M_RA|M_D, F_RT_D_RA_0, 0 },
+ { "stbu", D_OP(39), M_RT|M_RA|M_D, F_RT_D_RA, FL_CHECK_RA },
+ { "stbux", D_OP(31)|D_XO(247), M_RT|M_RA|M_RB, F_RT_RA_RB, FL_CHECK_RA },
+ { "stbx", D_OP(31)|D_XO(215), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0 },
+ { "stfd", D_OP(54), M_RT|M_RA|M_D, F_FRT_D_RA_0, 0 },
+ { "stfdu", D_OP(55), M_RT|M_RA|M_D, F_FRT_D_RA, FL_CHECK_RA },
+ { "stfdux", D_OP(31)|D_XO(759), M_RT|M_RA|M_RB, F_FRT_RA_RB, FL_CHECK_RA },
+ { "stfdx", D_OP(31)|D_XO(727), M_RT|M_RA|M_RB, F_FRT_RA_0_RB, 0 },
+ { "stfiwx", D_OP(31)|D_XO(983), M_RT|M_RA|M_RB, F_FRT_RA_0_RB, 0 },
+ { "stfs", D_OP(52), M_RT|M_RA|M_D, F_FRT_D_RA_0, 0 },
+ { "stfsu", D_OP(53), M_RT|M_RA|M_D, F_FRT_D_RA, FL_CHECK_RA },
+ { "stfsux", D_OP(31)|D_XO(695), M_RT|M_RA|M_RB, F_FRT_RA_RB, FL_CHECK_RA },
+ { "stfsx", D_OP(31)|D_XO(663), M_RT|M_RA|M_RB, F_FRT_RA_0_RB, 0 },
+ { "sth", D_OP(44), M_RT|M_RA|M_D, F_RT_D_RA_0, 0 },
+ { "sthbrx", D_OP(31)|D_XO(918), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0 },
+ { "sthu", D_OP(45), M_RT|M_RA|M_D, F_RT_D_RA, FL_CHECK_RA },
+ { "sthux", D_OP(31)|D_XO(439), M_RT|M_RA|M_RB, F_RT_RA_RB, FL_CHECK_RA },
+ { "sthx", D_OP(31)|D_XO(407), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0 },
+ { "stmw", D_OP(47), M_RT|M_RA|M_D, F_RT_D_RA_0, 0 },
+ { "stswi", D_OP(31)|D_XO(725), M_RT|M_RA|M_NB, F_RT_RA_0_NB, 0 },
+ { "stswx", D_OP(31)|D_XO(661), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0 },
+ { "stw", D_OP(36), M_RT|M_RA|M_D, F_RT_D_RA_0, 0 },
+ { "stwbrx", D_OP(31)|D_XO(662), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0 },
+ { "stwcx.", D_OP(31)|D_XO(150)|1, M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0 },
+ { "stwu", D_OP(37), M_RT|M_RA|M_D, F_RT_D_RA, FL_CHECK_RA },
+ { "stwux", D_OP(31)|D_XO(183), M_RT|M_RA|M_RB, F_RT_RA_RB, FL_CHECK_RA },
+ { "stwx", D_OP(31)|D_XO(151), M_RT|M_RA|M_RB, F_RT_RA_0_RB, 0 },
+ { "subf", D_OP(31)|D_XO(40), M_RT|M_RA|M_RB|M_OE|M_RC, F_RT_RA_RB, FL_OE|FL_RC },
+ { "subfc", D_OP(31)|D_XO(8), M_RT|M_RA|M_RB|M_OE|M_RC, F_RT_RA_RB, FL_OE|FL_RC },
+ { "subfe", D_OP(31)|D_XO(136), M_RT|M_RA|M_RB|M_OE|M_RC, F_RT_RA_RB, FL_OE|FL_RC },
+ { "subfic", D_OP(8), M_RT|M_RA|M_SIMM, F_RT_RA_SIMM, 0 },
+ { "subfme", D_OP(31)|D_XO(232), M_RT|M_RA|M_OE|M_RC, F_RT_RA, FL_OE|FL_RC },
+ { "subfze", D_OP(31)|D_XO(200), M_RT|M_RA|M_OE|M_RC, F_RT_RA, FL_OE|FL_RC },
+ { "sync", D_OP(31)|D_XO(598), 0, F_NONE, 0 },
+ { "tlbia", D_OP(31)|D_XO(370), 0, F_NONE, 0 },
+ { "tlbie", D_OP(31)|D_XO(306), M_RB, F_RB, 0 },
+ { "tlbsync",D_OP(31)|D_XO(566), 0, F_NONE, 0 },
+ { "tw", D_OP(31)|D_XO(4), M_TO|M_RA|M_RB, F_TW, 0 },
+ { "twi", D_OP(3), M_TO|M_RA|M_SIMM, F_TWI, 0 },
+ { "wrtee", D_OP(31)|D_XO(131), M_RT, F_RT, 0 },
+ { "wrteei", D_OP(31)|D_XO(163), 0, 0, 0 },
+ { "xor", D_OP(31)|D_XO(316), M_RT|M_RA|M_RB|M_RC, F_RA_RT_RB, FL_RC },
+ { "xori", D_OP(26), M_RT|M_RA|M_UIMM, F_RA_RT_UIMM, 0 },
+ { "xoris", D_OP(27), M_RT|M_RA|M_UIMM, F_RA_RT_UIMM, 0 },
+
+ /*
+ * PowerPC 603e/EC603e-specific instructions
+ */
+
+ { "tlbld", D_OP(31)|D_XO(978), M_RB, F_RB, 0 },
+ { "tlbli", D_OP(31)|D_XO(1010),M_RB, F_RB, 0 }
+};
+
+/*
+ * CR Bits
+ *
+ * Use an index of BI&3 into this table to obtain the CR field bit name.
+ */
+
+static const char *const crbit[4] = { "lt", "gt", "eq", "so" };
+static const char *const crnbit[4] = { "ge", "le", "ne", "nso" };
+
+
+/*
+ * SPR():
+ *
+ * Decode the SPR (or TBR) field and append the register name to dest. If
+ * no name is associated with the field value, the value itself is printed.
+ */
+
+static void SPR(char *dest, int spr_field)
+{
+ int spr;
+
+ /*
+ * Construct the SPR number -- SPR field is 2 5-bit fields
+ */
+
+ spr = (spr_field >> 5) & 0x1f;
+ spr |= (spr_field & 0x1f) << 5;
+
+ /*
+ * Append the SPR name to the destination string using strcat()
+ */
+
+ switch (spr)
+ {
+ /* UISA SPR register indexes */
+ case SPR_XER: strcat(dest, "xer"); break;
+ case SPR_LR: strcat(dest, "lr"); break;
+ case SPR_CTR: strcat(dest, "ctr"); break;
+
+ /* VEA SPR register indexes */
+ case SPRVEA_TBL_R: strcat(dest, "tbl"); break;
+ case SPRVEA_TBU_R: strcat(dest, "tbu"); break;
+
+ /* OEA SPR register indexes */
+ case SPROEA_DSISR: strcat(dest, "dsisr"); break;
+ case SPROEA_DAR: strcat(dest, "dar"); break;
+ case SPROEA_DEC: strcat(dest, "dec"); break;
+ case SPROEA_SDR1: strcat(dest, "sdr1"); break;
+ case SPROEA_SRR0: strcat(dest, "srr0"); break;
+ case SPROEA_SRR1: strcat(dest, "srr1"); break;
+ case SPROEA_SPRG0: strcat(dest, "sprg0"); break;
+ case SPROEA_SPRG1: strcat(dest, "sprg1"); break;
+ case SPROEA_SPRG2: strcat(dest, "sprg2"); break;
+ case SPROEA_SPRG3: strcat(dest, "sprg3"); break;
+ case SPROEA_ASR: strcat(dest, "asr"); break;
+ case SPROEA_EAR: strcat(dest, "ear"); break;
+ case SPROEA_PVR: strcat(dest, "pvr"); break;
+ case SPROEA_IBAT0U: strcat(dest, "ibat0u"); break;
+ case SPROEA_IBAT0L: strcat(dest, "ibat0l"); break;
+ case SPROEA_IBAT1U: strcat(dest, "ibat1u"); break;
+ case SPROEA_IBAT1L: strcat(dest, "ibat1l"); break;
+ case SPROEA_IBAT2U: strcat(dest, "ibat2u"); break;
+ case SPROEA_IBAT2L: strcat(dest, "ibat2l"); break;
+ case SPROEA_IBAT3U: strcat(dest, "ibat3u"); break;
+ case SPROEA_IBAT3L: strcat(dest, "ibat3l"); break;
+ case SPROEA_DBAT0U: strcat(dest, "dbat0u"); break;
+ case SPROEA_DBAT0L: strcat(dest, "dbat0l"); break;
+ case SPROEA_DBAT1U: strcat(dest, "dbat1u"); break;
+ case SPROEA_DBAT1L: strcat(dest, "dbat1l"); break;
+ case SPROEA_DBAT2U: strcat(dest, "dbat2u"); break;
+ case SPROEA_DBAT2L: strcat(dest, "dbat2l"); break;
+ case SPROEA_DBAT3U: strcat(dest, "dbat3u"); break;
+ case SPROEA_DBAT3L: strcat(dest, "dbat3l"); break;
+ case SPROEA_DABR: strcat(dest, "dabr/iac2"); break; // unsupported on 603e/EC603e
+
+ /* PowerPC 603E SPR register indexes */
+ case SPR603_HID0: strcat(dest, "hid0/dbsr"); break;
+ case SPR603_HID1: strcat(dest, "hid1"); break;
+ case SPR603_DMISS: strcat(dest, "dmiss"); break;
+ case SPR603_DCMP: strcat(dest, "dcmp"); break;
+ case SPR603_HASH1: strcat(dest, "hash1"); break;
+ case SPR603_HASH2: strcat(dest, "hash2/icdbdr"); break;
+ case SPR603_IMISS: strcat(dest, "imiss"); break;
+ case SPR603_ICMP: strcat(dest, "icmp/dear"); break;
+ case SPR603_RPA: strcat(dest, "rpa/evpr"); break;
+ case SPR603_IABR: strcat(dest, "iabr/dbcr"); break;
+
+ /* PowerPC 4XX SPR register indexes */
+ case SPR4XX_SGR: strcat(dest, "sgr"); break;
+ case SPR4XX_DCWR: strcat(dest, "dcwr"); break;
+ case SPR4XX_PID: strcat(dest, "pid"); break;
+ case SPR4XX_TBHU: strcat(dest, "tbhu"); break;
+ case SPR4XX_TBLU: strcat(dest, "tblu"); break;
+// case SPR4XX_ICDBDR: strcat(dest, "icdbdr"); break; // same as SPR603E_HASH2
+// case SPR4XX_DEAR: strcat(dest, "dear"); break; // same as SPR603E_ICMP
+// case SPR4XX_EVPR: strcat(dest, "evpr"); break; // same as SPR603E_RPA
+ case SPR4XX_CDBCR: strcat(dest, "cdbcr"); break;
+ case SPR4XX_TSR: strcat(dest, "tsr"); break;
+ case SPR4XX_TCR: strcat(dest, "tcr"); break;
+ case SPR4XX_PIT: strcat(dest, "pit"); break;
+ case SPR4XX_TBHI: strcat(dest, "tbhi"); break;
+ case SPR4XX_TBLO: strcat(dest, "tblo"); break;
+ case SPR4XX_SRR2: strcat(dest, "srr2"); break;
+ case SPR4XX_SRR3: strcat(dest, "srr3"); break;
+// case SPR4XX_DBSR: strcat(dest, "dbsr"); break; // same as SPR603E_HID0
+// case SPR4XX_DBCR: strcat(dest, "dbcr"); break; // same as SPR603E_IABR
+ case SPR4XX_IAC1: strcat(dest, "iac1"); break;
+// case SPR4XX_IAC2: strcat(dest, "iac2"); break; // same as SPROEA_DABR
+ case SPR4XX_DAC1: strcat(dest, "dac1"); break;
+ case SPR4XX_DAC2: strcat(dest, "dac2"); break;
+ case SPR4XX_DCCR: strcat(dest, "dccr"); break;
+ case SPR4XX_ICCR: strcat(dest, "iccr"); break;
+ case SPR4XX_PBL1: strcat(dest, "pbl1"); break;
+ case SPR4XX_PBU1: strcat(dest, "pbu1"); break;
+ case SPR4XX_PBL2: strcat(dest, "pbl2"); break;
+ case SPR4XX_PBU2: strcat(dest, "pbu2"); break;
+
+ default: sprintf(dest + strlen(dest), "%d", spr); break;
+ }
+}
+
+static void DCR(char *dest, int dcr_field)
+{
+ int dcr;
+
+ /*
+ * Construct the DCR number -- DCR field is 2 5-bit fields
+ */
+
+ dcr = (dcr_field >> 5) & 0x1f;
+ dcr |= (dcr_field & 0x1f) << 5;
+
+ /*
+ * Append the DCR name to the destination string using strcat()
+ */
+
+ switch (dcr)
+ {
+ case 144: strcat(dest, "bear"); break;
+ case 145: strcat(dest, "besr"); break;
+ case 128: strcat(dest, "br0"); break;
+ case 129: strcat(dest, "br1"); break;
+ case 130: strcat(dest, "br2"); break;
+ case 131: strcat(dest, "br3"); break;
+ case 132: strcat(dest, "br4"); break;
+ case 133: strcat(dest, "br5"); break;
+ case 134: strcat(dest, "br6"); break;
+ case 135: strcat(dest, "br7"); break;
+ case 112: strcat(dest, "brh0"); break;
+ case 113: strcat(dest, "brh1"); break;
+ case 114: strcat(dest, "brh2"); break;
+ case 115: strcat(dest, "brh3"); break;
+ case 116: strcat(dest, "brh4"); break;
+ case 117: strcat(dest, "brh5"); break;
+ case 118: strcat(dest, "brh6"); break;
+ case 119: strcat(dest, "brh7"); break;
+ case 196: strcat(dest, "dmacc0"); break;
+ case 204: strcat(dest, "dmacc1"); break;
+ case 212: strcat(dest, "dmacc2"); break;
+ case 220: strcat(dest, "dmacc3"); break;
+ case 192: strcat(dest, "dmacr0"); break;
+ case 200: strcat(dest, "dmacr1"); break;
+ case 208: strcat(dest, "dmacr2"); break;
+ case 216: strcat(dest, "dmacr3"); break;
+ case 193: strcat(dest, "dmact0"); break;
+ case 201: strcat(dest, "dmact1"); break;
+ case 209: strcat(dest, "dmact2"); break;
+ case 217: strcat(dest, "dmact3"); break;
+ case 194: strcat(dest, "dmada0"); break;
+ case 202: strcat(dest, "dmada1"); break;
+ case 210: strcat(dest, "dmada2"); break;
+ case 218: strcat(dest, "dmada3"); break;
+ case 195: strcat(dest, "dmasa0"); break;
+ case 203: strcat(dest, "dmasa1"); break;
+ case 211: strcat(dest, "dmasa2"); break;
+ case 219: strcat(dest, "dmasa3"); break;
+ case 224: strcat(dest, "dmasr"); break;
+ case 66: strcat(dest, "exier"); break;
+ case 64: strcat(dest, "exisr"); break;
+ case 160: strcat(dest, "iocr"); break;
+
+ default: sprintf(dest + strlen(dest), "%d", dcr); break;
+ }
+}
+
+
+/*
+ * DecodeSigned16():
+ *
+ * Predecodes the SIMM field for us. If do_unsigned, it is printed as an
+ * unsigned 16-bit integer.
+ */
+
+static void DecodeSigned16(char *outbuf, UINT32 op, int do_unsigned)
+{
+ INT16 s;
+
+ s = G_SIMM(op);
+ if (do_unsigned) // sign extend to unsigned 32-bits
+ sprintf(outbuf, "0x%04X", (UINT32) s);
+ else // print as signed 16 bits
+ {
+ if (s < 0)
+ {
+ s *= -1;
+ sprintf(outbuf, "-0x%04X", s);
+ }
+ else
+ sprintf(outbuf, "0x%04X",s);
+ }
+}
+
+/*
+ * Mask():
+ *
+ * Generate a mask from bit MB through ME (PPC-style backwards bit numbering.)
+ */
+
+static UINT32 Mask(int mb, int me)
+{
+ UINT32 i, mask;
+
+ mb &= 31;
+ me &= 31;
+
+ i = mb;
+ mask = 0;
+ while (1)
+ {
+ mask |= (1 << (31 - i));
+ if (i == me)
+ break;
+ i = (i + 1) & 31;
+ }
+
+ return mask;
+}
+
+/*
+ * Check():
+ *
+ * Perform checks on the instruction as required by the flags. Returns 1 if
+ * the instruction failed.
+ */
+
+#if 0
+static int Check(UINT32 op, int flags)
+{
+ int nb, rt, ra;
+
+ if( !flags ) return 0; // nothing to check for!
+
+ rt = G_RT(op);
+ ra = G_RA(op);
+
+ if (flags & FL_CHECK_RA_RT) // invalid if rA==0 or rA==rT
+ {
+ if ((G_RA(op) == 0) || (G_RA(op) == G_RT(op)))
+ return 1;
+ }
+
+ if (flags & FL_CHECK_RA) // invalid if rA==0
+ {
+ if (G_RA(op) == 0)
+ return 1;
+ }
+
+ if (flags & FL_CHECK_LSWI)
+ {
+ /*
+ * Check that rA is not in the range of registers to be loaded (even
+ * if rA == 0)
+ */
+
+ nb = G_NB(op);
+
+ if (ra >= rt && ra <= (rt + nb - 1)) return 1;
+ if ((rt + nb - 1) > 31) // register wrap-around!
+ {
+ if (ra < ((rt + nb - 1) - 31))
+ return 1;
+ }
+ }
+
+ if (flags & FL_CHECK_LSWX)
+ {
+ /*
+ * Check that rT != rA, rT != rB, and rD and rA both do not specify
+ * R0.
+ *
+ * We cannot check fully whether rA or rB are in the range of
+ * registers specified to be loaded because that depends on XER.
+ */
+
+ if (rt == ra || rt == G_RB(op) || ((rt == 0) && (ra == 0)))
+ return 1;
+ }
+
+ return 0; // passed checks
+}
+#endif
+/*
+ * Simplified():
+ *
+ * Handles all simplified instruction forms. Returns 1 if one was decoded,
+ * otherwise 0 to indicate disassembly should carry on as normal.
+ */
+
+static int Simplified(UINT32 op, UINT32 vpc, char *signed16, char *mnem, char *oprs)
+{
+ UINT32 value, disp;
+
+ value = G_SIMM(op); // value is fully sign-extended SIMM field
+ if (value & 0x8000)
+ value |= 0xffff0000;
+
+ if (op == (D_OP(24)|D_RT(0)|D_RA(0)|D_UIMM(0)))
+ strcat(mnem, "nop"); // ori r0,r0,0 -> nop
+ else if ((op & ~(M_RT|M_RA|M_RB|M_RC)) == (D_OP(31)|D_XO(444)))
+ {
+ if (G_RT(op) == G_RB(op))
+ {
+ strcat(mnem, "mr"); // orx rA,rT,rT -> mrx rA,rT
+ if (op & M_RC) strcat(mnem, ".");
+ sprintf(oprs, "r%d,r%d", G_RA(op), G_RT(op));
+ }
+ else
+ return 0;
+ }
+ else if ((op & ~(M_RT|M_RA|M_RB|M_RC)) == (D_OP(31)|D_XO(124)))
+ {
+ if (G_RT(op) == G_RB(op))
+ {
+ strcat(mnem, "not"); // nor rA,rT,rT -> not rA,rT
+ if (op & M_RC) strcat(mnem, ".");
+ sprintf(oprs, "r%d,r%d", G_RA(op), G_RT(op));
+ }
+ else
+ return 0;
+ }
+ else if ((op & ~(M_RT|M_RA|M_SIMM)) == D_OP(14))
+ {
+ if (G_RA(op) == 0)
+ {
+ strcat(mnem, "li"); // addi rT,0,value -> li rT,value
+ sprintf(oprs, "r%d,0x%08X", G_RT(op), value);
+ }
+ else
+ return 0;
+ }
+ else if ((op & ~(M_RT|M_RA|M_SIMM)) == D_OP(15))
+ {
+ if (G_RA(op) == 0)
+ {
+ strcat(mnem, "li"); // addis rT,0,value -> li rT,(value<<16)
+ sprintf(oprs, "r%d,0x%08X", G_RT(op), value << 16);
+ }
+ else
+ {
+ strcat(mnem, "addi"); // addis rT,rA,SIMM -> addi rT,rA,SIMM<<16
+ sprintf(oprs, "r%d,r%d,0x%08X", G_RT(op), G_RA(op), value << 16);
+ }
+ }
+ else if ((op & ~(M_RT|M_RA|M_UIMM)) == D_OP(29))
+ {
+ strcat(mnem, "andi."); // andis. rA,rT,UIMM -> andi. rA,rT,UIMM<<16
+ sprintf(oprs, "r%d,r%d,0x%08X", G_RA(op), G_RT(op), G_UIMM(op) << 16);
+ }
+ else if ((op & ~(M_RT|M_RA|M_UIMM)) == D_OP(25))
+ {
+ strcat(mnem, "ori"); // oris rA,rT,UIMM -> ori rA,rT,UIMM<<16
+ sprintf(oprs, "r%d,r%d,0x%08X", G_RA(op), G_RT(op), G_UIMM(op) << 16);
+ }
+ else if ((op & ~(M_RT|M_RA|M_UIMM)) == D_OP(27))
+ {
+ strcat(mnem, "xori"); // xoris rA,rT,UIMM -> xori rA,rT,UIMM<<16
+ sprintf(oprs, "r%d,r%d,0x%08X", G_RA(op), G_RT(op), G_UIMM(op) << 16);
+ }
+ else if ((op & ~(M_RT|M_RA|M_SH|M_MB|M_ME|M_RC)) == D_OP(20))
+ {
+ value = Mask(G_MB(op), G_ME(op));
+ strcat(mnem, "rlwimi"); // rlwimi[.] rA,rT,SH,MB,ME -> rlwimi[.] rA,rT,SH,MASK
+ if (op & M_RC) strcat(mnem, ".");
+ sprintf(oprs, "r%d,r%d,%d,0x%08X", G_RA(op), G_RT(op), G_SH(op), value);
+ }
+ else if ((op & ~(M_RT|M_RA|M_SH|M_MB|M_ME|M_RC)) == D_OP(21))
+ {
+ value = Mask(G_MB(op), G_ME(op));
+ if (G_SH(op) == 0) // rlwinm[.] rA,rT,0,MB,ME -> and[.] rA,rT,MASK
+ {
+ strcat(mnem, "and");
+ if (op & M_RC) strcat(mnem, ".");
+ sprintf(oprs, "r%d,r%d,0x%08X", G_RA(op), G_RT(op), value);
+ }
+ else // rlwinm[.] rA,rT,SH,MASK
+ {
+ strcat(mnem, "rlwinm");
+ if (op & M_RC) strcat(mnem, ".");
+ sprintf(oprs, "r%d,r%d,%d,0x%08X", G_RA(op), G_RT(op), G_SH(op), value);
+ }
+ }
+ else if ((op & ~(M_RT|M_RA|M_RB|M_MB|M_ME|M_RC)) == D_OP(23))
+ {
+ value = Mask(G_MB(op), G_ME(op));
+ strcat(mnem, "rlwnm"); // rlwnm[.] rA,rT,SH,MB,ME -> rlwnm[.] rA,rT,SH,MASK
+ if (op & M_RC) strcat(mnem, ".");
+ sprintf(oprs, "r%d,r%d,r%d,0x%08X", G_RA(op), G_RT(op), G_RB(op), value);
+ }
+ else if ((op & ~(M_BO|M_BI|M_BD|M_AA|M_LK)) == D_OP(16))
+ {
+ disp = G_BD(op) * 4;
+ if (disp & 0x00008000)
+ disp |= 0xffff0000;
+
+ switch (G_BO(op))
+ {
+ case 0x04: case 0x05: case 0x06: case 0x07:
+ strcat(mnem, "b");
+ strcat(mnem, crnbit[G_BI(op) & 3]);
+ break;
+ case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ strcat(mnem, "b");
+ strcat(mnem, crbit[G_BI(op) & 3]);
+ break;
+ case 0x10: case 0x11: case 0x18: case 0x19:
+ strcat(mnem, "bdnz");
+ break;
+ case 0x12: case 0x13: case 0x1a: case 0x1b:
+ strcat(mnem, "bdz");
+ break;
+ case 0x14: case 0x15: case 0x16: case 0x17:
+ case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ strcat(mnem, "b");
+ break;
+ default:
+ return 0;
+ }
+
+ if (op & M_LK) strcat(mnem, "l");
+ if (op & M_AA) strcat(mnem, "a");
+
+ if (!(G_BO(op) & 0x10) && G_BI(op) / 4 != 0)
+ sprintf(oprs, "cr%d,0x%08X", G_BI(op) / 4, disp + ((op & M_AA) ? 0 : vpc));
+ else
+ sprintf(oprs, "0x%08X", disp + ((op & M_AA) ? 0 : vpc));
+ }
+ else if ((op & ~(M_BO|M_BI|M_LK)) == (D_OP(19)|D_XO(528)) || (op & ~(M_BO|M_BI|M_LK)) == (D_OP(19)|D_XO(16)))
+ {
+ switch (G_BO(op))
+ {
+ case 0x04: case 0x05: case 0x06: case 0x07:
+ strcat(mnem, "b");
+ strcat(mnem, crnbit[G_BI(op) & 3]);
+ break;
+ case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ strcat(mnem, "b");
+ strcat(mnem, crbit[G_BI(op) & 3]);
+ break;
+ case 0x10: case 0x11: case 0x18: case 0x19:
+ strcat(mnem, "bdnz");
+ break;
+ case 0x12: case 0x13: case 0x1a: case 0x1b:
+ strcat(mnem, "bdz");
+ break;
+ case 0x14: case 0x15: case 0x16: case 0x17:
+ case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ strcat(mnem, "b");
+ break;
+ default:
+ return 0;
+ }
+
+ strcat(mnem, (G_XO(op) == 528) ? "ctr" : "lr");
+ if (op & M_LK) strcat(mnem, "l");
+ if (op & M_AA) strcat(mnem, "a");
+
+ if (!(G_BO(op) & 0x10) && G_BI(op) / 4 != 0)
+ sprintf(oprs, "cr%d", G_BI(op) / 4);
+ }
+ else if ((op & ~(M_RT|M_RA|M_RB|M_OE|M_RC)) == (D_OP(31)|D_XO(40)))
+ {
+ strcat(mnem, "sub");
+ if (op & M_OE) strcat(mnem, "o");
+ if (op & M_RC) strcat(mnem, ".");
+ sprintf(oprs, "r%d,r%d,r%d", G_RT(op), G_RB(op), G_RA(op));
+ }
+ else if ((op & ~(M_RT|M_RA|M_RB|M_OE|M_RC)) == (D_OP(31)|D_XO(8)))
+ {
+ strcat(mnem, "subc");
+ if (op & M_OE) strcat(mnem, "o");
+ if (op & M_RC) strcat(mnem, ".");
+ sprintf(oprs, "r%d,r%d,r%d", G_RT(op), G_RB(op), G_RA(op));
+ }
+ else
+ return 0; // no match
+
+ return 1;
+}
+
+offs_t ppc_dasm_one(char *buffer, UINT32 pc, UINT32 op)
+{
+ char signed16[12];
+ UINT32 disp;
+ int i,j;
+ char mnem[200];
+ char oprs[200];
+ offs_t flags = DASMFLAG_SUPPORTED;
+
+ mnem[0] = '\0'; // so we can use strcat()
+ oprs[0] = '\0';
+
+ /*
+ * Decode signed 16-bit fields (SIMM and d) to spare us the work later
+ */
+
+ DecodeSigned16(signed16, op, 0);
+
+ /*
+ * Try simplified forms first, then real instructions
+ */
+
+ if( Simplified(op, pc, signed16, mnem, oprs) ) {
+ buffer += sprintf(buffer, "%s", mnem);
+ for( j = strlen(mnem); j < 10; j++ ) {
+ buffer += sprintf(buffer, " ");
+ }
+ buffer += sprintf(buffer, "%s", oprs);
+ return 4 | flags;
+ }
+
+ /*
+ * Search for the instruction in the list and print it if there's a match
+ */
+
+ for (i = 0; i < sizeof(itab) / sizeof(IDESCR); i++)
+ {
+ if ((op & ~itab[i].mask) == itab[i].match) // check for match
+ {
+ /*
+ * Base mnemonic followed be O, ., L, A
+ */
+
+ strcat(mnem, itab[i].mnem);
+ if (itab[i].flags & FL_OE) if (op & M_OE) strcat(mnem, "o");
+ if (itab[i].flags & FL_RC) if (op & M_RC) strcat(mnem, ".");
+ if (itab[i].flags & FL_LK) if (op & M_LK) strcat(mnem, "l");
+ if (itab[i].flags & FL_AA) if (op & M_AA) strcat(mnem, "a");
+
+ /*
+ * Print operands
+ */
+
+ switch (itab[i].format)
+ {
+ case F_RT_RA_RB:
+ sprintf(oprs, "r%d,r%d,r%d", G_RT(op), G_RA(op), G_RB(op));
+ break;
+
+ case F_RT_RA_0_SIMM:
+ if (G_RA(op))
+ sprintf(oprs, "r%d,r%d,%s", G_RT(op), G_RA(op), signed16);
+ else
+ sprintf(oprs, "r%d,0,%s", G_RT(op), signed16);
+ break;
+
+ case F_ADDIS:
+ if (G_RA(op))
+ sprintf(oprs, "r%d,r%d,0x%04X", G_RT(op), G_RA(op), G_SIMM(op));
+ else
+ sprintf(oprs, "r%d,0,0x%04X", G_RT(op), G_SIMM(op));
+ break;
+
+ case F_RT_RA_SIMM:
+ sprintf(oprs, "r%d,r%d,%s", G_RT(op), G_RA(op), signed16);
+ break;
+
+ case F_RT_RA:
+ sprintf(oprs, "r%d,r%d", G_RT(op), G_RA(op));
+ break;
+
+ case F_RA_RT_RB:
+ sprintf(oprs, "r%d,r%d,r%d", G_RA(op), G_RT(op), G_RB(op));
+ break;
+
+ case F_RA_RT_UIMM:
+ sprintf(oprs, "r%d,r%d,0x%04X", G_RA(op), G_RT(op), G_UIMM(op));
+ break;
+
+ case F_LI:
+ disp = G_LI(op) * 4;
+ if (disp & 0x02000000) // sign extend
+ disp |= 0xfc000000;
+ sprintf(oprs, "0x%08X", disp + ((op & M_AA) ? 0 : pc));
+ break;
+
+ case F_BCx:
+ disp = G_BD(op) * 4;
+ if (disp & 0x00008000)
+ disp |= 0xffff0000;
+
+ if (G_BO(op) & 0x10) // BI is ignored (don't print CR bit)
+ sprintf(oprs, "0x%02X,%d,0x%08X", G_BO(op), G_BI(op), disp + ((op & M_AA) ? 0 : pc));
+ else // BI gives us the condition bit
+ sprintf(oprs, "0x%02X,cr%d[%s],0x%08X", G_BO(op), G_BI(op) / 4, crbit[G_BI(op) & 3], disp + ((op & M_AA) ? 0 : pc));
+ break;
+
+ case F_BO_BI:
+ if (G_BO(op) & 0x10) // BI is ignored (don't print CR bit)
+ sprintf(oprs, "0x%02X,%d", G_BO(op), G_BI(op));
+ else
+ sprintf(oprs, "0x%02X,cr%d[%s]", G_BO(op), G_BI(op) / 4, crbit[G_BI(op) & 3]);
+ break;
+
+ case F_CMP:
+ if (G_L(op))
+ strcat(mnem, "d");
+ if (G_CRFD(op) == 0)
+ sprintf(oprs, "r%d,r%d", G_RA(op), G_RB(op));
+ else
+ sprintf(oprs, "cr%d,r%d,r%d", G_CRFD(op), G_RA(op), G_RB(op));
+ break;
+
+ case F_CMP_SIMM:
+ if (G_L(op))
+ strcat(mnem, "d");
+ if (G_CRFD(op) == 0)
+ sprintf(oprs, "r%d,%s", G_RA(op), signed16);
+ else
+ sprintf(oprs, "cr%d,r%d,%s", G_CRFD(op), G_RA(op), signed16);
+ break;
+
+ case F_CMP_UIMM:
+ if (G_L(op))
+ strcat(mnem, "d");
+ if (G_CRFD(op) == 0)
+ sprintf(oprs, "r%d,0x%04X", G_RA(op), G_UIMM(op));
+ else
+ sprintf(oprs, "cr%d,r%d,0x%04X", G_CRFD(op), G_RA(op), G_UIMM(op));
+ break;
+
+ case F_RA_RT:
+ sprintf(oprs, "r%d,r%d", G_RA(op), G_RT(op));
+ break;
+
+ case F_CRBD_CRBA_CRBB:
+ sprintf(oprs, "cr%d[%s],cr%d[%s],cr%d[%s]", G_CRBD(op) / 4, crbit[G_CRBD(op) & 3], G_CRBA(op) / 4, crbit[G_CRBA(op) & 3], G_CRBB(op) / 4, crbit[G_CRBB(op) & 3]);
+ break;
+
+ case F_RA_0_RB:
+ if (G_RA(op))
+ sprintf(oprs, "r%d,r%d", G_RA(op), G_RB(op));
+ else
+ sprintf(oprs, "0,r%d", G_RB(op));
+ break;
+
+ case F_RT_RA_0_RB:
+ if (G_RA(op))
+ sprintf(oprs, "r%d,r%d,r%d", G_RT(op), G_RA(op), G_RB(op));
+ else
+ sprintf(oprs, "r%d,0,r%d", G_RT(op), G_RB(op));
+ break;
+
+ case F_FRT_FRB:
+ sprintf(oprs, "f%d,f%d", G_RT(op), G_RB(op));
+ break;
+
+ case F_FRT_FRA_FRB:
+ sprintf(oprs, "f%d,f%d,f%d", G_RT(op), G_RA(op), G_RB(op));
+ break;
+
+ case F_FCMP:
+ sprintf(oprs, "cr%d,f%d,f%d", G_CRFD(op), G_RA(op), G_RB(op));
+ break;
+
+ case F_FRT_FRA_FRC_FRB:
+ sprintf(oprs, "f%d,f%d,f%d,f%d", G_RT(op), G_RA(op), G_REGC(op), G_RB(op));
+ break;
+
+ case F_FRT_FRA_FRC:
+ sprintf(oprs, "f%d,f%d,f%d", G_RT(op), G_RA(op), G_REGC(op));
+ break;
+
+ case F_RT_D_RA_0:
+ if (G_RA(op))
+ sprintf(oprs, "r%d,%s(r%d)", G_RT(op), signed16, G_RA(op));
+ else
+ sprintf(oprs, "r%d,0x%08X", G_RT(op), (UINT32) ((INT16) G_D(op)));
+ break;
+
+ case F_RT_D_RA:
+ sprintf(oprs, "r%d,%s(r%d)", G_RT(op), signed16, G_RA(op));
+ break;
+
+ case F_FRT_D_RA_0:
+ if (G_RA(op))
+ sprintf(oprs, "f%d,%s(r%d)", G_RT(op), signed16, G_RA(op));
+ else
+ sprintf(oprs, "f%d,0x%08X", G_RT(op), (UINT32) ((INT16) G_D(op)));
+ break;
+
+ case F_FRT_D_RA:
+ sprintf(oprs, "f%d,%s(r%d)", G_RT(op), signed16, G_RA(op));
+ break;
+
+ case F_FRT_RA_RB:
+ sprintf(oprs, "f%d,r%d,r%d", G_RT(op), G_RA(op), G_RB(op));
+ break;
+
+ case F_FRT_RA_0_RB:
+ if (G_RA(op))
+ sprintf(oprs, "f%d,r%d,r%d", G_RT(op), G_RA(op), G_RB(op));
+ else
+ sprintf(oprs, "f%d,0,r%d", G_RT(op), G_RB(op));
+ break;
+
+ case F_RT_RA_0_NB:
+ if (G_RA(op))
+ sprintf(oprs, "r%d,r%d,%d", G_RT(op), G_RA(op), G_NB(op) ? G_NB(op) : 32);
+ else
+ sprintf(oprs, "r%d,0,%d", G_RT(op), G_NB(op) ? G_NB(op) : 32);
+ break;
+
+ case F_CRFD_CRFS:
+ sprintf(oprs, "cr%d,cr%d", G_CRFD(op), G_CRFS(op));
+ break;
+
+ case F_MCRXR:
+ sprintf(oprs, "cr%d", G_CRFD(op));
+ break;
+
+ case F_RT:
+ sprintf(oprs, "r%d", G_RT(op));
+ break;
+
+ case F_MFFSx:
+ sprintf(oprs, "f%d", G_RT(op));
+ break;
+
+ case F_FCRBD:
+ sprintf(oprs, "fpscr[%d]", G_CRBD(op));
+ break;
+
+ case F_RT_SPR:
+ sprintf(oprs, "r%d,", G_RT(op));
+ SPR(oprs, G_SPR(op));
+ break;
+
+ case F_RT_DCR:
+ sprintf(oprs, "r%d,", G_RT(op));
+ DCR(oprs, G_DCR(op));
+ break;
+
+ case F_MFSR:
+ sprintf(oprs, "r%d,sr%d", G_RT(op), G_SR(op));
+ break;
+
+ case F_MTCRF:
+ sprintf(oprs, "0x%02X,r%d", G_CRM(op), G_RT(op));
+ break;
+
+ case F_MTFSFx:
+ sprintf(oprs, "0x%02X,f%d", G_FM(op), G_RB(op));
+ break;
+
+ case F_MTFSFIx:
+ sprintf(oprs, "cr%d,0x%X", G_CRFD(op), G_IMM(op));
+ break;
+
+ case F_MTSPR:
+ SPR(oprs, G_SPR(op));
+ sprintf(oprs + strlen(oprs), ",r%d", G_RT(op));
+ break;
+
+ case F_MTDCR:
+ DCR(oprs, G_DCR(op));
+ sprintf(oprs + strlen(oprs), ",r%d", G_RT(op));
+ break;
+
+ case F_MTSR:
+ sprintf(oprs, "sr%d,r%d", G_SR(op), G_RT(op));
+ break;
+
+ case F_RT_RB:
+ sprintf(oprs, "r%d,r%d", G_RT(op), G_RB(op));
+ break;
+
+ case F_RA_RT_SH_MB_ME:
+ sprintf(oprs, "r%d,r%d,%d,%d,%d", G_RA(op), G_RT(op), G_SH(op), G_MB(op), G_ME(op));
+ break;
+
+ case F_RLWNMx:
+ sprintf(oprs, "r%d,r%d,r%d,%d,%d", G_RA(op), G_RT(op), G_RB(op), G_MB(op), G_ME(op));
+ break;
+
+ case F_SRAWIx:
+ sprintf(oprs, "r%d,r%d,%d", G_RA(op), G_RT(op), G_SH(op));
+ break;
+
+ case F_RB:
+ sprintf(oprs, "r%d", G_RB(op));
+ break;
+
+ case F_TW:
+ sprintf(oprs, "%d,r%d,r%d", G_TO(op), G_RA(op), G_RB(op));
+ break;
+
+ case F_TWI:
+ sprintf(oprs, "%d,r%d,%s", G_TO(op), G_RA(op), signed16);
+ break;
+
+ case F_NONE:
+ default:
+ break;
+ }
+
+ if ((itab[i].flags & FL_LK) && (op & M_LK))
+ flags |= DASMFLAG_STEP_OVER;
+ else if (itab[i].flags & FL_SO)
+ flags |= DASMFLAG_STEP_OUT;
+
+ buffer += sprintf(buffer, "%s", mnem);
+ for( j = strlen(mnem); j < 10; j++ ) {
+ buffer += sprintf(buffer, " ");
+ }
+ buffer += sprintf(buffer, "%s", oprs);
+ return 4 | flags;
+ }
+ }
+
+ sprintf(buffer, "?");
+ return 4 | flags;
+}
+
+CPU_DISASSEMBLE( powerpc )
+{
+ UINT32 op = *(UINT32 *)oprom;
+ op = BIG_ENDIANIZE_INT32(op);
+ return ppc_dasm_one(buffer, pc, op);
+}
diff --git a/trunk/src/emu/cpu/powerpc/ppc_mem.c b/trunk/src/emu/cpu/powerpc/ppc_mem.c
new file mode 100644
index 00000000000..38c76a6bba2
--- /dev/null
+++ b/trunk/src/emu/cpu/powerpc/ppc_mem.c
@@ -0,0 +1,419 @@
+#define DUMP_PAGEFAULTS 0
+
+INLINE UINT8 READ8(UINT32 a)
+{
+ return ppc.read8(ppc.program, a);
+}
+
+INLINE UINT16 READ16(UINT32 a)
+{
+ if( a & 0x1 )
+ return ppc.read16_unaligned(ppc.program, a);
+ else
+ return ppc.read16(ppc.program, a);
+}
+
+INLINE UINT32 READ32(UINT32 a)
+{
+ if( a & 0x3 )
+ return ppc.read32_unaligned(ppc.program, a);
+ else
+ return ppc.read32(ppc.program, a);
+}
+
+INLINE UINT64 READ64(UINT32 a)
+{
+ if( a & 0x7 )
+ return ppc.read64_unaligned(ppc.program, a);
+ else
+ return ppc.read64(ppc.program, a);
+}
+
+INLINE void WRITE8(UINT32 a, UINT8 d)
+{
+ ppc.write8(ppc.program, a, d);
+}
+
+INLINE void WRITE16(UINT32 a, UINT16 d)
+{
+ if( a & 0x1 )
+ ppc.write16_unaligned(ppc.program, a, d);
+ else
+ ppc.write16(ppc.program, a, d);
+}
+
+INLINE void WRITE32(UINT32 a, UINT32 d)
+{
+ if( ppc.reserved ) {
+ if( a == ppc.reserved_address ) {
+ ppc.reserved = 0;
+ }
+ }
+
+ if( a & 0x3 )
+ ppc.write32_unaligned(ppc.program, a, d);
+ else
+ ppc.write32(ppc.program, a, d);
+}
+
+INLINE void WRITE64(UINT32 a, UINT64 d)
+{
+ if( a & 0x7 )
+ ppc.write64_unaligned(ppc.program, a, d);
+ else
+ ppc.write64(ppc.program, a, d);
+}
+
+/***********************************************************************/
+
+static UINT16 ppc_read16_unaligned(address_space *space, UINT32 a)
+{
+ return ((UINT16)ppc.read8(space, a+0) << 8) | ((UINT16)ppc.read8(space, a+1) << 0);
+}
+
+static UINT32 ppc_read32_unaligned(address_space *space, UINT32 a)
+{
+ return ((UINT32)ppc.read8(space, a+0) << 24) | ((UINT32)ppc.read8(space, a+1) << 16) |
+ ((UINT32)ppc.read8(space, a+2) << 8) | ((UINT32)ppc.read8(space, a+3) << 0);
+}
+
+static UINT64 ppc_read64_unaligned(address_space *space, UINT32 a)
+{
+ return ((UINT64)READ32(space, a+0) << 32) | (UINT64)(READ32(space, a+4));
+}
+
+static void ppc_write16_unaligned(address_space *space, UINT32 a, UINT16 d)
+{
+ ppc.write8(space, a+0, (UINT8)(d >> 8));
+ ppc.write8(space, a+1, (UINT8)(d));
+}
+
+static void ppc_write32_unaligned(address_space *space, UINT32 a, UINT32 d)
+{
+ ppc.write8(space, a+0, (UINT8)(d >> 24));
+ ppc.write8(space, a+1, (UINT8)(d >> 16));
+ ppc.write8(space, a+2, (UINT8)(d >> 8));
+ ppc.write8(space, a+3, (UINT8)(d >> 0));
+}
+
+static void ppc_write64_unaligned(address_space *space, UINT32 a, UINT64 d)
+{
+ ppc.write32(space, a+0, (UINT32)(d >> 32));
+ ppc.write32(space, a+4, (UINT32)(d));
+}
+
+/***********************************************************************/
+
+#define DSISR_PAGE 0x40000000
+#define DSISR_PROT 0x08000000
+#define DSISR_STORE 0x02000000
+
+enum
+{
+ PPC_TRANSLATE_DATA = 0x0000,
+ PPC_TRANSLATE_CODE = 0x0001,
+
+ PPC_TRANSLATE_READ = 0x0000,
+ PPC_TRANSLATE_WRITE = 0x0002,
+
+ PPC_TRANSLATE_NOEXCEPTION = 0x0004
+};
+
+static int ppc_is_protected(UINT32 pp, int flags)
+{
+ if (flags & PPC_TRANSLATE_WRITE)
+ {
+ if ((pp & 0x00000003) != 0x00000002)
+ return TRUE;
+ }
+ else
+ {
+ if ((pp & 0x00000003) == 0x00000000)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static int ppc_translate_address(offs_t *addr_ptr, int flags)
+{
+ const BATENT *bat;
+ UINT32 address;
+ UINT32 sr, vsid, hash;
+ UINT32 pteg_address;
+ UINT32 target_pte, bl, mask;
+ UINT64 pte;
+ UINT64 *pteg_ptr[2];
+ int i, hash_type;
+ UINT32 dsisr = DSISR_PROT;
+
+ bat = (flags & PPC_TRANSLATE_CODE) ? ppc.ibat : ppc.dbat;
+
+ address = *addr_ptr;
+
+ /* first check the block address translation table */
+ for (i = 0; i < 4; i++)
+ {
+ if (bat[i].u & ((MSR & MSR_PR) ? 0x00000001 : 0x00000002))
+ {
+ bl = bat[i].u & 0x00001FFC;
+ mask = (~bl << 15) & 0xFFFE0000;
+
+ if ((address & mask) == (bat[i].u & 0xFFFE0000))
+ {
+ if (ppc_is_protected(bat[i].l, flags))
+ goto exception;
+
+ *addr_ptr = (bat[i].l & 0xFFFE0000)
+ | (address & ((bl << 15) | 0x0001FFFF));
+ return 1;
+ }
+ }
+ }
+
+ /* now try page address translation */
+ sr = ppc.sr[(address >> 28) & 0x0F];
+ if (sr & 0x80000000)
+ {
+ /* direct store translation */
+ if ((flags & PPC_TRANSLATE_NOEXCEPTION) == 0)
+ fatalerror("ppc: direct store translation not yet implemented");
+ return 0;
+ }
+ else
+ {
+ /* is no execute is set? */
+ if ((flags & PPC_TRANSLATE_CODE) && (sr & 0x10000000))
+ goto exception;
+
+ vsid = sr & 0x00FFFFFF;
+ hash = (vsid & 0x0007FFFF) ^ ((address >> 12) & 0xFFFF);
+ target_pte = (vsid << 7) | ((address >> 22) & 0x3F) | 0x80000000;
+
+ /* we have to try both types of hashes */
+ for (hash_type = 0; hash_type <= 1; hash_type++)
+ {
+ pteg_address = (ppc.sdr1 & 0xFFFF0000)
+ | (((ppc.sdr1 & 0x01FF) & (hash >> 10)) << 16)
+ | ((hash & 0x03FF) << 6);
+
+ pteg_ptr[hash_type] = ppc->program->get_read_ptr(pteg_address);
+ if (pteg_ptr[hash_type])
+ {
+ for (i = 0; i < 8; i++)
+ {
+ pte = pteg_ptr[hash_type][i];
+
+ /* is valid? */
+ if (((pte >> 32) & 0xFFFFFFFF) == target_pte)
+ {
+ if (ppc_is_protected((UINT32) pte, flags))
+ goto exception;
+
+ *addr_ptr = ((UINT32) (pte & 0xFFFFF000))
+ | (address & 0x0FFF);
+ return 1;
+ }
+ }
+ }
+
+ hash ^= 0x7FFFF;
+ target_pte ^= 0x40;
+ }
+
+ if (DUMP_PAGEFAULTS)
+ {
+ mame_printf_debug("PAGE FAULT: address=%08X PC=%08X SDR1=%08X MSR=%08X\n", address, ppc.pc, ppc.sdr1, ppc.msr);
+ mame_printf_debug("\n");
+
+ for (i = 0; i < 4; i++)
+ {
+ bl = bat[i].u & 0x00001FFC;
+ mask = (~bl << 15) & 0xFFFE0000;
+ mame_printf_debug(" BAT[%d]=%08X%08X (A & %08X = %08X)\n", i, bat[i].u, bat[i].l,
+ mask, bat[i].u & 0xFFFE0000);
+ }
+ mame_printf_debug("\n");
+ mame_printf_debug(" VSID=%06X HASH=%05X HASH\'=%05X\n", vsid, hash, hash ^ 0x7FFFF);
+
+ for (hash_type = 0; hash_type <= 1; hash_type++)
+ {
+ if (pteg_ptr[hash_type])
+ {
+ for (i = 0; i < 8; i++)
+ {
+ pte = pteg_ptr[hash_type][i];
+ mame_printf_debug(" PTE[%i%c]=%08X%08X\n",
+ i,
+ hash_type ? '\'' : ' ',
+ (unsigned) (pte >> 32),
+ (unsigned) (pte >> 0));
+ }
+ }
+ }
+ }
+ }
+
+ dsisr = DSISR_PAGE;
+
+exception:
+ /* lookup failure - exception */
+ if ((flags & PPC_TRANSLATE_NOEXCEPTION) == 0)
+ {
+ if (flags & PPC_TRANSLATE_CODE)
+ {
+ ppc_exception(EXCEPTION_ISI);
+ }
+ else
+ {
+ ppc.dar = address;
+ if (flags & PPC_TRANSLATE_WRITE)
+ ppc.dsisr = dsisr | DSISR_STORE;
+ else
+ ppc.dsisr = dsisr;
+
+ ppc_exception(EXCEPTION_DSI);
+ }
+ }
+ return 0;
+}
+
+static int ppc_translate_address_cb(address_spacenum space, offs_t *addr)
+{
+ int success = 1;
+
+ if (space == AS_PROGRAM)
+ {
+ if (MSR & MSR_DR)
+ success = ppc_translate_address(addr, PPC_TRANSLATE_CODE | PPC_TRANSLATE_READ | PPC_TRANSLATE_NOEXCEPTION);
+ }
+ return success;
+}
+
+static UINT8 ppc_read8_translated(address_space *space, offs_t address)
+{
+ ppc_translate_address(&address, PPC_TRANSLATE_DATA | PPC_TRANSLATE_READ);
+ return space->read_byte(address);
+}
+
+static UINT16 ppc_read16_translated(address_space *space, offs_t address)
+{
+ ppc_translate_address(&address, PPC_TRANSLATE_DATA | PPC_TRANSLATE_READ);
+ return space->read_word(address);
+}
+
+static UINT32 ppc_read32_translated(address_space *space, offs_t address)
+{
+ ppc_translate_address(&address, PPC_TRANSLATE_DATA | PPC_TRANSLATE_READ);
+ return space->read_dword(address);
+}
+
+static UINT64 ppc_read64_translated(address_space *space, offs_t address)
+{
+ ppc_translate_address(&address, PPC_TRANSLATE_DATA | PPC_TRANSLATE_READ);
+ return space->read_qword(address);
+}
+
+static void ppc_write8_translated(address_space *space, offs_t address, UINT8 data)
+{
+ ppc_translate_address(&address, PPC_TRANSLATE_DATA | PPC_TRANSLATE_WRITE);
+ space->write_byte(address, data);
+}
+
+static void ppc_write16_translated(address_space *space, offs_t address, UINT16 data)
+{
+ ppc_translate_address(&address, PPC_TRANSLATE_DATA | PPC_TRANSLATE_WRITE);
+ space->write_word(address, data);
+}
+
+static void ppc_write32_translated(address_space *space, offs_t address, UINT32 data)
+{
+ ppc_translate_address(&address, PPC_TRANSLATE_DATA | PPC_TRANSLATE_WRITE);
+ space->write_dword(address, data);
+}
+
+static void ppc_write64_translated(address_space *space, offs_t address, UINT64 data)
+{
+ ppc_translate_address(&address, PPC_TRANSLATE_DATA | PPC_TRANSLATE_WRITE);
+ space->write_qword(address, data);
+}
+
+#ifndef PPC_DRC
+static UINT32 ppc_readop_translated(address_space *space, offs_t address)
+{
+ ppc_translate_address(&address, PPC_TRANSLATE_CODE | PPC_TRANSLATE_READ);
+ return space->read_dword(address);
+}
+#endif
+
+/***********************************************************************/
+
+
+static CPU_DISASSEMBLE( ppc )
+{
+ UINT32 op;
+ op = BIG_ENDIANIZE_INT32(*((UINT32 *) oprom));
+ return ppc_dasm_one(buffer, pc, op);
+}
+
+/***********************************************************************/
+
+static CPU_READOP( ppc )
+{
+ if (!(ppc.msr & MSR_IR))
+ return 0;
+
+ *value = 0;
+
+ if (ppc_translate_address(&offset, PPC_TRANSLATE_CODE | PPC_TRANSLATE_READ | PPC_TRANSLATE_NOEXCEPTION))
+ {
+ switch(size)
+ {
+ case 1: *value = ppc.program->read_byte(offset); break;
+ case 2: *value = ppc.program->read_word(offset); break;
+ case 4: *value = ppc.program->read_dword(offset); break;
+ case 8: *value = ppc.program->read_qword(offset); break;
+ }
+ }
+
+ return 1;
+}
+
+static CPU_READ( ppc )
+{
+ if (!(ppc.msr & MSR_DR))
+ return 0;
+
+ *value = 0;
+
+ if (ppc_translate_address(&offset, PPC_TRANSLATE_DATA | PPC_TRANSLATE_READ | PPC_TRANSLATE_NOEXCEPTION))
+ {
+ switch(size)
+ {
+ case 1: *value = ppc.program->read_byte(offset); break;
+ case 2: *value = ppc.program->read_word(offset); break;
+ case 4: *value = ppc.program->read_dword(offset); break;
+ case 8: *value = ppc.program->read_qword(offset); break;
+ }
+ }
+
+ return 1;
+}
+
+static CPU_WRITE( ppc )
+{
+ if (!(ppc.msr & MSR_DR))
+ return 0;
+
+ if (ppc_translate_address(&offset, PPC_TRANSLATE_DATA | PPC_TRANSLATE_WRITE | PPC_TRANSLATE_NOEXCEPTION))
+ {
+ switch(size)
+ {
+ case 1: ppc.program->write_byte(offset, value); break;
+ case 2: ppc.program->write_word(offset, value); break;
+ case 4: ppc.program->write_dword(offset, value); break;
+ case 8: ppc.program->write_qword(offset, value); break;
+ }
+ }
+
+ return 1;
+}
diff --git a/trunk/src/emu/cpu/powerpc/ppc_ops.c b/trunk/src/emu/cpu/powerpc/ppc_ops.c
new file mode 100644
index 00000000000..287517fff77
--- /dev/null
+++ b/trunk/src/emu/cpu/powerpc/ppc_ops.c
@@ -0,0 +1,2818 @@
+/* PowerPC common opcodes */
+
+// it really seems like this should be elsewhere - like maybe the floating point checks can hang out someplace else
+#include <math.h>
+
+#ifndef PPC_DRC
+static void ppc_unimplemented(UINT32 op)
+{
+ fatalerror("ppc: Unimplemented opcode %08X at %08X", op, ppc.pc);
+}
+
+static void ppc_addx(UINT32 op)
+{
+ UINT32 ra = REG(RA);
+ UINT32 rb = REG(RB);
+
+ REG(RT) = ra + rb;
+
+ if( OEBIT ) {
+ SET_ADD_OV(REG(RT), ra, rb);
+ }
+ if( RCBIT ) {
+ SET_CR0(REG(RT));
+ }
+}
+
+static void ppc_addcx(UINT32 op)
+{
+ UINT32 ra = REG(RA);
+ UINT32 rb = REG(RB);
+
+ REG(RT) = ra + rb;
+
+ SET_ADD_CA(REG(RT), ra, rb);
+
+ if( OEBIT ) {
+ SET_ADD_OV(REG(RT), ra, rb);
+ }
+ if( RCBIT ) {
+ SET_CR0(REG(RT));
+ }
+}
+#endif
+
+static void ppc_addex(UINT32 op)
+{
+ UINT32 ra = REG(RA);
+ UINT32 rb = REG(RB);
+ UINT32 carry = (XER >> 29) & 0x1;
+ UINT32 tmp;
+
+ tmp = rb + carry;
+ REG(RT) = ra + tmp;
+
+ if( ADD_CA(tmp, rb, carry) || ADD_CA(REG(RT), ra, tmp) )
+ XER |= XER_CA;
+ else
+ XER &= ~XER_CA;
+
+ if( OEBIT ) {
+ SET_ADD_OV(REG(RT), ra, rb);
+ }
+ if( RCBIT ) {
+ SET_CR0(REG(RT));
+ }
+}
+
+#ifndef PPC_DRC
+static void ppc_addi(UINT32 op)
+{
+ UINT32 i = SIMM16;
+ UINT32 a = RA;
+
+ if( a )
+ i += REG(a);
+
+ REG(RT) = i;
+}
+
+static void ppc_addic(UINT32 op)
+{
+ UINT32 i = SIMM16;
+ UINT32 ra = REG(RA);
+
+ REG(RT) = ra + i;
+
+ if( ADD_CA(REG(RT), ra, i) )
+ XER |= XER_CA;
+ else
+ XER &= ~XER_CA;
+}
+
+static void ppc_addic_rc(UINT32 op)
+{
+ UINT32 i = SIMM16;
+ UINT32 ra = REG(RA);
+
+ REG(RT) = ra + i;
+
+ if( ADD_CA(REG(RT), ra, i) )
+ XER |= XER_CA;
+ else
+ XER &= ~XER_CA;
+
+ SET_CR0(REG(RT));
+}
+
+static void ppc_addis(UINT32 op)
+{
+ UINT32 i = UIMM16 << 16;
+ UINT32 a = RA;
+
+ if( a )
+ i += REG(a);
+
+ REG(RT) = i;
+}
+#endif
+
+static void ppc_addmex(UINT32 op)
+{
+ UINT32 ra = REG(RA);
+ UINT32 carry = (XER >> 29) & 0x1;
+ UINT32 tmp;
+
+ tmp = ra + carry;
+ REG(RT) = tmp + -1;
+
+ if( ADD_CA(tmp, ra, carry) || ADD_CA(REG(RT), tmp, -1) )
+ XER |= XER_CA;
+ else
+ XER &= ~XER_CA;
+
+ if( OEBIT ) {
+ SET_ADD_OV(REG(RT), ra, carry - 1);
+ }
+ if( RCBIT ) {
+ SET_CR0(REG(RT));
+ }
+}
+
+static void ppc_addzex(UINT32 op)
+{
+ UINT32 ra = REG(RA);
+ UINT32 carry = (XER >> 29) & 0x1;
+
+ REG(RT) = ra + carry;
+
+ if( ADD_CA(REG(RT), ra, carry) )
+ XER |= XER_CA;
+ else
+ XER &= ~XER_CA;
+
+ if( OEBIT ) {
+ SET_ADD_OV(REG(RT), ra, carry);
+ }
+ if( RCBIT ) {
+ SET_CR0(REG(RT));
+ }
+}
+
+#ifndef PPC_DRC
+static void ppc_andx(UINT32 op)
+{
+ REG(RA) = REG(RS) & REG(RB);
+
+ if( RCBIT ) {
+ SET_CR0(REG(RA));
+ }
+}
+
+static void ppc_andcx(UINT32 op)
+{
+ REG(RA) = REG(RS) & ~REG(RB);
+
+ if( RCBIT ) {
+ SET_CR0(REG(RA));
+ }
+}
+
+static void ppc_andi_rc(UINT32 op)
+{
+ UINT32 i = UIMM16;
+
+ REG(RA) = REG(RS) & i;
+
+ SET_CR0(REG(RA));
+}
+
+static void ppc_andis_rc(UINT32 op)
+{
+ UINT32 i = UIMM16 << 16;
+
+ REG(RA) = REG(RS) & i;
+
+ SET_CR0(REG(RA));
+}
+
+static void ppc_bx(UINT32 op)
+{
+ INT32 li = op & 0x3fffffc;
+ if( li & 0x2000000 )
+ li |= 0xfc000000;
+
+ if( AABIT ) {
+ ppc.npc = li;
+ } else {
+ ppc.npc = ppc.pc + li;
+ }
+
+ if( LKBIT ) {
+ LR = ppc.pc + 4;
+ }
+}
+
+static void ppc_bcx(UINT32 op)
+{
+ int condition = check_condition_code(BO, BI);
+
+ if( condition ) {
+ if( AABIT ) {
+ ppc.npc = SIMM16 & ~0x3;
+ } else {
+ ppc.npc = ppc.pc + (SIMM16 & ~0x3);
+ }
+ }
+
+ if( LKBIT ) {
+ LR = ppc.pc + 4;
+ }
+}
+
+static void ppc_bcctrx(UINT32 op)
+{
+ int condition = check_condition_code(BO, BI);
+
+ if( condition ) {
+ ppc.npc = CTR & ~0x3;
+ }
+
+ if( LKBIT ) {
+ LR = ppc.pc + 4;
+ }
+}
+
+static void ppc_bclrx(UINT32 op)
+{
+ int condition = check_condition_code(BO, BI);
+
+ if( condition ) {
+ ppc.npc = LR & ~0x3;
+ }
+
+ if( LKBIT ) {
+ LR = ppc.pc + 4;
+ }
+}
+
+static void ppc_cmp(UINT32 op)
+{
+ INT32 ra = REG(RA);
+ INT32 rb = REG(RB);
+ int d = CRFD;
+
+ if( ra < rb )
+ CR(d) = 0x8;
+ else if( ra > rb )
+ CR(d) = 0x4;
+ else
+ CR(d) = 0x2;
+
+ if( XER & XER_SO )
+ CR(d) |= 0x1;
+}
+
+static void ppc_cmpi(UINT32 op)
+{
+ INT32 ra = REG(RA);
+ INT32 i = SIMM16;
+ int d = CRFD;
+
+ if( ra < i )
+ CR(d) = 0x8;
+ else if( ra > i )
+ CR(d) = 0x4;
+ else
+ CR(d) = 0x2;
+
+ if( XER & XER_SO )
+ CR(d) |= 0x1;
+}
+
+static void ppc_cmpl(UINT32 op)
+{
+ UINT32 ra = REG(RA);
+ UINT32 rb = REG(RB);
+ int d = CRFD;
+
+ if( ra < rb )
+ CR(d) = 0x8;
+ else if( ra > rb )
+ CR(d) = 0x4;
+ else
+ CR(d) = 0x2;
+
+ if( XER & XER_SO )
+ CR(d) |= 0x1;
+}
+
+static void ppc_cmpli(UINT32 op)
+{
+ UINT32 ra = REG(RA);
+ UINT32 i = UIMM16;
+ int d = CRFD;
+
+ if( ra < i )
+ CR(d) = 0x8;
+ else if( ra > i )
+ CR(d) = 0x4;
+ else
+ CR(d) = 0x2;
+
+ if( XER & XER_SO )
+ CR(d) |= 0x1;
+}
+
+static void ppc_cntlzw(UINT32 op)
+{
+ int n = 0;
+ int t = RT;
+ UINT32 m = 0x80000000;
+
+ while(n < 32)
+ {
+ if( REG(t) & m )
+ break;
+ m >>= 1;
+ n++;
+ }
+
+ REG(RA) = n;
+
+ if( RCBIT ) {
+ SET_CR0(REG(RA));
+ }
+}
+#endif
+
+static void ppc_crand(UINT32 op)
+{
+ int bit = RT;
+ int b = CRBIT(RA) & CRBIT(RB);
+ if( b & 0x1 )
+ CR(bit / 4) |= _BIT(3-(bit % 4));
+ else
+ CR(bit / 4) &= ~_BIT(3-(bit % 4));
+}
+
+static void ppc_crandc(UINT32 op)
+{
+ int bit = RT;
+ int b = CRBIT(RA) & ~CRBIT(RB);
+ if( b & 0x1 )
+ CR(bit / 4) |= _BIT(3-(bit % 4));
+ else
+ CR(bit / 4) &= ~_BIT(3-(bit % 4));
+}
+
+static void ppc_creqv(UINT32 op)
+{
+ int bit = RT;
+ int b = ~(CRBIT(RA) ^ CRBIT(RB));
+ if( b & 0x1 )
+ CR(bit / 4) |= _BIT(3-(bit % 4));
+ else
+ CR(bit / 4) &= ~_BIT(3-(bit % 4));
+}
+
+static void ppc_crnand(UINT32 op)
+{
+ int bit = RT;
+ int b = ~(CRBIT(RA) & CRBIT(RB));
+ if( b & 0x1 )
+ CR(bit / 4) |= _BIT(3-(bit % 4));
+ else
+ CR(bit / 4) &= ~_BIT(3-(bit % 4));
+}
+
+static void ppc_crnor(UINT32 op)
+{
+ int bit = RT;
+ int b = ~(CRBIT(RA) | CRBIT(RB));
+ if( b & 0x1 )
+ CR(bit / 4) |= _BIT(3-(bit % 4));
+ else
+ CR(bit / 4) &= ~_BIT(3-(bit % 4));
+}
+
+static void ppc_cror(UINT32 op)
+{
+ int bit = RT;
+ int b = CRBIT(RA) | CRBIT(RB);
+ if( b & 0x1 )
+ CR(bit / 4) |= _BIT(3-(bit % 4));
+ else
+ CR(bit / 4) &= ~_BIT(3-(bit % 4));
+}
+
+static void ppc_crorc(UINT32 op)
+{
+ int bit = RT;
+ int b = CRBIT(RA) | ~CRBIT(RB);
+ if( b & 0x1 )
+ CR(bit / 4) |= _BIT(3-(bit % 4));
+ else
+ CR(bit / 4) &= ~_BIT(3-(bit % 4));
+}
+
+static void ppc_crxor(UINT32 op)
+{
+ int bit = RT;
+ int b = CRBIT(RA) ^ CRBIT(RB);
+ if( b & 0x1 )
+ CR(bit / 4) |= _BIT(3-(bit % 4));
+ else
+ CR(bit / 4) &= ~_BIT(3-(bit % 4));
+}
+
+#ifndef PPC_DRC
+static void ppc_dcbf(UINT32 op)
+{
+
+}
+
+static void ppc_dcbi(UINT32 op)
+{
+
+}
+
+static void ppc_dcbst(UINT32 op)
+{
+
+}
+
+static void ppc_dcbt(UINT32 op)
+{
+
+}
+
+static void ppc_dcbtst(UINT32 op)
+{
+
+}
+
+static void ppc_dcbz(UINT32 op)
+{
+
+}
+#endif
+
+static void ppc_divwx(UINT32 op)
+{
+ if( REG(RB) == 0 && REG(RA) < 0x80000000 )
+ {
+ REG(RT) = 0;
+ if( OEBIT ) {
+ XER |= XER_SO | XER_OV;
+ }
+ }
+ else if( REG(RB) == 0 || (REG(RB) == 0xffffffff && REG(RA) == 0x80000000) )
+ {
+ REG(RT) = 0xffffffff;
+ if( OEBIT ) {
+ XER |= XER_SO | XER_OV;
+ }
+ }
+ else
+ {
+ REG(RT) = (INT32)REG(RA) / (INT32)REG(RB);
+ if( OEBIT ) {
+ XER &= ~XER_OV;
+ }
+ }
+
+ if( RCBIT ) {
+ SET_CR0(REG(RT));
+ }
+}
+
+static void ppc_divwux(UINT32 op)
+{
+ if( REG(RB) == 0 )
+ {
+ REG(RT) = 0;
+ if( OEBIT ) {
+ XER |= XER_SO | XER_OV;
+ }
+ }
+ else
+ {
+ REG(RT) = (UINT32)REG(RA) / (UINT32)REG(RB);
+ if( OEBIT ) {
+ XER &= ~XER_OV;
+ }
+ }
+
+ if( RCBIT ) {
+ SET_CR0(REG(RT));
+ }
+}
+
+#ifndef PPC_DRC
+static void ppc_eieio(UINT32 op)
+{
+
+}
+
+static void ppc_eqvx(UINT32 op)
+{
+ REG(RA) = ~(REG(RS) ^ REG(RB));
+
+ if( RCBIT ) {
+ SET_CR0(REG(RA));
+ }
+}
+
+static void ppc_extsbx(UINT32 op)
+{
+ REG(RA) = (INT32)(INT8)REG(RS);
+
+ if( RCBIT ) {
+ SET_CR0(REG(RA));
+ }
+}
+
+static void ppc_extshx(UINT32 op)
+{
+ REG(RA) = (INT32)(INT16)REG(RS);
+
+ if( RCBIT ) {
+ SET_CR0(REG(RA));
+ }
+}
+
+static void ppc_icbi(UINT32 op)
+{
+
+}
+
+static void ppc_isync(UINT32 op)
+{
+
+}
+
+static void ppc_lbz(UINT32 op)
+{
+ UINT32 ea;
+
+ if( RA == 0 )
+ ea = SIMM16;
+ else
+ ea = REG(RA) + SIMM16;
+
+ REG(RT) = (UINT32)READ8(ea);
+}
+
+static void ppc_lbzu(UINT32 op)
+{
+ UINT32 ea = REG(RA) + SIMM16;
+
+ REG(RT) = (UINT32)READ8(ea);
+ REG(RA) = ea;
+}
+
+static void ppc_lbzux(UINT32 op)
+{
+ UINT32 ea = REG(RA) + REG(RB);
+
+ REG(RT) = (UINT32)READ8(ea);
+ REG(RA) = ea;
+}
+
+static void ppc_lbzx(UINT32 op)
+{
+ UINT32 ea;
+
+ if( RA == 0 )
+ ea = REG(RB);
+ else
+ ea = REG(RA) + REG(RB);
+
+ REG(RT) = (UINT32)READ8(ea);
+}
+
+static void ppc_lha(UINT32 op)
+{
+ UINT32 ea;
+
+ if( RA == 0 )
+ ea = SIMM16;
+ else
+ ea = REG(RA) + SIMM16;
+
+ REG(RT) = (INT32)(INT16)READ16(ea);
+}
+
+static void ppc_lhau(UINT32 op)
+{
+ UINT32 ea = REG(RA) + SIMM16;
+
+ REG(RT) = (INT32)(INT16)READ16(ea);
+ REG(RA) = ea;
+}
+
+static void ppc_lhaux(UINT32 op)
+{
+ UINT32 ea = REG(RA) + REG(RB);
+
+ REG(RT) = (INT32)(INT16)READ16(ea);
+ REG(RA) = ea;
+}
+
+static void ppc_lhax(UINT32 op)
+{
+ UINT32 ea;
+
+ if( RA == 0 )
+ ea = REG(RB);
+ else
+ ea = REG(RA) + REG(RB);
+
+ REG(RT) = (INT32)(INT16)READ16(ea);
+}
+
+static void ppc_lhbrx(UINT32 op)
+{
+ UINT32 ea;
+ UINT16 w;
+
+ if( RA == 0 )
+ ea = REG(RB);
+ else
+ ea = REG(RA) + REG(RB);
+
+ w = READ16(ea);
+ REG(RT) = (UINT32)BYTE_REVERSE16(w);
+}
+
+static void ppc_lhz(UINT32 op)
+{
+ UINT32 ea;
+
+ if( RA == 0 )
+ ea = SIMM16;
+ else
+ ea = REG(RA) + SIMM16;
+
+ REG(RT) = (UINT32)READ16(ea);
+}
+
+static void ppc_lhzu(UINT32 op)
+{
+ UINT32 ea = REG(RA) + SIMM16;
+
+ REG(RT) = (UINT32)READ16(ea);
+ REG(RA) = ea;
+}
+
+static void ppc_lhzux(UINT32 op)
+{
+ UINT32 ea = REG(RA) + REG(RB);
+
+ REG(RT) = (UINT32)READ16(ea);
+ REG(RA) = ea;
+}
+
+static void ppc_lhzx(UINT32 op)
+{
+ UINT32 ea;
+
+ if( RA == 0 )
+ ea = REG(RB);
+ else
+ ea = REG(RA) + REG(RB);
+
+ REG(RT) = (UINT32)READ16(ea);
+}
+#endif
+
+static void ppc_lmw(UINT32 op)
+{
+ int r = RT;
+ UINT32 ea;
+
+ if( RA == 0 )
+ ea = SIMM16;
+ else
+ ea = REG(RA) + SIMM16;
+
+ while( r <= 31 )
+ {
+ REG(r) = READ32(ea);
+ ea += 4;
+ r++;
+ }
+}
+
+static void ppc_lswi(UINT32 op)
+{
+ int n, r, i;
+ UINT32 ea = 0;
+ if( RA != 0 )
+ ea = REG(RA);
+
+ if( RB == 0 )
+ n = 32;
+ else
+ n = RB;
+
+ r = RT - 1;
+ i = 0;
+
+ while(n > 0)
+ {
+ if (i == 0) {
+ r = (r + 1) % 32;
+ REG(r) = 0;
+ }
+ REG(r) |= ((READ8(ea) & 0xff) << (24 - i));
+ i += 8;
+ if (i == 32) {
+ i = 0;
+ }
+ ea++;
+ n--;
+ }
+}
+
+static void ppc_lswx(UINT32 op)
+{
+ int n, r, i;
+ UINT32 ea = 0;
+ if( RA != 0 )
+ ea = REG(RA);
+
+ ea += REG(RB);
+
+ n = ppc.xer & 0x7f;
+
+ r = RT - 1;
+ i = 0;
+
+ while(n > 0)
+ {
+ if (i == 0) {
+ r = (r + 1) % 32;
+ REG(r) = 0;
+ }
+ REG(r) |= ((READ8(ea) & 0xff) << (24 - i));
+ i += 8;
+ if (i == 32) {
+ i = 0;
+ }
+ ea++;
+ n--;
+ }
+}
+
+static void ppc_lwarx(UINT32 op)
+{
+ UINT32 ea;
+
+ if( RA == 0 )
+ ea = REG(RB);
+ else
+ ea = REG(RA) + REG(RB);
+
+ ppc.reserved_address = ea;
+ ppc.reserved = 1;
+
+ REG(RT) = READ32(ea);
+}
+
+#ifndef PPC_DRC
+static void ppc_lwbrx(UINT32 op)
+{
+ UINT32 ea;
+ UINT32 w;
+
+ if( RA == 0 )
+ ea = REG(RB);
+ else
+ ea = REG(RA) + REG(RB);
+
+ w = READ32(ea);
+ REG(RT) = BYTE_REVERSE32(w);
+}
+
+static void ppc_lwz(UINT32 op)
+{
+ UINT32 ea;
+
+ if( RA == 0 )
+ ea = SIMM16;
+ else
+ ea = REG(RA) + SIMM16;
+
+ REG(RT) = READ32(ea);
+}
+
+static void ppc_lwzu(UINT32 op)
+{
+ UINT32 ea = REG(RA) + SIMM16;
+
+ REG(RT) = READ32(ea);
+ REG(RA) = ea;
+}
+
+static void ppc_lwzux(UINT32 op)
+{
+ UINT32 ea = REG(RA) + REG(RB);
+
+ REG(RT) = READ32(ea);
+ REG(RA) = ea;
+}
+
+static void ppc_lwzx(UINT32 op)
+{
+ UINT32 ea;
+
+ if( RA == 0 )
+ ea = REG(RB);
+ else
+ ea = REG(RA) + REG(RB);
+
+ REG(RT) = READ32(ea);
+}
+
+static void ppc_mcrf(UINT32 op)
+{
+ CR(RT >> 2) = CR(RA >> 2);
+}
+
+static void ppc_mcrxr(UINT32 op)
+{
+ CR(RT >> 2) = (XER >> 28) & 0x0F;
+ XER &= ~0xf0000000;
+}
+
+static void ppc_mfcr(UINT32 op)
+{
+ REG(RT) = ppc_get_cr();
+}
+
+static void ppc_mfmsr(UINT32 op)
+{
+ REG(RT) = ppc_get_msr();
+}
+
+static void ppc_mfspr(UINT32 op)
+{
+ REG(RT) = ppc_get_spr(SPR);
+}
+#endif
+
+static void ppc_mtcrf(UINT32 op)
+{
+ int fxm = FXM;
+ int t = RT;
+
+ if( fxm & 0x80 ) CR(0) = (REG(t) >> 28) & 0xf;
+ if( fxm & 0x40 ) CR(1) = (REG(t) >> 24) & 0xf;
+ if( fxm & 0x20 ) CR(2) = (REG(t) >> 20) & 0xf;
+ if( fxm & 0x10 ) CR(3) = (REG(t) >> 16) & 0xf;
+ if( fxm & 0x08 ) CR(4) = (REG(t) >> 12) & 0xf;
+ if( fxm & 0x04 ) CR(5) = (REG(t) >> 8) & 0xf;
+ if( fxm & 0x02 ) CR(6) = (REG(t) >> 4) & 0xf;
+ if( fxm & 0x01 ) CR(7) = (REG(t) >> 0) & 0xf;
+}
+
+#ifndef PPC_DRC
+static void ppc_mtmsr(UINT32 op)
+{
+ ppc_set_msr(REG(RS));
+}
+
+static void ppc_mtspr(UINT32 op)
+{
+ ppc_set_spr(SPR, REG(RS));
+}
+
+static void ppc_mulhwx(UINT32 op)
+{
+ INT64 ra = (INT64)(INT32)REG(RA);
+ INT64 rb = (INT64)(INT32)REG(RB);
+
+ REG(RT) = (UINT32)((ra * rb) >> 32);
+
+ if( RCBIT ) {
+ SET_CR0(REG(RT));
+ }
+}
+
+static void ppc_mulhwux(UINT32 op)
+{
+ UINT64 ra = (UINT64)REG(RA);
+ UINT64 rb = (UINT64)REG(RB);
+
+ REG(RT) = (UINT32)((ra * rb) >> 32);
+
+ if( RCBIT ) {
+ SET_CR0(REG(RT));
+ }
+}
+
+static void ppc_mulli(UINT32 op)
+{
+ INT32 ra = (INT32)REG(RA);
+ INT32 i = SIMM16;
+
+ REG(RT) = ra * i;
+}
+
+static void ppc_mullwx(UINT32 op)
+{
+ INT64 ra = (INT64)(INT32)REG(RA);
+ INT64 rb = (INT64)(INT32)REG(RB);
+ INT64 r;
+
+ r = ra * rb;
+ REG(RT) = (UINT32)r;
+
+ if( OEBIT ) {
+ XER &= ~XER_OV;
+
+ if( r != (INT64)(INT32)r )
+ XER |= XER_OV | XER_SO;
+ }
+
+ if( RCBIT ) {
+ SET_CR0(REG(RT));
+ }
+}
+
+static void ppc_nandx(UINT32 op)
+{
+ REG(RA) = ~(REG(RS) & REG(RB));
+
+ if( RCBIT ) {
+ SET_CR0(REG(RA));
+ }
+}
+
+static void ppc_negx(UINT32 op)
+{
+ REG(RT) = -REG(RA);
+
+ if( OEBIT ) {
+ if( REG(RT) == 0x80000000 )
+ XER |= XER_OV | XER_SO;
+ else
+ XER &= ~XER_OV;
+ }
+
+ if( RCBIT ) {
+ SET_CR0(REG(RT));
+ }
+}
+
+static void ppc_norx(UINT32 op)
+{
+ REG(RA) = ~(REG(RS) | REG(RB));
+
+ if( RCBIT ) {
+ SET_CR0(REG(RA));
+ }
+}
+
+static void ppc_orx(UINT32 op)
+{
+ REG(RA) = REG(RS) | REG(RB);
+
+ if( RCBIT ) {
+ SET_CR0(REG(RA));
+ }
+}
+
+static void ppc_orcx(UINT32 op)
+{
+ REG(RA) = REG(RS) | ~REG(RB);
+
+ if( RCBIT ) {
+ SET_CR0(REG(RA));
+ }
+}
+
+static void ppc_ori(UINT32 op)
+{
+ REG(RA) = REG(RS) | UIMM16;
+}
+
+static void ppc_oris(UINT32 op)
+{
+ REG(RA) = REG(RS) | (UIMM16 << 16);
+}
+
+static void ppc_rfi(UINT32 op)
+{
+ UINT32 msr;
+ ppc.npc = ppc_get_spr(SPR_SRR0);
+ msr = ppc_get_spr(SPR_SRR1);
+ ppc_set_msr( msr );
+}
+
+static void ppc_rlwimix(UINT32 op)
+{
+ UINT32 r;
+ UINT32 mask = GET_ROTATE_MASK(MB, ME);
+ UINT32 rs = REG(RS);
+ int sh = SH;
+
+ r = (rs << sh) | (rs >> (32-sh));
+ REG(RA) = (REG(RA) & ~mask) | (r & mask);
+
+ if( RCBIT ) {
+ SET_CR0(REG(RA));
+ }
+}
+
+static void ppc_rlwinmx(UINT32 op)
+{
+ UINT32 r;
+ UINT32 mask = GET_ROTATE_MASK(MB, ME);
+ UINT32 rs = REG(RS);
+ int sh = SH;
+
+ r = (rs << sh) | (rs >> (32-sh));
+ REG(RA) = r & mask;
+
+ if( RCBIT ) {
+ SET_CR0(REG(RA));
+ }
+}
+
+static void ppc_rlwnmx(UINT32 op)
+{
+ UINT32 r;
+ UINT32 mask = GET_ROTATE_MASK(MB, ME);
+ UINT32 rs = REG(RS);
+ int sh = REG(RB) & 0x1f;
+
+ r = (rs << sh) | (rs >> (32-sh));
+ REG(RA) = r & mask;
+
+ if( RCBIT ) {
+ SET_CR0(REG(RA));
+ }
+}
+#endif
+
+#ifndef PPC_DRC
+static void ppc_sc(UINT32 op)
+{
+ if (ppc.is603) {
+ ppc603_exception(EXCEPTION_SYSTEM_CALL);
+ }
+ if (ppc.is602) {
+ ppc602_exception(EXCEPTION_SYSTEM_CALL);
+ }
+ if (IS_PPC403()) {
+ ppc403_exception(EXCEPTION_SYSTEM_CALL);
+ }
+}
+#endif
+
+static void ppc_slwx(UINT32 op)
+{
+ int sh = REG(RB) & 0x3f;
+
+ if( sh > 31 ) {
+ REG(RA) = 0;
+ }
+ else {
+ REG(RA) = REG(RS) << sh;
+ }
+
+ if( RCBIT ) {
+ SET_CR0(REG(RA));
+ }
+}
+
+static void ppc_srawx(UINT32 op)
+{
+ int sh = REG(RB) & 0x3f;
+
+ XER &= ~XER_CA;
+
+ if( sh > 31 ) {
+ if (REG(RS) & 0x80000000)
+ REG(RA) = 0xffffffff;
+ else
+ REG(RA) = 0;
+ if( REG(RA) )
+ XER |= XER_CA;
+ }
+ else {
+ REG(RA) = (INT32)(REG(RS)) >> sh;
+ if( ((INT32)(REG(RS)) < 0) && (REG(RS) & BITMASK_0(sh)) )
+ XER |= XER_CA;
+ }
+
+ if( RCBIT ) {
+ SET_CR0(REG(RA));
+ }
+}
+
+static void ppc_srawix(UINT32 op)
+{
+ int sh = SH;
+
+ XER &= ~XER_CA;
+ if( ((INT32)(REG(RS)) < 0) && (REG(RS) & BITMASK_0(sh)) )
+ XER |= XER_CA;
+
+ REG(RA) = (INT32)(REG(RS)) >> sh;
+
+ if( RCBIT ) {
+ SET_CR0(REG(RA));
+ }
+}
+
+static void ppc_srwx(UINT32 op)
+{
+ int sh = REG(RB) & 0x3f;
+
+ if( sh > 31 ) {
+ REG(RA) = 0;
+ }
+ else {
+ REG(RA) = REG(RS) >> sh;
+ }
+
+ if( RCBIT ) {
+ SET_CR0(REG(RA));
+ }
+}
+
+#ifndef PPC_DRC
+static void ppc_stb(UINT32 op)
+{
+ UINT32 ea;
+
+ if( RA == 0 )
+ ea = SIMM16;
+ else
+ ea = REG(RA) + SIMM16;
+
+ WRITE8(ea, (UINT8)REG(RS));
+}
+
+static void ppc_stbu(UINT32 op)
+{
+ UINT32 ea = REG(RA) + SIMM16;
+
+ WRITE8(ea, (UINT8)REG(RS));
+ REG(RA) = ea;
+}
+
+static void ppc_stbux(UINT32 op)
+{
+ UINT32 ea = REG(RA) + REG(RB);
+
+ WRITE8(ea, (UINT8)REG(RS));
+ REG(RA) = ea;
+}
+
+static void ppc_stbx(UINT32 op)
+{
+ UINT32 ea;
+
+ if( RA == 0 )
+ ea = REG(RB);
+ else
+ ea = REG(RA) + REG(RB);
+
+ WRITE8(ea, (UINT8)REG(RS));
+}
+
+static void ppc_sth(UINT32 op)
+{
+ UINT32 ea;
+
+ if( RA == 0 )
+ ea = SIMM16;
+ else
+ ea = REG(RA) + SIMM16;
+
+ WRITE16(ea, (UINT16)REG(RS));
+}
+
+static void ppc_sthbrx(UINT32 op)
+{
+ UINT32 ea;
+ UINT16 w;
+
+ if( RA == 0 )
+ ea = REG(RB);
+ else
+ ea = REG(RA) + REG(RB);
+
+ w = REG(RS);
+ WRITE16(ea, (UINT16)BYTE_REVERSE16(w));
+}
+
+static void ppc_sthu(UINT32 op)
+{
+ UINT32 ea = REG(RA) + SIMM16;
+
+ WRITE16(ea, (UINT16)REG(RS));
+ REG(RA) = ea;
+}
+
+static void ppc_sthux(UINT32 op)
+{
+ UINT32 ea = REG(RA) + REG(RB);
+
+ WRITE16(ea, (UINT16)REG(RS));
+ REG(RA) = ea;
+}
+
+static void ppc_sthx(UINT32 op)
+{
+ UINT32 ea;
+
+ if( RA == 0 )
+ ea = REG(RB);
+ else
+ ea = REG(RA) + REG(RB);
+
+ WRITE16(ea, (UINT16)REG(RS));
+}
+#endif
+
+static void ppc_stmw(UINT32 op)
+{
+ UINT32 ea;
+ int r = RS;
+
+ if( RA == 0 )
+ ea = SIMM16;
+ else
+ ea = REG(RA) + SIMM16;
+
+ while( r <= 31 )
+ {
+ WRITE32(ea, REG(r));
+ ea += 4;
+ r++;
+ }
+}
+
+static void ppc_stswi(UINT32 op)
+{
+ int n, r, i;
+ UINT32 ea = 0;
+ if( RA != 0 )
+ ea = REG(RA);
+
+ if( RB == 0 )
+ n = 32;
+ else
+ n = RB;
+
+ r = RT - 1;
+ i = 0;
+
+ while(n > 0)
+ {
+ if (i == 0) {
+ r = (r + 1) % 32;
+ }
+ WRITE8(ea, (REG(r) >> (24-i)) & 0xff);
+ i += 8;
+ if (i == 32) {
+ i = 0;
+ }
+ ea++;
+ n--;
+ }
+}
+
+static void ppc_stswx(UINT32 op)
+{
+ int n, r, i;
+ UINT32 ea = 0;
+ if( RA != 0 )
+ ea = REG(RA);
+
+ ea += REG(RB);
+
+ n = ppc.xer & 0x7f;
+
+ r = RT - 1;
+ i = 0;
+
+ while(n > 0)
+ {
+ if (i == 0) {
+ r = (r + 1) % 32;
+ }
+ WRITE8(ea, (REG(r) >> (24-i)) & 0xff);
+ i += 8;
+ if (i == 32) {
+ i = 0;
+ }
+ ea++;
+ n--;
+ }
+}
+
+#ifndef PPC_DRC
+static void ppc_stw(UINT32 op)
+{
+ UINT32 ea;
+
+ if( RA == 0 )
+ ea = SIMM16;
+ else
+ ea = REG(RA) + SIMM16;
+
+ WRITE32(ea, REG(RS));
+}
+
+static void ppc_stwbrx(UINT32 op)
+{
+ UINT32 ea;
+ UINT32 w;
+
+ if( RA == 0 )
+ ea = REG(RB);
+ else
+ ea = REG(RA) + REG(RB);
+
+ w = REG(RS);
+ WRITE32(ea, BYTE_REVERSE32(w));
+}
+#endif
+
+static void ppc_stwcx_rc(UINT32 op)
+{
+ UINT32 ea;
+
+ if( RA == 0 )
+ ea = REG(RB);
+ else
+ ea = REG(RA) + REG(RB);
+
+ if( ppc.reserved ) {
+ WRITE32(ea, REG(RS));
+
+ ppc.reserved = 0;
+ ppc.reserved_address = 0;
+
+ CR(0) = 0x2;
+ if( XER & XER_SO )
+ CR(0) |= 0x1;
+ } else {
+ CR(0) = 0;
+ if( XER & XER_SO )
+ CR(0) |= 0x1;
+ }
+}
+
+#ifndef PPC_DRC
+static void ppc_stwu(UINT32 op)
+{
+ UINT32 ea = REG(RA) + SIMM16;
+
+ WRITE32(ea, REG(RS));
+ REG(RA) = ea;
+}
+
+static void ppc_stwux(UINT32 op)
+{
+ UINT32 ea = REG(RA) + REG(RB);
+
+ WRITE32(ea, REG(RS));
+ REG(RA) = ea;
+}
+
+static void ppc_stwx(UINT32 op)
+{
+ UINT32 ea;
+
+ if( RA == 0 )
+ ea = REG(RB);
+ else
+ ea = REG(RA) + REG(RB);
+
+ WRITE32(ea, REG(RS));
+}
+
+static void ppc_subfx(UINT32 op)
+{
+ UINT32 ra = REG(RA);
+ UINT32 rb = REG(RB);
+ REG(RT) = rb - ra;
+
+ if( OEBIT ) {
+ SET_SUB_OV(REG(RT), rb, ra);
+ }
+ if( RCBIT ) {
+ SET_CR0(REG(RT));
+ }
+}
+#endif
+
+static void ppc_subfcx(UINT32 op)
+{
+ UINT32 ra = REG(RA);
+ UINT32 rb = REG(RB);
+ REG(RT) = rb - ra;
+
+ SET_SUB_CA(REG(RT), rb, ra);
+
+ if( OEBIT ) {
+ SET_SUB_OV(REG(RT), rb, ra);
+ }
+ if( RCBIT ) {
+ SET_CR0(REG(RT));
+ }
+}
+
+#ifndef PPC_DRC
+static void ppc_subfex(UINT32 op)
+{
+ UINT32 ra = REG(RA);
+ UINT32 rb = REG(RB);
+ UINT32 carry = (XER >> 29) & 0x1;
+ UINT32 r;
+
+ r = ~ra + carry;
+ REG(RT) = rb + r;
+
+ SET_ADD_CA(r, ~ra, carry); /* step 1 carry */
+ if( REG(RT) < r ) /* step 2 carry */
+ XER |= XER_CA;
+
+ if( OEBIT ) {
+ SET_SUB_OV(REG(RT), rb, ra);
+ }
+ if( RCBIT ) {
+ SET_CR0(REG(RT));
+ }
+}
+
+static void ppc_subfic(UINT32 op)
+{
+ UINT32 i = SIMM16;
+ UINT32 ra = REG(RA);
+
+ REG(RT) = i - ra;
+
+ SET_SUB_CA(REG(RT), i, ra);
+}
+#endif
+
+static void ppc_subfmex(UINT32 op)
+{
+ UINT32 ra = REG(RA);
+ UINT32 carry = (XER >> 29) & 0x1;
+ UINT32 r;
+
+ r = ~ra + carry;
+ REG(RT) = r - 1;
+
+ SET_SUB_CA(r, ~ra, carry); /* step 1 carry */
+ if( REG(RT) < r )
+ XER |= XER_CA; /* step 2 carry */
+
+ if( OEBIT ) {
+ SET_SUB_OV(REG(RT), -1, ra);
+ }
+ if( RCBIT ) {
+ SET_CR0(REG(RT));
+ }
+}
+
+static void ppc_subfzex(UINT32 op)
+{
+ UINT32 ra = REG(RA);
+ UINT32 carry = (XER >> 29) & 0x1;
+
+ REG(RT) = ~ra + carry;
+
+ SET_ADD_CA(REG(RT), ~ra, carry);
+
+ if( OEBIT ) {
+ SET_SUB_OV(REG(RT), 0, REG(RA));
+ }
+ if( RCBIT ) {
+ SET_CR0(REG(RT));
+ }
+}
+
+#ifndef PPC_DRC
+static void ppc_sync(UINT32 op)
+{
+
+}
+#endif
+
+#ifndef PPC_DRC
+static void ppc_tw(UINT32 op)
+{
+ int exception = 0;
+ INT32 a = REG(RA);
+ INT32 b = REG(RB);
+ int to = RT;
+
+ if( (a < b) && (to & 0x10) ) {
+ exception = 1;
+ }
+ if( (a > b) && (to & 0x08) ) {
+ exception = 1;
+ }
+ if( (a == b) && (to & 0x04) ) {
+ exception = 1;
+ }
+ if( ((UINT32)a < (UINT32)b) && (to & 0x02) ) {
+ exception = 1;
+ }
+ if( ((UINT32)a > (UINT32)b) && (to & 0x01) ) {
+ exception = 1;
+ }
+
+ if (exception) {
+ if (ppc.is603) {
+ ppc603_exception(EXCEPTION_TRAP);
+ }
+ if (ppc.is602) {
+ ppc602_exception(EXCEPTION_TRAP);
+ }
+ if (IS_PPC403()) {
+ ppc403_exception(EXCEPTION_TRAP);
+ }
+ }
+}
+#endif
+
+#ifndef PPC_DRC
+static void ppc_twi(UINT32 op)
+{
+ int exception = 0;
+ INT32 a = REG(RA);
+ INT32 i = SIMM16;
+ int to = RT;
+
+ if( (a < i) && (to & 0x10) ) {
+ exception = 1;
+ }
+ if( (a > i) && (to & 0x08) ) {
+ exception = 1;
+ }
+ if( (a == i) && (to & 0x04) ) {
+ exception = 1;
+ }
+ if( ((UINT32)a < (UINT32)i) && (to & 0x02) ) {
+ exception = 1;
+ }
+ if( ((UINT32)a > (UINT32)i) && (to & 0x01) ) {
+ exception = 1;
+ }
+
+ if (exception) {
+ if (ppc.is603) {
+ ppc603_exception(EXCEPTION_TRAP);
+ }
+ if (ppc.is602) {
+ ppc602_exception(EXCEPTION_TRAP);
+ }
+ if (IS_PPC403()) {
+ ppc403_exception(EXCEPTION_TRAP);
+ }
+ }
+}
+#endif
+
+#ifndef PPC_DRC
+static void ppc_xorx(UINT32 op)
+{
+ REG(RA) = REG(RS) ^ REG(RB);
+
+ if( RCBIT ) {
+ SET_CR0(REG(RA));
+ }
+}
+
+static void ppc_xori(UINT32 op)
+{
+ REG(RA) = REG(RS) ^ UIMM16;
+}
+
+static void ppc_xoris(UINT32 op)
+{
+ REG(RA) = REG(RS) ^ (UIMM16 << 16);
+}
+
+
+
+static void ppc_invalid(UINT32 op)
+{
+ fatalerror("ppc: Invalid opcode %08X PC : %X", op, ppc.pc);
+}
+#endif
+
+
+// Everything below is new from AJG
+
+////////////////////////////
+// !here are the 6xx ops! //
+////////////////////////////
+
+#define DOUBLE_SIGN (U64(0x8000000000000000))
+#define DOUBLE_EXP (U64(0x7ff0000000000000))
+#define DOUBLE_FRAC (U64(0x000fffffffffffff))
+#define DOUBLE_ZERO (0)
+
+/*
+ Floating point operations.
+*/
+
+INLINE int is_nan_double(FPR x)
+{
+ return( ((x.id & DOUBLE_EXP) == DOUBLE_EXP) &&
+ ((x.id & DOUBLE_FRAC) != DOUBLE_ZERO) );
+}
+
+INLINE int is_qnan_double(FPR x)
+{
+ return( ((x.id & DOUBLE_EXP) == DOUBLE_EXP) &&
+ ((x.id & U64(0x0007fffffffffff)) == U64(0x000000000000000)) &&
+ ((x.id & U64(0x000800000000000)) == U64(0x000800000000000)) );
+}
+
+INLINE int is_snan_double(FPR x)
+{
+ return( ((x.id & DOUBLE_EXP) == DOUBLE_EXP) &&
+ ((x.id & DOUBLE_FRAC) != DOUBLE_ZERO) &&
+ ((x.id & U64(0x0008000000000000)) == DOUBLE_ZERO) );
+}
+
+INLINE int is_infinity_double(FPR x)
+{
+ return( ((x.id & DOUBLE_EXP) == DOUBLE_EXP) &&
+ ((x.id & DOUBLE_FRAC) == DOUBLE_ZERO) );
+}
+
+INLINE int is_normalized_double(FPR x)
+{
+ UINT64 exp;
+
+ exp = (x.id & DOUBLE_EXP) >> 52;
+
+ return (exp >= 1) && (exp <= 2046);
+}
+
+INLINE int is_denormalized_double(FPR x)
+{
+ return( ((x.id & DOUBLE_EXP) == 0) &&
+ ((x.id & DOUBLE_FRAC) != DOUBLE_ZERO) );
+}
+
+INLINE int sign_double(FPR x)
+{
+ return ((x.id & DOUBLE_SIGN) != 0);
+}
+
+INLINE INT64 round_to_nearest(FPR f)
+{
+ if (f.fd >= 0)
+ {
+ return (INT64)(f.fd + 0.5);
+ }
+ else
+ {
+ return -(INT64)(-f.fd + 0.5);
+ }
+}
+
+INLINE INT64 round_toward_zero(FPR f)
+{
+ return (INT64)(f.fd);
+}
+
+INLINE INT64 round_toward_positive_infinity(FPR f)
+{
+ double r = ceil(f.fd);
+ return (INT64)(r);
+}
+
+INLINE INT64 round_toward_negative_infinity(FPR f)
+{
+ double r = floor(f.fd);
+ return (INT64)(r);
+}
+
+
+INLINE void set_fprf(FPR f)
+{
+ UINT32 fprf;
+
+ // see page 3-30, 3-31
+
+ if (is_qnan_double(f))
+ {
+ fprf = 0x11;
+ }
+ else if (is_infinity_double(f))
+ {
+ if (sign_double(f)) // -INF
+ fprf = 0x09;
+ else // +INF
+ fprf = 0x05;
+ }
+ else if (is_normalized_double(f))
+ {
+ if (sign_double(f)) // -Normalized
+ fprf = 0x08;
+ else // +Normalized
+ fprf = 0x04;
+ }
+ else if (is_denormalized_double(f))
+ {
+ if (sign_double(f)) // -Denormalized
+ fprf = 0x18;
+ else // +Denormalized
+ fprf = 0x14;
+ }
+ else // Zero
+ {
+ if (sign_double(f)) // -Zero
+ fprf = 0x12;
+ else // +Zero
+ fprf = 0x02;
+ }
+
+ ppc.fpscr &= ~0x0001f000;
+ ppc.fpscr |= (fprf << 12);
+}
+
+
+
+#define SET_VXSNAN(a, b) if (is_snan_double(a) || is_snan_double(b)) ppc.fpscr |= 0x80000000
+#define SET_VXSNAN_1(c) if (is_snan_double(c)) ppc.fpscr |= 0x80000000
+
+
+
+
+static void ppc_lfs(UINT32 op)
+{
+ UINT32 ea = SIMM16;
+ UINT32 a = RA;
+ UINT32 t = RT;
+ FPR32 f;
+
+ if(a)
+ ea += REG(a);
+
+ f.i = READ32(ea);
+ FPR(t).fd = (double)(f.f);
+}
+
+static void ppc_lfsu(UINT32 op)
+{
+ UINT32 ea = SIMM16;
+ UINT32 a = RA;
+ UINT32 t = RT;
+ FPR32 f;
+
+ ea += REG(a);
+
+ f.i = READ32(ea);
+ FPR(t).fd = (double)(f.f);
+
+ REG(a) = ea;
+}
+
+#ifndef PPC_DRC
+static void ppc_lfd(UINT32 op)
+{
+ UINT32 ea = SIMM16;
+ UINT32 a = RA;
+ UINT32 t = RT;
+
+ if(a)
+ ea += REG(a);
+
+ FPR(t).id = READ64(ea);
+}
+
+static void ppc_lfdu(UINT32 op)
+{
+ UINT32 ea = SIMM16;
+ UINT32 a = RA;
+ UINT32 d = RD;
+
+ ea += REG(a);
+
+ FPR(d).id = READ64(ea);
+
+ REG(a) = ea;
+}
+#endif
+
+static void ppc_stfs(UINT32 op)
+{
+ UINT32 ea = SIMM16;
+ UINT32 a = RA;
+ UINT32 t = RT;
+ FPR32 f;
+
+ if(a)
+ ea += REG(a);
+
+ f.f = (float)(FPR(t).fd);
+ WRITE32(ea, f.i);
+}
+
+static void ppc_stfsu(UINT32 op)
+{
+ UINT32 ea = SIMM16;
+ UINT32 a = RA;
+ UINT32 t = RT;
+ FPR32 f;
+
+ ea += REG(a);
+
+ f.f = (float)(FPR(t).fd);
+ WRITE32(ea, f.i);
+
+ REG(a) = ea;
+}
+
+#ifndef PPC_DRC
+static void ppc_stfd(UINT32 op)
+{
+ UINT32 ea = SIMM16;
+ UINT32 a = RA;
+ UINT32 t = RT;
+
+ if(a)
+ ea += REG(a);
+
+ WRITE64(ea, FPR(t).id);
+}
+
+static void ppc_stfdu(UINT32 op)
+{
+ UINT32 ea = SIMM16;
+ UINT32 a = RA;
+ UINT32 t = RT;
+
+ ea += REG(a);
+
+ WRITE64(ea, FPR(t).id);
+
+ REG(a) = ea;
+}
+
+static void ppc_lfdux(UINT32 op)
+{
+ UINT32 ea = REG(RB);
+ UINT32 a = RA;
+ UINT32 d = RD;
+
+ ea += REG(a);
+
+ FPR(d).id = READ64(ea);
+
+ REG(a) = ea;
+}
+
+static void ppc_lfdx(UINT32 op)
+{
+ UINT32 ea = REG(RB);
+ UINT32 a = RA;
+ UINT32 d = RD;
+
+ if(a)
+ ea += REG(a);
+
+ FPR(d).id = READ64(ea);
+}
+#endif
+
+static void ppc_lfsux(UINT32 op)
+{
+ UINT32 ea = REG(RB);
+ UINT32 a = RA;
+ UINT32 t = RT;
+ FPR32 f;
+
+ ea += REG(a);
+
+ f.i = READ32(ea);
+ FPR(t).fd = (double)(f.f);
+
+ REG(a) = ea;
+}
+
+static void ppc_lfsx(UINT32 op)
+{
+ UINT32 ea = REG(RB);
+ UINT32 a = RA;
+ UINT32 t = RT;
+ FPR32 f;
+
+ if(a)
+ ea += REG(a);
+
+ f.i = READ32(ea);
+ FPR(t).fd = (double)(f.f);
+}
+
+static void ppc_mfsr(UINT32 op)
+{
+ UINT32 sr = (op >> 16) & 15;
+ UINT32 t = RT;
+
+ CHECK_SUPERVISOR();
+
+ REG(t) = ppc.sr[sr];
+}
+
+static void ppc_mfsrin(UINT32 op)
+{
+ UINT32 b = RB;
+ UINT32 t = RT;
+
+ CHECK_SUPERVISOR();
+
+ REG(t) = ppc.sr[REG(b) >> 28];
+}
+
+static void ppc_mftb(UINT32 op)
+{
+ UINT32 x = SPRF;
+
+ switch(x)
+ {
+ case 268: REG(RT) = (UINT32)(ppc_read_timebase()); break;
+ case 269: REG(RT) = (UINT32)(ppc_read_timebase() >> 32); break;
+ default: fatalerror("ppc: Invalid timebase register %d at %08X", x, ppc.pc); break;
+ }
+}
+
+static void ppc_mtsr(UINT32 op)
+{
+ UINT32 sr = (op >> 16) & 15;
+ UINT32 t = RT;
+
+ CHECK_SUPERVISOR();
+
+ ppc.sr[sr] = REG(t);
+}
+
+static void ppc_mtsrin(UINT32 op)
+{
+ UINT32 b = RB;
+ UINT32 t = RT;
+
+ CHECK_SUPERVISOR();
+
+ ppc.sr[REG(b) >> 28] = REG(t);
+}
+
+#ifndef PPC_DRC
+static void ppc_dcba(UINT32 op)
+{
+ /* TODO: Cache not emulated so this opcode doesn't need to be implemented */
+}
+
+static void ppc_stfdux(UINT32 op)
+{
+ UINT32 ea = REG(RB);
+ UINT32 a = RA;
+ UINT32 t = RT;
+
+ ea += REG(a);
+
+ WRITE64(ea, FPR(t).id);
+
+ REG(a) = ea;
+}
+#endif
+
+static void ppc_stfdx(UINT32 op)
+{
+ UINT32 ea = REG(RB);
+ UINT32 a = RA;
+ UINT32 t = RT;
+
+ if(a)
+ ea += REG(a);
+
+ WRITE64(ea, FPR(t).id);
+}
+
+static void ppc_stfiwx(UINT32 op)
+{
+ UINT32 ea = REG(RB);
+ UINT32 a = RA;
+ UINT32 t = RT;
+
+ if(a)
+ ea += REG(a);
+
+ WRITE32(ea, (UINT32)FPR(t).id);
+}
+
+static void ppc_stfsux(UINT32 op)
+{
+ UINT32 ea = REG(RB);
+ UINT32 a = RA;
+ UINT32 t = RT;
+ FPR32 f;
+
+ ea += REG(a);
+
+ f.f = (float)(FPR(t).fd);
+ WRITE32(ea, f.i);
+
+ REG(a) = ea;
+}
+
+static void ppc_stfsx(UINT32 op)
+{
+ UINT32 ea = REG(RB);
+ UINT32 a = RA;
+ UINT32 t = RT;
+ FPR32 f;
+
+ if(a)
+ ea += REG(a);
+
+ f.f = (float)(FPR(t).fd);
+
+ WRITE32(ea, f.i);
+}
+
+#ifndef PPC_DRC
+static void ppc_tlbia(UINT32 op)
+{
+ /* TODO: TLB not emulated so this opcode doesn't need to implemented */
+}
+
+static void ppc_tlbie(UINT32 op)
+{
+ /* TODO: TLB not emulated so this opcode doesn't need to implemented */
+}
+
+static void ppc_tlbsync(UINT32 op)
+{
+ /* TODO: TLB not emulated so this opcode doesn't need to implemented */
+}
+
+static void ppc_eciwx(UINT32 op)
+{
+ ppc_unimplemented(op);
+}
+
+static void ppc_ecowx(UINT32 op)
+{
+ ppc_unimplemented(op);
+}
+#endif
+
+static void ppc_fabsx(UINT32 op)
+{
+ UINT32 b = RB;
+ UINT32 t = RT;
+
+ CHECK_FPU_AVAILABLE();
+
+ FPR(t).id = FPR(b).id & ~DOUBLE_SIGN;
+
+ if( RCBIT ) {
+ SET_CR1();
+ }
+}
+
+static void ppc_faddx(UINT32 op)
+{
+ UINT32 b = RB;
+ UINT32 a = RA;
+ UINT32 t = RT;
+
+ CHECK_FPU_AVAILABLE();
+
+ SET_VXSNAN(FPR(a), FPR(b));
+
+ FPR(t).fd = FPR(a).fd + FPR(b).fd;
+
+ set_fprf(FPR(t));
+ if( RCBIT ) {
+ SET_CR1();
+ }
+}
+
+static void ppc_fcmpo(UINT32 op)
+{
+ UINT32 b = RB;
+ UINT32 a = RA;
+ UINT32 t = (RT >> 2);
+ UINT32 c;
+
+ CHECK_FPU_AVAILABLE();
+
+ SET_VXSNAN(FPR(a), FPR(b));
+
+ if(is_nan_double(FPR(a)) || is_nan_double(FPR(b)))
+ {
+ c = 1; /* OX */
+ if(is_snan_double(FPR(a)) || is_snan_double(FPR(b))) {
+ ppc.fpscr |= 0x01000000; /* VXSNAN */
+
+ if(!(ppc.fpscr & 0x40000000) || is_qnan_double(FPR(a)) || is_qnan_double(FPR(b)))
+ ppc.fpscr |= 0x00080000; /* VXVC */
+ }
+ }
+ else if(FPR(a).fd < FPR(b).fd){
+ c = 8; /* FX */
+ }
+ else if(FPR(a).fd > FPR(b).fd){
+ c = 4; /* FEX */
+ }
+ else {
+ c = 2; /* VX */
+ }
+
+ CR(t) = c;
+
+ ppc.fpscr &= ~0x0001F000;
+ ppc.fpscr |= (c << 12);
+}
+
+static void ppc_fcmpu(UINT32 op)
+{
+ UINT32 b = RB;
+ UINT32 a = RA;
+ UINT32 t = (RT >> 2);
+ UINT32 c;
+
+ CHECK_FPU_AVAILABLE();
+
+ SET_VXSNAN(FPR(a), FPR(b));
+
+ if(is_nan_double(FPR(a)) || is_nan_double(FPR(b)))
+ {
+ c = 1; /* OX */
+ if(is_snan_double(FPR(a)) || is_snan_double(FPR(b))) {
+ ppc.fpscr |= 0x01000000; /* VXSNAN */
+ }
+ }
+ else if(FPR(a).fd < FPR(b).fd){
+ c = 8; /* FX */
+ }
+ else if(FPR(a).fd > FPR(b).fd){
+ c = 4; /* FEX */
+ }
+ else {
+ c = 2; /* VX */
+ }
+
+ CR(t) = c;
+
+ ppc.fpscr &= ~0x0001F000;
+ ppc.fpscr |= (c << 12);
+}
+
+static void ppc_fctiwx(UINT32 op)
+{
+ UINT32 b = RB;
+ UINT32 t = RT;
+ INT64 r = 0;
+
+ // TODO: fix FPSCR flags FX,VXSNAN,VXCVI
+
+ CHECK_FPU_AVAILABLE();
+
+ SET_VXSNAN_1(FPR(b));
+
+ switch(ppc.fpscr & 3)
+ {
+ case 0: r = (INT64)round_to_nearest(FPR(b)); break;
+ case 1: r = (INT64)round_toward_zero(FPR(b)); break;
+ case 2: r = (INT64)round_toward_positive_infinity(FPR(b)); break;
+ case 3: r = (INT64)round_toward_negative_infinity(FPR(b)); break;
+ }
+
+ if(r > (INT64)((INT32)0x7FFFFFFF))
+ {
+ FPR(t).id = 0x7FFFFFFF;
+ // FPSCR[FR] = 0
+ // FPSCR[FI] = 1
+ // FPSCR[XX] = 1
+ }
+ else if(FPR(b).fd < (INT64)((INT32)0x80000000))
+ {
+ FPR(t).id = 0x80000000;
+ // FPSCR[FR] = 1
+ // FPSCR[FI] = 1
+ // FPSCR[XX] = 1
+ }
+ else
+ {
+ FPR(t).id = (UINT32)r;
+ // FPSCR[FR] = t.iw > t.fd
+ // FPSCR[FI] = t.iw == t.fd
+ // FPSCR[XX] = ?
+ }
+
+ // FPSCR[FPRF] = undefined (leave it as is)
+ if( RCBIT ) {
+ SET_CR1();
+ }
+}
+
+static void ppc_fctiwzx(UINT32 op)
+{
+ UINT32 b = RB;
+ UINT32 t = RT;
+ INT64 r;
+
+ // TODO: fix FPSCR flags FX,VXSNAN,VXCVI
+
+ CHECK_FPU_AVAILABLE();
+
+ SET_VXSNAN_1(FPR(b));
+ r = round_toward_zero(FPR(b));
+
+ if(r > (INT64)((INT32)0x7fffffff))
+ {
+ FPR(t).id = 0x7fffffff;
+ // FPSCR[FR] = 0
+ // FPSCR[FI] = 1
+ // FPSCR[XX] = 1
+
+ }
+ else if(r < (INT64)((INT32)0x80000000))
+ {
+ FPR(t).id = 0x80000000;
+ // FPSCR[FR] = 1
+ // FPSCR[FI] = 1
+ // FPSCR[XX] = 1
+ }
+ else
+ {
+ FPR(t).id = (UINT32)r;
+ // FPSCR[FR] = t.iw > t.fd
+ // FPSCR[FI] = t.iw == t.fd
+ // FPSCR[XX] = ?
+ }
+
+ // FPSCR[FPRF] = undefined (leave it as is)
+ if( RCBIT ) {
+ SET_CR1();
+ }
+}
+
+static void ppc_fdivx(UINT32 op)
+{
+ UINT32 b = RB;
+ UINT32 a = RA;
+ UINT32 t = RT;
+
+ CHECK_FPU_AVAILABLE();
+
+ SET_VXSNAN(FPR(a), FPR(b));
+
+ FPR(t).fd = FPR(a).fd / FPR(b).fd;
+
+ set_fprf(FPR(t));
+ if( RCBIT ) {
+ SET_CR1();
+ }
+}
+
+static void ppc_fmrx(UINT32 op)
+{
+ UINT32 b = RB;
+ UINT32 t = RT;
+
+ CHECK_FPU_AVAILABLE();
+
+ FPR(t).fd = FPR(b).fd;
+
+ if( RCBIT ) {
+ SET_CR1();
+ }
+}
+
+static void ppc_fnabsx(UINT32 op)
+{
+ UINT32 b = RB;
+ UINT32 t = RT;
+
+ CHECK_FPU_AVAILABLE();
+
+ FPR(t).id = FPR(b).id | DOUBLE_SIGN;
+
+ if( RCBIT ) {
+ SET_CR1();
+ }
+}
+
+static void ppc_fnegx(UINT32 op)
+{
+ UINT32 b = RB;
+ UINT32 t = RT;
+
+ CHECK_FPU_AVAILABLE();
+
+ FPR(t).id = FPR(b).id ^ DOUBLE_SIGN;
+
+ if( RCBIT ) {
+ SET_CR1();
+ }
+}
+
+static void ppc_frspx(UINT32 op)
+{
+ UINT32 b = RB;
+ UINT32 t = RT;
+
+ CHECK_FPU_AVAILABLE();
+
+ SET_VXSNAN_1(FPR(b));
+
+ FPR(t).fd = (float)FPR(b).fd;
+
+ set_fprf(FPR(t));
+ if( RCBIT ) {
+ SET_CR1();
+ }
+}
+
+static void ppc_frsqrtex(UINT32 op)
+{
+ UINT32 b = RB;
+ UINT32 t = RT;
+
+ CHECK_FPU_AVAILABLE();
+
+ SET_VXSNAN_1(FPR(b));
+
+ FPR(t).fd = 1.0 / sqrt(FPR(b).fd); /* verify this */
+
+ set_fprf(FPR(t));
+ if( RCBIT ) {
+ SET_CR1();
+ }
+}
+
+static void ppc_fsqrtx(UINT32 op)
+{
+ /* NOTE: PPC603e doesn't support this opcode */
+ UINT32 b = RB;
+ UINT32 t = RT;
+
+ CHECK_FPU_AVAILABLE();
+
+ SET_VXSNAN_1(FPR(b));
+
+ FPR(t).fd = (double)(sqrt(FPR(b).fd));
+
+ set_fprf(FPR(t));
+ if( RCBIT ) {
+ SET_CR1();
+ }
+}
+
+static void ppc_fsubx(UINT32 op)
+{
+ UINT32 b = RB;
+ UINT32 a = RA;
+ UINT32 t = RT;
+
+ CHECK_FPU_AVAILABLE();
+
+ SET_VXSNAN(FPR(a), FPR(b));
+
+ FPR(t).fd = FPR(a).fd - FPR(b).fd;
+
+ set_fprf(FPR(t));
+ if( RCBIT ) {
+ SET_CR1();
+ }
+}
+
+static void ppc_mffsx(UINT32 op)
+{
+ FPR(RT).id = (UINT32)ppc.fpscr;
+
+ if( RCBIT ) {
+ SET_CR1();
+ }
+}
+
+static void ppc_mtfsb0x(UINT32 op)
+{
+ UINT32 crbD;
+
+ crbD = (op >> 21) & 0x1F;
+
+ if (crbD != 1 && crbD != 2) // these bits cannot be explicitly cleared
+ ppc.fpscr &= ~(1 << (31 - crbD));
+
+ if( RCBIT ) {
+ SET_CR1();
+ }
+}
+
+static void ppc_mtfsb1x(UINT32 op)
+{
+ UINT32 crbD;
+
+ crbD = (op >> 21) & 0x1F;
+
+ if (crbD != 1 && crbD != 2) // these bits cannot be explicitly cleared
+ ppc.fpscr |= (1 << (31 - crbD));
+
+ if( RCBIT ) {
+ SET_CR1();
+ }
+}
+
+static void ppc_mtfsfx(UINT32 op)
+{
+ UINT32 b = RB;
+ UINT32 f = FM;
+
+ f = ppc_field_xlat[FM];
+
+ ppc.fpscr &= (~f) | ~(FPSCR_FEX | FPSCR_VX);
+ ppc.fpscr |= (UINT32)(FPR(b).id) & ~(FPSCR_FEX | FPSCR_VX);
+
+ // FEX, VX
+
+ if( RCBIT ) {
+ SET_CR1();
+ }
+}
+
+static void ppc_mtfsfix(UINT32 op)
+{
+ UINT32 crfd = CRFD;
+ UINT32 imm = (op >> 12) & 0xF;
+
+ /*
+ * According to the manual:
+ *
+ * If bits 0 and 3 of FPSCR are to be modified, they take the immediate
+ * value specified. Bits 1 and 2 (FEX and VX) are set according to the
+ * "usual rule" and not from IMM[1-2].
+ *
+ * The "usual rule" is not emulated, so these bits simply aren't modified
+ * at all here.
+ */
+
+ crfd = (7 - crfd) * 4; // calculate LSB position of field
+
+ if (crfd == 28) // field containing FEX and VX is special...
+ { // bits 1 and 2 of FPSCR must not be altered
+ ppc.fpscr &= 0x9fffffff;
+ ppc.fpscr |= (imm & 0x9fffffff);
+ }
+
+ ppc.fpscr &= ~(0xf << crfd); // clear field
+ ppc.fpscr |= (imm << crfd); // insert new data
+
+ if( RCBIT ) {
+ SET_CR1();
+ }
+}
+
+static void ppc_mcrfs(UINT32 op)
+{
+ UINT32 crfs, f;
+ crfs = CRFA;
+
+ f = ppc.fpscr >> ((7 - crfs) * 4); // get crfS field from FPSCR
+ f &= 0xf;
+
+ switch(crfs) // determine which exception bits to clear in FPSCR
+ {
+ case 0: // FX, OX
+ ppc.fpscr &= ~0x90000000;
+ break;
+ case 1: // UX, ZX, XX, VXSNAN
+ ppc.fpscr &= ~0x0f000000;
+ break;
+ case 2: // VXISI, VXIDI, VXZDZ, VXIMZ
+ ppc.fpscr &= ~0x00F00000;
+ break;
+ case 3: // VXVC
+ ppc.fpscr &= ~0x00080000;
+ break;
+ case 5: // VXSOFT, VXSQRT, VXCVI
+ ppc.fpscr &= ~0x00000e00;
+ break;
+ default:
+ break;
+ }
+
+ CR(CRFD) = f;
+}
+
+static void ppc_faddsx(UINT32 op)
+{
+ UINT32 b = RB;
+ UINT32 a = RA;
+ UINT32 t = RT;
+
+ CHECK_FPU_AVAILABLE();
+
+ SET_VXSNAN(FPR(a), FPR(b));
+
+ FPR(t).fd = (float)(FPR(a).fd + FPR(b).fd);
+
+ set_fprf(FPR(t));
+ if( RCBIT ) {
+ SET_CR1();
+ }
+}
+
+static void ppc_fdivsx(UINT32 op)
+{
+ UINT32 b = RB;
+ UINT32 a = RA;
+ UINT32 t = RT;
+
+ CHECK_FPU_AVAILABLE();
+
+ SET_VXSNAN(FPR(a), FPR(b));
+
+ FPR(t).fd = (float)(FPR(a).fd / FPR(b).fd);
+
+ set_fprf(FPR(t));
+ if( RCBIT ) {
+ SET_CR1();
+ }
+}
+
+static void ppc_fresx(UINT32 op)
+{
+ UINT32 b = RB;
+ UINT32 t = RT;
+
+ CHECK_FPU_AVAILABLE();
+
+ SET_VXSNAN_1(FPR(b));
+
+ FPR(t).fd = 1.0 / FPR(b).fd; /* ??? */
+
+ set_fprf(FPR(t));
+ if( RCBIT ) {
+ SET_CR1();
+ }
+}
+
+static void ppc_fsqrtsx(UINT32 op)
+{
+ /* NOTE: This opcode is not supported in PPC603e */
+ UINT32 b = RB;
+ UINT32 t = RT;
+
+ CHECK_FPU_AVAILABLE();
+
+ SET_VXSNAN_1(FPR(b));
+
+ FPR(t).fd = (float)(sqrt(FPR(b).fd));
+
+ set_fprf(FPR(t));
+ if( RCBIT ) {
+ SET_CR1();
+ }
+}
+
+static void ppc_fsubsx(UINT32 op)
+{
+ UINT32 b = RB;
+ UINT32 a = RA;
+ UINT32 t = RT;
+
+ CHECK_FPU_AVAILABLE();
+
+ SET_VXSNAN(FPR(a), FPR(b));
+
+ FPR(t).fd = (float)(FPR(a).fd - FPR(b).fd);
+
+ set_fprf(FPR(t));
+ if( RCBIT ) {
+ SET_CR1();
+ }
+}
+
+static void ppc_fmaddx(UINT32 op)
+{
+ UINT32 c = RC;
+ UINT32 b = RB;
+ UINT32 a = RA;
+ UINT32 t = RT;
+
+ CHECK_FPU_AVAILABLE();
+
+ SET_VXSNAN(FPR(a), FPR(b));
+ SET_VXSNAN_1(FPR(c));
+
+ FPR(t).fd = ((FPR(a).fd * FPR(c).fd) + FPR(b).fd);
+
+ set_fprf(FPR(t));
+ if( RCBIT ) {
+ SET_CR1();
+ }
+}
+
+static void ppc_fmsubx(UINT32 op)
+{
+ UINT32 c = RC;
+ UINT32 b = RB;
+ UINT32 a = RA;
+ UINT32 t = RT;
+
+ CHECK_FPU_AVAILABLE();
+
+ SET_VXSNAN(FPR(a), FPR(b));
+ SET_VXSNAN_1(FPR(c));
+
+ FPR(t).fd = ((FPR(a).fd * FPR(c).fd) - FPR(b).fd);
+
+ set_fprf(FPR(t));
+ if( RCBIT ) {
+ SET_CR1();
+ }
+}
+
+static void ppc_fmulx(UINT32 op)
+{
+ UINT32 c = RC;
+ UINT32 a = RA;
+ UINT32 t = RT;
+
+ CHECK_FPU_AVAILABLE();
+
+ SET_VXSNAN(FPR(a), FPR(c));
+
+ FPR(t).fd = (FPR(a).fd * FPR(c).fd);
+
+ set_fprf(FPR(t));
+ if( RCBIT ) {
+ SET_CR1();
+ }
+}
+
+static void ppc_fnmaddx(UINT32 op)
+{
+ UINT32 c = RC;
+ UINT32 b = RB;
+ UINT32 a = RA;
+ UINT32 t = RT;
+
+ CHECK_FPU_AVAILABLE();
+
+ SET_VXSNAN(FPR(a), FPR(b));
+ SET_VXSNAN_1(FPR(c));
+
+ FPR(t).fd = (-((FPR(a).fd * FPR(c).fd) + FPR(b).fd));
+
+ set_fprf(FPR(t));
+ if( RCBIT ) {
+ SET_CR1();
+ }
+}
+
+static void ppc_fnmsubx(UINT32 op)
+{
+ UINT32 c = RC;
+ UINT32 b = RB;
+ UINT32 a = RA;
+ UINT32 t = RT;
+
+ CHECK_FPU_AVAILABLE();
+
+ SET_VXSNAN(FPR(a), FPR(b));
+ SET_VXSNAN_1(FPR(c));
+
+ FPR(t).fd = (-((FPR(a).fd * FPR(c).fd) - FPR(b).fd));
+
+ set_fprf(FPR(t));
+ if( RCBIT ) {
+ SET_CR1();
+ }
+}
+
+static void ppc_fselx(UINT32 op)
+{
+ UINT32 c = RC;
+ UINT32 b = RB;
+ UINT32 a = RA;
+ UINT32 t = RT;
+
+ CHECK_FPU_AVAILABLE();
+
+ FPR(t).fd = (FPR(a).fd >= 0.0) ? FPR(c).fd : FPR(b).fd;
+
+ if( RCBIT ) {
+ SET_CR1();
+ }
+}
+
+static void ppc_fmaddsx(UINT32 op)
+{
+ UINT32 c = RC;
+ UINT32 b = RB;
+ UINT32 a = RA;
+ UINT32 t = RT;
+
+ CHECK_FPU_AVAILABLE();
+
+ SET_VXSNAN(FPR(a), FPR(b));
+ SET_VXSNAN_1(FPR(c));
+
+ FPR(t).fd = (float)((FPR(a).fd * FPR(c).fd) + FPR(b).fd);
+
+ set_fprf(FPR(t));
+ if( RCBIT ) {
+ SET_CR1();
+ }
+}
+
+static void ppc_fmsubsx(UINT32 op)
+{
+ UINT32 c = RC;
+ UINT32 b = RB;
+ UINT32 a = RA;
+ UINT32 t = RT;
+
+ CHECK_FPU_AVAILABLE();
+
+ SET_VXSNAN(FPR(a), FPR(b));
+ SET_VXSNAN_1(FPR(c));
+
+ FPR(t).fd = (float)((FPR(a).fd * FPR(c).fd) - FPR(b).fd);
+
+ set_fprf(FPR(t));
+ if( RCBIT ) {
+ SET_CR1();
+ }
+}
+
+static void ppc_fmulsx(UINT32 op)
+{
+ UINT32 c = RC;
+ UINT32 a = RA;
+ UINT32 t = RT;
+
+ CHECK_FPU_AVAILABLE();
+ SET_VXSNAN(FPR(a), FPR(c));
+
+ FPR(t).fd = (float)(FPR(a).fd * FPR(c).fd);
+
+ set_fprf(FPR(t));
+ if( RCBIT ) {
+ SET_CR1();
+ }
+}
+
+static void ppc_fnmaddsx(UINT32 op)
+{
+ UINT32 c = RC;
+ UINT32 b = RB;
+ UINT32 a = RA;
+ UINT32 t = RT;
+
+ CHECK_FPU_AVAILABLE();
+
+ SET_VXSNAN(FPR(a), FPR(b));
+ SET_VXSNAN_1(FPR(c));
+
+ FPR(t).fd = (float)(-((FPR(a).fd * FPR(c).fd) + FPR(b).fd));
+
+ set_fprf(FPR(t));
+ if( RCBIT ) {
+ SET_CR1();
+ }
+}
+
+static void ppc_fnmsubsx(UINT32 op)
+{
+ UINT32 c = RC;
+ UINT32 b = RB;
+ UINT32 a = RA;
+ UINT32 t = RT;
+
+ CHECK_FPU_AVAILABLE();
+
+ SET_VXSNAN(FPR(a), FPR(b));
+ SET_VXSNAN_1(FPR(c));
+
+ FPR(t).fd = (float)(-((FPR(a).fd * FPR(c).fd) - FPR(b).fd));
+
+ set_fprf(FPR(t));
+ if( RCBIT ) {
+ SET_CR1();
+ }
+}
diff --git a/trunk/src/emu/cpu/powerpc/ppc_ops.h b/trunk/src/emu/cpu/powerpc/ppc_ops.h
new file mode 100644
index 00000000000..48b9d5144a7
--- /dev/null
+++ b/trunk/src/emu/cpu/powerpc/ppc_ops.h
@@ -0,0 +1,150 @@
+#pragma once
+
+#ifndef __PPC_OPS_H__
+#define __PPC_OPS_H__
+
+static PPC_OPCODE ppc_opcode_common[] =
+{
+ /*code subcode handler */
+ { 31, 266, ppc_addx },
+ { 31, 266 | 512, ppc_addx },
+ { 31, 10, ppc_addcx },
+ { 31, 10 | 512, ppc_addcx },
+ { 31, 138, ppc_addex },
+ { 31, 138 | 512, ppc_addex },
+ { 14, -1, ppc_addi },
+ { 12, -1, ppc_addic },
+ { 13, -1, ppc_addic_rc },
+ { 15, -1, ppc_addis },
+ { 31, 234, ppc_addmex },
+ { 31, 234 | 512, ppc_addmex },
+ { 31, 202, ppc_addzex },
+ { 31, 202 | 512, ppc_addzex },
+ { 31, 28, ppc_andx },
+ { 31, 28 | 512, ppc_andx },
+ { 31, 60, ppc_andcx },
+ { 28, -1, ppc_andi_rc },
+ { 29, -1, ppc_andis_rc },
+ { 18, -1, ppc_bx },
+ { 16, -1, ppc_bcx },
+ { 19, 528, ppc_bcctrx },
+ { 19, 16, ppc_bclrx },
+ { 31, 0, ppc_cmp },
+ { 11, -1, ppc_cmpi },
+ { 31, 32, ppc_cmpl },
+ { 10, -1, ppc_cmpli },
+ { 31, 26, ppc_cntlzw },
+ { 19, 257, ppc_crand },
+ { 19, 129, ppc_crandc },
+ { 19, 289, ppc_creqv },
+ { 19, 225, ppc_crnand },
+ { 19, 33, ppc_crnor },
+ { 19, 449, ppc_cror },
+ { 19, 417, ppc_crorc },
+ { 19, 193, ppc_crxor },
+ { 31, 86, ppc_dcbf },
+ { 31, 470, ppc_dcbi },
+ { 31, 54, ppc_dcbst },
+ { 31, 278, ppc_dcbt },
+ { 31, 246, ppc_dcbtst },
+ { 31, 1014, ppc_dcbz },
+ { 31, 491, ppc_divwx },
+ { 31, 491 | 512, ppc_divwx },
+ { 31, 459, ppc_divwux },
+ { 31, 459 | 512, ppc_divwux },
+ { 31, 854, ppc_eieio },
+ { 31, 284, ppc_eqvx },
+ { 31, 954, ppc_extsbx },
+ { 31, 922, ppc_extshx },
+ { 31, 982, ppc_icbi },
+ { 19, 150, ppc_isync },
+ { 34, -1, ppc_lbz },
+ { 35, -1, ppc_lbzu },
+ { 31, 119, ppc_lbzux },
+ { 31, 87, ppc_lbzx },
+ { 42, -1, ppc_lha },
+ { 43, -1, ppc_lhau },
+ { 31, 375, ppc_lhaux },
+ { 31, 343, ppc_lhax },
+ { 31, 790, ppc_lhbrx },
+ { 40, -1, ppc_lhz },
+ { 41, -1, ppc_lhzu },
+ { 31, 311, ppc_lhzux },
+ { 31, 279, ppc_lhzx },
+ { 46, -1, ppc_lmw },
+ { 31, 597, ppc_lswi },
+ { 31, 533, ppc_lswx },
+ { 31, 20, ppc_lwarx },
+ { 31, 534, ppc_lwbrx },
+ { 32, -1, ppc_lwz },
+ { 33, -1, ppc_lwzu },
+ { 31, 55, ppc_lwzux },
+ { 31, 23, ppc_lwzx },
+ { 19, 0, ppc_mcrf },
+ { 31, 512, ppc_mcrxr },
+ { 31, 19, ppc_mfcr },
+ { 31, 83, ppc_mfmsr },
+ { 31, 339, ppc_mfspr },
+ { 31, 144, ppc_mtcrf },
+ { 31, 146, ppc_mtmsr },
+ { 31, 467, ppc_mtspr },
+ { 31, 75, ppc_mulhwx },
+ { 31, 11, ppc_mulhwux },
+ { 7, -1, ppc_mulli },
+ { 31, 235, ppc_mullwx },
+ { 31, 235 | 512, ppc_mullwx },
+ { 31, 476, ppc_nandx },
+ { 31, 104, ppc_negx },
+ { 31, 104 | 512, ppc_negx },
+ { 31, 124, ppc_norx },
+ { 31, 444, ppc_orx },
+ { 31, 412, ppc_orcx },
+ { 24, -1, ppc_ori },
+ { 25, -1, ppc_oris },
+ { 19, 50, ppc_rfi },
+ { 20, -1, ppc_rlwimix },
+ { 21, -1, ppc_rlwinmx },
+ { 23, -1, ppc_rlwnmx },
+ { 17, -1, ppc_sc },
+ { 31, 24, ppc_slwx },
+ { 31, 792, ppc_srawx },
+ { 31, 824, ppc_srawix },
+ { 31, 536, ppc_srwx },
+ { 38, -1, ppc_stb },
+ { 39, -1, ppc_stbu },
+ { 31, 247, ppc_stbux },
+ { 31, 215, ppc_stbx },
+ { 44, -1, ppc_sth },
+ { 31, 918, ppc_sthbrx },
+ { 45, -1, ppc_sthu },
+ { 31, 439, ppc_sthux },
+ { 31, 407, ppc_sthx },
+ { 47, -1, ppc_stmw },
+ { 31, 725, ppc_stswi },
+ { 31, 661, ppc_stswx },
+ { 36, -1, ppc_stw },
+ { 31, 662, ppc_stwbrx },
+ { 31, 150, ppc_stwcx_rc },
+ { 37, -1, ppc_stwu },
+ { 31, 183, ppc_stwux },
+ { 31, 151, ppc_stwx },
+ { 31, 40, ppc_subfx },
+ { 31, 40 | 512, ppc_subfx },
+ { 31, 8, ppc_subfcx },
+ { 31, 8 | 512, ppc_subfcx },
+ { 31, 136, ppc_subfex },
+ { 31, 136 | 512, ppc_subfex },
+ { 8, -1, ppc_subfic },
+ { 31, 232, ppc_subfmex },
+ { 31, 232 | 512, ppc_subfmex },
+ { 31, 200, ppc_subfzex },
+ { 31, 200 | 512, ppc_subfzex },
+ { 31, 598, ppc_sync },
+ { 31, 4, ppc_tw },
+ { 3, -1, ppc_twi },
+ { 31, 316, ppc_xorx },
+ { 26, -1, ppc_xori },
+ { 27, -1, ppc_xoris }
+};
+
+#endif /* __PPC_OPS_H__ */
diff --git a/trunk/src/emu/cpu/powerpc/ppccom.c b/trunk/src/emu/cpu/powerpc/ppccom.c
new file mode 100644
index 00000000000..a8d659e93ed
--- /dev/null
+++ b/trunk/src/emu/cpu/powerpc/ppccom.c
@@ -0,0 +1,2231 @@
+/***************************************************************************
+
+ ppccom.c
+
+ Common PowerPC definitions and functions
+
+***************************************************************************/
+
+#include "emu.h"
+#include "ppccom.h"
+
+
+/***************************************************************************
+ DEBUGGING
+***************************************************************************/
+
+#define PRINTF_SPU (0)
+#define PRINTF_DECREMENTER (0)
+
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define DOUBLE_SIGN (U64(0x8000000000000000))
+#define DOUBLE_EXP (U64(0x7ff0000000000000))
+#define DOUBLE_FRAC (U64(0x000fffffffffffff))
+#define DOUBLE_ZERO (0)
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static TIMER_CALLBACK( ppc4xx_fit_callback );
+static TIMER_CALLBACK( ppc4xx_pit_callback );
+static TIMER_CALLBACK( ppc4xx_spu_callback );
+static TIMER_CALLBACK( decrementer_int_callback );
+
+static void ppc4xx_set_irq_line(powerpc_state *ppc, UINT32 bitmask, int state);
+
+static void ppc4xx_dma_update_irq_states(powerpc_state *ppc);
+static int ppc4xx_dma_fetch_transmit_byte(powerpc_state *ppc, int dmachan, UINT8 *byte);
+static int ppc4xx_dma_handle_receive_byte(powerpc_state *ppc, int dmachan, UINT8 byte);
+static void ppc4xx_dma_exec(powerpc_state *ppc, int dmachan);
+
+static void ppc4xx_spu_update_irq_states(powerpc_state *ppc);
+static void ppc4xx_spu_timer_reset(powerpc_state *ppc);
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ page_access_allowed - return true if we are
+ allowed to access memory based on the type
+ of access and the protection bits
+-------------------------------------------------*/
+
+INLINE int page_access_allowed(int transtype, UINT8 key, UINT8 protbits)
+{
+ if (key == 0)
+ return (transtype == TRANSLATE_WRITE) ? (protbits != 3) : TRUE;
+ else
+ return (transtype == TRANSLATE_WRITE) ? (protbits == 2) : (protbits != 0);
+}
+
+
+/*-------------------------------------------------
+ get_cr - return the current CR value
+-------------------------------------------------*/
+
+INLINE UINT32 get_cr(powerpc_state *ppc)
+{
+ return ((ppc->cr[0] & 0x0f) << 28) |
+ ((ppc->cr[1] & 0x0f) << 24) |
+ ((ppc->cr[2] & 0x0f) << 20) |
+ ((ppc->cr[3] & 0x0f) << 16) |
+ ((ppc->cr[4] & 0x0f) << 12) |
+ ((ppc->cr[5] & 0x0f) << 8) |
+ ((ppc->cr[6] & 0x0f) << 4) |
+ ((ppc->cr[7] & 0x0f) << 0);
+}
+
+
+/*-------------------------------------------------
+ set_cr - set the current CR value
+-------------------------------------------------*/
+
+INLINE void set_cr(powerpc_state *ppc, UINT32 value)
+{
+ ppc->cr[0] = value >> 28;
+ ppc->cr[1] = value >> 24;
+ ppc->cr[2] = value >> 20;
+ ppc->cr[3] = value >> 16;
+ ppc->cr[4] = value >> 12;
+ ppc->cr[5] = value >> 8;
+ ppc->cr[6] = value >> 4;
+ ppc->cr[7] = value >> 0;
+}
+
+
+/*-------------------------------------------------
+ get_xer - return the current XER value
+-------------------------------------------------*/
+
+INLINE UINT32 get_xer(powerpc_state *ppc)
+{
+ return ppc->spr[SPR_XER] | (ppc->xerso << 31);
+}
+
+
+/*-------------------------------------------------
+ set_xer - set the current XER value
+-------------------------------------------------*/
+
+INLINE void set_xer(powerpc_state *ppc, UINT32 value)
+{
+ ppc->spr[SPR_XER] = value & ~XER_SO;
+ ppc->xerso = value >> 31;
+}
+
+
+/*-------------------------------------------------
+ get_timebase - return the current timebase
+ value
+-------------------------------------------------*/
+
+INLINE UINT64 get_timebase(powerpc_state *ppc)
+{
+ if (!ppc->tb_divisor)
+ {
+ return (ppc->device->total_cycles() - ppc->tb_zero_cycles);
+ }
+
+ return (ppc->device->total_cycles() - ppc->tb_zero_cycles) / ppc->tb_divisor;
+}
+
+
+/*-------------------------------------------------
+ set_timebase - set the timebase
+-------------------------------------------------*/
+
+INLINE void set_timebase(powerpc_state *ppc, UINT64 newtb)
+{
+ ppc->tb_zero_cycles = ppc->device->total_cycles() - newtb * ppc->tb_divisor;
+}
+
+
+/*-------------------------------------------------
+ get_decremeter - return the current
+ decrementer value
+-------------------------------------------------*/
+
+INLINE UINT32 get_decrementer(powerpc_state *ppc)
+{
+ INT64 cycles_until_zero = ppc->dec_zero_cycles - ppc->device->total_cycles();
+ cycles_until_zero = MAX(cycles_until_zero, 0);
+
+ if (!ppc->tb_divisor)
+ {
+ return 0;
+ }
+
+ return cycles_until_zero / ppc->tb_divisor;
+}
+
+
+/*-------------------------------------------------
+ set_decrementer - set the decremeter
+-------------------------------------------------*/
+
+INLINE void set_decrementer(powerpc_state *ppc, UINT32 newdec)
+{
+ UINT64 cycles_until_done = ((UINT64)newdec + 1) * ppc->tb_divisor;
+ UINT32 curdec = get_decrementer(ppc);
+
+ if (!ppc->tb_divisor)
+ {
+ return;
+ }
+
+ if (PRINTF_DECREMENTER)
+ {
+ UINT64 total = ppc->device->total_cycles();
+ mame_printf_debug("set_decrementer: olddec=%08X newdec=%08X divisor=%d totalcyc=%08X%08X timer=%08X%08X\n",
+ curdec, newdec, ppc->tb_divisor,
+ (UINT32)(total >> 32), (UINT32)total, (UINT32)(cycles_until_done >> 32), (UINT32)cycles_until_done);
+ }
+
+ ppc->dec_zero_cycles = ppc->device->total_cycles() + cycles_until_done;
+ ppc->decrementer_int_timer->adjust(ppc->device->cycles_to_attotime(cycles_until_done));
+
+ if ((INT32)curdec >= 0 && (INT32)newdec < 0)
+ ppc->irq_pending |= 0x02;
+}
+
+
+/*-------------------------------------------------
+ is_nan_double - is a double value a NaN
+-------------------------------------------------*/
+
+INLINE int is_nan_double(double x)
+{
+ UINT64 xi = *(UINT64*)&x;
+ return( ((xi & DOUBLE_EXP) == DOUBLE_EXP) &&
+ ((xi & DOUBLE_FRAC) != DOUBLE_ZERO) );
+}
+
+
+/*-------------------------------------------------
+ is_qnan_double - is a double value a
+ quiet NaN
+-------------------------------------------------*/
+
+INLINE int is_qnan_double(double x)
+{
+ UINT64 xi = *(UINT64*)&x;
+ return( ((xi & DOUBLE_EXP) == DOUBLE_EXP) &&
+ ((xi & U64(0x0007fffffffffff)) == U64(0x000000000000000)) &&
+ ((xi & U64(0x000800000000000)) == U64(0x000800000000000)) );
+}
+
+
+/*-------------------------------------------------
+ is_snan_double - is a double value a
+ signaling NaN
+-------------------------------------------------*/
+
+INLINE int is_snan_double(double x)
+{
+ UINT64 xi = *(UINT64*)&x;
+ return( ((xi & DOUBLE_EXP) == DOUBLE_EXP) &&
+ ((xi & DOUBLE_FRAC) != DOUBLE_ZERO) &&
+ ((xi & U64(0x0008000000000000)) == DOUBLE_ZERO) );
+}
+
+
+/*-------------------------------------------------
+ is_infinity_double - is a double value
+ infinity
+-------------------------------------------------*/
+
+INLINE int is_infinity_double(double x)
+{
+ UINT64 xi = *(UINT64*)&x;
+ return( ((xi & DOUBLE_EXP) == DOUBLE_EXP) &&
+ ((xi & DOUBLE_FRAC) == DOUBLE_ZERO) );
+}
+
+
+/*-------------------------------------------------
+ is_normalized_double - is a double value
+ normalized
+-------------------------------------------------*/
+
+INLINE int is_normalized_double(double x)
+{
+ UINT64 exp;
+ UINT64 xi = *(UINT64*)&x;
+ exp = (xi & DOUBLE_EXP) >> 52;
+
+ return (exp >= 1) && (exp <= 2046);
+}
+
+
+/*-------------------------------------------------
+ is_denormalized_double - is a double value
+ denormalized
+-------------------------------------------------*/
+
+INLINE int is_denormalized_double(double x)
+{
+ UINT64 xi = *(UINT64*)&x;
+ return( ((xi & DOUBLE_EXP) == 0) &&
+ ((xi & DOUBLE_FRAC) != DOUBLE_ZERO) );
+}
+
+
+/*-------------------------------------------------
+ sign_double - return sign of a double value
+-------------------------------------------------*/
+
+INLINE int sign_double(double x)
+{
+ UINT64 xi = *(UINT64*)&x;
+ return ((xi & DOUBLE_SIGN) != 0);
+}
+
+
+
+/***************************************************************************
+ INITIALIZATION AND SHUTDOWN
+***************************************************************************/
+
+/*-------------------------------------------------
+ ppccom_init - initialize the powerpc_state
+ structure based on the configured type
+-------------------------------------------------*/
+
+void ppccom_init(powerpc_state *ppc, powerpc_flavor flavor, UINT8 cap, int tb_divisor, legacy_cpu_device *device, device_irq_callback irqcallback)
+{
+ const powerpc_config *config = (const powerpc_config *)device->static_config();
+
+ /* initialize based on the config */
+ memset(ppc, 0, sizeof(*ppc));
+ ppc->flavor = flavor;
+ ppc->cap = cap;
+ ppc->cache_line_size = 32;
+ ppc->tb_divisor = tb_divisor;
+ ppc->cpu_clock = device->clock();
+ ppc->irq_callback = irqcallback;
+ ppc->device = device;
+ ppc->program = device->space(AS_PROGRAM);
+ ppc->direct = &ppc->program->direct();
+ ppc->system_clock = (config != NULL) ? config->bus_frequency : device->clock();
+ ppc->tb_divisor = (ppc->tb_divisor * device->clock() + ppc->system_clock / 2 - 1) / ppc->system_clock;
+ ppc->codexor = 0;
+ if (!(cap & PPCCAP_4XX) && device->space_config()->m_endianness != ENDIANNESS_NATIVE)
+ ppc->codexor = 4;
+
+ /* allocate the virtual TLB */
+ ppc->vtlb = vtlb_alloc(device, AS_PROGRAM, (cap & PPCCAP_603_MMU) ? PPC603_FIXED_TLB_ENTRIES : 0, POWERPC_TLB_ENTRIES);
+
+ /* allocate a timer for the compare interrupt */
+ if ((cap & PPCCAP_OEA) && (ppc->tb_divisor))
+ ppc->decrementer_int_timer = device->machine().scheduler().timer_alloc(FUNC(decrementer_int_callback), ppc);
+
+ /* and for the 4XX interrupts if needed */
+ if (cap & PPCCAP_4XX)
+ {
+ ppc->fit_timer = device->machine().scheduler().timer_alloc(FUNC(ppc4xx_fit_callback), ppc);
+ ppc->pit_timer = device->machine().scheduler().timer_alloc(FUNC(ppc4xx_pit_callback), ppc);
+ ppc->spu.timer = device->machine().scheduler().timer_alloc(FUNC(ppc4xx_spu_callback), ppc);
+ }
+
+ /* register for save states */
+ device->save_item(NAME(ppc->pc));
+ device->save_item(NAME(ppc->r));
+ device->save_item(NAME(ppc->f));
+ device->save_item(NAME(ppc->cr));
+ device->save_item(NAME(ppc->xerso));
+ device->save_item(NAME(ppc->fpscr));
+ device->save_item(NAME(ppc->msr));
+ device->save_item(NAME(ppc->sr));
+ device->save_item(NAME(ppc->spr));
+ device->save_item(NAME(ppc->dcr));
+ if (cap & PPCCAP_4XX)
+ {
+ device->save_item(NAME(ppc->spu.regs));
+ device->save_item(NAME(ppc->spu.txbuf));
+ device->save_item(NAME(ppc->spu.rxbuf));
+ device->save_item(NAME(ppc->spu.rxbuffer));
+ device->save_item(NAME(ppc->spu.rxin));
+ device->save_item(NAME(ppc->spu.rxout));
+ device->save_item(NAME(ppc->pit_reload));
+ device->save_item(NAME(ppc->irqstate));
+ }
+ if (cap & PPCCAP_603_MMU)
+ {
+ device->save_item(NAME(ppc->mmu603_cmp));
+ device->save_item(NAME(ppc->mmu603_hash));
+ device->save_item(NAME(ppc->mmu603_r));
+ }
+ device->save_item(NAME(ppc->irq_pending));
+ device->save_item(NAME(ppc->tb_zero_cycles));
+ device->save_item(NAME(ppc->dec_zero_cycles));
+}
+
+
+/*-------------------------------------------------
+ ppccom_exit - common cleanup/exit
+-------------------------------------------------*/
+
+void ppccom_exit(powerpc_state *ppc)
+{
+ if (ppc->vtlb != NULL)
+ vtlb_free(ppc->vtlb);
+}
+
+
+/*-------------------------------------------------
+ ppccom_reset - reset the state of all the
+ registers
+-------------------------------------------------*/
+
+void ppccom_reset(powerpc_state *ppc)
+{
+ int tlbindex;
+
+ /* initialize the OEA state */
+ if (ppc->cap & PPCCAP_OEA)
+ {
+ /* PC to the reset vector; MSR has IP set to start */
+ ppc->pc = 0xfff00100;
+ ppc->msr = MSROEA_IP;
+
+ /* reset the decrementer */
+ ppc->dec_zero_cycles = ppc->device->total_cycles();
+ if (ppc->tb_divisor)
+ {
+ decrementer_int_callback(ppc->device->machine(), ppc, 0);
+ }
+ }
+
+ /* initialize the 4XX state */
+ if (ppc->cap & PPCCAP_4XX)
+ {
+ /* PC to the last word; MSR to 0 */
+ ppc->pc = 0xfffffffc;
+ ppc->msr = 0;
+
+ /* reset the SPU status */
+ ppc->spr[SPR4XX_TCR] &= ~PPC4XX_TCR_WRC_MASK;
+ ppc->spu.regs[SPU4XX_LINE_STATUS] = 0x06;
+ }
+
+ /* initialize the 602 HID0 register */
+ if (ppc->flavor == PPC_MODEL_602)
+ ppc->spr[SPR603_HID0] = 1;
+
+ /* time base starts here */
+ ppc->tb_zero_cycles = ppc->device->total_cycles();
+
+ /* clear interrupts */
+ ppc->irq_pending = 0;
+
+ /* flush the TLB */
+ vtlb_flush_dynamic(ppc->vtlb);
+ if (ppc->cap & PPCCAP_603_MMU)
+ for (tlbindex = 0; tlbindex < PPC603_FIXED_TLB_ENTRIES; tlbindex++)
+ vtlb_load(ppc->vtlb, tlbindex, 0, 0, 0);
+}
+
+
+/*-------------------------------------------------
+ ppccom_dasm - handle disassembly for a
+ CPU
+-------------------------------------------------*/
+
+offs_t ppccom_dasm(powerpc_state *ppc, char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram)
+{
+ extern offs_t ppc_dasm_one(char *buffer, UINT32 pc, UINT32 op);
+ UINT32 op = *(UINT32 *)oprom;
+ op = BIG_ENDIANIZE_INT32(op);
+ return ppc_dasm_one(buffer, pc, op);
+}
+
+
+
+/***************************************************************************
+ TLB HANDLING
+***************************************************************************/
+
+/*-------------------------------------------------
+ ppccom_translate_address_internal - translate
+ an address from logical to physical; shared
+ between external requests and internal TLB
+ filling
+-------------------------------------------------*/
+
+static UINT32 ppccom_translate_address_internal(powerpc_state *ppc, int intention, offs_t *address)
+{
+ int transpriv = ((intention & TRANSLATE_USER_MASK) == 0); // 1 for supervisor, 0 for user
+ int transtype = intention & TRANSLATE_TYPE_MASK;
+ offs_t hash, hashbase, hashmask;
+ int batbase, batnum, hashnum;
+ UINT32 segreg;
+
+ /* 4xx case: "TLB" really just caches writes and checks compare registers */
+ if (ppc->cap & PPCCAP_4XX)
+ {
+ /* we don't support the MMU of the 403GCX */
+ if (ppc->flavor == PPC_MODEL_403GCX && (ppc->msr & MSROEA_DR))
+ fatalerror("MMU enabled but not supported!");
+
+ /* only check if PE is enabled */
+ if (transtype == TRANSLATE_WRITE && (ppc->msr & MSR4XX_PE))
+ {
+ /* are we within one of the protection ranges? */
+ int inrange1 = ((*address >> 12) >= (ppc->spr[SPR4XX_PBL1] >> 12) && (*address >> 12) < (ppc->spr[SPR4XX_PBU1] >> 12));
+ int inrange2 = ((*address >> 12) >= (ppc->spr[SPR4XX_PBL2] >> 12) && (*address >> 12) < (ppc->spr[SPR4XX_PBU2] >> 12));
+
+ /* if PX == 1, writes are only allowed OUTSIDE of the bounds */
+ if (((ppc->msr & MSR4XX_PX) && (inrange1 || inrange2)) || (!(ppc->msr & MSR4XX_PX) && (!inrange1 && !inrange2)))
+ return 0x002;
+ }
+ *address &= 0x7fffffff;
+ return 0x001;
+ }
+
+ /* only applies if we support the OEA */
+ if (!(ppc->cap & PPCCAP_OEA))
+ return 0x001;
+
+ /* also no translation necessary if translation is disabled */
+ if ((transtype == TRANSLATE_FETCH && (ppc->msr & MSROEA_IR) == 0) || (transtype != TRANSLATE_FETCH && (ppc->msr & MSROEA_DR) == 0))
+ return 0x001;
+
+ /* first scan the appropriate BAT */
+ if (ppc->cap & PPCCAP_601BAT)
+ {
+ for (batnum = 0; batnum < 4; batnum++)
+ {
+ UINT32 upper = ppc->spr[SPROEA_IBAT0U + 2*batnum + 0];
+ UINT32 lower = ppc->spr[SPROEA_IBAT0U + 2*batnum + 1];
+ int privbit = ((intention & TRANSLATE_USER_MASK) == 0) ? 3 : 2;
+
+// printf("bat %d upper = %08x privbit %d\n", batnum, upper, privbit);
+
+ // is this pair valid?
+ if (lower & 0x40)
+ {
+ UINT32 mask = (~lower & 0x3f) << 17;
+ UINT32 addrout;
+ UINT32 key = (upper >> privbit) & 1;
+
+ /* check for a hit against this bucket */
+ if ((*address & 0xfffe0000) == (upper & 0xfffe0000))
+ {
+ /* verify protection; if we fail, return false and indicate a protection violation */
+ if (!page_access_allowed(transtype, key, upper & 3))
+ {
+ return DSISR_PROTECTED | ((transtype == TRANSLATE_WRITE) ? DSISR_STORE : 0);
+ }
+
+ /* otherwise we're good */
+ addrout = (lower & 0xff100000) | (*address & ~0xfffe0000);
+ addrout |= ((*address & mask) | (lower & mask));
+ *address = addrout; // top 9 bits from top 9 of PBN
+ return 0x001;
+ }
+ }
+ }
+ }
+ else
+ {
+ batbase = (transtype == TRANSLATE_FETCH) ? SPROEA_IBAT0U : SPROEA_DBAT0U;
+
+ for (batnum = 0; batnum < 4; batnum++)
+ {
+ UINT32 upper = ppc->spr[batbase + 2*batnum + 0];
+
+ /* check user/supervisor valid bit */
+ if ((upper >> transpriv) & 0x01)
+ {
+ UINT32 mask = (~upper << 15) & 0xfffe0000;
+
+ /* check for a hit against this bucket */
+ if ((*address & mask) == (upper & mask))
+ {
+ UINT32 lower = ppc->spr[batbase + 2*batnum + 1];
+
+ /* verify protection; if we fail, return false and indicate a protection violation */
+ if (!page_access_allowed(transtype, 1, lower & 3))
+ {
+ return DSISR_PROTECTED | ((transtype == TRANSLATE_WRITE) ? DSISR_STORE : 0);
+ }
+
+ /* otherwise we're good */
+ *address = (lower & mask) | (*address & ~mask);
+ return 0x001;
+ }
+ }
+ }
+ }
+
+ /* look up the segment register */
+ segreg = ppc->sr[*address >> 28];
+ if (transtype == TRANSLATE_FETCH && (segreg & 0x10000000))
+ return DSISR_PROTECTED | ((transtype == TRANSLATE_WRITE) ? DSISR_STORE : 0);
+
+ /* check for memory-forced I/O */
+ if (ppc->cap & PPCCAP_MFIOC)
+ {
+ if ((transtype != TRANSLATE_FETCH) && ((segreg & 0x87f00000) == 0x87f00000))
+ {
+ *address = ((segreg & 0xf)<<28) | (*address & 0x0fffffff);
+ return 1;
+ }
+ else if (segreg & 0x80000000)
+ {
+ fatalerror("PPC: Unhandled segment register %08x with T=1\n", segreg);
+ }
+ }
+
+ /* get hash table information from SD1 */
+ hashbase = ppc->spr[SPROEA_SDR1] & 0xffff0000;
+ hashmask = ((ppc->spr[SPROEA_SDR1] & 0x1ff) << 16) | 0xffff;
+ hash = (segreg & 0x7ffff) ^ ((*address >> 12) & 0xffff);
+
+ /* if we're simulating the 603 MMU, fill in the data and stop here */
+ if (ppc->cap & PPCCAP_603_MMU)
+ {
+ UINT32 entry = vtlb_table(ppc->vtlb)[*address >> 12];
+ ppc->mmu603_cmp = 0x80000000 | ((segreg & 0xffffff) << 7) | (0 << 6) | ((*address >> 22) & 0x3f);
+ ppc->mmu603_hash[0] = hashbase | ((hash << 6) & hashmask);
+ ppc->mmu603_hash[1] = hashbase | ((~hash << 6) & hashmask);
+ if ((entry & (VTLB_FLAG_FIXED | VTLB_FLAG_VALID)) == (VTLB_FLAG_FIXED | VTLB_FLAG_VALID))
+ {
+ *address = (entry & 0xfffff000) | (*address & 0x00000fff);
+ return 0x001;
+ }
+ return DSISR_NOT_FOUND | ((transtype == TRANSLATE_WRITE) ? DSISR_STORE : 0);
+ }
+
+ /* loop twice over hashes */
+ for (hashnum = 0; hashnum < 2; hashnum++)
+ {
+ offs_t ptegaddr = hashbase | ((hash << 6) & hashmask);
+ UINT32 *ptegptr = (UINT32 *)ppc->program->get_read_ptr(ptegaddr);
+
+ /* should only have valid memory here, but make sure */
+ if (ptegptr != NULL)
+ {
+ UINT32 targetupper = 0x80000000 | ((segreg & 0xffffff) << 7) | (hashnum << 6) | ((*address >> 22) & 0x3f);
+ int ptenum;
+
+ /* scan PTEs */
+ for (ptenum = 0; ptenum < 8; ptenum++)
+ if (ptegptr[BYTE_XOR_BE(ptenum * 2)] == targetupper)
+ {
+ UINT32 pteglower = ptegptr[BYTE_XOR_BE(ptenum * 2 + 1)];
+
+ /* verify protection; if we fail, return false and indicate a protection violation */
+ if (!page_access_allowed(transtype, (segreg >> (29 + transpriv)) & 1, pteglower & 3))
+ return DSISR_PROTECTED | ((transtype == TRANSLATE_WRITE) ? DSISR_STORE : 0);
+
+ /* update page table bits */
+ if (!(intention & TRANSLATE_DEBUG_MASK))
+ {
+ pteglower |= 0x100;
+ if (transtype == TRANSLATE_WRITE)
+ pteglower |= 0x080;
+ ptegptr[BYTE_XOR_BE(ptenum * 2 + 1)] = pteglower;
+ }
+
+ /* otherwise we're good */
+ *address = (pteglower & 0xfffff000) | (*address & 0x00000fff);
+ return (pteglower >> 7) & 1;
+ }
+ }
+
+ /* invert the hash after the first round */
+ hash = ~hash;
+ }
+
+ /* we failed to find any match: not found */
+ return DSISR_NOT_FOUND | ((transtype == TRANSLATE_WRITE) ? DSISR_STORE : 0);
+}
+
+
+/*-------------------------------------------------
+ ppccom_translate_address - translate an address
+ from logical to physical
+-------------------------------------------------*/
+
+int ppccom_translate_address(powerpc_state *ppc, address_spacenum space, int intention, offs_t *address)
+{
+ /* only applies to the program address space */
+ if (space != AS_PROGRAM)
+ return TRUE;
+
+ /* translation is successful if the internal routine returns 0 or 1 */
+ return (ppccom_translate_address_internal(ppc, intention, address) <= 1);
+}
+
+
+/*-------------------------------------------------
+ ppccom_tlb_fill - handle a missing TLB entry
+-------------------------------------------------*/
+
+void ppccom_tlb_fill(powerpc_state *ppc)
+{
+ vtlb_fill(ppc->vtlb, ppc->param0, ppc->param1);
+}
+
+
+/*-------------------------------------------------
+ ppccom_tlb_flush - flush the entire TLB,
+ including fixed entries
+-------------------------------------------------*/
+
+void ppccom_tlb_flush(powerpc_state *ppc)
+{
+ vtlb_flush_dynamic(ppc->vtlb);
+}
+
+
+
+/***************************************************************************
+ OPCODE HANDLING
+***************************************************************************/
+
+/*-------------------------------------------------
+ ppccom_execute_tlbie - execute a TLBIE
+ instruction
+-------------------------------------------------*/
+
+void ppccom_execute_tlbie(powerpc_state *ppc)
+{
+ vtlb_flush_address(ppc->vtlb, ppc->param0);
+}
+
+
+/*-------------------------------------------------
+ ppccom_execute_tlbia - execute a TLBIA
+ instruction
+-------------------------------------------------*/
+
+void ppccom_execute_tlbia(powerpc_state *ppc)
+{
+ vtlb_flush_dynamic(ppc->vtlb);
+}
+
+
+/*-------------------------------------------------
+ ppccom_execute_tlbl - execute a TLBLD/TLBLI
+ instruction
+-------------------------------------------------*/
+
+void ppccom_execute_tlbl(powerpc_state *ppc)
+{
+ UINT32 address = ppc->param0;
+ int isitlb = ppc->param1;
+ vtlb_entry flags = 0;
+ int entrynum;
+
+ /* determine entry number; we use rand() for associativity */
+ entrynum = ((address >> 12) & 0x1f) | (ppc->device->machine().rand() & 0x20) | (isitlb ? 0x40 : 0);
+
+ /* determine the flags */
+ flags = VTLB_FLAG_VALID | VTLB_READ_ALLOWED | VTLB_FETCH_ALLOWED;
+ if (ppc->spr[SPR603_RPA] & 0x80)
+ flags |= VTLB_WRITE_ALLOWED;
+ if (isitlb)
+ flags |= VTLB_FETCH_ALLOWED;
+
+ /* load the entry */
+ vtlb_load(ppc->vtlb, entrynum, 1, address, (ppc->spr[SPR603_RPA] & 0xfffff000) | flags);
+}
+
+
+/*-------------------------------------------------
+ ppccom_execute_mftb - execute an MFTB
+ instruction
+-------------------------------------------------*/
+
+void ppccom_execute_mftb(powerpc_state *ppc)
+{
+ switch (ppc->param0)
+ {
+ /* user mode timebase read */
+ case SPRVEA_TBL_R:
+ ppc->param1 = get_timebase(ppc);
+ break;
+ case SPRVEA_TBU_R:
+ ppc->param1 = get_timebase(ppc) >> 32;
+ break;
+ }
+}
+
+
+/*-------------------------------------------------
+ ppccom_execute_mfspr - execute an MFSPR
+ instruction
+-------------------------------------------------*/
+
+void ppccom_execute_mfspr(powerpc_state *ppc)
+{
+ /* handle OEA SPRs */
+ if (ppc->cap & PPCCAP_OEA)
+ {
+ switch (ppc->param0)
+ {
+ /* read-through no-ops */
+ case SPROEA_DSISR:
+ case SPROEA_DAR:
+ case SPROEA_SDR1:
+ case SPROEA_SRR0:
+ case SPROEA_SRR1:
+ case SPROEA_EAR:
+ case SPROEA_IBAT0L:
+ case SPROEA_IBAT0U:
+ case SPROEA_IBAT1L:
+ case SPROEA_IBAT1U:
+ case SPROEA_IBAT2L:
+ case SPROEA_IBAT2U:
+ case SPROEA_IBAT3L:
+ case SPROEA_IBAT3U:
+ case SPROEA_DBAT0L:
+ case SPROEA_DBAT0U:
+ case SPROEA_DBAT1L:
+ case SPROEA_DBAT1U:
+ case SPROEA_DBAT2L:
+ case SPROEA_DBAT2U:
+ case SPROEA_DBAT3L:
+ case SPROEA_DBAT3U:
+ case SPROEA_DABR:
+ ppc->param1 = ppc->spr[ppc->param0];
+ return;
+
+ /* decrementer */
+ case SPROEA_DEC:
+ ppc->param1 = get_decrementer(ppc);
+ return;
+ }
+ }
+
+ /* handle 603 SPRs */
+ if (ppc->cap & PPCCAP_603_MMU)
+ {
+ switch (ppc->param0)
+ {
+ /* read-through no-ops */
+ case SPR603_DMISS:
+ case SPR603_DCMP:
+ case SPR603_HASH1:
+ case SPR603_HASH2:
+ case SPR603_IMISS:
+ case SPR603_ICMP:
+ case SPR603_RPA:
+ case SPR603_HID0:
+ case SPR603_HID1:
+ case SPR603_IABR:
+ case SPR603_HID2:
+ ppc->param1 = ppc->spr[ppc->param0];
+ return;
+
+ /* timebase */
+ case SPR603_TBL_R:
+ ppc->param1 = get_timebase(ppc);
+ return;
+ case SPR603_TBU_R:
+ ppc->param1 = (get_timebase(ppc) >> 32) & 0xffffff;
+ return;
+ }
+ }
+
+ /* handle 4XX SPRs */
+ if (ppc->cap & PPCCAP_4XX)
+ {
+ switch (ppc->param0)
+ {
+ /* read-through no-ops */
+ case SPR4XX_EVPR:
+ case SPR4XX_ESR:
+ case SPR4XX_SRR0:
+ case SPR4XX_SRR1:
+ case SPR4XX_SRR2:
+ case SPR4XX_SRR3:
+ case SPR4XX_TCR:
+ case SPR4XX_TSR:
+ case SPR4XX_IAC1:
+ case SPR4XX_IAC2:
+ case SPR4XX_DAC1:
+ case SPR4XX_DAC2:
+ case SPR4XX_DCCR:
+ case SPR4XX_ICCR:
+ case SPR4XX_PBL1:
+ case SPR4XX_PBU1:
+ case SPR4XX_PBL2:
+ case SPR4XX_PBU2:
+ ppc->param1 = ppc->spr[ppc->param0];
+ return;
+
+ /* timebase */
+ case SPR4XX_TBLO:
+ case SPR4XX_TBLU:
+ ppc->param1 = get_timebase(ppc);
+ return;
+ case SPR4XX_TBHI:
+ case SPR4XX_TBHU:
+ ppc->param1 = (get_timebase(ppc) >> 32) & 0xffffff;
+ return;
+ }
+ }
+
+ /* default handling */
+ mame_printf_debug("SPR %03X read\n", ppc->param0);
+ ppc->param1 = ppc->spr[ppc->param0];
+}
+
+
+/*-------------------------------------------------
+ ppccom_execute_mtspr - execute an MTSPR
+ instruction
+-------------------------------------------------*/
+
+void ppccom_execute_mtspr(powerpc_state *ppc)
+{
+ /* handle OEA SPRs */
+ if (ppc->cap & PPCCAP_OEA)
+ {
+ switch (ppc->param0)
+ {
+ /* write-through no-ops */
+ case SPROEA_DSISR:
+ case SPROEA_DAR:
+ case SPROEA_SRR0:
+ case SPROEA_SRR1:
+ case SPROEA_EAR:
+ case SPROEA_DABR:
+ ppc->spr[ppc->param0] = ppc->param1;
+ return;
+
+ /* registers that affect the memory map */
+ case SPROEA_SDR1:
+ case SPROEA_IBAT0L:
+ case SPROEA_IBAT0U:
+ case SPROEA_IBAT1L:
+ case SPROEA_IBAT1U:
+ case SPROEA_IBAT2L:
+ case SPROEA_IBAT2U:
+ case SPROEA_IBAT3L:
+ case SPROEA_IBAT3U:
+ case SPROEA_DBAT0L:
+ case SPROEA_DBAT0U:
+ case SPROEA_DBAT1L:
+ case SPROEA_DBAT1U:
+ case SPROEA_DBAT2L:
+ case SPROEA_DBAT2U:
+ case SPROEA_DBAT3L:
+ case SPROEA_DBAT3U:
+ ppc->spr[ppc->param0] = ppc->param1;
+ ppccom_tlb_flush(ppc);
+ return;
+
+ /* decrementer */
+ case SPROEA_DEC:
+ set_decrementer(ppc, ppc->param1);
+ return;
+ }
+ }
+
+ /* handle 603 SPRs */
+ if (ppc->cap & PPCCAP_603_MMU)
+ {
+ switch (ppc->param0)
+ {
+ /* read-only */
+ case SPR603_DMISS:
+ case SPR603_DCMP:
+ case SPR603_HASH1:
+ case SPR603_HASH2:
+ case SPR603_IMISS:
+ case SPR603_ICMP:
+ return;
+
+ /* write-through no-ops */
+ case SPR603_RPA:
+ case SPR603_HID0:
+ case SPR603_HID1:
+ case SPR603_IABR:
+ case SPR603_HID2:
+ ppc->spr[ppc->param0] = ppc->param1;
+ return;
+
+ /* timebase */
+ case SPR603_TBL_W:
+ set_timebase(ppc, (get_timebase(ppc) & ~U64(0xffffffff00000000)) | ppc->param1);
+ return;
+ case SPR603_TBU_W:
+ set_timebase(ppc, (get_timebase(ppc) & ~U64(0x00000000ffffffff)) | ((UINT64)ppc->param1 << 32));
+ return;
+ }
+ }
+
+ /* handle 4XX SPRs */
+ if (ppc->cap & PPCCAP_4XX)
+ {
+ UINT32 oldval = ppc->spr[ppc->param0];
+ switch (ppc->param0)
+ {
+ /* write-through no-ops */
+ case SPR4XX_EVPR:
+ case SPR4XX_ESR:
+ case SPR4XX_DCCR:
+ case SPR4XX_ICCR:
+ case SPR4XX_SRR0:
+ case SPR4XX_SRR1:
+ case SPR4XX_SRR2:
+ case SPR4XX_SRR3:
+ ppc->spr[ppc->param0] = ppc->param1;
+ return;
+
+ /* registers that affect the memory map */
+ case SPR4XX_PBL1:
+ case SPR4XX_PBU1:
+ case SPR4XX_PBL2:
+ case SPR4XX_PBU2:
+ ppc->spr[ppc->param0] = ppc->param1;
+ ppccom_tlb_flush(ppc);
+ return;
+
+ /* timer control register */
+ case SPR4XX_TCR:
+ ppc->spr[SPR4XX_TCR] = ppc->param1 | (oldval & PPC4XX_TCR_WRC_MASK);
+ if ((oldval ^ ppc->spr[SPR4XX_TCR]) & PPC4XX_TCR_FIE)
+ ppc4xx_fit_callback(ppc->device->machine(), ppc, FALSE);
+ if ((oldval ^ ppc->spr[SPR4XX_TCR]) & PPC4XX_TCR_PIE)
+ ppc4xx_pit_callback(ppc->device->machine(), ppc, FALSE);
+ return;
+
+ /* timer status register */
+ case SPR4XX_TSR:
+ ppc->spr[SPR4XX_TSR] &= ~ppc->param1;
+ ppc4xx_set_irq_line(ppc, 0, 0);
+ return;
+
+ /* PIT */
+ case SPR4XX_PIT:
+ ppc->spr[SPR4XX_PIT] = ppc->param1;
+ ppc->pit_reload = ppc->param1;
+ ppc4xx_pit_callback(ppc->device->machine(), ppc, FALSE);
+ return;
+
+ /* timebase */
+ case SPR4XX_TBLO:
+ set_timebase(ppc, (get_timebase(ppc) & ~U64(0x00ffffff00000000)) | ppc->param1);
+ return;
+ case SPR4XX_TBHI:
+ set_timebase(ppc, (get_timebase(ppc) & ~U64(0x00000000ffffffff)) | ((UINT64)(ppc->param1 & 0x00ffffff) << 32));
+ return;
+ }
+ }
+
+ /* default handling */
+ mame_printf_debug("SPR %03X write = %08X\n", ppc->param0, ppc->param1);
+ ppc->spr[ppc->param0] = ppc->param1;
+}
+
+
+/*-------------------------------------------------
+ ppccom_execute_mfdcr - execute an MFDCR
+ instruction
+-------------------------------------------------*/
+
+void ppccom_execute_mfdcr(powerpc_state *ppc)
+{
+ /* handle various DCRs */
+ switch (ppc->param0)
+ {
+ /* read-through no-ops */
+ case DCR4XX_BR0:
+ case DCR4XX_BR1:
+ case DCR4XX_BR2:
+ case DCR4XX_BR3:
+ case DCR4XX_BR4:
+ case DCR4XX_BR5:
+ case DCR4XX_BR6:
+ case DCR4XX_BR7:
+ case DCR4XX_BESR:
+ case DCR4XX_DMASR:
+ case DCR4XX_DMACT0:
+ case DCR4XX_DMADA0:
+ case DCR4XX_DMASA0:
+ case DCR4XX_DMACC0:
+ case DCR4XX_DMACR0:
+ case DCR4XX_DMACT1:
+ case DCR4XX_DMADA1:
+ case DCR4XX_DMASA1:
+ case DCR4XX_DMACC1:
+ case DCR4XX_DMACR1:
+ case DCR4XX_DMACT2:
+ case DCR4XX_DMADA2:
+ case DCR4XX_DMASA2:
+ case DCR4XX_DMACC2:
+ case DCR4XX_DMACR2:
+ case DCR4XX_DMACT3:
+ case DCR4XX_DMADA3:
+ case DCR4XX_DMASA3:
+ case DCR4XX_DMACC3:
+ case DCR4XX_DMACR3:
+ case DCR4XX_EXIER:
+ case DCR4XX_EXISR:
+ case DCR4XX_IOCR:
+ ppc->param1 = ppc->dcr[ppc->param0];
+ return;
+ }
+
+ /* default handling */
+ mame_printf_debug("DCR %03X read\n", ppc->param0);
+ if (ppc->param0 < ARRAY_LENGTH(ppc->dcr))
+ ppc->param1 = ppc->dcr[ppc->param0];
+ else
+ ppc->param1 = 0;
+}
+
+
+/*-------------------------------------------------
+ ppccom_execute_mtdcr - execute an MTDCR
+ instruction
+-------------------------------------------------*/
+
+void ppccom_execute_mtdcr(powerpc_state *ppc)
+{
+ UINT8 oldval;
+
+ /* handle various DCRs */
+ switch (ppc->param0)
+ {
+ /* write-through no-ops */
+ case DCR4XX_BR0:
+ case DCR4XX_BR1:
+ case DCR4XX_BR2:
+ case DCR4XX_BR3:
+ case DCR4XX_BR4:
+ case DCR4XX_BR5:
+ case DCR4XX_BR6:
+ case DCR4XX_BR7:
+ case DCR4XX_BESR:
+ case DCR4XX_DMACT0:
+ case DCR4XX_DMADA0:
+ case DCR4XX_DMASA0:
+ case DCR4XX_DMACC0:
+ case DCR4XX_DMACT1:
+ case DCR4XX_DMADA1:
+ case DCR4XX_DMASA1:
+ case DCR4XX_DMACC1:
+ case DCR4XX_DMACT2:
+ case DCR4XX_DMADA2:
+ case DCR4XX_DMASA2:
+ case DCR4XX_DMACC2:
+ case DCR4XX_DMACT3:
+ case DCR4XX_DMADA3:
+ case DCR4XX_DMASA3:
+ case DCR4XX_DMACC3:
+ ppc->dcr[ppc->param0] = ppc->param1;
+ return;
+
+ /* DMA status */
+ case DCR4XX_DMASR:
+ ppc->dcr[DCR4XX_DMASR] &= ~(ppc->param1 & 0xfff80070);
+ ppc4xx_dma_update_irq_states(ppc);
+ return;
+
+ /* interrupt enables */
+ case DCR4XX_EXIER:
+ ppc->dcr[DCR4XX_EXIER] = ppc->param1;
+ ppc4xx_set_irq_line(ppc, 0, 0);
+ return;
+
+ /* interrupt clear */
+ case DCR4XX_EXISR:
+ ppc->dcr[ppc->param0] &= ~ppc->param1;
+ ppc4xx_set_irq_line(ppc, 0, 0);
+ return;
+
+ /* DMA controls */
+ case DCR4XX_DMACR0:
+ case DCR4XX_DMACR1:
+ case DCR4XX_DMACR2:
+ case DCR4XX_DMACR3:
+ ppc->dcr[ppc->param0] = ppc->param1;
+ if (ppc->param1 & PPC4XX_DMACR_CE)
+ ppc4xx_dma_exec(ppc, (ppc->param0 - DCR4XX_DMACR0) / 8);
+ ppc4xx_dma_update_irq_states(ppc);
+ return;
+
+ /* I/O control */
+ case DCR4XX_IOCR:
+ oldval = ppc->dcr[ppc->param0];
+ ppc->dcr[ppc->param0] = ppc->param1;
+ if ((oldval ^ ppc->param1) & 0x02)
+ ppc4xx_spu_timer_reset(ppc);
+ return;
+ }
+
+ /* default handling */
+ mame_printf_debug("DCR %03X write = %08X\n", ppc->param0, ppc->param1);
+ if (ppc->param0 < ARRAY_LENGTH(ppc->dcr))
+ ppc->dcr[ppc->param0] = ppc->param1;
+}
+
+
+
+/***************************************************************************
+ FLOATING POINT STATUS FLAGS HANDLING
+***************************************************************************/
+
+/*-------------------------------------------------
+ ppccom_update_fprf - update the FPRF field
+ of the FPSCR register
+-------------------------------------------------*/
+
+void ppccom_update_fprf(powerpc_state *ppc)
+{
+ UINT32 fprf;
+ double f = ppc->f[ppc->param0];
+
+ if (is_qnan_double(f))
+ {
+ fprf = 0x11;
+ }
+ else if (is_infinity_double(f))
+ {
+ if (sign_double(f)) /* -Infinity */
+ fprf = 0x09;
+ else /* +Infinity */
+ fprf = 0x05;
+ }
+ else if (is_normalized_double(f))
+ {
+ if (sign_double(f)) /* -Normalized */
+ fprf = 0x08;
+ else /* +Normalized */
+ fprf = 0x04;
+ }
+ else if (is_denormalized_double(f))
+ {
+ if (sign_double(f)) /* -Denormalized */
+ fprf = 0x18;
+ else /* +Denormalized */
+ fprf = 0x14;
+ }
+ else
+ {
+ if (sign_double(f)) /* -Zero */
+ fprf = 0x12;
+ else /* +Zero */
+ fprf = 0x02;
+ }
+
+ ppc->fpscr &= ~0x0001f000;
+ ppc->fpscr |= fprf << 12;
+}
+
+
+
+/***************************************************************************
+ COMMON GET/SET INFO
+***************************************************************************/
+
+/*-------------------------------------------------
+ ppccom_set_info - set information about
+ a PowerPC CPU
+-------------------------------------------------*/
+
+void ppccom_set_info(powerpc_state *ppc, UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + PPC_IRQ: ppc->irq_pending = (ppc->irq_pending & ~1) | (info->i != CLEAR_LINE); break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + PPC_PC: ppc->pc = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_MSR: ppc->msr = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_CR: set_cr(ppc, info->i); break;
+ case CPUINFO_INT_REGISTER + PPC_LR: ppc->spr[SPR_LR] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_CTR: ppc->spr[SPR_CTR] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_XER: set_xer(ppc, info->i); break;
+ case CPUINFO_INT_REGISTER + PPC_SRR0: ppc->spr[SPROEA_SRR0] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_SRR1: ppc->spr[SPROEA_SRR1] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_SPRG0: ppc->spr[SPROEA_SPRG0] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_SPRG1: ppc->spr[SPROEA_SPRG1] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_SPRG2: ppc->spr[SPROEA_SPRG2] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_SPRG3: ppc->spr[SPROEA_SPRG3] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_SDR1: ppc->spr[SPROEA_SDR1] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_EXIER: ppc->dcr[DCR4XX_EXIER] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_EXISR: ppc->dcr[DCR4XX_EXISR] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_EVPR: ppc->spr[SPR4XX_EVPR] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_IOCR: ppc->dcr[DCR4XX_IOCR] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_TBL: set_timebase(ppc, (get_timebase(ppc) & ~U64(0x00ffffff00000000)) | info->i); break;
+ case CPUINFO_INT_REGISTER + PPC_TBH: set_timebase(ppc, (get_timebase(ppc) & ~U64(0x00000000ffffffff)) | ((UINT64)(ppc->param1 & 0x00ffffff) << 32)); break;
+ case CPUINFO_INT_REGISTER + PPC_DEC: set_decrementer(ppc, info->i); break;
+
+ case CPUINFO_INT_REGISTER + PPC_R0: ppc->r[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R1: ppc->r[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R2: ppc->r[2] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R3: ppc->r[3] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R4: ppc->r[4] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R5: ppc->r[5] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R6: ppc->r[6] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R7: ppc->r[7] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R8: ppc->r[8] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R9: ppc->r[9] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R10: ppc->r[10] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R11: ppc->r[11] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R12: ppc->r[12] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R13: ppc->r[13] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R14: ppc->r[14] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R15: ppc->r[15] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R16: ppc->r[16] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R17: ppc->r[17] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R18: ppc->r[18] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R19: ppc->r[19] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R20: ppc->r[20] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R21: ppc->r[21] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R22: ppc->r[22] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R23: ppc->r[23] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R24: ppc->r[24] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R25: ppc->r[25] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R26: ppc->r[26] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R27: ppc->r[27] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R28: ppc->r[28] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R29: ppc->r[29] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R30: ppc->r[30] = info->i; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + PPC_R31: ppc->r[31] = info->i; break;
+
+ case CPUINFO_INT_REGISTER + PPC_F0: ppc->f[0] = *(double *)&info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_F1: ppc->f[1] = *(double *)&info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_F2: ppc->f[2] = *(double *)&info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_F3: ppc->f[3] = *(double *)&info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_F4: ppc->f[4] = *(double *)&info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_F5: ppc->f[5] = *(double *)&info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_F6: ppc->f[6] = *(double *)&info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_F7: ppc->f[7] = *(double *)&info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_F8: ppc->f[8] = *(double *)&info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_F9: ppc->f[9] = *(double *)&info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_F10: ppc->f[10] = *(double *)&info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_F11: ppc->f[11] = *(double *)&info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_F12: ppc->f[12] = *(double *)&info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_F13: ppc->f[13] = *(double *)&info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_F14: ppc->f[14] = *(double *)&info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_F15: ppc->f[15] = *(double *)&info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_F16: ppc->f[16] = *(double *)&info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_F17: ppc->f[17] = *(double *)&info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_F18: ppc->f[18] = *(double *)&info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_F19: ppc->f[19] = *(double *)&info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_F20: ppc->f[20] = *(double *)&info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_F21: ppc->f[21] = *(double *)&info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_F22: ppc->f[22] = *(double *)&info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_F23: ppc->f[23] = *(double *)&info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_F24: ppc->f[24] = *(double *)&info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_F25: ppc->f[25] = *(double *)&info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_F26: ppc->f[26] = *(double *)&info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_F27: ppc->f[27] = *(double *)&info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_F28: ppc->f[28] = *(double *)&info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_F29: ppc->f[29] = *(double *)&info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_F30: ppc->f[30] = *(double *)&info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_F31: ppc->f[31] = *(double *)&info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_FPSCR: ppc->fpscr = info->i; break;
+ }
+}
+
+
+/*-------------------------------------------------
+ ppccom_get_info - get information about
+ a PowerPC CPU
+-------------------------------------------------*/
+
+void ppccom_get_info(powerpc_state *ppc, UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: /* provided by core */ break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 1; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 40; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 64; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case CPUINFO_INT_LOGADDR_WIDTH_PROGRAM: info->i = 32; break;
+ case CPUINFO_INT_PAGE_SHIFT_PROGRAM: info->i = POWERPC_MIN_PAGE_SHIFT;break;
+
+ case CPUINFO_INT_INPUT_STATE + PPC_IRQ: info->i = ppc->irq_pending ? ASSERT_LINE : CLEAR_LINE; break;
+
+ case CPUINFO_INT_PREVIOUSPC: /* optionally implemented */ break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + PPC_PC: info->i = ppc->pc; break;
+ case CPUINFO_INT_REGISTER + PPC_MSR: info->i = ppc->msr; break;
+ case CPUINFO_INT_REGISTER + PPC_CR: info->i = get_cr(ppc); break;
+ case CPUINFO_INT_REGISTER + PPC_LR: info->i = ppc->spr[SPR_LR]; break;
+ case CPUINFO_INT_REGISTER + PPC_CTR: info->i = ppc->spr[SPR_CTR]; break;
+ case CPUINFO_INT_REGISTER + PPC_XER: info->i = get_xer(ppc); break;
+ case CPUINFO_INT_REGISTER + PPC_SRR0: info->i = ppc->spr[SPROEA_SRR0]; break;
+ case CPUINFO_INT_REGISTER + PPC_SRR1: info->i = ppc->spr[SPROEA_SRR1]; break;
+ case CPUINFO_INT_REGISTER + PPC_SPRG0: info->i = ppc->spr[SPROEA_SPRG0]; break;
+ case CPUINFO_INT_REGISTER + PPC_SPRG1: info->i = ppc->spr[SPROEA_SPRG1]; break;
+ case CPUINFO_INT_REGISTER + PPC_SPRG2: info->i = ppc->spr[SPROEA_SPRG2]; break;
+ case CPUINFO_INT_REGISTER + PPC_SPRG3: info->i = ppc->spr[SPROEA_SPRG3]; break;
+ case CPUINFO_INT_REGISTER + PPC_SDR1: info->i = ppc->spr[SPROEA_SDR1]; break;
+ case CPUINFO_INT_REGISTER + PPC_EXIER: info->i = ppc->dcr[DCR4XX_EXIER]; break;
+ case CPUINFO_INT_REGISTER + PPC_EXISR: info->i = ppc->dcr[DCR4XX_EXISR]; break;
+ case CPUINFO_INT_REGISTER + PPC_EVPR: info->i = ppc->spr[SPR4XX_EVPR]; break;
+ case CPUINFO_INT_REGISTER + PPC_IOCR: info->i = ppc->dcr[DCR4XX_IOCR]; break;
+ case CPUINFO_INT_REGISTER + PPC_TBH: info->i = get_timebase(ppc) >> 32; break;
+ case CPUINFO_INT_REGISTER + PPC_TBL: info->i = (UINT32)get_timebase(ppc); break;
+ case CPUINFO_INT_REGISTER + PPC_DEC: info->i = get_decrementer(ppc); break;
+
+ case CPUINFO_INT_REGISTER + PPC_R0: info->i = ppc->r[0]; break;
+ case CPUINFO_INT_REGISTER + PPC_R1: info->i = ppc->r[1]; break;
+ case CPUINFO_INT_REGISTER + PPC_R2: info->i = ppc->r[2]; break;
+ case CPUINFO_INT_REGISTER + PPC_R3: info->i = ppc->r[3]; break;
+ case CPUINFO_INT_REGISTER + PPC_R4: info->i = ppc->r[4]; break;
+ case CPUINFO_INT_REGISTER + PPC_R5: info->i = ppc->r[5]; break;
+ case CPUINFO_INT_REGISTER + PPC_R6: info->i = ppc->r[6]; break;
+ case CPUINFO_INT_REGISTER + PPC_R7: info->i = ppc->r[7]; break;
+ case CPUINFO_INT_REGISTER + PPC_R8: info->i = ppc->r[8]; break;
+ case CPUINFO_INT_REGISTER + PPC_R9: info->i = ppc->r[9]; break;
+ case CPUINFO_INT_REGISTER + PPC_R10: info->i = ppc->r[10]; break;
+ case CPUINFO_INT_REGISTER + PPC_R11: info->i = ppc->r[11]; break;
+ case CPUINFO_INT_REGISTER + PPC_R12: info->i = ppc->r[12]; break;
+ case CPUINFO_INT_REGISTER + PPC_R13: info->i = ppc->r[13]; break;
+ case CPUINFO_INT_REGISTER + PPC_R14: info->i = ppc->r[14]; break;
+ case CPUINFO_INT_REGISTER + PPC_R15: info->i = ppc->r[15]; break;
+ case CPUINFO_INT_REGISTER + PPC_R16: info->i = ppc->r[16]; break;
+ case CPUINFO_INT_REGISTER + PPC_R17: info->i = ppc->r[17]; break;
+ case CPUINFO_INT_REGISTER + PPC_R18: info->i = ppc->r[18]; break;
+ case CPUINFO_INT_REGISTER + PPC_R19: info->i = ppc->r[19]; break;
+ case CPUINFO_INT_REGISTER + PPC_R20: info->i = ppc->r[20]; break;
+ case CPUINFO_INT_REGISTER + PPC_R21: info->i = ppc->r[21]; break;
+ case CPUINFO_INT_REGISTER + PPC_R22: info->i = ppc->r[22]; break;
+ case CPUINFO_INT_REGISTER + PPC_R23: info->i = ppc->r[23]; break;
+ case CPUINFO_INT_REGISTER + PPC_R24: info->i = ppc->r[24]; break;
+ case CPUINFO_INT_REGISTER + PPC_R25: info->i = ppc->r[25]; break;
+ case CPUINFO_INT_REGISTER + PPC_R26: info->i = ppc->r[26]; break;
+ case CPUINFO_INT_REGISTER + PPC_R27: info->i = ppc->r[27]; break;
+ case CPUINFO_INT_REGISTER + PPC_R28: info->i = ppc->r[28]; break;
+ case CPUINFO_INT_REGISTER + PPC_R29: info->i = ppc->r[29]; break;
+ case CPUINFO_INT_REGISTER + PPC_R30: info->i = ppc->r[30]; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + PPC_R31: info->i = ppc->r[31]; break;
+
+ case CPUINFO_INT_REGISTER + PPC_F0: info->i = *(UINT64 *)&ppc->f[0]; break;
+ case CPUINFO_INT_REGISTER + PPC_F1: info->i = *(UINT64 *)&ppc->f[1]; break;
+ case CPUINFO_INT_REGISTER + PPC_F2: info->i = *(UINT64 *)&ppc->f[2]; break;
+ case CPUINFO_INT_REGISTER + PPC_F3: info->i = *(UINT64 *)&ppc->f[3]; break;
+ case CPUINFO_INT_REGISTER + PPC_F4: info->i = *(UINT64 *)&ppc->f[4]; break;
+ case CPUINFO_INT_REGISTER + PPC_F5: info->i = *(UINT64 *)&ppc->f[5]; break;
+ case CPUINFO_INT_REGISTER + PPC_F6: info->i = *(UINT64 *)&ppc->f[6]; break;
+ case CPUINFO_INT_REGISTER + PPC_F7: info->i = *(UINT64 *)&ppc->f[7]; break;
+ case CPUINFO_INT_REGISTER + PPC_F8: info->i = *(UINT64 *)&ppc->f[8]; break;
+ case CPUINFO_INT_REGISTER + PPC_F9: info->i = *(UINT64 *)&ppc->f[9]; break;
+ case CPUINFO_INT_REGISTER + PPC_F10: info->i = *(UINT64 *)&ppc->f[10]; break;
+ case CPUINFO_INT_REGISTER + PPC_F11: info->i = *(UINT64 *)&ppc->f[11]; break;
+ case CPUINFO_INT_REGISTER + PPC_F12: info->i = *(UINT64 *)&ppc->f[12]; break;
+ case CPUINFO_INT_REGISTER + PPC_F13: info->i = *(UINT64 *)&ppc->f[13]; break;
+ case CPUINFO_INT_REGISTER + PPC_F14: info->i = *(UINT64 *)&ppc->f[14]; break;
+ case CPUINFO_INT_REGISTER + PPC_F15: info->i = *(UINT64 *)&ppc->f[15]; break;
+ case CPUINFO_INT_REGISTER + PPC_F16: info->i = *(UINT64 *)&ppc->f[16]; break;
+ case CPUINFO_INT_REGISTER + PPC_F17: info->i = *(UINT64 *)&ppc->f[17]; break;
+ case CPUINFO_INT_REGISTER + PPC_F18: info->i = *(UINT64 *)&ppc->f[18]; break;
+ case CPUINFO_INT_REGISTER + PPC_F19: info->i = *(UINT64 *)&ppc->f[19]; break;
+ case CPUINFO_INT_REGISTER + PPC_F20: info->i = *(UINT64 *)&ppc->f[20]; break;
+ case CPUINFO_INT_REGISTER + PPC_F21: info->i = *(UINT64 *)&ppc->f[21]; break;
+ case CPUINFO_INT_REGISTER + PPC_F22: info->i = *(UINT64 *)&ppc->f[22]; break;
+ case CPUINFO_INT_REGISTER + PPC_F23: info->i = *(UINT64 *)&ppc->f[23]; break;
+ case CPUINFO_INT_REGISTER + PPC_F24: info->i = *(UINT64 *)&ppc->f[24]; break;
+ case CPUINFO_INT_REGISTER + PPC_F25: info->i = *(UINT64 *)&ppc->f[25]; break;
+ case CPUINFO_INT_REGISTER + PPC_F26: info->i = *(UINT64 *)&ppc->f[26]; break;
+ case CPUINFO_INT_REGISTER + PPC_F27: info->i = *(UINT64 *)&ppc->f[27]; break;
+ case CPUINFO_INT_REGISTER + PPC_F28: info->i = *(UINT64 *)&ppc->f[28]; break;
+ case CPUINFO_INT_REGISTER + PPC_F29: info->i = *(UINT64 *)&ppc->f[29]; break;
+ case CPUINFO_INT_REGISTER + PPC_F30: info->i = *(UINT64 *)&ppc->f[30]; break;
+ case CPUINFO_INT_REGISTER + PPC_F31: info->i = *(UINT64 *)&ppc->f[31]; break;
+ case CPUINFO_INT_REGISTER + PPC_FPSCR: info->i = ppc->fpscr; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: /* provided by core */ break;
+ case CPUINFO_FCT_INIT: /* provided by core */ break;
+ case CPUINFO_FCT_RESET: /* provided by core */ break;
+ case CPUINFO_FCT_EXIT: /* provided by core */ break;
+ case CPUINFO_FCT_EXECUTE: /* provided by core */ break;
+ case CPUINFO_FCT_TRANSLATE: /* provided by core */ break;
+ case CPUINFO_FCT_DISASSEMBLE: /* provided by core */ break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &ppc->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "PowerPC"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "PowerPC"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "2.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: /* provided by core */ break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Aaron Giles"); break;
+
+ case CPUINFO_STR_FLAGS: strcpy(info->s, " "); break;
+
+ case CPUINFO_STR_REGISTER + PPC_PC: sprintf(info->s, "PC: %08X", ppc->pc); break;
+ case CPUINFO_STR_REGISTER + PPC_MSR: sprintf(info->s, "MSR:%08X", ppc->msr); break;
+ case CPUINFO_STR_REGISTER + PPC_CR: sprintf(info->s, "CR: %08X", get_cr(ppc)); break;
+ case CPUINFO_STR_REGISTER + PPC_LR: sprintf(info->s, "LR: %08X", ppc->spr[SPR_LR]); break;
+ case CPUINFO_STR_REGISTER + PPC_CTR: sprintf(info->s, "CTR:%08X", ppc->spr[SPR_CTR]); break;
+ case CPUINFO_STR_REGISTER + PPC_XER: sprintf(info->s, "XER:%08X", get_xer(ppc)); break;
+ case CPUINFO_STR_REGISTER + PPC_SRR0: sprintf(info->s, "SRR0: %08X", ppc->spr[SPROEA_SRR0]); break;
+ case CPUINFO_STR_REGISTER + PPC_SRR1: sprintf(info->s, "SRR1: %08X", ppc->spr[SPROEA_SRR1]); break;
+ case CPUINFO_STR_REGISTER + PPC_SPRG0: sprintf(info->s, "SPRG0: %08X", ppc->spr[SPROEA_SPRG0]); break;
+ case CPUINFO_STR_REGISTER + PPC_SPRG1: sprintf(info->s, "SPRG1: %08X", ppc->spr[SPROEA_SPRG1]); break;
+ case CPUINFO_STR_REGISTER + PPC_SPRG2: sprintf(info->s, "SPRG2: %08X", ppc->spr[SPROEA_SPRG2]); break;
+ case CPUINFO_STR_REGISTER + PPC_SPRG3: sprintf(info->s, "SPRG3: %08X", ppc->spr[SPROEA_SPRG3]); break;
+ case CPUINFO_STR_REGISTER + PPC_SDR1: sprintf(info->s, "SDR1: %08X", ppc->spr[SPROEA_SDR1]); break;
+ case CPUINFO_STR_REGISTER + PPC_EXIER: sprintf(info->s, "EXIER: %08X", ppc->dcr[DCR4XX_EXIER]); break;
+ case CPUINFO_STR_REGISTER + PPC_EXISR: sprintf(info->s, "EXISR: %08X", ppc->dcr[DCR4XX_EXISR]); break;
+ case CPUINFO_STR_REGISTER + PPC_EVPR: sprintf(info->s, "EVPR: %08X", ppc->spr[SPR4XX_EVPR]); break;
+ case CPUINFO_STR_REGISTER + PPC_IOCR: sprintf(info->s, "IOCR: %08X", ppc->dcr[DCR4XX_EXISR]); break;
+ case CPUINFO_STR_REGISTER + PPC_TBH: sprintf(info->s, "TBH: %08X", (UINT32)(get_timebase(ppc) >> 32)); break;
+ case CPUINFO_STR_REGISTER + PPC_TBL: sprintf(info->s, "TBL: %08X", (UINT32)get_timebase(ppc)); break;
+ case CPUINFO_STR_REGISTER + PPC_DEC: sprintf(info->s, "DEC: %08X", get_decrementer(ppc)); break;
+
+ case CPUINFO_STR_REGISTER + PPC_R0: sprintf(info->s, "R0: %08X", ppc->r[0]); break;
+ case CPUINFO_STR_REGISTER + PPC_R1: sprintf(info->s, "R1: %08X", ppc->r[1]); break;
+ case CPUINFO_STR_REGISTER + PPC_R2: sprintf(info->s, "R2: %08X", ppc->r[2]); break;
+ case CPUINFO_STR_REGISTER + PPC_R3: sprintf(info->s, "R3: %08X", ppc->r[3]); break;
+ case CPUINFO_STR_REGISTER + PPC_R4: sprintf(info->s, "R4: %08X", ppc->r[4]); break;
+ case CPUINFO_STR_REGISTER + PPC_R5: sprintf(info->s, "R5: %08X", ppc->r[5]); break;
+ case CPUINFO_STR_REGISTER + PPC_R6: sprintf(info->s, "R6: %08X", ppc->r[6]); break;
+ case CPUINFO_STR_REGISTER + PPC_R7: sprintf(info->s, "R7: %08X", ppc->r[7]); break;
+ case CPUINFO_STR_REGISTER + PPC_R8: sprintf(info->s, "R8: %08X", ppc->r[8]); break;
+ case CPUINFO_STR_REGISTER + PPC_R9: sprintf(info->s, "R9: %08X", ppc->r[9]); break;
+ case CPUINFO_STR_REGISTER + PPC_R10: sprintf(info->s, "R10:%08X", ppc->r[10]); break;
+ case CPUINFO_STR_REGISTER + PPC_R11: sprintf(info->s, "R11:%08X", ppc->r[11]); break;
+ case CPUINFO_STR_REGISTER + PPC_R12: sprintf(info->s, "R12:%08X", ppc->r[12]); break;
+ case CPUINFO_STR_REGISTER + PPC_R13: sprintf(info->s, "R13:%08X", ppc->r[13]); break;
+ case CPUINFO_STR_REGISTER + PPC_R14: sprintf(info->s, "R14:%08X", ppc->r[14]); break;
+ case CPUINFO_STR_REGISTER + PPC_R15: sprintf(info->s, "R15:%08X", ppc->r[15]); break;
+ case CPUINFO_STR_REGISTER + PPC_R16: sprintf(info->s, "R16:%08X", ppc->r[16]); break;
+ case CPUINFO_STR_REGISTER + PPC_R17: sprintf(info->s, "R17:%08X", ppc->r[17]); break;
+ case CPUINFO_STR_REGISTER + PPC_R18: sprintf(info->s, "R18:%08X", ppc->r[18]); break;
+ case CPUINFO_STR_REGISTER + PPC_R19: sprintf(info->s, "R19:%08X", ppc->r[19]); break;
+ case CPUINFO_STR_REGISTER + PPC_R20: sprintf(info->s, "R20:%08X", ppc->r[20]); break;
+ case CPUINFO_STR_REGISTER + PPC_R21: sprintf(info->s, "R21:%08X", ppc->r[21]); break;
+ case CPUINFO_STR_REGISTER + PPC_R22: sprintf(info->s, "R22:%08X", ppc->r[22]); break;
+ case CPUINFO_STR_REGISTER + PPC_R23: sprintf(info->s, "R23:%08X", ppc->r[23]); break;
+ case CPUINFO_STR_REGISTER + PPC_R24: sprintf(info->s, "R24:%08X", ppc->r[24]); break;
+ case CPUINFO_STR_REGISTER + PPC_R25: sprintf(info->s, "R25:%08X", ppc->r[25]); break;
+ case CPUINFO_STR_REGISTER + PPC_R26: sprintf(info->s, "R26:%08X", ppc->r[26]); break;
+ case CPUINFO_STR_REGISTER + PPC_R27: sprintf(info->s, "R27:%08X", ppc->r[27]); break;
+ case CPUINFO_STR_REGISTER + PPC_R28: sprintf(info->s, "R28:%08X", ppc->r[28]); break;
+ case CPUINFO_STR_REGISTER + PPC_R29: sprintf(info->s, "R29:%08X", ppc->r[29]); break;
+ case CPUINFO_STR_REGISTER + PPC_R30: sprintf(info->s, "R30:%08X", ppc->r[30]); break;
+ case CPUINFO_STR_REGISTER + PPC_R31: sprintf(info->s, "R31:%08X", ppc->r[31]); break;
+
+ case CPUINFO_STR_REGISTER + PPC_F0: sprintf(info->s, "F0: %12f", ppc->f[0]); break;
+ case CPUINFO_STR_REGISTER + PPC_F1: sprintf(info->s, "F1: %12f", ppc->f[1]); break;
+ case CPUINFO_STR_REGISTER + PPC_F2: sprintf(info->s, "F2: %12f", ppc->f[2]); break;
+ case CPUINFO_STR_REGISTER + PPC_F3: sprintf(info->s, "F3: %12f", ppc->f[3]); break;
+ case CPUINFO_STR_REGISTER + PPC_F4: sprintf(info->s, "F4: %12f", ppc->f[4]); break;
+ case CPUINFO_STR_REGISTER + PPC_F5: sprintf(info->s, "F5: %12f", ppc->f[5]); break;
+ case CPUINFO_STR_REGISTER + PPC_F6: sprintf(info->s, "F6: %12f", ppc->f[6]); break;
+ case CPUINFO_STR_REGISTER + PPC_F7: sprintf(info->s, "F7: %12f", ppc->f[7]); break;
+ case CPUINFO_STR_REGISTER + PPC_F8: sprintf(info->s, "F8: %12f", ppc->f[8]); break;
+ case CPUINFO_STR_REGISTER + PPC_F9: sprintf(info->s, "F9: %12f", ppc->f[9]); break;
+ case CPUINFO_STR_REGISTER + PPC_F10: sprintf(info->s, "F10:%12f", ppc->f[10]); break;
+ case CPUINFO_STR_REGISTER + PPC_F11: sprintf(info->s, "F11:%12f", ppc->f[11]); break;
+ case CPUINFO_STR_REGISTER + PPC_F12: sprintf(info->s, "F12:%12f", ppc->f[12]); break;
+ case CPUINFO_STR_REGISTER + PPC_F13: sprintf(info->s, "F13:%12f", ppc->f[13]); break;
+ case CPUINFO_STR_REGISTER + PPC_F14: sprintf(info->s, "F14:%12f", ppc->f[14]); break;
+ case CPUINFO_STR_REGISTER + PPC_F15: sprintf(info->s, "F15:%12f", ppc->f[15]); break;
+ case CPUINFO_STR_REGISTER + PPC_F16: sprintf(info->s, "F16:%12f", ppc->f[16]); break;
+ case CPUINFO_STR_REGISTER + PPC_F17: sprintf(info->s, "F17:%12f", ppc->f[17]); break;
+ case CPUINFO_STR_REGISTER + PPC_F18: sprintf(info->s, "F18:%12f", ppc->f[18]); break;
+ case CPUINFO_STR_REGISTER + PPC_F19: sprintf(info->s, "F19:%12f", ppc->f[19]); break;
+ case CPUINFO_STR_REGISTER + PPC_F20: sprintf(info->s, "F20:%12f", ppc->f[20]); break;
+ case CPUINFO_STR_REGISTER + PPC_F21: sprintf(info->s, "F21:%12f", ppc->f[21]); break;
+ case CPUINFO_STR_REGISTER + PPC_F22: sprintf(info->s, "F22:%12f", ppc->f[22]); break;
+ case CPUINFO_STR_REGISTER + PPC_F23: sprintf(info->s, "F23:%12f", ppc->f[23]); break;
+ case CPUINFO_STR_REGISTER + PPC_F24: sprintf(info->s, "F24:%12f", ppc->f[24]); break;
+ case CPUINFO_STR_REGISTER + PPC_F25: sprintf(info->s, "F25:%12f", ppc->f[25]); break;
+ case CPUINFO_STR_REGISTER + PPC_F26: sprintf(info->s, "F26:%12f", ppc->f[26]); break;
+ case CPUINFO_STR_REGISTER + PPC_F27: sprintf(info->s, "F27:%12f", ppc->f[27]); break;
+ case CPUINFO_STR_REGISTER + PPC_F28: sprintf(info->s, "F28:%12f", ppc->f[28]); break;
+ case CPUINFO_STR_REGISTER + PPC_F29: sprintf(info->s, "F29:%12f", ppc->f[29]); break;
+ case CPUINFO_STR_REGISTER + PPC_F30: sprintf(info->s, "F30:%12f", ppc->f[30]); break;
+ case CPUINFO_STR_REGISTER + PPC_F31: sprintf(info->s, "F31:%12f", ppc->f[31]); break;
+ case CPUINFO_STR_REGISTER + PPC_FPSCR: sprintf(info->s, "FPSCR:%08X", ppc->fpscr); break;
+ }
+}
+
+
+
+/***************************************************************************
+ OEA HELPERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ decrementer_int_callback - callback that fires
+ whenever a decrementer interrupt is generated
+-------------------------------------------------*/
+
+static TIMER_CALLBACK( decrementer_int_callback )
+{
+ powerpc_state *ppc = (powerpc_state *)ptr;
+ UINT64 cycles_until_next;
+
+ /* set the decrementer IRQ state */
+ ppc->irq_pending |= 0x02;
+
+ /* advance by another full rev */
+ ppc->dec_zero_cycles += (UINT64)ppc->tb_divisor << 32;
+ cycles_until_next = ppc->dec_zero_cycles - ppc->device->total_cycles();
+ ppc->decrementer_int_timer->adjust(ppc->device->cycles_to_attotime(cycles_until_next));
+}
+
+
+
+/***************************************************************************
+ EMBEDDED 4XX HELPERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ ppc4xx_set_irq_line - PowerPC 4XX-specific
+ IRQ line management
+-------------------------------------------------*/
+
+static void ppc4xx_set_irq_line(powerpc_state *ppc, UINT32 bitmask, int state)
+{
+ UINT32 oldstate = ppc->irqstate;
+ UINT32 levelmask;
+
+ /* set or clear the appropriate bit */
+ if (state != CLEAR_LINE)
+ ppc->irqstate |= bitmask;
+ else
+ ppc->irqstate &= ~bitmask;
+
+ /* if the state changed to on, edge trigger the interrupt */
+ if (((ppc->irqstate ^ oldstate) & bitmask) && (ppc->irqstate & bitmask))
+ ppc->dcr[DCR4XX_EXISR] |= bitmask;
+
+ /* pass through all level-triggered interrupts */
+ levelmask = PPC4XX_IRQ_BIT_CRITICAL | PPC4XX_IRQ_BIT_SPUR | PPC4XX_IRQ_BIT_SPUT;
+ levelmask |= PPC4XX_IRQ_BIT_JTAGR | PPC4XX_IRQ_BIT_JTAGT;
+ levelmask |= PPC4XX_IRQ_BIT_DMA0 | PPC4XX_IRQ_BIT_DMA1 | PPC4XX_IRQ_BIT_DMA2 | PPC4XX_IRQ_BIT_DMA3;
+ if (!(ppc->dcr[DCR4XX_IOCR] & 0x80000000)) levelmask |= PPC4XX_IRQ_BIT_EXT0;
+ if (!(ppc->dcr[DCR4XX_IOCR] & 0x20000000)) levelmask |= PPC4XX_IRQ_BIT_EXT1;
+ if (!(ppc->dcr[DCR4XX_IOCR] & 0x08000000)) levelmask |= PPC4XX_IRQ_BIT_EXT2;
+ if (!(ppc->dcr[DCR4XX_IOCR] & 0x02000000)) levelmask |= PPC4XX_IRQ_BIT_EXT3;
+ if (!(ppc->dcr[DCR4XX_IOCR] & 0x00800000)) levelmask |= PPC4XX_IRQ_BIT_EXT4;
+ ppc->dcr[DCR4XX_EXISR] = (ppc->dcr[DCR4XX_EXISR] & ~levelmask) | (ppc->irqstate & levelmask);
+
+ /* update the IRQ status */
+ ppc->irq_pending = ((ppc->dcr[DCR4XX_EXISR] & ppc->dcr[DCR4XX_EXIER]) != 0);
+ if ((ppc->spr[SPR4XX_TCR] & PPC4XX_TCR_FIE) && (ppc->spr[SPR4XX_TSR] & PPC4XX_TSR_FIS))
+ ppc->irq_pending = TRUE;
+ if ((ppc->spr[SPR4XX_TCR] & PPC4XX_TCR_PIE) && (ppc->spr[SPR4XX_TSR] & PPC4XX_TSR_PIS))
+ ppc->irq_pending = TRUE;
+}
+
+
+/*-------------------------------------------------
+ ppc4xx_get_irq_line - PowerPC 4XX-specific
+ IRQ line state getter
+-------------------------------------------------*/
+
+static int ppc4xx_get_irq_line(powerpc_state *ppc, UINT32 bitmask)
+{
+ return (ppc->irqstate & bitmask) ? ASSERT_LINE : CLEAR_LINE;
+}
+
+
+/*-------------------------------------------------
+ ppc4xx_dma_update_irq_states - update the IRQ
+ state for each DMA channel
+-------------------------------------------------*/
+
+static void ppc4xx_dma_update_irq_states(powerpc_state *ppc)
+{
+ int dmachan;
+
+ /* update the IRQ state for each DMA channel */
+ for (dmachan = 0; dmachan < 4; dmachan++)
+ if ((ppc->dcr[DCR4XX_DMACR0 + 8 * dmachan] & PPC4XX_DMACR_CIE) && (ppc->dcr[DCR4XX_DMASR] & (0x11 << (27 - dmachan))))
+ ppc4xx_set_irq_line(ppc, PPC4XX_IRQ_BIT_DMA(dmachan), ASSERT_LINE);
+ else
+ ppc4xx_set_irq_line(ppc, PPC4XX_IRQ_BIT_DMA(dmachan), CLEAR_LINE);
+}
+
+
+/*-------------------------------------------------
+ ppc4xx_dma_decrement_count - decrement the
+ count on a channel and interrupt if configured
+ to do so
+-------------------------------------------------*/
+
+static int ppc4xx_dma_decrement_count(powerpc_state *ppc, int dmachan)
+{
+ UINT32 *dmaregs = &ppc->dcr[8 * dmachan];
+
+ /* decrement the counter */
+ dmaregs[DCR4XX_DMACT0]--;
+
+ /* if non-zero, we keep going */
+ if ((dmaregs[DCR4XX_DMACT0] & 0xffff) != 0)
+ return FALSE;
+
+ /* set the complete bit and handle interrupts */
+ ppc->dcr[DCR4XX_DMASR] |= 1 << (31 - dmachan);
+// ppc->dcr[DCR4XX_DMASR] |= 1 << (27 - dmachan);
+ ppc4xx_dma_update_irq_states(ppc);
+ return TRUE;
+}
+
+
+/*-------------------------------------------------
+ ppc4xx_dma_fetch_transmit_byte - fetch a byte
+ to send to a peripheral
+-------------------------------------------------*/
+
+static int ppc4xx_dma_fetch_transmit_byte(powerpc_state *ppc, int dmachan, UINT8 *byte)
+{
+ UINT32 *dmaregs = &ppc->dcr[8 * dmachan];
+
+ /* if the channel is not enabled, fail */
+ if (!(dmaregs[DCR4XX_DMACR0] & PPC4XX_DMACR_CE))
+ return FALSE;
+
+ /* if no transfers remaining, fail */
+ if ((dmaregs[DCR4XX_DMACT0] & 0xffff) == 0)
+ return FALSE;
+
+ /* fetch the data */
+ *byte = ppc->program->read_byte(dmaregs[DCR4XX_DMADA0]++);
+ ppc4xx_dma_decrement_count(ppc, dmachan);
+ return TRUE;
+}
+
+
+/*-------------------------------------------------
+ ppc4xx_dma_handle_receive_byte - receive a byte
+ transmitted by a peripheral
+-------------------------------------------------*/
+
+static int ppc4xx_dma_handle_receive_byte(powerpc_state *ppc, int dmachan, UINT8 byte)
+{
+ UINT32 *dmaregs = &ppc->dcr[8 * dmachan];
+
+ /* if the channel is not enabled, fail */
+ if (!(dmaregs[DCR4XX_DMACR0] & PPC4XX_DMACR_CE))
+ return FALSE;
+
+ /* if no transfers remaining, fail */
+ if ((dmaregs[DCR4XX_DMACT0] & 0xffff) == 0)
+ return FALSE;
+
+ /* store the data */
+ ppc->program->write_byte(dmaregs[DCR4XX_DMADA0]++, byte);
+ ppc4xx_dma_decrement_count(ppc, dmachan);
+ return TRUE;
+}
+
+
+/*-------------------------------------------------
+ ppc4xx_dma_execute - execute a DMA operation
+ if one is pending
+-------------------------------------------------*/
+
+static void ppc4xx_dma_exec(powerpc_state *ppc, int dmachan)
+{
+ static const UINT8 dma_transfer_width[4] = { 1, 2, 4, 16 };
+ UINT32 *dmaregs = &ppc->dcr[8 * dmachan];
+ INT32 destinc, srcinc;
+ UINT8 width;
+
+ /* skip if not enabled */
+ if (!(dmaregs[DCR4XX_DMACR0] & PPC4XX_DMACR_CE))
+ return;
+
+ /* check for unsupported features */
+ if (!(dmaregs[DCR4XX_DMACR0] & PPC4XX_DMACR_TCE))
+ fatalerror("ppc4xx_dma_exec: DMA_TCE == 0");
+ if (dmaregs[DCR4XX_DMACR0] & PPC4XX_DMACR_CH)
+ fatalerror("ppc4xx_dma_exec: DMA chaining not implemented");
+
+ /* transfer mode */
+ switch ((dmaregs[DCR4XX_DMACR0] & PPC4XX_DMACR_TM_MASK) >> 21)
+ {
+ /* buffered mode DMA */
+ case 0:
+ /* nothing to do; this happens asynchronously and is driven by the SPU */
+ break;
+
+ /* fly-by mode DMA */
+ case 1:
+ fatalerror("ppc4xx_dma_exec: fly-by DMA not implemented");
+ break;
+
+ /* software initiated memory-to-memory mode DMA */
+ case 2:
+ width = dma_transfer_width[(dmaregs[DCR4XX_DMACR0] & PPC4XX_DMACR_PW_MASK) >> 26];
+ srcinc = (dmaregs[DCR4XX_DMACR0] & PPC4XX_DMACR_SAI) ? width : 0;
+ destinc = (dmaregs[DCR4XX_DMACR0] & PPC4XX_DMACR_DAI) ? width : 0;
+
+ switch (width)
+ {
+ /* byte transfer */
+ case 1:
+ do
+ {
+ ppc->program->write_byte(dmaregs[DCR4XX_DMADA0], ppc->program->read_byte(dmaregs[DCR4XX_DMASA0]));
+ dmaregs[DCR4XX_DMASA0] += srcinc;
+ dmaregs[DCR4XX_DMADA0] += destinc;
+ } while (!ppc4xx_dma_decrement_count(ppc, dmachan));
+ break;
+
+ /* word transfer */
+ case 2:
+ do
+ {
+ ppc->program->write_word(dmaregs[DCR4XX_DMADA0], ppc->program->read_word(dmaregs[DCR4XX_DMASA0]));
+ dmaregs[DCR4XX_DMASA0] += srcinc;
+ dmaregs[DCR4XX_DMADA0] += destinc;
+ } while (!ppc4xx_dma_decrement_count(ppc, dmachan));
+ break;
+
+ /* dword transfer */
+ case 4:
+ do
+ {
+ ppc->program->write_dword(dmaregs[DCR4XX_DMADA0], ppc->program->read_dword(dmaregs[DCR4XX_DMASA0]));
+ dmaregs[DCR4XX_DMASA0] += srcinc;
+ dmaregs[DCR4XX_DMADA0] += destinc;
+ } while (!ppc4xx_dma_decrement_count(ppc, dmachan));
+ break;
+
+ /* 16-byte transfer */
+ case 16:
+ do
+ {
+ ppc->program->write_qword(dmaregs[DCR4XX_DMADA0], ppc->program->read_qword(dmaregs[DCR4XX_DMASA0]));
+ ppc->program->write_qword(dmaregs[DCR4XX_DMADA0] + 8, ppc->program->read_qword(dmaregs[DCR4XX_DMASA0] + 8));
+ dmaregs[DCR4XX_DMASA0] += srcinc;
+ dmaregs[DCR4XX_DMADA0] += destinc;
+ } while (!ppc4xx_dma_decrement_count(ppc, dmachan));
+ break;
+ }
+ break;
+
+ /* hardware initiated memory-to-memory mode DMA */
+ case 3:
+ fatalerror("ppc4xx_dma_exec: HW mem-to-mem DMA not implemented");
+ break;
+ }
+}
+
+
+/*-------------------------------------------------
+ ppc4xx_fit_callback - FIT timer callback
+-------------------------------------------------*/
+
+static TIMER_CALLBACK( ppc4xx_fit_callback )
+{
+ powerpc_state *ppc = (powerpc_state *)ptr;
+
+ /* if this is a real callback and we are enabled, signal an interrupt */
+ if (param)
+ {
+ ppc->spr[SPR4XX_TSR] |= PPC4XX_TSR_FIS;
+ ppc4xx_set_irq_line(ppc, 0, 0);
+ }
+
+ /* update ourself for the next interval if we are enabled */
+ if (ppc->spr[SPR4XX_TCR] & PPC4XX_TCR_FIE)
+ {
+ UINT32 timebase = get_timebase(ppc);
+ UINT32 interval = 0x200 << (4 * ((ppc->spr[SPR4XX_TCR] & PPC4XX_TCR_FP_MASK) >> 24));
+ UINT32 target = (timebase + interval) & ~(interval - 1);
+ ppc->fit_timer->adjust(ppc->device->cycles_to_attotime((target + 1 - timebase) / ppc->tb_divisor), TRUE);
+ }
+
+ /* otherwise, turn ourself off */
+ else
+ ppc->fit_timer->adjust(attotime::never, FALSE);
+}
+
+
+/*-------------------------------------------------
+ ppc4xx_pit_callback - PIT timer callback
+-------------------------------------------------*/
+
+static TIMER_CALLBACK( ppc4xx_pit_callback )
+{
+ powerpc_state *ppc = (powerpc_state *)ptr;
+
+ /* if this is a real callback and we are enabled, signal an interrupt */
+ if (param)
+ {
+ ppc->spr[SPR4XX_TSR] |= PPC4XX_TSR_PIS;
+ ppc4xx_set_irq_line(ppc, 0, 0);
+ }
+
+ /* update ourself for the next interval if we are enabled and we are either being
+ forced to update, or we are in auto-reload mode */
+ if ((ppc->spr[SPR4XX_TCR] & PPC4XX_TCR_PIE) && ppc->pit_reload != 0 && (!param || (ppc->spr[SPR4XX_TCR] & PPC4XX_TCR_ARE)))
+ {
+ UINT32 timebase = get_timebase(ppc);
+ UINT32 interval = ppc->pit_reload;
+ UINT32 target = timebase + interval;
+ ppc->pit_timer->adjust(ppc->device->cycles_to_attotime((target + 1 - timebase) / ppc->tb_divisor), TRUE);
+ }
+
+ /* otherwise, turn ourself off */
+ else
+ ppc->pit_timer->adjust(attotime::never, FALSE);
+}
+
+
+/*-------------------------------------------------
+ ppc4xx_spu_update_irq_states - update the IRQ
+ state for the SPU
+-------------------------------------------------*/
+
+static void ppc4xx_spu_update_irq_states(powerpc_state *ppc)
+{
+ /* check for receive buffer full interrupt */
+ if ((ppc->spu.regs[SPU4XX_RX_COMMAND] & 0x60) == 0x20 && (ppc->spu.regs[SPU4XX_LINE_STATUS] & 0x80))
+ ppc4xx_set_irq_line(ppc, PPC4XX_IRQ_BIT_SPUR, ASSERT_LINE);
+
+ /* check for receive error interrupt */
+ else if ((ppc->spu.regs[SPU4XX_RX_COMMAND] & 0x10) && (ppc->spu.regs[SPU4XX_LINE_STATUS] & 0x78))
+ ppc4xx_set_irq_line(ppc, PPC4XX_IRQ_BIT_SPUR, ASSERT_LINE);
+
+ /* clear otherwise */
+ else
+ ppc4xx_set_irq_line(ppc, PPC4XX_IRQ_BIT_SPUR, CLEAR_LINE);
+
+ /* check for transmit buffer empty interrupt */
+ if ((ppc->spu.regs[SPU4XX_TX_COMMAND] & 0x60) == 0x20 && (ppc->spu.regs[SPU4XX_LINE_STATUS] & 0x04))
+ ppc4xx_set_irq_line(ppc, PPC4XX_IRQ_BIT_SPUT, ASSERT_LINE);
+
+ /* check for shift register empty interrupt */
+ else if ((ppc->spu.regs[SPU4XX_TX_COMMAND] & 0x10) && (ppc->spu.regs[SPU4XX_LINE_STATUS] & 0x02))
+ ppc4xx_set_irq_line(ppc, PPC4XX_IRQ_BIT_SPUT, ASSERT_LINE);
+
+ /* clear otherwise */
+ else
+ ppc4xx_set_irq_line(ppc, PPC4XX_IRQ_BIT_SPUT, CLEAR_LINE);
+}
+
+
+/*-------------------------------------------------
+ ppc4xx_spu_rx_data - serial port data receive
+-------------------------------------------------*/
+
+static void ppc4xx_spu_rx_data(powerpc_state *ppc, UINT8 data)
+{
+ UINT32 new_rxin;
+
+ /* fail if we are going to overflow */
+ new_rxin = (ppc->spu.rxin + 1) % ARRAY_LENGTH(ppc->spu.rxbuffer);
+ if (new_rxin == ppc->spu.rxout)
+ fatalerror("ppc4xx_spu_rx_data: buffer overrun!");
+
+ /* store the data and accept the new in index */
+ ppc->spu.rxbuffer[ppc->spu.rxin] = data;
+ ppc->spu.rxin = new_rxin;
+}
+
+
+/*-------------------------------------------------
+ ppc4xx_spu_timer_reset - reset and recompute
+ the transmit/receive timer
+-------------------------------------------------*/
+
+static void ppc4xx_spu_timer_reset(powerpc_state *ppc)
+{
+ UINT8 enabled = (ppc->spu.regs[SPU4XX_RX_COMMAND] | ppc->spu.regs[SPU4XX_TX_COMMAND]) & 0x80;
+
+ /* if we're enabled, reset at the current baud rate */
+ if (enabled)
+ {
+ attotime clockperiod = attotime::from_hz((ppc->dcr[DCR4XX_IOCR] & 0x02) ? 3686400 : 33333333);
+ int divisor = ((ppc->spu.regs[SPU4XX_BAUD_DIVISOR_H] * 256 + ppc->spu.regs[SPU4XX_BAUD_DIVISOR_L]) & 0xfff) + 1;
+ int bpc = 7 + ((ppc->spu.regs[SPU4XX_CONTROL] & 8) >> 3) + 1 + (ppc->spu.regs[SPU4XX_CONTROL] & 1);
+ attotime charperiod = clockperiod * (divisor * 16 * bpc);
+ ppc->spu.timer->adjust(charperiod, 0, charperiod);
+ if (PRINTF_SPU)
+ printf("ppc4xx_spu_timer_reset: baud rate = %.0f\n", ATTOSECONDS_TO_HZ(charperiod.attoseconds) * bpc);
+ }
+
+ /* otherwise, disable the timer */
+ else
+ ppc->spu.timer->adjust(attotime::never);
+}
+
+
+/*-------------------------------------------------
+ ppc4xx_spu_callback - serial port send/receive
+ timer
+-------------------------------------------------*/
+
+static TIMER_CALLBACK( ppc4xx_spu_callback )
+{
+ powerpc_state *ppc = (powerpc_state *)ptr;
+
+ /* transmit enabled? */
+ if (ppc->spu.regs[SPU4XX_TX_COMMAND] & 0x80)
+ {
+ int operation = (ppc->spu.regs[SPU4XX_TX_COMMAND] >> 5) & 3;
+
+ /* if we have data to transmit, do it now */
+ if (!(ppc->spu.regs[SPU4XX_LINE_STATUS] & 0x04))
+ {
+ /* if we have a transmit handler, send it that way */
+ if (ppc->spu.tx_handler != NULL)
+ (*ppc->spu.tx_handler)(ppc->device, ppc->spu.txbuf);
+
+ /* indicate that we have moved it to the shift register */
+ ppc->spu.regs[SPU4XX_LINE_STATUS] |= 0x04;
+ ppc->spu.regs[SPU4XX_LINE_STATUS] &= ~0x02;
+ }
+
+ /* otherwise, clear the shift register */
+ else if (!(ppc->spu.regs[SPU4XX_LINE_STATUS] & 0x02))
+ ppc->spu.regs[SPU4XX_LINE_STATUS] |= 0x02;
+
+ /* handle DMA */
+ if (operation >= 2 && ppc4xx_dma_fetch_transmit_byte(ppc, operation, &ppc->spu.txbuf))
+ ppc->spu.regs[SPU4XX_LINE_STATUS] &= ~0x04;
+ }
+
+ /* receive enabled? */
+ if (ppc->spu.regs[SPU4XX_RX_COMMAND] & 0x80)
+ if (ppc->spu.rxout != ppc->spu.rxin)
+ {
+ int operation = (ppc->spu.regs[SPU4XX_RX_COMMAND] >> 5) & 3;
+ UINT8 rxbyte;
+
+ /* consume the byte and advance the out pointer */
+ rxbyte = ppc->spu.rxbuffer[ppc->spu.rxout];
+ ppc->spu.rxout = (ppc->spu.rxout + 1) % ARRAY_LENGTH(ppc->spu.rxbuffer);
+
+ /* if we're not full, copy data to the buffer and update the line status */
+ if (!(ppc->spu.regs[SPU4XX_LINE_STATUS] & 0x80))
+ {
+ ppc->spu.rxbuf = rxbyte;
+ ppc->spu.regs[SPU4XX_LINE_STATUS] |= 0x80;
+ }
+
+ /* otherwise signal an overrun */
+ else
+ {
+ ppc->spu.regs[SPU4XX_LINE_STATUS] |= 0x20;
+ goto updateirq;
+ }
+
+ /* handle DMA */
+ if (operation >= 2 && ppc4xx_dma_handle_receive_byte(ppc, operation, ppc->spu.rxbuf))
+ ppc->spu.regs[SPU4XX_LINE_STATUS] &= ~0x80;
+ }
+
+ /* update the final IRQ states */
+updateirq:
+ ppc4xx_spu_update_irq_states(ppc);
+}
+
+
+/*-------------------------------------------------
+ ppc4xx_spu_r - serial port read handler
+-------------------------------------------------*/
+
+static READ8_HANDLER( ppc4xx_spu_r )
+{
+ powerpc_state *ppc = *(powerpc_state **)downcast<legacy_cpu_device *>(&space->device())->token();
+ UINT8 result = 0xff;
+
+ switch (offset)
+ {
+ case SPU4XX_BUFFER:
+ result = ppc->spu.rxbuf;
+ ppc->spu.regs[SPU4XX_LINE_STATUS] &= ~0x80;
+ break;
+
+ default:
+ if (offset < ARRAY_LENGTH(ppc->spu.regs))
+ result = ppc->spu.regs[offset];
+ break;
+ }
+ if (PRINTF_SPU)
+ printf("spu_r(%d) = %02X\n", offset, result);
+ return result;
+}
+
+
+/*-------------------------------------------------
+ ppc4xx_spu_w - serial port write handler
+-------------------------------------------------*/
+
+static WRITE8_HANDLER( ppc4xx_spu_w )
+{
+ powerpc_state *ppc = *(powerpc_state **)downcast<legacy_cpu_device *>(&space->device())->token();
+ UINT8 oldstate, newstate;
+
+ if (PRINTF_SPU)
+ printf("spu_w(%d) = %02X\n", offset, data);
+ switch (offset)
+ {
+ /* clear error bits */
+ case SPU4XX_LINE_STATUS:
+ ppc->spu.regs[SPU4XX_LINE_STATUS] &= ~(data & 0xf8);
+ ppc4xx_spu_update_irq_states(ppc);
+ break;
+
+ /* enable/disable the timer if one of these is enabled */
+ case SPU4XX_RX_COMMAND:
+ case SPU4XX_TX_COMMAND:
+ oldstate = ppc->spu.regs[SPU4XX_RX_COMMAND] | ppc->spu.regs[SPU4XX_TX_COMMAND];
+ ppc->spu.regs[offset] = data;
+ newstate = ppc->spu.regs[SPU4XX_RX_COMMAND] | ppc->spu.regs[SPU4XX_TX_COMMAND];
+ if ((oldstate ^ newstate) & 0x80)
+ ppc4xx_spu_timer_reset(ppc);
+ ppc4xx_spu_update_irq_states(ppc);
+ break;
+
+ /* if the divisor changes, we need to update the timer */
+ case SPU4XX_BAUD_DIVISOR_H:
+ case SPU4XX_BAUD_DIVISOR_L:
+ if (data != ppc->spu.regs[offset])
+ {
+ ppc->spu.regs[offset] = data;
+ ppc4xx_spu_timer_reset(ppc);
+ }
+ break;
+
+ /* if the number of data bits or stop bits changes, we need to update the timer */
+ case SPU4XX_CONTROL:
+ oldstate = ppc->spu.regs[offset];
+ ppc->spu.regs[offset] = data;
+ if ((oldstate ^ data) & 0x09)
+ ppc4xx_spu_timer_reset(ppc);
+ break;
+
+ break;
+
+ case SPU4XX_BUFFER:
+ /* write to the transmit buffer and mark it full */
+ ppc->spu.txbuf = data;
+ ppc->spu.regs[SPU4XX_LINE_STATUS] &= ~0x04;
+ break;
+
+ default:
+ if (offset < ARRAY_LENGTH(ppc->spu.regs))
+ ppc->spu.regs[offset] = data;
+ break;
+ }
+}
+
+
+
+/*-------------------------------------------------
+ internal_ppc4xx - internal address map for
+ the 4XX
+-------------------------------------------------*/
+
+static ADDRESS_MAP_START( internal_ppc4xx, AS_PROGRAM, 32 )
+ AM_RANGE(0x40000000, 0x4000000f) AM_READWRITE8(ppc4xx_spu_r, ppc4xx_spu_w, 0xffffffff)
+ADDRESS_MAP_END
+
+
+
+/*-------------------------------------------------
+ ppc4xx_spu_set_tx_handler - PowerPC 4XX-
+ specific TX handler configuration
+-------------------------------------------------*/
+
+void ppc4xx_spu_set_tx_handler(device_t *device, ppc4xx_spu_tx_handler handler)
+{
+ powerpc_state *ppc = *(powerpc_state **)downcast<legacy_cpu_device *>(device)->token();
+ ppc->spu.tx_handler = handler;
+}
+
+
+/*-------------------------------------------------
+ ppc4xx_spu_receive_byte - PowerPC 4XX-
+ specific serial byte receive
+-------------------------------------------------*/
+
+void ppc4xx_spu_receive_byte(device_t *device, UINT8 byteval)
+{
+ powerpc_state *ppc = *(powerpc_state **)downcast<legacy_cpu_device *>(device)->token();
+ ppc4xx_spu_rx_data(ppc, byteval);
+}
+
+
+/*-------------------------------------------------
+ ppc4xx_set_info - PowerPC 4XX-specific
+ information setter
+-------------------------------------------------*/
+
+void ppc4xx_set_info(powerpc_state *ppc, UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + PPC_IRQ_LINE_0: ppc4xx_set_irq_line(ppc, PPC4XX_IRQ_BIT_EXT0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + PPC_IRQ_LINE_1: ppc4xx_set_irq_line(ppc, PPC4XX_IRQ_BIT_EXT1, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + PPC_IRQ_LINE_2: ppc4xx_set_irq_line(ppc, PPC4XX_IRQ_BIT_EXT2, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + PPC_IRQ_LINE_3: ppc4xx_set_irq_line(ppc, PPC4XX_IRQ_BIT_EXT3, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + PPC_IRQ_LINE_4: ppc4xx_set_irq_line(ppc, PPC4XX_IRQ_BIT_EXT4, info->i); break;
+
+ /* --- everything else is handled generically --- */
+ default: ppccom_set_info(ppc, state, info); break;
+ }
+}
+
+
+/*-------------------------------------------------
+ ppc4xx_get_info - PowerPC 4XX-specific
+ information getter
+-------------------------------------------------*/
+
+void ppc4xx_get_info(powerpc_state *ppc, UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_LINES: info->i = 5; break;
+ case CPUINFO_INT_INPUT_STATE + PPC_IRQ_LINE_0: info->i = ppc4xx_get_irq_line(ppc, PPC4XX_IRQ_BIT_EXT0); break;
+ case CPUINFO_INT_INPUT_STATE + PPC_IRQ_LINE_1: info->i = ppc4xx_get_irq_line(ppc, PPC4XX_IRQ_BIT_EXT1); break;
+ case CPUINFO_INT_INPUT_STATE + PPC_IRQ_LINE_2: info->i = ppc4xx_get_irq_line(ppc, PPC4XX_IRQ_BIT_EXT2); break;
+ case CPUINFO_INT_INPUT_STATE + PPC_IRQ_LINE_3: info->i = ppc4xx_get_irq_line(ppc, PPC4XX_IRQ_BIT_EXT3); break;
+ case CPUINFO_INT_INPUT_STATE + PPC_IRQ_LINE_4: info->i = ppc4xx_get_irq_line(ppc, PPC4XX_IRQ_BIT_EXT4); break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 31; break;
+ case CPUINFO_INT_LOGADDR_WIDTH_PROGRAM: info->i = 32; break;
+ case CPUINFO_INT_PAGE_SHIFT_PROGRAM: info->i = POWERPC_MIN_PAGE_SHIFT;break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: /* provided per-CPU */ break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map32 = ADDRESS_MAP_NAME(internal_ppc4xx); break;
+
+ /* --- everything else is handled generically --- */
+ default: ppccom_get_info(ppc, state, info); break;
+ }
+}
+
diff --git a/trunk/src/emu/cpu/powerpc/ppccom.h b/trunk/src/emu/cpu/powerpc/ppccom.h
new file mode 100644
index 00000000000..24a41603c6e
--- /dev/null
+++ b/trunk/src/emu/cpu/powerpc/ppccom.h
@@ -0,0 +1,604 @@
+/***************************************************************************
+
+ ppccom.h
+
+ Common PowerPC definitions and functions
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __PPCCOM_H__
+#define __PPCCOM_H__
+
+#include "ppc.h"
+#include "cpu/vtlb.h"
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+/* core parameters */
+#define POWERPC_MIN_PAGE_SHIFT 12
+#define POWERPC_MIN_PAGE_SIZE (1 << POWERPC_MIN_PAGE_SHIFT)
+#define POWERPC_MIN_PAGE_MASK (POWERPC_MIN_PAGE_SIZE - 1)
+#define POWERPC_TLB_ENTRIES 128
+#define PPC603_FIXED_TLB_ENTRIES 128
+
+
+/* cycle parameters */
+#define POWERPC_COUNT_READ_TBL 100
+#define POWERPC_COUNT_READ_DEC 100
+
+
+/* internal capabilities flags */
+#define PPCCAP_OEA 0x01 /* TRUE if we conform to the OEA */
+#define PPCCAP_VEA 0x02 /* TRUE if we conform to the VEA */
+#define PPCCAP_FPU 0x04 /* TRUE if we have an FPU */
+#define PPCCAP_MISALIGNED 0x08 /* TRUE if misaligned accesses are supported */
+#define PPCCAP_4XX 0x10 /* TRUE if we are a non-OEA 4XX class chip */
+#define PPCCAP_603_MMU 0x20 /* TRUE if we have 603-class MMU features */
+#define PPCCAP_MFIOC 0x40 /* TRUE if we have memory-forced I/O controller interface accesses */
+#define PPCCAP_601BAT 0x80 /* TRUE if we're doing 601-style BATs (unified I/D, different bit layout) */
+
+/* PowerPC flavors */
+enum _powerpc_flavor
+{
+ PPC_MODEL_403GA = 0x00200000,
+ PPC_MODEL_403GB = 0x00200100,
+ PPC_MODEL_403GC = 0x00200200,
+ PPC_MODEL_403GCX = 0x00201400,
+ PPC_MODEL_405GP = 0x40110000,
+ PPC_MODEL_601 = 0x00010000,
+ PPC_MODEL_603 = 0x00030000, /* "Wart" */
+ PPC_MODEL_604 = 0x00040000, /* "Zephyr" */
+ PPC_MODEL_602 = 0x00050200, /* "Galahad" */
+ PPC_MODEL_603E = 0x00060103, /* "Stretch", version 1.3 */
+ PPC_MODEL_603EV = 0x00070000, /* "Valiant" */
+ PPC_MODEL_603R = 0x00071202, /* "Goldeneye", version 2.1 */
+ PPC_MODEL_740 = 0x00080301, /* "Arthur", version 3.1 */
+ PPC_MODEL_750 = PPC_MODEL_740,
+ PPC_MODEL_740P = 0x00080202, /* "Conan Doyle", version 1.2 */
+ PPC_MODEL_750P = PPC_MODEL_740P,
+ PPC_MODEL_755 = 0x00083203, /* "Goldfinger", version 2.3 */
+ PPC_MODEL_7400 = 0x000c0209, /* "Max", version 2.9 */
+ PPC_MODEL_7410 = 0x800c1104, /* "Nitro", version 3.4 */
+ PPC_MODEL_7450 = 0x80000201, /* "Vger", version 2.1 */
+ PPC_MODEL_7451 = 0x80000203, /* "Vger", version 2.3 */
+ PPC_MODEL_7441 = PPC_MODEL_7451,
+ PPC_MODEL_7455 = 0x80010303, /* "Apollo 6", version 3.3 */
+ PPC_MODEL_7445 = PPC_MODEL_7455,
+ PPC_MODEL_7457 = 0x80020101, /* "Apollo 7", version 1.1 */
+ PPC_MODEL_MPC8240 = 0x00810101, /* "Kahlua" */
+ PPC_MODEL_MPC8241 = 0x80811014, /* "Kahlua Lt" */
+ PPC_MODEL_MPC8245 = 0x80811014, /* "Kahlua II" */
+};
+typedef enum _powerpc_flavor powerpc_flavor;
+
+
+/* exception types */
+enum
+{
+ EXCEPTION_RESET = 1,
+ EXCEPTION_MACHCHECK = 2,
+ EXCEPTION_DSI = 3, /* PPCCAP_OEA */
+ EXCEPTION_PROTECTION = 3, /* PPCCAP_4XX */
+ EXCEPTION_ISI = 4,
+ EXCEPTION_EI = 5,
+ EXCEPTION_ALIGN = 6,
+ EXCEPTION_PROGRAM = 7,
+ EXCEPTION_NOFPU = 8,
+ EXCEPTION_DECREMENT = 9,
+ EXCEPTION_SYSCALL = 12,
+ EXCEPTION_TRACE = 13,
+ EXCEPTION_FPASSIST = 14,
+ EXCEPTION_ITLBMISS = 16, /* PPCCAP_603_MMU */
+ EXCEPTION_DTLBMISSL = 17, /* PPCCAP_603_MMU */
+ EXCEPTION_DTLBMISSS = 18, /* PPCCAP_603_MMU */
+ EXCEPTION_COUNT
+};
+
+
+/* SPRs */
+enum
+{
+ /* UISA SPR register indexes */
+ SPR_XER = 0x001, /* R/W Fixed Point Exception Register */
+ SPR_LR = 0x008, /* R/W Link Register */
+ SPR_CTR = 0x009, /* R/W Count Register */
+
+ /* VEA SPR register indexes */
+ SPRVEA_TBL_R = 0x10c, /* R Time Base Low */
+ SPRVEA_TBU_R = 0x10d, /* R Time Base High */
+
+ /* OEA SPR register indexes */
+ SPROEA_DSISR = 0x012, /* R/W DSI Status Register */
+ SPROEA_DAR = 0x013, /* R/W Data Address Register */
+ SPROEA_DEC = 0x016, /* R/W Decrementer Register */
+ SPROEA_SDR1 = 0x019, /* R/W Page Table Configuration */
+ SPROEA_SRR0 = 0x01a, /* R/W Machine Status Save/Restore Register 0 */
+ SPROEA_SRR1 = 0x01b, /* R/W Machine Status Save/Restore Register 1 */
+ SPROEA_SPRG0 = 0x110, /* R/W SPR General 0 */
+ SPROEA_SPRG1 = 0x111, /* R/W SPR General 1 */
+ SPROEA_SPRG2 = 0x112, /* R/W SPR General 2 */
+ SPROEA_SPRG3 = 0x113, /* R/W SPR General 3 */
+ SPROEA_ASR = 0x118, /* R/W Address Space Register (64-bit only) */
+ SPROEA_EAR = 0x11a, /* R/W External Access Register */
+ SPROEA_PVR = 0x11f, /* R Processor Version Number */
+ SPROEA_IBAT0U = 0x210, /* R/W Instruction BAT 0 Upper */
+ SPROEA_IBAT0L = 0x211, /* R/W Instruction BAT 0 Lower */
+ SPROEA_IBAT1U = 0x212, /* R/W Instruction BAT 1 Upper */
+ SPROEA_IBAT1L = 0x213, /* R/W Instruction BAT 1 Lower */
+ SPROEA_IBAT2U = 0x214, /* R/W Instruction BAT 2 Upper */
+ SPROEA_IBAT2L = 0x215, /* R/W Instruction BAT 2 Lower */
+ SPROEA_IBAT3U = 0x216, /* R/W Instruction BAT 3 Upper */
+ SPROEA_IBAT3L = 0x217, /* R/W Instruction BAT 3 Lower */
+ SPROEA_DBAT0U = 0x218, /* R/W Data BAT 0 Upper */
+ SPROEA_DBAT0L = 0x219, /* R/W Data BAT 0 Lower */
+ SPROEA_DBAT1U = 0x21a, /* R/W Data BAT 1 Upper */
+ SPROEA_DBAT1L = 0x21b, /* R/W Data BAT 1 Lower */
+ SPROEA_DBAT2U = 0x21c, /* R/W Data BAT 2 Upper */
+ SPROEA_DBAT2L = 0x21d, /* R/W Data BAT 2 Lower */
+ SPROEA_DBAT3U = 0x21e, /* R/W Data BAT 3 Upper */
+ SPROEA_DBAT3L = 0x21f, /* R/W Data BAT 3 Lower */
+ SPROEA_DABR = 0x3f5, /* R/W Data Address Breakpoint Register */
+
+ /* PowerPC 4XX SPR register indexes */
+ SPR4XX_SRR0 = 0x01a, /* R/W 403GA Machine Status Save/Restore Register 0 */
+ SPR4XX_SRR1 = 0x01b, /* R/W 403GA Machine Status Save/Restore Register 1 */
+ SPR4XX_SPRG0 = 0x110, /* R/W 403GA SPR General 0 */
+ SPR4XX_SPRG1 = 0x111, /* R/W 403GA SPR General 1 */
+ SPR4XX_SPRG2 = 0x112, /* R/W 403GA SPR General 2 */
+ SPR4XX_SPRG3 = 0x113, /* R/W 403GA SPR General 3 */
+ SPR4XX_PVR = 0x11f, /* R 403GA Processor Version Number */
+ SPR4XX_PID = 0x3b1, /* R/W 403GCX Process ID */
+ SPR4XX_SGR = 0x3b9, /* R/W 403GCX Storage Guarded Register */
+ SPR4XX_DCWR = 0x3ba, /* R/W 403GCX Data Cache Write Through */
+ SPR4XX_TBHU = 0x3cc, /* R/W 403GCX Time Base High User-mode */
+ SPR4XX_TBLU = 0x3cd, /* R/W 403GCX Time Base Low User-mode */
+ SPR4XX_ICDBDR = 0x3d3, /* R 403GA 406GA Instruction Cache Debug Data Register */
+ SPR4XX_ESR = 0x3d4, /* R/W 403GA 406GA Exception Syndrome Register */
+ SPR4XX_DEAR = 0x3d5, /* R 403GA 406GA Data Exception Address Register */
+ SPR4XX_EVPR = 0x3d6, /* R/W 403GA 406GA Exception Vector Prefix Register */
+ SPR4XX_CDBCR = 0x3d7, /* R/W 403GA 406GA Cache Debug Control Register */
+ SPR4XX_TSR = 0x3d8, /* R/C 403GA 406GA Timer Status Register */
+ SPR4XX_TCR = 0x3da, /* R/W 403GA 406GA Timer Control Register */
+ SPR4XX_PIT = 0x3db, /* R/W 403GA 406GA Programmable Interval Timer */
+ SPR4XX_TBHI = 0x3dc, /* R/W 403GA 406GA Time Base High */
+ SPR4XX_TBLO = 0x3dd, /* R/W 403GA 406GA Time Base Low */
+ SPR4XX_SRR2 = 0x3de, /* R/W 403GA 406GA Machine Status Save/Restore Register 2 */
+ SPR4XX_SRR3 = 0x3df, /* R/W 403GA 406GA Machine Status Save/Restore Register 3 */
+ SPR4XX_DBSR = 0x3f0, /* R/C 403GA 406GA Debug Status Register */
+ SPR4XX_DBCR = 0x3f2, /* R/W 403GA 406GA Debug Control Register */
+ SPR4XX_IAC1 = 0x3f4, /* R/W 403GA 406GA Instruction Address Compare 1 */
+ SPR4XX_IAC2 = 0x3f5, /* R/W 403GA 406GA Instruction Address Compare 2 */
+ SPR4XX_DAC1 = 0x3f6, /* R/W 403GA 406GA Data Address Compare 1 */
+ SPR4XX_DAC2 = 0x3f7, /* R/W 403GA 406GA Data Address Compare 2 */
+ SPR4XX_DCCR = 0x3fa, /* R/W 403GA 406GA Data Cache Cacheability Register */
+ SPR4XX_ICCR = 0x3fb, /* R/W 403GA 406GA Instruction Cache Cacheability Registe */
+ SPR4XX_PBL1 = 0x3fc, /* R/W 403GA 406GA Protection Bound Lower 1 */
+ SPR4XX_PBU1 = 0x3fd, /* R/W 403GA 406GA Protection Bound Upper 1 */
+ SPR4XX_PBL2 = 0x3fe, /* R/W 403GA 406GA Protection Bound Lower 2 */
+ SPR4XX_PBU2 = 0x3ff, /* R/W 403GA 406GA Protection Bound Upper 2 */
+
+ /* PowerPC 602 SPR register indexes */
+ SPR602_TCR = 0x3d8, /* 602 */
+ SPR602_IBR = 0x3da, /* 602 */
+ SPR602_ESASRR = 0x3db, /* 602 */
+ SPR602_SEBR = 0x3de, /* 602 */
+ SPR602_SER = 0x3df, /* 602 */
+ SPR602_SP = 0x3fd, /* 602 */
+ SPR602_LT = 0x3fe, /* 602 */
+
+ /* PowerPC 603 SPR register indexes */
+ SPR603_TBL_R = 0x10c, /* R 603 Time Base Low (Read-only) */
+ SPR603_TBU_R = 0x10d, /* R 603 Time Base High (Read-only) */
+ SPR603_TBL_W = 0x11c, /* W 603 Time Base Low (Write-only) */
+ SPR603_TBU_W = 0x11d, /* W 603 Time Base Hight (Write-only) */
+ SPR603_DMISS = 0x3d0, /* R 603 Data TLB Miss Address Register */
+ SPR603_DCMP = 0x3d1, /* R 603 Data TLB Compare Register */
+ SPR603_HASH1 = 0x3d2, /* R 603 Primary Hash Address Register */
+ SPR603_HASH2 = 0x3d3, /* R 603 Secondary Hash Address Register */
+ SPR603_IMISS = 0x3d4, /* R 603 Instruction TLB Miss Address Register */
+ SPR603_ICMP = 0x3d5, /* R 603 Instruction TLB Compare Register */
+ SPR603_RPA = 0x3d6, /* R/W 603 Required Physical Address Register */
+ SPR603_HID0 = 0x3f0, /* R/W 603 Hardware Implementation Register 0 */
+ SPR603_HID1 = 0x3f1, /* R/W 603 Hardware Implementation Register 1 */
+ SPR603_IABR = 0x3f2, /* R/W 603 Instruction Address Breakpoint Register */
+ SPR603_HID2 = 0x3f3 /* R/W 603 */
+};
+
+
+/* PowerPC 4XX DCR register indexes */
+enum
+{
+ DCR4XX_EXISR = 0x040, /* external interrupt status */
+ DCR4XX_EXIER = 0x042, /* external interrupt enable */
+ DCR4XX_BR0 = 0x080, /* bank */
+ DCR4XX_BR1 = 0x081, /* bank */
+ DCR4XX_BR2 = 0x082, /* bank */
+ DCR4XX_BR3 = 0x083, /* bank */
+ DCR4XX_BR4 = 0x084, /* bank */
+ DCR4XX_BR5 = 0x085, /* bank */
+ DCR4XX_BR6 = 0x086, /* bank */
+ DCR4XX_BR7 = 0x087, /* bank */
+ DCR4XX_BEAR = 0x090, /* bus error address */
+ DCR4XX_BESR = 0x091, /* bus error syndrome */
+ DCR4XX_IOCR = 0x0a0, /* io configuration */
+ DCR4XX_DMACR0 = 0x0c0, /* dma channel control */
+ DCR4XX_DMACT0 = 0x0c1, /* dma destination address */
+ DCR4XX_DMADA0 = 0x0c2, /* dma destination address */
+ DCR4XX_DMASA0 = 0x0c3, /* dma source address */
+ DCR4XX_DMACC0 = 0x0c4, /* dma chained count */
+ DCR4XX_DMACR1 = 0x0c8, /* dma channel control */
+ DCR4XX_DMACT1 = 0x0c9, /* dma destination address */
+ DCR4XX_DMADA1 = 0x0ca, /* dma destination address */
+ DCR4XX_DMASA1 = 0x0cb, /* dma source address */
+ DCR4XX_DMACC1 = 0x0cc, /* dma chained count */
+ DCR4XX_DMACR2 = 0x0d0, /* dma channel control */
+ DCR4XX_DMACT2 = 0x0d1, /* dma destination address */
+ DCR4XX_DMADA2 = 0x0d2, /* dma source address */
+ DCR4XX_DMASA2 = 0x0d3, /* dma source address */
+ DCR4XX_DMACC2 = 0x0d4, /* dma chained count */
+ DCR4XX_DMACR3 = 0x0d8, /* dma channel control */
+ DCR4XX_DMACT3 = 0x0d9, /* dma destination address */
+ DCR4XX_DMADA3 = 0x0da, /* dma source address */
+ DCR4XX_DMASA3 = 0x0db, /* dma source address */
+ DCR4XX_DMACC3 = 0x0dc, /* dma chained count */
+ DCR4XX_DMASR = 0x0e0 /* dma status */
+};
+
+
+/* PowerPC 4XX SPU register indexes */
+enum
+{
+ SPU4XX_LINE_STATUS = 0x00,
+ SPU4XX_HANDSHAKE_STATUS = 0x02,
+ SPU4XX_BAUD_DIVISOR_H = 0x04,
+ SPU4XX_BAUD_DIVISOR_L = 0x05,
+ SPU4XX_CONTROL = 0x06,
+ SPU4XX_RX_COMMAND = 0x07,
+ SPU4XX_TX_COMMAND = 0x08,
+ SPU4XX_BUFFER = 0x09
+};
+
+
+/* FPSCR register bits */
+#define FPSCR_FX 0x80000000
+#define FPSCR_FEX 0x40000000
+#define FPSCR_VX 0x20000000
+#define FPSCR_OX 0x10000000
+#define FPSCR_UX 0x08000000
+#define FPSCR_ZX 0x04000000
+#define FPSCR_XX 0x02000000
+
+
+/* XER register bits */
+#define XER_SO 0x80000000
+#define XER_OV 0x40000000
+#define XER_CA 0x20000000
+
+
+/* Machine State Register bits - common */
+#define MSR_ILE 0x00010000 /* Interrupt Little Endian Mode */
+#define MSR_EE 0x00008000 /* External Interrupt Enable */
+#define MSR_PR 0x00004000 /* Problem State */
+#define MSR_ME 0x00001000 /* Machine Check Enable */
+#define MSR_LE 0x00000001 /* Little Endian */
+
+/* Machine State Register bits - OEA */
+#define MSROEA_POW 0x00040000 /* Power Management Enable */
+#define MSROEA_FP 0x00002000 /* Floating Point Available */
+#define MSROEA_FE0 0x00000800 /* FP Exception Mode 0 */
+#define MSROEA_SE 0x00000400 /* Single Step Trace Enable */
+#define MSROEA_BE 0x00000200 /* Branch Trace Enable */
+#define MSROEA_FE1 0x00000100 /* FP Exception Mode 1 */
+#define MSROEA_IP 0x00000040 /* Interrupt Prefix */
+#define MSROEA_IR 0x00000020 /* Instruction Relocate */
+#define MSROEA_DR 0x00000010 /* Data Relocate */
+#define MSROEA_RI 0x00000002 /* Recoverable Interrupt Enable */
+
+/* Machine State Register bits - 4XX */
+#define MSR4XX_WE 0x00040000 /* Wait State Enable */
+#define MSR4XX_CE 0x00020000 /* Critical Interrupt Enable */
+#define MSR4XX_DE 0x00000200 /* Debug Exception Enable */
+#define MSR4XX_PE 0x00000008 /* Protection Enable (reserved for others) */
+#define MSR4XX_PX 0x00000004 /* Protection Exclusive Mode (reserved for others) */
+
+/* Machine State Register bits - 602 */
+#define MSR602_AP 0x00800000 /* Access privilege state */
+#define MSR602_SA 0x00400000 /* Supervisor access mode */
+
+/* Machine State Register bits - 603 */
+#define MSR603_TGPR 0x00020000 /* Temporary GPR Remapping */
+
+
+/* DSISR bits for DSI/alignment exceptions */
+#define DSISR_DIRECT 0x00000001 /* DSI: direct-store exception? */
+#define DSISR_NOT_FOUND 0x00000002 /* DSI: not found in HTEG or DBAT */
+#define DSISR_PROTECTED 0x00000010 /* DSI: exception due to protection */
+#define DSISR_CACHE_ERROR 0x00000020 /* DSI: operation on incorrect cache type */
+#define DSISR_STORE 0x00000040 /* DSI: store (1) or load (0) */
+#define DSISR_DABR 0x00000200 /* DSI: DABR match occurred */
+#define DSISR_NO_SEGMENT 0x00000400 /* DSI: no segment match found (64-bit only) */
+#define DSISR_INVALID_ECWX 0x00000800 /* DSI: ECIWX or ECOWX used with EAR[E] = 0 */
+#define DSISR_INSTRUCTION 0xfffff000 /* align: instruction decoding bits */
+
+
+/* PowerPC 4XX IRQ bits */
+#define PPC4XX_IRQ_BIT_CRITICAL (0x80000000 >> 0)
+#define PPC4XX_IRQ_BIT_SPUR (0x80000000 >> 4)
+#define PPC4XX_IRQ_BIT_SPUT (0x80000000 >> 5)
+#define PPC4XX_IRQ_BIT_JTAGR (0x80000000 >> 6)
+#define PPC4XX_IRQ_BIT_JTAGT (0x80000000 >> 7)
+#define PPC4XX_IRQ_BIT_DMA0 (0x80000000 >> 8)
+#define PPC4XX_IRQ_BIT_DMA1 (0x80000000 >> 9)
+#define PPC4XX_IRQ_BIT_DMA2 (0x80000000 >> 10)
+#define PPC4XX_IRQ_BIT_DMA3 (0x80000000 >> 11)
+#define PPC4XX_IRQ_BIT_EXT0 (0x80000000 >> 27)
+#define PPC4XX_IRQ_BIT_EXT1 (0x80000000 >> 28)
+#define PPC4XX_IRQ_BIT_EXT2 (0x80000000 >> 29)
+#define PPC4XX_IRQ_BIT_EXT3 (0x80000000 >> 30)
+#define PPC4XX_IRQ_BIT_EXT4 (0x80000000 >> 31)
+
+#define PPC4XX_IRQ_BIT_EXT(n) (PPC4XX_IRQ_BIT_EXT0 >> (n))
+#define PPC4XX_IRQ_BIT_DMA(n) (PPC4XX_IRQ_BIT_DMA0 >> (n))
+
+
+/* PowerPC 4XX DMA control bits */
+#define PPC4XX_DMACR_CE 0x80000000 /* channel enable */
+#define PPC4XX_DMACR_CIE 0x40000000 /* channel interrupt enable */
+#define PPC4XX_DMACR_TD 0x20000000 /* transfer direction */
+#define PPC4XX_DMACR_PL 0x10000000 /* peripheral location */
+#define PPC4XX_DMACR_PW_MASK 0x0c000000 /* peripheral width */
+#define PPC4XX_DMACR_DAI 0x02000000 /* destination address increment */
+#define PPC4XX_DMACR_SAI 0x01000000 /* source address increment */
+#define PPC4XX_DMACR_CP 0x00800000 /* channel priority */
+#define PPC4XX_DMACR_TM_MASK 0x00600000 /* transfer mode */
+#define PPC4XX_DMACR_PSC_MASK 0x00180000 /* peripheral setup cycles */
+#define PPC4XX_DMACR_PWC_MASK 0x0007e000 /* peripheral wait cycles */
+#define PPC4XX_DMACR_PHC_MASK 0x00001c00 /* peripheral hold cycles */
+#define PPC4XX_DMACR_ETD 0x00000200 /* end-of-transfer pin direction */
+#define PPC4XX_DMACR_TCE 0x00000100 /* terminal count enable */
+#define PPC4XX_DMACR_CH 0x00000080 /* chaining enable */
+#define PPC4XX_DMACR_BME 0x00000040 /* burst mode enable */
+#define PPC4XX_DMACR_ECE 0x00000020 /* EOT chain mode enable */
+#define PPC4XX_DMACR_TCD 0x00000010 /* TC chain mode disable */
+#define PPC4XX_DMACR_PCE 0x00000008
+
+
+/* PowerPC 4XX Timer control register bits */
+#define PPC4XX_TCR_WP_MASK 0xc0000000 /* watchdog period */
+#define PPC4XX_TCR_WRC_MASK 0x30000000 /* watchdog reset control */
+#define PPC4XX_TCR_WIE 0x08000000 /* watchdog interrupt enable */
+#define PPC4XX_TCR_PIE 0x04000000 /* PIT interrupt enable */
+#define PPC4XX_TCR_FP_MASK 0x03000000 /* FIT period */
+#define PPC4XX_TCR_FIE 0x00800000 /* FIT interrupt enable */
+#define PPC4XX_TCR_ARE 0x00400000 /* auto reload enable */
+
+
+/* PowerPC 4XX Timer status register bits */
+#define PPC4XX_TSR_ENW 0x80000000 /* enable next watchdog */
+#define PPC4XX_TSR_WIS 0x40000000 /* watchdog interrupt status */
+#define PPC4XX_TSR_WRS_MASK 0x30000000 /* watchdog reset status */
+#define PPC4XX_TSR_PIS 0x08000000 /* PIT interrupt status */
+#define PPC4XX_TSR_FIS 0x04000000 /* FIT interrupt status */
+
+
+/* instruction decoding masks */
+#define M_LI 0x03fffffc
+#define M_AA 0x00000002
+#define M_LK 0x00000001
+#define M_BO 0x03e00000
+#define M_BI 0x001f0000
+#define M_BD 0x0000fffc
+#define M_RT 0x03e00000
+#define M_RD 0x03e00000
+#define M_RS 0x03e00000
+#define M_RA 0x001f0000
+#define M_RB 0x0000f800
+#define M_CRFD 0x03800000
+#define M_L 0x00200000
+#define M_TO 0x03e00000
+#define M_D 0x0000ffff
+#define M_SIMM 0x0000ffff
+#define M_UIMM 0x0000ffff
+#define M_NB 0x0000f800
+#define M_SR 0x000f0000
+#define M_SH 0x0000f800
+#define M_CRFS 0x001c0000
+#define M_IMM 0x0000f000
+#define M_CRBD 0x03e00000
+#define M_RC 0x00000001
+#define M_CRBA 0x001f0000
+#define M_CRBB 0x0000f800
+#define M_SPR 0x001FF800
+#define M_TBR 0x001FF800
+#define M_CRM 0x000FF000
+#define M_DCR 0x001FF800
+#define M_FM 0x01FE0000
+#define M_OE 0x00000400
+#define M_REGC 0x000007c0
+#define M_MB 0x000007c0
+#define M_ME 0x0000003e
+#define M_XO 0x000007fe
+
+
+
+/***************************************************************************
+ HELPER MACROS
+***************************************************************************/
+
+/*
+ * Field Defining Macros
+ *
+ * These macros generate instruction words with their associated fields filled
+ * in with the passed value.
+ */
+
+#define D_OP(op) ((op & 0x3f) << 26)
+#define D_XO(xo) ((xo & 0x3ff) << 1)
+#define D_RT(r) ((r & 0x1f) << (31 - 10))
+#define D_RA(r) ((r & 0x1f) << (31 - 15))
+#define D_UIMM(u) (u & 0xffff)
+
+/*
+ * Macros to Get Field Values
+ *
+ * These macros return the values of fields in an opcode. They all return
+ * unsigned values and do not perform any sign extensions.
+ */
+
+#define G_RT(op) ((op & M_RT) >> (31 - 10))
+#define G_RD(op) ((op & M_RD) >> (31 - 10))
+#define G_RS(op) ((op & M_RS) >> (31 - 10))
+#define G_RA(op) ((op & M_RA) >> (31 - 15))
+#define G_RB(op) ((op & M_RB) >> (31 - 20))
+#define G_SIMM(op) (op & M_SIMM)
+#define G_UIMM(op) (op & M_UIMM)
+#define G_LI(op) ((op & M_LI) >> 2)
+#define G_BO(op) ((op & M_BO) >> (31 - 10))
+#define G_BI(op) ((op & M_BI) >> (31 - 15))
+#define G_BD(op) ((op & M_BD) >> 2)
+#define G_CRFD(op) ((op & M_CRFD) >> (31 - 8))
+#define G_L(op) ((op & M_L) >> (31 - 10))
+#define G_CRBD(op) ((op & M_CRBD) >> (31 - 10))
+#define G_CRBA(op) ((op & M_CRBA) >> (31 - 15))
+#define G_CRBB(op) ((op & M_CRBB) >> (31 - 20))
+#define G_REGC(op) ((op & M_REGC) >> (31 - 25))
+#define G_D(op) (op & M_D)
+#define G_NB(op) ((op & M_NB) >> (31 - 20))
+#define G_CRFS(op) ((op & M_CRFS) >> (31 - 13))
+#define G_SPR(op) ((op & M_SPR) >> (31 - 20))
+#define G_TBR(op) ((op & M_TBR) >> (31 - 20))
+#define G_DCR(op) ((op & M_DCR) >> (31 - 20))
+#define G_SR(op) ((op & M_SR) >> (31 - 15))
+#define G_CRM(op) ((op & M_CRM) >> (31 - 19))
+#define G_FM(op) ((op & M_FM) >> (31 - 14))
+#define G_IMM(op) ((op & M_IMM) >> (31 - 19))
+#define G_SH(op) ((op & M_SH) >> (31 - 20))
+#define G_MB(op) ((op & M_MB) >> (31 - 25))
+#define G_ME(op) ((op & M_ME) >> 1)
+#define G_TO(op) ((op & M_TO) >> (31 - 10))
+#define G_XO(op) ((op & M_XO) >> (31 - 30))
+
+
+
+/***************************************************************************
+ STRUCTURES & TYPEDEFS
+***************************************************************************/
+
+/* PowerPC 4XX-specific serial port state */
+typedef struct _ppc4xx_spu_state ppc4xx_spu_state;
+struct _ppc4xx_spu_state
+{
+ UINT8 regs[9];
+ UINT8 txbuf;
+ UINT8 rxbuf;
+ emu_timer * timer;
+ UINT8 rxbuffer[256];
+ UINT32 rxin, rxout;
+ ppc4xx_spu_tx_handler tx_handler;
+};
+
+
+/* forward declaration of implementation-specific state */
+typedef struct _ppcimp_state ppcimp_state;
+
+
+/* PowerPC state */
+typedef struct _powerpc_state powerpc_state;
+struct _powerpc_state
+{
+ /* core registers */
+ UINT32 pc;
+ int icount;
+ UINT32 r[32];
+ double f[32];
+ UINT32 cr[8];
+ UINT32 xerso;
+ UINT32 fpscr;
+ UINT32 msr;
+ UINT32 sr[16];
+ UINT32 spr[1024];
+ UINT32 dcr[256];
+
+ /* parameters for calls */
+ UINT32 param0;
+ UINT32 param1;
+
+ /* MMU */
+ vtlb_state * vtlb;
+
+ /* architectural distinctions */
+ powerpc_flavor flavor;
+ UINT8 cap;
+ UINT8 cache_line_size;
+ UINT32 tb_divisor;
+
+ /* PowerPC 4xx-specific state */
+ ppc4xx_spu_state spu;
+ emu_timer * fit_timer;
+ emu_timer * pit_timer;
+ emu_timer * wdog_timer;
+ UINT32 pit_reload;
+ UINT32 irqstate;
+
+ /* PowerPC 603-specific state */
+ UINT32 mmu603_cmp;
+ UINT32 mmu603_hash[2];
+ UINT32 mmu603_r[4];
+
+ /* internal stuff */
+ device_irq_callback irq_callback;
+ legacy_cpu_device * device;
+ address_space *program;
+ direct_read_data *direct;
+ offs_t codexor;
+ UINT32 irq_pending;
+ UINT32 system_clock;
+ UINT32 cpu_clock;
+ UINT64 tb_zero_cycles;
+ UINT64 dec_zero_cycles;
+ emu_timer * decrementer_int_timer;
+
+ /* for use by specific implementations */
+ ppcimp_state * impstate;
+};
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+void ppccom_init(powerpc_state *ppc, powerpc_flavor flavor, UINT8 cap, int tb_divisor, legacy_cpu_device *device, device_irq_callback irqcallback);
+void ppccom_exit(powerpc_state *ppc);
+
+void ppccom_reset(powerpc_state *ppc);
+offs_t ppccom_dasm(powerpc_state *ppc, char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram);
+
+int ppccom_translate_address(powerpc_state *ppc, address_spacenum space, int intention, offs_t *address);
+
+void ppccom_set_info(powerpc_state *ppc, UINT32 state, cpuinfo *info);
+void ppccom_get_info(powerpc_state *ppc, UINT32 state, cpuinfo *info);
+
+void ppccom_tlb_fill(powerpc_state *ppc);
+void ppccom_tlb_flush(powerpc_state *ppc);
+
+void ppccom_execute_tlbie(powerpc_state *ppc);
+void ppccom_execute_tlbia(powerpc_state *ppc);
+void ppccom_execute_tlbl(powerpc_state *ppc);
+void ppccom_execute_mftb(powerpc_state *ppc);
+void ppccom_execute_mfspr(powerpc_state *ppc);
+void ppccom_execute_mtspr(powerpc_state *ppc);
+void ppccom_execute_mfdcr(powerpc_state *ppc);
+void ppccom_execute_mtdcr(powerpc_state *ppc);
+
+void ppccom_update_fprf(powerpc_state *ppc);
+
+void ppc4xx_set_info(powerpc_state *ppc, UINT32 state, cpuinfo *info);
+void ppc4xx_get_info(powerpc_state *ppc, UINT32 state, cpuinfo *info);
+
+#endif /* __PPCCOM_H__ */
diff --git a/trunk/src/emu/cpu/powerpc/ppcdrc.c b/trunk/src/emu/cpu/powerpc/ppcdrc.c
new file mode 100644
index 00000000000..848f6e7b655
--- /dev/null
+++ b/trunk/src/emu/cpu/powerpc/ppcdrc.c
@@ -0,0 +1,4586 @@
+/***************************************************************************
+
+ ppcdrc.c
+
+ Universal machine language-based PowerPC emulator.
+
+ Copyright Aaron Giles
+ Released for general non-commercial use under the MAME license
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+****************************************************************************
+
+ Future improvements/changes:
+
+ * crxor a,a,a / creqv a,a,a / cror a,a,a
+
+***************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "profiler.h"
+#include "ppccom.h"
+#include "ppcfe.h"
+#include "cpu/drcfe.h"
+#include "cpu/drcuml.h"
+#include "cpu/drcumlsh.h"
+
+using namespace uml;
+
+extern offs_t ppc_dasm_one(char *buffer, UINT32 pc, UINT32 op);
+
+
+
+/***************************************************************************
+ DEBUGGING
+***************************************************************************/
+
+#define FORCE_C_BACKEND (0)
+#define LOG_UML (0)
+#define LOG_NATIVE (0)
+
+#define DISABLE_FLAG_OPTIMIZATIONS (0)
+#define DISABLE_FAST_REGISTERS (0)
+#define SINGLE_INSTRUCTION_MODE (0)
+
+#define PRINTF_EXCEPTIONS (0)
+#define PRINTF_MMU (0)
+
+#define PROBE_ADDRESS ~0
+
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+/* map variables */
+#define MAPVAR_PC M0
+#define MAPVAR_CYCLES M1
+#define MAPVAR_DSISR M2
+
+/* mode bits */
+#define MODE_LITTLE_ENDIAN 0x01
+#define MODE_DATA_TRANSLATION 0x02 /* OEA */
+#define MODE_PROTECTION 0x02 /* 4XX */
+#define MODE_USER 0x04
+
+/* size of the execution code cache */
+#define CACHE_SIZE (32 * 1024 * 1024)
+
+/* compilation boundaries -- how far back/forward does the analysis extend? */
+#define COMPILE_BACKWARDS_BYTES 128
+#define COMPILE_FORWARDS_BYTES 512
+#define COMPILE_MAX_INSTRUCTIONS ((COMPILE_BACKWARDS_BYTES/4) + (COMPILE_FORWARDS_BYTES/4))
+#define COMPILE_MAX_SEQUENCE 64
+
+/* exit codes */
+#define EXECUTE_OUT_OF_CYCLES 0
+#define EXECUTE_MISSING_CODE 1
+#define EXECUTE_UNMAPPED_CODE 2
+#define EXECUTE_RESET_CACHE 3
+
+
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+#define R32(reg) ppc->impstate->regmap[reg]
+#define R32Z(reg) (((reg) == 0) ? parameter(0) : ppc->impstate->regmap[reg])
+#define F64(reg) ppc->impstate->fdregmap[reg]
+#define CR32(reg) mem(&ppc->cr[reg])
+#define FPSCR32 mem(&ppc->fpscr)
+#define MSR32 mem(&ppc->msr)
+#define XERSO32 mem(&ppc->xerso)
+#define SR32(reg) mem(&ppc->sr[reg])
+#define SPR32(reg) mem(&ppc->spr[reg])
+
+#define CRMASK(reg) (0xf0000000 >> ((reg) * 4))
+
+/* DSISR values for various addressing types */
+#define DSISR_IMM(op) ((0) | /* bits 15-16: cleared */ \
+ ((((op) >> (31- 5)) & 0x01) << (31-17)) | /* bit 17: opcode bit 5 */ \
+ ((((op) >> (31- 4)) & 0x0f) << (31-21)) | /* bits 18-21: opcode bits 1-4 */ \
+ ((((op) >> (31-10)) & 0x1f) << (31-26)) | /* bits 22-26: opcode bits 6-10 */ \
+ (0)) /* bits 27-31: undefined */
+
+#define DSISR_IMMU(op) ((0) | /* bits 15-16: cleared */ \
+ ((((op) >> (31- 5)) & 0x01) << (31-17)) | /* bit 17: opcode bit 5 */ \
+ ((((op) >> (31- 4)) & 0x0f) << (31-21)) | /* bits 18-21: opcode bits 1-4 */ \
+ ((((op) >> (31-10)) & 0x1f) << (31-26)) | /* bits 22-26: opcode bits 6-10 */ \
+ ((((op) >> (31-15)) & 0x1f) << (31-31))) /* bits 27-31: opcode bits 11-15 */
+
+#define DSISR_IDX(op) (((((op) >> (31-30)) & 0x03) << (31-16)) | /* bits 15-16: opcode bits 29-30 */ \
+ ((((op) >> (31-25)) & 0x01) << (31-17)) | /* bit 17: opcode bit 25 */ \
+ ((((op) >> (31-24)) & 0x0f) << (31-21)) | /* bits 18-21: opcode bits 21-24 */ \
+ ((((op) >> (31-10)) & 0x1f) << (31-26)) | /* bits 22-26: opcode bits 6-10 */ \
+ (0)) /* bits 27-31: undefined */
+
+#define DSISR_IDXU(op) (((((op) >> (31-30)) & 0x03) << (31-16)) | /* bits 15-16: opcode bits 29-30 */ \
+ ((((op) >> (31-25)) & 0x01) << (31-17)) | /* bit 17: opcode bit 25 */ \
+ ((((op) >> (31-24)) & 0x0f) << (31-21)) | /* bits 18-21: opcode bits 21-24 */ \
+ ((((op) >> (31-10)) & 0x1f) << (31-26)) | /* bits 22-26: opcode bits 6-10 */ \
+ ((((op) >> (31-15)) & 0x1f) << (31-31))) /* bits 27-31: opcode bits 11-15 */
+
+
+
+/***************************************************************************
+ STRUCTURES & TYPEDEFS
+***************************************************************************/
+
+/* fast RAM info */
+typedef struct _fast_ram_info fast_ram_info;
+struct _fast_ram_info
+{
+ offs_t start; /* start of the RAM block */
+ offs_t end; /* end of the RAM block */
+ UINT8 readonly; /* TRUE if read-only */
+ void * base; /* base in memory where the RAM lives */
+};
+
+
+/* hotspot info */
+typedef struct _hotspot_info hotspot_info;
+struct _hotspot_info
+{
+ offs_t pc; /* PC to consider */
+ UINT32 opcode; /* required opcode at that PC */
+ UINT32 cycles; /* number of cycles to eat when hit */
+};
+
+
+/* internal compiler state */
+typedef struct _compiler_state compiler_state;
+struct _compiler_state
+{
+ UINT32 cycles; /* accumulated cycles */
+ UINT8 checkints; /* need to check interrupts before next instruction */
+ UINT8 checksoftints; /* need to check software interrupts before next instruction */
+ code_label labelnum; /* index for local labels */
+};
+
+
+/* PowerPC implementation state */
+struct _ppcimp_state
+{
+ /* core state */
+ drc_cache * cache; /* pointer to the DRC code cache */
+ drcuml_state * drcuml; /* DRC UML generator state */
+ ppc_frontend * drcfe; /* pointer to the DRC front-end state */
+ UINT32 drcoptions; /* configurable DRC options */
+
+ /* parameters for subroutines */
+ UINT32 mode; /* current global mode */
+ const char * format; /* format string for printing */
+ UINT32 arg0; /* print_debug argument 1 */
+ UINT32 arg1; /* print_debug argument 2 */
+ UINT32 updateaddr; /* update address storage */
+ UINT32 swcount; /* counter for sw instructions */
+ UINT32 tempaddr; /* temporary address storage */
+ drcuml_ireg tempdata; /* temporary data storage */
+ double fp0; /* floating point 0 */
+
+ /* tables */
+ UINT8 fpmode[4]; /* FPU mode table */
+ UINT8 sz_cr_table[32]; /* SZ CR table */
+ UINT8 cmp_cr_table[32]; /* CMP CR table */
+ UINT8 cmpl_cr_table[32]; /* CMPL CR table */
+ UINT8 fcmp_cr_table[32]; /* FCMP CR table */
+
+ /* internal stuff */
+ UINT8 cache_dirty; /* true if we need to flush the cache */
+
+ /* register mappings */
+ parameter regmap[32]; /* parameter to register mappings for all 32 integer registers */
+ parameter fdregmap[32]; /* parameter to register mappings for all 32 floating point registers */
+
+ /* subroutines */
+ code_handle * entry; /* entry point */
+ code_handle * nocode; /* nocode exception handler */
+ code_handle * out_of_cycles; /* out of cycles exception handler */
+ code_handle * tlb_mismatch; /* tlb mismatch handler */
+ code_handle * swap_tgpr; /* swap TGPR handler */
+ code_handle * lsw[8][32]; /* lsw entries */
+ code_handle * stsw[8][32]; /* stsw entries */
+ code_handle * read8[8]; /* read byte */
+ code_handle * write8[8]; /* write byte */
+ code_handle * read16[8]; /* read half */
+ code_handle * read16mask[8]; /* read half */
+ code_handle * write16[8]; /* write half */
+ code_handle * write16mask[8]; /* write half */
+ code_handle * read32[8]; /* read word */
+ code_handle * read32align[8]; /* read word aligned */
+ code_handle * read32mask[8]; /* read word */
+ code_handle * write32[8]; /* write word */
+ code_handle * write32align[8]; /* write word aligned */
+ code_handle * write32mask[8]; /* write word */
+ code_handle * read64[8]; /* read double */
+ code_handle * read64mask[8]; /* read double */
+ code_handle * write64[8]; /* write double */
+ code_handle * write64mask[8]; /* write double */
+ code_handle * exception[EXCEPTION_COUNT]; /* array of exception handlers */
+ code_handle * exception_norecover[EXCEPTION_COUNT]; /* array of exception handlers */
+
+ /* fast RAM */
+ UINT32 fastram_select;
+ fast_ram_info fastram[PPC_MAX_FASTRAM];
+
+ /* hotspots */
+ UINT32 hotspot_select;
+ hotspot_info hotspot[PPC_MAX_HOTSPOTS];
+};
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static void code_flush_cache(powerpc_state *ppc);
+static void code_compile_block(powerpc_state *ppc, UINT8 mode, offs_t pc);
+
+static void cfunc_printf_exception(void *param);
+static void cfunc_printf_probe(void *param);
+
+static void static_generate_entry_point(powerpc_state *ppc);
+static void static_generate_nocode_handler(powerpc_state *ppc);
+static void static_generate_out_of_cycles(powerpc_state *ppc);
+static void static_generate_tlb_mismatch(powerpc_state *ppc);
+static void static_generate_exception(powerpc_state *ppc, UINT8 exception, int recover, const char *name);
+static void static_generate_memory_accessor(powerpc_state *ppc, int mode, int size, int iswrite, int ismasked, const char *name, code_handle *&handleptr, code_handle *masked);
+static void static_generate_swap_tgpr(powerpc_state *ppc);
+static void static_generate_lsw_entries(powerpc_state *ppc, int mode);
+static void static_generate_stsw_entries(powerpc_state *ppc, int mode);
+
+static void generate_update_mode(powerpc_state *ppc, drcuml_block *block);
+static void generate_update_cycles(powerpc_state *ppc, drcuml_block *block, compiler_state *compiler, parameter, int allow_exception);
+static void generate_checksum_block(powerpc_state *ppc, drcuml_block *block, compiler_state *compiler, const opcode_desc *seqhead, const opcode_desc *seqlast);
+static void generate_sequence_instruction(powerpc_state *ppc, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+static int generate_opcode(powerpc_state *ppc, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+static int generate_instruction_13(powerpc_state *ppc, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+static int generate_instruction_1f(powerpc_state *ppc, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+static int generate_instruction_3b(powerpc_state *ppc, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+static int generate_instruction_3f(powerpc_state *ppc, drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+
+static void log_add_disasm_comment(drcuml_block *block, UINT32 pc, UINT32 op);
+static const char *log_desc_flags_to_string(UINT32 flags);
+static void log_register_list(drcuml_state *drcuml, const char *string, const UINT32 *reglist, const UINT32 *regnostarlist);
+static void log_opcode_desc(drcuml_state *drcuml, const opcode_desc *desclist, int indent);
+
+
+
+/***************************************************************************
+ PRIVATE GLOBAL VARIABLES
+***************************************************************************/
+
+/* lookup table for FP modes */
+static const UINT8 fpmode_source[4] =
+{
+ ROUND_ROUND,
+ ROUND_TRUNC,
+ ROUND_CEIL,
+ ROUND_FLOOR
+};
+
+/* flag lookup table for SZ */
+static const UINT8 sz_cr_table_source[32] =
+{
+ /* ..... */ 0x4,
+ /* ....C */ 0x4,
+ /* ...V. */ 0x4,
+ /* ...VC */ 0x4,
+ /* ..Z.. */ 0x2,
+ /* ..Z.C */ 0x2,
+ /* ..ZV. */ 0x2,
+ /* ..ZVC */ 0x2,
+ /* .S... */ 0x8,
+ /* .S..C */ 0x8,
+ /* .S.V. */ 0x8,
+ /* .S.VC */ 0x8,
+ /* .SZ.. */ 0x2,
+ /* .SZ.C */ 0x2,
+ /* .SZV. */ 0x2,
+ /* .SZVC */ 0x2,
+ /* U.... */ 0x4,
+ /* U...C */ 0x4,
+ /* U..V. */ 0x4,
+ /* U..VC */ 0x4,
+ /* U.Z.. */ 0x2,
+ /* U.Z.C */ 0x2,
+ /* U.ZV. */ 0x2,
+ /* U.ZVC */ 0x2,
+ /* US... */ 0x8,
+ /* US..C */ 0x8,
+ /* US.V. */ 0x8,
+ /* US.VC */ 0x8,
+ /* USZ.. */ 0x2,
+ /* USZ.C */ 0x2,
+ /* USZV. */ 0x2,
+ /* USZVC */ 0x2
+};
+
+/* flag lookup table for CMP */
+static const UINT8 cmp_cr_table_source[32] =
+{
+ /* ..... */ 0x4,
+ /* ....C */ 0x4,
+ /* ...V. */ 0x8,
+ /* ...VC */ 0x8,
+ /* ..Z.. */ 0x2,
+ /* ..Z.C */ 0x2,
+ /* ..ZV. */ 0x2,
+ /* ..ZVC */ 0x2,
+ /* .S... */ 0x8,
+ /* .S..C */ 0x8,
+ /* .S.V. */ 0x4,
+ /* .S.VC */ 0x4,
+ /* .SZ.. */ 0x2,
+ /* .SZ.C */ 0x2,
+ /* .SZV. */ 0x2,
+ /* .SZVC */ 0x2,
+ /* U.... */ 0x4,
+ /* U...C */ 0x4,
+ /* U..V. */ 0x8,
+ /* U..VC */ 0x8,
+ /* U.Z.. */ 0x2,
+ /* U.Z.C */ 0x2,
+ /* U.ZV. */ 0x2,
+ /* U.ZVC */ 0x2,
+ /* US... */ 0x8,
+ /* US..C */ 0x8,
+ /* US.V. */ 0x4,
+ /* US.VC */ 0x4,
+ /* USZ.. */ 0x2,
+ /* USZ.C */ 0x2,
+ /* USZV. */ 0x2,
+ /* USZVC */ 0x2
+};
+
+/* flag lookup table for CMPL */
+static const UINT8 cmpl_cr_table_source[32] =
+{
+ /* ..... */ 0x4,
+ /* ....C */ 0x8,
+ /* ...V. */ 0x4,
+ /* ...VC */ 0x8,
+ /* ..Z.. */ 0x2,
+ /* ..Z.C */ 0x2,
+ /* ..ZV. */ 0x2,
+ /* ..ZVC */ 0x2,
+ /* .S... */ 0x4,
+ /* .S..C */ 0x8,
+ /* .S.V. */ 0x4,
+ /* .S.VC */ 0x8,
+ /* .SZ.. */ 0x2,
+ /* .SZ.C */ 0x2,
+ /* .SZV. */ 0x2,
+ /* .SZVC */ 0x2,
+ /* U.... */ 0x4,
+ /* U...C */ 0x8,
+ /* U..V. */ 0x4,
+ /* U..VC */ 0x8,
+ /* U.Z.. */ 0x2,
+ /* U.Z.C */ 0x2,
+ /* U.ZV. */ 0x2,
+ /* U.ZVC */ 0x2,
+ /* US... */ 0x4,
+ /* US..C */ 0x8,
+ /* US.V. */ 0x4,
+ /* US.VC */ 0x8,
+ /* USZ.. */ 0x2,
+ /* USZ.C */ 0x2,
+ /* USZV. */ 0x2,
+ /* USZVC */ 0x2
+};
+
+/* flag lookup table for FCMP */
+static const UINT8 fcmp_cr_table_source[32] =
+{
+ /* ..... */ 0x4,
+ /* ....C */ 0x8,
+ /* ...V. */ 0x4,
+ /* ...VC */ 0x8,
+ /* ..Z.. */ 0x2,
+ /* ..Z.C */ 0xa,
+ /* ..ZV. */ 0x2,
+ /* ..ZVC */ 0xa,
+ /* .S... */ 0x4,
+ /* .S..C */ 0x8,
+ /* .S.V. */ 0x4,
+ /* .S.VC */ 0x8,
+ /* .SZ.. */ 0x2,
+ /* .SZ.C */ 0xa,
+ /* .SZV. */ 0x2,
+ /* .SZVC */ 0xa,
+ /* U.... */ 0x5,
+ /* U...C */ 0x9,
+ /* U..V. */ 0x5,
+ /* U..VC */ 0x9,
+ /* U.Z.. */ 0x3,
+ /* U.Z.C */ 0xb,
+ /* U.ZV. */ 0x3,
+ /* U.ZVC */ 0xb,
+ /* US... */ 0x5,
+ /* US..C */ 0x9,
+ /* US.V. */ 0x5,
+ /* US.VC */ 0x9,
+ /* USZ.. */ 0x3,
+ /* USZ.C */ 0xb,
+ /* USZV. */ 0x3,
+ /* USZVC */ 0xb
+};
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+INLINE powerpc_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == PPC403GA ||
+ device->type() == PPC403GCX ||
+ device->type() == PPC601 ||
+ device->type() == PPC602 ||
+ device->type() == PPC603 ||
+ device->type() == PPC603E ||
+ device->type() == PPC603R ||
+ device->type() == PPC604 ||
+ device->type() == MPC8240);
+ return *(powerpc_state **)downcast<legacy_cpu_device *>(device)->token();
+}
+
+/*-------------------------------------------------
+ alloc_handle - allocate a handle if not
+ already allocated
+-------------------------------------------------*/
+
+INLINE void alloc_handle(drcuml_state *drcuml, code_handle **handleptr, const char *name)
+{
+ if (*handleptr == NULL)
+ *handleptr = drcuml->handle_alloc(name);
+}
+
+
+/*-------------------------------------------------
+ load_fast_iregs - load any fast integer
+ registers
+-------------------------------------------------*/
+
+INLINE void load_fast_iregs(powerpc_state *ppc, drcuml_block *block)
+{
+ int regnum;
+
+ for (regnum = 0; regnum < ARRAY_LENGTH(ppc->impstate->regmap); regnum++)
+ if (ppc->impstate->regmap[regnum].is_int_register())
+ UML_MOV(block, ireg(ppc->impstate->regmap[regnum].ireg() - REG_I0), mem(&ppc->r[regnum]));
+}
+
+
+/*-------------------------------------------------
+ save_fast_iregs - save any fast integer
+ registers
+-------------------------------------------------*/
+
+INLINE void save_fast_iregs(powerpc_state *ppc, drcuml_block *block)
+{
+ int regnum;
+
+ for (regnum = 0; regnum < ARRAY_LENGTH(ppc->impstate->regmap); regnum++)
+ if (ppc->impstate->regmap[regnum].is_int_register())
+ UML_MOV(block, mem(&ppc->r[regnum]), ireg(ppc->impstate->regmap[regnum].ireg() - REG_I0));
+}
+
+
+/*-------------------------------------------------
+ compute_rlw_mask - compute the 32-bit mask
+ for an rlw* instruction
+-------------------------------------------------*/
+
+INLINE UINT32 compute_rlw_mask(UINT8 mb, UINT8 me)
+{
+ if (mb <= me)
+ return (0xffffffff >> mb) & (0xffffffff << (31 - me));
+ else
+ return (0xffffffff >> mb) | (0xffffffff << (31 - me));
+}
+
+
+/*-------------------------------------------------
+ compute_crf_mask - compute the 32-bit mask
+ for a mtcrf/mfcrf instruction
+-------------------------------------------------*/
+
+INLINE UINT32 compute_crf_mask(UINT8 crm)
+{
+ UINT32 mask = 0;
+ if (crm & 0x80) mask |= 0xf0000000;
+ if (crm & 0x40) mask |= 0x0f000000;
+ if (crm & 0x20) mask |= 0x00f00000;
+ if (crm & 0x10) mask |= 0x000f0000;
+ if (crm & 0x08) mask |= 0x0000f000;
+ if (crm & 0x04) mask |= 0x00000f00;
+ if (crm & 0x02) mask |= 0x000000f0;
+ if (crm & 0x01) mask |= 0x0000000f;
+ return mask;
+}
+
+
+/*-------------------------------------------------
+ compute_spr - compute the SPR index from the
+ SPR field of an opcode
+-------------------------------------------------*/
+
+INLINE UINT32 compute_spr(UINT32 spr)
+{
+ return ((spr >> 5) | (spr << 5)) & 0x3ff;
+}
+
+
+
+/***************************************************************************
+ CORE CALLBACKS
+***************************************************************************/
+
+/*-------------------------------------------------
+ ppcdrc_init - initialize the processor
+-------------------------------------------------*/
+
+static void ppcdrc_init(powerpc_flavor flavor, UINT8 cap, int tb_divisor, legacy_cpu_device *device, device_irq_callback irqcallback)
+{
+ powerpc_state *ppc;
+ drcbe_info beinfo;
+ UINT32 flags = 0;
+ drc_cache *cache;
+ int regnum;
+
+ /* allocate enough space for the cache and the core */
+ cache = auto_alloc(device->machine(), drc_cache(CACHE_SIZE + sizeof(*ppc)));
+
+ /* allocate the core from the near cache */
+ *(powerpc_state **)device->token() = ppc = (powerpc_state *)cache->alloc_near(sizeof(*ppc));
+ memset(ppc, 0, sizeof(*ppc));
+
+ /* initialize the core */
+ ppccom_init(ppc, flavor, cap, tb_divisor, device, irqcallback);
+
+ /* allocate the implementation-specific state from the full cache */
+ ppc->impstate = (ppcimp_state *)cache->alloc_near(sizeof(*ppc->impstate));
+ memset(ppc->impstate, 0, sizeof(*ppc->impstate));
+ ppc->impstate->cache = cache;
+
+ /* initialize the UML generator */
+ if (FORCE_C_BACKEND)
+ flags |= DRCUML_OPTION_USE_C;
+ if (LOG_UML)
+ flags |= DRCUML_OPTION_LOG_UML;
+ if (LOG_NATIVE)
+ flags |= DRCUML_OPTION_LOG_NATIVE;
+ ppc->impstate->drcuml = auto_alloc(device->machine(), drcuml_state(*device, *cache, flags, 8, 32, 2));
+
+ /* add symbols for our stuff */
+ ppc->impstate->drcuml->symbol_add(&ppc->pc, sizeof(ppc->pc), "pc");
+ ppc->impstate->drcuml->symbol_add(&ppc->icount, sizeof(ppc->icount), "icount");
+ for (regnum = 0; regnum < 32; regnum++)
+ {
+ char buf[10];
+ sprintf(buf, "r%d", regnum);
+ ppc->impstate->drcuml->symbol_add(&ppc->r[regnum], sizeof(ppc->r[regnum]), buf);
+ sprintf(buf, "fpr%d", regnum);
+ ppc->impstate->drcuml->symbol_add(&ppc->f[regnum], sizeof(ppc->r[regnum]), buf);
+ }
+ for (regnum = 0; regnum < 8; regnum++)
+ {
+ char buf[10];
+ sprintf(buf, "cr%d", regnum);
+ ppc->impstate->drcuml->symbol_add(&ppc->cr[regnum], sizeof(ppc->cr[regnum]), buf);
+ }
+ ppc->impstate->drcuml->symbol_add(&ppc->xerso, sizeof(ppc->xerso), "xerso");
+ ppc->impstate->drcuml->symbol_add(&ppc->fpscr, sizeof(ppc->fpscr), "fpscr");
+ ppc->impstate->drcuml->symbol_add(&ppc->msr, sizeof(ppc->msr), "msr");
+ ppc->impstate->drcuml->symbol_add(&ppc->sr, sizeof(ppc->sr), "sr");
+ ppc->impstate->drcuml->symbol_add(&ppc->spr[SPR_XER], sizeof(ppc->spr[SPR_XER]), "xer");
+ ppc->impstate->drcuml->symbol_add(&ppc->spr[SPR_LR], sizeof(ppc->spr[SPR_LR]), "lr");
+ ppc->impstate->drcuml->symbol_add(&ppc->spr[SPR_CTR], sizeof(ppc->spr[SPR_CTR]), "ctr");
+ ppc->impstate->drcuml->symbol_add(&ppc->spr, sizeof(ppc->spr), "spr");
+ ppc->impstate->drcuml->symbol_add(&ppc->dcr, sizeof(ppc->dcr), "dcr");
+ ppc->impstate->drcuml->symbol_add(&ppc->param0, sizeof(ppc->param0), "param0");
+ ppc->impstate->drcuml->symbol_add(&ppc->param1, sizeof(ppc->param1), "param1");
+ ppc->impstate->drcuml->symbol_add(&ppc->irq_pending, sizeof(ppc->irq_pending), "irq_pending");
+ ppc->impstate->drcuml->symbol_add(&ppc->impstate->mode, sizeof(ppc->impstate->mode), "mode");
+ ppc->impstate->drcuml->symbol_add(&ppc->impstate->arg0, sizeof(ppc->impstate->arg0), "arg0");
+ ppc->impstate->drcuml->symbol_add(&ppc->impstate->arg1, sizeof(ppc->impstate->arg1), "arg1");
+ ppc->impstate->drcuml->symbol_add(&ppc->impstate->updateaddr, sizeof(ppc->impstate->updateaddr), "updateaddr");
+ ppc->impstate->drcuml->symbol_add(&ppc->impstate->swcount, sizeof(ppc->impstate->swcount), "swcount");
+ ppc->impstate->drcuml->symbol_add(&ppc->impstate->tempaddr, sizeof(ppc->impstate->tempaddr), "tempaddr");
+ ppc->impstate->drcuml->symbol_add(&ppc->impstate->tempdata, sizeof(ppc->impstate->tempdata), "tempdata");
+ ppc->impstate->drcuml->symbol_add(&ppc->impstate->fp0, sizeof(ppc->impstate->fp0), "fp0");
+ ppc->impstate->drcuml->symbol_add(&ppc->impstate->fpmode, sizeof(ppc->impstate->fpmode), "fpmode");
+ ppc->impstate->drcuml->symbol_add(&ppc->impstate->sz_cr_table, sizeof(ppc->impstate->sz_cr_table), "sz_cr_table");
+ ppc->impstate->drcuml->symbol_add(&ppc->impstate->cmp_cr_table, sizeof(ppc->impstate->cmp_cr_table), "cmp_cr_table");
+ ppc->impstate->drcuml->symbol_add(&ppc->impstate->cmpl_cr_table, sizeof(ppc->impstate->cmpl_cr_table), "cmpl_cr_table");
+ ppc->impstate->drcuml->symbol_add(&ppc->impstate->fcmp_cr_table, sizeof(ppc->impstate->fcmp_cr_table), "fcmp_cr_table");
+
+ /* initialize the front-end helper */
+ ppc->impstate->drcfe = auto_alloc(device->machine(), ppc_frontend(*ppc, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE));
+
+ /* initialize the implementation state tables */
+ memcpy(ppc->impstate->fpmode, fpmode_source, sizeof(fpmode_source));
+ memcpy(ppc->impstate->sz_cr_table, sz_cr_table_source, sizeof(sz_cr_table_source));
+ memcpy(ppc->impstate->cmp_cr_table, cmp_cr_table_source, sizeof(cmp_cr_table_source));
+ memcpy(ppc->impstate->cmpl_cr_table, cmpl_cr_table_source, sizeof(cmpl_cr_table_source));
+ memcpy(ppc->impstate->fcmp_cr_table, fcmp_cr_table_source, sizeof(fcmp_cr_table_source));
+
+ /* compute the register parameters */
+ for (regnum = 0; regnum < 32; regnum++)
+ {
+ ppc->impstate->regmap[regnum] = mem(&ppc->r[regnum]);
+ ppc->impstate->fdregmap[regnum] = mem(&ppc->f[regnum]);
+ }
+
+ /* if we have registers to spare, assign r0, r1, r2 to leftovers */
+ if (!DISABLE_FAST_REGISTERS)
+ {
+ ppc->impstate->drcuml->get_backend_info(beinfo);
+ if (beinfo.direct_iregs > 5)
+ ppc->impstate->regmap[0] = I5;
+ if (beinfo.direct_iregs > 6)
+ ppc->impstate->regmap[1] = I6;
+ if (beinfo.direct_iregs > 7)
+ ppc->impstate->regmap[2] = I7;
+ }
+
+ /* mark the cache dirty so it is updated on next execute */
+ ppc->impstate->cache_dirty = TRUE;
+}
+
+
+/*-------------------------------------------------
+ ppcdrc_reset - reset the processor
+-------------------------------------------------*/
+
+static CPU_RESET( ppcdrc )
+{
+ powerpc_state *ppc = get_safe_token(device);
+
+ /* reset the common code and mark the cache dirty */
+ ppccom_reset(ppc);
+ ppc->impstate->mode = 0;
+ ppc->impstate->cache_dirty = TRUE;
+}
+
+
+/*-------------------------------------------------
+ ppcdrc_execute - execute the CPU for the
+ specified number of cycles
+-------------------------------------------------*/
+
+static CPU_EXECUTE( ppcdrc )
+{
+ powerpc_state *ppc = get_safe_token(device);
+ drcuml_state *drcuml = ppc->impstate->drcuml;
+ int execute_result;
+
+ /* reset the cache if dirty */
+ if (ppc->impstate->cache_dirty)
+ code_flush_cache(ppc);
+ ppc->impstate->cache_dirty = FALSE;
+
+ /* execute */
+ do
+ {
+ /* run as much as we can */
+ execute_result = drcuml->execute(*ppc->impstate->entry);
+
+ /* if we need to recompile, do it */
+ if (execute_result == EXECUTE_MISSING_CODE)
+ code_compile_block(ppc, ppc->impstate->mode, ppc->pc);
+ else if (execute_result == EXECUTE_UNMAPPED_CODE)
+ fatalerror("Attempted to execute unmapped code at PC=%08X\n", ppc->pc);
+ else if (execute_result == EXECUTE_RESET_CACHE)
+ code_flush_cache(ppc);
+
+ } while (execute_result != EXECUTE_OUT_OF_CYCLES);
+}
+
+
+/*-------------------------------------------------
+ ppcdrc_exit - cleanup from execution
+-------------------------------------------------*/
+
+static CPU_EXIT( ppcdrc )
+{
+ powerpc_state *ppc = get_safe_token(device);
+ ppccom_exit(ppc);
+
+ /* clean up the DRC */
+ auto_free(device->machine(), ppc->impstate->drcfe);
+ auto_free(device->machine(), ppc->impstate->drcuml);
+ auto_free(device->machine(), ppc->impstate->cache);
+}
+
+
+/*-------------------------------------------------
+ ppcdrc_translate - perform virtual-to-physical
+ address translation
+-------------------------------------------------*/
+
+static CPU_TRANSLATE( ppcdrc )
+{
+ powerpc_state *ppc = get_safe_token(device);
+ return ppccom_translate_address(ppc, space, intention, address);
+}
+
+
+/*-------------------------------------------------
+ ppcdrc_dasm - disassemble an instruction
+-------------------------------------------------*/
+
+static CPU_DISASSEMBLE( ppcdrc )
+{
+ powerpc_state *ppc = get_safe_token(device);
+ return ppccom_dasm(ppc, buffer, pc, oprom, opram);
+}
+
+
+/*-------------------------------------------------
+ ppcdrc_set_info - set information about a given
+ CPU instance
+-------------------------------------------------*/
+
+static CPU_SET_INFO( ppcdrc )
+{
+ powerpc_state *ppc = get_safe_token(device);
+
+ /* --- everything is handled generically --- */
+ ppccom_set_info(ppc, state, info);
+}
+
+
+/*-------------------------------------------------
+ ppcdrc_get_info - return information about a given
+ CPU instance
+-------------------------------------------------*/
+
+static CPU_GET_INFO( ppcdrc )
+{
+ powerpc_state *ppc = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(powerpc_state *); break;
+ case CPUINFO_INT_PREVIOUSPC: /* not implemented */ break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(ppcdrc); break;
+ case CPUINFO_FCT_INIT: /* provided per-CPU */ break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(ppcdrc); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(ppcdrc); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(ppcdrc); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(ppcdrc);break;
+ case CPUINFO_FCT_TRANSLATE: info->translate = CPU_TRANSLATE_NAME(ppcdrc); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+
+ /* --- everything else is handled generically --- */
+ default: ppccom_get_info(ppc, state, info); break;
+ }
+}
+
+
+/*-------------------------------------------------
+ ppcdrc_set_options - configure DRC options
+-------------------------------------------------*/
+
+void ppcdrc_set_options(device_t *device, UINT32 options)
+{
+ powerpc_state *ppc = get_safe_token(device);
+ ppc->impstate->drcoptions = options;
+}
+
+
+/*-------------------------------------------------
+ ppcdrc_add_fastram - add a new fastram
+ region
+-------------------------------------------------*/
+
+void ppcdrc_add_fastram(device_t *device, offs_t start, offs_t end, UINT8 readonly, void *base)
+{
+ powerpc_state *ppc = get_safe_token(device);
+ if (ppc->impstate->fastram_select < ARRAY_LENGTH(ppc->impstate->fastram))
+ {
+ ppc->impstate->fastram[ppc->impstate->fastram_select].start = start;
+ ppc->impstate->fastram[ppc->impstate->fastram_select].end = end;
+ ppc->impstate->fastram[ppc->impstate->fastram_select].readonly = readonly;
+ ppc->impstate->fastram[ppc->impstate->fastram_select].base = base;
+ ppc->impstate->fastram_select++;
+ }
+}
+
+
+/*-------------------------------------------------
+ ppcdrc_add_hotspot - add a new hotspot
+-------------------------------------------------*/
+
+void ppcdrc_add_hotspot(device_t *device, offs_t pc, UINT32 opcode, UINT32 cycles)
+{
+ powerpc_state *ppc = get_safe_token(device);
+ if (ppc->impstate->hotspot_select < ARRAY_LENGTH(ppc->impstate->hotspot))
+ {
+ ppc->impstate->hotspot[ppc->impstate->hotspot_select].pc = pc;
+ ppc->impstate->hotspot[ppc->impstate->hotspot_select].opcode = opcode;
+ ppc->impstate->hotspot[ppc->impstate->hotspot_select].cycles = cycles;
+ ppc->impstate->hotspot_select++;
+ }
+}
+
+
+
+/***************************************************************************
+ CACHE MANAGEMENT
+***************************************************************************/
+
+/*-------------------------------------------------
+ code_flush_cache - flush the cache and
+ regenerate static code
+-------------------------------------------------*/
+
+static void code_flush_cache(powerpc_state *ppc)
+{
+ drcuml_state *drcuml = ppc->impstate->drcuml;
+ int mode;
+
+ /* empty the transient cache contents */
+ drcuml->reset();
+
+ try
+ {
+ /* generate the entry point and out-of-cycles handlers */
+ static_generate_entry_point(ppc);
+ static_generate_nocode_handler(ppc);
+ static_generate_out_of_cycles(ppc);
+ static_generate_tlb_mismatch(ppc);
+ if (ppc->cap & PPCCAP_603_MMU)
+ static_generate_swap_tgpr(ppc);
+
+ /* append exception handlers for various types */
+ static_generate_exception(ppc, EXCEPTION_RESET, TRUE, "exception_reset");
+ static_generate_exception(ppc, EXCEPTION_MACHCHECK, TRUE, "exception_machine_check");
+ static_generate_exception(ppc, EXCEPTION_DSI, TRUE, "exception_dsi");
+ static_generate_exception(ppc, EXCEPTION_ISI, TRUE, "exception_isi");
+ static_generate_exception(ppc, EXCEPTION_EI, TRUE, "exception_ei");
+ static_generate_exception(ppc, EXCEPTION_EI, FALSE, "exception_ei_norecover");
+ static_generate_exception(ppc, EXCEPTION_ALIGN, TRUE, "exception_align");
+ static_generate_exception(ppc, EXCEPTION_PROGRAM, TRUE, "exception_program");
+ static_generate_exception(ppc, EXCEPTION_NOFPU, TRUE, "exception_fpu_unavailable");
+ static_generate_exception(ppc, EXCEPTION_DECREMENT, TRUE, "exception_decrementer");
+ static_generate_exception(ppc, EXCEPTION_SYSCALL, TRUE, "exception_syscall");
+ static_generate_exception(ppc, EXCEPTION_TRACE, TRUE, "exception_trace");
+ static_generate_exception(ppc, EXCEPTION_FPASSIST, TRUE, "exception_floating_point_assist");
+ if (ppc->cap & PPCCAP_603_MMU)
+ {
+ static_generate_exception(ppc, EXCEPTION_ITLBMISS, TRUE, "exception_itlb_miss");
+ static_generate_exception(ppc, EXCEPTION_DTLBMISSL, TRUE, "exception_dtlb_miss_load");
+ static_generate_exception(ppc, EXCEPTION_DTLBMISSS, TRUE, "exception_dtlb_miss_store");
+ }
+
+ /* add subroutines for memory accesses */
+ for (mode = 0; mode < 8; mode++)
+ {
+ static_generate_memory_accessor(ppc, mode, 1, FALSE, FALSE, "read8", ppc->impstate->read8[mode], NULL);
+ static_generate_memory_accessor(ppc, mode, 1, TRUE, FALSE, "write8", ppc->impstate->write8[mode], NULL);
+ static_generate_memory_accessor(ppc, mode, 2, FALSE, TRUE, "read16mask", ppc->impstate->read16mask[mode], NULL);
+ static_generate_memory_accessor(ppc, mode, 2, FALSE, FALSE, "read16", ppc->impstate->read16[mode], ppc->impstate->read16mask[mode]);
+ static_generate_memory_accessor(ppc, mode, 2, TRUE, TRUE, "write16mask", ppc->impstate->write16mask[mode], NULL);
+ static_generate_memory_accessor(ppc, mode, 2, TRUE, FALSE, "write16", ppc->impstate->write16[mode], ppc->impstate->write16mask[mode]);
+ static_generate_memory_accessor(ppc, mode, 4, FALSE, TRUE, "read32mask", ppc->impstate->read32mask[mode], NULL);
+ static_generate_memory_accessor(ppc, mode, 4, FALSE, FALSE, "read32align", ppc->impstate->read32align[mode], NULL);
+ static_generate_memory_accessor(ppc, mode, 4, FALSE, FALSE, "read32", ppc->impstate->read32[mode], ppc->impstate->read32mask[mode]);
+ static_generate_memory_accessor(ppc, mode, 4, TRUE, TRUE, "write32mask", ppc->impstate->write32mask[mode], NULL);
+ static_generate_memory_accessor(ppc, mode, 4, TRUE, FALSE, "write32align",ppc->impstate->write32align[mode],NULL);
+ static_generate_memory_accessor(ppc, mode, 4, TRUE, FALSE, "write32", ppc->impstate->write32[mode], ppc->impstate->write32mask[mode]);
+ static_generate_memory_accessor(ppc, mode, 8, FALSE, TRUE, "read64mask", ppc->impstate->read64mask[mode], NULL);
+ static_generate_memory_accessor(ppc, mode, 8, FALSE, FALSE, "read64", ppc->impstate->read64[mode], ppc->impstate->read64mask[mode]);
+ static_generate_memory_accessor(ppc, mode, 8, TRUE, TRUE, "write64mask", ppc->impstate->write64mask[mode], NULL);
+ static_generate_memory_accessor(ppc, mode, 8, TRUE, FALSE, "write64", ppc->impstate->write64[mode], ppc->impstate->write64mask[mode]);
+ static_generate_lsw_entries(ppc, mode);
+ static_generate_stsw_entries(ppc, mode);
+ }
+ }
+ catch (drcuml_block::abort_compilation &)
+ {
+ fatalerror("Error generating PPC static handlers");
+ }
+}
+
+
+/*-------------------------------------------------
+ code_compile_block - compile a block of the
+ given mode at the specified pc
+-------------------------------------------------*/
+
+static void code_compile_block(powerpc_state *ppc, UINT8 mode, offs_t pc)
+{
+ drcuml_state *drcuml = ppc->impstate->drcuml;
+ compiler_state compiler = { 0 };
+ const opcode_desc *seqhead, *seqlast;
+ const opcode_desc *desclist;
+ int override = FALSE;
+ drcuml_block *block;
+logerror("Compile %08X\n", pc);
+ g_profiler.start(PROFILER_DRC_COMPILE);
+
+ /* get a description of this sequence */
+ desclist = ppc->impstate->drcfe->describe_code(pc);
+ if (LOG_UML || LOG_NATIVE)
+ log_opcode_desc(drcuml, desclist, 0);
+
+ bool succeeded = false;
+ while (!succeeded)
+ {
+ try
+ {
+ /* start the block */
+ block = drcuml->begin_block(4096);
+
+ /* loop until we get through all instruction sequences */
+ for (seqhead = desclist; seqhead != NULL; seqhead = seqlast->next())
+ {
+ const opcode_desc *curdesc;
+ UINT32 nextpc;
+
+ /* add a code log entry */
+ if (LOG_UML)
+ block->append_comment("-------------------------"); // comment
+
+ /* determine the last instruction in this sequence */
+ for (seqlast = seqhead; seqlast != NULL; seqlast = seqlast->next())
+ if (seqlast->flags & OPFLAG_END_SEQUENCE)
+ break;
+ assert(seqlast != NULL);
+
+ /* if we don't have a hash for this mode/pc, or if we are overriding all, add one */
+ if (override || !drcuml->hash_exists(mode, seqhead->pc))
+ UML_HASH(block, mode, seqhead->pc); // hash mode,pc
+
+ /* if we already have a hash, and this is the first sequence, assume that we */
+ /* are recompiling due to being out of sync and allow future overrides */
+ else if (seqhead == desclist)
+ {
+ override = TRUE;
+ UML_HASH(block, mode, seqhead->pc); // hash mode,pc
+ }
+
+ /* otherwise, redispatch to that fixed PC and skip the rest of the processing */
+ else
+ {
+ UML_LABEL(block, seqhead->pc | 0x80000000); // label seqhead->pc | 0x80000000
+ UML_HASHJMP(block, ppc->impstate->mode, seqhead->pc, *ppc->impstate->nocode);
+ // hashjmp <mode>,seqhead->pc,nocode
+ continue;
+ }
+
+ /* validate this code block if we're not pointing into ROM */
+ if (ppc->program->get_write_ptr(seqhead->physpc) != NULL)
+ generate_checksum_block(ppc, block, &compiler, seqhead, seqlast); // <checksum>
+
+ /* label this instruction, if it may be jumped to locally */
+ if (seqhead->flags & OPFLAG_IS_BRANCH_TARGET)
+ UML_LABEL(block, seqhead->pc | 0x80000000); // label seqhead->pc | 0x80000000
+
+ /* iterate over instructions in the sequence and compile them */
+ for (curdesc = seqhead; curdesc != seqlast->next(); curdesc = curdesc->next())
+ generate_sequence_instruction(ppc, block, &compiler, curdesc); // <instruction>
+
+ /* if we need to return to the start, do it */
+ if (seqlast->flags & OPFLAG_RETURN_TO_START)
+ nextpc = pc;
+
+ /* otherwise we just go to the next instruction */
+ else
+ nextpc = seqlast->pc + (seqlast->skipslots + 1) * 4;
+
+ /* count off cycles and go there */
+ generate_update_cycles(ppc, block, &compiler, nextpc, TRUE); // <subtract cycles>
+
+ /* if the last instruction can change modes, use a variable mode; otherwise, assume the same mode */
+ if (seqlast->flags & OPFLAG_CAN_CHANGE_MODES)
+ UML_HASHJMP(block, mem(&ppc->impstate->mode), nextpc, *ppc->impstate->nocode);// hashjmp <mode>,nextpc,nocode
+ else if (seqlast->next() == NULL || seqlast->next()->pc != nextpc)
+ UML_HASHJMP(block, ppc->impstate->mode, nextpc, *ppc->impstate->nocode);// hashjmp <mode>,nextpc,nocode
+ }
+
+ /* end the sequence */
+ block->end();
+ g_profiler.stop();
+ succeeded = true;
+ }
+ catch (drcuml_block::abort_compilation &)
+ {
+ // flush the cache and try again
+ code_flush_cache(ppc);
+ }
+ }
+}
+
+
+
+/***************************************************************************
+ C FUNCTION CALLBACKS
+***************************************************************************/
+
+/*-------------------------------------------------
+ cfunc_printf_exception - log any exceptions that
+ aren't interrupts
+-------------------------------------------------*/
+
+static void cfunc_printf_exception(void *param)
+{
+ powerpc_state *ppc = (powerpc_state *)param;
+ printf("Exception: type=%2d EPC=%08X MSR=%08X\n", ppc->param0, ppc->spr[SPROEA_SRR0], ppc->spr[SPROEA_SRR1]);
+ cfunc_printf_probe(ppc);
+}
+
+
+/*-------------------------------------------------
+ cfunc_printf_debug - generic printf for
+ debugging
+-------------------------------------------------*/
+
+static void cfunc_printf_debug(void *param)
+{
+ powerpc_state *ppc = (powerpc_state *)param;
+ printf(ppc->impstate->format, ppc->impstate->arg0, ppc->impstate->arg1);
+}
+
+
+/*-------------------------------------------------
+ cfunc_printf_probe - print the current CPU
+ state and return
+-------------------------------------------------*/
+
+static void cfunc_printf_probe(void *param)
+{
+ powerpc_state *ppc = (powerpc_state *)param;
+ UINT32 pc = (UINT32)(FPTR)param;
+
+ printf(" PC=%08X\n", pc);
+ printf(" r0=%08X r1=%08X r2=%08X r3=%08X\n",
+ ppc->r[0], ppc->r[1], ppc->r[2], ppc->r[3]);
+ printf(" r4=%08X r5=%08X r6=%08X r7=%08X\n",
+ ppc->r[4], ppc->r[5], ppc->r[6], ppc->r[7]);
+ printf(" r8=%08X r9=%08X r10=%08X r11=%08X\n",
+ ppc->r[8], ppc->r[9], ppc->r[10], ppc->r[11]);
+ printf("r12=%08X r13=%08X r14=%08X r15=%08X\n",
+ ppc->r[12], ppc->r[13], ppc->r[14], ppc->r[15]);
+ printf("r16=%08X r17=%08X r18=%08X r19=%08X\n",
+ ppc->r[16], ppc->r[17], ppc->r[18], ppc->r[19]);
+ printf("r20=%08X r21=%08X r22=%08X r23=%08X\n",
+ ppc->r[20], ppc->r[21], ppc->r[22], ppc->r[23]);
+ printf("r24=%08X r25=%08X r26=%08X r27=%08X\n",
+ ppc->r[24], ppc->r[25], ppc->r[26], ppc->r[27]);
+ printf("r28=%08X r29=%08X r30=%08X r31=%08X\n",
+ ppc->r[28], ppc->r[29], ppc->r[30], ppc->r[31]);
+}
+
+
+/*-------------------------------------------------
+ cfunc_unimplemented - handler for
+ unimplemented opcdes
+-------------------------------------------------*/
+
+static void cfunc_unimplemented(void *param)
+{
+ powerpc_state *ppc = (powerpc_state *)param;
+ UINT32 opcode = ppc->impstate->arg0;
+ fatalerror("PC=%08X: Unimplemented op %08X", ppc->pc, opcode);
+}
+
+
+
+/***************************************************************************
+ STATIC CODEGEN
+***************************************************************************/
+
+/*-------------------------------------------------
+ static_generate_entry_point - generate a
+ static entry point
+-------------------------------------------------*/
+
+static void static_generate_entry_point(powerpc_state *ppc)
+{
+ drcuml_state *drcuml = ppc->impstate->drcuml;
+ code_label skip = 1;
+ drcuml_block *block;
+
+ /* begin generating */
+ block = drcuml->begin_block(20);
+
+ /* forward references */
+ alloc_handle(drcuml, &ppc->impstate->nocode, "nocode");
+ alloc_handle(drcuml, &ppc->impstate->exception_norecover[EXCEPTION_EI], "exception_ei_norecover");
+
+ alloc_handle(drcuml, &ppc->impstate->entry, "entry");
+ UML_HANDLE(block, *ppc->impstate->entry); // handle entry
+
+ /* reset the FPU mode */
+ UML_AND(block, I0, FPSCR32, 3); // and i0,fpscr,3
+ UML_LOAD(block, I0, &ppc->impstate->fpmode[0], I0, SIZE_BYTE, SCALE_x1); // load i0,fpmode,i0,byte
+ UML_SETFMOD(block, I0); // setfmod i0
+
+ /* load fast integer registers */
+ load_fast_iregs(ppc, block); // <load fastregs>
+
+ /* check for interrupts */
+ UML_TEST(block, mem(&ppc->irq_pending), ~0); // test [irq_pending],0
+ UML_JMPc(block, COND_Z, skip); // jmp skip,Z
+ UML_TEST(block, MSR32, MSR_EE); // test msr,MSR_EE
+ UML_JMPc(block, COND_Z, skip); // jmp skip,Z
+ UML_MOV(block, I0, mem(&ppc->pc)); // mov i0,pc
+ UML_MOV(block, I1, 0); // mov i1,0
+ UML_CALLH(block, *ppc->impstate->exception_norecover[EXCEPTION_EI]); // callh exception_norecover
+ UML_LABEL(block, skip); // skip:
+
+ /* generate a hash jump via the current mode and PC */
+ UML_HASHJMP(block, mem(&ppc->impstate->mode), mem(&ppc->pc), *ppc->impstate->nocode); // hashjmp <mode>,<pc>,nocode
+
+ block->end();
+}
+
+
+/*-------------------------------------------------
+ static_generate_nocode_handler - generate an
+ exception handler for "out of code"
+-------------------------------------------------*/
+
+static void static_generate_nocode_handler(powerpc_state *ppc)
+{
+ drcuml_state *drcuml = ppc->impstate->drcuml;
+ drcuml_block *block;
+
+ /* begin generating */
+ block = drcuml->begin_block(10);
+
+ /* generate a hash jump via the current mode and PC */
+ alloc_handle(drcuml, &ppc->impstate->nocode, "nocode");
+ UML_HANDLE(block, *ppc->impstate->nocode); // handle nocode
+ UML_GETEXP(block, I0); // getexp i0
+ UML_MOV(block, mem(&ppc->pc), I0); // mov [pc],i0
+ save_fast_iregs(ppc, block); // <save fastregs>
+ UML_EXIT(block, EXECUTE_MISSING_CODE); // exit EXECUTE_MISSING_CODE
+
+ block->end();
+}
+
+
+/*-------------------------------------------------
+ static_generate_out_of_cycles - generate an
+ out of cycles exception handler
+-------------------------------------------------*/
+
+static void static_generate_out_of_cycles(powerpc_state *ppc)
+{
+ drcuml_state *drcuml = ppc->impstate->drcuml;
+ drcuml_block *block;
+
+ /* begin generating */
+ block = drcuml->begin_block(10);
+
+ /* generate a hash jump via the current mode and PC */
+ alloc_handle(drcuml, &ppc->impstate->out_of_cycles, "out_of_cycles");
+ UML_HANDLE(block, *ppc->impstate->out_of_cycles); // handle out_of_cycles
+ UML_GETEXP(block, I0); // getexp i0
+ UML_MOV(block, mem(&ppc->pc), I0); // mov <pc>,i0
+ save_fast_iregs(ppc, block); // <save fastregs>
+ UML_EXIT(block, EXECUTE_OUT_OF_CYCLES); // exit EXECUTE_OUT_OF_CYCLES
+
+ block->end();
+}
+
+
+/*-------------------------------------------------
+ static_generate_tlb_mismatch - generate a
+ TLB mismatch handler
+-------------------------------------------------*/
+
+static void static_generate_tlb_mismatch(powerpc_state *ppc)
+{
+ drcuml_state *drcuml = ppc->impstate->drcuml;
+ drcuml_block *block;
+ int isi, exit, label = 1;
+
+ /* forward references */
+ alloc_handle(drcuml, &ppc->impstate->exception[EXCEPTION_ISI], "exception_isi");
+ if (ppc->cap & PPCCAP_603_MMU)
+ alloc_handle(drcuml, &ppc->impstate->exception[EXCEPTION_ITLBMISS], "exception_itlb_miss");
+
+ /* begin generating */
+ block = drcuml->begin_block(20);
+
+ /* generate a hash jump via the current mode and PC */
+ alloc_handle(drcuml, &ppc->impstate->tlb_mismatch, "tlb_mismatch");
+ UML_HANDLE(block, *ppc->impstate->tlb_mismatch); // handle tlb_mismatch
+ UML_RECOVER(block, I0, MAPVAR_PC); // recover i0,PC
+ UML_SHR(block, I1, I0, 12); // shr i1,i0,12
+ UML_LOAD(block, I2, (void *)vtlb_table(ppc->vtlb), I1, SIZE_DWORD, SCALE_x4); // load i2,[vtlb],i1,dword
+ UML_MOV(block, mem(&ppc->param0), I0); // mov [param0],i0
+ UML_MOV(block, mem(&ppc->param1), TRANSLATE_FETCH); // mov [param1],TRANSLATE_FETCH
+ UML_CALLC(block, (c_function)ppccom_tlb_fill, ppc); // callc tlbfill,ppc
+ UML_LOAD(block, I1, (void *)vtlb_table(ppc->vtlb), I1, SIZE_DWORD, SCALE_x4); // load i1,[vtlb],i1,dword
+ UML_TEST(block, I1, VTLB_FETCH_ALLOWED); // test i1,VTLB_FETCH_ALLOWED
+ UML_JMPc(block, COND_Z, isi = label++); // jmp isi,z
+ UML_CMP(block, I2, 0); // cmp i2,0
+ UML_JMPc(block, COND_NZ, exit = label++); // jmp exit,nz
+ UML_HASHJMP(block, mem(&ppc->impstate->mode), I0, *ppc->impstate->nocode); // hashjmp <mode>,i0,nocode
+ UML_LABEL(block, exit); // exit:
+ UML_MOV(block, mem(&ppc->pc), I0); // mov <pc>,i0
+ save_fast_iregs(ppc, block); // <save fastregs>
+ UML_EXIT(block, EXECUTE_MISSING_CODE); // exit EXECUTE_MISSING_CODE
+ UML_LABEL(block, isi); // isi:
+ if (!(ppc->cap & PPCCAP_603_MMU))
+ {
+ UML_MOV(block, SPR32(SPROEA_DSISR), mem(&ppc->param0)); // mov [dsisr],[param0]
+ UML_EXH(block, *ppc->impstate->exception[EXCEPTION_ISI], I0); // exh isi,i0
+ }
+ else